plan 9 kernel history: overview | file list | diff list

1995/0726/pc/scsi.c (diff list | history)

1993/0915/sys/src/9/pc/scsi.c:4,841994/0908/sys/src/9/pc/scsi.c:4,343 (short | long)
1993/0915    
#include "dat.h" 
#include "fns.h" 
#include "io.h" 
1994/0908    
#include "ureg.h" 
1993/0915    
#include "../port/error.h" 
1994/0908    
#include "../port/netif.h" 
1993/0915    
 
/* 
 * Known to devscsi.c. 
int scsidebugs[8]; 
int scsiownid = CtlrID; 
 */ 
1994/0908    
enum { 
	Ninq		= 255, 
	Nscratch	= 255, 
1993/0915    
 
1994/0908    
	CMDreqsense	= 0x03, 
	CMDinquire	= 0x12, 
}; 
 
typedef struct { 
	ISAConf; 
	Scsiio	io; 
 
	Target	target[NTarget]; 
} Ctlr; 
 
static Ctlr *scsi[MaxScsi]; 
 
static struct { 
	char	*type; 
	Scsiio	(*reset)(int, ISAConf*); 
} cards[MaxScsi+1]; 
 
1993/0915    
void 
initscsi(void) 
1994/0908    
addscsicard(char *t, Scsiio (*r)(int, ISAConf*)) 
1993/0915    
{ 
1994/0908    
	static int ncard; 
 
	if(ncard == MaxScsi) 
		panic("too many scsi cards\n"); 
	cards[ncard].type = t; 
	cards[ncard].reset = r; 
	ncard++; 
1993/0915    
} 
 
/* 
 * Quick hack. Need to do a better job of dynamic initialisation 
 * for machines with peculiar memory/cache restictions. 
 * Also, what about 16Mb address limit on the Adaptec? 
 */ 
static ulong bufdatasize; 
                 
void 
scsibufreset(ulong datasize) 
1994/0908    
scsireset(void) 
1993/0915    
{ 
	bufdatasize = datasize; 
1994/0908    
	Ctlr *ctlr; 
	int ctlrno, n, t; 
 
	for(ctlr = 0, ctlrno = 0; ctlrno < MaxScsi; ctlrno++){ 
		if(ctlr == 0) 
			ctlr = malloc(sizeof(Ctlr)); 
		memset(ctlr, 0, sizeof(Ctlr)); 
		if(isaconfig("scsi", ctlrno, ctlr) == 0) 
			continue; 
		for(n = 0; cards[n].type; n++){ 
			if(strcmp(cards[n].type, ctlr->type)) 
				continue; 
			if((ctlr->io = (*cards[n].reset)(ctlrno, ctlr)) == 0) 
				break; 
 
			print("scsi%d: %s: port %lux irq %d addr %lux size %d\n", 
				ctlrno, ctlr->type, ctlr->port, 
				ctlr->irq, ctlr->mem, ctlr->size); 
 
			for(t = 0; t < NTarget; t++){ 
				ctlr->target[t].ctlrno = ctlrno; 
				ctlr->target[t].target = t; 
				ctlr->target[t].inq = xalloc(Ninq); 
				ctlr->target[t].scratch = xalloc(Nscratch); 
			} 
 
			scsi[ctlrno] = ctlr; 
			ctlr = 0; 
			break; 
		} 
	} 
	if(ctlr) 
		free(ctlr); 
1993/0915    
} 
 
Scsibuf * 
scsibuf(void) 
1994/0908    
int 
scsiexec(Target *tp, int rw, uchar *cmd, int cbytes, void *data, int *dbytes) 
1993/0915    
{ 
	Scsibuf *b; 
1994/0908    
	return (*scsi[tp->ctlrno]->io)(tp, rw, cmd, cbytes, data, dbytes); 
} 
1993/0915    
 
	b = smalloc(sizeof(*b)); 
	b->virt = smalloc(bufdatasize); 
	b->phys = (void *)(PADDR(b->virt)); 
	return b; 
1994/0908    
Target* 
scsiunit(int ctlr, int unit) 
{ 
	Target *t; 
 
	if(ctlr < 0 || ctlr >= MaxScsi || scsi[ctlr] == 0) 
		return 0; 
	if(unit < 0 || unit >= NTarget) 
		return 0; 
	t = &scsi[ctlr]->target[unit]; 
	if(t->ok == 0) 
		return 0; 
	return t; 
1993/0915    
} 
 
void 
scsifree(Scsibuf *b) 
1994/0908    
static void 
scsiprobe(Ctlr *ctlr) 
1993/0915    
{ 
	free(b->virt); 
	free(b); 
1994/0908    
	Target *tp; 
	uchar cmd[6]; 
	int i, s, nbytes; 
 
	for(i = 0; i < NTarget; i++) { 
		tp = &ctlr->target[i]; 
 
		/* 
		 * Test unit ready 
		 */ 
		memset(cmd, 0, sizeof(cmd)); 
		s = scsiexec(tp, SCSIread, cmd, sizeof(cmd), 0, 0); 
		if(s < 0) 
			continue; 
 
		/* 
		 * Determine if the drive exists and is not ready or 
		 * is simply not responding 
		 */ 
		if((s = scsireqsense(tp, 0, 0)) != STok){ 
			print("scsi%d: unit %d unavailable, status %d\n", tp->ctlrno, i, s); 
			continue; 
		} 
 
		/* 
		 * Inquire to find out what the device is 
		 * Drivers then use the result to attach to targets 
		 */ 
		memset(tp->inq, 0, Ninq); 
		cmd[0] = CMDinquire; 
		cmd[4] = Ninq; 
		nbytes = Ninq; 
		s = scsiexec(tp, SCSIread, cmd, sizeof(cmd), tp->inq, &nbytes); 
		if(s < 0) { 
			print("scsi%d: unit %d inquire failed, status %d\n", tp->ctlrno, i, s); 
			continue; 
		} 
		print("scsi%d: unit %d %s\n", tp->ctlrno, i, tp->inq+8); 
		tp->ok = 1; 
	} 
1993/0915    
} 
 
/* 
 * Hack for devvid 
 */ 
Scsibuf * 
scsialloc(ulong n) 
1994/0908    
static void 
inventory(void) 
1993/0915    
{ 
	Scsibuf *b; 
1994/0908    
	int i; 
	static Lock ilock; 
	static int inited; 
1993/0915    
 
	b = smalloc(sizeof(*b)); 
	b->virt = smalloc(n); 
	b->phys = (void *)(PADDR(b->virt)); 
	return b; 
1994/0908    
	lock(&ilock); 
	if(inited) { 
		unlock(&ilock); 
		return; 
	} 
	inited = 1; 
	unlock(&ilock); 
 
	for(i = 0; i < MaxScsi; i++){ 
		if(scsi[i]) 
			scsiprobe(scsi[i]); 
	} 
1993/0915    
} 
 
extern int (*aha1542reset(void))(Scsi*, int); 
extern int (*ultra14freset(void))(Scsi*, int); 
1994/0908    
int 
scsiinv(int devno, int type, Target **rt, uchar **inq, char *id) 
{ 
	Target *t; 
	int ctlr, unit; 
1993/0915    
 
static int (*exec)(Scsi*, int); 
1994/0908    
	inventory(); 
1993/0915    
 
1994/0908    
	for(;;){ 
		ctlr = devno/NTarget; 
		unit = devno%NTarget; 
		if(ctlr >= MaxScsi || scsi[ctlr] == 0) 
			return -1; 
 
		t = &scsi[ctlr]->target[unit]; 
		devno++; 
		if(t->ok && (t->inq[0]&0x0F) == type){ 
			*rt = t; 
			*inq = t->inq; 
			sprint(id, "scsi%d: unit %d", ctlr, unit); 
			return devno; 
		} 
	} 
	return -1; 
} 
 
1993/0915    
int 
scsiexec(Scsi *p, int rflag) 
1994/0908    
scsistart(Target *t, char lun, int s) 
1993/0915    
{ 
	if(exec == 0) 
		error(Enonexist); 
	return (*exec)(p, rflag); 
1994/0908    
	uchar cmd[6]; 
 
	memset(cmd, 0, sizeof cmd); 
	cmd[0] = 0x1b; 
	cmd[1] = lun<<5; 
	cmd[4] = s ? 1 : 0; 
	return scsiexec(t, SCSIread, cmd, sizeof(cmd), 0, 0); 
1993/0915    
} 
 
void 
resetscsi(void) 
1994/0908    
int 
scsicap(Target *t, char lun, ulong *size, ulong *bsize) 
1993/0915    
{ 
	if(exec = aha1542reset()) 
		return; 
	exec = ultra14freset(); 
1994/0908    
	int s, nbytes; 
	uchar cmd[10], *d; 
 
	memset(cmd, 0, sizeof(cmd)); 
	cmd[0] = 0x25; 
	cmd[1] = lun<<5; 
 
	d = malloc(8); 
	if(d == 0) 
		return -1; 
 
	nbytes = 8; 
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), d, &nbytes); 
	if(s < 0) { 
		free(d); 
		return s; 
	} 
	*size  = (d[0]<<24)|(d[1]<<16)|(d[2]<<8)|(d[3]<<0); 
	*bsize = (d[4]<<24)|(d[5]<<16)|(d[6]<<8)|(d[7]<<0); 
	free(d); 
	return 0; 
1993/0915    
} 
1994/0908    
 
int 
scsibio(Target *t, char lun, int dir, void *b, long n, long bsize, long bno) 
{ 
	uchar cmd[10]; 
	int s, cdbsiz, nbytes; 
 
	memset(cmd, 0, sizeof cmd); 
	if(bno <= 0x1fffff && n < 256) { 
		cmd[0] = 0x0A; 
		if(dir == SCSIread) 
			cmd[0] = 0x08; 
		cmd[1] = (lun<<5) | bno >> 16; 
		cmd[2] = bno >> 8; 
		cmd[3] = bno; 
		cmd[4] = n; 
		cdbsiz = 6; 
	} 
	else { 
		cmd[0] = 0x2A; 
		if(dir == SCSIread) 
			cmd[0] = 0x28; 
		cmd[1] = (lun<<5); 
		cmd[2] = bno >> 24; 
		cmd[3] = bno >> 16; 
		cmd[4] = bno >> 8; 
		cmd[5] = bno; 
		cmd[7] = n>>8; 
		cmd[8] = n; 
		cdbsiz = 10; 
	} 
	nbytes = n*bsize; 
	s = scsiexec(t, dir, cmd, cdbsiz, b, &nbytes); 
	if(s < 0) { 
		scsireqsense(t, lun, 0); 
		return -1; 
	} 
	return nbytes; 
} 
 
static char *key[] = 
{ 
	"no sense", 
	"recovered error", 
	"not ready", 
	"medium error", 
	"hardware error", 
	"illegal request", 
	"unit attention", 
	"data protect", 
	"blank check", 
	"vendor specific", 
	"copy aborted", 
	"aborted command", 
	"equal", 
	"volume overflow", 
	"miscompare", 
	"reserved" 
}; 
 
int 
scsireqsense(Target *tp, char lun, int quiet) 
{ 
	char *s; 
	int sr, try, nbytes; 
	uchar cmd[6], *sense; 
 
	sense = tp->scratch; 
 
	for(try = 0; try < 5; try++) { 
		memset(cmd, 0, sizeof(cmd)); 
		cmd[0] = CMDreqsense; 
		cmd[1] = lun<<5; 
		cmd[4] = Nscratch; 
		memset(sense, 0, sizeof(sense)); 
 
		nbytes = Nscratch; 
		sr = scsiexec(tp, SCSIread, cmd, sizeof(cmd), sense, &nbytes); 
		if(sr != STok) 
			return sr; 
 
		/* 
		 * Unit attention. We can handle that. 
		 */ 
		if((sense[2] & 0x0F) == 0x00 || (sense[2] & 0x0F) == 0x06) 
			return STok; 
 
		/* 
		 * Recovered error. Why bother telling me. 
		 */ 
		if((sense[2] & 0x0F) == 0x01) 
			return STok; 
 
		/* 
		 * Unit is becoming ready 
		 */ 
		if(sense[12] != 0x04 || sense[13] != 0x01) 
			break; 
 
		delay(5000); 
	} 
 
	if(quiet) 
		return STcheck; 
 
	s = key[sense[2]&0xf]; 
	print("scsi%d: unit %d reqsense: '%s' code #%2.2ux #%2.2ux\n", 
		tp->ctlrno, tp->target, s, sense[12], sense[13]); 
	return STcheck; 
} 
 
1994/0908/sys/src/9/pc/scsi.c:81,891995/0324/sys/src/9/pc/scsi.c:81,89 (short | long)
1993/0915    
} 
 
1994/0908    
int 
scsiexec(Target *tp, int rw, uchar *cmd, int cbytes, void *data, int *dbytes) 
1995/0324    
scsiexec(Target *t, int rw, uchar *cmd, int cbytes, void *data, int *dbytes) 
1993/0915    
{ 
1994/0908    
	return (*scsi[tp->ctlrno]->io)(tp, rw, cmd, cbytes, data, dbytes); 
1995/0324    
	return (*scsi[t->ctlrno]->io)(t, rw, cmd, cbytes, data, dbytes); 
1994/0908    
} 
1993/0915    
 
1994/0908    
Target* 
1994/0908/sys/src/9/pc/scsi.c:104,1211995/0324/sys/src/9/pc/scsi.c:104,121
1994/0908    
static void 
scsiprobe(Ctlr *ctlr) 
1993/0915    
{ 
1994/0908    
	Target *tp; 
1995/0324    
	Target *t; 
1994/0908    
	uchar cmd[6]; 
	int i, s, nbytes; 
 
	for(i = 0; i < NTarget; i++) { 
		tp = &ctlr->target[i]; 
1995/0324    
		t = &ctlr->target[i]; 
1994/0908    
 
		/* 
		 * Test unit ready 
		 */ 
		memset(cmd, 0, sizeof(cmd)); 
		s = scsiexec(tp, SCSIread, cmd, sizeof(cmd), 0, 0); 
1995/0324    
		s = scsiexec(t, SCSIread, cmd, sizeof(cmd), 0, 0); 
1994/0908    
		if(s < 0) 
			continue; 
 
1994/0908/sys/src/9/pc/scsi.c:123,1301995/0324/sys/src/9/pc/scsi.c:123,130
1994/0908    
		 * Determine if the drive exists and is not ready or 
		 * is simply not responding 
		 */ 
		if((s = scsireqsense(tp, 0, 0)) != STok){ 
			print("scsi%d: unit %d unavailable, status %d\n", tp->ctlrno, i, s); 
1995/0324    
		if((s = scsireqsense(t, 0, 0)) != STok){ 
			print("scsi%d: unit %d unavailable, status %d\n", t->ctlrno, i, s); 
1994/0908    
			continue; 
		} 
 
1994/0908/sys/src/9/pc/scsi.c:132,1481995/0324/sys/src/9/pc/scsi.c:132,148
1994/0908    
		 * Inquire to find out what the device is 
		 * Drivers then use the result to attach to targets 
		 */ 
		memset(tp->inq, 0, Ninq); 
1995/0324    
		memset(t->inq, 0, Ninq); 
1994/0908    
		cmd[0] = CMDinquire; 
		cmd[4] = Ninq; 
		nbytes = Ninq; 
		s = scsiexec(tp, SCSIread, cmd, sizeof(cmd), tp->inq, &nbytes); 
1995/0324    
		s = scsiexec(t, SCSIread, cmd, sizeof(cmd), t->inq, &nbytes); 
1994/0908    
		if(s < 0) { 
			print("scsi%d: unit %d inquire failed, status %d\n", tp->ctlrno, i, s); 
1995/0324    
			print("scsi%d: unit %d inquire failed, status %d\n", t->ctlrno, i, s); 
1994/0908    
			continue; 
		} 
		print("scsi%d: unit %d %s\n", tp->ctlrno, i, tp->inq+8); 
		tp->ok = 1; 
1995/0324    
		print("scsi%d: unit %d %s\n", t->ctlrno, i, t->inq+8); 
		t->ok = 1; 
1994/0908    
	} 
1993/0915    
} 
 
1994/0908/sys/src/9/pc/scsi.c:291,3031995/0324/sys/src/9/pc/scsi.c:291,303
1994/0908    
}; 
 
int 
scsireqsense(Target *tp, char lun, int quiet) 
1995/0324    
scsireqsense(Target *t, char lun, int quiet) 
1994/0908    
{ 
	char *s; 
	int sr, try, nbytes; 
	uchar cmd[6], *sense; 
 
	sense = tp->scratch; 
1995/0324    
	sense = t->scratch; 
1994/0908    
 
	for(try = 0; try < 5; try++) { 
		memset(cmd, 0, sizeof(cmd)); 
1994/0908/sys/src/9/pc/scsi.c:307,3131995/0324/sys/src/9/pc/scsi.c:307,313
1994/0908    
		memset(sense, 0, sizeof(sense)); 
 
		nbytes = Nscratch; 
		sr = scsiexec(tp, SCSIread, cmd, sizeof(cmd), sense, &nbytes); 
1995/0324    
		sr = scsiexec(t, SCSIread, cmd, sizeof(cmd), sense, &nbytes); 
1994/0908    
		if(sr != STok) 
			return sr; 
 
1994/0908/sys/src/9/pc/scsi.c:337,3431995/0324/sys/src/9/pc/scsi.c:337,343
1994/0908    
 
	s = key[sense[2]&0xf]; 
	print("scsi%d: unit %d reqsense: '%s' code #%2.2ux #%2.2ux\n", 
		tp->ctlrno, tp->target, s, sense[12], sense[13]); 
1995/0324    
		t->ctlrno, t->target, s, sense[12], sense[13]); 
1994/0908    
	return STcheck; 
} 
 
1995/0324/sys/src/9/pc/scsi.c:25,451995/0328/sys/src/9/pc/scsi.c:25,54 (short | long)
1994/0908    
 
static Ctlr *scsi[MaxScsi]; 
 
static struct { 
1995/0328    
typedef struct Link Link; 
typedef struct Link { 
1994/0908    
	char	*type; 
	Scsiio	(*reset)(int, ISAConf*); 
} cards[MaxScsi+1]; 
 
1995/0328    
	Link*	link; 
} Link; 
 
static Link *link; 
static int linkcount; 
 
1993/0915    
void 
1994/0908    
addscsicard(char *t, Scsiio (*r)(int, ISAConf*)) 
1995/0328    
addscsilink(char *t, Scsiio (*r)(int, ISAConf*)) 
1993/0915    
{ 
1994/0908    
	static int ncard; 
1995/0328    
	Link *lp; 
1994/0908    
 
	if(ncard == MaxScsi) 
		panic("too many scsi cards\n"); 
	cards[ncard].type = t; 
	cards[ncard].reset = r; 
	ncard++; 
1995/0328    
	if((lp = xalloc(sizeof(Link))) == 0) 
		return; 
	lp->type = t; 
	lp->reset = r; 
 
	lp->link = link; 
	link = lp; 
	linkcount++; 
1993/0915    
} 
 
void 
1995/0324/sys/src/9/pc/scsi.c:46,521995/0328/sys/src/9/pc/scsi.c:55,62
1994/0908    
scsireset(void) 
1993/0915    
{ 
1994/0908    
	Ctlr *ctlr; 
	int ctlrno, n, t; 
1995/0328    
	int ctlrno, t; 
	Link *lp; 
1994/0908    
 
	for(ctlr = 0, ctlrno = 0; ctlrno < MaxScsi; ctlrno++){ 
		if(ctlr == 0) 
1995/0324/sys/src/9/pc/scsi.c:54,681995/0328/sys/src/9/pc/scsi.c:64,81
1994/0908    
		memset(ctlr, 0, sizeof(Ctlr)); 
		if(isaconfig("scsi", ctlrno, ctlr) == 0) 
			continue; 
		for(n = 0; cards[n].type; n++){ 
			if(strcmp(cards[n].type, ctlr->type)) 
1995/0328    
		for(lp = link; lp; lp = lp->link){ 
			if(strcmp(lp->type, ctlr->type)) 
1994/0908    
				continue; 
			if((ctlr->io = (*cards[n].reset)(ctlrno, ctlr)) == 0) 
1995/0328    
			if((ctlr->io = (*lp->reset)(ctlrno, ctlr)) == 0) 
1994/0908    
				break; 
 
			print("scsi%d: %s: port %lux irq %d addr %lux size %d\n", 
1995/0328    
			print("scsi%d: %s: port %lux irq %d", 
1994/0908    
				ctlrno, ctlr->type, ctlr->port, 
				ctlr->irq, ctlr->mem, ctlr->size); 
1995/0328    
			if(ctlr->mem) 
				print(" addr %lux size %d\n", ctlr->mem, ctlr->size); 
			print("\n"); 
1994/0908    
 
			for(t = 0; t < NTarget; t++){ 
				ctlr->target[t].ctlrno = ctlrno; 
1995/0328/sys/src/9/pc/scsi.c:12,191995/0329/sys/src/9/pc/scsi.c:12,25 (short | long)
1994/0908    
	Ninq		= 255, 
	Nscratch	= 255, 
1993/0915    
 
1995/0329    
	CMDtest		= 0x00, 
1994/0908    
	CMDreqsense	= 0x03, 
1995/0329    
	CMDread6	= 0x08, 
	CMDwrite6	= 0x0A, 
1994/0908    
	CMDinquire	= 0x12, 
1995/0329    
	CMDstart	= 0x1B, 
	CMDread10	= 0x28, 
	CMDwrite10	= 0x2A, 
1994/0908    
}; 
 
typedef struct { 
1995/0328/sys/src/9/pc/scsi.c:142,1551995/0329/sys/src/9/pc/scsi.c:148,159
1994/0908    
		} 
 
		/* 
		 * Inquire to find out what the device is 
1995/0329    
		 * Inquire to find out what the device is. 
1994/0908    
		 * Drivers then use the result to attach to targets 
		 */ 
1995/0324    
		memset(t->inq, 0, Ninq); 
1994/0908    
		cmd[0] = CMDinquire; 
		cmd[4] = Ninq; 
		nbytes = Ninq; 
1995/0324    
		s = scsiexec(t, SCSIread, cmd, sizeof(cmd), t->inq, &nbytes); 
1995/0329    
		s = scsiinquiry(t, 0, t->inq, &nbytes); 
1994/0908    
		if(s < 0) { 
1995/0324    
			print("scsi%d: unit %d inquire failed, status %d\n", t->ctlrno, i, s); 
1994/0908    
			continue; 
1995/0328/sys/src/9/pc/scsi.c:196,2021995/0329/sys/src/9/pc/scsi.c:200,206
1994/0908    
 
		t = &scsi[ctlr]->target[unit]; 
		devno++; 
		if(t->ok && (t->inq[0]&0x0F) == type){ 
1995/0329    
		if(t->ok && (t->inq[0]&0x1F) == type){ 
1994/0908    
			*rt = t; 
			*inq = t->inq; 
			sprint(id, "scsi%d: unit %d", ctlr, unit); 
1995/0328/sys/src/9/pc/scsi.c:212,2211995/0329/sys/src/9/pc/scsi.c:216,237
1994/0908    
	uchar cmd[6]; 
 
	memset(cmd, 0, sizeof cmd); 
	cmd[0] = 0x1b; 
1995/0329    
	cmd[0] = CMDstart; 
1994/0908    
	cmd[1] = lun<<5; 
	cmd[4] = s ? 1 : 0; 
	return scsiexec(t, SCSIread, cmd, sizeof(cmd), 0, 0); 
1995/0329    
} 
 
int 
scsiinquiry(Target *t, char lun, void *data, int *datalen) 
{ 
	uchar cmd[6]; 
 
	memset(cmd, 0, sizeof cmd); 
	cmd[0] = CMDinquire; 
	cmd[1] = lun<<5; 
	cmd[4] = *datalen; 
	return scsiexec(t, SCSIread, cmd, sizeof(cmd), data, datalen); 
1993/0915    
} 
 
1994/0908    
int 
1995/0329/sys/src/9/pc/scsi.c:158,1641995/0403/sys/src/9/pc/scsi.c:158,164 (short | long)
1995/0324    
			print("scsi%d: unit %d inquire failed, status %d\n", t->ctlrno, i, s); 
1994/0908    
			continue; 
		} 
1995/0324    
		print("scsi%d: unit %d %s\n", t->ctlrno, i, t->inq+8); 
1995/0403    
		print("scsi%d: unit %d:%2.2ux: %s\n", t->ctlrno, i, t->inq[0], t->inq+8); 
1995/0324    
		t->ok = 1; 
1994/0908    
	} 
1993/0915    
} 
1995/0329/sys/src/9/pc/scsi.c:185,1941995/0403/sys/src/9/pc/scsi.c:185,194
1993/0915    
} 
 
1994/0908    
int 
scsiinv(int devno, int type, Target **rt, uchar **inq, char *id) 
1995/0403    
scsiinv(int devno, int *type, Target **rt, uchar **inq, char *id) 
1994/0908    
{ 
	Target *t; 
	int ctlr, unit; 
1995/0403    
	int ctlr, *i, unit; 
1993/0915    
 
1994/0908    
	inventory(); 
1993/0915    
 
1995/0329/sys/src/9/pc/scsi.c:200,2101995/0403/sys/src/9/pc/scsi.c:200,215
1994/0908    
 
		t = &scsi[ctlr]->target[unit]; 
		devno++; 
1995/0329    
		if(t->ok && (t->inq[0]&0x1F) == type){ 
1994/0908    
			*rt = t; 
			*inq = t->inq; 
			sprint(id, "scsi%d: unit %d", ctlr, unit); 
			return devno; 
1995/0403    
		if(t->ok){ 
			for(i = type; *i >= 0; i++){ 
				if((t->inq[0]&0x1F) != *i) 
					continue; 
				*rt = t; 
				*inq = t->inq; 
				sprint(id, "scsi%d: unit %d", ctlr, unit); 
print("devno %d = %s\n", devno, id); 
				return devno; 
			} 
1994/0908    
		} 
	} 
	return -1; 
1995/0403/sys/src/9/pc/scsi.c:124,1411995/0404/sys/src/9/pc/scsi.c:124,135 (short | long)
1994/0908    
scsiprobe(Ctlr *ctlr) 
1993/0915    
{ 
1995/0324    
	Target *t; 
1994/0908    
	uchar cmd[6]; 
	int i, s, nbytes; 
 
	for(i = 0; i < NTarget; i++) { 
1995/0324    
		t = &ctlr->target[i]; 
1994/0908    
 
		/* 
		 * Test unit ready 
		 */ 
		memset(cmd, 0, sizeof(cmd)); 
1995/0324    
		s = scsiexec(t, SCSIread, cmd, sizeof(cmd), 0, 0); 
1994/0908    
		if(s < 0) 
1995/0404    
		if(scsitest(t, 0) < 0) 
1994/0908    
			continue; 
 
		/* 
1995/0403/sys/src/9/pc/scsi.c:213,2181995/0404/sys/src/9/pc/scsi.c:207,224
1994/0908    
		} 
	} 
	return -1; 
1995/0404    
} 
 
 
int 
scsitest(Target *t, char lun) 
{ 
	uchar cmd[6]; 
 
	memset(cmd, 0, sizeof(cmd)); 
	cmd[0] = CMDtest; 
	cmd[1] = lun<<5; 
	return scsiexec(t, SCSIread, cmd, sizeof(cmd), 0, 0); 
1994/0908    
} 
 
1993/0915    
int 
1995/0404/sys/src/9/pc/scsi.c:136,1421995/0405/sys/src/9/pc/scsi.c:136,144 (short | long)
1994/0908    
		 * Determine if the drive exists and is not ready or 
		 * is simply not responding 
		 */ 
1995/0324    
		if((s = scsireqsense(t, 0, 0)) != STok){ 
1995/0405    
		nbytes = Nscratch; 
		s = scsireqsense(t, 0, t->scratch, &nbytes, 0); 
		if(s != STok){ 
1995/0324    
			print("scsi%d: unit %d unavailable, status %d\n", t->ctlrno, i, s); 
1994/0908    
			continue; 
		} 
1995/0404/sys/src/9/pc/scsi.c:152,1581995/0405/sys/src/9/pc/scsi.c:154,160
1995/0324    
			print("scsi%d: unit %d inquire failed, status %d\n", t->ctlrno, i, s); 
1994/0908    
			continue; 
		} 
1995/0403    
		print("scsi%d: unit %d:%2.2ux: %s\n", t->ctlrno, i, t->inq[0], t->inq+8); 
1995/0405    
		print("scsi%d: unit %d: %s\n", t->ctlrno, i, t->inq+8); 
1995/0324    
		t->ok = 1; 
1994/0908    
	} 
1993/0915    
} 
1995/0404/sys/src/9/pc/scsi.c:260,2741995/0405/sys/src/9/pc/scsi.c:262,273
1994/0908    
		return -1; 
 
	nbytes = 8; 
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), d, &nbytes); 
	if(s < 0) { 
		free(d); 
		return s; 
1995/0405    
	if((s = scsiexec(t, SCSIread, cmd, sizeof(cmd), d, &nbytes)) == STok){ 
		*size  = (d[0]<<24)|(d[1]<<16)|(d[2]<<8)|(d[3]<<0); 
		*bsize = (d[4]<<24)|(d[5]<<16)|(d[6]<<8)|(d[7]<<0); 
1994/0908    
	} 
	*size  = (d[0]<<24)|(d[1]<<16)|(d[2]<<8)|(d[3]<<0); 
	*bsize = (d[4]<<24)|(d[5]<<16)|(d[6]<<8)|(d[7]<<0); 
	free(d); 
	return 0; 
1995/0405    
	return s; 
1993/0915    
} 
1994/0908    
 
int 
1995/0404/sys/src/9/pc/scsi.c:304,3101995/0405/sys/src/9/pc/scsi.c:303,310
1994/0908    
	nbytes = n*bsize; 
	s = scsiexec(t, dir, cmd, cdbsiz, b, &nbytes); 
	if(s < 0) { 
		scsireqsense(t, lun, 0); 
1995/0405    
		nbytes = Nscratch; 
		scsireqsense(t, lun, t->scratch, &nbytes, 0); 
1994/0908    
		return -1; 
	} 
	return nbytes; 
1995/0404/sys/src/9/pc/scsi.c:331,3671995/0405/sys/src/9/pc/scsi.c:331,374
1994/0908    
}; 
 
int 
1995/0324    
scsireqsense(Target *t, char lun, int quiet) 
1995/0405    
scsireqsense(Target *t, char lun, void *data, int *nbytes, int quiet) 
1994/0908    
{ 
	char *s; 
	int sr, try, nbytes; 
1995/0405    
	int status, try; 
1994/0908    
	uchar cmd[6], *sense; 
 
1995/0324    
	sense = t->scratch; 
1995/0405    
	sense = malloc(*nbytes); 
1994/0908    
 
	for(try = 0; try < 5; try++) { 
		memset(cmd, 0, sizeof(cmd)); 
		cmd[0] = CMDreqsense; 
		cmd[1] = lun<<5; 
		cmd[4] = Nscratch; 
		memset(sense, 0, sizeof(sense)); 
1995/0405    
		cmd[4] = *nbytes; 
		memset(sense, 0, *nbytes); 
1994/0908    
 
		nbytes = Nscratch; 
1995/0324    
		sr = scsiexec(t, SCSIread, cmd, sizeof(cmd), sense, &nbytes); 
1994/0908    
		if(sr != STok) 
			return sr; 
1995/0405    
		status = scsiexec(t, SCSIread, cmd, sizeof(cmd), sense, nbytes); 
		if(status != STok){ 
			free(sense); 
			return status; 
		} 
		*nbytes = sense[0x07]+8; 
		memmove(data, sense, *nbytes); 
1994/0908    
 
		/* 
		 * Unit attention. We can handle that. 
		 */ 
		if((sense[2] & 0x0F) == 0x00 || (sense[2] & 0x0F) == 0x06) 
1995/0405    
		if((sense[2] & 0x0F) == 0x00 || (sense[2] & 0x0F) == 0x06){ 
			free(sense); 
1994/0908    
			return STok; 
1995/0405    
		} 
1994/0908    
 
		/* 
		 * Recovered error. Why bother telling me. 
		 */ 
		if((sense[2] & 0x0F) == 0x01) 
1995/0405    
		if((sense[2] & 0x0F) == 0x01){ 
			free(sense); 
1994/0908    
			return STok; 
1995/0405    
		} 
1994/0908    
 
		/* 
		 * Unit is becoming ready 
1995/0404/sys/src/9/pc/scsi.c:372,3831995/0405/sys/src/9/pc/scsi.c:379,390
1994/0908    
		delay(5000); 
	} 
 
	if(quiet) 
		return STcheck; 
                 
	s = key[sense[2]&0xf]; 
	print("scsi%d: unit %d reqsense: '%s' code #%2.2ux #%2.2ux\n", 
1995/0324    
		t->ctlrno, t->target, s, sense[12], sense[13]); 
1995/0405    
	if(quiet == 0){ 
		s = key[sense[2]&0x0F]; 
		print("scsi%d: unit %d reqsense: '%s' code #%2.2ux #%2.2ux\n", 
			t->ctlrno, t->target, s, sense[12], sense[13]); 
	} 
	free(sense); 
1994/0908    
	return STcheck; 
} 
 
1995/0405/sys/src/9/pc/scsi.c:76,861995/0513/sys/src/9/pc/scsi.c:76,88 (short | long)
1995/0328    
			if((ctlr->io = (*lp->reset)(ctlrno, ctlr)) == 0) 
1994/0908    
				break; 
 
1995/0328    
			print("scsi%d: %s: port %lux irq %d", 
1995/0513    
			print("scsi%d: %s: port 0x%luX irq %d", 
1994/0908    
				ctlrno, ctlr->type, ctlr->port, 
				ctlr->irq, ctlr->mem, ctlr->size); 
1995/0328    
			if(ctlr->mem) 
				print(" addr %lux size %d\n", ctlr->mem, ctlr->size); 
1995/0513    
				print(" addr 0x%luX", ctlr->mem & ~KZERO); 
			if(ctlr->size) 
				print(" size 0x%luX", ctlr->size); 
1995/0328    
			print("\n"); 
1994/0908    
 
			for(t = 0; t < NTarget; t++){ 
1995/0405/sys/src/9/pc/scsi.c:203,2091995/0513/sys/src/9/pc/scsi.c:205,210
1995/0403    
				*rt = t; 
				*inq = t->inq; 
				sprint(id, "scsi%d: unit %d", ctlr, unit); 
print("devno %d = %s\n", devno, id); 
				return devno; 
			} 
1994/0908    
		} 
1995/0513/sys/src/9/pc/scsi.c:6,121995/0712/sys/src/9/pc/scsi.c:6,11 (short | long)
1993/0915    
#include "io.h" 
1994/0908    
#include "ureg.h" 
1993/0915    
#include "../port/error.h" 
1994/0908    
#include "../port/netif.h" 
1993/0915    
 
1994/0908    
enum { 
	Ninq		= 255, 
1995/0712/sys/src/9/pc/scsi.c:7,131995/0722/sys/src/9/pc/scsi.c:7,14 (short | long)
1994/0908    
#include "ureg.h" 
1993/0915    
#include "../port/error.h" 
 
1994/0908    
enum { 
1995/0722    
enum 
{ 
1994/0908    
	Ninq		= 255, 
	Nscratch	= 255, 
1993/0915    
 
1995/0712/sys/src/9/pc/scsi.c:21,271995/0722/sys/src/9/pc/scsi.c:22,29
1995/0329    
	CMDwrite10	= 0x2A, 
1994/0908    
}; 
 
typedef struct { 
1995/0722    
typedef struct 
{ 
1994/0908    
	ISAConf; 
	Scsiio	io; 
 
1995/0712/sys/src/9/pc/scsi.c:31,371995/0722/sys/src/9/pc/scsi.c:33,40
1994/0908    
static Ctlr *scsi[MaxScsi]; 
 
1995/0328    
typedef struct Link Link; 
typedef struct Link { 
1995/0722    
typedef struct Link 
{ 
1994/0908    
	char	*type; 
	Scsiio	(*reset)(int, ISAConf*); 
 
1995/0712/sys/src/9/pc/scsi.c:231,2371995/0722/sys/src/9/pc/scsi.c:234,240
1994/0908    
	memset(cmd, 0, sizeof cmd); 
1995/0329    
	cmd[0] = CMDstart; 
1994/0908    
	cmd[1] = lun<<5; 
	cmd[4] = s ? 1 : 0; 
1995/0722    
	cmd[4] = s? 1: 0; 
1994/0908    
	return scsiexec(t, SCSIread, cmd, sizeof(cmd), 0, 0); 
1995/0329    
} 
 
1995/0712/sys/src/9/pc/scsi.c:388,3901995/0722/sys/src/9/pc/scsi.c:391,437
1994/0908    
	return STcheck; 
} 
 
1995/0722    
int 
scsidiskinfo(Target *t, char lun, uchar *data) 
{ 
	int s, nbytes, try; 
	uchar cmd[10]; 
 
	for(try=0; try<3; try++) { 
 
		nbytes = 4; 
 
		memset(cmd, 0, sizeof(cmd)); 
		cmd[0] = 0x43; 
		cmd[1] = lun<<5; 
		cmd[7] = nbytes>>8; 
		cmd[8] = nbytes>>0; 
 
		s = scsiexec(t, SCSIread, cmd, sizeof(cmd), data, &nbytes); 
		if(s == STok) 
			break; 
 
		nbytes = Nscratch; 
		scsireqsense(t, lun, t->scratch, &nbytes, 0); 
	} 
	return s; 
} 
 
int 
scsitrackinfo(Target *t, char lun, int track, uchar *data) 
{ 
	int s, nbytes; 
	uchar cmd[10]; 
 
	nbytes = 12; 
 
	memset(cmd, 0, sizeof(cmd)); 
	cmd[0] = 0xe5; 
	cmd[1] = lun<<5; 
	cmd[5] = track; 
	cmd[7] = nbytes>>8; 
	cmd[8] = nbytes>>0; 
 
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), data, &nbytes); 
	return s; 
} 
1995/0722/sys/src/9/pc/scsi.c:30,361995/0723/sys/src/9/pc/scsi.c:30,36 (short | long)
1994/0908    
	Target	target[NTarget]; 
} Ctlr; 
 
static Ctlr *scsi[MaxScsi]; 
1995/0723    
static	Ctlr*	scsi[MaxScsi]; 
1994/0908    
 
1995/0328    
typedef struct Link Link; 
1995/0722    
typedef struct Link 
1995/0722/sys/src/9/pc/scsi.c:260,2751995/0723/sys/src/9/pc/scsi.c:260,276
1994/0908    
	cmd[0] = 0x25; 
	cmd[1] = lun<<5; 
 
	d = malloc(8); 
1995/0723    
	nbytes = 8; 
	d = scsialloc(nbytes); 
1994/0908    
	if(d == 0) 
		return -1; 
1995/0723    
		error(Enomem); 
1994/0908    
 
	nbytes = 8; 
1995/0405    
	if((s = scsiexec(t, SCSIread, cmd, sizeof(cmd), d, &nbytes)) == STok){ 
1995/0723    
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), d, &nbytes); 
	if(s == STok) { 
1995/0405    
		*size  = (d[0]<<24)|(d[1]<<16)|(d[2]<<8)|(d[3]<<0); 
		*bsize = (d[4]<<24)|(d[5]<<16)|(d[6]<<8)|(d[7]<<0); 
1994/0908    
	} 
	free(d); 
1995/0723    
	scsifree(d); 
1995/0405    
	return s; 
1993/0915    
} 
1994/0908    
 
1995/0722/sys/src/9/pc/scsi.c:394,4191995/0723/sys/src/9/pc/scsi.c:395,419
1995/0722    
int 
scsidiskinfo(Target *t, char lun, uchar *data) 
{ 
	int s, nbytes, try; 
	uchar cmd[10]; 
1995/0723    
	int s, nbytes; 
	uchar cmd[10], *d; 
1995/0722    
 
	for(try=0; try<3; try++) { 
1995/0723    
	nbytes = 4; 
1995/0722    
 
		nbytes = 4; 
1995/0723    
	memset(cmd, 0, sizeof(cmd)); 
	cmd[0] = 0x43; 
	cmd[1] = lun<<5; 
	cmd[7] = nbytes>>8; 
	cmd[8] = nbytes>>0; 
1995/0722    
 
		memset(cmd, 0, sizeof(cmd)); 
		cmd[0] = 0x43; 
		cmd[1] = lun<<5; 
		cmd[7] = nbytes>>8; 
		cmd[8] = nbytes>>0; 
1995/0723    
	d = scsialloc(nbytes); 
	if(d == 0) 
		error(Enomem); 
1995/0722    
 
		s = scsiexec(t, SCSIread, cmd, sizeof(cmd), data, &nbytes); 
		if(s == STok) 
			break; 
                 
		nbytes = Nscratch; 
		scsireqsense(t, lun, t->scratch, &nbytes, 0); 
	} 
1995/0723    
	memset(d, 0, nbytes); 
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), d, &nbytes); 
	memmove(data, d, 4); 
	scsifree(d); 
1995/0722    
	return s; 
} 
 
1995/0722/sys/src/9/pc/scsi.c:421,4271995/0723/sys/src/9/pc/scsi.c:421,427
1995/0722    
scsitrackinfo(Target *t, char lun, int track, uchar *data) 
{ 
	int s, nbytes; 
	uchar cmd[10]; 
1995/0723    
	uchar cmd[10], *d; 
1995/0722    
 
	nbytes = 12; 
 
1995/0722/sys/src/9/pc/scsi.c:432,4371995/0723/sys/src/9/pc/scsi.c:432,503
1995/0722    
	cmd[7] = nbytes>>8; 
	cmd[8] = nbytes>>0; 
 
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), data, &nbytes); 
1995/0723    
	d = scsialloc(nbytes); 
	if(d == 0) 
		error(Enomem); 
 
	memset(d, 0, nbytes); 
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), d, &nbytes); 
	memmove(data, d, 12); 
	scsifree(d); 
 
1995/0722    
	return s; 
1995/0723    
} 
 
int 
scsibufsize(Target *t, char lun, int size) 
{ 
	int s, nbytes; 
	uchar cmd[6], *d; 
 
 
	nbytes = 12; 
 
	memset(cmd, 0, sizeof(cmd)); 
	cmd[0] = 0x15; 
	cmd[1] = lun<<5; 
	cmd[4] = nbytes; 
 
	d = scsialloc(nbytes); 
	if(d == 0) 
		error(Enomem); 
 
	memset(d, 0, nbytes); 
	d[3] = 8; 
	d[9] = size>>16; 
	d[10] = size>>8; 
	d[11] = size>>0; 
 
	s = scsiexec(t, SCSIwrite, cmd, sizeof(cmd), d, &nbytes); 
	scsifree(d); 
	return s; 
} 
 
int 
scsireadcdda(Target *t, char lun, void *b, long n, long bsize, long bno) 
{ 
	uchar cmd[10]; 
	int s, nbytes; 
 
	memset(cmd, 0, sizeof(cmd)); 
 
	cmd[0] = 0xd8; 
	cmd[1] = (lun<<5); 
	cmd[2] = bno >> 24; 
	cmd[3] = bno >> 16; 
	cmd[4] = bno >> 8; 
	cmd[5] = bno; 
	cmd[6] = n>>24; 
	cmd[7] = n>>16; 
	cmd[8] = n>>8; 
	cmd[9] = n; 
 
	nbytes = n*bsize; 
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), b, &nbytes); 
	if(s < 0) { 
		nbytes = Nscratch; 
		scsireqsense(t, lun, t->scratch, &nbytes, 0); 
		return -1; 
	} 
	return nbytes; 
1995/0722    
} 
1995/0723/sys/src/9/pc/scsi.c:267,2741995/0724/sys/src/9/pc/scsi.c:267,274 (short | long)
1994/0908    
 
1995/0723    
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), d, &nbytes); 
	if(s == STok) { 
1995/0405    
		*size  = (d[0]<<24)|(d[1]<<16)|(d[2]<<8)|(d[3]<<0); 
		*bsize = (d[4]<<24)|(d[5]<<16)|(d[6]<<8)|(d[7]<<0); 
1995/0724    
		*size  = nhgetl(d+0); 
		*bsize = nhgetl(d+4); 
1994/0908    
	} 
1995/0723    
	scsifree(d); 
1995/0405    
	return s; 
1995/0723/sys/src/9/pc/scsi.c:286,2931995/0724/sys/src/9/pc/scsi.c:286,292
1994/0908    
		if(dir == SCSIread) 
			cmd[0] = 0x08; 
		cmd[1] = (lun<<5) | bno >> 16; 
		cmd[2] = bno >> 8; 
		cmd[3] = bno; 
1995/0724    
		hnputs(cmd+2, bno); 
1994/0908    
		cmd[4] = n; 
		cdbsiz = 6; 
	} 
1995/0723/sys/src/9/pc/scsi.c:296,3071995/0724/sys/src/9/pc/scsi.c:295,302
1994/0908    
		if(dir == SCSIread) 
			cmd[0] = 0x28; 
		cmd[1] = (lun<<5); 
		cmd[2] = bno >> 24; 
		cmd[3] = bno >> 16; 
		cmd[4] = bno >> 8; 
		cmd[5] = bno; 
		cmd[7] = n>>8; 
		cmd[8] = n; 
1995/0724    
		hnputl(cmd+2, bno); 
		hnputs(cmd+7, n); 
1994/0908    
		cdbsiz = 10; 
	} 
	nbytes = n*bsize; 
1995/0723/sys/src/9/pc/scsi.c:403,4101995/0724/sys/src/9/pc/scsi.c:398,404
1995/0723    
	memset(cmd, 0, sizeof(cmd)); 
	cmd[0] = 0x43; 
	cmd[1] = lun<<5; 
	cmd[7] = nbytes>>8; 
	cmd[8] = nbytes>>0; 
1995/0724    
	hnputs(cmd+7, nbytes); 
1995/0722    
 
1995/0723    
	d = scsialloc(nbytes); 
	if(d == 0) 
1995/0723/sys/src/9/pc/scsi.c:429,4361995/0724/sys/src/9/pc/scsi.c:423,429
1995/0722    
	cmd[0] = 0xe5; 
	cmd[1] = lun<<5; 
	cmd[5] = track; 
	cmd[7] = nbytes>>8; 
	cmd[8] = nbytes>>0; 
1995/0724    
	hnputs(cmd+7, nbytes); 
1995/0722    
 
1995/0723    
	d = scsialloc(nbytes); 
	if(d == 0) 
1995/0723/sys/src/9/pc/scsi.c:464,4721995/0724/sys/src/9/pc/scsi.c:457,463
1995/0723    
 
	memset(d, 0, nbytes); 
	d[3] = 8; 
	d[9] = size>>16; 
	d[10] = size>>8; 
	d[11] = size>>0; 
1995/0724    
	hnputl(d+8, size); 
1995/0723    
 
	s = scsiexec(t, SCSIwrite, cmd, sizeof(cmd), d, &nbytes); 
	scsifree(d); 
1995/0723/sys/src/9/pc/scsi.c:483,4961995/0724/sys/src/9/pc/scsi.c:474,481
1995/0723    
 
	cmd[0] = 0xd8; 
	cmd[1] = (lun<<5); 
	cmd[2] = bno >> 24; 
	cmd[3] = bno >> 16; 
	cmd[4] = bno >> 8; 
	cmd[5] = bno; 
	cmd[6] = n>>24; 
	cmd[7] = n>>16; 
	cmd[8] = n>>8; 
	cmd[9] = n; 
1995/0724    
	hnputl(cmd+2, bno); 
	hnputl(cmd+6, n); 
1995/0723    
 
	nbytes = n*bsize; 
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), b, &nbytes); 
1995/0724/sys/src/9/pc/scsi.c:206,2121995/0725/sys/src/9/pc/scsi.c:206,213 (short | long)
1995/0403    
					continue; 
				*rt = t; 
				*inq = t->inq; 
				sprint(id, "scsi%d: unit %d", ctlr, unit); 
1995/0725    
				if(id) 
					sprint(id, "scsi%d: unit %d", ctlr, unit); 
1995/0403    
				return devno; 
			} 
1994/0908    
		} 
1995/0725/sys/src/9/pc/scsi.c:466,4721995/0726/sys/src/9/pc/scsi.c:466,472 (short | long)
1995/0723    
} 
 
int 
scsireadcdda(Target *t, char lun, void *b, long n, long bsize, long bno) 
1995/0726    
scsireadcdda(Target *t, char lun, int dir, void *b, long n, long bsize, long bno) 
1995/0723    
{ 
	uchar cmd[10]; 
	int s, nbytes; 
1995/0726/sys/src/9/pc/scsi.c:371,3791995/0808/sys/src/9/pc/scsi.c:371,380 (short | long)
1995/0405    
		} 
1994/0908    
 
		/* 
		 * Unit is becoming ready 
1995/0808    
		 * Unit is becoming ready, rather than not ready 
1994/0908    
		 */ 
		if(sense[12] != 0x04 || sense[13] != 0x01) 
1995/0808    
		if((sense[2] & 0x0F) != 0x02 && 
		   (sense[12] != 0x04 || sense[13] != 0x01)) 
1994/0908    
			break; 
 
		delay(5000); 
1995/0726/sys/src/9/pc/scsi.c:389,4041995/0808/sys/src/9/pc/scsi.c:390,406
1994/0908    
} 
 
1995/0722    
int 
scsidiskinfo(Target *t, char lun, uchar *data) 
1995/0808    
scsidiskinfo(Target *t, char lun, int track, uchar *data) 
1995/0722    
{ 
1995/0723    
	int s, nbytes; 
	uchar cmd[10], *d; 
1995/0722    
 
1995/0723    
	nbytes = 4; 
1995/0808    
	nbytes = 12; 
1995/0722    
 
1995/0723    
	memset(cmd, 0, sizeof(cmd)); 
	cmd[0] = 0x43; 
	cmd[1] = lun<<5; 
1995/0808    
	cmd[6] = track; 
1995/0724    
	hnputs(cmd+7, nbytes); 
1995/0722    
 
1995/0723    
	d = scsialloc(nbytes); 
1995/0726/sys/src/9/pc/scsi.c:407,4131995/0808/sys/src/9/pc/scsi.c:409,415
1995/0722    
 
1995/0723    
	memset(d, 0, nbytes); 
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), d, &nbytes); 
	memmove(data, d, 4); 
1995/0808    
	memmove(data, d, 12); 
1995/0723    
	scsifree(d); 
1995/0722    
	return s; 
} 
1995/0726/sys/src/9/pc/scsi.c:466,4721995/0808/sys/src/9/pc/scsi.c:468,474
1995/0723    
} 
 
int 
1995/0726    
scsireadcdda(Target *t, char lun, int dir, void *b, long n, long bsize, long bno) 
1995/0808    
scsireadcdda(Target *t, char lun, int, void *b, long n, long bsize, long bno) 
1995/0723    
{ 
	uchar cmd[10]; 
	int s, nbytes; 
1995/0808/sys/src/9/pc/scsi.c:339,3451996/0210/sys/src/9/pc/scsi.c:339,345 (short | long)
1994/0908    
 
1995/0405    
	sense = malloc(*nbytes); 
1994/0908    
 
	for(try = 0; try < 5; try++) { 
1996/0210    
	for(try = 0; try < 20; try++) { 
1994/0908    
		memset(cmd, 0, sizeof(cmd)); 
		cmd[0] = CMDreqsense; 
		cmd[1] = lun<<5; 
1995/0808/sys/src/9/pc/scsi.c:354,3851996/0210/sys/src/9/pc/scsi.c:354,394
1995/0405    
		*nbytes = sense[0x07]+8; 
		memmove(data, sense, *nbytes); 
1994/0908    
 
		/* 
		 * Unit attention. We can handle that. 
		 */ 
1995/0405    
		if((sense[2] & 0x0F) == 0x00 || (sense[2] & 0x0F) == 0x06){ 
			free(sense); 
1994/0908    
			return STok; 
1995/0405    
		} 
1996/0210    
		switch(sense[2] & 0x0F){ 
1994/0908    
 
		/* 
		 * Recovered error. Why bother telling me. 
		 */ 
1995/0405    
		if((sense[2] & 0x0F) == 0x01){ 
1996/0210    
		case 6:						/* unit attention */ 
			if(sense[12] != 0x29)			/* power on, reset */ 
				goto buggery; 
			/*FALLTHROUGH*/ 
		case 0:						/* no sense */ 
		case 1:						/* recovered error */ 
1995/0405    
			free(sense); 
1994/0908    
			return STok; 
1995/0405    
		} 
1994/0908    
 
		/* 
1995/0808    
		 * Unit is becoming ready, rather than not ready 
1994/0908    
		 */ 
1995/0808    
		if((sense[2] & 0x0F) != 0x02 && 
		   (sense[12] != 0x04 || sense[13] != 0x01)) 
1994/0908    
			break; 
1996/0210    
		case 2:						/* not ready */ 
			if(sense[12] == 0x3A)			/* medium not present */ 
				goto buggery; 
			/*FALLTHROUGH*/ 
1994/0908    
 
		delay(5000); 
1996/0210    
		default: 
			/* 
			 * If unit is becoming ready, rather than not ready, 
			 * then wait a little then poke it again; should this 
			 * be here or in the caller? 
			 */ 
			if((sense[12] == 0x04 && sense[13] == 0x01)){ 
				while(waserror()) 
					; 
				tsleep(&t->rendez, return0, 0, 500); 
				poperror(); 
				scsitest(t, lun); 
				break; 
			} 
			goto buggery; 
		} 
1994/0908    
	} 
 
1996/0210    
buggery: 
1995/0405    
	if(quiet == 0){ 
		s = key[sense[2]&0x0F]; 
		print("scsi%d: unit %d reqsense: '%s' code #%2.2ux #%2.2ux\n", 
1996/0210/sys/src/9/pc/scsi.c:78,841996/0607/sys/src/9/pc/scsi.c:78,84 (short | long)
1995/0328    
			if((ctlr->io = (*lp->reset)(ctlrno, ctlr)) == 0) 
1994/0908    
				break; 
 
1995/0513    
			print("scsi%d: %s: port 0x%luX irq %d", 
1996/0607    
			print("scsi#%d: %s: port 0x%luX irq %d", 
1994/0908    
				ctlrno, ctlr->type, ctlr->port, 
				ctlr->irq, ctlr->mem, ctlr->size); 
1995/0328    
			if(ctlr->mem) 
1996/0210/sys/src/9/pc/scsi.c:106,1121996/0607/sys/src/9/pc/scsi.c:106,134
1994/0908    
int 
1995/0324    
scsiexec(Target *t, int rw, uchar *cmd, int cbytes, void *data, int *dbytes) 
1993/0915    
{ 
1995/0324    
	return (*scsi[t->ctlrno]->io)(t, rw, cmd, cbytes, data, dbytes); 
1996/0607    
	int s; 
 
	/* 
	 * Call the device-specific I/O routine. 
	 * There should be no calls to 'error()' below this 
	 * which percolate back up. 
	 */ 
	switch(s = (*scsi[t->ctlrno]->io)(t, rw, cmd, cbytes, data, dbytes)){ 
 
	default: 
		/* 
		 * It's more complicated than this. There are conditions which 
		 * are 'ok' but for which the returned status code is not 'STok'. 
		 * Also, not all conditions require a reqsense, there may be a 
		 * need to do a reqsense here when necessary and making it 
		 * available to the caller somehow. 
		 * 
		 * Later. 
		 */ 
		break; 
	} 
 
	return s; 
1994/0908    
} 
1993/0915    
 
1994/0908    
Target* 
1996/0210/sys/src/9/pc/scsi.c:143,1491996/0607/sys/src/9/pc/scsi.c:165,171
1995/0405    
		nbytes = Nscratch; 
		s = scsireqsense(t, 0, t->scratch, &nbytes, 0); 
		if(s != STok){ 
1995/0324    
			print("scsi%d: unit %d unavailable, status %d\n", t->ctlrno, i, s); 
1996/0607    
			print("scsi#%d: unit %d unavailable, status %d\n", t->ctlrno, i, s); 
1994/0908    
			continue; 
		} 
 
1996/0210/sys/src/9/pc/scsi.c:154,1641996/0607/sys/src/9/pc/scsi.c:176,186
1995/0324    
		memset(t->inq, 0, Ninq); 
1994/0908    
		nbytes = Ninq; 
1995/0329    
		s = scsiinquiry(t, 0, t->inq, &nbytes); 
1994/0908    
		if(s < 0) { 
1995/0324    
			print("scsi%d: unit %d inquire failed, status %d\n", t->ctlrno, i, s); 
1996/0607    
		if(s != STok) { 
			print("scsi#%d: unit %d inquire failed, status %d\n", t->ctlrno, i, s); 
1994/0908    
			continue; 
		} 
1995/0405    
		print("scsi%d: unit %d: %s\n", t->ctlrno, i, t->inq+8); 
1996/0607    
		print("scsi#%d: unit %d: %s\n", t->ctlrno, i, t->inq+8); 
1995/0324    
		t->ok = 1; 
1994/0908    
	} 
1993/0915    
} 
1996/0210/sys/src/9/pc/scsi.c:264,2701996/0607/sys/src/9/pc/scsi.c:286,292
1995/0723    
	nbytes = 8; 
	d = scsialloc(nbytes); 
1994/0908    
	if(d == 0) 
1995/0723    
		error(Enomem); 
1996/0607    
		return -1; 
1994/0908    
 
1995/0723    
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), d, &nbytes); 
	if(s == STok) { 
1996/0210/sys/src/9/pc/scsi.c:302,3111996/0607/sys/src/9/pc/scsi.c:324,333
1994/0908    
	} 
	nbytes = n*bsize; 
	s = scsiexec(t, dir, cmd, cdbsiz, b, &nbytes); 
	if(s < 0) { 
1996/0607    
	if(s != STok) { 
1995/0405    
		nbytes = Nscratch; 
		scsireqsense(t, lun, t->scratch, &nbytes, 0); 
1994/0908    
		return -1; 
1996/0607    
		return scsierrstr(s); 
1994/0908    
	} 
	return nbytes; 
} 
1996/0210/sys/src/9/pc/scsi.c:391,3971996/0607/sys/src/9/pc/scsi.c:413,419
1996/0210    
buggery: 
1995/0405    
	if(quiet == 0){ 
		s = key[sense[2]&0x0F]; 
		print("scsi%d: unit %d reqsense: '%s' code #%2.2ux #%2.2ux\n", 
1996/0607    
		print("scsi#%d: unit %d reqsense: '%s' code #%2.2ux #%2.2ux\n", 
1995/0405    
			t->ctlrno, t->target, s, sense[12], sense[13]); 
	} 
	free(sense); 
1996/0210/sys/src/9/pc/scsi.c:414,4201996/0607/sys/src/9/pc/scsi.c:436,442
1995/0722    
 
1995/0723    
	d = scsialloc(nbytes); 
	if(d == 0) 
		error(Enomem); 
1996/0607    
		return scsierrstr(STnomem); 
1995/0722    
 
1995/0723    
	memset(d, 0, nbytes); 
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), d, &nbytes); 
1996/0210/sys/src/9/pc/scsi.c:439,4451996/0607/sys/src/9/pc/scsi.c:461,467
1995/0722    
 
1995/0723    
	d = scsialloc(nbytes); 
	if(d == 0) 
		error(Enomem); 
1996/0607    
		return scsierrstr(STnomem); 
1995/0723    
 
	memset(d, 0, nbytes); 
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), d, &nbytes); 
1996/0210/sys/src/9/pc/scsi.c:465,4711996/0607/sys/src/9/pc/scsi.c:487,493
1995/0723    
 
	d = scsialloc(nbytes); 
	if(d == 0) 
		error(Enomem); 
1996/0607    
		return scsierrstr(STnomem); 
1995/0723    
 
	memset(d, 0, nbytes); 
	d[3] = 8; 
1996/0210/sys/src/9/pc/scsi.c:491,5001996/0607/sys/src/9/pc/scsi.c:513,577
1995/0723    
 
	nbytes = n*bsize; 
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), b, &nbytes); 
	if(s < 0) { 
1996/0607    
	if(s != STok) { 
1995/0723    
		nbytes = Nscratch; 
		scsireqsense(t, lun, t->scratch, &nbytes, 0); 
		return -1; 
1996/0607    
		return scsierrstr(s); 
1995/0723    
	} 
	return nbytes; 
1996/0607    
} 
 
int 
scsierrstr(int errno) 
{ 
	char *p; 
 
	switch(errno){ 
	case STnomem: 
		p = Enomem; 
		break; 
	case STtimeout: 
		p = "bus timeout"; 
		break; 
	case STownid: 
		p = "playing with myself"; 
		break; 
	case STharderr: 
		p = Eio; 
		break; 
	case STok: 
		p = Enoerror; 
		break; 
	case STcheck: 
		p = "check condition"; 
		break; 
	case STcondmet: 
		p = "condition met/good"; 
		break; 
	case STbusy: 
		p = "busy"; 
		break; 
	case STintok: 
		p = "intermediate/good"; 
		break; 
	case STintcondmet: 
		p = "intermediate/condition met/good"; 
		break; 
	case STresconf: 
		p = "reservation conflict"; 
		break; 
	case STterminated: 
		p = "command terminated"; 
		break; 
	case STqfull: 
		p = "queue full"; 
		break; 
 
	default: 
		p = "unknown SCSI error"; 
		break; 
	} 
	strncpy(up->error, p, NAMELEN); 
 
	return -1; 
1995/0722    
} 
1996/0607/sys/src/9/pc/scsi.c:286,2921996/0620/sys/src/9/pc/scsi.c:286,292 (short | long)
1995/0723    
	nbytes = 8; 
	d = scsialloc(nbytes); 
1994/0908    
	if(d == 0) 
1996/0607    
		return -1; 
1996/0620    
		return scsierrstr(STnomem); 
1994/0908    
 
1995/0723    
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), d, &nbytes); 
	if(s == STok) { 
1996/0620/sys/src/9/pc/scsi.c:290,2971996/0622/sys/src/9/pc/scsi.c:290,297 (short | long)
1994/0908    
 
1995/0723    
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), d, &nbytes); 
	if(s == STok) { 
1995/0724    
		*size  = nhgetl(d+0); 
		*bsize = nhgetl(d+4); 
1996/0622    
		*size = (d[0]<<24)|(d[1]<<16)|(d[2]<<8)|d[3]; 
		*bsize = (d[4]<<24)|(d[5]<<16)|(d[6]<<8)|d[7]; 
1994/0908    
	} 
1995/0723    
	scsifree(d); 
1995/0405    
	return s; 
1996/0620/sys/src/9/pc/scsi.c:303,3161996/0622/sys/src/9/pc/scsi.c:303,317
1994/0908    
	uchar cmd[10]; 
	int s, cdbsiz, nbytes; 
 
	memset(cmd, 0, sizeof cmd); 
	if(bno <= 0x1fffff && n < 256) { 
		cmd[0] = 0x0A; 
		if(dir == SCSIread) 
			cmd[0] = 0x08; 
		cmd[1] = (lun<<5) | bno >> 16; 
1995/0724    
		hnputs(cmd+2, bno); 
1996/0622    
		cmd[2] = bno>>8; 
		cmd[3] = bno; 
1994/0908    
		cmd[4] = n; 
1996/0622    
		cmd[5] = 0; 
1994/0908    
		cdbsiz = 6; 
	} 
	else { 
1996/0620/sys/src/9/pc/scsi.c:318,3251996/0622/sys/src/9/pc/scsi.c:319,331
1994/0908    
		if(dir == SCSIread) 
			cmd[0] = 0x28; 
		cmd[1] = (lun<<5); 
1995/0724    
		hnputl(cmd+2, bno); 
		hnputs(cmd+7, n); 
1996/0622    
		cmd[2] = bno>>24; 
		cmd[3] = bno>>16; 
		cmd[4] = bno>>8; 
		cmd[5] = bno; 
		cmd[7] = n>>8; 
		cmd[8] = n; 
		cmd[9] = 0; 
1994/0908    
		cdbsiz = 10; 
	} 
	nbytes = n*bsize; 
1996/0620/sys/src/9/pc/scsi.c:432,4381996/0622/sys/src/9/pc/scsi.c:438,445
1995/0723    
	cmd[0] = 0x43; 
	cmd[1] = lun<<5; 
1995/0808    
	cmd[6] = track; 
1995/0724    
	hnputs(cmd+7, nbytes); 
1996/0622    
	cmd[7] = nbytes>>8; 
	cmd[8] = nbytes; 
1995/0722    
 
1995/0723    
	d = scsialloc(nbytes); 
	if(d == 0) 
1996/0620/sys/src/9/pc/scsi.c:457,4631996/0622/sys/src/9/pc/scsi.c:464,471
1995/0722    
	cmd[0] = 0xe5; 
	cmd[1] = lun<<5; 
	cmd[5] = track; 
1995/0724    
	hnputs(cmd+7, nbytes); 
1996/0622    
	cmd[7] = nbytes>>8; 
	cmd[8] = nbytes; 
1995/0722    
 
1995/0723    
	d = scsialloc(nbytes); 
	if(d == 0) 
1996/0620/sys/src/9/pc/scsi.c:491,4971996/0622/sys/src/9/pc/scsi.c:499,508
1995/0723    
 
	memset(d, 0, nbytes); 
	d[3] = 8; 
1995/0724    
	hnputl(d+8, size); 
1996/0622    
	d[8] = size>>24; 
	d[9] = size>>16; 
	d[10] = size>>8; 
	d[11] = size; 
1995/0723    
 
	s = scsiexec(t, SCSIwrite, cmd, sizeof(cmd), d, &nbytes); 
	scsifree(d); 
1996/0620/sys/src/9/pc/scsi.c:508,5151996/0622/sys/src/9/pc/scsi.c:519,530
1995/0723    
 
	cmd[0] = 0xd8; 
	cmd[1] = (lun<<5); 
1995/0724    
	hnputl(cmd+2, bno); 
	hnputl(cmd+6, n); 
1996/0622    
	cmd[2] = bno>>24; 
	cmd[3] = bno>>16; 
	cmd[4] = bno>>8; 
	cmd[5] = bno; 
	cmd[6] = n>>8; 
	cmd[7] = n; 
1995/0723    
 
	nbytes = n*bsize; 
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), b, &nbytes); 
1996/0622/sys/src/9/pc/scsi.c:362,3791996/1018/sys/src/9/pc/scsi.c:362,381 (short | long)
1995/0405    
scsireqsense(Target *t, char lun, void *data, int *nbytes, int quiet) 
1994/0908    
{ 
	char *s; 
1995/0405    
	int status, try; 
1996/1018    
	int n, status, try; 
1994/0908    
	uchar cmd[6], *sense; 
 
1995/0405    
	sense = malloc(*nbytes); 
1996/1018    
	n = *nbytes; 
	sense = malloc(n); 
1994/0908    
 
1996/0210    
	for(try = 0; try < 20; try++) { 
1994/0908    
		memset(cmd, 0, sizeof(cmd)); 
		cmd[0] = CMDreqsense; 
		cmd[1] = lun<<5; 
1995/0405    
		cmd[4] = *nbytes; 
		memset(sense, 0, *nbytes); 
1996/1018    
		cmd[4] = n; 
		memset(sense, 0, n); 
1994/0908    
 
1996/1018    
		*nbytes = n; 
1995/0405    
		status = scsiexec(t, SCSIread, cmd, sizeof(cmd), sense, nbytes); 
		if(status != STok){ 
			free(sense); 
1996/1018/sys/src/9/pc/scsi.c:103,1081996/1022/sys/src/9/pc/scsi.c:103,111 (short | long)
1994/0908    
		free(ctlr); 
1993/0915    
} 
 
1996/1022    
static uchar lastcmd[16]; 
static int lastcmdsz; 
 
1994/0908    
int 
1995/0324    
scsiexec(Target *t, int rw, uchar *cmd, int cbytes, void *data, int *dbytes) 
1993/0915    
{ 
1996/1018/sys/src/9/pc/scsi.c:115,1201996/1022/sys/src/9/pc/scsi.c:118,128
1996/0607    
	 */ 
	switch(s = (*scsi[t->ctlrno]->io)(t, rw, cmd, cbytes, data, dbytes)){ 
 
1996/1022    
	case STcheck: 
		memmove(lastcmd, cmd, cbytes); 
		lastcmdsz = cbytes; 
		/*FALLTHROUGH*/ 
 
1996/0607    
	default: 
		/* 
		 * It's more complicated than this. There are conditions which 
1996/1018/sys/src/9/pc/scsi.c:323,3281996/1022/sys/src/9/pc/scsi.c:331,337
1996/0622    
		cmd[3] = bno>>16; 
		cmd[4] = bno>>8; 
		cmd[5] = bno; 
1996/1022    
		cmd[6] = 0; 
1996/0622    
		cmd[7] = n>>8; 
		cmd[8] = n; 
		cmd[9] = 0; 
1996/1018/sys/src/9/pc/scsi.c:423,4281996/1022/sys/src/9/pc/scsi.c:432,443
1995/0405    
		s = key[sense[2]&0x0F]; 
1996/0607    
		print("scsi#%d: unit %d reqsense: '%s' code #%2.2ux #%2.2ux\n", 
1995/0405    
			t->ctlrno, t->target, s, sense[12], sense[13]); 
1996/1022    
		print("scsi#%d: byte 2: #%2.2uX, bytes 15-17: #%2.2uX #%2.2uX #%2.2uX\n", 
			t->ctlrno, sense[2], sense[15], sense[16], sense[17]); 
		print("lastcmd (%d): ", lastcmdsz); 
		for(n = 0; n < lastcmdsz; n++) 
			print(" #%2.2uX", lastcmd[n]); 
		print("\n"); 
1995/0405    
	} 
	free(sense); 
1994/0908    
	return STcheck; 
1996/1022/sys/src/9/pc/scsi.c:540,5471996/1224/sys/src/9/pc/scsi.c:540,547 (short | long)
1996/0622    
	cmd[3] = bno>>16; 
	cmd[4] = bno>>8; 
	cmd[5] = bno; 
	cmd[6] = n>>8; 
	cmd[7] = n; 
1996/1224    
	cmd[8] = n>>8; 
	cmd[9] = n; 
1995/0723    
 
	nbytes = n*bsize; 
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), b, &nbytes); 
1996/1224/sys/src/9/pc/scsi.c:75,811997/0327/sys/src/9/pc/scsi.c:75,81 (short | long)
1995/0328    
		for(lp = link; lp; lp = lp->link){ 
			if(strcmp(lp->type, ctlr->type)) 
1994/0908    
				continue; 
1995/0328    
			if((ctlr->io = (*lp->reset)(ctlrno, ctlr)) == 0) 
1997/0327    
			if((ctlr->io = lp->reset(ctlrno, ctlr)) == 0) 
1994/0908    
				break; 
 
1996/0607    
			print("scsi#%d: %s: port 0x%luX irq %d", 
1996/1224/sys/src/9/pc/scsi.c:116,1221997/0327/sys/src/9/pc/scsi.c:116,122
1996/0607    
	 * There should be no calls to 'error()' below this 
	 * which percolate back up. 
	 */ 
	switch(s = (*scsi[t->ctlrno]->io)(t, rw, cmd, cbytes, data, dbytes)){ 
1997/0327    
	switch(s = scsi[t->ctlrno]->io(t, rw, cmd, cbytes, data, dbytes)){ 
1996/0607    
 
1996/1022    
	case STcheck: 
		memmove(lastcmd, cmd, cbytes); 
1996/1224/sys/src/9/pc/scsi.c:245,2511997/0327/sys/src/9/pc/scsi.c:245,250
1994/0908    
	return -1; 
1995/0404    
} 
 
                 
int 
scsitest(Target *t, char lun) 
{ 
1996/1224/sys/src/9/pc/scsi.c:540,5471997/0327/sys/src/9/pc/scsi.c:539,546
1996/0622    
	cmd[3] = bno>>16; 
	cmd[4] = bno>>8; 
	cmd[5] = bno; 
1996/1224    
	cmd[8] = n>>8; 
	cmd[9] = n; 
1997/0327    
	cmd[6] = n>>8; 
	cmd[7] = n; 
1995/0723    
 
	nbytes = n*bsize; 
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), b, &nbytes); 
1997/0327/sys/src/9/pc/scsi.c:539,5461997/0628/sys/src/9/pc/scsi.c:539,548 (short | long)
1996/0622    
	cmd[3] = bno>>16; 
	cmd[4] = bno>>8; 
	cmd[5] = bno; 
1997/0327    
	cmd[6] = n>>8; 
	cmd[7] = n; 
1997/0628    
	cmd[6] = n>>24; 
	cmd[7] = n>>16; 
	cmd[8] = n>>8; 
	cmd[9] = n; 
1995/0723    
 
	nbytes = n*bsize; 
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), b, &nbytes); 
1997/0628/sys/src/9/pc/scsi.c:320,3271997/0629/sys/src/9/pc/scsi.c:320,326 (short | long)
1994/0908    
		cmd[4] = n; 
1996/0622    
		cmd[5] = 0; 
1994/0908    
		cdbsiz = 6; 
	} 
	else { 
1997/0629    
	} else { 
1994/0908    
		cmd[0] = 0x2A; 
		if(dir == SCSIread) 
			cmd[0] = 0x28; 
Too many diffs (26 > 25). Stopping.


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)