A large set of changes to handle dual bus adapters.
This commit is contained in:
parent
fff99b2c79
commit
d6302276db
@ -1,5 +1,5 @@
|
||||
/* $Id: isp_freebsd.c,v 1.16 1999/04/04 02:22:42 mjacob Exp $ */
|
||||
/* release_4_3_99 */
|
||||
/* $Id: isp_freebsd.c,v 1.17 1999/05/06 20:16:25 ken Exp $ */
|
||||
/* release_5_11_99 */
|
||||
/*
|
||||
* Platform (FreeBSD) dependent common attachment code for Qlogic adapters.
|
||||
*
|
||||
@ -44,11 +44,21 @@ static void isp_action __P((struct cam_sim *, union ccb *));
|
||||
void
|
||||
isp_attach(struct ispsoftc *isp)
|
||||
{
|
||||
int primary, secondary;
|
||||
struct ccb_setasync csa;
|
||||
struct cam_devq *devq;
|
||||
struct cam_sim *sim;
|
||||
struct cam_path *path;
|
||||
|
||||
/*
|
||||
* Create the device queue for our SIM.
|
||||
* Establish (in case of 12X0) which bus is the primary.
|
||||
*/
|
||||
|
||||
primary = 0;
|
||||
secondary = 1;
|
||||
|
||||
/*
|
||||
* Create the device queue for our SIM(s).
|
||||
*/
|
||||
devq = cam_simq_alloc(MAXISPREQUEST);
|
||||
if (devq == NULL) {
|
||||
@ -56,33 +66,72 @@ isp_attach(struct ispsoftc *isp)
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct our SIM entry
|
||||
* Construct our SIM entry.
|
||||
*/
|
||||
isp->isp_sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp,
|
||||
sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp,
|
||||
isp->isp_unit, 1, MAXISPREQUEST, devq);
|
||||
if (isp->isp_sim == NULL) {
|
||||
if (sim == NULL) {
|
||||
cam_simq_free(devq);
|
||||
return;
|
||||
}
|
||||
if (xpt_bus_register(isp->isp_sim, 0) != CAM_SUCCESS) {
|
||||
cam_sim_free(isp->isp_sim, TRUE);
|
||||
if (xpt_bus_register(sim, primary) != CAM_SUCCESS) {
|
||||
cam_sim_free(sim, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (xpt_create_path(&isp->isp_path, NULL, cam_sim_path(isp->isp_sim),
|
||||
if (xpt_create_path(&path, NULL, cam_sim_path(sim),
|
||||
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
||||
xpt_bus_deregister(cam_sim_path(isp->isp_sim));
|
||||
cam_sim_free(isp->isp_sim, TRUE);
|
||||
xpt_bus_deregister(cam_sim_path(sim));
|
||||
cam_sim_free(sim, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
xpt_setup_ccb(&csa.ccb_h, isp->isp_path, 5);
|
||||
xpt_setup_ccb(&csa.ccb_h, path, 5);
|
||||
csa.ccb_h.func_code = XPT_SASYNC_CB;
|
||||
csa.event_enable = AC_LOST_DEVICE;
|
||||
csa.callback = isp_cam_async;
|
||||
csa.callback_arg = isp->isp_sim;
|
||||
csa.callback_arg = sim;
|
||||
xpt_action((union ccb *)&csa);
|
||||
isp->isp_sim = sim;
|
||||
isp->isp_path = path;
|
||||
|
||||
/*
|
||||
* If we have a second channel, construct SIM entry for that.
|
||||
*/
|
||||
if (IS_12X0(isp)) {
|
||||
sim = cam_sim_alloc(isp_action, isp_poll, "isp", isp,
|
||||
isp->isp_unit, 1, MAXISPREQUEST, devq);
|
||||
if (sim == NULL) {
|
||||
xpt_bus_deregister(cam_sim_path(isp->isp_sim));
|
||||
xpt_free_path(isp->isp_path);
|
||||
cam_simq_free(devq);
|
||||
return;
|
||||
}
|
||||
if (xpt_bus_register(sim, secondary) != CAM_SUCCESS) {
|
||||
xpt_bus_deregister(cam_sim_path(isp->isp_sim));
|
||||
xpt_free_path(isp->isp_path);
|
||||
cam_sim_free(sim, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (xpt_create_path(&path, NULL, cam_sim_path(sim),
|
||||
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
||||
xpt_bus_deregister(cam_sim_path(isp->isp_sim));
|
||||
xpt_free_path(isp->isp_path);
|
||||
xpt_bus_deregister(cam_sim_path(sim));
|
||||
cam_sim_free(sim, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
xpt_setup_ccb(&csa.ccb_h, path, 5);
|
||||
csa.ccb_h.func_code = XPT_SASYNC_CB;
|
||||
csa.event_enable = AC_LOST_DEVICE;
|
||||
csa.callback = isp_cam_async;
|
||||
csa.callback_arg = sim;
|
||||
xpt_action((union ccb *)&csa);
|
||||
isp->isp_sim2 = sim;
|
||||
isp->isp_path2 = path;
|
||||
}
|
||||
if (isp->isp_state == ISP_INITSTATE)
|
||||
isp->isp_state = ISP_RUNSTATE;
|
||||
}
|
||||
@ -102,6 +151,10 @@ isp_cam_async(void *cbarg, u_int32_t code, struct cam_path *path, void *arg)
|
||||
sdparam *sdp = isp->isp_param;
|
||||
int s, tgt = xpt_path_target_id(path);
|
||||
|
||||
s = splcam();
|
||||
sdp += cam_sim_bus(sim);
|
||||
isp->isp_update |= (1 << cam_sim_bus(sim));
|
||||
|
||||
nflags = DPARM_SAFE_DFLT;
|
||||
if (ISP_FW_REVX(isp->isp_fwrev) >=
|
||||
ISP_FW_REV(7, 55, 0)) {
|
||||
@ -110,11 +163,9 @@ isp_cam_async(void *cbarg, u_int32_t code, struct cam_path *path, void *arg)
|
||||
oflags = sdp->isp_devparam[tgt].dev_flags;
|
||||
sdp->isp_devparam[tgt].dev_flags = nflags;
|
||||
sdp->isp_devparam[tgt].dev_update = 1;
|
||||
|
||||
s = splcam();
|
||||
(void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL);
|
||||
(void) splx(s);
|
||||
sdp->isp_devparam[tgt].dev_flags = oflags;
|
||||
(void) splx(s);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -222,13 +273,6 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
|
||||
xpt_done(ccb);
|
||||
break;
|
||||
}
|
||||
|
||||
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_INFO,
|
||||
("cdb[0]=0x%x dlen%d\n",
|
||||
(ccb->ccb_h.flags & CAM_CDB_POINTER)?
|
||||
ccb->csio.cdb_io.cdb_ptr[0]:
|
||||
ccb->csio.cdb_io.cdb_bytes[0], ccb->csio.dxfer_len));
|
||||
|
||||
s = splcam();
|
||||
DISABLE_INTS(isp);
|
||||
switch (ispscsicmd((ISP_SCSI_XFER_T *) ccb)) {
|
||||
@ -271,10 +315,9 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
|
||||
break;
|
||||
|
||||
case XPT_RESET_DEV: /* BDR the specified SCSI device */
|
||||
tgt = ccb->ccb_h.target_id;
|
||||
tgt = ccb->ccb_h.target_id; /* XXX: Which Bus? */
|
||||
s = splcam();
|
||||
error =
|
||||
isp_control(isp, ISPCTL_RESET_DEV, (void *)(intptr_t) tgt);
|
||||
error = isp_control(isp, ISPCTL_RESET_DEV, &tgt);
|
||||
(void) splx(s);
|
||||
if (error) {
|
||||
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
|
||||
@ -305,7 +348,9 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
|
||||
} else {
|
||||
sdparam *sdp = isp->isp_param;
|
||||
u_int16_t *dptr;
|
||||
int bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path));
|
||||
|
||||
sdp += bus;
|
||||
#if 0
|
||||
if (cts->flags & CCB_TRANS_CURRENT_SETTINGS)
|
||||
dptr = &sdp->isp_devparam[tgt].cur_dflags;
|
||||
@ -364,8 +409,8 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
|
||||
} else {
|
||||
*dptr &= ~DPARM_SYNC;
|
||||
}
|
||||
IDPRINTF(3, ("%s: %d set %s period 0x%x offset 0x%x"
|
||||
" flags 0x%x\n", isp->isp_name, tgt,
|
||||
IDPRINTF(3, ("%s: %d.%d set %s period 0x%x offset 0x%x"
|
||||
" flags 0x%x\n", isp->isp_name, bus, tgt,
|
||||
(cts->flags & CCB_TRANS_CURRENT_SETTINGS)?
|
||||
"current" : "user",
|
||||
sdp->isp_devparam[tgt].sync_period,
|
||||
@ -373,7 +418,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
|
||||
sdp->isp_devparam[tgt].dev_flags));
|
||||
s = splcam();
|
||||
sdp->isp_devparam[tgt].dev_update = 1;
|
||||
isp->isp_update = 1;
|
||||
isp->isp_update |= (1 << bus);
|
||||
(void) isp_control(isp, ISPCTL_UPDATE_PARAMS, NULL);
|
||||
(void) splx(s);
|
||||
}
|
||||
@ -403,7 +448,9 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
|
||||
} else {
|
||||
sdparam *sdp = isp->isp_param;
|
||||
u_int16_t dval, pval, oval;
|
||||
int bus = cam_sim_bus(xpt_path_sim(cts->ccb_h.path));
|
||||
|
||||
sdp += bus;
|
||||
if (cts->flags & CCB_TRANS_CURRENT_SETTINGS) {
|
||||
dval = sdp->isp_devparam[tgt].cur_dflags;
|
||||
oval = sdp->isp_devparam[tgt].cur_offset;
|
||||
@ -439,8 +486,8 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
|
||||
CCB_TRANS_SYNC_OFFSET_VALID;
|
||||
}
|
||||
splx(s);
|
||||
IDPRINTF(3, ("%s: %d get %s period 0x%x offset 0x%x"
|
||||
" flags 0x%x\n", isp->isp_name, tgt,
|
||||
IDPRINTF(3, ("%s: %d.%d get %s period 0x%x offset 0x%x"
|
||||
" flags 0x%x\n", isp->isp_name, bus, tgt,
|
||||
(cts->flags & CCB_TRANS_CURRENT_SETTINGS)?
|
||||
"current" : "user", pval, oval, dval));
|
||||
}
|
||||
@ -478,13 +525,16 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
|
||||
break;
|
||||
}
|
||||
case XPT_RESET_BUS: /* Reset the specified bus */
|
||||
tgt = cam_sim_bus(sim);
|
||||
s = splcam();
|
||||
error = isp_control(isp, ISPCTL_RESET_BUS, NULL);
|
||||
error = isp_control(isp, ISPCTL_RESET_BUS, &tgt);
|
||||
(void) splx(s);
|
||||
if (error)
|
||||
ccb->ccb_h.status = CAM_REQ_CMP_ERR;
|
||||
else {
|
||||
if (isp->isp_path != NULL)
|
||||
if (cam_sim_bus(sim) && isp->isp_path2 != NULL)
|
||||
xpt_async(AC_BUS_RESET, isp->isp_path2, NULL);
|
||||
else if (isp->isp_path != NULL)
|
||||
xpt_async(AC_BUS_RESET, isp->isp_path, NULL);
|
||||
ccb->ccb_h.status = CAM_REQ_CMP;
|
||||
}
|
||||
@ -523,9 +573,10 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
|
||||
*/
|
||||
cpi->base_transfer_speed = 100000;
|
||||
} else {
|
||||
sdparam *sdp = isp->isp_param;
|
||||
sdp += cam_sim_bus(xpt_path_sim(cpi->ccb_h.path));
|
||||
cpi->hba_misc = 0;
|
||||
cpi->initiator_id =
|
||||
((sdparam *)isp->isp_param)->isp_initiator_id;
|
||||
cpi->initiator_id = sdp->isp_initiator_id;
|
||||
cpi->max_target = MAX_TARGETS-1;
|
||||
if (ISP_FW_REVX(isp->isp_fwrev) >=
|
||||
ISP_FW_REV(7, 55, 0)) {
|
||||
@ -603,7 +654,7 @@ isp_async(isp, cmd, arg)
|
||||
ispasync_t cmd;
|
||||
void *arg;
|
||||
{
|
||||
int rv = 0;
|
||||
int bus, rv = 0;
|
||||
switch (cmd) {
|
||||
case ISPASYNC_NEW_TGT_PARAMS:
|
||||
if (isp->isp_type & ISP_HA_SCSI) {
|
||||
@ -613,16 +664,18 @@ isp_async(isp, cmd, arg)
|
||||
struct cam_path *tmppath;
|
||||
|
||||
tgt = *((int *)arg);
|
||||
bus = (tgt >> 16) & 0xffff;
|
||||
tgt &= 0xffff;
|
||||
sdp += bus;
|
||||
if (xpt_create_path(&tmppath, NULL,
|
||||
cam_sim_path(isp->isp_sim), tgt,
|
||||
CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
||||
cam_sim_path(bus? isp->isp_sim2 : isp->isp_sim),
|
||||
tgt, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
||||
xpt_print_path(isp->isp_path);
|
||||
printf("isp_async cannot make temp path for "
|
||||
"target %d\n", tgt);
|
||||
"target %d bus %d\n", tgt, bus);
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
flags = sdp->isp_devparam[tgt].cur_dflags;
|
||||
neg.valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
|
||||
if (flags & DPARM_DISC) {
|
||||
@ -641,17 +694,21 @@ isp_async(isp, cmd, arg)
|
||||
CCB_TRANS_SYNC_RATE_VALID |
|
||||
CCB_TRANS_SYNC_OFFSET_VALID;
|
||||
}
|
||||
IDPRINTF(3, ("%s: New params tgt %d period 0x%x "
|
||||
"offset 0x%x flags 0x%x\n", isp->isp_name, tgt,
|
||||
neg.sync_period, neg.sync_offset, flags));
|
||||
IDPRINTF(3, ("%s: NEW_TGT_PARAMS bus %d tgt %d period "
|
||||
"0x%x offset 0x%x flags 0x%x\n", isp->isp_name,
|
||||
bus, tgt, neg.sync_period, neg.sync_offset, flags));
|
||||
xpt_setup_ccb(&neg.ccb_h, tmppath, 1);
|
||||
xpt_async(AC_TRANSFER_NEG, tmppath, &neg);
|
||||
xpt_free_path(tmppath);
|
||||
}
|
||||
break;
|
||||
case ISPASYNC_BUS_RESET:
|
||||
printf("%s: SCSI bus reset detected\n", isp->isp_name);
|
||||
if (isp->isp_path) {
|
||||
bus = *((int *)arg);
|
||||
printf("%s: SCSI bus reset on bus %d detected\n",
|
||||
isp->isp_name, bus);
|
||||
if (bus > 0 && isp->isp_path2) {
|
||||
xpt_async(AC_BUS_RESET, isp->isp_path2, NULL);
|
||||
} else if (isp->isp_path) {
|
||||
xpt_async(AC_BUS_RESET, isp->isp_path, NULL);
|
||||
}
|
||||
break;
|
||||
@ -744,15 +801,12 @@ isp_async(isp, cmd, arg)
|
||||
|
||||
|
||||
/*
|
||||
* Free any associated resources prior to decommissioning and
|
||||
* set the card to a known state (so it doesn't wake up and kick
|
||||
* us when we aren't expecting it to).
|
||||
*
|
||||
* Locks are held before coming here.
|
||||
*/
|
||||
void
|
||||
isp_uninit(struct ispsoftc *isp)
|
||||
{
|
||||
ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
|
||||
DISABLE_INTS(isp);
|
||||
}
|
||||
#else
|
||||
@ -801,11 +855,12 @@ isp_attach(struct ispsoftc *isp)
|
||||
((fcparam *)isp->isp_param)->isp_loopid;
|
||||
scbus->maxtarg = MAX_FC_TARG-1;
|
||||
} else {
|
||||
int tmp = 0; /* XXXX: Which Bus? */
|
||||
isp->isp_osinfo.delay_throttle_count = 1;
|
||||
isp->isp_osinfo._link.adapter_targ =
|
||||
((sdparam *)isp->isp_param)->isp_initiator_id;
|
||||
scbus->maxtarg = MAX_TARGETS-1;
|
||||
(void) isp_control(isp, ISPCTL_RESET_BUS, NULL);
|
||||
(void) isp_control(isp, ISPCTL_RESET_BUS, &tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1121,6 +1176,7 @@ isp_uninit(isp)
|
||||
/*
|
||||
* Leave with interrupts disabled.
|
||||
*/
|
||||
ISP_WRITE(isp, HCCR, HCCR_CMD_RESET);
|
||||
DISABLE_INTS(isp);
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user