From 0326d972fce41ce12a9215ca34c42eacc6d39db4 Mon Sep 17 00:00:00 2001 From: mav Date: Sat, 21 Jan 2017 08:17:30 +0000 Subject: MFC r311636: Make 'camcontrol modepage' support subpages. --- sbin/camcontrol/camcontrol.8 | 11 +- sbin/camcontrol/camcontrol.c | 58 +++++----- sbin/camcontrol/camcontrol.h | 8 +- sbin/camcontrol/modeedit.c | 249 +++++++++++++++++++++++++------------------ 4 files changed, 187 insertions(+), 139 deletions(-) (limited to 'sbin') diff --git a/sbin/camcontrol/camcontrol.8 b/sbin/camcontrol/camcontrol.8 index 9f2211c..87ea011 100644 --- a/sbin/camcontrol/camcontrol.8 +++ b/sbin/camcontrol/camcontrol.8 @@ -27,7 +27,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 26, 2016 +.Dd January 6, 2017 .Dt CAMCONTROL 8 .Os .Sh NAME @@ -121,7 +121,7 @@ .Ic modepage .Op device id .Op generic args -.Aq Fl m Ar page | Fl l +.Aq Fl m Ar page[,subpage] | Fl l .Op Fl P Ar pgctl .Op Fl b | Fl e .Op Fl d @@ -678,9 +678,10 @@ The editor will be invoked if detects that standard input is terminal. .It Fl l Lists all available mode pages. -.It Fl m Ar mode_page -This specifies the number of the mode page the user would like to view -and/or edit. +If specified more then once, also lists subpages. +.It Fl m Ar page[,subpage] +This specifies the number of the mode page and optionally subpage the user +would like to view and/or edit. This argument is mandatory unless .Fl l is specified. diff --git a/sbin/camcontrol/camcontrol.c b/sbin/camcontrol/camcontrol.c index cae7ec2..d662811 100644 --- a/sbin/camcontrol/camcontrol.c +++ b/sbin/camcontrol/camcontrol.c @@ -122,12 +122,9 @@ typedef enum { CAM_ARG_GET_STDINQ = 0x00002000, CAM_ARG_GET_XFERRATE = 0x00004000, CAM_ARG_INQ_MASK = 0x00007000, - CAM_ARG_MODE_EDIT = 0x00008000, - CAM_ARG_PAGE_CNTL = 0x00010000, CAM_ARG_TIMEOUT = 0x00020000, CAM_ARG_CMD_IN = 0x00040000, CAM_ARG_CMD_OUT = 0x00080000, - CAM_ARG_DBD = 0x00100000, CAM_ARG_ERR_RECOVER = 0x00200000, CAM_ARG_RETRIES = 0x00400000, CAM_ARG_START_UNIT = 0x00800000, @@ -3982,8 +3979,8 @@ reassignblocks(struct cam_device *device, u_int32_t *blocks, int num_blocks) #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) +mode_sense(struct cam_device *device, int dbd, int pc, int page, int subpage, + int retry_count, int timeout, u_int8_t *data, int datalen) { union ccb *ccb; int retval; @@ -3995,15 +3992,17 @@ mode_sense(struct cam_device *device, int mode_page, int page_control, CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio); - scsi_mode_sense(&ccb->csio, + scsi_mode_sense_subpage(&ccb->csio, /* retries */ retry_count, /* cbfcnp */ NULL, /* tag_action */ MSG_SIMPLE_Q_TAG, /* dbd */ dbd, - /* page_code */ page_control << 6, - /* page */ mode_page, + /* pc */ pc << 6, + /* page */ page, + /* subpage */ subpage, /* param_buf */ data, /* param_len */ datalen, + /* minimum_cmd_size */ 0, /* sense_len */ SSD_FULL_SIZE, /* timeout */ timeout ? timeout : 5000); @@ -4084,8 +4083,9 @@ void modepage(struct cam_device *device, int argc, char **argv, char *combinedopt, int retry_count, int timeout) { - int c, mode_page = -1, page_control = 0; - int binary = 0, list = 0; + char *str_subpage; + int c, page = -1, subpage = -1, pc = 0; + int binary = 0, dbd = 0, edit = 0, list = 0; while ((c = getopt(argc, argv, combinedopt)) != -1) { switch(c) { @@ -4093,40 +4093,44 @@ modepage(struct cam_device *device, int argc, char **argv, char *combinedopt, binary = 1; break; case 'd': - arglist |= CAM_ARG_DBD; + dbd = 1; break; case 'e': - arglist |= CAM_ARG_MODE_EDIT; + edit = 1; break; case 'l': - list = 1; + list++; break; case 'm': - mode_page = strtol(optarg, NULL, 0); - if (mode_page < 0) - errx(1, "invalid mode page %d", mode_page); + str_subpage = optarg; + strsep(&str_subpage, ","); + page = strtol(optarg, NULL, 0); + if (str_subpage) + subpage = strtol(str_subpage, NULL, 0); + else + subpage = 0; + if (page < 0) + errx(1, "invalid mode page %d", page); + if (subpage < 0) + errx(1, "invalid mode subpage %d", subpage); break; case 'P': - page_control = strtol(optarg, NULL, 0); - if ((page_control < 0) || (page_control > 3)) - errx(1, "invalid page control field %d", - page_control); - arglist |= CAM_ARG_PAGE_CNTL; + pc = strtol(optarg, NULL, 0); + if ((pc < 0) || (pc > 3)) + errx(1, "invalid page control field %d", pc); break; default: break; } } - if (mode_page == -1 && list == 0) + if (page == -1 && list == 0) errx(1, "you must specify a mode page!"); - if (list) { - mode_list(device, page_control, arglist & CAM_ARG_DBD, - retry_count, timeout); + if (list != 0) { + mode_list(device, dbd, pc, list > 1, retry_count, timeout); } else { - mode_edit(device, mode_page, page_control, - arglist & CAM_ARG_DBD, arglist & CAM_ARG_MODE_EDIT, binary, + mode_edit(device, dbd, pc, page, subpage, edit, binary, retry_count, timeout); } } diff --git a/sbin/camcontrol/camcontrol.h b/sbin/camcontrol/camcontrol.h index bb2fe4f..3d6b98d 100644 --- a/sbin/camcontrol/camcontrol.h +++ b/sbin/camcontrol/camcontrol.h @@ -73,14 +73,14 @@ int camxferrate(struct cam_device *device); int fwdownload(struct cam_device *device, int argc, char **argv, char *combinedopt, int printerrors, int retry_count, int timeout); -void mode_sense(struct cam_device *device, int mode_page, int page_control, - int dbd, int retry_count, int timeout, u_int8_t *data, +void mode_sense(struct cam_device *device, int dbd, int pc, int page, + int subpage, int retry_count, int timeout, uint8_t *data, int datalen); void mode_select(struct cam_device *device, int save_pages, int retry_count, int timeout, u_int8_t *data, int datalen); -void mode_edit(struct cam_device *device, int page, int page_control, int dbd, +void mode_edit(struct cam_device *device, int dbd, int pc, int page, int subpage, int edit, int binary, int retry_count, int timeout); -void mode_list(struct cam_device *device, int page_control, int dbd, +void mode_list(struct cam_device *device, int dbd, int pc, int subpages, int retry_count, int timeout); int scsidoinquiry(struct cam_device *device, int argc, char **argv, char *combinedopt, int retry_count, int timeout); diff --git a/sbin/camcontrol/modeedit.c b/sbin/camcontrol/modeedit.c index c98e0c5..cbc138c 100644 --- a/sbin/camcontrol/modeedit.c +++ b/sbin/camcontrol/modeedit.c @@ -66,9 +66,6 @@ __FBSDID("$FreeBSD$"); #define MODE_PAGE_HEADER(mh) \ (struct scsi_mode_page_header *)find_mode_page_6(mh) -#define MODE_PAGE_DATA(mph) \ - (u_int8_t *)(mph) + sizeof(struct scsi_mode_page_header) - struct editentry { STAILQ_ENTRY(editentry) link; @@ -86,7 +83,8 @@ static int editlist_changed = 0; /* Whether any entries were changed. */ struct pagename { SLIST_ENTRY(pagename) link; - int pagenum; + int page; + int subpage; char *name; }; static SLIST_HEAD(, pagename) namelist; /* Page number to name mappings. */ @@ -106,21 +104,22 @@ static int editentry_save(void *hook, char *name); static struct editentry *editentry_lookup(char *name); static int editentry_set(char *name, char *newvalue, int editonly); -static void editlist_populate(struct cam_device *device, - int modepage, int page_control, - int dbd, int retries, int timeout); -static void editlist_save(struct cam_device *device, int modepage, - int page_control, int dbd, int retries, - int timeout); -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); +static void editlist_populate(struct cam_device *device, int dbd, + int pc, int page, int subpage, + int retries, int timeout); +static void editlist_save(struct cam_device *device, int dbd, + int pc, int page, int subpage, + int retries, int timeout); +static void nameentry_create(int page, int subpage, char *name); +static struct pagename *nameentry_lookup(int page, int subpage); +static int load_format(const char *pagedb_path, int lpage, + int lsubpage); static int modepage_write(FILE *file, int editonly); 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); +static void modepage_dump(struct cam_device *device, int dbd, + int pc, int page, int subpage, int retries, + int timeout); static void cleanup_editfile(void); @@ -325,10 +324,10 @@ editentry_set(char *name, char *newvalue, int editonly) } static void -nameentry_create(int pagenum, char *name) { +nameentry_create(int page, int subpage, char *name) { struct pagename *newentry; - if (pagenum < 0 || name == NULL || name[0] == '\0') + if (page < 0 || subpage < 0 || name == NULL || name[0] == '\0') return; /* Allocate memory for the new entry and a copy of the entry name. */ @@ -339,16 +338,17 @@ nameentry_create(int pagenum, char *name) { /* Trim any trailing whitespace for the page name. */ RTRIM(newentry->name); - newentry->pagenum = pagenum; + newentry->page = page; + newentry->subpage = subpage; SLIST_INSERT_HEAD(&namelist, newentry, link); } static struct pagename * -nameentry_lookup(int pagenum) { +nameentry_lookup(int page, int subpage) { struct pagename *scan; SLIST_FOREACH(scan, &namelist, link) { - if (pagenum == scan->pagenum) + if (page == scan->page && subpage == scan->subpage) return (scan); } @@ -357,12 +357,14 @@ nameentry_lookup(int pagenum) { } static int -load_format(const char *pagedb_path, int page) +load_format(const char *pagedb_path, int lpage, int lsubpage) { FILE *pagedb; - char str_pagenum[MAX_PAGENUM_LEN]; + char str_page[MAX_PAGENUM_LEN]; + char *str_subpage; char str_pagename[MAX_PAGENAME_LEN]; - int pagenum; + int page; + int subpage; int depth; /* Quoting depth. */ int found; int lineno; @@ -371,9 +373,10 @@ load_format(const char *pagedb_path, int page) char c; #define SETSTATE_LOCATE do { \ - str_pagenum[0] = '\0'; \ + str_page[0] = '\0'; \ str_pagename[0] = '\0'; \ - pagenum = -1; \ + page = -1; \ + subpage = -1; \ state = LOCATE; \ } while (0) @@ -450,32 +453,46 @@ load_format(const char *pagedb_path, int page) * modes without providing a mode definition). */ /* Record the name of this page. */ - pagenum = strtol(str_pagenum, NULL, 0); - nameentry_create(pagenum, str_pagename); + str_subpage = str_page; + strsep(&str_subpage, ","); + page = strtol(str_page, NULL, 0); + if (str_subpage) + subpage = strtol(str_subpage, NULL, 0); + else + subpage = 0; + nameentry_create(page, subpage, str_pagename); SETSTATE_LOCATE; } else if (depth == 0 && c == PAGENAME_START) { SETSTATE_PAGENAME; } else if (c == PAGEDEF_START) { - pagenum = strtol(str_pagenum, NULL, 0); + str_subpage = str_page; + strsep(&str_subpage, ","); + page = strtol(str_page, NULL, 0); + if (str_subpage) + subpage = strtol(str_subpage, NULL, 0); + else + subpage = 0; if (depth == 1) { /* Record the name of this page. */ - nameentry_create(pagenum, str_pagename); + nameentry_create(page, subpage, + str_pagename); /* * Only record the format if this is * the page we are interested in. */ - if (page == pagenum && !found) + if (lpage == page && + lsubpage == subpage && !found) SETSTATE_PAGEDEF; } } else if (c == PAGEDEF_END) { /* Reset the processor state. */ SETSTATE_LOCATE; - } else if (depth == 0 && ! BUFFERFULL(str_pagenum)) { - strncat(str_pagenum, &c, 1); + } else if (depth == 0 && ! BUFFERFULL(str_page)) { + strncat(str_page, &c, 1); } else if (depth == 0) { errx(EX_OSFILE, "%s:%d: %s %zd %s", pagedb_path, lineno, "page identifier exceeds", - sizeof(str_pagenum) - 1, "characters"); + sizeof(str_page) - 1, "characters"); } break; @@ -491,7 +508,7 @@ load_format(const char *pagedb_path, int page) } else { errx(EX_OSFILE, "%s:%d: %s %zd %s", pagedb_path, lineno, "page name exceeds", - sizeof(str_pagenum) - 1, "characters"); + sizeof(str_page) - 1, "characters"); } break; @@ -532,88 +549,95 @@ load_format(const char *pagedb_path, int page) } static void -editlist_populate(struct cam_device *device, int modepage, int page_control, - int dbd, int retries, int timeout) +editlist_populate(struct cam_device *device, int dbd, int pc, int page, + int subpage, int retries, int timeout) { 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_page_header *mph; + struct scsi_mode_page_header_sp *mphsp; + int len; STAILQ_INIT(&editlist); /* Fetch changeable values; use to build initial editlist. */ - mode_sense(device, modepage, 1, dbd, retries, timeout, data, + mode_sense(device, dbd, 1, page, subpage, retries, timeout, data, sizeof(data)); mh = (struct scsi_mode_header_6 *)data; mph = MODE_PAGE_HEADER(mh); - mode_pars = MODE_PAGE_DATA(mph); + if ((mph->page_code & SMPH_SPF) == 0) { + mode_pars = (uint8_t *)(mph + 1); + len = mph->page_length; + } else { + mphsp = (struct scsi_mode_page_header_sp *)mph; + mode_pars = (uint8_t *)(mphsp + 1); + len = scsi_2btoul(mphsp->page_length); + } /* Decode the value data, creating edit_entries for each value. */ - buff_decode_visit(mode_pars, mh->data_length, format, - editentry_create, 0); + buff_decode_visit(mode_pars, len, 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); + mode_sense(device, dbd, pc, page, subpage, retries, timeout, + data, sizeof(data)); + buff_decode_visit(mode_pars, len, format, editentry_update, 0); } static void -editlist_save(struct cam_device *device, int modepage, int page_control, - int dbd, int retries, int timeout) +editlist_save(struct cam_device *device, int dbd, int pc, int page, + int subpage, int retries, int timeout) { 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_page_header *mph; + struct scsi_mode_page_header_sp *mphsp; + int len, hlen; /* Make sure that something changed before continuing. */ if (! editlist_changed) return; - /* - * Preload the CDB buffer with the current mode page data. - * XXX If buff_encode_visit would return the number of bytes encoded - * we *should* use that to build a header from scratch. As it is - * now, we need mode_sense to find out the page length. - */ - mode_sense(device, modepage, page_control, dbd, retries, timeout, data, - sizeof(data)); + /* Preload the CDB buffer with the current mode page data. */ + mode_sense(device, dbd, pc, page, subpage, retries, timeout, + data, sizeof(data)); /* Initial headers & offsets. */ mh = (struct scsi_mode_header_6 *)data; mph = MODE_PAGE_HEADER(mh); - mode_pars = MODE_PAGE_DATA(mph); + if ((mph->page_code & SMPH_SPF) == 0) { + hlen = sizeof(*mph); + mode_pars = (uint8_t *)(mph + 1); + len = mph->page_length; + } else { + mphsp = (struct scsi_mode_page_header_sp *)mph; + hlen = sizeof(*mphsp); + mode_pars = (uint8_t *)(mphsp + 1); + len = scsi_2btoul(mphsp->page_length); + } /* Encode the value data to be passed back to the device. */ - buff_encode_visit(mode_pars, mh->data_length, format, - editentry_save, 0); + buff_encode_visit(mode_pars, len, format, editentry_save, 0); /* Eliminate block descriptors. */ - bcopy(mph, ((u_int8_t *)mh) + sizeof(*mh), - sizeof(*mph) + mph->page_length); + bcopy(mph, mh + 1, hlen + len); /* Recalculate headers & offsets. */ - mh->blk_desc_len = 0; /* No block descriptors. */ + mh->data_length = 0; /* Reserved for MODE SELECT command. */ mh->dev_spec = 0; /* Clear device-specific parameters. */ + mh->blk_desc_len = 0; /* No block descriptors. */ mph = MODE_PAGE_HEADER(mh); - 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. */ + mph->page_code &= ~SMPH_PS; /* Reserved for MODE SELECT command. */ /* * Write the changes back to the device. If the user editted control * page 3 (saved values) then request the changes be permanently * recorded. */ - 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); + mode_select(device, (pc << PAGE_CTRL_SHIFT == SMS_PAGE_CTRL_SAVED), + retries, timeout, (u_int8_t *)mh, sizeof(*mh) + hlen + len); } static int @@ -782,24 +806,32 @@ modepage_edit(void) } static void -modepage_dump(struct cam_device *device, int page, int page_control, int dbd, +modepage_dump(struct cam_device *device, int dbd, int pc, int page, int subpage, int retries, int timeout) { 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_page_header *mph; - int indx; /* Index for scanning mode params. */ + struct scsi_mode_page_header_sp *mphsp; + int indx, len; - mode_sense(device, page, page_control, dbd, retries, timeout, data, - sizeof(data)); + mode_sense(device, dbd, pc, page, subpage, retries, timeout, + data, sizeof(data)); mh = (struct scsi_mode_header_6 *)data; mph = MODE_PAGE_HEADER(mh); - mode_pars = MODE_PAGE_DATA(mph); + if ((mph->page_code & SMPH_SPF) == 0) { + mode_pars = (uint8_t *)(mph + 1); + len = mph->page_length; + } else { + mphsp = (struct scsi_mode_page_header_sp *)mph; + mode_pars = (uint8_t *)(mphsp + 1); + len = scsi_2btoul(mphsp->page_length); + } /* Print the raw mode page data with newlines each 8 bytes. */ - for (indx = 0; indx < mph->page_length; indx++) { + for (indx = 0; indx < len; indx++) { printf("%02x%c",mode_pars[indx], (((indx + 1) % 8) == 0) ? '\n' : ' '); } @@ -817,7 +849,7 @@ cleanup_editfile(void) } void -mode_edit(struct cam_device *device, int page, int page_control, int dbd, +mode_edit(struct cam_device *device, int dbd, int pc, int page, int subpage, int edit, int binary, int retry_count, int timeout) { const char *pagedb_path; /* Path to modepage database. */ @@ -829,15 +861,17 @@ mode_edit(struct cam_device *device, int page, int page_control, int dbd, if ((pagedb_path = getenv("SCSI_MODES")) == NULL) pagedb_path = DEFAULT_SCSI_MODE_DB; - if (load_format(pagedb_path, page) != 0 && (edit || verbose)) { + if (load_format(pagedb_path, page, subpage) != 0 && + (edit || verbose)) { if (errno == ENOENT) { /* Modepage database file not found. */ warn("cannot open modepage database \"%s\"", pagedb_path); } else if (errno == ESRCH) { /* Modepage entry not found in database. */ - warnx("modepage %d not found in database" - "\"%s\"", page, pagedb_path); + warnx("modepage 0x%02x,0x%02x not found in " + "database \"%s\"", page, subpage, + pagedb_path); } /* We can recover in display mode, otherwise we exit. */ if (!edit) { @@ -847,22 +881,20 @@ mode_edit(struct cam_device *device, int page, int page_control, int dbd, exit(EX_OSFILE); } - editlist_populate(device, page, page_control, dbd, retry_count, + editlist_populate(device, dbd, pc, page, subpage, retry_count, timeout); } if (edit) { - if (page_control << PAGE_CTRL_SHIFT != SMS_PAGE_CTRL_CURRENT && - page_control << PAGE_CTRL_SHIFT != SMS_PAGE_CTRL_SAVED) + if (pc << PAGE_CTRL_SHIFT != SMS_PAGE_CTRL_CURRENT && + pc << PAGE_CTRL_SHIFT != SMS_PAGE_CTRL_SAVED) errx(EX_USAGE, "it only makes sense to edit page 0 " "(current) or page 3 (saved values)"); modepage_edit(); - editlist_save(device, page, page_control, dbd, retry_count, - timeout); + editlist_save(device, dbd, pc, page, subpage, retry_count, timeout); } else if (binary || STAILQ_EMPTY(&editlist)) { /* Display without formatting information. */ - modepage_dump(device, page, page_control, dbd, retry_count, - timeout); + modepage_dump(device, dbd, pc, page, subpage, retry_count, timeout); } else { /* Display with format. */ modepage_write(stdout, 0); @@ -870,44 +902,55 @@ mode_edit(struct cam_device *device, int page, int page_control, int dbd, } void -mode_list(struct cam_device *device, int page_control, int dbd, +mode_list(struct cam_device *device, int dbd, int pc, int subpages, int retry_count, int timeout) { u_int8_t data[MAX_COMMAND_SIZE];/* Buffer to hold sense data. */ struct scsi_mode_header_6 *mh; /* Location of mode header. */ struct scsi_mode_page_header *mph; + struct scsi_mode_page_header_sp *mphsp; struct pagename *nameentry; const char *pagedb_path; - int len; + int len, page, subpage; if ((pagedb_path = getenv("SCSI_MODES")) == NULL) pagedb_path = DEFAULT_SCSI_MODE_DB; - if (load_format(pagedb_path, 0) != 0 && verbose && errno == ENOENT) { + if (load_format(pagedb_path, 0, 0) != 0 && verbose && errno == ENOENT) { /* Modepage database file not found. */ warn("cannot open modepage database \"%s\"", pagedb_path); } /* 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)); + mode_sense(device, dbd, pc, SMS_ALL_PAGES_PAGE, + subpages ? SMS_SUBPAGE_ALL : 0, + retry_count, timeout, data, sizeof(data)); mh = (struct scsi_mode_header_6 *)data; len = sizeof(*mh) + mh->blk_desc_len; /* Skip block descriptors. */ /* Iterate through the pages in the reply. */ while (len < mh->data_length) { /* Locate the next mode page header. */ - mph = (struct scsi_mode_page_header *) - ((intptr_t)mh + len); - - mph->page_code &= SMS_PAGE_CODE; - nameentry = nameentry_lookup(mph->page_code); - - if (nameentry == NULL || nameentry->name == NULL) - printf("0x%02x\n", mph->page_code); - else - printf("0x%02x\t%s\n", mph->page_code, - nameentry->name); - len += mph->page_length + sizeof(*mph); + mph = (struct scsi_mode_page_header *)((intptr_t)mh + len); + + if ((mph->page_code & SMPH_SPF) == 0) { + page = mph->page_code & SMS_PAGE_CODE; + subpage = 0; + len += sizeof(*mph) + mph->page_length; + } else { + mphsp = (struct scsi_mode_page_header_sp *)mph; + page = mphsp->page_code & SMS_PAGE_CODE; + subpage = mphsp->subpage; + len += sizeof(*mphsp) + scsi_2btoul(mphsp->page_length); + } + + nameentry = nameentry_lookup(page, subpage); + if (subpage == 0) { + printf("0x%02x\t%s\n", page, + nameentry ? nameentry->name : ""); + } else { + printf("0x%02x,0x%02x\t%s\n", page, subpage, + nameentry ? nameentry->name : ""); + } } } -- cgit v1.1