diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2006-04-05 14:07:25 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2006-04-05 14:07:25 +0000 |
commit | 8fcb8ea8eecd36e9ddd04029d26e6c687fb534bb (patch) | |
tree | 0e3650002016cf2dbb47b8614f57c835c4f82596 /sys/dev | |
parent | 90eaab3787ac8bdf1e5981cb3301469518d5eb19 (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.c | 75 |
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); } |