summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2009-11-26 08:49:46 +0000
committermav <mav@FreeBSD.org>2009-11-26 08:49:46 +0000
commit7c0d54bcfc79dce34d24170f6ae5ebb6e25b9e9f (patch)
tree580d695f05aa2ddcdc2101f3114e9dd4e0dd13d7 /sbin
parent2d9252d6c71a08629a451a1966338c6e119912d1 (diff)
downloadFreeBSD-src-7c0d54bcfc79dce34d24170f6ae5ebb6e25b9e9f.zip
FreeBSD-src-7c0d54bcfc79dce34d24170f6ae5ebb6e25b9e9f.tar.gz
MFp4:
Improve ATA mode/SATA revision control.
Diffstat (limited to 'sbin')
-rw-r--r--sbin/camcontrol/camcontrol.83
-rw-r--r--sbin/camcontrol/camcontrol.c120
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"
OpenPOWER on IntegriCloud