source: rtems/bsps/powerpc/motorola_powerpc/console/polled_io.c @ f6895c6

5
Last change on this file since f6895c6 was f4db49a1, checked in by Sebastian Huber <sebastian.huber@…>, on 05/07/19 at 06:44:33

bsp/motorola_powerpc: Fix bootloader output

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