void
malo_cardbus_attach(struct device *parent, struct device *self, void *aux)
{
    struct malo_cardbus_softc *csc = (struct malo_cardbus_softc *)self;
    struct cardbus_attach_args *ca = aux;
    struct malo_softc *sc = &csc->sc_malo;
    cardbus_devfunc_t ct = ca->ca_ct;
    bus_addr_t base;
    int error;

    sc->sc_dmat = ca->ca_dmat;
    csc->sc_ct = ct;
    csc->sc_tag = ca->ca_tag;
    csc->sc_intrline = ca->ca_intrline;

    /* power management hooks */
    sc->sc_enable = malo_cardbus_enable;
    sc->sc_disable = malo_cardbus_disable;
#if 0
    sc->sc_power = malo_cardbus_power;
#endif

    /* map control/status registers */
    error = Cardbus_mapreg_map(ct, CARDBUS_BASE0_REG,
                               CARDBUS_MAPREG_TYPE_MEM, 0, &sc->sc_mem1_bt,
                               &sc->sc_mem1_bh, &base, &csc->sc_mapsize1);
    if (error != 0) {
        printf(": could not map 1st memory space\n");
        return;
    }
    csc->sc_bar1_val = base | CARDBUS_MAPREG_TYPE_MEM;

    /* map control/status registers */
    error = Cardbus_mapreg_map(ct, CARDBUS_BASE1_REG,
                               CARDBUS_MAPREG_TYPE_MEM, 0, &sc->sc_mem2_bt,
                               &sc->sc_mem2_bh, &base, &csc->sc_mapsize2);
    if (error != 0) {
        printf(": could not map 2nd memory space\n");
        Cardbus_mapreg_unmap(ct, CARDBUS_BASE0_REG, sc->sc_mem1_bt,
                             sc->sc_mem1_bh, csc->sc_mapsize1);
        return;
    }
    csc->sc_bar2_val = base | CARDBUS_MAPREG_TYPE_MEM;

    /* set up the PCI configuration registers */
    malo_cardbus_setup(csc);

    printf(": irq %d", csc->sc_intrline);

    error = malo_attach(sc);
    if (error != 0)
        malo_cardbus_detach(&sc->sc_dev, 0);

    Cardbus_function_disable(ct);
}
static void
malo_pci_attach(device_t parent, device_t self, void *aux)
{
	struct malo_pci_softc *psc = device_private(self);
	struct pci_attach_args *pa = aux;
	struct malo_softc *sc = &psc->sc_malo;
	const char *intrstr = NULL;
	pci_intr_handle_t ih;
	pcireg_t memtype1, memtype2;
	int error;

	sc->sc_dev = self;
	sc->sc_dmat = pa->pa_dmat;
	psc->sc_pc = pa->pa_pc;

	aprint_normal("\n");
	aprint_normal_dev(self,"Marvell Libertas Wireless\n");

	/* map control / status registers */
	memtype1 = pci_mapreg_type(pa->pa_pc, pa->pa_tag, MALO_PCI_BAR1);
	switch (memtype1) {
	case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
	case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
		break;
	default:
		aprint_error_dev(self, "invalid base address register\n");
		return;
	}

	error = pci_mapreg_map(pa, MALO_PCI_BAR1,
	    memtype1, 0, &sc->sc_mem1_bt, &sc->sc_mem1_bh,
		NULL, &psc->sc_mapsize1);
	if (error != 0) {
		aprint_error_dev(self, "can't map 1st mem space\n");
		return;
	}

	/* map control / status registers */
	memtype2 = pci_mapreg_type(pa->pa_pc, pa->pa_tag, MALO_PCI_BAR1);
	switch (memtype2) {
	case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
	case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
		break;
	default:
		aprint_error_dev(self, "invalid base address register\n");
		return;
	}

	error = pci_mapreg_map(pa, MALO_PCI_BAR2,
	    memtype2, 0, &sc->sc_mem2_bt, &sc->sc_mem2_bh,
		NULL, &psc->sc_mapsize2);
	if (error != 0) {
		aprint_error_dev(self, "can't map 2nd mem space\n");
		return;
	}

	/* map interrupt */
	if (pci_intr_map(pa, &ih) != 0) {
		aprint_error_dev(self, "can't map interrupt\n");
		return;
	}

	/* establish interrupt */
	intrstr = pci_intr_string(psc->sc_pc, ih);
	psc->sc_ih = pci_intr_establish(psc->sc_pc, ih, IPL_NET, malo_intr, sc);
	if (psc->sc_ih == NULL) {
		aprint_error_dev(self, "could not establish interrupt");
		if (intrstr != NULL)
			aprint_error(" at %s", intrstr);
		aprint_error("\n");
		return;
	}
	aprint_normal_dev(self, "interrupting at %s\n", intrstr);

	malo_attach(sc);

	if (pmf_device_register(self, malo_pci_suspend, malo_pci_resume))
		pmf_class_network_register(self, &sc->sc_if);
	else
		aprint_error_dev(self, "couldn't establish power handler\n");
}
示例#3
0
static int
malo_pci_attach(device_t dev)
{
	int error = ENXIO, i, msic, reg;
	struct malo_pci_softc *psc = device_get_softc(dev);
	struct malo_softc *sc = &psc->malo_sc;

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

	/* 
	 * Setup memory-mapping of PCI registers.
	 */
	psc->malo_mem_spec = malo_res_spec_mem;
	error = bus_alloc_resources(dev, psc->malo_mem_spec, psc->malo_res_mem);
	if (error) {
		device_printf(dev, "couldn't allocate memory resources\n");
		return (ENXIO);
	}

	/*
	 * Arrange and allocate interrupt line.
	 */
	sc->malo_invalid = 1;

	if (pci_find_cap(dev, PCIY_EXPRESS, &reg) == 0) {
		msic = pci_msi_count(dev);
		if (bootverbose)
			device_printf(dev, "MSI count : %d\n", msic);
	} else
		msic = 0;

	psc->malo_irq_spec = malo_res_spec_legacy;
	if (msic == MALO_MSI_MESSAGES && msi_disable == 0) {
		if (pci_alloc_msi(dev, &msic) == 0) {
			if (msic == MALO_MSI_MESSAGES) {
				device_printf(dev, "Using %d MSI messages\n",
				    msic);
				psc->malo_irq_spec = malo_res_spec_msi;
				psc->malo_msi = 1;
			} else
				pci_release_msi(dev);
		}
	}

	error = bus_alloc_resources(dev, psc->malo_irq_spec, psc->malo_res_irq);
	if (error) {
		device_printf(dev, "couldn't allocate IRQ resources\n");
		goto bad;
	}

	if (psc->malo_msi == 0)
		error = bus_setup_intr(dev, psc->malo_res_irq[0],
		    INTR_TYPE_NET | INTR_MPSAFE, malo_intr, NULL, sc,
		    &psc->malo_intrhand[0]);
	else {
		for (i = 0; i < MALO_MSI_MESSAGES; i++) {
			error = bus_setup_intr(dev, psc->malo_res_irq[i],
			    INTR_TYPE_NET | INTR_MPSAFE, malo_intr, NULL, sc,
			    &psc->malo_intrhand[i]);
			if (error != 0)
				break;
		}
	}

	/*
	 * Setup DMA descriptor area.
	 */
	if (bus_dma_tag_create(bus_get_dma_tag(dev),	/* parent */
			       1, 0,			/* alignment, bounds */
			       BUS_SPACE_MAXADDR_32BIT,	/* lowaddr */
			       BUS_SPACE_MAXADDR,	/* highaddr */
			       NULL, NULL,		/* filter, filterarg */
			       BUS_SPACE_MAXADDR,	/* maxsize */
			       0,			/* nsegments */
			       BUS_SPACE_MAXADDR,	/* maxsegsize */
			       0,			/* flags */
			       NULL,			/* lockfunc */
			       NULL,			/* lockarg */
			       &sc->malo_dmat)) {
		device_printf(dev, "cannot allocate DMA tag\n");
		goto bad1;
	}

	sc->malo_io0t = rman_get_bustag(psc->malo_res_mem[0]);
	sc->malo_io0h = rman_get_bushandle(psc->malo_res_mem[0]);
	sc->malo_io1t = rman_get_bustag(psc->malo_res_mem[1]);
	sc->malo_io1h = rman_get_bushandle(psc->malo_res_mem[1]);

	error = malo_attach(pci_get_device(dev), sc);

	if (error != 0)
		goto bad2;

	return (error);

bad2:
	bus_dma_tag_destroy(sc->malo_dmat);
bad1:
	if (psc->malo_msi == 0)
		bus_teardown_intr(dev, psc->malo_res_irq[0],
		    psc->malo_intrhand[0]);
	else {
		for (i = 0; i < MALO_MSI_MESSAGES; i++)
			bus_teardown_intr(dev, psc->malo_res_irq[i],
			    psc->malo_intrhand[i]);
	}
	bus_release_resources(dev, psc->malo_irq_spec, psc->malo_res_irq);
bad:
	if (psc->malo_msi != 0)
		pci_release_msi(dev);
	bus_release_resources(dev, psc->malo_mem_spec, psc->malo_res_mem);

	return (error);
}