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:
Alexander Motin 2010-01-28 08:41:30 +00:00
parent e59faa5014
commit 83c5d981ac
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=203108
40 changed files with 1051 additions and 1184 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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