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

Last change on this file since 116633f was 116633f, checked in by Joel Sherrill <joel.sherrill@…>, on 09/04/03 at 18:45:20

2003-09-04 Joel Sherrill <joel@…>

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