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.
@ -31,7 +31,7 @@
*/
#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
@ -87,7 +87,7 @@ void pcic_event_thread __P((void *));
void pcic_queue_event __P((struct pcic_handle *, int));
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 u_int8_t st_pcic_read __P((struct pcic_handle *, int));
@ -276,8 +276,15 @@ pcic_attach(sc)
SIMPLEQ_INIT(&h->events);
/* disable interrupts and leave socket in reset */
pcic_write(h, PCIC_CSC_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);
}
}
@ -424,7 +431,7 @@ pcic_attach_socket_finish(h)
struct pcic_handle *h;
{
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,
(long) (h - &sc->handle[0])));
@ -450,20 +457,11 @@ pcic_attach_socket_finish(h)
pcic_write(h, PCIC_CSC_INTR, reg);
/* 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)
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);
pcic_write(h, PCIC_INTR, PCIC_INTR_ENABLE);
/* 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,
h->vendor));
@ -799,9 +797,7 @@ pcic_intr_socket(h)
h->ph_parent->dv_xname));
pcic_queue_event(h, PCIC_EVENT_REMOVAL);
}
h->laststate =
((statreg & PCIC_IF_STATUS_CARDDETECT_MASK) == 0) ?
PCIC_LASTSTATE_EMPTY : PCIC_LASTSTATE_HALF;
h->laststate = PCIC_LASTSTATE_EMPTY;
}
}
if (cscreg & PCIC_CSC_READY) {
@ -1360,33 +1356,31 @@ pcic_chip_io_unmap(pch, window)
h->ioalloc &= ~(1 << window);
}
static void
static int
pcic_wait_ready(h)
struct pcic_handle *h;
{
u_int8_t stat;
int i;
/* wait an initial 10ms for quick cards */
if (pcic_read(h, PCIC_IF_STATUS) & PCIC_IF_STATUS_READY)
return;
stat = pcic_read(h, PCIC_IF_STATUS);
if (stat & PCIC_IF_STATUS_READY)
return (0);
pcic_delay(h, 10, "pccwr0");
for (i = 0; i < 50; i++) {
if (pcic_read(h, PCIC_IF_STATUS) & PCIC_IF_STATUS_READY)
return;
stat = pcic_read(h, PCIC_IF_STATUS);
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 */
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",
pcic_read(h, PCIC_IF_STATUS));
#endif
printf("pcic_wait_ready: ready never happened, status=%02x\n", stat);
return (EWOULDBLOCK);
}
/*
@ -1400,18 +1394,12 @@ pcic_delay(h, timo, wmesg)
{
#ifdef DIAGNOSTIC
if (timo <= 0) {
printf("called with timeout %d\n", timo);
panic("pcic_delay");
}
if (curlwp == NULL) {
printf("called in interrupt context\n");
panic("pcic_delay");
}
if (h->event_thread == NULL) {
printf("no event thread\n");
panic("pcic_delay");
}
if (timo <= 0)
panic("pcic_delay: called with timeout %d", timo);
if (!curlwp)
panic("pcic_delay: called in interrupt context");
if (!h->event_thread)
panic("pcic_delay: no event thread");
#endif
DPRINTF(("pcic_delay: \"%s\" %p, sleep %d ms\n",
wmesg, h->event_thread, timo));
@ -1423,8 +1411,9 @@ pcic_chip_socket_enable(pch)
pcmcia_chipset_handle_t pch;
{
struct pcic_handle *h = (struct pcic_handle *) pch;
int win, intr, pwr;
#if defined(DIAGNOSTIC) || defined(PCICDEBUG)
int win;
u_int8_t power, intr;
#ifdef DIAGNOSTIC
int reg;
#endif
@ -1441,15 +1430,13 @@ pcic_chip_socket_enable(pch)
/* zero out the address windows */
pcic_write(h, PCIC_ADDRWIN_ENABLE, 0);
/* power down the socket to reset it, clear the card reset pin */
pwr = 0;
pcic_write(h, PCIC_PWRCTL, pwr);
/* disable socket: negate output enable bit and power off */
power = 0;
pcic_write(h, PCIC_PWRCTL, power);
/*
* wait 300ms until power fails (Tpf). Then, wait 100ms since
* we are changing Vcc (Toff).
*/
pcic_delay(h, 300 + 100, "pccen0");
/* now make sure we have reset# active */
intr &= ~PCIC_INTR_RESET;
pcic_write(h, PCIC_INTR, intr);
/*
* 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);
printf("cvsr = %02x\n", pcic_read(h, 0x2f));
#endif
/* power up the socket */
pwr |= PCIC_PWRCTL_DISABLE_RESETDRV | PCIC_PWRCTL_PWR_ENABLE | PCIC_PWRCTL_VPP1_VCC;
pcic_write(h, PCIC_PWRCTL, pwr);
power |= PCIC_PWRCTL_PWR_ENABLE | PCIC_PWRCTL_VPP1_VCC;
pcic_write(h, PCIC_PWRCTL, power);
/*
* wait 100ms until power raise (Tpr) and 20ms to become
@ -1493,15 +1481,10 @@ pcic_chip_socket_enable(pch)
* (300ms is added here).
*/
pcic_delay(h, 100 + 20 + 300, "pccen1");
pwr |= PCIC_PWRCTL_OE;
pcic_write(h, PCIC_PWRCTL, pwr);
/* now make sure we have reset# active */
intr &= ~PCIC_INTR_RESET;
pcic_write(h, PCIC_INTR, intr);
power |= PCIC_PWRCTL_OE;
pcic_write(h, PCIC_PWRCTL, power);
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
* delay routine.
@ -1515,16 +1498,18 @@ pcic_chip_socket_enable(pch)
/* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
pcic_delay(h, 20, "pccen2");
#if defined(DIAGNOSTIC) || defined(PCICDEBUG)
reg = pcic_read(h, PCIC_IF_STATUS);
#endif
#ifdef DIAGNOSTIC
if (!(reg & PCIC_IF_STATUS_POWERACTIVE)) {
printf("pcic_chip_socket_enable: status %x\n", reg);
}
reg = pcic_read(h, PCIC_IF_STATUS);
if ((reg & PCIC_IF_STATUS_POWERACTIVE) == 0)
printf("pcic_chip_socket_enable: no power, status=%x\n", reg);
#endif
/* 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 */
for (win = 0; win < PCIC_MEM_WINS; win++)
@ -1542,7 +1527,7 @@ pcic_chip_socket_disable(pch)
pcmcia_chipset_handle_t pch;
{
struct pcic_handle *h = (struct pcic_handle *) pch;
int intr;
u_int8_t intr;
DPRINTF(("pcic_chip_socket_disable\n"));
@ -1554,9 +1539,12 @@ pcic_chip_socket_disable(pch)
/* zero out the address windows */
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);
/* wait 300ms for power to fall */
pcic_delay(h, 300, "pccwr1");
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.
@ -86,8 +86,7 @@ struct pcic_handle {
#define PCIC_FLAG_CARDP 0x0002
#define PCIC_FLAG_ENABLED 0x0004
#define PCIC_LASTSTATE_PRESENT 0x0002
#define PCIC_LASTSTATE_HALF 0x0001
#define PCIC_LASTSTATE_PRESENT 0x0001
#define PCIC_LASTSTATE_EMPTY 0x0000
#define C0SA 0