aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenneth D. Merry <ken@FreeBSD.org>1999-05-06 20:16:39 +0000
committerKenneth D. Merry <ken@FreeBSD.org>1999-05-06 20:16:39 +0000
commit9deea8574ea19e3db2c89e0d51af18441379fa8e (patch)
tree24da016949ae420e1f75e19eb4ce8a10750b504f
parentb0eeea20421ad6d9b90f1f1b081d980349642cc3 (diff)
downloadsrc-9deea8574ea19e3db2c89e0d51af18441379fa8e.tar.gz
src-9deea8574ea19e3db2c89e0d51af18441379fa8e.zip
Add a number of interrelated CAM feature enhancements and bug fixes.
NOTE: These changes will require recompilation of any userland applications, like cdrecord, xmcd, etc., that use the CAM passthrough interface. A make world is recommended. camcontrol.[c8]: - We now support two new commands, "tags" and "negotiate". - The tags commands allows users to view the number of tagged openings for a device as well as a number of other related parameters, and it allows users to set tagged openings for a device. - The negotiate command allows users to enable and disable disconnection and tagged queueing, set sync rates, offsets and bus width. Note that not all of those features are available for all controllers. Only the adv, ahc, and ncr drivers fully support all of the features at this point. Some cards do not allow the setting of sync rates, offsets and the like, and some of the drivers don't have any facilities to do so. Some drivers, like the adw driver, only support enabling or disabling sync negotiation, but do not support setting sync rates. - new description in the camcontrol man page of how to format a disk - cleanup of the camcontrol inquiry command - add support in the 'devlist' command for skipping unconfigured devices if -v was not specified on the command line. - make use of the new base_transfer_speed in the path inquiry CCB. - fix CCB bzero cases cam_xpt.c, cam_sim.[ch], cam_ccb.h: - new flags on many CCB function codes to designate whether they're non-immediate, use a user-supplied CCB, and can only be passed from userland programs via the xpt device. Use these flags in the transport layer and pass driver to categorize CCBs. - new flag in the transport layer device matching code for device nodes that indicates whether a device is unconfigured - bump the CAM version from 0x10 to 0x11 - Change the CAM ioctls to use the version as their group code, so we can force users to recompile code even when the CCB size doesn't change. - add + fill in a new value in the path inquiry CCB, base_transfer_speed. Remove a corresponding field from the cam_sim structure, and add code to every SIM to set this field to the proper value. - Fix the set transfer settings code in the transport layer. scsi_cd.c: - make some variables volatile instead of just casting them in various places - fix a race condition in the changer code - attach unless we get a "logical unit not supported" error. This should fix all of the cases where people have devices that return weird errors when they don't have media in the drive. scsi_da.c: - attach unless we get a "logical unit not supported" error scsi_pass.c: - for immediate CCBs, just malloc a CCB to send the user request in. This gets rid of the 'held' count problem in camcontrol tags. scsi_pass.h: - change the CAM ioctls to use the CAM version as their group code. adv driver: - Allow changing the sync rate and offset separately. adw driver - Allow changing the sync rate and offset separately. aha driver: - Don't return CAM_REQ_CMP for SET_TRAN_SETTINGS CCBs. ahc driver: - Allow setting offset and sync rate separately bt driver: - Don't return CAM_REQ_CMP for SET_TRAN_SETTINGS CCBs. NCR driver: - Fix the ultra/ultra 2 negotiation bug - allow setting both the sync rate and offset separately Other HBA drivers: - Put code in to set the base_transfer_speed field for XPT_GET_TRAN_SETTINGS CCBs. Reviewed by: gibbs, mjacob (isp), imp (aha)
Notes
Notes: svn path=/head/; revision=46581
-rw-r--r--sbin/camcontrol/camcontrol.8200
-rw-r--r--sbin/camcontrol/camcontrol.c911
-rw-r--r--sys/cam/cam_ccb.h120
-rw-r--r--sys/cam/cam_sim.c13
-rw-r--r--sys/cam/cam_sim.h13
-rw-r--r--sys/cam/cam_xpt.c68
-rw-r--r--sys/cam/scsi/scsi_cd.c35
-rw-r--r--sys/cam/scsi/scsi_da.c13
-rw-r--r--sys/cam/scsi/scsi_pass.c48
-rw-r--r--sys/cam/scsi/scsi_pass.h8
-rw-r--r--sys/dev/advansys/advansys.c45
-rw-r--r--sys/dev/advansys/advlib.c5
-rw-r--r--sys/dev/advansys/adwcam.c26
-rw-r--r--sys/dev/aha/aha.c5
-rw-r--r--sys/dev/ahb/ahb.c3
-rw-r--r--sys/dev/aic7xxx/aic7xxx.c14
-rw-r--r--sys/dev/buslogic/bt.c5
-rw-r--r--sys/dev/dpt/dpt_scsi.c3
-rw-r--r--sys/dev/isp/isp_freebsd.c19
-rw-r--r--sys/dev/ppbus/vpo.c3
-rw-r--r--sys/i386/eisa/ahb.c3
-rw-r--r--sys/i386/isa/bs/bs.c1
-rw-r--r--sys/pci/ncr.c62
-rw-r--r--sys/pci/simos.c3
24 files changed, 1400 insertions, 226 deletions
diff --git a/sbin/camcontrol/camcontrol.8 b/sbin/camcontrol/camcontrol.8
index 303318678167..f5dea97ae84a 100644
--- a/sbin/camcontrol/camcontrol.8
+++ b/sbin/camcontrol/camcontrol.8
@@ -1,5 +1,5 @@
.\"
-.\" Copyright (c) 1998 Kenneth D. Merry.
+.\" Copyright (c) 1998, 1999 Kenneth D. Merry.
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $Id: camcontrol.8,v 1.9 1998/12/20 18:51:56 mjacob Exp $
+.\" $Id: camcontrol.8,v 1.10 1999/02/27 07:55:58 ken Exp $
.\"
.Dd September 14, 1998
.Dt CAMCONTROL 8
@@ -97,6 +97,24 @@ debug
.Op Fl S
.Op Fl c
.Aq all|off|bus Ns Op :target Ns Op :lun
+.Nm camcontrol
+tags
+.Op generic args
+.Op Fl N Ar tags
+.Op Fl q
+.Op Fl v
+.Nm camcontrol
+negotiate
+.Op generic args
+.Op Fl c
+.Op Fl D Ar enable|disable
+.Op Fl O Ar offset
+.Op Fl q
+.Op Fl R Ar syncrate
+.Op Fl T Ar enable|disable
+.Op Fl U
+.Op Fl W Ar bus_width
+.Op Fl v
.Sh DESCRIPTION
.Nm camcontrol
is a utility designed to provide a way for users to access and control the
@@ -105,7 +123,7 @@ CAM subsystem.
.Pp
.Nm camcontrol
can cause a loss of data and/or system crashes if used improperly. Even
-expert users are encouraged to excercise caution when using this command.
+expert users are encouraged to exercise caution when using this command.
Novice users should stay away from this utility.
.Pp
.Nm camcontrol
@@ -239,7 +257,7 @@ This can be overridden by specifying a different file in the
.Ev SCSI_MODES
environment variable. The modepage command takes several arguments:
.Bl -tag -width 012345678901
-.It Fl B
+.It Fl d
Disable block descriptors for mode sense.
.It Fl e
This flag allows the user to edit values in the mode page.
@@ -314,6 +332,135 @@ Turn on debugging for the given bus, target or lun. If the lun or target
and lun are not specified, they are wildcarded. (i.e., just specifying a
bus turns on debugging printfs for all devices on that bus.)
.El
+.It tags
+Show or set the number of "tagged openings" or simultaneous transactions
+we attempt to queue to a particular device. By default, the
+.Sq tags
+command, with no command-specific arguments (i.e. only generic arguments)
+prints out the "soft" maximum number of transactions that can be queued to
+the device in question. For more detailed information, use the
+.Fl v
+argument described below.
+.Bl -tag -width 0123456
+.It Fl N Ar tags
+Set the number of tags for the given device. This must be between the
+minimum and maximum number set in the kernel quirk table. The default for
+most devices that support tagged queueing is a minimum of 2 and a maximum
+of 255. The minimum and maximum values for a given device may be
+determined by using the
+.Fl v
+switch. The meaning of the
+.Fl v
+switch for this
+.Nm camcontrol
+subcommand is described below.
+.It Fl q
+Be quiet, and don't report the number of tags. This is generally used when
+setting the number of tags.
+.It Fl v
+The verbose flag has special functionality for the
+.Em tags
+argument. It causes
+.Nm camcontrol
+to print out the tagged queueing related fields of the XPT_GDEV_TYPE CCB:
+.Bl -tag -width 0123456789012
+.It dev_openings
+This is the amount of capacity for transactions queued to a given device.
+.It dev_active
+This is the number of transactions currently queued to a device.
+.It devq_openings
+This is the kernel queue space for transactions. This count usually mirrors
+dev_openings except during error recovery operations when
+the device queue is frozen (device is not allowed to receive
+commands), the number of dev_openings is reduced, or transaction
+replay is occurring.
+.It devq_queued
+This is the number of transactions waiting in the kernel queue for capacity
+on the device. This number is usually zero unless error recovery is in
+progress.
+.It held
+The held count is the number of CCBs held by peripheral drivers that have
+either just been completed or are about to be released to the transport
+layer for service by a device. Held CCBs reserve capacity on a given
+device.
+.It mintags
+This is the current "hard" minimum number of transactions that can be
+queued to a device at once. The
+.Ar dev_openings
+value above cannot go below this number. The default value for
+.Ar mintags
+is 2, although it may be set higher or lower for various devices.
+.It maxtags
+This is the "hard" maximum number of transactions that can be queued to a
+device at one time. The
+.Ar dev_openings
+value cannot go above this number. The default value for
+.Ar maxtags
+is 255, although it may be set higher or lower for various devices.
+.El
+.El
+.It negotiate
+Show or negotiate various communication parameters. Some controllers may
+not support setting or changing some of these values. For instance, the
+Adaptec 174x controllers do not support changing a device's sync rate or
+offset.
+.Nm camcontrol
+will not attempt to set the parameter if the controller indicates that it
+does not support setting the parameter. To find out what the controller
+supports, use the
+.Fl v
+flag. The meaning of the
+.Fl v
+flag for the
+.Sq negotiate
+command is described below. Also, some controller drivers don't support
+setting negotiation parameters, even if the underlying controller supports
+negotiation changes. Some controllers, such as the Advansys wide
+controllers, support enabling and disabling synchronous negotiation for
+a device, but do not support setting the synchronous negotiation rate.
+.Bl -tag -width 01234567890123456
+.It Fl a
+Attempt to make the negotiation settings take effect immediately by sending
+a Test Unit Ready command to the device.
+.It Fl c
+Show or set current negotiation settings. This is the default.
+.It Fl D Ar enable|disable
+Enable or disable disconnection.
+.It Fl O Ar offset
+Set the command delay offset.
+.It Fl q
+Be quiet, don't print anything. This is generally useful when you want to
+set a parameter, but don't want any status information.
+.It Fl R Ar syncrate
+Change the synchronization rate for a device. The sync rate is a floating
+point value specified in MHz. So, for instance,
+.Sq 20.000
+is a legal value, as is
+.Sq 20 .
+.It Fl T Ar enable|disable
+Enable or disable tagged queueing for a device.
+.It Fl U
+Show or set user negotiation settings. The default is to show or set
+current negotiation settings.
+.It Fl v
+The verbose switch has special meaning for the
+.Sq negotiate
+subcommand. It causes
+.Nm camcontrol
+to print out the contents of a Path Inquiry (XPT_PATH_INQ) CCB sent to the
+controller driver.
+.It Fl W Ar bus_width
+Specify the bus width to negotiate with a device. The bus width is
+specified in bits. The only useful values to specify are 8, 16, and 32
+bits. The controller must support the bus width in question in order for
+the setting to take effect.
+.El
+.Pp
+In general, sync rate and offset settings will not take effect for a
+device until a command has been sent to the device. The
+.Fl a
+switch above will automatically send a Test Unit Ready to the device so
+negotiation parameters will take effect.
.El
.Sh ENVIRONMENT
The
@@ -396,8 +543,53 @@ Rescan SCSI bus 0 for devices that have been added, removed or changed.
.Pp
Rescan SCSI bus 0, target 1, lun 0 to see if it has been added, removed, or
changed.
+.Pp
+.Dl camcontrol tags -n da -u 5 -N 24
+.Pp
+Set the number of concurrent transactions for da5 to 24.
+.Pp
+.Bd -literal -offset foobar
+camcontrol negotiate -n da -u 4 -T disable
+.Ed
+.Pp
+Disable tagged queueing for da4.
+.Pp
+.Bd -literal -offset foobar
+camcontrol negotiate -n da -u 3 -R 20.000 -O 15 -a
+.Ed
+.Pp
+Negotiate a sync rate of 20MHz and an offset of 15 with da3. Then send a
+Test Unit Ready command to make the settings take effect.
+.Pp
+.Bd -literal -offset foobar
+camcontrol cmd -n da -u 3 -v -t 7200 -c "4 0 0 0 0 0"
+.Ed
+.Pp
+Send the FORMAT UNIT (0x04) command to da3. This will low-level format the
+disk. Print sense information if the command fails, and set the timeout to
+two hours (or 7200 seconds).
+.Pp
+.Em WARNING! WARNING! WARNING!
+.Pp
+Low level formatting a disk will destroy ALL data on the disk. Use
+extreme caution when issuing this command. Many users low-level format
+disks that do not really need to be low-level formatted. There are
+relatively few scenarios that call for low-level formatting a disk.
+One reason for
+low-level formatting a disk is if you want to change the physical sector
+size of the disk. Another reason for low-level formatting a disk is to
+revive the disk if you are getting "medium format corrupted" errors from the
+disk in response to read and write requests.
+.Pp
+Some disks take longer than others to format. Users should specify a
+timeout long enough to allow the format to complete. Some hard disks
+will complete a format operation in a very short period of time (on the
+order of 5 minutes or less). This is often because the drive doesn't
+really support the FORMAT UNIT command -- it just accepts the command,
+waits a few minutes and then returns it.
.Sh SEE ALSO
.Xr cam 3 ,
+.Xr cam_cdbparse 3 ,
.Xr pass 4 ,
.Xr cam 9 ,
.Xr xpt 9
diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c
index fb2f05e943a5..385e677ea6e2 100644
--- a/sbin/camcontrol/camcontrol.c
+++ b/sbin/camcontrol/camcontrol.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 1998 Kenneth D. Merry
+ * Copyright (c) 1997, 1998, 1999 Kenneth D. Merry
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: camcontrol.c,v 1.8 1998/12/20 20:32:34 mjacob Exp $
+ * $Id: camcontrol.c,v 1.9 1999/01/14 05:56:30 gibbs Exp $
*/
#include <sys/ioctl.h>
@@ -65,6 +65,9 @@ typedef enum {
CAM_ARG_USAGE = 0x0000000a,
CAM_ARG_DEBUG = 0x0000000b,
CAM_ARG_RESET = 0x0000000c,
+ CAM_ARG_FORMAT = 0x0000000d,
+ CAM_ARG_TAG = 0x0000000e,
+ CAM_ARG_RATE = 0x0000000f,
CAM_ARG_OPT_MASK = 0x0000000f,
CAM_ARG_VERBOSE = 0x00000010,
CAM_ARG_DEVICE = 0x00000020,
@@ -108,6 +111,7 @@ extern int optreset;
static const char scsicmd_opts[] = "c:i:o:";
static const char readdefect_opts[] = "f:GP";
+static const char negotiate_opts[] = "acD:O:qR:T:UW:";
struct camcontrol_opts option_table[] = {
{"tur", CAM_ARG_TUR, NULL},
@@ -124,6 +128,9 @@ struct camcontrol_opts option_table[] = {
{"devlist", CAM_ARG_DEVTREE, NULL},
{"periphlist", CAM_ARG_DEVLIST, NULL},
{"modepage", CAM_ARG_MODE_PAGE, "dem:P:"},
+ {"tags", CAM_ARG_TAG, "N:q"},
+ {"negotiate", CAM_ARG_RATE, negotiate_opts},
+ {"rate", CAM_ARG_RATE, negotiate_opts},
{"debug", CAM_ARG_DEBUG, "ITSc"},
{"help", CAM_ARG_USAGE, NULL},
{"-?", CAM_ARG_USAGE, NULL},
@@ -144,7 +151,7 @@ camcontrol_optret getoption(char *arg, cam_argmask *argnum, char **subopt);
static int getdevlist(struct cam_device *device);
static int getdevtree(void);
static int testunitready(struct cam_device *device, int retry_count,
- int timeout);
+ int timeout, int quiet);
static int scsistart(struct cam_device *device, int startstop, int loadeject,
int retry_count, int timeout);
static int scsidoinquiry(struct cam_device *device, int argc, char **argv,
@@ -161,6 +168,16 @@ static void modepage(struct cam_device *device, int argc, char **argv,
char *combinedopt, int retry_count, int timeout);
static int scsicmd(struct cam_device *device, int argc, char **argv,
char *combinedopt, int retry_count, int timeout);
+static int tagcontrol(struct cam_device *device, int argc, char **argv,
+ char *combinedopt);
+static void cts_print(struct cam_device *device,
+ struct ccb_trans_settings *cts);
+static void cpi_print(struct ccb_pathinq *cpi);
+static int get_cpi(struct cam_device *device, struct ccb_pathinq *cpi);
+static int get_print_cts(struct cam_device *device, int user_settings,
+ int quiet, struct ccb_trans_settings *cts);
+static int ratecontrol(struct cam_device *device, int retry_count,
+ int timeout, int argc, char **argv, char *combinedopt);
camcontrol_optret
getoption(char *arg, cam_argmask *argnum, char **subopt)
@@ -250,13 +267,15 @@ getdevtree(void)
int bufsize, i, fd;
int need_close = 0;
int error = 0;
+ int skip_device = 0;
if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
warn("couldn't open %s", XPT_DEVICE);
return(1);
}
- bzero(&(&ccb.ccb_h)[1], sizeof(struct ccb_dev_match));
+ bzero(&(&ccb.ccb_h)[1],
+ sizeof(struct ccb_dev_match) - sizeof(struct ccb_hdr));
ccb.ccb_h.func_code = XPT_DEV_MATCH;
bufsize = sizeof(struct dev_match_result) * 100;
@@ -326,6 +345,14 @@ getdevtree(void)
dev_result =
&ccb.cdm.matches[i].result.device_result;
+ if ((dev_result->flags
+ & DEV_RESULT_UNCONFIGURED)
+ && ((arglist & CAM_ARG_VERBOSE) == 0)) {
+ skip_device = 1;
+ break;
+ } else
+ skip_device = 0;
+
cam_strvis(vendor, dev_result->inq_data.vendor,
sizeof(dev_result->inq_data.vendor),
sizeof(vendor));
@@ -361,6 +388,9 @@ getdevtree(void)
periph_result =
&ccb.cdm.matches[i].result.periph_result;
+ if (skip_device != 0)
+ break;
+
if (need_close > 1)
fprintf(stdout, ",");
@@ -389,7 +419,8 @@ getdevtree(void)
}
static int
-testunitready(struct cam_device *device, int retry_count, int timeout)
+testunitready(struct cam_device *device, int retry_count, int timeout,
+ int quiet)
{
int error = 0;
union ccb *ccb;
@@ -410,7 +441,8 @@ testunitready(struct cam_device *device, int retry_count, int timeout)
ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
if (cam_send_ccb(device, ccb) < 0) {
- perror("error sending test unit ready");
+ if (quiet == 0)
+ perror("error sending test unit ready");
if (arglist & CAM_ARG_VERBOSE) {
if ((ccb->ccb_h.status & CAM_STATUS_MASK) ==
@@ -425,10 +457,12 @@ testunitready(struct cam_device *device, int retry_count, int timeout)
return(1);
}
- if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
- fprintf(stdout, "Unit is ready\n");
- else {
- fprintf(stdout, "Unit is not ready\n");
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
+ if (quiet == 0)
+ fprintf(stdout, "Unit is ready\n");
+ } else {
+ if (quiet == 0)
+ fprintf(stdout, "Unit is not ready\n");
error = 1;
if (arglist & CAM_ARG_VERBOSE) {
@@ -595,7 +629,8 @@ scsiinquiry(struct cam_device *device, int retry_count, int timeout)
}
/* cam_getccb cleans up the header, caller has to zero the payload */
- bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_scsiio));
+ bzero(&(&ccb->ccb_h)[1],
+ sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
inq_buf = (struct scsi_inquiry_data *)malloc(
sizeof(struct scsi_inquiry_data));
@@ -660,13 +695,12 @@ scsiinquiry(struct cam_device *device, int retry_count, int timeout)
return(error);
}
+ fprintf(stdout, "%s%d: ", device->device_name,
+ device->dev_unit_num);
scsi_print_inquiry(inq_buf);
free(inq_buf);
- if (arglist & CAM_ARG_GET_SERIAL)
- fprintf(stdout, "Serial Number ");
-
return(0);
}
@@ -686,7 +720,8 @@ scsiserial(struct cam_device *device, int retry_count, int timeout)
}
/* cam_getccb cleans up the header, caller has to zero the payload */
- bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_scsiio));
+ bzero(&(&ccb->ccb_h)[1],
+ sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
serial_buf = (struct scsi_vpd_unit_serial_number *)
malloc(sizeof(*serial_buf));
@@ -754,9 +789,10 @@ scsiserial(struct cam_device *device, int retry_count, int timeout)
bcopy(serial_buf->serial_num, serial_num, serial_buf->length);
serial_num[serial_buf->length] = '\0';
- if (((arglist & CAM_ARG_GET_STDINQ) == 0)
- && (arglist & CAM_ARG_GET_XFERRATE))
- fprintf(stdout, "Serial Number ");
+ if ((arglist & CAM_ARG_GET_STDINQ)
+ || (arglist & CAM_ARG_GET_XFERRATE))
+ fprintf(stdout, "%s%d: Serial Number ",
+ device->device_name, device->dev_unit_num);
fprintf(stdout, "%.60s\n", serial_num);
@@ -770,35 +806,106 @@ scsixferrate(struct cam_device *device)
{
u_int32_t freq;
u_int32_t speed;
+ union ccb *ccb;
+ u_int mb;
+ int retval = 0;
+
+ ccb = cam_getccb(device);
+
+ if (ccb == NULL) {
+ warnx("couldn't allocate CCB");
+ return(1);
+ }
+
+ bzero(&(&ccb->ccb_h)[1],
+ sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
+
+ ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
+ ccb->cts.flags = CCB_TRANS_CURRENT_SETTINGS;
+
+ if (((retval = cam_send_ccb(device, ccb)) < 0)
+ || ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP)) {
+ char *error_string = "error getting transfer settings";
+
+ if (retval < 0)
+ warn(error_string);
+ else
+ warnx(error_string);
+
+ /*
+ * If there is an error, it won't be a SCSI error since
+ * this isn't a SCSI CCB.
+ */
+ if (arglist & CAM_ARG_VERBOSE)
+ fprintf(stderr, "CAM status is %#x\n",
+ ccb->ccb_h.status);
+
+ retval = 1;
+
+ goto xferrate_bailout;
+
+ }
+
+ if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
+ && (ccb->cts.sync_offset != 0)) {
+ freq = scsi_calc_syncsrate(ccb->cts.sync_period);
+ speed = freq;
+ } else {
+ struct ccb_pathinq cpi;
+
+ retval = get_cpi(device, &cpi);
+
+ if (retval != 0)
+ goto xferrate_bailout;
- if (device->sync_period != 0)
- freq = scsi_calc_syncsrate(device->sync_period);
- else
+ speed = cpi.base_transfer_speed;
freq = 0;
+ }
+
+ fprintf(stdout, "%s%d: ", device->device_name,
+ device->dev_unit_num);
+
+ if ((ccb->cts.valid & CCB_TRANS_BUS_WIDTH_VALID) != 0)
+ speed *= (0x01 << device->bus_width);
+
+ mb = speed / 1000;
+
+ if (mb > 0)
+ fprintf(stdout, "%d.%03dMB/s transfers ",
+ mb, speed % 1000);
+ else
+ fprintf(stdout, "%dKB/s transfers ",
+ (speed % 1000) * 1000);
+
+ if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
+ && (ccb->cts.sync_offset != 0))
+ fprintf(stdout, "(%d.%03dMHz, offset %d", freq / 1000,
+ freq % 1000, ccb->cts.sync_offset);
+
+ if (((ccb->cts.valid & CCB_TRANS_BUS_WIDTH_VALID) != 0)
+ && (ccb->cts.bus_width > 0)) {
+ if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
+ && (ccb->cts.sync_offset != 0)) {
+ fprintf(stdout, ", ");
+ } else {
+ fprintf(stdout, " (");
+ }
+ fprintf(stdout, "%dbit)", 8 * (0x01 << ccb->cts.bus_width));
+ } else if (((ccb->cts.valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
+ && (ccb->cts.sync_offset != 0)) {
+ fprintf(stdout, ")");
+ }
- speed = freq;
- speed *= (0x01 << device->bus_width);
- fprintf(stdout, "%d.%dMB/s transfers ", speed / 1000, speed % 1000);
-
- if (device->sync_period != 0)
- fprintf(stdout, "(%d.%dMHz, offset %d", freq / 1000,
- freq % 1000, device->sync_offset);
-
- if (device->bus_width != 0) {
- if (device->sync_period == 0)
- fprintf(stdout, "(");
- else
- fprintf(stdout, ", ");
- fprintf(stdout, "%dbit)", 8 * (0x01 << device->bus_width));
- } else if (device->sync_period != 0)
- fprintf(stdout, ")");
-
if (device->inq_data.flags & SID_CmdQue)
fprintf(stdout, ", Tagged Queueing Enabled");
fprintf(stdout, "\n");
- return(0);
+xferrate_bailout:
+
+ cam_freeccb(ccb);
+
+ return(retval);
}
static int
@@ -1030,7 +1137,8 @@ readdefects(struct cam_device *device, int argc, char **argv,
* cam_getccb() zeros the CCB header only. So we need to zero the
* payload portion of the ccb.
*/
- bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_scsiio));
+ bzero(&(&ccb->ccb_h)[1],
+ sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
cam_fill_csio(&ccb->csio,
/*retries*/ retry_count,
@@ -1270,7 +1378,8 @@ mode_sense(struct cam_device *device, int mode_page, int page_control,
if (ccb == NULL)
errx(1, "mode_sense: couldn't allocate CCB");
- bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_scsiio));
+ bzero(&(&ccb->ccb_h)[1],
+ sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
scsi_mode_sense(&ccb->csio,
/* retries */ retry_count,
@@ -1323,7 +1432,8 @@ mode_select(struct cam_device *device, int save_pages, int retry_count,
if (ccb == NULL)
errx(1, "mode_select: couldn't allocate CCB");
- bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_scsiio));
+ bzero(&(&ccb->ccb_h)[1],
+ sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
scsi_mode_select(&ccb->csio,
/* retries */ retry_count,
@@ -1426,7 +1536,8 @@ scsicmd(struct cam_device *device, int argc, char **argv, char *combinedopt,
return(1);
}
- bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_scsiio));
+ bzero(&(&ccb->ccb_h)[1],
+ sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
while ((c = getopt(argc, argv, combinedopt)) != -1) {
switch(c) {
@@ -1784,6 +1895,685 @@ camdebug(int argc, char **argv, char *combinedopt)
return(error);
}
+static int
+tagcontrol(struct cam_device *device, int argc, char **argv,
+ char *combinedopt)
+{
+ int c;
+ union ccb *ccb;
+ int numtags = -1;
+ int retval = 0;
+ int quiet = 0;
+ char pathstr[1024];
+
+ ccb = cam_getccb(device);
+
+ if (ccb == NULL) {
+ warnx("tagcontrol: error allocating ccb");
+ return(1);
+ }
+
+ while ((c = getopt(argc, argv, combinedopt)) != -1) {
+ switch(c) {
+ case 'N':
+ numtags = strtol(optarg, NULL, 0);
+ if (numtags < 0) {
+ warnx("tag count %d is < 0", numtags);
+ retval = 1;
+ goto tagcontrol_bailout;
+ }
+ break;
+ case 'q':
+ quiet++;
+ break;
+ default:
+ break;
+ }
+ }
+
+ cam_path_string(device, pathstr, sizeof(pathstr));
+
+ if (numtags >= 0) {
+ bzero(&(&ccb->ccb_h)[1],
+ sizeof(struct ccb_relsim) - sizeof(struct ccb_hdr));
+ ccb->ccb_h.func_code = XPT_REL_SIMQ;
+ ccb->crs.release_flags = RELSIM_ADJUST_OPENINGS;
+ ccb->crs.openings = numtags;
+
+
+ if (cam_send_ccb(device, ccb) < 0) {
+ perror("error sending XPT_REL_SIMQ CCB");
+ retval = 1;
+ goto tagcontrol_bailout;
+ }
+
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ warnx("XPT_REL_SIMQ CCB failed, status %#x",
+ ccb->ccb_h.status);
+ retval = 1;
+ goto tagcontrol_bailout;
+ }
+
+
+ if (quiet == 0)
+ fprintf(stdout, "%stagged openings now %d\n",
+ pathstr, ccb->crs.openings);
+ }
+
+ bzero(&(&ccb->ccb_h)[1],
+ sizeof(struct ccb_getdev) - sizeof(struct ccb_hdr));
+
+ ccb->ccb_h.func_code = XPT_GDEV_TYPE;
+
+ if (cam_send_ccb(device, ccb) < 0) {
+ perror("error sending XPT_GDEV_TYPE CCB");
+ retval = 1;
+ goto tagcontrol_bailout;
+ }
+
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ warnx("XPT_GDEV_TYPE CCB failed, status %#x",
+ ccb->ccb_h.status);
+ retval = 1;
+ goto tagcontrol_bailout;
+ }
+
+ if (arglist & CAM_ARG_VERBOSE) {
+ fprintf(stdout, "%s", pathstr);
+ fprintf(stdout, "dev_openings %d\n", ccb->cgd.dev_openings);
+ fprintf(stdout, "%s", pathstr);
+ fprintf(stdout, "dev_active %d\n", ccb->cgd.dev_active);
+ fprintf(stdout, "%s", pathstr);
+ fprintf(stdout, "devq_openings %d\n", ccb->cgd.devq_openings);
+ fprintf(stdout, "%s", pathstr);
+ fprintf(stdout, "devq_queued %d\n", ccb->cgd.devq_queued);
+ fprintf(stdout, "%s", pathstr);
+ fprintf(stdout, "held %d\n", ccb->cgd.held);
+ fprintf(stdout, "%s", pathstr);
+ fprintf(stdout, "mintags %d\n", ccb->cgd.mintags);
+ fprintf(stdout, "%s", pathstr);
+ fprintf(stdout, "maxtags %d\n", ccb->cgd.maxtags);
+ } else {
+ if (quiet == 0) {
+ fprintf(stdout, "%s", pathstr);
+ fprintf(stdout, "device openings: ");
+ }
+ fprintf(stdout, "%d\n", ccb->cgd.dev_openings +
+ ccb->cgd.dev_active);
+ }
+
+tagcontrol_bailout:
+
+ cam_freeccb(ccb);
+ return(retval);
+}
+
+static void
+cts_print(struct cam_device *device, struct ccb_trans_settings *cts)
+{
+ char pathstr[1024];
+
+ cam_path_string(device, pathstr, sizeof(pathstr));
+
+ if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0) {
+
+ fprintf(stdout, "%ssync parameter: %d\n", pathstr,
+ cts->sync_period);
+
+ if (cts->sync_offset != 0) {
+ u_int freq;
+ u_int speed;
+
+ freq = scsi_calc_syncsrate(cts->sync_period);
+ fprintf(stdout, "%sfrequencey: %d.%03dMHz\n", pathstr,
+ freq / 1000, freq % 1000);
+ }
+ }
+
+ if (cts->valid & CCB_TRANS_SYNC_OFFSET_VALID)
+ fprintf(stdout, "%soffset: %d\n", pathstr, cts->sync_offset);
+
+ if (cts->valid & CCB_TRANS_BUS_WIDTH_VALID)
+ fprintf(stdout, "%sbus width: %d bits\n", pathstr,
+ (0x01 << cts->bus_width) * 8);
+
+ if (cts->valid & CCB_TRANS_DISC_VALID)
+ fprintf(stdout, "%sdisconnection is %s\n", pathstr,
+ (cts->flags & CCB_TRANS_DISC_ENB) ? "enabled" :
+ "disabled");
+
+ if (cts->valid & CCB_TRANS_TQ_VALID)
+ fprintf(stdout, "%stagged queueing is %s\n", pathstr,
+ (cts->flags & CCB_TRANS_TAG_ENB) ? "enabled" :
+ "disabled");
+
+}
+
+/*
+ * Get a path inquiry CCB for the specified device.
+ */
+static int
+get_cpi(struct cam_device *device, struct ccb_pathinq *cpi)
+{
+ union ccb *ccb;
+ int retval = 0;
+
+ ccb = cam_getccb(device);
+
+ if (ccb == NULL) {
+ warnx("get_cpi: couldn't allocate CCB");
+ return(1);
+ }
+
+ bzero(&(&ccb->ccb_h)[1],
+ sizeof(struct ccb_pathinq) - sizeof(struct ccb_hdr));
+
+ ccb->ccb_h.func_code = XPT_PATH_INQ;
+
+ if (cam_send_ccb(device, ccb) < 0) {
+ warn("get_cpi: error sending Path Inquiry CCB");
+
+ if (arglist & CAM_ARG_VERBOSE)
+ fprintf(stderr, "CAM status is %#x\n",
+ ccb->ccb_h.status);
+
+ retval = 1;
+
+ goto get_cpi_bailout;
+ }
+
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+
+ if (arglist & CAM_ARG_VERBOSE)
+ fprintf(stderr, "get_cpi: CAM status is %#x\n",
+ ccb->ccb_h.status);
+
+ retval = 1;
+
+ goto get_cpi_bailout;
+ }
+
+ bcopy(&ccb->cpi, cpi, sizeof(struct ccb_pathinq));
+
+get_cpi_bailout:
+
+ cam_freeccb(ccb);
+
+ return(retval);
+}
+
+static void
+cpi_print(struct ccb_pathinq *cpi)
+{
+ char adapter_str[1024];
+ int i;
+
+ snprintf(adapter_str, sizeof(adapter_str),
+ "%s%d:", cpi->dev_name, cpi->unit_number);
+
+ fprintf(stdout, "%s SIM/HBA version: %d\n", adapter_str,
+ cpi->version_num);
+
+ for (i = 1; i < 0xff; i = i << 1) {
+ char *str;
+
+ if ((i & cpi->hba_inquiry) == 0)
+ continue;
+
+ fprintf(stdout, "%s supports ", adapter_str);
+
+ switch(i) {
+ case PI_MDP_ABLE:
+ str = "MDP message";
+ break;
+ case PI_WIDE_32:
+ str = "32 bit wide SCSI";
+ break;
+ case PI_WIDE_16:
+ str = "16 bit wide SCSI";
+ break;
+ case PI_SDTR_ABLE:
+ str = "SDTR message";
+ break;
+ case PI_LINKED_CDB:
+ str = "linked CDBs";
+ break;
+ case PI_TAG_ABLE:
+ str = "tag queue messages";
+ break;
+ case PI_SOFT_RST:
+ str = "soft reset alternative";
+ break;
+ }
+ fprintf(stdout, "%s\n", str);
+ }
+
+ for (i = 1; i < 0xff; i = i << 1) {
+ char *str;
+
+ if ((i & cpi->hba_misc) == 0)
+ continue;
+
+ fprintf(stdout, "%s ", adapter_str);
+
+ switch(i) {
+ case PIM_SCANHILO:
+ str = "bus scans from high ID to low ID";
+ break;
+ case PIM_NOREMOVE:
+ str = "removable devices not included in scan";
+ break;
+ case PIM_NOINITIATOR:
+ str = "initiator role not supported";
+ break;
+ case PIM_NOBUSRESET:
+ str = "user has disabled initial BUS RESET or"
+ " controller is in target/mixed mode";
+ break;
+ }
+ fprintf(stdout, "%s\n", str);
+ }
+
+ for (i = 1; i < 0xff; i = i << 1) {
+ char *str;
+
+ if ((i & cpi->target_sprt) == 0)
+ continue;
+
+ fprintf(stdout, "%s supports ", adapter_str);
+ switch(i) {
+ case PIT_PROCESSOR:
+ str = "target mode processor mode";
+ break;
+ case PIT_PHASE:
+ str = "target mode phase cog. mode";
+ break;
+ case PIT_DISCONNECT:
+ str = "disconnects in target mode";
+ break;
+ case PIT_TERM_IO:
+ str = "terminate I/O message in target mode";
+ break;
+ case PIT_GRP_6:
+ str = "group 6 commands in target mode";
+ break;
+ case PIT_GRP_7:
+ str = "group 7 commands in target mode";
+ break;
+ }
+
+ fprintf(stdout, "%s\n", str);
+ }
+ fprintf(stdout, "%s HBA engine count: %d\n", adapter_str,
+ cpi->hba_eng_cnt);
+ fprintf(stdout, "%s maxium target: %d\n", adapter_str,
+ cpi->max_target);
+ fprintf(stdout, "%s maxium LUN: %d\n", adapter_str,
+ cpi->max_lun);
+ fprintf(stdout, "%s highest path ID in subsystem: %d\n",
+ adapter_str, cpi->hpath_id);
+ fprintf(stdout, "%s SIM vendor: %s\n", adapter_str, cpi->sim_vid);
+ fprintf(stdout, "%s HBA vendor: %s\n", adapter_str, cpi->hba_vid);
+ fprintf(stdout, "%s bus ID: %d\n", adapter_str, cpi->bus_id);
+ fprintf(stdout, "%s base transfer speed: ", adapter_str);
+ if (cpi->base_transfer_speed > 1000)
+ fprintf(stdout, "%d.%03dMB/sec\n",
+ cpi->base_transfer_speed / 1000,
+ cpi->base_transfer_speed % 1000);
+ else
+ fprintf(stdout, "%dKB/sec\n",
+ (cpi->base_transfer_speed % 1000) * 1000);
+}
+
+static int
+get_print_cts(struct cam_device *device, int user_settings, int quiet,
+ struct ccb_trans_settings *cts)
+{
+ int retval;
+ union ccb *ccb;
+
+ retval = 0;
+ ccb = cam_getccb(device);
+
+ if (ccb == NULL) {
+ warnx("get_print_cts: error allocating ccb");
+ return(1);
+ }
+
+ bzero(&(&ccb->ccb_h)[1],
+ sizeof(struct ccb_trans_settings) - sizeof(struct ccb_hdr));
+
+ ccb->ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
+
+ if (user_settings == 0)
+ ccb->cts.flags = CCB_TRANS_CURRENT_SETTINGS;
+ else
+ ccb->cts.flags = CCB_TRANS_USER_SETTINGS;
+
+ if (cam_send_ccb(device, ccb) < 0) {
+ perror("error sending XPT_GET_TRAN_SETTINGS CCB");
+ retval = 1;
+ goto get_print_cts_bailout;
+ }
+
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ warnx("XPT_GET_TRANS_SETTINGS CCB failed, status %#x",
+ ccb->ccb_h.status);
+ retval = 1;
+ goto get_print_cts_bailout;
+ }
+
+ if (quiet == 0)
+ cts_print(device, &ccb->cts);
+
+ if (cts != NULL)
+ bcopy(&ccb->cts, cts, sizeof(struct ccb_trans_settings));
+
+get_print_cts_bailout:
+
+ cam_freeccb(ccb);
+
+ return(retval);
+}
+
+static int
+ratecontrol(struct cam_device *device, int retry_count, int timeout,
+ int argc, char **argv, char *combinedopt)
+{
+ int c;
+ union ccb *ccb;
+ int user_settings = 0;
+ int retval = 0;
+ int disc_enable = -1, tag_enable = -1;
+ int offset = -1;
+ double syncrate = -1;
+ int bus_width = -1;
+ int quiet = 0;
+ int change_settings = 0, send_tur = 0;
+ 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':
+ send_tur = 1;
+ break;
+ case 'c':
+ user_settings = 0;
+ break;
+ case 'D':
+ if (strncasecmp(optarg, "enable", 6) == 0)
+ disc_enable = 1;
+ else if (strncasecmp(optarg, "disable", 7) == 0)
+ disc_enable = 0;
+ else {
+ warnx("-D argument \"%s\" is unknown", optarg);
+ retval = 1;
+ goto ratecontrol_bailout;
+ }
+ change_settings = 1;
+ break;
+ case 'O':
+ offset = strtol(optarg, NULL, 0);
+ if (offset < 0) {
+ warnx("offset value %d is < 0", offset);
+ retval = 1;
+ goto ratecontrol_bailout;
+ }
+ change_settings = 1;
+ break;
+ case 'q':
+ quiet++;
+ break;
+ case 'R':
+ syncrate = atof(optarg);
+
+ if (syncrate < 0) {
+ warnx("sync rate %f is < 0", syncrate);
+ retval = 1;
+ goto ratecontrol_bailout;
+ }
+ change_settings = 1;
+ break;
+ case 'T':
+ if (strncasecmp(optarg, "enable", 6) == 0)
+ tag_enable = 1;
+ else if (strncasecmp(optarg, "disable", 7) == 0)
+ tag_enable = 0;
+ else {
+ warnx("-T argument \"%s\" is unknown", optarg);
+ retval = 1;
+ goto ratecontrol_bailout;
+ }
+ change_settings = 1;
+ break;
+ case 'U':
+ user_settings = 1;
+ break;
+ case 'W':
+ bus_width = strtol(optarg, NULL, 0);
+ if (bus_width < 0) {
+ warnx("bus width %d is < 0", bus_width);
+ retval = 1;
+ goto ratecontrol_bailout;
+ }
+ change_settings = 1;
+ break;
+ default:
+ 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");
+ retval = 1;
+ goto ratecontrol_bailout;
+ }
+
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ warnx("XPT_PATH_INQ CCB failed, status %#x",
+ ccb->ccb_h.status);
+ 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");
+
+ retval = get_print_cts(device, user_settings, quiet, &ccb->cts);
+
+ if (retval != 0)
+ goto ratecontrol_bailout;
+
+ if (arglist & CAM_ARG_VERBOSE)
+ cpi_print(&cpi);
+
+ if (change_settings) {
+ if (disc_enable != -1) {
+ ccb->cts.valid |= CCB_TRANS_DISC_VALID;
+ if (disc_enable == 0)
+ ccb->cts.flags &= ~CCB_TRANS_DISC_ENB;
+ else
+ ccb->cts.flags |= CCB_TRANS_DISC_ENB;
+ } else
+ ccb->cts.valid &= ~CCB_TRANS_DISC_VALID;
+
+ if (tag_enable != -1) {
+ if ((cpi.hba_inquiry & PI_TAG_ABLE) == 0) {
+ warnx("HBA does not support tagged queueing, "
+ "so you cannot modify tag settings");
+ retval = 1;
+ goto ratecontrol_bailout;
+ }
+
+ ccb->cts.valid |= CCB_TRANS_TQ_VALID;
+
+ if (tag_enable == 0)
+ ccb->cts.flags &= ~CCB_TRANS_TAG_ENB;
+ else
+ ccb->cts.flags |= CCB_TRANS_TAG_ENB;
+ } else
+ ccb->cts.valid &= ~CCB_TRANS_TQ_VALID;
+
+ if (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);
+ retval = 1;
+ goto ratecontrol_bailout;
+ }
+ ccb->cts.valid |= CCB_TRANS_SYNC_OFFSET_VALID;
+ ccb->cts.sync_offset = offset;
+ } else
+ ccb->cts.valid &= ~CCB_TRANS_SYNC_OFFSET_VALID;
+
+ if (syncrate != -1) {
+ int num_syncrates;
+ int prelim_sync_period;
+ int period_factor_set = 0;
+ u_int freq;
+ int i;
+
+ 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);
+ retval = 1;
+ goto ratecontrol_bailout;
+ }
+
+ ccb->cts.valid |= CCB_TRANS_SYNC_RATE_VALID;
+
+ /*
+ * 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.
+ */
+ if (syncrate == 0)
+ prelim_sync_period = 0;
+ else
+ prelim_sync_period = 10000000 / syncrate;
+
+ ccb->cts.sync_period =
+ scsi_calc_syncparam(prelim_sync_period);
+
+ freq = scsi_calc_syncsrate(ccb->cts.sync_period);
+ } else
+ ccb->cts.valid &= ~CCB_TRANS_SYNC_RATE_VALID;
+
+ /*
+ * The bus_width argument goes like this:
+ * 0 == 8 bit
+ * 1 == 16 bit
+ * 2 == 32 bit
+ * Therefore, if you shift the number of bits given on the
+ * command line right by 4, you should get the correct
+ * number.
+ */
+ if (bus_width != -1) {
+
+ /*
+ * We might as well validate things here with a
+ * decipherable error message, rather than what
+ * will probably be an indecipherable error message
+ * by the time it gets back to us.
+ */
+ if ((bus_width == 16)
+ && ((cpi.hba_inquiry & PI_WIDE_16) == 0)) {
+ warnx("HBA does not support 16 bit bus width");
+ retval = 1;
+ goto ratecontrol_bailout;
+ } else if ((bus_width == 32)
+ && ((cpi.hba_inquiry & PI_WIDE_32) == 0)) {
+ warnx("HBA does not support 32 bit bus width");
+ retval = 1;
+ goto ratecontrol_bailout;
+ } else if (bus_width != 8) {
+ warnx("Invalid bus width %d", bus_width);
+ retval = 1;
+ goto ratecontrol_bailout;
+ }
+
+ ccb->cts.valid |= CCB_TRANS_BUS_WIDTH_VALID;
+ ccb->cts.bus_width = bus_width >> 4;
+ } else
+ ccb->cts.valid &= ~CCB_TRANS_BUS_WIDTH_VALID;
+
+ ccb->ccb_h.func_code = XPT_SET_TRAN_SETTINGS;
+
+ if (cam_send_ccb(device, ccb) < 0) {
+ perror("error sending XPT_SET_TRAN_SETTINGS CCB");
+ retval = 1;
+ goto ratecontrol_bailout;
+ }
+
+ if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
+ warnx("XPT_SET_TRANS_SETTINGS CCB failed, status %#x",
+ ccb->ccb_h.status);
+ retval = 1;
+ 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.
+ */
+ if (retval != 0) {
+ if (quiet == 0)
+ 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
+ * to print them.
+ */
+ if (quiet != 0)
+ goto ratecontrol_bailout;
+
+ fprintf(stdout, "New Parameters:\n");
+ retval = get_print_cts(device, user_settings, 0, NULL);
+ }
+
+ratecontrol_bailout:
+
+ cam_freeccb(ccb);
+ return(retval);
+}
+
void
usage(void)
{
@@ -1803,6 +2593,10 @@ usage(void)
" camcontrol cmd [generic args] <-c cmd [args]> \n"
" [-i len fmt|-o len fmt [args]]\n"
" camcontrol debug [-I][-T][-S][-c] <all|bus[:target[:lun]]|off>\n"
+" camcontrol tags [generic args] [-N tags] [-q] [-v]\n"
+" camcontrol negotiate [generic args] [-a][-c][-D <enable|disable>]\n"
+" [-O offset][-q][-R syncrate][-v]\n"
+" [-T <enable|disable>][-U][-W bus_width]\n"
"Specify one of the following options:\n"
"devlist list all CAM devices\n"
"periphlist list all CAM peripheral drivers attached to a device\n"
@@ -1817,6 +2611,8 @@ usage(void)
"modepage display or edit (-e) the given mode page\n"
"cmd send the given scsi command, may need -i or -o as well\n"
"debug turn debugging on/off for a bus, target, or lun, or all devices\n"
+"tags report or set the number of transaction slots for a device\n"
+"negotiate report or set device negotiation parameters\n"
"Generic arguments:\n"
"-v be verbose, print out sense information\n"
"-t timeout command timeout in seconds, overrides default timeout\n"
@@ -1825,8 +2621,9 @@ usage(void)
"-E have the kernel attempt to perform SCSI error recovery\n"
"-C count specify the SCSI command retry count (needs -E to work)\n"
"modepage arguments:\n"
+"-m page specify the mode page to view or edit\n"
"-e edit the specified mode page\n"
-"-B disable block descriptors for mode sense\n"
+"-d disable block descriptors for mode sense\n"
"-P pgctl page control field 0-3\n"
"defects arguments:\n"
"-f format specify defect list format (block, bfi or phys)\n"
@@ -1844,7 +2641,22 @@ usage(void)
"-I CAM_DEBUG_INFO -- scsi commands, errors, data\n"
"-T CAM_DEBUG_TRACE -- routine flow tracking\n"
"-S CAM_DEBUG_SUBTRACE -- internal routine command flow\n"
-"-c CAM_DEBUG_CDB -- print out SCSI CDBs only\n",
+"-c CAM_DEBUG_CDB -- print out SCSI CDBs only\n"
+"tags arguments:\n"
+"-N tags specify the number of tags to use for this device\n"
+"-q be quiet, don't report the number of tags\n"
+"-v report a number of tag-related parameters\n"
+"negotiate arguments:\n"
+"-a send a test unit ready after negotiation\n"
+"-c report/set current negotiation settings\n"
+"-D <arg> \"enable\" or \"disable\" disconnection\n"
+"-O offset set command delay offset\n"
+"-q be quiet, don't report anything\n"
+"-R syncrate synchronization rate in MHz\n"
+"-T <arg> \"enable\" or \"disable\" tagged queueing\n"
+"-U report/set user negotiation settings\n"
+"-W bus_width set the bus width in bits (8, 16 or 32)\n"
+"-v also print a Path Inquiry CCB for the controller\n",
DEFAULT_DEVICE, DEFAULT_UNIT);
}
@@ -2025,7 +2837,7 @@ main(int argc, char **argv)
error = getdevtree();
break;
case CAM_ARG_TUR:
- error = testunitready(cam_dev, retry_count, timeout);
+ error = testunitready(cam_dev, retry_count, timeout, 0);
break;
case CAM_ARG_INQUIRY:
error = scsidoinquiry(cam_dev, argc, argv, combinedopt,
@@ -2057,6 +2869,13 @@ main(int argc, char **argv)
case CAM_ARG_DEBUG:
error = camdebug(argc, argv, combinedopt);
break;
+ case CAM_ARG_TAG:
+ error = tagcontrol(cam_dev, argc, argv, combinedopt);
+ break;
+ case CAM_ARG_RATE:
+ error = ratecontrol(cam_dev, retry_count, timeout,
+ argc, argv, combinedopt);
+ break;
default:
usage();
error = 1;
diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h
index 5c04dfa02634..67b5934e0c68 100644
--- a/sys/cam/cam_ccb.h
+++ b/sys/cam/cam_ccb.h
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: cam_ccb.h,v 1.3 1998/12/10 04:05:49 gibbs Exp $
+ * $Id: cam_ccb.h,v 1.4 1999/03/05 23:13:20 gibbs Exp $
*/
#ifndef _CAM_CAM_CCB_H
@@ -98,61 +98,96 @@ typedef enum {
/* XPT Opcodes for xpt_action */
typedef enum {
+/* Function code flags are bits greater than 0xff */
+ XPT_FC_QUEUED = 0x100,
+ /* Non-immediate function code */
+ XPT_FC_USER_CCB = 0x200,
+ XPT_FC_XPT_ONLY = 0x400,
+ /* Only for the transport layer device */
/* Common function commands: 0x00->0x0F */
- XPT_NOOP, /* Execute Nothing */
- XPT_SCSI_IO, /* Execute the requested I/O operation */
- XPT_GDEV_TYPE, /* Get type information for specified device */
- XPT_GDEVLIST, /* Get a list of peripheral devices */
- XPT_PATH_INQ, /* Path routing inquiry */
- XPT_REL_SIMQ, /* Release a frozen SIM queue */
- XPT_SASYNC_CB, /* Set Asynchronous Callback Parameters */
- XPT_SDEV_TYPE, /* Set device type information */
- XPT_SCAN_BUS, /* (Re)Scan the SCSI Bus */
- XPT_DEV_MATCH, /* Get EDT entries matching the given pattern */
- XPT_DEBUG, /* Turn on debugging for a bus, target or lun */
+ XPT_NOOP = 0x00,
+ /* Execute Nothing */
+ XPT_SCSI_IO = 0x01 | XPT_FC_QUEUED,
+ /* Execute the requested I/O operation */
+ XPT_GDEV_TYPE = 0x02,
+ /* Get type information for specified device */
+ XPT_GDEVLIST = 0x03,
+ /* Get a list of peripheral devices */
+ XPT_PATH_INQ = 0x04,
+ /* Path routing inquiry */
+ XPT_REL_SIMQ = 0x05,
+ /* Release a frozen SIM queue */
+ XPT_SASYNC_CB = 0x06,
+ /* Set Asynchronous Callback Parameters */
+ XPT_SDEV_TYPE = 0x07,
+ /* Set device type information */
+ XPT_SCAN_BUS = 0x08 | XPT_FC_QUEUED | XPT_FC_USER_CCB
+ | XPT_FC_XPT_ONLY,
+ /* (Re)Scan the SCSI Bus */
+ XPT_DEV_MATCH = 0x09 | XPT_FC_XPT_ONLY,
+ /* Get EDT entries matching the given pattern */
+ XPT_DEBUG = 0x0a,
+ /* Turn on debugging for a bus, target or lun */
/* SCSI Control Functions: 0x10->0x1F */
- XPT_ABORT = 0x10, /* Abort the specified CCB */
- XPT_RESET_BUS, /* Reset the specified SCSI bus */
- XPT_RESET_DEV, /* Bus Device Reset the specified SCSI device */
- XPT_TERM_IO, /* Terminate the I/O process */
- XPT_SCAN_LUN, /* Scan Logical Unit */
- XPT_GET_TRAN_SETTINGS, /*
+ XPT_ABORT = 0x10,
+ /* Abort the specified CCB */
+ XPT_RESET_BUS = 0x11 | XPT_FC_XPT_ONLY,
+ /* Reset the specified SCSI bus */
+ XPT_RESET_DEV = 0x12,
+ /* Bus Device Reset the specified SCSI device */
+ XPT_TERM_IO = 0x13,
+ /* Terminate the I/O process */
+ XPT_SCAN_LUN = 0x14 | XPT_FC_QUEUED | XPT_FC_USER_CCB
+ | XPT_FC_XPT_ONLY,
+ /* Scan Logical Unit */
+ XPT_GET_TRAN_SETTINGS = 0x15,
+ /*
* Get default/user transfer settings
* for the target
*/
- XPT_SET_TRAN_SETTINGS, /*
+ XPT_SET_TRAN_SETTINGS = 0x16,
+ /*
* Set transfer rate/width
* negotiation settings
*/
- XPT_CALC_GEOMETRY, /*
+ XPT_CALC_GEOMETRY = 0x17,
+ /*
* Calculate the geometry parameters for
* a device give the sector size and
* volume size.
*/
/* HBA engine commands 0x20->0x2F */
- XPT_ENG_INQ = 0x20, /* HBA engine feature inquiry */
- XPT_ENG_EXEC, /* HBA execute engine request */
+ XPT_ENG_INQ = 0x20 | XPT_FC_XPT_ONLY,
+ /* HBA engine feature inquiry */
+ XPT_ENG_EXEC = 0x21 | XPT_FC_QUEUED | XPT_FC_XPT_ONLY,
+ /* HBA execute engine request */
/* Target mode commands: 0x30->0x3F */
- XPT_EN_LUN = 0x30, /* Enable LUN as a target */
- XPT_TARGET_IO, /* Execute target I/O request */
- XPT_ACCEPT_TARGET_IO, /* Accept Host Target Mode CDB */
- XPT_CONT_TARGET_IO, /* Continue Host Target I/O Connection */
- XPT_IMMED_NOTIFY, /* Notify Host Target driver of event */
- XPT_NOTIFY_ACK, /* Acknowledgement of event */
+ XPT_EN_LUN = 0x30,
+ /* Enable LUN as a target */
+ XPT_TARGET_IO = 0x31 | XPT_FC_QUEUED,
+ /* Execute target I/O request */
+ XPT_ACCEPT_TARGET_IO = 0x32 | XPT_FC_QUEUED | XPT_FC_USER_CCB,
+ /* Accept Host Target Mode CDB */
+ XPT_CONT_TARGET_IO = 0x33 | XPT_FC_QUEUED,
+ /* Continue Host Target I/O Connection */
+ XPT_IMMED_NOTIFY = 0x34 | XPT_FC_QUEUED | XPT_FC_USER_CCB,
+ /* Notify Host Target driver of event */
+ XPT_NOTIFY_ACK = 0x35,
+ /* Acknowledgement of event */
/* Vendor Unique codes: 0x80->0x8F */
- XPT_VUNIQUE = 0x80
+ XPT_VUNIQUE = 0x80
} xpt_opcode;
-#define XPT_OPCODE_GROUP_MASK 0xF0
-#define XPT_OPCODE_GROUP(op) ((op) & XPT_OPCODE_GROUP_MASK)
-#define XPT_OPCODE_GROUP_COMMON 0x00
-#define XPT_OPCODE_GROUP_SCSI_CONTROL 0x10
-#define XPT_OPCODE_GROUP_HBA_ENGINE 0x20
-#define XPT_OPCODE_GROUP_TMODE 0x30
-#define XPT_OPCODE_GROUP_VENDOR_UNIQUE 0x80
+#define XPT_FC_GROUP_MASK 0xF0
+#define XPT_FC_GROUP(op) ((op) & XPT_FC_GROUP_MASK)
+#define XPT_FC_GROUP_COMMON 0x00
+#define XPT_FC_GROUP_SCSI_CONTROL 0x10
+#define XPT_FC_GROUP_HBA_ENGINE 0x20
+#define XPT_FC_GROUP_TMODE 0x30
+#define XPT_FC_GROUP_VENDOR_UNIQUE 0x80
typedef union {
LIST_ENTRY(ccb_hdr) le;
@@ -216,11 +251,11 @@ struct ccb_getdev {
* CCBs held by peripheral drivers
* for this device
*/
- u_int8_t maxtags; /*
+ int maxtags; /*
* Boundary conditions for number of
* tagged operations
*/
- u_int8_t mintags;
+ int mintags;
};
@@ -318,11 +353,17 @@ struct periph_match_result {
lun_id_t target_lun;
};
+typedef enum {
+ DEV_RESULT_NOFLAG = 0x00,
+ DEV_RESULT_UNCONFIGURED = 0x01
+} dev_result_flags;
+
struct device_match_result {
path_id_t path_id;
target_id_t target_id;
lun_id_t target_lun;
struct scsi_inquiry_data inq_data;
+ dev_result_flags flags;
};
struct bus_match_result {
@@ -396,7 +437,7 @@ struct ccb_dev_match {
/*
* Definitions for the path inquiry CCB fields.
*/
-#define CAM_VERSION 0x10 /* Hex value for current version */
+#define CAM_VERSION 0x11 /* Hex value for current version */
typedef enum {
PI_MDP_ABLE = 0x80, /* Supports MDP message */
@@ -444,6 +485,7 @@ struct ccb_pathinq {
char dev_name[DEV_IDLEN];/* Device name for SIM */
u_int32_t unit_number; /* Unit number for SIM */
u_int32_t bus_id; /* Bus ID for SIM */
+ u_int32_t base_transfer_speed;/* Base bus speed in KB/sec */
};
typedef union {
diff --git a/sys/cam/cam_sim.c b/sys/cam/cam_sim.c
index 70204411f062..feaf9ed69491 100644
--- a/sys/cam/cam_sim.c
+++ b/sys/cam/cam_sim.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: cam_sim.c,v 1.1 1998/09/15 06:33:23 gibbs Exp $
*/
#include <sys/param.h>
@@ -54,8 +54,8 @@ cam_simq_free(struct cam_devq *devq)
struct cam_sim *
cam_sim_alloc(sim_action_func sim_action, sim_poll_func sim_poll,
char *sim_name, void *softc, u_int32_t unit,
- u_int32_t max_dev_transactions,
- u_int32_t max_tagged_dev_transactions, struct cam_devq *queue)
+ int max_dev_transactions,
+ int max_tagged_dev_transactions, struct cam_devq *queue)
{
struct cam_sim *sim;
@@ -80,7 +80,6 @@ cam_sim_alloc(sim_action_func sim_action, sim_poll_func sim_poll,
sim->path_id = CAM_PATH_ANY;
sim->unit_number = unit;
sim->bus_id = 0; /* set in xpt_bus_register */
- sim->base_transfer_speed = 3300; /* asynchronous 3300 kB/sec */
sim->max_tagged_dev_openings = max_tagged_dev_transactions;
sim->max_dev_openings = max_dev_transactions;
sim->flags = 0;
@@ -100,12 +99,6 @@ cam_sim_free(struct cam_sim *sim, int free_devq)
}
void
-cam_sim_set_basexfer_speed(struct cam_sim *sim, u_int32_t base_xfer_speed)
-{
- sim->base_transfer_speed = base_xfer_speed;
-}
-
-void
cam_sim_set_path(struct cam_sim *sim, u_int32_t path_id)
{
sim->path_id = path_id;
diff --git a/sys/cam/cam_sim.h b/sys/cam/cam_sim.h
index 183bcedd8213..53e7937b8570 100644
--- a/sys/cam/cam_sim.h
+++ b/sys/cam/cam_sim.h
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: cam_sim.h,v 1.1 1998/09/15 06:33:23 gibbs Exp $
*/
#ifndef _CAM_CAM_SIM_H
@@ -56,14 +56,12 @@ struct cam_sim * cam_sim_alloc(sim_action_func sim_action,
char *sim_name,
void *softc,
u_int32_t unit,
- u_int32_t max_dev_transactions,
- u_int32_t max_tagged_dev_transactions,
+ int max_dev_transactions,
+ int max_tagged_dev_transactions,
struct cam_devq *queue);
void cam_sim_free(struct cam_sim *sim, int free_devq);
/* Optional sim attributes may be set with these. */
-void cam_sim_set_basexfer_speed(struct cam_sim *sim,
- u_int32_t base_xfer_speed);
void cam_sim_set_path(struct cam_sim *sim, u_int32_t path_id);
@@ -95,9 +93,8 @@ struct cam_sim {
u_int32_t path_id;/* The Boot device may set this to 0? */
u_int32_t unit_number;
u_int32_t bus_id;
- u_int32_t base_transfer_speed; /* in kB/s */
- u_int32_t max_tagged_dev_openings;
- u_int32_t max_dev_openings;
+ int max_tagged_dev_openings;
+ int max_dev_openings;
u_int32_t flags;
#define CAM_SIM_REL_TIMEOUT_PENDING 0x01
struct callout_handle c_handle;
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index 59c5883e1e4f..b57bdbf674f3 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: cam_xpt.c,v 1.53 1999/04/21 07:26:24 peter Exp $
+ * $Id: cam_xpt.c,v 1.54 1999/04/23 23:25:48 gibbs Exp $
*/
#include <sys/param.h>
#include <sys/systm.h>
@@ -215,8 +215,8 @@ struct xpt_quirk_entry {
u_int8_t quirks;
#define CAM_QUIRK_NOLUNS 0x01
#define CAM_QUIRK_NOSERIAL 0x02
- u_int8_t mintags;
- u_int8_t maxtags;
+ u_int mintags;
+ u_int maxtags;
};
typedef enum {
@@ -942,6 +942,7 @@ xptioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
}
/* FALLTHROUGH */
case XPT_SCAN_LUN:
+ case XPT_RESET_DEV:
case XPT_ENG_INQ: /* XXX not implemented yet */
case XPT_ENG_EXEC:
@@ -1449,8 +1450,15 @@ xpt_announce_periph(struct cam_periph *periph, char *announce_string)
freq = scsi_calc_syncsrate(cts.sync_period);
speed = freq;
} else {
+ struct ccb_pathinq cpi;
+
+ /* Ask the SIM for its base transfer speed */
+ xpt_setup_ccb(&cpi.ccb_h, path, /*priority*/1);
+ cpi.ccb_h.func_code = XPT_PATH_INQ;
+ xpt_action((union ccb *)&cpi);
+
+ speed = cpi.base_transfer_speed;
freq = 0;
- speed = path->bus->sim->base_transfer_speed;
}
if ((cts.valid & CCB_TRANS_BUS_WIDTH_VALID) != 0)
speed *= (0x01 << cts.bus_width);
@@ -2043,6 +2051,14 @@ xptedtdevicefunc(struct cam_ed *device, void *arg)
bcopy(&device->inq_data,
&cdm->matches[j].result.device_result.inq_data,
sizeof(struct scsi_inquiry_data));
+
+ /* Let the user know whether this device is unconfigured */
+ if (device->flags & CAM_DEV_UNCONFIGURED)
+ cdm->matches[j].result.device_result.flags =
+ DEV_RESULT_UNCONFIGURED;
+ else
+ cdm->matches[j].result.device_result.flags =
+ DEV_RESULT_NOFLAG;
}
/*
@@ -4348,16 +4364,7 @@ xpt_done(union ccb *done_ccb)
s = splcam();
CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE, ("xpt_done\n"));
- switch (done_ccb->ccb_h.func_code) {
- case XPT_SCSI_IO:
- case XPT_ENG_EXEC:
- case XPT_TARGET_IO:
- case XPT_ACCEPT_TARGET_IO:
- case XPT_CONT_TARGET_IO:
- case XPT_IMMED_NOTIFY:
- case XPT_SCAN_BUS:
- case XPT_SCAN_LUN:
- {
+ if ((done_ccb->ccb_h.func_code & XPT_FC_QUEUED) != 0) {
/*
* Queue up the request for handling by our SWI handler
* any of the "non-immediate" type of ccbs.
@@ -4376,10 +4383,6 @@ xpt_done(union ccb *done_ccb)
setsoftcamnet();
break;
}
- break;
- }
- default:
- break;
}
splx(s);
}
@@ -5517,6 +5520,7 @@ xpt_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device,
if (async_update == FALSE) {
struct scsi_inquiry_data *inq_data;
struct ccb_pathinq cpi;
+ struct ccb_trans_settings cur_cts;
if (device == NULL) {
cts->ccb_h.status = CAM_PATH_INVALID;
@@ -5531,8 +5535,28 @@ xpt_set_transfer_settings(struct ccb_trans_settings *cts, struct cam_ed *device,
xpt_setup_ccb(&cpi.ccb_h, cts->ccb_h.path, /*priority*/1);
cpi.ccb_h.func_code = XPT_PATH_INQ;
xpt_action((union ccb *)&cpi);
-
+ xpt_setup_ccb(&cur_cts.ccb_h, cts->ccb_h.path, /*priority*/1);
+ cur_cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS;
+ cur_cts.flags = CCB_TRANS_CURRENT_SETTINGS;
+ xpt_action((union ccb *)&cur_cts);
inq_data = &device->inq_data;
+
+ /* Fill in any gaps in what the user gave us */
+ if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) == 0)
+ cts->sync_period = cur_cts.sync_period;
+ if ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) == 0)
+ cts->sync_offset = cur_cts.sync_offset;
+ if ((cts->valid & CCB_TRANS_BUS_WIDTH_VALID) == 0)
+ cts->bus_width = cur_cts.bus_width;
+ if ((cts->valid & CCB_TRANS_DISC_VALID) == 0) {
+ cts->flags &= ~CCB_TRANS_DISC_ENB;
+ cts->flags |= cur_cts.flags & CCB_TRANS_DISC_ENB;
+ }
+ if ((cts->valid & CCB_TRANS_TQ_VALID) == 0) {
+ cts->flags &= ~CCB_TRANS_TAG_ENB;
+ cts->flags |= cur_cts.flags & CCB_TRANS_TAG_ENB;
+ }
+
if ((inq_data->flags & SID_Sync) == 0
|| (cpi.hba_inquiry & PI_SDTR_ABLE) == 0) {
/* Force async */
@@ -5911,6 +5935,7 @@ xptaction(struct cam_sim *sim, union ccb *work_ccb)
strncpy(cpi->dev_name, sim->sim_name, DEV_IDLEN);
cpi->unit_number = sim->unit_number;
cpi->bus_id = sim->bus_id;
+ cpi->base_transfer_speed = 0;
cpi->ccb_h.status = CAM_REQ_CMP;
xpt_done(work_ccb);
break;
@@ -5984,10 +6009,7 @@ camisr(cam_isrq_t *queue)
TRUE);
}
}
- if ((ccb_h->func_code != XPT_ACCEPT_TARGET_IO)
- && (ccb_h->func_code != XPT_IMMED_NOTIFY)
- && (ccb_h->func_code != XPT_SCAN_LUN)
- && (ccb_h->func_code != XPT_SCAN_BUS)) {
+ if ((ccb_h->func_code & XPT_FC_USER_CCB) == 0) {
struct cam_ed *dev;
dev = ccb_h->path->device;
diff --git a/sys/cam/scsi/scsi_cd.c b/sys/cam/scsi/scsi_cd.c
index 787abc71e4a3..dc23ab39e7c4 100644
--- a/sys/cam/scsi/scsi_cd.c
+++ b/sys/cam/scsi/scsi_cd.c
@@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: scsi_cd.c,v 1.16 1999/04/07 22:57:54 gibbs Exp $
+ * $Id: scsi_cd.c,v 1.17 1999/04/19 21:26:17 gibbs Exp $
*/
/*
* Portions of this driver taken from the original FreeBSD cd driver.
@@ -126,7 +126,7 @@ typedef enum {
struct cd_softc {
cam_pinfo pinfo;
cd_state state;
- cd_flags flags;
+ volatile cd_flags flags;
struct buf_queue_head buf_queue;
LIST_HEAD(, ccb_hdr) pending_ccbs;
struct cd_params params;
@@ -301,7 +301,7 @@ struct cdchanger {
struct cd_softc *cur_device;
struct callout_handle short_handle;
struct callout_handle long_handle;
- cd_changer_flags flags;
+ volatile cd_changer_flags flags;
STAILQ_ENTRY(cdchanger) changer_links;
STAILQ_HEAD(chdevlist, cd_softc) chluns;
};
@@ -1103,7 +1103,8 @@ cdschedule(struct cam_periph *periph, int priority)
* bootstrap things.
*/
if (((softc->changer->flags & CHANGER_TIMEOUT_SCHED)==0)
- &&((softc->changer->flags & CHANGER_NEED_TIMEOUT)==0)){
+ && ((softc->changer->flags & CHANGER_NEED_TIMEOUT)==0)
+ && ((softc->changer->flags & CHANGER_SHORT_TMOUT_SCHED)==0)){
softc->changer->flags |= CHANGER_MANUAL_CALL;
cdrunchangerqueue(softc->changer);
}
@@ -1341,7 +1342,7 @@ cdgetccb(struct cam_periph *periph, u_int32_t priority)
* This should work the first time this device is woken up,
* but just in case it doesn't, we use a while loop.
*/
- while ((((volatile cd_flags)softc->flags) & CD_FLAG_ACTIVE)==0){
+ while ((softc->flags & CD_FLAG_ACTIVE) == 0) {
/*
* If this changer isn't already queued, queue it up.
*/
@@ -1352,10 +1353,10 @@ cdgetccb(struct cam_periph *periph, u_int32_t priority)
camq_insert(&softc->changer->devq,
(cam_pinfo *)softc);
}
- if (((((volatile cd_changer_flags)softc->changer->flags)
- & CHANGER_TIMEOUT_SCHED)==0)
- &&((((volatile cd_changer_flags)softc->changer->flags)
- & CHANGER_NEED_TIMEOUT)==0)){
+ if (((softc->changer->flags & CHANGER_TIMEOUT_SCHED)==0)
+ && ((softc->changer->flags & CHANGER_NEED_TIMEOUT)==0)
+ && ((softc->changer->flags
+ & CHANGER_SHORT_TMOUT_SCHED)==0)) {
softc->changer->flags |= CHANGER_MANUAL_CALL;
cdrunchangerqueue(softc->changer);
} else
@@ -1739,18 +1740,12 @@ cddone(struct cam_periph *periph, union ccb *done_ccb)
&asc, &ascq);
}
/*
- * With CDROM devices, we expect 0x3a
- * (Medium not present) errors, since not
- * everyone leaves a CD in the drive. Some
- * broken Philips and HP WORM drives return
- * 0x04,0x00 (logical unit not ready, cause
- * not reportable), so we accept any "not
- * ready" type errors as well. If the error
- * is anything else, though, we shouldn't
- * attach.
+ * Attach to anything that claims to be a
+ * CDROM or WORM device, as long as it
+ * doesn't return a "Logical unit not
+ * supported" (0x25) error.
*/
- if ((have_sense)
- && ((asc == 0x3a) || (asc == 0x04))
+ if ((have_sense) && (asc != 0x25)
&& (error_code == SSD_CURRENT_ERROR))
snprintf(announce_buf,
sizeof(announce_buf),
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index 388939d5f7dc..b603b173f69a 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: scsi_da.c,v 1.20 1999/02/10 00:03:15 ken Exp $
+ * $Id: scsi_da.c,v 1.21 1999/03/05 23:20:20 gibbs Exp $
*/
#include "opt_hw_wdog.h"
@@ -1381,13 +1381,12 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
&asc, &ascq);
}
/*
- * With removable media devices, we expect
- * 0x3a (Medium not present) errors, since not
- * everyone leaves a disk in the drive. If
- * the error is anything else, though, we
- * shouldn't attach.
+ * Attach to anything that claims to be a
+ * direct access or optical disk device,
+ * as long as it doesn't return a "Logical
+ * unit not supported" (0x25) error.
*/
- if ((have_sense) && (asc == 0x3a)
+ if ((have_sense) && (asc != 0x25)
&& (error_code == SSD_CURRENT_ERROR))
snprintf(announce_buf,
sizeof(announce_buf),
diff --git a/sys/cam/scsi/scsi_pass.c b/sys/cam/scsi/scsi_pass.c
index 927b1b84e64e..2f5d9732eca2 100644
--- a/sys/cam/scsi/scsi_pass.c
+++ b/sys/cam/scsi/scsi_pass.c
@@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: scsi_pass.c,v 1.5 1998/11/22 23:44:47 ken Exp $
+ * $Id: scsi_pass.c,v 1.6 1999/02/10 00:03:15 ken Exp $
*/
#include <sys/param.h>
@@ -703,13 +703,55 @@ passioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
{
union ccb *inccb;
union ccb *ccb;
+ int ccb_malloced;
inccb = (union ccb *)addr;
- ccb = cam_periph_getccb(periph, inccb->ccb_h.pinfo.priority);
+
+ /*
+ * Some CCB types, like scan bus and scan lun can only go
+ * through the transport layer device.
+ */
+ if (inccb->ccb_h.func_code & XPT_FC_XPT_ONLY) {
+ xpt_print_path(periph->path);
+ printf("CCB function code %#x is restricted to the "
+ "XPT device\n", inccb->ccb_h.func_code);
+ error = ENODEV;
+ break;
+ }
+
+ /*
+ * Non-immediate CCBs need a CCB from the per-device pool
+ * of CCBs, which is scheduled by the transport layer.
+ * Immediate CCBs and user-supplied CCBs should just be
+ * malloced.
+ */
+ if ((inccb->ccb_h.func_code & XPT_FC_QUEUED)
+ && ((inccb->ccb_h.func_code & XPT_FC_USER_CCB) == 0)) {
+ ccb = cam_periph_getccb(periph,
+ inccb->ccb_h.pinfo.priority);
+ ccb_malloced = 0;
+ } else {
+ ccb = xpt_alloc_ccb();
+
+ if (ccb != NULL)
+ xpt_setup_ccb(&ccb->ccb_h, periph->path,
+ inccb->ccb_h.pinfo.priority);
+ ccb_malloced = 1;
+ }
+
+ if (ccb == NULL) {
+ xpt_print_path(periph->path);
+ printf("unable to allocate CCB\n");
+ error = ENOMEM;
+ break;
+ }
error = passsendccb(periph, ccb, inccb);
- xpt_release_ccb(ccb);
+ if (ccb_malloced)
+ xpt_free_ccb(ccb);
+ else
+ xpt_release_ccb(ccb);
break;
}
diff --git a/sys/cam/scsi/scsi_pass.h b/sys/cam/scsi/scsi_pass.h
index 501598bf5ff9..12ad2e207c8f 100644
--- a/sys/cam/scsi/scsi_pass.h
+++ b/sys/cam/scsi/scsi_pass.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997 Kenneth D. Merry.
+ * Copyright (c) 1997, 1999 Kenneth D. Merry.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -22,7 +22,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: scsi_pass.h,v 1.1 1998/09/15 06:36:34 gibbs Exp $
*/
#ifndef _SCSI_PASS_H
@@ -32,7 +32,7 @@
#include <cam/cam_ccb.h>
-#define CAMIOCOMMAND _IOWR('Q', 2, union ccb)
-#define CAMGETPASSTHRU _IOWR('Q', 3, union ccb)
+#define CAMIOCOMMAND _IOWR(CAM_VERSION, 2, union ccb)
+#define CAMGETPASSTHRU _IOWR(CAM_VERSION, 3, union ccb)
#endif
diff --git a/sys/dev/advansys/advansys.c b/sys/dev/advansys/advansys.c
index 0071950ff9be..ee3f887473f0 100644
--- a/sys/dev/advansys/advansys.c
+++ b/sys/dev/advansys/advansys.c
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: advansys.c,v 1.8 1999/04/07 22:59:12 gibbs Exp $
+ * $Id: advansys.c,v 1.9 1999/04/19 21:27:35 gibbs Exp $
*/
/*
* Ported from:
@@ -237,18 +237,30 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
{
struct ccb_trans_settings *cts;
target_bit_vector targ_mask;
- struct adv_target_transinfo *tconf;
+ struct adv_transinfo *tconf;
u_int update_type;
int s;
cts = &ccb->cts;
targ_mask = ADV_TID_TO_TARGET_MASK(cts->ccb_h.target_id);
- tconf = &adv->tinfo[cts->ccb_h.target_id];
update_type = 0;
- if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0)
+
+ /*
+ * The user must specify which type of settings he wishes
+ * to change.
+ */
+ if (((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0)
+ && ((cts->flags & CCB_TRANS_USER_SETTINGS) == 0)) {
+ tconf = &adv->tinfo[cts->ccb_h.target_id].current;
update_type |= ADV_TRANS_GOAL;
- if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0)
+ } else if (((cts->flags & CCB_TRANS_USER_SETTINGS) != 0)
+ && ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) == 0)) {
+ tconf = &adv->tinfo[cts->ccb_h.target_id].user;
update_type |= ADV_TRANS_USER;
+ } else {
+ ccb->ccb_h.status = CAM_REQ_INVALID;
+ break;
+ }
s = splcam();
@@ -286,9 +298,26 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
}
}
- if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0) {
+ /*
+ * If the user specifies either the sync rate, or offset,
+ * but not both, the unspecified parameter defaults to its
+ * current value in transfer negotiations.
+ */
+ if (((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0)
+ || ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)) {
+ /*
+ * If the user provided a sync rate but no offset,
+ * use the current offset.
+ */
if ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) == 0)
- cts->sync_offset = 0;
+ cts->sync_offset = tconf->offset;
+
+ /*
+ * If the user provided an offset but no sync rate,
+ * use the current sync rate.
+ */
+ if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) == 0)
+ cts->sync_period = tconf->period;
adv_period_offset_to_sdtr(adv, &cts->sync_period,
&cts->sync_offset,
@@ -298,6 +327,7 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
cts->ccb_h.target_id, cts->sync_period,
cts->sync_offset, update_type);
}
+
splx(s);
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
@@ -402,6 +432,7 @@ adv_action(struct cam_sim *sim, union ccb *ccb)
cpi->max_lun = 7;
cpi->initiator_id = adv->scsi_id;
cpi->bus_id = cam_sim_bus(sim);
+ cpi->base_transfer_speed = 3300;
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
strncpy(cpi->hba_vid, "Advansys", HBA_IDLEN);
strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
diff --git a/sys/dev/advansys/advlib.c b/sys/dev/advansys/advlib.c
index 66640c84dd89..568bf9112f0b 100644
--- a/sys/dev/advansys/advlib.c
+++ b/sys/dev/advansys/advlib.c
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: advlib.c,v 1.11 1999/04/11 02:55:50 eivind Exp $
+ * $Id: advlib.c,v 1.12 1999/04/19 21:27:36 gibbs Exp $
*/
/*
* Ported from:
@@ -1790,7 +1790,8 @@ adv_put_ready_queue(struct adv_softc *adv, struct adv_scsi_q *scsiq,
tid_no = ADV_TIX_TO_TID(scsiq->q2.target_ix);
tinfo = &adv->tinfo[tid_no];
- if (tinfo->current.period != tinfo->goal.period) {
+ if ((tinfo->current.period != tinfo->goal.period)
+ || (tinfo->current.offset != tinfo->goal.offset)) {
adv_msgout_sdtr(adv, tinfo->goal.period, tinfo->goal.offset);
scsiq->q1.cntl |= QC_MSG_OUT;
diff --git a/sys/dev/advansys/adwcam.c b/sys/dev/advansys/adwcam.c
index e2c39214354f..aef46128e7b5 100644
--- a/sys/dev/advansys/adwcam.c
+++ b/sys/dev/advansys/adwcam.c
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: adwcam.c,v 1.1 1998/10/07 03:20:46 gibbs Exp $
+ * $Id: adwcam.c,v 1.2 1998/10/15 23:47:14 gibbs Exp $
*/
/*
* Ported from:
@@ -595,7 +595,8 @@ adw_action(struct cam_sim *sim, union ccb *ccb)
}
}
- if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0) {
+ if (((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0)
+ || ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)) {
u_int sdtrenb_orig;
u_int sdtrenb;
u_int ultraenb_orig;
@@ -613,14 +614,18 @@ adw_action(struct cam_sim *sim, union ccb *ccb)
sdtrdone = adw_lram_read_16(adw,
ADW_MC_SDTR_DONE);
- if (cts->sync_period == 0) {
- sdtrenb &= ~target_mask;
- } else if (cts->sync_period > 12) {
- ultraenb &= ~target_mask;
- sdtrenb |= target_mask;
- } else {
- ultraenb |= target_mask;
- sdtrenb |= target_mask;
+ if ((cts->valid
+ & CCB_TRANS_SYNC_RATE_VALID) != 0) {
+
+ if (cts->sync_period == 0) {
+ sdtrenb &= ~target_mask;
+ } else if (cts->sync_period > 12) {
+ ultraenb &= ~target_mask;
+ sdtrenb |= target_mask;
+ } else {
+ ultraenb |= target_mask;
+ sdtrenb |= target_mask;
+ }
}
if ((cts->valid
@@ -786,6 +791,7 @@ adw_action(struct cam_sim *sim, union ccb *ccb)
cpi->max_lun = ADW_MAX_LUN;
cpi->initiator_id = adw->initiator_id;
cpi->bus_id = cam_sim_bus(sim);
+ cpi->base_transfer_speed = 3300;
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
strncpy(cpi->hba_vid, "AdvanSys", HBA_IDLEN);
strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
diff --git a/sys/dev/aha/aha.c b/sys/dev/aha/aha.c
index 8ab5a855ac87..f0456db7ad8d 100644
--- a/sys/dev/aha/aha.c
+++ b/sys/dev/aha/aha.c
@@ -55,7 +55,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: aha.c,v 1.20 1999/03/02 20:56:07 imp Exp $
+ * $Id: aha.c,v 1.21 1999/04/11 02:55:50 eivind Exp $
*/
#include "pnp.h"
@@ -1029,7 +1029,7 @@ ahaaction(struct cam_sim *sim, union ccb *ccb)
case XPT_SET_TRAN_SETTINGS:
{
/* XXX Implement */
- ccb->ccb_h.status = CAM_REQ_CMP;
+ ccb->ccb_h.status = CAM_PROVIDE_FAIL;
xpt_done(ccb);
break;
}
@@ -1120,6 +1120,7 @@ ahaaction(struct cam_sim *sim, union ccb *ccb)
cpi->max_lun = 7;
cpi->initiator_id = aha->scsi_id;
cpi->bus_id = cam_sim_bus(sim);
+ cpi->base_transfer_speed = 3300;
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
diff --git a/sys/dev/ahb/ahb.c b/sys/dev/ahb/ahb.c
index 4bdc6bb09e03..6e0db43941c9 100644
--- a/sys/dev/ahb/ahb.c
+++ b/sys/dev/ahb/ahb.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: ahb.c,v 1.9 1999/04/18 15:50:33 peter Exp $
+ * $Id: ahb.c,v 1.10 1999/04/23 23:29:00 gibbs Exp $
*/
#include "eisa.h"
@@ -1214,6 +1214,7 @@ ahbaction(struct cam_sim *sim, union ccb *ccb)
cpi->max_lun = 7;
cpi->initiator_id = ahb->scsi_id;
cpi->bus_id = cam_sim_bus(sim);
+ cpi->base_transfer_speed = 3300;
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
diff --git a/sys/dev/aic7xxx/aic7xxx.c b/sys/dev/aic7xxx/aic7xxx.c
index 346e4b837d37..215e0a420f50 100644
--- a/sys/dev/aic7xxx/aic7xxx.c
+++ b/sys/dev/aic7xxx/aic7xxx.c
@@ -36,7 +36,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: aic7xxx.c,v 1.23 1999/04/23 23:27:29 gibbs Exp $
+ * $Id: aic7xxx.c,v 1.24 1999/04/26 22:03:44 ken Exp $
*/
/*
* A few notes on features of the driver.
@@ -1097,6 +1097,7 @@ ahc_update_target_msg_request(struct ahc_softc *ahc,
targ_msg_req_orig = ahc->targ_msg_req;
if (tinfo->current.period != tinfo->goal.period
|| tinfo->current.width != tinfo->goal.width
+ || tinfo->current.offset != tinfo->goal.offset
|| (force
&& (tinfo->goal.period != 0
|| tinfo->goal.width != MSG_EXT_WDTR_BUS_8_BIT)))
@@ -4480,7 +4481,8 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
cts->bus_width, update_type);
}
- if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0) {
+ if (((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0)
+ || ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)) {
struct ahc_syncrate *syncrate;
u_int maxsync;
@@ -4498,6 +4500,13 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
cts->sync_offset = tinfo->goal.offset;
}
+ if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) == 0) {
+ if (update_type & AHC_TRANS_USER)
+ cts->sync_period = tinfo->user.period;
+ else
+ cts->sync_period = tinfo->goal.period;
+ }
+
syncrate = ahc_find_syncrate(ahc, &cts->sync_period,
maxsync);
ahc_validate_offset(ahc, syncrate, &cts->sync_offset,
@@ -4645,6 +4654,7 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
cpi->hba_misc |= PIM_NOBUSRESET;
}
cpi->bus_id = cam_sim_bus(sim);
+ cpi->base_transfer_speed = 3300;
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
diff --git a/sys/dev/buslogic/bt.c b/sys/dev/buslogic/bt.c
index 343ad912c3cc..23de96cac40b 100644
--- a/sys/dev/buslogic/bt.c
+++ b/sys/dev/buslogic/bt.c
@@ -29,7 +29,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: bt.c,v 1.18 1999/04/23 23:28:19 gibbs Exp $
+ * $Id: bt.c,v 1.19 1999/05/05 06:45:09 imp Exp $
*/
/*
@@ -1250,7 +1250,7 @@ btaction(struct cam_sim *sim, union ccb *ccb)
case XPT_SET_TRAN_SETTINGS:
{
/* XXX Implement */
- ccb->ccb_h.status = CAM_REQ_CMP;
+ ccb->ccb_h.status = CAM_PROVIDE_FAIL;
xpt_done(ccb);
break;
}
@@ -1354,6 +1354,7 @@ btaction(struct cam_sim *sim, union ccb *ccb)
cpi->max_lun = 7;
cpi->initiator_id = bt->scsi_id;
cpi->bus_id = cam_sim_bus(sim);
+ cpi->base_transfer_speed = 3300;
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
strncpy(cpi->hba_vid, "BusLogic", HBA_IDLEN);
strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
diff --git a/sys/dev/dpt/dpt_scsi.c b/sys/dev/dpt/dpt_scsi.c
index 47c12a51bdad..d3143df8feb1 100644
--- a/sys/dev/dpt/dpt_scsi.c
+++ b/sys/dev/dpt/dpt_scsi.c
@@ -43,7 +43,7 @@
* arrays that span controllers (Wow!).
*/
-#ident "$Id: dpt_scsi.c,v 1.21 1998/12/22 00:52:27 eivind Exp $"
+#ident "$Id: dpt_scsi.c,v 1.22 1998/12/22 20:21:12 eivind Exp $"
#define _DPT_C_
@@ -974,6 +974,7 @@ dpt_action(struct cam_sim *sim, union ccb *ccb)
cpi->max_lun = dpt->max_lun;
cpi->initiator_id = dpt->hostid[cam_sim_bus(sim)];
cpi->bus_id = cam_sim_bus(sim);
+ cpi->base_transfer_speed = 3300;
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
strncpy(cpi->hba_vid, "DPT", HBA_IDLEN);
strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
diff --git a/sys/dev/isp/isp_freebsd.c b/sys/dev/isp/isp_freebsd.c
index 2c42f81d53ff..edeb582dee7a 100644
--- a/sys/dev/isp/isp_freebsd.c
+++ b/sys/dev/isp/isp_freebsd.c
@@ -1,4 +1,4 @@
-/* $Id: isp_freebsd.c,v 1.15 1999/04/04 01:35:03 mjacob Exp $ */
+/* $Id: isp_freebsd.c,v 1.16 1999/04/04 02:22:42 mjacob Exp $ */
/* release_4_3_99 */
/*
* Platform (FreeBSD) dependent common attachment code for Qlogic adapters.
@@ -83,15 +83,6 @@ isp_attach(struct ispsoftc *isp)
csa.callback_arg = isp->isp_sim;
xpt_action((union ccb *)&csa);
- /*
- * Set base transfer capabilities for Fibre Channel.
- * Technically not correct because we don't know
- * what media we're running on top of- but we'll
- * look good if we always say 100MB/s.
- */
- if (isp->isp_type & ISP_HA_FC) {
- isp->isp_sim->base_transfer_speed = 100000;
- }
if (isp->isp_state == ISP_INITSTATE)
isp->isp_state = ISP_RUNSTATE;
}
@@ -524,6 +515,13 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
#else
cpi->max_lun = (1 << 4) - 1;
#endif
+ /*
+ * Set base transfer capabilities for Fibre Channel.
+ * Technically not correct because we don't know
+ * what media we're running on top of- but we'll
+ * look good if we always say 100MB/s.
+ */
+ cpi->base_transfer_speed = 100000;
} else {
cpi->hba_misc = 0;
cpi->initiator_id =
@@ -542,6 +540,7 @@ isp_action(struct cam_sim *sim, union ccb *ccb)
} else {
cpi->max_lun = (1 << 3) - 1;
}
+ cpi->base_transfer_speed = 3300;
}
cpi->bus_id = cam_sim_bus(sim);
diff --git a/sys/dev/ppbus/vpo.c b/sys/dev/ppbus/vpo.c
index 17b67c5f632d..046d57590ef6 100644
--- a/sys/dev/ppbus/vpo.c
+++ b/sys/dev/ppbus/vpo.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: vpo.c,v 1.10 1999/01/09 18:05:46 nsouch Exp $
+ * $Id: vpo.c,v 1.11 1999/01/10 12:04:55 nsouch Exp $
*
*/
@@ -421,6 +421,7 @@ vpo_action(struct cam_sim *sim, union ccb *ccb)
cpi->max_lun = 0;
cpi->initiator_id = VP0_INITIATOR;
cpi->bus_id = sim->bus_id;
+ cpi->base_transfer_speed = 3300;
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
strncpy(cpi->hba_vid, "Iomega", HBA_IDLEN);
strncpy(cpi->dev_name, sim->sim_name, DEV_IDLEN);
diff --git a/sys/i386/eisa/ahb.c b/sys/i386/eisa/ahb.c
index 4bdc6bb09e03..6e0db43941c9 100644
--- a/sys/i386/eisa/ahb.c
+++ b/sys/i386/eisa/ahb.c
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: ahb.c,v 1.9 1999/04/18 15:50:33 peter Exp $
+ * $Id: ahb.c,v 1.10 1999/04/23 23:29:00 gibbs Exp $
*/
#include "eisa.h"
@@ -1214,6 +1214,7 @@ ahbaction(struct cam_sim *sim, union ccb *ccb)
cpi->max_lun = 7;
cpi->initiator_id = ahb->scsi_id;
cpi->bus_id = cam_sim_bus(sim);
+ cpi->base_transfer_speed = 3300;
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
diff --git a/sys/i386/isa/bs/bs.c b/sys/i386/isa/bs/bs.c
index 1f9374640432..0fdf78b8330d 100644
--- a/sys/i386/isa/bs/bs.c
+++ b/sys/i386/isa/bs/bs.c
@@ -206,6 +206,7 @@ bs_scsi_cmd(struct cam_sim *sim, union ccb *ccb)
cpi->max_lun = 7;
cpi->initiator_id = bsc->sc_hostid;
cpi->bus_id = cam_sim_bus(sim);
+ cpi->base_transfer_speed = 3300;
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
strncpy(cpi->hba_vid, "NEC", HBA_IDLEN);
strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
diff --git a/sys/pci/ncr.c b/sys/pci/ncr.c
index a32e14ae7443..38dd843ea61d 100644
--- a/sys/pci/ncr.c
+++ b/sys/pci/ncr.c
@@ -1,6 +1,6 @@
/**************************************************************************
**
-** $Id: ncr.c,v 1.142 1999/01/27 23:45:43 dillon Exp $
+** $Id: ncr.c,v 1.143 1999/04/24 20:14:02 peter Exp $
**
** Device driver for the NCR 53C8XX PCI-SCSI-Controller Family.
**
@@ -1361,7 +1361,7 @@ static void ncr_attach (pcici_t tag, int unit);
#if !defined(lint)
static const char ident[] =
- "\n$Id: ncr.c,v 1.142 1999/01/27 23:45:43 dillon Exp $\n";
+ "\n$Id: ncr.c,v 1.143 1999/04/24 20:14:02 peter Exp $\n";
#endif
static const u_long ncr_version = NCR_VERSION * 11
@@ -4022,8 +4022,10 @@ ncr_action (struct cam_sim *sim, union ccb *ccb)
!= tp->tinfo.goal.width) {
tp->nego_cp = cp;
nego = NS_WIDE;
- } else if (tp->tinfo.current.period
- != tp->tinfo.goal.period) {
+ } else if ((tp->tinfo.current.period
+ != tp->tinfo.goal.period)
+ || (tp->tinfo.current.offset
+ != tp->tinfo.goal.offset)) {
tp->nego_cp = cp;
nego = NS_SYNC;
};
@@ -4327,10 +4329,13 @@ ncr_action (struct cam_sim *sim, union ccb *ccb)
cts->bus_width = np->maxwide;
}
- if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0) {
- if (cts->sync_period != 0
- && (cts->sync_period < np->minsync))
- cts->sync_period = np->minsync;
+ if (((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0)
+ || ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)) {
+ if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0) {
+ if (cts->sync_period != 0
+ && (cts->sync_period < np->minsync))
+ cts->sync_period = np->minsync;
+ }
if ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0) {
if (cts->sync_offset == 0)
cts->sync_period = 0;
@@ -4339,14 +4344,22 @@ ncr_action (struct cam_sim *sim, union ccb *ccb)
}
}
if ((update_type & NCR_TRANS_USER) != 0) {
- tp->tinfo.user.period = cts->sync_period;
- tp->tinfo.user.offset = cts->sync_offset;
- tp->tinfo.user.width = cts->bus_width;
+ if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0)
+ tp->tinfo.user.period = cts->sync_period;
+ if ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
+ tp->tinfo.user.offset = cts->sync_offset;
+ if ((cts->valid & CCB_TRANS_BUS_WIDTH_VALID) != 0)
+ tp->tinfo.user.width = cts->bus_width;
}
if ((update_type & NCR_TRANS_GOAL) != 0) {
- tp->tinfo.goal.period = cts->sync_period;
- tp->tinfo.goal.offset = cts->sync_offset;
- tp->tinfo.goal.width = cts->bus_width;
+ if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0)
+ tp->tinfo.goal.period = cts->sync_period;
+
+ if ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)
+ tp->tinfo.goal.offset = cts->sync_offset;
+
+ if ((cts->valid & CCB_TRANS_BUS_WIDTH_VALID) != 0)
+ tp->tinfo.goal.width = cts->bus_width;
}
splx(s);
ccb->ccb_h.status = CAM_REQ_CMP;
@@ -4368,21 +4381,25 @@ ncr_action (struct cam_sim *sim, union ccb *ccb)
if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0) {
tinfo = &tp->tinfo.current;
if (tp->tinfo.disc_tag & NCR_CUR_DISCENB)
- cts->flags = CCB_TRANS_DISC_ENB;
+ cts->flags |= CCB_TRANS_DISC_ENB;
else
- cts->flags = 0;
+ cts->flags &= ~CCB_TRANS_DISC_ENB;
if (tp->tinfo.disc_tag & NCR_CUR_TAGENB)
cts->flags |= CCB_TRANS_TAG_ENB;
+ else
+ cts->flags &= ~CCB_TRANS_TAG_ENB;
} else {
tinfo = &tp->tinfo.user;
if (tp->tinfo.disc_tag & NCR_USR_DISCENB)
- cts->flags = CCB_TRANS_DISC_ENB;
+ cts->flags |= CCB_TRANS_DISC_ENB;
else
- cts->flags = 0;
+ cts->flags &= ~CCB_TRANS_DISC_ENB;
if (tp->tinfo.disc_tag & NCR_USR_TAGENB)
cts->flags |= CCB_TRANS_TAG_ENB;
+ else
+ cts->flags &= ~CCB_TRANS_TAG_ENB;
}
cts->sync_period = tinfo->period;
@@ -4458,6 +4475,7 @@ ncr_action (struct cam_sim *sim, union ccb *ccb)
cpi->max_lun = MAX_LUN - 1;
cpi->initiator_id = np->myaddr;
cpi->bus_id = cam_sim_bus(sim);
+ cpi->base_transfer_speed = 3300;
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
strncpy(cpi->hba_vid, "Symbios", HBA_IDLEN);
strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
@@ -4785,8 +4803,8 @@ ncr_freeze_devq (ncb_p np, struct cam_path *path)
**==========================================================
*/
-void ncr_init
-(ncb_p np, char * msg, u_long code)
+void
+ncr_init(ncb_p np, char * msg, u_long code)
{
int i;
@@ -7074,8 +7092,8 @@ static void ncr_getclock (ncb_p np, u_char multiplier)
stest1 = INB(nc_stest1);
np->multiplier = 1;
- /* always false, except for 875 with clock doubler selected */
- if ((stest1 & (DBLEN+DBLSEL)) == DBLEN+DBLSEL) {
+
+ if (multiplier > 1) {
np->multiplier = multiplier;
np->clock_khz = 40000 * multiplier;
} else {
diff --git a/sys/pci/simos.c b/sys/pci/simos.c
index d833bebb7378..4ad9bdfeb186 100644
--- a/sys/pci/simos.c
+++ b/sys/pci/simos.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: simos.c,v 1.3 1998/12/14 06:32:57 dillon Exp $
+ * $Id: simos.c,v 1.4 1999/04/24 20:14:03 peter Exp $
*/
#include <sys/param.h>
@@ -316,6 +316,7 @@ simos_action(struct cam_sim *sim, union ccb *ccb)
cpi->max_lun = 0;
cpi->initiator_id = 7;
cpi->bus_id = sim->bus_id;
+ cpi->base_transfer_speed = 3300;
strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
strncpy(cpi->hba_vid, "SimOS", HBA_IDLEN);
strncpy(cpi->dev_name, sim->sim_name, DEV_IDLEN);