1918 lines · 30.4 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <fis.h>#include "atazz.h"#include "tabs.h" #pragma	varargck	argpos	eprint	1#pragma	varargck	type	"π"	char** enum {	Dontread	= -2,}; int	interrupted;int	rflag;int	squelch;int	scttrace;uchar	issuetr[0x100]; Atatab	*idcmd;Atatab	*idpktcmd;Atatab	*sigcmd;Atatab	*sctread;Atatab	*sctissue; intπfmt(Fmt *f){	char **p; 	p = va_arg(f->args, char**);	if(p == nil)		return fmtstrcpy(f, "<nil**>");	for(; *p; p++){		fmtstrcpy(f, *p);		if(p[1] != nil)			fmtstrcpy(f, " ");	}	return 0;} inteprint(char *fmt, ...){	int n;	va_list args; 	if(squelch)		return 0;//	Bflush(&out); 	va_start(args, fmt);	n = vfprint(2, fmt, args);	va_end(args);	return n;} voidfisset(Req *r, uint i, uint v){	if(r->fisbits & 1<<i)		return;	r->fisbits |= 1<<i;	r->cmd.fis[i] = v;} voidprreq(Req *r){	uchar *u; 	print("%.2ux %.2ux\n", r->cmd.sdcmd, r->cmd.ataproto);	u = r->cmd.fis;	print("%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux ",		u[0], u[1], u[2], u[3], u[4], u[5], u[6], u[7]);	u += 8;	print("%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux\n",		u[0], u[1], u[2], u[3], u[4], u[5], u[6], u[7]);} char*protostr(char *p, char *e, int pr){	char *s; 	*p = 0;	if(pr & P28)		p = seprint(p, e, "28:");	else		p = seprint(p, e, "28:");	switch(pr & Pprotom){	default:		s = "unk";		break;	case Ppkt:		s = "pkt";		break;	case Pdiag:		s = "dig";		break;	case Preset:		s = "rst";		break;	case Pdmq:		s = "dmq";		break;	case Pdma:		s = "dma";		break;	case Ppio:		s = "pio";		break;	}	p = seprint(p, e, "%s:", s);	switch(pr & Pdatam){	default:		s = "nd";		break;	case Pin:		s = "in";		break;	case Pout:		s = "out";		break;	}	p = seprint(p, e, "%s", s);	return p;} voiddisplaycmd(Req *r, Atatab *a){	char buf[32];	int i; 	if(a->cc > nelem(issuetr) || !issuetr[a->cc])		return;	protostr(buf, buf + sizeof buf, a->protocol);	fprint(2, "cmd %s:%2ux ", buf, a->cc);	for(i = 0; i < 16; i++)		fprint(2, "%.2ux", r->cmd.fis[i]);	fprint(2, "\n");} intissueata(Req *r, Atatab *a, Dev *d){	uchar u;	int n, ok, pr, rv; 	r->haverfis = 0;	pr = a->protocol & Pdatam;	r->data = realloc(r->data, r->count);	if(r->data == nil && r->count > 0)		sysfatal("realloc: %r");	if(r->data == nil && pr != Pnd)		sysfatal("no data for cmd %.2ux", a->cc);	if(0 && r->fisbits)		print("fisbits %.16b\n", r->fisbits);	r->cmd.sdcmd = 0xff;	r->cmd.ataproto = a->protocol;	if(a->cc & 0xff00)		fisset(r, 0, a->cc >> 8);	else		fisset(r, 0, H2dev);	fisset(r, 1, Fiscmd);	fisset(r, 2, a->cc);	switch(pr){	case Pout:		if(r->rfd != Dontread){			n = readn(r->rfd, r->data, r->count);			if(n != r->count){				if(n == -1)					eprint("!short src read %r\n");				else					eprint("!short src read %d wanted %lld\n", n, r->count);				return -1;			}		}	case Pnd:	case Pin:		if(0 && (d->feat & Dlba) == 0 && (d->c | d->h | d->s)){			int c, h, s;			c = r->lba / (d->s * d->h);			h = (r->lba / d->s) % d->h;			s = (r->lba % d->s) + 1;fprint(2, "chs: %d %d %d\n", c, h, s);			fisset(r, 4, s);			fisset(r, 5, c);			fisset(r, 6, c >> 8);			fisset(r, 7, Ataobs | h);		}else{			fisset(r, 4, r->lba);			fisset(r, 5, r->lba >> 8);			fisset(r, 6, r->lba >> 16);			u = Ataobs;			if(pr == Pin || pr == Pout)				u |= Atalba;			if((d->feat & Dllba) == 0)				u |= (r->lba >> 24) & 7;			fisset(r, 7, u);			fisset(r, 8, r->lba >> 24);			fisset(r, 9, r->lba >> 32);			fisset(r, 10, r->lba >> 48);		}		fisset(r, 12, r->nsect);		fisset(r, 13, r->nsect >> 8);		break;	}	fisset(r, 7, Ataobs);	displaycmd(r, a);	if(write(d->fd, &r->cmd, Cmdsz) != Cmdsz){		eprint("fis write error: %r\n");		return -1;	} 	werrstr("");	switch(pr){	default:		ok = read(d->fd, "", 0) == 0;		break;	case Pin:		ok = read(d->fd, r->data, r->count) == r->count;		r->lba += r->nsect;		break;	case Pout:		ok = write(d->fd, r->data, r->count) == r->count;		r->lba += r->nsect;		break;	}	rv = 0;	if(ok == 0){		eprint("xfer error: %.2ux %r\n", a->cc);		rv = -1;	}	switch(n = read(d->fd, &r->reply, Replysz)){	case Replysz:		r->haverfis = 1;		return rv;	case -1:		eprint("status fis read error: %r\n");		return -1;	default:		eprint("status fis read error: short read: %d of %d\n", n, Replysz);		return -1;	}} /* * cheezy code; just issue a inquiry.  use scuzz * for real work with atapi devices */intissuepkt(Req *r, Atatab *a, Dev *d){	char *p;	uchar *u;	int n, rv; 	r->haverfis = 0;	r->count = 128;	r->data = realloc(r->data, r->count);	if(r->data == nil && r->count > 0)		sysfatal("realloc: %r");	r->cmd.sdcmd = 0xff;	r->cmd.ataproto = a->protocol;	memset(r->cmd.fis, 0, Fissize); 	u = r->cmd.fis;	u[0] = 0x12;	u[4] = 128-1;	displaycmd(r, a); 	if(write(d->fd, &r->cmd, 6 + 2) != 6 + 2){		eprint("fis write error: %r\n");		return -1;	}	n = read(d->fd, r->data, r->count);	rv = 0;	if(n == -1){		eprint("xfer error: %.2ux %r\n", a->cc);		rv = -1;	} 	print("n is %d (%lld)\n", n, r->count);	if(n > 32){		p = (char*)r->data;		print("%.8s %.16s\n", p + 8, p + 16);	} 	u = (uchar*)&r->reply;	n = read(d->fd, u, Replysz);	if(n < 0){		eprint("status fis read error (%d): %r\n", n);		return -1;	}		if(n < Replysz)		memset(u + n, 0, Replysz - n);	r->haverfis = 1;	return rv;} /* * silly protocol: * 1.  use write log ext 0xe0 to fill out the command * 2.  use write log ext 0xe1 to write or data (if any) * 3.  use read log ext 0xe0 to nab status.  polled */voidsctreq(Req *r){	memset(r, 0, sizeof *r);	r->rfd = Dontread;} char*sctrsp(Req *r){	uint i;	static char buf[32]; 	if(!r->haverfis)		return "no rfis";	if((r->reply.fis[Frerror] & (Eidnf | Eabrt)) == 0)		return nil;	i = r->reply.fis[Fsc] | r->reply.fis[Flba0]<<8;	if(i == 0xffff)		return "in progress";	else if(i == 0){		snprint(buf, sizeof buf, "unknown %.2ux", r->reply.fis[Frerror]);		return buf;	}else if(i < nelem(sctetab))		return sctetab[i];	else		return "<bad>";} char*sctready(Dev *d, int sec){	char *s;	int i;	Req r;	static char e[ERRMAX]; 	for(;;){		if(interrupted){			s = "interrupted";			break;		}		sctreq(&r);		fisset(&r, Fsc, 1);		fisset(&r, Flba0, 0xe0);		r.count = 512;		i = issueata(&r, sctread, d);		free(r.data);		if(i == -1){			rerrstr(e, ERRMAX);			s = e;			break;		}		if((r.cmd.fis[Fsc] | r.cmd.fis[Fsc8]<<8) != 0xffff){			s = sctrsp(&r);			break;		}		if(sec == 0){			s = "timeout";			break;		}		sleep(1000);		sec--;	}	return s;} typedef struct Sttab Sttab;struct Sttab {	int	o;	int	sz;	char	*name;}; Sttab sctt[] = {	0,	2,	"version",	2,	2,	"period",	4,	2,	"intval",	6,	1,	"max op",	7,	1,	"max",	8,	1,	"min op",	9,	1,	"min",}; voidsctttab(Req *r){	char c, buf[10];	int i, n, l, d;	uchar *u; 	u = r->data;	for(i = 0; i < nelem(sctt); i++){		switch(sctt[i].sz){		case 1:			c = u[sctt[i].o];			print("%s\t%d\n", sctt[i].name, c);			break;		case 2:			d = w(u + sctt[i].o);			print("%s\t%ud\n", sctt[i].name, d);			break;		}	}	n = w(u + 30);	l = w(u + 32);	for(i = 0; i < n; i++){		c = u[34 + (l + i) % n];		if((uchar)c == 0x80)			snprint(buf, sizeof buf, "xx");		else			snprint(buf, sizeof buf, "%d", c);		d = i%10;		if(d == 0)			print("\nt%d\t%d", i, c);		else			print("% .2d", c);	}	if(i%10)		print("\n");} static struct {	uint	code;	char	*s;	char	*ms;} fxtab[] = {	0x00010001,	"set features",	0,	0x00010002,	"enabled",	0,	0x00010003,	"disabled",	0, 	0x00020001,	"enabled",	0,	0x00020002,	"disabled",	0, 	0x0003ffff,	"minute",	"minutes",}; voidsctfcout(ushort *u, Req *r){	uchar *f;	ushort v;	uint c, m, i; 	f = r->reply.fis;	switch(u[1]){	case 1:	case 2:		v = f[Fsc] | f[Flba0]<<8;		c = u[2]<<16 | v;		m = u[2]<<16 | 0xffff;		for(i = 0; i < nelem(fxtab); i++)			if(fxtab[i].code == c)				print("%s\n", fxtab[i].s);			else if(fxtab[i].code == m)				print("%d %s\n", v, v>1? fxtab[i].ms: fxtab[i].s);		break;	case 3:		v = f[Fsc] | f[Flba0]<<8;		if(v & 1)			print("preserve\n");		else			print("volatile\n");		break;	}} voidscterout(ushort *u, Req *r){	uchar *f;	uint v; 	f = r->reply.fis;	switch(u[1]){	case 2:		v = f[Fsc] | f[Flba0]<<8;		v *= 100;		print("%dms\n", v);	}} voidsctout(ushort *u, Req *r){	switch(u[0]){	case 5:		sctttab(r);		break;	case 4:		sctfcout(u, r);

Lines 1–500 of 1918.