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:
Matt Jacob 2001-08-31 21:39:04 +00:00
parent a2f1799115
commit 126ec86486
7 changed files with 600 additions and 295 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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 */

View file

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