sdloop.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       sdloop.c (5157B)
       ---
            1 #include "u.h"
            2 #include "lib.h"
            3 #include "mem.h"
            4 #include "dat.h"
            5 #include "fns.h"
            6 #include "io.h"
            7 #include "ureg.h"
            8 #include "error.h"
            9 
           10 #include "sd.h"
           11 
           12 void        loopdev(char*, int);
           13 
           14 typedef struct Ctlr Ctlr;
           15 struct Ctlr{
           16         Ctlr        *next;
           17         Ctlr        *prev;
           18         
           19         QLock        lk;
           20         SDev        *sdev;
           21 
           22         Chan        *c;
           23         int                mode;
           24         uvlong        qidpath;
           25         char                fn[20];
           26 };
           27 
           28 static        Lock        ctlrlock;
           29 static        Ctlr        *ctlrhead;
           30 static        Ctlr        *ctlrtail;
           31 
           32 SDifc sdloopifc;
           33 
           34 static void
           35 loopopen(Ctlr *c)
           36 {
           37         if(c->c == nil)
           38                 c->c = namec(c->fn, Aopen, c->mode, 0);
           39 }
           40 
           41 static SDev*
           42 looppnp(void)
           43 {
           44         struct stat sbuf;
           45         char c, c2;
           46         char fn[20];
           47 
           48         for(c = 'a'; c <= 'j'; ++c){
           49                 sprint(fn, "#Z/dev/sd%c", c);
           50                 if(stat(fn+2, &sbuf) == 0)
           51                         loopdev(fn, ORDWR);
           52         }
           53         for(c = '0'; c <= '9'; ++c){
           54                 sprintf(fn, "#Z/dev/sd%c",c);
           55                 if(stat(fn+2, &sbuf) == 0)
           56                         loopdev(fn, ORDWR);
           57         }
           58         for(c = 'a'; c <= 'j'; ++c){
           59                 sprint(fn, "#Z/dev/hd%c", c);
           60                 if(stat(fn+2, &sbuf) == 0)
           61                         loopdev(fn, ORDWR);
           62         }
           63         for(c = '0'; c <= '9'; ++c){
           64                 sprint(fn, "#Z/dev/wd%c", c);
           65                 if(stat(fn+2, &sbuf) == 0)
           66                         loopdev(fn, ORDWR);
           67         }
           68         for(c = '0'; c <= '8'; ++c){
           69                 for(c2 = '0'; c2 <= '8'; ++c2){
           70                         sprint(fn, "#Z/dev/cciss/c%cd%c", c, c2);
           71                         if(stat(fn+2, &sbuf) == 0)
           72                                 loopdev(fn, ORDWR);
           73                 }
           74         }
           75         return nil;
           76 }
           77 
           78 /*
           79  * Cannot error.
           80  * Check that unit is available.
           81  * Return 1 if so, 0 if not.
           82  */
           83 static int
           84 loopverify(SDunit *u)
           85 {        
           86         return 1;
           87 }
           88 
           89 /*
           90  * Cannot error.
           91  * Check that unit is online.
           92  * If media changed, return 2.
           93  * If ready, return 1.
           94  * If not ready, return 0.
           95  */
           96 static int
           97 looponline(SDunit *unit)
           98 {
           99         uchar buf[sizeof(Dir)+100];
          100         Chan *c;
          101         SDev *sdev;
          102         Ctlr *ctlr;
          103         Dir dir;
          104         long n;
          105         
          106         if(waserror())
          107                 return 0;
          108 
          109         sdev = unit->dev;
          110         ctlr = sdev->ctlr;
          111         loopopen(ctlr);
          112         c = ctlr->c;
          113         n = devtab[c->type]->stat(c, buf, sizeof buf);
          114         if(convM2D(buf, n, &dir, nil) == 0)
          115                 error("internal error: stat error in looponline");
          116         if(ctlr->qidpath != dir.qid.path){
          117                 unit->sectors = dir.length/512;
          118                 unit->secsize = 512;
          119                 ctlr->qidpath = dir.qid.path;
          120                 poperror();
          121                 return 2;
          122         }
          123         poperror();
          124         return 1;
          125 }
          126 
          127 static int
          128 looprio(SDreq *r)
          129 {
          130         SDev *sdev;
          131         SDunit *unit;
          132         Ctlr *ctlr;
          133         uchar *cmd;
          134         uvlong lba;
          135         long count, n;
          136         Chan *c;
          137         int status;
          138 
          139         unit = r->unit;
          140         sdev = unit->dev;
          141         ctlr = sdev->ctlr;
          142         loopopen(ctlr);
          143         cmd = r->cmd;
          144 
          145         if((status = sdfakescsi(r, nil, 0)) != SDnostatus){
          146 #warning "Need to check for SDcheck in sdloop.";
          147                 /* XXX check for SDcheck here */
          148                 r->status = status;
          149                 return status;
          150         }
          151 
          152         switch(cmd[0]){
          153         case 0x28:        /* read */
          154         case 0x2A:        /* write */
          155                 break;
          156         default:
          157                 print("%s: bad cmd 0x%.2ux\n", unit->perm.name, cmd[0]);
          158                 r->status = SDcheck;
          159                 return SDcheck;
          160         }
          161 
          162         lba = (cmd[2]<<24)|(cmd[3]<<16)|(cmd[4]<<8)|cmd[5];
          163         count = (cmd[7]<<8)|cmd[8];
          164         if(r->data == nil)
          165                 return SDok;
          166         if(r->dlen < count*512)
          167                 count = r->dlen/512;
          168 
          169         c = ctlr->c;
          170         if(cmd[0] == 0x28)
          171                 n = devtab[c->type]->read(c, r->data, count*512, lba*512);
          172         else
          173                 n = devtab[c->type]->write(c, r->data, count*512, lba*512);
          174         r->rlen = n;
          175         return SDok;
          176 }
          177 
          178 static int
          179 looprctl(SDunit *unit, char *p, int l)
          180 {
          181         Ctlr *ctlr;
          182         char *e, *op;
          183         
          184         ctlr = unit->dev->ctlr;
          185         loopopen(ctlr);
          186         e = p+l;
          187         op = p;
          188         
          189         p = seprint(p, e, "loop %s %s\n", ctlr->mode == ORDWR ? "rw" : "ro", chanpath(ctlr->c));
          190         p = seprint(p, e, "geometry %llud 512\n", unit->sectors*512);
          191         return p - op;
          192 }
          193 
          194 static int
          195 loopwctl(SDunit *u, Cmdbuf *cmd)
          196 {
          197         cmderror(cmd, Ebadarg);
          198         return 0;
          199 }
          200 
          201 static void
          202 loopclear1(Ctlr *ctlr)
          203 {
          204         lock(&ctlrlock);
          205         if(ctlr->prev)
          206                 ctlr->prev->next = ctlr->next;
          207         else
          208                 ctlrhead = ctlr;
          209         if(ctlr->next)
          210                 ctlr->next->prev = ctlr->prev;
          211         else
          212                 ctlrtail = ctlr->prev;
          213         unlock(&ctlrlock);
          214         
          215         if(ctlr->c)
          216                 cclose(ctlr->c);
          217         free(ctlr);
          218 }
          219 
          220 static void
          221 loopclear(SDev *sdev)
          222 {
          223         loopclear1(sdev->ctlr);
          224 }
          225 
          226 static char*
          227 looprtopctl(SDev *s, char *p, char *e)
          228 {
          229         Ctlr *c;
          230         char *r;
          231 
          232         c = s->ctlr;
          233         loopopen(c);
          234         r = "ro";
          235         if(c->mode == ORDWR)
          236                 r = "rw";
          237         return seprint(p, e, "%s loop %s %s\n", s->name, r, chanpath(c->c));
          238 }
          239 
          240 static int
          241 loopwtopctl(SDev *sdev, Cmdbuf *cb)
          242 {
          243         int mode;
          244 
          245         mode = 0;
          246         if(cb->nf != 2)
          247                 cmderror(cb, Ebadarg);
          248         if(strcmp(cb->f[0], "rw") == 0)
          249                 mode = ORDWR;
          250         else if(strcmp(cb->f[0], "ro") == 0)
          251                 mode = OREAD;
          252         else
          253                 cmderror(cb, Ebadarg);
          254         
          255         loopdev(cb->f[1], mode);
          256         return 0;
          257 }
          258 
          259 void
          260 loopdev(char *name, int mode)
          261 {
          262         Chan *c;
          263         Ctlr *volatile ctlr;
          264         SDev *volatile sdev;
          265 
          266         ctlr = nil;
          267         sdev = nil;
          268 /*
          269         if(waserror()){
          270                 cclose(c);
          271                 if(ctlr)
          272                         free(ctlr);
          273                 if(sdev)
          274                         free(sdev);
          275                 nexterror();
          276         }
          277 */
          278 
          279         ctlr = smalloc(sizeof *ctlr);
          280         sdev = smalloc(sizeof *sdev);
          281         sdev->ifc = &sdloopifc;
          282         sdev->ctlr = ctlr;
          283         sdev->nunit = 1;
          284         sdev->idno = '0';
          285         ctlr->sdev = sdev;
          286         strcpy(ctlr->fn, name);
          287         ctlr->mode = mode;
          288 /*
          289         poperror();
          290 */
          291 
          292         lock(&ctlrlock);
          293         ctlr->next = nil;
          294         ctlr->prev = ctlrtail;
          295         ctlrtail = ctlr;
          296         if(ctlr->prev)
          297                 ctlr->prev->next = ctlr;
          298         else
          299                 ctlrhead = ctlr;
          300         unlock(&ctlrlock);
          301         
          302         sdadddevs(sdev);
          303 }
          304 
          305 
          306 SDifc sdloopifc = {
          307         "loop",
          308 
          309         looppnp,
          310         nil,                /* legacy */
          311         nil,                /* enable */
          312         nil,                /* disable */
          313 
          314         loopverify,
          315         looponline,
          316         looprio,
          317         looprctl,
          318         loopwctl,
          319 
          320         scsibio,
          321         nil,        /* probe */
          322         loopclear,        /* clear */
          323         looprtopctl,
          324         loopwtopctl,
          325 };
          326 
          327 
          328