xref: /inferno-os/os/boot/pc/sdaoe.c (revision a17fe75d12acceb8fa829b70751afdba094d9739)
1*8a8c2d74SCharles.Forsyth /*
2*8a8c2d74SCharles.Forsyth  * aoe sd bootstrap driver, copyright © 2007 coraid
3*8a8c2d74SCharles.Forsyth  */
4*8a8c2d74SCharles.Forsyth 
5*8a8c2d74SCharles.Forsyth #include "u.h"
6*8a8c2d74SCharles.Forsyth #include "mem.h"
7*8a8c2d74SCharles.Forsyth #include "lib.h"
8*8a8c2d74SCharles.Forsyth #include "dat.h"
9*8a8c2d74SCharles.Forsyth #include "fns.h"
10*8a8c2d74SCharles.Forsyth #include "io.h"
11*8a8c2d74SCharles.Forsyth #include "sd.h"
12*8a8c2d74SCharles.Forsyth #include "aoe.h"
13*8a8c2d74SCharles.Forsyth 
14*8a8c2d74SCharles.Forsyth 
15*8a8c2d74SCharles.Forsyth enum {
16*8a8c2d74SCharles.Forsyth 	Nctlr	= 4,
17*8a8c2d74SCharles.Forsyth };
18*8a8c2d74SCharles.Forsyth 
19*8a8c2d74SCharles.Forsyth enum {
20*8a8c2d74SCharles.Forsyth 	/* sync with ahci.h */
21*8a8c2d74SCharles.Forsyth 	Dllba 	= 1<<0,
22*8a8c2d74SCharles.Forsyth 	Dsmart	= 1<<1,
23*8a8c2d74SCharles.Forsyth 	Dpower	= 1<<2,
24*8a8c2d74SCharles.Forsyth 	Dnop	= 1<<3,
25*8a8c2d74SCharles.Forsyth 	Datapi	= 1<<4,
26*8a8c2d74SCharles.Forsyth 	Datapi16= 1<<5,
27*8a8c2d74SCharles.Forsyth };
28*8a8c2d74SCharles.Forsyth 
29*8a8c2d74SCharles.Forsyth enum {
30*8a8c2d74SCharles.Forsyth 	Tfree	= -1,
31*8a8c2d74SCharles.Forsyth 	Tmgmt,
32*8a8c2d74SCharles.Forsyth };
33*8a8c2d74SCharles.Forsyth 
34*8a8c2d74SCharles.Forsyth typedef struct Ctlr Ctlr;
35*8a8c2d74SCharles.Forsyth struct Ctlr{
36*8a8c2d74SCharles.Forsyth 	Ctlr	*next;
37*8a8c2d74SCharles.Forsyth 	SDunit	*unit;
38*8a8c2d74SCharles.Forsyth 
39*8a8c2d74SCharles.Forsyth 	int	ctlrno;
40*8a8c2d74SCharles.Forsyth 	int	major;
41*8a8c2d74SCharles.Forsyth 	int	minor;
42*8a8c2d74SCharles.Forsyth 	uchar	ea[Eaddrlen];
43*8a8c2d74SCharles.Forsyth 	ushort	lasttag;
44*8a8c2d74SCharles.Forsyth 
45*8a8c2d74SCharles.Forsyth 	ulong	vers;
46*8a8c2d74SCharles.Forsyth 	uchar	mediachange;
47*8a8c2d74SCharles.Forsyth 	uchar	flag;
48*8a8c2d74SCharles.Forsyth 	uchar	smart;
49*8a8c2d74SCharles.Forsyth 	uchar	smartrs;
50*8a8c2d74SCharles.Forsyth 	uchar	feat;
51*8a8c2d74SCharles.Forsyth 
52*8a8c2d74SCharles.Forsyth 	uvlong	sectors;
53*8a8c2d74SCharles.Forsyth 	char	serial[20+1];
54*8a8c2d74SCharles.Forsyth 	char	firmware[8+1];
55*8a8c2d74SCharles.Forsyth 	char	model[40+1];
56*8a8c2d74SCharles.Forsyth 	char	ident[0x100];
57*8a8c2d74SCharles.Forsyth };
58*8a8c2d74SCharles.Forsyth 
59*8a8c2d74SCharles.Forsyth static	Ctlr	*head;
60*8a8c2d74SCharles.Forsyth static	Ctlr	*tail;
61*8a8c2d74SCharles.Forsyth 
62*8a8c2d74SCharles.Forsyth static	int	aoeether[10];
63*8a8c2d74SCharles.Forsyth 
64*8a8c2d74SCharles.Forsyth SDifc sdaoeifc;
65*8a8c2d74SCharles.Forsyth 
66*8a8c2d74SCharles.Forsyth static void
hnputs(uchar * p,ushort i)67*8a8c2d74SCharles.Forsyth hnputs(uchar *p, ushort i)
68*8a8c2d74SCharles.Forsyth {
69*8a8c2d74SCharles.Forsyth 	p[0] = i >> 8;
70*8a8c2d74SCharles.Forsyth 	p[1] = i;
71*8a8c2d74SCharles.Forsyth }
72*8a8c2d74SCharles.Forsyth 
73*8a8c2d74SCharles.Forsyth static void
hnputl(uchar * p,ulong i)74*8a8c2d74SCharles.Forsyth hnputl(uchar *p, ulong i)
75*8a8c2d74SCharles.Forsyth {
76*8a8c2d74SCharles.Forsyth 	p[0] = i >> 24;
77*8a8c2d74SCharles.Forsyth 	p[1] = i >> 16;
78*8a8c2d74SCharles.Forsyth 	p[2] = i >> 8;
79*8a8c2d74SCharles.Forsyth 	p[3] = i;
80*8a8c2d74SCharles.Forsyth }
81*8a8c2d74SCharles.Forsyth 
82*8a8c2d74SCharles.Forsyth static ushort
nhgets(uchar * p)83*8a8c2d74SCharles.Forsyth nhgets(uchar *p)
84*8a8c2d74SCharles.Forsyth {
85*8a8c2d74SCharles.Forsyth 	return *p<<8 | p[1];
86*8a8c2d74SCharles.Forsyth }
87*8a8c2d74SCharles.Forsyth 
88*8a8c2d74SCharles.Forsyth static ulong
nhgetl(uchar * p)89*8a8c2d74SCharles.Forsyth nhgetl(uchar *p)
90*8a8c2d74SCharles.Forsyth {
91*8a8c2d74SCharles.Forsyth 	return p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3];
92*8a8c2d74SCharles.Forsyth }
93*8a8c2d74SCharles.Forsyth 
94*8a8c2d74SCharles.Forsyth static int
newtag(Ctlr * d)95*8a8c2d74SCharles.Forsyth newtag(Ctlr *d)
96*8a8c2d74SCharles.Forsyth {
97*8a8c2d74SCharles.Forsyth 	int t;
98*8a8c2d74SCharles.Forsyth 
99*8a8c2d74SCharles.Forsyth 	for(;;){
100*8a8c2d74SCharles.Forsyth 		t = ++d->lasttag << 16;
101*8a8c2d74SCharles.Forsyth 		t |= m->ticks & 0xffff;
102*8a8c2d74SCharles.Forsyth 		switch(t) {
103*8a8c2d74SCharles.Forsyth 		case Tfree:
104*8a8c2d74SCharles.Forsyth 		case Tmgmt:
105*8a8c2d74SCharles.Forsyth 			break;
106*8a8c2d74SCharles.Forsyth 		default:
107*8a8c2d74SCharles.Forsyth 			return t;
108*8a8c2d74SCharles.Forsyth 		}
109*8a8c2d74SCharles.Forsyth 	}
110*8a8c2d74SCharles.Forsyth }
111*8a8c2d74SCharles.Forsyth 
112*8a8c2d74SCharles.Forsyth static int
hset(Ctlr * d,Aoehdr * h,int cmd)113*8a8c2d74SCharles.Forsyth hset(Ctlr *d, Aoehdr *h, int cmd)
114*8a8c2d74SCharles.Forsyth {
115*8a8c2d74SCharles.Forsyth 	int tag;
116*8a8c2d74SCharles.Forsyth 
117*8a8c2d74SCharles.Forsyth 	memmove(h->dst, d->ea, Eaddrlen);
118*8a8c2d74SCharles.Forsyth 	hnputs(h->type, Aoetype);
119*8a8c2d74SCharles.Forsyth 	h->verflag = Aoever << 4;
120*8a8c2d74SCharles.Forsyth 	hnputs(h->major, d->major);
121*8a8c2d74SCharles.Forsyth 	h->minor = d->minor;
122*8a8c2d74SCharles.Forsyth 	h->cmd = cmd;
123*8a8c2d74SCharles.Forsyth 	hnputl(h->tag, tag = newtag(d));
124*8a8c2d74SCharles.Forsyth 	return tag;
125*8a8c2d74SCharles.Forsyth }
126*8a8c2d74SCharles.Forsyth 
127*8a8c2d74SCharles.Forsyth static void
idmove(char * p,ushort * a,int n)128*8a8c2d74SCharles.Forsyth idmove(char *p, ushort *a, int n)
129*8a8c2d74SCharles.Forsyth {
130*8a8c2d74SCharles.Forsyth 	int i;
131*8a8c2d74SCharles.Forsyth 	char *op, *e;
132*8a8c2d74SCharles.Forsyth 
133*8a8c2d74SCharles.Forsyth 	op = p;
134*8a8c2d74SCharles.Forsyth 	for(i = 0; i < n / 2; i++){
135*8a8c2d74SCharles.Forsyth 		*p++ = a[i] >> 8;
136*8a8c2d74SCharles.Forsyth 		*p++ = a[i];
137*8a8c2d74SCharles.Forsyth 	}
138*8a8c2d74SCharles.Forsyth 	*p = 0;
139*8a8c2d74SCharles.Forsyth 	while(p > op && *--p == ' ')
140*8a8c2d74SCharles.Forsyth 		*p = 0;
141*8a8c2d74SCharles.Forsyth 	e = p;
142*8a8c2d74SCharles.Forsyth 	p = op;
143*8a8c2d74SCharles.Forsyth 	while(*p == ' ')
144*8a8c2d74SCharles.Forsyth 		p++;
145*8a8c2d74SCharles.Forsyth 	memmove(op, p, n - (e - p));
146*8a8c2d74SCharles.Forsyth }
147*8a8c2d74SCharles.Forsyth 
148*8a8c2d74SCharles.Forsyth static ushort
gbit16(void * a)149*8a8c2d74SCharles.Forsyth gbit16(void *a)
150*8a8c2d74SCharles.Forsyth {
151*8a8c2d74SCharles.Forsyth 	uchar *i;
152*8a8c2d74SCharles.Forsyth 
153*8a8c2d74SCharles.Forsyth 	i = a;
154*8a8c2d74SCharles.Forsyth 	return i[1]<<8 | i[0];
155*8a8c2d74SCharles.Forsyth }
156*8a8c2d74SCharles.Forsyth 
157*8a8c2d74SCharles.Forsyth static ulong
gbit32(void * a)158*8a8c2d74SCharles.Forsyth gbit32(void *a)
159*8a8c2d74SCharles.Forsyth {
160*8a8c2d74SCharles.Forsyth 	uchar *i;
161*8a8c2d74SCharles.Forsyth 	ulong j;
162*8a8c2d74SCharles.Forsyth 
163*8a8c2d74SCharles.Forsyth 	i = a;
164*8a8c2d74SCharles.Forsyth 	j  = i[3] << 24;
165*8a8c2d74SCharles.Forsyth 	j |= i[2] << 16;
166*8a8c2d74SCharles.Forsyth 	j |= i[1] << 8;
167*8a8c2d74SCharles.Forsyth 	j |= i[0];
168*8a8c2d74SCharles.Forsyth 	return j;
169*8a8c2d74SCharles.Forsyth }
170*8a8c2d74SCharles.Forsyth 
171*8a8c2d74SCharles.Forsyth static uvlong
gbit64(void * a)172*8a8c2d74SCharles.Forsyth gbit64(void *a)
173*8a8c2d74SCharles.Forsyth {
174*8a8c2d74SCharles.Forsyth 	uchar *i;
175*8a8c2d74SCharles.Forsyth 
176*8a8c2d74SCharles.Forsyth 	i = a;
177*8a8c2d74SCharles.Forsyth 	return (uvlong)gbit32(i+4) << 32 | gbit32(a);
178*8a8c2d74SCharles.Forsyth }
179*8a8c2d74SCharles.Forsyth 
180*8a8c2d74SCharles.Forsyth static int
ataidentify(Ctlr * c,ushort * id)181*8a8c2d74SCharles.Forsyth ataidentify(Ctlr *c, ushort *id)
182*8a8c2d74SCharles.Forsyth {
183*8a8c2d74SCharles.Forsyth 	vlong s;
184*8a8c2d74SCharles.Forsyth 	int i;
185*8a8c2d74SCharles.Forsyth 
186*8a8c2d74SCharles.Forsyth 	i = gbit16(id+83) | gbit16(id+86);
187*8a8c2d74SCharles.Forsyth 	if(i & (1 << 10)){
188*8a8c2d74SCharles.Forsyth 		c->feat |= Dllba;
189*8a8c2d74SCharles.Forsyth 		s = gbit64(id+100);
190*8a8c2d74SCharles.Forsyth 	}else
191*8a8c2d74SCharles.Forsyth 		s = gbit32(id+60);
192*8a8c2d74SCharles.Forsyth 
193*8a8c2d74SCharles.Forsyth 	idmove(c->serial, id+10, 20);
194*8a8c2d74SCharles.Forsyth 	idmove(c->firmware, id+23, 8);
195*8a8c2d74SCharles.Forsyth 	idmove(c->model, id+27, 40);
196*8a8c2d74SCharles.Forsyth 
197*8a8c2d74SCharles.Forsyth print("aoe discovers %d.%d: %s %s\n", c->major, c->minor, c->model, c->serial);
198*8a8c2d74SCharles.Forsyth 
199*8a8c2d74SCharles.Forsyth 	c->sectors = s;
200*8a8c2d74SCharles.Forsyth 	c->mediachange = 1;
201*8a8c2d74SCharles.Forsyth 	return 0;
202*8a8c2d74SCharles.Forsyth }
203*8a8c2d74SCharles.Forsyth 
204*8a8c2d74SCharles.Forsyth static void
identifydump(Aoeata * a)205*8a8c2d74SCharles.Forsyth identifydump(Aoeata *a)
206*8a8c2d74SCharles.Forsyth {
207*8a8c2d74SCharles.Forsyth 	print("%E %E type=%.4ux verflag=%x error=%x %d.%d cmd=%d tag=%.8lux\n",
208*8a8c2d74SCharles.Forsyth 		a->dst, a->src, nhgets(a->type), a->verflag, a->error,
209*8a8c2d74SCharles.Forsyth 		nhgets(a->major), a->minor, a->cmd, nhgetl(a->tag));
210*8a8c2d74SCharles.Forsyth 	print("   aflag=%x errfeat=%ux scnt=%d cmdstat=%ux, lba=%d? res=%.4ux\n",
211*8a8c2d74SCharles.Forsyth 		a->aflag, a->errfeat, a->scnt, a->cmdstat, 0, nhgets(a->res));
212*8a8c2d74SCharles.Forsyth }
213*8a8c2d74SCharles.Forsyth 
214*8a8c2d74SCharles.Forsyth static int
idpkt(Ctlr * c,Aoeata * a)215*8a8c2d74SCharles.Forsyth idpkt(Ctlr *c, Aoeata *a)
216*8a8c2d74SCharles.Forsyth {
217*8a8c2d74SCharles.Forsyth 	memset(a, 0, sizeof *a);
218*8a8c2d74SCharles.Forsyth 	a->cmdstat = Cid;
219*8a8c2d74SCharles.Forsyth 	a->scnt = 1;
220*8a8c2d74SCharles.Forsyth 	a->lba[3] = 0xa0;
221*8a8c2d74SCharles.Forsyth 	return hset(c, a, ACata);
222*8a8c2d74SCharles.Forsyth }
223*8a8c2d74SCharles.Forsyth 
224*8a8c2d74SCharles.Forsyth static int
chktag(int * out,int nout,int tag)225*8a8c2d74SCharles.Forsyth chktag(int *out, int nout, int tag)
226*8a8c2d74SCharles.Forsyth {
227*8a8c2d74SCharles.Forsyth 	int j;
228*8a8c2d74SCharles.Forsyth 
229*8a8c2d74SCharles.Forsyth 	for(j = 0; j <= nout; j++)
230*8a8c2d74SCharles.Forsyth 		if(out[j] == tag)
231*8a8c2d74SCharles.Forsyth 			return 0;
232*8a8c2d74SCharles.Forsyth print("wrong tag\n");
233*8a8c2d74SCharles.Forsyth 	for(j = 0; j <= nout; j++)
234*8a8c2d74SCharles.Forsyth 		print("%.8ux != %.8ux\n", out[j], tag);
235*8a8c2d74SCharles.Forsyth 	return -1;
236*8a8c2d74SCharles.Forsyth }
237*8a8c2d74SCharles.Forsyth 
238*8a8c2d74SCharles.Forsyth /*
239*8a8c2d74SCharles.Forsyth  * ignore the tag for identify.  better than ignoring
240*8a8c2d74SCharles.Forsyth  * a response to the wrong identify request
241*8a8c2d74SCharles.Forsyth  */
242*8a8c2d74SCharles.Forsyth static int
identify(Ctlr * c)243*8a8c2d74SCharles.Forsyth identify(Ctlr *c)
244*8a8c2d74SCharles.Forsyth {
245*8a8c2d74SCharles.Forsyth 	int tag[5], i, n;
246*8a8c2d74SCharles.Forsyth 	Aoeata *a;
247*8a8c2d74SCharles.Forsyth 	Etherpkt p;
248*8a8c2d74SCharles.Forsyth 
249*8a8c2d74SCharles.Forsyth 	memset(&p, 0, sizeof p);
250*8a8c2d74SCharles.Forsyth 	a = (Aoeata*)&p;
251*8a8c2d74SCharles.Forsyth 	i = 0;
252*8a8c2d74SCharles.Forsyth 	do {
253*8a8c2d74SCharles.Forsyth 		if(i == 5){
254*8a8c2d74SCharles.Forsyth 			print("aoe: identify timeout\n");
255*8a8c2d74SCharles.Forsyth 			return -1;
256*8a8c2d74SCharles.Forsyth 		}
257*8a8c2d74SCharles.Forsyth 		tag[i] = idpkt(c, a);
258*8a8c2d74SCharles.Forsyth 		ethertxpkt(c->ctlrno, &p, sizeof *a, 0);
259*8a8c2d74SCharles.Forsyth 		memset(&p, 0, sizeof p);
260*8a8c2d74SCharles.Forsyth next:
261*8a8c2d74SCharles.Forsyth 		n = etherrxpkt(c->ctlrno, &p, 125);
262*8a8c2d74SCharles.Forsyth 		if(n == 0){
263*8a8c2d74SCharles.Forsyth 			i++;
264*8a8c2d74SCharles.Forsyth 			continue;
265*8a8c2d74SCharles.Forsyth 		}
266*8a8c2d74SCharles.Forsyth 		if(nhgets(a->type) != Aoetype)
267*8a8c2d74SCharles.Forsyth 			goto next;
268*8a8c2d74SCharles.Forsyth 		if(nhgets(a->major) != c->major || a->minor != c->minor){
269*8a8c2d74SCharles.Forsyth 			print("wrong device %d.%d want %d.%d; %d\n",
270*8a8c2d74SCharles.Forsyth 				nhgets(a->major), a->minor,
271*8a8c2d74SCharles.Forsyth 				c->major, c->minor, n);
272*8a8c2d74SCharles.Forsyth 			goto next;
273*8a8c2d74SCharles.Forsyth 		}
274*8a8c2d74SCharles.Forsyth 		if(chktag(tag, i, nhgetl(a->tag)) == -1)
275*8a8c2d74SCharles.Forsyth 			goto next;
276*8a8c2d74SCharles.Forsyth 		if(a->cmdstat & 0xa9){
277*8a8c2d74SCharles.Forsyth 			print("aoe: ata error on identify: %2ux\n", a->cmdstat);
278*8a8c2d74SCharles.Forsyth 			return -1;
279*8a8c2d74SCharles.Forsyth 		}
280*8a8c2d74SCharles.Forsyth 	} while (a->scnt != 1);
281*8a8c2d74SCharles.Forsyth 
282*8a8c2d74SCharles.Forsyth 	c->feat = 0;
283*8a8c2d74SCharles.Forsyth 	ataidentify(c, (ushort*)(a+1));
284*8a8c2d74SCharles.Forsyth 	return 0;
285*8a8c2d74SCharles.Forsyth }
286*8a8c2d74SCharles.Forsyth 
287*8a8c2d74SCharles.Forsyth static Ctlr*
ctlrlookup(int major,int minor)288*8a8c2d74SCharles.Forsyth ctlrlookup(int major, int minor)
289*8a8c2d74SCharles.Forsyth {
290*8a8c2d74SCharles.Forsyth 	Ctlr *c;
291*8a8c2d74SCharles.Forsyth 
292*8a8c2d74SCharles.Forsyth 	for(c = head; c; c = c->next)
293*8a8c2d74SCharles.Forsyth 		if(c->major == major && c->minor == minor)
294*8a8c2d74SCharles.Forsyth 			break;
295*8a8c2d74SCharles.Forsyth 	return c;
296*8a8c2d74SCharles.Forsyth }
297*8a8c2d74SCharles.Forsyth 
298*8a8c2d74SCharles.Forsyth static Ctlr*
newctlr(Etherpkt * p)299*8a8c2d74SCharles.Forsyth newctlr(Etherpkt *p)
300*8a8c2d74SCharles.Forsyth {
301*8a8c2d74SCharles.Forsyth 	int major, minor;
302*8a8c2d74SCharles.Forsyth 	Aoeqc *q;
303*8a8c2d74SCharles.Forsyth 	Ctlr *c;
304*8a8c2d74SCharles.Forsyth 
305*8a8c2d74SCharles.Forsyth 	q = (Aoeqc*)p;
306*8a8c2d74SCharles.Forsyth 	if(nhgets(q->type) != Aoetype)
307*8a8c2d74SCharles.Forsyth 		return 0;
308*8a8c2d74SCharles.Forsyth 	major = nhgets(q->major);
309*8a8c2d74SCharles.Forsyth 	minor = q->minor;
310*8a8c2d74SCharles.Forsyth 
311*8a8c2d74SCharles.Forsyth 	if(major == 0xffff || minor == 0xff)
312*8a8c2d74SCharles.Forsyth 		return 0;
313*8a8c2d74SCharles.Forsyth 
314*8a8c2d74SCharles.Forsyth 	if(ctlrlookup(major, minor)){
315*8a8c2d74SCharles.Forsyth 		print("duplicate shelf.slot\n");
316*8a8c2d74SCharles.Forsyth 		return 0;
317*8a8c2d74SCharles.Forsyth 	}
318*8a8c2d74SCharles.Forsyth 
319*8a8c2d74SCharles.Forsyth 	if((c = malloc(sizeof *c)) == 0)
320*8a8c2d74SCharles.Forsyth 		return 0;
321*8a8c2d74SCharles.Forsyth 	c->major = major;
322*8a8c2d74SCharles.Forsyth 	c->minor = minor;
323*8a8c2d74SCharles.Forsyth 	memmove(c->ea, q->src, Eaddrlen);
324*8a8c2d74SCharles.Forsyth 
325*8a8c2d74SCharles.Forsyth 	if(head != 0)
326*8a8c2d74SCharles.Forsyth 		tail->next = c;
327*8a8c2d74SCharles.Forsyth 	else
328*8a8c2d74SCharles.Forsyth 		head = c;
329*8a8c2d74SCharles.Forsyth 	tail = c;
330*8a8c2d74SCharles.Forsyth 	return c;
331*8a8c2d74SCharles.Forsyth }
332*8a8c2d74SCharles.Forsyth 
333*8a8c2d74SCharles.Forsyth static void
discover(int major,int minor)334*8a8c2d74SCharles.Forsyth discover(int major, int minor)
335*8a8c2d74SCharles.Forsyth {
336*8a8c2d74SCharles.Forsyth 	int i;
337*8a8c2d74SCharles.Forsyth 	Aoehdr *h;
338*8a8c2d74SCharles.Forsyth 	Etherpkt p;
339*8a8c2d74SCharles.Forsyth 
340*8a8c2d74SCharles.Forsyth 	for(i = 0; i < nelem(aoeether); i++){
341*8a8c2d74SCharles.Forsyth 		if(aoeether[i] == 0)
342*8a8c2d74SCharles.Forsyth 			continue;
343*8a8c2d74SCharles.Forsyth 		memset(&p, 0, ETHERMINTU);
344*8a8c2d74SCharles.Forsyth 		h = (Aoehdr*)&p;
345*8a8c2d74SCharles.Forsyth 		memset(h->dst, 0xff, sizeof h->dst);
346*8a8c2d74SCharles.Forsyth 		hnputs(h->type, Aoetype);
347*8a8c2d74SCharles.Forsyth 		h->verflag = Aoever << 4;
348*8a8c2d74SCharles.Forsyth 		hnputs(h->major, major);
349*8a8c2d74SCharles.Forsyth 		h->minor = minor;
350*8a8c2d74SCharles.Forsyth 		h->cmd = ACconfig;
351*8a8c2d74SCharles.Forsyth 		ethertxpkt(i, &p, ETHERMINTU, 0);
352*8a8c2d74SCharles.Forsyth 	}
353*8a8c2d74SCharles.Forsyth }
354*8a8c2d74SCharles.Forsyth 
355*8a8c2d74SCharles.Forsyth static int
rxany(Etherpkt * p,int t)356*8a8c2d74SCharles.Forsyth rxany(Etherpkt *p, int t)
357*8a8c2d74SCharles.Forsyth {
358*8a8c2d74SCharles.Forsyth 	int i, n;
359*8a8c2d74SCharles.Forsyth 
360*8a8c2d74SCharles.Forsyth 	for(i = 0; i < nelem(aoeether); i++){
361*8a8c2d74SCharles.Forsyth 		if(aoeether[i] == 0)
362*8a8c2d74SCharles.Forsyth 			continue;
363*8a8c2d74SCharles.Forsyth 		while ((n = etherrxpkt(i, p, t)) != 0)
364*8a8c2d74SCharles.Forsyth 			if(nhgets(p->type) == Aoetype)
365*8a8c2d74SCharles.Forsyth 				return n;
366*8a8c2d74SCharles.Forsyth 	}
367*8a8c2d74SCharles.Forsyth 	return 0;
368*8a8c2d74SCharles.Forsyth }
369*8a8c2d74SCharles.Forsyth 
370*8a8c2d74SCharles.Forsyth static int
aoeprobe(int major,int minor,SDev * s)371*8a8c2d74SCharles.Forsyth aoeprobe(int major, int minor, SDev *s)
372*8a8c2d74SCharles.Forsyth {
373*8a8c2d74SCharles.Forsyth 	Ctlr *ctlr;
374*8a8c2d74SCharles.Forsyth 	Etherpkt p;
375*8a8c2d74SCharles.Forsyth 	int n, i;
376*8a8c2d74SCharles.Forsyth 
377*8a8c2d74SCharles.Forsyth 	for(i = 0;; i += 200){
378*8a8c2d74SCharles.Forsyth 		if(i > 8000)
379*8a8c2d74SCharles.Forsyth 			return -1;
380*8a8c2d74SCharles.Forsyth 		discover(major, minor);
381*8a8c2d74SCharles.Forsyth again:
382*8a8c2d74SCharles.Forsyth 		n = rxany(&p, 100);
383*8a8c2d74SCharles.Forsyth 		if(n > 0 && (ctlr = newctlr(&p)))
384*8a8c2d74SCharles.Forsyth 			break;
385*8a8c2d74SCharles.Forsyth 		if(n > 0)
386*8a8c2d74SCharles.Forsyth 			goto again;
387*8a8c2d74SCharles.Forsyth 	}
388*8a8c2d74SCharles.Forsyth 
389*8a8c2d74SCharles.Forsyth 	s->ctlr = ctlr;
390*8a8c2d74SCharles.Forsyth 	s->ifc = &sdaoeifc;
391*8a8c2d74SCharles.Forsyth 	s->nunit = 1;
392*8a8c2d74SCharles.Forsyth 	return 0;
393*8a8c2d74SCharles.Forsyth }
394*8a8c2d74SCharles.Forsyth 
395*8a8c2d74SCharles.Forsyth static char 	*probef[32];
396*8a8c2d74SCharles.Forsyth static int 	nprobe;
397*8a8c2d74SCharles.Forsyth 
398*8a8c2d74SCharles.Forsyth int
pnpprobeid(char * s)399*8a8c2d74SCharles.Forsyth pnpprobeid(char *s)
400*8a8c2d74SCharles.Forsyth {
401*8a8c2d74SCharles.Forsyth 	int id;
402*8a8c2d74SCharles.Forsyth 
403*8a8c2d74SCharles.Forsyth 	if(strlen(s) < 2)
404*8a8c2d74SCharles.Forsyth 		return 0;
405*8a8c2d74SCharles.Forsyth 	id = 'e';
406*8a8c2d74SCharles.Forsyth 	if(s[1] == '!')
407*8a8c2d74SCharles.Forsyth 		id = s[0];
408*8a8c2d74SCharles.Forsyth 	return id;
409*8a8c2d74SCharles.Forsyth }
410*8a8c2d74SCharles.Forsyth 
411*8a8c2d74SCharles.Forsyth int
tokenize(char * s,char ** args,int maxargs)412*8a8c2d74SCharles.Forsyth tokenize(char *s, char **args, int maxargs)
413*8a8c2d74SCharles.Forsyth {
414*8a8c2d74SCharles.Forsyth 	int nargs;
415*8a8c2d74SCharles.Forsyth 
416*8a8c2d74SCharles.Forsyth 	for(nargs = 0; nargs < maxargs; nargs++){
417*8a8c2d74SCharles.Forsyth 		while(*s != '\0' && strchr("\t\n ", *s) != nil)
418*8a8c2d74SCharles.Forsyth 			s++;
419*8a8c2d74SCharles.Forsyth 		if(*s == '\0')
420*8a8c2d74SCharles.Forsyth 			break;
421*8a8c2d74SCharles.Forsyth 		args[nargs] = s;
422*8a8c2d74SCharles.Forsyth 		while(*s != '\0' && strchr("\t\n ", *s) == nil)
423*8a8c2d74SCharles.Forsyth 			s++;
424*8a8c2d74SCharles.Forsyth 		if(*s != '\0')
425*8a8c2d74SCharles.Forsyth 			*s++ = 0;
426*8a8c2d74SCharles.Forsyth 	}
427*8a8c2d74SCharles.Forsyth 	return nargs;
428*8a8c2d74SCharles.Forsyth }
429*8a8c2d74SCharles.Forsyth 
430*8a8c2d74SCharles.Forsyth int
aoepnp0(void)431*8a8c2d74SCharles.Forsyth aoepnp0(void)
432*8a8c2d74SCharles.Forsyth {
433*8a8c2d74SCharles.Forsyth 	int i;
434*8a8c2d74SCharles.Forsyth 	char *p, c;
435*8a8c2d74SCharles.Forsyth 
436*8a8c2d74SCharles.Forsyth 	if((p = getconf("aoeif")) == nil)
437*8a8c2d74SCharles.Forsyth 		return 0;
438*8a8c2d74SCharles.Forsyth print("aoeif = %s\n", p);
439*8a8c2d74SCharles.Forsyth 	nprobe = tokenize(p, probef, nelem(probef));
440*8a8c2d74SCharles.Forsyth 	for(i = 0; i < nprobe; i++){
441*8a8c2d74SCharles.Forsyth 		if(strncmp(probef[i], "ether", 5) != 0)
442*8a8c2d74SCharles.Forsyth 			continue;
443*8a8c2d74SCharles.Forsyth 		c = probef[i][5];
444*8a8c2d74SCharles.Forsyth 		if(c > '9' || c < '0')
445*8a8c2d74SCharles.Forsyth 			continue;
446*8a8c2d74SCharles.Forsyth 		aoeether[c - '0'] = 1;
447*8a8c2d74SCharles.Forsyth 	}
448*8a8c2d74SCharles.Forsyth 
449*8a8c2d74SCharles.Forsyth 	if((p = getconf("aoedev")) == nil)
450*8a8c2d74SCharles.Forsyth 		return 0;
451*8a8c2d74SCharles.Forsyth 	return nprobe = tokenize(p, probef, nelem(probef));
452*8a8c2d74SCharles.Forsyth }
453*8a8c2d74SCharles.Forsyth 
454*8a8c2d74SCharles.Forsyth int
probeshelf(char * s,int * shelf,int * slot)455*8a8c2d74SCharles.Forsyth probeshelf(char *s, int *shelf, int *slot)
456*8a8c2d74SCharles.Forsyth {
457*8a8c2d74SCharles.Forsyth 	int a, b;
458*8a8c2d74SCharles.Forsyth 	char *r;
459*8a8c2d74SCharles.Forsyth 
460*8a8c2d74SCharles.Forsyth 	for(r = s + strlen(s) - 1; r > s; r--)
461*8a8c2d74SCharles.Forsyth 		if((*r < '0' || *r > '9') && *r != '.'){
462*8a8c2d74SCharles.Forsyth 			r++;
463*8a8c2d74SCharles.Forsyth 			break;
464*8a8c2d74SCharles.Forsyth 		}
465*8a8c2d74SCharles.Forsyth 	a = strtoul(r, &r, 10);
466*8a8c2d74SCharles.Forsyth 	if(*r++ != '.')
467*8a8c2d74SCharles.Forsyth 		return -1;
468*8a8c2d74SCharles.Forsyth 	b = strtoul(r, 0, 10);
469*8a8c2d74SCharles.Forsyth 
470*8a8c2d74SCharles.Forsyth 	*shelf = a;
471*8a8c2d74SCharles.Forsyth 	*slot = b;
472*8a8c2d74SCharles.Forsyth print("  shelf=%d.%d\n", a, b);
473*8a8c2d74SCharles.Forsyth 	return 0;
474*8a8c2d74SCharles.Forsyth }
475*8a8c2d74SCharles.Forsyth 
476*8a8c2d74SCharles.Forsyth Ctlr*
pnpprobe(SDev * sd)477*8a8c2d74SCharles.Forsyth pnpprobe(SDev *sd)
478*8a8c2d74SCharles.Forsyth {
479*8a8c2d74SCharles.Forsyth 	int shelf, slot;
480*8a8c2d74SCharles.Forsyth 	char *p;
481*8a8c2d74SCharles.Forsyth 	static int i;
482*8a8c2d74SCharles.Forsyth 
483*8a8c2d74SCharles.Forsyth 	if(i >= nprobe)
484*8a8c2d74SCharles.Forsyth 		return 0;
485*8a8c2d74SCharles.Forsyth 	p = probef[i++];
486*8a8c2d74SCharles.Forsyth 	if(strlen(p) < 2)
487*8a8c2d74SCharles.Forsyth 		return 0;
488*8a8c2d74SCharles.Forsyth 	if(p[1] == '!'){
489*8a8c2d74SCharles.Forsyth 		sd->idno = p[0];
490*8a8c2d74SCharles.Forsyth 		p += 2;
491*8a8c2d74SCharles.Forsyth 	}
492*8a8c2d74SCharles.Forsyth 	if(probeshelf(p, &shelf, &slot) == -1 ||
493*8a8c2d74SCharles.Forsyth 	    aoeprobe(shelf, slot, sd) == -1 ||
494*8a8c2d74SCharles.Forsyth 	    identify(sd->ctlr) == -1)
495*8a8c2d74SCharles.Forsyth 		return 0;
496*8a8c2d74SCharles.Forsyth 	return sd->ctlr;
497*8a8c2d74SCharles.Forsyth }
498*8a8c2d74SCharles.Forsyth 
499*8a8c2d74SCharles.Forsyth /*
500*8a8c2d74SCharles.Forsyth  * we may need to pretend we found something
501*8a8c2d74SCharles.Forsyth  */
502*8a8c2d74SCharles.Forsyth 
503*8a8c2d74SCharles.Forsyth SDev*
aoepnp(void)504*8a8c2d74SCharles.Forsyth aoepnp(void)
505*8a8c2d74SCharles.Forsyth {
506*8a8c2d74SCharles.Forsyth 	int n, i, id;
507*8a8c2d74SCharles.Forsyth 	char *p;
508*8a8c2d74SCharles.Forsyth 	SDev *h, *t, *s;
509*8a8c2d74SCharles.Forsyth 
510*8a8c2d74SCharles.Forsyth 	p = getconf("aoeif");
511*8a8c2d74SCharles.Forsyth 	if (p)
512*8a8c2d74SCharles.Forsyth 		print("aoepnp: aoeif=%s\n", p);
513*8a8c2d74SCharles.Forsyth 
514*8a8c2d74SCharles.Forsyth 	if((n = aoepnp0()) == 0)
515*8a8c2d74SCharles.Forsyth 		n = 2;
516*8a8c2d74SCharles.Forsyth 	t = h = 0;
517*8a8c2d74SCharles.Forsyth 	for(i = 0; i < n; i++){
518*8a8c2d74SCharles.Forsyth 		id = 'e';
519*8a8c2d74SCharles.Forsyth 		s = malloc(sizeof *s);
520*8a8c2d74SCharles.Forsyth 		if(s == 0)
521*8a8c2d74SCharles.Forsyth 			break;
522*8a8c2d74SCharles.Forsyth 		s->ctlr = 0;
523*8a8c2d74SCharles.Forsyth 		s->idno = id;
524*8a8c2d74SCharles.Forsyth 		s->ifc = &sdaoeifc;
525*8a8c2d74SCharles.Forsyth 		s->nunit = 1;
526*8a8c2d74SCharles.Forsyth 		pnpprobe(s);
527*8a8c2d74SCharles.Forsyth 
528*8a8c2d74SCharles.Forsyth 		if(h)
529*8a8c2d74SCharles.Forsyth 			t->next = s;
530*8a8c2d74SCharles.Forsyth 		else
531*8a8c2d74SCharles.Forsyth 			h = s;
532*8a8c2d74SCharles.Forsyth 		t = s;
533*8a8c2d74SCharles.Forsyth 	}
534*8a8c2d74SCharles.Forsyth 	return h;
535*8a8c2d74SCharles.Forsyth }
536*8a8c2d74SCharles.Forsyth 
537*8a8c2d74SCharles.Forsyth static int
aoeverify(SDunit * u)538*8a8c2d74SCharles.Forsyth aoeverify(SDunit *u)
539*8a8c2d74SCharles.Forsyth {
540*8a8c2d74SCharles.Forsyth 	Ctlr *c;
541*8a8c2d74SCharles.Forsyth 	SDev *s;
542*8a8c2d74SCharles.Forsyth 
543*8a8c2d74SCharles.Forsyth 	s = u->dev;
544*8a8c2d74SCharles.Forsyth 	c = s->ctlr;
545*8a8c2d74SCharles.Forsyth 	if(c == 0){
546*8a8c2d74SCharles.Forsyth 		aoepnp0();
547*8a8c2d74SCharles.Forsyth 		if((s->ctlr = c = pnpprobe(s)) == nil)
548*8a8c2d74SCharles.Forsyth 			return 0;
549*8a8c2d74SCharles.Forsyth 	}
550*8a8c2d74SCharles.Forsyth 	c->mediachange = 1;
551*8a8c2d74SCharles.Forsyth 	return 1;
552*8a8c2d74SCharles.Forsyth }
553*8a8c2d74SCharles.Forsyth 
554*8a8c2d74SCharles.Forsyth static int
aoeonline(SDunit * u)555*8a8c2d74SCharles.Forsyth aoeonline(SDunit *u)
556*8a8c2d74SCharles.Forsyth {
557*8a8c2d74SCharles.Forsyth 	int r;
558*8a8c2d74SCharles.Forsyth 	Ctlr *c;
559*8a8c2d74SCharles.Forsyth 
560*8a8c2d74SCharles.Forsyth 	c = u->dev->ctlr;
561*8a8c2d74SCharles.Forsyth 	if(c->mediachange){
562*8a8c2d74SCharles.Forsyth 		r = 2;
563*8a8c2d74SCharles.Forsyth 		c->mediachange = 0;
564*8a8c2d74SCharles.Forsyth 		u->sectors = c->sectors;
565*8a8c2d74SCharles.Forsyth 		u->secsize = 512;
566*8a8c2d74SCharles.Forsyth 	} else
567*8a8c2d74SCharles.Forsyth 		r = 1;
568*8a8c2d74SCharles.Forsyth 	return r;
569*8a8c2d74SCharles.Forsyth }
570*8a8c2d74SCharles.Forsyth 
571*8a8c2d74SCharles.Forsyth static int
rio(Ctlr * c,Aoeata * a,int n,int scnt)572*8a8c2d74SCharles.Forsyth rio(Ctlr *c, Aoeata *a, int n, int scnt)
573*8a8c2d74SCharles.Forsyth {
574*8a8c2d74SCharles.Forsyth 	int i, tag, cmd;
575*8a8c2d74SCharles.Forsyth 
576*8a8c2d74SCharles.Forsyth 	for(i = 0; i < 5; i++){
577*8a8c2d74SCharles.Forsyth 		tag = hset(c, a, ACata);
578*8a8c2d74SCharles.Forsyth 		cmd = a->cmdstat;
579*8a8c2d74SCharles.Forsyth 		ethertxpkt(c->ctlrno, (Etherpkt*)a, n, 0);
580*8a8c2d74SCharles.Forsyth 		memset(a, 0, sizeof *a);
581*8a8c2d74SCharles.Forsyth again:
582*8a8c2d74SCharles.Forsyth 		n = etherrxpkt(c->ctlrno, (Etherpkt*)a, 125);
583*8a8c2d74SCharles.Forsyth 		if(n == 0)
584*8a8c2d74SCharles.Forsyth 			continue;
585*8a8c2d74SCharles.Forsyth 		if(nhgets(a->type) != Aoetype || nhgetl(a->tag) != tag ||
586*8a8c2d74SCharles.Forsyth 		    nhgets(a->major) != c->major || a->minor != c->minor)
587*8a8c2d74SCharles.Forsyth 			goto again;
588*8a8c2d74SCharles.Forsyth 		if(a->cmdstat & 0xa9){
589*8a8c2d74SCharles.Forsyth 			print("aoe: ata rio error: %2ux\n", a->cmdstat);
590*8a8c2d74SCharles.Forsyth 			return 0;
591*8a8c2d74SCharles.Forsyth 		}
592*8a8c2d74SCharles.Forsyth 		switch(cmd){
593*8a8c2d74SCharles.Forsyth 		case Crd:
594*8a8c2d74SCharles.Forsyth 		case Crdext:
595*8a8c2d74SCharles.Forsyth 			if(n - sizeof *a < scnt * 512){
596*8a8c2d74SCharles.Forsyth 				print("aoe: runt expect %d got %d\n",
597*8a8c2d74SCharles.Forsyth 					scnt*512 + sizeof *a, n);
598*8a8c2d74SCharles.Forsyth 				return 0;
599*8a8c2d74SCharles.Forsyth 			}
600*8a8c2d74SCharles.Forsyth 			return n - sizeof *a;
601*8a8c2d74SCharles.Forsyth 		case Cwr:
602*8a8c2d74SCharles.Forsyth 		case Cwrext:
603*8a8c2d74SCharles.Forsyth 			return scnt * 512;
604*8a8c2d74SCharles.Forsyth 		default:
605*8a8c2d74SCharles.Forsyth print("unknown cmd %ux\n", cmd);
606*8a8c2d74SCharles.Forsyth 			break;
607*8a8c2d74SCharles.Forsyth 		}
608*8a8c2d74SCharles.Forsyth 	}
609*8a8c2d74SCharles.Forsyth 	print("aoe: rio timeout\n");
610*8a8c2d74SCharles.Forsyth 	return 0;
611*8a8c2d74SCharles.Forsyth }
612*8a8c2d74SCharles.Forsyth 
613*8a8c2d74SCharles.Forsyth static void
putlba(Aoeata * a,vlong lba)614*8a8c2d74SCharles.Forsyth putlba(Aoeata *a, vlong lba)
615*8a8c2d74SCharles.Forsyth {
616*8a8c2d74SCharles.Forsyth 	uchar *c;
617*8a8c2d74SCharles.Forsyth 
618*8a8c2d74SCharles.Forsyth 	c = a->lba;
619*8a8c2d74SCharles.Forsyth 	c[0] = lba;
620*8a8c2d74SCharles.Forsyth 	c[1] = lba >> 8;
621*8a8c2d74SCharles.Forsyth 	c[2] = lba >> 16;
622*8a8c2d74SCharles.Forsyth 	c[3] = lba >> 24;
623*8a8c2d74SCharles.Forsyth 	c[4] = lba >> 32;
624*8a8c2d74SCharles.Forsyth 	c[5] = lba >> 40;
625*8a8c2d74SCharles.Forsyth }
626*8a8c2d74SCharles.Forsyth 
627*8a8c2d74SCharles.Forsyth /*
628*8a8c2d74SCharles.Forsyth  * you'll need to loop if you want to read more than 2 sectors.  for now
629*8a8c2d74SCharles.Forsyth  * i'm cheeting and not bothering with a loop.
630*8a8c2d74SCharles.Forsyth  */
631*8a8c2d74SCharles.Forsyth static uchar pktbuf[1024 + sizeof(Aoeata)];
632*8a8c2d74SCharles.Forsyth 
633*8a8c2d74SCharles.Forsyth static int
aoebuild(Ctlr * c,uchar * cmd,char * data,vlong lba,int scnt)634*8a8c2d74SCharles.Forsyth aoebuild(Ctlr *c, uchar *cmd, char *data, vlong lba, int scnt)
635*8a8c2d74SCharles.Forsyth {
636*8a8c2d74SCharles.Forsyth 	int n;
637*8a8c2d74SCharles.Forsyth 	Aoeata *a;
638*8a8c2d74SCharles.Forsyth 
639*8a8c2d74SCharles.Forsyth 	memset(pktbuf, 0, sizeof pktbuf);
640*8a8c2d74SCharles.Forsyth 	a = (Aoeata*)pktbuf;
641*8a8c2d74SCharles.Forsyth 	hset(c, a, ACata);
642*8a8c2d74SCharles.Forsyth 	putlba(a, lba);
643*8a8c2d74SCharles.Forsyth 
644*8a8c2d74SCharles.Forsyth 	a->cmdstat = 0x20;
645*8a8c2d74SCharles.Forsyth 	if(c->flag & Dllba){
646*8a8c2d74SCharles.Forsyth 		a->aflag |= AAFext;
647*8a8c2d74SCharles.Forsyth 		a->cmdstat |= 4;
648*8a8c2d74SCharles.Forsyth 	}else{
649*8a8c2d74SCharles.Forsyth 		a->lba[3] &= 0xf;
650*8a8c2d74SCharles.Forsyth 		a->lba[3] |= 0xe0;		/* LBA bit+obsolete 0xa0 */
651*8a8c2d74SCharles.Forsyth 	}
652*8a8c2d74SCharles.Forsyth 
653*8a8c2d74SCharles.Forsyth 	n = scnt;
654*8a8c2d74SCharles.Forsyth 	if(n > 2)
655*8a8c2d74SCharles.Forsyth 		n = 2;
656*8a8c2d74SCharles.Forsyth 	a->scnt = n;
657*8a8c2d74SCharles.Forsyth 
658*8a8c2d74SCharles.Forsyth 	switch(*cmd){
659*8a8c2d74SCharles.Forsyth 	case 0x2a:
660*8a8c2d74SCharles.Forsyth 		a->aflag |= AAFwrite;
661*8a8c2d74SCharles.Forsyth 		a->cmdstat |= 10;
662*8a8c2d74SCharles.Forsyth 		memmove(a+1, data, n*512);
663*8a8c2d74SCharles.Forsyth 		n = sizeof *a + n*512;
664*8a8c2d74SCharles.Forsyth 		break;
665*8a8c2d74SCharles.Forsyth 	case 0x28:
666*8a8c2d74SCharles.Forsyth 		n = sizeof *a;
667*8a8c2d74SCharles.Forsyth 		break;
668*8a8c2d74SCharles.Forsyth 	default:
669*8a8c2d74SCharles.Forsyth 		print("aoe: bad cmd 0x%.2ux\n", cmd[0]);
670*8a8c2d74SCharles.Forsyth 		return -1;
671*8a8c2d74SCharles.Forsyth 	}
672*8a8c2d74SCharles.Forsyth 	return n;
673*8a8c2d74SCharles.Forsyth }
674*8a8c2d74SCharles.Forsyth 
675*8a8c2d74SCharles.Forsyth static int
aoerio(SDreq * r)676*8a8c2d74SCharles.Forsyth aoerio(SDreq *r)
677*8a8c2d74SCharles.Forsyth {
678*8a8c2d74SCharles.Forsyth 	int size, nsec, n;
679*8a8c2d74SCharles.Forsyth 	vlong lba;
680*8a8c2d74SCharles.Forsyth 	char *data;
681*8a8c2d74SCharles.Forsyth 	uchar *cmd;
682*8a8c2d74SCharles.Forsyth 	Aoeata *a;
683*8a8c2d74SCharles.Forsyth 	Ctlr *c;
684*8a8c2d74SCharles.Forsyth 	SDunit *unit;
685*8a8c2d74SCharles.Forsyth 
686*8a8c2d74SCharles.Forsyth 	unit = r->unit;
687*8a8c2d74SCharles.Forsyth 	c = unit->dev->ctlr;
688*8a8c2d74SCharles.Forsyth 	if(r->data == nil)
689*8a8c2d74SCharles.Forsyth 		return SDok;
690*8a8c2d74SCharles.Forsyth 	cmd = r->cmd;
691*8a8c2d74SCharles.Forsyth 
692*8a8c2d74SCharles.Forsyth 	lba = cmd[2]<<24 | cmd[3]<<16 | cmd[4]<<8 | cmd[5];	/* sic. */
693*8a8c2d74SCharles.Forsyth 	nsec = cmd[7]<<8 | cmd[8];
694*8a8c2d74SCharles.Forsyth 	a = (Aoeata*)pktbuf;
695*8a8c2d74SCharles.Forsyth 	data = r->data;
696*8a8c2d74SCharles.Forsyth 	r->rlen = 0;
697*8a8c2d74SCharles.Forsyth 
698*8a8c2d74SCharles.Forsyth 	for(; nsec > 0; nsec -= n){
699*8a8c2d74SCharles.Forsyth //		print("aoebuild(%2x, %p, %lld, %d)\n", *cmd, data, lba, nsec);
700*8a8c2d74SCharles.Forsyth 		size = aoebuild(c, cmd, data, lba, nsec);
701*8a8c2d74SCharles.Forsyth 		if(size < 0){
702*8a8c2d74SCharles.Forsyth 			r->status = SDcheck;
703*8a8c2d74SCharles.Forsyth 			return SDcheck;
704*8a8c2d74SCharles.Forsyth 		}
705*8a8c2d74SCharles.Forsyth 		n = a->scnt;
706*8a8c2d74SCharles.Forsyth 		r->rlen += rio(c, a, size, n);
707*8a8c2d74SCharles.Forsyth 		if(*cmd == 0x28)
708*8a8c2d74SCharles.Forsyth 			memmove(r->data, a + 1, n * 512);
709*8a8c2d74SCharles.Forsyth 		data += n * 512;
710*8a8c2d74SCharles.Forsyth 		lba += n;
711*8a8c2d74SCharles.Forsyth 	}
712*8a8c2d74SCharles.Forsyth 
713*8a8c2d74SCharles.Forsyth 	r->status = SDok;
714*8a8c2d74SCharles.Forsyth 	return SDok;
715*8a8c2d74SCharles.Forsyth }
716*8a8c2d74SCharles.Forsyth 
717*8a8c2d74SCharles.Forsyth SDifc sdaoeifc = {
718*8a8c2d74SCharles.Forsyth 	"aoe",
719*8a8c2d74SCharles.Forsyth 
720*8a8c2d74SCharles.Forsyth 	aoepnp,
721*8a8c2d74SCharles.Forsyth 	nil,		/* legacy */
722*8a8c2d74SCharles.Forsyth 	nil,		/* id */
723*8a8c2d74SCharles.Forsyth 	nil,		/* enable */
724*8a8c2d74SCharles.Forsyth 	nil,		/* disable */
725*8a8c2d74SCharles.Forsyth 
726*8a8c2d74SCharles.Forsyth 	aoeverify,
727*8a8c2d74SCharles.Forsyth 	aoeonline,
728*8a8c2d74SCharles.Forsyth 	aoerio,
729*8a8c2d74SCharles.Forsyth 	nil,
730*8a8c2d74SCharles.Forsyth 	nil,
731*8a8c2d74SCharles.Forsyth 
732*8a8c2d74SCharles.Forsyth 	scsibio,
733*8a8c2d74SCharles.Forsyth };
734