diff options
author | mjacob <mjacob@FreeBSD.org> | 2001-07-04 18:54:29 +0000 |
---|---|---|
committer | mjacob <mjacob@FreeBSD.org> | 2001-07-04 18:54:29 +0000 |
commit | 804d4fc2040f1f3f3892bd6008aeb124580da535 (patch) | |
tree | 61051a9e1b7ff611a993db1a628cdebf7f658696 | |
parent | 354b370854482bf6b20fdb6c6e202b6eca2ff1c7 (diff) | |
download | FreeBSD-src-804d4fc2040f1f3f3892bd6008aeb124580da535.zip FreeBSD-src-804d4fc2040f1f3f3892bd6008aeb124580da535.tar.gz |
Add CAM_NEW_TRAN_CODE support. Use correct CAMLOCK_2_ISPLOCK macros.
For fibre channel, start going for the gusto and using AC_FOUND_DEVICE
and AC_LOST_DEVICE calls to xpt_async when devices appear and disappear
as the loop or fabric changes.
ISPASYNC_FW_CRASH is the async event code where the platform layer
deals with a firmware crash.
-rw-r--r-- | sys/dev/isp/isp_freebsd.c | 265 |
1 files changed, 234 insertions, 31 deletions
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c index 008da7b..1edf005 100644 --- a/sys/dev/isp/isp_freebsd.c +++ b/sys/dev/isp/isp_freebsd.c @@ -1954,31 +1954,29 @@ isp_action(struct cam_sim *sim, union ccb *ccb) xpt_done(ccb); break; } +#ifdef CAM_NEW_TRAN_CODE +#define IS_CURRENT_SETTINGS(c) (c->type == CTS_TYPE_CURRENT_SETTINGS) +#else +#define IS_CURRENT_SETTINGS(c) (c->flags & CCB_TRANS_CURRENT_SETTINGS) +#endif case XPT_SET_TRAN_SETTINGS: /* Nexus Settings */ - cts = &ccb->cts; tgt = cts->ccb_h.target_id; CAMLOCK_2_ISPLOCK(isp); if (IS_SCSI(isp)) { +#ifndef CAM_NEW_TRAN_CODE sdparam *sdp = isp->isp_param; u_int16_t *dptr; bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path)); sdp += bus; -#if 0 - if (cts->flags & CCB_TRANS_CURRENT_SETTINGS) - dptr = &sdp->isp_devparam[tgt].cur_dflags; - else - dptr = &sdp->isp_devparam[tgt].dev_flags; -#else /* * We always update (internally) from dev_flags * so any request to change settings just gets * vectored to that location. */ dptr = &sdp->isp_devparam[tgt].dev_flags; -#endif /* * Note that these operations affect the @@ -2025,26 +2023,87 @@ isp_action(struct cam_sim *sim, union ccb *ccb) *dptr &= ~DPARM_SYNC; } *dptr |= DPARM_SAFE_DFLT; +#else + struct ccb_trans_settings_scsi *scsi = + &cts->proto_specific.scsi; + struct ccb_trans_settings_spi *spi = + &cts->xport_specific.spi; + sdparam *sdp = isp->isp_param; + u_int16_t *dptr; + + bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path)); + sdp += bus; + /* + * We always update (internally) from dev_flags + * so any request to change settings just gets + * vectored to that location. + */ + dptr = &sdp->isp_devparam[tgt].dev_flags; + + if ((spi->valid & CTS_SPI_VALID_DISC) != 0) { + if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0) + *dptr |= DPARM_DISC; + else + *dptr &= ~DPARM_DISC; + } + + if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) { + if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) + *dptr |= DPARM_TQING; + else + *dptr &= ~DPARM_TQING; + } + + if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) { + if (spi->bus_width == MSG_EXT_WDTR_BUS_16_BIT) + *dptr |= DPARM_WIDE; + else + *dptr &= ~DPARM_WIDE; + } + + /* + * XXX: FIX ME + */ + if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) && + (spi->valid & CTS_SPI_VALID_SYNC_RATE)) { + *dptr |= DPARM_SYNC; + isp_prt(isp, ISP_LOGDEBUG0, + "enabling synchronous mode, but ignoring " + "setting to period 0x%x offset 0x%x", + spi->sync_period, spi->sync_offset); + } else if (spi->sync_period && spi->sync_offset) { + *dptr |= DPARM_SYNC; + isp_prt(isp, ISP_LOGDEBUG0, + "enabling synchronous mode (1), but ignoring" + " setting to period 0x%x offset 0x%x", + spi->sync_period, spi->sync_offset); + } else { + *dptr &= ~DPARM_SYNC; + } +#endif isp_prt(isp, ISP_LOGDEBUG0, "%d.%d set %s period 0x%x offset 0x%x flags 0x%x", - bus, tgt, (cts->flags & CCB_TRANS_CURRENT_SETTINGS)? - "current" : "user", - sdp->isp_devparam[tgt].sync_period, + bus, tgt, IS_CURRENT_SETTINGS(cts)? "current" : + "user", sdp->isp_devparam[tgt].sync_period, sdp->isp_devparam[tgt].sync_offset, sdp->isp_devparam[tgt].dev_flags); sdp->isp_devparam[tgt].dev_update = 1; isp->isp_update |= (1 << bus); + } else { + /* + * What, if anything, are we supposed to do? + */ } ISPLOCK_2_CAMLOCK(isp); ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); break; - case XPT_GET_TRAN_SETTINGS: - cts = &ccb->cts; tgt = cts->ccb_h.target_id; + CAMLOCK_2_ISPLOCK(isp); if (IS_FC(isp)) { +#ifndef CAM_NEW_TRAN_CODE /* * a lot of normal SCSI things don't make sense. */ @@ -2058,14 +2117,41 @@ isp_action(struct cam_sim *sim, union ccb *ccb) * (above) a 'base' transfer speed to be gigabit. */ cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; +#else + fcparam *fcp = isp->isp_param; + struct ccb_trans_settings_fc *fc = + &cts->xport_specific.fc; + + cts->protocol = PROTO_SCSI; + cts->protocol_version = SCSI_REV_2; + cts->transport = XPORT_FC; + cts->transport_version = 0; + + fc->valid = CTS_FC_VALID_SPEED; + fc->bitrate = 100000; + if (tgt > 0 && tgt < MAX_FC_TARG) { + struct lportdb *lp = &fcp->portdb[tgt]; + fc->wwnn = lp->node_wwn; + fc->wwpn = lp->port_wwn; + fc->port = lp->portid; + fc->valid |= CTS_FC_VALID_WWNN | + CTS_FC_VALID_WWPN | CTS_FC_VALID_PORT; + } +#endif } else { +#ifdef CAM_NEW_TRAN_CODE + struct ccb_trans_settings_scsi *scsi = + &cts->proto_specific.scsi; + struct ccb_trans_settings_spi *spi = + &cts->xport_specific.spi; +#endif sdparam *sdp = isp->isp_param; - u_int16_t dval, pval, oval; int bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path)); + u_int16_t dval, pval, oval; - CAMLOCK_2_ISPLOCK(isp); sdp += bus; - if (cts->flags & CCB_TRANS_CURRENT_SETTINGS) { + + if (IS_CURRENT_SETTINGS(cts)) { sdp->isp_devparam[tgt].dev_refresh = 1; isp->isp_update |= (1 << bus); (void) isp_control(isp, ISPCTL_UPDATE_PARAMS, @@ -2079,6 +2165,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb) pval = sdp->isp_devparam[tgt].sync_period; } +#ifndef CAM_NEW_TRAN_CODE cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB); if (dval & DPARM_DISC) { @@ -2102,12 +2189,45 @@ isp_action(struct cam_sim *sim, union ccb *ccb) CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID; } - ISPLOCK_2_CAMLOCK(isp); +#else + cts->protocol = PROTO_SCSI; + cts->protocol_version = SCSI_REV_2; + cts->transport = XPORT_SPI; + cts->transport_version = 2; + + scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; + spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; + if (dval & DPARM_DISC) { + spi->flags |= CTS_SPI_FLAGS_DISC_ENB; + } + if (dval & DPARM_TQING) { + scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; + } + if ((dval & DPARM_SYNC) && oval != 0) { + spi->sync_offset = oval; + spi->sync_period = pval; + spi->valid |= CTS_SPI_VALID_SYNC_OFFSET; + spi->valid |= CTS_SPI_VALID_SYNC_RATE; + } + spi->valid |= CTS_SPI_VALID_BUS_WIDTH; + if (dval & DPARM_WIDE) { + spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; + } else { + spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT; + } + if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) { + scsi->valid = CTS_SCSI_VALID_TQ; + spi->valid |= CTS_SPI_VALID_DISC; + } else { + scsi->valid = 0; + } +#endif isp_prt(isp, ISP_LOGDEBUG0, "%d.%d get %s period 0x%x offset 0x%x flags 0x%x", - bus, tgt, (cts->flags & CCB_TRANS_CURRENT_SETTINGS)? - "current" : "user", pval, oval, dval); + bus, tgt, IS_CURRENT_SETTINGS(cts)? "current" : + "user", pval, oval, dval); } + ISPLOCK_2_CAMLOCK(isp); ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); break; @@ -2193,6 +2313,10 @@ isp_action(struct cam_sim *sim, union ccb *ccb) */ cpi->base_transfer_speed = 100000; cpi->hba_inquiry = PI_TAG_ABLE; +#ifdef CAM_NEW_TRAN_CODE + cpi->transport = XPORT_FC; + cpi->transport_version = 0; /* WHAT'S THIS FOR? */ +#endif } else { sdparam *sdp = isp->isp_param; sdp += cam_sim_bus(xpt_path_sim(cpi->ccb_h.path)); @@ -2200,7 +2324,15 @@ isp_action(struct cam_sim *sim, union ccb *ccb) cpi->hba_misc = 0; cpi->initiator_id = sdp->isp_initiator_id; cpi->base_transfer_speed = 3300; +#ifdef CAM_NEW_TRAN_CODE + cpi->transport = XPORT_SPI; + cpi->transport_version = 2; /* WHAT'S THIS FOR? */ +#endif } +#ifdef CAM_NEW_TRAN_CODE + cpi->protocol = PROTO_SCSI; + cpi->protocol_version = SCSI_REV_2; +#endif strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); strncpy(cpi->hba_vid, "Qlogic", HBA_IDLEN); strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); @@ -2301,11 +2433,17 @@ isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg) switch (cmd) { case ISPASYNC_NEW_TGT_PARAMS: { +#ifdef CAM_NEW_TRAN_CODE + struct ccb_trans_settings_scsi *scsi; + struct ccb_trans_settings_spi *spi; +#endif int flags, tgt; sdparam *sdp = isp->isp_param; - struct ccb_trans_settings neg; + struct ccb_trans_settings cts; struct cam_path *tmppath; + bzero(&cts, sizeof (struct ccb_trans_settings)); + tgt = *((int *)arg); bus = (tgt >> 16) & 0xffff; tgt &= 0xffff; @@ -2320,29 +2458,63 @@ isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg) break; } flags = sdp->isp_devparam[tgt].cur_dflags; - neg.valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID; +#ifdef CAM_NEW_TRAN_CODE + cts.type = CTS_TYPE_CURRENT_SETTINGS; + cts.protocol = PROTO_SCSI; + cts.transport = XPORT_SPI; + + scsi = &cts.proto_specific.scsi; + spi = &cts.xport_specific.spi; + + if (flags & DPARM_TQING) { + scsi->valid |= CTS_SCSI_VALID_TQ; + scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; + spi->flags |= CTS_SPI_FLAGS_TAG_ENB; + } + if (flags & DPARM_DISC) { - neg.flags |= CCB_TRANS_DISC_ENB; + spi->valid |= CTS_SPI_VALID_DISC; + spi->flags |= CTS_SPI_FLAGS_DISC_ENB; + } + spi->flags |= CTS_SPI_VALID_BUS_WIDTH; + if (flags & DPARM_WIDE) { + spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; + } else { + spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT; + } + if (flags & DPARM_SYNC) { + spi->valid |= CTS_SPI_VALID_SYNC_RATE; + spi->valid |= CTS_SPI_VALID_SYNC_OFFSET; + spi->sync_period = sdp->isp_devparam[tgt].cur_period; + spi->sync_offset = sdp->isp_devparam[tgt].cur_offset; + } +#else + cts.flags = CCB_TRANS_CURRENT_SETTINGS; + cts.valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID; + if (flags & DPARM_DISC) { + cts.flags |= CCB_TRANS_DISC_ENB; } if (flags & DPARM_TQING) { - neg.flags |= CCB_TRANS_TAG_ENB; + cts.flags |= CCB_TRANS_TAG_ENB; } - neg.valid |= CCB_TRANS_BUS_WIDTH_VALID; - neg.bus_width = (flags & DPARM_WIDE)? + cts.valid |= CCB_TRANS_BUS_WIDTH_VALID; + cts.bus_width = (flags & DPARM_WIDE)? MSG_EXT_WDTR_BUS_8_BIT : MSG_EXT_WDTR_BUS_16_BIT; - neg.sync_period = sdp->isp_devparam[tgt].cur_period; - neg.sync_offset = sdp->isp_devparam[tgt].cur_offset; + cts.sync_period = sdp->isp_devparam[tgt].cur_period; + cts.sync_offset = sdp->isp_devparam[tgt].cur_offset; if (flags & DPARM_SYNC) { - neg.valid |= + cts.valid |= CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID; } +#endif isp_prt(isp, ISP_LOGDEBUG2, "NEW_TGT_PARAMS bus %d tgt %d period %x offset %x flags %x", - bus, tgt, neg.sync_period, neg.sync_offset, flags); - xpt_setup_ccb(&neg.ccb_h, tmppath, 1); + bus, tgt, sdp->isp_devparam[tgt].cur_period, + sdp->isp_devparam[tgt].cur_offset, flags); + xpt_setup_ccb(&cts.ccb_h, tmppath, 1); ISPLOCK_2_CAMLOCK(isp); - xpt_async(AC_TRANSFER_NEG, tmppath, &neg); + xpt_async(AC_TRANSFER_NEG, tmppath, &cts); CAMLOCK_2_ISPLOCK(isp); xpt_free_path(tmppath); break; @@ -2410,6 +2582,7 @@ isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg) break; case ISPASYNC_PROMENADE: { + struct cam_path *tmppath; const char *fmt = "Target %d (Loop 0x%x) Port ID 0x%x " "(role %s) %s\n Port WWN 0x%08x%08x\n Node WWN 0x%08x%08x"; static const char *roles[4] = { @@ -2426,6 +2599,21 @@ isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg) (u_int32_t) (lp->port_wwn & 0xffffffffLL), (u_int32_t) (lp->node_wwn >> 32), (u_int32_t) (lp->node_wwn & 0xffffffffLL)); + + if (xpt_create_path(&tmppath, NULL, cam_sim_path(isp->isp_sim), + (target_id_t)tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + break; + } + if (lp->valid && (lp->roles & + (SVC3_INI_ROLE >> SVC3_ROLE_SHIFT))) { + ISPLOCK_2_CAMLOCK(isp); + xpt_async(AC_FOUND_DEVICE, tmppath, NULL); + } else { + ISPLOCK_2_CAMLOCK(isp); + xpt_async(AC_LOST_DEVICE, tmppath, NULL); + } + CAMLOCK_2_ISPLOCK(isp); + xpt_free_path(tmppath); break; } case ISPASYNC_CHANGE_NOTIFY: @@ -2598,6 +2786,21 @@ isp_async(struct ispsoftc *isp, ispasync_t cmd, void *arg) } break; #endif + case ISPASYNC_FW_CRASH: + { + u_int16_t mbox1, mbox6; + mbox1 = ISP_READ(isp, OUTMAILBOX1); + if (IS_DUALBUS(isp)) { + mbox6 = ISP_READ(isp, OUTMAILBOX6); + } else { + mbox6 = 0; + } + isp_prt(isp, ISP_LOGERR, + "Internal Firmware on bus %d Error @ RISC Address 0x%x", + mbox6, mbox1); + isp_reinit(isp); + break; + } default: isp_prt(isp, ISP_LOGERR, "unknown isp_async event %d", cmd); rv = -1; |