Home | History | Annotate | Line # | Download | only in pnpbios
pnpbios.c revision 1.10
      1  1.10     soren /* $NetBSD: pnpbios.c,v 1.10 2000/02/20 21:42:26 soren Exp $ */
      2   1.1  drochner /*
      3   1.1  drochner  * Copyright (c) 1999
      4   1.1  drochner  * 	Matthias Drochner.  All rights reserved.
      5   1.1  drochner  *
      6   1.1  drochner  * Redistribution and use in source and binary forms, with or without
      7   1.1  drochner  * modification, are permitted provided that the following conditions
      8   1.1  drochner  * are met:
      9   1.1  drochner  * 1. Redistributions of source code must retain the above copyright
     10   1.1  drochner  *    notice, this list of conditions, and the following disclaimer.
     11   1.1  drochner  * 2. Redistributions in binary form must reproduce the above copyright
     12   1.1  drochner  *    notice, this list of conditions and the following disclaimer in the
     13   1.1  drochner  *    documentation and/or other materials provided with the distribution.
     14   1.1  drochner  *
     15   1.1  drochner  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     16   1.1  drochner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     17   1.1  drochner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     18   1.1  drochner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     19   1.1  drochner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20   1.1  drochner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     21   1.1  drochner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22   1.1  drochner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23   1.1  drochner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24   1.1  drochner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25   1.1  drochner  * SUCH DAMAGE.
     26  1.10     soren  */
     27  1.10     soren 
     28  1.10     soren /*
     29  1.10     soren  * PnP BIOS documentation is available at the following locations.
     30  1.10     soren  *
     31  1.10     soren  * http://www.microsoft.com/hwdev/download/respec/pnpbios.zip
     32  1.10     soren  * http://www.microsoft.com/hwdev/download/respec/biosclar.zip
     33  1.10     soren  * http://www.microsoft.com/hwdev/download/respec/devids.txt
     34   1.1  drochner  */
     35   1.1  drochner 
     36   1.1  drochner #include <sys/param.h>
     37   1.1  drochner #include <sys/systm.h>
     38   1.1  drochner #include <sys/device.h>
     39   1.1  drochner #include <sys/malloc.h>
     40   1.1  drochner #include <dev/isa/isareg.h>
     41   1.1  drochner #include <machine/isa_machdep.h>
     42   1.1  drochner #include <machine/segments.h>
     43   1.1  drochner #include <vm/vm.h>
     44   1.1  drochner #include <vm/vm_kern.h>
     45   1.1  drochner 
     46   1.1  drochner #include <arch/i386/pnpbios/pnpbiosvar.h>
     47   1.1  drochner 
     48   1.1  drochner #include "opt_pnpbiosverbose.h"
     49   1.5      matt #include "isadma.h"
     50   1.2   thorpej #include "locators.h"
     51   1.1  drochner 
     52   1.1  drochner struct pnpbios_softc {
     53   1.1  drochner 	struct device sc_dev;
     54   1.1  drochner 	isa_chipset_tag_t sc_ic;
     55   1.1  drochner };
     56   1.1  drochner 
     57   1.1  drochner static caddr_t pnpbios_find __P((void));
     58   1.1  drochner static int pnpbios_match __P((struct device *, struct cfdata *, void *));
     59   1.1  drochner static void pnpbios_attach __P((struct device *, struct device *, void *));
     60   1.1  drochner static void pnpbios_printres __P((struct pnpresources *));
     61   1.1  drochner static int pnpbios_print __P((void *, const char *));
     62   1.1  drochner static int pnpbios_getnumnodes __P((int *, size_t *));
     63   1.1  drochner static int pnpbios_getnode __P((int, int *, unsigned char *, size_t));
     64   1.1  drochner static void eisaid_to_string __P((unsigned char *, char *));
     65   1.2   thorpej static void pnpbios_attachnode __P((struct pnpbios_softc *, int,
     66   1.1  drochner 				    unsigned char *, size_t));
     67   1.1  drochner static int pnp_scan __P((unsigned char **, size_t, struct pnpresources *, int));
     68   1.1  drochner 
     69   1.2   thorpej static int pnpbios_submatch __P((struct device *, struct cfdata *, void *));
     70   1.2   thorpej 
     71   1.1  drochner extern int pnpbioscall __P((int));
     72   1.1  drochner 
     73   1.1  drochner struct cfattach pnpbios_ca = {
     74   1.1  drochner 	sizeof(struct pnpbios_softc), pnpbios_match, pnpbios_attach
     75   1.1  drochner };
     76   1.1  drochner 
     77   1.1  drochner /*
     78   1.1  drochner  * Private stack and return value buffer. Spec (1.0a, ch. 4.3) says that
     79   1.1  drochner  * 1024 bytes must be available to the BIOS function.
     80   1.1  drochner  */
     81   1.1  drochner #define PNPBIOS_BUFSIZE 4096
     82   1.1  drochner 
     83   1.1  drochner int pnpbios_enabled = 1;
     84   1.1  drochner size_t pnpbios_entry;
     85   1.1  drochner caddr_t pnpbios_scratchbuf;
     86   1.1  drochner 
     87   1.2   thorpej /*
     88   1.2   thorpej  * There can be only one of these, and the i386 ISA code needs to
     89   1.2   thorpej  * reference this.
     90   1.2   thorpej  */
     91   1.2   thorpej struct pnpbios_softc *pnpbios_softc;
     92   1.2   thorpej 
     93   1.1  drochner #define PNPBIOS_SIGNATURE ('$' | ('P' << 8) | ('n' << 16) | ('P' << 24))
     94   1.1  drochner 
     95   1.1  drochner static caddr_t
     96   1.1  drochner pnpbios_find()
     97   1.1  drochner {
     98   1.1  drochner 	caddr_t p, c;
     99   1.1  drochner 	unsigned char cksum;
    100   1.1  drochner 	size_t structlen;
    101   1.1  drochner 
    102   1.1  drochner 	for (p = (caddr_t)ISA_HOLE_VADDR(0xf0000);
    103   1.1  drochner 	     p <= (caddr_t)ISA_HOLE_VADDR(0xffff0);
    104   1.1  drochner 	     p += 16) {
    105   1.1  drochner 		if (*(int *)p != PNPBIOS_SIGNATURE)
    106   1.1  drochner 			continue;
    107   1.1  drochner 		structlen = *(unsigned char *)(p + 5);
    108   1.1  drochner 		if ((structlen < 0x21) ||
    109   1.1  drochner 		    ((p + structlen - 1) > (caddr_t)ISA_HOLE_VADDR(0xfffff)))
    110   1.1  drochner 			continue;
    111   1.1  drochner 
    112   1.1  drochner 		cksum = 0;
    113   1.1  drochner 		for (c = p; c < p + structlen; c++)
    114   1.1  drochner 			cksum += *(unsigned char *)c;
    115   1.1  drochner 		if (cksum != 0)
    116   1.1  drochner 			continue;
    117   1.1  drochner 
    118   1.1  drochner 		if (*(char *)(p + 4) != 0x10) {
    119   1.1  drochner 			printf("unknown version %x\n", *(char *)(p + 4));
    120   1.1  drochner 			continue;
    121   1.1  drochner 		}
    122   1.1  drochner 
    123   1.1  drochner 		return (p);
    124   1.1  drochner 	}
    125   1.1  drochner 
    126   1.1  drochner 	return (0);
    127   1.1  drochner }
    128   1.1  drochner 
    129   1.1  drochner int
    130   1.1  drochner pnpbios_probe()
    131   1.1  drochner {
    132   1.1  drochner 
    133   1.1  drochner 	return (pnpbios_find() != 0);
    134   1.1  drochner }
    135   1.1  drochner 
    136   1.1  drochner static int
    137   1.1  drochner pnpbios_match(parent, match, aux)
    138   1.1  drochner 	struct device *parent;
    139   1.1  drochner 	struct cfdata *match;
    140   1.1  drochner 	void *aux;
    141   1.1  drochner {
    142   1.1  drochner 	struct pnpbios_attach_args *paa = aux;
    143   1.1  drochner 
    144   1.1  drochner 	/* These are not the droids you're looking for. */
    145   1.1  drochner 	if (strcmp(paa->paa_busname, "pnpbios") != 0)
    146   1.1  drochner 		return (0);
    147   1.1  drochner 
    148   1.1  drochner 	/* There can be only one! */
    149   1.2   thorpej 	if (pnpbios_softc != NULL)
    150   1.1  drochner 		return (0);
    151   1.1  drochner 
    152   1.1  drochner 	return (pnpbios_enabled);
    153   1.1  drochner }
    154   1.1  drochner 
    155   1.1  drochner static caddr_t mapit __P((u_long, u_long, int));
    156   1.1  drochner 
    157   1.1  drochner static caddr_t
    158   1.1  drochner mapit(addr, len, prot)
    159   1.1  drochner 	u_long addr, len;
    160   1.1  drochner 	int prot;
    161   1.1  drochner {
    162   1.1  drochner 	u_long startpa, pa, endpa;
    163   1.1  drochner 	vaddr_t startva, va;
    164   1.1  drochner 
    165   1.1  drochner 	pa = startpa = i386_trunc_page(addr);
    166   1.1  drochner 	endpa = i386_round_page(addr + len);
    167   1.1  drochner 
    168   1.1  drochner 	va = startva = uvm_km_valloc(kernel_map, endpa - startpa);
    169   1.1  drochner 	if (!startva)
    170   1.1  drochner 		return (0);
    171   1.1  drochner 	for (; pa < endpa; pa += NBPG, va += NBPG)
    172   1.1  drochner 		pmap_kenter_pa(va, pa, prot);
    173   1.1  drochner 
    174   1.1  drochner 	return ((caddr_t)(startva + (addr - startpa)));
    175   1.1  drochner }
    176   1.1  drochner 
    177   1.1  drochner static void
    178   1.1  drochner pnpbios_attach(parent, self, aux)
    179   1.1  drochner 	struct device *parent, *self;
    180   1.1  drochner 	void *aux;
    181   1.1  drochner {
    182   1.1  drochner 	struct pnpbios_softc *sc = (struct pnpbios_softc *)self;
    183   1.1  drochner 	struct pnpbios_attach_args *paa = aux;
    184   1.1  drochner 	caddr_t p;
    185   1.1  drochner 	unsigned int codepbase, datapbase;
    186   1.1  drochner 	caddr_t codeva, datava;
    187   1.1  drochner 	extern char pnpbiostramp[], epnpbiostramp[];
    188   1.1  drochner 	int res, num, i, size, idx;
    189   1.1  drochner 	unsigned char *buf;
    190   1.1  drochner 
    191   1.2   thorpej 	pnpbios_softc = sc;
    192   1.1  drochner 	sc->sc_ic = paa->paa_ic;
    193   1.1  drochner 
    194   1.5      matt #if NISADMA > 0
    195   1.1  drochner 	isa_dmainit(sc->sc_ic, I386_BUS_SPACE_IO, &isa_bus_dma_tag, self);
    196   1.5      matt #endif
    197   1.1  drochner 
    198   1.1  drochner 	p = pnpbios_find();
    199   1.1  drochner 	if (!p)
    200   1.1  drochner 		panic("pnpbios_attach: disappeared");
    201   1.1  drochner 
    202   1.1  drochner 	codepbase = *(unsigned int *)(p + 0x13);
    203   1.1  drochner 	datapbase = *(unsigned int *)(p + 0x1d);
    204   1.1  drochner 	pnpbios_entry = *(unsigned short *)(p + 0x11);
    205   1.1  drochner 
    206   1.1  drochner #ifdef PNPBIOSVERBOSE
    207   1.1  drochner 	printf(": code %x, data %x, entry %x\n%s",
    208   1.1  drochner 		codepbase, datapbase, pnpbios_entry, self->dv_xname);
    209   1.1  drochner #endif
    210   1.1  drochner 
    211   1.1  drochner 	codeva = mapit(codepbase, 0x10000,
    212   1.1  drochner 		VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
    213   1.1  drochner 	datava = mapit(datapbase, 0x10000,
    214   1.1  drochner 		VM_PROT_READ | VM_PROT_WRITE);
    215   1.1  drochner 	if (codeva == 0 || datava == 0) {
    216   1.1  drochner 		printf("no vm for mapping\n");
    217   1.1  drochner 		return;
    218   1.1  drochner 	}
    219   1.1  drochner 	pnpbios_scratchbuf = malloc(PNPBIOS_BUFSIZE, M_DEVBUF, M_NOWAIT);
    220   1.1  drochner 
    221   1.1  drochner 	setsegment(&gdt[GPNPBIOSCODE_SEL].sd, codeva, 0xffff,
    222   1.1  drochner 		   SDT_MEMERA, SEL_KPL, 0, 0);
    223   1.1  drochner 	setsegment(&gdt[GPNPBIOSDATA_SEL].sd, datava, 0xffff,
    224   1.1  drochner 		   SDT_MEMRWA, SEL_KPL, 0, 0);
    225   1.1  drochner 	setsegment(&gdt[GPNPBIOSSCRATCH_SEL].sd,
    226   1.1  drochner 		   pnpbios_scratchbuf, PNPBIOS_BUFSIZE - 1,
    227   1.1  drochner 		   SDT_MEMRWA, SEL_KPL, 0, 0);
    228   1.1  drochner 	setsegment(&gdt[GPNPBIOSTRAMP_SEL].sd,
    229   1.1  drochner 		   pnpbiostramp, epnpbiostramp - pnpbiostramp - 1,
    230   1.1  drochner 		   SDT_MEMERA, SEL_KPL, 1, 0);
    231   1.1  drochner 
    232   1.1  drochner 	res = pnpbios_getnumnodes(&num, &size);
    233   1.1  drochner 	if (res) {
    234   1.1  drochner 		printf("pnpbios_getnumnodes: error %d\n", res);
    235   1.1  drochner 		return;
    236   1.1  drochner 	}
    237   1.1  drochner 
    238   1.1  drochner 	printf(": %d nodes, max len %d\n", num, size);
    239   1.1  drochner 	buf = malloc(size, M_DEVBUF, M_NOWAIT);
    240   1.1  drochner 
    241   1.1  drochner 	idx = 0;
    242   1.6  drochner 	for (i = 0; i < num && idx != 0xff; i++) {
    243   1.3  drochner 		int node = idx;
    244   1.1  drochner 		res = pnpbios_getnode(1, &idx, buf, size);
    245   1.1  drochner 		if (res) {
    246   1.1  drochner 			printf("pnpbios_getnode: error %d\n", res);
    247   1.1  drochner 			continue;
    248   1.1  drochner 		}
    249   1.3  drochner 		if (buf[2] != node)
    250   1.4     soren 			printf("node idx: called %d, got %d\n", node, buf[2]);
    251   1.3  drochner 		pnpbios_attachnode(sc, node, buf, buf[0] + (buf[1] << 8));
    252   1.1  drochner 	}
    253   1.6  drochner 	if (i != num)
    254   1.6  drochner 		printf("got only %d nodes\n", i);
    255   1.1  drochner 	if (idx != 0xff)
    256   1.1  drochner 		printf("last idx=%x\n", idx);
    257   1.1  drochner 
    258   1.1  drochner 	free(buf, M_DEVBUF);
    259   1.1  drochner }
    260   1.1  drochner 
    261   1.1  drochner static int
    262   1.1  drochner pnpbios_getnumnodes(nump, sizep)
    263   1.1  drochner 	int *nump;
    264   1.1  drochner 	size_t *sizep;
    265   1.1  drochner {
    266   1.1  drochner 	int res;
    267   1.1  drochner 	short *help = (short *)(pnpbios_scratchbuf + PNPBIOS_BUFSIZE);
    268   1.1  drochner 
    269   1.1  drochner 	*--help = GSEL(GPNPBIOSDATA_SEL, SEL_KPL);
    270   1.1  drochner 	*--help = GSEL(GPNPBIOSSCRATCH_SEL, SEL_KPL);
    271   1.1  drochner 	*--help = 2; /* buffer offset for node size */
    272   1.1  drochner 	*--help = GSEL(GPNPBIOSSCRATCH_SEL, SEL_KPL);
    273   1.1  drochner 	*--help = 0; /* buffer offset for numnodes */
    274   1.1  drochner 	*--help = 0; /* GET_NUM_NODES */
    275   1.1  drochner 
    276   1.1  drochner 	res = pnpbioscall(((caddr_t)help) - pnpbios_scratchbuf);
    277   1.1  drochner 	if (res)
    278   1.1  drochner 		return (res);
    279   1.1  drochner 
    280   1.1  drochner 	*nump = *(short *)(pnpbios_scratchbuf + 0);
    281   1.1  drochner 	*sizep = *(short *)(pnpbios_scratchbuf + 2);
    282   1.1  drochner 	return (0);
    283   1.1  drochner }
    284   1.1  drochner 
    285   1.1  drochner static int
    286   1.1  drochner pnpbios_getnode(flags, idxp, buf, len)
    287   1.1  drochner 	int flags;
    288   1.1  drochner 	int *idxp;
    289   1.1  drochner 	unsigned char *buf;
    290   1.1  drochner 	size_t len;
    291   1.1  drochner {
    292   1.1  drochner 	int res;
    293   1.1  drochner 	short *help = (short *)(pnpbios_scratchbuf + PNPBIOS_BUFSIZE);
    294   1.1  drochner 
    295   1.1  drochner 	*--help = GSEL(GPNPBIOSDATA_SEL, SEL_KPL);
    296   1.1  drochner 	*--help = flags;
    297   1.1  drochner 	*--help = GSEL(GPNPBIOSSCRATCH_SEL, SEL_KPL);
    298   1.1  drochner 	*--help = 2; /* buffer offset for node data */
    299   1.1  drochner 	*--help = GSEL(GPNPBIOSSCRATCH_SEL, SEL_KPL);
    300   1.1  drochner 	*--help = 0; /* buffer offset for index in/out */
    301   1.1  drochner 	*--help = 1; /* GET_DEVICE_NODE */
    302   1.1  drochner 
    303   1.1  drochner 	*(short *)(pnpbios_scratchbuf + 0) = *idxp;
    304   1.1  drochner 
    305   1.1  drochner 	res = pnpbioscall(((caddr_t)help) - pnpbios_scratchbuf);
    306   1.1  drochner 	if (res)
    307   1.1  drochner 		return (res);
    308   1.1  drochner 
    309   1.1  drochner 	*idxp = *(short *)(pnpbios_scratchbuf + 0);
    310   1.1  drochner 	bcopy(pnpbios_scratchbuf + 2, buf, len);
    311   1.1  drochner 	return (0);
    312   1.1  drochner }
    313   1.1  drochner 
    314   1.1  drochner static void
    315   1.1  drochner eisaid_to_string(id, s)
    316   1.1  drochner 	unsigned char *id;
    317   1.1  drochner 	char *s;
    318   1.1  drochner {
    319   1.1  drochner 	static char hex[] = "0123456789ABCDEF";
    320   1.1  drochner 
    321   1.1  drochner 	*s++ = 'A' + (id[0] >> 2) - 1;
    322   1.1  drochner 	*s++ = 'A' + ((id[0] & 3) << 3) + (id[1] >> 5) - 1;
    323   1.1  drochner 	*s++ = 'A' + (id[1] & 0x1f) - 1;
    324   1.1  drochner 	*s++ = hex[id[2] >> 4];
    325   1.1  drochner 	*s++ = hex[id[2] & 0x0f];
    326   1.1  drochner 	*s++ = hex[id[3] >> 4];
    327   1.1  drochner 	*s++ = hex[id[3] & 0x0f];
    328   1.1  drochner 	*s = '\0';
    329   1.1  drochner }
    330   1.1  drochner 
    331   1.1  drochner static void
    332   1.1  drochner pnpbios_printres(r)
    333   1.1  drochner 	struct pnpresources *r;
    334   1.1  drochner {
    335   1.1  drochner 	struct pnp_mem *mem;
    336   1.1  drochner 	struct pnp_io *io;
    337   1.1  drochner 	struct pnp_irq *irq;
    338   1.1  drochner 	struct pnp_dma *dma;
    339   1.1  drochner 	int p = 0;
    340   1.1  drochner 
    341   1.1  drochner 	mem = SIMPLEQ_FIRST(&r->mem);
    342   1.1  drochner 	if (mem) {
    343   1.1  drochner 		printf("mem");
    344   1.1  drochner 		do {
    345   1.1  drochner 			printf(" %x", mem->minbase);
    346   1.1  drochner 			if (mem->len > 1)
    347   1.1  drochner 				printf("-%x", mem->minbase + mem->len - 1);
    348   1.1  drochner 		} while ((mem = SIMPLEQ_NEXT(mem, next)));
    349   1.1  drochner 		p++;
    350   1.1  drochner 	}
    351   1.1  drochner 	io = SIMPLEQ_FIRST(&r->io);
    352   1.1  drochner 	if (io) {
    353   1.1  drochner 		if (p++)
    354   1.1  drochner 			printf(", ");
    355   1.1  drochner 		printf("io");
    356   1.1  drochner 		do {
    357   1.1  drochner 			printf(" %x", io->minbase);
    358   1.1  drochner 			if (io->len > 1)
    359   1.1  drochner 				printf("-%x", io->minbase + io->len - 1);
    360   1.1  drochner 		} while ((io = SIMPLEQ_NEXT(io, next)));
    361   1.1  drochner 	}
    362   1.1  drochner 	irq = SIMPLEQ_FIRST(&r->irq);
    363   1.1  drochner 	if (irq) {
    364   1.1  drochner 		if (p++)
    365   1.1  drochner 			printf(", ");
    366   1.1  drochner 		printf("irq");
    367   1.1  drochner 		do {
    368   1.1  drochner 			printf(" %d", ffs(irq->mask) - 1);
    369   1.1  drochner 		} while ((irq = SIMPLEQ_NEXT(irq, next)));
    370   1.1  drochner 	}
    371   1.1  drochner 	dma = SIMPLEQ_FIRST(&r->dma);
    372   1.1  drochner 	if (dma) {
    373   1.1  drochner 		if (p)
    374   1.1  drochner 			printf(", ");
    375   1.1  drochner 		printf("dma");
    376   1.1  drochner 		do {
    377   1.1  drochner 			printf(" %d", ffs(dma->mask) - 1);
    378   1.1  drochner 		} while ((dma = SIMPLEQ_NEXT(dma, next)));
    379   1.1  drochner 	}
    380   1.1  drochner }
    381   1.1  drochner 
    382   1.1  drochner static int
    383   1.1  drochner pnpbios_print(aux, pnp)
    384   1.1  drochner 	void *aux;
    385   1.1  drochner 	const char *pnp;
    386   1.1  drochner {
    387   1.1  drochner 	struct pnpbiosdev_attach_args *aa = aux;
    388   1.1  drochner 
    389   1.1  drochner 	if (pnp)
    390   1.1  drochner 		return (QUIET);
    391   1.1  drochner 
    392   1.2   thorpej 	printf(" index %d (%s", aa->idx, aa->primid);
    393   1.1  drochner 	if (aa->resc->longname)
    394   1.1  drochner 		printf(", %s", aa->resc->longname);
    395   1.1  drochner 	if (aa->idstr != aa->primid)
    396   1.1  drochner 		printf(", attached as %s", aa->idstr);
    397   1.2   thorpej 	printf(")");
    398   1.2   thorpej 
    399   1.2   thorpej 	return (0);
    400   1.2   thorpej }
    401   1.2   thorpej 
    402   1.2   thorpej void
    403   1.2   thorpej pnpbios_print_devres(dev, aa)
    404   1.2   thorpej 	struct device *dev;
    405   1.2   thorpej 	struct pnpbiosdev_attach_args *aa;
    406   1.2   thorpej {
    407   1.2   thorpej 
    408   1.2   thorpej 	printf("%s: ", dev->dv_xname);
    409   1.1  drochner 	pnpbios_printres(aa->resc);
    410   1.2   thorpej 	printf("\n");
    411   1.2   thorpej }
    412   1.1  drochner 
    413   1.2   thorpej static int
    414   1.2   thorpej pnpbios_submatch(parent, match, aux)
    415   1.2   thorpej 	struct device *parent;
    416   1.2   thorpej 	struct cfdata *match;
    417   1.2   thorpej 	void *aux;
    418   1.2   thorpej {
    419   1.2   thorpej 	struct pnpbiosdev_attach_args *aa = aux;
    420   1.2   thorpej 
    421   1.2   thorpej 	if (match->cf_loc[PNPBIOSCF_INDEX] != PNPBIOSCF_INDEX_DEFAULT &&
    422   1.2   thorpej 	    match->cf_loc[PNPBIOSCF_INDEX] != aa->idx)
    423   1.2   thorpej 		return (0);
    424   1.2   thorpej 
    425   1.2   thorpej 	return ((*match->cf_attach->ca_match)(parent, match, aux));
    426   1.1  drochner }
    427   1.1  drochner 
    428   1.1  drochner static void
    429   1.2   thorpej pnpbios_attachnode(sc, idx, buf, len)
    430   1.1  drochner 	struct pnpbios_softc *sc;
    431   1.2   thorpej 	int idx;
    432   1.1  drochner 	unsigned char *buf;
    433   1.1  drochner 	size_t len;
    434   1.1  drochner {
    435   1.1  drochner 	char idstr[8];
    436   1.1  drochner 	unsigned char *p;
    437   1.1  drochner 	int res;
    438   1.1  drochner 	struct pnpresources r, s;
    439   1.1  drochner 	int i;
    440   1.1  drochner 	struct pnpbiosdev_attach_args aa;
    441   1.1  drochner 	struct pnp_compatid *compatid;
    442   1.1  drochner 
    443   1.1  drochner 	eisaid_to_string(buf + 3, idstr);
    444   1.1  drochner 	p = buf + 12;
    445   1.1  drochner 
    446   1.1  drochner 	res = pnp_scan(&p, len - 12, &r, 0);
    447   1.1  drochner 	if (res < 0) {
    448   1.1  drochner 		printf("error in config data\n");
    449   1.1  drochner 		goto dump;
    450   1.1  drochner 	}
    451   1.1  drochner 
    452   1.1  drochner 	/*
    453   1.1  drochner 	 * the following is consistency check only for now
    454   1.1  drochner 	 */
    455   1.1  drochner 	res = pnp_scan(&p, len - (p - buf), &s, 0);
    456   1.1  drochner 	if (res < 0) {
    457   1.1  drochner 		printf("error in possible configuration\n");
    458   1.1  drochner 		goto dump;
    459   1.1  drochner 	}
    460   1.1  drochner 
    461   1.1  drochner 	res = pnp_scan(&p, len - (p - buf), &s, 0);
    462   1.1  drochner 	if (res < 0) {
    463   1.1  drochner 		printf("error in compatible ID\n");
    464   1.1  drochner 		goto dump;
    465   1.1  drochner 	}
    466   1.1  drochner 
    467   1.1  drochner 	if (p != buf + len) {
    468   1.8  drochner 		printf("%s: length mismatch in node %d: used %d of %d Bytes\n",
    469   1.8  drochner 		       sc->sc_dev.dv_xname, idx, p - buf, len);
    470   1.8  drochner 		if (p > buf + len) {
    471   1.8  drochner 			/* XXX shouldn't happen - pnp_scan should catch it */
    472   1.8  drochner 			goto dump;
    473   1.8  drochner 		}
    474   1.8  drochner 		/* Crappy BIOS: Buffer is not fully used. Be generous. */
    475   1.8  drochner 	}
    476   1.8  drochner 
    477   1.8  drochner 	if (r.nummem + r.numio + r.numirq + r.numdma == 0) {
    478   1.8  drochner #ifdef PNPBIOSVERBOSE
    479   1.8  drochner 		printf("%s", idstr);
    480   1.8  drochner 		if (r.longname)
    481   1.8  drochner 			printf(", %s", r.longname);
    482   1.8  drochner 		compatid = s.compatids;
    483   1.8  drochner 		while (compatid) {
    484   1.8  drochner 			printf(", %s", compatid->idstr);
    485   1.8  drochner 			compatid = compatid->next;
    486   1.8  drochner 		}
    487   1.8  drochner 		printf(" at %s index %d disabled\n", sc->sc_dev.dv_xname, idx);
    488   1.8  drochner #endif
    489   1.8  drochner 		return;
    490   1.1  drochner 	}
    491   1.1  drochner 
    492   1.1  drochner 	aa.pbt = 0; /* XXX placeholder */
    493   1.2   thorpej 	aa.idx = idx;
    494   1.1  drochner 	aa.resc = &r;
    495   1.1  drochner 	aa.ic = sc->sc_ic;
    496   1.1  drochner 	aa.primid = idstr;
    497   1.1  drochner 
    498   1.1  drochner 	/* first try the specific device ID */
    499   1.1  drochner 	aa.idstr = idstr;
    500   1.2   thorpej 	if (config_found_sm((struct device *)sc, &aa, pnpbios_print,
    501   1.2   thorpej 	    pnpbios_submatch))
    502   1.1  drochner 		return;
    503   1.1  drochner 
    504   1.1  drochner 	/* if no driver was found, try compatible IDs */
    505   1.1  drochner 	compatid = s.compatids;
    506   1.1  drochner 	while (compatid) {
    507   1.1  drochner 		aa.idstr = compatid->idstr;
    508   1.2   thorpej 		if (config_found_sm((struct device *)sc, &aa, pnpbios_print,
    509   1.2   thorpej 		    pnpbios_submatch))
    510   1.1  drochner 			return;
    511   1.1  drochner 		compatid = compatid->next;
    512   1.1  drochner 	}
    513   1.1  drochner 
    514   1.1  drochner #ifdef PNPBIOSVERBOSE
    515   1.1  drochner 	printf("%s", idstr);
    516   1.1  drochner 	if (r.longname)
    517   1.1  drochner 		printf(", %s", r.longname);
    518   1.1  drochner 	compatid = s.compatids;
    519   1.1  drochner 	while (compatid) {
    520   1.1  drochner 		printf(", %s", compatid->idstr);
    521   1.1  drochner 		compatid = compatid->next;
    522   1.1  drochner 	}
    523   1.1  drochner 	printf(" (");
    524   1.1  drochner 	pnpbios_printres(&r);
    525   1.2   thorpej 	printf(") at %s index %d ignored\n", sc->sc_dev.dv_xname, idx);
    526   1.1  drochner #endif
    527   1.1  drochner 
    528   1.1  drochner 	return;
    529   1.1  drochner 
    530   1.1  drochner 	/* XXX should free ressource lists */
    531   1.1  drochner 
    532   1.1  drochner dump:
    533   1.1  drochner 	for (i = 0; i < len; i++)
    534   1.1  drochner 		printf(" %02x", buf[i]);
    535   1.1  drochner 	printf("\n");
    536   1.1  drochner }
    537   1.1  drochner 
    538   1.1  drochner static int pnp_compatid __P((struct pnpresources *, unsigned char *, size_t));
    539   1.1  drochner static int pnp_newirq __P((struct pnpresources *, unsigned char *, size_t));
    540   1.1  drochner static int pnp_newdma __P((struct pnpresources *, unsigned char *, size_t));
    541   1.1  drochner static int pnp_newioport __P((struct pnpresources *, unsigned char *, size_t));
    542   1.8  drochner static int pnp_newfixedioport __P((struct pnpresources *, unsigned char *, size_t));
    543   1.1  drochner 
    544   1.1  drochner /*
    545   1.1  drochner  * small ressource types (beginning with 1)
    546   1.1  drochner  */
    547   1.1  drochner static struct{
    548   1.1  drochner 	int (*handler) __P((struct pnpresources *, unsigned char *, size_t));
    549   1.1  drochner 	int minlen, maxlen;
    550   1.1  drochner } smallrescs[] = {
    551   1.1  drochner 	{0, 2, 2}, /* PnP version number */
    552   1.1  drochner 	{0, 5, 6}, /* logical device id */
    553   1.1  drochner 	{pnp_compatid, 4, 4}, /* compatible device id */
    554   1.1  drochner 	{pnp_newirq, 2, 3}, /* irq  descriptor */
    555   1.1  drochner 	{pnp_newdma, 2, 2}, /* dma  descriptor */
    556   1.1  drochner 	{0, 0, 1}, /* start dep */
    557   1.1  drochner 	{0, 0, 0}, /* end dep */
    558   1.1  drochner 	{pnp_newioport, 7, 7}, /* io descriptor */
    559   1.8  drochner 	{pnp_newfixedioport, 3, 3}, /* fixed io descriptor */
    560   1.1  drochner 	{0, -1, -1}, /* reserved */
    561   1.1  drochner 	{0, -1, -1},
    562   1.1  drochner 	{0, -1, -1},
    563   1.1  drochner 	{0, -1, -1},
    564   1.1  drochner 	{0, 1, 7}, /* vendor defined */
    565   1.1  drochner 	{0, 1, 1} /* end */
    566   1.1  drochner };
    567   1.1  drochner 
    568   1.1  drochner #define NEXTBYTE(p) (*(p)++)
    569   1.1  drochner 
    570   1.1  drochner static int
    571   1.1  drochner pnp_scan(bufp, maxlen, r, in_depends)
    572   1.1  drochner 	unsigned char **bufp;
    573   1.1  drochner 	size_t maxlen;
    574   1.1  drochner 	struct pnpresources *r;
    575   1.1  drochner 	int in_depends;
    576   1.1  drochner {
    577   1.1  drochner 	unsigned char *p = *bufp;
    578   1.1  drochner 	int tag, type, len;
    579   1.1  drochner 	char *idstr;
    580   1.1  drochner 	int i;
    581   1.1  drochner 	struct pnp_mem *mem;
    582   1.1  drochner 
    583   1.1  drochner 	bzero(r, sizeof(*r));
    584   1.1  drochner 	SIMPLEQ_INIT(&r->mem);
    585   1.1  drochner 	SIMPLEQ_INIT(&r->io);
    586   1.1  drochner 	SIMPLEQ_INIT(&r->irq);
    587   1.1  drochner 	SIMPLEQ_INIT(&r->dma);
    588   1.1  drochner 
    589   1.1  drochner 	for (;;) {
    590   1.1  drochner 		if (p >= *bufp + maxlen) {
    591   1.1  drochner 			printf("pnp_scanresources: end of buffer\n");
    592   1.1  drochner 			return (-1);
    593   1.1  drochner 		}
    594   1.1  drochner 		tag = NEXTBYTE(p);
    595   1.1  drochner 
    596   1.1  drochner 		if (tag & 0x80) { /* long tag */
    597   1.1  drochner 			type = tag & 0x7f;
    598   1.1  drochner 			len = NEXTBYTE(p);
    599   1.1  drochner 			len |= NEXTBYTE(p) << 8;
    600   1.1  drochner 
    601   1.1  drochner 			switch (type) {
    602   1.1  drochner 			case 0x01: /* memory descriptor */
    603   1.1  drochner 				if (len != 9) {
    604   1.1  drochner 					printf("pnp_scan: bad mem desc\n");
    605   1.1  drochner 					return (-1);
    606   1.1  drochner 				}
    607   1.1  drochner 
    608   1.1  drochner 				mem = malloc(sizeof(struct pnp_mem),
    609   1.1  drochner 					     M_DEVBUF, M_WAITOK);
    610   1.1  drochner 				mem->flags = NEXTBYTE(p);
    611   1.1  drochner 				mem->minbase = NEXTBYTE(p) << 8;
    612   1.1  drochner 				mem->minbase |= NEXTBYTE(p) << 16;
    613   1.1  drochner 				mem->maxbase = NEXTBYTE(p) << 8;
    614   1.1  drochner 				mem->maxbase |= NEXTBYTE(p) << 16;
    615   1.1  drochner 				mem->align = NEXTBYTE(p);
    616   1.1  drochner 				mem->align |= NEXTBYTE(p) << 8;
    617   1.1  drochner 				if (mem->align == 0)
    618   1.1  drochner 					mem->align = 0x10000;
    619   1.1  drochner 				mem->len = NEXTBYTE(p) << 8;
    620   1.1  drochner 				mem->len |= NEXTBYTE(p) << 16;
    621   1.8  drochner 				goto gotmem;
    622   1.1  drochner 			case 0x02:
    623   1.1  drochner 				if (in_depends)
    624   1.1  drochner 					printf("ID in dep?\n");
    625   1.1  drochner 				idstr = malloc(len + 1, M_DEVBUF, M_NOWAIT);
    626   1.1  drochner 				for (i = 0; i < len; i++)
    627   1.1  drochner 					idstr[i] = NEXTBYTE(p);
    628   1.1  drochner 				idstr[len] = '\0';
    629   1.9  drochner 				if (idstr[0] == '\0') {
    630   1.9  drochner 					/* disabled device */
    631   1.9  drochner 					free(idstr, M_DEVBUF);
    632   1.9  drochner 					break;
    633   1.9  drochner 				}
    634   1.1  drochner 				r->longname = idstr;
    635   1.7  drochner 				break;
    636   1.7  drochner 			case 0x05:  /* 32bit memory descriptor */
    637   1.7  drochner 				if (len != 17) {
    638   1.7  drochner 					printf("pnp_scan: bad mem32 desc\n");
    639   1.7  drochner 					return (-1);
    640   1.7  drochner 				}
    641   1.7  drochner 
    642   1.7  drochner 				mem = malloc(sizeof(struct pnp_mem),
    643   1.7  drochner 					     M_DEVBUF, M_WAITOK);
    644   1.7  drochner 				mem->flags = NEXTBYTE(p);
    645   1.7  drochner 				mem->minbase = NEXTBYTE(p);
    646   1.7  drochner 				mem->minbase |= NEXTBYTE(p) << 8;
    647   1.7  drochner 				mem->minbase |= NEXTBYTE(p) << 16;
    648   1.7  drochner 				mem->minbase |= NEXTBYTE(p) << 24;
    649   1.7  drochner 				mem->maxbase = NEXTBYTE(p);
    650   1.7  drochner 				mem->maxbase |= NEXTBYTE(p) << 8;
    651   1.7  drochner 				mem->maxbase |= NEXTBYTE(p) << 16;
    652   1.7  drochner 				mem->maxbase |= NEXTBYTE(p) << 24;
    653   1.7  drochner 				mem->align = NEXTBYTE(p);
    654   1.7  drochner 				mem->align |= NEXTBYTE(p) << 8;
    655   1.7  drochner 				mem->align |= NEXTBYTE(p) << 16;
    656   1.7  drochner 				mem->align |= NEXTBYTE(p) << 24;
    657   1.7  drochner 				mem->len = NEXTBYTE(p);
    658   1.7  drochner 				mem->len |= NEXTBYTE(p) << 8;
    659   1.7  drochner 				mem->len |= NEXTBYTE(p) << 16;
    660   1.7  drochner 				mem->len |= NEXTBYTE(p) << 24;
    661   1.8  drochner 				goto gotmem;
    662   1.1  drochner 			case 0x06: /* 32bit fixed memory descriptor */
    663   1.1  drochner 				if (len != 9) {
    664   1.1  drochner 					printf("pnp_scan: bad mem32 desc\n");
    665   1.1  drochner 					return (-1);
    666   1.1  drochner 				}
    667   1.1  drochner 
    668   1.1  drochner 				mem = malloc(sizeof(struct pnp_mem),
    669   1.1  drochner 					     M_DEVBUF, M_WAITOK);
    670   1.1  drochner 				mem->flags = NEXTBYTE(p);
    671   1.1  drochner 				mem->minbase = NEXTBYTE(p);
    672   1.1  drochner 				mem->minbase |= NEXTBYTE(p) << 8;
    673   1.1  drochner 				mem->minbase |= NEXTBYTE(p) << 16;
    674   1.1  drochner 				mem->minbase |= NEXTBYTE(p) << 24;
    675   1.1  drochner 				mem->maxbase = mem->minbase;
    676   1.1  drochner 				mem->align = 0;
    677   1.1  drochner 				mem->len = NEXTBYTE(p);
    678   1.1  drochner 				mem->len |= NEXTBYTE(p) << 8;
    679   1.1  drochner 				mem->len |= NEXTBYTE(p) << 16;
    680   1.1  drochner 				mem->len |= NEXTBYTE(p) << 24;
    681   1.8  drochner gotmem:
    682   1.8  drochner 				if (mem->len == 0) { /* disabled */
    683   1.1  drochner #ifdef PNPBIOSDEBUG
    684   1.1  drochner 					printf("ZERO mem descriptor\n");
    685   1.1  drochner #endif
    686   1.8  drochner 					free(mem, M_DEVBUF);
    687   1.8  drochner 					break;
    688   1.8  drochner 				}
    689   1.8  drochner 				SIMPLEQ_INSERT_TAIL(&r->mem, mem, next);
    690   1.8  drochner 				r->nummem++;
    691   1.1  drochner 				break;
    692   1.1  drochner 			default:
    693   1.1  drochner 				printf("ignoring long tag %x\n", type);
    694   1.1  drochner 				while (len--)
    695   1.1  drochner 					(void) NEXTBYTE(p);
    696   1.1  drochner 			}
    697   1.1  drochner 		} else {
    698   1.1  drochner 			unsigned char tmpbuf[7];
    699   1.1  drochner 			int i;
    700   1.1  drochner 
    701   1.1  drochner 			type = (tag >> 3) & 0x0f;
    702   1.1  drochner 			len = tag & 0x07;
    703   1.1  drochner 
    704   1.1  drochner 			if (type == 0 ||
    705   1.1  drochner 			    len < smallrescs[type - 1].minlen ||
    706   1.1  drochner 			    len > smallrescs[type - 1].maxlen) {
    707   1.1  drochner 				printf("pnp_scan: bad small resource\n");
    708   1.1  drochner 				return (-1);
    709   1.1  drochner 			}
    710   1.1  drochner 			for (i = 0; i < len; i++)
    711   1.1  drochner 				tmpbuf[i] = NEXTBYTE(p);
    712   1.1  drochner 
    713   1.1  drochner 			if (type == 0x0f) { /* end mark */
    714   1.1  drochner 				if (in_depends) {
    715   1.1  drochner 					printf("end in dep?\n");
    716   1.1  drochner 					return (-1);
    717   1.1  drochner 				}
    718   1.1  drochner 				break;
    719   1.1  drochner 			}
    720   1.1  drochner 			if (type == 0x06) { /* start dep */
    721   1.1  drochner 				struct pnpresources *new, *last;
    722   1.1  drochner 				int res;
    723   1.1  drochner 
    724   1.1  drochner 				if (r->dependant_link) {
    725   1.1  drochner 					printf("second dep?\n");
    726   1.1  drochner 					return (-1);
    727   1.1  drochner 				}
    728   1.1  drochner 
    729   1.1  drochner 				if (in_depends) {
    730   1.1  drochner 					*bufp = p;
    731   1.1  drochner 					return (1);
    732   1.1  drochner 				}
    733   1.1  drochner 
    734   1.1  drochner 				last = r;
    735   1.1  drochner 				do {
    736   1.1  drochner 					new = malloc(sizeof(*new),
    737   1.1  drochner 						     M_DEVBUF, M_NOWAIT);
    738   1.1  drochner 
    739   1.1  drochner 					res = pnp_scan(&p, maxlen - (p - *bufp),
    740   1.1  drochner 						       new, 1);
    741   1.1  drochner 					if (res < 0) {
    742   1.1  drochner 				printf("error in dependant function\n");
    743   1.1  drochner 						free(new, M_DEVBUF);
    744   1.1  drochner 						return (-1);
    745   1.1  drochner 					}
    746   1.1  drochner 
    747   1.1  drochner 					last->dependant_link = new;
    748   1.1  drochner 					last = new;
    749   1.1  drochner 				} while (res > 0);
    750   1.1  drochner 				continue;
    751   1.1  drochner 			}
    752   1.1  drochner 			if (type == 0x07) { /* end dep */
    753   1.1  drochner 				if (!in_depends) {
    754   1.1  drochner 					printf("end dep?\n");
    755   1.1  drochner 					return (-1);
    756   1.1  drochner 				}
    757   1.1  drochner 				break;
    758   1.1  drochner 			}
    759   1.1  drochner 
    760   1.1  drochner 			if (!smallrescs[type - 1].handler)
    761   1.1  drochner 				printf("ignoring short tag %x\n", type);
    762   1.1  drochner 			else
    763   1.1  drochner 				if ((*smallrescs[type - 1].handler)(r, tmpbuf,
    764   1.1  drochner 								    len))
    765   1.1  drochner 					return (-1);
    766   1.1  drochner 		}
    767   1.1  drochner 	}
    768   1.1  drochner 	*bufp = p;
    769   1.1  drochner 	return (0);
    770   1.1  drochner }
    771   1.1  drochner 
    772   1.1  drochner static int
    773   1.1  drochner pnp_newirq(r, buf, len)
    774   1.1  drochner 	struct pnpresources *r;
    775   1.1  drochner 	unsigned char *buf;
    776   1.1  drochner 	size_t len;
    777   1.1  drochner {
    778   1.1  drochner 	struct pnp_irq *irq;
    779   1.1  drochner 
    780   1.8  drochner 	if (buf[0] == 0 && buf[1] == 0) { /* disabled */
    781   1.8  drochner #ifdef PNPBIOSDEBUG
    782   1.8  drochner 		printf("ZERO irq descriptor\n");
    783   1.8  drochner #endif
    784   1.8  drochner 		return (0);
    785   1.8  drochner 	}
    786   1.1  drochner 	irq = malloc(sizeof(struct pnp_irq), M_DEVBUF, M_NOWAIT);
    787   1.1  drochner 	irq->mask = buf[0] | (buf[1] << 8);
    788   1.1  drochner 	if (len > 2)
    789   1.1  drochner 		irq->flags = buf[2];
    790   1.1  drochner 	else
    791   1.1  drochner 		irq->flags = 0x01;
    792   1.1  drochner 	SIMPLEQ_INSERT_TAIL(&r->irq, irq, next);
    793   1.1  drochner 	r->numirq++;
    794   1.1  drochner 	return (0);
    795   1.1  drochner }
    796   1.1  drochner 
    797   1.1  drochner static int
    798   1.1  drochner pnp_newdma(r, buf, len)
    799   1.1  drochner 	struct pnpresources *r;
    800   1.1  drochner 	unsigned char *buf;
    801   1.1  drochner 	size_t len;
    802   1.1  drochner {
    803   1.1  drochner 	struct pnp_dma *dma;
    804   1.1  drochner 
    805   1.8  drochner 	if (buf[0] == 0) { /* disabled */
    806   1.8  drochner #ifdef PNPBIOSDEBUG
    807   1.8  drochner 		printf("ZERO dma descriptor\n");
    808   1.8  drochner #endif
    809   1.8  drochner 		return (0);
    810   1.8  drochner 	}
    811   1.1  drochner 	dma = malloc(sizeof(struct pnp_dma), M_DEVBUF, M_NOWAIT);
    812   1.1  drochner 	dma->mask = buf[0];
    813   1.1  drochner 	dma->flags = buf[1];
    814   1.1  drochner 	SIMPLEQ_INSERT_TAIL(&r->dma, dma, next);
    815   1.1  drochner 	r->numdma++;
    816   1.1  drochner 	return (0);
    817   1.1  drochner }
    818   1.1  drochner 
    819   1.1  drochner static int
    820   1.1  drochner pnp_newioport(r, buf, len)
    821   1.1  drochner 	struct pnpresources *r;
    822   1.1  drochner 	unsigned char *buf;
    823   1.1  drochner 	size_t len;
    824   1.1  drochner {
    825   1.1  drochner 	struct pnp_io *io;
    826   1.1  drochner 
    827   1.8  drochner 	if (buf[6] == 0) { /* disabled */
    828   1.8  drochner #ifdef PNPBIOSDEBUG
    829   1.8  drochner 		printf("ZERO io descriptor\n");
    830   1.8  drochner #endif
    831   1.8  drochner 		return (0);
    832   1.8  drochner 	}
    833   1.1  drochner 	io = malloc(sizeof(struct pnp_io), M_DEVBUF, M_NOWAIT);
    834   1.1  drochner 	io->flags = buf[0];
    835   1.1  drochner 	io->minbase = buf[1] | (buf[2] << 8);
    836   1.1  drochner 	io->maxbase = buf[3] | (buf[4] << 8);
    837   1.1  drochner 	io->align = buf[5];
    838   1.1  drochner 	io->len = buf[6];
    839   1.8  drochner 	SIMPLEQ_INSERT_TAIL(&r->io, io, next);
    840   1.8  drochner 	r->numio++;
    841   1.8  drochner 	return (0);
    842   1.8  drochner }
    843   1.8  drochner 
    844   1.8  drochner static int
    845   1.8  drochner pnp_newfixedioport(r, buf, len)
    846   1.8  drochner 	struct pnpresources *r;
    847   1.8  drochner 	unsigned char *buf;
    848   1.8  drochner 	size_t len;
    849   1.8  drochner {
    850   1.8  drochner 	struct pnp_io *io;
    851   1.8  drochner 
    852   1.8  drochner 	if (buf[2] == 0) { /* disabled */
    853   1.8  drochner #ifdef PNPBIOSDEBUG
    854   1.8  drochner 		printf("ZERO fixed io descriptor\n");
    855   1.8  drochner #endif
    856   1.8  drochner 		return (0);
    857   1.8  drochner 	}
    858   1.8  drochner 	io = malloc(sizeof(struct pnp_io), M_DEVBUF, M_NOWAIT);
    859   1.8  drochner 	io->flags = 1; /* 10 bit decoding */
    860   1.8  drochner 	io->minbase = io->maxbase = buf[0] | (buf[1] << 8);
    861   1.8  drochner 	io->align = 1;
    862   1.8  drochner 	io->len = buf[2];
    863   1.1  drochner 	SIMPLEQ_INSERT_TAIL(&r->io, io, next);
    864   1.1  drochner 	r->numio++;
    865   1.1  drochner 	return (0);
    866   1.1  drochner }
    867   1.1  drochner 
    868   1.1  drochner static int
    869   1.1  drochner pnp_compatid(r, buf, len)
    870   1.1  drochner 	struct pnpresources *r;
    871   1.1  drochner 	unsigned char *buf;
    872   1.1  drochner 	size_t len;
    873   1.1  drochner {
    874   1.1  drochner 	struct pnp_compatid *id;
    875   1.1  drochner 
    876   1.1  drochner 	id = malloc(sizeof(*id), M_DEVBUF, M_NOWAIT);
    877   1.1  drochner 	eisaid_to_string(buf, id->idstr);
    878   1.1  drochner 	id->next = r->compatids;
    879   1.1  drochner 	r->compatids = id;
    880   1.1  drochner 	return (0);
    881   1.1  drochner }
    882   1.1  drochner 
    883   1.1  drochner int
    884   1.1  drochner pnpbios_io_map(pbt, resc, idx, tagp, hdlp)
    885   1.1  drochner 	pnpbios_tag_t pbt;
    886   1.1  drochner 	struct pnpresources *resc;
    887   1.1  drochner 	int idx;
    888   1.1  drochner 	bus_space_tag_t *tagp;
    889   1.1  drochner 	bus_space_handle_t *hdlp;
    890   1.1  drochner {
    891   1.1  drochner 	struct pnp_io *io;
    892   1.1  drochner 
    893   1.1  drochner 	if (idx >= resc->numio)
    894   1.1  drochner 		return (EINVAL);
    895   1.1  drochner 
    896   1.1  drochner 	io = SIMPLEQ_FIRST(&resc->io);
    897   1.1  drochner 	while (idx--)
    898   1.1  drochner 		io = SIMPLEQ_NEXT(io, next);
    899   1.1  drochner 
    900   1.1  drochner 	*tagp = I386_BUS_SPACE_IO;
    901   1.1  drochner 	return (i386_memio_map(I386_BUS_SPACE_IO, io->minbase, io->len,
    902   1.1  drochner 			       0, hdlp));
    903   1.1  drochner }
    904   1.1  drochner 
    905   1.1  drochner int
    906   1.1  drochner pnpbios_getiobase(pbt, resc, idx, tagp, basep)
    907   1.1  drochner 	pnpbios_tag_t pbt;
    908   1.1  drochner 	struct pnpresources *resc;
    909   1.1  drochner 	int idx;
    910   1.1  drochner 	bus_space_tag_t *tagp;
    911   1.1  drochner 	int *basep;
    912   1.1  drochner {
    913   1.1  drochner 	struct pnp_io *io;
    914   1.1  drochner 
    915   1.1  drochner 	if (idx >= resc->numio)
    916   1.1  drochner 		return (EINVAL);
    917   1.1  drochner 
    918   1.1  drochner 	io = SIMPLEQ_FIRST(&resc->io);
    919   1.1  drochner 	while (idx--)
    920   1.1  drochner 		io = SIMPLEQ_NEXT(io, next);
    921   1.1  drochner 
    922   1.1  drochner 	if (tagp)
    923   1.1  drochner 		*tagp = I386_BUS_SPACE_IO;
    924   1.1  drochner 	if (basep)
    925   1.1  drochner 		*basep = io->minbase;
    926   1.1  drochner 	return (0);
    927   1.1  drochner }
    928   1.1  drochner 
    929   1.1  drochner void *
    930   1.1  drochner pnpbios_intr_establish(pbt, resc, idx, level, fcn, arg)
    931   1.1  drochner 	pnpbios_tag_t pbt;
    932   1.1  drochner 	struct pnpresources *resc;
    933   1.1  drochner 	int idx, level;
    934   1.1  drochner 	int (*fcn) __P((void *));
    935   1.1  drochner 	void *arg;
    936   1.1  drochner {
    937   1.1  drochner 	struct pnp_irq *irq;
    938   1.1  drochner 	int irqnum, type;
    939   1.1  drochner 
    940   1.1  drochner 	if (idx >= resc->numirq)
    941   1.1  drochner 		return (0);
    942   1.1  drochner 
    943   1.1  drochner 	irq = SIMPLEQ_FIRST(&resc->irq);
    944   1.1  drochner 	while (idx--)
    945   1.1  drochner 		irq = SIMPLEQ_NEXT(irq, next);
    946   1.1  drochner 
    947   1.1  drochner 	irqnum = ffs(irq->mask) - 1;
    948   1.1  drochner 	type = (irq->flags & 0x0c) ? IST_LEVEL : IST_EDGE;
    949   1.1  drochner 
    950   1.1  drochner 	return (isa_intr_establish(0, irqnum, type, level, fcn, arg));
    951   1.1  drochner }
    952   1.1  drochner 
    953   1.1  drochner int
    954   1.1  drochner pnpbios_getirqnum(pbt, resc, idx, irqp)
    955   1.1  drochner 	pnpbios_tag_t pbt;
    956   1.1  drochner 	struct pnpresources *resc;
    957   1.1  drochner 	int idx;
    958   1.1  drochner 	int *irqp;
    959   1.1  drochner {
    960   1.1  drochner 	struct pnp_irq *irq;
    961   1.1  drochner 
    962   1.1  drochner 	if (idx >= resc->numirq)
    963   1.1  drochner 		return (EINVAL);
    964   1.1  drochner 
    965   1.1  drochner 	irq = SIMPLEQ_FIRST(&resc->irq);
    966   1.1  drochner 	while (idx--)
    967   1.1  drochner 		irq = SIMPLEQ_NEXT(irq, next);
    968   1.1  drochner 
    969   1.1  drochner 	*irqp = ffs(irq->mask) - 1;
    970   1.1  drochner 	return (0);
    971   1.1  drochner }
    972   1.1  drochner 
    973   1.1  drochner int
    974   1.1  drochner pnpbios_getdmachan(pbt, resc, idx, chanp)
    975   1.1  drochner 	pnpbios_tag_t pbt;
    976   1.1  drochner 	struct pnpresources *resc;
    977   1.1  drochner 	int idx;
    978   1.1  drochner 	int *chanp;
    979   1.1  drochner {
    980   1.1  drochner 	struct pnp_dma *dma;
    981   1.1  drochner 
    982   1.1  drochner 	if (idx >= resc->numdma)
    983   1.1  drochner 		return (EINVAL);
    984   1.1  drochner 
    985   1.1  drochner 	dma = SIMPLEQ_FIRST(&resc->dma);
    986   1.1  drochner 	while (idx--)
    987   1.1  drochner 		dma = SIMPLEQ_NEXT(dma, next);
    988   1.1  drochner 
    989   1.1  drochner 	*chanp = ffs(dma->mask) - 1;
    990   1.1  drochner 	return (0);
    991   1.1  drochner }
    992