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