aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorSøren Schmidt <sos@FreeBSD.org>1999-03-05 09:43:30 +0000
committerSøren Schmidt <sos@FreeBSD.org>1999-03-05 09:43:30 +0000
commit2e526e2ac0812995e9cdb4ee3c58ef1413b9c414 (patch)
tree9b1595f8d5888ab83bb9e9656721d93771123552 /sys
parentabd022381de2e66f8ce6765f06555136aa3b826e (diff)
Notes
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ata/ata-all.c157
-rw-r--r--sys/dev/ata/ata-all.h103
-rw-r--r--sys/dev/ata/ata-disk.c105
-rw-r--r--sys/dev/ata/ata-disk.h76
-rw-r--r--sys/dev/ata/atapi-all.c154
-rw-r--r--sys/dev/ata/atapi-cd.c12
-rw-r--r--sys/dev/ata/atapi-fd.c12
-rw-r--r--sys/dev/ata/atapi-tape.c12
8 files changed, 300 insertions, 331 deletions
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)
+int32_t
+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)
{
- 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))
+ /* 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));
- 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)
-{
- 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);
- }
+ 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);
- if (!(status & ATA_S_BSY))
- break;
- DELAY (10);
- }
- if (timeout <= 0)
- return -1;
- if (!mask)
- return (status & ATA_S_ERROR);
+ 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;
- /* 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))
- return -1;
+ case ATA_IGNORE_INTR:
+ scp->active = ATA_IGNORE_INTR;
+ outb(scp->ioaddr + ATA_CMD, command);
+ break;
- 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;
-
- 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_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; 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 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; 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 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);