|
|
1.1 root 1: #include "u.h"
2: #include "../port/lib.h"
3: #include "mem.h"
4: #include "dat.h"
5: #include "fns.h"
6: #include "../port/error.h"
7: #include "devtab.h"
8: #include "io.h"
9:
10: /*
11: * CD-ROM. Gutted version of devwren.
12: */
13:
14: #define DATASIZE 2048 /* max in a transfer */
15:
16: typedef struct Drive Drive;
17:
18: enum {
19: Ndisk= 8, /* maximum disks */
20: /* file types */
21: Qdir= 0,
22: Qdisk= 1,
23: };
24:
25: struct Drive
26: {
27: QLock;
28: ulong blocks; /* blocks on disk */
29: ulong bsize; /* bytes per block */
30: int drive;
31: };
32:
33: static Drive cdrom[Ndisk];
34:
35: static void cdromsize(int);
36: static long cdromio(Chan*, char*, ulong, ulong);
37:
38: static char Ecap[] = "CD-ROM device capacity unknown";
39: static char EnotCD[] = "not a CD-ROM device";
40:
41: /*
42: * accepts [0-7]. lun is therefore always zero.
43: */
44: static int
45: cdromdev(char *p)
46: {
47: int drive;
48:
49: if(p == 0 || p[0] == '\0')
50: error(Ebadarg);
51: if(p[0] < '0' || p[0] > '7' || p[1])
52: error(Ebadarg);
53: drive = p[0] - '0';
54: return (drive << 3) | 0;
55: }
56:
57: static int
58: cdromgen(Chan *c, Dirtab *tab, long ntab, long s, Dir *dirp)
59: {
60: char name[NAMELEN+4];
61: Drive *dp;
62:
63: USED(tab, ntab);
64: if(s != 0)
65: return -1;
66: sprint(name, "cd%d", c->dev>>3);
67: dp = &cdrom[c->dev>>3];
68: devdir(c, (Qid){Qdisk, 0}, name, dp->blocks*dp->bsize, eve, 0444, dirp);
69: return 1;
70: }
71:
72: void
73: cdromreset(void)
74: {
75: }
76:
77: void
78: cdrominit(void)
79: {
80: }
81:
82: /*
83: * param is #R<target>
84: */
85: Chan*
86: cdromattach(char *param)
87: {
88: Chan *c;
89: int drive;
90:
91: drive = cdromdev(param);
92: cdromsize(drive);
93: c = devattach('R', param);
94: c->dev = drive;
95: return c;
96: }
97:
98: Chan*
99: cdromclone(Chan *c, Chan *nc)
100: {
101: return devclone(c, nc);
102: }
103:
104: int
105: cdromwalk(Chan *c, char *name)
106: {
107: return devwalk(c, name, 0, 0, cdromgen);
108: }
109:
110: void
111: cdromstat(Chan *c, char *dp)
112: {
113: devstat(c, dp, 0, 0, cdromgen);
114: }
115:
116: Chan*
117: cdromopen(Chan *c, int omode)
118: {
119: return devopen(c, omode, 0, 0, cdromgen);
120: }
121:
122: void
123: cdromcreate(Chan *c, char *name, int omode, ulong perm)
124: {
125: USED(c, name, omode, perm);
126: error(Eperm);
127: }
128:
129: void
130: cdromclose(Chan *c)
131: {
132: USED(c);
133: }
134:
135: void
136: cdromremove(Chan *c)
137: {
138: USED(c);
139: error(Eperm);
140: }
141:
142: void
143: cdromwstat(Chan *c, char *dp)
144: {
145: USED(c, dp);
146: error(Eperm);
147: }
148:
149: long
150: cdromread(Chan *c, char *a, long n, ulong offset)
151: {
152: if(c->qid.path == CHDIR)
153: return devdirread(c, a, n, 0, 0, cdromgen);
154: return cdromio(c, a, n, offset);
155: }
156:
157: long
158: cdromwrite(Chan *c, char *a, long n, ulong offset)
159: {
160: USED(c, a, n, offset);
161: error(Eperm);
162: return 0;
163: }
164:
165: static long
166: cdromio(Chan *c, char *a, ulong len, ulong offset)
167: {
168: Drive *d;
169: Scsibuf *b;
170: ulong block, n, max, x;
171:
172: d = &cdrom[c->dev>>3];
173:
174: block = offset / d->bsize;
175: n = (offset + len + d->bsize - 1) / d->bsize - block;
176: max = DATASIZE / d->bsize;
177: if(n > max)
178: n = max;
179: if(block + n > d->blocks)
180: n = d->blocks - block;
181: if(block >= d->blocks || n == 0)
182: return 0;
183: b = scsibuf();
184: if(waserror()){
185: scsifree(b);
186: nexterror();
187: }
188: offset %= d->bsize;
189: x = scsibread(d->drive, b, n, d->bsize, block);
190: if(x < offset)
191: len = 0;
192: else if(len > x - offset)
193: len = x - offset;
194: memmove(a, (char*)b->virt + offset, len);
195: poperror();
196: scsifree(b);
197: return len;
198: }
199:
200: /*
201: * size disk
202: */
203: static void
204: cdromsize(int dev)
205: {
206: Drive *dp;
207: uchar buf[128];
208: long nb, bs;
209:
210: dp = &cdrom[dev>>3];
211: if(waserror()){
212: qunlock(dp);
213: nexterror();
214: }
215: qlock(dp);
216: scsiready(dev);
217: scsisense(dev, buf);
218: /*
219: * capacity not defined on CD-ROM, but most implement it.
220: */
221: if(scsicap(dev, buf)!=0)
222: error(Ecap);
223: nb = (buf[0]<<24)|(buf[1]<<16)|(buf[2]<<8)|(buf[3]<<0);
224: bs = (buf[4]<<24)|(buf[5]<<16)|(buf[6]<<8)|(buf[7]<<0);
225: if(nb==0 || bs==0)
226: error(Ecap);
227:
228: scsiinquiry(dev, buf, sizeof buf);
229: dp->drive = dev;
230: dp->blocks = nb;
231: dp->bsize = bs;
232: poperror();
233: qunlock(dp);
234: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.