4 * Mapping from internal code (such as Latin-1 or Unicode or IBM PC code)
9 * Support for multiple unimaps by Jakub Jelinek <jj@ultra.linux.cz>, July 1998
11 * Fix bug in inverse translation. Stanislav Voronyi <stas@cnti.uanet.kharkov.ua>, Dec 1998
14 #include <linux/config.h>
15 #include <linux/module.h>
17 #include <linux/errno.h>
19 #include <linux/slab.h>
20 #include <linux/init.h>
21 #include <linux/tty.h>
22 #include <asm/uaccess.h>
23 #include <linux/consolemap.h>
24 #include <linux/vt_kern.h>
26 static unsigned short translations[][256] = {
27 /* 8-bit Latin-1 mapped to Unicode -- trivial mapping */
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
62 /* VT100 graphics mapped to Unicode */
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, 0xf800,
78 0xf801, 0x2500, 0xf803, 0xf804, 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
97 /* IBM Codepage 437 mapped to Unicode */
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
132 /* User mapping -- default to codes for direct font mapping */
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
169 /* The standard kernel character-to-font mappings are not invertible
170 -- this is just a best effort. */
172 #define MAX_GLYPH 512 /* Max possible glyph value */
174 static int inv_translate[MAX_NR_CONSOLES];
178 unsigned long refcount;
180 unsigned char *inverse_translations[4];
184 static struct uni_pagedir *dflt;
186 static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int i)
189 unsigned short *t = translations[i];
193 q = p->inverse_translations[i];
196 q = p->inverse_translations[i] = (unsigned char *)
197 kmalloc(MAX_GLYPH, GFP_KERNEL);
200 memset(q, 0, MAX_GLYPH);
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. */
211 unsigned short *set_translate(int m,int currcons)
213 inv_translate[currcons] = m;
214 return translations[m];
218 * Inverse translation is impossible for several reasons:
219 * 1. The font<->character maps are not 1-1.
220 * 2. The text may have been written while a different translation map
221 * was active, or using Unicode.
222 * Still, it is now possible to a certain extent to cut and paste non-ASCII.
224 unsigned char inverse_translate(struct vc_data *conp, int glyph)
226 struct uni_pagedir *p;
227 if (glyph < 0 || glyph >= MAX_GLYPH)
229 else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc) ||
230 !p->inverse_translations[inv_translate[conp->vc_num]])
233 return p->inverse_translations[inv_translate[conp->vc_num]][glyph];
236 static void update_user_maps(void)
239 struct uni_pagedir *p, *q = NULL;
241 for (i = 0; i < MAX_NR_CONSOLES; i++) {
242 if (!vc_cons_allocated(i))
244 p = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
246 set_inverse_transl(vc_cons[i].d, p, USER_MAP);
253 * Load customizable translation table
254 * arg points to a 256 byte translation table.
256 * The "old" variants are for translation directly to font (using the
257 * 0xf000-0xf0ff "transparent" Unicodes) whereas the "new" variants set
258 * Unicodes explicitly.
260 int con_set_trans_old(unsigned char __user * arg)
263 unsigned short *p = translations[USER_MAP];
265 i = verify_area(VERIFY_READ, arg, E_TABSZ);
269 for (i=0; i<E_TABSZ ; i++) {
271 __get_user(uc, arg+i);
272 p[i] = UNI_DIRECT_BASE | uc;
279 int con_get_trans_old(unsigned char __user * arg)
282 unsigned short *p = translations[USER_MAP];
284 i = verify_area(VERIFY_WRITE, arg, E_TABSZ);
288 for (i=0; i<E_TABSZ ; i++)
290 ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
291 __put_user((ch & ~0xff) ? 0 : ch, arg+i);
296 int con_set_trans_new(ushort __user * arg)
299 unsigned short *p = translations[USER_MAP];
301 i = verify_area(VERIFY_READ, arg, E_TABSZ*sizeof(unsigned short));
305 for (i=0; i<E_TABSZ ; i++) {
307 __get_user(us, arg+i);
315 int con_get_trans_new(ushort __user * arg)
318 unsigned short *p = translations[USER_MAP];
320 i = verify_area(VERIFY_WRITE, arg, E_TABSZ*sizeof(unsigned short));
324 for (i=0; i<E_TABSZ ; i++)
325 __put_user(p[i], arg+i);
331 * Unicode -> current font conversion
333 * A font has at most 512 chars, usually 256.
334 * But one font position may represent several Unicode chars.
335 * A hashtable is somewhat of a pain to deal with, so use a
336 * "paged table" instead. Simulation has shown the memory cost of
337 * this 3-level paged table scheme to be comparable to a hash table.
340 extern u8 dfont_unicount[]; /* Defined in console_defmap.c */
341 extern u16 dfont_unitable[];
343 static void con_release_unimap(struct uni_pagedir *p)
348 if (p == dflt) dflt = NULL;
349 for (i = 0; i < 32; i++) {
350 if ((p1 = p->uni_pgdir[i]) != NULL) {
351 for (j = 0; j < 32; j++)
356 p->uni_pgdir[i] = NULL;
358 for (i = 0; i < 4; i++)
359 if (p->inverse_translations[i]) {
360 kfree(p->inverse_translations[i]);
361 p->inverse_translations[i] = NULL;
365 void con_free_unimap(int con)
367 struct uni_pagedir *p;
368 struct vc_data *conp = vc_cons[con].d;
370 p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
372 *conp->vc_uni_pagedir_loc = 0;
373 if (--p->refcount) return;
374 con_release_unimap(p);
378 static int con_unify_unimap(struct vc_data *conp, struct uni_pagedir *p)
381 struct uni_pagedir *q;
383 for (i = 0; i < MAX_NR_CONSOLES; i++) {
384 if (!vc_cons_allocated(i))
386 q = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
387 if (!q || q == p || q->sum != p->sum)
389 for (j = 0; j < 32; j++) {
391 p1 = p->uni_pgdir[j]; q1 = q->uni_pgdir[j];
396 for (k = 0; k < 32; k++) {
397 if (!p1[k] && !q1[k])
399 if (!p1[k] || !q1[k])
401 if (memcmp(p1[k], q1[k], 64*sizeof(u16)))
409 *conp->vc_uni_pagedir_loc = (unsigned long)q;
410 con_release_unimap(p);
419 con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
424 if (!(p1 = p->uni_pgdir[n = unicode >> 11])) {
425 p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);
426 if (!p1) return -ENOMEM;
427 for (i = 0; i < 32; i++)
431 if (!(p2 = p1[n = (unicode >> 6) & 0x1f])) {
432 p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
433 if (!p2) return -ENOMEM;
434 memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */
437 p2[unicode & 0x3f] = fontpos;
439 p->sum += (fontpos << 20) + unicode;
444 /* ui is a leftover from using a hashtable, but might be used again */
445 int con_clear_unimap(int con, struct unimapinit *ui)
447 struct uni_pagedir *p, *q;
448 struct vc_data *conp = vc_cons[con].d;
450 p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
451 if (p && p->readonly) return -EIO;
452 if (!p || --p->refcount) {
453 q = (struct uni_pagedir *)kmalloc(sizeof(*p), GFP_KERNEL);
455 if (p) p->refcount++;
458 memset(q, 0, sizeof(*q));
460 *conp->vc_uni_pagedir_loc = (unsigned long)q;
462 if (p == dflt) dflt = NULL;
465 con_release_unimap(p);
471 con_set_unimap(int con, ushort ct, struct unipair __user *list)
473 int err = 0, err1, i;
474 struct uni_pagedir *p, *q;
475 struct vc_data *conp = vc_cons[con].d;
477 p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
478 if (p->readonly) return -EIO;
482 if (p->refcount > 1) {
486 err1 = con_clear_unimap(con, NULL);
487 if (err1) return err1;
489 q = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
490 for (i = 0, l = 0; i < 32; i++)
491 if ((p1 = p->uni_pgdir[i]))
492 for (j = 0; j < 32; j++)
494 for (k = 0; k < 64; k++, l++)
495 if (p2[k] != 0xffff) {
496 err1 = con_insert_unipair(q, l, p2[k]);
499 *conp->vc_uni_pagedir_loc = (unsigned long)p;
500 con_release_unimap(q);
506 } else if (p == dflt)
510 unsigned short unicode, fontpos;
511 __get_user(unicode, &list->unicode);
512 __get_user(fontpos, &list->fontpos);
513 if ((err1 = con_insert_unipair(p, unicode,fontpos)) != 0)
518 if (con_unify_unimap(conp, p))
521 for (i = 0; i <= 3; i++)
522 set_inverse_transl(conp, p, i); /* Update all inverse translations */
527 /* Loads the unimap for the hardware font, as defined in uni_hash.tbl.
528 The representation used was the most compact I could come up
529 with. This routine is executed at sys_setup time, and when the
530 PIO_FONTRESET ioctl is called. */
533 con_set_default_unimap(int con)
535 int i, j, err = 0, err1;
537 struct uni_pagedir *p;
538 struct vc_data *conp = vc_cons[con].d;
541 p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
545 *conp->vc_uni_pagedir_loc = (unsigned long)dflt;
546 if (p && --p->refcount) {
547 con_release_unimap(p);
553 /* The default font is always 256 characters */
555 err = con_clear_unimap(con,NULL);
558 p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
561 for (i = 0; i < 256; i++)
562 for (j = dfont_unicount[i]; j; j--) {
563 err1 = con_insert_unipair(p, *(q++), i);
568 if (con_unify_unimap(conp, p)) {
569 dflt = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
573 for (i = 0; i <= 3; i++)
574 set_inverse_transl(conp, p, i); /* Update all inverse translations */
578 EXPORT_SYMBOL(con_set_default_unimap);
581 con_copy_unimap(int dstcon, int srccon)
583 struct vc_data *sconp = vc_cons[srccon].d;
584 struct vc_data *dconp = vc_cons[dstcon].d;
585 struct uni_pagedir *q;
587 if (!vc_cons_allocated(srccon) || !*sconp->vc_uni_pagedir_loc)
589 if (*dconp->vc_uni_pagedir_loc == *sconp->vc_uni_pagedir_loc)
591 con_free_unimap(dstcon);
592 q = (struct uni_pagedir *)*sconp->vc_uni_pagedir_loc;
594 *dconp->vc_uni_pagedir_loc = (long)q;
599 con_get_unimap(int con, ushort ct, ushort __user *uct, struct unipair __user *list)
603 struct uni_pagedir *p;
604 struct vc_data *conp = vc_cons[con].d;
607 if (*conp->vc_uni_pagedir_loc) {
608 p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
609 for (i = 0; i < 32; i++)
610 if ((p1 = p->uni_pgdir[i]))
611 for (j = 0; j < 32; j++)
613 for (k = 0; k < 64; k++) {
614 if (*p2 < MAX_GLYPH && ect++ < ct) {
615 __put_user((u_short)((i<<11)+(j<<6)+k),
617 __put_user((u_short) *p2,
624 __put_user(ect, uct);
625 return ((ect <= ct) ? 0 : -ENOMEM);
628 void con_protect_unimap(int con, int rdonly)
630 struct uni_pagedir *p = (struct uni_pagedir *)
631 *vc_cons[con].d->vc_uni_pagedir_loc;
633 if (p) p->readonly = rdonly;
637 conv_uni_to_pc(struct vc_data *conp, long ucs)
641 struct uni_pagedir *p;
643 /* Only 16-bit codes supported at this time */
645 ucs = 0xfffd; /* U+FFFD: REPLACEMENT CHARACTER */
646 else if (ucs < 0x20 || ucs >= 0xfffe)
647 return -1; /* Not a printable character */
648 else if (ucs == 0xfeff || (ucs >= 0x200a && ucs <= 0x200f))
649 return -2; /* Zero-width space */
651 * UNI_DIRECT_BASE indicates the start of the region in the User Zone
652 * which always has a 1:1 mapping to the currently loaded font. The
653 * UNI_DIRECT_MASK indicates the bit span of the region.
655 else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
656 return ucs & UNI_DIRECT_MASK;
658 if (!*conp->vc_uni_pagedir_loc)
661 p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
662 if ((p1 = p->uni_pgdir[ucs >> 11]) &&
663 (p2 = p1[(ucs >> 6) & 0x1f]) &&
664 (h = p2[ucs & 0x3f]) < MAX_GLYPH)
667 return -4; /* not found */
671 * This is called at sys_setup time, after memory and the console are
672 * initialized. It must be possible to call kmalloc(..., GFP_KERNEL)
673 * from this function, hence the call from sys_setup.
676 console_map_init(void)
680 for (i = 0; i < MAX_NR_CONSOLES; i++)
681 if (vc_cons_allocated(i) && !*vc_cons[i].d->vc_uni_pagedir_loc)
682 con_set_default_unimap(i);
685 EXPORT_SYMBOL(con_copy_unimap);