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