1
2
3
4
5
6
7
8
9
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
30MODULE_LICENSE("GPL");
31MODULE_AUTHOR("Red Hat, Inc. - Arjan Van De Ven <arjanv@redhat.com>");
32MODULE_DESCRIPTION("Socket driver for Intel i82092AA PCI-PCMCIA bridge");
33
34
35#define I365_CPAGE 0x26
36
37
38static 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
50static 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
61static 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
77
78struct socket_info {
79 int card_state;
80
81
82
83 unsigned long io_base;
84 socket_cap_t cap;
85
86 unsigned int pending_events;
87
88 void (*handler)(void *info, u_int events);
89
90 void *info;
91
92 struct pci_dev *dev;
93};
94
95#define MAX_SOCKETS 4
96static struct socket_info sockets[MAX_SOCKETS];
97static int socket_count;
98
99int membase = -1;
100int isa_setup;
101
102MODULE_PARM(membase, "i");
103MODULE_PARM(isa_setup, "i");
104
105static 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
117
118
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);
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
164
165
166
167
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;
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
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
219 configbyte = 0xFF;
220 pci_write_config_byte(dev, 0x50, configbyte);
221
222
223
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
238static 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
247static spinlock_t port_lock = SPIN_LOCK_UNLOCKED;
248
249
250
251static 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
265static 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
282static 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
294static 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
311static 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
327static 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
349
350static int cycle_time = 120;
351
352static int to_cycles(int ns)
353{
354 if (cycle_time!=0)
355 return ns/cycle_time;
356 else
357 return 0;
358}
359
360static int to_ns(int cycles)
361{
362 return cycle_time*cycles;
363}
364
365
366
367
368static 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
382static struct tq_struct i82092aa_task = {
383 routine: i82092aa_bh
384};
385
386
387static 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
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)
408 continue;
409
410 csc = indirect_read(i,I365_CSC);
411
412 if ((csc==0) ||
413 (sockets[i].handler==NULL))
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
424 events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0;
425 } else {
426
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)
440 break;
441
442 }
443
444
445}
446
447
448
449
450
451static 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);
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
472static 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
487static 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
509static 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
518static 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}
531
532static 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}
539
540
541static 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);
548 *value = 0;
549
550 if ((status & I365_CS_DETECT) == I365_CS_DETECT) {
551 *value |= SS_DETECT;
552 }
553
554
555
556 if (indirect_read(sock, I365_INTCTL) & I365_PC_IOCARD) {
557
558 if (!(status & I365_CS_STSCHG))
559 *value |= SS_STSCHG;
560 } else {
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;
570
571 if (status & I365_CS_READY)
572 (*value) |= SS_READY;
573
574 if (status & I365_CS_POWERON)
575 (*value) |= SS_POWERON;
576
577
578 leave("i82092aa_get_status");
579 return 0;
580}
581
582
583static 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
595 reg = indirect_read(sock,I365_POWER);
596
597 if (reg & I365_PWR_AUTO)
598 state->flags |= SS_PWR_AUTO;
599
600 if (reg & I365_PWR_OUT)
601 state->flags |= SS_OUTPUT_ENA;
602
603 vcc = reg & I365_VCC_MASK; vpp = reg & I365_VPP1_MASK;
604
605 if (reg & I365_VCC_5V) {
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
620
621 reg = indirect_read(sock, I365_INTCTL);
622
623 if ((reg & I365_PC_RESET)==0)
624 state->flags |= SS_RESET;
625 if (reg & I365_PC_IOCARD)
626 state->flags |= SS_IOCARD;
627
628
629 if (sockets[sock].dev!=NULL)
630 state->io_irq = sockets[sock].dev->irq;
631
632
633 reg = indirect_read(sock, I365_CSCINT);
634
635 if (reg & I365_CSC_DETECT)
636 state->csc_mask |= SS_DETECT;
637
638 if (state->flags & SS_IOCARD) {
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
654static int i82092aa_set_socket(unsigned int sock, socket_state_t *state)
655{
656 unsigned char reg;
657
658 enter("i82092aa_set_socket");
659
660
661
662 set_bridge_state(sock);
663
664
665
666 reg = 0;
667 if (!(state->flags & SS_RESET))
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);
673
674
675
676 reg = I365_PWR_NORESET;
677
678 if (state->flags & SS_PWR_AUTO) {
679 dprintk("Auto power\n");
680 reg |= I365_PWR_AUTO;
681 }
682 if (state->flags & SS_OUTPUT_ENA) {
683 dprintk("Power Enabled \n");
684 reg |= I365_PWR_OUT;
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))
720 indirect_write(sock,I365_POWER,reg);
721
722
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
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
750static 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
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);
766 addr = indirect_read(sock,I365_ADDRWIN);
767
768 io->speed = to_ns(ioctl & I365_IOCTL_WAIT(map)) ? 1 : 0;
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
778static 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
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
797 if (indirect_read(sock, I365_ADDRWIN) & I365_ENA_IO(map))
798 indirect_resetbit(sock, I365_ADDRWIN, I365_ENA_IO(map));
799
800
801
802
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
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
821static 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;
840
841 base = I365_MEM(map);
842
843
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
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
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
879static 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
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
911
912
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
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
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
947 i |= I365_MEM_REG;
948 } else {
949
950 }
951 indirect_write16(sock,base+I365_W_OFF,i);
952 indirect_write(sock, I365_CPAGE, membase);
953
954
955 indirect_setbit(sock, I365_ADDRWIN, I365_ENA_MEM(map));
956
957 leave("i82092aa_set_mem_map");
958 return 0;
959}
960
961static void i82092aa_proc_setup(unsigned int sock, struct proc_dir_entry *base)
962{
963
964}
965
966
967static 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
975static 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
985module_init(i82092aa_module_init);
986module_exit(i82092aa_module_exit);
987
988