diff options
author | imp <imp@FreeBSD.org> | 2001-05-19 05:21:23 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 2001-05-19 05:21:23 +0000 |
commit | 19cf17e66bdb51d13bab00923578bca0d84b1767 (patch) | |
tree | c45081f7289aa2f5035db43efd349436e770e919 /sys/pccard | |
parent | 26885aebf5fdd5705ba9e5442caf61b733234219 (diff) | |
download | FreeBSD-src-19cf17e66bdb51d13bab00923578bca0d84b1767.zip FreeBSD-src-19cf17e66bdb51d13bab00923578bca0d84b1767.tar.gz |
Move ISA specific code into pcic_isa. This is the probe routine, the
get/setb1 routines. Also expose clrb and setb as pcic_{clrb,setb} so
we can use it from the probe. pcic_probe is no longer needed.
Diffstat (limited to 'sys/pccard')
-rw-r--r-- | sys/pccard/pcic.c | 298 | ||||
-rw-r--r-- | sys/pccard/pcic_isa.c | 215 | ||||
-rw-r--r-- | sys/pccard/pcicvar.h | 4 |
3 files changed, 255 insertions, 262 deletions
diff --git a/sys/pccard/pcic.c b/sys/pccard/pcic.c index ff77c16..a27a6f0 100644 --- a/sys/pccard/pcic.c +++ b/sys/pccard/pcic.c @@ -68,47 +68,11 @@ devclass_t pcic_devclass; static struct slot_ctrl cinfo; -static char *bridges[] = -{ - "Intel i82365SL-A/B", - "IBM PCIC", - "VLSI 82C146", - "Cirrus logic 672x", - "Cirrus logic 6710", - "Vadem 365", - "Vadem 465", - "Vadem 468", - "Vadem 469", - "Ricoh RF5C396", - "IBM KING PCMCIA Controller", - "Intel i82365SL-DF" -}; - -/* - * Read a register from the PCIC. - */ -static unsigned char -getb1(struct pcic_slot *sp, int reg) -{ - outb(sp->index, sp->offset + reg); - return (inb(sp->data)); -} - -/* - * Write a register on the PCIC - */ -static void -putb1(struct pcic_slot *sp, int reg, unsigned char val) -{ - outb(sp->index, sp->offset + reg); - outb(sp->data, val); -} - /* * Clear bit(s) of a register. */ -static __inline void -clrb(struct pcic_slot *sp, int reg, unsigned char mask) +__inline void +pcic_clrb(struct pcic_slot *sp, int reg, unsigned char mask) { sp->putb(sp, reg, sp->getb(sp, reg) & ~mask); } @@ -116,8 +80,8 @@ clrb(struct pcic_slot *sp, int reg, unsigned char mask) /* * Set bit(s) of a register */ -static __inline void -setb(struct pcic_slot *sp, int reg, unsigned char mask) +__inline void +pcic_setb(struct pcic_slot *sp, int reg, unsigned char mask) { sp->putb(sp, reg, sp->getb(sp, reg) | mask); } @@ -160,24 +124,24 @@ pcic_memory(struct slot *slt, int win) * Each 16 bit register has some flags in the upper bits. */ if (mp->flags & MDF_16BITS) - setb(sp, reg+1, PCIC_DATA16); + pcic_setb(sp, reg+1, PCIC_DATA16); if (mp->flags & MDF_ZEROWS) - setb(sp, reg+1, PCIC_ZEROWS); + pcic_setb(sp, reg+1, PCIC_ZEROWS); if (mp->flags & MDF_WS0) - setb(sp, reg+3, PCIC_MW0); + pcic_setb(sp, reg+3, PCIC_MW0); if (mp->flags & MDF_WS1) - setb(sp, reg+3, PCIC_MW1); + pcic_setb(sp, reg+3, PCIC_MW1); if (mp->flags & MDF_ATTR) - setb(sp, reg+5, PCIC_REG); + pcic_setb(sp, reg+5, PCIC_REG); if (mp->flags & MDF_WP) - setb(sp, reg+5, PCIC_WP); + pcic_setb(sp, reg+5, PCIC_WP); /* * Enable the memory window. By experiment, we need a delay. */ - setb(sp, PCIC_ADDRWINE, (1<<win) | PCIC_MEMCS16); + pcic_setb(sp, PCIC_ADDRWINE, (1<<win) | PCIC_MEMCS16); DELAY(50); } else { - clrb(sp, PCIC_ADDRWINE, 1<<win); + pcic_clrb(sp, PCIC_ADDRWINE, 1<<win); putw(sp, reg, 0); putw(sp, reg+2, 0); putw(sp, reg+4, 0); @@ -242,10 +206,10 @@ pcic_io(struct slot *slt, int win) break; } DELAY(100); - setb(sp, PCIC_ADDRWINE, mask); + pcic_setb(sp, PCIC_ADDRWINE, mask); DELAY(100); } else { - clrb(sp, PCIC_ADDRWINE, mask); + pcic_clrb(sp, PCIC_ADDRWINE, mask); DELAY(100); putw(sp, reg, 0); putw(sp, reg + 2, 0); @@ -253,209 +217,11 @@ pcic_io(struct slot *slt, int win) return (0); } -/* - * Look for an Intel PCIC (or compatible). - * For each available slot, allocate a PC-CARD slot. - */ -int -pcic_probe(device_t dev) -{ - int slotnum, validslots = 0; - struct pcic_slot *sp; - struct pcic_slot *sp0; - struct pcic_slot *sp1; - struct pcic_slot spsave; - unsigned char c; - struct resource *r; - int rid; - struct pcic_softc *sc; - - /* - * Initialise controller information structure. - */ - cinfo.mapirq = pcic_mapirq; - cinfo.mapmem = pcic_memory; - cinfo.mapio = pcic_io; - cinfo.ioctl = pcic_ioctl; - cinfo.power = pcic_power; - cinfo.reset = pcic_reset; - cinfo.disable = pcic_disable; - cinfo.resume = pcic_resume; - cinfo.maxmem = PCIC_MEM_WIN; - cinfo.maxio = PCIC_IO_WIN; - - if (bus_get_resource_start(dev, SYS_RES_IOPORT, 0) == 0) - bus_set_resource(dev, SYS_RES_IOPORT, 0, PCIC_INDEX0, 2); - rid = 0; - r = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); - if (!r) { - if (bootverbose) - device_printf(dev, "Cannot get I/O range\n"); - return (ENOMEM); - } - - sc = (struct pcic_softc *) device_get_softc(dev); - sc->unit = device_get_unit(dev); - sp = &sc->slots[0]; - for (slotnum = 0; slotnum < PCIC_CARD_SLOTS; slotnum++, sp++) { - /* - * Initialise the PCIC slot table. - */ - sp->getb = getb1; - sp->putb = putb1; - sp->index = rman_get_start(r); - sp->data = sp->index + 1; - sp->offset = slotnum * PCIC_SLOT_SIZE; - sp->controller = -1; - } - - /* - * Prescan for the broken VLSI chips. - * - * According to the Linux PCMCIA code from David Hinds, - * working chipsets return 0x84 from their (correct) ID ports, - * while the broken ones would need to be probed at the new - * offset we set after we assume it's broken. - * - * Note: because of this, we may incorrectly detect a single - * slot vlsi chip as a i82365sl step D. I cannot find a - * datasheet for the affected chip, so that's the best we can - * do for now. - */ - sp0 = &sc->slots[0]; - sp1 = &sc->slots[1]; - if (sp0->getb(sp0, PCIC_ID_REV) == PCIC_VLSI82C146 && - sp1->getb(sp1, PCIC_ID_REV) != PCIC_VLSI82C146) { - spsave = *sp1; - sp1->index += 4; - sp1->data += 4; - sp1->offset = PCIC_SLOT_SIZE << 1; - if (sp1->getb(sp1, PCIC_ID_REV) != PCIC_VLSI82C146) { - *sp1 = spsave; - } else { - sp0->controller = PCIC_VLSI; - sp1->controller = PCIC_VLSI; - } - } - - /* - * Look for normal chipsets here. - */ - sp = &sc->slots[0]; - for (slotnum = 0; slotnum < PCIC_CARD_SLOTS; slotnum++, sp++) { - /* - * see if there's a PCMCIA controller here - * Intel PCMCIA controllers use 0x82 and 0x83 - * IBM clone chips use 0x88 and 0x89, apparently - */ - c = sp->getb(sp, PCIC_ID_REV); - sp->revision = -1; - switch(c) { - /* - * 82365 or clones. - */ - case PCIC_INTEL0: - case PCIC_INTEL1: - sp->controller = PCIC_I82365; - sp->revision = c & 1; - /* - * Now check for VADEM chips. - */ - outb(sp->index, 0x0E); /* Unlock VADEM's extra regs */ - outb(sp->index, 0x37); - setb(sp, PCIC_VMISC, PCIC_VADEMREV); - c = sp->getb(sp, PCIC_ID_REV); - if (c & 0x08) { - switch (sp->revision = c & 7) { - case 1: - sp->controller = PCIC_VG365; - break; - case 2: - sp->controller = PCIC_VG465; - break; - case 3: - sp->controller = PCIC_VG468; - break; - default: - sp->controller = PCIC_VG469; - break; - } - clrb(sp, PCIC_VMISC, PCIC_VADEMREV); - } - - /* - * Check for RICOH RF5C396 PCMCIA Controller - */ - c = sp->getb(sp, 0x3a); - if (c == 0xb2) { - sp->controller = PCIC_RF5C396; - } - - break; - /* - * Intel i82365D or maybe a vlsi 82c146 - * we detected the vlsi case earlier, so if the controller - * isn't set, we know it is a i82365sl step D. - */ - case PCIC_INTEL2: - if (sp->controller == -1) - sp->controller = PCIC_I82365SL_DF; - break; - case PCIC_IBM1: - case PCIC_IBM2: - sp->controller = PCIC_IBM; - sp->revision = c & 1; - break; - case PCIC_IBM3: - sp->controller = PCIC_IBM_KING; - sp->revision = c & 1; - break; - default: - continue; - } - /* - * Check for Cirrus logic chips. - */ - sp->putb(sp, PCIC_CLCHIP, 0); - c = sp->getb(sp, PCIC_CLCHIP); - if ((c & PCIC_CLC_TOGGLE) == PCIC_CLC_TOGGLE) { - c = sp->getb(sp, PCIC_CLCHIP); - if ((c & PCIC_CLC_TOGGLE) == 0) { - if (c & PCIC_CLC_DUAL) - sp->controller = PCIC_PD672X; - else - sp->controller = PCIC_PD6710; - sp->revision = 8 - ((c & 0x1F) >> 2); - } - } - device_set_desc(dev, bridges[(int) sp->controller]); - /* - * OK it seems we have a PCIC or lookalike. - * Allocate a slot and initialise the data structures. - */ - validslots++; - sp->slt = (struct slot *) 1; - /* - * Modem cards send the speaker audio (dialing noises) - * to the host's speaker. Cirrus Logic PCIC chips must - * enable this. There is also a Low Power Dynamic Mode bit - * that claims to reduce power consumption by 30%, so - * enable it and hope for the best. - */ - if (sp->controller == PCIC_PD672X) { - setb(sp, PCIC_MISC1, PCIC_MISC1_SPEAKER); - setb(sp, PCIC_MISC2, PCIC_LPDM_EN); - } - } - bus_release_resource(dev, SYS_RES_IOPORT, rid, r); - return (validslots ? 0 : ENXIO); -} - static void do_mgt_irq(struct pcic_slot *sp, int irq) { /* Management IRQ changes */ - clrb(sp, PCIC_INT_GEN, PCIC_INTR_ENA); + pcic_clrb(sp, PCIC_INT_GEN, PCIC_INTR_ENA); sp->putb(sp, PCIC_STAT_INT, (irq << 4) | 0xF); } @@ -474,6 +240,20 @@ pcic_attach(device_t dev) struct pcic_slot *sp; int stat; + /* + * Initialise controller information structure. + */ + cinfo.mapirq = pcic_mapirq; + cinfo.mapmem = pcic_memory; + cinfo.mapio = pcic_io; + cinfo.ioctl = pcic_ioctl; + cinfo.power = pcic_power; + cinfo.reset = pcic_reset; + cinfo.disable = pcic_disable; + cinfo.resume = pcic_resume; + cinfo.maxmem = PCIC_MEM_WIN; + cinfo.maxio = PCIC_IO_WIN; + sc = (struct pcic_softc *) device_get_softc(dev); sp = &sc->slots[0]; for (i = 0; i < PCIC_CARD_SLOTS; i++, sp++) { @@ -545,7 +325,7 @@ pcic_attach(device_t dev) do_mgt_irq(sp, irq); /* Check for changes */ - setb(sp, PCIC_POWER, PCIC_PCPWRE| PCIC_DISRST); + pcic_setb(sp, PCIC_POWER, PCIC_PCPWRE| PCIC_DISRST); stat = sp->getb(sp, PCIC_STATUS); if (bootverbose) printf("stat is %x\n", stat); @@ -644,9 +424,9 @@ pcic_power(struct slot *slt) (sp->controller == PCIC_VG469) || (sp->controller == PCIC_VG465) || (sp->controller == PCIC_VG365)) - setb(sp, PCIC_CVSR, PCIC_CVSR_VS); + pcic_setb(sp, PCIC_CVSR, PCIC_CVSR_VS); else - setb(sp, PCIC_MISC1, PCIC_MISC1_VCC_33); + pcic_setb(sp, PCIC_MISC1, PCIC_MISC1_VCC_33); break; case 50: if (sp->controller == PCIC_IBM_KING) { @@ -658,9 +438,9 @@ pcic_power(struct slot *slt) (sp->controller == PCIC_VG469) || (sp->controller == PCIC_VG465) || (sp->controller == PCIC_VG365)) - clrb(sp, PCIC_CVSR, PCIC_CVSR_VS); + pcic_clrb(sp, PCIC_CVSR, PCIC_CVSR_VS); else - clrb(sp, PCIC_MISC1, PCIC_MISC1_VCC_33); + pcic_clrb(sp, PCIC_MISC1, PCIC_MISC1_VCC_33); break; } break; @@ -694,7 +474,7 @@ pcic_mapirq(struct slot *slt, int irq) { struct pcic_slot *sp = slt->cdata; if (irq == 0) - clrb(sp, PCIC_INT_GEN, 0xF); + pcic_clrb(sp, PCIC_INT_GEN, 0xF); else sp->putb(sp, PCIC_INT_GEN, (sp->getb(sp, PCIC_INT_GEN) & 0xF0) | irq); @@ -713,12 +493,12 @@ pcic_reset(void *chan) case 0: /* Something funny happended on the way to the pub... */ return; case 1: /* Assert reset */ - clrb(sp, PCIC_INT_GEN, PCIC_CARDRESET); + pcic_clrb(sp, PCIC_INT_GEN, PCIC_CARDRESET); slt->insert_seq = 2; timeout(cinfo.reset, (void *)slt, hz/4); return; case 2: /* Deassert it again */ - setb(sp, PCIC_INT_GEN, PCIC_CARDRESET|PCIC_IOCARD); + pcic_setb(sp, PCIC_INT_GEN, PCIC_CARDRESET|PCIC_IOCARD); slt->insert_seq = 3; timeout(cinfo.reset, (void *)slt, hz/4); return; @@ -833,8 +613,8 @@ pcic_resume(struct slot *slt) do_mgt_irq(sp, slt->irq); if (sp->controller == PCIC_PD672X) { - setb(sp, PCIC_MISC1, PCIC_MISC1_SPEAKER); - setb(sp, PCIC_MISC2, PCIC_LPDM_EN); + pcic_setb(sp, PCIC_MISC1, PCIC_MISC1_SPEAKER); + pcic_setb(sp, PCIC_MISC2, PCIC_LPDM_EN); } } diff --git a/sys/pccard/pcic_isa.c b/sys/pccard/pcic_isa.c index 46a3cb9..130e670 100644 --- a/sys/pccard/pcic_isa.c +++ b/sys/pccard/pcic_isa.c @@ -53,9 +53,58 @@ static struct isa_pnp_id pcic_ids[] = { {0} }; +static char *bridges[] = +{ + "Intel i82365SL-A/B", + "IBM PCIC", + "VLSI 82C146", + "Cirrus logic 672x", + "Cirrus logic 6710", + "Vadem 365", + "Vadem 465", + "Vadem 468", + "Vadem 469", + "Ricoh RF5C396", + "IBM KING PCMCIA Controller", + "Intel i82365SL-DF" +}; + +/* + * Read a register from the PCIC. + */ +static unsigned char +getb1(struct pcic_slot *sp, int reg) +{ + outb(sp->index, sp->offset + reg); + return (inb(sp->data)); +} + +/* + * Write a register on the PCIC + */ +static void +putb1(struct pcic_slot *sp, int reg, unsigned char val) +{ + outb(sp->index, sp->offset + reg); + outb(sp->data, val); +} + +/* + * Look for an Intel PCIC (or compatible). + * For each available slot, allocate a PC-CARD slot. + */ static int pcic_isa_probe(device_t dev) { + int slotnum, validslots = 0; + struct pcic_slot *sp; + struct pcic_slot *sp0; + struct pcic_slot *sp1; + struct pcic_slot spsave; + unsigned char c; + struct resource *r; + int rid; + struct pcic_softc *sc; int error; /* Check isapnp ids */ @@ -63,7 +112,171 @@ pcic_isa_probe(device_t dev) if (error == ENXIO) return (ENXIO); - return (pcic_probe(dev)); + if (bus_get_resource_start(dev, SYS_RES_IOPORT, 0) == 0) + bus_set_resource(dev, SYS_RES_IOPORT, 0, PCIC_INDEX0, 2); + rid = 0; + r = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1, RF_ACTIVE); + if (!r) { + if (bootverbose) + device_printf(dev, "Cannot get I/O range\n"); + return (ENOMEM); + } + + sc = (struct pcic_softc *) device_get_softc(dev); + sc->unit = device_get_unit(dev); + sp = &sc->slots[0]; + for (slotnum = 0; slotnum < PCIC_CARD_SLOTS; slotnum++, sp++) { + /* + * Initialise the PCIC slot table. + */ + sp->getb = getb1; + sp->putb = putb1; + sp->index = rman_get_start(r); + sp->data = sp->index + 1; + sp->offset = slotnum * PCIC_SLOT_SIZE; + sp->controller = -1; + } + + /* + * Prescan for the broken VLSI chips. + * + * According to the Linux PCMCIA code from David Hinds, + * working chipsets return 0x84 from their (correct) ID ports, + * while the broken ones would need to be probed at the new + * offset we set after we assume it's broken. + * + * Note: because of this, we may incorrectly detect a single + * slot vlsi chip as a i82365sl step D. I cannot find a + * datasheet for the affected chip, so that's the best we can + * do for now. + */ + sp0 = &sc->slots[0]; + sp1 = &sc->slots[1]; + if (sp0->getb(sp0, PCIC_ID_REV) == PCIC_VLSI82C146 && + sp1->getb(sp1, PCIC_ID_REV) != PCIC_VLSI82C146) { + spsave = *sp1; + sp1->index += 4; + sp1->data += 4; + sp1->offset = PCIC_SLOT_SIZE << 1; + if (sp1->getb(sp1, PCIC_ID_REV) != PCIC_VLSI82C146) { + *sp1 = spsave; + } else { + sp0->controller = PCIC_VLSI; + sp1->controller = PCIC_VLSI; + } + } + + /* + * Look for normal chipsets here. + */ + sp = &sc->slots[0]; + for (slotnum = 0; slotnum < PCIC_CARD_SLOTS; slotnum++, sp++) { + /* + * see if there's a PCMCIA controller here + * Intel PCMCIA controllers use 0x82 and 0x83 + * IBM clone chips use 0x88 and 0x89, apparently + */ + c = sp->getb(sp, PCIC_ID_REV); + sp->revision = -1; + switch(c) { + /* + * 82365 or clones. + */ + case PCIC_INTEL0: + case PCIC_INTEL1: + sp->controller = PCIC_I82365; + sp->revision = c & 1; + /* + * Now check for VADEM chips. + */ + outb(sp->index, 0x0E); /* Unlock VADEM's extra regs */ + outb(sp->index, 0x37); + pcic_setb(sp, PCIC_VMISC, PCIC_VADEMREV); + c = sp->getb(sp, PCIC_ID_REV); + if (c & 0x08) { + switch (sp->revision = c & 7) { + case 1: + sp->controller = PCIC_VG365; + break; + case 2: + sp->controller = PCIC_VG465; + break; + case 3: + sp->controller = PCIC_VG468; + break; + default: + sp->controller = PCIC_VG469; + break; + } + pcic_clrb(sp, PCIC_VMISC, PCIC_VADEMREV); + } + + /* + * Check for RICOH RF5C396 PCMCIA Controller + */ + c = sp->getb(sp, 0x3a); + if (c == 0xb2) { + sp->controller = PCIC_RF5C396; + } + + break; + /* + * Intel i82365D or maybe a vlsi 82c146 + * we detected the vlsi case earlier, so if the controller + * isn't set, we know it is a i82365sl step D. + */ + case PCIC_INTEL2: + if (sp->controller == -1) + sp->controller = PCIC_I82365SL_DF; + break; + case PCIC_IBM1: + case PCIC_IBM2: + sp->controller = PCIC_IBM; + sp->revision = c & 1; + break; + case PCIC_IBM3: + sp->controller = PCIC_IBM_KING; + sp->revision = c & 1; + break; + default: + continue; + } + /* + * Check for Cirrus logic chips. + */ + sp->putb(sp, PCIC_CLCHIP, 0); + c = sp->getb(sp, PCIC_CLCHIP); + if ((c & PCIC_CLC_TOGGLE) == PCIC_CLC_TOGGLE) { + c = sp->getb(sp, PCIC_CLCHIP); + if ((c & PCIC_CLC_TOGGLE) == 0) { + if (c & PCIC_CLC_DUAL) + sp->controller = PCIC_PD672X; + else + sp->controller = PCIC_PD6710; + sp->revision = 8 - ((c & 0x1F) >> 2); + } + } + device_set_desc(dev, bridges[(int) sp->controller]); + /* + * OK it seems we have a PCIC or lookalike. + * Allocate a slot and initialise the data structures. + */ + validslots++; + sp->slt = (struct slot *) 1; + /* + * Modem cards send the speaker audio (dialing noises) + * to the host's speaker. Cirrus Logic PCIC chips must + * enable this. There is also a Low Power Dynamic Mode bit + * that claims to reduce power consumption by 30%, so + * enable it and hope for the best. + */ + if (sp->controller == PCIC_PD672X) { + pcic_setb(sp, PCIC_MISC1, PCIC_MISC1_SPEAKER); + pcic_setb(sp, PCIC_MISC2, PCIC_LPDM_EN); + } + } + bus_release_resource(dev, SYS_RES_IOPORT, rid, r); + return (validslots ? 0 : ENXIO); } static int diff --git a/sys/pccard/pcicvar.h b/sys/pccard/pcicvar.h index fa38922..bc0dd34 100644 --- a/sys/pccard/pcicvar.h +++ b/sys/pccard/pcicvar.h @@ -47,7 +47,6 @@ struct pcic_softc extern devclass_t pcic_devclass; -int pcic_probe(device_t dev); int pcic_attach(device_t dev); int pcic_activate_resource(device_t dev, device_t child, int type, int rid, struct resource *r); @@ -65,4 +64,5 @@ int pcic_get_memory_offset(device_t bus, device_t child, int rid, u_int32_t *offset); int pcic_set_memory_offset(device_t bus, device_t child, int rid, u_int32_t offset, u_int32_t *deltap); - +void pcic_clrb(struct pcic_slot *sp, int reg, unsigned char mask); +void pcic_setb(struct pcic_slot *sp, int reg, unsigned char mask); |