# To unbundle, sh this file echo LL.c 1>&2 mkdir scsi scsi/osanity scsi/scsi scsi/inc scsi/generic scsi/sony scsi/wren sed 's/.//' >LL.c <<'//GO.SYSIN DD LL.c' -#include <sys/param.h> - -/* - * long-long support - */ - -#define M 0x80000000 - -unsigned -Lshift(ll, l) -llong_t ll; -long l; -{ - return (ll.hi<<(32-l)) | (ll.lo>>l); -} - -llong_t -ltoL(l) -long l; -{ - llong_t t; - - t.hi = 0; - t.lo = l; - return t; -} - -llong_t -Lladd(ll, l) -llong_t ll; -long l; -{ - llong_t t; - long cin; - - t = ll; - t.lo += l; - cin = ll.lo^t.lo; - if (l>=0) { - if ((ll.lo&cin)&M) - t.hi++; - } else { - if ((~ll.lo&cin)&M) - t.hi--; - } - return t; -} - -llong_t -Luadd(ll, u) -llong_t ll; -unsigned long u; -{ - llong_t t; - long cin; - - t = ll; - t.lo += u; - cin = ll.lo^t.lo; - if ((ll.lo&cin)&M) - t.hi++; - return t; -} - -llong_t -LLadd(lla, llb) -llong_t lla, llb; -{ - llong_t t; - - t.hi = lla.hi+llb.hi; - t.lo = lla.lo+llb.lo; - if ((lla.lo&llb.lo | lla.lo&~t.lo | llb.lo&~t.lo)&M) - t.hi++; - return t; -} - -llong_t -Llmul(a, b) - llong_t a; - unsigned long b; -{ - llong_t r; - - r = ltoL(0); - while(b){ - if(b&1) - r = LLadd(r, a); - b >>= 1; - a = LLadd(a, a); - } - return(r); -} //GO.SYSIN DD LL.c echo btree.c 1>&2 sed 's/.//' >btree.c <<'//GO.SYSIN DD btree.c' -#include <libc.h> -#include <cbt.h> -#undef nfree -#include "worm.h" -#include "sym.h" -#include <sys/types.h> -#include <sys/stat.h> - -static char *inonames; -static bfile *bf; -static dirlk(), wormdir(); - -char * -cbtinit(s, blk, doinodes) - register Superblock *s; - long blk; -{ - static char buf[64]; - char name[256], buf1[256]; - - if(s->magic != SMAGIC){ - fprint(2, "bad Superblock at %ld\n", blk); - exit(1); - } - numinodes = s->ninodes; - if(doinodes){ - inonames = malloc(s->blocksize*(int)NBLKS(s, s->ninochars)); - if(inonames == 0){ - sprint(buf, "cbtinit: can't malloc %d\n", s->blocksize*(int)NBLKS(s, s->ninochars)); - return(buf); - } - if(dirlk(s) == 0) - wormdir(s); - } else - inonames = 0; - return((char *)0); -} - -static -dirlk(s) - register Superblock *s; -{ - char name[256], buf1[256]; - struct stat sbuf; - int fd; - - sprint(name, "/usr/worm/dirs/%s", s->vol_id); - sprint(buf1, "%s.I", name); - if(stat(buf1, &sbuf) < 0) - return(0); - if(sbuf.st_mtime < s->ctime) - return(0); /* worm is more recent than disk */ - if((bf = bopen(name, 0)) == 0) - return(0); - sprint(buf1, "%s.I", name); - if((fd = open(buf1, 0)) < 0){ - fprint(2, "%s: btree but no inodes\n", name); - return(0); - } - if(read(fd, inonames, (int)s->ninochars) != s->ninochars){ - fprint(2, "%s: expected %d chars\n", buf1, s->ninochars); - close(fd); - return(0); - } - close(fd); - return(1); -} - -static -wormdir(s) - register Superblock *s; -{ - char name[256], buf1[256]; - - sprint(name, "/tmp/worm%d", getpid()); - Seek(s, s->binodes); - sprint(buf1, "%s.F", name); - copyout(s, buf1, s->nF, 0, 0); - sprint(buf1, "%s.T", name); - copyout(s, buf1, s->nT, 0, 0); - if(Read(s, inonames, NBLKS(s, s->ninochars))) - return(0); - if((bf = bopen(name, 0)) == 0){ - fprint(2, "can't bopen %s", name); - return(0); - } - sprint(buf1, "%s.F", name); unlink(buf1); - sprint(buf1, "%s.T", name); unlink(buf1); - return(1); -} - -copyout(s, name, len, overwrite, verbose) - register Superblock *s; - char *name; - long len; -{ - int fd, l; - char *buf; - - if(access(name, 0) == 0){ - if(!overwrite){ - fprint(2, "%s already exists!\n", name); - exit(1); - } - if(verbose) - fprint(2, "overwriting %s\n", name); - } - if((fd = creat(name, 0666)) < 0){ - perror(name); - exit(1); - } - if((buf = malloc(l = (BIGBLOCK/1024)*s->blocksize)) == 0){ - fprint(2, "can't malloc %d\n", l); - exit(1); - } - if(verbose) - print("%s: %d bytes\n", name, len); - while(len >= l){ - if(Read(s, buf, NBLKS(s, l))) - exit(1); - if(write(fd, buf, l) != l){ - perror(name); - exit(2); - } - len -= l; - } - if(Read(s, buf, NBLKS(s, len))) - exit(2); - if(write(fd, buf, (int)len) != len){ - perror(name); - exit(2); - } - free(buf); -} - -Inode * -binodefn(s) - char *s; -{ - static Inode i; - mbuf key; - - if(inonames == 0) - return((Inode *)0); - key.mdata = s; - key.mlen = strlen(s); - if(bseek(bf, key) != 1) - return((Inode *)0); - key.mdata = (char *)&i; - if(bread(bf, (mbuf *)0, &key)){ - perror("inode read"); - return((Inode *)0); - } - i.name.n = i.name.o+inonames; - return(&i); -} - -void -btraverse(fn) - void (*fn)(); -{ - static Inode i; - mbuf key; - - if(inonames == 0) - return; - bfirst(bf); - key.mdata = (char *)&i; - while(bread(bf, (mbuf *)0, &key) == 0){ - i.name.n = i.name.o+inonames; - (*fn)(&i); - } -} //GO.SYSIN DD btree.c echo c.c 1>&2 sed 's/.//' >c.c <<'//GO.SYSIN DD c.c' -#include <sys/param.h> -main(argc, argv) - char **argv; -{ - Long off; - long a, b; - - a = atoi(argv[1]); - b = atoi(argv[2]); - off = Llmul(ltoL(a), b); - print("%d(#%x) x %d(#%x) = #%ux%0.8ux(%.0f)\n", a, a, b, b, off.hi, off.lo, - ((float)off.lo) + 65536.0*65536.0*off.hi); - if(llseek(open("/dev/null", 0), off, 0) < 0) - perror("seek"); -} //GO.SYSIN DD c.c echo crap 1>&2 sed 's/.//' >crap <<'//GO.SYSIN DD crap' -#include <libc.h> -#include "sym.h" -#include "worm.h" - -main(argc, argv) - char **argv; -{ - Superblock s; - char *e; - Inode *i; - int c; - char *dev = "/dev/worm0"; - extern char *optarg; - extern int optind; - - while((c = getopt(argc, argv, "f:")) != -1) - switch(c) - { - case 'f': dev = optarg; break; - case '?': usage(); - } - if(optind+2 != argc) - usage(); - dev = mapdev(dev); - if((s.fd = open(dev, 0)) < 0){ - perror(dev); - exit(1); - } - if(e = openinode(&s, DO_INODE|SPIN_DOWN)){ - fprint(2, "%s: %s\n", dev, e); - exit(1); - } - if(strcmp(s.vol_id, argv[optind])){ - fprint(2, "vol_id mismatch: wanted %s, got %s\n", argv[optind], s.vol_id); - exit(1); - } - if(i = inodeof(argv[++optind])) - c = pr(&s, i); - else { - fprint(2, "wcat: can't find %s\n", argv[optind]); - c = 1; - } - exit(c); -} - -usage() -{ - fprint(2, "Usage: worm cat [-fdevice] vol_id file\n"); - exit(1); -} - -pr(s, i) - Superblock *s; - register Inode *i; -{ - char b[BIGBLOCK]; - register long len, n; - long nb; - int fd; - - fd = 1; - nb = sizeof b / s->blocksize; - Seek(s, i->block); - for(n = i->nbytes, len = nb*s->blocksize; n > 0;){ - if(len > n){ - len = n; - nb = (len+s->blocksize-1)/s->blocksize; - } - Read(s, b, nb); - if(write(fd, b, (int)len) != len){ - perror("write"); - return(1); - } - n -= len; - } - close(fd); - return(0); -} //GO.SYSIN DD crap echo flink.c 1>&2 sed 's/.//' >flink.c <<'//GO.SYSIN DD flink.c' -#include <libc.h> -#include "worm.h" - -static Inode *inodebase; -static char *namebase; -static long nnames, ninodes; -static char *expanded; -static readinodes; -static ifd; - -static Inode *diskinode(); - -static Inode * -finode(s) - char *s; -{ - register lo, hi, m; - register Inode *i; - - if(readinodes == 0) - return(diskinode(s)); -#define EXPAND(in) (i = inodebase+(in), expanded[in]?0:(i->name.n=i->name.o+namebase, expanded[in]=1)) -#define CMP(str, in) (EXPAND(in), strcmp(str, i->name.n)) - - if(CMP(s, lo = 0) < 0) - return(0); - if(CMP(s, (hi = ninodes)-1) > 0) - return(0); - while(lo < hi-1){ - m = (lo+hi)/2; - if(CMP(s, m) < 0) - hi = m; - else - lo = m; - } - if(CMP(s, lo) == 0) - return(inodebase+lo); - else - return(0); -} - -static void -ftraverse(fn) - void (*fn)(); -{ - register Inode *i; - register n; - - if(readinodes == 0){ - readinodes = 1; - lseek(ifd, 8L, 0); - read(ifd, (char *)inodebase, (int)ninodes*sizeof(Inode)); - } - for(n = 0; n < ninodes; n++){ - EXPAND(n); - (*fn)(i); - } -} - -fastlink(s, msg, ifn, tfn) - Superblock *s; - char **msg; - Inode *(**ifn)(); - void (**tfn)(); -{ - int n; - long t; - static char buf[256]; - - *msg = 0; - *ifn = finode; - *tfn = ftraverse; - sprint(buf, "/usr/worm/tmp/%s", s->vol_id); - if((ifd = open(buf, 0)) < 0) - return(0); - read(ifd, (char *)&t, 4); - if(t != s->ctime) - return(0); - read(ifd, (char *)&ninodes, 4); - inodebase = (Inode *)malloc(n = ninodes*sizeof(Inode)); - expanded = malloc((int)ninodes); - memset(expanded, 0, (int)ninodes); - lseek(ifd, (long)n, 1); - readinodes = 0; - read(ifd, (char *)&nnames, 4); - namebase = malloc((int)nnames); - read(ifd, namebase, (int)nnames); - numinodes = ninodes; - numnamechars = nnames; - return(1); -} - -static -readi(ino, ip) - Inode *ip; -{ - static myino = -1; - static Inode myi; - - if(ino != myino){ - myino = ino; - lseek(ifd, 8L+myino*sizeof(Inode), 0); - read(ifd, (char *)&myi, sizeof myi); - myi.name.n = myi.name.o+namebase; - } - *ip = myi; -} - -static Inode * -diskinode(s) - char *s; -{ - register lo, hi, m; - static Inode ii; - register Inode *i = ⅈ - -#define READ(in) readi(in, i) -#undef CMP -#define CMP(str, in) (READ(in), strcmp(str, i->name.n)) - - if(ninodes <= 0) - return(0); - if(CMP(s, lo = 0) < 0) - return(0); - if(CMP(s, (hi = ninodes)-1) > 0) - return(0); - while(lo < hi-1){ - m = (lo+hi)/2; - if(CMP(s, m) < 0) - hi = m; - else - lo = m; - } - if(CMP(s, lo) == 0) - return(i); - else - return(0); -} //GO.SYSIN DD flink.c echo getopt.c 1>&2 sed 's/.//' >getopt.c <<'//GO.SYSIN DD getopt.c' -#define ERR(str, chr) if(opterr){fprint(2, "%s%s%c\n", argv[0], str, chr);} -int opterr = 1; -int optind = 1; -int optopt; -char *optarg; -char *strchr(); - -int -getopt (argc, argv, opts) -char **argv, *opts; -{ - static int sp = 1; - register c; - register char *cp; - - if (sp == 1) - if (optind >= argc || - argv[optind][0] != '-' || argv[optind][1] == '\0') - return -1; - else if (strcmp(argv[optind], "--") == 0) { - optind++; - return -1; - } - optopt = c = argv[optind][sp]; - if (c == ':' || (cp=strchr(opts, c)) == 0) { - ERR (": illegal option -- ", c); - if (argv[optind][++sp] == '\0') { - optind++; - sp = 1; - } - return '?'; - } - if (*++cp == ':') { - if (argv[optind][sp+1] != '\0') - optarg = &argv[optind++][sp+1]; - else if (++optind >= argc) { - ERR (": option requires an argument -- ", c); - sp = 1; - return '?'; - } else - optarg = argv[optind++]; - sp = 1; - } else { - if (argv[optind][++sp] == '\0') { - sp = 1; - optind++; - } - optarg = 0; - } - return c; -} //GO.SYSIN DD getopt.c echo in.c 1>&2 sed 's/.//' >in.c <<'//GO.SYSIN DD in.c' -#include <libc.h> -#include <fio.h> -#include "worm.h" - -int bad = 0; -long nbytes; -long blkdone; -long nfiles; -char *argout; - -static Inode *inodes; -static long ip; -static long ninodes = 0; -static char *nameb; -static long np; -static long nnameb = 0; -static long nblocks; -#define IINC 1024 -#define NINC (64*IINC) - -ininit() -{ - if(nnameb == 0){ - nameb = malloc((unsigned)(nnameb = NINC)); - if(nameb == 0){ - fprint(2, "wwrite: malloc fail, %d bytes\n", nnameb); - exit(1); - } - } - np = 0; - if(ninodes == 0){ - inodes = (Inode *)malloc(sizeof(Inode)*(unsigned)(ninodes = IINC)); - if(inodes == 0){ - fprint(2, "wwrite: malloc fail, %d inodes %d bytes\n", ninodes, ninodes*sizeof(Inode)); - exit(1); - } - } - ip = 0; - nblocks = 0; -} - -inadd(s, i) - Superblock *s; - register Inode *i; -{ - register long len; - - len = strlen(i->name.n)+1; - if(np+len > nnameb){ - while(np+len > nnameb) - nnameb += NINC; - nameb = realloc(nameb, (unsigned)nnameb); - if(nameb == 0){ - fprint(2, "wwrite: realloc fail, %d bytes\n", nnameb); - exit(1); - } - } - strcpy(nameb+np, i->name.n); - i->name.o = np; - np += len; - i->block = s->nextffree + nblocks; - if(ip == ninodes){ - ninodes += IINC; - inodes = (Inode *)realloc((char *)inodes, (unsigned)ninodes*sizeof(Inode)); - if(inodes == 0){ - fprint(2, "wwrite: realloc fail, %d inodes %d bytes\n", ninodes, ninodes*sizeof(Inode)); - exit(1); - } - } - inodes[ip++] = *i; - nblocks += (i->nbytes+s->blocksize-1)/s->blocksize; - return(0); -} - -inwrite(s, arg) - Superblock *s; - void *arg; -{ - int i, j; - long next = s->nextffree; - char *e; - - if(e = lkwri(s, inodes, ip, nameb, np, nblocks)){ - fprint(2, "%s\n", e); - bad = 1; - return; - } - Seek(s, next); - argout[2] = ' '; - for(i = 0; i < ip; i++){ - inodes[i].block = next; - inodes[i].name.n = inodes[i].name.o + nameb; - writeout(s, &inodes[i], &next, arg); - j = (blkdone*100)/nblocks; - argout[0] = j/10+'0'; - argout[1] = j%10+'0'; - } -} //GO.SYSIN DD in.c echo inode.c 1>&2 sed 's/.//' >inode.c <<'//GO.SYSIN DD inode.c' -#include <libc.h> -#include "worm.h" -#include <sys/types.h> -#include <sys/udaioc.h> - -Inode *(*inodefn)(); -void (*traversefn)(); -extern Inode *vinodefn(), *binodefn(); -extern void vtraverse(), btraverse(); -extern char *lkopi(), *cbtinit(); -long numinodes; -long numnamechars; - -char * -openinode(s, flags) - register Superblock *s; -{ - short fd = s->fd; - char *b, *z; - long blk; - unsigned short ibuf[3]; - static char buf[64]; - extern char *getenv(); - extern long atol(); -int goo; extern errno; int ntry; - - if(z = getenv("WORMZERO")) - blk = atol(z); - else - blk = 0; - ntry = 0; -loop: - bigseek(s->fd, blk, 1024, 0); - if(((goo = read(s->fd, (char *)ibuf, sizeof ibuf)) != sizeof ibuf) || - ((((long)ibuf[1])<<16|ibuf[0]) != SMAGIC)){ - if((goo < 0) && (errno == ENXIO)) - blk++; /* blank check (unwritten), try next blk */ - else if((goo == sizeof ibuf) && (ibuf[0] == 0) && (ibuf[1] == 0)) - blk++; /* zeroes(??), try next blk */ - else { - fprint(2, "DEBUGGING[%d]: read=%d magic=0x%lx errno=%d\n", - ntry, goo, (((long)ibuf[1])<<16|ibuf[0]), errno); - if(ntry++ < 3) - goto loop; - } - bigseek(s->fd, blk, 1024, 0); - if(read(s->fd, (char *)ibuf, sizeof ibuf) < sizeof ibuf) - return("no block size"); - } - if(flags&SPIN_DOWN) - ioctl(s->fd, UIOSPDW); - s->blocksize = ibuf[2]; /* magic is 0-1 */ - if((b = malloc(s->blocksize)) == 0){ - sprint(buf, "couldn't malloc buffer (%d bytes)", s->blocksize); - return(buf); - } - bigseek(s->fd, blk, 1024, 0); - if(read(s->fd, b, s->blocksize) != s->blocksize) - return("superblock read error"); - *s = *((Superblock *)b); - free(b); - s->fd = fd; - if(s->myblock == 0) - s->myblock = blk; - switch(s->version) - { - case VLINK: - if(flags&DO_INODE){ - Superblock tmpsb; - - tmpsb = *s; - if(b = lkopi(s, blk, 0)) - return(b); - if(fastlink(s, &b, &inodefn, &traversefn)) - return(b); - *s = tmpsb; - } - inodefn = vinodefn; - traversefn = vtraverse; - return(lkopi(s, blk, flags&DO_INODE)); - case VBTREE: - inodefn = binodefn; - traversefn = btraverse; - return(cbtinit(s, blk, flags&DO_INODE)); - default: - sprint(buf, "unknown version %d@%ld", s->version, blk); - return(buf); - } -} //GO.SYSIN DD inode.c echo io.c 1>&2 sed 's/.//' >io.c <<'//GO.SYSIN DD io.c' -#include <libc.h> -#include "worm.h" - -Read(s, buf, n) - register Superblock *s; - char *buf; - long n; -{ - register k; - int len; - - n *= s->blocksize; - if(n != (int)n){ - fprint(2, "bad arg to Read n=%ld\n", n); - abort(); - } - len = BIGBLOCK; - while(n){ - if(n < len) len = n; - if((k = read(s->fd, buf, len)) != len){ - if(k && (errno != ENXIO)){ - perror("Read"); - exit(1); - } - return(1); - } - n -= len; - buf += len; - } - return(0); -} - -Write(s, buf, n) - register Superblock *s; - char *buf; - long n; -{ - register k; - int len; - char msg[256]; - - n *= s->blocksize; - if(n != (int)n){ - fprint(2, "bad arg to Write n=%d\n", n); - abort(); - } - len = BIGBLOCK; - while(n){ - if(n < len) len = n; - if((k = write(s->fd, buf, len)) != len){ - sprint(msg, "Write %d blks (%dB)", n/s->blocksize, n); - perror(msg); - return(1); - } - n -= len; - buf += len; - } - return(0); -} - -Seek(s, blk) - register Superblock *s; - long blk; -{ - bigseek(s->fd, blk, s->blocksize, 0); -} - -bigseek(fd, a, b, ptr) -{ -#define SEEK64 /**/ -#ifdef SEEK64 -#include <sys/param.h> - llong_t off; - extern llong_t Llmul(), ltoL(); - - off = Llmul(ltoL(a), b); - llseek(fd, off, ptr); -#else - lseek(fd, a*(long)b, ptr); -#endif -} //GO.SYSIN DD io.c echo mapdev.c 1>&2 sed 's/.//' >mapdev.c <<'//GO.SYSIN DD mapdev.c' -char * -mapdev(s) - char *s; -{ - static char buf[128]; - - if((s[1] == 0) && (*s >= '0') && (*s <= '9')){ - sprint(buf, "/dev/worm%c", *s); - s = buf; - } - return(s); -} //GO.SYSIN DD mapdev.c echo mkfile 1>&2 sed 's/.//' >mkfile <<'//GO.SYSIN DD mkfile' -CFLAGS=-g -I. -CC=cc -LIB=worm.a -BIN=/usr/lib/worm -L=io inode vlink flink sym getopt mapdev btree LL in timenow -OBJ=${L:%=$LIB(%.o)} -NPROC=2 -# remember to change /usr/bin/worm if you add programs -ALL=wmkfs wstat wwrite wread wls woffline wcat wbtree wrm\ - wdir wreset wmv wtmpdir wmount wcopy jukebox scsish -BALL=${ALL:%=$BIN/%} - -all:V: $ALL - -scsish jukebox:Pexit 1: /unix - cd scsi; mk both - -$LIB:Q: $OBJ - names=`membername $newprereq` - ar rv $LIB $names && rm $names - ranlib $LIB - -'^(w[^.]*)$':R: \\1.o $LIB #O/\\1 - $CC $CFLAGS -o $target $stem1.o $LIB -lcbt - -'^(poot)$':R: \\1.o $LIB #O/\\1 - $CC $CFLAGS -o $target $stem1.o $LIB -lcbt - -'^(O/w[^.]*)$':R: \\1.O $COBJ - cyntax $prereq && > $target - -$BIN/'(w[^.]*)$':R: \\1 - cp $stem1 $target && strip $target; chmod 775 $target -$BIN/'(scsish|jukebox)':R: \\1 - cp $stem1 $target && strip $target; chmod 775 $target - -sym.o wtree.o thing.o: sym.h -wtree.o thing.o: thing.h - -$LIB(%.o):N: %.o -%.o: worm.h -O/%.O: %.c - cyntax -c $stem.c && mv $stem.O O -O/%.O: worm.h - -pp: - smallpr mkfile worm.h *.c - -clean:V: - rm -f *.o *.a $ALL core O/* - -install:V: $BALL - -ship:V: shipped -shipped: $BALL /usr/bin/worm - ship $newprereq && touch $target - -goo:V: wmv wls wwrite wmkfs - set +e - > temp - wmkfs -ftemp testa - wwrite -ftemp testa w*.[ch] - wls -ftemp -l wreset.c; wls -ftemp -b wreset.c - wmv -ftemp testa wreset.c xxx - wls -ftemp -l wreset.c xxx; wls -ftemp -b xxx - -wild: $BALL - dest=wild ship $newprereq && touch $target - -poot:V: wcopy wls wstat wmkfs - > temp1 - wmkfs -ftemp1 -n300 test7a; wstat -v -ftemp1 - wls -ftemp | wcopy -ftemp -v -m0 testa temp1 test7a - wstat -v -ftemp; wls -ftemp -b | sort | mc - wstat -v -ftemp1; wls -ftemp1 -b | sort | mc - #wstat -v -ftemp; wstat -v -ftemp1 - wls -ftemp | wcopy -ftemp -v -m0 testa temp1 test7a - wstat -v -ftemp1; wls -ftemp1 -b | sort | mc - set +e;(wls -ftemp; echo; wls -ftemp; echo; wls -ftemp)| tee temp2 | wcopy -ftemp -v -m100 testa temp1 test7a - wstat -v -ftemp1; wls -ftemp1 -b | sort | mc - -goop:V: wmkfs wstat wwrite - > temp - wmkfs -ftemp -n1000 testa; wstat -vftemp - wmkfs -n666 -ftemp testa; wstat -vftemp //GO.SYSIN DD mkfile echo owcopy.c 1>&2 sed 's/.//' >owcopy.c <<'//GO.SYSIN DD owcopy.c' -#include <libc.h> -#include "worm.h" -#include "sym.h" -#include <sys/types.h> -#include <sys/stat.h> -#include <pwd.h> -#include <grp.h> - -char *timenow(); -long minfree = 40000; -int verbose = 0; -static char *copy(); - -main(argc, argv) - char **argv; -{ - char *e; - char *dev = "/dev/worm0"; - char *dest = 0; - Superblock in, out; - long start = 1; - long count = 1000000L; - int c; - extern char *optarg; - extern int optind; - void pr(); - - while((c = getopt(argc, argv, "vc:m:s:f:")) != -1) - switch(c) - { - case 'c': count = atol(optarg); break; - case 'f': dev = optarg; break; - case 'm': minfree = atol(optarg); break; - case 's': start = atol(optarg); break; - case 'v': verbose = 1; break; - case '?': usage(); - } - dev = mapdev(dev); - if((in.fd = open(dev, 0)) < 0){ - perror(dev); - exit(1); - } - if(optind+3 != argc) - usage(); - - if(e = openinode(&in, SPIN_DOWN)){ - fprint(2, "worm copy: %s: %s\n", dev, e); - exit(1); - } - if(strcmp(argv[optind], in.vol_id)){ - fprint(2, "src vol_id mismatch: expected %s, got %s\n", - argv[optind], in.vol_id); - exit(1); - } - dest = mapdev(argv[optind+1]); - if((out.fd = open(dest, 2)) < 0){ - perror(dest); - exit(1); - } - if(e = openinode(&out, SPIN_DOWN)){ - fprint(2, "worm copy: %s: %s\n", dest, e); - exit(1); - } - if(strcmp(argv[optind+2], out.vol_id)){ - fprint(2, "destination vol_id mismatch: expected %s, got %s\n", - argv[optind+2], out.vol_id); - exit(1); - } - if(e = copy(&in, start, count, &out)){ - fprint(2, "worm copy: %s: %s\n", dest, e); - exit(1); - } - exit(0); -} - -usage() -{ - fprint(2, "Usage: worm copy [-v] [-fdevice] [-s startblk] [-c count] [-m minfree] srcvolid destdev destvolid\n"); - exit(2); -} - -static char * -copy(in, blk, count, out) - register Superblock *in, *out; - long blk, count; -{ - register Inode *i; - short fd = in->fd; - char *b, *err; - long nb, ndata; - char *nameb; - Inode *inodes = 0; - Inode *iend; - long delta; - static char buf[64]; - extern char *lkwri(); - - in->blocksize = 1024; - if((b = malloc(in->blocksize)) == 0){ - sprint(buf, "couldn't malloc buffer (%d bytes)", in->blocksize); - return(buf); - } - Seek(in, blk); - if(Read(in, b, 1)){ - fprint(2, "worm copy: unexpected read error\n"); - exit(1); - } - *in = *((Superblock *)b); - in->fd = fd; - while(count-- > 0){ - if(in->magic != SMAGIC){ - fprint(2, "bad Superblock at %ld\n", blk); - exit(1); - } - if(in->ninodes){ - if(verbose) - fprint(2, "%s reading chunk %s:%ld (%.1f%%)\n", - timenow(), in->vol_id, in->myblock, - in->myblock*100./(float)in->nblocks); - if(out->nfree < minfree){ - fprint(2, "worm copy: disk %s has < %d free at input %d\n", - out->vol_id, minfree, in->myblock); - exit(1); - } - nb = (in->ninodes+(in->blocksize/sizeof(Inode))-1)/(in->blocksize/sizeof(Inode)); - inodes = (Inode *)malloc((unsigned)(in->blocksize*nb)); - if(inodes == 0){ - sprint(buf, "inode malloc(%d) fail, sbrk=%d\n", - (in->blocksize*nb), sbrk(0)); - return(buf); - } - Seek(in, in->binodes); - if(Read(in, (char *)inodes, nb)) - goto skip; - delta = out->nextffree - inodes->block; -print("%d inodes; delta=%d\n", in->ninodes, delta); - for(i = inodes, iend = inodes+in->ninodes; i < iend; i++) - if(i->block > 0) - i->block += delta; - nb = (in->ninochars+in->blocksize-1)/in->blocksize; - nameb = malloc((unsigned)(in->blocksize*nb)); - if(nameb == 0){ - sprint(buf, "name buffer malloc(%d) fail, sbrk=%d\n", - (in->blocksize*nb), sbrk(0)); - return(buf); - } - if(Read(in, nameb, nb)) - goto skip; - ndata = in->binodes - in->myblock - 1; - if(err = lkwri(out, inodes, in->ninodes, nameb, in->ninochars, ndata)){ - fprint(2, "wcopy: lkwri: %s at input %d\n", err, in->myblock); - exit(1); - } - dcopy(in, out, ndata); - } - skip: - blk = in->nextsb; - Seek(in, blk); - if(Read(in, b, 1L)) - break; - *in = *((Superblock *)b); - in->fd = fd; - if(in->myblock == 0) - in->myblock = blk; - } - free(b); - if(verbose) - fprint(2, "%s copy done, %s is %.1f%% full\n", timenow(), out->vol_id, - out->myblock*100.0/(float)out->nblocks); - return((char *)0); -} - -dcopy(in, out, n) - Superblock *in, *out; - long n; -{ - char buf[BIGBLOCK]; - long bs; - - bs = BIGBLOCK/in->blocksize; - Seek(in, in->myblock+1); - Seek(out, out->myblock+1); - while(n > 0){ - if(bs > n) bs = n; - if(Read(in, buf, bs)){ - fprint(2, "wcopy: warning: data read error at %d\n", in->myblock); - } - if(Write(out, buf, bs)){ - fprint(2, "wcopy: dcopy write error\n"); - exit(1); - } - n -= bs; - } -} - -char * -timenow() -{ - long tim; - char *tims; - - time(&tim); - tims = ctime(&tim); - tims[19] = 0; - return(tims); -} //GO.SYSIN DD owcopy.c echo partial.news 1>&2 sed 's/.//' >partial.news <<'//GO.SYSIN DD partial.news' -the worm programs now only run properly on systems -with llseek in the kernel. the three systems that matter //GO.SYSIN DD partial.news echo poot.c 1>&2 sed 's/.//' >poot.c <<'//GO.SYSIN DD poot.c' -#include <libc.h> -#include "sym.h" -#include "worm.h" - -main(argc, argv) - char **argv; -{ - Superblock s; - char buf[1024]; - char *e; - Inode *i; - int c; - char *com = 0; - char *dev = "/dev/worm0"; - extern char *optarg; - extern int optind; - - while((c = getopt(argc, argv, "f:c:")) != -1) - switch(c) - { - case 'c': com = optarg; break; - case 'f': dev = optarg; break; - case '?': usage(); - } - if(optind+2 != argc) - usage(); - dev = mapdev(dev); - if((s.fd = open(dev, 2)) < 0){ - perror(dev); - exit(1); - } - if(e = openinode(&s, SPIN_DOWN)){ - fprint(2, "%s: %s\n", dev, e); - exit(1); - } - if(strcmp(s.vol_id, argv[optind])){ - fprint(2, "vol_id mismatch: wanted %s, got %s\n", argv[optind], s.vol_id); - exit(1); - } - if(s.version != VBTREE){ - fprint(2, "poot: %s must be a btree disk\n", s.vol_id); - exit(1); - } - memset(buf, sizeof buf, 0); - memset(s.vol_id, sizeof s.vol_id, 0); - strcpy(s.vol_id, argv[++optind]); - if(com){ - memset(s.comment, sizeof s.comment, 0); - strcpy(s.comment, com); - } - memcpy(buf, &s, 1024); - lseek(s.fd, 0, 0); - if(write(s.fd, buf, 1024) != 1024){ - perror("write of new superblock"); - exit(1); - } - exit(0); -} - -usage() -{ - fprint(2, "Usage: poot [-fdevice] [-ccnewcomment] vol_id new_vol_id\n"); - exit(1); -} //GO.SYSIN DD poot.c echo scsi/mkfile 1>&2 sed 's/.//' >scsi/mkfile <<'//GO.SYSIN DD scsi/mkfile' -SYS=research -< $SYS.mk -JL=juke.a -X=allocate cold getstatus ioshelves iodr_sh lib load nlun warm -JLIB=${X:%=$JL(%.o)} -JSRC=${X:%=%.c} - -SL=scsi.a -X=s_$IO ge_sense s_volid s_pperror s_fixedstr s_longat s_xd -SLIB=${X:%=$SL(%.o)} - -SHL=scsish.a -GENERIC=ge_dev ge_inq ge_stop ge_start ge_capacity ge_display\ - ge_reset ge_tur ge_scsi ge_readt ge_copy # ge_sense in $SL -SONY=so_dev so_inq so_alt so_config so_status so_eject so_rel so_set\ - so_shelfside so_diskid so_internal so_media so_readid so_copy\ - so_i0.tab so_i1.tab so_scsi.tab so_sense so_nesd.tab -WREN=wr_dev wr_inq wr_rmode wr_wmode wr_diag -X=$GENERIC $SONY $WREN -SHLIB=${X:%=$SHL(%.o)} - -all:V: jukebox scsish - -both:V: ../jukebox ../scsish - -../%: % - cp $prereq $target - -jukebox: jukebox.o $JL $SHL $SL - $CC $CFLAGS -o $target $prereq $LDFLAGS - -scsish: scsish.o $SHL $SL - $CC $CFLAGS -o $target $prereq $LDFLAGS - -jpp:V: - pr mkfile juke.h scsi.h jukebox.c $JSRC | lp -ddp -n2 - -poot:V: scsish - echo 'dev scsi - copy 4 0 10 5 0 1' | scsish - -scsi.cpio:V: inc/scsi.h - find * -print | sed -e '/\.[oa]$/d' -e '/\.cpio$/d' | cpio -oc > $target -inc/scsi.h:Pcmp -s: /usr/include/scsi.h - cp $prereq $target - - -# below is just magic; believe it. - -$JL(%.o):N: %.o -$JL:Q: $JLIB - names=`membername $newprereq` - ar rv $JL $names && rm $names - $RANLIB $JL - -$SL(%.o):N: %.o -$SL:Q: $SLIB - names=`membername $newprereq` - ar rv $SL $names && rm $names - $RANLIB $SL - -$SHL(%.o):N: %.o -$SHL:Q: $SHLIB - names=`membername $newprereq` - ar rv $SHL $names && rm $names - $RANLIB $SHL - -s_%.o: scsi/%.c - cd scsi; $CC $CFLAGS -c $stem.c && mv $stem.o ../$target -so_%.o: sony/%.c - cd sony; $CC $CFLAGS -c $stem.c && mv $stem.o ../$target -so_%.o: sony/fns.h -ge_%.o: generic/%.c - cd generic; $CC $CFLAGS -c $stem.c && mv $stem.o ../$target -ge_%.o: generic/fns.h -wr_%.o: wren/%.c - cd wren; $CC $CFLAGS -c $stem.c && mv $stem.o ../$target -wr_%.o: wren/fns.h -so_%.o wr_%.o ge_%.o: scsish.h scsi.h - -so_%.tab.o:Q: sony/%.tab - cd sony - echo generating $target - p=$stem.tab - awk -F' ' ' - BEGIN { h["0"]=0;h["1"]=1;h["2"]=2;h["3"]=3;h["4"]=4;h["5"]=5;h["6"]=6;h["7"]=7; - h["8"]=8;h["9"]=9;h["a"]=10;h["b"]=11;h["c"]=12;h["d"]=13;h["e"]=14;h["f"]=15; - } - function done( i){ - for(i = 0; i < 256; i++) if(x[i]){ - print "\t\"" x[i] "\"," - x[i] = "" - } else printf "\t\"<#%x>\",\n", i - print "};" - } - function hex(n, i){ - return(h[substr(n, 1, 1)]*16+h[substr(n, 2, 1)]); - } - NF == 1 { if(NR > 1) done(); print "char *" $1 "[] = {" } - NF > 1 { x[hex($1)] = $2; } - END { done(); }' < $p > $p.c && $CC $CFLAGS -c $p.c && mv $p.o ../$target - rm $p.c //GO.SYSIN DD scsi/mkfile echo scsi/cold.c 1>&2 sed 's/.//' >scsi/cold.c <<'//GO.SYSIN DD scsi/cold.c' -#include <stddef.h> -#include <stdio.h> -#include <string.h> -#include "scsi.h" -#include "juke.h" - -static sort(char *buf); - -cold_inv(char type, char *buf) -{ - Side side; - int drive, sh, nsh; - int n; - char vol_id[512]; - int didit[NSHELF]; - - if(j_getstatus(buf)) /* get the jukebox status */ - return(-1); -printf("getstatus done\n"); - /* first clear out nonexistent labels */ - n = 0; - for(sh = 0; sh < NSHELF; sh++){ - if((j_status.shelf[sh]&0xC0) == 0xC0){ - n++; - j_shelf[sh] = "there"; - } else - j_shelf[sh] = 0; - didit[sh] = 0; - } - printf("%d disks in shelves.\n", n); - /* second, clear the drives */ - for(sh = 0; sh < NSHELF; sh++) - if(j_shelf[sh] == 0) - break; - for(drive = 0; drive < 8; drive++){ - if(!j_status.lun[drive].diskin) - continue; /* no disk in drive */ -printf("clearing drive %d:\n", drive); - if(j_status.lun[drive].diskindrive && !j_status.lun[drive].shelfvalid){ - if(j_drive_to_shelf(drive, sh, SIDEA, buf)) - return(-1); - for(sh++; sh < NSHELF; sh++) - if(j_shelf[sh] == 0) - break; - n++; - } else - if(j_drive_to_shelf(drive, -1, SIDEA, buf)) - return(-1); - printf("\n"); - } - printf("reloading %d disks.\n", n); - side = SIDEA; - drive = min(nlun+1, NLUN-1); - j_wrshelf = 1; - for(sh = 0; sh < NSHELF; sh++){ - if(didit[sh]) - continue; - j_shelf[sh] = 0; - /* the C0 means disk properly present (not temp) */ - if((j_status.shelf[sh]&0xC0) == 0xC0){ - if(getvol(sh, drive, vol_id, &side)) - errexit(vol_id); - switch(type) - { - case 'c': - for(nsh = 0; j_shelf[nsh]; nsh++) - ; - break; - case 's': - case 'r': - while(j_shelf[nsh = nrand(NSHELF)]) - ; - break; - case 'u': - default: - nsh = sh; - break; - } - printf("%s@%d -> %d\n", vol_id, sh, nsh); - if(j_drive_to_shelf(drive, nsh, side, buf) < 0) - return(-1); - j_shelf[nsh] = strdup(vol_id); - didit[nsh] = 1; - sleep(2); - } - } - printf("process any new disks.\n"); - if(warm_inv(buf)) - return(-1); - if(type == 's') - return(sort(buf)); - return(0); -} - -getvol(int sh, int drive, char *vol_id, int *side) -{ - int i; - char buf[512]; - - if(j_shelf_to_drive(sh, SIDEA, drive, vol_id) < 0) - return(-1); - if((i = j_rvolid(drive, buf)) < 0) - goto softerr; - if(i == 0) - *side = SIDEA; - else { - *side = SIDEB; - if(j_drive_to_shelf(drive, sh, SIDEA, vol_id) < 0) - return(-1); - if(j_shelf_to_drive(sh, SIDEB, drive, vol_id) < 0) - return(-1); - if((i = j_rvolid(drive, buf)) < 0) - goto softerr; - } - if(i > 0) - strcpy(vol_id, UNALLOCATED); - else { - strcpy(vol_id, buf); - i = strlen(vol_id)-1; - if(i < 0){ - sprintf(buf, "apparently good superblock but null vol_id"); - goto softerr; - } else if(vol_id[i] == 'a') - vol_id[i] = 0; - else if(vol_id[i] == 'b'){ - vol_id[i] = 0; - *side = !*side; - } else { - sprintf(buf, "vol_id '%s' must end in a or b", vol_id); - strcpy(vol_id, buf); - return(-1); - } - } - return(0); -softerr: - *side = SIDEA; - fprintf(stderr, "error in reading shelf %d: %s; proceeding\n", sh, buf); - sprintf(vol_id, "DISK_ERROR%d", sh); - gen_reset(0, (int *)0, 0, (char **)0, buf); - return(0); -} - -static int index[NSHELF]; -static -cmp(int *a, int *b) -{ - char *sa = j_shelf[*a], *sb = j_shelf[*b]; - - if((sa == 0) && (sb == 0)) return(0); - if(sa == 0) return(-1); - if(sb == 0) return(1); - return(strcmp(sa, sb)); -} - -static char *disk[8]; - -static -sd(int a, int b, char *err) -{ - disk[b] = j_shelf[a]; - return(j_shelf_to_drive(a, SIDEB, b, err)); -} -static -ds(int a, int b, char *err) -{ - j_shelf[b] = disk[a]; - return(j_drive_to_shelf(a, b, SIDEB, err)); -} - -static -sort(char *errbuf) -{ - int i, j, org; - - for(i = 0; i < NSHELF; i++) - index[i] = i; - qsort(index, NSHELF, sizeof index[0], cmp); - for(i = 0; i < NSHELF; i++){ - if(index[i] < 0) continue; - if(sd(org = i, NLUN-1, errbuf) < 0) - return(-1); - j = index[i]; - index[i] = -1; - while(j != org){ - if(sd(j, NLUN-2, errbuf) < 0) - return(-1); - if(ds(NLUN-2, i, errbuf) < 0) - return(-1); - i = j; - if(index[i] < 0) - break; - j = index[i]; - index[i] = -1; - } - if(ds(NLUN-1, i, errbuf) < 0) - return(-1); - } - return(0); -} //GO.SYSIN DD scsi/cold.c echo scsi/osanity/tstfill.c 1>&2 sed 's/.//' >scsi/osanity/tstfill.c <<'//GO.SYSIN DD scsi/osanity/tstfill.c' -short pat[][8] = -{ - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0xb6db, 0xeb6d, 0xb6db, 0xeb6d, 0xb6db, 0xeb6d, 0xb6db, 0xeb6d, - 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, - 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, 0xAAAA, - 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, 0x5555, -}; - -fillbuf(buf, n) - char *buf; -{ - int i = 0; - register j; - - while(n > 0){ - if(i >= sizeof(pat)/sizeof(pat[0])) - i = 0; - for(j = 0; j < 64; j++, buf += 16) - memcpy(buf, pat[i], 16); - n--; - i++; - } -} //GO.SYSIN DD scsi/osanity/tstfill.c echo scsi/osanity/tstrd.c 1>&2 sed 's/.//' >scsi/osanity/tstrd.c <<'//GO.SYSIN DD scsi/osanity/tstrd.c' -main(argc, argv) - char **argv; -{ - long first, last, t; - char buf[32768], buf1[32768], *bufp; - int fd, n; - char *worm = "/dev/worm0"; - - if((argc < 3) || (argc > 4)){ - print("Usage: tstrd [device] firstblock firstnonblock\n"); - exit(1); - } - if(argc > 3) - worm = *++argv; - if((fd = open(worm, 0)) < 0){ - perror(worm); - exit(1); - } - first = atol(argv[1]); - last = atol(argv[2]); - if((first < 0) || (last <= first)){ - print("bad first=%ld last=%ld\n", first, last); - exit(1); - } - print("reading blocks %ld - %ld inclusive on %s\n", first, last-1, worm); - fillbuf(buf, 32); - bufp = &buf[1024*(first%5)]; - lseek(fd, first*1024, 0); - while(first < last){ - n = last-first; - if(n > 25) n = 25; - if(read(fd, buf1, n*1024) != n*1024){ - print("block %ld: ", first); - perror("read"); - exit(1); - } - if(memcmp(bufp, buf1, n*1024)){ - print("block %ld: bytes differ\n", first); - exit(1); - } - if((first%5000) == 0){ - t = time((long *)0); - print("done block %ld: %s", first, ctime(&t)); - } - first += n; - } - exit(0); -} //GO.SYSIN DD scsi/osanity/tstrd.c echo scsi/osanity/tstsk.c 1>&2 sed 's/.//' >scsi/osanity/tstsk.c <<'//GO.SYSIN DD scsi/osanity/tstsk.c' -main(argc, argv) - char **argv; -{ - long first, last, t; - char buf[32768], buf1[32768], *bufp; - int fd, n, i; - char *worm = "/dev/worm0"; - long bands[50][2]; - int nbands; - long loop; - double tseek, tbl; - float floop; - - if(argc < 3){ - print("Usage: tstsk [device] firstblock firstnonblock ...\n"); - exit(1); - } - if((argc&1) == 0) - worm = *++argv; - if((fd = open(worm, 0)) < 0){ - perror(worm); - exit(1); - } - nbands = 0; - while(*++argv){ - first = atol(*argv); - last = atol(*++argv); - if((first < 0) || (last <= first)){ - print("bad first=%ld last=%ld\n", first, last); - exit(1); - } - bands[nbands][0] = first; - bands[nbands][1] = last; - nbands++; - } - tseek = tbl = 0; - last = 0; - fillbuf(buf, 32); - for(loop = 0;; loop++){ - i = nrand(nbands); - first = bands[i][0] + lrand()%(bands[i][1]-bands[i][0]); - n = 20; - if(first+n > bands[i][1]) - first = bands[i][1]-n; - if(first < bands[i][0]) - first = bands[i][0], n = bands[i][1]-first; - tbl += n; - lseek(fd, first*1024, 0); - last -= first; - if(last < 0) last = -last; - tseek += last; - bufp = &buf[1024*(first%5)]; - if(read(fd, buf1, n*1024) != n*1024){ - print("block %ld: ", first); - perror("read"); - exit(1); - } - if(memcmp(bufp, buf1, n*1024)){ - print("block %ld: bytes differ\n", first); - exit(1); - } - if(loop && ((loop%100) == 0)){ - t = time((long *)0); - floop = loop+1; - print("loop %ld: ave blocks=%.1f, ave seek=%.1fk at %s", - loop, tbl/floop, tseek/floop, ctime(&t)); - } - last = first+n; - } -} //GO.SYSIN DD scsi/osanity/tstsk.c echo scsi/osanity/tstwr.c 1>&2 sed 's/.//' >scsi/osanity/tstwr.c <<'//GO.SYSIN DD scsi/osanity/tstwr.c' -main(argc, argv) - char **argv; -{ - long first, last, t; - char buf[32768], buf1[32768], *bufp; - int fd, n; - char *worm = "/dev/worm0"; - - if((argc < 3) || (argc > 4)){ - print("Usage: tstwr [device] firstblock firstnonblock\n"); - exit(1); - } - if(argc > 3) - worm = *++argv; - if((fd = open(worm, 1)) < 0){ - perror(worm); - exit(1); - } - first = atol(argv[1]); - last = atol(argv[2]); - if((first < 0) || (last <= first)){ - print("bad first=%ld last=%ld\n", first, last); - exit(1); - } - print("writing blocks %ld - %ld inclusive on %s\n", first, last-1, worm); - fillbuf(buf, 32); - bufp = &buf[1024*(first%5)]; - lseek(fd, first*1024, 0); - while(first < last){ - n = last-first; - if(n > 25) n = 25; - if(write(fd, bufp, n*1024) != n*1024){ - print("block %ld: ", first); - perror("write"); - exit(1); - } - if((first%5000) == 0){ - t = time((long *)0); - print("done block %ld: %s", first, ctime(&t)); - } - first += n; - } - exit(0); -} //GO.SYSIN DD scsi/osanity/tstwr.c echo scsi/osanity/mkfile 1>&2 sed 's/.//' >scsi/osanity/mkfile <<'//GO.SYSIN DD scsi/osanity/mkfile' -CFLAGS=-g -NPROC=2 -ALL=tstwr tstrd tstsk - -all:V: $ALL - -tst%: tst%.o tstfill.o - $CC $CFLAGS -o $target $prereq - -clean:V: - rm -f *.o $ALL core //GO.SYSIN DD scsi/osanity/mkfile echo scsi/osanity/seek 1>&2 sed 's/.//' >scsi/osanity/seek <<'//GO.SYSIN DD scsi/osanity/seek' -tstsk 5 100000 400000 500000 800000 900000 1200000 1300000 1500000 1600000 //GO.SYSIN DD scsi/osanity/seek echo scsi/juke.3 1>&2 sed 's/.//' >scsi/juke.3 <<'//GO.SYSIN DD scsi/juke.3' -.TH INTERNAL 3 -.CT 2 file_io -.SH NAME -jukebox routines -.tr %" -.SH SYNOPSIS -.B "#include %hdr.h%" -.PP -.tr %% -.B "int j_shelf_to_drive(int sh, Side side, int dr, char *err)" -.PP -.B "int j_drive_to_shelf(int dr, int sh, Side side, char *err)" -.PP -.B "int j_empty_drive(int tlim, char *buf)" -.PP -.B "void j_rdshelves(char *buf)" -.PP -.B "int j_getstatus(char *buf)" -.PP -.B "int j_scsiio(struct scsi_cmd *cmd, int ncmd," -.br -.B "\ \ \ \ \ \ struct scsi_return *ret, int nret, char *err)" -.PP -.B "int j_shelfof(char *vol_id)" -.PP -.B "int j_volid(int dr, char *err)" -.PP -.B "extern char *j_shelf[NSHELF];" -.PP -.B "extern void pperror(char *buf, char *mesg); -.SH DESCRIPTION -.I J_shelf_to_drive -places the disk in shelf -.I sh -in logical drive -.IR dr . -It returns 0 on success; -otherwise an error message is placed in -.I err . -.PP -.I J_drive_to_shelf -places the disk -in logical drive -.IR dr -in shelf -.IR sh . -If -.I sh -is negative, -the disk is returned to its home shelf. -It returns 0 on success; -otherwise an error message is placed in -.IR err . -.PP -.I J_rdshelves -initializes each element of -.I j_shelf -to the volid of the disk on that shelf. -A zero pointer means there is no disk; -a name of -.B UNALLOCATED -means the disk has not been allocated a name yet. -It returns 0 on success; -otherwise an error message is placed in -.IR err . -.PP -.I J_getstatus -initializes -.B j_status -which include the following fields: -.EX - struct Lunstatus lun[NLUN]; /* disk status */ - uchar shelf[NSHELF]; /* shelf status */ - uchar iounit; /* I/O unit status */ - uchar carrier; /* carrier status */ - uchar udrive; /* upper drive status */ - uchar ldrive; /* lower drive status */ -.EE -A return value of 0 implies success; -otherwise \-1 is returned and an error message is placed in -.IR err . -.PP -.I J_scsiio -performs a SCSI transaction. -It sends the command in -.I cmd -and -.I ncmd -data bytes and stores the return status in -.IR ret . -A return value of 0 implies success; -otherwise \-1 is returned and an error message is placed in -.IR err . -.PP -.I J_shelfof -returns the shelf number of the disk labelled -.IR vol_id . -If there is no such disk, -\-1 is returned. -.PP -.I J_volid -returns the volid of the disk on drive -.I dr -in -.IR err . -A return value of 0 implies success; -otherwise \-1 is returned and an error message is placed in -.IR err . -.PP -.I Pperror -returns an error message that is contained in -.IR buf. -.PP -.SH "SEE ALSO" -.SH DIAGNOSTICS //GO.SYSIN DD scsi/juke.3 echo scsi/warm.c 1>&2 sed 's/.//' >scsi/warm.c <<'//GO.SYSIN DD scsi/warm.c' -#include <stddef.h> -#include <stdio.h> -#include <string.h> -#include "scsi.h" -#include "juke.h" - -warm_inv(char *buf) -{ - Side side; - int drive, sh; - char vol_id[512]; - - if(j_rdshelves(buf)) /* read in shelf names */ - return(-1); - side = SIDEA; - drive = min(nlun+1, NLUN-1); - for(;;){ - if(j_getstatus(buf)) /* get the jukebox status */ - return(-1); - for(sh = 0; sh < NSHELF; sh++) - if(j_status.shelf[sh]&0x10) break; - if(sh >= NSHELF) - break; - if(getvol(127, drive, vol_id, &side)){ - strcpy(buf, vol_id); - return(-1); - } - for(sh = 0; j_shelf[sh]; sh++) - ; - printf("%s -> %d\n", vol_id, sh); - if(j_drive_to_shelf(drive, sh, side, buf) < 0) - return(-1); - j_wrshelf = 1; - j_shelf[sh] = strdup(vol_id); - sleep(1); - } - return(0); -} //GO.SYSIN DD scsi/warm.c echo scsi/juke.h 1>&2 sed 's/.//' >scsi/juke.h <<'//GO.SYSIN DD scsi/juke.h' -#define NLUN 8 -#define NSHELF 50 -extern int nlun; -extern void setnlun(void); -extern char *j_shelf[NSHELF]; -extern int j_wrshelf; /* need to write out shelves */ -extern j_rdshelves(char *err); -extern j_wrshelves(char *err); -extern j_inventory(char cold, int tlim, char *err); - -typedef enum { SIDEA = 0, SIDEB = 1 } Side; - -struct Lunstatus -{ - unsigned int poweron:1; /* is power on ? */ - unsigned int diskin:1; /* is disk in drive? */ - unsigned int ready:1; /* is disk spun up or spun down? */ - unsigned int writeprotect:1; /* is disk write protected? */ - unsigned int diskindrive:1; /* is driveshelf a drive number? */ - unsigned int shelfvalid:1; /* is retshelf valid? */ - uchar driveshelf; /* drive number */ - uchar retshelf; /* return shelf */ -}; - -struct Jstatus -{ - struct Lunstatus lun[NLUN]; /* disk status */ - uchar shelf[NSHELF]; /* shelf status */ - uchar iounit; /* I/O unit status */ - uchar carrier; /* carrier status */ - uchar udrive; /* upper drive status */ - uchar ldrive; /* lower drive status */ -}; -extern struct Jstatus j_status; -extern int j_getstatus(char *err); -extern int j_shelfof(char *vol_id); -extern int j_driveof(char *vol_id); - -extern char *strdup(char *); -extern int j_shelf_to_drive(int, Side, int, char *); -extern int j_drive_to_shelf(int, int, Side, char *); -extern int j_empty_drive(long, char *); -extern int j_rvolid(int, char *); -extern int j_wvolid(int, char *, char *); -extern void pperror(char *buf, char *mesg); -extern int reserve_drive(int, char *); -extern int release_drive(int, char *); -extern int cold_inv(char, char *); -extern int warm_inv(char *); -extern int j_load(char *vol_id, char *buf, long tlim); -extern int j_unload(char *vol_id, char *buf); - -#define JUKEDIR "/usr/worm/jukedir" -#define UNALLOCATED "<unallocated>" //GO.SYSIN DD scsi/juke.h echo scsi/scsi.h 1>&2 sed 's/.//' >scsi/scsi.h <<'//GO.SYSIN DD scsi/scsi.h' -typedef unsigned char uchar; - -struct scsi_cmd -{ - unsigned long id; - uchar bus_id; /* SCSI id of destination device */ - uchar flags; - uchar cmd[10]; /* SCSI command */ - uchar data[4096]; /* optional data */ -}; - -struct scsi_return -{ - unsigned long id; - uchar scsi_stat; /* scsi status byte */ - uchar scsi_msg; /* scsi message byte */ - uchar flags; - uchar type; /* 1=td 2=us */ - unsigned short reg1; /* td=sa, us=per */ - unsigned short reg2; /* td=mscp, us=per */ - unsigned char sense[22]; - char pad[2]; - uchar data[4096]; /* any data */ - uchar nread; /* chars read(-8) if ret count was -ve */ -}; - -#define set6(x,a,b,c,d,e,f) (x).flags=0,(x).cmd[0]=(a),(x).cmd[1]=(b),(x).cmd[2]=(c),\ - (x).cmd[3]=(d),(x).cmd[4]=(e),(x).cmd[5]=(f) -#define set10(x,a,b,c,d,e,f,g,h,i,j) (x).flags=0,(x).cmd[0]=(a),(x).cmd[1]=(b),(x).cmd[2]=(c),\ - (x).cmd[3]=(d),(x).cmd[4]=(e),(x).cmd[5]=(f),(x).cmd[6]=(g),(x).cmd[7]=(h),\ - (x).cmd[8]=(i),(x).cmd[9]=(j) -#define setdiag(x,lun,n) (x).flags=0,(x).cmd[0]=0x1C,(x).cmd[1]=(lun)<<5,(x).cmd[2] = 0,\ - (x).cmd[3]=(n)>>8,(x).cmd[4]=(n),(x).cmd[5]=0 - -extern s_io(int, struct scsi_cmd *, int, struct scsi_return *, int, char *);/* return 0 on no error, does sense on error */ -extern ss_io(int, struct scsi_cmd *, int, struct scsi_return *, int, char *);/* return 0 on no error */ -extern int s_ignua; /* should s_io ignore unit attentions? */ -extern void (*ss_extsense)(uchar *, char *, int); -extern int s_start(int, char *); -extern int s_stop(int, char *); -extern int s_eject(int, char *); -extern int s_id; -extern unsigned long longat(uchar *); //GO.SYSIN DD scsi/scsi.h echo scsi/jukebox.c 1>&2 sed 's/.//' >scsi/jukebox.c <<'//GO.SYSIN DD scsi/jukebox.c' -#include <stdio.h> -#include <limits.h> -#include "scsi.h" -#include "juke.h" - -main(int argc, char *argv[]) -{ - int c; - int aflag = 0, eflag = 0, mflag = 0, pflag = 0; - int rflag = 0, sflag = 0, uflag = 0, Uflag = 0; - long secs = 3600L*24*183; /* half a year is enough */ - char *vol_id; - char errbuf[1024]; - extern int optind; - extern char *optarg; - - setbuf(stdout, (char *)0); /* turn off buffering */ - while((c = getopt(argc, argv, "aemprsuUw:")) != -1) - switch (c) - { - case 'a': aflag = 1; break; - case 'e': eflag = 1; break; - case 'm': mflag = 1; break; - case 'p': pflag = 1; break; - case 'r': rflag = 1; break; - case 's': sflag = 1; break; - case 'u': uflag = 1; break; - case 'U': Uflag = 1; break; - case 'w': secs = atol(optarg); break; - default: usage(); break; - } - s_id = 2; - setnlun(); - if(!aflag&&!eflag&&!mflag&&!pflag&&!rflag&&!uflag&&!Uflag) - sflag = 1; - vol_id = (optind < argc)? argv[optind] : 0; - if(uflag || Uflag) - unload(Uflag); - if(eflag){ - if(vol_id == 0){ - strcpy(errbuf, "-e needs a vol_id"); - goto scram; - } - if(eject(vol_id, errbuf)) - goto scram; - } - if(rflag){ - unload(1); - sleep(1); - if(cold_inv(vol_id? *vol_id : 'u', errbuf) < 0) - goto scram; - } - if(aflag){ - if(vol_id == 0){ - strcpy(errbuf, "-a needs a vol_id"); - goto scram; - } - if(allocate(vol_id, errbuf)) - goto scram; - } - if(mflag){ - if((c = j_load(vol_id, errbuf, secs)) < 0) - goto scram; - if(s_start(c, errbuf) < 0) - fprintf(stderr, "jukebox: %s\n", errbuf); - if(s_stop(c, errbuf) < 0) - fprintf(stderr, "jukebox: %s\n", errbuf); - printf("%d\n", c); - } - if(sflag) - prstatus(); - if(pflag){ - if(j_rdshelves(errbuf) < 0) - goto scram; - for(c = 0; c < NSHELF; c++) - if(j_shelf[c]) - printf("%d: %s\n", c, j_shelf[c]); - } - if(j_wrshelf) - if(j_wrshelves(errbuf)) - errexit(errbuf); - exit(0); -scram: - if(j_wrshelf) - j_wrshelves(errbuf); - errexit(errbuf); -} - -usage() -{ - fprintf(stderr, "Usage: jukebox [-aemprsuU] [-w secs] [vol_id\n"); - exit(1); -} - -errexit(char *errbuf) -{ - fprintf(stderr, "jukebox: %s\n", errbuf); - exit(1); -} - -prstatus() -{ - struct Lunstatus *l; - int c; - char errbuf[1024]; - static char *spin[2] = { "offline", "online" }; - - if(j_getstatus(errbuf)){ - fprintf(stderr, "jukebox: %s\n", errbuf); - exit(1); - } - if(j_rdshelves(errbuf)){ - fprintf(stderr, "jukebox: %s\n", errbuf); - exit(1); - } - for(c = 0; c < 8; c++){ - l = &j_status.lun[c]; - if(!l->diskin) - continue; - printf("lun %d(", c); - if(j_status.udrive == (0x80|c)) - printf("upper,%s", spin[l->ready]); - else if(j_status.ldrive == (0x80|c)) - printf("lower,%s", spin[l->ready]); - else - printf("in shelf"); - printf("): "); - if(l->shelfvalid){ - if(j_shelf[l->retshelf>>1]) - printf("%s%c", j_shelf[l->retshelf>>1], "ab"[l->retshelf&1]); - else - printf("unallocated shelf number %d??", l->retshelf); - } else - printf("<unknown shelf??>"); - printf("\n"); - } -} - -unload(int force) -{ - struct Lunstatus *l; - int c; - char errbuf[1024]; - - if(j_getstatus(errbuf)){ - fprintf(stderr, "jukebox: %s\n", errbuf); - exit(1); - } - if(j_rdshelves(errbuf)){ - fprintf(stderr, "jukebox: %s\n", errbuf); - exit(1); - } - for(c = 0; c < 8; c++){ - l = &j_status.lun[c]; - if(!l->diskin) - continue; - if(force || !l->ready) - if(j_drive_to_shelf(c, -1, SIDEA, errbuf)) - fprintf(stderr, "jukebox: %s\n", errbuf); - } -} - -eject(char *vol_id, char *errbuf) -{ - int sh; - int dr; - - if(j_rdshelves(errbuf)){ - fprintf(stderr, "jukebox: %s\n", errbuf); - exit(1); - } - sh = j_shelfof(vol_id); - if(sh < 0){ - sprintf(errbuf, "xcan't find vol_id %s", vol_id); - return(-1); - } - j_wrshelf = 1; - if((dr = j_driveof(vol_id)) >= 0){ - j_shelf[sh] = 0; - return(s_eject(dr, errbuf)); - } - dr = NLUN-1; - if(j_shelf_to_drive(sh, SIDEA, dr, errbuf) < 0) - return(-1); - if(s_eject(dr, errbuf)) - return(-1); - j_shelf[sh] = 0; - return(0); -} //GO.SYSIN DD scsi/jukebox.c echo scsi/getstatus.c 1>&2 sed 's/.//' >scsi/getstatus.c <<'//GO.SYSIN DD scsi/getstatus.c' -#include <stddef.h> -#include <stdio.h> -#include "scsi.h" -#include "juke.h" - -struct Jstatus j_status; - -static -dolun(struct Lunstatus *lun, uchar *u) -{ - lun->poweron = ((*u)&0x80) == 0; - lun->diskin = ((*u)&0x40) != 0; - lun->ready = ((*u)&0x01) != 0; - u++; - lun->diskindrive = ((*u)&0x80) != 0; - lun->driveshelf = (*u)&0x7F; - u++; - lun->shelfvalid = ((*u)&0x80) != 0; - lun->retshelf = (*u)&0x7F; -} - -j_getstatus(char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int i; - - set6(cmd, 0x1D, 0, 0, 0, 10, 0); - memset(cmd.data, 0, 10); - cmd.data[0] = 0xE2; - if(s_io(1, &cmd, 10, &ret, 0, err)) - return(-1); - set6(cmd, 0x1C, 0, 0, 0, 128, 0); - if(s_io(0, &cmd, 0, &ret, 128, err)) - return(-1); - for(i = 0; i < 8; i++) - dolun(&j_status.lun[i], &ret.data[16+4*i]); - for(i = 0; i < NSHELF; i++) - j_status.shelf[i] = ret.data[48+i]; - j_status.iounit = ret.data[98]; - j_status.carrier = ret.data[99]; - j_status.udrive = ret.data[100]; - j_status.ldrive = ret.data[101]; - return(0); -} //GO.SYSIN DD scsi/getstatus.c echo scsi/nlun.c 1>&2 sed 's/.//' >scsi/nlun.c <<'//GO.SYSIN DD scsi/nlun.c' -#include <stdio.h> -#include "scsi.h" -#include "juke.h" - -int nlun = 1; - -void -setnlun(void) -{ - char buf[512]; - - for(nlun = 0; nlun < NLUN; nlun++){ - sprintf(buf, "/dev/worm%d", nlun); - if(access(buf, 0) < 0) - return; - } -} //GO.SYSIN DD scsi/nlun.c echo scsi/allocate.c 1>&2 sed 's/.//' >scsi/allocate.c <<'//GO.SYSIN DD scsi/allocate.c' -#include <stddef.h> -#include <stdio.h> -#include <string.h> -#include "scsi.h" -#include "juke.h" - -allocate(char *vol_id, char *buf) -{ - int drive, sh; - char nbuf[512]; - - if(j_rdshelves(buf)) /* read in shelf names */ - return(-1); - if(j_getstatus(buf)) /* get the jukebox status */ - return(-1); - sh = j_shelfof(vol_id); - if(sh >= 0){ - sprintf(buf, "there is an existing '%s' on shelf %d", vol_id, sh); - return(-1); - } - sh = j_shelfof(UNALLOCATED); - if(sh < 0){ - sprintf(buf, "no unallocated disks"); - return(-1); - } - printf("using unallocated disk from shelf %d\n", sh); - drive = min(nlun+1, NLUN-1); - if(j_shelf_to_drive(sh, SIDEB, drive, buf) < 0) - return(-1); - sprintf(nbuf, "%sb", vol_id); - if(j_wvolid(drive, nbuf, buf)) - return(-1); - j_wrshelf = 1; - j_shelf[sh] = strdup(vol_id); - if(j_drive_to_shelf(drive, sh, SIDEB, buf) < 0) - return(-1); - if(j_shelf_to_drive(sh, SIDEA, drive, buf) < 0) - return(-1); - sprintf(nbuf, "%sa", vol_id); - if(j_wvolid(drive, nbuf, buf)) - return(-1); - if(j_drive_to_shelf(drive, sh, SIDEA, buf) < 0) - return(-1); - return(0); -} //GO.SYSIN DD scsi/allocate.c echo scsi/scsi/dslib.c 1>&2 sed 's/.//' >scsi/scsi/dslib.c <<'//GO.SYSIN DD scsi/scsi/dslib.c' -/* -|| dslib.c - library routines for /dev/scsi -|| -|| Copyright 1988, 1989, by -|| Gene Dronek (Vulcan Laboratory) and -|| Rich Morin (Canta Forda Computer Laboratory). -|| All rights reserved. -*/ -#ident "dslib.c: $Revision: 1.4 $" - -#include <stdio.h> -#include <sys/types.h> - -#include "dslib.h" -#ifdef aux -#include <sys/vio.h> -#include <sys/scsireq.h> -#endif aux - -int dsdebug=0; -long dsreqflags; /* flag bits always set by filldsreq */ - -#define min(i,j) ( (i) < (j) ? (i) : (j) ) - - -/* -|| Startup/shutdown ----------------------------------------------- -*/ - -static struct context *dsc[FDSIZ]; - - -/* -|| dsopen - open device, set up structures -*/ - -struct dsreq * -dsopen(opath, oflags) - char *opath; - int oflags; -{ - - struct dsreq *dsp; - struct context *cp; - int fd; - DSDBG(fprintf(stderr,"dsopen(%s,%x) ", opath, oflags)); - - fd = open(opath, oflags); - if (fd < 0) - return NULL; /* can't open */ - if (dsc[fd] != NULL) /* already in use */ - ds_zot("dsopen: fd already in use"); - - cp = (struct context *) calloc(1, sizeof(struct context)); - if (cp == NULL) /* can't allocate */ - ds_zot("dsopen: can't allocate space"); - dsc[fd] = cp; - cp->dsc_fd = fd; - dsp = &(cp->dsc_dsreq); - - dsp->ds_flags = 0; - dsp->ds_time = 10 * 1000; /* 10 second default timeout */ - dsp->ds_private = (ulong) cp; /* pointer back to context */ - dsp->ds_cmdbuf = cp->dsc_cmd; - dsp->ds_cmdlen = sizeof cp->dsc_cmd; - dsp->ds_databuf = 0; - dsp->ds_datalen = 0; - dsp->ds_sensebuf = cp->dsc_sense; - dsp->ds_senselen = sizeof cp->dsc_sense; - DSDBG(fprintf(stderr,"=>cp %x, dsp %x\n", cp, dsp)); - return dsp; -} - - -/* -|| dsclose - close device, release context struct. -*/ - -dsclose(dsp) - struct dsreq *dsp; -{ - int fd; - struct context *cp; - - if (dsp == NULL) - ds_zot("dsclose: dsp is NULL"); - - cp = (struct context *)dsp->ds_private; - fd = getfd(dsp); - if ( cp == NULL ) - ds_zot("dsclose: private is NULL"); - - cfree(cp); - dsc[fd] = (struct context *)NULL; - return; -} - - -/* -|| Generic SCSI CCS Command functions ------------------------------------ -|| -|| dsp dsreq pointer -|| data data buffer pointer -|| datalen data buffer length -|| lba logical block address -|| vu vendor unique bits -*/ - -/* -|| testunitready00 - issue group 0 "Test Unit Ready" command (0x00) -*/ - -testunitready00(dsp) - struct dsreq *dsp; -{ - fillg0cmd(dsp, CMDBUF(dsp), G0_TEST, 0, 0, 0, 0, 0); - filldsreq(dsp, 0, 0, DSRQ_READ|DSRQ_SENSE); - return(doscsireq(getfd(dsp), dsp)); -} - - -/* -|| requestsense03 - issue group 0 "Request Sense" command (0x03) -*/ - -requestsense03(dsp, data, datalen, vu) - struct dsreq *dsp; - caddr_t data; - long datalen; - char vu; -{ - fillg0cmd(dsp, CMDBUF(dsp), G0_REQU, 0, 0, 0, B1(datalen), B1(vu<<6)); - filldsreq(dsp, data, datalen, DSRQ_READ); - return(doscsireq(getfd(dsp), dsp)); -} - - -/* -|| write0a - issue group 0 "Write" command (0x0a) -*/ - -write0a(dsp, data, datalen, lba, vu) - struct dsreq *dsp; - caddr_t data; - long datalen, lba; - char vu; -{ - fillg0cmd(dsp, CMDBUF(dsp), G0_WRIT, B3(lba), B1(datalen), B1(vu<<6)); - filldsreq(dsp, data, datalen, DSRQ_READ); - return(doscsireq(getfd(dsp), dsp)); -} - - -/* -|| inquiry12 - issue group 0 "Inquiry" command (0x12) -*/ - -inquiry12(dsp, data, datalen, vu) - struct dsreq *dsp; - caddr_t data; - long datalen; - char vu; -{ - fillg0cmd(dsp, CMDBUF(dsp), G0_INQU, 0, 0, 0, B1(datalen), B1(vu<<6)); - filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE); - return(doscsireq(getfd(dsp), dsp)); -} - - -/* -|| modeselect15 - issue group 0 "Mode Select" command (0x15) -|| -|| save 0 - don't save saveable pages -|| 1 - save saveable pages -*/ - -modeselect15(dsp, data, datalen, save, vu) - struct dsreq *dsp; - caddr_t data; - long datalen; - char save, vu; -{ - fillg0cmd(dsp, CMDBUF(dsp), G0_MSEL, save&1, 0, 0, B1(datalen), B1(vu<<6)); - filldsreq(dsp, data, datalen, DSRQ_WRITE|DSRQ_SENSE); - return(doscsireq(getfd(dsp), dsp)); -} - - -/* -|| modesense1a - issue group 0 "Mode Sense" command (0x1a) -|| -|| pagectrl 0 - current values -|| 1 - changeable values -|| 2 - default values -|| 3 - saved values -|| -|| pagecode 0 - vendor unique -|| 1 - error recovery -|| 2 - disconnect/reconnect -|| 3 - direct access dev. fmt. -|| 4 - rigid disk geometry -|| 5 - flexible disk -|| 6-9 - see specific dev. types -|| 0a - implemented options -|| 0b - medium types supported -|| 3f - return all pages -*/ - -modesense1a(dsp, data, datalen, pagectrl, pagecode, vu) - struct dsreq *dsp; - caddr_t data; - long datalen; - char pagectrl, pagecode, vu; -{ - fillg0cmd(dsp, CMDBUF(dsp), G0_MSEN, 0x10, - ((pagectrl&3)<<6) | (pagecode&0x3F), - 0, B1(datalen), B1(vu<<6)); - filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE); - return(doscsireq(getfd(dsp), dsp)); -} - - -/* -|| senddiagnostic1d - issue group 0 "Send Diagnostic" command (0x1d) -|| -|| self 0 - run test, hold results -|| 1 - run test, return status -|| -|| dofl 0 - device online -|| 1 - device offline -|| -|| uofl 0 - unit online -|| 1 - unit offline -*/ - -senddiagnostic1d(dsp, data, datalen, self, dofl, uofl, vu) - struct dsreq *dsp; - caddr_t data; - long datalen; - char self, dofl, uofl, vu; -{ - fillg0cmd(dsp, CMDBUF(dsp), G0_MSEN, - (self&1)<<2 | (dofl&1)<<1 | (uofl&1), - 0, B2(datalen), B1(vu<<6)); - filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE); - return(doscsireq(getfd(dsp), dsp)); -} - - -/* -|| readcapacity25 - issue group 1 "Read Capacity" command (0x25) -|| -|| pmi 0 - return last logical block, entire unit -|| 1 - return last logical block, current track -*/ - -readcapacity25(dsp, data, datalen, lba, pmi, vu) - struct dsreq *dsp; - caddr_t data; - long datalen, lba; - char pmi, vu; -{ - fillg1cmd(dsp, CMDBUF(dsp), G1_RCAP, 0, B4(lba), 0, 0, pmi&1, B1(vu<<6)); - filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE - /* |DSRQ_CTRL2 */ ); - /* dsp->ds_time = 100; /* often takes a while */ - return(doscsireq(getfd(dsp), dsp)); -} - - -/* -|| readextended28 - issue group 1 "Read Extended" command (0x28) -*/ - -readextended28(dsp, data, datalen, lba, vu) - struct dsreq *dsp; - caddr_t data; - long datalen, lba; - char vu; -{ - fillg1cmd(dsp, CMDBUF(dsp), G1_READ, 0, B4(lba), 0, B2(datalen), B1(vu<<6)); - filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE - /* |DSRQ_CTRL2 */ ); - /* dsp->ds_time = 100; /* often takes a while */ - return(doscsireq(getfd(dsp), dsp)); -} - - -/* -|| writeextended2a - issue group 1 "Write Extended" command (0x2a) -*/ - -writeextended2a(dsp, data, datalen, lba, vu) - struct dsreq *dsp; - caddr_t data; - long datalen, lba; - char vu; -{ - fillg1cmd(dsp, CMDBUF(dsp), G1_WRIT, 0, B4(lba), 0, B2(datalen), B1(vu<<6)); - filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE - /* |DSRQ_CTRL2 */ ); - /* dsp->ds_time = 100; /* often takes a while */ - return(doscsireq(getfd(dsp), dsp)); -} - - -/* -|| Support functions ---------------------------------------------------- -*/ - -/* -|| fillg0cmd - Fill a Group 0 command buffer -*/ - -fillg0cmd(dsp, cmd, b0,b1,b2,b3,b4,b5) - struct dsreq *dsp; - uchar_t *cmd, b0,b1,b2,b3,b4,b5; -{ - uchar_t *c = cmd; - DSDBG(fprintf(stderr,"fillg0cmd(%x,%x, %02x %02x %02x %02x %02x %02x)\n", - dsp, cmd, b0,b1,b2,b3,b4,b5)); - *c++ = b0, *c++ = b1, *c++ = b2, *c++ = b3, *c++ = b4, *c++ = b5; - - CMDBUF(dsp) = (caddr_t) cmd; - CMDLEN(dsp) = 6; -} - - -/* -|| fillg1cmd - Fill a Group 1 command buffer -*/ - -fillg1cmd(dsp, cmd, b0,b1,b2,b3,b4,b5,b6,b7,b8,b9) - struct dsreq *dsp; - uchar_t *cmd, b0,b1,b2,b3,b4,b5,b6,b7,b8,b9; -{ - uchar_t *c = cmd; - DSDBG(fprintf(stderr, - "fillg1cmd(%x,%x, %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x)\n", - dsp, cmd, b0,b1,b2,b3,b4,b5,b6,b7,b8,b9)); - - *c++ = b0, *c++ = b1, *c++ = b2, *c++ = b3, *c++ = b4, *c++ = b5; - *c++ = b6, *c++ = b7, *c++ = b8, *c++ = b9; - - CMDBUF(dsp) = (caddr_t) cmd; - CMDLEN(dsp) = 10; -} - - -/* -|| filldsreq - Fill a dsreq structure -*/ - -filldsreq(dsp,data,datalen,flags) - struct dsreq *dsp; - uchar_t *data; -{ - DSDBG(fprintf(stderr,"filldsreq(%x,%x,%d,%x) cmdlen %d\n", - dsp,data,datalen,flags,CMDLEN(dsp))); - dsp->ds_flags = flags | dsreqflags | - (((dsdebug&1) ? DSRQ_TRACE : 0) | - ((dsdebug&2) ? DSRQ_PRINT : 0)); - dsp->ds_time = 10 * 1000; /* default to 10 seconds */ - dsp->ds_link = 0; - dsp->ds_synch = 0; - dsp->ds_ret = 0; - - DATABUF(dsp) = (caddr_t) data; - DATALEN(dsp) = datalen; -} - - -/* -|| bprint - print array of bytes, in hex. -*/ - -#define hex(x) "0123456789ABCDEF" [ (x) & 0xF ] - -bprint(s,n,nperline,space) - char *s; -{ - int i, x; - char *sp = (space) ? " ": ""; - - for(i=0;i<n;i++) { - x = s[i]; - fprintf(stderr,((i%4==3)?"%c%c%s%s":"%c%c%s"), - hex(x>>4), hex(x), sp, sp); - if ( i%nperline == (nperline - 1) ) - fprintf(stderr,"\n"); - } - if ( space ) - fprintf(stderr,"\n"); -} - - -/* -|| doscsireq - issue scsi command, return status or -1 error. -*/ - -doscsireq( fd, dsp) - int fd; /* ioctl file descriptor */ - struct dsreq *dsp; /* devscsi request packet */ -{ - int cc; - int retries = 4; - uchar_t sbyte; - - DSDBG(fprintf(stderr,"doscsireq(%d,%x) %x ---- %s\n",fd,dsp, - (CMDBUF(dsp))[0], - ds_vtostr( (CMDBUF(dsp))[0], cmdnametab))); - - /* - * loop, issuing command - * until done, or further retry pointless - */ - - while ( --retries > 0 ) { - - caddr_t sp; - - sp = SENSEBUF(dsp); - DSDBG(fprintf(stderr,"cmdbuf = "); - bprint(CMDBUF(dsp),CMDLEN(dsp),16,1)); - if ( (dsp->ds_flags & DSRQ_WRITE) ) - DSDBG(bprint( DATABUF(dsp), min(50,DATALEN(dsp)),16,1 )); - -DSDBG(fprintf(stderr,"databuf datalen %x %d\n",DATABUF(dsp), DATALEN(dsp))); - cc = ioctl( fd, DS_ENTER, dsp); - if ( cc < 0) { - ds_panic(dsp, "cannot ioctl fd %d\n",fd); - } - - DSDBG(fprintf(stderr,"cmdlen after ioctl=%d\n",CMDLEN(dsp))); - DSDBG(fprintf(stderr,"ioctl=%d ret=%x %s", - cc, RET(dsp), - RET(dsp) ? ds_vtostr(RET(dsp),dsrtnametab) : "")); - DSDBG(if (SENSESENT(dsp)) fprintf(stderr," sensesent=%d", - SENSESENT(dsp))); - - DSDBG(fprintf(stderr, - " cmdsent=%d datasent=%d sbyte=%x %s\n", - CMDSENT(dsp), DATASENT(dsp), STATUS(dsp), - ds_vtostr(STATUS(dsp), cmdstatustab))); - DSDBG(if ( FLAGS(dsp) & DSRQ_READ ) - bprint( DATABUF(dsp), min(16*16,DATASENT(dsp)), 16,1)); - -#ifdef aux - /* - * check for AUX bus-error - * we retry with poll-dma - */ - if ( RET(dsp) == DSRT_AGAIN ) { - int n = SDC_RDPOLL|SDC_WRPOLL; - DSDBG(fprintf(stderr,"setting rd/wr-poll")); - cc = ioctl( fd, DS_SET, n); /* set bits */ - if ( cc != 0 ) - return -1; - } -#endif aux - - if ( RET(dsp) == DSRT_NOSEL ) - continue; /* retry noselect 3X */ - - /* decode sense data returned */ - if ( SENSESENT(dsp) ) { - DSDBG( - fprintf(stderr, "sense key %x - %s\n", - SENSEKEY(sp), - ds_vtostr( SENSEKEY(sp), sensekeytab)); - bprint( SENSEBUF(dsp), - min(100, SENSESENT(dsp)), - 16,1); - ); - } - DSDBG(fprintf(stderr, "sbyte %x\n", STATUS(dsp))); - - /* decode scsi command status byte */ - sbyte = STATUS(dsp); - switch (sbyte) { - case 0x08: /* BUSY */ - case 0x18: /* RESERV CONFLICT */ - sleep(2); - continue; - case 0x00: /* GOOD */ - case 0x02: /* CHECK CONDITION */ - case 0x10: /* INTERM/GOOD */ - default: - return sbyte; - } - } - return -1; /* fail retry limit */ -} - - -/* -|| opttovar - lookup option in table, return var addr (NULL if fail) -*/ - -int * -opttovar( ostr, table) - char *ostr; - struct opttab{ - char *opt; - int *var; - } *table; -{ - register struct opttab *tp; - - for (tp=table; (tp->var); tp++) - if ( strncmp( ostr, tp->opt, 3) == 0 ) - break; - - if ( !tp->var ) - fprintf(stderr,"unknown option %s", ostr); - - return (tp->var); -} - - -/* -|| ds_vtostr - lookup value in table to return string pointer -*/ - -char * -ds_vtostr( v, table) - long v; - struct vtab *table; -{ - register struct vtab *tp; - - for (tp=table; (tp->string); tp++) - if ( v == tp->val ) - break; - - return (tp->string) ? tp->string : ""; -} - - -/* -|| ds_panic - yelp, leave... -*/ - -ds_panic( fmt, v) - char *fmt; - int v; -{ - extern errno; - - fprintf(stderr,fmt,v); - fprintf(stderr,"\nerrno = %d\n",errno); - exit(1); -} - - -/* -|| ds_zot - go away, with a message. -*/ - -ds_zot(message) - char *message; -{ - fprintf(stderr, "%s\n", message); - exit(1); -} //GO.SYSIN DD scsi/scsi/dslib.c echo scsi/scsi/volid.c 1>&2 sed 's/.//' >scsi/scsi/volid.c <<'//GO.SYSIN DD scsi/scsi/volid.c' -#include <stddef.h> -#include <stdio.h> -#include "../scsi.h" -#include "../juke.h" - -static -myread(int drive, long block, struct scsi_return *ret, char *err) -{ - struct scsi_cmd cmd; - - cmd.bus_id = s_id; - set10(cmd, 0x28, drive<<5, block>>24, block>>16, block>>8, block, 0, 0, 1, 0); - return(s_io(0, &cmd, 0, ret, 1024, err)); -} - -j_rvolid(int drive, char *err) -{ - struct scsi_return ret; - long b, lastb; - char buf[1024]; - int debug = 0; - - err[0] = 0; - if(s_start(drive, err) < 0) - return(-1); - if(myread(drive, 0L, &ret, err) == 0){ - memset(buf, 0, 1024); - if(memcmp(buf, ret.data, 1024)){ - if(debug) - fprintf(stderr, "superblok at 0\n"); - goto done; /* found a superblock at 0 */ - } - } - for(b = 1, lastb = -1;;){ -hack: - if(debug) - fprintf(stderr, "read block %d\n", b); - if(myread(drive, b, &ret, err)) - break; - lastb = b; - b = ((long *)ret.data)[9]; - } - if(lastb < 0){ - if(b == 1){ /* for disks with a bad block 1 */ - b = 2; - goto hack; - } - if(debug) - fprintf(stderr, "tried for superblock at blocks 1,2\n"); - sprintf(err, "no superblock"); - s_stop(drive, buf); - return(1); - } - if(myread(drive, lastb, &ret, err) < 0){ - s_stop(drive, buf); - fprintf(stderr, "read fail on block %d (b=%d)\n", lastb, b);/**/ - return(-1); - } - if(debug) - fprintf(stderr, "superblock at %d\n", lastb); -done: - strncpy(err, (char *)&ret.data[42], 128); - err[127] = 0; - s_stop(drive, buf); - return(0); -} - -static -mywrite(int drive, long block, struct scsi_cmd *cmd, struct scsi_return *ret, char *err) -{ - set10((*cmd), 0x2A, drive<<5, block>>24, block>>16, block>>8, block, 0, 0, 1, 0); - return(s_io(0, cmd, 1024, ret, 0, err)); -} - -j_wvolid(int drive, char *vol_id, char *err) -{ - char tmpfile[L_tmpnam]; - char buf[512]; - struct scsi_return ret; - struct scsi_cmd cmd; - FILE *fp; - int n; - - printf("mkfs %s\n", vol_id); - /* first get the capacity/size for mkfs to make a valid superblock */ - tmpnam(tmpfile); - if((fp = fopen(tmpfile, "w+r")) == NULL){ - pperror(err, tmpfile); - return(-1); - } - if(s_start(drive, err) < 0) - return(-1); - set10(cmd, 0x25, drive<<5, 0, 0, 0, 0, 0, 0, 0, 0); - if(n = s_io(0, &cmd, 0, &ret, 8, err)) - return(n); - switch(longat(&ret.data[0])) - { - case 1637999: /* sony 12in clv single density */ - sprintf(buf, "worm mkfs -n %d -f %s %s", 1600000, tmpfile, vol_id); - break; - case 3275999: /* sony 12in clv double density */ - sprintf(buf, "worm mkfs -n %d -f %s %s", 3250000, tmpfile, vol_id); - break; - default: - fprintf(stderr, "warning: bad capacity %d\n", longat(&ret.data[0])); - sprintf(buf, "worm mkfs -f %s %s", tmpfile, vol_id); - break; - } - if(system(buf)){ - sprintf(err, "%s: error", buf); - return(-1); - } - unlink(tmpfile); - fseek(fp, 1024L, 0); - if(fread(cmd.data, 1, 1024, fp) == 0){ - pperror(err, "mkfs read"); - return(-1); - } - fclose(fp); - if(mywrite(drive, 1L, &cmd, &ret, err)) - return(-1); - unlink(tmpfile); - s_stop(drive, err); - return(0); -} //GO.SYSIN DD scsi/scsi/volid.c echo scsi/scsi/pperror.c 1>&2 sed 's/.//' >scsi/scsi/pperror.c <<'//GO.SYSIN DD scsi/scsi/pperror.c' -#include "../scsi.h" - -void -pperror(char *buf, char *mesg) -{ - extern int sys_nerr; - extern char *sys_errlist[]; - extern int errno; - - if((errno < 0) || (errno >= sys_nerr)) - sprintf(buf, "%s: unknown errno %d", mesg, errno); - else - sprintf(buf, "%s: %s", mesg, sys_errlist[errno]); -} //GO.SYSIN DD scsi/scsi/pperror.c echo scsi/scsi/fixedstr.c 1>&2 sed 's/.//' >scsi/scsi/fixedstr.c <<'//GO.SYSIN DD scsi/scsi/fixedstr.c' -#include "../scsi.h" - -void -fixedstr(uchar *src, int len, char *dest) -{ - uchar *s; - - while((*src == ' ') && (len > 0)) - src++, len--; - for(s = src+len-1; s >= src; s--) - if(*s != ' ') - break; - memcpy(dest, (char *)src, len = s-src+1); - dest[len] = 0; -} //GO.SYSIN DD scsi/scsi/fixedstr.c echo scsi/scsi/longat.c 1>&2 sed 's/.//' >scsi/scsi/longat.c <<'//GO.SYSIN DD scsi/scsi/longat.c' -#include "../scsi.h" - -unsigned long -longat(uchar *src) -{ - unsigned long n; - - n = *src++; - n = (n<<8) | *src++; - n = (n<<8) | *src++; - n = (n<<8) | *src; - return(n); -} //GO.SYSIN DD scsi/scsi/longat.c echo scsi/scsi/xd.c 1>&2 sed 's/.//' >scsi/scsi/xd.c <<'//GO.SYSIN DD scsi/scsi/xd.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" - -#define WIDTH 32 - -void -xd(uchar *p, int n, FILE *fp) -{ - register i, nd, l; - unsigned char buf[WIDTH]; - int didstar; - unsigned char *s; - - for(nd = 0; n > 0; n -= l, nd += l){ - l = min(WIDTH, n); - if(nd && (l == WIDTH) && (memcmp(buf, p, l) == 0)){ - p += WIDTH; - if(didstar++ == 0) - fprintf(fp, "*\n"); - continue; - } - memcpy(buf, p, l); - didstar = 0; - fprintf(fp, "%5.5d", nd); - s = p; - for(i = 0; i < l; i++){ - if((i%4) == 0) putc(' ', fp); - fprintf(fp, "%2.2x", *p++); - } - putc('\n', fp); - fprintf(fp, " "); - for(i = 0; i < l; i++){ - if((i%4) == 0) putc(' ', fp); - if((*s >= ' ') && (*s < 0177)) - fprintf(fp, " %c", *s++); - else switch(*s++) - { - case '\n': fprintf(fp, "\\n"); break; - case '\t': fprintf(fp, "\\t"); break; - default: fprintf(fp, ".."); break; - } - } - putc('\n', fp); - } - fprintf(fp, "%5.5d\n", nd); -} //GO.SYSIN DD scsi/scsi/xd.c echo scsi/scsi/md_io.c 1>&2 sed 's/.//' >scsi/scsi/md_io.c <<'//GO.SYSIN DD scsi/scsi/md_io.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include <sys/types.h> -#include <sys/dsreq.h> - -#define DEV(buf, target, lun) sprintf(buf, "/dev/scsi/sc0d%dl%d", target, lun) - -static fd = -1; -int s_id; -void (*ss_extsense)(uchar *, char *, int); - -ss_io(int preserve, struct scsi_cmd *cmd, int ncmd, struct scsi_return *ret, int nret, char *err) -{ - int retv; - dsreq_t ds; - char dev[512]; - - err[0] = 0; - retv = -1; - if(ncmd && nret){ - sprintf(err, "both input (%d bytes) and output (%d bytes) expected", ncmd, nret); - return(retv); - } - if(cmd->bus_id & 0x8000){ - sprintf(err, "reset not supported"); - return(retv); - } - if(fd < 0){ - DEV(dev, cmd->bus_id, ((cmd->cmd[1]>>5)&7)); - if((fd = open(dev, 2)) < 0){ - pperror(err, dev); - return(-1); - } - } - ds.ds_flags = DSRQ_SENSE; - ds.ds_time = 30000; - ds.ds_cmdbuf = (char *)cmd->cmd; - ds.ds_cmdlen = 10; - if(ncmd){ - ds.ds_databuf = (char *)cmd->data; - ds.ds_datalen = ncmd; - ds.ds_flags |= DSRQ_WRITE; - } else { - ds.ds_databuf = (char *)ret->data; - ds.ds_datalen = nret; - ds.ds_flags |= DSRQ_READ; - } - ds.ds_sensebuf = (char *)ret->sense; - ds.ds_senselen = sizeof ret->sense; - ds.ds_iovbuf = 0; - ds.ds_link = 0; - if(ioctl(fd, DS_ENTER, &ds) < 0){ - pperror(err, "DS_ENTER ioctl"); -err_ret: - close(fd); - fd = -1; - return(retv); - } - if(ds.ds_ret - && (ds.ds_ret != DSRT_SHORT) - && (ds.ds_ret != DSRT_OK) - ) /* an error */ - fprintf(stderr, "ds_ret = #%x\n", ds.ds_ret); - ret->type = 3; - ret->scsi_stat = ds.ds_status; - ret->scsi_msg = ds.ds_msg; - ret->reg1 = ret->reg2 = 0; - if(nret >= 0){ - if(ds.ds_datasent != nret){ - if(ds.ds_datasent == 0) - retv = 1; - else - sprintf(err, "data transfer error; wanted %d, got %d", nret, ds.ds_datasent); - goto err_ret; - } - } else { - ret->nread = ds.ds_datasent; - } - if(!preserve){ - close(fd); - fd = -1; - } - return(0); -} - -static char *smsg[16] = -{ - "good", "check condition", "met/good", "reserved", - "busy", "reserved", "reserved", "reserved", - "intermediate good", "reserved", "intermediate good/met", "reserved", - "reservation conflict", "reserved", "reserved", "reserved", -}; - -s_io(int preserve, struct scsi_cmd *cmd, int ncmd, struct scsi_return *ret, int nret, char *err) -{ - int n; - int status; - char buf[512]; - char ioerr[512]; - - cmd->bus_id = s_id; - if(n = ss_io(preserve, cmd, ncmd, ret, nret, err)){ - if(n < 0) - return(n); - strcpy(ioerr, err); - err[0] = 0; - } else - ioerr[0] = 0; - if(status = ret->scsi_stat){ - (*ss_extsense)(ret->data, buf, sizeof buf); - sprintf(err, "%s; %s", ioerr[0]? ioerr : smsg[(status>>1)&0xF], buf); - return(1); - } - return(0); -} //GO.SYSIN DD scsi/scsi/md_io.c echo scsi/scsi/h_io.c 1>&2 sed 's/.//' >scsi/scsi/h_io.c <<'//GO.SYSIN DD scsi/scsi/h_io.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include <scsi.h> - -#define DEV "/dev/scsi" - -static fd = -1; -int s_id; -int s_ignua = 1; -void (*ss_extsense)(uchar *, char *, int); - -ss_io(int preserve, struct scsi_cmd *cmd, int ncmd, struct scsi_return *ret, int nret, char *err) -{ - int n; - int retv; - - err[0] = 0; - retv = -1; - if(fd < 0){ - if((fd = open(DEV, 2)) < 0){ - pperror(err, DEV); - return(-1); - } - } - cmd->flags |= (ncmd == 0)? SCSI_RD:SCSI_WR; - if((n = write(fd, cmd, 16+ncmd)) != 16+ncmd){ - pperror(err, "scsiio write"); -err_ret: - close(fd); - fd = -1; - return(retv); - } - if(nret >= 0){ - if((n = read(fd, ret, 36+nret)) != 36+nret){ - if(n == 36) - retv = 1; - else - pperror(err, "scsiio read"); - goto err_ret; - } - } else { - if((n = read(fd, ret, 36-nret)) < 0){ - pperror(err, "scsiio read"); - goto err_ret; - } - ret->nread = n-36; - } - if(!preserve){ - close(fd); - fd = -1; - } - return(0); -} - -static char *smsg[16] = -{ - "good", "check condition", "met/good", "reserved", - "busy", "reserved", "reserved", "reserved", - "intermediate good", "reserved", "intermediate good/met", "reserved", - "reservation conflict", "reserved", "reserved", "reserved", -}; - -s_io(int preserve, struct scsi_cmd *cmd, int ncmd, struct scsi_return *ret, int nret, char *err) -{ - int n; - int status; - char buf[512]; - char ioerr[512]; - struct scsi_cmd mycmd; - int ignoredua = 0; - - cmd->bus_id = s_id; -again: - if(n = ss_io(preserve, cmd, ncmd, ret, nret, err)){ - if(n < 0) - return(n); - strcpy(ioerr, err); - err[0] = 0; - } else - ioerr[0] = 0; - if(status = ret->scsi_stat){ - mycmd.bus_id = s_id; - set6(mycmd, 0x03, cmd->cmd[1]&0xE0, 0, 0, 100, 0); - if(n = ss_io(0, &mycmd, 0, ret, -100, err)) - return(n); - if(s_ignua){ /* ignore unit attention ?? */ - if((ret->data[2]&0xF) == 6){ /* it is */ - if(ignoredua++ == 0){ /* but only ignore once */ - mycmd.bus_id = s_id; - set6(mycmd, 0x12, cmd->cmd[1]&0xE0, 0, 0, 5, 0); - if(n = ss_io(0, &mycmd, 0, ret, 5, err)) - return(n); - goto again; - } - } - } - if(ss_extsense == 0) - ss_extsense = gen_extsense; - (*ss_extsense)(ret->data, buf, sizeof buf); - sprintf(err, "%s; %s", ioerr[0]? ioerr : smsg[(status>>1)&0xF], buf); - return(1); - } - return(0); -} //GO.SYSIN DD scsi/scsi/h_io.c echo scsi/scsi/gendev 1>&2 sed 's/.//' >scsi/scsi/gendev <<'//GO.SYSIN DD scsi/scsi/gendev' -awk 'END { for(t = 1; t < 8; t++) for(l=0; l < 8; l++){ - printf "/etc/mknod sc0d%dl%d c 43 %d\n", t, l, l*8+t - } - print "chmod 600 *; chown andrew *" - }' < /dev/null //GO.SYSIN DD scsi/scsi/gendev echo scsi/iodr_sh.c 1>&2 sed 's/.//' >scsi/iodr_sh.c <<'//GO.SYSIN DD scsi/iodr_sh.c' -#include "scsi.h" -#include "juke.h" - -j_shelf_to_drive(int sh, Side side, int dr, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - - set6(cmd, 0xD6, dr<<5, 0, (sh<<1)|side, 0, 0); - return(s_io(0, &cmd, 0, &ret, 0, err)); -} - -j_drive_to_shelf(int dr, int sh, Side side, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - - if(sh < 0) - set6(cmd, 0xD7, dr<<5, 0, 0, 0, 0); - else - set6(cmd, 0xD7, (dr<<5)|1, 0, (sh<<1)|side, 0, 0); - return(s_io(0, &cmd, 0, &ret, 0, err)); -} - -int -j_empty_drive(long tlimit, char *buf) -{ - int i, tstop; - - tstop = time((long *)0) + tlimit; - while(time((long *)0) <= tstop){ - setnlun(); /* in case it changes */ - /* look for empty drives */ - for(i = 0; i < nlun; i++) - if(!j_status.lun[i].diskin) - return(i); - /* look for spun down drives */ - for(i = 0; i < nlun; i++){ - if(!j_status.lun[i].ready){ - if(j_drive_to_shelf(i, -1, SIDEA, buf)) - return(-1); - else - return(i); - } - } - sleep(10); - if(j_getstatus(buf)) /* get the jukebox status */ - return(-1); - } - return(-1); -} //GO.SYSIN DD scsi/iodr_sh.c echo scsi/ioshelves.c 1>&2 sed 's/.//' >scsi/ioshelves.c <<'//GO.SYSIN DD scsi/ioshelves.c' -#include <stddef.h> -#include <stdio.h> -#include <string.h> -#include "scsi.h" -#include "juke.h" - -char *j_shelf[NSHELF]; -int j_wrshelf = 0; - -j_rdshelves(char *err) -{ - FILE *fp; - static haveread = 0; - int shno; - char vname[256]; - - if(haveread) - return(0); - for(shno = 0; shno < NSHELF; shno++) - j_shelf[shno] = 0; - if((fp = fopen(JUKEDIR, "r")) == NULL){ - pperror(err, JUKEDIR); - return(-1); - } - while(fscanf(fp, "%d %s\n", &shno, vname) == 2){ - if((shno < 0) || (shno >= NSHELF)){ - fprintf(stderr, "Warning: bad shelf number in %s: %d (vol_id=%s)\n", - JUKEDIR, shno, vname); - continue; - - } - j_shelf[shno] = strdup(vname); - } - fclose(fp); - haveread = 1; - return(0); -} - -j_wrshelves(char *err) -{ - FILE *fp; - int shno; - - if((fp = fopen(JUKEDIR, "w")) == NULL){ - pperror(err, JUKEDIR); - return(-1); - } - for(shno = 0; shno < NSHELF; shno++) - if(j_shelf[shno]) - fprintf(fp, "%d %s\n", shno, j_shelf[shno]); - fclose(fp); - return(0); -} - -int -j_shelfof(char *vol_id) -{ - int i; - char buf[512]; - - for(;;){ - for(i = 0; i < NSHELF; i++) - if(j_shelf[i] && (strcmp(j_shelf[i], vol_id) == 0)) - return(i); - if((i = warm_inv(buf)) <= 0) - break; - } - if(i < 0) - fprintf(stderr, "jukebox: %s\n", buf); - return(-1); -} - -int -j_driveof(char *vol_id) -{ - int i, sh; - - if((sh = j_shelfof(vol_id)) < 0) - return(-1); - for(i = 0; i < NLUN; i++) - if(j_status.lun[i].shelfvalid && (j_status.lun[i].retshelf == sh)) - return(i); - return(-1); -} //GO.SYSIN DD scsi/ioshelves.c echo scsi/scsish.c 1>&2 sed 's/.//' >scsi/scsish.c <<'//GO.SYSIN DD scsi/scsish.c' -#include <stddef.h> -#include <stdio.h> -#include <string.h> -#include "scsi.h" -#include "scsish.h" - -extern Device genericdev; -static Device *dev = 0; -static Function *function(char *, Device **); -static void parse(FILE *); - -main() -{ - setbuf(stdout, (char *)0); - scsi_target(2); - set_sony(); - printf("dev=%s, target=%d:\n", dev? dev->name:genericdev.name, s_id); - parse(stdin); - exit(0); -} - -static void -parse(FILE *fp) -{ - int i, n; - char *param; - char buf[4096]; - char *ptrs[100], *cargs[20]; - int iargs[20]; - int nc, ni; - Function *fn; - Device *thatdev; - char err[512]; - - for(;;){ - printf("> "); - fflush(stdout); - if(fgets(buf, sizeof buf, fp) == NULL) - break; - if(param = strchr(buf, '\n')) - *param = 0; - n = getmfields(buf, ptrs, sizeof ptrs/sizeof ptrs[0]); - if(n < 1) - continue; - if((fn = function(ptrs[0], &thatdev)) == 0){ - fprintf(stderr, "can't find cmd '%s'\n", ptrs[0]); - continue; - } - ni = nc = 0; - param = fn->param; - for(i = 1; i < n; i++){ - switch(*param++) - { - case 'I': - iargs[ni++] = atoi(ptrs[i]); - break; - case 'L': - iargs[ni++] = atoi(ptrs[i]); - if((iargs[ni-1] < 0) || (iargs[ni-1] > 7)){ - fprintf(stderr, "%s: lun %d out of range\n", ptrs[0], iargs[ni-1]); - continue; - } - break; - case 'S': - cargs[nc++] = ptrs[i]; - break; - default: - break; - } - if(*param == '?') - param++; - } - while(param[0] && param[1] && (param[1] == '?')) - param += 2; - if((i == n) != (*param == 0)){ - printf("param mismatch: %s: i=%d/n=%d param='%s'\n", - ptrs[0], i, n, param); - printf("device %s: %s\n", thatdev->name, fn->help); - continue; - } - if((*fn->fn)(ni, iargs, nc, cargs, err)) - fprintf(stderr, "error in '%s': %s\n", fn->name, err); - } -} - -static Function * -flook(Function *f, char *name) -{ - for(; f->help; f++) - if(strncmp(f->name, name, strlen(f->name)) == 0) - return(f); - return(0); -} - -static Function * -function(char *name, Device **devptr) -{ - Function *f = 0; - - if(dev && dev->fns && (f = flook(dev->fns, name))) - *devptr = dev; - else if(f = flook(genericdev.fns, name)) - *devptr = &genericdev; - return(f); -} - -void -setdevice(Device *d) -{ - dev = d; - ss_extsense = dev->extsense; -} - -static -help(Device *d, char *cmd, Device *prec) -{ - Function *f; - Function *base; - - base = (prec && prec->fns)? prec->fns:0; - if(cmd == 0){ - printf("device %s(%s):\n", d->name, d->verbose); - if(f = d->fns) - while(f->name){ - if((base == 0) || (flook(base, f->name) == 0)) - printf("\t%s\n", f->help); - f++; - } - return(0); - } else { - if(f = d->fns) - while(f->name) - if(strcmp(f->name, cmd) == 0){ - printf("(%s) %s\n", d->name, f->help); - return(1); - } else - f++; - return(0); - } -} - -int -gen_help(int niargs, int *iargs, int ncargs, char **cargs) -{ -#pragma ref niargs -#pragma ref iargs - - if(dev) - if(help(dev, ncargs == 0? 0:cargs[0], (Device *)0)) - return(0); - help(&genericdev, ncargs == 0? 0:cargs[0], dev); - return(0); -} - -extern Device sonydev; -extern Device wrendev; -static Device *devs[] = { - &genericdev, - &sonydev, - &wrendev, - 0 -}; - -int -gen_dev(int niargs, int *iargs, int ncargs, char **cargs) -{ - Device **d; - -#pragma ref niargs -#pragma ref iargs - - if(ncargs == 0) - printf("dev=%s\n", dev? dev->name : genericdev.name); - else if(strcmp(cargs[0], "?") == 0){ - printf("available devices:\n"); - for(d = devs; *d; d++) - printf("\t%s(%s)\n", (*d)->name, (*d)->verbose); - } else { - for(d = devs; *d; d++) - if(strcmp(cargs[0], (*d)->name) == 0) - break; - if(*d) - setdevice(*d); - else - fprintf(stderr, "device '%s' unknown\n", cargs[0]); - } - return(0); -} - -void -scsi_target(int n) -{ - if((n < 0) || (n >= 8)) - fprintf(stderr, "%d is an invalid target\n", n); - else - s_id = n; -} - -set_sony() -{ - int iargs[1]; - char *cargs[1]; - - cargs[0] = "sony"; - gen_dev(0, iargs, 1, cargs); -} //GO.SYSIN DD scsi/scsish.c echo scsi/dslib.c 1>&2 sed 's/.//' >scsi/dslib.c <<'//GO.SYSIN DD scsi/dslib.c' -/* -|| dslib.c - library routines for /dev/scsi -|| -|| Copyright 1988, 1989, by -|| Gene Dronek (Vulcan Laboratory) and -|| Rich Morin (Canta Forda Computer Laboratory). -|| All rights reserved. -*/ -#ident "dslib.c: $Revision: 1.4 $" - -#include <stdio.h> -#include <sys/types.h> - -#include "dslib.h" -#ifdef aux -#include <sys/vio.h> -#include <sys/scsireq.h> -#endif aux - -int dsdebug=0; -long dsreqflags; /* flag bits always set by filldsreq */ - -#define min(i,j) ( (i) < (j) ? (i) : (j) ) - - -/* -|| Startup/shutdown ----------------------------------------------- -*/ - -static struct context *dsc[FDSIZ]; - - -/* -|| dsopen - open device, set up structures -*/ - -struct dsreq * -dsopen(opath, oflags) - char *opath; - int oflags; -{ - - struct dsreq *dsp; - struct context *cp; - int fd; - DSDBG(fprintf(stderr,"dsopen(%s,%x) ", opath, oflags)); - - fd = open(opath, oflags); - if (fd < 0) - return NULL; /* can't open */ - if (dsc[fd] != NULL) /* already in use */ - ds_zot("dsopen: fd already in use"); - - cp = (struct context *) calloc(1, sizeof(struct context)); - if (cp == NULL) /* can't allocate */ - ds_zot("dsopen: can't allocate space"); - dsc[fd] = cp; - cp->dsc_fd = fd; - dsp = &(cp->dsc_dsreq); - - dsp->ds_flags = 0; - dsp->ds_time = 10 * 1000; /* 10 second default timeout */ - dsp->ds_private = (ulong) cp; /* pointer back to context */ - dsp->ds_cmdbuf = cp->dsc_cmd; - dsp->ds_cmdlen = sizeof cp->dsc_cmd; - dsp->ds_databuf = 0; - dsp->ds_datalen = 0; - dsp->ds_sensebuf = cp->dsc_sense; - dsp->ds_senselen = sizeof cp->dsc_sense; - DSDBG(fprintf(stderr,"=>cp %x, dsp %x\n", cp, dsp)); - return dsp; -} - - -/* -|| dsclose - close device, release context struct. -*/ - -dsclose(dsp) - struct dsreq *dsp; -{ - int fd; - struct context *cp; - - if (dsp == NULL) - ds_zot("dsclose: dsp is NULL"); - - cp = (struct context *)dsp->ds_private; - fd = getfd(dsp); - if ( cp == NULL ) - ds_zot("dsclose: private is NULL"); - - cfree(cp); - dsc[fd] = (struct context *)NULL; - return; -} - - -/* -|| Generic SCSI CCS Command functions ------------------------------------ -|| -|| dsp dsreq pointer -|| data data buffer pointer -|| datalen data buffer length -|| lba logical block address -|| vu vendor unique bits -*/ - -/* -|| testunitready00 - issue group 0 "Test Unit Ready" command (0x00) -*/ - -testunitready00(dsp) - struct dsreq *dsp; -{ - fillg0cmd(dsp, CMDBUF(dsp), G0_TEST, 0, 0, 0, 0, 0); - filldsreq(dsp, 0, 0, DSRQ_READ|DSRQ_SENSE); - return(doscsireq(getfd(dsp), dsp)); -} - - -/* -|| requestsense03 - issue group 0 "Request Sense" command (0x03) -*/ - -requestsense03(dsp, data, datalen, vu) - struct dsreq *dsp; - caddr_t data; - long datalen; - char vu; -{ - fillg0cmd(dsp, CMDBUF(dsp), G0_REQU, 0, 0, 0, B1(datalen), B1(vu<<6)); - filldsreq(dsp, data, datalen, DSRQ_READ); - return(doscsireq(getfd(dsp), dsp)); -} - - -/* -|| write0a - issue group 0 "Write" command (0x0a) -*/ - -write0a(dsp, data, datalen, lba, vu) - struct dsreq *dsp; - caddr_t data; - long datalen, lba; - char vu; -{ - fillg0cmd(dsp, CMDBUF(dsp), G0_WRIT, B3(lba), B1(datalen), B1(vu<<6)); - filldsreq(dsp, data, datalen, DSRQ_READ); - return(doscsireq(getfd(dsp), dsp)); -} - - -/* -|| inquiry12 - issue group 0 "Inquiry" command (0x12) -*/ - -inquiry12(dsp, data, datalen, vu) - struct dsreq *dsp; - caddr_t data; - long datalen; - char vu; -{ - fillg0cmd(dsp, CMDBUF(dsp), G0_INQU, 0, 0, 0, B1(datalen), B1(vu<<6)); - filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE); - return(doscsireq(getfd(dsp), dsp)); -} - - -/* -|| modeselect15 - issue group 0 "Mode Select" command (0x15) -|| -|| save 0 - don't save saveable pages -|| 1 - save saveable pages -*/ - -modeselect15(dsp, data, datalen, save, vu) - struct dsreq *dsp; - caddr_t data; - long datalen; - char save, vu; -{ - fillg0cmd(dsp, CMDBUF(dsp), G0_MSEL, save&1, 0, 0, B1(datalen), B1(vu<<6)); - filldsreq(dsp, data, datalen, DSRQ_WRITE|DSRQ_SENSE); - return(doscsireq(getfd(dsp), dsp)); -} - - -/* -|| modesense1a - issue group 0 "Mode Sense" command (0x1a) -|| -|| pagectrl 0 - current values -|| 1 - changeable values -|| 2 - default values -|| 3 - saved values -|| -|| pagecode 0 - vendor unique -|| 1 - error recovery -|| 2 - disconnect/reconnect -|| 3 - direct access dev. fmt. -|| 4 - rigid disk geometry -|| 5 - flexible disk -|| 6-9 - see specific dev. types -|| 0a - implemented options -|| 0b - medium types supported -|| 3f - return all pages -*/ - -modesense1a(dsp, data, datalen, pagectrl, pagecode, vu) - struct dsreq *dsp; - caddr_t data; - long datalen; - char pagectrl, pagecode, vu; -{ - fillg0cmd(dsp, CMDBUF(dsp), G0_MSEN, 0x10, - ((pagectrl&3)<<6) | (pagecode&0x3F), - 0, B1(datalen), B1(vu<<6)); - filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE); - return(doscsireq(getfd(dsp), dsp)); -} - - -/* -|| senddiagnostic1d - issue group 0 "Send Diagnostic" command (0x1d) -|| -|| self 0 - run test, hold results -|| 1 - run test, return status -|| -|| dofl 0 - device online -|| 1 - device offline -|| -|| uofl 0 - unit online -|| 1 - unit offline -*/ - -senddiagnostic1d(dsp, data, datalen, self, dofl, uofl, vu) - struct dsreq *dsp; - caddr_t data; - long datalen; - char self, dofl, uofl, vu; -{ - fillg0cmd(dsp, CMDBUF(dsp), G0_MSEN, - (self&1)<<2 | (dofl&1)<<1 | (uofl&1), - 0, B2(datalen), B1(vu<<6)); - filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE); - return(doscsireq(getfd(dsp), dsp)); -} - - -/* -|| readcapacity25 - issue group 1 "Read Capacity" command (0x25) -|| -|| pmi 0 - return last logical block, entire unit -|| 1 - return last logical block, current track -*/ - -readcapacity25(dsp, data, datalen, lba, pmi, vu) - struct dsreq *dsp; - caddr_t data; - long datalen, lba; - char pmi, vu; -{ - fillg1cmd(dsp, CMDBUF(dsp), G1_RCAP, 0, B4(lba), 0, 0, pmi&1, B1(vu<<6)); - filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE - /* |DSRQ_CTRL2 */ ); - /* dsp->ds_time = 100; /* often takes a while */ - return(doscsireq(getfd(dsp), dsp)); -} - - -/* -|| readextended28 - issue group 1 "Read Extended" command (0x28) -*/ - -readextended28(dsp, data, datalen, lba, vu) - struct dsreq *dsp; - caddr_t data; - long datalen, lba; - char vu; -{ - fillg1cmd(dsp, CMDBUF(dsp), G1_READ, 0, B4(lba), 0, B2(datalen), B1(vu<<6)); - filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE - /* |DSRQ_CTRL2 */ ); - /* dsp->ds_time = 100; /* often takes a while */ - return(doscsireq(getfd(dsp), dsp)); -} - - -/* -|| writeextended2a - issue group 1 "Write Extended" command (0x2a) -*/ - -writeextended2a(dsp, data, datalen, lba, vu) - struct dsreq *dsp; - caddr_t data; - long datalen, lba; - char vu; -{ - fillg1cmd(dsp, CMDBUF(dsp), G1_WRIT, 0, B4(lba), 0, B2(datalen), B1(vu<<6)); - filldsreq(dsp, data, datalen, DSRQ_READ|DSRQ_SENSE - /* |DSRQ_CTRL2 */ ); - /* dsp->ds_time = 100; /* often takes a while */ - return(doscsireq(getfd(dsp), dsp)); -} - - -/* -|| Support functions ---------------------------------------------------- -*/ - -/* -|| fillg0cmd - Fill a Group 0 command buffer -*/ - -fillg0cmd(dsp, cmd, b0,b1,b2,b3,b4,b5) - struct dsreq *dsp; - uchar_t *cmd, b0,b1,b2,b3,b4,b5; -{ - uchar_t *c = cmd; - DSDBG(fprintf(stderr,"fillg0cmd(%x,%x, %02x %02x %02x %02x %02x %02x)\n", - dsp, cmd, b0,b1,b2,b3,b4,b5)); - *c++ = b0, *c++ = b1, *c++ = b2, *c++ = b3, *c++ = b4, *c++ = b5; - - CMDBUF(dsp) = (caddr_t) cmd; - CMDLEN(dsp) = 6; -} - - -/* -|| fillg1cmd - Fill a Group 1 command buffer -*/ - -fillg1cmd(dsp, cmd, b0,b1,b2,b3,b4,b5,b6,b7,b8,b9) - struct dsreq *dsp; - uchar_t *cmd, b0,b1,b2,b3,b4,b5,b6,b7,b8,b9; -{ - uchar_t *c = cmd; - DSDBG(fprintf(stderr, - "fillg1cmd(%x,%x, %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x)\n", - dsp, cmd, b0,b1,b2,b3,b4,b5,b6,b7,b8,b9)); - - *c++ = b0, *c++ = b1, *c++ = b2, *c++ = b3, *c++ = b4, *c++ = b5; - *c++ = b6, *c++ = b7, *c++ = b8, *c++ = b9; - - CMDBUF(dsp) = (caddr_t) cmd; - CMDLEN(dsp) = 10; -} - - -/* -|| filldsreq - Fill a dsreq structure -*/ - -filldsreq(dsp,data,datalen,flags) - struct dsreq *dsp; - uchar_t *data; -{ - DSDBG(fprintf(stderr,"filldsreq(%x,%x,%d,%x) cmdlen %d\n", - dsp,data,datalen,flags,CMDLEN(dsp))); - dsp->ds_flags = flags | dsreqflags | - (((dsdebug&1) ? DSRQ_TRACE : 0) | - ((dsdebug&2) ? DSRQ_PRINT : 0)); - dsp->ds_time = 10 * 1000; /* default to 10 seconds */ - dsp->ds_link = 0; - dsp->ds_synch = 0; - dsp->ds_ret = 0; - - DATABUF(dsp) = (caddr_t) data; - DATALEN(dsp) = datalen; -} - - -/* -|| bprint - print array of bytes, in hex. -*/ - -#define hex(x) "0123456789ABCDEF" [ (x) & 0xF ] - -bprint(s,n,nperline,space) - char *s; -{ - int i, x; - char *sp = (space) ? " ": ""; - - for(i=0;i<n;i++) { - x = s[i]; - fprintf(stderr,((i%4==3)?"%c%c%s%s":"%c%c%s"), - hex(x>>4), hex(x), sp, sp); - if ( i%nperline == (nperline - 1) ) - fprintf(stderr,"\n"); - } - if ( space ) - fprintf(stderr,"\n"); -} - - -/* -|| doscsireq - issue scsi command, return status or -1 error. -*/ - -doscsireq( fd, dsp) - int fd; /* ioctl file descriptor */ - struct dsreq *dsp; /* devscsi request packet */ -{ - int cc; - int retries = 4; - uchar_t sbyte; - - DSDBG(fprintf(stderr,"doscsireq(%d,%x) %x ---- %s\n",fd,dsp, - (CMDBUF(dsp))[0], - ds_vtostr( (CMDBUF(dsp))[0], cmdnametab))); - - /* - * loop, issuing command - * until done, or further retry pointless - */ - - while ( --retries > 0 ) { - - caddr_t sp; - - sp = SENSEBUF(dsp); - DSDBG(fprintf(stderr,"cmdbuf = "); - bprint(CMDBUF(dsp),CMDLEN(dsp),16,1)); - if ( (dsp->ds_flags & DSRQ_WRITE) ) - DSDBG(bprint( DATABUF(dsp), min(50,DATALEN(dsp)),16,1 )); - -DSDBG(fprintf(stderr,"databuf datalen %x %d\n",DATABUF(dsp), DATALEN(dsp))); - cc = ioctl( fd, DS_ENTER, dsp); - if ( cc < 0) { - ds_panic(dsp, "cannot ioctl fd %d\n",fd); - } - - DSDBG(fprintf(stderr,"cmdlen after ioctl=%d\n",CMDLEN(dsp))); - DSDBG(fprintf(stderr,"ioctl=%d ret=%x %s", - cc, RET(dsp), - RET(dsp) ? ds_vtostr(RET(dsp),dsrtnametab) : "")); - DSDBG(if (SENSESENT(dsp)) fprintf(stderr," sensesent=%d", - SENSESENT(dsp))); - - DSDBG(fprintf(stderr, - " cmdsent=%d datasent=%d sbyte=%x %s\n", - CMDSENT(dsp), DATASENT(dsp), STATUS(dsp), - ds_vtostr(STATUS(dsp), cmdstatustab))); - DSDBG(if ( FLAGS(dsp) & DSRQ_READ ) - bprint( DATABUF(dsp), min(16*16,DATASENT(dsp)), 16,1)); - -#ifdef aux - /* - * check for AUX bus-error - * we retry with poll-dma - */ - if ( RET(dsp) == DSRT_AGAIN ) { - int n = SDC_RDPOLL|SDC_WRPOLL; - DSDBG(fprintf(stderr,"setting rd/wr-poll")); - cc = ioctl( fd, DS_SET, n); /* set bits */ - if ( cc != 0 ) - return -1; - } -#endif aux - - if ( RET(dsp) == DSRT_NOSEL ) - continue; /* retry noselect 3X */ - - /* decode sense data returned */ - if ( SENSESENT(dsp) ) { - DSDBG( - fprintf(stderr, "sense key %x - %s\n", - SENSEKEY(sp), - ds_vtostr( SENSEKEY(sp), sensekeytab)); - bprint( SENSEBUF(dsp), - min(100, SENSESENT(dsp)), - 16,1); - ); - } - DSDBG(fprintf(stderr, "sbyte %x\n", STATUS(dsp))); - - /* decode scsi command status byte */ - sbyte = STATUS(dsp); - switch (sbyte) { - case 0x08: /* BUSY */ - case 0x18: /* RESERV CONFLICT */ - sleep(2); - continue; - case 0x00: /* GOOD */ - case 0x02: /* CHECK CONDITION */ - case 0x10: /* INTERM/GOOD */ - default: - return sbyte; - } - } - return -1; /* fail retry limit */ -} - - -/* -|| opttovar - lookup option in table, return var addr (NULL if fail) -*/ - -int * -opttovar( ostr, table) - char *ostr; - struct opttab{ - char *opt; - int *var; - } *table; -{ - register struct opttab *tp; - - for (tp=table; (tp->var); tp++) - if ( strncmp( ostr, tp->opt, 3) == 0 ) - break; - - if ( !tp->var ) - fprintf(stderr,"unknown option %s", ostr); - - return (tp->var); -} - - -/* -|| ds_vtostr - lookup value in table to return string pointer -*/ - -char * -ds_vtostr( v, table) - long v; - struct vtab *table; -{ - register struct vtab *tp; - - for (tp=table; (tp->string); tp++) - if ( v == tp->val ) - break; - - return (tp->string) ? tp->string : ""; -} - - -/* -|| ds_panic - yelp, leave... -*/ - -ds_panic( fmt, v) - char *fmt; - int v; -{ - extern errno; - - fprintf(stderr,fmt,v); - fprintf(stderr,"\nerrno = %d\n",errno); - exit(1); -} - - -/* -|| ds_zot - go away, with a message. -*/ - -ds_zot(message) - char *message; -{ - fprintf(stderr, "%s\n", message); - exit(1); -} //GO.SYSIN DD scsi/dslib.c echo scsi/load.c 1>&2 sed 's/.//' >scsi/load.c <<'//GO.SYSIN DD scsi/load.c' -#include <stdio.h> -#include <stddef.h> -#include <string.h> -#include "scsi.h" -#include "juke.h" - -j_load(char *vol_id, char *buf, long tlimit) -{ - Side side; - int n, sh, dr; - char disk_to_load[256]; - struct Lunstatus *l; - - if(j_rdshelves(buf)) /* read in shelf names */ - return(-1); - if(j_getstatus(buf)) /* get the jukebox status */ - return(-1); - /* now check which side we want */ - n = strlen(vol_id); - strcpy(disk_to_load, vol_id); - if(disk_to_load[n-1] == 'a') - side = SIDEA; - else if(disk_to_load[n-1] == 'b') - side = SIDEB; - else { - sprintf(buf, "vol_id '%s' must end in a or b", vol_id); - return(-1); - } - disk_to_load[n-1] = 0; - /* which shelf is that? */ - sh = j_shelfof(disk_to_load); - if(sh < 0){ - sprintf(buf, "can't find vol_id %s", disk_to_load); - return(-1); - } - while(tlimit >= 0){ - for(n = 0; n < NLUN; n++){ - l = &j_status.lun[n]; - if(l->diskin && l->shelfvalid && (sh == (l->retshelf>>1))){ - if(((l->retshelf&1) == side) && (n < nlun)) - return(n); - if(l->ready) - goto await; - if(j_drive_to_shelf(n, -1, 0, buf)) - return(-1); - if(j_getstatus(buf)) /* get the jukebox status */ - return(-1); - break; - } - } - /* disk is available */ - dr = j_empty_drive(tlimit, buf); - if(dr < 0){ - sprintf(buf, "can't find a free drive"); - return(-1); - } - if(j_shelf_to_drive(sh, side, dr, buf) < 0) - return(-1); - return(dr); -await: - sleep(10); - tlimit -= 10; - if(j_getstatus(buf)) /* get the jukebox status */ - return(-1); - } - sprintf(buf, "disk '%s' busy", disk_to_load); - return(-1); -} //GO.SYSIN DD scsi/load.c echo scsi/main.c 1>&2 sed 's/.//' >scsi/main.c <<'//GO.SYSIN DD scsi/main.c' -#include <stdio.h> -#include "jukebox.h" -#include "hdr.h" - -main(int argc, char *argv[]) -{ - int c; - int err = 0, cold = 0, warm = 0; - char *toload = 0, *uload = 0; - char *drive = 0; - char buf[256]; - extern int optind; - extern char *optarg; - - setbuf(stdout, (char *)0); /* turn off buffering */ - /* gather options */ - while ((c = getopt(argc,argv,"cn:l:wu:")) != -1) - switch (c) - { - case 'l': toload = optarg; break; - case 'c': cold = 1; break; - case 'w': warm = 1; break; - case 'u': uload = optarg ; break; - case 'n': drive = optarg ; break; - default: err = 1; break; - } - if(err) - exit(1); - /* now actually do some work */ - if (toload){ - if (j_load(toload, buf, 30)) - printf("load %s failed: %s\n", toload, buf); - else - printf("loaded %s on %s\n", toload, buf); - } - if(drive){ - if(j_volid(atoi(drive), buf)) - printf("j_volid(%s) failed: %s\n", drive, buf); - else - printf("%s is mounted on drive %d\n", buf, atoi(drive)); - } - if(cold){ - printf("invent cold: %d\n", cold); - cold_inventory(30, buf); - - } - if (warm) { - printf("invent warm: %d\n", warm); - warm_inventory(buf); - - } - - - if (uload){ - if (j_unload(uload, buf)) - printf("unload %s failed: %s\n", uload, buf); - else - printf("unloaded %s from %s\n", uload, buf); - - - } - exit(0); -} //GO.SYSIN DD scsi/main.c echo scsi/inc/scsi.h 1>&2 sed 's/.//' >scsi/inc/scsi.h <<'//GO.SYSIN DD scsi/inc/scsi.h' -#define SCSI_WR 0x80 -#define SCSI_RD 0x40 -#define SCSI_BRESET 0x20 -#define SCSI_RESET 0x10 -#define SCSI_SENSE 0x08 -#define SCSI_LTMOUT 0x04 - - -#define SCSI_CERR 0x01 //GO.SYSIN DD scsi/inc/scsi.h echo scsi/research.mk 1>&2 sed 's/.//' >scsi/research.mk <<'//GO.SYSIN DD scsi/research.mk' -# config stuff: research unix -CC=lcc -CFLAGS=-g -RANLIB=ranlib -LDFLAGS= -IO=h_io -NPROC=2 //GO.SYSIN DD scsi/research.mk echo scsi/sgi.mk 1>&2 sed 's/.//' >scsi/sgi.mk <<'//GO.SYSIN DD scsi/sgi.mk' -# config stuff: sgi; system v with moran/droneck /dev/scsi -CC=pcc # must be ansi -RANLIB=: -LDFLAGS= -lds -IO=md_io -CFLAGS=-g -I../inc -NPROC=4 //GO.SYSIN DD scsi/sgi.mk echo scsi/unload.c 1>&2 sed 's/.//' >scsi/unload.c <<'//GO.SYSIN DD scsi/unload.c' -#include <stdio.h> -#include <stddef.h> -#include <string.h> -#include "scsi.h" -#include "juke.h" - -j_unload(char *vol_id, char *buf) -{ - Side side; - int i, sh, dr; - char disk_to_unload[256]; - - if(j_rdshelves(buf)) /* read in shelf names */ - return(-1); - if(j_getstatus(buf)) /* get the jukebox status */ - return(-1); - /* now check which side we want */ - - strcpy(disk_to_unload, vol_id); - side = SIDEA; - sh = j_shelfof(disk_to_unload); - if(sh < 0){ - sprintf(buf, "can not find vol_id %s", disk_to_unload); - return(-1); - } - dr = -1; - for(i = 0; i < NLUN; i++){ - printf("dr:.. %d ", i); - printf(" rtsh: %d\n", j_status.lun[i].retshelf); - - /* is sh = retshelf? */ - - if( (j_status.lun[i].retshelf>>1 == sh) || - (j_status.lun[i].retshelf == sh*2+1) ){ dr = i; - break; - } } - printf("dr: %d, sh: %d, side: %d, i: %d\n", dr, sh, side, i); - if (dr == -1){ - sprintf(buf, "no drive has vol_id %s", disk_to_unload); - return(-1); - } - /* put vol_id in it's shelf*/ - if (j_drive_to_shelf(dr, sh, side, buf) >= 0){ - sprintf(buf,"/dev/worm%d\n", dr); - return(0); - } - return(-1); -} //GO.SYSIN DD scsi/unload.c echo scsi/README 1>&2 sed 's/.//' >scsi/README <<'//GO.SYSIN DD scsi/README' - This is a simple extensible shell (scsish) for poking at scsi -devices, particularly the simpler kinds commonly called toasters. -it is supposed to be self-documenting in use; try the help command. -my use of the moran-dronek /dev/scsi library is still imperfect; -there is still some some debugging showing. - - To compile, you first need mk. you then have to pick a system type -to set some flags; currently we support research and sgi. -yours may differ, particularly as no one else has our ansi C compiler for the sgi. -the only problem i would expect is the normal header file crap you get -mixing ansi and non-ansi files. i recommend setting NPROC=1 while debugging hdr files. -if you change (header) files, try putting them in the directory inc -(then others may benefit). To support a new system (say sgi-gcc), just create -a new file sgi-gcc.mk and so on. you may be missing some devices in -your /dev/scsi; the script scsi/gendev may help (but check the major/minor -numbers and permissions). - - As for modifying/extending scsish, it has been designed to be not too hard. -Adding a new device means adding a new set of rules (like the other rules) -to mkfile and creating a new directory (say exabyte) and at least two files in it -(dev.c and fns.h). The wren directory is a small example you can clone. -Adding new functions to any device means updating a file list in mkfile, -updating dev.c and fns.h in the device directory. The argument syntax -scheme is arguably pokey, but liveable. at some future point we should probably -switch over to osterhout's tcl. - - as always, i invite you send extensions/fixes etc back to -andrew@research.att.com //GO.SYSIN DD scsi/README echo scsi/TODO 1>&2 sed 's/.//' >scsi/TODO <<'//GO.SYSIN DD scsi/TODO' - | COPY drive NUMBER NUMBER drive NUMBER {/*:COPY sdrive sstart nblocks ddrive dstart:: */ - s_copy($2, $3, $4, $5, $6); - } - | READ drive NUMBER { - struct scsi_ret output; - s_read($2, $3, 1, &output); - scsiodump(output.data, 1024); - } - | WRITE drive NUMBER { s_write($2, $3, 1); } - | WRITE drive NUMBER NUMBER { s_write($2, $3, $4); } /*:WRITE drive start n:: */ //GO.SYSIN DD scsi/TODO echo scsi/scsish.h 1>&2 sed 's/.//' >scsi/scsish.h <<'//GO.SYSIN DD scsi/scsish.h' -typedef int (*Functionfn)(int, int *, int, char **, char *); - -typedef struct -{ - char *name; - char *help; - char *param; - Functionfn fn; -} Function; - -typedef struct -{ - char *name; - char *verbose; - void (*extsense)(uchar *, char *, int); - Function *fns; -} Device; -extern void setdevice(Device *); - -extern void scsi_target(int); -extern void fixedstr(uchar *src, int len, char *dest); -extern void gen_extsense(uchar *, char *, int); -extern int shelfside(char *arg, char *err); -extern void xd(uchar *base, int, FILE *fp); //GO.SYSIN DD scsi/scsish.h echo scsi/generic/dev.c 1>&2 sed 's/.//' >scsi/generic/dev.c <<'//GO.SYSIN DD scsi/generic/dev.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -static int gen_id(int, int *, int, char **, char *); - -static Function fns[] = { - { "capacity", "capacity [lun=0]", "L?", gen_capacity }, - { "copy", "copy srclun start n destlun dest", "LIILII?", gen_copy }, - { "display", "display", "", gen_display }, - { "dev", "dev [type] # dev ? for list", "S?", gen_dev }, - { "help", "help [cmd]", "S?", gen_help }, - { "id", "id [target=0]", "L?", gen_id }, - { "inq", "inq [lun=0]", "L?", gen_inq }, - { "readt", "readt count [lun=0]", "IL?", gen_readt }, - { "reset", "reset", "", gen_reset }, - { "scsi", "scsi bytes... # 6 or 10", "I?I?I?I?I?I?I?I?I?I?", gen_scsi }, - { "sense", "sense [lun=0]", "L?", gen_sense }, - { "start", "start [lun=0]", "L?", gen_start }, - { "stop", "stop [lun=0]", "L?", gen_stop }, - { "testunit", "testunit [lun=0", "L?", gen_tur }, - { 0 } -}; - -Device genericdev = { - "scsi", "generic scsi", - gen_extsense, - fns -}; - -static int -gen_id(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ -#pragma ref ncargs -#pragma ref cargs -#pragma ref err - - if(niargs == 0) - printf("current SCSI id = %d\n", s_id); - else - scsi_target(iargs[0]); - return(0); -} //GO.SYSIN DD scsi/generic/dev.c echo scsi/generic/inq.c 1>&2 sed 's/.//' >scsi/generic/inq.c <<'//GO.SYSIN DD scsi/generic/inq.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -char *gen_rmb[2] = { "nonremovable", "removable" }; -char *gen_devtype[256] = { - "direct access", - "sequential access", - "printer", - "processor", - "worm", - "cd-rom" -}; - -int -gen_inq(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n, i; - -#pragma ref ncargs -#pragma ref cargs - - if(niargs == 0) - for(niargs = 0; niargs < 8; niargs++) - iargs[niargs] = niargs; - for(i = 0; i < niargs; i++){ - set6(cmd, 0x12, iargs[i]<<5, 0, 0, 36, 0); - if(n = s_io(0, &cmd, 0, &ret, -36, err)) - return(n); - printf("inq(%d,%d): %s %s;", s_id, iargs[i], - gen_rmb[ret.data[1]>>7], gen_devtype[ret.data[0]]); - if(ret.data[4] >= 16){ - char buf[256]; - - fixedstr(&ret.data[8], 8, buf); - printf(" %s", buf); - if(ret.data[4] >= 32){ - fixedstr(&ret.data[16], 16, buf); - printf("/%s", buf); - if(ret.data[4] >= 36){ - fixedstr(&ret.data[32], 4, buf); - printf(" rev=%s", buf); - } - } - } - printf(" [%d bytes]\n", ret.data[4]); - } - return(0); -} //GO.SYSIN DD scsi/generic/inq.c echo scsi/generic/sense.c 1>&2 sed 's/.//' >scsi/generic/sense.c <<'//GO.SYSIN DD scsi/generic/sense.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -int -gen_sense(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - -#pragma ref ncargs -#pragma ref cargs - - if(niargs == 0) - iargs[0] = 0; - set6(cmd, 0x03, iargs[0]<<5, 0, 0, 4, 0); - if(n = s_io(0, &cmd, 0, &ret, 4, err)) - return(n); - printf("sense(%d,%d): ", s_id, iargs[0]); - if((ret.data[0]&0x7F) == 0) - printf("no error\n"); - else { - printf("error class=0x%x, code=0x%x, sense=0x%x", - (ret.data[0]>>4)&7, ret.data[0]&0xF, ret.data[2]&0xF); - if(ret.data[0]&0x80) - printf(", addr=0x%x", ret.data[3]+256L*ret.data[2]+256L*256*ret.data[1]); - printf("\n"); - } - return(0); -} - -static char *exstab[16] = -{ - "no sense", - "recovered error", - "not ready", - "medium error", - "hardware error", - "illegal request", - "unit attention", - "data protect", - "blank check", - "vendor specific (#9)", - "copy aborted", - "aborted command", - "equal", - "volume overflow", - "miscompare", - "reserved (#f)", -}; - -void -gen_extsense(uchar *data, char *dest, int ndata) -{ - int class; - - class = (data[0]>>4)&7; - if(class == 7){ - if(data[0]&0x80) - 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]); - else - sprintf(dest, "extended sense: %s", exstab[data[2]&0xF]); - } else { - sprintf(dest, "sense: class=#%x, code=#%x", class, data[0]&0xF); - } -} //GO.SYSIN DD scsi/generic/sense.c echo scsi/generic/start.c 1>&2 sed 's/.//' >scsi/generic/start.c <<'//GO.SYSIN DD scsi/generic/start.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -int -gen_start(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - -#pragma ref ncargs -#pragma ref cargs - - if(niargs == 0) - iargs[0] = 0; - set6(cmd, 0x1B, iargs[0]<<5, 0, 0, 1, 0); - if(n = s_io(0, &cmd, 0, &ret, 0, err)) - return(n); - return(0); -} //GO.SYSIN DD scsi/generic/start.c echo scsi/generic/stop.c 1>&2 sed 's/.//' >scsi/generic/stop.c <<'//GO.SYSIN DD scsi/generic/stop.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -int -gen_stop(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - -#pragma ref ncargs -#pragma ref cargs - - if(niargs == 0) - iargs[0] = 0; - set6(cmd, 0x1B, iargs[0]<<5, 0, 0, 0, 0); - if(n = s_io(0, &cmd, 0, &ret, 0, err)) - return(n); - return(0); -} //GO.SYSIN DD scsi/generic/stop.c echo scsi/generic/capacity.c 1>&2 sed 's/.//' >scsi/generic/capacity.c <<'//GO.SYSIN DD scsi/generic/capacity.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -int -gen_capacity(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - unsigned long ns, ss; - -#pragma ref ncargs -#pragma ref cargs - - if(niargs == 0) - iargs[0] = 0; - set10(cmd, 0x25, iargs[0]<<5, 0, 0, 0, 0, 0, 0, 0, 0); - if(n = s_io(0, &cmd, 0, &ret, 8, err)) - return(n); - ns = longat(&ret.data[0]); - ss = longat(&ret.data[4]); - printf("capacity(%d,%d): %ld blocks of %ld bytes (#%xx#%x)\n", s_id, iargs[0], - ns, ss, ns, ss); - return(0); -} //GO.SYSIN DD scsi/generic/capacity.c echo scsi/generic/display.c 1>&2 sed 's/.//' >scsi/generic/display.c <<'//GO.SYSIN DD scsi/generic/display.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -extern char *gen_rmb[2]; -extern char *gen_devtype[256]; - -int -gen_display(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n, i, old_id; - int retv = 0; - char rev[100], vendor[100], product[100]; - -#pragma ref niargs -#pragma ref iargs -#pragma ref ncargs -#pragma ref cargs - - old_id = s_id; - for(s_id = 0; s_id < 8; s_id++){ - printf("target %d:\n"); - set6(cmd, 0x00, 0, 0, 0, 0, 0); - if(s_io(0, &cmd, 0, &ret, 0, err)) - continue; - printf("responded to test unit ready\n"); - continue; - for(i = 0; i < 8; i++){ - set6(cmd, 0x12, i<<5, 0, 0, 36, 0); - if(n = s_io(0, &cmd, 0, &ret, -36, err)){ - retv = n; - break; - } - if(ret.nread >= 16) - fixedstr(&ret.data[8], 8, vendor); - else - sprintf(vendor, "??"); - if(ret.nread >= 32) - fixedstr(&ret.data[16], 16, product); - else - sprintf(product, "??"); - if(ret.nread >= 16) - fixedstr(&ret.data[32], 4, rev); - else - sprintf(vendor, "??"); - printf("\tlun(%d): %s %s, %s/%s rev=%s\n", i, - gen_rmb[ret.data[1]>>7], gen_devtype[ret.data[0]], - vendor, product, rev); - } - } - s_id = old_id; - return(retv); -} //GO.SYSIN DD scsi/generic/display.c echo scsi/generic/reset.c 1>&2 sed 's/.//' >scsi/generic/reset.c <<'//GO.SYSIN DD scsi/generic/reset.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" -#include <scsi.h> - -int -gen_reset(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - -#pragma ref niargs -#pragma ref iargs -#pragma ref ncargs -#pragma ref cargs - - set6(cmd, 0, 0, 0, 0, 0, 0); - cmd.bus_id = s_id; - cmd.flags |= SCSI_RESET | SCSI_BRESET; - /* should probably test for some kind of error... */ - ss_io(0, &cmd, 0, &ret, 0, err); - return(0); -} //GO.SYSIN DD scsi/generic/reset.c echo scsi/generic/tur.c 1>&2 sed 's/.//' >scsi/generic/tur.c <<'//GO.SYSIN DD scsi/generic/tur.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -int -gen_tur(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - -#pragma ref ncargs -#pragma ref cargs - - if(niargs == 0) - iargs[0] = 0; - set6(cmd, 0x00, iargs[0]<<5, 0, 0, 0, 0); - if(n = s_io(0, &cmd, 0, &ret, 0, err)) - return(n); - printf("(%d,%d): good status\n", s_id, iargs[0]); - return(0); -} //GO.SYSIN DD scsi/generic/tur.c echo scsi/generic/scsi.c 1>&2 sed 's/.//' >scsi/generic/scsi.c <<'//GO.SYSIN DD scsi/generic/scsi.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -int -gen_scsi(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - -#pragma ref ncargs -#pragma ref cargs - - switch(niargs) - { - case 6: - set6(cmd, iargs[0], iargs[1], iargs[2], iargs[3], iargs[4], iargs[5]); - break; - case 10: - set10(cmd, iargs[0], iargs[1], iargs[2], iargs[3], iargs[4], iargs[5], iargs[6], iargs[7], iargs[8], iargs[9]); - break; - default: - sprintf(err, "number of bytes (%d) must be 6 or 10\n", niargs); - return(1); - } - if(n = s_io(0, &cmd, 0, &ret, 0, err)) - return(n); - return(0); -} //GO.SYSIN DD scsi/generic/scsi.c echo scsi/generic/fns.h 1>&2 sed 's/.//' >scsi/generic/fns.h <<'//GO.SYSIN DD scsi/generic/fns.h' -extern int gen_inq(int, int *, int, char **, char *); -extern int gen_dev(int, int *, int, char **, char *); -extern int gen_help(int, int *, int, char **, char *); -extern int gen_sense(int, int *, int, char **, char *); -extern int gen_start(int, int *, int, char **, char *); -extern int gen_stop(int, int *, int, char **, char *); -extern int gen_capacity(int, int *, int, char **, char *); -extern int gen_display(int, int *, int, char **, char *); -extern int gen_reset(int, int *, int, char **, char *); -extern int gen_tur(int, int *, int, char **, char *); -extern int gen_scsi(int, int *, int, char **, char *); -extern int gen_readt(int, int *, int, char **, char *); -extern int gen_copy(int, int *, int, char **, char *); //GO.SYSIN DD scsi/generic/fns.h echo scsi/generic/readt.c 1>&2 sed 's/.//' >scsi/generic/readt.c <<'//GO.SYSIN DD scsi/generic/readt.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -int -gen_readt(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n, i; - unsigned long ns, ss; - long bs, addr; - long t1, t2; - -#pragma ref ncargs -#pragma ref cargs - - if(niargs == 1) - iargs[1] = 0; - set10(cmd, 0x25, iargs[1]<<5, 0, 0, 0, 0, 0, 0, 0, 0); - if(n = s_io(0, &cmd, 0, &ret, 8, err)) - return(n); - ns = longat(&ret.data[0]); - ss = longat(&ret.data[4]); - bs = ss? sizeof(ret.data)/ss : 1; - time(&t1); - srand(t1); - addr = nrand(ns-iargs[0])-1; - printf("read(%d,%d): %d blocks @%d (chunk=%dx%d),", s_id, iargs[1], iargs[0], addr, bs, ss); - fflush(stdout); - time(&t1); - for(i = iargs[0]; i > 0; i -= bs){ - set10(cmd, 0x28, iargs[1]<<5, addr>>24, addr>>16, addr>>8, addr, - 0, 0, bs*0, 0); - if(n = s_io(0, &cmd, 0, &ret, bs*ss, err)) - return(n); - addr += bs; - } - time(&t2); - printf(" t=%ds (%.0fKB/s)\n", t2-t1, (iargs[0]*(float)ss/1024.)/((t1 == t2)? 1:t2-t1)); - return(0); -} //GO.SYSIN DD scsi/generic/readt.c echo scsi/generic/copy.c 1>&2 sed 's/.//' >scsi/generic/copy.c <<'//GO.SYSIN DD scsi/generic/copy.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -#define PROGRESS \ - if(sbase/TALK != goo){\ - goo = sbase/TALK;\ - time(&t2);\ - printf("\tdoing block %ld at %s", goo*TALK, ctime(&t2));\ - } - -static int copy1(int, int, int, int, int, int, int, char *); - -int -gen_copy(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - int n; - int sdr = 0; - int sbase = iargs[1]; - int nblocks = iargs[2]; - int ddr = 0; - int dbase = iargs[4]; - int starget = iargs[0]; - int dtarget = iargs[3]; - int block = 256; - long nb = nblocks; - long t1, t2; - long goo; - -#define TALK 10000 - extern char *ctime(); - -#pragma ref ncargs -#pragma ref cargs - - if(niargs == 6) - block = iargs[5]; - printf("copying drive (%d,%d)[%d-%d] to drive (%d,%d)[%d-%d] blk=%dK\n", - starget, sdr, sbase, sbase+nblocks-1, - dtarget, ddr, dbase, dbase+nblocks-1, block); - time(&t1); - goo = -1; - while(nblocks > 0){ - n = min(block, nblocks); - printf("writing %d-%d\n", sbase, sbase+n-1);/**/ - if(copy1(starget, sdr, sbase, n, dtarget, ddr, dbase, err)) - break; - sbase += n; - dbase += n; - nblocks -= n; - PROGRESS - } - time(&t2); - t2 -= t1; - if(t2 == 0) t2 = 1; - printf("%ds: ", t2); - if(nblocks){ - printf("copy buggered up: sbase=%d nblks=%d dbase=%d\n", - sbase, nblocks, dbase); - return(1); - } - printf("%d blocks at %.1fKB/s\n", nb, nb/(float)t2); - return(0); -} - -static int -copy1(int st, int sd, int sb, int n, int dt, int dd, int db, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - - set6(cmd, 0x18, sd<<5, 0, 0, 20, 0); - cmd.data[0] = 0x10; /* copy */ - cmd.data[1] = 0; - cmd.data[2] = 0; - cmd.data[3] = 0; - cmd.data[4] = (st<<5)|sd; - cmd.data[5] = (dt<<5)|dd; - cmd.data[6] = 0; - cmd.data[7] = 0; - cmd.data[8] = n>>24; - cmd.data[9] = n>>16; - cmd.data[10] = n>>8; - cmd.data[11] = n; - cmd.data[12] = sb>>24; - cmd.data[13] = sb>>16; - cmd.data[14] = sb>>8; - cmd.data[15] = sb; - cmd.data[16] = db>>24; - cmd.data[17] = db>>16; - cmd.data[18] = db>>8; - cmd.data[19] = db; - return(s_io(0, &cmd, 20, &ret, 0, err)); -} //GO.SYSIN DD scsi/generic/copy.c echo scsi/sony/dev.c 1>&2 sed 's/.//' >scsi/sony/dev.c <<'//GO.SYSIN DD scsi/sony/dev.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -static Function fns[] = { - { "alternate", "alternate [lun]", "L?", sony_alt }, - { "config", "config", "", sony_conf }, - { "copy", "copy srclun start n destlun dest", "LIILI", sony_copy }, - { "diskid", "diskid [lun]", "L?", sony_diskid }, - { "eject", "eject lun", "L", sony_eject }, - { "inq", "inq [lun]", "L?", sony_inq }, - { "internal", "internal test [drive] # internal -1 for list", "II?", sony_internal }, - { "media", "media lun start count [file]", "LIIS?", sony_media }, - { "readid", "readid lun [start]", "LI?", sony_readid }, - { "rel", "rel lun [shelfside]", "LS?", sony_rel }, - { "sense", "sense [lun=0]", "L?", sony_sense }, - { "set", "set shelfside lun", "SL", sony_set }, - { "status", "status", "", sony_status }, - { 0 } -}; - -Device sonydev = { - "sony", "Sony WDA-3000", - sony_extsense, - fns -}; //GO.SYSIN DD scsi/sony/dev.c echo scsi/sony/inq.c 1>&2 sed 's/.//' >scsi/sony/inq.c <<'//GO.SYSIN DD scsi/sony/inq.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -int -sony_inq(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n, i; - -#pragma ref ncargs -#pragma ref cargs - - if(niargs == 0) - for(niargs = 0; niargs < 8; niargs++) - iargs[niargs] = niargs; - for(i = 0; i < niargs; i++){ - set6(cmd, 0x12, iargs[i]<<5, 0, 0, 6, 0); - if(n = s_io(0, &cmd, 0, &ret, 6, err)) - return(n); - printf("inq(%d,%d): ", s_id, iargs[i]); - if(ret.data[5]&0x80) - printf("power off (0x%x)\n", ret.data[5]&0xFF); - else if(ret.data[5]&0x40) - printf("empty (0x%x)\n", ret.data[5]&0xFF); - else - printf("%s,%s,%s,%s (0x%x)\n", - (ret.data[5]&0x08)?"write protect":"writable", - (ret.data[5]&0x04)?"no alternate":"", - (ret.data[5]&0x02)?"drive error":"", - (ret.data[5]&0x01)?"ready":"not ready", - ret.data[5]&0xFF); - } - return(0); -} //GO.SYSIN DD scsi/sony/inq.c echo scsi/sony/alt.c 1>&2 sed 's/.//' >scsi/sony/alt.c <<'//GO.SYSIN DD scsi/sony/alt.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -static -table(int drive, int tab, uchar *data) -{ - int n, i; - - n = data[6]; - printf("(%d,%d): alternate table %d (%d entries)\n", s_id, drive, tab, n); - for(data += 0x18, i = 0; i < n; data += 4, i++) - printf("%ld%c", data[0]+256L*data[1]+256L*256*data[2], - (i%10 == 9)? '\n':' '); - if((i%10) && n) - putchar('\n'); -} - -int -sony_alt(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n, i; - -#pragma ref ncargs -#pragma ref cargs - - if(niargs == 0) - iargs[0] = 0; - set6(cmd, 0xC3, iargs[0]<<5, 0, 0, 0, 0); - if(n = s_io(0, &cmd, 0, &ret, 4096, err)) - return(n); - for(i = 0; i < 4; i++) - table(iargs[0], i+1, &ret.data[1024*i]); - return(0); -} //GO.SYSIN DD scsi/sony/alt.c echo scsi/sony/config.c 1>&2 sed 's/.//' >scsi/sony/config.c <<'//GO.SYSIN DD scsi/sony/config.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -static char mtab[5][2] = -{ - '0', '0', '1', '1', '1', '2', '2', '2', '?', '?' -}; -static char *brdname[] = { - "no doard", "T.D. Systems Viking", "U.S. Design 1158" -}; - -int -sony_conf(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n, i; - char buf[512]; - -#pragma ref niargs -#pragma ref iargs -#pragma ref ncargs -#pragma ref cargs - - set6(cmd, 0x12, 0, 0, 0, 44, 0); - if(n = s_io(0, &cmd, 0, &ret, 44, err)) - return(n); - i = min(ret.data[37], 4); - fixedstr(&ret.data[8], 28, buf); - printf("config(%d,%d): %s device, '%s', %c controller%s, %c drive%s\n", - s_id, 0, (ret.data[0] == 0x4)? "WORM":"Unknown", - buf, mtab[i][0], (mtab[i][0] == '1')?"":"s", - mtab[i][1], (mtab[i][1] == '1')?"":"s"); - printf("\tUnibus-SCSI controller=%s\n", brdname[ret.type]); - printf("\tROMS:"); - if(ret.data[38] != 0xFF) - printf(" upper controller=0x%x,", ret.data[38]); - if(ret.data[40] != 0xFF) - printf(" lower controller=0x%x,", ret.data[40]); - printf( " IF-129=0x%x, SY-46=0x%x, SS-30=0x%x\n", ret.data[36], - ret.data[42], ret.data[43]); - return(0); -} //GO.SYSIN DD scsi/sony/config.c echo scsi/sony/status.c 1>&2 sed 's/.//' >scsi/sony/status.c <<'//GO.SYSIN DD scsi/sony/status.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" - -static -shelf(int i) -{ - printf(": "); - if(i&0x80){ - printf("%s,", (i&0x40)? "disk":"temporary"); - if(i&0x10) printf("wait loading,"); - if(i&0x08) printf("wait ejection,"); - if(i&0x20) printf("use shelf instead of drive for LUN %d", i&7); - } else - printf("no disk"); - printf("\n"); -} - -int -sony_istatus(struct scsi_return *ret, char *err) -{ - struct scsi_cmd cmd; - int n; - - set6(cmd, 0x1D, 0, 0, 0, 10, 0); - cmd.data[0] = 0xE2; /* internal status */ - cmd.data[1] = 0; - cmd.data[2] = 0; - cmd.data[3] = 0; - cmd.data[4] = 0; - cmd.data[5] = 0; - cmd.data[6] = 0; - cmd.data[7] = 0; - cmd.data[8] = 0; - cmd.data[9] = 0; - if(n = s_io(0, &cmd, 10, ret, 0, err)) - return(n); - setdiag(cmd, 0, 128); - if(n = s_io(0, &cmd, 0, ret, 128, err)) - return(n); - return(0); -} - -int -sony_status(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_return ret; - int n, i, start; - uchar *d; - -#pragma ref niargs -#pragma ref iargs -#pragma ref ncargs -#pragma ref cargs - - if(n = sony_istatus(&ret, err)) - return(n); - d = &ret.data[16]; - for(i = 0; i < 8; i++, d += 4){ - printf("drive %d: %sready,%sdisk in LUN,power %s,", i, - (d[0]&1)?"":"not ", (d[0]&0x40)?"":"no ", - (d[0]&0x80)?"off":"on"); - if(d[0]&0x40){ - if(d[1]&0x80){ - printf("disk in drive %d", d[1]&0x7f); - if(d[2]&0x80) - printf(", return shelf %d%c", (d[2]&0x7F)/2, "ab"[d[2]&1]); - } else - printf("disk in shelf %d%c (%d)", (d[1]&0x7f)/2, (d[1]&1)+'a', d[1]&0x7f); - } - printf("\n"); - } - for(i = 0; i < 50;){ - for(start = i; ++i < 50;) - if(d[i] != d[start]) - break; - if(i == start+1) - printf("%d", start); - else - printf("%d-%d", start, i-1); - shelf(d[start]); - } - d += 50; - printf("I/O shelf"); - shelf(*d); - d++; - printf("carrier: "); - i = *d&0x7F; - if(*d&0x80) - printf("disk shelf=%d%c (%d)\n", i/2, 'a'+(i&1), i); - else - printf("no disk\n"); - d++; - if(*d&0x80) - printf("upper drive: disk, LUN=%d\n", *d&7); - else - printf("upper drive: no disk\n"); - d++; - if(*d&0x80) - printf("lower drive: disk, LUN=%d\n", *d&7); - else - printf("lower drive: no disk\n"); - return(0); -} //GO.SYSIN DD scsi/sony/status.c echo scsi/sony/rel.c 1>&2 sed 's/.//' >scsi/sony/rel.c <<'//GO.SYSIN DD scsi/sony/rel.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -int -sony_rel(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n, i, j; - -#pragma ref niargs - - if(ncargs == 0){ - i = 0; - j = 0; /* its ignored anyway */ - } else { - i = 1; - if((j = shelfside(cargs[0], err)) < 0) - return(1); - } - set6(cmd, 0xD7, (iargs[0]<<5)|i, 0, j, 0, 0); - if(n = s_io(0, &cmd, 0, &ret, 0, err)) - return(n); - return(0); -} //GO.SYSIN DD scsi/sony/rel.c echo scsi/sony/set.c 1>&2 sed 's/.//' >scsi/sony/set.c <<'//GO.SYSIN DD scsi/sony/set.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -int -sony_set(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n, i; - -#pragma ref niargs -#pragma ref ncargs - - if((i = shelfside(cargs[0], err)) < 0) - return(1); - set6(cmd, 0xD6, iargs[0]<<5, 0, i, 0, 0); - if(n = s_io(0, &cmd, 0, &ret, 0, err)) - return(n); - return(0); -} //GO.SYSIN DD scsi/sony/set.c echo scsi/sony/eject.c 1>&2 sed 's/.//' >scsi/sony/eject.c <<'//GO.SYSIN DD scsi/sony/eject.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -int -sony_eject(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - -#pragma ref niargs -#pragma ref ncargs -#pragma ref cargs - - set6(cmd, 0xC0, iargs[0]<<5, 0, 0, 0, 0); - if(n = s_io(0, &cmd, 0, &ret, 0, err)) - return(n); - return(0); -} //GO.SYSIN DD scsi/sony/eject.c echo scsi/sony/shelfside.c 1>&2 sed 's/.//' >scsi/sony/shelfside.c <<'//GO.SYSIN DD scsi/sony/shelfside.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -int -shelfside(char *arg, char *err) -{ - char *oarg = arg; - int shelf; - - if((*arg < '0') || (*arg > '9')){ -usage: - sprintf(err, "shelfside '%s' must be numa or numb", oarg); - return(-1); - } - shelf = 0; - while((*arg >= '0') && (*arg <= '9')) - shelf = 10*shelf + *arg++ - '0'; - shelf <<= 1; - if(*arg == 'a') - ; - else if(*arg == 'b') - shelf |= 1; - else - goto usage; - if(*++arg) - goto usage; - return(shelf); -} //GO.SYSIN DD scsi/sony/shelfside.c echo scsi/sony/diskid.c 1>&2 sed 's/.//' >scsi/sony/diskid.c <<'//GO.SYSIN DD scsi/sony/diskid.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -int -sony_diskid(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - -#pragma ref ncargs -#pragma ref cargs - - if(niargs == 0) - iargs[0] = 0; - set6(cmd, 0xC2, iargs[0]<<5, 0, 0, 0, 0); - if(n = s_io(0, &cmd, 0, &ret, 1024, err)) - return(n); - printf("(%d,%d) disk id block:\n", s_id, iargs[0]); - xd(ret.data, 1024, stdout); - return(0); -} //GO.SYSIN DD scsi/sony/diskid.c echo scsi/sony/internal.c 1>&2 sed 's/.//' >scsi/sony/internal.c <<'//GO.SYSIN DD scsi/sony/internal.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -static -internal(int n, int b1, int nb, struct scsi_return *ret, char *err) -{ - struct scsi_cmd cmd; - - set6(cmd, 0x1D, b1, 0, 0, 10, 0); - cmd.data[0] = n; - cmd.data[1] = b1>>8; - cmd.data[2] = 0; - cmd.data[3] = 0; - cmd.data[4] = 0; - cmd.data[5] = 0; - cmd.data[6] = 0; - cmd.data[7] = 0; - cmd.data[8] = 0; - cmd.data[9] = 0; - if(n = s_io(0, &cmd, 10, ret, 0, err)) - return(n); - setdiag(cmd, 0, nb); - if(n = s_io(0, &cmd, 0, ret, nb, err)) - return(n); - return(0); -} - -static char *cmds[] = { - "internal command table", - "error information table", - "arm controller diagnostics", - "scsi control board diagnostics", - "drive controller diagnostics", - "jukebox status", - 0 -}; - -static char *msg1[16] = -{ - "drive not connected or powered off", - "drive connected but no disk", - "diagnostic aborted: write-protect", - "diagnostic aborted: write area full", - "urk 4", "urk 5", "urk 6", "urk 7", "urk 8", "urk 9", "urk 10", - "urk 11", "urk 12", "urk 13", "urk 14", "urk 15" -}; - -static char *testn[10] = -{ - "drive on/off", - "read disk id", - "move", - "seek", - "blank sector search", - "written sector search", - "search writable area", - "write", - "ECC margin check", - "read data compare" -}; - -int -sony_internal(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - register unsigned char *d; - int i, drive, lower; - long t1, t2; - extern char *cmesg[]; - extern char *i0com[], *i1err[], *scsicmd[], *busid[], *scsiident[]; - -#pragma ref ncargs -#pragma ref cargs - - switch(iargs[0]) - { - case -1: - printf("available internal commands:\n"); - for(i = 0; cmds[i]; i++) - printf("\tinternal %d: %s\n", i, cmds[i]); - break; - case 0: - if(internal(0xE5, 0, 256, &ret, err)) - return(1); - printf("internal 0 (%s):\n", cmds[iargs[0]]); - printf("Diagnostic #E5: last 16 internal tasks (drive,shelf)\n"); - for(i = 0, d = ret.data; i < 16; i++, d += 16){ - printf("[%d] %s (%d,%d)\n", - d[0], i0com[d[1]], d[2], d[3]); - } - break; - case 1: - if(internal(0xE4, 0, 256, &ret, err)) - return(1); - printf("internal 1 (%s):\n", cmds[iargs[0]]); - printf("Diagnostic #E4: last 16 errors; initiator[identify] error[sense] (cmd)\n"); - for(i = 0, d = ret.data; i < 16; i++, d += 16){ - printf("%s[%s]: %s[#%x] (%s)\n", - busid[d[0]], scsiident[d[1]], i1err[d[14]], d[15], scsicmd[d[4]]); - } - break; - case 2: - printf("internal 2 (%s):\n", cmds[iargs[0]]); - fflush(stdout); - time(&t1); - if(internal(0x90, 0, 8, &ret, err)) - return(1); - time(&t2); - d = ret.data; - if(d[0] == 0) - printf("\tended normally"); - else - printf("\tfailed, error codes=#%x, #%x, #%x", - d[0], d[1], d[2]); - printf(" (time: %lds)\n", t2-t1); - break; - case 3: - printf("internal 3 (%s):\n", cmds[iargs[0]]); - fflush(stdout); - time(&t1); - if(internal(0xe0, 0, 8, &ret, err)) - return(1); - time(&t2); - d = ret.data; - if(d[0] == 0) - printf("\tended normally"); - else - printf("\tfailed, error codes=#%x, #%x, #%x", - d[0], d[1], d[2]); - printf(" (time: %lds)\n", t2-t1); - break; - case 4: - if(niargs == 1) - iargs[1] = 0; /* zero default */ - drive = iargs[1]; - if(sony_istatus(&ret, err)) - return(1); - if((ret.data[100]&0x80) && (drive == (ret.data[100]&7))) - lower = 0x100; - else if((ret.data[101]&0x80) && (drive == (ret.data[101]&7))) - lower = 0x200; - else { - fprintf(stderr, "drive %d not occupied\n", drive); - return(1); - } - printf("drive %d[%ser]: %s\n", drive, (lower == 0x200)?"low":"upp", cmds[iargs[0]]); - fflush(stdout); - time(&t1); - if(internal(0x18, lower, 256, &ret, err)) - return(1); - time(&t2); - d = ret.data; - if(d[1]&0x80){ - printf("diagnostic result:"); - if((d[1]&0x70) == 0) - printf(" no faults"); - else { - if(d[1]&0x10) - printf(" controller-fault"); - if(d[1]&0x20) - printf(" drive-fault"); - if(d[1]&0x10) - printf(" disk-fault"); - printf(" (last error code 0x%2.2ux)", d[4]); - } - } else - printf("diagnostic not performed: %s", msg1[d[1]&0xF]); - printf(" (time: %lds)\n", t2-t1); - for(i = 0; i < 10; i++) - printf("test %d[%s]: %s\n", i, testn[i], cmesg[d[i*8+drive+8]]); - printf("diagnostic count (drive:avail):"); - for(d += 104, i = 0; i < 8; i++, d += 2) - printf(" %d:%d", i, d[0]+d[1]*256); - printf("\n"); - break; - case 5: - set10(cmd, 0xD3, 0, 0, 0, 0, 0, 0, 0, 0, 0); - if(n = s_io(0, &cmd, 0, &ret, 20, err)) - return(n); - printf("%s: component(fatal err/err/cmds)\n", cmds[iargs[0]]); - d = ret.data; -#define ONE(str, x, sep) printf("%s(%d/%d/%d)%c", str, d[x+3], d[x+2], d[x+1]+256*d[x], sep) - - ONE("upper drive", 4, ' '); - ONE("lower drive", 8, ' '); - ONE("sys control", 12, ' '); - printf("backup mem(0/%d/%d)\n", d[19]+256*d[18], d[17]+256*d[16]); - break; - } - return(0); -} //GO.SYSIN DD scsi/sony/internal.c echo scsi/sony/i0.tab 1>&2 sed 's/.//' >scsi/sony/i0.tab <<'//GO.SYSIN DD scsi/sony/i0.tab' -i0com -00 nop -01 sense result -02 version check -04 recover disk warning -08 sense alternate information -0a error margin check -18 diagnostics -20 sense drive status -21 recalibrate -22 drive on -23 drive off -24 disk out -30 seek -31 move -32 read -a1 disk check -a2 carrier move -b1 disk set -b2 disk release -b3 disk rotate //GO.SYSIN DD scsi/sony/i0.tab echo scsi/sony/i1.tab 1>&2 sed 's/.//' >scsi/sony/i1.tab <<'//GO.SYSIN DD scsi/sony/i1.tab' -i1err -94 drive error (SONY) -a0 invalid command -a1 invalid LUN -a2 reserved bit nonzero -a3 illegal logical address -a4 illegal shelf number -a5 illegal parameter length -a6 illegal parameter -a7 unacceptable diagnostics parameter -a8 unit attention -a9 drive not ready -aa medium removal prevented -ab reserved -ac no disk in LUN //GO.SYSIN DD scsi/sony/i1.tab echo scsi/sony/scsi.tab 1>&2 sed 's/.//' >scsi/sony/scsi.tab <<'//GO.SYSIN DD scsi/sony/scsi.tab' -scsicmd -00 test unit ready -01 rezero unit -03 request sense -08 read -0a write -0b seek -0c move -12 inquiry -15 mode select -16 reserve -17 release -18 copy -1a mode sense -1b start/stop unit -1c receive diagnostics -1d send diagnostics -1e prevent/allow medium removal -25 read capacity -28 read -2a write -2c blank sector search -2d written sector search -c0 disk eject -c2 read disk id -c3 sense alternate information -c4 recover disk warning -d3 request recovered status -d6 disk set -d7 disk release -busid -01 0 -02 1 -80 7 -scsiident -80 no dis/reconnect-LUN 0 -81 no dis/reconnect-LUN 1 -82 no dis/reconnect-LUN 2 -83 no dis/reconnect-LUN 3 -84 no dis/reconnect-LUN 4 -85 no dis/reconnect-LUN 5 -86 no dis/reconnect-LUN 6 -87 no dis/reconnect-LUN 7 -c0 dis/reconnect-LUN 0 -c1 dis/reconnect-LUN 1 -c2 dis/reconnect-LUN 2 -c3 dis/reconnect-LUN 3 -c4 dis/reconnect-LUN 4 -c5 dis/reconnect-LUN 5 -c6 dis/reconnect-LUN 6 -c7 dis/reconnect-LUN 7 -cmesg -0 good -e0 test not done -ee diagnostic could not be done -fe drive not ready (no disk) -ff not connected or power off //GO.SYSIN DD scsi/sony/scsi.tab echo scsi/sony/media.c 1>&2 sed 's/.//' >scsi/sony/media.c <<'//GO.SYSIN DD scsi/sony/media.c' -#include <stdio.h> -#include <stddef.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -static int cnts[256]; -static char *cmsg[256]; - -sony_media1(int drive, long lbn, int lower, struct scsi_return *ret, char *err) -{ - struct scsi_cmd cmd; - int n; - - set6(cmd, 0x1D, drive<<5, 0, 0, 10, 0); - cmd.data[0] = 0x0A; /* error margin check */ - cmd.data[1] = lower? 2:1; - cmd.data[2] = 0; - cmd.data[3] = 0; - cmd.data[4] = drive; - cmd.data[5] = lbn; - cmd.data[6] = lbn>>8; - cmd.data[7] = lbn>>16; - cmd.data[8] = 0; - cmd.data[9] = 0; - if(n = s_io(0, &cmd, 10, ret, 0, err)) - return(n); - setdiag(cmd, drive, 256); - if(n = s_io(0, &cmd, 0, ret, 256, err)) - return(n); - return(0); -} - -int -sony_media(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_return ret; - uchar *d; - int bn, c; - char buf[256]; - int lower; - int nline; - int cur, curb; - int drive = iargs[0]; - long lbn = iargs[1]; - int count = iargs[2]; - extern char *strdup(char *); - int verbose = 0; - FILE *fp = 0; - -#pragma ref niargs - - if(ncargs == 1){ - if(strcmp(cargs[0], "-v") == 0) - verbose = 1; - else if((fp = fopen(cargs[0], "w")) == NULL){ - pperror(err, cargs[0]); - return(1); - } - } - if(sony_istatus(&ret, err)) - return(1); - if((ret.data[100]&0x80) && (drive == (ret.data[100]&7))) - lower = 0; - else if((ret.data[101]&0x80) && (drive == (ret.data[101]&7))) - lower = 1; - else { - sprintf(err, "drive %d not occupied and ready\n", drive); - return(1); - } - printf("media margin check for %d blocks [%d-%d] on %s drive (%d,%d):", - count, lbn, lbn+count-1, lower? "lower":"upper", s_id, drive); - if(fp) - printf(" stored in '%s'", cargs[0]); - putchar('\n'); - if(cmsg[0] == 0){ - for(bn = 0; bn < 256; bn++){ - sprintf(buf, "rare error 0x%x", bn); - cmsg[bn] = strdup(buf); - } - cmsg[0] = "good"; - cmsg[0x40] = "seek error 1 (alternated)"; - cmsg[0x41] = "seek error 2 (alternated)"; - cmsg[0x42] = "seek error 3 (alternated)"; - cmsg[0x44] = "read error 1 (alternated)"; - cmsg[0x45] = "unwritten"; - cmsg[0x46] = "read error 3 (alternated)"; - cmsg[0x81] = "<50% burst"; - cmsg[0x82] = "50-96% burst (alternated)"; - cmsg[0x83] = ">96% burst (alternated)"; - cmsg[0x84] = "uncorrectable (alternated)"; - } -#define DO(ch,cp) if(fp) putc(ch,fp); else if(ch != cur){\ - int newb = bn+cp-ret.data;\ - if(verbose && (curb>=0)){\ - printf("%d %s@%d, ", newb-curb, cmsg[cur], curb);\ - if(++nline == 5){nline = 0; putchar('\n');}\ - }\ - cur = ch;\ - curb = newb;\ - } - cur = 256; - curb = -1; - nline = 0; - for(bn = 0; bn < 256; bn++) - cnts[bn] = 0; - for(bn = lbn, c = count; c >= 256; c -= 256, bn += 256){ - if(sony_media1(drive, bn, lower, &ret, err)) - return(1); - for(d = ret.data; d < &ret.data[256];){ - DO(*d, d); - cnts[*d++]++; - } - } - if(c){ - if(sony_media1(drive, bn, lower, &ret, err)) - return(1); - for(d = ret.data; c; c--){ - DO(*d, d); - cnts[*d++]++; - } - } - DO(256, d); - if(nline) - putchar('\n'); - printf("\t"); - for(c = 0; c < 256; c++) - if(cnts[c]) - printf("%d %s, ", cnts[c], cmsg[c]); - printf("\n"); - return(0); -} //GO.SYSIN DD scsi/sony/media.c echo scsi/sony/readid.c 1>&2 sed 's/.//' >scsi/sony/readid.c <<'//GO.SYSIN DD scsi/sony/readid.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -static int -my_read(int lun, long blk, struct scsi_return *ret, char *err) -{ - struct scsi_cmd cmd; - int n; - - cmd.bus_id = s_id; - set10(cmd, 0x28, lun<<5, blk>>24, blk>>16, blk>>8, blk, 0, 0, 1, 0); - n = ss_io(0, &cmd, 0, ret, 1024, err); - return(n); -} - -int -sony_readid(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_return ret; - char buf[128]; - int drive = iargs[0]; - long blk, lastb; - int pr = 0; - -#pragma ref ncargs -#pragma ref cargs - - buf[0] = 0; - if(niargs == 2){ - if((blk = iargs[1]) < 0){ - blk = -blk; - pr = 1; - } - } else { - if(my_read(drive, 0L, &ret, err) == 0) - goto done; - blk = 1; - } - for(lastb = -1;;){ - if(pr){ - printf("%d: ", blk); - } - if(my_read(drive, blk, &ret, err)) - break; - lastb = blk; - blk = ((long *)ret.data)[9]; - } - if(lastb < 0){ - printf("read(blk=%d) failed\n", blk); - return(1); - } - if(my_read(drive, lastb, &ret, err) != 0) - return(1); -done: - strncpy(buf, (char *)&ret.data[42], 128); - buf[127] = 0; - printf("(%d,%d): '%s'\n", s_id, drive, buf); - return(0); -} //GO.SYSIN DD scsi/sony/readid.c echo scsi/sony/copy.c 1>&2 sed 's/.//' >scsi/sony/copy.c <<'//GO.SYSIN DD scsi/sony/copy.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -#define PROGRESS \ - if(sbase/TALK != goo){\ - goo = sbase/TALK;\ - time(&t2);\ - printf("\tdoing block %ld at %s", goo*TALK, ctime(&t2));\ - } - -static char good[256]; /* by default, all BAD */ -typedef enum { BAD = 0, GOOD } Searchtype; -static int copy1(int, int, int, int, int, int, int, char *); -static int search(int, int, int, int, Searchtype, char *); - -int -sony_copy(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - int n; - int sdr = iargs[0]; - int sbase = iargs[1]; - int nblocks = iargs[2]; - int ddr = iargs[3]; - int dbase = iargs[4]; - int starget = s_id; - int dtarget = s_id; - int wr, unwr; - long nb = nblocks; - long t1, t2; - long goo; - int lower; - struct scsi_return ret; -#define TALK 10000 - extern char *ctime(); - -#pragma ref niargs -#pragma ref ncargs -#pragma ref cargs - - printf("copying drive (%d,%d)[%d-%d] to drive (%d,%d)[%d-%d]\n", - starget, sdr, sbase, sbase+nblocks-1, - dtarget, ddr, dbase, dbase+nblocks-1); - if(sony_istatus(&ret, err)) - return(1); - if((ret.data[100]&0x80) && (sdr == (ret.data[100]&7))) - lower = 0; - else if((ret.data[101]&0x80) && (sdr == (ret.data[101]&7))) - lower = 1; - else { - sprintf(err, "drive %d not occupied\n", sdr); - return(1); - } - good[0] = good[0x81] = good[0x82] = good[0x83] = GOOD; - time(&t1); - goo = -1; - while(nblocks > 0){ - /* search for a block to copy */ - while(n = min(256, nblocks)){ - wr = search(sdr, lower, sbase, n, GOOD, err); - if(wr < 0) - break; - sbase += wr; - dbase += wr; - nblocks -= wr; - if(wr < n) - break; - PROGRESS - } - /* now copy until the first bad block */ - while(n = min(256, nblocks)){ - unwr = search(sdr, lower, sbase, n, BAD, err); - if(unwr < 0) - break; - /*printf("writing %d-%d\n", sbase, sbase+unwr-1);/**/ - if(copy1(starget, sdr, sbase, unwr, dtarget, ddr, dbase, err)) - break; - sbase += unwr; - dbase += unwr; - nblocks -= unwr; - PROGRESS - } - } - time(&t2); - t2 -= t1; - if(t2 == 0) t2 = 1; - printf("%ds: ", t2); - if(nblocks){ - printf("copy buggered up: sbase=%d nblks=%d dbase=%d\n", - sbase, nblocks, dbase); - return(1); - } - printf("%d blocks at %.1fKB/s\n", nb, nb/(float)t2); - return(0); -} - -static int -copy1(int st, int sd, int sb, int n, int dt, int dd, int db, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - - set6(cmd, 0x18, sd<<5, 0, 0, 20, 0); - cmd.data[0] = 0x10; /* copy */ - cmd.data[1] = 0; - cmd.data[2] = 0; - cmd.data[3] = 0; - cmd.data[4] = (st<<5)|sd; - cmd.data[5] = (dt<<5)|dd; - cmd.data[6] = 0; - cmd.data[7] = 0; - cmd.data[8] = n>>24; - cmd.data[9] = n>>16; - cmd.data[10] = n>>8; - cmd.data[11] = n; - cmd.data[12] = sb>>24; - cmd.data[13] = sb>>16; - cmd.data[14] = sb>>8; - cmd.data[15] = sb; - cmd.data[16] = db>>24; - cmd.data[17] = db>>16; - cmd.data[18] = db>>8; - cmd.data[19] = db; - return(s_io(0, &cmd, 20, &ret, 0, err)); -} - -static int -search(int dr, int lower, int sbase, int n, Searchtype s, char *err) -{ - uchar *cp; - struct scsi_return ret; - - if(n <= 0) - return(0); - if(n > 256) - n = 256; - if(sony_media1(dr, sbase, lower, &ret, err)) - return(-1); - for(cp = ret.data; n-- > 0; cp++) - if(good[*cp] != s) - break; - return(cp-ret.data); -} //GO.SYSIN DD scsi/sony/copy.c echo scsi/sony/fns.h 1>&2 sed 's/.//' >scsi/sony/fns.h <<'//GO.SYSIN DD scsi/sony/fns.h' -extern int sony_inq(int, int *, int, char **, char *); -extern int sony_alt(int, int *, int, char **, char *); -extern int sony_conf(int, int *, int, char **, char *); -extern int sony_status(int, int *, int, char **, char *); -extern int sony_set(int, int *, int, char **, char *); -extern int sony_rel(int, int *, int, char **, char *); -extern int sony_eject(int, int *, int, char **, char *); -extern int sony_diskid(int, int *, int, char **, char *); -extern int sony_internal(int, int *, int, char **, char *); -extern int sony_media(int, int *, int, char **, char *); -extern int sony_readid(int, int *, int, char **, char *); -extern int sony_copy(int, int *, int, char **, char *); -extern int sony_sense(int, int *, int, char **, char *); -extern void sony_extsense(uchar *, char *, int); - -extern int shelfside(char *arg, char *err); //GO.SYSIN DD scsi/sony/fns.h echo scsi/sony/sense.c 1>&2 sed 's/.//' >scsi/sony/sense.c <<'//GO.SYSIN DD scsi/sony/sense.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -int -sony_sense(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - char buf[4096]; - -#pragma ref ncargs -#pragma ref cargs - - if(niargs == 0) - iargs[0] = 0; - set6(cmd, 0x03, iargs[0]<<5, 0, 0, 32, 0); - if(n = s_io(0, &cmd, 0, &ret, -32, err)) - return(n); - printf("sense(%d,%d): ", s_id, iargs[0]); - sony_extsense(ret.data, buf, sizeof buf); - printf("%s\n", buf); - return(0); -} - -static char *exstab[16] = -{ - "no sense", - "recovered error", - "not ready", - "medium error", - "hardware error", - "illegal request", - "unit attention", - "data protect", - "blank check", - "key #9", - "copy aborted", - "aborted command", - "key #c", - "volume overflow", - "miscompare", - "key #f", -}; - -void -sony_extsense(uchar *data, char *dest, int ndata) -{ - char buf[4096]; - extern char *nesd[]; - - dest[0] = 0; - switch(data[2]) - { - case 0: - sprintf(dest, "no error"); - break; - case 0x1: /* recovered error */ - sprintf(dest, "recovered error"); - break; - case 0xA: /* recovered error */ - sprintf(dest, "recovered error"); - break; - default: - if(data[7] != 4) - sprintf((char *)data, "warning: extra data is %d, not 4! ", data[7]); - sprintf(buf, "sense: %s", nesd[data[8]&0x7f]); - strcat(dest, buf); - if(data[8]&0x80){ - sprintf(buf, " at addr #%x", data[11]+256L*data[10]+256L*256*data[9]); - strcat(dest, buf); - } - sprintf(buf, ", ext sense: %s", exstab[data[2]]); - strcat(dest, buf); - if(data[0]&0x80){ - sprintf(buf, " info=#%x", data[6]+256L*data[5]+256L*256L*data[4]+256L*256L*256L*data[3]); - strcat(dest, buf); - } - break; - } -} //GO.SYSIN DD scsi/sony/sense.c echo scsi/sony/nesd.tab 1>&2 sed 's/.//' >scsi/sony/nesd.tab <<'//GO.SYSIN DD scsi/sony/nesd.tab' -nesd -00 no sense -01 invalid command -02 recovered error -03 illegal request -06 unit attention -07 parity error -08 message reject error -0a copy aborted -10 ecc trouible occurred -11 time out error -12 controller error -13 SONY I/F II hardware/firmware error -14 scsi hardware/firmware error -20 command not terminated -21 drive interface parity error -22 loading trouble -23 focus trouble -24 tracking trouble -25 spindle trouble -26 slide trouible -27 skew trouble -28 head lead out -29 write modulation trouble -2a under laser power -2b over laser power -2f drive error -30 drive power off -31 no disk in drive -32 drive not ready -38 disk already exists in drive -39 no disk in drive -3a disk already exists in shelf -40 write warning -41 write error -42 disk error -43 cannot read disk id -44 write protect error 1 -45 write protect error 2 -46 disk warning -47 alternation trouble -50 specified address not found -51 address block not found -52 all address could not be read -53 data could not be read -54 uncorrectable read error -55 tracking error -60 no data in specified address -68 z-axis servo error -69 roter servo error -6a hook servo error -6b i/o shelf error -6c drive 0 error -6d drive 1 error -6e shelf error -6f carrier error //GO.SYSIN DD scsi/sony/nesd.tab echo scsi/lib.c 1>&2 sed 's/.//' >scsi/lib.c <<'//GO.SYSIN DD scsi/lib.c' -#include <stdio.h> -#include "scsi.h" -#include "scsish.h" -#include "generic/fns.h" -#include "sony/fns.h" - -s_start(int dr, char *err) -{ - int iargs[1]; - char *cargs[1]; - - iargs[0] = dr; - return(gen_start(1, iargs, 0, cargs, err)); -} - -s_stop(int dr, char *err) -{ - int iargs[1]; - char *cargs[1]; - - iargs[0] = dr; - return(gen_stop(1, iargs, 0, cargs, err)); -} - -s_eject(int dr, char *err) -{ - int iargs[1]; - char *cargs[1]; - - iargs[0] = dr; - return(sony_eject(1, iargs, 0, cargs, err)); -} //GO.SYSIN DD scsi/lib.c echo scsi/wren/dev.c 1>&2 sed 's/.//' >scsi/wren/dev.c <<'//GO.SYSIN DD scsi/wren/dev.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -static Function fns[] = { - { "diag", "diag", "", wr_diag }, - { "extinq", "extinq", "", wr_extinq }, - { "modesense", "modesense", "", wr_modesense }, - { "modeselect", "modeselect er-param er-retries read-recon write-recon cache-enable cache-thr cache-pre cache-size", "IIIIIIIII", wr_modeselect }, - { 0 } -}; -Device wrendev = { - "wren", "Wren V/VI/Runner-2", - gen_extsense, - fns -}; //GO.SYSIN DD scsi/wren/dev.c echo scsi/wren/inq.c 1>&2 sed 's/.//' >scsi/wren/inq.c <<'//GO.SYSIN DD scsi/wren/inq.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -extern char *gen_rmb[2]; -extern char *gen_devtype[256]; - -int -wr_extinq(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - char vendor[9], product[17]; - -#pragma ref niargs -#pragma ref iargs -#pragma ref ncargs -#pragma ref cargs - - set6(cmd, 0x12, 0, 0, 0, 96, 0); - if(n = s_io(0, &cmd, 0, &ret, 96, err)) - return(n); - fixedstr(&ret.data[8], 8, vendor); - fixedstr(&ret.data[16], 16, product); - printf("inq(%d,%d): %s %s, %s/%s rev=%0.4s serial=%0.8s\n", - s_id, 0, gen_rmb[ret.data[1]>>7], gen_devtype[ret.data[0]], - vendor, product, &ret.data[32], &ret.data[36]); - return(0); -} //GO.SYSIN DD scsi/wren/inq.c echo scsi/wren/wmode.c 1>&2 sed 's/.//' >scsi/wren/wmode.c <<'//GO.SYSIN DD scsi/wren/wmode.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -int -wr_modeselect(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - -#pragma ref niargs -#pragma ref ncargs -#pragma ref cargs - - printf("changing modes to "); - if((iargs[0] < 256) && (iargs[0] >= 0)) - printf("er-param=%d(=#%x), ", iargs[0], iargs[0]); - if((iargs[1] < 256) && (iargs[1] >= 0)) - printf("er-retries=%d, ", iargs[1]); - if((iargs[2] < 256) && (iargs[2] >= 0)) - printf("read-recon=%d/256, ", iargs[2]); - if((iargs[3] < 256) && (iargs[3] >= 0)) - printf("write-recon=%d/256, ", iargs[3]); - if((iargs[4] < 256) && (iargs[4] >= 0)) - printf("read cache %sable, ", iargs[4]?"dis":"en"); - if((iargs[5] < 256) && (iargs[5] >= 0)) - printf("write cache %sable, ", iargs[5]?"en":"dis"); - if((iargs[6] < 256) && (iargs[6] >= 0)) - printf("cache max prefetch=%d, ", iargs[6]); - if((iargs[7] < 256) && (iargs[7] >= 0)) - printf("cache size=%d, ", iargs[7]); - if((iargs[8] < 256) && (iargs[8] >= 0)) - printf("cross cyl %sable, ", iargs[8]?"en":"dis"); - printf("\nsleep(10); kill me if you disagree\n"); - fflush(stdout); - sleep(10); - /* do error recovery */ - if(((iargs[0] < 256) && (iargs[0] >= 0)) || ((iargs[1] < 256) && (iargs[1] >= 0))){ - set6(cmd, 0x1A, 0, (0<<6)|0x01, 0, 20, 0); - if(n = s_io(0, &cmd, 0, &ret, 20, err)) - return(n); - memcpy(cmd.data, ret.data, 20); - cmd.data[14] &= ~0x10; - if((iargs[0] < 256) && (iargs[0] >= 0)) - cmd.data[14] = iargs[0]; - if((iargs[1] < 256) && (iargs[1] >= 0)) - cmd.data[15] = iargs[1]; - set6(cmd, 0x15, 0x11, 0, 0, 20, 0); - if(n = s_io(0, &cmd, 20, &ret, 0, err)) - return(n); - } - /* reconnect */ - if(((iargs[2] < 256) && (iargs[2] >= 0)) || ((iargs[3] < 256) && (iargs[3] >= 0))){ - set6(cmd, 0x1A, 0, (0<<6)|0x02, 0, 24, 0); - if(n = s_io(0, &cmd, 0, &ret, 24, err)) - return(n); - memcpy(cmd.data, ret.data, 24); - if((iargs[2] < 256) && (iargs[2] >= 0)) - cmd.data[14] = iargs[2]; - if((iargs[3] < 256) && (iargs[3] >= 0)) - cmd.data[15] = iargs[3]; - set6(cmd, 0x15, 0x11, 0, 0, 24, 0); - if(n = s_io(0, &cmd, 24, &ret, 0, err)) - return(n); - } - /* do cache params*/ - if(((iargs[4] < 256) && (iargs[4] >= 0)) - || ((iargs[5] < 256) && (iargs[5] >= 0)) - || ((iargs[6] < 65536) && (iargs[6] >= 0))){ - set6(cmd, 0x1A, 0, (0<<6)|0x08, 0, 28, 0); - if(n = s_io(0, &cmd, 0, &ret, 24, err)) - return(n); - memcpy(cmd.data, ret.data, 24); - if((iargs[4] < 256) && (iargs[4] >= 0)){ - cmd.data[14] &= ~0x01; - cmd.data[14] |= iargs[4]; - } - if((iargs[5] < 256) && (iargs[5] >= 0)){ - cmd.data[14] &= ~0x04; - cmd.data[14] |= iargs[5]? 0x04:0; - } - if((iargs[6] < 65536) && (iargs[6] >= 0)){ - cmd.data[20] = iargs[6]>>8; - cmd.data[21] = iargs[6]; - } - set6(cmd, 0x15, 0x11, 0, 0, 24, 0); - if(n = s_io(0, &cmd, 24, &ret, 0, err)) - return(n); - } - /* do cache control */ - if(((iargs[8] < 256) && (iargs[8] >= 0)) - || ((iargs[7] < 256) && (iargs[7] >= 0))){ - set6(cmd, 0x1A, 0, (0<<6)|0x38, 0, 28, 0); - if(n = s_io(0, &cmd, 0, &ret, 28, err)) - return(n); - memcpy(cmd.data, ret.data, 28); - cmd.data[14] &= ~0x80; - if(iargs[8]) - cmd.data[14] |= 0x80; - if((iargs[7] < 256) && (iargs[7] >= 0)){ - cmd.data[14] &= 0xF0; - cmd.data[14] |= iargs[7]&0xF; - } - set6(cmd, 0x15, 0x11, 0, 0, 28, 0); - if(n = s_io(0, &cmd, 28, &ret, 0, err)) - return(n); - } - return(0); -} //GO.SYSIN DD scsi/wren/wmode.c echo scsi/wren/diag.c 1>&2 sed 's/.//' >scsi/wren/diag.c <<'//GO.SYSIN DD scsi/wren/diag.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -int -wr_diag(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - long t; - -#pragma ref niargs -#pragma ref iargs -#pragma ref ncargs -#pragma ref cargs - - t = time((long *)0); - set6(cmd, 0x1D, 0x04, 0, 0, 0, 0); - if(n = s_io(0, &cmd, 0, &ret, 0, err)) - return(n); - set6(cmd, 0x1C, 0, 0, 0, 8, 0); - if(n = s_io(0, &cmd, 0, &ret, 8, err)) - return(n); - t = time((long *)0)-t; - printf("selftest diagnostic (%ds)\n", t); - if((ret.data[7] == 0) && (ret.data[2] == 0)) - printf("\tno errors\n"); - else - printf("\terror==#%x,#%x FRU=(#%x,#%x,#%x,#%x)\n", - ret.data[6], ret.data[7], ret.data[2], - ret.data[3], ret.data[4], ret.data[5]); - return(0); -} //GO.SYSIN DD scsi/wren/diag.c echo scsi/wren/fns.h 1>&2 sed 's/.//' >scsi/wren/fns.h <<'//GO.SYSIN DD scsi/wren/fns.h' -extern int wr_extinq(int, int *, int, char **, char *); -extern int wr_modesense(int, int *, int, char **, char *); -extern int wr_modeselect(int, int *, int, char **, char *); -extern int wr_diag(int, int *, int, char **, char *); //GO.SYSIN DD scsi/wren/fns.h echo scsi/wren/omode.c 1>&2 sed 's/.//' >scsi/wren/omode.c <<'//GO.SYSIN DD scsi/wren/omode.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -#define SHORT(n) ((ret.data[n]<<8)|(ret.data[n+1])) - -static int -er(int pcf, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - static char *bit[8] = { "DCR", "DTE", "PER", "EEC", "RC", "TB", "ARRE", "AWRE" }; - - set6(cmd, 0x1A, 0, (pcf<<6)|0x01, 0, 20, 0); - if(n = s_io(0, &cmd, 0, &ret, 20, err)) - return(n); - printf("error recovery:\n\t"); - for(n = 7; n >= 0; n--) - printf(" %s%s", (ret.data[14]&(1<<n))? "":"~", bit[n]); - printf("\n\t%d retries, max ecc span=%d\n", ret.data[15], ret.data[16]); - return(0); -} - -static int -dr(int pcf, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - - set6(cmd, 0x1A, 0, (pcf<<6)|0x02, 0, 24, 0); - if(n = s_io(0, &cmd, 0, &ret, 24, err)) - return(n); - printf("disconnect/reconnect:\n"); - printf("\tread reconnect=%d/256,", ret.data[14]); - printf(" write reconnect=%d/256\n", ret.data[15]); - return(0); -} - -static int -fp(int pcf, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - static char *bit[8] = { "", "", "", "INS", "SURF", "Remove", "HardSec", "SoftSec" }; - - set6(cmd, 0x1A, 0, (pcf<<6)|0x03, 0, 36, 0); - if(n = s_io(0, &cmd, 0, &ret, 36, err)) - return(n); - printf("format parameters:\n"); - printf("\tsec=%dB, trk=%d secs, interleave=%d trk skew=%d cyl skew=%d\n", - SHORT(24), SHORT(22), SHORT(26), SHORT(28), SHORT(30)); - printf("\t%d alt sec/%d alt trk per zone(=%d trks), %d alt trks per vol\n", - SHORT(16), SHORT(18), SHORT(14), SHORT(20)); - printf("\tdrive type:"); - for(n = 7; n >= 3; n--) - printf(" %s%s", (ret.data[32]&(1<<n))? "":"~", bit[n]); - printf("\n"); - return(0); -} - -static int -geom(int pcf, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - - set6(cmd, 0x1A, 0, (pcf<<6)|0x04, 0, 32, 0); - if(n = s_io(0, &cmd, 0, &ret, 32, err)) - return(n); - printf("drive geometry:\n\t%d cyls, %d heads\n", - (ret.data[14]<<16)|SHORT(15), ret.data[17]); - return(0); -} - -static int -cc(int pcf, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - static char *bit[8] = { "", "", "", "", "CacheEnable", "RSVD", "WIE", "RSVD" }; - - set6(cmd, 0x1A, 0, (pcf<<6)|0x38, 0, 28, 0); - if(n = s_io(0, &cmd, 0, &ret, 28, err)) - return(n); - printf("cache control:\n\t"); - for(n = 7; n >= 4; n--) - printf(" %s%s", (ret.data[14]&(1<<n))? "":"~", bit[n]); - printf(", cache size=%d\n", ret.data[14]&0xF); - printf("\tprefetch: thr=%d max=%d(mult %d) min=%d(mult %d)\n", - ret.data[15], ret.data[16], ret.data[17], ret.data[18], ret.data[19]); - return(0); -} - -int -wr_modesense(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - int n; - -#pragma ref ncargs -#pragma ref cargs -#pragma ref niargs -#pragma ref iargs - -#define PCF 0 /* current values */ - - printf("mode sense(%d,0):\n", s_id); - if(n = er(PCF, err)) - return(n); - if(n = dr(PCF, err)) - return(n); - if(n = fp(PCF, err)) - return(n); - if(n = geom(PCF, err)) - return(n); - if(n = cc(PCF, err)) - return(n); - return(0); -} - -int -wr_modeselect(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - -#pragma ref niargs -#pragma ref ncargs -#pragma ref cargs - - printf("changing modes to "); - if((iargs[0] < 256) && (iargs[0] >= 0)) - printf("er-param=%d(=#%x), ", iargs[0], iargs[0]); - if((iargs[1] < 256) && (iargs[1] >= 0)) - printf("er-retries=%d, ", iargs[1]); - if((iargs[2] < 256) && (iargs[2] >= 0)) - printf("read-recon=%d/256, ", iargs[2]); - if((iargs[3] < 256) && (iargs[3] >= 0)) - printf("write-recon=%d/256, ", iargs[3]); - if((iargs[4] < 256) && (iargs[4] >= 0)) - printf("cache %sable, ", iargs[4]?"en":"dis"); - if((iargs[5] < 256) && (iargs[5] >= 0)) - printf("cache threshold=%d, ", iargs[5]); - if((iargs[6] < 256) && (iargs[6] >= 0)) - printf("cache max prefetch=%d, ", iargs[6]); - if((iargs[7] < 256) && (iargs[7] >= 0)) - printf("cache size=%d, ", iargs[7]); - printf("\nsleep(10); kill me if you disagree\n"); - fflush(stdout); - sleep(10); - /* do error recovery */ - if(((iargs[0] < 256) && (iargs[0] >= 0)) || ((iargs[1] < 256) && (iargs[1] >= 0))){ - set6(cmd, 0x1A, 0, (0<<6)|0x01, 0, 20, 0); - if(n = s_io(0, &cmd, 0, &ret, 20, err)) - return(n); - memcpy(cmd.data, ret.data, 20); - cmd.data[14] &= ~0x10; - if((iargs[0] < 256) && (iargs[0] >= 0)) - cmd.data[14] = iargs[0]; - if((iargs[1] < 256) && (iargs[1] >= 0)) - cmd.data[15] = iargs[1]; - set6(cmd, 0x15, 0x11, 0, 0, 20, 0); - if(n = s_io(0, &cmd, 20, &ret, 0, err)) - return(n); - } - /* reconnect */ - if(((iargs[2] < 256) && (iargs[2] >= 0)) || ((iargs[3] < 256) && (iargs[3] >= 0))){ - set6(cmd, 0x1A, 0, (0<<6)|0x02, 0, 24, 0); - if(n = s_io(0, &cmd, 0, &ret, 24, err)) - return(n); - memcpy(cmd.data, ret.data, 24); - if((iargs[3] < 256) && (iargs[3] >= 0)) - cmd.data[14] = iargs[3]; - if((iargs[4] < 256) && (iargs[4] >= 0)) - cmd.data[15] = iargs[4]; - set6(cmd, 0x15, 0x11, 0, 0, 24, 0); - if(n = s_io(0, &cmd, 24, &ret, 0, err)) - return(n); - } - /* do cache control */ - if(((iargs[4] < 256) && (iargs[4] >= 0)) - || ((iargs[5] < 256) && (iargs[5] >= 0)) - || ((iargs[6] < 256) && (iargs[6] >= 0)) - || ((iargs[7] < 256) && (iargs[7] >= 0))){ - set6(cmd, 0x1A, 0, (0<<6)|0x38, 0, 28, 0); - if(n = s_io(0, &cmd, 0, &ret, 28, err)) - return(n); - memcpy(cmd.data, ret.data, 28); - cmd.data[14] &= ~0x10; - if(iargs[4]) - cmd.data[14] |= 0x10; - if((iargs[7] < 256) && (iargs[7] >= 0)){ - cmd.data[14] &= 0xF0; - cmd.data[14] |= iargs[7]&0xF; - } - if((iargs[5] < 256) && (iargs[5] >= 0)) - cmd.data[15] = iargs[5]; - if((iargs[6] < 256) && (iargs[6] >= 0)) - cmd.data[16] = iargs[6]; - set6(cmd, 0x15, 0x11, 0, 0, 28, 0); - if(n = s_io(0, &cmd, 28, &ret, 0, err)) - return(n); - } - return(0); -} //GO.SYSIN DD scsi/wren/omode.c echo scsi/wren/oomode.c 1>&2 sed 's/.//' >scsi/wren/oomode.c <<'//GO.SYSIN DD scsi/wren/oomode.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -#define SHORT(n) ((ret.data[n]<<8)|(ret.data[n+1])) - -static int -er(int pcf, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - static char *bit[8] = { "DCR", "DTE", "PER", "EEC", "RC", "TB", "ARRE", "AWRE" }; - - set6(cmd, 0x1A, 0, (pcf<<6)|0x01, 0, 20, 0); - if(n = s_io(0, &cmd, 0, &ret, 20, err)) - return(n); - printf("error recovery:\n\t"); - for(n = 7; n >= 0; n--) - printf(" %s%s", (ret.data[14]&(1<<n))? "":"~", bit[n]); - printf("\n\t%d retries, max ecc span=%d\n", ret.data[15], ret.data[16]); - return(0); -} - -static int -dr(int pcf, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - - set6(cmd, 0x1A, 0, (pcf<<6)|0x02, 0, 24, 0); - if(n = s_io(0, &cmd, 0, &ret, 24, err)) - return(n); - printf("disconnect/reconnect:\n"); - printf("\tread reconnect=%d/256,", ret.data[14]); - printf(" write reconnect=%d/256\n", ret.data[15]); - return(0); -} - -static int -fp(int pcf, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - static char *bit[8] = { "", "", "", "INS", "SURF", "Remove", "HardSec", "SoftSec" }; - - set6(cmd, 0x1A, 0, (pcf<<6)|0x03, 0, 36, 0); - if(n = s_io(0, &cmd, 0, &ret, 36, err)) - return(n); - printf("format parameters:\n"); - printf("\tsec=%dB, trk=%d secs, interleave=%d trk skew=%d cyl skew=%d\n", - SHORT(24), SHORT(22), SHORT(26), SHORT(28), SHORT(30)); - printf("\t%d alt sec/%d alt trk per zone(=%d trks), %d alt trks per vol\n", - SHORT(16), SHORT(18), SHORT(14), SHORT(20)); - printf("\tdrive type:"); - for(n = 7; n >= 3; n--) - printf(" %s%s", (ret.data[32]&(1<<n))? "":"~", bit[n]); - printf("\n"); - return(0); -} - -static int -geom(int pcf, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - - set6(cmd, 0x1A, 0, (pcf<<6)|0x04, 0, 32, 0); - if(n = s_io(0, &cmd, 0, &ret, 32, err)) - return(n); - printf("drive geometry:\n\t%d cyls, %d heads\n", - (ret.data[14]<<16)|SHORT(15), ret.data[17]); - return(0); -} - -static int -cc(int pcf, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - static char *bit[8] = { "", "", "", "", "CacheEnable", "RSVD", "WIE", "RSVD" }; - - set6(cmd, 0x1A, 0, (pcf<<6)|0x38, 0, 28, 0); - if(n = s_io(0, &cmd, 0, &ret, 28, err)) - return(n); - printf("cache control:\n\t"); - for(n = 7; n >= 4; n--) - printf(" %s%s", (ret.data[14]&(1<<n))? "":"~", bit[n]); - printf(", cache size=%d\n", ret.data[14]&0xF); - printf("\tprefetch: thr=%d max=%dx%d min=%dx%d\n", - ret.data[15], ret.data[16], ret.data[17], ret.data[18], ret.data[19]); - return(0); -} - -int -wr_modesense(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - int n; - -#pragma ref ncargs -#pragma ref cargs -#pragma ref niargs -#pragma ref iargs - -#define PCF 0 /* current values */ - - printf("mode sense(%d,0):\n", s_id); - if(n = er(PCF, err)) - return(n); - if(n = dr(PCF, err)) - return(n); - if(n = fp(PCF, err)) - return(n); - if(n = geom(PCF, err)) - return(n); - if(n = cc(PCF, err)) - return(n); - return(0); -} - -int -wr_modeselect(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - -#pragma ref niargs -#pragma ref ncargs -#pragma ref cargs - - printf("changing modes to "); - if((iargs[0] < 256) && (iargs[0] >= 0)) - printf("er-param=%d(=#%x), ", iargs[0], iargs[0]); - if((iargs[1] < 256) && (iargs[1] >= 0)) - printf("er-retries=%d, ", iargs[1]); - if((iargs[2] < 256) && (iargs[2] >= 0)) - printf("read-recon=%d/256, ", iargs[2]); - if((iargs[3] < 256) && (iargs[3] >= 0)) - printf("write-recon=%d/256, ", iargs[3]); - if((iargs[4] < 256) && (iargs[4] >= 0)) - printf("cache %sable, ", iargs[4]?"en":"dis"); - printf("\nsleep(10); kill me if you disagree\n"); - fflush(stdout); - sleep(10); - /* do error recovery */ - if(((iargs[0] < 256) && (iargs[0] >= 0)) || ((iargs[1] < 256) && (iargs[1] >= 0))){ - set6(cmd, 0x1A, 0, (0<<6)|0x01, 0, 20, 0); - if(n = s_io(0, &cmd, 0, &ret, 20, err)) - return(n); - memcpy(cmd.data, ret.data, 20); - cmd.data[14] &= ~0x10; - if((iargs[0] < 256) && (iargs[0] >= 0)) - cmd.data[14] = iargs[0]; - if((iargs[1] < 256) && (iargs[1] >= 0)) - cmd.data[15] = iargs[1]; - set6(cmd, 0x15, 0x11, 0, 0, 20, 0); - if(n = s_io(0, &cmd, 20, &ret, 0, err)) - return(n); - } - /* reconnect */ - if(((iargs[2] < 256) && (iargs[2] >= 0)) || ((iargs[3] < 256) && (iargs[3] >= 0))){ - set6(cmd, 0x1A, 0, (0<<6)|0x02, 0, 24, 0); - if(n = s_io(0, &cmd, 0, &ret, 24, err)) - return(n); - memcpy(cmd.data, ret.data, 24); - if((iargs[3] < 256) && (iargs[3] >= 0)) - cmd.data[14] = iargs[3]; - if((iargs[4] < 256) && (iargs[4] >= 0)) - cmd.data[15] = iargs[4]; - set6(cmd, 0x15, 0x11, 0, 0, 24, 0); - if(n = s_io(0, &cmd, 24, &ret, 0, err)) - return(n); - } - /* do cache control */ - if((iargs[4] < 256) && (iargs[4] >= 0)){ - set6(cmd, 0x1A, 0, (0<<6)|0x38, 0, 28, 0); - if(n = s_io(0, &cmd, 0, &ret, 28, err)) - return(n); - memcpy(cmd.data, ret.data, 28); - cmd.data[14] &= ~0x10; - if(iargs[4]) - cmd.data[14] |= 0x10; - set6(cmd, 0x15, 0x11, 0, 0, 28, 0); - if(n = s_io(0, &cmd, 28, &ret, 0, err)) - return(n); - } - return(0); -} //GO.SYSIN DD scsi/wren/oomode.c echo scsi/wren/rmode.c 1>&2 sed 's/.//' >scsi/wren/rmode.c <<'//GO.SYSIN DD scsi/wren/rmode.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -#define SHORT(n) ((ret.data[n]<<8)|(ret.data[n+1])) - -static int -er_w6(int pcf, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - static char *bit[8] = { "DCR", "DTE", "PER", "EEC", "RC", "TB", "ARRE", "AWRE" }; - - set6(cmd, 0x1A, 0, (pcf<<6)|0x01, 0, 20, 0); - if(n = s_io(0, &cmd, 0, &ret, 20, err)) - return(n); - printf("error recovery:\n\t"); - for(n = 7; n >= 0; n--) - printf(" %s%s", (ret.data[14]&(1<<n))? "":"~", bit[n]); - printf("\n\t%d retries, max ecc span=%d, recov tlimit=%d\n", - ret.data[15], ret.data[16], ret.data[17]); - return(0); -} - -static int -dr_w6(int pcf, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - - set6(cmd, 0x1A, 0, (pcf<<6)|0x02, 0, 24, 0); - if(n = s_io(0, &cmd, 0, &ret, 24, err)) - return(n); - printf("disconnect/reconnect:\n"); - printf("\tread reconnect=%d/256 full,", ret.data[14]); - printf(" write reconnect=%d/256 empty\n", ret.data[15]); - return(0); -} - -static int -fp_w6(int pcf, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - static char *bit[8] = { "", "", "", "INS", "SURF", "Remove", "HardSec", "SoftSec" }; - - set6(cmd, 0x1A, 0, (pcf<<6)|0x03, 0, 36, 0); - if(n = s_io(0, &cmd, 0, &ret, 36, err)) - return(n); - printf("format parameters:\n"); - printf("\tsec=%d B, trk=%d secs, interleave=%d, trk_skew=%d, cyl_skew=%d\n", - SHORT(24), SHORT(22), SHORT(26), SHORT(28), SHORT(30)); - printf("\t%d alt_sec/%d alt_trk per zone(=%d trks), %d alt_trk per vol\n", - SHORT(16), SHORT(18), SHORT(14), SHORT(20)); - printf("\tdrive type:"); - for(n = 7; n >= 3; n--) - printf(" %s%s", (ret.data[32]&(1<<n))? "":"~", bit[n]); - printf("\n"); - return(0); -} - -static int -geom_w6(int pcf, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - - set6(cmd, 0x1A, 0, (pcf<<6)|0x04, 0, 32, 0); - if(n = s_io(0, &cmd, 0, &ret, 32, err)) - return(n); - printf("drive geometry:\n\t%d cyls, %d heads\n", - (ret.data[14]<<16)|SHORT(15), ret.data[17]); - return(0); -} - -static int -cc_w6(int pcf, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - static char *bit[8] = { "", "", "", "", "CacheEnable", "RSVD", "WIE", "RSVD" }; - - set6(cmd, 0x1A, 0, (pcf<<6)|0x38, 0, 28, 0); - if(n = s_io(0, &cmd, 0, &ret, 28, err)) - return(n); - printf("cache control:\n\t"); - for(n = 7; n >= 4; n--) - printf(" %s%s", (ret.data[14]&(1<<n))? "":"~", bit[n]); - printf(", cache size=%d\n", ret.data[14]&0xF); - printf("\tprefetch: thr=%d max=%d(mult %d) min=%d(mult %d)\n", - ret.data[15], ret.data[16], ret.data[17], ret.data[18], ret.data[19]); - return(0); -} - -static int -er_wr2(int pcf, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - static char *bit[8] = { "DCR", "DTE", "PER", "EEC", "RC", "TB", "ARRE", "AWRE" }; - - set6(cmd, 0x1A, 0, (pcf<<6)|0x01, 0, 20, 0); - if(n = s_io(0, &cmd, 0, &ret, 20, err)) - return(n); - printf("error recovery:\n\t"); - for(n = 7; n >= 0; n--) - printf(" %s%s", (ret.data[14]&(1<<n))? "":"~", bit[n]); - printf("\n\t%d retries, max ecc span=%d, %d wr retries, recov tlimit=%d\n", - ret.data[15], ret.data[16], ret.data[20], SHORT(22)); - return(0); -} - -static int -geom_wr2(int pcf, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - static char *sspin[4] = { - "no spindle synch", - "synch-spindle slave", - "synch-spindle master", - "synch-spindle master control", - }; - - set6(cmd, 0x1A, 0, (pcf<<6)|0x04, 0, 32, 0); - if(n = s_io(0, &cmd, 0, &ret, 32, err)) - return(n); - printf("drive geometry:\n\t%d cyls, %d heads, %s, rotation rate %d\n", - (ret.data[14]<<16)|SHORT(15), ret.data[17], - sspin[ret.data[29]&3], SHORT(32)); - return(0); -} - -static int -cp_wr2(int pcf, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - static char *bit[8] = { "ReadCacheDisable", "", "WriteCacheEnable", "", "", "", "", "" }; - - set6(cmd, 0x1A, 0, (pcf<<6)|0x08, 0, 24, 0); - if(n = s_io(0, &cmd, 0, &ret, 24, err)) - return(n); - printf("caching parameters:\n\t"); - for(n = 2; n >= 0; n -= 2) - printf(" %s%s", (ret.data[14]&(1<<n))? "":"~", bit[n]); - printf("\n\tprefetch: min=%d, max=%d, ceiling=%d\n", - SHORT(18), SHORT(20), SHORT(22)); - return(0); -} - -static int -cc_wr2(int pcf, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - static char *bit[8] = { "", "", "", "", "CacheEnable", "SSM", "WIE", "CCEN" }; - - set6(cmd, 0x1A, 0, (pcf<<6)|0x38, 0, 28, 0); - if(n = s_io(0, &cmd, 0, &ret, 28, err)) - return(n); - printf("cache control:\n\t"); - for(n = 7; n >= 4; n--) - printf(" %s%s", (ret.data[14]&(1<<n))? "":"~", bit[n]); - printf(", cache size=%d\n", ret.data[14]&0xF); - printf("\tprefetch: thr=%d max=%d(mult %d) min=%d(mult %d)\n", - ret.data[15], ret.data[16], ret.data[17], ret.data[18], ret.data[19]); - return(0); -} - -typedef (*Fn)(int, char *); -static struct Drive -{ - char *type; /* match inq field */ - char *desc; /* print at the user */ - Fn fns[10]; -} drive[] = { /* first one is default when none match */ - { "94181-15", "Wren VI", er_w6, dr_w6, fp_w6, geom_w6, cc_w6, 0 }, - { "ST4767", "Wren Runner-2", er_wr2, dr_w6, fp_w6, geom_wr2, cp_wr2, cc_wr2, 0 }, - { 0 } -}; - -int -wr_modesense(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - int n, i, retv; - char product[17]; - int found; - struct scsi_cmd cmd; - struct scsi_return ret; - -#pragma ref ncargs -#pragma ref cargs -#pragma ref niargs -#pragma ref iargs - -#define PCF 0 /* current values */ - - /* find drive type */ - set6(cmd, 0x12, 0, 0, 0, 32, 0); - if(n = s_io(0, &cmd, 0, &ret, 32, err)) - return(n); - fixedstr(&ret.data[16], 16, product); - for(n = 0, found = 0; drive[n].type; n++) - if(strcmp(product, drive[n].type) == 0){ - found = 1; - break; - } - if(!found) - n = 0; - - if(found) - printf("mode sense(%d,0)[%s(%s)]:\n", s_id, drive[n].desc, product); - else - printf("mode sense(%d,0)[using %s, found '%s']:\n", s_id, drive[n].desc, product); - for(i = 0; drive[n].fns[i]; i++) - if(retv = (*drive[n].fns[i])(PCF, err)) - return(retv); - return(0); -} //GO.SYSIN DD scsi/wren/rmode.c echo scsi/wren/w6mode.c 1>&2 sed 's/.//' >scsi/wren/w6mode.c <<'//GO.SYSIN DD scsi/wren/w6mode.c' -#include <stdio.h> -#include "../scsi.h" -#include "../scsish.h" -#include "fns.h" - -int -wr_modeselect(int niargs, int *iargs, int ncargs, char **cargs, char *err) -{ - struct scsi_cmd cmd; - struct scsi_return ret; - int n; - -#pragma ref niargs -#pragma ref ncargs -#pragma ref cargs - - printf("changing modes to "); - if((iargs[0] < 256) && (iargs[0] >= 0)) - printf("er-param=%d(=#%x), ", iargs[0], iargs[0]); - if((iargs[1] < 256) && (iargs[1] >= 0)) - printf("er-retries=%d, ", iargs[1]); - if((iargs[2] < 256) && (iargs[2] >= 0)) - printf("read-recon=%d/256, ", iargs[2]); - if((iargs[3] < 256) && (iargs[3] >= 0)) - printf("write-recon=%d/256, ", iargs[3]); - if((iargs[4] < 256) && (iargs[4] >= 0)) - printf("cache %sable, ", iargs[4]?"en":"dis"); - if((iargs[5] < 256) && (iargs[5] >= 0)) - printf("cache threshold=%d, ", iargs[5]); - if((iargs[6] < 256) && (iargs[6] >= 0)) - printf("cache max prefetch=%d, ", iargs[6]); - if((iargs[7] < 256) && (iargs[7] >= 0)) - printf("cache size=%d, ", iargs[7]); - printf("\nsleep(10); kill me if you disagree\n"); - fflush(stdout); - sleep(10); - /* do error recovery */ - if(((iargs[0] < 256) && (iargs[0] >= 0)) || ((iargs[1] < 256) && (iargs[1] >= 0))){ - set6(cmd, 0x1A, 0, (0<<6)|0x01, 0, 20, 0); - if(n = s_io(0, &cmd, 0, &ret, 20, err)) - return(n); - memcpy(cmd.data, ret.data, 20); - cmd.data[14] &= ~0x10; - if((iargs[0] < 256) && (iargs[0] >= 0)) - cmd.data[14] = iargs[0]; - if((iargs[1] < 256) && (iargs[1] >= 0)) - cmd.data[15] = iargs[1]; - set6(cmd, 0x15, 0x11, 0, 0, 20, 0); - if(n = s_io(0, &cmd, 20, &ret, 0, err)) - return(n); - } - /* reconnect */ - if(((iargs[2] < 256) && (iargs[2] >= 0)) || ((iargs[3] < 256) && (iargs[3] >= 0))){ - set6(cmd, 0x1A, 0, (0<<6)|0x02, 0, 24, 0); - if(n = s_io(0, &cmd, 0, &ret, 24, err)) - return(n); - memcpy(cmd.data, ret.data, 24); - if((iargs[3] < 256) && (iargs[3] >= 0)) - cmd.data[14] = iargs[3]; - if((iargs[4] < 256) && (iargs[4] >= 0)) - cmd.data[15] = iargs[4]; - set6(cmd, 0x15, 0x11, 0, 0, 24, 0); - if(n = s_io(0, &cmd, 24, &ret, 0, err)) - return(n); - } - /* do cache control */ - if(((iargs[4] < 256) && (iargs[4] >= 0)) - || ((iargs[5] < 256) && (iargs[5] >= 0)) - || ((iargs[6] < 256) && (iargs[6] >= 0)) - || ((iargs[7] < 256) && (iargs[7] >= 0))){ - set6(cmd, 0x1A, 0, (0<<6)|0x38, 0, 28, 0); - if(n = s_io(0, &cmd, 0, &ret, 28, err)) - return(n); - memcpy(cmd.data, ret.data, 28); - cmd.data[14] &= ~0x10; - if(iargs[4]) - cmd.data[14] |= 0x10; - if((iargs[7] < 256) && (iargs[7] >= 0)){ - cmd.data[14] &= 0xF0; - cmd.data[14] |= iargs[7]&0xF; - } - if((iargs[5] < 256) && (iargs[5] >= 0)) - cmd.data[15] = iargs[5]; - if((iargs[6] < 256) && (iargs[6] >= 0)) - cmd.data[16] = iargs[6]; - set6(cmd, 0x15, 0x11, 0, 0, 28, 0); - if(n = s_io(0, &cmd, 28, &ret, 0, err)) - return(n); - } - return(0); -} //GO.SYSIN DD scsi/wren/w6mode.c echo scsi/nohup.out 1>&2 sed 's/.//' >scsi/nohup.out <<'//GO.SYSIN DD scsi/nohup.out' //GO.SYSIN DD scsi/nohup.out echo shipped 1>&2 sed 's/.//' >shipped <<'//GO.SYSIN DD shipped' //GO.SYSIN DD shipped echo sym.c 1>&2 sed 's/.//' >sym.c <<'//GO.SYSIN DD sym.c' -#include <libc.h> -#include "worm.h" -#include "sym.h" - -#define NHASH 20011 /* prime please */ -#define HASHMUL 79L /* this is a good value */ -static Symtab *hash[NHASH]; -int sym_mem_fail; - -syminit() -{ - register Symtab **s, *ss; - - for(s = hash; s < &hash[NHASH]; s++){ - for(ss = *s; ss; ss = ss->next) - free((char *)ss); - *s = 0; - } -} - -void * -symlook(sym, space, install) - char *sym; - void *install; -{ - register long h; - register char *p; - register Symtab *s; - - for(p = sym, h = space; *p; h += *p++) - h *= HASHMUL; - if(h < 0) - h = ~h; - h %= NHASH; - for(s = hash[h]; s; s = s->next) - if((s->space == space) && (strcmp(s->name, sym) == 0)){ - if(install) - s->value = install; - return(s->value); - } - if(install){ - s = (Symtab *)malloc((unsigned)sizeof(Symtab)); - if(s == 0){ - sym_mem_fail++; - return(install); - } - s->space = space; - s->name = sym; - s->value = install; - s->next = hash[h]; - hash[h] = s; - } - return(install); -} - -symdel(sym, space) - char *sym; -{ - register long h; - register char *p; - register Symtab *s, *ls; - - for(p = sym, h = space; *p; h += *p++) - h *= HASHMUL; - if(h < 0) - h = ~h; - h %= NHASH; - for(s = hash[h], ls = 0; s; ls = s, s = s->next) - if((s->space == space) && (strcmp(s->name, sym) == 0)){ - if(ls) - ls->next = s->next; - else - hash[h] = s->next; - free((char *)s); - } -} - -symtraverse(space, fn) - void (*fn)(); -{ - register Symtab **s, *ss, *next; - - for(s = hash; s < &hash[NHASH]; s++) - for(ss = *s; ss; ss = next){ - next = ss->next; - if(ss->space == space) - (*fn)(ss->value); - } -} - -symstat() -{ - register Symtab **s, *ss; - int n[NHASH]; - register i, j; - int tot; - double d; - - for(i = 0; i < NHASH; i++) - n[i] = 0; - for(s = hash; s < &hash[NHASH]; s++){ - for(j = 0, ss = *s; ss; ss = ss->next) - j++; - n[j]++; - } - Fprint(1, "N=%ld mul=%ld\n", NHASH, HASHMUL); - for(i = 0, d = 0, tot = 0; i < NHASH; i++){ - if(n[i]) Fprint(1, "%d of length %d\n", n[i], i); - d += n[i]*i; - if(i) tot += n[i]; - } - Fprint(1, "ave len = %g\n", d/tot); -} - -symdump(sym, space) - char *sym; -{ - register long h; - register char *p; - register Symtab *s; - - for(p = sym, h = space; *p; h += *p++) - h *= HASHMUL; - if(h < 0) - h = ~h; - h %= NHASH; - print("symdump(%s):\n", sym); - for(s = hash[h]; s; s = s->next) - print("\t%s: space=%d value=%ld\n", s->name, s->space, s->value); -} //GO.SYSIN DD sym.c echo sym.h 1>&2 sed 's/.//' >sym.h <<'//GO.SYSIN DD sym.h' -typedef struct Symtab -{ - short space; - char *name; - void *value; - struct Symtab *next; -} Symtab; -extern void *symlook(); - -#define S_INODE 1 -#define S_UID 2 -#define S_GID 3 -#define S_FAIL 4 /* fetch */ -#define S_TOGO 5 /* wormy */ - -extern int sym_mem_fail; //GO.SYSIN DD sym.h echo t0 1>&2 sed 's/.//' >t0 <<'//GO.SYSIN DD t0' - -static Inode *inodes; -static long ip; -static long ninodes = 0; -static char *nameb; -static long np; -static long nnameb = 0; -static long nblocks; -#define IINC 1024 -#define NINC (64*IINC) - -ininit() -{ - if(nnameb == 0){ - nameb = malloc((unsigned)(nnameb = NINC)); - if(nameb == 0){ - fprint(2, "wmv: malloc fail, %d bytes\n", nnameb); - exit(1); - } - } - np = 0; - if(ninodes == 0){ - inodes = (Inode *)malloc(sizeof(Inode)*(unsigned)(ninodes = IINC)); - if(inodes == 0){ - fprint(2, "wmv: malloc fail, %d inodes %d bytes\n", ninodes, ninodes*sizeof(Inode)); - exit(1); - } - } - ip = 0; -} - -inadd(s, i) - Superblock *s; - register Inode *i; -{ - register long len; - - len = strlen(i->name.n)+1; - if(np+len > nnameb){ - while(np+len > nnameb) - nnameb += NINC; - nameb = realloc(nameb, (unsigned)nnameb); - if(nameb == 0){ - fprint(2, "wmv: realloc fail, %d bytes\n", nnameb); - exit(1); - } - } - strcpy(nameb+np, i->name.n); - i->name.o = np; - np += len; - if(ip == ninodes){ - ninodes += IINC; - inodes = (Inode *)realloc((char *)inodes, (unsigned)ninodes*sizeof(Inode)); - if(inodes == 0){ - fprint(2, "wmv: realloc fail, %d inodes %d bytes\n", ninodes, ninodes*sizeof(Inode)); - exit(1); - } - } - inodes[ip++] = *i; -} - -inwrite(s) - Superblock *s; -{ - char *e; - - if(e = lkwri(s, inodes, ip, nameb, np, 0L)){ - fprint(2, "%s\n", e); - return(1); - } - return(0); -} //GO.SYSIN DD t0 echo t1 1>&2 sed 's/.//' >t1 <<'//GO.SYSIN DD t1' - -static Inode *inodes; -static long ip; -static long ninodes = 0; -static char *nameb; -static long np; -static long nnameb = 0; -static long nblocks; -#define IINC 1024 -#define NINC (64*IINC) - -ininit() -{ - if(nnameb == 0) - nameb = malloc((unsigned)(nnameb = NINC)); - np = 0; - if(ninodes == 0) - inodes = (Inode *)malloc(sizeof(Inode)*(unsigned)(ninodes = IINC)); - ip = 0; -} - -inadd(s, i) - Superblock *s; - register Inode *i; -{ - register long len; - - len = strlen(i->name.n)+1; - if(np+len > nnameb){ - while(np+len > nnameb) - nnameb += NINC; - nameb = realloc(nameb, (unsigned)nnameb); - } - strcpy(nameb+np, i->name.n); - i->name.o = np; - np += len; - if(ip == ninodes){ - ninodes += IINC; - inodes = (Inode *)realloc((char *)inodes, (unsigned)ninodes*sizeof(Inode)); - } - inodes[ip++] = *i; - return(0); -} - -inwrite(s) - Superblock *s; -{ - char *e; - - if(e = lkwri(s, inodes, ip, nameb, np, 0L)){ - fprint(2, "%s\n", e); - bad = 1; - return; - } -} //GO.SYSIN DD t1 echo timenow.c 1>&2 sed 's/.//' >timenow.c <<'//GO.SYSIN DD timenow.c' -#include <libc.h> -#include "worm.h" - -char * -timenow() -{ - long tim; - char *tims; - - time(&tim); - tims = ctime(&tim); - tims[19] = 0; - return(tims); -} //GO.SYSIN DD timenow.c echo vlink.c 1>&2 sed 's/.//' >vlink.c <<'//GO.SYSIN DD vlink.c' -#include <libc.h> -#include "worm.h" -#include "sym.h" - -char * -lkopi(s, blk, doinodes) - register Superblock *s; - long blk; -{ - register Inode *i; - short fd = s->fd; - char *b; - long nb; - char *nameb; - Inode *inodes; - static char buf[64]; - - if((b = malloc(s->blocksize)) == 0){ - sprint(buf, "couldn't malloc buffer (%d bytes)", s->blocksize); - return(buf); - } - numinodes = 0; - numnamechars = 0; - for(;;){ - if(s->magic != SMAGIC){ - fprint(2, "bad Superblock at %ld\n", blk); - exit(1); - } - if(s->ninodes){ - numinodes += s->ninodes; - numnamechars += s->ninochars; - } - if(doinodes && s->ninodes){ - nb = (s->ninodes+IPERB-1)/IPERB; - inodes = (Inode *)malloc((unsigned)(s->blocksize*nb)); - if(inodes == 0){ - sprint(buf, "inode malloc(%d) fail, sbrk=%d\n", - (s->blocksize*nb), sbrk(0)); - return(buf); - } - Seek(s, s->binodes); - if(Read(s, (char *)inodes, nb)) - goto skip; - nb = (s->ninochars+s->blocksize-1)/s->blocksize; - nameb = malloc((unsigned)(s->blocksize*nb)); - if(nameb == 0){ - sprint(buf, "name buffer malloc(%d) fail, sbrk=%d\n", - (s->blocksize*nb), sbrk(0)); - return(buf); - } - if(Read(s, nameb, nb)) - goto skip; - for(nb = 0, i = inodes; nb < s->ninodes; nb++, i++){ - i->name.n = i->name.o+nameb; - if(i->block < 0) - (void)symdel(i->name.n, S_INODE); - else - (void)symlook(i->name.n, S_INODE, (void *)i); - } - if(sym_mem_fail){ - sprint(buf, "%d inode malloc fails: %d, %d sbrk=%d\n", - sym_mem_fail, numinodes, s->ninodes, sbrk(0)); - return(buf); - } - } - skip: - blk = s->nextsb; - Seek(s, blk); - if(Read(s, b, 1L)) - break; - *s = *((Superblock *)b); - s->fd = fd; - if(s->myblock == 0) - s->myblock = blk; - } - free(b); - return((char *)0); -} - -char * -lkwri(s, i, ni, c, nc, ndata) - Superblock *s; - Inode *i; - long ni, nc, ndata; - char *c; -{ - char *b; - long blk; - static char buf[256]; - long ib, ic; - - s->ninodes = ni; - s->ninochars = nc; - ib = (ni+IPERB-1)/IPERB; - ic = (nc+s->blocksize-1)/s->blocksize; - if(ndata+ib+ic+1 > s->nfree) /* one for superblock */ - return("not enough space for new files"); - s->binodes = s->nextffree+ndata; - s->nextffree += ndata+ib+ic; - s->nfree -= ndata+ib+ic; - - if((b = malloc(s->blocksize)) == 0){ - sprint(buf, "couldn't malloc buffer (%d bytes)", s->blocksize); - return(buf); - } - blk = s->nextsb; - s->nextsb = s->nextffree++; - s->nfree--; - s->myblock = blk; - time(&s->ctime); - memset(b, 0, s->blocksize); - *((Superblock *)b) = *s; - Seek(s, blk); - if(Write(s, b, 1L)){ - sprint(buf, "couldn't write superblock at %d", blk); - return(buf); - } - free(b); - Seek(s, s->binodes); - if(Write(s, (char *)i, ib)) - return("write1 error"); - if(Write(s, c, ic)) - return("write2 error"); - return((char *)0); -} - - -char * -lkwsb(s) - Superblock *s; -{ - char *b; - long blk; - static char buf[64]; - - if((b = malloc(s->blocksize)) == 0){ - sprint(buf, "couldn't malloc buffer (%d bytes)", s->blocksize); - return(buf); - } - blk = s->nextsb; - s->nextsb = s->nextffree++; - s->nfree--; - memset(b, 0, s->blocksize); - s->myblock = blk; - *((Superblock *)b) = *s; - Seek(s, blk); - if(Write(s, b, 1L)) - return("couldn't write superblock"); - free(b); - return((char *)0); -} - -Inode * -vinodefn(s) - char *s; -{ - return((Inode *)symlook(s, S_INODE, (void *)0)); -} - -void -vtraverse(fn) - void (*fn)(); -{ - symtraverse(S_INODE, fn); -} //GO.SYSIN DD vlink.c echo wbtree.c 1>&2 sed 's/.//' >wbtree.c <<'//GO.SYSIN DD wbtree.c' -#include <libc.h> -#include "worm.h" -#include "sym.h" -#include <sys/types.h> -#include <sys/stat.h> -#include <fio.h> - -Inode **inos; -long nino; -int fdT, fdF; -char *inonames; -char *timenow(); -char *tmp = "/tmp"; - -cmp(a, b) - Inode **a, **b; -{ - return(strcmp((*a)->name.n, (*b)->name.n)); -} - -main(argc, argv) - char **argv; -{ - Superblock s, news; - char *e; - char *dev = "/dev/worm0"; - int c, fd; - char dbname[256]; - extern char *optarg; - extern int optind; - void blkfn(); - - while((c = getopt(argc, argv, "t:f:")) != -1) - switch(c) - { - case 'f': dev = optarg; break; - case 't': tmp = optarg; break; - case '?': usage(); - } - dev = mapdev(dev); - if(optind != argc-1) - usage(); - sprint(dbname, "%s/cbt%d", tmp, getpid()); - fd = dbinit(dbname); - if((s.fd = open(dev, 2)) < 0){ - perror(dev); - exit(1); - } - if(e = openinode(&s, DO_INODE|SPIN_DOWN)){ - fprint(2, "%s: %s\n", dev, e); - exit(1); - } - if(strcmp(argv[optind], s.vol_id)){ - fprint(2, "wanted volid '%s'; got '%s'\n", argv[optind], s.vol_id); - exit(1); - } - if((inos = (Inode **)malloc(sizeof(inos[0])*(int)numinodes)) == 0){ - fprint(2, "out of memory (%d inodes, %d bytes)\n", numinodes, sizeof(inos[0])*(int)numinodes); - exit(1); - } - nino = 0; - inodetraverse(blkfn); - fprint(2, "%s: sorting inodes\n", timenow()); - qsort((char *)inos, (int)nino, sizeof(inos[0]), cmp); - news = s; - news.ninodes = nino; - creatdb(fd, dbname, &news); /* fills in nF, nT, inochars */ - c = NBLKS(&news, news.nF)+NBLKS(&news, news.nT)+NBLKS(&news, news.ninochars); - if(c > news.nfree){ - fprint(2, "%s: sorry, not enough blocks; %d+%d+%d>%d\n", - NBLKS(&news, news.nF), NBLKS(&news, news.nT), - NBLKS(&news, news.ninochars), news.nfree); - exit(1); - } - Seek(&s, news.binodes = s.nextffree); - fdwrite(&s, fdF, (int)news.nF); - fdwrite(&s, fdT, (int)news.nT); - memwrite(&s, inonames, (int)news.ninochars); - /* set up link ptrs so that zeroing block zero undoes btreeing */ - s.nfree -= c; - s.nextffree += c; - s.ninodes = 0; - if(e = lkwsb(&s)) - fprint(2, "%s\n", e); - news.nextffree = s.nextffree; - news.nfree = s.nfree; - news.myblock = 0; - news.version = VBTREE; - news.nextsb = s.myblock; - time(&news.ctime); - Seek(&s, news.myblock); - free((char *)inos); - e = malloc(news.blocksize); - if(e == 0){ - fprint(2, "wbtree: unbelievable malloc fail of %d\n", news.blocksize); - exit(1); - } - memset(e, 0, news.blocksize); - *((Superblock *)e) = news; - Write(&s, e, 1L); - exit(0); -} - -usage() -{ - fprint(2, "Usage: worm btree [-fdevice] [-ttmpdir] vol_id\n"); - exit(2); -} - -dbinit(name) - char *name; -{ - char buf[256]; - struct stat sbuf; - int pid, pip[2]; - - fprint(2, "%s: init db '%s'\n", timenow(), name); - sprint(buf, "cbt creat %s", name); - if(system(buf)) - exit(1); - pipe(pip); - pid = fork(); - if(pid < 0){ - perror("fork"); - exit(1); - } - if(pid){ - close(pip[0]); - return(pip[1]); - } else { - close(pip[1]); - dup2(pip[0], 0); - close(pip[0]); - execl("/usr/lib/btree/btbuild", "btbuild", name, 0); - perror("execl"); - exit(1); - return(0); - } -} - -creatdb(fd, name, s) - char *name; - Superblock *s; /* fills in nF, nT, inochars */ -{ - char buf[256]; - struct stat sbuf; - int status, i; - short n; - char *np; - - fprint(2, "%s: creating db '%s'\n", timenow(), name); - inonames = malloc((int)numnamechars+1024); - if(inonames == 0){ - sprint(buf, "malloc(%d) namechars failed", numnamechars+1024); - perror(buf); - exit(1); - } - Finit(fd, (char *)0); - np = inonames; - for(i = 0; i < nino; i++){ - n = strlen(inos[i]->name.n); - Fwrite(fd, (char *)&n, 2L); - Fwrite(fd, inos[i]->name.n, (long)n); - memcpy(np, inos[i]->name.n, n+1); - inos[i]->name.o = np - inonames; - np += n+1; - n = sizeof(Inode); - Fwrite(fd, (char *)&n, 2L); - Fwrite(fd, (char *)inos[i], (long)n); - } - s->ninochars = np-inonames; - Fflush(fd); - close(fd); - if(wait(&status) < 0){ - perror("wbtree: wait"); - exit(1); - } - if(status){ - fprint(2, "wbtree: bad status %d from btbuild\n", status); - exit(1); - } - sprint(buf, "%s.F", name); - if(((fdF = open(buf, 0)) < 0) || (fstat(fdF, &sbuf) < 0)){ - perror(buf); - exit(1); - } - unlink(buf); - s->nF = sbuf.st_size; - sprint(buf, "%s.T", name); - if(((fdT = open(buf, 0)) < 0) || (fstat(fdT, &sbuf) < 0)){ - perror(buf); - exit(1); - } - unlink(buf); - s->nT = sbuf.st_size; - fprint(2, "%s: db done\n", timenow()); -} - -void -blkfn(i) - Inode *i; -{ - inos[nino++] = i; -} - -fdwrite(s, fd, cnt) - Superblock *s; -{ - char b[BIGBLOCK]; - int n; - - lseek(fd, 0L, 0); - while(cnt >= sizeof b){ - n = read(fd, b, sizeof b); - if(n != sizeof b){ - perror("short read"); - exit(3); - } - Write(s, b, NBLKS(s, sizeof b)); - cnt -= sizeof b; - } - if(cnt){ - if(read(fd, b, cnt) != cnt){ - perror("short read"); - exit(4); - } - memset(b+cnt, 0, sizeof b - cnt); - Write(s, b, NBLKS(s, cnt)); - } -} - -memwrite(s, base, cnt) - Superblock *s; - char *base; -{ - int chunk = (BIGBLOCK/1024)*s->blocksize; - - while(cnt >= chunk){ - Write(s, base, NBLKS(s, chunk)); - cnt -= chunk; - base += chunk; - } - if(cnt) - Write(s, base, NBLKS(s, cnt)); -} - -char * -timenow() -{ - long tim; - char *tims; - - time(&tim); - tims = ctime(&tim); - tims[19] = 0; - return(tims); -} //GO.SYSIN DD wbtree.c echo wcat.c 1>&2 sed 's/.//' >wcat.c <<'//GO.SYSIN DD wcat.c' -#include <libc.h> -#include "sym.h" -#include "worm.h" - -main(argc, argv) - char **argv; -{ - Superblock s; - char *e; - Inode *i; - int c; - char *dev = "/dev/worm0"; - extern char *optarg; - extern int optind; - - while((c = getopt(argc, argv, "f:")) != -1) - switch(c) - { - case 'f': dev = optarg; break; - case '?': usage(); - } - if(optind+2 != argc) - usage(); - dev = mapdev(dev); - if((s.fd = open(dev, 0)) < 0){ - perror(dev); - exit(1); - } - if(e = openinode(&s, DO_INODE|SPIN_DOWN)){ - fprint(2, "%s: %s\n", dev, e); - exit(1); - } - if(strcmp(s.vol_id, argv[optind])){ - fprint(2, "vol_id mismatch: wanted %s, got %s\n", argv[optind], s.vol_id); - exit(1); - } - if(i = inodeof(argv[++optind])) - c = pr(&s, i); - else { - fprint(2, "wcat: can't find %s\n", argv[optind]); - c = 1; - } - exit(c); -} - -usage() -{ - fprint(2, "Usage: worm cat [-fdevice] vol_id file\n"); - exit(1); -} - -pr(s, i) - Superblock *s; - register Inode *i; -{ - char b[BIGBLOCK]; - register long len, n; - long nb; - int fd; - - fd = 1; - nb = sizeof b / s->blocksize; - Seek(s, i->block); - for(n = i->nbytes, len = nb*s->blocksize; n > 0;){ - if(len > n){ - len = n; - nb = (len+s->blocksize-1)/s->blocksize; - } - Read(s, b, nb); - if(write(fd, b, (int)len) != len){ - perror("write"); - return(1); - } - n -= len; - } - close(fd); - return(0); -} //GO.SYSIN DD wcat.c echo wcopy.c 1>&2 sed 's/.//' >wcopy.c <<'//GO.SYSIN DD wcopy.c' -#include <libc.h> -#include <fio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <signal.h> -#include "worm.h" - -long minfree = 40000; -int verbose = 0; - -main(argc, argv) - char **argv; -{ - Superblock in, out; - char *e; - char buf[4096]; - int n; - long lineno; - int c; - char *dev = "/dev/worm0"; - long tfiles, tbytes; - int eof; - char first[4096]; - extern char *optarg; - extern int optind; - - argout = argv[0]; - while((c = getopt(argc, argv, "vm:f:")) != -1) - switch(c) - { - case 'f': dev = optarg; break; - case 'm': minfree = atol(optarg); break; - case 'v': verbose = 1; break; - case '?': usage(); - } - - if(optind+3 != argc) - usage(); - e = mapdev(argv[optind+1]); - if((out.fd = open(e, 2)) < 0){ - perror(e); - exit(1); - } - if(e = openinode(&out, SPIN_DOWN)){ - fprint(2, "%s: %s\n", *argv, e); - exit(1); - } - if(strcmp(out.vol_id, argv[optind+2])){ - fprint(2, "vol_id mismatch: wanted %s, got %s\n", argv[optind+2], out.vol_id); - exit(1); - } - if(out.version != VLINK){ - fprint(2, "%s: can't write on a b-tree disk\n", out.vol_id); - exit(1); - } - dev = mapdev(dev); - if((in.fd = open(dev, 2)) < 0){ - perror(*argv); - exit(1); - } - if(e = openinode(&in, DO_INODE|SPIN_DOWN)){ - fprint(2, "%s: %s\n", *argv, e); - exit(1); - } - if(strcmp(in.vol_id, argv[optind])){ - fprint(2, "vol_id mismatch: wanted %s, got %s\n", argv[optind], in.vol_id); - exit(1); - } - for(n = 1; n <= NSIG; n++) - signal(n, SIG_IGN); - eof = 0; - tfiles = tbytes = 0; - lineno = 0; - while(!eof){ - /* flush seperater lines */ - while(e = Frdline(0)){ - lineno++; - if(*e) - break; - } - if(e == 0) - break; - ininit(); - proc(&out, e); - strncpy(first, e, sizeof first); - if(out.nfree < minfree){ - fprint(2, "wcopy: disk %s full before copying group '%s' line %d\n", - out.vol_id, first, lineno); - exit(1); - } - while(e = Frdline(0)){ - lineno++; - if(*e == 0) - break; - proc(&out, e); - } - if(e == 0) - eof = 1; - if(bad) - exit(1); - nfiles = nbytes = 0; - blkdone = 0; - inwrite(&out, &in); - if(bad) - exit(1); - if(verbose) - fprint(1, "%s group('%s' %d files, %.6fMB) done\n", - timenow(), first, nfiles, nbytes/1e6); - tfiles += nfiles; - tbytes += nbytes; - } - if(verbose) - fprint(1, "%s total: %d files, %.6fMB\n", timenow(), tfiles, tbytes/1e6); - exit(0); -} - -usage() -{ - fprint(2, "Usage: worm copy [-v] [-m minfree] [-f src_dev] src_id dest_dev dest_id < files\n"); - exit(1); -} - -proc(s, file) - Superblock *s; - char *file; -{ - struct stat sbuf; - unsigned short mode; - Inode i; - Inode *srci; - - if((srci = inodeof(file)) == 0){ - fprint(2, "can't find file '%s'\n", file); - return; - } - memset((char *)&i, 0, sizeof(i)); - i = *srci; - i.block = 0; - nbytes += i.nbytes; - if(inadd(s, &i)) - bad = 1; -} - -writeout(dest, i, blk, src) - Superblock *dest, *src; - Inode *i; - long *blk; -{ - char b[BIGBLOCK]; - Inode *srci; - long n, len, blen; - char *name; - - n = (i->nbytes+dest->blocksize-1)/dest->blocksize; - *blk += n; - blkdone += n; - blen = sizeof b/dest->blocksize; - len = blen*dest->blocksize; - nbytes += i->nbytes; - nfiles++; - name = i->name.n; - srci = inodeof(name); - Seek(src, srci->block); - for(n = i->nbytes; n > len; n -= len){ - if(Read(src, b, blen)){ - out: - fprint(2, "read problem: seek=%d n=%d blen=%d len=%d; ", - srci->block, n, blen, len); - perror(name); - bad = 1; - return; - } - if(Write(dest, b, blen)){ -fprint(2, "nb=%d, n=%d len=%d blen=%d\n", i->nbytes, n, len, blen); - perror("data write"); - exit(1); - } - } - if(n){ - n += dest->blocksize-1; - n /= dest->blocksize; - if(Read(src, b, n)) - goto out; - if(Write(dest, b, n)){ - perror("data write"); - exit(1); - } - } -} //GO.SYSIN DD wcopy.c echo wdir.c 1>&2 sed 's/.//' >wdir.c <<'//GO.SYSIN DD wdir.c' -#include <libc.h> -#include "worm.h" -#include "sym.h" -#include <sys/types.h> -#include <sys/stat.h> - -char *dumpdir(); -int verbose = 0; - -main(argc, argv) - char **argv; -{ - Superblock s, news; - char *e; - char *dev = "/dev/worm0"; - int update = 0; - int c; - char buf[1024]; - extern char *optarg; - extern int optind; - void blkfn(); - - while((c = getopt(argc, argv, "f:vu")) != -1) - switch(c) - { - case 'f': dev = optarg; break; - case 'u': update = 1; break; - case 'v': verbose = 1; break; - case '?': usage(); - } - dev = mapdev(dev); - if(optind != argc-1) - usage(); - if((s.fd = open(dev, 2)) < 0){ - perror(dev); - exit(1); - } - if(e = openinode(&s, SPIN_DOWN)){ - fprint(2, "%s: %s\n", dev, e); - exit(2); - } - if(s.version != VBTREE){ - fprint(2, "%s is not a btree!\n", s.vol_id); - exit(2); - } - if(strcmp(argv[optind], s.vol_id)){ - fprint(2, "wanted volid '%s'; got '%s'\n", argv[optind], s.vol_id); - exit(1); - } - if(e = dumpdir(&s, update)){ - fprint(2, "%s: %s\n", dev, e); - exit(2); - } - sprint(buf, "/usr/worm/tmp/%s", s.vol_id); - unlink(buf); - exit(0); -} - -usage() -{ - fprint(2, "Usage: dir [-fdevice] -v] [-u] vol_id\n"); - exit(2); -} - -char * -dumpdir(s, update) - register Superblock *s; -{ - char *b; - static char buf[64]; - char name[256], buf1[256]; - - if((b = malloc(s->blocksize)) == 0){ - sprint(buf, "couldn't malloc buffer (%d bytes)", s->blocksize); - return(buf); - } - numinodes = s->ninodes; - sprint(name, "/usr/worm/dirs/%s", s->vol_id); - Seek(s, s->binodes); - sprint(buf1, "%s.F", name); - copyout(s, buf1, s->nF, update, verbose); - sprint(buf1, "%s.T", name); - copyout(s, buf1, s->nT, update, verbose); - sprint(buf1, "%s.I", name); - copyout(s, buf1, s->ninochars, update, verbose); - free(b); - return((char *)0); -} //GO.SYSIN DD wdir.c echo wild 1>&2 sed 's/.//' >wild <<'//GO.SYSIN DD wild' //GO.SYSIN DD wild echo wls.c 1>&2 sed 's/.//' >wls.c <<'//GO.SYSIN DD wls.c' -#include <libc.h> -#include "worm.h" -#include "sym.h" -#include <sys/types.h> -#include <sys/stat.h> -#include <pwd.h> -#include <grp.h> - -int lflag = 0; -int bflag = 0; - -main(argc, argv) - char **argv; -{ - Superblock s; - register Inode *i; - char *e; - char *dev = "/dev/worm0"; - int c; - extern char *optarg; - extern int optind; - void pr(); - - while((c = getopt(argc, argv, "lbf:")) != -1) - switch(c) - { - case 'f': dev = optarg; break; - case 'l': lflag = 1; break; - case 'b': bflag = 1; break; - case '?': usage(); - } - dev = mapdev(dev); - if((s.fd = open(dev, 0)) < 0){ - perror(dev); - exit(1); - } - if(e = openinode(&s, DO_INODE|SPIN_DOWN)){ - fprint(2, "%s: %s\n", dev, e); - exit(1); - } - c = 0; - if(optind < argc) - while(optind < argc){ - if(i = inodeof(argv[optind])) - pr(i); - else { - Fprint(2, "%s not found\n", argv[optind]); - c = 1; - } - optind++; - } - else - inodetraverse(pr); - exit(c); -} - -char * -suid(n) -{ - static char buf[24]; - struct passwd *p; - char *s; - - sprint(buf, "#%d", n); - if(s = (char *)symlook(buf, S_UID, (void *)0)) - strcpy(buf, s); - else { - s = strdup(buf); - if(p = getpwuid(n)) - strcpy(buf, p->pw_name); - (void)symlook(s, S_UID, (void *)strdup(buf)); - } - return(buf); -} - -char * -sgid(n) -{ - static char buf[24]; - struct group *g; - char *s; - - sprint(buf, "#%d", n); - if(s = (char *)symlook(buf, S_GID, (void *)0)) - strcpy(buf, s); - else { - s = strdup(buf); - if(g = getgrgid(n)) - strcpy(buf, g->gr_name); - (void)symlook(s, S_GID, (void *)strdup(buf)); - } - return(buf); -} - -mode(n, sx) -{ - Fputc(1, (n&4)? 'r':'-'); - Fputc(1, (n&2)? 'w':'-'); - Fputc(1, (n&1)? sx:'-'); -} - -void -pr(i) - register Inode *i; -{ - char *s; - - if(lflag){ - Fputc(1, ((i->mode&S_IFMT) == S_IFDIR)? 'd':'-'); - mode(i->mode>>6, ((i->mode&S_IFMT) == S_ISUID)? 's':'x'); - mode(i->mode>>3, ((i->mode&S_IFMT) == S_ISGID)? 's':'x'); - mode(i->mode, 'x'); - Fputc(1, ((i->mode&S_IFMT) == S_IFLNK)? 'L':' '); - s = ctime(&i->ctime); - s += 4; - s[12] = 0; - Fprint(1, "%2d%8s%7s %6ld %s %s\n", 1, suid(i->uid), sgid(i->gid), - i->nbytes, s, i->name.n); - return; - } - if(bflag) - Fprint(1, "%s\t%ld\n", i->name.n, i->block); - else - Fprint(1, "%s\n", i->name.n); -} - -usage() -{ - fprint(2, "Usage: worm ls [-fdevice] [-l] [-b] [files ...]\n"); - exit(2); -} //GO.SYSIN DD wls.c echo wmkfs.c 1>&2 sed 's/.//' >wmkfs.c <<'//GO.SYSIN DD wmkfs.c' -#include <libc.h> -#include "worm.h" -#include <sys/types.h> -#include <sys/udaioc.h> - -usage() -{ - fprint(2, "Usage: worm mkfs [-fdevice] [-ccomments] [-bblksize] [-nnblks] [-vnewvol_id] vol_id\n"); - fprint(2, "e.g. worm mkfs -f1 -c\"512x512x24 movies\" tdmovies1a\n"); - exit(1); -} - -main(argc, argv) - char **argv; -{ - Superblock s, os; - char *b; - long sb; - int c; - char *volid; - char *dev = "/dev/worm0"; - char *nblks = 0; - char *bsize = 0; - char *nvolid = 0; - char *comments = 0; - char *e; - int virgin; - extern optind; - extern char *optarg; - - while((c = getopt(argc, argv, "f:n:b:c:v:")) != -1) - switch(c) - { - case 'b': bsize = optarg; break; - case 'c': comments = optarg; break; - case 'f': dev = optarg; break; - case 'n': nblks = optarg; break; - case 'v': nvolid = optarg; break; - case '?': usage(); - } - if(optind != argc-1) - usage(); - volid = argv[optind]; - if(strlen(volid) > sizeof(s.vol_id)-1) - volid[sizeof(s.vol_id)-1] = 0; - c = volid[strlen(volid)-1]; - if((c != 'a') && (c != 'b')){ - if(nvolid == 0){ - fprint(2, "worm mkfs: vol_id '%s' must end in 'a' or 'b'\n", volid); - exit(1); - } - fprint(2, "worm mkfs: warning: vol_id '%s' should end in 'a' or 'b'\n", volid); - } - if(nvolid){ - if(strlen(nvolid) > sizeof(s.vol_id)-1) - nvolid[sizeof(s.vol_id)-1] = 0; - c = nvolid[strlen(nvolid)-1]; - if((c != 'a') && (c != 'b')){ - fprint(2, "worm mkfs: vol_id '%s' must end in 'a' or 'b'\n", nvolid); - exit(1); - } - } - dev = mapdev(dev); - if((s.fd = open(dev, 2)) < 0){ - perror(dev); - exit(1); - } - /* - now, do we read the current superblock or make one up? - this is hard to answer in general, push the answer off to virginal() - */ - virgin = virginal(&s); - if(virgin){ - setdefaults(&s, nblks); - if((s.blocksize < 512) || (s.blocksize%512)){ - fprint(2, "worm mkfs: bad blocksize '%s'\n", bsize); - exit(1); - } - strcpy(s.vol_id, volid); - } else { - if(strcmp(volid, s.vol_id)){ - fprint(2, "worm mkfs: volid mismatch; expected %s, got %s\n", - volid, s.vol_id); - exit(1); - } - } - /* set any new parameters */ - if(nvolid) - strcpy(s.vol_id, nvolid); - if(bsize) - s.blocksize = atoi(bsize); - if(s.blocksize < 512){ - fprint(2, "wormmkfs: bad nblocks = '%s'\n", nblks); - exit(1); - } - if(s.blocksize % sizeof(Inode)){ - fprint(2, "worm mkfs: sizeof(Inode)=%d does not divide blocksize %d\n", - sizeof(Inode), s.blocksize); - exit(1); - } - if(comments){ - if(strlen(comments) > sizeof(s.comment)-1) - comments[sizeof(s.comment)-1] = 0; - strcpy(s.comment, comments); - } - /* only check if we are changing it */ - if(nblks && !virgin){ - s.nblocks = atoi(nblks); - s.nfree = s.nblocks - s.nextffree; - if(s.nfree <= 1){ - fprint(2, "worm mkfs: new nblocks(%d) is too small\n", s.nblocks); - exit(1); - } - } - /* now allocate the new superblock */ - sb = s.nextsb; - s.myblock = sb; - s.nextsb = sb+1; - s.nextffree = sb+2; - s.nfree -= 1; - s.ninodes = 0; - s.ninochars = 0; - s.binodes = 0; - time(&s.ctime); - /* write it */ - if((b = malloc(s.blocksize)) == 0){ - fprint(2, "worm mkfs: cannot malloc buffer %d bytes\n", s.blocksize); - exit(1); - } - memset(b, 0, s.blocksize); - memcpy(b, (char *)&s, sizeof(s)); - Seek(&s, sb); - if(Write(&s, b, 1L)) - exit(1); - ioctl(s.fd, UIOSPDW); - exit(0); -} - -setdefaults(s, nblks) - Superblock *s; - char *nblks; -{ - struct ud_unit sz; - char buf[1024]; - - s->magic = SMAGIC; - s->blocksize = 1024; - s->version = VLINK; - if(nblks){ - s->nblocks = atoi(nblks); - if(s->nblocks <= 2){ - fprint(2, "worm mkfs: nblocks(%d) too small\n", s->nblocks); - exit(1); - } - } else { - read(s->fd, buf, sizeof buf); /* ignore error */ - if(ioctl(s->fd, UIOCHAR, &sz) >= 0){ - switch(sz.radsize) - { /* note below figures/2 used in scsi/volid.c */ - case 3275999: /* sony 12in clv single density */ - s->nblocks = 1600000; - break; - case 6551999: /* sony 12in clv double density */ - s->nblocks = 3250000; - break; - default: - fprint(2, "worm mkfs: unknown size %d\n", sz.radsize); - exit(1); - } - } else - s->nblocks = 1600000; - fprint(2, "worm mkfs: using disk size %d\n", s->nblocks); - } - s->zero = 0; - s->nfree = s->nblocks-1; - s->nextffree = 0; - s->nextsb = 1; - s->vol_id[0] = 0; - s->comment[0] = 0; - s->myblock = 0; - s->ctime = 0; -} - -virginal(s) - Superblock *s; -{ - char buf[1024]; - static char zeros[1024]; - long sb; - char *e; - extern char *getenv(); - - if(e = getenv("WORMZERO")) - sb = atoi(e); - else - sb = 1; - bigseek(s->fd, sb, 1024, 0); - errno = 0; - if(read(s->fd, buf, 1024) == 1024) - goto valid; - if((errno != ENXIO) && (errno != 0) && memcmp(buf, zeros, 1024)) - goto invalid; - errno = 0; - if(read(s->fd, buf, 1024) == 1024){ /* try next block */ -valid: - if(e = openinode(s, SPIN_DOWN)){ - fprint(2, "worm mkfs: %s\n", e); - exit(1); - } - return(0); - } else { - if((errno == ENXIO) || (errno == 0) || (memcmp(buf, zeros, 1024) == 0)) - return(1); -invalid: - perror("worm mkfs: I/O errors probing for superblock"); - exit(1); - } -} //GO.SYSIN DD wmkfs.c echo wmount.c 1>&2 sed 's/.//' >wmount.c <<'//GO.SYSIN DD wmount.c' -#include <libc.h> -#include "worm.h" - -main(argc, argv) - char **argv; -{ - Superblock s; - char *e, *vol_id = 0, *vol; - char *dev = "/dev/worm0"; - int c; - long nf = 0; - char wflag[512]; - char buf[512]; - int i; - extern char *optarg; - extern int optind; - extern long atol(); - - wflag[0] = 0; - while((c = getopt(argc, argv, "w:")) != -1) - switch(c) - { - case 'w': sprint(wflag, "-w%s", optarg); break; - case '?': usage(); - } - if(optind < argc){ - vol_id = argv[optind++]; - if(optind != argc) - usage(); - } - if(vol_id == 0){ - for(i = 0; ; i++){ - sprint(buf, "%d", i); - dev = mapdev(buf); - if((s.fd = open(dev, 0)) < 0){ - if(errno == ENOENT) - break; - if(errno == ENXIO) - continue; - perror(dev); - exit(2); - } - if(e = openinode(&s, SPIN_DOWN)){ - fprint(2, "%s: %s\n", dev, e); - exit(2); - } - print("%s: %s\n", dev, s.vol_id); - close(s.fd); - } - exit(0); - } - if(isjukebox()){ - jload(vol_id, wflag); - exit(0); - } - { - for(i = 0; ; i++){ - sprint(buf, "%d", i); - dev = mapdev(buf); - if((s.fd = open(dev, 0)) < 0){ - if(errno == ENOENT) - break; - if(errno == ENXIO) - continue; - perror(dev); - exit(2); - } - if(e = openinode(&s, SPIN_DOWN)){ - fprint(2, "%s: %s\n", dev, e); - exit(2); - } - if(strcmp(vol_id, s.vol_id) == 0){ - print("%s\n", buf); - exit(0); - } - close(s.fd); - } - } - fprint(2, "worm mount: couldn't find %s\n", vol_id); - exit(1); -} - -usage() -{ - print("Usage: worm mount [-wsecs] [vol_id]\n"); - exit(2); -} - -/* - return zero if there isn't a jukebox -*/ -isjukebox() -{ - return(access("/dev/scsi", 6) == 0); -} - -/* - secs is the number of seconds to wait -*/ -jload(vol, secs) - char *vol, *secs; -{ - if(*secs) - execlp("/usr/lib/worm/jukebox", "jukebox", secs, "-m", vol, (char *)0); - else - execlp("/usr/lib/worm/jukebox", "jukebox", "-m", vol, (char *)0); - perror("execlp(/usr/lib/worm/jukebox)"); - exit(1); -} //GO.SYSIN DD wmount.c echo wmv.c 1>&2 sed 's/.//' >wmv.c <<'//GO.SYSIN DD wmv.c' -#include <libc.h> -#include "worm.h" -#include "sym.h" -#include <sys/types.h> -#include <sys/stat.h> -#include <pwd.h> -#include <grp.h> -#include <signal.h> - -int lflag = 0; -int bflag = 0; - -main(argc, argv) - char **argv; -{ - Superblock s; - register Inode *i; - Inode newi; - char *e; - char *dev = "/dev/worm0"; - int c; - extern char *optarg; - extern int optind; - void pr(); - - while((c = getopt(argc, argv, "lbf:")) != -1) - switch(c) - { - case 'f': dev = optarg; break; - case 'l': lflag = 1; break; - case 'b': bflag = 1; break; - case '?': usage(); - } - dev = mapdev(dev); - if((s.fd = open(dev, 2)) < 0){ - perror(dev); - exit(1); - } - if(e = openinode(&s, DO_INODE|SPIN_DOWN)){ - fprint(2, "%s: %s\n", dev, e); - exit(1); - } - if(optind != argc-3) - usage(); - if(strcmp(s.vol_id, argv[optind])){ - fprint(2, "worm mv: vol_id mismatch: wanted %s, got %s\n", argv[optind], s.vol_id); - exit(1); - } - optind++; - if((i = inodeof(argv[optind])) == 0){ - Fprint(2, "%s not found\n", argv[optind]); - exit(1); - } - optind++; - if(strlen(argv[optind]) < 1){ - Fprint(2, "worm mv: destination name is null\n"); - exit(1); - } - for(c = 1; c <= NSIG; c++) - signal(c, SIG_IGN); - ininit(); - newi = *i; - i->block = -1; - inadd(&s, i); - newi.name.n = argv[optind]; - inadd(&s, &newi); - if(inwrite(&s)) - exit(1); - exit(0); -} - -usage() -{ - fprint(2, "Usage: worm mv [-fdevice] vol_id from to\n"); - exit(2); -} - -static Inode *inodes; -static long ip; -static long ninodes = 0; -static char *nameb; -static long np; -static long nnameb = 0; -static long nblocks; -#define IINC 1024 -#define NINC (64*IINC) - -ininit() -{ - if(nnameb == 0){ - nameb = malloc((unsigned)(nnameb = NINC)); - if(nameb == 0){ - fprint(2, "wmv: malloc fail, %d bytes\n", nnameb); - exit(1); - } - } - np = 0; - if(ninodes == 0){ - inodes = (Inode *)malloc(sizeof(Inode)*(unsigned)(ninodes = IINC)); - if(inodes == 0){ - fprint(2, "wmv: malloc fail, %d inodes %d bytes\n", ninodes, ninodes*sizeof(Inode)); - exit(1); - } - } - ip = 0; -} - -inadd(s, i) - Superblock *s; - register Inode *i; -{ - register long len; - - len = strlen(i->name.n)+1; - if(np+len > nnameb){ - while(np+len > nnameb) - nnameb += NINC; - nameb = realloc(nameb, (unsigned)nnameb); - if(nameb == 0){ - fprint(2, "wmv: realloc fail, %d bytes\n", nnameb); - exit(1); - } - } - strcpy(nameb+np, i->name.n); - i->name.o = np; - np += len; - if(ip == ninodes){ - ninodes += IINC; - inodes = (Inode *)realloc((char *)inodes, (unsigned)ninodes*sizeof(Inode)); - if(inodes == 0){ - fprint(2, "wmv: realloc fail, %d inodes %d bytes\n", ninodes, ninodes*sizeof(Inode)); - exit(1); - } - } - inodes[ip++] = *i; -} - -inwrite(s) - Superblock *s; -{ - char *e; - - if(e = lkwri(s, inodes, ip, nameb, np, 0L)){ - fprint(2, "%s\n", e); - return(1); - } - return(0); -} //GO.SYSIN DD wmv.c echo woffline.c 1>&2 sed 's/.//' >woffline.c <<'//GO.SYSIN DD woffline.c' -#include <libc.h> -#include "worm.h" -#include <sys/types.h> -#include <sys/udaioc.h> - -main(argc, argv) - char **argv; -{ - Superblock s; - char *vol_id = 0; - char buf[1024]; - char *dev = "/dev/worm0"; - int c; - extern char *optarg; - extern int optind; - - while((c = getopt(argc, argv, "f:")) != -1) - switch(c) - { - case 'f': dev = optarg; break; - case '?': usage(); - } - if(optind != argc) - usage(); - dev = mapdev(dev); - if((s.fd = open(dev, 2)) < 0){ - if(!vol_id) - perror(dev); - exit(2); - } - /* have to read to make ioctl work */ - lseek(s.fd, 1024L, 0); - read(s.fd, buf, sizeof buf); - if(ioctl(s.fd, UIOSPDW) < 0){ - perror("ioctl"); - exit(2); - } - exit(0); -} - -usage() -{ - print("Usage: worm offline [-fdevice]\n"); - exit(2); -} //GO.SYSIN DD woffline.c echo worm.h 1>&2 sed 's/.//' >worm.h <<'//GO.SYSIN DD worm.h' -#include <errno.h> - -#define SMAGIC 0x21746967 -#define DMAGIC 0x3A746967 - -typedef struct Superblock -{ - long magic; /* magic number for Superblock */ - unsigned short blocksize; /* physical size of blocks */ - short version; /* type of superblock */ - long nblocks; /* number of blocks on device */ - long zero; /* first logical data block */ - long nfree; /* number of free blocks */ - long ninodes; /* number of inodes */ - long ninochars; /* number of bytes of inode names */ - long binodes; /* start of inodes */ - long nextffree; /* next free file block */ - long nextsb; /* next superblock */ - short fd; /* fildes for device (in core) */ - char vol_id[128]; /* name the disk can be mounted as */ - char comment[128]; /* comments */ - long myblock; /* where this superblock is */ - long nF; /* bytes for .F (VBTREE) */ - long nT; /* bytes for .T (VBTREE) */ - long ctime; /* create time for this superblock */ -} Superblock; - -typedef struct Inode -{ - long magic; /* magic number for Dirent */ - long block; /* starting block of file */ - long nbytes; /* bytes in file */ - long ctime; /* creation time */ - union { - char *n; /* core - name */ - long o; /* disk - offset into chars block */ - } name; /* filename */ - long pad1; /* to 32 bytes */ - short mode; /* a la stat */ - short uid; /* owner */ - short gid; /* owner */ - short pad2; /* to 32 bytes */ -} Inode; -#define IPERB (s->blocksize/sizeof(Inode)) - -extern char *openinode(), *lkwri(), *lkwsb(); -extern char *mapdev(); -extern Inode *(*inodefn)(); -extern void (*traversefn)(); -extern long numinodes; -extern long numnamechars; -extern char *timenow(); - -#define inodeof(s) (*inodefn)(s) -#define inodetraverse(fn) (*traversefn)(fn) - -#define VLINK 1 /* linked list version */ -#define VBTREE 2 /* cbt */ - -#define NBLKS(s, x) (long)(((s)->blocksize-1+(x))/(s)->blocksize) - -/* - flags for openinode -*/ -#define DO_INODE 1 -#define SPIN_DOWN 2 - -#define BIGBLOCK (60*1024L) /* max read/write */ - -/* - in.c declarations -*/ - -extern int bad; -extern long nbytes; -extern long blkdone; -extern long nfiles; -extern char *argout; //GO.SYSIN DD worm.h echo wpoke.c 1>&2 sed 's/.//' >wpoke.c <<'//GO.SYSIN DD wpoke.c' -#include <libc.h> -#include "worm.h" - -main(argc, argv) - char **argv; -{ - Superblock s; - char *e, *vol_id = 0; - char *dev = "/dev/worm0"; - int c; - long nf = 0; - int vflag = 0; - Superblock ss; - extern char *optarg; - extern int optind; - extern long atol(); - - while((c = getopt(argc, argv, "vF:f:")) != -1) - switch(c) - { - case 'f': dev = optarg; break; - case 'F': nf = atol(optarg); break; - case 'v': vflag = 1; break; - case '?': usage(); - } - if(optind < argc){ - vol_id = argv[optind++]; - if(optind != argc) - usage(); - } - dev = mapdev(dev); - if((s.fd = open(dev, 0)) < 0){ - perror(dev); - exit(2); - } - if(read(s.fd, &ss, sizeof ss) != sizeof ss){ - if(errno == ENXIO) - print("unwritten block zero\n"); - else - perror("block zero"); - } else { - if(ss.magic == SMAGIC){ - print("appears to be a good superblock at zero\n"); - exit(0); - } else if(ss.magic == 0){ - print("appears to be a zero'ed block at zero.\n"); - } else - print("ignoring bogus block at zero\n"); - } - vlink(s.fd, 1); - exit(0); -} - -usage() -{ - print("Usage: worm poke [-v] [-fdevice] [-Fnfree] [vol_id]\n"); - exit(2); -} - -vlink(fd, blk) -{ - Superblock s; - int i, n; - - while(blk < 1650000){ -loop: -print("reading sb at %d\n", blk); - bigseek(fd, blk, 1024, 0); - if(read(fd, &s, sizeof s) == sizeof s){ - if(s.magic == SMAGIC){ - blk = s.nextsb; - continue; - } - print("apparent garbage at supposed superblock@%ld\n", blk); - } else { - print("bad read at blk %ld, errno=%d\n", blk, errno); - lseek(fd, 1024, 1); - blk++; - } - for(i = 0; i < 50; i++){ - n = read(fd, &s, sizeof s); - if(n < 0){ - lseek(fd, 1024, 1); - continue; - } - if((n == sizeof s) && (s.magic == SMAGIC)){ - blk += i; - print("after error, skipped %d blocks to apparent superblock at %ld\n", i, blk); - goto loop; - } - } - print("after error, no superblock after %d tries\n", i); - blk += i; - } -} //GO.SYSIN DD wpoke.c echo wread.c 1>&2 sed 's/.//' >wread.c <<'//GO.SYSIN DD wread.c' -#include <libc.h> -#include <fio.h> -#include "sym.h" -#include "worm.h" -#include <sys/types.h> -#include <sys/stat.h> - -char *prefix = ""; -int dflag = 0; -int quiet = 0; -int mflag = 0; - -main(argc, argv) - char **argv; -{ - Superblock s; - char *e; - int c; - char *dev = "/dev/worm0"; - extern char *optarg; - extern int optind; - - while((c = getopt(argc, argv, "dmf:p:s")) != -1) - switch(c) - { - case 'd': dflag = 1; break; - case 'f': dev = optarg; break; - case 'm': mflag = 1; break; - case 'p': prefix = optarg; break; - case 's': quiet = 1; break; - case '?': usage(); - } - if(optind >= argc) - usage(); - dev = mapdev(dev); - if((s.fd = open(dev, 0)) < 0){ - perror(dev); - exit(1); - } - if(e = openinode(&s, DO_INODE|SPIN_DOWN)){ - fprint(2, "%s: %s\n", dev, e); - exit(1); - } - if(strcmp(s.vol_id, argv[optind])){ - fprint(2, "vol_id mismatch: wanted %s, got %s\n", argv[optind], s.vol_id); - exit(1); - } - optind++; - c = 0; - if(optind >= argc){ - while(e = Frdline(0)) - if(pr(&s, e)) - c = 1; - } else { - while(optind < argc) - if(pr(&s, argv[optind++])) - c = 1; - } - exit(c); -} - -usage() -{ - fprint(2, "Usage: worm read [-fdevice] [-pprefix] [-dm] vol_id [files ...]\n"); - exit(1); -} - -pr(s, name) - Superblock *s; - char *name; -{ - register Inode *i; - char b[63*1024L]; - register long len, n; - long nb; - int fd; - char buf[4096]; - - if((i = inodeof(name)) == 0){ - fprint(2, "%s not found\n", name); - return(1); - } - sprint(buf, "%s%s", prefix, name); - name = buf; - if((fd = create(name, i->mode, i->uid, i->gid, i->ctime)) < 0){ - if(dflag){ - createdirs(name); - fd = create(name, i->mode, i->uid, i->gid, i->ctime); - } - if(fd < 0){ - perror(name); - return(1); - } - } - if(fd == 0) /* a directory */ - return(0); - nb = sizeof b / s->blocksize; - Seek(s, i->block); - for(n = i->nbytes, len = nb*s->blocksize; n > 0;){ - if(len > n){ - len = n; - nb = (len+s->blocksize-1)/s->blocksize; - } - if(Read(s, b, nb)){ - fprint(2, "while writing %s: ", name); - perror("read"); - exit(1); - } - if(write(fd, b, (int)len) != len){ - fprint(2, "while writing %s: ", name); - perror("write"); - exit(1); - } - n -= len; - } - close(fd); - if(mflag){ - time_t tp[2]; - - tp[0] = tp[1] = i->ctime; - utime(name, tp); - } - return(0); -} - -createdirs(s) - char *s; -{ - char *ls, *ss; - - for(ls = s; *ls == '/'; ls++) - ; - for(; *ls && (ss = strchr(ls, '/')); ls = ss+1){ - *ss = 0; - if(access(s, 0) < 0){ - if(mkdir(s, 0777) < 0){ - perror(s); - return; - } else if(!quiet) - fprint(2, "created %s\n", s); - } - *ss = '/'; - } -} - -create(name, mode, uid, gid, t) - char *name; - time_t t; -{ - time_t tp[2]; - - tp[0] = tp[1] = t; - if((mode&S_IFMT) == S_IFDIR){ - if(access(name, 0) >= 0){ - if(chmod(name, mode) < 0){ - perror(name); - return(-1); - } - } else { - if(mkdir(name, mode) < 0){ - perror(name); - return(-1); - } - } - chown(name, uid, gid); - utime(name, tp); - return(0); - } else { - int fd; - - if((fd = creat(name, mode)) >= 0){ - chown(name, uid, gid); - utime(name, tp); - } - return(fd); - } -} //GO.SYSIN DD wread.c echo wreset.c 1>&2 sed 's/.//' >wreset.c <<'//GO.SYSIN DD wreset.c' -#include <libc.h> -#include "worm.h" -#include <sys/types.h> -#include <sys/udaioc.h> - -main(argc, argv) - char **argv; -{ - Superblock s; - char *e, *vol_id = 0; - char buf[1024]; - char *dev = "/dev/worm0"; - int c; - extern char *optarg; - extern int optind; - - while((c = getopt(argc, argv, "f:")) != -1) - switch(c) - { - case 'f': dev = optarg; break; - case '?': usage(); - } - if(optind != argc) - usage(); - dev = mapdev(dev); - if((s.fd = open(dev, 2)) < 0){ - if(!vol_id) - perror(dev); - exit(2); - } - /* - normally, you have to read to bring the drive online. - however, when you are likely to call reset, the drive - is online and blocked so skip the read - */ - /*lseek(s.fd, 1024L, 0); - read(s.fd, buf, sizeof buf);/**/ - if(ioctl(s.fd, UIORST) < 0) - perror("reset ioctl"); - exit(0); -} - -usage() -{ - print("Usage: worm reset [-fdevice]\n"); - exit(2); -} //GO.SYSIN DD wreset.c echo wrm.c 1>&2 sed 's/.//' >wrm.c <<'//GO.SYSIN DD wrm.c' -#include <libc.h> -#include <fio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <signal.h> -#include "worm.h" - -static int bad = 0; -static long nbytes; -static long nfiles; -char *argout; - -main(argc, argv) - char **argv; -{ - Superblock s; - char *e; - char buf[4096]; - int n; - int c; - char *dev = "/dev/worm0"; - extern char *optarg; - extern int optind; - - argout = argv[0]; - while((c = getopt(argc, argv, "f:")) != -1) - switch(c) - { - case 'f': dev = optarg; break; - case '?': usage(); - } - - if(optind >= argc) - usage(); - dev = mapdev(dev); - if((s.fd = open(dev, 2)) < 0){ - perror(*argv); - exit(1); - } - if(e = openinode(&s, DO_INODE|SPIN_DOWN)){ - fprint(2, "%s: %s\n", *argv, e); - exit(1); - } - if(strcmp(s.vol_id, argv[optind])){ - fprint(2, "vol_id mismatch: wanted %s, got %s\n", argv[optind], s.vol_id); - exit(1); - } - if(s.nfree == 0){ - fprint(2, "%s: can't write any more!\n", dev); - exit(1); - } - if(s.version != VLINK){ - fprint(2, "%s: can't write on a b-tree disk\n", s.vol_id); - exit(1); - } - for(n = 1; n <= NSIG; n++) - signal(n, SIG_IGN); - ininit(); - if(++optind < argc) - while(optind < argc) - proc(&s, argv[optind++]); - else - while(e = Frdline(0)) - proc(&s, e); - if(bad) - exit(1); - inwrite(&s); - if(bad) - exit(1); - exit(0); -} - -usage() -{ - fprint(2, "Usage: worm rm [-fdevice] vol_id [files]\n"); - exit(1); -} - -proc(s, file) - Superblock *s; - char *file; -{ - Inode i; - - if(inodeof(file) == 0){ - fprint(2, "%s: not on worm\n", file); - return; - } - i.magic = DMAGIC; - i.block = -1; - i.name.n = file; - if(inadd(s, &i)) - bad = 1; -} - -static Inode *inodes; -static long ip; -static long ninodes = 0; -static char *nameb; -static long np; -static long nnameb = 0; -static long nblocks; -#define IINC 1024 -#define NINC (64*IINC) - -ininit() -{ - if(nnameb == 0){ - nameb = malloc((unsigned)(nnameb = NINC)); - if(nameb == 0){ - fprint(2, "wrm: malloc fail, %d bytes\n", nnameb); - exit(1); - } - } - np = 0; - if(ninodes == 0){ - inodes = (Inode *)malloc(sizeof(Inode)*(unsigned)(ninodes = IINC)); - if(inodes == 0){ - fprint(2, "wrm: malloc fail, %d inodes %d bytes\n", ninodes, ninodes*sizeof(Inode)); - exit(1); - } - } - ip = 0; -} - -inadd(s, i) - Superblock *s; - register Inode *i; -{ - register long len; - - len = strlen(i->name.n)+1; - if(np+len > nnameb){ - while(np+len > nnameb) - nnameb += NINC; - nameb = realloc(nameb, (unsigned)nnameb); - if(nameb == 0){ - fprint(2, "wrm: realloc fail, %d bytes\n", nnameb); - exit(1); - } - } - strcpy(nameb+np, i->name.n); - i->name.o = np; - np += len; - if(ip == ninodes){ - ninodes += IINC; - inodes = (Inode *)realloc((char *)inodes, (unsigned)ninodes*sizeof(Inode)); - if(inodes == 0){ - fprint(2, "wrm: realloc fail, %d inodes %d bytes\n", ninodes, ninodes*sizeof(Inode)); - exit(1); - } - } - inodes[ip++] = *i; - return(0); -} - -inwrite(s) - Superblock *s; -{ - char *e; - - if(e = lkwri(s, inodes, ip, nameb, np, 0L)){ - fprint(2, "%s\n", e); - bad = 1; - return; - } -} //GO.SYSIN DD wrm.c echo wstat.c 1>&2 sed 's/.//' >wstat.c <<'//GO.SYSIN DD wstat.c' -#include <libc.h> -#include "worm.h" - -main(argc, argv) - char **argv; -{ - Superblock s; - char *e, *vol_id = 0; - char *dev = "/dev/worm0"; - int c; - long nf = 0; - int vflag = 0; - extern char *optarg; - extern int optind; - extern long atol(); - - while((c = getopt(argc, argv, "vF:f:")) != -1) - switch(c) - { - case 'f': dev = optarg; break; - case 'F': nf = atol(optarg); break; - case 'v': vflag = 1; break; - case '?': usage(); - } - if(optind < argc){ - vol_id = argv[optind++]; - if(optind != argc) - usage(); - } - dev = mapdev(dev); - if((s.fd = open(dev, 0)) < 0){ - if(!vol_id && !nf) - perror(dev); - exit(2); - } - if(e = openinode(&s, SPIN_DOWN)){ - if(!vol_id && !nf) - fprint(2, "%s: %s\n", dev, e); - exit(2); - } - if(nf){ - if(vol_id) - if(strcmp(vol_id, s.vol_id) != 0) - exit(1); - exit(s.nfree >= nf? 0:3); - } - if(vol_id) - exit(strcmp(vol_id, s.vol_id) != 0); - if(vflag){ - Fprint(1, "%s: %s, %s\t%ldx%uhd blocks, %ld (=%.1fMB) free, zero=%ld this_sb@%ld next_sb@%ld\n", - s.vol_id, s.comment, ctime(&s.ctime), s.nblocks, s.blocksize, - s.nfree, s.nfree*(double)s.blocksize*1e-6, s.zero, s.myblock, s.nextsb); - } else - Fprint(1, "%s: %.0f%% used (%.1fMB free)\n", s.vol_id, - s.nextffree*100.0/s.nblocks, s.nfree*(double)s.blocksize*1e-6); - exit(0); -} - -usage() -{ - print("Usage: worm stat [-v] [-fdevice] [-Fnfree] [vol_id]\n"); - exit(2); -} //GO.SYSIN DD wstat.c echo wtmpdir.c 1>&2 sed 's/.//' >wtmpdir.c <<'//GO.SYSIN DD wtmpdir.c' -#include <libc.h> -#include "worm.h" -#include "sym.h" -#include <sys/types.h> -#include <sys/stat.h> -#include <pwd.h> -#include <grp.h> - -Inode *inodebase, *inext; -char *namebase, *cnext; - -main(argc, argv) - char **argv; -{ - Superblock s; - char *e; - char *dev = "/dev/worm0"; - register c, j; - register Inode *from, *to; - extern char *optarg; - extern int optind; - char *vlk(); - int cmp(); - int fd; - int verbose = 0; - char buf[512]; - long ni, nc; - - while((c = getopt(argc, argv, "vf:")) != -1) - switch(c) - { - case 'v': verbose = 1; break; - case 'f': dev = optarg; break; - case '?': usage(); - } - dev = mapdev(dev); - if((s.fd = open(dev, 0)) < 0){ - perror(dev); - exit(1); - } - if(e = openinode(&s, SPIN_DOWN)){ - fprint(2, "%s: %s\n", dev, e); - exit(1); - } - if(s.version != VLINK){ - fprint(2, "%s: not a vlink disk, no action taken.\n", s.vol_id); - exit(1); - } - if(optind != argc-1) - usage(); - if(strcmp(argv[optind], s.vol_id)){ - fprint(2, "wanted volid '%s'; got '%s'\n", argv[optind], s.vol_id); - exit(1); - } - if(verbose) - print("%d inodes\n", numinodes); - if((inodebase = (Inode *)malloc(s.blocksize+(int)numinodes*sizeof(Inode))) == 0){ - fprint(2, "malloc of %ld inodes failed\n", numinodes); - exit(2); - } - if((namebase = malloc(s.blocksize+(int)numnamechars+(int)numinodes)) == 0){ - fprint(2, "malloc of %ld chars failed\n", numnamechars); - exit(2); - } - inext = inodebase; - cnext = namebase; - s.ninodes = 0; - s.nextsb = 2; - if(e = vlk(&s)){ - fprint(2, "%s: %s\n", dev, e); - exit(1); - } - j = inext-inodebase; - if(verbose) - print("%d in base\n", j); - qsort((char *)inodebase, j, sizeof(*inodebase), cmp); - for(to = inodebase, from = inodebase+1; from < inext; from++) - if(strcmp(from->name.o+namebase, from[-1].name.o+namebase)) - *to++ = from[-1]; - else { - while((++from < inext) && (strcmp(from->name.o+namebase, from[-1].name.o+namebase) == 0)) - ; - } - if(from == inext) - *to++ = from[-1]; - inext = to; - j = inext-inodebase; - sprint(buf, "/usr/worm/tmp/%s", s.vol_id); - if((fd = creat(buf, 0666)) < 0){ - perror(buf); - exit(1); - } - ni = j; - nc = cnext-namebase; - write(fd, (char *)&s.ctime, 4); - write(fd, (char *)&ni, 4); - write(fd, (char *)inodebase, (int)ni*sizeof(Inode)); - write(fd, (char *)&nc, 4); - write(fd, namebase, (int)nc); - exit(0); -} - -usage() -{ - fprint(2, "Usage: worm tmpdir [-fdevice] vol_id\n"); - exit(2); -} - -cmp(a, b) - Inode *a, *b; -{ - return(strcmp(namebase+a->name.o, namebase+b->name.o)); -} - -char * -vlk(s) - register Superblock *s; -{ - register Inode *i; - short fd = s->fd; - register long j; - long blk = -1; /* shouldn't be accessed first time through */ - char *b; - long nb; - Inode *iend; - static char buf[64]; - - if((b = malloc(s->blocksize)) == 0){ - sprint(buf, "couldn't malloc buffer (%d bytes)", s->blocksize); - return(buf); - } - for(;;){ - if(s->magic != SMAGIC){ - fprint(2, "bad Superblock at %ld\n", blk); - exit(1); - } - if(s->ninodes){ - nb = (s->ninodes+IPERB-1)/IPERB; - Seek(s, s->binodes); - if(Read(s, (char *)inext, nb)) - goto skip; - j = cnext-namebase; - for(i = inext, iend = i+s->ninodes; i < iend; i++) - i->name.o += j; - inext += s->ninodes; - nb = (s->ninochars+s->blocksize-1)/s->blocksize; - if(Read(s, cnext, nb)) - goto skip; - cnext += (s->ninochars+1)&~1; - } - skip: - blk = s->nextsb; - Seek(s, blk); - if(Read(s, b, 1L)) - break; - *s = *((Superblock *)b); - s->fd = fd; - if(s->myblock == 0) - s->myblock = blk; - } - free(b); - return((char *)0); -} //GO.SYSIN DD wtmpdir.c echo wwrite.c 1>&2 sed 's/.//' >wwrite.c <<'//GO.SYSIN DD wwrite.c' -#include <libc.h> -#include <fio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <signal.h> -#include "worm.h" - -main(argc, argv) - char **argv; -{ - Superblock s; - char *e; - char buf[4096]; - int n; - int c; - char *dev = "/dev/worm0"; - extern char *optarg; - extern int optind; - - argout = argv[0]; - while((c = getopt(argc, argv, "f:")) != -1) - switch(c) - { - case 'f': dev = optarg; break; - case '?': usage(); - } - - if(optind >= argc) - usage(); - dev = mapdev(dev); - if((s.fd = open(dev, 2)) < 0){ - perror(*argv); - exit(1); - } - if(e = openinode(&s, SPIN_DOWN)){ - fprint(2, "%s: %s\n", *argv, e); - exit(1); - } - if(strcmp(s.vol_id, argv[optind])){ - fprint(2, "vol_id mismatch: wanted %s, got %s\n", argv[optind], s.vol_id); - exit(1); - } - if(s.nfree == 0){ - fprint(2, "%s: can't write any more!\n", dev); - exit(1); - } - if(s.version != VLINK){ - fprint(2, "%s: can't write on a b-tree disk\n", s.vol_id); - exit(1); - } - for(n = 1; n <= NSIG; n++) - signal(n, SIG_IGN); - ininit(); - if(++optind < argc) - while(optind < argc) - proc(&s, argv[optind++]); - else - while(e = Frdline(0)) - proc(&s, e); - if(bad) - exit(1); - nfiles = nbytes = 0; - inwrite(&s, (void *)0); - if(bad) - exit(1); - fprint(1, "%d files, %.6fMb\n", nfiles, nbytes/1e6); - exit(0); -} - -usage() -{ - fprint(2, "Usage: worm write [-fdevice] vol_id [files]\n"); - exit(1); -} - -proc(s, file) - Superblock *s; - char *file; -{ - struct stat sbuf; - unsigned short mode; - Inode i; - - memset((char *)&i, 0, sizeof(i)); - if(stat(file, &sbuf) < 0){ - perror(file); - return; - } - mode = sbuf.st_mode&S_IFMT; - if((mode == S_IFREG) || (mode == S_IFDIR)){ - i.magic = DMAGIC; - i.block = 0; - i.nbytes = sbuf.st_size; - nbytes += i.nbytes; - i.ctime = sbuf.st_ctime; - i.name.n = file; - i.mode = sbuf.st_mode; - i.uid = sbuf.st_uid; - i.gid = sbuf.st_gid; - if(inadd(s, &i)) - bad = 1; - } else - fprint(2, "%s is not a file\n", file); -} - -writeout(s, i, blk) - Superblock *s; - Inode *i; - long *blk; -{ - char b[63*1024L]; - int fd; - long n, len, blen; - char *name; - - n = (i->nbytes+s->blocksize-1)/s->blocksize; - *blk += n; - blkdone += n; - blen = sizeof b/s->blocksize; - len = blen*s->blocksize; - nbytes += i->nbytes; - nfiles++; - name = i->name.n; - if((fd = open(name, 0)) < 0) - goto out; - for(n = i->nbytes; n > len; n -= len){ - if(read(fd, (char *)b, (int)len) != len){ - out: - perror(name); - bad = 1; - return; - } - if(Write(s, b, blen)){ -fprint(2, "nb=%d, n=%d len=%d blen=%d\n", i->nbytes, n, len, blen); - perror("data write"); - exit(1); - } - } - if(n){ - memset(b, 0, sizeof b); - if(read(fd, (char *)b, (int)n) != n) - goto out; - n += s->blocksize-1; - n /= s->blocksize; - if(Write(s, b, n)){ - perror("data write"); - exit(1); - } - } - close(fd); -} //GO.SYSIN DD wwrite.c