source: rtems/c/src/lib/libbsp/powerpc/mcp750/console/polled_io.c @ fcee56c0

4.104.114.84.95
Last change on this file since fcee56c0 was fcee56c0, checked in by Joel Sherrill <joel.sherrill@…>, on 07/01/99 at 23:39:13

Patch from Eric Valette <valette@…> to clean up the
previous submission.

  • Property mode set to 100644
File size: 28.5 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
409void * memset(void *p, int c, size_t n) {
410        char *q =p;
411        for(; n>0; --n) *q++=c;
412        return p;
413}
414
415void * memcpy(void *dst, const void * src, size_t n) {
416        u_char *d=dst;
417        const u_char *s=src;
418        while(n-- > 0) *d++=*s++;
419        return dst;
420}
421
422char * strcat(char * dest, const char * src)
423{
424        char *tmp = dest;
425
426        while (*dest)
427                dest++;
428        while ((*dest++ = *src++) != '\0')
429                ;
430
431        return tmp;
432}
433
434/* The decrementer is present on all processors and the RTC on the 601
435 * has the annoying characteristic of jumping from 1e9 to 0, so we
436 * use the decrementer.
437 */
438void udelay(int us) {
439        us = us*ticks_per_ms/1000;
440        _write_DEC(us);
441        while((int)_read_DEC() >= 0);
442}
443
444void debug_putc(const u_char c)
445{
446  curIo->putc(c);
447}
448
449int debug_getc(void)
450{
451  return curIo->getc();
452}
453
454int debug_tstc(void)
455{
456  return curIo->tstc();
457}
458
459
460
461#define vidmem ((__io_ptr)(ptr_mem_map->isa_mem_base+0xb8000))
462
463void vacuum_putc(u_char c) {
464        console_global_data.vacuum_sent++;
465}
466
467int vacuum_getc(void) {
468        return -1;
469}
470
471int vacuum_tstc(void) {
472        return 0;
473}
474
475/*
476 * COM1 NS16550 support
477 */
478
479#define rbr 0
480#define ier 1
481#define fcr 2
482#define lcr 3
483#define mcr 4
484#define lsr 5
485#define msr 6
486#define scr 7
487#define thr rbr
488#define iir fcr
489#define dll rbr
490#define dlm ier
491
492#define LSR_DR   0x01  /* Data ready */
493#define LSR_OE   0x02  /* Overrun */
494#define LSR_PE   0x04  /* Parity error */
495#define LSR_FE   0x08  /* Framing error */
496#define LSR_BI   0x10  /* Break */
497#define LSR_THRE 0x20  /* Xmit holding register empty */
498#define LSR_TEMT 0x40  /* Xmitter empty */
499#define LSR_ERR  0x80  /* Error */
500
501#define COM1    0x3F8
502
503#ifdef STATIC_LOG_ALLOC
504static int global_index = 0;
505
506static void *__palloc(int s)
507{
508  if (global_index ==( STATIC_LOG_DATA_PAGE_NB - 1) ) return (void*) 0;
509  return  (void*) log_page_pool [PAGE_SIZE * global_index++];
510}
511
512static void pfree(void* p)
513{
514  --global_index;
515}
516#endif
517 
518
519void log_putc(const u_char c) {
520        console_log *l;
521        for(l=console_global_data.log; l; l=l->next) {
522                if (l->offset<PAGE_LOG_CHARS) break;
523        }
524        if (!l) {
525                l=__palloc(sizeof(console_log));
526                memset(l, 0, sizeof(console_log));
527                if (!console_global_data.log)
528                        console_global_data.log = l;
529                else {
530                        console_log *p;
531                        for (p=console_global_data.log;
532                             p->next; p=p->next);
533                        p->next = l;
534                }
535        }
536        l->data[l->offset++] = c;
537}
538
539/* This puts is non standard since it does not automatically add a newline
540 * at the end. So it is made private to avoid confusion in other files.
541 */
542static
543void puts(const u_char *s)
544{
545        char c;
546
547        while ( ( c = *s++ ) != '\0' ) {
548                debug_putc(c);
549                if ( c == '\n' )
550                        debug_putc('\r');
551        }
552}
553
554
555static
556void flush_log(void) {
557        console_log *p, *next;
558        if (console_global_data.vacuum_sent) {
559                printk("%d characters sent into oblivion before MM init!\n",
560                       console_global_data.vacuum_sent);
561        }
562        for(p=console_global_data.log; p; p=next) {
563                puts(p->data);
564                next = p->next;
565                pfree(p);
566        }
567}
568
569void serial_putc(const u_char c)
570{
571        while ((inb(COM1+lsr) & LSR_THRE) == 0) ;
572        outb(c, COM1+thr);
573}
574 
575int serial_getc(void)
576{
577        while ((inb(COM1+lsr) & LSR_DR) == 0) ;
578        return (inb(COM1+rbr));
579}
580
581int serial_tstc(void)
582{
583        return ((inb(COM1+lsr) & LSR_DR) != 0);
584}
585
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        outb(14, 0x3D4);
606        outb(pos>>8, 0x3D5);
607        outb(15, 0x3D4);
608        outb(pos, 0x3D5);
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
647/* Keyboard support */
648static int kbd_getc(void)
649{
650        unsigned char dt, brk, val;
651        unsigned code;
652loop:
653        while((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0) ;
654
655        dt = inb(KBD_DATA_REG);
656
657        brk = dt & 0x80;        /* brk == 1 on key release */
658        dt = dt & 0x7f;         /* keycode */
659
660        if (console_global_data.shfts)
661            code = shift_map[dt];
662        else if (console_global_data.ctls)
663            code = ctrl_map[dt];
664        else
665            code = plain_map[dt];
666
667        val = KVAL(code);
668        switch (KTYP(code) & 0x0f) {
669            case KT_LATIN:
670                if (brk)
671                    break;
672                if (console_global_data.alts)
673                    val |= 0x80;
674                if (val == 0x7f)        /* map delete to backspace */
675                    val = '\b';
676                return val;
677
678            case KT_LETTER:
679                if (brk)
680                    break;
681                if (console_global_data.caps)
682                    val -= 'a'-'A';
683                return val;
684
685            case KT_SPEC:
686                if (brk)
687                    break;
688                if (val == KVAL(K_CAPS))
689                    console_global_data.caps = !console_global_data.caps;
690                else if (val == KVAL(K_ENTER)) {
691enter:              /* Wait for key up */
692                    while (1) {
693                        while((inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0) ;
694                        dt = inb(KBD_DATA_REG);
695                        if (dt & 0x80) /* key up */ break;
696                    }
697                    return 10;
698                }
699                break;
700
701            case KT_PAD:
702                if (brk)
703                    break;
704                if (val < 10)
705                    return val;
706                if (val == KVAL(K_PENTER))
707                    goto enter;
708                break;
709
710            case KT_SHIFT:
711                switch (val) {
712                    case KG_SHIFT:
713                    case KG_SHIFTL:
714                    case KG_SHIFTR:
715                        console_global_data.shfts = brk ? 0 : 1;
716                        break;
717                    case KG_ALT:
718                    case KG_ALTGR:
719                        console_global_data.alts = brk ? 0 : 1;
720                        break;
721                    case KG_CTRL:
722                    case KG_CTRLL:
723                    case KG_CTRLR:
724                        console_global_data.ctls = brk ? 0 : 1;
725                        break;
726                }
727                break;
728
729            case KT_LOCK:
730                switch (val) {
731                    case KG_SHIFT:
732                    case KG_SHIFTL:
733                    case KG_SHIFTR:
734                        if (brk)
735                            console_global_data.shfts = !console_global_data.shfts;
736                        break;
737                    case KG_ALT:
738                    case KG_ALTGR:
739                        if (brk)
740                            console_global_data.alts = !console_global_data.alts;
741                        break;
742                    case KG_CTRL:
743                    case KG_CTRLL:
744                    case KG_CTRLR:
745                        if (brk)
746                            console_global_data.ctls = !console_global_data.ctls;
747                        break;
748                }
749                break;
750        }
751        /* if (brk) return (0); */  /* Ignore initial 'key up' codes */
752        goto loop;
753}
754
755static int kbd_get(int ms) {
756        int status, data;
757        while(1) {
758                status = inb(KBD_STATUS_REG);
759                if (status & KBD_STAT_OBF) {
760                        data = inb(KBD_DATA_REG);
761                        if (status & (KBD_STAT_GTO | KBD_STAT_PERR))
762                                return -1;
763                        else
764                                return data;
765                }
766                if (--ms < 0) return -1;
767                udelay(1000);
768        }
769}
770
771static void kbd_put(u_char c, int ms, int port) {
772        while (inb(KBD_STATUS_REG) & KBD_STAT_IBF) {
773                if (--ms < 0) return;
774                udelay(1000);
775        }
776        outb(c, port);
777}
778
779int kbdreset(void)
780{
781        int c;
782
783        /* Flush all pending data */
784        while(kbd_get(10) != -1);
785
786        /* Send self-test */
787        kbd_put(KBD_CCMD_SELF_TEST, 10, KBD_CNTL_REG);
788        c = kbd_get(1000);
789        if (c != 0x55) return 1;
790
791        /* Enable then reset the KB */
792        kbd_put(KBD_CCMD_KBD_ENABLE, 10, KBD_CNTL_REG);
793       
794        while (1) {
795                kbd_put(KBD_CMD_RESET, 10, KBD_DATA_REG);
796                c = kbd_get(1000);
797                if (c == KBD_REPLY_ACK) break;
798                if (c != KBD_REPLY_RESEND) return 2;
799        }
800       
801        if (kbd_get(1000) != KBD_REPLY_POR) return 3;
802
803        /* Disable the keyboard while setting up the controller */
804        kbd_put(KBD_CMD_DISABLE, 10, KBD_DATA_REG);
805        if (kbd_get(10)!=KBD_REPLY_ACK) return 4;
806
807        /* Enable interrupts and keyboard controller */
808        kbd_put(KBD_CCMD_WRITE_MODE, 10, KBD_CNTL_REG);
809        kbd_put(KBD_MODE_KBD_INT | KBD_MODE_SYS |
810                KBD_MODE_DISABLE_MOUSE | KBD_MODE_KCC,
811                10, KBD_DATA_REG);
812
813        /* Reenable the keyboard */
814        kbd_put(KBD_CMD_ENABLE, 10, KBD_DATA_REG);
815        if (kbd_get(10)!=KBD_REPLY_ACK) return 5;
816
817        return 0;
818}
819
820int kbd_tstc(void)
821{
822        return ((inb(KBD_STATUS_REG) & KBD_STAT_OBF) != 0);
823}
824
825const struct console_io
826vacuum_console_functions = {
827        vacuum_putc,
828        vacuum_getc,
829        vacuum_tstc
830};
831
832static const struct console_io
833log_console_functions = {
834        log_putc,
835        vacuum_getc,
836        vacuum_tstc
837},
838
839serial_console_functions = {
840        serial_putc,
841        serial_getc,
842        serial_tstc
843},
844
845vga_console_functions = {
846        vga_putc,
847        kbd_getc,
848        kbd_tstc
849};
850
851console_io* curIo = &vacuum_console_functions;
852
853int select_console(ioType t) {
854  static ioType curType = CONSOLE_VACUUM;
855 
856  switch (t) {
857  case CONSOLE_VACUUM   : curIo = &vacuum_console_functions; break;
858  case CONSOLE_LOG      : curIo = &log_console_functions; break;
859  case CONSOLE_SERIAL   : curIo = &serial_console_functions; break;
860  case CONSOLE_VGA      : curIo = &vga_console_functions; break;
861  default               : curIo = &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
872static int skip_atoi(const char **s)
873{
874        int i=0;
875
876        while (is_digit(**s))
877                i = i*10 + *((*s)++) - '0';
878        return i;
879}
880
881/* Based on linux/lib/vsprintf.c and modified to suit our needs,
882 * bloat has been limited since we basically only need %u, %x, %s and %c.
883 * But we need 64 bit values !
884 */
885
886int printk(const char *fmt, ...) {
887        va_list args;
888        int i;
889        /* Should not be a problem with 8kB of stack */
890        char buf[1024];
891       
892        va_start(args, fmt);
893        i = vsprintf(buf, fmt, args);
894        va_end(args);
895        puts(buf);
896        return  i;
897}
898
899/* Necessary to avoid including a library, and GCC won't do this inline. */
900#define div10(num, rmd)                                                  \
901do {    u32 t1, t2, t3;                                                  \
902        asm("lis %4,0xcccd; "                                            \
903            "addi %4,%4,0xffffcccd; "   /* Build 0xcccccccd */           \
904            "mulhwu %3,%0+1,%4; "       /* (num.l*cst.l).h  */           \
905            "mullw %2,%0,%4; "          /* (num.h*cst.l).l  */           \
906            "addc %3,%3,%2; "                                            \
907            "mulhwu %2,%0,%4; "         /* (num.h*cst.l).h  */           \
908            "addi %4,%4,-1; "           /* Build 0xcccccccc */           \
909            "mullw %1,%0,%4; "          /* (num.h*cst.h).l  */           \
910            "adde %2,%2,%1; "                                            \
911            "mulhwu %1,%0,%4; "         /* (num.h*cst.h).h  */           \
912            "addze %1,%1; "                                              \
913            "mullw %0,%0+1,%4; "        /* (num.l*cst.h).l  */           \
914            "addc %3,%3,%0; "                                            \
915            "mulhwu %0,%0+1,%4; "       /* (num.l*cst.h).h  */           \
916            "adde %2,%2,%0; "                                            \
917            "addze %1,%1; "                                              \
918            "srwi %2,%2,3; "                                             \
919            "srwi %0,%1,3; "                                             \
920            "rlwimi %2,%1,29,0,2; "                                      \
921            "mulli %4,%2,10; "                                           \
922            "sub %4,%0+1,%4; "                                           \
923            "mr %0+1,%2; " :                                             \
924            "=r" (num), "=&r" (t1), "=&r" (t2), "=&r"(t3), "=&b" (rmd) : \
925            "0" (num));                                                  \
926                                                                         \
927} while(0);
928
929#define SIGN    1               /* unsigned/signed long */
930#define LARGE   2               /* use 'ABCDEF' instead of 'abcdef' */
931#define HEX     4               /* hexadecimal instead of decimal */
932#define ADDR    8               /* Value is an addres (p) */
933#define ZEROPAD 16              /* pad with zero */
934#define HALF    32
935#define LONG    64              /* long argument */
936#define LLONG   128             /* 64 bit argument */
937
938static char * number(char * str, int size, int type, u64 num)
939{
940        char fill,sign,tmp[24];
941        const char *digits="0123456789abcdef";
942        int i;
943
944        if (type & LARGE)
945                digits = "0123456789ABCDEF";
946        fill = (type & ZEROPAD) ? '0' : ' ';
947        sign = 0;
948        if (type & SIGN) {
949                if ((s64)num <0) {
950                        sign = '-';
951                        num = -num;
952                        size--;
953                }
954        }
955
956        i = 0;
957        do {
958                unsigned rem;
959                if (type&HEX) {
960                        rem = num & 0x0f;
961                        num >>=4;
962                } else {
963                        div10(num, rem);
964                }
965                tmp[i++] = digits[rem];
966        } while (num != 0);
967               
968        size -= i;
969        if (!(type&(ZEROPAD)))
970                while(size-->0)
971                        *str++ = ' ';
972        if (sign)
973                *str++ = sign;
974
975        while (size-- > 0)
976                *str++ = fill;
977        while (i-- > 0)
978                *str++ = tmp[i];
979        while (size-- > 0)
980                *str++ = ' ';
981        return str;
982}
983
984int vsprintf(char *buf, const char *fmt, va_list args)
985{
986        int len;
987        u64 num;
988        int i;
989        char * str;
990        const char *s;
991
992        int flags;              /* flags to number() and private */
993
994        int field_width;        /* width of output field */
995
996        for (str=buf ; *fmt ; ++fmt) {
997                if (*fmt != '%') {
998                        *str++ = *fmt;
999                        continue;
1000                }
1001                       
1002                /* process flags, only 0 padding needed */
1003                flags = 0;
1004                if (*++fmt == '0' ) {
1005                        flags |= ZEROPAD;
1006                        fmt++;
1007                }
1008               
1009                /* get field width */
1010                field_width = -1;
1011                if (is_digit(*fmt))
1012                        field_width = skip_atoi(&fmt);
1013
1014                /* get the conversion qualifier */
1015                if (*fmt == 'h') {
1016                        flags |= HALF;
1017                        fmt++;
1018                } else if (*fmt == 'L') {
1019                        flags |= LLONG;
1020                        fmt++;
1021                } else if (*fmt == 'l') {
1022                        flags |= LONG;
1023                        fmt++;
1024                }
1025
1026                switch (*fmt) {
1027                case 'c':
1028                        *str++ = (unsigned char) va_arg(args, int);
1029                        while (--field_width > 0)
1030                                *str++ = ' ';
1031                        continue;
1032
1033                case 's':
1034                        s = va_arg(args, char *);
1035                        len = strlen(s);
1036
1037                        for (i = 0; i < len; ++i)
1038                                *str++ = *s++;
1039                        while (len < field_width--)
1040                                *str++ = ' ';
1041                        continue;
1042
1043                case 'p':
1044                        if (field_width == -1) {
1045                                field_width = 2*sizeof(void *);
1046                        }
1047                        flags |= ZEROPAD|HEX|ADDR;
1048                        break;
1049
1050                case 'X':
1051                        flags |= LARGE;
1052                case 'x':
1053                        flags |= HEX;
1054                        break;
1055
1056                case 'd':
1057                case 'i':
1058                        flags |= SIGN;
1059                case 'u':
1060                        break;
1061
1062                default:
1063                        if (*fmt != '%')
1064                                *str++ = '%';
1065                        if (*fmt)
1066                                *str++ = *fmt;
1067                        else
1068                                --fmt;
1069                        continue;
1070                }
1071                /* This ugly code tries to minimize the number of va_arg()
1072                 * since they expand to a lot of code on PPC under the SYSV
1073                 * calling conventions (but not with -mcall-aix which has
1074                 * other problems). Arguments have at least the size of a
1075                 * long allocated, and we use this fact to minimize bloat.
1076                 * (and pointers are assimilated to unsigned long too).
1077                 */
1078                if (sizeof(long long) > sizeof(long) && flags & LLONG)
1079                        num = va_arg(args, unsigned long long);
1080                else {
1081                        u_long n = va_arg(args, unsigned long);
1082                        if (flags & HALF) {
1083                                if (flags & SIGN)
1084                                        n = (short) n;
1085                                else
1086                                        n = (unsigned short) n;
1087                        } else if (! flags & LONG) {
1088                                /* Here the compiler correctly removes this
1089                                 * do nothing code on 32 bit PPC.
1090                                 */
1091                                if (flags & SIGN)
1092                                        n = (int) n;
1093                                else
1094                                        n = (unsigned) n;
1095                        }
1096                        if (flags & SIGN)  num = (long) n; else num = n;
1097                }
1098                str = number(str, field_width, flags, num);
1099        }
1100        *str = '\0';
1101        return str-buf;
1102}
Note: See TracBrowser for help on using the repository browser.