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

5
Last change on this file since 03e1d837 was 03e1d837, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 24, 2018 at 5:06:36 AM

bsps/powerpc: Move bootloader to bsps

This bootloader is only used by the motorola_powerpc BSP.

This patch is a part of the BSP source reorganization.

Update #3285.

  • 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/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_onlcr;
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 u_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        debug_putc(c);
433}
434
435int debug_getc(void)
436{
437  return curIo->console_io_getc();
438}
439
440int debug_tstc(void)
441{
442  return curIo->console_io_tstc();
443}
444
445#define vidmem ((__io_ptr)(ptr_mem_map->isa_mem_base+0xb8000))
446
447static void vacuum_putc(u_char c) {
448        console_global_data.vacuum_sent++;
449}
450
451static int vacuum_getc(void) {
452        return -1;
453}
454
455static int vacuum_tstc(void) {
456        return 0;
457}
458
459/*
460 * COM1 NS16550 support
461 */
462
463#define rbr 0
464#define ier 1
465#define fcr 2
466#define lcr 3
467#define mcr 4
468#define lsr 5
469#define msr 6
470#define scr 7
471#define thr rbr
472#define iir fcr
473#define dll rbr
474#define dlm ier
475
476#define LSR_DR   0x01  /* Data ready */
477#define LSR_OE   0x02  /* Overrun */
478#define LSR_PE   0x04  /* Parity error */
479#define LSR_FE   0x08  /* Framing error */
480#define LSR_BI   0x10  /* Break */
481#define LSR_THRE 0x20  /* Xmit holding register empty */
482#define LSR_TEMT 0x40  /* Xmitter empty */
483#define LSR_ERR  0x80  /* Error */
484
485#ifdef STATIC_LOG_ALLOC
486static int global_index = 0;
487
488static void *__palloc(int s)
489{
490  if (global_index ==( STATIC_LOG_DATA_PAGE_NB - 1) ) return (void*) 0;
491  return  (void*) &(log_page_pool [PAGE_SIZE * global_index++]);
492}
493
494static void pfree(void* p)
495{
496  --global_index;
497}
498#endif
499
500static void log_putc(const u_char c) {
501        console_log *l;
502        for(l=console_global_data.log; l; l=l->next) {
503                if (l->offset<PAGE_LOG_CHARS) break;
504        }
505        if (!l) {
506                l=__palloc(sizeof(console_log));
507                memset(l, 0, sizeof(console_log));
508                if (!console_global_data.log)
509                        console_global_data.log = l;
510                else {
511                        console_log *p;
512                        for (p=console_global_data.log;
513                             p->next; p=p->next);
514                        p->next = l;
515                }
516        }
517        l->data[l->offset++] = c;
518}
519
520/* This puts is non standard since it does not automatically add a newline
521 * at the end. So it is made private to avoid confusion in other files.
522 */
523static
524void my_puts(const u_char *s)
525{
526        char c;
527
528        while ( ( c = *s++ ) != '\0' ) {
529                                rtems_putc(c);
530        }
531}
532
533static
534void flush_log(void) {
535        console_log *p, *next;
536        if (console_global_data.vacuum_sent) {
537#ifdef TRACE_FLUSH_LOG
538                printk("%d characters sent into oblivion before MM init!\n",
539                       console_global_data.vacuum_sent);
540#endif
541        }
542        for(p=console_global_data.log; p; p=next) {
543                my_puts(p->data);
544                next = p->next;
545                pfree(p);
546        }
547}
548
549#ifndef INL_CONSOLE_INB
550#error "BSP probably didn't define a console port"
551#endif
552
553static void serial_putc(const u_char c)
554{
555        while ((INL_CONSOLE_INB(lsr) & LSR_THRE) == 0) ;
556        INL_CONSOLE_OUTB(thr, c);
557}
558
559static int serial_getc(void)
560{
561        while ((INL_CONSOLE_INB(lsr) & LSR_DR) == 0) ;
562        return (INL_CONSOLE_INB(rbr));
563}
564
565static int serial_tstc(void)
566{
567        return ((INL_CONSOLE_INB(lsr) & LSR_DR) != 0);
568}
569
570#ifdef USE_VGA_SUPPORT
571static void scroll(void)
572{
573        int i;
574
575        memcpy ( (u_char *)vidmem, (u_char *)vidmem + console_global_data.cols * 2,
576                 ( console_global_data.lines - 1 ) * console_global_data.cols * 2 );
577        for ( i = ( console_global_data.lines - 1 ) * console_global_data.cols * 2;
578              i < console_global_data.lines * console_global_data.cols * 2;
579              i += 2 )
580                vidmem[i] = ' ';
581}
582
583/*
584 * cursor() sets an offset (0-1999) into the 80x25 text area
585 */
586static void
587cursor(int x, int y)
588{
589        int pos = console_global_data.cols*y + x;
590        vga_outb(14, 0x14);
591        vga_outb(0x15, pos>>8);
592        vga_outb(0x14, 15);
593        vga_outb(0x15, pos);
594}
595
596static void
597vga_putc(const u_char c)
598{
599        int x,y;
600
601        x = console_global_data.orig_x;
602        y = console_global_data.orig_y;
603
604        if ( c == '\n' ) {
605                if ( ++y >= console_global_data.lines ) {
606                        scroll();
607                        y--;
608                }
609        } else if (c == '\b') {
610                if (x > 0) {
611                        x--;
612                }
613        } else if (c == '\r') {
614                x = 0;
615        } else {
616                vidmem [ ( x + console_global_data.cols * y ) * 2 ] = c;
617                if ( ++x >= console_global_data.cols ) {
618                        x = 0;
619                        if ( ++y >= console_global_data.lines ) {
620                                scroll();
621                                y--;
622                        }
623                }
624        }
625
626        cursor(x, y);
627
628        console_global_data.orig_x = x;
629        console_global_data.orig_y = y;
630}
631#endif /* USE_VGA_SUPPORT */
632
633#ifdef USE_KBD_SUPPORT
634/* Keyboard support */
635static int kbd_getc(void)
636{
637        unsigned char dt, brk, val;
638        unsigned code;
639loop:
640        while((kbd_inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0) ;
641
642        dt = kbd_inb(KBD_DATA_REG);
643
644        brk = dt & 0x80;        /* brk == 1 on key release */
645        dt = dt & 0x7f;         /* keycode */
646
647        if (console_global_data.shfts)
648            code = shift_map[dt];
649        else if (console_global_data.ctls)
650            code = ctrl_map[dt];
651        else
652            code = plain_map[dt];
653
654        val = KVAL(code);
655        switch (KTYP(code) & 0x0f) {
656            case KT_LATIN:
657                if (brk)
658                    break;
659                if (console_global_data.alts)
660                    val |= 0x80;
661                if (val == 0x7f)        /* map delete to backspace */
662                    val = '\b';
663                return val;
664
665            case KT_LETTER:
666                if (brk)
667                    break;
668                if (console_global_data.caps)
669                    val -= 'a'-'A';
670                return val;
671
672            case KT_SPEC:
673                if (brk)
674                    break;
675                if (val == KVAL(K_CAPS))
676                    console_global_data.caps = !console_global_data.caps;
677                else if (val == KVAL(K_ENTER)) {
678enter:              /* Wait for key up */
679                    while (1) {
680                        while((kbd_inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0) ;
681                        dt = kbd_inb(KBD_DATA_REG);
682                        if (dt & 0x80) /* key up */ break;
683                    }
684                    return 10;
685                }
686                break;
687
688            case KT_PAD:
689                if (brk)
690                    break;
691                if (val < 10)
692                    return val;
693                if (val == KVAL(K_PENTER))
694                    goto enter;
695                break;
696
697            case KT_SHIFT:
698                switch (val) {
699                    case KG_SHIFT:
700                    case KG_SHIFTL:
701                    case KG_SHIFTR:
702                        console_global_data.shfts = brk ? 0 : 1;
703                        break;
704                    case KG_ALT:
705                    case KG_ALTGR:
706                        console_global_data.alts = brk ? 0 : 1;
707                        break;
708                    case KG_CTRL:
709                    case KG_CTRLL:
710                    case KG_CTRLR:
711                        console_global_data.ctls = brk ? 0 : 1;
712                        break;
713                }
714                break;
715
716            case KT_LOCK:
717                switch (val) {
718                    case KG_SHIFT:
719                    case KG_SHIFTL:
720                    case KG_SHIFTR:
721                        if (brk)
722                            console_global_data.shfts = !console_global_data.shfts;
723                        break;
724                    case KG_ALT:
725                    case KG_ALTGR:
726                        if (brk)
727                            console_global_data.alts = !console_global_data.alts;
728                        break;
729                    case KG_CTRL:
730                    case KG_CTRLL:
731                    case KG_CTRLR:
732                        if (brk)
733                            console_global_data.ctls = !console_global_data.ctls;
734                        break;
735                }
736                break;
737        }
738        /* if (brk) return (0); */  /* Ignore initial 'key up' codes */
739        goto loop;
740}
741
742static int kbd_get(int ms) {
743        int status, data;
744        while(1) {
745                status = kbd_inb(KBD_STATUS_REG);
746                if (status & KBD_STAT_OBF) {
747                        data = kbd_inb(KBD_DATA_REG);
748                        if (status & (KBD_STAT_GTO | KBD_STAT_PERR))
749                                return -1;
750                        else
751                                return data;
752                }
753                if (--ms < 0) return -1;
754#ifdef __BOOT__
755                boot_udelay(1000);
756#else
757                rtems_bsp_delay(1000);
758#endif
759        }
760}
761
762static void kbd_put(u_char c, int ms, int port) {
763        while (kbd_inb(KBD_STATUS_REG) & KBD_STAT_IBF) {
764                if (--ms < 0) return;
765#ifdef __BOOT__
766                boot_udelay(1000);
767#else
768                rtems_bsp_delay(1000);
769#endif
770        }
771        kbd_outb(port, c);
772}
773
774int kbdreset(void)
775{
776        int c;
777
778        /* Flush all pending data */
779        while(kbd_get(10) != -1);
780
781        /* Send self-test */
782        kbd_put(KBD_CCMD_SELF_TEST, 10, KBD_CNTL_REG);
783        c = kbd_get(1000);
784        if (c != 0x55) return 1;
785
786        /* Enable then reset the KB */
787        kbd_put(KBD_CCMD_KBD_ENABLE, 10, KBD_CNTL_REG);
788
789        while (1) {
790                kbd_put(KBD_CMD_RESET, 10, KBD_DATA_REG);
791                c = kbd_get(1000);
792                if (c == KBD_REPLY_ACK) break;
793                if (c != KBD_REPLY_RESEND) return 2;
794        }
795
796        if (kbd_get(1000) != KBD_REPLY_POR) return 3;
797
798        /* Disable the keyboard while setting up the controller */
799        kbd_put(KBD_CMD_DISABLE, 10, KBD_DATA_REG);
800        if (kbd_get(10)!=KBD_REPLY_ACK) return 4;
801
802        /* Enable interrupts and keyboard controller */
803        kbd_put(KBD_CCMD_WRITE_MODE, 10, KBD_CNTL_REG);
804        kbd_put(KBD_MODE_KBD_INT | KBD_MODE_SYS |
805                KBD_MODE_DISABLE_MOUSE | KBD_MODE_KCC,
806                10, KBD_DATA_REG);
807
808        /* Reenable the keyboard */
809        kbd_put(KBD_CMD_ENABLE, 10, KBD_DATA_REG);
810        if (kbd_get(10)!=KBD_REPLY_ACK) return 5;
811
812        return 0;
813}
814
815static int kbd_tstc(void)
816{
817        return ((kbd_inb(KBD_STATUS_REG) & KBD_STAT_OBF) != 0);
818}
819#endif /* USE_KBD_SUPPORT */
820
821const struct console_io
822vacuum_console_functions = {
823        vacuum_putc,
824        vacuum_getc,
825        vacuum_tstc
826};
827
828static const struct console_io
829log_console_functions = {
830        log_putc,
831        vacuum_getc,
832        vacuum_tstc
833}
834,
835serial_console_functions = {
836        serial_putc,
837        serial_getc,
838        serial_tstc
839}
840#if defined(USE_KBD_SUPPORT) && defined(USE_VGA_SUPPORT)
841,
842vga_console_functions = {
843        vga_putc,
844        kbd_getc,
845        kbd_tstc
846}
847#endif
848;
849
850console_io* curIo = (console_io*) &vacuum_console_functions;
851
852int select_console(ioType t) {
853  static ioType curType = CONSOLE_VACUUM;
854
855  switch (t) {
856  case CONSOLE_VACUUM   : curIo = (console_io*)&vacuum_console_functions; break;
857  case CONSOLE_LOG      : curIo = (console_io*)&log_console_functions; break;
858  case CONSOLE_SERIAL   : curIo = (console_io*)&serial_console_functions; break;
859#if defined(USE_KBD_SUPPORT) && defined(USE_VGA_SUPPORT)
860  case CONSOLE_VGA      : curIo = (console_io*)&vga_console_functions; break;
861#endif
862  default               : curIo = (console_io*)&vacuum_console_functions;break;
863  }
864  if (curType == CONSOLE_LOG) flush_log();
865  curType = t;
866  return 0;
867}
868
869/* we use this so that we can do without the ctype library */
870#define is_digit(c)     ((c) >= '0' && (c) <= '9')
871
872/* provide this for the bootloader only; otherwise
873 * use libcpu implementation
874 */
875#if defined(__BOOT__)
876static int skip_atoi(const char **s)
877{
878        int i=0;
879
880        while (is_digit(**s))
881                i = i*10 + *((*s)++) - '0';
882        return i;
883}
884
885/* Based on linux/lib/vsprintf.c and modified to suit our needs,
886 * bloat has been limited since we basically only need %u, %x, %s and %c.
887 * But we need 64 bit values !
888 */
889int k_vsprintf(char *buf, const char *fmt, va_list args);
890
891int  printk(const char *fmt, ...) {
892        va_list args;
893        int i;
894        /* Should not be a problem with 8kB of stack */
895        char buf[1024];
896
897        va_start(args, fmt);
898        i = k_vsprintf(buf, fmt, args);
899        va_end(args);
900        my_puts((u_char*)buf);
901        return i;
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.