17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5342440ecSPrasad Singamsetty * Common Development and Distribution License (the "License").
6342440ecSPrasad Singamsetty * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate
227c478bd9Sstevel@tonic-gate /*
23342440ecSPrasad Singamsetty * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate * This file contains functions implementing the scsi menu commands.
297c478bd9Sstevel@tonic-gate *
307c478bd9Sstevel@tonic-gate * These functions are intended for expert use only, and provide
317c478bd9Sstevel@tonic-gate * a raw access to a scsi device's mode pages. The ability to
327c478bd9Sstevel@tonic-gate * issue a raw format command is also provided, should a page be
337c478bd9Sstevel@tonic-gate * changed that requires a format.
347c478bd9Sstevel@tonic-gate */
357c478bd9Sstevel@tonic-gate #include "global.h"
367c478bd9Sstevel@tonic-gate #include <stdlib.h>
377c478bd9Sstevel@tonic-gate #include <ctype.h>
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate #include "io.h"
407c478bd9Sstevel@tonic-gate #include "menu.h"
417c478bd9Sstevel@tonic-gate #include "misc.h"
427c478bd9Sstevel@tonic-gate #include "menu_scsi.h"
437c478bd9Sstevel@tonic-gate #include "ctlr_scsi.h"
447c478bd9Sstevel@tonic-gate #include "startup.h"
453e1bd7a2Ssjelinek #include "checkdev.h"
467c478bd9Sstevel@tonic-gate
477c478bd9Sstevel@tonic-gate static int do_mode_sense(int);
487c478bd9Sstevel@tonic-gate static int do_mode_sense_all(void);
497c478bd9Sstevel@tonic-gate static int do_mode_select(struct chg_list *);
507c478bd9Sstevel@tonic-gate static int do_format(void);
517c478bd9Sstevel@tonic-gate static void do_list(void);
527c478bd9Sstevel@tonic-gate static int do_inquiry(void);
537c478bd9Sstevel@tonic-gate static void do_apply(void);
547c478bd9Sstevel@tonic-gate static void do_cancel(void);
557c478bd9Sstevel@tonic-gate static void do_display(void);
567c478bd9Sstevel@tonic-gate static int parse_change_spec(char *, char *, int, struct chg_list *);
577c478bd9Sstevel@tonic-gate static void add_new_change_list_item(struct chg_list *);
587c478bd9Sstevel@tonic-gate static void free_change_list(void);
597c478bd9Sstevel@tonic-gate static void do_default(char *);
607c478bd9Sstevel@tonic-gate static void default_all_pages(void);
617c478bd9Sstevel@tonic-gate static int default_page(int);
627c478bd9Sstevel@tonic-gate
637c478bd9Sstevel@tonic-gate /*
647c478bd9Sstevel@tonic-gate * Menu data for the SCSI menu display
657c478bd9Sstevel@tonic-gate */
667c478bd9Sstevel@tonic-gate static char *scsi_menu_strings[] = {
677c478bd9Sstevel@tonic-gate "p<n> - display a mode sense page",
687c478bd9Sstevel@tonic-gate "p<n> b<n> <op> [~]<n> - change a byte and issue mode select",
697c478bd9Sstevel@tonic-gate "b<n> <op> [~]<n> - add an operation to the mode select list",
707c478bd9Sstevel@tonic-gate " for the current page",
717c478bd9Sstevel@tonic-gate "",
727c478bd9Sstevel@tonic-gate " where: p<n> specifies the page with page code <n>",
737c478bd9Sstevel@tonic-gate " b<n> specifies byte <n> of the page",
747c478bd9Sstevel@tonic-gate " <op> can be one of the following operators:",
757c478bd9Sstevel@tonic-gate " = (set specified value)",
767c478bd9Sstevel@tonic-gate " |= (bitwise OR with current value)",
777c478bd9Sstevel@tonic-gate " &= (bitwise AND with current value)",
787c478bd9Sstevel@tonic-gate " <n> can be a decimal value in the range 0-255,",
797c478bd9Sstevel@tonic-gate " or two hexadecimal digits, in the form 0x<xx>.",
807c478bd9Sstevel@tonic-gate " [~] complements the specified value",
817c478bd9Sstevel@tonic-gate "",
827c478bd9Sstevel@tonic-gate "apply - apply mode select list",
837c478bd9Sstevel@tonic-gate "cancel - cancel mode select list",
847c478bd9Sstevel@tonic-gate "display - display mode select list",
857c478bd9Sstevel@tonic-gate "all - display all supported mode sense pages",
867c478bd9Sstevel@tonic-gate "default p<n> - mode select page <n> to default values",
877c478bd9Sstevel@tonic-gate "default all - mode select all pages to default values",
887c478bd9Sstevel@tonic-gate "format - format without standard mode selects",
897c478bd9Sstevel@tonic-gate "inquiry - display device's inquiry response",
907c478bd9Sstevel@tonic-gate "list - list common SCSI-2 mode pages",
917c478bd9Sstevel@tonic-gate "!<cmd> - execute <cmd> , then return"
927c478bd9Sstevel@tonic-gate };
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate #define N_SCSI_STRINGS (sizeof (scsi_menu_strings) / sizeof (char *))
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate /*
977c478bd9Sstevel@tonic-gate * Command types
987c478bd9Sstevel@tonic-gate */
997c478bd9Sstevel@tonic-gate #define CMD_ALL 0
1007c478bd9Sstevel@tonic-gate #define CMD_FORMAT 1
1017c478bd9Sstevel@tonic-gate #define CMD_QUIT 2
1027c478bd9Sstevel@tonic-gate #define CMD_HELP 3
1037c478bd9Sstevel@tonic-gate #define CMD_LIST 4
1047c478bd9Sstevel@tonic-gate #define CMD_INQUIRY 5
1057c478bd9Sstevel@tonic-gate #define CMD_APPLY 6
1067c478bd9Sstevel@tonic-gate #define CMD_CANCEL 7
1077c478bd9Sstevel@tonic-gate #define CMD_DISPLAY 8
1087c478bd9Sstevel@tonic-gate
1097c478bd9Sstevel@tonic-gate /*
1107c478bd9Sstevel@tonic-gate * SCSI menu commands for minimum recognition
1117c478bd9Sstevel@tonic-gate */
1127c478bd9Sstevel@tonic-gate static struct slist cmds_list[] = {
1137c478bd9Sstevel@tonic-gate { "all", NULL, CMD_ALL },
1147c478bd9Sstevel@tonic-gate { "format", NULL, CMD_FORMAT },
1157c478bd9Sstevel@tonic-gate { "quit", NULL, CMD_QUIT },
1167c478bd9Sstevel@tonic-gate { "help", NULL, CMD_HELP },
1177c478bd9Sstevel@tonic-gate { "?", NULL, CMD_HELP },
1187c478bd9Sstevel@tonic-gate { "list", NULL, CMD_LIST },
1197c478bd9Sstevel@tonic-gate { "inquiry", NULL, CMD_INQUIRY },
1207c478bd9Sstevel@tonic-gate { "apply", NULL, CMD_APPLY },
1217c478bd9Sstevel@tonic-gate { "cancel", NULL, CMD_CANCEL },
1227c478bd9Sstevel@tonic-gate { "display", NULL, CMD_DISPLAY },
1237c478bd9Sstevel@tonic-gate { NULL }
1247c478bd9Sstevel@tonic-gate };
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gate /*
1277c478bd9Sstevel@tonic-gate * Implied page for mode select change lists
1287c478bd9Sstevel@tonic-gate */
1297c478bd9Sstevel@tonic-gate static int current_page;
1307c478bd9Sstevel@tonic-gate static struct chg_list *change_list;
1317c478bd9Sstevel@tonic-gate
1327c478bd9Sstevel@tonic-gate /*
1337c478bd9Sstevel@tonic-gate * Manage the SCSI menu.
1347c478bd9Sstevel@tonic-gate * Parse input and dispatch to the appropriate functions.
1357c478bd9Sstevel@tonic-gate * The commands we accept are not simple one-word commands,
1367c478bd9Sstevel@tonic-gate * so we cannot use the standard format menu-handling functions.
1377c478bd9Sstevel@tonic-gate */
1387c478bd9Sstevel@tonic-gate int
c_scsi(void)139*b12aaafbSToomas Soome c_scsi(void)
1407c478bd9Sstevel@tonic-gate {
1417c478bd9Sstevel@tonic-gate int i;
1427c478bd9Sstevel@tonic-gate struct env env;
1437c478bd9Sstevel@tonic-gate char **menu;
1447c478bd9Sstevel@tonic-gate struct menu_item scsi_menu[N_SCSI_STRINGS+1];
1457c478bd9Sstevel@tonic-gate struct chg_list change_item;
1467c478bd9Sstevel@tonic-gate struct chg_list *chg_item;
1477c478bd9Sstevel@tonic-gate char s[MAXPATHLEN], nclean[MAXPATHLEN];
1487c478bd9Sstevel@tonic-gate char *p;
1497c478bd9Sstevel@tonic-gate char *p2;
1507c478bd9Sstevel@tonic-gate int cmd;
1517c478bd9Sstevel@tonic-gate int pageno;
1527c478bd9Sstevel@tonic-gate int help = 1;
1537c478bd9Sstevel@tonic-gate
1547c478bd9Sstevel@tonic-gate /*
1557c478bd9Sstevel@tonic-gate * Warn casual users that maybe they should not be
1567c478bd9Sstevel@tonic-gate * using this menu.
1577c478bd9Sstevel@tonic-gate */
1587c478bd9Sstevel@tonic-gate fmt_print("\n"
1597c478bd9Sstevel@tonic-gate "Warning: these functions are intended for expert use only, for\n"
1607c478bd9Sstevel@tonic-gate "debugging disk devices and for unusual configuration settings.\n"
1617c478bd9Sstevel@tonic-gate "It is recommended that you do not use this menu for normal disk\n"
1627c478bd9Sstevel@tonic-gate "configuration and formatting, unless you have explicit instructions,\n"
1637c478bd9Sstevel@tonic-gate "or know exactly what you are doing.\n");
1647c478bd9Sstevel@tonic-gate
1657c478bd9Sstevel@tonic-gate /*
1667c478bd9Sstevel@tonic-gate * Initialize change list and current page to empty
1677c478bd9Sstevel@tonic-gate */
1687c478bd9Sstevel@tonic-gate current_page = -1;
1697c478bd9Sstevel@tonic-gate change_list = NULL;
1707c478bd9Sstevel@tonic-gate
1717c478bd9Sstevel@tonic-gate /*
1727c478bd9Sstevel@tonic-gate * Build and display the menu.
1737c478bd9Sstevel@tonic-gate * we only use this for display purposes.
1747c478bd9Sstevel@tonic-gate */
1757c478bd9Sstevel@tonic-gate for (i = 0; i < N_SCSI_STRINGS; i++) {
1767c478bd9Sstevel@tonic-gate scsi_menu[i].menu_cmd = scsi_menu_strings[i];
1777c478bd9Sstevel@tonic-gate scsi_menu[i].menu_func = NULL;
1787c478bd9Sstevel@tonic-gate scsi_menu[i].menu_state = true;
1797c478bd9Sstevel@tonic-gate }
1807c478bd9Sstevel@tonic-gate scsi_menu[i].menu_cmd = NULL;
1817c478bd9Sstevel@tonic-gate menu = create_menu_list(scsi_menu);
1827c478bd9Sstevel@tonic-gate /*
1837c478bd9Sstevel@tonic-gate * Save the environment so a ctrl-C out of a command lands here.
1847c478bd9Sstevel@tonic-gate */
1857c478bd9Sstevel@tonic-gate saveenv(env);
1867c478bd9Sstevel@tonic-gate for (;;) {
1877c478bd9Sstevel@tonic-gate if (help) {
1887c478bd9Sstevel@tonic-gate help = 0;
1897c478bd9Sstevel@tonic-gate fmt_print("\n\nSCSI MENU:\n");
1907c478bd9Sstevel@tonic-gate display_menu_list(menu);
1917c478bd9Sstevel@tonic-gate }
1927c478bd9Sstevel@tonic-gate /*
1937c478bd9Sstevel@tonic-gate * Prompt and get next input line. We don't use the
1947c478bd9Sstevel@tonic-gate * standard input routine, since we need a little
1957c478bd9Sstevel@tonic-gate * more flexibility in parsing the input.
1967c478bd9Sstevel@tonic-gate */
1977c478bd9Sstevel@tonic-gate fmt_print("scsi> ");
1987c478bd9Sstevel@tonic-gate get_inputline(nclean, sizeof (nclean));
1997c478bd9Sstevel@tonic-gate
2007c478bd9Sstevel@tonic-gate clean_token(s, nclean);
2017c478bd9Sstevel@tonic-gate
2027c478bd9Sstevel@tonic-gate /*
2037c478bd9Sstevel@tonic-gate * Mark the saved environment active so the user can now
2047c478bd9Sstevel@tonic-gate * do a ctrl-C to get out of the command.
2057c478bd9Sstevel@tonic-gate */
2067c478bd9Sstevel@tonic-gate useenv();
2077c478bd9Sstevel@tonic-gate
2087c478bd9Sstevel@tonic-gate /*
2097c478bd9Sstevel@tonic-gate * Figure out what the user chose
2107c478bd9Sstevel@tonic-gate */
2117c478bd9Sstevel@tonic-gate i = find_value(cmds_list, s, &cmd);
2127c478bd9Sstevel@tonic-gate if (i == 1) {
2137c478bd9Sstevel@tonic-gate switch (cmd) {
2147c478bd9Sstevel@tonic-gate case CMD_ALL:
2157c478bd9Sstevel@tonic-gate (void) do_mode_sense_all();
2167c478bd9Sstevel@tonic-gate break;
2177c478bd9Sstevel@tonic-gate case CMD_FORMAT:
2187c478bd9Sstevel@tonic-gate (void) do_format();
2197c478bd9Sstevel@tonic-gate break;
2207c478bd9Sstevel@tonic-gate case CMD_QUIT:
2217c478bd9Sstevel@tonic-gate goto exit;
2227c478bd9Sstevel@tonic-gate /*NOTREACHED*/
2237c478bd9Sstevel@tonic-gate case CMD_HELP:
2247c478bd9Sstevel@tonic-gate fmt_print("\n\nSCSI MENU:\n");
2257c478bd9Sstevel@tonic-gate display_menu_list(menu);
2267c478bd9Sstevel@tonic-gate break;
2277c478bd9Sstevel@tonic-gate case CMD_LIST:
2287c478bd9Sstevel@tonic-gate do_list();
2297c478bd9Sstevel@tonic-gate break;
2307c478bd9Sstevel@tonic-gate case CMD_INQUIRY:
2317c478bd9Sstevel@tonic-gate (void) do_inquiry();
2327c478bd9Sstevel@tonic-gate break;
2337c478bd9Sstevel@tonic-gate case CMD_APPLY:
2347c478bd9Sstevel@tonic-gate do_apply();
2357c478bd9Sstevel@tonic-gate break;
2367c478bd9Sstevel@tonic-gate case CMD_CANCEL:
2377c478bd9Sstevel@tonic-gate do_cancel();
2387c478bd9Sstevel@tonic-gate break;
2397c478bd9Sstevel@tonic-gate case CMD_DISPLAY:
2407c478bd9Sstevel@tonic-gate do_display();
2417c478bd9Sstevel@tonic-gate break;
2427c478bd9Sstevel@tonic-gate }
2437c478bd9Sstevel@tonic-gate } else if (s[0] == 'd') {
2447c478bd9Sstevel@tonic-gate do_default(s);
2457c478bd9Sstevel@tonic-gate } else if (s[0] == 'p') {
2467c478bd9Sstevel@tonic-gate p = s + 1;
2477c478bd9Sstevel@tonic-gate pageno = (int)strtol(p, &p2, 0);
2487c478bd9Sstevel@tonic-gate if (p2 == p) {
2497c478bd9Sstevel@tonic-gate err_print("Syntax error: %s\n", s);
2507c478bd9Sstevel@tonic-gate goto error;
2517c478bd9Sstevel@tonic-gate }
2527c478bd9Sstevel@tonic-gate current_page = pageno;
2537c478bd9Sstevel@tonic-gate for (p = p2; *p == ' '; p++)
2547c478bd9Sstevel@tonic-gate ;
2557c478bd9Sstevel@tonic-gate if (*p == 0) {
2567c478bd9Sstevel@tonic-gate (void) do_mode_sense(pageno);
2577c478bd9Sstevel@tonic-gate } else if (*p == 'b') {
2587c478bd9Sstevel@tonic-gate if (parse_change_spec(s, p, pageno,
259342440ecSPrasad Singamsetty &change_item)) {
2607c478bd9Sstevel@tonic-gate (void) do_mode_select(&change_item);
2617c478bd9Sstevel@tonic-gate }
2627c478bd9Sstevel@tonic-gate }
2637c478bd9Sstevel@tonic-gate } else if (s[0] == 'b') {
2647c478bd9Sstevel@tonic-gate if (current_page == -1) {
2657c478bd9Sstevel@tonic-gate err_print("\
2667c478bd9Sstevel@tonic-gate Please display the page on which you'd like to do a mode select\n");
2677c478bd9Sstevel@tonic-gate goto error;
2687c478bd9Sstevel@tonic-gate }
2697c478bd9Sstevel@tonic-gate chg_item = (struct chg_list *)
270342440ecSPrasad Singamsetty zalloc(sizeof (struct chg_list));
2717c478bd9Sstevel@tonic-gate if (parse_change_spec(s, s, current_page,
272342440ecSPrasad Singamsetty chg_item)) {
2737c478bd9Sstevel@tonic-gate add_new_change_list_item(chg_item);
2747c478bd9Sstevel@tonic-gate } else {
2757c478bd9Sstevel@tonic-gate destroy_data((char *)chg_item);
2767c478bd9Sstevel@tonic-gate }
2777c478bd9Sstevel@tonic-gate } else if (s[0] == '!') {
278f1c60556Spr (void) execute_shell(&s[1], sizeof (s) - 1);
2797c478bd9Sstevel@tonic-gate help = 1;
2807c478bd9Sstevel@tonic-gate } else if (s[0] != 0) {
2817c478bd9Sstevel@tonic-gate err_print("Syntax error: %s\n", s);
2827c478bd9Sstevel@tonic-gate }
2837c478bd9Sstevel@tonic-gate error:
2847c478bd9Sstevel@tonic-gate /*
2857c478bd9Sstevel@tonic-gate * Mark the saved environment inactive so ctrl-C doesn't
2867c478bd9Sstevel@tonic-gate * work at the menu itself.
2877c478bd9Sstevel@tonic-gate */
2887c478bd9Sstevel@tonic-gate unuseenv();
2897c478bd9Sstevel@tonic-gate }
2907c478bd9Sstevel@tonic-gate exit:
2917c478bd9Sstevel@tonic-gate /*
2927c478bd9Sstevel@tonic-gate * Clean up the environment stack and free the menu
2937c478bd9Sstevel@tonic-gate */
2947c478bd9Sstevel@tonic-gate clearenv();
2957c478bd9Sstevel@tonic-gate destroy_data((char *)menu);
2967c478bd9Sstevel@tonic-gate
2977c478bd9Sstevel@tonic-gate /*
2987c478bd9Sstevel@tonic-gate * Clean up the change list, if anything left over
2997c478bd9Sstevel@tonic-gate */
3007c478bd9Sstevel@tonic-gate free_change_list();
3017c478bd9Sstevel@tonic-gate
3027c478bd9Sstevel@tonic-gate /*
3037c478bd9Sstevel@tonic-gate * Make sure user is prompted with previous menu
3047c478bd9Sstevel@tonic-gate */
3057c478bd9Sstevel@tonic-gate last_menu++;
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate return (0);
3087c478bd9Sstevel@tonic-gate }
3097c478bd9Sstevel@tonic-gate
3107c478bd9Sstevel@tonic-gate
3117c478bd9Sstevel@tonic-gate /*
3127c478bd9Sstevel@tonic-gate * Do a mode sense on a particular page, and dump the data.
3137c478bd9Sstevel@tonic-gate * Get all the various flavors: default, current, saved, changeable.
3147c478bd9Sstevel@tonic-gate */
3157c478bd9Sstevel@tonic-gate static int
do_mode_sense(int pageno)316*b12aaafbSToomas Soome do_mode_sense(int pageno)
3177c478bd9Sstevel@tonic-gate {
3187c478bd9Sstevel@tonic-gate struct scsi_ms_header header;
3197c478bd9Sstevel@tonic-gate struct mode_page *pg;
3207c478bd9Sstevel@tonic-gate char msbuf[MAX_MODE_SENSE_SIZE];
3217c478bd9Sstevel@tonic-gate int result = 0;
3227c478bd9Sstevel@tonic-gate
3237c478bd9Sstevel@tonic-gate char *default_msg = "default: ";
3247c478bd9Sstevel@tonic-gate char *saved_msg = "saved: ";
3257c478bd9Sstevel@tonic-gate char *current_msg = "current: ";
3267c478bd9Sstevel@tonic-gate char *changeable_msg = "changeable: ";
3277c478bd9Sstevel@tonic-gate
3287c478bd9Sstevel@tonic-gate
3297c478bd9Sstevel@tonic-gate pg = (struct mode_page *)msbuf;
3307c478bd9Sstevel@tonic-gate
3317c478bd9Sstevel@tonic-gate fmt_print("\nPage 0x%x:\n", pageno);
3327c478bd9Sstevel@tonic-gate if (uscsi_mode_sense(cur_file, pageno, MODE_SENSE_PC_DEFAULT,
333*b12aaafbSToomas Soome msbuf, MAX_MODE_SENSE_SIZE, &header)) {
3347c478bd9Sstevel@tonic-gate err_print("%sfailed\n", default_msg);
3357c478bd9Sstevel@tonic-gate result = 1;
3367c478bd9Sstevel@tonic-gate } else {
337*b12aaafbSToomas Soome dump(default_msg, msbuf, MODESENSE_PAGE_LEN(pg), HEX_ONLY);
3387c478bd9Sstevel@tonic-gate }
3397c478bd9Sstevel@tonic-gate
3407c478bd9Sstevel@tonic-gate if (uscsi_mode_sense(cur_file, pageno, MODE_SENSE_PC_CURRENT,
341*b12aaafbSToomas Soome msbuf, MAX_MODE_SENSE_SIZE, &header)) {
3427c478bd9Sstevel@tonic-gate err_print("%sfailed\n", current_msg);
3437c478bd9Sstevel@tonic-gate result = 1;
3447c478bd9Sstevel@tonic-gate } else {
345*b12aaafbSToomas Soome dump(current_msg, msbuf, MODESENSE_PAGE_LEN(pg), HEX_ONLY);
3467c478bd9Sstevel@tonic-gate }
3477c478bd9Sstevel@tonic-gate
3487c478bd9Sstevel@tonic-gate if (uscsi_mode_sense(cur_file, pageno, MODE_SENSE_PC_SAVED,
349*b12aaafbSToomas Soome msbuf, MAX_MODE_SENSE_SIZE, &header)) {
3507c478bd9Sstevel@tonic-gate err_print("%sfailed\n", saved_msg);
3517c478bd9Sstevel@tonic-gate result = 1;
3527c478bd9Sstevel@tonic-gate } else {
353*b12aaafbSToomas Soome dump(saved_msg, msbuf, MODESENSE_PAGE_LEN(pg), HEX_ONLY);
3547c478bd9Sstevel@tonic-gate }
3557c478bd9Sstevel@tonic-gate
3567c478bd9Sstevel@tonic-gate if (uscsi_mode_sense(cur_file, pageno, MODE_SENSE_PC_CHANGEABLE,
357*b12aaafbSToomas Soome msbuf, MAX_MODE_SENSE_SIZE, &header)) {
3587c478bd9Sstevel@tonic-gate err_print("%sfailed\n", changeable_msg);
3597c478bd9Sstevel@tonic-gate result = 1;
3607c478bd9Sstevel@tonic-gate } else {
361*b12aaafbSToomas Soome dump(changeable_msg, msbuf, MODESENSE_PAGE_LEN(pg), HEX_ONLY);
3627c478bd9Sstevel@tonic-gate }
3637c478bd9Sstevel@tonic-gate
3647c478bd9Sstevel@tonic-gate fmt_print("\n");
3657c478bd9Sstevel@tonic-gate return (result);
3667c478bd9Sstevel@tonic-gate }
3677c478bd9Sstevel@tonic-gate
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate /*
3707c478bd9Sstevel@tonic-gate * Dump all the pages a device supports
3717c478bd9Sstevel@tonic-gate */
3727c478bd9Sstevel@tonic-gate static int
do_mode_sense_all(void)373*b12aaafbSToomas Soome do_mode_sense_all(void)
3747c478bd9Sstevel@tonic-gate {
3757c478bd9Sstevel@tonic-gate int result = 0;
3767c478bd9Sstevel@tonic-gate
3777c478bd9Sstevel@tonic-gate if (scsi_dump_mode_sense_pages(MODE_SENSE_PC_DEFAULT)) {
3787c478bd9Sstevel@tonic-gate result = 1;
3797c478bd9Sstevel@tonic-gate }
3807c478bd9Sstevel@tonic-gate if (scsi_dump_mode_sense_pages(MODE_SENSE_PC_CURRENT)) {
3817c478bd9Sstevel@tonic-gate result = 1;
3827c478bd9Sstevel@tonic-gate }
3837c478bd9Sstevel@tonic-gate if (scsi_dump_mode_sense_pages(MODE_SENSE_PC_SAVED)) {
3847c478bd9Sstevel@tonic-gate result = 1;
3857c478bd9Sstevel@tonic-gate }
3867c478bd9Sstevel@tonic-gate if (scsi_dump_mode_sense_pages(MODE_SENSE_PC_CHANGEABLE)) {
3877c478bd9Sstevel@tonic-gate result = 1;
3887c478bd9Sstevel@tonic-gate }
3897c478bd9Sstevel@tonic-gate fmt_print("\n");
3907c478bd9Sstevel@tonic-gate return (result);
3917c478bd9Sstevel@tonic-gate }
3927c478bd9Sstevel@tonic-gate
3937c478bd9Sstevel@tonic-gate
3947c478bd9Sstevel@tonic-gate /*
3957c478bd9Sstevel@tonic-gate * Get the current mode sense for a particular page, change
3967c478bd9Sstevel@tonic-gate * a byte, and issue a mode select. Note that we can only
3977c478bd9Sstevel@tonic-gate * change a value if the device indicates that those bits
3987c478bd9Sstevel@tonic-gate * are changeable.
3997c478bd9Sstevel@tonic-gate */
4007c478bd9Sstevel@tonic-gate static int
do_mode_select(struct chg_list * change_item)401*b12aaafbSToomas Soome do_mode_select(struct chg_list *change_item)
4027c478bd9Sstevel@tonic-gate {
4037c478bd9Sstevel@tonic-gate struct scsi_ms_header header;
4047c478bd9Sstevel@tonic-gate char saved[MAX_MODE_SENSE_SIZE];
4057c478bd9Sstevel@tonic-gate char changeable[MAX_MODE_SENSE_SIZE];
4067c478bd9Sstevel@tonic-gate struct mode_page *pg;
4077c478bd9Sstevel@tonic-gate struct mode_page *pg2;
4087c478bd9Sstevel@tonic-gate int length;
4097c478bd9Sstevel@tonic-gate int pageno;
4107c478bd9Sstevel@tonic-gate int flags;
4117c478bd9Sstevel@tonic-gate int result = 0;
4127c478bd9Sstevel@tonic-gate
4137c478bd9Sstevel@tonic-gate pageno = change_item->pageno;
4147c478bd9Sstevel@tonic-gate
4157c478bd9Sstevel@tonic-gate /*
4167c478bd9Sstevel@tonic-gate * Get changeable mode sense
4177c478bd9Sstevel@tonic-gate */
4187c478bd9Sstevel@tonic-gate if (uscsi_mode_sense(cur_file, pageno, MODE_SENSE_PC_CHANGEABLE,
419*b12aaafbSToomas Soome changeable, MAX_MODE_SENSE_SIZE, &header)) {
4207c478bd9Sstevel@tonic-gate err_print("Mode sense on page %x (changeable) failed\n",
421*b12aaafbSToomas Soome pageno);
4227c478bd9Sstevel@tonic-gate return (1);
4237c478bd9Sstevel@tonic-gate }
4247c478bd9Sstevel@tonic-gate
4257c478bd9Sstevel@tonic-gate /*
4267c478bd9Sstevel@tonic-gate * Get saved mode sense. If saved fails, use current values.
4277c478bd9Sstevel@tonic-gate */
4287c478bd9Sstevel@tonic-gate if (uscsi_mode_sense(cur_file, pageno, MODE_SENSE_PC_SAVED,
429*b12aaafbSToomas Soome saved, MAX_MODE_SENSE_SIZE, &header)) {
430*b12aaafbSToomas Soome err_print("Mode sense on page %x (saved) failed\n", pageno);
4317c478bd9Sstevel@tonic-gate if (uscsi_mode_sense(cur_file, pageno, MODE_SENSE_PC_CURRENT,
432*b12aaafbSToomas Soome saved, MAX_MODE_SENSE_SIZE, &header)) {
4337c478bd9Sstevel@tonic-gate err_print("Mode sense on page %x (current) failed\n",
434*b12aaafbSToomas Soome pageno);
4357c478bd9Sstevel@tonic-gate return (1);
4367c478bd9Sstevel@tonic-gate } else {
4377c478bd9Sstevel@tonic-gate err_print("Using current values instead\n");
4387c478bd9Sstevel@tonic-gate }
4397c478bd9Sstevel@tonic-gate }
4407c478bd9Sstevel@tonic-gate
4417c478bd9Sstevel@tonic-gate /*
4427c478bd9Sstevel@tonic-gate * Use the intersection of the saved and changeable
4437c478bd9Sstevel@tonic-gate */
4447c478bd9Sstevel@tonic-gate pg = (struct mode_page *)saved;
4457c478bd9Sstevel@tonic-gate pg2 = (struct mode_page *)changeable;
4467c478bd9Sstevel@tonic-gate length = min(MODESENSE_PAGE_LEN(pg), MODESENSE_PAGE_LEN(pg2));
4477c478bd9Sstevel@tonic-gate
4487c478bd9Sstevel@tonic-gate /*
4497c478bd9Sstevel@tonic-gate * Try making this change to this page
4507c478bd9Sstevel@tonic-gate */
4517c478bd9Sstevel@tonic-gate if (apply_chg_list(pageno, length, (uchar_t *)saved,
452*b12aaafbSToomas Soome (uchar_t *)changeable, change_item)) {
4537c478bd9Sstevel@tonic-gate /*
4547c478bd9Sstevel@tonic-gate * A change was made. Do a mode select
4557c478bd9Sstevel@tonic-gate * We always want to set the Page Format bit.
4567c478bd9Sstevel@tonic-gate * Set the Save Page bit if the drive indicates
4577c478bd9Sstevel@tonic-gate * that it can save this page.
4587c478bd9Sstevel@tonic-gate */
4597c478bd9Sstevel@tonic-gate flags = MODE_SELECT_PF;
4607c478bd9Sstevel@tonic-gate if (pg->ps) {
4617c478bd9Sstevel@tonic-gate flags |= MODE_SELECT_SP;
4627c478bd9Sstevel@tonic-gate }
4637c478bd9Sstevel@tonic-gate pg->ps = 0;
4647c478bd9Sstevel@tonic-gate header.mode_header.length = 0;
4657c478bd9Sstevel@tonic-gate header.mode_header.device_specific = 0;
4667c478bd9Sstevel@tonic-gate if (uscsi_mode_select(cur_file, pageno, flags,
467*b12aaafbSToomas Soome saved, length, &header)) {
4687c478bd9Sstevel@tonic-gate /*
4697c478bd9Sstevel@tonic-gate * Failed - try not saving parameters,
4707c478bd9Sstevel@tonic-gate * if possible.
4717c478bd9Sstevel@tonic-gate */
4727c478bd9Sstevel@tonic-gate if (flags & MODE_SELECT_SP) {
4737c478bd9Sstevel@tonic-gate flags &= ~MODE_SELECT_SP;
4747c478bd9Sstevel@tonic-gate if (uscsi_mode_select(cur_file, pageno,
475*b12aaafbSToomas Soome flags, saved, length, &header)) {
4767c478bd9Sstevel@tonic-gate result = 1;
4777c478bd9Sstevel@tonic-gate }
4787c478bd9Sstevel@tonic-gate } else {
4797c478bd9Sstevel@tonic-gate result = 1;
4807c478bd9Sstevel@tonic-gate }
4817c478bd9Sstevel@tonic-gate }
4827c478bd9Sstevel@tonic-gate
4837c478bd9Sstevel@tonic-gate if (result) {
4847c478bd9Sstevel@tonic-gate fmt_print("\n\
4857c478bd9Sstevel@tonic-gate Mode select on page %x failed.\n", pageno);
4867c478bd9Sstevel@tonic-gate } else if ((flags & MODE_SELECT_SP) == 0) {
4877c478bd9Sstevel@tonic-gate fmt_print("\n\
4887c478bd9Sstevel@tonic-gate Mode select on page %x ok, but unable to save change permanently.\n", pageno);
4897c478bd9Sstevel@tonic-gate } else {
4907c478bd9Sstevel@tonic-gate fmt_print("\n\
4917c478bd9Sstevel@tonic-gate Mode select on page %x ok.\n", pageno);
4927c478bd9Sstevel@tonic-gate }
4937c478bd9Sstevel@tonic-gate } else {
4947c478bd9Sstevel@tonic-gate err_print("\nDevice cannot support this change\n");
4957c478bd9Sstevel@tonic-gate }
4967c478bd9Sstevel@tonic-gate
4977c478bd9Sstevel@tonic-gate fmt_print("\n");
4987c478bd9Sstevel@tonic-gate return (result);
4997c478bd9Sstevel@tonic-gate }
5007c478bd9Sstevel@tonic-gate
5017c478bd9Sstevel@tonic-gate
5027c478bd9Sstevel@tonic-gate /*
5037c478bd9Sstevel@tonic-gate * Format a device, without any of the standard mode selects.
5047c478bd9Sstevel@tonic-gate * Ask if we should format with the P or the P&G lists.
5057c478bd9Sstevel@tonic-gate */
5067c478bd9Sstevel@tonic-gate static int
do_format(void)507*b12aaafbSToomas Soome do_format(void)
5087c478bd9Sstevel@tonic-gate {
5097c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd;
5107c478bd9Sstevel@tonic-gate union scsi_cdb cdb;
5117c478bd9Sstevel@tonic-gate struct scsi_defect_hdr defect_hdr;
5127c478bd9Sstevel@tonic-gate int status;
5137c478bd9Sstevel@tonic-gate u_ioparam_t ioparam;
5147c478bd9Sstevel@tonic-gate int deflt;
5157c478bd9Sstevel@tonic-gate int grown_list;
5167c478bd9Sstevel@tonic-gate
5177c478bd9Sstevel@tonic-gate fmt_print("\n");
5187c478bd9Sstevel@tonic-gate /*
5197c478bd9Sstevel@tonic-gate * Are there mounted partitions?
5207c478bd9Sstevel@tonic-gate */
521342440ecSPrasad Singamsetty if (checkmount((diskaddr_t)-1, (diskaddr_t)-1)) {
5227c478bd9Sstevel@tonic-gate err_print("Cannot format disk with mounted partitions\n\n");
5237c478bd9Sstevel@tonic-gate return (-1);
5247c478bd9Sstevel@tonic-gate }
5257c478bd9Sstevel@tonic-gate
5267c478bd9Sstevel@tonic-gate /*
5277c478bd9Sstevel@tonic-gate * Is any of the partitions being used for swapping.
5287c478bd9Sstevel@tonic-gate */
529342440ecSPrasad Singamsetty if (checkswap((diskaddr_t)-1, (diskaddr_t)-1)) {
5307c478bd9Sstevel@tonic-gate err_print("Cannot format disk while its partitions are \
5317c478bd9Sstevel@tonic-gate currently being used for swapping.\n\n");
5327c478bd9Sstevel@tonic-gate return (-1);
5337c478bd9Sstevel@tonic-gate }
5343e1bd7a2Ssjelinek /*
5353e1bd7a2Ssjelinek * Are any being used for SVM, VxVM or live upgrade.
5363e1bd7a2Ssjelinek */
5373e1bd7a2Ssjelinek if (checkdevinuse(cur_disk->disk_name, (diskaddr_t)-1,
5383e1bd7a2Ssjelinek (diskaddr_t)-1, 0, 0)) {
5393e1bd7a2Ssjelinek err_print("Cannot format disk while its partitions are "
5403e1bd7a2Ssjelinek "currently being used as described.\n");
5413e1bd7a2Ssjelinek return (-1);
5423e1bd7a2Ssjelinek }
5437c478bd9Sstevel@tonic-gate
5447c478bd9Sstevel@tonic-gate /*
5457c478bd9Sstevel@tonic-gate * Let the user choose between formatting with either
5467c478bd9Sstevel@tonic-gate * the P, or the P&G lists. Note that yes is 0, no is 1.
5477c478bd9Sstevel@tonic-gate */
5487c478bd9Sstevel@tonic-gate deflt = 0;
5497c478bd9Sstevel@tonic-gate ioparam.io_charlist = confirm_list;
5507c478bd9Sstevel@tonic-gate grown_list = !input(FIO_MSTR, "Format with the Grown Defects list",
551342440ecSPrasad Singamsetty '?', &ioparam, &deflt, DATA_INPUT);
5527c478bd9Sstevel@tonic-gate
5537c478bd9Sstevel@tonic-gate /*
5547c478bd9Sstevel@tonic-gate * Construct the uscsi format ioctl.
5557c478bd9Sstevel@tonic-gate * To format with the P and G list, we set the fmtData
5567c478bd9Sstevel@tonic-gate * and cmpLst bits to zero. To format with just the
5577c478bd9Sstevel@tonic-gate * P list, we set the fmtData bit (meaning that we will
5587c478bd9Sstevel@tonic-gate * send down a defect list in the data phase) and the
5597c478bd9Sstevel@tonic-gate * cmpLst bit (meaning that the list we send is the
5607c478bd9Sstevel@tonic-gate * complete G list), and a defect list header with
5617c478bd9Sstevel@tonic-gate * a defect list length of zero.
5627c478bd9Sstevel@tonic-gate */
5637c478bd9Sstevel@tonic-gate (void) memset((char *)&ucmd, 0, sizeof (ucmd));
5647c478bd9Sstevel@tonic-gate (void) memset((char *)&cdb, 0, sizeof (union scsi_cdb));
5657c478bd9Sstevel@tonic-gate cdb.scc_cmd = SCMD_FORMAT;
5667c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
5677c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0;
5687c478bd9Sstevel@tonic-gate if (!grown_list) {
5697c478bd9Sstevel@tonic-gate /*
5707c478bd9Sstevel@tonic-gate * No G list. Send empty defect list to replace it.
5717c478bd9Sstevel@tonic-gate */
5727c478bd9Sstevel@tonic-gate cdb.cdb_opaque[1] = FPB_DATA | FPB_CMPLT | FPB_BFI;
5737c478bd9Sstevel@tonic-gate (void) memset((char *)&defect_hdr, 0, sizeof (defect_hdr));
5747c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = (caddr_t)&defect_hdr;
5757c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = sizeof (defect_hdr);
5767c478bd9Sstevel@tonic-gate }
5777c478bd9Sstevel@tonic-gate
5787c478bd9Sstevel@tonic-gate /*
5797c478bd9Sstevel@tonic-gate * Issue the format ioctl
5807c478bd9Sstevel@tonic-gate */
5817c478bd9Sstevel@tonic-gate fmt_print("Formatting...\n");
5827c478bd9Sstevel@tonic-gate (void) fflush(stdout);
5837c478bd9Sstevel@tonic-gate status = uscsi_cmd(cur_file, &ucmd, F_NORMAL);
5847c478bd9Sstevel@tonic-gate fmt_print(status ? "Format failed\n\n" : "Format ok\n\n");
5857c478bd9Sstevel@tonic-gate return (status);
5867c478bd9Sstevel@tonic-gate }
5877c478bd9Sstevel@tonic-gate
5887c478bd9Sstevel@tonic-gate
5897c478bd9Sstevel@tonic-gate /*
5907c478bd9Sstevel@tonic-gate * List common SCSI-2 mode pages
5917c478bd9Sstevel@tonic-gate */
5927c478bd9Sstevel@tonic-gate static void
do_list(void)593*b12aaafbSToomas Soome do_list(void)
5947c478bd9Sstevel@tonic-gate {
5957c478bd9Sstevel@tonic-gate fmt_print("\n\
5967c478bd9Sstevel@tonic-gate Common SCSI-2 pages applicable to direct-access devices:\n\n");
5977c478bd9Sstevel@tonic-gate fmt_print("Page 0x1 - Read-Write Error Recovery Page\n");
5987c478bd9Sstevel@tonic-gate fmt_print("Page 0x2 - Disconnect-Reconnect Page\n");
5997c478bd9Sstevel@tonic-gate fmt_print("Page 0x3 - Format Device Page\n");
6007c478bd9Sstevel@tonic-gate fmt_print("Page 0x4 - Rigid Disk Geometry Page\n");
6017c478bd9Sstevel@tonic-gate fmt_print("Page 0x7 - Verify Error Recovery Page\n");
6027c478bd9Sstevel@tonic-gate fmt_print("Page 0x8 - Caching Page\n");
6037c478bd9Sstevel@tonic-gate fmt_print("Page 0xA - Control Mode Page\n");
6047c478bd9Sstevel@tonic-gate fmt_print("\n");
6057c478bd9Sstevel@tonic-gate }
6067c478bd9Sstevel@tonic-gate
6077c478bd9Sstevel@tonic-gate
6087c478bd9Sstevel@tonic-gate /*
6097c478bd9Sstevel@tonic-gate * Labels for the various fields of the scsi_inquiry structure
6107c478bd9Sstevel@tonic-gate */
6117c478bd9Sstevel@tonic-gate static char *scsi_inquiry_labels[] = {
6127c478bd9Sstevel@tonic-gate "Vendor: ",
6137c478bd9Sstevel@tonic-gate "Product: ",
6147c478bd9Sstevel@tonic-gate "Revision: ",
6157c478bd9Sstevel@tonic-gate "Removable media: ",
6167c478bd9Sstevel@tonic-gate "Device type: ",
6177c478bd9Sstevel@tonic-gate "ISO version: ",
6187c478bd9Sstevel@tonic-gate "ECMA version: ",
6197c478bd9Sstevel@tonic-gate "ANSI version: ",
6207c478bd9Sstevel@tonic-gate "Async event notification: ",
6217c478bd9Sstevel@tonic-gate "Terminate i/o process msg: ",
6227c478bd9Sstevel@tonic-gate "Response data format: ",
6237c478bd9Sstevel@tonic-gate "Additional length: ",
6247c478bd9Sstevel@tonic-gate "Relative addressing: ",
6257c478bd9Sstevel@tonic-gate "32 bit transfers: ",
6267c478bd9Sstevel@tonic-gate "16 bit transfers: ",
6277c478bd9Sstevel@tonic-gate "Synchronous transfers: ",
6287c478bd9Sstevel@tonic-gate "Linked commands: ",
6297c478bd9Sstevel@tonic-gate "Command queueing: ",
6307c478bd9Sstevel@tonic-gate "Soft reset option: "
6317c478bd9Sstevel@tonic-gate };
6327c478bd9Sstevel@tonic-gate
6337c478bd9Sstevel@tonic-gate
6347c478bd9Sstevel@tonic-gate /*
6357c478bd9Sstevel@tonic-gate * Dump the full inquiry as returned by the device
6367c478bd9Sstevel@tonic-gate */
6377c478bd9Sstevel@tonic-gate static int
do_inquiry(void)638*b12aaafbSToomas Soome do_inquiry(void)
6397c478bd9Sstevel@tonic-gate {
6407c478bd9Sstevel@tonic-gate char inqbuf[255];
6417c478bd9Sstevel@tonic-gate struct scsi_inquiry *inq;
6427c478bd9Sstevel@tonic-gate char **p;
6437c478bd9Sstevel@tonic-gate
6447c478bd9Sstevel@tonic-gate inq = (struct scsi_inquiry *)inqbuf;
6457c478bd9Sstevel@tonic-gate
6467c478bd9Sstevel@tonic-gate if (uscsi_inquiry(cur_file, inqbuf, sizeof (inqbuf))) {
6477c478bd9Sstevel@tonic-gate err_print("\nInquiry failed\n");
6487c478bd9Sstevel@tonic-gate return (1);
6497c478bd9Sstevel@tonic-gate }
6507c478bd9Sstevel@tonic-gate
6517c478bd9Sstevel@tonic-gate fmt_print("\nInquiry:\n");
6527c478bd9Sstevel@tonic-gate /*
6537c478bd9Sstevel@tonic-gate * The SCSI-2 spec defines "Additional length" as (n-4) bytes,
6547c478bd9Sstevel@tonic-gate * where n is the last byte of the INQUIRY data. Thus
6557c478bd9Sstevel@tonic-gate * there are n+1 bytes of INQUIRY data. We need to add 5 to
6567c478bd9Sstevel@tonic-gate * inq_len in order to get all the INQUIRY data.
6577c478bd9Sstevel@tonic-gate */
6587c478bd9Sstevel@tonic-gate dump(" ", inqbuf, inq->inq_len + 5, HEX_ASCII);
6597c478bd9Sstevel@tonic-gate fmt_print("\n");
6607c478bd9Sstevel@tonic-gate
6617c478bd9Sstevel@tonic-gate p = scsi_inquiry_labels;
6627c478bd9Sstevel@tonic-gate
6637c478bd9Sstevel@tonic-gate fmt_print("%s", *p++);
6647c478bd9Sstevel@tonic-gate print_buf(inq->inq_vid, sizeof (inq->inq_vid));
6657c478bd9Sstevel@tonic-gate fmt_print("\n%s", *p++);
6667c478bd9Sstevel@tonic-gate print_buf(inq->inq_pid, sizeof (inq->inq_pid));
6677c478bd9Sstevel@tonic-gate fmt_print("\n%s", *p++);
6687c478bd9Sstevel@tonic-gate print_buf(inq->inq_revision, sizeof (inq->inq_revision));
6697c478bd9Sstevel@tonic-gate
6707c478bd9Sstevel@tonic-gate fmt_print("\n%s%s\n", *p++, inq->inq_rmb ? "yes" : "no");
6717c478bd9Sstevel@tonic-gate fmt_print("%s%d\n", *p++, inq->inq_qual);
6727c478bd9Sstevel@tonic-gate fmt_print("%s%d\n", *p++, inq->inq_iso);
6737c478bd9Sstevel@tonic-gate fmt_print("%s%d\n", *p++, inq->inq_ecma);
6747c478bd9Sstevel@tonic-gate fmt_print("%s%d\n", *p++, inq->inq_ansi);
6757c478bd9Sstevel@tonic-gate fmt_print("%s%s\n", *p++, inq->inq_aenc ? "yes" : "no");
6767c478bd9Sstevel@tonic-gate fmt_print("%s%s\n", *p++, inq->inq_trmiop ? "yes" : "no");
6777c478bd9Sstevel@tonic-gate fmt_print("%s%d\n", *p++, inq->inq_rdf);
6787c478bd9Sstevel@tonic-gate fmt_print("%s%d\n", *p++, inq->inq_len);
6797c478bd9Sstevel@tonic-gate fmt_print("%s%s\n", *p++, inq->inq_reladdr ? "yes" : "no");
6807c478bd9Sstevel@tonic-gate fmt_print("%s%s\n", *p++, inq->inq_wbus32 ? "yes" : "no");
6817c478bd9Sstevel@tonic-gate fmt_print("%s%s\n", *p++, inq->inq_wbus16 ? "yes" : "no");
6827c478bd9Sstevel@tonic-gate fmt_print("%s%s\n", *p++, inq->inq_sync ? "yes" : "no");
6837c478bd9Sstevel@tonic-gate fmt_print("%s%s\n", *p++, inq->inq_linked ? "yes" : "no");
6847c478bd9Sstevel@tonic-gate fmt_print("%s%s\n", *p++, inq->inq_cmdque ? "yes" : "no");
6857c478bd9Sstevel@tonic-gate fmt_print("%s%s\n", *p++, inq->inq_sftre ? "yes" : "no");
6867c478bd9Sstevel@tonic-gate
6877c478bd9Sstevel@tonic-gate fmt_print("\n");
6887c478bd9Sstevel@tonic-gate return (0);
6897c478bd9Sstevel@tonic-gate }
6907c478bd9Sstevel@tonic-gate
6917c478bd9Sstevel@tonic-gate
6927c478bd9Sstevel@tonic-gate static void
do_apply(void)693*b12aaafbSToomas Soome do_apply(void)
6947c478bd9Sstevel@tonic-gate {
6957c478bd9Sstevel@tonic-gate if (change_list == NULL) {
6967c478bd9Sstevel@tonic-gate fmt_print("\nlist empty.\n");
6977c478bd9Sstevel@tonic-gate } else {
6987c478bd9Sstevel@tonic-gate (void) do_mode_select(change_list);
6997c478bd9Sstevel@tonic-gate free_change_list();
7007c478bd9Sstevel@tonic-gate }
7017c478bd9Sstevel@tonic-gate }
7027c478bd9Sstevel@tonic-gate
7037c478bd9Sstevel@tonic-gate
7047c478bd9Sstevel@tonic-gate static void
do_cancel(void)705*b12aaafbSToomas Soome do_cancel(void)
7067c478bd9Sstevel@tonic-gate {
7077c478bd9Sstevel@tonic-gate if (change_list == NULL) {
7087c478bd9Sstevel@tonic-gate fmt_print("\nlist empty.\n");
7097c478bd9Sstevel@tonic-gate } else {
7107c478bd9Sstevel@tonic-gate free_change_list();
7117c478bd9Sstevel@tonic-gate }
7127c478bd9Sstevel@tonic-gate }
7137c478bd9Sstevel@tonic-gate
7147c478bd9Sstevel@tonic-gate
7157c478bd9Sstevel@tonic-gate static void
do_display(void)716*b12aaafbSToomas Soome do_display(void)
7177c478bd9Sstevel@tonic-gate {
7187c478bd9Sstevel@tonic-gate struct chg_list *cp;
7197c478bd9Sstevel@tonic-gate
7207c478bd9Sstevel@tonic-gate if (change_list == NULL) {
7217c478bd9Sstevel@tonic-gate fmt_print("\nlist empty.\n");
7227c478bd9Sstevel@tonic-gate } else {
7237c478bd9Sstevel@tonic-gate fmt_print("\nPage 0x%x\n", current_page);
7247c478bd9Sstevel@tonic-gate for (cp = change_list; cp != NULL; cp = cp->next) {
7257c478bd9Sstevel@tonic-gate fmt_print(" b0x%x ", cp->byteno);
7267c478bd9Sstevel@tonic-gate switch (cp->mode) {
7277c478bd9Sstevel@tonic-gate case CHG_MODE_ABS:
7287c478bd9Sstevel@tonic-gate fmt_print("= 0x%x\n", cp->value);
7297c478bd9Sstevel@tonic-gate break;
7307c478bd9Sstevel@tonic-gate case CHG_MODE_SET:
7317c478bd9Sstevel@tonic-gate fmt_print("|= 0x%x\n", cp->value);
7327c478bd9Sstevel@tonic-gate break;
7337c478bd9Sstevel@tonic-gate case CHG_MODE_CLR:
7347c478bd9Sstevel@tonic-gate fmt_print("&= ~0x%x\n",
735342440ecSPrasad Singamsetty (~(cp->value)) & 0xff);
7367c478bd9Sstevel@tonic-gate break;
7377c478bd9Sstevel@tonic-gate default:
7387c478bd9Sstevel@tonic-gate impossible("do_display");
7397c478bd9Sstevel@tonic-gate /*NOTREACHED*/
7407c478bd9Sstevel@tonic-gate }
7417c478bd9Sstevel@tonic-gate }
7427c478bd9Sstevel@tonic-gate fmt_print("\n");
7437c478bd9Sstevel@tonic-gate }
7447c478bd9Sstevel@tonic-gate }
7457c478bd9Sstevel@tonic-gate
7467c478bd9Sstevel@tonic-gate
7477c478bd9Sstevel@tonic-gate static int
parse_change_spec(char * full_input,char * input,int pageno,struct chg_list * chg_item)748*b12aaafbSToomas Soome parse_change_spec(char *full_input, char *input, int pageno,
749*b12aaafbSToomas Soome struct chg_list *chg_item)
7507c478bd9Sstevel@tonic-gate {
7517c478bd9Sstevel@tonic-gate char *p;
7527c478bd9Sstevel@tonic-gate int tilde;
7537c478bd9Sstevel@tonic-gate
7547c478bd9Sstevel@tonic-gate assert(*input == 'b');
7557c478bd9Sstevel@tonic-gate
7567c478bd9Sstevel@tonic-gate chg_item->pageno = pageno;
7577c478bd9Sstevel@tonic-gate chg_item->next = NULL;
7587c478bd9Sstevel@tonic-gate
7597c478bd9Sstevel@tonic-gate input++;
7607c478bd9Sstevel@tonic-gate chg_item->byteno = (int)strtol(input, &p, 0);
7617c478bd9Sstevel@tonic-gate if (p == input) {
7627c478bd9Sstevel@tonic-gate err_print("Syntax error: %s\n", full_input);
7637c478bd9Sstevel@tonic-gate return (0);
7647c478bd9Sstevel@tonic-gate }
7657c478bd9Sstevel@tonic-gate if (chg_item->byteno < 2) {
766*b12aaafbSToomas Soome err_print(" Unsupported byte offset: %d\n", chg_item->byteno);
7677c478bd9Sstevel@tonic-gate return (0);
7687c478bd9Sstevel@tonic-gate }
7697c478bd9Sstevel@tonic-gate for (input = p; *input == ' '; input++)
7707c478bd9Sstevel@tonic-gate ;
7717c478bd9Sstevel@tonic-gate chg_item->mode = CHG_MODE_UNDEFINED;
7727c478bd9Sstevel@tonic-gate switch (*input++) {
7737c478bd9Sstevel@tonic-gate case '=':
7747c478bd9Sstevel@tonic-gate chg_item->mode = CHG_MODE_ABS;
7757c478bd9Sstevel@tonic-gate break;
7767c478bd9Sstevel@tonic-gate case '|':
7777c478bd9Sstevel@tonic-gate if (*input++ == '=') {
7787c478bd9Sstevel@tonic-gate chg_item->mode = CHG_MODE_SET;
7797c478bd9Sstevel@tonic-gate }
7807c478bd9Sstevel@tonic-gate break;
7817c478bd9Sstevel@tonic-gate case '&':
7827c478bd9Sstevel@tonic-gate if (*input++ == '=') {
7837c478bd9Sstevel@tonic-gate chg_item->mode = CHG_MODE_CLR;
7847c478bd9Sstevel@tonic-gate }
7857c478bd9Sstevel@tonic-gate break;
7867c478bd9Sstevel@tonic-gate }
7877c478bd9Sstevel@tonic-gate if (chg_item->mode == CHG_MODE_UNDEFINED) {
7887c478bd9Sstevel@tonic-gate err_print("Syntax error: %s\n", full_input);
7897c478bd9Sstevel@tonic-gate return (0);
7907c478bd9Sstevel@tonic-gate }
7917c478bd9Sstevel@tonic-gate for (; *input == ' '; input++)
7927c478bd9Sstevel@tonic-gate ;
7937c478bd9Sstevel@tonic-gate if (*input == '~') {
7947c478bd9Sstevel@tonic-gate tilde = 1;
7957c478bd9Sstevel@tonic-gate for (input++; *input == ' '; input++)
7967c478bd9Sstevel@tonic-gate ;
7977c478bd9Sstevel@tonic-gate } else {
7987c478bd9Sstevel@tonic-gate tilde = 0;
7997c478bd9Sstevel@tonic-gate }
8007c478bd9Sstevel@tonic-gate chg_item->value = (int)strtol(input, &p, 0);
8017c478bd9Sstevel@tonic-gate if (p == input || *p != 0) {
8027c478bd9Sstevel@tonic-gate err_print("Syntax error: %s\n", full_input);
8037c478bd9Sstevel@tonic-gate return (0);
8047c478bd9Sstevel@tonic-gate }
8057c478bd9Sstevel@tonic-gate /*
8067c478bd9Sstevel@tonic-gate * Apply complement if selected.
8077c478bd9Sstevel@tonic-gate * Constrain to a byte value.
8087c478bd9Sstevel@tonic-gate */
8097c478bd9Sstevel@tonic-gate if (tilde) {
8107c478bd9Sstevel@tonic-gate chg_item->value = ~chg_item->value;
8117c478bd9Sstevel@tonic-gate }
8127c478bd9Sstevel@tonic-gate chg_item->value &= 0xff;
8137c478bd9Sstevel@tonic-gate
8147c478bd9Sstevel@tonic-gate return (1);
8157c478bd9Sstevel@tonic-gate }
8167c478bd9Sstevel@tonic-gate
8177c478bd9Sstevel@tonic-gate
8187c478bd9Sstevel@tonic-gate static void
add_new_change_list_item(struct chg_list * chg_item)819*b12aaafbSToomas Soome add_new_change_list_item(struct chg_list *chg_item)
8207c478bd9Sstevel@tonic-gate {
8217c478bd9Sstevel@tonic-gate struct chg_list *cp;
8227c478bd9Sstevel@tonic-gate
8237c478bd9Sstevel@tonic-gate if (change_list == NULL) {
8247c478bd9Sstevel@tonic-gate change_list = chg_item;
8257c478bd9Sstevel@tonic-gate } else {
8267c478bd9Sstevel@tonic-gate for (cp = change_list; cp->next != NULL; cp = cp->next)
8277c478bd9Sstevel@tonic-gate ;
8287c478bd9Sstevel@tonic-gate cp->next = chg_item;
8297c478bd9Sstevel@tonic-gate }
8307c478bd9Sstevel@tonic-gate chg_item->next = NULL;
8317c478bd9Sstevel@tonic-gate }
8327c478bd9Sstevel@tonic-gate
8337c478bd9Sstevel@tonic-gate
8347c478bd9Sstevel@tonic-gate static void
free_change_list(void)835*b12aaafbSToomas Soome free_change_list(void)
8367c478bd9Sstevel@tonic-gate {
8377c478bd9Sstevel@tonic-gate struct chg_list *cp;
8387c478bd9Sstevel@tonic-gate struct chg_list *cp2;
8397c478bd9Sstevel@tonic-gate
8407c478bd9Sstevel@tonic-gate cp = change_list;
8417c478bd9Sstevel@tonic-gate while (cp != NULL) {
8427c478bd9Sstevel@tonic-gate cp2 = cp->next;
8437c478bd9Sstevel@tonic-gate destroy_data((char *)cp);
8447c478bd9Sstevel@tonic-gate cp = cp2;
8457c478bd9Sstevel@tonic-gate }
8467c478bd9Sstevel@tonic-gate change_list = NULL;
8477c478bd9Sstevel@tonic-gate }
8487c478bd9Sstevel@tonic-gate
8497c478bd9Sstevel@tonic-gate
8507c478bd9Sstevel@tonic-gate static void
do_default(char * input)851*b12aaafbSToomas Soome do_default(char *input)
8527c478bd9Sstevel@tonic-gate {
8537c478bd9Sstevel@tonic-gate char *s = input;
8547c478bd9Sstevel@tonic-gate char *p;
8557c478bd9Sstevel@tonic-gate int n;
8567c478bd9Sstevel@tonic-gate
8577c478bd9Sstevel@tonic-gate /*
8587c478bd9Sstevel@tonic-gate * Reset current page indicator
8597c478bd9Sstevel@tonic-gate */
8607c478bd9Sstevel@tonic-gate current_page = -1;
8617c478bd9Sstevel@tonic-gate
8627c478bd9Sstevel@tonic-gate /*
8637c478bd9Sstevel@tonic-gate * Skip the leading "default" command, which we
8647c478bd9Sstevel@tonic-gate * must have, or we wouldn't have come here,
8657c478bd9Sstevel@tonic-gate * and any white space.
8667c478bd9Sstevel@tonic-gate */
8677c478bd9Sstevel@tonic-gate while (isspace(*s)) {
8687c478bd9Sstevel@tonic-gate s++;
8697c478bd9Sstevel@tonic-gate }
8707c478bd9Sstevel@tonic-gate
8717c478bd9Sstevel@tonic-gate while (*s && isascii(*s) && isalpha(*s)) {
8727c478bd9Sstevel@tonic-gate s++;
8737c478bd9Sstevel@tonic-gate }
8747c478bd9Sstevel@tonic-gate
8757c478bd9Sstevel@tonic-gate while (isspace(*s)) {
8767c478bd9Sstevel@tonic-gate s++;
8777c478bd9Sstevel@tonic-gate }
8787c478bd9Sstevel@tonic-gate
8797c478bd9Sstevel@tonic-gate /*
8807c478bd9Sstevel@tonic-gate * Subsequent modifier must be either "p<n>", or "all".
8817c478bd9Sstevel@tonic-gate */
8827c478bd9Sstevel@tonic-gate if (*s == 'p') {
8837c478bd9Sstevel@tonic-gate s++;
8847c478bd9Sstevel@tonic-gate n = (int)strtol(s, &p, 0);
8857c478bd9Sstevel@tonic-gate if (p == s || *p != 0) {
8867c478bd9Sstevel@tonic-gate err_print("Syntax error: %s\n", input);
8877c478bd9Sstevel@tonic-gate } else {
8887c478bd9Sstevel@tonic-gate fmt_print("\n");
8897c478bd9Sstevel@tonic-gate (void) default_page(n);
8907c478bd9Sstevel@tonic-gate fmt_print("\n");
8917c478bd9Sstevel@tonic-gate }
8927c478bd9Sstevel@tonic-gate } else if (*s == 'a') {
8937c478bd9Sstevel@tonic-gate default_all_pages();
8947c478bd9Sstevel@tonic-gate } else {
8957c478bd9Sstevel@tonic-gate err_print("Syntax error: %s\n", input);
8967c478bd9Sstevel@tonic-gate }
8977c478bd9Sstevel@tonic-gate }
8987c478bd9Sstevel@tonic-gate
8997c478bd9Sstevel@tonic-gate
9007c478bd9Sstevel@tonic-gate static void
default_all_pages(void)901*b12aaafbSToomas Soome default_all_pages(void)
9027c478bd9Sstevel@tonic-gate {
9037c478bd9Sstevel@tonic-gate char *p;
9047c478bd9Sstevel@tonic-gate struct mode_header *mh;
9057c478bd9Sstevel@tonic-gate struct mode_page *mp;
9067c478bd9Sstevel@tonic-gate int n;
9077c478bd9Sstevel@tonic-gate struct uscsi_cmd ucmd;
9087c478bd9Sstevel@tonic-gate union scsi_cdb cdb;
9097c478bd9Sstevel@tonic-gate char msbuf[MAX_MODE_SENSE_SIZE];
9107c478bd9Sstevel@tonic-gate int nbytes = sizeof (msbuf);
9117c478bd9Sstevel@tonic-gate int status;
9127c478bd9Sstevel@tonic-gate
9137c478bd9Sstevel@tonic-gate /*
9147c478bd9Sstevel@tonic-gate * Build and execute the uscsi ioctl. Note that
9157c478bd9Sstevel@tonic-gate * we cannot simply call uscsi_mode_sense() here,
9167c478bd9Sstevel@tonic-gate * since that function attempts to valididate the
9177c478bd9Sstevel@tonic-gate * returned data, and the page 0x3f has a unique
9187c478bd9Sstevel@tonic-gate * format.
9197c478bd9Sstevel@tonic-gate */
9207c478bd9Sstevel@tonic-gate nbytes = MAX_MODE_SENSE_SIZE;
9217c478bd9Sstevel@tonic-gate (void) memset(msbuf, 0, nbytes);
9227c478bd9Sstevel@tonic-gate (void) memset((char *)&ucmd, 0, sizeof (ucmd));
9237c478bd9Sstevel@tonic-gate (void) memset((char *)&cdb, 0, sizeof (union scsi_cdb));
9247c478bd9Sstevel@tonic-gate cdb.scc_cmd = SCMD_MODE_SENSE;
9257c478bd9Sstevel@tonic-gate FORMG0COUNT(&cdb, (uchar_t)nbytes);
9267c478bd9Sstevel@tonic-gate cdb.cdb_opaque[2] = MODE_SENSE_PC_DEFAULT | 0x3f;
9277c478bd9Sstevel@tonic-gate ucmd.uscsi_cdb = (caddr_t)&cdb;
9287c478bd9Sstevel@tonic-gate ucmd.uscsi_cdblen = CDB_GROUP0;
9297c478bd9Sstevel@tonic-gate ucmd.uscsi_bufaddr = msbuf;
9307c478bd9Sstevel@tonic-gate ucmd.uscsi_buflen = nbytes;
931342440ecSPrasad Singamsetty status = uscsi_cmd(cur_file, &ucmd, (option_msg) ? F_NORMAL : F_SILENT);
9327c478bd9Sstevel@tonic-gate if (status) {
9337c478bd9Sstevel@tonic-gate if (!option_msg) {
9347c478bd9Sstevel@tonic-gate err_print("\nMode sense page 0x3f failed\n");
9357c478bd9Sstevel@tonic-gate }
9367c478bd9Sstevel@tonic-gate return;
9377c478bd9Sstevel@tonic-gate }
9387c478bd9Sstevel@tonic-gate
9397c478bd9Sstevel@tonic-gate fmt_print("\n");
9407c478bd9Sstevel@tonic-gate
9417c478bd9Sstevel@tonic-gate /*
9427c478bd9Sstevel@tonic-gate * Now parse the page 0x3f
9437c478bd9Sstevel@tonic-gate */
9447c478bd9Sstevel@tonic-gate mh = (struct mode_header *)msbuf;
9457c478bd9Sstevel@tonic-gate nbytes = mh->length - sizeof (struct mode_header) -
946342440ecSPrasad Singamsetty mh->bdesc_length + 1;
9477c478bd9Sstevel@tonic-gate p = msbuf + sizeof (struct mode_header) + mh->bdesc_length;
9487c478bd9Sstevel@tonic-gate
9497c478bd9Sstevel@tonic-gate while (nbytes > 0) {
9507c478bd9Sstevel@tonic-gate mp = (struct mode_page *)p;
9517c478bd9Sstevel@tonic-gate n = mp->length + sizeof (struct mode_page);
9527c478bd9Sstevel@tonic-gate nbytes -= n;
9537c478bd9Sstevel@tonic-gate if (nbytes < 0)
9547c478bd9Sstevel@tonic-gate break;
9557c478bd9Sstevel@tonic-gate if (default_page(mp->code) == 0) {
9567c478bd9Sstevel@tonic-gate goto error;
9577c478bd9Sstevel@tonic-gate }
9587c478bd9Sstevel@tonic-gate p += n;
9597c478bd9Sstevel@tonic-gate }
9607c478bd9Sstevel@tonic-gate
9617c478bd9Sstevel@tonic-gate if (nbytes < 0) {
9627c478bd9Sstevel@tonic-gate err_print("Mode sense page 0x3f formatted incorrectly:\n");
9637c478bd9Sstevel@tonic-gate }
9647c478bd9Sstevel@tonic-gate error:
9657c478bd9Sstevel@tonic-gate fmt_print("\n");
9667c478bd9Sstevel@tonic-gate }
9677c478bd9Sstevel@tonic-gate
9687c478bd9Sstevel@tonic-gate
9697c478bd9Sstevel@tonic-gate static int
default_page(int pageno)970*b12aaafbSToomas Soome default_page(int pageno)
9717c478bd9Sstevel@tonic-gate {
9727c478bd9Sstevel@tonic-gate struct scsi_ms_header header;
9737c478bd9Sstevel@tonic-gate char saved[MAX_MODE_SENSE_SIZE];
9747c478bd9Sstevel@tonic-gate char current[MAX_MODE_SENSE_SIZE];
9757c478bd9Sstevel@tonic-gate char dfault[MAX_MODE_SENSE_SIZE];
9767c478bd9Sstevel@tonic-gate struct mode_page *sp;
9777c478bd9Sstevel@tonic-gate struct mode_page *cp;
9787c478bd9Sstevel@tonic-gate struct mode_page *dp;
9797c478bd9Sstevel@tonic-gate int length;
9807c478bd9Sstevel@tonic-gate int flags;
9817c478bd9Sstevel@tonic-gate int i;
9827c478bd9Sstevel@tonic-gate int need_mode_select;
9837c478bd9Sstevel@tonic-gate
9847c478bd9Sstevel@tonic-gate /*
9857c478bd9Sstevel@tonic-gate * Get default mode sense
9867c478bd9Sstevel@tonic-gate */
9877c478bd9Sstevel@tonic-gate if (uscsi_mode_sense(cur_file, pageno, MODE_SENSE_PC_DEFAULT,
988*b12aaafbSToomas Soome dfault, MAX_MODE_SENSE_SIZE, &header)) {
989*b12aaafbSToomas Soome err_print("Mode sense on page %x (dfault) failed\n", pageno);
9907c478bd9Sstevel@tonic-gate return (0);
9917c478bd9Sstevel@tonic-gate }
9927c478bd9Sstevel@tonic-gate
9937c478bd9Sstevel@tonic-gate /*
9947c478bd9Sstevel@tonic-gate * Get the current mode sense.
9957c478bd9Sstevel@tonic-gate */
9967c478bd9Sstevel@tonic-gate if (uscsi_mode_sense(cur_file, pageno, MODE_SENSE_PC_CURRENT,
997*b12aaafbSToomas Soome current, MAX_MODE_SENSE_SIZE, &header)) {
998*b12aaafbSToomas Soome err_print("Mode sense on page %x (current) failed\n", pageno);
9997c478bd9Sstevel@tonic-gate return (0);
10007c478bd9Sstevel@tonic-gate }
10017c478bd9Sstevel@tonic-gate
10027c478bd9Sstevel@tonic-gate /*
10037c478bd9Sstevel@tonic-gate * Get saved mode sense. If this fails, assume it is
10047c478bd9Sstevel@tonic-gate * the same as the current.
10057c478bd9Sstevel@tonic-gate */
10067c478bd9Sstevel@tonic-gate if (uscsi_mode_sense(cur_file, pageno, MODE_SENSE_PC_SAVED,
1007*b12aaafbSToomas Soome saved, MAX_MODE_SENSE_SIZE, &header)) {
10087c478bd9Sstevel@tonic-gate (void) memcpy(saved, current, MAX_MODE_SENSE_SIZE);
10097c478bd9Sstevel@tonic-gate }
10107c478bd9Sstevel@tonic-gate
10117c478bd9Sstevel@tonic-gate /*
10127c478bd9Sstevel@tonic-gate * Determine if we need a mode select on this page.
10137c478bd9Sstevel@tonic-gate * Just deal with the intersection of the three pages.
10147c478bd9Sstevel@tonic-gate */
10157c478bd9Sstevel@tonic-gate sp = (struct mode_page *)saved;
10167c478bd9Sstevel@tonic-gate cp = (struct mode_page *)current;
10177c478bd9Sstevel@tonic-gate dp = (struct mode_page *)dfault;
10187c478bd9Sstevel@tonic-gate length = min(MODESENSE_PAGE_LEN(sp), MODESENSE_PAGE_LEN(cp));
10197c478bd9Sstevel@tonic-gate length = min(length, MODESENSE_PAGE_LEN(dp));
10207c478bd9Sstevel@tonic-gate
10217c478bd9Sstevel@tonic-gate need_mode_select = 0;
10227c478bd9Sstevel@tonic-gate for (i = 2; i < length; i++) {
10237c478bd9Sstevel@tonic-gate if (current[i] != dfault[i] || saved[i] != dfault[i]) {
10247c478bd9Sstevel@tonic-gate current[i] = dfault[i];
10257c478bd9Sstevel@tonic-gate need_mode_select = 1;
10267c478bd9Sstevel@tonic-gate }
10277c478bd9Sstevel@tonic-gate }
10287c478bd9Sstevel@tonic-gate
10297c478bd9Sstevel@tonic-gate if (need_mode_select == 0) {
1030*b12aaafbSToomas Soome fmt_print("Defaulting page 0x%x: ok\n", pageno);
10317c478bd9Sstevel@tonic-gate return (1);
10327c478bd9Sstevel@tonic-gate }
10337c478bd9Sstevel@tonic-gate
10347c478bd9Sstevel@tonic-gate /*
10357c478bd9Sstevel@tonic-gate * A change was made. Do a mode select
10367c478bd9Sstevel@tonic-gate * We always want to set the Page Format bit.
10377c478bd9Sstevel@tonic-gate * Set the Save Page bit if the drive indicates
10387c478bd9Sstevel@tonic-gate * that it can save this page.
10397c478bd9Sstevel@tonic-gate */
10407c478bd9Sstevel@tonic-gate length = MODESENSE_PAGE_LEN(cp);
10417c478bd9Sstevel@tonic-gate flags = MODE_SELECT_PF;
10427c478bd9Sstevel@tonic-gate if (cp->ps) {
10437c478bd9Sstevel@tonic-gate flags |= MODE_SELECT_SP;
10447c478bd9Sstevel@tonic-gate }
10457c478bd9Sstevel@tonic-gate cp->ps = 0;
10467c478bd9Sstevel@tonic-gate header.mode_header.length = 0;
10477c478bd9Sstevel@tonic-gate header.mode_header.device_specific = 0;
10487c478bd9Sstevel@tonic-gate if (uscsi_mode_select(cur_file, pageno, flags,
1049*b12aaafbSToomas Soome current, length, &header)) {
10507c478bd9Sstevel@tonic-gate /*
10517c478bd9Sstevel@tonic-gate * Failed - try not saving parameters,
10527c478bd9Sstevel@tonic-gate * if possible.
10537c478bd9Sstevel@tonic-gate */
10547c478bd9Sstevel@tonic-gate if (flags & MODE_SELECT_SP) {
10557c478bd9Sstevel@tonic-gate flags &= ~MODE_SELECT_SP;
10567c478bd9Sstevel@tonic-gate if (uscsi_mode_select(cur_file, pageno, flags,
1057*b12aaafbSToomas Soome saved, length, &header)) {
10587c478bd9Sstevel@tonic-gate fmt_print("Defaulting page 0x%x: failed\n",
1059*b12aaafbSToomas Soome pageno);
10607c478bd9Sstevel@tonic-gate } else {
1061*b12aaafbSToomas Soome fmt_print("Defaulting page 0x%x: ", pageno);
10627c478bd9Sstevel@tonic-gate fmt_print("cannot save page permanently\n");
10637c478bd9Sstevel@tonic-gate }
10647c478bd9Sstevel@tonic-gate } else {
10657c478bd9Sstevel@tonic-gate fmt_print("Defaulting page 0x%x: ", pageno);
10667c478bd9Sstevel@tonic-gate fmt_print("cannot save page permanently\n");
10677c478bd9Sstevel@tonic-gate }
10687c478bd9Sstevel@tonic-gate } else {
10697c478bd9Sstevel@tonic-gate fmt_print("Defaulting page 0x%x: mode select ok\n", pageno);
10707c478bd9Sstevel@tonic-gate }
10717c478bd9Sstevel@tonic-gate
10727c478bd9Sstevel@tonic-gate return (1);
10737c478bd9Sstevel@tonic-gate }
1074