pnpparse.c revision 105220
152059Sdfr/*- 252059Sdfr * Copyright (c) 1999 Doug Rabson 352059Sdfr * All rights reserved. 452059Sdfr * 552059Sdfr * Redistribution and use in source and binary forms, with or without 652059Sdfr * modification, are permitted provided that the following conditions 752059Sdfr * are met: 852059Sdfr * 1. Redistributions of source code must retain the above copyright 952059Sdfr * notice, this list of conditions and the following disclaimer. 1052059Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1152059Sdfr * notice, this list of conditions and the following disclaimer in the 1252059Sdfr * documentation and/or other materials provided with the distribution. 1352059Sdfr * 1452059Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1552059Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1652059Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1752059Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1852059Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1952059Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2052059Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2152059Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2252059Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2352059Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2452059Sdfr * SUCH DAMAGE. 2552059Sdfr * 2652059Sdfr * $FreeBSD: head/sys/isa/pnpparse.c 105220 2002-10-16 09:07:30Z phk $ 2752059Sdfr */ 2852059Sdfr 2952059Sdfr#include <sys/param.h> 3052059Sdfr#include <sys/systm.h> 3158873Sdfr#include <sys/malloc.h> 3252059Sdfr#include <sys/module.h> 3352059Sdfr#include <sys/bus.h> 3483051Syokota 3583051Syokota#include <machine/stdarg.h> 3683051Syokota 3752059Sdfr#include <isa/isavar.h> 3852059Sdfr#include <isa/pnpreg.h> 3952059Sdfr#include <isa/pnpvar.h> 4052059Sdfr 4158850Sdfr#define MAXDEP 8 4258850Sdfr 4352241Sdfr#define I16(p) ((p)[0] + ((p)[1] << 8)) 44105220Sphk#define I32(p) (I16(p) + (I16((p)+2) << 16)) 4552241Sdfr 4683051Syokotavoid 4783051Syokotapnp_printf(u_int32_t id, char *fmt, ...) 4883051Syokota{ 4983051Syokota va_list ap; 5083051Syokota 5183051Syokota va_start(ap, fmt); 5283051Syokota printf("%s: ", pnp_eisaformat(id)); 5383051Syokota vprintf(fmt, ap); 5483051Syokota va_end(ap); 5583051Syokota} 5683051Syokota 5783051Syokota/* parse a single descriptor */ 5883051Syokota 5983051Syokotastatic int 6083051Syokotapnp_parse_desc(device_t dev, u_char tag, u_char *res, int len, 6183051Syokota struct isa_config *config, int ldn) 6283051Syokota{ 6383051Syokota char buf[100]; 6483051Syokota u_int32_t id; 6583051Syokota u_int32_t compat_id; 6683051Syokota int temp; 6783051Syokota 6883051Syokota id = isa_get_logicalid(dev); 6983051Syokota 7083051Syokota if (PNP_RES_TYPE(tag) == 0) { 7183051Syokota 7283051Syokota /* Small resource */ 7383051Syokota switch (PNP_SRES_NUM(tag)) { 7483051Syokota 7583051Syokota case PNP_TAG_VERSION: 7683051Syokota case PNP_TAG_VENDOR: 7783051Syokota /* these descriptors are quietly ignored */ 7883051Syokota break; 7983051Syokota 8083051Syokota case PNP_TAG_LOGICAL_DEVICE: 8183051Syokota case PNP_TAG_START_DEPENDANT: 8283051Syokota case PNP_TAG_END_DEPENDANT: 8383051Syokota if (bootverbose) 8483051Syokota pnp_printf(id, "unexpected small tag %d\n", 8583051Syokota PNP_SRES_NUM(tag)); 8683051Syokota /* shouldn't happen; quit now */ 8783051Syokota return (1); 8883051Syokota 8983051Syokota case PNP_TAG_COMPAT_DEVICE: 9083051Syokota /* 9183051Syokota * Got a compatible device id resource. 9283051Syokota * Should keep a list of compat ids in the device. 9383051Syokota */ 9483051Syokota bcopy(res, &compat_id, 4); 9583051Syokota if (isa_get_compatid(dev) == 0) 9683051Syokota isa_set_compatid(dev, compat_id); 9783051Syokota break; 9883051Syokota 9983051Syokota case PNP_TAG_IRQ_FORMAT: 10083051Syokota if (config->ic_nirq == ISA_NIRQ) { 10183051Syokota pnp_printf(id, "too many irqs\n"); 10283051Syokota return (1); 10383051Syokota } 10483051Syokota if (I16(res) == 0) { 10583051Syokota /* a null descriptor */ 10683051Syokota config->ic_irqmask[config->ic_nirq] = 0; 10783051Syokota config->ic_nirq++; 10883051Syokota break; 10983051Syokota } 11083051Syokota if (bootverbose) 11183051Syokota pnp_printf(id, "adding irq mask %#02x\n", 11283051Syokota I16(res)); 11383051Syokota config->ic_irqmask[config->ic_nirq] = I16(res); 11483051Syokota config->ic_nirq++; 11583051Syokota break; 11683051Syokota 11783051Syokota case PNP_TAG_DMA_FORMAT: 11883051Syokota if (config->ic_ndrq == ISA_NDRQ) { 11983051Syokota pnp_printf(id, "too many drqs\n"); 12083051Syokota return (1); 12183051Syokota } 12283051Syokota if (res[0] == 0) { 12383051Syokota /* a null descriptor */ 12483051Syokota config->ic_drqmask[config->ic_ndrq] = 0; 12583051Syokota config->ic_ndrq++; 12683051Syokota break; 12783051Syokota } 12883051Syokota if (bootverbose) 12983051Syokota pnp_printf(id, "adding dma mask %#02x\n", 13083051Syokota res[0]); 13183051Syokota config->ic_drqmask[config->ic_ndrq] = res[0]; 13283051Syokota config->ic_ndrq++; 13383051Syokota break; 13483051Syokota 13583051Syokota case PNP_TAG_IO_RANGE: 13683051Syokota if (config->ic_nport == ISA_NPORT) { 13783051Syokota pnp_printf(id, "too many ports\n"); 13883051Syokota return (1); 13983051Syokota } 14083051Syokota if (res[6] == 0) { 14183051Syokota /* a null descriptor */ 14283051Syokota config->ic_port[config->ic_nport].ir_start = 0; 14383051Syokota config->ic_port[config->ic_nport].ir_end = 0; 14483051Syokota config->ic_port[config->ic_nport].ir_size = 0; 14583051Syokota config->ic_port[config->ic_nport].ir_align = 0; 14683051Syokota config->ic_nport++; 14783051Syokota break; 14883051Syokota } 14983051Syokota if (bootverbose) { 15083051Syokota pnp_printf(id, "adding io range " 15183051Syokota "%#x-%#x, size=%#x, " 15283051Syokota "align=%#x\n", 15383051Syokota I16(res + 1), 15483051Syokota I16(res + 3) + res[6]-1, 15583051Syokota res[6], res[5]); 15683051Syokota } 15783051Syokota config->ic_port[config->ic_nport].ir_start = 15883051Syokota I16(res + 1); 15983051Syokota config->ic_port[config->ic_nport].ir_end = 16083051Syokota I16(res + 3) + res[6] - 1; 16183051Syokota config->ic_port[config->ic_nport].ir_size = res[6]; 16283051Syokota if (res[5] == 0) { 16383051Syokota /* Make sure align is at least one */ 16483051Syokota res[5] = 1; 16583051Syokota } 16683051Syokota config->ic_port[config->ic_nport].ir_align = res[5]; 16783051Syokota config->ic_nport++; 16883051Syokota pnp_check_quirks(isa_get_vendorid(dev), 16983051Syokota isa_get_logicalid(dev), ldn, config); 17083051Syokota break; 17183051Syokota 17283051Syokota case PNP_TAG_IO_FIXED: 17383051Syokota if (config->ic_nport == ISA_NPORT) { 17483051Syokota pnp_printf(id, "too many ports\n"); 17583051Syokota return (1); 17683051Syokota } 17783051Syokota if (res[2] == 0) { 17883051Syokota /* a null descriptor */ 17983051Syokota config->ic_port[config->ic_nport].ir_start = 0; 18083051Syokota config->ic_port[config->ic_nport].ir_end = 0; 18183051Syokota config->ic_port[config->ic_nport].ir_size = 0; 18283051Syokota config->ic_port[config->ic_nport].ir_align = 0; 18383051Syokota config->ic_nport++; 18483051Syokota break; 18583051Syokota } 18683051Syokota if (bootverbose) { 18783051Syokota pnp_printf(id, "adding fixed io range " 18883051Syokota "%#x-%#x, size=%#x, " 18983051Syokota "align=%#x\n", 19083051Syokota I16(res), 19183051Syokota I16(res) + res[2] - 1, 19283051Syokota res[2], 1); 19383051Syokota } 19483051Syokota config->ic_port[config->ic_nport].ir_start = I16(res); 19583051Syokota config->ic_port[config->ic_nport].ir_end = 19683051Syokota I16(res) + res[2] - 1; 19783051Syokota config->ic_port[config->ic_nport].ir_size = res[2]; 19883051Syokota config->ic_port[config->ic_nport].ir_align = 1; 19983051Syokota config->ic_nport++; 20083051Syokota break; 20183051Syokota 20283051Syokota case PNP_TAG_END: 20383051Syokota if (bootverbose) 20483051Syokota pnp_printf(id, "end config\n"); 20583051Syokota return (1); 20683051Syokota 20783051Syokota default: 20883051Syokota /* Skip this resource */ 20983051Syokota pnp_printf(id, "unexpected small tag %d\n", 21083051Syokota PNP_SRES_NUM(tag)); 21183051Syokota break; 21283051Syokota } 21383051Syokota } else { 21483051Syokota /* Large resource */ 21583051Syokota switch (PNP_LRES_NUM(tag)) { 21683051Syokota 21783051Syokota case PNP_TAG_ID_UNICODE: 21883051Syokota case PNP_TAG_LARGE_VENDOR: 21983051Syokota /* these descriptors are quietly ignored */ 22083051Syokota break; 22183051Syokota 22283051Syokota case PNP_TAG_ID_ANSI: 22383051Syokota if (len > sizeof(buf) - 1) 22483051Syokota len = sizeof(buf) - 1; 22583051Syokota bcopy(res, buf, len); 22683051Syokota 22783051Syokota /* 22883051Syokota * Trim trailing spaces and garbage. 22983051Syokota */ 23083051Syokota while (len > 0 && buf[len - 1] <= ' ') 23183051Syokota len--; 23283051Syokota buf[len] = '\0'; 23383051Syokota device_set_desc_copy(dev, buf); 23483051Syokota break; 23583051Syokota 23683051Syokota case PNP_TAG_MEMORY_RANGE: 23783051Syokota if (config->ic_nmem == ISA_NMEM) { 23883051Syokota pnp_printf(id, "too many memory ranges\n"); 23983051Syokota return (1); 24083051Syokota } 24183051Syokota if (I16(res + 7) == 0) { 24283051Syokota /* a null descriptor */ 24383051Syokota config->ic_mem[config->ic_nmem].ir_start = 0; 24483051Syokota config->ic_mem[config->ic_nmem].ir_end = 0; 24583051Syokota config->ic_mem[config->ic_nmem].ir_size = 0; 24683051Syokota config->ic_mem[config->ic_nmem].ir_align = 0; 24783051Syokota config->ic_nmem++; 24883051Syokota break; 24983051Syokota } 25083051Syokota if (bootverbose) { 25183051Syokota temp = I16(res + 7) << 8; 25283051Syokota pnp_printf(id, "adding memory range " 25383051Syokota "%#x-%#x, size=%#x, " 25483051Syokota "align=%#x\n", 25583051Syokota I16(res + 1) << 8, 25683051Syokota (I16(res + 3) << 8) + temp - 1, 25783051Syokota temp, I16(res + 5)); 25883051Syokota } 25983051Syokota config->ic_mem[config->ic_nmem].ir_start = 26083051Syokota I16(res + 1) << 8; 26183051Syokota config->ic_mem[config->ic_nmem].ir_end = 26283051Syokota (I16(res + 3) << 8) + (I16(res + 7) << 8) - 1; 26383051Syokota config->ic_mem[config->ic_nmem].ir_size = 26483051Syokota I16(res + 7) << 8; 26583051Syokota config->ic_mem[config->ic_nmem].ir_align = I16(res + 5); 26683051Syokota if (!config->ic_mem[config->ic_nmem].ir_align) 26783051Syokota config->ic_mem[config->ic_nmem].ir_align = 26883051Syokota 0x10000; 26983051Syokota config->ic_nmem++; 27083051Syokota break; 27183051Syokota 27283051Syokota case PNP_TAG_MEMORY32_RANGE: 27383051Syokota if (config->ic_nmem == ISA_NMEM) { 27483051Syokota pnp_printf(id, "too many memory ranges\n"); 27583051Syokota return (1); 27683051Syokota } 27783051Syokota if (I32(res + 13) == 0) { 27883051Syokota /* a null descriptor */ 27983051Syokota config->ic_mem[config->ic_nmem].ir_start = 0; 28083051Syokota config->ic_mem[config->ic_nmem].ir_end = 0; 28183051Syokota config->ic_mem[config->ic_nmem].ir_size = 0; 28283051Syokota config->ic_mem[config->ic_nmem].ir_align = 0; 28383051Syokota config->ic_nmem++; 28483051Syokota break; 28583051Syokota } 28683051Syokota if (bootverbose) { 28783051Syokota pnp_printf(id, "adding memory32 range " 28883051Syokota "%#x-%#x, size=%#x, " 28983051Syokota "align=%#x\n", 29083051Syokota I32(res + 1), 29183051Syokota I32(res + 5) + I32(res + 13) - 1, 29283051Syokota I32(res + 13), I32(res + 9)); 29383051Syokota } 29483051Syokota config->ic_mem[config->ic_nmem].ir_start = I32(res + 1); 29583051Syokota config->ic_mem[config->ic_nmem].ir_end = 29683051Syokota I32(res + 5) + I32(res + 13) - 1; 29783051Syokota config->ic_mem[config->ic_nmem].ir_size = I32(res + 13); 29883051Syokota config->ic_mem[config->ic_nmem].ir_align = I32(res + 9); 29983051Syokota config->ic_nmem++; 30083051Syokota break; 30183051Syokota 30283051Syokota case PNP_TAG_MEMORY32_FIXED: 30383051Syokota if (config->ic_nmem == ISA_NMEM) { 30483051Syokota pnp_printf(id, "too many memory ranges\n"); 30583051Syokota return (1); 30683051Syokota } 30783051Syokota if (I32(res + 5) == 0) { 30883051Syokota /* a null descriptor */ 30983051Syokota config->ic_mem[config->ic_nmem].ir_start = 0; 31083051Syokota config->ic_mem[config->ic_nmem].ir_end = 0; 31183051Syokota config->ic_mem[config->ic_nmem].ir_size = 0; 31283051Syokota config->ic_mem[config->ic_nmem].ir_align = 0; 31383051Syokota break; 31483051Syokota } 31583051Syokota if (bootverbose) { 31683051Syokota pnp_printf(id, "adding fixed memory32 range " 31783051Syokota "%#x-%#x, size=%#x\n", 31883051Syokota I32(res + 1), 31983051Syokota I32(res + 1) + I32(res + 5) - 1, 32083051Syokota I32(res + 5)); 32183051Syokota } 32283051Syokota config->ic_mem[config->ic_nmem].ir_start = I32(res + 1); 32383051Syokota config->ic_mem[config->ic_nmem].ir_end = 32483051Syokota I32(res + 1) + I32(res + 5) - 1; 32583051Syokota config->ic_mem[config->ic_nmem].ir_size = I32(res + 5); 32683051Syokota config->ic_mem[config->ic_nmem].ir_align = 1; 32783051Syokota config->ic_nmem++; 32883051Syokota break; 32983051Syokota 33083051Syokota default: 33183051Syokota /* Skip this resource */ 33283051Syokota pnp_printf(id, "unexpected large tag %d\n", 33383051Syokota PNP_SRES_NUM(tag)); 33483051Syokota break; 33583051Syokota } 33683051Syokota } 33783051Syokota 33883051Syokota return (0); 33983051Syokota} 34083051Syokota 34152059Sdfr/* 34283051Syokota * Parse a single "dependent" resource combination. 34383051Syokota */ 34483051Syokota 34583051Syokotau_char 34683051Syokota*pnp_parse_dependant(device_t dev, u_char *resources, int len, 34783051Syokota struct isa_config *config, int ldn) 34883051Syokota{ 34983051Syokota 35083051Syokota return pnp_scan_resources(dev, resources, len, config, ldn, 35183051Syokota pnp_parse_desc); 35283051Syokota} 35383051Syokota 35483051Syokotastatic void 35583051Syokotapnp_merge_resources(device_t dev, struct isa_config *from, 35683051Syokota struct isa_config *to) 35783051Syokota{ 35883051Syokota device_t parent; 35983051Syokota int i; 36083051Syokota 36183051Syokota parent = device_get_parent(dev); 36283051Syokota for (i = 0; i < from->ic_nmem; i++) { 36383051Syokota if (to->ic_nmem == ISA_NMEM) { 36483051Syokota device_printf(parent, "too many memory ranges\n"); 36583051Syokota return; 36683051Syokota } 36783051Syokota to->ic_mem[to->ic_nmem] = from->ic_mem[i]; 36883051Syokota to->ic_nmem++; 36983051Syokota } 37083051Syokota for (i = 0; i < from->ic_nport; i++) { 37183051Syokota if (to->ic_nport == ISA_NPORT) { 37283051Syokota device_printf(parent, "too many port ranges\n"); 37383051Syokota return; 37483051Syokota } 37583051Syokota to->ic_port[to->ic_nport] = from->ic_port[i]; 37683051Syokota to->ic_nport++; 37783051Syokota } 37883051Syokota for (i = 0; i < from->ic_nirq; i++) { 37983051Syokota if (to->ic_nirq == ISA_NIRQ) { 38083051Syokota device_printf(parent, "too many irq ranges\n"); 38183051Syokota return; 38283051Syokota } 38383051Syokota to->ic_irqmask[to->ic_nirq] = from->ic_irqmask[i]; 38483051Syokota to->ic_nirq++; 38583051Syokota } 38683051Syokota for (i = 0; i < from->ic_ndrq; i++) { 38783051Syokota if (to->ic_ndrq == ISA_NDRQ) { 38883051Syokota device_printf(parent, "too many drq ranges\n"); 38983051Syokota return; 39083051Syokota } 39183051Syokota to->ic_drqmask[to->ic_ndrq] = from->ic_drqmask[i]; 39283051Syokota to->ic_ndrq++; 39383051Syokota } 39483051Syokota} 39583051Syokota 39683051Syokota/* 39783051Syokota * Parse resource data for Logical Devices, make a list of available 39883051Syokota * resource configurations, and add them to the device. 39952059Sdfr * 40052059Sdfr * This function exits as soon as it gets an error reading *ANY* 40158850Sdfr * Resource Data or it reaches the end of Resource Data. 40252059Sdfr */ 40383051Syokota 40452059Sdfrvoid 40583051Syokotapnp_parse_resources(device_t dev, u_char *resources, int len, int ldn) 40652059Sdfr{ 40783051Syokota struct isa_config *configs; 40852059Sdfr struct isa_config *config; 40983051Syokota device_t parent; 41058850Sdfr int priorities[1 + MAXDEP]; 41183051Syokota u_char *start; 41283051Syokota u_char *p; 41383051Syokota u_char tag; 41483051Syokota u_int32_t id; 41583051Syokota int ncfgs; 41683051Syokota int l; 41758850Sdfr int i; 41852059Sdfr 41983051Syokota parent = device_get_parent(dev); 42052241Sdfr id = isa_get_logicalid(dev); 42183051Syokota 42283051Syokota configs = (struct isa_config *)malloc(sizeof(*configs)*(1 + MAXDEP), 42383051Syokota M_DEVBUF, M_NOWAIT | M_ZERO); 42458873Sdfr if (configs == NULL) { 42583051Syokota device_printf(parent, "No memory to parse PNP data\n"); 42658873Sdfr return; 42758873Sdfr } 42858850Sdfr config = &configs[0]; 42958850Sdfr priorities[0] = 0; 43083051Syokota ncfgs = 1; 43183051Syokota 43283051Syokota p = resources; 43383051Syokota start = NULL; 43483051Syokota while (len > 0) { 43583051Syokota tag = *p++; 43683051Syokota len--; 43752059Sdfr if (PNP_RES_TYPE(tag) == 0) { 43852059Sdfr /* Small resource */ 43983051Syokota l = PNP_SRES_LEN(tag); 44083051Syokota if (len < l) { 44183051Syokota len = 0; 44252059Sdfr continue; 44352059Sdfr } 44483051Syokota len -= l; 44583051Syokota 44652059Sdfr switch (PNP_SRES_NUM(tag)) { 44752059Sdfr 44852059Sdfr case PNP_TAG_START_DEPENDANT: 44983051Syokota if (start != NULL) { 45083051Syokota /* 45183051Syokota * Copy the common resources first, 45283051Syokota * then parse the "dependent" resources. 45383051Syokota */ 45483051Syokota pnp_merge_resources(dev, &configs[0], 45583051Syokota config); 45683051Syokota pnp_parse_dependant(dev, start, 45783051Syokota p - start - 1, 45883051Syokota config, ldn); 45952241Sdfr } 46083051Syokota start = p + l; 46159002Sdfr if (ncfgs > MAXDEP) { 46258850Sdfr device_printf(parent, "too many dependant configs (%d)\n", MAXDEP); 46383051Syokota len = 0; 46452059Sdfr break; 46552059Sdfr } 46658850Sdfr config = &configs[ncfgs]; 46752059Sdfr /* 46852059Sdfr * If the priority is not specified, 46983051Syokota * then use the default of 'acceptable' 47052059Sdfr */ 47183051Syokota if (l > 0) 47283051Syokota priorities[ncfgs] = p[0]; 47352059Sdfr else 47458850Sdfr priorities[ncfgs] = 1; 47583051Syokota if (bootverbose) 47683051Syokota pnp_printf(id, "start dependent (%d)\n", 47783051Syokota priorities[ncfgs]); 47858850Sdfr ncfgs++; 47952059Sdfr break; 48052059Sdfr 48152059Sdfr case PNP_TAG_END_DEPENDANT: 48283051Syokota if (start == NULL) { 48383051Syokota device_printf(parent, 48483051Syokota "malformed resources\n"); 48583051Syokota len = 0; 48652059Sdfr break; 48752059Sdfr } 48883051Syokota /* 48983051Syokota * Copy the common resources first, 49083051Syokota * then parse the "dependent" resources. 49183051Syokota */ 49283051Syokota pnp_merge_resources(dev, &configs[0], config); 49383051Syokota pnp_parse_dependant(dev, start, p - start - 1, 49483051Syokota config, ldn); 49583051Syokota start = NULL; 49683051Syokota if (bootverbose) 49783051Syokota pnp_printf(id, "end dependent\n"); 49883051Syokota /* 49983051Syokota * Back to the common part; clear it 50083051Syokota * as its contents has already been copied 50183051Syokota * to each dependant. 50283051Syokota */ 50383051Syokota config = &configs[0]; 50483051Syokota bzero(config, sizeof(*config)); 50552059Sdfr break; 50652059Sdfr 50752241Sdfr case PNP_TAG_END: 50883051Syokota if (start != NULL) { 50983051Syokota device_printf(parent, 51083051Syokota "malformed resources\n"); 51152241Sdfr } 51283051Syokota len = 0; 51352241Sdfr break; 51452241Sdfr 51552059Sdfr default: 51683051Syokota if (start != NULL) 51783051Syokota /* defer parsing a dependent section */ 51883051Syokota break; 51983051Syokota if (pnp_parse_desc(dev, tag, p, l, config, ldn)) 52083051Syokota len = 0; 52152059Sdfr break; 52252059Sdfr } 52383051Syokota p += l; 52452059Sdfr } else { 52552059Sdfr /* Large resource */ 52683051Syokota if (len < 2) { 52783051Syokota len = 0; 52883051Syokota break; 52952059Sdfr } 53083051Syokota l = I16(p); 53183051Syokota p += 2; 53283051Syokota len -= 2; 53383051Syokota if (len < l) { 53483051Syokota len = 0; 53583051Syokota break; 53652059Sdfr } 53783051Syokota len -= l; 53883051Syokota if (start == NULL && 53983051Syokota pnp_parse_desc(dev, tag, p, l, config, ldn)) { 54083051Syokota len = 0; 54152241Sdfr break; 54252241Sdfr } 54383051Syokota p += l; 54452059Sdfr } 54552059Sdfr } 54683051Syokota 54783051Syokota if (ncfgs == 1) { 54858850Sdfr /* Single config without dependants */ 54983051Syokota ISA_ADD_CONFIG(parent, dev, priorities[0], &configs[0]); 55058873Sdfr free(configs, M_DEVBUF); 55158850Sdfr return; 55258850Sdfr } 55383051Syokota 55483051Syokota for (i = 1; i < ncfgs; i++) { 55583051Syokota /* 55683051Syokota * Merge the remaining part of the common resources, 55783051Syokota * if any. Strictly speaking, there shouldn't be common/main 55883051Syokota * resources after the END_DEPENDENT tag. 55983051Syokota */ 56083051Syokota pnp_merge_resources(dev, &configs[0], &configs[i]); 56183051Syokota ISA_ADD_CONFIG(parent, dev, priorities[i], &configs[i]); 56258850Sdfr } 56383051Syokota 56458873Sdfr free(configs, M_DEVBUF); 56552059Sdfr} 56683051Syokota 56783051Syokotau_char 56883051Syokota*pnp_scan_resources(device_t dev, u_char *resources, int len, 56983051Syokota struct isa_config *config, int ldn, pnp_scan_cb *cb) 57083051Syokota{ 57183051Syokota u_char *p; 57283051Syokota u_char tag; 57383051Syokota int l; 57483051Syokota 57583051Syokota p = resources; 57683051Syokota while (len > 0) { 57783051Syokota tag = *p++; 57883051Syokota len--; 57983051Syokota if (PNP_RES_TYPE(tag) == 0) { 58083051Syokota /* small resource */ 58183051Syokota l = PNP_SRES_LEN(tag); 58283051Syokota if (len < l) 58383051Syokota break; 58483051Syokota if ((*cb)(dev, tag, p, l, config, ldn)) 58583051Syokota return (p + l); 58683051Syokota if (PNP_SRES_NUM(tag) == PNP_TAG_END) 58783051Syokota return (p + l); 58883051Syokota } else { 58983051Syokota /* large resource */ 59083051Syokota if (len < 2) 59183051Syokota break; 59283051Syokota l = I16(p); 59383051Syokota p += 2; 59483051Syokota len -= 2; 59583051Syokota if (len < l) 59683051Syokota break; 59783051Syokota if ((*cb)(dev, tag, p, l, config, ldn)) 59883051Syokota return (p + l); 59983051Syokota } 60083051Syokota p += l; 60183051Syokota len -= l; 60283051Syokota } 60383051Syokota return NULL; 60483051Syokota} 605