summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2004-07-05 20:56:06 +0000
committerphk <phk@FreeBSD.org>2004-07-05 20:56:06 +0000
commitfe7583f88c43e3d41c4526d3f8370a0b22407f37 (patch)
treec9c803f97b121596226af6487d058902e2c5db57 /sys/dev
parent290617ea0ebdeb45c43aa0913abbf73a3a055794 (diff)
downloadFreeBSD-src-fe7583f88c43e3d41c4526d3f8370a0b22407f37.zip
FreeBSD-src-fe7583f88c43e3d41c4526d3f8370a0b22407f37.tar.gz
Allocate the DMA channel shareable and only aquire it while the
device is open. This allows certain old and rather special dual floppy controllers to work on both channels, as long as you only have one open at a time.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/fdc/fdc.c33
1 files changed, 18 insertions, 15 deletions
diff --git a/sys/dev/fdc/fdc.c b/sys/dev/fdc/fdc.c
index 7883927..70e9835 100644
--- a/sys/dev/fdc/fdc.c
+++ b/sys/dev/fdc/fdc.c
@@ -132,6 +132,7 @@ struct fdc_data
{
int fdcu; /* our unit number */
int dmachan;
+ int dmacnt;
int flags;
#define FDC_ATTACHED 0x01
#define FDC_STAT_VALID 0x08
@@ -770,7 +771,8 @@ fdc_alloc_resources(struct fdc_data *fdc)
}
fdc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
- &fdc->rid_irq, RF_ACTIVE | RF_SHAREABLE);
+ &fdc->rid_irq,
+ RF_ACTIVE | RF_SHAREABLE);
if (fdc->res_irq == 0) {
device_printf(dev, "cannot reserve interrupt line\n");
return ENXIO;
@@ -778,8 +780,7 @@ fdc_alloc_resources(struct fdc_data *fdc)
if ((fdc->flags & FDC_NODMA) == 0) {
fdc->res_drq = bus_alloc_resource_any(dev, SYS_RES_DRQ,
- &fdc->rid_drq,
- RF_ACTIVE);
+ &fdc->rid_drq, RF_ACTIVE | RF_SHAREABLE);
if (fdc->res_drq == 0) {
device_printf(dev, "cannot reserve DMA request line\n");
fdc->flags |= FDC_NODMA;
@@ -964,9 +965,6 @@ fdc_detach(device_t dev)
/* reset controller, turn motor off */
fdout_wr(fdc, 0);
- if ((fdc->flags & FDC_NODMA) == 0)
- isa_dma_release(fdc->dmachan);
-
if ((fdc->flags & FDC_ATTACHED) == 0) {
device_printf(dev, "already unloaded\n");
return (0);
@@ -1030,15 +1028,6 @@ fdc_attach(device_t dev)
fdc->fdcu = device_get_unit(dev);
fdc->flags |= FDC_ATTACHED | FDC_NEEDS_RESET;
- if ((fdc->flags & FDC_NODMA) == 0) {
- /*
- * Acquire the DMA channel forever, the driver will do
- * the rest
- * XXX should integrate with rman
- */
- isa_dma_acquire(fdc->dmachan);
- isa_dmainit(fdc->dmachan, MAX_SEC_SIZE);
- }
fdc->state = DEVIDLE;
/* reset controller, turn motor off, clear fdout mirror reg */
@@ -1574,6 +1563,14 @@ fdopen(struct cdev *dev, int flags, int mode, struct thread *td)
return (rv);
}
fd->flags |= FD_OPEN;
+
+ if ((fdc->flags & FDC_NODMA) == 0) {
+ if (fdc->dmacnt++ == 0) {
+ isa_dma_acquire(fdc->dmachan);
+ isa_dmainit(fdc->dmachan, MAX_SEC_SIZE);
+ }
+ }
+
/*
* Clearing the DMA overrun counter at open time is a bit messy.
* Since we're only managing one counter per controller, opening
@@ -1594,11 +1591,17 @@ static int
fdclose(struct cdev *dev, int flags, int mode, struct thread *td)
{
struct fd_data *fd;
+ fdc_p fdc;
fd = dev->si_drv1;
+ fdc = fd->fdc;
fd->flags &= ~(FD_OPEN | FD_NONBLOCK);
fd->options &= ~(FDOPT_NORETRY | FDOPT_NOERRLOG | FDOPT_NOERROR);
+ if ((fdc->flags & FDC_NODMA) == 0)
+ if (--fdc->dmacnt == 0)
+ isa_dma_release(fdc->dmachan);
+
return (0);
}
OpenPOWER on IntegriCloud