Ejemplo n.º 1
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);
	}
}
Ejemplo n.º 2
0
/*
 * Non-destructive identify.
 */
static void
ex_isa_identify(driver_t *driver, device_t parent)
{
	device_t	child;
	bus_addr_t	ioport;
	u_char 		enaddr[6];
	u_int		irq;
	int		tmp;
	const char *	desc;
	struct ex_softc sc;
	int		rid;

	if (bootverbose)
		printf("ex_isa_identify()\n");

	for (ioport = 0x200; ioport < 0x3a0; ioport += 0x10) {
		rid = 0;
		sc.ioport = bus_alloc_resource(parent, SYS_RES_IOPORT, &rid,
		    ioport, ioport, 0x10, RF_ACTIVE);
		if (sc.ioport == NULL)
			continue;

		/* No board found at address */
		if (!ex_look_for_card(&sc)) {
			bus_release_resource(parent, SYS_RES_IOPORT, rid,
			    sc.ioport);
			continue;
		}

		if (bootverbose)
			printf("ex: Found card at 0x%03lx!\n", (unsigned long)ioport);

		/* Board in PnP mode */
		if (ex_eeprom_read(&sc, EE_W0) & EE_W0_PNP) {
			/* Reset the card. */
			CSR_WRITE_1(&sc, CMD_REG, Reset_CMD);
			DELAY(500);
			if (bootverbose)
				printf("ex: card at 0x%03lx in PnP mode!\n", (unsigned long)ioport);
			bus_release_resource(parent, SYS_RES_IOPORT, rid,
			    sc.ioport);
			continue;
		}

		bzero(enaddr, sizeof(enaddr));

		/* Reset the card. */
		CSR_WRITE_1(&sc, CMD_REG, Reset_CMD);
		DELAY(400);

		ex_get_address(&sc, enaddr);
		tmp = ex_eeprom_read(&sc, EE_W1) & EE_W1_INT_SEL;

		/* work out which set of irq <-> internal tables to use */
		if (ex_card_type(enaddr) == CARD_TYPE_EX_10_PLUS) {
			irq  = plus_ee2irqmap[tmp];
			desc = "Intel Pro/10+";
		} else {
			irq = ee2irqmap[tmp];
			desc = "Intel Pro/10";
		}

		bus_release_resource(parent, SYS_RES_IOPORT, rid, sc.ioport);
		child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "ex", -1);
		device_set_desc_copy(child, desc);
		device_set_driver(child, driver);
		bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1);
		bus_set_resource(child, SYS_RES_IOPORT, 0, ioport, EX_IOSIZE);
		if (bootverbose)
			printf("ex: Adding board at 0x%03lx, irq %d\n",
			   (unsigned long)ioport, irq);
	}

	return;
}
Ejemplo n.º 3
0
static int
ex_isa_probe(device_t dev)
{
	bus_addr_t	iobase;
	u_int		irq;
	char *		irq2ee;
	u_char *	ee2irq;
	u_char 		enaddr[6];
	int		tmp;
	int		error;
	struct ex_softc *sc = device_get_softc(dev);

	/* Check isapnp ids */
	error = ISA_PNP_PROBE(device_get_parent(dev), dev, ex_ids);

	/* If the card had a PnP ID that didn't match any we know about */
	if (error == ENXIO)
		return(error);

	/* If we had some other problem. */
	if (!(error == 0 || error == ENOENT))
		return(error);

	error = ex_alloc_resources(dev);
	if (error != 0)
		goto bad;
	iobase = bus_get_resource_start(dev, SYS_RES_IOPORT, 0);
	if (!ex_look_for_card(sc)) {
		if (bootverbose)
			printf("ex: no card found at 0x%03lx.\n", (unsigned long)iobase);
		error = ENXIO;
		goto bad;
	}
	if (bootverbose)
		printf("ex: ex_isa_probe() found card at 0x%03lx\n", (unsigned long)iobase);

	/*
	 * Reset the card.
	 */
	CSR_WRITE_1(sc, CMD_REG, Reset_CMD);
	DELAY(800);

	ex_get_address(sc, enaddr);

	/* work out which set of irq <-> internal tables to use */
	if (ex_card_type(enaddr) == CARD_TYPE_EX_10_PLUS) {
		irq2ee = plus_irq2eemap;
		ee2irq = plus_ee2irqmap;
	} else {
		irq2ee = irq2eemap;
		ee2irq = ee2irqmap;
	}

	tmp = ex_eeprom_read(sc, EE_W1) & EE_W1_INT_SEL;
	irq = bus_get_resource_start(dev, SYS_RES_IRQ, 0);
	if (irq > 0) {
		/* This will happen if board is in PnP mode. */
		if (ee2irq[tmp] != irq) {
			device_printf(dev,
			    "WARNING: IRQ mismatch: EEPROM %d, using %d\n",
				ee2irq[tmp], irq);
		}
	} else {
		irq = ee2irq[tmp];
		bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1);
	}

	if (irq == 0) {
		printf("ex: invalid IRQ.\n");
		error = ENXIO;
	}

bad:;
	ex_release_resources(dev);
	return (error);
}
Ejemplo n.º 4
0
static int
snc_isa_probe(device_t dev)
{
	struct snc_softc *sc = device_get_softc(dev);
	int type;
 	int error = 0;

	bzero(sc, sizeof(struct snc_softc));

	/* Check isapnp ids */
	error = ISA_PNP_PROBE(device_get_parent(dev), dev, snc_ids);

	/* If the card had a PnP ID that didn't match any we know about */
	if (error == ENXIO) {
		return(error);
	}

	switch (error) {
	case 0:		/* Matched PnP */
		type = SNEC_TYPE_PNP;
		break;

	case ENOENT:	/* Legacy ISA */
		type = SNEC_TYPE_LEGACY;
		break;

	default:	/* If we had some other problem. */
		return(error);
	}

	if (type == SNEC_TYPE_PNP && isa_get_portsize(dev) == 0) {
		int port;
		int rid = 0;
		struct resource *res = NULL;

		for (port = 0x0888; port <= 0x3888; port += 0x1000) {
			bus_set_resource(dev, SYS_RES_IOPORT, rid,
					 port, SNEC_NREGS);
			res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
						 0ul, ~0ul, SNEC_NREGS,
						 0 /* !RF_ACTIVE */);
			if (res) break;
		}

		printf("snc_isa_probe: broken PnP resource, ");
		if (res) {
			printf("use port 0x%x\n", port);
			bus_release_resource(dev, SYS_RES_IOPORT, rid, res);
			snc_isapnp_reconfig(dev);
		} else {
			printf("and can't find port\n");
		}
	}

	error = snc_alloc_port(dev, 0);
	error = max(error, snc_alloc_memory(dev, 0));
	error = max(error, snc_alloc_irq(dev, 0, 0));

	if (!error && !snc_probe(dev, type))
		error = ENOENT;

	snc_release_resources(dev);
	return (error);
}
Ejemplo n.º 5
0
static int
intsmb_attach(device_t dev)
{
	struct intsmb_softc *sc = device_get_softc(dev);
	int error, rid, value;
	int intr;
	char *str;

	sc->dev = dev;

	mtx_init(&sc->lock, device_get_nameunit(dev), "intsmb", MTX_DEF);

	sc->cfg_irq9 = 0;
#ifndef NO_CHANGE_PCICONF
	switch (pci_get_devid(dev)) {
	case 0x71138086:	/* Intel 82371AB */
	case 0x719b8086:	/* Intel 82443MX */
		/* Changing configuration is allowed. */
		sc->cfg_irq9 = 1;
		break;
	}
#endif

	rid = PCI_BASE_ADDR_SMB;
	sc->io_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
	    RF_ACTIVE);
	if (sc->io_res == NULL) {
		device_printf(dev, "Could not allocate I/O space\n");
		error = ENXIO;
		goto fail;
	}

	if (sc->cfg_irq9) {
		pci_write_config(dev, PCIR_INTLINE, 0x9, 1);
		pci_write_config(dev, PCI_HST_CFG_SMB,
		    PCI_INTR_SMB_IRQ9 | PCI_INTR_SMB_ENABLE, 1);
	}
	value = pci_read_config(dev, PCI_HST_CFG_SMB, 1);
	sc->poll = (value & PCI_INTR_SMB_ENABLE) == 0;
	intr = value & PCI_INTR_SMB_MASK;
	switch (intr) {
	case PCI_INTR_SMB_SMI:
		str = "SMI";
		break;
	case PCI_INTR_SMB_IRQ9:
		str = "IRQ 9";
		break;
	case PCI_INTR_SMB_IRQ_PCI:
		str = "PCI IRQ";
		break;
	default:
		str = "BOGUS";
	}

	device_printf(dev, "intr %s %s ", str,
	    sc->poll == 0 ? "enabled" : "disabled");
	printf("revision %d\n", pci_read_config(dev, PCI_REVID_SMB, 1));

	if (!sc->poll && intr == PCI_INTR_SMB_SMI) {
		device_printf(dev,
		    "using polling mode when configured interrupt is SMI\n");
		sc->poll = 1;
	}

	if (sc->poll)
	    goto no_intr;

	if (intr != PCI_INTR_SMB_IRQ9 && intr != PCI_INTR_SMB_IRQ_PCI) {
		device_printf(dev, "Unsupported interrupt mode\n");
		error = ENXIO;
		goto fail;
	}

	/* Force IRQ 9. */
	rid = 0;
	if (sc->cfg_irq9)
		bus_set_resource(dev, SYS_RES_IRQ, rid, 9, 1);

	sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
	    RF_SHAREABLE | RF_ACTIVE);
	if (sc->irq_res == NULL) {
		device_printf(dev, "Could not allocate irq\n");
		error = ENXIO;
		goto fail;
	}

	error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
	    NULL, intsmb_rawintr, sc, &sc->irq_hand);
	if (error) {
		device_printf(dev, "Failed to map intr\n");
		goto fail;
	}

no_intr:
	sc->isbusy = 0;
	sc->smbus = device_add_child(dev, "smbus", -1);
	if (sc->smbus == NULL) {
		error = ENXIO;
		goto fail;
	}
	error = device_probe_and_attach(sc->smbus);
	if (error)
		goto fail;

#ifdef ENABLE_ALART
	/* Enable Arart */
	bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, PIIX4_SMBSLVCNT_ALTEN);
#endif
	return (0);

fail:
	intsmb_detach(dev);
	return (error);
}
Ejemplo n.º 6
0
static int
viapm_pro_probe(device_t dev)
{
	struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
#ifdef VIAPM_BASE_ADDR
	u_int32_t l;
#endif
	u_int32_t base_cfgreg;
	char *desc;

	switch (pci_get_devid(dev)) {
	case VIA_596A_PMU_ID:
		desc = "VIA VT82C596A Power Management Unit";
		viapm->type = VIAPM_TYP_596B;
		base_cfgreg = VIAPM_PRO_BASE;
		goto viapro;

	case VIA_596B_PMU_ID:
		desc = "VIA VT82C596B Power Management Unit";
		viapm->type = VIAPM_TYP_596B;
		base_cfgreg = VIAPM_PRO_BASE;
		goto viapro;

	case VIA_686A_PMU_ID:
		desc = "VIA VT82C686A Power Management Unit";
		viapm->type = VIAPM_TYP_686A;
		base_cfgreg = VIAPM_PRO_BASE;
		goto viapro;

	case VIA_8233_PMU_ID:
	case VIA_8233A_PMU_ID:
		desc = "VIA VT8233 Power Management Unit";
		viapm->type = VIAPM_TYP_UNKNOWN;
		base_cfgreg = VIAPM_8233_BASE;
		goto viapro;

	case VIA_8235_PMU_ID:
		desc = "VIA VT8235 Power Management Unit";
		viapm->type = VIAPM_TYP_UNKNOWN;
		base_cfgreg = VIAPM_8233_BASE;
		goto viapro;

	case VIA_8237_PMU_ID:
		desc = "VIA VT8237 Power Management Unit";
		viapm->type = VIAPM_TYP_UNKNOWN;
		base_cfgreg = VIAPM_8233_BASE;
		goto viapro;

	case VIA_CX700_PMU_ID:
		desc = "VIA CX700 Power Management Unit";
		viapm->type = VIAPM_TYP_UNKNOWN;
		base_cfgreg = VIAPM_8233_BASE;
		goto viapro;

	viapro:

#ifdef VIAPM_BASE_ADDR
		/* force VIAPM I/O base address */

		/* enable the SMBus controller function */
		l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1);
		pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 1, 1);

		/* write the base address */
		pci_write_config(dev, base_cfgreg,
				 VIAPM_BASE_ADDR & VIAPM_PRO_BA_MASK, 4);
#endif

		viapm->base = pci_read_config(dev, base_cfgreg, 4) & VIAPM_PRO_BA_MASK;

		/*
		 * We have to set the I/O resources by hand because it is
		 * described outside the viapmope of the traditional maps
		 */
		viapm->iorid = base_cfgreg;
		if (bus_set_resource(dev, SYS_RES_IOPORT, viapm->iorid,
				     viapm->base, 16)) {
			device_printf(dev, "could not set bus resource 0x%x\n",
					viapm->base);
			return ENXIO;
		}

		if (bootverbose) {
			device_printf(dev, "SMBus I/O base at 0x%x\n", viapm->base);
		}

		device_set_desc(dev, desc);
		return (BUS_PROBE_DEFAULT);

	default:
		break;
	}

	return ENXIO;
}
Ejemplo n.º 7
0
/*
 * Probe for Allied-Telesis RE1000Plus/ME1500 series.
 */
static int
fe_probe_jli(device_t dev)
{
	struct fe_softc *sc = device_get_softc(dev);
	int i, n, xirq, error;
	u_long iobase, irq;
	u_char eeprom [JLI_EEPROM_SIZE];
	u_short const * irqmap;

	static u_short const baseaddr [8] =
		{ 0x1D6, 0x1D8, 0x1DA, 0x1D4, 0x0D4, 0x0D2, 0x0D8, 0x0D0 };
	static struct fe_simple_probe_struct const probe_table [] = {
	/*	{ FE_DLCR1,  0x20, 0x00 },	Doesn't work. */
		{ FE_DLCR2,  0x50, 0x00 },
		{ FE_DLCR4,  0x08, 0x00 },
	/*	{ FE_DLCR5,  0x80, 0x00 },	Doesn't work. */
#if 0
		{ FE_BMPR16, 0x1B, 0x00 },
		{ FE_BMPR17, 0x7F, 0x00 },
#endif
		{ 0 }
	};

	/*
	 * See if the specified address is possible for MB86965A JLI mode.
	 */
	if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, NULL) != 0)
		return ENXIO;
	for (i = 0; i < 8; i++) {
		if (baseaddr[i] == iobase)
			break;
	}
	if (i == 8)
		return ENXIO;

	if (fe98_alloc_port(dev, FE_TYPE_RE1000))
		return ENXIO;

	/* Fill the softc struct with default values.  */
	fe_softc_defaults(sc);

	/*
	 * We should test if MB86965A is on the base address now.
	 * Unfortunately, it is very hard to probe it reliably, since
	 * we have no way to reset the chip under software control.
	 * On cold boot, we could check the "signature" bit patterns
	 * described in the Fujitsu document.  On warm boot, however,
	 * we can predict almost nothing about register values.
	 */
	if (!fe_simple_probe(sc, probe_table))
		return ENXIO;

	/* Check if our I/O address matches config info on 86965.  */
	n = (fe_inb(sc, FE_BMPR19) & FE_B19_ADDR) >> FE_B19_ADDR_SHIFT;
	if (baseaddr[n] != iobase)
		return ENXIO;

	/*
	 * We are now almost sure we have an MB86965 at the given
	 * address.  So, read EEPROM through it.  We have to write
	 * into LSI registers to read from EEPROM.  I want to avoid it
	 * at this stage, but I cannot test the presence of the chip
	 * any further without reading EEPROM.  FIXME.
	 */
	fe_read_eeprom_jli(sc, eeprom);

	/* Make sure that config info in EEPROM and 86965 agree.  */
	if (eeprom[FE_EEPROM_CONF] != fe_inb(sc, FE_BMPR19))
		return ENXIO;

	/* Use 86965 media selection scheme, unless othewise
           specified.  It is "AUTO always" and "select with BMPR13".
           This behaviour covers most of the 86965 based board (as
           minimum requirements.)  It is backward compatible with
           previous versions, also.  */
	sc->mbitmap = MB_HA;
	sc->defmedia = MB_HA;
	sc->msel = fe_msel_965;

	/* Perform board-specific probe.  */
	if ((irqmap = fe_probe_jli_re1000p(sc, eeprom)) == NULL)
		return ENXIO;

	/* Find the IRQ read from EEPROM.  */
	n = (fe_inb(sc, FE_BMPR19) & FE_B19_IRQ) >> FE_B19_IRQ_SHIFT;
	xirq = irqmap[n];

	/* Try to determine IRQ setting.  */
	error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL);
	if (error && xirq == NO_IRQ) {
		/* The device must be configured with an explicit IRQ.  */
		device_printf(dev, "IRQ auto-detection does not work\n");
		return ENXIO;
	} else if (error && xirq != NO_IRQ) {
		/* Just use the probed IRQ value.  */
		bus_set_resource(dev, SYS_RES_IRQ, 0, xirq, 1);
	} else if (!error && xirq == NO_IRQ) {
		/* No problem.  Go ahead.  */
	} else if (irq == xirq) {
		/* Good.  Go ahead.  */
	} else {
		/* User must be warned in this case.  */
		sc->stability |= UNSTABLE_IRQ;
	}

	/* Setup a hook, which resets te 86965 when the driver is being
           initialized.  This may solve a nasty bug.  FIXME.  */
	sc->init = fe_init_jli;

	return 0;
}
Ejemplo n.º 8
0
ACPI_STATUS
AcpiOsInstallInterruptHandler(UINT32 InterruptNumber,
    ACPI_OSD_HANDLER ServiceRoutine, void *Context)
{
    struct acpi_softc	*sc;
    u_int flags;

    ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);

    if ((sc = devclass_get_softc(devclass_find("acpi"), 0)) == NULL)
	panic("can't find ACPI device to register interrupt");
    if (sc->acpi_dev == NULL)
	panic("acpi softc has invalid device");

    /*
     * Configure SCI mode
     */
    acpi_sci_config();

    /*
     * This could happen:
     * - SCI is disabled by user
     * - No suitable interrupt mode for SCI
     */
    if (!acpi_sci_enabled())
	return_ACPI_STATUS (AE_OK);

    if (InterruptNumber < 0 || InterruptNumber > 255)
	return_ACPI_STATUS (AE_BAD_PARAMETER);
    if (ServiceRoutine == NULL)
	return_ACPI_STATUS (AE_BAD_PARAMETER);
    if (InterruptHandler != NULL) {
	device_printf(sc->acpi_dev, "interrupt handler already installed\n");
	return_ACPI_STATUS (AE_ALREADY_EXISTS);
    }
    InterruptHandler = ServiceRoutine;

    flags = RF_ACTIVE;
    if (acpi_sci_pci_shariable())
	flags |= RF_SHAREABLE;

    /* Set up the interrupt resource. */
    sc->acpi_irq_rid = 0;
    bus_set_resource(sc->acpi_dev, SYS_RES_IRQ, 0, InterruptNumber, 1);
    sc->acpi_irq = bus_alloc_resource_any(sc->acpi_dev, SYS_RES_IRQ,
	&sc->acpi_irq_rid, flags);
    if (sc->acpi_irq == NULL) {
	device_printf(sc->acpi_dev, "could not allocate interrupt\n");
	goto error;
    }
    if (bus_setup_intr(sc->acpi_dev, sc->acpi_irq, 0,
		    InterruptWrapper, Context, &sc->acpi_irq_handle, NULL)) {
	device_printf(sc->acpi_dev, "could not set up interrupt\n");
	goto error;
    }

    return_ACPI_STATUS (AE_OK);

error:
    if (sc->acpi_irq_handle)
	bus_teardown_intr(sc->acpi_dev, sc->acpi_irq, sc->acpi_irq_handle);
    sc->acpi_irq_handle = NULL;
    if (sc->acpi_irq)
	bus_release_resource(sc->acpi_dev, SYS_RES_IRQ, 0, sc->acpi_irq);
    sc->acpi_irq = NULL;
    bus_delete_resource(sc->acpi_dev, SYS_RES_IRQ, 0);
    InterruptHandler = NULL;

    return_ACPI_STATUS (AE_ALREADY_EXISTS);
}
Ejemplo n.º 9
0
static int
sbc_attach(device_t dev)
{
	char *err = NULL;
	struct sbc_softc *scp;
	struct sndcard_func *func;
	u_int32_t logical_id = isa_get_logicalid(dev);
    	int flags = device_get_flags(dev);
	int f, dh, dl, x, irq, i;

    	if (!logical_id && (flags & DV_F_DUAL_DMA)) {
        	bus_set_resource(dev, SYS_RES_DRQ, 1,
				 flags & DV_F_DRQ_MASK, 1);
    	}

	scp = device_get_softc(dev);
	bzero(scp, sizeof(*scp));
	scp->dev = dev;
	sbc_lockinit(scp);
	err = "alloc_resource";
	if (alloc_resource(scp)) goto bad;

	err = "sb_reset_dsp";
	if (sb_reset_dsp(scp->io[0])) goto bad;
	err = "sb_identify_board";
	scp->bd_ver = sb_identify_board(scp->io[0]) & 0x00000fff;
	if (scp->bd_ver == 0) goto bad;
	f = 0;
	if (logical_id == 0x01200000 && scp->bd_ver < 0x0400) scp->bd_ver = 0x0499;
	switch ((scp->bd_ver & 0x0f00) >> 8) {
    	case 1: /* old sound blaster has nothing... */
		break;

    	case 2:
		f |= BD_F_DUP_MIDI;
		if (scp->bd_ver > 0x200) f |= BD_F_MIX_CT1335;
		break;

	case 5:
		f |= BD_F_ESS;
		scp->bd_ver = 0x0301;
    	case 3:
		f |= BD_F_DUP_MIDI | BD_F_MIX_CT1345;
		break;

    	case 4:
    		f |= BD_F_SB16 | BD_F_MIX_CT1745;
		if (scp->drq[0]) dl = rman_get_start(scp->drq[0]); else dl = -1;
		if (scp->drq[1]) dh = rman_get_start(scp->drq[1]); else dh = dl;
		if (!logical_id && (dh < dl)) {
			struct resource *r;
			r = scp->drq[0];
			scp->drq[0] = scp->drq[1];
			scp->drq[1] = r;
			dl = rman_get_start(scp->drq[0]);
			dh = rman_get_start(scp->drq[1]);
		}
		/* soft irq/dma configuration */
		x = -1;
		irq = rman_get_start(scp->irq[0]);
#ifdef PC98
		/* SB16 in PC98 use different IRQ table */
		if	(irq == 3) x = 1;
		else if (irq == 5) x = 8;
		else if (irq == 10) x = 2;
		else if (irq == 12) x = 4;
		if (x == -1) {
			err = "bad irq (3/5/10/12 valid)";
			goto bad;
		}
		else sb_setmixer(scp->io[0], IRQ_NR, x);
		/* SB16 in PC98 use different dma setting */
		sb_setmixer(scp->io[0], DMA_NR, dh == 0 ? 1 : 2);
#else
		if      (irq == 5) x = 2;
		else if (irq == 7) x = 4;
		else if (irq == 9) x = 1;
		else if (irq == 10) x = 8;
		if (x == -1) {
			err = "bad irq (5/7/9/10 valid)";
			goto bad;
		}
		else sb_setmixer(scp->io[0], IRQ_NR, x);
		sb_setmixer(scp->io[0], DMA_NR, (1 << dh) | (1 << dl));
#endif
		if (bootverbose) {
			device_printf(dev, "setting card to irq %d, drq %d", irq, dl);
			if (dl != dh) printf(", %d", dh);
			printf("\n");
    		}
		break;
    	}

	switch (logical_id) {
    	case 0x43008c0e:	/* CTL0043 */
	case 0x01200000:
	case 0x01000000:
		f |= BD_F_SB16X;
		break;
	}
	scp->bd_ver |= f << 16;

	err = "setup_intr";
	for (i = 0; i < IRQ_MAX; i++) {
		scp->ihl[i].parent = scp;
		if (snd_setup_intr(dev, scp->irq[i], 0, sbc_intr, &scp->ihl[i], &scp->ih[i]))
			goto bad;
	}

	/* PCM Audio */
	func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
	if (func == NULL) goto bad;
	func->func = SCF_PCM;
	scp->child_pcm = device_add_child(dev, "pcm", -1);
	device_set_ivars(scp->child_pcm, func);

	/* Midi Interface */
	func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
	if (func == NULL) goto bad;
	func->func = SCF_MIDI;
	scp->child_midi1 = device_add_child(dev, "midi", -1);
	device_set_ivars(scp->child_midi1, func);

	/* OPL FM Synthesizer */
	func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
	if (func == NULL) goto bad;
	func->func = SCF_SYNTH;
	scp->child_midi2 = device_add_child(dev, "midi", -1);
	device_set_ivars(scp->child_midi2, func);

	/* probe/attach kids */
	bus_generic_attach(dev);

	return (0);

bad:	if (err) device_printf(dev, "%s\n", err);
	release_resource(scp);
	return (ENXIO);
}
Ejemplo n.º 10
0
static int
atkbdc_isa_probe(device_t dev)
{
	struct resource	*port0;
	struct resource	*port1;
	u_long		start;
	u_long		count;
	int		error;
	int		rid;
#if defined(__i386__) || defined(__amd64__)
	bus_space_tag_t	tag;
	bus_space_handle_t ioh1;
	volatile int	i;
	register_t	flags;
#endif

	/* check PnP IDs */
	if (ISA_PNP_PROBE(device_get_parent(dev), dev, atkbdc_ids) == ENXIO)
		return ENXIO;

	device_set_desc(dev, "Keyboard controller (i8042)");

	/*
	 * Adjust I/O port resources.
	 * The AT keyboard controller uses two ports (a command/data port
	 * 0x60 and a status port 0x64), which may be given to us in 
	 * one resource (0x60 through 0x64) or as two separate resources
	 * (0x60 and 0x64). Some brain-damaged ACPI BIOS has reversed
	 * command/data port and status port. Furthermore, /boot/device.hints
	 * may contain just one port, 0x60. We shall adjust resource settings
	 * so that these two ports are available as two separate resources
	 * in correct order.
	 */
	device_quiet(dev);
	rid = 0;
	if (bus_get_resource(dev, SYS_RES_IOPORT, rid, &start, &count) != 0)
		return ENXIO;
	if (start == IO_KBD + KBD_STATUS_PORT) {
		start = IO_KBD;
		count++;
	}
	if (count > 1)	/* adjust the count and/or start port */
		bus_set_resource(dev, SYS_RES_IOPORT, rid, start, 1);
	port0 = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
	if (port0 == NULL)
		return ENXIO;
	rid = 1;
	if (bus_get_resource(dev, SYS_RES_IOPORT, rid, NULL, NULL) != 0)
		bus_set_resource(dev, SYS_RES_IOPORT, 1,
				 start + KBD_STATUS_PORT, 1);
	port1 = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
	if (port1 == NULL) {
		bus_release_resource(dev, SYS_RES_IOPORT, 0, port0);
		return ENXIO;
	}

#if defined(__i386__) || defined(__amd64__)
	/*
	 * Check if we really have AT keyboard controller. Poll status
	 * register until we get "all clear" indication. If no such
	 * indication comes, it probably means that there is no AT
	 * keyboard controller present. Give up in such case. Check relies
	 * on the fact that reading from non-existing in/out port returns
	 * 0xff on i386. May or may not be true on other platforms.
	 */
	tag = rman_get_bustag(port0);
	ioh1 = rman_get_bushandle(port1);
	flags = intr_disable();
	for (i = 0; i != 65535; i++) {
		if ((bus_space_read_1(tag, ioh1, 0) & 0x2) == 0)
			break;
	}
	intr_restore(flags);
	if (i == 65535) {
		bus_release_resource(dev, SYS_RES_IOPORT, 0, port0);
		bus_release_resource(dev, SYS_RES_IOPORT, 1, port1);
		if (bootverbose)
			device_printf(dev, "AT keyboard controller not found\n");
		return ENXIO;
	}
#endif

	device_verbose(dev);

	error = atkbdc_probe_unit(device_get_unit(dev), port0, port1);
	if (error == 0)
		bus_generic_probe(dev);

	bus_release_resource(dev, SYS_RES_IOPORT, 0, port0);
	bus_release_resource(dev, SYS_RES_IOPORT, 1, port1);

	return error;
}
Ejemplo n.º 11
0
static int
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];

	/*
	 * rescanning the isa bus, do nothing
	 */
	if (device_get_state(parent) == DS_ATTACHED)
		return (0);

	/*
	 * Otherwise see if it exists
	 */
	child = BUS_ADD_CHILD(parent, 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, -1);
		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, -1);
		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;
	}

	/*
	 * note: sc becomes invalid after we delete the child.
	 */
	if (sc->rnum == 0) {
		device_delete_child(parent, child);
		return (ENXIO);
	}
	if (sc->rnum == 1)
		device_set_desc(child, "ISA Option ROM");
	else
		device_set_desc(child, "ISA Option ROMs");
	return (0);
}
Ejemplo n.º 12
0
static void
ichss_identify(driver_t *driver, device_t parent)
{
	device_t child;
	uint32_t pmbase;

	if (resource_disabled("ichss", 0))
		return;

	/*
	 * It appears that ICH SpeedStep only requires a single CPU to
	 * set the value (since the chipset is shared by all CPUs.)
	 * Thus, we only add a child to cpu 0.
	 */
	if (device_get_unit(parent) != 0)
		return;

	/* Avoid duplicates. */
	if (device_find_child(parent, "ichss", -1))
		return;

	/*
	 * ICH2/3/4-M I/O Controller Hub is at bus 0, slot 1F, function 0.
	 * E.g. see Section 6.1 "PCI Devices and Functions" and table 6.1 of
	 * Intel(r) 82801BA I/O Controller Hub 2 (ICH2) and Intel(r) 82801BAM
	 * I/O Controller Hub 2 Mobile (ICH2-M).
	 */
	ich_device = pci_find_bsf(0, 0x1f, 0);
	if (ich_device == NULL ||
	    pci_get_vendor(ich_device) != PCI_VENDOR_INTEL ||
	    (pci_get_device(ich_device) != PCI_DEV_82801BA &&
	    pci_get_device(ich_device) != PCI_DEV_82801CA &&
	    pci_get_device(ich_device) != PCI_DEV_82801DB))
		return;

	/*
	 * Certain systems with ICH2 and an Intel 82815_MC host bridge
	 * where the host bridge's revision is < 5 lockup if SpeedStep
	 * is used.
	 */
	if (pci_get_device(ich_device) == PCI_DEV_82801BA) {
		device_t hostb;

		hostb = pci_find_bsf(0, 0, 0);
		if (hostb != NULL &&
		    pci_get_vendor(hostb) == PCI_VENDOR_INTEL &&
		    pci_get_device(hostb) == PCI_DEV_82815_MC &&
		    pci_get_revid(hostb) < 5)
			return;
	}

	/* Find the PMBASE register from our PCI config header. */
	pmbase = pci_read_config(ich_device, ICHSS_PMBASE_OFFSET,
	    sizeof(pmbase));
	if ((pmbase & ICHSS_IO_REG) == 0) {
		printf("ichss: invalid PMBASE memory type\n");
		return;
	}
	pmbase &= ICHSS_PMBASE_MASK;
	if (pmbase == 0) {
		printf("ichss: invalid zero PMBASE address\n");
		return;
	}
	DPRINT("ichss: PMBASE is %#x\n", pmbase);

	child = BUS_ADD_CHILD(parent, 20, "ichss", 0);
	if (child == NULL) {
		device_printf(parent, "add SpeedStep child failed\n");
		return;
	}

	/* Add the bus master arbitration and control registers. */
	bus_set_resource(child, SYS_RES_IOPORT, 0, pmbase + ICHSS_BM_OFFSET,
	    1);
	bus_set_resource(child, SYS_RES_IOPORT, 1, pmbase + ICHSS_CTRL_OFFSET,
	    1);
}
Ejemplo n.º 13
0
/*
 * Probe and vendor specific initialization for the HP PC Lan+ Cards.
 * (HP Part nos: 27247B and 27252A).
 *
 * The card has an asic wrapper around a DS8390 core.  The asic handles 
 * host accesses and offers both standard register IO and memory mapped 
 * IO.  Memory mapped I/O allows better performance at the expense of greater
 * chance of an incompatibility with existing ISA cards.
 *
 * The card has a few caveats: it isn't tolerant of byte wide accesses, only
 * short (16 bit) or word (32 bit) accesses are allowed.  Some card revisions
 * don't allow 32 bit accesses; these are indicated by a bit in the software
 * ID register (see if_edreg.h).
 * 
 * Other caveats are: we should read the MAC address only when the card
 * is inactive.
 *
 * For more information; please consult the CRYNWR packet driver.
 *
 * The AUI port is turned on using the "link2" option on the ifconfig 
 * command line.
 */
int
ed_probe_HP_pclanp(device_t dev, int port_rid, int flags)
{
	struct ed_softc *sc = device_get_softc(dev);
	int error;
	int n;				/* temp var */
	int memsize;			/* mem on board */
	u_char checksum;		/* checksum of board address */
	u_char irq;			/* board configured IRQ */
	uint8_t test_pattern[ED_HPP_TEST_SIZE];	/* read/write areas for */
	uint8_t test_buffer[ED_HPP_TEST_SIZE];	/* probing card */
	u_long conf_maddr, conf_msize, conf_irq, junk;

	error = ed_alloc_port(dev, 0, ED_HPP_IO_PORTS);
	if (error)
		return (error);

	/* Fill in basic information */
	sc->asic_offset = ED_HPP_ASIC_OFFSET;
	sc->nic_offset  = ED_HPP_NIC_OFFSET;

	sc->chip_type = ED_CHIP_TYPE_DP8390;
	sc->isa16bit = 0;	/* the 8390 core needs to be in byte mode */

	/* 
	 * Look for the HP PCLAN+ signature: "0x50,0x48,0x00,0x53" 
	 */
	
	if ((ed_asic_inb(sc, ED_HPP_ID) != 0x50) || 
	    (ed_asic_inb(sc, ED_HPP_ID + 1) != 0x48) ||
	    ((ed_asic_inb(sc, ED_HPP_ID + 2) & 0xF0) != 0) ||
	    (ed_asic_inb(sc, ED_HPP_ID + 3) != 0x53))
		return (ENXIO);

	/* 
	 * Read the MAC address and verify checksum on the address.
	 */

	ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_MAC);
	for (n  = 0, checksum = 0; n < ETHER_ADDR_LEN; n++)
		checksum += (sc->enaddr[n] = 
		    ed_asic_inb(sc, ED_HPP_MAC_ADDR + n));
	
	checksum += ed_asic_inb(sc, ED_HPP_MAC_ADDR + ETHER_ADDR_LEN);

	if (checksum != 0xFF)
		return (ENXIO);

	/*
	 * Verify that the software model number is 0.
	 */
	
	ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_ID);
	if (((sc->hpp_id = ed_asic_inw(sc, ED_HPP_PAGE_4)) & 
		ED_HPP_ID_SOFT_MODEL_MASK) != 0x0000)
		return (ENXIO);

	/*
	 * Read in and save the current options configured on card.
	 */

	sc->hpp_options = ed_asic_inw(sc, ED_HPP_OPTION);

	sc->hpp_options |= (ED_HPP_OPTION_NIC_RESET | 
	    ED_HPP_OPTION_CHIP_RESET | ED_HPP_OPTION_ENABLE_IRQ);

	/* 
	 * Reset the chip.  This requires writing to the option register
	 * so take care to preserve the other bits.
	 */

	ed_asic_outw(sc, ED_HPP_OPTION, 
	    (sc->hpp_options & ~(ED_HPP_OPTION_NIC_RESET | 
	    ED_HPP_OPTION_CHIP_RESET)));

	DELAY(5000);	/* wait for chip reset to complete */

	ed_asic_outw(sc, ED_HPP_OPTION,
	    (sc->hpp_options | (ED_HPP_OPTION_NIC_RESET |
	    ED_HPP_OPTION_CHIP_RESET |
	    ED_HPP_OPTION_ENABLE_IRQ)));

	DELAY(5000);

	if (!(ed_nic_inb(sc, ED_P0_ISR) & ED_ISR_RST))
		return (ENXIO);	/* reset did not complete */

	/*
	 * Read out configuration information.
	 */

	ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_HW);

	irq = ed_asic_inb(sc, ED_HPP_HW_IRQ);

	/*
 	 * Check for impossible IRQ.
	 */

	if (irq >= (sizeof(ed_hpp_intr_val) / sizeof(ed_hpp_intr_val[0])))
		return (ENXIO);

	/* 
	 * If the kernel IRQ was specified with a '?' use the cards idea
	 * of the IRQ.  If the kernel IRQ was explicitly specified, it
 	 * should match that of the hardware.
	 */
	error = bus_get_resource(dev, SYS_RES_IRQ, 0, &conf_irq, &junk);
	if (error)
		bus_set_resource(dev, SYS_RES_IRQ, 0, ed_hpp_intr_val[irq], 1);
	else {
		if (conf_irq != ed_hpp_intr_val[irq])
			return (ENXIO);
	}

	/*
	 * Fill in softconfig info.
	 */

	sc->vendor = ED_VENDOR_HP;
	sc->type = ED_TYPE_HP_PCLANPLUS;
	sc->type_str = "HP-PCLAN+";

	sc->mem_shared = 0;	/* we DON'T have dual ported RAM */
	sc->mem_start = 0;	/* we use offsets inside the card RAM */

	sc->hpp_mem_start = NULL;/* no memory mapped I/O by default */

	/*
	 * The board has 32KB of memory.  Is there a way to determine
	 * this programmatically?
	 */
	
	memsize = 32768;

	/*
	 * Check if memory mapping of the I/O registers possible.
	 */
	if (sc->hpp_options & ED_HPP_OPTION_MEM_ENABLE) {
		u_long mem_addr;

		/*
		 * determine the memory address from the board.
		 */
		
		ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_HW);
		mem_addr = (ed_asic_inw(sc, ED_HPP_HW_MEM_MAP) << 8);

		/*
		 * Check that the kernel specified start of memory and
		 * hardware's idea of it match.
		 */
		error = bus_get_resource(dev, SYS_RES_MEMORY, 0,
					 &conf_maddr, &conf_msize);
		if (error)
			return (error);
		
		if (mem_addr != conf_maddr)
			return (ENXIO);

		error = ed_alloc_memory(dev, 0, memsize);
		if (error)
			return (error);

		sc->hpp_mem_start = rman_get_virtual(sc->mem_res);
	}

	/*
	 * Fill in the rest of the soft config structure.
	 */

	/*
	 * The transmit page index.
	 */

	sc->tx_page_start = ED_HPP_TX_PAGE_OFFSET;

	if (device_get_flags(dev) & ED_FLAGS_NO_MULTI_BUFFERING)
		sc->txb_cnt = 1;
	else
		sc->txb_cnt = 2;

	/*
	 * Memory description
	 */

	sc->mem_size = memsize;
	sc->mem_ring = sc->mem_start + 
		(sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE);
	sc->mem_end = sc->mem_start + sc->mem_size;

	/*
	 * Receive area starts after the transmit area and 
	 * continues till the end of memory.
	 */

	sc->rec_page_start = sc->tx_page_start + 
				(sc->txb_cnt * ED_TXBUF_SIZE);
	sc->rec_page_stop = (sc->mem_size / ED_PAGE_SIZE);


	sc->cr_proto = 0;	/* value works */

	/*
	 * Set the wrap registers for string I/O reads.
	 */

	ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_HW);
	ed_asic_outw(sc, ED_HPP_HW_WRAP,
	    ((sc->rec_page_start / ED_PAGE_SIZE) |
	    (((sc->rec_page_stop / ED_PAGE_SIZE) - 1) << 8)));

	/*
	 * Reset the register page to normal operation.
	 */

	ed_asic_outw(sc, ED_HPP_PAGING, ED_HPP_PAGE_PERF);

	/*
	 * Verify that we can read/write from adapter memory.
	 * Create test pattern.
	 */

	for (n = 0; n < ED_HPP_TEST_SIZE; n++)
		test_pattern[n] = (n*n) ^ ~n;

#undef	ED_HPP_TEST_SIZE

	/*
	 * Check that the memory is accessible thru the I/O ports.
	 * Write out the contents of "test_pattern", read back
	 * into "test_buffer" and compare the two for any
	 * mismatch.
	 */

	for (n = 0; n < (32768 / ED_PAGE_SIZE); n ++) {
		ed_hpp_writemem(sc, test_pattern, (n * ED_PAGE_SIZE), 
				sizeof(test_pattern));
		ed_hpp_readmem(sc, (n * ED_PAGE_SIZE), 
			test_buffer, sizeof(test_pattern));

		if (bcmp(test_pattern, test_buffer, 
			sizeof(test_pattern)))
			return (ENXIO);
	}

	sc->sc_mediachg = ed_hpp_set_physical_link;
	sc->sc_write_mbufs = ed_hpp_write_mbufs;
	sc->readmem = ed_hpp_readmem;
	return (0);
}
Ejemplo n.º 14
0
static int
adv_isa_probe(device_t dev)
{
	int	port_index;
	int	max_port_index;
	u_long	iobase, iocount, irq;
	int	user_iobase = 0;
	int	rid = 0;
	void	*ih;
	struct resource	*iores, *irqres;

	/*
	 * We don't know of any PnP ID's for these cards.
	 */
	if (isa_get_logicalid(dev) != 0)
		return (ENXIO);

	/*
	 * Default to scanning all possible device locations.
	 */
	port_index = 0;
	max_port_index = MAX_ISA_IOPORT_INDEX;

	if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, &iocount) == 0) {
		user_iobase = 1;
		for (;port_index <= max_port_index; port_index++)
			if (iobase <= adv_isa_ioports[port_index])
				break;
		if ((port_index > max_port_index)
		 || (iobase != adv_isa_ioports[port_index])) {
			if (bootverbose)
				device_printf(dev,
				    "Invalid baseport of 0x%lx specified. "
				    "Nearest valid baseport is 0x%x.  Failing "
				    "probe.\n", iobase,
				    (port_index <= max_port_index) ?
				    adv_isa_ioports[port_index] :
				    adv_isa_ioports[max_port_index]);
			return ENXIO;
		}
		max_port_index = port_index;
	}

	/* Perform the actual probing */
	adv_set_isapnp_wait_for_key();
	for (;port_index <= max_port_index; port_index++) {
		u_int16_t port_addr = adv_isa_ioports[port_index];
		bus_size_t maxsegsz;
		bus_size_t maxsize;
		bus_addr_t lowaddr;
		int error;
		struct adv_softc *adv;

		if (port_addr == 0)
			/* Already been attached */
			continue;
		
		if (bus_set_resource(dev, SYS_RES_IOPORT, 0, port_addr, 1))
			continue;

		/* XXX what is the real portsize? */
		iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
					       RF_ACTIVE);
		if (iores == NULL)
			continue;

		if (adv_find_signature(iores) == 0) {
			bus_release_resource(dev, SYS_RES_IOPORT, 0, iores);
			continue;
		}

		/*
		 * Got one.  Now allocate our softc
		 * and see if we can initialize the card.
		 */
		adv = adv_alloc(dev, iores, 0);
		if (adv == NULL) {
			bus_release_resource(dev, SYS_RES_IOPORT, 0, iores);
			break;
		}

		/*
		 * Stop the chip.
		 */
		ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT);
		ADV_OUTW(adv, ADV_CHIP_STATUS, 0);
		/*
		 * Determine the chip version.
		 */
		adv->chip_version = ADV_INB(adv, ADV_NONEISA_CHIP_REVISION);
		if ((adv->chip_version >= ADV_CHIP_MIN_VER_VL)
		    && (adv->chip_version <= ADV_CHIP_MAX_VER_VL)) {
			adv->type = ADV_VL;
			maxsegsz = ADV_VL_MAX_DMA_COUNT;
			maxsize = BUS_SPACE_MAXSIZE_32BIT;
			lowaddr = ADV_VL_MAX_DMA_ADDR;
			bus_delete_resource(dev, SYS_RES_DRQ, 0);
		} else if ((adv->chip_version >= ADV_CHIP_MIN_VER_ISA)
			   && (adv->chip_version <= ADV_CHIP_MAX_VER_ISA)) {
			if (adv->chip_version >= ADV_CHIP_MIN_VER_ISA_PNP) {
				adv->type = ADV_ISAPNP;
				ADV_OUTB(adv, ADV_REG_IFC,
					 ADV_IFC_INIT_DEFAULT);
			} else {
				adv->type = ADV_ISA;
			}
			maxsegsz = ADV_ISA_MAX_DMA_COUNT;
			maxsize = BUS_SPACE_MAXSIZE_24BIT;
			lowaddr = ADV_ISA_MAX_DMA_ADDR;
			adv->isa_dma_speed = ADV_DEF_ISA_DMA_SPEED;
			adv->isa_dma_channel = adv_get_isa_dma_channel(adv);
			bus_set_resource(dev, SYS_RES_DRQ, 0,
					 adv->isa_dma_channel, 1);
		} else {
			panic("advisaprobe: Unknown card revision\n");
		}

		/*
		 * Allocate a parent dmatag for all tags created
		 * by the MI portions of the advansys driver
		 */
		error = bus_dma_tag_create(
				/* parent	*/ bus_get_dma_tag(dev),
				/* alignemnt	*/ 1,
				/* boundary	*/ 0,
				/* lowaddr	*/ lowaddr,
				/* highaddr	*/ BUS_SPACE_MAXADDR,
				/* filter	*/ NULL,
				/* filterarg	*/ NULL,
				/* maxsize	*/ maxsize,
				/* nsegments	*/ ~0,
				/* maxsegsz	*/ maxsegsz,
				/* flags	*/ 0,
				/* lockfunc	*/ NULL,
				/* lockarg	*/ NULL,
				&adv->parent_dmat); 

		if (error != 0) {
			device_printf(dev,
			    "Could not allocate DMA tag - error %d\n", error);
			adv_free(adv); 
			bus_release_resource(dev, SYS_RES_IOPORT, 0, iores);
			break;
		}

		adv->init_level += 2;

		if (overrun_buf == NULL) {
			/* Need to allocate our overrun buffer */
			if (bus_dma_tag_create(
				/* parent	*/ adv->parent_dmat,
				/* alignment	*/ 8,
				/* boundary	*/ 0,
				/* lowaddr	*/ ADV_ISA_MAX_DMA_ADDR,
				/* highaddr	*/ BUS_SPACE_MAXADDR,
				/* filter	*/ NULL,
				/* filterarg	*/ NULL,
				/* maxsize	*/ ADV_OVERRUN_BSIZE,
				/* nsegments	*/ 1,
				/* maxsegsz	*/ BUS_SPACE_MAXSIZE_32BIT,
				/* flags	*/ 0,
				/* lockfunc	*/ NULL,
				/* lockarg	*/ NULL,
				&overrun_dmat) != 0) {
				adv_free(adv);
				bus_release_resource(dev, SYS_RES_IOPORT, 0,
						     iores);
				break;
			}
			if (bus_dmamem_alloc(overrun_dmat,
					     (void **)&overrun_buf,
					     BUS_DMA_NOWAIT,
					     &overrun_dmamap) != 0) {
				bus_dma_tag_destroy(overrun_dmat);
				adv_free(adv);
				bus_release_resource(dev, SYS_RES_IOPORT, 0,
						     iores);
				break;
			}
			/* And permanently map it in */  
			bus_dmamap_load(overrun_dmat, overrun_dmamap,
					overrun_buf, ADV_OVERRUN_BSIZE,
					adv_map, &overrun_physbase,
					/*flags*/0);
		}

		adv->overrun_physbase = overrun_physbase;

		if (adv_init(adv) != 0) {
			bus_dmamap_unload(overrun_dmat, overrun_dmamap);
			bus_dmamem_free(overrun_dmat, overrun_buf,
			    overrun_dmamap);
			bus_dma_tag_destroy(overrun_dmat);
			adv_free(adv);
			bus_release_resource(dev, SYS_RES_IOPORT, 0, iores);
			break;
		}

		switch (adv->type) {
		case ADV_ISAPNP:
			if (adv->chip_version == ADV_CHIP_VER_ASYN_BUG) {
				adv->bug_fix_control
				    |= ADV_BUG_FIX_ASYN_USE_SYN;
				adv->fix_asyn_xfer = ~0;
			}
			/* Fall Through */
		case ADV_ISA:
			adv->max_dma_count = ADV_ISA_MAX_DMA_COUNT;
			adv->max_dma_addr = ADV_ISA_MAX_DMA_ADDR;
			adv_set_isa_dma_settings(adv);
			break;

		case ADV_VL:
			adv->max_dma_count = ADV_VL_MAX_DMA_COUNT;
			adv->max_dma_addr = ADV_VL_MAX_DMA_ADDR;
			break;
		default:
			panic("advisaprobe: Invalid card type\n");
		}
			
		/* Determine our IRQ */
		if (bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, NULL))
			bus_set_resource(dev, SYS_RES_IRQ, 0,
					 adv_get_chip_irq(adv), 1);
		else
			adv_set_chip_irq(adv, irq);

		irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
						RF_ACTIVE);
		if (irqres == NULL ||
		    bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|
		    INTR_MPSAFE, NULL, adv_intr, adv, &ih) != 0) {
			if (irqres != NULL)
				bus_release_resource(dev, SYS_RES_IRQ, rid,
				    irqres);
			bus_dmamap_unload(overrun_dmat, overrun_dmamap);
			bus_dmamem_free(overrun_dmat, overrun_buf,
			    overrun_dmamap);
			bus_dma_tag_destroy(overrun_dmat);
			adv_free(adv);
			bus_release_resource(dev, SYS_RES_IOPORT, 0, iores);
			break;
		}

		/* Mark as probed */
		adv_isa_ioports[port_index] = 0;
		return 0;
	}

	if (user_iobase)
		bus_set_resource(dev, SYS_RES_IOPORT, 0, iobase, iocount);
	else
		bus_delete_resource(dev, SYS_RES_IOPORT, 0);

	return ENXIO;
}
Ejemplo n.º 15
0
int
ppc_probe(device_t dev, int rid)
{
#ifdef __i386__
	static short next_bios_ppc = 0;
#ifdef PC98
	unsigned int pc98_ieee_mode = 0x00;
	unsigned int tmp;
#endif
#endif
	struct ppc_data *ppc;
	int error;
	rman_res_t port;

	/*
	 * Allocate the ppc_data structure.
	 */
	ppc = DEVTOSOFTC(dev);
	bzero(ppc, sizeof(struct ppc_data));

	ppc->rid_ioport = rid;

	/* retrieve ISA parameters */
	error = bus_get_resource(dev, SYS_RES_IOPORT, rid, &port, NULL);

#ifdef __i386__
	/*
	 * If port not specified, use bios list.
	 */
	if (error) {
#ifdef PC98
		if (next_bios_ppc == 0) {
			/* Use default IEEE-1284 port of NEC PC-98x1 */
			port = PC98_IEEE_1284_PORT;
			next_bios_ppc += 1;
			if (bootverbose)
				device_printf(dev,
				    "parallel port found at 0x%lx\n", port);
		}
#else
		if ((next_bios_ppc < BIOS_MAX_PPC) &&
		    (*(BIOS_PORTS + next_bios_ppc) != 0)) {
			port = *(BIOS_PORTS + next_bios_ppc++);
			if (bootverbose)
				device_printf(dev,
				    "parallel port found at 0x%lx\n", port);
		} else {
			device_printf(dev, "parallel port not found.\n");
			return (ENXIO);
		}
#endif	/* PC98 */
		bus_set_resource(dev, SYS_RES_IOPORT, rid, port,
				 IO_LPTSIZE_EXTENDED);
	}
#endif

	/* IO port is mandatory */

	/* Try "extended" IO port range...*/
	ppc->res_ioport = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT,
						      &ppc->rid_ioport,
						      IO_LPTSIZE_EXTENDED,
						      RF_ACTIVE);

	if (ppc->res_ioport != 0) {
		if (bootverbose)
			device_printf(dev, "using extended I/O port range\n");
	} else {
		/* Failed? If so, then try the "normal" IO port range... */
		 ppc->res_ioport = bus_alloc_resource_anywhere(dev,
		 	 				       SYS_RES_IOPORT,
							       &ppc->rid_ioport,
							       IO_LPTSIZE_NORMAL,
							       RF_ACTIVE);
		if (ppc->res_ioport != 0) {
			if (bootverbose)
				device_printf(dev, "using normal I/O port range\n");
		} else {
			device_printf(dev, "cannot reserve I/O port range\n");
			goto error;
		}
	}

 	ppc->ppc_base = rman_get_start(ppc->res_ioport);

	ppc->ppc_flags = device_get_flags(dev);

	if (!(ppc->ppc_flags & 0x20)) {
		ppc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
						      &ppc->rid_irq,
						      RF_SHAREABLE);
		ppc->res_drq = bus_alloc_resource_any(dev, SYS_RES_DRQ,
						      &ppc->rid_drq,
						      RF_ACTIVE);
	}

	if (ppc->res_irq)
		ppc->ppc_irq = rman_get_start(ppc->res_irq);
	if (ppc->res_drq)
		ppc->ppc_dmachan = rman_get_start(ppc->res_drq);

	ppc->ppc_dev = dev;
	ppc->ppc_model = GENERIC;

	ppc->ppc_mode = PPB_COMPATIBLE;
	ppc->ppc_epp = (ppc->ppc_flags & 0x10) >> 4;

	ppc->ppc_type = PPC_TYPE_GENERIC;

#if defined(__i386__) && defined(PC98)
	/*
	 * IEEE STD 1284 Function Check and Enable
	 * for default IEEE-1284 port of NEC PC-98x1
	 */
	if (ppc->ppc_base == PC98_IEEE_1284_PORT &&
	    !(ppc->ppc_flags & PC98_IEEE_1284_DISABLE)) {
		tmp = inb(ppc->ppc_base + PPC_1284_ENABLE);
		pc98_ieee_mode = tmp;
		if ((tmp & 0x10) == 0x10) {
			outb(ppc->ppc_base + PPC_1284_ENABLE, tmp & ~0x10);
			tmp = inb(ppc->ppc_base + PPC_1284_ENABLE);
			if ((tmp & 0x10) == 0x10)
				goto error;
		} else {
			outb(ppc->ppc_base + PPC_1284_ENABLE, tmp | 0x10);
			tmp = inb(ppc->ppc_base + PPC_1284_ENABLE);
			if ((tmp & 0x10) != 0x10)
				goto error;
		}
		outb(ppc->ppc_base + PPC_1284_ENABLE, pc98_ieee_mode | 0x10);
	}
#endif

	/*
	 * Try to detect the chipset and its mode.
	 */
	if (ppc_detect(ppc, ppc->ppc_flags & 0xf))
		goto error;

	return (0);

error:
#if defined(__i386__) && defined(PC98)
	if (ppc->ppc_base == PC98_IEEE_1284_PORT &&
	    !(ppc->ppc_flags & PC98_IEEE_1284_DISABLE)) {
		outb(ppc->ppc_base + PPC_1284_ENABLE, pc98_ieee_mode);
	}
#endif
	if (ppc->res_irq != 0) {
		bus_release_resource(dev, SYS_RES_IRQ, ppc->rid_irq,
				     ppc->res_irq);
	}
	if (ppc->res_ioport != 0) {
		bus_release_resource(dev, SYS_RES_IOPORT, ppc->rid_ioport,
				     ppc->res_ioport);
	}
	if (ppc->res_drq != 0) {
		bus_release_resource(dev, SYS_RES_DRQ, ppc->rid_drq,
				     ppc->res_drq);
	}
	return (ENXIO);
}
Ejemplo n.º 16
0
/*
 * Check if the device can be found at the port given
 */
static int
aha_isa_probe(device_t dev)
{
	/*
	 * find unit and check we have that many defined
	 */
	struct	aha_softc *aha = device_get_softc(dev);
	int	error;
	u_long	port_start;
	struct resource *port_res;
	int	port_rid;
	int	drq;
	int	irq;
	config_data_t config_data;

	aha->dev = dev;
	/* Check isapnp ids */
	if (ISA_PNP_PROBE(device_get_parent(dev), dev, aha_ids) == ENXIO)
		return (ENXIO);

	port_rid = 0;
	port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &port_rid,
	    0, ~0, AHA_NREGS, RF_ACTIVE);

	if (port_res == NULL)
		return (ENXIO);

	port_start = rman_get_start(port_res);
	aha_alloc(aha, device_get_unit(dev), rman_get_bustag(port_res),
	    rman_get_bushandle(port_res));

	/* See if there is really a card present */
	if (aha_probe(aha) || aha_fetch_adapter_info(aha)) {
		aha_free(aha);
		bus_release_resource(dev, SYS_RES_IOPORT, port_rid, port_res);
		return (ENXIO);
	}

	/*
	 * Determine our IRQ, and DMA settings and
	 * export them to the configuration system.
	 */
	error = aha_cmd(aha, AOP_INQUIRE_CONFIG, NULL, /*parmlen*/0,
	    (uint8_t*)&config_data, sizeof(config_data), DEFAULT_CMD_TIMEOUT);

	if (error != 0) {
		device_printf(dev, "Could not determine IRQ or DMA "
		    "settings for adapter at %#jx.  Failing probe\n",
		    (uintmax_t)port_start);
		aha_free(aha);
		bus_release_resource(dev, SYS_RES_IOPORT, port_rid,
		    port_res);
		return (ENXIO);
	}

	bus_release_resource(dev, SYS_RES_IOPORT, port_rid, port_res);

	switch (config_data.dma_chan) {
	case DMA_CHAN_5:
		drq = 5;
		break;
	case DMA_CHAN_6:
		drq = 6;
		break;
	case DMA_CHAN_7:
		drq = 7;
		break;
	default:
		device_printf(dev, "Invalid DMA setting for adapter at %#jx.",
		    (uintmax_t)port_start);
		return (ENXIO);
	}
	error = bus_set_resource(dev, SYS_RES_DRQ, 0, drq, 1);
	if (error)
		return error;

	irq = ffs(config_data.irq) + 8;
	error = bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1);
	return (error);
}
Ejemplo n.º 17
0
static int
ram_attach(device_t dev)
{
	struct bios_smap *smapbase, *smap, *smapend;
	struct resource *res;
	vm_paddr_t *p;
	caddr_t kmdp;
	uint32_t smapsize;
	int error, rid;

	/* Retrieve the system memory map from the loader. */
	kmdp = preload_search_by_type("elf kernel");
	if (kmdp == NULL)
		kmdp = preload_search_by_type(ELF_KERN_STR);  
	if (kmdp != NULL)
		smapbase = (struct bios_smap *)preload_search_info(kmdp,
		    MODINFO_METADATA | MODINFOMD_SMAP);
	else
		smapbase = NULL;
	if (smapbase != NULL) {
		smapsize = *((u_int32_t *)smapbase - 1);
		smapend = (struct bios_smap *)((uintptr_t)smapbase + smapsize);

		rid = 0;
		for (smap = smapbase; smap < smapend; smap++) {
			if (smap->type != SMAP_TYPE_MEMORY ||
			    smap->length == 0)
				continue;
#ifdef __i386__
			/*
			 * Resources use long's to track resources, so
			 * we can't include memory regions above 4GB.
			 */
			if (smap->base > ~0ul)
				continue;
#endif
			error = bus_set_resource(dev, SYS_RES_MEMORY, rid,
			    smap->base, smap->length);
			if (error)
				panic(
				    "ram_attach: resource %d failed set with %d",
				    rid, error);
			res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
			    0);
			if (res == NULL)
				panic("ram_attach: resource %d failed to attach",
				    rid);
			rid++;
		}
		return (0);
	}

	/*
	 * If the system map is not available, fall back to using
	 * dump_avail[].  We use the dump_avail[] array rather than
	 * phys_avail[] for the memory map as phys_avail[] contains
	 * holes for kernel memory, page 0, the message buffer, and
	 * the dcons buffer.  We test the end address in the loop
	 * instead of the start since the start address for the first
	 * segment is 0.
	 */
	for (rid = 0, p = dump_avail; p[1] != 0; rid++, p += 2) {
#ifdef PAE
		/*
		 * Resources use long's to track resources, so we can't
		 * include memory regions above 4GB.
		 */
		if (p[0] > ~0ul)
			break;
#endif
		error = bus_set_resource(dev, SYS_RES_MEMORY, rid, p[0],
		    p[1] - p[0]);
		if (error)
			panic("ram_attach: resource %d failed set with %d", rid,
			    error);
		res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 0);
		if (res == NULL)
			panic("ram_attach: resource %d failed to attach", rid);
	}
	return (0);
}
Ejemplo n.º 18
0
static int
chipc_add_children(struct chipc_softc *sc)
{
	device_t	 child;
	const char	*flash_bus;
	int		 error;

	/* SPROM/OTP */
	if (sc->caps.nvram_src == BHND_NVRAM_SRC_SPROM ||
	    sc->caps.nvram_src == BHND_NVRAM_SRC_OTP)
	{
		child = BUS_ADD_CHILD(sc->dev, 0, "bhnd_nvram", -1);
		if (child == NULL) {
			device_printf(sc->dev, "failed to add nvram device\n");
			return (ENXIO);
		}

		/* Both OTP and external SPROM are mapped at CHIPC_SPROM_OTP */
		error = chipc_set_resource(sc, child, SYS_RES_MEMORY, 0,
		    CHIPC_SPROM_OTP, CHIPC_SPROM_OTP_SIZE, 0, 0);
		if (error)
			return (error);
	}

	/*
	 * PMU/PWR_CTRL
	 * 
	 * On AOB ("Always on Bus") devices, the PMU core (if it exists) is
	 * attached directly to the bhnd(4) bus -- not chipc.
	 */
	if (sc->caps.pwr_ctrl || (sc->caps.pmu && !sc->caps.aob)) {
		child = BUS_ADD_CHILD(sc->dev, 0, "bhnd_pmu", -1);
		if (child == NULL) {
			device_printf(sc->dev, "failed to add pmu\n");
			return (ENXIO);
		}
	}

	/* All remaining devices are SoC-only */
	if (bhnd_get_attach_type(sc->dev) != BHND_ATTACH_NATIVE)
		return (0);

	/* UARTs */
	for (u_int i = 0; i < min(sc->caps.num_uarts, CHIPC_UART_MAX); i++) {
		child = BUS_ADD_CHILD(sc->dev, 0, "uart", -1);
		if (child == NULL) {
			device_printf(sc->dev, "failed to add uart%u\n", i);
			return (ENXIO);
		}

		/* Shared IRQ */
		error = bus_set_resource(child, SYS_RES_IRQ, 0, CHIPC_MIPS_IRQ,
		    1);
		if (error) {
			device_printf(sc->dev, "failed to set uart%u irq %u\n",
			    i, CHIPC_MIPS_IRQ);
			return (error);
		}

		/* UART registers are mapped sequentially */
		error = chipc_set_resource(sc, child, SYS_RES_MEMORY, 0,
		    CHIPC_UART(i), CHIPC_UART_SIZE, 0, 0);
		if (error)
			return (error);
	}

	/* Flash */
	flash_bus = chipc_flash_bus_name(sc->caps.flash_type);
	if (flash_bus != NULL) {
		child = BUS_ADD_CHILD(sc->dev, 0, flash_bus, -1);
		if (child == NULL) {
			device_printf(sc->dev, "failed to add %s device\n",
			    flash_bus);
			return (ENXIO);
		}

		/* flash memory mapping */
		error = chipc_set_resource(sc, child, SYS_RES_MEMORY, 0,
		    0, RM_MAX_END, 1, 1);
		if (error)
			return (error);

		/* flashctrl registers */
		error = chipc_set_resource(sc, child, SYS_RES_MEMORY, 1,
		    CHIPC_SFLASH_BASE, CHIPC_SFLASH_SIZE, 0, 0);
		if (error)
			return (error);
	}

	return (0);
}
Ejemplo n.º 19
0
static int
ahc_isa_probe(device_t dev)
{
	struct	  aic7770_identity *entry;
	bus_space_tag_t	    tag;
	bus_space_handle_t  bsh;
	struct	  resource *regs;
	struct	  resource *irq;
	uint32_t  iobase;
	u_int	  intdef;
	u_int	  hcntrl;
	int	  irq_num;
	int	  error;
	int	  zero;

	error = ENXIO;
	zero = 0;
	regs = NULL;
	irq = NULL;

	/* Skip probes for ISA PnP devices */
	if (isa_get_logicalid(dev) != 0)
		return (error);

	regs = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &zero, RF_ACTIVE);
	if (regs == NULL) {
		device_printf(dev, "No resources allocated.\n");
		return (ENOMEM);
	}

	iobase = rman_get_start(regs);
	tag = rman_get_bustag(regs);
	bsh = rman_get_bushandle(regs);

	entry = ahc_isa_find_device(tag, bsh);
	if (entry == NULL)
		goto cleanup;

	/* Pause the card preseving the IRQ type */
	hcntrl = bus_space_read_1(tag, bsh, HCNTRL) & IRQMS;
	bus_space_write_1(tag, bsh, HCNTRL, hcntrl | PAUSE);
	while ((bus_space_read_1(tag, bsh, HCNTRL) & PAUSE) == 0)
		;

	/* Make sure we have a valid interrupt vector */
	intdef = bus_space_read_1(tag, bsh, INTDEF);
	irq_num = intdef & VECTOR;
	switch (irq_num) {
	case 9: 
	case 10:
	case 11:
	case 12:
	case 14:
	case 15:
		break;
	default:
		device_printf(dev, "@0x%x: illegal irq setting %d\n",
			      iobase, irq_num);
		goto cleanup;
	}

	if (bus_set_resource(dev, SYS_RES_IRQ, zero, irq_num, 1) != 0)
		goto cleanup;

	/*
	 * The 284X only supports edge triggered interrupts,
	 * so do not claim RF_SHAREABLE.
	 */
	irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &zero,
				     0 /*!(RF_ACTIVE|RF_SHAREABLE)*/);
	if (irq != NULL) {
		error = 0;
		device_set_desc(dev, entry->name);
	} else 
		device_printf(dev, "@0x%x: irq %d allocation failed\n",
			      iobase, irq_num);

cleanup:
	if (regs != NULL) {
		bus_release_resource(dev, SYS_RES_IOPORT, zero, regs);
		regs = NULL;
	}

	if (irq != NULL) {
		bus_release_resource(dev, SYS_RES_IRQ, zero, irq);
		irq = NULL;
	}

	return (error);
}
Ejemplo n.º 20
0
static int
acpi_sysres_attach(device_t dev)
{
    device_t bus;
    struct resource_list_entry *bus_rle, *dev_rle;
    struct resource_list *bus_rl, *dev_rl;
    int done, type;
    u_long start, end, count;

    /*
     * Loop through all current resources to see if the new one overlaps
     * any existing ones.  If so, grow the old one up and/or down
     * accordingly.  Discard any that are wholly contained in the old.  If
     * the resource is unique, add it to the parent.  It will later go into
     * the rman pool.
     */
    bus = device_get_parent(dev);
    dev_rl = BUS_GET_RESOURCE_LIST(bus, dev);
    bus_rl = BUS_GET_RESOURCE_LIST(device_get_parent(bus), bus);
    STAILQ_FOREACH(dev_rle, dev_rl, link) {
	if (dev_rle->type != SYS_RES_IOPORT && dev_rle->type != SYS_RES_MEMORY)
	    continue;

	start = dev_rle->start;
	end = dev_rle->end;
	count = dev_rle->count;
	type = dev_rle->type;
	done = FALSE;

	STAILQ_FOREACH(bus_rle, bus_rl, link) {
	    if (bus_rle->type != type)
		continue;

	    /* New resource wholly contained in old, discard. */
	    if (start >= bus_rle->start && end <= bus_rle->end)
		break;

	    /* New tail overlaps old head, grow existing resource downward. */
	    if (start < bus_rle->start && end >= bus_rle->start) {
		bus_rle->count += bus_rle->start - start;
		bus_rle->start = start;
		done = TRUE;
	    }

	    /* New head overlaps old tail, grow existing resource upward. */
	    if (start <= bus_rle->end && end > bus_rle->end) {
		bus_rle->count += end - bus_rle->end;
		bus_rle->end = end;
		done = TRUE;
	    }

	    /* If we adjusted the old resource, we're finished. */
	    if (done)
		break;
	}

	/* If we didn't merge with anything, add this resource. */
	if (bus_rle == NULL)
	    bus_set_resource(bus, type, acpi_sysres_rid++, start, count);
    }

    /* After merging/moving resources to the parent, free the list. */
    resource_list_free(dev_rl);

    return (0);
}
Ejemplo n.º 21
0
/*
 * Probe for Contec C-NET(98)P2 series.
 * (Logitec LAN-98TP/LAN-98T25P - parhaps)
 */
static int
fe_probe_ssi(device_t dev)
{
	struct fe_softc *sc = device_get_softc(dev);
	u_long iobase, irq;

	u_char eeprom [SSI_EEPROM_SIZE];
	static struct fe_simple_probe_struct probe_table [] = {
		{ FE_DLCR2, 0x08, 0x00 },
		{ FE_DLCR4, 0x08, 0x00 },
		{ 0 }
	};
	static u_short const irqmap[] = {
		/*                        INT0          INT1    INT2       */
		NO_IRQ, NO_IRQ, NO_IRQ,      3, NO_IRQ,    5,      6, NO_IRQ,
		NO_IRQ,      9,     10, NO_IRQ,     12,   13, NO_IRQ, NO_IRQ,
		/*        INT3   INT41            INT5  INT6               */
	};

	/* See if the specified I/O address is possible for 78Q8377A.  */
	/* [0-D]3D0 are allowed.  */
	if (bus_get_resource(dev, SYS_RES_IOPORT, 0, &iobase, NULL) != 0)
		return ENXIO;
	if ((iobase & 0xFFF) != 0x3D0)
		return ENXIO;
		
	if (fe98_alloc_port(dev, FE_TYPE_SSI))
		return ENXIO;

	/* Fill the softc struct with default values.  */
	fe_softc_defaults(sc);

	/* See if the card is on its address.  */
	if (!fe_simple_probe(sc, probe_table))
		return ENXIO;

	/* We now have to read the config EEPROM.  We should be very
           careful, since doing so destroys a register.  (Remember, we
           are not yet sure we have a C-NET(98)P2 board here.)  Don't
           remember to select BMPRs bofore reading EEPROM, since other
           register bank may be selected before the probe() is called.  */
	fe_read_eeprom_ssi(sc, eeprom);

	/* Make sure the Ethernet (MAC) station address is of Contec's.  */
	if (!fe_valid_Ether_p(eeprom + FE_SSI_EEP_ADDR, 0x00804C))
		return ENXIO;
	bcopy(eeprom + FE_SSI_EEP_ADDR, sc->enaddr, ETHER_ADDR_LEN);

	/* Setup the board type.  */
        sc->typestr = "C-NET(98)P2";

	/* Non-PnP mode, set static resource from eeprom. */
	if (!isa_get_vendorid(dev)) {
		/* Get IRQ configuration from EEPROM.  */
		irq = irqmap[eeprom[FE_SSI_EEP_IRQ]];
		if (irq == NO_IRQ) {
			fe_irq_failure(sc->typestr, sc->sc_unit, irq,
				       "3/5/6/9/10/12/13");
			return ENXIO;
		}
		bus_set_resource(dev, SYS_RES_IRQ, 0, irq, 1);
	}

	/* Get Duplex-mode configuration from EEPROM.  */
	sc->proto_dlcr4 |= (eeprom[FE_SSI_EEP_DUPLEX] & FE_D4_DSC);

	/* Fill softc struct accordingly.  */
	sc->mbitmap = MB_HT;
	sc->defmedia = MB_HT;

	return 0;
}
Ejemplo n.º 22
0
/*---------------------------------------------------------------------------*
 *	isic_probe_s0163 - probe routine for Teles S0/16.3
 *---------------------------------------------------------------------------*/
int
isic_probe_s0163(device_t dev)
{
	size_t unit = device_get_unit(dev);	/* get unit */
	struct l1_softc *sc = 0;	/* pointer to softc */
	void *ih = 0;			/* dummy */
	bus_space_tag_t    t;		/* bus things */
	bus_space_handle_t h;
	u_int8_t b0,b1,b2;		/* signature */

	/* check max unit range */

	if(unit >= ISIC_MAXUNIT)
	{
		kprintf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles 16.3!\n",
				unit, unit);
		return(ENXIO);	
	}

	sc = &l1_sc[unit];			/* get pointer to softc */
	sc->sc_unit = unit;			/* set unit */

	/* see if an io base was supplied */
	
	if(!(sc->sc_resources.io_base[0] =
			bus_alloc_resource(dev, SYS_RES_IOPORT,
	                                   &sc->sc_resources.io_rid[0],
	                                   0ul, ~0ul, 1, RF_ACTIVE)))
	{
		kprintf("isic%d: Could not get iobase for Teles S0/16.3.\n",
				unit);
		return(ENXIO);
	}

	/* set io base */

	sc->sc_port = rman_get_start(sc->sc_resources.io_base[0]);
	/* Release the resource -  re-allocate later with correct size	*/
        bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_resources.io_rid[0],
			sc->sc_resources.io_base[0]);
	
	switch(sc->sc_port)
	{
		case 0xd80:
		case 0xe80:
		case 0xf80:
			break;
			
		case 0x180:
		case 0x280:
		case 0x380:
			kprintf("isic%d: Error, instead of using iobase 0x%x for your Teles S0/16.3,\n",
				unit, sc->sc_port);
			kprintf("isic%d:        please use 0x%x in the kernel configuration file!\n",
				unit, sc->sc_port+0xc00);			
			isic_detach_common(dev);
			return(ENXIO);
			break;
	
		default:
			kprintf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16.3!\n",
				unit, sc->sc_port);
			isic_detach_common(dev);
			return(ENXIO);
			break;
	}
	
	/* set io port resources */

	sc->sc_resources.io_rid[0] = 0;	
	bus_set_resource(dev, SYS_RES_IOPORT, 0, sc->sc_port, 0x20);
	sc->sc_resources.io_base[0] =
		bus_alloc_resource(dev, SYS_RES_IOPORT,
				   &sc->sc_resources.io_rid[0],
				   0ul, ~0ul, 1, RF_ACTIVE);
	if(!sc->sc_resources.io_base[0])
	{
		kprintf("isic%d: Error allocating io at 0x%x for Teles S0/16.3!\n",
			unit, sc->sc_port);
		isic_detach_common(dev);
		return ENXIO;
	}
	sc->sc_resources.io_rid[1] = 1;	
	bus_set_resource(dev, SYS_RES_IOPORT, 1,
		sc->sc_port-ISAC_OFFS, 0x20);
	sc->sc_resources.io_base[1] =
		bus_alloc_resource(dev, SYS_RES_IOPORT,
				   &sc->sc_resources.io_rid[1],
				   0ul, ~0ul, 1, RF_ACTIVE);
	if(!sc->sc_resources.io_base[1])
	{
		kprintf("isic%d: Error allocating io at 0x%x for Teles S0/16.3!\n",
			unit, sc->sc_port-ISAC_OFFS);
		isic_detach_common(dev);
		return ENXIO;
	}
	
	sc->sc_resources.io_rid[2] = 2;
	bus_set_resource(dev, SYS_RES_IOPORT, 2,
		sc->sc_port-HSCXA_OFFS, 0x20);
	sc->sc_resources.io_base[2] =
		bus_alloc_resource(dev, SYS_RES_IOPORT,
				   &sc->sc_resources.io_rid[2],
				   0ul, ~0ul, 1, RF_ACTIVE);
	if(!sc->sc_resources.io_base[2])
	{
		kprintf("isic%d: Error allocating io at 0x%x for Teles S0/16.3!\n",
			unit, sc->sc_port-HSCXA_OFFS);
		isic_detach_common(dev);
		return ENXIO;
	}

	sc->sc_resources.io_rid[3] = 3;
	bus_set_resource(dev, SYS_RES_IOPORT, 3,
		sc->sc_port-HSCXB_OFFS, 0x20);
	sc->sc_resources.io_base[3] =
		bus_alloc_resource(dev, SYS_RES_IOPORT,
				   &sc->sc_resources.io_rid[3],
				   0ul, ~0ul, 1, RF_ACTIVE);
	if(!sc->sc_resources.io_base[3])
	{
		kprintf("isic%d: Error allocating io at 0x%x for Teles S0/16.3!\n",
			unit, sc->sc_port-HSCXB_OFFS);
		isic_detach_common(dev);
		return ENXIO;
	}

	/* setup access routines */

	sc->clearirq = NULL;
	sc->readreg = tels0163_read_reg;
	sc->writereg = tels0163_write_reg;

	sc->readfifo = tels0163_read_fifo;
	sc->writefifo = tels0163_write_fifo;

	/* setup card type */
	
	sc->sc_cardtyp= CARD_TYPEP_16_3;

	/* setup IOM bus type */
	
	sc->sc_bustyp = BUS_TYPE_IOM2;

	sc->sc_ipac = 0;
	sc->sc_bfifolen = HSCX_FIFO_LEN;

	t = rman_get_bustag(sc->sc_resources.io_base[0]);
	h = rman_get_bushandle(sc->sc_resources.io_base[0]);

	b0 = bus_space_read_1(t, h, 0);
	b1 = bus_space_read_1(t, h, 1);
	b2 = bus_space_read_1(t, h, 2);
	
	if ( b0 != 0x51 && b0 != 0x10 ) {
		kprintf("isic%d: Error, signature 1 0x%x != 0x51 or 0x10 for Teles S0/16.3!\n",
			unit, b0);
		isic_detach_common(dev);
		return ENXIO;
	}
	
	if ( b1 != 0x93 ) {
		kprintf("isic%d: Error, signature 2 0x%x != 0x93 for Teles S0/16.3!\n",
			unit, b1);
		isic_detach_common(dev);
		return ENXIO;
	}
	if (( b2 != 0x1c ) && ( b2 != 0x1f )) {
		kprintf("isic%d: Error, signature 3 0x%x != (0x1c || 0x1f) for Teles S0/16.3!\n",
			unit, b2);
		isic_detach_common(dev);
		return ENXIO;	
	}
	
	/* 
	 * Read HSCX A/B VSTR.  Expected value for the S0/16.3 card is
	 * 0x05 or 0x04 (for older 16.3's) in the least significant bits.
	 */
	 
	if( (((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) &&
	     ((HSCX_READ(0, H_VSTR) & 0xf) != 0x4))	||
            (((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) &&
	     ((HSCX_READ(1, H_VSTR) & 0xf) != 0x4)) )  
	{
		kprintf("isic%d: HSCX VSTR test failed for Teles S0/16.3\n",
			unit);
		kprintf("isic%d: HSC0: VSTR: %#x\n",
			unit, HSCX_READ(0, H_VSTR));
		kprintf("isic%d: HSC1: VSTR: %#x\n",
			unit, HSCX_READ(1, H_VSTR));
		isic_detach_common(dev);
		return (ENXIO);
	}                   

	/* get our irq */

	if(!(sc->sc_resources.irq =
		bus_alloc_resource(dev, SYS_RES_IRQ,
		&sc->sc_resources.irq_rid,
		0ul, ~0ul, 1, RF_ACTIVE)))
	{
		kprintf("isic%d: Could not get IRQ for Teles S0/16.3.\n",unit);
		isic_detach_common(dev);
		return ENXIO;
	}

	/* get the irq number */
	sc->sc_irq = rman_get_start(sc->sc_resources.irq);

	switch(sc->sc_irq)
	{
		case 2:
		case 9:
		case 5:
		case 10:
		case 12:
		case 15:
			break;

		default:
			kprintf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/16.3!\n",
				unit, sc->sc_irq);
			isic_detach_common(dev);
			return(ENXIO);
			break;
	}

	/* register interupt routine */
	bus_setup_intr(dev, sc->sc_resources.irq,
		       0, (void(*)(void *))(isicintr),
		       sc, &ih, NULL);

	return (0);
}