summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2006-04-05 14:07:25 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2006-04-05 14:07:25 +0000
commit8fcb8ea8eecd36e9ddd04029d26e6c687fb534bb (patch)
tree0e3650002016cf2dbb47b8614f57c835c4f82596 /sys/dev
parent90eaab3787ac8bdf1e5981cb3301469518d5eb19 (diff)
reintroduce ami_complete, a replacement for ami_poll that is built on top
of the async exec and done commands. ami_poll uses a special command id that isnt needed for normal commands. on top of this we should drain the runq before using ami_poll. using ami_complete means that we can poll with commands still on the card.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/ami.c75
1 files changed, 68 insertions, 7 deletions
diff --git a/sys/dev/ic/ami.c b/sys/dev/ic/ami.c
index 6a33e077d61..1abbfb13cad 100644
--- a/sys/dev/ic/ami.c
+++ b/sys/dev/ic/ami.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ami.c,v 1.140 2006/04/03 01:53:04 marco Exp $ */
+/* $OpenBSD: ami.c,v 1.141 2006/04/05 14:07:24 dlg Exp $ */
/*
* Copyright (c) 2001 Michael Shalayeff
@@ -129,6 +129,7 @@ void ami_freemem(struct ami_softc *, struct ami_mem *);
int ami_poll(struct ami_softc *, struct ami_ccb *);
void ami_start(struct ami_softc *, struct ami_ccb *);
+void ami_complete(struct ami_softc *, struct ami_ccb *, int);
int ami_done(struct ami_softc *, int);
void ami_runqueue(void *);
@@ -971,14 +972,14 @@ ami_schwartz_poll(struct ami_softc *sc, struct ami_iocmd *mbox)
int
ami_start_xs(struct ami_softc *sc, struct ami_ccb *ccb, struct scsi_xfer *xs)
{
+ timeout_set(&xs->stimeout, ami_stimeout, ccb);
+
if (xs->flags & SCSI_POLL) {
- ami_poll(sc, ccb);
+ ami_complete(sc, ccb, xs->timeout);
return (COMPLETE);
- }
-
- timeout_set(&xs->stimeout, ami_stimeout, ccb);
+ }
+
timeout_add(&xs->stimeout, (xs->timeout * hz) / 1000);
-
ami_start(sc, ccb);
return (SUCCESSFULLY_QUEUED);
@@ -1036,6 +1037,67 @@ ami_poll(struct ami_softc *sc, struct ami_ccb *ccb)
}
void
+ami_complete(struct ami_softc *sc, struct ami_ccb *ccb, int timeout)
+{
+ struct ami_iocmd mbox;
+ int i = 0, done = 0;
+ int s;
+
+ s = splbio();
+
+ /*
+ * since exec will return if the mbox is busy we have to busy wait
+ * ourselves. once its in, jam it into the runq.
+ */
+ while (i < AMI_MAX_BUSYWAIT) {
+ if (sc->sc_exec(sc, &ccb->ccb_cmd) == 0) {
+ ccb->ccb_state = AMI_CCB_QUEUED;
+ TAILQ_INSERT_TAIL(&sc->sc_ccb_runq, ccb, ccb_link);
+ break;
+ }
+
+ DELAY(1000);
+ i++;
+ }
+ if (ccb->ccb_state != AMI_CCB_QUEUED)
+ goto err;
+
+ i = 0;
+ while (i < timeout) {
+ if (sc->sc_done(sc, &mbox) != 0) {
+ for (i = 0; i < mbox.acc_nstat; i++) {
+ int ready = mbox.acc_cmplidl[i];
+ ami_done(sc, ready);
+ if (ready == ccb->ccb_cmd.acc_id)
+ done = 1;
+ }
+ if (done)
+ break;
+ }
+
+ DELAY(1000);
+ i++;
+ }
+ if (!done) {
+ printf("%s: timeout ccb %d\n", DEVNAME(sc),
+ ccb->ccb_cmd.acc_id);
+ TAILQ_REMOVE(&sc->sc_ccb_runq, ccb, ccb_link);
+ goto err;
+ }
+ splx(s);
+
+ /* start the runqueue again */
+ ami_runqueue(sc);
+ return;
+
+err:
+ splx(s);
+ ccb->ccb_flags |= AMI_CCB_F_ERR;
+ ccb->ccb_state = AMI_CCB_READY;
+ ccb->ccb_done(sc, ccb);
+}
+
+void
ami_stimeout(void *v)
{
struct ami_ccb *ccb = v;
@@ -1606,7 +1668,6 @@ ami_intr(void *v)
if (rv)
ami_runqueue(sc);
-
AMI_DPRINTF(AMI_D_INTR, ("exit "));
return (rv);
}