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/module.h>
16
#include <linux/errno.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>
25
static unsigned short translations[][256] = {
26
/* 8-bit Latin-1 mapped to Unicode -- trivial mapping */
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
61
/* VT100 graphics mapped to Unicode */
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
96
/* IBM Codepage 437 mapped to Unicode */
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
131
/* User mapping -- default to codes for direct font mapping */
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
168
/* The standard kernel character-to-font mappings are not invertible
169
-- this is just a best effort. */
171
#define MAX_GLYPH 512 /* Max possible glyph value */
173
static int inv_translate[MAX_NR_CONSOLES];
177
unsigned long refcount;
179
unsigned char *inverse_translations[4];
180
u16 *inverse_trans_unicode;
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
static void set_inverse_trans_unicode(struct vc_data *conp,
212
struct uni_pagedir *p)
219
q = p->inverse_trans_unicode;
221
q = p->inverse_trans_unicode =
222
kmalloc(MAX_GLYPH * sizeof(u16), GFP_KERNEL);
226
memset(q, 0, MAX_GLYPH * sizeof(u16));
228
for (i = 0; i < 32; i++) {
229
p1 = p->uni_pgdir[i];
232
for (j = 0; j < 32; j++) {
236
for (k = 0; k < 64; k++) {
238
if (glyph >= 0 && glyph < MAX_GLYPH
240
q[glyph] = (i << 11) + (j << 6) + k;
246
unsigned short *set_translate(int m, struct vc_data *vc)
248
inv_translate[vc->vc_num] = m;
249
return translations[m];
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
257
* Still, it is now possible to a certain extent to cut and paste non-ASCII.
259
u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode)
261
struct uni_pagedir *p;
263
if (glyph < 0 || glyph >= MAX_GLYPH)
265
else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc))
267
else if (use_unicode) {
268
if (!p->inverse_trans_unicode)
271
return p->inverse_trans_unicode[glyph];
273
m = inv_translate[conp->vc_num];
274
if (!p->inverse_translations[m])
277
return p->inverse_translations[m][glyph];
280
EXPORT_SYMBOL_GPL(inverse_translate);
282
static void update_user_maps(void)
285
struct uni_pagedir *p, *q = NULL;
287
for (i = 0; i < MAX_NR_CONSOLES; i++) {
288
if (!vc_cons_allocated(i))
290
p = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
292
set_inverse_transl(vc_cons[i].d, p, USER_MAP);
293
set_inverse_trans_unicode(vc_cons[i].d, p);
300
* Load customizable translation table
301
* arg points to a 256 byte translation table.
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.
307
int con_set_trans_old(unsigned char __user * arg)
310
unsigned short *p = translations[USER_MAP];
312
if (!access_ok(VERIFY_READ, arg, E_TABSZ))
315
for (i=0; i<E_TABSZ ; i++) {
317
__get_user(uc, arg+i);
318
p[i] = UNI_DIRECT_BASE | uc;
325
int con_get_trans_old(unsigned char __user * arg)
328
unsigned short *p = translations[USER_MAP];
330
if (!access_ok(VERIFY_WRITE, arg, E_TABSZ))
333
for (i=0; i<E_TABSZ ; i++)
335
ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
336
__put_user((ch & ~0xff) ? 0 : ch, arg+i);
341
int con_set_trans_new(ushort __user * arg)
344
unsigned short *p = translations[USER_MAP];
346
if (!access_ok(VERIFY_READ, arg, E_TABSZ*sizeof(unsigned short)))
349
for (i=0; i<E_TABSZ ; i++) {
351
__get_user(us, arg+i);
359
int con_get_trans_new(ushort __user * arg)
362
unsigned short *p = translations[USER_MAP];
364
if (!access_ok(VERIFY_WRITE, arg, E_TABSZ*sizeof(unsigned short)))
367
for (i=0; i<E_TABSZ ; i++)
368
__put_user(p[i], arg+i);
374
* Unicode -> current font conversion
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.
383
extern u8 dfont_unicount[]; /* Defined in console_defmap.c */
384
extern u16 dfont_unitable[];
386
static void con_release_unimap(struct uni_pagedir *p)
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++)
398
p->uni_pgdir[i] = NULL;
400
for (i = 0; i < 4; i++) {
401
kfree(p->inverse_translations[i]);
402
p->inverse_translations[i] = NULL;
404
if (p->inverse_trans_unicode) {
405
kfree(p->inverse_trans_unicode);
406
p->inverse_trans_unicode = NULL;
410
void con_free_unimap(struct vc_data *vc)
412
struct uni_pagedir *p;
414
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
417
*vc->vc_uni_pagedir_loc = 0;
420
con_release_unimap(p);
424
static int con_unify_unimap(struct vc_data *conp, struct uni_pagedir *p)
427
struct uni_pagedir *q;
429
for (i = 0; i < MAX_NR_CONSOLES; i++) {
430
if (!vc_cons_allocated(i))
432
q = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
433
if (!q || q == p || q->sum != p->sum)
435
for (j = 0; j < 32; j++) {
437
p1 = p->uni_pgdir[j]; q1 = q->uni_pgdir[j];
442
for (k = 0; k < 32; k++) {
443
if (!p1[k] && !q1[k])
445
if (!p1[k] || !q1[k])
447
if (memcmp(p1[k], q1[k], 64*sizeof(u16)))
455
*conp->vc_uni_pagedir_loc = (unsigned long)q;
456
con_release_unimap(p);
465
con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
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++)
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) */
483
p2[unicode & 0x3f] = fontpos;
485
p->sum += (fontpos << 20) + unicode;
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)
493
struct uni_pagedir *p, *q;
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);
500
if (p) p->refcount++;
504
*vc->vc_uni_pagedir_loc = (unsigned long)q;
506
if (p == dflt) dflt = NULL;
509
con_release_unimap(p);
514
int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
516
int err = 0, err1, i;
517
struct uni_pagedir *p, *q;
519
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
520
if (p->readonly) return -EIO;
524
if (p->refcount > 1) {
528
err1 = con_clear_unimap(vc, NULL);
529
if (err1) return err1;
531
q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
532
for (i = 0, l = 0; i < 32; i++)
533
if ((p1 = p->uni_pgdir[i]))
534
for (j = 0; j < 32; j++)
536
for (k = 0; k < 64; k++, l++)
537
if (p2[k] != 0xffff) {
538
err1 = con_insert_unipair(q, l, p2[k]);
541
*vc->vc_uni_pagedir_loc = (unsigned long)p;
542
con_release_unimap(q);
548
} else if (p == dflt)
552
unsigned short unicode, fontpos;
553
__get_user(unicode, &list->unicode);
554
__get_user(fontpos, &list->fontpos);
555
if ((err1 = con_insert_unipair(p, unicode,fontpos)) != 0)
560
if (con_unify_unimap(vc, p))
563
for (i = 0; i <= 3; i++)
564
set_inverse_transl(vc, p, i); /* Update all inverse translations */
565
set_inverse_trans_unicode(vc, p);
570
/* Loads the unimap for the hardware font, as defined in uni_hash.tbl.
571
The representation used was the most compact I could come up
572
with. This routine is executed at sys_setup time, and when the
573
PIO_FONTRESET ioctl is called. */
575
int con_set_default_unimap(struct vc_data *vc)
577
int i, j, err = 0, err1;
579
struct uni_pagedir *p;
582
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
586
*vc->vc_uni_pagedir_loc = (unsigned long)dflt;
587
if (p && --p->refcount) {
588
con_release_unimap(p);
594
/* The default font is always 256 characters */
596
err = con_clear_unimap(vc, NULL);
599
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
602
for (i = 0; i < 256; i++)
603
for (j = dfont_unicount[i]; j; j--) {
604
err1 = con_insert_unipair(p, *(q++), i);
609
if (con_unify_unimap(vc, p)) {
610
dflt = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
614
for (i = 0; i <= 3; i++)
615
set_inverse_transl(vc, p, i); /* Update all inverse translations */
616
set_inverse_trans_unicode(vc, p);
620
EXPORT_SYMBOL(con_set_default_unimap);
622
int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
624
struct uni_pagedir *q;
626
if (!*src_vc->vc_uni_pagedir_loc)
628
if (*dst_vc->vc_uni_pagedir_loc == *src_vc->vc_uni_pagedir_loc)
630
con_free_unimap(dst_vc);
631
q = (struct uni_pagedir *)*src_vc->vc_uni_pagedir_loc;
633
*dst_vc->vc_uni_pagedir_loc = (long)q;
637
int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list)
641
struct uni_pagedir *p;
644
if (*vc->vc_uni_pagedir_loc) {
645
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
646
for (i = 0; i < 32; i++)
647
if ((p1 = p->uni_pgdir[i]))
648
for (j = 0; j < 32; j++)
650
for (k = 0; k < 64; k++) {
651
if (*p2 < MAX_GLYPH && ect++ < ct) {
652
__put_user((u_short)((i<<11)+(j<<6)+k),
654
__put_user((u_short) *p2,
661
__put_user(ect, uct);
662
return ((ect <= ct) ? 0 : -ENOMEM);
665
void con_protect_unimap(struct vc_data *vc, int rdonly)
667
struct uni_pagedir *p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
670
p->readonly = rdonly;
674
* Always use USER_MAP. These functions are used by the keyboard,
675
* which shouldn't be affected by G0/G1 switching, etc.
676
* If the user map still contains default values, i.e. the
677
* direct-to-font mapping, then assume user is using Latin1.
679
/* may be called during an interrupt */
680
u32 conv_8bit_to_uni(unsigned char c)
682
unsigned short uni = translations[USER_MAP][c];
683
return uni == (0xf000 | c) ? c : uni;
686
int conv_uni_to_8bit(u32 uni)
689
for (c = 0; c < 0x100; c++)
690
if (translations[USER_MAP][c] == uni ||
691
(translations[USER_MAP][c] == (c | 0xf000) && uni == c))
697
conv_uni_to_pc(struct vc_data *conp, long ucs)
701
struct uni_pagedir *p;
703
/* Only 16-bit codes supported at this time */
705
return -4; /* Not found */
707
return -1; /* Not a printable character */
708
else if (ucs == 0xfeff || (ucs >= 0x200b && ucs <= 0x200f))
709
return -2; /* Zero-width space */
711
* UNI_DIRECT_BASE indicates the start of the region in the User Zone
712
* which always has a 1:1 mapping to the currently loaded font. The
713
* UNI_DIRECT_MASK indicates the bit span of the region.
715
else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
716
return ucs & UNI_DIRECT_MASK;
718
if (!*conp->vc_uni_pagedir_loc)
721
p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
722
if ((p1 = p->uni_pgdir[ucs >> 11]) &&
723
(p2 = p1[(ucs >> 6) & 0x1f]) &&
724
(h = p2[ucs & 0x3f]) < MAX_GLYPH)
727
return -4; /* not found */
731
* This is called at sys_setup time, after memory and the console are
732
* initialized. It must be possible to call kmalloc(..., GFP_KERNEL)
733
* from this function, hence the call from sys_setup.
736
console_map_init(void)
740
for (i = 0; i < MAX_NR_CONSOLES; i++)
741
if (vc_cons_allocated(i) && !*vc_cons[i].d->vc_uni_pagedir_loc)
742
con_set_default_unimap(vc_cons[i].d);
745
EXPORT_SYMBOL(con_copy_unimap);