summaryrefslogtreecommitdiffstats
path: root/sys/pccard/pcic.c
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2001-05-14 21:08:20 +0000
committerimp <imp@FreeBSD.org>2001-05-14 21:08:20 +0000
commit1d2e092aa3b4717a37c7c031dcf3a851dcd5714e (patch)
tree1f601fcd797f36cb586c59923db08230227577fd /sys/pccard/pcic.c
parenta4894456f12b9b51f0f12f6c6a248570ba9abe79 (diff)
downloadFreeBSD-src-1d2e092aa3b4717a37c7c031dcf3a851dcd5714e.zip
FreeBSD-src-1d2e092aa3b4717a37c7c031dcf3a851dcd5714e.tar.gz
Fix the so called "static bug" in polling mode. Some desktop cards
have bad grounding characteristics which allow small static discharges (or sunspots, we're not 100% sure which) to reach the bridge chip. This causes the bridge chip to wedge/reset itself. There's no known cure short of rebooting. The bug manifests itself by the STAT_CHG return 0xff when read. This is impossible because the upper bits are reserved (and therefore zero). In addition, some of the lower bits are one only for memory cards, which OLDCARD doesn't support, so if they are set, something seriously foobar'd is going on. So far we've seen this in exactly one brand of pcmcia <-> isa bridge which plug and play identifies only as "VIA PCMCIA CARD". This card just has buffers on the isa card and the actual bridge chip on the remote slot, which is connected by long ribbon cables. We think this long cable run, coupled with the lack of coupling capacitors is a major reason why it is so static sensitive while its bretheren aren't. Work Supported by: Timing Solutions, Inc. MFC After: 3 days
Diffstat (limited to 'sys/pccard/pcic.c')
-rw-r--r--sys/pccard/pcic.c39
1 files changed, 33 insertions, 6 deletions
diff --git a/sys/pccard/pcic.c b/sys/pccard/pcic.c
index f76e72f..f9fd5ab 100644
--- a/sys/pccard/pcic.c
+++ b/sys/pccard/pcic.c
@@ -60,6 +60,7 @@
* Prototypes for interrupt handler.
*/
static driver_intr_t pcicintr;
+static int pcicintr1(void *);
static int pcic_ioctl(struct slot *, int, caddr_t);
static int pcic_power(struct slot *);
static void pcic_mapirq(struct slot *, int);
@@ -818,6 +819,15 @@ pcic_disable(struct slot *slt)
}
/*
+ * Wrapper function for pcicintr so that signatures match.
+ */
+static void
+pcicintr(void *arg)
+{
+ pcicintr1(arg);
+}
+
+/*
* PCIC timer. If the controller doesn't have a free IRQ to use
* or if interrupt steering doesn't work, poll the controller for
* insertion/removal events.
@@ -825,7 +835,11 @@ pcic_disable(struct slot *slt)
static void
pcictimeout(void *chan)
{
- pcicintr(chan);
+ if (pcicintr1(chan) != 0) {
+ printf("pcic%d: Static bug detected, ignoring hardware.\n",
+ (int) chan);
+ return;
+ }
pcictimeout_ch = timeout(pcictimeout, chan, hz/2);
}
@@ -835,8 +849,8 @@ pcictimeout(void *chan)
* register. If this is non-zero, then a change has occurred
* on this card, so send an event to the main code.
*/
-static void
-pcicintr(void *arg)
+static int
+pcicintr1(void *arg)
{
int slot, s;
unsigned char chg;
@@ -862,9 +876,21 @@ pcicintr(void *arg)
for (slot = 0; slot < PCIC_CARD_SLOTS; slot++, sp++) {
if (sp->slt &&
(chg = sp->getb(sp, PCIC_STAT_CHG)) != 0) {
- if (bootverbose)
- printf("Slot %d chg = 0x%x\n", slot,
- chg);
+ /*
+ * if chg is 0xff, then we know that
+ * we've hit the famous "static bug" for
+ * some desktop pcmcia cards. This is
+ * caused by static discharge frying the
+ * poor card's mind and it starts return 0xff
+ * forever. We return an error and stop
+ * polling the card. When we're interrupt
+ * based, we never see this. The card just
+ * goes away silently.
+ */
+ if (chg == 0xff) {
+ splx(s);
+ return (EIO);
+ }
if (chg & PCIC_CDTCH) {
if ((sp->getb(sp, PCIC_STATUS) &
PCIC_CD) == PCIC_CD) {
@@ -880,6 +906,7 @@ pcicintr(void *arg)
}
}
splx(s);
+ return (0);
}
/*
OpenPOWER on IntegriCloud