Add infrastructure to the ATA and SCSI transports that supports
using a driver-supplied sbuf for printing device discovery announcements. This helps ensure that messages to the console will be properly serialized (through sbuf_putbuf) and not be truncated and interleaved with other messages. The infrastructure mirrors the existing xpt_announce_periph() entry point and is opt-in for now. No content or formatting changes are visible to the operator other than the new coherency. While here, eliminate the stack usage of the temporary announcement buffer in some of the drivers. It's moved to the softc for now, but future work will eliminate it entirely by making the code flow more linear. Future work will also address locking so that the sbufs can be dynamically sized. The scsi_da, scs_cd, scsi_ses, and ata_da drivers are converted at this point, other drivers can be converted at a later date. A tunable+sysctl, kern.cam.announce_nosbuf, exists for testing purposes but will be removed later. TODO: Eliminate all of the code duplication and temporary buffers. The old printf-based methods will be retired, and xpt_announce_periph() will just be a wrapper that uses a dynamically sized sbuf. This requires that the register and deregister paths be made malloc-safe, which they aren't currently. Sponsored by: Netflix
This commit is contained in:
parent
7b8306bcd2
commit
5d01277f59
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=317143
@ -382,12 +382,10 @@ void
|
||||
ata_print_ident(struct ata_params *ident_data)
|
||||
{
|
||||
const char *proto;
|
||||
char product[48], revision[16], ata[12], sata[12];
|
||||
char ata[12], sata[12];
|
||||
|
||||
ata_print_ident_short(ident_data);
|
||||
|
||||
cam_strvis(product, ident_data->model, sizeof(ident_data->model),
|
||||
sizeof(product));
|
||||
cam_strvis(revision, ident_data->revision, sizeof(ident_data->revision),
|
||||
sizeof(revision));
|
||||
proto = (ident_data->config == ATA_PROTO_CFA) ? "CFA" :
|
||||
(ident_data->config & ATA_PROTO_ATAPI) ? "ATAPI" : "ATA";
|
||||
if (ata_version(ident_data->version_major) == 0) {
|
||||
@ -412,7 +410,55 @@ ata_print_ident(struct ata_params *ident_data)
|
||||
snprintf(sata, sizeof(sata), " SATA");
|
||||
} else
|
||||
sata[0] = 0;
|
||||
printf("<%s %s> %s%s device\n", product, revision, ata, sata);
|
||||
printf(" %s%s device\n", ata, sata);
|
||||
}
|
||||
|
||||
void
|
||||
ata_print_ident_sbuf(struct ata_params *ident_data, struct sbuf *sb)
|
||||
{
|
||||
const char *proto, *sata;
|
||||
int version;
|
||||
|
||||
ata_print_ident_short_sbuf(ident_data, sb);
|
||||
sbuf_printf(sb, " ");
|
||||
|
||||
proto = (ident_data->config == ATA_PROTO_CFA) ? "CFA" :
|
||||
(ident_data->config & ATA_PROTO_ATAPI) ? "ATAPI" : "ATA";
|
||||
version = ata_version(ident_data->version_major);
|
||||
|
||||
switch (version) {
|
||||
case 0:
|
||||
sbuf_printf(sb, "%s", proto);
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
sbuf_printf(sb, "%s-%d", proto, version);
|
||||
break;
|
||||
case 8:
|
||||
sbuf_printf(sb, "%s8-ACS", proto);
|
||||
break;
|
||||
default:
|
||||
sbuf_printf(sb, "ACS-%d %s", version - 7, proto);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ident_data->satacapabilities && ident_data->satacapabilities != 0xffff) {
|
||||
if (ident_data->satacapabilities & ATA_SATA_GEN3)
|
||||
sata = " SATA 3.x";
|
||||
else if (ident_data->satacapabilities & ATA_SATA_GEN2)
|
||||
sata = " SATA 2.x";
|
||||
else if (ident_data->satacapabilities & ATA_SATA_GEN1)
|
||||
sata = " SATA 1.x";
|
||||
else
|
||||
sata = " SATA";
|
||||
} else
|
||||
sata = "";
|
||||
sbuf_printf(sb, "%s device\n", sata);
|
||||
}
|
||||
|
||||
void
|
||||
@ -427,19 +473,39 @@ ata_print_ident_short(struct ata_params *ident_data)
|
||||
printf("<%s %s>", product, revision);
|
||||
}
|
||||
|
||||
void
|
||||
ata_print_ident_short_sbuf(struct ata_params *ident_data, struct sbuf *sb)
|
||||
{
|
||||
|
||||
sbuf_printf(sb, "<");
|
||||
cam_strvis_sbuf(sb, ident_data->model, sizeof(ident_data->model), 0);
|
||||
sbuf_printf(sb, " ");
|
||||
cam_strvis_sbuf(sb, ident_data->revision, sizeof(ident_data->revision), 0);
|
||||
sbuf_printf(sb, ">");
|
||||
}
|
||||
|
||||
void
|
||||
semb_print_ident(struct sep_identify_data *ident_data)
|
||||
{
|
||||
char vendor[9], product[17], revision[5], fw[5], in[7], ins[5];
|
||||
char in[7], ins[5];
|
||||
|
||||
cam_strvis(vendor, ident_data->vendor_id, 8, sizeof(vendor));
|
||||
cam_strvis(product, ident_data->product_id, 16, sizeof(product));
|
||||
cam_strvis(revision, ident_data->product_rev, 4, sizeof(revision));
|
||||
cam_strvis(fw, ident_data->firmware_rev, 4, sizeof(fw));
|
||||
semb_print_ident_short(ident_data);
|
||||
cam_strvis(in, ident_data->interface_id, 6, sizeof(in));
|
||||
cam_strvis(ins, ident_data->interface_rev, 4, sizeof(ins));
|
||||
printf("<%s %s %s %s> SEMB %s %s device\n",
|
||||
vendor, product, revision, fw, in, ins);
|
||||
printf(" SEMB %s %s device\n", in, ins);
|
||||
}
|
||||
|
||||
void
|
||||
semb_print_ident_sbuf(struct sep_identify_data *ident_data, struct sbuf *sb)
|
||||
{
|
||||
|
||||
semb_print_ident_short_sbuf(ident_data, sb);
|
||||
|
||||
sbuf_printf(sb, " SEMB ");
|
||||
cam_strvis_sbuf(sb, ident_data->interface_id, 6, 0);
|
||||
sbuf_printf(sb, " ");
|
||||
cam_strvis_sbuf(sb, ident_data->interface_rev, 4, 0);
|
||||
sbuf_printf(sb, " device\n");
|
||||
}
|
||||
|
||||
void
|
||||
@ -454,6 +520,21 @@ semb_print_ident_short(struct sep_identify_data *ident_data)
|
||||
printf("<%s %s %s %s>", vendor, product, revision, fw);
|
||||
}
|
||||
|
||||
void
|
||||
semb_print_ident_short_sbuf(struct sep_identify_data *ident_data, struct sbuf *sb)
|
||||
{
|
||||
|
||||
sbuf_printf(sb, "<");
|
||||
cam_strvis_sbuf(sb, ident_data->vendor_id, 8, 0);
|
||||
sbuf_printf(sb, " ");
|
||||
cam_strvis_sbuf(sb, ident_data->product_id, 16, 0);
|
||||
sbuf_printf(sb, " ");
|
||||
cam_strvis_sbuf(sb, ident_data->product_rev, 4, 0);
|
||||
sbuf_printf(sb, " ");
|
||||
cam_strvis_sbuf(sb, ident_data->firmware_rev, 4, 0);
|
||||
sbuf_printf(sb, ">");
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ata_logical_sector_size(struct ata_params *ident_data)
|
||||
{
|
||||
|
@ -110,7 +110,9 @@ int ata_status_sbuf(struct ccb_ataio *ataio, struct sbuf *sb);
|
||||
int ata_res_sbuf(struct ata_res *res, struct sbuf *sb);
|
||||
|
||||
void ata_print_ident(struct ata_params *ident_data);
|
||||
void ata_print_ident_sbuf(struct ata_params *ident_data, struct sbuf *sb);
|
||||
void ata_print_ident_short(struct ata_params *ident_data);
|
||||
void ata_print_ident_short_sbuf(struct ata_params *ident_data, struct sbuf *sb);
|
||||
|
||||
uint32_t ata_logical_sector_size(struct ata_params *ident_data);
|
||||
uint64_t ata_physical_sector_size(struct ata_params *ident_data);
|
||||
@ -150,7 +152,9 @@ int ata_identify_match(caddr_t identbuffer, caddr_t table_entry);
|
||||
int ata_static_identify_match(caddr_t identbuffer, caddr_t table_entry);
|
||||
|
||||
void semb_print_ident(struct sep_identify_data *ident_data);
|
||||
void semb_print_ident_sbuf(struct sep_identify_data *ident_data, struct sbuf *sb);
|
||||
void semb_print_ident_short(struct sep_identify_data *ident_data);
|
||||
void semb_print_ident_short_sbuf(struct sep_identify_data *ident_data, struct sbuf *sb);
|
||||
|
||||
void semb_receive_diagnostic_results(struct ccb_ataio *ataio,
|
||||
u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb*),
|
||||
|
@ -256,6 +256,10 @@ struct ada_softc {
|
||||
u_int errors;
|
||||
u_int invalidations;
|
||||
#endif
|
||||
#define ADA_ANNOUNCETMP_SZ 80
|
||||
char announce_temp[ADA_ANNOUNCETMP_SZ];
|
||||
#define ADA_ANNOUNCE_SZ 400
|
||||
char announce_buffer[ADA_ANNOUNCE_SZ];
|
||||
};
|
||||
|
||||
struct ada_quirk_entry {
|
||||
@ -1659,8 +1663,9 @@ adaregister(struct cam_periph *periph, void *arg)
|
||||
struct ada_softc *softc;
|
||||
struct ccb_pathinq cpi;
|
||||
struct ccb_getdev *cgd;
|
||||
char announce_buf[80];
|
||||
struct disk_params *dp;
|
||||
struct sbuf sb;
|
||||
char *announce_buf;
|
||||
caddr_t match;
|
||||
u_int maxio;
|
||||
int quirks;
|
||||
@ -1680,6 +1685,9 @@ adaregister(struct cam_periph *periph, void *arg)
|
||||
return(CAM_REQ_CMP_ERR);
|
||||
}
|
||||
|
||||
announce_buf = softc->announce_temp;
|
||||
bzero(announce_buf, ADA_ANNOUNCETMP_SZ);
|
||||
|
||||
if (cam_iosched_init(&softc->cam_iosched, periph) != 0) {
|
||||
printf("adaregister: Unable to probe new device. "
|
||||
"Unable to allocate iosched memory\n");
|
||||
@ -1713,17 +1721,17 @@ adaregister(struct cam_periph *periph, void *arg)
|
||||
*/
|
||||
(void)cam_periph_hold(periph, PRIBIO);
|
||||
cam_periph_unlock(periph);
|
||||
snprintf(announce_buf, sizeof(announce_buf),
|
||||
snprintf(announce_buf, ADA_ANNOUNCETMP_SZ,
|
||||
"kern.cam.ada.%d.quirks", periph->unit_number);
|
||||
quirks = softc->quirks;
|
||||
TUNABLE_INT_FETCH(announce_buf, &quirks);
|
||||
softc->quirks = quirks;
|
||||
softc->read_ahead = -1;
|
||||
snprintf(announce_buf, sizeof(announce_buf),
|
||||
snprintf(announce_buf, ADA_ANNOUNCETMP_SZ,
|
||||
"kern.cam.ada.%d.read_ahead", periph->unit_number);
|
||||
TUNABLE_INT_FETCH(announce_buf, &softc->read_ahead);
|
||||
softc->write_cache = -1;
|
||||
snprintf(announce_buf, sizeof(announce_buf),
|
||||
snprintf(announce_buf, ADA_ANNOUNCETMP_SZ,
|
||||
"kern.cam.ada.%d.write_cache", periph->unit_number);
|
||||
TUNABLE_INT_FETCH(announce_buf, &softc->write_cache);
|
||||
|
||||
@ -1829,12 +1837,16 @@ adaregister(struct cam_periph *periph, void *arg)
|
||||
cam_periph_lock(periph);
|
||||
|
||||
dp = &softc->params;
|
||||
snprintf(announce_buf, sizeof(announce_buf),
|
||||
snprintf(announce_buf, ADA_ANNOUNCETMP_SZ,
|
||||
"%juMB (%ju %u byte sectors)",
|
||||
((uintmax_t)dp->secsize * dp->sectors) / (1024 * 1024),
|
||||
(uintmax_t)dp->sectors, dp->secsize);
|
||||
xpt_announce_periph(periph, announce_buf);
|
||||
xpt_announce_quirks(periph, softc->quirks, ADA_Q_BIT_STRING);
|
||||
|
||||
sbuf_new(&sb, softc->announce_buffer, ADA_ANNOUNCE_SZ, SBUF_FIXEDLEN);
|
||||
xpt_announce_periph_sbuf(periph, &sb, announce_buf);
|
||||
xpt_announce_quirks_sbuf(periph, &sb, softc->quirks, ADA_Q_BIT_STRING);
|
||||
sbuf_finish(&sb);
|
||||
sbuf_putbuf(&sb);
|
||||
|
||||
/*
|
||||
* Create our sysctl variables, now that we know
|
||||
|
@ -189,11 +189,16 @@ static void ata_dev_async(u_int32_t async_code,
|
||||
void *async_arg);
|
||||
static void ata_action(union ccb *start_ccb);
|
||||
static void ata_announce_periph(struct cam_periph *periph);
|
||||
static void ata_announce_periph_sbuf(struct cam_periph *periph, struct sbuf *sb);
|
||||
static void ata_proto_announce(struct cam_ed *device);
|
||||
static void ata_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb);
|
||||
static void ata_proto_denounce(struct cam_ed *device);
|
||||
static void ata_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb);
|
||||
static void ata_proto_debug_out(union ccb *ccb);
|
||||
static void semb_proto_announce(struct cam_ed *device);
|
||||
static void semb_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb);
|
||||
static void semb_proto_denounce(struct cam_ed *device);
|
||||
static void semb_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb);
|
||||
|
||||
static int ata_dma = 1;
|
||||
static int atapi_dma = 1;
|
||||
@ -206,6 +211,7 @@ static struct xpt_xport_ops ata_xport_ops = {
|
||||
.action = ata_action,
|
||||
.async = ata_dev_async,
|
||||
.announce = ata_announce_periph,
|
||||
.announce_sbuf = ata_announce_periph_sbuf,
|
||||
};
|
||||
#define ATA_XPT_XPORT(x, X) \
|
||||
static struct xpt_xport ata_xport_ ## x = { \
|
||||
@ -222,7 +228,9 @@ ATA_XPT_XPORT(sata, SATA);
|
||||
|
||||
static struct xpt_proto_ops ata_proto_ops_ata = {
|
||||
.announce = ata_proto_announce,
|
||||
.announce_sbuf = ata_proto_announce_sbuf,
|
||||
.denounce = ata_proto_denounce,
|
||||
.denounce_sbuf = ata_proto_denounce_sbuf,
|
||||
.debug_out = ata_proto_debug_out,
|
||||
};
|
||||
static struct xpt_proto ata_proto_ata = {
|
||||
@ -233,7 +241,9 @@ static struct xpt_proto ata_proto_ata = {
|
||||
|
||||
static struct xpt_proto_ops ata_proto_ops_satapm = {
|
||||
.announce = ata_proto_announce,
|
||||
.announce_sbuf = ata_proto_announce_sbuf,
|
||||
.denounce = ata_proto_denounce,
|
||||
.denounce_sbuf = ata_proto_denounce_sbuf,
|
||||
.debug_out = ata_proto_debug_out,
|
||||
};
|
||||
static struct xpt_proto ata_proto_satapm = {
|
||||
@ -244,7 +254,9 @@ static struct xpt_proto ata_proto_satapm = {
|
||||
|
||||
static struct xpt_proto_ops ata_proto_ops_semb = {
|
||||
.announce = semb_proto_announce,
|
||||
.announce_sbuf = semb_proto_announce_sbuf,
|
||||
.denounce = semb_proto_denounce,
|
||||
.denounce_sbuf = semb_proto_denounce_sbuf,
|
||||
.debug_out = ata_proto_debug_out,
|
||||
};
|
||||
static struct xpt_proto ata_proto_semb = {
|
||||
@ -2072,42 +2084,51 @@ ata_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target,
|
||||
}
|
||||
|
||||
static void
|
||||
ata_announce_periph(struct cam_periph *periph)
|
||||
_ata_announce_periph(struct cam_periph *periph, struct ccb_trans_settings *cts, u_int *speed)
|
||||
{
|
||||
struct ccb_pathinq cpi;
|
||||
struct ccb_trans_settings cts;
|
||||
struct cam_path *path = periph->path;
|
||||
u_int speed;
|
||||
u_int mb;
|
||||
|
||||
cam_periph_assert(periph, MA_OWNED);
|
||||
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
|
||||
cts.type = CTS_TYPE_CURRENT_SETTINGS;
|
||||
xpt_action((union ccb*)&cts);
|
||||
if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
|
||||
xpt_setup_ccb(&cts->ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
cts->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
|
||||
cts->type = CTS_TYPE_CURRENT_SETTINGS;
|
||||
xpt_action((union ccb*)cts);
|
||||
if ((cts->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
|
||||
return;
|
||||
/* Ask the SIM for its base transfer speed */
|
||||
xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
cpi.ccb_h.func_code = XPT_PATH_INQ;
|
||||
xpt_action((union ccb *)&cpi);
|
||||
/* Report connection speed */
|
||||
speed = cpi.base_transfer_speed;
|
||||
if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) {
|
||||
*speed = cpi.base_transfer_speed;
|
||||
if (cts->transport == XPORT_ATA) {
|
||||
struct ccb_trans_settings_pata *pata =
|
||||
&cts.xport_specific.ata;
|
||||
&cts->xport_specific.ata;
|
||||
|
||||
if (pata->valid & CTS_ATA_VALID_MODE)
|
||||
speed = ata_mode2speed(pata->mode);
|
||||
*speed = ata_mode2speed(pata->mode);
|
||||
}
|
||||
if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) {
|
||||
if (cts->transport == XPORT_SATA) {
|
||||
struct ccb_trans_settings_sata *sata =
|
||||
&cts.xport_specific.sata;
|
||||
&cts->xport_specific.sata;
|
||||
|
||||
if (sata->valid & CTS_SATA_VALID_REVISION)
|
||||
speed = ata_revision2speed(sata->revision);
|
||||
*speed = ata_revision2speed(sata->revision);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ata_announce_periph(struct cam_periph *periph)
|
||||
{
|
||||
struct ccb_trans_settings cts;
|
||||
u_int speed, mb;
|
||||
|
||||
_ata_announce_periph(periph, &cts, &speed);
|
||||
if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
|
||||
return;
|
||||
|
||||
mb = speed / 1000;
|
||||
if (mb > 0)
|
||||
printf("%s%d: %d.%03dMB/s transfers",
|
||||
@ -2117,7 +2138,7 @@ ata_announce_periph(struct cam_periph *periph)
|
||||
printf("%s%d: %dKB/s transfers", periph->periph_name,
|
||||
periph->unit_number, speed);
|
||||
/* Report additional information about connection */
|
||||
if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) {
|
||||
if (cts.transport == XPORT_ATA) {
|
||||
struct ccb_trans_settings_pata *pata =
|
||||
&cts.xport_specific.ata;
|
||||
|
||||
@ -2130,7 +2151,7 @@ ata_announce_periph(struct cam_periph *periph)
|
||||
printf("PIO %dbytes", pata->bytecount);
|
||||
printf(")");
|
||||
}
|
||||
if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) {
|
||||
if (cts.transport == XPORT_SATA) {
|
||||
struct ccb_trans_settings_sata *sata =
|
||||
&cts.xport_specific.sata;
|
||||
|
||||
@ -2150,6 +2171,64 @@ ata_announce_periph(struct cam_periph *periph)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
ata_announce_periph_sbuf(struct cam_periph *periph, struct sbuf *sb)
|
||||
{
|
||||
struct ccb_trans_settings cts;
|
||||
u_int speed, mb;
|
||||
|
||||
_ata_announce_periph(periph, &cts, &speed);
|
||||
if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)
|
||||
return;
|
||||
|
||||
mb = speed / 1000;
|
||||
if (mb > 0)
|
||||
sbuf_printf(sb, "%s%d: %d.%03dMB/s transfers",
|
||||
periph->periph_name, periph->unit_number,
|
||||
mb, speed % 1000);
|
||||
else
|
||||
sbuf_printf(sb, "%s%d: %dKB/s transfers", periph->periph_name,
|
||||
periph->unit_number, speed);
|
||||
/* Report additional information about connection */
|
||||
if (cts.transport == XPORT_ATA) {
|
||||
struct ccb_trans_settings_pata *pata =
|
||||
&cts.xport_specific.ata;
|
||||
|
||||
sbuf_printf(sb, " (");
|
||||
if (pata->valid & CTS_ATA_VALID_MODE)
|
||||
sbuf_printf(sb, "%s, ", ata_mode2string(pata->mode));
|
||||
if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0)
|
||||
sbuf_printf(sb, "ATAPI %dbytes, ", pata->atapi);
|
||||
if (pata->valid & CTS_ATA_VALID_BYTECOUNT)
|
||||
sbuf_printf(sb, "PIO %dbytes", pata->bytecount);
|
||||
sbuf_printf(sb, ")");
|
||||
}
|
||||
if (cts.transport == XPORT_SATA) {
|
||||
struct ccb_trans_settings_sata *sata =
|
||||
&cts.xport_specific.sata;
|
||||
|
||||
sbuf_printf(sb, " (");
|
||||
if (sata->valid & CTS_SATA_VALID_REVISION)
|
||||
sbuf_printf(sb, "SATA %d.x, ", sata->revision);
|
||||
else
|
||||
sbuf_printf(sb, "SATA, ");
|
||||
if (sata->valid & CTS_SATA_VALID_MODE)
|
||||
sbuf_printf(sb, "%s, ", ata_mode2string(sata->mode));
|
||||
if ((sata->valid & CTS_ATA_VALID_ATAPI) && sata->atapi != 0)
|
||||
sbuf_printf(sb, "ATAPI %dbytes, ", sata->atapi);
|
||||
if (sata->valid & CTS_SATA_VALID_BYTECOUNT)
|
||||
sbuf_printf(sb, "PIO %dbytes", sata->bytecount);
|
||||
sbuf_printf(sb, ")");
|
||||
}
|
||||
sbuf_printf(sb, "\n");
|
||||
}
|
||||
|
||||
static void
|
||||
ata_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb)
|
||||
{
|
||||
ata_print_ident_sbuf(&device->ident_data, sb);
|
||||
}
|
||||
|
||||
static void
|
||||
ata_proto_announce(struct cam_ed *device)
|
||||
{
|
||||
@ -2162,6 +2241,18 @@ ata_proto_denounce(struct cam_ed *device)
|
||||
ata_print_ident_short(&device->ident_data);
|
||||
}
|
||||
|
||||
static void
|
||||
ata_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb)
|
||||
{
|
||||
ata_print_ident_short_sbuf(&device->ident_data, sb);
|
||||
}
|
||||
|
||||
static void
|
||||
semb_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb)
|
||||
{
|
||||
semb_print_ident_sbuf((struct sep_identify_data *)&device->ident_data, sb);
|
||||
}
|
||||
|
||||
static void
|
||||
semb_proto_announce(struct cam_ed *device)
|
||||
{
|
||||
@ -2174,6 +2265,12 @@ semb_proto_denounce(struct cam_ed *device)
|
||||
semb_print_ident_short((struct sep_identify_data *)&device->ident_data);
|
||||
}
|
||||
|
||||
static void
|
||||
semb_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb)
|
||||
{
|
||||
semb_print_ident_short_sbuf((struct sep_identify_data *)&device->ident_data, sb);
|
||||
}
|
||||
|
||||
static void
|
||||
ata_proto_debug_out(union ccb *ccb)
|
||||
{
|
||||
|
@ -641,8 +641,14 @@ cam_periph_invalidate(struct cam_periph *periph)
|
||||
return;
|
||||
|
||||
CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Periph invalidated\n"));
|
||||
if ((periph->flags & CAM_PERIPH_ANNOUNCED) && !rebooting)
|
||||
xpt_denounce_periph(periph);
|
||||
if ((periph->flags & CAM_PERIPH_ANNOUNCED) && !rebooting) {
|
||||
struct sbuf sb;
|
||||
|
||||
sbuf_new(&sb, NULL, 160, SBUF_FIXEDLEN);
|
||||
xpt_denounce_periph_sbuf(periph, &sb);
|
||||
sbuf_finish(&sb);
|
||||
sbuf_putbuf(&sb);
|
||||
}
|
||||
periph->flags |= CAM_PERIPH_INVALID;
|
||||
periph->flags &= ~CAM_PERIPH_NEW_DEV_FOUND;
|
||||
if (periph->periph_oninval != NULL)
|
||||
|
@ -116,6 +116,7 @@ struct xpt_softc {
|
||||
TAILQ_HEAD(, ccb_hdr) ccb_scanq;
|
||||
int buses_to_config;
|
||||
int buses_config_done;
|
||||
int announce_nosbuf;
|
||||
|
||||
/*
|
||||
* Registered buses
|
||||
@ -174,6 +175,8 @@ SYSCTL_INT(_kern_cam, OID_AUTO, boot_delay, CTLFLAG_RDTUN,
|
||||
&xsoftc.boot_delay, 0, "Bus registration wait time");
|
||||
SYSCTL_UINT(_kern_cam, OID_AUTO, xpt_generation, CTLFLAG_RD,
|
||||
&xsoftc.xpt_generation, 0, "CAM peripheral generation count");
|
||||
SYSCTL_INT(_kern_cam, OID_AUTO, announce_nosbuf, CTLFLAG_RWTUN,
|
||||
&xsoftc.announce_nosbuf, 0, "Don't use sbuf for announcements");
|
||||
|
||||
struct cam_doneq {
|
||||
struct mtx_padalign cam_doneq_mtx;
|
||||
@ -1093,6 +1096,64 @@ xpt_announce_periph(struct cam_periph *periph, char *announce_string)
|
||||
periph->unit_number, announce_string);
|
||||
}
|
||||
|
||||
void
|
||||
xpt_announce_periph_sbuf(struct cam_periph *periph, struct sbuf *sb,
|
||||
char *announce_string)
|
||||
{
|
||||
struct cam_path *path = periph->path;
|
||||
struct xpt_proto *proto;
|
||||
|
||||
cam_periph_assert(periph, MA_OWNED);
|
||||
periph->flags |= CAM_PERIPH_ANNOUNCED;
|
||||
|
||||
/* Fall back to the non-sbuf method if necessary */
|
||||
if (xsoftc.announce_nosbuf != 0) {
|
||||
xpt_announce_periph(periph, announce_string);
|
||||
return;
|
||||
}
|
||||
proto = xpt_proto_find(path->device->protocol);
|
||||
if (((proto != NULL) && (proto->ops->announce_sbuf == NULL)) ||
|
||||
(path->bus->xport->ops->announce_sbuf == NULL)) {
|
||||
xpt_announce_periph(periph, announce_string);
|
||||
return;
|
||||
}
|
||||
|
||||
sbuf_printf(sb, "%s%d at %s%d bus %d scbus%d target %d lun %jx\n",
|
||||
periph->periph_name, periph->unit_number,
|
||||
path->bus->sim->sim_name,
|
||||
path->bus->sim->unit_number,
|
||||
path->bus->sim->bus_id,
|
||||
path->bus->path_id,
|
||||
path->target->target_id,
|
||||
(uintmax_t)path->device->lun_id);
|
||||
sbuf_printf(sb, "%s%d: ", periph->periph_name, periph->unit_number);
|
||||
|
||||
if (proto)
|
||||
proto->ops->announce_sbuf(path->device, sb);
|
||||
else
|
||||
sbuf_printf(sb, "%s%d: Unknown protocol device %d\n",
|
||||
periph->periph_name, periph->unit_number,
|
||||
path->device->protocol);
|
||||
if (path->device->serial_num_len > 0) {
|
||||
/* Don't wrap the screen - print only the first 60 chars */
|
||||
sbuf_printf(sb, "%s%d: Serial Number %.60s\n",
|
||||
periph->periph_name, periph->unit_number,
|
||||
path->device->serial_num);
|
||||
}
|
||||
/* Announce transport details. */
|
||||
path->bus->xport->ops->announce_sbuf(periph, sb);
|
||||
/* Announce command queueing. */
|
||||
if (path->device->inq_flags & SID_CmdQue
|
||||
|| path->device->flags & CAM_DEV_TAG_AFTER_COUNT) {
|
||||
sbuf_printf(sb, "%s%d: Command Queueing enabled\n",
|
||||
periph->periph_name, periph->unit_number);
|
||||
}
|
||||
/* Announce caller's details if they've passed in. */
|
||||
if (announce_string != NULL)
|
||||
sbuf_printf(sb, "%s%d: %s\n", periph->periph_name,
|
||||
periph->unit_number, announce_string);
|
||||
}
|
||||
|
||||
void
|
||||
xpt_announce_quirks(struct cam_periph *periph, int quirks, char *bit_string)
|
||||
{
|
||||
@ -1102,6 +1163,21 @@ xpt_announce_quirks(struct cam_periph *periph, int quirks, char *bit_string)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xpt_announce_quirks_sbuf(struct cam_periph *periph, struct sbuf *sb,
|
||||
int quirks, char *bit_string)
|
||||
{
|
||||
if (xsoftc.announce_nosbuf != 0) {
|
||||
xpt_announce_quirks(periph, quirks, bit_string);
|
||||
return;
|
||||
}
|
||||
|
||||
if (quirks != 0) {
|
||||
sbuf_printf(sb, "%s%d: quirks=0x%b\n", periph->periph_name,
|
||||
periph->unit_number, quirks, bit_string);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xpt_denounce_periph(struct cam_periph *periph)
|
||||
{
|
||||
@ -1130,6 +1206,45 @@ xpt_denounce_periph(struct cam_periph *periph)
|
||||
printf(" detached\n");
|
||||
}
|
||||
|
||||
void
|
||||
xpt_denounce_periph_sbuf(struct cam_periph *periph, struct sbuf *sb)
|
||||
{
|
||||
struct cam_path *path = periph->path;
|
||||
struct xpt_proto *proto;
|
||||
|
||||
cam_periph_assert(periph, MA_OWNED);
|
||||
|
||||
/* Fall back to the non-sbuf method if necessary */
|
||||
if (xsoftc.announce_nosbuf != 0) {
|
||||
xpt_denounce_periph(periph);
|
||||
return;
|
||||
}
|
||||
proto = xpt_proto_find(path->device->protocol);
|
||||
if ((proto != NULL) && (proto->ops->denounce_sbuf == NULL)) {
|
||||
xpt_denounce_periph(periph);
|
||||
return;
|
||||
}
|
||||
|
||||
sbuf_printf(sb, "%s%d at %s%d bus %d scbus%d target %d lun %jx\n",
|
||||
periph->periph_name, periph->unit_number,
|
||||
path->bus->sim->sim_name,
|
||||
path->bus->sim->unit_number,
|
||||
path->bus->sim->bus_id,
|
||||
path->bus->path_id,
|
||||
path->target->target_id,
|
||||
(uintmax_t)path->device->lun_id);
|
||||
sbuf_printf(sb, "%s%d: ", periph->periph_name, periph->unit_number);
|
||||
|
||||
if (proto)
|
||||
proto->ops->denounce_sbuf(path->device, sb);
|
||||
else
|
||||
sbuf_printf(sb, "%s%d: Unknown protocol device %d\n",
|
||||
periph->periph_name, periph->unit_number,
|
||||
path->device->protocol);
|
||||
if (path->device->serial_num_len > 0)
|
||||
sbuf_printf(sb, " s/n %.60s", path->device->serial_num);
|
||||
sbuf_printf(sb, " detached\n");
|
||||
}
|
||||
|
||||
int
|
||||
xpt_getattr(char *buf, size_t len, const char *attr, struct cam_path *path)
|
||||
|
@ -47,6 +47,7 @@ typedef void (*xpt_dev_async_func)(u_int32_t async_code,
|
||||
struct cam_ed *device,
|
||||
void *async_arg);
|
||||
typedef void (*xpt_announce_periph_func)(struct cam_periph *periph);
|
||||
typedef void (*xpt_announce_periph_sbuf_func)(struct cam_periph *periph, struct sbuf *sbuf);
|
||||
|
||||
struct xpt_xport_ops {
|
||||
xpt_alloc_device_func alloc_device;
|
||||
@ -54,6 +55,7 @@ struct xpt_xport_ops {
|
||||
xpt_action_func action;
|
||||
xpt_dev_async_func async;
|
||||
xpt_announce_periph_func announce;
|
||||
xpt_announce_periph_sbuf_func announce_sbuf;
|
||||
};
|
||||
|
||||
struct xpt_xport {
|
||||
@ -67,11 +69,14 @@ SET_DECLARE(cam_xpt_xport_set, struct xpt_xport);
|
||||
DATA_SET(cam_xpt_xport_set, data)
|
||||
|
||||
typedef void (*xpt_proto_announce_func)(struct cam_ed *);
|
||||
typedef void (*xpt_proto_announce_sbuf_func)(struct cam_ed *, struct sbuf *);
|
||||
typedef void (*xpt_proto_debug_out_func)(union ccb *);
|
||||
|
||||
struct xpt_proto_ops {
|
||||
xpt_proto_announce_func announce;
|
||||
xpt_proto_announce_sbuf_func announce_sbuf;
|
||||
xpt_proto_announce_func denounce;
|
||||
xpt_proto_announce_sbuf_func denounce_sbuf;
|
||||
xpt_proto_debug_out_func debug_out;
|
||||
};
|
||||
|
||||
|
@ -45,9 +45,16 @@ int32_t xpt_add_periph(struct cam_periph *periph);
|
||||
void xpt_remove_periph(struct cam_periph *periph);
|
||||
void xpt_announce_periph(struct cam_periph *periph,
|
||||
char *announce_string);
|
||||
void xpt_announce_periph_sbuf(struct cam_periph *periph,
|
||||
struct sbuf *sb,
|
||||
char *announce_string);
|
||||
void xpt_announce_quirks(struct cam_periph *periph,
|
||||
int quirks, char *bit_string);
|
||||
void xpt_announce_quirks_sbuf(struct cam_periph *periph,
|
||||
struct sbuf *sb,
|
||||
int quirks, char *bit_string);
|
||||
void xpt_denounce_periph(struct cam_periph *periph);
|
||||
void xpt_denounce_periph_sbuf(struct cam_periph *periph, struct sbuf *sb);
|
||||
#endif
|
||||
|
||||
#endif /* _CAM_CAM_XPT_PERIPH_H */
|
||||
|
@ -5169,7 +5169,7 @@ scsi_sense_print(struct ccb_scsiio *csio)
|
||||
|
||||
sbuf_finish(&sb);
|
||||
|
||||
printf("%s", sbuf_data(&sb));
|
||||
sbuf_putbuf(&sb);
|
||||
}
|
||||
|
||||
#else /* !_KERNEL */
|
||||
@ -5361,11 +5361,10 @@ scsi_get_ascq(struct scsi_sense_data *sense_data, u_int sense_len,
|
||||
* for this routine to function properly.
|
||||
*/
|
||||
void
|
||||
scsi_print_inquiry(struct scsi_inquiry_data *inq_data)
|
||||
scsi_print_inquiry_sbuf(struct sbuf *sb, struct scsi_inquiry_data *inq_data)
|
||||
{
|
||||
u_int8_t type;
|
||||
char *dtype, *qtype;
|
||||
char vendor[16], product[48], revision[16], rstr[12];
|
||||
|
||||
type = SID_TYPE(inq_data);
|
||||
|
||||
@ -5454,41 +5453,55 @@ scsi_print_inquiry(struct scsi_inquiry_data *inq_data)
|
||||
break;
|
||||
}
|
||||
|
||||
cam_strvis(vendor, inq_data->vendor, sizeof(inq_data->vendor),
|
||||
sizeof(vendor));
|
||||
cam_strvis(product, inq_data->product, sizeof(inq_data->product),
|
||||
sizeof(product));
|
||||
cam_strvis(revision, inq_data->revision, sizeof(inq_data->revision),
|
||||
sizeof(revision));
|
||||
scsi_print_inquiry_short_sbuf(sb, inq_data);
|
||||
|
||||
sbuf_printf(sb, "%s %s ", SID_IS_REMOVABLE(inq_data) ? "Removable" : "Fixed", dtype);
|
||||
|
||||
if (SID_ANSI_REV(inq_data) == SCSI_REV_0)
|
||||
snprintf(rstr, sizeof(rstr), "SCSI");
|
||||
sbuf_printf(sb, "SCSI ");
|
||||
else if (SID_ANSI_REV(inq_data) <= SCSI_REV_SPC) {
|
||||
snprintf(rstr, sizeof(rstr), "SCSI-%d",
|
||||
SID_ANSI_REV(inq_data));
|
||||
sbuf_printf(sb, "SCSI-%d ", SID_ANSI_REV(inq_data));
|
||||
} else {
|
||||
snprintf(rstr, sizeof(rstr), "SPC-%d SCSI",
|
||||
SID_ANSI_REV(inq_data) - 2);
|
||||
sbuf_printf(sb, "SPC-%d SCSI ", SID_ANSI_REV(inq_data) - 2);
|
||||
}
|
||||
printf("<%s %s %s> %s %s %s device%s\n",
|
||||
vendor, product, revision,
|
||||
SID_IS_REMOVABLE(inq_data) ? "Removable" : "Fixed",
|
||||
dtype, rstr, qtype);
|
||||
sbuf_printf(sb, "device%s\n", qtype);
|
||||
}
|
||||
|
||||
void
|
||||
scsi_print_inquiry(struct scsi_inquiry_data *inq_data)
|
||||
{
|
||||
struct sbuf sb;
|
||||
char buffer[120];
|
||||
|
||||
sbuf_new(&sb, buffer, 120, SBUF_FIXEDLEN);
|
||||
scsi_print_inquiry_sbuf(&sb, inq_data);
|
||||
sbuf_finish(&sb);
|
||||
sbuf_putbuf(&sb);
|
||||
}
|
||||
|
||||
void
|
||||
scsi_print_inquiry_short_sbuf(struct sbuf *sb, struct scsi_inquiry_data *inq_data)
|
||||
{
|
||||
|
||||
sbuf_printf(sb, "<");
|
||||
cam_strvis_sbuf(sb, inq_data->vendor, sizeof(inq_data->vendor), 0);
|
||||
sbuf_printf(sb, " ");
|
||||
cam_strvis_sbuf(sb, inq_data->product, sizeof(inq_data->product), 0);
|
||||
sbuf_printf(sb, " ");
|
||||
cam_strvis_sbuf(sb, inq_data->revision, sizeof(inq_data->revision), 0);
|
||||
sbuf_printf(sb, "> ");
|
||||
}
|
||||
|
||||
void
|
||||
scsi_print_inquiry_short(struct scsi_inquiry_data *inq_data)
|
||||
{
|
||||
char vendor[16], product[48], revision[16];
|
||||
struct sbuf sb;
|
||||
char buffer[84];
|
||||
|
||||
cam_strvis(vendor, inq_data->vendor, sizeof(inq_data->vendor),
|
||||
sizeof(vendor));
|
||||
cam_strvis(product, inq_data->product, sizeof(inq_data->product),
|
||||
sizeof(product));
|
||||
cam_strvis(revision, inq_data->revision, sizeof(inq_data->revision),
|
||||
sizeof(revision));
|
||||
|
||||
printf("<%s %s %s>", vendor, product, revision);
|
||||
sbuf_new(&sb, buffer, 84, SBUF_FIXEDLEN);
|
||||
scsi_print_inquiry_short_sbuf(&sb, inq_data);
|
||||
sbuf_finish(&sb);
|
||||
sbuf_putbuf(&sb);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3820,7 +3820,11 @@ char * scsi_cdb_string(u_int8_t *cdb_ptr, char *cdb_string,
|
||||
void scsi_cdb_sbuf(u_int8_t *cdb_ptr, struct sbuf *sb);
|
||||
|
||||
void scsi_print_inquiry(struct scsi_inquiry_data *inq_data);
|
||||
void scsi_print_inquiry_sbuf(struct sbuf *sb,
|
||||
struct scsi_inquiry_data *inq_data);
|
||||
void scsi_print_inquiry_short(struct scsi_inquiry_data *inq_data);
|
||||
void scsi_print_inquiry_short_sbuf(struct sbuf *sb,
|
||||
struct scsi_inquiry_data *inq_data);
|
||||
|
||||
u_int scsi_calc_syncsrate(u_int period_factor);
|
||||
u_int scsi_calc_syncparam(u_int period);
|
||||
|
@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/cdrio.h>
|
||||
#include <sys/dvdio.h>
|
||||
#include <sys/devicestat.h>
|
||||
#include <sys/sbuf.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/taskqueue.h>
|
||||
#include <geom/geom_disk.h>
|
||||
@ -158,6 +159,11 @@ struct cd_softc {
|
||||
struct cd_tocdata toc;
|
||||
struct disk *disk;
|
||||
struct callout mediapoll_c;
|
||||
|
||||
#define CD_ANNOUNCETMP_SZ 120
|
||||
char announce_temp[CD_ANNOUNCETMP_SZ];
|
||||
#define CD_ANNOUNCE_SZ 400
|
||||
char announce_buf[CD_ANNOUNCE_SZ];
|
||||
};
|
||||
|
||||
struct cd_page_sizes {
|
||||
@ -1046,28 +1052,12 @@ cddone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
case CD_CCB_PROBE:
|
||||
{
|
||||
struct scsi_read_capacity_data *rdcap;
|
||||
char announce_buf[120]; /*
|
||||
* Currently (9/30/97) the
|
||||
* longest possible announce
|
||||
* buffer is 108 bytes, for the
|
||||
* first error case below.
|
||||
* That is 39 bytes for the
|
||||
* basic string, 16 bytes for the
|
||||
* biggest sense key (hardware
|
||||
* error), 52 bytes for the
|
||||
* text of the largest sense
|
||||
* qualifier valid for a CDROM,
|
||||
* (0x72, 0x03 or 0x04,
|
||||
* 0x03), and one byte for the
|
||||
* null terminating character.
|
||||
* To allow for longer strings,
|
||||
* the announce buffer is 120
|
||||
* bytes.
|
||||
*/
|
||||
char *announce_buf;
|
||||
struct cd_params *cdp;
|
||||
int error;
|
||||
|
||||
cdp = &softc->params;
|
||||
announce_buf = softc->announce_temp;
|
||||
|
||||
rdcap = (struct scsi_read_capacity_data *)csio->data_ptr;
|
||||
|
||||
@ -1081,7 +1071,7 @@ cddone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP ||
|
||||
(error = cderror(done_ccb, CAM_RETRY_SELTO,
|
||||
SF_RETRY_UA | SF_NO_PRINT)) == 0) {
|
||||
snprintf(announce_buf, sizeof(announce_buf),
|
||||
snprintf(announce_buf, CD_ANNOUNCETMP_SZ,
|
||||
"%juMB (%ju %u byte sectors)",
|
||||
((uintmax_t)cdp->disksize * cdp->blksize) /
|
||||
(1024 * 1024),
|
||||
@ -1186,22 +1176,29 @@ cddone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
*/
|
||||
cam_periph_invalidate(periph);
|
||||
|
||||
announce_buf[0] = '\0';
|
||||
announce_buf = NULL;
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Invalidate this peripheral.
|
||||
*/
|
||||
cam_periph_invalidate(periph);
|
||||
announce_buf[0] = '\0';
|
||||
announce_buf = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
free(rdcap, M_SCSICD);
|
||||
if (announce_buf[0] != '\0') {
|
||||
xpt_announce_periph(periph, announce_buf);
|
||||
xpt_announce_quirks(periph, softc->quirks,
|
||||
if (announce_buf != NULL) {
|
||||
struct sbuf sb;
|
||||
|
||||
sbuf_new(&sb, softc->announce_buf, CD_ANNOUNCE_SZ,
|
||||
SBUF_FIXEDLEN);
|
||||
xpt_announce_periph_sbuf(periph, &sb, announce_buf);
|
||||
xpt_announce_quirks_sbuf(periph, &sb, softc->quirks,
|
||||
CD_Q_BIT_STRING);
|
||||
sbuf_finish(&sb);
|
||||
sbuf_putbuf(&sb);
|
||||
|
||||
/*
|
||||
* Create our sysctl variables, now that we know
|
||||
* we have successfully attached.
|
||||
|
@ -338,6 +338,10 @@ struct da_softc {
|
||||
u_int timeouts;
|
||||
u_int invalidations;
|
||||
#endif
|
||||
#define DA_ANNOUNCETMP_SZ 80
|
||||
char announce_temp[DA_ANNOUNCETMP_SZ];
|
||||
#define DA_ANNOUNCE_SZ 400
|
||||
char announcebuf[DA_ANNOUNCE_SZ];
|
||||
};
|
||||
|
||||
#define dadeleteflag(softc, delete_method, enable) \
|
||||
@ -4219,12 +4223,16 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
{
|
||||
struct scsi_read_capacity_data *rdcap;
|
||||
struct scsi_read_capacity_data_long *rcaplong;
|
||||
char announce_buf[80];
|
||||
char *announce_buf;
|
||||
int lbp;
|
||||
|
||||
lbp = 0;
|
||||
rdcap = NULL;
|
||||
rcaplong = NULL;
|
||||
/* XXX TODO: can this be a malloc? */
|
||||
announce_buf = softc->announce_temp;
|
||||
bzero(announce_buf, DA_ANNOUNCETMP_SZ);
|
||||
|
||||
if (state == DA_CCB_PROBE_RC)
|
||||
rdcap =(struct scsi_read_capacity_data *)csio->data_ptr;
|
||||
else
|
||||
@ -4277,7 +4285,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
xpt_print(periph->path,
|
||||
"unsupportable block size %ju\n",
|
||||
(uintmax_t) block_size);
|
||||
announce_buf[0] = '\0';
|
||||
announce_buf = NULL;
|
||||
cam_periph_invalidate(periph);
|
||||
} else {
|
||||
/*
|
||||
@ -4289,7 +4297,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
rcaplong, sizeof(*rcaplong));
|
||||
lbp = (lalba & SRC16_LBPME_A);
|
||||
dp = &softc->params;
|
||||
snprintf(announce_buf, sizeof(announce_buf),
|
||||
snprintf(announce_buf, DA_ANNOUNCETMP_SZ,
|
||||
"%juMB (%ju %u byte sectors)",
|
||||
((uintmax_t)dp->secsize * dp->sectors) /
|
||||
(1024 * 1024),
|
||||
@ -4298,8 +4306,6 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
} else {
|
||||
int error;
|
||||
|
||||
announce_buf[0] = '\0';
|
||||
|
||||
/*
|
||||
* Retry any UNIT ATTENTION type errors. They
|
||||
* are expected at boot.
|
||||
@ -4383,11 +4389,10 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
&sense_key_desc,
|
||||
&asc_desc);
|
||||
snprintf(announce_buf,
|
||||
sizeof(announce_buf),
|
||||
"Attempt to query device "
|
||||
"size failed: %s, %s",
|
||||
sense_key_desc,
|
||||
asc_desc);
|
||||
DA_ANNOUNCETMP_SZ,
|
||||
"Attempt to query device "
|
||||
"size failed: %s, %s",
|
||||
sense_key_desc, asc_desc);
|
||||
} else {
|
||||
if (have_sense)
|
||||
scsi_sense_print(
|
||||
@ -4401,6 +4406,8 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
xpt_print(periph->path, "fatal error, "
|
||||
"failed to attach to device\n");
|
||||
|
||||
announce_buf = NULL;
|
||||
|
||||
/*
|
||||
* Free up resources.
|
||||
*/
|
||||
@ -4409,20 +4416,29 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
}
|
||||
}
|
||||
free(csio->data_ptr, M_SCSIDA);
|
||||
if (announce_buf[0] != '\0' &&
|
||||
if (announce_buf != NULL &&
|
||||
((softc->flags & DA_FLAG_ANNOUNCED) == 0)) {
|
||||
struct sbuf sb;
|
||||
|
||||
sbuf_new(&sb, softc->announcebuf, DA_ANNOUNCE_SZ,
|
||||
SBUF_FIXEDLEN);
|
||||
xpt_announce_periph_sbuf(periph, &sb, announce_buf);
|
||||
xpt_announce_quirks_sbuf(periph, &sb, softc->quirks,
|
||||
DA_Q_BIT_STRING);
|
||||
sbuf_finish(&sb);
|
||||
sbuf_putbuf(&sb);
|
||||
|
||||
/*
|
||||
* Create our sysctl variables, now that we know
|
||||
* we have successfully attached.
|
||||
*/
|
||||
/* increase the refcount */
|
||||
if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
|
||||
|
||||
taskqueue_enqueue(taskqueue_thread,
|
||||
&softc->sysctl_task);
|
||||
xpt_announce_periph(periph, announce_buf);
|
||||
xpt_announce_quirks(periph, softc->quirks,
|
||||
DA_Q_BIT_STRING);
|
||||
} else {
|
||||
/* XXX This message is useless! */
|
||||
xpt_print(periph->path, "fatal error, "
|
||||
"could not acquire reference count\n");
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/sbuf.h>
|
||||
#include <sys/sx.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/sysctl.h>
|
||||
@ -897,6 +898,7 @@ enc_ctor(struct cam_periph *periph, void *arg)
|
||||
struct ccb_getdev *cgd;
|
||||
char *tname;
|
||||
struct make_dev_args args;
|
||||
struct sbuf sb;
|
||||
|
||||
cgd = (struct ccb_getdev *)arg;
|
||||
if (cgd == NULL) {
|
||||
@ -1026,7 +1028,12 @@ enc_ctor(struct cam_periph *periph, void *arg)
|
||||
tname = "SEMB SAF-TE Device";
|
||||
break;
|
||||
}
|
||||
xpt_announce_periph(periph, tname);
|
||||
|
||||
sbuf_new(&sb, enc->announce_buf, ENC_ANNOUNCE_SZ, SBUF_FIXEDLEN);
|
||||
xpt_announce_periph_sbuf(periph, &sb, tname);
|
||||
sbuf_finish(&sb);
|
||||
sbuf_putbuf(&sb);
|
||||
|
||||
status = CAM_REQ_CMP;
|
||||
|
||||
out:
|
||||
|
@ -166,6 +166,9 @@ struct enc_softc {
|
||||
struct enc_fsm_state *enc_fsm_states;
|
||||
|
||||
struct intr_config_hook enc_boot_hold_ch;
|
||||
|
||||
#define ENC_ANNOUNCE_SZ 400
|
||||
char announce_buf[ENC_ANNOUNCE_SZ];
|
||||
};
|
||||
|
||||
static inline enc_cache_t *
|
||||
|
@ -589,15 +589,22 @@ static void scsi_dev_async(u_int32_t async_code,
|
||||
void *async_arg);
|
||||
static void scsi_action(union ccb *start_ccb);
|
||||
static void scsi_announce_periph(struct cam_periph *periph);
|
||||
static void scsi_announce_periph_sbuf(struct cam_periph *periph, struct sbuf *sb);
|
||||
static void scsi_proto_announce(struct cam_ed *device);
|
||||
static void scsi_proto_announce_sbuf(struct cam_ed *device,
|
||||
struct sbuf *sb);
|
||||
static void scsi_proto_denounce(struct cam_ed *device);
|
||||
static void scsi_proto_denounce_sbuf(struct cam_ed *device,
|
||||
struct sbuf *sb);
|
||||
static void scsi_proto_debug_out(union ccb *ccb);
|
||||
static void _scsi_announce_periph(struct cam_periph *, u_int *, u_int *, struct ccb_trans_settings *);
|
||||
|
||||
static struct xpt_xport_ops scsi_xport_ops = {
|
||||
.alloc_device = scsi_alloc_device,
|
||||
.action = scsi_action,
|
||||
.async = scsi_dev_async,
|
||||
.announce = scsi_announce_periph,
|
||||
.announce_sbuf = scsi_announce_periph_sbuf,
|
||||
};
|
||||
#define SCSI_XPT_XPORT(x, X) \
|
||||
static struct xpt_xport scsi_xport_ ## x = { \
|
||||
@ -619,7 +626,9 @@ SCSI_XPT_XPORT(ppb, PPB);
|
||||
|
||||
static struct xpt_proto_ops scsi_proto_ops = {
|
||||
.announce = scsi_proto_announce,
|
||||
.announce_sbuf = scsi_proto_announce_sbuf,
|
||||
.denounce = scsi_proto_denounce,
|
||||
.denounce_sbuf = scsi_proto_denounce_sbuf,
|
||||
.debug_out = scsi_proto_debug_out,
|
||||
};
|
||||
static struct xpt_proto scsi_proto = {
|
||||
@ -3019,56 +3028,123 @@ scsi_dev_async(u_int32_t async_code, struct cam_eb *bus, struct cam_et *target,
|
||||
}
|
||||
|
||||
static void
|
||||
scsi_announce_periph(struct cam_periph *periph)
|
||||
_scsi_announce_periph(struct cam_periph *periph, u_int *speed, u_int *freq, struct ccb_trans_settings *cts)
|
||||
{
|
||||
struct ccb_pathinq cpi;
|
||||
struct ccb_trans_settings cts;
|
||||
struct cam_path *path = periph->path;
|
||||
u_int speed;
|
||||
u_int freq;
|
||||
u_int mb;
|
||||
|
||||
cam_periph_assert(periph, MA_OWNED);
|
||||
|
||||
xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
|
||||
cts.type = CTS_TYPE_CURRENT_SETTINGS;
|
||||
xpt_action((union ccb*)&cts);
|
||||
if (cam_ccb_status((union ccb *)&cts) != CAM_REQ_CMP)
|
||||
xpt_setup_ccb(&cts->ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
cts->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
|
||||
cts->type = CTS_TYPE_CURRENT_SETTINGS;
|
||||
xpt_action((union ccb*)cts);
|
||||
if (cam_ccb_status((union ccb *)cts) != CAM_REQ_CMP)
|
||||
return;
|
||||
|
||||
/* Ask the SIM for its base transfer speed */
|
||||
xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL);
|
||||
cpi.ccb_h.func_code = XPT_PATH_INQ;
|
||||
xpt_action((union ccb *)&cpi);
|
||||
|
||||
/* Report connection speed */
|
||||
speed = cpi.base_transfer_speed;
|
||||
freq = 0;
|
||||
if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SPI) {
|
||||
*speed = cpi.base_transfer_speed;
|
||||
*freq = 0;
|
||||
|
||||
if (cts->ccb_h.status == CAM_REQ_CMP && cts->transport == XPORT_SPI) {
|
||||
struct ccb_trans_settings_spi *spi =
|
||||
&cts.xport_specific.spi;
|
||||
&cts->xport_specific.spi;
|
||||
|
||||
if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0
|
||||
&& spi->sync_offset != 0) {
|
||||
freq = scsi_calc_syncsrate(spi->sync_period);
|
||||
speed = freq;
|
||||
*freq = scsi_calc_syncsrate(spi->sync_period);
|
||||
*speed = *freq;
|
||||
}
|
||||
if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0)
|
||||
speed *= (0x01 << spi->bus_width);
|
||||
*speed *= (0x01 << spi->bus_width);
|
||||
}
|
||||
if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_FC) {
|
||||
if (cts->ccb_h.status == CAM_REQ_CMP && cts->transport == XPORT_FC) {
|
||||
struct ccb_trans_settings_fc *fc =
|
||||
&cts.xport_specific.fc;
|
||||
&cts->xport_specific.fc;
|
||||
|
||||
if (fc->valid & CTS_FC_VALID_SPEED)
|
||||
speed = fc->bitrate;
|
||||
*speed = fc->bitrate;
|
||||
}
|
||||
if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SAS) {
|
||||
if (cts->ccb_h.status == CAM_REQ_CMP && cts->transport == XPORT_SAS) {
|
||||
struct ccb_trans_settings_sas *sas =
|
||||
&cts.xport_specific.sas;
|
||||
&cts->xport_specific.sas;
|
||||
|
||||
if (sas->valid & CTS_SAS_VALID_SPEED)
|
||||
speed = sas->bitrate;
|
||||
*speed = sas->bitrate;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
scsi_announce_periph_sbuf(struct cam_periph *periph, struct sbuf *sb)
|
||||
{
|
||||
struct ccb_trans_settings cts;
|
||||
u_int speed, freq, mb;
|
||||
|
||||
_scsi_announce_periph(periph, &speed, &freq, &cts);
|
||||
if (cam_ccb_status((union ccb *)&cts) != CAM_REQ_CMP)
|
||||
return;
|
||||
|
||||
mb = speed / 1000;
|
||||
if (mb > 0)
|
||||
sbuf_printf(sb, "%s%d: %d.%03dMB/s transfers",
|
||||
periph->periph_name, periph->unit_number,
|
||||
mb, speed % 1000);
|
||||
else
|
||||
sbuf_printf(sb, "%s%d: %dKB/s transfers", periph->periph_name,
|
||||
periph->unit_number, speed);
|
||||
/* Report additional information about SPI connections */
|
||||
if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SPI) {
|
||||
struct ccb_trans_settings_spi *spi;
|
||||
|
||||
spi = &cts.xport_specific.spi;
|
||||
if (freq != 0) {
|
||||
sbuf_printf(sb, " (%d.%03dMHz%s, offset %d", freq / 1000,
|
||||
freq % 1000,
|
||||
(spi->ppr_options & MSG_EXT_PPR_DT_REQ) != 0
|
||||
? " DT" : "",
|
||||
spi->sync_offset);
|
||||
}
|
||||
if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0
|
||||
&& spi->bus_width > 0) {
|
||||
if (freq != 0) {
|
||||
sbuf_printf(sb, ", ");
|
||||
} else {
|
||||
sbuf_printf(sb, " (");
|
||||
}
|
||||
sbuf_printf(sb, "%dbit)", 8 * (0x01 << spi->bus_width));
|
||||
} else if (freq != 0) {
|
||||
sbuf_printf(sb, ")");
|
||||
}
|
||||
}
|
||||
if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_FC) {
|
||||
struct ccb_trans_settings_fc *fc;
|
||||
|
||||
fc = &cts.xport_specific.fc;
|
||||
if (fc->valid & CTS_FC_VALID_WWNN)
|
||||
sbuf_printf(sb, " WWNN 0x%llx", (long long) fc->wwnn);
|
||||
if (fc->valid & CTS_FC_VALID_WWPN)
|
||||
sbuf_printf(sb, " WWPN 0x%llx", (long long) fc->wwpn);
|
||||
if (fc->valid & CTS_FC_VALID_PORT)
|
||||
sbuf_printf(sb, " PortID 0x%x", fc->port);
|
||||
}
|
||||
sbuf_printf(sb, "\n");
|
||||
}
|
||||
|
||||
static void
|
||||
scsi_announce_periph(struct cam_periph *periph)
|
||||
{
|
||||
struct ccb_trans_settings cts;
|
||||
u_int speed, freq, mb;
|
||||
|
||||
_scsi_announce_periph(periph, &speed, &freq, &cts);
|
||||
if (cam_ccb_status((union ccb *)&cts) != CAM_REQ_CMP)
|
||||
return;
|
||||
|
||||
mb = speed / 1000;
|
||||
if (mb > 0)
|
||||
printf("%s%d: %d.%03dMB/s transfers",
|
||||
@ -3115,12 +3191,24 @@ scsi_announce_periph(struct cam_periph *periph)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
scsi_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb)
|
||||
{
|
||||
scsi_print_inquiry_sbuf(sb, &device->inq_data);
|
||||
}
|
||||
|
||||
static void
|
||||
scsi_proto_announce(struct cam_ed *device)
|
||||
{
|
||||
scsi_print_inquiry(&device->inq_data);
|
||||
}
|
||||
|
||||
static void
|
||||
scsi_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb)
|
||||
{
|
||||
scsi_print_inquiry_short_sbuf(sb, &device->inq_data);
|
||||
}
|
||||
|
||||
static void
|
||||
scsi_proto_denounce(struct cam_ed *device)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user