~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/pnp/isapnp.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  ISA Plug & Play support
  3  *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
  4  *
  5  *
  6  *   This program is free software; you can redistribute it and/or modify
  7  *   it under the terms of the GNU General Public License as published by
  8  *   the Free Software Foundation; either version 2 of the License, or
  9  *   (at your option) any later version.
 10  *
 11  *   This program is distributed in the hope that it will be useful,
 12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14  *   GNU General Public License for more details.
 15  *
 16  *   You should have received a copy of the GNU General Public License
 17  *   along with this program; if not, write to the Free Software
 18  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 19  *
 20  *  Changelog:
 21  *  2000-01-01  Added quirks handling for buggy hardware
 22  *              Peter Denison <peterd@pnd-pc.demon.co.uk>
 23  *  2000-06-14  Added isapnp_probe_devs() and isapnp_activate_dev()
 24  *              Christoph Hellwig <hch@caldera.de>
 25  */
 26 
 27 #include <linux/config.h>
 28 #include <linux/version.h>
 29 #include <linux/module.h>
 30 #include <linux/kernel.h>
 31 #include <linux/errno.h>
 32 #include <linux/ioport.h>
 33 #include <linux/string.h>
 34 #include <linux/malloc.h>
 35 #include <linux/delay.h>
 36 #include <asm/io.h>
 37 #include <asm/dma.h>
 38 #include <asm/irq.h>
 39 #include <linux/pci.h>
 40 #include <linux/init.h>
 41 #include <linux/isapnp.h>
 42 
 43 LIST_HEAD(isapnp_cards);
 44 LIST_HEAD(isapnp_devices);
 45 
 46 #if 0
 47 #define ISAPNP_REGION_OK
 48 #endif
 49 #if 0
 50 #define ISAPNP_DEBUG
 51 #endif
 52 
 53 struct resource *pidxr_res;
 54 struct resource *pnpwrp_res;
 55 struct resource *isapnp_rdp_res;
 56 
 57 int isapnp_disable;                     /* Disable ISA PnP */
 58 int isapnp_rdp;                 /* Read Data Port */
 59 int isapnp_reset = 1;                   /* reset all PnP cards (deactivate) */
 60 int isapnp_skip_pci_scan;               /* skip PCI resource scanning */
 61 int isapnp_verbose = 1;                 /* verbose mode */
 62 int isapnp_reserve_irq[16] = { [0 ... 15] = -1 };       /* reserve (don't use) some IRQ */
 63 int isapnp_reserve_dma[8] = { [0 ... 7] = -1 };         /* reserve (don't use) some DMA */
 64 int isapnp_reserve_io[16] = { [0 ... 15] = -1 };        /* reserve (don't use) some I/O region */
 65 int isapnp_reserve_mem[16] = { [0 ... 15] = -1 };       /* reserve (don't use) some memory region */
 66 
 67 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 68 MODULE_DESCRIPTION("Generic ISA Plug & Play support");
 69 MODULE_PARM(isapnp_disable, "i");
 70 MODULE_PARM_DESC(isapnp_disable, "ISA Plug & Play disable");
 71 MODULE_PARM(isapnp_rdp, "i");
 72 MODULE_PARM_DESC(isapnp_rdp, "ISA Plug & Play read data port");
 73 MODULE_PARM(isapnp_reset, "i");
 74 MODULE_PARM_DESC(isapnp_reset, "ISA Plug & Play reset all cards");
 75 MODULE_PARM(isapnp_skip_pci_scan, "i");
 76 MODULE_PARM_DESC(isapnp_skip_pci_scan, "ISA Plug & Play skip PCI resource scanning");
 77 MODULE_PARM(isapnp_verbose, "i");
 78 MODULE_PARM_DESC(isapnp_verbose, "ISA Plug & Play verbose mode");
 79 MODULE_PARM(isapnp_reserve_irq, "1-16i");
 80 MODULE_PARM_DESC(isapnp_reserve_irq, "ISA Plug & Play - reserve IRQ line(s)");
 81 MODULE_PARM(isapnp_reserve_dma, "1-8i");
 82 MODULE_PARM_DESC(isapnp_reserve_dma, "ISA Plug & Play - reserve DMA channel(s)");
 83 MODULE_PARM(isapnp_reserve_io, "1-16i");
 84 MODULE_PARM_DESC(isapnp_reserve_io, "ISA Plug & Play - reserve I/O region(s) - port,size");
 85 MODULE_PARM(isapnp_reserve_mem, "1-16i");
 86 MODULE_PARM_DESC(isapnp_reserve_mem, "ISA Plug & Play - reserve memory region(s) - address,size");
 87 
 88 #define _PIDXR          0x279
 89 #define _PNPWRP         0xa79
 90 
 91 /* short tags */
 92 #define _STAG_PNPVERNO          0x01
 93 #define _STAG_LOGDEVID          0x02
 94 #define _STAG_COMPATDEVID       0x03
 95 #define _STAG_IRQ               0x04
 96 #define _STAG_DMA               0x05
 97 #define _STAG_STARTDEP          0x06
 98 #define _STAG_ENDDEP            0x07
 99 #define _STAG_IOPORT            0x08
100 #define _STAG_FIXEDIO           0x09
101 #define _STAG_VENDOR            0x0e
102 #define _STAG_END               0x0f
103 /* long tags */
104 #define _LTAG_MEMRANGE          0x81
105 #define _LTAG_ANSISTR           0x82
106 #define _LTAG_UNICODESTR        0x83
107 #define _LTAG_VENDOR            0x84
108 #define _LTAG_MEM32RANGE        0x85
109 #define _LTAG_FIXEDMEM32RANGE   0x86
110 
111 static unsigned char isapnp_checksum_value;
112 static DECLARE_MUTEX(isapnp_cfg_mutex);
113 static int isapnp_detected;
114 
115 /* some prototypes */
116 
117 static int isapnp_config_prepare(struct pci_dev *dev);
118 static int isapnp_config_activate(struct pci_dev *dev);
119 static int isapnp_config_deactivate(struct pci_dev *dev);
120 
121 static inline void write_data(unsigned char x)
122 {
123         outb(x, _PNPWRP);
124 }
125 
126 static inline void write_address(unsigned char x)
127 {
128         outb(x, _PIDXR);
129         udelay(20);
130 }
131 
132 static inline unsigned char read_data(void)
133 {
134         unsigned char val = inb(isapnp_rdp);
135         return val;
136 }
137 
138 unsigned char isapnp_read_byte(unsigned char idx)
139 {
140         write_address(idx);
141         return read_data();
142 }
143 
144 unsigned short isapnp_read_word(unsigned char idx)
145 {
146         unsigned short val;
147 
148         val = isapnp_read_byte(idx);
149         val = (val << 8) + isapnp_read_byte(idx+1);
150         return val;
151 }
152 
153 unsigned int isapnp_read_dword(unsigned char idx)
154 {
155         unsigned int val;
156 
157         val = isapnp_read_byte(idx);
158         val = (val << 8) + isapnp_read_byte(idx+1);
159         val = (val << 8) + isapnp_read_byte(idx+2);
160         val = (val << 8) + isapnp_read_byte(idx+3);
161         return val;
162 }
163 
164 void isapnp_write_byte(unsigned char idx, unsigned char val)
165 {
166         write_address(idx);
167         write_data(val);
168 }
169 
170 void isapnp_write_word(unsigned char idx, unsigned short val)
171 {
172         isapnp_write_byte(idx, val >> 8);
173         isapnp_write_byte(idx+1, val);
174 }
175 
176 void isapnp_write_dword(unsigned char idx, unsigned int val)
177 {
178         isapnp_write_byte(idx, val >> 24);
179         isapnp_write_byte(idx+1, val >> 16);
180         isapnp_write_byte(idx+2, val >> 8);
181         isapnp_write_byte(idx+3, val);
182 }
183 
184 void *isapnp_alloc(long size)
185 {
186         void *result;
187 
188         result = kmalloc(size, GFP_KERNEL);
189         if (!result)
190                 return NULL;
191         memset(result, 0, size);
192         return result;
193 }
194 
195 static void isapnp_key(void)
196 {
197         unsigned char code = 0x6a, msb;
198         int i;
199 
200         mdelay(1);
201         write_address(0x00);
202         write_address(0x00);
203 
204         write_address(code);
205 
206         for (i = 1; i < 32; i++) {
207                 msb = ((code & 0x01) ^ ((code & 0x02) >> 1)) << 7;
208                 code = (code >> 1) | msb;
209                 write_address(code);
210         }
211 }
212 
213 /* place all pnp cards in wait-for-key state */
214 static void isapnp_wait(void)
215 {
216         isapnp_write_byte(0x02, 0x02);
217 }
218 
219 void isapnp_wake(unsigned char csn)
220 {
221         isapnp_write_byte(0x03, csn);
222 }
223 
224 void isapnp_device(unsigned char logdev)
225 {
226         isapnp_write_byte(0x07, logdev);
227 }
228 
229 void isapnp_activate(unsigned char logdev)
230 {
231         isapnp_device(logdev);
232         isapnp_write_byte(ISAPNP_CFG_ACTIVATE, 1);
233         udelay(250);
234 }
235 
236 void isapnp_deactivate(unsigned char logdev)
237 {
238         isapnp_device(logdev);
239         isapnp_write_byte(ISAPNP_CFG_ACTIVATE, 0);
240         udelay(500);
241 }
242 
243 static void __init isapnp_peek(unsigned char *data, int bytes)
244 {
245         int i, j;
246         unsigned char d=0;
247 
248         for (i = 1; i <= bytes; i++) {
249                 for (j = 0; j < 20; j++) {
250                         d = isapnp_read_byte(0x05);
251                         if (d & 1)
252                                 break;
253                         udelay(100);
254                 }
255                 if (!(d & 1)) {
256                         if (data != NULL)
257                                 *data++ = 0xff;
258                         continue;
259                 }
260                 d = isapnp_read_byte(0x04);     /* PRESDI */
261                 isapnp_checksum_value += d;
262                 if (data != NULL)
263                         *data++ = d;
264         }
265 }
266 
267 #define RDP_STEP        32      /* minimum is 4 */
268 
269 static int isapnp_next_rdp(void)
270 {
271         int rdp = isapnp_rdp;
272         while (rdp <= 0x3ff) {
273                 /*
274                  *      We cannot use NE2000 probe spaces for ISAPnP or we
275                  *      will lock up machines.
276                  */
277                 if ((rdp < 0x280 || rdp >  0x380) && !check_region(rdp, 1)) 
278                 {
279                         isapnp_rdp = rdp;
280                         return 0;
281                 }
282                 rdp += RDP_STEP;
283         }
284         return -1;
285 }
286 
287 /* Set read port address */
288 static inline void isapnp_set_rdp(void)
289 {
290         isapnp_write_byte(0x00, isapnp_rdp >> 2);
291         udelay(100);
292 }
293 
294 /*
295  *      Perform an isolation. The port selection code now tries to avoid
296  *      "dangerous to read" ports.
297  */
298 
299 static int __init isapnp_isolate_rdp_select(void)
300 {
301         isapnp_wait();
302         isapnp_key();
303 
304         /* Control: reset CSN and conditionally everything else too */
305         isapnp_write_byte(0x02, isapnp_reset ? 0x05 : 0x04);
306         mdelay(2);
307 
308         isapnp_wait();
309         isapnp_key();
310         isapnp_wake(0x00);
311 
312         if (isapnp_next_rdp() < 0) {
313                 isapnp_wait();
314                 return -1;
315         }
316 
317         isapnp_set_rdp();
318         udelay(1000);
319         write_address(0x01);
320         udelay(1000);
321         return 0;
322 }
323 
324 /*
325  *  Isolate (assign uniqued CSN) to all ISA PnP devices.
326  */
327 
328 static int __init isapnp_isolate(void)
329 {
330         unsigned char checksum = 0x6a;
331         unsigned char chksum = 0x00;
332         unsigned char bit = 0x00;
333         int data;
334         int csn = 0;
335         int i;
336         int iteration = 1;
337 
338         isapnp_rdp = 0x213;
339         if (isapnp_isolate_rdp_select() < 0)
340                 return -1;
341 
342         while (1) {
343                 for (i = 1; i <= 64; i++) {
344                         data = read_data() << 8;
345                         udelay(250);
346                         data = data | read_data();
347                         udelay(250);
348                         if (data == 0x55aa)
349                                 bit = 0x01;
350                         checksum = ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit) << 7) | (checksum >> 1);
351                         bit = 0x00;
352                 }
353                 for (i = 65; i <= 72; i++) {
354                         data = read_data() << 8;
355                         udelay(250);
356                         data = data | read_data();
357                         udelay(250);
358                         if (data == 0x55aa)
359                                 chksum |= (1 << (i - 65));
360                 }
361                 if (checksum != 0x00 && checksum == chksum) {
362                         csn++;
363 
364                         isapnp_write_byte(0x06, csn);
365                         udelay(250);
366                         iteration++;
367                         isapnp_wake(0x00);
368                         isapnp_set_rdp();
369                         udelay(1000);
370                         write_address(0x01);
371                         udelay(1000);
372                         goto __next;
373                 }
374                 if (iteration == 1) {
375                         isapnp_rdp += RDP_STEP;
376                         if (isapnp_isolate_rdp_select() < 0)
377                                 return -1;
378                 } else if (iteration > 1) {
379                         break;
380                 }
381               __next:
382                 checksum = 0x6a;
383                 chksum = 0x00;
384                 bit = 0x00;
385         }
386         isapnp_wait();
387         return csn;
388 }
389 
390 /*
391  *  Read one tag from stream.
392  */
393 
394 static int __init isapnp_read_tag(unsigned char *type, unsigned short *size)
395 {
396         unsigned char tag, tmp[2];
397 
398         isapnp_peek(&tag, 1);
399         if (tag == 0)                           /* invalid tag */
400                 return -1;
401         if (tag & 0x80) {       /* large item */
402                 *type = tag;
403                 isapnp_peek(tmp, 2);
404                 *size = (tmp[1] << 8) | tmp[0];
405         } else {
406                 *type = (tag >> 3) & 0x0f;
407                 *size = tag & 0x07;
408         }
409 #if 0
410         printk("tag = 0x%x, type = 0x%x, size = %i\n", tag, *type, *size);
411 #endif
412         if (type == 0)                          /* wrong type */
413                 return -1;
414         if (*type == 0xff && *size == 0xffff)   /* probably invalid data */
415                 return -1;
416         return 0;
417 }
418 
419 /*
420  *  Skip specified number of bytes from stream.
421  */
422  
423 static void __init isapnp_skip_bytes(int count)
424 {
425         isapnp_peek(NULL, count);
426 }
427 
428 /*
429  *  Parse logical device tag.
430  */
431 
432 static struct pci_dev * __init isapnp_parse_device(struct pci_bus *card, int size, int number)
433 {
434         unsigned char tmp[6];
435         struct pci_dev *dev;
436 
437         isapnp_peek(tmp, size);
438         dev = isapnp_alloc(sizeof(struct pci_dev));
439         if (!dev)
440                 return NULL;
441         dev->dma_mask = 0x00ffffff;
442         dev->devfn = number;
443         dev->vendor = (tmp[1] << 8) | tmp[0];
444         dev->device = (tmp[3] << 8) | tmp[2];
445         dev->regs = tmp[4];
446         dev->bus = card;
447         if (size > 5)
448                 dev->regs |= tmp[5] << 8;
449         dev->prepare = isapnp_config_prepare;
450         dev->activate = isapnp_config_activate;
451         dev->deactivate = isapnp_config_deactivate;
452         return dev;
453 }
454 
455 /*
456  *  Build new resources structure
457  */
458 
459 static struct isapnp_resources * __init isapnp_build_resources(struct pci_dev *dev, int dependent)
460 {
461         struct isapnp_resources *res, *ptr, *ptra;
462         
463         res = isapnp_alloc(sizeof(struct isapnp_resources));
464         if (!res)
465                 return NULL;
466         res->dev = dev;
467         ptr = (struct isapnp_resources *)dev->sysdata;
468         while (ptr && ptr->next)
469                 ptr = ptr->next;
470         if (ptr && ptr->dependent && dependent) { /* add to another list */
471                 ptra = ptr->alt;
472                 while (ptra && ptra->alt)
473                         ptra = ptra->alt;
474                 if (!ptra)
475                         ptr->alt = res;
476                 else
477                         ptra->alt = res;
478         } else {
479                 if (!ptr)
480                         dev->sysdata = res;
481                 else
482                         ptr->next = res;
483         }
484         if (dependent) {
485                 res->priority = dependent & 0xff;
486                 if (res->priority > ISAPNP_RES_PRIORITY_FUNCTIONAL)
487                         res->priority = ISAPNP_RES_PRIORITY_INVALID;
488                 res->dependent = 1;
489         } else {
490                 res->priority = ISAPNP_RES_PRIORITY_PREFERRED;
491                 res->dependent = 0;
492         }
493         return res;
494 }
495 
496 /*
497  *  Add IRQ resource to resources list.
498  */
499 
500 static void __init isapnp_add_irq_resource(struct pci_dev *dev,
501                                                struct isapnp_resources **res,
502                                                int dependent, int size)
503 {
504         unsigned char tmp[3];
505         int i;
506         struct isapnp_irq *irq, *ptr;
507 
508         isapnp_peek(tmp, size);
509         irq = isapnp_alloc(sizeof(struct isapnp_irq));
510         if (!irq)
511                 return;
512         if (*res == NULL) {
513                 *res = isapnp_build_resources(dev, dependent);
514                 if (*res == NULL) {
515                         kfree(irq);
516                         return;
517                 }
518         }
519         irq->map = (tmp[1] << 8) | tmp[0];
520         if (size > 2)
521                 irq->flags = tmp[2];
522         else
523                 irq->flags = IORESOURCE_IRQ_HIGHEDGE;
524         irq->res = *res;
525         ptr = (*res)->irq;
526         while (ptr && ptr->next)
527                 ptr = ptr->next;
528         if (ptr)
529                 ptr->next = irq;
530         else
531                 (*res)->irq = irq;
532 #ifdef CONFIG_PCI
533         for (i=0; i<16; i++)
534                 if (irq->map & (1<<i))
535                         pcibios_penalize_isa_irq(i);
536 #endif
537 }
538 
539 /*
540  *  Add DMA resource to resources list.
541  */
542 
543 static void __init isapnp_add_dma_resource(struct pci_dev *dev,
544                                                struct isapnp_resources **res,
545                                                int dependent, int size)
546 {
547         unsigned char tmp[2];
548         struct isapnp_dma *dma, *ptr;
549 
550         isapnp_peek(tmp, size);
551         dma = isapnp_alloc(sizeof(struct isapnp_dma));
552         if (!dma)
553                 return;
554         if (*res == NULL) {
555                 *res = isapnp_build_resources(dev, dependent);
556                 if (*res == NULL) {
557                         kfree(dma);
558                         return;
559                 }
560         }
561         dma->map = tmp[0];
562         dma->flags = tmp[1];
563         dma->res = *res;
564         ptr = (*res)->dma;
565         while (ptr && ptr->next)
566                 ptr = ptr->next;
567         if (ptr)
568                 ptr->next = dma;
569         else
570                 (*res)->dma = dma;
571 }
572 
573 /*
574  *  Add port resource to resources list.
575  */
576 
577 static void __init isapnp_add_port_resource(struct pci_dev *dev,
578                                                 struct isapnp_resources **res,
579                                                 int dependent, int size)
580 {
581         unsigned char tmp[7];
582         struct isapnp_port *port, *ptr;
583 
584         isapnp_peek(tmp, size);
585         port = isapnp_alloc(sizeof(struct isapnp_port));
586         if (!port)
587                 return;
588         if (*res == NULL) {
589                 *res = isapnp_build_resources(dev, dependent);
590                 if (*res == NULL) {
591                         kfree(port);
592                         return;
593                 }
594         }
595         port->min = (tmp[2] << 8) | tmp[1];
596         port->max = (tmp[4] << 8) | tmp[3];
597         port->align = tmp[5];
598         port->size = tmp[6];
599         port->flags = tmp[0] ? ISAPNP_PORT_FLAG_16BITADDR : 0;
600         port->res = *res;
601         ptr = (*res)->port;
602         while (ptr && ptr->next)
603                 ptr = ptr->next;
604         if (ptr)
605                 ptr->next = port;
606         else
607                 (*res)->port = port;
608 }
609 
610 /*
611  *  Add fixed port resource to resources list.
612  */
613 
614 static void __init isapnp_add_fixed_port_resource(struct pci_dev *dev,
615                                                       struct isapnp_resources **res,
616                                                       int dependent, int size)
617 {
618         unsigned char tmp[3];
619         struct isapnp_port *port, *ptr;
620 
621         isapnp_peek(tmp, size);
622         port = isapnp_alloc(sizeof(struct isapnp_port));
623         if (!port)
624                 return;
625         if (*res == NULL) {
626                 *res = isapnp_build_resources(dev, dependent);
627                 if (*res == NULL) {
628                         kfree(port);
629                         return;
630                 }
631         }
632         port->min = port->max = (tmp[1] << 8) | tmp[0];
633         port->size = tmp[2];
634         port->align = 0;
635         port->flags = ISAPNP_PORT_FLAG_FIXED;
636         port->res = *res;
637         ptr = (*res)->port;
638         while (ptr && ptr->next)
639                 ptr = ptr->next;
640         if (ptr)
641                 ptr->next = port;
642         else
643                 (*res)->port = port;
644 }
645 
646 /*
647  *  Add memory resource to resources list.
648  */
649 
650 static void __init isapnp_add_mem_resource(struct pci_dev *dev,
651                                                struct isapnp_resources **res,
652                                                int dependent, int size)
653 {
654         unsigned char tmp[9];
655         struct isapnp_mem *mem, *ptr;
656 
657         isapnp_peek(tmp, size);
658         mem = isapnp_alloc(sizeof(struct isapnp_mem));
659         if (!mem)
660                 return;
661         if (*res == NULL) {
662                 *res = isapnp_build_resources(dev, dependent);
663                 if (*res == NULL) {
664                         kfree(mem);
665                         return;
666                 }
667         }
668         mem->min = ((tmp[2] << 8) | tmp[1]) << 8;
669         mem->max = ((tmp[4] << 8) | tmp[3]) << 8;
670         mem->align = (tmp[6] << 8) | tmp[5];
671         mem->size = ((tmp[8] << 8) | tmp[7]) << 8;
672         mem->flags = tmp[0];
673         mem->res = *res;
674         ptr = (*res)->mem;
675         while (ptr && ptr->next)
676                 ptr = ptr->next;
677         if (ptr)
678                 ptr->next = mem;
679         else
680                 (*res)->mem = mem;
681 }
682 
683 /*
684  *  Add 32-bit memory resource to resources list.
685  */
686 
687 static void __init isapnp_add_mem32_resource(struct pci_dev *dev,
688                                                  struct isapnp_resources **res,
689                                                  int dependent, int size)
690 {
691         unsigned char tmp[17];
692         struct isapnp_mem32 *mem32, *ptr;
693 
694         isapnp_peek(tmp, size);
695         mem32 = isapnp_alloc(sizeof(struct isapnp_mem32));
696         if (!mem32)
697                 return;
698         if (*res == NULL) {
699                 *res = isapnp_build_resources(dev, dependent);
700                 if (*res == NULL) {
701                         kfree(mem32);
702                         return;
703                 }
704         }
705         memcpy(mem32->data, tmp, 17);
706         mem32->res = *res;
707         ptr = (*res)->mem32;
708         while (ptr && ptr->next)
709                 ptr = ptr->next;
710         if (ptr)
711                 ptr->next = mem32;
712         else
713                 (*res)->mem32 = mem32;
714 }
715 
716 /*
717  *  Add 32-bit fixed memory resource to resources list.
718  */
719 
720 static void __init isapnp_add_fixed_mem32_resource(struct pci_dev *dev,
721                                                        struct isapnp_resources **res,
722                                                        int dependent, int size)
723 {
724         unsigned char tmp[17];
725         struct isapnp_mem32 *mem32, *ptr;
726 
727         isapnp_peek(tmp, size);
728         mem32 = isapnp_alloc(sizeof(struct isapnp_mem32));
729         if (!mem32)
730                 return;
731         if (*res == NULL) {
732                 *res = isapnp_build_resources(dev, dependent);
733                 if (*res == NULL) {
734                         kfree(mem32);
735                         return;
736                 }
737         }
738         memcpy(mem32->data, tmp, 17);
739         mem32->res = *res;
740         ptr = (*res)->mem32;
741         while (ptr && ptr->next)
742                 ptr = ptr->next;
743         if (ptr)
744                 ptr->next = mem32;
745         else
746                 (*res)->mem32 = mem32;
747 }
748 
749 /*
750  *  Parse card name for ISA PnP device.
751  */ 
752  
753 static void __init 
754 isapnp_parse_name(char *name, unsigned int name_max, unsigned short *size)
755 {
756         if (name[0] == '\0') {
757                 unsigned short size1 = *size >= name_max ? (name_max - 1) : *size;
758                 isapnp_peek(name, size1);
759                 name[size1] = '\0';
760                 *size -= size1;
761                 
762                 /* clean whitespace from end of string */
763                 while (size1 > 0  &&  name[--size1] == ' ') 
764                         name[size1] = '\0';
765         }       
766 }
767 
768 /*
769  *  Parse resource map for logical device.
770  */
771 
772 static int __init isapnp_create_device(struct pci_bus *card,
773                                            unsigned short size)
774 {
775         int number = 0, skip = 0, dependent = 0, compat = 0;
776         unsigned char type, tmp[17];
777         struct pci_dev *dev;
778         struct isapnp_resources *res = NULL;
779         
780         if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
781                 return 1;
782         list_add(&dev->bus_list, &card->devices);
783         list_add_tail(&dev->global_list, &isapnp_devices);
784         while (1) {
785                 if (isapnp_read_tag(&type, &size)<0)
786                         return 1;
787                 if (skip && type != _STAG_LOGDEVID && type != _STAG_END)
788                         goto __skip;
789                 switch (type) {
790                 case _STAG_LOGDEVID:
791                         if (size >= 5 && size <= 6) {
792                                 isapnp_config_prepare(dev);
793                                 if ((dev = isapnp_parse_device(card, size, number++)) == NULL)
794                                         return 1;
795                                 list_add_tail(&dev->bus_list, &card->devices);
796                                 list_add_tail(&dev->global_list, &isapnp_devices);
797                                 size = 0;
798                                 skip = 0;
799                         } else {
800                                 skip = 1;
801                         }
802                         res = NULL;
803                         dependent = 0;
804                         compat = 0;
805                         break;
806                 case _STAG_COMPATDEVID:
807                         if (size == 4 && compat < DEVICE_COUNT_COMPATIBLE) {
808                                 isapnp_peek(tmp, 4);
809                                 dev->vendor_compatible[compat] = (tmp[1] << 8) | tmp[0];
810                                 dev->device_compatible[compat] = (tmp[3] << 8) | tmp[2];
811                                 compat++;
812                                 size = 0;
813                         }
814                         break;
815                 case _STAG_IRQ:
816                         if (size < 2 || size > 3)
817                                 goto __skip;
818                         isapnp_add_irq_resource(dev, &res, dependent, size);
819                         size = 0;
820                         break;
821                 case _STAG_DMA:
822                         if (size != 2)
823                                 goto __skip;
824                         isapnp_add_dma_resource(dev, &res, dependent, size);
825                         size = 0;
826                         break;
827                 case _STAG_STARTDEP:
828                         if (size > 1)
829                                 goto __skip;
830                         res = NULL;
831                         dependent = 0x100 | ISAPNP_RES_PRIORITY_ACCEPTABLE;
832                         if (size > 0) {
833                                 isapnp_peek(tmp, size);
834                                 dependent = 0x100 | tmp[0];
835                                 size = 0;
836                         }
837                         break;
838                 case _STAG_ENDDEP:
839                         if (size != 0)
840                                 goto __skip;
841                         res = NULL;
842                         dependent = 0;
843                         break;
844                 case _STAG_IOPORT:
845                         if (size != 7)
846                                 goto __skip;
847                         isapnp_add_port_resource(dev, &res, dependent, size);
848                         size = 0;
849                         break;
850                 case _STAG_FIXEDIO:
851                         if (size != 3)
852                                 goto __skip;
853                         isapnp_add_fixed_port_resource(dev, &res, dependent, size);
854                         size = 0;
855                         break;
856                 case _STAG_VENDOR:
857                         break;
858                 case _LTAG_MEMRANGE:
859                         if (size != 9)
860                                 goto __skip;
861                         isapnp_add_mem_resource(dev, &res, dependent, size);
862                         size = 0;
863                         break;
864                 case _LTAG_ANSISTR:
865                         isapnp_parse_name(dev->name, sizeof(dev->name), &size);
866                         break;
867                 case _LTAG_UNICODESTR:
868                         /* silently ignore */
869                         /* who use unicode for hardware identification? */
870                         break;
871                 case _LTAG_VENDOR:
872                         break;
873                 case _LTAG_MEM32RANGE:
874                         if (size != 17)
875                                 goto __skip;
876                         isapnp_add_mem32_resource(dev, &res, dependent, size);
877                         size = 0;
878                         break;
879                 case _LTAG_FIXEDMEM32RANGE:
880                         if (size != 17)
881                                 goto __skip;
882                         isapnp_add_fixed_mem32_resource(dev, &res, dependent, size);
883                         size = 0;
884                         break;
885                 case _STAG_END:
886                         if (size > 0)
887                                 isapnp_skip_bytes(size);
888                         return 1;
889                 default:
890                         printk("isapnp: unexpected or unknown tag type 0x%x for logical device %i (device %i), ignored\n", type, dev->devfn, card->number);
891                 }
892               __skip:
893                 if (size > 0)
894                         isapnp_skip_bytes(size);
895         }
896         isapnp_config_prepare(dev);
897         return 0;
898 }
899 
900 /*
901  *  Parse resource map for ISA PnP card.
902  */
903  
904 static void __init isapnp_parse_resource_map(struct pci_bus *card)
905 {
906         unsigned char type, tmp[17];
907         unsigned short size;
908         
909         while (1) {
910                 if (isapnp_read_tag(&type, &size)<0)
911                         return;
912                 switch (type) {
913                 case _STAG_PNPVERNO:
914                         if (size != 2)
915                                 goto __skip;
916                         isapnp_peek(tmp, 2);
917                         card->pnpver = tmp[0];
918                         card->productver = tmp[1];
919                         size = 0;
920                         break;
921                 case _STAG_LOGDEVID:
922                         if (size >= 5 && size <= 6) {
923                                 if (isapnp_create_device(card, size)==1)
924                                         return;
925                                 size = 0;
926                         }
927                         break;
928                 case _STAG_VENDOR:
929                         break;
930                 case _LTAG_ANSISTR:
931                         isapnp_parse_name(card->name, sizeof(card->name), &size);
932                         break;
933                 case _LTAG_UNICODESTR:
934                         /* silently ignore */
935                         /* who use unicode for hardware identification? */
936                         break;
937                 case _LTAG_VENDOR:
938                         break;
939                 case _STAG_END:
940                         if (size > 0)
941                                 isapnp_skip_bytes(size);
942                         return;
943                 default:
944                         printk("isapnp: unexpected or unknown tag type 0x%x for device %i, ignored\n", type, card->number);
945                 }
946               __skip:
947                 if (size > 0)
948                         isapnp_skip_bytes(size);
949         }
950 }
951 
952 /*
953  *  Compute ISA PnP checksum for first eight bytes.
954  */
955 
956 static unsigned char __init isapnp_checksum(unsigned char *data)
957 {
958         int i, j;
959         unsigned char checksum = 0x6a, bit, b;
960         
961         for (i = 0; i < 8; i++) {
962                 b = data[i];
963                 for (j = 0; j < 8; j++) {
964                         bit = 0;
965                         if (b & (1 << j))
966                                 bit = 1;
967                         checksum = ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit) << 7) | (checksum >> 1);
968                 }
969         }
970         return checksum;
971 }
972 
973 /*
974  *  Build device list for all present ISA PnP devices.
975  */
976 
977 static int __init isapnp_build_device_list(void)
978 {
979         int csn;
980         unsigned char header[9], checksum;
981         struct pci_bus *card;
982         struct pci_dev *dev;
983 
984         isapnp_wait();
985         isapnp_key();
986         for (csn = 1; csn <= 10; csn++) {
987                 isapnp_wake(csn);
988                 isapnp_peek(header, 9);
989                 checksum = isapnp_checksum(header);
990 #if 0
991                 printk("vendor: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
992                         header[0], header[1], header[2], header[3],
993                         header[4], header[5], header[6], header[7], header[8]);
994                 printk("checksum = 0x%x\n", checksum);
995 #endif
996                 if (checksum == 0x00 || checksum != header[8])  /* not valid CSN */
997                         continue;
998                 if ((card = isapnp_alloc(sizeof(struct pci_bus))) == NULL)
999                         continue;
1000                 card->number = csn;
1001                 card->vendor = (header[1] << 8) | header[0];
1002                 card->device = (header[3] << 8) | header[2];
1003                 card->serial = (header[7] << 24) | (header[6] << 16) | (header[5] << 8) | header[4];
1004                 isapnp_checksum_value = 0x00;
1005                 INIT_LIST_HEAD(&card->children);
1006                 INIT_LIST_HEAD(&card->devices);
1007                 isapnp_parse_resource_map(card);
1008                 if (isapnp_checksum_value != 0x00)
1009                         printk("isapnp: checksum for device %i is not valid (0x%x)\n", csn, isapnp_checksum_value);
1010                 card->checksum = isapnp_checksum_value;
1011 
1012                 list_add_tail(&card->node, &isapnp_cards);
1013         }
1014         isapnp_for_each_dev(dev) {
1015                 isapnp_fixup_device(dev);
1016         }
1017         return 0;
1018 }
1019 
1020 /*
1021  *  Basic configuration routines.
1022  */
1023 
1024 int isapnp_present(void)
1025 {
1026         return !list_empty(&isapnp_devices);
1027 }
1028 
1029 int isapnp_cfg_begin(int csn, int logdev)
1030 {
1031         if (csn < 1 || csn > 10 || logdev > 10)
1032                 return -EINVAL;
1033         MOD_INC_USE_COUNT;
1034         down(&isapnp_cfg_mutex);
1035         isapnp_wait();
1036         isapnp_key();
1037         isapnp_wake(csn);
1038 #if 1   /* to avoid malfunction when the isapnptools package is used */
1039         isapnp_set_rdp();
1040         udelay(1000);   /* delay 1000us */
1041         write_address(0x01);
1042         udelay(1000);   /* delay 1000us */
1043 #endif
1044         if (logdev >= 0)
1045                 isapnp_device(logdev);
1046         return 0;
1047 }
1048 
1049 int isapnp_cfg_end(void)
1050 {
1051         isapnp_wait();
1052         up(&isapnp_cfg_mutex);
1053         MOD_DEC_USE_COUNT;
1054         return 0;
1055 }
1056 
1057 /*
1058  *  Resource manager.
1059  */
1060 
1061 static struct isapnp_port *isapnp_find_port(struct pci_dev *dev, int index)
1062 {
1063         struct isapnp_resources *res;
1064         struct isapnp_port *port;
1065         
1066         if (!dev || index < 0 || index > 7)
1067                 return NULL;
1068         for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
1069                 for (port = res->port; port; port = port->next) {
1070                         if (!index)
1071                                 return port;
1072                         index--;
1073                 }
1074         }
1075         return NULL;
1076 }
1077 
1078 struct isapnp_irq *isapnp_find_irq(struct pci_dev *dev, int index)
1079 {
1080         struct isapnp_resources *res, *resa;
1081         struct isapnp_irq *irq;
1082         int index1, index2, index3;
1083         
1084         if (!dev || index < 0 || index > 7)
1085                 return NULL;
1086         for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
1087                 index3 = 0;
1088                 for (resa = res; resa; resa = resa->alt) {
1089                         index1 = index;
1090                         index2 = 0;
1091                         for (irq = resa->irq; irq; irq = irq->next) {
1092                                 if (!index1)
1093                                         return irq;
1094                                 index1--;
1095                                 index2++;
1096                         }
1097                         if (index3 < index2)
1098                                 index3 = index2;
1099                 }
1100                 index -= index3;
1101         }
1102         return NULL;
1103 }
1104 
1105 struct isapnp_dma *isapnp_find_dma(struct pci_dev *dev, int index)
1106 {
1107         struct isapnp_resources *res;
1108         struct isapnp_dma *dma;
1109         
1110         if (!dev || index < 0 || index > 7)
1111                 return NULL;
1112         for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
1113                 for (dma = res->dma; dma; dma = dma->next) {
1114                         if (!index)
1115                                 return dma;
1116                         index--;
1117                 }
1118         }
1119         return NULL;
1120 }
1121 
1122 struct isapnp_mem *isapnp_find_mem(struct pci_dev *dev, int index)
1123 {
1124         struct isapnp_resources *res;
1125         struct isapnp_mem *mem;
1126         
1127         if (!dev || index < 0 || index > 7)
1128                 return NULL;
1129         for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
1130                 for (mem = res->mem; mem; mem = mem->next) {
1131                         if (!index)
1132                                 return mem;
1133                         index--;
1134                 }
1135         }
1136         return NULL;
1137 }
1138 
1139 struct isapnp_mem32 *isapnp_find_mem32(struct pci_dev *dev, int index)
1140 {
1141         struct isapnp_resources *res;
1142         struct isapnp_mem32 *mem32;
1143         
1144         if (!dev || index < 0 || index > 7)
1145                 return NULL;
1146         for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
1147                 for (mem32 = res->mem32; mem32; mem32 = mem32->next) {
1148                         if (!index)
1149                                 return mem32;
1150                         index--;
1151                 }
1152         }
1153         return NULL;
1154 }
1155 
1156 /*
1157  *  Device manager.
1158  */
1159 
1160 struct pci_bus *isapnp_find_card(unsigned short vendor,
1161                                  unsigned short device,
1162                                  struct pci_bus *from)
1163 {
1164         struct list_head *list;
1165 
1166         list = isapnp_cards.next;
1167         if (from)
1168                 list = from->node.next;
1169 
1170         while (list != &isapnp_cards) {
1171                 struct pci_bus *card = pci_bus_b(list);
1172                 if (card->vendor == vendor && card->device == device)
1173                         return card;
1174                 list = list->next;
1175         }
1176         return NULL;
1177 }
1178 
1179 struct pci_dev *isapnp_find_dev(struct pci_bus *card,
1180                                 unsigned short vendor,
1181                                 unsigned short function,
1182                                 struct pci_dev *from)
1183 {
1184         if (card == NULL) {     /* look for a logical device from all cards */
1185                 struct list_head *list;
1186 
1187                 list = isapnp_devices.next;
1188                 if (from)
1189                         list = from->global_list.next;
1190 
1191                 while (list != &isapnp_devices) {
1192                         int idx;
1193                         struct pci_dev *dev = pci_dev_g(list);
1194 
1195                         if (dev->vendor == vendor && dev->device == function)
1196                                 return dev;
1197                         for (idx = 0; idx < DEVICE_COUNT_COMPATIBLE; idx++)
1198                                 if (dev->vendor_compatible[idx] == vendor &&
1199                                     dev->device_compatible[idx] == function)
1200                                         return dev;
1201                         list = list->next;
1202                 }
1203         } else {
1204                 struct list_head *list;
1205 
1206                 list = card->devices.next;
1207                 if (from) {
1208                         list = from->bus_list.next;
1209                         if (from->bus != card)  /* something is wrong */
1210                                 return NULL;
1211                 }
1212                 while (list != &card->devices) {
1213                         int idx;
1214                         struct pci_dev *dev = pci_dev_b(list);
1215 
1216                         if (dev->vendor == vendor && dev->device == function)
1217                                 return dev;
1218                         for (idx = 0; idx < DEVICE_COUNT_COMPATIBLE; idx++)
1219                                 if (dev->vendor_compatible[idx] == vendor &&
1220                                     dev->device_compatible[idx] == function)
1221                                         return dev;
1222                         list = list->next;
1223                 }
1224         }
1225         return NULL;
1226 }
1227 
1228 static const struct isapnp_card_id *
1229 isapnp_match_card(const struct isapnp_card_id *ids, struct pci_bus *card)
1230 {
1231         int idx;
1232 
1233         while (ids->card_vendor || ids->card_device) {
1234                 if ((ids->card_vendor == ISAPNP_ANY_ID || ids->card_vendor == card->vendor) &&
1235                     (ids->card_device == ISAPNP_ANY_ID || ids->card_device == card->device)) {
1236                         for (idx = 0; idx < ISAPNP_CARD_DEVS; idx++) {
1237                                 if (ids->devs[idx].vendor == 0 &&
1238                                     ids->devs[idx].function == 0)
1239                                         return ids;
1240                                 if (isapnp_find_dev(card,
1241                                                     ids->devs[idx].vendor,
1242                                                     ids->devs[idx].function,
1243                                                     NULL) == NULL)
1244                                         goto __next;
1245                         }
1246                         return ids;
1247                 }
1248               __next:
1249                 ids++;
1250         }
1251         return NULL;
1252 }
1253 
1254 int isapnp_probe_cards(const struct isapnp_card_id *ids,
1255                        int (*probe)(struct pci_bus *_card,
1256                                     const struct isapnp_card_id *_id))
1257 {
1258         struct pci_bus *card;   
1259         const struct isapnp_card_id *id;
1260         int count = 0;
1261 
1262         if (ids == NULL || probe == NULL)
1263                 return -EINVAL;
1264         isapnp_for_each_card(card) {
1265                 id = isapnp_match_card(ids, card);
1266                 if (id != NULL && probe(card, id) >= 0)
1267                         count++;
1268         }
1269         return count;
1270 }
1271 
1272 static const struct isapnp_device_id *
1273 isapnp_match_dev(const struct isapnp_device_id *ids, struct pci_dev *dev)
1274 {
1275         while (ids->card_vendor || ids->card_device) {
1276                 if ((ids->card_vendor == ISAPNP_ANY_ID || ids->card_vendor == dev->bus->vendor) &&
1277                     (ids->card_device == ISAPNP_ANY_ID || ids->card_device == dev->bus->device) &&
1278                     (ids->vendor == ISAPNP_ANY_ID || ids->vendor == dev->vendor) &&
1279                     (ids->function == ISAPNP_ANY_ID || ids->function == dev->device))
1280                         return ids;
1281                 ids++;
1282         }
1283         return NULL;
1284 }
1285 
1286 int isapnp_probe_devs(const struct isapnp_device_id *ids,
1287                       int (*probe)(struct pci_dev *dev,
1288                                    const struct isapnp_device_id *id))
1289 {
1290         
1291         struct pci_dev *dev;
1292         const struct isapnp_device_id *id;
1293         int count = 0;
1294 
1295         if (ids == NULL || probe == NULL)
1296                 return -EINVAL;
1297         isapnp_for_each_dev(dev) {
1298                 id = isapnp_match_dev(ids, dev);
1299                 if (id != NULL && probe(dev, id) >= 0)
1300                         count++;
1301         }
1302         return count;
1303 }
1304 
1305 int isapnp_activate_dev(struct pci_dev *dev, const char *name)
1306 {
1307         int err;
1308         
1309         /* Device already active? Let's use it and inform the caller */
1310         if (dev->active)
1311                 return -EBUSY;
1312 
1313         if ((err = dev->activate(dev)) < 0) {
1314                 printk(KERN_ERR "isapnp: config of %s failed (out of resources?)[%d]\n", name, err);
1315                 dev->deactivate(dev);
1316                 return err;
1317         }
1318 
1319         return 0;
1320 }
1321 
1322 static unsigned int isapnp_dma_resource_flags(struct isapnp_dma *dma)
1323 {
1324         return dma->flags | IORESOURCE_DMA | IORESOURCE_AUTO;
1325 }
1326 
1327 static unsigned int isapnp_mem_resource_flags(struct isapnp_mem *mem)
1328 {
1329         unsigned int result;
1330 
1331         result = mem->flags | IORESOURCE_MEM | IORESOURCE_AUTO;
1332         if (!(mem->flags & IORESOURCE_MEM_WRITEABLE))
1333                 result |= IORESOURCE_READONLY;
1334         if (mem->flags & IORESOURCE_MEM_CACHEABLE)
1335                 result |= IORESOURCE_CACHEABLE;
1336         if (mem->flags & IORESOURCE_MEM_RANGELENGTH)
1337                 result |= IORESOURCE_RANGELENGTH;
1338         if (mem->flags & IORESOURCE_MEM_SHADOWABLE)
1339                 result |= IORESOURCE_SHADOWABLE;
1340         return result;
1341 }
1342 
1343 static unsigned int isapnp_irq_resource_flags(struct isapnp_irq *irq)
1344 {
1345         return irq->flags | IORESOURCE_IRQ | IORESOURCE_AUTO;
1346 }
1347 
1348 static unsigned int isapnp_port_resource_flags(struct isapnp_port *port)
1349 {
1350         return port->flags | IORESOURCE_IO | IORESOURCE_AUTO;
1351 }
1352 
1353 static int isapnp_config_prepare(struct pci_dev *dev)
1354 {
1355         struct isapnp_resources *res, *resa;
1356         struct isapnp_port *port;
1357         struct isapnp_irq *irq;
1358         struct isapnp_dma *dma;
1359         struct isapnp_mem *mem;
1360         int port_count, port_count1;
1361         int irq_count, irq_count1;
1362         int dma_count, dma_count1;
1363         int mem_count, mem_count1;
1364         int idx;
1365 
1366         if (dev == NULL)
1367                 return -EINVAL;
1368         if (dev->active || dev->ro)
1369                 return -EBUSY;
1370         for (idx = 0; idx < DEVICE_COUNT_IRQ; idx++) {
1371                 dev->irq_resource[idx].name = NULL;
1372                 dev->irq_resource[idx].start = 0;
1373                 dev->irq_resource[idx].end = 0;
1374                 dev->irq_resource[idx].flags = 0;
1375         }
1376         for (idx = 0; idx < DEVICE_COUNT_DMA; idx++) {
1377                 dev->dma_resource[idx].name = NULL;
1378                 dev->dma_resource[idx].start = 0;
1379                 dev->dma_resource[idx].end = 0;
1380                 dev->dma_resource[idx].flags = 0;
1381         }
1382         for (idx = 0; idx < DEVICE_COUNT_RESOURCE; idx++) {
1383                 dev->resource[idx].name = NULL;
1384                 dev->resource[idx].start = 0;
1385                 dev->resource[idx].end = 0;
1386                 dev->resource[idx].flags = 0;
1387         }
1388         port_count = irq_count = dma_count = mem_count = 0;
1389         for (res = (struct isapnp_resources *)dev->sysdata; res; res = res->next) {
1390                 port_count1 = irq_count1 = dma_count1 = mem_count1 = 0;
1391                 for (resa = res; resa; resa = resa->alt) {
1392                         for (port = resa->port, idx = 0; port; port = port->next, idx++) {
1393                                 if (dev->resource[port_count + idx].flags == 0) {
1394                                         dev->resource[port_count + idx].flags = isapnp_port_resource_flags(port);
1395                                         dev->resource[port_count + idx].end = port->size;
1396                                 }
1397                         }
1398                         if (port_count1 < idx)
1399                                 port_count1 = idx;
1400                         for (irq = resa->irq, idx = 0; irq; irq = irq->next, idx++) {
1401                                 int count = irq_count + idx;
1402                                 if (count < DEVICE_COUNT_IRQ) {
1403                                         if (dev->irq_resource[count].flags == 0) {
1404                                                 dev->irq_resource[count].flags = isapnp_irq_resource_flags(irq);
1405                                         }
1406                                 }
1407                                 
1408                         }
1409                         if (irq_count1 < idx)
1410                                 irq_count1 = idx;
1411                         for (dma = resa->dma, idx = 0; dma; dma = dma->next, idx++)
1412                                 if (dev->dma_resource[idx].flags == 0) {
1413                                         dev->dma_resource[idx].flags = isapnp_dma_resource_flags(dma);
1414                                 }
1415                         if (dma_count1 < idx)
1416                                 dma_count1 = idx;
1417                         for (mem = resa->mem, idx = 0; mem; mem = mem->next, idx++)
1418                                 if (dev->resource[mem_count + idx + 8].flags == 0) {
1419                                         dev->resource[mem_count + idx + 8].flags = isapnp_mem_resource_flags(mem);
1420                                 }
1421                         if (mem_count1 < idx)
1422                                 mem_count1 = idx;
1423                 }
1424                 port_count += port_count1;
1425                 irq_count += irq_count1;
1426                 dma_count += dma_count1;
1427                 mem_count += mem_count1;
1428         }
1429         return 0;
1430 }
1431 
1432 struct isapnp_cfgtmp {
1433         struct isapnp_port *port[8];
1434         struct isapnp_irq *irq[2];
1435         struct isapnp_dma *dma[2];
1436         struct isapnp_mem *mem[4];
1437         struct pci_dev *request;
1438         struct pci_dev result;
1439 };
1440 
1441 static int isapnp_alternative_switch(struct isapnp_cfgtmp *cfg,
1442                                      struct isapnp_resources *from,
1443                                      struct isapnp_resources *to)
1444 {
1445         int tmp, tmp1;
1446         struct isapnp_port *port;
1447         struct isapnp_irq *irq;
1448         struct isapnp_dma *dma;
1449         struct isapnp_mem *mem;
1450 
1451         if (!cfg)
1452                 return -EINVAL;
1453         /* process port settings */
1454         for (tmp = 0; tmp < 8; tmp++) {
1455                 if (!(cfg->request->resource[tmp].flags & IORESOURCE_AUTO))
1456                         continue;               /* don't touch */
1457                 port = cfg->port[tmp];
1458                 if (!port) {
1459                         cfg->port[tmp] = port = isapnp_find_port(cfg->request, tmp);
1460                         if (!port)
1461                                 return -EINVAL;
1462                 }
1463                 if (from && port->res == from) {
1464                         while (port->res != to) {
1465                                 if (!port->res->alt)
1466                                         return -EINVAL;
1467                                 port = port->res->alt->port;
1468                                 for (tmp1 = tmp; tmp1 > 0 && port; tmp1--)
1469                                         port = port->next;
1470                                 cfg->port[tmp] = port;
1471                                 if (!port)
1472                                         return -ENOENT;
1473                                 cfg->result.resource[tmp].flags = isapnp_port_resource_flags(port);
1474                         }
1475                 }
1476         }
1477         /* process irq settings */
1478         for (tmp = 0; tmp < 2; tmp++) {
1479                 if (!(cfg->request->irq_resource[tmp].flags & IORESOURCE_AUTO))
1480                         continue;               /* don't touch */
1481                 irq = cfg->irq[tmp];
1482                 if (!irq) {
1483                         cfg->irq[tmp] = irq = isapnp_find_irq(cfg->request, tmp);
1484                         if (!irq)
1485                                 return -EINVAL;
1486                 }
1487                 if (from && irq->res == from) {
1488                         while (irq->res != to) {
1489                                 if (!irq->res->alt)
1490                                         return -EINVAL;
1491                                 irq = irq->res->alt->irq;
1492                                 for (tmp1 = tmp; tmp1 > 0 && irq; tmp1--)
1493                                         irq = irq->next;
1494                                 cfg->irq[tmp] = irq;
1495                                 if (!irq)
1496                                         return -ENOENT;
1497                                 cfg->result.irq_resource[tmp].flags = isapnp_irq_resource_flags(irq);
1498                         }
1499                 }
1500         }
1501         /* process dma settings */
1502         for (tmp = 0; tmp < 2; tmp++) {
1503                 if (!(cfg->request->dma_resource[tmp].flags & IORESOURCE_AUTO))
1504                         continue;               /* don't touch */
1505                 dma = cfg->dma[tmp];
1506                 if (!dma) {
1507                         cfg->dma[tmp] = dma = isapnp_find_dma(cfg->request, tmp);
1508                         if (!dma)
1509                                 return -EINVAL;
1510                 }
1511                 if (from && dma->res == from) {
1512                         while (dma->res != to) {
1513                                 if (!dma->res->alt)
1514                                         return -EINVAL;
1515                                 dma = dma->res->alt->dma;
1516                                 for (tmp1 = tmp; tmp1 > 0 && dma; tmp1--)
1517                                         dma = dma->next;
1518                                 cfg->dma[tmp] = dma;
1519                                 if (!dma)
1520                                         return -ENOENT;
1521                                 cfg->result.dma_resource[tmp].flags = isapnp_dma_resource_flags(dma);
1522                         }
1523                 }
1524         }
1525         /* process memory settings */
1526         for (tmp = 0; tmp < 4; tmp++) {
1527                 if (!(cfg->request->resource[tmp + 8].flags & IORESOURCE_AUTO))
1528                         continue;               /* don't touch */
1529                 mem = cfg->mem[tmp];
1530                 if (!mem) {
1531                         cfg->mem[tmp] = mem = isapnp_find_mem(cfg->request, tmp);
1532                         if (!mem)
1533                                 return -EINVAL;
1534                 }
1535                 if (from && mem->res == from) {
1536                         while (mem->res != to) {
1537                                 if (!mem->res->alt)
1538                                         return -EINVAL;
1539                                 mem = mem->res->alt->mem;
1540                                 for (tmp1 = tmp; tmp1 > 0 && mem; tmp1--)
1541                                         mem = mem->next;
1542                                 cfg->mem[tmp] = mem;
1543                                 if (!mem)
1544                                         return -ENOENT;
1545                                 cfg->result.resource[tmp + 8].flags = isapnp_mem_resource_flags(mem);
1546                         }
1547                 }
1548         }
1549         return 0;
1550 }
1551 
1552 static int isapnp_check_port(struct isapnp_cfgtmp *cfg, int port, int size, int idx)
1553 {
1554         int i, tmp, rport, rsize;
1555         struct isapnp_port *xport;
1556         struct pci_dev *dev;
1557 
1558         if (check_region(port, size))
1559                 return 1;
1560         for (i = 0; i < 8; i++) {
1561                 rport = isapnp_reserve_io[i << 1];
1562                 rsize = isapnp_reserve_io[(i << 1) + 1];
1563                 if (port >= rport && port < rport + rsize)
1564                         return 1;
1565                 if (port + size > rport && port + size < (rport + rsize) - 1)
1566                         return 1;
1567         }
1568 
1569         isapnp_for_each_dev(dev) {
1570                 if (dev->active) {
1571                         for (tmp = 0; tmp < 8; tmp++) {
1572                                 if (dev->resource[tmp].flags) {
1573                                         rport = dev->resource[tmp].start;
1574                                         rsize = (dev->resource[tmp].end - rport) + 1;
1575                                         if (port >= rport && port < rport + rsize)
1576                                                 return 1;
1577                                         if (port + size > rport && port + size < (rport + rsize) - 1)
1578                                                 return 1;
1579                                 }
1580                         }
1581                 }
1582         }
1583         for (i = 0; i < 8; i++) {
1584                 unsigned int flags;
1585                 if (i == idx)
1586                         continue;
1587                 flags = cfg->request->resource[i].flags;
1588                 if (!flags)
1589                         continue;
1590                 tmp = cfg->request->resource[i].start;
1591                 if (flags & IORESOURCE_AUTO) {          /* auto */
1592                         xport = cfg->port[i];
1593                         if (!xport)
1594                                 return 1;
1595                         if (cfg->result.resource[i].flags & IORESOURCE_AUTO)
1596                                 continue;
1597                         tmp = cfg->result.resource[i].start;
1598                         if (tmp + xport->size >= port && tmp <= port + xport->size)
1599                                 return 1;
1600                         continue;
1601                 }
1602                 if (port == tmp)
1603                         return 1;
1604                 xport = isapnp_find_port(cfg->request, i);
1605                 if (!xport)
1606                         return 1;
1607                 if (tmp + xport->size >= port && tmp <= port + xport->size)
1608                         return 1;
1609         }
1610         return 0;
1611 }
1612 
1613 static int isapnp_valid_port(struct isapnp_cfgtmp *cfg, int idx)
1614 {
1615         int err;
1616         unsigned long *value1, *value2;
1617         struct isapnp_port *port;
1618 
1619         if (!cfg || idx < 0 || idx > 7)
1620                 return -EINVAL;
1621         if (!(cfg->result.resource[idx].flags & IORESOURCE_AUTO)) /* don't touch */
1622                 return 0;
1623       __again:
1624         port = cfg->port[idx];
1625         if (!port)
1626                 return -EINVAL;
1627         value1 = &cfg->result.resource[idx].start;
1628         value2 = &cfg->result.resource[idx].end;
1629         if (cfg->result.resource[idx].flags & IORESOURCE_AUTO) {
1630                 cfg->result.resource[idx].flags &= ~IORESOURCE_AUTO;
1631                 *value1 = port->min;
1632                 *value2 = port->min + port->size - 1;
1633                 if (!isapnp_check_port(cfg, *value1, port->size, idx))
1634                         return 0;
1635         }
1636         do {
1637                 *value1 += port->align;
1638                 *value2 = *value1 + port->size - 1;
1639                 if (*value1 > port->max || !port->align) {
1640                         if (port->res && port->res->alt) {
1641                                 if ((err = isapnp_alternative_switch(cfg, port->res, port->res->alt))<0)
1642                                         return err;
1643                                 goto __again;
1644                         }
1645                         return -ENOENT;
1646                 }
1647         } while (isapnp_check_port(cfg, *value1, port->size, idx));
1648         return 0;
1649 }
1650 
1651 static void isapnp_test_handler(int irq, void *dev_id, struct pt_regs *regs)
1652 {
1653 }
1654 
1655 static int isapnp_check_interrupt(struct isapnp_cfgtmp *cfg, int irq, int idx)
1656 {
1657         int i;
1658         struct pci_dev *dev;
1659 
1660         if (irq < 0 || irq > 15)
1661                 return 1;
1662         for (i = 0; i < 16; i++) {
1663                 if (isapnp_reserve_irq[i] == irq)
1664                         return 1;
1665         }
1666         isapnp_for_each_dev(dev) {
1667                 if (dev->active) {
1668                         if (dev->irq_resource[0].start == irq ||
1669                             dev->irq_resource[1].start == irq)
1670                                 return 1;
1671                 }
1672         }
1673 #ifdef CONFIG_PCI
1674         if (!isapnp_skip_pci_scan) {
1675                 pci_for_each_dev(dev) {
1676                         if (dev->irq == irq)
1677                                 return 1;
1678                 }
1679         }
1680 #endif
1681         if (request_irq(irq, isapnp_test_handler, SA_INTERRUPT, "isapnp", NULL))
1682                 return 1;
1683         free_irq(irq, NULL);
1684         for (i = 0; i < DEVICE_COUNT_IRQ; i++) {
1685                 if (i == idx)
1686                         continue;
1687                 if (!cfg->result.irq_resource[i].flags)
1688                         continue;
1689                 if (cfg->result.irq_resource[i].flags & IORESOURCE_AUTO)
1690                         continue;
1691                 if (cfg->result.irq_resource[i].start == irq)
1692                         return 1;
1693         }
1694         return 0;
1695 }
1696 
1697 static int isapnp_valid_irq(struct isapnp_cfgtmp *cfg, int idx)
1698 {
1699         /* IRQ priority: this table is good for i386 */
1700         static unsigned short xtab[16] = {
1701                 5, 10, 11, 12, 9, 14, 15, 7, 3, 4, 13, 0, 1, 6, 8, 2
1702         };
1703         int err, i;
1704         unsigned long *value1, *value2;
1705         struct isapnp_irq *irq;
1706 
1707         if (!cfg || idx < 0 || idx > 1)
1708                 return -EINVAL;
1709         if (!(cfg->result.irq_resource[idx].flags & IORESOURCE_AUTO))
1710                 return 0;
1711       __again:
1712         irq = cfg->irq[idx];
1713         if (!irq)
1714                 return -EINVAL;
1715         value1 = &cfg->result.irq_resource[idx].start;
1716         value2 = &cfg->result.irq_resource[idx].end;
1717         if (cfg->result.irq_resource[idx].flags & IORESOURCE_AUTO) {
1718                 for (i = 0; i < 16 && !(irq->map & (1<<xtab[i])); i++);
1719                 if (i >= 16)
1720                         return -ENOENT;
1721                 cfg->result.irq_resource[idx].flags &= ~IORESOURCE_AUTO;
1722                 if (!isapnp_check_interrupt(cfg, *value1 = *value2 = xtab[i], idx))
1723                         return 0;
1724         }
1725         do {
1726                 for (i = 0; i < 16 && xtab[i] != *value1; i++);
1727                 for (i++; i < 16 && !(irq->map & (1<<xtab[i])); i++);
1728                 if (i >= 16) {
1729                         if (irq->res && irq->res->alt) {
1730                                 if ((err = isapnp_alternative_switch(cfg, irq->res, irq->res->alt))<0)
1731                                         return err;
1732                                 goto __again;
1733                         }
1734                         return -ENOENT;
1735                 } else {
1736                         *value1 = *value2 = xtab[i];
1737                 }
1738         } while (isapnp_check_interrupt(cfg, *value1, idx));
1739         return 0;
1740 }
1741 
1742 static int isapnp_check_dma(struct isapnp_cfgtmp *cfg, int dma, int idx)
1743 {
1744         int i;
1745         struct pci_dev *dev;
1746 
1747         /* Some machines allow DMA 0, but others don't. In fact on some 
1748            boxes DMA 0 is the memory refresh. Play safe */
1749            
1750         if (dma < 1 || dma == 4 || dma > 7)
1751                 return 1;
1752         for (i = 0; i < 8; i++) {
1753                 if (isapnp_reserve_dma[i] == dma)
1754                         return 1;
1755         }
1756         isapnp_for_each_dev(dev) {
1757                 if (dev->active) {
1758                         if (dev->dma_resource[0].start == dma || dev->dma_resource[1].start == dma)
1759                                 return 1;
1760                 }
1761         }
1762         if (request_dma(dma, "isapnp"))
1763                 return 1;
1764         free_dma(dma);
1765         for (i = 0; i < 2; i++) {
1766                 if (i == idx)
1767                         continue;
1768                 if (!cfg->result.dma_resource[i].flags ||
1769                     (cfg->result.dma_resource[i].flags & IORESOURCE_AUTO))
1770                         continue;
1771                 if (cfg->result.dma_resource[i].start == dma)
1772                         return 1;
1773         }
1774         return 0;
1775 }
1776 
1777 static int isapnp_valid_dma(struct isapnp_cfgtmp *cfg, int idx)
1778 {
1779         int err, i;
1780         unsigned long *value1, *value2;
1781         struct isapnp_dma *dma;
1782 
1783         if (!cfg || idx < 0 || idx > 1)
1784                 return -EINVAL;
1785         if (!(cfg->result.dma_resource[idx].flags & IORESOURCE_AUTO))   /* don't touch */
1786                 return 0;
1787       __again:
1788         dma = cfg->dma[idx];
1789         if (!dma)
1790                 return -EINVAL;
1791         value1 = &cfg->result.dma_resource[idx].start;
1792         value2 = &cfg->result.dma_resource[idx].end;
1793         if (cfg->result.dma_resource[idx].flags & IORESOURCE_AUTO) {
1794                 for (i = 0; i < 8 && !(dma->map & (1<<i)); i++);
1795                 if (i >= 8)
1796                         return -ENOENT;
1797                 cfg->result.dma_resource[idx].flags &= ~IORESOURCE_AUTO;
1798                 if (!isapnp_check_dma(cfg, *value1 = *value2 = i, idx))
1799                         return 0;
1800         }
1801         do {
1802                 for (i = *value1 + 1; i < 8 && !(dma->map & (1<<i)); i++);
1803                 if (i >= 8) {
1804                         if (dma->res && dma->res->alt) {
1805                                 if ((err = isapnp_alternative_switch(cfg, dma->res, dma->res->alt))<0)
1806                                         return err;
1807                                 goto __again;
1808                         }
1809                         return -ENOENT;
1810                 } else {
1811                         *value1 = *value2 = i;
1812                 }
1813         } while (isapnp_check_dma(cfg, *value1, idx));
1814         return 0;
1815 }
1816 
1817 static int isapnp_check_mem(struct isapnp_cfgtmp *cfg, unsigned int addr, unsigned int size, int idx)
1818 {
1819         int i, tmp;
1820         unsigned int raddr, rsize;
1821         struct isapnp_mem *xmem;
1822         struct pci_dev *dev;
1823 
1824         for (i = 0; i < 8; i++) {
1825                 raddr = (unsigned int)isapnp_reserve_mem[i << 1];
1826                 rsize = (unsigned int)isapnp_reserve_mem[(i << 1) + 1];
1827                 if (addr >= raddr && addr < raddr + rsize)
1828                         return 1;
1829                 if (addr + size > raddr && addr + size < (raddr + rsize) - 1)
1830                         return 1;
1831                 if (__check_region(&iomem_resource, addr, size))
1832                         return 1;
1833         }
1834         isapnp_for_each_dev(dev) {
1835                 if (dev->active) {
1836                         for (tmp = 0; tmp < 4; tmp++) {
1837                                 if (dev->resource[tmp].flags) {
1838                                         raddr = dev->resource[tmp + 8].start;
1839                                         rsize = (dev->resource[tmp + 8].end - raddr) + 1;
1840                                         if (addr >= raddr && addr < raddr + rsize)
1841                                                 return 1;
1842                                         if (addr + size > raddr && addr + size < (raddr + rsize) - 1)
1843                                                 return 1;
1844                                 }
1845                         }
1846                 }
1847         }
1848         for (i = 0; i < 4; i++) {
1849                 unsigned int flags = cfg->request->resource[i + 8].flags;
1850                 if (i == idx)
1851                         continue;
1852                 if (!flags)
1853                         continue;
1854                 tmp = cfg->result.resource[i + 8].start;
1855                 if (flags & IORESOURCE_AUTO) {          /* auto */
1856                         xmem = cfg->mem[i];
1857                         if (!xmem)
1858                                 return 1;
1859                         if (cfg->result.resource[i + 8].flags & IORESOURCE_AUTO)
1860                                 continue;
1861                         if (tmp + xmem->size >= addr && tmp <= addr + xmem->size)
1862                                 return 1;
1863                         continue;
1864                 }
1865                 if (addr == tmp)
1866                         return 1;
1867                 xmem = isapnp_find_mem(cfg->request, i);
1868                 if (!xmem)
1869                         return 1;
1870                 if (tmp + xmem->size >= addr && tmp <= addr + xmem->size)
1871                         return 1;
1872         }
1873         return 0;
1874 }
1875 
1876 static int isapnp_valid_mem(struct isapnp_cfgtmp *cfg, int idx)
1877 {
1878         int err;
1879         unsigned long *value1, *value2;
1880         struct isapnp_mem *mem;
1881 
1882         if (!cfg || idx < 0 || idx > 3)
1883                 return -EINVAL;
1884         if (!(cfg->result.resource[idx + 8].flags & IORESOURCE_AUTO)) /* don't touch */
1885                 return 0;
1886       __again:
1887         mem = cfg->mem[idx];
1888         if (!mem)
1889                 return -EINVAL;
1890         value1 = &cfg->result.resource[idx + 8].start;
1891         value2 = &cfg->result.resource[idx + 8].end;
1892         if (cfg->result.resource[idx + 8].flags & IORESOURCE_AUTO) {
1893                 cfg->result.resource[idx + 8].flags &= ~IORESOURCE_AUTO;
1894                 *value1 = mem->min;
1895                 *value2 = mem->min + mem->size - 1;
1896                 if (!isapnp_check_mem(cfg, *value1, mem->size, idx))
1897                         return 0;
1898         }
1899         do {
1900                 *value1 += mem->align;
1901                 *value2 = *value1 + mem->size - 1;
1902                 if (*value1 > mem->max || !mem->align) {
1903                         if (mem->res && mem->res->alt) {
1904                                 if ((err = isapnp_alternative_switch(cfg, mem->res, mem->res->alt))<0)
1905                                         return err;
1906                                 goto __again;
1907                         }
1908                         return -ENOENT;
1909                 }
1910         } while (isapnp_check_mem(cfg, *value1, mem->size, idx));
1911         return 0;
1912 }
1913 
1914 static int isapnp_check_valid(struct isapnp_cfgtmp *cfg)
1915 {
1916         int tmp;
1917         
1918         for (tmp = 0; tmp < 8; tmp++)
1919                 if (cfg->result.resource[tmp].flags & IORESOURCE_AUTO)
1920                         return -EAGAIN;
1921         for (tmp = 0; tmp < 2; tmp++)
1922                 if (cfg->result.irq_resource[tmp].flags & IORESOURCE_AUTO)
1923                         return -EAGAIN;
1924         for (tmp = 0; tmp < 2; tmp++)
1925                 if (cfg->result.dma_resource[tmp].flags & IORESOURCE_AUTO)
1926                         return -EAGAIN;
1927         for (tmp = 0; tmp < 4; tmp++)
1928                 if (cfg->result.resource[tmp + 8].flags & IORESOURCE_AUTO)
1929                         return -EAGAIN;
1930         return 0;
1931 }
1932 
1933 static int isapnp_config_activate(struct pci_dev *dev)
1934 {
1935         struct isapnp_cfgtmp cfg;
1936         int tmp, fauto, err;
1937         
1938         if (!dev)
1939                 return -EINVAL;
1940         if (dev->active)
1941                 return -EBUSY;
1942         memset(&cfg, 0, sizeof(cfg));
1943         cfg.request = dev;
1944         memcpy(&cfg.result, dev, sizeof(struct pci_dev));
1945         /* check if all values are set, otherwise try auto-configuration */
1946         for (tmp = fauto = 0; !fauto && tmp < 8; tmp++) {
1947                 if (dev->resource[tmp].flags & IORESOURCE_AUTO)
1948                         fauto++;
1949         }
1950         for (tmp = 0; !fauto && tmp < 2; tmp++) {
1951                 if (dev->irq_resource[tmp].flags & IORESOURCE_AUTO)
1952                         fauto++;
1953         }
1954         for (tmp = 0; !fauto && tmp < 2; tmp++) {
1955                 if (dev->dma_resource[tmp].flags & IORESOURCE_AUTO)
1956                         fauto++;
1957         }
1958         for (tmp = 0; !fauto && tmp < 4; tmp++) {
1959                 if (dev->resource[tmp + 8].flags & IORESOURCE_AUTO)
1960                         fauto++;
1961         }
1962         if (!fauto)
1963                 goto __skip_auto;
1964         /* set variables to initial values */
1965         if ((err = isapnp_alternative_switch(&cfg, NULL, NULL))<0)
1966                 return err;
1967         /* find first valid configuration */
1968         fauto = 0;
1969         do {
1970                 for (tmp = 0; tmp < 8 && cfg.result.resource[tmp].flags; tmp++)
1971                         if ((err = isapnp_valid_port(&cfg, tmp))<0)
1972                                 return err;
1973                 for (tmp = 0; tmp < 2 && cfg.result.irq_resource[tmp].flags; tmp++)
1974                         if ((err = isapnp_valid_irq(&cfg, tmp))<0)
1975                                 return err;
1976                 for (tmp = 0; tmp < 2 && cfg.result.dma_resource[tmp].flags; tmp++)
1977                         if ((err = isapnp_valid_dma(&cfg, tmp))<0)
1978                                 return err;
1979                 for (tmp = 0; tmp < 4 && cfg.result.resource[tmp + 8].flags; tmp++)
1980                         if ((err = isapnp_valid_mem(&cfg, tmp))<0)
1981                                 return err;
1982         } while (isapnp_check_valid(&cfg)<0 && fauto++ < 20);
1983         if (fauto >= 20)
1984                 return -EAGAIN;
1985       __skip_auto:
1986         /* we have valid configuration, try configure hardware */
1987         isapnp_cfg_begin(dev->bus->number, dev->devfn);
1988         dev->active = 1;
1989         dev->irq_resource[0] = cfg.result.irq_resource[0];
1990         dev->irq_resource[1] = cfg.result.irq_resource[1];
1991         dev->dma_resource[0] = cfg.result.dma_resource[0];
1992         dev->dma_resource[1] = cfg.result.dma_resource[1];
1993         for (tmp = 0; tmp < 12; tmp++) {
1994                 dev->resource[tmp] = cfg.result.resource[tmp];
1995         }       
1996         for (tmp = 0; tmp < 8 && dev->resource[tmp].flags; tmp++)
1997                 isapnp_write_word(ISAPNP_CFG_PORT+(tmp<<1), dev->resource[tmp].start);
1998         for (tmp = 0; tmp < 2 && dev->irq_resource[tmp].flags; tmp++) {
1999                 int irq = dev->irq_resource[tmp].start;
2000                 if (irq == 2)
2001                         irq = 9;
2002                 isapnp_write_byte(ISAPNP_CFG_IRQ+(tmp<<1), irq);
2003         }
2004         for (tmp = 0; tmp < 2 && dev->dma_resource[tmp].flags; tmp++)
2005                 isapnp_write_byte(ISAPNP_CFG_DMA+tmp, dev->dma_resource[tmp].start);
2006         for (tmp = 0; tmp < 4 && dev->resource[tmp+8].flags; tmp++)
2007                 isapnp_write_word(ISAPNP_CFG_MEM+(tmp<<2), (dev->resource[tmp + 8].start >> 8) & 0xffff);
2008         isapnp_activate(dev->devfn);
2009         isapnp_cfg_end();
2010         return 0;
2011 }
2012 
2013 static int isapnp_config_deactivate(struct pci_dev *dev)
2014 {
2015         if (!dev || !dev->active)
2016                 return -EINVAL;
2017         isapnp_cfg_begin(dev->bus->number, dev->devfn);
2018         isapnp_deactivate(dev->devfn);
2019         dev->active = 0;
2020         isapnp_cfg_end();
2021         return 0;
2022 }
2023 
2024 void isapnp_resource_change(struct resource *resource,
2025                             unsigned long start,
2026                             unsigned long size)
2027 {
2028         if (resource == NULL)
2029                 return;
2030         resource->flags &= ~IORESOURCE_AUTO;
2031         resource->start = start;
2032         resource->end = start + size - 1;
2033 }
2034 
2035 /*
2036  *  Inititialization.
2037  */
2038 
2039 #ifdef MODULE
2040 
2041 static void isapnp_free_port(struct isapnp_port *port)
2042 {
2043         struct isapnp_port *next;
2044 
2045         while (port) {
2046                 next = port->next;
2047                 kfree(port);
2048                 port = next;
2049         }
2050 }
2051 
2052 static void isapnp_free_irq(struct isapnp_irq *irq)
2053 {
2054         struct isapnp_irq *next;
2055 
2056         while (irq) {
2057                 next = irq->next;
2058                 kfree(irq);
2059                 irq = next;
2060         }
2061 }
2062 
2063 static void isapnp_free_dma(struct isapnp_dma *dma)
2064 {
2065         struct isapnp_dma *next;
2066 
2067         while (dma) {
2068                 next = dma->next;
2069                 kfree(dma);
2070                 dma = next;
2071         }
2072 }
2073 
2074 static void isapnp_free_mem(struct isapnp_mem *mem)
2075 {
2076         struct isapnp_mem *next;
2077 
2078         while (mem) {
2079                 next = mem->next;
2080                 kfree(mem);
2081                 mem = next;
2082         }
2083 }
2084 
2085 static void isapnp_free_mem32(struct isapnp_mem32 *mem32)
2086 {
2087         struct isapnp_mem32 *next;
2088 
2089         while (mem32) {
2090                 next = mem32->next;
2091                 kfree(mem32);
2092                 mem32 = next;
2093         }
2094 }
2095 
2096 static void isapnp_free_resources(struct isapnp_resources *resources, int alt)
2097 {
2098         struct isapnp_resources *next;
2099 
2100         while (resources) {
2101                 next = alt ? resources->alt : resources->next;
2102                 isapnp_free_port(resources->port);
2103                 isapnp_free_irq(resources->irq);
2104                 isapnp_free_dma(resources->dma);
2105                 isapnp_free_mem(resources->mem);
2106                 isapnp_free_mem32(resources->mem32);
2107                 if (!alt && resources->alt)
2108                         isapnp_free_resources(resources->alt, 1);
2109                 kfree(resources);
2110                 resources = next;
2111         }
2112 }
2113 
2114 static void isapnp_free_card(struct pci_bus *card)
2115 {
2116         while (!list_empty(&card->devices)) {
2117                 struct list_head *list = card->devices.next;
2118                 struct pci_dev *dev = pci_dev_b(list);
2119                 list_del(list);
2120                 isapnp_free_resources((struct isapnp_resources *)dev->sysdata, 0);
2121                 kfree(dev);
2122         }
2123         kfree(card);
2124 }
2125 
2126 #endif /* MODULE */
2127 
2128 static void isapnp_free_all_resources(void)
2129 {
2130 #ifdef ISAPNP_REGION_OK
2131         if (pidxr_res)
2132                 release_resource(pidxr_res);
2133 #endif
2134         if (pnpwrp_res)
2135                 release_resource(pnpwrp_res);
2136         if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff && isapnp_rdp_res)
2137                 release_resource(isapnp_rdp_res);
2138 #ifdef MODULE
2139 #ifdef CONFIG_PROC_FS
2140         isapnp_proc_done();
2141 #endif
2142         while (!list_empty(&isapnp_cards)) {
2143                 struct list_head *list = isapnp_cards.next;
2144                 list_del(list);
2145                 isapnp_free_card(pci_bus_b(list));
2146         }
2147 #endif
2148 }
2149 
2150 EXPORT_SYMBOL(isapnp_cards);
2151 EXPORT_SYMBOL(isapnp_devices);
2152 EXPORT_SYMBOL(isapnp_present);
2153 EXPORT_SYMBOL(isapnp_cfg_begin);
2154 EXPORT_SYMBOL(isapnp_cfg_end);
2155 EXPORT_SYMBOL(isapnp_read_byte);
2156 EXPORT_SYMBOL(isapnp_read_word);
2157 EXPORT_SYMBOL(isapnp_read_dword);
2158 EXPORT_SYMBOL(isapnp_write_byte);
2159 EXPORT_SYMBOL(isapnp_write_word);
2160 EXPORT_SYMBOL(isapnp_write_dword);
2161 EXPORT_SYMBOL(isapnp_wake);
2162 EXPORT_SYMBOL(isapnp_device);
2163 EXPORT_SYMBOL(isapnp_activate);
2164 EXPORT_SYMBOL(isapnp_deactivate);
2165 EXPORT_SYMBOL(isapnp_find_card);
2166 EXPORT_SYMBOL(isapnp_find_dev);
2167 EXPORT_SYMBOL(isapnp_probe_cards);
2168 EXPORT_SYMBOL(isapnp_probe_devs);
2169 EXPORT_SYMBOL(isapnp_activate_dev);
2170 EXPORT_SYMBOL(isapnp_resource_change);
2171 
2172 int __init isapnp_init(void)
2173 {
2174         int cards;
2175         struct pci_bus *card;
2176 
2177         if (isapnp_disable) {
2178                 isapnp_detected = 0;
2179                 printk("isapnp: ISA Plug & Play support disabled\n");
2180                 return 0;
2181         }
2182 #ifdef ISAPNP_REGION_OK
2183         pidxr_res=request_region(_PIDXR, 1, "isapnp index");
2184         if(!pidxr_res) {
2185                 printk("isapnp: Index Register 0x%x already used\n", _PIDXR);
2186                 return -EBUSY;
2187         }
2188 #endif
2189         pnpwrp_res=request_region(_PNPWRP, 1, "isapnp write");
2190         if(!pnpwrp_res) {
2191                 printk("isapnp: Write Data Register 0x%x already used\n", _PNPWRP);
2192                 return -EBUSY;
2193         }
2194         
2195         /*
2196          *      Print a message. The existing ISAPnP code is hanging machines
2197          *      so let the user know where.
2198          */
2199          
2200         printk("isapnp: Scanning for Pnp cards...\n");
2201         if (isapnp_rdp >= 0x203 && isapnp_rdp <= 0x3ff) {
2202                 isapnp_rdp |= 3;
2203                 isapnp_rdp_res=request_region(isapnp_rdp, 1, "isapnp read");
2204                 if(!isapnp_rdp_res) {
2205                         printk("isapnp: Read Data Register 0x%x already used\n", isapnp_rdp);
2206                         return -EBUSY;
2207                 }
2208                 isapnp_set_rdp();
2209         }
2210         isapnp_detected = 1;
2211         if (isapnp_rdp < 0x203 || isapnp_rdp > 0x3ff) {
2212                 cards = isapnp_isolate();
2213                 if (cards < 0 || 
2214                     (isapnp_rdp < 0x203 || isapnp_rdp > 0x3ff)) {
2215                         isapnp_free_all_resources();
2216                         isapnp_detected = 0;
2217                         printk("isapnp: No Plug & Play device found\n");
2218                         return 0;
2219                 }
2220                 isapnp_rdp_res=request_region(isapnp_rdp, 1, "isapnp read");
2221         }
2222         isapnp_build_device_list();
2223         cards = 0;
2224 
2225         isapnp_for_each_card(card) {
2226                 cards++;
2227                 if (isapnp_verbose) {
2228                         struct list_head *devlist;
2229                         printk( "isapnp: Card '%s'\n", card->name[0]?card->name:"Unknown");
2230                         if (isapnp_verbose < 2)
2231                                 continue;
2232                         for (devlist = card->devices.next; devlist != &card->devices; devlist = devlist->next) {
2233                                 struct pci_dev *dev = pci_dev_b(devlist);
2234                                 printk("isapnp:   Device '%s'\n", dev->name[0]?card->name:"Unknown");
2235                         }
2236                 }
2237         }
2238         if (cards) {
2239                 printk("isapnp: %i Plug & Play card%s detected total\n", cards, cards>1?"s":"");
2240         } else {
2241                 printk("isapnp: No Plug & Play card found\n");
2242         }
2243 #ifdef CONFIG_PROC_FS
2244         isapnp_proc_init();
2245 #endif
2246         return 0;
2247 }
2248 
2249 #ifdef MODULE
2250 
2251 int init_module(void)
2252 {
2253         return isapnp_init();
2254 }
2255 
2256 void cleanup_module(void)
2257 {
2258         if (isapnp_detected)
2259                 isapnp_free_all_resources();
2260 }
2261 
2262 #endif
2263 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.