Ejemplo n.º 1
0
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_32BIT,	/* maxsize */
	    0,				/* nsegments */
	    BUS_SPACE_MAXSIZE_32BIT,	/* 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);
}
Ejemplo n.º 2
0
static int
lpc_fb_attach(device_t dev)
{
	struct lpc_fb_softc *sc = device_get_softc(dev);
	struct lpc_fb_dmamap_arg ctx;
	phandle_t node;
	int mode, rid, err = 0;

	sc->lf_dev = dev;
	mtx_init(&sc->lf_mtx, "lpcfb", "fb", MTX_DEF);

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

	sc->lf_bst = rman_get_bustag(sc->lf_mem_res);
	sc->lf_bsh = rman_get_bushandle(sc->lf_mem_res);

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

	if (bus_setup_intr(dev, sc->lf_irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
	    NULL, lpc_fb_intr, sc, &sc->lf_intrhand))
	{
		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->lf_mem_res);
		bus_release_resource(dev, SYS_RES_IRQ, 1, sc->lf_irq_res);
		device_printf(dev, "cannot setup interrupt handler\n");
		return (ENXIO);
	}

	node = ofw_bus_get_node(dev);

	err = lpc_fb_read_lcd_config(node, &sc->lf_lcd_config);
	if (err) {
		device_printf(dev, "cannot read LCD configuration\n");
		goto fail;
	}

	sc->lf_buffer_size = sc->lf_lcd_config.lc_xres * 
	    sc->lf_lcd_config.lc_yres *
	    (sc->lf_lcd_config.lc_bpp == 24 ? 3 : 2);

	device_printf(dev, "%dx%d LCD, %d bits per pixel, %dkHz pixel clock\n",
	    sc->lf_lcd_config.lc_xres, sc->lf_lcd_config.lc_yres,
	    sc->lf_lcd_config.lc_bpp, sc->lf_lcd_config.lc_pixelclock / 1000);

	err = bus_dma_tag_create(
	    bus_get_dma_tag(sc->lf_dev),
	    4, 0,			/* alignment, boundary */
	    BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
	    BUS_SPACE_MAXADDR,		/* highaddr */
	    NULL, NULL,			/* filter, filterarg */
	    sc->lf_buffer_size, 1,	/* maxsize, nsegments */
	    sc->lf_buffer_size, 0,	/* maxsegsize, flags */
	    NULL, NULL,			/* lockfunc, lockarg */
	    &sc->lf_dma_tag);

	err = bus_dmamem_alloc(sc->lf_dma_tag, (void **)&sc->lf_buffer,
	    0, &sc->lf_dma_map);
	if (err) {
		device_printf(dev, "cannot allocate framebuffer\n");
		goto fail;
	}

	err = bus_dmamap_load(sc->lf_dma_tag, sc->lf_dma_map, sc->lf_buffer,
	    sc->lf_buffer_size, lpc_fb_dmamap_cb, &ctx, BUS_DMA_NOWAIT);
	if (err) {
		device_printf(dev, "cannot load DMA map\n");
		goto fail;
	}

	switch (sc->lf_lcd_config.lc_bpp) {
	case 12:
		mode = LPC_CLKPWR_LCDCLK_CTRL_MODE_12;
		break;
	case 15:
		mode = LPC_CLKPWR_LCDCLK_CTRL_MODE_15;
		break;
	case 16:
		mode = LPC_CLKPWR_LCDCLK_CTRL_MODE_16;
		break;
	case 24:
		mode = LPC_CLKPWR_LCDCLK_CTRL_MODE_24;
		break;
	default:
		panic("unsupported bpp");
	}

	lpc_pwr_write(sc->lf_dev, LPC_CLKPWR_LCDCLK_CTRL,
	    LPC_CLKPWR_LCDCLK_CTRL_MODE(mode) |
	    LPC_CLKPWR_LCDCLK_CTRL_HCLKEN);

	sc->lf_buffer_phys = ctx.lf_dma_busaddr;
	sc->lf_cdev = make_dev(&lpc_fb_cdevsw, 0, UID_ROOT, GID_WHEEL,
	    0600, "lpcfb");

	sc->lf_cdev->si_drv1 = sc;

	return (0);
fail:
	return (ENXIO);
}
Ejemplo n.º 3
0
static int
iir_pci_attach(device_t dev)
{
    struct gdt_softc    *gdt;
    struct resource     *io = NULL, *irq = NULL;
    int                 retries, rid, error = 0;
    void                *ih;
    u_int8_t            protocol;  
 
    /* map DPMEM */
    rid = PCI_DPMEM;
    io = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
    if (io == NULL) {
        device_printf(dev, "can't allocate register resources\n");
        error = ENOMEM;
        goto err;
    }

    /* get IRQ */
    rid = 0;
    irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
                                 RF_ACTIVE | RF_SHAREABLE);
    if (irq == NULL) {
        device_printf(dev, "can't find IRQ value\n");
        error = ENOMEM;
        goto err;
    }

    gdt = device_get_softc(dev);
    gdt->sc_devnode = dev;
    gdt->sc_init_level = 0;
    gdt->sc_dpmemt = rman_get_bustag(io);
    gdt->sc_dpmemh = rman_get_bushandle(io);
    gdt->sc_dpmembase = rman_get_start(io);
    gdt->sc_hanum = device_get_unit(dev);
    gdt->sc_bus = pci_get_bus(dev);
    gdt->sc_slot = pci_get_slot(dev);
    gdt->sc_vendor = pci_get_vendor(dev);
    gdt->sc_device = pci_get_device(dev);
    gdt->sc_subdevice = pci_get_subdevice(dev);
    gdt->sc_class = GDT_MPR;
/* no FC ctr.
    if (gdt->sc_device >= GDT_PCI_PRODUCT_FC)
        gdt->sc_class |= GDT_FC;
*/

    /* initialize RP controller */
    /* check and reset interface area */
    bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC,
                      htole32(GDT_MPR_MAGIC));
    if (bus_space_read_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC) !=
        htole32(GDT_MPR_MAGIC)) {
        printf("cannot access DPMEM at 0x%jx (shadowed?)\n",
               (uintmax_t)gdt->sc_dpmembase);
        error = ENXIO;
        goto err;
    }
    bus_space_set_region_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_I960_SZ, htole32(0),
                           GDT_MPR_SZ >> 2);

    /* Disable everything */
    bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_EDOOR_EN,
                      bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh, 
                                       GDT_EDOOR_EN) | 4);
    bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_EDOOR, 0xff);
    bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_STATUS,
                      0);
    bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_CMD_INDEX,
                      0);

    bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_INFO,
                      htole32(gdt->sc_dpmembase));
    bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_CMD_INDX,
                      0xff);
    bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_LDOOR, 1);

    DELAY(20);
    retries = GDT_RETRIES;
    while (bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh,
                            GDT_MPR_IC + GDT_S_STATUS) != 0xff) {
        if (--retries == 0) {
            printf("DEINIT failed\n");
            error = ENXIO;
            goto err;
        }
        DELAY(1);
    }

    protocol = (uint8_t)le32toh(bus_space_read_4(gdt->sc_dpmemt, gdt->sc_dpmemh,
                                                  GDT_MPR_IC + GDT_S_INFO));
    bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_STATUS,
                      0);
    if (protocol != GDT_PROTOCOL_VERSION) {
        printf("unsupported protocol %d\n", protocol);
        error = ENXIO;
        goto err;
    }
    
    /* special commnd to controller BIOS */
    bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_INFO,
                      htole32(0));
    bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh,
                      GDT_MPR_IC + GDT_S_INFO + sizeof (u_int32_t), htole32(0));
    bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh,
                      GDT_MPR_IC + GDT_S_INFO + 2 * sizeof (u_int32_t),
                      htole32(1));
    bus_space_write_4(gdt->sc_dpmemt, gdt->sc_dpmemh,
                      GDT_MPR_IC + GDT_S_INFO + 3 * sizeof (u_int32_t),
                      htole32(0));
    bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_CMD_INDX,
                      0xfe);
    bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_LDOOR, 1);

    DELAY(20);
    retries = GDT_RETRIES;
    while (bus_space_read_1(gdt->sc_dpmemt, gdt->sc_dpmemh,
                            GDT_MPR_IC + GDT_S_STATUS) != 0xfe) {
        if (--retries == 0) {
            printf("initialization error\n");
            error = ENXIO;
            goto err;
        }
        DELAY(1);
    }

    bus_space_write_1(gdt->sc_dpmemt, gdt->sc_dpmemh, GDT_MPR_IC + GDT_S_STATUS,
                      0);

    gdt->sc_ic_all_size = GDT_MPR_SZ;
    
    gdt->sc_copy_cmd = gdt_mpr_copy_cmd;
    gdt->sc_get_status = gdt_mpr_get_status;
    gdt->sc_intr = gdt_mpr_intr;
    gdt->sc_release_event = gdt_mpr_release_event;
    gdt->sc_set_sema0 = gdt_mpr_set_sema0;
    gdt->sc_test_busy = gdt_mpr_test_busy;

    /* Allocate a dmatag representing the capabilities of this attachment */
    if (bus_dma_tag_create(/*parent*/bus_get_dma_tag(dev),
                           /*alignemnt*/1, /*boundary*/0,
                           /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
                           /*highaddr*/BUS_SPACE_MAXADDR,
                           /*filter*/NULL, /*filterarg*/NULL,
                           /*maxsize*/BUS_SPACE_MAXSIZE_32BIT,
                           /*nsegments*/GDT_MAXSG,
                           /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
			   /*flags*/0, /*lockfunc*/busdma_lock_mutex,
			   /*lockarg*/&Giant, &gdt->sc_parent_dmat) != 0) {
        error = ENXIO;
        goto err;
    }
    gdt->sc_init_level++;

    if (iir_init(gdt) != 0) {
        iir_free(gdt);
        error = ENXIO;
        goto err;
    }

    /* Register with the XPT */
    iir_attach(gdt);

    /* associate interrupt handler */
    if (bus_setup_intr( dev, irq, INTR_TYPE_CAM, 
                        NULL, iir_intr, gdt, &ih )) {
        device_printf(dev, "Unable to register interrupt handler\n");
        error = ENXIO;
        goto err;
    }

    gdt_pci_enable_intr(gdt);
    return (0);
    
err:
    if (irq)
        bus_release_resource( dev, SYS_RES_IRQ, 0, irq );
/*
    if (io)
        bus_release_resource( dev, SYS_RES_MEMORY, rid, io );
*/
    return (error);
}
Ejemplo n.º 4
0
static int
ebus_pci_attach(device_t dev)
{
	struct ebus_softc *sc;
	struct ebus_rinfo *eri;
	struct resource *res;
	struct isa_ranges *range;
	phandle_t node;
	int i, rnum, rid;

	sc = device_get_softc(dev);
	sc->sc_flags |= EBUS_PCI;

	pci_write_config(dev, PCIR_COMMAND,
	    pci_read_config(dev, PCIR_COMMAND, 2) | PCIM_CMD_SERRESPEN |
	    PCIM_CMD_PERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN, 2);
	pci_write_config(dev, PCIR_CACHELNSZ, 16 /* 64 bytes */, 1);
	pci_write_config(dev, PCIR_LATTIMER, 64 /* 64 PCI cycles */, 1);

	node = ofw_bus_get_node(dev);
	sc->sc_nrange = OF_getprop_alloc(node, "ranges",
	    sizeof(struct isa_ranges), &sc->sc_range);
	if (sc->sc_nrange == -1) {
		device_printf(dev, "could not get ranges property\n");
		return (ENXIO);
	}

	sc->sc_rinfo = malloc(sizeof(*sc->sc_rinfo) * sc->sc_nrange, M_DEVBUF,
	    M_WAITOK | M_ZERO);

	/* For every range, there must be a matching resource. */
	for (rnum = 0; rnum < sc->sc_nrange; rnum++) {
		eri = &sc->sc_rinfo[rnum];
		range = &((struct isa_ranges *)sc->sc_range)[rnum];
		eri->eri_rtype = ofw_isa_range_restype(range);
		rid = PCIR_BAR(rnum);
		res = bus_alloc_resource_any(dev, eri->eri_rtype, &rid,
		    RF_ACTIVE);
		if (res == NULL) {
			device_printf(dev,
			    "could not allocate range resource %d\n", rnum);
			goto fail;
		}
		if (rman_get_start(res) != ISA_RANGE_PHYS(range)) {
			device_printf(dev,
			    "mismatch in start of range %d (0x%lx/0x%lx)\n",
			    rnum, rman_get_start(res), ISA_RANGE_PHYS(range));
			goto fail;
		}
		if (rman_get_size(res) != range->size) {
			device_printf(dev,
			    "mismatch in size of range %d (0x%lx/0x%x)\n",
			    rnum, rman_get_size(res), range->size);
			goto fail;
		}
		eri->eri_res = res;
		eri->eri_rman.rm_type = RMAN_ARRAY;
		eri->eri_rman.rm_descr = "EBus range";
		if (rman_init_from_resource(&eri->eri_rman, res) != 0) {
			device_printf(dev,
			    "could not initialize rman for range %d", rnum);
			goto fail;
		}
	}
	return (ebus_attach(dev, sc, node));

 fail:
	for (i = rnum; i >= 0; i--) {
		eri = &sc->sc_rinfo[i];
		if (i < rnum)
			rman_fini(&eri->eri_rman);
		if (eri->eri_res != NULL) {
			bus_release_resource(dev, eri->eri_rtype,
			    PCIR_BAR(rnum), eri->eri_res);
		}
	}
	free(sc->sc_rinfo, M_DEVBUF);
	free(sc->sc_range, M_OFWPROP);
	return (ENXIO);
}
Ejemplo n.º 5
0
static int
cs4281_pci_attach(device_t dev)
{
    struct sc_info *sc;
    struct ac97_info *codec = NULL;
    u_int32_t data;
    char status[SND_STATUSLEN];

    if ((sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT)) == NULL) {
	device_printf(dev, "cannot allocate softc\n");
	return ENXIO;
    }

    bzero(sc, sizeof(*sc));
    sc->dev = dev;
    sc->type = pci_get_devid(dev);

    data = pci_read_config(dev, PCIR_COMMAND, 2);
    data |= (PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
    pci_write_config(dev, PCIR_COMMAND, data, 2);

    data = pci_read_config(dev, PCIR_COMMAND, 2);

#if __FreeBSD_version > 500000
    if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) {
	/* Reset the power state. */
	device_printf(dev, "chip is in D%d power mode "
		      "-- setting to D0\n", pci_get_powerstate(dev));

	pci_set_powerstate(dev, PCI_POWERSTATE_D0);
    }
#endif
    sc->regid   = PCIR_MAPS;
    sc->regtype = SYS_RES_MEMORY;
    sc->reg = bus_alloc_resource(dev, sc->regtype, &sc->regid,
				 0, ~0, CS4281PCI_BA0_SIZE, RF_ACTIVE);
    if (!sc->reg) {
	sc->regtype = SYS_RES_IOPORT;
	sc->reg = bus_alloc_resource(dev, sc->regtype, &sc->regid,
				     0, ~0, CS4281PCI_BA0_SIZE, RF_ACTIVE);
	if (!sc->reg) {
	    device_printf(dev, "unable to allocate register space\n");
	    goto bad;
	}
    }
    sc->st = rman_get_bustag(sc->reg);
    sc->sh = rman_get_bushandle(sc->reg);

    sc->memid = PCIR_MAPS + 4;
    sc->mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->memid, 0,
				 ~0, CS4281PCI_BA1_SIZE, RF_ACTIVE);
    if (sc->mem == NULL) {
	device_printf(dev, "unable to allocate fifo space\n");
	goto bad;
    }

    sc->irqid = 0;
    sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqid,
				 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
    if (!sc->irq) {
	device_printf(dev, "unable to allocate interrupt\n");
	goto bad;
    }

    if (bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, cs4281_intr, sc, &sc->ih)) {
	device_printf(dev, "unable to setup interrupt\n");
	goto bad;
    }

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

    /* power up */
    cs4281_power(sc, 0);

    /* init chip */
    if (cs4281_init(sc) == -1) {
	device_printf(dev, "unable to initialize the card\n");
	goto bad;
    }

    /* create/init mixer */
    codec = AC97_CREATE(dev, sc, cs4281_ac97);
    if (codec == NULL)
        goto bad;

    mixer_init(dev, ac97_getmixerclass(), codec);

    if (pcm_register(dev, sc, 1, 1))
	goto bad;

    pcm_addchan(dev, PCMDIR_PLAY, &cs4281chan_class, sc);
    pcm_addchan(dev, PCMDIR_REC, &cs4281chan_class, sc);

    snprintf(status, SND_STATUSLEN, "at %s 0x%lx irq %ld",
	     (sc->regtype == SYS_RES_IOPORT)? "io" : "memory",
	     rman_get_start(sc->reg), rman_get_start(sc->irq));
    pcm_setstatus(dev, status);

    return 0;

 bad:
    if (codec)
	ac97_destroy(codec);
    if (sc->reg)
	bus_release_resource(dev, sc->regtype, sc->regid, sc->reg);
    if (sc->mem)
	bus_release_resource(dev, SYS_RES_MEMORY, sc->memid, sc->mem);
    if (sc->ih)
	bus_teardown_intr(dev, sc->irq, sc->ih);
    if (sc->irq)
	bus_release_resource(dev, SYS_RES_IRQ, sc->irqid, sc->irq);
    if (sc->parent_dmat)
	bus_dma_tag_destroy(sc->parent_dmat);
    free(sc, M_DEVBUF);

    return ENXIO;
}
Ejemplo n.º 6
0
int
ahd_pci_map_registers(struct ahd_softc *ahd)
{
	struct	resource *regs;
	struct	resource *regs2;
	u_int	command;
	int	regs_type;
	int	regs_id;
	int	regs_id2;
	int	allow_memio;

	command = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/1);
	regs = NULL;
	regs2 = NULL;
	regs_type = 0;
	regs_id = 0;

	/* Retrieve the per-device 'allow_memio' hint */
	if (resource_int_value(device_get_name(ahd->dev_softc),
			       device_get_unit(ahd->dev_softc),
			       "allow_memio", &allow_memio) != 0) {
		if (bootverbose)
			device_printf(ahd->dev_softc,
				      "Defaulting to MEMIO on\n");
		allow_memio = 1;
	}

	if ((command & PCIM_CMD_MEMEN) != 0
	 && (ahd->bugs & AHD_PCIX_MMAPIO_BUG) == 0
	 && allow_memio != 0) {

		regs_type = SYS_RES_MEMORY;
		regs_id = AHD_PCI_MEMADDR;
		regs = bus_alloc_resource_any(ahd->dev_softc, regs_type,
					      &regs_id, RF_ACTIVE);
		if (regs != NULL) {
			int error;

			ahd->tags[0] = rman_get_bustag(regs);
			ahd->bshs[0] = rman_get_bushandle(regs);
			ahd->tags[1] = ahd->tags[0];
			error = bus_space_subregion(ahd->tags[0], ahd->bshs[0],
						    /*offset*/0x100,
						    /*size*/0x100,
						    &ahd->bshs[1]);
			/*
			 * Do a quick test to see if memory mapped
			 * I/O is functioning correctly.
			 */
			if (error != 0
			 || ahd_pci_test_register_access(ahd) != 0) {
				device_printf(ahd->dev_softc,
				       "PCI Device %d:%d:%d failed memory "
				       "mapped test.  Using PIO.\n",
				       aic_get_pci_bus(ahd->dev_softc),
				       aic_get_pci_slot(ahd->dev_softc),
				       aic_get_pci_function(ahd->dev_softc));
				bus_release_resource(ahd->dev_softc, regs_type,
						     regs_id, regs);
				regs = NULL;
				AHD_CORRECTABLE_ERROR(ahd);
			} else {
				command &= ~PCIM_CMD_PORTEN;
				aic_pci_write_config(ahd->dev_softc,
						     PCIR_COMMAND,
						     command, /*bytes*/1);
			}
		}
	}
	if (regs == NULL && (command & PCIM_CMD_PORTEN) != 0) {
		regs_type = SYS_RES_IOPORT;
		regs_id = AHD_PCI_IOADDR0;
		regs = bus_alloc_resource_any(ahd->dev_softc, regs_type,
					      &regs_id, RF_ACTIVE);
		if (regs == NULL) {
			device_printf(ahd->dev_softc,
				      "can't allocate register resources\n");
			AHD_UNCORRECTABLE_ERROR(ahd);
			return (ENOMEM);
		}
		ahd->tags[0] = rman_get_bustag(regs);
		ahd->bshs[0] = rman_get_bushandle(regs);

		/* And now the second BAR */
		regs_id2 = AHD_PCI_IOADDR1;
		regs2 = bus_alloc_resource_any(ahd->dev_softc, regs_type,
					       &regs_id2, RF_ACTIVE);
		if (regs2 == NULL) {
			device_printf(ahd->dev_softc,
				      "can't allocate register resources\n");
			AHD_UNCORRECTABLE_ERROR(ahd);
			return (ENOMEM);
		}
		ahd->tags[1] = rman_get_bustag(regs2);
		ahd->bshs[1] = rman_get_bushandle(regs2);
		command &= ~PCIM_CMD_MEMEN;
		aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
				     command, /*bytes*/1);
		ahd->platform_data->regs_res_type[1] = regs_type;
		ahd->platform_data->regs_res_id[1] = regs_id2;
		ahd->platform_data->regs[1] = regs2;
	}
	ahd->platform_data->regs_res_type[0] = regs_type;
	ahd->platform_data->regs_res_id[0] = regs_id;
	ahd->platform_data->regs[0] = regs;
	return (0);
}
Ejemplo n.º 7
0
static int
csa_attach(device_t dev)
{
	u_int32_t stcmd;
	sc_p scp;
	csa_res *resp;
	struct sndcard_func *func;
	int error = ENXIO;

	scp = device_get_softc(dev);

	/* Fill in the softc. */
	bzero(scp, sizeof(*scp));
	scp->dev = dev;

	/* Wake up the device. */
	stcmd = pci_read_config(dev, PCIR_COMMAND, 2);
	if ((stcmd & PCIM_CMD_MEMEN) == 0 || (stcmd & PCIM_CMD_BUSMASTEREN) == 0) {
		stcmd |= (PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN);
		pci_write_config(dev, PCIR_COMMAND, stcmd, 2);
	}

	/* Allocate the resources. */
	resp = &scp->res;
	scp->card = csa_findsubcard(dev);
	scp->binfo.card = scp->card;
	printf("csa: card is %s\n", scp->card->name);
	resp->io_rid = PCIR_BAR(0);
	resp->io = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 
		&resp->io_rid, RF_ACTIVE);
	if (resp->io == NULL)
		return (ENXIO);
	resp->mem_rid = PCIR_BAR(1);
	resp->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
		&resp->mem_rid, RF_ACTIVE);
	if (resp->mem == NULL)
		goto err_io;
	resp->irq_rid = 0;
	resp->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
		&resp->irq_rid, RF_ACTIVE | RF_SHAREABLE);
	if (resp->irq == NULL)
		goto err_mem;

	/* Enable interrupt. */
	if (snd_setup_intr(dev, resp->irq, 0, csa_intr, scp, &scp->ih))
		goto err_intr;
#if 0
	if ((csa_readio(resp, BA0_HISR) & HISR_INTENA) == 0)
		csa_writeio(resp, BA0_HICR, HICR_IEV | HICR_CHGM);
#endif

	/* Initialize the chip. */
	if (csa_initialize(scp))
		goto err_teardown;

	/* Reset the Processor. */
	csa_resetdsp(resp);

	/* Download the Processor Image to the processor. */
	if (csa_downloadimage(resp))
		goto err_teardown;

	/* Attach the children. */

	/* PCM Audio */
	func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
	if (func == NULL) {
		error = ENOMEM;
		goto err_teardown;
	}
	func->varinfo = &scp->binfo;
	func->func = SCF_PCM;
	scp->pcm = device_add_child(dev, "pcm", -1);
	device_set_ivars(scp->pcm, func);

	/* Midi Interface */
	func = malloc(sizeof(struct sndcard_func), M_DEVBUF, M_NOWAIT | M_ZERO);
	if (func == NULL) {
		error = ENOMEM;
		goto err_teardown;
	}
	func->varinfo = &scp->binfo;
	func->func = SCF_MIDI;
	scp->midi = device_add_child(dev, "midi", -1);
	device_set_ivars(scp->midi, func);

	bus_generic_attach(dev);

	return (0);

err_teardown:
	bus_teardown_intr(dev, resp->irq, scp->ih);
err_intr:
	bus_release_resource(dev, SYS_RES_IRQ, resp->irq_rid, resp->irq);
err_mem:
	bus_release_resource(dev, SYS_RES_MEMORY, resp->mem_rid, resp->mem);
err_io:
	bus_release_resource(dev, SYS_RES_MEMORY, resp->io_rid, resp->io);
	return (error);
}
Ejemplo n.º 8
0
int
ata_attach(device_t dev)
{
    struct ata_channel *ch = device_get_softc(dev);
    int error, rid;
    struct cam_devq *devq;
    const char *res;
    char buf[64];
    int i, mode;

    /* check that we have a virgin channel to attach */
    if (ch->r_irq)
	return EEXIST;

    /* initialize the softc basics */
    ch->dev = dev;
    ch->state = ATA_IDLE;
    bzero(&ch->state_mtx, sizeof(struct mtx));
    mtx_init(&ch->state_mtx, "ATA state lock", NULL, MTX_DEF);
    TASK_INIT(&ch->conntask, 0, ata_conn_event, dev);
	for (i = 0; i < 16; i++) {
		ch->user[i].revision = 0;
		snprintf(buf, sizeof(buf), "dev%d.sata_rev", i);
		if (resource_int_value(device_get_name(dev),
		    device_get_unit(dev), buf, &mode) != 0 &&
		    resource_int_value(device_get_name(dev),
		    device_get_unit(dev), "sata_rev", &mode) != 0)
			mode = -1;
		if (mode >= 0)
			ch->user[i].revision = mode;
		ch->user[i].mode = 0;
		snprintf(buf, sizeof(buf), "dev%d.mode", i);
		if (resource_string_value(device_get_name(dev),
		    device_get_unit(dev), buf, &res) == 0)
			mode = ata_str2mode(res);
		else if (resource_string_value(device_get_name(dev),
		    device_get_unit(dev), "mode", &res) == 0)
			mode = ata_str2mode(res);
		else
			mode = -1;
		if (mode >= 0)
			ch->user[i].mode = mode;
		if (ch->flags & ATA_SATA)
			ch->user[i].bytecount = 8192;
		else
			ch->user[i].bytecount = MAXPHYS;
		ch->user[i].caps = 0;
		ch->curr[i] = ch->user[i];
		if (ch->flags & ATA_SATA) {
			if (ch->pm_level > 0)
				ch->user[i].caps |= CTS_SATA_CAPS_H_PMREQ;
			if (ch->pm_level > 1)
				ch->user[i].caps |= CTS_SATA_CAPS_D_PMREQ;
		} else {
			if (!(ch->flags & ATA_NO_48BIT_DMA))
				ch->user[i].caps |= CTS_ATA_CAPS_H_DMA48;
		}
	}
	callout_init(&ch->poll_callout, 1);

    /* allocate DMA resources if DMA HW present*/
    if (ch->dma.alloc)
	ch->dma.alloc(dev);

    /* setup interrupt delivery */
    rid = ATA_IRQ_RID;
    ch->r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
				       RF_SHAREABLE | RF_ACTIVE);
    if (!ch->r_irq) {
	device_printf(dev, "unable to allocate interrupt\n");
	return ENXIO;
    }
    if ((error = bus_setup_intr(dev, ch->r_irq, ATA_INTR_FLAGS, NULL,
				ata_interrupt, ch, &ch->ih))) {
	bus_release_resource(dev, SYS_RES_IRQ, rid, ch->r_irq);
	device_printf(dev, "unable to setup interrupt\n");
	return error;
    }

	if (ch->flags & ATA_PERIODIC_POLL)
		callout_reset(&ch->poll_callout, hz, ata_periodic_poll, ch);
	mtx_lock(&ch->state_mtx);
	/* Create the device queue for our SIM. */
	devq = cam_simq_alloc(1);
	if (devq == NULL) {
		device_printf(dev, "Unable to allocate simq\n");
		error = ENOMEM;
		goto err1;
	}
	/* Construct SIM entry */
	ch->sim = cam_sim_alloc(ataaction, atapoll, "ata", ch,
	    device_get_unit(dev), &ch->state_mtx, 1, 0, devq);
	if (ch->sim == NULL) {
		device_printf(dev, "unable to allocate sim\n");
		cam_simq_free(devq);
		error = ENOMEM;
		goto err1;
	}
	if (xpt_bus_register(ch->sim, dev, 0) != CAM_SUCCESS) {
		device_printf(dev, "unable to register xpt bus\n");
		error = ENXIO;
		goto err2;
	}
	if (xpt_create_path(&ch->path, /*periph*/NULL, cam_sim_path(ch->sim),
	    CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
		device_printf(dev, "unable to create path\n");
		error = ENXIO;
		goto err3;
	}
	mtx_unlock(&ch->state_mtx);
	return (0);

err3:
	xpt_bus_deregister(cam_sim_path(ch->sim));
err2:
	cam_sim_free(ch->sim, /*free_devq*/TRUE);
	ch->sim = NULL;
err1:
	bus_release_resource(dev, SYS_RES_IRQ, rid, ch->r_irq);
	mtx_unlock(&ch->state_mtx);
	if (ch->flags & ATA_PERIODIC_POLL)
		callout_drain(&ch->poll_callout);
	return (error);
}
Ejemplo n.º 9
0
/*
 * The adv_b stuff to handle twin-channel cards will not work in its current
 * incarnation.  It tries to reuse the same softc since adv_alloc() doesn't
 * actually allocate a softc.  It also tries to reuse the same unit number
 * for both sims.  This can be re-enabled if someone fixes it properly.
 */
static int
adv_eisa_attach(device_t dev)
{
	struct adv_softc *adv;
#if 0
	struct adv_softc *adv_b;
#endif
	struct resource *io;
	struct resource *irq;
	int rid, error;
	void *ih;

#if 0
	adv_b = NULL;
#endif

	rid = 0;
	io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE);
	if (!io) {
		device_printf(dev, "No I/O space?!\n");
		return ENOMEM;
	}

	rid = 0;
	irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
				     RF_SHAREABLE | RF_ACTIVE);
	if (!irq) {
		device_printf(dev, "No irq?!\n");
		bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
		return ENOMEM;

	}

	switch (eisa_get_id(dev) & ~0xF) {
	case EISA_DEVICE_ID_ADVANSYS_750:
#if 0
		adv_b = adv_alloc(dev, io, ADV_EISA_OFFSET_CHAN2);
		if (adv_b == NULL)
			goto bad;
		
		/*
		 * Allocate a parent dmatag for all tags created
		 * by the MI portions of the advansys driver
		 */
		error = bus_dma_tag_create(
				/* parent	*/ bus_get_dma_tag(dev),
				/* alignment	*/ 1,
				/* boundary	*/ 0,
				/* lowaddr	*/ ADV_EISA_MAX_DMA_ADDR,
				/* highaddr	*/ BUS_SPACE_MAXADDR,
				/* filter	*/ NULL,
				/* filterarg	*/ NULL,
				/* maxsize	*/ BUS_SPACE_MAXSIZE_32BIT,
				/* nsegments	*/ ~0,
				/* maxsegsz	*/ ADV_EISA_MAX_DMA_COUNT,
				/* flags	*/ 0,
				/* lockfunc	*/ NULL,
				/* lockarg	*/ NULL,
				&adv_b->parent_dmat);
 
		if (error != 0) {
			device_printf(dev, "Could not allocate DMA tag - error %d\n",
			       error);
			adv_free(adv_b);
			goto bad;
		}

		adv_b->init_level++;
#endif

		/* FALLTHROUGH */
	case EISA_DEVICE_ID_ADVANSYS_740:
		adv = adv_alloc(dev, io, ADV_EISA_OFFSET_CHAN1);
		if (adv == NULL) {
#if 0
			if (adv_b != NULL)
				adv_free(adv_b);
#endif
			goto bad;
		}

		/*
		 * Allocate a parent dmatag for all tags created
		 * by the MI portions of the advansys driver
		 */
		error = bus_dma_tag_create(
				/* parent	*/ bus_get_dma_tag(dev),
				/* alignment	*/ 1,
				/* boundary	*/ 0,
				/* lowaddr	*/ ADV_EISA_MAX_DMA_ADDR,
				/* highaddr	*/ BUS_SPACE_MAXADDR,
				/* filter	*/ NULL,
				/* filterarg	*/ NULL,
				/* maxsize	*/ BUS_SPACE_MAXSIZE_32BIT,
				/* nsegments	*/ ~0,
				/* maxsegsz	*/ ADV_EISA_MAX_DMA_COUNT,
				/* flags	*/ 0,
				/* lockfunc	*/ NULL,
				/* lockarg	*/ NULL,
				&adv->parent_dmat);
 
		if (error != 0) {
			device_printf(dev, "Could not allocate DMA tag - error %d\n",
			       error);
			adv_free(adv);
			goto bad;
		}

		adv->init_level++;
		break;
	default: 
		printf("adveisaattach: Unknown device type!\n");
		goto bad;
		break;
	}

	if (overrun_buf == NULL) {
		/* Need to allocate our overrun buffer */
		if (bus_dma_tag_create(
				/* parent	*/ bus_get_dma_tag(dev),
				/* alignment	*/ 8,
				/* boundary	*/ 0,
				/* lowaddr	*/ ADV_EISA_MAX_DMA_ADDR,
				/* highaddr	*/ BUS_SPACE_MAXADDR,
				/* filter	*/ NULL,
				/* filterarg	*/ NULL,
				/* maxsize	*/ ADV_OVERRUN_BSIZE,
				/* nsegments	*/ 1,
				/* maxsegsz	*/ BUS_SPACE_MAXSIZE_32BIT,
				/* flags	*/ 0,
				/* lockfunc	*/ NULL,
				/* lockarg	*/ NULL,
				&overrun_dmat) != 0) {
			adv_free(adv);
			goto bad;
       		}
		if (bus_dmamem_alloc(overrun_dmat,
				     &overrun_buf,
				     BUS_DMA_NOWAIT,
				     &overrun_dmamap) != 0) {
			bus_dma_tag_destroy(overrun_dmat);
			adv_free(adv);
			goto bad;
		}
		/* And permanently map it in */  
		bus_dmamap_load(overrun_dmat, overrun_dmamap,
				overrun_buf, ADV_OVERRUN_BSIZE,
				adv_map, &overrun_physbase,
				/*flags*/0);
	}
	
	/*
	 * Now that we know we own the resources we need, do the 
	 * card initialization.
	 */

	/*
	 * Stop the chip.
	 */
	ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT);
	ADV_OUTW(adv, ADV_CHIP_STATUS, 0);

	adv->chip_version = EISA_REVISION_ID(eisa_get_id(dev))
			  + ADV_CHIP_MIN_VER_EISA - 1;

	if (adv_init(adv) != 0) {
		adv_free(adv);
#if 0
		if (adv_b != NULL)
			adv_free(adv_b);
#endif
		goto bad;
	}

	adv->max_dma_count = ADV_EISA_MAX_DMA_COUNT;
	adv->max_dma_addr = ADV_EISA_MAX_DMA_ADDR;

#if 0
	if (adv_b != NULL) {
		/*
		 * Stop the chip.
		 */
		ADV_OUTB(adv_b, ADV_CHIP_CTRL, ADV_CC_HALT);
		ADV_OUTW(adv_b, ADV_CHIP_STATUS, 0);

		adv_b->chip_version = EISA_REVISION_ID(eisa_get_id(dev))
				    + ADV_CHIP_MIN_VER_EISA - 1;

		if (adv_init(adv_b) != 0) {
			adv_free(adv_b);
		} else {
			adv_b->max_dma_count = ADV_EISA_MAX_DMA_COUNT;
			adv_b->max_dma_addr = ADV_EISA_MAX_DMA_ADDR;
		}
	}
#endif

	/*
	 * Enable our interrupt handler.
	 */
	if (bus_setup_intr(dev, irq, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, NULL,
	    adv_intr, adv, &ih) != 0) {
		adv_free(adv);
		goto bad;
	}

	/* Attach sub-devices */
	if (adv_attach(adv) != 0) {
		adv_free(adv);
		goto bad;
	}
#if 0
	if (adv_b != NULL)
		adv_attach(adv_b);
#endif

	return 0;

 bad:
	bus_release_resource(dev, SYS_RES_IOPORT, 0, io);
	bus_release_resource(dev, SYS_RES_IRQ, 0, irq);
	return ENXIO;
}
Ejemplo n.º 10
0
int
smc_probe(device_t dev)
{
	int			rid, type, error;
	uint16_t		val;
	struct smc_softc	*sc;
	struct resource		*reg;

	sc = device_get_softc(dev);
	rid = 0;
	type = SYS_RES_IOPORT;
	error = 0;

	if (sc->smc_usemem)
		type = SYS_RES_MEMORY;

	reg = bus_alloc_resource(dev, type, &rid, 0, ~0, 16, RF_ACTIVE);
	if (reg == NULL) {
		if (bootverbose)
			device_printf(dev,
			    "could not allocate I/O resource for probe\n");
		return (ENXIO);
	}

	/* Check for the identification value in the BSR. */
	val = bus_read_2(reg, BSR);
	if ((val & BSR_IDENTIFY_MASK) != BSR_IDENTIFY) {
		if (bootverbose)
			device_printf(dev, "identification value not in BSR\n");
		error = ENXIO;
		goto done;
	}

	/*
	 * Try switching banks and make sure we still get the identification
	 * value.
	 */
	bus_write_2(reg, BSR, 0);
	val = bus_read_2(reg, BSR);
	if ((val & BSR_IDENTIFY_MASK) != BSR_IDENTIFY) {
		if (bootverbose)
			device_printf(dev,
			    "identification value not in BSR after write\n");
		error = ENXIO;
		goto done;
	}

#if 0
	/* Check the BAR. */
	bus_write_2(reg, BSR, 1);
	val = bus_read_2(reg, BAR);
	val = BAR_ADDRESS(val);
	if (rman_get_start(reg) != val) {
		if (bootverbose)
			device_printf(dev, "BAR address %x does not match "
			    "I/O resource address %lx\n", val,
			    rman_get_start(reg));
		error = ENXIO;
		goto done;
	}
#endif

	/* Compare REV against known chip revisions. */
	bus_write_2(reg, BSR, 3);
	val = bus_read_2(reg, REV);
	val = (val & REV_CHIP_MASK) >> REV_CHIP_SHIFT;
	if (smc_chip_ids[val] == NULL) {
		if (bootverbose)
			device_printf(dev, "Unknown chip revision: %d\n", val);
		error = ENXIO;
		goto done;
	}

	device_set_desc(dev, smc_chip_ids[val]);

done:
	bus_release_resource(dev, type, rid, reg);
	return (error);
}
Ejemplo n.º 11
0
int
smc_detach(device_t dev)
{
	int			type;
	struct smc_softc	*sc;

	sc = device_get_softc(dev);
	SMC_LOCK(sc);
	smc_stop(sc);
	SMC_UNLOCK(sc);

	if (sc->smc_ifp != NULL) {
		ether_ifdetach(sc->smc_ifp);
	}
	
	callout_drain(&sc->smc_watchdog);
	callout_drain(&sc->smc_mii_tick_ch);
	
#ifdef DEVICE_POLLING
	if (sc->smc_ifp->if_capenable & IFCAP_POLLING)
		ether_poll_deregister(sc->smc_ifp);
#endif

	if (sc->smc_ih != NULL)
		bus_teardown_intr(sc->smc_dev, sc->smc_irq, sc->smc_ih);

	if (sc->smc_tq != NULL) {
		taskqueue_drain(sc->smc_tq, &sc->smc_intr);
		taskqueue_drain(sc->smc_tq, &sc->smc_rx);
		taskqueue_drain(sc->smc_tq, &sc->smc_tx);
		taskqueue_free(sc->smc_tq);
		sc->smc_tq = NULL;
	}

	if (sc->smc_ifp != NULL) {
		if_free(sc->smc_ifp);
	}

	if (sc->smc_miibus != NULL) {
		device_delete_child(sc->smc_dev, sc->smc_miibus);
		bus_generic_detach(sc->smc_dev);
	}

	if (sc->smc_reg != NULL) {
		type = SYS_RES_IOPORT;
		if (sc->smc_usemem)
			type = SYS_RES_MEMORY;

		bus_release_resource(sc->smc_dev, type, sc->smc_reg_rid,
		    sc->smc_reg);
	}

	if (sc->smc_irq != NULL)
		bus_release_resource(sc->smc_dev, SYS_RES_IRQ, sc->smc_irq_rid,
		   sc->smc_irq);

	if (mtx_initialized(&sc->smc_mtx))
		mtx_destroy(&sc->smc_mtx);

	return (0);
}
Ejemplo n.º 12
0
static int
si_pci_attach(device_t dev)
{
	struct si_softc *sc;
	void *ih;
	int error;

	error = 0;
	ih = NULL;
	sc = device_get_softc(dev);

	switch (pci_get_devid(dev)) {
	case 0x400011cb:
		sc->sc_type = SIPCI;
		sc->sc_mem_rid = SIPCIBADR;
		break;
	case 0x200011cb:
		sc->sc_type = SIJETPCI;
		sc->sc_mem_rid = SIJETBADR;
		break;
	}

	sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
						&sc->sc_mem_rid,
						RF_ACTIVE);
	if (!sc->sc_mem_res) {
		device_printf(dev, "couldn't map memory\n");
		goto fail;
	}
	sc->sc_paddr = (caddr_t)rman_get_start(sc->sc_mem_res);
	sc->sc_maddr = rman_get_virtual(sc->sc_mem_res);

	sc->sc_irq_rid = 0;
	sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
						&sc->sc_irq_rid,
						RF_ACTIVE | RF_SHAREABLE);
	if (!sc->sc_irq_res) {
		device_printf(dev, "couldn't map interrupt\n");
		goto fail;
	}
	sc->sc_irq = rman_get_start(sc->sc_irq_res);
	error = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_TTY,
			       NULL, si_intr, sc, &ih);
	if (error) {
		device_printf(dev, "could not activate interrupt\n");
		goto fail;
	}

	if (pci_get_devid(dev) == 0x200011cb) {
		int rid;
		struct resource *plx_res;
		uint32_t *addr;
		uint32_t oldvalue;

		/* Perform a PLX control register fixup */
		rid = PCIR_BAR(0);
		plx_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
		    RF_ACTIVE);
		if (plx_res == NULL) {
			device_printf(dev, "couldn't map plx registers\n");
		} else {
			addr = rman_get_virtual(plx_res);
			oldvalue = addr[0x50 / 4];
			if (oldvalue != 0x18260000) {
				device_printf(dev, "PLX register 0x50: 0x%08x changed to 0x%08x\n", oldvalue, 0x18260000);
				addr[0x50 / 4] = 0x18260000;
			}
			bus_release_resource(dev, SYS_RES_MEMORY, rid, plx_res);
		}
	}

	error = siattach(dev);
	if (error)
		goto fail;
	return (0);		/* success */

fail:
	if (error == 0)
		error = ENXIO;
	if (sc->sc_irq_res) {
		if (ih)
			bus_teardown_intr(dev, sc->sc_irq_res, ih);
		bus_release_resource(dev, SYS_RES_IRQ,
				     sc->sc_irq_rid, sc->sc_irq_res);
		sc->sc_irq_res = 0;
	}
	if (sc->sc_mem_res) {
		bus_release_resource(dev, SYS_RES_MEMORY,
				     sc->sc_mem_rid, sc->sc_mem_res);
		sc->sc_mem_res = 0;
	}
	return (error);
}
Ejemplo n.º 13
0
int
ahc_pci_map_registers(struct ahc_softc *ahc)
{
	struct	resource *regs;
	u_int	command;
	int	regs_type;
	int	regs_id;
	int	allow_memio;

	command = aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1);
	regs = NULL;
	regs_type = 0;
	regs_id = 0;

	/* Retrieve the per-device 'allow_memio' hint */
	if (resource_int_value(device_get_name(ahc->dev_softc),
			       device_get_unit(ahc->dev_softc),
			       "allow_memio", &allow_memio) != 0) {
		if (bootverbose)
			device_printf(ahc->dev_softc, "Defaulting to MEMIO ");
#ifdef AHC_ALLOW_MEMIO
		if (bootverbose)
			printf("on\n");
		allow_memio = 1;
#else
		if (bootverbose)
			printf("off\n");
		allow_memio = 0;
#endif
	}

	if ((allow_memio != 0) && (command & PCIM_CMD_MEMEN) != 0) {

		regs_type = SYS_RES_MEMORY;
		regs_id = AHC_PCI_MEMADDR;
		regs = bus_alloc_resource_any(ahc->dev_softc, regs_type,
					      &regs_id, RF_ACTIVE);
		if (regs != NULL) {
			ahc->tag = rman_get_bustag(regs);
			ahc->bsh = rman_get_bushandle(regs);

			/*
			 * Do a quick test to see if memory mapped
			 * I/O is functioning correctly.
			 */
			if (ahc_pci_test_register_access(ahc) != 0) {
				device_printf(ahc->dev_softc,
				       "PCI Device %d:%d:%d failed memory "
				       "mapped test.  Using PIO.\n",
				       aic_get_pci_bus(ahc->dev_softc),
				       aic_get_pci_slot(ahc->dev_softc),
				       aic_get_pci_function(ahc->dev_softc));
				bus_release_resource(ahc->dev_softc, regs_type,
						     regs_id, regs);
				regs = NULL;
			} else {
				command &= ~PCIM_CMD_PORTEN;
				aic_pci_write_config(ahc->dev_softc,
						     PCIR_COMMAND,
						     command, /*bytes*/1);
			}
		}
	}

	if (regs == NULL && (command & PCIM_CMD_PORTEN) != 0) {
		regs_type = SYS_RES_IOPORT;
		regs_id = AHC_PCI_IOADDR;
		regs = bus_alloc_resource_any(ahc->dev_softc, regs_type,
					      &regs_id, RF_ACTIVE);
		if (regs != NULL) {
			ahc->tag = rman_get_bustag(regs);
			ahc->bsh = rman_get_bushandle(regs);
			if (ahc_pci_test_register_access(ahc) != 0) {
				device_printf(ahc->dev_softc,
				       "PCI Device %d:%d:%d failed I/O "
				       "mapped test.\n",
				       aic_get_pci_bus(ahc->dev_softc),
				       aic_get_pci_slot(ahc->dev_softc),
				       aic_get_pci_function(ahc->dev_softc));
				bus_release_resource(ahc->dev_softc, regs_type,
						     regs_id, regs);
				regs = NULL;
			} else {
				command &= ~PCIM_CMD_MEMEN;
				aic_pci_write_config(ahc->dev_softc,
						     PCIR_COMMAND,
						     command, /*bytes*/1);
			}
		}
	}
	if (regs == NULL) {
		device_printf(ahc->dev_softc,
			      "can't allocate register resources\n");
		return (ENOMEM);
	}
	ahc->platform_data->regs_res_type = regs_type;
	ahc->platform_data->regs_res_id = regs_id;
	ahc->platform_data->regs = regs;
	return (0);
}
Ejemplo n.º 14
0
static int
le_isa_attach(device_t dev)
{
	struct le_isa_softc *lesc;
	struct lance_softc *sc;
	bus_size_t macstart, rap, rdp;
	int error, i, j, macstride;

	lesc = device_get_softc(dev);
	sc = &lesc->sc_am7990.lsc;

	LE_LOCK_INIT(sc, device_get_nameunit(dev));

	j = 0;
	switch (ISA_PNP_PROBE(device_get_parent(dev), dev, le_isa_ids)) {
	case 0:
		lesc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
		    &j, RF_ACTIVE);
		rap = PCNET_RAP;
		rdp = PCNET_RDP;
		macstart = 0;
		macstride = 1;
		break;
	case ENOENT:
		for (i = 0; i < sizeof(le_isa_params) /
		    sizeof(le_isa_params[0]); i++) {
			if (le_isa_probe_legacy(dev, &le_isa_params[i]) == 0) {
				lesc->sc_rres = bus_alloc_resource(dev,
				    SYS_RES_IOPORT, &j, 0, ~0,
				    le_isa_params[i].iosize, RF_ACTIVE);
				rap = le_isa_params[i].rap;
				rdp = le_isa_params[i].rdp;
				macstart = le_isa_params[i].macstart;
				macstride = le_isa_params[i].macstride;
				goto found;
			}
		}
		/* FALLTHROUGH */
	case ENXIO:
	default:
		device_printf(dev, "cannot determine chip\n");
		error = ENXIO;
		goto fail_mtx;
	}

 found:
	if (lesc->sc_rres == NULL) {
		device_printf(dev, "cannot allocate registers\n");
		error = ENXIO;
		goto fail_mtx;
	}
	lesc->sc_rap = rap;
	lesc->sc_rdp = rdp;

	i = 0;
	if ((lesc->sc_dres = bus_alloc_resource_any(dev, SYS_RES_DRQ,
	    &i, RF_ACTIVE)) == NULL) {
		device_printf(dev, "cannot allocate DMA channel\n");
		error = ENXIO;
		goto fail_rres;
	}

	i = 0;
	if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ,
	    &i, RF_SHAREABLE | RF_ACTIVE)) == NULL) {
		device_printf(dev, "cannot allocate interrupt\n");
		error = ENXIO;
		goto fail_dres;
	}

	error = bus_dma_tag_create(
	    bus_get_dma_tag(dev),	/* parent */
	    1, 0,			/* alignment, boundary */
	    BUS_SPACE_MAXADDR_24BIT,	/* lowaddr */
	    BUS_SPACE_MAXADDR,		/* highaddr */
	    NULL, NULL,			/* filter, filterarg */
	    BUS_SPACE_MAXSIZE_32BIT,	/* maxsize */
	    0,				/* nsegments */
	    BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
	    0,				/* flags */
	    NULL, NULL,			/* lockfunc, lockarg */
	    &lesc->sc_pdmat);
	if (error != 0) {
		device_printf(dev, "cannot allocate parent DMA tag\n");
		goto fail_ires;
	}

	sc->sc_memsize = LE_ISA_MEMSIZE;
	/*
	 * For Am79C90, Am79C961 and Am79C961A the init block must be 2-byte
	 * aligned and the ring descriptors must be 8-byte aligned.
	 */
	error = bus_dma_tag_create(
	    lesc->sc_pdmat,		/* parent */
	    8, 0,			/* alignment, boundary */
	    BUS_SPACE_MAXADDR_24BIT,	/* lowaddr */
	    BUS_SPACE_MAXADDR,		/* highaddr */
	    NULL, NULL,			/* filter, filterarg */
	    sc->sc_memsize,		/* maxsize */
	    1,				/* nsegments */
	    sc->sc_memsize,		/* maxsegsize */
	    0,				/* flags */
	    NULL, NULL,			/* lockfunc, lockarg */
	    &lesc->sc_dmat);
	if (error != 0) {
		device_printf(dev, "cannot allocate buffer DMA tag\n");
		goto fail_pdtag;
	}

	error = bus_dmamem_alloc(lesc->sc_dmat, (void **)&sc->sc_mem,
	    BUS_DMA_WAITOK | BUS_DMA_COHERENT, &lesc->sc_dmam);
	if (error != 0) {
		device_printf(dev, "cannot allocate DMA buffer memory\n");
		goto fail_dtag;
	}

	sc->sc_addr = 0;
	error = bus_dmamap_load(lesc->sc_dmat, lesc->sc_dmam, sc->sc_mem,
	    sc->sc_memsize, le_isa_dma_callback, sc, 0);
	if (error != 0 || sc->sc_addr == 0) {
		device_printf(dev, "cannot load DMA buffer map\n");
		goto fail_dmem;
	}

	isa_dmacascade(rman_get_start(lesc->sc_dres));

	sc->sc_flags = 0;
	sc->sc_conf3 = 0;

	/*
	 * Extract the physical MAC address from the ROM.
	 */
	for (i = 0; i < sizeof(sc->sc_enaddr); i++)
		sc->sc_enaddr[i] = bus_read_1(lesc->sc_rres,
		    macstart + i * macstride);

	sc->sc_copytodesc = lance_copytobuf_contig;
	sc->sc_copyfromdesc = lance_copyfrombuf_contig;
	sc->sc_copytobuf = lance_copytobuf_contig;
	sc->sc_copyfrombuf = lance_copyfrombuf_contig;
	sc->sc_zerobuf = lance_zerobuf_contig;

	sc->sc_rdcsr = le_isa_rdcsr;
	sc->sc_wrcsr = le_isa_wrcsr;
	sc->sc_hwreset = NULL;
	sc->sc_hwinit = NULL;
	sc->sc_hwintr = NULL;
	sc->sc_nocarrier = NULL;
	sc->sc_mediachange = NULL;
	sc->sc_mediastatus = NULL;
	sc->sc_supmedia = NULL;

	error = am7990_config(&lesc->sc_am7990, device_get_name(dev),
	    device_get_unit(dev));
	if (error != 0) {
		device_printf(dev, "cannot attach Am7990\n");
		goto fail_dmap;
	}

	error = bus_setup_intr(dev, lesc->sc_ires, INTR_TYPE_NET | INTR_MPSAFE,
	    NULL, am7990_intr, sc, &lesc->sc_ih);
	if (error != 0) {
		device_printf(dev, "cannot set up interrupt\n");
		goto fail_am7990;
	}

	return (0);

 fail_am7990:
	am7990_detach(&lesc->sc_am7990);
 fail_dmap:
	bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam);
 fail_dmem:
	bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam);
 fail_dtag:
	bus_dma_tag_destroy(lesc->sc_dmat);
 fail_pdtag:
	bus_dma_tag_destroy(lesc->sc_pdmat);
 fail_ires:
	bus_release_resource(dev, SYS_RES_IRQ,
	    rman_get_rid(lesc->sc_ires), lesc->sc_ires);
 fail_dres:
	bus_release_resource(dev, SYS_RES_DRQ,
	    rman_get_rid(lesc->sc_dres), lesc->sc_dres);
 fail_rres:
	bus_release_resource(dev, SYS_RES_IOPORT,
	    rman_get_rid(lesc->sc_rres), lesc->sc_rres);
 fail_mtx:
	LE_LOCK_DESTROY(sc);
	return (error);
}
Ejemplo n.º 15
0
static int
atkbdc_ebus_probe(device_t dev)
{
	struct resource *port0, *port1;
	u_long count, start;
	int error, rid;

	if (strcmp(ofw_bus_get_name(dev), "8042") != 0)
		return (ENXIO);

	/*
	 * On AXi and AXmp boards the NS16550 (used to connect keyboard/
	 * mouse) share their IRQ lines with the i8042. Any IRQ activity
	 * (typically during attach) of the NS16550 used to connect the
	 * keyboard when actually the PS/2 keyboard is selected in OFW
	 * causes interaction with the OBP i8042 driver resulting in a
	 * hang and vice versa. As RS232 keyboards and mice obviously
	 * aren't meant to be used in parallel with PS/2 ones on these
	 * boards don't attach to the i8042 in case the PS/2 keyboard
	 * isn't selected in order to prevent such hangs.
	 * Note that it's not sufficient here to rely on the '8042' node
	 * only showing up when a PS/2 keyboard is actually connected as
	 * the user still might have adjusted the 'keyboard' alias to
	 * point to the RS232 keyboard.
	 */
	if ((!strcmp(sparc64_model, "SUNW,UltraAX-MP") ||
	    !strcmp(sparc64_model, "SUNW,UltraSPARC-IIi-Engine")) &&
	    OF_finddevice("keyboard") != ofw_bus_get_node(dev)) {
		device_disable(dev);
		return (ENXIO);
	}

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

	/*
	 * The '8042' node has two identical 8 addresses wide resources
	 * which are apparently meant to be used one for the keyboard
	 * half and the other one for the mouse half. To simplify matters
	 * we use one for the command/data port resource and the other
	 * one for the status port resource as the atkbdc(4) back-end
	 * expects two struct resource rather than two bus space handles.
	 */
	rid = 0;
	if (bus_get_resource(dev, SYS_RES_MEMORY, rid, &start, &count) != 0) {
		device_printf(dev,
		    "cannot determine command/data port resource\n");
		return (ENXIO);
	}
	port0 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, start, start, 1,
	    RF_ACTIVE);
	if (port0 == NULL) {
		device_printf(dev,
		    "cannot allocate command/data port resource\n");
		return (ENXIO);
	}

	rid = 1;
	if (bus_get_resource(dev, SYS_RES_MEMORY, rid, &start, &count) != 0) {
		device_printf(dev, "cannot determine status port resource\n");
		error = ENXIO;
		goto fail_port0;
	}
	start += KBD_STATUS_PORT;
	port1 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, start, start, 1,
	    RF_ACTIVE);
	if (port1 == NULL) {
		device_printf(dev, "cannot allocate status port resource\n");
		error = ENXIO;
		goto fail_port0;
	}

	error = atkbdc_probe_unit(device_get_unit(dev), port0, port1);
	if (error != 0)
		device_printf(dev, "atkbdc_porbe_unit failed\n");

	bus_release_resource(dev, SYS_RES_MEMORY, 1, port1);
 fail_port0:
	bus_release_resource(dev, SYS_RES_MEMORY, 0, port0);

	return (error);
}
Ejemplo n.º 16
0
static int
lbc_attach(device_t dev)
{
	struct lbc_softc *sc;
	struct rman *rm;
	const struct lbc_resource *lbcres;
	int error;

	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_bst = rman_get_bustag(sc->sc_res);
	sc->sc_bsh = rman_get_bushandle(sc->sc_res);

	rm = &sc->sc_rman;
	rm->rm_type = RMAN_ARRAY;
	rm->rm_descr = "MPC85XX 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;
	}

	/*
	 * 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
	 */
	lbc_write_reg(sc, LBC85XX_LBCR, 0x00000000);

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

	lbcres = mpc85xx_lbc_resources;

	for (; lbcres->lbr_devtype; lbcres++)
		if (!lbc_mk_child(dev, lbcres)) {
			error = ENXIO;
			goto fail;
		}

	return (bus_generic_attach(dev));

fail:
	bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res);
	return (error);
}
Ejemplo n.º 17
0
int
hme_pci_attach(device_t dev)
{
	struct hme_pci_softc *hsc;
	struct hme_softc *sc;
	bus_space_tag_t	memt;
	bus_space_handle_t memh;
	int i, error = 0;
#if !(defined(__powerpc__) || defined(__sparc64__))
	device_t *children, ebus_dev;
	struct resource *ebus_rres;
	int j, slot;
#endif

	pci_enable_busmaster(dev);
	/*
	 * Some Sun HMEs do have their intpin register bogusly set to 0,
	 * although it should be 1.  Correct that.
	 */
	if (pci_get_intpin(dev) == 0)
		pci_set_intpin(dev, 1);

	hsc = device_get_softc(dev);
	sc = &hsc->hsc_hme;
	sc->sc_dev = dev;
	sc->sc_flags |= HME_PCI;
	mtx_init(&sc->sc_lock, device_get_nameunit(dev), MTX_NETWORK_LOCK,
	    MTX_DEF);

	/*
	 * Map five register banks:
	 *
	 *	bank 0: HME SEB registers:	+0x0000
	 *	bank 1: HME ETX registers:	+0x2000
	 *	bank 2: HME ERX registers:	+0x4000
	 *	bank 3: HME MAC registers:	+0x6000
	 *	bank 4: HME MIF registers:	+0x7000
	 *
	 */
	i = PCIR_BAR(0);
	hsc->hsc_sres = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
	    &i, RF_ACTIVE);
	if (hsc->hsc_sres == NULL) {
		device_printf(dev, "could not map device registers\n");
		error = ENXIO;
		goto fail_mtx;
	}
	i = 0;
	hsc->hsc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ,
	    &i, RF_SHAREABLE | RF_ACTIVE);
	if (hsc->hsc_ires == NULL) {
		device_printf(dev, "could not allocate interrupt\n");
		error = ENXIO;
		goto fail_sres;
	}
	memt = rman_get_bustag(hsc->hsc_sres);
	memh = rman_get_bushandle(hsc->hsc_sres);
	sc->sc_sebt = sc->sc_etxt = sc->sc_erxt = sc->sc_mact = sc->sc_mift =
	    memt;
	bus_space_subregion(memt, memh, 0x0000, 0x1000, &sc->sc_sebh);
	bus_space_subregion(memt, memh, 0x2000, 0x1000, &sc->sc_etxh);
	bus_space_subregion(memt, memh, 0x4000, 0x1000, &sc->sc_erxh);
	bus_space_subregion(memt, memh, 0x6000, 0x1000, &sc->sc_mach);
	bus_space_subregion(memt, memh, 0x7000, 0x1000, &sc->sc_mifh);

#if defined(__powerpc__) || defined(__sparc64__)
	OF_getetheraddr(dev, sc->sc_enaddr);
#else
	/*
	 * Dig out VPD (vital product data) and read NA (network address).
	 *
	 * The PCI HME is a PCIO chip, which is composed of two functions:
	 *	function 0: PCI-EBus2 bridge, and
	 *	function 1: HappyMeal Ethernet controller.
	 *
	 * The VPD of HME resides in the Boot PROM (PCI FCode) attached
	 * to the EBus bridge and can't be accessed via the PCI capability
	 * pointer.
	 * ``Writing FCode 3.x Programs'' (newer ones, dated 1997 and later)
	 * chapter 2 describes the data structure.
	 *
	 * We don't have a MI EBus driver since no EBus device exists
	 * (besides the FCode PROM) on add-on HME boards.  The ``no driver
	 * attached'' message for function 0 therefore is what is expected.
	 */

#define	PCI_ROMHDR_SIZE			0x1c
#define	PCI_ROMHDR_SIG			0x00
#define	PCI_ROMHDR_SIG_MAGIC		0xaa55		/* little endian */
#define	PCI_ROMHDR_PTR_DATA		0x18
#define	PCI_ROM_SIZE			0x18
#define	PCI_ROM_SIG			0x00
#define	PCI_ROM_SIG_MAGIC		0x52494350	/* "PCIR", endian */
							/* reversed */
#define	PCI_ROM_VENDOR			0x04
#define	PCI_ROM_DEVICE			0x06
#define	PCI_ROM_PTR_VPD			0x08
#define	PCI_VPDRES_BYTE0		0x00
#define	PCI_VPDRES_ISLARGE(x)		((x) & 0x80)
#define	PCI_VPDRES_LARGE_NAME(x)	((x) & 0x7f)
#define	PCI_VPDRES_TYPE_VPD		0x10		/* large */
#define	PCI_VPDRES_LARGE_LEN_LSB	0x01
#define	PCI_VPDRES_LARGE_LEN_MSB	0x02
#define	PCI_VPDRES_LARGE_DATA		0x03
#define	PCI_VPD_SIZE			0x03
#define	PCI_VPD_KEY0			0x00
#define	PCI_VPD_KEY1			0x01
#define	PCI_VPD_LEN			0x02
#define	PCI_VPD_DATA			0x03

#define	HME_ROM_READ_N(n, offs)	bus_space_read_ ## n (memt, memh, (offs))
#define	HME_ROM_READ_1(offs)	HME_ROM_READ_N(1, (offs))
#define	HME_ROM_READ_2(offs)	HME_ROM_READ_N(2, (offs))
#define	HME_ROM_READ_4(offs)	HME_ROM_READ_N(4, (offs))

	/* Search accompanying EBus bridge. */
	slot = pci_get_slot(dev);
	if (device_get_children(device_get_parent(dev), &children, &i) != 0) {
		device_printf(dev, "could not get children\n");
		error = ENXIO;
		goto fail_sres;
	}
	ebus_dev = NULL;
	for (j = 0; j < i; j++) {
		if (pci_get_class(children[j]) == PCIC_BRIDGE &&
		    pci_get_vendor(children[j]) == PCI_VENDOR_SUN &&
		    pci_get_device(children[j]) == PCI_PRODUCT_SUN_EBUS &&
		    pci_get_slot(children[j]) == slot) {
			ebus_dev = children[j];
			break;
		}
	}
	if (ebus_dev == NULL) {
		device_printf(dev, "could not find EBus bridge\n");
		error = ENXIO;
		goto fail_children;
	}

	/* Map EBus bridge PROM registers. */
	i = PCIR_BAR(0);
	if ((ebus_rres = bus_alloc_resource_any(ebus_dev, SYS_RES_MEMORY,
	    &i, RF_ACTIVE)) == NULL) {
		device_printf(dev, "could not map PROM registers\n");
		error = ENXIO;
		goto fail_children;
	}
	memt = rman_get_bustag(ebus_rres);
	memh = rman_get_bushandle(ebus_rres);

	/* Read PCI Expansion ROM header. */
	if (HME_ROM_READ_2(PCI_ROMHDR_SIG) != PCI_ROMHDR_SIG_MAGIC ||
	    (i = HME_ROM_READ_2(PCI_ROMHDR_PTR_DATA)) < PCI_ROMHDR_SIZE) {
		device_printf(dev, "unexpected PCI Expansion ROM header\n");
		error = ENXIO;
		goto fail_rres;
	}

	/* Read PCI Expansion ROM data. */
	if (HME_ROM_READ_4(i + PCI_ROM_SIG) != PCI_ROM_SIG_MAGIC ||
	    HME_ROM_READ_2(i + PCI_ROM_VENDOR) != pci_get_vendor(dev) ||
	    HME_ROM_READ_2(i + PCI_ROM_DEVICE) != pci_get_device(dev) ||
	    (j = HME_ROM_READ_2(i + PCI_ROM_PTR_VPD)) < i + PCI_ROM_SIZE) {
		device_printf(dev, "unexpected PCI Expansion ROM data\n");
		error = ENXIO;
		goto fail_rres;
	}

	/*
	 * Read PCI VPD.
	 * SUNW,hme cards have a single large resource VPD-R tag
	 * containing one NA.  SUNW,qfe cards have four large resource
	 * VPD-R tags containing one NA each (all four HME chips share
	 * the same PROM).
	 * The VPD used on both cards is not in PCI 2.2 standard format
	 * however.  The length in the resource header is in big endian
	 * and the end tag is non-standard (0x79) and followed by an
	 * all-zero "checksum" byte.  Sun calls this a "Fresh Choice
	 * Ethernet" VPD...
	 */
	/* Look at the end tag to determine whether this is a VPD with 4 NAs. */
	if (HME_ROM_READ_1(j + PCI_VPDRES_LARGE_DATA + PCI_VPD_SIZE +
	    ETHER_ADDR_LEN) != 0x79 &&
	    HME_ROM_READ_1(j + 4 * (PCI_VPDRES_LARGE_DATA + PCI_VPD_SIZE +
	    ETHER_ADDR_LEN)) == 0x79)
		/* Use the Nth NA for the Nth HME on this SUNW,qfe. */
		j += slot * (PCI_VPDRES_LARGE_DATA + PCI_VPD_SIZE +
		    ETHER_ADDR_LEN);
	if (PCI_VPDRES_ISLARGE(HME_ROM_READ_1(j + PCI_VPDRES_BYTE0)) == 0 ||
	    PCI_VPDRES_LARGE_NAME(HME_ROM_READ_1(j + PCI_VPDRES_BYTE0)) !=
	    PCI_VPDRES_TYPE_VPD ||
	    (HME_ROM_READ_1(j + PCI_VPDRES_LARGE_LEN_LSB) << 8 |
	    HME_ROM_READ_1(j + PCI_VPDRES_LARGE_LEN_MSB)) !=
	    PCI_VPD_SIZE + ETHER_ADDR_LEN ||
	    HME_ROM_READ_1(j + PCI_VPDRES_LARGE_DATA + PCI_VPD_KEY0) !=
	    0x4e /* N */ ||
	    HME_ROM_READ_1(j + PCI_VPDRES_LARGE_DATA + PCI_VPD_KEY1) !=
	    0x41 /* A */ ||
	    HME_ROM_READ_1(j + PCI_VPDRES_LARGE_DATA + PCI_VPD_LEN) !=
	    ETHER_ADDR_LEN) {
		device_printf(dev, "unexpected PCI VPD\n");
		error = ENXIO;
		goto fail_rres;
	}
	bus_space_read_region_1(memt, memh, j + PCI_VPDRES_LARGE_DATA +
	    PCI_VPD_DATA, sc->sc_enaddr, ETHER_ADDR_LEN);

fail_rres:
	bus_release_resource(ebus_dev, SYS_RES_MEMORY,
	    rman_get_rid(ebus_rres), ebus_rres);
fail_children:
	free(children, M_TEMP);
	if (error != 0)
		goto fail_sres;
#endif

	sc->sc_burst = 64;	/* XXX */

	/*
	 * call the main configure
	 */
	if ((error = hme_config(sc)) != 0) {
		device_printf(dev, "could not be configured\n");
		goto fail_ires;
	}

	if ((error = bus_setup_intr(dev, hsc->hsc_ires, INTR_TYPE_NET |
	    INTR_MPSAFE, NULL, hme_intr, sc, &hsc->hsc_ih)) != 0) {
		device_printf(dev, "couldn't establish interrupt\n");
		hme_detach(sc);
		goto fail_ires;
	}
	return (0);

fail_ires:
	bus_release_resource(dev, SYS_RES_IRQ,
	    rman_get_rid(hsc->hsc_ires), hsc->hsc_ires);
fail_sres:
	bus_release_resource(dev, SYS_RES_MEMORY,
	    rman_get_rid(hsc->hsc_sres), hsc->hsc_sres);
fail_mtx:
	mtx_destroy(&sc->sc_lock);
	return (error);
}
Ejemplo n.º 18
0
static int
gx_attach(device_t dev)
{
	struct ifnet *ifp;
	struct gx_softc *sc;
	uint8_t mac[6];
	int error;
	int rid;

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

	/* Read MAC address.  */
	GXEMUL_ETHER_DEV_WRITE(GXEMUL_ETHER_DEV_MAC, (uintptr_t)mac);

	/* Allocate and establish interrupt.  */
	rid = 0;
	sc->sc_intr = bus_alloc_resource(sc->sc_dev, SYS_RES_IRQ, &rid,
	    GXEMUL_ETHER_DEV_IRQ - 2, GXEMUL_ETHER_DEV_IRQ - 2, 1, RF_ACTIVE);
	if (sc->sc_intr == NULL) {
		device_printf(dev, "unable to allocate IRQ.\n");
		return (ENXIO);
	}

	error = bus_setup_intr(sc->sc_dev, sc->sc_intr, INTR_TYPE_NET, NULL,
	    gx_rx_intr, sc, &sc->sc_intr_cookie);
	if (error != 0) {
		device_printf(dev, "unable to setup interrupt.\n");
		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_intr);
		return (ENXIO);
	}

	bus_describe_intr(sc->sc_dev, sc->sc_intr, sc->sc_intr_cookie, "rx");

	ifp = if_alloc(IFT_ETHER);
	if (ifp == NULL) {
		device_printf(dev, "cannot allocate ifnet.\n");
		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_intr);
		return (ENOMEM);
	}

	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
	ifp->if_mtu = ETHERMTU;
	ifp->if_init = gx_init;
	ifp->if_softc = sc;
	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | IFF_ALLMULTI;
	ifp->if_ioctl = gx_ioctl;

	sc->sc_ifp = ifp;
	sc->sc_flags = ifp->if_flags;

	ifmedia_init(&sc->sc_ifmedia, 0, gx_medchange, gx_medstat);

	ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_AUTO, 0, NULL);
	ifmedia_set(&sc->sc_ifmedia, IFM_ETHER | IFM_AUTO);

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

	ether_ifattach(ifp, mac);

	ifp->if_transmit = gx_transmit;

	return (bus_generic_attach(dev));
}
Ejemplo n.º 19
0
static int
sb8xx_attach(device_t dev)
{
	static const int	AMDSB_PMIO_INDEX = 0xcd6;
	static const int	AMDSB_PMIO_WIDTH = 2;
	static const int	AMDSB8_SMBUS_ADDR = 0x2c;
	static const int		AMDSB8_SMBUS_EN = 0x01;
	static const int		AMDSB8_SMBUS_ADDR_MASK = ~0x1fu;
	static const int	AMDSB_SMBIO_WIDTH = 0x14;
	static const int	AMDSB_SMBUS_CFG = 0x10;
	static const int		AMDSB_SMBUS_IRQ = 0x01;
	static const int		AMDSB_SMBUS_REV_MASK = ~0x0fu;
	static const int		AMDSB_SMBUS_REV_SHIFT = 4;
	static const int	AMDSB_IO_RID = 0;

	struct intsmb_softc	*sc;
	struct resource		*res;
	uint16_t		addr;
	uint8_t			cfg;
	int			rid;
	int			rc;

	sc = device_get_softc(dev);
	rid = AMDSB_IO_RID;
	rc = bus_set_resource(dev, SYS_RES_IOPORT, rid, AMDSB_PMIO_INDEX,
	    AMDSB_PMIO_WIDTH);
	if (rc != 0) {
		device_printf(dev, "bus_set_resource for PM IO failed\n");
		return (ENXIO);
	}
	res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
	    RF_ACTIVE | RF_SHAREABLE);
	if (res == NULL) {
		device_printf(dev, "bus_alloc_resource for PM IO failed\n");
		return (ENXIO);
	}

	addr = sb8xx_pmio_read(res, AMDSB8_SMBUS_ADDR + 1);
	addr <<= 8;
	addr |= sb8xx_pmio_read(res, AMDSB8_SMBUS_ADDR);

	bus_release_resource(dev, SYS_RES_IOPORT, rid, res);
	bus_delete_resource(dev, SYS_RES_IOPORT, rid);

	if ((addr & AMDSB8_SMBUS_EN) == 0) {
		device_printf(dev, "SB8xx SMBus not enabled\n");
		return (ENXIO);
	}

	addr &= AMDSB8_SMBUS_ADDR_MASK;
	sc->io_rid = AMDSB_IO_RID;
	rc = bus_set_resource(dev, SYS_RES_IOPORT, sc->io_rid, addr,
	    AMDSB_SMBIO_WIDTH);
	if (rc != 0) {
		device_printf(dev, "bus_set_resource for SMBus IO failed\n");
		return (ENXIO);
	}
	if (res == NULL) {
		device_printf(dev, "bus_alloc_resource for SMBus IO failed\n");
		return (ENXIO);
	}
	sc->io_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->io_rid,
	    RF_ACTIVE | RF_SHAREABLE);
	cfg = bus_read_1(sc->io_res, AMDSB_SMBUS_CFG);

	sc->poll = 1;
	device_printf(dev, "intr %s disabled ",
	    (cfg & AMDSB_SMBUS_IRQ) != 0 ? "IRQ" : "SMI");
	printf("revision %d\n",
	    (cfg & AMDSB_SMBUS_REV_MASK) >> AMDSB_SMBUS_REV_SHIFT);

	return (0);
}
Ejemplo n.º 20
0
int
scc_bfe_attach(device_t dev, u_int ipc)
{
	struct resource_list_entry *rle;
	struct scc_chan *ch;
	struct scc_class *cl;
	struct scc_mode *m;
	struct scc_softc *sc, *sc0;
	const char *sep;
	bus_space_handle_t bh;
	u_long base, size, start, sz;
	int c, error, mode, sysdev;

	/*
	 * The sc_class field defines the type of SCC we're going to work
	 * with and thus the size of the softc. Replace the generic softc
	 * with one that matches the SCC now that we're certain we handle
	 * the device.
	 */
	sc0 = device_get_softc(dev);
	cl = sc0->sc_class;
	if (cl->size > sizeof(*sc)) {
		sc = malloc(cl->size, M_SCC, M_WAITOK|M_ZERO);
		bcopy(sc0, sc, sizeof(*sc));
		device_set_softc(dev, sc);
	} else
		sc = sc0;

	size = abs(cl->cl_range) << sc->sc_bas.regshft;

	mtx_init(&sc->sc_hwmtx, "scc_hwmtx", NULL, MTX_SPIN);

	/*
	 * Re-allocate. We expect that the softc contains the information
	 * collected by scc_bfe_probe() intact.
	 */
	sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, &sc->sc_rrid,
	    0, ~0, cl->cl_channels * size, RF_ACTIVE);
	if (sc->sc_rres == NULL)
		return (ENXIO);
	sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres);
	sc->sc_bas.bst = rman_get_bustag(sc->sc_rres);

	/*
	 * Allocate interrupt resources. There may be a different interrupt
	 * per channel. We allocate them all...
	 */
	sc->sc_chan = malloc(sizeof(struct scc_chan) * cl->cl_channels,
	    M_SCC, M_WAITOK | M_ZERO);
	for (c = 0; c < cl->cl_channels; c++) {
		ch = &sc->sc_chan[c];
		/*
		 * XXX temporary hack. If we have more than 1 interrupt
		 * per channel, allocate the first for the channel. At
		 * this time only the macio bus front-end has more than
		 * 1 interrupt per channel and we don't use the 2nd and
		 * 3rd, because we don't support DMA yet.
		 */
		ch->ch_irid = c * ipc;
		ch->ch_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ,
		    &ch->ch_irid, RF_ACTIVE | RF_SHAREABLE);
		if (ipc == 0)
			break;
	}

	/*
	 * Create the control structures for our children. Probe devices
	 * and query them to see if we can reset the hardware.
	 */
	sysdev = 0;
	base = rman_get_start(sc->sc_rres);
	sz = (size != 0) ? size : rman_get_size(sc->sc_rres);
	start = base + ((cl->cl_range < 0) ? size * (cl->cl_channels - 1) : 0);
	for (c = 0; c < cl->cl_channels; c++) {
		ch = &sc->sc_chan[c];
		resource_list_init(&ch->ch_rlist);
		ch->ch_nr = c + 1;

		if (!SCC_ENABLED(sc, ch))
			goto next;

		ch->ch_enabled = 1;
		resource_list_add(&ch->ch_rlist, sc->sc_rtype, 0, start,
		    start + sz - 1, sz);
		rle = resource_list_find(&ch->ch_rlist, sc->sc_rtype, 0);
		rle->res = &ch->ch_rres;
		bus_space_subregion(rman_get_bustag(sc->sc_rres),
		    rman_get_bushandle(sc->sc_rres), start - base, sz, &bh);
		rman_set_bushandle(rle->res, bh);
		rman_set_bustag(rle->res, rman_get_bustag(sc->sc_rres));

		resource_list_add(&ch->ch_rlist, SYS_RES_IRQ, 0, c, c, 1);
		rle = resource_list_find(&ch->ch_rlist, SYS_RES_IRQ, 0);
		rle->res = (ch->ch_ires != NULL) ? ch->ch_ires :
			    sc->sc_chan[0].ch_ires;

		for (mode = 0; mode < SCC_NMODES; mode++) {
			m = &ch->ch_mode[mode];
			m->m_chan = ch;
			m->m_mode = 1U << mode;
			if ((cl->cl_modes & m->m_mode) == 0 || ch->ch_sysdev)
				continue;
			m->m_dev = device_add_child(dev, NULL, -1);
			device_set_ivars(m->m_dev, (void *)m);
			error = device_probe_child(dev, m->m_dev);
			if (!error) {
				m->m_probed = 1;
				m->m_sysdev = SERDEV_SYSDEV(m->m_dev) ? 1 : 0;
				ch->ch_sysdev |= m->m_sysdev;
			}
		}

	 next:
		start += (cl->cl_range < 0) ? -size : size;
		sysdev |= ch->ch_sysdev;
	}

	/*
	 * Have the hardware driver initialize the hardware. Tell it
	 * whether or not a hardware reset should be performed.
	 */
	if (bootverbose) {
		device_printf(dev, "%sresetting hardware\n",
		    (sysdev) ? "not " : "");
	}
	error = SCC_ATTACH(sc, !sysdev);
	if (error)
		goto fail;

	/*
	 * Setup our interrupt handler. Make it FAST under the assumption
	 * that our children's are fast as well. We make it MPSAFE as soon
	 * as a child sets up a MPSAFE interrupt handler.
	 * Of course, if we can't setup a fast handler, we make it MPSAFE
	 * right away.
	 */
	for (c = 0; c < cl->cl_channels; c++) {
		ch = &sc->sc_chan[c];
		if (ch->ch_ires == NULL)
			continue;
		error = bus_setup_intr(dev, ch->ch_ires,
		    INTR_TYPE_TTY, scc_bfe_intr, NULL, sc,
		    &ch->ch_icookie);
		if (error) {
			error = bus_setup_intr(dev, ch->ch_ires,
			    INTR_TYPE_TTY | INTR_MPSAFE, NULL,
			    (driver_intr_t *)scc_bfe_intr, sc, &ch->ch_icookie);
		} else
			sc->sc_fastintr = 1;

		if (error) {
			device_printf(dev, "could not activate interrupt\n");
			bus_release_resource(dev, SYS_RES_IRQ, ch->ch_irid,
			    ch->ch_ires);
			ch->ch_ires = NULL;
		}
	}
	sc->sc_polled = 1;
	for (c = 0; c < cl->cl_channels; c++) {
		if (sc->sc_chan[0].ch_ires != NULL)
			sc->sc_polled = 0;
	}

	/*
	 * Attach all child devices that were probed successfully.
	 */
	for (c = 0; c < cl->cl_channels; c++) {
		ch = &sc->sc_chan[c];
		for (mode = 0; mode < SCC_NMODES; mode++) {
			m = &ch->ch_mode[mode];
			if (!m->m_probed)
				continue;
			error = device_attach(m->m_dev);
			if (error)
				continue;
			m->m_attached = 1;
		}
	}

	if (bootverbose && (sc->sc_fastintr || sc->sc_polled)) {
		sep = "";
		device_print_prettyname(dev);
		if (sc->sc_fastintr) {
			printf("%sfast interrupt", sep);
			sep = ", ";
		}
		if (sc->sc_polled) {
			printf("%spolled mode", sep);
			sep = ", ";
		}
		printf("\n");
	}

	return (0);

 fail:
	for (c = 0; c < cl->cl_channels; c++) {
		ch = &sc->sc_chan[c];
		if (ch->ch_ires == NULL)
			continue;
		bus_release_resource(dev, SYS_RES_IRQ, ch->ch_irid,
		    ch->ch_ires);
	}
	bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
	return (error);
}
Ejemplo n.º 21
0
static int 
vx_pci_attach(device_t dev)
{
    struct vx_softc *sc = device_get_softc(dev);
    struct ifnet *ifp = &sc->arpcom.ac_if;
    int rid;

    rid = PCIR_MAPS;
    sc->vx_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
	RF_ACTIVE);

    if (sc->vx_res == NULL)
	goto bad;

    sc->vx_btag = rman_get_bustag(sc->vx_res);
    sc->vx_bhandle = rman_get_bushandle(sc->vx_res);

    rid = 0;
    sc->vx_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
	RF_SHAREABLE | RF_ACTIVE);

    if (sc->vx_irq == NULL)
	goto bad;

    if (vxattach(dev) == 0) {
	goto bad;
    }

    /* defect check for 3C590 */
    if (pci_get_device(dev) == PCI_PRODUCT_3COM_3C590) {
	GO_WINDOW(0);
	if (vxbusyeeprom(sc))
	    goto bad;
	CSR_WRITE_2(sc, VX_W0_EEPROM_COMMAND,
	    EEPROM_CMD_RD | EEPROM_SOFT_INFO_2);
	if (vxbusyeeprom(sc))
	    goto bad;
	if (!(CSR_READ_2(sc, VX_W0_EEPROM_DATA) & NO_RX_OVN_ANOMALY)) {
	    kprintf("Warning! Defective early revision adapter!\n");
	}
    }

    ifq_set_cpuid(&ifp->if_snd, rman_get_cpuid(sc->vx_irq));

    if (bus_setup_intr(dev, sc->vx_irq, INTR_MPSAFE,
		       vxintr, sc, &sc->vx_intrhand, 
		       ifp->if_serializer)
    ) {
	ether_ifdetach(&sc->arpcom.ac_if);
	goto bad;
    }

    return(0);

bad:
    if (sc->vx_res != NULL)
	bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->vx_res);
    if (sc->vx_irq != NULL)
	bus_release_resource(dev, SYS_RES_IRQ, 0, sc->vx_irq);
    return(ENXIO);
}
Ejemplo n.º 22
0
static int
terasic_mtl_nexus_attach(device_t dev)
{
	struct terasic_mtl_softc *sc;
	u_long pixel_maddr, text_maddr, reg_maddr;
	u_long pixel_msize, text_msize, reg_msize;
	int error;

	sc = device_get_softc(dev);
	sc->mtl_dev = dev;
	sc->mtl_unit = device_get_unit(dev);

	/*
	 * Query non-standard hints to find the locations of our two memory
	 * regions.  Enforce certain alignment and size requirements.
	 */
	if (resource_long_value(device_get_name(dev), device_get_unit(dev),
	    "reg_maddr", &reg_maddr) != 0 || (reg_maddr % PAGE_SIZE != 0)) {
		device_printf(dev, "improper register address");
		return (ENXIO);
	}
	if (resource_long_value(device_get_name(dev), device_get_unit(dev),
	    "reg_msize", &reg_msize) != 0 || (reg_msize % PAGE_SIZE != 0)) {
		device_printf(dev, "improper register size");
		return (ENXIO);
	}
	if (resource_long_value(device_get_name(dev), device_get_unit(dev),
	    "pixel_maddr", &pixel_maddr) != 0 ||
	    (pixel_maddr % PAGE_SIZE != 0)) {
		device_printf(dev, "improper pixel frame buffer address");
		return (ENXIO);
	}
	if (resource_long_value(device_get_name(dev), device_get_unit(dev),
	    "pixel_msize", &pixel_msize) != 0 ||
	    (pixel_msize % PAGE_SIZE != 0)) {
		device_printf(dev, "improper pixel frame buffer size");
		return (ENXIO);
	}
	if (resource_long_value(device_get_name(dev), device_get_unit(dev),
	    "text_maddr", &text_maddr) != 0 ||
	    (text_maddr % PAGE_SIZE != 0)) {
		device_printf(dev, "improper text frame buffer address");
		return (ENXIO);
	}
	if (resource_long_value(device_get_name(dev), device_get_unit(dev),
	    "text_msize", &text_msize) != 0 ||
	    (text_msize % PAGE_SIZE != 0)) {
		device_printf(dev, "improper text frame buffer size");
		return (ENXIO);
	}

	/*
	 * Allocate resources.
	 */
	sc->mtl_reg_rid = 0;
	sc->mtl_reg_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
	    &sc->mtl_reg_rid, reg_maddr, reg_maddr + reg_msize - 1,
	    reg_msize, RF_ACTIVE);
	if (sc->mtl_reg_res == NULL) {
		device_printf(dev, "couldn't map register memory\n");
		error = ENXIO;
		goto error;
	}
	device_printf(sc->mtl_dev, "registers at mem %p-%p\n",
	    (void *)reg_maddr, (void *)(reg_maddr + reg_msize));
	sc->mtl_pixel_rid = 0;
	sc->mtl_pixel_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
	    &sc->mtl_pixel_rid, pixel_maddr, pixel_maddr + pixel_msize - 1,
	    pixel_msize, RF_ACTIVE);
	if (sc->mtl_pixel_res == NULL) {
		device_printf(dev, "couldn't map pixel memory\n");
		error = ENXIO;
		goto error;
	}
	device_printf(sc->mtl_dev, "pixel frame buffer at mem %p-%p\n",
	    (void *)pixel_maddr, (void *)(pixel_maddr + pixel_msize));
	sc->mtl_text_rid = 0;
	sc->mtl_text_res = bus_alloc_resource(dev, SYS_RES_MEMORY,
	    &sc->mtl_text_rid, text_maddr, text_maddr + text_msize - 1,
	    text_msize, RF_ACTIVE);
	if (sc->mtl_text_res == NULL) {
		device_printf(dev, "couldn't map text memory\n");
		error = ENXIO;
		goto error;
	}
	device_printf(sc->mtl_dev, "text frame buffer at mem %p-%p\n",
	    (void *)text_maddr, (void *)(text_maddr + text_msize));
	error = terasic_mtl_attach(sc);
	if (error == 0)
		return (0);
error:
	if (sc->mtl_text_res != NULL)
		bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_text_rid,
		    sc->mtl_text_res);
	if (sc->mtl_pixel_res != NULL)
		bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_pixel_rid,
		    sc->mtl_pixel_res);
	if (sc->mtl_reg_res != NULL)
		bus_release_resource(dev, SYS_RES_MEMORY, sc->mtl_reg_rid,
		    sc->mtl_reg_res);
	return (error);
}
Ejemplo n.º 23
0
static int
acpi_ec_attach(device_t dev)
{
    struct acpi_ec_softc	*sc;
    struct acpi_ec_params	*params;
    ACPI_STATUS			Status;

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

    /* Fetch/initialize softc (assumes softc is pre-zeroed). */
    sc = device_get_softc(dev);
    params = acpi_get_private(dev);
    sc->ec_dev = dev;
    sc->ec_handle = acpi_get_handle(dev);

    /* Retrieve previously probed values via device ivars. */
    sc->ec_glk = params->glk;
    sc->ec_gpebit = params->gpe_bit;
    sc->ec_gpehandle = params->gpe_handle;
    sc->ec_uid = params->uid;
    sc->ec_suspending = FALSE;
    acpi_set_private(dev, NULL);
    free(params, M_TEMP);

    /* Attach bus resources for data and command/status ports. */
    sc->ec_data_rid = 0;
    sc->ec_data_res = bus_alloc_resource_any(sc->ec_dev, SYS_RES_IOPORT,
			&sc->ec_data_rid, RF_ACTIVE);
    if (sc->ec_data_res == NULL) {
	device_printf(dev, "can't allocate data port\n");
	goto error;
    }
    sc->ec_data_tag = rman_get_bustag(sc->ec_data_res);
    sc->ec_data_handle = rman_get_bushandle(sc->ec_data_res);

    sc->ec_csr_rid = 1;
    sc->ec_csr_res = bus_alloc_resource_any(sc->ec_dev, SYS_RES_IOPORT,
			&sc->ec_csr_rid, RF_ACTIVE);
    if (sc->ec_csr_res == NULL) {
	device_printf(dev, "can't allocate command/status port\n");
	goto error;
    }
    sc->ec_csr_tag = rman_get_bustag(sc->ec_csr_res);
    sc->ec_csr_handle = rman_get_bushandle(sc->ec_csr_res);

    /*
     * Install a handler for this EC's GPE bit.  We want edge-triggered
     * behavior.
     */
    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching GPE handler\n"));
    Status = AcpiInstallGpeHandler(sc->ec_gpehandle, sc->ec_gpebit,
		ACPI_GPE_EDGE_TRIGGERED, EcGpeHandler, sc);
    if (ACPI_FAILURE(Status)) {
	device_printf(dev, "can't install GPE handler for %s - %s\n",
		      acpi_name(sc->ec_handle), AcpiFormatException(Status));
	goto error;
    }

    /*
     * Install address space handler
     */
    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching address space handler\n"));
    Status = AcpiInstallAddressSpaceHandler(sc->ec_handle, ACPI_ADR_SPACE_EC,
		&EcSpaceHandler, &EcSpaceSetup, sc);
    if (ACPI_FAILURE(Status)) {
	device_printf(dev, "can't install address space handler for %s - %s\n",
		      acpi_name(sc->ec_handle), AcpiFormatException(Status));
	goto error;
    }

    /* Enable runtime GPEs for the handler. */
    Status = AcpiEnableGpe(sc->ec_gpehandle, sc->ec_gpebit);
    if (ACPI_FAILURE(Status)) {
	device_printf(dev, "AcpiEnableGpe failed: %s\n",
		      AcpiFormatException(Status));
	goto error;
    }

    ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "acpi_ec_attach complete\n"));
    return (0);

error:
    AcpiRemoveGpeHandler(sc->ec_gpehandle, sc->ec_gpebit, EcGpeHandler);
    AcpiRemoveAddressSpaceHandler(sc->ec_handle, ACPI_ADR_SPACE_EC,
	EcSpaceHandler);
    if (sc->ec_csr_res)
	bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_csr_rid,
			     sc->ec_csr_res);
    if (sc->ec_data_res)
	bus_release_resource(sc->ec_dev, SYS_RES_IOPORT, sc->ec_data_rid,
			     sc->ec_data_res);
    return (ENXIO);
}
Ejemplo n.º 24
0
static int
acpi_hpet_attach(device_t dev)
{
	struct acpi_hpet_softc *sc;
	int rid;
	uint32_t val, val2;
	uintmax_t freq;

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

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

	rid = 0;
	sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
					     RF_ACTIVE);
	if (sc->mem_res == NULL) {
		/*
		 * We only need to make sure that main counter
		 * is accessable.
		 */
		device_printf(dev, "can't map %dB register space, try %dB\n",
			      HPET_MEM_WIDTH, HPET_MEM_WIDTH_MIN);
		rid = 0;
		sc->mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
				acpi_hpet_res_start,
				acpi_hpet_res_start + HPET_MEM_WIDTH_MIN - 1,
				HPET_MEM_WIDTH_MIN, RF_ACTIVE);
		if (sc->mem_res == NULL)
			return ENOMEM;
	}

	/* Validate that we can access the whole region. */
	if (rman_get_size(sc->mem_res) < HPET_MEM_WIDTH_MIN) {
		device_printf(dev, "memory region width %ld too small\n",
			      rman_get_size(sc->mem_res));
		bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->mem_res);
		return ENXIO;
	}

	acpi_hpet_bsh = rman_get_bushandle(sc->mem_res);
	acpi_hpet_bst = rman_get_bustag(sc->mem_res);

	/* Be sure timer is enabled. */
	acpi_hpet_enable(sc);

	/* Read basic statistics about the timer. */
	val = bus_space_read_4(acpi_hpet_bst, acpi_hpet_bsh, HPET_PERIOD);
	if (val == 0) {
		device_printf(dev, "invalid period\n");
		acpi_hpet_disable(sc);
		bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->mem_res);
		return ENXIO;
	}

	freq = (1000000000000000LL + val / 2) / val;
	if (bootverbose) {
		val = bus_space_read_4(acpi_hpet_bst, acpi_hpet_bsh,
				       HPET_CAPABILITIES);
		device_printf(dev,
		    "vend: 0x%x, rev: 0x%x, num: %d, opts:%s%s\n",
		    val >> 16, val & HPET_CAP_REV_ID,
		    (val & HPET_CAP_NUM_TIM) >> 8,
		    (val & HPET_CAP_LEG_RT) ? " legacy_route" : "",
		    (val & HPET_CAP_COUNT_SIZE) ? " 64-bit" : "");
	}

	if (ktestenv("debug.acpi.hpet_test"))
		acpi_hpet_test(sc);

	/*
	 * Don't attach if the timer never increments.  Since the spec
	 * requires it to be at least 10 MHz, it has to change in 1 us.
	 */
	val = bus_space_read_4(acpi_hpet_bst, acpi_hpet_bsh,
			       HPET_MAIN_COUNTER);
	DELAY(1);
	val2 = bus_space_read_4(acpi_hpet_bst, acpi_hpet_bsh,
				HPET_MAIN_COUNTER);
	if (val == val2) {
		device_printf(dev, "HPET never increments, disabling\n");
		acpi_hpet_disable(sc);
		bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->mem_res);
		return ENXIO;
	}

	acpi_hpet_timer.freq = freq;
	device_printf(dev, "frequency %u\n", acpi_hpet_timer.freq);

	cputimer_register(&acpi_hpet_timer);
	cputimer_select(&acpi_hpet_timer, 0);

	return 0;
}
Ejemplo n.º 25
0
static int
hme_sbus_attach(device_t dev)
{
	struct hme_sbus_softc *hsc;
	struct hme_softc *sc;
	u_long start, count;
	uint32_t burst;
	int i, error = 0;

	hsc = device_get_softc(dev);
	sc = &hsc->hsc_hme;
	mtx_init(&sc->sc_lock, device_get_nameunit(dev), MTX_NETWORK_LOCK,
	    MTX_DEF);
	/*
	 * Map five register banks:
	 *
	 *	bank 0: HME SEB registers
	 *	bank 1: HME ETX registers
	 *	bank 2: HME ERX registers
	 *	bank 3: HME MAC registers
	 *	bank 4: HME MIF registers
	 *
	 */
	i = 0;
	hsc->hsc_seb_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
	    &i, RF_ACTIVE);
	if (hsc->hsc_seb_res == NULL) {
		device_printf(dev, "cannot map SEB registers\n");
		error = ENXIO;
		goto fail_mtx_res;
	}
	sc->sc_sebt = rman_get_bustag(hsc->hsc_seb_res);
	sc->sc_sebh = rman_get_bushandle(hsc->hsc_seb_res);

	i = 1;
	hsc->hsc_etx_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
	    &i, RF_ACTIVE);
	if (hsc->hsc_etx_res == NULL) {
		device_printf(dev, "cannot map ETX registers\n");
		error = ENXIO;
		goto fail_seb_res;
	}
	sc->sc_etxt = rman_get_bustag(hsc->hsc_etx_res);
	sc->sc_etxh = rman_get_bushandle(hsc->hsc_etx_res);

	i = 2;
	hsc->hsc_erx_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
	    &i, RF_ACTIVE);
	if (hsc->hsc_erx_res == NULL) {
		device_printf(dev, "cannot map ERX registers\n");
		error = ENXIO;
		goto fail_etx_res;
	}
	sc->sc_erxt = rman_get_bustag(hsc->hsc_erx_res);
	sc->sc_erxh = rman_get_bushandle(hsc->hsc_erx_res);

	i = 3;
	hsc->hsc_mac_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
	    &i, RF_ACTIVE);
	if (hsc->hsc_mac_res == NULL) {
		device_printf(dev, "cannot map MAC registers\n");
		error = ENXIO;
		goto fail_erx_res;
	}
	sc->sc_mact = rman_get_bustag(hsc->hsc_mac_res);
	sc->sc_mach = rman_get_bushandle(hsc->hsc_mac_res);

	/*
	 * At least on some HMEs, the MIF registers seem to be inside the MAC
	 * range, so try to kludge around it.
	 */
	i = 4;
	hsc->hsc_mif_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
	    &i, RF_ACTIVE);
	if (hsc->hsc_mif_res == NULL) {
		if (bus_get_resource(dev, SYS_RES_MEMORY, i,
		    &start, &count) != 0) {
			device_printf(dev, "cannot get MIF registers\n");
			error = ENXIO;
			goto fail_mac_res;
		}
		if (start < rman_get_start(hsc->hsc_mac_res) ||
		    start + count - 1 > rman_get_end(hsc->hsc_mac_res)) {
			device_printf(dev, "cannot move MIF registers to MAC "
			    "bank\n");
			error = ENXIO;
			goto fail_mac_res;
		}
		sc->sc_mift = sc->sc_mact;
		bus_space_subregion(sc->sc_mact, sc->sc_mach,
		    start - rman_get_start(hsc->hsc_mac_res), count,
		    &sc->sc_mifh);
	} else {
		sc->sc_mift = rman_get_bustag(hsc->hsc_mif_res);
		sc->sc_mifh = rman_get_bushandle(hsc->hsc_mif_res);
	}

	i = 0;
	hsc->hsc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ,
	    &i, RF_SHAREABLE | RF_ACTIVE);
	if (hsc->hsc_ires == NULL) {
		device_printf(dev, "could not allocate interrupt\n");
		error = ENXIO;
		goto fail_mif_res;
	}

	OF_getetheraddr(dev, sc->sc_enaddr);

	burst = sbus_get_burstsz(dev);
	/* Translate into plain numerical format */
	if ((burst & SBUS_BURST_64))
		sc->sc_burst = 64;
	else if ((burst & SBUS_BURST_32))
		sc->sc_burst = 32;
	else if ((burst & SBUS_BURST_16))
		sc->sc_burst = 16;
	else
		 sc->sc_burst = 0;

	sc->sc_dev = dev;
	sc->sc_flags = 0;

	if ((error = hme_config(sc)) != 0) {
		device_printf(dev, "could not be configured\n");
		goto fail_ires;
	}

	if ((error = bus_setup_intr(dev, hsc->hsc_ires, INTR_TYPE_NET |
	    INTR_MPSAFE, NULL, hme_intr, sc, &hsc->hsc_ih)) != 0) {
		device_printf(dev, "couldn't establish interrupt\n");
		hme_detach(sc);
		goto fail_ires;
	}
	return (0);

fail_ires:
	bus_release_resource(dev, SYS_RES_IRQ,
	    rman_get_rid(hsc->hsc_ires), hsc->hsc_ires);
fail_mif_res:
	if (hsc->hsc_mif_res != NULL) {
		bus_release_resource(dev, SYS_RES_MEMORY,
		    rman_get_rid(hsc->hsc_mif_res), hsc->hsc_mif_res);
	}
fail_mac_res:
	bus_release_resource(dev, SYS_RES_MEMORY,
	    rman_get_rid(hsc->hsc_mac_res), hsc->hsc_mac_res);
fail_erx_res:
	bus_release_resource(dev, SYS_RES_MEMORY,
	    rman_get_rid(hsc->hsc_erx_res), hsc->hsc_erx_res);
fail_etx_res:
	bus_release_resource(dev, SYS_RES_MEMORY,
	    rman_get_rid(hsc->hsc_etx_res), hsc->hsc_etx_res);
fail_seb_res:
	bus_release_resource(dev, SYS_RES_MEMORY,
	    rman_get_rid(hsc->hsc_seb_res), hsc->hsc_seb_res);
fail_mtx_res:
	mtx_destroy(&sc->sc_lock);
	return (error);
}
Ejemplo n.º 26
0
static void
orm_identify(driver_t* driver, device_t parent)
{
	bus_space_handle_t	bh;
	bus_space_tag_t		bt;
	device_t		child;
	u_int32_t		chunk = IOMEM_START;
	struct resource		*res;
	int			rid;
	u_int32_t		rom_size;
	struct orm_softc	*sc;
	u_int8_t		buf[3];

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

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

	if (sc->rnum == 0)
		device_delete_child(parent, child);
	else if (sc->rnum == 1)
		device_set_desc(child, "ISA Option ROM");
	else
		device_set_desc(child, "ISA Option ROMs");
}
Ejemplo n.º 27
0
static int
pcf_ebus_attach(device_t dev)
{
	struct pcf_softc *sc;
	int rv = ENXIO;
	phandle_t node;
	uint64_t own_addr;

	sc = DEVTOSOFTC(dev);
	mtx_init(&sc->pcf_lock, device_get_nameunit(dev), "pcf", MTX_DEF);

	/* get OFW node of the pcf */
	if ((node = ofw_bus_get_node(dev)) == -1) {
		device_printf(dev, "cannot get OFW node\n");
		goto error;
	}

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

	sc->pcf_flags = device_get_flags(dev);

	/*
	 * XXX use poll-mode property?
	 */
	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;
		}
	}

	/*
	 * XXX on AXmp there's probably a second IRQ which is the fan fail
	 *     interrupt genererated by the PCF8574 at 0x78.
	 */

	/* get address of the pcf */
	if (OF_getprop(node, "own-address", &own_addr, sizeof(own_addr)) ==
	    -1) {
		device_printf(dev, "cannot get own address\n");
		goto error;
	}
	if (bootverbose)
		device_printf(dev, "PCF8584 address: 0x%08llx\n", (unsigned
		    long long)own_addr);

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

	if (sc->res_irq) {
		rv = bus_setup_intr(dev, sc->res_irq,
		    INTR_TYPE_NET /* | INTR_ENTROPY */, NULL, 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_release_resource(dev, SYS_RES_IRQ, sc->rid_irq,
		    sc->res_irq);
	}
	if (sc->res_ioport != 0) {
		bus_release_resource(dev, SYS_RES_MEMORY, sc->rid_ioport,
		    sc->res_ioport);
	}
	mtx_destroy(&sc->pcf_lock);
	return (rv);
}
Ejemplo n.º 28
0
static int
atkbdc_ebus_attach(device_t dev)
{
	atkbdc_softc_t *sc;
	atkbdc_device_t *adi;
	device_t cdev;
	phandle_t child;
	u_long count, intr, start;
	int children, error, rid, unit;
	char *cname, *dname;

	unit = device_get_unit(dev);
	sc = *(atkbdc_softc_t **)device_get_softc(dev);
	if (sc == NULL) {
		/*
		 * We have to maintain two copies of the kbdc_softc struct,
		 * as the low-level console needs to have access to the
		 * keyboard controller before kbdc is probed and attached.
		 * kbdc_soft[] contains the default entry for that purpose.
		 * See atkbdc.c. XXX
		 */
		sc = atkbdc_get_softc(unit);
		if (sc == NULL)
			return (ENOMEM);
		device_set_softc(dev, sc);
	}

	rid = 0;
	if (bus_get_resource(dev, SYS_RES_MEMORY, rid, &start, &count) != 0) {
		device_printf(dev,
		    "cannot determine command/data port resource\n");
		return (ENXIO);
	}
	sc->retry = 5000;
	sc->port0 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, start, start,
	    1, RF_ACTIVE);
	if (sc->port0 == NULL) {
		device_printf(dev,
		    "cannot allocate command/data port resource\n");
		return (ENXIO);
	}

	rid = 1;
	if (bus_get_resource(dev, SYS_RES_MEMORY, rid, &start, &count) != 0) {
		device_printf(dev, "cannot determine status port resource\n");
		error = ENXIO;
		goto fail_port0;
	}
	start += KBD_STATUS_PORT;
	sc->port1 = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, start, start,
	    1, RF_ACTIVE);
	if (sc->port1 == NULL) {
		device_printf(dev, "cannot allocate status port resource\n");
		error = ENXIO;
		goto fail_port0;
	}

	error = atkbdc_attach_unit(unit, sc, sc->port0, sc->port1);
	if (error != 0) {
		device_printf(dev, "atkbdc_attach_unit failed\n");
		goto fail_port1;
	}

	/* Attach children. */
	children = 0;
	for (child = OF_child(ofw_bus_get_node(dev)); child != 0;
	    child = OF_peer(child)) {
		if ((OF_getprop_alloc(child, "name", 1, (void **)&cname)) == -1)
			continue;
		if (children >= 2) {
			device_printf(dev,
			    "<%s>: only two children per 8042 supported\n",
			    cname);
			free(cname, M_OFWPROP);
			continue;
		}
		adi = malloc(sizeof(struct atkbdc_device), M_ATKBDDEV,
		    M_NOWAIT | M_ZERO);
		if (adi == NULL) {
			device_printf(dev, "<%s>: malloc failed\n", cname);
			free(cname, M_OFWPROP);
			continue;
		}
		if (strcmp(cname, "kb_ps2") == 0) {
			adi->rid = KBDC_RID_KBD;
			dname = ATKBD_DRIVER_NAME;
		} else if (strcmp(cname, "kdmouse") == 0) {
			adi->rid = KBDC_RID_AUX;
			dname = PSM_DRIVER_NAME;
		} else {
			device_printf(dev, "<%s>: unknown device\n", cname);
			free(adi, M_ATKBDDEV);
			free(cname, M_OFWPROP);
			continue;
		}
		intr = bus_get_resource_start(dev, SYS_RES_IRQ, adi->rid);
		if (intr == 0) {
			device_printf(dev,
			    "<%s>: cannot determine interrupt resource\n",
			    cname);
			free(adi, M_ATKBDDEV);
			free(cname, M_OFWPROP);
			continue;
		}
		resource_list_init(&adi->resources);
		resource_list_add(&adi->resources, SYS_RES_IRQ, adi->rid,
		    intr, intr, 1);
		if ((cdev = device_add_child(dev, dname, -1)) == NULL) {
			device_printf(dev, "<%s>: device_add_child failed\n",
			    cname);
			resource_list_free(&adi->resources);
			free(adi, M_ATKBDDEV);
			free(cname, M_OFWPROP);
			continue;
		}
		device_set_ivars(cdev, adi);
		children++;
	}

	error = bus_generic_attach(dev);
	if (error != 0) {
		device_printf(dev, "bus_generic_attach failed\n");
		goto fail_port1;
	}

	return (0);

 fail_port1:
	bus_release_resource(dev, SYS_RES_MEMORY, 1, sc->port1);
 fail_port0:
	bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->port0);

	return (error);
}
Ejemplo n.º 29
0
static int
wi_pci_attach(device_t dev)
{
	struct wi_softc		*sc;
	u_int32_t		command, wanted;
	u_int16_t		reg;
	int			error;
	int			timeout;

	wlan_serialize_enter();
	sc = device_get_softc(dev);

	command = pci_read_config(dev, PCIR_COMMAND, 4);
	wanted = PCIM_CMD_PORTEN|PCIM_CMD_MEMEN;
	command |= wanted;
	pci_write_config(dev, PCIR_COMMAND, command, 4);
	command = pci_read_config(dev, PCIR_COMMAND, 4);
	if ((command & wanted) != wanted) {
		device_printf(dev, "wi_pci_attach() failed to enable pci!\n");
		wlan_serialize_exit();
		return (ENXIO);
	}

	if (sc->wi_bus_type != WI_BUS_PCI_NATIVE) {
		error = wi_alloc(dev, WI_PCI_IORES);
		if (error) {
			wlan_serialize_exit();
			return (error);
		}

		/* Make sure interrupts are disabled. */
		CSR_WRITE_2(sc, WI_INT_EN, 0);
		CSR_WRITE_2(sc, WI_EVENT_ACK, 0xFFFF);

		/* We have to do a magic PLX poke to enable interrupts */
		sc->local_rid = WI_PCI_LOCALRES;
		sc->local = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
		    &sc->local_rid, RF_ACTIVE);
		sc->wi_localtag = rman_get_bustag(sc->local);
		sc->wi_localhandle = rman_get_bushandle(sc->local);
		command = bus_space_read_4(sc->wi_localtag, sc->wi_localhandle,
		    WI_LOCAL_INTCSR);
		command |= WI_LOCAL_INTEN;
		bus_space_write_4(sc->wi_localtag, sc->wi_localhandle,
		    WI_LOCAL_INTCSR, command);
		bus_release_resource(dev, SYS_RES_IOPORT, sc->local_rid,
		    sc->local);
		sc->local = NULL;

		sc->mem_rid = WI_PCI_MEMRES;
		sc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
					&sc->mem_rid, RF_ACTIVE);
		if (sc->mem == NULL) {
			device_printf(dev, "couldn't allocate memory\n");
			wi_free(dev);
			wlan_serialize_exit();
			return (ENXIO);
		}
		sc->wi_bmemtag = rman_get_bustag(sc->mem);
		sc->wi_bmemhandle = rman_get_bushandle(sc->mem);

		/*
		 * Write COR to enable PC card
		 * This is a subset of the protocol that the pccard bus code
		 * would do.  In theory, we should parse the CIS to find the
		 * COR offset.  In practice, the COR_OFFSET is always 0x3e0.
		 */
		CSM_WRITE_1(sc, WI_COR_OFFSET, WI_COR_VALUE); 
		reg = CSM_READ_1(sc, WI_COR_OFFSET);
		if (reg != WI_COR_VALUE) {
			device_printf(dev, "CSM_READ_1(WI_COR_OFFSET) "
			    "wanted %d, got %d\n", WI_COR_VALUE, reg);
			wi_free(dev);
			wlan_serialize_exit();
			return (ENXIO);
		}
	} else {
		error = wi_alloc(dev, WI_PCI_LMEMRES);
		if (error) {
			wlan_serialize_exit();
			return (error);
		}

		CSR_WRITE_2(sc, WI_PCICOR_OFF, WI_PCICOR_RESET);
		DELAY(250000);

		CSR_WRITE_2(sc, WI_PCICOR_OFF, 0x0000);
		DELAY(500000);

		timeout=2000000;
		while ((--timeout > 0) &&
		    (CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY))
			DELAY(10);

		if (timeout == 0) {
			device_printf(dev, "couldn't reset prism pci core.\n");
			wi_free(dev);
			wlan_serialize_exit();
			return(ENXIO);
		}
	}

	CSR_WRITE_2(sc, WI_HFA384X_SWSUPPORT0_OFF, WI_PRISM2STA_MAGIC);
	reg = CSR_READ_2(sc, WI_HFA384X_SWSUPPORT0_OFF);
	if (reg != WI_PRISM2STA_MAGIC) {
		device_printf(dev,
		    "CSR_READ_2(WI_HFA384X_SWSUPPORT0_OFF) "
		    "wanted %d, got %d\n", WI_PRISM2STA_MAGIC, reg);
		wi_free(dev);
		wlan_serialize_exit();
		return (ENXIO);
	}

	error = wi_attach(dev);
	if (error != 0)
		wi_free(dev);
	wlan_serialize_exit();
	return (error);
}
Ejemplo n.º 30
0
static int
xhci_pci_attach(device_t self)
{
	struct xhci_softc *sc = device_get_softc(self);
	int count, err, rid;
	uint8_t usedma32;

	rid = PCI_XHCI_CBMEM;
	sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid,
	    RF_ACTIVE);
	if (!sc->sc_io_res) {
		device_printf(self, "Could not map memory\n");
		return (ENOMEM);
	}
	sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
	sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
	sc->sc_io_size = rman_get_size(sc->sc_io_res);

	/* check for USB 3.0 controllers which don't support 64-bit DMA */
	switch (pci_get_devid(self)) {
	case 0x01941033:	/* NEC uPD720200 USB 3.0 controller */
		usedma32 = 1;
		break;
	default:
		usedma32 = 0;
		break;
	}

	if (xhci_init(sc, self, usedma32)) {
		device_printf(self, "Could not initialize softc\n");
		bus_release_resource(self, SYS_RES_MEMORY, PCI_XHCI_CBMEM,
		    sc->sc_io_res);
		return (ENXIO);
	}

	pci_enable_busmaster(self);

	usb_callout_init_mtx(&sc->sc_callout, &sc->sc_bus.bus_lock, 0);

	rid = 0;
	if (xhci_use_msi) {
		count = pci_msi_count(self);
		if (count >= 1) {
			count = 1;
			if (pci_alloc_msi(self, &rid, 1, count) == 0) {
				if (bootverbose)
					device_printf(self, "MSI enabled\n");
				sc->sc_irq_rid = 1;
			}
		}
	}
	sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ,
	    &sc->sc_irq_rid, RF_SHAREABLE | RF_ACTIVE);
	if (sc->sc_irq_res == NULL) {
		pci_release_msi(self);
		device_printf(self, "Could not allocate IRQ\n");
		/* goto error; FALLTHROUGH - use polling */
	}
	sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
	if (sc->sc_bus.bdev == NULL) {
		device_printf(self, "Could not add USB device\n");
		goto error;
	}
	device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);

	ksprintf(sc->sc_vendor, "0x%04x", pci_get_vendor(self));

	if (sc->sc_irq_res != NULL) {
		err = bus_setup_intr(self, sc->sc_irq_res, INTR_MPSAFE,
		    (driver_intr_t *)xhci_interrupt, sc, &sc->sc_intr_hdl, NULL);
		if (err != 0) {
			bus_release_resource(self, SYS_RES_IRQ,
			    rman_get_rid(sc->sc_irq_res), sc->sc_irq_res);
			sc->sc_irq_res = NULL;
			pci_release_msi(self);
			device_printf(self, "Could not setup IRQ, err=%d\n", err);
			sc->sc_intr_hdl = NULL;
		}
	}
	if (sc->sc_irq_res == NULL || sc->sc_intr_hdl == NULL) {
		if (xhci_use_polling() != 0) {
			device_printf(self, "Interrupt polling at %dHz\n", hz);
			USB_BUS_LOCK(&sc->sc_bus);
			xhci_interrupt_poll(sc);
			USB_BUS_UNLOCK(&sc->sc_bus);
		} else
			goto error;
	}

	/* On Intel chipsets reroute ports from EHCI to XHCI controller. */
	switch (pci_get_devid(self)) {
	case 0x0f358086:	/* BayTrail */
	case 0x9c318086:	/* Panther Point */
	case 0x1e318086:	/* Panther Point */
	case 0x8c318086:	/* Lynx Point */
	case 0x8cb18086:	/* Wildcat Point */
	case 0x9cb18086:	/* Wildcat Point-LP */
		sc->sc_port_route = &xhci_pci_port_route;
		sc->sc_imod_default = XHCI_IMOD_DEFAULT_LP;
		break;
	default:
		break;
	}

	xhci_pci_take_controller(self);

	err = xhci_halt_controller(sc);

	if (err == 0)
		err = xhci_start_controller(sc);

	if (err == 0)
		err = device_probe_and_attach(sc->sc_bus.bdev);

	if (err) {
		device_printf(self, "XHCI halt/start/probe failed err=%d\n", err);
		goto error;
	}
	return (0);

error:
	xhci_pci_detach(self);
	return (ENXIO);
}