/*
 * Now thread-safe.
 *
 * The codeqlock guarantees that once codes != nil, that pointer will never 
 * change nor become invalid.
 *
 * The QLock in the Scsi structure moderates access to the raw device.
 * We should probably export some of the already-locked routines, but
 * there hasn't been a need.
 */

#include <u.h>
#include <libc.h>
#include <disk.h>

int scsiverbose;

#define codefile "/sys/lib/scsicodes"

static char *codes;
static QLock codeqlock;

static void
getcodes(void)
{
	Dir *d;
	int n, fd;

	if(codes != nil)
		return;

	qlock(&codeqlock);
	if(codes != nil) {
		qunlock(&codeqlock);
		return;
	}

	if((d = dirstat(codefile)) == nil || (fd = open(codefile, OREAD)) < 0) {
		qunlock(&codeqlock);
		return;
	}

	codes = malloc(1+d->length+1);
	if(codes == nil) {
		close(fd);
		qunlock(&codeqlock);
		free(d);
		return;
	}

	codes[0] = '\n';	/* for searches */
	n = readn(fd, codes+1, d->length);
	close(fd);
	free(d);

	if(n < 0) {
		free(codes);
		codes = nil;
		qunlock(&codeqlock);
		return;
	}
	codes[n] = '\0';
	qunlock(&codeqlock);
}
	
char*
scsierror(int asc, int ascq)
{
	char *p, *q;
	static char search[32];
	static char buf[128];

	getcodes();

	if(codes) {
		sprint(search, "\n%.2ux%.2ux ", asc, ascq);
		if(p = strstr(codes, search)) {
			p += 6;
			if((q = strchr(p, '\n')) == nil)
				q = p+strlen(p);
			snprint(buf, sizeof buf, "%.*s", (int)(q-p), p);
			return buf;
		}

		sprint(search, "\n%.2ux00", asc);
		if(p = strstr(codes, search)) {
			p += 6;
			if((q = strchr(p, '\n')) == nil)
				q = p+strlen(p);
			snprint(buf, sizeof buf, "(ascq #%.2ux) %.*s", ascq, (int)(q-p), p);
			return buf;
		}
	}

	sprint(buf, "scsi #%.2ux %.2ux", asc, ascq);
	return buf;
}


static int
_scsicmd(Scsi *s, uchar *cmd, int ccount, void *data, int dcount, int io, int dolock)
{
	uchar resp[16];
	int n;
	long status;

	if(dolock)
		qlock(&s->lk);
	if(write(s->rawfd, cmd, ccount) != ccount) {
		werrstr("cmd write: %r");
		if(dolock)
			qunlock(&s->lk);
		return -1;
	}

	switch(io){
	case Sread:
		n = read(s->rawfd, data, dcount);
		if(n < 0 && scsiverbose)
			fprint(2, "dat read: %r: cmd 0x%2.2uX\n", cmd[0]);
		break;
	case Swrite:
		n = write(s->rawfd, data, dcount);
		if(n != dcount && scsiverbose)
			fprint(2, "dat write: %r: cmd 0x%2.2uX\n", cmd[0]);
		break;
	default:
	case Snone:
		n = write(s->rawfd, resp, 0);
		if(n != 0 && scsiverbose)
			fprint(2, "none write: %r: cmd 0x%2.2uX\n", cmd[0]);
		break;
	}

	memset(resp, 0, sizeof(resp));
	if(read(s->rawfd, resp, sizeof(resp)) < 0) {
		werrstr("resp read: %r\n");
		if(dolock)
			qunlock(&s->lk);
		return -1;
	}
	if(dolock)
		qunlock(&s->lk);

	resp[sizeof(resp)-1] = '\0';
	status = atoi((char*)resp);
	if(status == 0)
		return n;

	werrstr("cmd %2.2uX: status %luX dcount %d n %d", cmd[0], status, dcount, n);
	return -1;
}

int
scsicmd(Scsi *s, uchar *cmd, int ccount, void *data, int dcount, int io)
{
	return _scsicmd(s, cmd, ccount, data, dcount, io, 1);
}

static int
_scsiready(Scsi *s, int dolock)
{
	uchar cmd[6], resp[16];
	int status, i;

	if(dolock)
		qlock(&s->lk);
	for(i=0; i<3; i++) {
		memset(cmd, 0, sizeof(cmd));
		cmd[0] = 0x00;	/* unit ready */
		if(write(s->rawfd, cmd, sizeof(cmd)) != sizeof(cmd)) {
			if(scsiverbose)
				fprint(2, "ur cmd write: %r\n");
			goto bad;
		}
		write(s->rawfd, resp, 0);
		if(read(s->rawfd, resp, sizeof(resp)) < 0) {
			if(scsiverbose)
				fprint(2, "ur resp read: %r\n");
			goto bad;
		}
		resp[sizeof(resp)-1] = '\0';
		status = atoi((char*)resp);
		if(status == 0 || status == 0x02) {
			if(dolock)
				qunlock(&s->lk);
			return 0;
		}
		if(scsiverbose)
			fprint(2, "target: bad status: %x\n", status);
	bad:;
	}
	if(dolock)
		qunlock(&s->lk);
	return -1;
}

int
scsiready(Scsi *s)
{
	return _scsiready(s, 1);
}

int
scsi(Scsi *s, uchar *cmd, int ccount, void *v, int dcount, int io)
{
	uchar req[6], sense[255], *data;
	int tries, code, key, n;
	char *p;

	data = v;
	SET(key); SET(code);
	qlock(&s->lk);
	for(tries=0; tries<2; tries++) {
		n = _scsicmd(s, cmd, ccount, data, dcount, io, 0);
		if(n >= 0) {
			qunlock(&s->lk);
			return n;
		}

		/*
		 * request sense
		 */
		memset(req, 0, sizeof(req));
		req[0] = 0x03;
		req[4] = sizeof(sense);
		memset(sense, 0xFF, sizeof(sense));
		if((n=_scsicmd(s, req, sizeof(req), sense, sizeof(sense), Sread, 0)) < 14)
			if(scsiverbose)
				fprint(2, "reqsense scsicmd %d: %r\n", n);
	
		if(_scsiready(s, 0) < 0)
			if(scsiverbose)
				fprint(2, "unit not ready\n");
	
		key = sense[2];
		code = sense[12];
		if(code == 0x17 || code == 0x18) {	/* recovered errors */
			qunlock(&s->lk);
			return dcount;
		}
		if(code == 0x28 && cmd[0] == 0x43) {	/* get info and media changed */
			s->nchange++;
			s->changetime = time(0);
			continue;
		}
	}

	/* drive not ready, or medium not present */
	if(cmd[0] == 0x43 && key == 2 && (code == 0x3a || code == 0x04)) {
		s->changetime = 0;
		qunlock(&s->lk);
		return -1;
	}
	qunlock(&s->lk);

	if(cmd[0] == 0x43 && key == 5 && code == 0x24)	/* blank media */
		return -1;

	p = scsierror(code, sense[13]);

	werrstr("cmd #%.2ux: %s", cmd[0], p);

	if(scsiverbose)
		fprint(2, "scsi cmd #%.2ux: %.2ux %.2ux %.2ux: %s\n", cmd[0], key, code, sense[13], p);

/*	if(key == 0) */
/*		return dcount; */
	return -1;
}

Scsi*
openscsi(char *dev)
{
	Scsi *s;
	int rawfd, ctlfd, l, n;
	char *name, *p, buf[512];

	l = strlen(dev)+1+3+1;
	name = malloc(l);
	if(name == nil)
		return nil;

	snprint(name, l, "%s/raw", dev);
	if((rawfd = open(name, ORDWR)) < 0) {
		free(name);
		return nil;
	}

	snprint(name, l, "%s/ctl", dev);
	if((ctlfd = open(name, ORDWR)) < 0) {
		free(name);
	Error:
		close(rawfd);
		return nil;
	}
	free(name);

	n = readn(ctlfd, buf, sizeof buf);
	close(ctlfd);
	if(n <= 0)
		goto Error;

	if(strncmp(buf, "inquiry ", 8) != 0 || (p = strchr(buf, '\n')) == nil)
		goto Error;
	*p = '\0';

	if((p = strdup(buf+8)) == nil)
		goto Error;

	s = malloc(sizeof(*s));
	if(s == nil) {
	Error1:
		free(p);
		goto Error;
	}
	memset(s, 0, sizeof(*s));

	s->rawfd = rawfd;
	s->inquire = p;
	s->changetime = time(0);
	
	if(scsiready(s) < 0)
		goto Error1;

	return s;
}
