Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:54

0001 /*
0002  *  polled_io.c -- Basic input/output for early boot
0003  *
0004  *  Copyright (C) 1998, 1999 Gabriel Paubert, paubert@iram.es
0005  *
0006  *  Modified to compile in RTEMS development environment
0007  *  by Eric Valette
0008  *
0009  *  Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
0010  *
0011  *  The license and distribution terms for this file may be
0012  *  found in the file LICENSE in this distribution or at
0013  *  http://www.rtems.org/license/LICENSE.
0014  */
0015 
0016 #include <sys/param.h>
0017 #include <sys/types.h>
0018 #include <libcpu/byteorder.h>
0019 #include <libcpu/mmu.h>
0020 #include <libcpu/io.h>
0021 #include <string.h>
0022 #include <stdarg.h>
0023 #include <bsp/consoleIo.h>
0024 #include <bsp.h>
0025 #include <libcpu/spr.h>
0026 
0027 #ifndef __BOOT__
0028 #define STATIC_LOG_ALLOC
0029 #endif
0030 
0031 #ifdef BSP_KBD_IOBASE
0032 #define USE_KBD_SUPPORT
0033 #endif
0034 #ifdef BSP_VGA_IOBASE
0035 #define USE_VGA_SUPPORT
0036 #endif
0037 
0038 #ifdef USE_KBD_SUPPORT
0039 #include "keyboard.h"
0040 #endif
0041 #include "console.inl"
0042 
0043 #ifdef __BOOT__
0044 extern void boot_udelay(uint32_t   _microseconds);
0045 void * __palloc(u_long);
0046 void  pfree(void *);
0047 #else
0048 #include <rtems/bspIo.h>
0049 #endif
0050 
0051 #ifndef __BOOT__
0052 BSP_output_char_function_type     BSP_output_char = debug_putc;
0053 BSP_polling_getchar_function_type BSP_poll_char = NULL;
0054 #endif
0055 
0056 #ifdef USE_KBD_SUPPORT
0057 unsigned short plain_map[NR_KEYS] = {
0058     0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036,
0059     0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf07f, 0xf009,
0060     0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
0061     0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201, 0xf702, 0xfb61, 0xfb73,
0062     0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b,
0063     0xf027, 0xf060, 0xf700, 0xf05c, 0xfb7a, 0xfb78, 0xfb63, 0xfb76,
0064     0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf700, 0xf30c,
0065     0xf703, 0xf020, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
0066     0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf209, 0xf307,
0067     0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
0068     0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03c, 0xf10a,
0069     0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0070     0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
0071     0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
0072     0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
0073     0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0074 };
0075 
0076 unsigned short shift_map[NR_KEYS] = {
0077     0xf200, 0xf01b, 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e,
0078     0xf026, 0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf07f, 0xf009,
0079     0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, 0xfb59, 0xfb55, 0xfb49,
0080     0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf201, 0xf702, 0xfb41, 0xfb53,
0081     0xfb44, 0xfb46, 0xfb47, 0xfb48, 0xfb4a, 0xfb4b, 0xfb4c, 0xf03a,
0082     0xf022, 0xf07e, 0xf700, 0xf07c, 0xfb5a, 0xfb58, 0xfb43, 0xfb56,
0083     0xfb42, 0xfb4e, 0xfb4d, 0xf03c, 0xf03e, 0xf03f, 0xf700, 0xf30c,
0084     0xf703, 0xf020, 0xf207, 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf10e,
0085     0xf10f, 0xf110, 0xf111, 0xf112, 0xf113, 0xf213, 0xf203, 0xf307,
0086     0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
0087     0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03e, 0xf10a,
0088     0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0089     0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
0090     0xf20b, 0xf601, 0xf602, 0xf117, 0xf600, 0xf20a, 0xf115, 0xf116,
0091     0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
0092     0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0093 };
0094 
0095 unsigned short altgr_map[NR_KEYS] = {
0096     0xf200, 0xf200, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200,
0097     0xf07b, 0xf05b, 0xf05d, 0xf07d, 0xf05c, 0xf200, 0xf200, 0xf200,
0098     0xfb71, 0xfb77, 0xf918, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
0099     0xfb6f, 0xfb70, 0xf200, 0xf07e, 0xf201, 0xf702, 0xf914, 0xfb73,
0100     0xf917, 0xf919, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf200,
0101     0xf200, 0xf200, 0xf700, 0xf200, 0xfb7a, 0xfb78, 0xf916, 0xfb76,
0102     0xf915, 0xfb6e, 0xfb6d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
0103     0xf703, 0xf200, 0xf207, 0xf50c, 0xf50d, 0xf50e, 0xf50f, 0xf510,
0104     0xf511, 0xf512, 0xf513, 0xf514, 0xf515, 0xf208, 0xf202, 0xf911,
0105     0xf912, 0xf913, 0xf30b, 0xf90e, 0xf90f, 0xf910, 0xf30a, 0xf90b,
0106     0xf90c, 0xf90d, 0xf90a, 0xf310, 0xf206, 0xf200, 0xf07c, 0xf516,
0107     0xf517, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0108     0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
0109     0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
0110     0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
0111     0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0112 };
0113 
0114 unsigned short ctrl_map[NR_KEYS] = {
0115     0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e,
0116     0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200,
0117     0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
0118     0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013,
0119     0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
0120     0xf007, 0xf000, 0xf700, 0xf01c, 0xf01a, 0xf018, 0xf003, 0xf016,
0121     0xf002, 0xf00e, 0xf00d, 0xf200, 0xf20e, 0xf07f, 0xf700, 0xf30c,
0122     0xf703, 0xf000, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
0123     0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf204, 0xf307,
0124     0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
0125     0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf10a,
0126     0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0127     0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
0128     0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
0129     0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
0130     0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0131 };
0132 
0133 unsigned short shift_ctrl_map[NR_KEYS] = {
0134     0xf200, 0xf200, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200,
0135     0xf200, 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200,
0136     0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
0137     0xf00f, 0xf010, 0xf200, 0xf200, 0xf201, 0xf702, 0xf001, 0xf013,
0138     0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
0139     0xf200, 0xf200, 0xf700, 0xf200, 0xf01a, 0xf018, 0xf003, 0xf016,
0140     0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
0141     0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0142     0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf208, 0xf200, 0xf307,
0143     0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
0144     0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf200,
0145     0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0146     0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
0147     0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
0148     0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
0149     0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0150 };
0151 
0152 unsigned short alt_map[NR_KEYS] = {
0153     0xf200, 0xf81b, 0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836,
0154     0xf837, 0xf838, 0xf839, 0xf830, 0xf82d, 0xf83d, 0xf87f, 0xf809,
0155     0xf871, 0xf877, 0xf865, 0xf872, 0xf874, 0xf879, 0xf875, 0xf869,
0156     0xf86f, 0xf870, 0xf85b, 0xf85d, 0xf80d, 0xf702, 0xf861, 0xf873,
0157     0xf864, 0xf866, 0xf867, 0xf868, 0xf86a, 0xf86b, 0xf86c, 0xf83b,
0158     0xf827, 0xf860, 0xf700, 0xf85c, 0xf87a, 0xf878, 0xf863, 0xf876,
0159     0xf862, 0xf86e, 0xf86d, 0xf82c, 0xf82e, 0xf82f, 0xf700, 0xf30c,
0160     0xf703, 0xf820, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
0161     0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf209, 0xf907,
0162     0xf908, 0xf909, 0xf30b, 0xf904, 0xf905, 0xf906, 0xf30a, 0xf901,
0163     0xf902, 0xf903, 0xf900, 0xf310, 0xf206, 0xf200, 0xf83c, 0xf50a,
0164     0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0165     0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
0166     0xf118, 0xf210, 0xf211, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
0167     0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
0168     0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0169 };
0170 
0171 unsigned short ctrl_alt_map[NR_KEYS] = {
0172     0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0173     0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0174     0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809,
0175     0xf80f, 0xf810, 0xf200, 0xf200, 0xf201, 0xf702, 0xf801, 0xf813,
0176     0xf804, 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c, 0xf200,
0177     0xf200, 0xf200, 0xf700, 0xf200, 0xf81a, 0xf818, 0xf803, 0xf816,
0178     0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
0179     0xf703, 0xf200, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
0180     0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf200, 0xf307,
0181     0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
0182     0xf302, 0xf303, 0xf300, 0xf20c, 0xf206, 0xf200, 0xf200, 0xf50a,
0183     0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0184     0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
0185     0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf20c,
0186     0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
0187     0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0188 };
0189 
0190 ushort *key_maps[MAX_NR_KEYMAPS] = {
0191     plain_map, shift_map, altgr_map, 0,
0192     ctrl_map, shift_ctrl_map, 0, 0,
0193     alt_map, 0, 0, 0,
0194     ctrl_alt_map,   0
0195 };
0196 
0197 unsigned int keymap_count = 7;
0198 
0199 /*
0200  * Philosophy: most people do not define more strings, but they who do
0201  * often want quite a lot of string space. So, we statically allocate
0202  * the default and allocate dynamically in chunks of 512 bytes.
0203  */
0204 
0205 char func_buf[] = {
0206     '\033', '[', '[', 'A', 0,
0207     '\033', '[', '[', 'B', 0,
0208     '\033', '[', '[', 'C', 0,
0209     '\033', '[', '[', 'D', 0,
0210     '\033', '[', '[', 'E', 0,
0211     '\033', '[', '1', '7', '~', 0,
0212     '\033', '[', '1', '8', '~', 0,
0213     '\033', '[', '1', '9', '~', 0,
0214     '\033', '[', '2', '0', '~', 0,
0215     '\033', '[', '2', '1', '~', 0,
0216     '\033', '[', '2', '3', '~', 0,
0217     '\033', '[', '2', '4', '~', 0,
0218     '\033', '[', '2', '5', '~', 0,
0219     '\033', '[', '2', '6', '~', 0,
0220     '\033', '[', '2', '8', '~', 0,
0221     '\033', '[', '2', '9', '~', 0,
0222     '\033', '[', '3', '1', '~', 0,
0223     '\033', '[', '3', '2', '~', 0,
0224     '\033', '[', '3', '3', '~', 0,
0225     '\033', '[', '3', '4', '~', 0,
0226     '\033', '[', '1', '~', 0,
0227     '\033', '[', '2', '~', 0,
0228     '\033', '[', '3', '~', 0,
0229     '\033', '[', '4', '~', 0,
0230     '\033', '[', '5', '~', 0,
0231     '\033', '[', '6', '~', 0,
0232     '\033', '[', 'M', 0,
0233     '\033', '[', 'P', 0,
0234 };
0235 
0236 char *funcbufptr = func_buf;
0237 int funcbufsize = sizeof(func_buf);
0238 int funcbufleft = 0;          /* space left */
0239 
0240 char *func_table[MAX_NR_FUNC] = {
0241     func_buf + 0,
0242     func_buf + 5,
0243     func_buf + 10,
0244     func_buf + 15,
0245     func_buf + 20,
0246     func_buf + 25,
0247     func_buf + 31,
0248     func_buf + 37,
0249     func_buf + 43,
0250     func_buf + 49,
0251     func_buf + 55,
0252     func_buf + 61,
0253     func_buf + 67,
0254     func_buf + 73,
0255     func_buf + 79,
0256     func_buf + 85,
0257     func_buf + 91,
0258     func_buf + 97,
0259     func_buf + 103,
0260     func_buf + 109,
0261     func_buf + 115,
0262     func_buf + 120,
0263     func_buf + 125,
0264     func_buf + 130,
0265     func_buf + 135,
0266     func_buf + 140,
0267     func_buf + 145,
0268     0,
0269     0,
0270     func_buf + 149,
0271     0,
0272 };
0273 
0274 struct kbdiacr {
0275         unsigned char diacr, base, result;
0276 };
0277 
0278 struct kbdiacr accent_table[MAX_DIACR] = {
0279     {'`', 'A', '\300'}, {'`', 'a', '\340'},
0280     {'\'', 'A', '\301'},    {'\'', 'a', '\341'},
0281     {'^', 'A', '\302'}, {'^', 'a', '\342'},
0282     {'~', 'A', '\303'}, {'~', 'a', '\343'},
0283     {'"', 'A', '\304'}, {'"', 'a', '\344'},
0284     {'O', 'A', '\305'}, {'o', 'a', '\345'},
0285     {'0', 'A', '\305'}, {'0', 'a', '\345'},
0286     {'A', 'A', '\305'}, {'a', 'a', '\345'},
0287     {'A', 'E', '\306'}, {'a', 'e', '\346'},
0288     {',', 'C', '\307'}, {',', 'c', '\347'},
0289     {'`', 'E', '\310'}, {'`', 'e', '\350'},
0290     {'\'', 'E', '\311'},    {'\'', 'e', '\351'},
0291     {'^', 'E', '\312'}, {'^', 'e', '\352'},
0292     {'"', 'E', '\313'}, {'"', 'e', '\353'},
0293     {'`', 'I', '\314'}, {'`', 'i', '\354'},
0294     {'\'', 'I', '\315'},    {'\'', 'i', '\355'},
0295     {'^', 'I', '\316'}, {'^', 'i', '\356'},
0296     {'"', 'I', '\317'}, {'"', 'i', '\357'},
0297     {'-', 'D', '\320'}, {'-', 'd', '\360'},
0298     {'~', 'N', '\321'}, {'~', 'n', '\361'},
0299     {'`', 'O', '\322'}, {'`', 'o', '\362'},
0300     {'\'', 'O', '\323'},    {'\'', 'o', '\363'},
0301     {'^', 'O', '\324'}, {'^', 'o', '\364'},
0302     {'~', 'O', '\325'}, {'~', 'o', '\365'},
0303     {'"', 'O', '\326'}, {'"', 'o', '\366'},
0304     {'/', 'O', '\330'}, {'/', 'o', '\370'},
0305     {'`', 'U', '\331'}, {'`', 'u', '\371'},
0306     {'\'', 'U', '\332'},    {'\'', 'u', '\372'},
0307     {'^', 'U', '\333'}, {'^', 'u', '\373'},
0308     {'"', 'U', '\334'}, {'"', 'u', '\374'},
0309     {'\'', 'Y', '\335'},    {'\'', 'y', '\375'},
0310     {'T', 'H', '\336'}, {'t', 'h', '\376'},
0311     {'s', 's', '\337'}, {'"', 'y', '\377'},
0312     {'s', 'z', '\337'}, {'i', 'j', '\377'},
0313 };
0314 
0315 unsigned int accent_table_size = 68;
0316 
0317 /* These #defines have been copied from drivers/char/pc_keyb.h, by
0318  * Martin Mares (mj@ucw.cz).
0319  * converted to offsets by Till Straumann <strauman@slac.stanford.edu>
0320  */
0321 #define KBD_STATUS_REG      0x4 /* Status register (R) */
0322 #define KBD_CNTL_REG        0x4 /* Controller command register (W) */
0323 #define KBD_DATA_REG        0x0 /* Keyboard data register (R/W) */
0324 
0325 /*
0326  *  Keyboard Controller Commands
0327  */
0328 
0329 #define KBD_CCMD_WRITE_MODE 0x60    /* Write mode bits */
0330 #define KBD_CCMD_GET_VERSION    0xA1    /* Get controller version */
0331 #define KBD_CCMD_MOUSE_DISABLE  0xA7    /* Disable mouse interface */
0332 #define KBD_CCMD_MOUSE_ENABLE   0xA8    /* Enable mouse interface */
0333 #define KBD_CCMD_TEST_MOUSE 0xA9    /* Mouse interface test */
0334 #define KBD_CCMD_SELF_TEST  0xAA    /* Controller self test */
0335 #define KBD_CCMD_KBD_TEST   0xAB    /* Keyboard interface test */
0336 #define KBD_CCMD_KBD_DISABLE    0xAD    /* Keyboard interface disable */
0337 #define KBD_CCMD_KBD_ENABLE 0xAE    /* Keyboard interface enable */
0338 
0339 /*
0340  *  Keyboard Commands
0341  */
0342 
0343 #define KBD_CMD_ENABLE      0xF4    /* Enable scanning */
0344 #define KBD_CMD_DISABLE     0xF5    /* Disable scanning */
0345 #define KBD_CMD_RESET       0xFF    /* Reset */
0346 
0347 /*
0348  *  Keyboard Replies
0349  */
0350 
0351 #define KBD_REPLY_POR       0xAA    /* Power on reset */
0352 #define KBD_REPLY_ACK       0xFA    /* Command ACK */
0353 #define KBD_REPLY_RESEND    0xFE    /* Command NACK, send the cmd again */
0354 
0355 /*
0356  *  Status Register Bits
0357  */
0358 
0359 #define KBD_STAT_OBF        0x01    /* Keyboard output buffer full */
0360 #define KBD_STAT_IBF        0x02    /* Keyboard input buffer full */
0361 #define KBD_STAT_UNLOCKED   0x10    /* Zero if keyboard locked */
0362 #define KBD_STAT_GTO        0x40    /* General receive/xmit timeout */
0363 #define KBD_STAT_PERR       0x80    /* Parity error */
0364 
0365 /*
0366  *  Controller Mode Register Bits
0367  */
0368 
0369 #define KBD_MODE_KBD_INT    0x01    /* Keyboard data generate IRQ1 */
0370 #define KBD_MODE_SYS        0x04    /* The system flag (?) */
0371 #define KBD_MODE_NO_KEYLOCK 0x08    /* The keylock doesn't affect the keyboard if set */
0372 #define KBD_MODE_DISABLE_KBD    0x10    /* Disable keyboard interface */
0373 #define KBD_MODE_DISABLE_MOUSE  0x20    /* Disable mouse interface */
0374 #define KBD_MODE_KCC        0x40    /* Scan code conversion to PC format */
0375 #define KBD_MODE_RFU        0x80
0376 
0377 #endif /* USE_KBD_SUPPORT */
0378 
0379 /* Early messages after mm init but before console init are kept in log
0380  * buffers.
0381  */
0382 #define PAGE_LOG_CHARS (PAGE_SIZE-sizeof(int)-sizeof(u_long)-1)
0383 
0384 typedef struct _console_log {
0385     struct _console_log *next;
0386     int offset;
0387     u_char data[PAGE_LOG_CHARS];
0388 } console_log;
0389 
0390 #ifdef STATIC_LOG_ALLOC
0391 
0392 #define STATIC_LOG_DATA_PAGE_NB 3
0393 
0394 static  u_char  log_page_pool   [STATIC_LOG_DATA_PAGE_NB * PAGE_SIZE];
0395 
0396 #endif
0397 
0398 static board_memory_map mem_map = {
0399   (__io_ptr) _IO_BASE,      /* from libcpu/io.h */
0400   (__io_ptr) _ISA_MEM_BASE,
0401 };
0402 
0403 board_memory_map *ptr_mem_map = &mem_map;
0404 
0405 struct _console_global_data {
0406     console_log *log;
0407     int vacuum_sent;
0408     int lines;
0409     int cols;
0410     int orig_x;
0411     int orig_y;
0412     u_char shfts, ctls, alts, caps;
0413 } console_global_data = {NULL, 0, 25, 80, 0, 24, 0, 0, 0, 0};
0414 
0415 typedef struct console_io {
0416     void    (*console_io_putc)  (const u_char);
0417     int     (*console_io_getc)  (void);
0418     int     (*console_io_tstc)  (void);
0419 }console_io;
0420 
0421 extern console_io* curIo;
0422 
0423 void debug_putc(const char c)
0424 {
0425   curIo->console_io_putc(c);
0426 }
0427 
0428 /* const char arg to be compatible with BSP_output_char decl. */
0429 void
0430 debug_putc_onlcr(const char c)
0431 {
0432     if (c == '\n') {
0433         debug_putc('\r');
0434     }
0435 
0436     debug_putc(c);
0437 }
0438 
0439 int debug_getc(void)
0440 {
0441   return curIo->console_io_getc();
0442 }
0443 
0444 int debug_tstc(void)
0445 {
0446   return curIo->console_io_tstc();
0447 }
0448 
0449 #define vidmem ((__io_ptr)(ptr_mem_map->isa_mem_base+0xb8000))
0450 
0451 static void vacuum_putc(u_char c) {
0452     console_global_data.vacuum_sent++;
0453 }
0454 
0455 static int vacuum_getc(void) {
0456     return -1;
0457 }
0458 
0459 static int vacuum_tstc(void) {
0460     return 0;
0461 }
0462 
0463 /*
0464  * COM1 NS16550 support
0465  */
0466 
0467 #define rbr 0
0468 #define ier 1
0469 #define fcr 2
0470 #define lcr 3
0471 #define mcr 4
0472 #define lsr 5
0473 #define msr 6
0474 #define scr 7
0475 #define thr rbr
0476 #define iir fcr
0477 #define dll rbr
0478 #define dlm ier
0479 
0480 #define LSR_DR   0x01  /* Data ready */
0481 #define LSR_OE   0x02  /* Overrun */
0482 #define LSR_PE   0x04  /* Parity error */
0483 #define LSR_FE   0x08  /* Framing error */
0484 #define LSR_BI   0x10  /* Break */
0485 #define LSR_THRE 0x20  /* Xmit holding register empty */
0486 #define LSR_TEMT 0x40  /* Xmitter empty */
0487 #define LSR_ERR  0x80  /* Error */
0488 
0489 #ifdef STATIC_LOG_ALLOC
0490 static int global_index = 0;
0491 
0492 static void *__palloc(int s)
0493 {
0494   if (global_index ==( STATIC_LOG_DATA_PAGE_NB - 1) ) return (void*) 0;
0495   return  (void*) &(log_page_pool [PAGE_SIZE * global_index++]);
0496 }
0497 
0498 static void pfree(void* p)
0499 {
0500   --global_index;
0501 }
0502 #endif
0503 
0504 static void log_putc(const u_char c) {
0505     console_log *l;
0506     for(l=console_global_data.log; l; l=l->next) {
0507         if (l->offset<PAGE_LOG_CHARS) break;
0508     }
0509     if (!l) {
0510         l=__palloc(sizeof(console_log));
0511         memset(l, 0, sizeof(console_log));
0512         if (!console_global_data.log)
0513             console_global_data.log = l;
0514         else {
0515             console_log *p;
0516             for (p=console_global_data.log;
0517                  p->next; p=p->next);
0518             p->next = l;
0519         }
0520     }
0521     l->data[l->offset++] = c;
0522 }
0523 
0524 /* This puts is non standard since it does not automatically add a newline
0525  * at the end. So it is made private to avoid confusion in other files.
0526  */
0527 static
0528 void my_puts(const u_char *s)
0529 {
0530         char c;
0531 
0532         while ( ( c = *s++ ) != '\0' ) {
0533                 debug_putc_onlcr(c);
0534         }
0535 }
0536 
0537 static
0538 void flush_log(void) {
0539     console_log *p, *next;
0540     if (console_global_data.vacuum_sent) {
0541 #ifdef TRACE_FLUSH_LOG
0542         printk("%d characters sent into oblivion before MM init!\n",
0543                console_global_data.vacuum_sent);
0544 #endif
0545     }
0546     for(p=console_global_data.log; p; p=next) {
0547         my_puts(p->data);
0548         next = p->next;
0549         pfree(p);
0550     }
0551 }
0552 
0553 #ifndef INL_CONSOLE_INB
0554 #error "BSP probably didn't define a console port"
0555 #endif
0556 
0557 static void serial_putc(const u_char c)
0558 {
0559     while ((INL_CONSOLE_INB(lsr) & LSR_THRE) == 0) ;
0560     INL_CONSOLE_OUTB(thr, c);
0561 }
0562 
0563 static int serial_getc(void)
0564 {
0565     while ((INL_CONSOLE_INB(lsr) & LSR_DR) == 0) ;
0566     return (INL_CONSOLE_INB(rbr));
0567 }
0568 
0569 static int serial_tstc(void)
0570 {
0571     return ((INL_CONSOLE_INB(lsr) & LSR_DR) != 0);
0572 }
0573 
0574 #ifdef USE_VGA_SUPPORT
0575 static void scroll(void)
0576 {
0577     int i;
0578 
0579     memcpy ( (u_char *)vidmem, (u_char *)vidmem + console_global_data.cols * 2,
0580          ( console_global_data.lines - 1 ) * console_global_data.cols * 2 );
0581     for ( i = ( console_global_data.lines - 1 ) * console_global_data.cols * 2;
0582           i < console_global_data.lines * console_global_data.cols * 2;
0583           i += 2 )
0584         vidmem[i] = ' ';
0585 }
0586 
0587 /*
0588  * cursor() sets an offset (0-1999) into the 80x25 text area
0589  */
0590 static void
0591 cursor(int x, int y)
0592 {
0593     int pos = console_global_data.cols*y + x;
0594     vga_outb(14, 0x14);
0595     vga_outb(0x15, pos>>8);
0596     vga_outb(0x14, 15);
0597     vga_outb(0x15, pos);
0598 }
0599 
0600 static void
0601 vga_putc(const u_char c)
0602 {
0603     int x,y;
0604 
0605     x = console_global_data.orig_x;
0606     y = console_global_data.orig_y;
0607 
0608     if ( c == '\n' ) {
0609         if ( ++y >= console_global_data.lines ) {
0610             scroll();
0611             y--;
0612         }
0613     } else if (c == '\b') {
0614         if (x > 0) {
0615             x--;
0616         }
0617     } else if (c == '\r') {
0618         x = 0;
0619     } else {
0620         vidmem [ ( x + console_global_data.cols * y ) * 2 ] = c;
0621         if ( ++x >= console_global_data.cols ) {
0622             x = 0;
0623             if ( ++y >= console_global_data.lines ) {
0624                 scroll();
0625                 y--;
0626             }
0627         }
0628     }
0629 
0630     cursor(x, y);
0631 
0632     console_global_data.orig_x = x;
0633     console_global_data.orig_y = y;
0634 }
0635 #endif /* USE_VGA_SUPPORT */
0636 
0637 #ifdef USE_KBD_SUPPORT
0638 /* Keyboard support */
0639 static int kbd_getc(void)
0640 {
0641     unsigned char dt, brk, val;
0642     unsigned code;
0643 loop:
0644     while((kbd_inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0) ;
0645 
0646     dt = kbd_inb(KBD_DATA_REG);
0647 
0648     brk = dt & 0x80;    /* brk == 1 on key release */
0649     dt = dt & 0x7f;     /* keycode */
0650 
0651     if (console_global_data.shfts)
0652         code = shift_map[dt];
0653     else if (console_global_data.ctls)
0654         code = ctrl_map[dt];
0655     else
0656         code = plain_map[dt];
0657 
0658     val = KVAL(code);
0659     switch (KTYP(code) & 0x0f) {
0660         case KT_LATIN:
0661         if (brk)
0662             break;
0663         if (console_global_data.alts)
0664             val |= 0x80;
0665         if (val == 0x7f)    /* map delete to backspace */
0666             val = '\b';
0667         return val;
0668 
0669         case KT_LETTER:
0670         if (brk)
0671             break;
0672         if (console_global_data.caps)
0673             val -= 'a'-'A';
0674         return val;
0675 
0676         case KT_SPEC:
0677         if (brk)
0678             break;
0679         if (val == KVAL(K_CAPS))
0680             console_global_data.caps = !console_global_data.caps;
0681         else if (val == KVAL(K_ENTER)) {
0682 enter:          /* Wait for key up */
0683             while (1) {
0684             while((kbd_inb(KBD_STATUS_REG) & KBD_STAT_OBF) == 0) ;
0685             dt = kbd_inb(KBD_DATA_REG);
0686             if (dt & 0x80) /* key up */ break;
0687             }
0688             return 10;
0689         }
0690         break;
0691 
0692         case KT_PAD:
0693         if (brk)
0694             break;
0695         if (val < 10)
0696             return val;
0697         if (val == KVAL(K_PENTER))
0698             goto enter;
0699         break;
0700 
0701         case KT_SHIFT:
0702         switch (val) {
0703             case KG_SHIFT:
0704             case KG_SHIFTL:
0705             case KG_SHIFTR:
0706             console_global_data.shfts = brk ? 0 : 1;
0707             break;
0708             case KG_ALT:
0709             case KG_ALTGR:
0710             console_global_data.alts = brk ? 0 : 1;
0711             break;
0712             case KG_CTRL:
0713             case KG_CTRLL:
0714             case KG_CTRLR:
0715             console_global_data.ctls = brk ? 0 : 1;
0716             break;
0717         }
0718         break;
0719 
0720         case KT_LOCK:
0721         switch (val) {
0722             case KG_SHIFT:
0723             case KG_SHIFTL:
0724             case KG_SHIFTR:
0725             if (brk)
0726                 console_global_data.shfts = !console_global_data.shfts;
0727             break;
0728             case KG_ALT:
0729             case KG_ALTGR:
0730             if (brk)
0731                 console_global_data.alts = !console_global_data.alts;
0732             break;
0733             case KG_CTRL:
0734             case KG_CTRLL:
0735             case KG_CTRLR:
0736             if (brk)
0737                 console_global_data.ctls = !console_global_data.ctls;
0738             break;
0739         }
0740         break;
0741     }
0742     /* if (brk) return (0); */  /* Ignore initial 'key up' codes */
0743     goto loop;
0744 }
0745 
0746 static int kbd_get(int ms) {
0747     int status, data;
0748     while(1) {
0749         status = kbd_inb(KBD_STATUS_REG);
0750         if (status & KBD_STAT_OBF) {
0751             data = kbd_inb(KBD_DATA_REG);
0752             if (status & (KBD_STAT_GTO | KBD_STAT_PERR))
0753                 return -1;
0754             else
0755                 return data;
0756         }
0757         if (--ms < 0) return -1;
0758 #ifdef __BOOT__
0759         boot_udelay(1000);
0760 #else
0761         rtems_bsp_delay(1000);
0762 #endif
0763     }
0764 }
0765 
0766 static void kbd_put(u_char c, int ms, int port) {
0767     while (kbd_inb(KBD_STATUS_REG) & KBD_STAT_IBF) {
0768         if (--ms < 0) return;
0769 #ifdef __BOOT__
0770         boot_udelay(1000);
0771 #else
0772         rtems_bsp_delay(1000);
0773 #endif
0774     }
0775     kbd_outb(port, c);
0776 }
0777 
0778 int kbdreset(void)
0779 {
0780     int c;
0781 
0782     /* Flush all pending data */
0783     while(kbd_get(10) != -1);
0784 
0785     /* Send self-test */
0786     kbd_put(KBD_CCMD_SELF_TEST, 10, KBD_CNTL_REG);
0787     c = kbd_get(1000);
0788     if (c != 0x55) return 1;
0789 
0790     /* Enable then reset the KB */
0791     kbd_put(KBD_CCMD_KBD_ENABLE, 10, KBD_CNTL_REG);
0792 
0793     while (1) {
0794         kbd_put(KBD_CMD_RESET, 10, KBD_DATA_REG);
0795         c = kbd_get(1000);
0796         if (c == KBD_REPLY_ACK) break;
0797         if (c != KBD_REPLY_RESEND) return 2;
0798     }
0799 
0800     if (kbd_get(1000) != KBD_REPLY_POR) return 3;
0801 
0802     /* Disable the keyboard while setting up the controller */
0803     kbd_put(KBD_CMD_DISABLE, 10, KBD_DATA_REG);
0804     if (kbd_get(10)!=KBD_REPLY_ACK) return 4;
0805 
0806     /* Enable interrupts and keyboard controller */
0807     kbd_put(KBD_CCMD_WRITE_MODE, 10, KBD_CNTL_REG);
0808     kbd_put(KBD_MODE_KBD_INT | KBD_MODE_SYS |
0809         KBD_MODE_DISABLE_MOUSE | KBD_MODE_KCC,
0810         10, KBD_DATA_REG);
0811 
0812     /* Reenable the keyboard */
0813     kbd_put(KBD_CMD_ENABLE, 10, KBD_DATA_REG);
0814     if (kbd_get(10)!=KBD_REPLY_ACK) return 5;
0815 
0816     return 0;
0817 }
0818 
0819 static int kbd_tstc(void)
0820 {
0821     return ((kbd_inb(KBD_STATUS_REG) & KBD_STAT_OBF) != 0);
0822 }
0823 #endif /* USE_KBD_SUPPORT */
0824 
0825 const struct console_io
0826 vacuum_console_functions = {
0827     vacuum_putc,
0828     vacuum_getc,
0829     vacuum_tstc
0830 };
0831 
0832 static const struct console_io
0833 log_console_functions = {
0834     log_putc,
0835     vacuum_getc,
0836     vacuum_tstc
0837 }
0838 ,
0839 serial_console_functions = {
0840     serial_putc,
0841     serial_getc,
0842     serial_tstc
0843 }
0844 #if defined(USE_KBD_SUPPORT) && defined(USE_VGA_SUPPORT)
0845 ,
0846 vga_console_functions = {
0847     vga_putc,
0848     kbd_getc,
0849     kbd_tstc
0850 }
0851 #endif
0852 ;
0853 
0854 console_io* curIo = (console_io*) &vacuum_console_functions;
0855 
0856 int select_console(ioType t) {
0857   static ioType curType = CONSOLE_VACUUM;
0858 
0859   switch (t) {
0860   case CONSOLE_VACUUM   : curIo = (console_io*)&vacuum_console_functions; break;
0861   case CONSOLE_LOG  : curIo = (console_io*)&log_console_functions; break;
0862   case CONSOLE_SERIAL   : curIo = (console_io*)&serial_console_functions; break;
0863 #if defined(USE_KBD_SUPPORT) && defined(USE_VGA_SUPPORT)
0864   case CONSOLE_VGA  : curIo = (console_io*)&vga_console_functions; break;
0865 #endif
0866   default           : curIo = (console_io*)&vacuum_console_functions;break;
0867   }
0868   if (curType == CONSOLE_LOG) flush_log();
0869   curType = t;
0870   return 0;
0871 }
0872 
0873 /* we use this so that we can do without the ctype library */
0874 #define is_digit(c) ((c) >= '0' && (c) <= '9')
0875 
0876 /* provide this for the bootloader only; otherwise
0877  * use libcpu implementation
0878  */
0879 #if defined(__BOOT__)
0880 static int skip_atoi(const char **s)
0881 {
0882     int i=0;
0883 
0884     while (is_digit(**s))
0885         i = i*10 + *((*s)++) - '0';
0886     return i;
0887 }
0888 
0889 /* Based on linux/lib/vsprintf.c and modified to suit our needs,
0890  * bloat has been limited since we basically only need %u, %x, %s and %c.
0891  * But we need 64 bit values !
0892  */
0893 int k_vsprintf(char *buf, const char *fmt, va_list args);
0894 
0895 int  printk(const char *fmt, ...) {
0896     va_list args;
0897     int i;
0898     /* Should not be a problem with 8kB of stack */
0899     char buf[1024];
0900 
0901     va_start(args, fmt);
0902     i = k_vsprintf(buf, fmt, args);
0903     va_end(args);
0904     my_puts((u_char*)buf);
0905     return i;
0906 }
0907 
0908 #endif
0909 
0910 /* Necessary to avoid including a library, and GCC won't do this inline. */
0911 #define div10(num, rmd)                          \
0912 do {    uint32_t t1, t2, t3;                             \
0913     __asm__ ("lis %4,0xcccd; "                       \
0914         "addi %4,%4,0xffffcccd; "   /* Build 0xcccccccd */       \
0915         "mulhwu %3,%0+1,%4; "   /* (num.l*cst.l).h  */       \
0916         "mullw %2,%0,%4; "      /* (num.h*cst.l).l  */       \
0917         "addc %3,%3,%2; "                        \
0918         "mulhwu %2,%0,%4; "     /* (num.h*cst.l).h  */       \
0919         "addi %4,%4,-1; "       /* Build 0xcccccccc */       \
0920         "mullw %1,%0,%4; "      /* (num.h*cst.h).l  */       \
0921         "adde %2,%2,%1; "                        \
0922         "mulhwu %1,%0,%4; "     /* (num.h*cst.h).h  */       \
0923         "addze %1,%1; "                      \
0924         "mullw %0,%0+1,%4; "    /* (num.l*cst.h).l  */       \
0925         "addc %3,%3,%0; "                        \
0926         "mulhwu %0,%0+1,%4; "   /* (num.l*cst.h).h  */       \
0927         "adde %2,%2,%0; "                        \
0928         "addze %1,%1; "                      \
0929         "srwi %2,%2,3; "                         \
0930         "srwi %0,%1,3; "                         \
0931         "rlwimi %2,%1,29,0,2; "                  \
0932         "mulli %4,%2,10; "                       \
0933         "sub %4,%0+1,%4; "                       \
0934         "mr %0+1,%2; " :                         \
0935         "=r" (num), "=&r" (t1), "=&r" (t2), "=&r"(t3), "=&b" (rmd) : \
0936         "0" (num));                          \
0937                                      \
0938 } while(0);
0939 
0940 #define SIGN    1       /* unsigned/signed long */
0941 #define LARGE   2       /* use 'ABCDEF' instead of 'abcdef' */
0942 #define HEX 4       /* hexadecimal instead of decimal */
0943 #define ADDR    8               /* Value is an addres (p) */
0944 #define ZEROPAD 16      /* pad with zero */
0945 #define HALF    32
0946 #define LONG    64      /* long argument */
0947 #define LLONG   128     /* 64 bit argument */
0948 
0949 #if defined(__BOOT__)
0950 static char * number(char * str, int size, int type, uint64_t num)
0951 {
0952     char fill,sign,tmp[24];
0953     const char *digits="0123456789abcdef";
0954     int i;
0955 
0956     if (type & LARGE)
0957         digits = "0123456789ABCDEF";
0958     fill = (type & ZEROPAD) ? '0' : ' ';
0959     sign = 0;
0960     if (type & SIGN) {
0961         if ((int64_t)num <0) {
0962             sign = '-';
0963             num = -num;
0964             size--;
0965         }
0966     }
0967 
0968     i = 0;
0969     do {
0970         unsigned rem;
0971         if (type&HEX) {
0972             rem = num & 0x0f;
0973             num >>=4;
0974         } else {
0975             div10(num, rem);
0976         }
0977         tmp[i++] = digits[rem];
0978     } while (num != 0);
0979 
0980     size -= i;
0981     if (!(type&(ZEROPAD)))
0982         while(size-->0)
0983             *str++ = ' ';
0984     if (sign)
0985         *str++ = sign;
0986 
0987     while (size-- > 0)
0988         *str++ = fill;
0989     while (i-- > 0)
0990         *str++ = tmp[i];
0991     while (size-- > 0)
0992         *str++ = ' ';
0993     return str;
0994 }
0995 
0996 int k_vsprintf(char *buf, const char *fmt, va_list args)
0997 {
0998     int len;
0999     uint64_t num;
1000     int i;
1001     char * str;
1002     const char *s;
1003 
1004     int flags;      /* flags to number() and private */
1005 
1006     int field_width;    /* width of output field */
1007 
1008     for (str=buf ; *fmt ; ++fmt) {
1009         if (*fmt != '%') {
1010             *str++ = *fmt;
1011             continue;
1012         }
1013 
1014         /* process flags, only 0 padding needed */
1015         flags = 0;
1016         if (*++fmt == '0' ) {
1017             flags |= ZEROPAD;
1018             fmt++;
1019         }
1020 
1021         /* get field width */
1022         field_width = -1;
1023         if (is_digit(*fmt))
1024             field_width = skip_atoi(&fmt);
1025 
1026         /* get the conversion qualifier */
1027         if (*fmt == 'h') {
1028             flags |= HALF;
1029             fmt++;
1030         } else if (*fmt == 'L') {
1031             flags |= LLONG;
1032             fmt++;
1033         } else if (*fmt == 'l') {
1034             flags |= LONG;
1035             fmt++;
1036         }
1037 
1038         switch (*fmt) {
1039         case 'c':
1040             *str++ = (unsigned char) va_arg(args, int);
1041             while (--field_width > 0)
1042                 *str++ = ' ';
1043             continue;
1044 
1045         case 's':
1046             s = va_arg(args, char *);
1047             len = strlen(s);
1048 
1049             for (i = 0; i < len; ++i)
1050                 *str++ = *s++;
1051             while (len < field_width--)
1052                 *str++ = ' ';
1053             continue;
1054 
1055         case 'p':
1056             if (field_width == -1) {
1057                 field_width = 2*sizeof(void *);
1058             }
1059             flags |= ZEROPAD|HEX|ADDR;
1060             break;
1061 
1062         case 'X':
1063             flags |= LARGE;
1064         case 'x':
1065             flags |= HEX;
1066             break;
1067 
1068         case 'd':
1069         case 'i':
1070             flags |= SIGN;
1071         case 'u':
1072             break;
1073 
1074         default:
1075             if (*fmt != '%')
1076                 *str++ = '%';
1077             if (*fmt)
1078                 *str++ = *fmt;
1079             else
1080                 --fmt;
1081             continue;
1082         }
1083         /* This ugly code tries to minimize the number of va_arg()
1084          * since they expand to a lot of code on PPC under the SYSV
1085          * calling conventions (but not with -mcall-aix which has
1086          * other problems). Arguments have at least the size of a
1087          * long allocated, and we use this fact to minimize bloat.
1088          * (and pointers are assimilated to unsigned long too).
1089          */
1090         if (sizeof(long long) > sizeof(long) && flags & LLONG)
1091             num = va_arg(args, unsigned long long);
1092         else {
1093             u_long n = va_arg(args, unsigned long);
1094             if (flags & HALF) {
1095                 if (flags & SIGN)
1096                     n = (short) n;
1097                 else
1098                     n = (unsigned short) n;
1099             } else if (!(flags & LONG)) {
1100                 /* Here the compiler correctly removes this
1101                  * do nothing code on 32 bit PPC.
1102                  */
1103                 if (flags & SIGN)
1104                     n = (int) n;
1105                 else
1106                     n = (unsigned) n;
1107             }
1108             if (flags & SIGN)  num = (long) n; else num = n;
1109         }
1110         str = number(str, field_width, flags, num);
1111     }
1112     *str = '\0';
1113     return str-buf;
1114 }
1115 #endif