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