13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <bio.h>
4*fd362a73SDavid du Colombier #include <disk.h>
53e12c5d1SDavid du Colombier #include "scsireq.h"
63e12c5d1SDavid du Colombier
7e6dcbf51SDavid du Colombier enum { /* fundamental constants/defaults */
8e6dcbf51SDavid du Colombier /*
9e6dcbf51SDavid du Colombier * default & maximum `maximum i/o size'; overridden by -m.
10e6dcbf51SDavid du Colombier * limits kernel memory consumption.
11e6dcbf51SDavid du Colombier * 240K is exabyte maximum block size.
12e6dcbf51SDavid du Colombier */
13e6dcbf51SDavid du Colombier MaxIOsize = 240*1024,
14e6dcbf51SDavid du Colombier };
15e6dcbf51SDavid du Colombier
163e12c5d1SDavid du Colombier #define MIN(a, b) ((a) < (b) ? (a): (b))
173e12c5d1SDavid du Colombier
183e12c5d1SDavid du Colombier static char rwbuf[MaxIOsize];
193e12c5d1SDavid du Colombier static int verbose = 1;
20968130a0SDavid du Colombier
21968130a0SDavid du Colombier Biobuf bin, bout;
2280ee5cbfSDavid du Colombier long maxiosize = MaxIOsize;
23968130a0SDavid du Colombier int exabyte = 0;
24968130a0SDavid du Colombier int force6bytecmds = 0;
253e12c5d1SDavid du Colombier
263e12c5d1SDavid du Colombier typedef struct {
273e12c5d1SDavid du Colombier char *name;
283e12c5d1SDavid du Colombier long (*f)(ScsiReq *, int, char *[]);
293e12c5d1SDavid du Colombier int open;
303e12c5d1SDavid du Colombier char *help;
313e12c5d1SDavid du Colombier } ScsiCmd;
32968130a0SDavid du Colombier
33*fd362a73SDavid du Colombier static ScsiCmd scsicmds[];
343e12c5d1SDavid du Colombier
35968130a0SDavid du Colombier static vlong
vlmin(vlong a,vlong b)36968130a0SDavid du Colombier vlmin(vlong a, vlong b)
37968130a0SDavid du Colombier {
38968130a0SDavid du Colombier if (a < b)
39968130a0SDavid du Colombier return a;
40968130a0SDavid du Colombier else
41968130a0SDavid du Colombier return b;
42968130a0SDavid du Colombier }
43968130a0SDavid du Colombier
443e12c5d1SDavid du Colombier static long
cmdready(ScsiReq * rp,int argc,char * argv[])453e12c5d1SDavid du Colombier cmdready(ScsiReq *rp, int argc, char *argv[])
463e12c5d1SDavid du Colombier {
473e12c5d1SDavid du Colombier USED(argc, argv);
483e12c5d1SDavid du Colombier return SRready(rp);
493e12c5d1SDavid du Colombier }
503e12c5d1SDavid du Colombier
513e12c5d1SDavid du Colombier static long
cmdrewind(ScsiReq * rp,int argc,char * argv[])523e12c5d1SDavid du Colombier cmdrewind(ScsiReq *rp, int argc, char *argv[])
533e12c5d1SDavid du Colombier {
543e12c5d1SDavid du Colombier USED(argc, argv);
553e12c5d1SDavid du Colombier return SRrewind(rp);
563e12c5d1SDavid du Colombier }
573e12c5d1SDavid du Colombier
583e12c5d1SDavid du Colombier static long
cmdreqsense(ScsiReq * rp,int argc,char * argv[])593e12c5d1SDavid du Colombier cmdreqsense(ScsiReq *rp, int argc, char *argv[])
603e12c5d1SDavid du Colombier {
613e12c5d1SDavid du Colombier long nbytes;
623e12c5d1SDavid du Colombier
633e12c5d1SDavid du Colombier USED(argc, argv);
643e12c5d1SDavid du Colombier if((nbytes = SRreqsense(rp)) != -1)
653e12c5d1SDavid du Colombier makesense(rp);
663e12c5d1SDavid du Colombier return nbytes;
673e12c5d1SDavid du Colombier }
683e12c5d1SDavid du Colombier
693e12c5d1SDavid du Colombier static long
cmdformat(ScsiReq * rp,int argc,char * argv[])703e12c5d1SDavid du Colombier cmdformat(ScsiReq *rp, int argc, char *argv[])
713e12c5d1SDavid du Colombier {
723e12c5d1SDavid du Colombier USED(argc, argv);
733e12c5d1SDavid du Colombier return SRformat(rp);
743e12c5d1SDavid du Colombier }
753e12c5d1SDavid du Colombier
763e12c5d1SDavid du Colombier static long
cmdrblimits(ScsiReq * rp,int argc,char * argv[])773e12c5d1SDavid du Colombier cmdrblimits(ScsiReq *rp, int argc, char *argv[])
783e12c5d1SDavid du Colombier {
793e12c5d1SDavid du Colombier uchar l[6];
803e12c5d1SDavid du Colombier long n;
813e12c5d1SDavid du Colombier
823e12c5d1SDavid du Colombier USED(argc, argv);
833e12c5d1SDavid du Colombier if((n = SRrblimits(rp, l)) == -1)
843e12c5d1SDavid du Colombier return -1;
857dd7cddfSDavid du Colombier Bprint(&bout, " %2.2uX %2.2uX %2.2uX %2.2uX %2.2uX %2.2uX\n",
863e12c5d1SDavid du Colombier l[0], l[1], l[2], l[3], l[4], l[5]);
873e12c5d1SDavid du Colombier return n;
883e12c5d1SDavid du Colombier }
893e12c5d1SDavid du Colombier
903e12c5d1SDavid du Colombier static int
mkfile(char * file,int omode,int * pid)913e12c5d1SDavid du Colombier mkfile(char *file, int omode, int *pid)
923e12c5d1SDavid du Colombier {
933e12c5d1SDavid du Colombier int fd[2];
943e12c5d1SDavid du Colombier
953e12c5d1SDavid du Colombier if(*file != '|'){
963e12c5d1SDavid du Colombier *pid = -1;
973e12c5d1SDavid du Colombier if(omode == OWRITE)
983e12c5d1SDavid du Colombier return create(file, OWRITE, 0666);
993e12c5d1SDavid du Colombier else if(omode == OREAD)
1003e12c5d1SDavid du Colombier return open(file, OREAD);
1013e12c5d1SDavid du Colombier return -1;
1023e12c5d1SDavid du Colombier }
1033e12c5d1SDavid du Colombier
1043e12c5d1SDavid du Colombier file++;
1053e12c5d1SDavid du Colombier if(*file == 0 || pipe(fd) == -1)
1063e12c5d1SDavid du Colombier return -1;
1073e12c5d1SDavid du Colombier if((*pid = fork()) == -1){
1083e12c5d1SDavid du Colombier close(fd[0]);
1097dd7cddfSDavid du Colombier close(fd[1]);
1103e12c5d1SDavid du Colombier return -1;
1113e12c5d1SDavid du Colombier }
1123e12c5d1SDavid du Colombier if(*pid == 0){
1133e12c5d1SDavid du Colombier switch(omode){
1143e12c5d1SDavid du Colombier
1153e12c5d1SDavid du Colombier case OREAD:
1163e12c5d1SDavid du Colombier dup(fd[0], 1);
1173e12c5d1SDavid du Colombier break;
1183e12c5d1SDavid du Colombier
1193e12c5d1SDavid du Colombier case OWRITE:
1203e12c5d1SDavid du Colombier dup(fd[0], 0);
1213e12c5d1SDavid du Colombier break;
1223e12c5d1SDavid du Colombier }
1233e12c5d1SDavid du Colombier close(fd[0]);
1243e12c5d1SDavid du Colombier close(fd[1]);
125f19e7b74SDavid du Colombier execl("/bin/rc", "rc", "-c", file, nil);
1263e12c5d1SDavid du Colombier exits("exec");
1273e12c5d1SDavid du Colombier }
1283e12c5d1SDavid du Colombier close(fd[0]);
1293e12c5d1SDavid du Colombier return fd[1];
1303e12c5d1SDavid du Colombier }
1313e12c5d1SDavid du Colombier
1323e12c5d1SDavid du Colombier int
waitfor(int pid)1333e12c5d1SDavid du Colombier waitfor(int pid)
1343e12c5d1SDavid du Colombier {
1359a747e4fSDavid du Colombier int msg;
1369a747e4fSDavid du Colombier Waitmsg *w;
1373e12c5d1SDavid du Colombier
1389a747e4fSDavid du Colombier while((w = wait()) != nil){
1399a747e4fSDavid du Colombier if(w->pid != pid){
1409a747e4fSDavid du Colombier free(w);
1419a747e4fSDavid du Colombier continue;
1429a747e4fSDavid du Colombier }
1439a747e4fSDavid du Colombier msg = (w->msg[0] != '\0');
1449a747e4fSDavid du Colombier free(w);
1459a747e4fSDavid du Colombier return msg;
1469a747e4fSDavid du Colombier }
1479a747e4fSDavid du Colombier return -1;
1483e12c5d1SDavid du Colombier }
1493e12c5d1SDavid du Colombier
1503e12c5d1SDavid du Colombier static long
cmdread(ScsiReq * rp,int argc,char * argv[])1513e12c5d1SDavid du Colombier cmdread(ScsiReq *rp, int argc, char *argv[])
1523e12c5d1SDavid du Colombier {
153968130a0SDavid du Colombier long n, iosize, prevsize = 0;
15480ee5cbfSDavid du Colombier vlong nbytes, total;
1553e12c5d1SDavid du Colombier int fd, pid;
1563e12c5d1SDavid du Colombier char *p;
1573e12c5d1SDavid du Colombier
15880ee5cbfSDavid du Colombier iosize = maxiosize;
1598e5b7f3bSDavid du Colombier nbytes = ~0ULL >> 1;
1603e12c5d1SDavid du Colombier switch(argc){
1613e12c5d1SDavid du Colombier
1623e12c5d1SDavid du Colombier default:
1633e12c5d1SDavid du Colombier rp->status = Status_BADARG;
1643e12c5d1SDavid du Colombier return -1;
1653e12c5d1SDavid du Colombier
1663e12c5d1SDavid du Colombier case 2:
16780ee5cbfSDavid du Colombier nbytes = strtoll(argv[1], &p, 0);
16880ee5cbfSDavid du Colombier if(nbytes == 0 && p == argv[1]){
1693e12c5d1SDavid du Colombier rp->status = Status_BADARG;
1703e12c5d1SDavid du Colombier return -1;
1713e12c5d1SDavid du Colombier }
1723e12c5d1SDavid du Colombier /*FALLTHROUGH*/
1733e12c5d1SDavid du Colombier
1743e12c5d1SDavid du Colombier case 1:
1753e12c5d1SDavid du Colombier if((fd = mkfile(argv[0], OWRITE, &pid)) == -1){
1763e12c5d1SDavid du Colombier rp->status = Status_BADARG;
1773e12c5d1SDavid du Colombier return -1;
1783e12c5d1SDavid du Colombier }
1793e12c5d1SDavid du Colombier break;
1803e12c5d1SDavid du Colombier }
1817d7728c9SDavid du Colombier print("device native block size=%lud\n", rp->lbsize);
1823e12c5d1SDavid du Colombier total = 0;
1833e12c5d1SDavid du Colombier while(nbytes){
184968130a0SDavid du Colombier n = vlmin(nbytes, iosize);
185968130a0SDavid du Colombier if((n = SRread(rp, rwbuf, n)) == -1){
1863e12c5d1SDavid du Colombier if(total == 0)
1873e12c5d1SDavid du Colombier total = -1;
1883e12c5d1SDavid du Colombier break;
1893e12c5d1SDavid du Colombier }
190968130a0SDavid du Colombier if (n == 0)
191968130a0SDavid du Colombier break;
192968130a0SDavid du Colombier if (prevsize != n) {
193968130a0SDavid du Colombier print("tape block size=%ld\n", n);
194968130a0SDavid du Colombier prevsize = n;
195968130a0SDavid du Colombier }
1963e12c5d1SDavid du Colombier if(write(fd, rwbuf, n) != n){
1973e12c5d1SDavid du Colombier if(total == 0)
1983e12c5d1SDavid du Colombier total = -1;
1997dd7cddfSDavid du Colombier if(rp->status == STok)
2003e12c5d1SDavid du Colombier rp->status = Status_SW;
2013e12c5d1SDavid du Colombier break;
2023e12c5d1SDavid du Colombier }
2033e12c5d1SDavid du Colombier nbytes -= n;
2043e12c5d1SDavid du Colombier total += n;
2053e12c5d1SDavid du Colombier }
2063e12c5d1SDavid du Colombier close(fd);
2073e12c5d1SDavid du Colombier if(pid >= 0 && waitfor(pid)){
2083e12c5d1SDavid du Colombier rp->status = Status_SW;
2093e12c5d1SDavid du Colombier return -1;
2103e12c5d1SDavid du Colombier }
2113e12c5d1SDavid du Colombier return total;
2123e12c5d1SDavid du Colombier }
2133e12c5d1SDavid du Colombier
2143e12c5d1SDavid du Colombier static long
cmdwrite(ScsiReq * rp,int argc,char * argv[])2153e12c5d1SDavid du Colombier cmdwrite(ScsiReq *rp, int argc, char *argv[])
2163e12c5d1SDavid du Colombier {
217968130a0SDavid du Colombier long n, prevsize = 0;
21880ee5cbfSDavid du Colombier vlong nbytes, total;
2193e12c5d1SDavid du Colombier int fd, pid;
2203e12c5d1SDavid du Colombier char *p;
2213e12c5d1SDavid du Colombier
2228e5b7f3bSDavid du Colombier nbytes = ~0ULL >> 1;
2233e12c5d1SDavid du Colombier switch(argc){
2243e12c5d1SDavid du Colombier
2253e12c5d1SDavid du Colombier default:
2263e12c5d1SDavid du Colombier rp->status = Status_BADARG;
2273e12c5d1SDavid du Colombier return -1;
2283e12c5d1SDavid du Colombier
2293e12c5d1SDavid du Colombier case 2:
23080ee5cbfSDavid du Colombier nbytes = strtoll(argv[1], &p, 0);
23180ee5cbfSDavid du Colombier if(nbytes == 0 && p == argv[1]){
2323e12c5d1SDavid du Colombier rp->status = Status_BADARG;
2333e12c5d1SDavid du Colombier return -1;
2343e12c5d1SDavid du Colombier }
2353e12c5d1SDavid du Colombier /*FALLTHROUGH*/
2363e12c5d1SDavid du Colombier
2373e12c5d1SDavid du Colombier case 1:
2383e12c5d1SDavid du Colombier if((fd = mkfile(argv[0], OREAD, &pid)) == -1){
2393e12c5d1SDavid du Colombier rp->status = Status_BADARG;
2403e12c5d1SDavid du Colombier return -1;
2413e12c5d1SDavid du Colombier }
2423e12c5d1SDavid du Colombier break;
2433e12c5d1SDavid du Colombier }
2443e12c5d1SDavid du Colombier total = 0;
2453e12c5d1SDavid du Colombier while(nbytes){
246968130a0SDavid du Colombier n = vlmin(nbytes, maxiosize);
247968130a0SDavid du Colombier if((n = read(fd, rwbuf, n)) == -1){
2483e12c5d1SDavid du Colombier if(total == 0)
2493e12c5d1SDavid du Colombier total = -1;
2503e12c5d1SDavid du Colombier break;
2513e12c5d1SDavid du Colombier }
252968130a0SDavid du Colombier if (n == 0)
253968130a0SDavid du Colombier break;
254968130a0SDavid du Colombier if (prevsize != n) {
255968130a0SDavid du Colombier print("tape block size=%ld\n", n);
256968130a0SDavid du Colombier prevsize = n;
257968130a0SDavid du Colombier }
2583e12c5d1SDavid du Colombier if(SRwrite(rp, rwbuf, n) != n){
2593e12c5d1SDavid du Colombier if(total == 0)
2603e12c5d1SDavid du Colombier total = -1;
2617dd7cddfSDavid du Colombier if(rp->status == STok)
2623e12c5d1SDavid du Colombier rp->status = Status_SW;
2633e12c5d1SDavid du Colombier break;
2643e12c5d1SDavid du Colombier }
2653e12c5d1SDavid du Colombier nbytes -= n;
2663e12c5d1SDavid du Colombier total += n;
2673e12c5d1SDavid du Colombier }
2683e12c5d1SDavid du Colombier close(fd);
2693e12c5d1SDavid du Colombier if(pid >= 0 && waitfor(pid)){
2703e12c5d1SDavid du Colombier rp->status = Status_SW;
2713e12c5d1SDavid du Colombier return -1;
2723e12c5d1SDavid du Colombier }
2733e12c5d1SDavid du Colombier return total;
2743e12c5d1SDavid du Colombier }
2753e12c5d1SDavid du Colombier
2763e12c5d1SDavid du Colombier static long
cmdseek(ScsiReq * rp,int argc,char * argv[])2773e12c5d1SDavid du Colombier cmdseek(ScsiReq *rp, int argc, char *argv[])
2783e12c5d1SDavid du Colombier {
2793e12c5d1SDavid du Colombier char *p;
2803e12c5d1SDavid du Colombier long offset;
2813e12c5d1SDavid du Colombier int type;
2823e12c5d1SDavid du Colombier
2833e12c5d1SDavid du Colombier type = 0;
2843e12c5d1SDavid du Colombier switch(argc){
2853e12c5d1SDavid du Colombier
2863e12c5d1SDavid du Colombier default:
2873e12c5d1SDavid du Colombier rp->status = Status_BADARG;
2883e12c5d1SDavid du Colombier return -1;
2893e12c5d1SDavid du Colombier
2903e12c5d1SDavid du Colombier case 2:
2913e12c5d1SDavid du Colombier if((type = strtol(argv[1], &p, 0)) == 0 && p == argv[1]){
2923e12c5d1SDavid du Colombier rp->status = Status_BADARG;
2933e12c5d1SDavid du Colombier return -1;
2943e12c5d1SDavid du Colombier }
2953e12c5d1SDavid du Colombier /*FALLTHROUGH*/
2963e12c5d1SDavid du Colombier
2973e12c5d1SDavid du Colombier case 1:
2983e12c5d1SDavid du Colombier if((offset = strtol(argv[0], &p, 0)) == 0 && p == argv[0]){
2993e12c5d1SDavid du Colombier rp->status = Status_BADARG;
3003e12c5d1SDavid du Colombier return -1;
3013e12c5d1SDavid du Colombier }
3023e12c5d1SDavid du Colombier break;
3033e12c5d1SDavid du Colombier }
3043e12c5d1SDavid du Colombier return SRseek(rp, offset, type);
3053e12c5d1SDavid du Colombier }
3063e12c5d1SDavid du Colombier
3073e12c5d1SDavid du Colombier static long
cmdfilemark(ScsiReq * rp,int argc,char * argv[])3083e12c5d1SDavid du Colombier cmdfilemark(ScsiReq *rp, int argc, char *argv[])
3093e12c5d1SDavid du Colombier {
3103e12c5d1SDavid du Colombier char *p;
3113e12c5d1SDavid du Colombier ulong howmany;
3123e12c5d1SDavid du Colombier
3133e12c5d1SDavid du Colombier howmany = 1;
3143e12c5d1SDavid du Colombier if(argc && (howmany = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){
3153e12c5d1SDavid du Colombier rp->status = Status_BADARG;
3163e12c5d1SDavid du Colombier return -1;
3173e12c5d1SDavid du Colombier }
3183e12c5d1SDavid du Colombier return SRfilemark(rp, howmany);
3193e12c5d1SDavid du Colombier }
3203e12c5d1SDavid du Colombier
3213e12c5d1SDavid du Colombier static long
cmdspace(ScsiReq * rp,int argc,char * argv[])3223e12c5d1SDavid du Colombier cmdspace(ScsiReq *rp, int argc, char *argv[])
3233e12c5d1SDavid du Colombier {
3243e12c5d1SDavid du Colombier uchar code;
3253e12c5d1SDavid du Colombier long howmany;
3263e12c5d1SDavid du Colombier char option, *p;
3273e12c5d1SDavid du Colombier
3283e12c5d1SDavid du Colombier code = 0x00;
3293e12c5d1SDavid du Colombier howmany = 1;
3303e12c5d1SDavid du Colombier while(argc && (*argv)[0] == '-'){
3313e12c5d1SDavid du Colombier while(option = *++argv[0]){
3323e12c5d1SDavid du Colombier switch(option){
3333e12c5d1SDavid du Colombier
3343e12c5d1SDavid du Colombier case '-':
3353e12c5d1SDavid du Colombier break;
3363e12c5d1SDavid du Colombier
3373e12c5d1SDavid du Colombier case 'b':
3383e12c5d1SDavid du Colombier code = 0x00;
3393e12c5d1SDavid du Colombier break;
3403e12c5d1SDavid du Colombier
3413e12c5d1SDavid du Colombier case 'f':
3423e12c5d1SDavid du Colombier code = 0x01;
3433e12c5d1SDavid du Colombier break;
3443e12c5d1SDavid du Colombier
3453e12c5d1SDavid du Colombier default:
3463e12c5d1SDavid du Colombier rp->status = Status_BADARG;
3473e12c5d1SDavid du Colombier return -1;
3483e12c5d1SDavid du Colombier }
3493e12c5d1SDavid du Colombier break;
3503e12c5d1SDavid du Colombier }
3513e12c5d1SDavid du Colombier argc--; argv++;
3523e12c5d1SDavid du Colombier if(option == '-')
3533e12c5d1SDavid du Colombier break;
3543e12c5d1SDavid du Colombier }
3557dd7cddfSDavid du Colombier if(argc && ((howmany = strtol(argv[0], &p, 0)) == 0 && p == argv[0])){
3563e12c5d1SDavid du Colombier rp->status = Status_BADARG;
3573e12c5d1SDavid du Colombier return -1;
3583e12c5d1SDavid du Colombier }
3593e12c5d1SDavid du Colombier return SRspace(rp, code, howmany);
3603e12c5d1SDavid du Colombier }
3613e12c5d1SDavid du Colombier
3623e12c5d1SDavid du Colombier static long
cmdinquiry(ScsiReq * rp,int argc,char * argv[])3633e12c5d1SDavid du Colombier cmdinquiry(ScsiReq *rp, int argc, char *argv[])
3643e12c5d1SDavid du Colombier {
3653e12c5d1SDavid du Colombier long status;
3663e12c5d1SDavid du Colombier int i, n;
3673e12c5d1SDavid du Colombier uchar *p;
3683e12c5d1SDavid du Colombier
3693e12c5d1SDavid du Colombier USED(argc, argv);
3703e12c5d1SDavid du Colombier if((status = SRinquiry(rp)) != -1){
3713e12c5d1SDavid du Colombier n = rp->inquiry[4]+4;
3723e12c5d1SDavid du Colombier for(i = 0; i < MIN(8, n); i++)
3737dd7cddfSDavid du Colombier Bprint(&bout, " %2.2uX", rp->inquiry[i]);
3743e12c5d1SDavid du Colombier p = &rp->inquiry[8];
3753e12c5d1SDavid du Colombier n = MIN(n, sizeof(rp->inquiry)-8);
3763e12c5d1SDavid du Colombier while(n && (*p == ' ' || *p == '\t' || *p == '\n')){
3773e12c5d1SDavid du Colombier n--;
3783e12c5d1SDavid du Colombier p++;
3793e12c5d1SDavid du Colombier }
3807dd7cddfSDavid du Colombier Bprint(&bout, "\t%.*s\n", n, (char*)p);
3813e12c5d1SDavid du Colombier }
3823e12c5d1SDavid du Colombier return status;
3833e12c5d1SDavid du Colombier }
3843e12c5d1SDavid du Colombier
3853e12c5d1SDavid du Colombier static long
cmdmodeselect6(ScsiReq * rp,int argc,char * argv[])3867dd7cddfSDavid du Colombier cmdmodeselect6(ScsiReq *rp, int argc, char *argv[])
3873e12c5d1SDavid du Colombier {
3883e12c5d1SDavid du Colombier uchar list[MaxDirData];
3893e12c5d1SDavid du Colombier long nbytes, ul;
3903e12c5d1SDavid du Colombier char *p;
3913e12c5d1SDavid du Colombier
392e29d4813SDavid du Colombier memset(list, 0, sizeof list);
3933e12c5d1SDavid du Colombier for(nbytes = 0; argc; argc--, argv++, nbytes++){
3943e12c5d1SDavid du Colombier if((ul = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){
3953e12c5d1SDavid du Colombier rp->status = Status_BADARG;
3963e12c5d1SDavid du Colombier return -1;
3973e12c5d1SDavid du Colombier }
3983e12c5d1SDavid du Colombier list[nbytes] = ul;
3997dd7cddfSDavid du Colombier
4003e12c5d1SDavid du Colombier }
4017dd7cddfSDavid du Colombier if(!(rp->flags & Finqok) && SRinquiry(rp) == -1)
4027dd7cddfSDavid du Colombier Bprint(&bout, "warning: couldn't determine whether SCSI-1/SCSI-2 mode");
4037dd7cddfSDavid du Colombier return SRmodeselect6(rp, list, nbytes);
4043e12c5d1SDavid du Colombier }
4053e12c5d1SDavid du Colombier
4063e12c5d1SDavid du Colombier static long
cmdmodeselect10(ScsiReq * rp,int argc,char * argv[])4077dd7cddfSDavid du Colombier cmdmodeselect10(ScsiReq *rp, int argc, char *argv[])
4087dd7cddfSDavid du Colombier {
4097dd7cddfSDavid du Colombier uchar list[MaxDirData];
4107dd7cddfSDavid du Colombier long nbytes, ul;
4117dd7cddfSDavid du Colombier char *p;
4127dd7cddfSDavid du Colombier
413e29d4813SDavid du Colombier memset(list, 0, sizeof list);
4147dd7cddfSDavid du Colombier for(nbytes = 0; argc; argc--, argv++, nbytes++){
4157dd7cddfSDavid du Colombier if((ul = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){
4167dd7cddfSDavid du Colombier rp->status = Status_BADARG;
4177dd7cddfSDavid du Colombier return -1;
4187dd7cddfSDavid du Colombier }
4197dd7cddfSDavid du Colombier list[nbytes] = ul;
4207dd7cddfSDavid du Colombier
4217dd7cddfSDavid du Colombier }
4227dd7cddfSDavid du Colombier if(!(rp->flags & Finqok) && SRinquiry(rp) == -1)
4237dd7cddfSDavid du Colombier Bprint(&bout, "warning: couldn't determine whether SCSI-1/SCSI-2 mode");
4247dd7cddfSDavid du Colombier return SRmodeselect10(rp, list, nbytes);
4257dd7cddfSDavid du Colombier }
4267dd7cddfSDavid du Colombier
4277dd7cddfSDavid du Colombier static long
cmdmodesense6(ScsiReq * rp,int argc,char * argv[])4287dd7cddfSDavid du Colombier cmdmodesense6(ScsiReq *rp, int argc, char *argv[])
4293e12c5d1SDavid du Colombier {
4303e12c5d1SDavid du Colombier uchar list[MaxDirData], *lp, page;
4317dd7cddfSDavid du Colombier long i, n, nbytes, status;
4323e12c5d1SDavid du Colombier char *p;
4333e12c5d1SDavid du Colombier
434e29d4813SDavid du Colombier nbytes = sizeof list;
4353e12c5d1SDavid du Colombier switch(argc){
4363e12c5d1SDavid du Colombier
4373e12c5d1SDavid du Colombier default:
4383e12c5d1SDavid du Colombier rp->status = Status_BADARG;
4393e12c5d1SDavid du Colombier return -1;
4403e12c5d1SDavid du Colombier
4413e12c5d1SDavid du Colombier case 2:
4423e12c5d1SDavid du Colombier if((nbytes = strtoul(argv[1], &p, 0)) == 0 && p == argv[1]){
4433e12c5d1SDavid du Colombier rp->status = Status_BADARG;
4443e12c5d1SDavid du Colombier return -1;
4453e12c5d1SDavid du Colombier }
4463e12c5d1SDavid du Colombier /*FALLTHROUGH*/
4473e12c5d1SDavid du Colombier
4483e12c5d1SDavid du Colombier case 1:
4493e12c5d1SDavid du Colombier if((page = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){
4503e12c5d1SDavid du Colombier rp->status = Status_BADARG;
4513e12c5d1SDavid du Colombier return -1;
4523e12c5d1SDavid du Colombier }
4533e12c5d1SDavid du Colombier break;
4543e12c5d1SDavid du Colombier
4553e12c5d1SDavid du Colombier case 0:
456e29d4813SDavid du Colombier page = Allmodepages;
4573e12c5d1SDavid du Colombier break;
4583e12c5d1SDavid du Colombier }
4597dd7cddfSDavid du Colombier if((status = SRmodesense6(rp, page, list, nbytes)) == -1)
4603e12c5d1SDavid du Colombier return -1;
4613e12c5d1SDavid du Colombier lp = list;
4627dd7cddfSDavid du Colombier nbytes = list[0];
4637dd7cddfSDavid du Colombier Bprint(&bout, " Header\n ");
4643e12c5d1SDavid du Colombier for(i = 0; i < 4; i++){ /* header */
4657dd7cddfSDavid du Colombier Bprint(&bout, " %2.2uX", *lp);
4663e12c5d1SDavid du Colombier lp++;
4673e12c5d1SDavid du Colombier }
4683e12c5d1SDavid du Colombier Bputc(&bout, '\n');
4697dd7cddfSDavid du Colombier
4707dd7cddfSDavid du Colombier if(list[3]){ /* block descriptors */
4717dd7cddfSDavid du Colombier for(n = 0; n < list[3]/8; n++){
4727dd7cddfSDavid du Colombier Bprint(&bout, " Block %ld\n ", n);
4737dd7cddfSDavid du Colombier for(i = 0; i < 8; i++)
4747dd7cddfSDavid du Colombier Bprint(&bout, " %2.2uX", lp[i]);
4757dd7cddfSDavid du Colombier Bprint(&bout, " (density %2.2uX", lp[0]);
4767dd7cddfSDavid du Colombier Bprint(&bout, " blocks %d", (lp[1]<<16)|(lp[2]<<8)|lp[3]);
4777dd7cddfSDavid du Colombier Bprint(&bout, " length %d)", (lp[5]<<16)|(lp[6]<<8)|lp[7]);
4787dd7cddfSDavid du Colombier lp += 8;
4793e12c5d1SDavid du Colombier nbytes -= 8;
4803e12c5d1SDavid du Colombier Bputc(&bout, '\n');
4817dd7cddfSDavid du Colombier }
4827dd7cddfSDavid du Colombier }
4837dd7cddfSDavid du Colombier
4847dd7cddfSDavid du Colombier while(nbytes > 0){ /* pages */
4853e12c5d1SDavid du Colombier i = *(lp+1);
4863e12c5d1SDavid du Colombier nbytes -= i+2;
4877dd7cddfSDavid du Colombier Bprint(&bout, " Page %2.2uX %d\n ", *lp & 0x3F, *(lp+1));
4883e12c5d1SDavid du Colombier lp += 2;
4897dd7cddfSDavid du Colombier for(n = 0; n < i; n++){
4907dd7cddfSDavid du Colombier if(n && ((n & 0x0F) == 0))
4917dd7cddfSDavid du Colombier Bprint(&bout, "\n ");
4927dd7cddfSDavid du Colombier Bprint(&bout, " %2.2uX", *lp);
4937dd7cddfSDavid du Colombier lp++;
4947dd7cddfSDavid du Colombier }
4957dd7cddfSDavid du Colombier if(n && (n & 0x0F))
4967dd7cddfSDavid du Colombier Bputc(&bout, '\n');
4977dd7cddfSDavid du Colombier }
4987dd7cddfSDavid du Colombier return status;
4997dd7cddfSDavid du Colombier }
5007dd7cddfSDavid du Colombier
5017dd7cddfSDavid du Colombier static long
cmdmodesense10(ScsiReq * rp,int argc,char * argv[])5027dd7cddfSDavid du Colombier cmdmodesense10(ScsiReq *rp, int argc, char *argv[])
5037dd7cddfSDavid du Colombier {
5047dd7cddfSDavid du Colombier uchar *list, *lp, page;
5057dd7cddfSDavid du Colombier long blen, i, n, nbytes, status;
5067dd7cddfSDavid du Colombier char *p;
5077dd7cddfSDavid du Colombier
5087dd7cddfSDavid du Colombier nbytes = MaxDirData;
5097dd7cddfSDavid du Colombier switch(argc){
5107dd7cddfSDavid du Colombier default:
5117dd7cddfSDavid du Colombier rp->status = Status_BADARG;
5127dd7cddfSDavid du Colombier return -1;
5137dd7cddfSDavid du Colombier
5147dd7cddfSDavid du Colombier case 2:
5157dd7cddfSDavid du Colombier if((nbytes = strtoul(argv[1], &p, 0)) == 0 && p == argv[1]){
5167dd7cddfSDavid du Colombier rp->status = Status_BADARG;
5177dd7cddfSDavid du Colombier return -1;
5187dd7cddfSDavid du Colombier }
5197dd7cddfSDavid du Colombier /*FALLTHROUGH*/
5207dd7cddfSDavid du Colombier case 1:
5217dd7cddfSDavid du Colombier if((page = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){
5227dd7cddfSDavid du Colombier rp->status = Status_BADARG;
5237dd7cddfSDavid du Colombier return -1;
5247dd7cddfSDavid du Colombier }
5257dd7cddfSDavid du Colombier break;
5267dd7cddfSDavid du Colombier
5277dd7cddfSDavid du Colombier case 0:
528e29d4813SDavid du Colombier page = Allmodepages;
5297dd7cddfSDavid du Colombier break;
5307dd7cddfSDavid du Colombier }
5317dd7cddfSDavid du Colombier list = malloc(nbytes);
5327dd7cddfSDavid du Colombier if(list == 0){
5337dd7cddfSDavid du Colombier rp->status = STnomem;
5347dd7cddfSDavid du Colombier return -1;
5357dd7cddfSDavid du Colombier }
5367dd7cddfSDavid du Colombier if((status = SRmodesense10(rp, page, list, nbytes)) == -1)
5377dd7cddfSDavid du Colombier return -1;
5387dd7cddfSDavid du Colombier lp = list;
5397dd7cddfSDavid du Colombier nbytes = ((list[0]<<8)|list[1]);
5407dd7cddfSDavid du Colombier Bprint(&bout, " Header\n ");
5417dd7cddfSDavid du Colombier for(i = 0; i < 8; i++){ /* header */
5427dd7cddfSDavid du Colombier Bprint(&bout, " %2.2uX", *lp);
5433e12c5d1SDavid du Colombier lp++;
5443e12c5d1SDavid du Colombier }
5453e12c5d1SDavid du Colombier Bputc(&bout, '\n');
5467dd7cddfSDavid du Colombier
5477dd7cddfSDavid du Colombier blen = (list[6]<<8)|list[7];
5487dd7cddfSDavid du Colombier if(blen){ /* block descriptors */
5497dd7cddfSDavid du Colombier for(n = 0; n < blen/8; n++){
5507dd7cddfSDavid du Colombier Bprint(&bout, " Block %ld\n ", n);
5517dd7cddfSDavid du Colombier for(i = 0; i < 8; i++)
5527dd7cddfSDavid du Colombier Bprint(&bout, " %2.2uX", lp[i]);
5537dd7cddfSDavid du Colombier Bprint(&bout, " (density %2.2uX", lp[0]);
5547dd7cddfSDavid du Colombier Bprint(&bout, " blocks %d", (lp[1]<<16)|(lp[2]<<8)|lp[3]);
5557dd7cddfSDavid du Colombier Bprint(&bout, " length %d)", (lp[5]<<16)|(lp[6]<<8)|lp[7]);
5567dd7cddfSDavid du Colombier lp += 8;
5577dd7cddfSDavid du Colombier nbytes -= 8;
5587dd7cddfSDavid du Colombier Bputc(&bout, '\n');
5593e12c5d1SDavid du Colombier }
5607dd7cddfSDavid du Colombier }
5617dd7cddfSDavid du Colombier
5627dd7cddfSDavid du Colombier /*
5637dd7cddfSDavid du Colombier * Special for ATA drives, page 0 is the drive info in 16-bit
5647dd7cddfSDavid du Colombier * chunks, little-endian, 256 in total. No decoding for now.
5657dd7cddfSDavid du Colombier */
5667dd7cddfSDavid du Colombier if(page == 0){
5677dd7cddfSDavid du Colombier for(n = 0; n < nbytes; n += 2){
5687dd7cddfSDavid du Colombier if(n && ((n & 0x1F) == 0))
5697dd7cddfSDavid du Colombier Bprint(&bout, "\n");
5707dd7cddfSDavid du Colombier Bprint(&bout, " %4.4uX", (*(lp+1)<<8)|*lp);
5717dd7cddfSDavid du Colombier lp += 2;
5727dd7cddfSDavid du Colombier }
5737dd7cddfSDavid du Colombier Bputc(&bout, '\n');
5747dd7cddfSDavid du Colombier }
575e29d4813SDavid du Colombier else
576e29d4813SDavid du Colombier while(nbytes > 0){ /* pages */
5777dd7cddfSDavid du Colombier i = *(lp+1);
5787dd7cddfSDavid du Colombier nbytes -= i+2;
579e29d4813SDavid du Colombier Bprint(&bout, " Page %2.2uX %d\n ", *lp & 0x3F, lp[1]);
5807dd7cddfSDavid du Colombier lp += 2;
5817dd7cddfSDavid du Colombier for(n = 0; n < i; n++){
5827dd7cddfSDavid du Colombier if(n && ((n & 0x0F) == 0))
5837dd7cddfSDavid du Colombier Bprint(&bout, "\n ");
5847dd7cddfSDavid du Colombier Bprint(&bout, " %2.2uX", *lp);
5857dd7cddfSDavid du Colombier lp++;
5867dd7cddfSDavid du Colombier }
5877dd7cddfSDavid du Colombier if(n && (n & 0x0F))
5887dd7cddfSDavid du Colombier Bputc(&bout, '\n');
5897dd7cddfSDavid du Colombier }
5907dd7cddfSDavid du Colombier free(list);
5913e12c5d1SDavid du Colombier return status;
5923e12c5d1SDavid du Colombier }
5933e12c5d1SDavid du Colombier
5943e12c5d1SDavid du Colombier static long
start(ScsiReq * rp,int argc,char * argv[],uchar code)5953e12c5d1SDavid du Colombier start(ScsiReq *rp, int argc, char *argv[], uchar code)
5963e12c5d1SDavid du Colombier {
5973e12c5d1SDavid du Colombier char *p;
5983e12c5d1SDavid du Colombier
5993e12c5d1SDavid du Colombier if(argc && (code = 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 return SRstart(rp, code);
6043e12c5d1SDavid du Colombier }
6053e12c5d1SDavid du Colombier
6063e12c5d1SDavid du Colombier static long
cmdstart(ScsiReq * rp,int argc,char * argv[])6073e12c5d1SDavid du Colombier cmdstart(ScsiReq *rp, int argc, char *argv[])
6083e12c5d1SDavid du Colombier {
6093e12c5d1SDavid du Colombier return start(rp, argc, argv, 1);
6103e12c5d1SDavid du Colombier }
6113e12c5d1SDavid du Colombier
6123e12c5d1SDavid du Colombier static long
cmdstop(ScsiReq * rp,int argc,char * argv[])6133e12c5d1SDavid du Colombier cmdstop(ScsiReq *rp, int argc, char *argv[])
6143e12c5d1SDavid du Colombier {
6153e12c5d1SDavid du Colombier return start(rp, argc, argv, 0);
6163e12c5d1SDavid du Colombier }
6173e12c5d1SDavid du Colombier
6183e12c5d1SDavid du Colombier static long
cmdeject(ScsiReq * rp,int argc,char * argv[])6193e12c5d1SDavid du Colombier cmdeject(ScsiReq *rp, int argc, char *argv[])
6203e12c5d1SDavid du Colombier {
6213e12c5d1SDavid du Colombier return start(rp, argc, argv, 2);
6223e12c5d1SDavid du Colombier }
6233e12c5d1SDavid du Colombier
6243e12c5d1SDavid du Colombier static long
cmdingest(ScsiReq * rp,int argc,char * argv[])6257dd7cddfSDavid du Colombier cmdingest(ScsiReq *rp, int argc, char *argv[])
6267dd7cddfSDavid du Colombier {
6277dd7cddfSDavid du Colombier return start(rp, argc, argv, 3);
6287dd7cddfSDavid du Colombier }
6297dd7cddfSDavid du Colombier
6307dd7cddfSDavid du Colombier static long
cmdcapacity(ScsiReq * rp,int argc,char * argv[])6313e12c5d1SDavid du Colombier cmdcapacity(ScsiReq *rp, int argc, char *argv[])
6323e12c5d1SDavid du Colombier {
6337dd7cddfSDavid du Colombier uchar d[8];
6343e12c5d1SDavid du Colombier long n;
6353e12c5d1SDavid du Colombier
6363e12c5d1SDavid du Colombier USED(argc, argv);
6373e12c5d1SDavid du Colombier if((n = SRrcapacity(rp, d)) == -1)
6383e12c5d1SDavid du Colombier return -1;
6397dd7cddfSDavid du Colombier Bprint(&bout, " %ud %ud\n",
6407dd7cddfSDavid du Colombier d[0]<<24|d[1]<<16|d[2]<<8|d[3],
6413e12c5d1SDavid du Colombier d[4]<<24|d[5]<<16|d[6]<<8|d[7]);
6423e12c5d1SDavid du Colombier return n;
6433e12c5d1SDavid du Colombier }
6443e12c5d1SDavid du Colombier
6453e12c5d1SDavid du Colombier static long
cmdblank(ScsiReq * rp,int argc,char * argv[])6467dd7cddfSDavid du Colombier cmdblank(ScsiReq *rp, int argc, char *argv[])
6473e12c5d1SDavid du Colombier {
6487dd7cddfSDavid du Colombier uchar type, track;
6493e12c5d1SDavid du Colombier char *sp;
6503e12c5d1SDavid du Colombier
6517dd7cddfSDavid du Colombier type = track = 0;
6523e12c5d1SDavid du Colombier switch(argc){
6533e12c5d1SDavid du Colombier
6543e12c5d1SDavid du Colombier default:
6553e12c5d1SDavid du Colombier rp->status = Status_BADARG;
6563e12c5d1SDavid du Colombier return -1;
6573e12c5d1SDavid du Colombier
6583e12c5d1SDavid du Colombier case 2:
6597dd7cddfSDavid du Colombier if((type = strtoul(argv[1], &sp, 0)) == 0 && sp == argv[1]){
6607dd7cddfSDavid du Colombier rp->status = Status_BADARG;
6617dd7cddfSDavid du Colombier return -1;
6627dd7cddfSDavid du Colombier }
663968130a0SDavid du Colombier if(type > 6){
6643e12c5d1SDavid du Colombier rp->status = Status_BADARG;
6653e12c5d1SDavid du Colombier return -1;
6663e12c5d1SDavid du Colombier }
6673e12c5d1SDavid du Colombier /*FALLTHROUGH*/
6683e12c5d1SDavid du Colombier
6693e12c5d1SDavid du Colombier case 1:
6703e12c5d1SDavid du Colombier if((track = strtoul(argv[0], &sp, 0)) == 0 && sp == argv[0]){
6713e12c5d1SDavid du Colombier rp->status = Status_BADARG;
6723e12c5d1SDavid du Colombier return -1;
6733e12c5d1SDavid du Colombier }
6743e12c5d1SDavid du Colombier /*FALLTHROUGH*/
6753e12c5d1SDavid du Colombier
6763e12c5d1SDavid du Colombier case 0:
6773e12c5d1SDavid du Colombier break;
6783e12c5d1SDavid du Colombier }
6797dd7cddfSDavid du Colombier return SRblank(rp, type, track);
6807dd7cddfSDavid du Colombier }
6817dd7cddfSDavid du Colombier
6827dd7cddfSDavid du Colombier static long
cmdsynccache(ScsiReq * rp,int argc,char * argv[])6837dd7cddfSDavid du Colombier cmdsynccache(ScsiReq *rp, int argc, char *argv[])
6847dd7cddfSDavid du Colombier {
6857dd7cddfSDavid du Colombier USED(argc, argv);
6867dd7cddfSDavid du Colombier return SRsynccache(rp);
6877dd7cddfSDavid du Colombier }
6887dd7cddfSDavid du Colombier
6897dd7cddfSDavid du Colombier static long
cmdrtoc(ScsiReq * rp,int argc,char * argv[])6907dd7cddfSDavid du Colombier cmdrtoc(ScsiReq *rp, int argc, char *argv[])
6917dd7cddfSDavid du Colombier {
6927dd7cddfSDavid du Colombier uchar d[100*8+4], format, track, *p;
6937dd7cddfSDavid du Colombier char *sp;
6947dd7cddfSDavid du Colombier long n, nbytes;
6957dd7cddfSDavid du Colombier int tdl;
6967dd7cddfSDavid du Colombier
6977dd7cddfSDavid du Colombier format = track = 0;
6987dd7cddfSDavid du Colombier switch(argc){
6997dd7cddfSDavid du Colombier
7007dd7cddfSDavid du Colombier default:
7017dd7cddfSDavid du Colombier rp->status = Status_BADARG;
7023e12c5d1SDavid du Colombier return -1;
7037dd7cddfSDavid du Colombier
7047dd7cddfSDavid du Colombier case 2:
7057dd7cddfSDavid du Colombier if((format = strtoul(argv[1], &sp, 0)) == 0 && sp == argv[1]){
7067dd7cddfSDavid du Colombier rp->status = Status_BADARG;
7077dd7cddfSDavid du Colombier return -1;
7087dd7cddfSDavid du Colombier }
709968130a0SDavid du Colombier if(format > 4){
7107dd7cddfSDavid du Colombier rp->status = Status_BADARG;
7117dd7cddfSDavid du Colombier return -1;
7127dd7cddfSDavid du Colombier }
7137dd7cddfSDavid du Colombier /*FALLTHROUGH*/
7147dd7cddfSDavid du Colombier
7157dd7cddfSDavid du Colombier case 1:
7167dd7cddfSDavid du Colombier if((track = strtoul(argv[0], &sp, 0)) == 0 && sp == argv[0]){
7177dd7cddfSDavid du Colombier rp->status = Status_BADARG;
7187dd7cddfSDavid du Colombier return -1;
7197dd7cddfSDavid du Colombier }
7207dd7cddfSDavid du Colombier /*FALLTHROUGH*/
7217dd7cddfSDavid du Colombier
7227dd7cddfSDavid du Colombier case 0:
7237dd7cddfSDavid du Colombier break;
7247dd7cddfSDavid du Colombier }
725e29d4813SDavid du Colombier if((nbytes = SRTOC(rp, d, sizeof d, format, track)) == -1){
7267dd7cddfSDavid du Colombier if(rp->status == STok)
7277dd7cddfSDavid du Colombier Bprint(&bout, "\t(probably empty)\n");
7287dd7cddfSDavid du Colombier return -1;
7297dd7cddfSDavid du Colombier }
7307dd7cddfSDavid du Colombier tdl = (d[0]<<8)|d[1];
7317dd7cddfSDavid du Colombier switch(format){
7327dd7cddfSDavid du Colombier
7337dd7cddfSDavid du Colombier case 0:
7347dd7cddfSDavid du Colombier Bprint(&bout, "\ttoc/pma data length: 0x%uX\n", tdl);
7353e12c5d1SDavid du Colombier Bprint(&bout, "\tfirst track number: %d\n", d[2]);
7363e12c5d1SDavid du Colombier Bprint(&bout, "\tlast track number: %d\n", d[3]);
7377dd7cddfSDavid du Colombier for(p = &d[4], n = tdl-2; n; n -= 8, p += 8){
7387dd7cddfSDavid du Colombier Bprint(&bout, "\ttrack number: 0x%2.2uX\n", p[2]);
7397dd7cddfSDavid du Colombier Bprint(&bout, "\t\tcontrol: 0x%2.2uX\n", p[1] & 0x0F);
7407dd7cddfSDavid du Colombier Bprint(&bout, "\t\tblock address: 0x%uX\n",
7413e12c5d1SDavid du Colombier (p[4]<<24)|(p[5]<<16)|(p[6]<<8)|p[7]);
7423e12c5d1SDavid du Colombier }
7437dd7cddfSDavid du Colombier break;
7447dd7cddfSDavid du Colombier
7457dd7cddfSDavid du Colombier case 1:
7467dd7cddfSDavid du Colombier Bprint(&bout, "\tsessions data length: 0x%uX\n", tdl);
7473e12c5d1SDavid du Colombier Bprint(&bout, "\tnumber of finished sessions: %d\n", d[2]);
7483e12c5d1SDavid du Colombier Bprint(&bout, "\tunfinished session number: %d\n", d[3]);
7497dd7cddfSDavid du Colombier for(p = &d[4], n = tdl-2; n; n -= 8, p += 8){
7507dd7cddfSDavid du Colombier Bprint(&bout, "\tsession number: 0x%2.2uX\n", p[0]);
7517dd7cddfSDavid du Colombier Bprint(&bout, "\t\tfirst track number in session: 0x%2.2uX\n",
7523e12c5d1SDavid du Colombier p[2]);
7537dd7cddfSDavid du Colombier Bprint(&bout, "\t\tlogical start address: 0x%uX\n",
7543e12c5d1SDavid du Colombier (p[5]<<16)|(p[6]<<8)|p[7]);
7553e12c5d1SDavid du Colombier }
7567dd7cddfSDavid du Colombier break;
7577dd7cddfSDavid du Colombier
7587dd7cddfSDavid du Colombier case 2:
7597dd7cddfSDavid du Colombier Bprint(&bout, "\tfull TOC data length: 0x%uX\n", tdl);
7607dd7cddfSDavid du Colombier Bprint(&bout, "\tnumber of finished sessions: %d\n", d[2]);
7617dd7cddfSDavid du Colombier Bprint(&bout, "\tunfinished session number: %d\n", d[3]);
7627dd7cddfSDavid du Colombier for(p = &d[4], n = tdl-2; n > 0; n -= 11, p += 11){
7637dd7cddfSDavid du Colombier Bprint(&bout, "\tsession number: 0x%2.2uX\n", p[0]);
7647dd7cddfSDavid du Colombier Bprint(&bout, "\t\tcontrol: 0x%2.2uX\n", p[1] & 0x0F);
7657dd7cddfSDavid du Colombier Bprint(&bout, "\t\tADR: 0x%2.2uX\n", (p[1]>>4) & 0x0F);
7667dd7cddfSDavid du Colombier Bprint(&bout, "\t\tTNO: 0x%2.2uX\n", p[2]);
7677dd7cddfSDavid du Colombier Bprint(&bout, "\t\tPOINT: 0x%2.2uX\n", p[3]);
7687dd7cddfSDavid du Colombier Bprint(&bout, "\t\tMin: 0x%2.2uX\n", p[4]);
7697dd7cddfSDavid du Colombier Bprint(&bout, "\t\tSec: 0x%2.2uX\n", p[5]);
7707dd7cddfSDavid du Colombier Bprint(&bout, "\t\tFrame: 0x%2.2uX\n", p[6]);
7717dd7cddfSDavid du Colombier Bprint(&bout, "\t\tZero: 0x%2.2uX\n", p[7]);
7727dd7cddfSDavid du Colombier Bprint(&bout, "\t\tPMIN: 0x%2.2uX\n", p[8]);
7737dd7cddfSDavid du Colombier Bprint(&bout, "\t\tPSEC: 0x%2.2uX\n", p[9]);
7747dd7cddfSDavid du Colombier Bprint(&bout, "\t\tPFRAME: 0x%2.2uX\n", p[10]);
7753e12c5d1SDavid du Colombier }
7767dd7cddfSDavid du Colombier break;
7777dd7cddfSDavid du Colombier case 3:
7787dd7cddfSDavid du Colombier Bprint(&bout, "\tPMA data length: 0x%uX\n", tdl);
7797dd7cddfSDavid du Colombier for(p = &d[4], n = tdl-2; n > 0; n -= 11, p += 11){
7807dd7cddfSDavid du Colombier Bprint(&bout, "\t\tcontrol: 0x%2.2uX\n", p[1] & 0x0F);
7817dd7cddfSDavid du Colombier Bprint(&bout, "\t\tADR: 0x%2.2uX\n", (p[1]>>4) & 0x0F);
7827dd7cddfSDavid du Colombier Bprint(&bout, "\t\tTNO: 0x%2.2uX\n", p[2]);
7837dd7cddfSDavid du Colombier Bprint(&bout, "\t\tPOINT: 0x%2.2uX\n", p[3]);
7847dd7cddfSDavid du Colombier Bprint(&bout, "\t\tMin: 0x%2.2uX\n", p[4]);
7857dd7cddfSDavid du Colombier Bprint(&bout, "\t\tSec: 0x%2.2uX\n", p[5]);
7867dd7cddfSDavid du Colombier Bprint(&bout, "\t\tFrame: 0x%2.2uX\n", p[6]);
7877dd7cddfSDavid du Colombier Bprint(&bout, "\t\tZero: 0x%2.2uX\n", p[7]);
7887dd7cddfSDavid du Colombier Bprint(&bout, "\t\tPMIN: 0x%2.2uX\n", p[8]);
7897dd7cddfSDavid du Colombier Bprint(&bout, "\t\tPSEC: 0x%2.2uX\n", p[9]);
7907dd7cddfSDavid du Colombier Bprint(&bout, "\t\tPFRAME: 0x%2.2uX\n", p[10]);
7917dd7cddfSDavid du Colombier }
7927dd7cddfSDavid du Colombier break;
7937dd7cddfSDavid du Colombier
7947dd7cddfSDavid du Colombier case 4:
7957dd7cddfSDavid du Colombier Bprint(&bout, "\tATIP data length: 0x%uX\n", tdl);
7967dd7cddfSDavid du Colombier break;
7977dd7cddfSDavid du Colombier
7987dd7cddfSDavid du Colombier }
7997dd7cddfSDavid du Colombier for(n = 0; n < nbytes; n++){
8007dd7cddfSDavid du Colombier if(n && ((n & 0x0F) == 0))
8013e12c5d1SDavid du Colombier Bprint(&bout, "\n");
8027dd7cddfSDavid du Colombier Bprint(&bout, " %2.2uX", d[n]);
8037dd7cddfSDavid du Colombier }
8047dd7cddfSDavid du Colombier if(n && (n & 0x0F))
8057dd7cddfSDavid du Colombier Bputc(&bout, '\n');
8063e12c5d1SDavid du Colombier return nbytes;
8073e12c5d1SDavid du Colombier }
8083e12c5d1SDavid du Colombier
8093e12c5d1SDavid du Colombier static long
cmdrdiscinfo(ScsiReq * rp,int argc,char * [])8107dd7cddfSDavid du Colombier cmdrdiscinfo(ScsiReq *rp, int argc, char*[])
8117dd7cddfSDavid du Colombier {
8127dd7cddfSDavid du Colombier uchar d[MaxDirData];
8137dd7cddfSDavid du Colombier int dl;
8147dd7cddfSDavid du Colombier long n, nbytes;
8157dd7cddfSDavid du Colombier
8167dd7cddfSDavid du Colombier switch(argc){
8177dd7cddfSDavid du Colombier
8187dd7cddfSDavid du Colombier default:
8197dd7cddfSDavid du Colombier rp->status = Status_BADARG;
8207dd7cddfSDavid du Colombier return -1;
8217dd7cddfSDavid du Colombier
8227dd7cddfSDavid du Colombier case 0:
8237dd7cddfSDavid du Colombier break;
8247dd7cddfSDavid du Colombier }
825e29d4813SDavid du Colombier if((nbytes = SRrdiscinfo(rp, d, sizeof d)) == -1)
8267dd7cddfSDavid du Colombier return -1;
8277dd7cddfSDavid du Colombier
8287dd7cddfSDavid du Colombier dl = (d[0]<<8)|d[1];
8297dd7cddfSDavid du Colombier Bprint(&bout, "\tdata length: 0x%uX\n", dl);
8307dd7cddfSDavid du Colombier Bprint(&bout, "\tinfo[2] 0x%2.2uX\n", d[2]);
8317dd7cddfSDavid du Colombier switch(d[2] & 0x03){
8327dd7cddfSDavid du Colombier
8337dd7cddfSDavid du Colombier case 0:
8347dd7cddfSDavid du Colombier Bprint(&bout, "\t\tEmpty\n");
8357dd7cddfSDavid du Colombier break;
8367dd7cddfSDavid du Colombier
8377dd7cddfSDavid du Colombier case 1:
8387dd7cddfSDavid du Colombier Bprint(&bout, "\t\tIncomplete disc (Appendable)\n");
8397dd7cddfSDavid du Colombier break;
8407dd7cddfSDavid du Colombier
8417dd7cddfSDavid du Colombier case 2:
8427dd7cddfSDavid du Colombier Bprint(&bout, "\t\tComplete (CD-ROM or last session is closed and has no next session pointer)\n");
8437dd7cddfSDavid du Colombier break;
8447dd7cddfSDavid du Colombier
8457dd7cddfSDavid du Colombier case 3:
8467dd7cddfSDavid du Colombier Bprint(&bout, "\t\tReserved\n");
8477dd7cddfSDavid du Colombier break;
8487dd7cddfSDavid du Colombier }
8497dd7cddfSDavid du Colombier switch((d[2]>>2) & 0x03){
8507dd7cddfSDavid du Colombier
8517dd7cddfSDavid du Colombier case 0:
8527dd7cddfSDavid du Colombier Bprint(&bout, "\t\tEmpty Session\n");
8537dd7cddfSDavid du Colombier break;
8547dd7cddfSDavid du Colombier
8557dd7cddfSDavid du Colombier case 1:
8567dd7cddfSDavid du Colombier Bprint(&bout, "\t\tIncomplete Session\n");
8577dd7cddfSDavid du Colombier break;
8587dd7cddfSDavid du Colombier
8597dd7cddfSDavid du Colombier case 2:
8607dd7cddfSDavid du Colombier Bprint(&bout, "\t\tReserved\n");
8617dd7cddfSDavid du Colombier break;
8627dd7cddfSDavid du Colombier
8637dd7cddfSDavid du Colombier case 3:
8647dd7cddfSDavid du Colombier Bprint(&bout, "\t\tComplete Session (only possible when disc Status is Complete)\n");
8657dd7cddfSDavid du Colombier break;
8667dd7cddfSDavid du Colombier }
8677dd7cddfSDavid du Colombier if(d[2] & 0x10)
8687dd7cddfSDavid du Colombier Bprint(&bout, "\t\tErasable\n");
8697dd7cddfSDavid du Colombier Bprint(&bout, "\tNumber of First Track on Disc %ud\n", d[3]);
8707dd7cddfSDavid du Colombier Bprint(&bout, "\tNumber of Sessions %ud\n", d[4]);
8717dd7cddfSDavid du Colombier Bprint(&bout, "\tFirst Track Number in Last Session %ud\n", d[5]);
8727dd7cddfSDavid du Colombier Bprint(&bout, "\tLast Track Number in Last Session %ud\n", d[6]);
8737dd7cddfSDavid du Colombier Bprint(&bout, "\tinfo[7] 0x%2.2uX\n", d[7]);
8747dd7cddfSDavid du Colombier if(d[7] & 0x20)
8757dd7cddfSDavid du Colombier Bprint(&bout, "\t\tUnrestricted Use Disc\n");
8767dd7cddfSDavid du Colombier if(d[7] & 0x40)
8777dd7cddfSDavid du Colombier Bprint(&bout, "\t\tDisc Bar Code Valid\n");
8787dd7cddfSDavid du Colombier if(d[7] & 0x80)
8797dd7cddfSDavid du Colombier Bprint(&bout, "\t\tDisc ID Valid\n");
8807dd7cddfSDavid du Colombier Bprint(&bout, "\tinfo[8] 0x%2.2uX\n", d[8]);
8817dd7cddfSDavid du Colombier switch(d[8]){
8827dd7cddfSDavid du Colombier
8837dd7cddfSDavid du Colombier case 0x00:
8847dd7cddfSDavid du Colombier Bprint(&bout, "\t\tCD-DA or CD-ROM Disc\n");
8857dd7cddfSDavid du Colombier break;
8867dd7cddfSDavid du Colombier
8877dd7cddfSDavid du Colombier case 0x10:
8887dd7cddfSDavid du Colombier Bprint(&bout, "\t\tCD-I Disc\n");
8897dd7cddfSDavid du Colombier break;
8907dd7cddfSDavid du Colombier
8917dd7cddfSDavid du Colombier case 0x20:
8927dd7cddfSDavid du Colombier Bprint(&bout, "\t\tCD-ROM XA Disc\n");
8937dd7cddfSDavid du Colombier break;
8947dd7cddfSDavid du Colombier
8957dd7cddfSDavid du Colombier case 0xFF:
8967dd7cddfSDavid du Colombier Bprint(&bout, "\t\tUndefined\n");
8977dd7cddfSDavid du Colombier break;
8987dd7cddfSDavid du Colombier
8997dd7cddfSDavid du Colombier default:
9007dd7cddfSDavid du Colombier Bprint(&bout, "\t\tReserved\n");
9017dd7cddfSDavid du Colombier break;
9027dd7cddfSDavid du Colombier }
9037dd7cddfSDavid du Colombier Bprint(&bout, "\tLast Session lead-in Start Time M/S/F: 0x%2.2uX/0x%2.2uX/0x%2.2uX\n",
9047dd7cddfSDavid du Colombier d[17], d[18], d[19]);
9057dd7cddfSDavid du Colombier Bprint(&bout, "\tLast Possible Start Time for Start of lead-out M/S/F: 0x%2.2uX/0x%2.2uX/0x%2.2uX\n",
9067dd7cddfSDavid du Colombier d[21], d[22], d[23]);
9077dd7cddfSDavid du Colombier
9087dd7cddfSDavid du Colombier for(n = 0; n < nbytes; n++){
9097dd7cddfSDavid du Colombier if(n && ((n & 0x0F) == 0))
9107dd7cddfSDavid du Colombier Bprint(&bout, "\n");
9117dd7cddfSDavid du Colombier Bprint(&bout, " %2.2uX", d[n]);
9127dd7cddfSDavid du Colombier }
9137dd7cddfSDavid du Colombier if(n && (n & 0x0F))
9147dd7cddfSDavid du Colombier Bputc(&bout, '\n');
9157dd7cddfSDavid du Colombier
9167dd7cddfSDavid du Colombier return nbytes;
9177dd7cddfSDavid du Colombier }
9187dd7cddfSDavid du Colombier
9197dd7cddfSDavid du Colombier static long
cmdrtrackinfo(ScsiReq * rp,int argc,char * argv[])9207dd7cddfSDavid du Colombier cmdrtrackinfo(ScsiReq *rp, int argc, char *argv[])
9217dd7cddfSDavid du Colombier {
9227dd7cddfSDavid du Colombier uchar d[MaxDirData], track;
9237dd7cddfSDavid du Colombier char *sp;
9247dd7cddfSDavid du Colombier long n, nbytes;
9257dd7cddfSDavid du Colombier int dl;
9267dd7cddfSDavid du Colombier
9277dd7cddfSDavid du Colombier track = 0;
9287dd7cddfSDavid du Colombier switch(argc){
9297dd7cddfSDavid du Colombier
9307dd7cddfSDavid du Colombier default:
9317dd7cddfSDavid du Colombier rp->status = Status_BADARG;
9327dd7cddfSDavid du Colombier return -1;
9337dd7cddfSDavid du Colombier
9347dd7cddfSDavid du Colombier case 1:
9357dd7cddfSDavid du Colombier if((track = strtoul(argv[0], &sp, 0)) == 0 && sp == argv[0]){
9367dd7cddfSDavid du Colombier rp->status = Status_BADARG;
9377dd7cddfSDavid du Colombier return -1;
9387dd7cddfSDavid du Colombier }
9397dd7cddfSDavid du Colombier /*FALLTHROUGH*/
9407dd7cddfSDavid du Colombier
9417dd7cddfSDavid du Colombier case 0:
9427dd7cddfSDavid du Colombier break;
9437dd7cddfSDavid du Colombier }
944e29d4813SDavid du Colombier if((nbytes = SRrtrackinfo(rp, d, sizeof d, track)) == -1)
9457dd7cddfSDavid du Colombier return -1;
9467dd7cddfSDavid du Colombier
9477dd7cddfSDavid du Colombier dl = (d[0]<<8)|d[1];
9487dd7cddfSDavid du Colombier Bprint(&bout, "\tdata length: 0x%uX\n", dl);
9497dd7cddfSDavid du Colombier Bprint(&bout, "\Track Number %d\n", d[2]);
9507dd7cddfSDavid du Colombier Bprint(&bout, "\Session Number %d\n", d[3]);
9517dd7cddfSDavid du Colombier Bprint(&bout, "\tinfo[4] 0x%2.2uX\n", d[5]);
9527dd7cddfSDavid du Colombier Bprint(&bout, "\t\tTrack Mode 0x%2.2uX: ", d[5] & 0x0F);
9537dd7cddfSDavid du Colombier switch(d[5] & 0x0F){
9547dd7cddfSDavid du Colombier case 0x00:
9557dd7cddfSDavid du Colombier case 0x02:
9567dd7cddfSDavid du Colombier Bprint(&bout, "2 audio channels without pre-emphasis\n");
9577dd7cddfSDavid du Colombier break;
9587dd7cddfSDavid du Colombier case 0x01:
9597dd7cddfSDavid du Colombier case 0x03:
9607dd7cddfSDavid du Colombier Bprint(&bout, "2 audio channels with pre-emphasis of 50/15µs\n");
9617dd7cddfSDavid du Colombier break;
9627dd7cddfSDavid du Colombier case 0x08:
9637dd7cddfSDavid du Colombier case 0x0A:
9647dd7cddfSDavid du Colombier Bprint(&bout, "audio channels without pre-emphasis (reserved in CD-R/RW)\n");
9657dd7cddfSDavid du Colombier break;
9667dd7cddfSDavid du Colombier case 0x09:
9677dd7cddfSDavid du Colombier case 0x0B:
9687dd7cddfSDavid du Colombier Bprint(&bout, "audio channels with pre-emphasis of 50/15µs (reserved in CD-R/RW)\n");
9697dd7cddfSDavid du Colombier break;
9707dd7cddfSDavid du Colombier case 0x04:
9717dd7cddfSDavid du Colombier case 0x06:
9727dd7cddfSDavid du Colombier Bprint(&bout, "Data track, recorded uninterrupted\n");
9737dd7cddfSDavid du Colombier break;
9747dd7cddfSDavid du Colombier case 0x05:
9757dd7cddfSDavid du Colombier case 0x07:
9767dd7cddfSDavid du Colombier Bprint(&bout, "Data track, recorded incremental\n");
9777dd7cddfSDavid du Colombier break;
9787dd7cddfSDavid du Colombier default:
9797dd7cddfSDavid du Colombier Bprint(&bout, "(mode unknown)\n");
9807dd7cddfSDavid du Colombier break;
9817dd7cddfSDavid du Colombier }
9827dd7cddfSDavid du Colombier if(d[5] & 0x10)
9837dd7cddfSDavid du Colombier Bprint(&bout, "\t\tCopy\n");
9847dd7cddfSDavid du Colombier if(d[5] & 0x20)
9857dd7cddfSDavid du Colombier Bprint(&bout, "\t\tDamage\n");
9867dd7cddfSDavid du Colombier Bprint(&bout, "\tinfo[6] 0x%2.2uX\n", d[6]);
9877dd7cddfSDavid du Colombier Bprint(&bout, "\t\tData Mode 0x%2.2uX: ", d[6] & 0x0F);
9887dd7cddfSDavid du Colombier switch(d[6] & 0x0F){
9897dd7cddfSDavid du Colombier case 0x01:
9907dd7cddfSDavid du Colombier Bprint(&bout, "Mode 1 (ISO/IEC 10149)\n");
9917dd7cddfSDavid du Colombier break;
9927dd7cddfSDavid du Colombier case 0x02:
9937dd7cddfSDavid du Colombier Bprint(&bout, "Mode 2 (ISO/IEC 10149 or CD-ROM XA)\n");
9947dd7cddfSDavid du Colombier break;
9957dd7cddfSDavid du Colombier case 0x0F:
9967dd7cddfSDavid du Colombier Bprint(&bout, "Data Block Type unknown (no track descriptor block)\n");
9977dd7cddfSDavid du Colombier break;
9987dd7cddfSDavid du Colombier default:
9997dd7cddfSDavid du Colombier Bprint(&bout, "(Reserved)\n");
10007dd7cddfSDavid du Colombier break;
10017dd7cddfSDavid du Colombier }
10027dd7cddfSDavid du Colombier if(d[6] & 0x10)
10037dd7cddfSDavid du Colombier Bprint(&bout, "\t\tFP\n");
10047dd7cddfSDavid du Colombier if(d[6] & 0x20)
10057dd7cddfSDavid du Colombier Bprint(&bout, "\t\tPacket\n");
10067dd7cddfSDavid du Colombier if(d[6] & 0x40)
10077dd7cddfSDavid du Colombier Bprint(&bout, "\t\tBlank\n");
10087dd7cddfSDavid du Colombier if(d[6] & 0x80)
10097dd7cddfSDavid du Colombier Bprint(&bout, "\t\tRT\n");
10107dd7cddfSDavid du Colombier Bprint(&bout, "\tTrack Start Address 0x%8.8uX\n",
10117dd7cddfSDavid du Colombier (d[8]<<24)|(d[9]<<16)|(d[10]<<8)|d[11]);
10127dd7cddfSDavid du Colombier if(d[7] & 0x01)
10137dd7cddfSDavid du Colombier Bprint(&bout, "\tNext Writeable Address 0x%8.8uX\n",
10147dd7cddfSDavid du Colombier (d[12]<<24)|(d[13]<<16)|(d[14]<<8)|d[15]);
10157dd7cddfSDavid du Colombier Bprint(&bout, "\tFree Blocks 0x%8.8uX\n",
10167dd7cddfSDavid du Colombier (d[16]<<24)|(d[17]<<16)|(d[18]<<8)|d[19]);
10177dd7cddfSDavid du Colombier if((d[6] & 0x30) == 0x30)
10187dd7cddfSDavid du Colombier Bprint(&bout, "\tFixed Packet Size 0x%8.8uX\n",
10197dd7cddfSDavid du Colombier (d[20]<<24)|(d[21]<<16)|(d[22]<<8)|d[23]);
10207dd7cddfSDavid du Colombier Bprint(&bout, "\tTrack Size 0x%8.8uX\n",
10217dd7cddfSDavid du Colombier (d[24]<<24)|(d[25]<<16)|(d[26]<<8)|d[27]);
10227dd7cddfSDavid du Colombier
10237dd7cddfSDavid du Colombier for(n = 0; n < nbytes; n++){
10247dd7cddfSDavid du Colombier if(n && ((n & 0x0F) == 0))
10257dd7cddfSDavid du Colombier Bprint(&bout, "\n");
10267dd7cddfSDavid du Colombier Bprint(&bout, " %2.2uX", d[n]);
10277dd7cddfSDavid du Colombier }
10287dd7cddfSDavid du Colombier if(n && (n & 0x0F))
10297dd7cddfSDavid du Colombier Bputc(&bout, '\n');
10307dd7cddfSDavid du Colombier
10317dd7cddfSDavid du Colombier return nbytes;
10327dd7cddfSDavid du Colombier }
10337dd7cddfSDavid du Colombier
10347dd7cddfSDavid du Colombier static long
cmdcdpause(ScsiReq * rp,int argc,char * argv[])10357dd7cddfSDavid du Colombier cmdcdpause(ScsiReq *rp, int argc, char *argv[])
10367dd7cddfSDavid du Colombier {
10377dd7cddfSDavid du Colombier USED(argc, argv);
10387dd7cddfSDavid du Colombier return SRcdpause(rp, 0);
10397dd7cddfSDavid du Colombier }
10407dd7cddfSDavid du Colombier
10417dd7cddfSDavid du Colombier static long
cmdcdresume(ScsiReq * rp,int argc,char * argv[])10427dd7cddfSDavid du Colombier cmdcdresume(ScsiReq *rp, int argc, char *argv[])
10437dd7cddfSDavid du Colombier {
10447dd7cddfSDavid du Colombier USED(argc, argv);
10457dd7cddfSDavid du Colombier return SRcdpause(rp, 1);
10467dd7cddfSDavid du Colombier }
10477dd7cddfSDavid du Colombier
10487dd7cddfSDavid du Colombier static long
cmdcdstop(ScsiReq * rp,int argc,char * argv[])10497dd7cddfSDavid du Colombier cmdcdstop(ScsiReq *rp, int argc, char *argv[])
10507dd7cddfSDavid du Colombier {
10517dd7cddfSDavid du Colombier USED(argc, argv);
10527dd7cddfSDavid du Colombier return SRcdstop(rp);
10537dd7cddfSDavid du Colombier }
10547dd7cddfSDavid du Colombier
10557dd7cddfSDavid du Colombier static long
cmdcdplay(ScsiReq * rp,int argc,char * argv[])10567dd7cddfSDavid du Colombier cmdcdplay(ScsiReq *rp, int argc, char *argv[])
10577dd7cddfSDavid du Colombier {
10587dd7cddfSDavid du Colombier long length, start;
10597dd7cddfSDavid du Colombier char *sp;
10607dd7cddfSDavid du Colombier int raw;
10617dd7cddfSDavid du Colombier
10627dd7cddfSDavid du Colombier raw = 0;
10637dd7cddfSDavid du Colombier start = 0;
10647dd7cddfSDavid du Colombier if(argc && strcmp("-r", argv[0]) == 0){
10657dd7cddfSDavid du Colombier raw = 1;
10667dd7cddfSDavid du Colombier argc--, argv++;
10677dd7cddfSDavid du Colombier }
10687dd7cddfSDavid du Colombier
10697dd7cddfSDavid du Colombier length = 0xFFFFFFFF;
10707dd7cddfSDavid du Colombier switch(argc){
10717dd7cddfSDavid du Colombier
10727dd7cddfSDavid du Colombier default:
10737dd7cddfSDavid du Colombier rp->status = Status_BADARG;
10747dd7cddfSDavid du Colombier return -1;
10757dd7cddfSDavid du Colombier
10767dd7cddfSDavid du Colombier case 2:
10777dd7cddfSDavid du Colombier if(!raw || ((length = strtol(argv[1], &sp, 0)) == 0 && sp == argv[1])){
10787dd7cddfSDavid du Colombier rp->status = Status_BADARG;
10797dd7cddfSDavid du Colombier return -1;
10807dd7cddfSDavid du Colombier }
10817dd7cddfSDavid du Colombier /*FALLTHROUGH*/
10827dd7cddfSDavid du Colombier
10837dd7cddfSDavid du Colombier case 1:
10847dd7cddfSDavid du Colombier if((start = strtol(argv[0], &sp, 0)) == 0 && sp == argv[0]){
10857dd7cddfSDavid du Colombier rp->status = Status_BADARG;
10867dd7cddfSDavid du Colombier return -1;
10877dd7cddfSDavid du Colombier }
10887dd7cddfSDavid du Colombier /*FALLTHROUGH*/
10897dd7cddfSDavid du Colombier
10907dd7cddfSDavid du Colombier case 0:
10917dd7cddfSDavid du Colombier break;
10927dd7cddfSDavid du Colombier }
10937dd7cddfSDavid du Colombier
10947dd7cddfSDavid du Colombier return SRcdplay(rp, raw, start, length);
10957dd7cddfSDavid du Colombier }
10967dd7cddfSDavid du Colombier
10977dd7cddfSDavid du Colombier static long
cmdcdload(ScsiReq * rp,int argc,char * argv[])10987dd7cddfSDavid du Colombier cmdcdload(ScsiReq *rp, int argc, char *argv[])
10997dd7cddfSDavid du Colombier {
11007dd7cddfSDavid du Colombier char *p;
11017dd7cddfSDavid du Colombier ulong slot;
11027dd7cddfSDavid du Colombier
11037dd7cddfSDavid du Colombier slot = 0;
11047dd7cddfSDavid du Colombier if(argc && (slot = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){
11057dd7cddfSDavid du Colombier rp->status = Status_BADARG;
11067dd7cddfSDavid du Colombier return -1;
11077dd7cddfSDavid du Colombier }
11087dd7cddfSDavid du Colombier return SRcdload(rp, 1, slot);
11097dd7cddfSDavid du Colombier }
11107dd7cddfSDavid du Colombier
11117dd7cddfSDavid du Colombier static long
cmdcdunload(ScsiReq * rp,int argc,char * argv[])11127dd7cddfSDavid du Colombier cmdcdunload(ScsiReq *rp, int argc, char *argv[])
11137dd7cddfSDavid du Colombier {
11147dd7cddfSDavid du Colombier char *p;
11157dd7cddfSDavid du Colombier ulong slot;
11167dd7cddfSDavid du Colombier
11177dd7cddfSDavid du Colombier slot = 0;
11187dd7cddfSDavid du Colombier if(argc && (slot = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){
11197dd7cddfSDavid du Colombier rp->status = Status_BADARG;
11207dd7cddfSDavid du Colombier return -1;
11217dd7cddfSDavid du Colombier }
11227dd7cddfSDavid du Colombier return SRcdload(rp, 0, slot);
11237dd7cddfSDavid du Colombier }
11247dd7cddfSDavid du Colombier
11257dd7cddfSDavid du Colombier static long
cmdcdstatus(ScsiReq * rp,int argc,char * argv[])11267dd7cddfSDavid du Colombier cmdcdstatus(ScsiReq *rp, int argc, char *argv[])
11277dd7cddfSDavid du Colombier {
11287dd7cddfSDavid du Colombier uchar *list, *lp;
11297dd7cddfSDavid du Colombier long nbytes, status;
11307dd7cddfSDavid du Colombier int i, slots;
11317dd7cddfSDavid du Colombier
11327dd7cddfSDavid du Colombier USED(argc, argv);
11337dd7cddfSDavid du Colombier
11347dd7cddfSDavid du Colombier nbytes = 4096;
11357dd7cddfSDavid du Colombier list = malloc(nbytes);
11367dd7cddfSDavid du Colombier if(list == 0){
11377dd7cddfSDavid du Colombier rp->status = STnomem;
11387dd7cddfSDavid du Colombier return -1;
11397dd7cddfSDavid du Colombier }
11407dd7cddfSDavid du Colombier status = SRcdstatus(rp, list, nbytes);
11417dd7cddfSDavid du Colombier if(status == -1){
11427dd7cddfSDavid du Colombier free(list);
11437dd7cddfSDavid du Colombier return -1;
11447dd7cddfSDavid du Colombier }
11457dd7cddfSDavid du Colombier
11467dd7cddfSDavid du Colombier lp = list;
11477dd7cddfSDavid du Colombier Bprint(&bout, " Header\n ");
11487dd7cddfSDavid du Colombier for(i = 0; i < 8; i++){ /* header */
11497dd7cddfSDavid du Colombier Bprint(&bout, " %2.2uX", *lp);
11507dd7cddfSDavid du Colombier lp++;
11517dd7cddfSDavid du Colombier }
11527dd7cddfSDavid du Colombier Bputc(&bout, '\n');
11537dd7cddfSDavid du Colombier
11547dd7cddfSDavid du Colombier slots = ((list[6]<<8)|list[7])/4;
11557dd7cddfSDavid du Colombier Bprint(&bout, " Slots\n ");
11567dd7cddfSDavid du Colombier while(slots--){
11577dd7cddfSDavid du Colombier Bprint(&bout, " %2.2uX %2.2uX %2.2uX %2.2uX\n ",
11587dd7cddfSDavid du Colombier *lp, *(lp+1), *(lp+2), *(lp+3));
11597dd7cddfSDavid du Colombier lp += 4;
11607dd7cddfSDavid du Colombier }
11617dd7cddfSDavid du Colombier
11627dd7cddfSDavid du Colombier free(list);
11637dd7cddfSDavid du Colombier return status;
11647dd7cddfSDavid du Colombier }
11657dd7cddfSDavid du Colombier
11667dd7cddfSDavid du Colombier static long
cmdgetconf(ScsiReq * rp,int argc,char * argv[])11677dd7cddfSDavid du Colombier cmdgetconf(ScsiReq *rp, int argc, char *argv[])
11687dd7cddfSDavid du Colombier {
11697dd7cddfSDavid du Colombier uchar *list;
11707dd7cddfSDavid du Colombier long nbytes, status;
11717dd7cddfSDavid du Colombier
11727dd7cddfSDavid du Colombier USED(argc, argv);
11737dd7cddfSDavid du Colombier
11747dd7cddfSDavid du Colombier nbytes = 4096;
11757dd7cddfSDavid du Colombier list = malloc(nbytes);
11767dd7cddfSDavid du Colombier if(list == 0){
11777dd7cddfSDavid du Colombier rp->status = STnomem;
11787dd7cddfSDavid du Colombier return -1;
11797dd7cddfSDavid du Colombier }
11807dd7cddfSDavid du Colombier status = SRgetconf(rp, list, nbytes);
11817dd7cddfSDavid du Colombier if(status == -1){
11827dd7cddfSDavid du Colombier free(list);
11837dd7cddfSDavid du Colombier return -1;
11847dd7cddfSDavid du Colombier }
11857dd7cddfSDavid du Colombier /* to be done... */
11867dd7cddfSDavid du Colombier free(list);
11877dd7cddfSDavid du Colombier return status;
11887dd7cddfSDavid du Colombier }
11897dd7cddfSDavid du Colombier
11907dd7cddfSDavid du Colombier static long
cmdfwaddr(ScsiReq * rp,int argc,char * argv[])11913e12c5d1SDavid du Colombier cmdfwaddr(ScsiReq *rp, int argc, char *argv[])
11923e12c5d1SDavid du Colombier {
11933e12c5d1SDavid du Colombier uchar d[MaxDirData], npa, track, mode;
11943e12c5d1SDavid du Colombier long n;
11953e12c5d1SDavid du Colombier char *p;
11963e12c5d1SDavid du Colombier
11973e12c5d1SDavid du Colombier npa = mode = track = 0;
11983e12c5d1SDavid du Colombier switch(argc){
11993e12c5d1SDavid du Colombier
12003e12c5d1SDavid du Colombier default:
12013e12c5d1SDavid du Colombier rp->status = Status_BADARG;
12023e12c5d1SDavid du Colombier return -1;
12033e12c5d1SDavid du Colombier
12043e12c5d1SDavid du Colombier case 3:
12053e12c5d1SDavid du Colombier if((npa = strtoul(argv[1], &p, 0)) == 0 && p == argv[1]){
12063e12c5d1SDavid du Colombier rp->status = Status_BADARG;
12073e12c5d1SDavid du Colombier return -1;
12083e12c5d1SDavid du Colombier }
12093e12c5d1SDavid du Colombier /*FALLTHROUGH*/
12103e12c5d1SDavid du Colombier
12113e12c5d1SDavid du Colombier case 2:
12123e12c5d1SDavid du Colombier if((mode = strtoul(argv[1], &p, 0)) == 0 && p == argv[1]){
12133e12c5d1SDavid du Colombier rp->status = Status_BADARG;
12143e12c5d1SDavid du Colombier return -1;
12153e12c5d1SDavid du Colombier }
12163e12c5d1SDavid du Colombier /*FALLTHROUGH*/
12173e12c5d1SDavid du Colombier
12183e12c5d1SDavid du Colombier case 1:
12193e12c5d1SDavid du Colombier if((track = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){
12203e12c5d1SDavid du Colombier rp->status = Status_BADARG;
12213e12c5d1SDavid du Colombier return -1;
12223e12c5d1SDavid du Colombier }
12233e12c5d1SDavid du Colombier break;
12243e12c5d1SDavid du Colombier
12253e12c5d1SDavid du Colombier case 0:
12263e12c5d1SDavid du Colombier break;
12273e12c5d1SDavid du Colombier }
12283e12c5d1SDavid du Colombier if((n = SRfwaddr(rp, track, mode, npa, d)) == -1)
12293e12c5d1SDavid du Colombier return -1;
12307dd7cddfSDavid du Colombier Bprint(&bout, "%ud %ud\n", d[0], (d[1]<<24)|(d[2]<<16)|(d[3]<<8)|d[4]);
12313e12c5d1SDavid du Colombier return n;
12323e12c5d1SDavid du Colombier }
12333e12c5d1SDavid du Colombier
12343e12c5d1SDavid du Colombier static long
cmdtreserve(ScsiReq * rp,int argc,char * argv[])12353e12c5d1SDavid du Colombier cmdtreserve(ScsiReq *rp, int argc, char *argv[])
12363e12c5d1SDavid du Colombier {
12373e12c5d1SDavid du Colombier long nbytes;
12383e12c5d1SDavid du Colombier char *p;
12393e12c5d1SDavid du Colombier
12403e12c5d1SDavid du Colombier if(argc != 1 || ((nbytes = strtoul(argv[0], &p, 0)) == 0 && p == argv[0])){
12413e12c5d1SDavid du Colombier rp->status = Status_BADARG;
12423e12c5d1SDavid du Colombier return -1;
12433e12c5d1SDavid du Colombier }
12443e12c5d1SDavid du Colombier return SRtreserve(rp, nbytes);
12453e12c5d1SDavid du Colombier }
12463e12c5d1SDavid du Colombier
12473e12c5d1SDavid du Colombier static long
cmdtrackinfo(ScsiReq * rp,int argc,char * argv[])12483e12c5d1SDavid du Colombier cmdtrackinfo(ScsiReq *rp, int argc, char *argv[])
12493e12c5d1SDavid du Colombier {
12503e12c5d1SDavid du Colombier uchar d[MaxDirData], track;
12513e12c5d1SDavid du Colombier long n;
12523e12c5d1SDavid du Colombier ulong ul;
12533e12c5d1SDavid du Colombier char *p;
12543e12c5d1SDavid du Colombier
12553e12c5d1SDavid du Colombier track = 0;
12563e12c5d1SDavid du Colombier if(argc && (track = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){
12573e12c5d1SDavid du Colombier rp->status = Status_BADARG;
12583e12c5d1SDavid du Colombier return -1;
12593e12c5d1SDavid du Colombier }
12603e12c5d1SDavid du Colombier if((n = SRtinfo(rp, track, d)) == -1)
12613e12c5d1SDavid du Colombier return -1;
12627dd7cddfSDavid du Colombier Bprint(&bout, "buffer length: 0x%uX\n", d[0]);
12637dd7cddfSDavid du Colombier Bprint(&bout, "number of tracks: 0x%uX\n", d[1]);
12643e12c5d1SDavid du Colombier ul = (d[2]<<24)|(d[3]<<16)|(d[4]<<8)|d[5];
12657dd7cddfSDavid du Colombier Bprint(&bout, "start address: 0x%luX\n", ul);
12663e12c5d1SDavid du Colombier ul = (d[6]<<24)|(d[7]<<16)|(d[8]<<8)|d[9];
12677dd7cddfSDavid du Colombier Bprint(&bout, "track length: 0x%luX\n", ul);
12687dd7cddfSDavid du Colombier Bprint(&bout, "track mode: 0x%uX\n", d[0x0A] & 0x0F);
12697dd7cddfSDavid du Colombier Bprint(&bout, "track status: 0x%uX\n", (d[0x0A]>>4) & 0x0F);
12707dd7cddfSDavid du Colombier Bprint(&bout, "data mode: 0x%uX\n", d[0x0B] & 0x0F);
12713e12c5d1SDavid du Colombier ul = (d[0x0C]<<24)|(d[0x0D]<<16)|(d[0x0E]<<8)|d[0x0F];
12727dd7cddfSDavid du Colombier Bprint(&bout, "free blocks: 0x%luX\n", ul);
12733e12c5d1SDavid du Colombier return n;
12743e12c5d1SDavid du Colombier }
12753e12c5d1SDavid du Colombier
12763e12c5d1SDavid du Colombier static long
cmdwtrack(ScsiReq * rp,int argc,char * argv[])12773e12c5d1SDavid du Colombier cmdwtrack(ScsiReq *rp, int argc, char *argv[])
12783e12c5d1SDavid du Colombier {
12793e12c5d1SDavid du Colombier uchar mode, track;
12803e12c5d1SDavid du Colombier long n, nbytes, total, x;
12813e12c5d1SDavid du Colombier int fd, pid;
12823e12c5d1SDavid du Colombier char *p;
12833e12c5d1SDavid du Colombier
12843e12c5d1SDavid du Colombier mode = track = 0;
12853e12c5d1SDavid du Colombier nbytes = 0;
12863e12c5d1SDavid du Colombier switch(argc){
12873e12c5d1SDavid du Colombier
12883e12c5d1SDavid du Colombier default:
12893e12c5d1SDavid du Colombier rp->status = Status_BADARG;
12903e12c5d1SDavid du Colombier return -1;
12913e12c5d1SDavid du Colombier
12923e12c5d1SDavid du Colombier case 4:
12933e12c5d1SDavid du Colombier if((mode = strtoul(argv[3], &p, 0)) == 0 && p == argv[3]){
12943e12c5d1SDavid du Colombier rp->status = Status_BADARG;
12953e12c5d1SDavid du Colombier return -1;
12963e12c5d1SDavid du Colombier }
12973e12c5d1SDavid du Colombier /*FALLTHROUGH*/
12983e12c5d1SDavid du Colombier
12993e12c5d1SDavid du Colombier case 3:
13003e12c5d1SDavid du Colombier if((track = strtoul(argv[2], &p, 0)) == 0 && p == argv[2]){
13013e12c5d1SDavid du Colombier rp->status = Status_BADARG;
13023e12c5d1SDavid du Colombier return -1;
13033e12c5d1SDavid du Colombier }
13043e12c5d1SDavid du Colombier /*FALLTHROUGH*/
13053e12c5d1SDavid du Colombier
13063e12c5d1SDavid du Colombier case 2:
13073e12c5d1SDavid du Colombier if((nbytes = strtoul(argv[1], &p, 0)) == 0 && p == argv[1]){
13083e12c5d1SDavid du Colombier rp->status = Status_BADARG;
13093e12c5d1SDavid du Colombier return -1;
13103e12c5d1SDavid du Colombier }
13113e12c5d1SDavid du Colombier /*FALLTHROUGH*/
13123e12c5d1SDavid du Colombier
13133e12c5d1SDavid du Colombier case 1:
13143e12c5d1SDavid du Colombier if((fd = mkfile(argv[0], OREAD, &pid)) == -1){
13153e12c5d1SDavid du Colombier rp->status = Status_BADARG;
13163e12c5d1SDavid du Colombier return -1;
13173e12c5d1SDavid du Colombier }
13183e12c5d1SDavid du Colombier break;
13193e12c5d1SDavid du Colombier }
13203e12c5d1SDavid du Colombier total = 0;
132180ee5cbfSDavid du Colombier n = MIN(nbytes, maxiosize);
132280ee5cbfSDavid du Colombier if((n = readn(fd, rwbuf, n)) == -1){
13233e12c5d1SDavid du Colombier fprint(2, "file read failed %r\n");
13243e12c5d1SDavid du Colombier close(fd);
13253e12c5d1SDavid du Colombier return -1;
13263e12c5d1SDavid du Colombier }
13273e12c5d1SDavid du Colombier if((x = SRwtrack(rp, rwbuf, n, track, mode)) != n){
13287dd7cddfSDavid du Colombier fprint(2, "wtrack: write incomplete: asked %ld, did %ld\n", n, x);
13297dd7cddfSDavid du Colombier if(rp->status == STok)
13303e12c5d1SDavid du Colombier rp->status = Status_SW;
13313e12c5d1SDavid du Colombier close(fd);
13323e12c5d1SDavid du Colombier return -1;
13333e12c5d1SDavid du Colombier }
13343e12c5d1SDavid du Colombier nbytes -= n;
13353e12c5d1SDavid du Colombier total += n;
13363e12c5d1SDavid du Colombier while(nbytes){
133780ee5cbfSDavid du Colombier n = MIN(nbytes, maxiosize);
13383e12c5d1SDavid du Colombier if((n = read(fd, rwbuf, n)) == -1){
13393e12c5d1SDavid du Colombier break;
13403e12c5d1SDavid du Colombier }
13413e12c5d1SDavid du Colombier if((x = SRwrite(rp, rwbuf, n)) != n){
13427dd7cddfSDavid du Colombier fprint(2, "write: write incomplete: asked %ld, did %ld\n", n, x);
13437dd7cddfSDavid du Colombier if(rp->status == STok)
13443e12c5d1SDavid du Colombier rp->status = Status_SW;
13453e12c5d1SDavid du Colombier break;
13463e12c5d1SDavid du Colombier }
13473e12c5d1SDavid du Colombier nbytes -= n;
13483e12c5d1SDavid du Colombier total += n;
13493e12c5d1SDavid du Colombier }
13503e12c5d1SDavid du Colombier close(fd);
13513e12c5d1SDavid du Colombier if(pid >= 0 && waitfor(pid)){
13523e12c5d1SDavid du Colombier rp->status = Status_SW;
13533e12c5d1SDavid du Colombier return -1;
13543e12c5d1SDavid du Colombier }
13553e12c5d1SDavid du Colombier return total;
13563e12c5d1SDavid du Colombier }
13573e12c5d1SDavid du Colombier
13583e12c5d1SDavid du Colombier static long
cmdload(ScsiReq * rp,int argc,char * argv[])13593e12c5d1SDavid du Colombier cmdload(ScsiReq *rp, int argc, char *argv[])
13603e12c5d1SDavid du Colombier {
13613e12c5d1SDavid du Colombier USED(argc, argv);
13623e12c5d1SDavid du Colombier return SRmload(rp, 0);
13633e12c5d1SDavid du Colombier }
13643e12c5d1SDavid du Colombier
13653e12c5d1SDavid du Colombier static long
cmdunload(ScsiReq * rp,int argc,char * argv[])13663e12c5d1SDavid du Colombier cmdunload(ScsiReq *rp, int argc, char *argv[])
13673e12c5d1SDavid du Colombier {
13683e12c5d1SDavid du Colombier USED(argc, argv);
13693e12c5d1SDavid du Colombier return SRmload(rp, 1);
13703e12c5d1SDavid du Colombier }
13713e12c5d1SDavid du Colombier
13723e12c5d1SDavid du Colombier static long
cmdfixation(ScsiReq * rp,int argc,char * argv[])13733e12c5d1SDavid du Colombier cmdfixation(ScsiReq *rp, int argc, char *argv[])
13743e12c5d1SDavid du Colombier {
13753e12c5d1SDavid du Colombier uchar type;
13763e12c5d1SDavid du Colombier char *p;
13773e12c5d1SDavid du Colombier
13783e12c5d1SDavid du Colombier type = 0;
13793e12c5d1SDavid du Colombier if(argc && (type = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){
13803e12c5d1SDavid du Colombier rp->status = Status_BADARG;
13813e12c5d1SDavid du Colombier return -1;
13823e12c5d1SDavid du Colombier }
13833e12c5d1SDavid du Colombier return SRfixation(rp, type);
13843e12c5d1SDavid du Colombier }
13853e12c5d1SDavid du Colombier
13863e12c5d1SDavid du Colombier static long
cmdeinit(ScsiReq * rp,int argc,char * argv[])13877dd7cddfSDavid du Colombier cmdeinit(ScsiReq *rp, int argc, char *argv[])
13887dd7cddfSDavid du Colombier {
13897dd7cddfSDavid du Colombier USED(argc, argv);
13907dd7cddfSDavid du Colombier return SReinitialise(rp);
13917dd7cddfSDavid du Colombier }
13927dd7cddfSDavid du Colombier
13937dd7cddfSDavid du Colombier static long
cmdmmove(ScsiReq * rp,int argc,char * argv[])13947dd7cddfSDavid du Colombier cmdmmove(ScsiReq *rp, int argc, char *argv[])
13957dd7cddfSDavid du Colombier {
13967dd7cddfSDavid du Colombier int transport, source, destination, invert;
13977dd7cddfSDavid du Colombier char *p;
13987dd7cddfSDavid du Colombier
13997dd7cddfSDavid du Colombier invert = 0;
14007dd7cddfSDavid du Colombier
14017dd7cddfSDavid du Colombier switch(argc){
14027dd7cddfSDavid du Colombier
14037dd7cddfSDavid du Colombier default:
14047dd7cddfSDavid du Colombier rp->status = Status_BADARG;
14057dd7cddfSDavid du Colombier return -1;
14067dd7cddfSDavid du Colombier
14077dd7cddfSDavid du Colombier case 4:
14087dd7cddfSDavid du Colombier if((invert = strtoul(argv[3], &p, 0)) == 0 && p == argv[3]){
14097dd7cddfSDavid du Colombier rp->status = Status_BADARG;
14107dd7cddfSDavid du Colombier return -1;
14117dd7cddfSDavid du Colombier }
14127dd7cddfSDavid du Colombier /*FALLTHROUGH*/
14137dd7cddfSDavid du Colombier
14147dd7cddfSDavid du Colombier case 3:
14157dd7cddfSDavid du Colombier if((transport = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){
14167dd7cddfSDavid du Colombier rp->status = Status_BADARG;
14177dd7cddfSDavid du Colombier return -1;
14187dd7cddfSDavid du Colombier }
14197dd7cddfSDavid du Colombier if((source = strtoul(argv[1], &p, 0)) == 0 && p == argv[1]){
14207dd7cddfSDavid du Colombier rp->status = Status_BADARG;
14217dd7cddfSDavid du Colombier return -1;
14227dd7cddfSDavid du Colombier }
14237dd7cddfSDavid du Colombier if((destination = strtoul(argv[2], &p, 0)) == 0 && p == argv[2]){
14247dd7cddfSDavid du Colombier rp->status = Status_BADARG;
14257dd7cddfSDavid du Colombier return -1;
14267dd7cddfSDavid du Colombier }
14277dd7cddfSDavid du Colombier break;
14287dd7cddfSDavid du Colombier }
14297dd7cddfSDavid du Colombier
14307dd7cddfSDavid du Colombier return SRmmove(rp, transport, source, destination, invert);
14317dd7cddfSDavid du Colombier }
14327dd7cddfSDavid du Colombier
14337dd7cddfSDavid du Colombier static long
cmdestatus(ScsiReq * rp,int argc,char * argv[])14347dd7cddfSDavid du Colombier cmdestatus(ScsiReq *rp, int argc, char *argv[])
14357dd7cddfSDavid du Colombier {
14367dd7cddfSDavid du Colombier uchar *list, *lp, type;
14377dd7cddfSDavid du Colombier long d, i, n, nbytes, status;
14387dd7cddfSDavid du Colombier char *p;
14397dd7cddfSDavid du Colombier
14407dd7cddfSDavid du Colombier type = 0;
14417dd7cddfSDavid du Colombier nbytes = 4096;
14427dd7cddfSDavid du Colombier
14437dd7cddfSDavid du Colombier switch(argc){
14447dd7cddfSDavid du Colombier
14457dd7cddfSDavid du Colombier default:
14467dd7cddfSDavid du Colombier rp->status = Status_BADARG;
14477dd7cddfSDavid du Colombier return -1;
14487dd7cddfSDavid du Colombier
14497dd7cddfSDavid du Colombier case 2:
14507dd7cddfSDavid du Colombier if((nbytes = strtoul(argv[1], &p, 0)) == 0 && p == argv[1]){
14517dd7cddfSDavid du Colombier rp->status = Status_BADARG;
14527dd7cddfSDavid du Colombier return -1;
14537dd7cddfSDavid du Colombier }
14547dd7cddfSDavid du Colombier /*FALLTHROUGH*/
14557dd7cddfSDavid du Colombier
14567dd7cddfSDavid du Colombier case 1:
14577dd7cddfSDavid du Colombier if((type = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){
14587dd7cddfSDavid du Colombier rp->status = Status_BADARG;
14597dd7cddfSDavid du Colombier return -1;
14607dd7cddfSDavid du Colombier }
14617dd7cddfSDavid du Colombier break;
14627dd7cddfSDavid du Colombier
14637dd7cddfSDavid du Colombier case 0:
14647dd7cddfSDavid du Colombier break;
14657dd7cddfSDavid du Colombier }
14667dd7cddfSDavid du Colombier
14677dd7cddfSDavid du Colombier list = malloc(nbytes);
14687dd7cddfSDavid du Colombier if(list == 0){
14697dd7cddfSDavid du Colombier rp->status = STnomem;
14707dd7cddfSDavid du Colombier return -1;
14717dd7cddfSDavid du Colombier }
14727dd7cddfSDavid du Colombier status = SRestatus(rp, type, list, nbytes);
14737dd7cddfSDavid du Colombier if(status == -1){
14747dd7cddfSDavid du Colombier free(list);
14757dd7cddfSDavid du Colombier return -1;
14767dd7cddfSDavid du Colombier }
14777dd7cddfSDavid du Colombier
14787dd7cddfSDavid du Colombier lp = list;
14797dd7cddfSDavid du Colombier nbytes = ((lp[5]<<16)|(lp[6]<<8)|lp[7])-8;
14807dd7cddfSDavid du Colombier Bprint(&bout, " Header\n ");
14817dd7cddfSDavid du Colombier for(i = 0; i < 8; i++){ /* header */
14827dd7cddfSDavid du Colombier Bprint(&bout, " %2.2uX", *lp);
14837dd7cddfSDavid du Colombier lp++;
14847dd7cddfSDavid du Colombier }
14857dd7cddfSDavid du Colombier Bputc(&bout, '\n');
14867dd7cddfSDavid du Colombier
14877dd7cddfSDavid du Colombier while(nbytes > 0){ /* pages */
14887dd7cddfSDavid du Colombier i = ((lp[5]<<16)|(lp[6]<<8)|lp[7]);
14897dd7cddfSDavid du Colombier nbytes -= i+8;
14907dd7cddfSDavid du Colombier Bprint(&bout, " Type");
14917dd7cddfSDavid du Colombier for(n = 0; n < 8; n++) /* header */
14927dd7cddfSDavid du Colombier Bprint(&bout, " %2.2uX", lp[n]);
14937dd7cddfSDavid du Colombier Bprint(&bout, "\n ");
14947dd7cddfSDavid du Colombier d = (lp[2]<<8)|lp[3];
14957dd7cddfSDavid du Colombier lp += 8;
14967dd7cddfSDavid du Colombier for(n = 0; n < i; n++){
14977dd7cddfSDavid du Colombier if(n && (n % d) == 0)
14987dd7cddfSDavid du Colombier Bprint(&bout, "\n ");
14997dd7cddfSDavid du Colombier Bprint(&bout, " %2.2uX", *lp);
15007dd7cddfSDavid du Colombier lp++;
15017dd7cddfSDavid du Colombier }
15027dd7cddfSDavid du Colombier if(n && (n % d))
15037dd7cddfSDavid du Colombier Bputc(&bout, '\n');
15047dd7cddfSDavid du Colombier }
15057dd7cddfSDavid du Colombier
15067dd7cddfSDavid du Colombier free(list);
15077dd7cddfSDavid du Colombier return status;
15087dd7cddfSDavid du Colombier }
15097dd7cddfSDavid du Colombier
15107dd7cddfSDavid du Colombier static long
cmdhelp(ScsiReq * rp,int argc,char * argv[])15113e12c5d1SDavid du Colombier cmdhelp(ScsiReq *rp, int argc, char *argv[])
15123e12c5d1SDavid du Colombier {
15133e12c5d1SDavid du Colombier ScsiCmd *cp;
15143e12c5d1SDavid du Colombier char *p;
15153e12c5d1SDavid du Colombier
15163e12c5d1SDavid du Colombier USED(rp);
15173e12c5d1SDavid du Colombier if(argc)
15183e12c5d1SDavid du Colombier p = argv[0];
15193e12c5d1SDavid du Colombier else
15203e12c5d1SDavid du Colombier p = 0;
1521*fd362a73SDavid du Colombier for(cp = scsicmds; cp->name; cp++){
15223e12c5d1SDavid du Colombier if(p == 0 || strcmp(p, cp->name) == 0)
15233e12c5d1SDavid du Colombier Bprint(&bout, "%s\n", cp->help);
15243e12c5d1SDavid du Colombier }
15253e12c5d1SDavid du Colombier return 0;
15263e12c5d1SDavid du Colombier }
15273e12c5d1SDavid du Colombier
15283e12c5d1SDavid du Colombier static long
cmdprobe(ScsiReq * rp,int argc,char * argv[])15293e12c5d1SDavid du Colombier cmdprobe(ScsiReq *rp, int argc, char *argv[])
15303e12c5d1SDavid du Colombier {
15317dd7cddfSDavid du Colombier char buf[32];
15323e12c5d1SDavid du Colombier ScsiReq scsireq;
15337dd7cddfSDavid du Colombier char *ctlr, *unit;
15343e12c5d1SDavid du Colombier
15353e12c5d1SDavid du Colombier USED(argc, argv);
15367dd7cddfSDavid du Colombier rp->status = STok;
15373e12c5d1SDavid du Colombier scsireq.flags = 0;
15387dd7cddfSDavid du Colombier
1539670efe9aSDavid du Colombier for(ctlr="CDEFGHIJ0123456789abcdef"; *ctlr; ctlr++) {
15407dd7cddfSDavid du Colombier /*
15417dd7cddfSDavid du Colombier * I can guess how many units you have.
1542670efe9aSDavid du Colombier * SATA controllers can have more than two drives each.
15437dd7cddfSDavid du Colombier */
1544670efe9aSDavid du Colombier if(*ctlr >= 'C' && *ctlr <= 'D')
15457dd7cddfSDavid du Colombier unit = "01";
15467dd7cddfSDavid du Colombier else if((*ctlr >= '0' && *ctlr <= '9')
15477dd7cddfSDavid du Colombier || (*ctlr >= 'a' && *ctlr <= 'f'))
1548670efe9aSDavid du Colombier unit = "0123456789abcdef"; /* allow wide scsi */
15497dd7cddfSDavid du Colombier else
1550670efe9aSDavid du Colombier unit = "01234567";
15517dd7cddfSDavid du Colombier
15527dd7cddfSDavid du Colombier for(; *unit; unit++){
15537dd7cddfSDavid du Colombier sprint(buf, "/dev/sd%c%c", *ctlr, *unit);
15547dd7cddfSDavid du Colombier if(SRopenraw(&scsireq, buf) == -1)
15557dd7cddfSDavid du Colombier continue;
15563e12c5d1SDavid du Colombier SRreqsense(&scsireq);
15573e12c5d1SDavid du Colombier switch(scsireq.status){
15587dd7cddfSDavid du Colombier case STok:
15593e12c5d1SDavid du Colombier case Status_SD:
15607dd7cddfSDavid du Colombier Bprint(&bout, "%s: ", buf);
15613e12c5d1SDavid du Colombier cmdinquiry(&scsireq, 0, 0);
15623e12c5d1SDavid du Colombier break;
15633e12c5d1SDavid du Colombier }
15643e12c5d1SDavid du Colombier SRclose(&scsireq);
15653e12c5d1SDavid du Colombier }
15667dd7cddfSDavid du Colombier }
15673e12c5d1SDavid du Colombier return 0;
15683e12c5d1SDavid du Colombier }
15693e12c5d1SDavid du Colombier
15703e12c5d1SDavid du Colombier static long
cmdclose(ScsiReq * rp,int argc,char * argv[])15713e12c5d1SDavid du Colombier cmdclose(ScsiReq *rp, int argc, char *argv[])
15723e12c5d1SDavid du Colombier {
15733e12c5d1SDavid du Colombier USED(argc, argv);
15743e12c5d1SDavid du Colombier return SRclose(rp);
15753e12c5d1SDavid du Colombier }
15763e12c5d1SDavid du Colombier
15773e12c5d1SDavid du Colombier static long
cmdopen(ScsiReq * rp,int argc,char * argv[])15783e12c5d1SDavid du Colombier cmdopen(ScsiReq *rp, int argc, char *argv[])
15793e12c5d1SDavid du Colombier {
15807dd7cddfSDavid du Colombier int raw;
15813e12c5d1SDavid du Colombier long status;
15823e12c5d1SDavid du Colombier
1583bd389b36SDavid du Colombier raw = 0;
1584bd389b36SDavid du Colombier if(argc && strcmp("-r", argv[0]) == 0){
1585bd389b36SDavid du Colombier raw = 1;
1586bd389b36SDavid du Colombier argc--, argv++;
1587bd389b36SDavid du Colombier }
15887dd7cddfSDavid du Colombier if(argc != 1){
15893e12c5d1SDavid du Colombier rp->status = Status_BADARG;
15903e12c5d1SDavid du Colombier return -1;
15913e12c5d1SDavid du Colombier }
1592bd389b36SDavid du Colombier if(raw == 0){
15937dd7cddfSDavid du Colombier if((status = SRopen(rp, argv[0])) != -1 && verbose)
15947dd7cddfSDavid du Colombier Bprint(&bout, "%sblock size: %ld\n",
15957dd7cddfSDavid du Colombier rp->flags&Fbfixed? "fixed ": "", rp->lbsize);
1596bd389b36SDavid du Colombier }
1597bd389b36SDavid du Colombier else {
15987dd7cddfSDavid du Colombier status = SRopenraw(rp, argv[0]);
1599bd389b36SDavid du Colombier rp->lbsize = 512;
1600bd389b36SDavid du Colombier }
16013e12c5d1SDavid du Colombier return status;
16023e12c5d1SDavid du Colombier }
16033e12c5d1SDavid du Colombier
1604*fd362a73SDavid du Colombier static ScsiCmd scsicmds[] = {
16053e12c5d1SDavid du Colombier { "ready", cmdready, 1, /*[0x00]*/
16063e12c5d1SDavid du Colombier "ready",
16073e12c5d1SDavid du Colombier },
16083e12c5d1SDavid du Colombier { "rewind", cmdrewind, 1, /*[0x01]*/
16093e12c5d1SDavid du Colombier "rewind",
16103e12c5d1SDavid du Colombier },
16113e12c5d1SDavid du Colombier { "rezero", cmdrewind, 1, /*[0x01]*/
16123e12c5d1SDavid du Colombier "rezero",
16133e12c5d1SDavid du Colombier },
16143e12c5d1SDavid du Colombier { "reqsense", cmdreqsense, 1, /*[0x03]*/
16153e12c5d1SDavid du Colombier "reqsense",
16163e12c5d1SDavid du Colombier },
1617bd389b36SDavid du Colombier { "format", cmdformat, 0, /*[0x04]*/
16183e12c5d1SDavid du Colombier "format",
16193e12c5d1SDavid du Colombier },
16203e12c5d1SDavid du Colombier { "rblimits", cmdrblimits, 1, /*[0x05]*/
16213e12c5d1SDavid du Colombier "rblimits",
16223e12c5d1SDavid du Colombier },
16233e12c5d1SDavid du Colombier { "read", cmdread, 1, /*[0x08]*/
16243e12c5d1SDavid du Colombier "read [|]file [nbytes]",
16253e12c5d1SDavid du Colombier },
16263e12c5d1SDavid du Colombier { "write", cmdwrite, 1, /*[0x0A]*/
16273e12c5d1SDavid du Colombier "write [|]file [nbytes]",
16283e12c5d1SDavid du Colombier },
16293e12c5d1SDavid du Colombier { "seek", cmdseek, 1, /*[0x0B]*/
16303e12c5d1SDavid du Colombier "seek offset [whence]",
16313e12c5d1SDavid du Colombier },
16323e12c5d1SDavid du Colombier { "filemark", cmdfilemark, 1, /*[0x10]*/
16333e12c5d1SDavid du Colombier "filemark [howmany]",
16343e12c5d1SDavid du Colombier },
16353e12c5d1SDavid du Colombier { "space", cmdspace, 1, /*[0x11]*/
16363e12c5d1SDavid du Colombier "space [-f] [-b] [[--] howmany]",
16373e12c5d1SDavid du Colombier },
16383e12c5d1SDavid du Colombier { "inquiry", cmdinquiry, 1, /*[0x12]*/
16393e12c5d1SDavid du Colombier "inquiry",
16403e12c5d1SDavid du Colombier },
16417dd7cddfSDavid du Colombier { "modeselect6",cmdmodeselect6, 1, /*[0x15] */
16427dd7cddfSDavid du Colombier "modeselect6 bytes...",
16437dd7cddfSDavid du Colombier },
16447dd7cddfSDavid du Colombier { "modeselect", cmdmodeselect10, 1, /*[0x55] */
16453e12c5d1SDavid du Colombier "modeselect bytes...",
16463e12c5d1SDavid du Colombier },
16477dd7cddfSDavid du Colombier { "modesense6", cmdmodesense6, 1, /*[0x1A]*/
16487dd7cddfSDavid du Colombier "modesense6 [page [nbytes]]",
16497dd7cddfSDavid du Colombier },
16507dd7cddfSDavid du Colombier { "modesense", cmdmodesense10, 1, /*[0x5A]*/
16513e12c5d1SDavid du Colombier "modesense [page [nbytes]]",
16523e12c5d1SDavid du Colombier },
16533e12c5d1SDavid du Colombier { "start", cmdstart, 1, /*[0x1B]*/
16543e12c5d1SDavid du Colombier "start [code]",
16553e12c5d1SDavid du Colombier },
16563e12c5d1SDavid du Colombier { "stop", cmdstop, 1, /*[0x1B]*/
16577dd7cddfSDavid du Colombier "stop",
16583e12c5d1SDavid du Colombier },
16593e12c5d1SDavid du Colombier { "eject", cmdeject, 1, /*[0x1B]*/
16607dd7cddfSDavid du Colombier "eject",
16617dd7cddfSDavid du Colombier },
16627dd7cddfSDavid du Colombier { "ingest", cmdingest, 1, /*[0x1B]*/
16637dd7cddfSDavid du Colombier "ingest",
16643e12c5d1SDavid du Colombier },
16653e12c5d1SDavid du Colombier { "capacity", cmdcapacity, 1, /*[0x25]*/
16663e12c5d1SDavid du Colombier "capacity",
16673e12c5d1SDavid du Colombier },
16683e12c5d1SDavid du Colombier
16697dd7cddfSDavid du Colombier { "blank", cmdblank, 1, /*[0xA1]*/
16707dd7cddfSDavid du Colombier "blank [track/LBA [type]]",
16713e12c5d1SDavid du Colombier },
16727dd7cddfSDavid du Colombier // { "synccache", cmdsynccache, 1, /*[0x35]*/
16737dd7cddfSDavid du Colombier // "synccache",
16747dd7cddfSDavid du Colombier // },
16757dd7cddfSDavid du Colombier { "rtoc", cmdrtoc, 1, /*[0x43]*/
16767dd7cddfSDavid du Colombier "rtoc [track/session-number [format]]",
16773e12c5d1SDavid du Colombier },
16787dd7cddfSDavid du Colombier { "rdiscinfo", cmdrdiscinfo, 1, /*[0x51]*/
16797dd7cddfSDavid du Colombier "rdiscinfo",
16803e12c5d1SDavid du Colombier },
16817dd7cddfSDavid du Colombier { "rtrackinfo", cmdrtrackinfo, 1, /*[0x52]*/
16827dd7cddfSDavid du Colombier "rtrackinfo [track]",
16833e12c5d1SDavid du Colombier },
16847dd7cddfSDavid du Colombier
16857dd7cddfSDavid du Colombier { "cdpause", cmdcdpause, 1, /*[0x4B]*/
16867dd7cddfSDavid du Colombier "cdpause",
16873e12c5d1SDavid du Colombier },
16887dd7cddfSDavid du Colombier { "cdresume", cmdcdresume, 1, /*[0x4B]*/
16897dd7cddfSDavid du Colombier "cdresume",
16903e12c5d1SDavid du Colombier },
16917dd7cddfSDavid du Colombier { "cdstop", cmdcdstop, 1, /*[0x4E]*/
16927dd7cddfSDavid du Colombier "cdstop",
16933e12c5d1SDavid du Colombier },
16947dd7cddfSDavid du Colombier { "cdplay", cmdcdplay, 1, /*[0xA5]*/
16957dd7cddfSDavid du Colombier "cdplay [track-number] or [-r [LBA [length]]]",
16963e12c5d1SDavid du Colombier },
16977dd7cddfSDavid du Colombier { "cdload", cmdcdload, 1, /*[0xA6*/
16987dd7cddfSDavid du Colombier "cdload [slot]",
16997dd7cddfSDavid du Colombier },
17007dd7cddfSDavid du Colombier { "cdunload", cmdcdunload, 1, /*[0xA6]*/
17017dd7cddfSDavid du Colombier "cdunload [slot]",
17027dd7cddfSDavid du Colombier },
17037dd7cddfSDavid du Colombier { "cdstatus", cmdcdstatus, 1, /*[0xBD]*/
17047dd7cddfSDavid du Colombier "cdstatus",
17057dd7cddfSDavid du Colombier },
17067dd7cddfSDavid du Colombier // { "getconf", cmdgetconf, 1, /*[0x46]*/
17077dd7cddfSDavid du Colombier // "getconf",
17087dd7cddfSDavid du Colombier // },
17097dd7cddfSDavid du Colombier
17107dd7cddfSDavid du Colombier // { "fwaddr", cmdfwaddr, 1, /*[0xE2]*/
17117dd7cddfSDavid du Colombier // "fwaddr [track [mode [npa]]]",
17127dd7cddfSDavid du Colombier // },
17137dd7cddfSDavid du Colombier // { "treserve", cmdtreserve, 1, /*[0xE4]*/
17147dd7cddfSDavid du Colombier // "treserve nbytes",
17157dd7cddfSDavid du Colombier // },
17167dd7cddfSDavid du Colombier // { "trackinfo", cmdtrackinfo, 1, /*[0xE5]*/
17177dd7cddfSDavid du Colombier // "trackinfo [track]",
17187dd7cddfSDavid du Colombier // },
17197dd7cddfSDavid du Colombier // { "wtrack", cmdwtrack, 1, /*[0xE6]*/
17207dd7cddfSDavid du Colombier // "wtrack [|]file [nbytes [track [mode]]]",
17217dd7cddfSDavid du Colombier // },
17227dd7cddfSDavid du Colombier // { "load", cmdload, 1, /*[0xE7]*/
17237dd7cddfSDavid du Colombier // "load",
17247dd7cddfSDavid du Colombier // },
17257dd7cddfSDavid du Colombier // { "unload", cmdunload, 1, /*[0xE7]*/
17267dd7cddfSDavid du Colombier // "unload",
17277dd7cddfSDavid du Colombier // },
17287dd7cddfSDavid du Colombier // { "fixation", cmdfixation, 1, /*[0xE9]*/
17297dd7cddfSDavid du Colombier // "fixation [toc-type]",
17307dd7cddfSDavid du Colombier // },
17317dd7cddfSDavid du Colombier { "einit", cmdeinit, 1, /*[0x07]*/
17327dd7cddfSDavid du Colombier "einit",
17337dd7cddfSDavid du Colombier },
17347dd7cddfSDavid du Colombier { "estatus", cmdestatus, 1, /*[0xB8]*/
17357dd7cddfSDavid du Colombier "estatus",
17367dd7cddfSDavid du Colombier },
17377dd7cddfSDavid du Colombier { "mmove", cmdmmove, 1, /*[0xA5]*/
17387dd7cddfSDavid du Colombier "mmove transport source destination [invert]",
17393e12c5d1SDavid du Colombier },
17403e12c5d1SDavid du Colombier
17413e12c5d1SDavid du Colombier { "help", cmdhelp, 0,
17423e12c5d1SDavid du Colombier "help",
17433e12c5d1SDavid du Colombier },
17443e12c5d1SDavid du Colombier { "probe", cmdprobe, 0,
17453e12c5d1SDavid du Colombier "probe",
17463e12c5d1SDavid du Colombier },
17473e12c5d1SDavid du Colombier { "close", cmdclose, 1,
17483e12c5d1SDavid du Colombier "close",
17493e12c5d1SDavid du Colombier },
17503e12c5d1SDavid du Colombier { "open", cmdopen, 0,
17517dd7cddfSDavid du Colombier "open [-r] sddev",
17523e12c5d1SDavid du Colombier },
17533e12c5d1SDavid du Colombier { 0, 0 },
17543e12c5d1SDavid du Colombier };
17553e12c5d1SDavid du Colombier
17563e12c5d1SDavid du Colombier #define SEP(c) (((c)==' ')||((c)=='\t')||((c)=='\n'))
17573e12c5d1SDavid du Colombier
17583e12c5d1SDavid du Colombier static char *
tokenise(char * s,char ** start,char ** end)17593e12c5d1SDavid du Colombier tokenise(char *s, char **start, char **end)
17603e12c5d1SDavid du Colombier {
17613e12c5d1SDavid du Colombier char *to;
17623e12c5d1SDavid du Colombier Rune r;
17633e12c5d1SDavid du Colombier int n;
17643e12c5d1SDavid du Colombier
17653e12c5d1SDavid du Colombier while(*s && SEP(*s)) /* skip leading white space */
17663e12c5d1SDavid du Colombier s++;
17673e12c5d1SDavid du Colombier to = *start = s;
17683e12c5d1SDavid du Colombier while(*s){
17693e12c5d1SDavid du Colombier n = chartorune(&r, s);
17703e12c5d1SDavid du Colombier if(SEP(r)){
17713e12c5d1SDavid du Colombier if(to != *start) /* we have data */
17723e12c5d1SDavid du Colombier break;
17733e12c5d1SDavid du Colombier s += n; /* null string - keep looking */
17743e12c5d1SDavid du Colombier while(*s && SEP(*s))
17753e12c5d1SDavid du Colombier s++;
17763e12c5d1SDavid du Colombier to = *start = s;
17773e12c5d1SDavid du Colombier }
17783e12c5d1SDavid du Colombier else if(r == '\''){
17793e12c5d1SDavid du Colombier s += n; /* skip leading quote */
17803e12c5d1SDavid du Colombier while(*s){
17813e12c5d1SDavid du Colombier n = chartorune(&r, s);
17823e12c5d1SDavid du Colombier if(r == '\''){
17833e12c5d1SDavid du Colombier if(s[1] != '\'')
17843e12c5d1SDavid du Colombier break;
17853e12c5d1SDavid du Colombier s++; /* embedded quote */
17863e12c5d1SDavid du Colombier }
17873e12c5d1SDavid du Colombier while (n--)
17883e12c5d1SDavid du Colombier *to++ = *s++;
17893e12c5d1SDavid du Colombier }
17903e12c5d1SDavid du Colombier if(!*s) /* no trailing quote */
17913e12c5d1SDavid du Colombier break;
17923e12c5d1SDavid du Colombier s++; /* skip trailing quote */
17933e12c5d1SDavid du Colombier }
17943e12c5d1SDavid du Colombier else {
17953e12c5d1SDavid du Colombier while(n--)
17963e12c5d1SDavid du Colombier *to++ = *s++;
17973e12c5d1SDavid du Colombier }
17983e12c5d1SDavid du Colombier }
17993e12c5d1SDavid du Colombier *end = to;
18003e12c5d1SDavid du Colombier return s;
18013e12c5d1SDavid du Colombier }
18023e12c5d1SDavid du Colombier
18033e12c5d1SDavid du Colombier static int
parse(char * s,char * fields[],int nfields)18043e12c5d1SDavid du Colombier parse(char *s, char *fields[], int nfields)
18053e12c5d1SDavid du Colombier {
1806219b2ee8SDavid du Colombier int c, argc;
18073e12c5d1SDavid du Colombier char *start, *end;
18083e12c5d1SDavid du Colombier
18093e12c5d1SDavid du Colombier argc = 0;
1810219b2ee8SDavid du Colombier c = *s;
1811219b2ee8SDavid du Colombier while(c){
18123e12c5d1SDavid du Colombier s = tokenise(s, &start, &end);
1813219b2ee8SDavid du Colombier c = *s++;
18143e12c5d1SDavid du Colombier if(*start == 0)
18153e12c5d1SDavid du Colombier break;
18163e12c5d1SDavid du Colombier if(argc >= nfields-1)
18173e12c5d1SDavid du Colombier return -1;
18183e12c5d1SDavid du Colombier *end = 0;
18193e12c5d1SDavid du Colombier fields[argc++] = start;
18203e12c5d1SDavid du Colombier }
18213e12c5d1SDavid du Colombier fields[argc] = 0;
18223e12c5d1SDavid du Colombier return argc;
18233e12c5d1SDavid du Colombier }
18243e12c5d1SDavid du Colombier
18253e12c5d1SDavid du Colombier static void
usage(void)18263e12c5d1SDavid du Colombier usage(void)
18273e12c5d1SDavid du Colombier {
1828968130a0SDavid du Colombier fprint(2, "usage: %s [-6eq] [-m maxiosize] [[-r] /dev/sdXX]\n", argv0);
18293e12c5d1SDavid du Colombier exits("usage");
18303e12c5d1SDavid du Colombier }
18313e12c5d1SDavid du Colombier
18327dd7cddfSDavid du Colombier static struct {
18337dd7cddfSDavid du Colombier int status;
18347dd7cddfSDavid du Colombier char* description;
18357dd7cddfSDavid du Colombier } description[] = {
18367dd7cddfSDavid du Colombier STnomem, "buffer allocation failed",
18377dd7cddfSDavid du Colombier STtimeout, "bus timeout",
18387dd7cddfSDavid du Colombier STharderr, "controller error of some kind",
18397dd7cddfSDavid du Colombier STok, "good",
18407dd7cddfSDavid du Colombier STcheck, "check condition",
18417dd7cddfSDavid du Colombier STcondmet, "condition met/good",
18427dd7cddfSDavid du Colombier STbusy, "busy ",
18437dd7cddfSDavid du Colombier STintok, "intermediate/good",
18447dd7cddfSDavid du Colombier STintcondmet, "intermediate/condition met/good",
18457dd7cddfSDavid du Colombier STresconf, "reservation conflict",
18467dd7cddfSDavid du Colombier STterminated, "command terminated",
18477dd7cddfSDavid du Colombier STqfull, "queue full",
18487dd7cddfSDavid du Colombier
18497dd7cddfSDavid du Colombier Status_SD, "sense-data available",
18507dd7cddfSDavid du Colombier Status_SW, "internal software error",
18517dd7cddfSDavid du Colombier Status_BADARG, "bad argument to request",
18527dd7cddfSDavid du Colombier
18537dd7cddfSDavid du Colombier 0, 0,
18547dd7cddfSDavid du Colombier };
18557dd7cddfSDavid du Colombier
18563e12c5d1SDavid du Colombier void
main(int argc,char * argv[])18573e12c5d1SDavid du Colombier main(int argc, char *argv[])
18583e12c5d1SDavid du Colombier {
18593e12c5d1SDavid du Colombier ScsiReq target;
18607dd7cddfSDavid du Colombier char *ap, *av[256];
1861968130a0SDavid du Colombier int ac, i, raw = 0;
18623e12c5d1SDavid du Colombier ScsiCmd *cp;
18633e12c5d1SDavid du Colombier long status;
18643e12c5d1SDavid du Colombier
18653e12c5d1SDavid du Colombier ARGBEGIN {
1866968130a0SDavid du Colombier case 'e':
1867968130a0SDavid du Colombier exabyte = 1;
1868968130a0SDavid du Colombier /* fallthrough */
1869968130a0SDavid du Colombier case '6':
1870968130a0SDavid du Colombier force6bytecmds = 1;
18713e12c5d1SDavid du Colombier break;
187280ee5cbfSDavid du Colombier case 'm':
187380ee5cbfSDavid du Colombier ap = ARGF();
187480ee5cbfSDavid du Colombier if(ap == nil)
187580ee5cbfSDavid du Colombier usage();
187680ee5cbfSDavid du Colombier maxiosize = atol(ap);
187780ee5cbfSDavid du Colombier if(maxiosize < 512 || maxiosize > MaxIOsize)
1878968130a0SDavid du Colombier sysfatal("max-xfer < 512 or > %d", MaxIOsize);
1879968130a0SDavid du Colombier break;
1880968130a0SDavid du Colombier case 'r': /* must be last option and not bundled */
1881968130a0SDavid du Colombier raw++;
1882968130a0SDavid du Colombier break;
1883968130a0SDavid du Colombier case 'q':
1884968130a0SDavid du Colombier verbose = 0;
188580ee5cbfSDavid du Colombier break;
18863e12c5d1SDavid du Colombier default:
18873e12c5d1SDavid du Colombier usage();
18883e12c5d1SDavid du Colombier } ARGEND
18893e12c5d1SDavid du Colombier
18903e12c5d1SDavid du Colombier if(Binit(&bin, 0, OREAD) == Beof || Binit(&bout, 1, OWRITE) == Beof){
18913e12c5d1SDavid du Colombier fprint(2, "%s: can't init bio: %r\n", argv0);
18923e12c5d1SDavid du Colombier exits("Binit");
18933e12c5d1SDavid du Colombier }
18943e12c5d1SDavid du Colombier
1895e29d4813SDavid du Colombier memset(&target, 0, sizeof target);
1896968130a0SDavid du Colombier if (raw) { /* hack for -r */
1897968130a0SDavid du Colombier ++argc;
1898968130a0SDavid du Colombier --argv;
1899968130a0SDavid du Colombier }
19007dd7cddfSDavid du Colombier if(argc && cmdopen(&target, argc, argv) == -1) {
19017dd7cddfSDavid du Colombier fprint(2, "open failed\n");
19023e12c5d1SDavid du Colombier usage();
19037dd7cddfSDavid du Colombier }
19043e12c5d1SDavid du Colombier Bflush(&bout);
19053e12c5d1SDavid du Colombier
19063e12c5d1SDavid du Colombier while(ap = Brdline(&bin, '\n')){
19077dd7cddfSDavid du Colombier ap[Blinelen(&bin)-1] = 0;
1908219b2ee8SDavid du Colombier switch(ac = parse(ap, av, nelem(av))){
19093e12c5d1SDavid du Colombier
19103e12c5d1SDavid du Colombier default:
1911*fd362a73SDavid du Colombier for(cp = scsicmds; cp->name; cp++){
19123e12c5d1SDavid du Colombier if(strcmp(cp->name, av[0]) == 0)
19133e12c5d1SDavid du Colombier break;
19143e12c5d1SDavid du Colombier }
19153e12c5d1SDavid du Colombier if(cp->name == 0){
19163e12c5d1SDavid du Colombier Bprint(&bout, "eh?\n");
19173e12c5d1SDavid du Colombier break;
19183e12c5d1SDavid du Colombier }
19193e12c5d1SDavid du Colombier if((target.flags & Fopen) == 0 && cp->open){
19203e12c5d1SDavid du Colombier Bprint(&bout, "no current target\n");
19213e12c5d1SDavid du Colombier break;
19223e12c5d1SDavid du Colombier }
19233e12c5d1SDavid du Colombier if((status = (*cp->f)(&target, ac-1, &av[1])) != -1){
19243e12c5d1SDavid du Colombier if(verbose)
19253e12c5d1SDavid du Colombier Bprint(&bout, "ok %ld\n", status);
19263e12c5d1SDavid du Colombier break;
19273e12c5d1SDavid du Colombier }
19287dd7cddfSDavid du Colombier for(i = 0; description[i].description; i++){
19297dd7cddfSDavid du Colombier if(target.status != description[i].status)
19307dd7cddfSDavid du Colombier continue;
19317dd7cddfSDavid du Colombier if(target.status == Status_SD)
19323e12c5d1SDavid du Colombier makesense(&target);
19337dd7cddfSDavid du Colombier else
19347dd7cddfSDavid du Colombier Bprint(&bout, "%s\n", description[i].description);
19353e12c5d1SDavid du Colombier break;
19363e12c5d1SDavid du Colombier }
19373e12c5d1SDavid du Colombier break;
19383e12c5d1SDavid du Colombier
19393e12c5d1SDavid du Colombier case -1:
19403e12c5d1SDavid du Colombier Bprint(&bout, "eh?\n");
19413e12c5d1SDavid du Colombier break;
19423e12c5d1SDavid du Colombier
19433e12c5d1SDavid du Colombier case 0:
19443e12c5d1SDavid du Colombier break;
19453e12c5d1SDavid du Colombier }
19463e12c5d1SDavid du Colombier Bflush(&bout);
19473e12c5d1SDavid du Colombier }
19483e12c5d1SDavid du Colombier exits(0);
19493e12c5d1SDavid du Colombier }
1950e6dcbf51SDavid du Colombier
1951e6dcbf51SDavid du Colombier /* USB mass storage fake */
1952e6dcbf51SDavid du Colombier long
umsrequest(Umsc * umsc,ScsiPtr * cmd,ScsiPtr * data,int * status)1953e6dcbf51SDavid du Colombier umsrequest(Umsc *umsc, ScsiPtr *cmd, ScsiPtr *data, int *status)
1954e6dcbf51SDavid du Colombier {
1955e6dcbf51SDavid du Colombier USED(umsc, data, cmd);
1956e6dcbf51SDavid du Colombier *status = STharderr;
1957e6dcbf51SDavid du Colombier return -1;
1958e6dcbf51SDavid du Colombier }
1959