diff options
| author | Justin T. Gibbs <gibbs@FreeBSD.org> | 1999-05-25 20:15:20 +0000 |
|---|---|---|
| committer | Justin T. Gibbs <gibbs@FreeBSD.org> | 1999-05-25 20:15:20 +0000 |
| commit | 378d6d73953db663b673c1699127277daa56829c (patch) | |
| tree | eaf8c7de51c8947474e343b68866bb98e472eaac /sys/dev/aha | |
| parent | f40c8d715503ff49f47461e906a959935af6bac3 (diff) | |
Notes
Diffstat (limited to 'sys/dev/aha')
| -rw-r--r-- | sys/dev/aha/aha.c | 120 | ||||
| -rw-r--r-- | sys/dev/aha/ahareg.h | 4 |
2 files changed, 90 insertions, 34 deletions
diff --git a/sys/dev/aha/aha.c b/sys/dev/aha/aha.c index 320c1ae40021..97bc80b8c422 100644 --- a/sys/dev/aha/aha.c +++ b/sys/dev/aha/aha.c @@ -55,7 +55,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: aha.c,v 1.24 1999/05/11 08:12:11 imp Exp $ + * $Id: aha.c,v 1.25 1999/05/14 23:10:25 imp Exp $ */ #include "pnp.h" @@ -100,6 +100,10 @@ struct aha_softc *aha_softcs[NAHATOT]; */ #define PROBABLY_NEW_BOARD(REV) (REV > 0x43 && REV < 0x56) +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + /* MailBox Management functions */ static __inline void ahanextinbox(struct aha_softc *aha); static __inline void ahanextoutbox(struct aha_softc *aha); @@ -1049,9 +1053,12 @@ ahaaction(struct cam_sim *sim, union ccb *ccb) if ((aha->disc_permitted & target_mask) != 0) cts->flags |= CCB_TRANS_DISC_ENB; cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; - if ((aha->sync_permitted & target_mask) != 0) - cts->sync_period = 50; - else + if ((aha->sync_permitted & target_mask) != 0) { + if (aha->boardid >= BOARD_1542CF) + cts->sync_period = 25; + else + cts->sync_period = 50; + } else cts->sync_period = 0; if (cts->sync_period != 0) @@ -1571,34 +1578,67 @@ ahareset(struct aha_softc* aha, int hard_reset) */ int aha_cmd(struct aha_softc *aha, aha_op_t opcode, u_int8_t *params, - u_int param_len, u_int8_t *reply_data, u_int reply_len, - u_int cmd_timeout) + u_int param_len, u_int8_t *reply_data, u_int reply_len, + u_int cmd_timeout) { u_int timeout; u_int status; + u_int saved_status; u_int intstat; u_int reply_buf_size; int s; int cmd_complete; + int error; /* No data returned to start */ reply_buf_size = reply_len; reply_len = 0; intstat = 0; cmd_complete = 0; + saved_status = 0; + error = 0; + + /* + * All commands except for the "start mailbox" and the "enable + * outgoing mailbox read interrupt" commands cannot be issued + * while there are pending transactions. Freeze our SIMQ + * and wait for all completions to occur if necessary. + */ + timeout = 100000; + s = splcam(); + while (LIST_FIRST(&aha->pending_ccbs) != NULL && --timeout) { + /* Fire the interrupt handler in case interrupts are blocked */ + aha_intr(aha); + splx(s); + DELAY(100); + s = splcam(); + } + splx(s); + if (timeout == 0) { + printf("%s: aha_cmd: Timeout waiting for adapter idle\n", + aha_name(aha)); + return (ETIMEDOUT); + } aha->command_cmp = 0; /* - * Wait up to 1 sec. for the adapter to become + * Wait up to 10 sec. for the adapter to become * ready to accept commands. */ - timeout = 10000; + timeout = 100000; while (--timeout) { status = aha_inb(aha, STATUS_REG); if ((status & HA_READY) != 0 && (status & CMD_REG_BUSY) == 0) break; + /* + * Throw away any pending data which may be + * left over from earlier commands that we + * timedout on. + */ + if ((status & DATAIN_REG_READY) != 0) + (void)aha_inb(aha, DATAIN_REG); DELAY(100); } if (timeout == 0) { @@ -1618,15 +1658,20 @@ aha_cmd(struct aha_softc *aha, aha_op_t opcode, u_int8_t *params, timeout = 10000; while (param_len && --timeout) { DELAY(100); + s = splcam(); status = aha_inb(aha, STATUS_REG); intstat = aha_inb(aha, INTSTAT_REG); + splx(s); + if ((intstat & (INTR_PENDING|CMD_COMPLETE)) == (INTR_PENDING|CMD_COMPLETE)) { + saved_status = status; cmd_complete = 1; break; } + if (aha->command_cmp != 0) { - status = aha->latched_status; + saved_status = aha->latched_status; cmd_complete = 1; break; } @@ -1635,12 +1680,13 @@ aha_cmd(struct aha_softc *aha, aha_op_t opcode, u_int8_t *params, if ((status & CMD_REG_BUSY) == 0) { aha_outb(aha, COMMAND_REG, *params++); param_len--; + timeout = 10000; } } if (timeout == 0) { printf("%s: aha_cmd: Timeout sending parameters, " "status = 0x%x\n", aha_name(aha), status); - return (ETIMEDOUT); + error = ETIMEDOUT; } /* @@ -1649,34 +1695,43 @@ aha_cmd(struct aha_softc *aha, aha_op_t opcode, u_int8_t *params, */ while (cmd_complete == 0 && --cmd_timeout) { + s = splcam(); status = aha_inb(aha, STATUS_REG); intstat = aha_inb(aha, INTSTAT_REG); - if ((intstat & (INTR_PENDING|CMD_COMPLETE)) - == (INTR_PENDING|CMD_COMPLETE)) - break; + splx(s); if (aha->command_cmp != 0) { - status = aha->latched_status; - break; - } - - if ((status & DATAIN_REG_READY) != 0) { + cmd_complete = 1; + saved_status = aha->latched_status; + } else if ((intstat & (INTR_PENDING|CMD_COMPLETE)) + == (INTR_PENDING|CMD_COMPLETE)) { + /* + * Our poll (in case interrupts are blocked) + * saw the CMD_COMPLETE interrupt. + */ + cmd_complete = 1; + saved_status = status; + } else if ((status & DATAIN_REG_READY) != 0) { u_int8_t data; data = aha_inb(aha, DATAIN_REG); if (reply_len < reply_buf_size) { *reply_data++ = data; } else { - printf("%s: aha_cmd - Discarded reply data byte " - "for opcode 0x%x\n", aha_name(aha), + printf("%s: aha_cmd - Discarded reply data " + "byte for opcode 0x%x\n", aha_name(aha), opcode); } + /* + * Reset timeout to ensure at least a second + * between response bytes. + */ + cmd_timeout = MAX(cmd_timeout, 10000); reply_len++; } - DELAY(100); } - if (timeout == 0) { + if (cmd_timeout == 0) { printf("%s: aha_cmd: Timeout waiting for reply data and " "command complete.\n%s: status = 0x%x, intstat = 0x%x, " "reply_len = %d\n", aha_name(aha), aha_name(aha), status, @@ -1692,10 +1747,13 @@ aha_cmd(struct aha_softc *aha, aha_op_t opcode, u_int8_t *params, aha_intr(aha); splx(s); + if (error != 0) + return (error); + /* * If the command was rejected by the controller, tell the caller. */ - if ((status & CMD_INVALID) != 0) { + if ((saved_status & CMD_INVALID) != 0) { PRVERB(("%s: Invalid Command 0x%x\n", aha_name(aha), opcode)); /* * Some early adapters may not recover properly from @@ -1714,7 +1772,6 @@ aha_cmd(struct aha_softc *aha, aha_op_t opcode, u_int8_t *params, return (EINVAL); } - if (param_len > 0) { /* The controller did not accept the full argument list */ return (E2BIG); @@ -1774,19 +1831,16 @@ ahafetchtransinfo(struct aha_softc *aha, struct ccb_trans_settings* cts) /* * Inquire Setup Information. This command retreives - * the sync info for older models. We put a small delay here - * because that seems to help the stability. 10mS is known - * to work, but other values might also work. + * the sync info for older models. */ - DELAY(10000); param = sizeof(setup_info); error = aha_cmd(aha, AOP_INQUIRE_SETUP_INFO, ¶m, /*paramlen*/1, (u_int8_t*)&setup_info, sizeof(setup_info), DEFAULT_CMD_TIMEOUT); if (error != 0) { - printf("%s: ahafetchtransinfo - Inquire Setup Info Failed\n", - aha_name(aha)); + printf("%s: ahafetchtransinfo - Inquire Setup Info Failed %d\n", + aha_name(aha), error); return; } @@ -1799,7 +1853,11 @@ ahafetchtransinfo(struct aha_softc *aha, struct ccb_trans_settings* cts) cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; - sync_period = 2000 + (500 * sync_info.period); + if (aha->boardid >= BOARD_1542CF) + sync_period = 1000; + else + sync_period = 2000; + sync_period += 500 * sync_info.period; /* Convert ns value to standard SCSI sync rate */ if (cts->sync_offset != 0) diff --git a/sys/dev/aha/ahareg.h b/sys/dev/aha/ahareg.h index 82f3f4a49bd4..ba3a1c3ddac3 100644 --- a/sys/dev/aha/ahareg.h +++ b/sys/dev/aha/ahareg.h @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ahareg.h,v 1.4 1998/11/10 06:44:42 gibbs Exp $ + * $Id: ahareg.h,v 1.5 1999/01/20 06:21:27 imp Exp $ */ #ifndef _AHAREG_H_ @@ -382,10 +382,8 @@ struct aha_softc { tag_capable :1, resource_shortage:1, :26; - u_int16_t tags_permitted; u_int16_t disc_permitted; u_int16_t sync_permitted; - u_int16_t fast_permitted; u_int8_t init_level; volatile u_int8_t command_cmp; volatile u_int8_t latched_status; |
