~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/char/consolemap.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.