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