Annotation of researchv10no/cmd/worm/oscsi/scsi.cpio, revision 1.1.1.1
1.1 root 1: 0707070035050422111006660011710000040000010273220464714144700000700000003143README This is a simple extensible shell (scsish) for poking at scsi
2: devices, particularly the simpler kinds commonly called toasters.
3: it is supposed to be self-documenting in use; try the help command.
4: my use of the moran-dronek /dev/scsi library is still imperfect;
5: there is still some some debugging showing.
6:
7: To compile, you first need mk. you then have to pick a system type
8: to set some flags; currently we support research and sgi.
9: yours may differ, particularly as no one else has our ansi C compiler for the sgi.
10: the only problem i would expect is the normal header file crap you get
11: mixing ansi and non-ansi files. i recommend setting NPROC=1 while debugging hdr files.
12: if you change (header) files, try putting them in the directory inc
13: (then others may benefit). To support a new system (say sgi-gcc), just create
14: a new file sgi-gcc.mk and so on. you may be missing some devices in
15: your /dev/scsi; the script scsi/gendev may help (but check the major/minor
16: numbers and permissions).
17:
18: As for modifying/extending scsish, it has been designed to be not too hard.
19: Adding a new device means adding a new set of rules (like the other rules)
20: to mkfile and creating a new directory (say exabyte) and at least two files in it
21: (dev.c and fns.h). The wren directory is a small example you can clone.
22: Adding new functions to any device means updating a file list in mkfile,
23: updating dev.c and fns.h in the device directory. The argument syntax
24: scheme is arguably pokey, but liveable. at some future point we should probably
25: switch over to osterhout's tcl.
26:
27: as always, i invite you send extensions/fixes etc back to
28: [email protected]
29: 0707070035050453661006660011710000040000010451330457563432000000500000000565TODO | COPY drive NUMBER NUMBER drive NUMBER {/*:COPY sdrive sstart nblocks ddrive dstart:: */
30: s_copy($2, $3, $4, $5, $6);
31: }
32: | READ drive NUMBER {
33: struct scsi_ret output;
34: s_read($2, $3, 1, &output);
35: scsiodump(output.data, 1024);
36: }
37: | WRITE drive NUMBER { s_write($2, $3, 1); }
38: | WRITE drive NUMBER NUMBER { s_write($2, $3, $4); } /*:WRITE drive start n:: */
39: 0707070035050450521006660011710000040000010447750457563431100001300000002057allocate.c #include <stddef.h>
40: #include <stdio.h>
41: #include <string.h>
42: #include "scsi.h"
43: #include "juke.h"
44:
45: allocate(char *vol_id, char *buf)
46: {
47: int drive, sh;
48: char nbuf[512];
49:
50: if(j_rdshelves(buf)) /* read in shelf names */
51: return(-1);
52: if(j_getstatus(buf)) /* get the jukebox status */
53: return(-1);
54: sh = j_shelfof(vol_id);
55: if(sh >= 0){
56: sprintf(buf, "there is an existing '%s' on shelf %d", vol_id, sh);
57: return(-1);
58: }
59: sh = j_shelfof(UNALLOCATED);
60: if(sh < 0){
61: sprintf(buf, "no unallocated disks");
62: return(-1);
63: }
64: printf("using unallocated disk from shelf %d\n", sh);
65: drive = min(nlun+1, NLUN-1);
66: if(j_shelf_to_drive(sh, SIDEB, drive, buf) < 0)
67: return(-1);
68: sprintf(nbuf, "%sb", vol_id);
69: if(j_wvolid(drive, nbuf, buf))
70: return(-1);
71: j_wrshelf = 1;
72: j_shelf[sh] = strdup(vol_id);
73: if(j_drive_to_shelf(drive, sh, SIDEB, buf) < 0)
74: return(-1);
75: if(j_shelf_to_drive(sh, SIDEA, drive, buf) < 0)
76: return(-1);
77: sprintf(nbuf, "%sa", vol_id);
78: if(j_wvolid(drive, nbuf, buf))
79: return(-1);
80: if(j_drive_to_shelf(drive, sh, SIDEA, buf) < 0)
81: return(-1);
82: return(0);
83: }
84: 0707070035050452321006660011710000040000010576150463130011500000700000007736cold.c #include <stddef.h>
85: #include <stdio.h>
86: #include <string.h>
87: #include "scsi.h"
88: #include "juke.h"
89:
90: static sort(char *buf);
91:
92: cold_inv(char type, char *buf)
93: {
94: Side side;
95: int drive, sh, nsh;
96: int n;
97: char vol_id[512];
98: int didit[NSHELF];
99:
100: if(j_getstatus(buf)) /* get the jukebox status */
101: return(-1);
102: printf("getstatus done\n");
103: /* first clear out nonexistent labels */
104: n = 0;
105: for(sh = 0; sh < NSHELF; sh++){
106: if((j_status.shelf[sh]&0xC0) == 0xC0){
107: n++;
108: j_shelf[sh] = "there";
109: } else
110: j_shelf[sh] = 0;
111: didit[sh] = 0;
112: }
113: printf("%d disks in shelves.\n", n);
114: /* second, clear the drives */
115: for(sh = 0; sh < NSHELF; sh++)
116: if(j_shelf[sh] == 0)
117: break;
118: for(drive = 0; drive < 8; drive++){
119: if(!j_status.lun[drive].diskin)
120: continue; /* no disk in drive */
121: printf("clearing drive %d:\n", drive);
122: if(j_status.lun[drive].diskindrive && !j_status.lun[drive].shelfvalid){
123: if(j_drive_to_shelf(drive, sh, SIDEA, buf))
124: return(-1);
125: for(sh++; sh < NSHELF; sh++)
126: if(j_shelf[sh] == 0)
127: break;
128: n++;
129: } else
130: if(j_drive_to_shelf(drive, -1, SIDEA, buf))
131: return(-1);
132: printf("\n");
133: }
134: printf("reloading %d disks.\n", n);
135: side = SIDEA;
136: drive = min(nlun+1, NLUN-1);
137: j_wrshelf = 1;
138: for(sh = 0; sh < NSHELF; sh++){
139: if(didit[sh])
140: continue;
141: j_shelf[sh] = 0;
142: /* the C0 means disk properly present (not temp) */
143: if((j_status.shelf[sh]&0xC0) == 0xC0){
144: if(getvol(sh, drive, vol_id, &side))
145: errexit(vol_id);
146: switch(type)
147: {
148: case 'c':
149: for(nsh = 0; j_shelf[nsh]; nsh++)
150: ;
151: break;
152: case 's':
153: case 'r':
154: while(j_shelf[nsh = nrand(NSHELF)])
155: ;
156: break;
157: case 'u':
158: default:
159: nsh = sh;
160: break;
161: }
162: printf("%s@%d -> %d\n", vol_id, sh, nsh);
163: if(j_drive_to_shelf(drive, nsh, side, buf) < 0)
164: return(-1);
165: j_shelf[nsh] = strdup(vol_id);
166: didit[nsh] = 1;
167: sleep(2);
168: }
169: }
170: printf("process any new disks.\n");
171: if(warm_inv(buf))
172: return(-1);
173: if(type == 's')
174: return(sort(buf));
175: return(0);
176: }
177:
178: getvol(int sh, int drive, char *vol_id, int *side)
179: {
180: int i;
181: char buf[512];
182:
183: if(j_shelf_to_drive(sh, SIDEA, drive, vol_id) < 0)
184: return(-1);
185: if((i = j_rvolid(drive, buf)) < 0)
186: goto softerr;
187: if(i == 0)
188: *side = SIDEA;
189: else {
190: *side = SIDEB;
191: if(j_drive_to_shelf(drive, sh, SIDEA, vol_id) < 0)
192: return(-1);
193: if(j_shelf_to_drive(sh, SIDEB, drive, vol_id) < 0)
194: return(-1);
195: if((i = j_rvolid(drive, buf)) < 0)
196: goto softerr;
197: }
198: if(i > 0)
199: strcpy(vol_id, UNALLOCATED);
200: else {
201: strcpy(vol_id, buf);
202: i = strlen(vol_id)-1;
203: if(i < 0){
204: sprintf(buf, "apparently good superblock but null vol_id");
205: goto softerr;
206: } else if(vol_id[i] == 'a')
207: vol_id[i] = 0;
208: else if(vol_id[i] == 'b'){
209: vol_id[i] = 0;
210: *side = !*side;
211: } else {
212: sprintf(buf, "vol_id '%s' must end in a or b", vol_id);
213: strcpy(vol_id, buf);
214: return(-1);
215: }
216: }
217: return(0);
218: softerr:
219: *side = SIDEA;
220: fprintf(stderr, "error in reading shelf %d: %s; proceeding\n", sh, buf);
221: sprintf(vol_id, "DISK_ERROR%d", sh);
222: gen_reset(0, (int *)0, 0, (char **)0, buf);
223: return(0);
224: }
225:
226: static int index[NSHELF];
227: static
228: cmp(int *a, int *b)
229: {
230: char *sa = j_shelf[*a], *sb = j_shelf[*b];
231:
232: if((sa == 0) && (sb == 0)) return(0);
233: if(sa == 0) return(-1);
234: if(sb == 0) return(1);
235: return(strcmp(sa, sb));
236: }
237:
238: static char *disk[8];
239:
240: static
241: sd(int a, int b, char *err)
242: {
243: disk[b] = j_shelf[a];
244: return(j_shelf_to_drive(a, SIDEB, b, err));
245: }
246: static
247: ds(int a, int b, char *err)
248: {
249: j_shelf[b] = disk[a];
250: return(j_drive_to_shelf(a, b, SIDEB, err));
251: }
252:
253: static
254: sort(char *errbuf)
255: {
256: int i, j, org;
257:
258: for(i = 0; i < NSHELF; i++)
259: index[i] = i;
260: qsort(index, NSHELF, sizeof index[0], cmp);
261: for(i = 0; i < NSHELF; i++){
262: if(index[i] < 0) continue;
263: if(sd(org = i, NLUN-1, errbuf) < 0)
264: return(-1);
265: j = index[i];
266: index[i] = -1;
267: while(j != org){
268: if(sd(j, NLUN-2, errbuf) < 0)
269: return(-1);
270: if(ds(NLUN-2, i, errbuf) < 0)
271: return(-1);
272: i = j;
273: if(index[i] < 0)
274: break;
275: j = index[i];
276: index[i] = -1;
277: }
278: if(ds(NLUN-1, i, errbuf) < 0)
279: return(-1);
280: }
281: return(0);
282: }
283: 0707070035050513661006440011710000040000010044130464677201700001000000027722dslib.c /*
284: || dslib.c - library routines for /dev/scsi
285: ||
286: || Copyright 1988, 1989, by
287: || Gene Dronek (Vulcan Laboratory) and
288: || Rich Morin (Canta Forda Computer Laboratory).
289: || All rights reserved.
290: */
291: #ident "dslib.c: $Revision: 1.4 $"
292:
293: #include <stdio.h>
294: #include <sys/types.h>
295:
296: #include "dslib.h"
297: #ifdef aux
298: #include <sys/vio.h>
299: #include <sys/scsireq.h>
300: #endif aux
301:
302: int dsdebug=0;
303: long dsreqflags; /* flag bits always set by filldsreq */
304:
305: #define min(i,j) ( (i) < (j) ? (i) : (j) )
306:
307:
308: /*
309: || Startup/shutdown -----------------------------------------------
310: */
311:
312: static struct context *dsc[FDSIZ];
313:
314:
315: /*
316: || dsopen - open device, set up structures
317: */
318:
319: struct dsreq *
320: dsopen(opath, oflags)
321: char *opath;
322: int oflags;
323: {
324:
325: struct dsreq *dsp;
326: struct context *cp;
327: int fd;
328: DSDBG(fprintf(stderr,"dsopen(%s,%x) ", opath, oflags));
329:
330: fd = open(opath, oflags);
331: if (fd < 0)
332: return NULL; /* can't open */
333: if (dsc[fd] != NULL) /* already in use */
334: ds_zot("dsopen: fd already in use");
335:
336: cp = (struct context *) calloc(1, sizeof(struct context));
337: if (cp == NULL) /* can't allocate */
338: ds_zot("dsopen: can't allocate space");
339: dsc[fd] = cp;
340: cp->dsc_fd = fd;
341: dsp = &(cp->dsc_dsreq);
342:
343: dsp->ds_flags = 0;
344: dsp->ds_time = 10 * 1000; /* 10 second default timeout */
345: dsp->ds_private = (ulong) cp; /* pointer back to context */
346: dsp->ds_cmdbuf = cp->dsc_cmd;
347: dsp->ds_cmdlen = sizeof cp->dsc_cmd;
348: dsp->ds_databuf = 0;
349: dsp->ds_datalen = 0;
350: dsp->ds_sensebuf = cp->dsc_sense;
351: dsp->ds_senselen = sizeof cp->dsc_sense;
352: DSDBG(fprintf(stderr,"=>cp %x, dsp %x\n", cp, dsp));
353: return dsp;
354: }
355:
356:
357: /*
358: || dsclose - close device, release context struct.
359: */
360:
361: dsclose(dsp)
362: struct dsreq *dsp;
363: {
364: int fd;
365: struct context *cp;
366:
367: if (dsp == NULL)
368: ds_zot("dsclose: dsp is NULL");
369:
370: cp = (struct context *)dsp->ds_private;
371: fd = getfd(dsp);
372: if ( cp == NULL )
373: ds_zot("dsclose: private is NULL");
374:
375: cfree(cp);
376: dsc[fd] = (struct context *)NULL;
377: return;
378: }
379:
380:
381: /*
382: || Generic SCSI CCS Command functions ------------------------------------
383: ||
384: || dsp dsreq pointer
385: || data data buffer pointer
386: || datalen data buffer length
387: || lba logical block address
388: || vu vendor unique bits
389: */
390:
391: /*
392: || testunitready00 - issue group 0 "Test Unit Ready" command (0x00)
393: */
394:
395: testunitready00(dsp)
396: struct dsreq *dsp;
397: {
398: fillg0cmd(dsp, CMDBUF(dsp), G0_TEST, 0, 0, 0, 0, 0);
399: filldsreq(dsp, 0, 0, DSRQ_READ|DSRQ_SENSE);
400: return(doscsireq(getfd(dsp), dsp));
401: }
402:
403:
404: /*
405: || requestsense03 - issue group 0 "Request Sense" command (0x03)
406: */
407:
408: requestsense03(dsp, data, datalen, vu)
409: struct dsreq *dsp;
410: caddr_t data;
411: long datalen;
412: char vu;
413: {
414: fillg0cmd(dsp, CMDBUF(dsp), G0_REQU, 0, 0, 0, B1(datalen), B1(vu<<6));
415: filldsreq(dsp, data, datalen, DSRQ_READ);
416: return(doscsireq(getfd(dsp), dsp));
417: }
418:
419:
420: /*
421: || write0a - issue group 0 "Write" command (0x0a)
422: */
423:
424: write0a(dsp, data, datalen, lba, vu)
425: struct dsreq *dsp;
426: caddr_t data;
427: long datalen, lba;
428: char vu;
429: {
430: fillg0cmd(dsp, CMDBUF(dsp), G0_WRIT, B3(lba), B1(datalen), B1(vu<<6));
431: filldsreq(dsp, data, datalen, DSRQ_READ);
432: return(doscsireq(getfd(dsp), dsp));
433: }
434:
435:
436: /*
437: || inquiry12 - issue group 0 "Inquiry" command (0x12)
438: */
439:
440: inquiry12(dsp, data, datalen, vu)
441: struct dsreq *dsp;
442: caddr_t data;
443: long datalen;
444: char vu;
445: {
446: fillg0cmd(dsp, CMDBUF(dsp), G0_INQU, 0, 0, 0, B1(datalen), B1(vu<<6));
447: filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE);
448: return(doscsireq(getfd(dsp), dsp));
449: }
450:
451:
452: /*
453: || modeselect15 - issue group 0 "Mode Select" command (0x15)
454: ||
455: || save 0 - don't save saveable pages
456: || 1 - save saveable pages
457: */
458:
459: modeselect15(dsp, data, datalen, save, vu)
460: struct dsreq *dsp;
461: caddr_t data;
462: long datalen;
463: char save, vu;
464: {
465: fillg0cmd(dsp, CMDBUF(dsp), G0_MSEL, save&1, 0, 0, B1(datalen), B1(vu<<6));
466: filldsreq(dsp, data, datalen, DSRQ_WRITE|DSRQ_SENSE);
467: return(doscsireq(getfd(dsp), dsp));
468: }
469:
470:
471: /*
472: || modesense1a - issue group 0 "Mode Sense" command (0x1a)
473: ||
474: || pagectrl 0 - current values
475: || 1 - changeable values
476: || 2 - default values
477: || 3 - saved values
478: ||
479: || pagecode 0 - vendor unique
480: || 1 - error recovery
481: || 2 - disconnect/reconnect
482: || 3 - direct access dev. fmt.
483: || 4 - rigid disk geometry
484: || 5 - flexible disk
485: || 6-9 - see specific dev. types
486: || 0a - implemented options
487: || 0b - medium types supported
488: || 3f - return all pages
489: */
490:
491: modesense1a(dsp, data, datalen, pagectrl, pagecode, vu)
492: struct dsreq *dsp;
493: caddr_t data;
494: long datalen;
495: char pagectrl, pagecode, vu;
496: {
497: fillg0cmd(dsp, CMDBUF(dsp), G0_MSEN, 0x10,
498: ((pagectrl&3)<<6) | (pagecode&0x3F),
499: 0, B1(datalen), B1(vu<<6));
500: filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE);
501: return(doscsireq(getfd(dsp), dsp));
502: }
503:
504:
505: /*
506: || senddiagnostic1d - issue group 0 "Send Diagnostic" command (0x1d)
507: ||
508: || self 0 - run test, hold results
509: || 1 - run test, return status
510: ||
511: || dofl 0 - device online
512: || 1 - device offline
513: ||
514: || uofl 0 - unit online
515: || 1 - unit offline
516: */
517:
518: senddiagnostic1d(dsp, data, datalen, self, dofl, uofl, vu)
519: struct dsreq *dsp;
520: caddr_t data;
521: long datalen;
522: char self, dofl, uofl, vu;
523: {
524: fillg0cmd(dsp, CMDBUF(dsp), G0_MSEN,
525: (self&1)<<2 | (dofl&1)<<1 | (uofl&1),
526: 0, B2(datalen), B1(vu<<6));
527: filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE);
528: return(doscsireq(getfd(dsp), dsp));
529: }
530:
531:
532: /*
533: || readcapacity25 - issue group 1 "Read Capacity" command (0x25)
534: ||
535: || pmi 0 - return last logical block, entire unit
536: || 1 - return last logical block, current track
537: */
538:
539: readcapacity25(dsp, data, datalen, lba, pmi, vu)
540: struct dsreq *dsp;
541: caddr_t data;
542: long datalen, lba;
543: char pmi, vu;
544: {
545: fillg1cmd(dsp, CMDBUF(dsp), G1_RCAP, 0, B4(lba), 0, 0, pmi&1, B1(vu<<6));
546: filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE
547: /* |DSRQ_CTRL2 */ );
548: /* dsp->ds_time = 100; /* often takes a while */
549: return(doscsireq(getfd(dsp), dsp));
550: }
551:
552:
553: /*
554: || readextended28 - issue group 1 "Read Extended" command (0x28)
555: */
556:
557: readextended28(dsp, data, datalen, lba, vu)
558: struct dsreq *dsp;
559: caddr_t data;
560: long datalen, lba;
561: char vu;
562: {
563: fillg1cmd(dsp, CMDBUF(dsp), G1_READ, 0, B4(lba), 0, B2(datalen), B1(vu<<6));
564: filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE
565: /* |DSRQ_CTRL2 */ );
566: /* dsp->ds_time = 100; /* often takes a while */
567: return(doscsireq(getfd(dsp), dsp));
568: }
569:
570:
571: /*
572: || writeextended2a - issue group 1 "Write Extended" command (0x2a)
573: */
574:
575: writeextended2a(dsp, data, datalen, lba, vu)
576: struct dsreq *dsp;
577: caddr_t data;
578: long datalen, lba;
579: char vu;
580: {
581: fillg1cmd(dsp, CMDBUF(dsp), G1_WRIT, 0, B4(lba), 0, B2(datalen), B1(vu<<6));
582: filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE
583: /* |DSRQ_CTRL2 */ );
584: /* dsp->ds_time = 100; /* often takes a while */
585: return(doscsireq(getfd(dsp), dsp));
586: }
587:
588:
589: /*
590: || Support functions ----------------------------------------------------
591: */
592:
593: /*
594: || fillg0cmd - Fill a Group 0 command buffer
595: */
596:
597: fillg0cmd(dsp, cmd, b0,b1,b2,b3,b4,b5)
598: struct dsreq *dsp;
599: uchar_t *cmd, b0,b1,b2,b3,b4,b5;
600: {
601: uchar_t *c = cmd;
602: DSDBG(fprintf(stderr,"fillg0cmd(%x,%x, %02x %02x %02x %02x %02x %02x)\n",
603: dsp, cmd, b0,b1,b2,b3,b4,b5));
604: *c++ = b0, *c++ = b1, *c++ = b2, *c++ = b3, *c++ = b4, *c++ = b5;
605:
606: CMDBUF(dsp) = (caddr_t) cmd;
607: CMDLEN(dsp) = 6;
608: }
609:
610:
611: /*
612: || fillg1cmd - Fill a Group 1 command buffer
613: */
614:
615: fillg1cmd(dsp, cmd, b0,b1,b2,b3,b4,b5,b6,b7,b8,b9)
616: struct dsreq *dsp;
617: uchar_t *cmd, b0,b1,b2,b3,b4,b5,b6,b7,b8,b9;
618: {
619: uchar_t *c = cmd;
620: DSDBG(fprintf(stderr,
621: "fillg1cmd(%x,%x, %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x)\n",
622: dsp, cmd, b0,b1,b2,b3,b4,b5,b6,b7,b8,b9));
623:
624: *c++ = b0, *c++ = b1, *c++ = b2, *c++ = b3, *c++ = b4, *c++ = b5;
625: *c++ = b6, *c++ = b7, *c++ = b8, *c++ = b9;
626:
627: CMDBUF(dsp) = (caddr_t) cmd;
628: CMDLEN(dsp) = 10;
629: }
630:
631:
632: /*
633: || filldsreq - Fill a dsreq structure
634: */
635:
636: filldsreq(dsp,data,datalen,flags)
637: struct dsreq *dsp;
638: uchar_t *data;
639: {
640: DSDBG(fprintf(stderr,"filldsreq(%x,%x,%d,%x) cmdlen %d\n",
641: dsp,data,datalen,flags,CMDLEN(dsp)));
642: dsp->ds_flags = flags | dsreqflags |
643: (((dsdebug&1) ? DSRQ_TRACE : 0) |
644: ((dsdebug&2) ? DSRQ_PRINT : 0));
645: dsp->ds_time = 10 * 1000; /* default to 10 seconds */
646: dsp->ds_link = 0;
647: dsp->ds_synch = 0;
648: dsp->ds_ret = 0;
649:
650: DATABUF(dsp) = (caddr_t) data;
651: DATALEN(dsp) = datalen;
652: }
653:
654:
655: /*
656: || bprint - print array of bytes, in hex.
657: */
658:
659: #define hex(x) "0123456789ABCDEF" [ (x) & 0xF ]
660:
661: bprint(s,n,nperline,space)
662: char *s;
663: {
664: int i, x;
665: char *sp = (space) ? " ": "";
666:
667: for(i=0;i<n;i++) {
668: x = s[i];
669: fprintf(stderr,((i%4==3)?"%c%c%s%s":"%c%c%s"),
670: hex(x>>4), hex(x), sp, sp);
671: if ( i%nperline == (nperline - 1) )
672: fprintf(stderr,"\n");
673: }
674: if ( space )
675: fprintf(stderr,"\n");
676: }
677:
678:
679: /*
680: || doscsireq - issue scsi command, return status or -1 error.
681: */
682:
683: doscsireq( fd, dsp)
684: int fd; /* ioctl file descriptor */
685: struct dsreq *dsp; /* devscsi request packet */
686: {
687: int cc;
688: int retries = 4;
689: uchar_t sbyte;
690:
691: DSDBG(fprintf(stderr,"doscsireq(%d,%x) %x ---- %s\n",fd,dsp,
692: (CMDBUF(dsp))[0],
693: ds_vtostr( (CMDBUF(dsp))[0], cmdnametab)));
694:
695: /*
696: * loop, issuing command
697: * until done, or further retry pointless
698: */
699:
700: while ( --retries > 0 ) {
701:
702: caddr_t sp;
703:
704: sp = SENSEBUF(dsp);
705: DSDBG(fprintf(stderr,"cmdbuf = ");
706: bprint(CMDBUF(dsp),CMDLEN(dsp),16,1));
707: if ( (dsp->ds_flags & DSRQ_WRITE) )
708: DSDBG(bprint( DATABUF(dsp), min(50,DATALEN(dsp)),16,1 ));
709:
710: DSDBG(fprintf(stderr,"databuf datalen %x %d\n",DATABUF(dsp), DATALEN(dsp)));
711: cc = ioctl( fd, DS_ENTER, dsp);
712: if ( cc < 0) {
713: ds_panic(dsp, "cannot ioctl fd %d\n",fd);
714: }
715:
716: DSDBG(fprintf(stderr,"cmdlen after ioctl=%d\n",CMDLEN(dsp)));
717: DSDBG(fprintf(stderr,"ioctl=%d ret=%x %s",
718: cc, RET(dsp),
719: RET(dsp) ? ds_vtostr(RET(dsp),dsrtnametab) : ""));
720: DSDBG(if (SENSESENT(dsp)) fprintf(stderr," sensesent=%d",
721: SENSESENT(dsp)));
722:
723: DSDBG(fprintf(stderr,
724: " cmdsent=%d datasent=%d sbyte=%x %s\n",
725: CMDSENT(dsp), DATASENT(dsp), STATUS(dsp),
726: ds_vtostr(STATUS(dsp), cmdstatustab)));
727: DSDBG(if ( FLAGS(dsp) & DSRQ_READ )
728: bprint( DATABUF(dsp), min(16*16,DATASENT(dsp)), 16,1));
729:
730: #ifdef aux
731: /*
732: * check for AUX bus-error
733: * we retry with poll-dma
734: */
735: if ( RET(dsp) == DSRT_AGAIN ) {
736: int n = SDC_RDPOLL|SDC_WRPOLL;
737: DSDBG(fprintf(stderr,"setting rd/wr-poll"));
738: cc = ioctl( fd, DS_SET, n); /* set bits */
739: if ( cc != 0 )
740: return -1;
741: }
742: #endif aux
743:
744: if ( RET(dsp) == DSRT_NOSEL )
745: continue; /* retry noselect 3X */
746:
747: /* decode sense data returned */
748: if ( SENSESENT(dsp) ) {
749: DSDBG(
750: fprintf(stderr, "sense key %x - %s\n",
751: SENSEKEY(sp),
752: ds_vtostr( SENSEKEY(sp), sensekeytab));
753: bprint( SENSEBUF(dsp),
754: min(100, SENSESENT(dsp)),
755: 16,1);
756: );
757: }
758: DSDBG(fprintf(stderr, "sbyte %x\n", STATUS(dsp)));
759:
760: /* decode scsi command status byte */
761: sbyte = STATUS(dsp);
762: switch (sbyte) {
763: case 0x08: /* BUSY */
764: case 0x18: /* RESERV CONFLICT */
765: sleep(2);
766: continue;
767: case 0x00: /* GOOD */
768: case 0x02: /* CHECK CONDITION */
769: case 0x10: /* INTERM/GOOD */
770: default:
771: return sbyte;
772: }
773: }
774: return -1; /* fail retry limit */
775: }
776:
777:
778: /*
779: || opttovar - lookup option in table, return var addr (NULL if fail)
780: */
781:
782: int *
783: opttovar( ostr, table)
784: char *ostr;
785: struct opttab{
786: char *opt;
787: int *var;
788: } *table;
789: {
790: register struct opttab *tp;
791:
792: for (tp=table; (tp->var); tp++)
793: if ( strncmp( ostr, tp->opt, 3) == 0 )
794: break;
795:
796: if ( !tp->var )
797: fprintf(stderr,"unknown option %s", ostr);
798:
799: return (tp->var);
800: }
801:
802:
803: /*
804: || ds_vtostr - lookup value in table to return string pointer
805: */
806:
807: char *
808: ds_vtostr( v, table)
809: long v;
810: struct vtab *table;
811: {
812: register struct vtab *tp;
813:
814: for (tp=table; (tp->string); tp++)
815: if ( v == tp->val )
816: break;
817:
818: return (tp->string) ? tp->string : "";
819: }
820:
821:
822: /*
823: || ds_panic - yelp, leave...
824: */
825:
826: ds_panic( fmt, v)
827: char *fmt;
828: int v;
829: {
830: extern errno;
831:
832: fprintf(stderr,fmt,v);
833: fprintf(stderr,"\nerrno = %d\n",errno);
834: exit(1);
835: }
836:
837:
838: /*
839: || ds_zot - go away, with a message.
840: */
841:
842: ds_zot(message)
843: char *message;
844: {
845: fprintf(stderr, "%s\n", message);
846: exit(1);
847: }
848: 0707070035050453640407770011710000040000020451370464700560700001000000000000generic 0707070035050453631006660011710000040000010255410464713532400001600000002147generic/dev.c #include <stdio.h>
849: #include "../scsi.h"
850: #include "../scsish.h"
851: #include "fns.h"
852:
853: static int gen_id(int, int *, int, char **, char *);
854:
855: static Function fns[] = {
856: { "capacity", "capacity [lun=0]", "L?", gen_capacity },
857: { "display", "display", "", gen_display },
858: { "dev", "dev [type] # dev ? for list", "S?", gen_dev },
859: { "help", "help [cmd]", "S?", gen_help },
860: { "id", "id [target=0]", "L?", gen_id },
861: { "inq", "inq [lun=0]", "L?", gen_inq },
862: { "readt", "readt count [lun=0]", "IL?", gen_readt },
863: { "reset", "reset", "", gen_reset },
864: { "scsi", "scsi bytes... # 6 or 10", "I?I?I?I?I?I?I?I?I?I?", gen_scsi },
865: { "sense", "sense [lun=0]", "L?", gen_sense },
866: { "start", "start [lun=0]", "L?", gen_start },
867: { "stop", "stop [lun=0]", "L?", gen_stop },
868: { "testunit", "testunit [lun=0", "L?", gen_tur },
869: { 0 }
870: };
871:
872: Device genericdev = {
873: "scsi", "generic scsi",
874: gen_extsense,
875: fns
876: };
877:
878: static int
879: gen_id(int niargs, int *iargs, int ncargs, char **cargs, char *err)
880: {
881: #pragma ref ncargs
882: #pragma ref cargs
883: #pragma ref err
884:
885: if(niargs == 0)
886: printf("current SCSI id = %d\n", s_id);
887: else
888: scsi_target(iargs[0]);
889: return(0);
890: }
891: 0707070035050453621006660011710000040000010255560464677353600001600000002107generic/inq.c #include <stdio.h>
892: #include "../scsi.h"
893: #include "../scsish.h"
894: #include "fns.h"
895:
896: char *gen_rmb[2] = { "nonremovable", "removable" };
897: char *gen_devtype[256] = {
898: "direct access",
899: "sequential access",
900: "printer",
901: "processor",
902: "worm",
903: "cd-rom"
904: };
905:
906: int
907: gen_inq(int niargs, int *iargs, int ncargs, char **cargs, char *err)
908: {
909: struct scsi_cmd cmd;
910: struct scsi_return ret;
911: int n, i;
912:
913: #pragma ref ncargs
914: #pragma ref cargs
915:
916: if(niargs == 0)
917: for(niargs = 0; niargs < 8; niargs++)
918: iargs[niargs] = niargs;
919: for(i = 0; i < niargs; i++){
920: set6(cmd, 0x12, iargs[i]<<5, 0, 0, 36, 0);
921: if(n = s_io(0, &cmd, 0, &ret, -36, err))
922: return(n);
923: printf("inq(%d,%d): %s %s;", s_id, iargs[i],
924: gen_rmb[ret.data[1]>>7], gen_devtype[ret.data[0]]);
925: if(ret.data[4] >= 16){
926: char buf[256];
927:
928: fixedstr(&ret.data[8], 8, buf);
929: printf(" %s", buf);
930: if(ret.data[4] >= 32){
931: fixedstr(&ret.data[16], 16, buf);
932: printf("/%s", buf);
933: if(ret.data[4] >= 36){
934: fixedstr(&ret.data[32], 4, buf);
935: printf(" rev=%s", buf);
936: }
937: }
938: }
939: printf(" [%d bytes]\n", ret.data[4]);
940: }
941: return(0);
942: }
943: 0707070035050453611006660011710000040000011500150464667004700002000000002650generic/sense.c #include <stdio.h>
944: #include "../scsi.h"
945: #include "../scsish.h"
946: #include "fns.h"
947:
948: int
949: gen_sense(int niargs, int *iargs, int ncargs, char **cargs, char *err)
950: {
951: struct scsi_cmd cmd;
952: struct scsi_return ret;
953: int n;
954:
955: #pragma ref ncargs
956: #pragma ref cargs
957:
958: if(niargs == 0)
959: iargs[0] = 0;
960: set6(cmd, 0x03, iargs[0]<<5, 0, 0, 4, 0);
961: if(n = s_io(0, &cmd, 0, &ret, 4, err))
962: return(n);
963: printf("sense(%d,%d): ", s_id, iargs[0]);
964: if((ret.data[0]&0x7F) == 0)
965: printf("no error\n");
966: else {
967: printf("error class=0x%x, code=0x%x, sense=0x%x",
968: (ret.data[0]>>4)&7, ret.data[0]&0xF, ret.data[2]&0xF);
969: if(ret.data[0]&0x80)
970: printf(", addr=0x%x", ret.data[3]+256L*ret.data[2]+256L*256*ret.data[1]);
971: printf("\n");
972: }
973: return(0);
974: }
975:
976: static char *exstab[16] =
977: {
978: "no sense",
979: "recovered error",
980: "not ready",
981: "medium error",
982: "hardware error",
983: "illegal request",
984: "unit attention",
985: "data protect",
986: "blank check",
987: "vendor specific (#9)",
988: "copy aborted",
989: "aborted command",
990: "equal",
991: "volume overflow",
992: "miscompare",
993: "reserved (#f)",
994: };
995:
996: void
997: gen_extsense(uchar *data, char *dest, int ndata)
998: {
999: int class;
1000:
1001: class = (data[0]>>4)&7;
1002: if(class == 7){
1003: if(data[0]&0x80)
1004: sprintf(dest, "extended sense: %s info=#%2.2x#%2.2x#%2.2x#%2.2x", exstab[data[2]&0xF], data[3], data[4], data[5], data[6]);
1005: else
1006: sprintf(dest, "extended sense: %s", exstab[data[2]&0xF]);
1007: } else {
1008: sprintf(dest, "sense: class=#%x, code=#%x", class, data[0]&0xF);
1009: }
1010: }
1011: 0707070035050453571006660011710000040000010451570457563432000002000000000613generic/start.c #include <stdio.h>
1012: #include "../scsi.h"
1013: #include "../scsish.h"
1014: #include "fns.h"
1015:
1016: int
1017: gen_start(int niargs, int *iargs, int ncargs, char **cargs, char *err)
1018: {
1019: struct scsi_cmd cmd;
1020: struct scsi_return ret;
1021: int n;
1022:
1023: #pragma ref ncargs
1024: #pragma ref cargs
1025:
1026: if(niargs == 0)
1027: iargs[0] = 0;
1028: set6(cmd, 0x1B, iargs[0]<<5, 0, 0, 1, 0);
1029: if(n = s_io(0, &cmd, 0, &ret, 0, err))
1030: return(n);
1031: return(0);
1032: }
1033: 0707070035050453561006660011710000040000010451730457563432000001700000000612generic/stop.c #include <stdio.h>
1034: #include "../scsi.h"
1035: #include "../scsish.h"
1036: #include "fns.h"
1037:
1038: int
1039: gen_stop(int niargs, int *iargs, int ncargs, char **cargs, char *err)
1040: {
1041: struct scsi_cmd cmd;
1042: struct scsi_return ret;
1043: int n;
1044:
1045: #pragma ref ncargs
1046: #pragma ref cargs
1047:
1048: if(niargs == 0)
1049: iargs[0] = 0;
1050: set6(cmd, 0x1B, iargs[0]<<5, 0, 0, 0, 0);
1051: if(n = s_io(0, &cmd, 0, &ret, 0, err))
1052: return(n);
1053: return(0);
1054: }
1055: 0707070035050453551006660011710000040000010451750457563432000002300000001115generic/capacity.c #include <stdio.h>
1056: #include "../scsi.h"
1057: #include "../scsish.h"
1058: #include "fns.h"
1059:
1060: int
1061: gen_capacity(int niargs, int *iargs, int ncargs, char **cargs, char *err)
1062: {
1063: struct scsi_cmd cmd;
1064: struct scsi_return ret;
1065: int n;
1066: unsigned long ns, ss;
1067:
1068: #pragma ref ncargs
1069: #pragma ref cargs
1070:
1071: if(niargs == 0)
1072: iargs[0] = 0;
1073: set10(cmd, 0x25, iargs[0]<<5, 0, 0, 0, 0, 0, 0, 0, 0);
1074: if(n = s_io(0, &cmd, 0, &ret, 8, err))
1075: return(n);
1076: ns = longat(&ret.data[0]);
1077: ss = longat(&ret.data[4]);
1078: printf("capacity(%d,%d): %ld blocks of %ld bytes (#%xx#%x)\n", s_id, iargs[0],
1079: ns, ss, ns, ss);
1080: return(0);
1081: }
1082: 0707070035050453541006660011710000040000010451770457563432000002200000002323generic/display.c #include <stdio.h>
1083: #include "../scsi.h"
1084: #include "../scsish.h"
1085: #include "fns.h"
1086:
1087: extern char *gen_rmb[2];
1088: extern char *gen_devtype[256];
1089:
1090: int
1091: gen_display(int niargs, int *iargs, int ncargs, char **cargs, char *err)
1092: {
1093: struct scsi_cmd cmd;
1094: struct scsi_return ret;
1095: int n, i, old_id;
1096: int retv = 0;
1097: char rev[100], vendor[100], product[100];
1098:
1099: #pragma ref niargs
1100: #pragma ref iargs
1101: #pragma ref ncargs
1102: #pragma ref cargs
1103:
1104: old_id = s_id;
1105: for(s_id = 0; s_id < 8; s_id++){
1106: printf("target %d:\n");
1107: set6(cmd, 0x00, 0, 0, 0, 0, 0);
1108: if(s_io(0, &cmd, 0, &ret, 0, err))
1109: continue;
1110: printf("responded to test unit ready\n");
1111: continue;
1112: for(i = 0; i < 8; i++){
1113: set6(cmd, 0x12, i<<5, 0, 0, 36, 0);
1114: if(n = s_io(0, &cmd, 0, &ret, -36, err)){
1115: retv = n;
1116: break;
1117: }
1118: if(ret.nread >= 16)
1119: fixedstr(&ret.data[8], 8, vendor);
1120: else
1121: sprintf(vendor, "??");
1122: if(ret.nread >= 32)
1123: fixedstr(&ret.data[16], 16, product);
1124: else
1125: sprintf(product, "??");
1126: if(ret.nread >= 16)
1127: fixedstr(&ret.data[32], 4, rev);
1128: else
1129: sprintf(vendor, "??");
1130: printf("\tlun(%d): %s %s, %s/%s rev=%s\n", i,
1131: gen_rmb[ret.data[1]>>7], gen_devtype[ret.data[0]],
1132: vendor, product, rev);
1133: }
1134: }
1135: s_id = old_id;
1136: return(retv);
1137: }
1138: 0707070035050453531006660011710000040000011504230464700546400002000000000753generic/reset.c #include <stdio.h>
1139: #include "../scsi.h"
1140: #include "../scsish.h"
1141: #include "fns.h"
1142: #include <scsi.h>
1143:
1144: int
1145: gen_reset(int niargs, int *iargs, int ncargs, char **cargs, char *err)
1146: {
1147: struct scsi_cmd cmd;
1148: struct scsi_return ret;
1149:
1150: #pragma ref niargs
1151: #pragma ref iargs
1152: #pragma ref ncargs
1153: #pragma ref cargs
1154:
1155: set6(cmd, 0, 0, 0, 0, 0, 0);
1156: cmd.bus_id = s_id;
1157: cmd.flags |= SCSI_RESET | SCSI_BRESET;
1158: /* should probably test for some kind of error... */
1159: ss_io(0, &cmd, 0, &ret, 0, err);
1160: return(0);
1161: }
1162: 0707070035050453521006660011710000040000010452030457563432100001600000000674generic/tur.c #include <stdio.h>
1163: #include "../scsi.h"
1164: #include "../scsish.h"
1165: #include "fns.h"
1166:
1167: int
1168: gen_tur(int niargs, int *iargs, int ncargs, char **cargs, char *err)
1169: {
1170: struct scsi_cmd cmd;
1171: struct scsi_return ret;
1172: int n;
1173:
1174: #pragma ref ncargs
1175: #pragma ref cargs
1176:
1177: if(niargs == 0)
1178: iargs[0] = 0;
1179: set6(cmd, 0x00, iargs[0]<<5, 0, 0, 0, 0);
1180: if(n = s_io(0, &cmd, 0, &ret, 0, err))
1181: return(n);
1182: printf("(%d,%d): good status\n", s_id, iargs[0]);
1183: return(0);
1184: }
1185: 0707070035050453511006660011710000040000010452040457563432100001700000001215generic/scsi.c #include <stdio.h>
1186: #include "../scsi.h"
1187: #include "../scsish.h"
1188: #include "fns.h"
1189:
1190: int
1191: gen_scsi(int niargs, int *iargs, int ncargs, char **cargs, char *err)
1192: {
1193: struct scsi_cmd cmd;
1194: struct scsi_return ret;
1195: int n;
1196:
1197: #pragma ref ncargs
1198: #pragma ref cargs
1199:
1200: switch(niargs)
1201: {
1202: case 6:
1203: set6(cmd, iargs[0], iargs[1], iargs[2], iargs[3], iargs[4], iargs[5]);
1204: break;
1205: case 10:
1206: set10(cmd, iargs[0], iargs[1], iargs[2], iargs[3], iargs[4], iargs[5], iargs[6], iargs[7], iargs[8], iargs[9]);
1207: break;
1208: default:
1209: sprintf(err, "number of bytes (%d) must be 6 or 10\n", niargs);
1210: return(1);
1211: }
1212: if(n = s_io(0, &cmd, 0, &ret, 0, err))
1213: return(n);
1214: return(0);
1215: }
1216: 0707070035050453501006660011710000040000010255540464677346100001600000001234generic/fns.h extern int gen_inq(int, int *, int, char **, char *);
1217: extern int gen_dev(int, int *, int, char **, char *);
1218: extern int gen_help(int, int *, int, char **, char *);
1219: extern int gen_sense(int, int *, int, char **, char *);
1220: extern int gen_start(int, int *, int, char **, char *);
1221: extern int gen_stop(int, int *, int, char **, char *);
1222: extern int gen_capacity(int, int *, int, char **, char *);
1223: extern int gen_display(int, int *, int, char **, char *);
1224: extern int gen_reset(int, int *, int, char **, char *);
1225: extern int gen_tur(int, int *, int, char **, char *);
1226: extern int gen_scsi(int, int *, int, char **, char *);
1227: extern int gen_readt(int, int *, int, char **, char *);
1228: 0707070035050513641006660011710000040000010255520464677343300002000000002007generic/readt.c #include <stdio.h>
1229: #include "../scsi.h"
1230: #include "../scsish.h"
1231: #include "fns.h"
1232:
1233: int
1234: gen_readt(int niargs, int *iargs, int ncargs, char **cargs, char *err)
1235: {
1236: struct scsi_cmd cmd;
1237: struct scsi_return ret;
1238: int n, i;
1239: unsigned long ns, ss;
1240: long bs, addr;
1241: long t1, t2;
1242:
1243: #pragma ref ncargs
1244: #pragma ref cargs
1245:
1246: if(niargs == 1)
1247: iargs[1] = 0;
1248: set10(cmd, 0x25, iargs[1]<<5, 0, 0, 0, 0, 0, 0, 0, 0);
1249: if(n = s_io(0, &cmd, 0, &ret, 8, err))
1250: return(n);
1251: ns = longat(&ret.data[0]);
1252: ss = longat(&ret.data[4]);
1253: bs = ss? sizeof(ret.data)/ss : 1;
1254: time(&t1);
1255: srand(t1);
1256: addr = nrand(ns-iargs[0])-1;
1257: printf("read(%d,%d): %d blocks @%d (chunk=%dx%d),", s_id, iargs[1], iargs[0], addr, bs, ss);
1258: fflush(stdout);
1259: time(&t1);
1260: for(i = iargs[0]; i > 0; i -= bs){
1261: set10(cmd, 0x28, iargs[1]<<5, addr>>24, addr>>16, addr>>8, addr,
1262: 0, 0, bs*0, 0);
1263: if(n = s_io(0, &cmd, 0, &ret, bs*ss, err))
1264: return(n);
1265: addr += bs;
1266: }
1267: time(&t2);
1268: printf(" t=%ds (%.0fKB/s)\n", t2-t1, (iargs[0]*(float)ss/1024.)/((t1 == t2)? 1:t2-t1));
1269: return(0);
1270: }
1271: 0707070035050450541006660011710000040000010253650464677245500001400000001727getstatus.c #include <stddef.h>
1272: #include <stdio.h>
1273: #include "scsi.h"
1274: #include "juke.h"
1275:
1276: struct Jstatus j_status;
1277:
1278: static
1279: dolun(struct Lunstatus *lun, uchar *u)
1280: {
1281: lun->poweron = ((*u)&0x80) == 0;
1282: lun->diskin = ((*u)&0x40) != 0;
1283: lun->ready = ((*u)&0x01) != 0;
1284: u++;
1285: lun->diskindrive = ((*u)&0x80) != 0;
1286: lun->driveshelf = (*u)&0x7F;
1287: u++;
1288: lun->shelfvalid = ((*u)&0x80) != 0;
1289: lun->retshelf = (*u)&0x7F;
1290: }
1291:
1292: j_getstatus(char *err)
1293: {
1294: struct scsi_cmd cmd;
1295: struct scsi_return ret;
1296: int i;
1297:
1298: set6(cmd, 0x1D, 0, 0, 0, 10, 0);
1299: memset(cmd.data, 0, 10);
1300: cmd.data[0] = 0xE2;
1301: if(s_io(1, &cmd, 10, &ret, 0, err))
1302: return(-1);
1303: set6(cmd, 0x1C, 0, 0, 0, 128, 0);
1304: if(s_io(0, &cmd, 0, &ret, 128, err))
1305: return(-1);
1306: for(i = 0; i < 8; i++)
1307: dolun(&j_status.lun[i], &ret.data[16+4*i]);
1308: for(i = 0; i < NSHELF; i++)
1309: j_status.shelf[i] = ret.data[48+i];
1310: j_status.iounit = ret.data[98];
1311: j_status.carrier = ret.data[99];
1312: j_status.udrive = ret.data[100];
1313: j_status.ldrive = ret.data[101];
1314: return(0);
1315: }
1316: 0707070035050422060407770011710000040000020273120464713312700000400000000000inc 0707070035050422051006660011710000040000010273140464713312700001300000000247inc/scsi.h #define SCSI_WR 0x80
1317: #define SCSI_RD 0x40
1318: #define SCSI_BRESET 0x20
1319: #define SCSI_RESET 0x10
1320: #define SCSI_SENSE 0x08
1321: #define SCSI_LTMOUT 0x04
1322:
1323:
1324: #define SCSI_CERR 0x01
1325: 0707070035050450411006660011710000040000010450110457563431200001200000002035iodr_sh.c #include "scsi.h"
1326: #include "juke.h"
1327:
1328: j_shelf_to_drive(int sh, Side side, int dr, char *err)
1329: {
1330: struct scsi_cmd cmd;
1331: struct scsi_return ret;
1332:
1333: set6(cmd, 0xD6, dr<<5, 0, (sh<<1)|side, 0, 0);
1334: return(s_io(0, &cmd, 0, &ret, 0, err));
1335: }
1336:
1337: j_drive_to_shelf(int dr, int sh, Side side, char *err)
1338: {
1339: struct scsi_cmd cmd;
1340: struct scsi_return ret;
1341:
1342: if(sh < 0)
1343: set6(cmd, 0xD7, dr<<5, 0, 0, 0, 0);
1344: else
1345: set6(cmd, 0xD7, (dr<<5)|1, 0, (sh<<1)|side, 0, 0);
1346: return(s_io(0, &cmd, 0, &ret, 0, err));
1347: }
1348:
1349: int
1350: j_empty_drive(long tlimit, char *buf)
1351: {
1352: int i, tstop;
1353:
1354: tstop = time((long *)0) + tlimit;
1355: while(time((long *)0) <= tstop){
1356: setnlun(); /* in case it changes */
1357: /* look for empty drives */
1358: for(i = 0; i < nlun; i++)
1359: if(!j_status.lun[i].diskin)
1360: return(i);
1361: /* look for spun down drives */
1362: for(i = 0; i < nlun; i++){
1363: if(!j_status.lun[i].ready){
1364: if(j_drive_to_shelf(i, -1, SIDEA, buf))
1365: return(-1);
1366: else
1367: return(i);
1368: }
1369: }
1370: sleep(10);
1371: if(j_getstatus(buf)) /* get the jukebox status */
1372: return(-1);
1373: }
1374: return(-1);
1375: }
1376: 0707070035050450401006660011710000040000010450120457563431300001400000002643ioshelves.c #include <stddef.h>
1377: #include <stdio.h>
1378: #include <string.h>
1379: #include "scsi.h"
1380: #include "juke.h"
1381:
1382: char *j_shelf[NSHELF];
1383: int j_wrshelf = 0;
1384:
1385: j_rdshelves(char *err)
1386: {
1387: FILE *fp;
1388: static haveread = 0;
1389: int shno;
1390: char vname[256];
1391:
1392: if(haveread)
1393: return(0);
1394: for(shno = 0; shno < NSHELF; shno++)
1395: j_shelf[shno] = 0;
1396: if((fp = fopen(JUKEDIR, "r")) == NULL){
1397: pperror(err, JUKEDIR);
1398: return(-1);
1399: }
1400: while(fscanf(fp, "%d %s\n", &shno, vname) == 2){
1401: if((shno < 0) || (shno >= NSHELF)){
1402: fprintf(stderr, "Warning: bad shelf number in %s: %d (vol_id=%s)\n",
1403: JUKEDIR, shno, vname);
1404: continue;
1405:
1406: }
1407: j_shelf[shno] = strdup(vname);
1408: }
1409: fclose(fp);
1410: haveread = 1;
1411: return(0);
1412: }
1413:
1414: j_wrshelves(char *err)
1415: {
1416: FILE *fp;
1417: int shno;
1418:
1419: if((fp = fopen(JUKEDIR, "w")) == NULL){
1420: pperror(err, JUKEDIR);
1421: return(-1);
1422: }
1423: for(shno = 0; shno < NSHELF; shno++)
1424: if(j_shelf[shno])
1425: fprintf(fp, "%d %s\n", shno, j_shelf[shno]);
1426: fclose(fp);
1427: return(0);
1428: }
1429:
1430: int
1431: j_shelfof(char *vol_id)
1432: {
1433: int i;
1434: char buf[512];
1435:
1436: for(;;){
1437: for(i = 0; i < NSHELF; i++)
1438: if(j_shelf[i] && (strcmp(j_shelf[i], vol_id) == 0))
1439: return(i);
1440: if((i = warm_inv(buf)) <= 0)
1441: break;
1442: }
1443: if(i < 0)
1444: fprintf(stderr, "jukebox: %s\n", buf);
1445: return(-1);
1446: }
1447:
1448: int
1449: j_driveof(char *vol_id)
1450: {
1451: int i, sh;
1452:
1453: if((sh = j_shelfof(vol_id)) < 0)
1454: return(-1);
1455: for(i = 0; i < NLUN; i++)
1456: if(j_status.lun[i].shelfvalid && (j_status.lun[i].retshelf == sh))
1457: return(i);
1458: return(-1);
1459: }
1460: 0707070035050452251006660011710000040000010447370457563430700000700000004561juke.3