Import a good chunk of the PNP code from FreeBSD-5.x
authorMatthew Dillon <dillon@dragonflybsd.org>
Sat, 8 Nov 2003 02:55:19 +0000 (02:55 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Sat, 8 Nov 2003 02:55:19 +0000 (02:55 +0000)
sys/bus/isa/isavar.h
sys/bus/isa/pnp.c
sys/bus/isa/pnpparse.c
sys/bus/isa/pnpvar.h
sys/i386/i386/bios.c
sys/i386/include/pc/bios.h
sys/platform/pc32/i386/bios.c
sys/platform/pc32/include/pc/bios.h

index c6cbf48..3bdc571 100644 (file)
@@ -24,7 +24,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/isa/isavar.h,v 1.16.2.2 2000/10/29 13:07:56 nyan Exp $
- * $DragonFly: src/sys/bus/isa/isavar.h,v 1.4 2003/08/27 11:42:34 rob Exp $
+ * $DragonFly: src/sys/bus/isa/isavar.h,v 1.5 2003/11/08 02:55:16 dillon Exp $
  */
 
 #ifndef _ISA_ISAVAR_H_
@@ -113,9 +113,17 @@ enum isa_device_ivars {
        ISA_IVAR_VENDORID,
        ISA_IVAR_SERIAL,
        ISA_IVAR_LOGICALID,
-       ISA_IVAR_COMPATID
+       ISA_IVAR_COMPATID,
+       ISA_IVAR_CONFIGATTR
 };
 
+/*
+ * ISA_IVAR_CONFIGATTR bits
+ */
+#define ISACFGATTR_CANDISABLE  (1 << 0)        /* can be disabled */
+#define ISACFGATTR_DYNAMIC     (1 << 1)        /* dynamic configuration */
+#define ISACFGATTR_MULTI       (1 << 2)        /* multiple configurations */
+
 /*
  * Simplified accessors for isa devices
  */
@@ -144,6 +152,7 @@ ISA_ACCESSOR(vendorid, VENDORID, int)
 ISA_ACCESSOR(serial, SERIAL, int)
 ISA_ACCESSOR(logicalid, LOGICALID, int)
 ISA_ACCESSOR(compatid, COMPATID, int)
+ISA_ACCESSOR(configattr, CONFIGATTR, int)
 
 extern intrmask_t isa_irq_pending(void);
 extern intrmask_t isa_irq_mask(void);
index 784c273..af8e380 100644 (file)
@@ -24,7 +24,7 @@
  * SUCH DAMAGE.
  *
  *     $FreeBSD: src/sys/isa/pnp.c,v 1.5.2.1 2002/10/14 09:31:09 nyan Exp $
- *     $DragonFly: src/sys/bus/isa/pnp.c,v 1.3 2003/08/07 21:16:46 dillon Exp $
+ *     $DragonFly: src/sys/bus/isa/pnp.c,v 1.4 2003/11/08 02:55:16 dillon Exp $
  *      from: pnp.c,v 1.11 1999/05/06 22:11:19 peter Exp
  */
 
@@ -54,21 +54,49 @@ struct pnp_quirk {
        u_int32_t vendor_id;    /* Vendor of the card */
        u_int32_t logical_id;   /* ID of the device with quirk */
        int     type;
-#define PNP_QUIRK_WRITE_REG    1 /* Need to write a pnp register  */
        int     arg1;
        int     arg2;
 };
 
-struct pnp_quirk pnp_quirks[] = {
-       /*
-        * The Gravis UltraSound needs register 0xf2 to be set to 0xff
-        * to enable power.
-        * XXX need to know the logical device id.
-        */
-       { 0x0100561e /* GRV0001 */,     0,
-         PNP_QUIRK_WRITE_REG,  0xf2,    0xff },
+#define PNP_QUIRK_WRITE_REG    1 /* Need to write a pnp register  */
+#define PNP_QUIRK_EXTRA_IO     2 /* Has extra io ports */
 
-       { 0 }
+struct pnp_quirk pnp_quirks[] = {
+        /*
+         * The Gravis UltraSound needs register 0xf2 to be set to 0xff
+         * to enable power.
+         * XXX need to know the logical device id.
+         */
+        { 0x0100561e /* GRV0001 */,     0,
+          PNP_QUIRK_WRITE_REG,  0xf2,    0xff },
+        /*
+         * An emu8000 does not give us other than the first
+         * port.
+         */
+        { 0x0100561e /* GRV0001 */,     0,
+          PNP_QUIRK_WRITE_REG,  0xf2,    0xff },
+        /*
+         * An emu8000 does not give us other than the first
+         * port.
+         */
+        { 0x26008c0e /* SB16 */,        0x21008c0e,
+          PNP_QUIRK_EXTRA_IO,   0x400,   0x800 },
+        { 0x42008c0e /* SB32(CTL0042) */,       0x21008c0e,
+          PNP_QUIRK_EXTRA_IO,   0x400,   0x800 },
+        { 0x44008c0e /* SB32(CTL0044) */,       0x21008c0e,
+          PNP_QUIRK_EXTRA_IO,   0x400,   0x800 },
+        { 0x49008c0e /* SB32(CTL0049) */,       0x21008c0e,
+          PNP_QUIRK_EXTRA_IO,   0x400,   0x800 },
+        { 0xf1008c0e /* SB32(CTL00f1) */,       0x21008c0e,
+          PNP_QUIRK_EXTRA_IO,   0x400,   0x800 },
+        { 0xc1008c0e /* SB64(CTL00c1) */,       0x22008c0e,
+          PNP_QUIRK_EXTRA_IO,   0x400,   0x800 },
+        { 0xc5008c0e /* SB64(CTL00c5) */,       0x22008c0e,
+          PNP_QUIRK_EXTRA_IO,   0x400,   0x800 },
+        { 0xe4008c0e /* SB64(CTL00e4) */,       0x22008c0e,
+          PNP_QUIRK_EXTRA_IO,   0x400,   0x800 },
+
+        { 0 }
 };
 
 #ifdef PC98
@@ -375,8 +403,9 @@ pnp_set_config(void *arg, struct isa_config *config, int enable)
 /*
  * Process quirks for a logical device.. The card must be in Config state.
  */
-static void
-pnp_check_quirks(u_int32_t vendor_id, u_int32_t logical_id, int ldn)
+void
+pnp_check_quirks(u_int32_t vendor_id, u_int32_t logical_id,
+    int ldn, struct isa_config *config)
 {
        struct pnp_quirk *qp;
 
@@ -389,6 +418,23 @@ pnp_check_quirks(u_int32_t vendor_id, u_int32_t logical_id, int ldn)
                                pnp_write(PNP_SET_LDN, ldn);
                                pnp_write(qp->arg1, qp->arg2);
                                break;
+                       case PNP_QUIRK_EXTRA_IO:
+                               if (config == NULL)
+                                       break;
+                                if (qp->arg1 != 0) {
+                                        config->ic_nport++;
+                                        config->ic_port[config->ic_nport - 1] = config->ic_port[0];
+                                        config->ic_port[config->ic_nport - 1].ir_start += qp->arg1;
+                                        config->ic_port[config->ic_nport - 1].ir_end += qp->arg1;
+                                }
+                                if (qp->arg2 != 0) {
+                                        config->ic_nport++;
+                                        config->ic_port[config->ic_nport - 1] = config->ic_port[0];
+                                        config->ic_port[config->ic_nport - 1].ir_start += qp->arg2;
+                                        config->ic_port[config->ic_nport - 1].ir_end += qp->arg2;
+                                }
+                                break;
+
                        }
                }
        }
@@ -473,7 +519,7 @@ pnp_create_devices(device_t parent, pnp_id *p, int csn,
                         */
                        if (startres) {
                                pnp_parse_resources(dev, startres,
-                                                   resinfo - startres - 1);
+                                           resinfo - startres - 1, ldn);
                                dev = 0;
                                startres = 0;
                        }
@@ -483,7 +529,7 @@ pnp_create_devices(device_t parent, pnp_id *p, int csn,
                         * resources.
                         */
                        bcopy(resinfo, &logical_id, 4);
-                       pnp_check_quirks(p->vendor_id, logical_id, ldn);
+                       pnp_check_quirks(p->vendor_id, logical_id, ldn, NULL);
                        compat_id = 0;
                        dev = BUS_ADD_CHILD(parent, ISA_ORDER_PNP, NULL, -1);
                        if (desc)
@@ -514,7 +560,7 @@ pnp_create_devices(device_t parent, pnp_id *p, int csn,
                                break;
                        }
                        pnp_parse_resources(dev, startres,
-                                           resinfo - startres - 1);
+                                           resinfo - startres - 1, ldn);
                        dev = 0;
                        startres = 0;
                        scanning = 0;
index 692e75a..1723fda 100644 (file)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     $FreeBSD: src/sys/isa/pnpparse.c,v 1.2.2.3 2000/11/07 05:53:55 msmith Exp $
- *     $DragonFly: src/sys/bus/isa/pnpparse.c,v 1.3 2003/08/07 21:16:46 dillon Exp $
+ * $FreeBSD: src/sys/isa/pnpparse.c,v 1.14 2003/06/11 00:32:45 obrien Exp $
+ * $DragonFly: src/sys/bus/isa/pnpparse.c,v 1.4 2003/11/08 02:55:16 dillon Exp $
  */
 
 #include <sys/param.h>
 #include <sys/systm.h>
-#include <sys/kernel.h>
 #include <sys/malloc.h>
 #include <sys/module.h>
 #include <sys/bus.h>
+
+#include <machine/stdarg.h>
+
 #include "isavar.h"
 #include "pnpreg.h"
 #include "pnpvar.h"
 #define        MAXDEP  8
 
 #define I16(p) ((p)[0] + ((p)[1] << 8))
-#define I32(p) (I16(p) + (I16(p+2) << 16))
+#define I32(p) (I16(p) + (I16((p)+2) << 16))
+
+void
+pnp_printf(u_int32_t id, char *fmt, ...)
+{
+       va_list ap;
+
+       va_start(ap, fmt);
+       printf("%s: ", pnp_eisaformat(id));
+       vprintf(fmt, ap);
+       va_end(ap);
+}
+
+/* parse a single descriptor */
+
+static int
+pnp_parse_desc(device_t dev, u_char tag, u_char *res, int len,
+              struct isa_config *config, int ldn)
+{
+       char buf[100];
+       u_int32_t id;
+       u_int32_t compat_id;
+       int temp;
+
+       id = isa_get_logicalid(dev);
+
+       if (PNP_RES_TYPE(tag) == 0) {
+
+               /* Small resource */
+               switch (PNP_SRES_NUM(tag)) {
+
+               case PNP_TAG_VERSION:
+               case PNP_TAG_VENDOR:
+                       /* these descriptors are quietly ignored */
+                       break;
+
+               case PNP_TAG_LOGICAL_DEVICE:
+               case PNP_TAG_START_DEPENDANT:
+               case PNP_TAG_END_DEPENDANT:
+                       if (bootverbose)
+                               pnp_printf(id, "unexpected small tag %d\n",
+                                          PNP_SRES_NUM(tag));
+                       /* shouldn't happen; quit now */
+                       return (1);
+
+               case PNP_TAG_COMPAT_DEVICE:
+                       /*
+                        * Got a compatible device id resource.
+                        * Should keep a list of compat ids in the device.
+                        */
+                       bcopy(res, &compat_id, 4);
+                       if (isa_get_compatid(dev) == 0)
+                               isa_set_compatid(dev, compat_id);
+                       break;
+           
+               case PNP_TAG_IRQ_FORMAT:
+                       if (config->ic_nirq == ISA_NIRQ) {
+                               pnp_printf(id, "too many irqs\n");
+                               return (1);
+                       }
+                       if (I16(res) == 0) {
+                               /* a null descriptor */
+                               config->ic_irqmask[config->ic_nirq] = 0;
+                               config->ic_nirq++;
+                               break;
+                       }
+                       if (bootverbose)
+                               pnp_printf(id, "adding irq mask %#02x\n",
+                                          I16(res));
+                       config->ic_irqmask[config->ic_nirq] = I16(res);
+                       config->ic_nirq++;
+                       break;
+
+               case PNP_TAG_DMA_FORMAT:
+                       if (config->ic_ndrq == ISA_NDRQ) {
+                               pnp_printf(id, "too many drqs\n");
+                               return (1);
+                       }
+                       if (res[0] == 0) {
+                               /* a null descriptor */
+                               config->ic_drqmask[config->ic_ndrq] = 0;
+                               config->ic_ndrq++;
+                               break;
+                       }
+                       if (bootverbose)
+                               pnp_printf(id, "adding dma mask %#02x\n",
+                                          res[0]);
+                       config->ic_drqmask[config->ic_ndrq] = res[0];
+                       config->ic_ndrq++;
+                       break;
+
+               case PNP_TAG_IO_RANGE:
+                       if (config->ic_nport == ISA_NPORT) {
+                               pnp_printf(id, "too many ports\n");
+                               return (1);
+                       }
+                       if (res[6] == 0) {
+                               /* a null descriptor */
+                               config->ic_port[config->ic_nport].ir_start = 0;
+                               config->ic_port[config->ic_nport].ir_end = 0;
+                               config->ic_port[config->ic_nport].ir_size = 0;
+                               config->ic_port[config->ic_nport].ir_align = 0;
+                               config->ic_nport++;
+                               break;
+                       }
+                       if (bootverbose) {
+                               pnp_printf(id, "adding io range "
+                                          "%#x-%#x, size=%#x, "
+                                          "align=%#x\n",
+                                          I16(res + 1),
+                                          I16(res + 3) + res[6]-1,
+                                          res[6], res[5]);
+                       }
+                       config->ic_port[config->ic_nport].ir_start =
+                           I16(res + 1);
+                       config->ic_port[config->ic_nport].ir_end =
+                           I16(res + 3) + res[6] - 1;
+                       config->ic_port[config->ic_nport].ir_size = res[6];
+                       if (res[5] == 0) {
+                           /* Make sure align is at least one */
+                           res[5] = 1;
+                       }
+                       config->ic_port[config->ic_nport].ir_align = res[5];
+                       config->ic_nport++;
+                       pnp_check_quirks(isa_get_vendorid(dev),
+                                        isa_get_logicalid(dev), ldn, config);
+                       break;
+
+               case PNP_TAG_IO_FIXED:
+                       if (config->ic_nport == ISA_NPORT) {
+                               pnp_printf(id, "too many ports\n");
+                               return (1);
+                       }
+                       if (res[2] == 0) {
+                               /* a null descriptor */
+                               config->ic_port[config->ic_nport].ir_start = 0;
+                               config->ic_port[config->ic_nport].ir_end = 0;
+                               config->ic_port[config->ic_nport].ir_size = 0;
+                               config->ic_port[config->ic_nport].ir_align = 0;
+                               config->ic_nport++;
+                               break;
+                       }
+                       if (bootverbose) {
+                               pnp_printf(id, "adding fixed io range "
+                                          "%#x-%#x, size=%#x, "
+                                          "align=%#x\n",
+                                          I16(res),
+                                          I16(res) + res[2] - 1,
+                                          res[2], 1);
+                       }
+                       config->ic_port[config->ic_nport].ir_start = I16(res);
+                       config->ic_port[config->ic_nport].ir_end =
+                           I16(res) + res[2] - 1;
+                       config->ic_port[config->ic_nport].ir_size = res[2];
+                       config->ic_port[config->ic_nport].ir_align = 1;
+                       config->ic_nport++;
+                       break;
+
+               case PNP_TAG_END:
+                       if (bootverbose)
+                               pnp_printf(id, "end config\n");
+                       return (1);
+
+               default:
+                       /* Skip this resource */
+                       pnp_printf(id, "unexpected small tag %d\n",
+                                     PNP_SRES_NUM(tag));
+                       break;
+               }
+       } else {
+               /* Large resource */
+               switch (PNP_LRES_NUM(tag)) {
+
+               case PNP_TAG_ID_UNICODE:
+               case PNP_TAG_LARGE_VENDOR:
+                       /* these descriptors are quietly ignored */
+                       break;
+
+               case PNP_TAG_ID_ANSI:
+                       if (len > sizeof(buf) - 1)
+                               len = sizeof(buf) - 1;
+                       bcopy(res, buf, len);
+
+                       /*
+                        * Trim trailing spaces and garbage.
+                        */
+                       while (len > 0 && buf[len - 1] <= ' ')
+                               len--;
+                       buf[len] = '\0';
+                       device_set_desc_copy(dev, buf);
+                       break;
+                       
+               case PNP_TAG_MEMORY_RANGE:
+                       if (config->ic_nmem == ISA_NMEM) {
+                               pnp_printf(id, "too many memory ranges\n");
+                               return (1);
+                       }
+                       if (I16(res + 7) == 0) {
+                               /* a null descriptor */
+                               config->ic_mem[config->ic_nmem].ir_start = 0;
+                               config->ic_mem[config->ic_nmem].ir_end = 0;
+                               config->ic_mem[config->ic_nmem].ir_size = 0;
+                               config->ic_mem[config->ic_nmem].ir_align = 0;
+                               config->ic_nmem++;
+                               break;
+                       }
+                       if (bootverbose) {
+                               temp = I16(res + 7) << 8;
+                               pnp_printf(id, "adding memory range "
+                                          "%#x-%#x, size=%#x, "
+                                          "align=%#x\n",
+                                          I16(res + 1) << 8,
+                                          (I16(res + 3) << 8) + temp - 1,
+                                          temp, I16(res + 5));
+                       }
+                       config->ic_mem[config->ic_nmem].ir_start =
+                           I16(res + 1) << 8;
+                       config->ic_mem[config->ic_nmem].ir_end =
+                           (I16(res + 3) << 8) + (I16(res + 7) << 8) - 1;
+                       config->ic_mem[config->ic_nmem].ir_size =
+                           I16(res + 7) << 8;
+                       config->ic_mem[config->ic_nmem].ir_align = I16(res + 5);
+                       if (!config->ic_mem[config->ic_nmem].ir_align)
+                               config->ic_mem[config->ic_nmem].ir_align =
+                                   0x10000;
+                       config->ic_nmem++;
+                       break;
+
+               case PNP_TAG_MEMORY32_RANGE:
+                       if (config->ic_nmem == ISA_NMEM) {
+                               pnp_printf(id, "too many memory ranges\n");
+                               return (1);
+                       }
+                       if (I32(res + 13) == 0) {
+                               /* a null descriptor */
+                               config->ic_mem[config->ic_nmem].ir_start = 0;
+                               config->ic_mem[config->ic_nmem].ir_end = 0;
+                               config->ic_mem[config->ic_nmem].ir_size = 0;
+                               config->ic_mem[config->ic_nmem].ir_align = 0;
+                               config->ic_nmem++;
+                               break;
+                       }
+                       if (bootverbose) {
+                               pnp_printf(id, "adding memory32 range "
+                                          "%#x-%#x, size=%#x, "
+                                          "align=%#x\n",
+                                          I32(res + 1),
+                                          I32(res + 5) + I32(res + 13) - 1,
+                                          I32(res + 13), I32(res + 9));
+                       }
+                       config->ic_mem[config->ic_nmem].ir_start = I32(res + 1);
+                       config->ic_mem[config->ic_nmem].ir_end =
+                           I32(res + 5) + I32(res + 13) - 1;
+                       config->ic_mem[config->ic_nmem].ir_size = I32(res + 13);
+                       config->ic_mem[config->ic_nmem].ir_align = I32(res + 9);
+                       config->ic_nmem++;
+                       break;
+
+               case PNP_TAG_MEMORY32_FIXED:
+                       if (config->ic_nmem == ISA_NMEM) {
+                               pnp_printf(id, "too many memory ranges\n");
+                               return (1);
+                       }
+                       if (I32(res + 5) == 0) {
+                               /* a null descriptor */
+                               config->ic_mem[config->ic_nmem].ir_start = 0;
+                               config->ic_mem[config->ic_nmem].ir_end = 0;
+                               config->ic_mem[config->ic_nmem].ir_size = 0;
+                               config->ic_mem[config->ic_nmem].ir_align = 0;
+                               break;
+                       }
+                       if (bootverbose) {
+                               pnp_printf(id, "adding fixed memory32 range "
+                                          "%#x-%#x, size=%#x\n",
+                                          I32(res + 1),
+                                          I32(res + 1) + I32(res + 5) - 1,
+                                          I32(res + 5));
+                       }
+                       config->ic_mem[config->ic_nmem].ir_start = I32(res + 1);
+                       config->ic_mem[config->ic_nmem].ir_end =
+                           I32(res + 1) + I32(res + 5) - 1;
+                       config->ic_mem[config->ic_nmem].ir_size = I32(res + 5);
+                       config->ic_mem[config->ic_nmem].ir_align = 1;
+                       config->ic_nmem++;
+                       break;
+
+               default:
+                       /* Skip this resource */
+                       pnp_printf(id, "unexpected large tag %d\n",
+                                  PNP_SRES_NUM(tag));
+                       break;
+               }
+       }
+
+       return (0);
+}
+
+/*
+ * Parse a single "dependent" resource combination.
+ */
+
+u_char *
+pnp_parse_dependant(device_t dev, u_char *resources, int len,
+                    struct isa_config *config, int ldn)
+{
+       u_char *res;
+
+       res = pnp_scan_resources(dev, resources, len, config,
+                               ldn, pnp_parse_desc);
+       return(res);
+}
+
+static void
+pnp_merge_resources(device_t dev, struct isa_config *from,
+                   struct isa_config *to)
+{
+       device_t parent;
+       int i;
+
+       parent = device_get_parent(dev);
+       for (i = 0; i < from->ic_nmem; i++) {
+               if (to->ic_nmem == ISA_NMEM) {
+                       device_printf(parent, "too many memory ranges\n");
+                       return;
+               }
+               to->ic_mem[to->ic_nmem] = from->ic_mem[i];
+               to->ic_nmem++;
+       }
+       for (i = 0; i < from->ic_nport; i++) {
+               if (to->ic_nport == ISA_NPORT) {
+                       device_printf(parent, "too many port ranges\n");
+                       return;
+               }
+               to->ic_port[to->ic_nport] = from->ic_port[i];
+               to->ic_nport++;
+       }
+       for (i = 0; i < from->ic_nirq; i++) {
+               if (to->ic_nirq == ISA_NIRQ) {
+                       device_printf(parent, "too many irq ranges\n");
+                       return;
+               }
+               to->ic_irqmask[to->ic_nirq] = from->ic_irqmask[i];
+               to->ic_nirq++;
+       }
+       for (i = 0; i < from->ic_ndrq; i++) {
+               if (to->ic_ndrq == ISA_NDRQ) {
+                       device_printf(parent, "too many drq ranges\n");
+                       return;
+               }
+               to->ic_drqmask[to->ic_ndrq] = from->ic_drqmask[i];
+               to->ic_ndrq++;
+       }
+}
 
 /*
- * Parse resource data for Logical Devices.
+ * Parse resource data for Logical Devices, make a list of available
+ * resource configurations, and add them to the device.
  *
  * This function exits as soon as it gets an error reading *ANY*
  * Resource Data or it reaches the end of Resource Data.
  */
+
 void
-pnp_parse_resources(device_t dev, u_char *resources, int len)
+pnp_parse_resources(device_t dev, u_char *resources, int len, int ldn)
 {
-       device_t parent = device_get_parent(dev);
-       u_char tag, *resp, *resinfo;
-       int large_len, scanning = len;
-       u_int32_t id, compat_id;
+       struct isa_config *configs;
        struct isa_config *config;
-       int ncfgs = 1;
+       device_t parent;
        int priorities[1 + MAXDEP];
-       struct isa_config *configs;
-       char buf[100];
+       u_char *start;
+       u_char *p;
+       u_char tag;
+       u_int32_t id;
+       int ncfgs;
+       int l;
        int i;
 
+       parent = device_get_parent(dev);
        id = isa_get_logicalid(dev);
-       configs = (struct isa_config *)malloc(sizeof(*configs) * (1 + MAXDEP),
-                                               M_DEVBUF, M_NOWAIT);
+
+       configs = (struct isa_config *)malloc(sizeof(*configs)*(1 + MAXDEP),
+                                             M_DEVBUF, M_NOWAIT | M_ZERO);
        if (configs == NULL) {
-               device_printf(dev, "No memory to parse PNP data\n");
+               device_printf(parent, "No memory to parse PNP data\n");
                return;
        }
-       bzero(configs, sizeof(*configs) * (1 + MAXDEP));
        config = &configs[0];
        priorities[0] = 0;
-       resp = resources;
-       while (scanning > 0) {
-               tag = *resp++;
-               scanning--;
+       ncfgs = 1;
+
+       p = resources;
+       start = NULL;
+       while (len > 0) {
+               tag = *p++;
+               len--;
                if (PNP_RES_TYPE(tag) == 0) {
                        /* Small resource */
-                       if (scanning < PNP_SRES_LEN(tag)) {
-                               scanning = 0;
+                       l = PNP_SRES_LEN(tag);
+                       if (len < l) {
+                               len = 0;
                                continue;
                        }
-                       resinfo = resp;
-                       resp += PNP_SRES_LEN(tag);
-                       scanning -= PNP_SRES_LEN(tag);;
-                       
-                       switch (PNP_SRES_NUM(tag)) {
-                       case PNP_TAG_COMPAT_DEVICE:
-                               /*
-                                * Got a compatible device id
-                                * resource. Should keep a list of
-                                * compat ids in the device.
-                                */
-                               bcopy(resinfo, &compat_id, 4);
-                               isa_set_compatid(dev, compat_id);
-                               break;
-                   
-                       case PNP_TAG_IRQ_FORMAT:
-                               if (bootverbose) {
-                                       printf("%s: adding irq mask %#04x\n",
-                                              pnp_eisaformat(id),
-                                              I16(resinfo));
-                               }
-                               if (config->ic_nirq == ISA_NIRQ) {
-                                       device_printf(parent, "too many irqs\n");
-                                       scanning = 0;
-                                       break;
-                               }
-                               config->ic_irqmask[config->ic_nirq] =
-                                       I16(resinfo);
-                               config->ic_nirq++;
-                               break;
+                       len -= l;
 
-                       case PNP_TAG_DMA_FORMAT:
-                               if (bootverbose) {
-                                       printf("%s: adding dma mask %#02x\n",
-                                              pnp_eisaformat(id),
-                                              resinfo[0]);
-                               }
-                               if (config->ic_ndrq == ISA_NDRQ) {
-                                       device_printf(parent, "too many drqs\n");
-                                       scanning = 0;
-                                       break;
-                               }
-                               config->ic_drqmask[config->ic_ndrq] =
-                                       resinfo[0];
-                               config->ic_ndrq++;
-                               break;
+                       switch (PNP_SRES_NUM(tag)) {
 
                        case PNP_TAG_START_DEPENDANT:
-                               if (bootverbose) {
-                                       printf("%s: start dependant\n",
-                                              pnp_eisaformat(id));
+                               if (start != NULL) {
+                                       /*
+                                        * Copy the common resources first,
+                                        * then parse the "dependent" resources.
+                                        */
+                                       pnp_merge_resources(dev, &configs[0],
+                                                           config);
+                                       pnp_parse_dependant(dev, start,
+                                                           p - start - 1,
+                                                           config, ldn);
                                }
-                               if (ncfgs >= MAXDEP) {
+                               start = p + l;
+                               if (ncfgs > MAXDEP) {
                                        device_printf(parent, "too many dependant configs (%d)\n", MAXDEP);
-                                       scanning = 0;
+                                       len = 0;
                                        break;
                                }
                                config = &configs[ncfgs];
                                /*
                                 * If the priority is not specified,
-                                * then use the default of
-                                * 'acceptable'
+                                * then use the default of 'acceptable'
                                 */
-                               if (PNP_SRES_LEN(tag) > 0)
-                                       priorities[ncfgs] = resinfo[0];
+                               if (l > 0)
+                                       priorities[ncfgs] = p[0];
                                else
                                        priorities[ncfgs] = 1;
+                               if (bootverbose)
+                                       pnp_printf(id, "start dependent (%d)\n",
+                                                  priorities[ncfgs]);
                                ncfgs++;
                                break;
 
                        case PNP_TAG_END_DEPENDANT:
-                               if (bootverbose) {
-                                       printf("%s: end dependant\n",
-                                              pnp_eisaformat(id));
-                               }
-                               config = &configs[0];   /* back to main config */
-                               break;
-
-                       case PNP_TAG_IO_RANGE:
-                               if (bootverbose) {
-                                       printf("%s: adding io range "
-                                              "%#x-%#x, size=%#x, "
-                                              "align=%#x\n",
-                                              pnp_eisaformat(id),
-                                              I16(resinfo + 1),
-                                              I16(resinfo + 3) + resinfo[6]-1,
-                                              resinfo[6],
-                                              resinfo[5]);
-                               }
-                               if (config->ic_nport == ISA_NPORT) {
-                                       device_printf(parent, "too many ports\n");
-                                       scanning = 0;
+                               if (start == NULL) {
+                                       device_printf(parent,
+                                                     "malformed resources\n");
+                                       len = 0;
                                        break;
                                }
-                               config->ic_port[config->ic_nport].ir_start =
-                                       I16(resinfo + 1);
-                               config->ic_port[config->ic_nport].ir_end =
-                                       I16(resinfo + 3) + resinfo[6] - 1;
-                               config->ic_port[config->ic_nport].ir_size =
-                                       resinfo[6];
-                               if (resinfo[5] == 0) {
-                                   /* Make sure align is at least one */
-                                   resinfo[5] = 1;
-                               }
-                               config->ic_port[config->ic_nport].ir_align =
-                                       resinfo[5];
-                               config->ic_nport++;
-                               break;
-
-                       case PNP_TAG_IO_FIXED:
-                               if (bootverbose) {
-                                       printf("%s: adding fixed io range "
-                                              "%#x-%#x, size=%#x, "
-                                              "align=%#x\n",
-                                              pnp_eisaformat(id),
-                                              I16(resinfo),
-                                              I16(resinfo) + resinfo[2] - 1,
-                                              resinfo[2],
-                                              1);
-                               }
-                               if (config->ic_nport == ISA_NPORT) {
-                                       device_printf(parent, "too many ports\n");
-                                       scanning = 0;
-                                       break;
-                               }
-                               config->ic_port[config->ic_nport].ir_start =
-                                       I16(resinfo);
-                               config->ic_port[config->ic_nport].ir_end =
-                                       I16(resinfo) + resinfo[2] - 1;
-                               config->ic_port[config->ic_nport].ir_size
-                                       = resinfo[2];
-                               config->ic_port[config->ic_nport].ir_align = 1;
-                               config->ic_nport++;
+                               /*
+                                * Copy the common resources first,
+                                * then parse the "dependent" resources.
+                                */
+                               pnp_merge_resources(dev, &configs[0], config);
+                               pnp_parse_dependant(dev, start, p - start - 1,
+                                                   config, ldn);
+                               start = NULL;
+                               if (bootverbose)
+                                       pnp_printf(id, "end dependent\n");
+                               /*
+                                * Back to the common part; clear it
+                                * as its contents has already been copied
+                                * to each dependant.
+                                */
+                               config = &configs[0];
+                               bzero(config, sizeof(*config));
                                break;
 
                        case PNP_TAG_END:
-                               if (bootverbose) {
-                                       printf("%s: end config\n",
-                                              pnp_eisaformat(id));
+                               if (start != NULL) {
+                                       device_printf(parent,
+                                                     "malformed resources\n");
                                }
-                               scanning = 0;
+                               len = 0;
                                break;
 
                        default:
-                               /* Skip this resource */
-                               device_printf(parent, "unexpected small tag %d\n",
-                                             PNP_SRES_NUM(tag));
+                               if (start != NULL)
+                                       /* defer parsing a dependent section */
+                                       break;
+                               if (pnp_parse_desc(dev, tag, p, l, config, ldn))
+                                       len = 0;
                                break;
                        }
+                       p += l;
                } else {
                        /* Large resource */
-                       if (scanning < 2) {
-                               scanning = 0;
-                               continue;
-                       }
-                       large_len = I16(resp);
-                       resp += 2;
-                       scanning -= 2;
-
-                       if (scanning < large_len) {
-                               scanning = 0;
-                               continue;
-                       }
-                       resinfo = resp;
-                       resp += large_len;
-                       scanning -= large_len;
-
-                       switch (PNP_LRES_NUM(tag)) {
-                       case PNP_TAG_ID_ANSI:
-                               if (large_len > sizeof(buf) - 1)
-                                       large_len = sizeof(buf) - 1;
-                               bcopy(resinfo, buf, large_len);
-
-                               /*
-                                * Trim trailing spaces and garbage.
-                                */
-                               while (large_len > 0 && buf[large_len - 1] <= ' ')
-                                       large_len--;
-                               buf[large_len] = '\0';
-                               device_set_desc_copy(dev, buf);
-                               break;
-                               
-                       case PNP_TAG_MEMORY_RANGE:
-                               if (bootverbose) {
-                                       int temp = I16(resinfo + 7) << 8;
-
-                                       printf("%s: adding memory range "
-                                              "%#x-%#x, size=%#x, "
-                                              "align=%#x\n",
-                                              pnp_eisaformat(id),
-                                              I16(resinfo + 1)<<8,
-                                              (I16(resinfo + 3)<<8) + temp - 1,
-                                              temp,
-                                              I16(resinfo + 5));
-                               }
-
-                               if (config->ic_nmem == ISA_NMEM) {
-                                       device_printf(parent, "too many memory ranges\n");
-                                       scanning = 0;
-                                       break;
-                               }
-
-                               config->ic_mem[config->ic_nmem].ir_start =
-                                       I16(resinfo + 1)<<8;
-                               config->ic_mem[config->ic_nmem].ir_end =
-                                       (I16(resinfo + 3)<<8)
-                                       + (I16(resinfo + 7) << 8) - 1;
-                               config->ic_mem[config->ic_nmem].ir_size =
-                                       I16(resinfo + 7) << 8;
-                               config->ic_mem[config->ic_nmem].ir_align =
-                                       I16(resinfo + 5);
-                               if (!config->ic_mem[config->ic_nmem].ir_align)
-                                       config->ic_mem[config->ic_nmem]
-                                               .ir_align = 0x10000;
-                               config->ic_nmem++;
+                       if (len < 2) {
+                               len = 0;
                                break;
-
-                       case PNP_TAG_MEMORY32_RANGE:
-                               if (I32(resinfo + 13) == 0) {
-                                       if (bootverbose) {
-                                               printf("%s: skipping empty range\n",
-                                                      pnp_eisaformat(id));
-                                       }
-                                       continue;
-                               }
-                               if (bootverbose) {
-                                       printf("%s: adding memory32 range "
-                                              "%#x-%#x, size=%#x, "
-                                              "align=%#x\n",
-                                              pnp_eisaformat(id),
-                                              I32(resinfo + 1),
-                                              I32(resinfo + 5)
-                                              + I32(resinfo + 13) - 1,
-                                              I32(resinfo + 13),
-                                              I32(resinfo + 9));
-                               }
-
-                               if (config->ic_nmem == ISA_NMEM) {
-                                       device_printf(parent, "too many memory ranges\n");
-                                       scanning = 0;
-                                       break;
-                               }
-
-                               config->ic_mem[config->ic_nmem].ir_start =
-                                       I32(resinfo + 1);
-                               config->ic_mem[config->ic_nmem].ir_end =
-                                       I32(resinfo + 5)
-                                       + I32(resinfo + 13) - 1;
-                               config->ic_mem[config->ic_nmem].ir_size =
-                                       I32(resinfo + 13);
-                               config->ic_mem[config->ic_nmem].ir_align =
-                                       I32(resinfo + 9);
-                               config->ic_nmem++;
+                       }
+                       l = I16(p);
+                       p += 2;
+                       len -= 2;
+                       if (len < l) {
+                               len = 0;
                                break;
-
-                       case PNP_TAG_MEMORY32_FIXED:
-                               if (I32(resinfo + 5) == 0) {
-                                       if (bootverbose) {
-                                               printf("%s: skipping empty range\n",
-                                                      pnp_eisaformat(id));
-                                       }
-                                       continue;
-                               }
-                               if (bootverbose) {
-                                       printf("%s: adding fixed memory32 range "
-                                              "%#x-%#x, size=%#x\n",
-                                              pnp_eisaformat(id),
-                                              I32(resinfo + 1),
-                                              I32(resinfo + 1)
-                                              + I32(resinfo + 5) - 1,
-                                              I32(resinfo + 5));
-                               }
-
-                               if (config->ic_nmem == ISA_NMEM) {
-                                       device_printf(parent, "too many memory ranges\n");
-                                       scanning = 0;
-                                       break;
-                               }
-
-                               config->ic_mem[config->ic_nmem].ir_start =
-                                       I32(resinfo + 1);
-                               config->ic_mem[config->ic_nmem].ir_end =
-                                       I32(resinfo + 1)
-                                       + I32(resinfo + 5) - 1;
-                               config->ic_mem[config->ic_nmem].ir_size =
-                                       I32(resinfo + 5);
-                               config->ic_mem[config->ic_nmem].ir_align = 1;
-                               config->ic_nmem++;
+                       }
+                       len -= l;
+                       if (start == NULL &&
+                           pnp_parse_desc(dev, tag, p, l, config, ldn)) {
+                               len = 0;
                                break;
-
-                       default:
-                               /* Skip this resource */
-                               device_printf(parent, "unexpected large tag %d\n",
-                                             PNP_SRES_NUM(tag));
                        }
+                       p += l;
                }
        }
-       if(ncfgs == 1) {
+
+       if (ncfgs == 1) {
                /* Single config without dependants */
-               (void)ISA_ADD_CONFIG(parent, dev, priorities[0], &configs[0]);
+               ISA_ADD_CONFIG(parent, dev, priorities[0], &configs[0]);
                free(configs, M_DEVBUF);
                return;
        }
-       /* Cycle through dependant configs merging primary details */
-       for(i = 1; i < ncfgs; i++) {
-               int j;
-               config = &configs[i];
-               for(j = 0; j < configs[0].ic_nmem; j++) {
-                       if (config->ic_nmem == ISA_NMEM) {
-                               device_printf(parent, "too many memory ranges\n");
-                               free(configs, M_DEVBUF);
-                               return;
-                       }
-                       config->ic_mem[config->ic_nmem] = configs[0].ic_mem[j];
-                       config->ic_nmem++;
-               }
-               for(j = 0; j < configs[0].ic_nport; j++) {
-                       if (config->ic_nport == ISA_NPORT) {
-                               device_printf(parent, "too many port ranges\n");
-                               free(configs, M_DEVBUF);
-                               return;
-                       }
-                       config->ic_port[config->ic_nport] = configs[0].ic_port[j];
-                       config->ic_nport++;
-               }
-               for(j = 0; j < configs[0].ic_nirq; j++) {
-                       if (config->ic_nirq == ISA_NIRQ) {
-                               device_printf(parent, "too many irq ranges\n");
-                               free(configs, M_DEVBUF);
-                               return;
-                       }
-                       config->ic_irqmask[config->ic_nirq] = configs[0].ic_irqmask[j];
-                       config->ic_nirq++;
-               }
-               for(j = 0; j < configs[0].ic_ndrq; j++) {
-                       if (config->ic_ndrq == ISA_NDRQ) {
-                               device_printf(parent, "too many drq ranges\n");
-                               free(configs, M_DEVBUF);
-                               return;
-                       }
-                       config->ic_drqmask[config->ic_ndrq] = configs[0].ic_drqmask[j];
-                       config->ic_ndrq++;
-               }
-               (void)ISA_ADD_CONFIG(parent, dev, priorities[i], &configs[i]);
+
+       for (i = 1; i < ncfgs; i++) {
+               /*
+                * Merge the remaining part of the common resources,
+                * if any. Strictly speaking, there shouldn't be common/main
+                * resources after the END_DEPENDENT tag.
+                */
+               pnp_merge_resources(dev, &configs[0], &configs[i]);
+               ISA_ADD_CONFIG(parent, dev, priorities[i], &configs[i]);
        }
+
        free(configs, M_DEVBUF);
 }
+
+u_char *
+pnp_scan_resources(device_t dev, u_char *resources, int len,
+                   struct isa_config *config, int ldn, pnp_scan_cb *cb)
+{
+       u_char *p;
+       u_char tag;
+       int l;
+
+       p = resources;
+       while (len > 0) {
+               tag = *p++;
+               len--;
+               if (PNP_RES_TYPE(tag) == 0) {
+                       /* small resource */
+                       l = PNP_SRES_LEN(tag);
+                       if (len < l)
+                               break;
+                       if ((*cb)(dev, tag, p, l, config, ldn))
+                               return (p + l);
+                       if (PNP_SRES_NUM(tag) == PNP_TAG_END)
+                               return (p + l);
+               } else {
+                       /* large resource */
+                       if (len < 2)
+                               break;
+                       l = I16(p);
+                       p += 2;
+                       len -= 2;
+                       if (len < l)
+                               break;
+                       if ((*cb)(dev, tag, p, l, config, ldn))
+                               return (p + l);
+               }
+               p += l;
+               len -= l;
+       }
+       return NULL;
+}
index 52960e2..a1c6b76 100644 (file)
@@ -23,8 +23,8 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     $FreeBSD: src/sys/isa/pnpvar.h,v 1.4 1999/12/29 04:54:36 peter Exp $
- *     $DragonFly: src/sys/bus/isa/pnpvar.h,v 1.2 2003/06/17 04:28:40 dillon Exp $
+ * $FreeBSD: src/sys/isa/pnpvar.h,v 1.6 2001/09/05 03:54:28 yokota Exp $
+ * $DragonFly: src/sys/bus/isa/pnpvar.h,v 1.3 2003/11/08 02:55:16 dillon Exp $
  */
 
 #ifndef _ISA_PNPVAR_H_
@@ -53,8 +53,20 @@ u_char  pnp_read(int d); /* currently unused, but who knows... */
         | (PNP_HEXTONUM(s[6]) << 24)           \
         | (PNP_HEXTONUM(s[5]) << 28))
 
+struct isa_config;
+
+typedef int pnp_scan_cb(device_t dev, u_char tag, u_char *res, int len,
+                       struct isa_config *config, int ldn);
+
 char *pnp_eisaformat(u_int32_t id);
-void pnp_parse_resources(device_t dev, u_char *resources, int len);
+void pnp_printf(u_int32_t id, char *fmt, ...);
+void pnp_parse_resources(device_t dev, u_char *resources, int len, int ldn);
+u_char *pnp_parse_dependant(device_t dev, u_char *resources, int len,
+                           struct isa_config *config, int ldn);
+u_char *pnp_scan_resources(device_t dev, u_char *resources, int len,
+                          struct isa_config *config, int ldn, pnp_scan_cb *cb);
+
+void pnp_check_quirks(u_int32_t vendor_id, u_int32_t logical_id, int ldn, struct isa_config *config);
 
 #endif /* _KERNEL */
 
index acb2bb1..75b2302 100644 (file)
@@ -25,7 +25,7 @@
  * 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.6 2003/11/07 18:28:52 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/bios.c,v 1.7 2003/11/08 02:55:17 dillon Exp $
  */
 
 /*
@@ -476,6 +476,10 @@ struct pnp_sysdev
     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 */
@@ -483,18 +487,17 @@ struct pnp_sysdev
 #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
-#define PNPATTR_CONFIG(a)      (((a) >> 7) & 0x03)
-    /* device-specific data comes here */
-    u_int8_t   devdata[0];
-} __packed;
 
 /* 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;
 };
 
@@ -529,7 +532,7 @@ pnpbios_identify(driver_t *driver, device_t parent)
        return;
 
     /* ACPI already active */
-    if (devlass_get_softc(devclass_find("ACPI"), 0) != NULL)
+    if (devclass_get_softc(devclass_find("ACPI"), 0) != NULL)
        return;
     
     bzero(&args, sizeof(args));
@@ -552,11 +555,15 @@ pnpbios_identify(driver_t *driver, device_t parent)
     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);
@@ -578,7 +585,7 @@ pnpbios_identify(driver_t *driver, device_t parent)
            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);
@@ -588,14 +595,15 @@ pnpbios_identify(driver_t *driver, device_t parent)
         * 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
+        * 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)
@@ -603,7 +611,7 @@ pnpbios_identify(driver_t *driver, device_t parent)
 
        ISA_SET_CONFIG_CALLBACK(parent, dev, pnpbios_set_config, 0);
        pnp_parse_resources(dev, &pd->devdata[0],
-                           pd->size - sizeof(struct pnp_sysdev));
+                           pd->size - sizeof(struct pnp_sysdev), 0);
        if (!device_get_desc(dev))
            device_set_desc_copy(dev, pnp_eisaformat(pd->devid));
 
index a421616..db56568 100644 (file)
@@ -25,7 +25,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/include/pc/bios.h,v 1.7.2.3 2001/10/21 03:16:56 yokota Exp $
- * $DragonFly: src/sys/i386/include/pc/Attic/bios.h,v 1.2 2003/06/17 04:28:36 dillon Exp $
+ * $DragonFly: src/sys/i386/include/pc/Attic/bios.h,v 1.3 2003/11/08 02:55:19 dillon Exp $
  */
 
 /* 
@@ -169,6 +169,22 @@ struct bios_args {
  *     i       = int (32 bits)
  *     p       = pointer (converted to seg:offset)
  *     C,D,U   = selector (corresponding to code/data/utility segment)
+ *
+ * GetDevNodes(0x01, nodenumptr, nodebuf, control, biossel)
+ *
+ *     Required.  if *nodenumptr is 0 the system bios will return the
+ *     first node.  On return *nodenumptr will contain the next node
+ *     number or 0xFFh if no more nodes exist.
+ *
+ *     Control flag: bit 1: do not get info for how the device will be
+ *                          configured for the next boot.
+ *                   bit 0: do not get info on how the device is configured
+ *                          right now.
+ *                   bit 0 or bit 1 must be set. 0 is illegal, both are
+ *                          illegal.
+ *
+ *     Returns %ax 0 if success, !0 if an error (bit 7 set) or warning
+ *     occured.
  */
 #define PNP_COUNT_DEVNODES     "sppD",         0x00
 #define PNP_GET_DEVNODE                "sppsD",        0x01
index 0d938e6..55dad44 100644 (file)
@@ -25,7 +25,7 @@
  * 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.6 2003/11/07 18:28:52 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/bios.c,v 1.7 2003/11/08 02:55:17 dillon Exp $
  */
 
 /*
@@ -476,6 +476,10 @@ struct pnp_sysdev
     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 */
@@ -483,18 +487,17 @@ struct pnp_sysdev
 #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
-#define PNPATTR_CONFIG(a)      (((a) >> 7) & 0x03)
-    /* device-specific data comes here */
-    u_int8_t   devdata[0];
-} __packed;
 
 /* 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;
 };
 
@@ -529,7 +532,7 @@ pnpbios_identify(driver_t *driver, device_t parent)
        return;
 
     /* ACPI already active */
-    if (devlass_get_softc(devclass_find("ACPI"), 0) != NULL)
+    if (devclass_get_softc(devclass_find("ACPI"), 0) != NULL)
        return;
     
     bzero(&args, sizeof(args));
@@ -552,11 +555,15 @@ pnpbios_identify(driver_t *driver, device_t parent)
     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);
@@ -578,7 +585,7 @@ pnpbios_identify(driver_t *driver, device_t parent)
            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);
@@ -588,14 +595,15 @@ pnpbios_identify(driver_t *driver, device_t parent)
         * 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
+        * 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)
@@ -603,7 +611,7 @@ pnpbios_identify(driver_t *driver, device_t parent)
 
        ISA_SET_CONFIG_CALLBACK(parent, dev, pnpbios_set_config, 0);
        pnp_parse_resources(dev, &pd->devdata[0],
-                           pd->size - sizeof(struct pnp_sysdev));
+                           pd->size - sizeof(struct pnp_sysdev), 0);
        if (!device_get_desc(dev))
            device_set_desc_copy(dev, pnp_eisaformat(pd->devid));
 
index 40ca2a2..8c73600 100644 (file)
@@ -25,7 +25,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/i386/include/pc/bios.h,v 1.7.2.3 2001/10/21 03:16:56 yokota Exp $
- * $DragonFly: src/sys/platform/pc32/include/pc/bios.h,v 1.2 2003/06/17 04:28:36 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/include/pc/bios.h,v 1.3 2003/11/08 02:55:19 dillon Exp $
  */
 
 /* 
@@ -169,6 +169,22 @@ struct bios_args {
  *     i       = int (32 bits)
  *     p       = pointer (converted to seg:offset)
  *     C,D,U   = selector (corresponding to code/data/utility segment)
+ *
+ * GetDevNodes(0x01, nodenumptr, nodebuf, control, biossel)
+ *
+ *     Required.  if *nodenumptr is 0 the system bios will return the
+ *     first node.  On return *nodenumptr will contain the next node
+ *     number or 0xFFh if no more nodes exist.
+ *
+ *     Control flag: bit 1: do not get info for how the device will be
+ *                          configured for the next boot.
+ *                   bit 0: do not get info on how the device is configured
+ *                          right now.
+ *                   bit 0 or bit 1 must be set. 0 is illegal, both are
+ *                          illegal.
+ *
+ *     Returns %ax 0 if success, !0 if an error (bit 7 set) or warning
+ *     occured.
  */
 #define PNP_COUNT_DEVNODES     "sppD",         0x00
 #define PNP_GET_DEVNODE                "sppsD",        0x01