Various cleanup:

* Clean up the socket state earlier in the attach process -- not relying on
  the socket attachment to do it.
* Get rid of PCIC_LASTSTATE_HALF.  It's pointless.
* In pcic_wait_ready(), also check for the card vanishing, like in pccbb.
* Assert #RESET before powering up the card, not after.  (I think it was
  actually okay because the value was left as 0 from a previous disable or
  the initial socket attach, but...
* If the card fails to come ready, don't bother reinstating windows or
  anything -- just power it down.
This commit is contained in:
mycroft 2004-08-12 13:37:40 +00:00
parent 1368e3d93c
commit 768040dd66
2 changed files with 64 additions and 77 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: i82365.c,v 1.82 2004/08/11 01:51:41 mycroft Exp $ */ /* $NetBSD: i82365.c,v 1.83 2004/08/12 13:37:40 mycroft Exp $ */
/* /*
* Copyright (c) 2000 Christian E. Hopps. All rights reserved. * Copyright (c) 2000 Christian E. Hopps. All rights reserved.
@ -31,7 +31,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: i82365.c,v 1.82 2004/08/11 01:51:41 mycroft Exp $"); __KERNEL_RCSID(0, "$NetBSD: i82365.c,v 1.83 2004/08/12 13:37:40 mycroft Exp $");
#define PCICDEBUG #define PCICDEBUG
@ -87,7 +87,7 @@ void pcic_event_thread __P((void *));
void pcic_queue_event __P((struct pcic_handle *, int)); void pcic_queue_event __P((struct pcic_handle *, int));
void pcic_power __P((int, void *)); void pcic_power __P((int, void *));
static void pcic_wait_ready __P((struct pcic_handle *)); static int pcic_wait_ready __P((struct pcic_handle *));
static void pcic_delay __P((struct pcic_handle *, int, const char *)); static void pcic_delay __P((struct pcic_handle *, int, const char *));
static u_int8_t st_pcic_read __P((struct pcic_handle *, int)); static u_int8_t st_pcic_read __P((struct pcic_handle *, int));
@ -276,8 +276,15 @@ pcic_attach(sc)
SIMPLEQ_INIT(&h->events); SIMPLEQ_INIT(&h->events);
/* disable interrupts and leave socket in reset */ /* disable interrupts and leave socket in reset */
pcic_write(h, PCIC_CSC_INTR, 0);
pcic_write(h, PCIC_INTR, 0); pcic_write(h, PCIC_INTR, 0);
/* zero out the address windows */
pcic_write(h, PCIC_ADDRWIN_ENABLE, 0);
/* power down the socket */
pcic_write(h, PCIC_PWRCTL, 0);
pcic_write(h, PCIC_CSC_INTR, 0);
(void) pcic_read(h, PCIC_CSC); (void) pcic_read(h, PCIC_CSC);
} }
} }
@ -424,7 +431,7 @@ pcic_attach_socket_finish(h)
struct pcic_handle *h; struct pcic_handle *h;
{ {
struct pcic_softc *sc = (struct pcic_softc *)h->ph_parent; struct pcic_softc *sc = (struct pcic_softc *)h->ph_parent;
int reg, intr; int reg;
DPRINTF(("%s: attach finish socket %ld\n", h->ph_parent->dv_xname, DPRINTF(("%s: attach finish socket %ld\n", h->ph_parent->dv_xname,
(long) (h - &sc->handle[0]))); (long) (h - &sc->handle[0])));
@ -450,20 +457,11 @@ pcic_attach_socket_finish(h)
pcic_write(h, PCIC_CSC_INTR, reg); pcic_write(h, PCIC_CSC_INTR, reg);
/* steer above mgmt interrupt to configured place */ /* steer above mgmt interrupt to configured place */
intr = pcic_read(h, PCIC_INTR);
intr &= ~(PCIC_INTR_IRQ_MASK | PCIC_INTR_ENABLE);
if (sc->irq == 0) if (sc->irq == 0)
intr |= PCIC_INTR_ENABLE; pcic_write(h, PCIC_INTR, PCIC_INTR_ENABLE);
pcic_write(h, PCIC_INTR, intr);
/* power down the socket */
pcic_write(h, PCIC_PWRCTL, 0);
/* zero out the address windows */
pcic_write(h, PCIC_ADDRWIN_ENABLE, 0);
/* clear possible card detect interrupt */ /* clear possible card detect interrupt */
pcic_read(h, PCIC_CSC); (void) pcic_read(h, PCIC_CSC);
DPRINTF(("%s: attach finish vendor 0x%02x\n", h->ph_parent->dv_xname, DPRINTF(("%s: attach finish vendor 0x%02x\n", h->ph_parent->dv_xname,
h->vendor)); h->vendor));
@ -799,9 +797,7 @@ pcic_intr_socket(h)
h->ph_parent->dv_xname)); h->ph_parent->dv_xname));
pcic_queue_event(h, PCIC_EVENT_REMOVAL); pcic_queue_event(h, PCIC_EVENT_REMOVAL);
} }
h->laststate = h->laststate = PCIC_LASTSTATE_EMPTY;
((statreg & PCIC_IF_STATUS_CARDDETECT_MASK) == 0) ?
PCIC_LASTSTATE_EMPTY : PCIC_LASTSTATE_HALF;
} }
} }
if (cscreg & PCIC_CSC_READY) { if (cscreg & PCIC_CSC_READY) {
@ -1360,33 +1356,31 @@ pcic_chip_io_unmap(pch, window)
h->ioalloc &= ~(1 << window); h->ioalloc &= ~(1 << window);
} }
static void static int
pcic_wait_ready(h) pcic_wait_ready(h)
struct pcic_handle *h; struct pcic_handle *h;
{ {
u_int8_t stat;
int i; int i;
/* wait an initial 10ms for quick cards */ /* wait an initial 10ms for quick cards */
if (pcic_read(h, PCIC_IF_STATUS) & PCIC_IF_STATUS_READY) stat = pcic_read(h, PCIC_IF_STATUS);
return; if (stat & PCIC_IF_STATUS_READY)
return (0);
pcic_delay(h, 10, "pccwr0"); pcic_delay(h, 10, "pccwr0");
for (i = 0; i < 50; i++) { for (i = 0; i < 50; i++) {
if (pcic_read(h, PCIC_IF_STATUS) & PCIC_IF_STATUS_READY) stat = pcic_read(h, PCIC_IF_STATUS);
return; if (stat & PCIC_IF_STATUS_READY)
return (0);
if ((stat & PCIC_IF_STATUS_CARDDETECT_MASK) !=
PCIC_IF_STATUS_CARDDETECT_PRESENT)
return (ENXIO);
/* wait .1s (100ms) each iteration now */ /* wait .1s (100ms) each iteration now */
pcic_delay(h, 100, "pccwr1"); pcic_delay(h, 100, "pccwr1");
#ifdef PCICDEBUG
if (pcic_debug) {
if ((i > 20) && (i % 100 == 99))
printf(".");
}
#endif
} }
#ifdef DIAGNOSTIC printf("pcic_wait_ready: ready never happened, status=%02x\n", stat);
printf("pcic_wait_ready: ready never happened, status = %02x\n", return (EWOULDBLOCK);
pcic_read(h, PCIC_IF_STATUS));
#endif
} }
/* /*
@ -1400,18 +1394,12 @@ pcic_delay(h, timo, wmesg)
{ {
#ifdef DIAGNOSTIC #ifdef DIAGNOSTIC
if (timo <= 0) { if (timo <= 0)
printf("called with timeout %d\n", timo); panic("pcic_delay: called with timeout %d", timo);
panic("pcic_delay"); if (!curlwp)
} panic("pcic_delay: called in interrupt context");
if (curlwp == NULL) { if (!h->event_thread)
printf("called in interrupt context\n"); panic("pcic_delay: no event thread");
panic("pcic_delay");
}
if (h->event_thread == NULL) {
printf("no event thread\n");
panic("pcic_delay");
}
#endif #endif
DPRINTF(("pcic_delay: \"%s\" %p, sleep %d ms\n", DPRINTF(("pcic_delay: \"%s\" %p, sleep %d ms\n",
wmesg, h->event_thread, timo)); wmesg, h->event_thread, timo));
@ -1423,8 +1411,9 @@ pcic_chip_socket_enable(pch)
pcmcia_chipset_handle_t pch; pcmcia_chipset_handle_t pch;
{ {
struct pcic_handle *h = (struct pcic_handle *) pch; struct pcic_handle *h = (struct pcic_handle *) pch;
int win, intr, pwr; int win;
#if defined(DIAGNOSTIC) || defined(PCICDEBUG) u_int8_t power, intr;
#ifdef DIAGNOSTIC
int reg; int reg;
#endif #endif
@ -1441,15 +1430,13 @@ pcic_chip_socket_enable(pch)
/* zero out the address windows */ /* zero out the address windows */
pcic_write(h, PCIC_ADDRWIN_ENABLE, 0); pcic_write(h, PCIC_ADDRWIN_ENABLE, 0);
/* power down the socket to reset it, clear the card reset pin */ /* disable socket: negate output enable bit and power off */
pwr = 0; power = 0;
pcic_write(h, PCIC_PWRCTL, pwr); pcic_write(h, PCIC_PWRCTL, power);
/* /* now make sure we have reset# active */
* wait 300ms until power fails (Tpf). Then, wait 100ms since intr &= ~PCIC_INTR_RESET;
* we are changing Vcc (Toff). pcic_write(h, PCIC_INTR, intr);
*/
pcic_delay(h, 300 + 100, "pccen0");
/* /*
* power hack for RICOH RF5C[23]96 * power hack for RICOH RF5C[23]96
@ -1481,9 +1468,10 @@ pcic_chip_socket_enable(pch)
pcic_write(h, 0x2f, pcic_read(h, 0x2f) & ~0x03); pcic_write(h, 0x2f, pcic_read(h, 0x2f) & ~0x03);
printf("cvsr = %02x\n", pcic_read(h, 0x2f)); printf("cvsr = %02x\n", pcic_read(h, 0x2f));
#endif #endif
/* power up the socket */ /* power up the socket */
pwr |= PCIC_PWRCTL_DISABLE_RESETDRV | PCIC_PWRCTL_PWR_ENABLE | PCIC_PWRCTL_VPP1_VCC; power |= PCIC_PWRCTL_PWR_ENABLE | PCIC_PWRCTL_VPP1_VCC;
pcic_write(h, PCIC_PWRCTL, pwr); pcic_write(h, PCIC_PWRCTL, power);
/* /*
* wait 100ms until power raise (Tpr) and 20ms to become * wait 100ms until power raise (Tpr) and 20ms to become
@ -1493,15 +1481,10 @@ pcic_chip_socket_enable(pch)
* (300ms is added here). * (300ms is added here).
*/ */
pcic_delay(h, 100 + 20 + 300, "pccen1"); pcic_delay(h, 100 + 20 + 300, "pccen1");
pwr |= PCIC_PWRCTL_OE;
pcic_write(h, PCIC_PWRCTL, pwr);
/* now make sure we have reset# active */ power |= PCIC_PWRCTL_OE;
intr &= ~PCIC_INTR_RESET; pcic_write(h, PCIC_PWRCTL, power);
pcic_write(h, PCIC_INTR, intr);
pcic_write(h, PCIC_PWRCTL, PCIC_PWRCTL_DISABLE_RESETDRV |
PCIC_PWRCTL_OE | PCIC_PWRCTL_PWR_ENABLE | PCIC_PWRCTL_VPP1_VCC);
/* /*
* hold RESET at least 10us, this is a min allow for slop in * hold RESET at least 10us, this is a min allow for slop in
* delay routine. * delay routine.
@ -1515,16 +1498,18 @@ pcic_chip_socket_enable(pch)
/* wait 20ms as per pc card standard (r2.01) section 4.3.6 */ /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
pcic_delay(h, 20, "pccen2"); pcic_delay(h, 20, "pccen2");
#if defined(DIAGNOSTIC) || defined(PCICDEBUG)
reg = pcic_read(h, PCIC_IF_STATUS);
#endif
#ifdef DIAGNOSTIC #ifdef DIAGNOSTIC
if (!(reg & PCIC_IF_STATUS_POWERACTIVE)) { reg = pcic_read(h, PCIC_IF_STATUS);
printf("pcic_chip_socket_enable: status %x\n", reg); if ((reg & PCIC_IF_STATUS_POWERACTIVE) == 0)
} printf("pcic_chip_socket_enable: no power, status=%x\n", reg);
#endif #endif
/* wait for the chip to finish initializing */ /* wait for the chip to finish initializing */
pcic_wait_ready(h); if (pcic_wait_ready(h)) {
/* XXX return a failure status?? */
pcic_write(h, PCIC_PWRCTL, 0);
return;
}
/* reinstall all the memory and io mappings */ /* reinstall all the memory and io mappings */
for (win = 0; win < PCIC_MEM_WINS; win++) for (win = 0; win < PCIC_MEM_WINS; win++)
@ -1542,7 +1527,7 @@ pcic_chip_socket_disable(pch)
pcmcia_chipset_handle_t pch; pcmcia_chipset_handle_t pch;
{ {
struct pcic_handle *h = (struct pcic_handle *) pch; struct pcic_handle *h = (struct pcic_handle *) pch;
int intr; u_int8_t intr;
DPRINTF(("pcic_chip_socket_disable\n")); DPRINTF(("pcic_chip_socket_disable\n"));
@ -1554,9 +1539,12 @@ pcic_chip_socket_disable(pch)
/* zero out the address windows */ /* zero out the address windows */
pcic_write(h, PCIC_ADDRWIN_ENABLE, 0); pcic_write(h, PCIC_ADDRWIN_ENABLE, 0);
/* power down the socket */ /* disable socket: negate output enable bit and power off */
pcic_write(h, PCIC_PWRCTL, 0); pcic_write(h, PCIC_PWRCTL, 0);
/* wait 300ms for power to fall */
pcic_delay(h, 300, "pccwr1");
h->flags &= ~PCIC_FLAG_ENABLED; h->flags &= ~PCIC_FLAG_ENABLED;
} }

View File

@ -1,4 +1,4 @@
/* $NetBSD: i82365var.h,v 1.19 2004/08/11 00:18:19 mycroft Exp $ */ /* $NetBSD: i82365var.h,v 1.20 2004/08/12 13:37:40 mycroft Exp $ */
/* /*
* Copyright (c) 1997 Marc Horowitz. All rights reserved. * Copyright (c) 1997 Marc Horowitz. All rights reserved.
@ -86,8 +86,7 @@ struct pcic_handle {
#define PCIC_FLAG_CARDP 0x0002 #define PCIC_FLAG_CARDP 0x0002
#define PCIC_FLAG_ENABLED 0x0004 #define PCIC_FLAG_ENABLED 0x0004
#define PCIC_LASTSTATE_PRESENT 0x0002 #define PCIC_LASTSTATE_PRESENT 0x0001
#define PCIC_LASTSTATE_HALF 0x0001
#define PCIC_LASTSTATE_EMPTY 0x0000 #define PCIC_LASTSTATE_EMPTY 0x0000
#define C0SA 0 #define C0SA 0