|
|
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 */ 45: static int kmsg_in_use; 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 */ 49: static int kmsg_init_done = 0; 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); 58: kmsg_in_use = 0; 59: simple_lock_init (&kmsg_lock); 60: } 61: 62: /* Kernel Message Open Handler */ 63: io_return_t 64: kmsgopen (dev_t dev, int flag, io_req_t ior) 65: { 66: simple_lock (&kmsg_lock); 67: if (kmsg_in_use) 68: { 69: simple_unlock (&kmsg_lock); 70: return D_ALREADY_OPEN; 71: } 72: 73: kmsg_in_use = 1; 74: 75: simple_unlock (&kmsg_lock); 76: return D_SUCCESS; 77: } 78: 79: /* Kernel Message Close Handler */ 80: io_return_t 81: kmsgclose (dev_t dev, int flag) 82: { 83: simple_lock (&kmsg_lock); 84: kmsg_in_use = 0; 85: 86: simple_unlock (&kmsg_lock); 87: return D_SUCCESS; 88: } 89: 90: static boolean_t kmsg_read_done (io_req_t ior); 91: 92: /* Kernel Message Read Handler */ 93: io_return_t 94: kmsgread (dev_t dev, io_req_t ior) 95: { 96: int err; 97: int amt, len; 98: 99: err = device_read_alloc (ior, ior->io_count); 100: if (err != KERN_SUCCESS) 101: return err; 102: 103: simple_lock (&kmsg_lock); 104: if (kmsg_read_offset == kmsg_write_offset) 105: { 106: /* The queue is empty. */ 107: if (ior->io_mode & D_NOWAIT) 108: { 109: simple_unlock (&kmsg_lock); 110: return D_WOULD_BLOCK; 111: } 112: 113: ior->io_done = kmsg_read_done; 1.1.1.2 ! root 114: enqueue_tail (&kmsg_read_queue, (queue_entry_t) ior); 1.1 root 115: simple_unlock (&kmsg_lock); 116: return D_IO_QUEUED; 117: } 118: 119: len = kmsg_write_offset - kmsg_read_offset; 120: if (len < 0) 121: len += KMSGBUFSIZE; 122: 123: amt = ior->io_count; 124: if (amt > len) 125: amt = len; 126: 127: if (kmsg_read_offset + amt <= KMSGBUFSIZE) 128: { 129: memcpy (ior->io_data, kmsg_buffer + kmsg_read_offset, amt); 130: } 131: else 132: { 133: int cnt; 134: 135: cnt = KMSGBUFSIZE - kmsg_read_offset; 136: memcpy (ior->io_data, kmsg_buffer + kmsg_read_offset, cnt); 137: memcpy (ior->io_data + cnt, kmsg_buffer, amt - cnt); 138: } 139: 140: kmsg_read_offset += amt; 141: if (kmsg_read_offset >= KMSGBUFSIZE) 142: kmsg_read_offset -= KMSGBUFSIZE; 143: 144: ior->io_residual = ior->io_count - amt; 145: 146: simple_unlock (&kmsg_lock); 147: return D_SUCCESS; 148: } 149: 150: static boolean_t 151: kmsg_read_done (io_req_t ior) 152: { 153: int amt, len; 154: 155: simple_lock (&kmsg_lock); 156: if (kmsg_read_offset == kmsg_write_offset) 157: { 158: /* The queue is empty. */ 159: ior->io_done = kmsg_read_done; 1.1.1.2 ! root 160: enqueue_tail (&kmsg_read_queue, (queue_entry_t) ior); 1.1 root 161: simple_unlock (&kmsg_lock); 162: return FALSE; 163: } 164: 165: len = kmsg_write_offset - kmsg_read_offset; 166: if (len < 0) 167: len += KMSGBUFSIZE; 168: 169: amt = ior->io_count; 170: if (amt > len) 171: amt = len; 172: 173: if (kmsg_read_offset + amt <= KMSGBUFSIZE) 174: { 175: memcpy (ior->io_data, kmsg_buffer + kmsg_read_offset, amt); 176: } 177: else 178: { 179: int cnt; 180: 181: cnt = KMSGBUFSIZE - kmsg_read_offset; 182: memcpy (ior->io_data, kmsg_buffer + kmsg_read_offset, cnt); 183: memcpy (ior->io_data + cnt, kmsg_buffer, amt - cnt); 184: } 185: 186: kmsg_read_offset += amt; 187: if (kmsg_read_offset >= KMSGBUFSIZE) 188: kmsg_read_offset -= KMSGBUFSIZE; 189: 190: ior->io_residual = ior->io_count - amt; 191: 192: simple_unlock (&kmsg_lock); 193: ds_read_done (ior); 194: 195: return TRUE; 196: } 197: 198: io_return_t 199: kmsggetstat (dev_t dev, int flavor, int *data, unsigned int *count) 200: { 201: switch (flavor) 202: { 203: case DEV_GET_SIZE: 204: data[DEV_GET_SIZE_DEVICE_SIZE] = 0; 205: data[DEV_GET_SIZE_RECORD_SIZE] = 1; 206: *count = DEV_GET_SIZE_COUNT; 207: break; 208: 209: default: 210: return D_INVALID_OPERATION; 211: } 212: 213: return D_SUCCESS; 214: } 215: 216: /* Write to Kernel Message Buffer */ 217: void 218: kmsg_putchar (int c) 219: { 220: io_req_t ior; 221: int offset; 222: 223: /* XXX: cninit is not called before cnputc is used. So call kmsginit 224: here if not initialized yet. */ 225: if (!kmsg_init_done) 226: { 227: kmsginit (); 228: kmsg_init_done = 1; 229: } 230: 231: simple_lock (&kmsg_lock); 232: offset = kmsg_write_offset + 1; 233: if (offset == KMSGBUFSIZE) 234: offset = 0; 235: 236: if (offset == kmsg_read_offset) 237: { 238: /* Discard C. */ 239: simple_unlock (&kmsg_lock); 240: return; 241: } 242: 243: kmsg_buffer[kmsg_write_offset++] = c; 244: if (kmsg_write_offset == KMSGBUFSIZE) 245: kmsg_write_offset = 0; 246: 247: while ((ior = (io_req_t) dequeue_head (&kmsg_read_queue)) != NULL) 248: iodone (ior); 249: 250: simple_unlock (&kmsg_lock); 251: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.