Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/pc/scsi.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname pc/scsi.c 1993/0915
## diff -e /dev/null /n/fornaxdump/1993/0915/sys/src/brazil/pc/scsi.c
0a
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "io.h"
#include "../port/error.h"

/*
 * Known to devscsi.c.
int scsidebugs[8];
int scsiownid = CtlrID;
 */

void
initscsi(void)
{
}

/*
 * 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)
{
	bufdatasize = datasize;
}

Scsibuf *
scsibuf(void)
{
	Scsibuf *b;

	b = smalloc(sizeof(*b));
	b->virt = smalloc(bufdatasize);
	b->phys = (void *)(PADDR(b->virt));
	return b;
}

void
scsifree(Scsibuf *b)
{
	free(b->virt);
	free(b);
}

/*
 * Hack for devvid
 */
Scsibuf *
scsialloc(ulong n)
{
	Scsibuf *b;

	b = smalloc(sizeof(*b));
	b->virt = smalloc(n);
	b->phys = (void *)(PADDR(b->virt));
	return b;
}

extern int (*aha1542reset(void))(Scsi*, int);
extern int (*ultra14freset(void))(Scsi*, int);

static int (*exec)(Scsi*, int);

int
scsiexec(Scsi *p, int rflag)
{
	if(exec == 0)
		error(Enonexist);
	return (*exec)(p, rflag);
}

void
resetscsi(void)
{
	if(exec = aha1542reset())
		return;
	exec = ultra14freset();
}
.
## diffname pc/scsi.c 1994/0908
## diff -e /n/fornaxdump/1993/0915/sys/src/brazil/pc/scsi.c /n/fornaxdump/1994/0908/sys/src/brazil/pc/scsi.c
84a

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;
}

.
81,83c
	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;
.
78,79c
int
scsicap(Target *t, char lun, ulong *size, ulong *bsize)
.
73,75c
	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);
.
71c
scsistart(Target *t, char lun, int s)
.
69a
	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;
}

.
68c
	inventory();
.
65,66c
int
scsiinv(int devno, int type, Target **rt, uchar **inq, char *id)
{
	Target *t;
	int ctlr, unit;
.
59,62c
	lock(&ilock);
	if(inited) {
		unlock(&ilock);
		return;
	}
	inited = 1;
	unlock(&ilock);

	for(i = 0; i < MaxScsi; i++){
		if(scsi[i])
			scsiprobe(scsi[i]);
	}
.
57c
	int i;
	static Lock ilock;
	static int inited;
.
51,55c
static void
inventory(void)
.
47,48c
	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;
	}
.
44,45c
static void
scsiprobe(Ctlr *ctlr)
.
38,41c
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;
.
36c
	return (*scsi[tp->ctlrno]->io)(tp, rw, cmd, cbytes, data, dbytes);
}
.
33,34c
int
scsiexec(Target *tp, int rw, uchar *cmd, int cbytes, void *data, int *dbytes)
.
30c
	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);
.
28c
scsireset(void)
.
20,26d
17a
	static int ncard;

	if(ncard == MaxScsi)
		panic("too many scsi cards\n");
	cards[ncard].type = t;
	cards[ncard].reset = r;
	ncard++;
.
16c
addscsicard(char *t, Scsiio (*r)(int, ISAConf*))
.
14a
	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];

.
9,13c
enum {
	Ninq		= 255,
	Nscratch	= 255,
.
7a
#include "../port/netif.h"
.
6a
#include "ureg.h"
.
## diffname pc/scsi.c 1995/0324
## diff -e /n/fornaxdump/1994/0908/sys/src/brazil/pc/scsi.c /n/fornaxdump/1995/0324/sys/src/brazil/pc/scsi.c
340c
		t->ctlrno, t->target, s, sense[12], sense[13]);
.
310c
		sr = scsiexec(t, SCSIread, cmd, sizeof(cmd), sense, &nbytes);
.
300c
	sense = t->scratch;
.
294c
scsireqsense(Target *t, char lun, int quiet)
.
144,145c
		print("scsi%d: unit %d %s\n", t->ctlrno, i, t->inq+8);
		t->ok = 1;
.
141c
			print("scsi%d: unit %d inquire failed, status %d\n", t->ctlrno, i, s);
.
139c
		s = scsiexec(t, SCSIread, cmd, sizeof(cmd), t->inq, &nbytes);
.
135c
		memset(t->inq, 0, Ninq);
.
126,127c
		if((s = scsireqsense(t, 0, 0)) != STok){
			print("scsi%d: unit %d unavailable, status %d\n", t->ctlrno, i, s);
.
118c
		s = scsiexec(t, SCSIread, cmd, sizeof(cmd), 0, 0);
.
112c
		t = &ctlr->target[i];
.
107c
	Target *t;
.
86c
	return (*scsi[t->ctlrno]->io)(t, rw, cmd, cbytes, data, dbytes);
.
84c
scsiexec(Target *t, int rw, uchar *cmd, int cbytes, void *data, int *dbytes)
.
## diffname pc/scsi.c 1995/0328
## diff -e /n/fornaxdump/1995/0324/sys/src/brazil/pc/scsi.c /n/fornaxdump/1995/0328/sys/src/brazil/pc/scsi.c
65a
			if(ctlr->mem)
				print(" addr %lux size %d\n", ctlr->mem, ctlr->size);
			print("\n");
.
63c
			print("scsi%d: %s: port %lux irq %d",
.
60c
			if((ctlr->io = (*lp->reset)(ctlrno, ctlr)) == 0)
.
57,58c
		for(lp = link; lp; lp = lp->link){
			if(strcmp(lp->type, ctlr->type))
.
49c
	int ctlrno, t;
	Link *lp;
.
38,42c
	if((lp = xalloc(sizeof(Link))) == 0)
		return;
	lp->type = t;
	lp->reset = r;

	lp->link = link;
	link = lp;
	linkcount++;
.
36c
	Link *lp;
.
34c
addscsilink(char *t, Scsiio (*r)(int, ISAConf*))
.
32a
	Link*	link;
} Link;

static Link *link;
static int linkcount;

.
31d
28c
typedef struct Link Link;
typedef struct Link {
.
## diffname pc/scsi.c 1995/0329
## diff -e /n/fornaxdump/1995/0328/sys/src/brazil/pc/scsi.c /n/fornaxdump/1995/0329/sys/src/brazil/pc/scsi.c
218a
}

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);
.
215c
	cmd[0] = CMDstart;
.
199c
		if(t->ok && (t->inq[0]&0x1F) == type){
.
152c
		s = scsiinquiry(t, 0, t->inq, &nbytes);
.
149,150d
145c
		 * Inquire to find out what the device is.
.
16a
	CMDstart	= 0x1B,
	CMDread10	= 0x28,
	CMDwrite10	= 0x2A,
.
15a
	CMDread6	= 0x08,
	CMDwrite6	= 0x0A,
.
14a
	CMDtest		= 0x00,
.
## diffname pc/scsi.c 1995/0403
## diff -e /n/fornaxdump/1995/0329/sys/src/brazil/pc/scsi.c /n/fornaxdump/1995/0403/sys/src/brazil/pc/scsi.c
203,207c
		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;
			}
.
191c
	int ctlr, *i, unit;
.
188c
scsiinv(int devno, int *type, Target **rt, uchar **inq, char *id)
.
161c
		print("scsi%d: unit %d:%2.2ux: %s\n", t->ctlrno, i, t->inq[0], t->inq+8);
.
## diffname pc/scsi.c 1995/0404
## diff -e /n/fornaxdump/1995/0403/sys/src/brazil/pc/scsi.c /n/fornaxdump/1995/0404/sys/src/brazil/pc/scsi.c
215a
}


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);
.
133,138c
		if(scsitest(t, 0) < 0)
.
127d
## diffname pc/scsi.c 1995/0405
## diff -e /n/fornaxdump/1995/0404/sys/src/brazil/pc/scsi.c /n/fornaxdump/1995/0405/sys/src/brazil/pc/scsi.c
375,380c
	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);
.
364a
		}
.
363c
		if((sense[2] & 0x0F) == 0x01){
			free(sense);
.
358a
		}
.
357c
		if((sense[2] & 0x0F) == 0x00 || (sense[2] & 0x0F) == 0x06){
			free(sense);
.
349,352c
		status = scsiexec(t, SCSIread, cmd, sizeof(cmd), sense, nbytes);
		if(status != STok){
			free(sense);
			return status;
		}
		*nbytes = sense[0x07]+8;
		memmove(data, sense, *nbytes);
.
346,347c
		cmd[4] = *nbytes;
		memset(sense, 0, *nbytes);
.
340c
	sense = malloc(*nbytes);
.
337c
	int status, try;
.
334c
scsireqsense(Target *t, char lun, void *data, int *nbytes, int quiet)
.
307c
		nbytes = Nscratch;
		scsireqsense(t, lun, t->scratch, &nbytes, 0);
.
271c
	return s;
.
268,269d
263,266c
	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);
.
155c
		print("scsi%d: unit %d: %s\n", t->ctlrno, i, t->inq+8);
.
139c
		nbytes = Nscratch;
		s = scsireqsense(t, 0, t->scratch, &nbytes, 0);
		if(s != STok){
.
## diffname pc/scsi.c 1995/0513
## diff -e /n/fornaxdump/1995/0405/sys/src/brazil/pc/scsi.c /n/fornaxdump/1995/0513/sys/src/brazil/pc/scsi.c
206d
83c
				print(" addr 0x%luX", ctlr->mem & ~KZERO);
			if(ctlr->size)
				print(" size 0x%luX", ctlr->size);
.
79c
			print("scsi%d: %s: port 0x%luX irq %d",
.
## diffname pc/scsi.c 1995/0712
## diff -e /n/fornaxdump/1995/0513/sys/src/brazil/pc/scsi.c /n/fornaxdump/1995/0712/sys/src/brazil/pc/scsi.c
9d
## diffname pc/scsi.c 1995/0722
## diff -e /n/fornaxdump/1995/0712/sys/src/brazil/pc/scsi.c /n/fornaxdump/1995/0722/sys/src/brazil/pc/scsi.c
390a
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;
}
.
234c
	cmd[4] = s? 1: 0;
.
34c
typedef struct Link
{
.
24c
typedef struct
{
.
10c
enum
{
.
## diffname pc/scsi.c 1995/0723
## diff -e /n/fornaxdump/1995/0722/sys/src/brazil/pc/scsi.c /n/fornaxdump/1995/0723/sys/src/brazil/pc/scsi.c
436a
}

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;
.
435c
	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);

.
424c
	uchar cmd[10], *d;
.
410,416c
	memset(d, 0, nbytes);
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), d, &nbytes);
	memmove(data, d, 4);
	scsifree(d);
.
404,408c
	d = scsialloc(nbytes);
	if(d == 0)
		error(Enomem);
.
402c
	memset(cmd, 0, sizeof(cmd));
	cmd[0] = 0x43;
	cmd[1] = lun<<5;
	cmd[7] = nbytes>>8;
	cmd[8] = nbytes>>0;
.
400c
	nbytes = 4;
.
397,398c
	int s, nbytes;
	uchar cmd[10], *d;
.
272c
	scsifree(d);
.
267,268c
	s = scsiexec(t, SCSIread, cmd, sizeof(cmd), d, &nbytes);
	if(s == STok) {
.
265c
		error(Enomem);
.
263c
	nbytes = 8;
	d = scsialloc(nbytes);
.
33c
static	Ctlr*	scsi[MaxScsi];
.
## diffname pc/scsi.c 1995/0724
## diff -e /n/fornaxdump/1995/0723/sys/src/brazil/pc/scsi.c /n/fornaxdump/1995/0724/sys/src/brazil/pc/scsi.c
486,493c
	hnputl(cmd+2, bno);
	hnputl(cmd+6, n);
.
467,469c
	hnputl(d+8, size);
.
432,433c
	hnputs(cmd+7, nbytes);
.
406,407c
	hnputs(cmd+7, nbytes);
.
299,304c
		hnputl(cmd+2, bno);
		hnputs(cmd+7, n);
.
289,290c
		hnputs(cmd+2, bno);
.
270,271c
		*size  = nhgetl(d+0);
		*bsize = nhgetl(d+4);
.
## diffname pc/scsi.c 1995/0725
## diff -e /n/fornaxdump/1995/0724/sys/src/brazil/pc/scsi.c /n/fornaxdump/1995/0725/sys/src/brazil/pc/scsi.c
209c
				if(id)
					sprint(id, "scsi%d: unit %d", ctlr, unit);
.
## diffname pc/scsi.c 1995/0726
## diff -e /n/fornaxdump/1995/0725/sys/src/brazil/pc/scsi.c /n/fornaxdump/1995/0726/sys/src/brazil/pc/scsi.c
469c
scsireadcdda(Target *t, char lun, int dir, void *b, long n, long bsize, long bno)
.
## diffname pc/scsi.c 1995/0808
## diff -e /n/fornaxdump/1995/0726/sys/src/brazil/pc/scsi.c /n/fornaxdump/1995/0808/sys/src/brazil/pc/scsi.c
469c
scsireadcdda(Target *t, char lun, int, void *b, long n, long bsize, long bno)
.
410c
	memmove(data, d, 12);
.
401a
	cmd[6] = track;
.
397c
	nbytes = 12;
.
392c
scsidiskinfo(Target *t, char lun, int track, uchar *data)
.
376c
		if((sense[2] & 0x0F) != 0x02 &&
		   (sense[12] != 0x04 || sense[13] != 0x01))
.
374c
		 * Unit is becoming ready, rather than not ready
.
## diffname pc/scsi.c 1996/0210
## diff -e /n/fornaxdump/1995/0808/sys/src/brazil/pc/scsi.c /n/fornaxdump/1996/0210/sys/src/brazil/pc/scsi.c
382a
buggery:
.
380c
		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;
		}
.
373,378c
		case 2:						/* not ready */
			if(sense[12] == 0x3A)			/* medium not present */
				goto buggery;
			/*FALLTHROUGH*/
.
371d
365,368c
		case 6:						/* unit attention */
			if(sense[12] != 0x29)			/* power on, reset */
				goto buggery;
			/*FALLTHROUGH*/
		case 0:						/* no sense */
		case 1:						/* recovered error */
.
357,363c
		switch(sense[2] & 0x0F){
.
342c
	for(try = 0; try < 20; try++) {
.
## diffname pc/scsi.c 1996/0607
## diff -e /n/fornaxdump/1996/0210/sys/src/brazil/pc/scsi.c /n/fornaxdump/1996/0607/sys/src/brazil/pc/scsi.c
499a
}

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;
.
497c
		return scsierrstr(s);
.
494c
	if(s != STok) {
.
468c
		return scsierrstr(STnomem);
.
442c
		return scsierrstr(STnomem);
.
417c
		return scsierrstr(STnomem);
.
394c
		print("scsi#%d: unit %d reqsense: '%s' code #%2.2ux #%2.2ux\n",
.
308c
		return scsierrstr(s);
.
305c
	if(s != STok) {
.
267c
		return -1;
.
161c
		print("scsi#%d: unit %d: %s\n", t->ctlrno, i, t->inq+8);
.
157,158c
		if(s != STok) {
			print("scsi#%d: unit %d inquire failed, status %d\n", t->ctlrno, i, s);
.
146c
			print("scsi#%d: unit %d unavailable, status %d\n", t->ctlrno, i, s);
.
109c
	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;
.
81c
			print("scsi#%d: %s: port 0x%luX irq %d",
.
## diffname pc/scsi.c 1996/0620
## diff -e /n/fornaxdump/1996/0607/sys/src/brazil/pc/scsi.c /n/fornaxdump/1996/0620/sys/src/brazil/pc/scsi.c
289c
		return scsierrstr(STnomem);
.
## diffname pc/scsi.c 1996/0622
## diff -e /n/fornaxdump/1996/0620/sys/src/brazil/pc/scsi.c /n/fornaxdump/1996/0622/sys/src/brazil/pc/scsi.c
511,512c
	cmd[2] = bno>>24;
	cmd[3] = bno>>16;
	cmd[4] = bno>>8;
	cmd[5] = bno;
	cmd[6] = n>>8;
	cmd[7] = n;
.
494c
	d[8] = size>>24;
	d[9] = size>>16;
	d[10] = size>>8;
	d[11] = size;
.
460c
	cmd[7] = nbytes>>8;
	cmd[8] = nbytes;
.
435c
	cmd[7] = nbytes>>8;
	cmd[8] = nbytes;
.
321,322c
		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;
.
313a
		cmd[5] = 0;
.
312c
		cmd[2] = bno>>8;
		cmd[3] = bno;
.
306d
293,294c
		*size = (d[0]<<24)|(d[1]<<16)|(d[2]<<8)|d[3];
		*bsize = (d[4]<<24)|(d[5]<<16)|(d[6]<<8)|d[7];
.
## diffname pc/scsi.c 1996/1018
## diff -e /n/fornaxdump/1996/0622/sys/src/brazil/pc/scsi.c /n/fornaxdump/1996/1018/sys/src/brazil/pc/scsi.c
376a
		*nbytes = n;
.
374,375c
		cmd[4] = n;
		memset(sense, 0, n);
.
368c
	n = *nbytes;
	sense = malloc(n);
.
365c
	int n, status, try;
.
## diffname pc/scsi.c 1996/1022
## diff -e /n/fornaxdump/1996/1018/sys/src/brazil/pc/scsi.c /n/fornaxdump/1996/1022/sys/src/brazil/pc/scsi.c
425a
		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");
.
325a
		cmd[6] = 0;
.
117a
	case STcheck:
		memmove(lastcmd, cmd, cbytes);
		lastcmdsz = cbytes;
		/*FALLTHROUGH*/

.
105a
static uchar lastcmd[16];
static int lastcmdsz;

.
## diffname pc/scsi.c 1996/1224
## diff -e /n/fornaxdump/1996/1022/sys/src/brazil/pc/scsi.c /n/fornaxdump/1996/1224/sys/src/brazil/pc/scsi.c
543,544c
	cmd[8] = n>>8;
	cmd[9] = n;
.
## diffname pc/scsi.c 1997/0327
## diff -e /n/fornaxdump/1996/1224/sys/src/brazil/pc/scsi.c /n/emeliedump/1997/0327/sys/src/brazil/pc/scsi.c
543,544c
	cmd[6] = n>>8;
	cmd[7] = n;
.
248d
119c
	switch(s = scsi[t->ctlrno]->io(t, rw, cmd, cbytes, data, dbytes)){
.
78c
			if((ctlr->io = lp->reset(ctlrno, ctlr)) == 0)
.
## diffname pc/scsi.c 1997/0628
## diff -e /n/emeliedump/1997/0327/sys/src/brazil/pc/scsi.c /n/emeliedump/1997/0628/sys/src/brazil/pc/scsi.c
542,543c
	cmd[6] = n>>24;
	cmd[7] = n>>16;
	cmd[8] = n>>8;
	cmd[9] = n;
.
## diffname pc/scsi.c 1997/0629
## diff -e /n/emeliedump/1997/0628/sys/src/brazil/pc/scsi.c /n/emeliedump/1997/0629/sys/src/brazil/pc/scsi.c
323,324c
	} else {
.
## diffname pc/scsi.c 1997/0808
## diff -e /n/emeliedump/1997/0629/sys/src/brazil/pc/scsi.c /n/emeliedump/1997/0808/sys/src/brazil/pc/scsi.c
323c
	}
	else {
.
## diffname pc/scsi.c 1997/1101
## diff -e /n/emeliedump/1997/0808/sys/src/brazil/pc/scsi.c /n/emeliedump/1997/1101/sys/src/brazil/pc/scsi.c
85c
				print(" addr 0x%luX", PADDR(ctlr->mem));
.
## diffname pc/scsi.c 1998/0201
## diff -e /n/emeliedump/1997/1101/sys/src/brazil/pc/scsi.c /n/emeliedump/1998/0201/sys/src/brazil/pc/scsi.c
531c
	uchar cmd[12];
.
504d
313,338c
	cmd[0] = CMDwrite10;
	if(dir == SCSIread)
		cmd[0] = CMDread10;
	cmd[1] = (lun<<5);
	cmd[2] = bno>>24;
	cmd[3] = bno>>16;
	cmd[4] = bno>>8;
	cmd[5] = bno;
	cmd[6] = 0;
	cmd[7] = n>>8;
	cmd[8] = n;
	cmd[9] = 0;
	cdbsiz = 10;

.
## diffname pc/scsi.c 1998/0811
## diff -e /n/emeliedump/1998/0201/sys/src/brazil/pc/scsi.c /n/emeliedump/1998/0811/sys/src/brazil/pc/scsi.c
191c
		print("scsi#%d: unit %d: %s\n", t->ctlrno, i, (char*)(t->inq+8));
.
83c
				ctlr->irq);
.
## diffname pc/scsi.c 1998/0825
## diff -e /n/emeliedump/1998/0811/sys/src/brazil/pc/scsi.c /n/emeliedump/1998/0825/sys/src/brazil/pc/scsi.c
81c
			print("scsi#%d: %s: port 0x%luX irq %lud",
.
## diffname pc/scsi.c 1998/0910
## diff -e /n/emeliedump/1998/0825/sys/src/brazil/pc/scsi.c /n/emeliedump/1998/0910/sys/src/brazil/pc/scsi.c
78c
			if((ctlr->io = scsidev[i]->reset(ctlrno, ctlr)) == 0)
.
75,76c
		for(i = 0; scsidev[i]; i++){
			if(strcmp(ctlr->type, scsidev[i]->type))
.
66,67c
	int ctlrno, i, t;
.
48,62d
41,46d
35,39c
extern SCSIdev* scsidev[];
.
33c
static Ctlr* scsi[MaxScsi];
.
25,26c
typedef struct {
.
10,11c
enum {
.
## diffname pc/scsi.c 1998/0916
## diff -e /n/emeliedump/1998/0910/sys/src/brazil/pc/scsi.c /n/emeliedump/1998/0916/sys/src/brazil/pc/scsi.c
48c
			if(cistrcmp(ctlr->type, scsidev[i]->type))
.
## diffname pc/scsi.c 1999/0119
## diff -e /n/emeliedump/1998/0916/sys/src/brazil/pc/scsi.c /n/emeliedump/1999/0119/sys/src/brazil/pc/scsi.c
366,367c
		case 2:					/* not ready */
			if(sense[12] == 0x3A)		/* medium not present */
.
361,362c
		case 0:					/* no sense */
		case 1:					/* recovered error */
.
357,358c
		case 6:					/* unit attention */
			if(sense[12] != 0x29)		/* power on, reset */
.
262c
	cmd[0] = CMDcapacity;
.
212c
					sprint(id, "scsi%d: unit %d",
						ctlr, unit);
.
163c
		print("scsi#%d: unit %d: %s\n",
			t->ctlrno, i, (char*)(t->inq+8));
.
160c
			print("scsi#%d: unit %d inquire failed, status %d\n",
				t->ctlrno, i, s);
.
148c
			print("scsi#%d: unit %d unavailable, status %d\n",
				t->ctlrno, i, s);
.
100,104c
		 * 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, might
		 * need to do a reqsense here and make it available to the
		 * caller somehow.
.
19a
	CMDcapacity	= 0x25,
.
## diffname pc/scsi.c 1999/0301
## diff -e /n/emeliedump/1999/0119/sys/src/brazil/pc/scsi.c /n/emeliedump/1999/0301/sys/src/brazil/pc/scsi.c
411,520d
364c
			/*
			 * 0x28 - not ready to ready transition,
			 *	  medium may have changed.
			 * 0x29 - power on, RESET or BUS DEVICE RESET occurred.
			 */
			if(sense[12] != 0x28 && sense[12] != 0x29)
.
16,17d
## diffname pc/scsi.c 1999/0507
## diff -e /n/emeliedump/1999/0301/sys/src/brazil/pc/scsi.c /n/emeliedump/1999/0507/sys/src/brazil/pc/scsi.c
334c
scsireqsense(Target *t, int lun, void *data, int *nbytes, int quiet)
.
284c
scsibio(Target *t, int lun, int dir, void *b, long n, long bsize, long bno)
.
260c
scsicap(Target *t, int lun, ulong *size, ulong *bsize)
.
248c
scsiinquiry(Target *t, int lun, void *data, int *datalen)
.
236c
scsistart(Target *t, int lun, int s)
.
225c
scsitest(Target *t, int lun)
.
## diffname pc/scsi.c 2000/0506 # deleted
## diff -e /n/emeliedump/1999/0507/sys/src/brazil/pc/scsi.c /n/emeliedump/2000/0506/sys/src/9/pc/scsi.c
1,468d

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].