3 * copyright © 2009-10 erik quanstrom
7 #include "../port/lib.h"
12 #include "../port/error.h"
13 #include "../port/sd.h"
14 #include "../port/netif.h"
16 extern char Echange[];
19 #define uprint(...) snprint(up->genbuf, sizeof up->genbuf, __VA_ARGS__);
26 typedef struct Ctlr Ctlr;
49 /* must call with c qlocked */
51 identify(Ctlr *c, SDunit *u)
55 uchar buf[sizeof(Dir) + 100];
59 iprint("sdloop: identify: %s\n", up->errstr);
62 osectors = c->sectors;
63 n = devtab[c->c->type]->stat(c->c, buf, sizeof buf);
64 if(convM2D(buf, n, &dir, nil) == 0)
65 error("internal error: stat error in seek");
66 s = dir.length / c->sectsize;
69 memset(u->inquiry, 0, sizeof u->inquiry);
72 u->inquiry[4] = sizeof u->inquiry - 4;
73 memmove(u->inquiry+8, c->path, 40);
75 if(osectors == 0 || osectors != s){
83 ctlrlookup(char *path)
88 for(c = head; c; c = c->next)
89 if(strcmp(c->path, path) == 0)
102 if((c = malloc(sizeof *c)) == nil)
108 c->c = namec(path, Aopen, ORDWR, 0);
110 kstrcpy(c->path, path, sizeof c->path);
128 for(prev = 0, x = head; x; prev = x, x = c->next)
129 if(strcmp(c->path, x->path) == 0)
137 prev->next = x->next;
150 probe(char *path, SDev *s)
157 if(p = strchr(path, '!')){
159 sectsize = strtoul(p + 1, 0, 0);
162 c->sectsize = sectsize? sectsize: Devsectsize;
163 if(s == nil && (s = malloc(sizeof *s)) == nil)
171 static char *probef[32];
194 if((p = getconf("loopdev")) == 0)
196 nprobe = tokenize(p, probef, nelem(probef));
198 for(i = 0; i < nprobe; i++){
199 id = pnpprobeid(probef[i]);
202 s = malloc(sizeof *s);
238 loopverify(SDunit *u)
248 s->ctlr = c = pnpprobe(s);
256 connect(SDunit *u, Ctlr *c)
263 identify(u->dev->ctlr, u);
270 looponline(SDunit *u)
277 if(connect(u, c) == -1)
281 u->sectors = c->sectors;
282 u->secsize = c->sectsize;
289 loopbio(SDunit *u, int, int write, void *a, long count, uvlong lba)
293 long (*rio)(Chan*, void*, long, vlong);
299 rio = devtab[c->c->type]->write;
301 rio = devtab[c->c->type]->read;
304 if(strcmp(up->errstr, Echange) == 0 ||
305 strcmp(up->errstr, Enotup) == 0)
309 n = rio(c->c, data, c->sectsize * count, c->sectsize * lba);
323 if(r->cmd[0] == 0x35 || r->cmd[0] == 0x91)
324 return sdsetsense(r, SDok, 0, 0, 0);
326 if((i = sdfakescsi(r)) != SDnostatus)
327 return r->status = i;
328 if((i = sdfakescsirw(r, &lba, &count, &rw)) != SDnostatus)
330 r->rlen = loopbio(u, r->lun, rw == SDwrite, r->data, count, lba);
331 return r->status = SDok;
335 looprctl(SDunit *u, char *p, int l)
340 if((c = u->dev->ctlr) == nil)
345 p = seprint(p, e, "path\t%s\n", c->path);
346 p = seprint(p, e, "geometry %llud %d\n", c->sectors, c->sectsize);
351 loopwctl(SDunit *, Cmdbuf *cmd)
353 cmderror(cmd, Ebadarg);
358 loopprobew(DevConf *c)
362 p = strchr(c->type, '/');
363 if(p == nil || strlen(p) > Maxpath - 1)
374 delctlr((Ctlr *)s->ctlr);
378 looprtopctl(SDev *s, char *p, char *e)
383 return seprint(p, e, "%s loop %s\n", s->name, c? c->path: "");
387 loopwtopctl(SDev *, Cmdbuf *cmd)
391 cmderror(cmd, Ebadarg);
411 loopprobew, /* probe */
412 loopclear, /* clear */