void pcic_attach(struct pcic_softc *sc) { int i, reg, chip, socket; struct pcic_handle *h; device_t self; DPRINTF(("pcic ident regs:")); self = sc->dev; mutex_init(&sc->sc_pcic_lock, MUTEX_DEFAULT, IPL_NONE); /* find and configure for the available sockets */ for (i = 0; i < __arraycount(sc->handle); i++) { h = &sc->handle[i]; chip = i / 2; socket = i % 2; h->ph_parent = self; h->chip = chip; h->socket = socket; h->sock = chip * PCIC_CHIP_OFFSET + socket * PCIC_SOCKET_OFFSET; h->laststate = PCIC_LASTSTATE_EMPTY; /* initialize pcic_read and pcic_write functions */ h->ph_read = st_pcic_read; h->ph_write = st_pcic_write; h->ph_bus_t = sc->iot; h->ph_bus_h = sc->ioh; h->flags = 0; /* need to read vendor -- for cirrus to report no xtra chip */ if (socket == 0) { h->vendor = pcic_vendor(h); if (i < __arraycount(sc->handle) - 1) (h + 1)->vendor = h->vendor; } switch (h->vendor) { case PCIC_VENDOR_NONE: /* no chip */ continue; case PCIC_VENDOR_CIRRUS_PD67XX: reg = pcic_read(h, PCIC_CIRRUS_CHIP_INFO); if (socket == 0 || (reg & PCIC_CIRRUS_CHIP_INFO_SLOTS)) h->flags = PCIC_FLAG_SOCKETP; break; default: /* * During the socket probe, read the ident register * twice. I don't understand why, but sometimes the * clone chips in hpcmips boxes read all-0s the first * time. -- mycroft */ reg = pcic_read(h, PCIC_IDENT); DPRINTF(("socket %d ident reg 0x%02x\n", i, reg)); reg = pcic_read(h, PCIC_IDENT); DPRINTF(("socket %d ident reg 0x%02x\n", i, reg)); if (pcic_ident_ok(reg)) h->flags = PCIC_FLAG_SOCKETP; break; } } for (i = 0; i < __arraycount(sc->handle); i++) { h = &sc->handle[i]; if (h->flags & PCIC_FLAG_SOCKETP) { SIMPLEQ_INIT(&h->events); /* disable interrupts and leave socket in reset */ pcic_write(h, PCIC_INTR, 0); /* zero out the address windows */ pcic_write(h, PCIC_ADDRWIN_ENABLE, 0); /* power down the socket */ pcic_write(h, PCIC_PWRCTL, 0); pcic_write(h, PCIC_CSC_INTR, 0); (void) pcic_read(h, PCIC_CSC); } } /* print detected info */ for (i = 0; i < __arraycount(sc->handle) - 1; i += 2) { h = &sc->handle[i]; chip = i / 2; if (h->vendor == PCIC_VENDOR_NONE) continue; aprint_normal_dev(self, "controller %d (%s) has ", chip, pcic_vendor_to_string(sc->handle[i].vendor)); if ((h->flags & PCIC_FLAG_SOCKETP) && ((h + 1)->flags & PCIC_FLAG_SOCKETP)) aprint_normal("sockets A and B\n"); else if (h->flags & PCIC_FLAG_SOCKETP) aprint_normal("socket A only\n"); else if ((h + 1)->flags & PCIC_FLAG_SOCKETP) aprint_normal("socket B only\n"); else aprint_normal("no sockets\n"); } }
void pcic_isapnp_attach(struct device *parent, struct device *self, void *aux) { struct pcic_softc *sc = device_private(self); struct pcic_isa_softc *isc = device_private(self); struct isapnp_attach_args *ipa = aux; isa_chipset_tag_t ic = ipa->ipa_ic; bus_space_tag_t iot = ipa->ipa_iot; bus_space_tag_t memt = ipa->ipa_memt; bus_space_handle_t ioh; bus_space_handle_t memh; bus_addr_t maddr; int msize; int tmp1; printf("\n"); if (isapnp_config(iot, memt, ipa)) { aprint_error_dev(&sc->dev, "error in region allocation\n"); return; } printf("%s: %s %s", device_xname(&sc->dev), ipa->ipa_devident, ipa->ipa_devclass); /* sanity check that we get at least one hunk of IO space.. */ if (ipa->ipa_nio < 1) { aprint_error_dev(&sc->dev, "failed to get one chunk of i/o space\n"); return; } /* Find i/o space. */ ioh = ipa->ipa_io[0].h; /* sanity check to make sure we have a real PCIC there.. */ bus_space_write_1(iot, ioh, PCIC_REG_INDEX, C0SA + PCIC_IDENT); tmp1 = bus_space_read_1(iot, ioh, PCIC_REG_DATA); printf("(ident 0x%x", tmp1); if (pcic_ident_ok(tmp1)) { printf(" OK)"); } else { printf(" Not OK)\n"); return; } msize = 0x4000; if (isa_mem_alloc (memt, msize, msize, 0, 0, &maddr, &memh)) { printf(": can't alloc mem space\n"); return; } printf(": using iomem 0x%lx iosiz 0x%x", maddr, msize); sc->membase = maddr; sc->subregionmask = (1 << (msize / PCIC_MEM_PAGESIZE)) - 1; isc->sc_ic = ic; sc->pct = (pcmcia_chipset_tag_t) & pcic_isa_functions; sc->iot = iot; sc->ioh = ioh; sc->memt = memt; sc->memh = memh; /* * allocate an irq. it will be used by both controllers. I could * use two different interrupts, but interrupts are relatively * scarce, shareable, and for PCIC controllers, very infrequent. */ if (ipa->ipa_nirq > 0) sc->irq = ipa->ipa_irq[0].num; else sc->irq = -1; printf("\n"); pcic_attach(sc); pcic_isa_bus_width_probe(sc, iot, ioh, ipa->ipa_io[0].base, ipa->ipa_io[0].length); pcic_attach_sockets(sc); config_interrupts(self, pcic_isa_config_interrupts); }