]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/isa/pnp.c
This commit was generated by cvs2svn to compensate for changes in r59191,
[FreeBSD/FreeBSD.git] / sys / isa / pnp.c
1 /*
2  * Copyright (c) 1996, Sujal M. Patel
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  *      $FreeBSD$
27  *      from: pnp.c,v 1.11 1999/05/06 22:11:19 peter Exp
28  */
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/module.h>
34 #include <sys/bus.h>
35 #include <sys/malloc.h>
36 #include <isa/isavar.h>
37 #include <isa/pnpreg.h>
38 #include <isa/pnpvar.h>
39 #include <machine/clock.h>
40
41 typedef struct _pnp_id {
42         u_int32_t vendor_id;
43         u_int32_t serial;
44         u_char checksum;
45 } pnp_id;
46
47 struct pnp_set_config_arg {
48         int     csn;            /* Card number to configure */
49         int     ldn;            /* Logical device on card */
50 };
51
52 struct pnp_quirk {
53         u_int32_t vendor_id;    /* Vendor of the card */
54         u_int32_t logical_id;   /* ID of the device with quirk */
55         int     type;
56 #define PNP_QUIRK_WRITE_REG     1 /* Need to write a pnp register  */
57         int     arg1;
58         int     arg2;
59 };
60
61 struct pnp_quirk pnp_quirks[] = {
62         /*
63          * The Gravis UltraSound needs register 0xf2 to be set to 0xff
64          * to enable power.
65          * XXX need to know the logical device id.
66          */
67         { 0x0100561e /* GRV0001 */,     0,
68           PNP_QUIRK_WRITE_REG,  0xf2,    0xff },
69
70         { 0 }
71 };
72
73 #if 0
74 /*
75  * these entries are initialized using the autoconfig menu
76  * The struct is invalid (and must be initialized) if the first
77  * CSN is zero. The init code fills invalid entries with CSN 255
78  * which is not a supported value.
79  */
80
81 struct pnp_cinfo pnp_ldn_overrides[MAX_PNP_LDN] = {
82     { 0 }
83 };
84 #endif
85
86 /* The READ_DATA port that we are using currently */
87 static int pnp_rd_port;
88
89 static void   pnp_send_initiation_key(void);
90 static int    pnp_get_serial(pnp_id *p);
91 static int    pnp_isolation_protocol(device_t parent);
92
93 char *
94 pnp_eisaformat(u_int32_t id)
95 {
96         u_int8_t *data = (u_int8_t *) &id;
97         static char idbuf[8];
98         const char  hextoascii[] = "0123456789abcdef";
99
100         idbuf[0] = '@' + ((data[0] & 0x7c) >> 2);
101         idbuf[1] = '@' + (((data[0] & 0x3) << 3) + ((data[1] & 0xe0) >> 5));
102         idbuf[2] = '@' + (data[1] & 0x1f);
103         idbuf[3] = hextoascii[(data[2] >> 4)];
104         idbuf[4] = hextoascii[(data[2] & 0xf)];
105         idbuf[5] = hextoascii[(data[3] >> 4)];
106         idbuf[6] = hextoascii[(data[3] & 0xf)];
107         idbuf[7] = 0;
108         return(idbuf);
109 }
110
111 static void
112 pnp_write(int d, u_char r)
113 {
114         outb (_PNP_ADDRESS, d);
115         outb (_PNP_WRITE_DATA, r);
116 }
117
118 #if 0
119
120 static u_char
121 pnp_read(int d)
122 {
123         outb (_PNP_ADDRESS, d);
124         return (inb(3 | (pnp_rd_port <<2)));
125 }
126
127 #endif
128
129 /*
130  * Send Initiation LFSR as described in "Plug and Play ISA Specification",
131  * Intel May 94.
132  */
133 static void
134 pnp_send_initiation_key()
135 {
136         int cur, i;
137
138         /* Reset the LSFR */
139         outb(_PNP_ADDRESS, 0);
140         outb(_PNP_ADDRESS, 0); /* yes, we do need it twice! */
141
142         cur = 0x6a;
143         outb(_PNP_ADDRESS, cur);
144
145         for (i = 1; i < 32; i++) {
146                 cur = (cur >> 1) | (((cur ^ (cur >> 1)) << 7) & 0xff);
147                 outb(_PNP_ADDRESS, cur);
148         }
149 }
150
151
152 /*
153  * Get the device's serial number.  Returns 1 if the serial is valid.
154  */
155 static int
156 pnp_get_serial(pnp_id *p)
157 {
158         int i, bit, valid = 0, sum = 0x6a;
159         u_char *data = (u_char *)p;
160
161         bzero(data, sizeof(char) * 9);
162         outb(_PNP_ADDRESS, PNP_SERIAL_ISOLATION);
163         for (i = 0; i < 72; i++) {
164                 bit = inb((pnp_rd_port << 2) | 0x3) == 0x55;
165                 DELAY(250);     /* Delay 250 usec */
166
167                 /* Can't Short Circuit the next evaluation, so 'and' is last */
168                 bit = (inb((pnp_rd_port << 2) | 0x3) == 0xaa) && bit;
169                 DELAY(250);     /* Delay 250 usec */
170
171                 valid = valid || bit;
172
173                 if (i < 64)
174                         sum = (sum >> 1) |
175                                 (((sum ^ (sum >> 1) ^ bit) << 7) & 0xff);
176
177                 data[i / 8] = (data[i / 8] >> 1) | (bit ? 0x80 : 0);
178         }
179
180         valid = valid && (data[8] == sum);
181
182         return valid;
183 }
184
185 /*
186  * Fill's the buffer with resource info from the device.
187  * Returns the number of characters read.
188  */
189 static int
190 pnp_get_resource_info(u_char *buffer, int len)
191 {
192         int i, j, count;
193         u_char temp;
194
195         count = 0;
196         for (i = 0; i < len; i++) {
197                 outb(_PNP_ADDRESS, PNP_STATUS);
198                 for (j = 0; j < 100; j++) {
199                         if ((inb((pnp_rd_port << 2) | 0x3)) & 0x1)
200                                 break;
201                         DELAY(1);
202                 }
203                 if (j == 100) {
204                         printf("PnP device failed to report resource data\n");
205                         return count;
206                 }
207                 outb(_PNP_ADDRESS, PNP_RESOURCE_DATA);
208                 temp = inb((pnp_rd_port << 2) | 0x3);
209                 if (buffer != NULL)
210                         buffer[i] = temp;
211                 count++;
212         }
213         return count;
214 }
215
216 #if 0
217 /*
218  * write_pnp_parms initializes a logical device with the parms
219  * in d, and then activates the board if the last parameter is 1.
220  */
221
222 static int
223 write_pnp_parms(struct pnp_cinfo *d, pnp_id *p, int ldn)
224 {
225     int i, empty = -1 ;
226
227     pnp_write (SET_LDN, ldn );
228     i = pnp_read(SET_LDN) ;
229     if (i != ldn) {
230         printf("Warning: LDN %d does not exist\n", ldn);
231     }
232     for (i = 0; i < 8; i++) {
233         pnp_write(IO_CONFIG_BASE + i * 2, d->ic_port[i] >> 8 );
234         pnp_write(IO_CONFIG_BASE + i * 2 + 1, d->ic_port[i] & 0xff );
235     }
236     for (i = 0; i < 4; i++) {
237         pnp_write(MEM_CONFIG + i*8, (d->ic_mem[i].base >> 16) & 0xff );
238         pnp_write(MEM_CONFIG + i*8+1, (d->ic_mem[i].base >> 8) & 0xff );
239         pnp_write(MEM_CONFIG + i*8+2, d->ic_mem[i].control & 0xff );
240         pnp_write(MEM_CONFIG + i*8+3, (d->ic_mem[i].range >> 16) & 0xff );
241         pnp_write(MEM_CONFIG + i*8+4, (d->ic_mem[i].range >> 8) & 0xff );
242     }
243     for (i = 0; i < 2; i++) {
244         pnp_write(IRQ_CONFIG + i*2    , d->irq[i] );
245         pnp_write(IRQ_CONFIG + i*2 + 1, d->irq_type[i] );
246         pnp_write(DRQ_CONFIG + i, d->drq[i] );
247     }
248     /*
249      * store parameters read into the current kernel
250      * so manual editing next time is easier
251      */
252     for (i = 0 ; i < MAX_PNP_LDN; i++) {
253         if (pnp_ldn_overrides[i].csn == d->csn &&
254                 pnp_ldn_overrides[i].ldn == ldn) {
255             d->flags = pnp_ldn_overrides[i].flags ;
256             pnp_ldn_overrides[i] = *d ;
257             break ;
258         } else if (pnp_ldn_overrides[i].csn < 1 ||
259                 pnp_ldn_overrides[i].csn == 255)
260             empty = i ;
261     }
262     if (i== MAX_PNP_LDN && empty != -1)
263         pnp_ldn_overrides[empty] = *d;
264
265     /*
266      * Here should really perform the range check, and
267      * return a failure if not successful.
268      */
269     pnp_write (IO_RANGE_CHECK, 0);
270     DELAY(1000); /* XXX is it really necessary ? */
271     pnp_write (ACTIVATE, d->enable ? 1 : 0);
272     DELAY(1000); /* XXX is it really necessary ? */
273     return 1 ;
274 }
275 #endif
276
277 /*
278  * This function is called after the bus has assigned resource
279  * locations for a logical device.
280  */
281 static void
282 pnp_set_config(void *arg, struct isa_config *config, int enable)
283 {
284         int csn = ((struct pnp_set_config_arg *) arg)->csn;
285         int ldn = ((struct pnp_set_config_arg *) arg)->ldn;
286         int i;
287
288         /*
289          * First put all cards into Sleep state with the initiation
290          * key, then put our card into Config state.
291          */
292         pnp_send_initiation_key();
293         pnp_write(PNP_WAKE, csn);
294
295         /*
296          * Select our logical device so that we can program it.
297          */
298         pnp_write(PNP_SET_LDN, ldn);
299
300         /*
301          * Now program the resources.
302          */
303         for (i = 0; i < config->ic_nmem; i++) {
304                 u_int32_t start = config->ic_mem[i].ir_start;
305                 u_int32_t size =  config->ic_mem[i].ir_size;
306                 if (start & 0xff)
307                         panic("pnp_set_config: bogus memory assignment");
308                 pnp_write(PNP_MEM_BASE_HIGH(i), (start >> 16) & 0xff);
309                 pnp_write(PNP_MEM_BASE_LOW(i), (start >> 8) & 0xff);
310                 pnp_write(PNP_MEM_RANGE_HIGH(i), (size >> 16) & 0xff);
311                 pnp_write(PNP_MEM_RANGE_LOW(i), (size >> 8) & 0xff);
312         }
313         for (; i < ISA_NMEM; i++) {
314                 pnp_write(PNP_MEM_BASE_HIGH(i), 0);
315                 pnp_write(PNP_MEM_BASE_LOW(i), 0);
316                 pnp_write(PNP_MEM_RANGE_HIGH(i), 0);
317                 pnp_write(PNP_MEM_RANGE_LOW(i), 0);
318         }
319
320         for (i = 0; i < config->ic_nport; i++) {
321                 u_int32_t start = config->ic_port[i].ir_start;
322                 pnp_write(PNP_IO_BASE_HIGH(i), (start >> 8) & 0xff);
323                 pnp_write(PNP_IO_BASE_LOW(i), (start >> 0) & 0xff);
324         }
325         for (; i < ISA_NPORT; i++) {
326                 pnp_write(PNP_IO_BASE_HIGH(i), 0);
327                 pnp_write(PNP_IO_BASE_LOW(i), 0);
328         }
329
330         for (i = 0; i < config->ic_nirq; i++) {
331                 int irq = ffs(config->ic_irqmask[i]) - 1;
332                 pnp_write(PNP_IRQ_LEVEL(i), irq);
333                 pnp_write(PNP_IRQ_TYPE(i), 2); /* XXX */
334         }
335         for (; i < ISA_NIRQ; i++) {
336                 /*
337                  * IRQ 0 is not a valid interrupt selection and
338                  * represents no interrupt selection.
339                  */
340                 pnp_write(PNP_IRQ_LEVEL(i), 0);
341         }               
342
343         for (i = 0; i < config->ic_ndrq; i++) {
344                 int drq = ffs(config->ic_drqmask[i]) - 1;
345                 pnp_write(PNP_DMA_CHANNEL(i), drq);
346         }
347         for (; i < ISA_NDRQ; i++) {
348                 /*
349                  * DMA channel 4, the cascade channel is used to
350                  * indicate no DMA channel is active.
351                  */
352                 pnp_write(PNP_DMA_CHANNEL(i), 4);
353         }               
354
355         pnp_write(PNP_ACTIVATE, enable ? 1 : 0);
356
357         /*
358          * Wake everyone up again, we are finished.
359          */
360         pnp_write(PNP_CONFIG_CONTROL, PNP_CONFIG_CONTROL_WAIT_FOR_KEY);
361 }
362
363 /*
364  * Process quirks for a logical device.. The card must be in Config state.
365  */
366 static void
367 pnp_check_quirks(u_int32_t vendor_id, u_int32_t logical_id, int ldn)
368 {
369         struct pnp_quirk *qp;
370
371         for (qp = &pnp_quirks[0]; qp->vendor_id; qp++) {
372                 if (qp->vendor_id == vendor_id
373                     && (qp->logical_id == 0
374                         || qp->logical_id == logical_id)) {
375                         switch (qp->type) {
376                         case PNP_QUIRK_WRITE_REG:
377                                 pnp_write(PNP_SET_LDN, ldn);
378                                 pnp_write(qp->arg1, qp->arg2);
379                                 break;
380                         }
381                 }
382         }
383 }
384
385 /*
386  * Scan Resource Data for Logical Devices.
387  *
388  * This function exits as soon as it gets an error reading *ANY*
389  * Resource Data or it reaches the end of Resource Data.  In the first
390  * case the return value will be TRUE, FALSE otherwise.
391  */
392 static int
393 pnp_create_devices(device_t parent, pnp_id *p, int csn,
394                    u_char *resources, int len)
395 {
396         u_char tag, *resp, *resinfo, *startres = 0;
397         int large_len, scanning = len, retval = FALSE;
398         u_int32_t logical_id;
399         u_int32_t compat_id;
400         device_t dev = 0;
401         int ldn = 0;
402         struct pnp_set_config_arg *csnldn;
403         char buf[100];
404         char *desc = 0;
405
406         resp = resources;
407         while (scanning > 0) {
408                 tag = *resp++;
409                 scanning--;
410                 if (PNP_RES_TYPE(tag) != 0) {
411                         /* Large resource */
412                         if (scanning < 2) {
413                                 scanning = 0;
414                                 continue;
415                         }
416                         large_len = resp[0] + (resp[1] << 8);
417                         resp += 2;
418
419                         if (scanning < large_len) {
420                                 scanning = 0;
421                                 continue;
422                         }
423                         resinfo = resp;
424                         resp += large_len;
425                         scanning -= large_len;
426
427                         if (PNP_LRES_NUM(tag) == PNP_TAG_ID_ANSI) {
428                                 if (large_len > sizeof(buf) - 1)
429                                         large_len = sizeof(buf) - 1;
430                                 bcopy(resinfo, buf, large_len);
431
432                                 /*
433                                  * Trim trailing spaces.
434                                  */
435                                 while (buf[large_len-1] == ' ')
436                                         large_len--;
437                                 buf[large_len] = '\0';
438                                 desc = buf;
439                                 if (dev)
440                                         device_set_desc_copy(dev, desc);
441                                 continue;
442                         }
443
444                         continue;
445                 }
446                 
447                 /* Small resource */
448                 if (scanning < PNP_SRES_LEN(tag)) {
449                         scanning = 0;
450                         continue;
451                 }
452                 resinfo = resp;
453                 resp += PNP_SRES_LEN(tag);
454                 scanning -= PNP_SRES_LEN(tag);;
455                         
456                 switch (PNP_SRES_NUM(tag)) {
457                 case PNP_TAG_LOGICAL_DEVICE:
458                         /*
459                          * Parse the resources for the previous
460                          * logical device (if any).
461                          */
462                         if (startres) {
463                                 pnp_parse_resources(dev, startres,
464                                                     resinfo - startres - 1);
465                                 dev = 0;
466                                 startres = 0;
467                         }
468
469                         /* 
470                          * A new logical device. Scan for end of
471                          * resources.
472                          */
473                         bcopy(resinfo, &logical_id, 4);
474                         pnp_check_quirks(p->vendor_id, logical_id, ldn);
475                         compat_id = 0;
476                         dev = BUS_ADD_CHILD(parent, ISA_ORDER_PNP, NULL, -1);
477                         if (desc)
478                                 device_set_desc_copy(dev, desc);
479                         isa_set_vendorid(dev, p->vendor_id);
480                         isa_set_serial(dev, p->serial);
481                         isa_set_logicalid(dev, logical_id);
482                         csnldn = malloc(sizeof *csnldn, M_DEVBUF, M_NOWAIT);
483                         if (!csnldn) {
484                                 device_printf(parent,
485                                               "out of memory\n");
486                                 scanning = 0;
487                                 break;
488                         }
489                         csnldn->csn = csn;
490                         csnldn->ldn = ldn;
491                         ISA_SET_CONFIG_CALLBACK(parent, dev,
492                                                 pnp_set_config, csnldn);
493                         ldn++;
494                         startres = resp;
495                         break;
496                     
497                 case PNP_TAG_END:
498                         if (!startres) {
499                                 device_printf(parent,
500                                               "malformed resources\n");
501                                 scanning = 0;
502                                 break;
503                         }
504                         pnp_parse_resources(dev, startres,
505                                             resinfo - startres - 1);
506                         dev = 0;
507                         startres = 0;
508                         scanning = 0;
509                         break;
510
511                 default:
512                         /* Skip this resource */
513                         break;
514                 }
515         }
516
517         return retval;
518 }
519
520 /*
521  * Read 'amount' bytes of resources from the card, allocating memory
522  * as needed. If a buffer is already available, it should be passed in
523  * '*resourcesp' and its length in '*spacep'. The number of resource
524  * bytes already in the buffer should be passed in '*lenp'. The memory
525  * allocated will be returned in '*resourcesp' with its size and the
526  * number of bytes of resources in '*spacep' and '*lenp' respectively.
527  */
528 static int
529 pnp_read_bytes(int amount, u_char **resourcesp, int *spacep, int *lenp)
530 {
531         u_char *resources = *resourcesp;
532         u_char *newres;
533         int space = *spacep;
534         int len = *lenp;
535
536         if (space == 0) {
537                 space = 1024;
538                 resources = malloc(space, M_TEMP, M_NOWAIT);
539                 if (!resources)
540                         return ENOMEM;
541         }
542         
543         if (len + amount > space) {
544                 int extra = 1024;
545                 while (len + amount > space + extra)
546                         extra += 1024;
547                 newres = malloc(space + extra, M_TEMP, M_NOWAIT);
548                 if (!newres)
549                         return ENOMEM;
550                 bcopy(resources, newres, len);
551                 free(resources, M_TEMP);
552                 resources = newres;
553                 space += extra;
554         }
555
556         if (pnp_get_resource_info(resources + len, amount) != amount)
557                 return EINVAL;
558         len += amount;
559
560         *resourcesp = resources;
561         *spacep = space;
562         *lenp = len;
563
564         return 0;
565 }
566
567 /*
568  * Read all resources from the card, allocating memory as needed. If a
569  * buffer is already available, it should be passed in '*resourcesp'
570  * and its length in '*spacep'. The memory allocated will be returned
571  * in '*resourcesp' with its size and the number of bytes of resources
572  * in '*spacep' and '*lenp' respectively.
573  */
574 static int
575 pnp_read_resources(u_char **resourcesp, int *spacep, int *lenp)
576 {
577         u_char *resources = *resourcesp;
578         int space = *spacep;
579         int len = 0;
580         int error, done;
581         u_char tag;
582
583         error = 0;
584         done = 0;
585         while (!done) {
586                 error = pnp_read_bytes(1, &resources, &space, &len);
587                 if (error)
588                         goto out;
589                 tag = resources[len-1];
590                 if (PNP_RES_TYPE(tag) == 0) {
591                         /*
592                          * Small resource, read contents.
593                          */
594                         error = pnp_read_bytes(PNP_SRES_LEN(tag),
595                                                &resources, &space, &len);
596                         if (error)
597                                 goto out;
598                         if (PNP_SRES_NUM(tag) == PNP_TAG_END)
599                                 done = 1;
600                 } else {
601                         /*
602                          * Large resource, read length and contents.
603                          */
604                         error = pnp_read_bytes(2, &resources, &space, &len);
605                         if (error)
606                                 goto out;
607                         error = pnp_read_bytes(resources[len-2]
608                                                + (resources[len-1] << 8),
609                                                &resources, &space, &len);
610                         if (error)
611                                 goto out;
612                 }
613         }
614
615  out:
616         *resourcesp = resources;
617         *spacep = space;
618         *lenp = len;
619         return error;
620 }
621
622 /*
623  * Run the isolation protocol. Use pnp_rd_port as the READ_DATA port
624  * value (caller should try multiple READ_DATA locations before giving
625  * up). Upon exiting, all cards are aware that they should use
626  * pnp_rd_port as the READ_DATA port.
627  *
628  * In the first pass, a csn is assigned to each board and pnp_id's
629  * are saved to an array, pnp_devices. In the second pass, each
630  * card is woken up and the device configuration is called.
631  */
632 static int
633 pnp_isolation_protocol(device_t parent)
634 {
635         int csn;
636         pnp_id id;
637         int found = 0, len;
638         u_char *resources = 0;
639         int space = 0;
640         int error;
641
642         /*
643          * Put all cards into the Sleep state so that we can clear
644          * their CSNs.
645          */
646         pnp_send_initiation_key();
647
648         /*
649          * Clear the CSN for all cards.
650          */
651         pnp_write(PNP_CONFIG_CONTROL, PNP_CONFIG_CONTROL_RESET_CSN);
652
653         /*
654          * Move all cards to the Isolation state.
655          */
656         pnp_write(PNP_WAKE, 0);
657
658         /*
659          * Tell them where the read point is going to be this time.
660          */
661         pnp_write(PNP_SET_RD_DATA, pnp_rd_port);
662
663         for (csn = 1; csn < PNP_MAX_CARDS; csn++) {
664                 /*
665                  * Start the serial isolation protocol.
666                  */
667                 outb(_PNP_ADDRESS, PNP_SERIAL_ISOLATION);
668                 DELAY(1000);    /* Delay 1 msec */
669
670                 if (pnp_get_serial(&id)) {
671                         /*
672                          * We have read the id from a card
673                          * successfully. The card which won the
674                          * isolation protocol will be in Isolation
675                          * mode and all others will be in Sleep.
676                          * Program the CSN of the isolated card
677                          * (taking it to Config state) and read its
678                          * resources, creating devices as we find
679                          * logical devices on the card.
680                          */
681                         pnp_write(PNP_SET_CSN, csn);
682                         error = pnp_read_resources(&resources,
683                                                    &space,
684                                                    &len);
685                         if (error)
686                                 break;
687                         pnp_create_devices(parent, &id, csn,
688                                            resources, len);
689                         found++;
690                 } else
691                         break;
692
693                 /*
694                  * Put this card back to the Sleep state and
695                  * simultaneously move all cards which don't have a
696                  * CSN yet to Isolation state.
697                  */
698                 pnp_write(PNP_WAKE, 0);
699         }
700
701         /*
702          * Unless we have chosen the wrong read port, all cards will
703          * be in Sleep state. Put them back into WaitForKey for
704          * now. Their resources will be programmed later.
705          */
706         pnp_write(PNP_CONFIG_CONTROL, PNP_CONFIG_CONTROL_WAIT_FOR_KEY);
707
708         /*
709          * Cleanup.
710          */
711         if (resources)
712                 free(resources, M_TEMP);
713
714         return found;
715 }
716
717
718 /*
719  * pnp_identify()
720  *
721  * autoconfiguration of pnp devices. This routine just runs the
722  * isolation protocol over several ports, until one is successful.
723  *
724  * may be called more than once ?
725  *
726  */
727
728 static void
729 pnp_identify(driver_t *driver, device_t parent)
730 {
731         int num_pnp_devs;
732
733 #if 0
734         if (pnp_ldn_overrides[0].csn == 0) {
735                 if (bootverbose)
736                         printf("Initializing PnP override table\n");
737                 bzero (pnp_ldn_overrides, sizeof(pnp_ldn_overrides));
738                 pnp_ldn_overrides[0].csn = 255 ;
739         }
740 #endif
741
742         /* Try various READ_DATA ports from 0x203-0x3ff */
743         for (pnp_rd_port = 0x80; (pnp_rd_port < 0xff); pnp_rd_port += 0x10) {
744                 if (bootverbose)
745                         printf("Trying Read_Port at %x\n", (pnp_rd_port << 2) | 0x3);
746
747                 num_pnp_devs = pnp_isolation_protocol(parent);
748                 if (num_pnp_devs)
749                         break;
750         }
751 }
752
753 static device_method_t pnp_methods[] = {
754         /* Device interface */
755         DEVMETHOD(device_identify,      pnp_identify),
756
757         { 0, 0 }
758 };
759
760 static driver_t pnp_driver = {
761         "pnp",
762         pnp_methods,
763         1,                      /* no softc */
764 };
765
766 static devclass_t pnp_devclass;
767
768 DRIVER_MODULE(pnp, isa, pnp_driver, pnp_devclass, 0, 0);