sys/platform/pc32/i386/pnpbios.c
static int
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;

    /*
     * Umm, we aren't going to rescan the PnP BIOS to look for new additions.
     */
    if (device_get_state(parent) == DS_ATTACHED)
	return (0);
        
    /* no PnP BIOS information */
    if (pt == NULL)
	return (ENXIO);

    /* ACPI already active */
    if (devclass_get_softc(devclass_find("ACPI"), 0) != NULL)
	return (ENXIO);
    
    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))
	kprintf("pnpbios: error %d/%x getting device count/size limit\n", error, args.r.eax);
    ndevs &= 0xff;				/* clear high byte garbage */
    if (bootverbose)
	kprintf("pnpbios: %d devices, largest %d bytes\n", ndevs, bigdev);

    devnodebuf = kmalloc(bigdev + (sizeof(struct pnp_sysdevargs) - sizeof(struct pnp_sysdev)), M_DEVBUF, M_INTWAIT);
    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))) {
	    kprintf("pnpbios: error %d making BIOS16 call\n", error);
	    break;
	}
	if (bootverbose)
	    kprintf("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)
		kprintf("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)) {
	    kprintf("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, 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)
			kprintf("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) {
	    kprintf("pnpbios: handle %d device ID %s (%08x)", 
		   pd->handle, pnp_eisaformat(*devid), *devid);
	    if (compid != NULL)
		kprintf(" compat ID %s (%08x)",
		       pnp_eisaformat(*compid), *compid);
	    kprintf("\n");
	}
    }
    return (0);
}
/*
 * Quiz the PnP BIOS, build a list of PNP IDs and resource data.
 */
Quiz the PnP BIOS, build a list of PNP IDs and resource data.
Quiz the PnP BIOS build a list of PNP IDs and resource data .
static int
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;
    if (device_get_state(parent) == DS_ATTACHED)
	return (0);
    if (pt == NULL)
	return (ENXIO);
    if (devclass_get_softc(devclass_find("ACPI"), 0) != NULL)
	return (ENXIO);
    bzero(&args, sizeof(args));
    args.seg.code16.base = BIOS_PADDRTOVADDR(pt->pmentrybase);
    args.seg.code16.limit = 0xffff;		
    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))
	kprintf("pnpbios: error %d/%x getting device count/size limit\n", error, args.r.eax);
    ndevs &= 0xff;				
    if (bootverbose)
	kprintf("pnpbios: %d devices, largest %d bytes\n", ndevs, bigdev);
    devnodebuf = kmalloc(bigdev + (sizeof(struct pnp_sysdevargs) - sizeof(struct pnp_sysdev)), M_DEVBUF, M_INTWAIT);
    pda = (struct pnp_sysdevargs *)devnodebuf;
    pd = &pda->node;
    for (currdev = 0, left = ndevs; (currdev != 0xff) && (left > 0); left--) {
	bzero(pd, bigdev);
	pda->next = currdev;
	if ((error = bios16(&args, PNP_GET_DEVNODE, &pda->next, &pda->node, 1))) {
	    kprintf("pnpbios: error %d making BIOS16 call\n", error);
	    break;
	}
	if (bootverbose)
	    kprintf("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)
		kprintf("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)) {
	    kprintf("pnpbios: bogus system node data, aborting scan\n");
	    break;
	}
	if (!strcmp(pnp_eisaformat(pd->devid), "PNP0000"))	
	    continue;
	if (!strcmp(pnp_eisaformat(pd->devid), "PNP0003"))	
	    continue;
	dev = BUS_ADD_CHILD(parent, parent, ISA_ORDER_PNP, NULL, -1);
	isa_set_vendorid(dev, pd->devid);
	isa_set_logicalid(dev, pd->devid);
#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));
	devid = &pd->devid;
	compid = NULL;
	left = pd->size - sizeof(struct pnp_sysdev);
	idx = 0;
	while (idx < left) {
	    tag = pd->devdata[idx++];
	    if (PNP_RES_TYPE(tag) == 0) {
		switch (PNP_SRES_NUM(tag)) {
		case PNP_TAG_COMPAT_DEVICE:
		    compid = (uint32_t *)(pd->devdata + idx);
		    if (bootverbose)
			kprintf("pnpbios: node %d compat ID 0x%08x\n", pd->handle, *compid);
		case PNP_TAG_END:
		    idx = left;
		    break;
		default:
		    idx += PNP_SRES_LEN(tag);
		    break;
		}
	    } else
		idx += *(uint16_t *)(pd->devdata + idx) + 2;
	}
	if (bootverbose) {
	    kprintf("pnpbios: handle %d device ID %s (%08x)", 
		   pd->handle, pnp_eisaformat(*devid), *devid);
	    if (compid != NULL)
		kprintf(" compat ID %s (%08x)",
		       pnp_eisaformat(*compid), *compid);
	    kprintf("\n");
	}
    }
    return (0);
}
static int 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 ; if ( device_get_state ( parent ) == DS_ATTACHED ) return ( 0 ) ; if ( pt == NULL ) return ( ENXIO ) ; if ( devclass_get_softc ( devclass_find ( " " ) , 0 ) != NULL ) return ( ENXIO ) ; bzero ( & args , sizeof ( args ) ) ; args . seg . code16 . base = BIOS_PADDRTOVADDR ( pt -> pmentrybase ) ; args . seg . code16 . limit = 0xffff ; 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 ) ) kprintf ( " \n " , error , args . r . eax ) ; ndevs &= 0xff ; if ( bootverbose ) kprintf ( " \n " , ndevs , bigdev ) ; devnodebuf = kmalloc ( bigdev + ( sizeof ( struct pnp_sysdevargs ) - sizeof ( struct pnp_sysdev ) ) , M_DEVBUF , M_INTWAIT ) ; pda = ( struct pnp_sysdevargs * ) devnodebuf ; pd = & pda -> node ; for ( currdev = 0 , left = ndevs ; ( currdev != 0xff ) && ( left > 0 ) ; left -- ) { bzero ( pd , bigdev ) ; pda -> next = currdev ; if ( ( error = bios16 ( & args , PNP_GET_DEVNODE , & pda -> next , & pda -> node , 1 ) ) ) { kprintf ( " \n " , error ) ; break ; } if ( bootverbose ) kprintf ( " \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 ) kprintf ( " \n " , error & 0x80 ? " " : " " , error , currdev ) ; if ( error & 0x80 ) break ; } currdev = pda -> next ; if ( pd -> size < sizeof ( struct pnp_sysdev ) ) { kprintf ( " \n " ) ; break ; } if ( ! strcmp ( pnp_eisaformat ( pd -> devid ) , " " ) ) continue ; if ( ! strcmp ( pnp_eisaformat ( pd -> devid ) , " " ) ) continue ; dev = BUS_ADD_CHILD ( parent , parent , ISA_ORDER_PNP , NULL , -1 ) ; isa_set_vendorid ( dev , pd -> devid ) ; isa_set_logicalid ( dev , pd -> devid ) ; #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 ) ) ; devid = & pd -> devid ; compid = NULL ; left = pd -> size - sizeof ( struct pnp_sysdev ) ; idx = 0 ; while ( idx < left ) { tag = pd -> devdata [ idx ++ ] ; if ( PNP_RES_TYPE ( tag ) == 0 ) { switch ( PNP_SRES_NUM ( tag ) ) { case PNP_TAG_COMPAT_DEVICE : compid = ( uint32_t * ) ( pd -> devdata + idx ) ; if ( bootverbose ) kprintf ( " \n " , pd -> handle , * compid ) ; case PNP_TAG_END : idx = left ; break ; default : idx += PNP_SRES_LEN ( tag ) ; break ; } } else idx += * ( uint16_t * ) ( pd -> devdata + idx ) + 2 ; } if ( bootverbose ) { kprintf ( " " , pd -> handle , pnp_eisaformat ( * devid ) , * devid ) ; if ( compid != NULL ) kprintf ( " " , pnp_eisaformat ( * compid ) , * compid ) ; kprintf ( " \n " ) ; } } return ( 0 ) ; }
Quiz the PnP BIOS, build a list of PNP IDs and resource data.
Quiz the PnP BIOS build a list of PNP IDs and resource data .
/*
     * Umm, we aren't going to rescan the PnP BIOS to look for new additions.
     */ /* no PnP BIOS information */ /* ACPI already active */ /* XXX ? */ /* clear high byte garbage */ /* get current configuration */ /*
	 * 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.
	 */ /* ISA PIC */ /* APIC */ /* Add the device and parse its resources */ /*
	 * 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
	 */ /* Find device IDs */ /* look for a compatible device ID too */ /* Small resource */ /* FALLTHROUGH */ /* Large resource, skip it */