diff options
author | sos <sos@FreeBSD.org> | 1999-03-05 09:43:30 +0000 |
---|---|---|
committer | sos <sos@FreeBSD.org> | 1999-03-05 09:43:30 +0000 |
commit | 84b9188bc6d2104df298fac795d1e2977c6dea6e (patch) | |
tree | b3beba461d45b95646d0e8117c5a8d4cfcd92d74 | |
parent | 801213cd08eae6e66a4b862813a82db6a997140f (diff) | |
download | FreeBSD-src-84b9188bc6d2104df298fac795d1e2977c6dea6e.zip FreeBSD-src-84b9188bc6d2104df298fac795d1e2977c6dea6e.tar.gz |
Now all actual probing of both ATA & ATAPI devices are done after
interrupts are enabled, this kills the last "unwanted interrupts"
(and there is no ugly hacks like in the old driver to avoid them).
COmmand interrupt devices are now supported, this applies mostly
to older CDROM's and apparently also the ZIP.
Fixed problems:
Number of total sectors wrong on some older drives.
Fixed by not using the LBA size unless we know its valid.
There has also been more general code clenaups, some reorgs also.
-rw-r--r-- | sys/dev/ata/ata-all.c | 159 | ||||
-rw-r--r-- | sys/dev/ata/ata-all.h | 103 | ||||
-rw-r--r-- | sys/dev/ata/ata-disk.c | 105 | ||||
-rw-r--r-- | sys/dev/ata/ata-disk.h | 76 | ||||
-rw-r--r-- | sys/dev/ata/atapi-all.c | 154 | ||||
-rw-r--r-- | sys/dev/ata/atapi-cd.c | 12 | ||||
-rw-r--r-- | sys/dev/ata/atapi-fd.c | 12 | ||||
-rw-r--r-- | sys/dev/ata/atapi-tape.c | 12 |
8 files changed, 301 insertions, 332 deletions
diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index d493ab6..dae55e5 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.1 1999/03/01 21:19:18 sos Exp $ + * $Id: ata-all.c,v 1.2 1999/03/03 21:10:29 sos Exp $ */ #include "ata.h" @@ -65,12 +65,7 @@ static void ata_pciattach(pcici_t, int32_t); static void promise_intr(int32_t); #endif static int32_t ata_probe(int32_t, int32_t, int32_t *); -static int32_t ata_attach(int32_t); static void ataintr(int32_t); -static int32_t ata_device_attach(struct ata_softc *, int32_t); -static int32_t atapi_device_attach(struct ata_softc *, int32_t); -static void bswap(int8_t *, int32_t); -static void btrim(int8_t *, int32_t); static int32_t atanlun = 0, sysctrl = 0; struct ata_softc *atadevices[MAXATA]; @@ -98,7 +93,7 @@ ata_isaprobe(struct isa_device *devp) static int32_t ata_isaattach(struct isa_device *devp) { - return ata_attach(devp->id_unit); + return 1; } #endif @@ -223,7 +218,6 @@ ata_pciattach(pcici_t tag, int32_t unit) } printf("ata%d at 0x%04x irq %d on ata-pci%d\n", lun, iobase_1, irq1, unit); - ata_attach(lun); } if (ata_probe(iobase_2, altiobase_2, &lun)) { if (iobase_2 == IO_WD2) @@ -234,7 +228,6 @@ ata_pciattach(pcici_t tag, int32_t unit) } printf("ata%d at 0x%04x irq %d on ata-pci%d\n", lun, iobase_2, irq2, unit); - ata_attach(lun); } } @@ -402,31 +395,6 @@ ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t *unit) return ATA_IOSIZE; } -static int32_t -ata_attach(int32_t unit) -{ - struct ata_softc *scp; - - if (unit > atanlun) - return 0; - - scp = atadevices[unit]; - - if (scp->devices & ATA_ATA_MASTER) - if (ata_device_attach(scp, ATA_MASTER)) - scp->devices &= ~ATA_ATA_MASTER; - if (scp->devices & ATA_ATA_SLAVE) - if (ata_device_attach(scp, ATA_SLAVE)) - scp->devices &= ~ATA_ATA_SLAVE; - if (scp->devices & ATA_ATAPI_MASTER) - if (atapi_device_attach(scp, ATA_MASTER)) - scp->devices &= ~ATA_ATAPI_MASTER; - if (scp->devices & ATA_ATAPI_SLAVE) - if (atapi_device_attach(scp, ATA_SLAVE)) - scp->devices &= ~ATA_ATAPI_SLAVE; - return scp->devices; -} - static void ataintr(int32_t unit) { @@ -459,6 +427,11 @@ ataintr(int32_t unit) atapi_interrupt(atapi_request); break; + case ATA_WAIT_INTR: + wakeup((caddr_t)scp); + scp->active = ATA_IDLE; + break; + case ATA_IGNORE_INTR: scp->active = ATA_IDLE; break; @@ -527,99 +500,45 @@ ata_wait(struct ata_softc *scp, u_int8_t mask) return -1; } -static int32_t -ata_device_attach(struct ata_softc *scp, int32_t device) -{ - struct ata_params *ata_parm; - int8_t buffer[DEV_BSIZE]; - - outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | device); - if (ata_wait(scp, 0) < 0) - return -1; - outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | device); /* XXX SOS */ - scp->active = ATA_IGNORE_INTR; - outb(scp->ioaddr + ATA_CMD, ATA_C_ATA_IDENTIFY); - if (ata_wait(scp, ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ)) - return -1; - - insw(scp->ioaddr + ATA_DATA, buffer, sizeof(buffer)/sizeof(int16_t)); - ata_parm = malloc(sizeof(struct ata_params), M_DEVBUF, M_NOWAIT); - if (!ata_parm) - return -1; - bcopy(buffer, ata_parm, sizeof(struct ata_params)); - bswap(ata_parm->model, sizeof(ata_parm->model)); - btrim(ata_parm->model, sizeof(ata_parm->model)); - bswap(ata_parm->revision, sizeof(ata_parm->revision)); - btrim(ata_parm->revision, sizeof(ata_parm->revision)); - scp->ata_parm[device == ATA_SLAVE] = ata_parm; - return 0; -} - int32_t -atapi_wait(struct ata_softc *scp, u_int8_t mask) +ata_command(struct ata_softc *scp, int32_t device, u_int32_t command, + u_int32_t cylinder, u_int32_t head, u_int32_t sector, + u_int32_t count, int32_t flags) { - u_int8_t status; - u_int32_t timeout = 0; - - while (timeout++ <= 500000) { /* timeout 5 secs */ - status = inb(scp->ioaddr + ATA_STATUS); - if ((status == 0xff) && (scp->flags & ATA_F_SLAVE_ONLY)) { - outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_SLAVE); - status = inb(scp->ioaddr + ATA_STATUS); - } - - if (!(status & ATA_S_BSY)) - break; - DELAY (10); - } - if (timeout <= 0) - return -1; - if (!mask) - return (status & ATA_S_ERROR); - - /* Wait 50 msec for bits wanted. */ - for (timeout=5000; timeout>0; --timeout) { - status = inb(scp->ioaddr + ATA_STATUS); - if ((status & mask) == mask) - return (status & ATA_S_ERROR); - DELAY (10); - } - return -1; -} - -static int32_t -atapi_device_attach(struct ata_softc *scp, int32_t device) -{ - struct atapi_params *atapi_parm; - int8_t buffer[DEV_BSIZE]; - - outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | device); - if (atapi_wait(scp, 0) < 0) - return -1; - outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | device); /* XXX SOS */ - outb(scp->ioaddr + ATA_CMD, ATA_C_ATAPI_IDENTIFY); - if (atapi_wait(scp, ATA_S_DRQ)) + /* ready to issue command ? */ + while (ata_wait(scp, 0) < 0) { + printf("ad_transfer: timeout waiting to give command"); return -1; + } - insw(scp->ioaddr + ATA_DATA, buffer, sizeof(buffer)/sizeof(int16_t)); - atapi_parm = malloc(sizeof(struct atapi_params), M_DEVBUF, M_NOWAIT); - if (!atapi_parm) - return -1; + outb(scp->ioaddr + ATA_PRECOMP, 0); /* no precompensation */ + outb(scp->ioaddr + ATA_CYL_LSB, cylinder); + outb(scp->ioaddr + ATA_CYL_MSB, cylinder >> 8); + outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | device | head); + outb(scp->ioaddr + ATA_SECTOR, sector); + outb(scp->ioaddr + ATA_COUNT, count); + + switch (flags) { + case ATA_WAIT_INTR: + scp->active = ATA_WAIT_INTR; + outb(scp->ioaddr + ATA_CMD, command); + tsleep((caddr_t)scp, PRIBIO, "atacmd", 0); + break; - bcopy(buffer, atapi_parm, sizeof(struct atapi_params)); - if (!((atapi_parm->model[0] == 'N' && atapi_parm->model[1] == 'E') || - (atapi_parm->model[0] == 'F' && atapi_parm->model[1] == 'X'))) - bswap(atapi_parm->model, sizeof(atapi_parm->model)); - btrim(atapi_parm->model, sizeof(atapi_parm->model)); - bswap(atapi_parm->revision, sizeof(atapi_parm->revision)); - btrim(atapi_parm->revision, sizeof(atapi_parm->revision)); - bswap(atapi_parm->serial, sizeof(atapi_parm->serial)); /* unused SOS */ - btrim(atapi_parm->serial, sizeof(atapi_parm->serial)); /* unused SOS */ - scp->atapi_parm[device == ATA_SLAVE] = atapi_parm; + case ATA_IGNORE_INTR: + scp->active = ATA_IGNORE_INTR; + outb(scp->ioaddr + ATA_CMD, command); + break; + + case ATA_IMMEDIATE: + default: + outb(scp->ioaddr + ATA_CMD, command); + break; + } return 0; } -static void +void bswap(int8_t *buf, int32_t len) { u_int16_t *p = (u_int16_t*)(buf + len); @@ -628,7 +547,7 @@ bswap(int8_t *buf, int32_t len) *p = ntohs(*p); } -static void +void btrim(int8_t *buf, int32_t len) { int8_t *p; diff --git a/sys/dev/ata/ata-all.h b/sys/dev/ata/ata-all.h index a63b4b32..15f62a6 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.1 1999/03/01 21:19:18 sos Exp $ + * $Id: ata-all.h,v 1.2 1999/03/03 21:10:29 sos Exp $ */ /* ATA register defines */ @@ -79,79 +79,6 @@ #define ATA_ATAPI_MASTER 0x04 #define ATA_ATAPI_SLAVE 0x08 -struct ata_params { - int16_t config; /* general configuration bits */ - u_int16_t cylinders; /* number of cylinders */ - int16_t reserved2; - u_int16_t heads; /* # heads */ - int16_t unfbytespertrk; /* # unformatted bytes/track */ - int16_t unfbytes; /* # unformatted bytes/sector */ - u_int16_t sectors; /* # sectors/track */ - int16_t vendorunique[3]; - int8_t serial[20]; /* serial number */ - int16_t buffertype; /* buffer type */ -#define ATA_BT_SINGLEPORTSECTOR 1 /* 1 port, 1 sector buffer */ -#define ATA_BT_DUALPORTMULTI 2 /* 2 port, mult sector buffer */ -#define ATA_BT_DUALPORTMULTICACHE 3 /* above plus track cache */ - - int16_t buffersize; /* buf size, 512-byte units */ - int16_t necc; /* ecc bytes appended */ - int8_t revision[8]; /* firmware revision */ - int8_t model[40]; /* model name */ - int8_t nsecperint; /* sectors per interrupt */ - int8_t vendorunique1; - int16_t usedmovsd; /* double word read/write? */ - int8_t vendorunique2; - int8_t capability; /* various capability bits */ - int16_t cap_validate; /* validation for above */ - int8_t vendorunique3; - int8_t opiomode; /* PIO modes 0-2 */ - int8_t vendorunique4; - int8_t odmamode; /* old DMA modes, not ATA-3 */ - int16_t atavalid; /* fields valid */ - int16_t currcyls; - int16_t currheads; - int16_t currsectors; - int16_t currsize0; - int16_t currsize1; - int8_t currmultsect; - int8_t multsectvalid; - int lbasize; - int16_t dmasword; /* obsolete in ATA-3 */ - int16_t dmamword; /* multiword DMA modes */ - int16_t eidepiomodes; /* advanced PIO modes */ - int16_t eidedmamin; /* fastest DMA timing */ - int16_t eidedmanorm; /* recommended DMA timing */ - int16_t eidepioblind; /* fastest possible blind PIO */ - int16_t eidepioacked; /* fastest possible IORDY PIO */ - int16_t reserved69; - int16_t reserved70; - int16_t reserved71; - int16_t reserved72; - int16_t reserved73; - int16_t reserved74; - int16_t queuelen; - int16_t reserved76; - int16_t reserved77; - int16_t reserved78; - int16_t reserved79; - int16_t versmajor; - int16_t versminor; - int16_t featsupp1; - int16_t featsupp2; - int16_t featsupp3; - int16_t featenab1; - int16_t featenab2; - int16_t featenab3; - int16_t udmamode; /* UltraDMA modes */ - int16_t erasetime; - int16_t enherasetime; - int16_t apmlevel; - int16_t reserved92[34]; - int16_t rmvcap; - int16_t securelevel; -}; - /* Structure describing an ATA device */ struct ata_softc { u_int32_t unit; /* this instance's number */ @@ -164,30 +91,16 @@ struct ata_softc { int32_t devices; /* what is present */ u_int8_t status; /* last controller status */ u_int8_t error; /* last controller error */ - int32_t active; /* active processing request */ #define ATA_IDLE 0x0 -#define ATA_ACTIVE_ATA 0x1 -#define ATA_ACTIVE_ATAPI 0x2 -#define ATA_IGNORE_INTR 0x3 +#define ATA_IMMEDIATE 0x0 +#define ATA_WAIT_INTR 0x1 +#define ATA_IGNORE_INTR 0x2 +#define ATA_ACTIVE_ATA 0x3 +#define ATA_ACTIVE_ATAPI 0x4 struct buf_queue_head ata_queue; /* head of ATA queue */ - struct ata_params *ata_parm[2]; /* ata device params */ TAILQ_HEAD(, atapi_request) atapi_queue; /* head of ATAPI queue */ - struct atapi_params *atapi_parm[2]; /* atapi device params */ -}; - -struct ata_request { - struct ad_softc *driver; /* ptr to parent device */ - /*bla request bla*/ - u_int32_t flags; /* drive flags */ -#define A_READ 0x0001 - - u_int32_t bytecount; /* bytes to transfer */ - u_int32_t donecount; /* bytes transferred */ - u_int32_t currentsize; /* size of current transfer */ - struct buf *bp; /* associated buf ptr */ - TAILQ_ENTRY(ata_request) chain; /* list management */ }; #define MAXATA 8 @@ -197,6 +110,8 @@ extern struct ata_softc *atadevices[]; /* public prototypes */ void ata_start(struct ata_softc *); int32_t ata_wait(struct ata_softc *, u_int8_t); -int32_t atapi_wait(struct ata_softc *, u_int8_t); +int32_t ata_command(struct ata_softc *, int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, int32_t); +void bswap(int8_t *, int32_t); +void btrim(int8_t *, int32_t); void bpack(int8_t *, int8_t *, int32_t); diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c index cf1551e..2dc9957 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.1 1999/03/01 21:19:18 sos Exp $ + * $Id: ata-disk.c,v 1.2 1999/03/03 21:10:29 sos Exp $ */ #include "ata.h" @@ -80,10 +80,10 @@ static struct cdevsw ad_cdevsw = { /* prototypes */ static void ad_attach(void *); +static int32_t ata_get_param(struct ad_softc *); static void ad_strategy(struct buf *); static void ad_start(struct ad_softc *); static void ad_sleep(struct ad_softc *, int8_t *); -static int32_t ad_command(struct ad_softc *, u_int32_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t); static int8_t ad_version(u_int16_t); static void ad_drvinit(void); @@ -102,34 +102,42 @@ ad_attach(void *notused) /* now, run through atadevices and look for ATA disks */ for (ctlr=0; ctlr<MAXATA && atadevices[ctlr]; ctlr++) { for (dev=0; dev<2; dev++) { - if (atadevices[ctlr]->ata_parm[dev]) { + if (atadevices[ctlr]->devices & + (dev ? ATA_ATA_SLAVE : ATA_ATA_MASTER)) { #ifdef ATA_STATIC_ID adnlun = dev + ctlr * 2; #endif adp = adtab[adnlun]; if (adp) printf("ad%d: unit already attached\n", adnlun); - adp = malloc(sizeof(struct ad_softc), M_DEVBUF, M_NOWAIT); - if (adp == NULL) + if (!(adp = malloc(sizeof(struct ad_softc), + M_DEVBUF, M_NOWAIT))) { printf("ad%d: failed to allocate driver storage\n", adnlun); + continue; + } bzero(adp, sizeof(struct ad_softc)); adp->controller = atadevices[ctlr]; - adp->ata_parm = atadevices[ctlr]->ata_parm[dev]; adp->unit = (dev == 0) ? ATA_MASTER : ATA_SLAVE; adp->lun = adnlun; + if (ata_get_param(adp)) { + free(adp, M_DEVBUF); + continue; + } adp->cylinders = adp->ata_parm->cylinders; adp->heads = adp->ata_parm->heads; adp->sectors = adp->ata_parm->sectors; - adp->total_secs = adp->ata_parm->lbasize; - if (!adp->total_secs) - adp->total_secs = adp->cylinders*adp->heads*adp->sectors; - if (adp->cylinders == 16383) + adp->total_secs = adp->cylinders * adp->heads * adp->sectors; + if (adp->cylinders == 16383 && + adp->total_secs < adp->ata_parm->lbasize) { + adp->total_secs = adp->ata_parm->lbasize; adp->cylinders = adp->total_secs/(adp->heads*adp->sectors); + } /* support multiple sectors / interrupt ? */ adp->transfersize = DEV_BSIZE; secsperint = min(adp->ata_parm->nsecperint, 16); - if (!ad_command(adp, ATA_C_SET_MULTI, 0, 0, 0, secsperint) && + if (!ata_command(adp->controller, adp->unit, ATA_C_SET_MULTI, + 0, 0, 0, secsperint, ATA_WAIT_INTR) && ata_wait(adp->controller, ATA_S_DRDY) >= 0) adp->transfersize *= secsperint; @@ -179,6 +187,30 @@ ad_attach(void *notused) } static int32_t +ata_get_param(struct ad_softc *adp) +{ + struct ata_params *ata_parm; + int8_t buffer[DEV_BSIZE]; + + ata_command(adp->controller, adp->unit, ATA_C_ATA_IDENTIFY, + 0, 0, 0, 0, ATA_WAIT_INTR); + if (ata_wait(adp->controller, ATA_S_DRDY | ATA_S_DSC | ATA_S_DRQ)) + return -1; + insw(adp->controller->ioaddr + ATA_DATA, buffer, + sizeof(buffer)/sizeof(int16_t)); + ata_parm = malloc(sizeof(struct ata_params), M_DEVBUF, M_NOWAIT); + if (!ata_parm) + return -1; + bcopy(buffer, ata_parm, sizeof(struct ata_params)); + bswap(ata_parm->model, sizeof(ata_parm->model)); + btrim(ata_parm->model, sizeof(ata_parm->model)); + bswap(ata_parm->revision, sizeof(ata_parm->revision)); + btrim(ata_parm->revision, sizeof(ata_parm->revision)); + adp->ata_parm = ata_parm; + return 0; +} + +static int adopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) { int32_t lun = UNIT(dev); @@ -216,7 +248,7 @@ printf("adopen: lun=%d adnlun=%d\n", lun, adnlun); return error; } -static int32_t +static int adclose(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) { int32_t lun = UNIT(dev); @@ -232,19 +264,19 @@ printf("adclose: lun=%d adnlun=%d\n", lun, adnlun); return 0; } -static int32_t +static int adread(dev_t dev, struct uio *uio, int32_t ioflag) { return physio(adstrategy, NULL, dev, 1, minphys, uio); } -static int32_t +static int adwrite(dev_t dev, struct uio *uio, int32_t ioflag) { return physio(adstrategy, NULL, dev, 0, minphys, uio); } -static int32_t +static int adioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flags, struct proc *p) { struct ad_softc *adp; @@ -308,7 +340,7 @@ done: splx(s); } -static int32_t +static int adpsize(dev_t dev) { struct ad_softc *adp; @@ -393,17 +425,8 @@ ad_transfer(struct buf *bp) /*ata_unwedge(adp->controller); SOS */ } - outb(adp->controller->ioaddr + ATA_DRIVE, ATA_D_IBM | adp->unit | head); - outb(adp->controller->ioaddr + ATA_PRECOMP, 0); /* no precompensation */ - outb(adp->controller->ioaddr + ATA_CYL_LSB, cylinder); - outb(adp->controller->ioaddr + ATA_CYL_MSB, cylinder >> 8); - outb(adp->controller->ioaddr + ATA_SECTOR, sector + 1); - outb(adp->controller->ioaddr + ATA_COUNT, count); -/* - if (ata_wait(adp->controller, ATA_S_DRDY) < 0) - printf("ad_transfer: timeout waiting to send command"); -*/ - outb(adp->controller->ioaddr + ATA_CMD, command); + ata_command(adp->controller, adp->unit, command, cylinder, head, + sector + 1, count, ATA_IMMEDIATE); } /* if this is a read operation, return and wait for interrupt */ @@ -533,34 +556,6 @@ ad_sleep(struct ad_softc *adp, int8_t *mesg) splx(s); } -static int32_t -ad_command(struct ad_softc *adp, u_int32_t command, - u_int32_t cylinder, u_int32_t head, u_int32_t sector, - u_int32_t count) -{ - /* ready to issue command ? */ - while (ata_wait(adp->controller, 0) < 0) { - printf("ad_transfer: timeout waiting to give command"); - return -1; - } - - outb(adp->controller->ioaddr + ATA_DRIVE, ATA_D_IBM | adp->unit | head); - outb(adp->controller->ioaddr + ATA_PRECOMP, 0); /* no precompensation */ - outb(adp->controller->ioaddr + ATA_CYL_LSB, cylinder); - outb(adp->controller->ioaddr + ATA_CYL_MSB, cylinder >> 8); - outb(adp->controller->ioaddr + ATA_SECTOR, sector + 1); - outb(adp->controller->ioaddr + ATA_COUNT, count); -/* - if (ata_wait(adp->controller, ATA_S_DRDY) < 0) { - printf("ad_transfer: timeout waiting to send command"); - return -1; - } -*/ - adp->controller->active = ATA_IGNORE_INTR; - outb(adp->controller->ioaddr + ATA_CMD, command); - return 0; -} - static int8_t ad_version(u_int16_t version) { diff --git a/sys/dev/ata/ata-disk.h b/sys/dev/ata/ata-disk.h index 3da1752..de69057 100644 --- a/sys/dev/ata/ata-disk.h +++ b/sys/dev/ata/ata-disk.h @@ -25,9 +25,83 @@ * (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.1 1999/03/01 21:19:18 sos Exp $ + * $Id: ata-disk.h,v 1.2 1999/03/03 21:10:29 sos Exp $ */ +/* ATA device parameter information */ +struct ata_params { + int16_t config; /* general configuration bits */ + u_int16_t cylinders; /* number of cylinders */ + int16_t reserved2; + u_int16_t heads; /* # heads */ + int16_t unfbytespertrk; /* # unformatted bytes/track */ + int16_t unfbytes; /* # unformatted bytes/sector */ + u_int16_t sectors; /* # sectors/track */ + int16_t vendorunique[3]; + int8_t serial[20]; /* serial number */ + int16_t buffertype; /* buffer type */ +#define ATA_BT_SINGLEPORTSECTOR 1 /* 1 port, 1 sector buffer */ +#define ATA_BT_DUALPORTMULTI 2 /* 2 port, mult sector buffer */ +#define ATA_BT_DUALPORTMULTICACHE 3 /* above plus track cache */ + + int16_t buffersize; /* buf size, 512-byte units */ + int16_t necc; /* ecc bytes appended */ + int8_t revision[8]; /* firmware revision */ + int8_t model[40]; /* model name */ + int8_t nsecperint; /* sectors per interrupt */ + int8_t vendorunique1; + int16_t usedmovsd; /* double word read/write? */ + int8_t vendorunique2; + int8_t capability; /* various capability bits */ + int16_t cap_validate; /* validation for above */ + int8_t vendorunique3; + int8_t opiomode; /* PIO modes 0-2 */ + int8_t vendorunique4; + int8_t odmamode; /* old DMA modes, not ATA-3 */ + int16_t atavalid; /* fields valid */ + int16_t currcyls; + int16_t currheads; + int16_t currsectors; + int16_t currsize0; + int16_t currsize1; + int8_t currmultsect; + int8_t multsectvalid; + int32_t lbasize; + int16_t dmasword; /* obsolete in ATA-3 */ + int16_t dmamword; /* multiword DMA modes */ + int16_t eidepiomodes; /* advanced PIO modes */ + int16_t eidedmamin; /* fastest DMA timing */ + int16_t eidedmanorm; /* recommended DMA timing */ + int16_t eidepioblind; /* fastest possible blind PIO */ + int16_t eidepioacked; /* fastest possible IORDY PIO */ + int16_t reserved69; + int16_t reserved70; + int16_t reserved71; + int16_t reserved72; + int16_t reserved73; + int16_t reserved74; + int16_t queuelen; + int16_t reserved76; + int16_t reserved77; + int16_t reserved78; + int16_t reserved79; + int16_t versmajor; + int16_t versminor; + int16_t featsupp1; + int16_t featsupp2; + int16_t featsupp3; + int16_t featenab1; + int16_t featenab2; + int16_t featenab3; + int16_t udmamode; /* UltraDMA modes */ + int16_t erasetime; + int16_t enherasetime; + int16_t apmlevel; + int16_t reserved92[34]; + int16_t rmvcap; + int16_t securelevel; +}; + /* Structure describing an ATA disk */ struct ad_softc { struct ata_softc *controller; /* ptr to parent ctrl */ diff --git a/sys/dev/ata/atapi-all.c b/sys/dev/ata/atapi-all.c index b1a333a..a36b7cf 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.1 1999/03/01 21:19:18 sos Exp $ + * $Id: atapi-all.c,v 1.2 1999/03/03 21:10:29 sos Exp $ */ #include "ata.h" @@ -49,8 +49,12 @@ /* prototypes */ static void atapi_attach(void *); +static int32_t atapi_get_param(struct atapi_softc *); static int8_t *atapi_type(int32_t); +#ifdef ATAPI_DEBUG static int8_t *atapi_cmd2str(u_int8_t); +#endif +int32_t atapi_wait(struct ata_softc *, u_int8_t); static void atapi_init(void); /* extern references */ @@ -63,6 +67,7 @@ static struct intr_config_hook *atapi_attach_hook; static void atapi_attach(void *notused) { + struct atapi_softc *atp; int32_t ctlr, dev; int8_t model_buf[40+1]; int8_t revision_buf[8+1]; @@ -70,18 +75,21 @@ atapi_attach(void *notused) /* now, run through atadevices and look for ATAPI devices */ for (ctlr=0; ctlr<MAXATA && atadevices[ctlr]; ctlr++) { for (dev=0; dev<2; dev++) { - struct ata_softc *scp = atadevices[ctlr]; - - if (scp->atapi_parm[dev]) { - struct atapi_softc *atp; - - atp = malloc(sizeof(struct atapi_softc), M_DEVBUF, M_NOWAIT); + if (atadevices[ctlr]->devices & + (dev ? ATA_ATAPI_SLAVE : ATA_ATAPI_MASTER)) { + if (!(atp = malloc(sizeof(struct atapi_softc), + M_DEVBUF, M_NOWAIT))) { + printf("atapi: failed to allocate driver storage\n"); + continue; + } bzero(atp, sizeof(struct atapi_softc)); - atp->controller = scp; - atp->atapi_parm = scp->atapi_parm[dev]; + atp->controller = atadevices[ctlr]; atp->unit = (dev) ? ATA_SLAVE : ATA_MASTER; - - switch (scp->atapi_parm[dev]->device_type) { + if (atapi_get_param(atp)) { + free(atp, M_DEVBUF); + continue; + } + switch (atp->atapi_parm->device_type) { #if NATAPICD > 0 case ATAPI_TYPE_CDROM: if (acdattach(atp)) @@ -103,14 +111,13 @@ atapi_attach(void *notused) notfound: default: free(atp, M_DEVBUF); - bpack(scp->atapi_parm[dev]->model, model_buf, - sizeof(model_buf)); - bpack(scp->atapi_parm[dev]->revision, revision_buf, + bpack(atp->atapi_parm->model, model_buf, sizeof(model_buf)); + bpack(atp->atapi_parm->revision, revision_buf, sizeof(revision_buf)); printf("atapi: <%s/%s> %s device at ata%d as %s " "- NO DRIVER!\n", model_buf, revision_buf, - atapi_type(scp->atapi_parm[dev]->device_type), + atapi_type(atp->atapi_parm->device_type), ctlr, (dev) ? "slave" : "master "); } @@ -120,6 +127,34 @@ notfound: config_intrhook_disestablish(atapi_attach_hook); } +static int32_t +atapi_get_param(struct atapi_softc *atp) +{ + struct atapi_params *atapi_parm; + int8_t buffer[DEV_BSIZE]; + + ata_command(atp->controller, atp->unit, ATA_C_ATAPI_IDENTIFY, + 0, 0, 0, 0, ATA_WAIT_INTR); + if (atapi_wait(atp->controller, ATA_S_DRQ)) + return -1; + insw(atp->controller->ioaddr + ATA_DATA, buffer, + sizeof(buffer)/sizeof(int16_t)); + if (!(atapi_parm = malloc(sizeof(struct atapi_params), M_DEVBUF, M_NOWAIT))) + return -1; + bcopy(buffer, atapi_parm, sizeof(struct atapi_params)); + if (!((atapi_parm->model[0] == 'N' && atapi_parm->model[1] == 'E') || + (atapi_parm->model[0] == 'F' && atapi_parm->model[1] == 'X'))) + bswap(atapi_parm->model, sizeof(atapi_parm->model)); + btrim(atapi_parm->model, sizeof(atapi_parm->model)); + bswap(atapi_parm->revision, sizeof(atapi_parm->revision)); + btrim(atapi_parm->revision, sizeof(atapi_parm->revision)); + bswap(atapi_parm->serial, sizeof(atapi_parm->serial)); /* unused SOS */ + btrim(atapi_parm->serial, sizeof(atapi_parm->serial)); /* unused SOS */ + atp->atapi_parm = atapi_parm; + return 0; +} + + int32_t atapi_queue_cmd(struct atapi_softc *atp, int8_t *ccb, void *data, int32_t count, int32_t flags, @@ -127,12 +162,11 @@ atapi_queue_cmd(struct atapi_softc *atp, int8_t *ccb, void *data, { struct atapi_request *request; int32_t error = 0; - int32_t s = splbio(); + int32_t x; - if (!(request = malloc(sizeof(struct atapi_request), M_DEVBUF, M_NOWAIT))) { - splx(s); + if (!(request = malloc(sizeof(struct atapi_request), M_DEVBUF, M_NOWAIT))) return -1; - } + x = splbio(); bzero(request, sizeof(struct atapi_request)); request->device = atp; request->data = data; @@ -149,22 +183,24 @@ atapi_queue_cmd(struct atapi_softc *atp, int8_t *ccb, void *data, /* link onto controller queue */ TAILQ_INSERT_TAIL(&atp->controller->atapi_queue, request, chain); #ifdef ATAPI_DEBUG - printf("atapi: trying to start %s command\n", atapi_cmd2str(ccb[0])); + printf("atapi: queued %s cmd\n", atapi_cmd2str(ccb[0])); #endif + /* try to start controller */ if (!atp->controller->active) ata_start(atp->controller); - if (!callback) { /* wait for command to complete */ - tsleep((caddr_t)request, PRIBIO, "atprq", 0); + if (tsleep((caddr_t)request, PRIBIO, "atprq", 100)) + error = 0xf0; + else + error = request->result; #ifdef ATAPI_DEBUG printf("atapi: phew, got back from tsleep\n"); #endif - error = request->result; free(request, M_DEVBUF); } - splx(s); + splx(x); return error; } @@ -178,21 +214,17 @@ atapi_transfer(struct atapi_request *request) /* get device params */ atp = request->device; +#ifdef ATAPI_DEBUG + printf("atapi: trying to start %s cmd\n", atapi_cmd2str(request->ccb[0])); +#endif + /* start ATAPI operation */ - outb(atp->controller->ioaddr + ATA_DRIVE, ATA_D_IBM | atp->unit); - if (atapi_wait(atp->controller, 0) < 0) { - printf ("atapi_transfer: timeout waiting to send PACKET command\n"); - /* now what ? SOS */ - } - outb(atp->controller->ioaddr + ATA_PRECOMP, 0); - outb(atp->controller->ioaddr + ATA_COUNT, 0); - outb(atp->controller->ioaddr + ATA_SECTOR, 0); - outb(atp->controller->ioaddr + ATA_CYL_LSB, request->bytecount); - outb(atp->controller->ioaddr + ATA_CYL_MSB, request->bytecount >> 8); - outb(atp->controller->ioaddr + ATA_CMD, ATA_C_PACKET_CMD); - - /* wait for interrupt ?? not supported yet. */ - /* just return then and let atapi_interrupt handle it */ + ata_command(atp->controller, atp->unit, ATA_C_PACKET_CMD, + request->bytecount, 0, 0, 0, ATA_IMMEDIATE); + + /* command interrupt device ? just return */ + if (atp->atapi_parm->drqtype == ATAPI_DRQT_INTR) + return; /* ready to write ATAPI command */ timeout = 5000; /* might be less for fast devices */ @@ -210,6 +242,9 @@ atapi_transfer(struct atapi_request *request) /* now what ?? SOS atapi-done & again */ } + /* this seems to be needed for some (slow) devices */ + DELAY(10); + /* send actual command */ outsw(atp->controller->ioaddr + ATA_DATA, request->ccb, request->ccbsize / sizeof(int16_t)); @@ -248,15 +283,12 @@ printf("atapi_interrupt: length=%d reason=0x%02x\n", length, reason); switch (reason) { case ATAPI_P_CMDOUT: - printf("atapi_interrupt: command interrupt, not supported yet\n"); -#if notyet - /* send actual command */ - if (!(atp->status & ATA_S_DRQ)) + /* send ATAPI command */ + if (!(atp->controller->status & ATA_S_DRQ)) printf("atapi_interrupt: command interrupt, but no DRQ\n"); else outsw(atp->controller->ioaddr + ATA_DATA, request->ccb, - request->ccdsize / sizeof(int16_t)); -#endif + request->ccbsize / sizeof(int16_t)); return; case ATAPI_P_WRITE: @@ -371,6 +403,7 @@ atapi_type(int32_t type) } } +#ifdef ATAPI_DEBUG static int8_t * atapi_cmd2str(u_int8_t cmd) { @@ -414,6 +447,39 @@ atapi_cmd2str(u_int8_t cmd) } } } +#endif + +int32_t +atapi_wait(struct ata_softc *scp, u_int8_t mask) +{ + u_int8_t status; + u_int32_t timeout = 0; + + while (timeout++ <= 500000) { /* timeout 5 secs */ + status = inb(scp->ioaddr + ATA_STATUS); + if ((status == 0xff) && (scp->flags & ATA_F_SLAVE_ONLY)) { + outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_SLAVE); + status = inb(scp->ioaddr + ATA_STATUS); + } + + if (!(status & ATA_S_BSY)) + break; + DELAY (10); + } + if (timeout <= 0) + return -1; + if (!mask) + return (status & ATA_S_ERROR); + + /* Wait 50 msec for bits wanted. */ + for (timeout=5000; timeout>0; --timeout) { + status = inb(scp->ioaddr + ATA_STATUS); + if ((status & mask) == mask) + return (status & ATA_S_ERROR); + DELAY (10); + } + return -1; +} static void atapi_init(void) diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c index c9fb72d..b01e387 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.1 1999/03/01 21:19:18 sos Exp $ + * $Id: atapi-cd.c,v 1.2 1999/03/03 21:10:29 sos Exp $ */ #include "ata.h" @@ -395,7 +395,7 @@ msf2lba(u_int8_t m, u_int8_t s, u_int8_t f) return (m * 60 + s) * 75 + f - 150; } -static int32_t +static int acdopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) { int32_t lun = dkunit(dev); @@ -431,7 +431,7 @@ acdopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) return 0; } -static int32_t +static int acdclose(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) { int32_t lun = dkunit(dev); @@ -460,19 +460,19 @@ acdclose(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) return 0; } -static int32_t +static int acdread(dev_t dev, struct uio *uio, int32_t ioflag) { return physio(acdstrategy, NULL, dev, 1, minphys, uio); } -static int32_t +static int acdwrite(dev_t dev, struct uio *uio, int32_t ioflag) { return physio(acdstrategy, NULL, dev, 0, minphys, uio); } -static int32_t +static int acdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) { int32_t lun = dkunit(dev); diff --git a/sys/dev/ata/atapi-fd.c b/sys/dev/ata/atapi-fd.c index 6aa18db..2bdd447 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$ + * $Id: atapi-fd.c,v 1.1 1999/03/03 21:10:29 sos Exp $ */ #include "ata.h" @@ -191,7 +191,7 @@ afd_describe(struct afd_softc *fdp) printf("\n"); } -static int32_t +static int afdopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) { struct afd_softc *fdp; @@ -220,7 +220,7 @@ afdopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) (ds_setgeom_t *)NULL, &afd_cdevsw); } -static int32_t +static int afdclose(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) { int32_t lun = UNIT(dev); @@ -235,19 +235,19 @@ afdclose(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) return 0; } -static int32_t +static int afdread(dev_t dev, struct uio *uio, int32_t ioflag) { return physio(afdstrategy, NULL, dev, 1, minphys, uio); } -static int32_t +static int afdwrite(dev_t dev, struct uio *uio, int32_t ioflag) { return physio(afdstrategy, NULL, dev, 0, minphys, uio); } -static int32_t +static int afdioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) { int32_t lun = UNIT(dev); diff --git a/sys/dev/ata/atapi-tape.c b/sys/dev/ata/atapi-tape.c index c51521d..d938cc2 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.1 1999/03/01 21:19:18 sos Exp $ + * $Id: atapi-tape.c,v 1.2 1999/03/03 21:10:29 sos Exp $ */ #include "ata.h" @@ -209,7 +209,7 @@ ast_describe(struct ast_softc *stp) printf("\n"); } -static int32_t +static int astopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) { int32_t lun = UNIT(dev); @@ -228,7 +228,7 @@ astopen(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) return 0; } -static int32_t +static int astclose(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) { int32_t lun = UNIT(dev); @@ -257,19 +257,19 @@ astclose(dev_t dev, int32_t flags, int32_t fmt, struct proc *p) return 0; } -static int32_t +static int astread(dev_t dev, struct uio *uio, int32_t ioflag) { return physio(aststrategy, NULL, dev, 1, minphys, uio); } -static int32_t +static int astwrite(dev_t dev, struct uio *uio, int32_t ioflag) { return physio(aststrategy, NULL, dev, 0, minphys, uio); } -static int32_t +static int astioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p) { int32_t lun = UNIT(dev); |