1525689f1SJustin T. Gibbs /* 2525689f1SJustin T. Gibbs * Written By Julian ELischer 3525689f1SJustin T. Gibbs * Copyright julian Elischer 1993. 4525689f1SJustin T. Gibbs * Permission is granted to use or redistribute this file in any way as long 5525689f1SJustin T. Gibbs * as this notice remains. Julian Elischer does not guarantee that this file 6525689f1SJustin T. Gibbs * is totally correct for any given task and users of this file must 7525689f1SJustin T. Gibbs * accept responsibility for any damage that occurs from the application of this 8525689f1SJustin T. Gibbs * file. 9525689f1SJustin T. Gibbs * 10525689f1SJustin T. Gibbs * (julian@tfs.com julian@dialix.oz.au) 11525689f1SJustin T. Gibbs * 12525689f1SJustin T. Gibbs * User SCSI hooks added by Peter Dufault: 13525689f1SJustin T. Gibbs * 14525689f1SJustin T. Gibbs * Copyright (c) 1994 HD Associates 15525689f1SJustin T. Gibbs * (contact: dufault@hda.com) 16525689f1SJustin T. Gibbs * All rights reserved. 17525689f1SJustin T. Gibbs * 18525689f1SJustin T. Gibbs * Redistribution and use in source and binary forms, with or without 19525689f1SJustin T. Gibbs * modification, are permitted provided that the following conditions 20525689f1SJustin T. Gibbs * are met: 21525689f1SJustin T. Gibbs * 1. Redistributions of source code must retain the above copyright 22525689f1SJustin T. Gibbs * notice, this list of conditions and the following disclaimer. 23525689f1SJustin T. Gibbs * 2. Redistributions in binary form must reproduce the above copyright 24525689f1SJustin T. Gibbs * notice, this list of conditions and the following disclaimer in the 25525689f1SJustin T. Gibbs * documentation and/or other materials provided with the distribution. 26525689f1SJustin T. Gibbs * 3. The name of HD Associates 27525689f1SJustin T. Gibbs * may not be used to endorse or promote products derived from this software 28525689f1SJustin T. Gibbs * without specific prior written permission. 29525689f1SJustin T. Gibbs * 30525689f1SJustin T. Gibbs * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES ``AS IS'' AND 31525689f1SJustin T. Gibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32525689f1SJustin T. Gibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33525689f1SJustin T. Gibbs * ARE DISCLAIMED. IN NO EVENT SHALL HD ASSOCIATES BE LIABLE 34525689f1SJustin T. Gibbs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35525689f1SJustin T. Gibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36525689f1SJustin T. Gibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 37525689f1SJustin T. Gibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 38525689f1SJustin T. Gibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 39525689f1SJustin T. Gibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40525689f1SJustin T. Gibbs * SUCH DAMAGE. 41525689f1SJustin T. Gibbs */ 42525689f1SJustin T. Gibbs /* 43525689f1SJustin T. Gibbs * Taken from the original scsi(8) program. 44525689f1SJustin T. Gibbs * from: scsi.c,v 1.17 1998/01/12 07:57:57 charnier Exp $"; 45525689f1SJustin T. Gibbs */ 46525689f1SJustin T. Gibbs #ifndef lint 47525689f1SJustin T. Gibbs static const char rcsid[] = 48c60e19a8SKenneth D. Merry "$Id: modeedit.c,v 1.1 1998/09/15 06:43:02 gibbs Exp $"; 49525689f1SJustin T. Gibbs #endif /* not lint */ 50525689f1SJustin T. Gibbs 51525689f1SJustin T. Gibbs #include <ctype.h> 52525689f1SJustin T. Gibbs #include <err.h> 53525689f1SJustin T. Gibbs #include <errno.h> 54525689f1SJustin T. Gibbs #include <string.h> 55525689f1SJustin T. Gibbs #include <stdlib.h> 56525689f1SJustin T. Gibbs #include <stdio.h> 57525689f1SJustin T. Gibbs #include <sys/file.h> 58525689f1SJustin T. Gibbs #include <signal.h> 59525689f1SJustin T. Gibbs #include <unistd.h> 60525689f1SJustin T. Gibbs 61525689f1SJustin T. Gibbs #include <cam/cam.h> 62525689f1SJustin T. Gibbs #include <cam/cam_ccb.h> 63525689f1SJustin T. Gibbs #include <camlib.h> 64525689f1SJustin T. Gibbs #include "camcontrol.h" 65525689f1SJustin T. Gibbs 66525689f1SJustin T. Gibbs int verbose = 0; 67525689f1SJustin T. Gibbs 68525689f1SJustin T. Gibbs /* iget: Integer argument callback 69525689f1SJustin T. Gibbs */ 70525689f1SJustin T. Gibbs int 71525689f1SJustin T. Gibbs iget(void *hook, char *name) 72525689f1SJustin T. Gibbs { 73525689f1SJustin T. Gibbs struct get_hook *h = (struct get_hook *)hook; 74525689f1SJustin T. Gibbs int arg; 75525689f1SJustin T. Gibbs 76525689f1SJustin T. Gibbs if (h->got >= h->argc) 77525689f1SJustin T. Gibbs { 78525689f1SJustin T. Gibbs fprintf(stderr, "Expecting an integer argument.\n"); 79c60e19a8SKenneth D. Merry usage(0); 80525689f1SJustin T. Gibbs exit(1); 81525689f1SJustin T. Gibbs } 82525689f1SJustin T. Gibbs arg = strtol(h->argv[h->got], 0, 0); 83525689f1SJustin T. Gibbs h->got++; 84525689f1SJustin T. Gibbs 85525689f1SJustin T. Gibbs if (verbose && name && *name) 86525689f1SJustin T. Gibbs printf("%s: %d\n", name, arg); 87525689f1SJustin T. Gibbs 88525689f1SJustin T. Gibbs return arg; 89525689f1SJustin T. Gibbs } 90525689f1SJustin T. Gibbs 91525689f1SJustin T. Gibbs /* cget: char * argument callback 92525689f1SJustin T. Gibbs */ 93525689f1SJustin T. Gibbs char * 94525689f1SJustin T. Gibbs cget(void *hook, char *name) 95525689f1SJustin T. Gibbs { 96525689f1SJustin T. Gibbs struct get_hook *h = (struct get_hook *)hook; 97525689f1SJustin T. Gibbs char *arg; 98525689f1SJustin T. Gibbs 99525689f1SJustin T. Gibbs if (h->got >= h->argc) 100525689f1SJustin T. Gibbs { 101525689f1SJustin T. Gibbs fprintf(stderr, "Expecting a character pointer argument.\n"); 102c60e19a8SKenneth D. Merry usage(0); 103525689f1SJustin T. Gibbs exit(1); 104525689f1SJustin T. Gibbs } 105525689f1SJustin T. Gibbs arg = h->argv[h->got]; 106525689f1SJustin T. Gibbs h->got++; 107525689f1SJustin T. Gibbs 108525689f1SJustin T. Gibbs if (verbose && name) 109525689f1SJustin T. Gibbs printf("cget: %s: %s", name, arg); 110525689f1SJustin T. Gibbs 111525689f1SJustin T. Gibbs return arg; 112525689f1SJustin T. Gibbs } 113525689f1SJustin T. Gibbs 114525689f1SJustin T. Gibbs /* arg_put: "put argument" callback 115525689f1SJustin T. Gibbs */ 116525689f1SJustin T. Gibbs void 117525689f1SJustin T. Gibbs arg_put(void *hook, int letter, void *arg, int count, char *name) 118525689f1SJustin T. Gibbs { 119525689f1SJustin T. Gibbs if (verbose && name && *name) 120525689f1SJustin T. Gibbs printf("%s: ", name); 121525689f1SJustin T. Gibbs 122525689f1SJustin T. Gibbs switch(letter) 123525689f1SJustin T. Gibbs { 124525689f1SJustin T. Gibbs case 'i': 125525689f1SJustin T. Gibbs case 'b': 126525689f1SJustin T. Gibbs printf("%d ", (int)arg); 127525689f1SJustin T. Gibbs break; 128525689f1SJustin T. Gibbs 129525689f1SJustin T. Gibbs case 'c': 130525689f1SJustin T. Gibbs case 'z': 131525689f1SJustin T. Gibbs { 132525689f1SJustin T. Gibbs char *p; 133525689f1SJustin T. Gibbs 134525689f1SJustin T. Gibbs p = malloc(count + 1); 135525689f1SJustin T. Gibbs 136525689f1SJustin T. Gibbs bzero(p, count +1); 137525689f1SJustin T. Gibbs strncpy(p, (char *)arg, count); 138525689f1SJustin T. Gibbs if (letter == 'z') 139525689f1SJustin T. Gibbs { 140525689f1SJustin T. Gibbs int i; 141525689f1SJustin T. Gibbs for (i = count - 1; i >= 0; i--) 142525689f1SJustin T. Gibbs if (p[i] == ' ') 143525689f1SJustin T. Gibbs p[i] = 0; 144525689f1SJustin T. Gibbs else 145525689f1SJustin T. Gibbs break; 146525689f1SJustin T. Gibbs } 147525689f1SJustin T. Gibbs printf("%s ", p); 148525689f1SJustin T. Gibbs 149525689f1SJustin T. Gibbs free(p); 150525689f1SJustin T. Gibbs } 151525689f1SJustin T. Gibbs 152525689f1SJustin T. Gibbs break; 153525689f1SJustin T. Gibbs 154525689f1SJustin T. Gibbs default: 155525689f1SJustin T. Gibbs printf("Unknown format letter: '%c'\n", letter); 156525689f1SJustin T. Gibbs } 157525689f1SJustin T. Gibbs if (verbose) 158525689f1SJustin T. Gibbs putchar('\n'); 159525689f1SJustin T. Gibbs } 160525689f1SJustin T. Gibbs 161525689f1SJustin T. Gibbs #define START_ENTRY '{' 162525689f1SJustin T. Gibbs #define END_ENTRY '}' 163525689f1SJustin T. Gibbs 164525689f1SJustin T. Gibbs static void 165525689f1SJustin T. Gibbs skipwhite(FILE *f) 166525689f1SJustin T. Gibbs { 167525689f1SJustin T. Gibbs int c; 168525689f1SJustin T. Gibbs 169525689f1SJustin T. Gibbs skip_again: 170525689f1SJustin T. Gibbs 171525689f1SJustin T. Gibbs while (isspace(c = getc(f))) 172525689f1SJustin T. Gibbs ; 173525689f1SJustin T. Gibbs 174525689f1SJustin T. Gibbs if (c == '#') { 175525689f1SJustin T. Gibbs while ((c = getc(f)) != '\n' && c != EOF) 176525689f1SJustin T. Gibbs ; 177525689f1SJustin T. Gibbs goto skip_again; 178525689f1SJustin T. Gibbs } 179525689f1SJustin T. Gibbs 180525689f1SJustin T. Gibbs ungetc(c, f); 181525689f1SJustin T. Gibbs } 182525689f1SJustin T. Gibbs 183525689f1SJustin T. Gibbs /* mode_lookup: Lookup a format description for a given page. 184525689f1SJustin T. Gibbs */ 185525689f1SJustin T. Gibbs char *mode_db = "/usr/share/misc/scsi_modes"; 186525689f1SJustin T. Gibbs static char * 187525689f1SJustin T. Gibbs mode_lookup(int page) 188525689f1SJustin T. Gibbs { 189525689f1SJustin T. Gibbs char *new_db; 190525689f1SJustin T. Gibbs FILE *modes; 191525689f1SJustin T. Gibbs int match, next, found, c; 192525689f1SJustin T. Gibbs static char fmt[4096]; /* XXX This should be with strealloc */ 193525689f1SJustin T. Gibbs int page_desc; 194525689f1SJustin T. Gibbs new_db = getenv("SCSI_MODES"); 195525689f1SJustin T. Gibbs 196525689f1SJustin T. Gibbs if (new_db) 197525689f1SJustin T. Gibbs mode_db = new_db; 198525689f1SJustin T. Gibbs 199525689f1SJustin T. Gibbs modes = fopen(mode_db, "r"); 200525689f1SJustin T. Gibbs if (modes == 0) 201525689f1SJustin T. Gibbs return 0; 202525689f1SJustin T. Gibbs 203525689f1SJustin T. Gibbs next = 0; 204525689f1SJustin T. Gibbs found = 0; 205525689f1SJustin T. Gibbs 206525689f1SJustin T. Gibbs while (!found) { 207525689f1SJustin T. Gibbs 208525689f1SJustin T. Gibbs skipwhite(modes); 209525689f1SJustin T. Gibbs 210525689f1SJustin T. Gibbs if (fscanf(modes, "%i", &page_desc) != 1) 211525689f1SJustin T. Gibbs break; 212525689f1SJustin T. Gibbs 213525689f1SJustin T. Gibbs if (page_desc == page) 214525689f1SJustin T. Gibbs found = 1; 215525689f1SJustin T. Gibbs 216525689f1SJustin T. Gibbs skipwhite(modes); 217525689f1SJustin T. Gibbs if (getc(modes) != START_ENTRY) 218525689f1SJustin T. Gibbs errx(1, "expected %c", START_ENTRY); 219525689f1SJustin T. Gibbs 220525689f1SJustin T. Gibbs match = 1; 221525689f1SJustin T. Gibbs while (match != 0) { 222525689f1SJustin T. Gibbs c = getc(modes); 223525689f1SJustin T. Gibbs if (c == EOF) { 224525689f1SJustin T. Gibbs warnx("expected %c", END_ENTRY); 225525689f1SJustin T. Gibbs } 226525689f1SJustin T. Gibbs 227525689f1SJustin T. Gibbs if (c == START_ENTRY) { 228525689f1SJustin T. Gibbs match++; 229525689f1SJustin T. Gibbs } 230525689f1SJustin T. Gibbs if (c == END_ENTRY) { 231525689f1SJustin T. Gibbs match--; 232525689f1SJustin T. Gibbs if (match == 0) 233525689f1SJustin T. Gibbs break; 234525689f1SJustin T. Gibbs } 235525689f1SJustin T. Gibbs if (found && c != '\n') { 236525689f1SJustin T. Gibbs if (next >= sizeof(fmt)) 237525689f1SJustin T. Gibbs errx(1, "buffer overflow"); 238525689f1SJustin T. Gibbs 239525689f1SJustin T. Gibbs fmt[next++] = (u_char)c; 240525689f1SJustin T. Gibbs } 241525689f1SJustin T. Gibbs } 242525689f1SJustin T. Gibbs } 243525689f1SJustin T. Gibbs fmt[next] = 0; 244525689f1SJustin T. Gibbs 245525689f1SJustin T. Gibbs return (found) ? fmt : 0; 246525689f1SJustin T. Gibbs } 247525689f1SJustin T. Gibbs 248525689f1SJustin T. Gibbs /* -------- edit: Mode Select Editor --------- 249525689f1SJustin T. Gibbs */ 250525689f1SJustin T. Gibbs struct editinfo 251525689f1SJustin T. Gibbs { 252525689f1SJustin T. Gibbs int can_edit; 253525689f1SJustin T. Gibbs int default_value; 254525689f1SJustin T. Gibbs } editinfo[64]; /* XXX Bogus fixed size */ 255525689f1SJustin T. Gibbs 256525689f1SJustin T. Gibbs static int editind; 257525689f1SJustin T. Gibbs volatile int edit_opened; 258525689f1SJustin T. Gibbs static FILE *edit_file; 259525689f1SJustin T. Gibbs static char edit_name[L_tmpnam]; 260525689f1SJustin T. Gibbs 261525689f1SJustin T. Gibbs static inline void 262525689f1SJustin T. Gibbs edit_rewind(void) 263525689f1SJustin T. Gibbs { 264525689f1SJustin T. Gibbs editind = 0; 265525689f1SJustin T. Gibbs } 266525689f1SJustin T. Gibbs 267525689f1SJustin T. Gibbs static void 268525689f1SJustin T. Gibbs edit_done(void) 269525689f1SJustin T. Gibbs { 270525689f1SJustin T. Gibbs int opened; 271525689f1SJustin T. Gibbs 272525689f1SJustin T. Gibbs sigset_t all, prev; 273525689f1SJustin T. Gibbs sigfillset(&all); 274525689f1SJustin T. Gibbs 275525689f1SJustin T. Gibbs (void)sigprocmask(SIG_SETMASK, &all, &prev); 276525689f1SJustin T. Gibbs 277525689f1SJustin T. Gibbs opened = (int)edit_opened; 278525689f1SJustin T. Gibbs edit_opened = 0; 279525689f1SJustin T. Gibbs 280525689f1SJustin T. Gibbs (void)sigprocmask(SIG_SETMASK, &prev, 0); 281525689f1SJustin T. Gibbs 282525689f1SJustin T. Gibbs if (opened) 283525689f1SJustin T. Gibbs { 284525689f1SJustin T. Gibbs if (fclose(edit_file)) 285525689f1SJustin T. Gibbs warn("%s", edit_name); 286525689f1SJustin T. Gibbs if (unlink(edit_name)) 287525689f1SJustin T. Gibbs warn("%s", edit_name); 288525689f1SJustin T. Gibbs } 289525689f1SJustin T. Gibbs } 290525689f1SJustin T. Gibbs 291525689f1SJustin T. Gibbs static void 292525689f1SJustin T. Gibbs edit_init(void) 293525689f1SJustin T. Gibbs { 294525689f1SJustin T. Gibbs edit_rewind(); 295525689f1SJustin T. Gibbs if (tmpnam(edit_name) == 0) 296525689f1SJustin T. Gibbs errx(1, "tmpnam failed"); 297525689f1SJustin T. Gibbs if ((edit_file = fopen(edit_name, "w")) == 0) 298525689f1SJustin T. Gibbs err(1, "%s", edit_name); 299525689f1SJustin T. Gibbs edit_opened = 1; 300525689f1SJustin T. Gibbs 301525689f1SJustin T. Gibbs atexit(edit_done); 302525689f1SJustin T. Gibbs } 303525689f1SJustin T. Gibbs 304525689f1SJustin T. Gibbs static void 305525689f1SJustin T. Gibbs edit_check(void *hook, int letter, void *arg, int count, char *name) 306525689f1SJustin T. Gibbs { 307525689f1SJustin T. Gibbs if (letter != 'i' && letter != 'b') 308525689f1SJustin T. Gibbs errx(1, "can't edit format %c", letter); 309525689f1SJustin T. Gibbs 310525689f1SJustin T. Gibbs if (editind >= sizeof(editinfo) / sizeof(editinfo[0])) 311525689f1SJustin T. Gibbs errx(1, "edit table overflow"); 312525689f1SJustin T. Gibbs 313525689f1SJustin T. Gibbs editinfo[editind].can_edit = ((int)arg != 0); 314525689f1SJustin T. Gibbs editind++; 315525689f1SJustin T. Gibbs } 316525689f1SJustin T. Gibbs 317525689f1SJustin T. Gibbs static void 318525689f1SJustin T. Gibbs edit_defaults(void *hook, int letter, void *arg, int count, char *name) 319525689f1SJustin T. Gibbs { 320525689f1SJustin T. Gibbs if (letter != 'i' && letter != 'b') 321525689f1SJustin T. Gibbs errx(1, "can't edit format %c", letter); 322525689f1SJustin T. Gibbs 323525689f1SJustin T. Gibbs editinfo[editind].default_value = ((int)arg); 324525689f1SJustin T. Gibbs editind++; 325525689f1SJustin T. Gibbs } 326525689f1SJustin T. Gibbs 327525689f1SJustin T. Gibbs static void 328525689f1SJustin T. Gibbs edit_report(void *hook, int letter, void *arg, int count, char *name) 329525689f1SJustin T. Gibbs { 330525689f1SJustin T. Gibbs if (editinfo[editind].can_edit) { 331525689f1SJustin T. Gibbs if (letter != 'i' && letter != 'b') 332525689f1SJustin T. Gibbs errx(1, "can't report format %c", letter); 333525689f1SJustin T. Gibbs 334525689f1SJustin T. Gibbs fprintf(edit_file, "%s: %d\n", name, (int)arg); 335525689f1SJustin T. Gibbs } 336525689f1SJustin T. Gibbs 337525689f1SJustin T. Gibbs editind++; 338525689f1SJustin T. Gibbs } 339525689f1SJustin T. Gibbs 340525689f1SJustin T. Gibbs static int 341525689f1SJustin T. Gibbs edit_get(void *hook, char *name) 342525689f1SJustin T. Gibbs { 343525689f1SJustin T. Gibbs int arg = editinfo[editind].default_value; 344525689f1SJustin T. Gibbs 345525689f1SJustin T. Gibbs if (editinfo[editind].can_edit) { 346525689f1SJustin T. Gibbs char line[80]; 347525689f1SJustin T. Gibbs if (fgets(line, sizeof(line), edit_file) == 0) 348525689f1SJustin T. Gibbs err(1, "fgets"); 349525689f1SJustin T. Gibbs 350525689f1SJustin T. Gibbs line[strlen(line) - 1] = 0; 351525689f1SJustin T. Gibbs 352525689f1SJustin T. Gibbs if (strncmp(name, line, strlen(name)) != 0) 353525689f1SJustin T. Gibbs errx(1, "expected \"%s\" and read \"%s\"", name, line); 354525689f1SJustin T. Gibbs 355525689f1SJustin T. Gibbs arg = strtoul(line + strlen(name) + 2, 0, 0); 356525689f1SJustin T. Gibbs } 357525689f1SJustin T. Gibbs 358525689f1SJustin T. Gibbs editind++; 359525689f1SJustin T. Gibbs return arg; 360525689f1SJustin T. Gibbs } 361525689f1SJustin T. Gibbs 362525689f1SJustin T. Gibbs static void 363525689f1SJustin T. Gibbs edit_edit(void) 364525689f1SJustin T. Gibbs { 365525689f1SJustin T. Gibbs char *system_line; 366525689f1SJustin T. Gibbs char *editor = getenv("EDITOR"); 367525689f1SJustin T. Gibbs if (!editor) 368525689f1SJustin T. Gibbs editor = "vi"; 369525689f1SJustin T. Gibbs 370525689f1SJustin T. Gibbs fclose(edit_file); 371525689f1SJustin T. Gibbs 372525689f1SJustin T. Gibbs system_line = malloc(strlen(editor) + strlen(edit_name) + 6); 373525689f1SJustin T. Gibbs sprintf(system_line, "%s %s", editor, edit_name); 374525689f1SJustin T. Gibbs system(system_line); 375525689f1SJustin T. Gibbs free(system_line); 376525689f1SJustin T. Gibbs 377525689f1SJustin T. Gibbs if ((edit_file = fopen(edit_name, "r")) == 0) 378525689f1SJustin T. Gibbs err(1, "%s", edit_name); 379525689f1SJustin T. Gibbs } 380525689f1SJustin T. Gibbs 381525689f1SJustin T. Gibbs void 382525689f1SJustin T. Gibbs mode_edit(struct cam_device *device, int page, int page_control, int dbd, 383525689f1SJustin T. Gibbs int edit, int retry_count, int timeout) 384525689f1SJustin T. Gibbs { 385525689f1SJustin T. Gibbs int i; 386525689f1SJustin T. Gibbs u_char data[255]; 387525689f1SJustin T. Gibbs u_char *mode_pars; 388525689f1SJustin T. Gibbs struct mode_header 389525689f1SJustin T. Gibbs { 390525689f1SJustin T. Gibbs u_char mdl; /* Mode data length */ 391525689f1SJustin T. Gibbs u_char medium_type; 392525689f1SJustin T. Gibbs u_char dev_spec_par; 393525689f1SJustin T. Gibbs u_char bdl; /* Block descriptor length */ 394525689f1SJustin T. Gibbs }; 395525689f1SJustin T. Gibbs 396525689f1SJustin T. Gibbs struct mode_page_header 397525689f1SJustin T. Gibbs { 398525689f1SJustin T. Gibbs u_char page_code; 399525689f1SJustin T. Gibbs u_char page_length; 400525689f1SJustin T. Gibbs }; 401525689f1SJustin T. Gibbs 402525689f1SJustin T. Gibbs struct mode_header *mh; 403525689f1SJustin T. Gibbs struct mode_page_header *mph; 404525689f1SJustin T. Gibbs 405525689f1SJustin T. Gibbs char *fmt = mode_lookup(page); 406525689f1SJustin T. Gibbs if (!fmt && verbose) { 407525689f1SJustin T. Gibbs fprintf(stderr, 408525689f1SJustin T. Gibbs "No mode data base entry in \"%s\" for page %d; " 409525689f1SJustin T. Gibbs " binary %s only.\n", 410525689f1SJustin T. Gibbs mode_db, page, (edit ? "edit" : "display")); 411525689f1SJustin T. Gibbs } 412525689f1SJustin T. Gibbs 413525689f1SJustin T. Gibbs if (edit) { 414525689f1SJustin T. Gibbs if (!fmt) 415525689f1SJustin T. Gibbs errx(1, "can't edit without a format"); 416525689f1SJustin T. Gibbs 417525689f1SJustin T. Gibbs if (page_control != 0 && page_control != 3) 418525689f1SJustin T. Gibbs errx(1, "it only makes sense to edit page 0 " 419525689f1SJustin T. Gibbs "(current) or page 3 (saved values)"); 420525689f1SJustin T. Gibbs 421525689f1SJustin T. Gibbs verbose = 1; 422525689f1SJustin T. Gibbs 423525689f1SJustin T. Gibbs mode_sense(device, page, 1, dbd, retry_count, timeout, 424525689f1SJustin T. Gibbs data, sizeof(data)); 425525689f1SJustin T. Gibbs 426525689f1SJustin T. Gibbs mh = (struct mode_header *)data; 427525689f1SJustin T. Gibbs mph = (struct mode_page_header *) 428525689f1SJustin T. Gibbs (((char *)mh) + sizeof(*mh) + mh->bdl); 429525689f1SJustin T. Gibbs 430525689f1SJustin T. Gibbs mode_pars = (char *)mph + sizeof(*mph); 431525689f1SJustin T. Gibbs 432525689f1SJustin T. Gibbs edit_init(); 433525689f1SJustin T. Gibbs buff_decode_visit(mode_pars, mh->mdl, fmt, edit_check, 0); 434525689f1SJustin T. Gibbs 435525689f1SJustin T. Gibbs mode_sense(device, page, 0, dbd, retry_count, timeout, 436525689f1SJustin T. Gibbs data, sizeof(data)); 437525689f1SJustin T. Gibbs 438525689f1SJustin T. Gibbs edit_rewind(); 439525689f1SJustin T. Gibbs buff_decode_visit(mode_pars, mh->mdl, fmt, edit_defaults, 0); 440525689f1SJustin T. Gibbs 441525689f1SJustin T. Gibbs edit_rewind(); 442525689f1SJustin T. Gibbs buff_decode_visit(mode_pars, mh->mdl, fmt, edit_report, 0); 443525689f1SJustin T. Gibbs 444525689f1SJustin T. Gibbs edit_edit(); 445525689f1SJustin T. Gibbs 446525689f1SJustin T. Gibbs edit_rewind(); 447525689f1SJustin T. Gibbs buff_encode_visit(mode_pars, mh->mdl, fmt, edit_get, 0); 448525689f1SJustin T. Gibbs 449525689f1SJustin T. Gibbs /* Eliminate block descriptors: 450525689f1SJustin T. Gibbs */ 451525689f1SJustin T. Gibbs bcopy((char *)mph, ((char *)mh) + sizeof(*mh), 452525689f1SJustin T. Gibbs sizeof(*mph) + mph->page_length); 453525689f1SJustin T. Gibbs 454525689f1SJustin T. Gibbs mh->bdl = mh->dev_spec_par = 0; 455525689f1SJustin T. Gibbs mph = (struct mode_page_header *) (((char *)mh) + sizeof(*mh)); 456525689f1SJustin T. Gibbs mode_pars = ((char *)mph) + 2; 457525689f1SJustin T. Gibbs 458525689f1SJustin T. Gibbs #if 0 459525689f1SJustin T. Gibbs /* Turn this on to see what you're sending to the 460525689f1SJustin T. Gibbs * device: 461525689f1SJustin T. Gibbs */ 462525689f1SJustin T. Gibbs edit_rewind(); 463525689f1SJustin T. Gibbs buff_decode_visit(mode_pars, mh->mdl, fmt, arg_put, 0); 464525689f1SJustin T. Gibbs #endif 465525689f1SJustin T. Gibbs 466525689f1SJustin T. Gibbs edit_done(); 467525689f1SJustin T. Gibbs 468525689f1SJustin T. Gibbs /* Make it permanent if pageselect is three. 469525689f1SJustin T. Gibbs */ 470525689f1SJustin T. Gibbs 471525689f1SJustin T. Gibbs mph->page_code &= ~0xC0; /* Clear PS and RESERVED */ 472525689f1SJustin T. Gibbs mh->mdl = 0; /* Reserved for mode select */ 473525689f1SJustin T. Gibbs 474525689f1SJustin T. Gibbs mode_select(device, (page_control == 3), retry_count, 475525689f1SJustin T. Gibbs timeout, (u_int8_t *)mh, sizeof(*mh) + mh->bdl + 476525689f1SJustin T. Gibbs sizeof(*mph) + mph->page_length); 477525689f1SJustin T. Gibbs 478525689f1SJustin T. Gibbs return; 479525689f1SJustin T. Gibbs } 480525689f1SJustin T. Gibbs 481525689f1SJustin T. Gibbs mode_sense(device, page, page_control, dbd, retry_count, timeout, 482525689f1SJustin T. Gibbs data, sizeof(data)); 483525689f1SJustin T. Gibbs 484525689f1SJustin T. Gibbs /* Skip over the block descriptors. 485525689f1SJustin T. Gibbs */ 486525689f1SJustin T. Gibbs mh = (struct mode_header *)data; 487525689f1SJustin T. Gibbs mph = (struct mode_page_header *)(((char *)mh) + sizeof(*mh) + mh->bdl); 488525689f1SJustin T. Gibbs mode_pars = (char *)mph + sizeof(*mph); 489525689f1SJustin T. Gibbs 490525689f1SJustin T. Gibbs if (!fmt) { 491525689f1SJustin T. Gibbs for (i = 0; i < mh->mdl; i++) { 492525689f1SJustin T. Gibbs printf("%02x%c",mode_pars[i], 493525689f1SJustin T. Gibbs (((i + 1) % 8) == 0) ? '\n' : ' '); 494525689f1SJustin T. Gibbs } 495525689f1SJustin T. Gibbs putc('\n', stdout); 496525689f1SJustin T. Gibbs } else { 497525689f1SJustin T. Gibbs verbose = 1; 498525689f1SJustin T. Gibbs buff_decode_visit(mode_pars, mh->mdl, fmt, arg_put, NULL); 499525689f1SJustin T. Gibbs } 500525689f1SJustin T. Gibbs } 501