From 28445eef28f9ea07a078a1b0ffeb92df783ad9f5 Mon Sep 17 00:00:00 2001 From: Matt Jacob Date: Tue, 27 Jun 2000 19:44:31 +0000 Subject: [PATCH] Fix usage of DELAY (SYS_DELAY is the platform independent local define). Fix stupidity wrt checking whether we've gone to LOOP_PDB_RCVD loopstate- it's okay to be greater than this state. D'oh! Protect calls to isp_pdb_sync and isp_fclink_state with IS_FC macros. Completely redo mailbox command routine (in preparation to make this possibly wait rather than poll for completion). Make a major attempt to solve the 'lost interrupt' problem 1. Problem The Qlogic cards would appear to 'lose' interrupts, i.e., a legitimate regular SCSI command placed on the request queue would never complete and the watchdog routine in the driver would eventually wakeup and catch it. This would typically only happen on Alphas, although a couple folks with 700MHz Intel platforms have also seen this. For a long time I thought it was a foulup with f/w negotiations of SYNC and/or WIDE as it always seemed to happen right after the platform it was running on had done a SET TARGET PARAMETERS mailbox command to (re)enable sync && wide (after initially forcing ASYNC/NARROW at startup). However, occasionally, the same thing would also occur for the Fibre Channel cards as well (which, ahem, have no SET TARGET PARAMETERS for transfer mode). After finally putting in a better set of watchdog routines for the platforms for this driver, it seemed to be the case that the command in question (usually a READ CAPACITY) just had up and died- the watchdog routine would catch it after ~10 seconds. For some platforms (NetBSD/OpenBSD)- an ABORT COMMAND mailbox command was sent (which would always fail- indicating that the f/w denied knowledge of this command, i.e., the f/w thought it was a done command). In any case, retrying the command worked. But this whole problem needed to be really fixed. 2. A False Step That Went in The Right Direction The mailbox code was completely rewritten to no longer try and grab the mailbox semaphore register and to try and 'by hand' complete async fast posting completions. It was also rewritten to now have separate in && out bitpatterns for registers to load to start and retrieve to complete. This means that isp_intr now handles mailbox completions. This substantially simplifies the mailbox handling code, and carries things 90% toward getting this to be a non-polled routine for this driver. This did not solve the problem, though. 3. Register Debouncing I saw some comments in some errata sheets and some notes in a Qlogic produced Linux driver (for the Qlogic 2100) that seemed to indicate that debouncing of reads of the mailbox registers might be needed, so I added this. This did not affect the problem. In fact, it made the problem worse for non-2100 cards. 5. Interrupt masking/unmasking The driver *used* to do a substantial amount of masking/unmasking of the interrupt control register. This was done to make sure that the core common code could just assume it would never get pre-empted. This apparently substantially contributed to the lost interrupt problem. The rewrite of the ICR (Interrupt Control Register), which is a separate register from the ISR (Interrupt Status Register) should not have caused any change to interrupt assertions pending. The manual does not state that it will, and the register layout seems to imply that the ICR is just an active route gate. We only enable PCI Interrupts and RISC Interrupts- this should mean that when the f/w asserts a RISC interrupt and (and the ICR allows RISC Interrupts) and we have PCI Interrupts enabled, we should get a PCI interrupt. Apparently this is a latch- not a signal route. Removing this got rid of *most* but not all, lost interrupts. 5. Watchdog Smartening I made sure that the watchdog routine would catch cases where the Qlogic's ISR showed an interrupt assertion. The watchdog routine now calls the interrupt service routine if it sees this. Some additional internal state flags were added so that the watchdog routine could then know whether the command it was in the middle of burying (because we had time it out) was in fact completed by the interrupt service routine. 6. Occasional Constipation Of Commands.. In running some very strenous high IOPs tests (generating about 11000 interrupts/second across one Qlogic 1040, one Qlogic 1080 and one Qlogic 2200 on an Alpha PC164), I found that I would get occasional but regular 'watchdog timeouts' on both the 1080 and the 2100 cards. This is under FreeBSD, and the watchdog timeout routine just marks the command in error and retries it. Invariably, right after this 'watchdog timeout' error, I'd get a command completion for the command that I had thought timed out. That is, I'd get a command completion, but the handle returned by the firmware mapped to no current command. The frequency of this problem is low under such a load- it would usually take an 30 minutes per 'lost' interrupt. I doubled the timeout for commands to see if it just was an edge case of waiting too short a period. This has no effect. I gathered and printed out microtimes for the watchdog completed command and the completion that couldn't find a command- it was always the case that the order of occurrence was "timeout, completion" separated by a time on the order of 100 to 150 ms. This caused me to consider 'firmware constipation' as to be a possible culprit. That is, resubmission of a command to the device that had suffered a watchdog timeout seemed to cause the presumed dead command to show back up. I added code in the watchdog routine that, when first entered for the command, marks the command with a flag, reissues a local timeout call for one second later, but also then issues a MARKER Request Queue entry to the Qlogic f/w. A MARKER entry is used typically after a Bus Reset to cause the f/w to get synchronized with respect to either a Bus, a Nexus or a Target. Since I've added this code, I always now see the occasional watchdog timeout, but the command that was about to be terminated always now seems to be completed after the MARKER entry is issued (and before the timeout extension fires, which would come back and *really* terminate the command). --- sys/dev/isp/isp.c | 853 +++++++++++++++++++++------------------------- 1 file changed, 383 insertions(+), 470 deletions(-) diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index 617901f180a..7996b0fcedf 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -577,7 +577,7 @@ again: mbs.param[1] = 0x1000; isp_mboxcmd(isp, &mbs); /* give it a chance to start */ - DELAY(500); + SYS_DELAY(500); if (IS_SCSI(isp)) { /* @@ -1470,12 +1470,12 @@ isp_pdb_sync(isp, target) for (lim = loopid = 0; loopid < prange; loopid++) { lp = &tport[loopid]; lp->node_wwn = isp_get_portname(isp, loopid, 1); - if (fcp->isp_loopstate != LOOP_PDB_RCVD) + if (fcp->isp_loopstate < LOOP_PDB_RCVD) return (-1); if (lp->node_wwn == 0) continue; lp->port_wwn = isp_get_portname(isp, loopid, 0); - if (fcp->isp_loopstate != LOOP_PDB_RCVD) + if (fcp->isp_loopstate < LOOP_PDB_RCVD) return (-1); if (lp->port_wwn == 0) { lp->node_wwn = 0; @@ -1486,12 +1486,12 @@ isp_pdb_sync(isp, target) * Get an entry.... */ if (isp_getpdb(isp, loopid, &pdb) != 0) { - if (fcp->isp_loopstate != LOOP_PDB_RCVD) + if (fcp->isp_loopstate < LOOP_PDB_RCVD) return (-1); continue; } - if (fcp->isp_loopstate != LOOP_PDB_RCVD) + if (fcp->isp_loopstate < LOOP_PDB_RCVD) return (-1); /* @@ -2375,10 +2375,16 @@ isp_control(isp, ctl, arg) return (0); case ISPCTL_FCLINK_TEST: - return (isp_fclink_test(isp, FC_FW_READY_DELAY)); + if (IS_FC(isp)) { + return (isp_fclink_test(isp, FC_FW_READY_DELAY)); + } + break; case ISPCTL_PDB_SYNC: - return (isp_pdb_sync(isp, -1)); + if (IS_FC(isp)) { + return (isp_pdb_sync(isp, -1)); + } + break; #ifdef ISP_TARGET_MODE case ISPCTL_TOGGLE_TMODE: @@ -2413,41 +2419,74 @@ isp_intr(arg) { ISP_SCSI_XFER_T *complist[RESULT_QUEUE_LEN], *xs; struct ispsoftc *isp = arg; - u_int16_t iptr, optr; - u_int16_t isr, sema; + u_int16_t iptr, optr, isr, sema, junk; int i, nlooked = 0, ndone = 0; - /* - * If we've disabled interrupts, we may get a case where - * isr isn't set, but sema is. - */ - isr = ISP_READ(isp, BIU_ISR); - sema = ISP_READ(isp, BIU_SEMA) & 0x1; + if (IS_2100(isp)) { + i = 0; + do { + isr = ISP_READ(isp, BIU_ISR); + junk = ISP_READ(isp, BIU_ISR); + } while (isr != junk && ++i < 1000); + if (isr != junk) { + PRINTF("%s: isr unsteady (%x, %x)\n", + isp->isp_name, isr, junk); + } + i = 0; + do { + sema = ISP_READ(isp, BIU_SEMA); + junk = ISP_READ(isp, BIU_SEMA); + } while (sema != junk && ++i < 1000); + if (sema != junk) { + PRINTF("%s: sema unsteady (%x, %x)\n", + isp->isp_name, sema, junk); + } + } else { + isr = ISP_READ(isp, BIU_ISR); + sema = ISP_READ(isp, BIU_SEMA); + } IDPRINTF(5, ("%s: isp_intr isr %x sem %x\n", isp->isp_name, isr, sema)); + isr &= INT_PENDING_MASK(isp); + sema &= BIU_SEMA_LOCK; if (isr == 0 && sema == 0) { return (0); } -#if 0 - if (!INT_PENDING(isp, isr)) { - IDPRINTF(4, ("%s: isp_intr isr=%x\n", isp->isp_name, isr)); - return (0); - } -#endif - if (isp->isp_state != ISP_RUNSTATE) { - IDPRINTF(3, ("%s: interrupt (isr=%x,sema=%x) when not ready\n", - isp->isp_name, isr, sema)); - ISP_WRITE(isp, INMAILBOX5, ISP_READ(isp, OUTMAILBOX5)); - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - ISP_WRITE(isp, BIU_SEMA, 0); - ENABLE_INTS(isp); - return (1); - } if (sema) { - u_int16_t mbox = ISP_READ(isp, OUTMAILBOX0); + u_int16_t mbox; + + if (IS_2100(isp)) { + i = 0; + do { + mbox = ISP_READ(isp, OUTMAILBOX0); + junk = ISP_READ(isp, OUTMAILBOX0);; + } while (junk != mbox && ++i < 1000); + if (mbox != junk) { + PRINTF("%s: mailbox0 unsteady (%x, %x)\n", + isp->isp_name, mbox, junk); + ISP_WRITE(isp, BIU_SEMA, 0); + ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); + return (1); + } + } else { + mbox = ISP_READ(isp, OUTMAILBOX0); + } if (mbox & 0x4000) { - IDPRINTF(4, ("%s: Command Mbox 0x%x\n", - isp->isp_name, mbox)); + int obits, i = 0; + if ((obits = isp->isp_mboxbsy) != 0) { + isp->isp_mboxtmp[i++] = mbox; + for (i = 1; i < 8; i++) { + if ((obits & (1 << i)) == 0) { + continue; + } + isp->isp_mboxtmp[i] = + ISP_READ(isp, MBOX_OFF(i)); + } + isp->isp_mboxbsy = 0; + } else { + PRINTF("%s: Command Mbox 0x%x\n", + isp->isp_name, mbox); + } } else { u_int32_t fhandle = isp_parse_async(isp, (int) mbox); IDPRINTF(4, ("%s: Async Mbox 0x%x\n", @@ -2456,26 +2495,64 @@ isp_intr(arg) isp_fastpost_complete(isp, fhandle); } } - if (IS_FC(isp)) { + if (IS_FC(isp) || isp->isp_state != ISP_RUNSTATE) { ISP_WRITE(isp, BIU_SEMA, 0); ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - ENABLE_INTS(isp); return (1); } } + /* + * We can't be getting this now. + */ + if (isp->isp_state != ISP_RUNSTATE) { + PRINTF("%s: interrupt (isr=%x, sema=%x) when not ready\n", + isp->isp_name, isr, sema); + ISP_WRITE(isp, INMAILBOX5, ISP_READ(isp, OUTMAILBOX5)); + ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); + ISP_WRITE(isp, BIU_SEMA, 0); + return (1); + } + /* * You *must* read OUTMAILBOX5 prior to clearing the RISC interrupt. */ optr = isp->isp_residx; - iptr = ISP_READ(isp, OUTMAILBOX5); + + if (IS_2100(isp)) { + i = 0; + do { + iptr = ISP_READ(isp, OUTMAILBOX5); + junk = ISP_READ(isp, OUTMAILBOX5); + } while (junk != iptr && ++i < 1000); + + if (iptr != junk) { + ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); + PRINTF("%s: mailbox5 unsteady (%x, %x)\n", + isp->isp_name, iptr, junk); + return (1); + } + } else { + iptr = ISP_READ(isp, OUTMAILBOX5); + } + if (sema) { ISP_WRITE(isp, BIU_SEMA, 0); } ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); + if (optr == iptr && sema == 0) { - IDPRINTF(1, ("%s: why intr? isr %x iptr %x optr %x\n", - isp->isp_name, isr, optr, iptr)); + /* + * There are a lot of these- reasons unknown- mostly on + * faster Alpha machines. + * + * I tried delaying after writing HCCR_CMD_CLEAR_RISC_INT to + * make sure the old interrupt went away (to avoid 'ringing' + * effects), but that didn't stop this from occurring. + */ + junk = ISP_READ(isp, BIU_ISR); + IDPRINTF(2, ("%s: null intr- isr %x (%x) iptr %x optr %x\n", + isp->isp_name, isr, junk, iptr, optr)); } while (optr != iptr) { @@ -2633,24 +2710,6 @@ isp_intr(arg) if (XS_XFRLEN(xs)) { ISP_DMAFREE(isp, xs, sp->req_handle); } - /* - * Let the platforms cope. - */ -#if 0 - /* - * XXX: If we have a check condition, but no Sense Data, - * XXX: mark it as an error (ARQ failed). We need to - * XXX: to do a more distinct job because there may - * XXX: cases where ARQ is disabled. - */ - if (XS_STS(xs) == SCSI_CHECK && !(XS_IS_SNS_VALID(xs))) { - if (XS_NOERR(xs)) { - PRINTF("%s: ARQ failure for target %d lun %d\n", - isp->isp_name, XS_TGT(xs), XS_LUN(xs)); - XS_SETERR(xs, HBA_ARQFAIL); - } - } -#endif if ((isp->isp_dblev >= 5) || (isp->isp_dblev > 2 && !XS_NOERR(xs))) { PRINTF("%s(%d.%d): FIN dl%d resid%d STS %x", @@ -2679,6 +2738,7 @@ isp_intr(arg) ISP_WRITE(isp, INMAILBOX5, optr); isp->isp_reqodx = ISP_READ(isp, OUTMAILBOX4); } + isp->isp_residx = optr; for (i = 0; i < ndone; i++) { xs = complist[i]; @@ -2686,7 +2746,6 @@ isp_intr(arg) XS_CMD_DONE(xs); } } - ENABLE_INTS(isp); return (1); } @@ -3154,7 +3213,7 @@ isp_parse_status(isp, sp, xs) case RQCS_ARQS_FAILED: PRINTF("%s: Auto Request Sense failed for %d.%d.%d\n", - isp->isp_name, XS_TGT(xs), XS_LUN(xs), XS_CHANNEL(xs)); + isp->isp_name, XS_CHANNEL(xs), XS_TGT(xs), XS_LUN(xs)); return; case RQCS_WIDE_FAILED: @@ -3258,307 +3317,279 @@ isp_fastpost_complete(isp, fph) isp->isp_nactive--; } -#define HINIB(x) ((x) >> 0x4) -#define LONIB(x) ((x) & 0xf) -#define MAKNIB(a, b) (((a) << 4) | (b)) -static u_int8_t mbpcnt[] = { - MAKNIB(1, 1), /* 0x00: MBOX_NO_OP */ - MAKNIB(5, 5), /* 0x01: MBOX_LOAD_RAM */ - MAKNIB(2, 0), /* 0x02: MBOX_EXEC_FIRMWARE */ - MAKNIB(5, 5), /* 0x03: MBOX_DUMP_RAM */ - MAKNIB(3, 3), /* 0x04: MBOX_WRITE_RAM_WORD */ - MAKNIB(2, 3), /* 0x05: MBOX_READ_RAM_WORD */ - MAKNIB(6, 6), /* 0x06: MBOX_MAILBOX_REG_TEST */ - MAKNIB(2, 3), /* 0x07: MBOX_VERIFY_CHECKSUM */ - MAKNIB(1, 4), /* 0x08: MBOX_ABOUT_FIRMWARE */ - MAKNIB(0, 0), /* 0x09: */ - MAKNIB(0, 0), /* 0x0a: */ - MAKNIB(0, 0), /* 0x0b: */ - MAKNIB(0, 0), /* 0x0c: */ - MAKNIB(0, 0), /* 0x0d: */ - MAKNIB(1, 2), /* 0x0e: MBOX_CHECK_FIRMWARE */ - MAKNIB(0, 0), /* 0x0f: */ - MAKNIB(5, 5), /* 0x10: MBOX_INIT_REQ_QUEUE */ - MAKNIB(6, 6), /* 0x11: MBOX_INIT_RES_QUEUE */ - MAKNIB(4, 4), /* 0x12: MBOX_EXECUTE_IOCB */ - MAKNIB(2, 2), /* 0x13: MBOX_WAKE_UP */ - MAKNIB(1, 6), /* 0x14: MBOX_STOP_FIRMWARE */ - MAKNIB(4, 4), /* 0x15: MBOX_ABORT */ - MAKNIB(2, 2), /* 0x16: MBOX_ABORT_DEVICE */ - MAKNIB(3, 3), /* 0x17: MBOX_ABORT_TARGET */ - MAKNIB(3, 1), /* 0x18: MBOX_BUS_RESET */ - MAKNIB(2, 3), /* 0x19: MBOX_STOP_QUEUE */ - MAKNIB(2, 3), /* 0x1a: MBOX_START_QUEUE */ - MAKNIB(2, 3), /* 0x1b: MBOX_SINGLE_STEP_QUEUE */ - MAKNIB(2, 3), /* 0x1c: MBOX_ABORT_QUEUE */ - MAKNIB(2, 4), /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */ - MAKNIB(0, 0), /* 0x1e: */ - MAKNIB(1, 3), /* 0x1f: MBOX_GET_FIRMWARE_STATUS */ - MAKNIB(1, 4), /* 0x20: MBOX_GET_INIT_SCSI_ID, MBOX_GET_LOOP_ID */ - MAKNIB(1, 3), /* 0x21: MBOX_GET_SELECT_TIMEOUT */ - MAKNIB(1, 3), /* 0x22: MBOX_GET_RETRY_COUNT */ - MAKNIB(1, 2), /* 0x23: MBOX_GET_TAG_AGE_LIMIT */ - MAKNIB(1, 2), /* 0x24: MBOX_GET_CLOCK_RATE */ - MAKNIB(1, 2), /* 0x25: MBOX_GET_ACT_NEG_STATE */ - MAKNIB(1, 2), /* 0x26: MBOX_GET_ASYNC_DATA_SETUP_TIME */ - MAKNIB(1, 3), /* 0x27: MBOX_GET_PCI_PARAMS */ - MAKNIB(2, 4), /* 0x28: MBOX_GET_TARGET_PARAMS */ - MAKNIB(2, 4), /* 0x29: MBOX_GET_DEV_QUEUE_PARAMS */ - MAKNIB(1, 2), /* 0x2a: MBOX_GET_RESET_DELAY_PARAMS */ - MAKNIB(0, 0), /* 0x2b: */ - MAKNIB(0, 0), /* 0x2c: */ - MAKNIB(0, 0), /* 0x2d: */ - MAKNIB(0, 0), /* 0x2e: */ - MAKNIB(0, 0), /* 0x2f: */ - MAKNIB(2, 2), /* 0x30: MBOX_SET_INIT_SCSI_ID */ - MAKNIB(2, 3), /* 0x31: MBOX_SET_SELECT_TIMEOUT */ - MAKNIB(3, 3), /* 0x32: MBOX_SET_RETRY_COUNT */ - MAKNIB(2, 2), /* 0x33: MBOX_SET_TAG_AGE_LIMIT */ - MAKNIB(2, 2), /* 0x34: MBOX_SET_CLOCK_RATE */ - MAKNIB(2, 2), /* 0x35: MBOX_SET_ACT_NEG_STATE */ - MAKNIB(2, 2), /* 0x36: MBOX_SET_ASYNC_DATA_SETUP_TIME */ - MAKNIB(3, 3), /* 0x37: MBOX_SET_PCI_CONTROL_PARAMS */ - MAKNIB(4, 4), /* 0x38: MBOX_SET_TARGET_PARAMS */ - MAKNIB(4, 4), /* 0x39: MBOX_SET_DEV_QUEUE_PARAMS */ - MAKNIB(1, 2), /* 0x3a: MBOX_SET_RESET_DELAY_PARAMS */ - MAKNIB(0, 0), /* 0x3b: */ - MAKNIB(0, 0), /* 0x3c: */ - MAKNIB(0, 0), /* 0x3d: */ - MAKNIB(0, 0), /* 0x3e: */ - MAKNIB(0, 0), /* 0x3f: */ - MAKNIB(1, 2), /* 0x40: MBOX_RETURN_BIOS_BLOCK_ADDR */ - MAKNIB(6, 1), /* 0x41: MBOX_WRITE_FOUR_RAM_WORDS */ - MAKNIB(2, 3), /* 0x42: MBOX_EXEC_BIOS_IOCB */ - MAKNIB(0, 0), /* 0x43: */ - MAKNIB(0, 0), /* 0x44: */ - MAKNIB(0, 0), /* 0x45: */ - MAKNIB(0, 0), /* 0x46: */ - MAKNIB(0, 0), /* 0x47: */ - MAKNIB(0, 0), /* 0x48: */ - MAKNIB(0, 0), /* 0x49: */ - MAKNIB(2, 1), /* 0x4a: MBOX_SET_FIRMWARE_FEATURES */ - MAKNIB(1, 2), /* 0x4b: MBOX_GET_FIRMWARE_FEATURES */ - MAKNIB(0, 0), /* 0x4c: */ - MAKNIB(0, 0), /* 0x4d: */ - MAKNIB(0, 0), /* 0x4e: */ - MAKNIB(0, 0), /* 0x4f: */ - MAKNIB(0, 0), /* 0x50: */ - MAKNIB(0, 0), /* 0x51: */ - MAKNIB(0, 0), /* 0x52: */ - MAKNIB(0, 0), /* 0x53: */ - MAKNIB(8, 0), /* 0x54: MBOX_EXEC_COMMAND_IOCB_A64 */ - MAKNIB(2, 1), /* 0x55: MBOX_ENABLE_TARGET_MODE */ - MAKNIB(0, 0), /* 0x56: */ - MAKNIB(0, 0), /* 0x57: */ - MAKNIB(0, 0), /* 0x58: */ - MAKNIB(0, 0), /* 0x59: */ - MAKNIB(0, 0), /* 0x5a: */ - MAKNIB(0, 0), /* 0x5b: */ - MAKNIB(0, 0), /* 0x5c: */ - MAKNIB(0, 0), /* 0x5d: */ - MAKNIB(0, 0), /* 0x5e: */ - MAKNIB(0, 0), /* 0x5f: */ - MAKNIB(8, 6), /* 0x60: MBOX_INIT_FIRMWARE */ - MAKNIB(0, 0), /* 0x61: */ - MAKNIB(2, 1), /* 0x62: MBOX_INIT_LIP */ - MAKNIB(8, 1), /* 0x63: MBOX_GET_FC_AL_POSITION_MAP */ - MAKNIB(8, 1), /* 0x64: MBOX_GET_PORT_DB */ - MAKNIB(3, 1), /* 0x65: MBOX_CLEAR_ACA */ - MAKNIB(3, 1), /* 0x66: MBOX_TARGET_RESET */ - MAKNIB(3, 1), /* 0x67: MBOX_CLEAR_TASK_SET */ - MAKNIB(3, 1), /* 0x68: MBOX_ABORT_TASK_SET */ - MAKNIB(1, 2), /* 0x69: MBOX_GET_FW_STATE */ - MAKNIB(2, 8), /* 0x6a: MBOX_GET_PORT_NAME */ - MAKNIB(8, 1), /* 0x6b: MBOX_GET_LINK_STATUS */ - MAKNIB(4, 4), /* 0x6c: MBOX_INIT_LIP_RESET */ - MAKNIB(0, 0), /* 0x6d: */ - MAKNIB(8, 2), /* 0x6e: MBOX_SEND_SNS */ - MAKNIB(4, 3), /* 0x6f: MBOX_FABRIC_LOGIN */ - MAKNIB(2, 1), /* 0x70: MBOX_SEND_CHANGE_REQUEST */ - MAKNIB(2, 1), /* 0x71: MBOX_FABRIC_LOGOUT */ - MAKNIB(4, 1) /* 0x72: MBOX_INIT_LIP_LOGIN */ +#define HIBYT(x) ((x) >> 0x8) +#define LOBYT(x) ((x) & 0xff) +#define ISPOPMAP(a, b) (((a) << 8) | (b)) +static u_int16_t mbpscsi[] = { + ISPOPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */ + ISPOPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */ + ISPOPMAP(0x03, 0x01), /* 0x02: MBOX_EXEC_FIRMWARE */ + ISPOPMAP(0x1f, 0x01), /* 0x03: MBOX_DUMP_RAM */ + ISPOPMAP(0x07, 0x07), /* 0x04: MBOX_WRITE_RAM_WORD */ + ISPOPMAP(0x03, 0x07), /* 0x05: MBOX_READ_RAM_WORD */ + ISPOPMAP(0x3f, 0x3f), /* 0x06: MBOX_MAILBOX_REG_TEST */ + ISPOPMAP(0x03, 0x07), /* 0x07: MBOX_VERIFY_CHECKSUM */ + ISPOPMAP(0x01, 0x0f), /* 0x08: MBOX_ABOUT_FIRMWARE */ + ISPOPMAP(0x00, 0x00), /* 0x09: */ + ISPOPMAP(0x00, 0x00), /* 0x0a: */ + ISPOPMAP(0x00, 0x00), /* 0x0b: */ + ISPOPMAP(0x00, 0x00), /* 0x0c: */ + ISPOPMAP(0x00, 0x00), /* 0x0d: */ + ISPOPMAP(0x01, 0x05), /* 0x0e: MBOX_CHECK_FIRMWARE */ + ISPOPMAP(0x00, 0x00), /* 0x0f: */ + ISPOPMAP(0x1f, 0x1f), /* 0x10: MBOX_INIT_REQ_QUEUE */ + ISPOPMAP(0x3f, 0x3f), /* 0x11: MBOX_INIT_RES_QUEUE */ + ISPOPMAP(0x0f, 0x0f), /* 0x12: MBOX_EXECUTE_IOCB */ + ISPOPMAP(0x03, 0x03), /* 0x13: MBOX_WAKE_UP */ + ISPOPMAP(0x01, 0x3f), /* 0x14: MBOX_STOP_FIRMWARE */ + ISPOPMAP(0x0f, 0x0f), /* 0x15: MBOX_ABORT */ + ISPOPMAP(0x03, 0x03), /* 0x16: MBOX_ABORT_DEVICE */ + ISPOPMAP(0x07, 0x07), /* 0x17: MBOX_ABORT_TARGET */ + ISPOPMAP(0x07, 0x07), /* 0x18: MBOX_BUS_RESET */ + ISPOPMAP(0x03, 0x07), /* 0x19: MBOX_STOP_QUEUE */ + ISPOPMAP(0x03, 0x07), /* 0x1a: MBOX_START_QUEUE */ + ISPOPMAP(0x03, 0x07), /* 0x1b: MBOX_SINGLE_STEP_QUEUE */ + ISPOPMAP(0x03, 0x07), /* 0x1c: MBOX_ABORT_QUEUE */ + ISPOPMAP(0x03, 0x4f), /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */ + ISPOPMAP(0x00, 0x00), /* 0x1e: */ + ISPOPMAP(0x01, 0x07), /* 0x1f: MBOX_GET_FIRMWARE_STATUS */ + ISPOPMAP(0x01, 0x07), /* 0x20: MBOX_GET_INIT_SCSI_ID */ + ISPOPMAP(0x01, 0x07), /* 0x21: MBOX_GET_SELECT_TIMEOUT */ + ISPOPMAP(0x01, 0xc7), /* 0x22: MBOX_GET_RETRY_COUNT */ + ISPOPMAP(0x01, 0x07), /* 0x23: MBOX_GET_TAG_AGE_LIMIT */ + ISPOPMAP(0x01, 0x03), /* 0x24: MBOX_GET_CLOCK_RATE */ + ISPOPMAP(0x01, 0x07), /* 0x25: MBOX_GET_ACT_NEG_STATE */ + ISPOPMAP(0x01, 0x07), /* 0x26: MBOX_GET_ASYNC_DATA_SETUP_TIME */ + ISPOPMAP(0x01, 0x07), /* 0x27: MBOX_GET_PCI_PARAMS */ + ISPOPMAP(0x03, 0x4f), /* 0x28: MBOX_GET_TARGET_PARAMS */ + ISPOPMAP(0x03, 0x0f), /* 0x29: MBOX_GET_DEV_QUEUE_PARAMS */ + ISPOPMAP(0x01, 0x07), /* 0x2a: MBOX_GET_RESET_DELAY_PARAMS */ + ISPOPMAP(0x00, 0x00), /* 0x2b: */ + ISPOPMAP(0x00, 0x00), /* 0x2c: */ + ISPOPMAP(0x00, 0x00), /* 0x2d: */ + ISPOPMAP(0x00, 0x00), /* 0x2e: */ + ISPOPMAP(0x00, 0x00), /* 0x2f: */ + ISPOPMAP(0x03, 0x03), /* 0x30: MBOX_SET_INIT_SCSI_ID */ + ISPOPMAP(0x07, 0x07), /* 0x31: MBOX_SET_SELECT_TIMEOUT */ + ISPOPMAP(0xc7, 0xc7), /* 0x32: MBOX_SET_RETRY_COUNT */ + ISPOPMAP(0x07, 0x07), /* 0x33: MBOX_SET_TAG_AGE_LIMIT */ + ISPOPMAP(0x03, 0x03), /* 0x34: MBOX_SET_CLOCK_RATE */ + ISPOPMAP(0x07, 0x07), /* 0x35: MBOX_SET_ACT_NEG_STATE */ + ISPOPMAP(0x07, 0x07), /* 0x36: MBOX_SET_ASYNC_DATA_SETUP_TIME */ + ISPOPMAP(0x07, 0x07), /* 0x37: MBOX_SET_PCI_CONTROL_PARAMS */ + ISPOPMAP(0x4f, 0x4f), /* 0x38: MBOX_SET_TARGET_PARAMS */ + ISPOPMAP(0x0f, 0x0f), /* 0x39: MBOX_SET_DEV_QUEUE_PARAMS */ + ISPOPMAP(0x07, 0x07), /* 0x3a: MBOX_SET_RESET_DELAY_PARAMS */ + ISPOPMAP(0x00, 0x00), /* 0x3b: */ + ISPOPMAP(0x00, 0x00), /* 0x3c: */ + ISPOPMAP(0x00, 0x00), /* 0x3d: */ + ISPOPMAP(0x00, 0x00), /* 0x3e: */ + ISPOPMAP(0x00, 0x00), /* 0x3f: */ + ISPOPMAP(0x01, 0x03), /* 0x40: MBOX_RETURN_BIOS_BLOCK_ADDR */ + ISPOPMAP(0x3f, 0x01), /* 0x41: MBOX_WRITE_FOUR_RAM_WORDS */ + ISPOPMAP(0x03, 0x07), /* 0x42: MBOX_EXEC_BIOS_IOCB */ + ISPOPMAP(0x00, 0x00), /* 0x43: */ + ISPOPMAP(0x00, 0x00), /* 0x44: */ + ISPOPMAP(0x03, 0x03), /* 0x45: SET SYSTEM PARAMETER */ + ISPOPMAP(0x01, 0x03), /* 0x46: GET SYSTEM PARAMETER */ + ISPOPMAP(0x00, 0x00), /* 0x47: */ + ISPOPMAP(0x01, 0xcf), /* 0x48: GET SCAM CONFIGURATION */ + ISPOPMAP(0xcf, 0xcf), /* 0x49: SET SCAM CONFIGURATION */ + ISPOPMAP(0x03, 0x03), /* 0x4a: MBOX_SET_FIRMWARE_FEATURES */ + ISPOPMAP(0x01, 0x03), /* 0x4b: MBOX_GET_FIRMWARE_FEATURES */ + ISPOPMAP(0x00, 0x00), /* 0x4c: */ + ISPOPMAP(0x00, 0x00), /* 0x4d: */ + ISPOPMAP(0x00, 0x00), /* 0x4e: */ + ISPOPMAP(0x00, 0x00), /* 0x4f: */ + ISPOPMAP(0xdf, 0xdf), /* 0x50: LOAD RAM A64 */ + ISPOPMAP(0xdf, 0xdf), /* 0x51: DUMP RAM A64 */ + ISPOPMAP(0xdf, 0xdf), /* 0x52: INITIALIZE REQUEST QUEUE A64 */ + ISPOPMAP(0xff, 0xff), /* 0x53: INITIALIZE RESPONSE QUEUE A64 */ + ISPOPMAP(0xcf, 0xff), /* 0x54: EXECUTE IOCB A64 */ + ISPOPMAP(0x03, 0x01), /* 0x55: ENABLE TARGET MODE */ + ISPOPMAP(0x00, 0x00), /* 0x56: */ + ISPOPMAP(0x00, 0x00), /* 0x57: */ + ISPOPMAP(0x00, 0x00), /* 0x58: */ + ISPOPMAP(0x00, 0x00), /* 0x59: */ + ISPOPMAP(0x03, 0x03), /* 0x5a: SET DATA OVERRUN RECOVERY MODE */ + ISPOPMAP(0x01, 0x03), /* 0x5b: GET DATA OVERRUN RECOVERY MODE */ + ISPOPMAP(0x0f, 0x0f), /* 0x5c: SET HOST DATA */ + ISPOPMAP(0x01, 0x01) /* 0x5d: GET NOST DATA */ +}; + +static u_int16_t mbpfc[] = { + ISPOPMAP(0x01, 0x01), /* 0x00: MBOX_NO_OP */ + ISPOPMAP(0x1f, 0x01), /* 0x01: MBOX_LOAD_RAM */ + ISPOPMAP(0x03, 0x01), /* 0x02: MBOX_EXEC_FIRMWARE */ + ISPOPMAP(0x1f, 0x01), /* 0x03: MBOX_DUMP_RAM */ + ISPOPMAP(0x07, 0x07), /* 0x04: MBOX_WRITE_RAM_WORD */ + ISPOPMAP(0x03, 0x07), /* 0x05: MBOX_READ_RAM_WORD */ + ISPOPMAP(0xff, 0xff), /* 0x06: MBOX_MAILBOX_REG_TEST */ + ISPOPMAP(0x03, 0x05), /* 0x07: MBOX_VERIFY_CHECKSUM */ + ISPOPMAP(0x01, 0x0f), /* 0x08: MBOX_ABOUT_FIRMWARE */ + ISPOPMAP(0xdf, 0x01), /* 0x09: LOAD RAM */ + ISPOPMAP(0xdf, 0x01), /* 0x0a: DUMP RAM */ + ISPOPMAP(0x00, 0x00), /* 0x0b: */ + ISPOPMAP(0x00, 0x00), /* 0x0c: */ + ISPOPMAP(0x00, 0x00), /* 0x0d: */ + ISPOPMAP(0x01, 0x05), /* 0x0e: MBOX_CHECK_FIRMWARE */ + ISPOPMAP(0x00, 0x00), /* 0x0f: */ + ISPOPMAP(0x1f, 0x11), /* 0x10: MBOX_INIT_REQ_QUEUE */ + ISPOPMAP(0x2f, 0x21), /* 0x11: MBOX_INIT_RES_QUEUE */ + ISPOPMAP(0x0f, 0x01), /* 0x12: MBOX_EXECUTE_IOCB */ + ISPOPMAP(0x03, 0x03), /* 0x13: MBOX_WAKE_UP */ + ISPOPMAP(0x01, 0xff), /* 0x14: MBOX_STOP_FIRMWARE */ + ISPOPMAP(0x4f, 0x01), /* 0x15: MBOX_ABORT */ + ISPOPMAP(0x07, 0x01), /* 0x16: MBOX_ABORT_DEVICE */ + ISPOPMAP(0x07, 0x01), /* 0x17: MBOX_ABORT_TARGET */ + ISPOPMAP(0x03, 0x03), /* 0x18: MBOX_BUS_RESET */ + ISPOPMAP(0x07, 0x05), /* 0x19: MBOX_STOP_QUEUE */ + ISPOPMAP(0x07, 0x05), /* 0x1a: MBOX_START_QUEUE */ + ISPOPMAP(0x07, 0x05), /* 0x1b: MBOX_SINGLE_STEP_QUEUE */ + ISPOPMAP(0x07, 0x05), /* 0x1c: MBOX_ABORT_QUEUE */ + ISPOPMAP(0x07, 0x03), /* 0x1d: MBOX_GET_DEV_QUEUE_STATUS */ + ISPOPMAP(0x00, 0x00), /* 0x1e: */ + ISPOPMAP(0x01, 0x07), /* 0x1f: MBOX_GET_FIRMWARE_STATUS */ + ISPOPMAP(0x01, 0x4f), /* 0x20: MBOX_GET_LOOP_ID */ + ISPOPMAP(0x00, 0x00), /* 0x21: */ + ISPOPMAP(0x01, 0x07), /* 0x22: MBOX_GET_RETRY_COUNT */ + ISPOPMAP(0x00, 0x00), /* 0x23: */ + ISPOPMAP(0x00, 0x00), /* 0x24: */ + ISPOPMAP(0x00, 0x00), /* 0x25: */ + ISPOPMAP(0x00, 0x00), /* 0x26: */ + ISPOPMAP(0x00, 0x00), /* 0x27: */ + ISPOPMAP(0x0f, 0x1), /* 0x28: MBOX_GET_FIRMWARE_OPTIONS */ + ISPOPMAP(0x03, 0x07), /* 0x29: MBOX_GET_PORT_QUEUE_PARAMS */ + ISPOPMAP(0x00, 0x00), /* 0x2a: */ + ISPOPMAP(0x00, 0x00), /* 0x2b: */ + ISPOPMAP(0x00, 0x00), /* 0x2c: */ + ISPOPMAP(0x00, 0x00), /* 0x2d: */ + ISPOPMAP(0x00, 0x00), /* 0x2e: */ + ISPOPMAP(0x00, 0x00), /* 0x2f: */ + ISPOPMAP(0x00, 0x00), /* 0x30: */ + ISPOPMAP(0x00, 0x00), /* 0x31: */ + ISPOPMAP(0x07, 0x07), /* 0x32: MBOX_SET_RETRY_COUNT */ + ISPOPMAP(0x00, 0x00), /* 0x33: */ + ISPOPMAP(0x00, 0x00), /* 0x34: */ + ISPOPMAP(0x00, 0x00), /* 0x35: */ + ISPOPMAP(0x00, 0x00), /* 0x36: */ + ISPOPMAP(0x00, 0x00), /* 0x37: */ + ISPOPMAP(0x0f, 0x01), /* 0x38: MBOX_SET_FIRMWARE_OPTIONS */ + ISPOPMAP(0x0f, 0x07), /* 0x39: MBOX_SET_PORT_QUEUE_PARAMS */ + ISPOPMAP(0x00, 0x00), /* 0x3a: */ + ISPOPMAP(0x00, 0x00), /* 0x3b: */ + ISPOPMAP(0x00, 0x00), /* 0x3c: */ + ISPOPMAP(0x00, 0x00), /* 0x3d: */ + ISPOPMAP(0x00, 0x00), /* 0x3e: */ + ISPOPMAP(0x00, 0x00), /* 0x3f: */ + ISPOPMAP(0x03, 0x01), /* 0x40: MBOX_LOOP_PORT_BYPASS */ + ISPOPMAP(0x03, 0x01), /* 0x41: MBOX_LOOP_PORT_ENABLE */ + ISPOPMAP(0x03, 0x07), /* 0x42: MBOX_GET_RESOURCE_COUNTS */ + ISPOPMAP(0x01, 0x01), /* 0x43: MBOX_REQUEST_NON_PARTICIPATING_MODE */ + ISPOPMAP(0x00, 0x00), /* 0x44: */ + ISPOPMAP(0x00, 0x00), /* 0x45: */ + ISPOPMAP(0x00, 0x00), /* 0x46: */ + ISPOPMAP(0xcf, 0x03), /* 0x47: GET PORT_DATABASE ENHANCED */ + ISPOPMAP(0x00, 0x00), /* 0x48: */ + ISPOPMAP(0x00, 0x00), /* 0x49: */ + ISPOPMAP(0x00, 0x00), /* 0x4a: */ + ISPOPMAP(0x00, 0x00), /* 0x4b: */ + ISPOPMAP(0x00, 0x00), /* 0x4c: */ + ISPOPMAP(0x00, 0x00), /* 0x4d: */ + ISPOPMAP(0x00, 0x00), /* 0x4e: */ + ISPOPMAP(0x00, 0x00), /* 0x4f: */ + ISPOPMAP(0x00, 0x00), /* 0x50: */ + ISPOPMAP(0x00, 0x00), /* 0x51: */ + ISPOPMAP(0x00, 0x00), /* 0x52: */ + ISPOPMAP(0x00, 0x00), /* 0x53: */ + ISPOPMAP(0xcf, 0x01), /* 0x54: EXECUTE IOCB A64 */ + ISPOPMAP(0x00, 0x00), /* 0x55: */ + ISPOPMAP(0x00, 0x00), /* 0x56: */ + ISPOPMAP(0x00, 0x00), /* 0x57: */ + ISPOPMAP(0x00, 0x00), /* 0x58: */ + ISPOPMAP(0x00, 0x00), /* 0x59: */ + ISPOPMAP(0x00, 0x00), /* 0x5a: */ + ISPOPMAP(0x00, 0x00), /* 0x5b: */ + ISPOPMAP(0x00, 0x00), /* 0x5c: */ + ISPOPMAP(0x00, 0x00), /* 0x5d: */ + ISPOPMAP(0x00, 0x00), /* 0x5e: */ + ISPOPMAP(0x00, 0x00), /* 0x5f: */ + ISPOPMAP(0xfd, 0x31), /* 0x60: MBOX_INIT_FIRMWARE */ + ISPOPMAP(0x00, 0x00), /* 0x61: */ + ISPOPMAP(0x01, 0x01), /* 0x62: MBOX_INIT_LIP */ + ISPOPMAP(0xcd, 0x03), /* 0x63: MBOX_GET_FC_AL_POSITION_MAP */ + ISPOPMAP(0xcf, 0x01), /* 0x64: MBOX_GET_PORT_DB */ + ISPOPMAP(0x07, 0x01), /* 0x65: MBOX_CLEAR_ACA */ + ISPOPMAP(0x07, 0x01), /* 0x66: MBOX_TARGET_RESET */ + ISPOPMAP(0x07, 0x01), /* 0x67: MBOX_CLEAR_TASK_SET */ + ISPOPMAP(0x07, 0x01), /* 0x68: MBOX_ABORT_TASK_SET */ + ISPOPMAP(0x01, 0x07), /* 0x69: MBOX_GET_FW_STATE */ + ISPOPMAP(0x03, 0xcf), /* 0x6a: MBOX_GET_PORT_NAME */ + ISPOPMAP(0xcf, 0x01), /* 0x6b: MBOX_GET_LINK_STATUS */ + ISPOPMAP(0x0f, 0x01), /* 0x6c: MBOX_INIT_LIP_RESET */ + ISPOPMAP(0x00, 0x00), /* 0x6d: */ + ISPOPMAP(0xcf, 0x03), /* 0x6e: MBOX_SEND_SNS */ + ISPOPMAP(0x0f, 0x07), /* 0x6f: MBOX_FABRIC_LOGIN */ + ISPOPMAP(0x03, 0x01), /* 0x70: MBOX_SEND_CHANGE_REQUEST */ + ISPOPMAP(0x03, 0x03), /* 0x71: MBOX_FABRIC_LOGOUT */ + ISPOPMAP(0x0f, 0x0f), /* 0x72: MBOX_INIT_LIP_LOGIN */ + ISPOPMAP(0x00, 0x00), /* 0x73: */ + ISPOPMAP(0x07, 0x01), /* 0x74: LOGIN LOOP PORT */ + ISPOPMAP(0xcf, 0x03), /* 0x75: GET PORT/NODE NAME LIST */ + ISPOPMAP(0x4f, 0x01), /* 0x76: SET VENDOR ID */ + ISPOPMAP(0xcd, 0x01), /* 0x77: INITIALIZE IP MAILBOX */ + ISPOPMAP(0x00, 0x00), /* 0x78: */ + ISPOPMAP(0x00, 0x00), /* 0x79: */ + ISPOPMAP(0x00, 0x00), /* 0x7a: */ + ISPOPMAP(0x00, 0x00), /* 0x7b: */ + ISPOPMAP(0x4f, 0x03), /* 0x7c: Get ID List */ + ISPOPMAP(0xcf, 0x01), /* 0x7d: SEND LFA */ + ISPOPMAP(0x07, 0x01) /* 0x7e: Lun RESET */ }; -#define NMBCOM (sizeof (mbpcnt) / sizeof (mbpcnt[0])) static void isp_mboxcmd(isp, mbp) struct ispsoftc *isp; mbreg_t *mbp; { - int outparam, inparam; - int loops, dld = 0; - u_int8_t opcode; + unsigned int lim, ibits, obits, box, opcode; + u_int16_t *mcp; - if (mbp->param[0] == ISP2100_SET_PCI_PARAM) { - opcode = mbp->param[0] = MBOX_SET_PCI_PARAMETERS; - inparam = 4; - outparam = 4; - goto command_known; - } else if (mbp->param[0] > NMBCOM) { - PRINTF("%s: bad command %x\n", isp->isp_name, mbp->param[0]); + if (IS_FC(isp)) { + mcp = mbpfc; + lim = (sizeof (mbpfc) / sizeof (mbpfc[0])); + } else { + mcp = mbpscsi; + lim = (sizeof (mbpscsi) / sizeof (mbpscsi[0])); + } + + if ((opcode = mbp->param[0]) >= lim) { + mbp->param[0] = MBOX_INVALID_COMMAND; + PRINTF("%s: unknown command 0x%x\n", isp->isp_name, opcode); return; } - opcode = mbp->param[0]; - inparam = HINIB(mbpcnt[mbp->param[0]]); - outparam = LONIB(mbpcnt[mbp->param[0]]); + ibits = HIBYT(mcp[opcode]) & NMBOX_BMASK(isp); + obits = LOBYT(mcp[opcode]) & NMBOX_BMASK(isp); - if (inparam == 0 && outparam == 0) { - PRINTF("%s: no parameters for %x\n", isp->isp_name, - mbp->param[0]); + if (ibits == 0 && obits == 0) { + mbp->param[0] = MBOX_COMMAND_PARAM_ERROR; + PRINTF("%s: no parameters for opcode 0x%x\n", isp->isp_name, + opcode); return; } - - /* - * Check for variants - */ - if (IS_FC(isp) && isp->isp_maxluns > 16) { - switch (mbp->param[0]) { - case MBOX_ABORT: - inparam = 7; - break; - case MBOX_ABORT_DEVICE: - case MBOX_START_QUEUE: - case MBOX_STOP_QUEUE: - case MBOX_SINGLE_STEP_QUEUE: - case MBOX_ABORT_QUEUE: - case MBOX_GET_DEV_QUEUE_STATUS: - inparam = 3; - break; - case MBOX_BUS_RESET: - inparam = 2; - break; - default: - break; - } - } - -command_known: - - /* - * Set semaphore on mailbox registers to win any races to acquire them. - */ - ISP_WRITE(isp, BIU_SEMA, 1); - - /* - * Qlogic Errata for the ISP2100 says that there is a necessary - * debounce between between writing the semaphore register - * and reading a mailbox register. I believe we're okay here. - */ - - /* - * Make sure we can send some words. - * Check to see if there's an async mbox event pending. - */ - - loops = MBOX_DELAY_COUNT; - while ((ISP_READ(isp, HCCR) & HCCR_HOST_INT) != 0) { - if (ISP_READ(isp, BIU_SEMA) & 1) { - int fph; - u_int16_t mbox = ISP_READ(isp, OUTMAILBOX0); - /* - * We have a pending MBOX async event. - */ - if (mbox & 0x8000) { - fph = isp_parse_async(isp, (int) mbox); - IDPRINTF(5, ("%s: line %d, fph %d\n", - isp->isp_name, __LINE__, fph)); - ISP_WRITE(isp, BIU_SEMA, 0); - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - if (fph < 0) { - return; - } else if (fph > 0) { - isp_fastpost_complete(isp, fph); - } - SYS_DELAY(100); - goto command_known; - } - /* - * We have a pending MBOX completion? Might be - * from a previous command. We can't (sometimes) - * just clear HOST INTERRUPT, so we'll just silently - * eat this here. - */ - if (mbox & 0x4000) { - IDPRINTF(5, ("%s: line %d, mbox 0x%x\n", - isp->isp_name, __LINE__, mbox)); - ISP_WRITE(isp, BIU_SEMA, 0); - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - SYS_DELAY(100); - goto command_known; - } - } - SYS_DELAY(100); - if (--loops < 0) { - if (dld++ > 10) { - PRINTF("%s: isp_mboxcmd could not get command " - "started\n", isp->isp_name); - return; - } - ISP_WRITE(isp, BIU_SEMA, 0); - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - goto command_known; + for (box = 0; box < MAX_MAILBOX; box++) { + if (ibits & (1 << box)) { + ISP_WRITE(isp, MBOX_OFF(box), mbp->param[box]); } + isp->isp_mboxtmp[box] = mbp->param[box] = 0; } /* - * Write input parameters. - * - * Special case some of the setups for the dual port SCSI cards. - * XXX Eventually will be fixed by converting register write/read - * XXX counts to bitmasks. + * We assume that we can't overwrite a previous command. */ - if (IS_DUALBUS(isp)) { - switch (opcode) { - case MBOX_GET_RETRY_COUNT: - case MBOX_SET_RETRY_COUNT: - ISP_WRITE(isp, INMAILBOX7, mbp->param[7]); - mbp->param[7] = 0; - ISP_WRITE(isp, INMAILBOX6, mbp->param[6]); - mbp->param[6] = 0; - break; - case MBOX_SET_ASYNC_DATA_SETUP_TIME: - case MBOX_SET_ACT_NEG_STATE: - case MBOX_SET_TAG_AGE_LIMIT: - case MBOX_SET_SELECT_TIMEOUT: - ISP_WRITE(isp, INMAILBOX2, mbp->param[2]); - mbp->param[2] = 0; - break; - } - } - - switch (inparam) { - case 8: ISP_WRITE(isp, INMAILBOX7, mbp->param[7]); mbp->param[7] = 0; - case 7: ISP_WRITE(isp, INMAILBOX6, mbp->param[6]); mbp->param[6] = 0; - case 6: - /* - * The Qlogic 2100 cannot have registers 4 and 5 written to - * after initialization or BAD THINGS HAPPEN (tm). - */ - if (IS_SCSI(isp) || mbp->param[0] == MBOX_INIT_FIRMWARE) - ISP_WRITE(isp, INMAILBOX5, mbp->param[5]); - mbp->param[5] = 0; - case 5: - if (IS_SCSI(isp) || mbp->param[0] == MBOX_INIT_FIRMWARE) - ISP_WRITE(isp, INMAILBOX4, mbp->param[4]); - mbp->param[4] = 0; - case 4: ISP_WRITE(isp, INMAILBOX3, mbp->param[3]); mbp->param[3] = 0; - case 3: ISP_WRITE(isp, INMAILBOX2, mbp->param[2]); mbp->param[2] = 0; - case 2: ISP_WRITE(isp, INMAILBOX1, mbp->param[1]); mbp->param[1] = 0; - case 1: ISP_WRITE(isp, INMAILBOX0, mbp->param[0]); mbp->param[0] = 0; - } - - /* - * Clear RISC int condition. - */ - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - - /* - * Clear semaphore on mailbox registers so that the Qlogic - * may update outgoing registers. - */ - ISP_WRITE(isp, BIU_SEMA, 0); + isp->isp_mboxbsy = obits; /* * Set Host Interrupt condition so that RISC will pick up mailbox regs. @@ -3566,121 +3597,30 @@ command_known: ISP_WRITE(isp, HCCR, HCCR_CMD_SET_HOST_INT); /* - * Wait until HOST INT has gone away (meaning that the Qlogic - * has picked up the mailbox command. Wait a long time. + * Give the f/w a chance to pick this up. */ - loops = MBOX_DELAY_COUNT * 5; - while ((ISP_READ(isp, HCCR) & HCCR_CMD_CLEAR_RISC_INT) != 0) { - SYS_DELAY(100); - if (--loops < 0) { - PRINTF("%s: isp_mboxcmd timeout #2\n", isp->isp_name); - return; - } - } + SYS_DELAY(250); + /* - * While the Semaphore registers isn't set, wait for the Qlogic - * to process the mailbox command. Again- wait a long time. + * While we haven't finished the command, spin our wheels here. */ - loops = MBOX_DELAY_COUNT * 5; - while ((ISP_READ(isp, BIU_SEMA) & 1) == 0) { - SYS_DELAY(100); - /* - * Wierd- I've seen the case where the semaphore register - * isn't getting set- sort of a violation of the protocol.. - */ - if (ISP_READ(isp, OUTMAILBOX0) & 0x4000) - break; - if (--loops < 0) { - PRINTF("%s: isp_mboxcmd timeout #3\n", isp->isp_name); - return; + + do { + if (isp_intr(isp) == 0) { + SYS_DELAY(500); } - } + } while (isp->isp_mboxbsy != 0); /* - * Make sure that the MBOX_BUSY has gone away + * Copy back output registers. */ - loops = MBOX_DELAY_COUNT; - for (;;) { - u_int16_t mbox = ISP_READ(isp, OUTMAILBOX0); - if (mbox == MBOX_BUSY) { - if (--loops < 0) { - PRINTF("%s: isp_mboxcmd timeout #4\n", - isp->isp_name); - return; - } - SYS_DELAY(100); - continue; - } - /* - * We have a pending MBOX async event. - */ - if (mbox & 0x8000) { - int fph = isp_parse_async(isp, (int) mbox); - ISP_WRITE(isp, BIU_SEMA, 0); - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - if (fph < 0) { - return; - } else if (fph > 0) { - isp_fastpost_complete(isp, fph); - } - SYS_DELAY(100); - continue; - } - break; - } - - /* - * Pick up output parameters. Special case some of the readbacks - * for the dual port SCSI cards. - */ - if (IS_DUALBUS(isp)) { - switch (opcode) { - case MBOX_GET_RETRY_COUNT: - case MBOX_SET_RETRY_COUNT: - mbp->param[7] = ISP_READ(isp, OUTMAILBOX7); - mbp->param[6] = ISP_READ(isp, OUTMAILBOX6); - break; - case MBOX_GET_TAG_AGE_LIMIT: - case MBOX_SET_TAG_AGE_LIMIT: - case MBOX_GET_ACT_NEG_STATE: - case MBOX_SET_ACT_NEG_STATE: - case MBOX_SET_ASYNC_DATA_SETUP_TIME: - case MBOX_GET_ASYNC_DATA_SETUP_TIME: - case MBOX_GET_RESET_DELAY_PARAMS: - case MBOX_SET_RESET_DELAY_PARAMS: - mbp->param[2] = ISP_READ(isp, OUTMAILBOX2); - break; + for (box = 0; box < MAX_MAILBOX; box++) { + if (obits & (1 << box)) { + mbp->param[box] = isp->isp_mboxtmp[box]; } } - if (IS_2200(isp)) { - if (opcode == MBOX_GET_LOOP_ID) { - mbp->param[6] = ISP_READ(isp, OUTMAILBOX6); - } - } - - switch (outparam) { - case 8: mbp->param[7] = ISP_READ(isp, OUTMAILBOX7); - case 7: mbp->param[6] = ISP_READ(isp, OUTMAILBOX6); - case 6: mbp->param[5] = ISP_READ(isp, OUTMAILBOX5); - case 5: mbp->param[4] = ISP_READ(isp, OUTMAILBOX4); - case 4: mbp->param[3] = ISP_READ(isp, OUTMAILBOX3); - case 3: mbp->param[2] = ISP_READ(isp, OUTMAILBOX2); - case 2: mbp->param[1] = ISP_READ(isp, OUTMAILBOX1); - case 1: mbp->param[0] = ISP_READ(isp, OUTMAILBOX0); - } - - /* - * Clear RISC int. - */ - ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT); - - /* - * Release semaphore on mailbox registers - */ - ISP_WRITE(isp, BIU_SEMA, 0); - /* * Just to be chatty here... */ @@ -3721,30 +3661,6 @@ command_known: case MBOX_ALL_IDS_USED: break; - - /* - * Be silent about these... - */ - case ASYNC_PDB_CHANGED: - ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_PDB_RCVD; - break; - - case ASYNC_LIP_OCCURRED: - ((fcparam *) isp->isp_param)->isp_lipseq = mbp->param[1]; - /* FALLTHROUGH */ - case ASYNC_LOOP_UP: - ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT; - ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_LIP_RCVD; - break; - - case ASYNC_LOOP_DOWN: - case ASYNC_LOOP_RESET: - ((fcparam *) isp->isp_param)->isp_fwstate = FW_CONFIG_WAIT; - ((fcparam *) isp->isp_param)->isp_loopstate = LOOP_NIL; - /* FALLTHROUGH */ - case ASYNC_CHANGE_NOTIFY: - break; - default: /* * The expected return of EXEC_FIRMWARE is zero. @@ -4215,9 +4131,6 @@ isp_restart(isp) ISP_SCSI_XFER_T *xs; u_int32_t handle; -#if 0 - isp->isp_gotdparms = 0; -#endif isp_reset(isp); if (isp->isp_state == ISP_RESETSTATE) { isp_init(isp);