diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index d493ab672211..dae55e50a3e2 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 a63b4b32e600..15f62a6d38e6 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 cf1551e985d5..2dc99570f178 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; ctlrata_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 3da175205714..de690573bfa8 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 b1a333a278b0..a36b7cf599f8 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; ctlratapi_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 c9fb72d56b85..b01e38724ea8 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 6aa18db25020..2bdd44726498 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 c51521dea829..d938cc2ddae1 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);