Annotation of researchv10no/cmd/worm/oscsi/scsi.cpio, revision 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