diff options
author | mav <mav@FreeBSD.org> | 2009-11-26 08:49:46 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2009-11-26 08:49:46 +0000 |
commit | 7c0d54bcfc79dce34d24170f6ae5ebb6e25b9e9f (patch) | |
tree | 580d695f05aa2ddcdc2101f3114e9dd4e0dd13d7 /sbin/camcontrol | |
parent | 2d9252d6c71a08629a451a1966338c6e119912d1 (diff) | |
download | FreeBSD-src-7c0d54bcfc79dce34d24170f6ae5ebb6e25b9e9f.zip FreeBSD-src-7c0d54bcfc79dce34d24170f6ae5ebb6e25b9e9f.tar.gz |
MFp4:
Improve ATA mode/SATA revision control.
Diffstat (limited to 'sbin/camcontrol')
-rw-r--r-- | sbin/camcontrol/camcontrol.8 | 3 | ||||
-rw-r--r-- | sbin/camcontrol/camcontrol.c | 120 |
2 files changed, 72 insertions, 51 deletions
diff --git a/sbin/camcontrol/camcontrol.8 b/sbin/camcontrol/camcontrol.8 index a0871ac..0509ef7 100644 --- a/sbin/camcontrol/camcontrol.8 +++ b/sbin/camcontrol/camcontrol.8 @@ -149,6 +149,7 @@ .Op generic args .Op Fl c .Op Fl D Ar enable|disable +.Op Fl M Ar mode .Op Fl O Ar offset .Op Fl q .Op Fl R Ar syncrate @@ -705,6 +706,8 @@ Show or set current negotiation settings. This is the default. .It Fl D Ar enable|disable Enable or disable disconnection. +.It Fl M Ar mode +Set ATA mode. .It Fl O Ar offset Set the command delay offset. .It Fl q diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c index 73bcd8f..1e71ae0 100644 --- a/sbin/camcontrol/camcontrol.c +++ b/sbin/camcontrol/camcontrol.c @@ -125,7 +125,7 @@ struct camcontrol_opts { #ifndef MINIMALISTIC static const char scsicmd_opts[] = "a:c:i:o:r"; static const char readdefect_opts[] = "f:GP"; -static const char negotiate_opts[] = "acD:O:qR:T:UW:"; +static const char negotiate_opts[] = "acD:M:O:qR:T:UW:"; #endif struct camcontrol_opts option_table[] = { @@ -3112,6 +3112,7 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, int user_settings = 0; int retval = 0; int disc_enable = -1, tag_enable = -1; + int mode = -1; int offset = -1; double syncrate = -1; int bus_width = -1; @@ -3120,12 +3121,10 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, struct ccb_pathinq cpi; ccb = cam_getccb(device); - if (ccb == NULL) { warnx("ratecontrol: error allocating ccb"); return(1); } - while ((c = getopt(argc, argv, combinedopt)) != -1) { switch(c){ case 'a': @@ -3146,6 +3145,15 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, } change_settings = 1; break; + case 'M': + mode = ata_string2mode(optarg); + if (mode < 0) { + warnx("unknown mode '%s'", optarg); + retval = 1; + goto ratecontrol_bailout; + } + change_settings = 1; + break; case 'O': offset = strtol(optarg, NULL, 0); if (offset < 0) { @@ -3160,7 +3168,6 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, break; case 'R': syncrate = atof(optarg); - if (syncrate < 0) { warnx("sync rate %f is < 0", syncrate); retval = 1; @@ -3196,17 +3203,14 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, break; } } - bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr)); - /* * Grab path inquiry information, so we can determine whether * or not the initiator is capable of the things that the user * requests. */ ccb->ccb_h.func_code = XPT_PATH_INQ; - if (cam_send_ccb(device, ccb) < 0) { perror("error sending XPT_PATH_INQ CCB"); if (arglist & CAM_ARG_VERBOSE) { @@ -3216,7 +3220,6 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, retval = 1; goto ratecontrol_bailout; } - if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { warnx("XPT_PATH_INQ CCB failed"); if (arglist & CAM_ARG_VERBOSE) { @@ -3226,17 +3229,14 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, retval = 1; goto ratecontrol_bailout; } - bcopy(&ccb->cpi, &cpi, sizeof(struct ccb_pathinq)); - bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr)); - - if (quiet == 0) - fprintf(stdout, "Current Parameters:\n"); - + if (quiet == 0) { + fprintf(stdout, "%s parameters:\n", + user_settings ? "User" : "Current"); + } retval = get_print_cts(device, user_settings, quiet, &ccb->cts); - if (retval != 0) goto ratecontrol_bailout; @@ -3246,16 +3246,20 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, if (change_settings) { int didsettings = 0; struct ccb_trans_settings_spi *spi = NULL; + struct ccb_trans_settings_ata *ata = NULL; + struct ccb_trans_settings_sata *sata = NULL; struct ccb_trans_settings_scsi *scsi = NULL; - if (ccb->cts.transport == XPORT_SPI) { + if (ccb->cts.transport == XPORT_SPI) spi = &ccb->cts.xport_specific.spi; - spi->valid = 0; - } - if (ccb->cts.protocol == PROTO_SCSI) { + if (ccb->cts.transport == XPORT_ATA) + ata = &ccb->cts.xport_specific.ata; + if (ccb->cts.transport == XPORT_SATA) + sata = &ccb->cts.xport_specific.sata; + if (ccb->cts.protocol == PROTO_SCSI) scsi = &ccb->cts.proto_specific.scsi; - scsi->valid = 0; - } + ccb->cts.xport_specific.valid = 0; + ccb->cts.proto_specific.valid = 0; if (spi && disc_enable != -1) { spi->valid |= CTS_SPI_VALID_DISC; if (disc_enable == 0) @@ -3263,7 +3267,6 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, else spi->flags |= CTS_SPI_FLAGS_DISC_ENB; } - if (scsi && tag_enable != -1) { if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) { warnx("HBA does not support tagged queueing, " @@ -3271,21 +3274,16 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, retval = 1; goto ratecontrol_bailout; } - scsi->valid |= CTS_SCSI_VALID_TQ; - if (tag_enable == 0) scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; else scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; didsettings++; } - if (spi && offset != -1) { if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) { - warnx("HBA at %s%d is not cable of changing " - "offset", cpi.dev_name, - cpi.unit_number); + warnx("HBA is not capable of changing offset"); retval = 1; goto ratecontrol_bailout; } @@ -3293,28 +3291,23 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, spi->sync_offset = offset; didsettings++; } - if (spi && syncrate != -1) { int prelim_sync_period; u_int freq; if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) { - warnx("HBA at %s%d is not cable of changing " - "transfer rates", cpi.dev_name, - cpi.unit_number); + warnx("HBA is not capable of changing " + "transfer rates"); retval = 1; goto ratecontrol_bailout; } - spi->valid |= CTS_SPI_VALID_SYNC_RATE; - /* * The sync rate the user gives us is in MHz. * We need to translate it into KHz for this * calculation. */ syncrate *= 1000; - /* * Next, we calculate a "preliminary" sync period * in tenths of a nanosecond. @@ -3323,14 +3316,43 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, prelim_sync_period = 0; else prelim_sync_period = 10000000 / syncrate; - spi->sync_period = scsi_calc_syncparam(prelim_sync_period); - freq = scsi_calc_syncsrate(spi->sync_period); didsettings++; } - + if (sata && syncrate != -1) { + if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) { + warnx("HBA is not capable of changing " + "transfer rates"); + retval = 1; + goto ratecontrol_bailout; + } + sata->revision = ata_speed2revision(syncrate * 100); + if (sata->revision < 0) { + warnx("Invalid rate %f", syncrate); + retval = 1; + goto ratecontrol_bailout; + } + sata->valid |= CTS_SATA_VALID_REVISION; + didsettings++; + } + if ((ata || sata) && mode != -1) { + if ((cpi.hba_inquiry & PI_SDTR_ABLE) == 0) { + warnx("HBA is not capable of changing " + "transfer rates"); + retval = 1; + goto ratecontrol_bailout; + } + if (ata) { + ata->mode = mode; + ata->valid |= CTS_ATA_VALID_MODE; + } else { + sata->mode = mode; + sata->valid |= CTS_SATA_VALID_MODE; + } + didsettings++; + } /* * The bus_width argument goes like this: * 0 == 8 bit @@ -3341,7 +3363,6 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, * number. */ if (spi && bus_width != -1) { - /* * We might as well validate things here with a * decipherable error message, rather than what @@ -3365,17 +3386,19 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, retval = 1; goto ratecontrol_bailout; } - spi->valid |= CTS_SPI_VALID_BUS_WIDTH; spi->bus_width = bus_width >> 4; didsettings++; } - if (didsettings == 0) { goto ratecontrol_bailout; } + if (!user_settings && (ata || sata)) { + warnx("You can modify only user settings for ATA/SATA"); + retval = 1; + goto ratecontrol_bailout; + } ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS; - if (cam_send_ccb(device, ccb) < 0) { perror("error sending XPT_SET_TRAN_SETTINGS CCB"); if (arglist & CAM_ARG_VERBOSE) { @@ -3385,7 +3408,6 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, retval = 1; goto ratecontrol_bailout; } - if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { warnx("XPT_SET_TRANS_SETTINGS CCB failed"); if (arglist & CAM_ARG_VERBOSE) { @@ -3396,11 +3418,9 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, goto ratecontrol_bailout; } } - if (send_tur) { retval = testunitready(device, retry_count, timeout, (arglist & CAM_ARG_VERBOSE) ? 0 : 1); - /* * If the TUR didn't succeed, just bail. */ @@ -3409,7 +3429,6 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, fprintf(stderr, "Test Unit Ready failed\n"); goto ratecontrol_bailout; } - /* * If the user wants things quiet, there's no sense in * getting the transfer settings, if we're not going @@ -3417,13 +3436,11 @@ ratecontrol(struct cam_device *device, int retry_count, int timeout, */ if (quiet != 0) goto ratecontrol_bailout; - - fprintf(stdout, "New Parameters:\n"); + fprintf(stdout, "New parameters:\n"); retval = get_print_cts(device, user_settings, 0, NULL); } ratecontrol_bailout: - cam_freeccb(ccb); return(retval); } @@ -4310,8 +4327,8 @@ usage(int verbose) " <all|bus[:target[:lun]]|off>\n" " camcontrol tags [dev_id][generic args] [-N tags] [-q] [-v]\n" " camcontrol negotiate [dev_id][generic args] [-a][-c]\n" -" [-D <enable|disable>][-O offset][-q]\n" -" [-R syncrate][-v][-T <enable|disable>]\n" +" [-D <enable|disable>][-M mode][-O offset]\n" +" [-q][-R syncrate][-v][-T <enable|disable>]\n" " [-U][-W bus_width]\n" " camcontrol format [dev_id][generic args][-q][-r][-w][-y]\n" " camcontrol idle [dev_id][generic args][-t time]\n" @@ -4402,6 +4419,7 @@ usage(int verbose) "-a send a test unit ready after negotiation\n" "-c report/set current negotiation settings\n" "-D <arg> \"enable\" or \"disable\" disconnection\n" +"-M mode set ATA mode\n" "-O offset set command delay offset\n" "-q be quiet, don't report anything\n" "-R syncrate synchronization rate in MHz\n" |