2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
24 #include <i386/cpu_data.h>
25 #include <i386/machine_cpu.h>
26 #include <i386/machine_routines.h>
27 #include <i386/misc_protos.h>
28 #include <vm/vm_kern.h>
29 #include <console/video_console.h>
30 #include <kern/kalloc.h>
38 decl_simple_lock_data(,read_lock
);
39 decl_simple_lock_data(,write_lock
);
42 typedef struct console_buf
{
46 #define CPU_BUFFER_LEN (256 - 3*(sizeof(char*)))
47 char buf
[CPU_BUFFER_LEN
];
55 console_ring
.len
= PAGE_SIZE
;
56 ret
= kmem_alloc(kernel_map
, (vm_offset_t
*) &console_ring
.buffer
,
58 if (ret
!= KERN_SUCCESS
)
59 panic("console_ring_init() "
60 "failed to allocate ring buffer, error %d\n", ret
);
61 console_ring
.used
= 0;
62 console_ring
.read_ptr
= console_ring
.buffer
;
63 console_ring
.write_ptr
= console_ring
.buffer
;
64 simple_lock_init(&console_ring
.read_lock
, 0);
65 simple_lock_init(&console_ring
.write_lock
, 0);
70 console_cpu_alloc(__unused boolean_t boot_processor
)
75 ret
= kmem_alloc(kernel_map
, (vm_offset_t
*) &cbp
,
76 sizeof(console_buf_t
));
77 if (ret
!= KERN_SUCCESS
) {
78 printf("console_cpu_alloc() "
79 "failed to allocate cpu buffer, error=%d\n", ret
);
83 cbp
->buf_base
= (char *) &cbp
->buf
;
84 cbp
->buf_ptr
= cbp
->buf_base
;
85 cbp
->buf_end
= cbp
->buf_base
+ CPU_BUFFER_LEN
;
91 console_cpu_free(void *buf
)
94 kfree((void *) buf
, sizeof(console_buf_t
));
98 console_ring_put(char ch
)
100 if (console_ring
.used
< console_ring
.len
) {
101 console_ring
.used
++;;
102 *console_ring
.write_ptr
++ = ch
;
103 if (console_ring
.write_ptr
- console_ring
.buffer
105 console_ring
.write_ptr
= console_ring
.buffer
;
113 console_ring_get(void)
117 if (console_ring
.used
> 0) {
119 ch
= *console_ring
.read_ptr
++;
120 if (console_ring
.read_ptr
- console_ring
.buffer
122 console_ring
.read_ptr
= console_ring
.buffer
;
128 cpu_buffer_put(console_buf_t
*cbp
, char ch
)
130 if (cbp
->buf_ptr
< cbp
->buf_end
)
131 *(cbp
->buf_ptr
++) = ch
;
145 simple_lock(&console_ring
.read_lock
);
147 simple_unlock(&console_ring
.read_lock
);
155 if (!(real_ncpus
> 1)) {
160 mp_disable_preemption();
161 /* add to stack buf */
162 cbp
= (console_buf_t
*) current_cpu_datap()->cpu_console_buf
;
164 cpu_buffer_put(cbp
, c
);
169 /* Here at end of printf -- time to try to output */
171 /* copy this buffer into the shared ring buffer */
172 state
= ml_set_interrupts_enabled(FALSE
);
173 simple_lock(&console_ring
.write_lock
);
174 for (cp
= cbp
->buf_base
; cp
< cbp
->buf_ptr
; cp
++) {
175 while (!console_ring_put(*cp
))
176 /* spin if share buffer full */
179 (void) console_ring_put('\n');
180 simple_unlock(&console_ring
.write_lock
);
181 ml_set_interrupts_enabled(state
);
182 cbp
->buf_ptr
= cbp
->buf_base
;
185 * Try to get the read lock on the ring buffer to empty it.
186 * If this fails someone else is already emptying...
188 if (simple_lock_try(&console_ring
.read_lock
)) {
192 simple_lock(&console_ring
.write_lock
);
193 ch
= console_ring_get();
194 simple_unlock(&console_ring
.write_lock
);
199 simple_unlock(&console_ring
.read_lock
);
202 mp_enable_preemption();