diff options
| author | Alexander Motin <mav@FreeBSD.org> | 2017-03-14 08:03:56 +0000 |
|---|---|---|
| committer | Alexander Motin <mav@FreeBSD.org> | 2017-03-14 08:03:56 +0000 |
| commit | a1fa02673afaed21473adc4633faac57b554acc0 (patch) | |
| tree | 17548ba20920729ca4bef84e31cb17e11b357cb7 /sys/dev/isp | |
| parent | 3667f39ea3bcb716a7e6dc3ebd973e4cac6980f0 (diff) | |
Notes
Diffstat (limited to 'sys/dev/isp')
| -rw-r--r-- | sys/dev/isp/isp.c | 192 | ||||
| -rw-r--r-- | sys/dev/isp/isp_freebsd.c | 17 | ||||
| -rw-r--r-- | sys/dev/isp/isp_freebsd.h | 1 | ||||
| -rw-r--r-- | sys/dev/isp/isp_library.c | 22 | ||||
| -rw-r--r-- | sys/dev/isp/isp_library.h | 5 | ||||
| -rw-r--r-- | sys/dev/isp/isp_pci.c | 290 | ||||
| -rw-r--r-- | sys/dev/isp/isp_sbus.c | 154 | ||||
| -rw-r--r-- | sys/dev/isp/ispvar.h | 24 |
8 files changed, 314 insertions, 391 deletions
diff --git a/sys/dev/isp/isp.c b/sys/dev/isp/isp.c index 44281cec608c0..87c1dd9460725 100644 --- a/sys/dev/isp/isp.c +++ b/sys/dev/isp/isp.c @@ -178,13 +178,6 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) const char *btype = "????"; static const char dcrc[] = "Downloaded RISC Code Checksum Failure"; - isp->isp_state = ISP_NILSTATE; - if (isp->isp_dead) { - isp_shutdown(isp); - ISP_DISABLE_INTS(isp); - return; - } - /* * Basic types (SCSI, FibreChannel and PCI or SBus) * have been set in the MD code. We figure out more @@ -195,56 +188,10 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) * for SCSI adapters and do other settings for the 2100. */ + isp->isp_state = ISP_NILSTATE; ISP_DISABLE_INTS(isp); /* - * Pick an initial maxcmds value which will be used - * to allocate xflist pointer space. It may be changed - * later by the firmware. - */ - if (IS_24XX(isp)) { - isp->isp_maxcmds = 4096; - } else if (IS_2322(isp)) { - isp->isp_maxcmds = 2048; - } else if (IS_23XX(isp) || IS_2200(isp)) { - isp->isp_maxcmds = 1024; - } else { - isp->isp_maxcmds = 512; - } - - /* - * Set up DMA for the request and response queues. - * - * We do this now so we can use the request queue - * for dma to load firmware from. - */ - if (ISP_MBOXDMASETUP(isp) != 0) { - isp_prt(isp, ISP_LOGERR, "Cannot setup DMA"); - return; - } - - /* - * Set up default request/response queue in-pointer/out-pointer - * register indices. - */ - if (IS_24XX(isp)) { - isp->isp_rqstinrp = BIU2400_REQINP; - isp->isp_rqstoutrp = BIU2400_REQOUTP; - isp->isp_respinrp = BIU2400_RSPINP; - isp->isp_respoutrp = BIU2400_RSPOUTP; - } else if (IS_23XX(isp)) { - isp->isp_rqstinrp = BIU_REQINP; - isp->isp_rqstoutrp = BIU_REQOUTP; - isp->isp_respinrp = BIU_RSPINP; - isp->isp_respoutrp = BIU_RSPOUTP; - } else { - isp->isp_rqstinrp = INMAILBOX4; - isp->isp_rqstoutrp = OUTMAILBOX4; - isp->isp_respinrp = OUTMAILBOX5; - isp->isp_respoutrp = INMAILBOX5; - } - - /* * Put the board into PAUSE mode (so we can read the SXP registers * or write FPM/FBM registers). */ @@ -468,7 +415,6 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) isp->isp_clock = isp->isp_mdvec->dv_clock; } } - } /* @@ -477,11 +423,6 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) isp->isp_intcnt = isp->isp_intbogus = 0; /* - * Do MD specific pre initialization - */ - ISP_RESET0(isp); - - /* * Hit the chip over the head with hammer, * and give it a chance to recover. */ @@ -513,7 +454,6 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) } } if (val & BIU2400_DMA_ACTIVE) { - ISP_RESET0(isp); isp_prt(isp, ISP_LOGERR, "DMA Failed to Stop on Reset"); return; } @@ -533,7 +473,6 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) } } if (val & BIU2400_SOFT_RESET) { - ISP_RESET0(isp); isp_prt(isp, ISP_LOGERR, "Failed to come out of reset"); return; } @@ -572,7 +511,6 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) ISP_DELAY(100); if (--loops < 0) { ISP_DUMPREGS(isp, "chip reset timed out"); - ISP_RESET0(isp); return; } } @@ -613,7 +551,6 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) } } if (val != 0) { - ISP_RESET0(isp); isp_prt(isp, ISP_LOGERR, "reset didn't clear"); return; } @@ -655,6 +592,26 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) ISP_WRITE(isp, HCCR, HCCR_CMD_RELEASE); } + /* + * Set up default request/response queue in-pointer/out-pointer + * register indices. + */ + if (IS_24XX(isp)) { + isp->isp_rqstinrp = BIU2400_REQINP; + isp->isp_rqstoutrp = BIU2400_REQOUTP; + isp->isp_respinrp = BIU2400_RSPINP; + isp->isp_respoutrp = BIU2400_RSPOUTP; + } else if (IS_23XX(isp)) { + isp->isp_rqstinrp = BIU_REQINP; + isp->isp_rqstoutrp = BIU_REQOUTP; + isp->isp_respinrp = BIU_RSPINP; + isp->isp_respoutrp = BIU_RSPOUTP; + } else { + isp->isp_rqstinrp = INMAILBOX4; + isp->isp_rqstoutrp = OUTMAILBOX4; + isp->isp_respinrp = OUTMAILBOX5; + isp->isp_respoutrp = INMAILBOX5; + } ISP_WRITE(isp, isp->isp_rqstinrp, 0); ISP_WRITE(isp, isp->isp_rqstoutrp, 0); ISP_WRITE(isp, isp->isp_respinrp, 0); @@ -668,10 +625,10 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) ISP_WRITE(isp, BIU2400_ATIO_RSPOUTP, 0); } - /* - * Do MD specific post initialization - */ - ISP_RESET1(isp); + if (!IS_24XX(isp) && isp->isp_bustype == ISP_BT_PCI) { + /* Make sure the BIOS is disabled */ + ISP_WRITE(isp, HCCR, PCI_HCCR_CMD_BIOS); + } /* * Wait for everything to finish firing up. @@ -686,7 +643,6 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) while (ISP_READ(isp, OUTMAILBOX0) == MBOX_BUSY) { ISP_DELAY(100); if (--loops < 0) { - ISP_RESET0(isp); isp_prt(isp, ISP_LOGERR, "MBOX_BUSY never cleared on reset"); return; } @@ -707,14 +663,12 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { isp_prt(isp, ISP_LOGERR, "NOP command failed (%x)", mbs.param[0]); - ISP_RESET0(isp); return; } /* * Do some operational tests */ - if (IS_SCSI(isp) || IS_24XX(isp)) { static const uint16_t patterns[MAX_MAILBOX] = { 0x0000, 0xdead, 0xbeef, 0xffff, @@ -735,12 +689,10 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) } isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - ISP_RESET0(isp); return; } for (i = 1; i < nmbox; i++) { if (mbs.param[i] != patterns[i]) { - ISP_RESET0(isp); isp_prt(isp, ISP_LOGERR, "Register Test Failed at Register %d: should have 0x%04x but got 0x%04x", i, patterns[i], mbs.param[i]); return; } @@ -758,6 +710,17 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) */ if ((isp->isp_mdvec->dv_ispfw == NULL) || (isp->isp_confopts & ISP_CFG_NORELOAD)) { dodnld = 0; + } else { + + /* + * Set up DMA for the request and response queues. + * We do this now so we can use the request queue + * for dma to load firmware from. + */ + if (ISP_MBOXDMASETUP(isp) != 0) { + isp_prt(isp, ISP_LOGERR, "Cannot setup DMA"); + return; + } } if (IS_24XX(isp)) { @@ -849,7 +812,6 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) goto again; } isp_prt(isp, ISP_LOGERR, "F/W Risc Ram Load Failed"); - ISP_RESET0(isp); return; } la += nw; @@ -918,7 +880,6 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { isp_prt(isp, ISP_LOGERR, "F/W Risc Ram Load Failed"); - ISP_RESET0(isp); return; } la += nw; @@ -961,7 +922,6 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { isp_prt(isp, ISP_LOGERR, "F/W download failed at word %d", isp->isp_mbxwrk1 - code_org); - ISP_RESET0(isp); return; } } else if (IS_26XX(isp)) { @@ -971,7 +931,6 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { isp_prt(isp, ISP_LOGERR, "Flash F/W load failed"); - ISP_RESET0(isp); return; } } else { @@ -992,7 +951,6 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { isp_prt(isp, ISP_LOGERR, dcrc); - ISP_RESET0(isp); return; } } @@ -1003,8 +961,6 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) * If we didn't actually download f/w, * we still need to (re)start it. */ - - MBSINIT(&mbs, MBOX_EXEC_FIRMWARE, MBLOGALL, 5000000); if (IS_24XX(isp)) { mbs.param[1] = code_org >> 16; @@ -1027,7 +983,6 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) isp_mboxcmd(isp, &mbs); if (IS_2322(isp) || IS_24XX(isp)) { if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - ISP_RESET0(isp); return; } } @@ -1051,7 +1006,6 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) MBSINIT(&mbs, MBOX_ABOUT_FIRMWARE, MBLOGALL, 0); isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - ISP_RESET0(isp); return; } @@ -1249,22 +1203,16 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) MBSINIT(&mbs, MBOX_GET_RESOURCE_COUNT, MBLOGALL, 0); isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - ISP_RESET0(isp); return; } - if (isp->isp_maxcmds >= mbs.param[3]) { - isp->isp_maxcmds = mbs.param[3]; - } + isp->isp_maxcmds = mbs.param[3]; } else { MBSINIT(&mbs, MBOX_GET_FIRMWARE_STATUS, MBLOGALL, 0); isp_mboxcmd(isp, &mbs); if (mbs.param[0] != MBOX_COMMAND_COMPLETE) { - ISP_RESET0(isp); return; } - if (isp->isp_maxcmds >= mbs.param[2]) { - isp->isp_maxcmds = mbs.param[2]; - } + isp->isp_maxcmds = mbs.param[2]; } isp_prt(isp, ISP_LOGCONFIG, "%d max I/O command limit set", isp->isp_maxcmds); @@ -1284,15 +1232,28 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) isp->isp_nchan = 1; } } + + /* + * Final DMA setup after we got isp_maxcmds. + */ + if (ISP_MBOXDMASETUP(isp) != 0) { + isp_prt(isp, ISP_LOGERR, "Cannot setup DMA"); + return; + } + + /* + * Setup interrupts. + */ + if (ISP_IRQSETUP(isp) != 0) { + isp_prt(isp, ISP_LOGERR, "Cannot setup IRQ"); + return; + } + ISP_ENABLE_INTS(isp); + if (IS_FC(isp)) { for (i = 0; i < isp->isp_nchan; i++) isp_change_fw_state(isp, i, FW_CONFIG_WAIT); } - if (isp->isp_dead) { - isp_shutdown(isp); - ISP_DISABLE_INTS(isp); - return; - } isp->isp_state = ISP_RESETSTATE; @@ -1303,7 +1264,7 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) * of knowing how many luns we support. * * Expanded lun firmware gives you 32 luns for SCSI cards and - * 16384 luns for Fibre Channel cards. + * unlimited luns for Fibre Channel cards. * * It turns out that even for QLogic 2100s with ROM 1.10 and above * we do get a firmware attributes word returned in mailbox register 6. @@ -1351,7 +1312,7 @@ isp_reset(ispsoftc_t *isp, int do_load_defaults) * Clean firmware shutdown. */ static int -isp_deinit(ispsoftc_t *isp) +isp_stop(ispsoftc_t *isp) { mbreg_t mbs; @@ -1370,6 +1331,35 @@ isp_deinit(ispsoftc_t *isp) } /* + * Hardware shutdown. + */ +void +isp_shutdown(ispsoftc_t *isp) +{ + + if (isp->isp_state >= ISP_RESETSTATE) + isp_stop(isp); + ISP_DISABLE_INTS(isp); + if (IS_FC(isp)) { + if (IS_24XX(isp)) { + ISP_WRITE(isp, BIU2400_ICR, 0); + ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE); + } else { + ISP_WRITE(isp, BIU_ICR, 0); + ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); + ISP_WRITE(isp, BIU2100_CSR, BIU2100_FPM0_REGS); + ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET); + ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS); + ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL); + ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS); + } + } else { + ISP_WRITE(isp, BIU_ICR, 0); + ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); + } +} + +/* * Initialize Parameters of Hardware to a known state. * * Locks are held before coming here. @@ -5599,7 +5589,6 @@ isp_parse_async(ispsoftc_t *isp, uint16_t mbox) isp_async(isp, ISPASYNC_BUS_RESET, chan); break; case ASYNC_SYSTEM_ERROR: - isp->isp_dead = 1; isp->isp_state = ISP_CRASHED; /* * Were we waiting for a mailbox command to complete? @@ -5770,7 +5759,6 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox) switch (mbox) { case ASYNC_SYSTEM_ERROR: - isp->isp_dead = 1; isp->isp_state = ISP_CRASHED; FCPARAM(isp, chan)->isp_loopstate = LOOP_NIL; isp_change_fw_state(isp, chan, FW_CONFIG_WAIT); @@ -6052,7 +6040,6 @@ isp_parse_async_fc(ispsoftc_t *isp, uint16_t mbox) "Point-to-Point -> Loop mode (BAD LIP)"); break; case ISP_CONN_FATAL: - isp->isp_dead = 1; isp->isp_state = ISP_CRASHED; isp_prt(isp, ISP_LOGERR, "FATAL CONNECTION ERROR"); isp_async(isp, ISPASYNC_FW_CRASH); @@ -7895,14 +7882,13 @@ isp_reinit(ispsoftc_t *isp, int do_load_defaults) { int i, res = 0; - if (isp->isp_state == ISP_RUNSTATE) - isp_deinit(isp); + if (isp->isp_state > ISP_RESETSTATE) + isp_stop(isp); if (isp->isp_state != ISP_RESETSTATE) isp_reset(isp, do_load_defaults); if (isp->isp_state != ISP_RESETSTATE) { res = EIO; isp_prt(isp, ISP_LOGERR, "%s: cannot reset card", __func__); - ISP_DISABLE_INTS(isp); goto cleanup; } diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c index ba66cf6fee645..9009fa21f080b 100644 --- a/sys/dev/isp/isp_freebsd.c +++ b/sys/dev/isp/isp_freebsd.c @@ -1529,7 +1529,7 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb, enum Start_Ctio_How how) isp_prt(isp, ISP_LOGTDEBUG0, "%s: ests base %p vaddr %p ecmd_dma %jx addr %jx len %u", __func__, isp->isp_osinfo.ecmd_base, atp->ests, (uintmax_t) isp->isp_osinfo.ecmd_dma, (uintmax_t)addr, MIN_FCP_RESPONSE_SIZE + sense_length); cto->rsp.m2.ct_datalen = MIN_FCP_RESPONSE_SIZE + sense_length; - if (isp->isp_osinfo.sixtyfourbit) { + if (cto->ct_header.rqs_entry_type == RQSTYPE_CTIO3) { cto->rsp.m2.u.ct_fcp_rsp_iudata_64.ds_base = DMA_LO32(addr); cto->rsp.m2.u.ct_fcp_rsp_iudata_64.ds_basehi = DMA_HI32(addr); cto->rsp.m2.u.ct_fcp_rsp_iudata_64.ds_count = MIN_FCP_RESPONSE_SIZE + sense_length; @@ -4304,21 +4304,6 @@ changed: } } - -/* - * Locks are held before coming here. - */ -void -isp_uninit(ispsoftc_t *isp) -{ - if (IS_24XX(isp)) { - ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RESET); - } else { - ISP_WRITE(isp, HCCR, HCCR_CMD_RESET); - } - ISP_DISABLE_INTS(isp); -} - uint64_t isp_default_wwn(ispsoftc_t * isp, int chan, int isactive, int iswwnn) { diff --git a/sys/dev/isp/isp_freebsd.h b/sys/dev/isp/isp_freebsd.h index f3c6df3269954..06d8236e389c4 100644 --- a/sys/dev/isp/isp_freebsd.h +++ b/sys/dev/isp/isp_freebsd.h @@ -697,7 +697,6 @@ default: \ */ extern int isp_attach(ispsoftc_t *); extern int isp_detach(ispsoftc_t *); -extern void isp_uninit(ispsoftc_t *); extern uint64_t isp_default_wwn(ispsoftc_t *, int, int, int); /* diff --git a/sys/dev/isp/isp_library.c b/sys/dev/isp/isp_library.c index f186e50b23951..d46593e383d89 100644 --- a/sys/dev/isp/isp_library.c +++ b/sys/dev/isp/isp_library.c @@ -632,28 +632,6 @@ isp_clear_commands(ispsoftc_t *isp) #endif } -void -isp_shutdown(ispsoftc_t *isp) -{ - if (IS_FC(isp)) { - if (IS_24XX(isp)) { - ISP_WRITE(isp, BIU2400_ICR, 0); - ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_PAUSE); - } else { - ISP_WRITE(isp, BIU_ICR, 0); - ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); - ISP_WRITE(isp, BIU2100_CSR, BIU2100_FPM0_REGS); - ISP_WRITE(isp, FPM_DIAG_CONFIG, FPM_SOFT_RESET); - ISP_WRITE(isp, BIU2100_CSR, BIU2100_FB_REGS); - ISP_WRITE(isp, FBM_CMD, FBMCMD_FIFO_RESET_ALL); - ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS); - } - } else { - ISP_WRITE(isp, BIU_ICR, 0); - ISP_WRITE(isp, HCCR, HCCR_CMD_PAUSE); - } -} - /* * Functions to move stuff to a form that the QLogic RISC engine understands * and functions to move stuff back to a form the processor understands. diff --git a/sys/dev/isp/isp_library.h b/sys/dev/isp/isp_library.h index c70b2ccda01d0..7b90e3e10428a 100644 --- a/sys/dev/isp/isp_library.h +++ b/sys/dev/isp/isp_library.h @@ -77,11 +77,6 @@ const char *isp_fc_toponame(fcparam *); void isp_clear_commands(ispsoftc_t *); /* - * Common chip shutdown function - */ -void isp_shutdown(ispsoftc_t *); - -/* * Put/Get routines to push from CPU view to device view * or to pull from device view to CPU view for various * data structures (IOCB) diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c index 8a51cf511a757..bb1322a89fff5 100644 --- a/sys/dev/isp/isp_pci.c +++ b/sys/dev/isp/isp_pci.c @@ -65,11 +65,9 @@ static int isp_pci_rd_isr(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *); static int isp_pci_rd_isr_2300(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *); static int isp_pci_rd_isr_2400(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *); static int isp_pci_mbxdma(ispsoftc_t *); +static void isp_pci_mbxdmafree(ispsoftc_t *); static int isp_pci_dmasetup(ispsoftc_t *, XS_T *, void *); - - -static void isp_pci_reset0(ispsoftc_t *); -static void isp_pci_reset1(ispsoftc_t *); +static int isp_pci_irqsetup(ispsoftc_t *); static void isp_pci_dumpregs(ispsoftc_t *, const char *); static struct ispmdvec mdvec = { @@ -79,8 +77,7 @@ static struct ispmdvec mdvec = { isp_pci_mbxdma, isp_pci_dmasetup, isp_common_dmateardown, - isp_pci_reset0, - isp_pci_reset1, + isp_pci_irqsetup, isp_pci_dumpregs, NULL, BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 @@ -93,8 +90,7 @@ static struct ispmdvec mdvec_1080 = { isp_pci_mbxdma, isp_pci_dmasetup, isp_common_dmateardown, - isp_pci_reset0, - isp_pci_reset1, + isp_pci_irqsetup, isp_pci_dumpregs, NULL, BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 @@ -107,8 +103,7 @@ static struct ispmdvec mdvec_12160 = { isp_pci_mbxdma, isp_pci_dmasetup, isp_common_dmateardown, - isp_pci_reset0, - isp_pci_reset1, + isp_pci_irqsetup, isp_pci_dumpregs, NULL, BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 @@ -121,8 +116,7 @@ static struct ispmdvec mdvec_2100 = { isp_pci_mbxdma, isp_pci_dmasetup, isp_common_dmateardown, - isp_pci_reset0, - isp_pci_reset1, + isp_pci_irqsetup, isp_pci_dumpregs }; @@ -133,8 +127,7 @@ static struct ispmdvec mdvec_2200 = { isp_pci_mbxdma, isp_pci_dmasetup, isp_common_dmateardown, - isp_pci_reset0, - isp_pci_reset1, + isp_pci_irqsetup, isp_pci_dumpregs }; @@ -145,8 +138,7 @@ static struct ispmdvec mdvec_2300 = { isp_pci_mbxdma, isp_pci_dmasetup, isp_common_dmateardown, - isp_pci_reset0, - isp_pci_reset1, + isp_pci_irqsetup, isp_pci_dumpregs }; @@ -157,8 +149,7 @@ static struct ispmdvec mdvec_2400 = { isp_pci_mbxdma, isp_pci_dmasetup, isp_common_dmateardown, - isp_pci_reset0, - isp_pci_reset1, + isp_pci_irqsetup, NULL }; @@ -169,8 +160,7 @@ static struct ispmdvec mdvec_2500 = { isp_pci_mbxdma, isp_pci_dmasetup, isp_common_dmateardown, - isp_pci_reset0, - isp_pci_reset1, + isp_pci_irqsetup, NULL }; @@ -181,8 +171,7 @@ static struct ispmdvec mdvec_2600 = { isp_pci_mbxdma, isp_pci_dmasetup, isp_common_dmateardown, - isp_pci_reset0, - isp_pci_reset1, + isp_pci_irqsetup, NULL }; @@ -681,26 +670,19 @@ isp_get_specific_options(device_t dev, int chan, ispsoftc_t *isp) static int isp_pci_attach(device_t dev) { - int i, locksetup = 0; + struct isp_pcisoftc *pcs = device_get_softc(dev); + ispsoftc_t *isp = &pcs->pci_isp; + int i; uint32_t data, cmd, linesz, did; - struct isp_pcisoftc *pcs; - ispsoftc_t *isp; size_t psize, xsize; char fwname[32]; - pcs = device_get_softc(dev); - if (pcs == NULL) { - device_printf(dev, "cannot get softc\n"); - return (ENOMEM); - } - memset(pcs, 0, sizeof (*pcs)); - pcs->pci_dev = dev; - isp = &pcs->pci_isp; isp->isp_dev = dev; isp->isp_nchan = 1; if (sizeof (bus_addr_t) > 4) isp->isp_osinfo.sixtyfourbit = 1; + mtx_init(&isp->isp_osinfo.lock, "isp", NULL, MTX_DEF); /* * Get Generic Options @@ -980,10 +962,6 @@ isp_pci_attach(device_t dev) goto bad; } - /* Make sure the lock is set up. */ - mtx_init(&isp->isp_osinfo.lock, "isp", NULL, MTX_DEF); - locksetup++; - if (isp_setup_intr(dev, pcs->irq, ISP_IFLAGS, NULL, isp_platform_intr, isp, &pcs->ih)) { device_printf(dev, "could not setup interrupt\n"); goto bad; @@ -1007,7 +985,7 @@ isp_pci_attach(device_t dev) ISP_UNLOCK(isp); if (isp_attach(isp)) { ISP_LOCK(isp); - isp_uninit(isp); + isp_shutdown(isp); ISP_UNLOCK(isp); goto bad; } @@ -1017,9 +995,6 @@ bad: if (pcs->ih) { (void) bus_teardown_intr(dev, pcs->irq, pcs->ih); } - if (locksetup) { - mtx_destroy(&isp->isp_osinfo.lock); - } if (pcs->irq) { (void) bus_release_resource(dev, SYS_RES_IRQ, pcs->iqd, pcs->irq); } @@ -1040,43 +1015,34 @@ bad: free(pcs->pci_isp.isp_osinfo.pc.ptr, M_DEVBUF); pcs->pci_isp.isp_osinfo.pc.ptr = NULL; } + mtx_destroy(&isp->isp_osinfo.lock); return (ENXIO); } static int isp_pci_detach(device_t dev) { - struct isp_pcisoftc *pcs; - ispsoftc_t *isp; + struct isp_pcisoftc *pcs = device_get_softc(dev); + ispsoftc_t *isp = &pcs->pci_isp; int status; - pcs = device_get_softc(dev); - if (pcs == NULL) { - return (ENXIO); - } - isp = (ispsoftc_t *) pcs; status = isp_detach(isp); if (status) return (status); ISP_LOCK(isp); - isp_uninit(isp); - if (pcs->ih) { - (void) bus_teardown_intr(dev, pcs->irq, pcs->ih); - } + isp_shutdown(isp); ISP_UNLOCK(isp); - mtx_destroy(&isp->isp_osinfo.lock); + if (pcs->ih) + (void) bus_teardown_intr(dev, pcs->irq, pcs->ih); (void) bus_release_resource(dev, SYS_RES_IRQ, pcs->iqd, pcs->irq); - if (pcs->msicount) { + if (pcs->msicount) pci_release_msi(dev); - } (void) bus_release_resource(dev, pcs->rtp, pcs->rgd, pcs->regs); if (pcs->regs1) (void) bus_release_resource(dev, pcs->rtp1, pcs->rgd1, pcs->regs1); if (pcs->regs2) (void) bus_release_resource(dev, pcs->rtp2, pcs->rgd2, pcs->regs2); - /* - * XXX: THERE IS A LOT OF LEAKAGE HERE - */ + isp_pci_mbxdmafree(isp); if (pcs->pci_isp.isp_param) { free(pcs->pci_isp.isp_param, M_DEVBUF); pcs->pci_isp.isp_param = NULL; @@ -1085,6 +1051,7 @@ isp_pci_detach(device_t dev) free(pcs->pci_isp.isp_osinfo.pc.ptr, M_DEVBUF); pcs->pci_isp.isp_osinfo.pc.ptr = NULL; } + mtx_destroy(&isp->isp_osinfo.lock); return (0); } @@ -1571,56 +1538,39 @@ isp_pci_mbxdma(ispsoftc_t *isp) struct imush im; isp_ecmd_t *ecmd; - /* - * Already been here? If so, leave... - */ - if (isp->isp_rquest) { + /* Already been here? If so, leave... */ + if (isp->isp_xflist != NULL) + return (0); + if (isp->isp_rquest != NULL && isp->isp_maxcmds == 0) return (0); - } ISP_UNLOCK(isp); - - if (isp->isp_maxcmds == 0) { - isp_prt(isp, ISP_LOGERR, "maxcmds not set"); - ISP_LOCK(isp); - return (1); - } + if (isp->isp_rquest != NULL) + goto gotmaxcmds; hlim = BUS_SPACE_MAXADDR; if (IS_ULTRA2(isp) || IS_FC(isp) || IS_1240(isp)) { - if (sizeof (bus_size_t) > 4) { + if (sizeof (bus_size_t) > 4) slim = (bus_size_t) (1ULL << 32); - } else { + else slim = (bus_size_t) (1UL << 31); - } llim = BUS_SPACE_MAXADDR; } else { - llim = BUS_SPACE_MAXADDR_32BIT; slim = (1UL << 24); + llim = BUS_SPACE_MAXADDR_32BIT; } - - len = isp->isp_maxcmds * sizeof (struct isp_pcmd); - isp->isp_osinfo.pcmd_pool = (struct isp_pcmd *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); - - if (isp->isp_osinfo.sixtyfourbit) { + if (isp->isp_osinfo.sixtyfourbit) nsegs = ISP_NSEG64_MAX; - } else { + else nsegs = ISP_NSEG_MAX; - } - if (isp_dma_tag_create(BUS_DMA_ROOTARG(ISP_PCD(isp)), 1, slim, llim, hlim, NULL, NULL, BUS_SPACE_MAXSIZE, nsegs, slim, 0, &isp->isp_osinfo.dmat)) { - free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); + if (isp_dma_tag_create(BUS_DMA_ROOTARG(ISP_PCD(isp)), 1, + slim, llim, hlim, NULL, NULL, BUS_SPACE_MAXSIZE, nsegs, slim, 0, + &isp->isp_osinfo.dmat)) { ISP_LOCK(isp); isp_prt(isp, ISP_LOGERR, "could not create master dma tag"); return (1); } - len = sizeof (isp_hdl_t) * isp->isp_maxcmds; - isp->isp_xflist = (isp_hdl_t *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); - for (len = 0; len < isp->isp_maxcmds - 1; len++) { - isp->isp_xflist[len].cmd = &isp->isp_xflist[len+1]; - } - isp->isp_xffree = isp->isp_xflist; - /* * Allocate and map the request queue and a region for external * DMA addressable command/status structures (22XX and later). @@ -1632,20 +1582,20 @@ isp_pci_mbxdma(ispsoftc_t *isp) BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, len, 1, len, 0, &isp->isp_osinfo.reqdmat)) { isp_prt(isp, ISP_LOGERR, "cannot create request DMA tag"); - goto bad1; + goto bad; } if (bus_dmamem_alloc(isp->isp_osinfo.reqdmat, (void **)&base, BUS_DMA_COHERENT, &isp->isp_osinfo.reqmap) != 0) { isp_prt(isp, ISP_LOGERR, "cannot allocate request DMA memory"); bus_dma_tag_destroy(isp->isp_osinfo.reqdmat); - goto bad1; + goto bad; } isp->isp_rquest = base; im.error = 0; if (bus_dmamap_load(isp->isp_osinfo.reqdmat, isp->isp_osinfo.reqmap, base, len, imc, &im, 0) || im.error) { isp_prt(isp, ISP_LOGERR, "error loading request DMA map %d", im.error); - goto bad1; + goto bad; } isp_prt(isp, ISP_LOGDEBUG0, "request area @ 0x%jx/0x%jx", (uintmax_t)im.maddr, (uintmax_t)len); @@ -1673,20 +1623,20 @@ isp_pci_mbxdma(ispsoftc_t *isp) BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, len, 1, len, 0, &isp->isp_osinfo.respdmat)) { isp_prt(isp, ISP_LOGERR, "cannot create response DMA tag"); - goto bad1; + goto bad; } if (bus_dmamem_alloc(isp->isp_osinfo.respdmat, (void **)&base, BUS_DMA_COHERENT, &isp->isp_osinfo.respmap) != 0) { isp_prt(isp, ISP_LOGERR, "cannot allocate response DMA memory"); bus_dma_tag_destroy(isp->isp_osinfo.respdmat); - goto bad1; + goto bad; } isp->isp_result = base; im.error = 0; if (bus_dmamap_load(isp->isp_osinfo.respdmat, isp->isp_osinfo.respmap, base, len, imc, &im, 0) || im.error) { isp_prt(isp, ISP_LOGERR, "error loading response DMA map %d", im.error); - goto bad1; + goto bad; } isp_prt(isp, ISP_LOGDEBUG0, "response area @ 0x%jx/0x%jx", (uintmax_t)im.maddr, (uintmax_t)len); @@ -1702,13 +1652,13 @@ isp_pci_mbxdma(ispsoftc_t *isp) BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, len, 1, len, 0, &isp->isp_osinfo.atiodmat)) { isp_prt(isp, ISP_LOGERR, "cannot create ATIO DMA tag"); - goto bad1; + goto bad; } if (bus_dmamem_alloc(isp->isp_osinfo.atiodmat, (void **)&base, BUS_DMA_COHERENT, &isp->isp_osinfo.atiomap) != 0) { isp_prt(isp, ISP_LOGERR, "cannot allocate ATIO DMA memory"); bus_dma_tag_destroy(isp->isp_osinfo.atiodmat); - goto bad1; + goto bad; } isp->isp_atioq = base; im.error = 0; @@ -1754,6 +1704,7 @@ isp_pci_mbxdma(ispsoftc_t *isp) base, ISP_FC_SCRLEN, imc, &im, 0) || im.error) { bus_dmamem_free(isp->isp_osinfo.scdmat, base, fc->scmap); + FCPARAM(isp, cmap)->isp_scratch = NULL; goto bad; } FCPARAM(isp, cmap)->isp_scdma = im.maddr; @@ -1775,83 +1726,134 @@ isp_pci_mbxdma(ispsoftc_t *isp) } } + if (isp->isp_maxcmds == 0) { + ISP_LOCK(isp); + return (0); + } + +gotmaxcmds: + len = isp->isp_maxcmds * sizeof (struct isp_pcmd); + isp->isp_osinfo.pcmd_pool = (struct isp_pcmd *) + malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); for (i = 0; i < isp->isp_maxcmds; i++) { struct isp_pcmd *pcmd = &isp->isp_osinfo.pcmd_pool[i]; error = bus_dmamap_create(isp->isp_osinfo.dmat, 0, &pcmd->dmap); if (error) { isp_prt(isp, ISP_LOGERR, "error %d creating per-cmd DMA maps", error); while (--i >= 0) { - bus_dmamap_destroy(isp->isp_osinfo.dmat, isp->isp_osinfo.pcmd_pool[i].dmap); + bus_dmamap_destroy(isp->isp_osinfo.dmat, + isp->isp_osinfo.pcmd_pool[i].dmap); } goto bad; } callout_init_mtx(&pcmd->wdog, &isp->isp_osinfo.lock, 0); - if (i == isp->isp_maxcmds-1) { + if (i == isp->isp_maxcmds-1) pcmd->next = NULL; - } else { + else pcmd->next = &isp->isp_osinfo.pcmd_pool[i+1]; - } } isp->isp_osinfo.pcmd_free = &isp->isp_osinfo.pcmd_pool[0]; + + len = sizeof (isp_hdl_t) * isp->isp_maxcmds; + isp->isp_xflist = (isp_hdl_t *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); + for (len = 0; len < isp->isp_maxcmds - 1; len++) + isp->isp_xflist[len].cmd = &isp->isp_xflist[len+1]; + isp->isp_xffree = isp->isp_xflist; + ISP_LOCK(isp); return (0); bad: + isp_pci_mbxdmafree(isp); + ISP_LOCK(isp); + return (1); +} + +static void +isp_pci_mbxdmafree(ispsoftc_t *isp) +{ + int i; + + if (isp->isp_xflist != NULL) { + free(isp->isp_xflist, M_DEVBUF); + isp->isp_xflist = NULL; + } + if (isp->isp_osinfo.pcmd_pool != NULL) { + for (i = 0; i < isp->isp_maxcmds; i++) { + bus_dmamap_destroy(isp->isp_osinfo.dmat, + isp->isp_osinfo.pcmd_pool[i].dmap); + } + free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); + isp->isp_osinfo.pcmd_pool = NULL; + } if (IS_FC(isp)) { - while (--cmap >= 0) { - struct isp_fc *fc = ISP_FC_PC(isp, cmap); - bus_dmamap_unload(isp->isp_osinfo.scdmat, fc->scmap); - bus_dmamem_free(isp->isp_osinfo.scdmat, - FCPARAM(isp, cmap)->isp_scratch, fc->scmap); + for (i = 0; i < isp->isp_nchan; i++) { + struct isp_fc *fc = ISP_FC_PC(isp, i); + if (FCPARAM(isp, i)->isp_scdma != 0) { + bus_dmamap_unload(isp->isp_osinfo.scdmat, + fc->scmap); + FCPARAM(isp, i)->isp_scdma = 0; + } + if (FCPARAM(isp, i)->isp_scratch != NULL) { + bus_dmamem_free(isp->isp_osinfo.scdmat, + FCPARAM(isp, i)->isp_scratch, fc->scmap); + FCPARAM(isp, i)->isp_scratch = NULL; + } while (fc->nexus_free_list) { struct isp_nexus *n = fc->nexus_free_list; fc->nexus_free_list = n->next; free(n, M_DEVBUF); } } - bus_dma_tag_destroy(isp->isp_osinfo.scdmat); - bus_dmamap_unload(isp->isp_osinfo.iocbdmat, isp->isp_osinfo.iocbmap); - bus_dmamem_free(isp->isp_osinfo.iocbdmat, isp->isp_iocb, - isp->isp_osinfo.iocbmap); - bus_dma_tag_destroy(isp->isp_osinfo.iocbdmat); - } -bad1: - if (isp->isp_rquest_dma != 0) { - bus_dmamap_unload(isp->isp_osinfo.reqdmat, - isp->isp_osinfo.reqmap); - } - if (isp->isp_rquest != NULL) { - bus_dmamem_free(isp->isp_osinfo.reqdmat, isp->isp_rquest, - isp->isp_osinfo.reqmap); - bus_dma_tag_destroy(isp->isp_osinfo.reqdmat); - } - if (isp->isp_result_dma != 0) { - bus_dmamap_unload(isp->isp_osinfo.respdmat, - isp->isp_osinfo.respmap); - } - if (isp->isp_result != NULL) { - bus_dmamem_free(isp->isp_osinfo.respdmat, isp->isp_result, - isp->isp_osinfo.respmap); - bus_dma_tag_destroy(isp->isp_osinfo.respdmat); + if (isp->isp_iocb_dma != 0) { + bus_dma_tag_destroy(isp->isp_osinfo.scdmat); + bus_dmamap_unload(isp->isp_osinfo.iocbdmat, + isp->isp_osinfo.iocbmap); + isp->isp_iocb_dma = 0; + } + if (isp->isp_iocb != NULL) { + bus_dmamem_free(isp->isp_osinfo.iocbdmat, + isp->isp_iocb, isp->isp_osinfo.iocbmap); + bus_dma_tag_destroy(isp->isp_osinfo.iocbdmat); + } } #ifdef ISP_TARGET_MODE if (IS_24XX(isp)) { if (isp->isp_atioq_dma != 0) { bus_dmamap_unload(isp->isp_osinfo.atiodmat, isp->isp_osinfo.atiomap); + isp->isp_atioq_dma = 0; } if (isp->isp_atioq != NULL) { - bus_dmamem_free(isp->isp_osinfo.reqdmat, isp->isp_atioq, + bus_dmamem_free(isp->isp_osinfo.atiodmat, isp->isp_atioq, isp->isp_osinfo.atiomap); bus_dma_tag_destroy(isp->isp_osinfo.atiodmat); + isp->isp_atioq = NULL; } } #endif - free(isp->isp_xflist, M_DEVBUF); - free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); - isp->isp_rquest = NULL; - ISP_LOCK(isp); - return (1); + if (isp->isp_result_dma != 0) { + bus_dmamap_unload(isp->isp_osinfo.respdmat, + isp->isp_osinfo.respmap); + isp->isp_result_dma = 0; + } + if (isp->isp_result != NULL) { + bus_dmamem_free(isp->isp_osinfo.respdmat, isp->isp_result, + isp->isp_osinfo.respmap); + bus_dma_tag_destroy(isp->isp_osinfo.respdmat); + isp->isp_result = NULL; + } + if (isp->isp_rquest_dma != 0) { + bus_dmamap_unload(isp->isp_osinfo.reqdmat, + isp->isp_osinfo.reqmap); + isp->isp_rquest_dma = 0; + } + if (isp->isp_rquest != NULL) { + bus_dmamem_free(isp->isp_osinfo.reqdmat, isp->isp_rquest, + isp->isp_osinfo.reqmap); + bus_dma_tag_destroy(isp->isp_osinfo.reqdmat); + isp->isp_rquest = NULL; + } } typedef struct { @@ -2071,21 +2073,11 @@ isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, void *ff) return (CMD_QUEUED); } -static void -isp_pci_reset0(ispsoftc_t *isp) +static int +isp_pci_irqsetup(ispsoftc_t *isp) { - ISP_DISABLE_INTS(isp); -} -static void -isp_pci_reset1(ispsoftc_t *isp) -{ - if (!IS_24XX(isp)) { - /* Make sure the BIOS is disabled */ - isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS); - } - /* and enable interrupts */ - ISP_ENABLE_INTS(isp); + return (0); } static void diff --git a/sys/dev/isp/isp_sbus.c b/sys/dev/isp/isp_sbus.c index b3963b9905e56..65c5ee52da1f8 100644 --- a/sys/dev/isp/isp_sbus.c +++ b/sys/dev/isp/isp_sbus.c @@ -55,11 +55,8 @@ static uint32_t isp_sbus_rd_reg(ispsoftc_t *, int); static void isp_sbus_wr_reg(ispsoftc_t *, int, uint32_t); static int isp_sbus_rd_isr(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *); static int isp_sbus_mbxdma(ispsoftc_t *); +static void isp_sbus_mbxdmafree(ispsoftc_t *); static int isp_sbus_dmasetup(ispsoftc_t *, XS_T *, void *); - - -static void isp_sbus_reset0(ispsoftc_t *); -static void isp_sbus_reset1(ispsoftc_t *); static void isp_sbus_dumpregs(ispsoftc_t *, const char *); static struct ispmdvec mdvec = { @@ -69,8 +66,7 @@ static struct ispmdvec mdvec = { isp_sbus_mbxdma, isp_sbus_dmasetup, isp_common_dmateardown, - isp_sbus_reset0, - isp_sbus_reset1, + NULL, isp_sbus_dumpregs, NULL, BIU_BURST_ENABLE|BIU_PCI_CONF1_FIFO_64 @@ -140,20 +136,15 @@ isp_sbus_probe(device_t dev) static int isp_sbus_attach(device_t dev) { + struct isp_sbussoftc *sbs = device_get_softc(dev); + ispsoftc_t *isp = &sbs->sbus_isp; int tval, isp_debug, role, ispburst, default_id; - struct isp_sbussoftc *sbs; - ispsoftc_t *isp = NULL; - int locksetup = 0; int ints_setup = 0; - sbs = device_get_softc(dev); - if (sbs == NULL) { - device_printf(dev, "cannot get softc\n"); - return (ENOMEM); - } - sbs->sbus_dev = dev; sbs->sbus_mdvec = mdvec; + isp->isp_dev = dev; + mtx_init(&isp->isp_osinfo.lock, "isp", NULL, MTX_DEF); role = 0; if (resource_int_value(device_get_name(dev), device_get_unit(dev), @@ -179,7 +170,6 @@ isp_sbus_attach(device_t dev) sbs->sbus_poff[SXP_BLOCK >> _BLK_REG_SHFT] = SBUS_SXP_REGS_OFF; sbs->sbus_poff[RISC_BLOCK >> _BLK_REG_SHFT] = SBUS_RISC_REGS_OFF; sbs->sbus_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF; - isp = &sbs->sbus_isp; isp->isp_regs = sbs->regs; isp->isp_mdvec = &sbs->sbus_mdvec; isp->isp_bustype = ISP_BT_SBUS; @@ -187,7 +177,6 @@ isp_sbus_attach(device_t dev) isp->isp_param = &sbs->sbus_param; isp->isp_osinfo.pc.ptr = &sbs->sbus_spi; isp->isp_revision = 0; /* XXX */ - isp->isp_dev = dev; isp->isp_nchan = 1; if (IS_FC(isp)) ISP_FC_PC(isp, 0)->def_role = role; @@ -266,10 +255,6 @@ isp_sbus_attach(device_t dev) (void) resource_int_value(device_get_name(dev), device_get_unit(dev), "debug", &isp_debug); - /* Make sure the lock is set up. */ - mtx_init(&isp->isp_osinfo.lock, "isp", NULL, MTX_DEF); - locksetup++; - sbs->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sbs->iqd, RF_ACTIVE | RF_SHAREABLE); if (sbs->irq == NULL) { @@ -301,14 +286,13 @@ isp_sbus_attach(device_t dev) */ ISP_LOCK(isp); if (isp_reinit(isp, 1) != 0) { - isp_uninit(isp); ISP_UNLOCK(isp); goto bad; } ISP_UNLOCK(isp); if (isp_attach(isp)) { ISP_LOCK(isp); - isp_uninit(isp); + isp_shutdown(isp); ISP_UNLOCK(isp); goto bad; } @@ -324,41 +308,33 @@ bad: bus_release_resource(dev, SYS_RES_IRQ, sbs->iqd, sbs->irq); } - if (locksetup && isp) { - mtx_destroy(&isp->isp_osinfo.lock); - } - if (sbs->regs) { (void) bus_release_resource(dev, SYS_RES_MEMORY, sbs->rgd, sbs->regs); } + mtx_destroy(&isp->isp_osinfo.lock); return (ENXIO); } static int isp_sbus_detach(device_t dev) { - struct isp_sbussoftc *sbs; - ispsoftc_t *isp; + struct isp_sbussoftc *sbs = device_get_softc(dev); + ispsoftc_t *isp = &sbs->sbus_isp; int status; - sbs = device_get_softc(dev); - if (sbs == NULL) { - return (ENXIO); - } - isp = (ispsoftc_t *) sbs; status = isp_detach(isp); if (status) return (status); ISP_LOCK(isp); - isp_uninit(isp); - if (sbs->ih) { - (void) bus_teardown_intr(dev, sbs->irq, sbs->ih); - } + isp_shutdown(isp); ISP_UNLOCK(isp); - mtx_destroy(&isp->isp_osinfo.lock); + if (sbs->ih) + (void) bus_teardown_intr(dev, sbs->irq, sbs->ih); (void) bus_release_resource(dev, SYS_RES_IRQ, sbs->iqd, sbs->irq); (void) bus_release_resource(dev, SYS_RES_MEMORY, sbs->rgd, sbs->regs); + isp_sbus_mbxdmafree(isp); + mtx_destroy(&isp->isp_osinfo.lock); return (0); } @@ -436,25 +412,14 @@ isp_sbus_mbxdma(ispsoftc_t *isp) int i, error; struct imush im; - /* - * Already been here? If so, leave... - */ - if (isp->isp_rquest) { + /* Already been here? If so, leave... */ + if (isp->isp_xflist != NULL) + return (0); + if (isp->isp_rquest != NULL && isp->isp_maxcmds == 0) return (0); - } - ISP_UNLOCK(isp); - - len = sizeof (struct isp_pcmd) * isp->isp_maxcmds; - isp->isp_osinfo.pcmd_pool = (struct isp_pcmd *) - malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); - len = sizeof (isp_hdl_t *) * isp->isp_maxcmds; - isp->isp_xflist = (isp_hdl_t *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); - for (len = 0; len < isp->isp_maxcmds - 1; len++) { - isp->isp_xflist[len].cmd = &isp->isp_xflist[len+1]; - } - isp->isp_xffree = isp->isp_xflist; - len = sizeof (bus_dmamap_t) * isp->isp_maxcmds; + if (isp->isp_rquest != NULL) + goto gotmaxcmds; if (isp_dma_tag_create(BUS_DMA_ROOTARG(ISP_SBD(isp)), 1, BUS_SPACE_MAXADDR_24BIT+1, BUS_SPACE_MAXADDR_32BIT, @@ -480,6 +445,7 @@ isp_sbus_mbxdma(ispsoftc_t *isp) bus_dma_tag_destroy(isp->isp_osinfo.reqdmat); goto bad; } + isp->isp_rquest = base; im.error = 0; if (bus_dmamap_load(isp->isp_osinfo.reqdmat, isp->isp_osinfo.reqmap, base, len, imc, &im, 0) || im.error) { @@ -488,7 +454,6 @@ isp_sbus_mbxdma(ispsoftc_t *isp) } isp_prt(isp, ISP_LOGDEBUG0, "request area @ 0x%jx/0x%jx", (uintmax_t)im.maddr, (uintmax_t)len); - isp->isp_rquest = base; isp->isp_rquest_dma = im.maddr; /* @@ -507,6 +472,7 @@ isp_sbus_mbxdma(ispsoftc_t *isp) bus_dma_tag_destroy(isp->isp_osinfo.respdmat); goto bad; } + isp->isp_result = base; im.error = 0; if (bus_dmamap_load(isp->isp_osinfo.respdmat, isp->isp_osinfo.respmap, base, len, imc, &im, 0) || im.error) { @@ -515,9 +481,17 @@ isp_sbus_mbxdma(ispsoftc_t *isp) } isp_prt(isp, ISP_LOGDEBUG0, "response area @ 0x%jx/0x%jx", (uintmax_t)im.maddr, (uintmax_t)len); - isp->isp_result = base; isp->isp_result_dma = im.maddr; + if (isp->isp_maxcmds == 0) { + ISP_LOCK(isp); + return (0); + } + +gotmaxcmds: + len = sizeof (struct isp_pcmd) * isp->isp_maxcmds; + isp->isp_osinfo.pcmd_pool = (struct isp_pcmd *) + malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); for (i = 0; i < isp->isp_maxcmds; i++) { struct isp_pcmd *pcmd = &isp->isp_osinfo.pcmd_pool[i]; error = bus_dmamap_create(isp->isp_osinfo.dmat, 0, &pcmd->dmap); @@ -538,33 +512,61 @@ isp_sbus_mbxdma(ispsoftc_t *isp) } } isp->isp_osinfo.pcmd_free = &isp->isp_osinfo.pcmd_pool[0]; + + len = sizeof (isp_hdl_t *) * isp->isp_maxcmds; + isp->isp_xflist = (isp_hdl_t *) malloc(len, M_DEVBUF, M_WAITOK | M_ZERO); + for (len = 0; len < isp->isp_maxcmds - 1; len++) + isp->isp_xflist[len].cmd = &isp->isp_xflist[len+1]; + isp->isp_xffree = isp->isp_xflist; + ISP_LOCK(isp); return (0); bad: - if (isp->isp_rquest_dma != 0) { - bus_dmamap_unload(isp->isp_osinfo.reqdmat, - isp->isp_osinfo.reqmap); + isp_sbus_mbxdmafree(isp); + ISP_LOCK(isp); + return (1); +} + +static void +isp_sbus_mbxdmafree(ispsoftc_t *isp) +{ + int i; + + if (isp->isp_xflist != NULL) { + free(isp->isp_xflist, M_DEVBUF); + isp->isp_xflist = NULL; } - if (isp->isp_rquest != NULL) { - bus_dmamem_free(isp->isp_osinfo.reqdmat, isp->isp_rquest, - isp->isp_osinfo.reqmap); - bus_dma_tag_destroy(isp->isp_osinfo.reqdmat); + if (isp->isp_osinfo.pcmd_pool != NULL) { + for (i = 0; i < isp->isp_maxcmds; i++) { + bus_dmamap_destroy(isp->isp_osinfo.dmat, + isp->isp_osinfo.pcmd_pool[i].dmap); + } + free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); + isp->isp_osinfo.pcmd_pool = NULL; } if (isp->isp_result_dma != 0) { bus_dmamap_unload(isp->isp_osinfo.respdmat, isp->isp_osinfo.respmap); + isp->isp_result_dma = 0; } if (isp->isp_result != NULL) { bus_dmamem_free(isp->isp_osinfo.respdmat, isp->isp_result, isp->isp_osinfo.respmap); bus_dma_tag_destroy(isp->isp_osinfo.respdmat); + isp->isp_result = NULL; + } + if (isp->isp_rquest_dma != 0) { + bus_dmamap_unload(isp->isp_osinfo.reqdmat, + isp->isp_osinfo.reqmap); + isp->isp_rquest_dma = 0; + } + if (isp->isp_rquest != NULL) { + bus_dmamem_free(isp->isp_osinfo.reqdmat, isp->isp_rquest, + isp->isp_osinfo.reqmap); + bus_dma_tag_destroy(isp->isp_osinfo.reqdmat); + isp->isp_rquest = NULL; } - free(isp->isp_xflist, M_DEVBUF); - free(isp->isp_osinfo.pcmd_pool, M_DEVBUF); - isp->isp_rquest = NULL; - ISP_LOCK(isp); - return (1); } typedef struct { @@ -663,18 +665,6 @@ isp_sbus_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, void *ff) } static void -isp_sbus_reset0(ispsoftc_t *isp) -{ - ISP_DISABLE_INTS(isp); -} - -static void -isp_sbus_reset1(ispsoftc_t *isp) -{ - ISP_ENABLE_INTS(isp); -} - -static void isp_sbus_dumpregs(ispsoftc_t *isp, const char *msg) { if (msg) diff --git a/sys/dev/isp/ispvar.h b/sys/dev/isp/ispvar.h index caaba74561765..72193d6c4b729 100644 --- a/sys/dev/isp/ispvar.h +++ b/sys/dev/isp/ispvar.h @@ -64,8 +64,7 @@ struct ispmdvec { int (*dv_mbxdma) (ispsoftc_t *); int (*dv_dmaset) (ispsoftc_t *, XS_T *, void *); void (*dv_dmaclr) (ispsoftc_t *, XS_T *, uint32_t); - void (*dv_reset0) (ispsoftc_t *); - void (*dv_reset1) (ispsoftc_t *); + int (*dv_irqsetup) (ispsoftc_t *); void (*dv_dregs) (ispsoftc_t *, const char *); const void * dv_ispfw; /* ptr to f/w */ uint16_t dv_conf1; @@ -105,10 +104,8 @@ struct ispmdvec { if ((isp)->isp_mdvec->dv_dmaclr) \ (*(isp)->isp_mdvec->dv_dmaclr)((isp), (xs), (hndl)) -#define ISP_RESET0(isp) \ - if ((isp)->isp_mdvec->dv_reset0) (*(isp)->isp_mdvec->dv_reset0)((isp)) -#define ISP_RESET1(isp) \ - if ((isp)->isp_mdvec->dv_reset1) (*(isp)->isp_mdvec->dv_reset1)((isp)) +#define ISP_IRQSETUP(isp) \ + (((isp)->isp_mdvec->dv_irqsetup) ? (*(isp)->isp_mdvec->dv_irqsetup)(isp) : 0) #define ISP_DUMPREGS(isp, m) \ if ((isp)->isp_mdvec->dv_dregs) (*(isp)->isp_mdvec->dv_dregs)((isp),(m)) @@ -565,13 +562,9 @@ struct ispsoftc { * Volatile state */ - volatile uint32_t : 8, - : 2, - isp_dead : 1, - : 1, - isp_mboxbsy : 1, /* mailbox command active */ - isp_state : 3, - isp_nactive : 16; /* how many commands active */ + volatile u_int isp_mboxbsy; /* mailbox command active */ + volatile u_int isp_state; + volatile u_int isp_nactive; /* how many commands active */ volatile mbreg_t isp_curmbx; /* currently active mailbox command */ volatile uint32_t isp_reqodx; /* index of last ISP pickup */ volatile uint32_t isp_reqidx; /* index of next request */ @@ -819,6 +812,11 @@ void isp_init(ispsoftc_t *); int isp_reinit(ispsoftc_t *, int); /* + * Shutdown hardware after use. + */ +void isp_shutdown(ispsoftc_t *); + +/* * Internal Interrupt Service Routine * * The outer layers do the spade work to get the appropriate status register, |
