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