root/drivers/char/consolemap.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. set_inverse_transl
  2. set_translate
  3. inverse_translate
  4. con_set_trans_old
  5. con_get_trans_old
  6. con_set_trans_new
  7. con_get_trans_new
  8. con_insert_unipair
  9. con_clear_unimap
  10. con_set_unimap
  11. con_set_default_unimap
  12. con_get_unimap
  13. conv_uni_to_pc
  14. console_map_init

   1 /*
   2  * consolemap.c
   3  *
   4  * Mapping from internal code (such as Latin-1 or Unicode or IBM PC code)
   5  * to font positions.
   6  *
   7  * aeb, 950210
   8  */
   9 
  10 #include <linux/kd.h>
  11 #include <linux/errno.h>
  12 #include <linux/mm.h>
  13 #include <linux/malloc.h>
  14 #include <asm/segment.h>
  15 #include "consolemap.h"
  16 
  17 static unsigned short translations[][256] = {
  18   /* 8-bit Latin-1 mapped to Unicode -- trivial mapping */
  19   {
  20     0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
  21     0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
  22     0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
  23     0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
  24     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
  25     0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
  26     0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
  27     0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
  28     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
  29     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
  30     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
  31     0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
  32     0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
  33     0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
  34     0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
  35     0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
  36     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
  37     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
  38     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
  39     0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
  40     0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
  41     0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
  42     0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
  43     0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
  44     0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
  45     0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
  46     0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
  47     0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
  48     0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
  49     0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
  50     0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
  51     0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
  52   }, 
  53   /* VT100 graphics mapped to Unicode */
  54   {
  55     0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
  56     0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
  57     0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
  58     0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
  59     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
  60     0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
  61     0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
  62     0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
  63     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
  64     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
  65     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
  66     0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x00a0,
  67     0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1,
  68     0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0xf800,
  69     0xf801, 0x2500, 0xf803, 0xf804, 0x251c, 0x2524, 0x2534, 0x252c,
  70     0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x007f,
  71     0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
  72     0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
  73     0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
  74     0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
  75     0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
  76     0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
  77     0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
  78     0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
  79     0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
  80     0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
  81     0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
  82     0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
  83     0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
  84     0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
  85     0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
  86     0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
  87   },
  88   /* IBM Codepage 437 mapped to Unicode */
  89   {
  90     0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022, 
  91     0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
  92     0x25ba, 0x25c4, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
  93     0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
  94     0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
  95     0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
  96     0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
  97     0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
  98     0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
  99     0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
 100     0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
 101     0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
 102     0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
 103     0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
 104     0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
 105     0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
 106     0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
 107     0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
 108     0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
 109     0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
 110     0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
 111     0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
 112     0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
 113     0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
 114     0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
 115     0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
 116     0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
 117     0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
 118     0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
 119     0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
 120     0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
 121     0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
 122   }, 
 123   /* User mapping -- default to codes for direct font mapping */
 124   {
 125     0xf000, 0xf001, 0xf002, 0xf003, 0xf004, 0xf005, 0xf006, 0xf007,
 126     0xf008, 0xf009, 0xf00a, 0xf00b, 0xf00c, 0xf00d, 0xf00e, 0xf00f,
 127     0xf010, 0xf011, 0xf012, 0xf013, 0xf014, 0xf015, 0xf016, 0xf017,
 128     0xf018, 0xf019, 0xf01a, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
 129     0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
 130     0xf028, 0xf029, 0xf02a, 0xf02b, 0xf02c, 0xf02d, 0xf02e, 0xf02f,
 131     0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
 132     0xf038, 0xf039, 0xf03a, 0xf03b, 0xf03c, 0xf03d, 0xf03e, 0xf03f,
 133     0xf040, 0xf041, 0xf042, 0xf043, 0xf044, 0xf045, 0xf046, 0xf047,
 134     0xf048, 0xf049, 0xf04a, 0xf04b, 0xf04c, 0xf04d, 0xf04e, 0xf04f,
 135     0xf050, 0xf051, 0xf052, 0xf053, 0xf054, 0xf055, 0xf056, 0xf057,
 136     0xf058, 0xf059, 0xf05a, 0xf05b, 0xf05c, 0xf05d, 0xf05e, 0xf05f,
 137     0xf060, 0xf061, 0xf062, 0xf063, 0xf064, 0xf065, 0xf066, 0xf067,
 138     0xf068, 0xf069, 0xf06a, 0xf06b, 0xf06c, 0xf06d, 0xf06e, 0xf06f,
 139     0xf070, 0xf071, 0xf072, 0xf073, 0xf074, 0xf075, 0xf076, 0xf077,
 140     0xf078, 0xf079, 0xf07a, 0xf07b, 0xf07c, 0xf07d, 0xf07e, 0xf07f,
 141     0xf080, 0xf081, 0xf082, 0xf083, 0xf084, 0xf085, 0xf086, 0xf087,
 142     0xf088, 0xf089, 0xf08a, 0xf08b, 0xf08c, 0xf08d, 0xf08e, 0xf08f,
 143     0xf090, 0xf091, 0xf092, 0xf093, 0xf094, 0xf095, 0xf096, 0xf097,
 144     0xf098, 0xf099, 0xf09a, 0xf09b, 0xf09c, 0xf09d, 0xf09e, 0xf09f,
 145     0xf0a0, 0xf0a1, 0xf0a2, 0xf0a3, 0xf0a4, 0xf0a5, 0xf0a6, 0xf0a7,
 146     0xf0a8, 0xf0a9, 0xf0aa, 0xf0ab, 0xf0ac, 0xf0ad, 0xf0ae, 0xf0af,
 147     0xf0b0, 0xf0b1, 0xf0b2, 0xf0b3, 0xf0b4, 0xf0b5, 0xf0b6, 0xf0b7,
 148     0xf0b8, 0xf0b9, 0xf0ba, 0xf0bb, 0xf0bc, 0xf0bd, 0xf0be, 0xf0bf,
 149     0xf0c0, 0xf0c1, 0xf0c2, 0xf0c3, 0xf0c4, 0xf0c5, 0xf0c6, 0xf0c7,
 150     0xf0c8, 0xf0c9, 0xf0ca, 0xf0cb, 0xf0cc, 0xf0cd, 0xf0ce, 0xf0cf,
 151     0xf0d0, 0xf0d1, 0xf0d2, 0xf0d3, 0xf0d4, 0xf0d5, 0xf0d6, 0xf0d7,
 152     0xf0d8, 0xf0d9, 0xf0da, 0xf0db, 0xf0dc, 0xf0dd, 0xf0de, 0xf0df,
 153     0xf0e0, 0xf0e1, 0xf0e2, 0xf0e3, 0xf0e4, 0xf0e5, 0xf0e6, 0xf0e7,
 154     0xf0e8, 0xf0e9, 0xf0ea, 0xf0eb, 0xf0ec, 0xf0ed, 0xf0ee, 0xf0ef,
 155     0xf0f0, 0xf0f1, 0xf0f2, 0xf0f3, 0xf0f4, 0xf0f5, 0xf0f6, 0xf0f7,
 156     0xf0f8, 0xf0f9, 0xf0fa, 0xf0fb, 0xf0fc, 0xf0fd, 0xf0fe, 0xf0ff
 157   }
 158 };
 159 
 160 /* The standard kernel character-to-font mappings are not invertible
 161    -- this is just a best effort. */
 162 
 163 #define MAX_GLYPH 512           /* Max possible glyph value */
 164 
 165 static unsigned char * inv_translate = NULL;
 166 static unsigned char inv_norm_transl[MAX_GLYPH];
 167 static unsigned char * inverse_translations[4] = { NULL, NULL, NULL, NULL };
 168 
 169 static void set_inverse_transl(int i)
     /* [previous][next][first][last][top][bottom][index][help] */
 170 {
 171         int j, glyph;
 172         unsigned short *p = translations[i];
 173         unsigned char *q = inverse_translations[i];
 174 
 175         if (!q) {
 176                 /* slightly messy to avoid calling kmalloc too early */
 177                 q = inverse_translations[i] = ((i == LAT1_MAP)
 178                         ? inv_norm_transl
 179                         : (unsigned char *) kmalloc(MAX_GLYPH, GFP_KERNEL));
 180                 if (!q)
 181                         return;
 182         }
 183         for (j=0; j<MAX_GLYPH; j++)
 184                 q[j] = 0;
 185 
 186         for (j=0; j<E_TABSZ; j++) {
 187                 glyph = conv_uni_to_pc(p[j]);
 188                 if (glyph >= 0 && glyph < MAX_GLYPH && q[glyph] < 32) {
 189                         /* prefer '-' above SHY etc. */
 190                         q[glyph] = j;
 191                 }
 192         }
 193 }
 194 
 195 unsigned short *set_translate(int m)
     /* [previous][next][first][last][top][bottom][index][help] */
 196 {
 197         if (!inverse_translations[m])
 198                 set_inverse_transl(m);
 199         inv_translate = inverse_translations[m];
 200         return translations[m];
 201 }
 202 
 203 /*
 204  * Inverse translation is impossible for several reasons:
 205  * 1. The font<->character maps are not 1-1.
 206  * 2. The text may have been written while a different translation map
 207  *    was active, or using Unicode.
 208  * Still, it is now possible to a certain extent to cut and paste non-ASCII.
 209  */
 210 unsigned char inverse_translate(int glyph) {
     /* [previous][next][first][last][top][bottom][index][help] */
 211         if ( glyph < 0 || glyph >= MAX_GLYPH )
 212                 return 0;
 213         else
 214                 return ((inv_translate && inv_translate[glyph])
 215                         ? inv_translate[glyph]
 216                         : (unsigned char)(glyph & 0xff));
 217 }
 218 
 219 /*
 220  * Load customizable translation table
 221  * arg points to a 256 byte translation table.
 222  *
 223  * The "old" variants are for translation directly to font (using the
 224  * 0xf000-0xf0ff "transparent" Unicodes) whereas the "new" variants set
 225  * Unicodes explictly.
 226  */
 227 int con_set_trans_old(unsigned char * arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 228 {
 229         int i;
 230         unsigned short *p = translations[USER_MAP];
 231 
 232         i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ);
 233         if (i)
 234                 return i;
 235 
 236         for (i=0; i<E_TABSZ ; i++)
 237                 p[i] = UNI_DIRECT_BASE | get_user(arg+i);
 238 
 239         set_inverse_transl(USER_MAP);
 240         return 0;
 241 }
 242 
 243 int con_get_trans_old(unsigned char * arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 244 {
 245         int i, ch;
 246         unsigned short *p = translations[USER_MAP];
 247 
 248         i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ);
 249         if (i)
 250                 return i;
 251 
 252         for (i=0; i<E_TABSZ ; i++)
 253           {
 254             ch = conv_uni_to_pc(p[i]);
 255             put_user((ch & ~0xff) ? 0 : ch, arg+i);
 256           }
 257         return 0;
 258 }
 259 
 260 int con_set_trans_new(ushort * arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 261 {
 262         int i;
 263         unsigned short *p = translations[USER_MAP];
 264 
 265         i = verify_area(VERIFY_READ, (void *)arg,
 266                         E_TABSZ*sizeof(unsigned short));
 267         if (i)
 268                 return i;
 269 
 270         for (i=0; i<E_TABSZ ; i++)
 271           p[i] = get_user(arg+i);
 272 
 273         set_inverse_transl(USER_MAP);
 274         return 0;
 275 }
 276 
 277 int con_get_trans_new(ushort * arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 278 {
 279         int i;
 280         unsigned short *p = translations[USER_MAP];
 281 
 282         i = verify_area(VERIFY_WRITE, (void *)arg,
 283                         E_TABSZ*sizeof(unsigned short));
 284         if (i)
 285                 return i;
 286 
 287         for (i=0; i<E_TABSZ ; i++)
 288           put_user(p[i], arg+i);
 289         
 290         return 0;
 291 }
 292 
 293 /*
 294  * Unicode -> current font conversion 
 295  *
 296  * A font has at most 512 chars, usually 256.
 297  * But one font position may represent several Unicode chars.
 298  * A hashtable is somewhat of a pain to deal with, so use a
 299  * "paged table" instead.  Simulation has shown the memory cost of
 300  * this 3-level paged table scheme to be comparable to a hash table.
 301  */
 302 
 303 #include "uni_hash.tbl"         /* Include hash tables & parameters */
 304 
 305 int hashtable_contents_valid = 0; /* Use ASCII-only mode for bootup*/
 306 
 307 static u16 **uni_pagedir[32] =
 308 {
 309   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 310   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 311   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 312   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 313 };
 314 
 315 static int
 316 con_insert_unipair(u_short unicode, u_short fontpos)
     /* [previous][next][first][last][top][bottom][index][help] */
 317 {
 318   int i, n;
 319   u16 **p1, *p2;
 320 
 321   if ( !(p1 = uni_pagedir[n = unicode >> 11]) )
 322     {
 323       p1 = uni_pagedir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);
 324       if ( !p1 )
 325         return -ENOMEM;
 326 
 327       for ( i = 0 ; i < 32 ; i++ )
 328         p1[i] = NULL;
 329     }
 330 
 331   if ( !(p2 = p1[n = (unicode >> 6) & 0x1f]) )
 332     {
 333       p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
 334       if ( !p2 )
 335         return -ENOMEM;
 336 
 337       for ( i = 0 ; i < 64 ; i++ )
 338         p2[i] = 0xffff;         /* No glyph for this character (yet) */
 339     }
 340 
 341   p2[unicode & 0x3f] = fontpos;
 342   
 343   return 0;
 344 }
 345   
 346 /* ui is a leftover from using a hashtable, but might be used again */
 347 void
 348 con_clear_unimap(struct unimapinit *ui)
     /* [previous][next][first][last][top][bottom][index][help] */
 349 {
 350   int i, j;
 351   u16 **p1;
 352   
 353   for ( i = 0 ; i < 32 ; i++ )
 354     {
 355       if ( (p1 = uni_pagedir[i]) != NULL )
 356         {
 357           for ( j = 0 ; j < 32 ; j++ )
 358             {
 359               if ( p1[j] )
 360                 kfree(p1[j]);
 361             }
 362           kfree(p1);
 363         }
 364       uni_pagedir[i] = NULL;
 365     }
 366 
 367   hashtable_contents_valid = 1;
 368 }
 369 
 370 int
 371 con_set_unimap(ushort ct, struct unipair *list)
     /* [previous][next][first][last][top][bottom][index][help] */
 372 {
 373   int err = 0, err1, i;
 374 
 375   while( ct-- )
 376     {
 377       if ( (err1 = con_insert_unipair(get_user(&list->unicode),
 378                                       get_user(&list->fontpos))) != 0 )
 379         err = err1;
 380       list++;
 381     }
 382 
 383   for ( i = 0 ; i <= 3 ; i++ )
 384     set_inverse_transl(i); /* Update all inverse translations */
 385   
 386   return err;
 387 }
 388 
 389 /* Loads the unimap for the hardware font, as defined in uni_hash.tbl.
 390    The representation used was the most compact I could come up
 391    with.  This routine is executed at sys_setup time, and when the
 392    PIO_FONTRESET ioctl is called. */
 393 
 394 void
 395 con_set_default_unimap(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 396 {
 397   int i, j;
 398   u16 *p;
 399 
 400   /* The default font is always 256 characters */
 401 
 402   con_clear_unimap(NULL);
 403 
 404   p = dfont_unitable;
 405   for ( i = 0 ; i < 256 ; i++ )
 406     for ( j = dfont_unicount[i] ; j ; j-- )
 407       con_insert_unipair(*(p++), i);
 408 
 409   for ( i = 0 ; i <= 3 ; i++ )
 410     set_inverse_transl(i);      /* Update all inverse translations */
 411 }
 412 
 413 int
 414 con_get_unimap(ushort ct, ushort *uct, struct unipair *list){
     /* [previous][next][first][last][top][bottom][index][help] */
 415         int i, j, k, ect;
 416         u16 **p1, *p2;
 417 
 418         ect = 0;
 419         if (hashtable_contents_valid)
 420           {
 421             for ( i = 0 ; i < 32 ; i++ )
 422               if ( (p1 = uni_pagedir[i]) != NULL )
 423                 for ( j = 0 ; j < 32 ; j++ )
 424                   if ( (p2 = *(p1++)) != NULL )
 425                     for ( k = 0 ; k < 64 ; k++ )
 426                       {
 427                         if ( *p2 < MAX_GLYPH && ect++ < ct )
 428                           {
 429                             put_user((u_short)((i<<11)+(j<<6)+k),
 430                                      &list->unicode);
 431                             put_user((u_short) *p2, &list->fontpos);
 432                             list++;
 433                           }
 434                         p2++;
 435                       }
 436           }
 437         put_user(ect, uct);
 438         return ((ect <= ct) ? 0 : -ENOMEM);
 439 }
 440 
 441 int
 442 conv_uni_to_pc(long ucs) 
     /* [previous][next][first][last][top][bottom][index][help] */
 443 {
 444   int h;
 445   u16 **p1, *p2;
 446   
 447   /* Only 16-bit codes supported at this time */
 448   if (ucs > 0xffff)
 449     ucs = 0xfffd;               /* U+FFFD: REPLACEMENT CHARACTER */
 450   else if (ucs < 0x20 || ucs >= 0xfffe)
 451     return -1;          /* Not a printable character */
 452   else if (ucs == 0xfeff || (ucs >= 0x200a && ucs <= 0x200f))
 453     return -2;                  /* Zero-width space */
 454   /*
 455    * UNI_DIRECT_BASE indicates the start of the region in the User Zone
 456    * which always has a 1:1 mapping to the currently loaded font.  The
 457    * UNI_DIRECT_MASK indicates the bit span of the region.
 458    */
 459   else if ( (ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE )
 460     return ucs & UNI_DIRECT_MASK;
 461   
 462   if (!hashtable_contents_valid)
 463     return -3;
 464   
 465   if ( (p1 = uni_pagedir[ucs >> 11]) &&
 466       (p2 = p1[(ucs >> 6) & 0x1f]) &&
 467       (h = p2[ucs & 0x3f]) < MAX_GLYPH )
 468     return h;
 469 
 470   return -4;            /* not found */
 471 }
 472 
 473 /*
 474  * This is called at sys_setup time, after memory and the console are
 475  * initialized.  It must be possible to call kmalloc(..., GFP_KERNEL)
 476  * from this function, hence the call from sys_setup.
 477  */
 478 void
 479 console_map_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 480 {
 481   con_set_default_unimap();
 482 }

/* [previous][next][first][last][top][bottom][index][help] */