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