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

5
Last change on this file since 89f627b5 was 89f627b5, checked in by Sebastian Huber <sebastian.huber@…>, on 06/08/16 at 14:03:12

bsps/powerpc: Update to RTEMS printer changes

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