summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 3033186..f5dea97 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 fb2f05e..385e677 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 5c04dfa..67b5934 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 7020441..feaf9ed 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 183bced..53e7937 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 59c5883..b57bdbf 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 787abc7..dc23ab3 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 388939d..b603b17 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 927b1b8..2f5d973 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 501598b..12ad2e2 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 0071950..ee3f887 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 66640c8..568bf91 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 e2c3921..aef4612 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 8ab5a85..f0456db 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 4bdc6bb..6e0db43 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 346e4b8..215e0a4 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 343ad91..23de96c 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 47c12a5..d3143df 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 2c42f81..edeb582 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 17b67c5..046d575 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 4bdc6bb..6e0db43 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 1f93746..0fdf78b8 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 a32e14a..38dd843 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 d833beb..4ad9bdf 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);
OpenPOWER on IntegriCloud