summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2002-09-04 06:53:37 +0000
committerimp <imp@FreeBSD.org>2002-09-04 06:53:37 +0000
commitb720c131c7532fffe5f7a40db73bd7fb3518a6ba (patch)
tree4ebfa5b99f9e745369cb81dc1715a4ae49ab6b2e /sys
parent469a54660c62e422b1cd51a6ad4f65086007b6bb (diff)
downloadFreeBSD-src-b720c131c7532fffe5f7a40db73bd7fb3518a6ba.zip
FreeBSD-src-b720c131c7532fffe5f7a40db73bd7fb3518a6ba.tar.gz
More in the continuing saga of phk vs his strange serial card.
In this installment, we learn that it is bad to access registers that are only defined for mfc cards in the interrupt handler when we do not in fact have a mfc card. For MFC cards, we'll only call the ISR if the this card interrupted bit is set. For non mfc cards (which are basically 90% of pccards in use), we always call the ISR and avoid touching the suspect registers. We always pacify the bit in the MFC case on the off chance that will help in the itnerrupt handler not being registed.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pccard/pccard.c100
1 files changed, 20 insertions, 80 deletions
diff --git a/sys/dev/pccard/pccard.c b/sys/dev/pccard/pccard.c
index 2376fc1..aa42cf2 100644
--- a/sys/dev/pccard/pccard.c
+++ b/sys/dev/pccard/pccard.c
@@ -717,70 +717,6 @@ pccard_function_disable(struct pccard_function *pf)
pf->sc->sc_enabled_count--;
}
-#if 0
-/* XXX These functions are needed, but not like this XXX */
-int
-pccard_io_map(struct pccard_function *pf, int width, bus_addr_t offset,
- bus_size_t size, struct pccard_io_handle *pcihp, int *windowp)
-{
- int reg;
-
- if (pccard_chip_io_map(pf->sc->pct, pf->sc->pch, width, offset, size,
- pcihp, windowp))
- return (1);
-
- /*
- * XXX in the multifunction multi-iospace-per-function case, this
- * needs to cooperate with io_alloc to make sure that the spaces
- * don't overlap, and that the ccr's are set correctly
- */
-
- if (pccard_mfc(pf->sc)) {
- long tmp, iosize;
-
- if (pf->pf_mfc_iomax == 0) {
- pf->pf_mfc_iobase = pcihp->addr + offset;
- pf->pf_mfc_iomax = pf->pf_mfc_iobase + size;
- } else {
- /* this makes the assumption that nothing overlaps */
- if (pf->pf_mfc_iobase > pcihp->addr + offset)
- pf->pf_mfc_iobase = pcihp->addr + offset;
- if (pf->pf_mfc_iomax < pcihp->addr + offset + size)
- pf->pf_mfc_iomax = pcihp->addr + offset + size;
- }
-
- tmp = pf->pf_mfc_iomax - pf->pf_mfc_iobase;
- /* round up to nearest (2^n)-1 */
- for (iosize = 1; iosize >= tmp; iosize <<= 1)
- ;
- iosize--;
-
- pccard_ccr_write(pf, PCCARD_CCR_IOBASE0,
- pf->pf_mfc_iobase & 0xff);
- pccard_ccr_write(pf, PCCARD_CCR_IOBASE1,
- (pf->pf_mfc_iobase >> 8) & 0xff);
- pccard_ccr_write(pf, PCCARD_CCR_IOBASE2, 0);
- pccard_ccr_write(pf, PCCARD_CCR_IOBASE3, 0);
-
- pccard_ccr_write(pf, PCCARD_CCR_IOSIZE, iosize);
-
- reg = pccard_ccr_read(pf, PCCARD_CCR_OPTION);
- reg |= PCCARD_CCR_OPTION_ADDR_DECODE;
- pccard_ccr_write(pf, PCCARD_CCR_OPTION, reg);
- }
- return (0);
-}
-
-void
-pccard_io_unmap(struct pccard_function *pf, int window)
-{
-
- pccard_chip_io_unmap(pf->sc->pct, pf->sc->pch, window);
-
- /* XXX Anything for multi-function cards? */
-}
-#endif
-
/*
* simulate the old "probe" routine. In the new world order, the driver
* needs to grab devices while in the old they were assigned to the device by
@@ -1174,27 +1110,31 @@ static void
pccard_intr(void *arg)
{
struct pccard_function *pf = (struct pccard_function*) arg;
-#ifdef COOKIE_FOR_WARNER
int reg;
-
- if (pf->intr_handler == NULL)
- return;
+ int doisr = 1;
/*
- * XXX The CCR_STATUS register bits used here are
- * only valid for multi function cards.
+ * MFC cards know if they interrupted, so we have to ack the
+ * interrupt and call the ISR. Non-MFC cards don't have these
+ * bits, so they always get called. Many non-MFC cards have
+ * this bit set always upon read, but some do not.
+ *
+ * We always ack the interrupt, even if there's no ISR
+ * for the card. This is done on the theory that acking
+ * the interrupt will pacify the card enough to keep an
+ * interrupt storm from happening. Of course this won't
+ * help in the non-MFC case.
*/
- reg = pccard_ccr_read(pf, PCCARD_CCR_STATUS);
- if (reg & PCCARD_CCR_STATUS_INTR) {
- pccard_ccr_write(pf, PCCARD_CCR_STATUS,
- reg & ~PCCARD_CCR_STATUS_INTR);
- pf->intr_handler(pf->intr_handler_arg);
+ if (pccard_mfc(pf->sc)) {
+ reg = pccard_ccr_read(pf, PCCARD_CCR_STATUS);
+ if (reg & PCCARD_CCR_STATUS_INTR)
+ pccard_ccr_write(pf, PCCARD_CCR_STATUS,
+ reg & ~PCCARD_CCR_STATUS_INTR);
+ else
+ doisr = 0;
}
-#else
- if (pf->intr_handler == NULL)
- return;
- pf->intr_handler(pf->intr_handler_arg);
-#endif
+ if (pf->intr_handler != NULL && doisr)
+ pf->intr_handler(pf->intr_handler_arg);
}
static int
OpenPOWER on IntegriCloud