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