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