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

4.104.114.84.95
Last change on this file since 969de1f3 was acc25ee, checked in by Joel Sherrill <joel.sherrill@…>, on 12/02/99 at 14:31:19

Merged of mcp750 and mvme2307 BSP by Eric Valette <valette@…>.
As part of this effort, the mpc750 libcpu code is now shared with the
ppc6xx.

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