xref: /freebsd/sys/isa/pnpparse.c (revision ca403ff820f17ac64a34c8279759122cdb01dd5f)
15b45337dSDoug Rabson /*-
25b45337dSDoug Rabson  * Copyright (c) 1999 Doug Rabson
35b45337dSDoug Rabson  * All rights reserved.
45b45337dSDoug Rabson  *
55b45337dSDoug Rabson  * Redistribution and use in source and binary forms, with or without
65b45337dSDoug Rabson  * modification, are permitted provided that the following conditions
75b45337dSDoug Rabson  * are met:
85b45337dSDoug Rabson  * 1. Redistributions of source code must retain the above copyright
95b45337dSDoug Rabson  *    notice, this list of conditions and the following disclaimer.
105b45337dSDoug Rabson  * 2. Redistributions in binary form must reproduce the above copyright
115b45337dSDoug Rabson  *    notice, this list of conditions and the following disclaimer in the
125b45337dSDoug Rabson  *    documentation and/or other materials provided with the distribution.
135b45337dSDoug Rabson  *
145b45337dSDoug Rabson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
155b45337dSDoug Rabson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
165b45337dSDoug Rabson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
175b45337dSDoug Rabson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
185b45337dSDoug Rabson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
195b45337dSDoug Rabson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
205b45337dSDoug Rabson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
215b45337dSDoug Rabson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
225b45337dSDoug Rabson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
235b45337dSDoug Rabson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
245b45337dSDoug Rabson  * SUCH DAMAGE.
255b45337dSDoug Rabson  *
265b45337dSDoug Rabson  *	$FreeBSD$
275b45337dSDoug Rabson  */
285b45337dSDoug Rabson 
295b45337dSDoug Rabson #include <sys/param.h>
305b45337dSDoug Rabson #include <sys/systm.h>
315b45337dSDoug Rabson #include <sys/kernel.h>
32ca403ff8SDoug Rabson #include <sys/malloc.h>
335b45337dSDoug Rabson #include <sys/module.h>
345b45337dSDoug Rabson #include <sys/bus.h>
355b45337dSDoug Rabson #include <isa/isavar.h>
365b45337dSDoug Rabson #include <isa/pnpreg.h>
375b45337dSDoug Rabson #include <isa/pnpvar.h>
385b45337dSDoug Rabson 
39acd3131bSDoug Rabson #define	MAXDEP	8
40acd3131bSDoug Rabson 
41bb2b9030SDoug Rabson #define I16(p)	((p)[0] + ((p)[1] << 8))
42bb2b9030SDoug Rabson #define I32(p)	(I16(p) + (I16(p+2) << 16))
43bb2b9030SDoug Rabson 
445b45337dSDoug Rabson /*
455b45337dSDoug Rabson  * Parse resource data for Logical Devices.
465b45337dSDoug Rabson  *
475b45337dSDoug Rabson  * This function exits as soon as it gets an error reading *ANY*
48acd3131bSDoug Rabson  * Resource Data or it reaches the end of Resource Data.
495b45337dSDoug Rabson  */
505b45337dSDoug Rabson void
515b45337dSDoug Rabson pnp_parse_resources(device_t dev, u_char *resources, int len)
525b45337dSDoug Rabson {
535b45337dSDoug Rabson 	device_t parent = device_get_parent(dev);
545b45337dSDoug Rabson 	u_char tag, *resp, *resinfo;
555b45337dSDoug Rabson 	int large_len, scanning = len;
56bb2b9030SDoug Rabson 	u_int32_t id, compat_id;
575b45337dSDoug Rabson 	struct isa_config *config;
58acd3131bSDoug Rabson 	int ncfgs = 1;
59acd3131bSDoug Rabson 	int priorities[1 + MAXDEP];
60ca403ff8SDoug Rabson 	struct isa_config *configs;
615b45337dSDoug Rabson 	char buf[100];
62acd3131bSDoug Rabson 	int i;
635b45337dSDoug Rabson 
64bb2b9030SDoug Rabson 	id = isa_get_logicalid(dev);
65ca403ff8SDoug Rabson 	configs = (struct isa_config *)malloc(sizeof(*configs) * (1 + MAXDEP),
66ca403ff8SDoug Rabson 						M_DEVBUF, M_NOWAIT);
67ca403ff8SDoug Rabson 	if (configs == NULL) {
68ca403ff8SDoug Rabson 		device_printf(dev, "No memory to parse PNP data\n");
69ca403ff8SDoug Rabson 		return;
70ca403ff8SDoug Rabson 	}
71ca403ff8SDoug Rabson 	bzero(configs, sizeof(*configs) * (1 + MAXDEP));
72acd3131bSDoug Rabson 	config = &configs[0];
73acd3131bSDoug Rabson 	priorities[0] = 0;
745b45337dSDoug Rabson 	resp = resources;
755b45337dSDoug Rabson 	while (scanning > 0) {
765b45337dSDoug Rabson 		tag = *resp++;
775b45337dSDoug Rabson 		scanning--;
785b45337dSDoug Rabson 		if (PNP_RES_TYPE(tag) == 0) {
795b45337dSDoug Rabson 			/* Small resource */
805b45337dSDoug Rabson 			if (scanning < PNP_SRES_LEN(tag)) {
815b45337dSDoug Rabson 				scanning = 0;
825b45337dSDoug Rabson 				continue;
835b45337dSDoug Rabson 			}
845b45337dSDoug Rabson 			resinfo = resp;
855b45337dSDoug Rabson 			resp += PNP_SRES_LEN(tag);
865b45337dSDoug Rabson 			scanning -= PNP_SRES_LEN(tag);;
875b45337dSDoug Rabson 
885b45337dSDoug Rabson 			switch (PNP_SRES_NUM(tag)) {
895b45337dSDoug Rabson 			case PNP_TAG_COMPAT_DEVICE:
905b45337dSDoug Rabson 				/*
915b45337dSDoug Rabson 				 * Got a compatible device id
925b45337dSDoug Rabson 				 * resource. Should keep a list of
935b45337dSDoug Rabson 				 * compat ids in the device.
945b45337dSDoug Rabson 				 */
955b45337dSDoug Rabson 				bcopy(resinfo, &compat_id, 4);
965b45337dSDoug Rabson 				isa_set_compatid(dev, compat_id);
975b45337dSDoug Rabson 				break;
985b45337dSDoug Rabson 
995b45337dSDoug Rabson 			case PNP_TAG_IRQ_FORMAT:
100bb2b9030SDoug Rabson 				if (bootverbose) {
101bb2b9030SDoug Rabson 					printf("%s: adding irq mask %#04x\n",
102bb2b9030SDoug Rabson 					       pnp_eisaformat(id),
103bb2b9030SDoug Rabson 					       I16(resinfo));
104bb2b9030SDoug Rabson 				}
1055b45337dSDoug Rabson 				if (config->ic_nirq == ISA_NIRQ) {
106acd3131bSDoug Rabson 					device_printf(parent, "too many irqs\n");
1075b45337dSDoug Rabson 					scanning = 0;
1085b45337dSDoug Rabson 					break;
1095b45337dSDoug Rabson 				}
1105b45337dSDoug Rabson 				config->ic_irqmask[config->ic_nirq] =
111bb2b9030SDoug Rabson 					I16(resinfo);
1125b45337dSDoug Rabson 				config->ic_nirq++;
1135b45337dSDoug Rabson 				break;
1145b45337dSDoug Rabson 
1155b45337dSDoug Rabson 			case PNP_TAG_DMA_FORMAT:
116bb2b9030SDoug Rabson 				if (bootverbose) {
117bb2b9030SDoug Rabson 					printf("%s: adding dma mask %#02x\n",
118bb2b9030SDoug Rabson 					       pnp_eisaformat(id),
119bb2b9030SDoug Rabson 					       resinfo[0]);
120bb2b9030SDoug Rabson 				}
1215b45337dSDoug Rabson 				if (config->ic_ndrq == ISA_NDRQ) {
122acd3131bSDoug Rabson 					device_printf(parent, "too many drqs\n");
1235b45337dSDoug Rabson 					scanning = 0;
1245b45337dSDoug Rabson 					break;
1255b45337dSDoug Rabson 				}
1265b45337dSDoug Rabson 				config->ic_drqmask[config->ic_ndrq] =
1275b45337dSDoug Rabson 					resinfo[0];
1285b45337dSDoug Rabson 				config->ic_ndrq++;
1295b45337dSDoug Rabson 				break;
1305b45337dSDoug Rabson 
1315b45337dSDoug Rabson 			case PNP_TAG_START_DEPENDANT:
132bb2b9030SDoug Rabson 				if (bootverbose) {
133bb2b9030SDoug Rabson 					printf("%s: start dependant\n",
134bb2b9030SDoug Rabson 					       pnp_eisaformat(id));
135bb2b9030SDoug Rabson 				}
136acd3131bSDoug Rabson 				if (ncfgs >= MAXDEP) {
137acd3131bSDoug Rabson 					device_printf(parent, "too many dependant configs (%d)\n", MAXDEP);
1385b45337dSDoug Rabson 					scanning = 0;
1395b45337dSDoug Rabson 					break;
1405b45337dSDoug Rabson 				}
141acd3131bSDoug Rabson 				config = &configs[ncfgs];
1425b45337dSDoug Rabson 				/*
1435b45337dSDoug Rabson 				 * If the priority is not specified,
1445b45337dSDoug Rabson 				 * then use the default of
1455b45337dSDoug Rabson 				 * 'acceptable'
1465b45337dSDoug Rabson 				 */
1475b45337dSDoug Rabson 				if (PNP_SRES_LEN(tag) > 0)
148acd3131bSDoug Rabson 					priorities[ncfgs] = resinfo[0];
1495b45337dSDoug Rabson 				else
150acd3131bSDoug Rabson 					priorities[ncfgs] = 1;
151acd3131bSDoug Rabson 				ncfgs++;
1525b45337dSDoug Rabson 				break;
1535b45337dSDoug Rabson 
1545b45337dSDoug Rabson 			case PNP_TAG_END_DEPENDANT:
155bb2b9030SDoug Rabson 				if (bootverbose) {
156bb2b9030SDoug Rabson 					printf("%s: end dependant\n",
157bb2b9030SDoug Rabson 					       pnp_eisaformat(id));
158bb2b9030SDoug Rabson 				}
159acd3131bSDoug Rabson 				config = &configs[0];	/* back to main config */
1605b45337dSDoug Rabson 				break;
1615b45337dSDoug Rabson 
1625b45337dSDoug Rabson 			case PNP_TAG_IO_RANGE:
163bb2b9030SDoug Rabson 				if (bootverbose) {
164bb2b9030SDoug Rabson 					printf("%s: adding io range "
165bb2b9030SDoug Rabson 					       "%#x-%#x, size=%#x, "
166bb2b9030SDoug Rabson 					       "align=%#x\n",
167bb2b9030SDoug Rabson 					       pnp_eisaformat(id),
168bb2b9030SDoug Rabson 					       I16(resinfo + 1),
169bb2b9030SDoug Rabson 					       I16(resinfo + 3) + resinfo[6]-1,
170bb2b9030SDoug Rabson 					       resinfo[6],
171bb2b9030SDoug Rabson 					       resinfo[5]);
172bb2b9030SDoug Rabson 				}
1735b45337dSDoug Rabson 				if (config->ic_nport == ISA_NPORT) {
174acd3131bSDoug Rabson 					device_printf(parent, "too many ports\n");
1755b45337dSDoug Rabson 					scanning = 0;
1765b45337dSDoug Rabson 					break;
1775b45337dSDoug Rabson 				}
1785b45337dSDoug Rabson 				config->ic_port[config->ic_nport].ir_start =
179bb2b9030SDoug Rabson 					I16(resinfo + 1);
1805b45337dSDoug Rabson 				config->ic_port[config->ic_nport].ir_end =
181bb2b9030SDoug Rabson 					I16(resinfo + 3) + resinfo[6] - 1;
182bb2b9030SDoug Rabson 				config->ic_port[config->ic_nport].ir_size =
1835b45337dSDoug Rabson 					resinfo[6];
184bb2b9030SDoug Rabson 				if (resinfo[5] == 0) {
185bb2b9030SDoug Rabson 				    /* Make sure align is at least one */
186bb2b9030SDoug Rabson 				    resinfo[5] = 1;
187bb2b9030SDoug Rabson 				}
1885b45337dSDoug Rabson 				config->ic_port[config->ic_nport].ir_align =
1895b45337dSDoug Rabson 					resinfo[5];
1905b45337dSDoug Rabson 				config->ic_nport++;
1915b45337dSDoug Rabson 				break;
1925b45337dSDoug Rabson 
1935b45337dSDoug Rabson 			case PNP_TAG_IO_FIXED:
194bb2b9030SDoug Rabson 				if (bootverbose) {
195acd3131bSDoug Rabson 					printf("%s: adding fixed io range "
196bb2b9030SDoug Rabson 					       "%#x-%#x, size=%#x, "
197bb2b9030SDoug Rabson 					       "align=%#x\n",
198bb2b9030SDoug Rabson 					       pnp_eisaformat(id),
199bb2b9030SDoug Rabson 					       I16(resinfo),
200bb2b9030SDoug Rabson 					       I16(resinfo) + resinfo[2] - 1,
201bb2b9030SDoug Rabson 					       resinfo[2],
202bb2b9030SDoug Rabson 					       1);
203bb2b9030SDoug Rabson 				}
2045b45337dSDoug Rabson 				if (config->ic_nport == ISA_NPORT) {
205acd3131bSDoug Rabson 					device_printf(parent, "too many ports\n");
2065b45337dSDoug Rabson 					scanning = 0;
2075b45337dSDoug Rabson 					break;
2085b45337dSDoug Rabson 				}
2095b45337dSDoug Rabson 				config->ic_port[config->ic_nport].ir_start =
210bb2b9030SDoug Rabson 					I16(resinfo);
2115b45337dSDoug Rabson 				config->ic_port[config->ic_nport].ir_end =
212bb2b9030SDoug Rabson 					I16(resinfo) + resinfo[2] - 1;
2135b45337dSDoug Rabson 				config->ic_port[config->ic_nport].ir_size
2145b45337dSDoug Rabson 					= resinfo[2];
2155b45337dSDoug Rabson 				config->ic_port[config->ic_nport].ir_align = 1;
2165b45337dSDoug Rabson 				config->ic_nport++;
2175b45337dSDoug Rabson 				break;
2185b45337dSDoug Rabson 
219bb2b9030SDoug Rabson 			case PNP_TAG_END:
220bb2b9030SDoug Rabson 				if (bootverbose) {
221acd3131bSDoug Rabson 					printf("%s: end config\n",
222bb2b9030SDoug Rabson 					       pnp_eisaformat(id));
223bb2b9030SDoug Rabson 				}
224bb2b9030SDoug Rabson 				scanning = 0;
225bb2b9030SDoug Rabson 				break;
226bb2b9030SDoug Rabson 
2275b45337dSDoug Rabson 			default:
2285b45337dSDoug Rabson 				/* Skip this resource */
229acd3131bSDoug Rabson 				device_printf(parent, "unexpected small tag %d\n",
2305b45337dSDoug Rabson 					      PNP_SRES_NUM(tag));
2315b45337dSDoug Rabson 				break;
2325b45337dSDoug Rabson 			}
2335b45337dSDoug Rabson 		} else {
2345b45337dSDoug Rabson 			/* Large resource */
2355b45337dSDoug Rabson 			if (scanning < 2) {
2365b45337dSDoug Rabson 				scanning = 0;
2375b45337dSDoug Rabson 				continue;
2385b45337dSDoug Rabson 			}
239bb2b9030SDoug Rabson 			large_len = I16(resp);
2405b45337dSDoug Rabson 			resp += 2;
2415b45337dSDoug Rabson 			scanning -= 2;
2425b45337dSDoug Rabson 
2435b45337dSDoug Rabson 			if (scanning < large_len) {
2445b45337dSDoug Rabson 				scanning = 0;
2455b45337dSDoug Rabson 				continue;
2465b45337dSDoug Rabson 			}
2475b45337dSDoug Rabson 			resinfo = resp;
2485b45337dSDoug Rabson 			resp += large_len;
2495b45337dSDoug Rabson 			scanning -= large_len;
2505b45337dSDoug Rabson 
251bb2b9030SDoug Rabson 			switch (PNP_LRES_NUM(tag)) {
252bb2b9030SDoug Rabson 			case PNP_TAG_ID_ANSI:
2535b45337dSDoug Rabson 				if (large_len > sizeof(buf) - 1)
2545b45337dSDoug Rabson 					large_len = sizeof(buf) - 1;
2555b45337dSDoug Rabson 				bcopy(resinfo, buf, large_len);
2565b45337dSDoug Rabson 
2575b45337dSDoug Rabson 				/*
258acd3131bSDoug Rabson 				 * Trim trailing spaces and garbage.
2595b45337dSDoug Rabson 				 */
260acd3131bSDoug Rabson 				while (large_len > 0 && buf[large_len - 1] <= ' ')
2615b45337dSDoug Rabson 					large_len--;
2625b45337dSDoug Rabson 				buf[large_len] = '\0';
2635b45337dSDoug Rabson 				device_set_desc_copy(dev, buf);
264bb2b9030SDoug Rabson 				break;
2655b45337dSDoug Rabson 
266bb2b9030SDoug Rabson 			case PNP_TAG_MEMORY_RANGE:
267bb2b9030SDoug Rabson 				if (bootverbose) {
2681f1624dcSDoug Rabson 					int temp = I16(resinfo + 7) << 8;
2691f1624dcSDoug Rabson 
270bb2b9030SDoug Rabson 					printf("%s: adding memory range "
271bb2b9030SDoug Rabson 					       "%#x-%#x, size=%#x, "
272bb2b9030SDoug Rabson 					       "align=%#x\n",
273bb2b9030SDoug Rabson 					       pnp_eisaformat(id),
274bb2b9030SDoug Rabson 					       I16(resinfo + 1)<<8,
2751f1624dcSDoug Rabson 					       (I16(resinfo + 3)<<8) + temp - 1,
2761f1624dcSDoug Rabson 					       temp,
277bb2b9030SDoug Rabson 					       I16(resinfo + 5));
2785b45337dSDoug Rabson 				}
2795b45337dSDoug Rabson 
2805b45337dSDoug Rabson 				if (config->ic_nmem == ISA_NMEM) {
281ca403ff8SDoug Rabson 					device_printf(parent, "too many memory ranges\n");
2825b45337dSDoug Rabson 					scanning = 0;
2835b45337dSDoug Rabson 					break;
2845b45337dSDoug Rabson 				}
2855b45337dSDoug Rabson 
2865b45337dSDoug Rabson 				config->ic_mem[config->ic_nmem].ir_start =
287bb2b9030SDoug Rabson 					I16(resinfo + 1)<<8;
2885b45337dSDoug Rabson 				config->ic_mem[config->ic_nmem].ir_end =
289bb2b9030SDoug Rabson 					(I16(resinfo + 3)<<8)
2901f1624dcSDoug Rabson 					+ (I16(resinfo + 7) << 8) - 1;
2915b45337dSDoug Rabson 				config->ic_mem[config->ic_nmem].ir_size =
2921f1624dcSDoug Rabson 					I16(resinfo + 7) << 8;
2935b45337dSDoug Rabson 				config->ic_mem[config->ic_nmem].ir_align =
294bb2b9030SDoug Rabson 					I16(resinfo + 5);
2955b45337dSDoug Rabson 				if (!config->ic_mem[config->ic_nmem].ir_align)
296bb2b9030SDoug Rabson 					config->ic_mem[config->ic_nmem]
297bb2b9030SDoug Rabson 						.ir_align = 0x10000;
2985b45337dSDoug Rabson 				config->ic_nmem++;
299bb2b9030SDoug Rabson 				break;
300bb2b9030SDoug Rabson 
301bb2b9030SDoug Rabson 			case PNP_TAG_MEMORY32_RANGE:
302bb2b9030SDoug Rabson 				if (bootverbose) {
303acd3131bSDoug Rabson 					printf("%s: adding memory32 range "
304bb2b9030SDoug Rabson 					       "%#x-%#x, size=%#x, "
305bb2b9030SDoug Rabson 					       "align=%#x\n",
306bb2b9030SDoug Rabson 					       pnp_eisaformat(id),
307bb2b9030SDoug Rabson 					       I32(resinfo + 1),
308bb2b9030SDoug Rabson 					       I32(resinfo + 5)
309bb2b9030SDoug Rabson 					       + I32(resinfo + 13) - 1,
310bb2b9030SDoug Rabson 					       I32(resinfo + 13),
311bb2b9030SDoug Rabson 					       I32(resinfo + 9));
312bb2b9030SDoug Rabson 				}
313bb2b9030SDoug Rabson 
314bb2b9030SDoug Rabson 				if (config->ic_nmem == ISA_NMEM) {
315acd3131bSDoug Rabson 					device_printf(parent, "too many memory ranges\n");
316bb2b9030SDoug Rabson 					scanning = 0;
317bb2b9030SDoug Rabson 					break;
318bb2b9030SDoug Rabson 				}
319bb2b9030SDoug Rabson 
320bb2b9030SDoug Rabson 				config->ic_mem[config->ic_nmem].ir_start =
321bb2b9030SDoug Rabson 					I32(resinfo + 1);
322bb2b9030SDoug Rabson 				config->ic_mem[config->ic_nmem].ir_end =
323bb2b9030SDoug Rabson 					I32(resinfo + 5)
324bb2b9030SDoug Rabson 					+ I32(resinfo + 13) - 1;
325bb2b9030SDoug Rabson 				config->ic_mem[config->ic_nmem].ir_size =
326bb2b9030SDoug Rabson 					I32(resinfo + 13);
327bb2b9030SDoug Rabson 				config->ic_mem[config->ic_nmem].ir_align =
328bb2b9030SDoug Rabson 					I32(resinfo + 9);
329bb2b9030SDoug Rabson 				config->ic_nmem++;
330bb2b9030SDoug Rabson 				break;
331bb2b9030SDoug Rabson 
332bb2b9030SDoug Rabson 			case PNP_TAG_MEMORY32_FIXED:
333bb2b9030SDoug Rabson 				if (I32(resinfo + 5) == 0) {
334bb2b9030SDoug Rabson 					if (bootverbose) {
335bb2b9030SDoug Rabson 						printf("%s: skipping empty range\n",
336bb2b9030SDoug Rabson 						       pnp_eisaformat(id));
337bb2b9030SDoug Rabson 					}
338bb2b9030SDoug Rabson 					continue;
339bb2b9030SDoug Rabson 				}
340bb2b9030SDoug Rabson 				if (bootverbose) {
341acd3131bSDoug Rabson 					printf("%s: adding fixed memory32 range "
342bb2b9030SDoug Rabson 					       "%#x-%#x, size=%#x\n",
343bb2b9030SDoug Rabson 					       pnp_eisaformat(id),
344bb2b9030SDoug Rabson 					       I32(resinfo + 1),
345bb2b9030SDoug Rabson 					       I32(resinfo + 1)
346bb2b9030SDoug Rabson 					       + I32(resinfo + 5) - 1,
347bb2b9030SDoug Rabson 					       I32(resinfo + 5));
348bb2b9030SDoug Rabson 				}
349bb2b9030SDoug Rabson 
350bb2b9030SDoug Rabson 				if (config->ic_nmem == ISA_NMEM) {
351acd3131bSDoug Rabson 					device_printf(parent, "too many memory ranges\n");
352bb2b9030SDoug Rabson 					scanning = 0;
353bb2b9030SDoug Rabson 					break;
354bb2b9030SDoug Rabson 				}
355bb2b9030SDoug Rabson 
356bb2b9030SDoug Rabson 				config->ic_mem[config->ic_nmem].ir_start =
357bb2b9030SDoug Rabson 					I32(resinfo + 1);
358bb2b9030SDoug Rabson 				config->ic_mem[config->ic_nmem].ir_end =
359bb2b9030SDoug Rabson 					I32(resinfo + 1)
360bb2b9030SDoug Rabson 					+ I32(resinfo + 5) - 1;
361bb2b9030SDoug Rabson 				config->ic_mem[config->ic_nmem].ir_size =
362bb2b9030SDoug Rabson 					I32(resinfo + 5);
363bb2b9030SDoug Rabson 				config->ic_mem[config->ic_nmem].ir_align = 1;
364bb2b9030SDoug Rabson 				config->ic_nmem++;
365bb2b9030SDoug Rabson 				break;
366bb2b9030SDoug Rabson 
367bb2b9030SDoug Rabson 			default:
368bb2b9030SDoug Rabson 				/* Skip this resource */
369acd3131bSDoug Rabson 				device_printf(parent, "unexpected large tag %d\n",
370bb2b9030SDoug Rabson 					      PNP_SRES_NUM(tag));
371bb2b9030SDoug Rabson 			}
3725b45337dSDoug Rabson 		}
3735b45337dSDoug Rabson 	}
374acd3131bSDoug Rabson 	if(ncfgs == 1) {
375acd3131bSDoug Rabson 		/* Single config without dependants */
376acd3131bSDoug Rabson 		(void)ISA_ADD_CONFIG(parent, dev, priorities[0], &configs[0]);
377ca403ff8SDoug Rabson 		free(configs, M_DEVBUF);
378acd3131bSDoug Rabson 		return;
3795b45337dSDoug Rabson 	}
380acd3131bSDoug Rabson 	/* Cycle through dependant configs merging primary details */
381acd3131bSDoug Rabson 	for(i = 1; i < ncfgs; i++) {
382acd3131bSDoug Rabson 		int j;
383acd3131bSDoug Rabson 		config = &configs[i];
384acd3131bSDoug Rabson 		for(j = 0; j < configs[0].ic_nmem; j++) {
385acd3131bSDoug Rabson 			if (config->ic_nmem == ISA_NMEM) {
386acd3131bSDoug Rabson 				device_printf(parent, "too many memory ranges\n");
387ca403ff8SDoug Rabson 				free(configs, M_DEVBUF);
388acd3131bSDoug Rabson 				return;
389acd3131bSDoug Rabson 			}
390acd3131bSDoug Rabson 			config->ic_mem[config->ic_nmem] = configs[0].ic_mem[j];
391acd3131bSDoug Rabson 			config->ic_nmem++;
392acd3131bSDoug Rabson 		}
393acd3131bSDoug Rabson 		for(j = 0; j < configs[0].ic_nport; j++) {
394acd3131bSDoug Rabson 			if (config->ic_nport == ISA_NPORT) {
395acd3131bSDoug Rabson 				device_printf(parent, "too many port ranges\n");
396ca403ff8SDoug Rabson 				free(configs, M_DEVBUF);
397acd3131bSDoug Rabson 				return;
398acd3131bSDoug Rabson 			}
399acd3131bSDoug Rabson 			config->ic_port[config->ic_nport] = configs[0].ic_port[j];
400acd3131bSDoug Rabson 			config->ic_nport++;
401acd3131bSDoug Rabson 		}
402acd3131bSDoug Rabson 		for(j = 0; j < configs[0].ic_nirq; j++) {
403acd3131bSDoug Rabson 			if (config->ic_nirq == ISA_NIRQ) {
404acd3131bSDoug Rabson 				device_printf(parent, "too many irq ranges\n");
405ca403ff8SDoug Rabson 				free(configs, M_DEVBUF);
406acd3131bSDoug Rabson 				return;
407acd3131bSDoug Rabson 			}
408acd3131bSDoug Rabson 			config->ic_irqmask[config->ic_nirq] = configs[0].ic_irqmask[j];
409acd3131bSDoug Rabson 			config->ic_nirq++;
410acd3131bSDoug Rabson 		}
411acd3131bSDoug Rabson 		for(j = 0; j < configs[0].ic_ndrq; j++) {
412acd3131bSDoug Rabson 			if (config->ic_ndrq == ISA_NDRQ) {
413acd3131bSDoug Rabson 				device_printf(parent, "too many drq ranges\n");
414ca403ff8SDoug Rabson 				free(configs, M_DEVBUF);
415acd3131bSDoug Rabson 				return;
416acd3131bSDoug Rabson 			}
417acd3131bSDoug Rabson 			config->ic_drqmask[config->ic_ndrq] = configs[0].ic_drqmask[j];
418acd3131bSDoug Rabson 			config->ic_ndrq++;
419acd3131bSDoug Rabson 		}
420acd3131bSDoug Rabson 		(void)ISA_ADD_CONFIG(parent, dev, priorities[i], &configs[i]);
421acd3131bSDoug Rabson 	}
422ca403ff8SDoug Rabson 	free(configs, M_DEVBUF);
423acd3131bSDoug Rabson }
424