Finish implementing interrupt-driven card insertion and removal support.
- Deactivate the card on removal and queue a REMOVAL event for the socket's event thread to finish the detach. - Queue an INSERTION event for the socket's event thread on insertion. Implement a few missing infrastructure pieces to support this. Hot swapping of PCMCIA cards now "works". (Not quite; things like network devices need changes for their respestive subsystems. These changes are coming soon...)
This commit is contained in:
parent
ab1b371163
commit
0c3ca7b31e
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: i82365.c,v 1.14 1998/11/16 22:41:01 thorpej Exp $ */
|
||||
/* $NetBSD: i82365.c,v 1.15 1998/11/17 08:49:11 thorpej Exp $ */
|
||||
|
||||
#define PCICDEBUG
|
||||
|
||||
@ -80,7 +80,8 @@ int pcic_print __P((void *arg, const char *pnp));
|
||||
int pcic_intr_socket __P((struct pcic_handle *));
|
||||
|
||||
void pcic_attach_card __P((struct pcic_handle *));
|
||||
void pcic_detach_card __P((struct pcic_handle *));
|
||||
void pcic_detach_card __P((struct pcic_handle *, int));
|
||||
void pcic_deactivate_card __P((struct pcic_handle *));
|
||||
|
||||
void pcic_chip_do_mem_map __P((struct pcic_handle *, int));
|
||||
void pcic_chip_do_io_map __P((struct pcic_handle *, int));
|
||||
@ -388,7 +389,7 @@ pcic_event_thread(arg)
|
||||
|
||||
case PCIC_EVENT_REMOVAL:
|
||||
DPRINTF(("%s: removal event\n", h->sc->dev.dv_xname));
|
||||
pcic_detach_card(h);
|
||||
pcic_detach_card(h, DETACH_FORCE);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -589,7 +590,11 @@ pcic_intr_socket(h)
|
||||
}
|
||||
} else {
|
||||
if (h->flags & PCIC_FLAG_CARDP) {
|
||||
/* XXX Should deactivate children NOW. */
|
||||
/* Deactivate the card now. */
|
||||
DPRINTF(("%s: deactivating card\n",
|
||||
h->sc->dev.dv_xname));
|
||||
pcic_deactivate_card(h);
|
||||
|
||||
DPRINTF(("%s: enqueing REMOVAL event\n",
|
||||
h->sc->dev.dv_xname));
|
||||
pcic_queue_event(h, PCIC_EVENT_REMOVAL);
|
||||
@ -632,37 +637,46 @@ void
|
||||
pcic_attach_card(h)
|
||||
struct pcic_handle *h;
|
||||
{
|
||||
|
||||
if (h->flags & PCIC_FLAG_CARDP)
|
||||
panic("pcic_attach_card: already attached");
|
||||
|
||||
/* call the MI attach function */
|
||||
|
||||
pcmcia_card_attach(h->pcmcia);
|
||||
|
||||
h->flags |= PCIC_FLAG_CARDP;
|
||||
}
|
||||
|
||||
void
|
||||
pcic_detach_card(h)
|
||||
pcic_detach_card(h, flags)
|
||||
struct pcic_handle *h;
|
||||
int flags; /* DETACH_* */
|
||||
{
|
||||
|
||||
if (!(h->flags & PCIC_FLAG_CARDP))
|
||||
panic("pcic_attach_card: already detached");
|
||||
|
||||
h->flags &= ~PCIC_FLAG_CARDP;
|
||||
|
||||
/* call the MI attach function */
|
||||
/* call the MI detach function */
|
||||
pcmcia_card_detach(h->pcmcia, flags);
|
||||
}
|
||||
|
||||
pcmcia_card_detach(h->pcmcia);
|
||||
void
|
||||
pcic_deactivate_card(h)
|
||||
struct pcic_handle *h;
|
||||
{
|
||||
|
||||
/* disable card detect resume and configuration reset */
|
||||
if (!(h->flags & PCIC_FLAG_CARDP))
|
||||
panic("pcic_deactivate_card: already detached");
|
||||
|
||||
/* call the MI deactivate function */
|
||||
pcmcia_card_deactivate(h->pcmcia);
|
||||
|
||||
/* power down the socket */
|
||||
|
||||
pcic_write(h, PCIC_PWRCTL, 0);
|
||||
|
||||
/* reset the card */
|
||||
|
||||
/* reset the socket */
|
||||
pcic_write(h, PCIC_INTR, 0);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: pcmcia.c,v 1.10 1998/11/14 01:54:25 thorpej Exp $ */
|
||||
/* $NetBSD: pcmcia.c,v 1.11 1998/11/17 08:49:12 thorpej Exp $ */
|
||||
|
||||
#define PCMCIADEBUG
|
||||
|
||||
@ -167,7 +167,16 @@ pcmcia_card_attach(dev)
|
||||
if (pf->cfe_head.sqh_first == NULL)
|
||||
continue;
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
if (pf->child != NULL) {
|
||||
printf("%s: %s still attached to function %d!\n",
|
||||
sc->dev.dv_xname, pf->child->dv_xname,
|
||||
pf->number);
|
||||
panic("pcmcia_card_attach");
|
||||
}
|
||||
#endif
|
||||
pf->sc = sc;
|
||||
pf->child = NULL;
|
||||
pf->cfe = NULL;
|
||||
pf->ih_fct = NULL;
|
||||
pf->ih_arg = NULL;
|
||||
@ -183,8 +192,8 @@ pcmcia_card_attach(dev)
|
||||
paa.card = &sc->card;
|
||||
paa.pf = pf;
|
||||
|
||||
if (config_found_sm(&sc->dev, &paa, pcmcia_print,
|
||||
pcmcia_submatch)) {
|
||||
if ((pf->child = config_found_sm(&sc->dev, &paa, pcmcia_print,
|
||||
pcmcia_submatch)) != NULL) {
|
||||
attached++;
|
||||
|
||||
DPRINTF(("%s: function %d CCR at %d "
|
||||
@ -203,23 +212,57 @@ pcmcia_card_attach(dev)
|
||||
}
|
||||
|
||||
void
|
||||
pcmcia_card_detach(dev)
|
||||
pcmcia_card_detach(dev, flags)
|
||||
struct device *dev;
|
||||
int flags; /* DETACH_* flags */
|
||||
{
|
||||
struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
|
||||
struct pcmcia_function *pf;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* We are running on either the PCMCIA socket's event thread
|
||||
* or in user context detaching a device by user request.
|
||||
*/
|
||||
for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
|
||||
pf = SIMPLEQ_NEXT(pf, pf_list)) {
|
||||
if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL)
|
||||
continue;
|
||||
if (pf->child == NULL)
|
||||
continue;
|
||||
DPRINTF(("%s: detaching %s (function %d)\n",
|
||||
sc->dev.dv_xname, pf->child->dv_xname, pf->number));
|
||||
if ((error = config_detach(pf->child, flags)) != 0) {
|
||||
printf("%s: error %d detaching %s (function %d)\n",
|
||||
sc->dev.dv_xname, error, pf->child->dv_xname,
|
||||
pf->number);
|
||||
} else
|
||||
pf->child = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pcmcia_card_deactivate(dev)
|
||||
struct device *dev;
|
||||
{
|
||||
struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
|
||||
struct pcmcia_function *pf;
|
||||
|
||||
/* XXX Implement me!
|
||||
*
|
||||
* Should:
|
||||
*
|
||||
* - ensure child is deactivated
|
||||
*
|
||||
* - config_detach child
|
||||
*
|
||||
* We assume we have context (and can block).
|
||||
/*
|
||||
* We're in the chip's card removal interrupt handler.
|
||||
* Deactivate the child driver. The PCMCIA socket's
|
||||
* event thread will run later to finish the detach.
|
||||
*/
|
||||
|
||||
printf("%s: pcmcia_card_detach called!\n", sc->dev.dv_xname);
|
||||
for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
|
||||
pf = SIMPLEQ_NEXT(pf, pf_list)) {
|
||||
if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL)
|
||||
continue;
|
||||
if (pf->child == NULL)
|
||||
continue;
|
||||
DPRINTF(("%s: deactivating %s (function %d)\n",
|
||||
sc->dev.dv_xname, pf->child->dv_xname, pf->number));
|
||||
config_deactivate(pf->child);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
@ -557,6 +600,17 @@ pcmcia_io_map(pf, width, offset, size, pcihp, windowp)
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
pcmcia_io_unmap(pf, window)
|
||||
struct pcmcia_function *pf;
|
||||
int window;
|
||||
{
|
||||
|
||||
pcmcia_chip_io_unmap(pf->sc->pct, pf->sc->pch, window);
|
||||
|
||||
/* XXX Anything for multi-function cards? */
|
||||
}
|
||||
|
||||
void *
|
||||
pcmcia_intr_establish(pf, ipl, ih_fct, ih_arg)
|
||||
struct pcmcia_function *pf;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: pcmciachip.h,v 1.2 1997/10/16 23:27:36 thorpej Exp $ */
|
||||
/* $NetBSD: pcmciachip.h,v 1.3 1998/11/17 08:49:12 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Marc Horowitz. All rights reserved.
|
||||
@ -138,7 +138,8 @@ struct pcmciabus_attach_args {
|
||||
/* interfaces for the chipset to call pcmcia */
|
||||
|
||||
int pcmcia_card_attach __P((struct device *));
|
||||
void pcmcia_card_detach __P((struct device *));
|
||||
void pcmcia_card_detach __P((struct device *, int));
|
||||
void pcmcia_card_deactivate __P((struct device *));
|
||||
int pcmcia_card_gettype __P((struct device *));
|
||||
|
||||
#endif /* _PCMCIA_PCMCIACHIP_H_ */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: pcmciavar.h,v 1.6 1998/10/10 21:59:40 thorpej Exp $ */
|
||||
/* $NetBSD: pcmciavar.h,v 1.7 1998/11/17 08:49:13 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1997 Marc Horowitz. All rights reserved.
|
||||
@ -114,6 +114,7 @@ struct pcmcia_function {
|
||||
SIMPLEQ_ENTRY(pcmcia_function) pf_list;
|
||||
/* run-time state */
|
||||
struct pcmcia_softc *sc;
|
||||
struct device *child;
|
||||
struct pcmcia_config_entry *cfe;
|
||||
struct pcmcia_mem_handle pf_pcmh;
|
||||
#define pf_ccrt pf_pcmh.memt
|
||||
@ -246,6 +247,7 @@ void pcmcia_function_disable __P((struct pcmcia_function *));
|
||||
|
||||
int pcmcia_io_map __P((struct pcmcia_function *, int, bus_addr_t,
|
||||
bus_size_t, struct pcmcia_io_handle *, int *));
|
||||
void pcmcia_io_unmap __P((struct pcmcia_function *, int));
|
||||
|
||||
#define pcmcia_mem_alloc(pf, size, pcmhp) \
|
||||
(pcmcia_chip_mem_alloc((pf)->sc->pct, (pf)->sc->pch, (size), (pcmhp)))
|
||||
|
Loading…
Reference in New Issue
Block a user