1 /*- 2 * Copyright (c) 1992 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This software was developed by the Computer Systems Engineering group 6 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7 * contributed to Berkeley. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)scsiformat.c 5.2 (Berkeley) 07/20/92 12 */ 13 14 #include <sys/param.h> 15 #include <sys/ioctl.h> 16 #include <hp300/dev/scsireg.h> 17 18 #include <fcntl.h> 19 #include <errno.h> 20 #include <unistd.h> 21 #include <stdlib.h> 22 #include <stdio.h> 23 #include <string.h> 24 25 struct scsi_inquiry inqbuf; 26 struct { 27 int blks; 28 int blksize; 29 } capbuf; 30 struct { 31 struct scsi_modesense_hdr h; 32 u_char p[126-12]; 33 } msbuf; 34 35 struct scsi_fmt_cdb inq = { 36 6, 37 CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0 38 }; 39 struct scsi_fmt_cdb cap = { 40 10, 41 CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 42 }; 43 struct scsi_fmt_cdb modesense = { 44 6, 45 CMD_MODE_SENSE, 0, 0x3f, 0, sizeof(msbuf), 0 46 }; 47 48 int fd; 49 char *device; 50 51 void do_command __P((int, struct scsi_fmt_cdb *, u_char *, int)); 52 void print_capacity __P((void)); 53 void print_inquiry __P((void)); 54 u_char *print_mode_page __P((u_char *)); 55 void print_mode_sense __P((void)); 56 void usage __P((void)); 57 58 int 59 main (argc, argv) 60 int argc; 61 char *argv[]; 62 { 63 int ch; 64 65 while ((ch = getopt(argc, argv, "")) != EOF) 66 switch(ch) { 67 case '?': 68 default: 69 usage(); 70 } 71 argc -= optind; 72 argv += optind; 73 74 if (argc != 1) 75 usage(); 76 77 device = *argv; 78 if ((fd = open(device, O_RDWR, 0)) < 0) { 79 (void)fprintf(stderr, 80 "scsiformat: %s: %s\n", device, strerror(errno)); 81 exit(1); 82 } 83 print_inquiry(); 84 print_capacity(); 85 print_mode_sense(); 86 exit(0); 87 } 88 89 void 90 print_inquiry() 91 { 92 char idstr[32]; 93 int i; 94 95 do_command(fd, &inq, (u_char *)&inqbuf, sizeof(inqbuf)); 96 printf("%s: ", device); 97 98 if (inqbuf.version != 1) { 99 printf("type 0x%x, qual 0x%x, ver %d\n", inqbuf.type, 100 inqbuf.qual, inqbuf.version); 101 return; 102 } 103 switch (inqbuf.type) { 104 case 0: printf("(disk)"); break; 105 case 4: printf("(WORM)"); break; 106 case 5: printf("(CD-ROM)"); break; 107 case 7: printf("(MO-DISK)"); break; 108 default: printf("(??)"); break; 109 } 110 bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28); 111 for (i = 27; i > 23; --i) 112 if (idstr[i] != ' ') 113 break; 114 idstr[i+1] = 0; 115 for (i = 23; i > 7; --i) 116 if (idstr[i] != ' ') 117 break; 118 idstr[i+1] = 0; 119 for (i = 7; i >= 0; --i) 120 if (idstr[i] != ' ') 121 break; 122 idstr[i+1] = 0; 123 printf(" %s %s rev %s:", idstr, &idstr[8], &idstr[24]); 124 } 125 126 void 127 print_capacity() 128 { 129 do_command(fd, &cap, (u_char *)&capbuf, sizeof(capbuf)); 130 printf(" %d blocks of %d bytes each\n", capbuf.blks, capbuf.blksize); 131 } 132 133 void 134 print_mode_sense() 135 { 136 u_char *cp; 137 u_char *ep; 138 139 do_command(fd, &modesense, (u_char *)&msbuf, sizeof(msbuf)); 140 141 printf("\n%d bytes of mode sense data. ", msbuf.h.len); 142 printf("media type %d, %swrite protected\n", msbuf.h.media_type, 143 msbuf.h.wp? "" : "not "); 144 if (msbuf.h.block_desc_len) { 145 printf("density 0x%x, ", msbuf.h.density); 146 if (msbuf.h.number_blocks) 147 printf("%d blocks of length %d\n", 148 msbuf.h.number_blocks, msbuf.h.block_length); 149 else 150 printf("all blocks of length %d\n", 151 msbuf.h.block_length); 152 cp = msbuf.p; 153 } else 154 cp = &msbuf.h.block_desc_len + 1; 155 156 ep = (u_char *)&msbuf + msbuf.h.len; 157 while (cp < ep) 158 cp = print_mode_page(cp); 159 } 160 161 u_char * 162 print_mode_page(cp) 163 u_char *cp; 164 { 165 int n = cp[1]; 166 int i; 167 char c; 168 169 printf("\npage type %d%s (%d bytes): ", cp[0] & 0x7f, 170 (cp[0] & 0x80)? " (saveable)" : "", n); 171 switch (cp[0] & 0x7f) { 172 case 1: 173 printf("Error Recovery parameters.\n"); 174 printf("\tflags = 0x%x ", i = cp[2]); 175 c = '<'; 176 if (i & 0x80) { 177 printf("%cAWRE", c); 178 c = ','; 179 } 180 if (i & 0x40) { 181 printf("%cARRE", c); 182 c = ','; 183 } 184 if (i & 0x20) { 185 printf("%cTB", c); 186 c = ','; 187 } 188 if (i & 0x10) { 189 printf("%cRC", c); 190 c = ','; 191 } 192 if (i & 0x08) { 193 printf("%cEEC", c); 194 c = ','; 195 } 196 if (i & 0x04) { 197 printf("%cPER", c); 198 c = ','; 199 } 200 if (i & 0x02) { 201 printf("%cDTE", c); 202 c = ','; 203 } 204 if (i & 0x01) { 205 printf("%cDCR", c); 206 c = ','; 207 } 208 if (c == ',') 209 printf(">"); 210 211 printf("\n\t%d retries, %d correction span bits,\n", cp[3], 212 cp[4]); 213 printf("\t%d head offsets, %d data strobe offsets,\n\t", 214 cp[5], cp[6]); 215 if (cp[7] != 0xff) 216 printf("%d", cp[7]); 217 else 218 printf("no"); 219 printf(" recovery time limit.\n"); 220 cp += 8; 221 break; 222 223 case 2: 224 printf("Disconnect/Reconnect control.\n"); 225 printf("\tbuffer full ratio %d, buffer empty ratio %d,\n", 226 cp[2], cp[3]); 227 printf("\ttime limits: %d bus inactivity, ", 228 *(u_short *)&cp[4]); 229 printf("%d disconnect, %d connect.\n", 230 *(u_short *)&cp[6],*(u_short *)&cp[8]); 231 cp += 12; 232 break; 233 234 case 3: 235 { 236 struct scsi_format *sf = (struct scsi_format *)cp; 237 printf("Format parameters.\n"); 238 printf("\t%d tracks/zone, %d alt.sect./zone, ", 239 sf->tracks_per_zone, sf->alt_sect_zone); 240 printf("%d alt.tracks/zone,\n\t%d alt.tracks/vol., ", 241 sf->alt_tracks_zone, sf->alt_tracks_vol); 242 printf("%d sectors/track, %d bytes/sector, interleave %d\n", 243 sf->sect_track, sf->data_sect, sf->interleave); 244 printf("\ttrack skew %d, cylinder skew %d,\n", 245 sf->track_skew_factor, sf->cyl_skew_factor); 246 printf("\tdrive type 0x%x ", i = cp[20]); 247 c = '<'; 248 if (i & 0x80) { 249 printf("%cSSEC", c); 250 c = ','; 251 } 252 if (i & 0x40) { 253 printf("%cHSEC", c); 254 c = ','; 255 } 256 if (i & 0x20) { 257 printf("%cRMB", c); 258 c = ','; 259 } 260 if (i & 0x10) { 261 printf("%cSURF", c); 262 c = ','; 263 } 264 if (i & 0x08) { 265 printf("%cINS", c); 266 c = ','; 267 } 268 if (i & 0x04) { 269 printf("%c?", c); 270 c = ','; 271 } 272 if (i & 0x02) { 273 printf("%c?", c); 274 c = ','; 275 } 276 if (i & 0x01) { 277 printf("%c?", c); 278 c = ','; 279 } 280 if (c == ',') 281 printf(">"); 282 printf("\n"); 283 cp += 24; 284 } 285 break; 286 287 case 4: 288 printf("Disk Geometry parameters.\n"); 289 printf("\t%d cylinders, %d heads.\n", 290 (cp[2] << 16) | (cp[3] << 8) | cp[4], cp[5]); 291 cp += cp[1] + 2; 292 break; 293 294 default: 295 printf("Unknown page type."); 296 for (cp += 2, i = 0; i < n; ++i) { 297 if ((i & 7) == 0) 298 printf("\n\t%2d ", i); 299 printf(" %02x", *cp++); 300 } 301 printf("\n"); 302 break; 303 } 304 return (cp); 305 } 306 307 void 308 do_command(fd, cdb, buf, len) 309 int fd; 310 struct scsi_fmt_cdb *cdb; 311 u_char *buf; 312 int len; 313 { 314 static int on = 1; 315 static int off = 0; 316 317 if (ioctl(fd, SDIOCSFORMAT, &on) < 0) { 318 (void)fprintf(stderr, 319 "scsiformat: SDIOCSFORMAT (on): %s\n", strerror(errno)); 320 return; 321 } 322 if (ioctl(fd, SDIOCSCSICOMMAND, cdb) < 0) 323 (void)fprintf(stderr, 324 "scsiformat: SDIOCSCSICOMMAND: %s\n", strerror(errno)); 325 else if (read(fd, buf, len) < 0) 326 (void)fprintf(stderr, 327 "scsiformat: read: %s\n", strerror(errno)); 328 329 if (ioctl(fd, SDIOCSFORMAT, &off) < 0) 330 (void)fprintf(stderr, 331 "scsiformat: SDIOCSFORMAT (off): %s\n", strerror(errno)); 332 } 333 334 void 335 usage() 336 { 337 (void)fprintf(stderr, "usage: scsiformat device\n"); 338 exit(1); 339 } 340