summaryrefslogtreecommitdiff
path: root/sys/dev/ata/atascsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ata/atascsi.c')
-rw-r--r--sys/dev/ata/atascsi.c240
1 files changed, 139 insertions, 101 deletions
diff --git a/sys/dev/ata/atascsi.c b/sys/dev/ata/atascsi.c
index 099d1c90df6..13a97ed252d 100644
--- a/sys/dev/ata/atascsi.c
+++ b/sys/dev/ata/atascsi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: atascsi.c,v 1.66 2009/10/22 07:59:26 dlg Exp $ */
+/* $OpenBSD: atascsi.c,v 1.67 2009/12/07 09:37:34 dlg Exp $ */
/*
* Copyright (c) 2007 David Gwynne <dlg@openbsd.org>
@@ -68,28 +68,31 @@ struct scsi_device atascsi_device = {
void ata_fix_identify(struct ata_identify *);
-int atascsi_disk_cmd(struct scsi_xfer *);
+void atascsi_disk_cmd(struct scsi_xfer *);
void atascsi_disk_cmd_done(struct ata_xfer *);
-int atascsi_disk_inq(struct scsi_xfer *);
-int atascsi_disk_inquiry(struct scsi_xfer *);
-int atascsi_disk_vpd_supported(struct scsi_xfer *);
-int atascsi_disk_vpd_serial(struct scsi_xfer *);
-int atascsi_disk_vpd_ident(struct scsi_xfer *);
-int atascsi_disk_capacity(struct scsi_xfer *);
-int atascsi_disk_sync(struct scsi_xfer *);
+void atascsi_disk_inq(struct scsi_xfer *);
+void atascsi_disk_inquiry(struct scsi_xfer *);
+void atascsi_disk_vpd_supported(struct scsi_xfer *);
+void atascsi_disk_vpd_serial(struct scsi_xfer *);
+void atascsi_disk_vpd_ident(struct scsi_xfer *);
+void atascsi_disk_capacity(struct scsi_xfer *);
+void atascsi_disk_sync(struct scsi_xfer *);
void atascsi_disk_sync_done(struct ata_xfer *);
-int atascsi_disk_sense(struct scsi_xfer *);
+void atascsi_disk_sense(struct scsi_xfer *);
-int atascsi_atapi_cmd(struct scsi_xfer *);
+void atascsi_atapi_cmd(struct scsi_xfer *);
void atascsi_atapi_cmd_done(struct ata_xfer *);
-int atascsi_done(struct scsi_xfer *, int);
+void atascsi_done(struct scsi_xfer *, int);
-int ata_exec(struct atascsi *, struct ata_xfer *);
+void ata_exec(struct atascsi *, struct ata_xfer *);
struct ata_xfer *ata_get_xfer(struct ata_port *);
void ata_put_xfer(struct ata_xfer *);
+void ata_polled_complete(struct ata_xfer *);
+int ata_polled(struct ata_xfer *);
+
struct atascsi *
atascsi_attach(struct device *self, struct atascsi_attach_args *aaa)
{
@@ -204,12 +207,11 @@ atascsi_probe(struct scsi_link *link)
xa->fis->command = ATA_C_IDENTIFY;
xa->fis->device = 0;
xa->flags = ATA_F_READ | ATA_F_PIO | ATA_F_POLL;
- xa->complete = ata_put_xfer;
xa->timeout = 1000;
- if (ata_exec(as, xa) != COMPLETE) {
- rv = EIO;
+ xa->complete = ata_polled_complete;
+ rv = ata_polled(xa);
+ if (rv != 0)
goto error;
- }
ata_fix_identify(&ap->ap_identify);
@@ -227,9 +229,9 @@ atascsi_probe(struct scsi_link *link)
xa->fis->features = ATA_SF_WRITECACHE_EN;
xa->fis->flags = ATA_H2D_FLAGS_CMD;
xa->flags = ATA_F_READ | ATA_F_PIO | ATA_F_POLL;
- xa->complete = ata_put_xfer;
xa->timeout = 1000;
- ata_exec(as, xa); /* we dont care if this works or not */
+ xa->complete = ata_polled_complete;
+ ata_polled(xa); /* we dont care if it doesnt work */
}
/* Enable read lookahead if supported */
@@ -241,9 +243,9 @@ atascsi_probe(struct scsi_link *link)
xa->fis->features = ATA_SF_LOOKAHEAD_EN;
xa->fis->flags = ATA_H2D_FLAGS_CMD;
xa->flags = ATA_F_READ | ATA_F_PIO | ATA_F_POLL;
- xa->complete = ata_put_xfer;
xa->timeout = 1000;
- ata_exec(as, xa); /* we dont care if this works or not */
+ xa->complete = ata_polled_complete;
+ ata_polled(xa); /* we dont care if it doesnt work */
}
/*
@@ -259,9 +261,9 @@ atascsi_probe(struct scsi_link *link)
xa->fis->command = ATA_C_SEC_FREEZE_LOCK;
xa->fis->flags = ATA_H2D_FLAGS_CMD;
xa->flags = ATA_F_READ | ATA_F_PIO | ATA_F_POLL;
- xa->complete = ata_put_xfer;
xa->timeout = 1000;
- ata_exec(as, xa); /* we dont care if this works or not */
+ xa->complete = ata_polled_complete;
+ ata_polled(xa); /* we dont care if it doesnt work */
return (0);
error:
@@ -321,22 +323,29 @@ atascsi_cmd(struct scsi_xfer *xs)
struct atascsi *as = link->adapter_softc;
struct ata_port *ap = as->as_ports[link->target];
- if (ap == NULL)
- return (atascsi_done(xs, XS_DRIVER_STUFFUP));
+ if (ap == NULL) {
+ atascsi_done(xs, XS_DRIVER_STUFFUP);
+ return (COMPLETE);
+ }
switch (ap->ap_type) {
case ATA_PORT_T_DISK:
- return (atascsi_disk_cmd(xs));
+ atascsi_disk_cmd(xs);
+ break;
case ATA_PORT_T_ATAPI:
- return (atascsi_atapi_cmd(xs));
+ atascsi_atapi_cmd(xs);
+ break;
case ATA_PORT_T_NONE:
default:
- return (atascsi_done(xs, XS_DRIVER_STUFFUP));
+ atascsi_done(xs, XS_DRIVER_STUFFUP);
+ break;
}
+
+ return (COMPLETE);
}
-int
+void
atascsi_disk_cmd(struct scsi_xfer *xs)
{
struct scsi_link *link = xs->sc_link;
@@ -362,26 +371,34 @@ atascsi_disk_cmd(struct scsi_xfer *xs)
break;
case SYNCHRONIZE_CACHE:
- return (atascsi_disk_sync(xs));
+ atascsi_disk_sync(xs);
+ return;
case REQUEST_SENSE:
- return (atascsi_disk_sense(xs));
+ atascsi_disk_sense(xs);
+ return;
case INQUIRY:
- return (atascsi_disk_inq(xs));
+ atascsi_disk_inq(xs);
+ return;
case READ_CAPACITY:
- return (atascsi_disk_capacity(xs));
+ atascsi_disk_capacity(xs);
+ return;
case TEST_UNIT_READY:
case START_STOP:
case PREVENT_ALLOW:
- return (atascsi_done(xs, XS_NOERROR));
+ atascsi_done(xs, XS_NOERROR);
+ return;
default:
- return (atascsi_done(xs, XS_DRIVER_STUFFUP));
+ atascsi_done(xs, XS_DRIVER_STUFFUP);
+ return;
}
xa = ata_get_xfer(ap);
- if (xa == NULL)
- return (NO_CCB);
+ if (xa == NULL) {
+ atascsi_done(xs, XS_NO_CCB);
+ return;
+ }
xa->flags = flags;
if (xs->cmdlen == 6) {
@@ -439,7 +456,7 @@ atascsi_disk_cmd(struct scsi_xfer *xs)
if (xs->flags & SCSI_POLL)
xa->flags |= ATA_F_POLL;
- return (ata_exec(as, xa));
+ ata_exec(as, xa);
}
void
@@ -470,7 +487,7 @@ atascsi_disk_cmd_done(struct ata_xfer *xa)
scsi_done(xs);
}
-int
+void
atascsi_disk_inq(struct scsi_xfer *xs)
{
struct scsi_inquiry *inq = (struct scsi_inquiry *)xs->cmd;
@@ -478,27 +495,29 @@ atascsi_disk_inq(struct scsi_xfer *xs)
if (ISSET(inq->flags, SI_EVPD)) {
switch (inq->pagecode) {
case SI_PG_SUPPORTED:
- return (atascsi_disk_vpd_supported(xs));
+ atascsi_disk_vpd_supported(xs);
+ break;
case SI_PG_SERIAL:
- return (atascsi_disk_vpd_serial(xs));
+ atascsi_disk_vpd_serial(xs);
+ break;
case SI_PG_DEVID:
- return (atascsi_disk_vpd_ident(xs));
+ atascsi_disk_vpd_ident(xs);
+ break;
default:
- return (atascsi_done(xs, XS_DRIVER_STUFFUP));
+ atascsi_done(xs, XS_DRIVER_STUFFUP);
+ break;
}
- }
-
- return (atascsi_disk_inquiry(xs));
+ } else
+ atascsi_disk_inquiry(xs);
}
-int
+void
atascsi_disk_inquiry(struct scsi_xfer *xs)
{
struct scsi_link *link = xs->sc_link;
struct atascsi *as = link->adapter_softc;
struct ata_port *ap = as->as_ports[link->target];
struct scsi_inquiry_data inq;
- int rv;
bzero(&inq, sizeof(inq));
@@ -512,10 +531,10 @@ atascsi_disk_inquiry(struct scsi_xfer *xs)
bcopy(&inq, xs->data, MIN(sizeof(inq), xs->datalen));
- rv = atascsi_done(xs, XS_NOERROR);
+ atascsi_done(xs, XS_NOERROR);
if (ap->ap_features & ATA_PORT_F_PROBED)
- return (rv);
+ return;
ap->ap_features = ATA_PORT_F_PROBED;
@@ -550,11 +569,9 @@ atascsi_disk_inquiry(struct scsi_xfer *xs)
}
}
}
-
- return (rv);
}
-int
+void
atascsi_disk_vpd_supported(struct scsi_xfer *xs)
{
struct {
@@ -573,10 +590,10 @@ atascsi_disk_vpd_supported(struct scsi_xfer *xs)
bcopy(&pg, xs->data, MIN(sizeof(pg), xs->datalen));
- return (atascsi_done(xs, XS_NOERROR));
+ atascsi_done(xs, XS_NOERROR);
}
-int
+void
atascsi_disk_vpd_serial(struct scsi_xfer *xs)
{
struct scsi_link *link = xs->sc_link;
@@ -594,10 +611,10 @@ atascsi_disk_vpd_serial(struct scsi_xfer *xs)
bcopy(&pg, xs->data, MIN(sizeof(pg), xs->datalen));
- return (atascsi_done(xs, XS_NOERROR));
+ atascsi_done(xs, XS_NOERROR);
}
-int
+void
atascsi_disk_vpd_ident(struct scsi_xfer *xs)
{
struct scsi_link *link = xs->sc_link;
@@ -646,10 +663,10 @@ atascsi_disk_vpd_ident(struct scsi_xfer *xs)
bcopy(&pg, xs->data, MIN(pg_len, xs->datalen));
- return (atascsi_done(xs, XS_NOERROR));
+ atascsi_done(xs, XS_NOERROR);
}
-int
+void
atascsi_disk_sync(struct scsi_xfer *xs)
{
struct scsi_link *link = xs->sc_link;
@@ -658,8 +675,10 @@ atascsi_disk_sync(struct scsi_xfer *xs)
struct ata_xfer *xa;
xa = ata_get_xfer(ap);
- if (xa == NULL)
- return (NO_CCB);
+ if (xa == NULL) {
+ atascsi_done(xs, XS_NO_CCB);
+ return;
+ }
xa->datalen = 0;
xa->flags = ATA_F_READ;
@@ -674,7 +693,7 @@ atascsi_disk_sync(struct scsi_xfer *xs)
xa->fis->command = ATA_C_FLUSH_CACHE;
xa->fis->device = 0;
- return (ata_exec(as, xa));
+ ata_exec(as, xa);
}
void
@@ -706,7 +725,7 @@ atascsi_disk_sync_done(struct ata_xfer *xa)
scsi_done(xs);
}
-int
+void
atascsi_disk_capacity(struct scsi_xfer *xs)
{
struct scsi_link *link = xs->sc_link;
@@ -738,10 +757,10 @@ atascsi_disk_capacity(struct scsi_xfer *xs)
bcopy(&rcd, xs->data, MIN(sizeof(rcd), xs->datalen));
- return (atascsi_done(xs, XS_NOERROR));
+ atascsi_done(xs, XS_NOERROR);
}
-int
+void
atascsi_disk_sense(struct scsi_xfer *xs)
{
struct scsi_sense_data *sd = (struct scsi_sense_data *)xs->data;
@@ -751,10 +770,10 @@ atascsi_disk_sense(struct scsi_xfer *xs)
sd->error_code = 0x70; /* XXX magic */
sd->flags = SKEY_NO_SENSE;
- return (atascsi_done(xs, XS_NOERROR));
+ atascsi_done(xs, XS_NOERROR);
}
-int
+void
atascsi_atapi_cmd(struct scsi_xfer *xs)
{
struct scsi_link *link = xs->sc_link;
@@ -764,8 +783,10 @@ atascsi_atapi_cmd(struct scsi_xfer *xs)
struct ata_fis_h2d *fis;
xa = ata_get_xfer(ap);
- if (xa == NULL)
- return (NO_CCB);
+ if (xa == NULL) {
+ atascsi_done(xs, XS_NO_CCB);
+ return;
+ }
switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
case SCSI_DATA_IN:
@@ -799,7 +820,7 @@ atascsi_atapi_cmd(struct scsi_xfer *xs)
/* Copy SCSI command into ATAPI packet. */
memcpy(xa->packetcmd, xs->cmd, xs->cmdlen);
- return (ata_exec(as, xa));
+ ata_exec(as, xa);
}
void
@@ -840,18 +861,16 @@ atascsi_atapi_cmd_done(struct ata_xfer *xa)
scsi_done(xs);
}
-int
+void
atascsi_done(struct scsi_xfer *xs, int error)
{
int s;
xs->error = error;
- xs->flags |= ITSDONE;
s = splbio();
scsi_done(xs);
splx(s);
- return (COMPLETE);
}
int atascsi_ioctl_cmd(struct atascsi *, struct ata_port *, atareq_t *);
@@ -879,6 +898,7 @@ atascsi_ioctl_cmd(struct atascsi *as, struct ata_port *ap, atareq_t *atareq)
struct ata_fis_h2d *fis;
void *buf;
int rc = 0;
+ int s;
xa = ata_get_xfer(ap);
if (xa == NULL)
@@ -909,21 +929,11 @@ atascsi_ioctl_cmd(struct atascsi *as, struct ata_port *ap, atareq_t *atareq)
}
xa->atascsi_private = NULL;
- switch (as->as_methods->ata_cmd(xa)) {
- case ATA_COMPLETE:
- break;
- case ATA_QUEUED:
- while (xa->state == ATA_S_PENDING || xa->state == ATA_S_ONCHIP)
- tsleep(xa, PRIBIO, "atascsi", 0);
- break;
- case ATA_ERROR:
- free(buf, M_TEMP);
- ata_put_xfer(xa);
- atareq->retsts = ATACMD_ERROR;
- return (EIO);
- default:
- panic("atascsi_ioctl_cmd: unexpected return from ata_cmd");
- }
+ as->as_methods->ata_cmd(xa);
+ s = splbio();
+ while (!ISSET(xa->flags, ATA_F_DONE))
+ tsleep(xa, PRIBIO, "atascsi", 0);
+ splx(s);
switch (xa->state) {
case ATA_S_COMPLETE:
@@ -955,21 +965,10 @@ atascsi_ioctl_done(struct ata_xfer *xa)
wakeup(xa);
}
-int
+void
ata_exec(struct atascsi *as, struct ata_xfer *xa)
{
- int polled = xa->flags & ATA_F_POLL;
-
- switch (as->as_methods->ata_cmd(xa)) {
- case ATA_COMPLETE:
- case ATA_ERROR:
- return (COMPLETE);
- case ATA_QUEUED:
- if (!polled)
- return (SUCCESSFULLY_QUEUED);
- default:
- panic("unexpected return from ata_exec");
- }
+ as->as_methods->ata_cmd(xa);
}
struct ata_xfer *
@@ -990,3 +989,42 @@ ata_put_xfer(struct ata_xfer *xa)
{
xa->ata_put_xfer(xa);
}
+
+void
+ata_polled_complete(struct ata_xfer *xa)
+{
+ /* do nothing */
+}
+
+int
+ata_polled(struct ata_xfer *xa)
+{
+ int rv;
+
+ if (!ISSET(xa->flags, ATA_F_DONE))
+ panic("ata_polled: xa isnt complete");
+
+ switch (xa->state) {
+ case ATA_S_COMPLETE:
+ rv = 0;
+ break;
+ case ATA_S_ERROR:
+ case ATA_S_TIMEOUT:
+ rv = EIO;
+ break;
+ default:
+ panic("ata_polled: xa state (%d)",
+ xa->state);
+ }
+
+ ata_put_xfer(xa);
+
+ return (rv);
+}
+
+void
+ata_complete(struct ata_xfer *xa)
+{
+ SET(xa->flags, ATA_F_DONE);
+ xa->complete(xa);
+}