source: rtems/c/src/lib/libbsp/powerpc/shared/console/polled_io.c @ 1bc0ad2

5
Last change on this file since 1bc0ad2 was 1bc0ad2, checked in by Sebastian Huber <sebastian.huber@…>, on 09/08/17 at 08:38:46

Simplify and unify BSP_output_char

The BSP_output_char should output a char and not mingle with high level
processing, e.g. '\n' to '\r\n' translation. Move this translation to
rtems_putc(). Remove it from all the BSP_output_char implementations.

Close #3122.

  • Property mode set to 100644
File size: 29.1 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.org/license/LICENSE.
14 */
15
16#include <rtems/system.h>
17#include <sys/types.h>
18#include <libcpu/byteorder.h>
19#include <libcpu/page.h>
20#include <libcpu/mmu.h>
21#include <libcpu/io.h>
22#include <string.h>
23#include <stdarg.h>
24#include <bsp/consoleIo.h>
25#include <bsp.h>
26#include <libcpu/spr.h>
27
28#ifdef BSP_KBD_IOBASE
29#define USE_KBD_SUPPORT
30#endif
31#ifdef BSP_VGA_IOBASE
32#define USE_VGA_SUPPORT
33#endif
34
35#ifdef USE_KBD_SUPPORT
36#include "keyboard.h"
37#endif
38#include "console.inl"
39
40#ifdef __BOOT__
41extern void boot_udelay(uint32_t   _microseconds);
42void * __palloc(u_long);
43void  pfree(void *);
44#else
45#include <rtems/bspIo.h>
46#endif
47
48#ifndef __BOOT__
49BSP_output_char_function_type     BSP_output_char = debug_putc_onlcr;
50BSP_polling_getchar_function_type BSP_poll_char = NULL;
51#endif
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/* These #defines have been copied from drivers/char/pc_keyb.h, by
315 * Martin Mares (mj@ucw.cz).
316 * converted to offsets by Till Straumann <strauman@slac.stanford.edu>
317 */
318#define KBD_STATUS_REG          0x4     /* Status register (R) */
319#define KBD_CNTL_REG            0x4     /* Controller command register (W) */
320#define KBD_DATA_REG            0x0     /* Keyboard data register (R/W) */
321
322/*
323 *      Keyboard Controller Commands
324 */
325
326#define KBD_CCMD_WRITE_MODE     0x60    /* Write mode bits */
327#define KBD_CCMD_GET_VERSION    0xA1    /* Get controller version */
328#define KBD_CCMD_MOUSE_DISABLE  0xA7    /* Disable mouse interface */
329#define KBD_CCMD_MOUSE_ENABLE   0xA8    /* Enable mouse interface */
330#define KBD_CCMD_TEST_MOUSE     0xA9    /* Mouse interface test */
331#define KBD_CCMD_SELF_TEST      0xAA    /* Controller self test */
332#define KBD_CCMD_KBD_TEST       0xAB    /* Keyboard interface test */
333#define KBD_CCMD_KBD_DISABLE    0xAD    /* Keyboard interface disable */
334#define KBD_CCMD_KBD_ENABLE     0xAE    /* Keyboard interface enable */
335
336/*
337 *      Keyboard Commands
338 */
339
340#define KBD_CMD_ENABLE          0xF4    /* Enable scanning */
341#define KBD_CMD_DISABLE         0xF5    /* Disable scanning */
342#define KBD_CMD_RESET           0xFF    /* Reset */
343
344/*
345 *      Keyboard Replies
346 */
347
348#define KBD_REPLY_POR           0xAA    /* Power on reset */
349#define KBD_REPLY_ACK           0xFA    /* Command ACK */
350#define KBD_REPLY_RESEND        0xFE    /* Command NACK, send the cmd again */
351
352/*
353 *      Status Register Bits
354 */
355
356#define KBD_STAT_OBF            0x01    /* Keyboard output buffer full */
357#define KBD_STAT_IBF            0x02    /* Keyboard input buffer full */
358#define KBD_STAT_UNLOCKED       0x10    /* Zero if keyboard locked */
359#define KBD_STAT_GTO            0x40    /* General receive/xmit timeout */
360#define KBD_STAT_PERR           0x80    /* Parity error */
361
362/*
363 *      Controller Mode Register Bits
364 */
365
366#define KBD_MODE_KBD_INT        0x01    /* Keyboard data generate IRQ1 */
367#define KBD_MODE_SYS            0x04    /* The system flag (?) */
368#define KBD_MODE_NO_KEYLOCK     0x08    /* The keylock doesn't affect the keyboard if set */
369#define KBD_MODE_DISABLE_KBD    0x10    /* Disable keyboard interface */
370#define KBD_MODE_DISABLE_MOUSE  0x20    /* Disable mouse interface */
371#define KBD_MODE_KCC            0x40    /* Scan code conversion to PC format */
372#define KBD_MODE_RFU            0x80
373
374#endif /* USE_KBD_SUPPORT */
375
376/* Early messages after mm init but before console init are kept in log
377 * buffers.
378 */
379#define PAGE_LOG_CHARS (PAGE_SIZE-sizeof(int)-sizeof(u_long)-1)
380
381typedef struct _console_log {
382        struct _console_log *next;
383        int offset;
384        u_char data[PAGE_LOG_CHARS];
385} console_log;
386
387#ifdef STATIC_LOG_ALLOC
388
389#define STATIC_LOG_DATA_PAGE_NB 3
390
391static  u_char  log_page_pool   [STATIC_LOG_DATA_PAGE_NB * PAGE_SIZE];
392
393#endif
394
395static board_memory_map mem_map = {
396  (__io_ptr) _IO_BASE,          /* from libcpu/io.h */
397  (__io_ptr) _ISA_MEM_BASE,
398};
399
400board_memory_map *ptr_mem_map = &mem_map;
401
402struct _console_global_data {
403        console_log *log;
404        int vacuum_sent;
405        int lines;
406        int cols;
407        int orig_x;
408        int orig_y;
409        u_char shfts, ctls, alts, caps;
410} console_global_data = {NULL, 0, 25, 80, 0, 24, 0, 0, 0, 0};
411
412typedef struct console_io {
413        void    (*console_io_putc)      (const u_char);
414        int     (*console_io_getc)      (void);
415        int     (*console_io_tstc)      (void);
416}console_io;
417
418extern console_io* curIo;
419
420void debug_putc(const u_char c)
421{
422  curIo->console_io_putc(c);
423}
424
425/* const char arg to be compatible with BSP_output_char decl. */
426void
427debug_putc_onlcr(const char c)
428{
429        debug_putc(c);
430}
431
432int debug_getc(void)
433{
434  return curIo->console_io_getc();
435}
436
437int debug_tstc(void)
438{
439  return curIo->console_io_tstc();
440}
441
442#define vidmem ((__io_ptr)(ptr_mem_map->isa_mem_base+0xb8000))
443
444static void vacuum_putc(u_char c) {
445        console_global_data.vacuum_sent++;
446}
447
448static int vacuum_getc(void) {
449        return -1;
450}
451
452static int vacuum_tstc(void) {
453        return 0;
454}
455
456/*
457 * COM1 NS16550 support
458 */
459
460#define rbr 0
461#define ier 1
462#define fcr 2
463#define lcr 3
464#define mcr 4
465#define lsr 5
466#define msr 6
467#define scr 7
468#define thr rbr
469#define iir fcr
470#define dll rbr
471#define dlm ier
472
473#define LSR_DR   0x01  /* Data ready */
474#define LSR_OE   0x02  /* Overrun */
475#define LSR_PE   0x04  /* Parity error */
476#define LSR_FE   0x08  /* Framing error */
477#define LSR_BI   0x10  /* Break */
478#define LSR_THRE 0x20  /* Xmit holding register empty */
479#define LSR_TEMT 0x40  /* Xmitter empty */
480#define LSR_ERR  0x80  /* Error */
481
482#ifdef STATIC_LOG_ALLOC
483static int global_index = 0;
484
485static void *__palloc(int s)
486{
487  if (global_index ==( STATIC_LOG_DATA_PAGE_NB - 1) ) return (void*) 0;
488  return  (void*) &(log_page_pool [PAGE_SIZE * global_index++]);
489}
490
491static void pfree(void* p)
492{
493  --global_index;
494}
495#endif
496
497static void log_putc(const u_char c) {
498        console_log *l;
499        for(l=console_global_data.log; l; l=l->next) {
500                if (l->offset<PAGE_LOG_CHARS) break;
501        }
502        if (!l) {
503                l=__palloc(sizeof(console_log));
504                memset(l, 0, sizeof(console_log));
505                if (!console_global_data.log)
506                        console_global_data.log = l;
507                else {
508                        console_log *p;
509                        for (p=console_global_data.log;
510                             p->next; p=p->next);
511                        p->next = l;
512                }
513        }
514        l->data[l->offset++] = c;
515}
516
517/* This puts is non standard since it does not automatically add a newline
518 * at the end. So it is made private to avoid confusion in other files.
519 */
520static
521void my_puts(const u_char *s)
522{
523        char c;
524
525        while ( ( c = *s++ ) != '\0' ) {
526                                rtems_putc(c);
527        }
528}
529
530static
531void flush_log(void) {
532        console_log *p, *next;
533        if (console_global_data.vacuum_sent) {
534#ifdef TRACE_FLUSH_LOG
535                printk("%d characters sent into oblivion before MM init!\n",
536                       console_global_data.vacuum_sent);
537#endif
538        }
539        for(p=console_global_data.log; p; p=next) {
540                my_puts(p->data);
541                next = p->next;
542                pfree(p);
543        }
544}
545
546#ifndef INL_CONSOLE_INB
547#error "BSP probably didn't define a console port"
548#endif
549
550static void serial_putc(const u_char c)
551{
552        while ((INL_CONSOLE_INB(lsr) & LSR_THRE) == 0) ;
553        INL_CONSOLE_OUTB(thr, c);
554}
555
556static int serial_getc(void)
557{
558        while ((INL_CONSOLE_INB(lsr) & LSR_DR) == 0) ;
559        return (INL_CONSOLE_INB(rbr));
560}
561
562static int serial_tstc(void)
563{
564        return ((INL_CONSOLE_INB(lsr) & LSR_DR) != 0);
565}
566
567#ifdef USE_VGA_SUPPORT
568static void scroll(void)
569{
570        int i;
571
572        memcpy ( (u_char *)vidmem, (u_char *)vidmem + console_global_data.cols * 2,
573                 ( console_global_data.lines - 1 ) * console_global_data.cols * 2 );
574        for ( i = ( console_global_data.lines - 1 ) * console_global_data.cols * 2;
575              i < console_global_data.lines * console_global_data.cols * 2;
576              i += 2 )
577                vidmem[i] = ' ';
578}
579
580/*
581 * cursor() sets an offset (0-1999) into the 80x25 text area
582 */
583static void
584cursor(int x, int y)
585{
586        int pos = console_global_data.cols*y + x;
587        vga_outb(14, 0x14);
588        vga_outb(0x15, pos>>8);
589        vga_outb(0x14, 15);
590        vga_outb(0x15, pos);
591}
592
593static void
594vga_putc(const u_char c)
595{
596        int x,y;
597
598        x = console_global_data.orig_x;
599        y = console_global_data.orig_y;
600
601        if ( c == '\n' ) {
602                if ( ++y >= console_global_data.lines ) {
603                        scroll();
604                        y--;
605                }
606        } else if (c == '\b') {
607                if (x > 0) {
608                        x--;
609                }
610        } else if (c == '\r') {
611                x = 0;
612        } else {
613                vidmem [ ( x + console_global_data.cols * y ) * 2 ] = c;
614                if ( ++x >= console_global_data.cols ) {
615                        x = 0;
616                        if ( ++y >= console_global_data.lines ) {
617                                scroll();
618                                y--;
619                        }
620                }
621        }
622
623        cursor(x, y);
624
625        console_global_data.orig_x = x;
626        console_global_data.orig_y = y;
627}
628#endif /* USE_VGA_SUPPORT */
629
630#ifdef USE_KBD_SUPPORT
631/* Keyboard support */
632static int kbd_getc(void)
633{
634        unsigned char dt, brk, val;
635        unsigned code;
636loop:
637        while((kbd_inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0) ;
638
639        dt = kbd_inb(KBD_DATA_REG);
640
641        brk = dt & 0x80;        /* brk == 1 on key release */
642        dt = dt & 0x7f;         /* keycode */
643
644        if (console_global_data.shfts)
645            code = shift_map[dt];
646        else if (console_global_data.ctls)
647            code = ctrl_map[dt];
648        else
649            code = plain_map[dt];
650
651        val = KVAL(code);
652        switch (KTYP(code) & 0x0f) {
653            case KT_LATIN:
654                if (brk)
655                    break;
656                if (console_global_data.alts)
657                    val |= 0x80;
658                if (val == 0x7f)        /* map delete to backspace */
659                    val = '\b';
660                return val;
661
662            case KT_LETTER:
663                if (brk)
664                    break;
665                if (console_global_data.caps)
666                    val -= 'a'-'A';
667                return val;
668
669            case KT_SPEC:
670                if (brk)
671                    break;
672                if (val == KVAL(K_CAPS))
673                    console_global_data.caps = !console_global_data.caps;
674                else if (val == KVAL(K_ENTER)) {
675enter:              /* Wait for key up */
676                    while (1) {
677                        while((kbd_inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0) ;
678                        dt = kbd_inb(KBD_DATA_REG);
679                        if (dt & 0x80) /* key up */ break;
680                    }
681                    return 10;
682                }
683                break;
684
685            case KT_PAD:
686                if (brk)
687                    break;
688                if (val < 10)
689                    return val;
690                if (val == KVAL(K_PENTER))
691                    goto enter;
692                break;
693
694            case KT_SHIFT:
695                switch (val) {
696                    case KG_SHIFT:
697                    case KG_SHIFTL:
698                    case KG_SHIFTR:
699                        console_global_data.shfts = brk ? 0 : 1;
700                        break;
701                    case KG_ALT:
702                    case KG_ALTGR:
703                        console_global_data.alts = brk ? 0 : 1;
704                        break;
705                    case KG_CTRL:
706                    case KG_CTRLL:
707                    case KG_CTRLR:
708                        console_global_data.ctls = brk ? 0 : 1;
709                        break;
710                }
711                break;
712
713            case KT_LOCK:
714                switch (val) {
715                    case KG_SHIFT:
716                    case KG_SHIFTL:
717                    case KG_SHIFTR:
718                        if (brk)
719                            console_global_data.shfts = !console_global_data.shfts;
720                        break;
721                    case KG_ALT:
722                    case KG_ALTGR:
723                        if (brk)
724                            console_global_data.alts = !console_global_data.alts;
725                        break;
726                    case KG_CTRL:
727                    case KG_CTRLL:
728                    case KG_CTRLR:
729                        if (brk)
730                            console_global_data.ctls = !console_global_data.ctls;
731                        break;
732                }
733                break;
734        }
735        /* if (brk) return (0); */  /* Ignore initial 'key up' codes */
736        goto loop;
737}
738
739static int kbd_get(int ms) {
740        int status, data;
741        while(1) {
742                status = kbd_inb(KBD_STATUS_REG);
743                if (status & KBD_STAT_OBF) {
744                        data = kbd_inb(KBD_DATA_REG);
745                        if (status & (KBD_STAT_GTO | KBD_STAT_PERR))
746                                return -1;
747                        else
748                                return data;
749                }
750                if (--ms < 0) return -1;
751#ifdef __BOOT__
752                boot_udelay(1000);
753#else
754                rtems_bsp_delay(1000);
755#endif
756        }
757}
758
759static void kbd_put(u_char c, int ms, int port) {
760        while (kbd_inb(KBD_STATUS_REG) & KBD_STAT_IBF) {
761                if (--ms < 0) return;
762#ifdef __BOOT__
763                boot_udelay(1000);
764#else
765                rtems_bsp_delay(1000);
766#endif
767        }
768        kbd_outb(port, c);
769}
770
771int kbdreset(void)
772{
773        int c;
774
775        /* Flush all pending data */
776        while(kbd_get(10) != -1);
777
778        /* Send self-test */
779        kbd_put(KBD_CCMD_SELF_TEST, 10, KBD_CNTL_REG);
780        c = kbd_get(1000);
781        if (c != 0x55) return 1;
782
783        /* Enable then reset the KB */
784        kbd_put(KBD_CCMD_KBD_ENABLE, 10, KBD_CNTL_REG);
785
786        while (1) {
787                kbd_put(KBD_CMD_RESET, 10, KBD_DATA_REG);
788                c = kbd_get(1000);
789                if (c == KBD_REPLY_ACK) break;
790                if (c != KBD_REPLY_RESEND) return 2;
791        }
792
793        if (kbd_get(1000) != KBD_REPLY_POR) return 3;
794
795        /* Disable the keyboard while setting up the controller */
796        kbd_put(KBD_CMD_DISABLE, 10, KBD_DATA_REG);
797        if (kbd_get(10)!=KBD_REPLY_ACK) return 4;
798
799        /* Enable interrupts and keyboard controller */
800        kbd_put(KBD_CCMD_WRITE_MODE, 10, KBD_CNTL_REG);
801        kbd_put(KBD_MODE_KBD_INT | KBD_MODE_SYS |
802                KBD_MODE_DISABLE_MOUSE | KBD_MODE_KCC,
803                10, KBD_DATA_REG);
804
805        /* Reenable the keyboard */
806        kbd_put(KBD_CMD_ENABLE, 10, KBD_DATA_REG);
807        if (kbd_get(10)!=KBD_REPLY_ACK) return 5;
808
809        return 0;
810}
811
812static int kbd_tstc(void)
813{
814        return ((kbd_inb(KBD_STATUS_REG) & KBD_STAT_OBF) != 0);
815}
816#endif /* USE_KBD_SUPPORT */
817
818const struct console_io
819vacuum_console_functions = {
820        vacuum_putc,
821        vacuum_getc,
822        vacuum_tstc
823};
824
825static const struct console_io
826log_console_functions = {
827        log_putc,
828        vacuum_getc,
829        vacuum_tstc
830}
831,
832serial_console_functions = {
833        serial_putc,
834        serial_getc,
835        serial_tstc
836}
837#if defined(USE_KBD_SUPPORT) && defined(USE_VGA_SUPPORT)
838,
839vga_console_functions = {
840        vga_putc,
841        kbd_getc,
842        kbd_tstc
843}
844#endif
845;
846
847console_io* curIo = (console_io*) &vacuum_console_functions;
848
849int select_console(ioType t) {
850  static ioType curType = CONSOLE_VACUUM;
851
852  switch (t) {
853  case CONSOLE_VACUUM   : curIo = (console_io*)&vacuum_console_functions; break;
854  case CONSOLE_LOG      : curIo = (console_io*)&log_console_functions; break;
855  case CONSOLE_SERIAL   : curIo = (console_io*)&serial_console_functions; break;
856#if defined(USE_KBD_SUPPORT) && defined(USE_VGA_SUPPORT)
857  case CONSOLE_VGA      : curIo = (console_io*)&vga_console_functions; break;
858#endif
859  default               : curIo = (console_io*)&vacuum_console_functions;break;
860  }
861  if (curType == CONSOLE_LOG) flush_log();
862  curType = t;
863  return 0;
864}
865
866/* we use this so that we can do without the ctype library */
867#define is_digit(c)     ((c) >= '0' && (c) <= '9')
868
869/* provide this for the bootloader only; otherwise
870 * use libcpu implementation
871 */
872#if defined(__BOOT__)
873static int skip_atoi(const char **s)
874{
875        int i=0;
876
877        while (is_digit(**s))
878                i = i*10 + *((*s)++) - '0';
879        return i;
880}
881
882/* Based on linux/lib/vsprintf.c and modified to suit our needs,
883 * bloat has been limited since we basically only need %u, %x, %s and %c.
884 * But we need 64 bit values !
885 */
886int k_vsprintf(char *buf, const char *fmt, va_list args);
887
888int  printk(const char *fmt, ...) {
889        va_list args;
890        int i;
891        /* Should not be a problem with 8kB of stack */
892        char buf[1024];
893
894        va_start(args, fmt);
895        i = k_vsprintf(buf, fmt, args);
896        va_end(args);
897        my_puts((u_char*)buf);
898        return i;
899}
900
901#endif
902
903/* Necessary to avoid including a library, and GCC won't do this inline. */
904#define div10(num, rmd)                                                  \
905do {    uint32_t t1, t2, t3;                                                     \
906        __asm__ ("lis %4,0xcccd; "                                               \
907            "addi %4,%4,0xffffcccd; "   /* Build 0xcccccccd */           \
908            "mulhwu %3,%0+1,%4; "       /* (num.l*cst.l).h  */           \
909            "mullw %2,%0,%4; "          /* (num.h*cst.l).l  */           \
910            "addc %3,%3,%2; "                                            \
911            "mulhwu %2,%0,%4; "         /* (num.h*cst.l).h  */           \
912            "addi %4,%4,-1; "           /* Build 0xcccccccc */           \
913            "mullw %1,%0,%4; "          /* (num.h*cst.h).l  */           \
914            "adde %2,%2,%1; "                                            \
915            "mulhwu %1,%0,%4; "         /* (num.h*cst.h).h  */           \
916            "addze %1,%1; "                                              \
917            "mullw %0,%0+1,%4; "        /* (num.l*cst.h).l  */           \
918            "addc %3,%3,%0; "                                            \
919            "mulhwu %0,%0+1,%4; "       /* (num.l*cst.h).h  */           \
920            "adde %2,%2,%0; "                                            \
921            "addze %1,%1; "                                              \
922            "srwi %2,%2,3; "                                             \
923            "srwi %0,%1,3; "                                             \
924            "rlwimi %2,%1,29,0,2; "                                      \
925            "mulli %4,%2,10; "                                           \
926            "sub %4,%0+1,%4; "                                           \
927            "mr %0+1,%2; " :                                             \
928            "=r" (num), "=&r" (t1), "=&r" (t2), "=&r"(t3), "=&b" (rmd) : \
929            "0" (num));                                                  \
930                                                                         \
931} while(0);
932
933#define SIGN    1               /* unsigned/signed long */
934#define LARGE   2               /* use 'ABCDEF' instead of 'abcdef' */
935#define HEX     4               /* hexadecimal instead of decimal */
936#define ADDR    8               /* Value is an addres (p) */
937#define ZEROPAD 16              /* pad with zero */
938#define HALF    32
939#define LONG    64              /* long argument */
940#define LLONG   128             /* 64 bit argument */
941
942#if defined(__BOOT__)
943static char * number(char * str, int size, int type, uint64_t num)
944{
945        char fill,sign,tmp[24];
946        const char *digits="0123456789abcdef";
947        int i;
948
949        if (type & LARGE)
950                digits = "0123456789ABCDEF";
951        fill = (type & ZEROPAD) ? '0' : ' ';
952        sign = 0;
953        if (type & SIGN) {
954                if ((int64_t)num <0) {
955                        sign = '-';
956                        num = -num;
957                        size--;
958                }
959        }
960
961        i = 0;
962        do {
963                unsigned rem;
964                if (type&HEX) {
965                        rem = num & 0x0f;
966                        num >>=4;
967                } else {
968                        div10(num, rem);
969                }
970                tmp[i++] = digits[rem];
971        } while (num != 0);
972
973        size -= i;
974        if (!(type&(ZEROPAD)))
975                while(size-->0)
976                        *str++ = ' ';
977        if (sign)
978                *str++ = sign;
979
980        while (size-- > 0)
981                *str++ = fill;
982        while (i-- > 0)
983                *str++ = tmp[i];
984        while (size-- > 0)
985                *str++ = ' ';
986        return str;
987}
988
989int k_vsprintf(char *buf, const char *fmt, va_list args)
990{
991        int len;
992        uint64_t num;
993        int i;
994        char * str;
995        const char *s;
996
997        int flags;              /* flags to number() and private */
998
999        int field_width;        /* width of output field */
1000
1001        for (str=buf ; *fmt ; ++fmt) {
1002                if (*fmt != '%') {
1003                        *str++ = *fmt;
1004                        continue;
1005                }
1006
1007                /* process flags, only 0 padding needed */
1008                flags = 0;
1009                if (*++fmt == '0' ) {
1010                        flags |= ZEROPAD;
1011                        fmt++;
1012                }
1013
1014                /* get field width */
1015                field_width = -1;
1016                if (is_digit(*fmt))
1017                        field_width = skip_atoi(&fmt);
1018
1019                /* get the conversion qualifier */
1020                if (*fmt == 'h') {
1021                        flags |= HALF;
1022                        fmt++;
1023                } else if (*fmt == 'L') {
1024                        flags |= LLONG;
1025                        fmt++;
1026                } else if (*fmt == 'l') {
1027                        flags |= LONG;
1028                        fmt++;
1029                }
1030
1031                switch (*fmt) {
1032                case 'c':
1033                        *str++ = (unsigned char) va_arg(args, int);
1034                        while (--field_width > 0)
1035                                *str++ = ' ';
1036                        continue;
1037
1038                case 's':
1039                        s = va_arg(args, char *);
1040                        len = strlen(s);
1041
1042                        for (i = 0; i < len; ++i)
1043                                *str++ = *s++;
1044                        while (len < field_width--)
1045                                *str++ = ' ';
1046                        continue;
1047
1048                case 'p':
1049                        if (field_width == -1) {
1050                                field_width = 2*sizeof(void *);
1051                        }
1052                        flags |= ZEROPAD|HEX|ADDR;
1053                        break;
1054
1055                case 'X':
1056                        flags |= LARGE;
1057                case 'x':
1058                        flags |= HEX;
1059                        break;
1060
1061                case 'd':
1062                case 'i':
1063                        flags |= SIGN;
1064                case 'u':
1065                        break;
1066
1067                default:
1068                        if (*fmt != '%')
1069                                *str++ = '%';
1070                        if (*fmt)
1071                                *str++ = *fmt;
1072                        else
1073                                --fmt;
1074                        continue;
1075                }
1076                /* This ugly code tries to minimize the number of va_arg()
1077                 * since they expand to a lot of code on PPC under the SYSV
1078                 * calling conventions (but not with -mcall-aix which has
1079                 * other problems). Arguments have at least the size of a
1080                 * long allocated, and we use this fact to minimize bloat.
1081                 * (and pointers are assimilated to unsigned long too).
1082                 */
1083                if (sizeof(long long) > sizeof(long) && flags & LLONG)
1084                        num = va_arg(args, unsigned long long);
1085                else {
1086                        u_long n = va_arg(args, unsigned long);
1087                        if (flags & HALF) {
1088                                if (flags & SIGN)
1089                                        n = (short) n;
1090                                else
1091                                        n = (unsigned short) n;
1092                        } else if (!(flags & LONG)) {
1093                                /* Here the compiler correctly removes this
1094                                 * do nothing code on 32 bit PPC.
1095                                 */
1096                                if (flags & SIGN)
1097                                        n = (int) n;
1098                                else
1099                                        n = (unsigned) n;
1100                        }
1101                        if (flags & SIGN)  num = (long) n; else num = n;
1102                }
1103                str = number(str, field_width, flags, num);
1104        }
1105        *str = '\0';
1106        return str-buf;
1107}
1108#endif
Note: See TracBrowser for help on using the repository browser.