4.4BSD snapshot (revision 8.1); add 1993 to copyright
[unix-history] / usr / src / sbin / scsiformat / scsiformat.c
CommitLineData
3a637e8d
KB
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 *
be2c1524 11 * @(#)scsiformat.c 5.3 (Berkeley) %G%
3a637e8d
KB
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
25struct scsi_inquiry inqbuf;
26struct {
27 int blks;
28 int blksize;
29} capbuf;
30struct {
31 struct scsi_modesense_hdr h;
32 u_char p[126-12];
33} msbuf;
be2c1524 34u_char mselbuf[24];
3a637e8d 35
be2c1524
KB
36struct scsi_fmt_cdb cap = {
37 10,
38 CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0
39};
40struct scsi_fmt_cdb format = {
41 6,
42 CMD_FORMAT_UNIT, 0, 0, 0, 0, 0
43};
3a637e8d
KB
44struct scsi_fmt_cdb inq = {
45 6,
46 CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0
47};
be2c1524
KB
48struct scsi_fmt_cdb modeselect = {
49 6,
50 CMD_MODE_SELECT, 0x11, 0, 0, sizeof(mselbuf), 0
3a637e8d
KB
51};
52struct scsi_fmt_cdb modesense = {
53 6,
54 CMD_MODE_SENSE, 0, 0x3f, 0, sizeof(msbuf), 0
55};
56
57int fd;
58char *device;
59
60void do_command __P((int, struct scsi_fmt_cdb *, u_char *, int));
be2c1524 61void do_format __P((void));
3a637e8d
KB
62void print_capacity __P((void));
63void print_inquiry __P((void));
64u_char *print_mode_page __P((u_char *));
65void print_mode_sense __P((void));
66void usage __P((void));
67
68int
be2c1524 69main(argc, argv)
3a637e8d
KB
70 int argc;
71 char *argv[];
72{
73 int ch;
74
75 while ((ch = getopt(argc, argv, "")) != EOF)
76 switch(ch) {
77 case '?':
78 default:
79 usage();
80 }
81 argc -= optind;
82 argv += optind;
83
84 if (argc != 1)
85 usage();
86
873fa9ad
KB
87 device = *argv;
88 if ((fd = open(device, O_RDWR, 0)) < 0) {
3a637e8d
KB
89 (void)fprintf(stderr,
90 "scsiformat: %s: %s\n", device, strerror(errno));
91 exit(1);
92 }
93 print_inquiry();
94 print_capacity();
95 print_mode_sense();
be2c1524
KB
96
97 do_format();
3a637e8d
KB
98 exit(0);
99}
100
3a637e8d
KB
101void
102print_inquiry()
103{
104 char idstr[32];
105 int i;
106
107 do_command(fd, &inq, (u_char *)&inqbuf, sizeof(inqbuf));
108 printf("%s: ", device);
109
110 if (inqbuf.version != 1) {
111 printf("type 0x%x, qual 0x%x, ver %d\n", inqbuf.type,
112 inqbuf.qual, inqbuf.version);
113 return;
114 }
115 switch (inqbuf.type) {
116 case 0: printf("(disk)"); break;
117 case 4: printf("(WORM)"); break;
118 case 5: printf("(CD-ROM)"); break;
119 case 7: printf("(MO-DISK)"); break;
120 default: printf("(??)"); break;
121 }
122 bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28);
123 for (i = 27; i > 23; --i)
124 if (idstr[i] != ' ')
125 break;
126 idstr[i+1] = 0;
127 for (i = 23; i > 7; --i)
128 if (idstr[i] != ' ')
129 break;
130 idstr[i+1] = 0;
131 for (i = 7; i >= 0; --i)
132 if (idstr[i] != ' ')
133 break;
134 idstr[i+1] = 0;
135 printf(" %s %s rev %s:", idstr, &idstr[8], &idstr[24]);
136}
137
138void
139print_capacity()
140{
141 do_command(fd, &cap, (u_char *)&capbuf, sizeof(capbuf));
142 printf(" %d blocks of %d bytes each\n", capbuf.blks, capbuf.blksize);
143}
144
873fa9ad
KB
145void
146print_mode_sense()
147{
148 u_char *cp;
149 u_char *ep;
150
151 do_command(fd, &modesense, (u_char *)&msbuf, sizeof(msbuf));
152
153 printf("\n%d bytes of mode sense data. ", msbuf.h.len);
154 printf("media type %d, %swrite protected\n", msbuf.h.media_type,
155 msbuf.h.wp? "" : "not ");
156 if (msbuf.h.block_desc_len) {
157 printf("density 0x%x, ", msbuf.h.density);
158 if (msbuf.h.number_blocks)
159 printf("%d blocks of length %d\n",
160 msbuf.h.number_blocks, msbuf.h.block_length);
161 else
162 printf("all blocks of length %d\n",
163 msbuf.h.block_length);
164 cp = msbuf.p;
165 } else
166 cp = &msbuf.h.block_desc_len + 1;
167
168 ep = (u_char *)&msbuf + msbuf.h.len;
169 while (cp < ep)
170 cp = print_mode_page(cp);
171}
172
3a637e8d
KB
173u_char *
174print_mode_page(cp)
175 u_char *cp;
176{
177 int n = cp[1];
178 int i;
179 char c;
180
181 printf("\npage type %d%s (%d bytes): ", cp[0] & 0x7f,
182 (cp[0] & 0x80)? " (saveable)" : "", n);
183 switch (cp[0] & 0x7f) {
184 case 1:
185 printf("Error Recovery parameters.\n");
186 printf("\tflags = 0x%x ", i = cp[2]);
187 c = '<';
188 if (i & 0x80) {
189 printf("%cAWRE", c);
190 c = ',';
191 }
192 if (i & 0x40) {
193 printf("%cARRE", c);
194 c = ',';
195 }
196 if (i & 0x20) {
197 printf("%cTB", c);
198 c = ',';
199 }
200 if (i & 0x10) {
201 printf("%cRC", c);
202 c = ',';
203 }
204 if (i & 0x08) {
205 printf("%cEEC", c);
206 c = ',';
207 }
208 if (i & 0x04) {
209 printf("%cPER", c);
210 c = ',';
211 }
212 if (i & 0x02) {
213 printf("%cDTE", c);
214 c = ',';
215 }
216 if (i & 0x01) {
217 printf("%cDCR", c);
218 c = ',';
219 }
220 if (c == ',')
221 printf(">");
222
223 printf("\n\t%d retries, %d correction span bits,\n", cp[3],
224 cp[4]);
225 printf("\t%d head offsets, %d data strobe offsets,\n\t",
226 cp[5], cp[6]);
227 if (cp[7] != 0xff)
228 printf("%d", cp[7]);
229 else
230 printf("no");
231 printf(" recovery time limit.\n");
232 cp += 8;
233 break;
234
235 case 2:
236 printf("Disconnect/Reconnect control.\n");
237 printf("\tbuffer full ratio %d, buffer empty ratio %d,\n",
238 cp[2], cp[3]);
239 printf("\ttime limits: %d bus inactivity, ",
240 *(u_short *)&cp[4]);
241 printf("%d disconnect, %d connect.\n",
242 *(u_short *)&cp[6],*(u_short *)&cp[8]);
243 cp += 12;
244 break;
245
246 case 3:
247 {
248 struct scsi_format *sf = (struct scsi_format *)cp;
249 printf("Format parameters.\n");
250 printf("\t%d tracks/zone, %d alt.sect./zone, ",
251 sf->tracks_per_zone, sf->alt_sect_zone);
252 printf("%d alt.tracks/zone,\n\t%d alt.tracks/vol., ",
253 sf->alt_tracks_zone, sf->alt_tracks_vol);
254 printf("%d sectors/track, %d bytes/sector, interleave %d\n",
255 sf->sect_track, sf->data_sect, sf->interleave);
256 printf("\ttrack skew %d, cylinder skew %d,\n",
257 sf->track_skew_factor, sf->cyl_skew_factor);
258 printf("\tdrive type 0x%x ", i = cp[20]);
259 c = '<';
260 if (i & 0x80) {
261 printf("%cSSEC", c);
262 c = ',';
263 }
264 if (i & 0x40) {
265 printf("%cHSEC", c);
266 c = ',';
267 }
268 if (i & 0x20) {
269 printf("%cRMB", c);
270 c = ',';
271 }
272 if (i & 0x10) {
273 printf("%cSURF", c);
274 c = ',';
275 }
276 if (i & 0x08) {
277 printf("%cINS", c);
278 c = ',';
279 }
280 if (i & 0x04) {
281 printf("%c?", c);
282 c = ',';
283 }
284 if (i & 0x02) {
285 printf("%c?", c);
286 c = ',';
287 }
288 if (i & 0x01) {
289 printf("%c?", c);
290 c = ',';
291 }
292 if (c == ',')
293 printf(">");
294 printf("\n");
295 cp += 24;
296 }
297 break;
298
299 case 4:
300 printf("Disk Geometry parameters.\n");
301 printf("\t%d cylinders, %d heads.\n",
302 (cp[2] << 16) | (cp[3] << 8) | cp[4], cp[5]);
303 cp += cp[1] + 2;
304 break;
305
306 default:
307 printf("Unknown page type.");
308 for (cp += 2, i = 0; i < n; ++i) {
309 if ((i & 7) == 0)
310 printf("\n\t%2d ", i);
311 printf(" %02x", *cp++);
312 }
313 printf("\n");
314 break;
315 }
316 return (cp);
317}
318
be2c1524
KB
319void
320pr_sense(fd)
321 int fd;
322{
323 static struct scsi_fmt_sense s;
324
325 if (ioctl(fd, SDIOCSENSE, &s) < 0)
326 (void)fprintf(stderr,
327 "scsiformat: SDIOCSENSE: %s\n", strerror(errno));
328
329 (void)printf("scsi status 0x%x", s.status);
330 if (s.status & STS_CHECKCOND) {
331 struct scsi_xsense *sp = (struct scsi_xsense *)s.sense;
332
333 (void)printf(" sense class %d, code %d", sp->class, sp->code);
334 if (sp->class == 7) {
335 (void)printf(", key %d", sp->key);
336 if (sp->valid)
337 (void)printf(", blk %d", *(int *)&sp->info1);
338 }
339 }
340 (void)printf("\n");
341}
342
343void
344do_format()
345{
346 static int on = 1;
347 static int off = 0;
348 static u_char fmtbuf[128];
349 struct scsi_modesel_hdr *ms = (struct scsi_modesel_hdr *)mselbuf;
350
351 ms->block_desc_len = 8;
352 ms->block_length = 512;
353 mselbuf[12] = 32;
354 mselbuf[13] = 10;
355 mselbuf[14] = 1;
356
357 if (ioctl(fd, SDIOCSFORMAT, &on) < 0) {
358 (void)fprintf(stderr,
359 "scsiformat: SDIOCSFORMAT (on): %s\n", strerror(errno));
360 return;
361 }
362 if (ioctl(fd, SDIOCSCSICOMMAND, &modeselect) < 0)
363 (void)fprintf(stderr,
364 "scsiformat: modeselect cmd: %s\n", strerror(errno));
365 else if (write(fd, mselbuf, sizeof(mselbuf)) < 0) {
366 (void)fprintf(stderr,
367 "scsiformat: modeselect write: %s\n", strerror(errno));
368 pr_sense(fd);
369 } else if (ioctl(fd, SDIOCSCSICOMMAND, &format) < 0)
370 (void)fprintf(stderr,
371 "scsiformat: format cmd: %s\n", strerror(errno));
372 else if (write(fd, fmtbuf, sizeof(fmtbuf)) < 0) {
373 (void)fprintf(stderr,
374 "scsiformat: format write: %s\n", strerror(errno));
375 pr_sense(fd);
376 }
377 if (ioctl(fd, SDIOCSFORMAT, &off) < 0)
378 (void)fprintf(stderr,
379 "scsiformat: SDIOCSFORMAT (off): %s\n", strerror(errno));
380}
381
3a637e8d 382void
873fa9ad
KB
383do_command(fd, cdb, buf, len)
384 int fd;
385 struct scsi_fmt_cdb *cdb;
386 u_char *buf;
387 int len;
3a637e8d 388{
873fa9ad
KB
389 static int on = 1;
390 static int off = 0;
3a637e8d 391
873fa9ad
KB
392 if (ioctl(fd, SDIOCSFORMAT, &on) < 0) {
393 (void)fprintf(stderr,
394 "scsiformat: SDIOCSFORMAT (on): %s\n", strerror(errno));
395 return;
396 }
397 if (ioctl(fd, SDIOCSCSICOMMAND, cdb) < 0)
398 (void)fprintf(stderr,
399 "scsiformat: SDIOCSCSICOMMAND: %s\n", strerror(errno));
be2c1524 400 else if (read(fd, buf, len) < 0) {
873fa9ad
KB
401 (void)fprintf(stderr,
402 "scsiformat: read: %s\n", strerror(errno));
be2c1524
KB
403 pr_sense(fd);
404 }
3a637e8d 405
873fa9ad
KB
406 if (ioctl(fd, SDIOCSFORMAT, &off) < 0)
407 (void)fprintf(stderr,
408 "scsiformat: SDIOCSFORMAT (off): %s\n", strerror(errno));
3a637e8d
KB
409}
410
411void
412usage()
413{
414 (void)fprintf(stderr, "usage: scsiformat device\n");
415 exit(1);
416}