mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
Add 2 Gigabit Fibre Channel support (2300 && 2312 cards). This required
some reworking (and consequent cleanup) of the interrupt service code. Also begin to start a cleanup of target mode support that will (eventually) not require more inforamtion routed with the ATIO to come back with the CTIO other than tag. MFC after: 4 weeks
This commit is contained in:
parent
a2f1799115
commit
126ec86486
7 changed files with 600 additions and 295 deletions
|
|
@ -150,12 +150,14 @@ static void isp_parse_nvram_2100 __P((struct ispsoftc *, u_int8_t *));
|
|||
*
|
||||
* Locking done elsewhere.
|
||||
*/
|
||||
|
||||
void
|
||||
isp_reset(struct ispsoftc *isp)
|
||||
{
|
||||
mbreg_t mbs;
|
||||
u_int16_t code_org;
|
||||
int loops, i, touched, dodnld = 1;
|
||||
char *revname = "????";
|
||||
char *btype = "????";
|
||||
|
||||
isp->isp_state = ISP_NILSTATE;
|
||||
|
||||
|
|
@ -163,7 +165,8 @@ isp_reset(struct ispsoftc *isp)
|
|||
/*
|
||||
* Basic types (SCSI, FibreChannel and PCI or SBus)
|
||||
* have been set in the MD code. We figure out more
|
||||
* here.
|
||||
* here. Possibly more refined types based upon PCI
|
||||
* identification. Chip revision has been gathered.
|
||||
*
|
||||
* After we've fired this chip up, zero out the conf1 register
|
||||
* for SCSI adapters and do other settings for the 2100.
|
||||
|
|
@ -205,6 +208,14 @@ isp_reset(struct ispsoftc *isp)
|
|||
}
|
||||
|
||||
DISABLE_INTS(isp);
|
||||
/*
|
||||
* Set up default request/response queue in-pointer/out-pointer
|
||||
* register indices.
|
||||
*/
|
||||
isp->isp_rqstinrp = INMAILBOX4;
|
||||
isp->isp_rqstoutrp = OUTMAILBOX4;
|
||||
isp->isp_respinrp = OUTMAILBOX5;
|
||||
isp->isp_respoutrp = INMAILBOX5;
|
||||
|
||||
/*
|
||||
* Put the board into PAUSE mode (so we can read the SXP registers
|
||||
|
|
@ -215,13 +226,17 @@ isp_reset(struct ispsoftc *isp)
|
|||
if (IS_FC(isp)) {
|
||||
switch (isp->isp_type) {
|
||||
case ISP_HA_FC_2100:
|
||||
revname = "2100";
|
||||
btype = "2100";
|
||||
break;
|
||||
case ISP_HA_FC_2200:
|
||||
revname = "2200";
|
||||
btype = "2200";
|
||||
break;
|
||||
case ISP_HA_FC_2300:
|
||||
revname = "2300";
|
||||
isp->isp_rqstinrp = BIU_REQINP;
|
||||
isp->isp_rqstoutrp = BIU_REQOUTP;
|
||||
isp->isp_respinrp = BIU_RSPINP;
|
||||
isp->isp_respoutrp = BIU_RSPOUTP;
|
||||
btype = "2300";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -236,7 +251,7 @@ isp_reset(struct ispsoftc *isp)
|
|||
ISP_WRITE(isp, BIU2100_CSR, BIU2100_RISC_REGS);
|
||||
} else if (IS_1240(isp)) {
|
||||
sdparam *sdp = isp->isp_param;
|
||||
revname = "1240";
|
||||
btype = "1240";
|
||||
isp->isp_clock = 60;
|
||||
sdp->isp_ultramode = 1;
|
||||
sdp++;
|
||||
|
|
@ -252,13 +267,13 @@ isp_reset(struct ispsoftc *isp)
|
|||
isp->isp_clock = 100;
|
||||
|
||||
if (IS_1280(isp))
|
||||
revname = "1280";
|
||||
btype = "1280";
|
||||
else if (IS_1080(isp))
|
||||
revname = "1080";
|
||||
btype = "1080";
|
||||
else if (IS_12160(isp))
|
||||
revname = "12160";
|
||||
btype = "12160";
|
||||
else
|
||||
revname = "<UNKLVD>";
|
||||
btype = "<UNKLVD>";
|
||||
|
||||
l = ISP_READ(isp, SXP_PINS_DIFF) & ISP1080_MODE_MASK;
|
||||
switch (l) {
|
||||
|
|
@ -313,7 +328,7 @@ isp_reset(struct ispsoftc *isp)
|
|||
isp_prt(isp, ISP_LOGALL, "Unknown Chip Type 0x%x", i);
|
||||
/* FALLTHROUGH */
|
||||
case 1:
|
||||
revname = "1020";
|
||||
btype = "1020";
|
||||
isp->isp_type = ISP_HA_SCSI_1020;
|
||||
isp->isp_clock = 40;
|
||||
break;
|
||||
|
|
@ -323,27 +338,27 @@ isp_reset(struct ispsoftc *isp)
|
|||
* run the clock rate up for that unless told to
|
||||
* do so by the Ultra Capable bits being set.
|
||||
*/
|
||||
revname = "1020A";
|
||||
btype = "1020A";
|
||||
isp->isp_type = ISP_HA_SCSI_1020A;
|
||||
isp->isp_clock = 40;
|
||||
break;
|
||||
case 3:
|
||||
revname = "1040";
|
||||
btype = "1040";
|
||||
isp->isp_type = ISP_HA_SCSI_1040;
|
||||
isp->isp_clock = 60;
|
||||
break;
|
||||
case 4:
|
||||
revname = "1040A";
|
||||
btype = "1040A";
|
||||
isp->isp_type = ISP_HA_SCSI_1040A;
|
||||
isp->isp_clock = 60;
|
||||
break;
|
||||
case 5:
|
||||
revname = "1040B";
|
||||
btype = "1040B";
|
||||
isp->isp_type = ISP_HA_SCSI_1040B;
|
||||
isp->isp_clock = 60;
|
||||
break;
|
||||
case 6:
|
||||
revname = "1040C";
|
||||
btype = "1040C";
|
||||
isp->isp_type = ISP_HA_SCSI_1040C;
|
||||
isp->isp_clock = 60;
|
||||
break;
|
||||
|
|
@ -593,11 +608,16 @@ again:
|
|||
dodnld = 0;
|
||||
}
|
||||
|
||||
if (IS_2300(isp))
|
||||
code_org = ISP_CODE_ORG_2300;
|
||||
else
|
||||
code_org = ISP_CODE_ORG;
|
||||
|
||||
if (dodnld) {
|
||||
u_int16_t fwlen = isp->isp_mdvec->dv_ispfw[3];
|
||||
for (i = 0; i < fwlen; i++) {
|
||||
mbs.param[0] = MBOX_WRITE_RAM_WORD;
|
||||
mbs.param[1] = ISP_CODE_ORG + i;
|
||||
mbs.param[1] = code_org + i;
|
||||
mbs.param[2] = isp->isp_mdvec->dv_ispfw[i];
|
||||
isp_mboxcmd(isp, &mbs, MBLOGNONE);
|
||||
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
|
||||
|
|
@ -612,7 +632,7 @@ again:
|
|||
* Verify that it downloaded correctly.
|
||||
*/
|
||||
mbs.param[0] = MBOX_VERIFY_CHECKSUM;
|
||||
mbs.param[1] = ISP_CODE_ORG;
|
||||
mbs.param[1] = code_org;
|
||||
isp_mboxcmd(isp, &mbs, MBLOGNONE);
|
||||
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
|
||||
isp_prt(isp, ISP_LOGERR, "Ram Checksum Failure");
|
||||
|
|
@ -631,8 +651,9 @@ again:
|
|||
* we still need to (re)start it.
|
||||
*/
|
||||
|
||||
|
||||
mbs.param[0] = MBOX_EXEC_FIRMWARE;
|
||||
mbs.param[1] = ISP_CODE_ORG;
|
||||
mbs.param[1] = code_org;
|
||||
isp_mboxcmd(isp, &mbs, MBLOGNONE);
|
||||
/* give it a chance to start */
|
||||
USEC_SLEEP(isp, 500);
|
||||
|
|
@ -655,9 +676,9 @@ again:
|
|||
return;
|
||||
}
|
||||
isp_prt(isp, ISP_LOGCONFIG,
|
||||
"Board Revision %s, %s F/W Revision %d.%d.%d", revname,
|
||||
dodnld? "loaded" : "resident", mbs.param[1], mbs.param[2],
|
||||
mbs.param[3]);
|
||||
"Board Type %s, Chip Revision 0x%x, %s F/W Revision %d.%d.%d",
|
||||
btype, isp->isp_revision, dodnld? "loaded" : "resident",
|
||||
mbs.param[1], mbs.param[2], mbs.param[3]);
|
||||
if (IS_FC(isp)) {
|
||||
isp_prt(isp, ISP_LOGCONFIG, "Firmware Attributes = 0x%x",
|
||||
mbs.param[6]);
|
||||
|
|
@ -871,8 +892,8 @@ isp_scsi_init(struct ispsoftc *isp)
|
|||
|
||||
mbs.param[0] = MBOX_INIT_RES_QUEUE;
|
||||
mbs.param[1] = RESULT_QUEUE_LEN(isp);
|
||||
mbs.param[2] = DMA_MSW(isp->isp_result_dma);
|
||||
mbs.param[3] = DMA_LSW(isp->isp_result_dma);
|
||||
mbs.param[2] = DMA_WD1(isp->isp_result_dma);
|
||||
mbs.param[3] = DMA_WD0(isp->isp_result_dma);
|
||||
mbs.param[4] = 0;
|
||||
mbs.param[5] = 0;
|
||||
isp_mboxcmd(isp, &mbs, MBLOGALL);
|
||||
|
|
@ -883,8 +904,8 @@ isp_scsi_init(struct ispsoftc *isp)
|
|||
|
||||
mbs.param[0] = MBOX_INIT_REQ_QUEUE;
|
||||
mbs.param[1] = RQUEST_QUEUE_LEN(isp);
|
||||
mbs.param[2] = DMA_MSW(isp->isp_rquest_dma);
|
||||
mbs.param[3] = DMA_LSW(isp->isp_rquest_dma);
|
||||
mbs.param[2] = DMA_WD1(isp->isp_rquest_dma);
|
||||
mbs.param[3] = DMA_WD0(isp->isp_rquest_dma);
|
||||
mbs.param[4] = 0;
|
||||
isp_mboxcmd(isp, &mbs, MBLOGALL);
|
||||
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
|
||||
|
|
@ -1142,6 +1163,8 @@ isp_fibre_init(struct ispsoftc *isp)
|
|||
/*
|
||||
* Right now we just set extended options to prefer point-to-point
|
||||
* over loop based upon some soft config options.
|
||||
*
|
||||
* NB: for the 2300, ICBOPT_EXTENDED is required.
|
||||
*/
|
||||
if (IS_2200(isp) || IS_2300(isp)) {
|
||||
icbp->icb_fwoptions |= ICBOPT_EXTENDED;
|
||||
|
|
@ -1162,6 +1185,15 @@ isp_fibre_init(struct ispsoftc *isp)
|
|||
icbp->icb_xfwoptions = ICBXOPT_LOOP_2_PTP;
|
||||
break;
|
||||
}
|
||||
if (IS_2300(isp)) {
|
||||
if (isp->isp_revision < 2) {
|
||||
icbp->icb_fwoptions &= ~ICBOPT_FAST_POST;
|
||||
}
|
||||
icbp->icb_xfwoptions |= ICBXOPT_RATE_AUTO;
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_2200(isp) || IS_2300(isp)) {
|
||||
/*
|
||||
* Turn on LIP F8 async event (1)
|
||||
* Turn on generate AE 8013 on all LIP Resets (2)
|
||||
|
|
@ -1173,7 +1205,14 @@ isp_fibre_init(struct ispsoftc *isp)
|
|||
mbs.param[3] = 0;
|
||||
isp_mboxcmd(isp, &mbs, MBLOGALL);
|
||||
}
|
||||
icbp->icb_logintime = 60; /* 60 second login timeout */
|
||||
icbp->icb_logintime = 30; /* 30 second login timeout */
|
||||
|
||||
if (IS_2300(isp)) {
|
||||
ISP_WRITE(isp, isp->isp_rqstinrp, 0);
|
||||
ISP_WRITE(isp, isp->isp_rqstoutrp, 0);
|
||||
ISP_WRITE(isp, isp->isp_respinrp, 0);
|
||||
ISP_WRITE(isp, isp->isp_respoutrp, 0);
|
||||
}
|
||||
|
||||
nwwn = ISP_NODEWWN(isp);
|
||||
pwwn = ISP_PORTWWN(isp);
|
||||
|
|
@ -1193,10 +1232,14 @@ isp_fibre_init(struct ispsoftc *isp)
|
|||
}
|
||||
icbp->icb_rqstqlen = RQUEST_QUEUE_LEN(isp);
|
||||
icbp->icb_rsltqlen = RESULT_QUEUE_LEN(isp);
|
||||
icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_LSW(isp->isp_rquest_dma);
|
||||
icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_MSW(isp->isp_rquest_dma);
|
||||
icbp->icb_respaddr[RQRSP_ADDR0015] = DMA_LSW(isp->isp_result_dma);
|
||||
icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_MSW(isp->isp_result_dma);
|
||||
icbp->icb_rqstaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_rquest_dma);
|
||||
icbp->icb_rqstaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_rquest_dma);
|
||||
icbp->icb_rqstaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_rquest_dma);
|
||||
icbp->icb_rqstaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_rquest_dma);
|
||||
icbp->icb_respaddr[RQRSP_ADDR0015] = DMA_WD0(isp->isp_result_dma);
|
||||
icbp->icb_respaddr[RQRSP_ADDR1631] = DMA_WD1(isp->isp_result_dma);
|
||||
icbp->icb_respaddr[RQRSP_ADDR3247] = DMA_WD2(isp->isp_result_dma);
|
||||
icbp->icb_respaddr[RQRSP_ADDR4863] = DMA_WD3(isp->isp_result_dma);
|
||||
isp_prt(isp, ISP_LOGDEBUG1,
|
||||
"isp_fibre_init: fwoptions 0x%x", fcp->isp_fwoptions);
|
||||
ISP_SWIZZLE_ICB(isp, icbp);
|
||||
|
|
@ -1207,12 +1250,12 @@ isp_fibre_init(struct ispsoftc *isp)
|
|||
*/
|
||||
mbs.param[0] = MBOX_INIT_FIRMWARE;
|
||||
mbs.param[1] = 0;
|
||||
mbs.param[2] = DMA_MSW(fcp->isp_scdma);
|
||||
mbs.param[3] = DMA_LSW(fcp->isp_scdma);
|
||||
mbs.param[2] = DMA_WD1(fcp->isp_scdma);
|
||||
mbs.param[3] = DMA_WD0(fcp->isp_scdma);
|
||||
mbs.param[4] = 0;
|
||||
mbs.param[5] = 0;
|
||||
mbs.param[6] = 0;
|
||||
mbs.param[7] = 0;
|
||||
mbs.param[6] = DMA_WD3(fcp->isp_scdma);
|
||||
mbs.param[7] = DMA_WD2(fcp->isp_scdma);
|
||||
isp_mboxcmd(isp, &mbs, MBLOGALL);
|
||||
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
|
||||
return;
|
||||
|
|
@ -1242,8 +1285,8 @@ isp_getmap(struct ispsoftc *isp, fcpos_map_t *map)
|
|||
|
||||
mbs.param[0] = MBOX_GET_FC_AL_POSITION_MAP;
|
||||
mbs.param[1] = 0;
|
||||
mbs.param[2] = DMA_MSW(fcp->isp_scdma);
|
||||
mbs.param[3] = DMA_LSW(fcp->isp_scdma);
|
||||
mbs.param[2] = DMA_WD1(fcp->isp_scdma);
|
||||
mbs.param[3] = DMA_WD0(fcp->isp_scdma);
|
||||
/*
|
||||
* Unneeded. For the 2100, except for initializing f/w, registers
|
||||
* 4/5 have to not be written to.
|
||||
|
|
@ -1280,8 +1323,8 @@ isp_getpdb(struct ispsoftc *isp, int id, isp_pdb_t *pdbp)
|
|||
|
||||
mbs.param[0] = MBOX_GET_PORT_DB;
|
||||
mbs.param[1] = id << 8;
|
||||
mbs.param[2] = DMA_MSW(fcp->isp_scdma);
|
||||
mbs.param[3] = DMA_LSW(fcp->isp_scdma);
|
||||
mbs.param[2] = DMA_WD1(fcp->isp_scdma);
|
||||
mbs.param[3] = DMA_WD0(fcp->isp_scdma);
|
||||
/*
|
||||
* Unneeded. For the 2100, except for initializing f/w, registers
|
||||
* 4/5 have to not be written to.
|
||||
|
|
@ -1289,8 +1332,8 @@ isp_getpdb(struct ispsoftc *isp, int id, isp_pdb_t *pdbp)
|
|||
* mbs.param[5] = 0;
|
||||
*
|
||||
*/
|
||||
mbs.param[6] = 0;
|
||||
mbs.param[7] = 0;
|
||||
mbs.param[6] = DMA_WD3(fcp->isp_scdma);
|
||||
mbs.param[7] = DMA_WD2(fcp->isp_scdma);
|
||||
isp_mboxcmd(isp, &mbs, MBLOGALL & ~MBOX_COMMAND_PARAM_ERROR);
|
||||
if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
|
||||
ISP_UNSWIZZLE_AND_COPY_PDBP(isp, pdbp, fcp->isp_scratch);
|
||||
|
|
@ -2183,9 +2226,13 @@ isp_scan_fabric(struct ispsoftc *isp)
|
|||
MEMZERO((void *) reqp, SNS_GAN_REQ_SIZE);
|
||||
reqp->snscb_rblen = SNS_GAN_RESP_SIZE >> 1;
|
||||
reqp->snscb_addr[RQRSP_ADDR0015] =
|
||||
DMA_LSW(fcp->isp_scdma + 0x100);
|
||||
DMA_WD0(fcp->isp_scdma + 0x100);
|
||||
reqp->snscb_addr[RQRSP_ADDR1631] =
|
||||
DMA_MSW(fcp->isp_scdma + 0x100);
|
||||
DMA_WD1(fcp->isp_scdma + 0x100);
|
||||
reqp->snscb_addr[RQRSP_ADDR3247] =
|
||||
DMA_WD2(fcp->isp_scdma + 0x100);
|
||||
reqp->snscb_addr[RQRSP_ADDR4863] =
|
||||
DMA_WD3(fcp->isp_scdma + 0x100);
|
||||
reqp->snscb_sblen = 6;
|
||||
reqp->snscb_data[0] = SNS_GAN;
|
||||
reqp->snscb_data[4] = portid & 0xffff;
|
||||
|
|
@ -2193,10 +2240,13 @@ isp_scan_fabric(struct ispsoftc *isp)
|
|||
ISP_SWIZZLE_SNS_REQ(isp, reqp);
|
||||
mbs.param[0] = MBOX_SEND_SNS;
|
||||
mbs.param[1] = SNS_GAN_REQ_SIZE >> 1;
|
||||
mbs.param[2] = DMA_MSW(fcp->isp_scdma);
|
||||
mbs.param[3] = DMA_LSW(fcp->isp_scdma);
|
||||
mbs.param[6] = 0;
|
||||
mbs.param[7] = 0;
|
||||
mbs.param[2] = DMA_WD1(fcp->isp_scdma);
|
||||
mbs.param[3] = DMA_WD0(fcp->isp_scdma);
|
||||
/*
|
||||
* Leave 4 and 5 alone
|
||||
*/
|
||||
mbs.param[6] = DMA_WD3(fcp->isp_scdma);
|
||||
mbs.param[7] = DMA_WD2(fcp->isp_scdma);
|
||||
isp_mboxcmd(isp, &mbs, MBLOGNONE);
|
||||
if (mbs.param[0] != MBOX_COMMAND_COMPLETE) {
|
||||
if (fcp->isp_loopstate == LOOP_SCANNING_FABRIC) {
|
||||
|
|
@ -2268,8 +2318,10 @@ isp_register_fc4_type(struct ispsoftc *isp)
|
|||
reqp = (sns_screq_t *) fcp->isp_scratch;
|
||||
MEMZERO((void *) reqp, SNS_RFT_REQ_SIZE);
|
||||
reqp->snscb_rblen = SNS_RFT_RESP_SIZE >> 1;
|
||||
reqp->snscb_addr[RQRSP_ADDR0015] = DMA_LSW(fcp->isp_scdma + 0x100);
|
||||
reqp->snscb_addr[RQRSP_ADDR1631] = DMA_MSW(fcp->isp_scdma + 0x100);
|
||||
reqp->snscb_addr[RQRSP_ADDR0015] = DMA_WD0(fcp->isp_scdma + 0x100);
|
||||
reqp->snscb_addr[RQRSP_ADDR1631] = DMA_WD1(fcp->isp_scdma + 0x100);
|
||||
reqp->snscb_addr[RQRSP_ADDR3247] = DMA_WD2(fcp->isp_scdma + 0x100);
|
||||
reqp->snscb_addr[RQRSP_ADDR4863] = DMA_WD3(fcp->isp_scdma + 0x100);
|
||||
reqp->snscb_sblen = 22;
|
||||
reqp->snscb_data[0] = SNS_RFT;
|
||||
reqp->snscb_data[4] = fcp->isp_portid & 0xffff;
|
||||
|
|
@ -2281,10 +2333,13 @@ isp_register_fc4_type(struct ispsoftc *isp)
|
|||
ISP_SWIZZLE_SNS_REQ(isp, reqp);
|
||||
mbs.param[0] = MBOX_SEND_SNS;
|
||||
mbs.param[1] = SNS_RFT_REQ_SIZE >> 1;
|
||||
mbs.param[2] = DMA_MSW(fcp->isp_scdma);
|
||||
mbs.param[3] = DMA_LSW(fcp->isp_scdma);
|
||||
mbs.param[6] = 0;
|
||||
mbs.param[7] = 0;
|
||||
mbs.param[2] = DMA_WD1(fcp->isp_scdma);
|
||||
mbs.param[3] = DMA_WD0(fcp->isp_scdma);
|
||||
/*
|
||||
* Leave 4 and 5 alone
|
||||
*/
|
||||
mbs.param[6] = DMA_WD3(fcp->isp_scdma);
|
||||
mbs.param[7] = DMA_WD2(fcp->isp_scdma);
|
||||
isp_mboxcmd(isp, &mbs, MBLOGALL);
|
||||
if (mbs.param[0] == MBOX_COMMAND_COMPLETE) {
|
||||
isp_prt(isp, ISP_LOGDEBUG0, "Register FC4 types succeeded");
|
||||
|
|
@ -2603,12 +2658,12 @@ isp_start(XS_T *xs)
|
|||
} else {
|
||||
/*
|
||||
* If we don't know what tag to use, use HEAD OF QUEUE
|
||||
* for Request Sense or Ordered (for safety's sake).
|
||||
* for Request Sense or Simple.
|
||||
*/
|
||||
if (XS_CDBP(xs)[0] == 0x3) /* REQUEST SENSE */
|
||||
t2reqp->req_flags = REQFLAG_HTAG;
|
||||
else
|
||||
t2reqp->req_flags = REQFLAG_OTAG;
|
||||
t2reqp->req_flags = REQFLAG_STAG;
|
||||
}
|
||||
} else {
|
||||
sdparam *sdp = (sdparam *)isp->isp_param;
|
||||
|
|
@ -2865,65 +2920,18 @@ isp_control(struct ispsoftc *isp, ispctl_t ctl, void *arg)
|
|||
*/
|
||||
#define MAX_REQUESTQ_COMPLETIONS 32
|
||||
|
||||
int
|
||||
isp_intr(void *arg)
|
||||
void
|
||||
isp_intr(struct ispsoftc *isp, u_int16_t isr, u_int16_t sema, u_int16_t mbox)
|
||||
{
|
||||
struct ispsoftc *isp = arg;
|
||||
XS_T *complist[MAX_REQUESTQ_COMPLETIONS], *xs;
|
||||
u_int16_t iptr, optr, isr, sema, junk;
|
||||
u_int16_t iptr, optr, junk;
|
||||
int i, nlooked = 0, ndone = 0;
|
||||
|
||||
if (IS_2100(isp)) {
|
||||
i = 0;
|
||||
do {
|
||||
isr = ISP_READ(isp, BIU_ISR);
|
||||
junk = ISP_READ(isp, BIU_ISR);
|
||||
} while (isr != junk && ++i < 1000);
|
||||
if (isr != junk) {
|
||||
isp_prt(isp, ISP_LOGWARN,
|
||||
"isr unsteady (%x, %x)", isr, junk);
|
||||
}
|
||||
i = 0;
|
||||
do {
|
||||
sema = ISP_READ(isp, BIU_SEMA);
|
||||
junk = ISP_READ(isp, BIU_SEMA);
|
||||
} while (sema != junk && ++i < 1000);
|
||||
if (sema != junk) {
|
||||
isp_prt(isp, ISP_LOGWARN,
|
||||
"sema unsteady (%x, %x)", sema, junk);
|
||||
}
|
||||
} else {
|
||||
isr = ISP_READ(isp, BIU_ISR);
|
||||
sema = ISP_READ(isp, BIU_SEMA);
|
||||
}
|
||||
isp_prt(isp, ISP_LOGDEBUG3, "isp_intr isr %x sem %x", isr, sema);
|
||||
isr &= INT_PENDING_MASK(isp);
|
||||
sema &= BIU_SEMA_LOCK;
|
||||
isp->isp_intcnt++;
|
||||
if (isr == 0 && sema == 0) {
|
||||
isp->isp_intbogus++;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Is this a mailbox related interrupt?
|
||||
* The mailbox semaphore will be nonzero if so.
|
||||
*/
|
||||
if (sema) {
|
||||
u_int16_t mbox;
|
||||
|
||||
if (IS_2100(isp)) {
|
||||
i = 0;
|
||||
do {
|
||||
mbox = ISP_READ(isp, OUTMAILBOX0);
|
||||
junk = ISP_READ(isp, OUTMAILBOX0);;
|
||||
} while (junk != mbox && ++i < 1000);
|
||||
if (mbox != junk) {
|
||||
isp_prt(isp, ISP_LOGWARN,
|
||||
"mailbox0 unsteady (%x, %x)", mbox, junk);
|
||||
ISP_WRITE(isp, BIU_SEMA, 0);
|
||||
ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
|
||||
return (1);
|
||||
}
|
||||
} else {
|
||||
mbox = ISP_READ(isp, OUTMAILBOX0);
|
||||
}
|
||||
if (mbox & 0x4000) {
|
||||
int obits, i = 0;
|
||||
if ((obits = isp->isp_mboxbsy) != 0) {
|
||||
|
|
@ -2949,9 +2957,9 @@ isp_intr(void *arg)
|
|||
}
|
||||
}
|
||||
if (IS_FC(isp) || isp->isp_state != ISP_RUNSTATE) {
|
||||
ISP_WRITE(isp, BIU_SEMA, 0);
|
||||
ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
|
||||
return (1);
|
||||
ISP_WRITE(isp, BIU_SEMA, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2960,41 +2968,55 @@ isp_intr(void *arg)
|
|||
*/
|
||||
if (isp->isp_state != ISP_RUNSTATE) {
|
||||
isp_prt(isp, ISP_LOGWARN,
|
||||
"interrupt (isr=%x, sema=%x) when not ready", isr, sema);
|
||||
WRITE_RESPONSE_QUEUE_IN_POINTER(isp,
|
||||
READ_RESPONSE_QUEUE_OUT_POINTER(isp));
|
||||
"interrupt (ISR=%x SEMA=%x) when not ready", isr, sema);
|
||||
/*
|
||||
* Thank you very much! *Burrrp*!
|
||||
*/
|
||||
WRITE_RESPONSE_QUEUE_OUT_POINTER(isp,
|
||||
READ_RESPONSE_QUEUE_IN_POINTER(isp));
|
||||
|
||||
ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
|
||||
ISP_WRITE(isp, BIU_SEMA, 0);
|
||||
return (1);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* You *must* read the Response Queue Out Pointer
|
||||
* Get the current Response Queue Out Pointer.
|
||||
*
|
||||
* If we're a 2300, we can ask what hardware what it thinks.
|
||||
*/
|
||||
if (IS_2300(isp)) {
|
||||
optr = ISP_READ(isp, isp->isp_respoutrp);
|
||||
if (isp->isp_residx != optr) {
|
||||
isp_prt(isp, ISP_LOGWARN, "optr %x soft optr %x",
|
||||
optr, isp->isp_residx);
|
||||
}
|
||||
} else {
|
||||
optr = isp->isp_residx;
|
||||
}
|
||||
|
||||
/*
|
||||
* You *must* read the Response Queue In Pointer
|
||||
* prior to clearing the RISC interrupt.
|
||||
*/
|
||||
optr = isp->isp_residx;
|
||||
|
||||
if (IS_2100(isp)) {
|
||||
if (IS_2100(isp) || IS_2300(isp)) {
|
||||
i = 0;
|
||||
do {
|
||||
iptr = READ_RESPONSE_QUEUE_OUT_POINTER(isp);
|
||||
junk = READ_RESPONSE_QUEUE_OUT_POINTER(isp);
|
||||
iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp);
|
||||
junk = READ_RESPONSE_QUEUE_IN_POINTER(isp);
|
||||
} while (junk != iptr && ++i < 1000);
|
||||
|
||||
if (iptr != junk) {
|
||||
ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
|
||||
isp_prt(isp, ISP_LOGWARN,
|
||||
"mailbox5 unsteady (%x, %x)", iptr, junk);
|
||||
return (1);
|
||||
"Response Queue Out Pointer Unstable (%x, %x)",
|
||||
iptr, junk);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
iptr = READ_RESPONSE_QUEUE_OUT_POINTER(isp);
|
||||
iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp);
|
||||
}
|
||||
|
||||
if (sema) {
|
||||
ISP_WRITE(isp, BIU_SEMA, 0);
|
||||
}
|
||||
ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
|
||||
|
||||
if (optr == iptr && sema == 0) {
|
||||
/*
|
||||
|
|
@ -3005,12 +3027,22 @@ isp_intr(void *arg)
|
|||
* make sure the old interrupt went away (to avoid 'ringing'
|
||||
* effects), but that didn't stop this from occurring.
|
||||
*/
|
||||
junk = ISP_READ(isp, BIU_ISR);
|
||||
isp_prt(isp, ISP_LOGDEBUG2,
|
||||
"bogus intr- isr %x (%x) iptr %x optr %x",
|
||||
isr, junk, iptr, optr);
|
||||
isp->isp_intbogus++;
|
||||
if (IS_2300(isp)) {
|
||||
USEC_DELAY(100);
|
||||
iptr = READ_RESPONSE_QUEUE_IN_POINTER(isp);
|
||||
junk = ISP_READ(isp, BIU_R2HSTSLO);
|
||||
} else {
|
||||
junk = ISP_READ(isp, BIU_ISR);
|
||||
}
|
||||
if (optr == iptr) {
|
||||
isp_prt(isp, ISP_LOGDEBUG0,
|
||||
"bogus intr- isr %x (%x) iptr %x optr %x",
|
||||
isr, junk, iptr, optr);
|
||||
isp->isp_intbogus++;
|
||||
}
|
||||
}
|
||||
ISP_WRITE(isp, HCCR, HCCR_CMD_CLEAR_RISC_INT);
|
||||
ISP_WRITE(isp, BIU_SEMA, 0);
|
||||
|
||||
while (optr != iptr) {
|
||||
ispstatusreq_t *sp;
|
||||
|
|
@ -3057,7 +3089,7 @@ isp_intr(void *arg)
|
|||
if (sp->req_header.rqs_flags & RQSFLAG_CONTINUATION) {
|
||||
isp_prt(isp, ISP_LOGWARN,
|
||||
"continuation segment");
|
||||
WRITE_RESPONSE_QUEUE_IN_POINTER(isp, optr);
|
||||
WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr);
|
||||
continue;
|
||||
}
|
||||
if (sp->req_header.rqs_flags & RQSFLAG_FULL) {
|
||||
|
|
@ -3089,7 +3121,7 @@ isp_intr(void *arg)
|
|||
"bad request handle %d (type 0x%x, flags 0x%x)",
|
||||
sp->req_handle, sp->req_header.rqs_entry_type,
|
||||
sp->req_header.rqs_flags);
|
||||
WRITE_RESPONSE_QUEUE_IN_POINTER(isp, optr);
|
||||
WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr);
|
||||
continue;
|
||||
}
|
||||
xs = isp_find_xs(isp, sp->req_handle);
|
||||
|
|
@ -3098,7 +3130,7 @@ isp_intr(void *arg)
|
|||
isp_prt(isp, ISP_LOGERR,
|
||||
"cannot find handle 0x%x in xflist",
|
||||
sp->req_handle);
|
||||
WRITE_RESPONSE_QUEUE_IN_POINTER(isp, optr);
|
||||
WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr);
|
||||
continue;
|
||||
}
|
||||
isp_destroy_handle(isp, sp->req_handle);
|
||||
|
|
@ -3233,7 +3265,10 @@ isp_intr(void *arg)
|
|||
* ISP's notion of what we've seen so far.
|
||||
*/
|
||||
if (nlooked) {
|
||||
WRITE_RESPONSE_QUEUE_IN_POINTER(isp, optr);
|
||||
WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, optr);
|
||||
/*
|
||||
* While we're at it, reqad the requst queue out pointer.
|
||||
*/
|
||||
isp->isp_reqodx = READ_REQUEST_QUEUE_OUT_POINTER(isp);
|
||||
}
|
||||
|
||||
|
|
@ -3244,7 +3279,6 @@ isp_intr(void *arg)
|
|||
isp_done(xs);
|
||||
}
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -390,15 +390,16 @@ get_lun_statep(struct ispsoftc *isp, int bus, lun_id_t lun)
|
|||
tstate_t *tptr;
|
||||
|
||||
if (lun == CAM_LUN_WILDCARD) {
|
||||
tptr = &isp->isp_osinfo.tsdflt[bus];
|
||||
tptr->hold++;
|
||||
return (tptr);
|
||||
if (isp->isp_osinfo.tmflags & TM_WILDCARD_ENABLED) {
|
||||
tptr = &isp->isp_osinfo.tsdflt[bus];
|
||||
tptr->hold++;
|
||||
return (tptr);
|
||||
} else {
|
||||
return (NULL);
|
||||
}
|
||||
} else {
|
||||
tptr = isp->isp_osinfo.lun_hash[LUN_HASH_FUNC(isp, bus, lun)];
|
||||
}
|
||||
if (tptr == NULL) {
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
do {
|
||||
if (tptr->lun == lun && tptr->bus == bus) {
|
||||
|
|
@ -546,7 +547,7 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
|
|||
struct ccb_en_lun *cel = &ccb->cel;
|
||||
tstate_t *tptr;
|
||||
u_int16_t rstat;
|
||||
int bus, cmd, frozen = 0;
|
||||
int bus, cmd, av, wildcard, frozen = 0;
|
||||
lun_id_t lun;
|
||||
target_id_t tgt;
|
||||
|
||||
|
|
@ -630,23 +631,23 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
|
|||
}
|
||||
}
|
||||
|
||||
if (lun == CAM_LUN_WILDCARD && tgt == CAM_TARGET_WILDCARD) {
|
||||
wildcard = 1;
|
||||
} else {
|
||||
wildcard = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Next check to see whether this is a target/lun wildcard action.
|
||||
*
|
||||
* If so, we enable/disable target mode but don't do any lun enabling.
|
||||
* If so, we know that we can accept commands and send them
|
||||
* upstream. Otherwise, we have to handle them locally.
|
||||
*/
|
||||
if (lun == CAM_LUN_WILDCARD && tgt == CAM_TARGET_WILDCARD) {
|
||||
int av = bus << 31;
|
||||
|
||||
if (wildcard) {
|
||||
tptr = &isp->isp_osinfo.tsdflt[bus];
|
||||
if (cel->enable) {
|
||||
if (isp->isp_osinfo.tmflags & (1 << bus)) {
|
||||
if (isp->isp_osinfo.tmflags & TM_WILDCARD_ENABLED) {
|
||||
ccb->ccb_h.status = CAM_LUN_ALRDY_ENA;
|
||||
if (frozen) {
|
||||
ISPLOCK_2_CAMLOCK(isp);
|
||||
xpt_release_simq(isp->isp_sim, 1);
|
||||
CAMLOCK_2_ISPLOCK(isp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
ccb->ccb_h.status =
|
||||
|
|
@ -664,54 +665,72 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
|
|||
}
|
||||
SLIST_INIT(&tptr->atios);
|
||||
SLIST_INIT(&tptr->inots);
|
||||
av |= ENABLE_TARGET_FLAG;
|
||||
av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
|
||||
if (av) {
|
||||
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
|
||||
xpt_free_path(tptr->owner);
|
||||
if (frozen) {
|
||||
ISPLOCK_2_CAMLOCK(isp);
|
||||
xpt_release_simq(isp->isp_sim, 1);
|
||||
CAMLOCK_2_ISPLOCK(isp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
isp->isp_osinfo.tmflags |= (1 << bus);
|
||||
isp->isp_osinfo.tmflags |= TM_WILDCARD_ENABLED;
|
||||
} else {
|
||||
if ((isp->isp_osinfo.tmflags & (1 << bus)) == 0) {
|
||||
ccb->ccb_h.status = CAM_LUN_INVALID;
|
||||
if (frozen) {
|
||||
ISPLOCK_2_CAMLOCK(isp);
|
||||
xpt_release_simq(isp->isp_sim, 1);
|
||||
CAMLOCK_2_ISPLOCK(isp);
|
||||
}
|
||||
if (!(isp->isp_osinfo.tmflags & TM_WILDCARD_ENABLED)) {
|
||||
ccb->ccb_h.status = CAM_REQ_CMP;
|
||||
return;
|
||||
}
|
||||
if (are_any_luns_enabled(isp, bus)) {
|
||||
if (tptr->hold) {
|
||||
ccb->ccb_h.status = CAM_SCSI_BUSY;
|
||||
if (frozen) {
|
||||
ISPLOCK_2_CAMLOCK(isp);
|
||||
xpt_release_simq(isp->isp_sim, 1);
|
||||
CAMLOCK_2_ISPLOCK(isp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
|
||||
if (av) {
|
||||
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
|
||||
if (frozen) {
|
||||
ISPLOCK_2_CAMLOCK(isp);
|
||||
xpt_release_simq(isp->isp_sim, 1);
|
||||
CAMLOCK_2_ISPLOCK(isp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
isp->isp_osinfo.tmflags &= ~(1 << bus);
|
||||
ccb->ccb_h.status = CAM_REQ_CMP;
|
||||
xpt_free_path(tptr->owner);
|
||||
isp->isp_osinfo.tmflags &= ~TM_WILDCARD_ENABLED;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now check to see whether this bus needs to be
|
||||
* enabled/disabled with respect to target mode.
|
||||
*/
|
||||
|
||||
av = bus << 31;
|
||||
if (cel->enable && (isp->isp_osinfo.tmflags & (1 << bus)) == 0) {
|
||||
av |= ENABLE_TARGET_FLAG;
|
||||
av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
|
||||
if (av) {
|
||||
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
|
||||
ISPLOCK_2_CAMLOCK(isp);
|
||||
xpt_release_simq(isp->isp_sim, 1);
|
||||
CAMLOCK_2_ISPLOCK(isp);
|
||||
if (wildcard) {
|
||||
isp->isp_osinfo.tmflags &= ~TM_WILDCARD_ENABLED;
|
||||
xpt_free_path(tptr->owner);
|
||||
}
|
||||
return;
|
||||
}
|
||||
isp_prt(isp, ISP_LOGINFO,
|
||||
"Target Mode enabled on channel %d", bus);
|
||||
} else if (cel->enable == 0 && (isp->isp_osinfo.tmflags & (1 << bus)) &&
|
||||
wildcard) {
|
||||
if (are_any_luns_enabled(isp, bus)) {
|
||||
ccb->ccb_h.status = CAM_SCSI_BUSY;
|
||||
if (frozen) {
|
||||
ISPLOCK_2_CAMLOCK(isp);
|
||||
xpt_release_simq(isp->isp_sim, 1);
|
||||
CAMLOCK_2_ISPLOCK(isp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
|
||||
if (av) {
|
||||
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
|
||||
if (frozen) {
|
||||
ISPLOCK_2_CAMLOCK(isp);
|
||||
xpt_release_simq(isp->isp_sim, 1);
|
||||
CAMLOCK_2_ISPLOCK(isp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
isp->isp_osinfo.tmflags &= ~(1 << bus);
|
||||
ccb->ccb_h.status = CAM_REQ_CMP;
|
||||
xpt_print_path(ccb->ccb_h.path);
|
||||
isp_prt(isp, ISP_LOGINFO, "Target Mode %sabled on channel %d",
|
||||
(cel->enable) ? "en" : "dis", bus);
|
||||
isp_prt(isp, ISP_LOGINFO,
|
||||
"Target Mode disabled on channel %d", bus);
|
||||
}
|
||||
|
||||
if (wildcard) {
|
||||
if (frozen) {
|
||||
ISPLOCK_2_CAMLOCK(isp);
|
||||
xpt_release_simq(isp->isp_sim, 1);
|
||||
|
|
@ -850,7 +869,21 @@ isp_en_lun(struct ispsoftc *isp, union ccb *ccb)
|
|||
"DISABLE LUN returned 0x%x", rstat);
|
||||
goto out;
|
||||
}
|
||||
if (are_any_luns_enabled(isp, bus) == 0) {
|
||||
av = isp_control(isp, ISPCTL_TOGGLE_TMODE, &av);
|
||||
if (av) {
|
||||
isp_prt(isp, ISP_LOGWARN,
|
||||
"disable target mode on channel %d failed",
|
||||
bus);
|
||||
goto out;
|
||||
}
|
||||
isp->isp_osinfo.tmflags &= ~(1 << bus);
|
||||
xpt_print_path(ccb->ccb_h.path);
|
||||
isp_prt(isp, ISP_LOGINFO,
|
||||
"Target Mode disabled on channel %d", bus);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
isp_vsema_rqe(isp);
|
||||
|
||||
|
|
@ -1571,8 +1604,12 @@ static void
|
|||
isp_poll(struct cam_sim *sim)
|
||||
{
|
||||
struct ispsoftc *isp = cam_sim_softc(sim);
|
||||
u_int16_t isr, sema, mbox;
|
||||
|
||||
ISP_LOCK(isp);
|
||||
(void) isp_intr(isp);
|
||||
if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
|
||||
isp_intr(isp, isr, sema, mbox);
|
||||
}
|
||||
ISP_UNLOCK(isp);
|
||||
}
|
||||
|
||||
|
|
@ -1609,7 +1646,8 @@ isp_watchdog(void *arg)
|
|||
ISP_LOCK(isp);
|
||||
handle = isp_find_handle(isp, xs);
|
||||
if (handle) {
|
||||
u_int16_t r;
|
||||
u_int16_t isr, sema, mbox;
|
||||
|
||||
|
||||
if (XS_CMD_DONE_P(xs)) {
|
||||
isp_prt(isp, ISP_LOGDEBUG1,
|
||||
|
|
@ -1626,12 +1664,12 @@ isp_watchdog(void *arg)
|
|||
}
|
||||
|
||||
XS_CMD_S_WDOG(xs);
|
||||
|
||||
r = ISP_READ(isp, BIU_ISR);
|
||||
|
||||
if (INT_PENDING(isp, r) && isp_intr(isp) && XS_CMD_DONE_P(xs)) {
|
||||
if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
|
||||
isp_intr(isp, isr, sema, mbox);
|
||||
}
|
||||
if (XS_CMD_DONE_P(xs)) {
|
||||
isp_prt(isp, ISP_LOGDEBUG2,
|
||||
"watchdog cleanup (%x, %x)", handle, r);
|
||||
"watchdog cleanup for handle 0x%x", handle);
|
||||
xpt_done((union ccb *) xs);
|
||||
} else if (XS_CMD_GRACE_P(xs)) {
|
||||
/*
|
||||
|
|
@ -1649,7 +1687,7 @@ isp_watchdog(void *arg)
|
|||
isp_destroy_handle(isp, handle);
|
||||
xpt_print_path(xs->ccb_h.path);
|
||||
isp_prt(isp, ISP_LOGWARN,
|
||||
"watchdog timeout (%x, %x)", handle, r);
|
||||
"watchdog timeout for handle %x", handle);
|
||||
XS_SETERR(xs, CAM_CMD_TIMEOUT);
|
||||
XS_CMD_C_WDOG(xs);
|
||||
isp_done(xs);
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ struct isposinfo {
|
|||
#ifdef ISP_TARGET_MODE
|
||||
#define TM_WANTED 0x80
|
||||
#define TM_BUSY 0x40
|
||||
#define TM_WILDCARD_ENABLED 0x20
|
||||
#define TM_TMODE_ENABLED 0x03
|
||||
u_int8_t tmflags;
|
||||
u_int8_t rstatus;
|
||||
|
|
@ -328,12 +329,17 @@ isp_mbox_wait_complete(struct ispsoftc *isp)
|
|||
} else {
|
||||
int j;
|
||||
for (j = 0; j < 60 * 10000; j++) {
|
||||
if (isp_intr(isp) == 0) {
|
||||
USEC_DELAY(500);
|
||||
}
|
||||
u_int16_t isr, sema, mbox;
|
||||
if (isp->isp_mboxbsy == 0) {
|
||||
break;
|
||||
}
|
||||
if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
|
||||
isp_intr(isp, isr, sema, mbox);
|
||||
if (isp->isp_mboxbsy == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
USEC_DELAY(500);
|
||||
}
|
||||
if (isp->isp_mboxbsy != 0) {
|
||||
isp_prt(isp, ISP_LOGWARN,
|
||||
|
|
|
|||
|
|
@ -45,24 +45,29 @@
|
|||
|
||||
#include <dev/isp/isp_freebsd.h>
|
||||
|
||||
static u_int16_t isp_pci_rd_reg __P((struct ispsoftc *, int));
|
||||
static void isp_pci_wr_reg __P((struct ispsoftc *, int, u_int16_t));
|
||||
static u_int16_t isp_pci_rd_reg_1080 __P((struct ispsoftc *, int));
|
||||
static void isp_pci_wr_reg_1080 __P((struct ispsoftc *, int, u_int16_t));
|
||||
static int isp_pci_mbxdma __P((struct ispsoftc *));
|
||||
static int isp_pci_dmasetup __P((struct ispsoftc *, XS_T *,
|
||||
ispreq_t *, u_int16_t *, u_int16_t));
|
||||
static u_int16_t isp_pci_rd_reg(struct ispsoftc *, int);
|
||||
static void isp_pci_wr_reg(struct ispsoftc *, int, u_int16_t);
|
||||
static u_int16_t isp_pci_rd_reg_1080(struct ispsoftc *, int);
|
||||
static void isp_pci_wr_reg_1080(struct ispsoftc *, int, u_int16_t);
|
||||
static int
|
||||
isp_pci_rd_isr(struct ispsoftc *, u_int16_t *, u_int16_t *, u_int16_t *);
|
||||
static int
|
||||
isp_pci_rd_isr_2300(struct ispsoftc *, u_int16_t *, u_int16_t *, u_int16_t *);
|
||||
static int isp_pci_mbxdma(struct ispsoftc *);
|
||||
static int
|
||||
isp_pci_dmasetup(struct ispsoftc *, XS_T *, ispreq_t *, u_int16_t *, u_int16_t);
|
||||
static void
|
||||
isp_pci_dmateardown __P((struct ispsoftc *, XS_T *, u_int16_t));
|
||||
isp_pci_dmateardown(struct ispsoftc *, XS_T *, u_int16_t);
|
||||
|
||||
static void isp_pci_reset1 __P((struct ispsoftc *));
|
||||
static void isp_pci_dumpregs __P((struct ispsoftc *, const char *));
|
||||
static void isp_pci_reset1(struct ispsoftc *);
|
||||
static void isp_pci_dumpregs(struct ispsoftc *, const char *);
|
||||
|
||||
#ifndef ISP_CODE_ORG
|
||||
#define ISP_CODE_ORG 0x1000
|
||||
#endif
|
||||
|
||||
static struct ispmdvec mdvec = {
|
||||
isp_pci_rd_isr,
|
||||
isp_pci_rd_reg,
|
||||
isp_pci_wr_reg,
|
||||
isp_pci_mbxdma,
|
||||
|
|
@ -76,6 +81,7 @@ static struct ispmdvec mdvec = {
|
|||
};
|
||||
|
||||
static struct ispmdvec mdvec_1080 = {
|
||||
isp_pci_rd_isr,
|
||||
isp_pci_rd_reg_1080,
|
||||
isp_pci_wr_reg_1080,
|
||||
isp_pci_mbxdma,
|
||||
|
|
@ -89,6 +95,7 @@ static struct ispmdvec mdvec_1080 = {
|
|||
};
|
||||
|
||||
static struct ispmdvec mdvec_12160 = {
|
||||
isp_pci_rd_isr,
|
||||
isp_pci_rd_reg_1080,
|
||||
isp_pci_wr_reg_1080,
|
||||
isp_pci_mbxdma,
|
||||
|
|
@ -102,6 +109,7 @@ static struct ispmdvec mdvec_12160 = {
|
|||
};
|
||||
|
||||
static struct ispmdvec mdvec_2100 = {
|
||||
isp_pci_rd_isr,
|
||||
isp_pci_rd_reg,
|
||||
isp_pci_wr_reg,
|
||||
isp_pci_mbxdma,
|
||||
|
|
@ -113,6 +121,19 @@ static struct ispmdvec mdvec_2100 = {
|
|||
};
|
||||
|
||||
static struct ispmdvec mdvec_2200 = {
|
||||
isp_pci_rd_isr,
|
||||
isp_pci_rd_reg,
|
||||
isp_pci_wr_reg,
|
||||
isp_pci_mbxdma,
|
||||
isp_pci_dmasetup,
|
||||
isp_pci_dmateardown,
|
||||
NULL,
|
||||
isp_pci_reset1,
|
||||
isp_pci_dumpregs
|
||||
};
|
||||
|
||||
static struct ispmdvec mdvec_2300 = {
|
||||
isp_pci_rd_isr_2300,
|
||||
isp_pci_rd_reg,
|
||||
isp_pci_wr_reg,
|
||||
isp_pci_mbxdma,
|
||||
|
|
@ -184,6 +205,14 @@ static struct ispmdvec mdvec_2200 = {
|
|||
#define PCI_PRODUCT_QLOGIC_ISP2200 0x2200
|
||||
#endif
|
||||
|
||||
#ifndef PCI_PRODUCT_QLOGIC_ISP2300
|
||||
#define PCI_PRODUCT_QLOGIC_ISP2300 0x2300
|
||||
#endif
|
||||
|
||||
#ifndef PCI_PRODUCT_QLOGIC_ISP2312
|
||||
#define PCI_PRODUCT_QLOGIC_ISP2312 0x2312
|
||||
#endif
|
||||
|
||||
#define PCI_QLOGIC_ISP1020 \
|
||||
((PCI_PRODUCT_QLOGIC_ISP1020 << 16) | PCI_VENDOR_QLOGIC)
|
||||
|
||||
|
|
@ -205,6 +234,12 @@ static struct ispmdvec mdvec_2200 = {
|
|||
#define PCI_QLOGIC_ISP2200 \
|
||||
((PCI_PRODUCT_QLOGIC_ISP2200 << 16) | PCI_VENDOR_QLOGIC)
|
||||
|
||||
#define PCI_QLOGIC_ISP2300 \
|
||||
((PCI_PRODUCT_QLOGIC_ISP2300 << 16) | PCI_VENDOR_QLOGIC)
|
||||
|
||||
#define PCI_QLOGIC_ISP2312 \
|
||||
((PCI_PRODUCT_QLOGIC_ISP2312 << 16) | PCI_VENDOR_QLOGIC)
|
||||
|
||||
/*
|
||||
* Odd case for some AMI raid cards... We need to *not* attach to this.
|
||||
*/
|
||||
|
|
@ -240,7 +275,7 @@ static device_method_t isp_pci_methods[] = {
|
|||
DEVMETHOD(device_attach, isp_pci_attach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
static void isp_pci_intr __P((void *));
|
||||
static void isp_pci_intr(void *);
|
||||
|
||||
static driver_t isp_pci_driver = {
|
||||
"isp", isp_pci_methods, sizeof (struct isp_pcisoftc)
|
||||
|
|
@ -277,6 +312,12 @@ isp_pci_probe(device_t dev)
|
|||
case PCI_QLOGIC_ISP2200:
|
||||
device_set_desc(dev, "Qlogic ISP 2200 PCI FC-AL Adapter");
|
||||
break;
|
||||
case PCI_QLOGIC_ISP2300:
|
||||
device_set_desc(dev, "Qlogic ISP 2300 PCI FC-AL Adapter");
|
||||
break;
|
||||
case PCI_QLOGIC_ISP2312:
|
||||
device_set_desc(dev, "Qlogic ISP 2312 PCI FC-AL Adapter");
|
||||
break;
|
||||
default:
|
||||
return (ENXIO);
|
||||
}
|
||||
|
|
@ -455,6 +496,14 @@ isp_pci_attach(device_t dev)
|
|||
pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
|
||||
PCI_MBOX_REGS2100_OFF;
|
||||
}
|
||||
if (pci_get_devid(dev) == PCI_QLOGIC_ISP2300 ||
|
||||
pci_get_devid(dev) == PCI_QLOGIC_ISP2312) {
|
||||
mdvp = &mdvec_2300;
|
||||
basetype = ISP_HA_FC_2300;
|
||||
psize = sizeof (fcparam);
|
||||
pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
|
||||
PCI_MBOX_REGS2300_OFF;
|
||||
}
|
||||
isp = &pcs->pci_isp;
|
||||
isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT | M_ZERO);
|
||||
if (isp->isp_param == NULL) {
|
||||
|
|
@ -698,68 +747,167 @@ static void
|
|||
isp_pci_intr(void *arg)
|
||||
{
|
||||
struct ispsoftc *isp = arg;
|
||||
u_int16_t isr, sema, mbox;
|
||||
|
||||
ISP_LOCK(isp);
|
||||
(void) isp_intr(isp);
|
||||
isp->isp_intcnt++;
|
||||
if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) {
|
||||
isp->isp_intbogus++;
|
||||
} else {
|
||||
isp_intr(isp, isr, sema, mbox);
|
||||
}
|
||||
ISP_UNLOCK(isp);
|
||||
}
|
||||
|
||||
|
||||
#define IspVirt2Off(a, x) \
|
||||
(((struct isp_pcisoftc *)a)->pci_poff[((x) & _BLK_REG_MASK) >> \
|
||||
_BLK_REG_SHFT] + ((x) & 0xff))
|
||||
|
||||
#define BXR2(pcs, off) \
|
||||
bus_space_read_2(pcs->pci_st, pcs->pci_sh, off)
|
||||
#define BXW2(pcs, off, v) \
|
||||
bus_space_write_2(pcs->pci_st, pcs->pci_sh, off, v)
|
||||
|
||||
|
||||
static INLINE int
|
||||
isp_pci_rd_debounced(struct ispsoftc *isp, int off, u_int16_t *rp)
|
||||
{
|
||||
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
|
||||
u_int16_t val0, val1;
|
||||
int i = 0;
|
||||
|
||||
do {
|
||||
val0 = BXR2(pcs, IspVirt2Off(isp, off));
|
||||
val1 = BXR2(pcs, IspVirt2Off(isp, off));
|
||||
} while (val0 != val1 && ++i < 1000);
|
||||
if (val0 != val1) {
|
||||
return (1);
|
||||
}
|
||||
*rp = val0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
isp_pci_rd_isr(struct ispsoftc *isp, u_int16_t *isrp,
|
||||
u_int16_t *semap, u_int16_t *mbp)
|
||||
{
|
||||
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
|
||||
u_int16_t isr, sema;
|
||||
|
||||
if (IS_2100(isp)) {
|
||||
if (isp_pci_rd_debounced(isp, BIU_ISR, &isr)) {
|
||||
return (0);
|
||||
}
|
||||
if (isp_pci_rd_debounced(isp, BIU_SEMA, &sema)) {
|
||||
return (0);
|
||||
}
|
||||
} else {
|
||||
isr = BXR2(pcs, IspVirt2Off(isp, BIU_ISR));
|
||||
sema = BXR2(pcs, IspVirt2Off(isp, BIU_SEMA));
|
||||
}
|
||||
isp_prt(isp, ISP_LOGDEBUG3, "ISR 0x%x SEMA 0x%x", isr, sema);
|
||||
isr &= INT_PENDING_MASK(isp);
|
||||
sema &= BIU_SEMA_LOCK;
|
||||
if (isr == 0 && sema == 0) {
|
||||
return (0);
|
||||
}
|
||||
*isrp = isr;
|
||||
if ((*semap = sema) != 0) {
|
||||
if (IS_2100(isp)) {
|
||||
if (isp_pci_rd_debounced(isp, OUTMAILBOX0, mbp)) {
|
||||
return (0);
|
||||
}
|
||||
} else {
|
||||
*mbp = BXR2(pcs, IspVirt2Off(isp, OUTMAILBOX0));
|
||||
}
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
isp_pci_rd_isr_2300(struct ispsoftc *isp, u_int16_t *isrp,
|
||||
u_int16_t *semap, u_int16_t *mbox0p)
|
||||
{
|
||||
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
|
||||
u_int32_t r2hisr;
|
||||
|
||||
r2hisr = bus_space_read_4(pcs->pci_st, pcs->pci_sh,
|
||||
IspVirt2Off(pcs, BIU_R2HSTSLO));
|
||||
isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr);
|
||||
if ((r2hisr & BIU_R2HST_INTR) == 0) {
|
||||
*isrp = 0;
|
||||
return (0);
|
||||
}
|
||||
switch (r2hisr & BIU_R2HST_ISTAT_MASK) {
|
||||
case ISPR2HST_ROM_MBX_OK:
|
||||
case ISPR2HST_ROM_MBX_FAIL:
|
||||
case ISPR2HST_MBX_OK:
|
||||
case ISPR2HST_MBX_FAIL:
|
||||
case ISPR2HST_ASYNC_EVENT:
|
||||
case ISPR2HST_FPOST:
|
||||
case ISPR2HST_FPOST_CTIO:
|
||||
*isrp = r2hisr & 0xffff;
|
||||
*mbox0p = (r2hisr >> 16);
|
||||
*semap = 1;
|
||||
return (1);
|
||||
case ISPR2HST_RSPQ_UPDATE:
|
||||
*isrp = r2hisr & 0xffff;
|
||||
*mbox0p = 0;
|
||||
*semap = 0;
|
||||
return (1);
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
static u_int16_t
|
||||
isp_pci_rd_reg(isp, regoff)
|
||||
struct ispsoftc *isp;
|
||||
int regoff;
|
||||
isp_pci_rd_reg(struct ispsoftc *isp, int regoff)
|
||||
{
|
||||
u_int16_t rv;
|
||||
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
|
||||
int offset, oldconf = 0;
|
||||
int oldconf = 0;
|
||||
|
||||
if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
|
||||
/*
|
||||
* We will assume that someone has paused the RISC processor.
|
||||
*/
|
||||
oldconf = isp_pci_rd_reg(isp, BIU_CONF1);
|
||||
isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP);
|
||||
oldconf = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
|
||||
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1),
|
||||
oldconf | BIU_PCI_CONF1_SXP);
|
||||
}
|
||||
offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
|
||||
offset += (regoff & 0xff);
|
||||
rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset);
|
||||
rv = BXR2(pcs, IspVirt2Off(isp, regoff));
|
||||
if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
|
||||
isp_pci_wr_reg(isp, BIU_CONF1, oldconf);
|
||||
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf);
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
|
||||
static void
|
||||
isp_pci_wr_reg(isp, regoff, val)
|
||||
struct ispsoftc *isp;
|
||||
int regoff;
|
||||
u_int16_t val;
|
||||
isp_pci_wr_reg(struct ispsoftc *isp, int regoff, u_int16_t val)
|
||||
{
|
||||
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
|
||||
int offset, oldconf = 0;
|
||||
int oldconf = 0;
|
||||
|
||||
if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
|
||||
/*
|
||||
* We will assume that someone has paused the RISC processor.
|
||||
*/
|
||||
oldconf = isp_pci_rd_reg(isp, BIU_CONF1);
|
||||
isp_pci_wr_reg(isp, BIU_CONF1, oldconf | BIU_PCI_CONF1_SXP);
|
||||
oldconf = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
|
||||
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1),
|
||||
oldconf | BIU_PCI_CONF1_SXP);
|
||||
}
|
||||
offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
|
||||
offset += (regoff & 0xff);
|
||||
bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val);
|
||||
BXW2(pcs, IspVirt2Off(isp, regoff), val);
|
||||
if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
|
||||
isp_pci_wr_reg(isp, BIU_CONF1, oldconf);
|
||||
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf);
|
||||
}
|
||||
}
|
||||
|
||||
static u_int16_t
|
||||
isp_pci_rd_reg_1080(isp, regoff)
|
||||
struct ispsoftc *isp;
|
||||
int regoff;
|
||||
isp_pci_rd_reg_1080(struct ispsoftc *isp, int regoff)
|
||||
{
|
||||
u_int16_t rv, oc = 0;
|
||||
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
|
||||
int offset;
|
||||
|
||||
if ((regoff & _BLK_REG_MASK) == SXP_BLOCK ||
|
||||
(regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) {
|
||||
|
|
@ -767,34 +915,30 @@ isp_pci_rd_reg_1080(isp, regoff)
|
|||
/*
|
||||
* We will assume that someone has paused the RISC processor.
|
||||
*/
|
||||
oc = isp_pci_rd_reg(isp, BIU_CONF1);
|
||||
oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
|
||||
tc = oc & ~BIU_PCI1080_CONF1_DMA;
|
||||
if (regoff & SXP_BANK1_SELECT)
|
||||
tc |= BIU_PCI1080_CONF1_SXP1;
|
||||
else
|
||||
tc |= BIU_PCI1080_CONF1_SXP0;
|
||||
isp_pci_wr_reg(isp, BIU_CONF1, tc);
|
||||
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), tc);
|
||||
} else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) {
|
||||
oc = isp_pci_rd_reg(isp, BIU_CONF1);
|
||||
isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA);
|
||||
oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
|
||||
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1),
|
||||
oc | BIU_PCI1080_CONF1_DMA);
|
||||
}
|
||||
offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
|
||||
offset += (regoff & 0xff);
|
||||
rv = bus_space_read_2(pcs->pci_st, pcs->pci_sh, offset);
|
||||
rv = BXR2(pcs, IspVirt2Off(isp, regoff));
|
||||
if (oc) {
|
||||
isp_pci_wr_reg(isp, BIU_CONF1, oc);
|
||||
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc);
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
|
||||
static void
|
||||
isp_pci_wr_reg_1080(isp, regoff, val)
|
||||
struct ispsoftc *isp;
|
||||
int regoff;
|
||||
u_int16_t val;
|
||||
isp_pci_wr_reg_1080(struct ispsoftc *isp, int regoff, u_int16_t val)
|
||||
{
|
||||
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
|
||||
int offset, oc = 0;
|
||||
int oc = 0;
|
||||
|
||||
if ((regoff & _BLK_REG_MASK) == SXP_BLOCK ||
|
||||
(regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) {
|
||||
|
|
@ -802,28 +946,27 @@ isp_pci_wr_reg_1080(isp, regoff, val)
|
|||
/*
|
||||
* We will assume that someone has paused the RISC processor.
|
||||
*/
|
||||
oc = isp_pci_rd_reg(isp, BIU_CONF1);
|
||||
oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
|
||||
tc = oc & ~BIU_PCI1080_CONF1_DMA;
|
||||
if (regoff & SXP_BANK1_SELECT)
|
||||
tc |= BIU_PCI1080_CONF1_SXP1;
|
||||
else
|
||||
tc |= BIU_PCI1080_CONF1_SXP0;
|
||||
isp_pci_wr_reg(isp, BIU_CONF1, tc);
|
||||
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), tc);
|
||||
} else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) {
|
||||
oc = isp_pci_rd_reg(isp, BIU_CONF1);
|
||||
isp_pci_wr_reg(isp, BIU_CONF1, oc | BIU_PCI1080_CONF1_DMA);
|
||||
oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
|
||||
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1),
|
||||
oc | BIU_PCI1080_CONF1_DMA);
|
||||
}
|
||||
offset = pcs->pci_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
|
||||
offset += (regoff & 0xff);
|
||||
bus_space_write_2(pcs->pci_st, pcs->pci_sh, offset, val);
|
||||
BXW2(pcs, IspVirt2Off(isp, regoff), val);
|
||||
if (oc) {
|
||||
isp_pci_wr_reg(isp, BIU_CONF1, oc);
|
||||
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc);
|
||||
}
|
||||
}
|
||||
|
||||
static void isp_map_rquest __P((void *, bus_dma_segment_t *, int, int));
|
||||
static void isp_map_result __P((void *, bus_dma_segment_t *, int, int));
|
||||
static void isp_map_fcscrt __P((void *, bus_dma_segment_t *, int, int));
|
||||
static void isp_map_rquest(void *, bus_dma_segment_t *, int, int);
|
||||
static void isp_map_result(void *, bus_dma_segment_t *, int, int);
|
||||
static void isp_map_fcscrt(void *, bus_dma_segment_t *, int, int);
|
||||
|
||||
struct imush {
|
||||
struct ispsoftc *isp;
|
||||
|
|
@ -1552,7 +1695,7 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void dma2 __P((void *, bus_dma_segment_t *, int, int));
|
||||
static void dma2(void *, bus_dma_segment_t *, int, int);
|
||||
|
||||
static void
|
||||
dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
|
||||
|
|
@ -1700,7 +1843,7 @@ isp_pci_dmasetup(struct ispsoftc *isp, struct ccb_scsiio *csio, ispreq_t *rq,
|
|||
struct isp_pcisoftc *pci = (struct isp_pcisoftc *)isp;
|
||||
bus_dmamap_t *dp = NULL;
|
||||
mush_t mush, *mp;
|
||||
void (*eptr) __P((void *, bus_dma_segment_t *, int, int));
|
||||
void (*eptr)(void *, bus_dma_segment_t *, int, int);
|
||||
|
||||
#ifdef ISP_TARGET_MODE
|
||||
if (csio->ccb_h.func_code == XPT_CONT_TARGET_IO) {
|
||||
|
|
|
|||
|
|
@ -219,16 +219,16 @@ typedef struct {
|
|||
*/
|
||||
|
||||
#define WRITE_REQUEST_QUEUE_IN_POINTER(isp, value) \
|
||||
ISP_WRITE(isp, INMAILBOX4, value)
|
||||
ISP_WRITE(isp, isp->isp_rqstinrp, value)
|
||||
|
||||
#define READ_REQUEST_QUEUE_OUT_POINTER(isp) \
|
||||
ISP_READ(isp, OUTMAILBOX4)
|
||||
#define READ_REQUEST_QUEUE_OUT_POINTER(isp) \
|
||||
ISP_READ(isp, isp->isp_rqstoutrp)
|
||||
|
||||
#define WRITE_RESPONSE_QUEUE_IN_POINTER(isp, value) \
|
||||
ISP_WRITE(isp, INMAILBOX5, value)
|
||||
#define READ_RESPONSE_QUEUE_IN_POINTER(isp) \
|
||||
ISP_READ(isp, isp->isp_respinrp)
|
||||
|
||||
#define READ_RESPONSE_QUEUE_OUT_POINTER(isp) \
|
||||
ISP_READ(isp, OUTMAILBOX5)
|
||||
#define WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, value) \
|
||||
ISP_WRITE(isp, isp->isp_respoutrp, value)
|
||||
|
||||
/*
|
||||
* Command Structure Definitions
|
||||
|
|
@ -240,7 +240,8 @@ typedef struct {
|
|||
} ispds_t;
|
||||
|
||||
typedef struct {
|
||||
u_int64_t ds_base;
|
||||
u_int32_t ds_base;
|
||||
u_int32_t ds_basehi;
|
||||
u_int32_t ds_count;
|
||||
} ispds64_t;
|
||||
|
||||
|
|
@ -353,7 +354,7 @@ typedef struct {
|
|||
#define ISP_SBUSIFY_ISPREQ(a, b)
|
||||
#endif
|
||||
|
||||
#define ISP_RQDSEG_T2 3
|
||||
#define ISP_RQDSEG_T2 3
|
||||
typedef struct {
|
||||
isphdr_t req_header;
|
||||
u_int32_t req_handle;
|
||||
|
|
@ -369,6 +370,22 @@ typedef struct {
|
|||
ispds_t req_dataseg[ISP_RQDSEG_T2];
|
||||
} ispreqt2_t;
|
||||
|
||||
#define ISP_RQDSEG_T3 2
|
||||
typedef struct {
|
||||
isphdr_t req_header;
|
||||
u_int32_t req_handle;
|
||||
u_int8_t req_lun_trn;
|
||||
u_int8_t req_target;
|
||||
u_int16_t req_scclun;
|
||||
u_int16_t req_flags;
|
||||
u_int16_t _res2;
|
||||
u_int16_t req_time;
|
||||
u_int16_t req_seg_count;
|
||||
u_int32_t req_cdb[4];
|
||||
u_int32_t req_totalcnt;
|
||||
ispds64_t req_dataseg[ISP_RQDSEG_T3];
|
||||
} ispreqt3_t;
|
||||
|
||||
/* req_flag values */
|
||||
#define REQFLAG_NODISCON 0x0001
|
||||
#define REQFLAG_HTAG 0x0002
|
||||
|
|
@ -410,6 +427,12 @@ typedef struct {
|
|||
ispds_t req_dataseg[ISP_CDSEG];
|
||||
} ispcontreq_t;
|
||||
|
||||
#define ISP_CDSEG64 5
|
||||
typedef struct {
|
||||
isphdr_t req_header;
|
||||
ispds64_t req_dataseg[ISP_CDSEG64];
|
||||
} ispcontreq64_t;
|
||||
|
||||
typedef struct {
|
||||
isphdr_t req_header;
|
||||
u_int32_t req_handle;
|
||||
|
|
@ -630,6 +653,10 @@ typedef struct isp_icb {
|
|||
#define ICBXOPT_RIO_16BIT_DELAY 3
|
||||
#define ICBXOPT_RIO_32BIT_DELAY 4
|
||||
|
||||
/* These 3 only apply to the 2300 */
|
||||
#define ICBXOPT_RATE_ONEGB (0 << 14)
|
||||
#define ICBXOPT_RATE_TWOGB (1 << 14)
|
||||
#define ICBXOPT_RATE_AUTO (2 << 14)
|
||||
|
||||
|
||||
#define ICB_MIN_FRMLEN 256
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@
|
|||
|
||||
#define PCI_MBOX_REGS_OFF 0x70
|
||||
#define PCI_MBOX_REGS2100_OFF 0x10
|
||||
#define PCI_MBOX_REGS2300_OFF 0x40
|
||||
#define SBUS_MBOX_REGS_OFF 0x80
|
||||
|
||||
#define PCI_SXP_REGS_OFF 0x80
|
||||
|
|
@ -107,6 +108,37 @@
|
|||
#define BIU_ISR (BIU_BLOCK+0xA) /* R : Bus Interface Status */
|
||||
#define BIU_SEMA (BIU_BLOCK+0xC) /* RW : Bus Semaphore */
|
||||
#define BIU_NVRAM (BIU_BLOCK+0xE) /* RW : Bus NVRAM */
|
||||
/*
|
||||
* These are specific to the 2300.
|
||||
*
|
||||
* They *claim* you can read BIU_R2HSTSLO with a full 32 bit access
|
||||
* and get both registers, but I'm a bit dubious about that. But the
|
||||
* point here is that the top 16 bits are firmware defined bits that
|
||||
* the RISC processor uses to inform the host about something- usually
|
||||
* something which was nominally in a mailbox register.
|
||||
*/
|
||||
#define BIU_REQINP (BIU_BLOCK+0x10) /* Request Queue In */
|
||||
#define BIU_REQOUTP (BIU_BLOCK+0x12) /* Request Queue Out */
|
||||
#define BIU_RSPINP (BIU_BLOCK+0x14) /* Response Queue In */
|
||||
#define BIU_RSPOUTP (BIU_BLOCK+0x16) /* Response Queue Out */
|
||||
|
||||
#define BIU_R2HSTSLO (BIU_BLOCK+0x18)
|
||||
#define BIU_R2HSTSHI (BIU_BLOCK+0x1A)
|
||||
|
||||
#define BIU_R2HST_INTR (1 << 15) /* RISC to Host Interrupt */
|
||||
#define BIU_R2HST_PAUSED (1 << 8) /* RISC paused */
|
||||
#define BIU_R2HST_ISTAT_MASK 0x3f /* intr information && status */
|
||||
#define ISPR2HST_ROM_MBX_OK 0x1 /* ROM mailbox cmd done ok */
|
||||
#define ISPR2HST_ROM_MBX_FAIL 0x2 /* ROM mailbox cmd done fail */
|
||||
#define ISPR2HST_MBX_OK 0x10 /* mailbox cmd done ok */
|
||||
#define ISPR2HST_MBX_FAIL 0x11 /* mailbox cmd done fail */
|
||||
#define ISPR2HST_ASYNC_EVENT 0x12 /* Async Event */
|
||||
#define ISPR2HST_RSPQ_UPDATE 0x13 /* Response Queue Update */
|
||||
#define ISPR2HST_RQST_UPDATE 0x14 /* Resquest Queue Update */
|
||||
#define ISPR2HST_RIO_16 0x15 /* RIO 1-16 */
|
||||
#define ISPR2HST_FPOST 0x16 /* Low 16 bits fast post */
|
||||
#define ISPR2HST_FPOST_CTIO 0x17 /* Low 16 bits fast post ctio */
|
||||
|
||||
#define DFIFO_COMMAND (BIU_BLOCK+0x60) /* RW : Command FIFO Port */
|
||||
#define RDMA2100_CONTROL DFIFO_COMMAND
|
||||
#define DFIFO_DATA (BIU_BLOCK+0x62) /* RW : Data FIFO Port */
|
||||
|
|
|
|||
|
|
@ -54,20 +54,22 @@
|
|||
#endif
|
||||
|
||||
#define ISP_CORE_VERSION_MAJOR 2
|
||||
#define ISP_CORE_VERSION_MINOR 2
|
||||
#define ISP_CORE_VERSION_MINOR 4
|
||||
|
||||
/*
|
||||
* Vector for bus specific code to provide specific services.
|
||||
*/
|
||||
struct ispsoftc;
|
||||
struct ispmdvec {
|
||||
int (*dv_rd_isr)
|
||||
(struct ispsoftc *, u_int16_t *, u_int16_t *, u_int16_t *);
|
||||
u_int16_t (*dv_rd_reg) (struct ispsoftc *, int);
|
||||
void (*dv_wr_reg) (struct ispsoftc *, int, u_int16_t);
|
||||
int (*dv_mbxdma) (struct ispsoftc *);
|
||||
int (*dv_dmaset) (struct ispsoftc *,
|
||||
XS_T *, ispreq_t *, u_int16_t *, u_int16_t);
|
||||
XS_T *, ispreq_t *, u_int16_t *, u_int16_t);
|
||||
void (*dv_dmaclr)
|
||||
(struct ispsoftc *, XS_T *, u_int16_t);
|
||||
(struct ispsoftc *, XS_T *, u_int16_t);
|
||||
void (*dv_reset0) (struct ispsoftc *);
|
||||
void (*dv_reset1) (struct ispsoftc *);
|
||||
void (*dv_dregs) (struct ispsoftc *, const char *);
|
||||
|
|
@ -79,16 +81,24 @@ struct ispmdvec {
|
|||
/*
|
||||
* Overall parameters
|
||||
*/
|
||||
#define MAX_TARGETS 16
|
||||
#define MAX_FC_TARG 256
|
||||
#define MAX_TARGETS 16
|
||||
#define MAX_FC_TARG 256
|
||||
#define ISP_MAX_TARGETS(isp) (IS_FC(isp)? MAX_FC_TARG : MAX_TARGETS)
|
||||
#define ISP_MAX_LUNS(isp) (isp)->isp_maxluns
|
||||
|
||||
/*
|
||||
* 'Types'
|
||||
*/
|
||||
#ifndef ISP_DMA_ADDR_T
|
||||
#define ISP_DMA_ADDR_T u_int32_t
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Macros to access ISP registers through bus specific layers-
|
||||
* mostly wrappers to vector through the mdvec structure.
|
||||
*/
|
||||
#define ISP_READ_ISR(isp, isrp, semap, mbox0p) \
|
||||
(*(isp)->isp_mdvec->dv_rd_isr)(isp, isrp, semap, mbox0p)
|
||||
|
||||
#define ISP_READ(isp, reg) \
|
||||
(*(isp)->isp_mdvec->dv_rd_reg)((isp), (reg))
|
||||
|
|
@ -152,7 +162,7 @@ struct ispmdvec {
|
|||
|
||||
#define ISP_ADD_REQUEST(isp, iptr) \
|
||||
MEMORYBARRIER(isp, SYNC_REQUEST, iptr, QENTRY_LEN); \
|
||||
ISP_WRITE(isp, INMAILBOX4, iptr); \
|
||||
WRITE_REQUEST_QUEUE_IN_POINTER(isp, iptr); \
|
||||
isp->isp_reqidx = iptr
|
||||
|
||||
/*
|
||||
|
|
@ -284,7 +294,7 @@ typedef struct {
|
|||
* Scratch DMA mapped in area to fetch Port Database stuff, etc.
|
||||
*/
|
||||
caddr_t isp_scratch;
|
||||
u_int32_t isp_scdma;
|
||||
ISP_DMA_ADDR_T isp_scdma;
|
||||
} fcparam;
|
||||
|
||||
#define FW_CONFIG_WAIT 0
|
||||
|
|
@ -350,6 +360,11 @@ typedef struct ispsoftc {
|
|||
|
||||
u_int32_t isp_confopts; /* config options */
|
||||
|
||||
u_int16_t isp_rqstinrp; /* register for REQINP */
|
||||
u_int16_t isp_rqstoutrp; /* register for REQOUTP */
|
||||
u_int16_t isp_respinrp; /* register for RESINP */
|
||||
u_int16_t isp_respoutrp; /* register for RESOUTP */
|
||||
|
||||
/*
|
||||
* Instrumentation
|
||||
*/
|
||||
|
|
@ -384,8 +399,8 @@ typedef struct ispsoftc {
|
|||
*/
|
||||
caddr_t isp_rquest;
|
||||
caddr_t isp_result;
|
||||
u_int32_t isp_rquest_dma;
|
||||
u_int32_t isp_result_dma;
|
||||
ISP_DMA_ADDR_T isp_rquest_dma;
|
||||
ISP_DMA_ADDR_T isp_result_dma;
|
||||
} ispsoftc_t;
|
||||
|
||||
#define SDPARAM(isp) ((sdparam *) (isp)->isp_param)
|
||||
|
|
@ -447,6 +462,7 @@ typedef struct ispsoftc {
|
|||
* Firmware related defines
|
||||
*/
|
||||
#define ISP_CODE_ORG 0x1000 /* default f/w code start */
|
||||
#define ISP_CODE_ORG_2300 0x0800 /* ..except for 2300s */
|
||||
#define ISP_FW_REV(maj, min, mic) ((maj << 24) | (min << 16) | mic)
|
||||
#define ISP_FW_REVX(xp) ((xp[0]<<24) | (xp[1] << 16) | xp[2])
|
||||
|
||||
|
|
@ -490,16 +506,15 @@ typedef struct ispsoftc {
|
|||
#define IS_FC(isp) ((isp)->isp_type & ISP_HA_FC)
|
||||
#define IS_2100(isp) ((isp)->isp_type == ISP_HA_FC_2100)
|
||||
#define IS_2200(isp) ((isp)->isp_type == ISP_HA_FC_2200)
|
||||
#define IS_2300(isp) ((isp)->isp_type == ISP_HA_FC_2300)
|
||||
|
||||
/* 2300 Support isn't ready yet */
|
||||
#define ISP_DISABLE_2300_SUPPORT 1
|
||||
#define IS_2300(isp) ((isp)->isp_type >= ISP_HA_FC_2300)
|
||||
|
||||
/*
|
||||
* DMA cookie macros
|
||||
*/
|
||||
#define DMA_MSW(x) (((x) >> 16) & 0xffff)
|
||||
#define DMA_LSW(x) (((x) & 0xffff))
|
||||
#define DMA_WD3(x) 0
|
||||
#define DMA_WD2(x) 0
|
||||
#define DMA_WD1(x) (((x) >> 16) & 0xffff)
|
||||
#define DMA_WD0(x) (((x) & 0xffff))
|
||||
|
||||
/*
|
||||
* Core System Function Prototypes
|
||||
|
|
@ -522,9 +537,14 @@ void isp_init(struct ispsoftc *);
|
|||
void isp_reinit(struct ispsoftc *);
|
||||
|
||||
/*
|
||||
* Interrupt Service Routine
|
||||
* Internal Interrupt Service Routine
|
||||
*
|
||||
* The outer layers do the spade work to get the appropriate status register,
|
||||
* semaphore register and first mailbox register (if appropriate). This also
|
||||
* means that most spurious/bogus interrupts not for us can be filtered first.
|
||||
*/
|
||||
int isp_intr(void *);
|
||||
void isp_intr(struct ispsoftc *, u_int16_t, u_int16_t, u_int16_t);
|
||||
|
||||
|
||||
/*
|
||||
* Command Entry Point- Platform Dependent layers call into this
|
||||
|
|
@ -689,6 +709,11 @@ void isp_prt(struct ispsoftc *, int level, const char *, ...);
|
|||
*
|
||||
* INLINE - platform specific define for 'inline' functions
|
||||
*
|
||||
* ISP_DMA_ADDR_T - platform specific dma address coookie- basically
|
||||
* the largest integer that can hold the 32 or
|
||||
* 64 bit value appropriate for the QLogic's DMA
|
||||
* addressing. Defaults to u_int32_t.
|
||||
*
|
||||
* ISP2100_SCRLEN - length for the Fibre Channel scratch DMA area
|
||||
*
|
||||
* MEMZERO(dst, src) platform zeroing function
|
||||
|
|
|
|||
Loading…
Reference in a new issue