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