From 0e1cb2e27714d4bde29cf01489e90e7705ab3ee6 Mon Sep 17 00:00:00 2001 From: Joerg Sonnenberger Date: Thu, 29 Apr 2004 12:11:16 +0000 Subject: [PATCH] Move the Plug'n'Play BIOS support into a separate file. This is included with "device pnpbios" instead of "options PNPBIOS". This is still not included by default in GENERIC. While at it, convert some u_intXX_t, u_short and u_int to uintXX_t in preparation for AMD64. --- sys/conf/files.amd64 | 3 +- sys/conf/files.i386 | 3 +- sys/conf/files.pc98 | 3 +- sys/conf/options.amd64 | 5 +- sys/conf/options.i386 | 5 +- sys/conf/options.pc98 | 5 +- sys/config/LINT | 8 +- sys/i386/conf/LINT | 8 +- sys/i386/i386/bios.c | 245 ++--------------------------- sys/i386/i386/pnpbios.c | 256 +++++++++++++++++++++++++++++++ sys/platform/pc32/i386/bios.c | 245 ++--------------------------- sys/platform/pc32/i386/pnpbios.c | 256 +++++++++++++++++++++++++++++++ 12 files changed, 553 insertions(+), 489 deletions(-) create mode 100644 sys/i386/i386/pnpbios.c create mode 100644 sys/platform/pc32/i386/pnpbios.c diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index c995e8edef..0f843c50c5 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -2,7 +2,7 @@ # files marked standard are always included. # # $FreeBSD: src/sys/conf/files.i386,v 1.307.2.38 2003/01/02 20:41:33 kan Exp $ -# $DragonFly: src/sys/conf/Attic/files.amd64,v 1.2 2004/02/14 21:12:38 dillon Exp $ +# $DragonFly: src/sys/conf/Attic/files.amd64,v 1.3 2004/04/29 12:11:15 joerg Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -160,6 +160,7 @@ i386/i386/nexus.c standard i386/i386/perfmon.c optional perfmon i386/i386/perfmon.c optional perfmon profiling-routine i386/i386/pmap.c standard +i386/i386/pnpbios.c optional pnpbios i386/i386/procfs_machdep.c standard i386/i386/spinlock.s standard i386/i386/support.s standard diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 470561c30c..9ef8fae21d 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -2,7 +2,7 @@ # files marked standard are always included. # # $FreeBSD: src/sys/conf/files.i386,v 1.307.2.38 2003/01/02 20:41:33 kan Exp $ -# $DragonFly: src/sys/conf/Attic/files.i386,v 1.22 2004/03/28 08:25:54 dillon Exp $ +# $DragonFly: src/sys/conf/Attic/files.i386,v 1.23 2004/04/29 12:11:15 joerg Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -217,6 +217,7 @@ i386/i386/perfmon.c optional perfmon i386/i386/perfmon.c optional perfmon profiling-routine i386/i386/pmap.c standard i386/i386/pmap_inval.c standard +i386/i386/pnpbios.c optional pnpbios i386/i386/procfs_machdep.c standard i386/i386/spinlock.s standard i386/i386/support.s standard diff --git a/sys/conf/files.pc98 b/sys/conf/files.pc98 index d3c386751e..e54c3ba3ad 100644 --- a/sys/conf/files.pc98 +++ b/sys/conf/files.pc98 @@ -4,7 +4,7 @@ # modified for PC-9801 # # $FreeBSD: src/sys/conf/files.pc98,v 1.140.2.44 2003/02/10 13:11:50 nyan Exp $ -# $DragonFly: src/sys/conf/Attic/files.pc98,v 1.5 2004/02/14 21:12:38 dillon Exp $ +# $DragonFly: src/sys/conf/Attic/files.pc98,v 1.6 2004/04/29 12:11:15 joerg Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -193,6 +193,7 @@ i386/i386/nexus.c standard i386/i386/perfmon.c optional perfmon i386/i386/perfmon.c optional perfmon profiling-routine i386/i386/pmap.c standard +i386/i386/pnpbios.c optional pnpbios i386/i386/procfs_machdep.c standard i386/i386/spinlock.s standard i386/i386/support.s standard diff --git a/sys/conf/options.amd64 b/sys/conf/options.amd64 index bcae9ed92d..e6ff8f1570 100644 --- a/sys/conf/options.amd64 +++ b/sys/conf/options.amd64 @@ -1,5 +1,5 @@ # $FreeBSD: src/sys/conf/options.i386,v 1.132.2.18 2003/03/14 21:22:35 jhb Exp $ -# $DragonFly: src/sys/conf/Attic/options.amd64,v 1.1 2004/02/02 08:05:56 dillon Exp $ +# $DragonFly: src/sys/conf/Attic/options.amd64,v 1.2 2004/04/29 12:11:15 joerg Exp $ DISABLE_PSE IDE_DELAY @@ -200,9 +200,6 @@ OLTR_NO_BULLSEYE_MAC opt_oltr.h # Defaults to NDGB*16. NDGBPORTS opt_dgb.h -# Temporary options for moving to pnpbios -PNPBIOS opt_pnp.h - # SMB/CIFS requester NETSMB opt_netsmb.h NETSMBCRYPTO opt_netsmb.h diff --git a/sys/conf/options.i386 b/sys/conf/options.i386 index fa28f579d4..9bba017061 100644 --- a/sys/conf/options.i386 +++ b/sys/conf/options.i386 @@ -1,5 +1,5 @@ # $FreeBSD: src/sys/conf/options.i386,v 1.132.2.18 2003/03/14 21:22:35 jhb Exp $ -# $DragonFly: src/sys/conf/Attic/options.i386,v 1.5 2004/01/09 20:49:39 drhodus Exp $ +# $DragonFly: src/sys/conf/Attic/options.i386,v 1.6 2004/04/29 12:11:15 joerg Exp $ DISABLE_PSE IDE_DELAY @@ -203,9 +203,6 @@ OLTR_NO_BULLSEYE_MAC opt_oltr.h # Defaults to NDGB*16. NDGBPORTS opt_dgb.h -# Temporary options for moving to pnpbios -PNPBIOS opt_pnp.h - # SMB/CIFS requester NETSMB opt_netsmb.h NETSMBCRYPTO opt_netsmb.h diff --git a/sys/conf/options.pc98 b/sys/conf/options.pc98 index 99197b933b..a14b2d0286 100644 --- a/sys/conf/options.pc98 +++ b/sys/conf/options.pc98 @@ -1,5 +1,5 @@ # $FreeBSD: src/sys/conf/options.pc98,v 1.103.2.17 2003/03/14 21:22:35 jhb Exp $ -# $DragonFly: src/sys/conf/Attic/options.pc98,v 1.5 2004/01/09 20:49:39 drhodus Exp $ +# $DragonFly: src/sys/conf/Attic/options.pc98,v 1.6 2004/04/29 12:11:15 joerg Exp $ DISABLE_PSE IDE_DELAY @@ -192,9 +192,6 @@ OLTR_NO_BULLSEYE_MAC opt_oltr.h # Defaults to NDGB*16. NDGBPORTS opt_dgb.h -# Temporary options for moving to pnpbios -PNPBIOS opt_pnp.h - # bs driver options SCSI_BOUNCE_SIZE opt_bs.h BS_TARG_SAFEMODE opt_bs.h diff --git a/sys/config/LINT b/sys/config/LINT index cdd6bf5267..bfcd227894 100644 --- a/sys/config/LINT +++ b/sys/config/LINT @@ -3,7 +3,7 @@ # as much of the source tree as it can. # # $FreeBSD: src/sys/i386/conf/LINT,v 1.749.2.144 2003/06/04 17:56:59 sam Exp $ -# $DragonFly: src/sys/config/LINT,v 1.27 2004/04/16 20:13:17 drhodus Exp $ +# $DragonFly: src/sys/config/LINT,v 1.28 2004/04/29 12:11:16 joerg Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from @@ -1024,6 +1024,9 @@ options MSGBUF_SIZE=40960 # device isa +# ISA-PnP BIOS support +device pnpbios + # # Options for `isa': # @@ -1532,7 +1535,7 @@ options NATM #native ATM #device uart0 at isa? port 0x330 irq 5 # The newpcm driver (use INSTEAD of snd0 and all VOXWARE drivers!). -# Note that motherboard sound devices may require options PNPBIOS. +# Note that motherboard sound devices may require device PNPBIOS. # # Supported cards include: # Creative SoundBlaster ISA PnP/non-PnP @@ -2747,7 +2750,6 @@ options NETATALKDEBUG #options OLTR_NO_BULLSEYE_MAC #options OLTR_NO_HAWKEYE_MAC #options OLTR_NO_TMS_MAC -options PNPBIOS options PSM_DEBUG=1 options SCSI_NCR_DEBUG options SCSI_NCR_MAX_SYNC=10000 diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT index a8277528fe..b5c3fe6cf8 100644 --- a/sys/i386/conf/LINT +++ b/sys/i386/conf/LINT @@ -3,7 +3,7 @@ # as much of the source tree as it can. # # $FreeBSD: src/sys/i386/conf/LINT,v 1.749.2.144 2003/06/04 17:56:59 sam Exp $ -# $DragonFly: src/sys/i386/conf/Attic/LINT,v 1.27 2004/04/16 20:13:17 drhodus Exp $ +# $DragonFly: src/sys/i386/conf/Attic/LINT,v 1.28 2004/04/29 12:11:16 joerg Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from @@ -1024,6 +1024,9 @@ options MSGBUF_SIZE=40960 # device isa +# ISA-PnP BIOS support +device pnpbios + # # Options for `isa': # @@ -1532,7 +1535,7 @@ options NATM #native ATM #device uart0 at isa? port 0x330 irq 5 # The newpcm driver (use INSTEAD of snd0 and all VOXWARE drivers!). -# Note that motherboard sound devices may require options PNPBIOS. +# Note that motherboard sound devices may require device PNPBIOS. # # Supported cards include: # Creative SoundBlaster ISA PnP/non-PnP @@ -2747,7 +2750,6 @@ options NETATALKDEBUG #options OLTR_NO_BULLSEYE_MAC #options OLTR_NO_HAWKEYE_MAC #options OLTR_NO_TMS_MAC -options PNPBIOS options PSM_DEBUG=1 options SCSI_NCR_DEBUG options SCSI_NCR_MAX_SYNC=10000 diff --git a/sys/i386/i386/bios.c b/sys/i386/i386/bios.c index 05b7db830d..65b50f6322 100644 --- a/sys/i386/i386/bios.c +++ b/sys/i386/i386/bios.c @@ -25,33 +25,21 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/i386/i386/bios.c,v 1.29.2.3 2001/07/19 18:07:35 imp Exp $ - * $DragonFly: src/sys/i386/i386/Attic/bios.c,v 1.9 2004/02/17 19:38:53 dillon Exp $ + * $DragonFly: src/sys/i386/i386/Attic/bios.c,v 1.10 2004/04/29 12:11:16 joerg Exp $ */ /* * Code for dealing with the BIOS in x86 PC systems. */ -#include "opt_pnp.h" -/*#include "opt_isa.h"*/ - #include #include #include -#include -#include #include #include #include #include -#include -#include -#include -#include #include -#include -#include -#include #define BIOS_START 0xe0000 #define BIOS_SIZE 0x20000 @@ -77,7 +65,7 @@ bios32_init(void *junk) u_long sigaddr; struct bios32_SDheader *sdh; struct PnPBIOS_table *pt; - u_int8_t ck, *cv; + uint8_t ck, *cv; int i; char *p; @@ -90,7 +78,7 @@ bios32_init(void *junk) /* get a virtual pointer to the structure */ sdh = (struct bios32_SDheader *)(uintptr_t)BIOS_PADDRTOVADDR(sigaddr); - for (cv = (u_int8_t *)sdh, ck = 0, i = 0; i < (sdh->len * 16); i++) { + for (cv = (uint8_t *)sdh, ck = 0, i = 0; i < (sdh->len * 16); i++) { ck += cv[i]; } /* If checksum is OK, enable use of the entrypoint */ @@ -128,7 +116,7 @@ bios32_init(void *junk) ) { /* get a virtual pointer to the structure */ pt = (struct PnPBIOS_table *)(uintptr_t)BIOS_PADDRTOVADDR(sigaddr); - for (cv = (u_int8_t *)pt, ck = 0, i = 0; i < pt->len; i++) { + for (cv = (uint8_t *)pt, ck = 0, i = 0; i < pt->len; i++) { ck += cv[i]; } /* If checksum is OK, enable use of the entrypoint */ @@ -204,8 +192,8 @@ bios32_SDlookup(struct bios32_SDentry *ent) * signature was not found. */ -u_int32_t -bios_sigsearch(u_int32_t start, u_char *sig, int siglen, int paralen, int sigofs) +uint32_t +bios_sigsearch(uint32_t start, u_char *sig, int siglen, int paralen, int sigofs) { u_char *sp, *end; @@ -227,7 +215,7 @@ bios_sigsearch(u_int32_t start, u_char *sig, int siglen, int paralen, int sigofs /* compare here */ if (!bcmp(sp + sigofs, sig, siglen)) { /* convert back to physical address */ - return((u_int32_t)BIOS_VADDRTOPADDR(sp)); + return((uint32_t)BIOS_VADDRTOPADDR(sp)); } sp += paralen; } @@ -239,12 +227,12 @@ bios_sigsearch(u_int32_t start, u_char *sig, int siglen, int paralen, int sigofs */ union { struct { - u_short offset; - u_short segment; + uint16_t offset; + uint16_t segment; } vec16; struct { - u_int offset; - u_short segment; + uint32_t offset; + uint16_t segment; } vec32; } bioscall_vector; /* bios jump vector */ @@ -462,214 +450,3 @@ bios16(struct bios_args *args, char *fmt, ...) cpu_invltlb(); return (i); } - -#ifdef PNPBIOS /* remove conditional later */ - -/* - * PnP BIOS interface; enumerate devices only known to the system - * BIOS and save information about them for later use. - */ - -struct pnp_sysdev -{ - u_int16_t size; - u_int8_t handle; - u_int32_t devid; - u_int8_t type[3]; - u_int16_t attrib; - /* device-specific data comes here */ - u_int8_t devdata[0]; -} __attribute__((__packed__)); - -#define PNPATTR_NODISABLE (1<<0) /* can't be disabled */ -#define PNPATTR_NOCONFIG (1<<1) /* can't be configured */ -#define PNPATTR_OUTPUT (1<<2) /* can be primary output */ -#define PNPATTR_INPUT (1<<3) /* can be primary input */ -#define PNPATTR_BOOTABLE (1<<4) /* can be booted from */ -#define PNPATTR_DOCK (1<<5) /* is a docking station */ -#define PNPATTR_REMOVEABLE (1<<6) /* device is removeable */ - -#define PNPATTR_CONFIG(a) (((a) >> 7) & 0x03) -#define PNPATTR_CONFIG_STATIC 0x00 -#define PNPATTR_CONFIG_DYNAMIC 0x01 -#define PNPATTR_CONFIG_DYNONLY 0x03 - -/* We have to cluster arguments within a 64k range for the bios16 call */ -struct pnp_sysdevargs -{ - u_int16_t next; - u_int16_t pad; - struct pnp_sysdev node; -}; - -/* - * This function is called after the bus has assigned resource - * locations for a logical device. - */ -static void -pnpbios_set_config(void *arg, struct isa_config *config, int enable) -{ -} - -/* - * Quiz the PnP BIOS, build a list of PNP IDs and resource data. - */ -static void -pnpbios_identify(driver_t *driver, device_t parent) -{ - struct PnPBIOS_table *pt = PnPBIOStable; - struct bios_args args; - struct pnp_sysdev *pd; - struct pnp_sysdevargs *pda; - u_int16_t ndevs, bigdev; - int error, currdev; - u_int8_t *devnodebuf, tag; - u_int32_t *devid, *compid; - int idx, left; - device_t dev; - - /* no PnP BIOS information */ - if (pt == NULL) - return; - - /* ACPI already active */ - if (devclass_get_softc(devclass_find("ACPI"), 0) != NULL) - return; - - bzero(&args, sizeof(args)); - args.seg.code16.base = BIOS_PADDRTOVADDR(pt->pmentrybase); - args.seg.code16.limit = 0xffff; /* XXX ? */ - args.seg.data.base = BIOS_PADDRTOVADDR(pt->pmdataseg); - args.seg.data.limit = 0xffff; - args.entry = pt->pmentryoffset; - - if ((error = bios16(&args, PNP_COUNT_DEVNODES, &ndevs, &bigdev)) || (args.r.eax & 0xff)) - printf("pnpbios: error %d/%x getting device count/size limit\n", error, args.r.eax); - ndevs &= 0xff; /* clear high byte garbage */ - if (bootverbose) - printf("pnpbios: %d devices, largest %d bytes\n", ndevs, bigdev); - - devnodebuf = malloc(bigdev + (sizeof(struct pnp_sysdevargs) - sizeof(struct pnp_sysdev)), M_DEVBUF, M_NOWAIT); - pda = (struct pnp_sysdevargs *)devnodebuf; - pd = &pda->node; - - for (currdev = 0, left = ndevs; (currdev != 0xff) && (left > 0); left--) { - bzero(pd, bigdev); - pda->next = currdev; - - /* get current configuration */ - if ((error = bios16(&args, PNP_GET_DEVNODE, &pda->next, &pda->node, 1))) { - printf("pnpbios: error %d making BIOS16 call\n", error); - break; - } - if (bootverbose) - printf("pnp_get_devnode cd=%d nxt=%d size=%d handle=%d devid=%08x type=%02x%02x%02x, attrib=%04x\n", currdev, pda->next, pd->size, pd->handle, pd->devid, pd->type[0], pd->type[1], pd->type[2], pd->attrib); - - if ((error = (args.r.eax & 0xff))) { - if (bootverbose) - printf("pnpbios: %s 0x%x fetching node %d\n", error & 0x80 ? "error" : "warning", error, currdev); - if (error & 0x80) - break; - } - currdev = pda->next; - if (pd->size < sizeof(struct pnp_sysdev)) { - printf("pnpbios: bogus system node data, aborting scan\n"); - break; - } - - /* - * Ignore PICs so that we don't have to worry about the PICs - * claiming IRQs to prevent their use. The PIC drivers - * already ensure that invalid IRQs are not used. - */ - if (!strcmp(pnp_eisaformat(pd->devid), "PNP0000")) /* ISA PIC */ - continue; - if (!strcmp(pnp_eisaformat(pd->devid), "PNP0003")) /* APIC */ - continue; - - /* Add the device and parse its resources */ - dev = BUS_ADD_CHILD(parent, ISA_ORDER_PNP, NULL, -1); - isa_set_vendorid(dev, pd->devid); - isa_set_logicalid(dev, pd->devid); - - /* - * It appears that some PnP BIOS doesn't allow us to re-enable - * the embedded system device once it is disabled. We shall - * mark all system device nodes as "cannot be disabled", regardless - * of actual settings in the device attribute byte. XXX - */ -#if 0 - isa_set_configattr(dev, - ((pd->attrib & PNPATTR_NODISABLE) ? 0 : ISACFGATTR_CANDISABLE) | - ((!(pd->attrib & PNPATTR_NOCONFIG) && - PNPATTR_CONFIG(pd->attrib) != PNPATTR_CONFIG_STATIC) - ? ISACFGATTR_DYNAMIC : 0)); -#endif - isa_set_configattr(dev, - (!(pd->attrib & PNPATTR_NOCONFIG) && - PNPATTR_CONFIG(pd->attrib) != PNPATTR_CONFIG_STATIC) - ? ISACFGATTR_DYNAMIC : 0); - - ISA_SET_CONFIG_CALLBACK(parent, dev, pnpbios_set_config, 0); - pnp_parse_resources(dev, &pd->devdata[0], - pd->size - sizeof(struct pnp_sysdev), 0); - if (!device_get_desc(dev)) - device_set_desc_copy(dev, pnp_eisaformat(pd->devid)); - - /* Find device IDs */ - devid = &pd->devid; - compid = NULL; - - /* look for a compatible device ID too */ - left = pd->size - sizeof(struct pnp_sysdev); - idx = 0; - while (idx < left) { - tag = pd->devdata[idx++]; - if (PNP_RES_TYPE(tag) == 0) { - /* Small resource */ - switch (PNP_SRES_NUM(tag)) { - case PNP_TAG_COMPAT_DEVICE: - compid = (u_int32_t *)(pd->devdata + idx); - if (bootverbose) - printf("pnpbios: node %d compat ID 0x%08x\n", pd->handle, *compid); - /* FALLTHROUGH */ - case PNP_TAG_END: - idx = left; - break; - default: - idx += PNP_SRES_LEN(tag); - break; - } - } else - /* Large resource, skip it */ - idx += *(u_int16_t *)(pd->devdata + idx) + 2; - } - if (bootverbose) { - printf("pnpbios: handle %d device ID %s (%08x)", - pd->handle, pnp_eisaformat(*devid), *devid); - if (compid != NULL) - printf(" compat ID %s (%08x)", - pnp_eisaformat(*compid), *compid); - printf("\n"); - } - } -} - -static device_method_t pnpbios_methods[] = { - /* Device interface */ - DEVMETHOD(device_identify, pnpbios_identify), - - { 0, 0 } -}; - -static driver_t pnpbios_driver = { - "pnpbios", - pnpbios_methods, - 1, /* no softc */ -}; - -static devclass_t pnpbios_devclass; - -DRIVER_MODULE(pnpbios, isa, pnpbios_driver, pnpbios_devclass, 0, 0); - -#endif /* PNPBIOS */ diff --git a/sys/i386/i386/pnpbios.c b/sys/i386/i386/pnpbios.c new file mode 100644 index 0000000000..ad86ba729a --- /dev/null +++ b/sys/i386/i386/pnpbios.c @@ -0,0 +1,256 @@ +/*- + * Copyright (c) 2004 Joerg Sonnenberger + * + * Copyright (c) 1997 Michael Smith + * Copyright (c) 1998 Jonathan Lemon + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $DragonFly: src/sys/i386/i386/Attic/pnpbios.c,v 1.1 2004/04/29 12:11:16 joerg Exp $ + */ + +/* + * Code for dealing with the PnP-BIOS in x86 PC systems. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +/* + * PnP BIOS interface; enumerate devices only known to the system + * BIOS and save information about them for later use. + */ + +struct pnp_sysdev +{ + uint16_t size; + uint8_t handle; + uint32_t devid; + uint8_t type[3]; + uint16_t attrib; + /* device-specific data comes here */ + uint8_t devdata[0]; +} __attribute__((__packed__)); + +#define PNPATTR_NODISABLE (1<<0) /* can't be disabled */ +#define PNPATTR_NOCONFIG (1<<1) /* can't be configured */ +#define PNPATTR_OUTPUT (1<<2) /* can be primary output */ +#define PNPATTR_INPUT (1<<3) /* can be primary input */ +#define PNPATTR_BOOTABLE (1<<4) /* can be booted from */ +#define PNPATTR_DOCK (1<<5) /* is a docking station */ +#define PNPATTR_REMOVEABLE (1<<6) /* device is removeable */ + +#define PNPATTR_CONFIG(a) (((a) >> 7) & 0x03) +#define PNPATTR_CONFIG_STATIC 0x00 +#define PNPATTR_CONFIG_DYNAMIC 0x01 +#define PNPATTR_CONFIG_DYNONLY 0x03 + +/* We have to cluster arguments within a 64k range for the bios16 call */ +struct pnp_sysdevargs +{ + uint16_t next; + uint16_t pad; + struct pnp_sysdev node; +}; + +/* + * This function is called after the bus has assigned resource + * locations for a logical device. + */ +static void +pnpbios_set_config(void *arg, struct isa_config *config, int enable) +{ +} + +/* + * Quiz the PnP BIOS, build a list of PNP IDs and resource data. + */ +static void +pnpbios_identify(driver_t *driver, device_t parent) +{ + struct PnPBIOS_table *pt = PnPBIOStable; + struct bios_args args; + struct pnp_sysdev *pd; + struct pnp_sysdevargs *pda; + uint16_t ndevs, bigdev; + int error, currdev; + uint8_t *devnodebuf, tag; + uint32_t *devid, *compid; + int idx, left; + device_t dev; + + /* no PnP BIOS information */ + if (pt == NULL) + return; + + /* ACPI already active */ + if (devclass_get_softc(devclass_find("ACPI"), 0) != NULL) + return; + + bzero(&args, sizeof(args)); + args.seg.code16.base = BIOS_PADDRTOVADDR(pt->pmentrybase); + args.seg.code16.limit = 0xffff; /* XXX ? */ + args.seg.data.base = BIOS_PADDRTOVADDR(pt->pmdataseg); + args.seg.data.limit = 0xffff; + args.entry = pt->pmentryoffset; + + if ((error = bios16(&args, PNP_COUNT_DEVNODES, &ndevs, &bigdev)) || (args.r.eax & 0xff)) + printf("pnpbios: error %d/%x getting device count/size limit\n", error, args.r.eax); + ndevs &= 0xff; /* clear high byte garbage */ + if (bootverbose) + printf("pnpbios: %d devices, largest %d bytes\n", ndevs, bigdev); + + devnodebuf = malloc(bigdev + (sizeof(struct pnp_sysdevargs) - sizeof(struct pnp_sysdev)), M_DEVBUF, M_NOWAIT); + pda = (struct pnp_sysdevargs *)devnodebuf; + pd = &pda->node; + + for (currdev = 0, left = ndevs; (currdev != 0xff) && (left > 0); left--) { + bzero(pd, bigdev); + pda->next = currdev; + + /* get current configuration */ + if ((error = bios16(&args, PNP_GET_DEVNODE, &pda->next, &pda->node, 1))) { + printf("pnpbios: error %d making BIOS16 call\n", error); + break; + } + if (bootverbose) + printf("pnp_get_devnode cd=%d nxt=%d size=%d handle=%d devid=%08x type=%02x%02x%02x, attrib=%04x\n", currdev, pda->next, pd->size, pd->handle, pd->devid, pd->type[0], pd->type[1], pd->type[2], pd->attrib); + + if ((error = (args.r.eax & 0xff))) { + if (bootverbose) + printf("pnpbios: %s 0x%x fetching node %d\n", error & 0x80 ? "error" : "warning", error, currdev); + if (error & 0x80) + break; + } + currdev = pda->next; + if (pd->size < sizeof(struct pnp_sysdev)) { + printf("pnpbios: bogus system node data, aborting scan\n"); + break; + } + + /* + * Ignore PICs so that we don't have to worry about the PICs + * claiming IRQs to prevent their use. The PIC drivers + * already ensure that invalid IRQs are not used. + */ + if (!strcmp(pnp_eisaformat(pd->devid), "PNP0000")) /* ISA PIC */ + continue; + if (!strcmp(pnp_eisaformat(pd->devid), "PNP0003")) /* APIC */ + continue; + + /* Add the device and parse its resources */ + dev = BUS_ADD_CHILD(parent, ISA_ORDER_PNP, NULL, -1); + isa_set_vendorid(dev, pd->devid); + isa_set_logicalid(dev, pd->devid); + + /* + * It appears that some PnP BIOS doesn't allow us to re-enable + * the embedded system device once it is disabled. We shall + * mark all system device nodes as "cannot be disabled", regardless + * of actual settings in the device attribute byte. XXX + */ +#if 0 + isa_set_configattr(dev, + ((pd->attrib & PNPATTR_NODISABLE) ? 0 : ISACFGATTR_CANDISABLE) | + ((!(pd->attrib & PNPATTR_NOCONFIG) && + PNPATTR_CONFIG(pd->attrib) != PNPATTR_CONFIG_STATIC) + ? ISACFGATTR_DYNAMIC : 0)); +#endif + isa_set_configattr(dev, + (!(pd->attrib & PNPATTR_NOCONFIG) && + PNPATTR_CONFIG(pd->attrib) != PNPATTR_CONFIG_STATIC) + ? ISACFGATTR_DYNAMIC : 0); + + ISA_SET_CONFIG_CALLBACK(parent, dev, pnpbios_set_config, 0); + pnp_parse_resources(dev, &pd->devdata[0], + pd->size - sizeof(struct pnp_sysdev), 0); + if (!device_get_desc(dev)) + device_set_desc_copy(dev, pnp_eisaformat(pd->devid)); + + /* Find device IDs */ + devid = &pd->devid; + compid = NULL; + + /* look for a compatible device ID too */ + left = pd->size - sizeof(struct pnp_sysdev); + idx = 0; + while (idx < left) { + tag = pd->devdata[idx++]; + if (PNP_RES_TYPE(tag) == 0) { + /* Small resource */ + switch (PNP_SRES_NUM(tag)) { + case PNP_TAG_COMPAT_DEVICE: + compid = (uint32_t *)(pd->devdata + idx); + if (bootverbose) + printf("pnpbios: node %d compat ID 0x%08x\n", pd->handle, *compid); + /* FALLTHROUGH */ + case PNP_TAG_END: + idx = left; + break; + default: + idx += PNP_SRES_LEN(tag); + break; + } + } else + /* Large resource, skip it */ + idx += *(uint16_t *)(pd->devdata + idx) + 2; + } + if (bootverbose) { + printf("pnpbios: handle %d device ID %s (%08x)", + pd->handle, pnp_eisaformat(*devid), *devid); + if (compid != NULL) + printf(" compat ID %s (%08x)", + pnp_eisaformat(*compid), *compid); + printf("\n"); + } + } +} + +static device_method_t pnpbios_methods[] = { + /* Device interface */ + DEVMETHOD(device_identify, pnpbios_identify), + + { 0, 0 } +}; + +static driver_t pnpbios_driver = { + "pnpbios", + pnpbios_methods, + 1, /* no softc */ +}; + +static devclass_t pnpbios_devclass; + +DRIVER_MODULE(pnpbios, isa, pnpbios_driver, pnpbios_devclass, 0, 0); diff --git a/sys/platform/pc32/i386/bios.c b/sys/platform/pc32/i386/bios.c index 3870cb4a05..c784f85ceb 100644 --- a/sys/platform/pc32/i386/bios.c +++ b/sys/platform/pc32/i386/bios.c @@ -25,33 +25,21 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/i386/i386/bios.c,v 1.29.2.3 2001/07/19 18:07:35 imp Exp $ - * $DragonFly: src/sys/platform/pc32/i386/bios.c,v 1.9 2004/02/17 19:38:53 dillon Exp $ + * $DragonFly: src/sys/platform/pc32/i386/bios.c,v 1.10 2004/04/29 12:11:16 joerg Exp $ */ /* * Code for dealing with the BIOS in x86 PC systems. */ -#include "opt_pnp.h" -/*#include "opt_isa.h"*/ - #include #include #include -#include -#include #include #include #include #include -#include -#include -#include -#include #include -#include -#include -#include #define BIOS_START 0xe0000 #define BIOS_SIZE 0x20000 @@ -77,7 +65,7 @@ bios32_init(void *junk) u_long sigaddr; struct bios32_SDheader *sdh; struct PnPBIOS_table *pt; - u_int8_t ck, *cv; + uint8_t ck, *cv; int i; char *p; @@ -90,7 +78,7 @@ bios32_init(void *junk) /* get a virtual pointer to the structure */ sdh = (struct bios32_SDheader *)(uintptr_t)BIOS_PADDRTOVADDR(sigaddr); - for (cv = (u_int8_t *)sdh, ck = 0, i = 0; i < (sdh->len * 16); i++) { + for (cv = (uint8_t *)sdh, ck = 0, i = 0; i < (sdh->len * 16); i++) { ck += cv[i]; } /* If checksum is OK, enable use of the entrypoint */ @@ -128,7 +116,7 @@ bios32_init(void *junk) ) { /* get a virtual pointer to the structure */ pt = (struct PnPBIOS_table *)(uintptr_t)BIOS_PADDRTOVADDR(sigaddr); - for (cv = (u_int8_t *)pt, ck = 0, i = 0; i < pt->len; i++) { + for (cv = (uint8_t *)pt, ck = 0, i = 0; i < pt->len; i++) { ck += cv[i]; } /* If checksum is OK, enable use of the entrypoint */ @@ -204,8 +192,8 @@ bios32_SDlookup(struct bios32_SDentry *ent) * signature was not found. */ -u_int32_t -bios_sigsearch(u_int32_t start, u_char *sig, int siglen, int paralen, int sigofs) +uint32_t +bios_sigsearch(uint32_t start, u_char *sig, int siglen, int paralen, int sigofs) { u_char *sp, *end; @@ -227,7 +215,7 @@ bios_sigsearch(u_int32_t start, u_char *sig, int siglen, int paralen, int sigofs /* compare here */ if (!bcmp(sp + sigofs, sig, siglen)) { /* convert back to physical address */ - return((u_int32_t)BIOS_VADDRTOPADDR(sp)); + return((uint32_t)BIOS_VADDRTOPADDR(sp)); } sp += paralen; } @@ -239,12 +227,12 @@ bios_sigsearch(u_int32_t start, u_char *sig, int siglen, int paralen, int sigofs */ union { struct { - u_short offset; - u_short segment; + uint16_t offset; + uint16_t segment; } vec16; struct { - u_int offset; - u_short segment; + uint32_t offset; + uint16_t segment; } vec32; } bioscall_vector; /* bios jump vector */ @@ -462,214 +450,3 @@ bios16(struct bios_args *args, char *fmt, ...) cpu_invltlb(); return (i); } - -#ifdef PNPBIOS /* remove conditional later */ - -/* - * PnP BIOS interface; enumerate devices only known to the system - * BIOS and save information about them for later use. - */ - -struct pnp_sysdev -{ - u_int16_t size; - u_int8_t handle; - u_int32_t devid; - u_int8_t type[3]; - u_int16_t attrib; - /* device-specific data comes here */ - u_int8_t devdata[0]; -} __attribute__((__packed__)); - -#define PNPATTR_NODISABLE (1<<0) /* can't be disabled */ -#define PNPATTR_NOCONFIG (1<<1) /* can't be configured */ -#define PNPATTR_OUTPUT (1<<2) /* can be primary output */ -#define PNPATTR_INPUT (1<<3) /* can be primary input */ -#define PNPATTR_BOOTABLE (1<<4) /* can be booted from */ -#define PNPATTR_DOCK (1<<5) /* is a docking station */ -#define PNPATTR_REMOVEABLE (1<<6) /* device is removeable */ - -#define PNPATTR_CONFIG(a) (((a) >> 7) & 0x03) -#define PNPATTR_CONFIG_STATIC 0x00 -#define PNPATTR_CONFIG_DYNAMIC 0x01 -#define PNPATTR_CONFIG_DYNONLY 0x03 - -/* We have to cluster arguments within a 64k range for the bios16 call */ -struct pnp_sysdevargs -{ - u_int16_t next; - u_int16_t pad; - struct pnp_sysdev node; -}; - -/* - * This function is called after the bus has assigned resource - * locations for a logical device. - */ -static void -pnpbios_set_config(void *arg, struct isa_config *config, int enable) -{ -} - -/* - * Quiz the PnP BIOS, build a list of PNP IDs and resource data. - */ -static void -pnpbios_identify(driver_t *driver, device_t parent) -{ - struct PnPBIOS_table *pt = PnPBIOStable; - struct bios_args args; - struct pnp_sysdev *pd; - struct pnp_sysdevargs *pda; - u_int16_t ndevs, bigdev; - int error, currdev; - u_int8_t *devnodebuf, tag; - u_int32_t *devid, *compid; - int idx, left; - device_t dev; - - /* no PnP BIOS information */ - if (pt == NULL) - return; - - /* ACPI already active */ - if (devclass_get_softc(devclass_find("ACPI"), 0) != NULL) - return; - - bzero(&args, sizeof(args)); - args.seg.code16.base = BIOS_PADDRTOVADDR(pt->pmentrybase); - args.seg.code16.limit = 0xffff; /* XXX ? */ - args.seg.data.base = BIOS_PADDRTOVADDR(pt->pmdataseg); - args.seg.data.limit = 0xffff; - args.entry = pt->pmentryoffset; - - if ((error = bios16(&args, PNP_COUNT_DEVNODES, &ndevs, &bigdev)) || (args.r.eax & 0xff)) - printf("pnpbios: error %d/%x getting device count/size limit\n", error, args.r.eax); - ndevs &= 0xff; /* clear high byte garbage */ - if (bootverbose) - printf("pnpbios: %d devices, largest %d bytes\n", ndevs, bigdev); - - devnodebuf = malloc(bigdev + (sizeof(struct pnp_sysdevargs) - sizeof(struct pnp_sysdev)), M_DEVBUF, M_NOWAIT); - pda = (struct pnp_sysdevargs *)devnodebuf; - pd = &pda->node; - - for (currdev = 0, left = ndevs; (currdev != 0xff) && (left > 0); left--) { - bzero(pd, bigdev); - pda->next = currdev; - - /* get current configuration */ - if ((error = bios16(&args, PNP_GET_DEVNODE, &pda->next, &pda->node, 1))) { - printf("pnpbios: error %d making BIOS16 call\n", error); - break; - } - if (bootverbose) - printf("pnp_get_devnode cd=%d nxt=%d size=%d handle=%d devid=%08x type=%02x%02x%02x, attrib=%04x\n", currdev, pda->next, pd->size, pd->handle, pd->devid, pd->type[0], pd->type[1], pd->type[2], pd->attrib); - - if ((error = (args.r.eax & 0xff))) { - if (bootverbose) - printf("pnpbios: %s 0x%x fetching node %d\n", error & 0x80 ? "error" : "warning", error, currdev); - if (error & 0x80) - break; - } - currdev = pda->next; - if (pd->size < sizeof(struct pnp_sysdev)) { - printf("pnpbios: bogus system node data, aborting scan\n"); - break; - } - - /* - * Ignore PICs so that we don't have to worry about the PICs - * claiming IRQs to prevent their use. The PIC drivers - * already ensure that invalid IRQs are not used. - */ - if (!strcmp(pnp_eisaformat(pd->devid), "PNP0000")) /* ISA PIC */ - continue; - if (!strcmp(pnp_eisaformat(pd->devid), "PNP0003")) /* APIC */ - continue; - - /* Add the device and parse its resources */ - dev = BUS_ADD_CHILD(parent, ISA_ORDER_PNP, NULL, -1); - isa_set_vendorid(dev, pd->devid); - isa_set_logicalid(dev, pd->devid); - - /* - * It appears that some PnP BIOS doesn't allow us to re-enable - * the embedded system device once it is disabled. We shall - * mark all system device nodes as "cannot be disabled", regardless - * of actual settings in the device attribute byte. XXX - */ -#if 0 - isa_set_configattr(dev, - ((pd->attrib & PNPATTR_NODISABLE) ? 0 : ISACFGATTR_CANDISABLE) | - ((!(pd->attrib & PNPATTR_NOCONFIG) && - PNPATTR_CONFIG(pd->attrib) != PNPATTR_CONFIG_STATIC) - ? ISACFGATTR_DYNAMIC : 0)); -#endif - isa_set_configattr(dev, - (!(pd->attrib & PNPATTR_NOCONFIG) && - PNPATTR_CONFIG(pd->attrib) != PNPATTR_CONFIG_STATIC) - ? ISACFGATTR_DYNAMIC : 0); - - ISA_SET_CONFIG_CALLBACK(parent, dev, pnpbios_set_config, 0); - pnp_parse_resources(dev, &pd->devdata[0], - pd->size - sizeof(struct pnp_sysdev), 0); - if (!device_get_desc(dev)) - device_set_desc_copy(dev, pnp_eisaformat(pd->devid)); - - /* Find device IDs */ - devid = &pd->devid; - compid = NULL; - - /* look for a compatible device ID too */ - left = pd->size - sizeof(struct pnp_sysdev); - idx = 0; - while (idx < left) { - tag = pd->devdata[idx++]; - if (PNP_RES_TYPE(tag) == 0) { - /* Small resource */ - switch (PNP_SRES_NUM(tag)) { - case PNP_TAG_COMPAT_DEVICE: - compid = (u_int32_t *)(pd->devdata + idx); - if (bootverbose) - printf("pnpbios: node %d compat ID 0x%08x\n", pd->handle, *compid); - /* FALLTHROUGH */ - case PNP_TAG_END: - idx = left; - break; - default: - idx += PNP_SRES_LEN(tag); - break; - } - } else - /* Large resource, skip it */ - idx += *(u_int16_t *)(pd->devdata + idx) + 2; - } - if (bootverbose) { - printf("pnpbios: handle %d device ID %s (%08x)", - pd->handle, pnp_eisaformat(*devid), *devid); - if (compid != NULL) - printf(" compat ID %s (%08x)", - pnp_eisaformat(*compid), *compid); - printf("\n"); - } - } -} - -static device_method_t pnpbios_methods[] = { - /* Device interface */ - DEVMETHOD(device_identify, pnpbios_identify), - - { 0, 0 } -}; - -static driver_t pnpbios_driver = { - "pnpbios", - pnpbios_methods, - 1, /* no softc */ -}; - -static devclass_t pnpbios_devclass; - -DRIVER_MODULE(pnpbios, isa, pnpbios_driver, pnpbios_devclass, 0, 0); - -#endif /* PNPBIOS */ diff --git a/sys/platform/pc32/i386/pnpbios.c b/sys/platform/pc32/i386/pnpbios.c new file mode 100644 index 0000000000..601c22d38c --- /dev/null +++ b/sys/platform/pc32/i386/pnpbios.c @@ -0,0 +1,256 @@ +/*- + * Copyright (c) 2004 Joerg Sonnenberger + * + * Copyright (c) 1997 Michael Smith + * Copyright (c) 1998 Jonathan Lemon + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $DragonFly: src/sys/platform/pc32/i386/pnpbios.c,v 1.1 2004/04/29 12:11:16 joerg Exp $ + */ + +/* + * Code for dealing with the PnP-BIOS in x86 PC systems. + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +/* + * PnP BIOS interface; enumerate devices only known to the system + * BIOS and save information about them for later use. + */ + +struct pnp_sysdev +{ + uint16_t size; + uint8_t handle; + uint32_t devid; + uint8_t type[3]; + uint16_t attrib; + /* device-specific data comes here */ + uint8_t devdata[0]; +} __attribute__((__packed__)); + +#define PNPATTR_NODISABLE (1<<0) /* can't be disabled */ +#define PNPATTR_NOCONFIG (1<<1) /* can't be configured */ +#define PNPATTR_OUTPUT (1<<2) /* can be primary output */ +#define PNPATTR_INPUT (1<<3) /* can be primary input */ +#define PNPATTR_BOOTABLE (1<<4) /* can be booted from */ +#define PNPATTR_DOCK (1<<5) /* is a docking station */ +#define PNPATTR_REMOVEABLE (1<<6) /* device is removeable */ + +#define PNPATTR_CONFIG(a) (((a) >> 7) & 0x03) +#define PNPATTR_CONFIG_STATIC 0x00 +#define PNPATTR_CONFIG_DYNAMIC 0x01 +#define PNPATTR_CONFIG_DYNONLY 0x03 + +/* We have to cluster arguments within a 64k range for the bios16 call */ +struct pnp_sysdevargs +{ + uint16_t next; + uint16_t pad; + struct pnp_sysdev node; +}; + +/* + * This function is called after the bus has assigned resource + * locations for a logical device. + */ +static void +pnpbios_set_config(void *arg, struct isa_config *config, int enable) +{ +} + +/* + * Quiz the PnP BIOS, build a list of PNP IDs and resource data. + */ +static void +pnpbios_identify(driver_t *driver, device_t parent) +{ + struct PnPBIOS_table *pt = PnPBIOStable; + struct bios_args args; + struct pnp_sysdev *pd; + struct pnp_sysdevargs *pda; + uint16_t ndevs, bigdev; + int error, currdev; + uint8_t *devnodebuf, tag; + uint32_t *devid, *compid; + int idx, left; + device_t dev; + + /* no PnP BIOS information */ + if (pt == NULL) + return; + + /* ACPI already active */ + if (devclass_get_softc(devclass_find("ACPI"), 0) != NULL) + return; + + bzero(&args, sizeof(args)); + args.seg.code16.base = BIOS_PADDRTOVADDR(pt->pmentrybase); + args.seg.code16.limit = 0xffff; /* XXX ? */ + args.seg.data.base = BIOS_PADDRTOVADDR(pt->pmdataseg); + args.seg.data.limit = 0xffff; + args.entry = pt->pmentryoffset; + + if ((error = bios16(&args, PNP_COUNT_DEVNODES, &ndevs, &bigdev)) || (args.r.eax & 0xff)) + printf("pnpbios: error %d/%x getting device count/size limit\n", error, args.r.eax); + ndevs &= 0xff; /* clear high byte garbage */ + if (bootverbose) + printf("pnpbios: %d devices, largest %d bytes\n", ndevs, bigdev); + + devnodebuf = malloc(bigdev + (sizeof(struct pnp_sysdevargs) - sizeof(struct pnp_sysdev)), M_DEVBUF, M_NOWAIT); + pda = (struct pnp_sysdevargs *)devnodebuf; + pd = &pda->node; + + for (currdev = 0, left = ndevs; (currdev != 0xff) && (left > 0); left--) { + bzero(pd, bigdev); + pda->next = currdev; + + /* get current configuration */ + if ((error = bios16(&args, PNP_GET_DEVNODE, &pda->next, &pda->node, 1))) { + printf("pnpbios: error %d making BIOS16 call\n", error); + break; + } + if (bootverbose) + printf("pnp_get_devnode cd=%d nxt=%d size=%d handle=%d devid=%08x type=%02x%02x%02x, attrib=%04x\n", currdev, pda->next, pd->size, pd->handle, pd->devid, pd->type[0], pd->type[1], pd->type[2], pd->attrib); + + if ((error = (args.r.eax & 0xff))) { + if (bootverbose) + printf("pnpbios: %s 0x%x fetching node %d\n", error & 0x80 ? "error" : "warning", error, currdev); + if (error & 0x80) + break; + } + currdev = pda->next; + if (pd->size < sizeof(struct pnp_sysdev)) { + printf("pnpbios: bogus system node data, aborting scan\n"); + break; + } + + /* + * Ignore PICs so that we don't have to worry about the PICs + * claiming IRQs to prevent their use. The PIC drivers + * already ensure that invalid IRQs are not used. + */ + if (!strcmp(pnp_eisaformat(pd->devid), "PNP0000")) /* ISA PIC */ + continue; + if (!strcmp(pnp_eisaformat(pd->devid), "PNP0003")) /* APIC */ + continue; + + /* Add the device and parse its resources */ + dev = BUS_ADD_CHILD(parent, ISA_ORDER_PNP, NULL, -1); + isa_set_vendorid(dev, pd->devid); + isa_set_logicalid(dev, pd->devid); + + /* + * It appears that some PnP BIOS doesn't allow us to re-enable + * the embedded system device once it is disabled. We shall + * mark all system device nodes as "cannot be disabled", regardless + * of actual settings in the device attribute byte. XXX + */ +#if 0 + isa_set_configattr(dev, + ((pd->attrib & PNPATTR_NODISABLE) ? 0 : ISACFGATTR_CANDISABLE) | + ((!(pd->attrib & PNPATTR_NOCONFIG) && + PNPATTR_CONFIG(pd->attrib) != PNPATTR_CONFIG_STATIC) + ? ISACFGATTR_DYNAMIC : 0)); +#endif + isa_set_configattr(dev, + (!(pd->attrib & PNPATTR_NOCONFIG) && + PNPATTR_CONFIG(pd->attrib) != PNPATTR_CONFIG_STATIC) + ? ISACFGATTR_DYNAMIC : 0); + + ISA_SET_CONFIG_CALLBACK(parent, dev, pnpbios_set_config, 0); + pnp_parse_resources(dev, &pd->devdata[0], + pd->size - sizeof(struct pnp_sysdev), 0); + if (!device_get_desc(dev)) + device_set_desc_copy(dev, pnp_eisaformat(pd->devid)); + + /* Find device IDs */ + devid = &pd->devid; + compid = NULL; + + /* look for a compatible device ID too */ + left = pd->size - sizeof(struct pnp_sysdev); + idx = 0; + while (idx < left) { + tag = pd->devdata[idx++]; + if (PNP_RES_TYPE(tag) == 0) { + /* Small resource */ + switch (PNP_SRES_NUM(tag)) { + case PNP_TAG_COMPAT_DEVICE: + compid = (uint32_t *)(pd->devdata + idx); + if (bootverbose) + printf("pnpbios: node %d compat ID 0x%08x\n", pd->handle, *compid); + /* FALLTHROUGH */ + case PNP_TAG_END: + idx = left; + break; + default: + idx += PNP_SRES_LEN(tag); + break; + } + } else + /* Large resource, skip it */ + idx += *(uint16_t *)(pd->devdata + idx) + 2; + } + if (bootverbose) { + printf("pnpbios: handle %d device ID %s (%08x)", + pd->handle, pnp_eisaformat(*devid), *devid); + if (compid != NULL) + printf(" compat ID %s (%08x)", + pnp_eisaformat(*compid), *compid); + printf("\n"); + } + } +} + +static device_method_t pnpbios_methods[] = { + /* Device interface */ + DEVMETHOD(device_identify, pnpbios_identify), + + { 0, 0 } +}; + +static driver_t pnpbios_driver = { + "pnpbios", + pnpbios_methods, + 1, /* no softc */ +}; + +static devclass_t pnpbios_devclass; + +DRIVER_MODULE(pnpbios, isa, pnpbios_driver, pnpbios_devclass, 0, 0); -- 2.41.0