diff options
author | groudier <groudier@FreeBSD.org> | 2001-03-24 21:11:31 +0000 |
---|---|---|
committer | groudier <groudier@FreeBSD.org> | 2001-03-24 21:11:31 +0000 |
commit | 4887732081c545aab296a7932db991ff2ce1fa87 (patch) | |
tree | 1f0fddcbbac304c925f9ab931f00cd7b3af3dd91 /sys/dev/sym/sym_hipd.c | |
parent | 250b6a9c42af07b528f4634a8bfcc4aadb3be389 (diff) | |
download | FreeBSD-src-4887732081c545aab296a7932db991ff2ce1fa87.zip FreeBSD-src-4887732081c545aab296a7932db991ff2ce1fa87.tar.gz |
Add #if'ed support for the future option CAM_NEW_TRAN_CODE.
Diffstat (limited to 'sys/dev/sym/sym_hipd.c')
-rw-r--r-- | sys/dev/sym/sym_hipd.c | 293 |
1 files changed, 236 insertions, 57 deletions
diff --git a/sys/dev/sym/sym_hipd.c b/sys/dev/sym/sym_hipd.c index fed183b..eebd097 100644 --- a/sys/dev/sym/sym_hipd.c +++ b/sys/dev/sym/sym_hipd.c @@ -60,6 +60,7 @@ #define SYM_DRIVER_NAME "sym-1.6.5-20000902" /* #define SYM_DEBUG_GENERIC_SUPPORT */ +/* #define CAM_NEW_TRAN_CODE */ #include <sys/param.h> @@ -137,6 +138,13 @@ typedef u_int16_t u16; typedef u_int32_t u32; /* + * From 'cam.error_recovery_diffs.20010313.context' patch. + */ +#ifdef CAM_NEW_TRAN_CODE +#define FreeBSD_New_Tran_Settings +#endif /* CAM_NEW_TRAN_CODE */ + +/* * Driver definitions. */ #include <dev/sym/sym_defs.h> @@ -1240,6 +1248,10 @@ typedef struct sym_hcb *hcb_p; * Gather negotiable parameters value */ struct sym_trans { +#ifdef FreeBSD_New_Tran_Settings + u8 scsi_version; + u8 spi_version; +#endif u8 period; u8 offset; u8 width; @@ -2943,6 +2955,10 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram) for (i = 0 ; i < SYM_CONF_MAX_TARGET ; i++) { tcb_p tp = &np->target[i]; +#ifdef FreeBSD_New_Tran_Settings + tp->tinfo.user.scsi_version = tp->tinfo.current.scsi_version= 2; + tp->tinfo.user.spi_version = tp->tinfo.current.spi_version = 2; +#endif tp->tinfo.user.period = np->minsync; tp->tinfo.user.offset = np->maxoffs; tp->tinfo.user.width = np->maxwide ? BUS_16_BIT : BUS_8_BIT; @@ -2960,6 +2976,9 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram) tp->tinfo.user.width == BUS_16_BIT) { tp->tinfo.user.options |= PPR_OPT_DT; tp->tinfo.user.offset = np->maxoffs_dt; +#ifdef FreeBSD_New_Tran_Settings + tp->tinfo.user.spi_version = 3; +#endif } } @@ -3629,13 +3648,91 @@ sym_getsync(hcb_p np, u_char dt, u_char sfac, u_char *divp, u_char *fakp) } /* + * Tell the SCSI layer about the new transfer parameters. + */ +static void +sym_xpt_async_transfer_neg(hcb_p np, int target, u_int spi_valid) +{ + struct ccb_trans_settings cts; + struct cam_path *path; + int sts; + tcb_p tp = &np->target[target]; + + sts = xpt_create_path(&path, NULL, cam_sim_path(np->sim), target, + CAM_LUN_WILDCARD); + if (sts != CAM_REQ_CMP) + return; + + bzero(&cts, sizeof(cts)); + +#ifdef FreeBSD_New_Tran_Settings +#define cts__scsi (cts.proto_specific.scsi) +#define cts__spi (cts.xport_specific.spi) + + cts.type = CTS_TYPE_CURRENT_SETTINGS; + cts.protocol = PROTO_SCSI; + cts.transport = XPORT_SPI; + cts.protocol_version = tp->tinfo.current.scsi_version; + cts.transport_version = tp->tinfo.current.spi_version; + + cts__spi.valid = spi_valid; + if (spi_valid & CTS_SPI_VALID_SYNC_RATE) + cts__spi.sync_period = tp->tinfo.current.period; + if (spi_valid & CTS_SPI_VALID_SYNC_OFFSET) + cts__spi.sync_offset = tp->tinfo.current.offset; + if (spi_valid & CTS_SPI_VALID_BUS_WIDTH) + cts__spi.bus_width = tp->tinfo.current.width; + if (spi_valid & CTS_SPI_VALID_PPR_OPTIONS) + cts__spi.ppr_options = tp->tinfo.current.options; +#undef cts__spi +#undef cts__scsi +#else + cts.valid = spi_valid; + if (spi_valid & CCB_TRANS_SYNC_RATE_VALID) + cts.sync_period = tp->tinfo.current.period; + if (spi_valid & CCB_TRANS_SYNC_OFFSET_VALID) + cts.sync_offset = tp->tinfo.current.offset; + if (spi_valid & CCB_TRANS_BUS_WIDTH_VALID) + cts.bus_width = tp->tinfo.current.width; +#endif + xpt_setup_ccb(&cts.ccb_h, path, /*priority*/1); + xpt_async(AC_TRANSFER_NEG, path, &cts); + xpt_free_path(path); +} + +#ifdef FreeBSD_New_Tran_Settings +#define SYM_SPI_VALID_WDTR \ + CTS_SPI_VALID_BUS_WIDTH | \ + CTS_SPI_VALID_SYNC_RATE | \ + CTS_SPI_VALID_SYNC_OFFSET +#define SYM_SPI_VALID_SDTR \ + CTS_SPI_VALID_SYNC_RATE | \ + CTS_SPI_VALID_SYNC_OFFSET +#define SYM_SPI_VALID_PPR \ + CTS_SPI_VALID_PPR_OPTIONS | \ + CTS_SPI_VALID_BUS_WIDTH | \ + CTS_SPI_VALID_SYNC_RATE | \ + CTS_SPI_VALID_SYNC_OFFSET +#else +#define SYM_SPI_VALID_WDTR \ + CCB_TRANS_BUS_WIDTH_VALID | \ + CCB_TRANS_SYNC_RATE_VALID | \ + CCB_TRANS_SYNC_OFFSET_VALID +#define SYM_SPI_VALID_SDTR \ + CCB_TRANS_SYNC_RATE_VALID | \ + CCB_TRANS_SYNC_OFFSET_VALID +#define SYM_SPI_VALID_PPR \ + CCB_TRANS_BUS_WIDTH_VALID | \ + CCB_TRANS_SYNC_RATE_VALID | \ + CCB_TRANS_SYNC_OFFSET_VALID +#endif + +/* * We received a WDTR. * Let everything be aware of the changes. */ static void sym_setwide(hcb_p np, ccb_p cp, u_char wide) { - struct ccb_trans_settings neg; - union ccb *ccb = cp->cam_ccb; tcb_p tp = &np->target[cp->target]; sym_settrans(np, cp, 0, 0, 0, wide, 0, 0); @@ -3647,14 +3744,8 @@ static void sym_setwide(hcb_p np, ccb_p cp, u_char wide) tp->tinfo.current.offset = 0; tp->tinfo.current.period = 0; tp->tinfo.current.options = 0; - neg.bus_width = wide ? BUS_16_BIT : BUS_8_BIT; - neg.sync_period = tp->tinfo.current.period; - neg.sync_offset = tp->tinfo.current.offset; - neg.valid = CCB_TRANS_BUS_WIDTH_VALID - | CCB_TRANS_SYNC_RATE_VALID - | CCB_TRANS_SYNC_OFFSET_VALID; - xpt_setup_ccb(&neg.ccb_h, ccb->ccb_h.path, /*priority*/1); - xpt_async(AC_TRANSFER_NEG, ccb->ccb_h.path, &neg); + + sym_xpt_async_transfer_neg(np, cp->target, SYM_SPI_VALID_WDTR); } /* @@ -3664,8 +3755,6 @@ static void sym_setwide(hcb_p np, ccb_p cp, u_char wide) static void sym_setsync(hcb_p np, ccb_p cp, u_char ofs, u_char per, u_char div, u_char fak) { - struct ccb_trans_settings neg; - union ccb *ccb = cp->cam_ccb; tcb_p tp = &np->target[cp->target]; u_char wide = (cp->phys.select.sel_scntl3 & EWS) ? 1 : 0; @@ -3677,12 +3766,8 @@ sym_setsync(hcb_p np, ccb_p cp, u_char ofs, u_char per, u_char div, u_char fak) tp->tinfo.goal.period = tp->tinfo.current.period = per; tp->tinfo.goal.offset = tp->tinfo.current.offset = ofs; tp->tinfo.goal.options = tp->tinfo.current.options = 0; - neg.sync_period = tp->tinfo.current.period; - neg.sync_offset = tp->tinfo.current.offset; - neg.valid = CCB_TRANS_SYNC_RATE_VALID - | CCB_TRANS_SYNC_OFFSET_VALID; - xpt_setup_ccb(&neg.ccb_h, ccb->ccb_h.path, /*priority*/1); - xpt_async(AC_TRANSFER_NEG, ccb->ccb_h.path, &neg); + + sym_xpt_async_transfer_neg(np, cp->target, SYM_SPI_VALID_SDTR); } /* @@ -3692,8 +3777,6 @@ sym_setsync(hcb_p np, ccb_p cp, u_char ofs, u_char per, u_char div, u_char fak) static void sym_setpprot(hcb_p np, ccb_p cp, u_char dt, u_char ofs, u_char per, u_char wide, u_char div, u_char fak) { - struct ccb_trans_settings neg; - union ccb *ccb = cp->cam_ccb; tcb_p tp = &np->target[cp->target]; sym_settrans(np, cp, dt, ofs, per, wide, div, fak); @@ -3705,14 +3788,8 @@ static void sym_setpprot(hcb_p np, ccb_p cp, u_char dt, u_char ofs, tp->tinfo.goal.period = tp->tinfo.current.period = per; tp->tinfo.goal.offset = tp->tinfo.current.offset = ofs; tp->tinfo.goal.options = tp->tinfo.current.options = dt; - neg.sync_period = tp->tinfo.current.period; - neg.sync_offset = tp->tinfo.current.offset; - neg.bus_width = wide ? BUS_16_BIT : BUS_8_BIT; - neg.valid = CCB_TRANS_BUS_WIDTH_VALID - | CCB_TRANS_SYNC_RATE_VALID - | CCB_TRANS_SYNC_OFFSET_VALID; - xpt_setup_ccb(&neg.ccb_h, ccb->ccb_h.path, /*priority*/1); - xpt_async(AC_TRANSFER_NEG, ccb->ccb_h.path, &neg); + + sym_xpt_async_transfer_neg(np, cp->target, SYM_SPI_VALID_PPR); } /* @@ -4943,6 +5020,10 @@ static void sym_sir_bad_scsi_status(hcb_p np, int num, ccb_p cp) */ cp->sensecmd[0] = 0x03; cp->sensecmd[1] = cp->lun << 5; +#ifdef FreeBSD_New_Tran_Settings + if (tp->tinfo.current.scsi_version > 2 || cp->lun > 7) + cp->sensecmd[1] = 0; +#endif cp->sensecmd[4] = SYM_SNS_BBUF_LEN; cp->data_len = SYM_SNS_BBUF_LEN; @@ -8366,28 +8447,28 @@ static void sym_action2(struct cam_sim *sim, union ccb *ccb) tp = &np->target[ccb_h->target_id]; /* - * Update our transfer settings (basically WIDE/SYNC). - * These features are to be handled in a per target - * basis according to SCSI specifications. - */ - if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) - sym_update_trans(np, tp, &tp->tinfo.user, cts); - - if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0) - sym_update_trans(np, tp, &tp->tinfo.goal, cts); - - /* - * Update our disconnect and tag settings. - * SCSI requires CmdQue feature to be handled in a per - * device (logical unit) basis. + * Update SPI transport settings in TARGET control block. + * Update SCSI device settings in LUN control block. */ lp = sym_lp(np, tp, ccb_h->target_lun); - if (lp) { - if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) - sym_update_dflags(np, &lp->user_flags, cts); - if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0) +#ifdef FreeBSD_New_Tran_Settings + if (cts->type == CTS_TYPE_CURRENT_SETTINGS) { +#else + if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0) { +#endif + sym_update_trans(np, tp, &tp->tinfo.goal, cts); + if (lp) sym_update_dflags(np, &lp->current_flags, cts); } +#ifdef FreeBSD_New_Tran_Settings + if (cts->type == CTS_TYPE_USER_SETTINGS) { +#else + if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) { +#endif + sym_update_trans(np, tp, &tp->tinfo.user, cts); + if (lp) + sym_update_dflags(np, &lp->user_flags, cts); + } sym_xpt_done2(np, ccb, CAM_REQ_CMP); break; @@ -8402,6 +8483,45 @@ static void sym_action2(struct cam_sim *sim, union ccb *ccb) tp = &np->target[ccb_h->target_id]; lp = sym_lp(np, tp, ccb_h->target_lun); +#ifdef FreeBSD_New_Tran_Settings +#define cts__scsi (&cts->proto_specific.scsi) +#define cts__spi (&cts->xport_specific.spi) + if (cts->type == CTS_TYPE_CURRENT_SETTINGS) { + tip = &tp->tinfo.current; + dflags = lp ? lp->current_flags : 0; + } + else { + tip = &tp->tinfo.user; + dflags = lp ? lp->user_flags : tp->usrflags; + } + + cts->protocol = PROTO_SCSI; + cts->transport = XPORT_SPI; + cts->protocol_version = tip->scsi_version; + cts->transport_version = tip->spi_version; + + cts__spi->sync_period = tip->period; + cts__spi->sync_offset = tip->offset; + cts__spi->bus_width = tip->width; + cts__spi->ppr_options = tip->options; + + cts__spi->valid = CTS_SPI_VALID_SYNC_RATE + | CTS_SPI_VALID_SYNC_OFFSET + | CTS_SPI_VALID_BUS_WIDTH + | CTS_SPI_VALID_PPR_OPTIONS; + + cts__spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; + if (dflags & SYM_DISC_ENABLED) + cts__spi->flags |= CTS_SPI_FLAGS_DISC_ENB; + cts__spi->valid |= CTS_SPI_VALID_DISC; + + cts__scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; + if (dflags & SYM_TAGS_ENABLED) + cts__scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; + cts__scsi->valid |= CTS_SCSI_VALID_TQ; +#undef cts__spi +#undef cts__scsi +#else if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0) { tip = &tp->tinfo.current; dflags = lp ? lp->current_flags : 0; @@ -8419,19 +8539,17 @@ static void sym_action2(struct cam_sim *sim, union ccb *ccb) | CCB_TRANS_SYNC_OFFSET_VALID | CCB_TRANS_BUS_WIDTH_VALID; - if (lp) { - cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB); + cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB); - if (dflags & SYM_DISC_ENABLED) - cts->flags |= CCB_TRANS_DISC_ENB; + if (dflags & SYM_DISC_ENABLED) + cts->flags |= CCB_TRANS_DISC_ENB; - if (dflags & SYM_TAGS_ENABLED) - cts->flags |= CCB_TRANS_TAG_ENB; - - cts->valid |= CCB_TRANS_DISC_VALID; - cts->valid |= CCB_TRANS_TQ_VALID; - } + if (dflags & SYM_TAGS_ENABLED) + cts->flags |= CCB_TRANS_TAG_ENB; + cts->valid |= CCB_TRANS_DISC_VALID; + cts->valid |= CCB_TRANS_TQ_VALID; +#endif sym_xpt_done2(np, ccb, CAM_REQ_CMP); break; } @@ -8488,6 +8606,19 @@ static void sym_action2(struct cam_sim *sim, union ccb *ccb) strncpy(cpi->hba_vid, "Symbios", HBA_IDLEN); strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); cpi->unit_number = cam_sim_unit(sim); + +#ifdef FreeBSD_New_Tran_Settings + cpi->protocol = PROTO_SCSI; + cpi->protocol_version = SCSI_REV_2; + cpi->transport = XPORT_SPI; + cpi->transport_version = 2; + cpi->xport_specific.spi.ppr_options = SID_SPI_CLOCK_ST; + if (np->features & FE_ULTRA3) { + cpi->transport_version = 3; + cpi->xport_specific.spi.ppr_options = + SID_SPI_CLOCK_DT_ST; + } +#endif sym_xpt_done2(np, ccb, CAM_REQ_CMP); break; } @@ -8586,13 +8717,31 @@ static void sym_update_trans(hcb_p np, tcb_p tp, struct sym_trans *tip, /* * Update the infos. */ +#ifdef FreeBSD_New_Tran_Settings +#define cts__spi (&cts->xport_specific.spi) + if ((cts__spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) + tip->width = cts__spi->bus_width; + if ((cts__spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0) + tip->offset = cts__spi->sync_offset; + if ((cts__spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0) + tip->period = cts__spi->sync_period; + if ((cts__spi->valid & CTS_SPI_VALID_PPR_OPTIONS) != 0) + tip->options = (cts__spi->ppr_options & PPR_OPT_DT); + if (cts->protocol_version != PROTO_VERSION_UNSPECIFIED && + cts->protocol_version != PROTO_VERSION_UNKNOWN) + tip->scsi_version = cts->protocol_version; + if (cts->transport_version != XPORT_VERSION_UNSPECIFIED && + cts->transport_version != XPORT_VERSION_UNKNOWN) + tip->spi_version = cts->transport_version; +#undef cts__spi +#else if ((cts->valid & CCB_TRANS_BUS_WIDTH_VALID) != 0) tip->width = cts->bus_width; if ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0) tip->offset = cts->sync_offset; if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0) tip->period = cts->sync_period; - +#endif /* * Scale against driver configuration limits. */ @@ -8606,6 +8755,15 @@ static void sym_update_trans(hcb_p np, tcb_p tp, struct sym_trans *tip, if (tip->width > np->maxwide) tip->width = np->maxwide; +#ifdef FreeBSD_New_Tran_Settings + /* + * Only accept DT if controller supports and SYNC/WIDE asked. + */ + if (!((np->features & (FE_C10|FE_ULTRA3)) == (FE_C10|FE_ULTRA3)) || + !(tip->width == BUS_16_BIT && tip->offset)) { + tip->options &= ~PPR_OPT_DT; + } +#else /* * For now, only assume DT if period <= 9, BUS 16 and offset != 0. */ @@ -8614,6 +8772,7 @@ static void sym_update_trans(hcb_p np, tcb_p tp, struct sym_trans *tip, tip->period <= 9 && tip->width == BUS_16_BIT && tip->offset) { tip->options |= PPR_OPT_DT; } +#endif /* * Scale period factor and offset against controller limits. @@ -8642,6 +8801,25 @@ static void sym_update_trans(hcb_p np, tcb_p tp, struct sym_trans *tip, static void sym_update_dflags(hcb_p np, u_char *flags, struct ccb_trans_settings *cts) { +#ifdef FreeBSD_New_Tran_Settings +#define cts__scsi (&cts->proto_specific.scsi) +#define cts__spi (&cts->xport_specific.spi) + if ((cts__spi->valid & CTS_SPI_VALID_DISC) != 0) { + if ((cts__spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0) + *flags |= SYM_DISC_ENABLED; + else + *flags &= ~SYM_DISC_ENABLED; + } + + if ((cts__scsi->valid & CTS_SCSI_VALID_TQ) != 0) { + if ((cts__scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) + *flags |= SYM_TAGS_ENABLED; + else + *flags &= ~SYM_TAGS_ENABLED; + } +#undef cts__spi +#undef cts__scsi +#else if ((cts->valid & CCB_TRANS_DISC_VALID) != 0) { if ((cts->flags & CCB_TRANS_DISC_ENB) != 0) *flags |= SYM_DISC_ENABLED; @@ -8655,6 +8833,7 @@ sym_update_dflags(hcb_p np, u_char *flags, struct ccb_trans_settings *cts) else *flags &= ~SYM_TAGS_ENABLED; } +#endif } |