void
puc_cardbus_attach(struct device *parent, struct device *self, void *aux)
{
    struct puc_cardbus_softc *csc = (struct puc_cardbus_softc *)self;
    struct puc_softc *sc = &csc->sc_psc;
    struct cardbus_attach_args *ca = aux;
    struct cardbus_devfunc *ct = ca->ca_ct;
    cardbus_chipset_tag_t cc = ct->ct_cc;
    pci_chipset_tag_t pc = ca->ca_pc;
    cardbus_function_tag_t cf = ct->ct_cf;
    struct puc_attach_args paa;
    pcireg_t reg;
    int i;

    Cardbus_function_enable(ct);

    csc->ct = ct;

    reg = pci_conf_read(pc, ca->ca_tag, PCI_SUBSYS_ID_REG);
    sc->sc_desc = puc_find_description(PCI_VENDOR(ca->ca_id),
                                       PCI_PRODUCT(ca->ca_id), PCI_VENDOR(reg), PCI_PRODUCT(reg));

    puc_print_ports(sc->sc_desc);

    /* the fifth one is some memory we dunno */
    for (i = 0; i < PUC_NBARS; i++) {
        pcireg_t type;
        int bar;

        sc->sc_bar_mappings[i].mapped = 0;
        bar = PCI_MAPREG_START + 4 * i;
        if (!pci_mapreg_probe(pc, ca->ca_tag, bar, &type))
            continue;

        if (!(sc->sc_bar_mappings[i].mapped = !Cardbus_mapreg_map(ct,
                                              bar, type, 0,
                                              &sc->sc_bar_mappings[i].t, &sc->sc_bar_mappings[i].h,
                                              &sc->sc_bar_mappings[i].a, &sc->sc_bar_mappings[i].s)))
            printf("%s: couldn't map BAR at offset 0x%lx\n",
                   sc->sc_dev.dv_xname, (long)bar);
        sc->sc_bar_mappings[i].type = type;
    }

    csc->intrline = ca->ca_intrline;

    if (pci_get_capability(pc, ca->ca_tag, PCI_CAP_PWRMGMT, &reg,
                           0)) {
        reg = pci_conf_read(pc, ca->ca_tag, reg + 4) & 3;
        if (reg) {
            printf("%s: awakening from state D%d\n",
                   sc->sc_dev.dv_xname, reg);
            pci_conf_write(pc, ca->ca_tag, reg + 4, 0);
        }
    }

    (*cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
    (*cf->cardbus_ctrl)(cc, CARDBUS_IO_ENABLE);
    (*cf->cardbus_ctrl)(cc, CARDBUS_BM_ENABLE);

    paa.puc = sc;
    paa.hwtype = COM_UART_OX16C950;		/* XXX */
    paa.intr_string = &puc_cardbus_intr_string;
    paa.intr_establish = &puc_cardbus_intr_establish;
    puc_common_attach(sc, &paa);
}
Exemple #2
0
void
puc_pci_attach(struct device *parent, struct device *self, void *aux)
{
	struct puc_pci_softc *psc = (struct puc_pci_softc *)self;
	struct puc_softc *sc = &psc->sc_psc;
	struct pci_attach_args *pa = aux;
	struct puc_attach_args paa;
	pcireg_t subsys;
	int i;

	subsys = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
	sc->sc_desc = puc_find_description(PCI_VENDOR(pa->pa_id),
	    PCI_PRODUCT(pa->pa_id), PCI_VENDOR(subsys), PCI_PRODUCT(subsys));

	puc_print_ports(sc->sc_desc);

	for (i = 0; i < PUC_NBARS; i++) {
		pcireg_t type;
		int bar;

		sc->sc_bar_mappings[i].mapped = 0;
		bar = PCI_MAPREG_START + 4 * i;
		if (!pci_mapreg_probe(pa->pa_pc, pa->pa_tag, bar, &type))
			continue;

		sc->sc_bar_mappings[i].mapped = (pci_mapreg_map(pa, bar, type,
		    0, &sc->sc_bar_mappings[i].t, &sc->sc_bar_mappings[i].h,
		    &sc->sc_bar_mappings[i].a, &sc->sc_bar_mappings[i].s, 0)
		      == 0);
		if (sc->sc_bar_mappings[i].mapped)
			continue;

		/*
		 * If a port on this card is used as serial console,
		 * mapping the associated BAR will fail because the
		 * bus space is already mapped.  In that case, we try
		 * to re-use the already existing mapping.
		 * Unfortunately this means that if a BAR is used to
		 * support multiple ports, only the first port will
		 * work.
		 */
		if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, bar, type,
		    &sc->sc_bar_mappings[i].a, NULL, NULL) == 0 &&
		    pa->pa_iot == comconsiot &&
		    sc->sc_bar_mappings[i].a == comconsaddr) {
			sc->sc_bar_mappings[i].t = comconsiot;
			sc->sc_bar_mappings[i].h = comconsioh;
			sc->sc_bar_mappings[i].s = COM_NPORTS;
			sc->sc_bar_mappings[i].mapped = 1;
			continue;
		}

		printf("%s: couldn't map BAR at offset 0x%lx\n",
		    sc->sc_dev.dv_xname, (long)bar);
	}

	/* Map interrupt. */
	psc->pc = pa->pa_pc;
	if (pci_intr_map(pa, &psc->ih)) {
		printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
		return;
	}

	paa.puc = sc;
	paa.intr_string = &puc_pci_intr_string;
	paa.intr_establish = &puc_pci_intr_establish;

	puc_common_attach(sc, &paa);
}