示例#1
0
/**
 * Find an NVRAM child device on @p dev, if any.
 * 
 * @retval device_t An NVRAM device.
 * @retval NULL If no NVRAM device is found.
 */
static device_t
find_nvram_child(device_t dev)
{
	device_t chipc, nvram;

	/* Look for a directly-attached NVRAM child */
	nvram = device_find_child(dev, devclass_get_name(bhnd_nvram_devclass),
	    -1);
	if (nvram == NULL)
		return (NULL);

	/* Further checks require a bhnd(4) bus */
	if (device_get_devclass(dev) != bhnd_devclass)
		return (NULL);

	/* Look for a ChipCommon-attached OTP device */
	if ((chipc = bhnd_find_child(dev, BHND_DEVCLASS_CC, -1)) != NULL) {
		/* Recursively search the ChipCommon device */
		if ((nvram = find_nvram_child(chipc)) != NULL)
			return (nvram);
	}

	/* Not found */
	return (NULL);
}
示例#2
0
static int
gusc_setup_intr(device_t dev, device_t child, struct resource *irq, int flags,
#if __FreeBSD_version >= 700031
		driver_filter_t *filter,
#endif
		driver_intr_t *intr, void *arg, void **cookiep)
{
	sc_p scp = (sc_p)device_get_softc(dev);
	devclass_t devclass;

#if __FreeBSD_version >= 700031
	if (filter != NULL) {
		printf("gusc.c: we cannot use a filter here\n");
		return (EINVAL);
	}
#endif
	devclass = device_get_devclass(child);
	if (strcmp(devclass_get_name(devclass), "midi") == 0) {
		scp->midi_intr.intr = intr;
		scp->midi_intr.arg = arg;
		return 0;
	} else if (strcmp(devclass_get_name(devclass), "pcm") == 0) {
		scp->pcm_intr.intr = intr;
		scp->pcm_intr.arg = arg;
		return 0;
	}
	return bus_generic_setup_intr(dev, child, irq, flags,
#if __FreeBSD_version >= 700031
				filter,
#endif
				intr, arg, cookiep);
}
示例#3
0
文件: ata-pci.c 项目: coyizumi/cs111
int
ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq, 
		   int flags, driver_filter_t *filter, driver_intr_t *function, 
		   void *argument, void **cookiep)
{
	struct ata_pci_controller *controller = device_get_softc(dev);

	if (controller->legacy) {
		return BUS_SETUP_INTR(device_get_parent(dev), child, irq,
			      flags, filter, function, argument, cookiep);
	} else {
		struct ata_pci_controller *controller = device_get_softc(dev);
		int unit;

	    	if (filter != NULL) {
			printf("ata-pci.c: we cannot use a filter here\n");
			return (EINVAL);
		}
		if (device_get_devclass(child) == ata_devclass)
			unit = ((struct ata_channel *)device_get_softc(child))->unit;
		else
			unit = ATA_PCI_MAX_CH - 1;
		controller->interrupt[unit].function = function;
		controller->interrupt[unit].argument = argument;
		*cookiep = controller;
		return 0;
	}
}
示例#4
0
文件: ata-pci.c 项目: coyizumi/cs111
struct resource *
ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid,
		       u_long start, u_long end, u_long count, u_int flags)
{
	struct ata_pci_controller *controller = device_get_softc(dev);
	struct resource *res = NULL;

	if (device_get_devclass(child) == ata_devclass) {
		int unit = ((struct ata_channel *)device_get_softc(child))->unit;
		int myrid;

		if (type == SYS_RES_IOPORT) {
			switch (*rid) {
			case ATA_IOADDR_RID:
			    if (controller->legacy) {
				start = (unit ? ATA_SECONDARY : ATA_PRIMARY);
				count = ATA_IOSIZE;
				end = start + count - 1;
			    }
			    myrid = PCIR_BAR(0) + (unit << 3);
			    res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
				SYS_RES_IOPORT, &myrid,
				start, end, count, flags);
			    break;
			case ATA_CTLADDR_RID:
			    if (controller->legacy) {
				start = (unit ? ATA_SECONDARY : ATA_PRIMARY) +
				    ATA_CTLOFFSET;
				count = ATA_CTLIOSIZE;
				end = start + count - 1;
			    }
			    myrid = PCIR_BAR(1) + (unit << 3);
			    res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
				SYS_RES_IOPORT, &myrid,
				start, end, count, flags);
			    break;
			}
		}
		if (type == SYS_RES_IRQ && *rid == ATA_IRQ_RID) {
			if (controller->legacy) {
			    int irq = (unit == 0 ? 14 : 15);
	    
			    res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
				SYS_RES_IRQ, rid, irq, irq, 1, flags);
			} else
			    res = controller->r_irq;
		}
	} else {
		if (type == SYS_RES_IRQ) {
			if (*rid != ATA_IRQ_RID)
				return (NULL);
			res = controller->r_irq;
		} else {
			res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
			     type, rid, start, end, count, flags);
		}
	}
	return (res);
}
示例#5
0
/** 
 * Default bhndb_pci implementation of device_probe().
 * 
 * Verifies that the parent is a PCI/PCIe device.
 */
static int
bhndb_pci_probe(device_t dev)
{
	struct bhndb_pci_probe	*probe;
	struct bhndb_pci_core	*entry;
	bhnd_devclass_t		 hostb_devclass;
	device_t		 parent, parent_bus;
	devclass_t		 pci, bus_devclass;
	int			 error;

	probe = NULL;

	/* Our parent must be a PCI/PCIe device. */
	pci = devclass_find("pci");
	parent = device_get_parent(dev);
	parent_bus = device_get_parent(parent);
	if (parent_bus == NULL)
		return (ENXIO);

	/* The bus device class may inherit from 'pci' */
	for (bus_devclass = device_get_devclass(parent_bus);
	    bus_devclass != NULL;
	    bus_devclass = devclass_get_parent(bus_devclass))
	{
		if (bus_devclass == pci)
			break;
	}

	if (bus_devclass != pci)
		return (ENXIO);

	/* Enable clocks */
	if ((error = bhndb_enable_pci_clocks(dev)))
		return (error);

	/* Identify the chip and enumerate the bridged cores */
	hostb_devclass = bhndb_expected_pci_devclass(dev);
	if ((error = bhndb_pci_probe_alloc(&probe, dev, hostb_devclass)))
		goto cleanup;

	/* Look for a matching core table entry */
	if ((entry = bhndb_pci_find_core(&probe->hostb_core)) == NULL) {
		error = ENXIO;
		goto cleanup;
	}

	device_set_desc(dev, "PCI-BHND bridge");

	/* fall-through */
	error = BUS_PROBE_DEFAULT;

cleanup:
	if (probe != NULL)
		bhndb_pci_probe_free(probe);

	bhndb_disable_pci_clocks(dev);

	return (error);
}
示例#6
0
int
vga_pci_is_boot_display(device_t dev)
{
	int unit;
	device_t pcib;
	uint16_t config;

	/* Check that the given device is a video card */
	if ((pci_get_class(dev) != PCIC_DISPLAY &&
	    (pci_get_class(dev) != PCIC_OLD ||
	     pci_get_subclass(dev) != PCIS_OLD_VGA)))
		return (0);

	unit = device_get_unit(dev);

	if (vga_pci_default_unit >= 0) {
		/*
		 * The boot display device was determined by a previous
		 * call to this function, or the user forced it using
		 * the hw.pci.default_vgapci_unit tunable.
		 */
		return (vga_pci_default_unit == unit);
	}

	/*
	 * The primary video card used as a boot display must have the
	 * "I/O" and "Memory Address Space Decoding" bits set in its
	 * Command register.
	 *
	 * Furthermore, if the card is attached to a bridge, instead of
	 * the root PCI bus, the bridge must have the "VGA Enable" bit
	 * set in its Control register.
	 */

	pcib = device_get_parent(device_get_parent(dev));
	if (device_get_devclass(device_get_parent(pcib)) ==
	    devclass_find("pci")) {
		/*
		 * The parent bridge is a PCI-to-PCI bridge: check the
		 * value of the "VGA Enable" bit.
		 */
		config = pci_read_config(pcib, PCIR_BRIDGECTL_1, 2);
		if ((config & PCIB_BCR_VGA_ENABLE) == 0)
			return (0);
	}

	config = pci_read_config(dev, PCIR_COMMAND, 2);
	if ((config & (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN)) == 0)
		return (0);

	/* This video card is the boot display: record its unit number. */
	vga_pci_default_unit = unit;
	device_set_flags(dev, 1);

	return (1);
}
示例#7
0
文件: ata-pci.c 项目: coyizumi/cs111
int
ata_pci_release_resource(device_t dev, device_t child, int type, int rid,
			 struct resource *r)
{

	if (device_get_devclass(child) == ata_devclass) {
		struct ata_pci_controller *controller = device_get_softc(dev);
		int unit = ((struct ata_channel *)device_get_softc(child))->unit;

	        if (type == SYS_RES_IOPORT) {
	    		switch (rid) {
			case ATA_IOADDR_RID:
		    	    return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev,
				SYS_RES_IOPORT,
				PCIR_BAR(0) + (unit << 3), r);
			case ATA_CTLADDR_RID:
			    return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev,
				SYS_RES_IOPORT,
				PCIR_BAR(1) + (unit << 3), r);
			default:
			    return ENOENT;
			}
		}
		if (type == SYS_RES_IRQ) {
			if (rid != ATA_IRQ_RID)
				return ENOENT;
			if (controller->legacy) {
				return BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
				    SYS_RES_IRQ, rid, r);
			} else  
				return 0;
		}
	} else {
		if (type == SYS_RES_IRQ) {
			if (rid != ATA_IRQ_RID)
				return (ENOENT);
			return (0);
		} else {
			return (BUS_RELEASE_RESOURCE(device_get_parent(dev), child,
			    type, rid, r));
		}
	}
	return (EINVAL);
}
示例#8
0
/** 
 * Default bhndb_pci implementation of device_probe().
 * 
 * Verifies that the parent is a PCI/PCIe device.
 */
static int
bhndb_pci_probe(device_t dev)
{
	device_t	parent;
	devclass_t	parent_bus;
	devclass_t	pci;

	/* Our parent must be a PCI/PCIe device. */
	pci = devclass_find("pci");
	parent = device_get_parent(dev);
	parent_bus = device_get_devclass(device_get_parent(parent));

	if (parent_bus != pci)
		return (ENXIO);

	device_set_desc(dev, "PCI-BHND bridge");

	return (BUS_PROBE_DEFAULT);
}
示例#9
0
static int
gusc_setup_intr(device_t dev, device_t child, struct resource *irq,
		int flags, driver_intr_t *intr, void *arg, void **cookiep)
{
	sc_p scp = (sc_p)device_get_softc(dev);
	devclass_t devclass;

	devclass = device_get_devclass(child);
	if (strcmp(devclass_get_name(devclass), "midi") == 0) {
		scp->midi_intr.intr = intr;
		scp->midi_intr.arg = arg;
		return 0;
	} else if (strcmp(devclass_get_name(devclass), "pcm") == 0) {
		scp->pcm_intr.intr = intr;
		scp->pcm_intr.arg = arg;
		return 0;
	}
	return bus_generic_setup_intr(dev, child, irq, flags, intr,
				      arg, cookiep, NULL, NULL);
}
示例#10
0
文件: ata-pci.c 项目: coyizumi/cs111
int
ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq,
		      void *cookie)
{
	struct ata_pci_controller *controller = device_get_softc(dev);

        if (controller->legacy) {
		return BUS_TEARDOWN_INTR(device_get_parent(dev), child, irq, cookie);
	} else {
		struct ata_pci_controller *controller = device_get_softc(dev);
		int unit;

		if (device_get_devclass(child) == ata_devclass)
			unit = ((struct ata_channel *)device_get_softc(child))->unit;
		else
			unit = ATA_PCI_MAX_CH - 1;
		controller->interrupt[unit].function = NULL;
		controller->interrupt[unit].argument = NULL;
		return 0;
	}
}
示例#11
0
static device_t
find_masterdev(sc_p scp)
{
	int i, units;
	devclass_t devclass;
	device_t dev;

	devclass = device_get_devclass(scp->dev);
	units = devclass_get_maxunit(devclass);
	dev = NULL;
	for (i = 0 ; i < units ; i++) {
		dev = devclass_get_device(devclass, i);
		if (isa_get_vendorid(dev) == isa_get_vendorid(scp->dev)
		    && isa_get_logicalid(dev) == LOGICALID_PCM
		    && isa_get_serial(dev) == isa_get_serial(scp->dev))
			break;
	}
	if (i == units)
		return (NULL);

	return (dev);
}
示例#12
0
static int
bhnd_pmu_chipc_probe(device_t dev)
{
	struct bhnd_pmu_softc	*sc;
	struct chipc_caps	*ccaps;
	struct chipc_softc	*chipc_sc;
	device_t		 chipc;
	char			 desc[34];
	int			 error;
	uint32_t		 pcaps;
	uint8_t			 rev;

	sc = device_get_softc(dev);

	/* Look for chipc parent */
	chipc = device_get_parent(dev);
	if (device_get_devclass(chipc) != devclass_find("bhnd_chipc"))
		return (ENXIO);

	/* Check the chipc PMU capability flag. */
	ccaps = BHND_CHIPC_GET_CAPS(chipc);
	if (!ccaps->pmu)
		return (ENXIO);

	/* Delegate to common driver implementation */
	if ((error = bhnd_pmu_probe(dev)) > 0)
		return (error);

	/* Fetch PMU capability flags */
	chipc_sc = device_get_softc(chipc);
	pcaps = bhnd_bus_read_4(chipc_sc->core, BHND_PMU_CAP);

	/* Set description */
	rev = BHND_PMU_GET_BITS(pcaps, BHND_PMU_CAP_REV);
	snprintf(desc, sizeof(desc), "Broadcom ChipCommon PMU, rev %hhu", rev);
	device_set_desc_copy(dev, desc);

	return (BUS_PROBE_NOWILDCARD);
}
示例#13
0
/**
 * Using the generic PCI bridge hardware configuration, allocate, initialize
 * and return a new bhndb_pci probe state instance.
 * 
 * On success, the caller assumes ownership of the returned probe instance, and
 * is responsible for releasing this reference using bhndb_pci_probe_free().
 * 
 * @param[out]	probe		On success, the newly allocated probe instance.
 * @param	dev		The bhndb_pci bridge device.
 * @param	hostb_devclass	The expected device class of the bridge core.
 *
 * @retval 0		success
 * @retval non-zero	if allocating the probe state fails, a regular
 * 			unix error code will be returned.
 * 
 * @note This function requires exclusive ownership over allocating and 
 * configuring host bridge resources, and should only be called prior to
 * completion of device attach and full configuration of the bridge.
 */
static int
bhndb_pci_probe_alloc(struct bhndb_pci_probe **probe, device_t dev,
    bhnd_devclass_t hostb_devclass)
{
	struct bhndb_pci_probe		*p;
	struct bhnd_erom_io		*eio;
	const struct bhndb_hwcfg	*hwcfg;
	const struct bhnd_chipid	*hint;
	device_t			 parent_dev;
	int				 error;

	parent_dev = device_get_parent(dev);
	eio = NULL;

	p = malloc(sizeof(*p), M_BHND, M_ZERO|M_WAITOK);
	p->dev = dev;
	p->pci_dev = parent_dev;

	/* Our register window mapping state must be initialized at this point,
	 * as bhndb_pci_eio will begin making calls into
	 * bhndb_pci_probe_(read|write|get_mapping) */
	p->m_win = NULL;
	p->m_res = NULL;
	p->m_valid = false;

	bhndb_pci_eio_init(&p->erom_io, p);
	eio = &p->erom_io.eio;

	/* Fetch our chipid hint (if any) and generic hardware configuration */
	hwcfg = BHNDB_BUS_GET_GENERIC_HWCFG(parent_dev, dev);
	hint = BHNDB_BUS_GET_CHIPID(parent_dev, dev);

	/* Allocate our host resources */
	error = bhndb_alloc_host_resources(&p->hr, dev, parent_dev, hwcfg);
	if (error) {
		p->hr = NULL;
		goto failed;
	}

	/* Map the first bus core from our bridged bhnd(4) bus */
	error = bhnd_erom_io_map(eio, BHND_DEFAULT_CHIPC_ADDR,
	    BHND_DEFAULT_CORE_SIZE);
	if (error)
		goto failed;

	/* Probe for a usable EROM class, and read the chip identifier */
	p->erom_class = bhnd_erom_probe_driver_classes(
	    device_get_devclass(dev), eio, hint, &p->cid);
	if (p->erom_class == NULL) {
		device_printf(dev, "device enumeration unsupported; no "
		    "compatible driver found\n");

		error = ENXIO;
		goto failed;
	}

	/* Allocate EROM parser */
	p->erom = bhnd_erom_alloc(p->erom_class, &p->cid, eio);
	if (p->erom == NULL) {
		device_printf(dev, "failed to allocate device enumeration "
		    "table parser\n");
		error = ENXIO;
		goto failed;
	}

	/* The EROM I/O instance is now owned by our EROM parser */
	eio = NULL;

	/* Read the full core table */
	error = bhnd_erom_get_core_table(p->erom, &p->cores, &p->ncores);
	if (error) {
		device_printf(p->dev, "error fetching core table: %d\n",
		    error);

		p->cores = NULL;
		goto failed;
	}

	/* Identify the host bridge core */
	error = bhndb_find_hostb_core(p->cores, p->ncores, hostb_devclass,
	    &p->hostb_core);
	if (error) {
		device_printf(dev, "failed to identify the host bridge "
		    "core: %d\n", error);

		goto failed;
	}

	*probe = p;
	return (0);

failed:
	if (eio != NULL) {
		KASSERT(p->erom == NULL, ("I/O instance will be freed by "
		    "its owning parser"));

		bhnd_erom_io_fini(eio);
	}

	if (p->erom != NULL) {
		if (p->cores != NULL)
			bhnd_erom_free_core_table(p->erom, p->cores);

		bhnd_erom_free(p->erom);
	} else {
		KASSERT(p->cores == NULL, ("cannot free erom-owned core table "
		    "without erom reference"));
	}

	if (p->hr != NULL)
		bhndb_release_host_resources(p->hr);

	free(p, M_BHND);

	return (error);
}
示例#14
0
static int
ehci_pci_attach(device_t self)
{
	ehci_softc_t *sc = device_get_softc(self);
	devclass_t dc;
	device_t parent;
	device_t *neighbors;
	device_t *nbus;
	struct usbd_bus *bsc;
	int err;
	int rid;
	int ncomp;
	int count, buscount;
	int slot, function;
	int res;
	int i;

	switch(pci_read_config(self, PCI_USBREV, 1) & PCI_USBREV_MASK) {
	case PCI_USBREV_PRE_1_0:
	case PCI_USBREV_1_0:
	case PCI_USBREV_1_1:
		device_printf(self, "pre-2.0 USB rev\n");
		if (pci_get_devid(self) == PCI_EHCI_DEVICEID_CS5536) {
			sc->sc_bus.usbrev = USBREV_2_0;
			device_printf(self, "Quirk for CS5536 USB 2.0 enabled\n");
			break;
		}
		sc->sc_bus.usbrev = USBREV_UNKNOWN;
		return ENXIO;
	case PCI_USBREV_2_0:
		sc->sc_bus.usbrev = USBREV_2_0;
		break;
	default:
		sc->sc_bus.usbrev = USBREV_UNKNOWN;
		break;
	}

	pci_enable_busmaster(self);

	rid = PCI_CBMEM;
	sc->io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE);
	if (!sc->io_res) {
		device_printf(self, "Could not map memory\n");
		return ENXIO;
	}
	sc->iot = rman_get_bustag(sc->io_res);
	sc->ioh = rman_get_bushandle(sc->io_res);

	rid = 0;
	sc->irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
	    RF_SHAREABLE | RF_ACTIVE);
	if (sc->irq_res == NULL) {
		device_printf(self, "Could not allocate irq\n");
		ehci_pci_detach(self);
		return ENXIO;
	}
	sc->sc_bus.bdev = device_add_child(self, "usb", -1);
	if (!sc->sc_bus.bdev) {
		device_printf(self, "Could not add USB device\n");
		ehci_pci_detach(self);
		return ENOMEM;
	}
	device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);

	/* ehci_pci_match will never return NULL if ehci_pci_probe succeeded */
	device_set_desc(sc->sc_bus.bdev, ehci_pci_match(self));
	switch (pci_get_vendor(self)) {
	case PCI_EHCI_VENDORID_ACERLABS:
		sprintf(sc->sc_vendor, "AcerLabs");
		break;
	case PCI_EHCI_VENDORID_AMD:
		sprintf(sc->sc_vendor, "AMD");
		break;
	case PCI_EHCI_VENDORID_APPLE:
		sprintf(sc->sc_vendor, "Apple");
		break;
	case PCI_EHCI_VENDORID_ATI:
		sprintf(sc->sc_vendor, "ATI");
		break;
	case PCI_EHCI_VENDORID_CMDTECH:
		sprintf(sc->sc_vendor, "CMDTECH");
		break;
	case PCI_EHCI_VENDORID_INTEL:
		sprintf(sc->sc_vendor, "Intel");
		break;
	case PCI_EHCI_VENDORID_NEC:
		sprintf(sc->sc_vendor, "NEC");
		break;
	case PCI_EHCI_VENDORID_OPTI:
		sprintf(sc->sc_vendor, "OPTi");
		break;
	case PCI_EHCI_VENDORID_SIS:
		sprintf(sc->sc_vendor, "SiS");
		break;
	case PCI_EHCI_VENDORID_NVIDIA:
	case PCI_EHCI_VENDORID_NVIDIA2:
		sprintf(sc->sc_vendor, "nVidia");
		break;
	case PCI_EHCI_VENDORID_VIA:
		sprintf(sc->sc_vendor, "VIA");
		break;
	default:
		if (bootverbose)
			device_printf(self, "(New EHCI DeviceId=0x%08x)\n",
			    pci_get_devid(self));
		sprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self));
	}

	err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_BIO,
	    NULL, (driver_intr_t *)ehci_intr, sc, &sc->ih);
	if (err) {
		device_printf(self, "Could not setup irq, %d\n", err);
		sc->ih = NULL;
		ehci_pci_detach(self);
		return ENXIO;
	}

	/* Enable workaround for dropped interrupts as required */
	switch (pci_get_vendor(self)) {
	case PCI_EHCI_VENDORID_ATI:
	case PCI_EHCI_VENDORID_VIA:
		sc->sc_flags |= EHCI_SCFLG_LOSTINTRBUG;
		if (bootverbose)
			device_printf(self,
			    "Dropped interrupts workaround enabled\n");
		break;
	default:
		break;
	}

	/*
	 * Find companion controllers.  According to the spec they always
	 * have lower function numbers so they should be enumerated already.
	 */
	parent = device_get_parent(self);
	res = device_get_children(parent, &neighbors, &count);
	if (res != 0) {
		device_printf(self, "Error finding companion busses\n");
		ehci_pci_detach(self);
		return ENXIO;
	}
	ncomp = 0;
	dc = devclass_find("usb");
	slot = pci_get_slot(self);
	function = pci_get_function(self);
	for (i = 0; i < count; i++) {
		if (pci_get_slot(neighbors[i]) == slot && \
			pci_get_function(neighbors[i]) < function) {
			res = device_get_children(neighbors[i],
				&nbus, &buscount);
			if (res != 0)
				continue;
			if (buscount != 1) {
				free(nbus, M_TEMP);
				continue;
			}
			if (device_get_devclass(nbus[0]) != dc) {
				free(nbus, M_TEMP);
				continue;
			}
			bsc = device_get_softc(nbus[0]);
			free(nbus, M_TEMP);
			DPRINTF(("ehci_pci_attach: companion %s\n",
			    device_get_nameunit(bsc->bdev)));
			sc->sc_comps[ncomp++] = bsc;
			if (ncomp >= EHCI_COMPANION_MAX)
				break;
		}
	}
	sc->sc_ncomp = ncomp;

	/* Allocate a parent dma tag for DMA maps */
	err = bus_dma_tag_create(bus_get_dma_tag(self), 1, 0,
	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
	    BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0,
	    NULL, NULL, &sc->sc_bus.parent_dmatag);
	if (err) {
		device_printf(self, "Could not allocate parent DMA tag (%d)\n",
		    err);
		ehci_pci_detach(self);
		return ENXIO;
	}

	/* Allocate a dma tag for transfer buffers */
	err = bus_dma_tag_create(sc->sc_bus.parent_dmatag, 1, 0,
	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
	    BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0,
	    busdma_lock_mutex, &Giant, &sc->sc_bus.buffer_dmatag);
	if (err) {
		device_printf(self, "Could not allocate buffer DMA tag (%d)\n",
		    err);
		ehci_pci_detach(self);
		return ENXIO;
	}

	ehci_pci_takecontroller(self);
	err = ehci_init(sc);
	if (!err) {
		sc->sc_flags |= EHCI_SCFLG_DONEINIT;
		err = device_probe_and_attach(sc->sc_bus.bdev);
	}

	if (err) {
		device_printf(self, "USB init failed err=%d\n", err);
		ehci_pci_detach(self);
		return EIO;
	}
	return 0;
}
示例#15
0
static int
ad_attach(device_t dev)
{
    struct ata_channel *ch = device_get_softc(device_get_parent(dev));
    struct ata_device *atadev = device_get_softc(dev);
    struct ad_softc *adp;
    device_t parent;

    /* check that we have a virgin disk to attach */
    if (device_get_ivars(dev))
	return EEXIST;

    if (!(adp = malloc(sizeof(struct ad_softc), M_AD, M_NOWAIT | M_ZERO))) {
	device_printf(dev, "out of memory\n");
	return ENOMEM;
    }
    device_set_ivars(dev, adp);

    /* get device geometry into internal structs */
    if (ad_get_geometry(dev))
	return ENXIO;

    /* set the max size if configured */
    if (ata_setmax)
	ad_set_geometry(dev);

    /* init device parameters */
    ad_init(dev);

    /* announce we are here */
    ad_describe(dev);

    /* create the disk device */
    adp->disk = disk_alloc();
    adp->disk->d_strategy = ad_strategy;
    adp->disk->d_ioctl = ad_ioctl;
    adp->disk->d_dump = ad_dump;
    adp->disk->d_name = "ad";
    adp->disk->d_drv1 = dev;
    adp->disk->d_maxsize = ch->dma.max_iosize ? ch->dma.max_iosize : DFLTPHYS;
    if (atadev->param.support.command2 & ATA_SUPPORT_ADDRESS48)
	adp->disk->d_maxsize = min(adp->disk->d_maxsize, 65536 * DEV_BSIZE);
    else					/* 28bit ATA command limit */
	adp->disk->d_maxsize = min(adp->disk->d_maxsize, 256 * DEV_BSIZE);
    adp->disk->d_sectorsize = DEV_BSIZE;
    adp->disk->d_mediasize = DEV_BSIZE * (off_t)adp->total_secs;
    adp->disk->d_fwsectors = adp->sectors;
    adp->disk->d_fwheads = adp->heads;
    adp->disk->d_unit = device_get_unit(dev);
    if (atadev->param.support.command2 & ATA_SUPPORT_FLUSHCACHE)
	adp->disk->d_flags |= DISKFLAG_CANFLUSHCACHE;
    if ((atadev->param.support.command2 & ATA_SUPPORT_CFA) ||
	atadev->param.config == ATA_PROTO_CFA)
	adp->disk->d_flags |= DISKFLAG_CANDELETE;
    strlcpy(adp->disk->d_ident, atadev->param.serial,
	sizeof(adp->disk->d_ident));
    strlcpy(adp->disk->d_descr, atadev->param.model,
	sizeof(adp->disk->d_descr));
    parent = device_get_parent(ch->dev);
    if (parent != NULL && device_get_parent(parent) != NULL &&
	    (device_get_devclass(parent) ==
	     devclass_find("atapci") ||
	     device_get_devclass(device_get_parent(parent)) ==
	     devclass_find("pci"))) {
	adp->disk->d_hba_vendor = pci_get_vendor(parent);
	adp->disk->d_hba_device = pci_get_device(parent);
	adp->disk->d_hba_subvendor = pci_get_subvendor(parent);
	adp->disk->d_hba_subdevice = pci_get_subdevice(parent);
    }
    ata_disk_firmware_geom_adjust(adp->disk);
    disk_create(adp->disk, DISK_VERSION);
    device_add_child(dev, "subdisk", device_get_unit(dev));
    bus_generic_attach(dev);

    callout_init(&atadev->spindown_timer, 1);
    return 0;
}
示例#16
0
/**
 * Default bhnd_pmu driver implementation of DEVICE_ATTACH().
 * 
 * @param dev PMU device.
 * @param res The PMU device registers. The driver will maintain a borrowed
 * reference to this resource for the lifetime of the device.
 */
int
bhnd_pmu_attach(device_t dev, struct bhnd_resource *res)
{
	struct bhnd_pmu_softc	*sc;
	struct sysctl_ctx_list	*ctx;
	struct sysctl_oid	*tree;
	devclass_t		 bhnd_class;
	device_t		 core, bus;
	int			 error;

	sc = device_get_softc(dev);
	sc->dev = dev;
	sc->quirks = 0;
	sc->res = res;

	/* Fetch capability flags */
	sc->caps = bhnd_bus_read_4(sc->res, BHND_PMU_CAP);

	/* Find the bus-attached core */
	bhnd_class = devclass_find("bhnd");
	core = sc->dev;
	while ((bus = device_get_parent(core)) != NULL) {
		if (device_get_devclass(bus) == bhnd_class)
			break;

		core = bus;
	}

	if (core == NULL) {
		device_printf(sc->dev, "bhnd bus not found\n");
		return (ENXIO);
	}

	/* Fetch chip and board info */
	sc->cid = *bhnd_get_chipid(core);

	if ((error = bhnd_read_board_info(core, &sc->board))) {
		device_printf(sc->dev, "error fetching board info: %d\n",
		    error);
		return (ENXIO);
	}

	/* Locate ChipCommon device */
	sc->chipc_dev = bhnd_find_child(bus, BHND_DEVCLASS_CC, 0);
	if (sc->chipc_dev == NULL) {
		device_printf(sc->dev, "chipcommon device not found\n");
		return (ENXIO);
	}

	/* Initialize query state */
	error = bhnd_pmu_query_init(&sc->query, dev, sc->cid, &bhnd_pmu_res_io,
	    sc);
	if (error)
		return (error);
	sc->io = sc->query.io; 
	sc->io_ctx = sc->query.io_ctx;

	BPMU_LOCK_INIT(sc);

	/* Set quirk flags */
	switch (sc->cid.chip_id) {
	case BHND_CHIPID_BCM4328:
	case BHND_CHIPID_BCM5354:
		/* HTAVAIL/ALPAVAIL are bitswapped in CLKCTL */
		sc->quirks |= BPMU_QUIRK_CLKCTL_CCS0;
		break;
	default:
		break;
	}

	/* Initialize PMU */
	if ((error = bhnd_pmu_init(sc))) {
		device_printf(sc->dev, "PMU init failed: %d\n", error);
		goto failed;
	}

	/* Set up sysctl nodes */
	ctx = device_get_sysctl_ctx(dev);
	tree = device_get_sysctl_tree(dev);

	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
	    "bus_freq", CTLTYPE_UINT | CTLFLAG_RD, sc, 0,
	    bhnd_pmu_sysctl_bus_freq, "IU", "Bus clock frequency");

	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
	    "cpu_freq", CTLTYPE_UINT | CTLFLAG_RD, sc, 0,
	    bhnd_pmu_sysctl_cpu_freq, "IU", "CPU clock frequency");
	
	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
	    "mem_freq", CTLTYPE_UINT | CTLFLAG_RD, sc, 0,
	    bhnd_pmu_sysctl_mem_freq, "IU", "Memory clock frequency");

	return (0);

failed:
	BPMU_LOCK_DESTROY(sc);
	bhnd_pmu_query_fini(&sc->query);
	return (error);
}
示例#17
0
static void
ataaction(struct cam_sim *sim, union ccb *ccb)
{
	device_t dev, parent;
	struct ata_channel *ch;

	CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ataaction func_code=%x\n",
	    ccb->ccb_h.func_code));

	ch = (struct ata_channel *)cam_sim_softc(sim);
	dev = ch->dev;
	switch (ccb->ccb_h.func_code) {
	/* Common cases first */
	case XPT_ATA_IO:	/* Execute the requested I/O operation */
	case XPT_SCSI_IO:
		if (ata_check_ids(dev, ccb))
			return;
		if ((ch->devices & ((ATA_ATA_MASTER | ATA_ATAPI_MASTER)
		    << ccb->ccb_h.target_id)) == 0) {
			ccb->ccb_h.status = CAM_SEL_TIMEOUT;
			break;
		}
		if (ch->running)
			device_printf(dev, "already running!\n");
		if (ccb->ccb_h.func_code == XPT_ATA_IO &&
		    (ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) &&
		    (ccb->ataio.cmd.control & ATA_A_RESET)) {
			struct ata_res *res = &ccb->ataio.res;
			
			bzero(res, sizeof(*res));
			if (ch->devices & (ATA_ATA_MASTER << ccb->ccb_h.target_id)) {
				res->lba_high = 0;
				res->lba_mid = 0;
			} else {
				res->lba_high = 0xeb;
				res->lba_mid = 0x14;
			}
			ccb->ccb_h.status = CAM_REQ_CMP;
			break;
		}
		ata_cam_begin_transaction(dev, ccb);
		return;
	case XPT_EN_LUN:		/* Enable LUN as a target */
	case XPT_TARGET_IO:		/* Execute target I/O request */
	case XPT_ACCEPT_TARGET_IO:	/* Accept Host Target Mode CDB */
	case XPT_CONT_TARGET_IO:	/* Continue Host Target I/O Connection*/
	case XPT_ABORT:			/* Abort the specified CCB */
		/* XXX Implement */
		ccb->ccb_h.status = CAM_REQ_INVALID;
		break;
	case XPT_SET_TRAN_SETTINGS:
	{
		struct	ccb_trans_settings *cts = &ccb->cts;
		struct	ata_cam_device *d; 

		if (ata_check_ids(dev, ccb))
			return;
		if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
			d = &ch->curr[ccb->ccb_h.target_id];
		else
			d = &ch->user[ccb->ccb_h.target_id];
		if (ch->flags & ATA_SATA) {
			if (cts->xport_specific.sata.valid & CTS_SATA_VALID_REVISION)
				d->revision = cts->xport_specific.sata.revision;
			if (cts->xport_specific.sata.valid & CTS_SATA_VALID_MODE) {
				if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
					d->mode = ATA_SETMODE(ch->dev,
					    ccb->ccb_h.target_id,
					    cts->xport_specific.sata.mode);
				} else
					d->mode = cts->xport_specific.sata.mode;
			}
			if (cts->xport_specific.sata.valid & CTS_SATA_VALID_BYTECOUNT)
				d->bytecount = min(8192, cts->xport_specific.sata.bytecount);
			if (cts->xport_specific.sata.valid & CTS_SATA_VALID_ATAPI)
				d->atapi = cts->xport_specific.sata.atapi;
			if (cts->xport_specific.sata.valid & CTS_SATA_VALID_CAPS)
				d->caps = cts->xport_specific.sata.caps;
		} else {
			if (cts->xport_specific.ata.valid & CTS_ATA_VALID_MODE) {
				if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
					d->mode = ATA_SETMODE(ch->dev,
					    ccb->ccb_h.target_id,
					    cts->xport_specific.ata.mode);
				} else
					d->mode = cts->xport_specific.ata.mode;
			}
			if (cts->xport_specific.ata.valid & CTS_ATA_VALID_BYTECOUNT)
				d->bytecount = cts->xport_specific.ata.bytecount;
			if (cts->xport_specific.ata.valid & CTS_ATA_VALID_ATAPI)
				d->atapi = cts->xport_specific.ata.atapi;
			if (cts->xport_specific.ata.valid & CTS_ATA_VALID_CAPS)
				d->caps = cts->xport_specific.ata.caps;
		}
		ccb->ccb_h.status = CAM_REQ_CMP;
		break;
	}
	case XPT_GET_TRAN_SETTINGS:
	{
		struct	ccb_trans_settings *cts = &ccb->cts;
		struct  ata_cam_device *d;

		if (ata_check_ids(dev, ccb))
			return;
		if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
			d = &ch->curr[ccb->ccb_h.target_id];
		else
			d = &ch->user[ccb->ccb_h.target_id];
		cts->protocol = PROTO_UNSPECIFIED;
		cts->protocol_version = PROTO_VERSION_UNSPECIFIED;
		if (ch->flags & ATA_SATA) {
			cts->transport = XPORT_SATA;
			cts->transport_version = XPORT_VERSION_UNSPECIFIED;
			cts->xport_specific.sata.valid = 0;
			cts->xport_specific.sata.mode = d->mode;
			cts->xport_specific.sata.valid |= CTS_SATA_VALID_MODE;
			cts->xport_specific.sata.bytecount = d->bytecount;
			cts->xport_specific.sata.valid |= CTS_SATA_VALID_BYTECOUNT;
			if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
				cts->xport_specific.sata.revision =
				    ATA_GETREV(dev, ccb->ccb_h.target_id);
				if (cts->xport_specific.sata.revision != 0xff) {
					cts->xport_specific.sata.valid |=
					    CTS_SATA_VALID_REVISION;
				}
				cts->xport_specific.sata.caps =
				    d->caps & CTS_SATA_CAPS_D;
				if (ch->pm_level) {
					cts->xport_specific.sata.caps |=
					    CTS_SATA_CAPS_H_PMREQ;
				}
				cts->xport_specific.sata.caps &=
				    ch->user[ccb->ccb_h.target_id].caps;
			} else {
				cts->xport_specific.sata.revision = d->revision;
				cts->xport_specific.sata.valid |= CTS_SATA_VALID_REVISION;
				cts->xport_specific.sata.caps = d->caps;
			}
			cts->xport_specific.sata.valid |= CTS_SATA_VALID_CAPS;
			cts->xport_specific.sata.atapi = d->atapi;
			cts->xport_specific.sata.valid |= CTS_SATA_VALID_ATAPI;
		} else {
			cts->transport = XPORT_ATA;
			cts->transport_version = XPORT_VERSION_UNSPECIFIED;
			cts->xport_specific.ata.valid = 0;
			cts->xport_specific.ata.mode = d->mode;
			cts->xport_specific.ata.valid |= CTS_ATA_VALID_MODE;
			cts->xport_specific.ata.bytecount = d->bytecount;
			cts->xport_specific.ata.valid |= CTS_ATA_VALID_BYTECOUNT;
			if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
				cts->xport_specific.ata.caps =
				    d->caps & CTS_ATA_CAPS_D;
				if (!(ch->flags & ATA_NO_48BIT_DMA))
					cts->xport_specific.ata.caps |=
					    CTS_ATA_CAPS_H_DMA48;
				cts->xport_specific.ata.caps &=
				    ch->user[ccb->ccb_h.target_id].caps;
			} else
				cts->xport_specific.ata.caps = d->caps;
			cts->xport_specific.ata.valid |= CTS_ATA_VALID_CAPS;
			cts->xport_specific.ata.atapi = d->atapi;
			cts->xport_specific.ata.valid |= CTS_ATA_VALID_ATAPI;
		}
		ccb->ccb_h.status = CAM_REQ_CMP;
		break;
	}
	case XPT_RESET_BUS:		/* Reset the specified SCSI bus */
	case XPT_RESET_DEV:	/* Bus Device Reset the specified SCSI device */
		ata_reinit(dev);
		ccb->ccb_h.status = CAM_REQ_CMP;
		break;
	case XPT_TERM_IO:		/* Terminate the I/O process */
		/* XXX Implement */
		ccb->ccb_h.status = CAM_REQ_INVALID;
		break;
	case XPT_PATH_INQ:		/* Path routing inquiry */
	{
		struct ccb_pathinq *cpi = &ccb->cpi;

		parent = device_get_parent(dev);
		cpi->version_num = 1; /* XXX??? */
		cpi->hba_inquiry = PI_SDTR_ABLE;
		cpi->target_sprt = 0;
		cpi->hba_misc = PIM_SEQSCAN;
		cpi->hba_eng_cnt = 0;
		if (ch->flags & ATA_NO_SLAVE)
			cpi->max_target = 0;
		else
			cpi->max_target = 1;
		cpi->max_lun = 0;
		cpi->initiator_id = 0;
		cpi->bus_id = cam_sim_bus(sim);
		if (ch->flags & ATA_SATA)
			cpi->base_transfer_speed = 150000;
		else
			cpi->base_transfer_speed = 3300;
		strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
		strncpy(cpi->hba_vid, "ATA", HBA_IDLEN);
		strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
		cpi->unit_number = cam_sim_unit(sim);
		if (ch->flags & ATA_SATA)
			cpi->transport = XPORT_SATA;
		else
			cpi->transport = XPORT_ATA;
		cpi->transport_version = XPORT_VERSION_UNSPECIFIED;
		cpi->protocol = PROTO_ATA;
		cpi->protocol_version = PROTO_VERSION_UNSPECIFIED;
		cpi->maxio = ch->dma.max_iosize ? ch->dma.max_iosize : DFLTPHYS;
		if (device_get_devclass(device_get_parent(parent)) ==
		    devclass_find("pci")) {
			cpi->hba_vendor = pci_get_vendor(parent);
			cpi->hba_device = pci_get_device(parent);
			cpi->hba_subvendor = pci_get_subvendor(parent);
			cpi->hba_subdevice = pci_get_subdevice(parent);
		}
		cpi->ccb_h.status = CAM_REQ_CMP;
		break;
	}
	default:
		ccb->ccb_h.status = CAM_REQ_INVALID;
		break;
	}
	xpt_done(ccb);
}
示例#18
0
static int
thunder_pem_attach(device_t dev)
{
	devclass_t pci_class;
	device_t parent;
	struct thunder_pem_softc *sc;
	int error;
	int rid;
	int tuple;
	uint64_t base, size;
	struct rman *rman;

	sc = device_get_softc(dev);
	sc->dev = dev;

	/* Allocate memory for resource */
	pci_class = devclass_find("pci");
	parent = device_get_parent(dev);
	if (device_get_devclass(parent) == pci_class)
		rid = PCIR_BAR(0);
	else
		rid = RID_PEM_SPACE;

	sc->reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
	    &rid, RF_ACTIVE);
	if (sc->reg == NULL) {
		device_printf(dev, "Failed to allocate resource\n");
		return (ENXIO);
	}
	sc->reg_bst = rman_get_bustag(sc->reg);
	sc->reg_bsh = rman_get_bushandle(sc->reg);

	/* Map SLI, do it only once */
	if (!sli0_s2m_regx_base) {
		bus_space_map(sc->reg_bst, SLIX_S2M_REGX_ACC,
		    SLIX_S2M_REGX_ACC_SIZE, 0, &sli0_s2m_regx_base);
	}
	if (!sli1_s2m_regx_base) {
		bus_space_map(sc->reg_bst, SLIX_S2M_REGX_ACC +
		    SLIX_S2M_REGX_ACC_SPACING, SLIX_S2M_REGX_ACC_SIZE, 0,
		    &sli1_s2m_regx_base);
	}

	if ((sli0_s2m_regx_base == 0) || (sli1_s2m_regx_base == 0)) {
		device_printf(dev,
		    "bus_space_map failed to map slix_s2m_regx_base\n");
		goto fail;
	}

	/* Identify PEM */
	if (thunder_pem_identify(dev) != 0)
		goto fail;

	/* Initialize rman and allocate regions */
	sc->mem_rman.rm_type = RMAN_ARRAY;
	sc->mem_rman.rm_descr = "PEM PCIe Memory";
	error = rman_init(&sc->mem_rman);
	if (error != 0) {
		device_printf(dev, "memory rman_init() failed. error = %d\n",
		    error);
		goto fail;
	}
	sc->io_rman.rm_type = RMAN_ARRAY;
	sc->io_rman.rm_descr = "PEM PCIe IO";
	error = rman_init(&sc->io_rman);
	if (error != 0) {
		device_printf(dev, "IO rman_init() failed. error = %d\n",
		    error);
		goto fail_mem;
	}

	/*
	 * We ignore the values that may have been provided in FDT
	 * and configure ranges according to the below formula
	 * for all types of devices. This is because some DTBs provided
	 * by EFI do not have proper ranges property or don't have them
	 * at all.
	 */
	/* Fill memory window */
	sc->ranges[0].pci_base = PCI_MEMORY_BASE;
	sc->ranges[0].size = PCI_MEMORY_SIZE;
	sc->ranges[0].phys_base = sc->sli_window_base + SLI_PCI_OFFSET +
	    sc->ranges[0].pci_base;
	sc->ranges[0].flags = SYS_RES_MEMORY;

	/* Fill IO window */
	sc->ranges[1].pci_base = PCI_IO_BASE;
	sc->ranges[1].size = PCI_IO_SIZE;
	sc->ranges[1].phys_base = sc->sli_window_base + SLI_PCI_OFFSET +
	    sc->ranges[1].pci_base;
	sc->ranges[1].flags = SYS_RES_IOPORT;

	for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) {
		base = sc->ranges[tuple].pci_base;
		size = sc->ranges[tuple].size;
		if (size == 0)
			continue; /* empty range element */

		rman = thunder_pem_rman(sc, sc->ranges[tuple].flags);
		if (rman != NULL)
			error = rman_manage_region(rman, base,
			    base + size - 1);
		else
			error = EINVAL;
		if (error) {
			device_printf(dev,
			    "rman_manage_region() failed. error = %d\n", error);
			rman_fini(&sc->mem_rman);
			return (error);
		}
		if (bootverbose) {
			device_printf(dev,
			    "\tPCI addr: 0x%jx, CPU addr: 0x%jx, Size: 0x%jx, Flags:0x%jx\n",
			    sc->ranges[tuple].pci_base,
			    sc->ranges[tuple].phys_base,
			    sc->ranges[tuple].size,
			    sc->ranges[tuple].flags);
		}
	}

	if (thunder_pem_init(sc)) {
		device_printf(dev, "Failure during PEM init\n");
		goto fail_io;
	}

	device_add_child(dev, "pci", -1);

	return (bus_generic_attach(dev));

fail_io:
	rman_fini(&sc->io_rman);
fail_mem:
	rman_fini(&sc->mem_rman);
fail:
	bus_free_resource(dev, SYS_RES_MEMORY, sc->reg);
	return (ENXIO);
}