summaryrefslogtreecommitdiffstats
path: root/sys/dev/ata
diff options
context:
space:
mode:
authorsos <sos@FreeBSD.org>2000-11-12 20:41:24 +0000
committersos <sos@FreeBSD.org>2000-11-12 20:41:24 +0000
commitc2971789cc079e18aad42dd1f7e9120dd18bc0ed (patch)
tree56290f2bc1382d58b3f31930dd6962ed69ffc697 /sys/dev/ata
parentd17388a5b237b0370d7e306255870c472cf2a4ef (diff)
downloadFreeBSD-src-c2971789cc079e18aad42dd1f7e9120dd18bc0ed.zip
FreeBSD-src-c2971789cc079e18aad42dd1f7e9120dd18bc0ed.tar.gz
Better handling of immediate commands, mainly to solve timeouts
in the atapi-tape code...
Diffstat (limited to 'sys/dev/ata')
-rw-r--r--sys/dev/ata/atapi-all.c37
-rw-r--r--sys/dev/ata/atapi-all.h1
-rw-r--r--sys/dev/ata/atapi-fd.c8
-rw-r--r--sys/dev/ata/atapi-tape.c3
4 files changed, 37 insertions, 12 deletions
diff --git a/sys/dev/ata/atapi-all.c b/sys/dev/ata/atapi-all.c
index 04c42c0..2ea1e5c 100644
--- a/sys/dev/ata/atapi-all.c
+++ b/sys/dev/ata/atapi-all.c
@@ -248,9 +248,31 @@ atapi_transfer(struct atapi_request *request)
request->device->devname, atapi_cmd2str(request->ccb[0]));
atapi_dump("ccb = ", &request->ccb[0], sizeof(request->ccb));
#endif
+ /* is this just a POLL DSC command ? */
+ if (request->ccb[0] == ATAPI_POLL_DSC) {
+ outb(atp->controller->ioaddr + ATA_DRIVE, ATA_D_IBM | atp->unit);
+ DELAY(10);
+ if (inb(atp->controller->altioaddr) & ATA_S_DSC)
+ request->error = 0;
+ else
+ request->error = EBUSY;
+ if (request->callback) {
+ if (!((request->callback)(request))) {
+ if (request->dmatab)
+ free(request->dmatab, M_DEVBUF);
+ free(request, M_ATAPI);
+ }
+ }
+ else
+ wakeup((caddr_t)request);
+ atp->controller->active = ATA_IDLE; /* should go in ata-all.c */
+ return;
+ }
+
/* start timeout for this command */
request->timeout_handle = timeout((timeout_t *)atapi_timeout,
request, request->timeout);
+
if (request->ccb[0] != ATAPI_REQUEST_SENSE)
atp->cmd = request->ccb[0];
@@ -486,13 +508,17 @@ atapi_test_ready(struct atapi_softc *atp)
int
atapi_wait_ready(struct atapi_softc *atp, int timeout)
{
- int error = 0, timout = timeout * hz;
+ int error = 0;
+ int8_t ccb[16] = { ATAPI_POLL_DSC, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- while (timout > 0) {
- if ((error = atapi_test_ready(atp)) != EBUSY)
+ timeout *= hz;
+ while (timeout > 0) {
+ error = atapi_queue_cmd(atp, ccb, NULL, 0, 0, 0, NULL, NULL);
+ if (error != EBUSY)
break;
- tsleep((caddr_t)&error, PRIBIO, "atpwt", 50);
- timout -= 50;
+ tsleep((caddr_t)&error, PRIBIO, "atpwt", hz / 2);
+ timeout -= (hz / 2);
}
return error;
}
@@ -666,6 +692,7 @@ atapi_cmd2str(u_int8_t cmd)
case 0xbb: return ("SET_SPEED");
case 0xbd: return ("MECH_STATUS");
case 0xbe: return ("READ_CD");
+ case 0xff: return ("POLL_DSC");
default: {
static char buffer[16];
sprintf(buffer, "unknown CMD (0x%02x)", cmd);
diff --git a/sys/dev/ata/atapi-all.h b/sys/dev/ata/atapi-all.h
index 72cf781..b81770f 100644
--- a/sys/dev/ata/atapi-all.h
+++ b/sys/dev/ata/atapi-all.h
@@ -116,6 +116,7 @@
#define ATAPI_SET_SPEED 0xbb /* set drive speed */
#define ATAPI_MECH_STATUS 0xbd /* get changer status */
#define ATAPI_READ_CD 0xbe /* read data */
+#define ATAPI_POLL_DSC 0xff /* poll DSC status bit */
/* ATAPI request sense structure */
struct atapi_reqsense {
diff --git a/sys/dev/ata/atapi-fd.c b/sys/dev/ata/atapi-fd.c
index 3f985ef..62f844d 100644
--- a/sys/dev/ata/atapi-fd.c
+++ b/sys/dev/ata/atapi-fd.c
@@ -412,14 +412,10 @@ afd_eject(struct afd_softc *fdp, int close)
static int
afd_start_stop(struct afd_softc *fdp, int start)
{
- int8_t ccb[16] = { ATAPI_START_STOP, 0x01, 0, 0, start,
+ int8_t ccb[16] = { ATAPI_START_STOP, 0, 0, 0, start,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- int error;
- error = atapi_queue_cmd(fdp->atp, ccb, NULL, 0, 0, 10, NULL, NULL);
- if (error)
- return error;
- return atapi_wait_ready(fdp->atp, 30);
+ return atapi_queue_cmd(fdp->atp, ccb, NULL, 0, 0, 30, NULL, NULL);
}
static int
diff --git a/sys/dev/ata/atapi-tape.c b/sys/dev/ata/atapi-tape.c
index e390b3f..ac1049c 100644
--- a/sys/dev/ata/atapi-tape.c
+++ b/sys/dev/ata/atapi-tape.c
@@ -482,7 +482,8 @@ ast_start(struct atapi_softc *atp)
devstat_start_transaction(&stp->stats);
atapi_queue_cmd(stp->atp, ccb, bp->bio_data, blkcount * stp->blksize,
- (bp->bio_cmd == BIO_READ) ? ATPR_F_READ : 0, 60, ast_done, bp);
+ (bp->bio_cmd == BIO_READ) ? ATPR_F_READ : 0,
+ 120, ast_done, bp);
}
static int
OpenPOWER on IntegriCloud