Fix about insertion/removal event problem.

This commit is contained in:
msaitoh 1999-01-21 07:43:32 +00:00
parent 74a54bbbc8
commit 88176e7d20
2 changed files with 91 additions and 25 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: i82365.c,v 1.19 1999/01/01 14:05:18 christos Exp $ */ /* $NetBSD: i82365.c,v 1.20 1999/01/21 07:43:32 msaitoh Exp $ */
#define PCICDEBUG #define PCICDEBUG
@ -36,6 +36,7 @@
#include <sys/systm.h> #include <sys/systm.h>
#include <sys/device.h> #include <sys/device.h>
#include <sys/extent.h> #include <sys/extent.h>
#include <sys/kernel.h>
#include <sys/malloc.h> #include <sys/malloc.h>
#include <sys/kthread.h> #include <sys/kthread.h>
@ -190,6 +191,7 @@ pcic_attach(sc)
} else { } else {
sc->handle[0].flags = 0; sc->handle[0].flags = 0;
} }
sc->handle[0].laststate = PCIC_LASTSTATE_EMPTY;
DPRINTF((" 0x%02x", reg)); DPRINTF((" 0x%02x", reg));
@ -201,6 +203,7 @@ pcic_attach(sc)
} else { } else {
sc->handle[1].flags = 0; sc->handle[1].flags = 0;
} }
sc->handle[1].laststate = PCIC_LASTSTATE_EMPTY;
DPRINTF((" 0x%02x", reg)); DPRINTF((" 0x%02x", reg));
@ -220,6 +223,7 @@ pcic_attach(sc)
} else { } else {
sc->handle[2].flags = 0; sc->handle[2].flags = 0;
} }
sc->handle[2].laststate = PCIC_LASTSTATE_EMPTY;
DPRINTF((" 0x%02x", reg)); DPRINTF((" 0x%02x", reg));
@ -232,6 +236,7 @@ pcic_attach(sc)
} else { } else {
sc->handle[3].flags = 0; sc->handle[3].flags = 0;
} }
sc->handle[3].laststate = PCIC_LASTSTATE_EMPTY;
DPRINTF((" 0x%02x\n", reg)); DPRINTF((" 0x%02x\n", reg));
} }
@ -386,17 +391,60 @@ pcic_event_thread(arg)
splx(s); splx(s);
(void) tsleep(&h->events, PWAIT, "pcicev", 0); (void) tsleep(&h->events, PWAIT, "pcicev", 0);
continue; continue;
} else {
splx(s);
/* sleep .25s to be enqueued chatterling interrupts */
(void) tsleep((caddr_t)pcic_event_thread, PWAIT, "pcicss", hz/4);
} }
s = splhigh();
SIMPLEQ_REMOVE_HEAD(&h->events, pe, pe_q); SIMPLEQ_REMOVE_HEAD(&h->events, pe, pe_q);
splx(s); splx(s);
switch (pe->pe_type) { switch (pe->pe_type) {
case PCIC_EVENT_INSERTION: case PCIC_EVENT_INSERTION:
s = splhigh();
while (1) {
struct pcic_event *pe1, *pe2;
if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL)
break;
if (pe1->pe_type != PCIC_EVENT_REMOVAL)
break;
if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL)
break;
if (pe2->pe_type == PCIC_EVENT_INSERTION) {
SIMPLEQ_REMOVE_HEAD(&h->events, pe1, pe_q);
free(pe1, M_TEMP);
SIMPLEQ_REMOVE_HEAD(&h->events, pe2, pe_q);
free(pe2, M_TEMP);
}
}
splx(s);
DPRINTF(("%s: insertion event\n", h->sc->dev.dv_xname)); DPRINTF(("%s: insertion event\n", h->sc->dev.dv_xname));
pcic_attach_card(h); pcic_attach_card(h);
break; break;
case PCIC_EVENT_REMOVAL: case PCIC_EVENT_REMOVAL:
s = splhigh();
while (1) {
struct pcic_event *pe1, *pe2;
if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL)
break;
if (pe1->pe_type != PCIC_EVENT_INSERTION)
break;
if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL)
break;
if (pe2->pe_type == PCIC_EVENT_REMOVAL) {
SIMPLEQ_REMOVE_HEAD(&h->events, pe1, pe_q);
free(pe1, M_TEMP);
SIMPLEQ_REMOVE_HEAD(&h->events, pe2, pe_q);
free(pe2, M_TEMP);
}
}
splx(s);
DPRINTF(("%s: removal event\n", h->sc->dev.dv_xname)); DPRINTF(("%s: removal event\n", h->sc->dev.dv_xname));
pcic_detach_card(h, DETACH_FORCE); pcic_detach_card(h, DETACH_FORCE);
break; break;
@ -455,8 +503,12 @@ pcic_init_socket(h)
reg = pcic_read(h, PCIC_IF_STATUS); reg = pcic_read(h, PCIC_IF_STATUS);
if ((reg & PCIC_IF_STATUS_CARDDETECT_MASK) == if ((reg & PCIC_IF_STATUS_CARDDETECT_MASK) ==
PCIC_IF_STATUS_CARDDETECT_PRESENT) PCIC_IF_STATUS_CARDDETECT_PRESENT) {
pcic_attach_card(h); pcic_attach_card(h);
h->laststate = PCIC_LASTSTATE_PRESENT;
} else {
h->laststate = PCIC_LASTSTATE_EMPTY;
}
} }
int int
@ -596,22 +648,25 @@ pcic_intr_socket(h)
if ((statreg & PCIC_IF_STATUS_CARDDETECT_MASK) == if ((statreg & PCIC_IF_STATUS_CARDDETECT_MASK) ==
PCIC_IF_STATUS_CARDDETECT_PRESENT) { PCIC_IF_STATUS_CARDDETECT_PRESENT) {
if (!(h->flags & PCIC_FLAG_CARDP)) { if (h->laststate != PCIC_LASTSTATE_PRESENT) {
DPRINTF(("%s: enqueing INSERTION event\n", DPRINTF(("%s: enqueing INSERTION event\n",
h->sc->dev.dv_xname)); h->sc->dev.dv_xname));
pcic_queue_event(h, PCIC_EVENT_INSERTION); pcic_queue_event(h, PCIC_EVENT_INSERTION);
} }
h->laststate = PCIC_LASTSTATE_PRESENT;
} else { } else {
if (h->flags & PCIC_FLAG_CARDP) { if (h->laststate == PCIC_LASTSTATE_PRESENT) {
/* Deactivate the card now. */ /* Deactivate the card now. */
DPRINTF(("%s: deactivating card\n", DPRINTF(("%s: deactivating card\n",
h->sc->dev.dv_xname)); h->sc->dev.dv_xname));
pcic_deactivate_card(h); pcic_deactivate_card(h);
DPRINTF(("%s: enqueing REMOVAL event\n", DPRINTF(("%s: enqueing REMOVAL event\n",
h->sc->dev.dv_xname)); h->sc->dev.dv_xname));
pcic_queue_event(h, PCIC_EVENT_REMOVAL); pcic_queue_event(h, PCIC_EVENT_REMOVAL);
} }
h->laststate = ((statreg & PCIC_IF_STATUS_CARDDETECT_MASK) == 0)
? PCIC_LASTSTATE_EMPTY : PCIC_LASTSTATE_HALF;
} }
} }
if (cscreg & PCIC_CSC_READY) { if (cscreg & PCIC_CSC_READY) {
@ -651,13 +706,14 @@ pcic_attach_card(h)
struct pcic_handle *h; struct pcic_handle *h;
{ {
if (h->flags & PCIC_FLAG_CARDP) if (!(h->flags & PCIC_FLAG_CARDP)) {
panic("pcic_attach_card: already attached"); /* call the MI attach function */
pcmcia_card_attach(h->pcmcia);
/* call the MI attach function */ h->flags |= PCIC_FLAG_CARDP;
pcmcia_card_attach(h->pcmcia); } else {
DPRINTF(("pcic_attach_card: already attached"));
h->flags |= PCIC_FLAG_CARDP; }
} }
void void
@ -666,13 +722,14 @@ pcic_detach_card(h, flags)
int flags; /* DETACH_* */ int flags; /* DETACH_* */
{ {
if (!(h->flags & PCIC_FLAG_CARDP)) if (h->flags & PCIC_FLAG_CARDP) {
panic("pcic_detach_card: already detached"); h->flags &= ~PCIC_FLAG_CARDP;
h->flags &= ~PCIC_FLAG_CARDP; /* call the MI detach function */
pcmcia_card_detach(h->pcmcia, flags);
/* call the MI detach function */ } else {
pcmcia_card_detach(h->pcmcia, flags); DPRINTF(("pcic_detach_card: already detached"));
}
} }
void void
@ -680,9 +737,6 @@ pcic_deactivate_card(h)
struct pcic_handle *h; struct pcic_handle *h;
{ {
if (!(h->flags & PCIC_FLAG_CARDP))
panic("pcic_deactivate_card: already detached");
/* call the MI deactivate function */ /* call the MI deactivate function */
pcmcia_card_deactivate(h->pcmcia); pcmcia_card_deactivate(h->pcmcia);
@ -1208,9 +1262,9 @@ pcic_chip_socket_enable(pch)
* stable (Tsu(Vcc)). * stable (Tsu(Vcc)).
* *
* some machines require some more time to be settled * some machines require some more time to be settled
* (another 200ms is added here). * (300ms is added here).
*/ */
delay((100 + 20 + 200) * 1000); delay((100 + 20 + 300) * 1000);
pcic_write(h, PCIC_PWRCTL, PCIC_PWRCTL_DISABLE_RESETDRV | PCIC_PWRCTL_OE pcic_write(h, PCIC_PWRCTL, PCIC_PWRCTL_DISABLE_RESETDRV | PCIC_PWRCTL_OE
| PCIC_PWRCTL_PWR_ENABLE); | PCIC_PWRCTL_PWR_ENABLE);
@ -1231,6 +1285,13 @@ pcic_chip_socket_enable(pch)
/* wait for the chip to finish initializing */ /* wait for the chip to finish initializing */
#ifdef DIAGNOSTIC
reg = pcic_read(h, PCIC_IF_STATUS);
if (!(reg & PCIC_IF_STATUS_POWERACTIVE)) {
printf("pcic_chip_socket_enable: status %x", reg);
}
#endif
pcic_wait_ready(h); pcic_wait_ready(h);
/* zero out the address windows */ /* zero out the address windows */

View File

@ -1,4 +1,4 @@
/* $NetBSD: i82365var.h,v 1.6 1999/01/01 14:05:18 christos Exp $ */ /* $NetBSD: i82365var.h,v 1.7 1999/01/21 07:43:33 msaitoh Exp $ */
/* /*
* Copyright (c) 1997 Marc Horowitz. All rights reserved. * Copyright (c) 1997 Marc Horowitz. All rights reserved.
@ -52,6 +52,7 @@ struct pcic_handle {
int vendor; int vendor;
int sock; int sock;
int flags; int flags;
int laststate;
int memalloc; int memalloc;
struct { struct {
bus_addr_t addr; bus_addr_t addr;
@ -76,6 +77,10 @@ struct pcic_handle {
#define PCIC_FLAG_SOCKETP 0x0001 #define PCIC_FLAG_SOCKETP 0x0001
#define PCIC_FLAG_CARDP 0x0002 #define PCIC_FLAG_CARDP 0x0002
#define PCIC_LASTSTATE_PRESENT 0x0002
#define PCIC_LASTSTATE_HALF 0x0001
#define PCIC_LASTSTATE_EMPTY 0x0000
#define C0SA PCIC_CHIP0_BASE+PCIC_SOCKETA_INDEX #define C0SA PCIC_CHIP0_BASE+PCIC_SOCKETA_INDEX
#define C0SB PCIC_CHIP0_BASE+PCIC_SOCKETB_INDEX #define C0SB PCIC_CHIP0_BASE+PCIC_SOCKETB_INDEX
#define C1SA PCIC_CHIP1_BASE+PCIC_SOCKETA_INDEX #define C1SA PCIC_CHIP1_BASE+PCIC_SOCKETA_INDEX