]> git.lizzy.rs Git - plan9front.git/commitdiff
usb/disk: ctl write support
authorment <thement@ibawizard.net>
Sat, 7 May 2011 23:36:37 +0000 (01:36 +0200)
committerment <thement@ibawizard.net>
Sat, 7 May 2011 23:36:37 +0000 (01:36 +0200)
sys/src/cmd/usb/disk/disk.c
sys/src/cmd/usb/disk/ums.h

index 884df2d04ee0beaa2abc72dc80af0196ad4e080b..8eea67c2a27ba33407e7133e22e0456ca0604c33 100644 (file)
@@ -38,6 +38,129 @@ static Dirtab dirtab[] =
        [Qdata] "data", 0640,
 };
 
+ulong ctlmode = 0664;
+
+/*
+ * Partition management (adapted from disk/partfs)
+ */
+int
+addpart(Umsc *lun, char *name, vlong start, vlong end)
+{
+       Part *p;
+
+       if(start < 0 || start > end || end > lun->blocks){
+               werrstr("bad partition boundaries");
+               return -1;
+       }
+
+       if (strcmp(name, "ctl") == 0 || strcmp(name, "data") == 0) {
+               werrstr("partition name already in use");
+               return -1;
+       }
+       for (p = lun->part; p < lun->part + Maxparts && p->inuse; p++)
+               if (strcmp(p->name, name) == 0) {
+                       werrstr("partition name already in use");
+                       return -1;
+               }
+       if(p == lun->part + Maxparts){
+               werrstr("no free partition slots");
+               return -1;
+       }
+
+       p->inuse = 1;
+       free(p->name);
+       p->name = estrdup(name);
+       p->offset = start;
+       p->length = end - start;
+       p->mode = ctlmode;
+       p->vers++;
+       return 0;
+}
+
+int
+delpart(Umsc *lun, char *s)
+{
+       Part *p;
+
+       for (p = lun->part; p < lun->part + Maxparts; p++)
+               if(p->inuse && strcmp(p->name, s) == 0)
+                       break;
+       if(p == lun->part + Maxparts){
+               werrstr("partition not found");
+               return -1;
+       }
+
+       p->inuse = 0;
+       free(p->name);
+       p->name = nil;
+       return 0;
+}
+
+/*
+ * ctl parsing & formatting (adapted from partfs)
+ */
+
+static char*
+ctlstring(Usbfs *fs)
+{
+       Part *p, *part;
+       Fmt fmt;
+       Umsc *lun;
+       Ums *ums;
+       
+       ums = fs->dev->aux;
+       lun = fs->aux;
+       part = &lun->part[0];
+
+       fmtstrinit(&fmt);
+       fmtprint(&fmt, "%s lun %ld: ", fs->dev->dir, lun - &ums->lun[0]);
+       if(lun->flags & Finqok)
+               fmtprint(&fmt, "inquiry %s ", lun->inq);
+       if(lun->blocks > 0)
+               fmtprint(&fmt, "geometry %llud %ld", lun->blocks, lun->lbsize);
+       fmtprint(&fmt, "\n");
+       for (p = part; p < &part[Maxparts]; p++)
+               if (p->inuse)
+                       fmtprint(&fmt, "part %s %lld %lld\n",
+                               p->name, p->offset, p->length);
+       return fmtstrflush(&fmt);
+}
+
+static int
+ctlparse(Usbfs *fs, char *msg)
+{
+       vlong start, end;
+       char *argv[16];
+       int argc;
+       Umsc *lun;
+       
+       lun = fs->aux;
+       argc = tokenize(msg, argv, nelem(argv));
+
+       if(argc < 1){
+               werrstr("empty control message");
+               return -1;
+       }
+
+       if(strcmp(argv[0], "part") == 0){
+               if(argc != 4){
+                       werrstr("part takes 3 args");
+                       return -1;
+               }
+               start = strtoll(argv[2], 0, 0);
+               end = strtoll(argv[3], 0, 0);
+               return addpart(lun, argv[1], start, end);
+       }else if(strcmp(argv[0], "delpart") == 0){
+               if(argc != 2){
+                       werrstr("delpart takes 1 arg");
+                       return -1;
+               }
+               return delpart(lun, argv[1]);
+       }
+       werrstr("unknown ctl");
+       return -1;
+}
+
 /*
  * These are used by scuzz scsireq
  */
@@ -461,8 +584,8 @@ dread(Usbfs *fs, Fid *fid, void *data, long count, vlong offset)
 {
        long n;
        ulong path;
-       char buf[1024];
-       char *s, *e;
+       char buf[64];
+       char *s;
        Umsc *lun;
        Ums *ums;
        Qid q;
@@ -478,15 +601,9 @@ dread(Usbfs *fs, Fid *fid, void *data, long count, vlong offset)
                count = usbdirread(fs, q, data, count, offset, dirgen, nil);
                break;
        case Qctl:
-               e = buf + sizeof(buf);
-               s = seprint(buf, e, "%s lun %ld: ", fs->dev->dir, lun - &ums->lun[0]);
-               if(lun->flags & Finqok)
-                       s = seprint(s, e, "inquiry %s ", lun->inq);
-               if(lun->blocks > 0)
-                       s = seprint(s, e, "geometry %llud %ld",
-                               lun->blocks, lun->lbsize);
-               s = seprint(s, e, "\n");
-               count = usbreadbuf(data, count, offset, buf, s - buf);
+               s = ctlstring(fs);
+               count = usbreadbuf(data, count, offset, s, strlen(s));
+               free(s);
                break;
        case Qraw:
                if(lun->lbsize <= 0 && umscapacity(lun) < 0){
@@ -548,6 +665,7 @@ dwrite(Usbfs *fs, Fid *fid, void *data, long count, vlong offset)
        uvlong bno;
        Ums *ums;
        Umsc *lun;
+       char *s;
 
        ums = fs->dev->aux;
        lun = fs->aux;
@@ -560,7 +678,13 @@ dwrite(Usbfs *fs, Fid *fid, void *data, long count, vlong offset)
                count = -1;
                break;
        case Qctl:
-               dprint(2, "usb/disk: ctl ignored\n");
+               s = emallocz(count+1, 1);
+               memmove(s, data, count);
+               if(s[count-1] == '\n')
+                       s[count-1] = 0;
+               if(ctlparse(fs, s) == -1)
+                       count = -1;
+               free(s);
                break;
        case Qraw:
                if(lun->lbsize <= 0 && umscapacity(lun) < 0){
index d65f8897beb83934f6dcb7284a9ef100783ee81a..d1c8219dcbdf22466d96b9a69af110d890a99a85 100644 (file)
@@ -7,6 +7,7 @@ typedef struct Umsc Umsc;
 typedef struct Ums Ums;
 typedef struct Cbw Cbw;                        /* command block wrapper */
 typedef struct Csw Csw;                        /* command status wrapper */
+typedef struct Part Part;
 
 enum
 {
@@ -42,12 +43,26 @@ enum
        CswOk           = 0,
        CswFailed       = 1,
        CswPhaseErr     = 2,
+       
+       Maxparts                = 8,
 };
 
 /*
  * corresponds to a lun.
  * these are ~600+Maxiosize bytes each; ScsiReq is not tiny.
  */
+
+struct Part
+{
+       int inuse;
+       int vers;
+       ulong mode;
+       char    *name;
+       vlong offset;           /* in lbsize units */
+       vlong length;           /* in lbsize units */
+};
+
+
 struct Umsc
 {
        ScsiReq;
@@ -59,6 +74,9 @@ struct Umsc
        long    off;            /* offset within a block */
        long    nb;             /* byte count */
 
+       /* partitions */
+       Part part[Maxparts];
+
        uchar   rawcmd[10];
        uchar   phase;
        char    *inq;