Let us safely detach the ISA bus and devices attaching to the ISA
bus: 1 Add isadetach() for detaching the ISA bus, and add some helper routines that release resources held for ISA DMA. 2 In isachilddetached(), forget references to child devices. While I am here, change ISA_DMA_DRQ_ISFREE(...) == 0 to the simpler expression, !ISA_DMA_DRQ_ISFREE(...).
This commit is contained in:
parent
b8d6b79b67
commit
40bc016e8a
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: isa.c,v 1.135 2009/04/07 21:48:46 dyoung Exp $ */
|
||||
/* $NetBSD: isa.c,v 1.136 2009/08/18 16:52:42 dyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 2001, 2008 The NetBSD Foundation, Inc.
|
||||
@ -30,7 +30,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: isa.c,v 1.135 2009/04/07 21:48:46 dyoung Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: isa.c,v 1.136 2009/08/18 16:52:42 dyoung Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -56,12 +56,13 @@ __KERNEL_RCSID(0, "$NetBSD: isa.c,v 1.135 2009/04/07 21:48:46 dyoung Exp $");
|
||||
|
||||
int isamatch(device_t, cfdata_t, void *);
|
||||
void isaattach(device_t, device_t, void *);
|
||||
int isadetach(device_t, int);
|
||||
int isarescan(device_t, const char *, const int *);
|
||||
void isachilddetached(device_t, device_t);
|
||||
int isaprint(void *, const char *);
|
||||
|
||||
CFATTACH_DECL2_NEW(isa, sizeof(struct isa_softc),
|
||||
isamatch, isaattach, NULL, NULL, isarescan, isachilddetached);
|
||||
isamatch, isaattach, isadetach, NULL, isarescan, isachilddetached);
|
||||
|
||||
void isa_attach_knowndevs(struct isa_softc *);
|
||||
void isa_free_knowndevs(struct isa_softc *);
|
||||
@ -137,6 +138,27 @@ isaattach(device_t parent, device_t self, void *aux)
|
||||
aprint_error_dev(self, "couldn't establish power handler\n");
|
||||
}
|
||||
|
||||
int
|
||||
isadetach(device_t self, int flags)
|
||||
{
|
||||
struct isa_softc *sc = device_private(self);
|
||||
int rc;
|
||||
|
||||
if ((rc = config_detach_children(self, flags)) != 0)
|
||||
return rc;
|
||||
|
||||
pmf_device_deregister(self);
|
||||
|
||||
isa_free_knowndevs(sc);
|
||||
|
||||
#if NISADMA > 0
|
||||
isa_dmadestroy(sc->sc_ic);
|
||||
#endif
|
||||
isa_detach_hook(self);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
isarescan(device_t self, const char *ifattr, const int *locators)
|
||||
{
|
||||
@ -162,7 +184,13 @@ isarescan(device_t self, const char *ifattr, const int *locators)
|
||||
void
|
||||
isachilddetached(device_t self, device_t child)
|
||||
{
|
||||
/* nothing to do */
|
||||
struct isa_knowndev *ik;
|
||||
struct isa_softc *sc = device_private(self);
|
||||
|
||||
TAILQ_FOREACH(ik, &sc->sc_knowndevs, ik_list) {
|
||||
if (ik->ik_claimed == child)
|
||||
ik->ik_claimed = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: isadma.c,v 1.61 2009/05/12 09:10:15 cegger Exp $ */
|
||||
/* $NetBSD: isadma.c,v 1.62 2009/08/18 16:52:42 dyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc.
|
||||
@ -35,7 +35,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: isadma.c,v 1.61 2009/05/12 09:10:15 cegger Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: isadma.c,v 1.62 2009/08/18 16:52:42 dyoung Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
@ -201,6 +201,24 @@ _isa_dmainit(struct isa_dma_state *ids, bus_space_tag_t bst, bus_dma_tag_t dmat,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_isa_dmadestroy(struct isa_dma_state *ids)
|
||||
{
|
||||
if (!ids->ids_initialized)
|
||||
return;
|
||||
|
||||
_isa_dmacascade_stop(ids, 4);
|
||||
|
||||
/*
|
||||
* Unmap the registers used by the ISA DMA controller.
|
||||
*/
|
||||
bus_space_unmap(ids->ids_bst, ids->ids_dmapgh, 0xf);
|
||||
bus_space_unmap(ids->ids_bst, ids->ids_dma2h, DMA2_IOSIZE);
|
||||
bus_space_unmap(ids->ids_bst, ids->ids_dma1h, DMA1_IOSIZE);
|
||||
|
||||
ids->ids_initialized = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* _isa_dmacascade(): program 8237 DMA controller channel to accept
|
||||
* external dma control by a board.
|
||||
@ -215,7 +233,7 @@ _isa_dmacascade(struct isa_dma_state *ids, int chan)
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
if (ISA_DMA_DRQ_ISFREE(ids, chan) == 0) {
|
||||
if (!ISA_DMA_DRQ_ISFREE(ids, chan)) {
|
||||
printf("%s: DRQ %d is not free\n", device_xname(ids->ids_dev),
|
||||
chan);
|
||||
return (EAGAIN);
|
||||
@ -235,10 +253,32 @@ _isa_dmacascade(struct isa_dma_state *ids, int chan)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* _isa_dmacascade_stop(): turn off cascading on the 8237 DMA controller channel
|
||||
* external dma control by a board.
|
||||
*/
|
||||
int
|
||||
_isa_dmacascade_stop(struct isa_dma_state *ids, int chan)
|
||||
{
|
||||
if (chan < 0 || chan > 7) {
|
||||
printf("%s: bogus drq %d\n", device_xname(ids->ids_dev), chan);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
if (ISA_DMA_DRQ_ISFREE(ids, chan))
|
||||
return 0;
|
||||
|
||||
_isa_dmamask(ids, chan);
|
||||
|
||||
ISA_DMA_DRQ_FREE(ids, chan);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
_isa_drq_alloc(struct isa_dma_state *ids, int chan)
|
||||
{
|
||||
if (ISA_DMA_DRQ_ISFREE(ids, chan) == 0)
|
||||
if (!ISA_DMA_DRQ_ISFREE(ids, chan))
|
||||
return EBUSY;
|
||||
ISA_DMA_DRQ_ALLOC(ids, chan);
|
||||
return 0;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: isadmavar.h,v 1.24 2009/05/12 09:10:15 cegger Exp $ */
|
||||
/* $NetBSD: isadmavar.h,v 1.25 2009/08/18 16:52:42 dyoung Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc.
|
||||
@ -97,7 +97,10 @@ struct malloc_type;
|
||||
void _isa_dmainit(struct isa_dma_state *, bus_space_tag_t,
|
||||
bus_dma_tag_t, device_t);
|
||||
|
||||
void _isa_dmadestroy(struct isa_dma_state *);
|
||||
|
||||
int _isa_dmacascade(struct isa_dma_state *, int);
|
||||
int _isa_dmacascade_stop(struct isa_dma_state *, int);
|
||||
|
||||
bus_size_t _isa_dmamaxsize(struct isa_dma_state *, int);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user