diff options
author | sos <sos@FreeBSD.org> | 1999-06-25 09:03:07 +0000 |
---|---|---|
committer | sos <sos@FreeBSD.org> | 1999-06-25 09:03:07 +0000 |
commit | 1823d8fdf691a11e672736945aadbe52a69ea664 (patch) | |
tree | f9a0d62ae754effb7c0bf56c32b97c0f19b17cad /sys/dev/ata | |
parent | 689fdb91cbd09faf9b8a4b0864bfa3085472d997 (diff) | |
download | FreeBSD-src-1823d8fdf691a11e672736945aadbe52a69ea664.zip FreeBSD-src-1823d8fdf691a11e672736945aadbe52a69ea664.tar.gz |
Nine'th update to the new ATA/ATAPI driver:
The atapi subsystem has gotten better error handeling and timeouts,
it also tries a REQUEST SENSE command when devices returns errors,
to give a little more info as to what went wrong. It might be a
little verbose for now, but I'm interested in as much feedback on
errors as possible, especially timeouts, as I'm a bit in doubt if
I've chosen resonable default values everywhere.
The disk driver has been changed a bit to prepare for tagged queing,
which is next on my list.
The disk driver has grown a dump routine, I got one implementation
from Darrell Anderson <anderson@cs.duke.edu> which also did
partial dumps (usefull on big memory machines) I left out the
partial stuff for now, and changed the rest alot to fit into the new
ad_request framework.
Some minor cleanups and rearrangements as well.
As usual USE AT YOUR OWN RISK!!, this is still pre alpha level code.
Especially the DMA support can hose your disk real bad if anything
goes wrong, again you have been warned :)
Notebook owners should be carefull that their machines dont suspend
as this might cause trouble...
But please tell me how it works for you!
Enjoy!
-Søren
Diffstat (limited to 'sys/dev/ata')
-rw-r--r-- | sys/dev/ata/ata-all.c | 18 | ||||
-rw-r--r-- | sys/dev/ata/ata-all.h | 4 | ||||
-rw-r--r-- | sys/dev/ata/ata-disk.c | 281 | ||||
-rw-r--r-- | sys/dev/ata/ata-disk.h | 35 | ||||
-rw-r--r-- | sys/dev/ata/atapi-all.c | 135 | ||||
-rw-r--r-- | sys/dev/ata/atapi-all.h | 40 | ||||
-rw-r--r-- | sys/dev/ata/atapi-cd.c | 361 | ||||
-rw-r--r-- | sys/dev/ata/atapi-fd.c | 62 | ||||
-rw-r--r-- | sys/dev/ata/atapi-tape.c | 162 | ||||
-rw-r--r-- | sys/dev/ata/atapi-tape.h | 20 |
10 files changed, 650 insertions, 468 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index 05f2812..9af5c28 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: ata-all.c,v 1.13 1999/05/17 15:58:44 sos Exp $ + * $Id: ata-all.c,v 1.14 1999/05/20 09:12:02 sos Exp $ */ #include "ata.h" @@ -199,7 +199,7 @@ ata_pcimatch(device_t dev) return "Cyrix 5530 IDE controller"; #endif default: - return "Unknown PCI IDE controller"; + return "Unknown PCI IDE controller (using generic mode)"; } } return NULL; @@ -532,7 +532,7 @@ ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t bmaddr, free(scp, M_DEVBUF); return 0; } - bufq_init(&scp->ata_queue); + TAILQ_INIT(&scp->ata_queue); TAILQ_INIT(&scp->atapi_queue); *unit = scp->lun; scp->dev = dev; @@ -550,7 +550,7 @@ ataintr(void *data) { struct ata_softc *scp; struct atapi_request *atapi_request; - struct buf *ata_request; + struct ad_request *ad_request; u_int8_t status; static int32_t intr_count = 0; @@ -560,8 +560,8 @@ ataintr(void *data) switch (scp->active) { #if NATADISK > 0 case ATA_ACTIVE_ATA: - if ((ata_request = bufq_first(&scp->ata_queue))) - if (ad_interrupt(ata_request) == ATA_OP_CONTINUES) + if ((ad_request = TAILQ_FIRST(&scp->ata_queue))) + if (ad_interrupt(ad_request) == ATA_OP_CONTINUES) return; break; #endif @@ -593,7 +593,7 @@ ataintr(void *data) void ata_start(struct ata_softc *scp) { - struct buf *ata_request; + struct ad_request *ad_request; struct atapi_request *atapi_request; #ifdef ATA_DEBUG @@ -606,9 +606,9 @@ ata_start(struct ata_softc *scp) #if NATADISK > 0 /* find & call the responsible driver if anything on ATA queue */ - if ((ata_request = bufq_first(&scp->ata_queue))) { + if ((ad_request = TAILQ_FIRST(&scp->ata_queue))) { scp->active = ATA_ACTIVE_ATA; - ad_transfer(ata_request); + ad_transfer(ad_request); #ifdef ATA_DEBUG printf("ata_start: started ata, leaving\n"); #endif diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h index 1818bfb..31f0d5b 100644 --- a/sys/dev/ata/ata-all.h +++ b/sys/dev/ata/ata-all.h @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: ata-all.h,v 1.5 1999/03/28 18:57:18 sos Exp $ + * $Id: ata-all.h,v 1.6 1999/04/18 20:48:15 sos Exp $ */ /* ATA register defines */ @@ -142,7 +142,7 @@ struct ata_softc { #define ATA_ACTIVE_ATA 0x3 #define ATA_ACTIVE_ATAPI 0x4 - struct buf_queue_head ata_queue; /* head of ATA queue */ + TAILQ_HEAD(, ad_request) ata_queue; /* head of ATA queue */ TAILQ_HEAD(, atapi_request) atapi_queue; /* head of ATAPI queue */ }; diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c index bc5eeee..27ef29d 100644 --- a/sys/dev/ata/ata-disk.c +++ b/sys/dev/ata/ata-disk.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: ata-disk.c,v 1.12 1999/05/30 16:51:12 phk Exp $ + * $Id: ata-disk.c,v 1.13 1999/05/31 11:24:25 phk Exp $ */ #include "ata.h" @@ -50,7 +50,13 @@ #ifdef DEVFS #include <sys/devfsext.h> #endif +#include <vm/vm.h> +#include <vm/vm_prot.h> +#include <vm/pmap.h> +#include <vm/vm_page.h> +#include <vm/vm_object.h> #include <machine/clock.h> +#include <machine/md_var.h> #include <dev/ata/ata-all.h> #include <dev/ata/ata-disk.h> @@ -59,10 +65,9 @@ static d_close_t adclose; static d_ioctl_t adioctl; static d_strategy_t adstrategy; static d_psize_t adpsize; +static d_dump_t addump; -#define BDEV_MAJOR 30 -#define CDEV_MAJOR 116 -#ifdef NOTYET /* the boot code needs to be fixed to boot arbitrary devices */ +#if 0 /* the boot code needs to be fixed to boot arbitrary devices */ #define DRIVER_NAME "ad" #else #define DRIVER_NAME "wd" @@ -81,17 +86,17 @@ static struct cdevsw ad_cdevsw = { /* strategy */ adstrategy, /* name */ DRIVER_NAME, /* parms */ noparms, - /* maj */ CDEV_MAJOR, - /* dump */ nodump, + /* maj */ 116, + /* dump */ addump, /* psize */ adpsize, /* flags */ D_DISK, /* maxio */ 0, - /* bmaj */ BDEV_MAJOR, + /* bmaj */ 30, }; static struct cdevsw fakewd_cdevsw; /* misc defines */ -#define UNIT(dev) (minor(dev)>>3 & 0x1f) /* assume 8 minor # per unit */ +#define UNIT(dev) (minor(dev)>>3 & 0x1f) /* assume 8 minor # per unit */ #define NUNIT 16 /* max # of devices */ /* prototypes */ @@ -104,6 +109,7 @@ static int8_t ad_version(u_int16_t); int32_t ad_timeout(char *data); static void ad_drvinit(void); +/* internal vars */ static struct ad_softc *adtab[NUNIT]; static int32_t adnlun = 0; /* number of config'd drives */ static struct intr_config_hook *ad_attach_hook; @@ -184,7 +190,7 @@ ad_attach(void *notused) } if (adp->ata_parm->atavalid & ATA_FLAG_54_58 && adp->ata_parm->lbasize) - adp->flags |= AD_F_USE_LBA; + adp->flags |= AD_F_LBA_ENABLED; /* use multiple sectors/interrupt if device supports it */ adp->transfersize = DEV_BSIZE; @@ -202,6 +208,10 @@ ad_attach(void *notused) udmamode(adp->ata_parm))) adp->flags |= AD_F_DMA_ENABLED; + /* use tagged queue if supported */ + if ((adp->num_tags = adp->ata_parm->queuelen & 0x1f)) + adp->flags |= AD_F_TAG_ENABLED; + bpack(adp->ata_parm->model, model_buf, sizeof(model_buf)); bpack(adp->ata_parm->revision, revision_buf, sizeof(revision_buf)); @@ -226,8 +236,7 @@ ad_attach(void *notused) wdmamode(adp->ata_parm), udmamode(adp->ata_parm)); printf("ad%d: %d secs/int, %d depth queue, %s mode\n", - adnlun, adp->transfersize / DEV_BSIZE, - adp->ata_parm->queuelen & 0x1f, + adnlun, adp->transfersize / DEV_BSIZE, adp->num_tags, (adp->flags & AD_F_DMA_ENABLED) ? "DMA" :"PIO"); devstat_add_entry(&adp->stats, "ad", adnlun, DEV_BSIZE, DEVSTAT_NO_ORDERED_TAGS, @@ -363,7 +372,7 @@ adstrategy(struct buf *bp) int32_t s; #ifdef AD_DEBUG -printf("adstrategy: entered\n"); +printf("adstrategy: entered count=%d\n", bp->b_bcount); #endif if (lun >= adnlun || bp->b_blkno < 0 || !(adp = adtab[lun]) || bp->b_bcount % DEV_BSIZE != 0) { @@ -384,15 +393,11 @@ printf("adstrategy: entered\n"); s = splbio(); bufqdisksort(&adp->queue, bp); - - if (!adp->active) - ad_start(adp); - - if (adp->controller->active == ATA_IDLE) - ata_start(adp->controller); - + ad_start(adp); splx(s); - return; +#ifdef AD_DEBUG +printf("adstrategy: leaving\n"); +#endif } static int @@ -406,6 +411,77 @@ adpsize(dev_t dev) return dssize(dev, &adp->slices, adopen, adclose); } +int +addump(dev_t dev) +{ + struct ad_softc *adp; + struct disklabel *lp; + struct ad_request request; + int32_t lun = UNIT(dev), part = dkpart(dev); + u_int32_t count, blkno, blkoff; + vm_offset_t addr = 0; + static int addoingadump = 0; + + if (addoingadump++ != 0) + return EFAULT; + + if (lun >= adnlun || !(adp = adtab[lun])) + return ENXIO; + + if ((adp->slices == NULL) || (lp = dsgetlabel(dev, adp->slices)) == NULL) + return ENXIO; + + count = (u_long)Maxmem * PAGE_SIZE / lp->d_secsize; + + if ((dumplo < 0) || (dumplo + count > lp->d_partitions[part].p_size)) + return EINVAL; + + blkoff = lp->d_partitions[part].p_offset + + adp->slices->dss_slices[dkslice(dev)].ds_offset; + blkno = blkoff + dumplo; + + adp->flags &= ~AD_F_DMA_ENABLED; + + while (count > 0) { + + if (is_physical_memory(addr)) + pmap_enter(kernel_pmap, (vm_offset_t)CADDR1, + trunc_page(addr), VM_PROT_READ, TRUE); + else + pmap_enter(kernel_pmap, (vm_offset_t)CADDR1, + trunc_page(0), VM_PROT_READ, TRUE); + + bzero(&request, sizeof(struct ad_request)); + request.device = adp; + request.blockaddr = blkno; + request.bytecount = PAGE_SIZE; + request.data = CADDR1; + + while (request.bytecount > 0) { + ad_transfer(&request); + request.donecount += request.currentsize; + DELAY(20); + } + + if (addr % (1024 * 1024) == 0) { +#ifdef HW_WDOG + if (wdog_tickler) + (*wdog_tickler)(); +#endif + printf("%ld ", (long)(count * DEV_BSIZE) / (1024 * 1024)); + } + + blkno += howmany(PAGE_SIZE, lp->d_secsize); + count -= howmany(PAGE_SIZE, lp->d_secsize); + addr += PAGE_SIZE; + } + + if (ata_wait(adp->controller, adp->unit, ATA_S_DRDY | ATA_S_DSC) < 0) + printf("ad_dump: timeout waiting for final ready\n"); + + return 0; +} + static void ad_strategy(struct buf *bp) { @@ -415,90 +491,100 @@ ad_strategy(struct buf *bp) static void ad_start(struct ad_softc *adp) { - struct buf *bp; + struct buf *bp = bufq_first(&adp->queue); + struct ad_request *request; #ifdef AD_DEBUG printf("ad_start:\n"); #endif - if (adp->active) { - printf("ad_start: should newer be called when active\n"); /* SOS */ + if (!bp) + return; + + if (!(request = malloc(sizeof(struct ad_request), M_DEVBUF, M_NOWAIT))) { + printf("ad_start: out of memory\n"); return; } - if (!(bp = bufq_first(&adp->queue))) - return; + + /* setup request */ + bzero(request, sizeof(struct ad_request)); + request->device = adp; + request->bp = bp; + request->blockaddr = bp->b_pblkno; + request->bytecount = bp->b_bcount; + request->data = bp->b_data; + request->flags = (bp->b_flags & B_READ) ? AR_F_READ : 0; /* remove from drive queue */ bufq_remove(&adp->queue, bp); - bp->b_driver1 = adp; /* link onto controller queue */ - bufq_insert_tail(&adp->controller->ata_queue, bp); + TAILQ_INSERT_TAIL(&adp->controller->ata_queue, request, chain); - /* mark the drive as busy */ - adp->active = 1; + /* try to start controller */ + if (adp->controller->active == ATA_IDLE) + ata_start(adp->controller); } void -ad_transfer(struct buf *bp) +ad_transfer(struct ad_request *request) { struct ad_softc *adp; - u_int32_t blknum, secsprcyl; - u_int32_t cylinder, head, sector, count, command; + u_int32_t blkno, secsprcyl; + u_int32_t cylinder, head, sector, count, cmd; /* get request params */ - adp = bp->b_driver1; + adp = request->device; /* calculate transfer details */ - blknum = bp->b_pblkno + (adp->donecount / DEV_BSIZE); + blkno = request->blockaddr + (request->donecount / DEV_BSIZE); #ifdef AD_DEBUG - printf("ad_transfer: blknum=%d\n", blknum); + printf("ad_transfer: blkno=%d\n", blkno); #endif - if (adp->donecount == 0) { + if (request->donecount == 0) { /* setup transfer parameters */ - adp->bytecount = bp->b_bcount; - count = howmany(adp->bytecount, DEV_BSIZE); + count = howmany(request->bytecount, DEV_BSIZE); - if (adp->flags & AD_F_USE_LBA) { - sector = (blknum >> 0) & 0xff; - cylinder = (blknum >> 8) & 0xffff; - head = ((blknum >> 24) & 0xf) | ATA_D_LBA; + if (adp->flags & AD_F_LBA_ENABLED) { + sector = (blkno >> 0) & 0xff; + cylinder = (blkno >> 8) & 0xffff; + head = ((blkno >> 24) & 0xf) | ATA_D_LBA; } else { secsprcyl = adp->sectors * adp->heads; - cylinder = blknum / secsprcyl; - head = (blknum % secsprcyl) / adp->sectors; - sector = (blknum % adp->sectors) + 1; + cylinder = blkno / secsprcyl; + head = (blkno % secsprcyl) / adp->sectors; + sector = (blkno % adp->sectors) + 1; } /* setup first transfer length */ - adp->currentsize = min(adp->bytecount, adp->transfersize); + request->currentsize = min(request->bytecount, adp->transfersize); devstat_start_transaction(&adp->stats); /* does this drive & transfer work with DMA ? */ - adp->flags &= ~AD_F_DMA_USED; + request->flags &= ~AR_F_DMA_USED; if ((adp->flags & AD_F_DMA_ENABLED) && !ata_dmasetup(adp->controller, adp->unit, - (void *)bp->b_data, adp->bytecount, - (bp->b_flags & B_READ))) { - adp->flags |= AD_F_DMA_USED; - command = (bp->b_flags&B_READ) ? ATA_C_READ_DMA : ATA_C_WRITE_DMA; - adp->currentsize = adp->bytecount; + (void *)request->data, request->bytecount, + (request->flags & AR_F_READ))) { + request->flags |= AR_F_DMA_USED; + cmd = request->flags & AR_F_READ ? ATA_C_READ_DMA : ATA_C_WRITE_DMA; + request->currentsize = request->bytecount; } /* does this drive support multi sector transfers ? */ - else if (adp->currentsize > DEV_BSIZE) - command = (bp->b_flags&B_READ) ? ATA_C_READ_MULTI:ATA_C_WRITE_MULTI; + else if (request->currentsize > DEV_BSIZE) + cmd = request->flags & AR_F_READ?ATA_C_READ_MULTI:ATA_C_WRITE_MULTI; else - command = (bp->b_flags&B_READ) ? ATA_C_READ : ATA_C_WRITE; + cmd = request->flags & AR_F_READ ? ATA_C_READ : ATA_C_WRITE; - ata_command(adp->controller, adp->unit, command, cylinder, head, + ata_command(adp->controller, adp->unit, cmd, cylinder, head, sector, count, 0, ATA_IMMEDIATE); } /* if this is a DMA transaction start it, return and wait for interrupt */ - if (adp->flags & AD_F_DMA_USED) { + if (request->flags & AR_F_DMA_USED) { ata_dmastart(adp->controller, adp->unit); #ifdef AD_DEBUG printf("ad_transfer: return waiting for DMA interrupt\n"); @@ -507,10 +593,10 @@ ad_transfer(struct buf *bp) } /* calculate this transfer length */ - adp->currentsize = min(adp->bytecount, adp->transfersize); + request->currentsize = min(request->bytecount, adp->transfersize); /* if this is a PIO read operation, return and wait for interrupt */ - if (bp->b_flags & B_READ) { + if (request->flags & AR_F_READ) { #ifdef AD_DEBUG printf("ad_transfer: return waiting for PIO read interrupt\n"); #endif @@ -526,54 +612,48 @@ ad_transfer(struct buf *bp) /* output the data */ #if 0 outsw(adp->controller->ioaddr + ATA_DATA, - (void *)((uintptr_t)bp->b_data + adp->donecount), - adp->currentsize / sizeof(int16_t)); + (void *)((uintptr_t)request->data + request->donecount), + request->currentsize / sizeof(int16_t)); #else outsl(adp->controller->ioaddr + ATA_DATA, - (void *)((uintptr_t)bp->b_data + adp->donecount), - adp->currentsize / sizeof(int32_t)); + (void *)((uintptr_t)request->data + request->donecount), + request->currentsize / sizeof(int32_t)); #endif - adp->bytecount -= adp->currentsize; + request->bytecount -= request->currentsize; #ifdef AD_DEBUG printf("ad_transfer: return wrote data\n"); #endif } int32_t -ad_interrupt(struct buf *bp) +ad_interrupt(struct ad_request *request) { - struct ad_softc *adp = bp->b_driver1; + struct ad_softc *adp = request->device; int32_t dma_stat = 0; /* finish DMA transfer */ - if (adp->flags & AD_F_DMA_USED) { - if (!(ata_dmastatus(adp->controller, adp->unit) & ATA_BMSTAT_INTERRUPT)){ -printf("extra SMP interrupt\n"); - return ATA_OP_CONTINUES; -} + if (request->flags & AR_F_DMA_USED) dma_stat = ata_dmadone(adp->controller, adp->unit); - } /* get drive status */ if (ata_wait(adp->controller, adp->unit, 0) < 0) printf("ad_interrupt: timeout waiting for status"); if (adp->controller->status & (ATA_S_ERROR | ATA_S_CORR) || - (adp->flags & AD_F_DMA_USED && dma_stat != ATA_BMSTAT_INTERRUPT)) { + (request->flags & AR_F_DMA_USED && dma_stat != ATA_BMSTAT_INTERRUPT)) { oops: printf("ad%d: status=%02x error=%02x\n", adp->lun, adp->controller->status, adp->controller->error); if (adp->controller->status & ATA_S_ERROR) { printf("ad_interrupt: hard error\n"); - bp->b_error = EIO; - bp->b_flags |= B_ERROR; + request->flags |= AR_F_ERROR; } if (adp->controller->status & ATA_S_CORR) - printf("ad_interrupt: soft ECC\n"); + printf("ad_interrupt: soft error ECC corrected\n"); } /* if this was a PIO read operation, get the data */ - if (adp->active && !(adp->flags & AD_F_DMA_USED) && - ((bp->b_flags & (B_READ | B_ERROR)) == B_READ)) { + if (!(request->flags & AR_F_DMA_USED) && + ((request->flags & (AR_F_READ | AR_F_ERROR)) == AR_F_READ)) { /* ready to receive data? */ if ((adp->controller->status & (ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ)) @@ -589,45 +669,50 @@ oops: /* data ready, read in */ #if 0 insw(adp->controller->ioaddr + ATA_DATA, - (void *)((uintptr_t)bp->b_data + adp->donecount), - adp->currentsize / sizeof(int16_t)); + (void *)((uintptr_t)request->data + request->donecount), + request->currentsize / sizeof(int16_t)); #else insl(adp->controller->ioaddr + ATA_DATA, - (void *)((uintptr_t)bp->b_data + adp->donecount), - adp->currentsize / sizeof(int32_t)); + (void *)((uintptr_t)request->data + request->donecount), + request->currentsize / sizeof(int32_t)); #endif - adp->bytecount -= adp->currentsize; + request->bytecount -= request->currentsize; #ifdef AD_DEBUG printf("ad_interrupt: read in data\n"); #endif } /* if this was a DMA operation finish up */ - if (adp->active && (adp->flags & AD_F_DMA_USED) && !(bp->b_flags & B_ERROR)) - adp->bytecount -= adp->currentsize; + if ((request->flags & AR_F_DMA_USED) && !(request->flags & AR_F_ERROR)) + request->bytecount -= request->currentsize; /* finish up this tranfer, check for more work on this buffer */ if (adp->controller->active == ATA_ACTIVE_ATA) { - if ((bp->b_flags & B_ERROR) == 0) { - adp->donecount += adp->currentsize; + if (request->flags & AR_F_ERROR) { + request->bp->b_error = EIO; + request->bp->b_flags |= B_ERROR; + } + else { + request->donecount += request->currentsize; #ifdef AD_DEBUG - printf("ad_interrupt: %s op OK\n", (bp->b_flags & B_READ)?"R":"W"); + printf("ad_interrupt: %s cmd OK\n", + (request->flags & AR_F_READ) ? "read" : "write"); #endif - if (adp->bytecount > 0) { - ad_transfer(bp); + if (request->bytecount > 0) { + ad_transfer(request); return ATA_OP_CONTINUES; } } - bufq_remove(&adp->controller->ata_queue, bp); - bp->b_resid = bp->b_bcount - adp->donecount; - biodone(bp); - devstat_end_transaction(&adp->stats, adp->donecount, + + TAILQ_REMOVE(&adp->controller->ata_queue, request, chain); + request->bp->b_resid = request->bytecount; + biodone(request->bp); + devstat_end_transaction(&adp->stats, request->donecount, DEVSTAT_TAG_NONE, - (bp->b_flags & B_READ) ? + (request->flags & AR_F_READ) ? DEVSTAT_READ : DEVSTAT_WRITE); - adp->donecount = 0; - adp->active = 0; } + free(request, M_DEVBUF); ad_start(adp); #ifdef AD_DEBUG printf("ad_interrupt: completed\n"); @@ -664,6 +749,8 @@ ad_drvinit(void) static int32_t ad_devsw_installed = 0; if (!ad_devsw_installed) { + if (!ad_cdevsw.d_maxio) + ad_cdevsw.d_maxio = 254 * DEV_BSIZE; cdevsw_add(&ad_cdevsw); fakewd_cdevsw = ad_cdevsw; fakewd_cdevsw.d_maj = 3; diff --git a/sys/dev/ata/ata-disk.h b/sys/dev/ata/ata-disk.h index bf5ba1f..ad9a0d3 100644 --- a/sys/dev/ata/ata-disk.h +++ b/sys/dev/ata/ata-disk.h @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: ata-disk.h,v 1.5 1999/03/28 18:57:18 sos Exp $ + * $Id: ata-disk.h,v 1.6 1999/05/20 09:12:03 sos Exp $ */ /* ATA device parameter information */ @@ -130,16 +130,13 @@ struct ad_softc { u_int8_t sectors; u_int32_t total_secs; /* total # of sectors (LBA) */ u_int32_t transfersize; /* size of each transfer */ - u_int32_t currentsize; /* size of current transfer */ - u_int32_t bytecount; /* bytes to transfer */ - u_int32_t donecount; /* bytes transferred */ - u_int32_t active; /* active processing request */ + u_int32_t num_tags; /* number of tags supported */ u_int32_t flags; /* drive flags */ #define AD_F_LABELLING 0x0001 -#define AD_F_USE_LBA 0x0002 -#define AD_F_USE_32BIT 0x0004 +#define AD_F_LBA_ENABLED 0x0002 +#define AD_F_32B_ENABLED 0x0004 #define AD_F_DMA_ENABLED 0x0008 -#define AD_F_DMA_USED 0x0010 +#define AD_F_TAG_ENABLED 0x0010 struct buf_queue_head queue; /* head of request queue */ struct devstat stats; /* devstat entry */ @@ -149,6 +146,24 @@ struct ad_softc { #endif }; -void ad_transfer(struct buf *); -int32_t ad_interrupt(struct buf *); +struct ad_request { + struct ad_softc *device; /* ptr to parent device */ + u_int32_t blockaddr; /* block number */ + u_int32_t bytecount; /* bytes to transfer */ + u_int32_t donecount; /* bytes transferred */ + u_int32_t currentsize; /* size of current transfer */ + u_int32_t result; /* result code */ + int32_t flags; +#define AR_F_READ 0x0001 +#define AR_F_ERROR 0x0002 +#define AR_F_DMA_USED 0x0004 + + int8_t *data; /* pointer to data buf */ + struct buf *bp; /* associated buf ptr */ + u_int8_t tag; /* tag ID of this request */ + TAILQ_ENTRY(ad_request) chain; /* list management */ +}; + +void ad_transfer(struct ad_request *); +int32_t ad_interrupt(struct ad_request *); diff --git a/sys/dev/ata/atapi-all.c b/sys/dev/ata/atapi-all.c index c0aa1b2..1564162 100644 --- a/sys/dev/ata/atapi-all.c +++ b/sys/dev/ata/atapi-all.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: atapi-all.c,v 1.8 1999/05/17 15:58:45 sos Exp $ + * $Id: atapi-all.c,v 1.9 1999/05/20 09:12:04 sos Exp $ */ #include "ata.h" @@ -52,9 +52,8 @@ static void atapi_attach(void *); static int32_t atapi_getparam(struct atapi_softc *); static int8_t *atapi_type(int32_t); -#ifdef ATAPI_DEBUG static int8_t *atapi_cmd2str(u_int8_t); -#endif +static int8_t * atapi_skey2str(u_int8_t); static int32_t atapi_wait(struct atapi_softc *, u_int8_t); static void atapi_init(void); @@ -163,13 +162,14 @@ atapi_getparam(struct atapi_softc *atp) int32_t atapi_queue_cmd(struct atapi_softc *atp, int8_t *ccb, void *data, - int32_t count, int32_t flags, /*timeout,*/ + int32_t count, int32_t flags, int32_t timeout, atapi_callback_t callback, void *driver, struct buf *bp) { struct atapi_request *request; int32_t error = 0; int32_t s; + atp->last_cmd = ccb[0]; if (!(request = malloc(sizeof(struct atapi_request), M_DEVBUF, M_NOWAIT))) return -1; bzero(request, sizeof(struct atapi_request)); @@ -189,7 +189,10 @@ atapi_queue_cmd(struct atapi_softc *atp, int8_t *ccb, void *data, s = splbio(); /* link onto controller queue */ - TAILQ_INSERT_TAIL(&atp->controller->atapi_queue, request, chain); + if (ccb[0] == ATAPI_REQUEST_SENSE) + TAILQ_INSERT_HEAD(&atp->controller->atapi_queue, request, chain); + else + TAILQ_INSERT_TAIL(&atp->controller->atapi_queue, request, chain); /* try to start controller */ if (atp->controller->active == ATA_IDLE) @@ -197,22 +200,31 @@ atapi_queue_cmd(struct atapi_softc *atp, int8_t *ccb, void *data, splx(s); -#ifdef ATAPI_DEBUG - printf("atapi: queued %s cmd\n", atapi_cmd2str(ccb[0])); -#endif + /* wait for command to complete */ + if (tsleep((caddr_t)request, PRIBIO, "atprq", timeout*100)) { + if (atp->controller->active != ATA_IDLE) + atp->controller->active = ATA_IDLE; + + /* should we reset device here ? */ + request->result |= 0xf0; + } - if (!callback) { - /* wait for command to complete */ - if (tsleep((caddr_t)request, PRIBIO, "atprq", 0/*timeout*/)) - error = 0xf0; - else - error = request->result; #ifdef ATAPI_DEBUG - printf("atapi: phew, got back from tsleep\n"); + printf("atapi: phew, got back from tsleep with %s\n" + (request->result & 0xf0) == 0xf0 ? "timeout" : "wakeup")); #endif + + if (callback) { + (request->callback)(request); free(request, M_DEVBUF); + return 0; } - return error; + error = request->result; + free(request, M_DEVBUF); + if (ccb[0] == ATAPI_REQUEST_SENSE) + return 0; + else + return atapi_error(atp, error); } void @@ -276,7 +288,8 @@ printf("atapi_interrupt: enter\n"); /* get drive status */ if (atapi_wait(atp, 0) < 0) { printf("atapi_interrupt: timeout waiting for status"); - /* maybe check sense code ?? SOS */ + request->result = inb(atp->controller->ioaddr + ATA_ERROR); + wakeup((caddr_t)request); return ATA_OP_FINISHED; } atp->controller->status = inb(atp->controller->ioaddr + ATA_STATUS); @@ -377,22 +390,57 @@ printf("atapi_interrupt: length=%d reason=0x%02x\n", length, reason); } TAILQ_REMOVE(&atp->controller->atapi_queue, request, chain); + #ifdef ATAPI_DEBUG printf("atapi_interrupt: error=0x%02x\n", request->result); #endif - if (request->callback) { - (request->callback)(request); - free(request, M_DEVBUF); - } - else - wakeup((caddr_t)request); + + wakeup((caddr_t)request); return ATA_OP_FINISHED; } -void +int32_t atapi_error(struct atapi_softc *atp, int32_t error) { - printf("atapi: error = 0x%02x\n", error); + struct atapi_reqsense sense; + int8_t cmd = atp->last_cmd; + int8_t ccb[16] = { ATAPI_REQUEST_SENSE, 0, 0, 0, sizeof(sense), + 0, 0, 0 ,0 ,0, 0, 0, 0, 0, 0, 0 }; + + switch ((error & 0xf0)) { + case ATAPI_SK_RESERVED: + printf("atapi_error: %s - timeout error = %02x\n", + atapi_cmd2str(cmd), error & 0x0f); + return EIO; + + case ATAPI_SK_NO_SENSE: + if (error & 0x0f) { + printf("atapi_error: %s - error = %02x\n", + atapi_cmd2str(cmd), error & 0x0f); + return EIO; + } + return 0; + + case ATAPI_SK_RECOVERED_ERROR: + printf("atapi_error: %s - recovered error\n", atapi_cmd2str(cmd)); + return 0; + + case ATAPI_SK_NOT_READY: + if (error & 0x0f) + break; + return EBUSY; + + case ATAPI_SK_UNIT_ATTENTION: + return EAGAIN; /* misused */ + } + + bzero(&sense, sizeof(struct atapi_reqsense)); + atapi_queue_cmd(atp, ccb, &sense, sizeof(struct atapi_reqsense), + A_READ, 10, NULL, NULL, NULL); + printf("atapi_error: %s - %s skey=%01x asc=%02x ascq=%02x error=%02x\n", + atapi_cmd2str(cmd), atapi_skey2str(sense.sense_key), + sense.sense_key, sense.asc, sense.ascq, error & 0x0f); + return EIO; } void @@ -423,17 +471,21 @@ atapi_type(int32_t type) } } -#ifdef ATAPI_DEBUG static int8_t * atapi_cmd2str(u_int8_t cmd) { switch (cmd) { case 0x00: return ("TEST_UNIT_READY"); - case 0x01: return ("REZERO_UNIT"); + case 0x01: return ("REZERO_UNIT/TAPE_REWIND"); case 0x03: return ("REQUEST_SENSE"); case 0x04: return ("FORMAT_UNIT"); + case 0x08: return ("TAPE_READ"); + case 0x0a: return ("TAPE_WRITE"); + case 0x10: return ("TAPE_WEOF"); + case 0x11: return ("TAPE_SPACE"); + case 0x19: return ("TAPE_ERASE"); case 0x1a: return ("TAPE_MODE_SENSE"); - case 0x1b: return ("START_STOP"); + case 0x1b: return ("START_STOP/TAPE_LOAD"); case 0x1e: return ("PREVENT_ALLOW"); case 0x25: return ("READ_CAPACITY"); case 0x28: return ("READ_BIG"); @@ -462,12 +514,35 @@ atapi_cmd2str(u_int8_t cmd) case 0xbe: return ("READ_CD"); default: { static int8_t buffer[16]; - sprintf(buffer, "Unknown 0x%02x", cmd); + sprintf(buffer, "Unknown CMD (0x%02x)", cmd); return buffer; } } } -#endif + +static int8_t * +atapi_skey2str(u_int8_t skey) +{ + switch (skey) { + case 0x00: return ("NO SENSE"); + case 0x01: return ("RECOVERED ERROR"); + case 0x02: return ("NOT READY"); + case 0x03: return ("MEDIUM ERROR"); + case 0x04: return ("HARDWARE ERROR"); + case 0x05: return ("ILLEGAL REQUEST"); + case 0x06: return ("UNIT ATTENTION"); + case 0x07: return ("DATA PROTECT"); + case 0x08: return ("BLANK CHECK"); + case 0x09: return ("VENDOR SPECIFIC"); + case 0x0a: return ("COPY ABORTED"); + case 0x0b: return ("ABORTED COMMAND"); + case 0x0c: return ("EQUAL"); + case 0x0d: return ("VOLUME OVERFLOW"); + case 0x0e: return ("MISCOMPARE"); + case 0x0f: return ("RESERVED"); + default: return("UNKNOWN"); + } +} static int32_t atapi_wait(struct atapi_softc *atp, u_int8_t mask) diff --git a/sys/dev/ata/atapi-all.h b/sys/dev/ata/atapi-all.h index 6600eaf..82f51a8 100644 --- a/sys/dev/ata/atapi-all.h +++ b/sys/dev/ata/atapi-all.h @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: atapi-all.h,v 1.5 1999/05/17 15:58:45 sos Exp $ + * $Id: atapi-all.h,v 1.6 1999/05/20 09:12:04 sos Exp $ */ /* ATAPI misc defines */ @@ -86,6 +86,22 @@ #define ATAPI_MECH_STATUS 0xbd /* get changer status */ #define ATAPI_READ_CD 0xbe /* read data */ +/* ATAPI tape commands not in std ATAPI command set */ +#define ATAPI_TAPE_REWIND 0x01 /* tape rewind */ +#define ATAPI_TAPE_READ_CMD 0x08 /* tape read data */ +#define ATAPI_TAPE_WRITE_CMD 0x0a /* tape write data */ +#define ATAPI_TAPE_WEOF 0x10 /* tape write EOF */ +#define WEOF_WRITE_MASK 0x01 +#define ATAPI_TAPE_SPACE_CMD 0x11 /* tape space command */ +#define SP_FM 0x01 +#define SP_EOD 0x03 +#define ATAPI_TAPE_ERASE 0x19 /* tape erase */ +#define ATAPI_TAPE_MODE_SENSE 0x1a /* tape mode sense */ +#define ATAPI_TAPE_LOAD_UNLOAD 0x1b /* tape load/unload */ +#define LU_LOAD_MASK 0x01 +#define LU_RETENSION_MASK 0x02 +#define LU_EOT_MASK 0x04 + /* ATAPI device parameter information */ struct atapi_params { u_int8_t cmdsize :2; /* packet command size */ @@ -185,32 +201,34 @@ struct atapi_params { }; /* ATAPI REQUEST SENSE structure */ -struct reqsense { +struct atapi_reqsense { u_int8_t error_code :7; /* current or deferred errors */ - u_int8_t valid :1; /* follows QIC-157C */ - u_int8_t reserved1; /* Segment number - reserved */ + u_int8_t valid :1; /* follows ATAPI spec */ + u_int8_t segment; /* Segment number */ u_int8_t sense_key :4; /* sense key */ u_int8_t reserved2_4 :1; /* reserved */ u_int8_t ili :1; /* incorrect length indicator */ u_int8_t eom :1; /* end of medium */ u_int8_t filemark :1; /* filemark */ - u_int8_t info __attribute__((packed)); /* cmd specific info */ - u_int8_t asl; /* additional sense length (n-7) */ - u_int8_t command_specific; /* additional cmd specific info */ + /* cmd information */ + u_int32_t cmd_info __attribute__((packed)); + u_int8_t sense_length; /* additional sense length (n-7) */ + /* additional cmd specific info */ + u_int32_t cmd_specific_info __attribute__((packed)); u_int8_t asc; /* additional sense code */ u_int8_t ascq; /* additional sense code qualifier */ u_int8_t replaceable_unit_code; /* field replaceable unit code */ u_int8_t sk_specific1 :7; /* sense key specific */ u_int8_t sksv :1; /* sense key specific info valid */ u_int8_t sk_specific2; /* sense key specific */ - u_int8_t sk_specific3; /* sense key Specific */ - u_int8_t pad[2]; /* padding */ + u_int8_t sk_specific3; /* sense key specific */ }; struct atapi_softc { struct ata_softc *controller; /* ptr to parent ctrl */ struct atapi_params *atapi_parm; /* ata device params */ int32_t unit; /* ATA_MASTER or ATA_SLAVE */ + int8_t last_cmd; /* last cmd executed */ u_int32_t flags; /* drive flags */ }; @@ -237,7 +255,7 @@ struct atapi_request { void atapi_transfer(struct atapi_request *); int32_t atapi_interrupt(struct atapi_request *); -int32_t atapi_queue_cmd(struct atapi_softc *, int8_t [], void *, int32_t, int32_t, atapi_callback_t, void *, struct buf *); -void atapi_error(struct atapi_softc *, int32_t); +int32_t atapi_queue_cmd(struct atapi_softc *, int8_t [], void *, int32_t, int32_t, int32_t, atapi_callback_t, void *, struct buf *); +int32_t atapi_error(struct atapi_softc *, int32_t); void atapi_dump(int8_t *, void *, int32_t); diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c index 200b648..a0cf35a 100644 --- a/sys/dev/ata/atapi-cd.c +++ b/sys/dev/ata/atapi-cd.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: atapi-cd.c,v 1.9 1999/05/30 16:51:14 phk Exp $ + * $Id: atapi-cd.c,v 1.10 1999/05/31 11:24:27 phk Exp $ */ #include "ata.h" @@ -60,8 +60,6 @@ static d_close_t acdclose; static d_ioctl_t acdioctl; static d_strategy_t acdstrategy; -#define BDEV_MAJOR 31 -#define CDEV_MAJOR 117 static struct cdevsw acd_cdevsw = { /* open */ acdopen, /* close */ acdclose, @@ -76,26 +74,26 @@ static struct cdevsw acd_cdevsw = { /* strategy */ acdstrategy, /* name */ "acd", /* parms */ noparms, - /* maj */ CDEV_MAJOR, + /* maj */ 117, /* dump */ nodump, /* psize */ nopsize, /* flags */ D_DISK, /* maxio */ 0, - /* bmaj */ BDEV_MAJOR + /* bmaj */ 31 }; -#define NUNIT 16 /* Max # of devices */ +#define NUNIT 16 /* max # of devices */ -#define F_BOPEN 0x0001 /* The block device is opened */ +#define F_BOPEN 0x0001 /* the block device is opened */ #define F_MEDIA_CHANGED 0x0002 /* The media have changed since open */ -#define F_LOCKED 0x0004 /* This unit is locked (or should be) */ -#define F_TRACK_PREP 0x0008 /* Track should be prep'ed */ -#define F_TRACK_PREPED 0x0010 /* Track has been prep'ed */ -#define F_DISK_PREPED 0x0020 /* Disk has been prep'ed */ -#define F_WRITTEN 0x0040 /* The medium has been written to */ +#define F_LOCKED 0x0004 /* this unit is locked (or should be) */ +#define F_TRACK_PREP 0x0008 /* track should be prep'ed */ +#define F_TRACK_PREPED 0x0010 /* track has been prep'ed */ +#define F_DISK_PREPED 0x0020 /* disk has been prep'ed */ +#define F_WRITTEN 0x0040 /* the medium has been written to */ static struct acd_softc *acdtab[NUNIT]; -static int32_t acdnlun = 0; /* Number of configured drives */ +static int32_t acdnlun = 0; /* number of configured drives */ int32_t acdattach(struct atapi_softc *); static struct acd_softc *acd_init_lun(struct atapi_softc *, int, struct devstat *); @@ -138,7 +136,7 @@ acdattach(struct atapi_softc *atp) return -1; } - /* Get drive capabilities, some drives needs this repeated */ + /* get drive capabilities, some drives needs this repeated */ for (count = 0 ; count < 5 ; count++) { if (!(error = acd_mode_sense(cdp, ATAPI_CDROM_CAP_PAGE, &cdp->cap, sizeof(cdp->cap)))) @@ -154,7 +152,7 @@ acdattach(struct atapi_softc *atp) cdp->cap.cur_speed = ntohs(cdp->cap.cur_speed); acd_describe(cdp); - /* If this is a changer device, allocate the neeeded lun's */ + /* if this is a changer device, allocate the neeeded lun's */ if (cdp->cap.mech == MST_MECH_CHANGER) { int8_t ccb[16] = { ATAPI_MECH_STATUS, 0, 0, 0, 0, 0, 0, 0, @@ -168,7 +166,7 @@ acdattach(struct atapi_softc *atp) } bzero(chp, sizeof(struct changer)); error = atapi_queue_cmd(cdp->atp, ccb, chp, sizeof(struct changer), - A_READ, NULL, NULL, NULL); + A_READ, 60, NULL, NULL, NULL); #ifdef ACD_DEBUG printf("error=%02x curr=%02x slots=%d len=%d\n", @@ -420,7 +418,7 @@ acdopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) return ENXIO; if (!(cdp->flags & F_BOPEN) && !cdp->refcnt) { - acd_lock_device(cdp, 1); /* Prevent user eject */ + acd_lock_device(cdp, 1); /* prevent user eject */ cdp->flags |= F_LOCKED; } if (fmt == S_IFBLK) @@ -428,14 +426,8 @@ acdopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) else cdp->refcnt++; - if (!(flags & O_NONBLOCK)) { - if (acd_read_toc(cdp)) { - if (!(flags & FWRITE)) { - printf("acd%d: read_toc failed\n", lun); - return EIO; - } - } - } + if (!(flags & O_NONBLOCK) && acd_read_toc(cdp) && !(flags & FWRITE)) + printf("acd%d: read_toc failed\n", lun); return 0; } @@ -453,16 +445,16 @@ acdclose(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) else cdp->refcnt--; - /* Are we the last open ?? */ + /* are we the last open ?? */ if (!(cdp->flags & F_BOPEN) && !cdp->refcnt) { - /* Yup, do we need to close any written tracks */ + /* yup, do we need to close any written tracks */ if ((flags & FWRITE) != 0) { if ((cdp->flags & F_TRACK_PREPED) != 0) { acd_close_track(cdp); cdp->flags &= ~(F_TRACK_PREPED | F_TRACK_PREP); } } - acd_lock_device(cdp, 0); /* Allow the user eject */ + acd_lock_device(cdp, 0); /* allow the user eject */ } cdp->flags &= ~F_LOCKED; return 0; @@ -478,7 +470,9 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) if (cdp->flags & F_MEDIA_CHANGED) switch (cmd) { case CDIOCRESET: - break; + acd_test_unit_ready(cdp); + break; + default: acd_read_toc(cdp); acd_lock_device(cdp, 1); @@ -488,46 +482,59 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) switch (cmd) { case CDIOCRESUME: - return acd_pause_device(cdp, 1); + error = acd_pause_device(cdp, 1); + break; case CDIOCPAUSE: - return acd_pause_device(cdp, 0); + error = acd_pause_device(cdp, 0); + break; case CDIOCSTART: - return acd_start_device(cdp, 1); + error = acd_start_device(cdp, 1); + break; case CDIOCSTOP: - return acd_start_device(cdp, 0); + error = acd_start_device(cdp, 0); + break; case CDIOCALLOW: acd_select_slot(cdp); cdp->flags &= ~F_LOCKED; - return acd_lock_device(cdp, 0); + error = acd_lock_device(cdp, 0); + break; case CDIOCPREVENT: acd_select_slot(cdp); cdp->flags |= F_LOCKED; - return acd_lock_device(cdp, 1); + error = acd_lock_device(cdp, 1); + break; case CDIOCRESET: error = suser(p); if (error) - return error; - return acd_test_unit_ready(cdp); + break; + error = acd_test_unit_ready(cdp); + break; case CDIOCEJECT: - if ((cdp->flags & F_BOPEN) && cdp->refcnt) - return EBUSY; - return acd_eject(cdp, 0); + if ((cdp->flags & F_BOPEN) && cdp->refcnt) { + error = EBUSY; + break; + } + error = acd_eject(cdp, 0); + break; case CDIOCCLOSE: if ((cdp->flags & F_BOPEN) && cdp->refcnt) - return 0; - return acd_eject(cdp, 1); + break; + error = acd_eject(cdp, 1); + break; case CDIOREADTOCHEADER: - if (!cdp->toc.hdr.ending_track) - return EIO; + if (!cdp->toc.hdr.ending_track) { + error = EIO; + break; + } bcopy(&cdp->toc.hdr, addr, sizeof(cdp->toc.hdr)); break; @@ -539,29 +546,37 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) u_int32_t len; u_int8_t starting_track = te->starting_track; - if (!cdp->toc.hdr.ending_track) - return EIO; + if (!cdp->toc.hdr.ending_track) { + error = EIO; + break; + } if (te->data_len < sizeof(toc->tab[0]) || (te->data_len % sizeof(toc->tab[0])) != 0 || (te->address_format != CD_MSF_FORMAT && - te->address_format != CD_LBA_FORMAT)) - return EINVAL; + te->address_format != CD_LBA_FORMAT)) { + error = EINVAL; + break; + } if (!starting_track) starting_track = toc->hdr.starting_track; else if (starting_track == 170) starting_track = toc->hdr.ending_track + 1; else if (starting_track < toc->hdr.starting_track || - starting_track > toc->hdr.ending_track + 1) - return EINVAL; + starting_track > toc->hdr.ending_track + 1) { + error = EINVAL; + break; + } len = ((toc->hdr.ending_track + 1 - starting_track) + 1) * sizeof(toc->tab[0]); if (te->data_len < len) len = te->data_len; - if (len > sizeof(toc->tab)) - return EINVAL; + if (len > sizeof(toc->tab)) { + error = EINVAL; + break; + } if (te->address_format == CD_MSF_FORMAT) { struct cd_toc_entry *entry; @@ -574,8 +589,9 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) lba2msf(ntohl(entry->addr.lba), &entry->addr.msf.minute, &entry->addr.msf.second, &entry->addr.msf.frame); } - return copyout(toc->tab + starting_track - toc->hdr.starting_track, - te->data, len); + error = copyout(toc->tab + starting_track - toc->hdr.starting_track, + te->data, len); + break; } case CDIOREADTOCENTRY: { @@ -585,20 +601,26 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) struct toc buf; u_int8_t track = te->track; - if (!cdp->toc.hdr.ending_track) - return EIO; + if (!cdp->toc.hdr.ending_track) { + error = EIO; + break; + } if (te->address_format != CD_MSF_FORMAT && - te->address_format != CD_LBA_FORMAT) - return EINVAL; + te->address_format != CD_LBA_FORMAT) { + error = EINVAL; + break; + } if (!track) track = toc->hdr.starting_track; else if (track == 170) track = toc->hdr.ending_track + 1; else if (track < toc->hdr.starting_track || - track > toc->hdr.ending_track + 1) - return EINVAL; + track > toc->hdr.ending_track + 1) { + error = EINVAL; + break; + } if (te->address_format == CD_MSF_FORMAT) { struct cd_toc_entry *entry; @@ -626,12 +648,16 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) 0, 0, 0, 0, 0, 0, 0 }; if (len > sizeof(data) || - len < sizeof(struct cd_sub_channel_header)) - return EINVAL; + len < sizeof(struct cd_sub_channel_header)) { + error = EINVAL; + break; + } + + if ((error = atapi_queue_cmd(cdp->atp, ccb, &cdp->subchan, + sizeof(cdp->subchan), A_READ, 10, + NULL, NULL, NULL))) + break; - if (atapi_queue_cmd(cdp->atp, ccb, &cdp->subchan, - sizeof(cdp->subchan), A_READ, NULL, NULL, NULL)) - return EIO; #ifdef ACD_DEBUG atapi_dump("acd: subchan", &cdp->subchan, sizeof(cdp->subchan)); #endif @@ -656,7 +682,8 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) data.what.position.addr_type = cdp->subchan.control >> 4; data.what.position.track_number = cdp->subchan.track; data.what.position.index_number = cdp->subchan.indx; - return copyout(&data, args->data, len); + error = copyout(&data, args->data, len); + break; } case CDIOCPLAYMSF: @@ -667,7 +694,9 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) args->end_m, args->end_s, args->end_f, 0, 0, 0, 0, 0, 0, 0 }; - return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL); + error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10, + NULL, NULL,NULL); + break; } case CDIOCPLAYBLOCKS: @@ -679,7 +708,9 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) args->len>>8, args->len, 0, 0, 0, 0, 0, 0 }; - return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL); + error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10, + NULL, NULL, NULL); + break; } case CDIOCPLAYTRACKS: @@ -689,8 +720,10 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) int32_t t1, t2; int8_t ccb[16]; - if (!cdp->toc.hdr.ending_track) - return EIO; + if (!cdp->toc.hdr.ending_track) { + error = EIO; + break; + } if (args->end_track < cdp->toc.hdr.ending_track + 1) ++args->end_track; @@ -698,8 +731,10 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) args->end_track = cdp->toc.hdr.ending_track + 1; t1 = args->start_track - cdp->toc.hdr.starting_track; t2 = args->end_track - cdp->toc.hdr.starting_track; - if (t1 < 0 || t2 < 0) - return EINVAL; + if (t1 < 0 || t2 < 0) { + error = EINVAL; + break; + } start = ntohl(cdp->toc.tab[t1].addr.lba); len = ntohl(cdp->toc.tab[t2].addr.lba) - start; @@ -714,7 +749,9 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) ccb[8] = len>>8; ccb[9] = len; - return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL); + error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 10, + NULL, NULL, NULL); + break; } case CDIOCREADAUDIO: @@ -724,11 +761,15 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) u_int8_t *buffer, *ubuf = args->buffer; int8_t ccb[16]; - if (!cdp->toc.hdr.ending_track) - return EIO; + if (!cdp->toc.hdr.ending_track) { + error = EIO; + break; + } - if ((frames = args->nframes) < 0) - return EINVAL; + if ((frames = args->nframes) < 0) { + error = EINVAL; + break; + } if (args->address_format == CD_LBA_FORMAT) lba = args->address.lba; @@ -736,14 +777,19 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) lba = msf2lba(args->address.msf.minute, args->address.msf.second, args->address.msf.frame); - else - return EINVAL; + else { + error = EINVAL; + break; + } + #ifndef CD_BUFFER_BLOCKS #define CD_BUFFER_BLOCKS 13 #endif if (!(buffer = malloc(CD_BUFFER_BLOCKS * 2352, - M_TEMP,M_NOWAIT))) - return ENOMEM; + M_TEMP,M_NOWAIT))) { + error = ENOMEM; + break; + } bzero(ccb, sizeof(ccb)); while (frames > 0) { int32_t size; @@ -761,7 +807,7 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) ccb[8] = blocks; ccb[9] = 0xf0; if ((error = atapi_queue_cmd(cdp->atp, ccb, buffer, size, - A_READ, NULL, NULL, NULL))) + A_READ, 30, NULL, NULL, NULL))) break; if ((error = copyout(buffer, ubuf, size))) @@ -778,7 +824,7 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) lba2msf(lba, &args->address.msf.minute, &args->address.msf.second, &args->address.msf.frame); - return error; + break; } case CDIOCGETVOL: @@ -787,15 +833,18 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE, &cdp->au, sizeof(cdp->au)))) - return error; - if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE) - return EIO; + break; + + if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE) { + error = EIO; + break; + } arg->vol[0] = cdp->au.port[0].volume; arg->vol[1] = cdp->au.port[1].volume; arg->vol[2] = cdp->au.port[2].volume; arg->vol[3] = cdp->au.port[3].volume; + break; } - break; case CDIOCSETVOL: { @@ -803,12 +852,14 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE, &cdp->au, sizeof(cdp->au)))) - return error; - if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE) - return EIO; + break; + if (cdp->au.page_code != ATAPI_CDROM_AUDIO_PAGE) { + error = EIO; + break; + } if ((error = acd_mode_sense(cdp, ATAPI_CDROM_AUDIO_PAGE_MASK, &cdp->aumask, sizeof(cdp->aumask)))) - return error; + break; cdp->au.data_length = 0; cdp->au.port[0].channels = CHANNEL_0; cdp->au.port[1].channels = CHANNEL_1; @@ -816,30 +867,37 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) cdp->au.port[1].volume = arg->vol[1] & cdp->aumask.port[1].volume; cdp->au.port[2].volume = arg->vol[2] & cdp->aumask.port[2].volume; cdp->au.port[3].volume = arg->vol[3] & cdp->aumask.port[3].volume; - return acd_mode_select(cdp, &cdp->au, sizeof(cdp->au)); + error = acd_mode_select(cdp, &cdp->au, sizeof(cdp->au)); + break; } case CDIOCSETPATCH: { struct ioc_patch *arg = (struct ioc_patch *)addr; - return acd_setchan(cdp, arg->patch[0], arg->patch[1], - arg->patch[2], arg->patch[3]); + error = acd_setchan(cdp, arg->patch[0], arg->patch[1], + arg->patch[2], arg->patch[3]); + break; } case CDIOCSETMONO: - return acd_setchan(cdp, CHANNEL_0|CHANNEL_1, CHANNEL_0|CHANNEL_1, 0, 0); + error = acd_setchan(cdp, CHANNEL_0|CHANNEL_1, CHANNEL_0|CHANNEL_1, 0,0); + break; case CDIOCSETSTEREO: - return acd_setchan(cdp, CHANNEL_0, CHANNEL_1, 0, 0); + error = acd_setchan(cdp, CHANNEL_0, CHANNEL_1, 0, 0); + break; case CDIOCSETMUTE: - return acd_setchan(cdp, 0, 0, 0, 0); + error = acd_setchan(cdp, 0, 0, 0, 0); + break; case CDIOCSETLEFT: - return acd_setchan(cdp, CHANNEL_0, CHANNEL_0, 0, 0); + error = acd_setchan(cdp, CHANNEL_0, CHANNEL_0, 0, 0); + break; case CDIOCSETRIGHT: - return acd_setchan(cdp, CHANNEL_1, CHANNEL_1, 0, 0); + error = acd_setchan(cdp, CHANNEL_1, CHANNEL_1, 0, 0); + break; case CDRIOCNEXTWRITEABLEADDR: { @@ -847,8 +905,11 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) if ((error = acd_read_track_info(cdp, 0xff, &track_info))) break; - if (!track_info.nwa_valid) - return EINVAL; + + if (!track_info.nwa_valid) { + error = EINVAL; + break; + } cdp->next_writeable_lba = track_info.next_writeable_addr; *(int*)addr = track_info.next_writeable_addr; } @@ -868,8 +929,8 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) cdp->speed = w->speed; } } + break; } - break; case WORMIOCPREPTRACK: { @@ -886,8 +947,8 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) cdp->flags |= F_TRACK_PREP; cdp->preptrack = *w; } + break; } - break; case WORMIOCFINISHTRACK: if ((cdp->flags & F_TRACK_PREPED) != 0) @@ -897,8 +958,7 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) case WORMIOCFIXATION: { - struct wormio_fixation *w = - (struct wormio_fixation *)addr; + struct wormio_fixation *w = (struct wormio_fixation *)addr; if ((cdp->flags & F_WRITTEN) == 0) error = EINVAL; @@ -914,14 +974,15 @@ acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) cdp->flags &= ~(F_WRITTEN|F_DISK_PREPED|F_TRACK_PREP|F_TRACK_PREPED); } + break; } - break; case CDRIOCBLANK: - return acd_blank_disk(cdp); + error = acd_blank_disk(cdp); + break; default: - return ENOTTY; + error = ENOTTY; } return error; } @@ -972,7 +1033,7 @@ acd_start(struct acd_softc *cdp) bufq_remove(&cdp->buf_queue, bp); - /* Should reject all queued entries if media have changed. */ + /* should reject all queued entries if media have changed. */ if (cdp->flags & F_MEDIA_CHANGED) { bp->b_error = EIO; bp->b_flags |= B_ERROR; @@ -1022,7 +1083,7 @@ acd_start(struct acd_softc *cdp) devstat_start_transaction(cdp->stats); atapi_queue_cmd(cdp->atp, ccb, bp->b_data, bp->b_bcount, - (bp->b_flags&B_READ)?A_READ : 0, acd_done, cdp, bp); + (bp->b_flags&B_READ)?A_READ : 0, 30, acd_done, cdp, bp); } static void @@ -1035,8 +1096,7 @@ acd_done(struct atapi_request *request) DEVSTAT_TAG_NONE, (bp->b_flags&B_READ) ? DEVSTAT_READ:DEVSTAT_WRITE); if (request->result) { - atapi_error(request->device, request->result); - bp->b_error = EIO; + bp->b_error = atapi_error(request->device, request->result); bp->b_flags |= B_ERROR; } else { @@ -1054,7 +1114,7 @@ acd_test_unit_ready(struct acd_softc *cdp) int8_t ccb[16] = { ATAPI_TEST_UNIT_READY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL); + return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL, NULL); } static int32_t @@ -1063,7 +1123,7 @@ acd_lock_device(struct acd_softc *cdp, int32_t lock) int8_t ccb[16] = { ATAPI_PREVENT_ALLOW, 0, 0, 0, lock, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL); + return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL, NULL); } static int32_t @@ -1072,7 +1132,7 @@ acd_start_device(struct acd_softc *cdp, int32_t start) int8_t ccb[16] = { ATAPI_START_STOP, 0, 0, 0, start, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL); + return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL, NULL); } static int32_t @@ -1081,7 +1141,7 @@ acd_pause_device(struct acd_softc *cdp, int32_t pause) int8_t ccb[16] = { ATAPI_START_STOP, 0, 0, 0, 0, 0, 0, 0, pause, 0, 0, 0, 0, 0, 0, 0 }; - return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL); + return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL, NULL); } static int32_t @@ -1092,7 +1152,7 @@ acd_mode_sense(struct acd_softc *cdp, u_int8_t page, int8_t ccb[16] = { ATAPI_MODE_SENSE, 0, page, 0, 0, 0, 0, pagesize>>8, pagesize, 0, 0, 0, 0, 0, 0, 0 }; - error = atapi_queue_cmd(cdp->atp, ccb, pagebuf, pagesize, A_READ, + error = atapi_queue_cmd(cdp->atp, ccb, pagebuf, pagesize, A_READ, 30, NULL, NULL, NULL); #ifdef ACD_DEBUG atapi_dump("acd: mode sense ", pagebuf, pagesize); @@ -1110,7 +1170,7 @@ acd_mode_select(struct acd_softc *cdp, void *pagebuf, int32_t pagesize) printf("acd: modeselect pagesize=%d\n", pagesize); atapi_dump("acd: mode select ", pagebuf, pagesize); #endif - return atapi_queue_cmd(cdp->atp, ccb, pagebuf, pagesize, 0, + return atapi_queue_cmd(cdp->atp, ccb, pagebuf, pagesize, 0, 30, NULL, NULL, NULL); } @@ -1127,16 +1187,14 @@ acd_read_toc(struct acd_softc *cdp) acd_select_slot(cdp); error = acd_test_unit_ready(cdp); - if ((error & ATAPI_SK_MASK) == ATAPI_SK_UNIT_ATTENTION) { + if (error == EAGAIN) { cdp->flags |= F_MEDIA_CHANGED; cdp->flags &= ~(F_WRITTEN | F_TRACK_PREP | F_TRACK_PREPED); error = acd_test_unit_ready(cdp); } - if (error) { - atapi_error(cdp->atp, error); - return EIO; - } + if (error) + return error; cdp->flags &= ~F_MEDIA_CHANGED; @@ -1144,7 +1202,8 @@ acd_read_toc(struct acd_softc *cdp) ccb[0] = ATAPI_READ_TOC; ccb[7] = len>>8; ccb[8] = len; - if (atapi_queue_cmd(cdp->atp, ccb, &cdp->toc, len, A_READ, NULL,NULL,NULL)){ + if (atapi_queue_cmd(cdp->atp, ccb, &cdp->toc, len, A_READ, 30, + NULL, NULL, NULL)){ bzero(&cdp->toc, sizeof(cdp->toc)); return 0; } @@ -1159,7 +1218,8 @@ acd_read_toc(struct acd_softc *cdp) ccb[0] = ATAPI_READ_TOC; ccb[7] = len>>8; ccb[8] = len; - if (atapi_queue_cmd(cdp->atp, ccb, &cdp->toc, len, A_READ, NULL,NULL,NULL)){ + if (atapi_queue_cmd(cdp->atp, ccb, &cdp->toc, len, A_READ, 30, + NULL, NULL, NULL)){ bzero(&cdp->toc, sizeof(cdp->toc)); return 0; } @@ -1169,7 +1229,7 @@ acd_read_toc(struct acd_softc *cdp) bzero(ccb, sizeof(ccb)); ccb[0] = ATAPI_READ_CAPACITY; if (atapi_queue_cmd(cdp->atp, ccb, &cdp->info, sizeof(cdp->info), - A_READ, NULL, NULL, NULL)) + A_READ, 30, NULL, NULL, NULL)) bzero(&cdp->info, sizeof(cdp->info)); cdp->toc.tab[ntracks].control = cdp->toc.tab[ntracks - 1].control; @@ -1224,10 +1284,7 @@ acd_eject(struct acd_softc *cdp, int32_t close) error = acd_start_device(cdp, 0); - if ((error & ATAPI_SK_MASK) && - ((error & ATAPI_SK_MASK) == ATAPI_SK_NOT_READY || - (error & ATAPI_SK_MASK) == ATAPI_SK_UNIT_ATTENTION)) { - + if (error == EBUSY || error == EAGAIN) { if (!close) return 0; if ((error = acd_start_device(cdp, 3))) @@ -1237,10 +1294,8 @@ acd_eject(struct acd_softc *cdp, int32_t close) cdp->flags |= F_LOCKED; return 0; } - if (error) { - atapi_error(cdp->atp, error); - return EIO; - } + if (error) + return error; if (close) return 0; @@ -1261,25 +1316,25 @@ acd_select_slot(struct acd_softc *cdp) if (cdp->slot < 0 || cdp->changer_info->current_slot == cdp->slot) return; - /* Unlock (might not be needed but its cheaper than asking) */ + /* unlock (might not be needed but its cheaper than asking) */ acd_lock_device(cdp, 0); bzero(ccb, sizeof(ccb)); - /* Unload the current media from player */ + /* unload the current media from player */ ccb[0] = ATAPI_LOAD_UNLOAD; ccb[4] = 2; ccb[8] = cdp->changer_info->current_slot; - atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL); + atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL, NULL); /* load the wanted slot */ ccb[0] = ATAPI_LOAD_UNLOAD; ccb[4] = 3; ccb[8] = cdp->slot; - atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL); + atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL, NULL); cdp->changer_info->current_slot = cdp->slot; - /* Lock the media if needed */ + /* lock the media if needed */ if (cdp->flags & F_LOCKED) acd_lock_device(cdp, 1); } @@ -1294,13 +1349,10 @@ acd_open_disk(struct acd_softc *cdp, int32_t test) static int32_t acd_close_disk(struct acd_softc *cdp) { - int8_t ccb[16]; + int8_t ccb[16] = { ATAPI_CLOSE_TRACK, 0, 0x02, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }; - bzero(ccb, sizeof(ccb)); - ccb[0] = ATAPI_CLOSE_TRACK; - ccb[2] = 2; - ccb[5] = 0; /* track to close (0 = last open) */ - return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL); + return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 600, NULL, NULL, NULL); } static int32_t @@ -1376,11 +1428,10 @@ acd_open_track(struct acd_softc *cdp, struct wormio_prepare_track *ptp) static int32_t acd_close_track(struct acd_softc *cdp) { - int8_t ccb[16]; + int8_t ccb[16] = { ATAPI_SYNCHRONIZE_CACHE, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0}; - bzero(ccb, sizeof(ccb)); - ccb[0] = ATAPI_SYNCHRONIZE_CACHE; - return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL); + return atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 600, NULL, NULL, NULL); } static int32_t @@ -1395,7 +1446,7 @@ acd_read_track_info(struct acd_softc *cdp, 0, 0, 0, 0, 0, 0, 0 }; if ((error = atapi_queue_cmd(cdp->atp, ccb, info, sizeof(*info), - A_READ, NULL, NULL, NULL))) + A_READ, 30, NULL, NULL, NULL))) return error; info->track_start_addr = ntohl(info->track_start_addr); info->next_writeable_addr = ntohl(info->next_writeable_addr); @@ -1409,12 +1460,10 @@ static int32_t acd_blank_disk(struct acd_softc *cdp) { int32_t error; - int8_t ccb[16]; + int8_t ccb[16] = { ATAPI_BLANK, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }; - bzero(ccb, sizeof(ccb)); - ccb[0] = ATAPI_BLANK; - ccb[1] = 1; - error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL); + error = atapi_queue_cmd(cdp->atp, ccb, NULL, 0, 0, 60*60, NULL, NULL, NULL); cdp->flags |= F_MEDIA_CHANGED; cdp->flags &= ~(F_WRITTEN|F_TRACK_PREP|F_TRACK_PREPED); return error; @@ -1426,6 +1475,8 @@ acd_drvinit(void *unused) static int32_t acd_devsw_installed = 0; if (!acd_devsw_installed) { + if (!acd_cdevsw.d_maxio) + acd_cdevsw.d_maxio = 254 * DEV_BSIZE; cdevsw_add(&acd_cdevsw); acd_devsw_installed = 1; } diff --git a/sys/dev/ata/atapi-fd.c b/sys/dev/ata/atapi-fd.c index e89d636..437e8bb 100644 --- a/sys/dev/ata/atapi-fd.c +++ b/sys/dev/ata/atapi-fd.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: atapi-fd.c,v 1.9 1999/05/30 16:51:15 phk Exp $ + * $Id: atapi-fd.c,v 1.10 1999/05/31 11:24:29 phk Exp $ */ #include "ata.h" @@ -61,9 +61,6 @@ static d_close_t afdclose; static d_ioctl_t afdioctl; static d_strategy_t afdstrategy; -#define BDEV_MAJOR 32 -#define CDEV_MAJOR 118 - static struct cdevsw afd_cdevsw = { /* open */ afdopen, /* close */ afdclose, @@ -78,22 +75,22 @@ static struct cdevsw afd_cdevsw = { /* strategy */ afdstrategy, /* name */ "afd", /* parms */ noparms, - /* maj */ CDEV_MAJOR, + /* maj */ 118, /* dump */ nodump, /* psize */ nopsize, /* flags */ D_DISK, /* maxio */ 0, - /* bmaj */ BDEV_MAJOR, + /* bmaj */ 32, }; #define NUNIT 8 #define UNIT(d) ((minor(d) >> 3) & 3) -#define F_OPEN 0x0001 /* The device is opened */ -#define F_MEDIA_CHANGED 0x0002 /* The media have changed */ +#define F_OPEN 0x0001 /* the device is opened */ +#define F_MEDIA_CHANGED 0x0002 /* the media have changed */ -static struct afd_softc *afdtab[NUNIT]; /* Drive info by unit number */ -static int32_t afdnlun = 0; /* Number of config'd drives */ +static struct afd_softc *afdtab[NUNIT]; /* drive info by unit number */ +static int32_t afdnlun = 0; /* number of config'd drives */ int32_t afdattach(struct atapi_softc *); static int32_t afd_sense(struct afd_softc *); @@ -140,7 +137,7 @@ afdattach(struct atapi_softc *atp) devstat_add_entry(&fdp->stats, "afd", fdp->lun, DEV_BSIZE, DEVSTAT_NO_ORDERED_TAGS, DEVSTAT_TYPE_DIRECT | DEVSTAT_TYPE_IF_IDE, - 0x178); + 0x174); #ifdef DEVFS fdp->cdevs_token = devfs_add_devswf(&afd_cdevsw, dkmakeminor(fdp->lun, 0,0), DV_CHR, UID_ROOT, GID_OPERATOR, @@ -162,10 +159,10 @@ afd_sense(struct afd_softc *fdp) 0, 0, 0, 0, 0, 0, 0 }; bzero(buffer, sizeof(buffer)); - /* Get drive capabilities, some drives needs this repeated */ + /* get drive capabilities, some drives needs this repeated */ for (count = 0 ; count < 5 ; count++) { if (!(error = atapi_queue_cmd(fdp->atp, ccb, buffer, sizeof(buffer), - A_READ, NULL, NULL, NULL))) + A_READ, 30, NULL, NULL, NULL))) break; } #ifdef AFD_DEBUG @@ -246,7 +243,7 @@ afdopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) label.d_secpercyl = fdp->cap.heads * fdp->cap.sectors; label.d_secperunit = fdp->cap.heads * fdp->cap.sectors * fdp->cap.cylinders; - /* Initialize slice tables. */ + /* initialize slice tables. */ return dsopen("afd", dev, fmt, 0, &fdp->slices, &label, afd_strategy, (ds_setgeom_t *)NULL, &afd_cdevsw); } @@ -296,7 +293,6 @@ afdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) default: return ENOTTY; } - return error; } static void @@ -340,7 +336,7 @@ afd_start(struct afd_softc *fdp) bufq_remove(&fdp->buf_queue, bp); - /* Should reject all queued entries if media have changed. */ + /* should reject all queued entries if media have changed. */ if (fdp->flags & F_MEDIA_CHANGED) { bp->b_error = EIO; bp->b_flags |= B_ERROR; @@ -363,7 +359,6 @@ afd_start(struct afd_softc *fdp) devstat_start_transaction(&fdp->stats); while (fdp->transfersize && (count > fdp->transfersize)) { - ccb[2] = lba>>24; ccb[3] = lba>>16; ccb[4] = lba>>8; @@ -373,7 +368,7 @@ afd_start(struct afd_softc *fdp) atapi_queue_cmd(fdp->atp, ccb, data_ptr, fdp->transfersize * fdp->cap.sector_size, - (bp->b_flags & B_READ) ? A_READ : 0, + (bp->b_flags & B_READ) ? A_READ : 0, 30, afd_partial_done, fdp, bp); count -= fdp->transfersize; @@ -389,7 +384,7 @@ afd_start(struct afd_softc *fdp) ccb[8] = count; atapi_queue_cmd(fdp->atp, ccb, data_ptr, count * fdp->cap.sector_size, - (bp->b_flags & B_READ) ? A_READ : 0, afd_done, fdp, bp); + (bp->b_flags & B_READ) ? A_READ : 0, 30, afd_done, fdp, bp); } static void @@ -398,7 +393,7 @@ afd_partial_done(struct atapi_request *request) struct buf *bp = request->bp; if (request->result) { - bp->b_error = EIO; + bp->b_error = atapi_error(request->device, request->result); bp->b_flags |= B_ERROR; } bp->b_resid += request->bytecount; @@ -411,8 +406,7 @@ afd_done(struct atapi_request *request) struct afd_softc *fdp = request->driver; if (request->result || (bp->b_flags & B_ERROR)) { - atapi_error(request->device, request->result); - bp->b_error = EIO; + bp->b_error = atapi_error(request->device, request->result); bp->b_flags |= B_ERROR; } else @@ -432,7 +426,7 @@ afd_start_device(struct afd_softc *fdp, int32_t start) int8_t ccb[16] = { ATAPI_START_STOP, 0, 0, 0, start, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - return atapi_queue_cmd(fdp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL); + return atapi_queue_cmd(fdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL, NULL); } static int32_t @@ -441,7 +435,7 @@ afd_lock_device(struct afd_softc *fdp, int32_t lock) int8_t ccb[16] = { ATAPI_PREVENT_ALLOW, 0, 0, 0, lock, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - return atapi_queue_cmd(fdp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL); + return atapi_queue_cmd(fdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL, NULL); } static int32_t @@ -450,27 +444,23 @@ afd_eject(struct afd_softc *fdp, int32_t close) int32_t error; error = afd_start_device(fdp, 0); - if ((error & ATAPI_SK_MASK) && - ((error & ATAPI_SK_MASK) == ATAPI_SK_NOT_READY || - (error & ATAPI_SK_MASK) == ATAPI_SK_UNIT_ATTENTION)) { - + if (error == EBUSY || error == EAGAIN) { if (!close) return 0; if ((error = afd_start_device(fdp, 3))) return error; - afd_lock_device(fdp, 1); - return 0; - } - if (error) { - atapi_error(fdp->atp, error); - return EIO; + return afd_lock_device(fdp, 1); } + if (error) + return error; + if (close) return 0; tsleep((caddr_t) &lbolt, PRIBIO, "afdej1", 0); tsleep((caddr_t) &lbolt, PRIBIO, "afdej2", 0); - afd_lock_device(fdp, 0); + if ((error = afd_lock_device(fdp, 0))) + return error; fdp->flags |= F_MEDIA_CHANGED; return afd_start_device(fdp, 2); } @@ -482,6 +472,8 @@ afd_drvinit(void *unused) static int32_t afd_devsw_installed = 0; if (!afd_devsw_installed) { + if (!afd_cdevsw.d_maxio) + afd_cdevsw.d_maxio = 254 * DEV_BSIZE; cdevsw_add(&afd_cdevsw); afd_devsw_installed = 1; } diff --git a/sys/dev/ata/atapi-tape.c b/sys/dev/ata/atapi-tape.c index a471232..3f618c8 100644 --- a/sys/dev/ata/atapi-tape.c +++ b/sys/dev/ata/atapi-tape.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: atapi-tape.c,v 1.9 1999/05/30 16:51:16 phk Exp $ + * $Id: atapi-tape.c,v 1.10 1999/05/31 11:24:30 phk Exp $ */ #include "ata.h" @@ -57,9 +57,6 @@ static d_close_t astclose; static d_ioctl_t astioctl; static d_strategy_t aststrategy; -#define BDEV_MAJOR 33 -#define CDEV_MAJOR 119 - static struct cdevsw ast_cdevsw = { /* open */ astopen, /* close */ astclose, @@ -74,12 +71,12 @@ static struct cdevsw ast_cdevsw = { /* strategy */ aststrategy, /* name */ "ast", /* parms */ noparms, - /* maj */ CDEV_MAJOR, + /* maj */ 119, /* dump */ nodump, /* psize */ nopsize, /* flags */ D_TAPE, /* maxio */ 0, - /* bmaj */ BDEV_MAJOR + /* bmaj */ 33 }; static u_int32_t ast_total = 0; @@ -87,14 +84,14 @@ static u_int32_t ast_total = 0; #define NUNIT 8 #define UNIT(d) ((minor(d) >> 3) & 3) -#define F_OPEN 0x0001 /* The device is opened */ -#define F_MEDIA_CHANGED 0x0002 /* The media have changed */ -#define F_DATA_WRITTEN 0x0004 /* Data has been written */ -#define F_FM_WRITTEN 0x0008 /* Filemark has been written */ -#define F_CTL_WARN 0x0010 /* Have we warned about CTL wrong? */ +#define F_OPEN 0x0001 /* the device is opened */ +#define F_MEDIA_CHANGED 0x0002 /* the media have changed */ +#define F_DATA_WRITTEN 0x0004 /* data has been written */ +#define F_FM_WRITTEN 0x0008 /* filemark has been written */ +#define F_CTL_WARN 0x0010 /* have we warned about CTL wrong? */ -static struct ast_softc *asttab[NUNIT]; /* Drive info by unit number */ -static int32_t astnlun = 0; /* Number of config'd drives */ +static struct ast_softc *asttab[NUNIT]; /* drive info by unit number */ +static int32_t astnlun = 0; /* number of config'd drives */ int32_t astattach(struct atapi_softc *); static int32_t ast_sense(struct ast_softc *); @@ -138,7 +135,7 @@ astattach(struct atapi_softc *atp) devstat_add_entry(&stp->stats, "ast", stp->lun, DEV_BSIZE, DEVSTAT_NO_ORDERED_TAGS, DEVSTAT_TYPE_SEQUENTIAL | DEVSTAT_TYPE_IF_IDE, - 0x178); + 0x170); #ifdef DEVFS stp->cdevs_token = devfs_add_devswf(&ast_cdevsw, dkmakeminor(stp->lun, 0,0), DV_CHR, UID_ROOT, GID_OPERATOR, 0640, @@ -159,10 +156,10 @@ ast_sense(struct ast_softc *stp) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; bzero(buffer, sizeof(buffer)); - /* Get drive capabilities, some drives needs this repeated */ + /* get drive capabilities, some drives needs this repeated */ for (count = 0 ; count < 5 ; count++) { if (!(error = atapi_queue_cmd(stp->atp, ccb, buffer, sizeof(buffer), - A_READ, NULL, NULL, NULL))) + A_READ, 30, NULL, NULL, NULL))) break; } #ifdef AST_DEBUG @@ -252,15 +249,15 @@ astclose(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) if (lun >= astnlun || !(stp = asttab[lun])) return ENXIO; - /* Flush buffers, some drives fail here, but they should report ctl = 0 */ + /* flush buffers, some drives fail here, but they should report ctl = 0 */ if (stp->cap.ctl && (stp->flags & F_DATA_WRITTEN)) ast_write_filemark(stp, 0); - /* Write filemark if data written to tape */ + /* write filemark if data written to tape */ if ((stp->flags & (F_DATA_WRITTEN | F_FM_WRITTEN)) == F_DATA_WRITTEN) ast_write_filemark(stp, WEOF_WRITE_MASK); - /* If minor is even rewind on close */ + /* if minor is even rewind on close */ if (!(minor(dev) & 0x01)) ast_rewind(stp); @@ -306,59 +303,62 @@ astioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) struct mtop *mt = (struct mtop *)addr; switch ((int16_t) (mt->mt_op)) { + case MTWEOF: for (i=0; i < mt->mt_count && !error; i++) - error = ast_write_filemark(stp, WEOF_WRITE_MASK); + error = ast_write_filemark(stp, WEOF_WRITE_MASK); break; + case MTFSF: if (mt->mt_count) - error = ast_space_cmd(stp, SP_FM, mt->mt_count); + error = ast_space_cmd(stp, SP_FM, mt->mt_count); break; + case MTBSF: if (mt->mt_count) - error = ast_space_cmd(stp, SP_FM, -(mt->mt_count)); + error = ast_space_cmd(stp, SP_FM, -(mt->mt_count)); break; - case MTFSR: - error = EINVAL; break; - case MTBSR: - error = EINVAL; break; + case MTREW: error = ast_rewind(stp); break; + case MTOFFL: if ((error = ast_rewind(stp))) break; error = ast_load_unload(stp, !LU_LOAD_MASK); - break; + break; + case MTNOP: error = ast_write_filemark(stp, 0); break; - case MTCACHE: - error = EINVAL; break; - case MTNOCACHE: - error = EINVAL; break; - case MTSETBSIZ: - error = EINVAL; break; - case MTSETDNSTY: - error = EINVAL; break; + case MTERASE: error = ast_erase(stp); break; + case MTEOD: error = ast_space_cmd(stp, SP_EOD, 0); break; - case MTCOMP: - error = EINVAL; break; + case MTRETENS: error = ast_load_unload(stp, LU_RETENSION_MASK|LU_LOAD_MASK); break; + + case MTFSR: + case MTBSR: + case MTCACHE: + case MTNOCACHE: + case MTSETBSIZ: + case MTSETDNSTY: + case MTCOMP: default: error = EINVAL; } return error; } default: - return ENOTTY; + error = ENOTTY; } return error; } @@ -370,14 +370,14 @@ aststrategy(struct buf *bp) struct ast_softc *stp = asttab[lun]; int32_t x; - /* If it's a null transfer, return immediatly. */ + /* if it's a null transfer, return immediatly. */ if (bp->b_bcount == 0) { bp->b_resid = 0; biodone(bp); return; } - /* Check for != blocksize requests */ + /* check for != blocksize requests */ if (bp->b_bcount % stp->blksize) { printf("ast%d: bad request, must be multiple of %d\n", lun, stp->blksize); @@ -386,6 +386,8 @@ aststrategy(struct buf *bp) biodone(bp); return; } + + /* warn about transfers bigger than the device suggests */ if (bp->b_bcount > stp->blksize * stp->cap.ctl) { if ((stp->flags & F_CTL_WARN) == 0) { printf("ast%d: WARNING: CTL exceeded %ld>%d\n", @@ -427,7 +429,7 @@ ast_start(struct ast_softc *stp) devstat_start_transaction(&stp->stats); atapi_queue_cmd(stp->atp, ccb, bp->b_data, bp->b_bcount, - (bp->b_flags & B_READ) ? A_READ : 0, ast_done, stp, bp); + (bp->b_flags & B_READ) ? A_READ : 0, 30, ast_done, stp, bp); } static void @@ -441,9 +443,7 @@ ast_done(struct atapi_request *request) (bp->b_flags&B_READ) ? DEVSTAT_READ:DEVSTAT_WRITE); if (request->result) { - /* check for EOM and return ENOSPC */ - atapi_error(request->device, request->result); - bp->b_error = EIO; + bp->b_error = atapi_error(request->device, request->result); bp->b_flags |= B_ERROR; } else @@ -455,28 +455,18 @@ ast_done(struct atapi_request *request) static int32_t ast_space_cmd(struct ast_softc *stp, u_int8_t function, u_int32_t count) { - int32_t error; - int8_t ccb[16]; + int8_t ccb[16] = { ATAPI_TAPE_SPACE_CMD, function, + count>>16, count>>8, count, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }; - bzero(ccb, sizeof(ccb)); - ccb[0] = ATAPI_TAPE_SPACE_CMD; - ccb[1] = function; - ccb[2] = count>>16; - ccb[3] = count>>8; - ccb[4] = count; - - if ((error = atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL))){ - atapi_error(stp->atp, error); - return EIO; - } - return 0; + return atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0, 60*60, NULL, NULL, NULL); } static int32_t ast_write_filemark(struct ast_softc *stp, u_int8_t function) { - int32_t error; - int8_t ccb[16]; + int8_t ccb[16] = { ATAPI_TAPE_WEOF, 0, 0, 0, function, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }; if (function) { if (stp->flags & F_FM_WRITTEN) @@ -484,68 +474,38 @@ ast_write_filemark(struct ast_softc *stp, u_int8_t function) else stp->flags |= F_FM_WRITTEN; } - bzero(ccb, sizeof(ccb)); - ccb[0] = ATAPI_TAPE_WEOF; - ccb[4] = function; - - if ((error = atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL))){ - atapi_error(stp->atp, error); - return EIO; - } - return 0; + return atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0, 30, NULL, NULL, NULL); } static int32_t ast_load_unload(struct ast_softc *stp, u_int8_t function) { - int32_t error; - int8_t ccb[16]; - - bzero(ccb, sizeof(ccb)); - ccb[0] = ATAPI_TAPE_LOAD_UNLOAD; - ccb[4] = function; + int8_t ccb[16] = { ATAPI_TAPE_LOAD_UNLOAD, 0, 0, 0, function, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }; - if ((error = atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL))){ - atapi_error(stp->atp, error); - return EIO; - } - return 0; + return atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0, 30, NULL, NULL, NULL); } static int32_t ast_erase(struct ast_softc *stp) { int32_t error; - int8_t ccb[16]; + int8_t ccb[16] = { ATAPI_TAPE_ERASE, 3, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }; if ((error = ast_rewind(stp))) return error; - bzero(ccb, sizeof(ccb)); - ccb[0] = ATAPI_TAPE_ERASE; - ccb[1] = 3; - - if ((error = atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL))){ - atapi_error(stp->atp, error); - return EIO; - } - return 0; + return atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0, 60*60, NULL, NULL, NULL); } static int32_t ast_rewind(struct ast_softc *stp) { - int32_t error; - int8_t ccb[16]; - - bzero(ccb, sizeof(ccb)); - ccb[0] = ATAPI_TAPE_REWIND; + int8_t ccb[16] = { ATAPI_TAPE_REWIND, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 }; - if ((error = atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0, NULL, NULL, NULL))){ - atapi_error(stp->atp, error); - return EIO; - } - return 0; + return atapi_queue_cmd(stp->atp, ccb, NULL, 0, 0, 60*60, NULL, NULL, NULL); } static void @@ -554,6 +514,8 @@ ast_drvinit(void *unused) static int32_t ast_devsw_installed = 0; if (!ast_devsw_installed) { + if (!ast_cdevsw.d_maxio) + ast_cdevsw.d_maxio = 254 * DEV_BSIZE; cdevsw_add(&ast_cdevsw); ast_devsw_installed = 1; } diff --git a/sys/dev/ata/atapi-tape.h b/sys/dev/ata/atapi-tape.h index 7bf5c3b..666ac96 100644 --- a/sys/dev/ata/atapi-tape.h +++ b/sys/dev/ata/atapi-tape.h @@ -25,27 +25,9 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: atapi-tape.h,v 1.2 1999/03/03 21:10:29 sos Exp $ + * $Id: atapi-tape.h,v 1.3 1999/03/07 21:49:14 sos Exp $ */ -/* ATAPI tape commands not in std ATAPI command set */ -#define ATAPI_TAPE_REWIND 0x01 -#define ATAPI_TAPE_READ_CMD 0x08 -#define ATAPI_TAPE_WRITE_CMD 0x0a -#define ATAPI_TAPE_WEOF 0x10 -#define WEOF_WRITE_MASK 0x01 -#define ATAPI_TAPE_SPACE_CMD 0x11 -#define SP_FM 0x01 -#define SP_EOD 0x03 -#define ATAPI_TAPE_ERASE 0x19 -#define ATAPI_TAPE_MODE_SENSE 0x1a -#define ATAPI_TAPE_LOAD_UNLOAD 0x1b -#define LU_LOAD_MASK 0x01 -#define LU_RETENSION_MASK 0x02 -#define LU_EOT_MASK 0x04 - -#define DSC_POLL_INTERVAL 10 - /* MODE SENSE parameter header */ struct ast_header { u_int8_t data_length; /* total length of data */ |