diff options
-rw-r--r-- | sys/dev/ata/atascsi.c | 240 | ||||
-rw-r--r-- | sys/dev/ata/atascsi.h | 18 | ||||
-rw-r--r-- | sys/dev/ic/sili.c | 28 | ||||
-rw-r--r-- | sys/dev/pci/ahci.c | 29 |
4 files changed, 175 insertions, 140 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); +} diff --git a/sys/dev/ata/atascsi.h b/sys/dev/ata/atascsi.h index c53d4c22c4e..fc02b0df5cf 100644 --- a/sys/dev/ata/atascsi.h +++ b/sys/dev/ata/atascsi.h @@ -1,4 +1,4 @@ -/* $OpenBSD: atascsi.h,v 1.33 2009/02/16 21:19:06 miod Exp $ */ +/* $OpenBSD: atascsi.h,v 1.34 2009/12/07 09:37:34 dlg Exp $ */ /* * Copyright (c) 2007 David Gwynne <dlg@openbsd.org> @@ -283,9 +283,10 @@ struct ata_xfer { #define ATA_F_PIO (1<<4) #define ATA_F_PACKET (1<<5) #define ATA_F_NCQ (1<<6) -#define ATA_FMT_FLAGS "\020" "\007NCQ" "\006PACKET" \ - "\005PIO" "\004POLL" "\003NOWAIT" \ - "\002WRITE" "\001READ" +#define ATA_F_DONE (1<<7) +#define ATA_FMT_FLAGS "\020" "\007DONE" "\007NCQ" \ + "\006PACKET" "\005PIO" "\004POLL" \ + "\003NOWAIT" "\002WRITE" "\001READ" volatile int state; #define ATA_S_SETUP 0 @@ -295,16 +296,13 @@ struct ata_xfer { #define ATA_S_TIMEOUT 4 #define ATA_S_ONCHIP 5 #define ATA_S_PUT 6 +#define ATA_S_DONE 7 void *atascsi_private; void (*ata_put_xfer)(struct ata_xfer *); }; -#define ATA_QUEUED 0 -#define ATA_COMPLETE 1 -#define ATA_ERROR 2 - /* * atascsi */ @@ -313,7 +311,7 @@ struct atascsi_methods { int (*probe)(void *, int); void (*free)(void *, int); struct ata_xfer * (*ata_get_xfer)(void *, int ); - int (*ata_cmd)(struct ata_xfer *); + void (*ata_cmd)(struct ata_xfer *); }; struct atascsi_attach_args { @@ -334,3 +332,5 @@ int atascsi_detach(struct atascsi *, int); int atascsi_probe_dev(struct atascsi *, int); int atascsi_detach_dev(struct atascsi *, int, int); + +void ata_complete(struct ata_xfer *); diff --git a/sys/dev/ic/sili.c b/sys/dev/ic/sili.c index 818dec6fcf3..867396f7778 100644 --- a/sys/dev/ic/sili.c +++ b/sys/dev/ic/sili.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sili.c,v 1.43 2009/06/05 03:57:32 ray Exp $ */ +/* $OpenBSD: sili.c,v 1.44 2009/12/07 09:37:33 dlg Exp $ */ /* * Copyright (c) 2007 David Gwynne <dlg@openbsd.org> @@ -164,7 +164,7 @@ int sili_ata_probe(void *, int); void sili_ata_free(void *, int); struct ata_xfer *sili_ata_get_xfer(void *, int); void sili_ata_put_xfer(struct ata_xfer *); -int sili_ata_cmd(struct ata_xfer *); +void sili_ata_cmd(struct ata_xfer *); struct atascsi_methods sili_atascsi_methods = { sili_ata_probe, @@ -381,7 +381,7 @@ fatal: KASSERT(ccb->ccb_xa.state == ATA_S_COMPLETE || ccb->ccb_xa.state == ATA_S_ERROR || ccb->ccb_xa.state == ATA_S_TIMEOUT); - ccb->ccb_xa.complete(&ccb->ccb_xa); + ata_complete(&ccb->ccb_xa); } } @@ -815,7 +815,7 @@ sili_ata_free(void *xsc, int port) /* XXX we should do more here */ } -int +void sili_ata_cmd(struct ata_xfer *xa) { struct sili_ccb *ccb = (struct sili_ccb *)xa; @@ -858,24 +858,22 @@ sili_ata_cmd(struct ata_xfer *xa) xa->state = ATA_S_PENDING; - if (xa->flags & ATA_F_POLL) { + if (xa->flags & ATA_F_POLL) sili_poll(ccb, xa->timeout, sili_ata_cmd_timeout); - return (ATA_COMPLETE); + else { + timeout_add_msec(&xa->stimeout, xa->timeout); + s = splbio(); + sili_start(sp, ccb); + splx(s); } - timeout_add_msec(&xa->stimeout, xa->timeout); - - s = splbio(); - sili_start(sp, ccb); - splx(s); - return (ATA_QUEUED); + return; failcmd: s = splbio(); xa->state = ATA_S_ERROR; - xa->complete(xa); + ata_complete(xa); splx(s); - return (ATA_ERROR); } void @@ -907,7 +905,7 @@ sili_ata_cmd_done(struct sili_ccb *ccb, int defer_completion) if (defer_completion) TAILQ_INSERT_TAIL(&sp->sp_deferred_ccbs, ccb, ccb_entry); else if (xa->state == ATA_S_COMPLETE) - xa->complete(xa); + ata_complete(xa); #ifdef DIAGNOSTIC else printf("%s: completion not deferred, but xa->state is %02x?\n", diff --git a/sys/dev/pci/ahci.c b/sys/dev/pci/ahci.c index 8f43b9bf63e..4d56e1a72d0 100644 --- a/sys/dev/pci/ahci.c +++ b/sys/dev/pci/ahci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ahci.c,v 1.153 2009/11/01 01:50:15 dlg Exp $ */ +/* $OpenBSD: ahci.c,v 1.154 2009/12/07 09:37:34 dlg Exp $ */ /* * Copyright (c) 2006 David Gwynne <dlg@openbsd.org> @@ -541,7 +541,7 @@ int ahci_ata_probe(void *, int); void ahci_ata_free(void *, int); struct ata_xfer * ahci_ata_get_xfer(void *, int); void ahci_ata_put_xfer(struct ata_xfer *); -int ahci_ata_cmd(struct ata_xfer *); +void ahci_ata_cmd(struct ata_xfer *); struct atascsi_methods ahci_atascsi_methods = { ahci_ata_probe, @@ -2326,7 +2326,7 @@ ahci_ata_put_xfer(struct ata_xfer *xa) ahci_put_ccb(ccb); } -int +void ahci_ata_cmd(struct ata_xfer *xa) { struct ahci_ccb *ccb = (struct ahci_ccb *)xa; @@ -2356,24 +2356,23 @@ ahci_ata_cmd(struct ata_xfer *xa) xa->state = ATA_S_PENDING; - if (xa->flags & ATA_F_POLL) { + if (xa->flags & ATA_F_POLL) ahci_poll(ccb, xa->timeout, ahci_ata_cmd_timeout); - return (ATA_COMPLETE); - } + else { + timeout_add_msec(&xa->stimeout, xa->timeout); - timeout_add_msec(&xa->stimeout, xa->timeout); + s = splbio(); + ahci_start(ccb); + splx(s); + } - s = splbio(); - ahci_start(ccb); - splx(s); - return (ATA_QUEUED); + return; failcmd: s = splbio(); xa->state = ATA_S_ERROR; - xa->complete(xa); + ata_complete(xa); splx(s); - return (ATA_ERROR); } void @@ -2398,7 +2397,7 @@ ahci_ata_cmd_done(struct ahci_ccb *ccb) ccb->ccb_slot); #endif if (xa->state != ATA_S_TIMEOUT) - xa->complete(xa); + ata_complete(xa); } void @@ -2483,7 +2482,7 @@ ahci_ata_cmd_timeout(void *arg) /* Complete the timed out ata_xfer I/O (may generate new I/O). */ DPRINTF(AHCI_D_TIMEOUT, "%s: run completion (2)\n", PORTNAME(ap)); - xa->complete(xa); + ata_complete(xa); DPRINTF(AHCI_D_TIMEOUT, "%s: splx\n", PORTNAME(ap)); ret: |