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