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:
parent
d1187c90af
commit
c4f4388714
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user