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