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:
parent
1368e3d93c
commit
768040dd66
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue