diff options
author | Matt Jacob <mjacob@FreeBSD.org> | 2006-10-31 05:53:29 +0000 |
---|---|---|
committer | Matt Jacob <mjacob@FreeBSD.org> | 2006-10-31 05:53:29 +0000 |
commit | fa9ed865067ef325f013a8174c94eff345a4f4ed (patch) | |
tree | 8b3b2da053646664eaa8096add01ca22cc513072 /sys/dev/advansys | |
parent | 9df92bda761535b468b198dc0bc23dc059051e8a (diff) |
Notes
Diffstat (limited to 'sys/dev/advansys')
-rw-r--r-- | sys/dev/advansys/advansys.c | 132 | ||||
-rw-r--r-- | sys/dev/advansys/advlib.c | 17 | ||||
-rw-r--r-- | sys/dev/advansys/adwcam.c | 200 |
3 files changed, 342 insertions, 7 deletions
diff --git a/sys/dev/advansys/advansys.c b/sys/dev/advansys/advansys.c index 6209d9d8fc80b..dd14a65e72ce1 100644 --- a/sys/dev/advansys/advansys.c +++ b/sys/dev/advansys/advansys.c @@ -288,8 +288,19 @@ adv_action(struct cam_sim *sim, union ccb *ccb) ccb->ccb_h.status = CAM_REQ_INVALID; xpt_done(ccb); break; +#ifdef CAM_NEW_TRAN_CODE +#define IS_CURRENT_SETTINGS(c) (c->type == CTS_TYPE_CURRENT_SETTINGS) +#define IS_USER_SETTINGS(c) (c->type == CTS_TYPE_USER_SETTINGS) +#else +#define IS_CURRENT_SETTINGS(c) (c->flags & CCB_TRANS_CURRENT_SETTINGS) +#define IS_USER_SETTINGS(c) (c->flags & CCB_TRANS_USER_SETTINGS) +#endif case XPT_SET_TRAN_SETTINGS: { +#ifdef CAM_NEW_TRAN_CODE + struct ccb_trans_settings_scsi *scsi; + struct ccb_trans_settings_spi *spi; +#endif struct ccb_trans_settings *cts; target_bit_vector targ_mask; struct adv_transinfo *tconf; @@ -304,12 +315,10 @@ adv_action(struct cam_sim *sim, union ccb *ccb) * The user must specify which type of settings he wishes * to change. */ - if (((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0) - && ((cts->flags & CCB_TRANS_USER_SETTINGS) == 0)) { + if (IS_CURRENT_SETTINGS(cts) && !IS_USER_SETTINGS(cts)) { tconf = &adv->tinfo[cts->ccb_h.target_id].current; update_type |= ADV_TRANS_GOAL; - } else if (((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) - && ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) == 0)) { + } else if (IS_USER_SETTINGS(cts) && !IS_CURRENT_SETTINGS(cts)) { tconf = &adv->tinfo[cts->ccb_h.target_id].user; update_type |= ADV_TRANS_USER; } else { @@ -318,7 +327,73 @@ adv_action(struct cam_sim *sim, union ccb *ccb) } s = splcam(); +#ifdef CAM_NEW_TRAN_CODE + scsi = &cts->proto_specific.scsi; + spi = &cts->xport_specific.spi; + if ((update_type & ADV_TRANS_GOAL) != 0) { + if ((spi->valid & CTS_SPI_VALID_DISC) != 0) { + if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0) + adv->disc_enable |= targ_mask; + else + adv->disc_enable &= ~targ_mask; + adv_write_lram_8(adv, ADVV_DISC_ENABLE_B, + adv->disc_enable); + } + + if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) { + if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) + adv->cmd_qng_enabled |= targ_mask; + else + adv->cmd_qng_enabled &= ~targ_mask; + } + } + + if ((update_type & ADV_TRANS_USER) != 0) { + if ((spi->valid & CTS_SPI_VALID_DISC) != 0) { + if ((spi->flags & CTS_SPI_VALID_DISC) != 0) + adv->user_disc_enable |= targ_mask; + else + adv->user_disc_enable &= ~targ_mask; + } + + if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) { + if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) + adv->user_cmd_qng_enabled |= targ_mask; + else + adv->user_cmd_qng_enabled &= ~targ_mask; + } + } + + /* + * If the user specifies either the sync rate, or offset, + * but not both, the unspecified parameter defaults to its + * current value in transfer negotiations. + */ + if (((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) + || ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)) { + /* + * If the user provided a sync rate but no offset, + * use the current offset. + */ + if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0) + spi->sync_offset = tconf->offset; + + /* + * If the user provided an offset but no sync rate, + * use the current sync rate. + */ + if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) + spi->sync_period = tconf->period; + adv_period_offset_to_sdtr(adv, &spi->sync_period, + &spi->sync_offset, + cts->ccb_h.target_id); + + adv_set_syncrate(adv, /*struct cam_path */NULL, + cts->ccb_h.target_id, spi->sync_period, + spi->sync_offset, update_type); + } +#else if ((update_type & ADV_TRANS_GOAL) != 0) { if ((cts->valid & CCB_TRANS_DISC_VALID) != 0) { if ((cts->flags & CCB_TRANS_DISC_ENB) != 0) @@ -382,6 +457,7 @@ adv_action(struct cam_sim *sim, union ccb *ccb) cts->ccb_h.target_id, cts->sync_period, cts->sync_offset, update_type); } +#endif splx(s); ccb->ccb_h.status = CAM_REQ_CMP; @@ -391,6 +467,10 @@ adv_action(struct cam_sim *sim, union ccb *ccb) case XPT_GET_TRAN_SETTINGS: /* Get default/user set transfer settings for the target */ { +#ifdef CAM_NEW_TRAN_CODE + struct ccb_trans_settings_scsi *scsi; + struct ccb_trans_settings_spi *spi; +#endif struct ccb_trans_settings *cts; struct adv_transinfo *tconf; target_bit_vector target_mask; @@ -399,8 +479,43 @@ adv_action(struct cam_sim *sim, union ccb *ccb) cts = &ccb->cts; target_mask = ADV_TID_TO_TARGET_MASK(cts->ccb_h.target_id); - cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB); +#ifdef CAM_NEW_TRAN_CODE + scsi = &cts->proto_specific.scsi; + spi = &cts->xport_specific.spi; + + 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; + + s = splcam(); + if (cts->type == CTS_TYPE_CURRENT_SETTINGS) { + tconf = &adv->tinfo[cts->ccb_h.target_id].current; + if ((adv->disc_enable & target_mask) != 0) + spi->flags |= CTS_SPI_FLAGS_DISC_ENB; + if ((adv->cmd_qng_enabled & target_mask) != 0) + scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; + } else { + tconf = &adv->tinfo[cts->ccb_h.target_id].user; + if ((adv->user_disc_enable & target_mask) != 0) + spi->flags |= CTS_SPI_FLAGS_DISC_ENB; + if ((adv->user_cmd_qng_enabled & target_mask) != 0) + scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; + } + spi->sync_period = tconf->period; + spi->sync_offset = tconf->offset; + splx(s); + spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT; + spi->valid = CTS_SPI_VALID_SYNC_RATE + | CTS_SPI_VALID_SYNC_OFFSET + | CTS_SPI_VALID_BUS_WIDTH + | CTS_SPI_VALID_DISC; + scsi->valid = CTS_SCSI_VALID_TQ; +#else + cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB); s = splcam(); if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0) { tconf = &adv->tinfo[cts->ccb_h.target_id].current; @@ -426,6 +541,7 @@ adv_action(struct cam_sim *sim, union ccb *ccb) | CCB_TRANS_BUS_WIDTH_VALID | CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID; +#endif ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); break; @@ -477,6 +593,12 @@ adv_action(struct cam_sim *sim, union ccb *ccb) strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); cpi->unit_number = cam_sim_unit(sim); cpi->ccb_h.status = CAM_REQ_CMP; +#ifdef CAM_NEW_TRAN_CODE + cpi->transport = XPORT_SPI; + cpi->transport_version = 2; + cpi->protocol = PROTO_SCSI; + cpi->protocol_version = SCSI_REV_2; +#endif xpt_done(ccb); break; } diff --git a/sys/dev/advansys/advlib.c b/sys/dev/advansys/advlib.c index 565b8c2bc594b..04c15a4940d1e 100644 --- a/sys/dev/advansys/advlib.c +++ b/sys/dev/advansys/advlib.c @@ -1135,11 +1135,26 @@ adv_set_syncrate(struct adv_softc *adv, struct cam_path *path, * new transfer parameters. */ struct ccb_trans_settings neg; - + memset(&neg, 0, sizeof (neg)); +#ifdef CAM_NEW_TRAN_CODE + struct ccb_trans_settings_spi *spi = + &neg.xport_specific.spi; + + neg.protocol = PROTO_SCSI; + neg.protocol_version = SCSI_REV_2; + neg.transport = XPORT_SPI; + neg.transport_version = 2; + + spi->sync_offset = offset; + spi->sync_period = period; + spi->valid |= CTS_SPI_VALID_SYNC_OFFSET; + spi->valid |= CTS_SPI_VALID_SYNC_RATE; +#else neg.sync_period = period; neg.sync_offset = offset; neg.valid = CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID; +#endif xpt_setup_ccb(&neg.ccb_h, path, /*priority*/1); xpt_async(AC_TRANSFER_NEG, path, &neg); } diff --git a/sys/dev/advansys/adwcam.c b/sys/dev/advansys/adwcam.c index 5de2a48b08a84..2f3c33b4adc50 100644 --- a/sys/dev/advansys/adwcam.c +++ b/sys/dev/advansys/adwcam.c @@ -525,6 +525,10 @@ adw_action(struct cam_sim *sim, union ccb *ccb) break; case XPT_SET_TRAN_SETTINGS: { +#ifdef CAM_NEW_TRAN_CODE + struct ccb_trans_settings_scsi *scsi; + struct ccb_trans_settings_spi *spi; +#endif struct ccb_trans_settings *cts; u_int target_mask; int s; @@ -533,6 +537,119 @@ adw_action(struct cam_sim *sim, union ccb *ccb) target_mask = 0x01 << ccb->ccb_h.target_id; s = splcam(); +#ifdef CAM_NEW_TRAN_CODE + scsi = &cts->proto_specific.scsi; + spi = &cts->xport_specific.spi; + if (cts->type == CTS_TYPE_CURRENT_SETTINGS) { + u_int sdtrdone; + + sdtrdone = adw_lram_read_16(adw, ADW_MC_SDTR_DONE); + if ((spi->valid & CTS_SPI_VALID_DISC) != 0) { + u_int discenb; + + discenb = + adw_lram_read_16(adw, ADW_MC_DISC_ENABLE); + + if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0) + discenb |= target_mask; + else + discenb &= ~target_mask; + + adw_lram_write_16(adw, ADW_MC_DISC_ENABLE, + discenb); + } + + if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) { + + if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) + adw->tagenb |= target_mask; + else + adw->tagenb &= ~target_mask; + } + + if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) { + u_int wdtrenb_orig; + u_int wdtrenb; + u_int wdtrdone; + + wdtrenb_orig = + adw_lram_read_16(adw, ADW_MC_WDTR_ABLE); + wdtrenb = wdtrenb_orig; + wdtrdone = adw_lram_read_16(adw, + ADW_MC_WDTR_DONE); + switch (spi->bus_width) { + case MSG_EXT_WDTR_BUS_32_BIT: + case MSG_EXT_WDTR_BUS_16_BIT: + wdtrenb |= target_mask; + break; + case MSG_EXT_WDTR_BUS_8_BIT: + default: + wdtrenb &= ~target_mask; + break; + } + if (wdtrenb != wdtrenb_orig) { + adw_lram_write_16(adw, + ADW_MC_WDTR_ABLE, + wdtrenb); + wdtrdone &= ~target_mask; + adw_lram_write_16(adw, + ADW_MC_WDTR_DONE, + wdtrdone); + /* Wide negotiation forces async */ + sdtrdone &= ~target_mask; + adw_lram_write_16(adw, + ADW_MC_SDTR_DONE, + sdtrdone); + } + } + + if (((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) + || ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)) { + u_int sdtr_orig; + u_int sdtr; + u_int sdtrable_orig; + u_int sdtrable; + + sdtr = adw_get_chip_sdtr(adw, + ccb->ccb_h.target_id); + sdtr_orig = sdtr; + sdtrable = adw_lram_read_16(adw, + ADW_MC_SDTR_ABLE); + sdtrable_orig = sdtrable; + + if ((spi->valid + & CTS_SPI_VALID_SYNC_RATE) != 0) { + + sdtr = + adw_find_sdtr(adw, + spi->sync_period); + } + + if ((spi->valid + & CTS_SPI_VALID_SYNC_OFFSET) != 0) { + if (spi->sync_offset == 0) + sdtr = ADW_MC_SDTR_ASYNC; + } + + if (sdtr == ADW_MC_SDTR_ASYNC) + sdtrable &= ~target_mask; + else + sdtrable |= target_mask; + if (sdtr != sdtr_orig + || sdtrable != sdtrable_orig) { + adw_set_chip_sdtr(adw, + ccb->ccb_h.target_id, + sdtr); + sdtrdone &= ~target_mask; + adw_lram_write_16(adw, ADW_MC_SDTR_ABLE, + sdtrable); + adw_lram_write_16(adw, ADW_MC_SDTR_DONE, + sdtrdone); + + } + } + } +#else if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0) { u_int sdtrdone; @@ -642,6 +759,7 @@ adw_action(struct cam_sim *sim, union ccb *ccb) } } } +#endif splx(s); ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); @@ -650,12 +768,85 @@ adw_action(struct cam_sim *sim, union ccb *ccb) case XPT_GET_TRAN_SETTINGS: /* Get default/user set transfer settings for the target */ { +#ifdef CAM_NEW_TRAN_CODE + struct ccb_trans_settings_scsi *scsi; + struct ccb_trans_settings_spi *spi; +#endif struct ccb_trans_settings *cts; u_int target_mask; cts = &ccb->cts; target_mask = 0x01 << ccb->ccb_h.target_id; - if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) { +#ifdef CAM_NEW_TRAN_CODE + cts->protocol = PROTO_SCSI; + cts->protocol_version = SCSI_REV_2; + cts->transport = XPORT_SPI; + cts->transport_version = 2; + + scsi = &cts->proto_specific.scsi; + spi = &cts->xport_specific.spi; + if (cts->type == CTS_TYPE_CURRENT_SETTINGS) { + u_int mc_sdtr; + + spi->flags = 0; + if ((adw->user_discenb & target_mask) != 0) + spi->flags |= CTS_SPI_FLAGS_DISC_ENB; + + if ((adw->user_tagenb & target_mask) != 0) + scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; + + if ((adw->user_wdtr & target_mask) != 0) + spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; + else + spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT; + + mc_sdtr = adw_get_user_sdtr(adw, ccb->ccb_h.target_id); + spi->sync_period = adw_find_period(adw, mc_sdtr); + if (spi->sync_period != 0) + spi->sync_offset = 15; /* XXX ??? */ + else + spi->sync_offset = 0; + + + } else { + u_int targ_tinfo; + + spi->flags = 0; + if ((adw_lram_read_16(adw, ADW_MC_DISC_ENABLE) + & target_mask) != 0) + spi->flags |= CTS_SPI_FLAGS_DISC_ENB; + + if ((adw->tagenb & target_mask) != 0) + scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; + + targ_tinfo = + adw_lram_read_16(adw, + ADW_MC_DEVICE_HSHK_CFG_TABLE + + (2 * ccb->ccb_h.target_id)); + + if ((targ_tinfo & ADW_HSHK_CFG_WIDE_XFR) != 0) + spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; + else + spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT; + + spi->sync_period = + adw_hshk_cfg_period_factor(targ_tinfo); + + spi->sync_offset = targ_tinfo & ADW_HSHK_CFG_OFFSET; + if (spi->sync_period == 0) + spi->sync_offset = 0; + + if (spi->sync_offset == 0) + spi->sync_period = 0; + } + + spi->valid = CTS_SPI_VALID_SYNC_RATE + | CTS_SPI_VALID_SYNC_OFFSET + | CTS_SPI_VALID_BUS_WIDTH + | CTS_SPI_VALID_DISC; + scsi->valid = CTS_SCSI_VALID_TQ; +#else + if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) { u_int mc_sdtr; cts->flags = 0; @@ -719,6 +910,7 @@ adw_action(struct cam_sim *sim, union ccb *ccb) | CCB_TRANS_BUS_WIDTH_VALID | CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID; +#endif ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); break; @@ -773,6 +965,12 @@ adw_action(struct cam_sim *sim, union ccb *ccb) strncpy(cpi->hba_vid, "AdvanSys", HBA_IDLEN); strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); cpi->unit_number = cam_sim_unit(sim); +#ifdef CAM_NEW_TRAN_CODE + cpi->transport = XPORT_SPI; + cpi->transport_version = 2; + cpi->protocol = PROTO_SCSI; + cpi->protocol_version = SCSI_REV_2; +#endif cpi->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); break; |