13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 33e12c5d1SDavid du Colombier #include <bio.h> 43e12c5d1SDavid du Colombier 53e12c5d1SDavid du Colombier #include "scsireq.h" 63e12c5d1SDavid du Colombier 73e12c5d1SDavid du Colombier #define MIN(a, b) ((a) < (b) ? (a): (b)) 83e12c5d1SDavid du Colombier 9*219b2ee8SDavid du Colombier int bus; 103e12c5d1SDavid du Colombier Biobuf bin, bout; 113e12c5d1SDavid du Colombier static char rwbuf[MaxIOsize]; 123e12c5d1SDavid du Colombier static int verbose = 1; 133e12c5d1SDavid du Colombier 143e12c5d1SDavid du Colombier typedef struct { 153e12c5d1SDavid du Colombier char *name; 163e12c5d1SDavid du Colombier long (*f)(ScsiReq *, int, char *[]); 173e12c5d1SDavid du Colombier int open; 183e12c5d1SDavid du Colombier char *help; 193e12c5d1SDavid du Colombier } ScsiCmd; 203e12c5d1SDavid du Colombier static ScsiCmd scsicmd[]; 213e12c5d1SDavid du Colombier 223e12c5d1SDavid du Colombier static long 233e12c5d1SDavid du Colombier cmdready(ScsiReq *rp, int argc, char *argv[]) 243e12c5d1SDavid du Colombier { 253e12c5d1SDavid du Colombier USED(argc, argv); 263e12c5d1SDavid du Colombier return SRready(rp); 273e12c5d1SDavid du Colombier } 283e12c5d1SDavid du Colombier 293e12c5d1SDavid du Colombier static long 303e12c5d1SDavid du Colombier cmdrewind(ScsiReq *rp, int argc, char *argv[]) 313e12c5d1SDavid du Colombier { 323e12c5d1SDavid du Colombier USED(argc, argv); 333e12c5d1SDavid du Colombier return SRrewind(rp); 343e12c5d1SDavid du Colombier } 353e12c5d1SDavid du Colombier 363e12c5d1SDavid du Colombier static long 373e12c5d1SDavid du Colombier cmdreqsense(ScsiReq *rp, int argc, char *argv[]) 383e12c5d1SDavid du Colombier { 393e12c5d1SDavid du Colombier long nbytes; 403e12c5d1SDavid du Colombier 413e12c5d1SDavid du Colombier USED(argc, argv); 423e12c5d1SDavid du Colombier if((nbytes = SRreqsense(rp)) != -1) 433e12c5d1SDavid du Colombier makesense(rp); 443e12c5d1SDavid du Colombier return nbytes; 453e12c5d1SDavid du Colombier } 463e12c5d1SDavid du Colombier 473e12c5d1SDavid du Colombier static long 483e12c5d1SDavid du Colombier cmdformat(ScsiReq *rp, int argc, char *argv[]) 493e12c5d1SDavid du Colombier { 503e12c5d1SDavid du Colombier USED(argc, argv); 513e12c5d1SDavid du Colombier return SRformat(rp); 523e12c5d1SDavid du Colombier } 533e12c5d1SDavid du Colombier 543e12c5d1SDavid du Colombier static long 553e12c5d1SDavid du Colombier cmdrblimits(ScsiReq *rp, int argc, char *argv[]) 563e12c5d1SDavid du Colombier { 573e12c5d1SDavid du Colombier uchar l[6]; 583e12c5d1SDavid du Colombier long n; 593e12c5d1SDavid du Colombier 603e12c5d1SDavid du Colombier USED(argc, argv); 613e12c5d1SDavid du Colombier if((n = SRrblimits(rp, l)) == -1) 623e12c5d1SDavid du Colombier return -1; 633e12c5d1SDavid du Colombier Bprint(&bout, " %2.2ux %2.2ux %2.2ux %2.2ux %2.2ux %2.2ux\n", 643e12c5d1SDavid du Colombier l[0], l[1], l[2], l[3], l[4], l[5]); 653e12c5d1SDavid du Colombier return n; 663e12c5d1SDavid du Colombier } 673e12c5d1SDavid du Colombier 683e12c5d1SDavid du Colombier static int 693e12c5d1SDavid du Colombier mkfile(char *file, int omode, int *pid) 703e12c5d1SDavid du Colombier { 713e12c5d1SDavid du Colombier int fd[2]; 723e12c5d1SDavid du Colombier 733e12c5d1SDavid du Colombier if(*file != '|'){ 743e12c5d1SDavid du Colombier *pid = -1; 753e12c5d1SDavid du Colombier if(omode == OWRITE) 763e12c5d1SDavid du Colombier return create(file, OWRITE, 0666); 773e12c5d1SDavid du Colombier else if(omode == OREAD) 783e12c5d1SDavid du Colombier return open(file, OREAD); 793e12c5d1SDavid du Colombier return -1; 803e12c5d1SDavid du Colombier } 813e12c5d1SDavid du Colombier 823e12c5d1SDavid du Colombier file++; 833e12c5d1SDavid du Colombier if(*file == 0 || pipe(fd) == -1) 843e12c5d1SDavid du Colombier return -1; 853e12c5d1SDavid du Colombier if((*pid = fork()) == -1){ 863e12c5d1SDavid du Colombier close(fd[0]); 873e12c5d1SDavid du Colombier return -1; 883e12c5d1SDavid du Colombier } 893e12c5d1SDavid du Colombier if(*pid == 0){ 903e12c5d1SDavid du Colombier switch(omode){ 913e12c5d1SDavid du Colombier 923e12c5d1SDavid du Colombier case OREAD: 933e12c5d1SDavid du Colombier dup(fd[0], 1); 943e12c5d1SDavid du Colombier break; 953e12c5d1SDavid du Colombier 963e12c5d1SDavid du Colombier case OWRITE: 973e12c5d1SDavid du Colombier dup(fd[0], 0); 983e12c5d1SDavid du Colombier break; 993e12c5d1SDavid du Colombier } 1003e12c5d1SDavid du Colombier close(fd[0]); 1013e12c5d1SDavid du Colombier close(fd[1]); 1023e12c5d1SDavid du Colombier execl("/bin/rc", "rc", "-c", file, 0); 1033e12c5d1SDavid du Colombier exits("exec"); 1043e12c5d1SDavid du Colombier } 1053e12c5d1SDavid du Colombier close(fd[0]); 1063e12c5d1SDavid du Colombier return fd[1]; 1073e12c5d1SDavid du Colombier } 1083e12c5d1SDavid du Colombier 1093e12c5d1SDavid du Colombier int 1103e12c5d1SDavid du Colombier waitfor(int pid) 1113e12c5d1SDavid du Colombier { 1123e12c5d1SDavid du Colombier int rpid; 1133e12c5d1SDavid du Colombier Waitmsg w; 1143e12c5d1SDavid du Colombier 1153e12c5d1SDavid du Colombier while((rpid = wait(&w)) != pid && rpid != -1) 1163e12c5d1SDavid du Colombier ; 1173e12c5d1SDavid du Colombier return w.msg[0]; 1183e12c5d1SDavid du Colombier } 1193e12c5d1SDavid du Colombier 1203e12c5d1SDavid du Colombier static long 1213e12c5d1SDavid du Colombier cmdread(ScsiReq *rp, int argc, char *argv[]) 1223e12c5d1SDavid du Colombier { 1233e12c5d1SDavid du Colombier long n, nbytes, total, iosize; 1243e12c5d1SDavid du Colombier int fd, pid; 1253e12c5d1SDavid du Colombier char *p; 1263e12c5d1SDavid du Colombier 1273e12c5d1SDavid du Colombier iosize = MaxIOsize; 1283e12c5d1SDavid du Colombier nbytes = 0x7FFFFFFF & ~iosize; 1293e12c5d1SDavid du Colombier switch(argc){ 1303e12c5d1SDavid du Colombier 1313e12c5d1SDavid du Colombier default: 1323e12c5d1SDavid du Colombier rp->status = Status_BADARG; 1333e12c5d1SDavid du Colombier return -1; 1343e12c5d1SDavid du Colombier 1353e12c5d1SDavid du Colombier case 2: 1363e12c5d1SDavid du Colombier if((nbytes = strtol(argv[1], &p, 0)) == 0 && p == argv[1]){ 1373e12c5d1SDavid du Colombier rp->status = Status_BADARG; 1383e12c5d1SDavid du Colombier return -1; 1393e12c5d1SDavid du Colombier } 1403e12c5d1SDavid du Colombier /*FALLTHROUGH*/ 1413e12c5d1SDavid du Colombier 1423e12c5d1SDavid du Colombier case 1: 1433e12c5d1SDavid du Colombier if((fd = mkfile(argv[0], OWRITE, &pid)) == -1){ 1443e12c5d1SDavid du Colombier rp->status = Status_BADARG; 1453e12c5d1SDavid du Colombier return -1; 1463e12c5d1SDavid du Colombier } 1473e12c5d1SDavid du Colombier break; 1483e12c5d1SDavid du Colombier } 149*219b2ee8SDavid du Colombier print("bsize=%d\n", rp->lbsize); 1503e12c5d1SDavid du Colombier total = 0; 1513e12c5d1SDavid du Colombier while(nbytes){ 1523e12c5d1SDavid du Colombier n = MIN(nbytes, iosize); 1533e12c5d1SDavid du Colombier if((n = SRread(rp, rwbuf, n)) == -1){ 1543e12c5d1SDavid du Colombier if(total == 0) 1553e12c5d1SDavid du Colombier total = -1; 1563e12c5d1SDavid du Colombier break; 1573e12c5d1SDavid du Colombier } 1583e12c5d1SDavid du Colombier if(write(fd, rwbuf, n) != n){ 1593e12c5d1SDavid du Colombier if(total == 0) 1603e12c5d1SDavid du Colombier total = -1; 1613e12c5d1SDavid du Colombier if(rp->status == Status_OK) 1623e12c5d1SDavid du Colombier rp->status = Status_SW; 1633e12c5d1SDavid du Colombier break; 1643e12c5d1SDavid du Colombier } 1653e12c5d1SDavid du Colombier nbytes -= n; 1663e12c5d1SDavid du Colombier total += n; 1673e12c5d1SDavid du Colombier } 1683e12c5d1SDavid du Colombier close(fd); 1693e12c5d1SDavid du Colombier if(pid >= 0 && waitfor(pid)){ 1703e12c5d1SDavid du Colombier rp->status = Status_SW; 1713e12c5d1SDavid du Colombier return -1; 1723e12c5d1SDavid du Colombier } 1733e12c5d1SDavid du Colombier return total; 1743e12c5d1SDavid du Colombier } 1753e12c5d1SDavid du Colombier 1763e12c5d1SDavid du Colombier static long 1773e12c5d1SDavid du Colombier cmdwrite(ScsiReq *rp, int argc, char *argv[]) 1783e12c5d1SDavid du Colombier { 1793e12c5d1SDavid du Colombier long n, nbytes, total; 1803e12c5d1SDavid du Colombier int fd, pid; 1813e12c5d1SDavid du Colombier char *p; 1823e12c5d1SDavid du Colombier 1833e12c5d1SDavid du Colombier nbytes = 0x7FFFFFFF & ~MaxIOsize; 1843e12c5d1SDavid du Colombier switch(argc){ 1853e12c5d1SDavid du Colombier 1863e12c5d1SDavid du Colombier default: 1873e12c5d1SDavid du Colombier rp->status = Status_BADARG; 1883e12c5d1SDavid du Colombier return -1; 1893e12c5d1SDavid du Colombier 1903e12c5d1SDavid du Colombier case 2: 1913e12c5d1SDavid du Colombier if((nbytes = strtol(argv[1], &p, 0)) == 0 && p == argv[1]){ 1923e12c5d1SDavid du Colombier rp->status = Status_BADARG; 1933e12c5d1SDavid du Colombier return -1; 1943e12c5d1SDavid du Colombier } 1953e12c5d1SDavid du Colombier /*FALLTHROUGH*/ 1963e12c5d1SDavid du Colombier 1973e12c5d1SDavid du Colombier case 1: 1983e12c5d1SDavid du Colombier if((fd = mkfile(argv[0], OREAD, &pid)) == -1){ 1993e12c5d1SDavid du Colombier rp->status = Status_BADARG; 2003e12c5d1SDavid du Colombier return -1; 2013e12c5d1SDavid du Colombier } 2023e12c5d1SDavid du Colombier break; 2033e12c5d1SDavid du Colombier } 2043e12c5d1SDavid du Colombier total = 0; 2053e12c5d1SDavid du Colombier while(nbytes){ 2063e12c5d1SDavid du Colombier n = MIN(nbytes, MaxIOsize); 2073e12c5d1SDavid du Colombier if((n = read(fd, rwbuf, n)) == -1){ 2083e12c5d1SDavid du Colombier if(total == 0) 2093e12c5d1SDavid du Colombier total = -1; 2103e12c5d1SDavid du Colombier break; 2113e12c5d1SDavid du Colombier } 2123e12c5d1SDavid du Colombier if(SRwrite(rp, rwbuf, n) != n){ 2133e12c5d1SDavid du Colombier if(total == 0) 2143e12c5d1SDavid du Colombier total = -1; 2153e12c5d1SDavid du Colombier if(rp->status == Status_OK) 2163e12c5d1SDavid du Colombier rp->status = Status_SW; 2173e12c5d1SDavid du Colombier break; 2183e12c5d1SDavid du Colombier } 2193e12c5d1SDavid du Colombier nbytes -= n; 2203e12c5d1SDavid du Colombier total += n; 2213e12c5d1SDavid du Colombier } 2223e12c5d1SDavid du Colombier close(fd); 2233e12c5d1SDavid du Colombier if(pid >= 0 && waitfor(pid)){ 2243e12c5d1SDavid du Colombier rp->status = Status_SW; 2253e12c5d1SDavid du Colombier return -1; 2263e12c5d1SDavid du Colombier } 2273e12c5d1SDavid du Colombier return total; 2283e12c5d1SDavid du Colombier } 2293e12c5d1SDavid du Colombier 2303e12c5d1SDavid du Colombier static long 2313e12c5d1SDavid du Colombier cmdseek(ScsiReq *rp, int argc, char *argv[]) 2323e12c5d1SDavid du Colombier { 2333e12c5d1SDavid du Colombier char *p; 2343e12c5d1SDavid du Colombier long offset; 2353e12c5d1SDavid du Colombier int type; 2363e12c5d1SDavid du Colombier 2373e12c5d1SDavid du Colombier type = 0; 2383e12c5d1SDavid du Colombier switch(argc){ 2393e12c5d1SDavid du Colombier 2403e12c5d1SDavid du Colombier default: 2413e12c5d1SDavid du Colombier rp->status = Status_BADARG; 2423e12c5d1SDavid du Colombier return -1; 2433e12c5d1SDavid du Colombier 2443e12c5d1SDavid du Colombier case 2: 2453e12c5d1SDavid du Colombier if((type = strtol(argv[1], &p, 0)) == 0 && p == argv[1]){ 2463e12c5d1SDavid du Colombier rp->status = Status_BADARG; 2473e12c5d1SDavid du Colombier return -1; 2483e12c5d1SDavid du Colombier } 2493e12c5d1SDavid du Colombier /*FALLTHROUGH*/ 2503e12c5d1SDavid du Colombier 2513e12c5d1SDavid du Colombier case 1: 2523e12c5d1SDavid du Colombier if((offset = strtol(argv[0], &p, 0)) == 0 && p == argv[0]){ 2533e12c5d1SDavid du Colombier rp->status = Status_BADARG; 2543e12c5d1SDavid du Colombier return -1; 2553e12c5d1SDavid du Colombier } 2563e12c5d1SDavid du Colombier break; 2573e12c5d1SDavid du Colombier } 2583e12c5d1SDavid du Colombier return SRseek(rp, offset, type); 2593e12c5d1SDavid du Colombier } 2603e12c5d1SDavid du Colombier 2613e12c5d1SDavid du Colombier static long 2623e12c5d1SDavid du Colombier cmdfilemark(ScsiReq *rp, int argc, char *argv[]) 2633e12c5d1SDavid du Colombier { 2643e12c5d1SDavid du Colombier char *p; 2653e12c5d1SDavid du Colombier ulong howmany; 2663e12c5d1SDavid du Colombier 2673e12c5d1SDavid du Colombier howmany = 1; 2683e12c5d1SDavid du Colombier if(argc && (howmany = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){ 2693e12c5d1SDavid du Colombier rp->status = Status_BADARG; 2703e12c5d1SDavid du Colombier return -1; 2713e12c5d1SDavid du Colombier } 2723e12c5d1SDavid du Colombier return SRfilemark(rp, howmany); 2733e12c5d1SDavid du Colombier } 2743e12c5d1SDavid du Colombier 2753e12c5d1SDavid du Colombier static long 2763e12c5d1SDavid du Colombier cmdspace(ScsiReq *rp, int argc, char *argv[]) 2773e12c5d1SDavid du Colombier { 2783e12c5d1SDavid du Colombier uchar code; 2793e12c5d1SDavid du Colombier long howmany; 2803e12c5d1SDavid du Colombier char option, *p; 2813e12c5d1SDavid du Colombier 2823e12c5d1SDavid du Colombier code = 0x00; 2833e12c5d1SDavid du Colombier howmany = 1; 2843e12c5d1SDavid du Colombier while(argc && (*argv)[0] == '-'){ 2853e12c5d1SDavid du Colombier while(option = *++argv[0]){ 2863e12c5d1SDavid du Colombier switch(option){ 2873e12c5d1SDavid du Colombier 2883e12c5d1SDavid du Colombier case '-': 2893e12c5d1SDavid du Colombier break; 2903e12c5d1SDavid du Colombier 2913e12c5d1SDavid du Colombier case 'b': 2923e12c5d1SDavid du Colombier code = 0x00; 2933e12c5d1SDavid du Colombier break; 2943e12c5d1SDavid du Colombier 2953e12c5d1SDavid du Colombier case 'f': 2963e12c5d1SDavid du Colombier code = 0x01; 2973e12c5d1SDavid du Colombier break; 2983e12c5d1SDavid du Colombier 2993e12c5d1SDavid du Colombier default: 3003e12c5d1SDavid du Colombier rp->status = Status_BADARG; 3013e12c5d1SDavid du Colombier return -1; 3023e12c5d1SDavid du Colombier } 3033e12c5d1SDavid du Colombier break; 3043e12c5d1SDavid du Colombier } 3053e12c5d1SDavid du Colombier argc--; argv++; 3063e12c5d1SDavid du Colombier if(option == '-') 3073e12c5d1SDavid du Colombier break; 3083e12c5d1SDavid du Colombier } 3093e12c5d1SDavid du Colombier if(argc || ((howmany = strtol(argv[0], &p, 0)) == 0 && p == argv[0])){ 3103e12c5d1SDavid du Colombier USED(howmany); 3113e12c5d1SDavid du Colombier rp->status = Status_BADARG; 3123e12c5d1SDavid du Colombier return -1; 3133e12c5d1SDavid du Colombier } 3143e12c5d1SDavid du Colombier return SRspace(rp, code, howmany); 3153e12c5d1SDavid du Colombier } 3163e12c5d1SDavid du Colombier 3173e12c5d1SDavid du Colombier static long 3183e12c5d1SDavid du Colombier cmdinquiry(ScsiReq *rp, int argc, char *argv[]) 3193e12c5d1SDavid du Colombier { 3203e12c5d1SDavid du Colombier long status; 3213e12c5d1SDavid du Colombier int i, n; 3223e12c5d1SDavid du Colombier uchar *p; 3233e12c5d1SDavid du Colombier 3243e12c5d1SDavid du Colombier USED(argc, argv); 3253e12c5d1SDavid du Colombier if((status = SRinquiry(rp)) != -1){ 3263e12c5d1SDavid du Colombier n = rp->inquiry[4]+4; 3273e12c5d1SDavid du Colombier for(i = 0; i < MIN(8, n); i++) 3283e12c5d1SDavid du Colombier Bprint(&bout, " %2.2ux", rp->inquiry[i]); 3293e12c5d1SDavid du Colombier p = &rp->inquiry[8]; 3303e12c5d1SDavid du Colombier n = MIN(n, sizeof(rp->inquiry)-8); 3313e12c5d1SDavid du Colombier while(n && (*p == ' ' || *p == '\t' || *p == '\n')){ 3323e12c5d1SDavid du Colombier n--; 3333e12c5d1SDavid du Colombier p++; 3343e12c5d1SDavid du Colombier } 3353e12c5d1SDavid du Colombier Bprint(&bout, "\t%.*s\n", n, p); 3363e12c5d1SDavid du Colombier } 3373e12c5d1SDavid du Colombier return status; 3383e12c5d1SDavid du Colombier } 3393e12c5d1SDavid du Colombier 3403e12c5d1SDavid du Colombier static long 3413e12c5d1SDavid du Colombier cmdmodeselect(ScsiReq *rp, int argc, char *argv[]) 3423e12c5d1SDavid du Colombier { 3433e12c5d1SDavid du Colombier uchar list[MaxDirData]; 3443e12c5d1SDavid du Colombier long nbytes, ul; 3453e12c5d1SDavid du Colombier char *p; 3463e12c5d1SDavid du Colombier 3473e12c5d1SDavid du Colombier memset(list, 0, sizeof(list)); 3483e12c5d1SDavid du Colombier for(nbytes = 0; argc; argc--, argv++, nbytes++){ 3493e12c5d1SDavid du Colombier if((ul = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){ 3503e12c5d1SDavid du Colombier rp->status = Status_BADARG; 3513e12c5d1SDavid du Colombier return -1; 3523e12c5d1SDavid du Colombier } 3533e12c5d1SDavid du Colombier list[nbytes] = ul; 3543e12c5d1SDavid du Colombier } 3553e12c5d1SDavid du Colombier return SRmodeselect(rp, list, nbytes); 3563e12c5d1SDavid du Colombier } 3573e12c5d1SDavid du Colombier 3583e12c5d1SDavid du Colombier static long 3593e12c5d1SDavid du Colombier cmdmodesense(ScsiReq *rp, int argc, char *argv[]) 3603e12c5d1SDavid du Colombier { 3613e12c5d1SDavid du Colombier uchar list[MaxDirData], *lp, page; 3623e12c5d1SDavid du Colombier long i, nbytes, status; 3633e12c5d1SDavid du Colombier char *p; 3643e12c5d1SDavid du Colombier 3653e12c5d1SDavid du Colombier nbytes = sizeof(list); 3663e12c5d1SDavid du Colombier switch(argc){ 3673e12c5d1SDavid du Colombier 3683e12c5d1SDavid du Colombier default: 3693e12c5d1SDavid du Colombier rp->status = Status_BADARG; 3703e12c5d1SDavid du Colombier return -1; 3713e12c5d1SDavid du Colombier 3723e12c5d1SDavid du Colombier case 2: 3733e12c5d1SDavid du Colombier if((nbytes = strtoul(argv[1], &p, 0)) == 0 && p == argv[1]){ 3743e12c5d1SDavid du Colombier rp->status = Status_BADARG; 3753e12c5d1SDavid du Colombier return -1; 3763e12c5d1SDavid du Colombier } 3773e12c5d1SDavid du Colombier /*FALLTHROUGH*/ 3783e12c5d1SDavid du Colombier 3793e12c5d1SDavid du Colombier case 1: 3803e12c5d1SDavid du Colombier if((page = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){ 3813e12c5d1SDavid du Colombier rp->status = Status_BADARG; 3823e12c5d1SDavid du Colombier return -1; 3833e12c5d1SDavid du Colombier } 3843e12c5d1SDavid du Colombier break; 3853e12c5d1SDavid du Colombier 3863e12c5d1SDavid du Colombier case 0: 3873e12c5d1SDavid du Colombier page = 0x3F; 3883e12c5d1SDavid du Colombier break; 3893e12c5d1SDavid du Colombier } 3903e12c5d1SDavid du Colombier if((status = SRmodesense(rp, page, list, nbytes)) == -1) 3913e12c5d1SDavid du Colombier return -1; 3923e12c5d1SDavid du Colombier lp = list; 3933e12c5d1SDavid du Colombier nbytes = list[0]-1; 3943e12c5d1SDavid du Colombier for(i = 0; i < 4; i++){ /* header */ 3953e12c5d1SDavid du Colombier Bprint(&bout, " %2.2ux", *lp); 3963e12c5d1SDavid du Colombier lp++; 3973e12c5d1SDavid du Colombier } 3983e12c5d1SDavid du Colombier nbytes -= 4; 3993e12c5d1SDavid du Colombier Bputc(&bout, '\n'); 4003e12c5d1SDavid du Colombier for(i = 0; i < 8; i++){ /* block descriptor */ 4013e12c5d1SDavid du Colombier Bprint(&bout, " %2.2ux", *lp); 4023e12c5d1SDavid du Colombier lp++; 4033e12c5d1SDavid du Colombier } 4043e12c5d1SDavid du Colombier nbytes -= 8; 4053e12c5d1SDavid du Colombier Bputc(&bout, '\n'); 4063e12c5d1SDavid du Colombier while(nbytes > 0){ 4073e12c5d1SDavid du Colombier i = *(lp+1); 4083e12c5d1SDavid du Colombier nbytes -= i+2; 4093e12c5d1SDavid du Colombier Bprint(&bout, " %2.2ux %2.2ux", *lp, *(lp+1)); 4103e12c5d1SDavid du Colombier lp += 2; 4113e12c5d1SDavid du Colombier while(i--){ 4123e12c5d1SDavid du Colombier Bprint(&bout, " %2.2ux", *lp); 4133e12c5d1SDavid du Colombier lp++; 4143e12c5d1SDavid du Colombier } 4153e12c5d1SDavid du Colombier Bputc(&bout, '\n'); 4163e12c5d1SDavid du Colombier } 4173e12c5d1SDavid du Colombier return status; 4183e12c5d1SDavid du Colombier } 4193e12c5d1SDavid du Colombier 4203e12c5d1SDavid du Colombier static long 4213e12c5d1SDavid du Colombier start(ScsiReq *rp, int argc, char *argv[], uchar code) 4223e12c5d1SDavid du Colombier { 4233e12c5d1SDavid du Colombier char *p; 4243e12c5d1SDavid du Colombier 4253e12c5d1SDavid du Colombier if(argc && (code = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){ 4263e12c5d1SDavid du Colombier rp->status = Status_BADARG; 4273e12c5d1SDavid du Colombier return -1; 4283e12c5d1SDavid du Colombier } 4293e12c5d1SDavid du Colombier return SRstart(rp, code); 4303e12c5d1SDavid du Colombier } 4313e12c5d1SDavid du Colombier 4323e12c5d1SDavid du Colombier static long 4333e12c5d1SDavid du Colombier cmdstart(ScsiReq *rp, int argc, char *argv[]) 4343e12c5d1SDavid du Colombier { 4353e12c5d1SDavid du Colombier return start(rp, argc, argv, 1); 4363e12c5d1SDavid du Colombier } 4373e12c5d1SDavid du Colombier 4383e12c5d1SDavid du Colombier static long 4393e12c5d1SDavid du Colombier cmdstop(ScsiReq *rp, int argc, char *argv[]) 4403e12c5d1SDavid du Colombier { 4413e12c5d1SDavid du Colombier return start(rp, argc, argv, 0); 4423e12c5d1SDavid du Colombier } 4433e12c5d1SDavid du Colombier 4443e12c5d1SDavid du Colombier static long 4453e12c5d1SDavid du Colombier cmdeject(ScsiReq *rp, int argc, char *argv[]) 4463e12c5d1SDavid du Colombier { 4473e12c5d1SDavid du Colombier return start(rp, argc, argv, 2); 4483e12c5d1SDavid du Colombier } 4493e12c5d1SDavid du Colombier 4503e12c5d1SDavid du Colombier static long 4513e12c5d1SDavid du Colombier cmdcapacity(ScsiReq *rp, int argc, char *argv[]) 4523e12c5d1SDavid du Colombier { 4533e12c5d1SDavid du Colombier uchar d[6]; 4543e12c5d1SDavid du Colombier long n; 4553e12c5d1SDavid du Colombier 4563e12c5d1SDavid du Colombier USED(argc, argv); 4573e12c5d1SDavid du Colombier if((n = SRrcapacity(rp, d)) == -1) 4583e12c5d1SDavid du Colombier return -1; 4593e12c5d1SDavid du Colombier Bprint(&bout, " %ld %ld\n", d[0]<<24|d[1]<<16|d[2]<<8|d[3], 4603e12c5d1SDavid du Colombier d[4]<<24|d[5]<<16|d[6]<<8|d[7]); 4613e12c5d1SDavid du Colombier return n; 4623e12c5d1SDavid du Colombier } 4633e12c5d1SDavid du Colombier 4643e12c5d1SDavid du Colombier static long 4653e12c5d1SDavid du Colombier cmdflushcache(ScsiReq *rp, int argc, char *argv[]) 4663e12c5d1SDavid du Colombier { 4673e12c5d1SDavid du Colombier USED(argc, argv); 4683e12c5d1SDavid du Colombier return SRflushcache(rp); 4693e12c5d1SDavid du Colombier } 4703e12c5d1SDavid du Colombier 4713e12c5d1SDavid du Colombier static long 4723e12c5d1SDavid du Colombier cmdrdiscinfo(ScsiReq *rp, int argc, char *argv[]) 4733e12c5d1SDavid du Colombier { 4743e12c5d1SDavid du Colombier uchar d[MaxDirData], ses, track, *p; 4753e12c5d1SDavid du Colombier char *sp; 4763e12c5d1SDavid du Colombier long n, nbytes; 4773e12c5d1SDavid du Colombier 4783e12c5d1SDavid du Colombier ses = track = 0; 4793e12c5d1SDavid du Colombier switch(argc){ 4803e12c5d1SDavid du Colombier 4813e12c5d1SDavid du Colombier default: 4823e12c5d1SDavid du Colombier rp->status = Status_BADARG; 4833e12c5d1SDavid du Colombier return -1; 4843e12c5d1SDavid du Colombier 4853e12c5d1SDavid du Colombier case 2: 4863e12c5d1SDavid du Colombier if((ses = strtoul(argv[1], &sp, 0)) == 0 && sp == argv[1]){ 4873e12c5d1SDavid du Colombier rp->status = Status_BADARG; 4883e12c5d1SDavid du Colombier return -1; 4893e12c5d1SDavid du Colombier } 4903e12c5d1SDavid du Colombier /*FALLTHROUGH*/ 4913e12c5d1SDavid du Colombier 4923e12c5d1SDavid du Colombier case 1: 4933e12c5d1SDavid du Colombier if((track = strtoul(argv[0], &sp, 0)) == 0 && sp == argv[0]){ 4943e12c5d1SDavid du Colombier rp->status = Status_BADARG; 4953e12c5d1SDavid du Colombier return -1; 4963e12c5d1SDavid du Colombier } 4973e12c5d1SDavid du Colombier /*FALLTHROUGH*/ 4983e12c5d1SDavid du Colombier 4993e12c5d1SDavid du Colombier case 0: 5003e12c5d1SDavid du Colombier break; 5013e12c5d1SDavid du Colombier } 5023e12c5d1SDavid du Colombier if((nbytes = SRrdiscinfo(rp, d, ses, track)) == -1) 5033e12c5d1SDavid du Colombier return -1; 5043e12c5d1SDavid du Colombier if(ses == 0){ 5053e12c5d1SDavid du Colombier Bprint(&bout, "\ttoc/pma data length: 0x%ux\n", (d[0]<<8)|d[1]); 5063e12c5d1SDavid du Colombier Bprint(&bout, "\tfirst track number: %d\n", d[2]); 5073e12c5d1SDavid du Colombier Bprint(&bout, "\tlast track number: %d\n", d[3]); 5083e12c5d1SDavid du Colombier for(p = &d[4], n = nbytes-4; n; n -= 8, p += 8){ 5093e12c5d1SDavid du Colombier Bprint(&bout, "\ttrack number: 0x%2.2ux\n", p[2]); 5103e12c5d1SDavid du Colombier Bprint(&bout, "\t\tcontrol: 0x%2.2ux\n", p[1] & 0x0F); 5113e12c5d1SDavid du Colombier Bprint(&bout, "\t\tblock address: 0x%lux\n", 5123e12c5d1SDavid du Colombier (p[4]<<24)|(p[5]<<16)|(p[6]<<8)|p[7]); 5133e12c5d1SDavid du Colombier } 5143e12c5d1SDavid du Colombier } 5153e12c5d1SDavid du Colombier else{ 5163e12c5d1SDavid du Colombier Bprint(&bout, "\tsessions data length: 0x%ux\n", (d[0]<<8)|d[1]); 5173e12c5d1SDavid du Colombier Bprint(&bout, "\tnumber of finished sessions: %d\n", d[2]); 5183e12c5d1SDavid du Colombier Bprint(&bout, "\tunfinished session number: %d\n", d[3]); 5193e12c5d1SDavid du Colombier for(p = &d[4], n = nbytes-4; n; n -= 8, p += 8){ 5203e12c5d1SDavid du Colombier Bprint(&bout, "\tsession number: 0x%2.2ux\n", p[0]); 5213e12c5d1SDavid du Colombier Bprint(&bout, "\t\tfirst track number in session: 0x%2.2ux\n", 5223e12c5d1SDavid du Colombier p[2]); 5233e12c5d1SDavid du Colombier Bprint(&bout, "\t\tlogical start address: 0x%lux\n", 5243e12c5d1SDavid du Colombier (p[5]<<16)|(p[6]<<8)|p[7]); 5253e12c5d1SDavid du Colombier } 5263e12c5d1SDavid du Colombier } 5273e12c5d1SDavid du Colombier for(n = 0; n < nbytes; n++) 5283e12c5d1SDavid du Colombier Bprint(&bout, " %2.2ux", d[n]); 5293e12c5d1SDavid du Colombier Bprint(&bout, "\n"); 5303e12c5d1SDavid du Colombier return nbytes; 5313e12c5d1SDavid du Colombier } 5323e12c5d1SDavid du Colombier 5333e12c5d1SDavid du Colombier static long 5343e12c5d1SDavid du Colombier cmdfwaddr(ScsiReq *rp, int argc, char *argv[]) 5353e12c5d1SDavid du Colombier { 5363e12c5d1SDavid du Colombier uchar d[MaxDirData], npa, track, mode; 5373e12c5d1SDavid du Colombier long n; 5383e12c5d1SDavid du Colombier char *p; 5393e12c5d1SDavid du Colombier 5403e12c5d1SDavid du Colombier npa = mode = track = 0; 5413e12c5d1SDavid du Colombier switch(argc){ 5423e12c5d1SDavid du Colombier 5433e12c5d1SDavid du Colombier default: 5443e12c5d1SDavid du Colombier rp->status = Status_BADARG; 5453e12c5d1SDavid du Colombier return -1; 5463e12c5d1SDavid du Colombier 5473e12c5d1SDavid du Colombier case 3: 5483e12c5d1SDavid du Colombier if((npa = strtoul(argv[1], &p, 0)) == 0 && p == argv[1]){ 5493e12c5d1SDavid du Colombier rp->status = Status_BADARG; 5503e12c5d1SDavid du Colombier return -1; 5513e12c5d1SDavid du Colombier } 5523e12c5d1SDavid du Colombier /*FALLTHROUGH*/ 5533e12c5d1SDavid du Colombier 5543e12c5d1SDavid du Colombier case 2: 5553e12c5d1SDavid du Colombier if((mode = strtoul(argv[1], &p, 0)) == 0 && p == argv[1]){ 5563e12c5d1SDavid du Colombier rp->status = Status_BADARG; 5573e12c5d1SDavid du Colombier return -1; 5583e12c5d1SDavid du Colombier } 5593e12c5d1SDavid du Colombier /*FALLTHROUGH*/ 5603e12c5d1SDavid du Colombier 5613e12c5d1SDavid du Colombier case 1: 5623e12c5d1SDavid du Colombier if((track = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){ 5633e12c5d1SDavid du Colombier rp->status = Status_BADARG; 5643e12c5d1SDavid du Colombier return -1; 5653e12c5d1SDavid du Colombier } 5663e12c5d1SDavid du Colombier break; 5673e12c5d1SDavid du Colombier 5683e12c5d1SDavid du Colombier case 0: 5693e12c5d1SDavid du Colombier break; 5703e12c5d1SDavid du Colombier } 5713e12c5d1SDavid du Colombier if((n = SRfwaddr(rp, track, mode, npa, d)) == -1) 5723e12c5d1SDavid du Colombier return -1; 5733e12c5d1SDavid du Colombier Bprint(&bout, "%ud %ld\n", d[0], (d[1]<<24)|(d[2]<<16)|(d[3]<<8)|d[4]); 5743e12c5d1SDavid du Colombier return n; 5753e12c5d1SDavid du Colombier } 5763e12c5d1SDavid du Colombier 5773e12c5d1SDavid du Colombier static long 5783e12c5d1SDavid du Colombier cmdtreserve(ScsiReq *rp, int argc, char *argv[]) 5793e12c5d1SDavid du Colombier { 5803e12c5d1SDavid du Colombier long nbytes; 5813e12c5d1SDavid du Colombier char *p; 5823e12c5d1SDavid du Colombier 5833e12c5d1SDavid du Colombier if(argc != 1 || ((nbytes = strtoul(argv[0], &p, 0)) == 0 && p == argv[0])){ 5843e12c5d1SDavid du Colombier rp->status = Status_BADARG; 5853e12c5d1SDavid du Colombier return -1; 5863e12c5d1SDavid du Colombier } 5873e12c5d1SDavid du Colombier return SRtreserve(rp, nbytes); 5883e12c5d1SDavid du Colombier } 5893e12c5d1SDavid du Colombier 5903e12c5d1SDavid du Colombier static long 5913e12c5d1SDavid du Colombier cmdtrackinfo(ScsiReq *rp, int argc, char *argv[]) 5923e12c5d1SDavid du Colombier { 5933e12c5d1SDavid du Colombier uchar d[MaxDirData], track; 5943e12c5d1SDavid du Colombier long n; 5953e12c5d1SDavid du Colombier ulong ul; 5963e12c5d1SDavid du Colombier char *p; 5973e12c5d1SDavid du Colombier 5983e12c5d1SDavid du Colombier track = 0; 5993e12c5d1SDavid du Colombier if(argc && (track = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){ 6003e12c5d1SDavid du Colombier rp->status = Status_BADARG; 6013e12c5d1SDavid du Colombier return -1; 6023e12c5d1SDavid du Colombier } 6033e12c5d1SDavid du Colombier if((n = SRtinfo(rp, track, d)) == -1) 6043e12c5d1SDavid du Colombier return -1; 6053e12c5d1SDavid du Colombier Bprint(&bout, "buffer length: 0x%ux\n", d[0]); 6063e12c5d1SDavid du Colombier Bprint(&bout, "number of tracks: 0x%ux\n", d[1]); 6073e12c5d1SDavid du Colombier ul = (d[2]<<24)|(d[3]<<16)|(d[4]<<8)|d[5]; 6083e12c5d1SDavid du Colombier Bprint(&bout, "start address: 0x%lux\n", ul); 6093e12c5d1SDavid du Colombier ul = (d[6]<<24)|(d[7]<<16)|(d[8]<<8)|d[9]; 6103e12c5d1SDavid du Colombier Bprint(&bout, "track length: 0x%lux\n", ul); 6113e12c5d1SDavid du Colombier Bprint(&bout, "track mode: 0x%ux\n", d[0x0A] & 0x0F); 6123e12c5d1SDavid du Colombier Bprint(&bout, "track status: 0x%ux\n", (d[0x0A]>>4) & 0x0F); 6133e12c5d1SDavid du Colombier Bprint(&bout, "data mode: 0x%ux\n", d[0x0B] & 0x0F); 6143e12c5d1SDavid du Colombier ul = (d[0x0C]<<24)|(d[0x0D]<<16)|(d[0x0E]<<8)|d[0x0F]; 6153e12c5d1SDavid du Colombier Bprint(&bout, "free blocks: 0x%lux\n", ul); 6163e12c5d1SDavid du Colombier return n; 6173e12c5d1SDavid du Colombier } 6183e12c5d1SDavid du Colombier 6193e12c5d1SDavid du Colombier static long 6203e12c5d1SDavid du Colombier cmdwtrack(ScsiReq *rp, int argc, char *argv[]) 6213e12c5d1SDavid du Colombier { 6223e12c5d1SDavid du Colombier uchar mode, track; 6233e12c5d1SDavid du Colombier long n, nbytes, total, x; 6243e12c5d1SDavid du Colombier int fd, pid; 6253e12c5d1SDavid du Colombier char *p; 6263e12c5d1SDavid du Colombier 6273e12c5d1SDavid du Colombier mode = track = 0; 6283e12c5d1SDavid du Colombier nbytes = 0; 6293e12c5d1SDavid du Colombier switch(argc){ 6303e12c5d1SDavid du Colombier 6313e12c5d1SDavid du Colombier default: 6323e12c5d1SDavid du Colombier rp->status = Status_BADARG; 6333e12c5d1SDavid du Colombier return -1; 6343e12c5d1SDavid du Colombier 6353e12c5d1SDavid du Colombier case 4: 6363e12c5d1SDavid du Colombier if((mode = strtoul(argv[3], &p, 0)) == 0 && p == argv[3]){ 6373e12c5d1SDavid du Colombier rp->status = Status_BADARG; 6383e12c5d1SDavid du Colombier return -1; 6393e12c5d1SDavid du Colombier } 6403e12c5d1SDavid du Colombier /*FALLTHROUGH*/ 6413e12c5d1SDavid du Colombier 6423e12c5d1SDavid du Colombier case 3: 6433e12c5d1SDavid du Colombier if((track = strtoul(argv[2], &p, 0)) == 0 && p == argv[2]){ 6443e12c5d1SDavid du Colombier rp->status = Status_BADARG; 6453e12c5d1SDavid du Colombier return -1; 6463e12c5d1SDavid du Colombier } 6473e12c5d1SDavid du Colombier /*FALLTHROUGH*/ 6483e12c5d1SDavid du Colombier 6493e12c5d1SDavid du Colombier case 2: 6503e12c5d1SDavid du Colombier if((nbytes = strtoul(argv[1], &p, 0)) == 0 && p == argv[1]){ 6513e12c5d1SDavid du Colombier rp->status = Status_BADARG; 6523e12c5d1SDavid du Colombier return -1; 6533e12c5d1SDavid du Colombier } 6543e12c5d1SDavid du Colombier /*FALLTHROUGH*/ 6553e12c5d1SDavid du Colombier 6563e12c5d1SDavid du Colombier case 1: 6573e12c5d1SDavid du Colombier if((fd = mkfile(argv[0], OREAD, &pid)) == -1){ 6583e12c5d1SDavid du Colombier rp->status = Status_BADARG; 6593e12c5d1SDavid du Colombier return -1; 6603e12c5d1SDavid du Colombier } 6613e12c5d1SDavid du Colombier break; 6623e12c5d1SDavid du Colombier } 6633e12c5d1SDavid du Colombier total = 0; 6643e12c5d1SDavid du Colombier n = MIN(nbytes, MaxIOsize); 6653e12c5d1SDavid du Colombier if((n = read(fd, rwbuf, n)) == -1){ 6663e12c5d1SDavid du Colombier fprint(2, "file read failed %r\n"); 6673e12c5d1SDavid du Colombier close(fd); 6683e12c5d1SDavid du Colombier return -1; 6693e12c5d1SDavid du Colombier } 6703e12c5d1SDavid du Colombier if((x = SRwtrack(rp, rwbuf, n, track, mode)) != n){ 6713e12c5d1SDavid du Colombier fprint(2, "wtrack: write incomplete: asked %d, did %d\n", n, x); 6723e12c5d1SDavid du Colombier if(rp->status == Status_OK) 6733e12c5d1SDavid du Colombier rp->status = Status_SW; 6743e12c5d1SDavid du Colombier close(fd); 6753e12c5d1SDavid du Colombier return -1; 6763e12c5d1SDavid du Colombier } 6773e12c5d1SDavid du Colombier nbytes -= n; 6783e12c5d1SDavid du Colombier total += n; 6793e12c5d1SDavid du Colombier while(nbytes){ 6803e12c5d1SDavid du Colombier n = MIN(nbytes, MaxIOsize); 6813e12c5d1SDavid du Colombier if((n = read(fd, rwbuf, n)) == -1){ 6823e12c5d1SDavid du Colombier break; 6833e12c5d1SDavid du Colombier } 6843e12c5d1SDavid du Colombier if((x = SRwrite(rp, rwbuf, n)) != n){ 6853e12c5d1SDavid du Colombier fprint(2, "write: write incomplete: asked %d, did %d\n", n, x); 6863e12c5d1SDavid du Colombier if(rp->status == Status_OK) 6873e12c5d1SDavid du Colombier rp->status = Status_SW; 6883e12c5d1SDavid du Colombier break; 6893e12c5d1SDavid du Colombier } 6903e12c5d1SDavid du Colombier nbytes -= n; 6913e12c5d1SDavid du Colombier total += n; 6923e12c5d1SDavid du Colombier } 6933e12c5d1SDavid du Colombier close(fd); 6943e12c5d1SDavid du Colombier if(pid >= 0 && waitfor(pid)){ 6953e12c5d1SDavid du Colombier rp->status = Status_SW; 6963e12c5d1SDavid du Colombier return -1; 6973e12c5d1SDavid du Colombier } 6983e12c5d1SDavid du Colombier return total; 6993e12c5d1SDavid du Colombier } 7003e12c5d1SDavid du Colombier 7013e12c5d1SDavid du Colombier static long 7023e12c5d1SDavid du Colombier cmdload(ScsiReq *rp, int argc, char *argv[]) 7033e12c5d1SDavid du Colombier { 7043e12c5d1SDavid du Colombier USED(argc, argv); 7053e12c5d1SDavid du Colombier return SRmload(rp, 0); 7063e12c5d1SDavid du Colombier } 7073e12c5d1SDavid du Colombier 7083e12c5d1SDavid du Colombier static long 7093e12c5d1SDavid du Colombier cmdunload(ScsiReq *rp, int argc, char *argv[]) 7103e12c5d1SDavid du Colombier { 7113e12c5d1SDavid du Colombier USED(argc, argv); 7123e12c5d1SDavid du Colombier return SRmload(rp, 1); 7133e12c5d1SDavid du Colombier } 7143e12c5d1SDavid du Colombier 7153e12c5d1SDavid du Colombier static long 7163e12c5d1SDavid du Colombier cmdfixation(ScsiReq *rp, int argc, char *argv[]) 7173e12c5d1SDavid du Colombier { 7183e12c5d1SDavid du Colombier uchar type; 7193e12c5d1SDavid du Colombier char *p; 7203e12c5d1SDavid du Colombier 7213e12c5d1SDavid du Colombier type = 0; 7223e12c5d1SDavid du Colombier if(argc && (type = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){ 7233e12c5d1SDavid du Colombier rp->status = Status_BADARG; 7243e12c5d1SDavid du Colombier return -1; 7253e12c5d1SDavid du Colombier } 7263e12c5d1SDavid du Colombier return SRfixation(rp, type); 7273e12c5d1SDavid du Colombier } 7283e12c5d1SDavid du Colombier 7293e12c5d1SDavid du Colombier static long 7303e12c5d1SDavid du Colombier cmdhelp(ScsiReq *rp, int argc, char *argv[]) 7313e12c5d1SDavid du Colombier { 7323e12c5d1SDavid du Colombier ScsiCmd *cp; 7333e12c5d1SDavid du Colombier char *p; 7343e12c5d1SDavid du Colombier 7353e12c5d1SDavid du Colombier USED(rp); 7363e12c5d1SDavid du Colombier if(argc) 7373e12c5d1SDavid du Colombier p = argv[0]; 7383e12c5d1SDavid du Colombier else 7393e12c5d1SDavid du Colombier p = 0; 7403e12c5d1SDavid du Colombier for(cp = scsicmd; cp->name; cp++){ 7413e12c5d1SDavid du Colombier if(p == 0 || strcmp(p, cp->name) == 0) 7423e12c5d1SDavid du Colombier Bprint(&bout, "%s\n", cp->help); 7433e12c5d1SDavid du Colombier } 7443e12c5d1SDavid du Colombier return 0; 7453e12c5d1SDavid du Colombier } 7463e12c5d1SDavid du Colombier 7473e12c5d1SDavid du Colombier static long 7483e12c5d1SDavid du Colombier cmdprobe(ScsiReq *rp, int argc, char *argv[]) 7493e12c5d1SDavid du Colombier { 7503e12c5d1SDavid du Colombier ScsiReq scsireq; 7513e12c5d1SDavid du Colombier uchar id; 7523e12c5d1SDavid du Colombier 7533e12c5d1SDavid du Colombier USED(argc, argv); 7543e12c5d1SDavid du Colombier rp->status = Status_OK; 7553e12c5d1SDavid du Colombier scsireq.flags = 0; 7563e12c5d1SDavid du Colombier for(id = 0; id < CtlrID; id++){ 7573e12c5d1SDavid du Colombier if(SRopenraw(&scsireq, id) == -1) 7583e12c5d1SDavid du Colombier return -1; 7593e12c5d1SDavid du Colombier SRreqsense(&scsireq); 7603e12c5d1SDavid du Colombier switch(scsireq.status){ 7613e12c5d1SDavid du Colombier 7623e12c5d1SDavid du Colombier default: 7633e12c5d1SDavid du Colombier break; 7643e12c5d1SDavid du Colombier 7653e12c5d1SDavid du Colombier case Status_OK: 7663e12c5d1SDavid du Colombier case Status_SD: 7673e12c5d1SDavid du Colombier Bprint(&bout, "%d: ", id); 7683e12c5d1SDavid du Colombier cmdinquiry(&scsireq, 0, 0); 7693e12c5d1SDavid du Colombier break; 7703e12c5d1SDavid du Colombier } 7713e12c5d1SDavid du Colombier SRclose(&scsireq); 7723e12c5d1SDavid du Colombier } 7733e12c5d1SDavid du Colombier return 0; 7743e12c5d1SDavid du Colombier } 7753e12c5d1SDavid du Colombier 7763e12c5d1SDavid du Colombier static long 7773e12c5d1SDavid du Colombier cmdclose(ScsiReq *rp, int argc, char *argv[]) 7783e12c5d1SDavid du Colombier { 7793e12c5d1SDavid du Colombier USED(argc, argv); 7803e12c5d1SDavid du Colombier return SRclose(rp); 7813e12c5d1SDavid du Colombier } 7823e12c5d1SDavid du Colombier 7833e12c5d1SDavid du Colombier static long 7843e12c5d1SDavid du Colombier cmdopen(ScsiReq *rp, int argc, char *argv[]) 7853e12c5d1SDavid du Colombier { 7863e12c5d1SDavid du Colombier char *p; 787bd389b36SDavid du Colombier int id, raw; 7883e12c5d1SDavid du Colombier long status; 7893e12c5d1SDavid du Colombier 790bd389b36SDavid du Colombier raw = 0; 791bd389b36SDavid du Colombier if(argc && strcmp("-r", argv[0]) == 0){ 792bd389b36SDavid du Colombier raw = 1; 793bd389b36SDavid du Colombier argc--, argv++; 794bd389b36SDavid du Colombier } 7953e12c5d1SDavid du Colombier if(argc != 1 || ((id = strtoul(argv[0], &p, 0)) == 0 && p == argv[0])){ 7963e12c5d1SDavid du Colombier rp->status = Status_BADARG; 7973e12c5d1SDavid du Colombier return -1; 7983e12c5d1SDavid du Colombier } 799bd389b36SDavid du Colombier if(raw == 0){ 800bd389b36SDavid du Colombier if((status = SRopen(rp, id)) != -1 && verbose) 8013e12c5d1SDavid du Colombier Bprint(&bout, "block size: %ld\n", rp->lbsize); 802bd389b36SDavid du Colombier } 803bd389b36SDavid du Colombier else { 804bd389b36SDavid du Colombier status = SRopenraw(rp, id); 805bd389b36SDavid du Colombier rp->lbsize = 512; 806bd389b36SDavid du Colombier } 8073e12c5d1SDavid du Colombier return status; 8083e12c5d1SDavid du Colombier } 8093e12c5d1SDavid du Colombier 8103e12c5d1SDavid du Colombier static ScsiCmd scsicmd[] = { 8113e12c5d1SDavid du Colombier { "ready", cmdready, 1, /*[0x00]*/ 8123e12c5d1SDavid du Colombier "ready", 8133e12c5d1SDavid du Colombier }, 8143e12c5d1SDavid du Colombier { "rewind", cmdrewind, 1, /*[0x01]*/ 8153e12c5d1SDavid du Colombier "rewind", 8163e12c5d1SDavid du Colombier }, 8173e12c5d1SDavid du Colombier { "rezero", cmdrewind, 1, /*[0x01]*/ 8183e12c5d1SDavid du Colombier "rezero", 8193e12c5d1SDavid du Colombier }, 8203e12c5d1SDavid du Colombier { "reqsense", cmdreqsense, 1, /*[0x03]*/ 8213e12c5d1SDavid du Colombier "reqsense", 8223e12c5d1SDavid du Colombier }, 823bd389b36SDavid du Colombier { "format", cmdformat, 0, /*[0x04]*/ 8243e12c5d1SDavid du Colombier "format", 8253e12c5d1SDavid du Colombier }, 8263e12c5d1SDavid du Colombier { "rblimits", cmdrblimits, 1, /*[0x05]*/ 8273e12c5d1SDavid du Colombier "rblimits", 8283e12c5d1SDavid du Colombier }, 8293e12c5d1SDavid du Colombier { "read", cmdread, 1, /*[0x08]*/ 8303e12c5d1SDavid du Colombier "read [|]file [nbytes]", 8313e12c5d1SDavid du Colombier }, 8323e12c5d1SDavid du Colombier { "write", cmdwrite, 1, /*[0x0A]*/ 8333e12c5d1SDavid du Colombier "write [|]file [nbytes]", 8343e12c5d1SDavid du Colombier }, 8353e12c5d1SDavid du Colombier { "seek", cmdseek, 1, /*[0x0B]*/ 8363e12c5d1SDavid du Colombier "seek offset [whence]", 8373e12c5d1SDavid du Colombier }, 8383e12c5d1SDavid du Colombier { "filemark", cmdfilemark, 1, /*[0x10]*/ 8393e12c5d1SDavid du Colombier "filemark [howmany]", 8403e12c5d1SDavid du Colombier }, 8413e12c5d1SDavid du Colombier { "space", cmdspace, 1, /*[0x11]*/ 8423e12c5d1SDavid du Colombier "space [-f] [-b] [[--] howmany]", 8433e12c5d1SDavid du Colombier }, 8443e12c5d1SDavid du Colombier { "inquiry", cmdinquiry, 1, /*[0x12]*/ 8453e12c5d1SDavid du Colombier "inquiry", 8463e12c5d1SDavid du Colombier }, 8473e12c5d1SDavid du Colombier { "modeselect", cmdmodeselect, 1, /*[0x15] */ 8483e12c5d1SDavid du Colombier "modeselect bytes...", 8493e12c5d1SDavid du Colombier }, 8503e12c5d1SDavid du Colombier { "modesense", cmdmodesense, 1, /*[0x1A]*/ 8513e12c5d1SDavid du Colombier "modesense [page [nbytes]]", 8523e12c5d1SDavid du Colombier }, 8533e12c5d1SDavid du Colombier { "start", cmdstart, 1, /*[0x1B]*/ 8543e12c5d1SDavid du Colombier "start [code]", 8553e12c5d1SDavid du Colombier }, 8563e12c5d1SDavid du Colombier { "stop", cmdstop, 1, /*[0x1B]*/ 8573e12c5d1SDavid du Colombier "stop [code]", 8583e12c5d1SDavid du Colombier }, 8593e12c5d1SDavid du Colombier { "eject", cmdeject, 1, /*[0x1B]*/ 8603e12c5d1SDavid du Colombier "eject [code]", 8613e12c5d1SDavid du Colombier }, 8623e12c5d1SDavid du Colombier { "capacity", cmdcapacity, 1, /*[0x25]*/ 8633e12c5d1SDavid du Colombier "capacity", 8643e12c5d1SDavid du Colombier }, 8653e12c5d1SDavid du Colombier 8663e12c5d1SDavid du Colombier { "flushcache", cmdflushcache, 1, /*[0x35]*/ 8673e12c5d1SDavid du Colombier "flushcache", 8683e12c5d1SDavid du Colombier }, 8693e12c5d1SDavid du Colombier { "rdiscinfo", cmdrdiscinfo, 1, /*[0x43]*/ 8703e12c5d1SDavid du Colombier "rdiscinfo [track/session-number [ses]]", 8713e12c5d1SDavid du Colombier }, 8723e12c5d1SDavid du Colombier { "fwaddr", cmdfwaddr, 1, /*[0xE2]*/ 8733e12c5d1SDavid du Colombier "fwaddr [track [mode [npa]]]", 8743e12c5d1SDavid du Colombier }, 8753e12c5d1SDavid du Colombier { "treserve", cmdtreserve, 1, /*[0xE4]*/ 8763e12c5d1SDavid du Colombier "treserve nbytes", 8773e12c5d1SDavid du Colombier }, 8783e12c5d1SDavid du Colombier { "trackinfo", cmdtrackinfo, 1, /*[0xE5]*/ 8793e12c5d1SDavid du Colombier "trackinfo [track]", 8803e12c5d1SDavid du Colombier }, 8813e12c5d1SDavid du Colombier { "wtrack", cmdwtrack, 1, /*[0xE6]*/ 8823e12c5d1SDavid du Colombier "wtrack [|]file [nbytes [track [mode]]]", 8833e12c5d1SDavid du Colombier }, 8843e12c5d1SDavid du Colombier { "load", cmdload, 1, /*[0xE7]*/ 8853e12c5d1SDavid du Colombier "load", 8863e12c5d1SDavid du Colombier }, 8873e12c5d1SDavid du Colombier { "unload", cmdunload, 1, /*[0xE7]*/ 8883e12c5d1SDavid du Colombier "unload", 8893e12c5d1SDavid du Colombier }, 8903e12c5d1SDavid du Colombier { "fixation", cmdfixation, 1, /*[0xE9]*/ 8913e12c5d1SDavid du Colombier "fixation [toc-type]", 8923e12c5d1SDavid du Colombier }, 8933e12c5d1SDavid du Colombier 8943e12c5d1SDavid du Colombier { "help", cmdhelp, 0, 8953e12c5d1SDavid du Colombier "help", 8963e12c5d1SDavid du Colombier }, 8973e12c5d1SDavid du Colombier { "probe", cmdprobe, 0, 8983e12c5d1SDavid du Colombier "probe", 8993e12c5d1SDavid du Colombier }, 9003e12c5d1SDavid du Colombier { "close", cmdclose, 1, 9013e12c5d1SDavid du Colombier "close", 9023e12c5d1SDavid du Colombier }, 9033e12c5d1SDavid du Colombier { "open", cmdopen, 0, 9043e12c5d1SDavid du Colombier "open target-id", 9053e12c5d1SDavid du Colombier }, 9063e12c5d1SDavid du Colombier { 0, 0 }, 9073e12c5d1SDavid du Colombier }; 9083e12c5d1SDavid du Colombier 9093e12c5d1SDavid du Colombier #define SEP(c) (((c)==' ')||((c)=='\t')||((c)=='\n')) 9103e12c5d1SDavid du Colombier 9113e12c5d1SDavid du Colombier static char * 9123e12c5d1SDavid du Colombier tokenise(char *s, char **start, char **end) 9133e12c5d1SDavid du Colombier { 9143e12c5d1SDavid du Colombier char *to; 9153e12c5d1SDavid du Colombier Rune r; 9163e12c5d1SDavid du Colombier int n; 9173e12c5d1SDavid du Colombier 9183e12c5d1SDavid du Colombier while(*s && SEP(*s)) /* skip leading white space */ 9193e12c5d1SDavid du Colombier s++; 9203e12c5d1SDavid du Colombier to = *start = s; 9213e12c5d1SDavid du Colombier while(*s){ 9223e12c5d1SDavid du Colombier n = chartorune(&r, s); 9233e12c5d1SDavid du Colombier if(SEP(r)){ 9243e12c5d1SDavid du Colombier if(to != *start) /* we have data */ 9253e12c5d1SDavid du Colombier break; 9263e12c5d1SDavid du Colombier s += n; /* null string - keep looking */ 9273e12c5d1SDavid du Colombier while(*s && SEP(*s)) 9283e12c5d1SDavid du Colombier s++; 9293e12c5d1SDavid du Colombier to = *start = s; 9303e12c5d1SDavid du Colombier } 9313e12c5d1SDavid du Colombier else if(r == '\''){ 9323e12c5d1SDavid du Colombier s += n; /* skip leading quote */ 9333e12c5d1SDavid du Colombier while(*s){ 9343e12c5d1SDavid du Colombier n = chartorune(&r, s); 9353e12c5d1SDavid du Colombier if(r == '\''){ 9363e12c5d1SDavid du Colombier if(s[1] != '\'') 9373e12c5d1SDavid du Colombier break; 9383e12c5d1SDavid du Colombier s++; /* embedded quote */ 9393e12c5d1SDavid du Colombier } 9403e12c5d1SDavid du Colombier while (n--) 9413e12c5d1SDavid du Colombier *to++ = *s++; 9423e12c5d1SDavid du Colombier } 9433e12c5d1SDavid du Colombier if(!*s) /* no trailing quote */ 9443e12c5d1SDavid du Colombier break; 9453e12c5d1SDavid du Colombier s++; /* skip trailing quote */ 9463e12c5d1SDavid du Colombier } 9473e12c5d1SDavid du Colombier else { 9483e12c5d1SDavid du Colombier while(n--) 9493e12c5d1SDavid du Colombier *to++ = *s++; 9503e12c5d1SDavid du Colombier } 9513e12c5d1SDavid du Colombier } 9523e12c5d1SDavid du Colombier *end = to; 9533e12c5d1SDavid du Colombier return s; 9543e12c5d1SDavid du Colombier } 9553e12c5d1SDavid du Colombier 9563e12c5d1SDavid du Colombier static int 9573e12c5d1SDavid du Colombier parse(char *s, char *fields[], int nfields) 9583e12c5d1SDavid du Colombier { 959*219b2ee8SDavid du Colombier int c, argc; 9603e12c5d1SDavid du Colombier char *start, *end; 9613e12c5d1SDavid du Colombier 9623e12c5d1SDavid du Colombier argc = 0; 963*219b2ee8SDavid du Colombier c = *s; 964*219b2ee8SDavid du Colombier while(c){ 9653e12c5d1SDavid du Colombier s = tokenise(s, &start, &end); 966*219b2ee8SDavid du Colombier c = *s++; 9673e12c5d1SDavid du Colombier if(*start == 0) 9683e12c5d1SDavid du Colombier break; 9693e12c5d1SDavid du Colombier if(argc >= nfields-1) 9703e12c5d1SDavid du Colombier return -1; 9713e12c5d1SDavid du Colombier *end = 0; 9723e12c5d1SDavid du Colombier fields[argc++] = start; 9733e12c5d1SDavid du Colombier } 9743e12c5d1SDavid du Colombier fields[argc] = 0; 9753e12c5d1SDavid du Colombier return argc; 9763e12c5d1SDavid du Colombier } 9773e12c5d1SDavid du Colombier 9783e12c5d1SDavid du Colombier static void 9793e12c5d1SDavid du Colombier usage(void) 9803e12c5d1SDavid du Colombier { 981*219b2ee8SDavid du Colombier fprint(2, "%s: usage: %s [-b bus] [-q] [scsi-id]\n", argv0, argv0); 9823e12c5d1SDavid du Colombier exits("usage"); 9833e12c5d1SDavid du Colombier } 9843e12c5d1SDavid du Colombier 9853e12c5d1SDavid du Colombier void 9863e12c5d1SDavid du Colombier main(int argc, char *argv[]) 9873e12c5d1SDavid du Colombier { 9883e12c5d1SDavid du Colombier ScsiReq target; 9893e12c5d1SDavid du Colombier char *ap, *av[50]; 9903e12c5d1SDavid du Colombier int ac; 9913e12c5d1SDavid du Colombier ScsiCmd *cp; 9923e12c5d1SDavid du Colombier long status; 9933e12c5d1SDavid du Colombier 9943e12c5d1SDavid du Colombier ARGBEGIN { 995*219b2ee8SDavid du Colombier case 'b': 996*219b2ee8SDavid du Colombier bus = atoi(ARGF()); 997*219b2ee8SDavid du Colombier break; 9983e12c5d1SDavid du Colombier 9993e12c5d1SDavid du Colombier case 'q': 10003e12c5d1SDavid du Colombier verbose = 0; 10013e12c5d1SDavid du Colombier break; 10023e12c5d1SDavid du Colombier 10033e12c5d1SDavid du Colombier default: 10043e12c5d1SDavid du Colombier usage(); 10053e12c5d1SDavid du Colombier } ARGEND 10063e12c5d1SDavid du Colombier 10073e12c5d1SDavid du Colombier if(Binit(&bin, 0, OREAD) == Beof || Binit(&bout, 1, OWRITE) == Beof){ 10083e12c5d1SDavid du Colombier fprint(2, "%s: can't init bio: %r\n", argv0); 10093e12c5d1SDavid du Colombier exits("Binit"); 10103e12c5d1SDavid du Colombier } 10113e12c5d1SDavid du Colombier 10123e12c5d1SDavid du Colombier memset(&target, 0, sizeof(target)); 10133e12c5d1SDavid du Colombier if(argc && cmdopen(&target, argc, argv) == -1) 10143e12c5d1SDavid du Colombier usage(); 10153e12c5d1SDavid du Colombier Bflush(&bout); 10163e12c5d1SDavid du Colombier 10173e12c5d1SDavid du Colombier while(ap = Brdline(&bin, '\n')){ 10183e12c5d1SDavid du Colombier ap[BLINELEN(&bin)-1] = 0; 1019*219b2ee8SDavid du Colombier switch(ac = parse(ap, av, nelem(av))){ 10203e12c5d1SDavid du Colombier 10213e12c5d1SDavid du Colombier default: 10223e12c5d1SDavid du Colombier for(cp = scsicmd; cp->name; cp++){ 10233e12c5d1SDavid du Colombier if(strcmp(cp->name, av[0]) == 0) 10243e12c5d1SDavid du Colombier break; 10253e12c5d1SDavid du Colombier } 10263e12c5d1SDavid du Colombier if(cp->name == 0){ 10273e12c5d1SDavid du Colombier Bprint(&bout, "eh?\n"); 10283e12c5d1SDavid du Colombier break; 10293e12c5d1SDavid du Colombier } 10303e12c5d1SDavid du Colombier if((target.flags & Fopen) == 0 && cp->open){ 10313e12c5d1SDavid du Colombier Bprint(&bout, "no current target\n"); 10323e12c5d1SDavid du Colombier break; 10333e12c5d1SDavid du Colombier } 10343e12c5d1SDavid du Colombier if((status = (*cp->f)(&target, ac-1, &av[1])) != -1){ 10353e12c5d1SDavid du Colombier if(verbose) 10363e12c5d1SDavid du Colombier Bprint(&bout, "ok %ld\n", status); 10373e12c5d1SDavid du Colombier break; 10383e12c5d1SDavid du Colombier } 10393e12c5d1SDavid du Colombier switch(target.status){ 10403e12c5d1SDavid du Colombier 10413e12c5d1SDavid du Colombier case Status_OK: 10423e12c5d1SDavid du Colombier if(verbose) 10433e12c5d1SDavid du Colombier Bprint(&bout, "ok %ld\n", status); 10443e12c5d1SDavid du Colombier break; 10453e12c5d1SDavid du Colombier 10463e12c5d1SDavid du Colombier case Status_SD: 10473e12c5d1SDavid du Colombier makesense(&target); 10483e12c5d1SDavid du Colombier break; 10493e12c5d1SDavid du Colombier 10503e12c5d1SDavid du Colombier case Status_NX: 10513e12c5d1SDavid du Colombier Bprint(&bout, "select timeout\n"); 10523e12c5d1SDavid du Colombier break; 10533e12c5d1SDavid du Colombier 10543e12c5d1SDavid du Colombier case Status_HW: 10553e12c5d1SDavid du Colombier Bprint(&bout, "hardware error\n"); 10563e12c5d1SDavid du Colombier break; 10573e12c5d1SDavid du Colombier 10583e12c5d1SDavid du Colombier case Status_SW: 10593e12c5d1SDavid du Colombier Bprint(&bout, "software error\n"); 10603e12c5d1SDavid du Colombier break; 10613e12c5d1SDavid du Colombier 10623e12c5d1SDavid du Colombier case Status_BADARG: 10633e12c5d1SDavid du Colombier Bprint(&bout, "bad argument\n"); 10643e12c5d1SDavid du Colombier break; 10653e12c5d1SDavid du Colombier 10663e12c5d1SDavid du Colombier case Status_RO: 10673e12c5d1SDavid du Colombier Bprint(&bout, "device is read-only\n"); 10683e12c5d1SDavid du Colombier break; 10693e12c5d1SDavid du Colombier 10703e12c5d1SDavid du Colombier default: 10713e12c5d1SDavid du Colombier Bprint(&bout, "status %ld #%2.2ux\n", status, target.status); 10723e12c5d1SDavid du Colombier break; 10733e12c5d1SDavid du Colombier } 10743e12c5d1SDavid du Colombier break; 10753e12c5d1SDavid du Colombier 10763e12c5d1SDavid du Colombier case -1: 10773e12c5d1SDavid du Colombier Bprint(&bout, "eh?\n"); 10783e12c5d1SDavid du Colombier break; 10793e12c5d1SDavid du Colombier 10803e12c5d1SDavid du Colombier case 0: 10813e12c5d1SDavid du Colombier break; 10823e12c5d1SDavid du Colombier } 10833e12c5d1SDavid du Colombier Bflush(&bout); 10843e12c5d1SDavid du Colombier } 10853e12c5d1SDavid du Colombier exits(0); 10863e12c5d1SDavid du Colombier } 10873e12c5d1SDavid du Colombier 1088