OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [pcmcia/] [i82092.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * Driver for Intel I82092AA PCI-PCMCIA bridge.
3
 *
4
 * (C) 2001-2003 Red Hat, Inc.
5
 *
6
 * Author: Arjan Van De Ven <arjanv@redhat.com>
7
 * Loosely based on i82365.c from the pcmcia-cs package
8
 *
9
 * $Id: i82092.c,v 1.1.1.1 2004-04-15 02:28:38 phoenix Exp $
10
 */
11
 
12
#include <linux/kernel.h>
13
#include <linux/config.h>
14
#include <linux/module.h>
15
#include <linux/pci.h>
16
#include <linux/init.h>
17
#include <linux/sched.h>
18
#include <linux/tqueue.h>
19
 
20
#include <pcmcia/cs_types.h>
21
#include <pcmcia/ss.h>
22
#include <pcmcia/cs.h>
23
 
24
#include <asm/system.h>
25
#include <asm/io.h>
26
 
27
#include "i82092aa.h"
28
#include "i82365.h"
29
 
30
MODULE_LICENSE("GPL");
31
MODULE_AUTHOR("Red Hat, Inc. - Arjan Van De Ven <arjanv@redhat.com>");
32
MODULE_DESCRIPTION("Socket driver for Intel i82092AA PCI-PCMCIA bridge");
33
 
34
/* Extra i82092-specific register */
35
#define I365_CPAGE 0x26
36
 
37
/* PCI core routines */
38
static struct pci_device_id i82092aa_pci_ids[] = {
39
        {
40
              vendor:PCI_VENDOR_ID_INTEL,
41
              device:PCI_DEVICE_ID_INTEL_82092AA_0,
42
              subvendor:PCI_ANY_ID,
43
              subdevice:PCI_ANY_ID,
44
              class: 0, class_mask:0,
45
 
46
         },
47
         {}
48
};
49
 
50
static struct pci_driver i82092aa_pci_drv = {
51
        name:           "i82092aa",
52
        id_table:       i82092aa_pci_ids,
53
        probe:          i82092aa_pci_probe,
54
        remove:         __devexit_p(i82092aa_pci_remove),
55
        suspend:        NULL,
56
        resume:         NULL
57
};
58
 
59
 
60
/* the pccard structure and its functions */
61
static struct pccard_operations i82092aa_operations = {
62
        init:                   i82092aa_init,
63
        suspend:                i82092aa_suspend,
64
        register_callback:      i82092aa_register_callback,
65
        inquire_socket:         i82092aa_inquire_socket,
66
        get_status:             i82092aa_get_status,
67
        get_socket:             i82092aa_get_socket,
68
        set_socket:             i82092aa_set_socket,
69
        get_io_map:             i82092aa_get_io_map,
70
        set_io_map:             i82092aa_set_io_map,
71
        get_mem_map:            i82092aa_get_mem_map,
72
        set_mem_map:            i82092aa_set_mem_map,
73
        proc_setup:             i82092aa_proc_setup,
74
};
75
 
76
/* The card can do upto 4 sockets, allocate a structure for each of them */
77
 
78
struct socket_info {
79
        int     card_state;     /*  0 = no socket,
80
                                    1 = empty socket,
81
                                    2 = card but not initialized,
82
                                    3 = operational card */
83
        unsigned long io_base;  /* base io address of the socket */
84
        socket_cap_t cap;
85
 
86
        unsigned int pending_events; /* Pending events on this interface */
87
 
88
        void    (*handler)(void *info, u_int events);
89
                                /* callback to the driver of the card */
90
        void    *info;          /* to be passed to the handler */
91
 
92
        struct pci_dev *dev;    /* The PCI device for the socket */
93
};
94
 
95
#define MAX_SOCKETS 4
96
static struct socket_info sockets[MAX_SOCKETS];
97
static int socket_count;  /* shortcut */
98
 
99
int membase = -1;
100
int isa_setup;
101
 
102
MODULE_PARM(membase, "i");
103
MODULE_PARM(isa_setup, "i");
104
 
105
static int __init i82092aa_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
106
{
107
        unsigned char configbyte;
108
        struct pci_dev *parent;
109
        int i;
110
 
111
        enter("i82092aa_pci_probe");
112
 
113
        if (pci_enable_device(dev))
114
                return -EIO;
115
 
116
        /* Since we have no memory BARs some firmware we may not
117
           have had PCI_COMMAND_MEM enabled, yet the device needs
118
           it. */
119
        pci_read_config_byte(dev, PCI_COMMAND, &configbyte);
120
        if (!(configbyte | PCI_COMMAND_MEMORY)) {
121
                dprintk(KERN_DEBUG "Enabling PCI_COMMAND_MEMORY\n");
122
                configbyte |= PCI_COMMAND_MEMORY;
123
                pci_write_config_byte(dev, PCI_COMMAND, configbyte);
124
        }
125
 
126
        pci_read_config_byte(dev, 0x40, &configbyte);  /* PCI Configuration Control */
127
        switch(configbyte&6) {
128
                case 0:
129
                        printk(KERN_INFO "i82092aa: configured as a 2 socket device.\n");
130
                        socket_count = 2;
131
                        break;
132
                case 2:
133
                        printk(KERN_INFO "i82092aa: configured as a 1 socket device.\n");
134
                        socket_count = 1;
135
                        break;
136
                case 4:
137
                case 6:
138
                        printk(KERN_INFO "i82092aa: configured as a 4 socket device.\n");
139
                        socket_count = 4;
140
                        break;
141
 
142
                default:
143
                        printk(KERN_ERR "i82092aa: Oops, you did something we didn't think of.\n");
144
                        return -EIO;
145
                        break;
146
        }
147
 
148
        if (membase == -1) {
149
                for (i = 0; i < 4; i++) {
150
                        if ((dev->bus->resource[i]->flags & (IORESOURCE_MEM|IORESOURCE_READONLY|IORESOURCE_CACHEABLE|IORESOURCE_SHADOWABLE))
151
                            == IORESOURCE_MEM) {
152
                                membase = dev->bus->resource[i]->start >> 24;
153
                                goto mem_ok;
154
                        }
155
                }
156
                printk(KERN_WARNING "No suitable memory range for i82092aa found\n");
157
                return -ENOSPC;
158
        }
159
 mem_ok:
160
        if (membase)
161
                printk(KERN_NOTICE "i82092 memory base address set to 0x%02x000000\n", membase);
162
 
163
        /* If we're down the end of the PCI bus chain where ISA cycles don't get sent, then
164
           only 1/4 of the I/O address space is going to be usable, unless we make sure that
165
           the NO_ISA bit in the Bridge Control register of all upstream busses is cleared.
166
           Since some PCMCIA cards (most serial ports, for example) will decode 10 bits and
167
           respond only to addresses where bits 8 and 9 are non-zero, we need to do this. */
168
        for (parent = dev->bus->self;
169
             parent && (parent->class>>8) == PCI_CLASS_BRIDGE_PCI;
170
             parent = parent->bus->self) {
171
                uint16_t brctl;
172
 
173
                if (pci_read_config_word(parent, PCI_BRIDGE_CONTROL, &brctl)) {
174
                        printk(KERN_WARNING "Error reading bridge control word from device %s\n", parent->slot_name);
175
                        continue;
176
                }
177
 
178
                if (!(brctl & PCI_BRIDGE_CTL_NO_ISA))
179
                        continue;
180
 
181
                if (isa_setup) {
182
                        printk(KERN_NOTICE "PCI bridge %s has NOISA bit set. Clearing to allow full PCMCIA operation\n",
183
                               parent->slot_name);
184
                        brctl &= ~PCI_BRIDGE_CTL_NO_ISA;
185
                        if (pci_write_config_word(parent, PCI_BRIDGE_CONTROL, brctl))
186
                                printk(KERN_WARNING "Error writing bridge control word from device %s\n", parent->slot_name);
187
                } else {
188
                        printk(KERN_NOTICE "PCI bridge %s has NOISA bit set. Some I/O addresses for PCMCIA cards will not work.\n",
189
                               parent->slot_name);
190
                        printk(KERN_NOTICE "Perhaps use 'isa_setup=1' option to i82092.o?\n");
191
                        break;
192
                }
193
        }
194
 
195
        for (i = 0;i<socket_count;i++) {
196
                sockets[i].card_state = 1; /* 1 = present but empty */
197
                sockets[i].io_base = (dev->resource[0].start & ~1);
198
                 if (sockets[i].io_base > 0)
199
                        request_region(sockets[i].io_base, 2, "i82092aa");
200
 
201
 
202
                sockets[i].cap.features |= SS_CAP_PCCARD | SS_CAP_PAGE_REGS;
203
                sockets[i].cap.map_size = 0x1000;
204
                sockets[i].cap.irq_mask = 0;
205
                sockets[i].cap.pci_irq  = dev->irq;
206
 
207
                /* Trick the resource code into doing the right thing... */
208
                sockets[i].cap.cb_dev = dev;
209
 
210
                if (card_present(i)) {
211
                        sockets[i].card_state = 3;
212
                        dprintk(KERN_DEBUG "i82092aa: slot %i is occupied\n",i);
213
                } else {
214
                        dprintk(KERN_DEBUG "i82092aa: slot %i is vacant\n",i);
215
                }
216
        }
217
 
218
        /* Now, specifiy that all interrupts are to be done as PCI interrupts */
219
        configbyte = 0xFF; /* bitmask, one bit per event, 1 = PCI interrupt, 0 = ISA interrupt */
220
        pci_write_config_byte(dev, 0x50, configbyte); /* PCI Interrupt Routing Register */
221
 
222
 
223
        /* Register the interrupt handler */
224
        dprintk(KERN_DEBUG "Requesting interrupt %i \n",dev->irq);
225
        if (request_irq(dev->irq, i82092aa_interrupt, SA_SHIRQ, "i82092aa", i82092aa_interrupt)) {
226
                printk(KERN_ERR "i82092aa: Failed to register IRQ %d, aborting\n", dev->irq);
227
                return -EIO;
228
        }
229
 
230
 
231
        if (register_ss_entry(socket_count, &i82092aa_operations) != 0)
232
                printk(KERN_NOTICE "i82092aa: register_ss_entry() failed\n");
233
 
234
        leave("i82092aa_pci_probe");
235
        return 0;
236
}
237
 
238
static void __devexit i82092aa_pci_remove(struct pci_dev *dev)
239
{
240
        enter("i82092aa_pci_remove");
241
 
242
        free_irq(dev->irq, i82092aa_interrupt);
243
 
244
        leave("i82092aa_pci_remove");
245
}
246
 
247
static spinlock_t port_lock = SPIN_LOCK_UNLOCKED;
248
 
249
/* basic value read/write functions */
250
 
251
static unsigned char indirect_read(int socket, unsigned short reg)
252
{
253
        unsigned long port;
254
        unsigned char val;
255
        unsigned long flags;
256
        spin_lock_irqsave(&port_lock,flags);
257
        reg += socket * 0x40;
258
        port = sockets[socket].io_base;
259
        outb(reg,port);
260
        val = inb(port+1);
261
        spin_unlock_irqrestore(&port_lock,flags);
262
        return val;
263
}
264
 
265
static unsigned short indirect_read16(int socket, unsigned short reg)
266
{
267
        unsigned long port;
268
        unsigned short tmp;
269
        unsigned long flags;
270
        spin_lock_irqsave(&port_lock,flags);
271
        reg  = reg + socket * 0x40;
272
        port = sockets[socket].io_base;
273
        outb(reg,port);
274
        tmp = inb(port+1);
275
        reg++;
276
        outb(reg,port);
277
        tmp = tmp | (inb(port+1)<<8);
278
        spin_unlock_irqrestore(&port_lock,flags);
279
        return tmp;
280
}
281
 
282
static void indirect_write(int socket, unsigned short reg, unsigned char value)
283
{
284
        unsigned long port;
285
        unsigned long flags;
286
        spin_lock_irqsave(&port_lock,flags);
287
        reg = reg + socket * 0x40;
288
        port = sockets[socket].io_base;
289
        outb(reg,port);
290
        outb(value,port+1);
291
        spin_unlock_irqrestore(&port_lock,flags);
292
}
293
 
294
static void indirect_setbit(int socket, unsigned short reg, unsigned char mask)
295
{
296
        unsigned long port;
297
        unsigned char val;
298
        unsigned long flags;
299
        spin_lock_irqsave(&port_lock,flags);
300
        reg = reg + socket * 0x40;
301
        port = sockets[socket].io_base;
302
        outb(reg,port);
303
        val = inb(port+1);
304
        val |= mask;
305
        outb(reg,port);
306
        outb(val,port+1);
307
        spin_unlock_irqrestore(&port_lock,flags);
308
}
309
 
310
 
311
static void indirect_resetbit(int socket, unsigned short reg, unsigned char mask)
312
{
313
        unsigned long port;
314
        unsigned char val;
315
        unsigned long flags;
316
        spin_lock_irqsave(&port_lock,flags);
317
        reg = reg + socket * 0x40;
318
        port = sockets[socket].io_base;
319
        outb(reg,port);
320
        val = inb(port+1);
321
        val &= ~mask;
322
        outb(reg,port);
323
        outb(val,port+1);
324
        spin_unlock_irqrestore(&port_lock,flags);
325
}
326
 
327
static void indirect_write16(int socket, unsigned short reg, unsigned short value)
328
{
329
        unsigned long port;
330
        unsigned char val;
331
        unsigned long flags;
332
        spin_lock_irqsave(&port_lock,flags);
333
        reg = reg + socket * 0x40;
334
        port = sockets[socket].io_base;
335
 
336
        outb(reg,port);
337
        val = value & 255;
338
        outb(val,port+1);
339
 
340
        reg++;
341
 
342
        outb(reg,port);
343
        val = value>>8;
344
        outb(val,port+1);
345
        spin_unlock_irqrestore(&port_lock,flags);
346
}
347
 
348
/* simple helper functions */
349
/* External clock time, in nanoseconds.  120 ns = 8.33 MHz */
350
static int cycle_time = 120;
351
 
352
static int to_cycles(int ns)
353
{
354
        if (cycle_time!=0)
355
                return ns/cycle_time;
356
        else
357
                return 0;
358
}
359
 
360
static int to_ns(int cycles)
361
{
362
        return cycle_time*cycles;
363
}
364
 
365
 
366
/* Interrupt handler functionality */
367
 
368
static void i82092aa_bh(void *dummy)
369
{
370
        unsigned int events;
371
        int i;
372
 
373
        for (i=0; i < socket_count; i++) {
374
                events = xchg(&(sockets[i].pending_events),0);
375
                dprintk("events = %x \n",events);
376
                if (sockets[i].handler)
377
                        sockets[i].handler(sockets[i].info, events);
378
        }
379
}
380
 
381
 
382
static struct tq_struct i82092aa_task = {
383
        routine:        i82092aa_bh
384
};
385
 
386
 
387
static void i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs)
388
{
389
        int i;
390
        int loopcount = 0;
391
 
392
        unsigned int events, active=0;
393
 
394
/*      enter("i82092aa_interrupt");*/
395
 
396
        while (1) {
397
                loopcount++;
398
                if (loopcount>20) {
399
                        printk(KERN_ERR "i82092aa: infinite eventloop in interrupt \n");
400
                        break;
401
                }
402
 
403
                active = 0;
404
 
405
                for (i=0;i<socket_count;i++) {
406
                        int csc;
407
                        if (sockets[i].card_state==0) /* Inactive socket, should not happen */
408
                                continue;
409
 
410
                        csc = indirect_read(i,I365_CSC); /* card status change register */
411
 
412
                        if ((csc==0) ||  /* no events on this socket */
413
                           (sockets[i].handler==NULL)) /* no way to handle events */
414
                                continue;
415
                        events = 0;
416
 
417
                        if (csc & I365_CSC_DETECT) {
418
                                events |= SS_DETECT;
419
                                dprintk("Card detected in socket %i!\n",i);
420
                         }
421
 
422
                        if (indirect_read(i,I365_INTCTL) & I365_PC_IOCARD) {
423
                                /* For IO/CARDS, bit 0 means "read the card" */
424
                                events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0;
425
                        } else {
426
                                /* Check for battery/ready events */
427
                                events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0;
428
                                events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0;
429
                                events |= (csc & I365_CSC_READY) ? SS_READY : 0;
430
                        }
431
 
432
                        if (events) {
433
                                sockets[i].pending_events |= events;
434
                                schedule_task(&i82092aa_task);
435
                        }
436
                        active |= events;
437
                }
438
 
439
                if (active==0) /* no more events to handle */
440
                        break;
441
 
442
        }
443
 
444
/*      leave("i82092aa_interrupt");*/
445
}
446
 
447
 
448
 
449
/* socket functions */
450
 
451
static int card_present(int socketno)
452
{
453
        unsigned int val;
454
        enter("card_present");
455
 
456
        if ((socketno<0) || (socketno > MAX_SOCKETS))
457
                return 0;
458
        if (sockets[socketno].io_base == 0)
459
                return 0;
460
 
461
 
462
        val = indirect_read(socketno, 1); /* Interface status register */
463
        if ((val&12)==12) {
464
                leave("card_present 1");
465
                return 1;
466
        }
467
 
468
        leave("card_present 0");
469
        return 0;
470
}
471
 
472
static void set_bridge_state(int sock)
473
{
474
        enter("set_bridge_state");
475
        indirect_write(sock, I365_GBLCTL,0x00);
476
        indirect_write(sock, I365_GENCTL,0x00);
477
 
478
        indirect_setbit(sock, I365_INTCTL,0x08);
479
        leave("set_bridge_state");
480
}
481
 
482
 
483
 
484
 
485
 
486
 
487
static int i82092aa_init(unsigned int s)
488
{
489
        int i;
490
        pccard_io_map io = { 0, 0, 0, 0, 1 };
491
        pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
492
 
493
        enter("i82092aa_init");
494
 
495
        i82092aa_set_socket(s, &dead_socket);
496
        for (i = 0; i < 2; i++) {
497
                io.map = i;
498
                i82092aa_set_io_map(s, &io);
499
        }
500
        for (i = 0; i < 5; i++) {
501
                mem.map = i;
502
                i82092aa_set_mem_map(s, &mem);
503
        }
504
 
505
        leave("i82092aa_init");
506
        return 0;
507
}
508
 
509
static int i82092aa_suspend(unsigned int sock)
510
{
511
        int retval;
512
        enter("i82092aa_suspend");
513
        retval =  i82092aa_set_socket(sock, &dead_socket);
514
        leave("i82092aa_suspend");
515
        return retval;
516
}
517
 
518
static int i82092aa_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
519
{
520
        enter("i82092aa_register_callback");
521
        sockets[sock].handler = handler;
522
        sockets[sock].info = info;
523
        if (handler == NULL) {
524
                MOD_DEC_USE_COUNT;
525
        } else {
526
                MOD_INC_USE_COUNT;
527
        }
528
        leave("i82092aa_register_callback");
529
        return 0;
530
} /* i82092aa_register_callback */
531
 
532
static int i82092aa_inquire_socket(unsigned int sock, socket_cap_t *cap)
533
{
534
        enter("i82092aa_inquire_socket");
535
        *cap = sockets[sock].cap;
536
        leave("i82092aa_inquire_socket");
537
        return 0;
538
} /* i82092aa_inquire_socket */
539
 
540
 
541
static int i82092aa_get_status(unsigned int sock, u_int *value)
542
{
543
        unsigned int status;
544
 
545
        enter("i82092aa_get_status");
546
 
547
        status = indirect_read(sock,I365_STATUS); /* Interface Status Register */
548
        *value = 0;
549
 
550
        if ((status & I365_CS_DETECT) == I365_CS_DETECT) {
551
                *value |= SS_DETECT;
552
        }
553
 
554
        /* IO cards have a different meaning of bits 0,1 */
555
        /* Also notice the inverse-logic on the bits */
556
         if (indirect_read(sock, I365_INTCTL) & I365_PC_IOCARD) {
557
                /* IO card */
558
                if (!(status & I365_CS_STSCHG))
559
                        *value |= SS_STSCHG;
560
         } else { /* non I/O card */
561
                if (!(status & I365_CS_BVD1))
562
                        *value |= SS_BATDEAD;
563
                if (!(status & I365_CS_BVD2))
564
                        *value |= SS_BATWARN;
565
 
566
         }
567
 
568
         if (status & I365_CS_WRPROT)
569
                (*value) |= SS_WRPROT;  /* card is write protected */
570
 
571
         if (status & I365_CS_READY)
572
                (*value) |= SS_READY;    /* card is not busy */
573
 
574
         if (status & I365_CS_POWERON)
575
                (*value) |= SS_POWERON;  /* power is applied to the card */
576
 
577
 
578
        leave("i82092aa_get_status");
579
        return 0;
580
}
581
 
582
 
583
static int i82092aa_get_socket(unsigned int sock, socket_state_t *state)
584
{
585
        unsigned char reg,vcc,vpp;
586
 
587
        enter("i82092aa_get_socket");
588
        state->flags    = 0;
589
        state->Vcc      = 0;
590
        state->Vpp      = 0;
591
        state->io_irq   = 0;
592
        state->csc_mask = 0;
593
 
594
        /* First the power status of the socket */
595
        reg = indirect_read(sock,I365_POWER); /* PCTRL - Power Control Register */
596
 
597
        if (reg & I365_PWR_AUTO)
598
                state->flags |= SS_PWR_AUTO;  /* Automatic Power Switch */
599
 
600
        if (reg & I365_PWR_OUT)
601
                state->flags |= SS_OUTPUT_ENA; /* Output signals are enabled */
602
 
603
        vcc = reg & I365_VCC_MASK;    vpp = reg & I365_VPP1_MASK;
604
 
605
        if (reg & I365_VCC_5V) { /* Can still be 3.3V, in this case the Vcc value will be overwritten later */
606
                state->Vcc = 50;
607
 
608
                if (vpp == I365_VPP1_5V)
609
                        state->Vpp = 50;
610
                if (vpp == I365_VPP1_12V)
611
                        state->Vpp = 120;
612
 
613
        }
614
 
615
        if ((reg & I365_VCC_3V)==I365_VCC_3V)
616
                state->Vcc = 33;
617
 
618
 
619
        /* Now the IO card, RESET flags and IO interrupt */
620
 
621
        reg = indirect_read(sock, I365_INTCTL); /* IGENC, Interrupt and General Control */
622
 
623
        if ((reg & I365_PC_RESET)==0)
624
                state->flags |= SS_RESET;
625
        if (reg & I365_PC_IOCARD)
626
                state->flags |= SS_IOCARD; /* This is an IO card */
627
 
628
        /* Set the IRQ number */
629
        if (sockets[sock].dev!=NULL)
630
                state->io_irq = sockets[sock].dev->irq;
631
 
632
        /* Card status change */
633
        reg = indirect_read(sock, I365_CSCINT); /* CSCICR, Card Status Change Interrupt Configuration */
634
 
635
        if (reg & I365_CSC_DETECT)
636
                state->csc_mask |= SS_DETECT; /* Card detect is enabled */
637
 
638
        if (state->flags & SS_IOCARD) {/* IO Cards behave different */
639
                if (reg & I365_CSC_STSCHG)
640
                        state->csc_mask |= SS_STSCHG;
641
        } else {
642
                if (reg & I365_CSC_BVD1)
643
                        state->csc_mask |= SS_BATDEAD;
644
                if (reg & I365_CSC_BVD2)
645
                        state->csc_mask |= SS_BATWARN;
646
                if (reg & I365_CSC_READY)
647
                        state->csc_mask |= SS_READY;
648
        }
649
 
650
        leave("i82092aa_get_socket");
651
        return 0;
652
}
653
 
654
static int i82092aa_set_socket(unsigned int sock, socket_state_t *state)
655
{
656
        unsigned char reg;
657
 
658
        enter("i82092aa_set_socket");
659
 
660
        /* First, set the global controller options */
661
 
662
        set_bridge_state(sock);
663
 
664
        /* Values for the IGENC register */
665
 
666
        reg = 0;
667
        if (!(state->flags & SS_RESET))         /* The reset bit has "inverse" logic */
668
                reg = reg | I365_PC_RESET;
669
        if (state->flags & SS_IOCARD)
670
                reg = reg | I365_PC_IOCARD;
671
 
672
        indirect_write(sock,I365_INTCTL,reg); /* IGENC, Interrupt and General Control Register */
673
 
674
        /* Power registers */
675
 
676
        reg = I365_PWR_NORESET; /* default: disable resetdrv on resume */
677
 
678
        if (state->flags & SS_PWR_AUTO) {
679
                dprintk("Auto power\n");
680
                reg |= I365_PWR_AUTO;   /* automatic power mngmnt */
681
        }
682
        if (state->flags & SS_OUTPUT_ENA) {
683
                dprintk("Power Enabled \n");
684
                reg |= I365_PWR_OUT;    /* enable power */
685
        }
686
 
687
        switch (state->Vcc) {
688
                case 0:
689
                        break;
690
                case 50:
691
                        dprintk("setting voltage to Vcc to 5V on socket %i\n",sock);
692
                        reg |= I365_VCC_5V;
693
                        break;
694
                default:
695
                        printk(KERN_WARNING "i82092aa: i82092aa_set_socket called with invalid VCC power value: %i ", state->Vcc);
696
                        leave("i82092aa_set_socket");
697
                        return -EINVAL;
698
        }
699
 
700
 
701
        switch (state->Vpp) {
702
                case 0:
703
                        dprintk("not setting Vpp on socket %i\n",sock);
704
                        break;
705
                case 50:
706
                        dprintk("setting Vpp to 5.0 for socket %i\n",sock);
707
                        reg |= I365_VPP1_5V | I365_VPP2_5V;
708
                        break;
709
                case 120:
710
                        dprintk("setting Vpp to 12.0\n");
711
                        reg |= I365_VPP1_12V | I365_VPP2_12V;
712
                        break;
713
                default:
714
                        printk(KERN_WARNING "i82092aa: i82092aa_set_socket called with invalid VPP power value: %i ", state->Vcc);
715
                        leave("i82092aa_set_socket");
716
                        return -EINVAL;
717
        }
718
 
719
        if (reg != indirect_read(sock,I365_POWER)) /* only write if changed */
720
                indirect_write(sock,I365_POWER,reg);
721
 
722
        /* Enable specific interrupt events */
723
 
724
        reg = 0x00;
725
        if (state->csc_mask & SS_DETECT) {
726
                reg |= I365_CSC_DETECT;
727
        }
728
        if (state->flags & SS_IOCARD) {
729
                if (state->csc_mask & SS_STSCHG)
730
                        reg |= I365_CSC_STSCHG;
731
        } else {
732
                if (state->csc_mask & SS_BATDEAD)
733
                        reg |= I365_CSC_BVD1;
734
                if (state->csc_mask & SS_BATWARN)
735
                        reg |= I365_CSC_BVD2;
736
                if (state->csc_mask & SS_READY)
737
                        reg |= I365_CSC_READY;
738
 
739
        }
740
 
741
        /* now write the value and clear the (probably bogus) pending stuff by doing a dummy read*/
742
 
743
        indirect_write(sock,I365_CSCINT,reg);
744
        (void)indirect_read(sock,I365_CSC);
745
 
746
        leave("i82092aa_set_socket");
747
        return 0;
748
}
749
 
750
static int i82092aa_get_io_map(unsigned int sock, struct pccard_io_map *io)
751
{
752
        unsigned char map, ioctl, addr;
753
 
754
        enter("i82092aa_get_io_map");
755
        map = io->map;
756
        if (map > 1) {
757
                leave("i82092aa_get_io_map with -EINVAL");
758
                return -EINVAL;
759
        }
760
 
761
        /* FIXME: How does this fit in with the PCI resource (re)allocation */
762
        io->start = indirect_read16(sock, I365_IO(map)+I365_W_START);
763
        io->stop  = indirect_read16(sock, I365_IO(map)+I365_W_START);
764
 
765
        ioctl = indirect_read(sock,I365_IOCTL); /* IOCREG: I/O Control Register */
766
        addr  = indirect_read(sock,I365_ADDRWIN); /* */
767
 
768
        io->speed = to_ns(ioctl & I365_IOCTL_WAIT(map)) ? 1 : 0; /* check this out later */
769
        io->flags = 0;
770
 
771
        if (addr & I365_IOCTL_16BIT(map))
772
                io->flags |= MAP_AUTOSZ;
773
 
774
        leave("i82092aa_get_io_map");
775
        return 0;
776
}
777
 
778
static int i82092aa_set_io_map(unsigned sock, struct pccard_io_map *io)
779
{
780
        unsigned char map, ioctl;
781
 
782
        enter("i82092aa_set_io_map");
783
 
784
        map = io->map;
785
 
786
        /* Check error conditions */
787
        if (map > 1) {
788
                leave("i82092aa_set_io_map with invalid map");
789
                return -EINVAL;
790
        }
791
        if ((io->start > 0xffff) || (io->stop > 0xffff) || (io->stop < io->start)){
792
                leave("i82092aa_set_io_map with invalid io");
793
                return -EINVAL;
794
        }
795
 
796
        /* Turn off the window before changing anything */
797
        if (indirect_read(sock, I365_ADDRWIN) & I365_ENA_IO(map))
798
                indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_IO(map));
799
 
800
/*      printk("set_io_map: Setting range to %x - %x \n",io->start,io->stop);  */
801
 
802
        /* write the new values */
803
        indirect_write16(sock,I365_IO(map)+I365_W_START,io->start);
804
        indirect_write16(sock,I365_IO(map)+I365_W_STOP,io->stop);
805
 
806
        ioctl = indirect_read(sock,I365_IOCTL) & ~I365_IOCTL_MASK(map);
807
 
808
        if (io->flags & (MAP_16BIT|MAP_AUTOSZ))
809
                ioctl |= I365_IOCTL_16BIT(map);
810
 
811
        indirect_write(sock,I365_IOCTL,ioctl);
812
 
813
        /* Turn the window back on if needed */
814
        if (io->flags & MAP_ACTIVE)
815
                indirect_setbit(sock,I365_ADDRWIN,I365_ENA_IO(map));
816
 
817
        leave("i82092aa_set_io_map");
818
        return 0;
819
}
820
 
821
static int i82092aa_get_mem_map(unsigned sock, struct pccard_mem_map *mem)
822
{
823
        unsigned short base, i;
824
        unsigned char map, addr;
825
 
826
        enter("i82092aa_get_mem_map");
827
 
828
        mem->flags = 0;
829
        mem->speed = 0;
830
        map = mem->map;
831
        if (map > 4) {
832
                leave("i82092aa_get_mem_map: -EINVAL");
833
                return -EINVAL;
834
        }
835
 
836
        addr = indirect_read(sock, I365_ADDRWIN);
837
 
838
        if (addr & I365_ENA_MEM(map))
839
                mem->flags |= MAP_ACTIVE;               /* yes this mapping is active */
840
 
841
        base = I365_MEM(map);
842
 
843
        /* Find the start address - this register also has mapping info */
844
 
845
        i = indirect_read16(sock,base+I365_W_START);
846
        if (i & I365_MEM_16BIT)
847
                mem->flags |= MAP_16BIT;
848
        if (i & I365_MEM_0WS)
849
                mem->flags |= MAP_0WS;
850
 
851
        mem->sys_start = ((unsigned long)(i & 0x0fff) << 12);
852
 
853
        /* Find the end address - this register also has speed info */
854
        i = indirect_read16(sock,base+I365_W_STOP);
855
        if (i & I365_MEM_WS0)
856
                mem->speed = 1;
857
        if (i & I365_MEM_WS1)
858
                mem->speed += 2;
859
        mem->speed = to_ns(mem->speed);
860
        mem->sys_stop = ( (unsigned long)(i & 0x0fff) << 12) + 0x0fff;
861
 
862
        /* Find the card start address, also some more MAP attributes */
863
 
864
        i = indirect_read16(sock, base+I365_W_OFF);
865
        if (i & I365_MEM_WRPROT)
866
                mem->flags |= MAP_WRPROT;
867
        if (i & I365_MEM_REG)
868
                mem->flags |= MAP_ATTRIB;
869
        mem->card_start = ( (unsigned long)(i & 0x3fff)<12) + mem->sys_start;
870
        mem->card_start &=  0x3ffffff;
871
 
872
        dprintk("Card %i is from %lx to %lx \n",sock,mem->sys_start,mem->sys_stop);
873
 
874
        leave("i82092aa_get_mem_map");
875
        return 0;
876
 
877
}
878
 
879
static int i82092aa_set_mem_map(unsigned sock, struct pccard_mem_map *mem)
880
{
881
        unsigned short base, i;
882
        unsigned char map;
883
 
884
        enter("i82092aa_set_mem_map");
885
 
886
        map = mem->map;
887
        if (map > 4) {
888
                leave("i82092aa_set_mem_map: invalid map");
889
                return -EINVAL;
890
        }
891
 
892
        /* Turn off the window before changing anything */
893
        if (indirect_read(sock, I365_ADDRWIN) & I365_ENA_MEM(map))
894
                      indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_MEM(map));
895
 
896
 
897
        if (!(mem->flags & MAP_ACTIVE))
898
                return 0;
899
 
900
        if ( (mem->card_start > 0x3ffffff) || (mem->sys_start > mem->sys_stop) ||
901
             ((mem->sys_start >> 24) != membase) || ((mem->sys_stop >> 24) != membase) ||
902
             (mem->speed > 1000) ) {
903
                leave("i82092aa_set_mem_map: invalid address / speed");
904
                printk(KERN_WARNING "invalid mem map for socket %i : %lx to %lx with a start of %x \n",sock,mem->sys_start, mem->sys_stop, mem->card_start);
905
                return -EINVAL;
906
        }
907
 
908
 
909
 
910
/*      printk("set_mem_map: Setting map %i range to %x - %x on socket %i, speed is %i, active = %i \n",map, mem->sys_start,mem->sys_stop,sock,mem->speed,mem->flags & MAP_ACTIVE);  */
911
 
912
        /* write the start address */
913
        base = I365_MEM(map);
914
        i = (mem->sys_start >> 12) & 0x0fff;
915
        if (mem->flags & MAP_16BIT)
916
                i |= I365_MEM_16BIT;
917
        if (mem->flags & MAP_0WS)
918
                i |= I365_MEM_0WS;
919
        indirect_write16(sock,base+I365_W_START,i);
920
 
921
        /* write the stop address */
922
 
923
        i= (mem->sys_stop >> 12) & 0x0fff;
924
        switch (to_cycles(mem->speed)) {
925
                case 0:
926
                        break;
927
                case 1:
928
                        i |= I365_MEM_WS0;
929
                        break;
930
                case 2:
931
                        i |= I365_MEM_WS1;
932
                        break;
933
                default:
934
                        i |= I365_MEM_WS1 | I365_MEM_WS0;
935
                        break;
936
        }
937
 
938
        indirect_write16(sock,base+I365_W_STOP,i);
939
 
940
        /* card start */
941
 
942
        i = (((mem->card_start - mem->sys_start) >> 12) - (membase << 12)) & 0x3fff;
943
        if (mem->flags & MAP_WRPROT)
944
                i |= I365_MEM_WRPROT;
945
        if (mem->flags & MAP_ATTRIB) {
946
/*              printk("requesting attribute memory for socket %i\n",sock);*/
947
                i |= I365_MEM_REG;
948
        } else {
949
/*              printk("requesting normal memory for socket %i\n",sock);*/
950
        }
951
        indirect_write16(sock,base+I365_W_OFF,i);
952
        indirect_write(sock, I365_CPAGE, membase);
953
 
954
        /* Enable the window if necessary */
955
        indirect_setbit(sock, I365_ADDRWIN, I365_ENA_MEM(map));
956
 
957
        leave("i82092aa_set_mem_map");
958
        return 0;
959
}
960
 
961
static void i82092aa_proc_setup(unsigned int sock, struct proc_dir_entry *base)
962
{
963
 
964
}
965
/* Module stuff */
966
 
967
static int i82092aa_module_init(void)
968
{
969
        enter("i82092aa_module_init");
970
        pci_register_driver(&i82092aa_pci_drv);
971
        leave("i82092aa_module_init");
972
        return 0;
973
}
974
 
975
static void i82092aa_module_exit(void)
976
{
977
        enter("i82092aa_module_exit");
978
        pci_unregister_driver(&i82092aa_pci_drv);
979
        unregister_ss_entry(&i82092aa_operations);
980
        if (sockets[0].io_base>0)
981
                         release_region(sockets[0].io_base, 2);
982
        leave("i82092aa_module_exit");
983
}
984
 
985
module_init(i82092aa_module_init);
986
module_exit(i82092aa_module_exit);
987
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.