|
|
1.1 root 1: /*
2: * System V Compatible Shared Memory Device Driver
3: *
4: * This device driver provides System V compatible shared memory operations.
5: * Operations are performed through the shared memory device (/dev/shm).
6: * and are implemented as ioctl calls from shmctl, shmget, shmat, shmdt
7: * utilities.
8: *
9: * Author: Allan Cornish.
10: *
11: */
12:
13: #include <sys/coherent.h>
14: #include <sys/sched.h>
15: #include <sys/types.h>
16: #include <sys/uproc.h>
17: #include <errno.h>
18: #include <sys/stat.h>
19: #include <sys/con.h>
20: #include <sys/seg.h>
21: #include <sys/shm.h>
22: #ifndef _I386
23: #define getusd(arg) getuwd(arg)
24: #define putusd(arg1, arg2) putuwd(arg1, arg2)
25: #endif
26:
27: #ifndef EIDRM
28: #define EIDRM EDOM
29: #endif
30:
31: /*
32: * Functions.
33: */
34:
35: int shmload();
36: int shmread();
37: int shmwrite();
38: int shmioctl();
39: int nulldev();
40: int nonedev();
41:
42: /*
43: * Device Configuration.
44: */
45:
46: CON shmcon = {
47: DFCHR, /* Flags */
48: 24, /* Major Index */
49: nulldev, /* Open */
50: nulldev, /* Close */
51: nonedev, /* Block */
52: shmread, /* Read */
53: shmwrite, /* Write */
54: shmioctl, /* Ioctl */
55: nulldev, /* Power fail */
56: nulldev, /* Timeout */
57: shmload, /* Load */
58: nulldev /* Unload */
59: };
60:
61: unsigned NSHMID = 16;
62: struct shmid_ds *shmids;
63: struct seg **shmsegs;
64:
65: /*
66: * Shared Memory Device Load.
67: */
68:
69: static
70: shmload()
71: {
72: register struct shmid_ds * idp;
73: register unsigned wanted;
74:
75: if (NSHMID == 0)
76: return 0;
77:
78: wanted = NSHMID * (sizeof(struct shmid_ds) + sizeof(struct seg *));
79:
80: /* allocate space for structs */
81:
82: if ((shmids = kalloc(wanted)) == 0) {
83: printf("couldn't kalloc %u shared memory ids\n", NSHMID);
84: NSHMID = 0;
85: return 0;
86: }
87: shmsegs = (struct seg *) &shmids[ NSHMID ];
88:
89: for (idp = &shmids[NSHMID]; --idp >= shmids;)
90: idp->shm_perm.mode = 0;
91:
92: return 0;
93: }
94:
95: /*
96: ** Shared Memory Read.
97: */
98:
99:
100:
101: static
102: shmread(dev, iop)
103:
104: dev_t dev;
105: register IO *iop;
106:
107: {
108: register struct shmid_ds *idp;
109: int shmid;
110: unsigned off;
111: #ifndef _I386
112: faddr_t faddr;
113: #endif
114:
115: #ifdef _I386
116: off = ((unsigned short *) &iop->io_seek)[0];
117: shmid = ((unsigned short *) &iop->io_seek)[1];
118: #else
119: off = ((unsigned *) &iop->io_seek)[0];
120: shmid = ((unsigned *) &iop->io_seek)[1];
121: #endif
122:
123: /* is shmid valid? */
124: if (shmid >= NSHMID) {
125: u.u_error = EFAULT;
126: return -1;
127: }
128:
129: idp = &shmids[shmid]; /* point to struct _ds being used */
130:
131: /* check mode */
132: if ((idp->shm_perm.mode & IPC_ALLOC) == 0) {
133: u.u_error = EIDRM;
134: return -1;
135: }
136:
137: /* check permissions */
138: if ((ipcaccess(&idp->shm_perm) & SHM_R) == 0) {
139: u.u_error = EACCES;
140: return -1;
141: }
142:
143: /* are we about to exceed our segment size? */
144: if (((long) off + iop->io_ioc) > idp->shm_segsz) {
145: u.u_error = EFAULT;
146: return -1;
147: }
148:
149: /* copy from kernel data to user data */
150: #ifndef _I386
151: FP_SEL(faddr) = FP_SEL(shmsegs[shmid]->s_faddr);
152: FP_OFF(faddr) = off;
153: #endif
154: #ifdef _I386
155: if (!kucopy(shmsegs[shmid], iop->io.vbase,
156: iop->io_ioc)){
157: #else
158: if (! fucopy(faddr, iop->io_base, iop->io_ioc)) {
159: #endif
160: u.u_error = EFAULT;
161: return -1;
162: }
163:
164: iop->io_ioc = 0;
165: return 0;
166: }
167:
168:
169:
170: /*
171: ** Shared Memory Write.
172: */
173:
174:
175: static
176: shmwrite(dev, iop)
177:
178: dev_t dev;
179: register IO *iop;
180:
181: {
182: register struct shmid_ds *idp;
183: int shmid;
184: unsigned off;
185: #ifndef _I386
186: faddr_t faddr;
187: #endif
188:
189:
190: #ifdef _I386
191: off = ((unsigned short *) &iop->io_seek)[0];
192: shmid = ((unsigned short *) &iop->io_seek)[1];
193: #else
194: off = ((unsigned *) &iop->io_seek)[0];
195: shmid = ((unsigned *) &iop->io_seek)[1];
196: #endif
197:
198: /* validate id # */
199: if (shmid >= NSHMID) {
200: u.u_error = EFAULT;
201: return -1;
202: }
203:
204: idp = &shmids[shmid]; /* set our pointer to struct we're working on*/
205:
206: /* verify mode */
207: if ((idp->shm_perm.mode & IPC_ALLOC) == 0) {
208: u.u_error = EIDRM;
209: return -1;
210: }
211:
212: /* verify Permissions */
213: if ((ipcaccess(&idp->shm_perm) & SHM_W) == 0) {
214: u.u_error = EFAULT;
215: return -1;
216: }
217:
218: /* verify that we won't overwrite our space */
219: if (((long) off + iop->io_ioc) > idp->shm_segsz) {
220: u.u_error = EFAULT;
221: return -1;
222: }
223:
224: /* copy from user memory to shared segment */
225: #ifndef _I386
226: FP_SEL(faddr) = FP_SEL(shmsegs[shmid]->s_faddr);
227: FP_OFF(faddr) = off;
228: #endif
229: #ifdef _I386
230: if (!ukcopy( iop->io.vbase, shmsegs[shmid],
231: iop->io_ioc)){
232: #else
233: if (! ufcopy(iop->io_base, faddr, iop->io_ioc)) {
234: #endif
235: u.u_error = EFAULT;
236: return -1;
237: }
238:
239: iop->io_ioc = 0;
240: return 0;
241: }
242:
243:
244:
245:
246: /*
247: * Shared Memory Device Ioctl.
248: *
249: * Input: dev = shared memory device (/dev/shm).
250: * com = command to perform (SHMCTL, SHMGET,SHMAT).
251: * vec = pointer to return value, followed by parameters.
252: *
253: * Action: Initiate command.
254: * Save commands return value in *vec.
255: */
256:
257: static
258: shmioctl(dev, com, vec)
259:
260: dev_t dev;
261: int com;
262: int *vec;
263:
264: {
265: switch (com) {
266:
267: case SHMCTL:
268: putusd(vec+0,
269: ushmctl(getusd(vec+1),
270: getusd(vec+2),
271: getusd(vec+3)));
272: break;
273:
274: case SHMGET:
275: putusd(vec+0,
276: ushmget(getusd(vec+1),
277: getusd(vec+2),
278: getusd(vec+3),
279: getusd(vec+4)));
280: break;
281:
282: default:
283: u.u_error = EINVAL;
284: break;
285: }
286: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.