PageRenderTime 70ms CodeModel.GetById 15ms app.highlight 48ms RepoModel.GetById 1ms app.codeStats 1ms

/drivers/char/consolemap.c

https://bitbucket.org/evzijst/gittest
C | 672 lines | 533 code | 79 blank | 60 comment | 130 complexity | 7e0bad37b338a3e6ebaf53fc99b32511 MD5 | raw file
  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/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>
 25
 26static unsigned short translations[][256] = {
 27  /* 8-bit Latin-1 mapped to Unicode -- trivial mapping */
 28  {
 29    0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
 30    0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
 31    0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
 32    0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
 33    0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
 34    0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
 35    0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
 36    0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
 37    0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
 38    0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
 39    0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
 40    0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
 41    0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
 42    0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
 43    0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
 44    0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
 45    0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
 46    0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
 47    0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
 48    0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
 49    0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
 50    0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
 51    0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
 52    0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
 53    0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
 54    0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
 55    0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
 56    0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
 57    0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
 58    0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
 59    0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
 60    0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
 61  }, 
 62  /* VT100 graphics mapped to Unicode */
 63  {
 64    0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
 65    0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
 66    0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
 67    0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
 68    0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
 69    0x0028, 0x0029, 0x002a, 0x2192, 0x2190, 0x2191, 0x2193, 0x002f,
 70    0x2588, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
 71    0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
 72    0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
 73    0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
 74    0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
 75    0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x00a0,
 76    0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1,
 77    0x2591, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba,
 78    0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c,
 79    0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x007f,
 80    0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
 81    0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
 82    0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
 83    0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
 84    0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
 85    0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
 86    0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
 87    0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
 88    0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
 89    0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
 90    0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
 91    0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
 92    0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
 93    0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
 94    0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
 95    0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
 96  },
 97  /* IBM Codepage 437 mapped to Unicode */
 98  {
 99    0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022, 
100    0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
101    0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
102    0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
103    0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
104    0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
105    0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
106    0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
107    0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
108    0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
109    0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
110    0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
111    0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
112    0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
113    0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
114    0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
115    0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
116    0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
117    0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
118    0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
119    0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
120    0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
121    0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
122    0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
123    0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
124    0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
125    0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
126    0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
127    0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
128    0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
129    0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
130    0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
131  }, 
132  /* User mapping -- default to codes for direct font mapping */
133  {
134    0xf000, 0xf001, 0xf002, 0xf003, 0xf004, 0xf005, 0xf006, 0xf007,
135    0xf008, 0xf009, 0xf00a, 0xf00b, 0xf00c, 0xf00d, 0xf00e, 0xf00f,
136    0xf010, 0xf011, 0xf012, 0xf013, 0xf014, 0xf015, 0xf016, 0xf017,
137    0xf018, 0xf019, 0xf01a, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
138    0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
139    0xf028, 0xf029, 0xf02a, 0xf02b, 0xf02c, 0xf02d, 0xf02e, 0xf02f,
140    0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
141    0xf038, 0xf039, 0xf03a, 0xf03b, 0xf03c, 0xf03d, 0xf03e, 0xf03f,
142    0xf040, 0xf041, 0xf042, 0xf043, 0xf044, 0xf045, 0xf046, 0xf047,
143    0xf048, 0xf049, 0xf04a, 0xf04b, 0xf04c, 0xf04d, 0xf04e, 0xf04f,
144    0xf050, 0xf051, 0xf052, 0xf053, 0xf054, 0xf055, 0xf056, 0xf057,
145    0xf058, 0xf059, 0xf05a, 0xf05b, 0xf05c, 0xf05d, 0xf05e, 0xf05f,
146    0xf060, 0xf061, 0xf062, 0xf063, 0xf064, 0xf065, 0xf066, 0xf067,
147    0xf068, 0xf069, 0xf06a, 0xf06b, 0xf06c, 0xf06d, 0xf06e, 0xf06f,
148    0xf070, 0xf071, 0xf072, 0xf073, 0xf074, 0xf075, 0xf076, 0xf077,
149    0xf078, 0xf079, 0xf07a, 0xf07b, 0xf07c, 0xf07d, 0xf07e, 0xf07f,
150    0xf080, 0xf081, 0xf082, 0xf083, 0xf084, 0xf085, 0xf086, 0xf087,
151    0xf088, 0xf089, 0xf08a, 0xf08b, 0xf08c, 0xf08d, 0xf08e, 0xf08f,
152    0xf090, 0xf091, 0xf092, 0xf093, 0xf094, 0xf095, 0xf096, 0xf097,
153    0xf098, 0xf099, 0xf09a, 0xf09b, 0xf09c, 0xf09d, 0xf09e, 0xf09f,
154    0xf0a0, 0xf0a1, 0xf0a2, 0xf0a3, 0xf0a4, 0xf0a5, 0xf0a6, 0xf0a7,
155    0xf0a8, 0xf0a9, 0xf0aa, 0xf0ab, 0xf0ac, 0xf0ad, 0xf0ae, 0xf0af,
156    0xf0b0, 0xf0b1, 0xf0b2, 0xf0b3, 0xf0b4, 0xf0b5, 0xf0b6, 0xf0b7,
157    0xf0b8, 0xf0b9, 0xf0ba, 0xf0bb, 0xf0bc, 0xf0bd, 0xf0be, 0xf0bf,
158    0xf0c0, 0xf0c1, 0xf0c2, 0xf0c3, 0xf0c4, 0xf0c5, 0xf0c6, 0xf0c7,
159    0xf0c8, 0xf0c9, 0xf0ca, 0xf0cb, 0xf0cc, 0xf0cd, 0xf0ce, 0xf0cf,
160    0xf0d0, 0xf0d1, 0xf0d2, 0xf0d3, 0xf0d4, 0xf0d5, 0xf0d6, 0xf0d7,
161    0xf0d8, 0xf0d9, 0xf0da, 0xf0db, 0xf0dc, 0xf0dd, 0xf0de, 0xf0df,
162    0xf0e0, 0xf0e1, 0xf0e2, 0xf0e3, 0xf0e4, 0xf0e5, 0xf0e6, 0xf0e7,
163    0xf0e8, 0xf0e9, 0xf0ea, 0xf0eb, 0xf0ec, 0xf0ed, 0xf0ee, 0xf0ef,
164    0xf0f0, 0xf0f1, 0xf0f2, 0xf0f3, 0xf0f4, 0xf0f5, 0xf0f6, 0xf0f7,
165    0xf0f8, 0xf0f9, 0xf0fa, 0xf0fb, 0xf0fc, 0xf0fd, 0xf0fe, 0xf0ff
166  }
167};
168
169/* The standard kernel character-to-font mappings are not invertible
170   -- this is just a best effort. */
171
172#define MAX_GLYPH 512		/* Max possible glyph value */
173
174static int inv_translate[MAX_NR_CONSOLES];
175
176struct uni_pagedir {
177	u16 		**uni_pgdir[32];
178	unsigned long	refcount;
179	unsigned long	sum;
180	unsigned char	*inverse_translations[4];
181	int		readonly;
182};
183
184static struct uni_pagedir *dflt;
185
186static 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
211unsigned short *set_translate(int m, struct vc_data *vc)
212{
213	inv_translate[vc->vc_num] = m;
214	return translations[m];
215}
216
217/*
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.
223 */
224unsigned char inverse_translate(struct vc_data *conp, int glyph)
225{
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];
234}
235
236static void update_user_maps(void)
237{
238	int i;
239	struct uni_pagedir *p, *q = NULL;
240	
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;
248		}
249	}
250}
251
252/*
253 * Load customizable translation table
254 * arg points to a 256 byte translation table.
255 *
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.
259 */
260int con_set_trans_old(unsigned char __user * arg)
261{
262	int i;
263	unsigned short *p = translations[USER_MAP];
264
265	if (!access_ok(VERIFY_READ, arg, E_TABSZ))
266		return -EFAULT;
267
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;
272	}
273
274	update_user_maps();
275	return 0;
276}
277
278int con_get_trans_old(unsigned char __user * arg)
279{
280	int i, ch;
281	unsigned short *p = translations[USER_MAP];
282
283	if (!access_ok(VERIFY_WRITE, arg, E_TABSZ))
284		return -EFAULT;
285
286	for (i=0; i<E_TABSZ ; i++)
287	  {
288	    ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
289	    __put_user((ch & ~0xff) ? 0 : ch, arg+i);
290	  }
291	return 0;
292}
293
294int con_set_trans_new(ushort __user * arg)
295{
296	int i;
297	unsigned short *p = translations[USER_MAP];
298
299	if (!access_ok(VERIFY_READ, arg, E_TABSZ*sizeof(unsigned short)))
300		return -EFAULT;
301
302	for (i=0; i<E_TABSZ ; i++) {
303		unsigned short us;
304		__get_user(us, arg+i);
305		p[i] = us;
306	}
307
308	update_user_maps();
309	return 0;
310}
311
312int con_get_trans_new(ushort __user * arg)
313{
314	int i;
315	unsigned short *p = translations[USER_MAP];
316
317	if (!access_ok(VERIFY_WRITE, arg, E_TABSZ*sizeof(unsigned short)))
318		return -EFAULT;
319
320	for (i=0; i<E_TABSZ ; i++)
321	  __put_user(p[i], arg+i);
322	
323	return 0;
324}
325
326/*
327 * Unicode -> current font conversion 
328 *
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.
334 */
335
336extern u8 dfont_unicount[];	/* Defined in console_defmap.c */
337extern u16 dfont_unitable[];
338
339static void con_release_unimap(struct uni_pagedir *p)
340{
341	u16 **p1;
342	int i, j;
343
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				if (p1[j])
349					kfree(p1[j]);
350			kfree(p1);
351		}
352		p->uni_pgdir[i] = NULL;
353	}
354	for (i = 0; i < 4; i++)
355		if (p->inverse_translations[i]) {
356			kfree(p->inverse_translations[i]);
357			p->inverse_translations[i] = NULL;
358		}
359}
360
361void con_free_unimap(struct vc_data *vc)
362{
363	struct uni_pagedir *p;
364
365	p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
366	if (!p)
367		return;
368	*vc->vc_uni_pagedir_loc = 0;
369	if (--p->refcount)
370		return;
371	con_release_unimap(p);
372	kfree(p);
373}
374  
375static int con_unify_unimap(struct vc_data *conp, struct uni_pagedir *p)
376{
377	int i, j, k;
378	struct uni_pagedir *q;
379	
380	for (i = 0; i < MAX_NR_CONSOLES; i++) {
381		if (!vc_cons_allocated(i))
382			continue;
383		q = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
384		if (!q || q == p || q->sum != p->sum)
385			continue;
386		for (j = 0; j < 32; j++) {
387			u16 **p1, **q1;
388			p1 = p->uni_pgdir[j]; q1 = q->uni_pgdir[j];
389			if (!p1 && !q1)
390				continue;
391			if (!p1 || !q1)
392				break;
393			for (k = 0; k < 32; k++) {
394				if (!p1[k] && !q1[k])
395					continue;
396				if (!p1[k] || !q1[k])
397					break;
398				if (memcmp(p1[k], q1[k], 64*sizeof(u16)))
399					break;
400			}
401			if (k < 32)
402				break;
403		}
404		if (j == 32) {
405			q->refcount++;
406			*conp->vc_uni_pagedir_loc = (unsigned long)q;
407			con_release_unimap(p);
408			kfree(p);
409			return 1;
410		}
411	}
412	return 0;
413}
414
415static int
416con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
417{
418	int i, n;
419	u16 **p1, *p2;
420
421	if (!(p1 = p->uni_pgdir[n = unicode >> 11])) {
422		p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);
423		if (!p1) return -ENOMEM;
424		for (i = 0; i < 32; i++)
425			p1[i] = NULL;
426	}
427
428	if (!(p2 = p1[n = (unicode >> 6) & 0x1f])) {
429		p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
430		if (!p2) return -ENOMEM;
431		memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */
432	}
433
434	p2[unicode & 0x3f] = fontpos;
435	
436	p->sum += (fontpos << 20) + unicode;
437
438	return 0;
439}
440
441/* ui is a leftover from using a hashtable, but might be used again */
442int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
443{
444	struct uni_pagedir *p, *q;
445  
446	p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
447	if (p && p->readonly) return -EIO;
448	if (!p || --p->refcount) {
449		q = (struct uni_pagedir *)kmalloc(sizeof(*p), GFP_KERNEL);
450		if (!q) {
451			if (p) p->refcount++;
452			return -ENOMEM;
453		}
454		memset(q, 0, sizeof(*q));
455		q->refcount=1;
456		*vc->vc_uni_pagedir_loc = (unsigned long)q;
457	} else {
458		if (p == dflt) dflt = NULL;
459		p->refcount++;
460		p->sum = 0;
461		con_release_unimap(p);
462	}
463	return 0;
464}
465
466int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
467{
468	int err = 0, err1, i;
469	struct uni_pagedir *p, *q;
470
471	p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
472	if (p->readonly) return -EIO;
473	
474	if (!ct) return 0;
475	
476	if (p->refcount > 1) {
477		int j, k;
478		u16 **p1, *p2, l;
479		
480		err1 = con_clear_unimap(vc, NULL);
481		if (err1) return err1;
482		
483		q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
484		for (i = 0, l = 0; i < 32; i++)
485		if ((p1 = p->uni_pgdir[i]))
486			for (j = 0; j < 32; j++)
487			if ((p2 = p1[j]))
488				for (k = 0; k < 64; k++, l++)
489				if (p2[k] != 0xffff) {
490					err1 = con_insert_unipair(q, l, p2[k]);
491					if (err1) {
492						p->refcount++;
493						*vc->vc_uni_pagedir_loc = (unsigned long)p;
494						con_release_unimap(q);
495						kfree(q);
496						return err1; 
497					}
498              			}
499              	p = q;
500	} else if (p == dflt)
501		dflt = NULL;
502	
503	while (ct--) {
504		unsigned short unicode, fontpos;
505		__get_user(unicode, &list->unicode);
506		__get_user(fontpos, &list->fontpos);
507		if ((err1 = con_insert_unipair(p, unicode,fontpos)) != 0)
508			err = err1;
509			list++;
510	}
511	
512	if (con_unify_unimap(vc, p))
513		return err;
514
515	for (i = 0; i <= 3; i++)
516		set_inverse_transl(vc, p, i); /* Update all inverse translations */
517  
518	return err;
519}
520
521/* Loads the unimap for the hardware font, as defined in uni_hash.tbl.
522   The representation used was the most compact I could come up
523   with.  This routine is executed at sys_setup time, and when the
524   PIO_FONTRESET ioctl is called. */
525
526int con_set_default_unimap(struct vc_data *vc)
527{
528	int i, j, err = 0, err1;
529	u16 *q;
530	struct uni_pagedir *p;
531
532	if (dflt) {
533		p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
534		if (p == dflt)
535			return 0;
536		dflt->refcount++;
537		*vc->vc_uni_pagedir_loc = (unsigned long)dflt;
538		if (p && --p->refcount) {
539			con_release_unimap(p);
540			kfree(p);
541		}
542		return 0;
543	}
544	
545	/* The default font is always 256 characters */
546
547	err = con_clear_unimap(vc, NULL);
548	if (err) return err;
549    
550	p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
551	q = dfont_unitable;
552	
553	for (i = 0; i < 256; i++)
554		for (j = dfont_unicount[i]; j; j--) {
555			err1 = con_insert_unipair(p, *(q++), i);
556			if (err1)
557				err = err1;
558		}
559			
560	if (con_unify_unimap(vc, p)) {
561		dflt = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
562		return err;
563	}
564
565	for (i = 0; i <= 3; i++)
566		set_inverse_transl(vc, p, i);	/* Update all inverse translations */
567	dflt = p;
568	return err;
569}
570EXPORT_SYMBOL(con_set_default_unimap);
571
572int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
573{
574	struct uni_pagedir *q;
575
576	if (!*src_vc->vc_uni_pagedir_loc)
577		return -EINVAL;
578	if (*dst_vc->vc_uni_pagedir_loc == *src_vc->vc_uni_pagedir_loc)
579		return 0;
580	con_free_unimap(dst_vc);
581	q = (struct uni_pagedir *)*src_vc->vc_uni_pagedir_loc;
582	q->refcount++;
583	*dst_vc->vc_uni_pagedir_loc = (long)q;
584	return 0;
585}
586
587int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list)
588{
589	int i, j, k, ect;
590	u16 **p1, *p2;
591	struct uni_pagedir *p;
592
593	ect = 0;
594	if (*vc->vc_uni_pagedir_loc) {
595		p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
596		for (i = 0; i < 32; i++)
597		if ((p1 = p->uni_pgdir[i]))
598			for (j = 0; j < 32; j++)
599			if ((p2 = *(p1++)))
600				for (k = 0; k < 64; k++) {
601					if (*p2 < MAX_GLYPH && ect++ < ct) {
602						__put_user((u_short)((i<<11)+(j<<6)+k),
603							   &list->unicode);
604						__put_user((u_short) *p2, 
605							   &list->fontpos);
606						list++;
607					}
608					p2++;
609				}
610	}
611	__put_user(ect, uct);
612	return ((ect <= ct) ? 0 : -ENOMEM);
613}
614
615void con_protect_unimap(struct vc_data *vc, int rdonly)
616{
617	struct uni_pagedir *p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
618	
619	if (p)
620		p->readonly = rdonly;
621}
622
623int
624conv_uni_to_pc(struct vc_data *conp, long ucs) 
625{
626	int h;
627	u16 **p1, *p2;
628	struct uni_pagedir *p;
629  
630	/* Only 16-bit codes supported at this time */
631	if (ucs > 0xffff)
632		ucs = 0xfffd;		/* U+FFFD: REPLACEMENT CHARACTER */
633	else if (ucs < 0x20 || ucs >= 0xfffe)
634		return -1;		/* Not a printable character */
635	else if (ucs == 0xfeff || (ucs >= 0x200a && ucs <= 0x200f))
636		return -2;			/* Zero-width space */
637	/*
638	 * UNI_DIRECT_BASE indicates the start of the region in the User Zone
639	 * which always has a 1:1 mapping to the currently loaded font.  The
640	 * UNI_DIRECT_MASK indicates the bit span of the region.
641	 */
642	else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
643		return ucs & UNI_DIRECT_MASK;
644  
645	if (!*conp->vc_uni_pagedir_loc)
646		return -3;
647
648	p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;  
649	if ((p1 = p->uni_pgdir[ucs >> 11]) &&
650	    (p2 = p1[(ucs >> 6) & 0x1f]) &&
651	    (h = p2[ucs & 0x3f]) < MAX_GLYPH)
652		return h;
653
654	return -4;		/* not found */
655}
656
657/*
658 * This is called at sys_setup time, after memory and the console are
659 * initialized.  It must be possible to call kmalloc(..., GFP_KERNEL)
660 * from this function, hence the call from sys_setup.
661 */
662void __init 
663console_map_init(void)
664{
665	int i;
666	
667	for (i = 0; i < MAX_NR_CONSOLES; i++)
668		if (vc_cons_allocated(i) && !*vc_cons[i].d->vc_uni_pagedir_loc)
669			con_set_default_unimap(vc_cons[i].d);
670}
671
672EXPORT_SYMBOL(con_copy_unimap);