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

4.115
Last change on this file since bd918ff7 was bd918ff7, checked in by Ralf Corsepius <ralf.corsepius@…>, on Feb 11, 2011 at 12:19:29 PM

2011-02-11 Ralf Corsépius <ralf.corsepius@…>

  • shared/console/polled_io.c, shared/flash/spansionFlash.c, shared/startup/bspidle.c, shared/startup/probeMemEnd.c: Use "asm" instead of "asm" for improved c99-compliance.
  • Property mode set to 100644
File size: 29.0 KB
Line 
1/*
2 *  polled_io.c -- Basic input/output for early boot
3 *
4 *  Copyright (C) 1998, 1999 Gabriel Paubert, paubert@iram.es
5 *
6 *  Modified to compile in RTEMS development environment
7 *  by Eric Valette
8 *
9 *  Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
10 *
11 *  The license and distribution terms for this file may be
12 *  found in the file LICENSE in this distribution or at
13 *  http://www.rtems.com/license/LICENSE.
14 *
15 * $Id$
16 */
17
18#include <rtems/system.h>
19#include <sys/types.h>
20#include <libcpu/byteorder.h>
21#include <libcpu/page.h>
22#include <libcpu/mmu.h>
23#include <libcpu/io.h>
24#include <string.h>
25#include <stdarg.h>
26#include <bsp/consoleIo.h>
27#include <bsp.h>
28#include <libcpu/spr.h>
29
30#ifdef BSP_KBD_IOBASE
31#define USE_KBD_SUPPORT
32#endif
33#ifdef BSP_VGA_IOBASE
34#define USE_VGA_SUPPORT
35#endif
36
37#ifdef USE_KBD_SUPPORT
38#include "keyboard.h"
39#endif
40#include "console.inl"
41
42#ifdef __BOOT__
43extern void boot_udelay(uint32_t   _microseconds);
44void * __palloc(u_long);
45void  pfree(void *);
46#else
47#include <rtems/bspIo.h>
48#endif
49
50#ifndef __BOOT__
51BSP_output_char_function_type     BSP_output_char = debug_putc_onlcr;
52BSP_polling_getchar_function_type BSP_poll_char = NULL;
53#endif
54
55#ifdef USE_KBD_SUPPORT
56unsigned short plain_map[NR_KEYS] = {
57        0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036,
58        0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf07f, 0xf009,
59        0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
60        0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201, 0xf702, 0xfb61, 0xfb73,
61        0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b,
62        0xf027, 0xf060, 0xf700, 0xf05c, 0xfb7a, 0xfb78, 0xfb63, 0xfb76,
63        0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf700, 0xf30c,
64        0xf703, 0xf020, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
65        0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf209, 0xf307,
66        0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
67        0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03c, 0xf10a,
68        0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
69        0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
70        0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
71        0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
72        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
73};
74
75unsigned short shift_map[NR_KEYS] = {
76        0xf200, 0xf01b, 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e,
77        0xf026, 0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf07f, 0xf009,
78        0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, 0xfb59, 0xfb55, 0xfb49,
79        0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf201, 0xf702, 0xfb41, 0xfb53,
80        0xfb44, 0xfb46, 0xfb47, 0xfb48, 0xfb4a, 0xfb4b, 0xfb4c, 0xf03a,
81        0xf022, 0xf07e, 0xf700, 0xf07c, 0xfb5a, 0xfb58, 0xfb43, 0xfb56,
82        0xfb42, 0xfb4e, 0xfb4d, 0xf03c, 0xf03e, 0xf03f, 0xf700, 0xf30c,
83        0xf703, 0xf020, 0xf207, 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf10e,
84        0xf10f, 0xf110, 0xf111, 0xf112, 0xf113, 0xf213, 0xf203, 0xf307,
85        0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
86        0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03e, 0xf10a,
87        0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
88        0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
89        0xf20b, 0xf601, 0xf602, 0xf117, 0xf600, 0xf20a, 0xf115, 0xf116,
90        0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
91        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
92};
93
94unsigned short altgr_map[NR_KEYS] = {
95        0xf200, 0xf200, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200,
96        0xf07b, 0xf05b, 0xf05d, 0xf07d, 0xf05c, 0xf200, 0xf200, 0xf200,
97        0xfb71, 0xfb77, 0xf918, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
98        0xfb6f, 0xfb70, 0xf200, 0xf07e, 0xf201, 0xf702, 0xf914, 0xfb73,
99        0xf917, 0xf919, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf200,
100        0xf200, 0xf200, 0xf700, 0xf200, 0xfb7a, 0xfb78, 0xf916, 0xfb76,
101        0xf915, 0xfb6e, 0xfb6d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
102        0xf703, 0xf200, 0xf207, 0xf50c, 0xf50d, 0xf50e, 0xf50f, 0xf510,
103        0xf511, 0xf512, 0xf513, 0xf514, 0xf515, 0xf208, 0xf202, 0xf911,
104        0xf912, 0xf913, 0xf30b, 0xf90e, 0xf90f, 0xf910, 0xf30a, 0xf90b,
105        0xf90c, 0xf90d, 0xf90a, 0xf310, 0xf206, 0xf200, 0xf07c, 0xf516,
106        0xf517, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
107        0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
108        0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
109        0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
110        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
111};
112
113unsigned short ctrl_map[NR_KEYS] = {
114        0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e,
115        0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200,
116        0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
117        0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013,
118        0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
119        0xf007, 0xf000, 0xf700, 0xf01c, 0xf01a, 0xf018, 0xf003, 0xf016,
120        0xf002, 0xf00e, 0xf00d, 0xf200, 0xf20e, 0xf07f, 0xf700, 0xf30c,
121        0xf703, 0xf000, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
122        0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf204, 0xf307,
123        0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
124        0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf10a,
125        0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
126        0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
127        0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
128        0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
129        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
130};
131
132unsigned short shift_ctrl_map[NR_KEYS] = {
133        0xf200, 0xf200, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200,
134        0xf200, 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200,
135        0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
136        0xf00f, 0xf010, 0xf200, 0xf200, 0xf201, 0xf702, 0xf001, 0xf013,
137        0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
138        0xf200, 0xf200, 0xf700, 0xf200, 0xf01a, 0xf018, 0xf003, 0xf016,
139        0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
140        0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
141        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf208, 0xf200, 0xf307,
142        0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
143        0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf200,
144        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
145        0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
146        0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
147        0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
148        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
149};
150
151unsigned short alt_map[NR_KEYS] = {
152        0xf200, 0xf81b, 0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836,
153        0xf837, 0xf838, 0xf839, 0xf830, 0xf82d, 0xf83d, 0xf87f, 0xf809,
154        0xf871, 0xf877, 0xf865, 0xf872, 0xf874, 0xf879, 0xf875, 0xf869,
155        0xf86f, 0xf870, 0xf85b, 0xf85d, 0xf80d, 0xf702, 0xf861, 0xf873,
156        0xf864, 0xf866, 0xf867, 0xf868, 0xf86a, 0xf86b, 0xf86c, 0xf83b,
157        0xf827, 0xf860, 0xf700, 0xf85c, 0xf87a, 0xf878, 0xf863, 0xf876,
158        0xf862, 0xf86e, 0xf86d, 0xf82c, 0xf82e, 0xf82f, 0xf700, 0xf30c,
159        0xf703, 0xf820, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
160        0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf209, 0xf907,
161        0xf908, 0xf909, 0xf30b, 0xf904, 0xf905, 0xf906, 0xf30a, 0xf901,
162        0xf902, 0xf903, 0xf900, 0xf310, 0xf206, 0xf200, 0xf83c, 0xf50a,
163        0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
164        0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
165        0xf118, 0xf210, 0xf211, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
166        0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
167        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
168};
169
170unsigned short ctrl_alt_map[NR_KEYS] = {
171        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
172        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
173        0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809,
174        0xf80f, 0xf810, 0xf200, 0xf200, 0xf201, 0xf702, 0xf801, 0xf813,
175        0xf804, 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c, 0xf200,
176        0xf200, 0xf200, 0xf700, 0xf200, 0xf81a, 0xf818, 0xf803, 0xf816,
177        0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
178        0xf703, 0xf200, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
179        0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf200, 0xf307,
180        0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
181        0xf302, 0xf303, 0xf300, 0xf20c, 0xf206, 0xf200, 0xf200, 0xf50a,
182        0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
183        0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
184        0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf20c,
185        0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
186        0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
187};
188
189ushort *key_maps[MAX_NR_KEYMAPS] = {
190        plain_map, shift_map, altgr_map, 0,
191        ctrl_map, shift_ctrl_map, 0, 0,
192        alt_map, 0, 0, 0,
193        ctrl_alt_map,   0
194};
195
196unsigned int keymap_count = 7;
197
198/*
199 * Philosophy: most people do not define more strings, but they who do
200 * often want quite a lot of string space. So, we statically allocate
201 * the default and allocate dynamically in chunks of 512 bytes.
202 */
203
204char func_buf[] = {
205        '\033', '[', '[', 'A', 0,
206        '\033', '[', '[', 'B', 0,
207        '\033', '[', '[', 'C', 0,
208        '\033', '[', '[', 'D', 0,
209        '\033', '[', '[', 'E', 0,
210        '\033', '[', '1', '7', '~', 0,
211        '\033', '[', '1', '8', '~', 0,
212        '\033', '[', '1', '9', '~', 0,
213        '\033', '[', '2', '0', '~', 0,
214        '\033', '[', '2', '1', '~', 0,
215        '\033', '[', '2', '3', '~', 0,
216        '\033', '[', '2', '4', '~', 0,
217        '\033', '[', '2', '5', '~', 0,
218        '\033', '[', '2', '6', '~', 0,
219        '\033', '[', '2', '8', '~', 0,
220        '\033', '[', '2', '9', '~', 0,
221        '\033', '[', '3', '1', '~', 0,
222        '\033', '[', '3', '2', '~', 0,
223        '\033', '[', '3', '3', '~', 0,
224        '\033', '[', '3', '4', '~', 0,
225        '\033', '[', '1', '~', 0,
226        '\033', '[', '2', '~', 0,
227        '\033', '[', '3', '~', 0,
228        '\033', '[', '4', '~', 0,
229        '\033', '[', '5', '~', 0,
230        '\033', '[', '6', '~', 0,
231        '\033', '[', 'M', 0,
232        '\033', '[', 'P', 0,
233};
234
235char *funcbufptr = func_buf;
236int funcbufsize = sizeof(func_buf);
237int funcbufleft = 0;          /* space left */
238
239char *func_table[MAX_NR_FUNC] = {
240        func_buf + 0,
241        func_buf + 5,
242        func_buf + 10,
243        func_buf + 15,
244        func_buf + 20,
245        func_buf + 25,
246        func_buf + 31,
247        func_buf + 37,
248        func_buf + 43,
249        func_buf + 49,
250        func_buf + 55,
251        func_buf + 61,
252        func_buf + 67,
253        func_buf + 73,
254        func_buf + 79,
255        func_buf + 85,
256        func_buf + 91,
257        func_buf + 97,
258        func_buf + 103,
259        func_buf + 109,
260        func_buf + 115,
261        func_buf + 120,
262        func_buf + 125,
263        func_buf + 130,
264        func_buf + 135,
265        func_buf + 140,
266        func_buf + 145,
267        0,
268        0,
269        func_buf + 149,
270        0,
271};
272
273struct kbdiacr {
274        unsigned char diacr, base, result;
275};
276
277struct kbdiacr accent_table[MAX_DIACR] = {
278        {'`', 'A', '\300'},     {'`', 'a', '\340'},
279        {'\'', 'A', '\301'},    {'\'', 'a', '\341'},
280        {'^', 'A', '\302'},     {'^', 'a', '\342'},
281        {'~', 'A', '\303'},     {'~', 'a', '\343'},
282        {'"', 'A', '\304'},     {'"', 'a', '\344'},
283        {'O', 'A', '\305'},     {'o', 'a', '\345'},
284        {'0', 'A', '\305'},     {'0', 'a', '\345'},
285        {'A', 'A', '\305'},     {'a', 'a', '\345'},
286        {'A', 'E', '\306'},     {'a', 'e', '\346'},
287        {',', 'C', '\307'},     {',', 'c', '\347'},
288        {'`', 'E', '\310'},     {'`', 'e', '\350'},
289        {'\'', 'E', '\311'},    {'\'', 'e', '\351'},
290        {'^', 'E', '\312'},     {'^', 'e', '\352'},
291        {'"', 'E', '\313'},     {'"', 'e', '\353'},
292        {'`', 'I', '\314'},     {'`', 'i', '\354'},
293        {'\'', 'I', '\315'},    {'\'', 'i', '\355'},
294        {'^', 'I', '\316'},     {'^', 'i', '\356'},
295        {'"', 'I', '\317'},     {'"', 'i', '\357'},
296        {'-', 'D', '\320'},     {'-', 'd', '\360'},
297        {'~', 'N', '\321'},     {'~', 'n', '\361'},
298        {'`', 'O', '\322'},     {'`', 'o', '\362'},
299        {'\'', 'O', '\323'},    {'\'', 'o', '\363'},
300        {'^', 'O', '\324'},     {'^', 'o', '\364'},
301        {'~', 'O', '\325'},     {'~', 'o', '\365'},
302        {'"', 'O', '\326'},     {'"', 'o', '\366'},
303        {'/', 'O', '\330'},     {'/', 'o', '\370'},
304        {'`', 'U', '\331'},     {'`', 'u', '\371'},
305        {'\'', 'U', '\332'},    {'\'', 'u', '\372'},
306        {'^', 'U', '\333'},     {'^', 'u', '\373'},
307        {'"', 'U', '\334'},     {'"', 'u', '\374'},
308        {'\'', 'Y', '\335'},    {'\'', 'y', '\375'},
309        {'T', 'H', '\336'},     {'t', 'h', '\376'},
310        {'s', 's', '\337'},     {'"', 'y', '\377'},
311        {'s', 'z', '\337'},     {'i', 'j', '\377'},
312};
313
314unsigned int accent_table_size = 68;
315
316/* These #defines have been copied from drivers/char/pc_keyb.h, by
317 * Martin Mares (mj@ucw.cz).
318 * converted to offsets by Till Straumann <strauman@slac.stanford.edu>
319 */
320#define KBD_STATUS_REG          0x4     /* Status register (R) */
321#define KBD_CNTL_REG            0x4     /* Controller command register (W) */
322#define KBD_DATA_REG            0x0     /* Keyboard data register (R/W) */
323
324/*
325 *      Keyboard Controller Commands
326 */
327
328#define KBD_CCMD_WRITE_MODE     0x60    /* Write mode bits */
329#define KBD_CCMD_GET_VERSION    0xA1    /* Get controller version */
330#define KBD_CCMD_MOUSE_DISABLE  0xA7    /* Disable mouse interface */
331#define KBD_CCMD_MOUSE_ENABLE   0xA8    /* Enable mouse interface */
332#define KBD_CCMD_TEST_MOUSE     0xA9    /* Mouse interface test */
333#define KBD_CCMD_SELF_TEST      0xAA    /* Controller self test */
334#define KBD_CCMD_KBD_TEST       0xAB    /* Keyboard interface test */
335#define KBD_CCMD_KBD_DISABLE    0xAD    /* Keyboard interface disable */
336#define KBD_CCMD_KBD_ENABLE     0xAE    /* Keyboard interface enable */
337
338/*
339 *      Keyboard Commands
340 */
341
342#define KBD_CMD_ENABLE          0xF4    /* Enable scanning */
343#define KBD_CMD_DISABLE         0xF5    /* Disable scanning */
344#define KBD_CMD_RESET           0xFF    /* Reset */
345
346/*
347 *      Keyboard Replies
348 */
349
350#define KBD_REPLY_POR           0xAA    /* Power on reset */
351#define KBD_REPLY_ACK           0xFA    /* Command ACK */
352#define KBD_REPLY_RESEND        0xFE    /* Command NACK, send the cmd again */
353
354/*
355 *      Status Register Bits
356 */
357
358#define KBD_STAT_OBF            0x01    /* Keyboard output buffer full */
359#define KBD_STAT_IBF            0x02    /* Keyboard input buffer full */
360#define KBD_STAT_UNLOCKED       0x10    /* Zero if keyboard locked */
361#define KBD_STAT_GTO            0x40    /* General receive/xmit timeout */
362#define KBD_STAT_PERR           0x80    /* Parity error */
363
364/*
365 *      Controller Mode Register Bits
366 */
367
368#define KBD_MODE_KBD_INT        0x01    /* Keyboard data generate IRQ1 */
369#define KBD_MODE_SYS            0x04    /* The system flag (?) */
370#define KBD_MODE_NO_KEYLOCK     0x08    /* The keylock doesn't affect the keyboard if set */
371#define KBD_MODE_DISABLE_KBD    0x10    /* Disable keyboard interface */
372#define KBD_MODE_DISABLE_MOUSE  0x20    /* Disable mouse interface */
373#define KBD_MODE_KCC            0x40    /* Scan code conversion to PC format */
374#define KBD_MODE_RFU            0x80
375
376SPR_RW(DEC)
377SPR_RO(PVR)
378
379#endif /* USE_KBD_SUPPORT */
380
381/* Early messages after mm init but before console init are kept in log
382 * buffers.
383 */
384#define PAGE_LOG_CHARS (PAGE_SIZE-sizeof(int)-sizeof(u_long)-1)
385
386typedef struct _console_log {
387        struct _console_log *next;
388        int offset;
389        u_char data[PAGE_LOG_CHARS];
390} console_log;
391
392#ifdef STATIC_LOG_ALLOC
393
394#define STATIC_LOG_DATA_PAGE_NB 3
395
396static  u_char  log_page_pool   [STATIC_LOG_DATA_PAGE_NB * PAGE_SIZE];
397
398#endif
399
400static board_memory_map mem_map = {
401  (__io_ptr) _IO_BASE,          /* from libcpu/io.h */
402  (__io_ptr) _ISA_MEM_BASE,
403};
404
405board_memory_map *ptr_mem_map = &mem_map;
406
407struct _console_global_data {
408        console_log *log;
409        int vacuum_sent;
410        int lines;
411        int cols;
412        int orig_x;
413        int orig_y;
414        u_char shfts, ctls, alts, caps;
415} console_global_data = {NULL, 0, 25, 80, 0, 24, 0, 0, 0, 0};
416
417typedef struct console_io {
418        void    (*putc) (const u_char);
419        int     (*getc) (void);
420        int     (*tstc) (void);
421}console_io;
422
423extern console_io* curIo;
424
425void debug_putc(const u_char c)
426{
427  curIo->putc(c);
428}
429
430/* const char arg to be compatible with BSP_output_char decl. */
431void
432debug_putc_onlcr(const char c)
433{
434        if ('\n'==c)
435                debug_putc('\r');
436        debug_putc(c);
437}
438
439int debug_getc(void)
440{
441  return curIo->getc();
442}
443
444int debug_tstc(void)
445{
446  return curIo->tstc();
447}
448
449#define vidmem ((__io_ptr)(ptr_mem_map->isa_mem_base+0xb8000))
450
451void vacuum_putc(u_char c) {
452        console_global_data.vacuum_sent++;
453}
454
455int vacuum_getc(void) {
456        return -1;
457}
458
459int 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
504void 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((const char)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
557void serial_putc(const u_char c)
558{
559        while ((INL_CONSOLE_INB(lsr) & LSR_THRE) == 0) ;
560        INL_CONSOLE_OUTB(thr, c);
561}
562
563int serial_getc(void)
564{
565        while ((INL_CONSOLE_INB(lsr) & LSR_DR) == 0) ;
566        return (INL_CONSOLE_INB(rbr));
567}
568
569int 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
600void
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
819int 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
895void  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}
906
907#endif
908
909/* Necessary to avoid including a library, and GCC won't do this inline. */
910#define div10(num, rmd)                                                  \
911do {    uint32_t t1, t2, t3;                                                     \
912        __asm__ ("lis %4,0xcccd; "                                               \
913            "addi %4,%4,0xffffcccd; "   /* Build 0xcccccccd */           \
914            "mulhwu %3,%0+1,%4; "       /* (num.l*cst.l).h  */           \
915            "mullw %2,%0,%4; "          /* (num.h*cst.l).l  */           \
916            "addc %3,%3,%2; "                                            \
917            "mulhwu %2,%0,%4; "         /* (num.h*cst.l).h  */           \
918            "addi %4,%4,-1; "           /* Build 0xcccccccc */           \
919            "mullw %1,%0,%4; "          /* (num.h*cst.h).l  */           \
920            "adde %2,%2,%1; "                                            \
921            "mulhwu %1,%0,%4; "         /* (num.h*cst.h).h  */           \
922            "addze %1,%1; "                                              \
923            "mullw %0,%0+1,%4; "        /* (num.l*cst.h).l  */           \
924            "addc %3,%3,%0; "                                            \
925            "mulhwu %0,%0+1,%4; "       /* (num.l*cst.h).h  */           \
926            "adde %2,%2,%0; "                                            \
927            "addze %1,%1; "                                              \
928            "srwi %2,%2,3; "                                             \
929            "srwi %0,%1,3; "                                             \
930            "rlwimi %2,%1,29,0,2; "                                      \
931            "mulli %4,%2,10; "                                           \
932            "sub %4,%0+1,%4; "                                           \
933            "mr %0+1,%2; " :                                             \
934            "=r" (num), "=&r" (t1), "=&r" (t2), "=&r"(t3), "=&b" (rmd) : \
935            "0" (num));                                                  \
936                                                                         \
937} while(0);
938
939#define SIGN    1               /* unsigned/signed long */
940#define LARGE   2               /* use 'ABCDEF' instead of 'abcdef' */
941#define HEX     4               /* hexadecimal instead of decimal */
942#define ADDR    8               /* Value is an addres (p) */
943#define ZEROPAD 16              /* pad with zero */
944#define HALF    32
945#define LONG    64              /* long argument */
946#define LLONG   128             /* 64 bit argument */
947
948#if defined(__BOOT__)
949static char * number(char * str, int size, int type, uint64_t num)
950{
951        char fill,sign,tmp[24];
952        const char *digits="0123456789abcdef";
953        int i;
954
955        if (type & LARGE)
956                digits = "0123456789ABCDEF";
957        fill = (type & ZEROPAD) ? '0' : ' ';
958        sign = 0;
959        if (type & SIGN) {
960                if ((int64_t)num <0) {
961                        sign = '-';
962                        num = -num;
963                        size--;
964                }
965        }
966
967        i = 0;
968        do {
969                unsigned rem;
970                if (type&HEX) {
971                        rem = num & 0x0f;
972                        num >>=4;
973                } else {
974                        div10(num, rem);
975                }
976                tmp[i++] = digits[rem];
977        } while (num != 0);
978
979        size -= i;
980        if (!(type&(ZEROPAD)))
981                while(size-->0)
982                        *str++ = ' ';
983        if (sign)
984                *str++ = sign;
985
986        while (size-- > 0)
987                *str++ = fill;
988        while (i-- > 0)
989                *str++ = tmp[i];
990        while (size-- > 0)
991                *str++ = ' ';
992        return str;
993}
994
995int k_vsprintf(char *buf, const char *fmt, va_list args)
996{
997        int len;
998        uint64_t num;
999        int i;
1000        char * str;
1001        const char *s;
1002
1003        int flags;              /* flags to number() and private */
1004
1005        int field_width;        /* width of output field */
1006
1007        for (str=buf ; *fmt ; ++fmt) {
1008                if (*fmt != '%') {
1009                        *str++ = *fmt;
1010                        continue;
1011                }
1012
1013                /* process flags, only 0 padding needed */
1014                flags = 0;
1015                if (*++fmt == '0' ) {
1016                        flags |= ZEROPAD;
1017                        fmt++;
1018                }
1019
1020                /* get field width */
1021                field_width = -1;
1022                if (is_digit(*fmt))
1023                        field_width = skip_atoi(&fmt);
1024
1025                /* get the conversion qualifier */
1026                if (*fmt == 'h') {
1027                        flags |= HALF;
1028                        fmt++;
1029                } else if (*fmt == 'L') {
1030                        flags |= LLONG;
1031                        fmt++;
1032                } else if (*fmt == 'l') {
1033                        flags |= LONG;
1034                        fmt++;
1035                }
1036
1037                switch (*fmt) {
1038                case 'c':
1039                        *str++ = (unsigned char) va_arg(args, int);
1040                        while (--field_width > 0)
1041                                *str++ = ' ';
1042                        continue;
1043
1044                case 's':
1045                        s = va_arg(args, char *);
1046                        len = strlen(s);
1047
1048                        for (i = 0; i < len; ++i)
1049                                *str++ = *s++;
1050                        while (len < field_width--)
1051                                *str++ = ' ';
1052                        continue;
1053
1054                case 'p':
1055                        if (field_width == -1) {
1056                                field_width = 2*sizeof(void *);
1057                        }
1058                        flags |= ZEROPAD|HEX|ADDR;
1059                        break;
1060
1061                case 'X':
1062                        flags |= LARGE;
1063                case 'x':
1064                        flags |= HEX;
1065                        break;
1066
1067                case 'd':
1068                case 'i':
1069                        flags |= SIGN;
1070                case 'u':
1071                        break;
1072
1073                default:
1074                        if (*fmt != '%')
1075                                *str++ = '%';
1076                        if (*fmt)
1077                                *str++ = *fmt;
1078                        else
1079                                --fmt;
1080                        continue;
1081                }
1082                /* This ugly code tries to minimize the number of va_arg()
1083                 * since they expand to a lot of code on PPC under the SYSV
1084                 * calling conventions (but not with -mcall-aix which has
1085                 * other problems). Arguments have at least the size of a
1086                 * long allocated, and we use this fact to minimize bloat.
1087                 * (and pointers are assimilated to unsigned long too).
1088                 */
1089                if (sizeof(long long) > sizeof(long) && flags & LLONG)
1090                        num = va_arg(args, unsigned long long);
1091                else {
1092                        u_long n = va_arg(args, unsigned long);
1093                        if (flags & HALF) {
1094                                if (flags & SIGN)
1095                                        n = (short) n;
1096                                else
1097                                        n = (unsigned short) n;
1098                        } else if (!(flags & LONG)) {
1099                                /* Here the compiler correctly removes this
1100                                 * do nothing code on 32 bit PPC.
1101                                 */
1102                                if (flags & SIGN)
1103                                        n = (int) n;
1104                                else
1105                                        n = (unsigned) n;
1106                        }
1107                        if (flags & SIGN)  num = (long) n; else num = n;
1108                }
1109                str = number(str, field_width, flags, num);
1110        }
1111        *str = '\0';
1112        return str-buf;
1113}
1114#endif
Note: See TracBrowser for help on using the repository browser.