diff options
-rw-r--r-- | sbin/camcontrol/camcontrol.8 | 200 | ||||
-rw-r--r-- | sbin/camcontrol/camcontrol.c | 911 | ||||
-rw-r--r-- | sys/cam/cam_ccb.h | 120 | ||||
-rw-r--r-- | sys/cam/cam_sim.c | 13 | ||||
-rw-r--r-- | sys/cam/cam_sim.h | 13 | ||||
-rw-r--r-- | sys/cam/cam_xpt.c | 68 | ||||
-rw-r--r-- | sys/cam/scsi/scsi_cd.c | 35 | ||||
-rw-r--r-- | sys/cam/scsi/scsi_da.c | 13 | ||||
-rw-r--r-- | sys/cam/scsi/scsi_pass.c | 48 | ||||
-rw-r--r-- | sys/cam/scsi/scsi_pass.h | 8 | ||||
-rw-r--r-- | sys/dev/advansys/advansys.c | 45 | ||||
-rw-r--r-- | sys/dev/advansys/advlib.c | 5 | ||||
-rw-r--r-- | sys/dev/advansys/adwcam.c | 26 | ||||
-rw-r--r-- | sys/dev/aha/aha.c | 5 | ||||
-rw-r--r-- | sys/dev/ahb/ahb.c | 3 | ||||
-rw-r--r-- | sys/dev/aic7xxx/aic7xxx.c | 14 | ||||
-rw-r--r-- | sys/dev/buslogic/bt.c | 5 | ||||
-rw-r--r-- | sys/dev/dpt/dpt_scsi.c | 3 | ||||
-rw-r--r-- | sys/dev/isp/isp_freebsd.c | 19 | ||||
-rw-r--r-- | sys/dev/ppbus/vpo.c | 3 | ||||
-rw-r--r-- | sys/i386/eisa/ahb.c | 3 | ||||
-rw-r--r-- | sys/i386/isa/bs/bs.c | 1 | ||||
-rw-r--r-- | sys/pci/ncr.c | 62 | ||||
-rw-r--r-- | sys/pci/simos.c | 3 |
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); |