1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-20 11:11:24 +00:00

Add 4Gb (24XX) support and lay the foundation for a lot of new stuff.

This commit is contained in:
Matt Jacob 2006-11-02 03:21:32 +00:00
parent 6576695766
commit 10365e5a68
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=163899
14 changed files with 7697 additions and 3442 deletions

File diff suppressed because it is too large Load Diff

View File

@ -46,6 +46,9 @@ __FBSDID("$FreeBSD$");
MODULE_VERSION(isp, 1);
MODULE_DEPEND(isp, cam, 1, 1, 1);
int isp_announced = 0;
int isp_fabric_hysteresis = 5;
int isp_loop_down_limit = 300; /* default loop down limit */
int isp_quickboot_time = 5; /* don't wait more than N secs for loop up */
static d_ioctl_t ispioctl;
static void isp_intr_enable(void *);
@ -242,7 +245,7 @@ isp_attach(ispsoftc_t *isp)
if (isp->isp_role != ISP_ROLE_NONE) {
isp->isp_state = ISP_RUNSTATE;
ENABLE_INTS(isp);
ISP_ENABLE_INTS(isp);
}
if (isplist == NULL) {
isplist = isp;
@ -387,7 +390,7 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
case ISP_FC_GETDINFO:
{
struct isp_fc_device *ifc = (struct isp_fc_device *) addr;
struct lportdb *lp;
fcportdb_t *lp;
if (IS_SCSI(isp)) {
break;
@ -398,9 +401,9 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
}
ISP_LOCK(isp);
lp = &FCPARAM(isp)->portdb[ifc->loopid];
if (lp->valid) {
if (lp->state == FC_PORTDB_STATE_VALID) {
ifc->role = lp->roles;
ifc->loopid = lp->loopid;
ifc->loopid = lp->handle;
ifc->portid = lp->portid;
ifc->node_wwn = lp->node_wwn;
ifc->port_wwn = lp->port_wwn;
@ -566,7 +569,7 @@ ispioctl(_DEV dev, u_long c, caddr_t addr, int flags, _IOP *td)
memset(&mbs, 0, sizeof (mbs));
needmarker = retval = 0;
loopid = fct->loopid;
if (IS_2KLOGIN(isp) == 0) {
if (FCPARAM(isp)->isp_2klogin == 0) {
loopid <<= 8;
}
switch (fct->action) {
@ -657,10 +660,7 @@ isp_intr_enable(void *arg)
{
ispsoftc_t *isp = arg;
if (isp->isp_role != ISP_ROLE_NONE) {
ENABLE_INTS(isp);
#if 0
isp->isp_osinfo.intsok = 1;
#endif
ISP_ENABLE_INTS(isp);
}
/* Release our hook so that the boot can continue. */
config_intrhook_disestablish(&isp->isp_osinfo.ehook);
@ -911,7 +911,7 @@ isp_en_lun(ispsoftc_t *isp, union ccb *ccb)
/*
* This is as a good a place as any to check f/w capabilities.
*/
if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_TMODE) == 0) {
if (FCPARAM(isp)->isp_tmode == 0) {
isp_prt(isp, ISP_LOGERR,
"firmware does not support target mode");
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
@ -921,9 +921,8 @@ isp_en_lun(ispsoftc_t *isp, union ccb *ccb)
* XXX: We *could* handle non-SCCLUN f/w, but we'd have to
* XXX: dorks with our already fragile enable/disable code.
*/
if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) {
isp_prt(isp, ISP_LOGERR,
"firmware not SCCLUN capable");
if (FCPARAM(isp)->isp_sccfw == 0) {
isp_prt(isp, ISP_LOGERR, "firmware not SCCLUN capable");
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
return (-1);
}
@ -1280,8 +1279,7 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
{
void *qe;
struct ccb_scsiio *cso = &ccb->csio;
uint16_t *hp, save_handle;
uint16_t nxti, optr;
uint32_t nxti, optr, handle;
uint8_t local[QENTRY_LEN];
@ -1303,11 +1301,11 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
cto->ct_header.rqs_entry_count = 1;
if (IS_2KLOGIN(isp)) {
if (FCPARAM(isp)->isp_2klogin) {
((ct2e_entry_t *)cto)->ct_iid = cso->init_id;
} else {
cto->ct_iid = cso->init_id;
if (!(FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN)) {
if (FCPARAM(isp)->isp_sccfw == 0) {
cto->ct_lun = ccb->ccb_h.target_lun;
}
}
@ -1386,7 +1384,6 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
atp->state = ATPD_STATE_CTIO;
}
cto->ct_timeout = 10;
hp = &cto->ct_syshandle;
} else {
ct_entry_t *cto = (ct_entry_t *) local;
@ -1422,10 +1419,9 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
}
ccb->ccb_h.flags &= ~CAM_SEND_SENSE;
cto->ct_timeout = 10;
hp = &cto->ct_syshandle;
}
if (isp_save_xs_tgt(isp, ccb, hp)) {
if (isp_save_xs_tgt(isp, ccb, &handle)) {
xpt_print_path(ccb->ccb_h.path);
printf("No XFLIST pointers for isp_target_start_ctio\n");
XS_SETERR(ccb, CAM_REQUEUE_REQ);
@ -1442,7 +1438,13 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
* format.
*/
save_handle = *hp;
if (IS_FC(isp)) {
ct2_entry_t *cto = (ct2_entry_t *) local;
cto->ct_syshandle = handle;
} else {
ct_entry_t *cto = (ct_entry_t *) local;
cto->ct_syshandle = handle;
}
switch (ISP_DMASETUP(isp, cso, (ispreq_t *) local, &nxti, optr)) {
case CMD_QUEUED:
@ -1457,7 +1459,7 @@ isp_target_start_ctio(ispsoftc_t *isp, union ccb *ccb)
default:
break;
}
isp_destroy_tgt_handle(isp, save_handle);
isp_destroy_tgt_handle(isp, handle);
out:
ISPLOCK_2_CAMLOCK(isp);
@ -1478,7 +1480,7 @@ isp_target_putback_atio(union ccb *ccb)
{
ispsoftc_t *isp;
struct ccb_scsiio *cso;
uint16_t nxti, optr;
uint32_t nxti, optr;
void *qe;
isp = XS_ISP(ccb);
@ -1496,7 +1498,7 @@ isp_target_putback_atio(union ccb *ccb)
MEMZERO(at, sizeof (at2_entry_t));
at->at_header.rqs_entry_type = RQSTYPE_ATIO2;
at->at_header.rqs_entry_count = 1;
if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) != 0) {
if (FCPARAM(isp)->isp_sccfw) {
at->at_scclun = (uint16_t) ccb->ccb_h.target_lun;
} else {
at->at_lun = (uint8_t) ccb->ccb_h.target_lun;
@ -1685,7 +1687,7 @@ isp_handle_platform_atio2(ispsoftc_t *isp, at2_entry_t *aep)
return (0);
}
if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) != 0) {
if (FCPARAM(isp)->isp_sccfw) {
lun = aep->at_scclun;
} else {
lun = aep->at_lun;
@ -1731,8 +1733,7 @@ isp_handle_platform_atio2(ispsoftc_t *isp, at2_entry_t *aep)
lun, tptr->atio_count);
if (tptr == &isp->isp_osinfo.tsdflt[0]) {
atiop->ccb_h.target_id =
((fcparam *)isp->isp_param)->isp_loopid;
atiop->ccb_h.target_id = FCPARAM(isp)->isp_loopid;
atiop->ccb_h.target_lun = lun;
}
/*
@ -2004,7 +2005,8 @@ static void
isp_poll(struct cam_sim *sim)
{
ispsoftc_t *isp = cam_sim_softc(sim);
uint16_t isr, sema, mbox;
uint32_t isr;
uint16_t sema, mbox;
ISP_LOCK(isp);
if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
@ -2020,7 +2022,6 @@ isp_watchdog(void *arg)
XS_T *xs = arg;
ispsoftc_t *isp = XS_ISP(xs);
uint32_t handle;
int iok;
/*
* We've decided this command is dead. Make sure we're not trying
@ -2028,11 +2029,10 @@ isp_watchdog(void *arg)
* and seeing whether it's still alive.
*/
ISP_LOCK(isp);
iok = isp->isp_osinfo.intsok;
isp->isp_osinfo.intsok = 0;
handle = isp_find_handle(isp, xs);
if (handle) {
uint16_t isr, sema, mbox;
uint32_t isr;
uint16_t sema, mbox;
if (XS_CMD_DONE_P(xs)) {
isp_prt(isp, ISP_LOGDEBUG1,
@ -2077,28 +2077,14 @@ isp_watchdog(void *arg)
XS_CMD_C_WDOG(xs);
isp_done(xs);
} else {
uint16_t nxti, optr;
ispreq_t local, *mp= &local, *qe;
XS_CMD_C_WDOG(xs);
xs->ccb_h.timeout_ch = timeout(isp_watchdog, xs, hz);
if (isp_getrqentry(isp, &nxti, &optr, (void **) &qe)) {
ISP_UNLOCK(isp);
return;
}
XS_CMD_S_GRACE(xs);
MEMZERO((void *) mp, sizeof (*mp));
mp->req_header.rqs_entry_count = 1;
mp->req_header.rqs_entry_type = RQSTYPE_MARKER;
mp->req_modifier = SYNC_ALL;
mp->req_target = XS_CHANNEL(xs) << 7;
isp_put_request(isp, mp, qe);
ISP_ADD_REQUEST(isp, nxti);
isp->isp_sendmarker |= 1 << XS_CHANNEL(xs);
}
} else {
isp_prt(isp, ISP_LOGDEBUG2, "watchdog with no command");
}
isp->isp_osinfo.intsok = iok;
ISP_UNLOCK(isp);
}
@ -2106,13 +2092,13 @@ static void
isp_kthread(void *arg)
{
ispsoftc_t *isp = arg;
int slp;
#if __FreeBSD_version < 500000
int s;
s = splcam();
isp->isp_osinfo.intsok = 1;
#else
#ifdef ISP_SMPLOCK
mtx_lock(&isp->isp_lock);
@ -2125,32 +2111,63 @@ isp_kthread(void *arg)
* gotten good fibre channel state.
*/
for (;;) {
int wasfrozen;
int wasfrozen, lb;
isp_prt(isp, ISP_LOGDEBUG0, "kthread: checking FC state");
while (isp_fc_runstate(isp, 2 * 1000000) != 0) {
isp_prt(isp, ISP_LOGDEBUG0, "kthread: FC state ungood");
if (FCPARAM(isp)->isp_fwstate != FW_READY ||
FCPARAM(isp)->isp_loopstate < LOOP_PDB_RCVD) {
if (FCPARAM(isp)->loop_seen_once == 0 ||
isp->isp_osinfo.ktmature == 0) {
break;
}
lb = isp_fc_runstate(isp, 250000);
if (lb) {
unsigned int inc = 1;
if (lb < 0) {
isp_prt(isp, ISP_LOGDEBUG0,
"kthread: FC loop not up (down count %d)",
isp->isp_osinfo.loop_down_time);
} else {
isp_prt(isp, ISP_LOGDEBUG0,
"kthread: FC got to %d (down count %d)",
lb, isp->isp_osinfo.loop_down_time);
}
#ifdef ISP_SMPLOCK
msleep(isp_kthread, &isp->isp_lock,
PRIBIO, "isp_fcthrd", hz);
#else
(void) tsleep(isp_kthread, PRIBIO, "isp_fcthrd", hz);
#endif
/*
* If we've never seen loop up and we've waited longer
* than quickboot time, give up and go to sleep until
* loop comes up. Otherwise, increment the loop down
* time and figure out how long to sleep to the next
* check.
*/
if (FCPARAM(isp)->loop_seen_once == 0 &&
isp->isp_osinfo.loop_down_time >=
isp_quickboot_time) {
isp->isp_osinfo.loop_down_time = 0xffff;
slp = 0;
} else if (isp->isp_osinfo.loop_down_time > 30) {
inc = 30;
slp = 30 * hz;
} else if (isp->isp_osinfo.loop_down_time > 1) {
slp = hz;
} else {
slp = 1;
}
inc += isp->isp_osinfo.loop_down_time;
if (inc < 0xffff) {
isp->isp_osinfo.loop_down_time = inc;
} else {
isp->isp_osinfo.loop_down_time = 0xfffe;
}
} else {
isp_prt(isp, ISP_LOGDEBUG0, "kthread: FC state OK");
isp->isp_osinfo.loop_down_time = 0;
slp = 0;
}
/*
* Even if we didn't get good loop state we may be
* unfreezing the SIMQ so that we can kill off
* commands (if we've never seen loop before, for example).
* If we'd frozen the simq, unfreeze it now so that CAM
* can start sending us commands. If the FC state isn't
* okay yet, they'll hit that in isp_start which will
* freeze the queue again.
*/
isp->isp_osinfo.ktmature = 1;
wasfrozen = isp->isp_osinfo.simqfrozen & SIMQFRZ_LOOPDOWN;
isp->isp_osinfo.simqfrozen &= ~SIMQFRZ_LOOPDOWN;
if (wasfrozen && isp->isp_osinfo.simqfrozen == 0) {
@ -2159,16 +2176,26 @@ isp_kthread(void *arg)
xpt_release_simq(isp->isp_sim, 1);
CAMLOCK_2_ISPLOCK(isp);
}
isp_prt(isp, ISP_LOGDEBUG0, "kthread: waiting until called");
#if __FreeBSD_version < 500000
tsleep(&isp->isp_osinfo.kproc, PRIBIO, "isp_fc_worker", 0);
tsleep(&isp->isp_osinfo.kproc, PRIBIO, "ispf", slp);
#else
#ifdef ISP_SMPLOCK
cv_wait(&isp->isp_osinfo.kthread_cv, &isp->isp_lock);
cv_timed_wait(&isp->isp_osinfo.kthread_cv, &isp->isp_lock, slp);
#else
(void) tsleep(&isp->isp_osinfo.kthread_cv, PRIBIO, "fc_cv", 0);
(void) tsleep(&isp->isp_osinfo.kthread_cv, PRIBIO, "ispf", slp);
#endif
#endif
/*
* If slp is zero, we're waking up for the first time after
* things have been okay. In this case, we set a deferral state
* for all commands and delay hysteresis seconds before starting
* the FC state evaluation. This gives the loop/fabric a chance
* to settle.
*/
if (slp == 0 && isp->isp_osinfo.hysteresis) {
(void) tsleep(&isp_fabric_hysteresis, PRIBIO, "ispT",
(isp->isp_osinfo.hysteresis * hz));
}
}
}
@ -2260,8 +2287,12 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
* This can only happen for Fibre Channel
*/
KASSERT((IS_FC(isp)), ("CMD_RQLATER for FC only"));
if (FCPARAM(isp)->loop_seen_once == 0 &&
isp->isp_osinfo.ktmature) {
/*
* If we've exceeded the loop down limit start
* failing commands.
*/
if (isp->isp_osinfo.loop_down_time >
isp->isp_osinfo.loop_down_limit) {
ISPLOCK_2_CAMLOCK(isp);
XS_SETERR(ccb, CAM_SEL_TIMEOUT);
xpt_done(ccb);
@ -2303,25 +2334,22 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
#ifdef ISP_TARGET_MODE
case XPT_EN_LUN: /* Enable LUN as a target */
{
int seq, iok, i;
int seq, i;
CAMLOCK_2_ISPLOCK(isp);
iok = isp->isp_osinfo.intsok;
isp->isp_osinfo.intsok = 0;
seq = isp_en_lun(isp, ccb);
if (seq < 0) {
isp->isp_osinfo.intsok = iok;
ISPLOCK_2_CAMLOCK(isp);
xpt_done(ccb);
break;
}
for (i = 0; isp->isp_osinfo.leact[seq] && i < 30 * 1000; i++) {
uint16_t isr, sema, mbox;
uint32_t isr;
uint16_t sema, mbox;
if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
isp_intr(isp, isr, sema, mbox);
}
DELAY(1000);
}
isp->isp_osinfo.intsok = iok;
ISPLOCK_2_CAMLOCK(isp);
break;
}
@ -2519,7 +2547,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
else
fc->bitrate = 100000;
if (tgt > 0 && tgt < MAX_FC_TARG) {
struct lportdb *lp = &fcp->portdb[tgt];
fcportdb_t *lp = &fcp->portdb[tgt];
fc->wwnn = lp->node_wwn;
fc->wwpn = lp->port_wwn;
fc->port = lp->portid;
@ -2767,6 +2795,19 @@ int
isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
{
int bus, rv = 0;
static const char *roles[4] = {
"(none)", "Target", "Initiator", "Target/Initiator"
};
static const char prom[] =
"PortID 0x%06x handle 0x%x role %s %s\n"
" WWNN 0x%08x%08x WWPN 0x%08x%08x";
static const char prom2[] =
"PortID 0x%06x handle 0x%x role %s %s tgt %u\n"
" WWNN 0x%08x%08x WWPN 0x%08x%08x";
target_id_t tgt;
fcportdb_t *lp;
struct cam_path *tmppath;
switch (cmd) {
case ISPASYNC_NEW_TGT_PARAMS:
{
@ -2775,7 +2816,6 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
int flags, tgt;
sdparam *sdp = isp->isp_param;
struct ccb_trans_settings cts;
struct cam_path *tmppath;
memset(&cts, 0, sizeof (struct ccb_trans_settings));
@ -2876,59 +2916,127 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
*/
isp_prt(isp, ISP_LOGINFO, "Loop UP");
break;
case ISPASYNC_PROMENADE:
{
const char *fmt = "Target %d (Loop 0x%x) Port ID 0x%x "
"(role %s) %s\n Port WWN 0x%08x%08x\n Node WWN 0x%08x%08x";
static const char *roles[4] = {
"(none)", "Target", "Initiator", "Target/Initiator"
};
fcparam *fcp = isp->isp_param;
int tgt = *((int *) arg);
#if __FreeBSD_version >= 500000
int is_tgt_mask = (SVC3_TGT_ROLE >> SVC3_ROLE_SHIFT);
struct cam_path *tmppath;
#endif
struct lportdb *lp = &fcp->portdb[tgt];
case ISPASYNC_DEV_ARRIVED:
lp = arg;
isp_prt(isp, ISP_LOGINFO, fmt, tgt, lp->loopid, lp->portid,
roles[lp->roles & 0x3],
(lp->valid)? "Arrived" : "Departed",
(uint32_t) (lp->port_wwn >> 32),
(uint32_t) (lp->port_wwn & 0xffffffffLL),
(uint32_t) (lp->node_wwn >> 32),
(uint32_t) (lp->node_wwn & 0xffffffffLL));
ISPLOCK_2_CAMLOCK(isp);
if (lp->ini_map_idx) {
tgt = lp->ini_map_idx - 1;
isp_prt(isp, ISP_LOGCONFIG, prom2,
lp->portid, lp->handle,
roles[lp->roles & 0x3], "arrived at", tgt,
(uint32_t) (lp->node_wwn >> 32),
(uint32_t) lp->node_wwn,
(uint32_t) (lp->port_wwn >> 32),
(uint32_t) lp->port_wwn);
#if __FreeBSD_version >= 500000
if (xpt_create_path(&tmppath, NULL, cam_sim_path(isp->isp_sim),
(target_id_t)tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
CAMLOCK_2_ISPLOCK(isp);
break;
}
/*
* Policy: only announce targets.
*/
if (lp->roles & is_tgt_mask) {
if (lp->valid) {
xpt_async(AC_FOUND_DEVICE, tmppath, NULL);
} else {
xpt_async(AC_LOST_DEVICE, tmppath, NULL);
ISPLOCK_2_CAMLOCK(isp);
if (xpt_create_path(&tmppath, NULL,
cam_sim_path(isp->isp_sim), tgt,
CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
CAMLOCK_2_ISPLOCK(isp);
break;
}
}
xpt_free_path(tmppath);
xpt_async(AC_FOUND_DEVICE, tmppath, NULL);
xpt_free_path(tmppath);
CAMLOCK_2_ISPLOCK(isp);
#endif
CAMLOCK_2_ISPLOCK(isp);
break;
}
case ISPASYNC_CHANGE_NOTIFY:
if (arg == ISPASYNC_CHANGE_PDB) {
isp_prt(isp, ISP_LOGINFO,
"Port Database Changed");
} else if (arg == ISPASYNC_CHANGE_SNS) {
isp_prt(isp, ISP_LOGINFO,
"Name Server Database Changed");
} else {
isp_prt(isp, ISP_LOGCONFIG, prom,
lp->portid, lp->handle,
roles[lp->roles & 0x3], "arrived",
(uint32_t) (lp->node_wwn >> 32),
(uint32_t) lp->node_wwn,
(uint32_t) (lp->port_wwn >> 32),
(uint32_t) lp->port_wwn);
}
break;
case ISPASYNC_DEV_CHANGED:
lp = arg;
if (lp->ini_map_idx) {
tgt = lp->ini_map_idx - 1;
isp_prt(isp, ISP_LOGCONFIG, prom2,
lp->portid, lp->handle,
roles[lp->roles & 0x3], "changed at", tgt,
(uint32_t) (lp->node_wwn >> 32),
(uint32_t) lp->node_wwn,
(uint32_t) (lp->port_wwn >> 32),
(uint32_t) lp->port_wwn);
} else {
isp_prt(isp, ISP_LOGCONFIG, prom,
lp->portid, lp->handle,
roles[lp->roles & 0x3], "changed",
(uint32_t) (lp->node_wwn >> 32),
(uint32_t) lp->node_wwn,
(uint32_t) (lp->port_wwn >> 32),
(uint32_t) lp->port_wwn);
}
break;
case ISPASYNC_DEV_STAYED:
lp = arg;
if (lp->ini_map_idx) {
tgt = lp->ini_map_idx - 1;
isp_prt(isp, ISP_LOGCONFIG, prom2,
lp->portid, lp->handle,
roles[lp->roles & 0x3], "stayed at", tgt,
(uint32_t) (lp->node_wwn >> 32),
(uint32_t) lp->node_wwn,
(uint32_t) (lp->port_wwn >> 32),
(uint32_t) lp->port_wwn);
} else {
isp_prt(isp, ISP_LOGCONFIG, prom,
lp->portid, lp->handle,
roles[lp->roles & 0x3], "stayed",
(uint32_t) (lp->node_wwn >> 32),
(uint32_t) lp->node_wwn,
(uint32_t) (lp->port_wwn >> 32),
(uint32_t) lp->port_wwn);
}
break;
case ISPASYNC_DEV_GONE:
lp = arg;
if (lp->ini_map_idx) {
tgt = lp->ini_map_idx - 1;
isp_prt(isp, ISP_LOGCONFIG, prom2,
lp->portid, lp->handle,
roles[lp->roles & 0x3], "departed from", tgt,
(uint32_t) (lp->node_wwn >> 32),
(uint32_t) lp->node_wwn,
(uint32_t) (lp->port_wwn >> 32),
(uint32_t) lp->port_wwn);
#if __FreeBSD_version >= 500000
ISPLOCK_2_CAMLOCK(isp);
if (xpt_create_path(&tmppath, NULL,
cam_sim_path(isp->isp_sim), tgt,
CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
CAMLOCK_2_ISPLOCK(isp);
break;
}
xpt_async(AC_LOST_DEVICE, tmppath, NULL);
xpt_free_path(tmppath);
CAMLOCK_2_ISPLOCK(isp);
#endif
} else {
isp_prt(isp, ISP_LOGCONFIG, prom,
lp->portid, lp->handle,
roles[lp->roles & 0x3], "departed",
(uint32_t) (lp->node_wwn >> 32),
(uint32_t) lp->node_wwn,
(uint32_t) (lp->port_wwn >> 32),
(uint32_t) lp->port_wwn);
}
break;
case ISPASYNC_CHANGE_NOTIFY:
{
char *msg;
if (arg == ISPASYNC_CHANGE_PDB) {
msg = "Port Database Changed";
} else if (arg == ISPASYNC_CHANGE_SNS) {
msg = "Name Server Database Changed";
} else {
msg = "Other Change Notify";
}
isp_prt(isp, ISP_LOGINFO, msg);
isp_freeze_loopdown(isp, msg);
#if __FreeBSD_version < 500000
wakeup(&isp->isp_osinfo.kproc);
#else
@ -2939,117 +3047,6 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
#endif
#endif
break;
case ISPASYNC_FABRIC_DEV:
{
int target, base, lim;
fcparam *fcp = isp->isp_param;
struct lportdb *lp = NULL;
struct lportdb *clp = (struct lportdb *) arg;
char *pt;
switch (clp->port_type) {
case 1:
pt = " N_Port";
break;
case 2:
pt = " NL_Port";
break;
case 3:
pt = "F/NL_Port";
break;
case 0x7f:
pt = " Nx_Port";
break;
case 0x81:
pt = " F_port";
break;
case 0x82:
pt = " FL_Port";
break;
case 0x84:
pt = " E_port";
break;
default:
pt = " ";
break;
}
isp_prt(isp, ISP_LOGINFO,
"%s Fabric Device @ PortID 0x%x", pt, clp->portid);
/*
* If we don't have an initiator role we bail.
*
* We just use ISPASYNC_FABRIC_DEV for announcement purposes.
*/
if ((isp->isp_role & ISP_ROLE_INITIATOR) == 0) {
break;
}
/*
* Is this entry for us? If so, we bail.
*/
if (fcp->isp_portid == clp->portid) {
break;
}
/*
* Else, the default policy is to find room for it in
* our local port database. Later, when we execute
* the call to isp_pdb_sync either this newly arrived
* or already logged in device will be (re)announced.
*/
if (fcp->isp_topo == TOPO_FL_PORT)
base = FC_SNS_ID+1;
else
base = 0;
if (fcp->isp_topo == TOPO_N_PORT)
lim = 1;
else
lim = MAX_FC_TARG;
/*
* Is it already in our list?
*/
for (target = base; target < lim; target++) {
if (target >= FL_PORT_ID && target <= FC_SNS_ID) {
continue;
}
lp = &fcp->portdb[target];
if (lp->port_wwn == clp->port_wwn &&
lp->node_wwn == clp->node_wwn) {
lp->fabric_dev = 1;
break;
}
}
if (target < lim) {
break;
}
for (target = base; target < lim; target++) {
if (target >= FL_PORT_ID && target <= FC_SNS_ID) {
continue;
}
lp = &fcp->portdb[target];
if (lp->port_wwn == 0) {
break;
}
}
if (target == lim) {
isp_prt(isp, ISP_LOGWARN,
"out of space for fabric devices");
break;
}
lp->port_type = clp->port_type;
lp->fc4_type = clp->fc4_type;
lp->node_wwn = clp->node_wwn;
lp->port_wwn = clp->port_wwn;
lp->portid = clp->portid;
lp->fabric_dev = 1;
break;
}
#ifdef ISP_TARGET_MODE
case ISPASYNC_TARGET_NOTIFY:
@ -3136,8 +3133,12 @@ isp_async(ispsoftc_t *isp, ispasync_t cmd, void *arg)
void
isp_uninit(ispsoftc_t *isp)
{
ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
DISABLE_INTS(isp);
if (IS_24XX(isp)) {
ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_RESET);
} else {
ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
}
ISP_DISABLE_INTS(isp);
}
void

View File

@ -149,13 +149,16 @@ struct isposinfo {
struct cam_sim *sim2;
struct cam_path *path2;
struct intr_config_hook ehook;
uint8_t
uint16_t loop_down_time;
uint16_t loop_down_limit;
uint32_t : 5,
simqfrozen : 3,
hysteresis : 8,
: 4,
disabled : 1,
fcbsy : 1,
ktmature : 1,
mboxwaiting : 1,
intsok : 1,
simqfrozen : 3;
mboxcmd_done : 1,
mboxbsy : 1;
#if __FreeBSD_version >= 500000
struct firmware * fw;
struct mtx lock;
@ -211,18 +214,13 @@ struct isposinfo {
* Required Macros/Defines
*/
#define ISP2100_SCRLEN 0x800
#define ISP2100_SCRLEN 0x1000
#define MEMZERO(a, b) memset(a, 0, b)
#define MEMCPY memcpy
#define SNPRINTF snprintf
#define USEC_DELAY DELAY
#define USEC_SLEEP(isp, x) \
if (isp->isp_osinfo.intsok) \
ISP_UNLOCK(isp); \
DELAY(x); \
if (isp->isp_osinfo.intsok) \
ISP_LOCK(isp)
#define USEC_SLEEP(isp, x) DELAY(x)
#define NANOTIME_T struct timespec
#define GET_NANOTIME nanotime
@ -247,15 +245,10 @@ default: \
break; \
}
#define MBOX_ACQUIRE(isp)
#define MBOX_ACQUIRE isp_mbox_acquire
#define MBOX_WAIT_COMPLETE isp_mbox_wait_complete
#define MBOX_NOTIFY_COMPLETE(isp) \
if (isp->isp_osinfo.mboxwaiting) { \
isp->isp_osinfo.mboxwaiting = 0; \
wakeup(&isp->isp_mbxworkp); \
} \
isp->isp_mboxbsy = 0
#define MBOX_RELEASE(isp)
#define MBOX_NOTIFY_COMPLETE(isp) isp->isp_osinfo.mboxcmd_done = 1
#define MBOX_RELEASE isp_mbox_release
#define FC_SCRATCH_ACQUIRE(isp) \
if (isp->isp_osinfo.fcbsy) { \
@ -361,7 +354,8 @@ default: \
#define ISP_IOXGET_32(isp, s, d) \
d = (isp->isp_bustype == ISP_BT_SBUS)? \
*((uint32_t *)s) : bswap32(*((uint32_t *)s))
#else
#else /* ISP_SBUS_SUPPORTED */
#define ISP_IOXPUT_8(isp, s, d) *(d) = s
#define ISP_IOXPUT_16(isp, s, d) *(d) = bswap16(s)
#define ISP_IOXPUT_32(isp, s, d) *(d) = bswap32(s)
@ -370,6 +364,15 @@ default: \
#define ISP_IOXGET_32(isp, s, d) d = bswap32(*((uint32_t *)s))
#endif
#define ISP_SWIZZLE_NVRAM_WORD(isp, rp) *rp = bswap16(*rp)
#define ISP_IOZGET_8(isp, s, d) d = (*((uint8_t *)s))
#define ISP_IOZGET_16(isp, s, d) d = (*((uint16_t *)s))
#define ISP_IOZGET_32(isp, s, d) d = (*((uint32_t *)s))
#define ISP_IOZPUT_8(isp, s, d) *(d) = s
#define ISP_IOZPUT_16(isp, s, d) *(d) = s
#define ISP_IOZPUT_32(isp, s, d) *(d) = s
#else
#define ISP_IOXPUT_8(isp, s, d) *(d) = s
#define ISP_IOXPUT_16(isp, s, d) *(d) = s
@ -378,6 +381,15 @@ default: \
#define ISP_IOXGET_16(isp, s, d) d = *(s)
#define ISP_IOXGET_32(isp, s, d) d = *(s)
#define ISP_SWIZZLE_NVRAM_WORD(isp, rp)
#define ISP_IOZPUT_8(isp, s, d) *(d) = s
#define ISP_IOZPUT_16(isp, s, d) *(d) = bswap16(s)
#define ISP_IOZPUT_32(isp, s, d) *(d) = bswap32(s)
#define ISP_IOZGET_8(isp, s, d) d = (*((uint8_t *)(s)))
#define ISP_IOZGET_16(isp, s, d) d = bswap16(*((uint16_t *)(s)))
#define ISP_IOZGET_32(isp, s, d) d = bswap32(*((uint32_t *)(s)))
#endif
/*
@ -417,6 +429,9 @@ extern void isp_uninit(ispsoftc_t *);
* driver global data
*/
extern int isp_announced;
extern int isp_fabric_hysteresis;
extern int isp_loop_down_limit;
extern int isp_quickboot_time;
/*
* Platform private flags
@ -444,49 +459,61 @@ extern int isp_announced;
* Platform specific inline functions
*/
static __inline void isp_mbox_wait_complete(ispsoftc_t *);
static __inline void
isp_mbox_wait_complete(ispsoftc_t *isp)
static __inline int isp_mbox_acquire(ispsoftc_t *);
static __inline void isp_mbox_wait_complete(ispsoftc_t *, mbreg_t *);
static __inline void isp_mbox_release(ispsoftc_t *);
static __inline int
isp_mbox_acquire(ispsoftc_t *isp)
{
if (isp->isp_osinfo.intsok) {
int lim = ((isp->isp_mbxwrk0)? 120 : 20) * hz;
isp->isp_osinfo.mboxwaiting = 1;
#ifdef ISP_SMPLOCK
(void) msleep(&isp->isp_mbxworkp,
&isp->isp_lock, PRIBIO, "isp_mboxwaiting", lim);
#else
(void) tsleep(&isp->isp_mbxworkp,
PRIBIO, "isp_mboxwaiting", lim);
#endif
if (isp->isp_mboxbsy != 0) {
isp_prt(isp, ISP_LOGWARN,
"Interrupting Mailbox Command (0x%x) Timeout",
isp->isp_lastmbxcmd);
isp->isp_mboxbsy = 0;
}
isp->isp_osinfo.mboxwaiting = 0;
if (isp->isp_osinfo.mboxbsy) {
return (1);
} else {
int lim = ((isp->isp_mbxwrk0)? 240 : 60) * 10000;
int j;
for (j = 0; j < lim; j++) {
uint16_t isr, sema, mbox;
if (isp->isp_mboxbsy == 0) {
isp->isp_osinfo.mboxcmd_done = 0;
isp->isp_osinfo.mboxbsy = 1;
return (0);
}
}
static __inline void
isp_mbox_wait_complete(ispsoftc_t *isp, mbreg_t *mbp)
{
int lim = mbp->timeout;
int j;
if (lim == 0) {
lim = MBCMD_DEFAULT_TIMEOUT;
}
if (isp->isp_mbxwrk0) {
lim *= isp->isp_mbxwrk0;
}
for (j = 0; j < lim; j += 100) {
uint32_t isr;
uint16_t sema, mbox;
if (isp->isp_osinfo.mboxcmd_done) {
break;
}
if (ISP_READ_ISR(isp, &isr, &sema, &mbox)) {
isp_intr(isp, isr, sema, mbox);
if (isp->isp_osinfo.mboxcmd_done) {
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,
"Polled Mailbox Command (0x%x) Timeout",
isp->isp_lastmbxcmd);
}
USEC_DELAY(100);
}
if (isp->isp_osinfo.mboxcmd_done == 0) {
isp_prt(isp, ISP_LOGWARN,
"Polled Mailbox Command (0x%x) Timeout",
isp->isp_lastmbxcmd);
mbp->param[0] = MBOX_TIMEOUT;
isp->isp_osinfo.mboxcmd_done = 1;
}
}
static __inline void
isp_mbox_release(ispsoftc_t *isp)
{
isp->isp_osinfo.mboxbsy = 0;
}
static __inline uint64_t nanotime_sub(struct timespec *, struct timespec *);

File diff suppressed because it is too large Load Diff

View File

@ -30,22 +30,26 @@
#ifndef _ISP_LIBRARY_H
#define _ISP_LIBRARY_H
extern int isp_save_xs(ispsoftc_t *, XS_T *, uint16_t *);
extern XS_T *isp_find_xs(ispsoftc_t *, uint16_t);
extern uint16_t isp_find_handle(ispsoftc_t *, XS_T *);
extern int isp_handle_index(uint16_t);
extern uint16_t isp_index_handle(int);
extern void isp_destroy_handle(ispsoftc_t *, uint16_t);
extern int isp_getrqentry(ispsoftc_t *, uint16_t *, uint16_t *, void **);
extern int isp_save_xs(ispsoftc_t *, XS_T *, uint32_t *);
extern XS_T *isp_find_xs(ispsoftc_t *, uint32_t);
extern uint32_t isp_find_handle(ispsoftc_t *, XS_T *);
extern uint32_t isp_handle_index(uint32_t);
extern void isp_destroy_handle(ispsoftc_t *, uint32_t);
extern int isp_getrqentry(ispsoftc_t *, uint32_t *, uint32_t *, void **);
extern void isp_print_qentry (ispsoftc_t *, char *, int, void *);
extern void isp_print_bytes(ispsoftc_t *, char *, int, void *);
extern int isp_fc_runstate(ispsoftc_t *, int);
extern void isp_copy_out_hdr(ispsoftc_t *, isphdr_t *, isphdr_t *);
extern void isp_copy_in_hdr(ispsoftc_t *, isphdr_t *, isphdr_t *);
extern void isp_shutdown(ispsoftc_t *);
extern void isp_put_hdr(ispsoftc_t *, isphdr_t *, isphdr_t *);
extern void isp_get_hdr(ispsoftc_t *, isphdr_t *, isphdr_t *);
extern int isp_get_response_type(ispsoftc_t *, isphdr_t *);
extern void
isp_put_request(ispsoftc_t *, ispreq_t *, ispreq_t *);
extern void
isp_put_marker(ispsoftc_t *, isp_marker_t *, isp_marker_t *);
extern void
isp_put_marker_24xx(ispsoftc_t *, isp_marker_24xx_t *, isp_marker_24xx_t *);
extern void
isp_put_request_t2(ispsoftc_t *, ispreqt2_t *, ispreqt2_t *);
extern void
isp_put_request_t2e(ispsoftc_t *, ispreqt2e_t *, ispreqt2e_t *);
@ -56,21 +60,37 @@ isp_put_request_t3e(ispsoftc_t *, ispreqt3e_t *, ispreqt3e_t *);
extern void
isp_put_extended_request(ispsoftc_t *, ispextreq_t *, ispextreq_t *);
extern void
isp_put_request_t7(ispsoftc_t *, ispreqt7_t *, ispreqt7_t *);
extern void
isp_put_24xx_abrt(ispsoftc_t *, isp24xx_abrt_t *, isp24xx_abrt_t *);
extern void
isp_put_cont_req(ispsoftc_t *, ispcontreq_t *, ispcontreq_t *);
extern void
isp_put_cont64_req(ispsoftc_t *, ispcontreq64_t *, ispcontreq64_t *);
extern void
isp_get_response(ispsoftc_t *, ispstatusreq_t *, ispstatusreq_t *);
extern void
isp_get_response_x(ispsoftc_t *, ispstatus_cont_t *, ispstatus_cont_t *);
extern void isp_get_24xx_response(ispsoftc_t *, isp24xx_statusreq_t *,
isp24xx_statusreq_t *);
void
isp_get_24xx_abrt(ispsoftc_t *, isp24xx_abrt_t *, isp24xx_abrt_t *);
extern void
isp_get_rio2(ispsoftc_t *, isp_rio2_t *, isp_rio2_t *);
extern void
isp_put_icb(ispsoftc_t *, isp_icb_t *, isp_icb_t *);
extern void
isp_get_pdb(ispsoftc_t *, isp_pdb_t *, isp_pdb_t *);
isp_put_icb_2400(ispsoftc_t *, isp_icb_2400_t *, isp_icb_2400_t *);
extern void
isp_get_ct_hdr(ispsoftc_t *isp, ct_hdr_t *, ct_hdr_t *);
isp_get_pdb_21xx(ispsoftc_t *, isp_pdb_21xx_t *, isp_pdb_21xx_t *);
extern void
isp_get_pdb_24xx(ispsoftc_t *, isp_pdb_24xx_t *, isp_pdb_24xx_t *);
extern void
isp_get_plogx(ispsoftc_t *, isp_plogx_t *, isp_plogx_t *);
extern void
isp_put_plogx(ispsoftc_t *, isp_plogx_t *, isp_plogx_t *);
extern void
isp_get_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *, isp_ct_pt_t *);
extern void
isp_put_ct_pt(ispsoftc_t *isp, isp_ct_pt_t *, isp_ct_pt_t *);
extern void
isp_put_sns_request(ispsoftc_t *, sns_screq_t *, sns_screq_t *);
extern void
@ -93,6 +113,17 @@ isp_get_gff_id_response(ispsoftc_t *, sns_gff_id_rsp_t *,
extern void
isp_get_ga_nxt_response(ispsoftc_t *, sns_ga_nxt_rsp_t *,
sns_ga_nxt_rsp_t *);
extern void
isp_get_els(ispsoftc_t *, els_t *, els_t *);
extern void
isp_put_els(ispsoftc_t *, els_t *, els_t *);
extern void
isp_get_fc_hdr(ispsoftc_t *, fc_hdr_t *, fc_hdr_t *);
extern void
isp_get_fcp_cmnd_iu(ispsoftc_t *, fcp_cmnd_iu_t *, fcp_cmnd_iu_t *);
extern void isp_put_rft_id(ispsoftc_t *, rft_id_t *, rft_id_t *);
extern void isp_get_ct_hdr(ispsoftc_t *isp, ct_hdr_t *, ct_hdr_t *);
extern void isp_put_ct_hdr(ispsoftc_t *isp, ct_hdr_t *, ct_hdr_t *);
#ifdef ISP_TARGET_MODE
#if defined(__NetBSD__) || defined(__OpenBSD__)
@ -103,10 +134,12 @@ isp_get_ga_nxt_response(ispsoftc_t *, sns_ga_nxt_rsp_t *,
#include "isp_target.h"
#endif
extern int isp_save_xs_tgt(ispsoftc_t *, void *, uint16_t *);
extern void *isp_find_xs_tgt(ispsoftc_t *, uint16_t);
extern uint16_t isp_find_tgt_handle(ispsoftc_t *, void *);
extern void isp_destroy_tgt_handle(ispsoftc_t *, uint16_t);
#define IS_TARGET_HANDLE(x) ((x) & 0x8000)
extern int isp_save_xs_tgt(ispsoftc_t *, void *, uint32_t *);
extern void *isp_find_xs_tgt(ispsoftc_t *, uint32_t);
extern uint32_t isp_find_tgt_handle(ispsoftc_t *, void *);
extern void isp_destroy_tgt_handle(ispsoftc_t *, uint32_t);
extern void
isp_put_atio(ispsoftc_t *, at_entry_t *, at_entry_t *);
@ -121,6 +154,8 @@ isp_get_atio2(ispsoftc_t *, at2_entry_t *, at2_entry_t *);
extern void
isp_get_atio2e(ispsoftc_t *, at2e_entry_t *, at2e_entry_t *);
extern void
isp_get_atio7(ispsoftc_t *isp, at7_entry_t *, at7_entry_t *);
extern void
isp_put_ctio(ispsoftc_t *, ct_entry_t *, ct_entry_t *);
extern void
isp_get_ctio(ispsoftc_t *, ct_entry_t *, ct_entry_t *);
@ -129,10 +164,14 @@ isp_put_ctio2(ispsoftc_t *, ct2_entry_t *, ct2_entry_t *);
extern void
isp_put_ctio2e(ispsoftc_t *, ct2e_entry_t *, ct2e_entry_t *);
extern void
isp_put_ctio7(ispsoftc_t *, ct7_entry_t *, ct7_entry_t *);
extern void
isp_get_ctio2(ispsoftc_t *, ct2_entry_t *, ct2_entry_t *);
extern void
isp_get_ctio2e(ispsoftc_t *, ct2e_entry_t *, ct2e_entry_t *);
extern void
isp_get_ctio7(ispsoftc_t *, ct7_entry_t *, ct7_entry_t *);
extern void
isp_put_enable_lun(ispsoftc_t *, lun_entry_t *, lun_entry_t *);
extern void
isp_get_enable_lun(ispsoftc_t *, lun_entry_t *, lun_entry_t *);
@ -145,20 +184,36 @@ isp_put_notify_fc(ispsoftc_t *, in_fcentry_t *, in_fcentry_t *);
extern void
isp_put_notify_fc_e(ispsoftc_t *, in_fcentry_e_t *, in_fcentry_e_t *);
extern void
isp_put_notify_24xx(ispsoftc_t *, in_fcentry_24xx_t *, in_fcentry_24xx_t *);
extern void
isp_get_notify_fc(ispsoftc_t *, in_fcentry_t *, in_fcentry_t *);
extern void
isp_get_notify_fc_e(ispsoftc_t *, in_fcentry_e_t *, in_fcentry_e_t *);
extern void
isp_get_notify_24xx(ispsoftc_t *, in_fcentry_24xx_t *, in_fcentry_24xx_t *);
extern void
isp_put_notify_ack(ispsoftc_t *, na_entry_t *, na_entry_t *);
extern void
isp_get_notify_ack(ispsoftc_t *, na_entry_t *, na_entry_t *);
extern void
isp_put_notify_24xx_ack(ispsoftc_t *, na_fcentry_24xx_t *, na_fcentry_24xx_t *);
extern void
isp_put_notify_ack_fc(ispsoftc_t *, na_fcentry_t *, na_fcentry_t *);
extern void
isp_put_notify_ack_fc_e(ispsoftc_t *, na_fcentry_e_t *, na_fcentry_e_t *);
extern void isp_put_notify_ack_24xx(ispsoftc_t *, na_fcentry_24xx_t *,
na_fcentry_24xx_t *);
extern void
isp_get_notify_ack_fc(ispsoftc_t *, na_fcentry_t *, na_fcentry_t *);
extern void
isp_get_notify_ack_fc_e(ispsoftc_t *, na_fcentry_e_t *, na_fcentry_e_t *);
extern void isp_get_notify_ack_24xx(ispsoftc_t *, na_fcentry_24xx_t *,
na_fcentry_24xx_t *);
extern void
isp_get_abts(ispsoftc_t *, abts_t *, abts_t *);
extern void
isp_put_abts_rsp(ispsoftc_t *, abts_rsp_t *, abts_rsp_t *);
extern void
isp_get_abts_rsp(ispsoftc_t *, abts_rsp_t *, abts_rsp_t *);
#endif /* ISP_TARGET_MODE */
#endif /* _ISP_LIBRARY_H */

View File

@ -62,19 +62,23 @@ __FBSDID("$FreeBSD$");
#define BUS_PROBE_DEFAULT 0
#endif
static uint16_t isp_pci_rd_reg(ispsoftc_t *, int);
static void isp_pci_wr_reg(ispsoftc_t *, int, uint16_t);
static uint16_t isp_pci_rd_reg_1080(ispsoftc_t *, int);
static void isp_pci_wr_reg_1080(ispsoftc_t *, int, uint16_t);
static uint32_t isp_pci_rd_reg(ispsoftc_t *, int);
static void isp_pci_wr_reg(ispsoftc_t *, int, uint32_t);
static uint32_t isp_pci_rd_reg_1080(ispsoftc_t *, int);
static void isp_pci_wr_reg_1080(ispsoftc_t *, int, uint32_t);
static uint32_t isp_pci_rd_reg_2400(ispsoftc_t *, int);
static void isp_pci_wr_reg_2400(ispsoftc_t *, int, uint32_t);
static int
isp_pci_rd_isr(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *);
isp_pci_rd_isr(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
static int
isp_pci_rd_isr_2300(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *);
isp_pci_rd_isr_2300(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
static int
isp_pci_rd_isr_2400(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
static int isp_pci_mbxdma(ispsoftc_t *);
static int
isp_pci_dmasetup(ispsoftc_t *, XS_T *, ispreq_t *, uint16_t *, uint16_t);
isp_pci_dmasetup(ispsoftc_t *, XS_T *, ispreq_t *, uint32_t *, uint32_t);
static void
isp_pci_dmateardown(ispsoftc_t *, XS_T *, uint16_t);
isp_pci_dmateardown(ispsoftc_t *, XS_T *, uint32_t);
static void isp_pci_reset1(ispsoftc_t *);
@ -158,6 +162,18 @@ static struct ispmdvec mdvec_2300 = {
isp_pci_dumpregs
};
static struct ispmdvec mdvec_2400 = {
isp_pci_rd_isr_2400,
isp_pci_rd_reg_2400,
isp_pci_wr_reg_2400,
isp_pci_mbxdma,
isp_pci_dmasetup,
isp_pci_dmateardown,
NULL,
isp_pci_reset1,
NULL
};
#ifndef PCIM_CMD_INVEN
#define PCIM_CMD_INVEN 0x10
#endif
@ -306,6 +322,7 @@ static struct ispmdvec mdvec_2300 = {
static int isp_pci_probe (device_t);
static int isp_pci_attach (device_t);
static int isp_pci_detach (device_t);
struct isp_pcisoftc {
@ -320,10 +337,12 @@ struct isp_pcisoftc {
bus_dmamap_t *dmaps;
};
static device_method_t isp_pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, isp_pci_probe),
DEVMETHOD(device_attach, isp_pci_attach),
DEVMETHOD(device_detach, isp_pci_detach),
{ 0, 0 }
};
static void isp_pci_intr(void *);
@ -380,11 +399,9 @@ isp_pci_probe(device_t dev)
case PCI_QLOGIC_ISP2322:
device_set_desc(dev, "Qlogic ISP 2322 PCI FC-AL Adapter");
break;
#if 0
case PCI_QLOGIC_ISP2422:
device_set_desc(dev, "Qlogic ISP 2422 PCI FC-AL Adapter");
break;
#endif
case PCI_QLOGIC_ISP6312:
device_set_desc(dev, "Qlogic ISP 6312 PCI FC-AL Adapter");
break;
@ -487,6 +504,23 @@ isp_get_options(device_t dev, ispsoftc_t *isp)
isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO;
}
bitmap = 0;
(void) getenv_int("isp_fabric_hysteresis", &bitmap);
if (bitmap >= 0 && bitmap < 256) {
isp->isp_osinfo.hysteresis = bitmap;
} else {
isp->isp_osinfo.hysteresis = isp_fabric_hysteresis;
}
bitmap = 0;
(void) getenv_int("isp_loop_down_limit", &bitmap);
if (bitmap >= 0 && bitmap < 0xffff) {
isp->isp_osinfo.loop_down_limit = bitmap;
} else {
isp->isp_osinfo.loop_down_limit = isp_loop_down_limit;
}
#ifdef ISP_FW_CRASH_DUMP
bitmap = 0;
if (getenv_int("isp_fw_dump_enable", &bitmap)) {
@ -690,6 +724,24 @@ isp_get_options(device_t dev, ispsoftc_t *isp)
isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO;
}
tval = 0;
(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
"hysteresis", &tval);
if (tval >= 0 && tval < 256) {
isp->isp_osinfo.hysteresis = tval;
} else {
isp->isp_osinfo.hysteresis = isp_fabric_hysteresis;
}
tval = 0;
(void) resource_int_value(device_get_name(dev), device_get_unit(dev),
"loop_down_limit", &tval);
if (tval >= 0 && tval < 0xffff) {
isp->isp_osinfo.loop_down_limit = tval;
} else {
isp->isp_osinfo.loop_down_limit = isp_loop_down_limit;
}
}
static void
@ -886,11 +938,11 @@ isp_pci_attach(device_t dev)
PCI_MBOX_REGS2300_OFF;
}
if (pci_get_devid(dev) == PCI_QLOGIC_ISP2422) {
mdvp = &mdvec_2300;
basetype = ISP_HA_FC_2422;
mdvp = &mdvec_2400;
basetype = ISP_HA_FC_2400;
psize = sizeof (fcparam);
pcs->pci_poff[MBOX_BLOCK >> _BLK_REG_SHFT] =
PCI_MBOX_REGS2300_OFF;
PCI_MBOX_REGS2400_OFF;
}
isp = &pcs->pci_isp;
isp->isp_param = malloc(psize, M_DEVBUF, M_NOWAIT | M_ZERO);
@ -932,6 +984,9 @@ isp_pci_attach(device_t dev)
case PCI_PRODUCT_QLOGIC_ISP6322:
did = 0x2322;
break;
case PCI_PRODUCT_QLOGIC_ISP2422:
did = 0x2400;
break;
default:
break;
}
@ -976,18 +1031,42 @@ isp_pci_attach(device_t dev)
cmd &= ~PCIM_CMD_INVEN;
}
if (IS_23XX(isp)) {
/*
* Can't tell if ROM will hang on 'ABOUT FIRMWARE' command.
*/
isp->isp_touched = 1;
}
if (IS_2322(isp) || pci_get_devid(dev) == PCI_QLOGIC_ISP6312) {
cmd &= ~PCIM_CMD_INTX_DISABLE;
}
if (IS_24XX(isp)) {
int reg;
cmd &= ~PCIM_CMD_INTX_DISABLE;
/*
* Is this a PCI-X card? If so, set max read byte count.
*/
if (pci_find_extcap(dev, PCIY_PCIX, &reg) == 0) {
uint16_t pxcmd;
reg += 2;
pxcmd = pci_read_config(dev, reg, 2);
pxcmd &= ~0xc;
pxcmd |= 0x8;
pci_write_config(dev, reg, 2, pxcmd);
}
/*
* Is this a PCI Express card? If so, set max read byte count.
*/
if (pci_find_extcap(dev, PCIY_EXPRESS, &reg) == 0) {
uint16_t pectl;
reg += 0x8;
pectl = pci_read_config(dev, reg, 2);
pectl &= ~0x7000;
pectl |= 0x4000;
pci_write_config(dev, reg, 2, pectl);
}
}
pci_write_config(dev, PCIR_COMMAND, cmd, 2);
/*
@ -1039,10 +1118,17 @@ isp_pci_attach(device_t dev)
/*
* Last minute checks...
*/
if (IS_23XX(isp)) {
if (IS_23XX(isp) || IS_24XX(isp)) {
isp->isp_port = pci_get_function(dev);
}
if (IS_23XX(isp)) {
/*
* Can't tell if ROM will hang on 'ABOUT FIRMWARE' command.
*/
isp->isp_touched = 1;
}
/*
* Make sure we're in reset state.
*/
@ -1069,6 +1155,7 @@ isp_pci_attach(device_t dev)
* XXXX: (or decrease the reference count to it).
*/
ISP_UNLOCK(isp);
return (0);
bad:
@ -1110,21 +1197,34 @@ isp_pci_attach(device_t dev)
return (ENXIO);
}
static int
isp_pci_detach(device_t dev)
{
struct isp_pcisoftc *pcs;
ispsoftc_t *isp;
pcs = device_get_softc(dev);
if (pcs == NULL) {
return (ENXIO);
}
isp = (ispsoftc_t *) pcs;
ISP_DISABLE_INTS(isp);
return (0);
}
static void
isp_pci_intr(void *arg)
{
ispsoftc_t *isp = arg;
uint16_t isr, sema, mbox;
uint32_t isr;
uint16_t sema, mbox;
ISP_LOCK(isp);
isp->isp_intcnt++;
if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) {
isp->isp_intbogus++;
} else {
int iok = isp->isp_osinfo.intsok;
isp->isp_osinfo.intsok = 0;
isp_intr(isp, isr, sema, mbox);
isp->isp_osinfo.intsok = iok;
}
ISP_UNLOCK(isp);
}
@ -1138,13 +1238,17 @@ isp_pci_intr(void *arg)
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)
#define BXR4(pcs, off) \
bus_space_read_4(pcs->pci_st, pcs->pci_sh, off)
#define BXW4(pcs, off, v) \
bus_space_write_4(pcs->pci_st, pcs->pci_sh, off, v)
static __inline int
isp_pci_rd_debounced(ispsoftc_t *isp, int off, uint16_t *rp)
{
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
uint16_t val0, val1;
uint32_t val0, val1;
int i = 0;
do {
@ -1159,7 +1263,7 @@ isp_pci_rd_debounced(ispsoftc_t *isp, int off, uint16_t *rp)
}
static int
isp_pci_rd_isr(ispsoftc_t *isp, uint16_t *isrp,
isp_pci_rd_isr(ispsoftc_t *isp, uint32_t *isrp,
uint16_t *semap, uint16_t *mbp)
{
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
@ -1196,19 +1300,18 @@ isp_pci_rd_isr(ispsoftc_t *isp, uint16_t *isrp,
}
static int
isp_pci_rd_isr_2300(ispsoftc_t *isp, uint16_t *isrp,
isp_pci_rd_isr_2300(ispsoftc_t *isp, uint32_t *isrp,
uint16_t *semap, uint16_t *mbox0p)
{
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
uint16_t hccr;
uint32_t hccr;
uint32_t r2hisr;
if (!(BXR2(pcs, IspVirt2Off(isp, BIU_ISR) & BIU2100_ISR_RISC_INT))) {
*isrp = 0;
return (0);
}
r2hisr = bus_space_read_4(pcs->pci_st, pcs->pci_sh,
IspVirt2Off(pcs, BIU_R2HSTSLO));
r2hisr = BXR4(pcs, IspVirt2Off(pcs, BIU_R2HSTSLO));
isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr);
if ((r2hisr & BIU_R2HST_INTR) == 0) {
*isrp = 0;
@ -1252,17 +1355,54 @@ isp_pci_rd_isr_2300(ispsoftc_t *isp, uint16_t *isrp,
"RISC paused at interrupt (%x->%x\n", hccr,
ISP_READ(isp, HCCR));
} else {
isp_prt(isp, ISP_LOGERR, "unknown interrerupt 0x%x\n",
isp_prt(isp, ISP_LOGERR, "unknown interrupt 0x%x\n",
r2hisr);
}
return (0);
}
}
static uint16_t
static int
isp_pci_rd_isr_2400(ispsoftc_t *isp, uint32_t *isrp,
uint16_t *semap, uint16_t *mbox0p)
{
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
uint32_t r2hisr;
r2hisr = BXR4(pcs, IspVirt2Off(pcs, BIU2400_R2HSTSLO));
isp_prt(isp, ISP_LOGDEBUG3, "RISC2HOST ISR 0x%x", r2hisr);
if ((r2hisr & BIU2400_R2HST_INTR) == 0) {
*isrp = 0;
return (0);
}
switch (r2hisr & BIU2400_R2HST_ISTAT_MASK) {
case ISP2400R2HST_ROM_MBX_OK:
case ISP2400R2HST_ROM_MBX_FAIL:
case ISP2400R2HST_MBX_OK:
case ISP2400R2HST_MBX_FAIL:
case ISP2400R2HST_ASYNC_EVENT:
*isrp = r2hisr & 0xffff;
*mbox0p = (r2hisr >> 16);
*semap = 1;
return (1);
case ISP2400R2HST_RSPQ_UPDATE:
case ISP2400R2HST_ATIO_RSPQ_UPDATE:
case ISP2400R2HST_ATIO_RQST_UPDATE:
*isrp = r2hisr & 0xffff;
*mbox0p = 0;
*semap = 0;
return (1);
default:
ISP_WRITE(isp, BIU2400_HCCR, HCCR_2400_CMD_CLEAR_RISC_INT);
isp_prt(isp, ISP_LOGERR, "unknown interrupt 0x%x\n", r2hisr);
return (0);
}
}
static uint32_t
isp_pci_rd_reg(ispsoftc_t *isp, int regoff)
{
uint16_t rv;
uint32_t rv;
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
int oldconf = 0;
@ -1282,10 +1422,11 @@ isp_pci_rd_reg(ispsoftc_t *isp, int regoff)
}
static void
isp_pci_wr_reg(ispsoftc_t *isp, int regoff, uint16_t val)
isp_pci_wr_reg(ispsoftc_t *isp, int regoff, uint32_t val)
{
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
int oldconf = 0;
volatile int junk;
if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
/*
@ -1294,22 +1435,25 @@ isp_pci_wr_reg(ispsoftc_t *isp, int regoff, uint16_t val)
oldconf = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1),
oldconf | BIU_PCI_CONF1_SXP);
junk = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
}
BXW2(pcs, IspVirt2Off(isp, regoff), val);
junk = BXR2(pcs, IspVirt2Off(isp, regoff));
if ((regoff & _BLK_REG_MASK) == SXP_BLOCK) {
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oldconf);
junk = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
}
}
static uint16_t
static uint32_t
isp_pci_rd_reg_1080(ispsoftc_t *isp, int regoff)
{
uint16_t rv, oc = 0;
uint32_t rv, oc = 0;
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
if ((regoff & _BLK_REG_MASK) == SXP_BLOCK ||
(regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) {
uint16_t tc;
uint32_t tc;
/*
* We will assume that someone has paused the RISC processor.
*/
@ -1333,14 +1477,15 @@ isp_pci_rd_reg_1080(ispsoftc_t *isp, int regoff)
}
static void
isp_pci_wr_reg_1080(ispsoftc_t *isp, int regoff, uint16_t val)
isp_pci_wr_reg_1080(ispsoftc_t *isp, int regoff, uint32_t val)
{
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
int oc = 0;
volatile int junk;
if ((regoff & _BLK_REG_MASK) == SXP_BLOCK ||
(regoff & _BLK_REG_MASK) == (SXP_BLOCK|SXP_BANK1_SELECT)) {
uint16_t tc;
uint32_t tc;
/*
* We will assume that someone has paused the RISC processor.
*/
@ -1351,14 +1496,137 @@ isp_pci_wr_reg_1080(ispsoftc_t *isp, int regoff, uint16_t val)
else
tc |= BIU_PCI1080_CONF1_SXP0;
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), tc);
junk = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
} else if ((regoff & _BLK_REG_MASK) == DMA_BLOCK) {
oc = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1),
oc | BIU_PCI1080_CONF1_DMA);
junk = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
}
BXW2(pcs, IspVirt2Off(isp, regoff), val);
junk = BXR2(pcs, IspVirt2Off(isp, regoff));
if (oc) {
BXW2(pcs, IspVirt2Off(isp, BIU_CONF1), oc);
junk = BXR2(pcs, IspVirt2Off(isp, BIU_CONF1));
}
}
static uint32_t
isp_pci_rd_reg_2400(ispsoftc_t *isp, int regoff)
{
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
uint32_t rv;
int block = regoff & _BLK_REG_MASK;
switch (block) {
case BIU_BLOCK:
break;
case MBOX_BLOCK:
return (BXR2(pcs, IspVirt2Off(pcs, regoff)));
case SXP_BLOCK:
isp_prt(isp, ISP_LOGWARN, "SXP_BLOCK read at 0x%x", regoff);
return (0xffffffff);
case RISC_BLOCK:
isp_prt(isp, ISP_LOGWARN, "RISC_BLOCK read at 0x%x", regoff);
return (0xffffffff);
case DMA_BLOCK:
isp_prt(isp, ISP_LOGWARN, "DMA_BLOCK read at 0x%x", regoff);
return (0xffffffff);
default:
isp_prt(isp, ISP_LOGWARN, "unknown block read at 0x%x", regoff);
return (0xffffffff);
}
switch (regoff) {
case BIU2400_FLASH_ADDR:
case BIU2400_FLASH_DATA:
case BIU2400_ICR:
case BIU2400_ISR:
case BIU2400_CSR:
case BIU2400_REQINP:
case BIU2400_REQOUTP:
case BIU2400_RSPINP:
case BIU2400_RSPOUTP:
case BIU2400_PRI_RQINP:
case BIU2400_PRI_RSPINP:
case BIU2400_ATIO_RSPINP:
case BIU2400_ATIO_REQINP:
case BIU2400_HCCR:
case BIU2400_GPIOD:
case BIU2400_GPIOE:
case BIU2400_HSEMA:
rv = BXR4(pcs, IspVirt2Off(pcs, regoff));
break;
case BIU2400_R2HSTSLO:
rv = BXR4(pcs, IspVirt2Off(pcs, regoff));
break;
case BIU2400_R2HSTSHI:
rv = BXR4(pcs, IspVirt2Off(pcs, regoff)) >> 16;
break;
default:
isp_prt(isp, ISP_LOGERR,
"isp_pci_rd_reg_2400: unknown offset %x", regoff);
rv = 0xffffffff;
break;
}
return (rv);
}
static void
isp_pci_wr_reg_2400(ispsoftc_t *isp, int regoff, uint32_t val)
{
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp;
int block = regoff & _BLK_REG_MASK;
volatile int junk;
switch (block) {
case BIU_BLOCK:
break;
case MBOX_BLOCK:
BXW2(pcs, IspVirt2Off(pcs, regoff), val);
junk = BXR2(pcs, IspVirt2Off(pcs, regoff));
return;
case SXP_BLOCK:
isp_prt(isp, ISP_LOGWARN, "SXP_BLOCK write at 0x%x", regoff);
return;
case RISC_BLOCK:
isp_prt(isp, ISP_LOGWARN, "RISC_BLOCK write at 0x%x", regoff);
return;
case DMA_BLOCK:
isp_prt(isp, ISP_LOGWARN, "DMA_BLOCK write at 0x%x", regoff);
return;
default:
isp_prt(isp, ISP_LOGWARN, "unknown block write at 0x%x",
regoff);
break;
}
switch (regoff) {
case BIU2400_FLASH_ADDR:
case BIU2400_FLASH_DATA:
case BIU2400_ICR:
case BIU2400_ISR:
case BIU2400_CSR:
case BIU2400_REQINP:
case BIU2400_REQOUTP:
case BIU2400_RSPINP:
case BIU2400_RSPOUTP:
case BIU2400_PRI_RQINP:
case BIU2400_PRI_RSPINP:
case BIU2400_ATIO_RSPINP:
case BIU2400_ATIO_REQINP:
case BIU2400_HCCR:
case BIU2400_GPIOD:
case BIU2400_GPIOE:
case BIU2400_HSEMA:
BXW4(pcs, IspVirt2Off(pcs, regoff), val);
junk = BXR4(pcs, IspVirt2Off(pcs, regoff));
break;
default:
isp_prt(isp, ISP_LOGERR,
"isp_pci_wr_reg_2400: bad offset 0x%x", regoff);
break;
}
}
@ -1430,6 +1698,11 @@ isp_pci_mbxdma(ispsoftc_t *isp)
return (0);
}
if (isp->isp_maxcmds == 0) {
isp_prt(isp, ISP_LOGERR, "maxcmds not set");
return (1);
}
hlim = BUS_SPACE_MAXADDR;
if (IS_ULTRA2(isp) || IS_FC(isp) || IS_1240(isp)) {
slim = (bus_size_t) (1ULL << 32);
@ -1576,8 +1849,8 @@ typedef struct {
ispsoftc_t *isp;
void *cmd_token;
void *rq;
uint16_t *nxtip;
uint16_t optr;
uint32_t *nxtip;
uint32_t optr;
int error;
} mush_t;
@ -1615,7 +1888,7 @@ tdma_mk(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
bus_dmamap_t *dp;
ct_entry_t *cto, *qe;
uint8_t scsi_status;
uint16_t curi, nxti, handle;
uint32_t curi, nxti, handle;
uint32_t sflags;
int32_t resid;
int nth_ctio, nctios, send_status;
@ -1855,7 +2128,7 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
struct ccb_scsiio *csio;
ispsoftc_t *isp;
ct2_entry_t *cto, *qe;
uint16_t curi, nxti;
uint32_t curi, nxti;
ispds_t *ds;
ispds64_t *ds64;
int segcnt, seglim;
@ -1894,7 +2167,7 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
"0x%x res %d", cto->ct_rxid, csio->ccb_h.target_lun,
cto->ct_iid, cto->ct_flags, cto->ct_status,
cto->rsp.m1.ct_scsi_status, cto->ct_resid);
if (IS_2KLOGIN(isp)) {
if (FCPARAM(isp)->isp_2klogin) {
isp_put_ctio2e(isp,
(ct2e_entry_t *)cto, (ct2e_entry_t *)qe);
} else {
@ -1933,12 +2206,12 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
if (segcnt != nseg) {
cto->ct_header.rqs_entry_type = RQSTYPE_CTIO3;
seglim = ISP_RQDSEG_T3;
ds64 = &cto->rsp.m0.ct_dataseg64[0];
ds64 = &cto->rsp.m0.u.ct_dataseg64[0];
ds = NULL;
} else {
seglim = ISP_RQDSEG_T2;
ds64 = NULL;
ds = &cto->rsp.m0.ct_dataseg[0];
ds = &cto->rsp.m0.u.ct_dataseg[0];
}
cto->ct_seg_count = 0;
@ -1973,7 +2246,7 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
}
while (segcnt < nseg) {
uint16_t curip;
uint32_t curip;
int seg;
ispcontreq_t local, *crq = &local, *qep;
@ -2044,18 +2317,127 @@ tdma_mkfc(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
cto->ct_rxid, csio->ccb_h.target_lun, (int) cto->ct_iid,
cto->ct_flags, cto->ct_status, cto->rsp.m1.ct_scsi_status,
cto->ct_resid);
if (IS_2KLOGIN(isp))
if (FCPARAM(isp)->isp_2klogin) {
isp_put_ctio2e(isp, (ct2e_entry_t *)cto, (ct2e_entry_t *)qe);
else
} else {
isp_put_ctio2(isp, cto, qe);
}
ISP_TDQE(isp, "last dma2_tgt_fc", curi, qe);
*mp->nxtip = nxti;
}
#endif
static void dma_2400(void *, bus_dma_segment_t *, int, int);
static void dma2_a64(void *, bus_dma_segment_t *, int, int);
static void dma2(void *, bus_dma_segment_t *, int, int);
static void
dma_2400(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
{
mush_t *mp;
ispsoftc_t *isp;
struct ccb_scsiio *csio;
struct isp_pcisoftc *pcs;
bus_dmamap_t *dp;
bus_dma_segment_t *eseg;
ispreqt7_t *rq;
int seglim, datalen;
uint32_t nxti;
mp = (mush_t *) arg;
if (error) {
mp->error = error;
return;
}
if (nseg < 1) {
isp_prt(mp->isp, ISP_LOGERR, "bad segment count (%d)", nseg);
mp->error = EFAULT;
return;
}
csio = mp->cmd_token;
isp = mp->isp;
rq = mp->rq;
pcs = (struct isp_pcisoftc *)mp->isp;
dp = &pcs->dmaps[isp_handle_index(rq->req_handle)];
nxti = *mp->nxtip;
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREREAD);
} else {
bus_dmamap_sync(pcs->dmat, *dp, BUS_DMASYNC_PREWRITE);
}
datalen = XS_XFRLEN(csio);
/*
* We're passed an initial partially filled in entry that
* has most fields filled in except for data transfer
* related values.
*
* Our job is to fill in the initial request queue entry and
* then to start allocating and filling in continuation entries
* until we've covered the entire transfer.
*/
rq->req_header.rqs_entry_type = RQSTYPE_T7RQS;
rq->req_dl = datalen;
if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
rq->req_alen_datadir = 0x2;
} else {
rq->req_alen_datadir = 0x1;
}
eseg = dm_segs + nseg;
rq->req_dataseg.ds_base = DMA_LO32(dm_segs->ds_addr);
rq->req_dataseg.ds_basehi = DMA_HI32(dm_segs->ds_addr);
rq->req_dataseg.ds_count = dm_segs->ds_len;
datalen -= dm_segs->ds_len;
dm_segs++;
rq->req_seg_count++;
while (datalen > 0 && dm_segs != eseg) {
uint32_t onxti;
ispcontreq64_t local, *crq = &local, *cqe;
cqe = (ispcontreq64_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, nxti);
onxti = nxti;
nxti = ISP_NXT_QENTRY(onxti, RQUEST_QUEUE_LEN(isp));
if (nxti == mp->optr) {
isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow++");
mp->error = MUSHERR_NOQENTRIES;
return;
}
rq->req_header.rqs_entry_count++;
MEMZERO((void *)crq, sizeof (*crq));
crq->req_header.rqs_entry_count = 1;
crq->req_header.rqs_entry_type = RQSTYPE_A64_CONT;
seglim = 0;
while (datalen > 0 && seglim < ISP_CDSEG64 && dm_segs != eseg) {
crq->req_dataseg[seglim].ds_base =
DMA_LO32(dm_segs->ds_addr);
crq->req_dataseg[seglim].ds_basehi =
DMA_HI32(dm_segs->ds_addr);
crq->req_dataseg[seglim].ds_count =
dm_segs->ds_len;
rq->req_seg_count++;
dm_segs++;
seglim++;
datalen -= dm_segs->ds_len;
}
if (isp->isp_dblev & ISP_LOGDEBUG1) {
isp_print_bytes(isp, "Continuation", QENTRY_LEN, crq);
}
isp_put_cont64_req(isp, crq, cqe);
MEMORYBARRIER(isp, SYNC_REQUEST, onxti, QENTRY_LEN);
}
*mp->nxtip = nxti;
}
static void
dma2_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
{
@ -2067,7 +2449,7 @@ dma2_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
bus_dma_segment_t *eseg;
ispreq64_t *rq;
int seglim, datalen;
uint16_t nxti;
uint32_t nxti;
mp = (mush_t *) arg;
if (error) {
@ -2152,7 +2534,7 @@ dma2_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
}
while (datalen > 0 && dm_segs != eseg) {
uint16_t onxti;
uint32_t onxti;
ispcontreq64_t local, *crq = &local, *cqe;
cqe = (ispcontreq64_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, nxti);
@ -2181,6 +2563,9 @@ dma2_a64(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
seglim++;
datalen -= dm_segs->ds_len;
}
if (isp->isp_dblev & ISP_LOGDEBUG1) {
isp_print_bytes(isp, "Continuation", QENTRY_LEN, crq);
}
isp_put_cont64_req(isp, crq, cqe);
MEMORYBARRIER(isp, SYNC_REQUEST, onxti, QENTRY_LEN);
}
@ -2198,7 +2583,7 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
bus_dma_segment_t *eseg;
ispreq_t *rq;
int seglim, datalen;
uint16_t nxti;
uint32_t nxti;
mp = (mush_t *) arg;
if (error) {
@ -2278,7 +2663,7 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
}
while (datalen > 0 && dm_segs != eseg) {
uint16_t onxti;
uint32_t onxti;
ispcontreq_t local, *crq = &local, *cqe;
cqe = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, nxti);
@ -2305,6 +2690,9 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
seglim++;
datalen -= dm_segs->ds_len;
}
if (isp->isp_dblev & ISP_LOGDEBUG1) {
isp_print_bytes(isp, "Continuation", QENTRY_LEN, crq);
}
isp_put_cont_req(isp, crq, cqe);
MEMORYBARRIER(isp, SYNC_REQUEST, onxti, QENTRY_LEN);
}
@ -2316,7 +2704,7 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
*/
static int
isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
uint16_t *nxtip, uint16_t optr)
uint32_t *nxtip, uint32_t optr)
{
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp;
ispreq_t *qep;
@ -2348,7 +2736,9 @@ isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
}
} else
#endif
if (sizeof (bus_addr_t) > 4) {
if (IS_24XX(isp)) {
eptr = dma_2400;
} else if (sizeof (bus_addr_t) > 4) {
eptr = dma2_a64;
} else {
eptr = dma2;
@ -2433,6 +2823,9 @@ isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
return (retval);
}
mbxsync:
if (isp->isp_dblev & ISP_LOGDEBUG1) {
isp_print_bytes(isp, "Request Queue Entry", QENTRY_LEN, rq);
}
switch (rq->req_header.rqs_entry_type) {
case RQSTYPE_REQUEST:
isp_put_request(isp, rq, qep);
@ -2448,12 +2841,15 @@ isp_pci_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
case RQSTYPE_T3RQS:
isp_put_request_t3(isp, (ispreqt3_t *) rq, (ispreqt3_t *) qep);
break;
case RQSTYPE_T7RQS:
isp_put_request_t7(isp, (ispreqt7_t *) rq, (ispreqt7_t *) qep);
break;
}
return (CMD_QUEUED);
}
static void
isp_pci_dmateardown(ispsoftc_t *isp, XS_T *xs, uint16_t handle)
isp_pci_dmateardown(ispsoftc_t *isp, XS_T *xs, uint32_t handle)
{
struct isp_pcisoftc *pcs = (struct isp_pcisoftc *)isp;
bus_dmamap_t *dp = &pcs->dmaps[isp_handle_index(handle)];
@ -2469,10 +2865,12 @@ isp_pci_dmateardown(ispsoftc_t *isp, XS_T *xs, uint16_t handle)
static void
isp_pci_reset1(ispsoftc_t *isp)
{
/* Make sure the BIOS is disabled */
isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS);
if (!IS_24XX(isp)) {
/* Make sure the BIOS is disabled */
isp_pci_wr_reg(isp, HCCR, PCI_HCCR_CMD_BIOS);
}
/* and enable interrupts */
ENABLE_INTS(isp);
ISP_ENABLE_INTS(isp);
}
static void

View File

@ -51,15 +51,17 @@ __FBSDID("$FreeBSD$");
#include <dev/isp/isp_freebsd.h>
static uint16_t isp_sbus_rd_reg(ispsoftc_t *, int);
static void isp_sbus_wr_reg(ispsoftc_t *, int, uint16_t);
static uint32_t
isp_sbus_rd_reg(ispsoftc_t *, int);
static void
isp_sbus_wr_reg(ispsoftc_t *, int, uint32_t);
static int
isp_sbus_rd_isr(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *);
isp_sbus_rd_isr(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
static int isp_sbus_mbxdma(ispsoftc_t *);
static int
isp_sbus_dmasetup(ispsoftc_t *, XS_T *, ispreq_t *, uint16_t *, uint16_t);
isp_sbus_dmasetup(ispsoftc_t *, XS_T *, ispreq_t *, uint32_t *, uint32_t);
static void
isp_sbus_dmateardown(ispsoftc_t *, XS_T *, uint16_t);
isp_sbus_dmateardown(ispsoftc_t *, XS_T *, uint32_t);
static void isp_sbus_reset1(ispsoftc_t *);
static void isp_sbus_dumpregs(ispsoftc_t *, const char *);
@ -149,6 +151,7 @@ isp_sbus_attach(device_t dev)
struct isp_sbussoftc *sbs;
ispsoftc_t *isp = NULL;
int locksetup = 0;
int ints_setup = 0;
/*
* Figure out if we're supposed to skip this one.
@ -184,10 +187,8 @@ isp_sbus_attach(device_t dev)
regs = NULL;
iqd = 0;
rid = 0;
regs =
bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
regs = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
if (regs == 0) {
device_printf(dev, "unable to map registers\n");
goto bad;
@ -242,21 +243,19 @@ isp_sbus_attach(device_t dev)
sbs->sbus_mdvec.dv_conf1 |= BIU_BURST_ENABLE;
}
/*
* Some early versions of the PTI SBus adapter
* would fail in trying to download (via poking)
* FW. We give up on them.
*/
if (strcmp("PTI,ptisp", ofw_bus_get_name(dev)) == 0 ||
strcmp("ptisp", ofw_bus_get_name(dev)) == 0) {
isp->isp_confopts |= ISP_CFG_NORELOAD;
}
/*
* We don't trust NVRAM on SBus cards
*/
isp->isp_confopts |= ISP_CFG_NONVRAM;
/*
* Mark things if we're a PTI SBus adapter.
*/
if (strcmp("PTI,ptisp", ofw_bus_get_name(dev)) == 0 ||
strcmp("ptisp", ofw_bus_get_name(dev)) == 0) {
SDPARAM(isp)->isp_ptisp = 1;
}
#if __FreeBSD_version >= 700000
isp->isp_osinfo.fw = firmware_get("isp_1000");
@ -277,14 +276,6 @@ isp_sbus_attach(device_t dev)
}
#endif
iqd = 0;
sbs->sbus_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd,
RF_ACTIVE | RF_SHAREABLE);
if (sbs->sbus_ires == NULL) {
device_printf(dev, "could not allocate interrupt\n");
goto bad;
}
tval = 0;
if (resource_int_value(device_get_name(dev), device_get_unit(dev),
"fwload_disable", &tval) == 0 && tval != 0) {
@ -313,11 +304,20 @@ isp_sbus_attach(device_t dev)
mtx_init(&isp->isp_osinfo.lock, "isp", NULL, MTX_DEF);
locksetup++;
iqd = 0;
sbs->sbus_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &iqd,
RF_ACTIVE | RF_SHAREABLE);
if (sbs->sbus_ires == NULL) {
device_printf(dev, "could not allocate interrupt\n");
goto bad;
}
if (bus_setup_intr(dev, sbs->sbus_ires, ISP_IFLAGS,
isp_sbus_intr, isp, &sbs->ih)) {
device_printf(dev, "could not setup interrupt\n");
goto bad;
}
ints_setup++;
/*
* Set up logging levels.
@ -327,8 +327,9 @@ isp_sbus_attach(device_t dev)
} else {
isp->isp_dblev = ISP_LOGWARN|ISP_LOGERR;
}
if (bootverbose)
if (bootverbose) {
isp->isp_dblev |= ISP_LOGCONFIG|ISP_LOGINFO;
}
/*
* Make sure we're in reset state.
@ -336,6 +337,7 @@ isp_sbus_attach(device_t dev)
ISP_LOCK(isp);
isp_reset(isp);
if (isp->isp_state != ISP_RESETSTATE) {
isp_uninit(isp);
ISP_UNLOCK(isp);
goto bad;
}
@ -351,42 +353,33 @@ isp_sbus_attach(device_t dev)
ISP_UNLOCK(isp);
goto bad;
}
/*
* XXXX: Here is where we might unload the f/w module
* XXXX: (or decrease the reference count to it).
*/
ISP_UNLOCK(isp);
return (0);
bad:
if (sbs && sbs->ih) {
if (sbs && ints_setup) {
(void) bus_teardown_intr(dev, sbs->sbus_ires, sbs->ih);
}
if (locksetup && isp) {
mtx_destroy(&isp->isp_osinfo.lock);
}
if (sbs && sbs->sbus_ires) {
bus_release_resource(dev, SYS_RES_IRQ, iqd, sbs->sbus_ires);
}
if (locksetup && isp) {
mtx_destroy(&isp->isp_osinfo.lock);
}
if (regs) {
(void) bus_release_resource(dev, 0, 0, regs);
}
if (sbs) {
if (sbs->sbus_isp.isp_param)
if (sbs->sbus_isp.isp_param) {
free(sbs->sbus_isp.isp_param, M_DEVBUF);
}
free(sbs, M_DEVBUF);
}
/*
* XXXX: Here is where we might unload the f/w module
* XXXX: (or decrease the reference count to it).
*/
return (ENXIO);
}
@ -394,17 +387,15 @@ static void
isp_sbus_intr(void *arg)
{
ispsoftc_t *isp = arg;
uint16_t isr, sema, mbox;
uint32_t isr;
uint16_t sema, mbox;
ISP_LOCK(isp);
isp->isp_intcnt++;
if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) {
isp->isp_intbogus++;
} else {
int iok = isp->isp_osinfo.intsok;
isp->isp_osinfo.intsok = 0;
isp_intr(isp, isr, sema, mbox);
isp->isp_osinfo.intsok = iok;
}
ISP_UNLOCK(isp);
}
@ -417,8 +408,7 @@ isp_sbus_intr(void *arg)
bus_space_read_2(sbc->sbus_st, sbc->sbus_sh, off)
static int
isp_sbus_rd_isr(ispsoftc_t *isp, uint16_t *isrp,
uint16_t *semap, uint16_t *mbp)
isp_sbus_rd_isr(ispsoftc_t *isp, uint32_t *isrp, uint16_t *semap, uint16_t *mbp)
{
struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp;
uint16_t isr, sema;
@ -438,7 +428,7 @@ isp_sbus_rd_isr(ispsoftc_t *isp, uint16_t *isrp,
return (1);
}
static uint16_t
static uint32_t
isp_sbus_rd_reg(ispsoftc_t *isp, int regoff)
{
uint16_t rval;
@ -452,7 +442,7 @@ isp_sbus_rd_reg(ispsoftc_t *isp, int regoff)
}
static void
isp_sbus_wr_reg(ispsoftc_t *isp, int regoff, uint16_t val)
isp_sbus_wr_reg(ispsoftc_t *isp, int regoff, uint32_t val)
{
struct isp_sbussoftc *sbs = (struct isp_sbussoftc *) isp;
int offset = sbs->sbus_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
@ -605,8 +595,8 @@ typedef struct {
ispsoftc_t *isp;
void *cmd_token;
void *rq;
uint16_t *nxtip;
uint16_t optr;
uint32_t *nxtip;
uint32_t optr;
int error;
} mush_t;
@ -721,7 +711,7 @@ dma2(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
static int
isp_sbus_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
uint16_t *nxtip, uint16_t optr)
uint32_t *nxtip, uint32_t optr)
{
struct isp_sbussoftc *sbs = (struct isp_sbussoftc *)isp;
ispreq_t *qep;
@ -809,6 +799,9 @@ isp_sbus_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
return (retval);
}
mbxsync:
if (isp->isp_dblev & ISP_LOGDEBUG1) {
isp_print_bytes(isp, "Request Queue Entry", QENTRY_LEN, rq);
}
switch (rq->req_header.rqs_entry_type) {
case RQSTYPE_REQUEST:
isp_put_request(isp, rq, qep);
@ -822,7 +815,7 @@ isp_sbus_dmasetup(ispsoftc_t *isp, struct ccb_scsiio *csio, ispreq_t *rq,
}
static void
isp_sbus_dmateardown(ispsoftc_t *isp, XS_T *xs, uint16_t handle)
isp_sbus_dmateardown(ispsoftc_t *isp, XS_T *xs, uint32_t handle)
{
struct isp_sbussoftc *sbs = (struct isp_sbussoftc *)isp;
bus_dmamap_t *dp = &sbs->dmaps[isp_handle_index(handle)];
@ -834,12 +827,10 @@ isp_sbus_dmateardown(ispsoftc_t *isp, XS_T *xs, uint16_t handle)
bus_dmamap_unload(sbs->dmat, *dp);
}
static void
isp_sbus_reset1(ispsoftc_t *isp)
{
/* enable interrupts */
ENABLE_INTS(isp);
ISP_ENABLE_INTS(isp);
}
static void

200
sys/dev/isp/isp_stds.h Normal file
View File

@ -0,0 +1,200 @@
/* $FreeBSD$ */
/*-
* Mailbox and Queue Entry Definitions for for Qlogic ISP SCSI adapters.
*
* Copyright (c) 1997-2006 by Matthew Jacob
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice immediately at the beginning of the file, without modification,
* this list of conditions, and the following disclaimer.
* 2. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/*
* Structures that derive directly from public standards.
*/
#ifndef _ISP_STDS_H
#define _ISP_STDS_H
/*
* FC Frame Header
*
* Source: dpANS-X3.xxx-199x, section 18 (AKA FC-PH-2)
*
*/
typedef struct {
uint8_t r_ctl;
uint8_t d_id[3];
uint8_t cs_ctl;
uint8_t s_id[3];
uint8_t type;
uint8_t f_ctl;
uint8_t seq_id;
uint8_t df_ctl;
uint16_t seq_cnt;
uint16_t ox_id;
uint16_t rx_id;
uint32_t parameter;
} fc_hdr_t;
/*
* FCP_CMND_IU Payload
*
* Source: NICTS T10, Project 1144D, Revision 07a, Section 9 (AKA fcp2-r07a)
*
* Notes:
* When additional cdb length is defined in fcp_cmnd_alen_datadir,
* bits 2..7, the actual cdb length is 16 + ((fcp_cmnd_alen_datadir>>2)*4),
* with the datalength following in MSB format just after.
*/
typedef struct {
uint8_t fcp_cmnd_lun[8];
uint8_t fcp_cmnd_crn;
uint8_t fcp_cmnd_task_attribute;
uint8_t fcp_cmnd_task_management;
uint8_t fcp_cmnd_alen_datadir;
union {
struct {
uint8_t fcp_cmnd_cdb[16];
uint32_t fcp_cmnd_dl;
} sf;
struct {
uint8_t fcp_cmnd_cdb[1];
} lf;
} cdb_dl;
} fcp_cmnd_iu_t;
#define FCP_CMND_TASK_ATTR_SIMPLE 0x00
#define FCP_CMND_TASK_ATTR_HEAD 0x01
#define FCP_CMND_TASK_ATTR_ORDERED 0x02
#define FCP_CMND_TASK_ATTR_ACA 0x04
#define FCP_CMND_TASK_ATTR_UNTAGGED 0x05
#define FCP_CMND_TASK_ATTR_MASK 0x07
#define FCP_CMND_ADDTL_CDBLEN_SHIFT 2
#define FCP_CMND_DATA_WRITE 0x01
#define FCP_CMND_DATA_READ 0x02
#define FCP_CMND_DATA_DIR_MASK 0x03
#define FCP_CMND_TMF_CLEAR_ACA 0x40
#define FCP_CMND_TMF_TGT_RESET 0x20
#define FCP_CMND_TMF_LUN_RESET 0x10
#define FCP_CMND_TMF_CLEAR_TASK_SET 0x04
#define FCP_CMND_TMF_ABORT_TASK_SET 0x02
/*
* Basic CT IU Header
*
* Source: X3.288-199x Generic Services 2 Rev 5.3 (FC-GS-2) Section 4.3.1
*/
typedef struct {
uint8_t ct_revision;
uint8_t ct_in_id[3];
uint8_t ct_fcs_type;
uint8_t ct_fcs_subtype;
uint8_t ct_options;
uint8_t ct_reserved0;
uint16_t ct_cmd_resp;
uint16_t ct_bcnt_resid;
uint8_t ct_reserved1;
uint8_t ct_reason;
uint8_t ct_explanation;
uint8_t ct_vunique;
} ct_hdr_t;
#define CT_REVISION 1
#define CT_FC_TYPE_FC 0xFC
#define CT_FC_SUBTYPE_NS 0x02
/*
* RFT_ID Requet CT_IU
*
* Source: INCITS xxx-200x Generic Services- 5 Rev 8.5 Section 5.2.5.30
*/
typedef struct {
ct_hdr_t rftid_hdr;
uint8_t rftid_reserved;
uint8_t rftid_portid[3];
uint32_t rftid_fc4types[8];
} rft_id_t;
/* unconverted miscellany */
/*
* Basic FC Link Service defines
*/
/*
* These are in the R_CTL field.
*/
#define ABTS 0x81
#define BA_ACC 0x84 /* of ABORT SEQUENCE */
#define BA_RJT 0x85 /* of ABORT SEQUENCE */
/*
* Link Service Accept/Reject
*/
#define LS_ACC 0x8002
#define LS_RJT 0x8001
/*
* FC ELS Codes- bits 31-24 of the first payload word of an ELS frame.
*/
#define PLOGI 0x03
#define FLOGI 0x04
#define LOGO 0x05
#define ABTX 0x06
#define PRLI 0x20
#define PRLO 0x21
#define TPRLO 0x24
#define RNC 0x53
/*
* FC4 defines
*/
#define FC4_IP 5 /* ISO/EEC 8802-2 LLC/SNAP */
#define FC4_SCSI 8 /* SCSI-3 via Fibre Channel Protocol (FCP) */
#define FC4_FC_SVC 0x20 /* Fibre Channel Services */
#ifndef MSG_ABORT
#define MSG_ABORT 0x06
#endif
#ifndef MSG_BUS_DEV_RESET
#define MSG_BUS_DEV_RESET 0x0c
#endif
#ifndef MSG_ABORT_TAG
#define MSG_ABORT_TAG 0x0d
#endif
#ifndef MSG_CLEAR_QUEUE
#define MSG_CLEAR_QUEUE 0x0e
#endif
#ifndef MSG_REL_RECOVERY
#define MSG_REL_RECOVERY 0x10
#endif
#ifndef MSG_TERM_IO_PROC
#define MSG_TERM_IO_PROC 0x11
#endif
#ifndef MSG_LUN_RESET
#define MSG_LUN_RESET 0x17
#endif
#endif /* _ISP_STDS_H */

View File

@ -53,15 +53,17 @@ static const char atiocope[] =
"ATIO returned for lun %d because it was in the middle of Bus Device Reset "
"on bus %d";
static const char atior[] =
"ATIO returned on for lun %d on from IID %d because a Bus Reset occurred "
"on bus %d";
"ATIO returned on for lun %d on from loopid %d because a Bus Reset "
"occurred on bus %d";
static void isp_got_msg(ispsoftc_t *, in_entry_t *);
static void isp_got_msg_fc(ispsoftc_t *, in_fcentry_t *);
static void isp_got_tmf_24xx(ispsoftc_t *, at7_entry_t *);
static void isp_handle_atio(ispsoftc_t *, at_entry_t *);
static void isp_handle_atio2(ispsoftc_t *, at2_entry_t *);
static void isp_handle_ctio(ispsoftc_t *, ct_entry_t *);
static void isp_handle_ctio2(ispsoftc_t *, ct2_entry_t *);
static void isp_handle_ctio7(ispsoftc_t *, ct7_entry_t *);
/*
* The Qlogic driver gets an interrupt to look at response queue entries.
@ -110,42 +112,57 @@ static void isp_handle_ctio2(ispsoftc_t *, ct2_entry_t *);
*/
int
isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp)
isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp)
{
uint16_t status, seqid;
uint16_t status;
uint32_t seqid;
union {
at_entry_t *atiop;
at2_entry_t *at2iop;
at2e_entry_t *at2eiop;
at7_entry_t *at7iop;
ct_entry_t *ctiop;
ct2_entry_t *ct2iop;
ct2e_entry_t *ct2eiop;
ct7_entry_t *ct7iop;
lun_entry_t *lunenp;
in_entry_t *inotp;
in_fcentry_t *inot_fcp;
in_fcentry_e_t *inote_fcp;
in_fcentry_24xx_t *inot_24xx;
na_entry_t *nackp;
na_fcentry_t *nack_fcp;
na_fcentry_e_t *nacke_fcp;
na_fcentry_24xx_t *nack_24xx;
isphdr_t *hp;
abts_t *abts;
abts_rsp_t *abts_rsp;
els_t *els;
void * *vp;
#define atiop unp.atiop
#define at2iop unp.at2iop
#define at2eiop unp.at2eiop
#define at7iop unp.at7iop
#define ctiop unp.ctiop
#define ct2iop unp.ct2iop
#define ct2eiop unp.ct2eiop
#define ct7iop unp.ct7iop
#define lunenp unp.lunenp
#define inotp unp.inotp
#define inot_fcp unp.inot_fcp
#define inote_fcp unp.inote_fcp
#define inot_24xx unp.inot_24xx
#define nackp unp.nackp
#define nack_fcp unp.nack_fcp
#define nacke_fcp unp.nacke_fcp
#define nack_24xx unp.nack_24xx
#define abts unp.abts
#define abts_rsp unp.abts_rsp
#define els unp.els
#define hdrp unp.hp
} unp;
uint8_t local[QENTRY_LEN];
int bus, type, rval = 1;
int bus, type, level, rval = 1;
type = isp_get_response_type(isp, (isphdr_t *)vptr);
unp.vp = vptr;
@ -154,30 +171,72 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp)
switch(type) {
case RQSTYPE_ATIO:
isp_get_atio(isp, atiop, (at_entry_t *) local);
isp_handle_atio(isp, (at_entry_t *) local);
if (IS_24XX(isp)) {
int len;
isp_get_atio7(isp, at7iop, (at7_entry_t *) local);
at7iop = (at7_entry_t *) local;
/*
* Check for and do something with commands whose IULEN
* extends past a singel queue entry.
*/
len = at7iop->at_ta_len & 0xfffff;
if (len > (QENTRY_LEN - 8)) {
len -= (QENTRY_LEN - 8);
isp_prt(isp, ISP_LOGINFO,
"long IU length (%d) ignored", len);
while (len > 0) {
*optrp = ISP_NXT_QENTRY(*optrp,
RESULT_QUEUE_LEN(isp));
len -= QENTRY_LEN;
}
}
/*
* Check for a task management function
*/
if (at7iop->at_cmnd.fcp_cmnd_task_management) {
isp_got_tmf_24xx(isp, at7iop);
break;
}
/*
* Just go straight to outer layer for this one.
*/
(void) isp_async(isp, ISPASYNC_TARGET_ACTION, local);
} else {
isp_get_atio(isp, atiop, (at_entry_t *) local);
isp_handle_atio(isp, (at_entry_t *) local);
}
break;
case RQSTYPE_CTIO:
isp_get_ctio(isp, ctiop, (ct_entry_t *) local);
isp_handle_ctio(isp, (ct_entry_t *) local);
break;
case RQSTYPE_ATIO2:
if (IS_2KLOGIN(isp)) {
if (FCPARAM(isp)->isp_2klogin) {
isp_get_atio2e(isp, at2eiop, (at2e_entry_t *) local);
} else {
isp_get_atio2(isp, at2iop, (at2_entry_t *) local);
}
}
isp_handle_atio2(isp, (at2_entry_t *) local);
break;
case RQSTYPE_CTIO3:
case RQSTYPE_CTIO2:
if (IS_2KLOGIN(isp)) {
if (FCPARAM(isp)->isp_2klogin) {
isp_get_ctio2e(isp, ct2eiop, (ct2e_entry_t *) local);
} else {
isp_get_ctio2(isp, ct2iop, (ct2_entry_t *) local);
}
}
isp_handle_ctio2(isp, (ct2_entry_t *) local);
break;
case RQSTYPE_CTIO7:
isp_get_ctio7(isp, ct7iop, (ct7_entry_t *) local);
isp_handle_ctio7(isp, (ct7_entry_t *) local);
break;
case RQSTYPE_ENABLE_LUN:
case RQSTYPE_MODIFY_LUN:
isp_get_enable_lun(isp, lunenp, (lun_entry_t *) local);
@ -193,8 +252,36 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp)
* (we set this initially in the Enable Lun entry).
*/
bus = 0;
if (IS_FC(isp)) {
if (IS_2KLOGIN(isp)) {
if (IS_24XX(isp)) {
isp_get_notify_24xx(isp, inot_24xx,
(in_fcentry_24xx_t *)local);
inot_24xx = (in_fcentry_24xx_t *) local;
status = inot_24xx->in_status;
seqid = inot_24xx->in_rxid;
isp_prt(isp, ISP_LOGTDEBUG0,
"Immediate Notify status=0x%x seqid=0x%x",
status, seqid);
switch (status) {
case IN24XX_LIP_RESET:
case IN24XX_LINK_RESET:
case IN24XX_PORT_LOGOUT:
case IN24XX_PORT_CHANGED:
case IN24XX_LINK_FAILED:
case IN24XX_SRR_RCVD:
case IN24XX_ELS_RCVD:
(void) isp_async(isp, ISPASYNC_TARGET_ACTION,
&local);
break;
default:
isp_prt(isp, ISP_LOGINFO,
"isp_target_notify: unknown status (0x%x)",
status);
isp_notify_ack(isp, local);
break;
}
break;
} else if (IS_FC(isp)) {
if (FCPARAM(isp)->isp_2klogin) {
isp_get_notify_fc_e(isp, inote_fcp,
(in_fcentry_e_t *)local);
} else {
@ -229,12 +316,28 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp)
}
break;
case IN_RSRC_UNAVAIL:
isp_prt(isp, ISP_LOGWARN, "Firmware out of ATIOs");
isp_prt(isp, ISP_LOGINFO, "Firmware out of ATIOs");
isp_notify_ack(isp, local);
break;
case IN_RESET:
(void) isp_target_async(isp, 0, ASYNC_BUS_RESET);
{
/*
* We form the notify structure here because we need
* to mark it as needing a NOTIFY ACK on return.
*/
tmd_notify_t notify;
MEMZERO(&notify, sizeof (tmd_notify_t));
notify.nt_hba = isp;
notify.nt_iid = INI_ANY;
/* nt_tgt set in outer layers */
notify.nt_lun = LUN_ANY;
notify.nt_tagval = TAG_ANY;
notify.nt_ncode = NT_BUS_RESET;
notify.nt_need_ack = 1;
(void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
break;
}
case IN_PORT_LOGOUT:
case IN_ABORT_TASK:
case IN_PORT_CHANGED:
@ -242,8 +345,9 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp)
(void) isp_async(isp, ISPASYNC_TARGET_ACTION, &local);
break;
default:
isp_prt(isp, ISP_LOGERR,
"bad status (0x%x) in isp_target_notify", status);
isp_prt(isp, ISP_LOGINFO,
"isp_target_notify: unknown status (0x%x)",
status);
isp_notify_ack(isp, local);
break;
}
@ -254,26 +358,68 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp)
* The ISP is acknowledging our acknowledgement of an
* Immediate Notify entry for some asynchronous event.
*/
if (IS_FC(isp)) {
if (IS_2KLOGIN(isp)) {
if (IS_24XX(isp)) {
isp_get_notify_ack_24xx(isp, nack_24xx,
(na_fcentry_24xx_t *) local);
nack_24xx = (na_fcentry_24xx_t *) local;
if (nack_24xx->na_status != NA_OK) {
level = ISP_LOGINFO;
} else {
level = ISP_LOGTDEBUG1;
}
isp_prt(isp, level,
"Notify Ack Status=0x%x; Subcode 0x%x seqid=0x%x",
nack_24xx->na_status, nack_24xx->na_status_subcode,
nack_24xx->na_rxid);
} else if (IS_FC(isp)) {
if (FCPARAM(isp)->isp_2klogin) {
isp_get_notify_ack_fc_e(isp, nacke_fcp,
(na_fcentry_e_t *)local);
} else {
isp_get_notify_ack_fc(isp, nack_fcp,
(na_fcentry_t *)local);
}
}
nack_fcp = (na_fcentry_t *)local;
isp_prt(isp, ISP_LOGTDEBUG1,
"Notify Ack status=0x%x seqid 0x%x",
if (nack_fcp->na_status != NA_OK) {
level = ISP_LOGINFO;
} else {
level = ISP_LOGTDEBUG1;
}
isp_prt(isp, level,
"Notify Ack Status=0x%x seqid 0x%x",
nack_fcp->na_status, nack_fcp->na_seqid);
} else {
isp_get_notify_ack(isp, nackp, (na_entry_t *)local);
nackp = (na_entry_t *)local;
isp_prt(isp, ISP_LOGTDEBUG1,
if (nackp->na_status != NA_OK) {
level = ISP_LOGINFO;
} else {
level = ISP_LOGTDEBUG1;
}
isp_prt(isp, level,
"Notify Ack event 0x%x status=0x%x seqid 0x%x",
nackp->na_event, nackp->na_status, nackp->na_seqid);
}
break;
case RQSTYPE_ABTS_RCVD:
isp_get_abts(isp, abts, (abts_t *)local);
(void) isp_async(isp, ISPASYNC_TARGET_ACTION, &local);
break;
case RQSTYPE_ABTS_RSP:
isp_get_abts_rsp(isp, abts_rsp, (abts_rsp_t *)local);
abts_rsp = (abts_rsp_t *) local;
if (abts_rsp->abts_rsp_status) {
level = ISP_LOGINFO;
} else {
level = ISP_LOGTDEBUG0;
}
isp_prt(isp, level,
"ABTS RSP response[0x%x]: status=0x%x sub=(0x%x 0x%x)",
abts_rsp->abts_rsp_rxid_task, abts_rsp->abts_rsp_status,
abts_rsp->abts_rsp_payload.rsp.subcode1,
abts_rsp->abts_rsp_payload.rsp.subcode2);
break;
default:
isp_prt(isp, ISP_LOGERR,
"Unknown entry type 0x%x in isp_target_notify", type);
@ -283,16 +429,23 @@ isp_target_notify(ispsoftc_t *isp, void *vptr, uint16_t *optrp)
#undef atiop
#undef at2iop
#undef at2eiop
#undef at7iop
#undef ctiop
#undef ct2iop
#undef ct2eiop
#undef ct7iop
#undef lunenp
#undef inotp
#undef inot_fcp
#undef inote_fcp
#undef inot_24xx
#undef nackp
#undef nack_fcp
#undef nacke_fcp
#undef hack_24xx
#undef abts
#undef abts_rsp
#undef els
#undef hdrp
return (rval);
}
@ -312,7 +465,7 @@ isp_lun_cmd(ispsoftc_t *isp, int cmd, int bus, int tgt, int lun,
int cmd_cnt, int inot_cnt, uint32_t opaque)
{
lun_entry_t el;
uint16_t nxti, optr;
uint32_t nxti, optr;
void *outp;
@ -344,7 +497,7 @@ isp_lun_cmd(ispsoftc_t *isp, int cmd, int bus, int tgt, int lun,
if (IS_SCSI(isp)) {
el.le_tgt = tgt;
el.le_lun = lun;
} else if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) {
} else if (FCPARAM(isp)->isp_sccfw == 0) {
el.le_lun = lun;
}
@ -364,7 +517,7 @@ int
isp_target_put_entry(ispsoftc_t *isp, void *ap)
{
void *outp;
uint16_t nxti, optr;
uint32_t nxti, optr;
uint8_t etype = ((isphdr_t *) ap)->rqs_entry_type;
if (isp_getrqentry(isp, &nxti, &optr, &outp)) {
@ -377,28 +530,34 @@ isp_target_put_entry(ispsoftc_t *isp, void *ap)
isp_put_atio(isp, (at_entry_t *) ap, (at_entry_t *) outp);
break;
case RQSTYPE_ATIO2:
if (IS_2KLOGIN(isp)) {
isp_put_atio2e(isp, (at2e_entry_t *) ap, (at2e_entry_t *) outp);
} else {
isp_put_atio2(isp, (at2_entry_t *) ap, (at2_entry_t *) outp);
}
if (FCPARAM(isp)->isp_2klogin) {
isp_put_atio2e(isp, (at2e_entry_t *) ap,
(at2e_entry_t *) outp);
} else {
isp_put_atio2(isp, (at2_entry_t *) ap,
(at2_entry_t *) outp);
}
break;
case RQSTYPE_CTIO:
isp_put_ctio(isp, (ct_entry_t *) ap, (ct_entry_t *) outp);
break;
case RQSTYPE_CTIO2:
if (IS_2KLOGIN(isp)) {
isp_put_ctio2e(isp, (ct2e_entry_t *) ap, (ct2e_entry_t *) outp);
} else {
isp_put_ctio2(isp, (ct2_entry_t *) ap, (ct2_entry_t *) outp);
}
if (FCPARAM(isp)->isp_2klogin) {
isp_put_ctio2e(isp, (ct2e_entry_t *) ap,
(ct2e_entry_t *) outp);
} else {
isp_put_ctio2(isp, (ct2_entry_t *) ap,
(ct2_entry_t *) outp);
}
break;
case RQSTYPE_CTIO7:
isp_put_ctio7(isp, (ct7_entry_t *) ap, (ct7_entry_t *) outp);
break;
default:
isp_prt(isp, ISP_LOGERR,
"Unknown type 0x%x in isp_put_entry", etype);
return (-1);
}
ISP_TDQE(isp, "isp_target_put_entry", (int) optr, ap);
ISP_ADD_REQUEST(isp, nxti);
return (0);
@ -418,12 +577,12 @@ isp_target_put_atio(ispsoftc_t *isp, void *arg)
at2_entry_t *aep = arg;
atun._atio2.at_header.rqs_entry_type = RQSTYPE_ATIO2;
atun._atio2.at_header.rqs_entry_count = 1;
if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {
atun._atio2.at_scclun = (uint16_t) aep->at_scclun;
if (FCPARAM(isp)->isp_sccfw) {
atun._atio2.at_scclun = aep->at_scclun;
} else {
atun._atio2.at_lun = (uint8_t) aep->at_lun;
}
if (IS_2KLOGIN(isp)) {
if (FCPARAM(isp)->isp_2klogin) {
atun._atio2e.at_iid = ((at2e_entry_t *)aep)->at_iid;
} else {
atun._atio2.at_iid = aep->at_iid;
@ -465,28 +624,56 @@ isp_target_put_atio(ispsoftc_t *isp, void *arg)
*/
int
isp_endcmd(ispsoftc_t *isp, void *arg, uint32_t code, uint16_t hdl)
isp_endcmd(ispsoftc_t *isp, void *arg, uint32_t code, uint32_t hdl)
{
int sts;
union {
ct_entry_t _ctio;
ct2_entry_t _ctio2;
ct2e_entry_t _ctio2e;
ct7_entry_t _ctio7;
} un;
MEMZERO(&un, sizeof un);
sts = code & 0xff;
if (IS_FC(isp)) {
if (IS_24XX(isp)) {
at7_entry_t *aep = arg;
ct7_entry_t *cto = &un._ctio7;
cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
cto->ct_header.rqs_entry_count = 1;
/* XXXX */ cto->ct_nphdl = aep->at_hdr.seq_id;
cto->ct_rxid = aep->at_rxid;
cto->ct_iid_lo = (aep->at_hdr.s_id[1] << 8) |
aep->at_hdr.s_id[2];
cto->ct_iid_hi = aep->at_hdr.s_id[0];
cto->ct_oxid = aep->at_hdr.ox_id;
cto->ct_scsi_status = sts;
cto->ct_flags = CT7_FLAG_MODE1 | CT7_NO_DATA | CT7_SENDSTATUS;
if (sts == SCSI_CHECK && (code & ECMD_SVALID)) {
cto->rsp.m1.ct_resplen = 16;
cto->rsp.m1.ct_resp[0] = 0xf0;
cto->rsp.m1.ct_resp[2] = (code >> 12) & 0xf;
cto->rsp.m1.ct_resp[7] = 8;
cto->rsp.m1.ct_resp[12] = (code >> 24) & 0xff;
cto->rsp.m1.ct_resp[13] = (code >> 16) & 0xff;
}
if (aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl) {
cto->ct_resid = aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl;
cto->ct_scsi_status |= CT2_DATA_UNDER;
}
cto->ct_syshandle = hdl;
} else if (IS_FC(isp)) {
at2_entry_t *aep = arg;
ct2_entry_t *cto = &un._ctio2;
cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
cto->ct_header.rqs_entry_count = 1;
if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) {
if (FCPARAM(isp)->isp_sccfw == 0) {
cto->ct_lun = aep->at_lun;
}
if (IS_2KLOGIN(isp)) {
if (FCPARAM(isp)->isp_2klogin) {
un._ctio2e.ct_iid = ((at2e_entry_t *)aep)->at_iid;
} else {
cto->ct_iid = aep->at_iid;
@ -565,6 +752,7 @@ isp_target_async(ispsoftc_t *isp, int bus, int event)
notify.nt_ncode = NT_LINK_DOWN;
(void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &notify);
break;
case ASYNC_LIP_ERROR:
case ASYNC_LIP_F8:
case ASYNC_LIP_OCCURRED:
case ASYNC_LOOP_RESET:
@ -584,7 +772,13 @@ isp_target_async(ispsoftc_t *isp, int bus, int event)
{
uint8_t storage[QENTRY_LEN];
memset(storage, 0, QENTRY_LEN);
if (IS_FC(isp)) {
if (IS_24XX(isp)) {
ct7_entry_t *ct = (ct7_entry_t *) storage;
ct->ct_header.rqs_entry_type = RQSTYPE_CTIO7;
ct->ct_nphdl = CT7_OK;
ct->ct_syshandle = bus;
ct->ct_flags = CT7_SENDSTATUS|CT7_FASTPOST;
} else if (IS_FC(isp)) {
/* This should also suffice for 2K login code */
ct2_entry_t *ct = (ct2_entry_t *) storage;
ct->ct_header.rqs_entry_type = RQSTYPE_CTIO2;
@ -599,7 +793,7 @@ isp_target_async(ispsoftc_t *isp, int bus, int event)
ct->ct_flags = CT_SENDSTATUS;
}
(void) isp_async(isp, ISPASYNC_TARGET_ACTION, storage);
return (0);
break;
}
default:
isp_prt(isp, ISP_LOGERR,
@ -679,14 +873,14 @@ static void
isp_got_msg_fc(ispsoftc_t *isp, in_fcentry_t *inp)
{
tmd_notify_t nt;
static const char f1[] = "%s from loop id %d lun %d seq 0x%x";
static const char f1[] = "%s from N-port handle 0x%x lun %d seq 0x%x";
static const char f2[] =
"unknown %s 0x%x lun %d loop id %d task flags 0x%x seq 0x%x\n";
"unknown %s 0x%x lun %d N-Port handle 0x%x task flags 0x%x seq 0x%x\n";
uint16_t seqid, loopid;
MEMZERO(&nt, sizeof (tmd_notify_t));
nt.nt_hba = isp;
if (IS_2KLOGIN(isp)) {
if (FCPARAM(isp)->isp_2klogin) {
nt.nt_iid = ((in_fcentry_e_t *)inp)->in_iid;
loopid = ((in_fcentry_e_t *)inp)->in_iid;
seqid = ((in_fcentry_e_t *)inp)->in_seqid;
@ -696,12 +890,13 @@ isp_got_msg_fc(ispsoftc_t *isp, in_fcentry_t *inp)
seqid = inp->in_seqid;
}
/* nt_tgt set in outer layers */
if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {
if (FCPARAM(isp)->isp_sccfw) {
nt.nt_lun = inp->in_scclun;
} else {
nt.nt_lun = inp->in_lun;
}
IN_FC_MAKE_TAGID(nt.nt_tagval, 0, seqid);
nt.nt_need_ack = 1;
nt.nt_lreserved = inp;
if (inp->in_status != IN_MSG_RECEIVED) {
@ -741,11 +936,69 @@ isp_got_msg_fc(ispsoftc_t *isp, in_fcentry_t *inp)
(void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt);
}
static void
isp_got_tmf_24xx(ispsoftc_t *isp, at7_entry_t *aep)
{
tmd_notify_t nt;
static const char f1[] = "%s from PortID 0x%06x lun %d seq 0x%x";
static const char f2[] =
"unknown Task Flag 0x%x lun %d PortID 0x%x tag 0x%x\n";
uint32_t sid;
MEMZERO(&nt, sizeof (tmd_notify_t));
nt.nt_hba = isp;
nt.nt_iid = INI_ANY;
nt.nt_lun =
(aep->at_cmnd.fcp_cmnd_lun[0] << 8) |
(aep->at_cmnd.fcp_cmnd_lun[1]);
nt.nt_tagval = aep->at_rxid;
nt.nt_lreserved = aep;
sid =
(aep->at_hdr.s_id[0] << 16) |
(aep->at_hdr.s_id[1] << 8) |
(aep->at_hdr.s_id[2]);
if (aep->at_cmnd.fcp_cmnd_task_management &
FCP_CMND_TMF_ABORT_TASK_SET) {
isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET",
sid, nt.nt_lun, nt.nt_tagval);
nt.nt_ncode = NT_ABORT_TASK_SET;
} else if (aep->at_cmnd.fcp_cmnd_task_management &
FCP_CMND_TMF_CLEAR_TASK_SET) {
isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET",
sid, nt.nt_lun, nt.nt_tagval);
nt.nt_ncode = NT_CLEAR_TASK_SET;
} else if (aep->at_cmnd.fcp_cmnd_task_management &
FCP_CMND_TMF_LUN_RESET) {
isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET",
sid, nt.nt_lun, nt.nt_tagval);
nt.nt_ncode = NT_LUN_RESET;
} else if (aep->at_cmnd.fcp_cmnd_task_management &
FCP_CMND_TMF_TGT_RESET) {
isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET",
sid, nt.nt_lun, nt.nt_tagval);
nt.nt_ncode = NT_TARGET_RESET;
nt.nt_lun = LUN_ANY;
} else if (aep->at_cmnd.fcp_cmnd_task_management &
FCP_CMND_TMF_CLEAR_ACA) {
isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA",
sid, nt.nt_lun, nt.nt_tagval);
nt.nt_ncode = NT_CLEAR_ACA;
} else {
isp_prt(isp, ISP_LOGWARN, f2,
aep->at_cmnd.fcp_cmnd_task_management,
nt.nt_lun, sid, nt.nt_tagval);
isp_endcmd(isp, aep, 0, 0);
return;
}
(void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt);
}
void
isp_notify_ack(ispsoftc_t *isp, void *arg)
{
char storage[QENTRY_LEN];
uint16_t nxti, optr;
uint32_t nxti, optr;
void *outp;
if (isp_getrqentry(isp, &nxti, &optr, &outp)) {
@ -756,14 +1009,49 @@ isp_notify_ack(ispsoftc_t *isp, void *arg)
MEMZERO(storage, QENTRY_LEN);
if (IS_FC(isp)) {
if (IS_24XX(isp) && arg != NULL && (((isphdr_t *)arg)->rqs_entry_type == RQSTYPE_ATIO)) {
at7_entry_t *aep = arg;
isp_endcmd(isp, aep, 0, 0);
return;
} else if (IS_24XX(isp) && arg != NULL && (((isphdr_t *)arg)->rqs_entry_type == RQSTYPE_ABTS_RSP)) {
abts_rsp_t *abts_rsp = (abts_rsp_t *) storage;
/*
* The caller will have set response values as appropriate
* in the ABTS structure just before calling us.
*/
MEMCPY(abts_rsp, arg, QENTRY_LEN);
isp_put_abts_rsp(isp, abts_rsp, (abts_rsp_t *)outp);
} else if (IS_24XX(isp)) {
na_fcentry_24xx_t *na = (na_fcentry_24xx_t *) storage;
if (arg) {
in_fcentry_24xx_t *in = arg;
na->na_nphdl = in->in_nphdl;
na->na_status = in->in_status;
na->na_status_subcode = in->in_status_subcode;
na->na_rxid = in->in_rxid;
na->na_oxid = in->in_oxid;
if (in->in_status == IN24XX_SRR_RCVD) {
na->na_srr_rxid = in->in_srr_rxid;
na->na_srr_reloff_hi = in->in_srr_reloff_hi;
na->na_srr_reloff_lo = in->in_srr_reloff_lo;
na->na_srr_iu = in->in_srr_iu;
na->na_srr_flags = 1;
na->na_srr_reject_vunique = 0;
na->na_srr_reject_explanation = 1;
na->na_srr_reject_code = 1;
}
}
na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
na->na_header.rqs_entry_count = 1;
isp_put_notify_24xx_ack(isp, na, (na_fcentry_24xx_t *)outp);
} else if (IS_FC(isp)) {
na_fcentry_t *na = (na_fcentry_t *) storage;
int iid = 0;
if (arg) {
in_fcentry_t *inp = arg;
MEMCPY(storage, arg, sizeof (isphdr_t));
if (IS_2KLOGIN(isp)) {
if (FCPARAM(isp)->isp_2klogin) {
((na_fcentry_e_t *)na)->na_iid =
((in_fcentry_e_t *)inp)->in_iid;
iid = ((na_fcentry_e_t *)na)->na_iid;
@ -788,14 +1076,14 @@ isp_notify_ack(ispsoftc_t *isp, void *arg)
}
na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
na->na_header.rqs_entry_count = 1;
if (IS_2KLOGIN(isp)) {
if (FCPARAM(isp)->isp_2klogin) {
isp_put_notify_ack_fc_e(isp, (na_fcentry_e_t *) na,
(na_fcentry_e_t *)outp);
} else {
isp_put_notify_ack_fc(isp, na, (na_fcentry_t *)outp);
}
isp_prt(isp, ISP_LOGTDEBUG0, "notify ack iid %u seqid %x flags "
"%x tflags %x response %x", iid, na->na_seqid,
isp_prt(isp, ISP_LOGTDEBUG0, "notify ack loopid %u seqid %x "
"flags %x tflags %x response %x", iid, na->na_seqid,
na->na_flags, na->na_task_flags, na->na_response);
} else {
na_entry_t *na = (na_entry_t *) storage;
@ -815,8 +1103,8 @@ isp_notify_ack(ispsoftc_t *isp, void *arg)
na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK;
na->na_header.rqs_entry_count = 1;
isp_put_notify_ack(isp, na, (na_entry_t *)outp);
isp_prt(isp, ISP_LOGTDEBUG0, "notify ack iid %u lun %u tgt %u "
"seqid %x event %x", na->na_iid, na->na_lun, na->na_tgt,
isp_prt(isp, ISP_LOGTDEBUG0, "notify ack loopid %u lun %u tgt "
"%u seqid %x event %x", na->na_iid, na->na_lun, na->na_tgt,
na->na_seqid, na->na_event);
}
ISP_TDQE(isp, "isp_notify_ack", (int) optr, storage);
@ -897,7 +1185,7 @@ isp_handle_atio(ispsoftc_t *isp, at_entry_t *aep)
default:
isp_prt(isp, ISP_LOGERR,
"Unknown ATIO status 0x%x from initiator %d for lun %d",
"Unknown ATIO status 0x%x from loopid %d for lun %d",
aep->at_status, aep->at_iid, lun);
(void) isp_target_put_atio(isp, aep);
break;
@ -909,13 +1197,13 @@ isp_handle_atio2(ispsoftc_t *isp, at2_entry_t *aep)
{
int lun, iid;
if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) {
if (FCPARAM(isp)->isp_sccfw) {
lun = aep->at_scclun;
} else {
lun = aep->at_lun;
}
if (IS_2KLOGIN(isp)) {
if (FCPARAM(isp)->isp_2klogin) {
iid = ((at2e_entry_t *)aep)->at_iid;
} else {
iid = aep->at_iid;
@ -986,7 +1274,7 @@ isp_handle_atio2(ispsoftc_t *isp, at2_entry_t *aep)
default:
isp_prt(isp, ISP_LOGERR,
"Unknown ATIO2 status 0x%x from initiator %d for lun %d",
"Unknown ATIO2 status 0x%x from loopid %d for lun %d",
aep->at_status, iid, lun);
(void) isp_target_put_atio(isp, aep);
break;
@ -1002,8 +1290,9 @@ isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct)
if (ct->ct_syshandle) {
xs = isp_find_xs_tgt(isp, ct->ct_syshandle);
if (xs == NULL)
if (xs == NULL) {
pl = ISP_LOGALL;
}
} else {
xs = NULL;
}
@ -1055,7 +1344,7 @@ isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct)
if (fmsg == NULL)
fmsg = "ABORT TAG message sent by Initiator";
isp_prt(isp, ISP_LOGWARN, "CTIO destroyed by %s", fmsg);
isp_prt(isp, ISP_LOGTDEBUG0, "CTIO destroyed by %s", fmsg);
break;
case CT_INVAL:
@ -1156,14 +1445,15 @@ isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct)
static void
isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct)
{
XS_T *xs;
void *xs;
int pl = ISP_LOGTDEBUG2;
char *fmsg = NULL;
if (ct->ct_syshandle) {
xs = isp_find_xs_tgt(isp, ct->ct_syshandle);
if (xs == NULL)
if (xs == NULL) {
pl = ISP_LOGALL;
}
} else {
xs = NULL;
}
@ -1193,7 +1483,7 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct)
* status. These CTIOs are handled in that same way as
* CT_ABORTED ones, so just fall through here.
*/
fmsg = "TARGET RESET Task Management Function Received";
fmsg = "TARGET RESET";
/*FALLTHROUGH*/
case CT_RESET:
if (fmsg == NULL)
@ -1205,11 +1495,12 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct)
* Bus Free and returns all outstanding CTIOs with the status
* set, then sends us an Immediate Notify entry.
*/
if (fmsg == NULL)
fmsg = "ABORT Task Management Function Received";
if (fmsg == NULL) {
fmsg = "ABORT";
}
isp_prt(isp, ISP_LOGERR, "CTIO2 destroyed by %s: RX_ID=0x%x",
fmsg, ct->ct_rxid);
isp_prt(isp, ISP_LOGTDEBUG0,
"CTIO2 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid);
break;
case CT_INVAL:
@ -1235,7 +1526,7 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct)
if (fmsg == NULL)
fmsg = "Port Logout";
/*FALLTHROUGH*/
case CT_PORTNOTAVAIL:
case CT_PORTUNAVAIL:
if (fmsg == NULL)
fmsg = "Port not available";
/*FALLTHROUGH*/
@ -1246,7 +1537,7 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct)
case CT_NOACK:
if (fmsg == NULL)
fmsg = "unacknowledged Immediate Notify pending";
isp_prt(isp, ISP_LOGERR, "CTIO returned by f/w- %s", fmsg);
isp_prt(isp, ISP_LOGWARN, "CTIO returned by f/w- %s", fmsg);
break;
case CT_INVRXID:
@ -1254,7 +1545,7 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct)
* CTIO rejected by the firmware because an invalid RX_ID.
* Just print a message.
*/
isp_prt(isp, ISP_LOGERR,
isp_prt(isp, ISP_LOGWARN,
"CTIO2 completed with Invalid RX_ID 0x%x", ct->ct_rxid);
break;
@ -1312,4 +1603,157 @@ isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct)
*/
}
}
static void
isp_handle_ctio7(ispsoftc_t *isp, ct7_entry_t *ct)
{
void *xs;
int pl = ISP_LOGTDEBUG2;
char *fmsg = NULL;
if (ct->ct_syshandle) {
xs = isp_find_xs_tgt(isp, ct->ct_syshandle);
if (xs == NULL) {
pl = ISP_LOGALL;
}
} else {
xs = NULL;
}
switch(ct->ct_nphdl) {
case CT7_BUS_ERROR:
isp_prt(isp, ISP_LOGERR, "PCI DMA Bus Error");
/* FALL Through */
case CT7_DATA_OVER:
case CT7_DATA_UNDER:
case CT7_OK:
/*
* There are generally 2 possibilities as to why we'd get
* this condition:
* We sent or received data.
* We sent status & command complete.
*/
break;
case CT7_RESET:
if (fmsg == NULL) {
fmsg = "LIP Reset";
}
/*FALLTHROUGH*/
case CT7_ABORTED:
/*
* When an Abort message is received the firmware goes to
* Bus Free and returns all outstanding CTIOs with the status
* set, then sends us an Immediate Notify entry.
*/
if (fmsg == NULL) {
fmsg = "ABORT";
}
isp_prt(isp, ISP_LOGTDEBUG0,
"CTIO7 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid);
break;
case CT7_TIMEOUT:
if (fmsg == NULL) {
fmsg = "command";
}
isp_prt(isp, ISP_LOGERR, "Firmware timed out on %s", fmsg);
break;
case CT7_ERR:
fmsg = "Completed with Error";
/*FALLTHROUGH*/
case CT7_LOGOUT:
if (fmsg == NULL) {
fmsg = "Port Logout";
}
/*FALLTHROUGH*/
case CT7_PORTUNAVAIL:
if (fmsg == NULL) {
fmsg = "Port not available";
}
/*FALLTHROUGH*/
case CT7_PORTCHANGED:
if (fmsg == NULL) {
fmsg = "Port Changed";
}
isp_prt(isp, ISP_LOGWARN, "CTIO returned by f/w- %s", fmsg);
break;
case CT7_INVRXID:
/*
* CTIO rejected by the firmware because an invalid RX_ID.
* Just print a message.
*/
isp_prt(isp, ISP_LOGWARN,
"CTIO7 completed with Invalid RX_ID 0x%x", ct->ct_rxid);
break;
case CT7_REASSY_ERR:
isp_prt(isp, ISP_LOGWARN, "reassembly error");
break;
case CT7_SRR:
isp_prt(isp, ISP_LOGWARN, "SRR received");
break;
default:
isp_prt(isp, ISP_LOGERR, "Unknown CTIO7 status 0x%x",
ct->ct_nphdl);
break;
}
if (xs == NULL) {
/*
* There may be more than one CTIO for a data transfer,
* or this may be a status CTIO we're not monitoring.
*
* The assumption is that they'll all be returned in the
* order we got them.
*/
if (ct->ct_syshandle == 0) {
if (ct->ct_flags & CT7_TERMINATE) {
isp_prt(isp, ISP_LOGINFO,
"termination of 0x%x complete",
ct->ct_rxid);
} else if ((ct->ct_flags & CT7_SENDSTATUS) == 0) {
isp_prt(isp, pl,
"intermediate CTIO completed ok");
} else {
isp_prt(isp, pl,
"unmonitored CTIO completed ok");
}
} else {
isp_prt(isp, pl,
"NO xs for CTIO (handle 0x%x) status 0x%x",
ct->ct_syshandle, ct->ct_nphdl);
}
} else {
if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) {
ISP_DMAFREE(isp, xs, ct->ct_syshandle);
}
if (ct->ct_flags & CT2_SENDSTATUS) {
/*
* Sent status and command complete.
*
* We're now really done with this command, so we
* punt to the platform dependent layers because
* only there can we do the appropriate command
* complete thread synchronization.
*/
isp_prt(isp, pl, "status CTIO complete");
} else {
/*
* Final CTIO completed. Release DMA resources and
* notify platform dependent layers.
*/
isp_prt(isp, pl, "data CTIO complete");
}
(void) isp_async(isp, ISPASYNC_TARGET_ACTION, ct);
/*
* The platform layer will destroy the handle if appropriate.
*/
}
}
#endif

View File

@ -155,28 +155,48 @@ typedef struct {
#define TASK_FLAGS_CLEAR_TASK_SET (1<<10)
#define TASK_FLAGS_ABORT_TASK_SET (1<<9)
#ifndef MSG_ABORT
#define MSG_ABORT 0x06
#endif
#ifndef MSG_BUS_DEV_RESET
#define MSG_BUS_DEV_RESET 0x0c
#endif
#ifndef MSG_ABORT_TAG
#define MSG_ABORT_TAG 0x0d
#endif
#ifndef MSG_CLEAR_QUEUE
#define MSG_CLEAR_QUEUE 0x0e
#endif
#ifndef MSG_REL_RECOVERY
#define MSG_REL_RECOVERY 0x10
#endif
#ifndef MSG_TERM_IO_PROC
#define MSG_TERM_IO_PROC 0x11
#endif
#ifndef MSG_LUN_RESET
#define MSG_LUN_RESET 0x17
#endif
/*
* ISP24XX Immediate Notify
*/
typedef struct {
isphdr_t in_header;
uint32_t in_reserved;
uint16_t in_nphdl;
uint16_t in_reserved1;
uint16_t in_flags;
uint16_t in_srr_rxid;
uint16_t in_status;
uint8_t in_status_subcode;
uint8_t in_reserved2;
uint32_t in_rxid;
uint16_t in_srr_reloff_lo;
uint16_t in_srr_reloff_hi;
uint16_t in_srr_iu;
uint16_t in_srr_oxid;
uint8_t in_reserved3[18];
uint8_t in_reserved4;
uint8_t in_vpindex;
uint32_t in_reserved5;
uint16_t in_portid_lo;
uint8_t in_portid_hi;
uint8_t in_reserved6;
uint16_t in_reserved7;
uint16_t in_oxid;
} in_fcentry_24xx_t;
#define IN24XX_FLAG_PUREX_IOCB 0x1
#define IN24XX_FLAG_GLOBAL_LOGOUT 0x2
#define IN24XX_LIP_RESET 0x0E
#define IN24XX_LINK_RESET 0x0F
#define IN24XX_PORT_LOGOUT 0x29
#define IN24XX_PORT_CHANGED 0x2A
#define IN24XX_LINK_FAILED 0x2E
#define IN24XX_SRR_RCVD 0x45
#define IN24XX_ELS_RCVD 0x46 /*
* login-affectin ELS received- check
* subcode for specific opcode
*/
/*
* Notify Acknowledge Entry structure
*/
@ -234,6 +254,36 @@ typedef struct {
#define NAFC_RST_CLRD 0x20 /* Clear LIP Reset */
#define NAFC_TVALID 0x10 /* task mangement response code is valid */
/*
* ISP24XX Notify Acknowledge
*/
typedef struct {
isphdr_t na_header;
uint32_t na_handle;
uint16_t na_nphdl;
uint16_t na_reserved1;
uint16_t na_flags;
uint16_t na_srr_rxid;
uint16_t na_status;
uint8_t na_status_subcode;
uint8_t na_reserved2;
uint32_t na_rxid;
uint16_t na_srr_reloff_lo;
uint16_t na_srr_reloff_hi;
uint16_t na_srr_iu;
uint16_t na_srr_flags;
uint8_t na_reserved3[18];
uint8_t na_reserved4;
uint8_t na_vpindex;
uint8_t na_srr_reject_vunique;
uint8_t na_srr_reject_explanation;
uint8_t na_srr_reject_code;
uint8_t na_reserved5;
uint8_t na_reserved6[6];
uint16_t na_oxid;
} na_fcentry_24xx_t;
/*
* Accept Target I/O Entry structure
*/
@ -399,6 +449,32 @@ typedef struct {
tid &= ~0xffff; \
tid |= (inst << 16)
/*
* 24XX ATIO Definition
*
* This is *quite* different from other entry types.
* First of all, it has its own queue it comes in on.
*
* Secondly, it doesn't have a normal header.
*
* Thirdly, it's just a passthru of the FCP CMND IU
* which is recorded in big endian mode.
*/
typedef struct {
uint8_t at_type;
uint8_t at_count;
/*
* Task attribute in high four bits,
* the rest is the FCP CMND IU Length.
* NB: the command can extend past the
* length for a single queue entry.
*/
uint16_t at_ta_len;
uint32_t at_rxid;
fc_hdr_t at_hdr;
fcp_cmnd_iu_t at_cmnd;
} at7_entry_t;
/*
* Continue Target I/O Entry structure
@ -409,8 +485,7 @@ typedef struct {
*/
typedef struct {
isphdr_t ct_header;
uint16_t ct_reserved;
#define ct_syshandle ct_reserved /* we use this */
uint16_t ct_syshandle;
uint16_t ct_fwhandle; /* required by f/w */
uint8_t ct_lun; /* lun */
uint8_t ct_iid; /* initiator id */
@ -425,14 +500,7 @@ typedef struct {
uint32_t ct_resid; /* residual length */
uint16_t ct_timeout;
uint16_t ct_seg_count;
/*
* This is so we can share tag name space with
* CTIO{2,3,4} with the minimum of pain.
*/
union {
ispds_t ct_a[ISP_RQDSEG];
} _u;
#define ct_dataseg _u.ct_a
ispds_t ct_dataseg[ISP_RQDSEG];
} ct_entry_t;
/*
@ -481,10 +549,10 @@ typedef struct {
#define CT_BUS_ERROR 0x10 /* (FC Only) DMA PCI Error */
#define CT_PANIC 0x13 /* Unrecoverable Error */
#define CT_PHASE_ERROR 0x14 /* Bus phase sequence error */
#define CT_BDR_MSG 0x17 /* Bus Device Reset msg received */
#define CT_DATA_UNDER 0x15 /* (FC only) Data Underrun */
#define CT_BDR_MSG 0x17 /* Bus Device Reset msg received */
#define CT_TERMINATED 0x19 /* due to Terminate Transfer mbox cmd */
#define CT_PORTNOTAVAIL 0x28 /* port not available */
#define CT_PORTUNAVAIL 0x28 /* port not available */
#define CT_LOGOUT 0x29 /* port logout */
#define CT_PORTCHANGED 0x2A /* port changed */
#define CT_IDE 0x33 /* Initiator Detected Error */
@ -513,8 +581,7 @@ typedef struct {
#define MAXRESPLEN 26
typedef struct {
isphdr_t ct_header;
uint16_t ct_reserved;
uint16_t ct_fwhandle; /* just to match CTIO */
uint32_t ct_syshandle;
uint8_t ct_lun; /* lun */
uint8_t ct_iid; /* initiator id */
uint16_t ct_rxid; /* response ID */
@ -544,13 +611,10 @@ typedef struct {
uint16_t ct_scsi_status;
uint32_t ct_xfrlen;
union {
ispds_t ct_a[ISP_RQDSEG_T2]; /* CTIO2 */
ispds64_t ct_b[ISP_RQDSEG_T3]; /* CTIO3 */
ispdslist_t ct_c; /* CTIO4 */
} _u;
#define ct_dataseg _u.ct_a
#define ct_dataseg64 _u.ct_b
#define ct_dslist _u.ct_c
ispds_t ct_dataseg[ISP_RQDSEG_T2];
ispds64_t ct_dataseg64[ISP_RQDSEG_T3];
ispdslist_t ct_dslist;
} u;
} m0;
struct {
uint16_t _reserved;
@ -572,8 +636,7 @@ typedef struct {
typedef struct {
isphdr_t ct_header;
uint16_t ct_reserved;
uint16_t ct_fwhandle; /* just to match CTIO */
uint32_t ct_syshandle;
uint16_t ct_iid; /* initiator id */
uint16_t ct_rxid; /* response ID */
uint16_t ct_flags;
@ -589,10 +652,10 @@ typedef struct {
uint16_t ct_scsi_status;
uint32_t ct_xfrlen;
union {
ispds_t ct_a[ISP_RQDSEG_T2]; /* CTIO2 */
ispds64_t ct_b[ISP_RQDSEG_T3]; /* CTIO3 */
ispdslist_t ct_c; /* CTIO4 */
} _u;
ispds_t ct_dataseg[ISP_RQDSEG_T2];
ispds64_t ct_dataseg64[ISP_RQDSEG_T3];
ispdslist_t ct_dslist;
} u;
} m0;
struct {
uint16_t _reserved;
@ -615,16 +678,17 @@ typedef struct {
/*
* ct_flags values for CTIO2
*/
#define CT2_FLAG_MMASK 0x0003
#define CT2_FLAG_MODE0 0x0000
#define CT2_FLAG_MODE1 0x0001
#define CT2_FLAG_MODE2 0x0002
#define CT2_DATA_IN CT_DATA_IN
#define CT2_DATA_OUT CT_DATA_OUT
#define CT2_NO_DATA CT_NO_DATA
#define CT2_DATAMASK CT_DATAMASK
#define CT2_FLAG_MMASK 0x0003
#define CT2_DATA_IN 0x0040
#define CT2_DATA_OUT 0x0080
#define CT2_NO_DATA 0x00C0
#define CT2_DATAMASK 0x00C0
#define CT2_CCINCR 0x0100
#define CT2_FASTPOST 0x0200
#define CT2_CONFIRM 0x2000
#define CT2_TERMINATE 0x4000
#define CT2_SENDSTATUS 0x8000
@ -642,6 +706,183 @@ typedef struct {
#define CT2_DATA_OVER 0x0400
#define CT2_DATA_UNDER 0x0800
/*
* ISP24XX CTIO
*/
#define MAXRESPLEN_24XX 24
typedef struct {
isphdr_t ct_header;
uint32_t ct_syshandle;
uint16_t ct_nphdl; /* status on returned CTIOs */
uint16_t ct_timeout;
uint16_t ct_seg_count;
uint8_t ct_vpindex;
uint8_t ct_xflags;
uint16_t ct_iid_lo; /* low 16 bits of portid */
uint8_t ct_iid_hi; /* hi 8 bits of portid */
uint8_t ct_reserved;
uint32_t ct_rxid;
uint16_t ct_senselen; /* mode 0 only */
uint16_t ct_flags;
int32_t ct_resid; /* residual length */
uint16_t ct_oxid;
uint16_t ct_scsi_status; /* modes 0 && 1 only */
union {
struct {
uint32_t reloff;
uint32_t reserved0;
uint32_t ct_xfrlen;
uint32_t reserved1;
ispds64_t ds;
} m0;
struct {
uint16_t ct_resplen;
uint16_t reserved;
uint8_t ct_resp[MAXRESPLEN_24XX];
} m1;
struct {
uint32_t reserved0;
uint32_t ct_datalen;
uint32_t reserved1;
ispds64_t ct_fcp_rsp_iudata;
} m2;
} rsp;
} ct7_entry_t;
/*
* ct_flags values for CTIO7
*/
#define CT7_DATA_IN 0x0002
#define CT7_DATA_OUT 0x0001
#define CT7_NO_DATA 0x0000
#define CT7_DATAMASK 0x003
#define CT7_DSD_ENABLE 0x0004
#define CT7_CONF_STSFD 0x0010
#define CT7_EXPLCT_CONF 0x0020
#define CT7_FLAG_MODE0 0x0000
#define CT7_FLAG_MODE1 0x0040
#define CT7_FLAG_MODE7 0x0080
#define CT7_FLAG_MMASK 0x00C0
#define CT7_FASTPOST 0x0100
#define CT7_ATTR_MASK 0x1e00 /* task attributes from atio7 */
#define CT7_CONFIRM 0x2000
#define CT7_TERMINATE 0x4000
#define CT7_SENDSTATUS 0x8000
/*
* Type 7 CTIO status codes
*/
#define CT7_OK 0x01 /* completed without error */
#define CT7_ABORTED 0x02 /* aborted by host */
#define CT7_ERR 0x04 /* see sense data for error */
#define CT7_INVAL 0x06 /* request for disabled lun */
#define CT7_INVRXID 0x08 /* (FC only) Invalid RX_ID */
#define CT7_DATA_OVER 0x09 /* (FC only) Data Overrun */
#define CT7_TIMEOUT 0x0B /* timed out */
#define CT7_RESET 0x0E /* LIP Rset Received */
#define CT7_BUS_ERROR 0x10 /* DMA PCI Error */
#define CT7_REASSY_ERR 0x11 /* DMA reassembly error */
#define CT7_DATA_UNDER 0x15 /* (FC only) Data Underrun */
#define CT7_PORTUNAVAIL 0x28 /* port not available */
#define CT7_LOGOUT 0x29 /* port logout */
#define CT7_PORTCHANGED 0x2A /* port changed */
#define CT7_SRR 0x45 /* SRR Received */
/*
* Other 24XX related target IOCBs
*/
/*
* ABTS Received
*/
typedef struct {
isphdr_t abts_header;
uint8_t abts_reserved0[6];
uint16_t abts_nphdl;
uint16_t abts_reserved1;
uint16_t abts_sof;
uint32_t abts_rxid_abts;
uint16_t abts_did_lo;
uint8_t abts_did_hi;
uint8_t abts_r_ctl;
uint16_t abts_sid_lo;
uint8_t abts_sid_hi;
uint8_t abts_cs_ctl;
uint16_t abts_fs_ctl;
uint8_t abts_f_ctl;
uint8_t abts_type;
uint16_t abts_seq_cnt;
uint8_t abts_df_ctl;
uint8_t abts_seq_id;
uint16_t abts_rx_id;
uint16_t abts_ox_id;
uint32_t abts_param;
uint8_t abts_reserved2[16];
uint32_t abts_rxid_task;
} abts_t;
typedef struct {
isphdr_t abts_rsp_header;
uint32_t abts_rsp_handle;
uint16_t abts_rsp_status;
uint16_t abts_rsp_nphdl;
uint16_t abts_rsp_ctl_flags;
uint16_t abts_rsp_sof;
uint32_t abts_rsp_rxid_abts;
uint16_t abts_rsp_did_lo;
uint8_t abts_rsp_did_hi;
uint8_t abts_rsp_r_ctl;
uint16_t abts_rsp_sid_lo;
uint8_t abts_rsp_sid_hi;
uint8_t abts_rsp_cs_ctl;
uint16_t abts_rsp_f_ctl_lo;
uint8_t abts_rsp_f_ctl_hi;
uint8_t abts_rsp_type;
uint16_t abts_rsp_seq_cnt;
uint8_t abts_rsp_df_ctl;
uint8_t abts_rsp_seq_id;
uint16_t abts_rsp_rx_id;
uint16_t abts_rsp_ox_id;
uint32_t abts_rsp_param;
union {
struct {
uint16_t reserved;
uint8_t last_seq_id;
uint8_t seq_id_valid;
uint16_t aborted_rx_id;
uint16_t aborted_ox_id;
uint16_t high_seq_cnt;
uint16_t low_seq_cnt;
uint8_t reserved2[4];
} ba_acc;
struct {
uint8_t vendor_unique;
uint8_t explanation;
uint8_t reason;
uint8_t reserved;
uint8_t reserved2[12];
} ba_rjt;
struct {
uint8_t reserved[8];
uint32_t subcode1;
uint32_t subcode2;
} rsp;
uint8_t reserved[16];
} abts_rsp_payload;
uint32_t abts_rsp_rxid_task;
} abts_rsp_t;
/* terminate this ABTS exchange */
#define ISP24XX_ABTS_RSP_TERMINATE 0x01
#define ISP24XX_ABTS_RSP_COMPLETE 0x00
#define ISP24XX_ABTS_RSP_RESET 0x04
#define ISP24XX_ABTS_RSP_ABORTED 0x05
#define ISP24XX_ABTS_RSP_TIMEOUT 0x06
#define ISP24XX_ABTS_RSP_INVXID 0x08
#define ISP24XX_ABTS_RSP_LOGOUT 0x29
#define ISP24XX_ABTS_RSP_SUBCODE 0x31
/*
* Debug macros
*/
@ -649,6 +890,7 @@ typedef struct {
#define ISP_TDQE(isp, msg, idx, arg) \
if (isp->isp_dblev & ISP_LOGTDEBUG2) isp_print_qentry(isp, msg, idx, arg)
#ifndef ISP_TOOLS
/*
* The functions below are for the publicly available
* target mode functions that are internal to the Qlogic driver.
@ -657,7 +899,7 @@ typedef struct {
/*
* This function handles new response queue entry appropriate for target mode.
*/
int isp_target_notify(ispsoftc_t *, void *, uint16_t *);
int isp_target_notify(ispsoftc_t *, void *, uint32_t *);
/*
* This function externalizes the ability to acknowledge an Immediate Notify
@ -690,7 +932,7 @@ int isp_target_put_atio(ispsoftc_t *, void *);
* General routine to send a final CTIO for a command- used mostly for
* local responses.
*/
int isp_endcmd(ispsoftc_t *, void *, uint32_t, uint16_t);
int isp_endcmd(ispsoftc_t *, void *, uint32_t, uint32_t);
#define ECMD_SVALID 0x100
/*
@ -699,5 +941,5 @@ int isp_endcmd(ispsoftc_t *, void *, uint32_t, uint16_t);
* Return nonzero if the interrupt that generated this event has been dismissed.
*/
int isp_target_async(ispsoftc_t *, int, int);
#endif
#endif /* _ISP_TARGET_H */

View File

@ -71,14 +71,29 @@ typedef enum {
* in, and the external module to call back with a QIN_HBA_REG that
* passes back the corresponding information.
*/
#define QR_VERSION 10
#define QR_VERSION 13
typedef struct {
void * r_identity;
void (*r_action)(qact_e, void *);
char r_name[8];
int r_inst;
int r_version;
enum { R_FC, R_SCSI } r_type;
struct {
enum {
R_FC,
R_SCSI
} r_type;
union {
struct {
uint64_t r_wwnn;
uint64_t r_wwpn;
} fc;
struct {
int r_iid;
} scsi;
} r_id;
} r_info;
void * r_private;
} hba_register_t;
/*
@ -104,7 +119,8 @@ typedef struct tmd_notify {
uint64_t nt_iid; /* inititator id */
uint64_t nt_tgt; /* target id */
uint16_t nt_lun; /* logical unit */
uint16_t nt_padding; /* padding */
uint16_t : 15,
nt_need_ack : 1; /* this notify needs an ACK */
uint32_t nt_tagval; /* tag value */
tmd_ncode_t nt_ncode; /* action */
void * nt_lreserved;
@ -251,7 +267,7 @@ typedef struct {
#define TMD_SENSELEN 18
#endif
#ifndef QCDS
#define QCDS 8
#define QCDS (sizeof (void *))
#endif
typedef struct tmd_cmd {
@ -279,7 +295,7 @@ typedef struct tmd_cmd {
uint32_t longs[QCDS / sizeof (uint32_t)];
uint16_t shorts[QCDS / sizeof (uint16_t)];
uint8_t bytes[QCDS];
} cd_lreserved[3], cd_hreserved[3];
} cd_lreserved[4], cd_hreserved[4];
} tmd_cmd_t;
/* defined tags */

View File

@ -44,7 +44,7 @@
#define MBOX_ABOUT_FIRMWARE 0x0008
/* 9 */
/* a */
/* b */
#define MBOX_LOAD_RISC_RAM 0x000b
/* c */
#define MBOX_WRITE_RAM_WORD_EXTENDED 0x000d
#define MBOX_CHECK_FIRMWARE 0x000e
@ -123,6 +123,7 @@
#define MBOX_GET_FIRMWARE_OPTIONS 0x0028
#define MBOX_SET_FIRMWARE_OPTIONS 0x0038
#define MBOX_GET_RESOURCE_COUNT 0x0042
#define MBOX_REQUEST_OFFLINE_MODE 0x0043
#define MBOX_ENHANCED_GET_PDB 0x0047
#define MBOX_EXEC_COMMAND_IOCB_A64 0x0054
#define MBOX_INIT_FIRMWARE 0x0060
@ -148,12 +149,14 @@
#define MBOX_DRIVER_HEARTBEAT 0x005B
#define MBOX_FW_HEARTBEAT 0x005C
#define MBOX_GET_SET_DATA_RATE 0x005D /* 23XX only */
#define MBGSD_GET_RATE 0
#define MBGSD_SET_RATE 1
#define MBOX_GET_SET_DATA_RATE 0x005D /* 24XX/23XX only */
#define MBGSD_GET_RATE 0
#define MBGSD_SET_RATE 1
#define MBGSD_SET_RATE_NOW 2 /* 24XX only */
#define MBGSD_ONEGB 0
#define MBGSD_TWOGB 1
#define MBGSD_AUTO 2
#define MBGSD_FOURGB 3 /* 24XX only */
#define ISP2100_SET_PCI_PARAM 0x00ff
@ -173,6 +176,10 @@
#define MBOX_LOOP_ID_USED 0x4008
#define MBOX_ALL_IDS_USED 0x4009
#define MBOX_NOT_LOGGED_IN 0x400A
/* pseudo mailbox completion codes */
#define MBOX_REGS_BUSY 0x6000 /* registers in use */
#define MBOX_TIMEOUT 0x6001 /* command timed out */
#define MBLOGALL 0x000f
#define MBLOGNONE 0x0000
#define MBLOGMASK(x) ((x) & 0xf)
@ -199,6 +206,8 @@
#define ASYNC_PDB_CHANGED 0x8014
#define ASYNC_CHANGE_NOTIFY 0x8015
#define ASYNC_LIP_F8 0x8016
#define ASYNC_LIP_ERROR 0x8017
#define ASYNC_SECURITY_UPDATE 0x801B
#define ASYNC_CMD_CMPLT 0x8020
#define ASYNC_CTIO_DONE 0x8021
#define ASYNC_IP_XMIT_DONE 0x8022
@ -221,6 +230,8 @@
#define ISP_CONN_LOOPBACK 5
#define ASYNC_RIO_RESP 0x8040
#define ASYNC_RIO_COMP 0x8042
#define ASYNC_RCV_ERR 0x8048
/*
* 2.01.31 2200 Only. Need Bit 13 in Mailbox 1 for Set Firmware Options
* mailbox command to enable this.
@ -228,20 +239,14 @@
#define ASYNC_QFULL_SENT 0x8049
/*
* Mailbox Usages
* 24XX only
*/
#define ASYNC_RJT_SENT 0x8049
#define WRITE_REQUEST_QUEUE_IN_POINTER(isp, value) \
ISP_WRITE(isp, isp->isp_rqstinrp, value)
#define READ_REQUEST_QUEUE_OUT_POINTER(isp) \
ISP_READ(isp, isp->isp_rqstoutrp)
#define READ_RESPONSE_QUEUE_IN_POINTER(isp) \
ISP_READ(isp, isp->isp_respinrp)
#define WRITE_RESPONSE_QUEUE_OUT_POINTER(isp, value) \
ISP_WRITE(isp, isp->isp_respoutrp, value)
/*
* All IOCB Queue entries are this size
*/
#define QENTRY_LEN 64
/*
* Command Structure Definitions
@ -288,6 +293,7 @@ typedef struct {
#define RQSFLAG_FULL 0x02
#define RQSFLAG_BADHEADER 0x04
#define RQSFLAG_BADPACKET 0x08
#define RQSFLAG_MASK 0x0f
/* RQS entry_type definitions */
#define RQSTYPE_REQUEST 0x01
@ -307,11 +313,13 @@ typedef struct {
#define RQSTYPE_CTIO1 0x0f /* Target Mode */
#define RQSTYPE_STATUS_CONT 0x10
#define RQSTYPE_T2RQS 0x11
#define RQSTYPE_CTIO7 0x12
#define RQSTYPE_IP_XMIT 0x13
#define RQSTYPE_TSK_MGMT 0x14
#define RQSTYPE_T4RQS 0x15
#define RQSTYPE_ATIO2 0x16 /* Target Mode */
#define RQSTYPE_CTIO2 0x17 /* Target Mode */
#define RQSTYPE_CSET0 0x18
#define RQSTYPE_T7RQS 0x18
#define RQSTYPE_T3RQS 0x19
#define RQSTYPE_IP_XMIT_64 0x1b
#define RQSTYPE_CTIO4 0x1e /* Target Mode */
@ -320,6 +328,12 @@ typedef struct {
#define RQSTYPE_RIO2 0x22
#define RQSTYPE_IP_RECV 0x23
#define RQSTYPE_IP_RECV_CONT 0x24
#define RQSTYPE_CT_PASSTHRU 0x29
#define RQSTYPE_ABORT_IO 0x33
#define RQSTYPE_T6RQS 0x48
#define RQSTYPE_LOGIN 0x52
#define RQSTYPE_ABTS_RCVD 0x54 /* 24XX only */
#define RQSTYPE_ABTS_RSP 0x55 /* 24XX only */
#define ISP_RQDSEG 4
@ -329,7 +343,6 @@ typedef struct {
uint8_t req_lun_trn;
uint8_t req_target;
uint16_t req_cdblen;
#define req_modifier req_cdblen /* marker packet */
uint16_t req_flags;
uint16_t req_reserved;
uint16_t req_time;
@ -337,13 +350,33 @@ typedef struct {
uint8_t req_cdb[12];
ispds_t req_dataseg[ISP_RQDSEG];
} ispreq_t;
#define ispreq64_t ispreqt3_t /* same as.... */
#define ISP_RQDSEG_A64 2
/*
* A request packet can also be a marker packet.
*/
typedef struct {
isphdr_t mrk_header;
uint32_t mrk_handle;
uint8_t mrk_reserved0;
uint8_t mrk_target;
uint16_t mrk_modifier;
uint16_t mrk_flags;
uint16_t mrk_lun;
uint8_t mrk_reserved1[48];
} isp_marker_t;
typedef struct {
isphdr_t mrk_header;
uint32_t mrk_handle;
uint16_t mrk_nphdl;
uint8_t mrk_modifier;
uint8_t mrk_reserved0;
uint8_t mrk_reserved1;
uint8_t mrk_vphdl;
uint16_t mrk_reserved2;
uint8_t mrk_lun[8];
uint8_t mrk_reserved3[40];
} isp_marker_24xx_t;
#define SYNC_DEVICE 0
#define SYNC_TARGET 1
#define SYNC_ALL 2
@ -357,7 +390,7 @@ typedef struct {
uint8_t req_target;
uint16_t req_scclun;
uint16_t req_flags;
uint16_t _res2;
uint16_t req_reserved;
uint16_t req_time;
uint16_t req_seg_count;
uint8_t req_cdb[16];
@ -371,7 +404,7 @@ typedef struct {
uint16_t req_target;
uint16_t req_scclun;
uint16_t req_flags;
uint16_t _res2;
uint16_t req_reserved;
uint16_t req_time;
uint16_t req_seg_count;
uint8_t req_cdb[16];
@ -387,13 +420,14 @@ typedef struct {
uint8_t req_target;
uint16_t req_scclun;
uint16_t req_flags;
uint16_t _res2;
uint16_t req_reserved;
uint16_t req_time;
uint16_t req_seg_count;
uint8_t req_cdb[16];
uint32_t req_totalcnt;
ispds64_t req_dataseg[ISP_RQDSEG_T3];
} ispreqt3_t;
#define ispreq64_t ispreqt3_t /* same as.... */
typedef struct {
isphdr_t req_header;
@ -401,7 +435,7 @@ typedef struct {
uint16_t req_target;
uint16_t req_scclun;
uint16_t req_flags;
uint16_t _res2;
uint16_t req_reserved;
uint16_t req_time;
uint16_t req_seg_count;
uint8_t req_cdb[16];
@ -437,16 +471,86 @@ typedef struct {
uint8_t req_target;
uint16_t req_cdblen;
uint16_t req_flags;
uint16_t _res1;
uint16_t req_reserved;
uint16_t req_time;
uint16_t req_seg_count;
uint8_t req_cdb[44];
} ispextreq_t;
/* 24XX only */
typedef struct {
uint16_t fcd_length;
uint16_t fcd_a1500;
uint16_t fcd_a3116;
uint16_t fcd_a4732;
uint16_t fcd_a6348;
} fcp_cmnd_ds_t;
typedef struct {
isphdr_t req_header;
uint32_t req_handle;
uint16_t req_nphdl;
uint16_t req_time;
uint16_t req_seg_count;
uint16_t req_fc_rsp_dsd_length;
uint8_t req_lun[8];
uint16_t req_flags;
uint16_t req_fc_cmnd_dsd_length;
uint16_t req_fc_cmnd_dsd_a1500;
uint16_t req_fc_cmnd_dsd_a3116;
uint16_t req_fc_cmnd_dsd_a4732;
uint16_t req_fc_cmnd_dsd_a6348;
uint16_t req_fc_rsp_dsd_a1500;
uint16_t req_fc_rsp_dsd_a3116;
uint16_t req_fc_rsp_dsd_a4732;
uint16_t req_fc_rsp_dsd_a6348;
uint32_t req_totalcnt;
uint16_t req_tidlo;
uint8_t req_tidhi;
uint8_t req_vpidx;
ispds64_t req_dataseg;
} ispreqt6_t;
typedef struct {
isphdr_t req_header;
uint32_t req_handle;
uint16_t req_nphdl;
uint16_t req_time;
uint16_t req_seg_count;
uint16_t req_reserved;
uint8_t req_lun[8];
uint8_t req_alen_datadir;
uint8_t req_task_management;
uint8_t req_task_attribute;
uint8_t req_crn;
uint8_t req_cdb[16];
uint32_t req_dl;
uint16_t req_tidlo;
uint8_t req_tidhi;
uint8_t req_vpidx;
ispds64_t req_dataseg;
} ispreqt7_t;
/* I/O Abort Structure */
typedef struct {
isphdr_t abrt_header;
uint32_t abrt_handle;
uint16_t abrt_nphdl;
uint16_t abrt_options;
uint32_t abrt_cmd_handle;
uint8_t abrt_reserved[32];
uint16_t abrt_tidlo;
uint8_t abrt_tidhi;
uint8_t abrt_vpidx;
uint8_t abrt_reserved1[12];
} isp24xx_abrt_t;
#define ISP24XX_ABRT_NO_ABTS 0x01 /* don't actually send an ABTS */
#define ISP24XX_ABRT_ENXIO 0x31 /* in nphdl on return */
#define ISP_CDSEG 7
typedef struct {
isphdr_t req_header;
uint32_t _res1;
uint32_t req_reserved;
ispds_t req_dataseg[ISP_CDSEG];
} ispcontreq_t;
@ -471,11 +575,33 @@ typedef struct {
uint8_t req_sense_data[32];
} ispstatusreq_t;
/*
* Status Continuation
*/
typedef struct {
isphdr_t req_header;
uint8_t req_sense_data[60];
} ispstatus_cont_t;
/*
* 24XX Type 0 status
*/
typedef struct {
isphdr_t req_header;
uint32_t req_handle;
uint16_t req_completion_status;
uint16_t req_oxid;
uint32_t req_resid;
uint16_t req_reserved0;
uint16_t req_state_flags;
uint16_t req_reserved1;
uint16_t req_scsi_status;
uint32_t req_fcp_residual;
uint32_t req_sense_len;
uint32_t req_response_len;
uint8_t req_rsp_sense[28];
} isp24xx_statusreq_t;
/*
* For Qlogic 2X00, the high order byte of SCSI status has
* additional meaning.
@ -486,6 +612,25 @@ typedef struct {
#define RQCS_SV 0x200 /* Sense Length Valid */
#define RQCS_RV 0x100 /* FCP Response Length Valid */
/*
* CT Passthru IOCB
*/
typedef struct {
isphdr_t ctp_header;
uint32_t ctp_handle;
uint16_t ctp_status;
uint16_t ctp_nphdl; /* n-port handle */
uint16_t ctp_cmd_cnt; /* Command DSD count */
uint16_t ctp_vpidx; /* low 8 bits */
uint16_t ctp_time;
uint16_t ctp_reserved0;
uint16_t ctp_rsp_cnt; /* Response DSD count */
uint16_t ctp_reserved1[5];
uint32_t ctp_rsp_bcnt; /* Response byte count */
uint32_t ctp_cmd_bcnt; /* Command byte count */
ispds64_t ctp_dataseg[2];
} isp_ct_pt_t;
/*
* Completion Status Codes.
*/
@ -530,6 +675,13 @@ typedef struct {
#define RQCS_PORT_CHANGED 0x002A
#define RQCS_PORT_BUSY 0x002B
/* 24XX Only Completion Codes */
#define RQCS_24XX_DRE 0x0011 /* data reassembly error */
#define RQCS_24XX_TABORT 0x0013 /* aborted by target */
#define RQCS_24XX_ENOMEM 0x002C /* f/w resource unavailable */
#define RQCS_24XX_TMO 0x0030 /* task management overrun */
/*
* 1X00 specific State Flags
*/
@ -587,6 +739,7 @@ typedef struct {
/*
* About Firmware returns an 'attribute' word in mailbox 6.
* These attributes are for 2200 and 2300.
*/
#define ISP_FW_ATTR_TMODE 0x01
#define ISP_FW_ATTR_SCCLUN 0x02
@ -598,8 +751,14 @@ typedef struct {
#define ISP_FW_ATTR_VI_SOLARIS 0x80
#define ISP_FW_ATTR_2KLOGINS 0x100 /* XXX: just a guess */
#define IS_2KLOGIN(isp) \
(IS_FC(isp) && (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_2KLOGINS))
/* and these are for the 2400 */
#define ISP2400_FW_ATTR_CLASS2 (1 << 0)
#define ISP2400_FW_ATTR_IP (1 << 1)
#define ISP2400_FW_ATTR_MULTIID (1 << 2)
#define ISP2400_FW_ATTR_SB2 (1 << 3)
#define ISP2400_FW_ATTR_T10CRC (1 << 4)
#define ISP2400_FW_ATTR_VI (1 << 5)
#define ISP2400_FW_ATTR_EXPFW (1 << 13)
/*
* Reduced Interrupt Operation Response Queue Entreis
@ -616,7 +775,7 @@ typedef struct {
} isp_rio2_t;
/*
* FC (ISP2100) specific data structures
* FC (ISP2100/ISP2200/ISP2300/ISP2400) specific data structures
*/
/*
@ -624,9 +783,9 @@ typedef struct {
*
* Version One (prime) format.
*/
typedef struct isp_icb {
typedef struct {
uint8_t icb_version;
uint8_t _reserved0;
uint8_t icb_reserved0;
uint16_t icb_fwoptions;
uint16_t icb_maxfrmlen;
uint16_t icb_maxalloc;
@ -648,42 +807,48 @@ typedef struct isp_icb {
uint8_t icb_ccnt;
uint8_t icb_icnt;
uint16_t icb_lunetimeout;
uint16_t _reserved1;
uint16_t icb_reserved1;
uint16_t icb_xfwoptions;
uint8_t icb_racctimer;
uint8_t icb_idelaytimer;
uint16_t icb_zfwoptions;
uint16_t _reserved2[13];
uint16_t icb_reserved2[13];
} isp_icb_t;
#define ICB_VERSION1 1
#define ICBOPT_HARD_ADDRESS 0x0001
#define ICBOPT_FAIRNESS 0x0002
#define ICBOPT_FULL_DUPLEX 0x0004
#define ICBOPT_FAST_POST 0x0008
#define ICBOPT_TGT_ENABLE 0x0010
#define ICBOPT_INI_DISABLE 0x0020
#define ICBOPT_INI_ADISC 0x0040
#define ICBOPT_INI_TGTTYPE 0x0080
#define ICBOPT_PDBCHANGE_AE 0x0100
#define ICBOPT_NOLIP 0x0200
#define ICBOPT_SRCHDOWN 0x0400
#define ICBOPT_PREVLOOP 0x0800
#define ICBOPT_STOP_ON_QFULL 0x1000
#define ICBOPT_FULL_LOGIN 0x2000
#define ICBOPT_BOTH_WWNS 0x4000
#define ICBOPT_EXTENDED 0x8000
#define ICBOPT_BOTH_WWNS 0x4000
#define ICBOPT_FULL_LOGIN 0x2000
#define ICBOPT_STOP_ON_QFULL 0x1000 /* 2200/2100 only */
#define ICBOPT_PREVLOOP 0x0800
#define ICBOPT_SRCHDOWN 0x0400
#define ICBOPT_NOLIP 0x0200
#define ICBOPT_PDBCHANGE_AE 0x0100
#define ICBOPT_INI_TGTTYPE 0x0080
#define ICBOPT_INI_ADISC 0x0040
#define ICBOPT_INI_DISABLE 0x0020
#define ICBOPT_TGT_ENABLE 0x0010
#define ICBOPT_FAST_POST 0x0008
#define ICBOPT_FULL_DUPLEX 0x0004
#define ICBOPT_FAIRNESS 0x0002
#define ICBOPT_HARD_ADDRESS 0x0001
#define ICBXOPT_NO_LOGOUT 0x8000 /* no logout on link failure */
#define ICBXOPT_FCTAPE_CCQ 0x4000 /* FC-Tape Command Queueing */
#define ICBXOPT_FCTAPE_CONFIRM 0x2000
#define ICBXOPT_FCTAPE 0x1000
#define ICBXOPT_CLASS2_ACK0 0x0200
#define ICBXOPT_CLASS2 0x0100
#define ICBXOPT_LOOP_ONLY (0 << 4)
#define ICBXOPT_PTP_ONLY (1 << 4)
#define ICBXOPT_LOOP_2_PTP (2 << 4)
#define ICBXOPT_PTP_2_LOOP (3 << 4)
#define ICBXOPT_NO_PLAY 0x0080 /* don't play if can't get hard addr */
#define ICBXOPT_TOPO_MASK 0x0070
#define ICBXOPT_LOOP_ONLY 0x0000
#define ICBXOPT_PTP_ONLY 0x0010
#define ICBXOPT_LOOP_2_PTP 0x0020
#define ICBXOPT_PTP_2_LOOP 0x0030
/*
* The lower 4 bits of the xfwoptions field are the OPERATION MODE bits.
* RIO is not defined for the 23XX cards
* RIO is not defined for the 23XX cards (just 2200)
*/
#define ICBXOPT_RIO_OFF 0
#define ICBXOPT_RIO_16BIT 1
@ -693,14 +858,60 @@ typedef struct isp_icb {
#define ICBXOPT_ZIO 5
#define ICBXOPT_TIMER_MASK 0x7
#define ICBZOPT_ENA_RDXFR_RDY 0x01
#define ICBZOPT_ENA_OOF (1 << 6) /* out of order frame handling */
#define ICBZOPT_50_OHM 0x0200
/* These 3 only apply to the 2300 */
#define ICBZOPT_RATE_ONEGB (MBGSD_ONEGB << 14)
#define ICBZOPT_RATE_TWOGB (MBGSD_TWOGB << 14)
#define ICBZOPT_RATE_AUTO (MBGSD_AUTO << 14)
#define ICBZOPT_RATE_MASK 0xC000
#define ICBZOPT_RATE_ONEGB 0x0000
#define ICBZOPT_RATE_AUTO 0x8000
#define ICBZOPT_RATE_TWOGB 0x4000
#define ICBZOPT_50_OHM 0x2000
#define ICBZOPT_ENA_OOF 0x0040 /* out of order frame handling */
#define ICBZOPT_RSPSZ_MASK 0x0030
#define ICBZOPT_RSPSZ_24 0x0000
#define ICBZOPT_RSPSZ_12 0x0010
#define ICBZOPT_RSPSZ_24A 0x0020
#define ICBZOPT_RSPSZ_32 0x0030
#define ICBZOPT_SOFTID 0x0002
#define ICBZOPT_ENA_RDXFR_RDY 0x0001
/* 2400 F/W options */
#define ICB2400_OPT1_BOTH_WWNS 0x00004000
#define ICB2400_OPT1_FULL_LOGIN 0x00002000
#define ICB2400_OPT1_PREVLOOP 0x00000800
#define ICB2400_OPT1_SRCHDOWN 0x00000400
#define ICB2400_OPT1_NOLIP 0x00000200
#define ICB2400_OPT1_INI_DISABLE 0x00000020
#define ICB2400_OPT1_TGT_ENABLE 0x00000010
#define ICB2400_OPT1_FULL_DUPLEX 0x00000004
#define ICB2400_OPT1_FAIRNESS 0x00000002
#define ICB2400_OPT1_HARD_ADDRESS 0x00000001
#define ICB2400_OPT2_FCTAPE 0x00001000
#define ICB2400_OPT2_CLASS2_ACK0 0x00000200
#define ICB2400_OPT2_CLASS2 0x00000100
#define ICB2400_OPT2_NO_PLAY 0x00000080
#define ICB2400_OPT2_TOPO_MASK 0x00000070
#define ICB2400_OPT2_LOOP_ONLY 0x00000000
#define ICB2400_OPT2_PTP_ONLY 0x00000010
#define ICB2400_OPT2_LOOP_2_PTP 0x00000020
#define ICB2400_OPT2_PTP_2_LOOP 0x00000030
#define ICB2400_OPT2_TIMER_MASK 0x00000007
#define ICB2400_OPT2_ZIO 0x00000005
#define ICB2400_OPT2_ZIO1 0x00000006
#define ICB2400_OPT3_75_OHM 0x00010000
#define ICB2400_OPT3_RATE_MASK 0x0000E000
#define ICB2400_OPT3_RATE_ONEGB 0x00000000
#define ICB2400_OPT3_RATE_TWOGB 0x00002000
#define ICB2400_OPT3_RATE_AUTO 0x00004000
#define ICB2400_OPT3_RATE_FOURGB 0x00006000
#define ICB2400_OPT3_ENA_OOF_XFRDY 0x00000200
#define ICB2400_OPT3_NO_LOCAL_PLOGI 0x00000080
#define ICB2400_OPT3_ENA_OOF 0x00000040
/* note that a response size flag of zero is reserved! */
#define ICB2400_OPT3_RSPSZ_MASK 0x00000030
#define ICB2400_OPT3_RSPSZ_12 0x00000010
#define ICB2400_OPT3_RSPSZ_24 0x00000020
#define ICB2400_OPT3_RSPSZ_32 0x00000030
#define ICB2400_OPT3_SOFTID 0x00000002
#define ICB_MIN_FRMLEN 256
#define ICB_MAX_FRMLEN 2112
@ -714,6 +925,41 @@ typedef struct isp_icb {
#define ICB_LUN_ENABLE_TOV 180
/*
* And somebody at QLogic had a great idea that you could just change
* the structure *and* keep the version number the same as the other cards.
*/
typedef struct {
uint16_t icb_version;
uint16_t icb_reserved0;
uint16_t icb_maxfrmlen;
uint16_t icb_execthrottle;
uint16_t icb_xchgcnt;
uint16_t icb_hardaddr;
uint8_t icb_portname[8];
uint8_t icb_nodename[8];
uint16_t icb_rspnsin;
uint16_t icb_rqstout;
uint16_t icb_retry_count;
uint16_t icb_priout;
uint16_t icb_rsltqlen;
uint16_t icb_rqstqlen;
uint16_t icb_ldn_nols;
uint16_t icb_prqstqlen;
uint16_t icb_rqstaddr[4];
uint16_t icb_respaddr[4];
uint16_t icb_priaddr[4];
uint16_t icb_reserved1[4];
uint16_t icb_atio_in;
uint16_t icb_atioqlen;
uint16_t icb_atioqaddr[4];
uint16_t icb_idelaytimer;
uint16_t icb_logintime;
uint32_t icb_fwoptions1;
uint32_t icb_fwoptions2;
uint32_t icb_fwoptions3;
uint16_t icb_reserved2[12];
} isp_icb_2400_t;
#define RQRSP_ADDR0015 0
#define RQRSP_ADDR1631 1
@ -750,22 +996,6 @@ typedef struct isp_icb {
((uint64_t) array[ICB_NNM6] << 48) | \
((uint64_t) array[ICB_NNM7] << 56)
/*
* FC-AL Position Map
*
* This is an at most 128 byte map that returns either
* the LILP or Firmware generated list of ports.
*
* We deviate a bit from the returned qlogic format to
* use an extra bit to say whether this was a LILP or
* f/w generated map.
*/
typedef struct {
uint8_t fwmap : 1,
count : 7;
uint8_t map[127];
} fcpos_map_t;
/*
* Port Data Base Element
*/
@ -774,7 +1004,6 @@ typedef struct {
uint16_t pdb_options;
uint8_t pdb_mstate;
uint8_t pdb_sstate;
#define BITS2WORD(x) ((x)[0] << 16 | (x)[3] << 8 | (x)[2])
uint8_t pdb_hardaddr_bits[4];
uint8_t pdb_portid_bits[4];
uint8_t pdb_nodename[8];
@ -810,7 +1039,7 @@ typedef struct {
uint16_t pdb_loopid;
uint16_t pdb_il_ptr;
uint16_t pdb_sl_ptr;
} isp_pdb_t;
} isp_pdb_21xx_t;
#define PDB_OPTIONS_XMITTING (1<<11)
#define PDB_OPTIONS_LNKXMIT (1<<10)
@ -835,35 +1064,109 @@ typedef struct {
#define SVC3_ROLE_MASK 0x30
#define SVC3_ROLE_SHIFT 4
#define BITS2WORD(x) ((x)[0] << 16 | (x)[3] << 8 | (x)[2])
#define BITS2WORD_24XX(x) ((x)[0] << 16 | (x)[1] << 8 | (x)[2])
/*
* CT definition
*
* This is as the QLogic f/w documentations defines it- which is just opposite,
* bit wise, from what the specification defines it as. Additionally, the
* ct_response and ct_resid (really from FC-GS-2) need to be byte swapped.
* Port Data Base Element- 24XX cards
*/
typedef struct {
uint8_t ct_revision;
uint8_t ct_portid[3];
uint8_t ct_fcs_type;
uint8_t ct_fcs_subtype;
uint8_t ct_options;
uint8_t ct_res0;
uint16_t ct_response;
uint16_t ct_resid;
uint8_t ct_res1;
uint8_t ct_reason;
uint8_t ct_explanation;
uint8_t ct_vunique;
} ct_hdr_t;
#define FS_ACC 0x8002
#define FS_RJT 0x8001
uint16_t pdb_flags;
uint8_t pdb_curstate;
uint8_t pdb_laststate;
uint8_t pdb_hardaddr_bits[4];
uint8_t pdb_portid_bits[4];
#define pdb_nxt_seqid_2400 pdb_portid_bits[3]
uint16_t pdb_retry_timer;
uint16_t pdb_handle;
uint16_t pdb_rcv_dsize;
uint16_t pdb_reserved0;
uint16_t pdb_prli_svc0;
uint16_t pdb_prli_svc3;
uint8_t pdb_portname[8];
uint8_t pdb_nodename[8];
uint8_t pdb_reserved1[24];
} isp_pdb_24xx_t;
#define FC4_IP 5 /* ISO/EEC 8802-2 LLC/SNAP "Out of Order Delivery" */
#define FC4_SCSI 8 /* SCSI-3 via Fivre Channel Protocol (FCP) */
#define FC4_FC_SVC 0x20 /* Fibre Channel Services */
#define PDB2400_TID_SUPPORTED 0x4000
#define PDB2400_FC_TAPE 0x0080
#define PDB2400_CLASS2_ACK0 0x0040
#define PDB2400_FCP_CONF 0x0020
#define PDB2400_CLASS2 0x0010
#define PDB2400_ADDR_VALID 0x0002
/*
* Common elements from the above two structures that are actually useful to us.
*/
typedef struct {
uint16_t handle;
uint16_t reserved;
uint32_t s3_role : 8,
portid : 24;
uint8_t portname[8];
uint8_t nodename[8];
} isp_pdb_t;
/*
* ISP24XX- Login/Logout Port IOCB
*/
typedef struct {
isphdr_t plogx_header;
uint32_t plogx_handle;
uint16_t plogx_status;
uint16_t plogx_nphdl;
uint16_t plogx_flags;
uint16_t plogx_vphdl; /* low 8 bits */
uint16_t plogx_portlo; /* low 16 bits */
uint16_t plogx_rspsz_porthi;
struct {
uint16_t lo16;
uint16_t hi16;
} plogx_ioparm[11];
} isp_plogx_t;
#define PLOGX_STATUS_OK 0x00
#define PLOGX_STATUS_UNAVAIL 0x28
#define PLOGX_STATUS_LOGOUT 0x29
#define PLOGX_STATUS_IOCBERR 0x31
#define PLOGX_IOCBERR_NOLINK 0x01
#define PLOGX_IOCBERR_NOIOCB 0x02
#define PLOGX_IOCBERR_NOXGHG 0x03
#define PLOGX_IOCBERR_FAILED 0x04 /* further info in IOPARM 1 */
#define PLOGX_IOCBERR_NOFABRIC 0x05
#define PLOGX_IOCBERR_NOTREADY 0x07
#define PLOGX_IOCBERR_NOLOGIN 0x08 /* further info in IOPARM 1 */
#define PLOGX_IOCBERR_NOPCB 0x0a
#define PLOGX_IOCBERR_REJECT 0x18 /* further info in IOPARM 1 */
#define PLOGX_IOCBERR_EINVAL 0x19 /* further info in IOPARM 1 */
#define PLOGX_IOCBERR_PORTUSED 0x1a /* further info in IOPARM 1 */
#define PLOGX_IOCBERR_HNDLUSED 0x1b /* further info in IOPARM 1 */
#define PLOGX_IOCBERR_NOHANDLE 0x1c
#define PLOGX_IOCBERR_NOFLOGI 0x1f /* further info in IOPARM 1 */
#define PLOGX_FLG_CMD_MASK 0xf
#define PLOGX_FLG_CMD_PLOGI 0
#define PLOGX_FLG_CMD_PRLI 1
#define PLOGX_FLG_CMD_PDISC 2
#define PLOGX_FLG_CMD_LOGO 8
#define PLOGX_FLG_CMD_PRLO 9
#define PLOGX_FLG_CMD_TPRLO 10
#define PLOGX_FLG_COND_PLOGI 0x10 /* if with PLOGI */
#define PLOGX_FLG_IMPLICIT 0x10 /* if with LOGO, PRLO, TPRLO */
#define PLOGX_FLG_SKIP_PRLI 0x20 /* if with PLOGI */
#define PLOGX_FLG_IMPLICIT_LOGO_ALL 0x20 /* if with LOGO */
#define PLOGX_FLG_EXPLICIT_LOGO 0x40 /* if with LOGO */
#define PLOGX_FLG_COMMON_FEATURES 0x80 /* if with PLOGI */
#define PLOGX_FLG_FREE_NPHDL 0x80 /* if with with LOGO */
#define PLOGX_FLG_CLASS2 0x100 /* if with PLOGI */
#define PLOGX_FLG_FCP2_OVERRIDE 0x200 /* if with PRLOG, PRLI */
/*
* Simple Name Server Data Structures
*/
#define SNS_GA_NXT 0x100
#define SNS_GPN_ID 0x112
#define SNS_GNN_ID 0x113
@ -872,61 +1175,61 @@ typedef struct {
#define SNS_RFT_ID 0x217
typedef struct {
uint16_t snscb_rblen; /* response buffer length (words) */
uint16_t snscb_res0;
uint16_t snscb_reserved0;
uint16_t snscb_addr[4]; /* response buffer address */
uint16_t snscb_sblen; /* subcommand buffer length (words) */
uint16_t snscb_res1;
uint16_t snscb_reserved1;
uint16_t snscb_data[1]; /* variable data */
} sns_screq_t; /* Subcommand Request Structure */
typedef struct {
uint16_t snscb_rblen; /* response buffer length (words) */
uint16_t snscb_res0;
uint16_t snscb_reserved0;
uint16_t snscb_addr[4]; /* response buffer address */
uint16_t snscb_sblen; /* subcommand buffer length (words) */
uint16_t snscb_res1;
uint16_t snscb_reserved1;
uint16_t snscb_cmd;
uint16_t snscb_res2;
uint32_t snscb_res3;
uint16_t snscb_reserved2;
uint32_t snscb_reserved3;
uint32_t snscb_port;
} sns_ga_nxt_req_t;
#define SNS_GA_NXT_REQ_SIZE (sizeof (sns_ga_nxt_req_t))
typedef struct {
uint16_t snscb_rblen; /* response buffer length (words) */
uint16_t snscb_res0;
uint16_t snscb_reserved0;
uint16_t snscb_addr[4]; /* response buffer address */
uint16_t snscb_sblen; /* subcommand buffer length (words) */
uint16_t snscb_res1;
uint16_t snscb_reserved1;
uint16_t snscb_cmd;
uint16_t snscb_res2;
uint32_t snscb_res3;
uint16_t snscb_reserved2;
uint32_t snscb_reserved3;
uint32_t snscb_portid;
} sns_gxn_id_req_t;
#define SNS_GXN_ID_REQ_SIZE (sizeof (sns_gxn_id_req_t))
typedef struct {
uint16_t snscb_rblen; /* response buffer length (words) */
uint16_t snscb_res0;
uint16_t snscb_reserved0;
uint16_t snscb_addr[4]; /* response buffer address */
uint16_t snscb_sblen; /* subcommand buffer length (words) */
uint16_t snscb_res1;
uint16_t snscb_reserved1;
uint16_t snscb_cmd;
uint16_t snscb_mword_div_2;
uint32_t snscb_res3;
uint32_t snscb_reserved3;
uint32_t snscb_fc4_type;
} sns_gid_ft_req_t;
#define SNS_GID_FT_REQ_SIZE (sizeof (sns_gid_ft_req_t))
typedef struct {
uint16_t snscb_rblen; /* response buffer length (words) */
uint16_t snscb_res0;
uint16_t snscb_reserved0;
uint16_t snscb_addr[4]; /* response buffer address */
uint16_t snscb_sblen; /* subcommand buffer length (words) */
uint16_t snscb_res1;
uint16_t snscb_reserved1;
uint16_t snscb_cmd;
uint16_t snscb_res2;
uint32_t snscb_res3;
uint16_t snscb_reserved2;
uint32_t snscb_reserved3;
uint32_t snscb_port;
uint32_t snscb_fc4_types[8];
} sns_rft_id_req_t;
@ -980,7 +1283,68 @@ typedef struct {
} snscb_ports[1];
} sns_gid_ft_rsp_t;
#define SNS_GID_FT_RESP_SIZE(x) ((sizeof (sns_gid_ft_rsp_t)) + ((x - 1) << 2))
#define SNS_RFT_ID_RESP_SIZE (sizeof (ct_hdr_t))
/*
* Other Misc Structures
*/
/* ELS Pass Through */
typedef struct {
isphdr_t els_hdr;
uint32_t els_handle;
uint16_t els_status;
uint16_t els_nphdl;
uint16_t els_xmit_dsd_count; /* outgoing only */
uint8_t els_vphdl;
uint8_t els_sof;
uint32_t els_rxid;
uint16_t els_recv_dsd_count; /* outgoing only */
uint8_t els_opcode;
uint8_t els_reserved1;
uint8_t els_did_lo;
uint8_t els_did_mid;
uint8_t els_did_hi;
uint8_t els_reserved2;
uint16_t els_reserved3;
uint16_t els_ctl_flags;
union {
struct {
uint32_t _els_bytecnt;
uint32_t _els_subcode1;
uint32_t _els_subcode2;
uint8_t _els_reserved4[20];
} in;
struct {
uint32_t _els_recv_bytecnt;
uint32_t _els_xmit_bytecnt;
uint32_t _els_xmit_dsd_length;
uint16_t _els_xmit_dsd_a1500;
uint16_t _els_xmit_dsd_a3116;
uint16_t _els_xmit_dsd_a4732;
uint16_t _els_xmit_dsd_a6348;
uint32_t _els_recv_dsd_length;
uint16_t _els_recv_dsd_a1500;
uint16_t _els_recv_dsd_a3116;
uint16_t _els_recv_dsd_a4732;
uint16_t _els_recv_dsd_a6348;
} out;
} inout;
#define els_bytecnt inout.in._els_bytecnt
#define els_subcode1 inout.in._els_subcode1
#define els_subcode2 inout.in._els_subcode2
#define els_reserved4 inout.in._els_reserved4
#define els_recv_bytecnt inout.out._els_recv_bytecnt
#define els_xmit_bytecnt inout.out._els_xmit_bytecnt
#define els_xmit_dsd_length inout.out._els_xmit_dsd_length
#define els_xmit_dsd_a1500 inout.out._els_xmit_dsd_a1500
#define els_xmit_dsd_a3116 inout.out._els_xmit_dsd_a3116
#define els_xmit_dsd_a4732 inout.out._els_xmit_dsd_a4732
#define els_xmit_dsd_a6348 inout.out._els_xmit_dsd_a6348
#define els_recv_dsd_length inout.out._els_recv_dsd_length
#define els_recv_dsd_a1500 inout.out._els_recv_dsd_a1500
#define els_recv_dsd_a3116 inout.out._els_recv_dsd_a3116
#define els_recv_dsd_a4732 inout.out._els_recv_dsd_a4732
#define els_recv_dsd_a6348 inout.out._els_recv_dsd_a6348
} els_t;
#endif /* _ISPMBOX_H */

View File

@ -64,6 +64,7 @@
#define PCI_MBOX_REGS_OFF 0x70
#define PCI_MBOX_REGS2100_OFF 0x10
#define PCI_MBOX_REGS2300_OFF 0x40
#define PCI_MBOX_REGS2400_OFF 0x80
#define SBUS_MBOX_REGS_OFF 0x80
#define PCI_SXP_REGS_OFF 0x80
@ -110,12 +111,6 @@
#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 */
@ -139,6 +134,7 @@
#define ISPR2HST_FPOST 0x16 /* Low 16 bits fast post */
#define ISPR2HST_FPOST_CTIO 0x17 /* Low 16 bits fast post ctio */
/* fifo command stuff- mostly for SPI */
#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 */
@ -219,6 +215,8 @@
#define BIU_ICR_ENABLE_ALL_INTS 0x0002 /* Global enable all inter */
#define BIU_ICR_SOFT_RESET 0x0001 /* Soft Reset of ISP */
#define BIU_IMASK (BIU_ICR_ENABLE_RISC_INT|BIU_ICR_ENABLE_ALL_INTS)
#define BIU2100_ICR_ENABLE_ALL_INTS 0x8000
#define BIU2100_ICR_ENA_FPM_INT 0x0020
#define BIU2100_ICR_ENA_FB_INT 0x0010
@ -228,16 +226,7 @@
#define BIU2100_ICR_ENABLE_TXDMA_INT 0x0001
#define BIU2100_ICR_DISABLE_ALL_INTS 0x0000
#define ENABLE_INTS(isp) (IS_SCSI(isp))? \
ISP_WRITE(isp, BIU_ICR, BIU_ICR_ENABLE_RISC_INT | BIU_ICR_ENABLE_ALL_INTS) : \
ISP_WRITE(isp, BIU_ICR, BIU2100_ICR_ENA_RISC_INT | BIU2100_ICR_ENABLE_ALL_INTS)
#define INTS_ENABLED(isp) ((IS_SCSI(isp))? \
(ISP_READ(isp, BIU_ICR) & (BIU_ICR_ENABLE_RISC_INT|BIU_ICR_ENABLE_ALL_INTS)) :\
(ISP_READ(isp, BIU_ICR) & \
(BIU2100_ICR_ENA_RISC_INT|BIU2100_ICR_ENABLE_ALL_INTS)))
#define DISABLE_INTS(isp) ISP_WRITE(isp, BIU_ICR, 0)
#define BIU2100_IMASK (BIU2100_ICR_ENA_RISC_INT|BIU2100_ICR_ENABLE_ALL_INTS)
/* BUS STATUS REGISTER */
#define BIU_ISR_DMA_INT 0x0020 /* DMA interrupt pending */
@ -254,11 +243,14 @@
#define BIU2100_ISR_RXDMA_INT_PENDING 0x0002 /* Global interrupt pending */
#define BIU2100_ISR_TXDMA_INT_PENDING 0x0001 /* Global interrupt pending */
#define INT_PENDING(isp, isr) (IS_FC(isp)? \
((isr & BIU2100_ISR_RISC_INT) != 0) : ((isr & BIU_ISR_RISC_INT) != 0))
#define INT_PENDING(isp, isr) \
IS_FC(isp)? \
(IS_24XX(isp)? (isr & BIU2400_ISR_RISC_INT) : (isr & BIU2100_ISR_RISC_INT)) :\
(isr & BIU_ISR_RISC_INT)
#define INT_PENDING_MASK(isp) \
(IS_FC(isp)? BIU2100_ISR_RISC_INT: BIU_ISR_RISC_INT)
(IS_FC(isp)? (IS_24XX(isp)? BIU2400_ISR_RISC_INT : BIU2100_ISR_RISC_INT) : \
(BIU_ISR_RISC_INT))
/* BUS SEMAPHORE REGISTER */
#define BIU_SEMA_STATUS 0x0002 /* Semaphore Status Bit */
@ -351,6 +343,86 @@
#define DMA_FIFO_SBUS_COUNT_MASK 0x007F /* FIFO Byte count mask */
#define DMA_FIFO_PCI_COUNT_MASK 0x00FF /* FIFO Byte count mask */
/*
* 2400 Interface Offsets and Register Definitions
*
* The 2400 looks quite different in terms of registers from other QLogic cards.
* It is getting to be a genuine pain and challenge to keep the same model
* for all.
*/
#define BIU2400_FLASH_ADDR (BIU_BLOCK+0x00)
#define BIU2400_FLASH_DATA (BIU_BLOCK+0x04)
#define BIU2400_CSR (BIU_BLOCK+0x08)
#define BIU2400_ICR (BIU_BLOCK+0x0C)
#define BIU2400_ISR (BIU_BLOCK+0x10)
#define BIU2400_REQINP (BIU_BLOCK+0x1C) /* Request Queue In */
#define BIU2400_REQOUTP (BIU_BLOCK+0x20) /* Request Queue Out */
#define BIU2400_RSPINP (BIU_BLOCK+0x24) /* Response Queue In */
#define BIU2400_RSPOUTP (BIU_BLOCK+0x28) /* Response Queue Out */
#define BIU2400_PRI_RQINP (BIU_BLOCK+0x2C) /* Priority Request Q In */
#define BIU2400_PRI_RSPINP (BIU_BLOCK+0x30) /* Priority Request Q Out */
#define BIU2400_ATIO_RSPINP (BIU_BLOCK+0x3C) /* ATIO Queue In */
#define BIU2400_ATIO_REQINP (BIU_BLOCK+0x40) /* ATIO Queue Out */
#define BIU2400_R2HSTSLO (BIU_BLOCK+0x44)
#define BIU2400_R2HSTSHI (BIU_BLOCK+0x46)
#define BIU2400_HCCR (BIU_BLOCK+0x48)
#define BIU2400_GPIOD (BIU_BLOCK+0x4C)
#define BIU2400_GPIOE (BIU_BLOCK+0x50)
#define BIU2400_HSEMA (BIU_BLOCK+0x58)
/* BIU2400_FLASH_ADDR definitions */
#define BIU2400_FLASH_DFLAG (1 << 30)
/* BIU2400_CSR definitions */
#define BIU2400_NVERR (1 << 18)
#define BIU2400_DMA_ACTIVE (1 << 17) /* RO */
#define BIU2400_DMA_STOP (1 << 16)
#define BIU2400_FUNCTION (1 << 15) /* RO */
#define BIU2400_PCIX_MODE(x) (((x) >> 8) & 0xf) /* RO */
#define BIU2400_CSR_64BIT (1 << 2) /* RO */
#define BIU2400_FLASH_ENABLE (1 << 1)
#define BIU2400_SOFT_RESET (1 << 0)
/* BIU2400_ICR definitions */
#define BIU2400_ICR_ENA_RISC_INT 0x8
#define BIU2400_IMASK (BIU2400_ICR_ENA_RISC_INT)
/* BIU2400_ISR definitions */
#define BIU2400_ISR_RISC_INT 0x8
#define BIU2400_R2HST_INTR BIU_R2HST_INTR
#define BIU2400_R2HST_PAUSED BIU_R2HST_PAUSED
#define BIU2400_R2HST_ISTAT_MASK 0x1f
/* interrupt status meanings */
#define ISP2400R2HST_ROM_MBX_OK 0x1 /* ROM mailbox cmd done ok */
#define ISP2400R2HST_ROM_MBX_FAIL 0x2 /* ROM mailbox cmd done fail */
#define ISP2400R2HST_MBX_OK 0x10 /* mailbox cmd done ok */
#define ISP2400R2HST_MBX_FAIL 0x11 /* mailbox cmd done fail */
#define ISP2400R2HST_ASYNC_EVENT 0x12 /* Async Event */
#define ISP2400R2HST_RSPQ_UPDATE 0x13 /* Response Queue Update */
#define ISP2400R2HST_ATIO_RSPQ_UPDATE 0x1C /* ATIO Response Queue Update */
#define ISP2400R2HST_ATIO_RQST_UPDATE 0x1D /* ATIO Request Queue Update */
/* BIU2400_HCCR definitions */
#define HCCR_2400_CMD_NOP (0x0 << 28)
#define HCCR_2400_CMD_RESET (0x1 << 28)
#define HCCR_2400_CMD_CLEAR_RESET (0x2 << 28)
#define HCCR_2400_CMD_PAUSE (0x3 << 28)
#define HCCR_2400_CMD_RELEASE (0x4 << 28)
#define HCCR_2400_CMD_SET_HOST_INT (0x5 << 28)
#define HCCR_2400_CMD_CLEAR_HOST_INT (0x6 << 28)
#define HCCR_2400_CMD_CLEAR_RISC_INT (0xA << 28)
#define HCCR_2400_RISC_ERR(x) (((x) >> 12) & 0x7) /* RO */
#define HCCR_2400_RISC2HOST_INT (1 << 6) /* RO */
#define HCCR_2400_RISC_RESET (1 << 5) /* RO */
/*
* Mailbox Block Register Offsets
*/
@ -377,7 +449,7 @@
* Strictly speaking, it's
* SCSI && 2100 : 8 MBOX registers
* 2200: 24 MBOX registers
* 2300: 32 MBOX registers
* 2300/2400: 32 MBOX registers
*/
#define MBOX_OFF(n) (MBOX_BLOCK + ((n) << 1))
#define NMBOX(isp) \
@ -389,9 +461,15 @@
#define MAX_MAILBOX(isp) ((IS_FC(isp))? 12 : 8)
#define MAILBOX_STORAGE 12
/* if timeout == 0, then default timeout is picked */
#define MBCMD_DEFAULT_TIMEOUT 100000 /* 100 ms */
typedef struct {
uint16_t param[MAILBOX_STORAGE];
uint16_t ibits, obits;
uint16_t ibits;
uint16_t obits;
uint32_t : 28,
logval : 4;
uint32_t timeout;
} mbreg_t;
/*
@ -672,6 +750,7 @@ typedef struct {
#define PCI_HCCR_CMD_PARITY_ERR 0xE000 /* Generate parity error */
#define HCCR_CMD_TEST_MODE 0xF000 /* Set Test Mode */
#define ISP2100_HCCR_PARITY_ENABLE_2 0x0400
#define ISP2100_HCCR_PARITY_ENABLE_1 0x0200
#define ISP2100_HCCR_PARITY_ENABLE_0 0x0100
@ -687,6 +766,25 @@ typedef struct {
#define PCI_HCCR_BIOS 0x0001 /* W : BIOS enable */
/*
* Defines for Interrupts
*/
#define ISP_INTS_ENABLED(isp) \
((IS_SCSI(isp))? \
(ISP_READ(isp, BIU_ICR) & BIU_IMASK) : \
(IS_24XX(isp)? (ISP_READ(isp, BIU2400_ICR) & BIU2400_IMASK) : \
(ISP_READ(isp, BIU_ICR) & BIU2100_IMASK)))
#define ISP_ENABLE_INTS(isp) \
(IS_SCSI(isp) ? \
ISP_WRITE(isp, BIU_ICR, BIU_IMASK) : \
(IS_24XX(isp) ? \
(ISP_WRITE(isp, BIU2400_ICR, BIU2400_IMASK)) : \
(ISP_WRITE(isp, BIU_ICR, BIU2100_IMASK))))
#define ISP_DISABLE_INTS(isp) \
IS_24XX(isp)? ISP_WRITE(isp, BIU2400_ICR, 0) : ISP_WRITE(isp, BIU_ICR, 0)
/*
* NVRAM Definitions (PCI cards only)
*/
@ -736,9 +834,9 @@ typedef struct {
#define ISP_NVRAM_FAST_MTTR_ENABLE(c) ISPBSMX(c, 22, 0, 0x01)
#define ISP_NVRAM_TARGOFF 28
#define ISP_NVARM_TARGSIZE 6
#define ISP_NVRAM_TARGSIZE 6
#define _IxT(tgt, tidx) \
(ISP_NVRAM_TARGOFF + (ISP_NVARM_TARGSIZE * (tgt)) + (tidx))
(ISP_NVRAM_TARGOFF + (ISP_NVRAM_TARGSIZE * (tgt)) + (tidx))
#define ISP_NVRAM_TGT_RENEG(c, t) ISPBSMX(c, _IxT(t, 0), 0, 0x01)
#define ISP_NVRAM_TGT_QFRZ(c, t) ISPBSMX(c, _IxT(t, 0), 1, 0x01)
#define ISP_NVRAM_TGT_ARQ(c, t) ISPBSMX(c, _IxT(t, 0), 2, 0x01)
@ -937,7 +1035,7 @@ typedef struct {
ISPBSMX(c, _IxT16(t, 4, (b)), 7, 0x01)
/*
* Qlogic 2XXX NVRAM is an array of 256 bytes.
* Qlogic 2100 thru 2300 NVRAM is an array of 256 bytes.
*
* Some portion of the front of this is for general RISC engine parameters,
* mostly reflecting the state of the last INITIALIZE FIRMWARE mailbox command.
@ -1011,6 +1109,51 @@ typedef struct {
#define ISP2100_HBA_FEATURES(c) ((c)[232] | ((c)[233] << 8))
/*
* Qlogic 2400 NVRAM is an array of 512 bytes with a 32 bit checksum.
*/
#define ISP2400_NVRAM_PORT0_ADDR 0x80
#define ISP2400_NVRAM_PORT1_ADDR 0x180
#define ISP2400_NVRAM_SIZE 512
#define ISP2400_NVRAM_VERSION(c) ((c)[4] | ((c)[5] << 8))
#define ISP2400_NVRAM_MAXFRAMELENGTH(c) (((c)[12]) | ((c)[13] << 8))
#define ISP2400_NVRAM_EXECUTION_THROTTLE(c) (((c)[14]) | ((c)[15] << 8))
#define ISP2400_NVRAM_EXCHANGE_COUNT(c) (((c)[16]) | ((c)[17] << 8))
#define ISP2400_NVRAM_HARDLOOPID(c) ((c)[18] | ((c)[19] << 8))
#define ISP2400_NVRAM_PORT_NAME(c) (\
(((uint64_t)(c)[20]) << 56) | \
(((uint64_t)(c)[21]) << 48) | \
(((uint64_t)(c)[22]) << 40) | \
(((uint64_t)(c)[23]) << 32) | \
(((uint64_t)(c)[24]) << 24) | \
(((uint64_t)(c)[25]) << 16) | \
(((uint64_t)(c)[26]) << 8) | \
(((uint64_t)(c)[27]) << 0))
#define ISP2400_NVRAM_NODE_NAME(c) (\
(((uint64_t)(c)[28]) << 56) | \
(((uint64_t)(c)[29]) << 48) | \
(((uint64_t)(c)[30]) << 40) | \
(((uint64_t)(c)[31]) << 32) | \
(((uint64_t)(c)[32]) << 24) | \
(((uint64_t)(c)[33]) << 16) | \
(((uint64_t)(c)[34]) << 8) | \
(((uint64_t)(c)[35]) << 0))
#define ISP2400_NVRAM_LOGIN_RETRY_CNT(c) ((c)[36] | ((c)[37] << 8))
#define ISP2400_NVRAM_LINK_DOWN_ON_NOS(c) ((c)[38] | ((c)[39] << 8))
#define ISP2400_NVRAM_INTERRUPT_DELAY(c) ((c)[40] | ((c)[41] << 8))
#define ISP2400_NVRAM_LOGIN_TIMEOUT(c) ((c)[42] | ((c)[43] << 8))
#define ISP2400_NVRAM_FIRMWARE_OPTIONS1(c) \
((c)[44] | ((c)[45] << 8) | ((c)[46] << 16) | ((c)[47] << 24))
#define ISP2400_NVRAM_FIRMWARE_OPTIONS2(c) \
((c)[48] | ((c)[49] << 8) | ((c)[50] << 16) | ((c)[51] << 24))
#define ISP2400_NVRAM_FIRMWARE_OPTIONS3(c) \
((c)[52] | ((c)[53] << 8) | ((c)[54] << 16) | ((c)[55] << 24))
/*
* Firmware Crash Dump
*

View File

@ -31,20 +31,24 @@
#define _ISPVAR_H
#if defined(__NetBSD__) || defined(__OpenBSD__)
#include <dev/ic/isp_stds.h>
#include <dev/ic/ispmbox.h>
#endif
#ifdef __FreeBSD__
#include <dev/isp/isp_stds.h>
#include <dev/isp/ispmbox.h>
#endif
#ifdef __linux__
#include "isp_stds.h"
#include "ispmbox.h"
#endif
#ifdef __svr4__
#include "isp_stds.h"
#include "ispmbox.h"
#endif
#define ISP_CORE_VERSION_MAJOR 2
#define ISP_CORE_VERSION_MINOR 11
#define ISP_CORE_VERSION_MAJOR 3
#define ISP_CORE_VERSION_MINOR 0
/*
* Vector for bus specific code to provide specific services.
@ -52,17 +56,17 @@
typedef struct ispsoftc ispsoftc_t;
struct ispmdvec {
int (*dv_rd_isr)
(ispsoftc_t *, uint16_t *, uint16_t *, uint16_t *);
uint16_t (*dv_rd_reg) (ispsoftc_t *, int);
void (*dv_wr_reg) (ispsoftc_t *, int, uint16_t);
(ispsoftc_t *, uint32_t *, uint16_t *, uint16_t *);
uint32_t (*dv_rd_reg) (ispsoftc_t *, int);
void (*dv_wr_reg) (ispsoftc_t *, int, uint32_t);
int (*dv_mbxdma) (ispsoftc_t *);
int (*dv_dmaset)
(ispsoftc_t *, XS_T *, ispreq_t *, uint16_t *, uint16_t);
void (*dv_dmaclr) (ispsoftc_t *, XS_T *, uint16_t);
(ispsoftc_t *, XS_T *, ispreq_t *, uint32_t *, uint32_t);
void (*dv_dmaclr) (ispsoftc_t *, XS_T *, uint32_t);
void (*dv_reset0) (ispsoftc_t *);
void (*dv_reset1) (ispsoftc_t *);
void (*dv_dregs) (ispsoftc_t *, const char *);
uint16_t *dv_ispfw; /* ptr to f/w */
void * dv_ispfw; /* ptr to f/w */
uint16_t dv_conf1;
uint16_t dv_clock; /* clock frequency */
};
@ -122,6 +126,7 @@ struct ispmdvec {
#define SYNC_SFORDEV 2 /* scratch, sync for ISP */
#define SYNC_SFORCPU 3 /* scratch, sync for CPU */
#define SYNC_REG 4 /* for registers */
#define SYNC_ATIOQ 5 /* atio result queue (24xx) */
/*
* Request/Response Queue defines and macros.
@ -148,7 +153,7 @@ struct ispmdvec {
#define ISP_ADD_REQUEST(isp, nxti) \
MEMORYBARRIER(isp, SYNC_REQUEST, isp->isp_reqidx, QENTRY_LEN); \
WRITE_REQUEST_QUEUE_IN_POINTER(isp, nxti); \
ISP_WRITE(isp, isp->isp_rqstinrp, nxti); \
isp->isp_reqidx = nxti
/*
@ -161,6 +166,7 @@ typedef struct {
isp_cmd_dma_burst_enable: 1,
isp_data_dma_burst_enabl: 1,
isp_fifo_threshold : 3,
isp_ptisp : 1,
isp_ultramode : 1,
isp_diffmode : 1,
isp_lvdmode : 1,
@ -222,32 +228,125 @@ typedef struct {
/*
* Fibre Channel Specifics
*/
#define FL_PORT_ID 0x7e /* FL_Port Special ID */
#define FC_PORT_ID 0x7f /* Fabric Controller Special ID */
#define FC_SNS_ID 0x80 /* SNS Server Special ID */
/* These are for 2100/2200/2300 cards */
#define FL_ID 0x7e /* FL_Port Special ID */
#define SNS_ID 0x80 /* SNS Server Special ID */
#define NPH_MAX 0xfe
/* #define ISP_USE_GA_NXT 1 */ /* Use GA_NXT with switches */
#ifndef GA_NXT_MAX
#define GA_NXT_MAX 256
#endif
/* These are for 24XX cards */
#define NPH_RESERVED 0x7F0 /* begin of reserved N-port handles */
#define NPH_MGT_ID 0x7FA /* Management Server Special ID */
#define NPH_SNS_ID 0x7FC /* SNS Server Special ID */
#define NPH_FL_ID 0x7FE /* FL Port Special ID */
#define NPH_MAX_24XX 0x800
/*
* Limit for devices on an arbitrated loop.
*/
#define LOCAL_LOOP_LIM 126
/*
* Special Port IDs
*/
#define MANAGEMENT_PORT_ID 0xFFFFFA
#define SNS_PORT_ID 0xFFFFFC
#define FABRIC_PORT_ID 0xFFFFFE
/*
* FC Port Database entry.
*
* It has a handle that the f/w uses to address commands to a device.
* This handle's value may be assigned by the firmware (e.g., for local loop
* devices) or by the driver (e.g., for fabric devices).
*
* It has a state. If the state if VALID, that means that we've logged into
* the device. We also *may* have a initiator map index entry. This is a value
* from 0..MAX_FC_TARG that is used to index into the isp_ini_map array. If
* the value therein is non-zero, then that value minus one is used to index
* into the Port Database to find the handle for forming commands. There is
* back-index minus one value within to Port Database entry that tells us
* which entry in isp_ini_map points to us (to avoid searching).
*
* Local loop devices the firmware automatically performs PLOGI on for us
* (which is why that handle is imposed upon us). Fabric devices we assign
* a handle to and perform the PLOGI on.
*
* When a PORT DATABASE CHANGED asynchronous event occurs, we mark all VALID
* entries as PROBATIONAL. This allows us, if policy says to, just keep track
* of devices whose handles change but are otherwise the same device (and
* thus keep 'target' constant).
*
* In any case, we search all possible local loop handles. For each one that
* has a port database entity returned, we search for any PROBATIONAL entry
* that matches it and update as appropriate. Otherwise, as a new entry, we
* find room for it in the Port Database. We *try* and use the handle as the
* index to put it into the Database, but that's just an optimization. We mark
* the entry VALID and make sure that the target index is updated and correct.
*
* When we get done searching the local loop, we then search similarily for
* a list of devices we've gotten from the fabric name controller (if we're
* on a fabric). VALID marking is also done similarily.
*
* When all of this is done, we can march through the database and clean up
* any entry that is still PROBATIONAL (these represent devices which have
* departed). Then we're done and can resume normal operations.
*
* Negative invariants that we try and test for are:
*
* + There can never be two non-NIL entries with the same { Port, Node } WWN
* duples.
*
* + There can never be two non-NIL entries with the same handle.
*
* + There can never be two non-NIL entries which have the same ini_map_idx
* value.
*/
typedef struct {
uint32_t : 13,
uint16_t handle;
uint16_t ini_map_idx : 12,
autologin : 1, /* F/W does PLOGI/PLOGO */
state : 3;
uint32_t : 6,
roles : 2,
portid : 24;
uint32_t : 6,
new_roles : 2,
new_portid : 24;
uint64_t node_wwn;
uint64_t port_wwn;
} fcportdb_t;
#define FC_PORTDB_STATE_NIL 0
#define FC_PORTDB_STATE_PROBATIONAL 1
#define FC_PORTDB_STATE_DEAD 2
#define FC_PORTDB_STATE_CHANGED 3
#define FC_PORTDB_STATE_NEW 4
#define FC_PORTDB_STATE_PENDING_VALID 5
#define FC_PORTDB_STATE_VALID 7
/*
* FC card specific information
*/
typedef struct {
uint32_t : 10,
isp_tmode : 1,
isp_2klogin : 1,
isp_sccfw : 1,
isp_gbspeed : 3,
: 1,
isp_iid_set : 1,
loop_seen_once : 1,
: 1,
: 1,
isp_loopstate : 4, /* Current Loop State */
isp_fwstate : 4, /* ISP F/W state */
isp_gotdparms : 1,
isp_topo : 3,
isp_onfabric : 1;
loop_seen_once : 1;
uint32_t : 8,
isp_portid : 24; /* S_ID */
uint16_t isp_fwoptions;
uint16_t isp_xfwoptions;
uint16_t isp_zfwoptions;
uint16_t isp_iid; /* 'initiator' id */
uint16_t isp_loopid; /* hard loop id */
uint16_t isp_fwattr; /* firmware attributes */
uint16_t isp_execthrottle;
@ -258,34 +357,8 @@ typedef struct {
uint16_t isp_maxfrmlen;
uint64_t isp_nodewwn;
uint64_t isp_portwwn;
/*
* Port Data Base. This is indexed by 'target', which is invariate.
* However, elements within can move around due to loop changes,
* so the actual loop ID passed to the F/W is in this structure.
* The first time the loop is seen up, loopid will match the index
* (except for fabric nodes which are above mapped above FC_SNS_ID
* and are completely virtual), but subsequent LIPs can cause things
* to move around.
*/
struct lportdb {
uint32_t loopid : 16,
: 2,
fc4_type : 4,
last_fabric_dev : 1,
relogin : 1,
force_logout : 1,
was_fabric_dev : 1,
fabric_dev : 1,
loggedin : 1,
roles : 2,
tvalid : 1,
valid : 1;
uint32_t port_type : 8,
portid : 24;
uint64_t node_wwn;
uint64_t port_wwn;
} portdb[MAX_FC_TARG], tport[FC_PORT_ID];
fcportdb_t portdb[MAX_FC_TARG];
uint16_t isp_ini_map[MAX_FC_TARG];
/*
* Scratch DMA mapped in area to fetch Port Database stuff, etc.
*/
@ -308,10 +381,10 @@ typedef struct {
#define LOOP_NIL 0
#define LOOP_LIP_RCVD 1
#define LOOP_PDB_RCVD 2
#define LOOP_SCANNING_FABRIC 3
#define LOOP_FSCAN_DONE 4
#define LOOP_SCANNING_LOOP 5
#define LOOP_LSCAN_DONE 6
#define LOOP_SCANNING_LOOP 3
#define LOOP_LSCAN_DONE 4
#define LOOP_SCANNING_FABRIC 5
#define LOOP_FSCAN_DONE 6
#define LOOP_SYNCING_PDB 7
#define LOOP_READY 8
@ -350,7 +423,7 @@ struct ispsoftc {
uint32_t isp_clock : 8, /* input clock */
: 4,
isp_port : 1, /* 23XX only */
isp_port : 1, /* 23XX/24XX only */
isp_failed : 1, /* board failed */
isp_open : 1, /* opened (ioctl) */
isp_touched : 1, /* board ever seen? */
@ -361,10 +434,12 @@ struct ispsoftc {
uint32_t isp_confopts; /* config options */
uint16_t isp_rqstinrp; /* register for REQINP */
uint16_t isp_rqstoutrp; /* register for REQOUTP */
uint16_t isp_respinrp; /* register for RESINP */
uint16_t isp_respoutrp; /* register for RESOUTP */
uint32_t isp_rqstinrp; /* register for REQINP */
uint32_t isp_rqstoutrp; /* register for REQOUTP */
uint32_t isp_respinrp; /* register for RESINP */
uint32_t isp_respoutrp; /* register for RESOUTP */
uint32_t isp_atioinrp; /* register for ATIOINP */
uint32_t isp_atiooutrp; /* register for ATIOOUTP */
/*
* Instrumentation
@ -388,13 +463,13 @@ struct ispsoftc {
isp_sendmarker : 2, /* send a marker entry */
isp_update : 2, /* update parameters */
isp_nactive : 16; /* how many commands active */
volatile uint16_t isp_reqodx; /* index of last ISP pickup */
volatile uint16_t isp_reqidx; /* index of next request */
volatile uint16_t isp_residx; /* index of next result */
volatile uint16_t isp_resodx; /* index of next result */
volatile uint16_t isp_rspbsy;
volatile uint16_t isp_lasthdls; /* last handle seed */
volatile uint16_t isp_obits; /* mailbox command output */
volatile uint32_t isp_reqodx; /* index of last ISP pickup */
volatile uint32_t isp_reqidx; /* index of next request */
volatile uint32_t isp_residx; /* index of next result */
volatile uint32_t isp_resodx; /* index of next result */
volatile uint32_t isp_rspbsy;
volatile uint32_t isp_lasthdls; /* last handle seed */
volatile uint32_t isp_obits; /* mailbox command output */
volatile uint16_t isp_mboxtmp[MAILBOX_STORAGE];
volatile uint16_t isp_lastmbxcmd; /* last mbox command sent */
volatile uint16_t isp_mbxwrk0;
@ -422,6 +497,11 @@ struct ispsoftc {
void * isp_result;
XS_DMA_ADDR_T isp_rquest_dma;
XS_DMA_ADDR_T isp_result_dma;
#ifdef ISP_TARGET_MODE
/* for 24XX only */
void * isp_atioq;
XS_DMA_ADDR_T isp_atioq_dma;
#endif
};
#define SDPARAM(isp) ((sdparam *) (isp)->isp_param)
@ -454,6 +534,7 @@ struct ispsoftc {
#define ISP_CFG_OWNFSZ 0x400 /* override NVRAM frame size */
#define ISP_CFG_OWNLOOPID 0x800 /* override NVRAM loopid */
#define ISP_CFG_OWNEXCTHROTTLE 0x1000 /* override NVRAM execution throttle */
#define ISP_CFG_FOURGB 0x2000 /* force 4GB connection (24XX only) */
/*
* Prior to calling isp_reset for the first time, the outer layer
@ -491,6 +572,7 @@ struct ispsoftc {
*/
#define ISP_CODE_ORG 0x1000 /* default f/w code start */
#define ISP_CODE_ORG_2300 0x0800 /* ..except for 2300s */
#define ISP_CODE_ORG_2400 0x100000 /* ..and 2400s */
#define ISP_FW_REV(maj, min, mic) ((maj << 24) | (min << 16) | mic)
#define ISP_FW_MAJOR(code) ((code >> 24) & 0xff)
#define ISP_FW_MINOR(code) ((code >> 16) & 0xff)
@ -501,6 +583,8 @@ struct ispsoftc {
#define ISP_FW_MICROX(xp) (xp[2])
#define ISP_FW_NEWER_THAN(i, major, minor, micro) \
(ISP_FW_REVX((i)->isp_fwrev) > ISP_FW_REV(major, minor, micro))
#define ISP_FW_OLDER_THAN(i, major, minor, micro) \
(ISP_FW_REVX((i)->isp_fwrev) < ISP_FW_REV(major, minor, micro))
/*
* Bus (implementation) types
@ -539,7 +623,6 @@ struct ispsoftc {
#define ISP_HA_FC_2312 0x40
#define ISP_HA_FC_2322 0x50
#define ISP_HA_FC_2400 0x60
#define ISP_HA_FC_2422 0x61
#define IS_SCSI(isp) (isp->isp_type & ISP_HA_SCSI)
#define IS_1240(isp) (isp->isp_type == ISP_HA_SCSI_1240)
@ -557,8 +640,8 @@ 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_23XX(isp) \
((isp)->isp_type >= ISP_HA_FC_2300 && (isp)->isp_type < ISP_HA_FC_2400)
#define IS_23XX(isp) ((isp)->isp_type >= ISP_HA_FC_2300 && \
(isp)->isp_type < ISP_HA_FC_2400)
#define IS_2300(isp) ((isp)->isp_type == ISP_HA_FC_2300)
#define IS_2312(isp) ((isp)->isp_type == ISP_HA_FC_2312)
#define IS_2322(isp) ((isp)->isp_type == ISP_HA_FC_2322)
@ -567,10 +650,10 @@ struct ispsoftc {
/*
* DMA related macros
*/
#define DMA_WD3(x) ((((uint64_t)x) >> 48) & 0xffff)
#define DMA_WD2(x) ((((uint64_t)x) >> 32) & 0xffff)
#define DMA_WD1(x) (((x) >> 16) & 0xffff)
#define DMA_WD0(x) (((x) & 0xffff))
#define DMA_WD3(x) (((uint16_t)(((uint64_t)x) >> 48)) & 0xffff)
#define DMA_WD2(x) (((uint16_t)(((uint64_t)x) >> 32)) & 0xffff)
#define DMA_WD1(x) ((uint16_t)((x) >> 16) & 0xffff)
#define DMA_WD0(x) ((uint16_t)((x) & 0xffff))
#define DMA_LO32(x) ((uint32_t) (x))
#define DMA_HI32(x) ((uint32_t)(((uint64_t)x) >> 32))
@ -609,7 +692,7 @@ void isp_fw_dump(ispsoftc_t *isp);
* semaphore register and first mailbox register (if appropriate). This also
* means that most spurious/bogus interrupts not for us can be filtered first.
*/
void isp_intr(ispsoftc_t *, uint16_t, uint16_t, uint16_t);
void isp_intr(ispsoftc_t *, uint32_t, uint16_t, uint16_t);
/*
@ -672,7 +755,7 @@ typedef enum {
ISPCTL_SCAN_LOOP, /* (Re)scan Local Loop */
ISPCTL_PDB_SYNC, /* Synchronize Port Database */
ISPCTL_SEND_LIP, /* Send a LIP */
ISPCTL_GET_POSMAP, /* Get FC-AL position map */
ISPCTL_GET_PORTNAME, /* get portname from an N-port handle */
ISPCTL_RUN_MBOXCMD, /* run a mailbox command */
ISPCTL_TOGGLE_TMODE, /* toggle target mode */
ISPCTL_GET_PDB /* get a single port database entry */
@ -728,8 +811,10 @@ typedef enum {
ISPASYNC_LIP, /* LIP Received */
ISPASYNC_LOOP_RESET, /* Loop Reset Received */
ISPASYNC_CHANGE_NOTIFY, /* FC Change Notification */
ISPASYNC_FABRIC_DEV, /* FC Fabric Device Arrival */
ISPASYNC_PROMENADE, /* FC Objects coming && going */
ISPASYNC_DEV_ARRIVED, /* FC Device Arrival */
ISPASYNC_DEV_CHANGED, /* FC Device Change */
ISPASYNC_DEV_STAYED, /* FC Device Stayed the Same */
ISPASYNC_DEV_GONE, /* FC Device Depart */
ISPASYNC_TARGET_NOTIFY, /* target asynchronous notification event */
ISPASYNC_TARGET_ACTION, /* target action requested */
ISPASYNC_CONF_CHANGE, /* Platform Configuration Change */
@ -804,7 +889,7 @@ int isp_async(ispsoftc_t *, ispasync_t, void *);
* of the same object is consistent.
*
* MBOX_ACQUIRE(ispsoftc_t *) acquire lock on mailbox regs
* MBOX_WAIT_COMPLETE(ispsoftc_t *) wait for mailbox cmd to be done
* MBOX_WAIT_COMPLETE(ispsoftc_t *, mbreg_t *) wait for cmd to be done
* MBOX_NOTIFY_COMPLETE(ispsoftc_t *) notification of mbox cmd donee
* MBOX_RELEASE(ispsoftc_t *) release lock on mailbox regs
*