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[];
23 typedef struct Ctlr Ctlr;
46 /* must call with c qlocked */
48 identify(Ctlr *c, SDunit *u)
52 uchar buf[sizeof(Dir) + 100];
56 iprint("sdloop: identify: %s\n", up->errstr);
59 osectors = c->sectors;
60 n = devtab[c->c->type]->stat(c->c, buf, sizeof buf);
61 if(convM2D(buf, n, &dir, nil) == 0)
62 error("internal error: stat error in seek");
63 s = dir.length / c->sectsize;
66 memset(u->inquiry, 0, sizeof u->inquiry);
69 u->inquiry[4] = sizeof u->inquiry - 4;
70 memmove(u->inquiry+8, c->path, 40);
72 if(osectors == 0 || osectors != s){
80 ctlrlookup(char *path)
85 for(c = head; c; c = c->next)
86 if(strcmp(c->path, path) == 0)
99 if((c = malloc(sizeof *c)) == nil)
105 c->c = namec(path, Aopen, ORDWR, 0);
107 kstrcpy(c->path, path, sizeof c->path);
125 for(prev = 0, x = head; x; prev = x, x = c->next)
126 if(strcmp(c->path, x->path) == 0)
134 prev->next = x->next;
147 probe(char *path, SDev *s)
154 if(p = strchr(path, '!')){
156 sectsize = strtoul(p + 1, 0, 0);
159 c->sectsize = sectsize? sectsize: Devsectsize;
160 if(s == nil && (s = malloc(sizeof *s)) == nil)
168 static char *probef[32];
191 if((p = getconf("loopdev")) == 0)
193 nprobe = tokenize(p, probef, nelem(probef));
195 for(i = 0; i < nprobe; i++){
196 id = pnpprobeid(probef[i]);
199 s = malloc(sizeof *s);
235 loopverify(SDunit *u)
245 s->ctlr = c = pnpprobe(s);
253 connect(SDunit *u, Ctlr *c)
260 identify(u->dev->ctlr, u);
267 looponline(SDunit *u)
274 if(connect(u, c) == -1)
278 u->sectors = c->sectors;
279 u->secsize = c->sectsize;
286 loopbio(SDunit *u, int, int write, void *a, long count, uvlong lba)
290 long (*rio)(Chan*, void*, long, vlong);
296 rio = devtab[c->c->type]->write;
298 rio = devtab[c->c->type]->read;
301 if(strcmp(up->errstr, Echange) == 0 ||
302 strstr(up->errstr, "device is down") != nil)
306 n = rio(c->c, data, c->sectsize * count, c->sectsize * lba);
320 if(r->cmd[0] == 0x35 || r->cmd[0] == 0x91)
321 return sdsetsense(r, SDok, 0, 0, 0);
323 if((i = sdfakescsi(r)) != SDnostatus)
324 return r->status = i;
325 if((i = sdfakescsirw(r, &lba, &count, &rw)) != SDnostatus)
327 r->rlen = loopbio(u, r->lun, rw == SDwrite, r->data, count, lba);
328 return r->status = SDok;
332 looprctl(SDunit *u, char *p, int l)
337 if((c = u->dev->ctlr) == nil)
342 p = seprint(p, e, "path\t%s\n", c->path);
343 p = seprint(p, e, "geometry %llud %d\n", c->sectors, c->sectsize);
348 loopwctl(SDunit *, Cmdbuf *cmd)
350 cmderror(cmd, Ebadarg);
355 loopprobew(DevConf *c)
359 p = strchr(c->type, '/');
360 if(p == nil || strlen(p) > Maxpath - 1)
371 delctlr((Ctlr *)s->ctlr);
375 looprtopctl(SDev *s, char *p, char *e)
380 return seprint(p, e, "%s loop %s\n", s->name, c? c->path: "");
384 loopwtopctl(SDev *, Cmdbuf *cmd)
388 cmderror(cmd, Ebadarg);
408 loopprobew, /* probe */
409 loopclear, /* clear */