diff options
Diffstat (limited to 'sys/pccard')
-rw-r--r-- | sys/pccard/i82365.h | 77 | ||||
-rw-r--r-- | sys/pccard/pcic.c | 152 | ||||
-rw-r--r-- | sys/pccard/slot.h | 2 |
3 files changed, 137 insertions, 94 deletions
diff --git a/sys/pccard/i82365.h b/sys/pccard/i82365.h index f3012ef..20b2c09 100644 --- a/sys/pccard/i82365.h +++ b/sys/pccard/i82365.h @@ -38,17 +38,17 @@ #define PCIC_I82365 0 /* Intel chip */ #define PCIC_IBM 1 /* IBM clone */ #define PCIC_VLSI 2 /* VLSI chip */ -#define PCIC_PD672X 3 /* Cirrus logic 627x */ +#define PCIC_PD672X 3 /* Cirrus logic 672x */ #define PCIC_PD6710 4 /* Cirrus logic 6710 */ -#define PCIC_CL6729 5 /* Cirrus logic 6729 */ -#define PCIC_VG365 6 /* Vadem 365 */ -#define PCIC_VG465 7 /* Vadem 465 */ -#define PCIC_VG468 8 /* Vadem 468 */ -#define PCIC_VG469 9 /* Vadem 469 */ -#define PCIC_RF5C396 10 /* Ricoh RF5C396 */ -#define PCIC_IBM_KING 11 /* IBM KING PCMCIA Controller */ -#define PCIC_PC98 12 /* NEC PC98 PCMCIA Controller */ -#define PCIC_TI1130 13 /* TI PCI1130 CardBus */ +#define PCIC_VG365 5 /* Vadem 365 */ +#define PCIC_VG465 6 /* Vadem 465 */ +#define PCIC_VG468 7 /* Vadem 468 */ +#define PCIC_VG469 8 /* Vadem 469 */ +#define PCIC_RF5C396 9 /* Ricoh RF5C396 */ +#define PCIC_IBM_KING 10 /* IBM KING PCMCIA Controller */ +/* These last two aren't in normal freebsd */ +#define PCIC_PC98 11 /* NEC PC98 PCMCIA Controller */ +#define PCIC_TI1130 12 /* TI PCI1130 CardBus */ /* * Address of the controllers. Each controller can manage @@ -84,6 +84,10 @@ #define PCIC_MISC1 0x16 /* PD672x: Misc control register 1 per slot */ #define PCIC_GLO_CTRL 0x1e /* Global Control Register */ #define PCIC_MISC2 0x1e /* PD672x: Misc control register 2 per chip */ +#define PCIC_CLCHIP 0x1f /* PD67xx: Chip I/D */ +#define PCIC_CVSR 0x2f /* Vadem: Voltage select register */ + +#define PCIC_VMISC 0x3a /* Vadem: Misc control register */ #define PCIC_TIME_SETUP0 0x3a #define PCIC_TIME_CMD0 0x3b @@ -99,6 +103,7 @@ /* For Identification and Revision (PCIC_ID_REV) */ #define PCIC_INTEL0 0x82 /* Intel 82365SL Rev. 0; Both Memory and I/O */ #define PCIC_INTEL1 0x83 /* Intel 82365SL Rev. 1; Both Memory and I/O */ +#define PCIC_VLSI82C146 0x84 /* VLSI 82C146 */ #define PCIC_IBM1 0x88 /* IBM PCIC clone; Both Memory and I/O */ #define PCIC_IBM2 0x89 /* IBM PCIC clone; Both Memory and I/O */ #define PCIC_IBM3 0x8a /* IBM KING PCIC clone; Both Memory and I/O */ @@ -120,7 +125,7 @@ #define PCIC_VCC_5V 0x10 /* 5 volts */ #define PCIC_VCC_3V 0x18 /* 3 volts */ #define PCIC_VCC_5V_KING 0x14 /* 5 volts for KING PCIC */ -#define PCIC_VPP 0x0C /* Vpp control bits */ +#define PCIC_VPP 0x03 /* Vpp control bits */ #define PCIC_VPP_5V 0x01 /* 5 volts */ #define PCIC_VPP_12V 0x02 /* 12 volts */ @@ -204,24 +209,62 @@ #define PCIC_CDRES_EN 0x10 /* card detect resume enable */ #define PCIC_SW_CD_INT 0x20 /* s/w card detect interrupt */ -/* For Misc. Control Register 1 */ -#define PCIC_SPKR_EN 0x10 /* Cirrus PD672x: speaker enable */ +/* CL-PD67[12]x: For 3.3V cards, etc. (PCIC_MISC1) */ +#define PCIC_MISC1_5V_DETECT 0x01 /* PD6710 only */ +#define PCIC_MISC1_VCC_33 0x02 /* Set Vcc is 3.3V, else 5.0V */ +#define PCIC_MISC1_PMINT 0x04 /* Pulse management intr */ +#define PCIC_MISC1_PCINT 0x08 /* Pulse card interrupt */ +#define PCIC_MISC1_SPEAKER 0x10 /* Enable speaker */ +#define PCIC_MISC1_INPACK 0x80 /* INPACK throttles data */ -/* For Global Control register (PCIC_GLO_CTRL) */ +/* i82365B and newer (!PD67xx) Global Control register (PCIC_GLO_CTRL) */ #define PCIC_PWR_DOWN 0x01 /* power down */ #define PCIC_LVL_MODE 0x02 /* level mode interrupt enable */ #define PCIC_WB_CSCINT 0x04 /* explicit write-back csc intr */ +/* Rev B only */ #define PCIC_IRQ0_LEVEL 0x08 /* irq 14 pulse mode enable */ #define PCIC_IRQ1_LEVEL 0x10 -/* For Misc. Control Register 2 */ +/* CL-PD67[12]x: For Misc. Control Register 2 (PCIC_MISC2) */ #define PCIC_LPDM_EN 0x02 /* Cirrus PD672x: low power dynamic mode */ +/* CL-PD67[12]x: Chip info (PCIC_CLCHIP) */ +#define PCIC_CLC_TOGGLE 0xc0 /* These bits toggle 1 -> 0 */ +#define PCIC_CLC_DUAL 0x20 /* Single/dual socket version */ + +/* Vadem: Card Voltage Select register (PCIC_CVSR) */ +#define PCIC_CVSR_VS 0x03 /* Voltage select */ +#define PCIC_CVSR_VS_5 0x00 /* 5.0 V */ +#define PCIC_CVSR_VS_33a 0x01 /* alt 3.3V */ +#define PCIC_CVSR_VS_XX 0x02 /* X.XV when available */ +#define PCIC_CVSR_VS_33 0x03 /* 3.3V */ + +/* Vadem: misc register (PCIC_VMISC) */ +#define PCIC_VADEMREV 0x40 + /* * Mask of allowable interrupts. - * Ints are 3,4,5,7,9,10,11,12,14,15 + * + * For IBM-AT machines, irqs 3, 4, 5, 7, 9, 10, 11, 12, 14, 15 are + * allowed. Nearly all IBM-AT machines with pcic cards or bridges + * wire these interrupts (or a subset thereof) to the corresponding + * pins on the ISA bus. Some older laptops are reported to not route + * all the interrupt pins to the bus because the designers knew that + * some would conflict with builtin devices. + * + * For NEC PC98 machines, irq 3, 5, 6, 9, 10, 11, 12, 13 are allowed. + * These correspond to the C-BUS signals INT 0, 1, 2, 3, 41, 42, 5, 6 + * respectively. This is with the desktop C-BUS addin card. I don't + * know if this corresponds to laptop usage or not. + * + * I'm not sure the proper way to map these interrupts, but it looks + * like pc98 is a subset of ibm-at so no actual mapping is required. */ -#define PCIC_INT_MASK_ALLOWED 0xDEB8 +#ifdef PC98 +#define PCIC_INT_MASK_ALLOWED 0x3E68 /* PC98 */ +#else +#define PCIC_INT_MASK_ALLOWED 0xDEB8 /* AT */ +#endif #define PCIC_IO_WIN 2 #define PCIC_MEM_WIN 5 diff --git a/sys/pccard/pcic.c b/sys/pccard/pcic.c index 8f1b624..3443ef6 100644 --- a/sys/pccard/pcic.c +++ b/sys/pccard/pcic.c @@ -55,7 +55,6 @@ static int pcic_power __P((struct slot *)); static timeout_t pcic_reset; static void pcic_resume(struct slot *); static void pcic_disable __P((struct slot *)); -static void pcic_mapirq __P((struct slot *, int)); static timeout_t pcictimeout; static struct callout_handle pcictimeout_ch = CALLOUT_HANDLE_INITIALIZER(&pcictimeout_ch); @@ -97,6 +96,21 @@ static int validunits = 0; #define GET_UNIT(d) *(int *)device_get_softc(d) #define SET_UNIT(d,u) *(int *)device_get_softc(d) = (u) +static char *bridges[] = +{ + "Intel i82365", + "IBM PCIC", + "VLSI 82C146", + "Cirrus logic 672x", + "Cirrus logic 6710", + "Vadem 365", + "Vadem 465", + "Vadem 468", + "Vadem 469", + "Ricoh RF5C396", + "IBM KING PCMCIA Controller" +}; + /* * Internal inline functions for accessing the PCIC. */ @@ -281,7 +295,6 @@ pcic_probe(device_t dev) struct slot *slt; struct pcic_slot *sp; unsigned char c; - char *name; int error; struct resource *r; int rid; @@ -299,7 +312,6 @@ pcic_probe(device_t dev) cinfo.mapio = pcic_io; cinfo.ioctl = pcic_ioctl; cinfo.power = pcic_power; - cinfo.mapirq = pcic_mapirq; cinfo.reset = pcic_reset; cinfo.disable = pcic_disable; cinfo.resume = pcic_resume; @@ -333,7 +345,8 @@ pcic_probe(device_t dev) * ones would need to be probed at the new offset we set after * we assume it's broken. */ - if (slotnum == 1 && maybe_vlsi && sp->getb(sp, PCIC_ID_REV) != 0x84) { + if (slotnum == 1 && maybe_vlsi && + sp->getb(sp, PCIC_ID_REV) != PCIC_VLSI82C146) { sp->index += 4; sp->data += 4; sp->offset = PCIC_SLOT_SIZE << 1; @@ -349,16 +362,16 @@ pcic_probe(device_t dev) /* * 82365 or clones. */ - case 0x82: - case 0x83: + case PCIC_INTEL0: + case PCIC_INTEL1: sp->controller = PCIC_I82365; sp->revision = c & 1; /* * Now check for VADEM chips. */ - outb(sp->index, 0x0E); + outb(sp->index, 0x0E); /* Unlock VADEM's extra regs */ outb(sp->index, 0x37); - setb(sp, 0x3A, 0x40); + setb(sp, PCIC_VMISC, PCIC_VADEMREV); c = sp->getb(sp, PCIC_ID_REV); if (c & 0x08) { switch (sp->revision = c & 7) { @@ -375,7 +388,7 @@ pcic_probe(device_t dev) sp->controller = PCIC_VG469; break; } - clrb(sp, 0x3A, 0x40); + clrb(sp, PCIC_VMISC, PCIC_VADEMREV); } /* @@ -390,16 +403,16 @@ pcic_probe(device_t dev) /* * VLSI chips. */ - case 0x84: + case PCIC_VLSI82C146: sp->controller = PCIC_VLSI; maybe_vlsi = 1; break; - case 0x88: - case 0x89: + case PCIC_IBM1: + case PCIC_IBM2: sp->controller = PCIC_IBM; sp->revision = c & 1; break; - case 0x8a: + case PCIC_IBM3: sp->controller = PCIC_IBM_KING; sp->revision = c & 1; break; @@ -409,57 +422,19 @@ pcic_probe(device_t dev) /* * Check for Cirrus logic chips. */ - sp->putb(sp, 0x1F, 0); - c = sp->getb(sp, 0x1F); - if ((c & 0xC0) == 0xC0) { - c = sp->getb(sp, 0x1F); - if ((c & 0xC0) == 0) { - if (c & 0x20) + 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); } } - switch(sp->controller) { - case PCIC_I82365: - name = "Intel i82365"; - break; - case PCIC_IBM: - name = "IBM PCIC"; - break; - case PCIC_IBM_KING: - name = "IBM KING PCMCIA Controller"; - break; - case PCIC_PD672X: - name = "Cirrus Logic PD672X"; - break; - case PCIC_PD6710: - name = "Cirrus Logic PD6710"; - break; - case PCIC_VG365: - name = "Vadem 365"; - break; - case PCIC_VG465: - name = "Vadem 465"; - break; - case PCIC_VG468: - name = "Vadem 468"; - break; - case PCIC_VG469: - name = "Vadem 469"; - break; - case PCIC_RF5C396: - name = "Ricoh RF5C396"; - break; - case PCIC_VLSI: - name = "VLSI 82C146"; - break; - default: - name = "Unknown!"; - break; - } - device_set_desc(dev, name); + 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. @@ -479,7 +454,7 @@ pcic_probe(device_t dev) * enable it and hope for the best. */ if (sp->controller == PCIC_PD672X) { - setb(sp, PCIC_MISC1, PCIC_SPKR_EN); + setb(sp, PCIC_MISC1, PCIC_MISC1_SPEAKER); setb(sp, PCIC_MISC2, PCIC_LPDM_EN); } } @@ -487,6 +462,14 @@ pcic_probe(device_t dev) 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); + sp->putb(sp, PCIC_STAT_INT, (irq << 4) | 0xF); +} + static int pcic_attach(device_t dev) { @@ -521,9 +504,17 @@ pcic_attach(device_t dev) } rid = 0; r = 0; - if (irq >= 0) { + if (irq > 0) { r = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, irq, - ~0, 1, RF_ACTIVE); + irq, 1, RF_ACTIVE); + } + if (r && ((1 << (rman_get_start(r))) & PCIC_INT_MASK_ALLOWED) == 0) { + device_printf(dev, + "Hardware does not support irq %d, trying polling.\n", + irq); + bus_release_resource(dev, SYS_RES_IRQ, rid, r); + r = 0; + irq = 0; } if (r) { error = bus_setup_intr(dev, r, INTR_TYPE_MISC, @@ -538,19 +529,20 @@ pcic_attach(device_t dev) irq = 0; } if (irq == 0) { - pcictimeout_ch = timeout(pcictimeout, (void *) GET_UNIT(dev), hz/2); + pcictimeout_ch = timeout(pcictimeout, (void *) GET_UNIT(dev), + hz/2); device_printf(dev, "Polling mode\n"); } sp = &pcic_slots[GET_UNIT(dev) * PCIC_CARD_SLOTS]; for (i = 0; i < PCIC_CARD_SLOTS; i++, sp++) { - /* Assign IRQ */ - sp->putb(sp, PCIC_STAT_INT, (irq << 4) | 0xF); + if (sp->slt == NULL) + continue; + + do_mgt_irq(sp, irq); /* Check for changes */ setb(sp, PCIC_POWER, PCIC_PCPWRE| PCIC_DISRST); - if (sp->slt == NULL) - continue; stat = sp->getb(sp, PCIC_STATUS); if (bootverbose) printf("stat is %x\n", stat); @@ -612,6 +604,7 @@ pcic_power(struct slot *slt) case PCIC_RF5C396: case PCIC_VLSI: case PCIC_IBM_KING: + case PCIC_I82365: switch(slt->pwr.vpp) { default: return(EINVAL); @@ -640,9 +633,9 @@ pcic_power(struct slot *slt) (sp->controller == PCIC_VG469) || (sp->controller == PCIC_VG465) || (sp->controller == PCIC_VG365)) - setb(sp, 0x2f, 0x03) ; + setb(sp, PCIC_CVSR, PCIC_CVSR_VS); else - setb(sp, 0x16, 0x02); + setb(sp, PCIC_MISC1, PCIC_MISC1_VCC_33); break; case 50: if (sp->controller == PCIC_IBM_KING) { @@ -654,9 +647,9 @@ pcic_power(struct slot *slt) (sp->controller == PCIC_VG469) || (sp->controller == PCIC_VG465) || (sp->controller == PCIC_VG365)) - clrb(sp, 0x2f, 0x03) ; + clrb(sp, PCIC_CVSR, PCIC_CVSR_VS); else - clrb(sp, 0x16, 0x02); + clrb(sp, PCIC_MISC1, PCIC_MISC1_VCC_33); break; } break; @@ -671,7 +664,7 @@ pcic_power(struct slot *slt) /* Some chips are smarter than us it seems, so if we weren't * allowed to use 5V, try 3.3 instead */ - if (!(sp->getb(sp, PCIC_STATUS) & 0x40) && slt->pwr.vcc == 50) { + if (!(sp->getb(sp, PCIC_STATUS) & PCIC_POW) && slt->pwr.vcc == 50) { slt->pwr.vcc = 33; slt->pwr.vpp = 0; return (pcic_power(slt)); @@ -681,7 +674,8 @@ pcic_power(struct slot *slt) /* * tell the PCIC which irq we want to use. only the following are legal: - * 3, 4, 5, 7, 9, 10, 11, 12, 14, 15 + * 3, 4, 5, 7, 9, 10, 11, 12, 14, 15. We require the callers of this + * routine to do the check for legality. */ static void pcic_mapirq(struct slot *slt, int irq) @@ -690,7 +684,8 @@ pcic_mapirq(struct slot *slt, int irq) if (irq == 0) clrb(sp, PCIC_INT_GEN, 0xF); else - sp->putb(sp, PCIC_INT_GEN, (sp->getb(sp, PCIC_INT_GEN) & 0xF0) | irq); + sp->putb(sp, PCIC_INT_GEN, + (sp->getb(sp, PCIC_INT_GEN) & 0xF0) | irq); } /* @@ -781,6 +776,7 @@ pcicintr(void *arg) PCIC_CD) { pccard_event(sp->slt, card_inserted); } else { + pcic_disable(sp->slt); pccard_event(sp->slt, card_removed); } } @@ -797,9 +793,9 @@ pcic_resume(struct slot *slt) { struct pcic_slot *sp = slt->cdata; - sp->putb(sp, PCIC_STAT_INT, (slt->irq << 4) | 0xF); + do_mgt_irq(sp, slt->irq); if (sp->controller == PCIC_PD672X) { - setb(sp, PCIC_MISC1, PCIC_SPKR_EN); + setb(sp, PCIC_MISC1, PCIC_MISC1_SPEAKER); setb(sp, PCIC_MISC2, PCIC_LPDM_EN); } } @@ -898,6 +894,12 @@ pcic_setup_intr(device_t dev, device_t child, struct resource *irq, struct pccard_devinfo *devi = device_get_ivars(child); int err; + if (((1 << rman_get_start(irq)) & PCIC_INT_MASK_ALLOWED) == 0) { + device_printf(dev, "Hardware does not support irq %ld.\n", + rman_get_start(irq)); + return (EINVAL); + } + err = bus_generic_setup_intr(dev, child, irq, flags, intr, arg, cookiep); if (err == 0) diff --git a/sys/pccard/slot.h b/sys/pccard/slot.h index edd1400..f43122c 100644 --- a/sys/pccard/slot.h +++ b/sys/pccard/slot.h @@ -66,8 +66,6 @@ struct slot_ctrl { /* Set power values */ int (*ioctl) __P((struct slot *, int, caddr_t)); /* ioctl to lower level */ - void (*mapirq) __P((struct slot *, int)); - /* Map interrupt number */ void (*resume) __P((struct slot *)); /* suspend/resume support */ int maxmem; /* Number of allowed memory windows */ |