Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <thread.h>
4
#include <fcall.h>
5
#include "usb.h"
6
#include "usbfs.h"
7
 
8
typedef struct Rpc Rpc;
9
 
10
enum
11
{
12
	Incr = 3,	/* increments for fs array */
13
	Dtop = 0,	/* high 32 bits for / 	*/
14
	Qdir = 0,	/* low 32 bits for /devdir */
15
};
16
 
17
QLock fslck;
18
static Usbfs** fs;
19
static int nfs;
20
static int fsused;
21
static int exitonclose = 1;
22
 
23
void
24
usbfsexits(int y)
25
{
26
	exitonclose = y;
27
}
28
 
29
static int
30
qiddev(uvlong path)
31
{
32
	return (int)(path>>32) & 0xFF;
33
}
34
 
35
static int
36
qidfile(uvlong path)
37
{
38
	return (int)(path & 0xFFFFFFFFULL);
39
}
40
 
41
static uvlong
42
mkqid(int qd, int qf)
43
{
44
	return ((uvlong)qd << 32) | (uvlong)qf;
45
}
46
 
47
void
48
usbfsdirdump(void)
49
{
50
	int i;
51
 
52
	qlock(&fslck);
53
	fprint(2, "%s: fs list: (%d used %d total)\n", argv0, fsused, nfs);
54
	for(i = 1; i < nfs; i++)
55
		if(fs[i] != nil)
56
			if(fs[i]->dev != nil)
57
				fprint(2, "%s\t%s dev %#p refs %ld\n",
58
					argv0, fs[i]->name, fs[i]->dev, fs[i]->dev->ref);
59
			else
60
				fprint(2, "%s:\t%s\n", argv0, fs[i]->name);
61
	qunlock(&fslck);
62
}
63
 
64
void
65
usbfsadd(Usbfs *dfs)
66
{
67
	int i, j;
68
 
69
	dprint(2, "%s: fsadd %s\n", argv0, dfs->name);
70
	qlock(&fslck);
71
	for(i = 1; i < nfs; i++)
72
		if(fs[i] == nil)
73
			break;
74
	if(i >= nfs){
75
		if((nfs%Incr) == 0){
76
			fs = realloc(fs, sizeof(Usbfs*) * (nfs+Incr));
77
			if(fs == nil)
78
				sysfatal("realloc: %r");
79
			for(j = nfs; j < nfs+Incr; j++)
80
				fs[j] = nil;
81
		}
82
		if(nfs == 0)	/* do not use entry 0 */
83
			nfs++;
84
		fs[nfs++] = dfs;
85
	}else
86
		fs[i] = dfs;
87
	dfs->qid = mkqid(i, 0);
88
	fsused++;
89
	qunlock(&fslck);
90
}
91
 
92
static void
93
usbfsdelnth(int i)
94
{
95
	if(fs[i] != nil){
96
		dprint(2, "%s: fsdel %s", argv0, fs[i]->name);
97
		if(fs[i]->dev != nil){
98
			dprint(2, " dev %#p ref %ld\n",
99
				fs[i]->dev, fs[i]->dev->ref);
100
		}else
101
			dprint(2, "no dev\n");
102
		if(fs[i]->end != nil)
103
			fs[i]->end(fs[i]);
104
		closedev(fs[i]->dev);
105
		fsused--;
106
	}
107
	fs[i] = nil;
108
	if(fsused == 0 && exitonclose != 0){
109
		fprint(2, "%s: all file systems gone: exiting\n", argv0);
110
		threadexitsall(nil);
111
	}
112
}
113
 
114
void
115
usbfsdel(Usbfs *dfs)
116
{
117
	int i;
118
 
119
	qlock(&fslck);
120
	for(i = 0; i < nfs; i++)
121
		if(dfs == nil || fs[i] == dfs){
122
			usbfsdelnth(i);
123
			if(dfs != nil)
124
				break;
125
		}
126
	qunlock(&fslck);
127
}
128
 
129
static void
130
fsend(Usbfs*)
131
{
132
	dprint(2, "%s: fsend\n", argv0);
133
	usbfsdel(nil);
134
}
135
 
136
void
137
usbfsgone(char *dir)
138
{
139
	int i;
140
 
141
	qlock(&fslck);
142
	/* devices may have more than one fs */
143
	for(i = 0; i < nfs; i++)
144
		if(fs[i] != nil && fs[i]->dev != nil)
145
		if(strcmp(fs[i]->dev->dir, dir) == 0)
146
			usbfsdelnth(i);
147
	qunlock(&fslck);
148
}
149
 
150
static void
151
fsclone(Usbfs*, Fid *o, Fid *n)
152
{
153
	int qd;
154
	Dev *dev;
155
	void (*xfsclone)(Usbfs *fs, Fid *of, Fid *nf);
156
 
157
	xfsclone = nil;
158
	dev = nil;
159
	qd = qiddev(o->qid.path);
160
	qlock(&fslck);
161
	if(qd != Dtop && fs[qd] != nil && fs[qd]->clone != nil){
162
		dev = fs[qd]->dev;
163
		if(dev != nil)
164
			incref(dev);
165
		xfsclone = fs[qd]->clone;
166
	}
167
	qunlock(&fslck);
168
	if(xfsclone != nil){
169
		xfsclone(fs[qd], o, n);
170
	}
171
	if(dev != nil)
172
		closedev(dev);
173
}
174
 
175
static int
176
fswalk(Usbfs*, Fid *fid, char *name)
177
{
178
	Qid q;
179
	int qd, qf;
180
	int i;
181
	int rc;
182
	Dev *dev;
183
	Dir d;
184
	int (*xfswalk)(Usbfs *fs, Fid *f, char *name);
185
 
186
	q = fid->qid;
187
	qd = qiddev(q.path);
188
	qf = qidfile(q.path);
189
 
190
	q.type = QTDIR;
191
	q.vers = 0;
192
	if(strcmp(name, "..") == 0)
193
		if(qd == Dtop || qf == Qdir){
194
			q.path = mkqid(Dtop, Qdir);
195
			fid->qid = q;
196
			return 0;
197
		}
198
	if(qd != 0){
199
		qlock(&fslck);
200
		if(fs[qd] == nil){
201
			qunlock(&fslck);
202
			werrstr(Eio);
203
			return -1;
204
		}
205
		dev = fs[qd]->dev;
206
		if(dev != nil)
207
			incref(dev);
208
		xfswalk = fs[qd]->walk;
209
		qunlock(&fslck);
210
		rc = xfswalk(fs[qd], fid, name);
211
		if(dev != nil)
212
			closedev(dev);
213
		return rc;
214
	}
215
	qlock(&fslck);
216
	for(i = 0; i < nfs; i++)
217
		if(fs[i] != nil && strcmp(name, fs[i]->name) == 0){
218
			q.path = mkqid(i, Qdir);
219
			fs[i]->stat(fs[i], q, &d); /* may be a file */
220
			fid->qid = d.qid;
221
			qunlock(&fslck);
222
			return 0;
223
		}
224
	qunlock(&fslck);
225
	werrstr(Enotfound);
226
	return -1;
227
}
228
 
229
static int
230
fsopen(Usbfs*, Fid *fid, int mode)
231
{
232
	int qd;
233
	int rc;
234
	Dev *dev;
235
	int (*xfsopen)(Usbfs *fs, Fid *f, int mode);
236
 
237
	qd = qiddev(fid->qid.path);
238
	if(qd == Dtop)
239
		return 0;
240
	qlock(&fslck);
241
	if(fs[qd] == nil){
242
		qunlock(&fslck);
243
		werrstr(Eio);
244
		return -1;
245
	}
246
	dev = fs[qd]->dev;
247
	if(dev != nil)
248
		incref(dev);
249
	xfsopen = fs[qd]->open;
250
	qunlock(&fslck);
251
	if(xfsopen != nil)
252
		rc = xfsopen(fs[qd], fid, mode);
253
	else
254
		rc = 0;
255
	if(dev != nil)
256
		closedev(dev);
257
	return rc;
258
}
259
 
260
static int
261
dirgen(Usbfs*, Qid, int n, Dir *d, void *)
262
{
263
	int i;
264
	Dev *dev;
265
	char *nm;
266
 
267
	qlock(&fslck);
268
	for(i = 0; i < nfs; i++)
269
		if(fs[i] != nil && n-- == 0){
270
			d->qid.type = QTDIR;
271
			d->qid.path = mkqid(i, Qdir);
272
			d->qid.vers = 0;
273
			dev = fs[i]->dev;
274
			if(dev != nil)
275
				incref(dev);
276
			nm = d->name;
277
			fs[i]->stat(fs[i], d->qid, d);
278
			d->name = nm;
279
			strncpy(d->name, fs[i]->name, Namesz);
280
			if(dev != nil)
281
				closedev(dev);
282
			qunlock(&fslck);
283
			return 0;
284
		}
285
	qunlock(&fslck);
286
	return -1;
287
}
288
 
289
static long
290
fsread(Usbfs*, Fid *fid, void *data, long cnt, vlong off)
291
{
292
	int qd;
293
	int rc;
294
	Dev *dev;
295
	Qid q;
296
	long (*xfsread)(Usbfs *fs, Fid *f, void *data, long count, vlong );
297
 
298
	q = fid->qid;
299
	qd = qiddev(q.path);
300
	if(qd == Dtop)
301
		return usbdirread(nil, q, data, cnt, off, dirgen, nil);
302
	qlock(&fslck);
303
	if(fs[qd] == nil){
304
		qunlock(&fslck);
305
		werrstr(Eio);
306
		return -1;
307
	}
308
	dev = fs[qd]->dev;
309
	if(dev != nil)
310
		incref(dev);
311
	xfsread = fs[qd]->read;
312
	qunlock(&fslck);
313
	rc = xfsread(fs[qd], fid, data, cnt, off);
314
	if(dev != nil)
315
		closedev(dev);
316
	return rc;
317
}
318
 
319
static long
320
fswrite(Usbfs*, Fid *fid, void *data, long cnt, vlong off)
321
{
322
	int qd;
323
	int rc;
324
	Dev *dev;
325
	long (*xfswrite)(Usbfs *fs, Fid *f, void *data, long count, vlong );
326
 
327
	qd = qiddev(fid->qid.path);
328
	if(qd == Dtop)
329
		sysfatal("fswrite: not for usbd /");
330
	qlock(&fslck);
331
	if(fs[qd] == nil){
332
		qunlock(&fslck);
333
		werrstr(Eio);
334
		return -1;
335
	}
336
	dev = fs[qd]->dev;
337
	if(dev != nil)
338
		incref(dev);
339
	xfswrite = fs[qd]->write;
340
	qunlock(&fslck);
341
	rc = xfswrite(fs[qd], fid, data, cnt, off);
342
	if(dev != nil)
343
		closedev(dev);
344
	return rc;
345
}
346
 
347
 
348
static void
349
fsclunk(Usbfs*, Fid* fid)
350
{
351
	int qd;
352
	Dev *dev;
353
	void (*xfsclunk)(Usbfs *fs, Fid *f);
354
 
355
	dev = nil;
356
	qd = qiddev(fid->qid.path);
357
	qlock(&fslck);
358
	if(qd != Dtop && fs[qd] != nil){
359
		dev=fs[qd]->dev;
360
		if(dev != nil)
361
			incref(dev);
362
		xfsclunk = fs[qd]->clunk;
363
	}else
364
		xfsclunk = nil;
365
	qunlock(&fslck);
366
	if(xfsclunk != nil){
367
		xfsclunk(fs[qd], fid);
368
	}
369
	if(dev != nil)
370
		closedev(dev);
371
}
372
 
373
static int
374
fsstat(Usbfs*, Qid qid, Dir *d)
375
{
376
	int qd;
377
	int rc;
378
	Dev *dev;
379
	int (*xfsstat)(Usbfs *fs, Qid q, Dir *d);
380
 
381
	qd = qiddev(qid.path);
382
	if(qd == Dtop){
383
		d->qid = qid;
384
		d->name = "usb";
385
		d->length = 0;
386
		d->mode = 0555|DMDIR;
387
		return 0;
388
	}
389
	qlock(&fslck);
390
	if(fs[qd] == nil){
391
		qunlock(&fslck);
392
		werrstr(Eio);
393
		return -1;
394
	}
395
	xfsstat = fs[qd]->stat;
396
	dev = fs[qd]->dev;
397
	if(dev != nil)
398
		incref(dev);
399
	qunlock(&fslck);
400
	rc = xfsstat(fs[qd], qid, d);
401
	if(dev != nil)
402
		closedev(dev);
403
	return rc;
404
}
405
 
406
Usbfs usbdirfs =
407
{
408
	.walk = fswalk,
409
	.clone = fsclone,
410
	.clunk = fsclunk,
411
	.open = fsopen,
412
	.read = fsread,
413
	.write = fswrite,
414
	.stat = fsstat,
415
	.end = fsend,
416
};
417