2491 lines · 46.0 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <bio.h> #include "scsireq.h" enum {					/* fundamental constants/defaults */	/*	 * default & maximum `maximum i/o size'; overridden by -m.	 * limits kernel memory consumption.	 * 240K is exabyte maximum block size.	 */	MaxIOsize	= 240*1024,}; #define MIN(a, b)	((a) < (b) ? (a): (b)) static char rwbuf[MaxIOsize];static int verbose = 1; Biobuf bin, bout;long maxiosize = MaxIOsize;int exabyte = 0;int force6bytecmds = 0; typedef struct {	char *name;	long (*f)(ScsiReq *, int, char *[]);	int open;	char *help;} ScsiCmd; static ScsiCmd scsicmd[]; static vlongvlmin(vlong a, vlong b){	if (a < b)		return a;	else		return b;} static longcmdready(ScsiReq *rp, int argc, char *argv[]){	USED(argc, argv);	return SRready(rp);} static longcmdrewind(ScsiReq *rp, int argc, char *argv[]){	USED(argc, argv);	return SRrewind(rp);} static longcmdreqsense(ScsiReq *rp, int argc, char *argv[]){	long nbytes; 	USED(argc, argv);	if((nbytes = SRreqsense(rp)) != -1)		makesense(rp);	return nbytes;} static longcmdformat(ScsiReq *rp, int argc, char *argv[]){	USED(argc, argv);	return SRformat(rp);} static longcmdrblimits(ScsiReq *rp, int argc, char *argv[]){	uchar l[6];	long n; 	USED(argc, argv);	if((n = SRrblimits(rp, l)) == -1)		return -1;	Bprint(&bout, " %2.2uX %2.2uX %2.2uX %2.2uX %2.2uX %2.2uX\n",		l[0], l[1], l[2], l[3], l[4], l[5]);	return n;} static intmkfile(char *file, int omode, int *pid){	int fd[2]; 	if(*file != '|'){		*pid = -1;		if(omode == OWRITE)			return create(file, OWRITE, 0666);		else if(omode == OREAD)			return open(file, OREAD);		return -1;	} 	file++;	if(*file == 0 || pipe(fd) == -1)		return -1;	if((*pid = fork()) == -1){		close(fd[0]);		close(fd[1]);		return -1;	}	if(*pid == 0){		switch(omode){ 		case OREAD:			dup(fd[0], 1);			break; 		case OWRITE:			dup(fd[0], 0);			break;		}		close(fd[0]);		close(fd[1]);		execl("/bin/rc", "rc", "-c", file, nil);		exits("exec");	}	close(fd[0]);	return fd[1];} intwaitfor(int pid){	int msg;	Waitmsg *w; 	while((w = wait()) != nil){		if(w->pid != pid){			free(w);			continue;		}		msg = (w->msg[0] != '\0');		free(w);		return msg;	}	return -1;} static longcmdread(ScsiReq *rp, int argc, char *argv[]){	long n, iosize, prevsize = 0;	vlong nbytes, total;	int fd, pid;	char *p; 	iosize = maxiosize;	nbytes = ~0ULL >> 1;	switch(argc){ 	default:		rp->status = Status_BADARG;		return -1; 	case 2:		nbytes = strtoll(argv[1], &p, 0);		if(nbytes == 0 && p == argv[1]){			rp->status = Status_BADARG;			return -1;		}		/*FALLTHROUGH*/ 	case 1:		if((fd = mkfile(argv[0], OWRITE, &pid)) == -1){			rp->status = Status_BADARG;			return -1;		}		break;	}	print("bsize=%lud\n", rp->lbsize);	total = 0;	while(nbytes){		n = vlmin(nbytes, iosize);		if((n = SRread(rp, rwbuf, n)) == -1){			if(total == 0)				total = -1;			break;		}		if (n == 0)			break;		if (prevsize != n) {			print("tape block size=%ld\n", n);			prevsize = n;		}		if(write(fd, rwbuf, n) != n){			if(total == 0)				total = -1;			if(rp->status == STok)				rp->status = Status_SW;			break;		}		nbytes -= n;		total += n;	}	close(fd);	if(pid >= 0 && waitfor(pid)){		rp->status = Status_SW;		return -1;	}	return total;} static longcmdwrite(ScsiReq *rp, int argc, char *argv[]){	long n, prevsize = 0;	vlong nbytes, total;	int fd, pid;	char *p; 	nbytes = ~0ULL >> 1;	switch(argc){ 	default:		rp->status = Status_BADARG;		return -1; 	case 2:		nbytes = strtoll(argv[1], &p, 0);		if(nbytes == 0 && p == argv[1]){			rp->status = Status_BADARG;			return -1;		}		/*FALLTHROUGH*/ 	case 1:		if((fd = mkfile(argv[0], OREAD, &pid)) == -1){			rp->status = Status_BADARG;			return -1;		}		break;	}	total = 0;	while(nbytes){		n = vlmin(nbytes, maxiosize);		if((n = read(fd, rwbuf, n)) == -1){			if(total == 0)				total = -1;			break;		}		if (n == 0)			break;		if (prevsize != n) {			print("tape block size=%ld\n", n);			prevsize = n;		}		if(SRwrite(rp, rwbuf, n) != n){			if(total == 0)				total = -1;			if(rp->status == STok)				rp->status = Status_SW;			break;		}		nbytes -= n;		total += n;	}	close(fd);	if(pid >= 0 && waitfor(pid)){		rp->status = Status_SW;		return -1;	}	return total;} static longcmdseek(ScsiReq *rp, int argc, char *argv[]){	char *p;	long offset;	int type; 	type = 0;	switch(argc){ 	default:		rp->status = Status_BADARG;		return -1; 	case 2:		if((type = strtol(argv[1], &p, 0)) == 0 && p == argv[1]){			rp->status = Status_BADARG;			return -1;		}		/*FALLTHROUGH*/ 	case 1:		if((offset = strtol(argv[0], &p, 0)) == 0 && p == argv[0]){			rp->status = Status_BADARG;			return -1;		}		break;	}	return SRseek(rp, offset, type);} static longcmdfilemark(ScsiReq *rp, int argc, char *argv[]){	char *p;	ulong howmany; 	howmany = 1;	if(argc && (howmany = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){		rp->status = Status_BADARG;		return -1;	}	return SRfilemark(rp, howmany);} static longcmdspace(ScsiReq *rp, int argc, char *argv[]){	uchar code;	long howmany;	char option, *p; 	code = 0x00;	howmany = 1;	while(argc && (*argv)[0] == '-'){		while(option = *++argv[0]){			switch(option){ 			case '-':				break; 			case 'b':				code = 0x00;				break; 			case 'f':				code = 0x01;				break; 			default:				rp->status = Status_BADARG;				return -1;			}			break;		}		argc--; argv++;		if(option == '-')			break;	}	if(argc && ((howmany = strtol(argv[0], &p, 0)) == 0 && p == argv[0])){		rp->status = Status_BADARG;		return -1;	}	return SRspace(rp, code, howmany);} static longcmdinquiry(ScsiReq *rp, int argc, char *argv[]){	long status;	int i, n;	uchar *p; 	USED(argc, argv);	if((status = SRinquiry(rp)) != -1){		n = rp->inquiry[4]+4;		for(i = 0; i < MIN(8, n); i++)			Bprint(&bout, " %2.2uX", rp->inquiry[i]);		p = &rp->inquiry[8];		n = MIN(n, sizeof(rp->inquiry)-8);		while(n && (*p == ' ' || *p == '\t' || *p == '\n')){			n--;			p++;		}		Bprint(&bout, "\t%.*s\n", n, (char*)p);	}	return status;} static longcmdmodeselect6(ScsiReq *rp, int argc, char *argv[]){	uchar list[MaxDirData];	long nbytes, ul;	char *p; 	memset(list, 0, sizeof list);	for(nbytes = 0; argc; argc--, argv++, nbytes++){		if((ul = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){			rp->status = Status_BADARG;			return -1;		}		list[nbytes] = ul; 	}	if(!(rp->flags & Finqok) && SRinquiry(rp) == -1)		Bprint(&bout, "warning: couldn't determine whether SCSI-1/SCSI-2 mode");	return SRmodeselect6(rp, list, nbytes);} longsel(ScsiReq *rp, uchar *list, long nbytes, int save){	uchar cmd[10]; 	memset(cmd, 0, sizeof cmd);	cmd[0] = 0x55;	cmd[1] = 0x10 | save!=0;		/* standard (scsi-2) format */	cmd[7] = nbytes>>8;	cmd[8] = nbytes;	rp->cmd.p = cmd;	rp->cmd.count = sizeof cmd;	rp->data.p = list;	rp->data.count = nbytes;	rp->data.write = 1;	return SRrequest(rp);} static longcmdmodeselect10(ScsiReq *rp, int argc, char *argv[]){	uchar list[MaxDirData];	int nbytes, save;	char *p; 	save = 0;	if(argc >= 1 && strcmp(*argv, "-s") == 0){		save = 1;		argv++;		argc--;	} 	if(argc >= nelem(list)){		rp->status = Status_BADARG;		return -1;	}	memset(list, 0, sizeof list);	for(nbytes = 0; argc; argc--, argv++, nbytes++)		if((list[nbytes] = strtoul(argv[0], &p, 0)) == 0 && p == argv[0]){			rp->status = Status_BADARG;			return -1;		}	if(!(rp->flags & Finqok) && SRinquiry(rp) == -1)		Bprint(&bout, "warning: couldn't determine whether SCSI-1/SCSI-2 mode");print("%d %d\n", nbytes, (rp->flags & Finqok) && (rp->inquiry[2] & 0x07) >= 2);//	return SRmodeselect10(rp, list, nbytes);	return sel(rp, list, nbytes, save);} static char*pflag(char *s, char *e, uint f, char **tab, uint ntab){	char *s0;	uchar i; 	s0 = s;	for(i = 0; i < ntab; i++)		if(f & (1 << i))			s = seprint(s, e, "%s ", tab[i]);	if(s > s0 && s[-1] == ' ')		s--;	*s = 0;	return s;} static char*xlatenum(uint f, char **tab, uint ntab){	static char buf[64]; 	if(f < ntab && tab[f])		return tab[f];	snprint(buf, sizeof buf, "unknown val %#ux", f);	return buf;} static char *recftab[] = {[0]	"dcr",[1]	"dte",[2]	"per",[3]	"eer",[4]	"rc",[5]	"tb",[6]	"arre",[7]	"awre",};voidrecoverpage(uchar *u){ 	char buf[128];	uint t; 	pflag(buf, buf + sizeof buf, u[2], recftab, nelem(recftab));	t = u[10]<<8 | u[11];

Lines 1–500 of 2491.