155431Sbostic /*- 255431Sbostic * Copyright (c) 1992 The Regents of the University of California. 355431Sbostic * All rights reserved. 455431Sbostic * 555431Sbostic * This software was developed by the Computer Systems Engineering group 655431Sbostic * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 755431Sbostic * contributed to Berkeley. 855431Sbostic * 955431Sbostic * %sccs.include.redist.c% 1055431Sbostic * 11*55448Sbostic * @(#)scsiformat.c 5.2 (Berkeley) 07/20/92 1255431Sbostic */ 1355431Sbostic 1455431Sbostic #include <sys/param.h> 1555431Sbostic #include <sys/ioctl.h> 1655431Sbostic #include <hp300/dev/scsireg.h> 1755431Sbostic 1855431Sbostic #include <fcntl.h> 1955431Sbostic #include <errno.h> 2055431Sbostic #include <unistd.h> 2155431Sbostic #include <stdlib.h> 2255431Sbostic #include <stdio.h> 2355431Sbostic #include <string.h> 2455431Sbostic 2555431Sbostic struct scsi_inquiry inqbuf; 2655431Sbostic struct { 2755431Sbostic int blks; 2855431Sbostic int blksize; 2955431Sbostic } capbuf; 3055431Sbostic struct { 3155431Sbostic struct scsi_modesense_hdr h; 3255431Sbostic u_char p[126-12]; 3355431Sbostic } msbuf; 3455431Sbostic 3555431Sbostic struct scsi_fmt_cdb inq = { 3655431Sbostic 6, 3755431Sbostic CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0 3855431Sbostic }; 3955431Sbostic struct scsi_fmt_cdb cap = { 4055431Sbostic 10, 4155431Sbostic CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 4255431Sbostic }; 4355431Sbostic struct scsi_fmt_cdb modesense = { 4455431Sbostic 6, 4555431Sbostic CMD_MODE_SENSE, 0, 0x3f, 0, sizeof(msbuf), 0 4655431Sbostic }; 4755431Sbostic 4855431Sbostic int fd; 4955431Sbostic char *device; 5055431Sbostic 5155431Sbostic void do_command __P((int, struct scsi_fmt_cdb *, u_char *, int)); 5255431Sbostic void print_capacity __P((void)); 5355431Sbostic void print_inquiry __P((void)); 5455431Sbostic u_char *print_mode_page __P((u_char *)); 5555431Sbostic void print_mode_sense __P((void)); 5655431Sbostic void usage __P((void)); 5755431Sbostic 5855431Sbostic int 5955431Sbostic main (argc, argv) 6055431Sbostic int argc; 6155431Sbostic char *argv[]; 6255431Sbostic { 6355431Sbostic int ch; 6455431Sbostic 6555431Sbostic while ((ch = getopt(argc, argv, "")) != EOF) 6655431Sbostic switch(ch) { 6755431Sbostic case '?': 6855431Sbostic default: 6955431Sbostic usage(); 7055431Sbostic } 7155431Sbostic argc -= optind; 7255431Sbostic argv += optind; 7355431Sbostic 7455431Sbostic if (argc != 1) 7555431Sbostic usage(); 7655431Sbostic 77*55448Sbostic device = *argv; 78*55448Sbostic if ((fd = open(device, O_RDWR, 0)) < 0) { 7955431Sbostic (void)fprintf(stderr, 8055431Sbostic "scsiformat: %s: %s\n", device, strerror(errno)); 8155431Sbostic exit(1); 8255431Sbostic } 8355431Sbostic print_inquiry(); 8455431Sbostic print_capacity(); 8555431Sbostic print_mode_sense(); 8655431Sbostic exit(0); 8755431Sbostic } 8855431Sbostic 8955431Sbostic void 9055431Sbostic print_inquiry() 9155431Sbostic { 9255431Sbostic char idstr[32]; 9355431Sbostic int i; 9455431Sbostic 9555431Sbostic do_command(fd, &inq, (u_char *)&inqbuf, sizeof(inqbuf)); 9655431Sbostic printf("%s: ", device); 9755431Sbostic 9855431Sbostic if (inqbuf.version != 1) { 9955431Sbostic printf("type 0x%x, qual 0x%x, ver %d\n", inqbuf.type, 10055431Sbostic inqbuf.qual, inqbuf.version); 10155431Sbostic return; 10255431Sbostic } 10355431Sbostic switch (inqbuf.type) { 10455431Sbostic case 0: printf("(disk)"); break; 10555431Sbostic case 4: printf("(WORM)"); break; 10655431Sbostic case 5: printf("(CD-ROM)"); break; 10755431Sbostic case 7: printf("(MO-DISK)"); break; 10855431Sbostic default: printf("(??)"); break; 10955431Sbostic } 11055431Sbostic bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28); 11155431Sbostic for (i = 27; i > 23; --i) 11255431Sbostic if (idstr[i] != ' ') 11355431Sbostic break; 11455431Sbostic idstr[i+1] = 0; 11555431Sbostic for (i = 23; i > 7; --i) 11655431Sbostic if (idstr[i] != ' ') 11755431Sbostic break; 11855431Sbostic idstr[i+1] = 0; 11955431Sbostic for (i = 7; i >= 0; --i) 12055431Sbostic if (idstr[i] != ' ') 12155431Sbostic break; 12255431Sbostic idstr[i+1] = 0; 12355431Sbostic printf(" %s %s rev %s:", idstr, &idstr[8], &idstr[24]); 12455431Sbostic } 12555431Sbostic 12655431Sbostic void 12755431Sbostic print_capacity() 12855431Sbostic { 12955431Sbostic do_command(fd, &cap, (u_char *)&capbuf, sizeof(capbuf)); 13055431Sbostic printf(" %d blocks of %d bytes each\n", capbuf.blks, capbuf.blksize); 13155431Sbostic } 13255431Sbostic 133*55448Sbostic void 134*55448Sbostic print_mode_sense() 135*55448Sbostic { 136*55448Sbostic u_char *cp; 137*55448Sbostic u_char *ep; 138*55448Sbostic 139*55448Sbostic do_command(fd, &modesense, (u_char *)&msbuf, sizeof(msbuf)); 140*55448Sbostic 141*55448Sbostic printf("\n%d bytes of mode sense data. ", msbuf.h.len); 142*55448Sbostic printf("media type %d, %swrite protected\n", msbuf.h.media_type, 143*55448Sbostic msbuf.h.wp? "" : "not "); 144*55448Sbostic if (msbuf.h.block_desc_len) { 145*55448Sbostic printf("density 0x%x, ", msbuf.h.density); 146*55448Sbostic if (msbuf.h.number_blocks) 147*55448Sbostic printf("%d blocks of length %d\n", 148*55448Sbostic msbuf.h.number_blocks, msbuf.h.block_length); 149*55448Sbostic else 150*55448Sbostic printf("all blocks of length %d\n", 151*55448Sbostic msbuf.h.block_length); 152*55448Sbostic cp = msbuf.p; 153*55448Sbostic } else 154*55448Sbostic cp = &msbuf.h.block_desc_len + 1; 155*55448Sbostic 156*55448Sbostic ep = (u_char *)&msbuf + msbuf.h.len; 157*55448Sbostic while (cp < ep) 158*55448Sbostic cp = print_mode_page(cp); 159*55448Sbostic } 160*55448Sbostic 16155431Sbostic u_char * 16255431Sbostic print_mode_page(cp) 16355431Sbostic u_char *cp; 16455431Sbostic { 16555431Sbostic int n = cp[1]; 16655431Sbostic int i; 16755431Sbostic char c; 16855431Sbostic 16955431Sbostic printf("\npage type %d%s (%d bytes): ", cp[0] & 0x7f, 17055431Sbostic (cp[0] & 0x80)? " (saveable)" : "", n); 17155431Sbostic switch (cp[0] & 0x7f) { 17255431Sbostic case 1: 17355431Sbostic printf("Error Recovery parameters.\n"); 17455431Sbostic printf("\tflags = 0x%x ", i = cp[2]); 17555431Sbostic c = '<'; 17655431Sbostic if (i & 0x80) { 17755431Sbostic printf("%cAWRE", c); 17855431Sbostic c = ','; 17955431Sbostic } 18055431Sbostic if (i & 0x40) { 18155431Sbostic printf("%cARRE", c); 18255431Sbostic c = ','; 18355431Sbostic } 18455431Sbostic if (i & 0x20) { 18555431Sbostic printf("%cTB", c); 18655431Sbostic c = ','; 18755431Sbostic } 18855431Sbostic if (i & 0x10) { 18955431Sbostic printf("%cRC", c); 19055431Sbostic c = ','; 19155431Sbostic } 19255431Sbostic if (i & 0x08) { 19355431Sbostic printf("%cEEC", c); 19455431Sbostic c = ','; 19555431Sbostic } 19655431Sbostic if (i & 0x04) { 19755431Sbostic printf("%cPER", c); 19855431Sbostic c = ','; 19955431Sbostic } 20055431Sbostic if (i & 0x02) { 20155431Sbostic printf("%cDTE", c); 20255431Sbostic c = ','; 20355431Sbostic } 20455431Sbostic if (i & 0x01) { 20555431Sbostic printf("%cDCR", c); 20655431Sbostic c = ','; 20755431Sbostic } 20855431Sbostic if (c == ',') 20955431Sbostic printf(">"); 21055431Sbostic 21155431Sbostic printf("\n\t%d retries, %d correction span bits,\n", cp[3], 21255431Sbostic cp[4]); 21355431Sbostic printf("\t%d head offsets, %d data strobe offsets,\n\t", 21455431Sbostic cp[5], cp[6]); 21555431Sbostic if (cp[7] != 0xff) 21655431Sbostic printf("%d", cp[7]); 21755431Sbostic else 21855431Sbostic printf("no"); 21955431Sbostic printf(" recovery time limit.\n"); 22055431Sbostic cp += 8; 22155431Sbostic break; 22255431Sbostic 22355431Sbostic case 2: 22455431Sbostic printf("Disconnect/Reconnect control.\n"); 22555431Sbostic printf("\tbuffer full ratio %d, buffer empty ratio %d,\n", 22655431Sbostic cp[2], cp[3]); 22755431Sbostic printf("\ttime limits: %d bus inactivity, ", 22855431Sbostic *(u_short *)&cp[4]); 22955431Sbostic printf("%d disconnect, %d connect.\n", 23055431Sbostic *(u_short *)&cp[6],*(u_short *)&cp[8]); 23155431Sbostic cp += 12; 23255431Sbostic break; 23355431Sbostic 23455431Sbostic case 3: 23555431Sbostic { 23655431Sbostic struct scsi_format *sf = (struct scsi_format *)cp; 23755431Sbostic printf("Format parameters.\n"); 23855431Sbostic printf("\t%d tracks/zone, %d alt.sect./zone, ", 23955431Sbostic sf->tracks_per_zone, sf->alt_sect_zone); 24055431Sbostic printf("%d alt.tracks/zone,\n\t%d alt.tracks/vol., ", 24155431Sbostic sf->alt_tracks_zone, sf->alt_tracks_vol); 24255431Sbostic printf("%d sectors/track, %d bytes/sector, interleave %d\n", 24355431Sbostic sf->sect_track, sf->data_sect, sf->interleave); 24455431Sbostic printf("\ttrack skew %d, cylinder skew %d,\n", 24555431Sbostic sf->track_skew_factor, sf->cyl_skew_factor); 24655431Sbostic printf("\tdrive type 0x%x ", i = cp[20]); 24755431Sbostic c = '<'; 24855431Sbostic if (i & 0x80) { 24955431Sbostic printf("%cSSEC", c); 25055431Sbostic c = ','; 25155431Sbostic } 25255431Sbostic if (i & 0x40) { 25355431Sbostic printf("%cHSEC", c); 25455431Sbostic c = ','; 25555431Sbostic } 25655431Sbostic if (i & 0x20) { 25755431Sbostic printf("%cRMB", c); 25855431Sbostic c = ','; 25955431Sbostic } 26055431Sbostic if (i & 0x10) { 26155431Sbostic printf("%cSURF", c); 26255431Sbostic c = ','; 26355431Sbostic } 26455431Sbostic if (i & 0x08) { 26555431Sbostic printf("%cINS", c); 26655431Sbostic c = ','; 26755431Sbostic } 26855431Sbostic if (i & 0x04) { 26955431Sbostic printf("%c?", c); 27055431Sbostic c = ','; 27155431Sbostic } 27255431Sbostic if (i & 0x02) { 27355431Sbostic printf("%c?", c); 27455431Sbostic c = ','; 27555431Sbostic } 27655431Sbostic if (i & 0x01) { 27755431Sbostic printf("%c?", c); 27855431Sbostic c = ','; 27955431Sbostic } 28055431Sbostic if (c == ',') 28155431Sbostic printf(">"); 28255431Sbostic printf("\n"); 28355431Sbostic cp += 24; 28455431Sbostic } 28555431Sbostic break; 28655431Sbostic 28755431Sbostic case 4: 28855431Sbostic printf("Disk Geometry parameters.\n"); 28955431Sbostic printf("\t%d cylinders, %d heads.\n", 29055431Sbostic (cp[2] << 16) | (cp[3] << 8) | cp[4], cp[5]); 29155431Sbostic cp += cp[1] + 2; 29255431Sbostic break; 29355431Sbostic 29455431Sbostic default: 29555431Sbostic printf("Unknown page type."); 29655431Sbostic for (cp += 2, i = 0; i < n; ++i) { 29755431Sbostic if ((i & 7) == 0) 29855431Sbostic printf("\n\t%2d ", i); 29955431Sbostic printf(" %02x", *cp++); 30055431Sbostic } 30155431Sbostic printf("\n"); 30255431Sbostic break; 30355431Sbostic } 30455431Sbostic return (cp); 30555431Sbostic } 30655431Sbostic 30755431Sbostic void 308*55448Sbostic do_command(fd, cdb, buf, len) 309*55448Sbostic int fd; 310*55448Sbostic struct scsi_fmt_cdb *cdb; 311*55448Sbostic u_char *buf; 312*55448Sbostic int len; 31355431Sbostic { 314*55448Sbostic static int on = 1; 315*55448Sbostic static int off = 0; 31655431Sbostic 317*55448Sbostic if (ioctl(fd, SDIOCSFORMAT, &on) < 0) { 318*55448Sbostic (void)fprintf(stderr, 319*55448Sbostic "scsiformat: SDIOCSFORMAT (on): %s\n", strerror(errno)); 320*55448Sbostic return; 321*55448Sbostic } 322*55448Sbostic if (ioctl(fd, SDIOCSCSICOMMAND, cdb) < 0) 323*55448Sbostic (void)fprintf(stderr, 324*55448Sbostic "scsiformat: SDIOCSCSICOMMAND: %s\n", strerror(errno)); 325*55448Sbostic else if (read(fd, buf, len) < 0) 326*55448Sbostic (void)fprintf(stderr, 327*55448Sbostic "scsiformat: read: %s\n", strerror(errno)); 32855431Sbostic 329*55448Sbostic if (ioctl(fd, SDIOCSFORMAT, &off) < 0) 330*55448Sbostic (void)fprintf(stderr, 331*55448Sbostic "scsiformat: SDIOCSFORMAT (off): %s\n", strerror(errno)); 33255431Sbostic } 33355431Sbostic 33455431Sbostic void 33555431Sbostic usage() 33655431Sbostic { 33755431Sbostic (void)fprintf(stderr, "usage: scsiformat device\n"); 33855431Sbostic exit(1); 33955431Sbostic } 340