]> Pileus Git - ~andy/linux/blob - drivers/tty/vt/consolemap.c
Merge branches 'misc', 'drv_cleanup', 'devm-cleanup' and 'ti-soc' of .git into next
[~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] = kmalloc(MAX_GLYPH, GFP_KERNEL);
198                 if (!q) return;
199         }
200         memset(q, 0, MAX_GLYPH);
201
202         for (j = 0; j < E_TABSZ; j++) {
203                 glyph = conv_uni_to_pc(conp, t[j]);
204                 if (glyph >= 0 && glyph < MAX_GLYPH && q[glyph] < 32) {
205                         /* prefer '-' above SHY etc. */
206                         q[glyph] = j;
207                 }
208         }
209 }
210
211 static void set_inverse_trans_unicode(struct vc_data *conp,
212                                       struct uni_pagedir *p)
213 {
214         int i, j, k, glyph;
215         u16 **p1, *p2;
216         u16 *q;
217
218         if (!p) return;
219         q = p->inverse_trans_unicode;
220         if (!q) {
221                 q = p->inverse_trans_unicode =
222                         kmalloc(MAX_GLYPH * sizeof(u16), GFP_KERNEL);
223                 if (!q)
224                         return;
225         }
226         memset(q, 0, MAX_GLYPH * sizeof(u16));
227
228         for (i = 0; i < 32; i++) {
229                 p1 = p->uni_pgdir[i];
230                 if (!p1)
231                         continue;
232                 for (j = 0; j < 32; j++) {
233                         p2 = p1[j];
234                         if (!p2)
235                                 continue;
236                         for (k = 0; k < 64; k++) {
237                                 glyph = p2[k];
238                                 if (glyph >= 0 && glyph < MAX_GLYPH
239                                                && q[glyph] < 32)
240                                         q[glyph] = (i << 11) + (j << 6) + k;
241                         }
242                 }
243         }
244 }
245
246 unsigned short *set_translate(int m, struct vc_data *vc)
247 {
248         inv_translate[vc->vc_num] = m;
249         return translations[m];
250 }
251
252 /*
253  * Inverse translation is impossible for several reasons:
254  * 1. The font<->character maps are not 1-1.
255  * 2. The text may have been written while a different translation map
256  *    was active.
257  * Still, it is now possible to a certain extent to cut and paste non-ASCII.
258  */
259 u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode)
260 {
261         struct uni_pagedir *p;
262         int m;
263         if (glyph < 0 || glyph >= MAX_GLYPH)
264                 return 0;
265         else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc))
266                 return glyph;
267         else if (use_unicode) {
268                 if (!p->inverse_trans_unicode)
269                         return glyph;
270                 else
271                         return p->inverse_trans_unicode[glyph];
272         } else {
273                 m = inv_translate[conp->vc_num];
274                 if (!p->inverse_translations[m])
275                         return glyph;
276                 else
277                         return p->inverse_translations[m][glyph];
278         }
279 }
280 EXPORT_SYMBOL_GPL(inverse_translate);
281
282 static void update_user_maps(void)
283 {
284         int i;
285         struct uni_pagedir *p, *q = NULL;
286         
287         for (i = 0; i < MAX_NR_CONSOLES; i++) {
288                 if (!vc_cons_allocated(i))
289                         continue;
290                 p = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
291                 if (p && p != q) {
292                         set_inverse_transl(vc_cons[i].d, p, USER_MAP);
293                         set_inverse_trans_unicode(vc_cons[i].d, p);
294                         q = p;
295                 }
296         }
297 }
298
299 /*
300  * Load customizable translation table
301  * arg points to a 256 byte translation table.
302  *
303  * The "old" variants are for translation directly to font (using the
304  * 0xf000-0xf0ff "transparent" Unicodes) whereas the "new" variants set
305  * Unicodes explicitly.
306  */
307 int con_set_trans_old(unsigned char __user * arg)
308 {
309         int i;
310         unsigned short *p = translations[USER_MAP];
311
312         if (!access_ok(VERIFY_READ, arg, E_TABSZ))
313                 return -EFAULT;
314
315         console_lock();
316         for (i=0; i<E_TABSZ ; i++) {
317                 unsigned char uc;
318                 __get_user(uc, arg+i);
319                 p[i] = UNI_DIRECT_BASE | uc;
320         }
321
322         update_user_maps();
323         console_unlock();
324         return 0;
325 }
326
327 int con_get_trans_old(unsigned char __user * arg)
328 {
329         int i, ch;
330         unsigned short *p = translations[USER_MAP];
331
332         if (!access_ok(VERIFY_WRITE, arg, E_TABSZ))
333                 return -EFAULT;
334
335         console_lock();
336         for (i=0; i<E_TABSZ ; i++)
337         {
338                 ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
339                 __put_user((ch & ~0xff) ? 0 : ch, arg+i);
340         }
341         console_unlock();
342         return 0;
343 }
344
345 int con_set_trans_new(ushort __user * arg)
346 {
347         int i;
348         unsigned short *p = translations[USER_MAP];
349
350         if (!access_ok(VERIFY_READ, arg, E_TABSZ*sizeof(unsigned short)))
351                 return -EFAULT;
352
353         console_lock();
354         for (i=0; i<E_TABSZ ; i++) {
355                 unsigned short us;
356                 __get_user(us, arg+i);
357                 p[i] = us;
358         }
359
360         update_user_maps();
361         console_unlock();
362         return 0;
363 }
364
365 int con_get_trans_new(ushort __user * arg)
366 {
367         int i;
368         unsigned short *p = translations[USER_MAP];
369
370         if (!access_ok(VERIFY_WRITE, arg, E_TABSZ*sizeof(unsigned short)))
371                 return -EFAULT;
372
373         console_lock();
374         for (i=0; i<E_TABSZ ; i++)
375           __put_user(p[i], arg+i);
376         console_unlock();
377         
378         return 0;
379 }
380
381 /*
382  * Unicode -> current font conversion 
383  *
384  * A font has at most 512 chars, usually 256.
385  * But one font position may represent several Unicode chars.
386  * A hashtable is somewhat of a pain to deal with, so use a
387  * "paged table" instead.  Simulation has shown the memory cost of
388  * this 3-level paged table scheme to be comparable to a hash table.
389  */
390
391 extern u8 dfont_unicount[];     /* Defined in console_defmap.c */
392 extern u16 dfont_unitable[];
393
394 static void con_release_unimap(struct uni_pagedir *p)
395 {
396         u16 **p1;
397         int i, j;
398
399         if (p == dflt) dflt = NULL;  
400         for (i = 0; i < 32; i++) {
401                 if ((p1 = p->uni_pgdir[i]) != NULL) {
402                         for (j = 0; j < 32; j++)
403                                 kfree(p1[j]);
404                         kfree(p1);
405                 }
406                 p->uni_pgdir[i] = NULL;
407         }
408         for (i = 0; i < 4; i++) {
409                 kfree(p->inverse_translations[i]);
410                 p->inverse_translations[i] = NULL;
411         }
412         kfree(p->inverse_trans_unicode);
413         p->inverse_trans_unicode = NULL;
414 }
415
416 /* Caller must hold the console lock */
417 void con_free_unimap(struct vc_data *vc)
418 {
419         struct uni_pagedir *p;
420
421         p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
422         if (!p)
423                 return;
424         *vc->vc_uni_pagedir_loc = 0;
425         if (--p->refcount)
426                 return;
427         con_release_unimap(p);
428         kfree(p);
429 }
430   
431 static int con_unify_unimap(struct vc_data *conp, struct uni_pagedir *p)
432 {
433         int i, j, k;
434         struct uni_pagedir *q;
435         
436         for (i = 0; i < MAX_NR_CONSOLES; i++) {
437                 if (!vc_cons_allocated(i))
438                         continue;
439                 q = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
440                 if (!q || q == p || q->sum != p->sum)
441                         continue;
442                 for (j = 0; j < 32; j++) {
443                         u16 **p1, **q1;
444                         p1 = p->uni_pgdir[j]; q1 = q->uni_pgdir[j];
445                         if (!p1 && !q1)
446                                 continue;
447                         if (!p1 || !q1)
448                                 break;
449                         for (k = 0; k < 32; k++) {
450                                 if (!p1[k] && !q1[k])
451                                         continue;
452                                 if (!p1[k] || !q1[k])
453                                         break;
454                                 if (memcmp(p1[k], q1[k], 64*sizeof(u16)))
455                                         break;
456                         }
457                         if (k < 32)
458                                 break;
459                 }
460                 if (j == 32) {
461                         q->refcount++;
462                         *conp->vc_uni_pagedir_loc = (unsigned long)q;
463                         con_release_unimap(p);
464                         kfree(p);
465                         return 1;
466                 }
467         }
468         return 0;
469 }
470
471 static int
472 con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
473 {
474         int i, n;
475         u16 **p1, *p2;
476
477         if (!(p1 = p->uni_pgdir[n = unicode >> 11])) {
478                 p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);
479                 if (!p1) return -ENOMEM;
480                 for (i = 0; i < 32; i++)
481                         p1[i] = NULL;
482         }
483
484         if (!(p2 = p1[n = (unicode >> 6) & 0x1f])) {
485                 p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
486                 if (!p2) return -ENOMEM;
487                 memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */
488         }
489
490         p2[unicode & 0x3f] = fontpos;
491         
492         p->sum += (fontpos << 20) + unicode;
493
494         return 0;
495 }
496
497 /* ui is a leftover from using a hashtable, but might be used again
498    Caller must hold the lock */
499 static int con_do_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
500 {
501         struct uni_pagedir *p, *q;
502
503         p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
504         if (p && p->readonly)
505                 return -EIO;
506
507         if (!p || --p->refcount) {
508                 q = kzalloc(sizeof(*p), GFP_KERNEL);
509                 if (!q) {
510                         if (p)
511                                 p->refcount++;
512                         return -ENOMEM;
513                 }
514                 q->refcount=1;
515                 *vc->vc_uni_pagedir_loc = (unsigned long)q;
516         } else {
517                 if (p == dflt) dflt = NULL;
518                 p->refcount++;
519                 p->sum = 0;
520                 con_release_unimap(p);
521         }
522         return 0;
523 }
524
525 int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
526 {
527         int ret;
528         console_lock();
529         ret = con_do_clear_unimap(vc, ui);
530         console_unlock();
531         return ret;
532 }
533         
534 int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
535 {
536         int err = 0, err1, i;
537         struct uni_pagedir *p, *q;
538
539         console_lock();
540
541         /* Save original vc_unipagdir_loc in case we allocate a new one */
542         p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
543         if (p->readonly) {
544                 console_unlock();
545                 return -EIO;
546         }
547         
548         if (!ct) {
549                 console_unlock();
550                 return 0;
551         }
552         
553         if (p->refcount > 1) {
554                 int j, k;
555                 u16 **p1, *p2, l;
556                 
557                 err1 = con_do_clear_unimap(vc, NULL);
558                 if (err1) {
559                         console_unlock();
560                         return err1;
561                 }
562                 
563                 /*
564                  * Since refcount was > 1, con_clear_unimap() allocated a
565                  * a new uni_pagedir for this vc.  Re: p != q
566                  */
567                 q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
568
569                 /*
570                  * uni_pgdir is a 32*32*64 table with rows allocated
571                  * when its first entry is added.  The unicode value must
572                  * still be incremented for empty rows.  We are copying
573                  * entries from "p" (old) to "q" (new).
574                  */
575                 l = 0;          /* unicode value */
576                 for (i = 0; i < 32; i++)
577                 if ((p1 = p->uni_pgdir[i]))
578                         for (j = 0; j < 32; j++)
579                         if ((p2 = p1[j])) {
580                                 for (k = 0; k < 64; k++, l++)
581                                 if (p2[k] != 0xffff) {
582                                         /*
583                                          * Found one, copy entry for unicode
584                                          * l with fontpos value p2[k].
585                                          */
586                                         err1 = con_insert_unipair(q, l, p2[k]);
587                                         if (err1) {
588                                                 p->refcount++;
589                                                 *vc->vc_uni_pagedir_loc = (unsigned long)p;
590                                                 con_release_unimap(q);
591                                                 kfree(q);
592                                                 console_unlock();
593                                                 return err1; 
594                                         }
595                                 }
596                         } else {
597                                 /* Account for row of 64 empty entries */
598                                 l += 64;
599                         }
600                 else
601                         /* Account for empty table */
602                         l += 32 * 64;
603
604                 /*
605                  * Finished copying font table, set vc_uni_pagedir to new table
606                  */
607                 p = q;
608         } else if (p == dflt) {
609                 dflt = NULL;
610         }
611
612         /*
613          * Insert user specified unicode pairs into new table.
614          */
615         while (ct--) {
616                 unsigned short unicode, fontpos;
617                 __get_user(unicode, &list->unicode);
618                 __get_user(fontpos, &list->fontpos);
619                 if ((err1 = con_insert_unipair(p, unicode,fontpos)) != 0)
620                         err = err1;
621                 list++;
622         }
623         
624         /*
625          * Merge with fontmaps of any other virtual consoles.
626          */
627         if (con_unify_unimap(vc, p)) {
628                 console_unlock();
629                 return err;
630         }
631
632         for (i = 0; i <= 3; i++)
633                 set_inverse_transl(vc, p, i); /* Update inverse translations */
634         set_inverse_trans_unicode(vc, p);
635
636         console_unlock();
637         return err;
638 }
639
640 /**
641  *      con_set_default_unimap  -       set default unicode map
642  *      @vc: the console we are updating
643  *
644  *      Loads the unimap for the hardware font, as defined in uni_hash.tbl.
645  *      The representation used was the most compact I could come up
646  *      with.  This routine is executed at video setup, and when the
647  *      PIO_FONTRESET ioctl is called. 
648  *
649  *      The caller must hold the console lock
650  */
651 int con_set_default_unimap(struct vc_data *vc)
652 {
653         int i, j, err = 0, err1;
654         u16 *q;
655         struct uni_pagedir *p;
656
657         if (dflt) {
658                 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
659                 if (p == dflt)
660                         return 0;
661
662                 dflt->refcount++;
663                 *vc->vc_uni_pagedir_loc = (unsigned long)dflt;
664                 if (p && !--p->refcount) {
665                         con_release_unimap(p);
666                         kfree(p);
667                 }
668                 return 0;
669         }
670         
671         /* The default font is always 256 characters */
672
673         err = con_do_clear_unimap(vc, NULL);
674         if (err)
675                 return err;
676     
677         p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
678         q = dfont_unitable;
679         
680         for (i = 0; i < 256; i++)
681                 for (j = dfont_unicount[i]; j; j--) {
682                         err1 = con_insert_unipair(p, *(q++), i);
683                         if (err1)
684                                 err = err1;
685                 }
686                         
687         if (con_unify_unimap(vc, p)) {
688                 dflt = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
689                 return err;
690         }
691
692         for (i = 0; i <= 3; i++)
693                 set_inverse_transl(vc, p, i);   /* Update all inverse translations */
694         set_inverse_trans_unicode(vc, p);
695         dflt = p;
696         return err;
697 }
698 EXPORT_SYMBOL(con_set_default_unimap);
699
700 /**
701  *      con_copy_unimap         -       copy unimap between two vts
702  *      @dst_vc: target
703  *      @src_vt: source
704  *
705  *      The caller must hold the console lock when invoking this method
706  */
707 int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
708 {
709         struct uni_pagedir *q;
710
711         if (!*src_vc->vc_uni_pagedir_loc)
712                 return -EINVAL;
713         if (*dst_vc->vc_uni_pagedir_loc == *src_vc->vc_uni_pagedir_loc)
714                 return 0;
715         con_free_unimap(dst_vc);
716         q = (struct uni_pagedir *)*src_vc->vc_uni_pagedir_loc;
717         q->refcount++;
718         *dst_vc->vc_uni_pagedir_loc = (long)q;
719         return 0;
720 }
721 EXPORT_SYMBOL(con_copy_unimap);
722
723 /**
724  *      con_get_unimap          -       get the unicode map
725  *      @vc: the console to read from
726  *
727  *      Read the console unicode data for this console. Called from the ioctl
728  *      handlers.
729  */
730 int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list)
731 {
732         int i, j, k, ect;
733         u16 **p1, *p2;
734         struct uni_pagedir *p;
735
736         console_lock();
737
738         ect = 0;
739         if (*vc->vc_uni_pagedir_loc) {
740                 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
741                 for (i = 0; i < 32; i++)
742                 if ((p1 = p->uni_pgdir[i]))
743                         for (j = 0; j < 32; j++)
744                         if ((p2 = *(p1++)))
745                                 for (k = 0; k < 64; k++) {
746                                         if (*p2 < MAX_GLYPH && ect++ < ct) {
747                                                 __put_user((u_short)((i<<11)+(j<<6)+k),
748                                                            &list->unicode);
749                                                 __put_user((u_short) *p2, 
750                                                            &list->fontpos);
751                                                 list++;
752                                         }
753                                         p2++;
754                                 }
755         }
756         __put_user(ect, uct);
757         console_unlock();
758         return ((ect <= ct) ? 0 : -ENOMEM);
759 }
760
761 /*
762  * Always use USER_MAP. These functions are used by the keyboard,
763  * which shouldn't be affected by G0/G1 switching, etc.
764  * If the user map still contains default values, i.e. the
765  * direct-to-font mapping, then assume user is using Latin1.
766  *
767  * FIXME: at some point we need to decide if we want to lock the table
768  * update element itself via the keyboard_event_lock for consistency with the
769  * keyboard driver as well as the consoles
770  */
771 /* may be called during an interrupt */
772 u32 conv_8bit_to_uni(unsigned char c)
773 {
774         unsigned short uni = translations[USER_MAP][c];
775         return uni == (0xf000 | c) ? c : uni;
776 }
777
778 int conv_uni_to_8bit(u32 uni)
779 {
780         int c;
781         for (c = 0; c < 0x100; c++)
782                 if (translations[USER_MAP][c] == uni ||
783                    (translations[USER_MAP][c] == (c | 0xf000) && uni == c))
784                         return c;
785         return -1;
786 }
787
788 int
789 conv_uni_to_pc(struct vc_data *conp, long ucs) 
790 {
791         int h;
792         u16 **p1, *p2;
793         struct uni_pagedir *p;
794   
795         /* Only 16-bit codes supported at this time */
796         if (ucs > 0xffff)
797                 return -4;              /* Not found */
798         else if (ucs < 0x20)
799                 return -1;              /* Not a printable character */
800         else if (ucs == 0xfeff || (ucs >= 0x200b && ucs <= 0x200f))
801                 return -2;                      /* Zero-width space */
802         /*
803          * UNI_DIRECT_BASE indicates the start of the region in the User Zone
804          * which always has a 1:1 mapping to the currently loaded font.  The
805          * UNI_DIRECT_MASK indicates the bit span of the region.
806          */
807         else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
808                 return ucs & UNI_DIRECT_MASK;
809   
810         if (!*conp->vc_uni_pagedir_loc)
811                 return -3;
812
813         p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;  
814         if ((p1 = p->uni_pgdir[ucs >> 11]) &&
815             (p2 = p1[(ucs >> 6) & 0x1f]) &&
816             (h = p2[ucs & 0x3f]) < MAX_GLYPH)
817                 return h;
818
819         return -4;              /* not found */
820 }
821
822 /*
823  * This is called at sys_setup time, after memory and the console are
824  * initialized.  It must be possible to call kmalloc(..., GFP_KERNEL)
825  * from this function, hence the call from sys_setup.
826  */
827 void __init 
828 console_map_init(void)
829 {
830         int i;
831         
832         for (i = 0; i < MAX_NR_CONSOLES; i++)
833                 if (vc_cons_allocated(i) && !*vc_cons[i].d->vc_uni_pagedir_loc)
834                         con_set_default_unimap(vc_cons[i].d);
835 }
836