Index: sys/cam/ata/ata_all.h =================================================================== --- sys/cam/ata/ata_all.h +++ sys/cam/ata/ata_all.h @@ -110,7 +110,9 @@ 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_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*), Index: sys/cam/ata/ata_all.c =================================================================== --- sys/cam/ata/ata_all.c +++ sys/cam/ata/ata_all.c @@ -382,12 +382,10 @@ 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 @@ 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 @@ -428,18 +474,38 @@ } 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 @@ 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) { Index: sys/cam/ata/ata_da.c =================================================================== --- sys/cam/ata/ata_da.c +++ sys/cam/ata/ata_da.c @@ -256,6 +256,8 @@ u_int errors; u_int invalidations; #endif +#define ADA_ANNOUNCE_SZ 400 + char announce_buffer[ADA_ANNOUNCE_SZ]; }; struct ada_quirk_entry { @@ -1659,8 +1661,9 @@ 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[80]; caddr_t match; u_int maxio; int quirks; @@ -1833,8 +1836,12 @@ "%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 Index: sys/cam/ata/ata_xpt.c =================================================================== --- sys/cam/ata/ata_xpt.c +++ sys/cam/ata/ata_xpt.c @@ -189,11 +189,16 @@ 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 @@ .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 @@ 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_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_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 @@ } 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 @@ 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 @@ 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; @@ -2151,6 +2172,64 @@ } 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) { ata_print_ident(&device->ident_data); @@ -2163,6 +2242,18 @@ } 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) { semb_print_ident((struct sep_identify_data *)&device->ident_data); @@ -2175,6 +2266,12 @@ } 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) { char cdb_str[(sizeof(struct ata_cmd) * 3) + 1]; Index: sys/cam/cam_periph.c =================================================================== --- sys/cam/cam_periph.c +++ sys/cam/cam_periph.c @@ -641,8 +641,14 @@ 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) Index: sys/cam/cam_xpt.c =================================================================== --- sys/cam/cam_xpt.c +++ sys/cam/cam_xpt.c @@ -116,6 +116,7 @@ TAILQ_HEAD(, ccb_hdr) ccb_scanq; int buses_to_config; int buses_config_done; + int announce_nosbuf; /* * Registered buses @@ -174,6 +175,8 @@ &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; @@ -1094,6 +1097,65 @@ } 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; + + if (xsoftc.announce_nosbuf != 0) { + xpt_announce_periph(periph, announce_string); + return; + } + + /* Fall back to the non-sbuf method if necessary */ + 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) { if (quirks != 0) { @@ -1103,6 +1165,21 @@ } 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) { struct cam_path *path = periph->path; @@ -1130,6 +1207,46 @@ 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); + + if (xsoftc.announce_nosbuf != 0) { + xpt_denounce_periph(periph); + return; + } + + /* Fall back to the non-sbuf method if necessary */ + 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) 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,11 +69,14 @@ 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; }; Index: sys/cam/cam_xpt_periph.h =================================================================== --- sys/cam/cam_xpt_periph.h +++ sys/cam/cam_xpt_periph.h @@ -45,9 +45,16 @@ 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 */ Index: sys/cam/scsi/scsi_all.h =================================================================== --- sys/cam/scsi/scsi_all.h +++ sys/cam/scsi/scsi_all.h @@ -3820,7 +3820,11 @@ 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); Index: sys/cam/scsi/scsi_all.c =================================================================== --- sys/cam/scsi/scsi_all.c +++ sys/cam/scsi/scsi_all.c @@ -5169,7 +5169,7 @@ sbuf_finish(&sb); - printf("%s", sbuf_data(&sb)); + sbuf_putbuf(&sb); } #else /* !_KERNEL */ @@ -5361,11 +5361,10 @@ * 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 @@ 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_short(struct scsi_inquiry_data *inq_data) +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) { - char vendor[16], product[48], revision[16]; - 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)); + 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) +{ + struct sbuf sb; + char buffer[84]; - 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); } /* Index: sys/cam/scsi/scsi_cd.c =================================================================== --- sys/cam/scsi/scsi_cd.c +++ sys/cam/scsi/scsi_cd.c @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include @@ -158,6 +159,11 @@ 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 @@ 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 @@ 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,27 +1176,32 @@ */ 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, - CD_Q_BIT_STRING); + if (announce_buf != NULL) { + struct sbuf sb; + + sbuf_new(&sb, softc->announce_buf, CD_ANNOUNCE_SZ, SBUF_FIXEDLEN); /* * Create our sysctl variables, now that we know * we have successfully attached. */ taskqueue_enqueue(taskqueue_thread,&softc->sysctl_task); + 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); } softc->state = CD_STATE_NORMAL; /* Index: sys/cam/scsi/scsi_da.c =================================================================== --- sys/cam/scsi/scsi_da.c +++ sys/cam/scsi/scsi_da.c @@ -338,6 +338,10 @@ 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) \ @@ -4218,12 +4222,16 @@ { 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 @@ -4276,7 +4284,7 @@ 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 { /* @@ -4288,7 +4296,7 @@ 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), @@ -4297,8 +4305,6 @@ } else { int error; - announce_buf[0] = '\0'; - /* * Retry any UNIT ATTENTION type errors. They * are expected at boot. @@ -4382,11 +4388,10 @@ &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( @@ -4400,6 +4405,8 @@ xpt_print(periph->path, "fatal error, " "failed to attach to device\n"); + announce_buf = NULL; + /* * Free up resources. */ @@ -4408,20 +4415,29 @@ } } 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"); } Index: sys/cam/scsi/scsi_enc.c =================================================================== --- sys/cam/scsi/scsi_enc.c +++ sys/cam/scsi/scsi_enc.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -897,6 +898,7 @@ 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 @@ 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: Index: sys/cam/scsi/scsi_enc_internal.h =================================================================== --- sys/cam/scsi/scsi_enc_internal.h +++ sys/cam/scsi/scsi_enc_internal.h @@ -166,6 +166,9 @@ 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 * Index: sys/cam/scsi/scsi_xpt.c =================================================================== --- sys/cam/scsi/scsi_xpt.c +++ sys/cam/scsi/scsi_xpt.c @@ -589,15 +589,22 @@ 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 @@ 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 @@ } 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,12 +3192,24 @@ } 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) { scsi_print_inquiry_short(&device->inq_data);