source: rtems/c/src/lib/libbsp/powerpc/shared/console/polled_io.c @ 7e85bfbe

4.115
Last change on this file since 7e85bfbe was 7e85bfbe, checked in by Sebastian Huber <sebastian.huber@…>, on 08/24/11 at 09:48:56

2011-08-24 Sebastian Huber <sebastian.huber@…>

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