示例#1
0
static void
atpic_isa_identify(driver_t *drv, device_t parent)
{
	device_t child;

	child = BUS_ADD_CHILD(parent, ISA_ORDER_SENSITIVE, drv->name, -1);
	device_set_driver(child, drv);
	isa_set_logicalid(child, atpic_ids[0].ip_id);
	isa_set_vendorid(child, atpic_ids[0].ip_id);

	bus_set_resource(child, SYS_RES_IOPORT, ATPIC_MASTER, IO_ICU1, 2);
	bus_set_resource(child, SYS_RES_IOPORT, ATPIC_SLAVE, IO_ICU2, 2);

	/* ISA interrupts are routed through external interrupt 0. */
	bus_set_resource(child, SYS_RES_IRQ, 0, PIC_IRQ_EXT(0), 1);
}
示例#2
0
文件: es1888.c 项目: MarginC/kame
static void
es1888_identify(driver_t *driver, device_t parent)
{
/*
 * Only use this on alpha since PNPBIOS is a better solution on x86.
 */
#ifdef __alpha__
	u_int32_t lo, hi;
	device_t dev;

	es1888_set_port(0x220);
	if (es1888_reset(0x220))
		return;

	/*
	 * Check identification bytes for es1888.
	 */
	if (es1888_dspwr(0x220, 0xe7))
		return;
	hi = es1888_get_byte(0x220);
	lo = es1888_get_byte(0x220);
	if (hi != 0x68 || (lo & 0xf0) != 0x80)
		return;

	/*
	 * Program irq and drq.
	 */
	if (es1888_dspwr(0x220, 0xc6) /* enter extended mode */
	    || es1888_dspwr(0x220, 0xb1) /* write register b1 */
	    || es1888_dspwr(0x220, 0x14) /* enable irq 5 */
	    || es1888_dspwr(0x220, 0xb2) /* write register b1 */
	    || es1888_dspwr(0x220, 0x18)) /* enable drq 1 */
		return;

	/*
	 * Create the device and program its resources.
	 */
	dev = BUS_ADD_CHILD(parent, ISA_ORDER_PNP, NULL, -1);
	bus_set_resource(dev, SYS_RES_IOPORT, 0, 0x220, 0x10);
	bus_set_resource(dev, SYS_RES_IRQ, 0, 5, 1);
	bus_set_resource(dev, SYS_RES_DRQ, 0, 1, 1);
	isa_set_vendorid(dev, PNP_EISAID("ESS1888"));
	isa_set_logicalid(dev, PNP_EISAID("ESS1888"));
#endif
}
示例#3
0
static void
isa_setup_children(device_t dev, phandle_t parent)
{
	struct isa_regs *regs;
	struct resource_list *rl;
	device_t cdev;
	u_int64_t end, start;
	ofw_isa_intr_t *intrs, rintr;
	phandle_t node;
	uint32_t *drqs, *regidx;
	int i, ndrq, nintr, nreg, nregidx, rid, rtype;
	char *name;

	/*
	 * Loop through children and fake up PnP devices for them.
	 * Their resources are added as fully mapped and specified because
	 * adjusting the resources and the resource list entries respectively
	 * in isa_alloc_resource() causes trouble with drivers which use
	 * rman_get_start(), pass-through or allocate and release resources
	 * multiple times, etc. Adjusting the resources might be better off
	 * in a bus_activate_resource method but the common ISA code doesn't
	 * allow for an isa_activate_resource().
	 */
	for (node = OF_child(parent); node != 0; node = OF_peer(node)) {
		if ((OF_getprop_alloc(node, "name", 1, (void **)&name)) == -1)
			continue;

		/*
		 * Keyboard and mouse controllers hang off of the `8042'
		 * node but we have no real use for the `8042' itself.
		 */
		if (strcmp(name, "8042") == 0) {
			isa_setup_children(dev, node);
			free(name, M_OFWPROP);
			continue;
		}

		for (i = 0; ofw_isa_pnp_map[i].name != NULL; i++)
			if (strcmp(ofw_isa_pnp_map[i].name, name) == 0)
				break;
		if (ofw_isa_pnp_map[i].name == NULL) {
			device_printf(dev, "no PnP map entry for node "
			    "0x%lx: %s\n", (unsigned long)node, name);
			free(name, M_OFWPROP);
			continue;
		}

		if ((cdev = BUS_ADD_CHILD(dev, ISA_ORDER_PNPBIOS, NULL, -1)) ==
		    NULL)
			panic("isa_setup_children: BUS_ADD_CHILD failed");
		isa_set_logicalid(cdev, ofw_isa_pnp_map[i].id);
		isa_set_vendorid(cdev, ofw_isa_pnp_map[i].id);

		rl = BUS_GET_RESOURCE_LIST(dev, cdev);
		nreg = OF_getprop_alloc(node, "reg", sizeof(*regs),
		    (void **)&regs);
		for (i = 0; i < nreg; i++) {
			start = ISA_REG_PHYS(&regs[i]);
			end = start + regs[i].size - 1;
			rtype = ofw_isa_range_map(isab_ranges, isab_nrange,
			    &start, &end, NULL);
			rid = 0;
			while (resource_list_find(rl, rtype, rid) != NULL)
				rid++;
			bus_set_resource(cdev, rtype, rid, start,
			    end - start + 1);
		}
		if (nreg == -1 && parent != isab_node) {
			/*
			 * The "reg" property still might be an index into
			 * the set of registers of the parent device like
			 * with the nodes hanging off of the `8042' node.
			 */
			nregidx = OF_getprop_alloc(node, "reg", sizeof(*regidx),
			    (void **)&regidx);
			if (nregidx > 2)
				panic("isa_setup_children: impossible number "
				    "of register indices");
			if (nregidx != -1 && (nreg = OF_getprop_alloc(parent,
			    "reg", sizeof(*regs), (void **)&regs)) >= nregidx) {
				for (i = 0; i < nregidx; i++) {
					start = ISA_REG_PHYS(&regs[regidx[i]]);
					end = start + regs[regidx[i]].size - 1;
					rtype = ofw_isa_range_map(isab_ranges,
					    isab_nrange, &start, &end, NULL);
					rid = 0;
					while (resource_list_find(rl, rtype,
					    rid) != NULL)
						rid++;
					bus_set_resource(cdev, rtype, rid,
					    start, end - start + 1);
				}
			}
			if (regidx != NULL)
				free(regidx, M_OFWPROP);
		}
		if (regs != NULL)
			free(regs, M_OFWPROP);

		nintr = OF_getprop_alloc(node, "interrupts", sizeof(*intrs),
		    (void **)&intrs);
		for (i = 0; i < nintr; i++) {
			if (intrs[i] > 7)
				panic("isa_setup_children: intr too large");
			rintr = ofw_isa_route_intr(device_get_parent(dev), node,
			    &isa_iinfo, intrs[i]);
			if (rintr == PCI_INVALID_IRQ) {
				device_printf(dev, "could not map ISA "
				    "interrupt %d for node 0x%lx: %s\n",
				    intrs[i], (unsigned long)node, name);
				continue;
			}
			bus_set_resource(cdev, SYS_RES_IRQ, i, rintr, 1);
		}
		if (intrs != NULL)
			free(intrs, M_OFWPROP);

		ndrq = OF_getprop_alloc(node, "dma-channel", sizeof(*drqs),
		    (void **)&drqs);
		for (i = 0; i < ndrq; i++)
			bus_set_resource(cdev, SYS_RES_DRQ, i, drqs[i], 1);
		if (drqs != NULL)
			free(drqs, M_OFWPROP);

		/*
		 * Devices using DMA hang off of the `dma' node instead of
		 * directly from the ISA bridge node.
		 */
		if (strcmp(name, "dma") == 0)
			isa_setup_children(dev, node);

		free(name, M_OFWPROP);
	}
}
示例#4
0
文件: orm.c 项目: JabirTech/Source
static void
orm_identify(driver_t* driver, device_t parent)
{
	bus_space_handle_t	bh;
	bus_space_tag_t		bt;
	device_t		child;
	u_int32_t		chunk = IOMEM_START;
	struct resource		*res;
	int			rid;
	u_int32_t		rom_size;
	struct orm_softc	*sc;
	u_int8_t		buf[3];

	child = BUS_ADD_CHILD(parent, ISA_ORDER_SENSITIVE, "orm", -1);
	device_set_driver(child, driver);
	isa_set_logicalid(child, ORM_ID);
	isa_set_vendorid(child, ORM_ID);
	sc = device_get_softc(child);
	sc->rnum = 0;
	while (chunk < IOMEM_END) {
		bus_set_resource(child, SYS_RES_MEMORY, sc->rnum, chunk,
		    IOMEM_STEP);
		rid = sc->rnum;
		res = bus_alloc_resource_any(child, SYS_RES_MEMORY, &rid,
		    RF_ACTIVE);
		if (res == NULL) {
			bus_delete_resource(child, SYS_RES_MEMORY, sc->rnum);
			chunk += IOMEM_STEP;
			continue;
		}
		bt = rman_get_bustag(res);
		bh = rman_get_bushandle(res);
		bus_space_read_region_1(bt, bh, 0, buf, sizeof(buf));

		/*
		 * We need to release and delete the resource since we're
		 * changing its size, or the rom isn't there.  There
		 * is a checksum field in the ROM to prevent false
		 * positives.  However, some common hardware (IBM thinkpads)
		 * neglects to put a valid checksum in the ROM, so we do
		 * not double check the checksum here.  On the ISA bus
		 * areas that have no hardware read back as 0xff, so the
		 * tests to see if we have 0x55 followed by 0xaa are
		 * generally sufficient.
		 */
		bus_release_resource(child, SYS_RES_MEMORY, rid, res);
		bus_delete_resource(child, SYS_RES_MEMORY, sc->rnum);
		if (buf[0] != 0x55 || buf[1] != 0xAA || (buf[2] & 0x03) != 0) {
			chunk += IOMEM_STEP;
			continue;
		}
		rom_size = buf[2] << 9;
		bus_set_resource(child, SYS_RES_MEMORY, sc->rnum, chunk,
		    rom_size);
		rid = sc->rnum;
		res = bus_alloc_resource_any(child, SYS_RES_MEMORY, &rid, 0);
		if (res == NULL) {
			bus_delete_resource(child, SYS_RES_MEMORY, sc->rnum);
			chunk += IOMEM_STEP;
			continue;
		}
		sc->rid[sc->rnum] = rid;
		sc->res[sc->rnum] = res;
		sc->rnum++;
		chunk += rom_size;
	}

	if (sc->rnum == 0)
		device_delete_child(parent, child);
	else if (sc->rnum == 1)
		device_set_desc(child, "ISA Option ROM");
	else
		device_set_desc(child, "ISA Option ROMs");
}
示例#5
0
/*
 * 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;

    /*
     * 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);
}