|
|
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.