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
This commit is contained in:
mjacob 2002-09-01 23:07:09 +00:00
parent d1187c90af
commit c4f4388714
4 changed files with 278 additions and 34 deletions

View File

@ -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.

View File

@ -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);

View File

@ -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);
}

View File

@ -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 {