|
|
1.1 root 1: /* GNU Mach Kernel Message Device.
2: Copyright (C) 1998, 1999 Free Software Foundation, Inc.
3: Written by OKUJI Yoshinori.
4:
5: This is free software; you can redistribute it and/or modify
6: it under the terms of the GNU General Public License as published by
7: the Free Software Foundation; either version 2, or (at your option)
8: any later version.
9:
10: This software is distributed in the hope that it will be useful,
11: but WITHOUT ANY WARRANTY; without even the implied warranty of
12: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13: GNU General Public License for more details.
14:
15: You should have received a copy of the GNU General Public License
16: along with the software; see the file COPYING. If not, write to
17: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
18:
19: /* Now kmsg provides stream interface, not random access methods. */
20:
21: #include <sys/types.h>
22: #include <device/conf.h>
23: #include <device/io_req.h>
24: #include <mach/boolean.h>
25: #include <kern/lock.h>
26: #include <kmsg.h>
27:
28:
29: #define KMSGBUFSIZE (4096) /* XXX */
30:
31: /* Simple array for buffering messages */
32: static char kmsg_buffer[KMSGBUFSIZE];
33: /* Point to the offset to write */
34: static int kmsg_write_offset;
35: /* Point to the offset to read */
36: static int kmsg_read_offset;
37: /* I/O request queue for blocking read */
38: static queue_head_t kmsg_read_queue;
39: /* Used for exclusive access to the device */
40: static int kmsg_in_use;
41: /* Used for exclusive access to the routines */
42: static simple_lock_data_t kmsg_lock;
43: /* If already initialized or not */
44: static int kmsg_init_done = 0;
45:
46: /* Kernel Message Initializer */
47: static void
48: kmsginit (void)
49: {
50: kmsg_write_offset = 0;
51: kmsg_read_offset = 0;
52: queue_init (&kmsg_read_queue);
53: kmsg_in_use = 0;
54: simple_lock_init (&kmsg_lock);
55: }
56:
57: /* Kernel Message Open Handler */
58: io_return_t
59: kmsgopen (dev_t dev, int flag, io_req_t ior)
60: {
61: simple_lock (&kmsg_lock);
62: if (kmsg_in_use)
63: {
64: simple_unlock (&kmsg_lock);
65: return D_ALREADY_OPEN;
66: }
67:
68: kmsg_in_use = 1;
69:
70: simple_unlock (&kmsg_lock);
71: return D_SUCCESS;
72: }
73:
74: /* Kernel Message Close Handler */
75: io_return_t
76: kmsgclose (dev_t dev, int flag)
77: {
78: simple_lock (&kmsg_lock);
79: kmsg_in_use = 0;
80:
81: simple_unlock (&kmsg_lock);
82: return D_SUCCESS;
83: }
84:
85: static boolean_t kmsg_read_done (io_req_t ior);
86:
87: /* Kernel Message Read Handler */
88: io_return_t
89: kmsgread (dev_t dev, io_req_t ior)
90: {
91: int err;
92: int amt, len;
93:
94: err = device_read_alloc (ior, ior->io_count);
95: if (err != KERN_SUCCESS)
96: return err;
97:
98: simple_lock (&kmsg_lock);
99: if (kmsg_read_offset == kmsg_write_offset)
100: {
101: /* The queue is empty. */
102: if (ior->io_mode & D_NOWAIT)
103: {
104: simple_unlock (&kmsg_lock);
105: return D_WOULD_BLOCK;
106: }
107:
108: ior->io_done = kmsg_read_done;
109: enqueue_tail (&kmsg_read_queue, ior);
110: simple_unlock (&kmsg_lock);
111: return D_IO_QUEUED;
112: }
113:
114: len = kmsg_write_offset - kmsg_read_offset;
115: if (len < 0)
116: len += KMSGBUFSIZE;
117:
118: amt = ior->io_count;
119: if (amt > len)
120: amt = len;
121:
122: if (kmsg_read_offset + amt <= KMSGBUFSIZE)
123: {
124: memcpy (ior->io_data, kmsg_buffer + kmsg_read_offset, amt);
125: }
126: else
127: {
128: int cnt;
129:
130: cnt = KMSGBUFSIZE - kmsg_read_offset;
131: memcpy (ior->io_data, kmsg_buffer + kmsg_read_offset, cnt);
132: memcpy (ior->io_data + cnt, kmsg_buffer, amt - cnt);
133: }
134:
135: kmsg_read_offset += amt;
136: if (kmsg_read_offset >= KMSGBUFSIZE)
137: kmsg_read_offset -= KMSGBUFSIZE;
138:
139: ior->io_residual = ior->io_count - amt;
140:
141: simple_unlock (&kmsg_lock);
142: return D_SUCCESS;
143: }
144:
145: static boolean_t
146: kmsg_read_done (io_req_t ior)
147: {
148: int err;
149: int amt, len;
150:
151: simple_lock (&kmsg_lock);
152: if (kmsg_read_offset == kmsg_write_offset)
153: {
154: /* The queue is empty. */
155: ior->io_done = kmsg_read_done;
156: enqueue_tail (&kmsg_read_queue, ior);
157: simple_unlock (&kmsg_lock);
158: return FALSE;
159: }
160:
161: len = kmsg_write_offset - kmsg_read_offset;
162: if (len < 0)
163: len += KMSGBUFSIZE;
164:
165: amt = ior->io_count;
166: if (amt > len)
167: amt = len;
168:
169: if (kmsg_read_offset + amt <= KMSGBUFSIZE)
170: {
171: memcpy (ior->io_data, kmsg_buffer + kmsg_read_offset, amt);
172: }
173: else
174: {
175: int cnt;
176:
177: cnt = KMSGBUFSIZE - kmsg_read_offset;
178: memcpy (ior->io_data, kmsg_buffer + kmsg_read_offset, cnt);
179: memcpy (ior->io_data + cnt, kmsg_buffer, amt - cnt);
180: }
181:
182: kmsg_read_offset += amt;
183: if (kmsg_read_offset >= KMSGBUFSIZE)
184: kmsg_read_offset -= KMSGBUFSIZE;
185:
186: ior->io_residual = ior->io_count - amt;
187:
188: simple_unlock (&kmsg_lock);
189: ds_read_done (ior);
190:
191: return TRUE;
192: }
193:
194: io_return_t
195: kmsggetstat (dev_t dev, int flavor, int *data, unsigned int *count)
196: {
197: switch (flavor)
198: {
199: case DEV_GET_SIZE:
200: data[DEV_GET_SIZE_DEVICE_SIZE] = 0;
201: data[DEV_GET_SIZE_RECORD_SIZE] = 1;
202: *count = DEV_GET_SIZE_COUNT;
203: break;
204:
205: default:
206: return D_INVALID_OPERATION;
207: }
208:
209: return D_SUCCESS;
210: }
211:
212: /* Write to Kernel Message Buffer */
213: void
214: kmsg_putchar (int c)
215: {
216: io_req_t ior;
217: int offset;
218:
219: /* XXX: cninit is not called before cnputc is used. So call kmsginit
220: here if not initialized yet. */
221: if (!kmsg_init_done)
222: {
223: kmsginit ();
224: kmsg_init_done = 1;
225: }
226:
227: simple_lock (&kmsg_lock);
228: offset = kmsg_write_offset + 1;
229: if (offset == KMSGBUFSIZE)
230: offset = 0;
231:
232: if (offset == kmsg_read_offset)
233: {
234: /* Discard C. */
235: simple_unlock (&kmsg_lock);
236: return;
237: }
238:
239: kmsg_buffer[kmsg_write_offset++] = c;
240: if (kmsg_write_offset == KMSGBUFSIZE)
241: kmsg_write_offset = 0;
242:
243: while ((ior = (io_req_t) dequeue_head (&kmsg_read_queue)) != NULL)
244: iodone (ior);
245:
246: simple_unlock (&kmsg_lock);
247: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.