|
|
1.1 root 1: /*
2: * Block or character device RAM disk driver.
3: * AT COHERENT (286 and 386).
4: */
5:
6: #include <sys/coherent.h>
7: #include <sys/con.h>
8: #include <sys/buf.h>
9: #include <errno.h>
10: #include <sys/devices.h>
11: #include <sys/inode.h>
12: #include <sys/stat.h>
13: #include <sys/seg.h>
14: #include <sys/uproc.h>
15:
16: /*
17: * Minor number encoding: dsssssss
18: * d drive number (0 or 1)
19: * sssssss allocation size: 0 to free, 1-127 allocsize (n*ASIZE*BSIZE bytes)
20: */
21: #define rm_drive(dev) (minor(dev) >> 7)
22: #define rm_asize(dev) (minor(dev) & 0x7F)
23: #define ASIZE 128 /* allocation chunk size in blocks (64KB) */
24: #define NUM_RM 2 /* number of ram disks
25: - tied to dev encoding (see above) */
26:
27: int nulldev();
28: int nonedev();
29: int rmload();
30: int rmuload();
31: int rmopen();
32: int rmclose();
33: int rmread();
34: int rmwrite();
35: int rmblock();
36:
37: CON rmcon = {
38: DFBLK|DFCHR,
39: RM_MAJOR,
40: rmopen, /* Open */
41: rmclose, /* Close */
42: rmblock, /* Block */
43: rmread, /* Read */
44: rmwrite, /* Write */
45: nonedev,
46: nulldev,
47: nulldev,
48: rmload, /* Load */
49: rmuload /* Unload */
50: };
51:
52: typedef struct rm {
53: #ifndef COH386
54: fsize_t rm_size; /* Size in allocation chunks */
55: paddr_t rm_paddr; /* Physical base of ram disc segment */
56: SEG *rm_segp; /* Segment pointer of ram device */
57: #else
58: off_t rm_size; /* Size in allocation chunks */
59: SR rm_sr;
60: #endif
61: BUF rm_buf; /* Static buffer for raw requests */
62: int rm_nopen; /* Open count to avoid blowups */
63: } RM;
64: static RM rm[NUM_RM];
65:
66: /*
67: * Load.
68: */
69: static
70: rmload()
71: {
72: }
73:
74: /*
75: * Unload.
76: * Release the allocated buffers.
77: */
78: static
79: rmuload()
80: {
81: int i;
82:
83: for (i = 0; i < NUM_RM; i++){
84: if (rm[i].rm_size != 0) {
85: #ifndef COH386
86: sfree(rm[i].rm_segp);
87: #else
88: unload(&rm[i].rm_sr);
89: sfree(rm[i].rm_sr.sr_segp);
90: #endif
91: }
92: }
93: }
94:
95: /*
96: * Open.
97: * Allocate on the first call.
98: * Increment the open count.
99: */
100: static
101: rmopen(dev, mode) dev_t dev; int mode;
102: {
103: register RM *rmp;
104: #ifndef COH386
105: register fsize_t asize, osize;
106: register SEG *segp;
107: #else
108: register off_t asize, osize;
109: #endif
110:
111: rmp = &rm[rm_drive(dev)];
112: asize = rm_asize(dev);
113: osize = rmp->rm_size;
114:
115: /* Fail on read before creation or bogus size. */
116: if ((mode == IPR && osize == 0)
117: || (asize != 0 && osize != 0 && asize != osize)
118: || (asize == 0 && osize == 0)) {
119: u.u_error = ENXIO;
120: return;
121: }
122:
123: #ifdef COH386
124: if (ASIZE*BSIZE*asize > ctob(RAMSIZE)) {
125: u.u_error = ENOMEM;
126: return;
127: }
128: #endif
129:
130: /*
131: * Allocate as required.
132: * Ignore case asize==0 && osize!=0, handled by rmclose().
133: * If asize!=0 && asize==osize, just bump the open count.
134: */
135: if (asize != 0 && osize == 0) {
136: #ifndef COH386
137: segp = rmp->rm_segp = salloc((fsize_t)ASIZE*BSIZE*asize,
138: SFSYST|SFNSWP|SFNCLR|SFHIGH);
139: if (segp == NULL) {
140: #else
141: rmp->rm_sr.sr_segp =
142: salloc((off_t)ASIZE*BSIZE*asize, SFSYST|SFNSWP|SFNCLR);
143: if (rmp->rm_sr.sr_segp == NULL) {
144: #endif
145: u.u_error = ENOMEM;
146: return;
147: }
148: rmp->rm_size = asize;
149: #ifndef COH386
150: rmp->rm_paddr = segp->s_paddr;
151: rmp->rm_nopen = 0;
152: pclear(rmp->rm_paddr, 1024L); /* clear 1st 2 blocks */
153: #else
154: rmp->rm_sr.sr_base = rm_drive(dev)==0 ?
155: ctob(RAM0) : ctob(RAM1);
156: rmp->rm_sr.sr_size = rmp->rm_sr.sr_segp->s_size;
157: doload(&rmp->rm_sr);
158: #endif
159: }
160: rmp->rm_nopen++;
161: }
162:
163: /*
164: * Close.
165: * Decrement the open count.
166: * Release the allocated buffer if minor number is 0.
167: */
168: static
169: rmclose(dev) dev_t dev;
170: {
171: register RM *rmp;
172: #ifndef COH386
173: register fsize_t asize, osize;
174: #else
175: register off_t asize, osize;
176: #endif
177:
178: rmp = &rm[rm_drive(dev)];
179: asize = rm_asize(dev);
180: osize = rmp->rm_size;
181:
182: if (osize == 0
183: || (asize != 0 && asize != osize)
184: || rmp->rm_nopen == 0) {
185: u.u_error = ENXIO;
186: return;
187: }
188: rmp->rm_nopen--;
189: if (asize == 0) {
190: if (rmp->rm_nopen != 0) {
191: #ifndef COH386
192: u.u_error = EDBUSY;
193: #else
194: u.u_error = EBUSY;
195: #endif
196: return;
197: }
198: #ifndef COH386
199: sfree(rmp->rm_segp);
200: #else
201: unload(&rmp->rm_sr);
202: sfree(rmp->rm_sr.sr_segp);
203: #endif
204: rmp->rm_size = 0;
205: }
206: }
207:
208: static
209: rmblock(bp) register BUF *bp;
210: {
211: #ifndef COH386
212: paddr_t base;
213: register fsize_t asize, osize;
214: #else
215: vaddr_t base;
216: register off_t asize, osize;
217: #endif
218: dev_t dev;
219: register RM *rmp;
220:
221: dev = bp->b_dev;
222: rmp = &rm[rm_drive(dev)];
223: asize = rm_asize(dev);
224: osize = rmp->rm_size;
225: if (osize == 0 || asize != osize) {
226: bp->b_flag |= BFERR;
227: u.u_error = ENXIO;
228: /*
229: * Make sure last block requested is within range of device.
230: */
231: } else if ((bp->b_bno + bp->b_count/BSIZE - 1) >= asize*ASIZE) {
232: bp->b_flag |= BFERR;
233: u.u_error = EIO;
234: } else {
235: #ifndef COH386
236: base = rmp->rm_paddr + (paddr_t)bp->b_bno * BSIZE;
237: #else
238: base = rmp->rm_sr.sr_base + (paddr_t)bp->b_bno * BSIZE;
239: #endif
240: if (bp->b_req == BREAD)
241: #ifndef COH386
242: plrcopy(base, bp->b_paddr, (fsize_t)bp->b_count);
243: #else
244: dmaout(bp->b_count, bp->b_paddr, base);
245: #endif
246: else
247: #ifndef COH386
248: plrcopy(bp->b_paddr, base, (fsize_t)bp->b_count);
249: #else
250: dmaout(bp->b_count, bp->b_paddr, base);
251: #endif
252: }
253: bdone(bp);
254: }
255:
256: /*
257: * The read routine calls the common raw I/O processing code,
258: * using a static buffer header in the driver.
259: */
260: static
261: rmread(dev, iop) register dev_t dev; IO *iop;
262: {
263: register BUF *bufp;
264:
265: bufp = &rm[rm_drive(dev)].rm_buf;
266: ioreq(bufp, iop, dev, BREAD, BFIOC|BFRAW);
267: }
268:
269: /*
270: * The write routine is just like the read routine,
271: * except that the function code is write instead of read.
272: */
273: static
274: rmwrite(dev, iop) register dev_t dev; IO *iop;
275: {
276: register BUF *bufp;
277:
278: bufp = &rm[rm_drive(dev)].rm_buf;
279: ioreq(bufp, iop, dev, BWRITE, BFIOC|BFRAW);
280: }
281:
282: /* end of rm.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.