source: rtems/c/src/lib/libbsp/powerpc/shared/console/polled_io.c @ 4f3e4f33

4.104.114.84.95
Last change on this file since 4f3e4f33 was 4f3e4f33, checked in by Joel Sherrill <joel.sherrill@…>, on Feb 20, 2003 at 9:32:07 PM

2003-02-20 Till Straumann <strauman@…>

PR 349/bsps

  • console/console.c, console/uart.c, console/uart.h: implement IOCTLs for the serial (UART) console to install/retrieve a BREAK-IRQ callback. The callback routine (if installed) is invoked from the UART ISR when a BREAK interrupt is detected. This can be used e.g. to enforce a "hotkey" reboot a la vxWorks Ctrl-X (although we use the serial line break condition) NOTE: The callback runs in ISR context.
  • Property mode set to 100644
File size: 28.8 KB
Line 
1/*
2 *  polled_io.c -- Basic input/output for early boot
3 *
4 *  Copyright (C) 1998, 1999 Gabriel Paubert, paubert@iram.es
5 *
6 *  Modified to compile in RTEMS development environment
7 *  by Eric Valette
8 *
9 *  Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
10 *
11 *  The license and distribution terms for this file may be
12 *  found in found in the file LICENSE in this distribution or at
13 *  http://www.OARcorp.com/rtems/license.html.
14 *
15 * $Id$
16 */
17
18#include <rtems/system.h>
19#include <sys/types.h>
20#include <libcpu/byteorder.h>
21#include <libcpu/page.h>
22#include <libcpu/mmu.h>
23#include <libcpu/io.h>
24#include <string.h>
25#include <stdarg.h>
26#include <bsp/consoleIo.h>
27#include <bsp.h>
28#include <libcpu/spr.h>
29
30#ifdef BSP_KBD_IOBASE
31#define USE_KBD_SUPPORT
32#endif
33#ifdef BSP_VGA_IOBASE
34#define USE_VGA_SUPPORT
35#endif
36
37#ifdef USE_KBD_SUPPORT
38#include "keyboard.h"
39#endif
40#include "console.inl"
41
42#ifdef __BOOT__
43extern void boot_udelay();
44void * __palloc(u_long);
45void  pfree(void *);
46
47#endif
48
49typedef unsigned long long u64;
50typedef long long s64;
51typedef unsigned int u32;
52
53#ifdef USE_KBD_SUPPORT
54unsigned short plain_map[NR_KEYS] = {
55        0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036,
56        0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf07f, 0xf009,
57        0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
58        0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201, 0xf702, 0xfb61, 0xfb73,
59        0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b,
60        0xf027, 0xf060, 0xf700, 0xf05c, 0xfb7a, 0xfb78, 0xfb63, 0xfb76,
61        0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf700, 0xf30c,
62        0xf703, 0xf020, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
63        0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf209, 0xf307,
64        0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
65        0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03c, 0xf10a,
66        0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
67        0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
68        0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
69        0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
70        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
71};
72
73unsigned short shift_map[NR_KEYS] = {
74        0xf200, 0xf01b, 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e,
75        0xf026, 0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf07f, 0xf009,
76        0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, 0xfb59, 0xfb55, 0xfb49,
77        0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf201, 0xf702, 0xfb41, 0xfb53,
78        0xfb44, 0xfb46, 0xfb47, 0xfb48, 0xfb4a, 0xfb4b, 0xfb4c, 0xf03a,
79        0xf022, 0xf07e, 0xf700, 0xf07c, 0xfb5a, 0xfb58, 0xfb43, 0xfb56,
80        0xfb42, 0xfb4e, 0xfb4d, 0xf03c, 0xf03e, 0xf03f, 0xf700, 0xf30c,
81        0xf703, 0xf020, 0xf207, 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf10e,
82        0xf10f, 0xf110, 0xf111, 0xf112, 0xf113, 0xf213, 0xf203, 0xf307,
83        0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
84        0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03e, 0xf10a,
85        0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
86        0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
87        0xf20b, 0xf601, 0xf602, 0xf117, 0xf600, 0xf20a, 0xf115, 0xf116,
88        0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
89        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
90};
91
92unsigned short altgr_map[NR_KEYS] = {
93        0xf200, 0xf200, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200,
94        0xf07b, 0xf05b, 0xf05d, 0xf07d, 0xf05c, 0xf200, 0xf200, 0xf200,
95        0xfb71, 0xfb77, 0xf918, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
96        0xfb6f, 0xfb70, 0xf200, 0xf07e, 0xf201, 0xf702, 0xf914, 0xfb73,
97        0xf917, 0xf919, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf200,
98        0xf200, 0xf200, 0xf700, 0xf200, 0xfb7a, 0xfb78, 0xf916, 0xfb76,
99        0xf915, 0xfb6e, 0xfb6d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
100        0xf703, 0xf200, 0xf207, 0xf50c, 0xf50d, 0xf50e, 0xf50f, 0xf510,
101        0xf511, 0xf512, 0xf513, 0xf514, 0xf515, 0xf208, 0xf202, 0xf911,
102        0xf912, 0xf913, 0xf30b, 0xf90e, 0xf90f, 0xf910, 0xf30a, 0xf90b,
103        0xf90c, 0xf90d, 0xf90a, 0xf310, 0xf206, 0xf200, 0xf07c, 0xf516,
104        0xf517, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
105        0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
106        0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
107        0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
108        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
109};
110
111unsigned short ctrl_map[NR_KEYS] = {
112        0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e,
113        0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200,
114        0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
115        0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013,
116        0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
117        0xf007, 0xf000, 0xf700, 0xf01c, 0xf01a, 0xf018, 0xf003, 0xf016,
118        0xf002, 0xf00e, 0xf00d, 0xf200, 0xf20e, 0xf07f, 0xf700, 0xf30c,
119        0xf703, 0xf000, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
120        0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf204, 0xf307,
121        0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
122        0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf10a,
123        0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
124        0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
125        0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
126        0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
127        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
128};
129
130unsigned short shift_ctrl_map[NR_KEYS] = {
131        0xf200, 0xf200, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200,
132        0xf200, 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200,
133        0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
134        0xf00f, 0xf010, 0xf200, 0xf200, 0xf201, 0xf702, 0xf001, 0xf013,
135        0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
136        0xf200, 0xf200, 0xf700, 0xf200, 0xf01a, 0xf018, 0xf003, 0xf016,
137        0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
138        0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
139        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf208, 0xf200, 0xf307,
140        0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
141        0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf200,
142        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
143        0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
144        0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
145        0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
146        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
147};
148
149unsigned short alt_map[NR_KEYS] = {
150        0xf200, 0xf81b, 0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836,
151        0xf837, 0xf838, 0xf839, 0xf830, 0xf82d, 0xf83d, 0xf87f, 0xf809,
152        0xf871, 0xf877, 0xf865, 0xf872, 0xf874, 0xf879, 0xf875, 0xf869,
153        0xf86f, 0xf870, 0xf85b, 0xf85d, 0xf80d, 0xf702, 0xf861, 0xf873,
154        0xf864, 0xf866, 0xf867, 0xf868, 0xf86a, 0xf86b, 0xf86c, 0xf83b,
155        0xf827, 0xf860, 0xf700, 0xf85c, 0xf87a, 0xf878, 0xf863, 0xf876,
156        0xf862, 0xf86e, 0xf86d, 0xf82c, 0xf82e, 0xf82f, 0xf700, 0xf30c,
157        0xf703, 0xf820, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
158        0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf209, 0xf907,
159        0xf908, 0xf909, 0xf30b, 0xf904, 0xf905, 0xf906, 0xf30a, 0xf901,
160        0xf902, 0xf903, 0xf900, 0xf310, 0xf206, 0xf200, 0xf83c, 0xf50a,
161        0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
162        0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
163        0xf118, 0xf210, 0xf211, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
164        0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
165        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
166};
167
168unsigned short ctrl_alt_map[NR_KEYS] = {
169        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
170        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
171        0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809,
172        0xf80f, 0xf810, 0xf200, 0xf200, 0xf201, 0xf702, 0xf801, 0xf813,
173        0xf804, 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c, 0xf200,
174        0xf200, 0xf200, 0xf700, 0xf200, 0xf81a, 0xf818, 0xf803, 0xf816,
175        0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
176        0xf703, 0xf200, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
177        0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf200, 0xf307,
178        0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
179        0xf302, 0xf303, 0xf300, 0xf20c, 0xf206, 0xf200, 0xf200, 0xf50a,
180        0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
181        0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
182        0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf20c,
183        0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
184        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
185};
186
187ushort *key_maps[MAX_NR_KEYMAPS] = {
188        plain_map, shift_map, altgr_map, 0,
189        ctrl_map, shift_ctrl_map, 0, 0,
190        alt_map, 0, 0, 0,
191        ctrl_alt_map,   0
192};
193
194unsigned int keymap_count = 7;
195
196/*
197 * Philosophy: most people do not define more strings, but they who do
198 * often want quite a lot of string space. So, we statically allocate
199 * the default and allocate dynamically in chunks of 512 bytes.
200 */
201
202char func_buf[] = {
203        '\033', '[', '[', 'A', 0, 
204        '\033', '[', '[', 'B', 0, 
205        '\033', '[', '[', 'C', 0, 
206        '\033', '[', '[', 'D', 0, 
207        '\033', '[', '[', 'E', 0, 
208        '\033', '[', '1', '7', '~', 0, 
209        '\033', '[', '1', '8', '~', 0, 
210        '\033', '[', '1', '9', '~', 0, 
211        '\033', '[', '2', '0', '~', 0, 
212        '\033', '[', '2', '1', '~', 0, 
213        '\033', '[', '2', '3', '~', 0, 
214        '\033', '[', '2', '4', '~', 0, 
215        '\033', '[', '2', '5', '~', 0, 
216        '\033', '[', '2', '6', '~', 0, 
217        '\033', '[', '2', '8', '~', 0, 
218        '\033', '[', '2', '9', '~', 0, 
219        '\033', '[', '3', '1', '~', 0, 
220        '\033', '[', '3', '2', '~', 0, 
221        '\033', '[', '3', '3', '~', 0, 
222        '\033', '[', '3', '4', '~', 0, 
223        '\033', '[', '1', '~', 0, 
224        '\033', '[', '2', '~', 0, 
225        '\033', '[', '3', '~', 0, 
226        '\033', '[', '4', '~', 0, 
227        '\033', '[', '5', '~', 0, 
228        '\033', '[', '6', '~', 0, 
229        '\033', '[', 'M', 0, 
230        '\033', '[', 'P', 0, 
231};
232
233char *funcbufptr = func_buf;
234int funcbufsize = sizeof(func_buf);
235int funcbufleft = 0;          /* space left */
236
237char *func_table[MAX_NR_FUNC] = {
238        func_buf + 0,
239        func_buf + 5,
240        func_buf + 10,
241        func_buf + 15,
242        func_buf + 20,
243        func_buf + 25,
244        func_buf + 31,
245        func_buf + 37,
246        func_buf + 43,
247        func_buf + 49,
248        func_buf + 55,
249        func_buf + 61,
250        func_buf + 67,
251        func_buf + 73,
252        func_buf + 79,
253        func_buf + 85,
254        func_buf + 91,
255        func_buf + 97,
256        func_buf + 103,
257        func_buf + 109,
258        func_buf + 115,
259        func_buf + 120,
260        func_buf + 125,
261        func_buf + 130,
262        func_buf + 135,
263        func_buf + 140,
264        func_buf + 145,
265        0,
266        0,
267        func_buf + 149,
268        0,
269};
270
271struct kbdiacr {
272        unsigned char diacr, base, result;
273};
274
275struct kbdiacr accent_table[MAX_DIACR] = {
276        {'`', 'A', '\300'},     {'`', 'a', '\340'},
277        {'\'', 'A', '\301'},    {'\'', 'a', '\341'},
278        {'^', 'A', '\302'},     {'^', 'a', '\342'},
279        {'~', 'A', '\303'},     {'~', 'a', '\343'},
280        {'"', 'A', '\304'},     {'"', 'a', '\344'},
281        {'O', 'A', '\305'},     {'o', 'a', '\345'},
282        {'0', 'A', '\305'},     {'0', 'a', '\345'},
283        {'A', 'A', '\305'},     {'a', 'a', '\345'},
284        {'A', 'E', '\306'},     {'a', 'e', '\346'},
285        {',', 'C', '\307'},     {',', 'c', '\347'},
286        {'`', 'E', '\310'},     {'`', 'e', '\350'},
287        {'\'', 'E', '\311'},    {'\'', 'e', '\351'},
288        {'^', 'E', '\312'},     {'^', 'e', '\352'},
289        {'"', 'E', '\313'},     {'"', 'e', '\353'},
290        {'`', 'I', '\314'},     {'`', 'i', '\354'},
291        {'\'', 'I', '\315'},    {'\'', 'i', '\355'},
292        {'^', 'I', '\316'},     {'^', 'i', '\356'},
293        {'"', 'I', '\317'},     {'"', 'i', '\357'},
294        {'-', 'D', '\320'},     {'-', 'd', '\360'},
295        {'~', 'N', '\321'},     {'~', 'n', '\361'},
296        {'`', 'O', '\322'},     {'`', 'o', '\362'},
297        {'\'', 'O', '\323'},    {'\'', 'o', '\363'},
298        {'^', 'O', '\324'},     {'^', 'o', '\364'},
299        {'~', 'O', '\325'},     {'~', 'o', '\365'},
300        {'"', 'O', '\326'},     {'"', 'o', '\366'},
301        {'/', 'O', '\330'},     {'/', 'o', '\370'},
302        {'`', 'U', '\331'},     {'`', 'u', '\371'},
303        {'\'', 'U', '\332'},    {'\'', 'u', '\372'},
304        {'^', 'U', '\333'},     {'^', 'u', '\373'},
305        {'"', 'U', '\334'},     {'"', 'u', '\374'},
306        {'\'', 'Y', '\335'},    {'\'', 'y', '\375'},
307        {'T', 'H', '\336'},     {'t', 'h', '\376'},
308        {'s', 's', '\337'},     {'"', 'y', '\377'},
309        {'s', 'z', '\337'},     {'i', 'j', '\377'},
310};
311
312unsigned int accent_table_size = 68;
313
314
315
316
317/* These #defines have been copied from drivers/char/pc_keyb.h, by
318 * Martin Mares (mj@ucw.cz). 
319 * converted to offsets by Till Straumann <strauman@slac.stanford.edu>
320 */
321#define KBD_STATUS_REG          0x4     /* Status register (R) */
322#define KBD_CNTL_REG            0x4     /* Controller command register (W) */
323#define KBD_DATA_REG            0x0     /* Keyboard data register (R/W) */
324
325/*
326 *      Keyboard Controller Commands
327 */
328
329#define KBD_CCMD_WRITE_MODE     0x60    /* Write mode bits */
330#define KBD_CCMD_GET_VERSION    0xA1    /* Get controller version */
331#define KBD_CCMD_MOUSE_DISABLE  0xA7    /* Disable mouse interface */
332#define KBD_CCMD_MOUSE_ENABLE   0xA8    /* Enable mouse interface */
333#define KBD_CCMD_TEST_MOUSE     0xA9    /* Mouse interface test */
334#define KBD_CCMD_SELF_TEST      0xAA    /* Controller self test */
335#define KBD_CCMD_KBD_TEST       0xAB    /* Keyboard interface test */
336#define KBD_CCMD_KBD_DISABLE    0xAD    /* Keyboard interface disable */
337#define KBD_CCMD_KBD_ENABLE     0xAE    /* Keyboard interface enable */
338
339/*
340 *      Keyboard Commands
341 */
342
343#define KBD_CMD_ENABLE          0xF4    /* Enable scanning */
344#define KBD_CMD_DISABLE         0xF5    /* Disable scanning */
345#define KBD_CMD_RESET           0xFF    /* Reset */
346
347/*
348 *      Keyboard Replies
349 */
350
351#define KBD_REPLY_POR           0xAA    /* Power on reset */
352#define KBD_REPLY_ACK           0xFA    /* Command ACK */
353#define KBD_REPLY_RESEND        0xFE    /* Command NACK, send the cmd again */
354
355/*
356 *      Status Register Bits
357 */
358
359#define KBD_STAT_OBF            0x01    /* Keyboard output buffer full */
360#define KBD_STAT_IBF            0x02    /* Keyboard input buffer full */
361#define KBD_STAT_UNLOCKED       0x10    /* Zero if keyboard locked */
362#define KBD_STAT_GTO            0x40    /* General receive/xmit timeout */
363#define KBD_STAT_PERR           0x80    /* Parity error */
364
365/*
366 *      Controller Mode Register Bits
367 */
368
369#define KBD_MODE_KBD_INT        0x01    /* Keyboard data generate IRQ1 */
370#define KBD_MODE_SYS            0x04    /* The system flag (?) */
371#define KBD_MODE_NO_KEYLOCK     0x08    /* The keylock doesn't affect the keyboard if set */
372#define KBD_MODE_DISABLE_KBD    0x10    /* Disable keyboard interface */
373#define KBD_MODE_DISABLE_MOUSE  0x20    /* Disable mouse interface */
374#define KBD_MODE_KCC            0x40    /* Scan code conversion to PC format */
375#define KBD_MODE_RFU            0x80
376
377SPR_RW(DEC)
378SPR_RO(PVR)
379
380#endif /* USE_KBD_SUPPORT */
381
382
383/* Early messages after mm init but before console init are kept in log
384 * buffers.
385 */
386#define PAGE_LOG_CHARS (PAGE_SIZE-sizeof(int)-sizeof(u_long)-1)
387
388typedef struct _console_log {
389        struct _console_log *next;
390        int offset;
391        u_char data[PAGE_LOG_CHARS];
392} console_log;
393
394#ifdef STATIC_LOG_ALLOC
395
396#define STATIC_LOG_DATA_PAGE_NB 3
397
398static  u_char  log_page_pool   [STATIC_LOG_DATA_PAGE_NB * PAGE_SIZE];
399
400#endif
401
402static board_memory_map mem_map = {
403  (__io_ptr) _IO_BASE,          /* from libcpu/io.h */
404  (__io_ptr) _ISA_MEM_BASE,
405};
406
407board_memory_map *ptr_mem_map = &mem_map;
408
409
410struct _console_global_data {
411        console_log *log;
412        int vacuum_sent;
413        int lines;
414        int cols;
415        int orig_x;
416        int orig_y;
417        u_char shfts, ctls, alts, caps;
418} console_global_data = {NULL, 0, 25, 80, 0, 24, 0, 0, 0, 0};
419
420typedef struct console_io {
421        void    (*putc) (const u_char);
422        int     (*getc) (void);
423        int     (*tstc) (void);
424}console_io;
425
426extern console_io* curIo;
427
428void debug_putc(const u_char c)
429{
430  curIo->putc(c);
431}
432
433int debug_getc(void)
434{
435  return curIo->getc();
436}
437
438int debug_tstc(void)
439{
440  return curIo->tstc();
441}
442
443
444
445#define vidmem ((__io_ptr)(ptr_mem_map->isa_mem_base+0xb8000))
446
447void vacuum_putc(u_char c) {
448        console_global_data.vacuum_sent++;
449}
450
451int vacuum_getc(void) {
452        return -1;
453}
454
455int vacuum_tstc(void) {
456        return 0;
457}
458
459/*
460 * COM1 NS16550 support
461 */
462
463#define rbr 0
464#define ier 1
465#define fcr 2
466#define lcr 3
467#define mcr 4
468#define lsr 5
469#define msr 6
470#define scr 7
471#define thr rbr
472#define iir fcr
473#define dll rbr
474#define dlm ier
475
476#define LSR_DR   0x01  /* Data ready */
477#define LSR_OE   0x02  /* Overrun */
478#define LSR_PE   0x04  /* Parity error */
479#define LSR_FE   0x08  /* Framing error */
480#define LSR_BI   0x10  /* Break */
481#define LSR_THRE 0x20  /* Xmit holding register empty */
482#define LSR_TEMT 0x40  /* Xmitter empty */
483#define LSR_ERR  0x80  /* Error */
484
485
486#ifdef STATIC_LOG_ALLOC
487static int global_index = 0;
488
489static void *__palloc(int s)
490{
491  if (global_index ==( STATIC_LOG_DATA_PAGE_NB - 1) ) return (void*) 0;
492  return  (void*) &(log_page_pool [PAGE_SIZE * global_index++]);
493}
494
495static void pfree(void* p)
496{
497  --global_index;
498}
499#endif
500 
501
502void log_putc(const u_char c) {
503        console_log *l;
504        for(l=console_global_data.log; l; l=l->next) {
505                if (l->offset<PAGE_LOG_CHARS) break;
506        }
507        if (!l) {
508                l=__palloc(sizeof(console_log));
509                memset(l, 0, sizeof(console_log));
510                if (!console_global_data.log) 
511                        console_global_data.log = l;
512                else {
513                        console_log *p;
514                        for (p=console_global_data.log; 
515                             p->next; p=p->next);
516                        p->next = l;
517                }
518        }
519        l->data[l->offset++] = c;
520}
521
522/* This puts is non standard since it does not automatically add a newline
523 * at the end. So it is made private to avoid confusion in other files.
524 */
525static 
526void puts(const u_char *s)
527{
528        char c;
529
530        while ( ( c = *s++ ) != '\0' ) {
531                debug_putc(c);
532                if ( c == '\n' )
533                        debug_putc('\r');
534        }
535}
536
537
538static
539void flush_log(void) {
540        console_log *p, *next;
541        if (console_global_data.vacuum_sent) {
542#ifdef TRACE_FLUSH_LOG   
543                printk("%d characters sent into oblivion before MM init!\n", 
544                       console_global_data.vacuum_sent);
545#endif         
546        }
547        for(p=console_global_data.log; p; p=next) {
548                puts(p->data);
549                next = p->next;
550                pfree(p);
551        }
552}
553
554#ifndef INL_CONSOLE_INB
555#error "BSP probably didn't define a console port"
556#endif
557
558void serial_putc(const u_char c)
559{
560        while ((INL_CONSOLE_INB(lsr) & LSR_THRE) == 0) ;
561        INL_CONSOLE_OUTB(thr, c);
562}
563 
564int serial_getc(void)
565{
566        while ((INL_CONSOLE_INB(lsr) & LSR_DR) == 0) ;
567        return (INL_CONSOLE_INB(rbr));
568}
569
570int serial_tstc(void)
571{
572        return ((INL_CONSOLE_INB(lsr) & LSR_DR) != 0);
573}
574
575#ifdef USE_VGA_SUPPORT
576static void scroll(void)
577{
578        int i;
579
580        memcpy ( (u_char *)vidmem, (u_char *)vidmem + console_global_data.cols * 2, 
581                 ( console_global_data.lines - 1 ) * console_global_data.cols * 2 );
582        for ( i = ( console_global_data.lines - 1 ) * console_global_data.cols * 2; 
583              i < console_global_data.lines * console_global_data.cols * 2; 
584              i += 2 )
585                vidmem[i] = ' ';
586}
587
588/*
589 * cursor() sets an offset (0-1999) into the 80x25 text area   
590 */
591static void
592cursor(int x, int y)
593{
594        int pos = console_global_data.cols*y + x;
595        vga_outb(14, 0x14);
596        vga_outb(0x15, pos>>8);
597        vga_outb(0x14, 15);
598        vga_outb(0x15, pos);
599}
600
601void 
602vga_putc(const u_char c)
603{
604        int x,y;
605
606        x = console_global_data.orig_x;
607        y = console_global_data.orig_y;
608
609        if ( c == '\n' ) {
610                if ( ++y >= console_global_data.lines ) {
611                        scroll();
612                        y--;
613                }
614        } else if (c == '\b') {
615                if (x > 0) {
616                        x--;
617                }
618        } else if (c == '\r') {
619                x = 0;
620        } else {
621                vidmem [ ( x + console_global_data.cols * y ) * 2 ] = c; 
622                if ( ++x >= console_global_data.cols ) {
623                        x = 0;
624                        if ( ++y >= console_global_data.lines ) {
625                                scroll();
626                                y--;
627                        }
628                }
629        }
630
631        cursor(x, y);
632
633        console_global_data.orig_x = x;
634        console_global_data.orig_y = y;
635}
636#endif /* USE_VGA_SUPPORT */
637
638#ifdef USE_KBD_SUPPORT
639/* Keyboard support */
640static int kbd_getc(void)
641{
642        unsigned char dt, brk, val;
643        unsigned code;
644loop:
645        while((kbd_inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0) ;
646
647        dt = kbd_inb(KBD_DATA_REG);
648
649        brk = dt & 0x80;        /* brk == 1 on key release */
650        dt = dt & 0x7f;         /* keycode */
651
652        if (console_global_data.shfts)
653            code = shift_map[dt];
654        else if (console_global_data.ctls)
655            code = ctrl_map[dt];
656        else
657            code = plain_map[dt];
658
659        val = KVAL(code);
660        switch (KTYP(code) & 0x0f) {
661            case KT_LATIN:
662                if (brk)
663                    break;
664                if (console_global_data.alts)
665                    val |= 0x80;
666                if (val == 0x7f)        /* map delete to backspace */
667                    val = '\b';
668                return val;
669
670            case KT_LETTER:
671                if (brk)
672                    break;
673                if (console_global_data.caps)
674                    val -= 'a'-'A';
675                return val;
676
677            case KT_SPEC:
678                if (brk)
679                    break;
680                if (val == KVAL(K_CAPS))
681                    console_global_data.caps = !console_global_data.caps;
682                else if (val == KVAL(K_ENTER)) {
683enter:              /* Wait for key up */
684                    while (1) {
685                        while((kbd_inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0) ;
686                        dt = kbd_inb(KBD_DATA_REG);
687                        if (dt & 0x80) /* key up */ break;
688                    }
689                    return 10;
690                }
691                break;
692
693            case KT_PAD:
694                if (brk)
695                    break;
696                if (val < 10)
697                    return val;
698                if (val == KVAL(K_PENTER))
699                    goto enter;
700                break;
701
702            case KT_SHIFT:
703                switch (val) {
704                    case KG_SHIFT:
705                    case KG_SHIFTL:
706                    case KG_SHIFTR:
707                        console_global_data.shfts = brk ? 0 : 1;
708                        break;
709                    case KG_ALT:
710                    case KG_ALTGR:
711                        console_global_data.alts = brk ? 0 : 1;
712                        break;
713                    case KG_CTRL:
714                    case KG_CTRLL:
715                    case KG_CTRLR:
716                        console_global_data.ctls = brk ? 0 : 1;
717                        break;
718                }
719                break;
720
721            case KT_LOCK:
722                switch (val) {
723                    case KG_SHIFT:
724                    case KG_SHIFTL:
725                    case KG_SHIFTR:
726                        if (brk)
727                            console_global_data.shfts = !console_global_data.shfts;
728                        break;
729                    case KG_ALT:
730                    case KG_ALTGR:
731                        if (brk)
732                            console_global_data.alts = !console_global_data.alts;
733                        break;
734                    case KG_CTRL:
735                    case KG_CTRLL:
736                    case KG_CTRLR:
737                        if (brk)
738                            console_global_data.ctls = !console_global_data.ctls;
739                        break;
740                }
741                break;
742        }
743        /* if (brk) return (0); */  /* Ignore initial 'key up' codes */
744        goto loop;
745}
746
747static int kbd_get(int ms) {
748        int status, data;
749        while(1) {
750                status = kbd_inb(KBD_STATUS_REG);
751                if (status & KBD_STAT_OBF) {
752                        data = kbd_inb(KBD_DATA_REG);
753                        if (status & (KBD_STAT_GTO | KBD_STAT_PERR))
754                                return -1;
755                        else
756                                return data;
757                }
758                if (--ms < 0) return -1; 
759#ifdef __BOOT__
760                boot_udelay(1000);
761#else
762                rtems_bsp_delay(1000);
763#endif
764        }
765}
766
767static void kbd_put(u_char c, int ms, int port) {
768        while (kbd_inb(KBD_STATUS_REG) & KBD_STAT_IBF) {
769                if (--ms < 0) return; 
770#ifdef __BOOT__
771                boot_udelay(1000);
772#else
773                rtems_bsp_delay(1000);
774#endif
775        }
776        kbd_outb(port, c);
777}
778
779int kbdreset(void)
780{
781        int c;
782
783        /* Flush all pending data */
784        while(kbd_get(10) != -1);
785
786        /* Send self-test */
787        kbd_put(KBD_CCMD_SELF_TEST, 10, KBD_CNTL_REG);
788        c = kbd_get(1000);
789        if (c != 0x55) return 1;
790
791        /* Enable then reset the KB */
792        kbd_put(KBD_CCMD_KBD_ENABLE, 10, KBD_CNTL_REG);
793       
794        while (1) {
795                kbd_put(KBD_CMD_RESET, 10, KBD_DATA_REG);
796                c = kbd_get(1000);
797                if (c == KBD_REPLY_ACK) break;
798                if (c != KBD_REPLY_RESEND) return 2;
799        }
800       
801        if (kbd_get(1000) != KBD_REPLY_POR) return 3;
802
803        /* Disable the keyboard while setting up the controller */
804        kbd_put(KBD_CMD_DISABLE, 10, KBD_DATA_REG);
805        if (kbd_get(10)!=KBD_REPLY_ACK) return 4;
806
807        /* Enable interrupts and keyboard controller */
808        kbd_put(KBD_CCMD_WRITE_MODE, 10, KBD_CNTL_REG);
809        kbd_put(KBD_MODE_KBD_INT | KBD_MODE_SYS | 
810                KBD_MODE_DISABLE_MOUSE | KBD_MODE_KCC,
811                10, KBD_DATA_REG);
812
813        /* Reenable the keyboard */
814        kbd_put(KBD_CMD_ENABLE, 10, KBD_DATA_REG);
815        if (kbd_get(10)!=KBD_REPLY_ACK) return 5;
816
817        return 0;
818}
819
820int kbd_tstc(void)
821{
822        return ((kbd_inb(KBD_STATUS_REG) & KBD_STAT_OBF) != 0);
823}
824#endif /* USE_KBD_SUPPORT */
825
826const struct console_io
827vacuum_console_functions = {
828        vacuum_putc, 
829        vacuum_getc, 
830        vacuum_tstc
831};
832
833static const struct console_io
834log_console_functions = {
835        log_putc, 
836        vacuum_getc, 
837        vacuum_tstc
838}
839,
840serial_console_functions = {
841        serial_putc, 
842        serial_getc, 
843        serial_tstc
844}
845#if defined(USE_KBD_SUPPORT) && defined(USE_VGA_SUPPORT)
846,
847vga_console_functions = {
848        vga_putc, 
849        kbd_getc, 
850        kbd_tstc
851}
852#endif
853;
854
855console_io* curIo = (console_io*) &vacuum_console_functions;
856
857int select_console(ioType t) {
858  static ioType curType = CONSOLE_VACUUM;
859 
860  switch (t) {
861  case CONSOLE_VACUUM   : curIo = (console_io*)&vacuum_console_functions; break;
862  case CONSOLE_LOG      : curIo = (console_io*)&log_console_functions; break;
863  case CONSOLE_SERIAL   : curIo = (console_io*)&serial_console_functions; break;
864#if defined(USE_KBD_SUPPORT) && defined(USE_VGA_SUPPORT)
865  case CONSOLE_VGA      : curIo = (console_io*)&vga_console_functions; break;
866#endif
867  default               : curIo = (console_io*)&vacuum_console_functions;break;
868  }
869  if (curType == CONSOLE_LOG) flush_log();
870  curType = t;
871  return 0;
872}
873
874/* we use this so that we can do without the ctype library */
875#define is_digit(c)     ((c) >= '0' && (c) <= '9')
876
877
878static int skip_atoi(const char **s)
879{
880        int i=0;
881
882        while (is_digit(**s))
883                i = i*10 + *((*s)++) - '0';
884        return i;
885}
886
887/* Based on linux/lib/vsprintf.c and modified to suit our needs,
888 * bloat has been limited since we basically only need %u, %x, %s and %c.
889 * But we need 64 bit values !
890 */
891int k_vsprintf(char *buf, const char *fmt, va_list args);
892
893int printk(const char *fmt, ...) {
894        va_list args;
895        int i;
896        /* Should not be a problem with 8kB of stack */
897        char buf[1024];
898       
899        va_start(args, fmt);
900        i = k_vsprintf(buf, fmt, args);
901        va_end(args);
902        puts(buf);
903        return  i;
904}
905
906/* Necessary to avoid including a library, and GCC won't do this inline. */
907#define div10(num, rmd)                                                  \
908do {    u32 t1, t2, t3;                                                  \
909        asm("lis %4,0xcccd; "                                            \
910            "addi %4,%4,0xffffcccd; "   /* Build 0xcccccccd */           \
911            "mulhwu %3,%0+1,%4; "       /* (num.l*cst.l).h  */           \
912            "mullw %2,%0,%4; "          /* (num.h*cst.l).l  */           \
913            "addc %3,%3,%2; "                                            \
914            "mulhwu %2,%0,%4; "         /* (num.h*cst.l).h  */           \
915            "addi %4,%4,-1; "           /* Build 0xcccccccc */           \
916            "mullw %1,%0,%4; "          /* (num.h*cst.h).l  */           \
917            "adde %2,%2,%1; "                                            \
918            "mulhwu %1,%0,%4; "         /* (num.h*cst.h).h  */           \
919            "addze %1,%1; "                                              \
920            "mullw %0,%0+1,%4; "        /* (num.l*cst.h).l  */           \
921            "addc %3,%3,%0; "                                            \
922            "mulhwu %0,%0+1,%4; "       /* (num.l*cst.h).h  */           \
923            "adde %2,%2,%0; "                                            \
924            "addze %1,%1; "                                              \
925            "srwi %2,%2,3; "                                             \
926            "srwi %0,%1,3; "                                             \
927            "rlwimi %2,%1,29,0,2; "                                      \
928            "mulli %4,%2,10; "                                           \
929            "sub %4,%0+1,%4; "                                           \
930            "mr %0+1,%2; " :                                             \
931            "=r" (num), "=&r" (t1), "=&r" (t2), "=&r"(t3), "=&b" (rmd) : \
932            "0" (num));                                                  \
933                                                                         \
934} while(0);
935
936#define SIGN    1               /* unsigned/signed long */
937#define LARGE   2               /* use 'ABCDEF' instead of 'abcdef' */
938#define HEX     4               /* hexadecimal instead of decimal */
939#define ADDR    8               /* Value is an addres (p) */
940#define ZEROPAD 16              /* pad with zero */
941#define HALF    32
942#define LONG    64              /* long argument */
943#define LLONG   128             /* 64 bit argument */
944
945static char * number(char * str, int size, int type, u64 num)
946{
947        char fill,sign,tmp[24];
948        const char *digits="0123456789abcdef";
949        int i;
950
951        if (type & LARGE)
952                digits = "0123456789ABCDEF";
953        fill = (type & ZEROPAD) ? '0' : ' ';
954        sign = 0;
955        if (type & SIGN) {
956                if ((s64)num <0) {
957                        sign = '-';
958                        num = -num;
959                        size--;
960                } 
961        }
962
963        i = 0;
964        do {
965                unsigned rem;
966                if (type&HEX) {
967                        rem = num & 0x0f;
968                        num >>=4;
969                } else {
970                        div10(num, rem);
971                }
972                tmp[i++] = digits[rem];
973        } while (num != 0);
974               
975        size -= i;
976        if (!(type&(ZEROPAD)))
977                while(size-->0)
978                        *str++ = ' ';
979        if (sign)
980                *str++ = sign;
981
982        while (size-- > 0)
983                *str++ = fill;
984        while (i-- > 0)
985                *str++ = tmp[i];
986        while (size-- > 0)
987                *str++ = ' ';
988        return str;
989}
990
991int k_vsprintf(char *buf, const char *fmt, va_list args)
992{
993        int len;
994        u64 num;
995        int i;
996        char * str;
997        const char *s;
998
999        int flags;              /* flags to number() and private */
1000
1001        int field_width;        /* width of output field */
1002
1003        for (str=buf ; *fmt ; ++fmt) {
1004                if (*fmt != '%') {
1005                        *str++ = *fmt;
1006                        continue;
1007                }
1008                       
1009                /* process flags, only 0 padding needed */
1010                flags = 0;
1011                if (*++fmt == '0' ) {
1012                        flags |= ZEROPAD;
1013                        fmt++;
1014                }
1015               
1016                /* get field width */
1017                field_width = -1;
1018                if (is_digit(*fmt))
1019                        field_width = skip_atoi(&fmt);
1020
1021                /* get the conversion qualifier */
1022                if (*fmt == 'h') {
1023                        flags |= HALF;
1024                        fmt++;
1025                } else if (*fmt == 'L') {
1026                        flags |= LLONG;
1027                        fmt++;
1028                } else if (*fmt == 'l') {
1029                        flags |= LONG;
1030                        fmt++;
1031                }
1032
1033                switch (*fmt) {
1034                case 'c':
1035                        *str++ = (unsigned char) va_arg(args, int);
1036                        while (--field_width > 0)
1037                                *str++ = ' ';
1038                        continue;
1039
1040                case 's':
1041                        s = va_arg(args, char *);
1042                        len = strlen(s);
1043
1044                        for (i = 0; i < len; ++i)
1045                                *str++ = *s++;
1046                        while (len < field_width--)
1047                                *str++ = ' ';
1048                        continue;
1049
1050                case 'p':
1051                        if (field_width == -1) {
1052                                field_width = 2*sizeof(void *);
1053                        }
1054                        flags |= ZEROPAD|HEX|ADDR;
1055                        break;
1056
1057                case 'X':
1058                        flags |= LARGE;
1059                case 'x':
1060                        flags |= HEX;
1061                        break;
1062
1063                case 'd':
1064                case 'i':
1065                        flags |= SIGN;
1066                case 'u':
1067                        break;
1068
1069                default:
1070                        if (*fmt != '%')
1071                                *str++ = '%';
1072                        if (*fmt)
1073                                *str++ = *fmt;
1074                        else
1075                                --fmt;
1076                        continue;
1077                }
1078                /* This ugly code tries to minimize the number of va_arg()
1079                 * since they expand to a lot of code on PPC under the SYSV
1080                 * calling conventions (but not with -mcall-aix which has
1081                 * other problems). Arguments have at least the size of a
1082                 * long allocated, and we use this fact to minimize bloat.
1083                 * (and pointers are assimilated to unsigned long too).
1084                 */
1085                if (sizeof(long long) > sizeof(long) && flags & LLONG) 
1086                        num = va_arg(args, unsigned long long);
1087                else {
1088                        u_long n = va_arg(args, unsigned long);
1089                        if (flags & HALF) {
1090                                if (flags & SIGN)
1091                                        n = (short) n;
1092                                else
1093                                        n = (unsigned short) n;
1094                        } else if (! flags & LONG) {
1095                                /* Here the compiler correctly removes this
1096                                 * do nothing code on 32 bit PPC.
1097                                 */
1098                                if (flags & SIGN) 
1099                                        n = (int) n;
1100                                else
1101                                        n = (unsigned) n;
1102                        }
1103                        if (flags & SIGN)  num = (long) n; else num = n;
1104                }
1105                str = number(str, field_width, flags, num);
1106        }
1107        *str = '\0';
1108        return str-buf;
1109}
Note: See TracBrowser for help on using the repository browser.