diff options
author | sos <sos@FreeBSD.org> | 2003-02-20 20:02:32 +0000 |
---|---|---|
committer | sos <sos@FreeBSD.org> | 2003-02-20 20:02:32 +0000 |
commit | 93c9b5f5d15135bbb2fbe83962364b1b8d98dd7b (patch) | |
tree | 21f00885355e44a0cfacbbf172b07133dc03eb36 /sys/dev/ata/ata-disk.c | |
parent | 465aae958c94f33f1c58bf6e4932b8bbb8ac7c73 (diff) | |
download | FreeBSD-src-93c9b5f5d15135bbb2fbe83962364b1b8d98dd7b.zip FreeBSD-src-93c9b5f5d15135bbb2fbe83962364b1b8d98dd7b.tar.gz |
First round off updates/fixes to the ATA driver.
This moves all chipset specific code to a new file 'ata-chipset.c'.
Extensive use of tables and pointers to avoid having the same switch
on chipset type in several places, and to allow substituting various
functions for different HW arch needs.
Added PIO mode setup and all DMA modes.
Support for all known SiS chipsets. Thanks to Christoph Kukulies for
sponsoring a nice ASUS P4S8X SiS648 based board for this work!
Tested on: i386, PC98, alpha and sparc64
Diffstat (limited to 'sys/dev/ata/ata-disk.c')
-rw-r--r-- | sys/dev/ata/ata-disk.c | 58 |
1 files changed, 26 insertions, 32 deletions
diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c index 49f2062..450011a 100644 --- a/sys/dev/ata/ata-disk.c +++ b/sys/dev/ata/ata-disk.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 1998,1999,2000,2001,2002 Søren Schmidt <sos@FreeBSD.org> + * Copyright (c) 1998 - 2003 Søren Schmidt <sos@FreeBSD.org> * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -47,6 +47,7 @@ #include <machine/bus.h> #include <sys/rman.h> #include <dev/ata/ata-all.h> +#include <dev/ata/ata-pci.h> #include <dev/ata/ata-disk.h> #include <dev/ata/ata-raid.h> @@ -182,11 +183,10 @@ ad_attach(struct ata_device *atadev) } /* use DMA if allowed and if drive/controller supports it */ - if (ata_dma) - ata_dmainit(atadev, ata_pmode(atadev->param), - ata_wmode(atadev->param), ata_umode(atadev->param)); + if (ata_dma && atadev->channel->dma) + atadev->setmode(atadev, ATA_DMA_MAX); else - ata_dmainit(atadev, ata_pmode(atadev->param), -1, -1); + atadev->setmode(atadev, ATA_PIO_MAX); /* use tagged queueing if allowed and supported */ if (ata_tags && ad_tagsupported(adp)) { @@ -249,7 +249,8 @@ ad_detach(struct ata_device *atadev, int flush) /* get rid of flush XXX SOS */ biofinish(request->bp, NULL, ENXIO); ad_free(request); } - ata_dmafree(atadev); + if (atadev->channel->dma) + atadev->channel->dma->free(atadev); while ((bp = bioq_first(&adp->queue))) { bioq_remove(&adp->queue, bp); biofinish(bp, NULL, ENXIO); @@ -288,12 +289,12 @@ adclose(dev_t dev, int flags, int fmt, struct thread *td) { struct ad_softc *adp = dev->si_drv1; - adp->device->channel->lock_func(adp->device->channel, ATA_LF_LOCK); + adp->device->channel->locking(adp->device->channel, ATA_LF_LOCK); ATA_SLEEPLOCK_CH(adp->device->channel, ATA_CONTROL); if (ata_command(adp->device, ATA_C_FLUSHCACHE, 0, 0, 0, ATA_WAIT_READY)) ata_prtdev(adp->device, "flushing cache on close failed\n"); ATA_UNLOCK_CH(adp->device->channel); - adp->device->channel->lock_func(adp->device->channel, ATA_LF_UNLOCK); + adp->device->channel->locking(adp->device->channel, ATA_LF_UNLOCK); return 0; } @@ -326,9 +327,9 @@ addump(dev_t dev, void *virtual, vm_offset_t physical, off_t offset, size_t leng if (!once) { /* force PIO mode for dumps */ adp->device->mode = ATA_PIO; - adp->device->channel->lock_func(adp->device->channel, ATA_LF_LOCK); + adp->device->channel->locking(adp->device->channel, ATA_LF_LOCK); ata_reinit(adp->device->channel); - adp->device->channel->lock_func(adp->device->channel, ATA_LF_UNLOCK); + adp->device->channel->locking(adp->device->channel, ATA_LF_UNLOCK); once = 1; } @@ -388,7 +389,7 @@ ad_start(struct ata_device *atadev) if (bp->bio_cmd == BIO_READ) request->flags |= ADR_F_READ; - if (adp->device->mode >= ATA_DMA && ata_dmaalloc(atadev)) + if (adp->device->mode >= ATA_DMA && atadev->channel->dma->alloc(atadev)) adp->device->mode = ATA_PIO; /* insert in tag array */ @@ -452,7 +453,7 @@ ad_transfer(struct ad_request *request) /* does this drive & transfer work with DMA ? */ request->flags &= ~ADR_F_DMA_USED; if (adp->device->mode >= ATA_DMA && - !ata_dmasetup(adp->device, request->data, request->bytecount)) { + !adp->device->channel->dma->setup(adp->device, request->data, request->bytecount)) { request->flags |= ADR_F_DMA_USED; request->currentsize = request->bytecount; @@ -501,7 +502,7 @@ ad_transfer(struct ad_request *request) } /* start transfer, return and wait for interrupt */ - ata_dmastart(adp->device, request->data, request->bytecount, + adp->device->channel->dma->start(adp->device, request->data, request->bytecount, request->flags & ADR_F_READ); return ATA_OP_CONTINUES; } @@ -571,7 +572,7 @@ ad_interrupt(struct ad_request *request) /* finish DMA transfer */ if (request->flags & ADR_F_DMA_USED) - dma_stat = ata_dmadone(adp->device); + dma_stat = adp->device->channel->dma->stop(adp->device); /* do we have a corrected soft error ? */ if (adp->device->channel->status & ATA_S_CORR) @@ -596,24 +597,24 @@ ad_interrupt(struct ad_request *request) if (request->retries++ < AD_MAX_RETRIES) printf(" retrying\n"); else { - ata_dmainit(adp->device, ata_pmode(adp->device->param), -1, -1); + adp->device->setmode(adp->device, ATA_PIO_MAX); printf(" falling back to PIO mode\n"); } TAILQ_INSERT_HEAD(&adp->device->channel->ata_queue, request, chain); return ATA_OP_FINISHED; } - +#if 0 /* XXX*/ /* if using DMA, try once again in PIO mode */ if (request->flags & ADR_F_DMA_USED) { untimeout((timeout_t *)ad_timeout, request,request->timeout_handle); ad_invalidatequeue(adp, request); - ata_dmainit(adp->device, ata_pmode(adp->device->param), -1, -1); + adp->device->setmode(adp->device, ATA_PIO_MAX); request->flags |= ADR_F_FORCE_PIO; printf(" trying PIO mode\n"); TAILQ_INSERT_HEAD(&adp->device->channel->ata_queue, request, chain); return ATA_OP_FINISHED; } - +#endif request->flags |= ADR_F_ERROR; printf(" status=%02x error=%02x\n", adp->device->channel->status, adp->device->channel->error); @@ -761,7 +762,7 @@ ad_service(struct ad_softc *adp, int change) ad_invalidatequeue(adp, NULL); return ATA_OP_FINISHED; } - ata_dmastart(adp->device, request->data, request->bytecount, + adp->device->channel->dma->start(adp->device, request->data, request->bytecount, request->flags & ADR_F_READ); return ATA_OP_CONTINUES; } @@ -802,12 +803,10 @@ ad_invalidatequeue(struct ad_softc *adp, struct ad_request *request) static int ad_tagsupported(struct ad_softc *adp) { + /* check for controllers that we know doesn't support tags */ switch (adp->device->channel->chiptype) { - case 0x0d30105a: /* Promises before TX2 doesn't work with tagged queuing */ - case 0x0d38105a: - case 0x4d30105a: - case 0x4d33105a: - case 0x4d38105a: + case ATA_PDC20265: case ATA_PDC20263: case ATA_PDC20267: + case ATA_PDC20246: case ATA_PDC20262: return 0; } @@ -851,10 +850,10 @@ ad_timeout(struct ad_request *request) request->tag, request->serv); if (request->flags & ADR_F_DMA_USED) { - ata_dmadone(adp->device); + adp->device->channel->dma->stop(adp->device); ad_invalidatequeue(adp, request); if (request->retries == AD_MAX_RETRIES) { - ata_dmainit(adp->device, ata_pmode(adp->device->param), -1, -1); + adp->device->setmode(adp->device, ATA_PIO_MAX); ata_prtdev(adp->device, "trying fallback to PIO mode\n"); request->retries = 0; } @@ -883,12 +882,7 @@ ad_reinit(struct ata_device *atadev) ad_invalidatequeue(atadev->driver, NULL); ata_command(atadev, ATA_C_SET_MULTI, 0, adp->transfersize / DEV_BSIZE, 0, ATA_WAIT_READY); - if (adp->device->mode >= ATA_DMA) - ata_dmainit(atadev, ata_pmode(adp->device->param), - ata_wmode(adp->device->param), - ata_umode(adp->device->param)); - else - ata_dmainit(atadev, ata_pmode(adp->device->param), -1, -1); + atadev->setmode(atadev, adp->device->mode); } void |