示例#1
0
int
cfi_attach(device_t dev)
{
    struct cfi_softc *sc;
    u_int blksz, blocks;
    u_int r, u;

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

    sc->sc_rid = 0;
    sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid,
                                        RF_ACTIVE);
    if (sc->sc_res == NULL)
        return (ENXIO);

    sc->sc_tag = rman_get_bustag(sc->sc_res);
    sc->sc_handle = rman_get_bushandle(sc->sc_res);

    /* Get time-out values for erase and write. */
    sc->sc_write_timeout = 1 << cfi_read_qry(sc, CFI_QRY_TTO_WRITE);
    sc->sc_erase_timeout = 1 << cfi_read_qry(sc, CFI_QRY_TTO_ERASE);
    sc->sc_write_timeout *= 1 << cfi_read_qry(sc, CFI_QRY_MTO_WRITE);
    sc->sc_erase_timeout *= 1 << cfi_read_qry(sc, CFI_QRY_MTO_ERASE);

    /* Get erase regions. */
    sc->sc_regions = cfi_read_qry(sc, CFI_QRY_NREGIONS);
    sc->sc_region = malloc(sc->sc_regions * sizeof(struct cfi_region),
                           M_TEMP, M_WAITOK | M_ZERO);
    for (r = 0; r < sc->sc_regions; r++) {
        blocks = cfi_read_qry(sc, CFI_QRY_REGION(r)) |
                 (cfi_read_qry(sc, CFI_QRY_REGION(r) + 1) << 8);
        sc->sc_region[r].r_blocks = blocks + 1;

        blksz = cfi_read_qry(sc, CFI_QRY_REGION(r) + 2) |
                (cfi_read_qry(sc, CFI_QRY_REGION(r) + 3) << 8);
        sc->sc_region[r].r_blksz = (blksz == 0) ? 128 :
                                   blksz * 256;
    }

    /* Reset the device to a default state. */
    cfi_write(sc, 0, CFI_BCS_CLEAR_STATUS);

    if (bootverbose) {
        device_printf(dev, "[");
        for (r = 0; r < sc->sc_regions; r++) {
            printf("%ux%s%s", sc->sc_region[r].r_blocks,
                   cfi_fmtsize(sc->sc_region[r].r_blksz),
                   (r == sc->sc_regions - 1) ? "]\n" : ",");
        }
    }

    u = device_get_unit(dev);
    sc->sc_nod = make_dev(&cfi_cdevsw, u, UID_ROOT, GID_WHEEL, 0600,
                          "%s%u", cfi_driver_name, u);
    sc->sc_nod->si_drv1 = sc;

    device_add_child(dev, "cfid", -1);
    bus_generic_attach(dev);

    return (0);
}
示例#2
0
static int
acpi_cpu_attach(device_t dev)
{
    struct acpi_cpu_softc *sc = device_get_softc(dev);
    ACPI_HANDLE handle;
    device_t child;
    int cpu_id, cpu_features;
    struct acpi_softc *acpi_sc;

    handle = acpi_get_handle(dev);
    cpu_id = acpi_get_magic(dev);

    acpi_sc = acpi_device_get_parent_softc(dev);
    if (cpu_id == 0) {
	sysctl_ctx_init(&sc->glob_sysctl_ctx);
	sc->glob_sysctl_tree = SYSCTL_ADD_NODE(&sc->glob_sysctl_ctx,
			       SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
			       OID_AUTO, "cpu", CTLFLAG_RD, 0,
			       "node for CPU global settings");
    	if (sc->glob_sysctl_tree == NULL)
	    return ENOMEM;
    }

    sysctl_ctx_init(&sc->pcpu_sysctl_ctx);
    sc->pcpu_sysctl_tree = SYSCTL_ADD_NODE(&sc->pcpu_sysctl_ctx,
			   SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree),
			   OID_AUTO, device_get_nameunit(dev), CTLFLAG_RD, 0,
			   "node for per-CPU settings");
    if (sc->pcpu_sysctl_tree == NULL) {
	sysctl_ctx_free(&sc->glob_sysctl_ctx);
	return ENOMEM;
    }

    /*
     * Before calling any CPU methods, collect child driver feature hints
     * and notify ACPI of them.  We support unified SMP power control
     * so advertise this ourselves.  Note this is not the same as independent
     * SMP control where each CPU can have different settings.
     */
    cpu_features = ACPI_PDC_MP_C1PXTX | ACPI_PDC_MP_C2C3;
    cpu_features |= acpi_cpu_md_features();

    /*
     * CPU capabilities are specified as a buffer of 32-bit integers:
     * revision, count, and one or more capabilities.
     */
    if (cpu_features) {
	ACPI_OBJECT_LIST arglist;
	uint32_t cap_set[3];
	ACPI_OBJECT arg[4];
	ACPI_STATUS status;

	/* UUID needed by _OSC evaluation */
	static uint8_t cpu_oscuuid[16] = {
	   0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47,
	   0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53
	};

	arglist.Pointer = arg;
	arglist.Count = 4;
	arg[0].Type = ACPI_TYPE_BUFFER;
	arg[0].Buffer.Length = sizeof(cpu_oscuuid);
	arg[0].Buffer.Pointer = cpu_oscuuid;	/* UUID */
	arg[1].Type = ACPI_TYPE_INTEGER;
	arg[1].Integer.Value = 1;		/* revision */
	arg[2].Type = ACPI_TYPE_INTEGER;
	arg[2].Integer.Value = 2;		/* # of capabilities integers */
	arg[3].Type = ACPI_TYPE_BUFFER;
	arg[3].Buffer.Length = sizeof(cap_set[0]) * 2; /* capabilities buffer */
	arg[3].Buffer.Pointer = (uint8_t *)cap_set;
	cap_set[0] = 0;
	cap_set[1] = cpu_features;
	status = AcpiEvaluateObject(handle, "_OSC", &arglist, NULL);

	if (!ACPI_SUCCESS(status)) {
	    if (bootverbose)
		device_printf(dev, "_OSC failed, use _PDC\n");

	    arglist.Pointer = arg;
	    arglist.Count = 1;
	    arg[0].Type = ACPI_TYPE_BUFFER;
	    arg[0].Buffer.Length = sizeof(cap_set);
	    arg[0].Buffer.Pointer = (uint8_t *)cap_set;
	    cap_set[0] = 1; /* revision */
	    cap_set[1] = 1; /* # of capabilities integers */
	    cap_set[2] = cpu_features;
	    AcpiEvaluateObject(handle, "_PDC", &arglist, NULL);
	}
    }

    child = BUS_ADD_CHILD(dev, dev, 0, "cpu_cst", -1);
    if (child == NULL)
	return ENXIO;
    acpi_set_handle(child, handle);
    acpi_set_magic(child, cpu_id);
    sc->cpu_cst = child;

    child = BUS_ADD_CHILD(dev, dev, 0, "cpu_pst", -1);
    if (child == NULL)
	return ENXIO;
    acpi_set_handle(child, handle);
    acpi_set_magic(child, cpu_id);

    bus_generic_probe(dev);
    bus_generic_attach(dev);

    AcpiInstallNotifyHandler(handle, ACPI_DEVICE_NOTIFY, acpi_cpu_notify, sc);

    return 0;
}
示例#3
0
文件: ismt.c 项目: 2asoft/freebsd
static int
ismt_attach(device_t dev)
{
	struct ismt_softc *sc = device_get_softc(dev);
	int err, num_vectors, val;

	sc->pcidev = dev;
	pci_enable_busmaster(dev);

	if ((sc->smbdev = device_add_child(dev, "smbus", -1)) == NULL) {
		device_printf(dev, "no smbus child found\n");
		err = ENXIO;
		goto fail;
	}

	sc->mmio_rid = PCIR_BAR(0);
	sc->mmio_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
	    &sc->mmio_rid, RF_ACTIVE);
	if (sc->mmio_res == NULL) {
		device_printf(dev, "cannot allocate mmio region\n");
		err = ENOMEM;
		goto fail;
	}

	sc->mmio_tag = rman_get_bustag(sc->mmio_res);
	sc->mmio_handle = rman_get_bushandle(sc->mmio_res);

	/* Attach "smbus" child */
	if ((err = bus_generic_attach(dev)) != 0) {
		device_printf(dev, "failed to attach child: %d\n", err);
		err = ENXIO;
		goto fail;
	}

	bus_dma_tag_create(bus_get_dma_tag(dev), 4, PAGE_SIZE,
	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
	    DESC_SIZE, 1, DESC_SIZE,
	    0, NULL, NULL, &sc->desc_dma_tag);

	bus_dma_tag_create(bus_get_dma_tag(dev), 4, PAGE_SIZE,
	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
	    DMA_BUFFER_SIZE, 1, DMA_BUFFER_SIZE,
	    0, NULL, NULL, &sc->dma_buffer_dma_tag);

	bus_dmamap_create(sc->desc_dma_tag, 0,
	    &sc->desc_dma_map);
	bus_dmamap_create(sc->dma_buffer_dma_tag, 0,
	    &sc->dma_buffer_dma_map);

	bus_dmamem_alloc(sc->desc_dma_tag,
	    (void **)&sc->desc, BUS_DMA_WAITOK,
	    &sc->desc_dma_map);
	bus_dmamem_alloc(sc->dma_buffer_dma_tag,
	    (void **)&sc->dma_buffer, BUS_DMA_WAITOK,
	    &sc->dma_buffer_dma_map);

	bus_dmamap_load(sc->desc_dma_tag,
	    sc->desc_dma_map, sc->desc, DESC_SIZE,
	    ismt_single_map, &sc->desc_bus_addr, 0);
	bus_dmamap_load(sc->dma_buffer_dma_tag,
	    sc->dma_buffer_dma_map, sc->dma_buffer, DMA_BUFFER_SIZE,
	    ismt_single_map, &sc->dma_buffer_bus_addr, 0);

	bus_write_4(sc->mmio_res, ISMT_MSTR_MDBA,
	    (sc->desc_bus_addr & 0xFFFFFFFFLL));
	bus_write_4(sc->mmio_res, ISMT_MSTR_MDBA + 4,
	    (sc->desc_bus_addr >> 32));

	/* initialize the Master Control Register (MCTRL) */
	bus_write_4(sc->mmio_res, ISMT_MSTR_MCTRL, ISMT_MCTRL_MEIE);

	/* initialize the Master Status Register (MSTS) */
	bus_write_4(sc->mmio_res, ISMT_MSTR_MSTS, 0);

	/* initialize the Master Descriptor Size (MDS) */
	val = bus_read_4(sc->mmio_res, ISMT_MSTR_MDS);
	val &= ~ISMT_MDS_MASK;
	val |= (ISMT_DESC_ENTRIES - 1);
	bus_write_4(sc->mmio_res, ISMT_MSTR_MDS, val);

	sc->using_msi = 1;

	if (pci_msi_count(dev) == 0) {
		sc->using_msi = 0;
		goto intx;
	}

	num_vectors = 1;
	if (pci_alloc_msi(dev, &num_vectors) != 0) {
		sc->using_msi = 0;
		goto intx;
	}

	sc->intr_rid = 1;
	sc->intr_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
	    &sc->intr_rid, RF_ACTIVE);

	if (sc->intr_res == NULL) {
		sc->using_msi = 0;
		pci_release_msi(dev);
	}

intx:
	if (sc->using_msi == 0) {
		sc->intr_rid = 0;
		sc->intr_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
		    &sc->intr_rid, RF_SHAREABLE | RF_ACTIVE);
		if (sc->intr_res == NULL) {
			device_printf(dev, "cannot allocate irq\n");
			err = ENXIO;
			goto fail;
		}
	}

	ISMT_DEBUG(dev, "using_msi = %d\n", sc->using_msi);

	err = bus_setup_intr(dev, sc->intr_res,
	    INTR_TYPE_MISC | INTR_MPSAFE, NULL, ismt_intr, sc,
	    &sc->intr_handle);
	if (err != 0) {
		device_printf(dev, "cannot setup interrupt\n");
		err = ENXIO;
		goto fail;
	}

	return (0);

fail:
	ismt_detach(dev);
	return (err);
}
示例#4
0
static int
bcm_spi_attach(device_t dev)
{
	struct bcm_spi_softc *sc;
	device_t gpio;
	int i, rid;

	if (device_get_unit(dev) != 0) {
		device_printf(dev, "only one SPI controller supported\n");
		return (ENXIO);
	}

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

	/* Configure the GPIO pins to ALT0 function to enable SPI the pins. */
	gpio = devclass_get_device(devclass_find("gpio"), 0);
	if (!gpio) {
		device_printf(dev, "cannot find gpio0\n");
		return (ENXIO);
	}
	for (i = 0; i < nitems(bcm_spi_pins); i++)
		bcm_gpio_set_alternate(gpio, bcm_spi_pins[i], BCM_GPIO_ALT0);

	rid = 0;
	sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE);
	if (!sc->sc_mem_res) {
		device_printf(dev, "cannot allocate memory window\n");
		return (ENXIO);
	}

	sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
	sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);

	rid = 0;
	sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
	    RF_ACTIVE);
	if (!sc->sc_irq_res) {
		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
		device_printf(dev, "cannot allocate interrupt\n");
		return (ENXIO);
	}

	/* Hook up our interrupt handler. */
	if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
	    NULL, bcm_spi_intr, sc, &sc->sc_intrhand)) {
		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
		device_printf(dev, "cannot setup the interrupt handler\n");
		return (ENXIO);
	}

	mtx_init(&sc->sc_mtx, "bcm_spi", NULL, MTX_DEF);

	/* Add sysctl nodes. */
	bcm_spi_sysctl_init(sc);

#ifdef	BCM_SPI_DEBUG
	bcm_spi_printr(dev);
#endif

	/*
	 * Enable the SPI controller.  Clear the rx and tx FIFO.
	 * Defaults to SPI mode 0.
	 */
	BCM_SPI_WRITE(sc, SPI_CS, SPI_CS_CLEAR_RXFIFO | SPI_CS_CLEAR_TXFIFO);

	/* Set the SPI clock to 500Khz. */
	BCM_SPI_WRITE(sc, SPI_CLK, SPI_CORE_CLK / 500000);

#ifdef	BCM_SPI_DEBUG
	bcm_spi_printr(dev);
#endif

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

	return (bus_generic_attach(dev));
}
示例#5
0
/*
 * Scan Open Firmware child nodes, and attach these as children
 * of the macgpio bus
 */
static int 
macgpio_attach(device_t dev)
{
	struct macgpio_softc *sc;
        struct macgpio_devinfo *dinfo;
        phandle_t root, child, iparent;
        device_t cdev;
	uint32_t irq;

	sc = device_get_softc(dev);
	root = sc->sc_node = ofw_bus_get_node(dev);
	
	sc->sc_gpios = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
	    &sc->sc_gpios_rid, RF_ACTIVE);

	/*
	 * Iterate through the sub-devices
	 */
	for (child = OF_child(root); child != 0; child = OF_peer(child)) {
		dinfo = malloc(sizeof(*dinfo), M_MACGPIO, M_WAITOK | M_ZERO);
		if (ofw_bus_gen_setup_devinfo(&dinfo->mdi_obdinfo, child) !=
		    0) {
			free(dinfo, M_MACGPIO);
			continue;
		}

		if (OF_getprop(child,"reg",&dinfo->gpio_num,
		    sizeof(dinfo->gpio_num)) != sizeof(dinfo->gpio_num)) {
			/*
			 * Some early GPIO controllers don't provide GPIO
			 * numbers for GPIOs designed only to provide
			 * interrupt resources.  We should still allow these
			 * to attach, but with caution.
			 */

			dinfo->gpio_num = -1;
		}

		resource_list_init(&dinfo->mdi_resources);

		if (OF_getprop(child, "interrupts", &irq, sizeof(irq)) == 
		    sizeof(irq)) {
			OF_searchprop(child, "interrupt-parent", &iparent,
			    sizeof(iparent));
			resource_list_add(&dinfo->mdi_resources, SYS_RES_IRQ,
			    0, MAP_IRQ(iparent, irq), MAP_IRQ(iparent, irq),
			    1);
		}

		/* Fix messed-up offsets */
		if (dinfo->gpio_num > 0x50)
			dinfo->gpio_num -= 0x50;

		cdev = device_add_child(dev, NULL, -1);
		if (cdev == NULL) {
			device_printf(dev, "<%s>: device_add_child failed\n",
			    dinfo->mdi_obdinfo.obd_name);
			ofw_bus_gen_destroy_devinfo(&dinfo->mdi_obdinfo);
			free(dinfo, M_MACGPIO);
			continue;
		}
		device_set_ivars(cdev, dinfo);
	}

	return (bus_generic_attach(dev));
}
示例#6
0
文件: obio.c 项目: 2asoft/freebsd
static int
obio_attach(device_t dev)
{
	struct obio_softc *sc = device_get_softc(dev);
	int rid;

	sc->oba_mem_rman.rm_type = RMAN_ARRAY;
	sc->oba_mem_rman.rm_descr = "OBIO memory";
	if (rman_init(&sc->oba_mem_rman) != 0 ||
	    rman_manage_region(&sc->oba_mem_rman, OBIO_MEM_START,
	        OBIO_MEM_END) != 0)
		panic("obio_attach: failed to set up I/O rman");

	sc->oba_irq_rman.rm_type = RMAN_ARRAY;
	sc->oba_irq_rman.rm_descr = "OBIO IRQ";
	if (rman_init(&sc->oba_irq_rman) != 0 ||
	    rman_manage_region(&sc->oba_irq_rman, 0, NIRQS-1) != 0)
		panic("obio_attach: failed to set up IRQ rman");

	/* Hook up our interrupt handler. */
	if ((sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
	    RT305X_INTR, RT305X_INTR, 1,
	    RF_SHAREABLE | RF_ACTIVE)) == NULL) {
		device_printf(dev, "unable to allocate IRQ resource\n");
		return (ENXIO);
	}

	if ((bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC, obio_intr, NULL,
	    sc, &sc->sc_ih))) {
		device_printf(dev,
		    "WARNING: unable to register interrupt handler\n");
		return (ENXIO);
	}

	/* Hook up our FAST interrupt handler. */
	if ((sc->sc_fast_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
	    RT305X_FAST_INTR, RT305X_FAST_INTR, 1,
	    RF_SHAREABLE | RF_ACTIVE)) == NULL) {
		device_printf(dev, "unable to allocate IRQ resource\n");
		return (ENXIO);
	}

	if ((bus_setup_intr(dev, sc->sc_fast_irq, INTR_TYPE_MISC, obio_intr,
	    NULL, sc, &sc->sc_fast_ih))) {
		device_printf(dev,
		    "WARNING: unable to register interrupt handler\n");
		return (ENXIO);
	}

	/* disable all interrupts */
	rt305x_ic_set(IC_INT_DIS, IC_INT_MASK|IC_LINE_GLOBAL);

	bus_generic_probe(dev);

	obio_add_res_child(dev, "rt305x_sysctl", 0, 
	    SYSCTL_BASE, (SYSCTL_END - SYSCTL_BASE + 1),
	    IC_SYSCTL);
	obio_add_res_child(dev, "rt305x_ic", 0, 
	    INTCTL_BASE, (INTCTL_END - INTCTL_BASE + 1),
	    -1);
#ifdef notyet
	obio_add_res_child(dev, "timer",0, 
	    TIMER_BASE, (TIMER_END - TIMER_BASE  + 1),
	    IC_TIMER0);
	obio_add_res_child(dev, "rt305x_memc", 0,
	    MEMCTRL_BASE, (MEMCTRL_END - MEMCTRL_BASE + 1),
	    -1);
	obio_add_res_child(dev, "pcm", 	0, 
	    PCM_BASE, (PCM_END - PCM_BASE  + 1),
	    IC_PCM);
#endif
	obio_add_res_child(dev, "uart", 0, 
	    UART_BASE, (UART_END - UART_BASE + 1),
	    IC_UART);
	obio_add_res_child(dev, "gpio", 0, 
	    PIO_BASE, (PIO_END - PIO_BASE  + 1),
	    IC_PIO);
#ifdef notyet
	obio_add_res_child(dev, "rt305x_dma", 0,
	    GDMA_BASE, (GDMA_END - GDMA_BASE + 1),
	    IC_DMA);
	obio_add_res_child(dev, "rt305x_nandc", 0,
	    NANDFC_BASE, (NANDFC_END - NANDFC_BASE  + 1),
	    IC_NAND);
	obio_add_res_child(dev, "i2c", 	0,
	    I2C_BASE, (I2C_END - I2C_BASE  + 1),
	    -1);
	obio_add_res_child(dev, "i2s", 0,
	    I2S_BASE, (I2S_END - I2S_BASE  + 1),
	    IC_I2S);
#endif
	obio_add_res_child(dev, "spi", 0, 
	    SPI_BASE, (SPI_END - SPI_BASE  + 1),
	    -1);
	obio_add_res_child(dev, "uart", 1,
	    UARTLITE_BASE, (UARTLITE_END - UARTLITE_BASE + 1),
	    IC_UARTLITE);
#if !defined(RT5350) && !defined(MT7620)
	obio_add_res_child(dev, "cfi", 	0,
	    FLASH_BASE, (FLASH_END - FLASH_BASE  + 1),
	    -1);
	obio_add_res_child(dev, "dwcotg", 0,
	    USB_OTG_BASE, (USB_OTG_END - USB_OTG_BASE  + 1),
	    IC_OTG);
#else
	obio_add_res_child(dev, "ehci", 0,
	    USB_OTG_BASE, (USB_OTG_END - USB_OTG_BASE  + 1),
	    IC_OTG);
	obio_add_res_child(dev, "ohci", 0,
	    USB_OHCI_BASE, (USB_OHCI_END - USB_OHCI_BASE + 1),
	    IC_OTG);
#endif
	obio_add_res_child(dev, "switch", 0,
	    ETHSW_BASE, (ETHSW_END - ETHSW_BASE  + 1),
	    IC_ETHSW);

	bus_enumerate_hinted_children(dev);
	bus_generic_attach(dev);

	/* enable IC */
	rt305x_ic_set(IC_INT_ENA, IC_LINE_GLOBAL);

	return (0);
}
示例#7
0
static int
ofw_cpu_attach(device_t dev)
{
	bus_generic_probe(dev);
	return (bus_generic_attach(dev));
}
示例#8
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;

	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;
	rman_manage_region(&sc->mem_rman, sc->ranges[0].phys_base,
	    sc->ranges[0].phys_base + sc->ranges[0].size - 1);

	/* 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;
	rman_manage_region(&sc->io_rman, sc->ranges[1].phys_base,
	    sc->ranges[1].phys_base + sc->ranges[1].size - 1);

	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);
}
示例#9
0
static int
zbpci_attach(device_t dev)
{
	int n, rid, size;
	vm_offset_t va;
	struct resource *res;
	
	/*
	 * Reserve the physical memory window used to map PCI I/O space.
	 */
	rid = 0;
	res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
				 PCI_IOSPACE_ADDR,
				 PCI_IOSPACE_ADDR + PCI_IOSPACE_SIZE - 1,
				 PCI_IOSPACE_SIZE, 0);
	if (res == NULL)
		panic("Cannot allocate resource for PCI I/O space mapping.");

	port_rman.rm_start = 0;
	port_rman.rm_end = PCI_IOSPACE_SIZE - 1;
	port_rman.rm_type = RMAN_ARRAY;
	port_rman.rm_descr = "PCI I/O ports";
	if (rman_init(&port_rman) != 0 ||
	    rman_manage_region(&port_rman, 0, PCI_IOSPACE_SIZE - 1) != 0)
		panic("%s: port_rman", __func__);

	/*
	 * Reserve the physical memory that is used to read/write to the
	 * pci config space but don't activate it. We are using a page worth
	 * of KVA as a window over this region.
	 */
	rid = 1;
	size = (PCI_BUSMAX + 1) * (PCI_SLOTMAX + 1) * (PCI_FUNCMAX + 1) * 256;
	res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, CFG_PADDR_BASE,
				 CFG_PADDR_BASE + size - 1, size, 0);
	if (res == NULL)
		panic("Cannot allocate resource for config space accesses.");

	/*
	 * Allocate the entire "match bit lanes" address space.
	 */
#if _BYTE_ORDER == _BIG_ENDIAN
	rid = 2;
	res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 
				 PCI_MATCH_BIT_LANES_START,
				 PCI_MATCH_BIT_LANES_END,
				 PCI_MATCH_BIT_LANES_SIZE, 0);
	if (res == NULL)
		panic("Cannot allocate resource for pci match bit lanes.");
#endif	/* _BYTE_ORDER ==_BIG_ENDIAN */

	/*
	 * Allocate KVA for accessing PCI config space.
	 */
	va = kva_alloc(PAGE_SIZE * mp_ncpus);
	if (va == 0) {
		device_printf(dev, "Cannot allocate virtual addresses for "
				   "config space access.\n");
		return (ENOMEM);
	}

	for (n = 0; n < mp_ncpus; ++n)
		zbpci_config_space[n].vaddr = va + n * PAGE_SIZE;

	/*
	 * Sibyte has the PCI bus hierarchy rooted at bus 0 and HT-PCI
	 * hierarchy rooted at bus 1.
	 */
	if (device_add_child(dev, "pci", 0) == NULL)
		panic("zbpci_attach: could not add pci bus 0.\n");

	if (device_add_child(dev, "pci", 1) == NULL)
		panic("zbpci_attach: could not add pci bus 1.\n");

	if (bootverbose)
		device_printf(dev, "attached.\n");

	return (bus_generic_attach(dev));
}
示例#10
0
static int
mambobus_attach(device_t dev)
{
	bus_generic_probe(dev);
	return (bus_generic_attach(dev));
}
示例#11
0
static int
sata_attach(device_t dev)
{
	struct sata_softc *sc;
	int mem_id, irq_id, error, i;
	device_t ata_chan;
	uint32_t reg;

	sc = device_get_softc(dev);
	sc->sc_dev = dev;
	mem_id = 0;
	irq_id = 0;

	/* Allocate resources */
	sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
	    &mem_id, RF_ACTIVE);
	if (sc->sc_mem_res == NULL) {
		device_printf(dev, "could not allocate memory.\n");
		return (ENOMEM);
	}

	sc->sc_mem_res_bustag = rman_get_bustag(sc->sc_mem_res);
	sc->sc_mem_res_bushdl = rman_get_bushandle(sc->sc_mem_res);
	KASSERT(sc->sc_mem_res_bustag && sc->sc_mem_res_bushdl,
	    ("cannot get bus handle or tag."));

	sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irq_id,
	    RF_ACTIVE);
	if (sc->sc_irq_res == NULL) {
		device_printf(dev, "could not allocate IRQ.\n");
		error = ENOMEM;
		goto err;
	}

	error = bus_setup_intr(dev, sc->sc_irq_res,
	    INTR_TYPE_BIO | INTR_MPSAFE | INTR_ENTROPY,
	    NULL, sata_intr, sc, &sc->sc_irq_cookiep);
	if (error != 0) {
		device_printf(dev, "could not setup interrupt.\n");
		goto err;
	}

	/* Attach channels */
	for (i = 0; i < SATA_CHAN_NUM; i++) {
		ata_chan = device_add_child(dev, "ata",
		    devclass_find_free_unit(ata_devclass, 0));

		if (!ata_chan) {
			device_printf(dev, "cannot add channel %d.\n", i);
			error = ENOMEM;
			goto err;
		}
	}

	/* Disable interrupt coalescing */
	reg = SATA_INL(sc, SATA_CR);
	for (i = 0; i < SATA_CHAN_NUM; i++)
		reg |= SATA_CR_COALDIS(i);

	/* Disable DMA byte swapping */
	if (sc->sc_version == 2)
		reg |= SATA_CR_NODMABS | SATA_CR_NOEDMABS |
		    SATA_CR_NOPRDPBS;

	SATA_OUTL(sc, SATA_CR, reg);

	/* Clear and mask all interrupts */
	SATA_OUTL(sc, SATA_ICR, 0);
	SATA_OUTL(sc, SATA_MIMR, 0);

	return(bus_generic_attach(dev));

err:
	sata_detach(dev);
	return (error);
}
示例#12
0
static int
lbc_attach(device_t dev)
{
	struct lbc_softc *sc;
	struct lbc_devinfo *di;
	struct rman *rm;
	u_long offset, start, size;
	device_t cdev;
	phandle_t node, child;
	pcell_t *ranges, *rangesptr;
	int tuple_size, tuples;
	int par_addr_cells;
	int bank, error, i;

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

	sc->sc_mrid = 0;
	sc->sc_mres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_mrid,
	    RF_ACTIVE);
	if (sc->sc_mres == NULL)
		return (ENXIO);

	sc->sc_bst = rman_get_bustag(sc->sc_mres);
	sc->sc_bsh = rman_get_bushandle(sc->sc_mres);

	for (bank = 0; bank < LBC_DEV_MAX; bank++) {
		bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_BR(bank), 0);
		bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_OR(bank), 0);
	}

	/*
	 * Initialize configuration register:
	 * - enable Local Bus
	 * - set data buffer control signal function
	 * - disable parity byte select
	 * - set ECC parity type
	 * - set bus monitor timing and timer prescale
	 */
	bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LBCR, 0);

	/*
	 * Initialize clock ratio register:
	 * - disable PLL bypass mode
	 * - configure LCLK delay cycles for the assertion of LALE
	 * - set system clock divider
	 */
	bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LCRR, 0x00030008);

	bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTEDR, 0);
	bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTESR, ~0);
	bus_space_write_4(sc->sc_bst, sc->sc_bsh, LBC85XX_LTEIR, 0x64080001);

	sc->sc_irid = 0;
	sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid,
	    RF_ACTIVE | RF_SHAREABLE);
	if (sc->sc_ires != NULL) {
		error = bus_setup_intr(dev, sc->sc_ires,
		    INTR_TYPE_MISC | INTR_MPSAFE, NULL, lbc_intr, sc,
		    &sc->sc_icookie);
		if (error) {
			device_printf(dev, "could not activate interrupt\n");
			bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
			    sc->sc_ires);
			sc->sc_ires = NULL;
		}
	}

	sc->sc_ltesr = ~0;

	rangesptr = NULL;

	rm = &sc->sc_rman;
	rm->rm_type = RMAN_ARRAY;
	rm->rm_descr = "Local Bus Space";
	rm->rm_start = 0UL;
	rm->rm_end = ~0UL;
	error = rman_init(rm);
	if (error)
		goto fail;

	error = rman_manage_region(rm, rm->rm_start, rm->rm_end);
	if (error) {
		rman_fini(rm);
		goto fail;
	}

	/*
	 * Process 'ranges' property.
	 */
	node = ofw_bus_get_node(dev);
	if ((fdt_addrsize_cells(node, &sc->sc_addr_cells,
	    &sc->sc_size_cells)) != 0) {
		error = ENXIO;
		goto fail;
	}

	par_addr_cells = fdt_parent_addr_cells(node);
	if (par_addr_cells > 2) {
		device_printf(dev, "unsupported parent #addr-cells\n");
		error = ERANGE;
		goto fail;
	}
	tuple_size = sizeof(pcell_t) * (sc->sc_addr_cells + par_addr_cells +
	    sc->sc_size_cells);

	tuples = OF_getprop_alloc(node, "ranges", tuple_size,
	    (void **)&ranges);
	if (tuples < 0) {
		device_printf(dev, "could not retrieve 'ranges' property\n");
		error = ENXIO;
		goto fail;
	}
	rangesptr = ranges;

	debugf("par addr_cells = %d, addr_cells = %d, size_cells = %d, "
	    "tuple_size = %d, tuples = %d\n", par_addr_cells,
	    sc->sc_addr_cells, sc->sc_size_cells, tuple_size, tuples);

	start = 0;
	size = 0;
	for (i = 0; i < tuples; i++) {

		/* The first cell is the bank (chip select) number. */
		bank = fdt_data_get((void *)ranges, 1);
		if (bank < 0 || bank > LBC_DEV_MAX) {
			device_printf(dev, "bank out of range: %d\n", bank);
			error = ERANGE;
			goto fail;
		}
		ranges += 1;

		/*
		 * Remaining cells of the child address define offset into
		 * this CS.
		 */
		offset = fdt_data_get((void *)ranges, sc->sc_addr_cells - 1);
		ranges += sc->sc_addr_cells - 1;

		/* Parent bus start address of this bank. */
		start = fdt_data_get((void *)ranges, par_addr_cells);
		ranges += par_addr_cells;

		size = fdt_data_get((void *)ranges, sc->sc_size_cells);
		ranges += sc->sc_size_cells;
		debugf("bank = %d, start = %lx, size = %lx\n", bank,
		    start, size);

		sc->sc_banks[bank].addr = start + offset;
		sc->sc_banks[bank].size = size;

		/*
		 * Attributes for the bank.
		 *
		 * XXX Note there are no DT bindings defined for them at the
		 * moment, so we need to provide some defaults.
		 */
		sc->sc_banks[bank].width = 16;
		sc->sc_banks[bank].msel = LBCRES_MSEL_GPCM;
		sc->sc_banks[bank].decc = LBCRES_DECC_DISABLED;
		sc->sc_banks[bank].atom = LBCRES_ATOM_DISABLED;
		sc->sc_banks[bank].wp = 0;
	}

	/*
	 * Initialize mem-mappings for the LBC banks (i.e. chip selects).
	 */
	error = lbc_banks_map(sc);
	if (error)
		goto fail;

	/*
	 * Walk the localbus and add direct subordinates as our children.
	 */
	for (child = OF_child(node); child != 0; child = OF_peer(child)) {

		di = malloc(sizeof(*di), M_LBC, M_WAITOK | M_ZERO);

		if (ofw_bus_gen_setup_devinfo(&di->di_ofw, child) != 0) {
			free(di, M_LBC);
			device_printf(dev, "could not set up devinfo\n");
			continue;
		}

		resource_list_init(&di->di_res);

		if (fdt_lbc_reg_decode(child, sc, di)) {
			device_printf(dev, "could not process 'reg' "
			    "property\n");
			ofw_bus_gen_destroy_devinfo(&di->di_ofw);
			free(di, M_LBC);
			continue;
		}

		fdt_lbc_fixup(child, sc, di);

		/* Add newbus device for this FDT node */
		cdev = device_add_child(dev, NULL, -1);
		if (cdev == NULL) {
			device_printf(dev, "could not add child: %s\n",
			    di->di_ofw.obd_name);
			resource_list_free(&di->di_res);
			ofw_bus_gen_destroy_devinfo(&di->di_ofw);
			free(di, M_LBC);
			continue;
		}
		debugf("added child name='%s', node=%p\n", di->di_ofw.obd_name,
		    (void *)child);
		device_set_ivars(cdev, di);
	}

	/*
	 * Enable the LBC.
	 */
	lbc_banks_enable(sc);

	free(rangesptr, M_OFWPROP);
	return (bus_generic_attach(dev));

fail:
	free(rangesptr, M_OFWPROP);
	bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mrid, sc->sc_mres);
	return (error);
}
示例#13
0
/*
 * PCI attach: scan Open Firmware child nodes, and attach these as children
 * of the macio bus
 */
static int 
macio_attach(device_t dev)
{
	struct macio_softc *sc;
        struct macio_devinfo *dinfo;
        phandle_t  root;
	phandle_t  child;
	phandle_t  subchild;
        device_t cdev;
        u_int reg[3];
	int error, quirks;

	sc = device_get_softc(dev);
	root = sc->sc_node = ofw_bus_get_node(dev);
	
	/*
	 * Locate the device node and it's base address
	 */
	if (OF_getprop(root, "assigned-addresses", 
		       reg, sizeof(reg)) < sizeof(reg)) {
		return (ENXIO);
	}

	sc->sc_base = reg[2];
	sc->sc_size = MACIO_REG_SIZE;

	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
	sc->sc_mem_rman.rm_descr = "MacIO Device Memory";
	error = rman_init(&sc->sc_mem_rman);
	if (error) {
		device_printf(dev, "rman_init() failed. error = %d\n", error);
		return (error);
	}
	error = rman_manage_region(&sc->sc_mem_rman, 0, sc->sc_size);	
	if (error) {
		device_printf(dev,
		    "rman_manage_region() failed. error = %d\n", error);
		return (error);
	}

	/*
	 * Iterate through the sub-devices
	 */
	for (child = OF_child(root); child != 0; child = OF_peer(child)) {
		dinfo = malloc(sizeof(*dinfo), M_MACIO, M_WAITOK | M_ZERO);
		if (ofw_bus_gen_setup_devinfo(&dinfo->mdi_obdinfo, child) !=
		    0) {
			free(dinfo, M_MACIO);
			continue;
		}
		quirks = macio_get_quirks(dinfo->mdi_obdinfo.obd_name);
		if ((quirks & MACIO_QUIRK_IGNORE) != 0) {
			ofw_bus_gen_destroy_devinfo(&dinfo->mdi_obdinfo);
			free(dinfo, M_MACIO);
			continue;
		}
		resource_list_init(&dinfo->mdi_resources);
		dinfo->mdi_ninterrupts = 0;
		macio_add_intr(child, dinfo);
		if ((quirks & MACIO_QUIRK_USE_CHILD_REG) != 0)
			macio_add_reg(OF_child(child), dinfo);
		else
			macio_add_reg(child, dinfo);
		if ((quirks & MACIO_QUIRK_CHILD_HAS_INTR) != 0)
			for (subchild = OF_child(child); subchild != 0;
			    subchild = OF_peer(subchild))
				macio_add_intr(subchild, dinfo);
		cdev = device_add_child(dev, NULL, -1);
		if (cdev == NULL) {
			device_printf(dev, "<%s>: device_add_child failed\n",
			    dinfo->mdi_obdinfo.obd_name);
			resource_list_free(&dinfo->mdi_resources);
			ofw_bus_gen_destroy_devinfo(&dinfo->mdi_obdinfo);
			free(dinfo, M_MACIO);
			continue;
		}
		device_set_ivars(cdev, dinfo);
	}

	return (bus_generic_attach(dev));
}
示例#14
0
文件: envctrl.c 项目: MarginC/kame
static int
envctrl_attach(device_t dev)
{
	struct pcf_softc *sc;
	int rv = ENXIO;

	sc = DEVTOSOFTC(dev);
	bzero(sc, sizeof(struct pcf_softc));

	/* IO port is mandatory */
	sc->res_ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
						&sc->rid_ioport, RF_ACTIVE);
	if (sc->res_ioport == 0) {
		device_printf(dev, "cannot reserve I/O port range\n");
		goto error;
	}
	sc->bt_ioport = rman_get_bustag(sc->res_ioport);
	sc->bh_ioport = rman_get_bushandle(sc->res_ioport);

	sc->pcf_flags = device_get_flags(dev);

	if (!(sc->pcf_flags & IIC_POLLED)) {
		sc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->rid_irq,
						     RF_ACTIVE);
		if (sc->res_irq == 0) {
			device_printf(dev, "can't reserve irq, polled mode.\n");
			sc->pcf_flags |= IIC_POLLED;
		}
	}

	/* reset the chip */
	pcf_rst_card(dev, IIC_FASTEST, PCF_DEFAULT_ADDR, NULL);

	rv = BUS_SETUP_INTR(device_get_parent(dev), dev, sc->res_irq,
			    INTR_TYPE_NET /* | INTR_ENTROPY */,
			    pcf_intr, sc, &sc->intr_cookie);
	if (rv) {
		device_printf(dev, "could not setup IRQ\n");
		goto error;
	}

	if ((sc->iicbus = device_add_child(dev, "iicbus", -1)) == NULL)
		device_printf(dev, "could not allocate iicbus instance\n");

	/* probe and attach the iicbus */
	bus_generic_attach(dev);

	return (0);

error:
	if (sc->res_irq != 0) {
		bus_deactivate_resource(dev, SYS_RES_IRQ, sc->rid_irq,
					sc->res_irq);
		bus_release_resource(dev, SYS_RES_IRQ, sc->rid_irq,
				     sc->res_irq);
	}
	if (sc->res_ioport != 0) {
		bus_deactivate_resource(dev, SYS_RES_IOPORT, sc->rid_ioport,
					sc->res_ioport);
		bus_release_resource(dev, SYS_RES_IOPORT, sc->rid_ioport,
				     sc->res_ioport);
	}
	return (rv);
}
示例#15
0
static int
fm801_pci_attach(device_t dev)
{
	struct ac97_info 	*codec = 0;
	struct fm801_info 	*fm801;
	int 			i;
	int 			mapped = 0;
	char 			status[SND_STATUSLEN];

	fm801 = malloc(sizeof(*fm801), M_DEVBUF, M_WAITOK | M_ZERO);
	fm801->type = pci_get_devid(dev);

	pci_enable_busmaster(dev);

	for (i = 0; (mapped == 0) && (i < PCI_MAXMAPS_0); i++) {
		fm801->regid = PCIR_BAR(i);
		fm801->regtype = SYS_RES_MEMORY;
		fm801->reg = bus_alloc_resource_any(dev, fm801->regtype,
						    &fm801->regid, RF_ACTIVE);
		if(!fm801->reg)
		{
			fm801->regtype = SYS_RES_IOPORT;
			fm801->reg = bus_alloc_resource_any(dev, 
							    fm801->regtype,
							    &fm801->regid,
							    RF_ACTIVE);
		}

		if(fm801->reg) {
			fm801->st = rman_get_bustag(fm801->reg);
			fm801->sh = rman_get_bushandle(fm801->reg);
			mapped++;
		}
	}

	if (mapped == 0) {
		device_printf(dev, "unable to map register space\n");
		goto oops;
	}

	fm801->bufsz = pcm_getbuffersize(dev, 4096, FM801_DEFAULT_BUFSZ, 65536);

	fm801_init(fm801);

	codec = AC97_CREATE(dev, fm801, fm801_ac97);
	if (codec == NULL) goto oops;

	if (mixer_init(dev, ac97_getmixerclass(), codec) == -1) goto oops;

	fm801->irqid = 0;
	fm801->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &fm801->irqid,
					    RF_ACTIVE | RF_SHAREABLE);
	if (!fm801->irq || snd_setup_intr(dev, fm801->irq, 0, fm801_intr, fm801, &fm801->ih)) {
		device_printf(dev, "unable to map interrupt\n");
		goto oops;
	}

	if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev), /*alignment*/2,
		/*boundary*/0,
		/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
		/*highaddr*/BUS_SPACE_MAXADDR,
		/*filter*/NULL, /*filterarg*/NULL,
		/*maxsize*/fm801->bufsz, /*nsegments*/1, /*maxsegz*/0x3ffff,
		/*flags*/0, /*lockfunc*/busdma_lock_mutex,
		/*lockarg*/&Giant, &fm801->parent_dmat) != 0) {
		device_printf(dev, "unable to create dma tag\n");
		goto oops;
	}

	snprintf(status, 64, "at %s 0x%jx irq %jd %s",
		(fm801->regtype == SYS_RES_IOPORT)? "io" : "memory",
		rman_get_start(fm801->reg), rman_get_start(fm801->irq),PCM_KLDSTRING(snd_fm801));

#define FM801_MAXPLAYCH	1
	if (pcm_register(dev, fm801, FM801_MAXPLAYCH, 1)) goto oops;
	pcm_addchan(dev, PCMDIR_PLAY, &fm801ch_class, fm801);
	pcm_addchan(dev, PCMDIR_REC, &fm801ch_class, fm801);
	pcm_setstatus(dev, status);

	fm801->radio = device_add_child(dev, "radio", -1);
	bus_generic_attach(dev);

	return 0;

oops:
	if (codec) ac97_destroy(codec);
	if (fm801->reg) bus_release_resource(dev, fm801->regtype, fm801->regid, fm801->reg);
	if (fm801->ih) bus_teardown_intr(dev, fm801->irq, fm801->ih);
	if (fm801->irq) bus_release_resource(dev, SYS_RES_IRQ, fm801->irqid, fm801->irq);
	if (fm801->parent_dmat) bus_dma_tag_destroy(fm801->parent_dmat);
	free(fm801, M_DEVBUF);
	return ENXIO;
}
示例#16
0
static int
apb_attach(device_t dev)
{
	struct apb_softc *sc = device_get_softc(dev);
#ifdef INTRNG
	intptr_t xref = pic_xref(dev);
	int miscirq;
#else
	int rid = 0;
#endif

	sc->apb_dev = dev;

	sc->apb_mem_rman.rm_type = RMAN_ARRAY;
	sc->apb_mem_rman.rm_descr = "APB memory window";

	if(ar531x_soc >= AR531X_SOC_AR5315) {
		if (rman_init(&sc->apb_mem_rman) != 0 ||
		    rman_manage_region(&sc->apb_mem_rman, 
			AR5315_APB_BASE, 
			AR5315_APB_BASE + AR5315_APB_SIZE - 1) != 0)
			panic("apb_attach: failed to set up memory rman");
	} else {
		if (rman_init(&sc->apb_mem_rman) != 0 ||
		    rman_manage_region(&sc->apb_mem_rman, 
			AR5312_APB_BASE, 
			AR5312_APB_BASE + AR5312_APB_SIZE - 1) != 0)
			panic("apb_attach: failed to set up memory rman");
	}

	sc->apb_irq_rman.rm_type = RMAN_ARRAY;
	sc->apb_irq_rman.rm_descr = "APB IRQ";

	if (rman_init(&sc->apb_irq_rman) != 0 ||
	    rman_manage_region(&sc->apb_irq_rman, 
			APB_IRQ_BASE, APB_IRQ_END) != 0)
		panic("apb_attach: failed to set up IRQ rman");

#ifndef INTRNG
	if ((sc->sc_misc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 
	    RF_SHAREABLE | RF_ACTIVE)) == NULL) {
		device_printf(dev, "unable to allocate IRQ resource\n");
		return (ENXIO);
	}

	if ((bus_setup_intr(dev, sc->sc_misc_irq, INTR_TYPE_MISC, 
	    apb_filter, NULL, sc, &sc->sc_misc_ih))) {
		device_printf(dev,
		    "WARNING: unable to register interrupt handler\n");
		return (ENXIO);
	}
#else
	/* Register the interrupts */
	if (apb_pic_register_isrcs(sc) != 0) {
		device_printf(dev, "could not register PIC ISRCs\n");
		return (ENXIO);
	}

	/*
	 * Now, when everything is initialized, it's right time to
	 * register interrupt controller to interrupt framefork.
	 */
	if (intr_pic_register(dev, xref) == NULL) {
		device_printf(dev, "could not register PIC\n");
		return (ENXIO);
	}

	if(ar531x_soc >= AR531X_SOC_AR5315) {
		miscirq = AR5315_CPU_IRQ_MISC;
	} else {
		miscirq = AR5312_IRQ_MISC;
	}
	cpu_establish_hardintr("aric", apb_filter, NULL, sc, miscirq,
	    INTR_TYPE_MISC, NULL);
#endif

	/* mask all misc interrupt */
	if(ar531x_soc >= AR531X_SOC_AR5315) {
		ATH_WRITE_REG(AR5315_SYSREG_BASE
			+ AR5315_SYSREG_MISC_INTMASK, 0);
	} else {
		ATH_WRITE_REG(AR5312_SYSREG_BASE
			+ AR5312_SYSREG_MISC_INTMASK, 0);
	}

	bus_generic_probe(dev);
	bus_enumerate_hinted_children(dev);
	bus_generic_attach(dev);

	return (0);
}
示例#17
0
static int
at91_attach(device_t dev)
{
	struct at91_softc *sc = device_get_softc(dev);
	const struct arm_devmap_entry *pdevmap;
	int i;

	arm_post_filter = at91_eoi;

	at91_softc = sc;
	sc->sc_st = &at91_bs_tag;
	sc->sc_sh = AT91_BASE;
	sc->sc_aic_sh = AT91_BASE + AT91_SYS_BASE;
	sc->dev = dev;

	sc->sc_irq_rman.rm_type = RMAN_ARRAY;
	sc->sc_irq_rman.rm_descr = "AT91 IRQs";
	if (rman_init(&sc->sc_irq_rman) != 0 ||
	    rman_manage_region(&sc->sc_irq_rman, 1, 31) != 0)
		panic("at91_attach: failed to set up IRQ rman");

	sc->sc_mem_rman.rm_type = RMAN_ARRAY;
	sc->sc_mem_rman.rm_descr = "AT91 Memory";
	if (rman_init(&sc->sc_mem_rman) != 0)
		panic("at91_attach: failed to set up memory rman");
	for (pdevmap = at91_devmap; pdevmap->pd_va != 0; pdevmap++) {
		if (rman_manage_region(&sc->sc_mem_rman, pdevmap->pd_va,
		    pdevmap->pd_va + pdevmap->pd_size - 1) != 0)
			panic("at91_attach: failed to set up memory rman");
	}

	/*
	 * Setup the interrupt table.
	 */
	if (soc_info.soc_data == NULL || soc_info.soc_data->soc_irq_prio == NULL)
		panic("Interrupt priority table missing\n");
	for (i = 0; i < 32; i++) {
		bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SVR +
		    i * 4, i);
		/* Priority. */
		bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SMR + i * 4,
		    soc_info.soc_data->soc_irq_prio[i]);
		if (i < 8)
			bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_EOICR,
			    1);
	}

	bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_SPU, 32);
	/* No debug. */
	bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_DCR, 0);
	/* Disable and clear all interrupts. */
	bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_IDCR, 0xffffffff);
	bus_space_write_4(sc->sc_st, sc->sc_aic_sh, IC_ICCR, 0xffffffff);

        /*
         * Add this device's children...
         */
	at91_cpu_add_builtin_children(dev, soc_info.soc_data->soc_children);
	soc_info.soc_data->soc_clock_init();

	bus_generic_probe(dev);
	bus_generic_attach(dev);
	enable_interrupts(I32_bit | F32_bit);
	return (0);
}
示例#18
0
static int
ofw_iicbus_attach(device_t dev)
{
	struct iicbus_softc *sc = IICBUS_SOFTC(dev);
	struct ofw_iicbus_devinfo *dinfo;
	phandle_t child, node, root;
	pcell_t freq, paddr;
	device_t childdev;
	ssize_t compatlen;
	char compat[255];
	char *curstr;
	u_int iic_addr_8bit = 0;

	sc->dev = dev;
	mtx_init(&sc->lock, "iicbus", NULL, MTX_DEF);

	/*
	 * If there is a clock-frequency property for the device node, use it as
	 * the starting value for the bus frequency.  Then call the common
	 * routine that handles the tunable/sysctl which allows the FDT value to
	 * be overridden by the user.
	 */
	node = ofw_bus_get_node(dev);
	freq = 0;
	OF_getencprop(node, "clock-frequency", &freq, sizeof(freq));
	iicbus_init_frequency(dev, freq);
	
	iicbus_reset(dev, IIC_FASTEST, 0, NULL);

	bus_generic_probe(dev);
	bus_enumerate_hinted_children(dev);

	/*
	 * Check if we're running on a PowerMac, needed for the I2C
	 * address below.
	 */
	root = OF_peer(0);
	compatlen = OF_getprop(root, "compatible", compat,
				sizeof(compat));
	if (compatlen != -1) {
	    for (curstr = compat; curstr < compat + compatlen;
		curstr += strlen(curstr) + 1) {
		if (strncmp(curstr, "MacRISC", 7) == 0)
		    iic_addr_8bit = 1;
	    }
	}

	/*
	 * Attach those children represented in the device tree.
	 */
	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
		/*
		 * Try to get the I2C address first from the i2c-address
		 * property, then try the reg property.  It moves around
		 * on different systems.
		 */
		if (OF_getencprop(child, "i2c-address", &paddr,
		    sizeof(paddr)) == -1)
			if (OF_getencprop(child, "reg", &paddr,
			    sizeof(paddr)) == -1)
				continue;

		/*
		 * Now set up the I2C and OFW bus layer devinfo and add it
		 * to the bus.
		 */
		dinfo = malloc(sizeof(struct ofw_iicbus_devinfo), M_DEVBUF,
		    M_NOWAIT | M_ZERO);
		if (dinfo == NULL)
			continue;
		/*
		 * FreeBSD drivers expect I2C addresses to be expressed as
		 * 8-bit values.  Apple OFW data contains 8-bit values, but
		 * Linux FDT data contains 7-bit values, so shift them up to
		 * 8-bit format.
		 */
		if (iic_addr_8bit)
		    dinfo->opd_dinfo.addr = paddr;
		else
		    dinfo->opd_dinfo.addr = paddr << 1;

		if (ofw_bus_gen_setup_devinfo(&dinfo->opd_obdinfo, child) !=
		    0) {
			free(dinfo, M_DEVBUF);
			continue;
		}

		childdev = device_add_child(dev, NULL, -1);
		resource_list_init(&dinfo->opd_dinfo.rl);
		ofw_bus_intr_to_rl(childdev, child,
					&dinfo->opd_dinfo.rl, NULL);
		device_set_ivars(childdev, dinfo);
	}

	/* Register bus */
	OF_device_register_xref(OF_xref_from_node(node), dev);
	return (bus_generic_attach(dev));
}
示例#19
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 disk_info info;
    struct ad_softc *adp;
    cdev_t cdev;
    u_int32_t lbasize;
    u_int64_t lbasize48;

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

    adp = kmalloc(sizeof(struct ad_softc), M_AD, M_INTWAIT | M_ZERO);
    device_set_ivars(dev, adp);

    if ((atadev->param.atavalid & ATA_FLAG_54_58) &&
	atadev->param.current_heads && atadev->param.current_sectors) {
	adp->heads = atadev->param.current_heads;
	adp->sectors = atadev->param.current_sectors;
	adp->total_secs = (u_int32_t)atadev->param.current_size_1 |
			  ((u_int32_t)atadev->param.current_size_2 << 16);
    }
    else {
	adp->heads = atadev->param.heads;
	adp->sectors = atadev->param.sectors;
	adp->total_secs = atadev->param.cylinders * adp->heads * adp->sectors;  
    }
    lbasize = (u_int32_t)atadev->param.lba_size_1 |
	      ((u_int32_t)atadev->param.lba_size_2 << 16);

    /* does this device need oldstyle CHS addressing */
    if (!ad_version(atadev->param.version_major) || !lbasize)
	atadev->flags |= ATA_D_USE_CHS;

    /* use the 28bit LBA size if valid or bigger than the CHS mapping */
    if (atadev->param.cylinders == 16383 || adp->total_secs < lbasize)
	adp->total_secs = lbasize;

    /* use the 48bit LBA size if valid */
    lbasize48 = ((u_int64_t)atadev->param.lba_size48_1) |
		((u_int64_t)atadev->param.lba_size48_2 << 16) |
		((u_int64_t)atadev->param.lba_size48_3 << 32) |
		((u_int64_t)atadev->param.lba_size48_4 << 48);
    if ((atadev->param.support.command2 & ATA_SUPPORT_ADDRESS48) &&
	lbasize48 > ATA_MAX_28BIT_LBA)
	adp->total_secs = lbasize48;

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

    /* create the disk device */
    /* XXX TGEN Maybe use DEVSTAT_ALL_SUPPORTED, DEVSTAT_TYPE_DIRECT,
       DEVSTAT_PRIORITY_MAX. */
    devstat_add_entry(&adp->stats, "ad", device_get_unit(dev), DEV_BSIZE,
		      DEVSTAT_NO_ORDERED_TAGS,
		      DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_IDE,
		      DEVSTAT_PRIORITY_DISK);
    cdev = disk_create(device_get_unit(dev), &adp->disk, &ad_ops);
    cdev->si_drv1 = dev;
    if (ch->dma)
        cdev->si_iosize_max = ch->dma->max_iosize;
    else
        cdev->si_iosize_max = DFLTPHYS;
    adp->cdev = cdev;

    bzero(&info, sizeof(info));
    info.d_media_blksize = DEV_BSIZE;		/* mandatory */
    info.d_media_blocks = adp->total_secs;

    info.d_secpertrack = adp->sectors;		/* optional */
    info.d_nheads = adp->heads;
    info.d_ncylinders = adp->total_secs/(adp->heads*adp->sectors);
    info.d_secpercyl = adp->sectors * adp->heads;
    info.d_serialno = atadev->param.serial;

    device_add_child(dev, "subdisk", device_get_unit(dev));
    bus_generic_attach(dev);

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

    disk_setdiskinfo(&adp->disk, &info);

    return 0;
}
示例#20
0
文件: sbc.c 项目: ele7enxxh/dtrace-pf
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);
}
示例#21
0
static int
bcm_bsc_attach(device_t dev)
{
    struct bcm_bsc_softc *sc;
    unsigned long start;
    device_t gpio;
    int i, rid;

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

    rid = 0;
    sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
                                            RF_ACTIVE);
    if (!sc->sc_mem_res) {
        device_printf(dev, "cannot allocate memory window\n");
        return (ENXIO);
    }

    sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
    sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);

    /* Check the unit we are attaching by its base address. */
    start = rman_get_start(sc->sc_mem_res);
    for (i = 0; i < nitems(bcm_bsc_pins); i++) {
        if (bcm_bsc_pins[i].start == (start & BCM_BSC_BASE_MASK))
            break;
    }
    if (i == nitems(bcm_bsc_pins)) {
        device_printf(dev, "only bsc0 and bsc1 are supported\n");
        bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
        return (ENXIO);
    }

    /*
     * Configure the GPIO pins to ALT0 function to enable BSC control
     * over the pins.
     */
    gpio = devclass_get_device(devclass_find("gpio"), 0);
    if (!gpio) {
        device_printf(dev, "cannot find gpio0\n");
        bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
        return (ENXIO);
    }
    bcm_gpio_set_alternate(gpio, bcm_bsc_pins[i].sda, BCM_GPIO_ALT0);
    bcm_gpio_set_alternate(gpio, bcm_bsc_pins[i].scl, BCM_GPIO_ALT0);

    rid = 0;
    sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
                                            RF_ACTIVE | RF_SHAREABLE);
    if (!sc->sc_irq_res) {
        bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
        device_printf(dev, "cannot allocate interrupt\n");
        return (ENXIO);
    }

    /* Hook up our interrupt handler. */
    if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
                       NULL, bcm_bsc_intr, sc, &sc->sc_intrhand)) {
        bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
        bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
        device_printf(dev, "cannot setup the interrupt handler\n");
        return (ENXIO);
    }

    mtx_init(&sc->sc_mtx, "bcm_bsc", NULL, MTX_DEF);

    bcm_bsc_sysctl_init(sc);

    /* Enable the BSC controller.  Flush the FIFO. */
    BCM_BSC_LOCK(sc);
    bcm_bsc_reset(sc);
    BCM_BSC_UNLOCK(sc);

    sc->sc_iicbus = device_add_child(dev, "iicbus", -1);
    if (sc->sc_iicbus == NULL) {
        bcm_bsc_detach(dev);
        return (ENXIO);
    }

    return (bus_generic_attach(dev));
}
示例#22
0
文件: dma_sbus.c 项目: coyizumi/cs111
static int
dma_attach(device_t dev)
{
	struct dma_softc *dsc;
	struct lsi64854_softc *lsc;
	struct dma_devinfo *ddi;
	device_t cdev;
	const char *name;
	char *cabletype;
	uint32_t csr;
	phandle_t child, node;
	int error, i;

	dsc = device_get_softc(dev);
	lsc = &dsc->sc_lsi64854;

	name = ofw_bus_get_name(dev);
	node = ofw_bus_get_node(dev);
	dsc->sc_ign = sbus_get_ign(dev);
	dsc->sc_slot = sbus_get_slot(dev);

	i = 0;
	lsc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &i,
	    RF_ACTIVE);
	if (lsc->sc_res == NULL) {
		device_printf(dev, "cannot allocate resources\n");
		return (ENXIO);
	}

	if (strcmp(name, "espdma") == 0 || strcmp(name, "dma") == 0)
		lsc->sc_channel = L64854_CHANNEL_SCSI;
	else if (strcmp(name, "ledma") == 0) {
		/*
		 * Check to see which cable type is currently active and
		 * set the appropriate bit in the ledma csr so that it
		 * gets used. If we didn't netboot, the PROM won't have
		 * the "cable-selection" property; default to TP and then
		 * the user can change it via a "media" option to ifconfig.
		 */
		csr = L64854_GCSR(lsc);
		if ((OF_getprop_alloc(node, "cable-selection", 1,
		    (void **)&cabletype)) == -1) {
			/* assume TP if nothing there */
			csr |= E_TP_AUI;
		} else {
			if (strcmp(cabletype, "aui") == 0)
				csr &= ~E_TP_AUI;
			else
				csr |= E_TP_AUI;
			free(cabletype, M_OFWPROP);
		}
		L64854_SCSR(lsc, csr);
		DELAY(20000);	/* manual says we need a 20ms delay */
		lsc->sc_channel = L64854_CHANNEL_ENET;
	} else {
		device_printf(dev, "unsupported DMA channel\n");
		error = ENXIO;
		goto fail_lres;
	}

	error = bus_dma_tag_create(
	    bus_get_dma_tag(dev),	/* parent */
	    1, 0,			/* alignment, boundary */
	    BUS_SPACE_MAXADDR,		/* lowaddr */
	    BUS_SPACE_MAXADDR,		/* highaddr */
	    NULL, NULL,			/* filter, filterarg */
	    BUS_SPACE_MAXSIZE,		/* maxsize */
	    BUS_SPACE_UNRESTRICTED,	/* nsegments */
	    BUS_SPACE_MAXSIZE,		/* maxsegsize */
	    0,				/* flags */
	    NULL, NULL,			/* no locking */
	    &lsc->sc_parent_dmat);
	if (error != 0) {
		device_printf(dev, "cannot allocate parent DMA tag\n");
		goto fail_lres;
	}

	i = sbus_get_burstsz(dev);
	lsc->sc_burst = (i & SBUS_BURST_32) ? 32 :
	    (i & SBUS_BURST_16) ? 16 : 0;
	lsc->sc_dev = dev;

	/* Attach children. */
	i = 0;
	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
		if ((ddi = dma_setup_dinfo(dev, dsc, child)) == NULL)
			continue;
		if (i != 0) {
			device_printf(dev,
			    "<%s>: only one child per DMA channel supported\n",
			    ddi->ddi_obdinfo.obd_name);
			dma_destroy_dinfo(ddi);
			continue;
		}
		if ((cdev = device_add_child(dev, NULL, -1)) == NULL) {
			device_printf(dev, "<%s>: device_add_child failed\n",
			    ddi->ddi_obdinfo.obd_name);
			dma_destroy_dinfo(ddi);
			continue;
		}
		device_set_ivars(cdev, ddi);
		i++;
	}
	return (bus_generic_attach(dev));

 fail_lres:
	bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lsc->sc_res),
	    lsc->sc_res);
	return (error);
}
示例#23
0
int
iq80321_attach(device_t dev)
{
	struct i80321_softc *sc = device_get_softc(dev);
	int b0u, b0l, b1u, b1l;
	vm_paddr_t memstart = 0;
	vm_size_t memsize = 0;
	int busno;

	/*
	 * Fill in the space tag for the i80321's own devices,
	 * and hand-craft the space handle for it (the device
	 * was mapped during early bootstrap).
	 */
	i80321_bs_init(&i80321_bs_tag, sc);
	sc->sc_st = &i80321_bs_tag;
	sc->sc_sh = IQ80321_80321_VBASE;
	sc->dev = dev;
	sc->sc_is_host = 1;

	/*
	 * Slice off a subregion for the Memory Controller -- we need it
	 * here in order read the memory size.
	 */
	if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_MCU_BASE,
	    VERDE_MCU_SIZE, &sc->sc_mcu_sh))
		panic("%s: unable to subregion MCU registers",
		    device_get_name(dev));

	if (bus_space_subregion(sc->sc_st, sc->sc_sh, VERDE_ATU_BASE,
	    VERDE_ATU_SIZE, &sc->sc_atu_sh))
		panic("%s: unable to subregion ATU registers",
		    device_get_name(dev));

	/*
	 * We have mapped the PCI I/O windows in the early
	 * bootstrap phase.
	 */
	sc->sc_iow_vaddr = IQ80321_IOW_VBASE;

	/*
	 * Check the configuration of the ATU to see if another BIOS
	 * has configured us.  If a PC BIOS didn't configure us, then:
	 * 	IQ80321: BAR0 00000000.0000000c BAR1 is 00000000.8000000c.
	 * 	IQ31244: BAR0 00000000.00000004 BAR1 is 00000000.0000000c.
	 * If a BIOS has configured us, at least one of those should be
	 * different.  This is pretty fragile, but it's not clear what
	 * would work better.
	 */
	b0l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x0);
	b0u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x4);
	b1l = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0x8);
	b1u = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, PCIR_BARS+0xc);

#ifdef VERBOSE_INIT_ARM	
	printf("i80321: BAR0 = %08x.%08x BAR1 = %08x.%08x\n",
		   b0l,b0u, b1l, b1u );
#endif

#define PCI_MAPREG_MEM_ADDR_MASK	0xfffffff0
	b0l &= PCI_MAPREG_MEM_ADDR_MASK;
	b0u &= PCI_MAPREG_MEM_ADDR_MASK;
	b1l &= PCI_MAPREG_MEM_ADDR_MASK;
	b1u &= PCI_MAPREG_MEM_ADDR_MASK;

#ifdef VERBOSE_INIT_ARM	
	printf("i80219: BAR0 = %08x.%08x BAR1 = %08x.%08x\n",
		   b0l,b0u, b1l, b1u );
#endif

	if ((b0u != b1u) || (b0l != 0) || ((b1l & ~0x80000000U) != 0))
		sc->sc_is_host = 0;
	else
		sc->sc_is_host = 1;

	/* FIXME: i force it's */	

#ifdef CPU_XSCALE_80219
	sc->sc_is_host = 1;
#endif
	
	i80321_sdram_bounds(sc->sc_st, sc->sc_mcu_sh, &memstart, &memsize);
	/*
	 * We set up the Inbound Windows as follows:
	 *
	 *	0	Access to i80321 PMMRs
	 *
	 *	1	Reserve space for private devices
	 *
	 *	2	RAM access
	 *
	 *	3	Unused.
	 *
	 * This chunk needs to be customized for each IOP321 application.
	 */
#if 0
	sc->sc_iwin[0].iwin_base_lo = VERDE_PMMR_BASE;
	sc->sc_iwin[0].iwin_base_hi = 0;
	sc->sc_iwin[0].iwin_xlate = VERDE_PMMR_BASE;
	sc->sc_iwin[0].iwin_size = VERDE_PMMR_SIZE;
#endif
	if (sc->sc_is_host) {
		
		/* Map PCI:Local 1:1. */
		sc->sc_iwin[1].iwin_base_lo = VERDE_OUT_XLATE_MEM_WIN0_BASE |
		    PCI_MAPREG_MEM_PREFETCHABLE_MASK |
		    PCI_MAPREG_MEM_TYPE_64BIT;
		sc->sc_iwin[1].iwin_base_hi = 0;
	} else {
		
		sc->sc_iwin[1].iwin_base_lo = 0;
		sc->sc_iwin[1].iwin_base_hi = 0;
	}
	sc->sc_iwin[1].iwin_xlate = VERDE_OUT_XLATE_MEM_WIN0_BASE;
	sc->sc_iwin[1].iwin_size = VERDE_OUT_XLATE_MEM_WIN_SIZE;
	
	if (sc->sc_is_host) {
		sc->sc_iwin[2].iwin_base_lo = memstart |
		    PCI_MAPREG_MEM_PREFETCHABLE_MASK |
		    PCI_MAPREG_MEM_TYPE_64BIT;
		sc->sc_iwin[2].iwin_base_hi = 0;
	} else {
		sc->sc_iwin[2].iwin_base_lo = 0;
		sc->sc_iwin[2].iwin_base_hi = 0;
	}
	sc->sc_iwin[2].iwin_xlate = memstart;
	sc->sc_iwin[2].iwin_size = memsize;

	if (sc->sc_is_host) {
		sc->sc_iwin[3].iwin_base_lo = 0 |
		    PCI_MAPREG_MEM_PREFETCHABLE_MASK |
		    PCI_MAPREG_MEM_TYPE_64BIT;
	} else {
		sc->sc_iwin[3].iwin_base_lo = 0;
	}
	sc->sc_iwin[3].iwin_base_hi = 0;
	sc->sc_iwin[3].iwin_xlate = 0;
	sc->sc_iwin[3].iwin_size = 0;
	
#ifdef 	VERBOSE_INIT_ARM
	printf("i80321: Reserve space for private devices (Inbound Window 1) \n hi:0x%08x lo:0x%08x xlate:0x%08x size:0x%08x\n",
		   sc->sc_iwin[1].iwin_base_hi,
		   sc->sc_iwin[1].iwin_base_lo,
		   sc->sc_iwin[1].iwin_xlate,
		   sc->sc_iwin[1].iwin_size
		);
	printf("i80321: RAM access (Inbound Window 2) \n hi:0x%08x lo:0x%08x xlate:0x%08x size:0x%08x\n",
		   sc->sc_iwin[2].iwin_base_hi,
		   sc->sc_iwin[2].iwin_base_lo,
		   sc->sc_iwin[2].iwin_xlate,
		   sc->sc_iwin[2].iwin_size
		);
#endif

	/*
	 * We set up the Outbound Windows as follows:
	 *
	 *	0	Access to private PCI space.
	 *
	 *	1	Unused.
	 */
#define PCI_MAPREG_MEM_ADDR(x) ((x) & 0xfffffff0)
	sc->sc_owin[0].owin_xlate_lo =
    	    PCI_MAPREG_MEM_ADDR(sc->sc_iwin[1].iwin_base_lo);
	sc->sc_owin[0].owin_xlate_hi = sc->sc_iwin[1].iwin_base_hi;
	/*
	 * Set the Secondary Outbound I/O window to map
	 * to PCI address 0 for all 64K of the I/O space.
	 */
	sc->sc_ioout_xlate = 0;
	i80321_attach(sc);
	i80321_dr.dr_sysbase = sc->sc_iwin[2].iwin_xlate;
	i80321_dr.dr_busbase = PCI_MAPREG_MEM_ADDR(sc->sc_iwin[2].iwin_base_lo);
	i80321_dr.dr_len = sc->sc_iwin[2].iwin_size;
	dma_range_init = 1;
	busno = bus_space_read_4(sc->sc_st, sc->sc_atu_sh, ATU_PCIXSR);
	busno = PCIXSR_BUSNO(busno);
	if (busno == 0xff)
		busno = 0;
	sc->sc_irq_rman.rm_type = RMAN_ARRAY;
	sc->sc_irq_rman.rm_descr = "i80321 IRQs";
	if (rman_init(&sc->sc_irq_rman) != 0 ||
	    rman_manage_region(&sc->sc_irq_rman, 0, 25) != 0)
		panic("i80321_attach: failed to set up IRQ rman");

	device_add_child(dev, "obio", 0);
	device_add_child(dev, "itimer", 0);
	device_add_child(dev, "iopwdog", 0);
#ifndef 	CPU_XSCALE_80219
	device_add_child(dev, "iqseg", 0);
#endif	
	device_add_child(dev, "pcib", busno);
	device_add_child(dev, "i80321_dma", 0);
	device_add_child(dev, "i80321_dma", 1);
#ifndef CPU_XSCALE_80219	
	device_add_child(dev, "i80321_aau", 0);
#endif
	bus_generic_probe(dev);
	bus_generic_attach(dev);

	return (0);
}
示例#24
0
static int
octe_attach(device_t dev)
{
    struct ifnet *ifp;
    cvm_oct_private_t *priv;
    device_t child;
    unsigned qos;
    int error;

    priv = device_get_softc(dev);
    ifp = priv->ifp;

    if_initname(ifp, device_get_name(dev), device_get_unit(dev));

    if (priv->phy_id != -1) {
        if (priv->phy_device == NULL) {
            error = mii_attach(dev, &priv->miibus, ifp,
                               octe_mii_medchange, octe_mii_medstat,
                               BMSR_DEFCAPMASK, priv->phy_id, MII_OFFSET_ANY, 0);
            if (error != 0)
                device_printf(dev, "attaching PHYs failed\n");
        } else {
            child = device_add_child(dev, priv->phy_device, -1);
            if (child == NULL)
                device_printf(dev, "missing phy %u device %s\n", priv->phy_id, priv->phy_device);
        }
    }

    if (priv->miibus == NULL) {
        ifmedia_init(&priv->media, 0, octe_medchange, octe_medstat);

        ifmedia_add(&priv->media, IFM_ETHER | IFM_AUTO, 0, NULL);
        ifmedia_set(&priv->media, IFM_ETHER | IFM_AUTO);
    }

    /*
     * XXX
     * We don't support programming the multicast filter right now, although it
     * ought to be easy enough.  (Presumably it's just a matter of putting
     * multicast addresses in the CAM?)
     */
    ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | IFF_ALLMULTI;
    ifp->if_init = octe_init;
    ifp->if_ioctl = octe_ioctl;

    priv->if_flags = ifp->if_flags;

    mtx_init(&priv->tx_mtx, ifp->if_xname, "octe tx send queue", MTX_DEF);

    for (qos = 0; qos < 16; qos++) {
        mtx_init(&priv->tx_free_queue[qos].ifq_mtx, ifp->if_xname, "octe tx free queue", MTX_DEF);
        IFQ_SET_MAXLEN(&priv->tx_free_queue[qos], MAX_OUT_QUEUE_DEPTH);
    }

    ether_ifattach(ifp, priv->mac);

    ifp->if_transmit = octe_transmit;

    ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
    ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_HWCSUM;
    ifp->if_capenable = ifp->if_capabilities;
    ifp->if_hwassist = CSUM_TCP | CSUM_UDP;

    OCTE_TX_LOCK(priv);
    IFQ_SET_MAXLEN(&ifp->if_snd, MAX_OUT_QUEUE_DEPTH);
    ifp->if_snd.ifq_drv_maxlen = MAX_OUT_QUEUE_DEPTH;
    IFQ_SET_READY(&ifp->if_snd);
    OCTE_TX_UNLOCK(priv);

    return (bus_generic_attach(dev));
}
示例#25
0
文件: fhc.c 项目: MarginC/kame
int
fhc_attach(device_t dev)
{
	struct fhc_devinfo *fdi;
	struct sbus_regs *reg;
	struct fhc_softc *sc;
	phandle_t child;
	phandle_t node;
	bus_addr_t size;
	bus_addr_t off;
	device_t cdev;
	uint32_t ctrl;
	char *name;
	int nreg;
	int i;

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

	for (i = FHC_FANFAIL; i <= FHC_TOD; i++) {
		bus_space_write_4(sc->sc_bt[i], sc->sc_bh[i], FHC_ICLR, 0x0);
		bus_space_read_4(sc->sc_bt[i], sc->sc_bh[i], FHC_ICLR);
	}

	sc->sc_ign = sc->sc_board << 1;
	bus_space_write_4(sc->sc_bt[FHC_IGN], sc->sc_bh[FHC_IGN], 0x0,
	    sc->sc_ign);
	sc->sc_ign = bus_space_read_4(sc->sc_bt[FHC_IGN],
	    sc->sc_bh[FHC_IGN], 0x0);

	ctrl = bus_space_read_4(sc->sc_bt[FHC_INTERNAL],
	    sc->sc_bh[FHC_INTERNAL], FHC_CTRL);
	if ((sc->sc_flags & FHC_CENTRAL) == 0)
		ctrl |= FHC_CTRL_IXIST;
	ctrl &= ~(FHC_CTRL_AOFF | FHC_CTRL_BOFF | FHC_CTRL_SLINE);
	bus_space_write_4(sc->sc_bt[FHC_INTERNAL], sc->sc_bh[FHC_INTERNAL],
	    FHC_CTRL, ctrl);
	ctrl = bus_space_read_4(sc->sc_bt[FHC_INTERNAL],
	    sc->sc_bh[FHC_INTERNAL], FHC_CTRL);

	sc->sc_nrange = OF_getprop_alloc(node, "ranges",
	    sizeof(*sc->sc_ranges), (void **)&sc->sc_ranges);
	if (sc->sc_nrange == -1) {
		device_printf(dev, "can't get ranges");
		return (ENXIO);
	}

	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
		if ((OF_getprop_alloc(child, "name", 1, (void **)&name)) == -1)
			continue;
		cdev = device_add_child(dev, NULL, -1);
		if (cdev != NULL) {
			fdi = malloc(sizeof(*fdi), M_DEVBUF,
			    M_WAITOK | M_ZERO);
			fdi->fdi_name = name;
			fdi->fdi_node = child;
			OF_getprop_alloc(child, "device_type", 1,
			    (void **)&fdi->fdi_type);
			resource_list_init(&fdi->fdi_rl);
			nreg = OF_getprop_alloc(child, "reg", sizeof(*reg),
			    (void **)&reg);
			if (nreg != -1) {
				for (i = 0; i < nreg; i++) {
					off = reg[i].sbr_offset;
					size = reg[i].sbr_size;
					resource_list_add(&fdi->fdi_rl,
					    SYS_RES_MEMORY, i, off, off + size,
					    size);
				}
				free(reg, M_OFWPROP);
			}
			device_set_ivars(cdev, fdi);
		} else
			free(name, M_OFWPROP);
	}

	return (bus_generic_attach(dev));
}
示例#26
0
文件: chipc.c 项目: wulf7/freebsd
static int
chipc_attach(device_t dev)
{
	struct chipc_softc		*sc;
	int				 error;

	sc = device_get_softc(dev);
	sc->dev = dev;
	sc->quirks = bhnd_device_quirks(dev, chipc_devices,
	    sizeof(chipc_devices[0]));
	sc->sprom_refcnt = 0;

	CHIPC_LOCK_INIT(sc);
	STAILQ_INIT(&sc->mem_regions);

	/* Set up resource management */
	if ((error = chipc_init_rman(sc))) {
		device_printf(sc->dev,
		    "failed to initialize chipc resource state: %d\n", error);
		goto failed;
	}

	/* Allocate the region containing the chipc register block */
	if ((sc->core_region = chipc_find_region_by_rid(sc, 0)) == NULL) {
		error = ENXIO;
		goto failed;
	}

	error = chipc_retain_region(sc, sc->core_region,
	    RF_ALLOCATED|RF_ACTIVE);
	if (error) {
		sc->core_region = NULL;
		goto failed;
	}

	/* Save a direct reference to our chipc registers */
	sc->core = sc->core_region->cr_res;

	/* Fetch and parse capability register(s) */
	if ((error = chipc_read_caps(sc, &sc->caps)))
		goto failed;

	if (bootverbose)
		chipc_print_caps(sc->dev, &sc->caps);

	/* Attach all supported child devices */
	if ((error = chipc_add_children(sc)))
		goto failed;

	if ((error = bus_generic_attach(dev)))
		goto failed;

	return (0);
	
failed:
	device_delete_children(sc->dev);

	if (sc->core_region != NULL) {
		chipc_release_region(sc, sc->core_region,
		    RF_ALLOCATED|RF_ACTIVE);
	}

	chipc_free_rman(sc);
	CHIPC_LOCK_DESTROY(sc);
	return (error);
}
示例#27
0
static int
viapm_pro_attach(device_t dev)
{
	struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
	u_int32_t l;

	mtx_init(&viapm->lock, device_get_nameunit(dev), "viapm", MTX_DEF);
	if (!(viapm->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
		&viapm->iorid, RF_ACTIVE))) {
		device_printf(dev, "could not allocate bus space\n");
		goto error;
	}

#ifdef notyet
	/* force irq 9 */
	l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1);
	pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 0x80, 1);

	viapm->irqrid = 0;
	if (!(viapm->irqres = bus_alloc_resource(dev, SYS_RES_IRQ,
				&viapm->irqrid, 9, 9, 1,
				RF_SHAREABLE | RF_ACTIVE))) {
		device_printf(dev, "could not allocate irq\n");
		goto error;
	}

	if (bus_setup_intr(dev, viapm->irqres, INTR_TYPE_MISC | INTR_MPSAFE,
			(driver_intr_t *) viasmb_intr, viapm, &viapm->irqih)) {
		device_printf(dev, "could not setup irq\n");
		goto error;
	}
#endif

	if (bootverbose) {
		l = pci_read_config(dev, VIAPM_PRO_REVID, 1);
		device_printf(dev, "SMBus revision code 0x%x\n", l);
	}

	viapm->smbus = device_add_child(dev, "smbus", -1);

	/* probe and attach the smbus */
	bus_generic_attach(dev);

	/* disable slave function */
	VIAPM_OUTB(SMBSCTRL, VIAPM_INB(SMBSCTRL) & ~SMBSCTRL_ENABLE);

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

#ifdef notyet
	/* enable interrupts */
	VIAPM_OUTB(SMBHCTRL, VIAPM_INB(SMBHCTRL) | SMBHCTRL_ENABLE);
#endif

#ifdef DEV_ISA
	/* If this device is a PCI-ISA bridge, then attach an ISA bus. */
	if ((pci_get_class(dev) == PCIC_BRIDGE) &&
	    (pci_get_subclass(dev) == PCIS_BRIDGE_ISA))
		isab_attach(dev);
#endif
	return 0;

error:
	if (viapm->iores)
		bus_release_resource(dev, SYS_RES_IOPORT, viapm->iorid, viapm->iores);
#ifdef notyet
	if (viapm->irqres)
		bus_release_resource(dev, SYS_RES_IRQ, viapm->irqrid, viapm->irqres);
#endif
	mtx_destroy(&viapm->lock);

	return ENXIO;
}
示例#28
0
文件: ig4_iic.c 项目: terimai/ichiic
/*
 *				SMBUS API FUNCTIONS
 *
 * Called from ig4iic_pci_attach/detach()
 */
int
ig4iic_attach(ig4iic_softc_t *sc)
{
	int error;
	uint32_t v;


	v = reg_read(sc, IG4_REG_COMP_TYPE);
	printf("type %08x\n", v);
	v = reg_read(sc, IG4_REG_COMP_PARAM1);
	printf("params %08x\n", v);
	v = reg_read(sc, IG4_REG_COMP_VER);
	printf("version %08x\n", v);
	if (v != IG4_COMP_VER) {
		error = ENXIO;
		goto done;
	}
#if 1
	v = reg_read(sc, IG4_REG_SS_SCL_HCNT);
	printf("SS_SCL_HCNT %08x\n", v);
	v = reg_read(sc, IG4_REG_SS_SCL_LCNT);
	printf("SS_SCL_LCNT %08x\n", v);
	v = reg_read(sc, IG4_REG_FS_SCL_HCNT);
	printf("FS_SCL_HCNT %08x\n", v);
	v = reg_read(sc, IG4_REG_FS_SCL_LCNT);
	printf("FS_SCL_LCNT %08x\n", v);
	v = reg_read(sc, IG4_REG_SDA_HOLD);
	printf("HOLD        %08x\n", v);

	v = reg_read(sc, IG4_REG_SS_SCL_HCNT);
	reg_write(sc, IG4_REG_FS_SCL_HCNT, v);
	v = reg_read(sc, IG4_REG_SS_SCL_LCNT);
	reg_write(sc, IG4_REG_FS_SCL_LCNT, v);
#endif
	/*
	 * Program based on a 25000 Hz clock.  This is a bit of a
	 * hack (obviously).  The defaults are 400 and 470 for standard
	 * and 60 and 130 for fast.  The defaults for standard fail
	 * utterly (presumably cause an abort) because the clock time
	 * is ~18.8ms by default.  This brings it down to ~4ms (for now).
	 */
	reg_write(sc, IG4_REG_SS_SCL_HCNT, 100);
	reg_write(sc, IG4_REG_SS_SCL_LCNT, 125);
	reg_write(sc, IG4_REG_FS_SCL_HCNT, 100);
	reg_write(sc, IG4_REG_FS_SCL_LCNT, 125);

	/*
	 * Use a threshold of 1 so we get interrupted on each character,
	 * allowing us to use lksleep() in our poll code.  Not perfect
	 * but this is better than using DELAY() for receiving data.
	 */
	reg_write(sc, IG4_REG_RX_TL, 1);

	reg_write(sc, IG4_REG_CTL,
		  IG4_CTL_MASTER |
		  IG4_CTL_SLAVE_DISABLE |
		  IG4_CTL_RESTARTEN |
		  IG4_CTL_SPEED_STD);

	mtx_lock(&sc->mtx);
	sc->smb = device_add_child(sc->dev, "smbus", -1);
	if (sc->smb == NULL) {
		device_printf(sc->dev, "smbus driver not found\n");
		error = ENXIO;
		goto done;
	}

#if 0
	/*
	 * Don't do this, it blows up the PCI config
	 */
	reg_write(sc, IG4_REG_RESETS, IG4_RESETS_ASSERT);
	reg_write(sc, IG4_REG_RESETS, IG4_RESETS_DEASSERT);
#endif

	/*
	 * Interrupt on STOP detect or receive character ready
	 */
	reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET |
					 IG4_INTR_RX_FULL);
	if (set_controller(sc, 0))
		device_printf(sc->dev, "controller error during attach-1\n");
	if (set_controller(sc, IG4_I2C_ENABLE))
		device_printf(sc->dev, "controller error during attach-2\n");
	mtx_unlock(&sc->mtx);
	error = bus_setup_intr(sc->dev, sc->intr_res,
			       INTR_TYPE_MISC | INTR_MPSAFE, NULL,
			       ig4iic_intr, sc, &sc->intr_handle);
	if (error) {
		device_printf(sc->dev,
			      "Unable to setup irq: error %d\n", error);
		goto done;
	}

	/* Attach us to the smbus */
	error = bus_generic_attach(sc->dev);
	mtx_lock(&sc->mtx);
	if (error) {
		device_printf(sc->dev,
			      "failed to attach child: error %d\n", error);
		goto done;
	}
	sc->generic_attached = 1;

done:
	mtx_unlock(&sc->mtx);
	return error;
}
示例#29
0
文件: smu.c 项目: 2asoft/freebsd
static int
smu_attach(device_t dev)
{
	struct smu_softc *sc;
	phandle_t	node, child;
	uint8_t		data[12];

	sc = device_get_softc(dev);

	mtx_init(&sc->sc_mtx, "smu", NULL, MTX_DEF);
	sc->sc_cur_cmd = NULL;
	sc->sc_doorbellirqid = -1;

	sc->sc_u3 = 0;
	if (OF_finddevice("/u3") != -1)
		sc->sc_u3 = 1;

	/*
	 * Map the mailbox area. This should be determined from firmware,
	 * but I have not found a simple way to do that.
	 */
	bus_dma_tag_create(NULL, 16, 0, BUS_SPACE_MAXADDR_32BIT,
	    BUS_SPACE_MAXADDR, NULL, NULL, PAGE_SIZE, 1, PAGE_SIZE, 0, NULL,
	    NULL, &(sc->sc_dmatag));
	sc->sc_bt = &bs_le_tag;
	bus_space_map(sc->sc_bt, SMU_MAILBOX, 4, 0, &sc->sc_mailbox);

	/*
	 * Allocate the command buffer. This can be anywhere in the low 4 GB
	 * of memory.
	 */
	bus_dmamem_alloc(sc->sc_dmatag, (void **)&sc->sc_cmd, BUS_DMA_WAITOK | 
	    BUS_DMA_ZERO, &sc->sc_cmd_dmamap);
	bus_dmamap_load(sc->sc_dmatag, sc->sc_cmd_dmamap,
	    sc->sc_cmd, PAGE_SIZE, smu_phys_callback, sc, 0);
	STAILQ_INIT(&sc->sc_cmdq);

	/*
	 * Set up handlers to change CPU voltage when CPU frequency is changed.
	 */
	EVENTHANDLER_REGISTER(cpufreq_pre_change, smu_cpufreq_pre_change, dev,
	    EVENTHANDLER_PRI_ANY);
	EVENTHANDLER_REGISTER(cpufreq_post_change, smu_cpufreq_post_change, dev,
	    EVENTHANDLER_PRI_ANY);

	node = ofw_bus_get_node(dev);

	/* Some SMUs have RPM and PWM controlled fans which do not sit
	 * under the same node. So we have to attach them separately.
	 */
	smu_attach_fans(dev, node);

	/*
	 * Now detect and attach the other child devices.
	 */
	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
		char name[32];
		memset(name, 0, sizeof(name));
		OF_getprop(child, "name", name, sizeof(name));

		if (strncmp(name, "sensors", 8) == 0)
			smu_attach_sensors(dev, child);

		if (strncmp(name, "smu-i2c-control", 15) == 0)
			smu_attach_i2c(dev, child);
	}

	/* Some SMUs have the I2C children directly under the bus. */
	smu_attach_i2c(dev, node);

	/*
	 * Collect calibration constants.
	 */
	smu_get_datablock(dev, SMU_CPUTEMP_CAL, data, sizeof(data));
	sc->sc_cpu_diode_scale = (data[4] << 8) + data[5];
	sc->sc_cpu_diode_offset = (data[6] << 8) + data[7];

	smu_get_datablock(dev, SMU_CPUVOLT_CAL, data, sizeof(data));
	sc->sc_cpu_volt_scale = (data[4] << 8) + data[5];
	sc->sc_cpu_volt_offset = (data[6] << 8) + data[7];
	sc->sc_cpu_curr_scale = (data[8] << 8) + data[9];
	sc->sc_cpu_curr_offset = (data[10] << 8) + data[11];

	smu_get_datablock(dev, SMU_SLOTPW_CAL, data, sizeof(data));
	sc->sc_slots_pow_scale = (data[4] << 8) + data[5];
	sc->sc_slots_pow_offset = (data[6] << 8) + data[7];

	/*
	 * Set up LED interface
	 */
	sc->sc_leddev = led_create(smu_set_sleepled, dev, "sleepled");

	/*
	 * Reset on power loss behavior
	 */

	SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
            SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO,
	    "server_mode", CTLTYPE_INT | CTLFLAG_RW, dev, 0,
	    smu_server_mode, "I", "Enable reboot after power failure");

	/*
	 * Set up doorbell interrupt.
	 */
	sc->sc_doorbellirqid = 0;
	sc->sc_doorbellirq = bus_alloc_resource_any(smu_doorbell, SYS_RES_IRQ,
	    &sc->sc_doorbellirqid, RF_ACTIVE);
	bus_setup_intr(smu_doorbell, sc->sc_doorbellirq,
	    INTR_TYPE_MISC | INTR_MPSAFE, NULL, smu_doorbell_intr, dev,
	    &sc->sc_doorbellirqcookie);
	powerpc_config_intr(rman_get_start(sc->sc_doorbellirq),
	    INTR_TRIGGER_EDGE, INTR_POLARITY_LOW);

	/*
	 * Connect RTC interface.
	 */
	clock_register(dev, 1000);

	/*
	 * Learn about shutdown events
	 */
	EVENTHANDLER_REGISTER(shutdown_final, smu_shutdown, dev,
	    SHUTDOWN_PRI_LAST);

	return (bus_generic_attach(dev));
}
示例#30
0
static int
bhndb_pci_attach(device_t dev)
{
	struct bhndb_pci_softc	*sc;
	struct bhnd_chipid	 cid;
	struct bhnd_core_info	*cores, hostb_core;
	bhnd_erom_class_t	*erom_class;
	struct bhndb_pci_probe	*probe;
	u_int			 ncores;
	int			 irq_rid;
	int			 error;

	sc = device_get_softc(dev);
	sc->dev = dev;
	sc->parent = device_get_parent(dev);
	sc->pci_devclass = bhndb_expected_pci_devclass(dev);
	sc->pci_quirks = 0;
	sc->set_regwin = NULL;

	BHNDB_PCI_LOCK_INIT(sc);

	probe = NULL;
	cores = NULL;

	/* Enable PCI bus mastering */
	pci_enable_busmaster(sc->parent);

	/* Enable clocks (if required by this hardware) */
	if ((error = bhndb_enable_pci_clocks(sc->dev)))
		goto cleanup;

	/* Identify the chip and enumerate the bridged cores */
	error = bhndb_pci_probe_alloc(&probe, dev, sc->pci_devclass);
	if (error)
		goto cleanup;

	sc->pci_quirks = bhndb_pci_get_core_quirks(&probe->cid,
	    &probe->hostb_core);

	/* Select the appropriate register window handler */
	if (probe->cid.chip_type == BHND_CHIPTYPE_SIBA) {
		sc->set_regwin = bhndb_pci_compat_setregwin;
	} else {
		sc->set_regwin = bhndb_pci_fast_setregwin;
	}

	/*
	 * Fix up our PCI base address in the SPROM shadow, if necessary.
	 * 
	 * This must be done prior to accessing any static register windows
	 * that map the PCI core.
	 */
	if ((error = bhndb_pci_srsh_pi_war(sc, probe)))
		goto cleanup;

	/* Set up PCI interrupt handling */
	if (bhndb_pci_alloc_msi(sc, &sc->msi_count) == 0) {
		/* MSI uses resource IDs starting at 1 */
		irq_rid = 1;

		device_printf(dev, "Using MSI interrupts on %s\n",
		    device_get_nameunit(sc->parent));
	} else {
		sc->msi_count = 0;
		irq_rid = 0;

		device_printf(dev, "Using INTx interrupts on %s\n",
		    device_get_nameunit(sc->parent));
	}

	sc->isrc = bhndb_alloc_intr_isrc(sc->parent, irq_rid, 0, RM_MAX_END, 1,
	    RF_SHAREABLE | RF_ACTIVE);
	if (sc->isrc == NULL) {
		device_printf(sc->dev, "failed to allocate interrupt "
		    "resource\n");
		error = ENXIO;
		goto cleanup;
	}

	/*
	 * Copy out the probe results and then free our probe state, releasing
	 * its exclusive ownership of host bridge resources.
	 * 
	 * This must be done prior to full configuration of the bridge via
	 * bhndb_attach().
	 */
	cid = probe->cid;
	erom_class = probe->erom_class;
	hostb_core = probe->hostb_core;

	error = bhndb_pci_probe_copy_core_table(probe, &cores, &ncores);
	if (error) {
		cores = NULL;
		goto cleanup;
	}

	bhndb_pci_probe_free(probe);
	probe = NULL;

	/* Perform bridge attach */
	error = bhndb_attach(dev, &cid, cores, ncores, &hostb_core, erom_class);
	if (error)
		goto cleanup;

	/* Add any additional child devices */
	if ((error = bhndb_pci_add_children(sc)))
		goto cleanup;

	/* Probe and attach our children */
	if ((error = bus_generic_attach(dev)))
		goto cleanup;

	bhndb_pci_probe_free_core_table(cores);

	return (0);

cleanup:
	device_delete_children(dev);

	if (sc->isrc != NULL)
		bhndb_free_intr_isrc(sc->isrc);

	if (sc->msi_count > 0)
		pci_release_msi(sc->parent);

	if (cores != NULL)
		bhndb_pci_probe_free_core_table(cores);

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

	bhndb_disable_pci_clocks(sc->dev);

	pci_disable_busmaster(sc->parent);

	BHNDB_PCI_LOCK_DESTROY(sc);

	return (error);
}