MFp4: Large set of CAM inprovements.
- Unify bus reset/probe sequence. Whenever bus attached at boot or later, CAM will automatically reset and scan it. It allows to remove duplicate code from many drivers. - Any bus, attached before CAM completed it's boot-time initialization, will equally join to the process, delaying boot if needed. - New kern.cam.boot_delay loader tunable should help controllers that are still unable to register their buses in time (such as slow USB/ PCCard/ CardBus devices), by adding one more event to wait on boot. - To allow synchronization between different CAM levels, concept of requests priorities was extended. Priorities now split between several "run levels". Device can be freezed at specified level, allowing higher priority requests to pass. For example, no payload requests allowed, until PMP driver enable port. ATA XPT negotiate transfer parameters, periph driver configure caching and so on. - Frozen requests are no more counted by request allocation scheduler. It fixes deadlocks, when frozen low priority payload requests occupying slots, required by higher levels to manage theit execution. - Two last changes were holding proper ATA reinitialization and error recovery implementation. Now it is done: SATA controllers and Port Multipliers now implement automatic hot-plug and should correctly recover from timeouts and bus resets. - Improve SCSI error recovery for devices on buses without automatic sense reporting, such as ATAPI or USB. For example, it allows CAM to wait, while CD drive loads disk, instead of immediately return error status. - Decapitalize diagnostic messages and make them more readable and sensible. - Teach PMP driver to limit maximum speed on fan-out ports. - Make boot wait for PMP scan completes, and make rescan more reliable. - Fix pass driver, to return CCB to user level in case of error. - Increase number of retries in cd driver, as device may return several UAs.
This commit is contained in:
parent
e59faa5014
commit
83c5d981ac
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=203108
@ -198,7 +198,7 @@ ata_command_sbuf(struct ccb_ataio *ataio, struct sbuf *sb)
|
||||
{
|
||||
char cmd_str[(12 * 3) + 1];
|
||||
|
||||
sbuf_printf(sb, "CMD: %s: %s",
|
||||
sbuf_printf(sb, "%s. ACB: %s",
|
||||
ata_op_string(&ataio->cmd),
|
||||
ata_cmd_string(&ataio->cmd, cmd_str, sizeof(cmd_str)));
|
||||
|
||||
@ -212,7 +212,7 @@ int
|
||||
ata_status_sbuf(struct ccb_ataio *ataio, struct sbuf *sb)
|
||||
{
|
||||
|
||||
sbuf_printf(sb, "ATA Status: %02x (%s%s%s%s%s%s%s%s)",
|
||||
sbuf_printf(sb, "ATA status: %02x (%s%s%s%s%s%s%s%s)",
|
||||
ataio->res.status,
|
||||
(ataio->res.status & 0x80) ? "BSY " : "",
|
||||
(ataio->res.status & 0x40) ? "DRDY " : "",
|
||||
@ -223,7 +223,7 @@ ata_status_sbuf(struct ccb_ataio *ataio, struct sbuf *sb)
|
||||
(ataio->res.status & 0x02) ? "IDX " : "",
|
||||
(ataio->res.status & 0x01) ? "ERR" : "");
|
||||
if (ataio->res.status & 1) {
|
||||
sbuf_printf(sb, ", Error: %02x (%s%s%s%s%s%s%s%s)",
|
||||
sbuf_printf(sb, ", error: %02x (%s%s%s%s%s%s%s%s)",
|
||||
ataio->res.error,
|
||||
(ataio->res.error & 0x80) ? "ICRC " : "",
|
||||
(ataio->res.error & 0x40) ? "UNC " : "",
|
||||
|
@ -689,7 +689,7 @@ adaregister(struct cam_periph *periph, void *arg)
|
||||
|
||||
/* Check if the SIM does not want queued commands */
|
||||
bzero(&cpi, sizeof(cpi));
|
||||
xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NONE);
|
||||
cpi.ccb_h.func_code = XPT_PATH_INQ;
|
||||
xpt_action((union ccb *)&cpi);
|
||||
if (cpi.ccb_h.status != CAM_REQ_CMP ||
|
||||
|
@ -98,6 +98,9 @@ struct pmp_softc {
|
||||
int reset;
|
||||
int frozen;
|
||||
int restart;
|
||||
int events;
|
||||
#define PMP_EV_RESET 1
|
||||
#define PMP_EV_RESCAN 2
|
||||
union ccb saved_ccb;
|
||||
struct task sysctl_task;
|
||||
struct sysctl_ctx_list sysctl_ctx;
|
||||
@ -179,7 +182,8 @@ pmpfreeze(struct cam_periph *periph, int mask)
|
||||
i, 0) == CAM_REQ_CMP) {
|
||||
softc->frozen |= (1 << i);
|
||||
xpt_acquire_device(dpath->device);
|
||||
cam_freeze_devq(dpath);
|
||||
cam_freeze_devq_arg(dpath,
|
||||
RELSIM_RELEASE_RUNLEVEL, CAM_RL_BUS + 1);
|
||||
xpt_free_path(dpath);
|
||||
}
|
||||
}
|
||||
@ -200,7 +204,8 @@ pmprelease(struct cam_periph *periph, int mask)
|
||||
xpt_path_path_id(periph->path),
|
||||
i, 0) == CAM_REQ_CMP) {
|
||||
softc->frozen &= ~(1 << i);
|
||||
cam_release_devq(dpath, 0, 0, 0, FALSE);
|
||||
cam_release_devq(dpath,
|
||||
RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_BUS + 1, FALSE);
|
||||
xpt_release_device(dpath->device);
|
||||
xpt_free_path(dpath);
|
||||
}
|
||||
@ -298,19 +303,20 @@ pmpasync(void *callback_arg, u_int32_t code,
|
||||
case AC_BUS_RESET:
|
||||
softc = (struct pmp_softc *)periph->softc;
|
||||
cam_periph_async(periph, code, path, arg);
|
||||
if (code == AC_SCSI_AEN && softc->state != PMP_STATE_NORMAL &&
|
||||
softc->state != PMP_STATE_SCAN)
|
||||
break;
|
||||
if (softc->state != PMP_STATE_SCAN)
|
||||
pmpfreeze(periph, softc->found);
|
||||
if (code == AC_SCSI_AEN)
|
||||
softc->events |= PMP_EV_RESCAN;
|
||||
else
|
||||
pmpfreeze(periph, softc->found & ~(1 << softc->pm_step));
|
||||
softc->events |= PMP_EV_RESET;
|
||||
if (code == AC_SCSI_AEN && softc->state != PMP_STATE_NORMAL)
|
||||
break;
|
||||
xpt_hold_boot();
|
||||
pmpfreeze(periph, softc->found);
|
||||
if (code == AC_SENT_BDR || code == AC_BUS_RESET)
|
||||
softc->found = 0; /* We have to reset everything. */
|
||||
if (softc->state == PMP_STATE_NORMAL) {
|
||||
softc->state = PMP_STATE_PORTS;
|
||||
softc->state = PMP_STATE_PRECONFIG;
|
||||
cam_periph_acquire(periph);
|
||||
xpt_schedule(periph, CAM_PRIORITY_BUS);
|
||||
xpt_schedule(periph, CAM_PRIORITY_DEV);
|
||||
} else
|
||||
softc->restart = 1;
|
||||
break;
|
||||
@ -353,7 +359,6 @@ static cam_status
|
||||
pmpregister(struct cam_periph *periph, void *arg)
|
||||
{
|
||||
struct pmp_softc *softc;
|
||||
struct ccb_pathinq cpi;
|
||||
struct ccb_getdev *cgd;
|
||||
|
||||
cgd = (struct ccb_getdev *)arg;
|
||||
@ -377,16 +382,8 @@ pmpregister(struct cam_periph *periph, void *arg)
|
||||
}
|
||||
periph->softc = softc;
|
||||
|
||||
softc->state = PMP_STATE_PORTS;
|
||||
softc->pm_pid = ((uint32_t *)&cgd->ident_data)[0];
|
||||
softc->pm_prv = ((uint32_t *)&cgd->ident_data)[1];
|
||||
|
||||
/* Check if the SIM does not want queued commands */
|
||||
bzero(&cpi, sizeof(cpi));
|
||||
xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
|
||||
cpi.ccb_h.func_code = XPT_PATH_INQ;
|
||||
xpt_action((union ccb *)&cpi);
|
||||
|
||||
TASK_INIT(&softc->sysctl_task, 0, pmpsysctlinit, periph);
|
||||
|
||||
xpt_announce_periph(periph, NULL);
|
||||
@ -408,7 +405,10 @@ pmpregister(struct cam_periph *periph, void *arg)
|
||||
* the end of probe.
|
||||
*/
|
||||
(void)cam_periph_acquire(periph);
|
||||
xpt_schedule(periph, CAM_PRIORITY_BUS);
|
||||
xpt_hold_boot();
|
||||
softc->state = PMP_STATE_PORTS;
|
||||
softc->events = PMP_EV_RESCAN;
|
||||
xpt_schedule(periph, CAM_PRIORITY_DEV);
|
||||
|
||||
return(CAM_REQ_CMP);
|
||||
}
|
||||
@ -416,17 +416,35 @@ pmpregister(struct cam_periph *periph, void *arg)
|
||||
static void
|
||||
pmpstart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
{
|
||||
struct ccb_trans_settings cts;
|
||||
struct ccb_ataio *ataio;
|
||||
struct pmp_softc *softc;
|
||||
struct cam_path *dpath;
|
||||
int revision = 0;
|
||||
|
||||
softc = (struct pmp_softc *)periph->softc;
|
||||
ataio = &start_ccb->ataio;
|
||||
|
||||
if (softc->restart) {
|
||||
softc->restart = 0;
|
||||
softc->state = PMP_STATE_PORTS;
|
||||
softc->state = min(softc->state, PMP_STATE_PRECONFIG);
|
||||
}
|
||||
/* Fetch user wanted device speed. */
|
||||
if (softc->state == PMP_STATE_RESET ||
|
||||
softc->state == PMP_STATE_CONNECT) {
|
||||
if (xpt_create_path(&dpath, periph,
|
||||
xpt_path_path_id(periph->path),
|
||||
softc->pm_step, 0) == CAM_REQ_CMP) {
|
||||
bzero(&cts, sizeof(cts));
|
||||
xpt_setup_ccb(&cts.ccb_h, dpath, CAM_PRIORITY_NONE);
|
||||
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
|
||||
cts.type = CTS_TYPE_USER_SETTINGS;
|
||||
xpt_action((union ccb *)&cts);
|
||||
if (cts.xport_specific.sata.valid & CTS_SATA_VALID_REVISION)
|
||||
revision = cts.xport_specific.sata.revision;
|
||||
xpt_free_path(dpath);
|
||||
}
|
||||
}
|
||||
|
||||
switch (softc->state) {
|
||||
case PMP_STATE_PORTS:
|
||||
cam_fill_ataio(ataio,
|
||||
@ -460,7 +478,8 @@ pmpstart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
/*dxfer_len*/0,
|
||||
pmp_default_timeout * 1000);
|
||||
ata_pm_write_cmd(ataio, 2, softc->pm_step,
|
||||
(softc->found & (1 << softc->pm_step)) ? 0 : 1);
|
||||
(revision << 4) |
|
||||
((softc->found & (1 << softc->pm_step)) ? 0 : 1));
|
||||
break;
|
||||
case PMP_STATE_CONNECT:
|
||||
cam_fill_ataio(ataio,
|
||||
@ -471,7 +490,8 @@ pmpstart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
/*data_ptr*/NULL,
|
||||
/*dxfer_len*/0,
|
||||
pmp_default_timeout * 1000);
|
||||
ata_pm_write_cmd(ataio, 2, softc->pm_step, 0);
|
||||
ata_pm_write_cmd(ataio, 2, softc->pm_step,
|
||||
(revision << 4));
|
||||
break;
|
||||
case PMP_STATE_CHECK:
|
||||
cam_fill_ataio(ataio,
|
||||
@ -519,9 +539,9 @@ pmpdone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
struct ccb_trans_settings cts;
|
||||
struct pmp_softc *softc;
|
||||
struct ccb_ataio *ataio;
|
||||
union ccb *work_ccb;
|
||||
struct cam_path *path, *dpath;
|
||||
u_int32_t priority, res;
|
||||
int i;
|
||||
|
||||
softc = (struct pmp_softc *)periph->softc;
|
||||
ataio = &done_ccb->ataio;
|
||||
@ -547,16 +567,8 @@ pmpdone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
|
||||
if (softc->restart) {
|
||||
softc->restart = 0;
|
||||
if (softc->state == PMP_STATE_SCAN) {
|
||||
pmpfreeze(periph, 1 << softc->pm_step);
|
||||
work_ccb = done_ccb;
|
||||
done_ccb = (union ccb*)work_ccb->ccb_h.ppriv_ptr0;
|
||||
/* Free the current request path- we're done with it. */
|
||||
xpt_free_path(work_ccb->ccb_h.path);
|
||||
xpt_free_ccb(work_ccb);
|
||||
}
|
||||
xpt_release_ccb(done_ccb);
|
||||
softc->state = PMP_STATE_PORTS;
|
||||
softc->state = min(softc->state, PMP_STATE_PRECONFIG);
|
||||
xpt_schedule(periph, priority);
|
||||
return;
|
||||
}
|
||||
@ -645,7 +657,7 @@ pmpdone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
xpt_path_path_id(periph->path),
|
||||
softc->pm_step, 0) == CAM_REQ_CMP) {
|
||||
bzero(&cts, sizeof(cts));
|
||||
xpt_setup_ccb(&cts.ccb_h, dpath, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cts.ccb_h, dpath, CAM_PRIORITY_NONE);
|
||||
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
|
||||
cts.type = CTS_TYPE_CURRENT_SETTINGS;
|
||||
cts.xport_specific.sata.revision = (res & 0x0f0) >> 4;
|
||||
@ -705,53 +717,43 @@ pmpdone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
xpt_schedule(periph, priority);
|
||||
return;
|
||||
case PMP_STATE_CONFIG:
|
||||
if (softc->found) {
|
||||
softc->pm_step = 0;
|
||||
softc->state = PMP_STATE_SCAN;
|
||||
work_ccb = xpt_alloc_ccb_nowait();
|
||||
if (work_ccb != NULL)
|
||||
goto do_scan;
|
||||
xpt_release_ccb(done_ccb);
|
||||
for (i = 0; i < softc->pm_ports; i++) {
|
||||
union ccb *ccb;
|
||||
|
||||
if ((softc->found & (1 << i)) == 0)
|
||||
continue;
|
||||
if (xpt_create_path(&dpath, periph,
|
||||
xpt_path_path_id(periph->path),
|
||||
i, 0) != CAM_REQ_CMP) {
|
||||
printf("pmpdone: xpt_create_path failed"
|
||||
", bus scan halted\n");
|
||||
xpt_free_ccb(done_ccb);
|
||||
goto done;
|
||||
}
|
||||
/* If we did hard reset to this device, inform XPT. */
|
||||
if ((softc->reset & softc->found & (1 << i)) != 0)
|
||||
xpt_async(AC_SENT_BDR, dpath, NULL);
|
||||
/* If rescan requested, scan this device. */
|
||||
if (softc->events & PMP_EV_RESCAN) {
|
||||
ccb = xpt_alloc_ccb_nowait();
|
||||
if (ccb == NULL) {
|
||||
xpt_free_path(dpath);
|
||||
goto done;
|
||||
}
|
||||
xpt_setup_ccb(&ccb->ccb_h, dpath, CAM_PRIORITY_XPT);
|
||||
xpt_rescan(ccb);
|
||||
} else
|
||||
xpt_free_path(dpath);
|
||||
}
|
||||
break;
|
||||
case PMP_STATE_SCAN:
|
||||
work_ccb = done_ccb;
|
||||
done_ccb = (union ccb*)work_ccb->ccb_h.ppriv_ptr0;
|
||||
/* Free the current request path- we're done with it. */
|
||||
xpt_free_path(work_ccb->ccb_h.path);
|
||||
softc->pm_step++;
|
||||
do_scan:
|
||||
while (softc->pm_step < softc->pm_ports &&
|
||||
(softc->found & (1 << softc->pm_step)) == 0) {
|
||||
softc->pm_step++;
|
||||
}
|
||||
if (softc->pm_step >= softc->pm_ports) {
|
||||
xpt_free_ccb(work_ccb);
|
||||
break;
|
||||
}
|
||||
if (xpt_create_path(&dpath, periph,
|
||||
done_ccb->ccb_h.path_id,
|
||||
softc->pm_step, 0) != CAM_REQ_CMP) {
|
||||
printf("pmpdone: xpt_create_path failed"
|
||||
", bus scan halted\n");
|
||||
xpt_free_ccb(work_ccb);
|
||||
break;
|
||||
}
|
||||
xpt_setup_ccb(&work_ccb->ccb_h, dpath,
|
||||
done_ccb->ccb_h.pinfo.priority);
|
||||
work_ccb->ccb_h.func_code = XPT_SCAN_LUN;
|
||||
work_ccb->ccb_h.cbfcnp = pmpdone;
|
||||
work_ccb->ccb_h.ppriv_ptr0 = done_ccb;
|
||||
work_ccb->crcn.flags = done_ccb->crcn.flags;
|
||||
xpt_action(work_ccb);
|
||||
pmprelease(periph, 1 << softc->pm_step);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
done:
|
||||
xpt_release_ccb(done_ccb);
|
||||
softc->state = PMP_STATE_NORMAL;
|
||||
softc->events = 0;
|
||||
xpt_release_boot();
|
||||
pmprelease(periph, -1);
|
||||
cam_periph_release_locked(periph);
|
||||
}
|
||||
|
@ -130,6 +130,7 @@ typedef struct {
|
||||
u_int8_t digest[16];
|
||||
uint32_t pm_pid;
|
||||
uint32_t pm_prv;
|
||||
int restart;
|
||||
struct cam_periph *periph;
|
||||
} probe_softc;
|
||||
|
||||
@ -231,15 +232,11 @@ proberegister(struct cam_periph *periph, void *arg)
|
||||
if (status != CAM_REQ_CMP) {
|
||||
return (status);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Ensure we've waited at least a bus settle
|
||||
* delay before attempting to probe the device.
|
||||
* For HBAs that don't do bus resets, this won't make a difference.
|
||||
* Ensure nobody slip in until probe finish.
|
||||
*/
|
||||
cam_periph_freeze_after_event(periph, &periph->path->bus->last_reset,
|
||||
scsi_delay);
|
||||
cam_freeze_devq_arg(periph->path,
|
||||
RELSIM_RELEASE_RUNLEVEL, CAM_RL_XPT + 1);
|
||||
probeschedule(periph);
|
||||
return(CAM_REQ_CMP);
|
||||
}
|
||||
@ -247,17 +244,12 @@ proberegister(struct cam_periph *periph, void *arg)
|
||||
static void
|
||||
probeschedule(struct cam_periph *periph)
|
||||
{
|
||||
struct ccb_pathinq cpi;
|
||||
union ccb *ccb;
|
||||
probe_softc *softc;
|
||||
|
||||
softc = (probe_softc *)periph->softc;
|
||||
ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs);
|
||||
|
||||
xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
|
||||
cpi.ccb_h.func_code = XPT_PATH_INQ;
|
||||
xpt_action((union ccb *)&cpi);
|
||||
|
||||
if ((periph->path->device->flags & CAM_DEV_UNCONFIGURED) ||
|
||||
periph->path->device->protocol == PROTO_SATAPM)
|
||||
PROBE_SET_ACTION(softc, PROBE_RESET);
|
||||
@ -269,7 +261,7 @@ probeschedule(struct cam_periph *periph)
|
||||
else
|
||||
softc->flags &= ~PROBE_NO_ANNOUNCE;
|
||||
|
||||
xpt_schedule(periph, ccb->ccb_h.pinfo.priority);
|
||||
xpt_schedule(periph, CAM_PRIORITY_XPT);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -290,6 +282,14 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
csio = &start_ccb->csio;
|
||||
ident_buf = &periph->path->device->ident_data;
|
||||
|
||||
if (softc->restart) {
|
||||
softc->restart = 0;
|
||||
if ((path->device->flags & CAM_DEV_UNCONFIGURED) ||
|
||||
path->device->protocol == PROTO_SATAPM)
|
||||
softc->action = PROBE_RESET;
|
||||
else
|
||||
softc->action = PROBE_IDENTIFY;
|
||||
}
|
||||
switch (softc->action) {
|
||||
case PROBE_RESET:
|
||||
cam_fill_ataio(ataio,
|
||||
@ -299,7 +299,7 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
0,
|
||||
/*data_ptr*/NULL,
|
||||
/*dxfer_len*/0,
|
||||
(start_ccb->ccb_h.target_id == 15 ? 3 : 15) * 1000);
|
||||
15 * 1000);
|
||||
ata_reset_cmd(ataio);
|
||||
break;
|
||||
case PROBE_IDENTIFY:
|
||||
@ -339,7 +339,7 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
mode = 0;
|
||||
/* Fetch user modes from SIM. */
|
||||
bzero(&cts, sizeof(cts));
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
|
||||
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
|
||||
cts.type = CTS_TYPE_USER_SETTINGS;
|
||||
xpt_action((union ccb *)&cts);
|
||||
@ -355,7 +355,7 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
wantmode = mode = ata_max_mode(ident_buf, mode);
|
||||
/* Report modes to SIM. */
|
||||
bzero(&cts, sizeof(cts));
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
|
||||
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
|
||||
cts.type = CTS_TYPE_CURRENT_SETTINGS;
|
||||
if (path->device->transport == XPORT_ATA) {
|
||||
@ -368,7 +368,7 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
xpt_action((union ccb *)&cts);
|
||||
/* Fetch current modes from SIM. */
|
||||
bzero(&cts, sizeof(cts));
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
|
||||
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
|
||||
cts.type = CTS_TYPE_CURRENT_SETTINGS;
|
||||
xpt_action((union ccb *)&cts);
|
||||
@ -400,7 +400,7 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
bytecount = 8192; /* SATA maximum */
|
||||
/* Fetch user bytecount from SIM. */
|
||||
bzero(&cts, sizeof(cts));
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
|
||||
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
|
||||
cts.type = CTS_TYPE_USER_SETTINGS;
|
||||
xpt_action((union ccb *)&cts);
|
||||
@ -416,7 +416,7 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
bytecount / ata_logical_sector_size(ident_buf)));
|
||||
/* Report bytecount to SIM. */
|
||||
bzero(&cts, sizeof(cts));
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
|
||||
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
|
||||
cts.type = CTS_TYPE_CURRENT_SETTINGS;
|
||||
if (path->device->transport == XPORT_ATA) {
|
||||
@ -431,7 +431,7 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
xpt_action((union ccb *)&cts);
|
||||
/* Fetch current bytecount from SIM. */
|
||||
bzero(&cts, sizeof(cts));
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
|
||||
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
|
||||
cts.type = CTS_TYPE_CURRENT_SETTINGS;
|
||||
xpt_action((union ccb *)&cts);
|
||||
@ -462,7 +462,7 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
bytecount = 8192; /* SATA maximum */
|
||||
/* Fetch user bytecount from SIM. */
|
||||
bzero(&cts, sizeof(cts));
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
|
||||
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
|
||||
cts.type = CTS_TYPE_USER_SETTINGS;
|
||||
xpt_action((union ccb *)&cts);
|
||||
@ -482,7 +482,7 @@ probestart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
}
|
||||
/* Report bytecount to SIM. */
|
||||
bzero(&cts, sizeof(cts));
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
|
||||
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
|
||||
cts.type = CTS_TYPE_CURRENT_SETTINGS;
|
||||
if (path->device->transport == XPORT_ATA) {
|
||||
@ -560,7 +560,7 @@ proberequestdefaultnegotiation(struct cam_periph *periph)
|
||||
{
|
||||
struct ccb_trans_settings cts;
|
||||
|
||||
xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE);
|
||||
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
|
||||
cts.type = CTS_TYPE_USER_SETTINGS;
|
||||
xpt_action((union ccb *)&cts);
|
||||
@ -582,7 +582,7 @@ proberequestbackoff(struct cam_periph *periph, struct cam_ed *device)
|
||||
struct ccb_trans_settings_spi *spi;
|
||||
|
||||
memset(&cts, 0, sizeof (cts));
|
||||
xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE);
|
||||
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
|
||||
cts.type = CTS_TYPE_CURRENT_SETTINGS;
|
||||
xpt_action((union ccb *)&cts);
|
||||
@ -739,7 +739,7 @@ device_fail: if (cam_periph_error(done_ccb, 0, 0,
|
||||
done_ccb->ccb_h.target_id == 15) {
|
||||
/* Report SIM that PM is present. */
|
||||
bzero(&cts, sizeof(cts));
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
|
||||
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
|
||||
cts.type = CTS_TYPE_CURRENT_SETTINGS;
|
||||
cts.xport_specific.sata.pm_present = 1;
|
||||
@ -836,7 +836,7 @@ device_fail: if (cam_periph_error(done_ccb, 0, 0,
|
||||
path->bus->sim->max_tagged_dev_openings != 0) {
|
||||
/* Report SIM which tags are allowed. */
|
||||
bzero(&cts, sizeof(cts));
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
|
||||
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
|
||||
cts.type = CTS_TYPE_CURRENT_SETTINGS;
|
||||
cts.xport_specific.sata.tags = path->device->maxtags;
|
||||
@ -957,18 +957,23 @@ device_fail: if (cam_periph_error(done_ccb, 0, 0,
|
||||
break;
|
||||
}
|
||||
done:
|
||||
xpt_release_ccb(done_ccb);
|
||||
done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs);
|
||||
TAILQ_REMOVE(&softc->request_ccbs, &done_ccb->ccb_h, periph_links.tqe);
|
||||
done_ccb->ccb_h.status = CAM_REQ_CMP;
|
||||
done_ccb->ccb_h.ppriv_field1 = found;
|
||||
xpt_done(done_ccb);
|
||||
if (TAILQ_FIRST(&softc->request_ccbs) == NULL) {
|
||||
cam_periph_invalidate(periph);
|
||||
cam_periph_release_locked(periph);
|
||||
} else {
|
||||
if (softc->restart) {
|
||||
softc->restart = 0;
|
||||
xpt_release_ccb(done_ccb);
|
||||
probeschedule(periph);
|
||||
return;
|
||||
}
|
||||
xpt_release_ccb(done_ccb);
|
||||
while ((done_ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs))) {
|
||||
TAILQ_REMOVE(&softc->request_ccbs,
|
||||
&done_ccb->ccb_h, periph_links.tqe);
|
||||
done_ccb->ccb_h.status = found ? CAM_REQ_CMP : CAM_REQ_CMP_ERR;
|
||||
xpt_done(done_ccb);
|
||||
}
|
||||
cam_release_devq(periph->path,
|
||||
RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_XPT + 1, FALSE);
|
||||
cam_periph_invalidate(periph);
|
||||
cam_periph_release_locked(periph);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1013,7 +1018,7 @@ ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
|
||||
{
|
||||
struct cam_path *path;
|
||||
ata_scan_bus_info *scan_info;
|
||||
union ccb *work_ccb;
|
||||
union ccb *work_ccb, *reset_ccb;
|
||||
cam_status status;
|
||||
|
||||
CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE,
|
||||
@ -1038,6 +1043,26 @@ ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
|
||||
return;
|
||||
}
|
||||
|
||||
/* We may need to reset bus first, if we haven't done it yet. */
|
||||
if ((work_ccb->cpi.hba_inquiry &
|
||||
(PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) &&
|
||||
!(work_ccb->cpi.hba_misc & PIM_NOBUSRESET) &&
|
||||
!timevalisset(&request_ccb->ccb_h.path->bus->last_reset)) {
|
||||
reset_ccb = xpt_alloc_ccb_nowait();
|
||||
xpt_setup_ccb(&reset_ccb->ccb_h, request_ccb->ccb_h.path,
|
||||
CAM_PRIORITY_NONE);
|
||||
reset_ccb->ccb_h.func_code = XPT_RESET_BUS;
|
||||
xpt_action(reset_ccb);
|
||||
if (reset_ccb->ccb_h.status != CAM_REQ_CMP) {
|
||||
request_ccb->ccb_h.status = reset_ccb->ccb_h.status;
|
||||
xpt_free_ccb(reset_ccb);
|
||||
xpt_free_ccb(work_ccb);
|
||||
xpt_done(request_ccb);
|
||||
return;
|
||||
}
|
||||
xpt_free_ccb(reset_ccb);
|
||||
}
|
||||
|
||||
/* Save some state for use while we probe for devices */
|
||||
scan_info = (ata_scan_bus_info *)
|
||||
malloc(sizeof(ata_scan_bus_info), M_CAMXPT, M_NOWAIT);
|
||||
@ -1071,7 +1096,7 @@ ata_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
|
||||
/* If there is PMP... */
|
||||
if ((scan_info->cpi->hba_inquiry & PI_SATAPM) &&
|
||||
(scan_info->counter == scan_info->cpi->max_target)) {
|
||||
if (work_ccb->ccb_h.ppriv_field1 != 0) {
|
||||
if (work_ccb->ccb_h.status == CAM_REQ_CMP) {
|
||||
/* everything else willbe probed by it */
|
||||
goto done;
|
||||
} else {
|
||||
@ -1141,10 +1166,9 @@ ata_scan_lun(struct cam_periph *periph, struct cam_path *path,
|
||||
struct cam_path *new_path;
|
||||
struct cam_periph *old_periph;
|
||||
|
||||
CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE,
|
||||
("xpt_scan_lun\n"));
|
||||
CAM_DEBUG(path, CAM_DEBUG_TRACE, ("xpt_scan_lun\n"));
|
||||
|
||||
xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE);
|
||||
cpi.ccb_h.func_code = XPT_PATH_INQ;
|
||||
xpt_action((union ccb *)&cpi);
|
||||
|
||||
@ -1182,7 +1206,7 @@ ata_scan_lun(struct cam_periph *periph, struct cam_path *path,
|
||||
free(new_path, M_CAMXPT);
|
||||
return;
|
||||
}
|
||||
xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_XPT);
|
||||
request_ccb->ccb_h.cbfcnp = xptscandone;
|
||||
request_ccb->ccb_h.func_code = XPT_SCAN_LUN;
|
||||
request_ccb->crcn.flags = flags;
|
||||
@ -1194,6 +1218,7 @@ ata_scan_lun(struct cam_periph *periph, struct cam_path *path,
|
||||
softc = (probe_softc *)old_periph->softc;
|
||||
TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h,
|
||||
periph_links.tqe);
|
||||
softc->restart = 1;
|
||||
} else {
|
||||
status = cam_periph_alloc(proberegister, NULL, probecleanup,
|
||||
probestart, "aprobe",
|
||||
@ -1281,7 +1306,7 @@ ata_device_transport(struct cam_path *path)
|
||||
struct ata_params *ident_buf = NULL;
|
||||
|
||||
/* Get transport information from the SIM */
|
||||
xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE);
|
||||
cpi.ccb_h.func_code = XPT_PATH_INQ;
|
||||
xpt_action((union ccb *)&cpi);
|
||||
|
||||
@ -1301,7 +1326,7 @@ ata_device_transport(struct cam_path *path)
|
||||
ata_version(ident_buf->version_major) : cpi.transport_version;
|
||||
|
||||
/* Tell the controller what we think */
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
|
||||
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
|
||||
cts.type = CTS_TYPE_CURRENT_SETTINGS;
|
||||
cts.transport = path->device->transport;
|
||||
@ -1429,7 +1454,7 @@ ata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device,
|
||||
|
||||
inq_data = &device->inq_data;
|
||||
scsi = &cts->proto_specific.scsi;
|
||||
xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE);
|
||||
cpi.ccb_h.func_code = XPT_PATH_INQ;
|
||||
xpt_action((union ccb *)&cpi);
|
||||
|
||||
@ -1450,7 +1475,7 @@ ata_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device,
|
||||
* Perform sanity checking against what the
|
||||
* controller and device can do.
|
||||
*/
|
||||
xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE);
|
||||
cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
|
||||
cur_cts.type = cts->type;
|
||||
xpt_action((union ccb *)&cur_cts);
|
||||
@ -1550,6 +1575,10 @@ ata_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target,
|
||||
*/
|
||||
ata_scan_lun(newpath.periph, &newpath,
|
||||
CAM_EXPECT_INQ_CHANGE, NULL);
|
||||
} else {
|
||||
/* We need to reinitialize device after reset. */
|
||||
ata_scan_lun(newpath.periph, &newpath,
|
||||
0, NULL);
|
||||
}
|
||||
xpt_release_path(&newpath);
|
||||
} else if (async_code == AC_LOST_DEVICE &&
|
||||
|
@ -305,10 +305,10 @@ cam_error_string(struct cam_device *device, union ccb *ccb, char *str,
|
||||
entry = cam_fetch_status_entry(status);
|
||||
|
||||
if (entry == NULL)
|
||||
sbuf_printf(&sb, "CAM Status: Unknown (%#x)\n",
|
||||
sbuf_printf(&sb, "CAM status: Unknown (%#x)\n",
|
||||
ccb->ccb_h.status);
|
||||
else
|
||||
sbuf_printf(&sb, "CAM Status: %s\n",
|
||||
sbuf_printf(&sb, "CAM status: %s\n",
|
||||
entry->status_text);
|
||||
}
|
||||
|
||||
@ -338,7 +338,7 @@ cam_error_string(struct cam_device *device, union ccb *ccb, char *str,
|
||||
|
||||
if (proto_flags & CAM_ESF_PRINT_STATUS) {
|
||||
sbuf_cat(&sb, path_str);
|
||||
sbuf_printf(&sb, "SCSI Status: %s\n",
|
||||
sbuf_printf(&sb, "SCSI status: %s\n",
|
||||
scsi_status_string(&ccb->csio));
|
||||
}
|
||||
|
||||
|
@ -60,16 +60,29 @@ typedef u_int lun_id_t;
|
||||
struct cam_periph;
|
||||
|
||||
/*
|
||||
* Priority information for a CAM structure. The generation number is
|
||||
* incremented everytime a new entry is entered into the queue giving round
|
||||
* robin per priority level scheduling.
|
||||
* Priority information for a CAM structure.
|
||||
*/
|
||||
typedef enum {
|
||||
CAM_RL_HOST,
|
||||
CAM_RL_BUS,
|
||||
CAM_RL_XPT,
|
||||
CAM_RL_DEV,
|
||||
CAM_RL_NORMAL,
|
||||
CAM_RL_VALUES
|
||||
} cam_rl;
|
||||
/*
|
||||
* The generation number is incremented everytime a new entry is entered into
|
||||
* the queue giving round robin per priority level scheduling.
|
||||
*/
|
||||
typedef struct {
|
||||
u_int32_t priority;
|
||||
#define CAM_PRIORITY_BUS 0
|
||||
#define CAM_PRIORITY_DEV 0
|
||||
#define CAM_PRIORITY_NORMAL 1
|
||||
#define CAM_PRIORITY_HOST ((CAM_RL_HOST << 8) + 0x80)
|
||||
#define CAM_PRIORITY_BUS ((CAM_RL_BUS << 8) + 0x80)
|
||||
#define CAM_PRIORITY_XPT ((CAM_RL_XPT << 8) + 0x80)
|
||||
#define CAM_PRIORITY_DEV ((CAM_RL_DEV << 8) + 0x80)
|
||||
#define CAM_PRIORITY_NORMAL ((CAM_RL_NORMAL << 8) + 0x80)
|
||||
#define CAM_PRIORITY_NONE (u_int32_t)-1
|
||||
#define CAM_PRIORITY_TO_RL(x) ((x) >> 8)
|
||||
u_int32_t generation;
|
||||
int index;
|
||||
#define CAM_UNQUEUED_INDEX -1
|
||||
|
@ -126,7 +126,7 @@ typedef enum {
|
||||
XPT_PATH_INQ = 0x04,
|
||||
/* Path routing inquiry */
|
||||
XPT_REL_SIMQ = 0x05,
|
||||
/* Release a frozen SIM queue */
|
||||
/* Release a frozen device queue */
|
||||
XPT_SASYNC_CB = 0x06,
|
||||
/* Set Asynchronous Callback Parameters */
|
||||
XPT_SDEV_TYPE = 0x07,
|
||||
@ -142,6 +142,8 @@ typedef enum {
|
||||
/* Path statistics (error counts, etc.) */
|
||||
XPT_GDEV_STATS = 0x0c,
|
||||
/* Device statistics (error counts, etc.) */
|
||||
XPT_FREEZE_QUEUE = 0x0d,
|
||||
/* Freeze device queue */
|
||||
/* SCSI Control Functions: 0x10->0x1F */
|
||||
XPT_ABORT = 0x10,
|
||||
/* Abort the specified CCB */
|
||||
@ -685,8 +687,9 @@ struct ccb_relsim {
|
||||
#define RELSIM_RELEASE_AFTER_TIMEOUT 0x02
|
||||
#define RELSIM_RELEASE_AFTER_CMDCMPLT 0x04
|
||||
#define RELSIM_RELEASE_AFTER_QEMPTY 0x08
|
||||
#define RELSIM_RELEASE_RUNLEVEL 0x10
|
||||
u_int32_t openings;
|
||||
u_int32_t release_timeout;
|
||||
u_int32_t release_timeout; /* Abstract argument. */
|
||||
u_int32_t qfrozen_cnt;
|
||||
};
|
||||
|
||||
|
@ -71,19 +71,20 @@ static void camperiphfree(struct cam_periph *periph);
|
||||
static int camperiphscsistatuserror(union ccb *ccb,
|
||||
cam_flags camflags,
|
||||
u_int32_t sense_flags,
|
||||
union ccb *save_ccb,
|
||||
int *openings,
|
||||
u_int32_t *relsim_flags,
|
||||
u_int32_t *timeout);
|
||||
u_int32_t *timeout,
|
||||
const char **action_string);
|
||||
static int camperiphscsisenseerror(union ccb *ccb,
|
||||
cam_flags camflags,
|
||||
u_int32_t sense_flags,
|
||||
union ccb *save_ccb,
|
||||
int *openings,
|
||||
u_int32_t *relsim_flags,
|
||||
u_int32_t *timeout);
|
||||
u_int32_t *timeout,
|
||||
const char **action_string);
|
||||
|
||||
static int nperiph_drivers;
|
||||
static int initialized = 0;
|
||||
struct periph_driver **periph_drivers;
|
||||
|
||||
MALLOC_DEFINE(M_CAMPERIPH, "CAM periph", "CAM peripheral buffers");
|
||||
@ -99,6 +100,7 @@ TUNABLE_INT("kern.cam.periph_busy_delay", &periph_busy_delay);
|
||||
void
|
||||
periphdriver_register(void *data)
|
||||
{
|
||||
struct periph_driver *drv = (struct periph_driver *)data;
|
||||
struct periph_driver **newdrivers, **old;
|
||||
int ndrivers;
|
||||
|
||||
@ -108,13 +110,30 @@ periphdriver_register(void *data)
|
||||
if (periph_drivers)
|
||||
bcopy(periph_drivers, newdrivers,
|
||||
sizeof(*newdrivers) * nperiph_drivers);
|
||||
newdrivers[nperiph_drivers] = (struct periph_driver *)data;
|
||||
newdrivers[nperiph_drivers] = drv;
|
||||
newdrivers[nperiph_drivers + 1] = NULL;
|
||||
old = periph_drivers;
|
||||
periph_drivers = newdrivers;
|
||||
if (old)
|
||||
free(old, M_CAMPERIPH);
|
||||
nperiph_drivers++;
|
||||
/* If driver marked as early or it is late now, initialize it. */
|
||||
if (((drv->flags & CAM_PERIPH_DRV_EARLY) != 0 && initialized > 0) ||
|
||||
initialized > 1)
|
||||
(*drv->init)();
|
||||
}
|
||||
|
||||
void
|
||||
periphdriver_init(int level)
|
||||
{
|
||||
int i, early;
|
||||
|
||||
initialized = max(initialized, level);
|
||||
for (i = 0; periph_drivers[i] != NULL; i++) {
|
||||
early = (periph_drivers[i]->flags & CAM_PERIPH_DRV_EARLY) ? 1 : 2;
|
||||
if (early == initialized)
|
||||
(*periph_drivers[i]->init)();
|
||||
}
|
||||
}
|
||||
|
||||
cam_status
|
||||
@ -915,12 +934,14 @@ cam_periph_runccb(union ccb *ccb,
|
||||
|
||||
} while (error == ERESTART);
|
||||
|
||||
if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
|
||||
if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) {
|
||||
cam_release_devq(ccb->ccb_h.path,
|
||||
/* relsim_flags */0,
|
||||
/* openings */0,
|
||||
/* timeout */0,
|
||||
/* getcount_only */ FALSE);
|
||||
ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
|
||||
}
|
||||
|
||||
if (ds != NULL) {
|
||||
if (ccb->ccb_h.func_code == XPT_SCSI_IO) {
|
||||
@ -950,17 +971,26 @@ cam_periph_runccb(union ccb *ccb,
|
||||
void
|
||||
cam_freeze_devq(struct cam_path *path)
|
||||
{
|
||||
struct ccb_hdr ccb_h;
|
||||
|
||||
xpt_setup_ccb(&ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
ccb_h.func_code = XPT_NOOP;
|
||||
ccb_h.flags = CAM_DEV_QFREEZE;
|
||||
xpt_action((union ccb *)&ccb_h);
|
||||
cam_freeze_devq_arg(path, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
cam_freeze_devq_arg(struct cam_path *path, uint32_t flags, uint32_t arg)
|
||||
{
|
||||
struct ccb_relsim crs;
|
||||
|
||||
xpt_setup_ccb(&crs.ccb_h, path, CAM_PRIORITY_NONE);
|
||||
crs.ccb_h.func_code = XPT_FREEZE_QUEUE;
|
||||
crs.release_flags = flags;
|
||||
crs.openings = arg;
|
||||
crs.release_timeout = arg;
|
||||
xpt_action((union ccb *)&crs);
|
||||
}
|
||||
|
||||
u_int32_t
|
||||
cam_release_devq(struct cam_path *path, u_int32_t relsim_flags,
|
||||
u_int32_t openings, u_int32_t timeout,
|
||||
u_int32_t openings, u_int32_t arg,
|
||||
int getcount_only)
|
||||
{
|
||||
struct ccb_relsim crs;
|
||||
@ -970,22 +1000,21 @@ cam_release_devq(struct cam_path *path, u_int32_t relsim_flags,
|
||||
crs.ccb_h.flags = getcount_only ? CAM_DEV_QFREEZE : 0;
|
||||
crs.release_flags = relsim_flags;
|
||||
crs.openings = openings;
|
||||
crs.release_timeout = timeout;
|
||||
crs.release_timeout = arg;
|
||||
xpt_action((union ccb *)&crs);
|
||||
return (crs.qfrozen_cnt);
|
||||
}
|
||||
|
||||
#define saved_ccb_ptr ppriv_ptr0
|
||||
#define recovery_depth ppriv_field1
|
||||
static void
|
||||
camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
camperiphsensedone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
{
|
||||
union ccb *saved_ccb;
|
||||
union ccb *saved_ccb = (union ccb *)done_ccb->ccb_h.saved_ccb_ptr;
|
||||
cam_status status;
|
||||
int frozen = 0;
|
||||
int sense;
|
||||
struct scsi_start_stop_unit *scsi_cmd;
|
||||
u_int32_t relsim_flags, timeout;
|
||||
int xpt_done_ccb = FALSE;
|
||||
u_int sense_key;
|
||||
int depth = done_ccb->ccb_h.recovery_depth;
|
||||
|
||||
status = done_ccb->ccb_h.status;
|
||||
if (status & CAM_DEV_QFRZN) {
|
||||
@ -996,14 +1025,83 @@ camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
*/
|
||||
done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
|
||||
}
|
||||
sense = (status & CAM_AUTOSNS_VALID) != 0;
|
||||
status &= CAM_STATUS_MASK;
|
||||
switch (status) {
|
||||
case CAM_REQ_CMP:
|
||||
{
|
||||
/*
|
||||
* If we manually retrieved sense into a CCB and got
|
||||
* something other than "NO SENSE" send the updated CCB
|
||||
* back to the client via xpt_done() to be processed via
|
||||
* the error recovery code again.
|
||||
*/
|
||||
sense_key = saved_ccb->csio.sense_data.flags;
|
||||
sense_key &= SSD_KEY;
|
||||
if (sense_key != SSD_KEY_NO_SENSE) {
|
||||
saved_ccb->ccb_h.status |=
|
||||
CAM_AUTOSNS_VALID;
|
||||
} else {
|
||||
saved_ccb->ccb_h.status &=
|
||||
~CAM_STATUS_MASK;
|
||||
saved_ccb->ccb_h.status |=
|
||||
CAM_AUTOSENSE_FAIL;
|
||||
}
|
||||
bcopy(saved_ccb, done_ccb, sizeof(union ccb));
|
||||
xpt_free_ccb(saved_ccb);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
bcopy(saved_ccb, done_ccb, sizeof(union ccb));
|
||||
xpt_free_ccb(saved_ccb);
|
||||
done_ccb->ccb_h.status &= ~CAM_STATUS_MASK;
|
||||
done_ccb->ccb_h.status |= CAM_AUTOSENSE_FAIL;
|
||||
break;
|
||||
}
|
||||
periph->flags &= ~CAM_PERIPH_SENSE_INPROG;
|
||||
/*
|
||||
* If it is the end of recovery, drop freeze, taken due to
|
||||
* CAM_DEV_QFREEZE flag, set on recovery request.
|
||||
*/
|
||||
if (depth == 0) {
|
||||
cam_release_devq(done_ccb->ccb_h.path,
|
||||
/*relsim_flags*/0,
|
||||
/*openings*/0,
|
||||
/*timeout*/0,
|
||||
/*getcount_only*/0);
|
||||
}
|
||||
/*
|
||||
* Copy frozen flag from recovery request if it is set there
|
||||
* for some reason.
|
||||
*/
|
||||
if (frozen != 0)
|
||||
done_ccb->ccb_h.status |= CAM_DEV_QFRZN;
|
||||
(*done_ccb->ccb_h.cbfcnp)(periph, done_ccb);
|
||||
}
|
||||
|
||||
static void
|
||||
camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
{
|
||||
union ccb *saved_ccb, *save_ccb;
|
||||
cam_status status;
|
||||
int frozen = 0;
|
||||
struct scsi_start_stop_unit *scsi_cmd;
|
||||
u_int32_t relsim_flags, timeout;
|
||||
|
||||
status = done_ccb->ccb_h.status;
|
||||
if (status & CAM_DEV_QFRZN) {
|
||||
frozen = 1;
|
||||
/*
|
||||
* Clear freeze flag now for case of retry,
|
||||
* freeze will be dropped later.
|
||||
*/
|
||||
done_ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
|
||||
}
|
||||
|
||||
timeout = 0;
|
||||
relsim_flags = 0;
|
||||
saved_ccb = (union ccb *)done_ccb->ccb_h.saved_ccb_ptr;
|
||||
|
||||
switch (status) {
|
||||
switch (status & CAM_STATUS_MASK) {
|
||||
case CAM_REQ_CMP:
|
||||
{
|
||||
/*
|
||||
@ -1012,57 +1110,19 @@ camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
* the inquiry information. Many devices (mostly disks)
|
||||
* don't properly report their inquiry information unless
|
||||
* they are spun up.
|
||||
*
|
||||
* If we manually retrieved sense into a CCB and got
|
||||
* something other than "NO SENSE" send the updated CCB
|
||||
* back to the client via xpt_done() to be processed via
|
||||
* the error recovery code again.
|
||||
*/
|
||||
if (done_ccb->ccb_h.func_code == XPT_SCSI_IO) {
|
||||
scsi_cmd = (struct scsi_start_stop_unit *)
|
||||
&done_ccb->csio.cdb_io.cdb_bytes;
|
||||
scsi_cmd = (struct scsi_start_stop_unit *)
|
||||
&done_ccb->csio.cdb_io.cdb_bytes;
|
||||
|
||||
if (scsi_cmd->opcode == START_STOP_UNIT)
|
||||
xpt_async(AC_INQ_CHANGED,
|
||||
done_ccb->ccb_h.path, NULL);
|
||||
if (scsi_cmd->opcode == REQUEST_SENSE) {
|
||||
u_int sense_key;
|
||||
|
||||
sense_key = saved_ccb->csio.sense_data.flags;
|
||||
sense_key &= SSD_KEY;
|
||||
if (sense_key != SSD_KEY_NO_SENSE) {
|
||||
saved_ccb->ccb_h.status |=
|
||||
CAM_AUTOSNS_VALID;
|
||||
#if 0
|
||||
xpt_print(saved_ccb->ccb_h.path,
|
||||
"Recovered Sense\n");
|
||||
scsi_sense_print(&saved_ccb->csio);
|
||||
cam_error_print(saved_ccb, CAM_ESF_ALL,
|
||||
CAM_EPF_ALL);
|
||||
#endif
|
||||
} else {
|
||||
saved_ccb->ccb_h.status &=
|
||||
~CAM_STATUS_MASK;
|
||||
saved_ccb->ccb_h.status |=
|
||||
CAM_AUTOSENSE_FAIL;
|
||||
}
|
||||
xpt_done_ccb = TRUE;
|
||||
}
|
||||
}
|
||||
bcopy(done_ccb->ccb_h.saved_ccb_ptr, done_ccb,
|
||||
sizeof(union ccb));
|
||||
|
||||
periph->flags &= ~CAM_PERIPH_RECOVERY_INPROG;
|
||||
|
||||
if (xpt_done_ccb == FALSE)
|
||||
xpt_action(done_ccb);
|
||||
|
||||
break;
|
||||
if (scsi_cmd->opcode == START_STOP_UNIT)
|
||||
xpt_async(AC_INQ_CHANGED,
|
||||
done_ccb->ccb_h.path, NULL);
|
||||
goto final;
|
||||
}
|
||||
case CAM_SCSI_STATUS_ERROR:
|
||||
scsi_cmd = (struct scsi_start_stop_unit *)
|
||||
&done_ccb->csio.cdb_io.cdb_bytes;
|
||||
if (sense != 0) {
|
||||
if (status & CAM_AUTOSNS_VALID) {
|
||||
struct ccb_getdev cgd;
|
||||
struct scsi_sense_data *sense;
|
||||
int error_code, sense_key, asc, ascq;
|
||||
@ -1071,7 +1131,6 @@ camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
sense = &done_ccb->csio.sense_data;
|
||||
scsi_extract_sense(sense, &error_code,
|
||||
&sense_key, &asc, &ascq);
|
||||
|
||||
/*
|
||||
* Grab the inquiry data for this device.
|
||||
*/
|
||||
@ -1081,7 +1140,6 @@ camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
xpt_action((union ccb *)&cgd);
|
||||
err_action = scsi_error_action(&done_ccb->csio,
|
||||
&cgd.inq_data, 0);
|
||||
|
||||
/*
|
||||
* If the error is "invalid field in CDB",
|
||||
* and the load/eject flag is set, turn the
|
||||
@ -1091,7 +1149,6 @@ camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
* the load/eject flag by default for
|
||||
* removable media.
|
||||
*/
|
||||
|
||||
/* XXX KDM
|
||||
* Should we check to see what the specific
|
||||
* scsi status is?? Or does it not matter
|
||||
@ -1106,9 +1163,7 @@ camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
(done_ccb->ccb_h.retry_count > 0)) {
|
||||
|
||||
scsi_cmd->how &= ~SSS_LOEJ;
|
||||
|
||||
xpt_action(done_ccb);
|
||||
|
||||
} else if ((done_ccb->ccb_h.retry_count > 1)
|
||||
&& ((err_action & SS_MASK) != SS_FAIL)) {
|
||||
|
||||
@ -1119,53 +1174,51 @@ camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
* it another try unless this is an
|
||||
* unretryable error.
|
||||
*/
|
||||
|
||||
/* set the timeout to .5 sec */
|
||||
relsim_flags =
|
||||
RELSIM_RELEASE_AFTER_TIMEOUT;
|
||||
timeout = 500;
|
||||
|
||||
xpt_action(done_ccb);
|
||||
|
||||
break;
|
||||
|
||||
} else {
|
||||
/*
|
||||
* Perform the final retry with the original
|
||||
* CCB so that final error processing is
|
||||
* performed by the owner of the CCB.
|
||||
*/
|
||||
bcopy(done_ccb->ccb_h.saved_ccb_ptr,
|
||||
done_ccb, sizeof(union ccb));
|
||||
|
||||
periph->flags &= ~CAM_PERIPH_RECOVERY_INPROG;
|
||||
|
||||
xpt_action(done_ccb);
|
||||
goto final;
|
||||
}
|
||||
} else {
|
||||
save_ccb = xpt_alloc_ccb_nowait();
|
||||
if (save_ccb == NULL)
|
||||
goto final;
|
||||
bcopy(done_ccb, save_ccb, sizeof(*save_ccb));
|
||||
periph->flags |= CAM_PERIPH_SENSE_INPROG;
|
||||
/*
|
||||
* Eh?? The command failed, but we don't
|
||||
* have any sense. What's up with that?
|
||||
* Fire the CCB again to return it to the
|
||||
* caller.
|
||||
* Send a Request Sense to the device. We
|
||||
* assume that we are in a contingent allegiance
|
||||
* condition so we do not tag this request.
|
||||
*/
|
||||
bcopy(done_ccb->ccb_h.saved_ccb_ptr,
|
||||
done_ccb, sizeof(union ccb));
|
||||
|
||||
periph->flags &= ~CAM_PERIPH_RECOVERY_INPROG;
|
||||
|
||||
scsi_request_sense(&done_ccb->csio, /*retries*/1,
|
||||
camperiphsensedone,
|
||||
&save_ccb->csio.sense_data,
|
||||
sizeof(save_ccb->csio.sense_data),
|
||||
CAM_TAG_ACTION_NONE,
|
||||
/*sense_len*/SSD_FULL_SIZE,
|
||||
/*timeout*/5000);
|
||||
done_ccb->ccb_h.pinfo.priority--;
|
||||
done_ccb->ccb_h.flags |= CAM_DEV_QFREEZE;
|
||||
done_ccb->ccb_h.saved_ccb_ptr = save_ccb;
|
||||
done_ccb->ccb_h.recovery_depth++;
|
||||
xpt_action(done_ccb);
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
bcopy(done_ccb->ccb_h.saved_ccb_ptr, done_ccb,
|
||||
sizeof(union ccb));
|
||||
|
||||
final:
|
||||
bcopy(saved_ccb, done_ccb, sizeof(*done_ccb));
|
||||
xpt_free_ccb(saved_ccb);
|
||||
periph->flags &= ~CAM_PERIPH_RECOVERY_INPROG;
|
||||
|
||||
xpt_action(done_ccb);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1188,23 +1241,13 @@ camperiphdone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
/*openings*/0,
|
||||
/*timeout*/timeout,
|
||||
/*getcount_only*/0);
|
||||
if (xpt_done_ccb == TRUE) {
|
||||
/*
|
||||
* Copy frozen flag from recovery request if it is set there
|
||||
* for some reason.
|
||||
*/
|
||||
if (frozen != 0)
|
||||
done_ccb->ccb_h.status |= CAM_DEV_QFRZN;
|
||||
(*done_ccb->ccb_h.cbfcnp)(periph, done_ccb);
|
||||
} else {
|
||||
/* Drop freeze taken, if this recovery request got error. */
|
||||
if (frozen != 0) {
|
||||
cam_release_devq(done_ccb->ccb_h.path,
|
||||
/*relsim_flags*/0,
|
||||
/*openings*/0,
|
||||
/*timeout*/0,
|
||||
/*getcount_only*/0);
|
||||
}
|
||||
/* Drop freeze taken, if this recovery request got error. */
|
||||
if (frozen != 0) {
|
||||
cam_release_devq(done_ccb->ccb_h.path,
|
||||
/*relsim_flags*/0,
|
||||
/*openings*/0,
|
||||
/*timeout*/0,
|
||||
/*getcount_only*/0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1221,12 +1264,6 @@ cam_periph_async(struct cam_periph *periph, u_int32_t code,
|
||||
case AC_LOST_DEVICE:
|
||||
cam_periph_invalidate(periph);
|
||||
break;
|
||||
case AC_SENT_BDR:
|
||||
case AC_BUS_RESET:
|
||||
{
|
||||
cam_periph_bus_settle(periph, scsi_delay);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1271,9 +1308,9 @@ cam_periph_freeze_after_event(struct cam_periph *periph,
|
||||
|
||||
static int
|
||||
camperiphscsistatuserror(union ccb *ccb, cam_flags camflags,
|
||||
u_int32_t sense_flags, union ccb *save_ccb,
|
||||
u_int32_t sense_flags,
|
||||
int *openings, u_int32_t *relsim_flags,
|
||||
u_int32_t *timeout)
|
||||
u_int32_t *timeout, const char **action_string)
|
||||
{
|
||||
int error;
|
||||
|
||||
@ -1286,13 +1323,15 @@ camperiphscsistatuserror(union ccb *ccb, cam_flags camflags,
|
||||
break;
|
||||
case SCSI_STATUS_CMD_TERMINATED:
|
||||
case SCSI_STATUS_CHECK_COND:
|
||||
if (bootverbose)
|
||||
xpt_print(ccb->ccb_h.path, "SCSI status error\n");
|
||||
error = camperiphscsisenseerror(ccb,
|
||||
camflags,
|
||||
sense_flags,
|
||||
save_ccb,
|
||||
openings,
|
||||
relsim_flags,
|
||||
timeout);
|
||||
timeout,
|
||||
action_string);
|
||||
break;
|
||||
case SCSI_STATUS_QUEUE_FULL:
|
||||
{
|
||||
@ -1347,7 +1386,7 @@ camperiphscsistatuserror(union ccb *ccb, cam_flags camflags,
|
||||
*timeout = 0;
|
||||
error = ERESTART;
|
||||
if (bootverbose) {
|
||||
xpt_print(ccb->ccb_h.path, "Queue Full\n");
|
||||
xpt_print(ccb->ccb_h.path, "Queue full\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1359,7 +1398,7 @@ camperiphscsistatuserror(union ccb *ccb, cam_flags camflags,
|
||||
* command completes or a 1 second timeout.
|
||||
*/
|
||||
if (bootverbose) {
|
||||
xpt_print(ccb->ccb_h.path, "Device Busy\n");
|
||||
xpt_print(ccb->ccb_h.path, "Device busy\n");
|
||||
}
|
||||
if (ccb->ccb_h.retry_count > 0) {
|
||||
ccb->ccb_h.retry_count--;
|
||||
@ -1372,11 +1411,11 @@ camperiphscsistatuserror(union ccb *ccb, cam_flags camflags,
|
||||
}
|
||||
break;
|
||||
case SCSI_STATUS_RESERV_CONFLICT:
|
||||
xpt_print(ccb->ccb_h.path, "Reservation Conflict\n");
|
||||
xpt_print(ccb->ccb_h.path, "Reservation conflict\n");
|
||||
error = EIO;
|
||||
break;
|
||||
default:
|
||||
xpt_print(ccb->ccb_h.path, "SCSI Status 0x%x\n",
|
||||
xpt_print(ccb->ccb_h.path, "SCSI status 0x%x\n",
|
||||
ccb->csio.scsi_status);
|
||||
error = EIO;
|
||||
break;
|
||||
@ -1386,16 +1425,17 @@ camperiphscsistatuserror(union ccb *ccb, cam_flags camflags,
|
||||
|
||||
static int
|
||||
camperiphscsisenseerror(union ccb *ccb, cam_flags camflags,
|
||||
u_int32_t sense_flags, union ccb *save_ccb,
|
||||
u_int32_t sense_flags,
|
||||
int *openings, u_int32_t *relsim_flags,
|
||||
u_int32_t *timeout)
|
||||
u_int32_t *timeout, const char **action_string)
|
||||
{
|
||||
struct cam_periph *periph;
|
||||
union ccb *orig_ccb = ccb;
|
||||
int error;
|
||||
|
||||
periph = xpt_path_periph(ccb->ccb_h.path);
|
||||
if (periph->flags & CAM_PERIPH_RECOVERY_INPROG) {
|
||||
|
||||
if (periph->flags &
|
||||
(CAM_PERIPH_RECOVERY_INPROG | CAM_PERIPH_SENSE_INPROG)) {
|
||||
/*
|
||||
* If error recovery is already in progress, don't attempt
|
||||
* to process this error, but requeue it unconditionally
|
||||
@ -1413,17 +1453,6 @@ camperiphscsisenseerror(union ccb *ccb, cam_flags camflags,
|
||||
} else {
|
||||
scsi_sense_action err_action;
|
||||
struct ccb_getdev cgd;
|
||||
const char *action_string;
|
||||
union ccb* print_ccb;
|
||||
|
||||
/* A description of the error recovery action performed */
|
||||
action_string = NULL;
|
||||
|
||||
/*
|
||||
* The location of the orignal ccb
|
||||
* for sense printing purposes.
|
||||
*/
|
||||
print_ccb = ccb;
|
||||
|
||||
/*
|
||||
* Grab the inquiry data for this device.
|
||||
@ -1451,7 +1480,7 @@ camperiphscsisenseerror(union ccb *ccb, cam_flags camflags,
|
||||
if (ccb->ccb_h.retry_count > 0)
|
||||
ccb->ccb_h.retry_count--;
|
||||
else {
|
||||
action_string = "Retries Exhausted";
|
||||
*action_string = "Retries exhausted";
|
||||
goto sense_error_done;
|
||||
}
|
||||
}
|
||||
@ -1461,8 +1490,9 @@ camperiphscsisenseerror(union ccb *ccb, cam_flags camflags,
|
||||
* Do common portions of commands that
|
||||
* use recovery CCBs.
|
||||
*/
|
||||
if (save_ccb == NULL) {
|
||||
action_string = "No recovery CCB supplied";
|
||||
orig_ccb = xpt_alloc_ccb_nowait();
|
||||
if (orig_ccb == NULL) {
|
||||
*action_string = "Can't allocate recovery CCB";
|
||||
goto sense_error_done;
|
||||
}
|
||||
/*
|
||||
@ -1470,22 +1500,20 @@ camperiphscsisenseerror(union ccb *ccb, cam_flags camflags,
|
||||
* this freeze will be dropped as part of ERESTART.
|
||||
*/
|
||||
ccb->ccb_h.status &= ~CAM_DEV_QFRZN;
|
||||
bcopy(ccb, save_ccb, sizeof(*save_ccb));
|
||||
print_ccb = save_ccb;
|
||||
periph->flags |= CAM_PERIPH_RECOVERY_INPROG;
|
||||
bcopy(ccb, orig_ccb, sizeof(*orig_ccb));
|
||||
}
|
||||
|
||||
switch (err_action & SS_MASK) {
|
||||
case SS_NOP:
|
||||
action_string = "No Recovery Action Needed";
|
||||
*action_string = "No recovery action needed";
|
||||
error = 0;
|
||||
break;
|
||||
case SS_RETRY:
|
||||
action_string = "Retrying Command (per Sense Data)";
|
||||
*action_string = "Retrying command (per sense data)";
|
||||
error = ERESTART;
|
||||
break;
|
||||
case SS_FAIL:
|
||||
action_string = "Unretryable error";
|
||||
*action_string = "Unretryable error";
|
||||
break;
|
||||
case SS_START:
|
||||
{
|
||||
@ -1495,7 +1523,8 @@ camperiphscsisenseerror(union ccb *ccb, cam_flags camflags,
|
||||
* Send a start unit command to the device, and
|
||||
* then retry the command.
|
||||
*/
|
||||
action_string = "Attempting to Start Unit";
|
||||
*action_string = "Attempting to start unit";
|
||||
periph->flags |= CAM_PERIPH_RECOVERY_INPROG;
|
||||
|
||||
/*
|
||||
* Check for removable media and set
|
||||
@ -1530,12 +1559,13 @@ camperiphscsisenseerror(union ccb *ccb, cam_flags camflags,
|
||||
int retries;
|
||||
|
||||
if ((err_action & SSQ_MANY) != 0) {
|
||||
action_string = "Polling device for readiness";
|
||||
*action_string = "Polling device for readiness";
|
||||
retries = 120;
|
||||
} else {
|
||||
action_string = "Testing device for readiness";
|
||||
*action_string = "Testing device for readiness";
|
||||
retries = 1;
|
||||
}
|
||||
periph->flags |= CAM_PERIPH_RECOVERY_INPROG;
|
||||
scsi_test_unit_ready(&ccb->csio,
|
||||
retries,
|
||||
camperiphdone,
|
||||
@ -1553,15 +1583,17 @@ camperiphscsisenseerror(union ccb *ccb, cam_flags camflags,
|
||||
}
|
||||
case SS_REQSENSE:
|
||||
{
|
||||
*action_string = "Requesting SCSI sense data";
|
||||
periph->flags |= CAM_PERIPH_SENSE_INPROG;
|
||||
/*
|
||||
* Send a Request Sense to the device. We
|
||||
* assume that we are in a contingent allegiance
|
||||
* condition so we do not tag this request.
|
||||
*/
|
||||
scsi_request_sense(&ccb->csio, /*retries*/1,
|
||||
camperiphdone,
|
||||
&save_ccb->csio.sense_data,
|
||||
sizeof(save_ccb->csio.sense_data),
|
||||
camperiphsensedone,
|
||||
&orig_ccb->csio.sense_data,
|
||||
sizeof(orig_ccb->csio.sense_data),
|
||||
CAM_TAG_ACTION_NONE,
|
||||
/*sense_len*/SSD_FULL_SIZE,
|
||||
/*timeout*/5000);
|
||||
@ -1580,21 +1612,17 @@ camperiphscsisenseerror(union ccb *ccb, cam_flags camflags,
|
||||
* the proper order before we release normal
|
||||
* transactions to the device.
|
||||
*/
|
||||
ccb->ccb_h.pinfo.priority = CAM_PRIORITY_DEV;
|
||||
ccb->ccb_h.pinfo.priority--;
|
||||
ccb->ccb_h.flags |= CAM_DEV_QFREEZE;
|
||||
ccb->ccb_h.saved_ccb_ptr = save_ccb;
|
||||
ccb->ccb_h.saved_ccb_ptr = orig_ccb;
|
||||
ccb->ccb_h.recovery_depth = 0;
|
||||
error = ERESTART;
|
||||
}
|
||||
|
||||
sense_error_done:
|
||||
if ((err_action & SSQ_PRINT_SENSE) != 0
|
||||
&& (ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0) {
|
||||
cam_error_print(print_ccb, CAM_ESF_ALL, CAM_EPF_ALL);
|
||||
xpt_print_path(ccb->ccb_h.path);
|
||||
if (bootverbose)
|
||||
scsi_sense_print(&print_ccb->csio);
|
||||
printf("%s\n", action_string);
|
||||
}
|
||||
&& (ccb->ccb_h.status & CAM_AUTOSNS_VALID) != 0)
|
||||
cam_error_print(orig_ccb, CAM_ESF_ALL, CAM_EPF_ALL);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
@ -1630,19 +1658,18 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
|
||||
error = camperiphscsistatuserror(ccb,
|
||||
camflags,
|
||||
sense_flags,
|
||||
save_ccb,
|
||||
&openings,
|
||||
&relsim_flags,
|
||||
&timeout);
|
||||
&timeout,
|
||||
&action_string);
|
||||
break;
|
||||
case CAM_AUTOSENSE_FAIL:
|
||||
xpt_print(ccb->ccb_h.path, "AutoSense Failed\n");
|
||||
xpt_print(ccb->ccb_h.path, "AutoSense failed\n");
|
||||
error = EIO; /* we have to kill the command */
|
||||
break;
|
||||
case CAM_ATA_STATUS_ERROR:
|
||||
if (bootverbose && printed == 0) {
|
||||
xpt_print(ccb->ccb_h.path,
|
||||
"Request completed with CAM_ATA_STATUS_ERROR\n");
|
||||
xpt_print(ccb->ccb_h.path, "ATA status error\n");
|
||||
cam_error_print(ccb, CAM_ESF_ALL, CAM_EPF_ALL);
|
||||
printed++;
|
||||
}
|
||||
@ -1669,13 +1696,13 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
|
||||
case CAM_UNCOR_PARITY:
|
||||
if (bootverbose && printed == 0) {
|
||||
xpt_print(ccb->ccb_h.path,
|
||||
"Uncorrected Parity Error\n");
|
||||
"Uncorrected parity error\n");
|
||||
printed++;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case CAM_DATA_RUN_ERR:
|
||||
if (bootverbose && printed == 0) {
|
||||
xpt_print(ccb->ccb_h.path, "Data Overrun\n");
|
||||
xpt_print(ccb->ccb_h.path, "Data overrun\n");
|
||||
printed++;
|
||||
}
|
||||
error = EIO; /* we have to kill the command */
|
||||
@ -1684,7 +1711,7 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
|
||||
ccb->ccb_h.retry_count--;
|
||||
error = ERESTART;
|
||||
} else {
|
||||
action_string = "Retries Exhausted";
|
||||
action_string = "Retries exhausted";
|
||||
error = EIO;
|
||||
}
|
||||
break;
|
||||
@ -1705,7 +1732,7 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
|
||||
error = ERESTART;
|
||||
if (bootverbose && printed == 0) {
|
||||
xpt_print(ccb->ccb_h.path,
|
||||
"Selection Timeout\n");
|
||||
"Selection timeout\n");
|
||||
printed++;
|
||||
}
|
||||
|
||||
@ -1767,7 +1794,7 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
|
||||
/* Unconditional requeue */
|
||||
error = ERESTART;
|
||||
if (bootverbose && printed == 0) {
|
||||
xpt_print(ccb->ccb_h.path, "Request Requeued\n");
|
||||
xpt_print(ccb->ccb_h.path, "Request requeued\n");
|
||||
printed++;
|
||||
}
|
||||
break;
|
||||
@ -1788,13 +1815,13 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
|
||||
ccb->ccb_h.retry_count--;
|
||||
error = ERESTART;
|
||||
if (bootverbose && printed == 0) {
|
||||
xpt_print(ccb->ccb_h.path, "CAM Status 0x%x\n",
|
||||
xpt_print(ccb->ccb_h.path, "CAM status 0x%x\n",
|
||||
status);
|
||||
printed++;
|
||||
}
|
||||
} else {
|
||||
error = EIO;
|
||||
action_string = "Retries Exhausted";
|
||||
action_string = "Retries exhausted";
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1807,11 +1834,13 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
|
||||
!(status == CAM_SEL_TIMEOUT && (camflags & CAM_RETRY_SELTO) == 0)) {
|
||||
if (error != ERESTART) {
|
||||
if (action_string == NULL)
|
||||
action_string = "Unretryable Error";
|
||||
xpt_print(ccb->ccb_h.path, "error %d\n", error);
|
||||
action_string = "Unretryable error";
|
||||
xpt_print(ccb->ccb_h.path, "Error %d, %s\n",
|
||||
error, action_string);
|
||||
} else if (action_string != NULL)
|
||||
xpt_print(ccb->ccb_h.path, "%s\n", action_string);
|
||||
} else
|
||||
xpt_print(ccb->ccb_h.path, "Retrying Command\n");
|
||||
else
|
||||
xpt_print(ccb->ccb_h.path, "Retrying command\n");
|
||||
}
|
||||
|
||||
/* Attempt a retry */
|
||||
|
@ -42,6 +42,7 @@ extern struct cam_periph *xpt_periph;
|
||||
|
||||
extern struct periph_driver **periph_drivers;
|
||||
void periphdriver_register(void *);
|
||||
void periphdriver_init(int level);
|
||||
|
||||
#include <sys/module.h>
|
||||
#define PERIPHDRIVER_DECLARE(name, driver) \
|
||||
@ -117,6 +118,7 @@ struct cam_periph {
|
||||
#define CAM_PERIPH_INVALID 0x08
|
||||
#define CAM_PERIPH_NEW_DEV_FOUND 0x10
|
||||
#define CAM_PERIPH_RECOVERY_INPROG 0x20
|
||||
#define CAM_PERIPH_SENSE_INPROG 0x40
|
||||
u_int32_t immediate_priority;
|
||||
u_int32_t refcount;
|
||||
SLIST_HEAD(, ccb_hdr) ccb_list; /* For "immediate" requests */
|
||||
@ -165,8 +167,10 @@ int cam_periph_ioctl(struct cam_periph *periph, u_long cmd,
|
||||
cam_flags camflags,
|
||||
u_int32_t sense_flags));
|
||||
void cam_freeze_devq(struct cam_path *path);
|
||||
void cam_freeze_devq_arg(struct cam_path *path, u_int32_t flags,
|
||||
uint32_t arg);
|
||||
u_int32_t cam_release_devq(struct cam_path *path, u_int32_t relsim_flags,
|
||||
u_int32_t opening_reduction, u_int32_t timeout,
|
||||
u_int32_t opening_reduction, u_int32_t arg,
|
||||
int getcount_only);
|
||||
void cam_periph_async(struct cam_periph *periph, u_int32_t code,
|
||||
struct cam_path *path, void *arg);
|
||||
|
@ -34,6 +34,7 @@
|
||||
#ifdef _KERNEL
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <cam/cam.h>
|
||||
|
||||
/*
|
||||
* This structure implements a heap based priority queue. The queue
|
||||
@ -47,7 +48,7 @@ struct camq {
|
||||
int array_size;
|
||||
int entries;
|
||||
u_int32_t generation;
|
||||
u_int32_t qfrozen_cnt;
|
||||
u_int32_t qfrozen_cnt[CAM_RL_VALUES];
|
||||
};
|
||||
|
||||
TAILQ_HEAD(ccb_hdr_tailq, ccb_hdr);
|
||||
@ -140,6 +141,10 @@ cam_pinfo *camq_remove(struct camq *queue, int index);
|
||||
/* Index the first element in the heap */
|
||||
#define CAMQ_GET_HEAD(camq) ((camq)->queue_array[CAMQ_HEAD])
|
||||
|
||||
/* Get the first element priority. */
|
||||
#define CAMQ_GET_PRIO(camq) (((camq)->entries > 0) ? \
|
||||
((camq)->queue_array[CAMQ_HEAD]->priority) : 0)
|
||||
|
||||
/*
|
||||
* camq_change_priority: Raise or lower the priority of an entry
|
||||
* maintaining queue order.
|
||||
@ -153,10 +158,10 @@ cam_ccbq_pending_ccb_count(struct cam_ccbq *ccbq);
|
||||
static __inline void
|
||||
cam_ccbq_take_opening(struct cam_ccbq *ccbq);
|
||||
|
||||
static __inline void
|
||||
static __inline int
|
||||
cam_ccbq_insert_ccb(struct cam_ccbq *ccbq, union ccb *new_ccb);
|
||||
|
||||
static __inline void
|
||||
static __inline int
|
||||
cam_ccbq_remove_ccb(struct cam_ccbq *ccbq, union ccb *ccb);
|
||||
|
||||
static __inline union ccb *
|
||||
@ -185,17 +190,31 @@ cam_ccbq_take_opening(struct cam_ccbq *ccbq)
|
||||
ccbq->held++;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
static __inline int
|
||||
cam_ccbq_insert_ccb(struct cam_ccbq *ccbq, union ccb *new_ccb)
|
||||
{
|
||||
ccbq->held--;
|
||||
camq_insert(&ccbq->queue, &new_ccb->ccb_h.pinfo);
|
||||
if (ccbq->queue.qfrozen_cnt[CAM_PRIORITY_TO_RL(
|
||||
new_ccb->ccb_h.pinfo.priority)] > 0) {
|
||||
ccbq->devq_openings++;
|
||||
ccbq->held++;
|
||||
return (1);
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
static __inline int
|
||||
cam_ccbq_remove_ccb(struct cam_ccbq *ccbq, union ccb *ccb)
|
||||
{
|
||||
camq_remove(&ccbq->queue, ccb->ccb_h.pinfo.index);
|
||||
if (ccbq->queue.qfrozen_cnt[CAM_PRIORITY_TO_RL(
|
||||
ccb->ccb_h.pinfo.priority)] > 0) {
|
||||
ccbq->devq_openings--;
|
||||
ccbq->held--;
|
||||
return (1);
|
||||
} else
|
||||
return (0);
|
||||
}
|
||||
|
||||
static __inline union ccb *
|
||||
@ -229,5 +248,81 @@ cam_ccbq_release_opening(struct cam_ccbq *ccbq)
|
||||
ccbq->devq_openings++;
|
||||
}
|
||||
|
||||
static __inline int
|
||||
cam_ccbq_freeze(struct cam_ccbq *ccbq, cam_rl rl, u_int32_t cnt)
|
||||
{
|
||||
int i, frozen = 0;
|
||||
cam_rl p, n;
|
||||
|
||||
/* Find pevious run level. */
|
||||
for (p = 0; p < CAM_RL_VALUES && ccbq->queue.qfrozen_cnt[p] == 0; p++);
|
||||
/* Find new run level. */
|
||||
n = min(rl, p);
|
||||
/* Apply new run level. */
|
||||
for (i = rl; i < CAM_RL_VALUES; i++)
|
||||
ccbq->queue.qfrozen_cnt[i] += cnt;
|
||||
/* Update ccbq statistics. */
|
||||
if (n == p)
|
||||
return (0);
|
||||
for (i = CAMQ_HEAD; i <= ccbq->queue.entries; i++) {
|
||||
cam_rl rrl =
|
||||
CAM_PRIORITY_TO_RL(ccbq->queue.queue_array[i]->priority);
|
||||
if (rrl < n)
|
||||
continue;
|
||||
if (rrl >= p)
|
||||
break;
|
||||
ccbq->devq_openings++;
|
||||
ccbq->held++;
|
||||
frozen++;
|
||||
}
|
||||
return (frozen);
|
||||
}
|
||||
|
||||
static __inline int
|
||||
cam_ccbq_release(struct cam_ccbq *ccbq, cam_rl rl, u_int32_t cnt)
|
||||
{
|
||||
int i, released = 0;
|
||||
cam_rl p, n;
|
||||
|
||||
/* Apply new run level. */
|
||||
for (i = rl; i < CAM_RL_VALUES; i++)
|
||||
ccbq->queue.qfrozen_cnt[i] -= cnt;
|
||||
/* Find new run level. */
|
||||
for (n = 0; n < CAM_RL_VALUES && ccbq->queue.qfrozen_cnt[n] == 0; n++);
|
||||
/* Find previous run level. */
|
||||
p = min(rl, n);
|
||||
/* Update ccbq statistics. */
|
||||
if (n == p)
|
||||
return (0);
|
||||
for (i = CAMQ_HEAD; i <= ccbq->queue.entries; i++) {
|
||||
cam_rl rrl =
|
||||
CAM_PRIORITY_TO_RL(ccbq->queue.queue_array[i]->priority);
|
||||
if (rrl < p)
|
||||
continue;
|
||||
if (rrl >= n)
|
||||
break;
|
||||
ccbq->devq_openings--;
|
||||
ccbq->held--;
|
||||
released++;
|
||||
}
|
||||
return (released);
|
||||
}
|
||||
|
||||
static __inline u_int32_t
|
||||
cam_ccbq_frozen(struct cam_ccbq *ccbq, cam_rl rl)
|
||||
{
|
||||
|
||||
return (ccbq->queue.qfrozen_cnt[rl]);
|
||||
}
|
||||
|
||||
static __inline u_int32_t
|
||||
cam_ccbq_frozen_top(struct cam_ccbq *ccbq)
|
||||
{
|
||||
cam_rl rl;
|
||||
|
||||
rl = CAM_PRIORITY_TO_RL(CAMQ_GET_PRIO(&ccbq->queue));
|
||||
return (ccbq->queue.qfrozen_cnt[rl]);
|
||||
}
|
||||
|
||||
#endif /* _KERNEL */
|
||||
#endif /* _CAM_CAM_QUEUE_H */
|
||||
|
@ -69,7 +69,7 @@ cam_sim_alloc(sim_action_func sim_action, sim_poll_func sim_poll,
|
||||
return (NULL);
|
||||
|
||||
sim = (struct cam_sim *)malloc(sizeof(struct cam_sim),
|
||||
M_CAMSIM, M_NOWAIT);
|
||||
M_CAMSIM, M_ZERO | M_NOWAIT);
|
||||
|
||||
if (sim == NULL)
|
||||
return (NULL);
|
||||
@ -86,6 +86,7 @@ cam_sim_alloc(sim_action_func sim_action, sim_poll_func sim_poll,
|
||||
sim->flags = 0;
|
||||
sim->refcount = 1;
|
||||
sim->devq = queue;
|
||||
sim->max_ccbs = 8; /* Reserve for management purposes. */
|
||||
sim->mtx = mtx;
|
||||
if (mtx == &Giant) {
|
||||
sim->flags |= 0;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -87,6 +87,9 @@ SLIST_HEAD(periph_list, cam_periph);
|
||||
|
||||
void xpt_action(union ccb *new_ccb);
|
||||
void xpt_action_default(union ccb *new_ccb);
|
||||
union ccb *xpt_alloc_ccb(void);
|
||||
union ccb *xpt_alloc_ccb_nowait(void);
|
||||
void xpt_free_ccb(union ccb *free_ccb);
|
||||
void xpt_setup_ccb(struct ccb_hdr *ccb_h,
|
||||
struct cam_path *path,
|
||||
u_int32_t priority);
|
||||
@ -115,6 +118,8 @@ struct cam_periph *xpt_path_periph(struct cam_path *path);
|
||||
void xpt_async(u_int32_t async_code, struct cam_path *path,
|
||||
void *async_arg);
|
||||
void xpt_rescan(union ccb *ccb);
|
||||
void xpt_hold_boot(void);
|
||||
void xpt_release_boot(void);
|
||||
void xpt_lock_buses(void);
|
||||
void xpt_unlock_buses(void);
|
||||
cam_status xpt_register_async(int event, ac_callback_t *cbfunc,
|
||||
|
@ -172,7 +172,6 @@ struct cam_ed * xpt_alloc_device(struct cam_eb *bus,
|
||||
lun_id_t lun_id);
|
||||
void xpt_acquire_device(struct cam_ed *device);
|
||||
void xpt_release_device(struct cam_ed *device);
|
||||
void xpt_run_dev_sendq(struct cam_eb *bus);
|
||||
int xpt_schedule_dev(struct camq *queue, cam_pinfo *dev_pinfo,
|
||||
u_int32_t new_priority);
|
||||
u_int32_t xpt_dev_ccbq_resize(struct cam_path *path, int newopenings);
|
||||
|
@ -39,9 +39,6 @@
|
||||
/* Functions accessed by the peripheral drivers */
|
||||
#ifdef _KERNEL
|
||||
void xpt_polled_action(union ccb *ccb);
|
||||
union ccb *xpt_alloc_ccb(void);
|
||||
union ccb *xpt_alloc_ccb_nowait(void);
|
||||
void xpt_free_ccb(union ccb *free_ccb);
|
||||
void xpt_release_ccb(union ccb *released_ccb);
|
||||
void xpt_schedule(struct cam_periph *perph, u_int32_t new_priority);
|
||||
int32_t xpt_add_periph(struct cam_periph *periph);
|
||||
|
@ -43,8 +43,12 @@ int32_t xpt_bus_deregister(path_id_t path_id);
|
||||
u_int32_t xpt_freeze_simq(struct cam_sim *sim, u_int count);
|
||||
void xpt_release_simq(struct cam_sim *sim, int run_queue);
|
||||
u_int32_t xpt_freeze_devq(struct cam_path *path, u_int count);
|
||||
void xpt_release_devq(struct cam_path *path, u_int count,
|
||||
int run_queue);
|
||||
u_int32_t xpt_freeze_devq_rl(struct cam_path *path, cam_rl rl,
|
||||
u_int count);
|
||||
void xpt_release_devq(struct cam_path *path,
|
||||
u_int count, int run_queue);
|
||||
void xpt_release_devq_rl(struct cam_path *path, cam_rl rl,
|
||||
u_int count, int run_queue);
|
||||
int xpt_sim_opened(struct cam_sim *sim);
|
||||
void xpt_done(union ccb *done_ccb);
|
||||
#endif
|
||||
|
@ -2880,7 +2880,7 @@ scsi_error_action(struct ccb_scsiio *csio, struct scsi_inquiry_data *inq_data,
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef KERNEL
|
||||
#ifdef _KERNEL
|
||||
if (bootverbose)
|
||||
sense_flags |= SF_PRINT_ALWAYS;
|
||||
#endif
|
||||
@ -2995,27 +2995,29 @@ scsi_command_string(struct cam_device *device, struct ccb_scsiio *csio,
|
||||
struct scsi_inquiry_data *inq_data;
|
||||
char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
|
||||
#ifdef _KERNEL
|
||||
struct ccb_getdev cgd;
|
||||
struct ccb_getdev *cgd;
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#ifdef _KERNEL
|
||||
if ((cgd = (struct ccb_getdev*)xpt_alloc_ccb_nowait()) == NULL)
|
||||
return(-1);
|
||||
/*
|
||||
* Get the device information.
|
||||
*/
|
||||
xpt_setup_ccb(&cgd.ccb_h,
|
||||
xpt_setup_ccb(&cgd->ccb_h,
|
||||
csio->ccb_h.path,
|
||||
CAM_PRIORITY_NORMAL);
|
||||
cgd.ccb_h.func_code = XPT_GDEV_TYPE;
|
||||
xpt_action((union ccb *)&cgd);
|
||||
cgd->ccb_h.func_code = XPT_GDEV_TYPE;
|
||||
xpt_action((union ccb *)cgd);
|
||||
|
||||
/*
|
||||
* If the device is unconfigured, just pretend that it is a hard
|
||||
* drive. scsi_op_desc() needs this.
|
||||
*/
|
||||
if (cgd.ccb_h.status == CAM_DEV_NOT_THERE)
|
||||
cgd.inq_data.device = T_DIRECT;
|
||||
if (cgd->ccb_h.status == CAM_DEV_NOT_THERE)
|
||||
cgd->inq_data.device = T_DIRECT;
|
||||
|
||||
inq_data = &cgd.inq_data;
|
||||
inq_data = &cgd->inq_data;
|
||||
|
||||
#else /* !_KERNEL */
|
||||
|
||||
@ -3055,7 +3057,7 @@ scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio,
|
||||
struct scsi_sense_data *sense;
|
||||
struct scsi_inquiry_data *inq_data;
|
||||
#ifdef _KERNEL
|
||||
struct ccb_getdev cgd;
|
||||
struct ccb_getdev *cgd;
|
||||
#endif /* _KERNEL */
|
||||
u_int32_t info;
|
||||
int error_code;
|
||||
@ -3083,23 +3085,25 @@ scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio,
|
||||
#endif /* _KERNEL/!_KERNEL */
|
||||
|
||||
#ifdef _KERNEL
|
||||
if ((cgd = (struct ccb_getdev*)xpt_alloc_ccb_nowait()) == NULL)
|
||||
return(-1);
|
||||
/*
|
||||
* Get the device information.
|
||||
*/
|
||||
xpt_setup_ccb(&cgd.ccb_h,
|
||||
xpt_setup_ccb(&cgd->ccb_h,
|
||||
csio->ccb_h.path,
|
||||
CAM_PRIORITY_NORMAL);
|
||||
cgd.ccb_h.func_code = XPT_GDEV_TYPE;
|
||||
xpt_action((union ccb *)&cgd);
|
||||
cgd->ccb_h.func_code = XPT_GDEV_TYPE;
|
||||
xpt_action((union ccb *)cgd);
|
||||
|
||||
/*
|
||||
* If the device is unconfigured, just pretend that it is a hard
|
||||
* drive. scsi_op_desc() needs this.
|
||||
*/
|
||||
if (cgd.ccb_h.status == CAM_DEV_NOT_THERE)
|
||||
cgd.inq_data.device = T_DIRECT;
|
||||
if (cgd->ccb_h.status == CAM_DEV_NOT_THERE)
|
||||
cgd->inq_data.device = T_DIRECT;
|
||||
|
||||
inq_data = &cgd.inq_data;
|
||||
inq_data = &cgd->inq_data;
|
||||
|
||||
#else /* !_KERNEL */
|
||||
|
||||
@ -3125,9 +3129,12 @@ scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio,
|
||||
* If the sense data is a physical pointer, forget it.
|
||||
*/
|
||||
if (csio->ccb_h.flags & CAM_SENSE_PTR) {
|
||||
if (csio->ccb_h.flags & CAM_SENSE_PHYS)
|
||||
if (csio->ccb_h.flags & CAM_SENSE_PHYS) {
|
||||
#ifdef _KERNEL
|
||||
xpt_free_ccb((union ccb*)cgd);
|
||||
#endif /* _KERNEL/!_KERNEL */
|
||||
return(-1);
|
||||
else {
|
||||
} else {
|
||||
/*
|
||||
* bcopy the pointer to avoid unaligned access
|
||||
* errors on finicky architectures. We don't
|
||||
@ -3145,9 +3152,12 @@ scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio,
|
||||
* dumped on one of the bogus pointer deferences above
|
||||
* already.)
|
||||
*/
|
||||
if (csio->ccb_h.flags & CAM_SENSE_PHYS)
|
||||
if (csio->ccb_h.flags & CAM_SENSE_PHYS) {
|
||||
#ifdef _KERNEL
|
||||
xpt_free_ccb((union ccb*)cgd);
|
||||
#endif /* _KERNEL/!_KERNEL */
|
||||
return(-1);
|
||||
else
|
||||
} else
|
||||
sense = &csio->sense_data;
|
||||
}
|
||||
|
||||
@ -3157,9 +3167,10 @@ scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio,
|
||||
error_code = sense->error_code & SSD_ERRCODE;
|
||||
sense_key = sense->flags & SSD_KEY;
|
||||
|
||||
sbuf_printf(sb, "SCSI sense: ");
|
||||
switch (error_code) {
|
||||
case SSD_DEFERRED_ERROR:
|
||||
sbuf_printf(sb, "Deferred Error: ");
|
||||
sbuf_printf(sb, "Deferred error: ");
|
||||
|
||||
/* FALLTHROUGH */
|
||||
case SSD_CURRENT_ERROR:
|
||||
@ -3212,8 +3223,7 @@ scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio,
|
||||
}
|
||||
}
|
||||
|
||||
sbuf_printf(sb, " asc:%x,%x\n%s%s", asc, ascq,
|
||||
path_str, asc_desc);
|
||||
sbuf_printf(sb, " asc:%x,%x (%s)", asc, ascq, asc_desc);
|
||||
|
||||
if (sense->extra_len >= 7 && sense->fru) {
|
||||
sbuf_printf(sb, " field replaceable unit: %x",
|
||||
@ -3265,7 +3275,7 @@ scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio,
|
||||
|
||||
}
|
||||
default:
|
||||
sbuf_printf(sb, "Sense Error Code 0x%x", sense->error_code);
|
||||
sbuf_printf(sb, "Error code 0x%x", sense->error_code);
|
||||
if (sense->error_code & SSD_ERRCODE_VALID) {
|
||||
sbuf_printf(sb, " at block no. %d (decimal)",
|
||||
info = scsi_4btoul(sense->info));
|
||||
@ -3274,6 +3284,9 @@ scsi_sense_sbuf(struct cam_device *device, struct ccb_scsiio *csio,
|
||||
|
||||
sbuf_printf(sb, "\n");
|
||||
|
||||
#ifdef _KERNEL
|
||||
xpt_free_ccb((union ccb*)cgd);
|
||||
#endif /* _KERNEL/!_KERNEL */
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
@ -433,7 +433,7 @@ cdcleanup(struct cam_periph *periph)
|
||||
callout_stop(&softc->changer->short_handle);
|
||||
softc->changer->flags &= ~CHANGER_SHORT_TMOUT_SCHED;
|
||||
}
|
||||
softc->changer->devq.qfrozen_cnt--;
|
||||
softc->changer->devq.qfrozen_cnt[0]--;
|
||||
softc->changer->flags |= CHANGER_MANUAL_CALL;
|
||||
cdrunchangerqueue(softc->changer);
|
||||
}
|
||||
@ -972,9 +972,9 @@ cdregister(struct cam_periph *periph, void *arg)
|
||||
(void)cam_periph_hold(periph, PRIBIO);
|
||||
|
||||
if ((softc->flags & CD_FLAG_CHANGER) == 0)
|
||||
xpt_schedule(periph, /*priority*/5);
|
||||
xpt_schedule(periph, CAM_PRIORITY_DEV);
|
||||
else
|
||||
cdschedule(periph, /*priority*/ 5);
|
||||
cdschedule(periph, CAM_PRIORITY_DEV);
|
||||
|
||||
return(CAM_REQ_CMP);
|
||||
}
|
||||
@ -1167,13 +1167,13 @@ cdrunchangerqueue(void *arg)
|
||||
* If the changer queue is frozen, that means we have an active
|
||||
* device.
|
||||
*/
|
||||
if (changer->devq.qfrozen_cnt > 0) {
|
||||
if (changer->devq.qfrozen_cnt[0] > 0) {
|
||||
|
||||
/*
|
||||
* We always need to reset the frozen count and clear the
|
||||
* active flag.
|
||||
*/
|
||||
changer->devq.qfrozen_cnt--;
|
||||
changer->devq.qfrozen_cnt[0]--;
|
||||
changer->cur_device->flags &= ~CD_FLAG_ACTIVE;
|
||||
changer->cur_device->flags &= ~CD_FLAG_SCHED_ON_COMP;
|
||||
|
||||
@ -1208,7 +1208,7 @@ cdrunchangerqueue(void *arg)
|
||||
|
||||
changer->cur_device = softc;
|
||||
|
||||
changer->devq.qfrozen_cnt++;
|
||||
changer->devq.qfrozen_cnt[0]++;
|
||||
softc->flags |= CD_FLAG_ACTIVE;
|
||||
|
||||
/* Just in case this device is waiting */
|
||||
@ -1465,7 +1465,7 @@ cdstart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
bioq_remove(&softc->bio_queue, bp);
|
||||
|
||||
scsi_read_write(&start_ccb->csio,
|
||||
/*retries*/cd_retry_count,
|
||||
/*retries*/ cd_retry_count,
|
||||
/* cbfcnp */ cddone,
|
||||
MSG_SIMPLE_Q_TAG,
|
||||
/* read */bp->bio_cmd == BIO_READ,
|
||||
@ -1516,7 +1516,7 @@ cdstart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
}
|
||||
csio = &start_ccb->csio;
|
||||
scsi_read_capacity(csio,
|
||||
/*retries*/1,
|
||||
/*retries*/ cd_retry_count,
|
||||
cddone,
|
||||
MSG_SIMPLE_Q_TAG,
|
||||
rcap,
|
||||
@ -2733,7 +2733,7 @@ cdprevent(struct cam_periph *periph, int action)
|
||||
ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL);
|
||||
|
||||
scsi_prevent(&ccb->csio,
|
||||
/*retries*/ 1,
|
||||
/*retries*/ cd_retry_count,
|
||||
cddone,
|
||||
MSG_SIMPLE_Q_TAG,
|
||||
action,
|
||||
@ -2911,7 +2911,7 @@ cdsize(struct cam_periph *periph, u_int32_t *size)
|
||||
return (ENOMEM);
|
||||
|
||||
scsi_read_capacity(&ccb->csio,
|
||||
/*retries*/ 1,
|
||||
/*retries*/ cd_retry_count,
|
||||
cddone,
|
||||
MSG_SIMPLE_Q_TAG,
|
||||
rcap_buf,
|
||||
@ -3159,7 +3159,7 @@ cdreadtoc(struct cam_periph *periph, u_int32_t mode, u_int32_t start,
|
||||
csio = &ccb->csio;
|
||||
|
||||
cam_fill_csio(csio,
|
||||
/* retries */ 1,
|
||||
/* retries */ cd_retry_count,
|
||||
/* cbfcnp */ cddone,
|
||||
/* flags */ CAM_DIR_IN,
|
||||
/* tag_action */ MSG_SIMPLE_Q_TAG,
|
||||
@ -3206,7 +3206,7 @@ cdreadsubchannel(struct cam_periph *periph, u_int32_t mode,
|
||||
csio = &ccb->csio;
|
||||
|
||||
cam_fill_csio(csio,
|
||||
/* retries */ 1,
|
||||
/* retries */ cd_retry_count,
|
||||
/* cbfcnp */ cddone,
|
||||
/* flags */ CAM_DIR_IN,
|
||||
/* tag_action */ MSG_SIMPLE_Q_TAG,
|
||||
@ -3267,7 +3267,7 @@ cdgetmode(struct cam_periph *periph, struct cd_mode_params *data,
|
||||
param_len = min(param_len, data->alloc_len);
|
||||
|
||||
scsi_mode_sense_len(csio,
|
||||
/* retries */ 1,
|
||||
/* retries */ cd_retry_count,
|
||||
/* cbfcnp */ cddone,
|
||||
/* tag_action */ MSG_SIMPLE_Q_TAG,
|
||||
/* dbd */ 0,
|
||||
@ -3410,7 +3410,7 @@ cdsetmode(struct cam_periph *periph, struct cd_mode_params *data)
|
||||
param_len = min(param_len, data->alloc_len);
|
||||
|
||||
scsi_mode_select_len(csio,
|
||||
/* retries */ 1,
|
||||
/* retries */ cd_retry_count,
|
||||
/* cbfcnp */ cddone,
|
||||
/* tag_action */ MSG_SIMPLE_Q_TAG,
|
||||
/* scsi_page_fmt */ 1,
|
||||
@ -3472,7 +3472,7 @@ cdplay(struct cam_periph *periph, u_int32_t blk, u_int32_t len)
|
||||
cdb_len = sizeof(*scsi_cmd);
|
||||
}
|
||||
cam_fill_csio(csio,
|
||||
/*retries*/2,
|
||||
/*retries*/ cd_retry_count,
|
||||
cddone,
|
||||
/*flags*/CAM_DIR_NONE,
|
||||
MSG_SIMPLE_Q_TAG,
|
||||
@ -3506,7 +3506,7 @@ cdplaymsf(struct cam_periph *periph, u_int32_t startm, u_int32_t starts,
|
||||
csio = &ccb->csio;
|
||||
|
||||
cam_fill_csio(csio,
|
||||
/* retries */ 1,
|
||||
/* retries */ cd_retry_count,
|
||||
/* cbfcnp */ cddone,
|
||||
/* flags */ CAM_DIR_NONE,
|
||||
/* tag_action */ MSG_SIMPLE_Q_TAG,
|
||||
@ -3552,7 +3552,7 @@ cdplaytracks(struct cam_periph *periph, u_int32_t strack, u_int32_t sindex,
|
||||
csio = &ccb->csio;
|
||||
|
||||
cam_fill_csio(csio,
|
||||
/* retries */ 1,
|
||||
/* retries */ cd_retry_count,
|
||||
/* cbfcnp */ cddone,
|
||||
/* flags */ CAM_DIR_NONE,
|
||||
/* tag_action */ MSG_SIMPLE_Q_TAG,
|
||||
@ -3594,7 +3594,7 @@ cdpause(struct cam_periph *periph, u_int32_t go)
|
||||
csio = &ccb->csio;
|
||||
|
||||
cam_fill_csio(csio,
|
||||
/* retries */ 1,
|
||||
/* retries */ cd_retry_count,
|
||||
/* cbfcnp */ cddone,
|
||||
/* flags */ CAM_DIR_NONE,
|
||||
/* tag_action */ MSG_SIMPLE_Q_TAG,
|
||||
@ -3629,7 +3629,7 @@ cdstartunit(struct cam_periph *periph, int load)
|
||||
ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL);
|
||||
|
||||
scsi_start_stop(&ccb->csio,
|
||||
/* retries */ 1,
|
||||
/* retries */ cd_retry_count,
|
||||
/* cbfcnp */ cddone,
|
||||
/* tag_action */ MSG_SIMPLE_Q_TAG,
|
||||
/* start */ TRUE,
|
||||
@ -3657,7 +3657,7 @@ cdstopunit(struct cam_periph *periph, u_int32_t eject)
|
||||
ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL);
|
||||
|
||||
scsi_start_stop(&ccb->csio,
|
||||
/* retries */ 1,
|
||||
/* retries */ cd_retry_count,
|
||||
/* cbfcnp */ cddone,
|
||||
/* tag_action */ MSG_SIMPLE_Q_TAG,
|
||||
/* start */ FALSE,
|
||||
@ -3693,7 +3693,7 @@ cdsetspeed(struct cam_periph *periph, u_int32_t rdspeed, u_int32_t wrspeed)
|
||||
wrspeed *= 177;
|
||||
|
||||
cam_fill_csio(csio,
|
||||
/* retries */ 1,
|
||||
/* retries */ cd_retry_count,
|
||||
/* cbfcnp */ cddone,
|
||||
/* flags */ CAM_DIR_NONE,
|
||||
/* tag_action */ MSG_SIMPLE_Q_TAG,
|
||||
@ -3768,7 +3768,7 @@ cdreportkey(struct cam_periph *periph, struct dvd_authinfo *authinfo)
|
||||
ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL);
|
||||
|
||||
scsi_report_key(&ccb->csio,
|
||||
/* retries */ 1,
|
||||
/* retries */ cd_retry_count,
|
||||
/* cbfcnp */ cddone,
|
||||
/* tag_action */ MSG_SIMPLE_Q_TAG,
|
||||
/* lba */ lba,
|
||||
@ -3946,7 +3946,7 @@ cdsendkey(struct cam_periph *periph, struct dvd_authinfo *authinfo)
|
||||
ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL);
|
||||
|
||||
scsi_send_key(&ccb->csio,
|
||||
/* retries */ 1,
|
||||
/* retries */ cd_retry_count,
|
||||
/* cbfcnp */ cddone,
|
||||
/* tag_action */ MSG_SIMPLE_Q_TAG,
|
||||
/* agid */ authinfo->agid,
|
||||
@ -4050,7 +4050,7 @@ cdreaddvdstructure(struct cam_periph *periph, struct dvd_struct *dvdstruct)
|
||||
ccb = cdgetccb(periph, CAM_PRIORITY_NORMAL);
|
||||
|
||||
scsi_read_dvd_structure(&ccb->csio,
|
||||
/* retries */ 1,
|
||||
/* retries */ cd_retry_count,
|
||||
/* cbfcnp */ cddone,
|
||||
/* tag_action */ MSG_SIMPLE_Q_TAG,
|
||||
/* lba */ address,
|
||||
|
@ -376,7 +376,7 @@ chregister(struct cam_periph *periph, void *arg)
|
||||
* This first call can't block
|
||||
*/
|
||||
(void)cam_periph_hold(periph, PRIBIO);
|
||||
xpt_schedule(periph, /*priority*/5);
|
||||
xpt_schedule(periph, CAM_PRIORITY_DEV);
|
||||
|
||||
return(CAM_REQ_CMP);
|
||||
}
|
||||
|
@ -1272,7 +1272,7 @@ daregister(struct cam_periph *periph, void *arg)
|
||||
* the end of probe.
|
||||
*/
|
||||
(void)cam_periph_hold(periph, PRIBIO);
|
||||
xpt_schedule(periph, /*priority*/5);
|
||||
xpt_schedule(periph, CAM_PRIORITY_DEV);
|
||||
|
||||
/*
|
||||
* Schedule a periodic event to occasionally send an
|
||||
|
@ -895,8 +895,6 @@ scsi_low_target_open(link, cf)
|
||||
#define SCSI_LOW_ALLOC_CCB(flags) scsi_low_get_ccb()
|
||||
|
||||
static void scsi_low_poll_cam(struct cam_sim *);
|
||||
static void scsi_low_cam_rescan_callback(struct cam_periph *, union ccb *);
|
||||
static void scsi_low_rescan_bus_cam(struct scsi_low_softc *);
|
||||
void scsi_low_scsi_action_cam(struct cam_sim *, union ccb *);
|
||||
|
||||
static int scsi_low_attach_cam(struct scsi_low_softc *);
|
||||
@ -954,38 +952,6 @@ scsi_low_poll_cam(sim)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
scsi_low_cam_rescan_callback(periph, ccb)
|
||||
struct cam_periph *periph;
|
||||
union ccb *ccb;
|
||||
{
|
||||
|
||||
xpt_free_path(ccb->ccb_h.path);
|
||||
xpt_free_ccb(ccb);
|
||||
}
|
||||
|
||||
static void
|
||||
scsi_low_rescan_bus_cam(slp)
|
||||
struct scsi_low_softc *slp;
|
||||
{
|
||||
struct cam_path *path;
|
||||
union ccb *ccb;
|
||||
cam_status status;
|
||||
|
||||
status = xpt_create_path(&path, xpt_periph,
|
||||
cam_sim_path(slp->sl_si.sim), -1, 0);
|
||||
if (status != CAM_REQ_CMP)
|
||||
return;
|
||||
|
||||
ccb = xpt_alloc_ccb();
|
||||
bzero(ccb, sizeof(union ccb));
|
||||
xpt_setup_ccb(&ccb->ccb_h, path, 5);
|
||||
ccb->ccb_h.func_code = XPT_SCAN_BUS;
|
||||
ccb->ccb_h.cbfcnp = scsi_low_cam_rescan_callback;
|
||||
ccb->crcn.flags = CAM_FLAG_NONE;
|
||||
xpt_action(ccb);
|
||||
}
|
||||
|
||||
void
|
||||
scsi_low_scsi_action_cam(sim, ccb)
|
||||
struct cam_sim *sim;
|
||||
@ -1376,8 +1342,6 @@ scsi_low_world_start_cam(slp)
|
||||
struct scsi_low_softc *slp;
|
||||
{
|
||||
|
||||
if (!cold)
|
||||
scsi_low_rescan_bus_cam(slp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -563,12 +563,10 @@ passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb)
|
||||
* that request. Otherwise, it's up to the user to perform any
|
||||
* error recovery.
|
||||
*/
|
||||
error = cam_periph_runccb(ccb,
|
||||
(ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER) ?
|
||||
passerror : NULL,
|
||||
/* cam_flags */ CAM_RETRY_SELTO,
|
||||
/* sense_flags */SF_RETRY_UA,
|
||||
softc->device_stats);
|
||||
cam_periph_runccb(ccb,
|
||||
(ccb->ccb_h.flags & CAM_PASS_ERR_RECOVER) ? passerror : NULL,
|
||||
/* cam_flags */ CAM_RETRY_SELTO, /* sense_flags */SF_RETRY_UA,
|
||||
softc->device_stats);
|
||||
|
||||
if (need_unmap != 0)
|
||||
cam_periph_unmapmem(ccb, &mapinfo);
|
||||
@ -577,7 +575,7 @@ passsendccb(struct cam_periph *periph, union ccb *ccb, union ccb *inccb)
|
||||
ccb->ccb_h.periph_priv = inccb->ccb_h.periph_priv;
|
||||
bcopy(ccb, inccb, sizeof(union ccb));
|
||||
|
||||
return(error);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -616,6 +616,11 @@ proberegister(struct cam_periph *periph, void *arg)
|
||||
*/
|
||||
cam_periph_freeze_after_event(periph, &periph->path->bus->last_reset,
|
||||
scsi_delay);
|
||||
/*
|
||||
* Ensure nobody slip in until probe finish.
|
||||
*/
|
||||
cam_freeze_devq_arg(periph->path,
|
||||
RELSIM_RELEASE_RUNLEVEL, CAM_RL_XPT + 1);
|
||||
probeschedule(periph);
|
||||
return(CAM_REQ_CMP);
|
||||
}
|
||||
@ -630,7 +635,7 @@ probeschedule(struct cam_periph *periph)
|
||||
softc = (probe_softc *)periph->softc;
|
||||
ccb = (union ccb *)TAILQ_FIRST(&softc->request_ccbs);
|
||||
|
||||
xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NONE);
|
||||
cpi.ccb_h.func_code = XPT_PATH_INQ;
|
||||
xpt_action((union ccb *)&cpi);
|
||||
|
||||
@ -668,7 +673,7 @@ probeschedule(struct cam_periph *periph)
|
||||
else
|
||||
softc->flags &= ~PROBE_NO_ANNOUNCE;
|
||||
|
||||
xpt_schedule(periph, ccb->ccb_h.pinfo.priority);
|
||||
xpt_schedule(periph, CAM_PRIORITY_XPT);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -881,7 +886,7 @@ proberequestdefaultnegotiation(struct cam_periph *periph)
|
||||
{
|
||||
struct ccb_trans_settings cts;
|
||||
|
||||
xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE);
|
||||
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
|
||||
cts.type = CTS_TYPE_USER_SETTINGS;
|
||||
xpt_action((union ccb *)&cts);
|
||||
@ -903,7 +908,7 @@ proberequestbackoff(struct cam_periph *periph, struct cam_ed *device)
|
||||
struct ccb_trans_settings_spi *spi;
|
||||
|
||||
memset(&cts, 0, sizeof (cts));
|
||||
xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cts.ccb_h, periph->path, CAM_PRIORITY_NONE);
|
||||
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
|
||||
cts.type = CTS_TYPE_CURRENT_SETTINGS;
|
||||
xpt_action((union ccb *)&cts);
|
||||
@ -1420,6 +1425,8 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
done_ccb->ccb_h.status = CAM_REQ_CMP;
|
||||
xpt_done(done_ccb);
|
||||
if (TAILQ_FIRST(&softc->request_ccbs) == NULL) {
|
||||
cam_release_devq(periph->path,
|
||||
RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_XPT + 1, FALSE);
|
||||
cam_periph_invalidate(periph);
|
||||
cam_periph_release_locked(periph);
|
||||
} else {
|
||||
@ -1491,7 +1498,7 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
|
||||
case XPT_SCAN_BUS:
|
||||
{
|
||||
scsi_scan_bus_info *scan_info;
|
||||
union ccb *work_ccb;
|
||||
union ccb *work_ccb, *reset_ccb;
|
||||
struct cam_path *path;
|
||||
u_int i;
|
||||
u_int max_target;
|
||||
@ -1526,6 +1533,26 @@ scsi_scan_bus(struct cam_periph *periph, union ccb *request_ccb)
|
||||
return;
|
||||
}
|
||||
|
||||
/* We may need to reset bus first, if we haven't done it yet. */
|
||||
if ((work_ccb->cpi.hba_inquiry &
|
||||
(PI_WIDE_32|PI_WIDE_16|PI_SDTR_ABLE)) &&
|
||||
!(work_ccb->cpi.hba_misc & PIM_NOBUSRESET) &&
|
||||
!timevalisset(&request_ccb->ccb_h.path->bus->last_reset)) {
|
||||
reset_ccb = xpt_alloc_ccb_nowait();
|
||||
xpt_setup_ccb(&reset_ccb->ccb_h, request_ccb->ccb_h.path,
|
||||
CAM_PRIORITY_NONE);
|
||||
reset_ccb->ccb_h.func_code = XPT_RESET_BUS;
|
||||
xpt_action(reset_ccb);
|
||||
if (reset_ccb->ccb_h.status != CAM_REQ_CMP) {
|
||||
request_ccb->ccb_h.status = reset_ccb->ccb_h.status;
|
||||
xpt_free_ccb(reset_ccb);
|
||||
xpt_free_ccb(work_ccb);
|
||||
xpt_done(request_ccb);
|
||||
return;
|
||||
}
|
||||
xpt_free_ccb(reset_ccb);
|
||||
}
|
||||
|
||||
/* Save some state for use while we probe for devices */
|
||||
scan_info = (scsi_scan_bus_info *)
|
||||
malloc(sizeof(scsi_scan_bus_info), M_CAMXPT, M_NOWAIT);
|
||||
@ -1756,10 +1783,9 @@ scsi_scan_lun(struct cam_periph *periph, struct cam_path *path,
|
||||
struct cam_path *new_path;
|
||||
struct cam_periph *old_periph;
|
||||
|
||||
CAM_DEBUG(request_ccb->ccb_h.path, CAM_DEBUG_TRACE,
|
||||
("scsi_scan_lun\n"));
|
||||
CAM_DEBUG(path, CAM_DEBUG_TRACE, ("scsi_scan_lun\n"));
|
||||
|
||||
xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE);
|
||||
cpi.ccb_h.func_code = XPT_PATH_INQ;
|
||||
xpt_action((union ccb *)&cpi);
|
||||
|
||||
@ -1809,7 +1835,7 @@ scsi_scan_lun(struct cam_periph *periph, struct cam_path *path,
|
||||
free(new_path, M_CAMXPT);
|
||||
return;
|
||||
}
|
||||
xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&request_ccb->ccb_h, new_path, CAM_PRIORITY_XPT);
|
||||
request_ccb->ccb_h.cbfcnp = xptscandone;
|
||||
request_ccb->ccb_h.func_code = XPT_SCAN_LUN;
|
||||
request_ccb->crcn.flags = flags;
|
||||
@ -1907,7 +1933,7 @@ scsi_devise_transport(struct cam_path *path)
|
||||
struct scsi_inquiry_data *inq_buf;
|
||||
|
||||
/* Get transport information from the SIM */
|
||||
xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NONE);
|
||||
cpi.ccb_h.func_code = XPT_PATH_INQ;
|
||||
xpt_action((union ccb *)&cpi);
|
||||
|
||||
@ -1967,7 +1993,7 @@ scsi_devise_transport(struct cam_path *path)
|
||||
*/
|
||||
|
||||
/* Tell the controller what we think */
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
|
||||
cts.ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
|
||||
cts.type = CTS_TYPE_CURRENT_SETTINGS;
|
||||
cts.transport = path->device->transport;
|
||||
@ -2095,7 +2121,7 @@ scsi_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device
|
||||
|
||||
inq_data = &device->inq_data;
|
||||
scsi = &cts->proto_specific.scsi;
|
||||
xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE);
|
||||
cpi.ccb_h.func_code = XPT_PATH_INQ;
|
||||
xpt_action((union ccb *)&cpi);
|
||||
|
||||
@ -2116,7 +2142,7 @@ scsi_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device
|
||||
* Perform sanity checking against what the
|
||||
* controller and device can do.
|
||||
*/
|
||||
xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, CAM_PRIORITY_NONE);
|
||||
cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
|
||||
cur_cts.type = cts->type;
|
||||
xpt_action((union ccb *)&cur_cts);
|
||||
@ -2300,7 +2326,7 @@ scsi_toggle_tags(struct cam_path *path)
|
||||
&& (dev->inq_flags & (SID_Sync|SID_WBus16|SID_WBus32)) != 0)) {
|
||||
struct ccb_trans_settings cts;
|
||||
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NONE);
|
||||
cts.protocol = PROTO_SCSI;
|
||||
cts.protocol_version = PROTO_VERSION_UNSPECIFIED;
|
||||
cts.transport = XPORT_UNSPECIFIED;
|
||||
@ -2350,11 +2376,18 @@ scsi_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target,
|
||||
|
||||
/*
|
||||
* Allow transfer negotiation to occur in a
|
||||
* tag free environment.
|
||||
* tag free environment and after settle delay.
|
||||
*/
|
||||
if (async_code == AC_SENT_BDR
|
||||
|| async_code == AC_BUS_RESET)
|
||||
|| async_code == AC_BUS_RESET) {
|
||||
cam_freeze_devq(&newpath);
|
||||
cam_release_devq(&newpath,
|
||||
RELSIM_RELEASE_AFTER_TIMEOUT,
|
||||
/*reduction*/0,
|
||||
/*timeout*/scsi_delay,
|
||||
/*getcount_only*/0);
|
||||
scsi_toggle_tags(&newpath);
|
||||
}
|
||||
|
||||
if (async_code == AC_INQ_CHANGED) {
|
||||
/*
|
||||
|
@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <cam/cam_ccb.h>
|
||||
#include <cam/cam_sim.h>
|
||||
#include <cam/cam_xpt_sim.h>
|
||||
#include <cam/cam_xpt_periph.h>
|
||||
#include <cam/cam_debug.h>
|
||||
|
||||
/* local prototypes */
|
||||
@ -86,7 +85,7 @@ static void ahci_start_fr(device_t dev);
|
||||
static void ahci_stop_fr(device_t dev);
|
||||
|
||||
static int ahci_sata_connect(struct ahci_channel *ch);
|
||||
static int ahci_sata_phy_reset(device_t dev, int quick);
|
||||
static int ahci_sata_phy_reset(device_t dev);
|
||||
|
||||
static void ahci_issue_read_log(device_t dev);
|
||||
static void ahci_process_read_log(device_t dev, union ccb *ccb);
|
||||
@ -348,6 +347,8 @@ ahci_attach(device_t dev)
|
||||
ctlr->caps = ATA_INL(ctlr->r_mem, AHCI_CAP);
|
||||
if (version >= 0x00010020)
|
||||
ctlr->caps2 = ATA_INL(ctlr->r_mem, AHCI_CAP2);
|
||||
if (ctlr->caps & AHCI_CAP_EMS)
|
||||
ctlr->capsem = ATA_INL(ctlr->r_mem, AHCI_EM_CTL);
|
||||
ctlr->ichannels = ATA_INL(ctlr->r_mem, AHCI_PI);
|
||||
if (ctlr->quirks & AHCI_Q_1CH) {
|
||||
ctlr->caps &= ~AHCI_CAP_NPMASK;
|
||||
@ -417,6 +418,17 @@ ahci_attach(device_t dev)
|
||||
(ctlr->caps2 & AHCI_CAP2_NVMP) ? " NVMP":"",
|
||||
(ctlr->caps2 & AHCI_CAP2_BOH) ? " BOH":"");
|
||||
}
|
||||
if (bootverbose && (ctlr->caps & AHCI_CAP_EMS)) {
|
||||
device_printf(dev, "EM Caps: %s%s%s%s%s%s%s%s\n",
|
||||
(ctlr->capsem & AHCI_EM_PM) ? " PM":"",
|
||||
(ctlr->capsem & AHCI_EM_ALHD) ? " ALHD":"",
|
||||
(ctlr->capsem & AHCI_EM_XMT) ? " XMT":"",
|
||||
(ctlr->capsem & AHCI_EM_SMB) ? " SMB":"",
|
||||
(ctlr->capsem & AHCI_EM_SGPIO) ? " SGPIO":"",
|
||||
(ctlr->capsem & AHCI_EM_SES2) ? " SES-2":"",
|
||||
(ctlr->capsem & AHCI_EM_SAFTE) ? " SAF-TE":"",
|
||||
(ctlr->capsem & AHCI_EM_LED) ? " LED":"");
|
||||
}
|
||||
/* Attach all channels on this controller */
|
||||
for (unit = 0; unit < ctlr->channels; unit++) {
|
||||
if ((ctlr->ichannels & (1 << unit)) == 0)
|
||||
@ -1131,6 +1143,8 @@ ahci_phy_check_events(device_t dev, u_int32_t serr)
|
||||
|
||||
if ((serr & ATA_SE_PHY_CHANGED) && (ch->pm_level == 0)) {
|
||||
u_int32_t status = ATA_INL(ch->r_mem, AHCI_P_SSTS);
|
||||
union ccb *ccb;
|
||||
|
||||
if (((status & ATA_SS_DET_MASK) == ATA_SS_DET_PHY_ONLINE) &&
|
||||
((status & ATA_SS_SPD_MASK) != ATA_SS_SPD_NO_SPEED) &&
|
||||
((status & ATA_SS_IPM_MASK) == ATA_SS_IPM_ACTIVE)) {
|
||||
@ -1142,6 +1156,15 @@ ahci_phy_check_events(device_t dev, u_int32_t serr)
|
||||
device_printf(dev, "DISCONNECT requested\n");
|
||||
ch->devices = 0;
|
||||
}
|
||||
if ((ccb = xpt_alloc_ccb_nowait()) == NULL)
|
||||
return;
|
||||
if (xpt_create_path(&ccb->ccb_h.path, NULL,
|
||||
cam_sim_path(ch->sim),
|
||||
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
||||
xpt_free_ccb(ccb);
|
||||
return;
|
||||
}
|
||||
xpt_rescan(ccb);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1511,6 +1534,13 @@ ahci_execute_transaction(struct ahci_slot *slot)
|
||||
if (timeout && (count >= timeout)) {
|
||||
device_printf(ch->dev,
|
||||
"Poll timeout on slot %d\n", slot->slot);
|
||||
device_printf(dev, "is %08x cs %08x ss %08x "
|
||||
"rs %08x tfd %02x serr %08x\n",
|
||||
ATA_INL(ch->r_mem, AHCI_P_IS),
|
||||
ATA_INL(ch->r_mem, AHCI_P_CI),
|
||||
ATA_INL(ch->r_mem, AHCI_P_SACT), ch->rslots,
|
||||
ATA_INL(ch->r_mem, AHCI_P_TFD),
|
||||
ATA_INL(ch->r_mem, AHCI_P_SERR));
|
||||
et = AHCI_ERR_TIMEOUT;
|
||||
}
|
||||
if (et != AHCI_ERR_NONE) {
|
||||
@ -1935,7 +1965,7 @@ ahci_wait_ready(device_t dev, int t)
|
||||
(ATA_S_BUSY | ATA_S_DRQ)) {
|
||||
DELAY(1000);
|
||||
if (timeout++ > t) {
|
||||
device_printf(dev, "port is not ready (timeout %dms) "
|
||||
device_printf(dev, "device is not ready (timeout %dms) "
|
||||
"tfd = %08x\n", t, val);
|
||||
return (EBUSY);
|
||||
}
|
||||
@ -1952,6 +1982,7 @@ ahci_reset(device_t dev)
|
||||
struct ahci_controller *ctlr = device_get_softc(device_get_parent(dev));
|
||||
int i;
|
||||
|
||||
xpt_freeze_simq(ch->sim, 1);
|
||||
if (bootverbose)
|
||||
device_printf(dev, "AHCI reset...\n");
|
||||
/* Requeue freezed command. */
|
||||
@ -1986,7 +2017,7 @@ ahci_reset(device_t dev)
|
||||
/* Disable port interrupts */
|
||||
ATA_OUTL(ch->r_mem, AHCI_P_IE, 0);
|
||||
/* Reset and reconnect PHY, */
|
||||
if (!ahci_sata_phy_reset(dev, 0)) {
|
||||
if (!ahci_sata_phy_reset(dev)) {
|
||||
if (bootverbose)
|
||||
device_printf(dev,
|
||||
"AHCI reset done: phy reset found no device\n");
|
||||
@ -1994,13 +2025,12 @@ ahci_reset(device_t dev)
|
||||
/* Enable wanted port interrupts */
|
||||
ATA_OUTL(ch->r_mem, AHCI_P_IE,
|
||||
(AHCI_P_IX_CPD | AHCI_P_IX_PRC | AHCI_P_IX_PC));
|
||||
xpt_release_simq(ch->sim, TRUE);
|
||||
return;
|
||||
}
|
||||
/* Wait for clearing busy status. */
|
||||
if (ahci_wait_ready(dev, 10000)) {
|
||||
device_printf(dev, "device ready timeout\n");
|
||||
if (ahci_wait_ready(dev, 15000))
|
||||
ahci_clo(dev);
|
||||
}
|
||||
ahci_start(dev);
|
||||
ch->devices = 1;
|
||||
/* Enable wanted port interrupts */
|
||||
@ -2012,6 +2042,7 @@ ahci_reset(device_t dev)
|
||||
AHCI_P_IX_DS | AHCI_P_IX_PS | (ctlr->ccc ? 0 : AHCI_P_IX_DHR)));
|
||||
if (bootverbose)
|
||||
device_printf(dev, "AHCI reset done: device found\n");
|
||||
xpt_release_simq(ch->sim, TRUE);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -2104,20 +2135,12 @@ ahci_sata_connect(struct ahci_channel *ch)
|
||||
}
|
||||
|
||||
static int
|
||||
ahci_sata_phy_reset(device_t dev, int quick)
|
||||
ahci_sata_phy_reset(device_t dev)
|
||||
{
|
||||
struct ahci_channel *ch = device_get_softc(dev);
|
||||
int sata_rev;
|
||||
uint32_t val;
|
||||
|
||||
if (quick) {
|
||||
val = ATA_INL(ch->r_mem, AHCI_P_SCTL);
|
||||
if ((val & ATA_SC_DET_MASK) == ATA_SC_DET_IDLE)
|
||||
return (ahci_sata_connect(ch));
|
||||
}
|
||||
|
||||
if (bootverbose)
|
||||
device_printf(dev, "hardware reset ...\n");
|
||||
sata_rev = ch->user[ch->pm_present ? 15 : 0].revision;
|
||||
if (sata_rev == 1)
|
||||
val = ATA_SC_SPD_SPEED_GEN1;
|
||||
|
@ -186,6 +186,20 @@
|
||||
#define AHCI_CCCC_EN 0x00000001
|
||||
#define AHCI_CCCP 0x18
|
||||
|
||||
#define AHCI_EM_LOC 0x1C
|
||||
#define AHCI_EM_CTL 0x20
|
||||
#define AHCI_EM_MR 0x00000001
|
||||
#define AHCI_EM_TM 0x00000100
|
||||
#define AHCI_EM_RST 0x00000200
|
||||
#define AHCI_EM_LED 0x00010000
|
||||
#define AHCI_EM_SAFTE 0x00020000
|
||||
#define AHCI_EM_SES2 0x00040000
|
||||
#define AHCI_EM_SGPIO 0x00080000
|
||||
#define AHCI_EM_SMB 0x01000000
|
||||
#define AHCI_EM_XMT 0x02000000
|
||||
#define AHCI_EM_ALHD 0x04000000
|
||||
#define AHCI_EM_PM 0x08000000
|
||||
|
||||
#define AHCI_CAP2 0x24
|
||||
#define AHCI_CAP2_BOH 0x00000001
|
||||
#define AHCI_CAP2_NVMP 0x00000002
|
||||
@ -402,6 +416,7 @@ struct ahci_controller {
|
||||
} irqs[16];
|
||||
uint32_t caps; /* Controller capabilities */
|
||||
uint32_t caps2; /* Controller capabilities */
|
||||
uint32_t capsem; /* Controller capabilities */
|
||||
int quirks;
|
||||
int numirqs;
|
||||
int channels;
|
||||
|
@ -130,7 +130,6 @@
|
||||
#include <cam/cam_ccb.h>
|
||||
#include <cam/cam_sim.h>
|
||||
#include <cam/cam_xpt_sim.h>
|
||||
#include <cam/cam_xpt_periph.h>
|
||||
|
||||
#include <cam/scsi/scsi_all.h>
|
||||
#include <cam/scsi/scsi_message.h>
|
||||
|
@ -55,7 +55,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <cam/cam_ccb.h>
|
||||
#include <cam/cam_sim.h>
|
||||
#include <cam/cam_xpt_sim.h>
|
||||
#include <cam/cam_xpt_periph.h>
|
||||
#include <cam/cam_debug.h>
|
||||
#endif
|
||||
|
||||
@ -289,12 +288,26 @@ ata_detach(device_t dev)
|
||||
static void
|
||||
ata_conn_event(void *context, int dummy)
|
||||
{
|
||||
device_t dev = (device_t)context;
|
||||
struct ata_channel *ch = device_get_softc(dev);
|
||||
device_t dev = (device_t)context;
|
||||
struct ata_channel *ch = device_get_softc(dev);
|
||||
#ifdef ATA_CAM
|
||||
union ccb *ccb;
|
||||
#endif
|
||||
|
||||
mtx_lock(&ch->state_mtx);
|
||||
ata_reinit(dev);
|
||||
mtx_unlock(&ch->state_mtx);
|
||||
mtx_lock(&ch->state_mtx);
|
||||
ata_reinit(dev);
|
||||
mtx_unlock(&ch->state_mtx);
|
||||
#ifdef ATA_CAM
|
||||
if ((ccb = xpt_alloc_ccb()) == NULL)
|
||||
return;
|
||||
if (xpt_create_path(&ccb->ccb_h.path, NULL,
|
||||
cam_sim_path(ch->sim),
|
||||
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
||||
xpt_free_ccb(ccb);
|
||||
return;
|
||||
}
|
||||
xpt_rescan(ccb);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
@ -390,6 +403,7 @@ ata_reinit(device_t dev)
|
||||
/* kick off requests on the queue */
|
||||
ata_start(dev);
|
||||
#else
|
||||
xpt_freeze_simq(ch->sim, 1);
|
||||
if ((request = ch->running)) {
|
||||
ch->running = NULL;
|
||||
if (ch->state == ATA_ACTIVE)
|
||||
@ -404,6 +418,7 @@ ata_reinit(device_t dev)
|
||||
ATA_RESET(dev);
|
||||
/* Tell the XPT about the event */
|
||||
xpt_async(AC_BUS_RESET, ch->path, NULL);
|
||||
xpt_release_simq(ch->sim, TRUE);
|
||||
#endif
|
||||
return(0);
|
||||
}
|
||||
|
@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <cam/cam_periph.h>
|
||||
#include <cam/cam_sim.h>
|
||||
#include <cam/cam_xpt_sim.h>
|
||||
#include <cam/cam_xpt_periph.h>
|
||||
#include <cam/cam_debug.h>
|
||||
#include <cam/scsi/scsi_all.h>
|
||||
|
||||
@ -109,7 +108,6 @@ static int atapi_cam_event_handler(module_t mod, int what, void *arg);
|
||||
/* internal functions */
|
||||
static void reinit_bus(struct atapi_xpt_softc *scp, enum reinit_reason reason);
|
||||
static void setup_async_cb(struct atapi_xpt_softc *, uint32_t);
|
||||
static void cam_rescan_callback(struct cam_periph *, union ccb *);
|
||||
static void cam_rescan(struct cam_sim *);
|
||||
static void free_hcb_and_ccb_done(struct atapi_hcb *, u_int32_t);
|
||||
static struct atapi_hcb *allocate_hcb(struct atapi_xpt_softc *, int, int, union ccb *);
|
||||
@ -315,6 +313,7 @@ reinit_bus(struct atapi_xpt_softc *scp, enum reinit_reason reason) {
|
||||
|
||||
switch (reason) {
|
||||
case BOOT_ATTACH:
|
||||
case ATTACH:
|
||||
break;
|
||||
case RESET:
|
||||
xpt_async(AC_BUS_RESET, scp->path, NULL);
|
||||
@ -322,8 +321,6 @@ reinit_bus(struct atapi_xpt_softc *scp, enum reinit_reason reason) {
|
||||
if (!dev_changed)
|
||||
break;
|
||||
|
||||
/*FALLTHROUGH*/
|
||||
case ATTACH:
|
||||
cam_rescan(scp->sim);
|
||||
break;
|
||||
}
|
||||
@ -821,42 +818,21 @@ atapi_async(void *callback_arg, u_int32_t code,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
|
||||
{
|
||||
if (ccb->ccb_h.status != CAM_REQ_CMP) {
|
||||
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
|
||||
("Rescan failed, 0x%04x\n", ccb->ccb_h.status));
|
||||
} else {
|
||||
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
|
||||
("Rescan succeeded\n"));
|
||||
}
|
||||
xpt_free_path(ccb->ccb_h.path);
|
||||
xpt_free_ccb(ccb);
|
||||
}
|
||||
|
||||
static void
|
||||
cam_rescan(struct cam_sim *sim)
|
||||
{
|
||||
struct cam_path *path;
|
||||
union ccb *ccb;
|
||||
|
||||
ccb = xpt_alloc_ccb_nowait();
|
||||
if (ccb == NULL)
|
||||
return;
|
||||
|
||||
if (xpt_create_path(&path, xpt_periph, cam_sim_path(sim),
|
||||
if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(sim),
|
||||
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
||||
xpt_free_ccb(ccb);
|
||||
return;
|
||||
}
|
||||
|
||||
CAM_DEBUG(path, CAM_DEBUG_TRACE, ("Rescanning ATAPI bus.\n"));
|
||||
xpt_setup_ccb(&ccb->ccb_h, path, 5/*priority (low)*/);
|
||||
ccb->ccb_h.func_code = XPT_SCAN_BUS;
|
||||
ccb->ccb_h.cbfcnp = cam_rescan_callback;
|
||||
ccb->crcn.flags = CAM_FLAG_NONE;
|
||||
xpt_action(ccb);
|
||||
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("Rescanning ATAPI bus.\n"));
|
||||
xpt_rescan(ccb);
|
||||
/* scan is in progress now */
|
||||
}
|
||||
|
||||
|
@ -173,8 +173,6 @@ static void ciss_unmap_request(struct ciss_request *cr);
|
||||
static int ciss_cam_init(struct ciss_softc *sc);
|
||||
static void ciss_cam_rescan_target(struct ciss_softc *sc,
|
||||
int bus, int target);
|
||||
static void ciss_cam_rescan_all(struct ciss_softc *sc);
|
||||
static void ciss_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb);
|
||||
static void ciss_cam_action(struct cam_sim *sim, union ccb *ccb);
|
||||
static int ciss_cam_action_io(struct cam_sim *sim, struct ccb_scsiio *csio);
|
||||
static int ciss_cam_emulate(struct ciss_softc *sc, struct ccb_scsiio *csio);
|
||||
@ -2863,13 +2861,6 @@ ciss_cam_init(struct ciss_softc *sc)
|
||||
mtx_unlock(&sc->ciss_mtx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initiate a rescan of the bus.
|
||||
*/
|
||||
mtx_lock(&sc->ciss_mtx);
|
||||
ciss_cam_rescan_all(sc);
|
||||
mtx_unlock(&sc->ciss_mtx);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
@ -2879,53 +2870,26 @@ ciss_cam_init(struct ciss_softc *sc)
|
||||
static void
|
||||
ciss_cam_rescan_target(struct ciss_softc *sc, int bus, int target)
|
||||
{
|
||||
struct cam_path *path;
|
||||
union ccb *ccb;
|
||||
|
||||
debug_called(1);
|
||||
|
||||
if ((ccb = malloc(sizeof(union ccb), CISS_MALLOC_CLASS, M_NOWAIT | M_ZERO)) == NULL) {
|
||||
if ((ccb = xpt_alloc_ccb_nowait()) == NULL) {
|
||||
ciss_printf(sc, "rescan failed (can't allocate CCB)\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->ciss_cam_sim[bus]),
|
||||
target, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
||||
if (xpt_create_path(&ccb->ccb_h.path, xpt_periph,
|
||||
cam_sim_path(sc->ciss_cam_sim[bus]),
|
||||
target, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
||||
ciss_printf(sc, "rescan failed (can't create path)\n");
|
||||
free(ccb, CISS_MALLOC_CLASS);
|
||||
xpt_free_ccb(ccb);
|
||||
return;
|
||||
}
|
||||
|
||||
xpt_setup_ccb(&ccb->ccb_h, path, 5/*priority (low)*/);
|
||||
ccb->ccb_h.func_code = XPT_SCAN_BUS;
|
||||
ccb->ccb_h.cbfcnp = ciss_cam_rescan_callback;
|
||||
ccb->crcn.flags = CAM_FLAG_NONE;
|
||||
xpt_action(ccb);
|
||||
|
||||
xpt_rescan(ccb);
|
||||
/* scan is now in progress */
|
||||
}
|
||||
|
||||
static void
|
||||
ciss_cam_rescan_all(struct ciss_softc *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Rescan the logical buses */
|
||||
for (i = 0; i < sc->ciss_max_logical_bus; i++)
|
||||
ciss_cam_rescan_target(sc, i, CAM_TARGET_WILDCARD);
|
||||
/* Rescan the physical buses */
|
||||
for (i = CISS_PHYSICAL_BASE; i < sc->ciss_max_physical_bus +
|
||||
CISS_PHYSICAL_BASE; i++)
|
||||
ciss_cam_rescan_target(sc, i, CAM_TARGET_WILDCARD);
|
||||
}
|
||||
|
||||
static void
|
||||
ciss_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
|
||||
{
|
||||
xpt_free_path(ccb->ccb_h.path);
|
||||
free(ccb, CISS_MALLOC_CLASS);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
* Handle requests coming from CAM
|
||||
*/
|
||||
|
@ -79,7 +79,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <cam/cam_sim.h>
|
||||
#include <cam/cam_xpt_sim.h>
|
||||
#include <cam/cam_debug.h>
|
||||
#include <cam/cam_xpt_periph.h>
|
||||
#include <cam/cam_periph.h>
|
||||
#include <cam/scsi/scsi_all.h>
|
||||
#include <cam/scsi/scsi_message.h>
|
||||
@ -105,7 +104,6 @@ static int hptiop_do_ioctl_itl(struct hpt_iop_hba *hba,
|
||||
struct hpt_iop_ioctl_param *pParams);
|
||||
static int hptiop_do_ioctl_mv(struct hpt_iop_hba *hba,
|
||||
struct hpt_iop_ioctl_param *pParams);
|
||||
static void hptiop_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
|
||||
static int hptiop_rescan_bus(struct hpt_iop_hba *hba);
|
||||
static int hptiop_alloc_pci_res_itl(struct hpt_iop_hba *hba);
|
||||
static int hptiop_alloc_pci_res_mv(struct hpt_iop_hba *hba);
|
||||
@ -1035,26 +1033,17 @@ static int hptiop_do_ioctl_mv(struct hpt_iop_hba *hba,
|
||||
|
||||
static int hptiop_rescan_bus(struct hpt_iop_hba * hba)
|
||||
{
|
||||
struct cam_path *path;
|
||||
union ccb *ccb;
|
||||
if (xpt_create_path(&path, xpt_periph, cam_sim_path(hba->sim),
|
||||
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP)
|
||||
return(EIO);
|
||||
if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL)
|
||||
return(ENOMEM);
|
||||
bzero(ccb, sizeof(union ccb));
|
||||
xpt_setup_ccb(&ccb->ccb_h, path, 5);
|
||||
ccb->ccb_h.func_code = XPT_SCAN_BUS;
|
||||
ccb->ccb_h.cbfcnp = hptiop_bus_scan_cb;
|
||||
ccb->crcn.flags = CAM_FLAG_NONE;
|
||||
xpt_action(ccb);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void hptiop_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
|
||||
{
|
||||
xpt_free_path(ccb->ccb_h.path);
|
||||
free(ccb, M_TEMP);
|
||||
if ((ccb = xpt_alloc_ccb()) == NULL)
|
||||
return(ENOMEM);
|
||||
if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(hba->sim),
|
||||
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
||||
xpt_free_ccb(ccb);
|
||||
return(EIO);
|
||||
}
|
||||
xpt_rescan(ccb);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static bus_dmamap_callback_t hptiop_map_srb;
|
||||
@ -1539,8 +1528,6 @@ static int hptiop_attach(device_t dev)
|
||||
hba->ioctl_dev->si_drv1 = hba;
|
||||
#endif
|
||||
|
||||
hptiop_rescan_bus(hba);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
|
@ -989,7 +989,6 @@ static void hpt_stop_tasks(PVBUS_EXT vbus_ext)
|
||||
static d_open_t hpt_open;
|
||||
static d_close_t hpt_close;
|
||||
static d_ioctl_t hpt_ioctl;
|
||||
static void hpt_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
|
||||
static int hpt_rescan_bus(void);
|
||||
|
||||
static struct cdevsw hpt_cdevsw = {
|
||||
@ -1381,7 +1380,6 @@ static int hpt_ioctl(ioctl_dev_t dev, u_long cmd, caddr_t data, int fflag, ioctl
|
||||
|
||||
static int hpt_rescan_bus(void)
|
||||
{
|
||||
struct cam_path *path;
|
||||
union ccb *ccb;
|
||||
PVBUS vbus;
|
||||
PVBUS_EXT vbus_ext;
|
||||
@ -1391,17 +1389,15 @@ static int hpt_rescan_bus(void)
|
||||
#endif
|
||||
|
||||
ldm_for_each_vbus(vbus, vbus_ext) {
|
||||
if (xpt_create_path(&path, xpt_periph, cam_sim_path(vbus_ext->sim),
|
||||
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP)
|
||||
return(EIO);
|
||||
if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL)
|
||||
if ((ccb = xpt_alloc_ccb()) == NULL)
|
||||
return(ENOMEM);
|
||||
bzero(ccb, sizeof(union ccb));
|
||||
xpt_setup_ccb(&ccb->ccb_h, path, 5);
|
||||
ccb->ccb_h.func_code = XPT_SCAN_BUS;
|
||||
ccb->ccb_h.cbfcnp = hpt_bus_scan_cb;
|
||||
ccb->crcn.flags = CAM_FLAG_NONE;
|
||||
xpt_action(ccb);
|
||||
if (xpt_create_path(&ccb->ccb_h.path, xpt_periph,
|
||||
cam_sim_path(vbus_ext->sim),
|
||||
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
||||
xpt_free_ccb(ccb);
|
||||
return(EIO);
|
||||
}
|
||||
xpt_rescan(ccb);
|
||||
}
|
||||
|
||||
#if (__FreeBSD_version >= 500000)
|
||||
@ -1410,15 +1406,3 @@ static int hpt_rescan_bus(void)
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void hpt_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
|
||||
{
|
||||
if (ccb->ccb_h.status != CAM_REQ_CMP)
|
||||
KdPrint(("cam_scan_callback: failure status = %x",ccb->ccb_h.status));
|
||||
else
|
||||
KdPrint(("Scan bus successfully!"));
|
||||
|
||||
xpt_free_path(ccb->ccb_h.path);
|
||||
free(ccb, M_TEMP);
|
||||
return;
|
||||
}
|
||||
|
@ -91,7 +91,6 @@
|
||||
#include <cam/cam_sim.h>
|
||||
#include <cam/cam_xpt_sim.h>
|
||||
#include <cam/cam_debug.h>
|
||||
#include <cam/cam_xpt_periph.h>
|
||||
#include <cam/cam_periph.h>
|
||||
#include <cam/scsi/scsi_all.h>
|
||||
#include <cam/scsi/scsi_message.h>
|
||||
|
@ -101,7 +101,6 @@ static void mly_unmap_command(struct mly_command *mc);
|
||||
static int mly_cam_attach(struct mly_softc *sc);
|
||||
static void mly_cam_detach(struct mly_softc *sc);
|
||||
static void mly_cam_rescan_btl(struct mly_softc *sc, int bus, int target);
|
||||
static void mly_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb);
|
||||
static void mly_cam_action(struct cam_sim *sim, union ccb *ccb);
|
||||
static int mly_cam_action_io(struct cam_sim *sim, struct ccb_scsiio *csio);
|
||||
static void mly_cam_poll(struct cam_sim *sim);
|
||||
@ -2017,29 +2016,18 @@ mly_cam_rescan_btl(struct mly_softc *sc, int bus, int target)
|
||||
|
||||
debug_called(1);
|
||||
|
||||
if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK | M_ZERO)) == NULL) {
|
||||
if ((ccb = xpt_alloc_ccb()) == NULL) {
|
||||
mly_printf(sc, "rescan failed (can't allocate CCB)\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (xpt_create_path(&sc->mly_cam_path, xpt_periph,
|
||||
cam_sim_path(sc->mly_cam_sim[bus]), target, 0) != CAM_REQ_CMP) {
|
||||
if (xpt_create_path(&ccb->ccb_h.path, xpt_periph,
|
||||
cam_sim_path(sc->mly_cam_sim[bus]), target, 0) != CAM_REQ_CMP) {
|
||||
mly_printf(sc, "rescan failed (can't create path)\n");
|
||||
free(ccb, M_TEMP);
|
||||
xpt_free_ccb(ccb);
|
||||
return;
|
||||
}
|
||||
xpt_setup_ccb(&ccb->ccb_h, sc->mly_cam_path, 5/*priority (low)*/);
|
||||
ccb->ccb_h.func_code = XPT_SCAN_LUN;
|
||||
ccb->ccb_h.cbfcnp = mly_cam_rescan_callback;
|
||||
ccb->crcn.flags = CAM_FLAG_NONE;
|
||||
debug(1, "rescan target %d:%d", bus, target);
|
||||
xpt_action(ccb);
|
||||
}
|
||||
|
||||
static void
|
||||
mly_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
|
||||
{
|
||||
free(ccb, M_TEMP);
|
||||
xpt_rescan(ccb);
|
||||
}
|
||||
|
||||
/********************************************************************************
|
||||
|
@ -102,7 +102,6 @@
|
||||
#include <cam/cam_sim.h>
|
||||
#include <cam/cam_xpt.h>
|
||||
#include <cam/cam_periph.h>
|
||||
#include <cam/cam_xpt_periph.h>
|
||||
#include <cam/cam_xpt_sim.h>
|
||||
#include <cam/cam_debug.h>
|
||||
#include <cam/scsi/scsi_all.h>
|
||||
|
@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <cam/cam.h>
|
||||
#include <cam/cam_ccb.h>
|
||||
#include <cam/cam_sim.h>
|
||||
#include <cam/cam_xpt_periph.h>
|
||||
#include <cam/cam_xpt_sim.h>
|
||||
|
||||
#if __FreeBSD_version < 500000
|
||||
@ -655,14 +654,6 @@ mpt_terminate_raid_thread(struct mpt_softc *mpt)
|
||||
mpt_sleep(mpt, &mpt->raid_thread, PUSER, "thtrm", 0);
|
||||
}
|
||||
|
||||
static void
|
||||
mpt_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
|
||||
{
|
||||
|
||||
xpt_free_path(ccb->ccb_h.path);
|
||||
xpt_free_ccb(ccb);
|
||||
}
|
||||
|
||||
static void
|
||||
mpt_raid_thread(void *arg)
|
||||
{
|
||||
@ -715,13 +706,7 @@ mpt_raid_thread(void *arg)
|
||||
xpt_free_ccb(ccb);
|
||||
mpt_prt(mpt, "Unable to rescan RAID Bus!\n");
|
||||
} else {
|
||||
xpt_setup_ccb(&ccb->ccb_h, path, 5);
|
||||
ccb->ccb_h.func_code = XPT_SCAN_BUS;
|
||||
ccb->ccb_h.cbfcnp = mpt_cam_rescan_callback;
|
||||
ccb->crcn.flags = CAM_FLAG_NONE;
|
||||
MPTLOCK_2_CAMLOCK(mpt);
|
||||
xpt_action(ccb);
|
||||
CAMLOCK_2_MPTLOCK(mpt);
|
||||
xpt_rescan(ccb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -83,9 +83,6 @@ struct vpo_data {
|
||||
/* cam related functions */
|
||||
static void vpo_action(struct cam_sim *sim, union ccb *ccb);
|
||||
static void vpo_poll(struct cam_sim *sim);
|
||||
static void vpo_cam_rescan_callback(struct cam_periph *periph,
|
||||
union ccb *ccb);
|
||||
static void vpo_cam_rescan(struct vpo_data *vpo);
|
||||
|
||||
static void
|
||||
vpo_identify(driver_t *driver, device_t parent)
|
||||
@ -176,44 +173,10 @@ vpo_attach(device_t dev)
|
||||
return (ENXIO);
|
||||
}
|
||||
ppb_unlock(ppbus);
|
||||
vpo_cam_rescan(vpo); /* have CAM rescan the bus */
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
vpo_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
|
||||
{
|
||||
|
||||
free(ccb, M_TEMP);
|
||||
}
|
||||
|
||||
static void
|
||||
vpo_cam_rescan(struct vpo_data *vpo)
|
||||
{
|
||||
device_t ppbus = device_get_parent(vpo->vpo_dev);
|
||||
struct cam_path *path;
|
||||
union ccb *ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK | M_ZERO);
|
||||
|
||||
ppb_lock(ppbus);
|
||||
if (xpt_create_path(&path, xpt_periph, cam_sim_path(vpo->sim), 0, 0)
|
||||
!= CAM_REQ_CMP) {
|
||||
/* A failure is benign as the user can do a manual rescan */
|
||||
ppb_unlock(ppbus);
|
||||
free(ccb, M_TEMP);
|
||||
return;
|
||||
}
|
||||
|
||||
xpt_setup_ccb(&ccb->ccb_h, path, 5/*priority (low)*/);
|
||||
ccb->ccb_h.func_code = XPT_SCAN_BUS;
|
||||
ccb->ccb_h.cbfcnp = vpo_cam_rescan_callback;
|
||||
ccb->crcn.flags = CAM_FLAG_NONE;
|
||||
xpt_action(ccb);
|
||||
ppb_unlock(ppbus);
|
||||
|
||||
/* The scan is in progress now. */
|
||||
}
|
||||
|
||||
/*
|
||||
* vpo_intr()
|
||||
*/
|
||||
|
@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <cam/cam_ccb.h>
|
||||
#include <cam/cam_sim.h>
|
||||
#include <cam/cam_xpt_sim.h>
|
||||
#include <cam/cam_xpt_periph.h>
|
||||
#include <cam/cam_debug.h>
|
||||
|
||||
/* local prototypes */
|
||||
@ -740,6 +739,8 @@ siis_phy_check_events(device_t dev)
|
||||
/* If we have a connection event, deal with it */
|
||||
if (ch->pm_level == 0) {
|
||||
u_int32_t status = ATA_INL(ch->r_mem, SIIS_P_SSTS);
|
||||
union ccb *ccb;
|
||||
|
||||
if (((status & ATA_SS_DET_MASK) == ATA_SS_DET_PHY_ONLINE) &&
|
||||
((status & ATA_SS_SPD_MASK) != ATA_SS_SPD_NO_SPEED) &&
|
||||
((status & ATA_SS_IPM_MASK) == ATA_SS_IPM_ACTIVE)) {
|
||||
@ -751,6 +752,15 @@ siis_phy_check_events(device_t dev)
|
||||
device_printf(dev, "DISCONNECT requested\n");
|
||||
ch->devices = 0;
|
||||
}
|
||||
if ((ccb = xpt_alloc_ccb_nowait()) == NULL)
|
||||
return;
|
||||
if (xpt_create_path(&ccb->ccb_h.path, NULL,
|
||||
cam_sim_path(ch->sim),
|
||||
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
||||
xpt_free_ccb(ccb);
|
||||
return;
|
||||
}
|
||||
xpt_rescan(ccb);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1025,6 +1035,13 @@ siis_execute_transaction(struct siis_slot *slot)
|
||||
if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
|
||||
ctp->control |= htole16(SIIS_PRB_PACKET_WRITE);
|
||||
}
|
||||
/* Special handling for Soft Reset command. */
|
||||
if ((ccb->ccb_h.func_code == XPT_ATA_IO) &&
|
||||
(ccb->ataio.cmd.flags & CAM_ATAIO_CONTROL) &&
|
||||
(ccb->ataio.cmd.control & ATA_A_RESET)) {
|
||||
/* Kick controller into sane state */
|
||||
siis_portinit(dev);
|
||||
}
|
||||
/* Setup the FIS for this request */
|
||||
if (!siis_setup_fis(dev, ctp, ccb, slot->slot)) {
|
||||
device_printf(ch->dev, "Setting up SATA FIS failed\n");
|
||||
@ -1081,10 +1098,11 @@ siis_timeout(struct siis_slot *slot)
|
||||
if (slot->state < SIIS_SLOT_RUNNING)
|
||||
return;
|
||||
device_printf(dev, "Timeout on slot %d\n", slot->slot);
|
||||
device_printf(dev, "%s is %08x ss %08x rs %08x es %08x sts %08x serr %08x\n",
|
||||
__func__, ATA_INL(ch->r_mem, SIIS_P_IS), ATA_INL(ch->r_mem, SIIS_P_SS), ch->rslots,
|
||||
ATA_INL(ch->r_mem, SIIS_P_CMDERR), ATA_INL(ch->r_mem, SIIS_P_STS),
|
||||
ATA_INL(ch->r_mem, SIIS_P_SERR));
|
||||
device_printf(dev, "%s is %08x ss %08x rs %08x es %08x sts %08x serr %08x\n",
|
||||
__func__, ATA_INL(ch->r_mem, SIIS_P_IS),
|
||||
ATA_INL(ch->r_mem, SIIS_P_SS), ch->rslots,
|
||||
ATA_INL(ch->r_mem, SIIS_P_CMDERR), ATA_INL(ch->r_mem, SIIS_P_STS),
|
||||
ATA_INL(ch->r_mem, SIIS_P_SERR));
|
||||
|
||||
if (ch->toslots == 0)
|
||||
xpt_freeze_simq(ch->sim, 1);
|
||||
@ -1368,8 +1386,6 @@ siis_devreset(device_t dev)
|
||||
return (EBUSY);
|
||||
}
|
||||
}
|
||||
if (bootverbose)
|
||||
device_printf(dev, "device reset time=%dms\n", timeout);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1389,8 +1405,6 @@ siis_wait_ready(device_t dev, int t)
|
||||
return (EBUSY);
|
||||
}
|
||||
}
|
||||
if (bootverbose)
|
||||
device_printf(dev, "ready wait time=%dms\n", timeout);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1401,6 +1415,7 @@ siis_reset(device_t dev)
|
||||
int i, retry = 0, sata_rev;
|
||||
uint32_t val;
|
||||
|
||||
xpt_freeze_simq(ch->sim, 1);
|
||||
if (bootverbose)
|
||||
device_printf(dev, "SIIS reset...\n");
|
||||
if (!ch->readlog && !ch->recovery)
|
||||
@ -1466,6 +1481,7 @@ siis_reset(device_t dev)
|
||||
"SIIS reset done: phy reset found no device\n");
|
||||
/* Tell the XPT about the event */
|
||||
xpt_async(AC_BUS_RESET, ch->path, NULL);
|
||||
xpt_release_simq(ch->sim, TRUE);
|
||||
return;
|
||||
}
|
||||
/* Wait for clearing busy status. */
|
||||
@ -1496,6 +1512,7 @@ siis_reset(device_t dev)
|
||||
device_printf(dev, "SIIS reset done: devices=%08x\n", ch->devices);
|
||||
/* Tell the XPT about the event */
|
||||
xpt_async(AC_BUS_RESET, ch->path, NULL);
|
||||
xpt_release_simq(ch->sim, TRUE);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -746,15 +746,6 @@ trm_action(struct cam_sim *psim, union ccb *pccb)
|
||||
pccb->ccb_h.status = CAM_REQ_INVALID;
|
||||
xpt_done(pccb);
|
||||
break;
|
||||
/*
|
||||
* (Re)Scan the SCSI Bus
|
||||
* Rescan the given bus, or bus/target/lun
|
||||
*/
|
||||
case XPT_SCAN_BUS:
|
||||
TRM_DPRINTF(" XPT_SCAN_BUS \n");
|
||||
pccb->ccb_h.status = CAM_REQ_INVALID;
|
||||
xpt_done(pccb);
|
||||
break;
|
||||
/*
|
||||
* Get EDT entries matching the given pattern
|
||||
*/
|
||||
@ -818,15 +809,6 @@ trm_action(struct cam_sim *psim, union ccb *pccb)
|
||||
pccb->ccb_h.status = CAM_REQ_INVALID;
|
||||
xpt_done(pccb);
|
||||
break;
|
||||
/*
|
||||
* Scan Logical Unit
|
||||
*/
|
||||
case XPT_SCAN_LUN:
|
||||
TRM_DPRINTF(" XPT_SCAN_LUN \n");
|
||||
pccb->ccb_h.status = CAM_REQ_INVALID;
|
||||
xpt_done(pccb);
|
||||
break;
|
||||
|
||||
/*
|
||||
* Get/Set transfer rate/width/disconnection/tag queueing
|
||||
* settings
|
||||
|
@ -56,7 +56,6 @@
|
||||
static TW_VOID twa_action(struct cam_sim *sim, union ccb *ccb);
|
||||
static TW_VOID twa_poll(struct cam_sim *sim);
|
||||
static TW_VOID twa_timeout(TW_VOID *arg);
|
||||
static TW_VOID twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb);
|
||||
|
||||
static TW_INT32 tw_osli_execute_scsi(struct tw_osli_req_context *req,
|
||||
union ccb *ccb);
|
||||
@ -76,7 +75,6 @@ TW_INT32
|
||||
tw_osli_cam_attach(struct twa_softc *sc)
|
||||
{
|
||||
struct cam_devq *devq;
|
||||
TW_INT32 error;
|
||||
|
||||
tw_osli_dbg_dprintf(3, sc, "entered");
|
||||
|
||||
@ -149,23 +147,8 @@ tw_osli_cam_attach(struct twa_softc *sc)
|
||||
mtx_unlock(sc->sim_lock);
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
tw_osli_dbg_dprintf(3, sc, "Calling xpt_setup_ccb");
|
||||
mtx_unlock(sc->sim_lock);
|
||||
|
||||
tw_osli_dbg_dprintf(3, sc, "Calling tw_osli_request_bus_scan");
|
||||
/*
|
||||
* Request a bus scan, so that CAM gets to know of
|
||||
* the logical units that we control.
|
||||
*/
|
||||
if ((error = tw_osli_request_bus_scan(sc)))
|
||||
tw_osli_printf(sc, "error = %d",
|
||||
TW_CL_SEVERITY_ERROR_STRING,
|
||||
TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER,
|
||||
0x2104,
|
||||
"Bus scan request to CAM failed",
|
||||
error);
|
||||
|
||||
tw_osli_dbg_dprintf(3, sc, "exiting");
|
||||
return(0);
|
||||
}
|
||||
@ -561,7 +544,6 @@ twa_timeout(TW_VOID *arg)
|
||||
TW_INT32
|
||||
tw_osli_request_bus_scan(struct twa_softc *sc)
|
||||
{
|
||||
struct cam_path *path;
|
||||
union ccb *ccb;
|
||||
|
||||
tw_osli_dbg_dprintf(3, sc, "entering");
|
||||
@ -569,13 +551,12 @@ tw_osli_request_bus_scan(struct twa_softc *sc)
|
||||
/* If we get here before sc->sim is initialized, return an error. */
|
||||
if (!(sc->sim))
|
||||
return(ENXIO);
|
||||
if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL)
|
||||
if ((ccb = xpt_alloc_ccb()) == NULL)
|
||||
return(ENOMEM);
|
||||
bzero(ccb, sizeof(union ccb));
|
||||
mtx_lock(sc->sim_lock);
|
||||
if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->sim),
|
||||
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
||||
free(ccb, M_TEMP);
|
||||
if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(sc->sim),
|
||||
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
|
||||
xpt_free_ccb(ccb);
|
||||
mtx_unlock(sc->sim_lock);
|
||||
return(EIO);
|
||||
}
|
||||
@ -586,43 +567,13 @@ tw_osli_request_bus_scan(struct twa_softc *sc)
|
||||
sc->state &= ~TW_OSLI_CTLR_STATE_SIMQ_FROZEN;
|
||||
}
|
||||
|
||||
xpt_setup_ccb(&ccb->ccb_h, path, 5);
|
||||
ccb->ccb_h.func_code = XPT_SCAN_BUS;
|
||||
ccb->ccb_h.cbfcnp = twa_bus_scan_cb;
|
||||
ccb->crcn.flags = CAM_FLAG_NONE;
|
||||
xpt_action(ccb);
|
||||
xpt_rescan(ccb);
|
||||
mtx_unlock(sc->sim_lock);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Function name: twa_bus_scan_cb
|
||||
* Description: Callback from CAM on a bus scan request.
|
||||
*
|
||||
* Input: periph -- we don't use this
|
||||
* ccb -- bus scan request ccb that we sent to CAM
|
||||
* Output: None
|
||||
* Return value: None
|
||||
*/
|
||||
static TW_VOID
|
||||
twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb)
|
||||
{
|
||||
tw_osli_dbg_printf(3, "entering");
|
||||
|
||||
if (ccb->ccb_h.status != CAM_REQ_CMP)
|
||||
printf("cam_scan_callback: failure status = %x\n",
|
||||
ccb->ccb_h.status);
|
||||
else
|
||||
tw_osli_dbg_printf(3, "success");
|
||||
|
||||
xpt_free_path(ccb->ccb_h.path);
|
||||
free(ccb, M_TEMP);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Function name: tw_osli_allow_new_requests
|
||||
* Description: Sets the appropriate status bits in a ccb such that,
|
||||
|
@ -469,8 +469,6 @@ static void umass_cbi_start_status(struct umass_softc *);
|
||||
static void umass_t_cbi_data_clear_stall_callback(struct usb_xfer *,
|
||||
uint8_t, uint8_t, usb_error_t);
|
||||
static int umass_cam_attach_sim(struct umass_softc *);
|
||||
static void umass_cam_rescan_callback(struct cam_periph *, union ccb *);
|
||||
static void umass_cam_rescan(struct umass_softc *);
|
||||
static void umass_cam_attach(struct umass_softc *);
|
||||
static void umass_cam_detach_sim(struct umass_softc *);
|
||||
static void umass_cam_action(struct cam_sim *, union ccb *);
|
||||
@ -2144,68 +2142,6 @@ umass_cam_attach_sim(struct umass_softc *sc)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
umass_cam_rescan_callback(struct cam_periph *periph, union ccb *ccb)
|
||||
{
|
||||
#if USB_DEBUG
|
||||
struct umass_softc *sc = NULL;
|
||||
|
||||
if (ccb->ccb_h.status != CAM_REQ_CMP) {
|
||||
DPRINTF(sc, UDMASS_SCSI, "%s:%d Rescan failed, 0x%04x\n",
|
||||
periph->periph_name, periph->unit_number,
|
||||
ccb->ccb_h.status);
|
||||
} else {
|
||||
DPRINTF(sc, UDMASS_SCSI, "%s%d: Rescan succeeded\n",
|
||||
periph->periph_name, periph->unit_number);
|
||||
}
|
||||
#endif
|
||||
|
||||
xpt_free_path(ccb->ccb_h.path);
|
||||
free(ccb, M_USBDEV);
|
||||
}
|
||||
|
||||
static void
|
||||
umass_cam_rescan(struct umass_softc *sc)
|
||||
{
|
||||
struct cam_path *path;
|
||||
union ccb *ccb;
|
||||
|
||||
DPRINTF(sc, UDMASS_SCSI, "scbus%d: scanning for %d:%d:%d\n",
|
||||
cam_sim_path(sc->sc_sim),
|
||||
cam_sim_path(sc->sc_sim),
|
||||
sc->sc_unit, CAM_LUN_WILDCARD);
|
||||
|
||||
ccb = malloc(sizeof(*ccb), M_USBDEV, M_WAITOK | M_ZERO);
|
||||
|
||||
if (ccb == NULL) {
|
||||
return;
|
||||
}
|
||||
#if (__FreeBSD_version >= 700037)
|
||||
mtx_lock(&sc->sc_mtx);
|
||||
#endif
|
||||
|
||||
if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->sc_sim),
|
||||
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD)
|
||||
!= CAM_REQ_CMP) {
|
||||
#if (__FreeBSD_version >= 700037)
|
||||
mtx_unlock(&sc->sc_mtx);
|
||||
#endif
|
||||
free(ccb, M_USBDEV);
|
||||
return;
|
||||
}
|
||||
xpt_setup_ccb(&ccb->ccb_h, path, 5 /* priority (low) */ );
|
||||
ccb->ccb_h.func_code = XPT_SCAN_BUS;
|
||||
ccb->ccb_h.cbfcnp = &umass_cam_rescan_callback;
|
||||
ccb->crcn.flags = CAM_FLAG_NONE;
|
||||
xpt_action(ccb);
|
||||
|
||||
#if (__FreeBSD_version >= 700037)
|
||||
mtx_unlock(&sc->sc_mtx);
|
||||
#endif
|
||||
|
||||
/* The scan is in progress now. */
|
||||
}
|
||||
|
||||
static void
|
||||
umass_cam_attach(struct umass_softc *sc)
|
||||
{
|
||||
@ -2216,19 +2152,6 @@ umass_cam_attach(struct umass_softc *sc)
|
||||
sc->sc_name, cam_sim_path(sc->sc_sim),
|
||||
sc->sc_unit, CAM_LUN_WILDCARD,
|
||||
cam_sim_path(sc->sc_sim));
|
||||
|
||||
if (!cold) {
|
||||
/*
|
||||
* Notify CAM of the new device after a short delay. Any
|
||||
* failure is benign, as the user can still do it by hand
|
||||
* (camcontrol rescan <busno>). Only do this if we are not
|
||||
* booting, because CAM does a scan after booting has
|
||||
* completed, when interrupts have been enabled.
|
||||
*/
|
||||
|
||||
/* scan the new sim */
|
||||
umass_cam_rescan(sc);
|
||||
}
|
||||
}
|
||||
|
||||
/* umass_cam_detach
|
||||
|
Loading…
Reference in New Issue
Block a user