Index: sys/cam/cam_xpt.c =================================================================== --- sys/cam/cam_xpt.c +++ sys/cam/cam_xpt.c @@ -1034,6 +1034,49 @@ } } +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; + + 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); + proto = xpt_proto_find(path->device->protocol); + 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_periph(struct cam_periph *periph, char *announce_string) @@ -1089,6 +1132,16 @@ } void +xpt_announce_quirks_sbuf(struct cam_periph *periph, int quirks, + char *bit_string, struct sbuf *sb) +{ + 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) { struct cam_path *path = periph->path; Index: sys/cam/cam_xpt_internal.h =================================================================== --- sys/cam/cam_xpt_internal.h +++ sys/cam/cam_xpt_internal.h @@ -47,6 +47,7 @@ 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 @@ 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,10 +69,12 @@ 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_debug_out_func debug_out; }; Index: sys/cam/cam_xpt_periph.h =================================================================== --- sys/cam/cam_xpt_periph.h +++ sys/cam/cam_xpt_periph.h @@ -45,8 +45,14 @@ 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, + int quirks, char *bit_string, + struct sbuf *sb); void xpt_denounce_periph(struct cam_periph *periph); #endif Index: sys/cam/scsi/scsi_all.h =================================================================== --- sys/cam/scsi/scsi_all.h +++ sys/cam/scsi/scsi_all.h @@ -3820,6 +3820,7 @@ 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 scsi_inquiry_data *inq_data, struct sbuf *sb); void scsi_print_inquiry_short(struct scsi_inquiry_data *inq_data); u_int scsi_calc_syncsrate(u_int period_factor); Index: sys/cam/scsi/scsi_all.c =================================================================== --- sys/cam/scsi/scsi_all.c +++ sys/cam/scsi/scsi_all.c @@ -5361,6 +5361,119 @@ * for this routine to function properly. */ void +scsi_print_inquiry_sbuf(struct scsi_inquiry_data *inq_data, struct sbuf *sb) +{ + u_int8_t type; + char *dtype, *qtype; + + type = SID_TYPE(inq_data); + + /* + * Figure out basic device type and qualifier. + */ + if (SID_QUAL_IS_VENDOR_UNIQUE(inq_data)) { + qtype = " (vendor-unique qualifier)"; + } else { + switch (SID_QUAL(inq_data)) { + case SID_QUAL_LU_CONNECTED: + qtype = ""; + break; + + case SID_QUAL_LU_OFFLINE: + qtype = " (offline)"; + break; + + case SID_QUAL_RSVD: + qtype = " (reserved qualifier)"; + break; + default: + case SID_QUAL_BAD_LU: + qtype = " (LUN not supported)"; + break; + } + } + + switch (type) { + case T_DIRECT: + dtype = "Direct Access"; + break; + case T_SEQUENTIAL: + dtype = "Sequential Access"; + break; + case T_PRINTER: + dtype = "Printer"; + break; + case T_PROCESSOR: + dtype = "Processor"; + break; + case T_WORM: + dtype = "WORM"; + break; + case T_CDROM: + dtype = "CD-ROM"; + break; + case T_SCANNER: + dtype = "Scanner"; + break; + case T_OPTICAL: + dtype = "Optical"; + break; + case T_CHANGER: + dtype = "Changer"; + break; + case T_COMM: + dtype = "Communication"; + break; + case T_STORARRAY: + dtype = "Storage Array"; + break; + case T_ENCLOSURE: + dtype = "Enclosure Services"; + break; + case T_RBC: + dtype = "Simplified Direct Access"; + break; + case T_OCRW: + dtype = "Optical Card Read/Write"; + break; + case T_OSD: + dtype = "Object-Based Storage"; + break; + case T_ADC: + dtype = "Automation/Drive Interface"; + break; + case T_ZBC_HM: + dtype = "Host Managed Zoned Block"; + break; + case T_NODEVICE: + dtype = "Uninstalled"; + break; + default: + dtype = "unknown"; + break; + } + + 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, "> "); + + sbuf_printf(sb, "%s %s ", SID_IS_REMOVABLE(inq_data) ? "Removable" : "Fixed", dtype); + + if (SID_ANSI_REV(inq_data) == SCSI_REV_0) + sbuf_printf(sb, "SCSI "); + else if (SID_ANSI_REV(inq_data) <= SCSI_REV_SPC) { + sbuf_printf(sb, "SCSI-%d ", SID_ANSI_REV(inq_data)); + } else { + sbuf_printf(sb, "SPC-%d SCSI ", SID_ANSI_REV(inq_data) - 2); + } + sbuf_printf(sb, "device%s\n", qtype); +} + +void scsi_print_inquiry(struct scsi_inquiry_data *inq_data) { u_int8_t type; Index: sys/cam/scsi/scsi_da.c =================================================================== --- sys/cam/scsi/scsi_da.c +++ sys/cam/scsi/scsi_da.c @@ -334,6 +334,8 @@ u_int timeouts; u_int invalidations; #endif +#define DA_ANNOUNCE_SZ 400 + char announcebuf[DA_ANNOUNCE_SZ]; }; #define dadeleteflag(softc, delete_method, enable) \ @@ -4375,11 +4377,16 @@ */ /* increase the refcount */ if (cam_periph_acquire(periph) == CAM_REQ_CMP) { + struct sbuf sb; + + sbuf_new(&sb, softc->announcebuf, DA_ANNOUNCE_SZ, SBUF_FIXEDLEN); taskqueue_enqueue(taskqueue_thread, &softc->sysctl_task); - xpt_announce_periph(periph, announce_buf); - xpt_announce_quirks(periph, softc->quirks, - DA_Q_BIT_STRING); + xpt_announce_periph_sbuf(periph, &sb, announce_buf); + xpt_announce_quirks_sbuf(periph, softc->quirks, + DA_Q_BIT_STRING, &sb); + sbuf_finish(&sb); + sbuf_putbuf(&sb); } else { xpt_print(periph->path, "fatal error, " "could not acquire reference count\n"); Index: sys/cam/scsi/scsi_xpt.c =================================================================== --- sys/cam/scsi/scsi_xpt.c +++ sys/cam/scsi/scsi_xpt.c @@ -589,15 +589,19 @@ 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_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,6 +623,7 @@ static struct xpt_proto_ops scsi_proto_ops = { .announce = scsi_proto_announce, + .announce_sbuf = scsi_proto_announce_sbuf, .denounce = scsi_proto_denounce, .debug_out = scsi_proto_debug_out, }; @@ -3019,56 +3024,123 @@ } 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", @@ -3116,6 +3188,12 @@ } static void +scsi_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb) +{ + scsi_print_inquiry_sbuf(&device->inq_data, sb); +} + +static void scsi_proto_announce(struct cam_ed *device) { scsi_print_inquiry(&device->inq_data);