|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * @OSF_FREE_COPYRIGHT@ ! 24: * ! 25: */ ! 26: ! 27: /* Intercept mach console output and supply it to a user application */ ! 28: ! 29: #include <mach_kdb.h> ! 30: ! 31: #include <types.h> ! 32: #include <device/buf.h> ! 33: #include <device/conf.h> ! 34: #include <device/errno.h> ! 35: #include <device/misc_protos.h> ! 36: #include <device/ds_routines.h> ! 37: #include <device/cirbuf.h> ! 38: #include <ppc/console_feed_entries.h> ! 39: #include <ppc/POWERMAC/serial_io.h> ! 40: ! 41: #if MACH_KDB ! 42: #include <ppc/db_machdep.h> ! 43: #endif /* MACH_KDB */ ! 44: ! 45: static struct cirbuf cons_feed_cb; ! 46: static int cons_feed_count = 0; ! 47: io_req_t cons_feed_queued = 0; ! 48: ! 49: /* console feed lock should be taken at splhigh */ ! 50: decl_simple_lock_data(,cons_feed_lock) ! 51: ! 52: boolean_t cons_feed_read_done(io_req_t ior); ! 53: ! 54: io_return_t ! 55: console_feed_open( ! 56: dev_t dev, ! 57: dev_mode_t flag, ! 58: io_req_t ior) ! 59: { ! 60: spl_t s; ! 61: ! 62: simple_lock_init(&cons_feed_lock, ETAP_IO_TTY); ! 63: #if MACH_KDB ! 64: if (console_is_serial()) { ! 65: return D_DEVICE_DOWN; ! 66: } ! 67: #endif /* MACH_KDB */ ! 68: cb_alloc(&cons_feed_cb, CONSOLE_FEED_BUFSIZE); ! 69: s = splhigh(); ! 70: simple_lock(&cons_feed_lock); ! 71: cons_feed_count++; ! 72: simple_unlock(&cons_feed_lock); ! 73: splx(s); ! 74: return D_SUCCESS; ! 75: } ! 76: ! 77: void ! 78: console_feed_close( ! 79: dev_t dev) ! 80: { ! 81: spl_t s; ! 82: ! 83: s = splhigh(); ! 84: simple_lock(&cons_feed_lock); ! 85: cons_feed_count--; ! 86: simple_unlock(&cons_feed_lock); ! 87: splx(s); ! 88: ! 89: console_feed_cancel_and_flush(); ! 90: cb_free(&cons_feed_cb); ! 91: ! 92: return; ! 93: } ! 94: ! 95: /* A routine that can be called from a panic or other problem ! 96: * situation. It switches off the console feed and dumps any ! 97: * remaining buffered information to the original console ! 98: * (usually the screen). It doesn't free up the buffer, since ! 99: * it tries to be as minimal as possible ! 100: */ ! 101: ! 102: void console_feed_cancel_and_flush(void) ! 103: { ! 104: int c; ! 105: spl_t s; ! 106: ! 107: #if NCONSFEED > 0 ! 108: #if MACH_KDB ! 109: if (console_is_serial()) { ! 110: return; ! 111: } ! 112: #endif /* MACH_KDB */ ! 113: ! 114: s = splhigh(); ! 115: simple_lock(&cons_feed_lock); ! 116: if (cons_feed_count == 0) { ! 117: simple_unlock(&cons_feed_lock); ! 118: splx(s); ! 119: return; ! 120: } ! 121: cons_feed_count = 0; ! 122: simple_unlock(&cons_feed_lock); ! 123: splx(s); ! 124: ! 125: do { ! 126: c = getc(&cons_feed_cb); ! 127: if (c == -1) ! 128: break; ! 129: cnputc(c); ! 130: } while (1); ! 131: #endif /* NCONSFEED > 0 */ ! 132: } ! 133: ! 134: io_return_t ! 135: console_feed_read( ! 136: dev_t dev, ! 137: io_req_t ior) ! 138: { ! 139: spl_t s; ! 140: kern_return_t rc; ! 141: int count; ! 142: ! 143: rc = device_read_alloc(ior, (vm_size_t) ior->io_count); ! 144: if (rc != KERN_SUCCESS) ! 145: return rc; ! 146: ! 147: s = splhigh(); ! 148: simple_lock(&cons_feed_lock); ! 149: ! 150: ior->io_residual = ior->io_count; ! 151: ! 152: count = q_to_b(&cons_feed_cb, (char *) ior->io_data, ior->io_count); ! 153: if (count == 0) { ! 154: if (ior->io_mode & D_NOWAIT) { ! 155: rc = D_WOULD_BLOCK; ! 156: } ! 157: if (cons_feed_queued == NULL) { ! 158: ior->io_done = cons_feed_read_done; ! 159: cons_feed_queued = ior; ! 160: rc = D_IO_QUEUED; ! 161: } else { ! 162: /* Can't queue multiple read requests yet */ ! 163: rc = D_INVALID_OPERATION; ! 164: } ! 165: simple_unlock(&cons_feed_lock); ! 166: splx(s); ! 167: return rc; ! 168: } ! 169: ! 170: simple_unlock(&cons_feed_lock); ! 171: splx(s); ! 172: ! 173: ior->io_residual -= count; ! 174: ! 175: iodone(ior); ! 176: ! 177: if (ior->io_op & IO_SYNC) { ! 178: iowait(ior); ! 179: } ! 180: ! 181: return D_SUCCESS; ! 182: } ! 183: ! 184: /* Called when data is ready and there's a queued-up read waiting */ ! 185: boolean_t cons_feed_read_done(io_req_t ior) ! 186: { ! 187: spl_t s; ! 188: int count; ! 189: ! 190: s = splhigh(); ! 191: simple_lock(&cons_feed_lock); ! 192: ! 193: count = q_to_b(&cons_feed_cb, (char *) ior->io_data, ior->io_count); ! 194: if (count == 0) { ! 195: if (cons_feed_queued == NULL) { ! 196: ior->io_done = cons_feed_read_done; ! 197: cons_feed_queued = ior; ! 198: } ! 199: simple_unlock(&cons_feed_lock); ! 200: splx(s); ! 201: return FALSE; ! 202: } ! 203: ! 204: simple_unlock(&cons_feed_lock); ! 205: splx(s); ! 206: ! 207: ior->io_residual -= count; ! 208: ds_read_done(ior); ! 209: ! 210: return TRUE; ! 211: } ! 212: ! 213: /* This routine is called from putc() - it should return TRUE if ! 214: * the character should be passed on to a physical console, FALSE ! 215: * if the feed has intercepted the character. It may be called from ! 216: * under interrupt (even splhigh) ! 217: */ ! 218: ! 219: boolean_t console_feed_putc(char c) ! 220: { ! 221: spl_t s; ! 222: io_req_t ior; ! 223: boolean_t retval; ! 224: ! 225: #if MACH_KDB ! 226: if (db_active) { ! 227: return TRUE; ! 228: } ! 229: #endif /* MACH_KDB */ ! 230: ! 231: retval=TRUE; /* TRUE : character should be displayed now */ ! 232: if (!cons_feed_count) { ! 233: return TRUE; ! 234: } ! 235: s = splhigh(); ! 236: simple_lock(&cons_feed_lock); ! 237: if (!cons_feed_count) { ! 238: simple_unlock(&cons_feed_lock); ! 239: splx(s); ! 240: return TRUE; ! 241: } ! 242: /* queue up the data if we can */ ! 243: if (!putc(c, &cons_feed_cb)) { ! 244: /* able to stock the character */ ! 245: retval = FALSE; ! 246: } ! 247: if (cons_feed_queued != NULL) { ! 248: /* Queued up request - service it */ ! 249: ior = cons_feed_queued; ! 250: cons_feed_queued = NULL; ! 251: simple_unlock(&cons_feed_lock); ! 252: splx(s); ! 253: iodone(ior); ! 254: retval=FALSE; ! 255: } else { ! 256: simple_unlock(&cons_feed_lock); ! 257: splx(s); ! 258: } ! 259: return retval; ! 260: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.