From c4f4388714c70defac789b47c61eeb2c9c3f4270 Mon Sep 17 00:00:00 2001 From: mjacob Date: Sun, 1 Sep 2002 23:07:09 +0000 Subject: Fix things so that: a) we don't believe what the board tells us all the time (if the BIOS hasn't run, port page 2 and port page 0 tend to be garbage) b) add the missing code to set parameters for the SPI cards. MFC after: 0 days --- sys/dev/mpt/mpt.c | 45 ++++++-- sys/dev/mpt/mpt.h | 4 +- sys/dev/mpt/mpt_freebsd.c | 257 ++++++++++++++++++++++++++++++++++++++++++---- sys/dev/mpt/mpt_freebsd.h | 6 +- 4 files changed, 278 insertions(+), 34 deletions(-) (limited to 'sys/dev/mpt') diff --git a/sys/dev/mpt/mpt.c b/sys/dev/mpt/mpt.c index 7fed740..7009a36 100644 --- a/sys/dev/mpt/mpt.c +++ b/sys/dev/mpt/mpt.c @@ -509,10 +509,6 @@ mpt_send_ioc_init(mpt_softc_t *mpt, u_int32_t who) static int mpt_read_cfg_header(mpt_softc_t *, int, int, int, fCONFIG_PAGE_HEADER *); -static int -mpt_read_cfg_page(mpt_softc_t *, int, fCONFIG_PAGE_HEADER *); -static int -mpt_write_cfg_page(mpt_softc_t *, int, fCONFIG_PAGE_HEADER *); static int mpt_read_cfg_header(mpt_softc_t *mpt, int PageType, int PageNumber, @@ -565,7 +561,7 @@ mpt_read_cfg_header(mpt_softc_t *mpt, int PageType, int PageNumber, #define CFG_DATA_OFF 40 -static int +int mpt_read_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr) { int count; @@ -637,7 +633,7 @@ mpt_read_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr) return (0); } -static int +int mpt_write_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr) { int count, hdr_attr; @@ -885,6 +881,9 @@ mpt_set_initial_config_spi(mpt_softc_t *mpt) { int i, pp1val = ((1 << mpt->mpt_ini_id) << 16) | mpt->mpt_ini_id; + mpt->mpt_disc_enable = 0xff; + mpt->mpt_tag_enable = 0; + if (mpt->mpt_port_page1.Configuration != pp1val) { fCONFIG_PAGE_SCSI_PORT_1 tmp; device_printf(mpt->dev, @@ -906,9 +905,6 @@ mpt_set_initial_config_spi(mpt_softc_t *mpt) mpt->mpt_port_page1 = tmp; } -#if 1 - i = i; -#else for (i = 0; i < 16; i++) { fCONFIG_PAGE_SCSI_DEVICE_1 tmp; tmp = mpt->mpt_dev_page1[i]; @@ -933,7 +929,35 @@ mpt_set_initial_config_spi(mpt_softc_t *mpt) mpt->mpt_dev_page1[i].Configuration); } } -#endif + + /* + * If the BIOS hasn't been enabled, the SCSI Port Page2 device + * parameter are apparently complete nonsense. I've had partially + * sensible Page2 settings on *one* bus, but nothing on another- + * it's ridiculous. + * + * For that matter, the Port Page 0 parameters are *also* nonsense, + * so the offset and period and currently connected physical interface + * is also nonsense. + * + * This makes it very difficult to try and figure out what maximum + * settings we could have. Therefore, we'll synthesize the maximums + * here. + */ + for (i = 0; i < 16; i++) { + mpt->mpt_port_page2.DeviceSettings[i].DeviceFlags = + MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE | + MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE; + } + mpt->mpt_port_page0.Capabilities = + MPI_SCSIPORTPAGE0_CAP_IU | + MPI_SCSIPORTPAGE0_CAP_DT | + MPI_SCSIPORTPAGE0_CAP_QAS | + MPI_SCSIPORTPAGE0_CAP_WIDE | + (31 << 16) | /* offset */ + (8 << 8); /* period */ + mpt->mpt_port_page0.PhysicalInterface = + MPI_SCSIPORTPAGE0_PHY_SIGNAL_LVD; return (0); } @@ -1061,7 +1085,6 @@ mpt_init(mpt_softc_t *mpt, u_int32_t who) break; } - for (try = 0; try < MPT_MAX_TRYS; try++) { /* * No need to reset if the IOC is already in the READY state. diff --git a/sys/dev/mpt/mpt.h b/sys/dev/mpt/mpt.h index 2ec76e3..e0ccdd3 100644 --- a/sys/dev/mpt/mpt.h +++ b/sys/dev/mpt/mpt.h @@ -150,7 +150,6 @@ int mpt_soft_reset(mpt_softc_t *mpt); void mpt_hard_reset(mpt_softc_t *mpt); int mpt_recv_handshake_reply(mpt_softc_t *mpt, size_t reply_len, void *reply); - void mpt_send_cmd(mpt_softc_t *mpt, request_t *req); void mpt_free_reply(mpt_softc_t *mpt, u_int32_t ptr); void mpt_enable_ints(mpt_softc_t *mpt); @@ -164,6 +163,9 @@ void mpt_free_request(mpt_softc_t *mpt, request_t *req); int mpt_intr(void *dummy); void mpt_check_doorbell(mpt_softc_t * mpt); +int mpt_read_cfg_page(mpt_softc_t *, int, fCONFIG_PAGE_HEADER *); +int mpt_write_cfg_page(mpt_softc_t *, int, fCONFIG_PAGE_HEADER *); + /* mpt_debug.c functions */ void mpt_print_reply(void *vmsg); void mpt_print_db(u_int32_t mb); diff --git a/sys/dev/mpt/mpt_freebsd.c b/sys/dev/mpt/mpt_freebsd.c index 52cb1ab..4ffd12a 100644 --- a/sys/dev/mpt/mpt_freebsd.c +++ b/sys/dev/mpt/mpt_freebsd.c @@ -35,6 +35,8 @@ static void mpt_poll(struct cam_sim *); static timeout_t mpttimeout; static void mpt_action(struct cam_sim *, union ccb *); +static int mpt_setwidth(mpt_softc_t *, int, int); +static int mpt_setsync(mpt_softc_t *, int, int, int); void mpt_cam_attach(mpt_softc_t *mpt) @@ -430,8 +432,10 @@ mpt_start(union ccb *ccb) mpt_req->Control |= MPI_SCSIIO_CONTROL_UNTAGGED; } - if (mpt->is_fc == 0 && (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) != 0) { - mpt_req->Control |= MPI_SCSIIO_CONTROL_NO_DISCONNECT; + if (mpt->is_fc == 0) { + if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) { + mpt_req->Control |= MPI_SCSIIO_CONTROL_NO_DISCONNECT; + } } /* Copy the scsi command block into place */ @@ -1071,9 +1075,19 @@ mpt_action(struct cam_sim *sim, union ccb *ccb) #else #define IS_CURRENT_SETTINGS(c) (c->flags & CCB_TRANS_CURRENT_SETTINGS) #endif -#define DP_DISC 0x1 -#define DP_TQING 0x2 -#define DP_WIDE 0x4 +#define DP_DISC_ENABLE 0x1 +#define DP_DISC_DISABL 0x2 +#define DP_DISC (DP_DISC_ENABLE|DP_DISC_DISABL) + +#define DP_TQING_ENABLE 0x4 +#define DP_TQING_DISABL 0x8 +#define DP_TQING (DP_TQING_ENABLE|DP_TQING_DISABL) + +#define DP_WIDE 0x10 +#define DP_NARROW 0x20 +#define DP_WIDTH (DP_WIDE|DP_NARROW) + +#define DP_SYNC 0x40 case XPT_SET_TRAN_SETTINGS: /* Nexus Settings */ cts = &ccb->cts; @@ -1082,7 +1096,104 @@ mpt_action(struct cam_sim *sim, union ccb *ccb) xpt_done(ccb); break; } - /* XXX: need to implement */ + tgt = cts->ccb_h.target_id; + if (mpt->is_fc == 0) { + u_int8_t dval = 0; + u_int period = 0, offset = 0; +#ifndef CAM_NEW_TRAN_CODE + if (cts->valid & CCB_TRANS_DISC_VALID) { + dval |= DP_DISC_ENABLE; + } + if (cts->valid & CCB_TRANS_TQ_VALID) { + dval |= DP_TQING_ENABLE; + } + if (cts->valid & CCB_TRANS_BUS_WIDTH_VALID) { + if (cts->bus_width) + dval |= DP_WIDE; + else + dval |= DP_NARROW; + } + /* + * Any SYNC RATE of nonzero and SYNC_OFFSET + * of nonzero will cause us to go to the + * selected (from NVRAM) maximum value for + * this device. At a later point, we'll + * allow finer control. + */ + if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) && + (cts->valid & CCB_TRANS_SYNC_OFFSET_VALID)) { + dval |= DP_SYNC; + period = cts->sync_period; + offset = cts->sync_offset; + } +#else + struct ccb_trans_settings_scsi *scsi = + &cts->proto_specific.scsi; + struct ccb_trans_settings_spi *spi = + &cts->xport_specific.spi; + + if ((spi->valid & CTS_SPI_VALID_DISC) != 0) { + if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0) + dval |= DP_DISC_ENABLE; + else + dval |= DP_DISC_DISABL; + } + + if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) { + if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) + dval |= DP_TQING_ENABLE; + else + dval |= DP_TQING_DISABL; + } + + if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) { + if (spi->bus_width == MSG_EXT_WDTR_BUS_16_BIT) + dval |= DP_WIDE; + else + dval |= DP_NARROW; + } + + if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) && + (spi->valid & CTS_SPI_VALID_SYNC_RATE) && + (spi->sync_period && spi->sync_offset)) { + dval |= DP_SYNC; + period = spi->sync_period; + offset = spi->sync_offset; + } +#endif + CAMLOCK_2_MPTLOCK(mpt); + if (dval & DP_DISC_ENABLE) { + mpt->mpt_disc_enable |= (1 << tgt); + } else if (dval & DP_DISC_DISABL) { + mpt->mpt_disc_enable &= ~(1 << tgt); + } + if (dval & DP_TQING_ENABLE) { + mpt->mpt_tag_enable |= (1 << tgt); + } else if (dval & DP_TQING_DISABL) { + mpt->mpt_tag_enable &= ~(1 << tgt); + } + if (dval & DP_WIDTH) { + if (mpt_setwidth(mpt, tgt, dval & DP_WIDE)) { + ccb->ccb_h.status = CAM_REQ_CMP_ERR; + MPTLOCK_2_CAMLOCK(mpt); + xpt_done(ccb); + break; + } + } + if (dval & DP_SYNC) { + if (mpt_setsync(mpt, tgt, period, offset)) { + ccb->ccb_h.status = CAM_REQ_CMP_ERR; + MPTLOCK_2_CAMLOCK(mpt); + xpt_done(ccb); + break; + } + } + if (mpt->verbose > 1) { + device_printf(mpt->dev, + "SET tgt %d flags %x period %x off %x\n", + tgt, dval, period, offset); + } + } ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); break; @@ -1127,22 +1238,46 @@ mpt_action(struct cam_sim *sim, union ccb *ccb) #endif u_int8_t dval, pval, oval; + /* + * We aren't going off of Port PAGE2 params for + * tagged queuing or disconnect capabilities + * for current settings. For goal settings, + * we assert all capabilities- we've had some + * problems with reading NVRAM data. + */ if (IS_CURRENT_SETTINGS(cts)) { + fCONFIG_PAGE_SCSI_DEVICE_0 tmp; dval = 0; + + tmp = mpt->mpt_dev_page0[tgt]; + CAMLOCK_2_MPTLOCK(mpt); + if (mpt_read_cfg_page(mpt, tgt, &tmp.Header)) { + device_printf(mpt->dev, + "cannot get target %d DP0\n", tgt); + } else { + mpt->mpt_dev_page0[tgt] = tmp; + if (mpt->verbose > 1) { + device_printf(mpt->dev, + "SPI Tgt %d Page 0: NParms %x Information %x\n", + tgt, + tmp.NegotiatedParameters, + tmp.Information); + } + } + MPTLOCK_2_CAMLOCK(mpt); + if (mpt->mpt_dev_page0[tgt]. NegotiatedParameters & MPI_SCSIDEVPAGE0_NP_WIDE) dval |= DP_WIDE; - if (mpt->mpt_port_page2.DeviceSettings[tgt]. - DeviceFlags & - MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE) - dval |= DP_DISC; + if (mpt->mpt_disc_enable & (1 << tgt)) { + dval |= DP_DISC_ENABLE; + } - if (mpt->mpt_port_page2.DeviceSettings[tgt]. - DeviceFlags & - MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE) - dval |= DP_TQING; + if (mpt->mpt_tag_enable & (1 << tgt)) { + dval |= DP_TQING_ENABLE; + } oval = (mpt->mpt_dev_page0[tgt]. NegotiatedParameters >> 16); @@ -1160,10 +1295,10 @@ mpt_action(struct cam_sim *sim, union ccb *ccb) } #ifndef CAM_NEW_TRAN_CODE cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB); - if (dval & DP_DISC) { + if (dval & DP_DISC_ENABLE) { cts->flags |= CCB_TRANS_DISC_ENB; } - if (dval & DP_TQING) { + if (dval & DP_TQING_ENABLE) { cts->flags |= CCB_TRANS_TAG_ENB; } if (dval & DP_WIDE) { @@ -1188,10 +1323,10 @@ mpt_action(struct cam_sim *sim, union ccb *ccb) scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; - if (dval & DP_DISC) { + if (dval & DP_DISC_ENABLE) { spi->flags |= CTS_SPI_FLAGS_DISC_ENB; } - if (dval & DP_TQING) { + if (dval & DP_TQING_ENABLE) { scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; } if (oval && pval) { @@ -1215,9 +1350,9 @@ mpt_action(struct cam_sim *sim, union ccb *ccb) #endif if (mpt->verbose > 1) { device_printf(mpt->dev, - "GET %s targ %d flags %x off %x per %x\n", + "GET %s tgt %d flags %x period %x off %x\n", IS_CURRENT_SETTINGS(cts)? "ACTIVE" : - "NVRAM", tgt, dval, oval, pval); + "NVRAM", tgt, dval, pval, oval); } } ccb->ccb_h.status = CAM_REQ_CMP; @@ -1288,3 +1423,85 @@ mpt_action(struct cam_sim *sim, union ccb *ccb) break; } } + +static int +mpt_setwidth(mpt_softc_t *mpt, int tgt, int onoff) +{ + fCONFIG_PAGE_SCSI_DEVICE_1 tmp; + tmp = mpt->mpt_dev_page1[tgt]; + if (onoff) { + tmp.RequestedParameters |= MPI_SCSIDEVPAGE1_RP_WIDE; + } else { + tmp.RequestedParameters &= ~MPI_SCSIDEVPAGE1_RP_WIDE; + } + if (mpt_write_cfg_page(mpt, tgt, &tmp.Header)) { + return (-1); + } + if (mpt_read_cfg_page(mpt, tgt, &tmp.Header)) { + return (-1); + } + mpt->mpt_dev_page1[tgt] = tmp; + if (mpt->verbose > 1) { + device_printf(mpt->dev, + "SPI Target %d Page 1: RequestedParameters %x Config %x\n", + tgt, mpt->mpt_dev_page1[tgt].RequestedParameters, + mpt->mpt_dev_page1[tgt].Configuration); + } + return (0); +} + +static int +mpt_setsync(mpt_softc_t *mpt, int tgt, int period, int offset) +{ + fCONFIG_PAGE_SCSI_DEVICE_1 tmp; + tmp = mpt->mpt_dev_page1[tgt]; + tmp.RequestedParameters &= + ~MPI_SCSIDEVPAGE1_RP_MIN_SYNC_PERIOD_MASK; + tmp.RequestedParameters &= + ~MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK; + tmp.RequestedParameters &= + ~MPI_SCSIDEVPAGE1_RP_DT; + tmp.RequestedParameters &= + ~MPI_SCSIDEVPAGE1_RP_QAS; + tmp.RequestedParameters &= + ~MPI_SCSIDEVPAGE1_RP_IU; + /* + * XXX: For now, we're ignoring specific settings + */ + if (period && offset) { + int factor, offset, np; + factor = + (mpt->mpt_port_page0.Capabilities >> 8) & 0xff; + offset = + (mpt->mpt_port_page0.Capabilities >> 16) & 0xff; + if ((mpt->mpt_port_page0.PhysicalInterface & + MPI_SCSIPORTPAGE0_PHY_SIGNAL_TYPE_MASK) != + MPI_SCSIPORTPAGE0_PHY_SIGNAL_LVD && factor < 0xa) { + factor = 0xa; + } + np = 0; + if (factor < 0x9) { + np |= MPI_SCSIDEVPAGE1_RP_QAS; + np |= MPI_SCSIDEVPAGE1_RP_IU; + } + if (factor < 0xa) { + np |= MPI_SCSIDEVPAGE1_RP_DT; + } + np |= (factor << 8) | (offset << 16); + tmp.RequestedParameters |= np; + } + if (mpt_write_cfg_page(mpt, tgt, &tmp.Header)) { + return (-1); + } + if (mpt_read_cfg_page(mpt, tgt, &tmp.Header)) { + return (-1); + } + mpt->mpt_dev_page1[tgt] = tmp; + if (mpt->verbose > 1) { + device_printf(mpt->dev, + "SPI Target %d Page 1: RequestedParameters %x Config %x\n", + tgt, mpt->mpt_dev_page1[tgt].RequestedParameters, + mpt->mpt_dev_page1[tgt].Configuration); + } + return (0); +} diff --git a/sys/dev/mpt/mpt_freebsd.h b/sys/dev/mpt/mpt_freebsd.h index d2a2970..aa38147 100644 --- a/sys/dev/mpt/mpt_freebsd.h +++ b/sys/dev/mpt/mpt_freebsd.h @@ -228,7 +228,8 @@ typedef struct mpt_softc { fCONFIG_PAGE_SCSI_PORT_2 _port_page2; fCONFIG_PAGE_SCSI_DEVICE_0 _dev_page0[16]; fCONFIG_PAGE_SCSI_DEVICE_1 _dev_page1[16]; - uint16_t _tagmask; + uint16_t _tag_enable; + uint16_t _disc_enable; uint16_t _update_params0; uint16_t _update_params1; } spi; @@ -237,7 +238,8 @@ typedef struct mpt_softc { #define mpt_port_page2 cfg.spi._port_page2 #define mpt_dev_page0 cfg.spi._dev_page0 #define mpt_dev_page1 cfg.spi._dev_page1 -#define mpt_tagmask cfg.spi._tagmask +#define mpt_tag_enable cfg.spi._tag_enable +#define mpt_disc_enable cfg.spi._disc_enable #define mpt_update_params0 cfg.spi._update_params0 #define mpt_update_params1 cfg.spi._update_params1 struct mpi_fc_cfg { -- cgit v1.1