Index: src/sbin/camcontrol/camcontrol.8 =================================================================== RCS file: /home/ncvs/src/sbin/camcontrol/camcontrol.8,v retrieving revision 1.38 diff -u -p -r1.38 camcontrol.8 --- src/sbin/camcontrol/camcontrol.8 3 Jul 2004 00:13:43 -0000 1.38 +++ src/sbin/camcontrol/camcontrol.8 6 Oct 2004 09:17:37 -0000 @@ -95,6 +95,7 @@ .Op Fl P Ar pgctl .Op Fl b | Fl e .Op Fl d +.Op Fl s .Nm .Ic cmd .Op device id @@ -376,6 +377,9 @@ and/or edit. This argument is mandatory unless .Fl l is specified. +.It Fl s +This forces the use of a 10-byte MODE SENSE or MODE SELECT command, which is +necessary for certain kinds of devices. .It Fl P Ar pgctl This allows the user to specify the page control field. Possible values are: Index: src/sbin/camcontrol/camcontrol.c =================================================================== RCS file: /home/ncvs/src/sbin/camcontrol/camcontrol.c,v retrieving revision 1.52 diff -u -p -r1.52 camcontrol.c --- src/sbin/camcontrol/camcontrol.c 3 Mar 2004 01:51:24 -0000 1.52 +++ src/sbin/camcontrol/camcontrol.c 6 Oct 2004 09:13:52 -0000 @@ -139,7 +139,7 @@ struct camcontrol_opts option_table[] = {"devlist", CAM_CMD_DEVTREE, CAM_ARG_NONE, NULL}, #ifndef MINIMALISTIC {"periphlist", CAM_CMD_DEVLIST, CAM_ARG_NONE, NULL}, - {"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:P:"}, + {"modepage", CAM_CMD_MODE_PAGE, CAM_ARG_NONE, "bdelm:sP:"}, {"tags", CAM_CMD_TAG, CAM_ARG_NONE, "N:q"}, {"negotiate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts}, {"rate", CAM_CMD_RATE, CAM_ARG_NONE, negotiate_opts}, @@ -1586,7 +1586,8 @@ reassignblocks(struct cam_device *device #ifndef MINIMALISTIC void mode_sense(struct cam_device *device, int mode_page, int page_control, - int dbd, int retry_count, int timeout, u_int8_t *data, int datalen) + int dbd, int retry_count, int timeout, u_int8_t *data, int datalen, + int force10bytes) { union ccb *ccb; int retval; @@ -1599,7 +1600,7 @@ mode_sense(struct cam_device *device, in bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr)); - scsi_mode_sense(&ccb->csio, + scsi_mode_sense_len(&ccb->csio, /* retries */ retry_count, /* cbfcnp */ NULL, /* tag_action */ MSG_SIMPLE_Q_TAG, @@ -1608,6 +1609,7 @@ mode_sense(struct cam_device *device, in /* page */ mode_page, /* param_buf */ data, /* param_len */ datalen, + /* minimum_cmd_size */ force10bytes ? 10 : 0, /* sense_len */ SSD_FULL_SIZE, /* timeout */ timeout ? timeout : 5000); @@ -1636,7 +1638,7 @@ mode_sense(struct cam_device *device, in void mode_select(struct cam_device *device, int save_pages, int retry_count, - int timeout, u_int8_t *data, int datalen) + int timeout, u_int8_t *data, int datalen, int force10bytes) { union ccb *ccb; int retval; @@ -1649,7 +1651,7 @@ mode_select(struct cam_device *device, i bzero(&(&ccb->ccb_h)[1], sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr)); - scsi_mode_select(&ccb->csio, + scsi_mode_select_len(&ccb->csio, /* retries */ retry_count, /* cbfcnp */ NULL, /* tag_action */ MSG_SIMPLE_Q_TAG, @@ -1657,6 +1659,7 @@ mode_select(struct cam_device *device, i /* save_pages */ save_pages, /* param_buf */ data, /* param_len */ datalen, + /* minimum_cmd_size */ force10bytes ? 10 : 0, /* sense_len */ SSD_FULL_SIZE, /* timeout */ timeout ? timeout : 5000); @@ -1690,7 +1693,7 @@ modepage(struct cam_device *device, int int retry_count, int timeout) { int c, mode_page = -1, page_control = 0; - int binary = 0, list = 0; + int binary = 0, list = 0, force10bytes = 0; while ((c = getopt(argc, argv, combinedopt)) != -1) { switch(c) { @@ -1711,6 +1714,9 @@ modepage(struct cam_device *device, int if (mode_page < 0) errx(1, "invalid mode page %d", mode_page); break; + case 's': + force10bytes = 1; + break; case 'P': page_control = strtol(optarg, NULL, 0); if ((page_control < 0) || (page_control > 3)) @@ -1728,11 +1734,11 @@ modepage(struct cam_device *device, int if (list) { mode_list(device, page_control, arglist & CAM_ARG_DBD, - retry_count, timeout); + retry_count, timeout, force10bytes); } else { mode_edit(device, mode_page, page_control, arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary, - retry_count, timeout); + retry_count, timeout, force10bytes); } } @@ -3166,7 +3172,7 @@ usage(int verbose) #ifndef MINIMALISTIC " camcontrol defects [dev_id][generic args] <-f format> [-P][-G]\n" " camcontrol modepage [dev_id][generic args] <-m page | -l>\n" -" [-P pagectl][-e | -b][-d]\n" +" [-P pagectl][-e | -b][-d][-s]\n" " camcontrol cmd [dev_id][generic args] <-c cmd [args]>\n" " [-i len fmt|-o len fmt [args]]\n" " camcontrol debug [-I][-P][-T][-S][-X][-c]\n" Index: src/sbin/camcontrol/camcontrol.h =================================================================== RCS file: /home/ncvs/src/sbin/camcontrol/camcontrol.h,v retrieving revision 1.4 diff -u -p -r1.4 camcontrol.h --- src/sbin/camcontrol/camcontrol.h 8 Aug 2000 06:24:15 -0000 1.4 +++ src/sbin/camcontrol/camcontrol.h 6 Oct 2004 09:14:03 -0000 @@ -42,13 +42,14 @@ struct get_hook void mode_sense(struct cam_device *device, int mode_page, int page_control, int dbd, int retry_count, int timeout, u_int8_t *data, - int datalen); + int datalen, int force10bytes); void mode_select(struct cam_device *device, int save_pages, int retry_count, - int timeout, u_int8_t *data, int datalen); + int timeout, u_int8_t *data, int datalen, int force10bytes); void mode_edit(struct cam_device *device, int page, int page_control, int dbd, - int edit, int binary, int retry_count, int timeout); + int edit, int binary, int retry_count, int timeout, + int force10bytes); void mode_list(struct cam_device *device, int page_control, int dbd, - int retry_count, int timeout); + int retry_count, int timeout, int force10bytes); char *cget(void *hook, char *name); int iget(void *hook, char *name); void arg_put(void *hook, int letter, void *arg, int count, char *name); Index: src/sbin/camcontrol/modeedit.c =================================================================== RCS file: /home/ncvs/src/sbin/camcontrol/modeedit.c,v retrieving revision 1.17 diff -u -p -r1.17 modeedit.c --- src/sbin/camcontrol/modeedit.c 22 Jan 2004 07:23:35 -0000 1.17 +++ src/sbin/camcontrol/modeedit.c 6 Oct 2004 10:44:30 -0000 @@ -65,9 +65,12 @@ int verbose = 0; /* Macros for working with mode pages. */ -#define MODE_PAGE_HEADER(mh) \ +#define MODE_PAGE_HEADER_6(mh) \ (struct scsi_mode_page_header *)find_mode_page_6(mh) +#define MODE_PAGE_HEADER_10(mh) \ + (struct scsi_mode_page_header *)find_mode_page_10(mh) + #define MODE_PAGE_DATA(mph) \ (u_int8_t *)(mph) + sizeof(struct scsi_mode_page_header) @@ -110,10 +113,11 @@ static int editentry_set(char *name, c int editonly); static void editlist_populate(struct cam_device *device, int modepage, int page_control, - int dbd, int retries, int timeout); + int dbd, int retries, int timeout, + int force10bytes); static void editlist_save(struct cam_device *device, int modepage, int page_control, int dbd, int retries, - int timeout); + int timeout, int force10bytes); static void nameentry_create(int pagenum, char *name); static struct pagename *nameentry_lookup(int pagenum); static int load_format(const char *pagedb_path, int page); @@ -122,7 +126,7 @@ static int modepage_read(FILE *file); static void modepage_edit(void); static void modepage_dump(struct cam_device *device, int page, int page_control, int dbd, int retries, - int timeout); + int timeout, int force10bytes); static void cleanup_editfile(void); @@ -527,42 +531,53 @@ load_format(const char *pagedb_path, int static void editlist_populate(struct cam_device *device, int modepage, int page_control, - int dbd, int retries, int timeout) + int dbd, int retries, int timeout, int force10bytes) { u_int8_t data[MAX_COMMAND_SIZE];/* Buffer to hold sense data. */ u_int8_t *mode_pars; /* Pointer to modepage params. */ - struct scsi_mode_header_6 *mh; /* Location of mode header. */ + u_int32_t data_length; + struct scsi_mode_header_6 *mh6; + struct scsi_mode_header_10 *mh10; struct scsi_mode_page_header *mph; STAILQ_INIT(&editlist); /* Fetch changeable values; use to build initial editlist. */ mode_sense(device, modepage, 1, dbd, retries, timeout, data, - sizeof(data)); + sizeof(data), force10bytes); - mh = (struct scsi_mode_header_6 *)data; - mph = MODE_PAGE_HEADER(mh); - mode_pars = MODE_PAGE_DATA(mph); + if (force10bytes) { + mh10 = (struct scsi_mode_header_10 *)data; + mph = MODE_PAGE_HEADER_10(mh10); + mode_pars = MODE_PAGE_DATA(mph); + data_length = scsi_2btoul(mh10->data_length); + } else { + mh6 = (struct scsi_mode_header_6 *)data; + mph = MODE_PAGE_HEADER_6(mh6); + mode_pars = MODE_PAGE_DATA(mph); + data_length = mh6->data_length; + } /* Decode the value data, creating edit_entries for each value. */ - buff_decode_visit(mode_pars, mh->data_length, format, + buff_decode_visit(mode_pars, data_length, format, editentry_create, 0); /* Fetch the current/saved values; use to set editentry values. */ mode_sense(device, modepage, page_control, dbd, retries, timeout, data, - sizeof(data)); - buff_decode_visit(mode_pars, mh->data_length, format, - editentry_update, 0); + sizeof(data), force10bytes); + buff_decode_visit(mode_pars, data_length, format, editentry_update, 0); } static void editlist_save(struct cam_device *device, int modepage, int page_control, - int dbd, int retries, int timeout) + int dbd, int retries, int timeout, int force10bytes) { u_int8_t data[MAX_COMMAND_SIZE];/* Buffer to hold sense data. */ u_int8_t *mode_pars; /* Pointer to modepage params. */ - struct scsi_mode_header_6 *mh; /* Location of mode header. */ + struct scsi_mode_header_6 *mh6; + struct scsi_mode_header_10 *mh10; struct scsi_mode_page_header *mph; + u_int32_t data_length, mh_size, mh_blk_desc_len; /* Make sure that something changed before continuing. */ if (! editlist_changed) @@ -575,29 +590,50 @@ editlist_save(struct cam_device *device, * now, we need mode_sense to find out the page length. */ mode_sense(device, modepage, page_control, dbd, retries, timeout, data, - sizeof(data)); + sizeof(data), force10bytes); /* Initial headers & offsets. */ - mh = (struct scsi_mode_header_6 *)data; - mph = MODE_PAGE_HEADER(mh); + mh6 = (struct scsi_mode_header_6 *)data; + mh10 = (struct scsi_mode_header_10 *)data; + if (force10bytes) { + mh_size = sizeof(*mh10); + mph = MODE_PAGE_HEADER_10(mh10); + data_length = scsi_2btoul(mh10->data_length); + } else { + mh_size = sizeof(*mh6); + mph = MODE_PAGE_HEADER_6(mh6); + data_length = mh6->data_length; + } + mode_pars = MODE_PAGE_DATA(mph); /* Encode the value data to be passed back to the device. */ - buff_encode_visit(mode_pars, mh->data_length, format, + buff_encode_visit(mode_pars, data_length, format, editentry_save, 0); /* Eliminate block descriptors. */ - bcopy(mph, ((u_int8_t *)mh) + sizeof(*mh), + bcopy(mph, ((u_int8_t *)data) + mh_size, sizeof(*mph) + mph->page_length); /* Recalculate headers & offsets. */ - mh->blk_desc_len = 0; /* No block descriptors. */ - mh->dev_spec = 0; /* Clear device-specific parameters. */ - mph = MODE_PAGE_HEADER(mh); + /* Clear device-specific parameters. */ + if (force10bytes) { + scsi_ulto2b(0, mh10->blk_desc_len); + mh10->dev_spec = 0; + scsi_ulto2b(0, mh10->data_length); + mph = MODE_PAGE_HEADER_10(mh10); + mh_blk_desc_len = scsi_2btoul(&mh6->blk_desc_len); + } else { + mh6->blk_desc_len = 0; + mh6->dev_spec = 0; + mh6->data_length = 0; + mph = MODE_PAGE_HEADER_6(mh6); + mh_blk_desc_len = mh6->blk_desc_len; + } mode_pars = MODE_PAGE_DATA(mph); - mph->page_code &= SMS_PAGE_CODE;/* Isolate just the page code. */ - mh->data_length = 0; /* Reserved for MODE SELECT command. */ + /* Isolate just the page code. */ + mph->page_code &= SMS_PAGE_CODE; /* * Write the changes back to the device. If the user editted control @@ -606,8 +642,9 @@ editlist_save(struct cam_device *device, */ mode_select(device, (page_control << PAGE_CTRL_SHIFT == SMS_PAGE_CTRL_SAVED), - retries, timeout, (u_int8_t *)mh, - sizeof(*mh) + mh->blk_desc_len + sizeof(*mph) + mph->page_length); + retries, timeout, (u_int8_t *)data, + mh_size + mh_blk_desc_len + sizeof(*mph) + mph->page_length, + force10bytes); } static int @@ -777,19 +814,26 @@ modepage_edit(void) static void modepage_dump(struct cam_device *device, int page, int page_control, int dbd, - int retries, int timeout) + int retries, int timeout, int force10bytes) { u_int8_t data[MAX_COMMAND_SIZE];/* Buffer to hold sense data. */ u_int8_t *mode_pars; /* Pointer to modepage params. */ - struct scsi_mode_header_6 *mh; /* Location of mode header. */ + struct scsi_mode_header_6 *mh6; + struct scsi_mode_header_10 *mh10; struct scsi_mode_page_header *mph; int indx; /* Index for scanning mode params. */ mode_sense(device, page, page_control, dbd, retries, timeout, data, - sizeof(data)); + sizeof(data), force10bytes); + + mh6 = (struct scsi_mode_header_6 *)data; + mh10 = (struct scsi_mode_header_10 *)data; + + if (force10bytes) + mph = MODE_PAGE_HEADER_10(mh10); + else + mph = MODE_PAGE_HEADER_6(mh6); - mh = (struct scsi_mode_header_6 *)data; - mph = MODE_PAGE_HEADER(mh); mode_pars = MODE_PAGE_DATA(mph); /* Print the raw mode page data with newlines each 8 bytes. */ @@ -812,7 +856,8 @@ cleanup_editfile(void) void mode_edit(struct cam_device *device, int page, int page_control, int dbd, - int edit, int binary, int retry_count, int timeout) + int edit, int binary, int retry_count, int timeout, + int force10bytes) { const char *pagedb_path; /* Path to modepage database. */ @@ -842,7 +887,7 @@ mode_edit(struct cam_device *device, int } editlist_populate(device, page, page_control, dbd, retry_count, - timeout); + timeout, force10bytes); } if (edit) { @@ -852,11 +897,11 @@ mode_edit(struct cam_device *device, int "(current) or page 3 (saved values)"); modepage_edit(); editlist_save(device, page, page_control, dbd, retry_count, - timeout); + timeout, force10bytes); } else if (binary || STAILQ_EMPTY(&editlist)) { /* Display without formatting information. */ modepage_dump(device, page, page_control, dbd, retry_count, - timeout); + timeout, force10bytes); } else { /* Display with format. */ modepage_write(stdout, 0); @@ -865,7 +910,7 @@ mode_edit(struct cam_device *device, int void mode_list(struct cam_device *device, int page_control, int dbd, - int retry_count, int timeout) + int retry_count, int timeout, int force10bytes) { u_int8_t data[MAX_COMMAND_SIZE];/* Buffer to hold sense data. */ u_int8_t *mode_pars; /* Pointer to modepage params. */ @@ -885,7 +930,7 @@ mode_list(struct cam_device *device, int /* Build the list of all mode pages by querying the "all pages" page. */ mode_sense(device, SMS_ALL_PAGES_PAGE, page_control, dbd, retry_count, - timeout, data, sizeof(data)); + timeout, data, sizeof(data), force10bytes); mh = (struct scsi_mode_header_6 *)data; len = mh->blk_desc_len; /* Skip block descriptors. */