2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_OSREFERENCE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
32 #include <i386/cpu_data.h>
33 #include <i386/machine_cpu.h>
34 #include <i386/machine_routines.h>
35 #include <i386/misc_protos.h>
36 #include <vm/vm_kern.h>
37 #include <console/video_console.h>
38 #include <kern/kalloc.h>
46 decl_simple_lock_data(,read_lock
);
47 decl_simple_lock_data(,write_lock
);
50 typedef struct console_buf
{
54 #define CPU_BUFFER_LEN (256 - 3*(sizeof(char*)))
55 char buf
[CPU_BUFFER_LEN
];
63 console_ring
.len
= PAGE_SIZE
;
64 ret
= kmem_alloc(kernel_map
, (vm_offset_t
*) &console_ring
.buffer
,
66 if (ret
!= KERN_SUCCESS
)
67 panic("console_ring_init() "
68 "failed to allocate ring buffer, error %d\n", ret
);
69 console_ring
.used
= 0;
70 console_ring
.read_ptr
= console_ring
.buffer
;
71 console_ring
.write_ptr
= console_ring
.buffer
;
72 simple_lock_init(&console_ring
.read_lock
, 0);
73 simple_lock_init(&console_ring
.write_lock
, 0);
78 console_cpu_alloc(__unused boolean_t boot_processor
)
83 ret
= kmem_alloc(kernel_map
, (vm_offset_t
*) &cbp
,
84 sizeof(console_buf_t
));
85 if (ret
!= KERN_SUCCESS
) {
86 printf("console_cpu_alloc() "
87 "failed to allocate cpu buffer, error=%d\n", ret
);
91 cbp
->buf_base
= (char *) &cbp
->buf
;
92 cbp
->buf_ptr
= cbp
->buf_base
;
93 cbp
->buf_end
= cbp
->buf_base
+ CPU_BUFFER_LEN
;
99 console_cpu_free(void *buf
)
102 kfree((void *) buf
, sizeof(console_buf_t
));
106 console_ring_put(char ch
)
108 if (console_ring
.used
< console_ring
.len
) {
109 console_ring
.used
++;;
110 *console_ring
.write_ptr
++ = ch
;
111 if (console_ring
.write_ptr
- console_ring
.buffer
113 console_ring
.write_ptr
= console_ring
.buffer
;
121 console_ring_get(void)
125 if (console_ring
.used
> 0) {
127 ch
= *console_ring
.read_ptr
++;
128 if (console_ring
.read_ptr
- console_ring
.buffer
130 console_ring
.read_ptr
= console_ring
.buffer
;
136 cpu_buffer_put(console_buf_t
*cbp
, char ch
)
138 if (cbp
->buf_ptr
< cbp
->buf_end
)
139 *(cbp
->buf_ptr
++) = ch
;
153 simple_lock(&console_ring
.read_lock
);
155 simple_unlock(&console_ring
.read_lock
);
163 if (!(real_ncpus
> 1)) {
168 mp_disable_preemption();
169 /* add to stack buf */
170 cbp
= (console_buf_t
*) current_cpu_datap()->cpu_console_buf
;
172 cpu_buffer_put(cbp
, c
);
177 /* Here at end of printf -- time to try to output */
179 /* copy this buffer into the shared ring buffer */
180 state
= ml_set_interrupts_enabled(FALSE
);
181 simple_lock(&console_ring
.write_lock
);
182 for (cp
= cbp
->buf_base
; cp
< cbp
->buf_ptr
; cp
++) {
183 while (!console_ring_put(*cp
))
184 /* spin if share buffer full */
187 (void) console_ring_put('\n');
188 simple_unlock(&console_ring
.write_lock
);
189 ml_set_interrupts_enabled(state
);
190 cbp
->buf_ptr
= cbp
->buf_base
;
193 * Try to get the read lock on the ring buffer to empty it.
194 * If this fails someone else is already emptying...
196 if (simple_lock_try(&console_ring
.read_lock
)) {
200 simple_lock(&console_ring
.write_lock
);
201 ch
= console_ring_get();
202 simple_unlock(&console_ring
.write_lock
);
207 simple_unlock(&console_ring
.read_lock
);
210 mp_enable_preemption();