summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/pccard/i82365.h77
-rw-r--r--sys/pccard/pcic.c152
-rw-r--r--sys/pccard/slot.h2
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 */
OpenPOWER on IntegriCloud