]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/port/sdaoe.c
bind devshr to /shr
[plan9front.git] / sys / src / 9 / port / sdaoe.c
1 /*
2  * aoe sd driver, copyright © 2007-9 coraid
3  */
4
5 #include "u.h"
6 #include "../port/lib.h"
7 #include "mem.h"
8 #include "dat.h"
9 #include "fns.h"
10 #include "io.h"
11 #include "../port/error.h"
12 #include "../port/sd.h"
13 #include "../port/netif.h"
14 #include "../port/aoe.h"
15 #include <fis.h>
16
17 extern  char    Echange[];
18 extern  char    Enotup[];
19
20 #define uprint(...)     snprint(up->genbuf, sizeof up->genbuf, __VA_ARGS__);
21
22 enum {
23         Maxpath         = 128,
24
25         Probeintvl      = 100,          /* ms. between probes */
26         Probemax        = 10*1000,      /* max ms. to wait */
27 };
28
29 typedef struct Ctlr Ctlr;
30 struct Ctlr {
31         QLock;
32
33         Ctlr    *next;
34         SDunit  *unit;
35
36         char    path[Maxpath];
37         Chan    *c;
38
39         ulong   vers;
40         uchar   drivechange;
41         Sfis;
42
43         uvlong  sectors;
44         char    serial[20+1];
45         char    firmware[8+1];
46         char    model[40+1];
47         char    ident[0x100];
48 };
49
50 static  Lock    ctlrlock;
51 static  Ctlr    *head;
52 static  Ctlr    *tail;
53
54 SDifc sdaoeifc;
55
56 static int
57 identify(Ctlr *c, ushort *id)
58 {
59         uchar oserial[21];
60         vlong osectors, s;
61
62         osectors = c->sectors;
63         memmove(oserial, c->serial, sizeof c->serial);
64         s = idfeat(c, id);
65         if(s == -1){
66                 uprint("%s: identify fails", c->unit->name);
67                 print("%s\n", up->genbuf);
68                 error(up->genbuf);
69         }
70         idmove(c->serial, id+10, 20);
71         idmove(c->firmware, id+23, 8);
72         idmove(c->model, id+27, 40);
73
74         if((osectors == 0 || osectors != s) &&
75             memcmp(oserial, c->serial, sizeof oserial) != 0){
76                 c->sectors = s;
77                 c->drivechange = 1;
78                 c->vers++;
79         }
80         return 0;
81 }
82
83 static void
84 aoectl(Ctlr *d, char *s)
85 {
86         Chan *c;
87
88         c = nil;
89         if(waserror()){
90                 if(c)
91                         cclose(c);
92                 print("sdaoectl: %s\n", up->errstr);
93                 nexterror();
94         }
95
96         uprint("%s/ctl", d->path);
97         c = namec(up->genbuf, Aopen, OWRITE, 0);
98         devtab[c->type]->write(c, s, strlen(s), 0);
99
100         poperror();
101         cclose(c);
102 }
103
104 /* must call with d qlocked */
105 static int
106 aoeidentify(Ctlr *d, SDunit *u)
107 {
108         Chan *c;
109
110         c = nil;
111         if(waserror()){
112                 if(c)
113                         cclose(c);
114                 iprint("aoeidentify: %s\n", up->errstr);
115                 nexterror();
116         }
117
118         uprint("%s/ident", d->path);
119         c = namec(up->genbuf, Aopen, OREAD, 0);
120         devtab[c->type]->read(c, d->ident, sizeof d->ident, 0);
121
122         poperror();
123         cclose(c);
124
125         d->feat = 0;
126         identify(d, (ushort*)d->ident);
127
128         memset(u->inquiry, 0, sizeof u->inquiry);
129         u->inquiry[2] = 2;
130         u->inquiry[3] = 2;
131         u->inquiry[4] = sizeof u->inquiry - 4;
132         memmove(u->inquiry+8, d->model, 40);
133
134         return 0;
135 }
136
137 static Ctlr*
138 ctlrlookup(char *path)
139 {
140         Ctlr *c;
141
142         lock(&ctlrlock);
143         for(c = head; c; c = c->next)
144                 if(strcmp(c->path, path) == 0)
145                         break;
146         unlock(&ctlrlock);
147         return c;
148 }
149
150 static Ctlr*
151 newctlr(char *path)
152 {
153         Ctlr *c;
154
155         if(ctlrlookup(path))
156                 error(Eexist);
157
158         if((c = malloc(sizeof *c)) == nil)
159                 return 0;
160         kstrcpy(c->path, path, sizeof c->path);
161         lock(&ctlrlock);
162         if(head != nil)
163                 tail->next = c;
164         else
165                 head = c;
166         tail = c;
167         unlock(&ctlrlock);
168         return c;
169 }
170
171 static void
172 delctlr(Ctlr *c)
173 {
174         Ctlr *x, *prev;
175
176         lock(&ctlrlock);
177
178         for(prev = 0, x = head; x; prev = x, x = c->next)
179                 if(strcmp(c->path, x->path) == 0)
180                         break;
181         if(x == 0){
182                 unlock(&ctlrlock);
183                 error(Enonexist);
184         }
185
186         if(prev)
187                 prev->next = x->next;
188         else
189                 head = x->next;
190         if(x->next == nil)
191                 tail = prev;
192         unlock(&ctlrlock);
193
194         if(x->c)
195                 cclose(x->c);
196         free(x);
197 }
198
199 static SDev*
200 aoeprobe(char *path, SDev *s)
201 {
202         int n, i;
203         char *p;
204         Chan *c;
205         Ctlr *ctlr;
206
207         if((p = strrchr(path, '/')) == 0)
208                 error(Ebadarg);
209         *p = 0;
210         uprint("%s/ctl", path);
211         *p = '/';
212
213         c = namec(up->genbuf, Aopen, OWRITE, 0);
214         if(waserror()) {
215                 cclose(c);
216                 nexterror();
217         }
218         n = uprint("discover %s", p+1);
219         devtab[c->type]->write(c, up->genbuf, n, 0);
220         poperror();
221         cclose(c);
222
223         for(i = 0;; i += Probeintvl){
224                 if(i > Probemax || waserror())
225                         error(Etimedout);
226                 tsleep(&up->sleep, return0, 0, Probeintvl);
227                 poperror();
228
229                 uprint("%s/ident", path);
230                 if(waserror())
231                         continue;
232                 c = namec(up->genbuf, Aopen, OREAD, 0);
233                 poperror();
234                 cclose(c);
235
236                 ctlr = newctlr(path);
237                 break;
238         }
239
240         if(s == nil && (s = malloc(sizeof *s)) == nil)
241                 return nil;
242         s->ctlr = ctlr;
243         s->ifc = &sdaoeifc;
244         s->nunit = 1;
245         return s;
246 }
247
248 static char     *probef[32];
249 static char     *probebuf;
250 static int      nprobe;
251
252 static int
253 pnpprobeid(char *s)
254 {
255         int id;
256
257         if(strlen(s) < 2)
258                 return 0;
259         id = 'e';
260         if(s[1] == '!')
261                 id = s[0];
262         return id;
263 }
264
265 static SDev*
266 aoepnp(void)
267 {
268         int i, id;
269         char *p;
270         SDev *h, *t, *s;
271
272         if((p = getconf("aoedev")) == 0)
273                 return 0;
274         kstrdup(&probebuf, p);
275         nprobe = tokenize(probebuf, probef, nelem(probef));
276         h = t = 0;
277         for(i = 0; i < nprobe; i++){
278                 id = pnpprobeid(probef[i]);
279                 if(id == 0)
280                         continue;
281                 s = malloc(sizeof *s);
282                 if(s == nil)
283                         break;
284                 s->ctlr = 0;
285                 s->idno = id;
286                 s->ifc = &sdaoeifc;
287                 s->nunit = 1;
288
289                 if(h)
290                         t->next = s;
291                 else
292                         h = s;
293                 t = s;
294         }
295         return h;
296 }
297
298 static Ctlr*
299 pnpprobe(SDev *sd)
300 {
301         int j;
302         char *p;
303         static int i;
304
305         if(i > nprobe)
306                 return 0;
307         p = probef[i++];
308         if(strlen(p) < 2)
309                 return 0;
310         if(p[1] == '!')
311                 p += 2;
312
313         for(j = 0;; j += Probeintvl){
314                 if(j > Probemax){
315                         print("#æ: pnpprobe: %s: %s\n", probef[i-1], up->errstr);
316                         return 0;
317                 }
318                 if(waserror()){
319                         tsleep(&up->sleep, return0, 0, Probeintvl);
320                         continue;
321                 }
322                 sd = aoeprobe(p, sd);
323                 poperror();
324                 break;
325         }
326         print("#æ: pnpprobe establishes %s in %dms\n", probef[i-1], j);
327         aoectl(sd->ctlr, "nofail on");
328         return sd->ctlr;
329 }
330
331
332 static int
333 aoeverify(SDunit *u)
334 {
335         SDev *s;
336         Ctlr *c;
337
338         s = u->dev;
339         c = s->ctlr;
340         if(c == nil && (s->ctlr = c = pnpprobe(s)) == nil)
341                 return 0;
342         c->drivechange = 1;
343         return 1;
344 }
345
346 static int
347 aoeconnect(SDunit *u, Ctlr *c)
348 {
349         qlock(c);
350         if(waserror()){
351                 qunlock(c);
352                 return -1;
353         }
354
355         aoeidentify(u->dev->ctlr, u);
356         if(c->c)
357                 cclose(c->c);
358         c->c = 0;
359         uprint("%s/data", c->path);
360         c->c = namec(up->genbuf, Aopen, ORDWR, 0);
361         qunlock(c);
362         poperror();
363
364         return 0;
365 }
366
367 static int
368 aoeonline(SDunit *u)
369 {
370         Ctlr *c;
371         int r;
372
373         c = u->dev->ctlr;
374         r = 0;
375
376         if((c->feat&Datapi) && c->drivechange){
377                 if(aoeconnect(u, c) == 0 && (r = scsionline(u)) > 0)
378                         c->drivechange = 0;
379                 return r;
380         }
381
382         if(c->drivechange){
383                 if(aoeconnect(u, c) == -1)
384                         return 0;
385                 r = 2;
386                 c->drivechange = 0;
387                 u->sectors = c->sectors;
388                 u->secsize = Aoesectsz;
389         } else
390                 r = 1;
391
392         return r;
393 }
394
395 static long
396 aoebio(SDunit *u, int, int write, void *a, long count, uvlong lba)
397 {
398         uchar *data;
399         int n;
400         long (*rio)(Chan*, void*, long, vlong);
401         Ctlr *c;
402
403         c = u->dev->ctlr;
404 //      if(c->feat & Datapi)
405 //              return scsibio(u, lun, write, a, count, lba);
406         data = a;
407         if(write)
408                 rio = devtab[c->c->type]->write;
409         else
410                 rio = devtab[c->c->type]->read;
411
412         if(waserror()){
413                 if(strcmp(up->errstr, Echange) == 0 ||
414                     strcmp(up->errstr, Enotup) == 0)
415                         u->sectors = 0;
416                 nexterror();
417         }
418         n = rio(c->c, data, Aoesectsz * count, Aoesectsz * lba);
419         poperror();
420         return n;
421 }
422
423 static int
424 flushcache(Ctlr *)
425 {
426         return -1;
427 }
428
429 static int
430 aoerio(SDreq *r)
431 {
432         int i, count, rw;
433         uvlong lba;
434         Ctlr *c;
435         SDunit *u;
436
437         u = r->unit;
438         c = u->dev->ctlr;
439 //      if(c->feat & Datapi)
440 //              return aoeriopkt(r, d);
441
442         if(r->cmd[0] == 0x35 || r->cmd[0] == 0x91){
443                 qlock(c);
444                 i = flushcache(c);
445                 qunlock(c);
446                 if(i == 0)
447                         return sdsetsense(r, SDok, 0, 0, 0);
448                 return sdsetsense(r, SDcheck, 3, 0xc, 2);
449         }
450
451         if((i = sdfakescsi(r)) != SDnostatus){
452                 r->status = i;
453                 return i;
454         }
455         if((i = sdfakescsirw(r, &lba, &count, &rw)) != SDnostatus)
456                 return i;
457         r->rlen = aoebio(u, r->lun, rw == SDwrite, r->data, count, lba);
458         return r->status = SDok;
459 }
460
461 static int
462 aoerctl(SDunit *u, char *p, int l)
463 {
464         Ctlr *c;
465         char *e, *op;
466
467         if((c = u->dev->ctlr) == nil)
468                 return 0;
469         e = p+l;
470         op = p;
471
472         p = seprint(p, e, "model\t%s\n", c->model);
473         p = seprint(p, e, "serial\t%s\n", c->serial);
474         p = seprint(p, e, "firm %s\n", c->firmware);
475         p = seprint(p, e, "flag ");
476         p = pflag(p, e, c);
477         p = seprint(p, e, "geometry %llud %d\n", c->sectors, Aoesectsz);
478         return p-op;
479 }
480
481 static int
482 aoewctl(SDunit *, Cmdbuf *cmd)
483 {
484         cmderror(cmd, Ebadarg);
485         return 0;
486 }
487
488 static SDev*
489 aoeprobew(DevConf *c)
490 {
491         char *p;
492
493         p = strchr(c->type, '/');
494         if(p == nil || strlen(p) > Maxpath - 11)
495                 error(Ebadarg);
496         if(p[1] == '#')
497                 p++;                    /* hack */
498         if(ctlrlookup(p))
499                 error(Einuse);
500         return aoeprobe(p, 0);
501 }
502
503 static void
504 aoeclear(SDev *s)
505 {
506         delctlr((Ctlr *)s->ctlr);
507 }
508
509 static char*
510 aoertopctl(SDev *s, char *p, char *e)
511 {
512         Ctlr *c;
513
514         c = s->ctlr;
515         return seprint(p, e, "%s aoe %s\n", s->name, c? c->path: "");
516 }
517
518 static int
519 aoewtopctl(SDev *, Cmdbuf *cmd)
520 {
521         switch(cmd->nf){
522         default:
523                 cmderror(cmd, Ebadarg);
524         }
525         return 0;
526 }
527
528 SDifc sdaoeifc = {
529         "aoe",
530
531         aoepnp,
532         nil,            /* legacy */
533         nil,            /* enable */
534         nil,            /* disable */
535
536         aoeverify,
537         aoeonline,
538         aoerio,
539         aoerctl,
540         aoewctl,
541
542         aoebio,
543         aoeprobew,      /* probe */
544         aoeclear,       /* clear */
545         aoertopctl,
546         aoewtopctl,
547 };