[PATCH] bcm43xx: fix whitespace
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / char / consolemap.c
blobc85a4fa60da7e235b207a6ba84d305928ec1e142
1 /*
2 * consolemap.c
4 * Mapping from internal code (such as Latin-1 or Unicode or IBM PC code)
5 * to font positions.
7 * aeb, 950210
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>
16 #include <linux/kd.h>
17 #include <linux/errno.h>
18 #include <linux/mm.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
61 },
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, 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
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];
176 struct uni_pagedir {
177 u16 **uni_pgdir[32];
178 unsigned long refcount;
179 unsigned long sum;
180 unsigned char *inverse_translations[4];
181 int readonly;
184 static struct uni_pagedir *dflt;
186 static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int i)
188 int j, glyph;
189 unsigned short *t = translations[i];
190 unsigned char *q;
192 if (!p) return;
193 q = p->inverse_translations[i];
195 if (!q) {
196 q = p->inverse_translations[i] = (unsigned char *)
197 kmalloc(MAX_GLYPH, GFP_KERNEL);
198 if (!q) return;
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. */
206 q[glyph] = j;
211 unsigned short *set_translate(int m, struct vc_data *vc)
213 inv_translate[vc->vc_num] = 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)
228 return 0;
229 else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc) ||
230 !p->inverse_translations[inv_translate[conp->vc_num]])
231 return glyph;
232 else
233 return p->inverse_translations[inv_translate[conp->vc_num]][glyph];
236 static void update_user_maps(void)
238 int i;
239 struct uni_pagedir *p, *q = NULL;
241 for (i = 0; i < MAX_NR_CONSOLES; i++) {
242 if (!vc_cons_allocated(i))
243 continue;
244 p = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
245 if (p && p != q) {
246 set_inverse_transl(vc_cons[i].d, p, USER_MAP);
247 q = p;
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)
262 int i;
263 unsigned short *p = translations[USER_MAP];
265 if (!access_ok(VERIFY_READ, arg, E_TABSZ))
266 return -EFAULT;
268 for (i=0; i<E_TABSZ ; i++) {
269 unsigned char uc;
270 __get_user(uc, arg+i);
271 p[i] = UNI_DIRECT_BASE | uc;
274 update_user_maps();
275 return 0;
278 int con_get_trans_old(unsigned char __user * arg)
280 int i, ch;
281 unsigned short *p = translations[USER_MAP];
283 if (!access_ok(VERIFY_WRITE, arg, E_TABSZ))
284 return -EFAULT;
286 for (i=0; i<E_TABSZ ; i++)
288 ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
289 __put_user((ch & ~0xff) ? 0 : ch, arg+i);
291 return 0;
294 int con_set_trans_new(ushort __user * arg)
296 int i;
297 unsigned short *p = translations[USER_MAP];
299 if (!access_ok(VERIFY_READ, arg, E_TABSZ*sizeof(unsigned short)))
300 return -EFAULT;
302 for (i=0; i<E_TABSZ ; i++) {
303 unsigned short us;
304 __get_user(us, arg+i);
305 p[i] = us;
308 update_user_maps();
309 return 0;
312 int con_get_trans_new(ushort __user * arg)
314 int i;
315 unsigned short *p = translations[USER_MAP];
317 if (!access_ok(VERIFY_WRITE, arg, E_TABSZ*sizeof(unsigned short)))
318 return -EFAULT;
320 for (i=0; i<E_TABSZ ; i++)
321 __put_user(p[i], arg+i);
323 return 0;
327 * Unicode -> current font conversion
329 * A font has at most 512 chars, usually 256.
330 * But one font position may represent several Unicode chars.
331 * A hashtable is somewhat of a pain to deal with, so use a
332 * "paged table" instead. Simulation has shown the memory cost of
333 * this 3-level paged table scheme to be comparable to a hash table.
336 extern u8 dfont_unicount[]; /* Defined in console_defmap.c */
337 extern u16 dfont_unitable[];
339 static void con_release_unimap(struct uni_pagedir *p)
341 u16 **p1;
342 int i, j;
344 if (p == dflt) dflt = NULL;
345 for (i = 0; i < 32; i++) {
346 if ((p1 = p->uni_pgdir[i]) != NULL) {
347 for (j = 0; j < 32; j++)
348 kfree(p1[j]);
349 kfree(p1);
351 p->uni_pgdir[i] = NULL;
353 for (i = 0; i < 4; i++) {
354 kfree(p->inverse_translations[i]);
355 p->inverse_translations[i] = NULL;
359 void con_free_unimap(struct vc_data *vc)
361 struct uni_pagedir *p;
363 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
364 if (!p)
365 return;
366 *vc->vc_uni_pagedir_loc = 0;
367 if (--p->refcount)
368 return;
369 con_release_unimap(p);
370 kfree(p);
373 static int con_unify_unimap(struct vc_data *conp, struct uni_pagedir *p)
375 int i, j, k;
376 struct uni_pagedir *q;
378 for (i = 0; i < MAX_NR_CONSOLES; i++) {
379 if (!vc_cons_allocated(i))
380 continue;
381 q = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
382 if (!q || q == p || q->sum != p->sum)
383 continue;
384 for (j = 0; j < 32; j++) {
385 u16 **p1, **q1;
386 p1 = p->uni_pgdir[j]; q1 = q->uni_pgdir[j];
387 if (!p1 && !q1)
388 continue;
389 if (!p1 || !q1)
390 break;
391 for (k = 0; k < 32; k++) {
392 if (!p1[k] && !q1[k])
393 continue;
394 if (!p1[k] || !q1[k])
395 break;
396 if (memcmp(p1[k], q1[k], 64*sizeof(u16)))
397 break;
399 if (k < 32)
400 break;
402 if (j == 32) {
403 q->refcount++;
404 *conp->vc_uni_pagedir_loc = (unsigned long)q;
405 con_release_unimap(p);
406 kfree(p);
407 return 1;
410 return 0;
413 static int
414 con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
416 int i, n;
417 u16 **p1, *p2;
419 if (!(p1 = p->uni_pgdir[n = unicode >> 11])) {
420 p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);
421 if (!p1) return -ENOMEM;
422 for (i = 0; i < 32; i++)
423 p1[i] = NULL;
426 if (!(p2 = p1[n = (unicode >> 6) & 0x1f])) {
427 p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
428 if (!p2) return -ENOMEM;
429 memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */
432 p2[unicode & 0x3f] = fontpos;
434 p->sum += (fontpos << 20) + unicode;
436 return 0;
439 /* ui is a leftover from using a hashtable, but might be used again */
440 int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
442 struct uni_pagedir *p, *q;
444 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
445 if (p && p->readonly) return -EIO;
446 if (!p || --p->refcount) {
447 q = (struct uni_pagedir *)kmalloc(sizeof(*p), GFP_KERNEL);
448 if (!q) {
449 if (p) p->refcount++;
450 return -ENOMEM;
452 memset(q, 0, sizeof(*q));
453 q->refcount=1;
454 *vc->vc_uni_pagedir_loc = (unsigned long)q;
455 } else {
456 if (p == dflt) dflt = NULL;
457 p->refcount++;
458 p->sum = 0;
459 con_release_unimap(p);
461 return 0;
464 int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
466 int err = 0, err1, i;
467 struct uni_pagedir *p, *q;
469 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
470 if (p->readonly) return -EIO;
472 if (!ct) return 0;
474 if (p->refcount > 1) {
475 int j, k;
476 u16 **p1, *p2, l;
478 err1 = con_clear_unimap(vc, NULL);
479 if (err1) return err1;
481 q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
482 for (i = 0, l = 0; i < 32; i++)
483 if ((p1 = p->uni_pgdir[i]))
484 for (j = 0; j < 32; j++)
485 if ((p2 = p1[j]))
486 for (k = 0; k < 64; k++, l++)
487 if (p2[k] != 0xffff) {
488 err1 = con_insert_unipair(q, l, p2[k]);
489 if (err1) {
490 p->refcount++;
491 *vc->vc_uni_pagedir_loc = (unsigned long)p;
492 con_release_unimap(q);
493 kfree(q);
494 return err1;
497 p = q;
498 } else if (p == dflt)
499 dflt = NULL;
501 while (ct--) {
502 unsigned short unicode, fontpos;
503 __get_user(unicode, &list->unicode);
504 __get_user(fontpos, &list->fontpos);
505 if ((err1 = con_insert_unipair(p, unicode,fontpos)) != 0)
506 err = err1;
507 list++;
510 if (con_unify_unimap(vc, p))
511 return err;
513 for (i = 0; i <= 3; i++)
514 set_inverse_transl(vc, p, i); /* Update all inverse translations */
516 return err;
519 /* Loads the unimap for the hardware font, as defined in uni_hash.tbl.
520 The representation used was the most compact I could come up
521 with. This routine is executed at sys_setup time, and when the
522 PIO_FONTRESET ioctl is called. */
524 int con_set_default_unimap(struct vc_data *vc)
526 int i, j, err = 0, err1;
527 u16 *q;
528 struct uni_pagedir *p;
530 if (dflt) {
531 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
532 if (p == dflt)
533 return 0;
534 dflt->refcount++;
535 *vc->vc_uni_pagedir_loc = (unsigned long)dflt;
536 if (p && --p->refcount) {
537 con_release_unimap(p);
538 kfree(p);
540 return 0;
543 /* The default font is always 256 characters */
545 err = con_clear_unimap(vc, NULL);
546 if (err) return err;
548 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
549 q = dfont_unitable;
551 for (i = 0; i < 256; i++)
552 for (j = dfont_unicount[i]; j; j--) {
553 err1 = con_insert_unipair(p, *(q++), i);
554 if (err1)
555 err = err1;
558 if (con_unify_unimap(vc, p)) {
559 dflt = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
560 return err;
563 for (i = 0; i <= 3; i++)
564 set_inverse_transl(vc, p, i); /* Update all inverse translations */
565 dflt = p;
566 return err;
568 EXPORT_SYMBOL(con_set_default_unimap);
570 int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
572 struct uni_pagedir *q;
574 if (!*src_vc->vc_uni_pagedir_loc)
575 return -EINVAL;
576 if (*dst_vc->vc_uni_pagedir_loc == *src_vc->vc_uni_pagedir_loc)
577 return 0;
578 con_free_unimap(dst_vc);
579 q = (struct uni_pagedir *)*src_vc->vc_uni_pagedir_loc;
580 q->refcount++;
581 *dst_vc->vc_uni_pagedir_loc = (long)q;
582 return 0;
585 int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list)
587 int i, j, k, ect;
588 u16 **p1, *p2;
589 struct uni_pagedir *p;
591 ect = 0;
592 if (*vc->vc_uni_pagedir_loc) {
593 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
594 for (i = 0; i < 32; i++)
595 if ((p1 = p->uni_pgdir[i]))
596 for (j = 0; j < 32; j++)
597 if ((p2 = *(p1++)))
598 for (k = 0; k < 64; k++) {
599 if (*p2 < MAX_GLYPH && ect++ < ct) {
600 __put_user((u_short)((i<<11)+(j<<6)+k),
601 &list->unicode);
602 __put_user((u_short) *p2,
603 &list->fontpos);
604 list++;
606 p2++;
609 __put_user(ect, uct);
610 return ((ect <= ct) ? 0 : -ENOMEM);
613 void con_protect_unimap(struct vc_data *vc, int rdonly)
615 struct uni_pagedir *p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
617 if (p)
618 p->readonly = rdonly;
622 conv_uni_to_pc(struct vc_data *conp, long ucs)
624 int h;
625 u16 **p1, *p2;
626 struct uni_pagedir *p;
628 /* Only 16-bit codes supported at this time */
629 if (ucs > 0xffff)
630 ucs = 0xfffd; /* U+FFFD: REPLACEMENT CHARACTER */
631 else if (ucs < 0x20 || ucs >= 0xfffe)
632 return -1; /* Not a printable character */
633 else if (ucs == 0xfeff || (ucs >= 0x200a && ucs <= 0x200f))
634 return -2; /* Zero-width space */
636 * UNI_DIRECT_BASE indicates the start of the region in the User Zone
637 * which always has a 1:1 mapping to the currently loaded font. The
638 * UNI_DIRECT_MASK indicates the bit span of the region.
640 else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
641 return ucs & UNI_DIRECT_MASK;
643 if (!*conp->vc_uni_pagedir_loc)
644 return -3;
646 p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
647 if ((p1 = p->uni_pgdir[ucs >> 11]) &&
648 (p2 = p1[(ucs >> 6) & 0x1f]) &&
649 (h = p2[ucs & 0x3f]) < MAX_GLYPH)
650 return h;
652 return -4; /* not found */
656 * This is called at sys_setup time, after memory and the console are
657 * initialized. It must be possible to call kmalloc(..., GFP_KERNEL)
658 * from this function, hence the call from sys_setup.
660 void __init
661 console_map_init(void)
663 int i;
665 for (i = 0; i < MAX_NR_CONSOLES; i++)
666 if (vc_cons_allocated(i) && !*vc_cons[i].d->vc_uni_pagedir_loc)
667 con_set_default_unimap(vc_cons[i].d);
670 EXPORT_SYMBOL(con_copy_unimap);