2 * Driver for Intel I82092AA PCI-PCMCIA bridge.
4 * (C) 2001-2003 Red Hat, Inc.
6 * Author: Arjan Van De Ven <arjanv@redhat.com>
7 * Loosely based on i82365.c from the pcmcia-cs package
9 * $Id: i82092.c,v 1.16 2003/04/15 16:36:42 dwmw2 Exp $
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>
20 #include <pcmcia/cs_types.h>
21 #include <pcmcia/ss.h>
22 #include <pcmcia/cs.h>
24 #include <asm/system.h>
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");
34 /* Extra i82092-specific register */
35 #define I365_CPAGE 0x26
37 /* PCI core routines */
38 static struct pci_device_id i82092aa_pci_ids[] = {
40 vendor:PCI_VENDOR_ID_INTEL,
41 device:PCI_DEVICE_ID_INTEL_82092AA_0,
44 class: 0, class_mask:0,
50 static struct pci_driver i82092aa_pci_drv = {
52 id_table: i82092aa_pci_ids,
53 probe: i82092aa_pci_probe,
54 remove: __devexit_p(i82092aa_pci_remove),
60 /* the pccard structure and its functions */
61 static struct pccard_operations i82092aa_operations = {
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,
76 /* The card can do upto 4 sockets, allocate a structure for each of them */
79 int card_state; /* 0 = no socket,
81 2 = card but not initialized,
82 3 = operational card */
83 unsigned long io_base; /* base io address of the socket */
86 unsigned int pending_events; /* Pending events on this interface */
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 */
92 struct pci_dev *dev; /* The PCI device for the socket */
96 static struct socket_info sockets[MAX_SOCKETS];
97 static int socket_count; /* shortcut */
102 MODULE_PARM(membase, "i");
103 MODULE_PARM(isa_setup, "i");
105 static int __init i82092aa_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
107 unsigned char configbyte;
108 struct pci_dev *parent;
111 enter("i82092aa_pci_probe");
113 if (pci_enable_device(dev))
116 /* Since we have no memory BARs some firmware we may not
117 have had PCI_COMMAND_MEM enabled, yet the device needs
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);
126 pci_read_config_byte(dev, 0x40, &configbyte); /* PCI Configuration Control */
127 switch(configbyte&6) {
129 printk(KERN_INFO "i82092aa: configured as a 2 socket device.\n");
133 printk(KERN_INFO "i82092aa: configured as a 1 socket device.\n");
138 printk(KERN_INFO "i82092aa: configured as a 4 socket device.\n");
143 printk(KERN_ERR "i82092aa: Oops, you did something we didn't think of.\n");
149 for (i = 0; i < 4; i++) {
150 if ((dev->bus->resource[i]->flags & (IORESOURCE_MEM|IORESOURCE_READONLY|IORESOURCE_CACHEABLE|IORESOURCE_SHADOWABLE))
152 membase = dev->bus->resource[i]->start >> 24;
156 printk(KERN_WARNING "No suitable memory range for i82092aa found\n");
161 printk(KERN_NOTICE "i82092 memory base address set to 0x%02x000000\n", membase);
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) {
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);
178 if (!(brctl & PCI_BRIDGE_CTL_NO_ISA))
182 printk(KERN_NOTICE "PCI bridge %s has NOISA bit set. Clearing to allow full PCMCIA operation\n",
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);
188 printk(KERN_NOTICE "PCI bridge %s has NOISA bit set. Some I/O addresses for PCMCIA cards will not work.\n",
190 printk(KERN_NOTICE "Perhaps use 'isa_setup=1' option to i82092.o?\n");
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");
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;
207 /* Trick the resource code into doing the right thing... */
208 sockets[i].cap.cb_dev = dev;
210 if (card_present(i)) {
211 sockets[i].card_state = 3;
212 dprintk(KERN_DEBUG "i82092aa: slot %i is occupied\n",i);
214 dprintk(KERN_DEBUG "i82092aa: slot %i is vacant\n",i);
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 */
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);
231 if (register_ss_entry(socket_count, &i82092aa_operations) != 0)
232 printk(KERN_NOTICE "i82092aa: register_ss_entry() failed\n");
234 leave("i82092aa_pci_probe");
238 static void __devexit i82092aa_pci_remove(struct pci_dev *dev)
240 enter("i82092aa_pci_remove");
242 free_irq(dev->irq, i82092aa_interrupt);
244 leave("i82092aa_pci_remove");
247 static spinlock_t port_lock = SPIN_LOCK_UNLOCKED;
249 /* basic value read/write functions */
251 static unsigned char indirect_read(int socket, unsigned short reg)
256 spin_lock_irqsave(&port_lock,flags);
257 reg += socket * 0x40;
258 port = sockets[socket].io_base;
261 spin_unlock_irqrestore(&port_lock,flags);
265 static unsigned short indirect_read16(int socket, unsigned short reg)
270 spin_lock_irqsave(&port_lock,flags);
271 reg = reg + socket * 0x40;
272 port = sockets[socket].io_base;
277 tmp = tmp | (inb(port+1)<<8);
278 spin_unlock_irqrestore(&port_lock,flags);
282 static void indirect_write(int socket, unsigned short reg, unsigned char value)
286 spin_lock_irqsave(&port_lock,flags);
287 reg = reg + socket * 0x40;
288 port = sockets[socket].io_base;
291 spin_unlock_irqrestore(&port_lock,flags);
294 static void indirect_setbit(int socket, unsigned short reg, unsigned char mask)
299 spin_lock_irqsave(&port_lock,flags);
300 reg = reg + socket * 0x40;
301 port = sockets[socket].io_base;
307 spin_unlock_irqrestore(&port_lock,flags);
311 static void indirect_resetbit(int socket, unsigned short reg, unsigned char mask)
316 spin_lock_irqsave(&port_lock,flags);
317 reg = reg + socket * 0x40;
318 port = sockets[socket].io_base;
324 spin_unlock_irqrestore(&port_lock,flags);
327 static void indirect_write16(int socket, unsigned short reg, unsigned short value)
332 spin_lock_irqsave(&port_lock,flags);
333 reg = reg + socket * 0x40;
334 port = sockets[socket].io_base;
345 spin_unlock_irqrestore(&port_lock,flags);
348 /* simple helper functions */
349 /* External clock time, in nanoseconds. 120 ns = 8.33 MHz */
350 static int cycle_time = 120;
352 static int to_cycles(int ns)
355 return ns/cycle_time;
360 static int to_ns(int cycles)
362 return cycle_time*cycles;
366 /* Interrupt handler functionality */
368 static void i82092aa_bh(void *dummy)
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);
382 static struct tq_struct i82092aa_task = {
387 static void i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs)
392 unsigned int events, active=0;
394 /* enter("i82092aa_interrupt");*/
399 printk(KERN_ERR "i82092aa: infinite eventloop in interrupt \n");
405 for (i=0;i<socket_count;i++) {
407 if (sockets[i].card_state==0) /* Inactive socket, should not happen */
410 csc = indirect_read(i,I365_CSC); /* card status change register */
412 if ((csc==0) || /* no events on this socket */
413 (sockets[i].handler==NULL)) /* no way to handle events */
417 if (csc & I365_CSC_DETECT) {
419 dprintk("Card detected in socket %i!\n",i);
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;
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;
433 sockets[i].pending_events |= events;
434 schedule_task(&i82092aa_task);
439 if (active==0) /* no more events to handle */
444 /* leave("i82092aa_interrupt");*/
449 /* socket functions */
451 static int card_present(int socketno)
454 enter("card_present");
456 if ((socketno<0) || (socketno > MAX_SOCKETS))
458 if (sockets[socketno].io_base == 0)
462 val = indirect_read(socketno, 1); /* Interface status register */
464 leave("card_present 1");
468 leave("card_present 0");
472 static void set_bridge_state(int sock)
474 enter("set_bridge_state");
475 indirect_write(sock, I365_GBLCTL,0x00);
476 indirect_write(sock, I365_GENCTL,0x00);
478 indirect_setbit(sock, I365_INTCTL,0x08);
479 leave("set_bridge_state");
487 static int i82092aa_init(unsigned int s)
490 pccard_io_map io = { 0, 0, 0, 0, 1 };
491 pccard_mem_map mem = { 0, 0, 0, 0, 0, 0 };
493 enter("i82092aa_init");
495 i82092aa_set_socket(s, &dead_socket);
496 for (i = 0; i < 2; i++) {
498 i82092aa_set_io_map(s, &io);
500 for (i = 0; i < 5; i++) {
502 i82092aa_set_mem_map(s, &mem);
505 leave("i82092aa_init");
509 static int i82092aa_suspend(unsigned int sock)
512 enter("i82092aa_suspend");
513 retval = i82092aa_set_socket(sock, &dead_socket);
514 leave("i82092aa_suspend");
518 static int i82092aa_register_callback(unsigned int sock, void (*handler)(void *, unsigned int), void * info)
520 enter("i82092aa_register_callback");
521 sockets[sock].handler = handler;
522 sockets[sock].info = info;
523 if (handler == NULL) {
528 leave("i82092aa_register_callback");
530 } /* i82092aa_register_callback */
532 static int i82092aa_inquire_socket(unsigned int sock, socket_cap_t *cap)
534 enter("i82092aa_inquire_socket");
535 *cap = sockets[sock].cap;
536 leave("i82092aa_inquire_socket");
538 } /* i82092aa_inquire_socket */
541 static int i82092aa_get_status(unsigned int sock, u_int *value)
545 enter("i82092aa_get_status");
547 status = indirect_read(sock,I365_STATUS); /* Interface Status Register */
550 if ((status & I365_CS_DETECT) == I365_CS_DETECT) {
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) {
558 if (!(status & I365_CS_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;
568 if (status & I365_CS_WRPROT)
569 (*value) |= SS_WRPROT; /* card is write protected */
571 if (status & I365_CS_READY)
572 (*value) |= SS_READY; /* card is not busy */
574 if (status & I365_CS_POWERON)
575 (*value) |= SS_POWERON; /* power is applied to the card */
578 leave("i82092aa_get_status");
583 static int i82092aa_get_socket(unsigned int sock, socket_state_t *state)
585 unsigned char reg,vcc,vpp;
587 enter("i82092aa_get_socket");
594 /* First the power status of the socket */
595 reg = indirect_read(sock,I365_POWER); /* PCTRL - Power Control Register */
597 if (reg & I365_PWR_AUTO)
598 state->flags |= SS_PWR_AUTO; /* Automatic Power Switch */
600 if (reg & I365_PWR_OUT)
601 state->flags |= SS_OUTPUT_ENA; /* Output signals are enabled */
603 vcc = reg & I365_VCC_MASK; vpp = reg & I365_VPP1_MASK;
605 if (reg & I365_VCC_5V) { /* Can still be 3.3V, in this case the Vcc value will be overwritten later */
608 if (vpp == I365_VPP1_5V)
610 if (vpp == I365_VPP1_12V)
615 if ((reg & I365_VCC_3V)==I365_VCC_3V)
619 /* Now the IO card, RESET flags and IO interrupt */
621 reg = indirect_read(sock, I365_INTCTL); /* IGENC, Interrupt and General Control */
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 */
628 /* Set the IRQ number */
629 if (sockets[sock].dev!=NULL)
630 state->io_irq = sockets[sock].dev->irq;
632 /* Card status change */
633 reg = indirect_read(sock, I365_CSCINT); /* CSCICR, Card Status Change Interrupt Configuration */
635 if (reg & I365_CSC_DETECT)
636 state->csc_mask |= SS_DETECT; /* Card detect is enabled */
638 if (state->flags & SS_IOCARD) {/* IO Cards behave different */
639 if (reg & I365_CSC_STSCHG)
640 state->csc_mask |= SS_STSCHG;
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;
650 leave("i82092aa_get_socket");
654 static int i82092aa_set_socket(unsigned int sock, socket_state_t *state)
658 enter("i82092aa_set_socket");
660 /* First, set the global controller options */
662 set_bridge_state(sock);
664 /* Values for the IGENC register */
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;
672 indirect_write(sock,I365_INTCTL,reg); /* IGENC, Interrupt and General Control Register */
674 /* Power registers */
676 reg = I365_PWR_NORESET; /* default: disable resetdrv on resume */
678 if (state->flags & SS_PWR_AUTO) {
679 dprintk("Auto power\n");
680 reg |= I365_PWR_AUTO; /* automatic power mngmnt */
682 if (state->flags & SS_OUTPUT_ENA) {
683 dprintk("Power Enabled \n");
684 reg |= I365_PWR_OUT; /* enable power */
687 switch (state->Vcc) {
691 dprintk("setting voltage to Vcc to 5V on socket %i\n",sock);
695 printk(KERN_WARNING "i82092aa: i82092aa_set_socket called with invalid VCC power value: %i ", state->Vcc);
696 leave("i82092aa_set_socket");
701 switch (state->Vpp) {
703 dprintk("not setting Vpp on socket %i\n",sock);
706 dprintk("setting Vpp to 5.0 for socket %i\n",sock);
707 reg |= I365_VPP1_5V | I365_VPP2_5V;
710 dprintk("setting Vpp to 12.0\n");
711 reg |= I365_VPP1_12V | I365_VPP2_12V;
714 printk(KERN_WARNING "i82092aa: i82092aa_set_socket called with invalid VPP power value: %i ", state->Vcc);
715 leave("i82092aa_set_socket");
719 if (reg != indirect_read(sock,I365_POWER)) /* only write if changed */
720 indirect_write(sock,I365_POWER,reg);
722 /* Enable specific interrupt events */
725 if (state->csc_mask & SS_DETECT) {
726 reg |= I365_CSC_DETECT;
728 if (state->flags & SS_IOCARD) {
729 if (state->csc_mask & SS_STSCHG)
730 reg |= I365_CSC_STSCHG;
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;
741 /* now write the value and clear the (probably bogus) pending stuff by doing a dummy read*/
743 indirect_write(sock,I365_CSCINT,reg);
744 (void)indirect_read(sock,I365_CSC);
746 leave("i82092aa_set_socket");
750 static int i82092aa_get_io_map(unsigned int sock, struct pccard_io_map *io)
752 unsigned char map, ioctl, addr;
754 enter("i82092aa_get_io_map");
757 leave("i82092aa_get_io_map with -EINVAL");
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);
765 ioctl = indirect_read(sock,I365_IOCTL); /* IOCREG: I/O Control Register */
766 addr = indirect_read(sock,I365_ADDRWIN); /* */
768 io->speed = to_ns(ioctl & I365_IOCTL_WAIT(map)) ? 1 : 0; /* check this out later */
771 if (addr & I365_IOCTL_16BIT(map))
772 io->flags |= MAP_AUTOSZ;
774 leave("i82092aa_get_io_map");
778 static int i82092aa_set_io_map(unsigned sock, struct pccard_io_map *io)
780 unsigned char map, ioctl;
782 enter("i82092aa_set_io_map");
786 /* Check error conditions */
788 leave("i82092aa_set_io_map with invalid map");
791 if ((io->start > 0xffff) || (io->stop > 0xffff) || (io->stop < io->start)){
792 leave("i82092aa_set_io_map with invalid io");
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));
800 /* printk("set_io_map: Setting range to %x - %x \n",io->start,io->stop); */
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);
806 ioctl = indirect_read(sock,I365_IOCTL) & ~I365_IOCTL_MASK(map);
808 if (io->flags & (MAP_16BIT|MAP_AUTOSZ))
809 ioctl |= I365_IOCTL_16BIT(map);
811 indirect_write(sock,I365_IOCTL,ioctl);
813 /* Turn the window back on if needed */
814 if (io->flags & MAP_ACTIVE)
815 indirect_setbit(sock,I365_ADDRWIN,I365_ENA_IO(map));
817 leave("i82092aa_set_io_map");
821 static int i82092aa_get_mem_map(unsigned sock, struct pccard_mem_map *mem)
823 unsigned short base, i;
824 unsigned char map, addr;
826 enter("i82092aa_get_mem_map");
832 leave("i82092aa_get_mem_map: -EINVAL");
836 addr = indirect_read(sock, I365_ADDRWIN);
838 if (addr & I365_ENA_MEM(map))
839 mem->flags |= MAP_ACTIVE; /* yes this mapping is active */
841 base = I365_MEM(map);
843 /* Find the start address - this register also has mapping info */
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;
851 mem->sys_start = ((unsigned long)(i & 0x0fff) << 12);
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)
857 if (i & I365_MEM_WS1)
859 mem->speed = to_ns(mem->speed);
860 mem->sys_stop = ( (unsigned long)(i & 0x0fff) << 12) + 0x0fff;
862 /* Find the card start address, also some more MAP attributes */
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;
872 dprintk("Card %i is from %lx to %lx \n",sock,mem->sys_start,mem->sys_stop);
874 leave("i82092aa_get_mem_map");
879 static int i82092aa_set_mem_map(unsigned sock, struct pccard_mem_map *mem)
881 unsigned short base, i;
884 enter("i82092aa_set_mem_map");
888 leave("i82092aa_set_mem_map: invalid map");
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));
897 if (!(mem->flags & MAP_ACTIVE))
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);
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); */
912 /* write the start address */
913 base = I365_MEM(map);
914 i = (mem->sys_start >> 12) & 0x0fff;
915 if (mem->flags & MAP_16BIT)
917 if (mem->flags & MAP_0WS)
919 indirect_write16(sock,base+I365_W_START,i);
921 /* write the stop address */
923 i= (mem->sys_stop >> 12) & 0x0fff;
924 switch (to_cycles(mem->speed)) {
934 i |= I365_MEM_WS1 | I365_MEM_WS0;
938 indirect_write16(sock,base+I365_W_STOP,i);
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);*/
949 /* printk("requesting normal memory for socket %i\n",sock);*/
951 indirect_write16(sock,base+I365_W_OFF,i);
952 indirect_write(sock, I365_CPAGE, membase);
954 /* Enable the window if necessary */
955 indirect_setbit(sock, I365_ADDRWIN, I365_ENA_MEM(map));
957 leave("i82092aa_set_mem_map");
961 static void i82092aa_proc_setup(unsigned int sock, struct proc_dir_entry *base)
967 static int i82092aa_module_init(void)
969 enter("i82092aa_module_init");
970 pci_register_driver(&i82092aa_pci_drv);
971 leave("i82092aa_module_init");
975 static void i82092aa_module_exit(void)
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");
985 module_init(i82092aa_module_init);
986 module_exit(i82092aa_module_exit);