OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [consolemap.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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/kd.h>
15
#include <linux/errno.h>
16
#include <linux/mm.h>
17
#include <linux/slab.h>
18
#include <linux/init.h>
19
#include <linux/tty.h>
20
#include <asm/uaccess.h>
21
#include <linux/consolemap.h>
22
#include <linux/console_struct.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, 0xf800,
77
    0xf801, 0x2500, 0xf803, 0xf804, 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
        int             readonly;
181
};
182
 
183
static struct uni_pagedir *dflt;
184
 
185
static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int i)
186
{
187
        int j, glyph;
188
        unsigned short *t = translations[i];
189
        unsigned char *q;
190
 
191
        if (!p) return;
192
        q = p->inverse_translations[i];
193
 
194
        if (!q) {
195
                q = p->inverse_translations[i] = (unsigned char *)
196
                        kmalloc(MAX_GLYPH, GFP_KERNEL);
197
                if (!q) return;
198
        }
199
        memset(q, 0, MAX_GLYPH);
200
 
201
        for (j = 0; j < E_TABSZ; j++) {
202
                glyph = conv_uni_to_pc(conp, t[j]);
203
                if (glyph >= 0 && glyph < MAX_GLYPH && q[glyph] < 32) {
204
                        /* prefer '-' above SHY etc. */
205
                        q[glyph] = j;
206
                }
207
        }
208
}
209
 
210
unsigned short *set_translate(int m,int currcons)
211
{
212
        inv_translate[currcons] = m;
213
        return translations[m];
214
}
215
 
216
/*
217
 * Inverse translation is impossible for several reasons:
218
 * 1. The font<->character maps are not 1-1.
219
 * 2. The text may have been written while a different translation map
220
 *    was active, or using Unicode.
221
 * Still, it is now possible to a certain extent to cut and paste non-ASCII.
222
 */
223
unsigned char inverse_translate(struct vc_data *conp, int glyph)
224
{
225
        struct uni_pagedir *p;
226
        if (glyph < 0 || glyph >= MAX_GLYPH)
227
                return 0;
228
        else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc) ||
229
                 !p->inverse_translations[inv_translate[conp->vc_num]])
230
                return glyph;
231
        else
232
                return p->inverse_translations[inv_translate[conp->vc_num]][glyph];
233
}
234
 
235
static void update_user_maps(void)
236
{
237
        int i;
238
        struct uni_pagedir *p, *q = NULL;
239
 
240
        for (i = 0; i < MAX_NR_CONSOLES; i++) {
241
                if (!vc_cons_allocated(i))
242
                        continue;
243
                p = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
244
                if (p && p != q) {
245
                        set_inverse_transl(vc_cons[i].d, p, USER_MAP);
246
                        q = p;
247
                }
248
        }
249
}
250
 
251
/*
252
 * Load customizable translation table
253
 * arg points to a 256 byte translation table.
254
 *
255
 * The "old" variants are for translation directly to font (using the
256
 * 0xf000-0xf0ff "transparent" Unicodes) whereas the "new" variants set
257
 * Unicodes explicitly.
258
 */
259
int con_set_trans_old(unsigned char * arg)
260
{
261
        int i;
262
        unsigned short *p = translations[USER_MAP];
263
 
264
        i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ);
265
        if (i)
266
                return i;
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
 
278
int con_get_trans_old(unsigned char * arg)
279
{
280
        int i, ch;
281
        unsigned short *p = translations[USER_MAP];
282
 
283
        i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ);
284
        if (i)
285
                return i;
286
 
287
        for (i=0; i<E_TABSZ ; i++)
288
          {
289
            ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
290
            __put_user((ch & ~0xff) ? 0 : ch, arg+i);
291
          }
292
        return 0;
293
}
294
 
295
int con_set_trans_new(ushort * arg)
296
{
297
        int i;
298
        unsigned short *p = translations[USER_MAP];
299
 
300
        i = verify_area(VERIFY_READ, (void *)arg,
301
                        E_TABSZ*sizeof(unsigned short));
302
        if (i)
303
                return i;
304
 
305
        for (i=0; i<E_TABSZ ; i++) {
306
                unsigned short us;
307
                __get_user(us, arg+i);
308
                p[i] = us;
309
        }
310
 
311
        update_user_maps();
312
        return 0;
313
}
314
 
315
int con_get_trans_new(ushort * arg)
316
{
317
        int i;
318
        unsigned short *p = translations[USER_MAP];
319
 
320
        i = verify_area(VERIFY_WRITE, (void *)arg,
321
                        E_TABSZ*sizeof(unsigned short));
322
        if (i)
323
                return i;
324
 
325
        for (i=0; i<E_TABSZ ; i++)
326
          __put_user(p[i], arg+i);
327
 
328
        return 0;
329
}
330
 
331
/*
332
 * Unicode -> current font conversion
333
 *
334
 * A font has at most 512 chars, usually 256.
335
 * But one font position may represent several Unicode chars.
336
 * A hashtable is somewhat of a pain to deal with, so use a
337
 * "paged table" instead.  Simulation has shown the memory cost of
338
 * this 3-level paged table scheme to be comparable to a hash table.
339
 */
340
 
341
extern u8 dfont_unicount[];     /* Defined in console_defmap.c */
342
extern u16 dfont_unitable[];
343
 
344
static void con_release_unimap(struct uni_pagedir *p)
345
{
346
        u16 **p1;
347
        int i, j;
348
 
349
        if (p == dflt) dflt = NULL;
350
        for (i = 0; i < 32; i++) {
351
                if ((p1 = p->uni_pgdir[i]) != NULL) {
352
                        for (j = 0; j < 32; j++)
353
                                if (p1[j])
354
                                        kfree(p1[j]);
355
                        kfree(p1);
356
                }
357
                p->uni_pgdir[i] = NULL;
358
        }
359
        for (i = 0; i < 4; i++)
360
                if (p->inverse_translations[i]) {
361
                        kfree(p->inverse_translations[i]);
362
                        p->inverse_translations[i] = NULL;
363
                }
364
}
365
 
366
void con_free_unimap(int con)
367
{
368
        struct uni_pagedir *p;
369
        struct vc_data *conp = vc_cons[con].d;
370
 
371
        p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
372
        if (!p) return;
373
        *conp->vc_uni_pagedir_loc = 0;
374
        if (--p->refcount) return;
375
        con_release_unimap(p);
376
        kfree(p);
377
}
378
 
379
static int con_unify_unimap(struct vc_data *conp, struct uni_pagedir *p)
380
{
381
        int i, j, k;
382
        struct uni_pagedir *q;
383
 
384
        for (i = 0; i < MAX_NR_CONSOLES; i++) {
385
                if (!vc_cons_allocated(i))
386
                        continue;
387
                q = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
388
                if (!q || q == p || q->sum != p->sum)
389
                        continue;
390
                for (j = 0; j < 32; j++) {
391
                        u16 **p1, **q1;
392
                        p1 = p->uni_pgdir[j]; q1 = q->uni_pgdir[j];
393
                        if (!p1 && !q1)
394
                                continue;
395
                        if (!p1 || !q1)
396
                                break;
397
                        for (k = 0; k < 32; k++) {
398
                                if (!p1[k] && !q1[k])
399
                                        continue;
400
                                if (!p1[k] || !q1[k])
401
                                        break;
402
                                if (memcmp(p1[k], q1[k], 64*sizeof(u16)))
403
                                        break;
404
                        }
405
                        if (k < 32)
406
                                break;
407
                }
408
                if (j == 32) {
409
                        q->refcount++;
410
                        *conp->vc_uni_pagedir_loc = (unsigned long)q;
411
                        con_release_unimap(p);
412
                        kfree(p);
413
                        return 1;
414
                }
415
        }
416
        return 0;
417
}
418
 
419
static int
420
con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
421
{
422
        int i, n;
423
        u16 **p1, *p2;
424
 
425
        if (!(p1 = p->uni_pgdir[n = unicode >> 11])) {
426
                p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);
427
                if (!p1) return -ENOMEM;
428
                for (i = 0; i < 32; i++)
429
                        p1[i] = NULL;
430
        }
431
 
432
        if (!(p2 = p1[n = (unicode >> 6) & 0x1f])) {
433
                p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
434
                if (!p2) return -ENOMEM;
435
                memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */
436
        }
437
 
438
        p2[unicode & 0x3f] = fontpos;
439
 
440
        p->sum += (fontpos << 20) + unicode;
441
 
442
        return 0;
443
}
444
 
445
/* ui is a leftover from using a hashtable, but might be used again */
446
int con_clear_unimap(int con, struct unimapinit *ui)
447
{
448
        struct uni_pagedir *p, *q;
449
        struct vc_data *conp = vc_cons[con].d;
450
 
451
        p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
452
        if (p && p->readonly) return -EIO;
453
        if (!p || --p->refcount) {
454
                q = (struct uni_pagedir *)kmalloc(sizeof(*p), GFP_KERNEL);
455
                if (!q) {
456
                        if (p) p->refcount++;
457
                        return -ENOMEM;
458
                }
459
                memset(q, 0, sizeof(*q));
460
                q->refcount=1;
461
                *conp->vc_uni_pagedir_loc = (unsigned long)q;
462
        } else {
463
                if (p == dflt) dflt = NULL;
464
                p->refcount++;
465
                p->sum = 0;
466
                con_release_unimap(p);
467
        }
468
        return 0;
469
}
470
 
471
int
472
con_set_unimap(int con, ushort ct, struct unipair *list)
473
{
474
        int err = 0, err1, i;
475
        struct uni_pagedir *p, *q;
476
        struct vc_data *conp = vc_cons[con].d;
477
 
478
        p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
479
        if (p->readonly) return -EIO;
480
 
481
        if (!ct) return 0;
482
 
483
        if (p->refcount > 1) {
484
                int j, k;
485
                u16 **p1, *p2, l;
486
 
487
                err1 = con_clear_unimap(con, NULL);
488
                if (err1) return err1;
489
 
490
                q = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
491
                for (i = 0, l = 0; i < 32; i++)
492
                if ((p1 = p->uni_pgdir[i]))
493
                        for (j = 0; j < 32; j++)
494
                        if ((p2 = p1[j]))
495
                                for (k = 0; k < 64; k++, l++)
496
                                if (p2[k] != 0xffff) {
497
                                        err1 = con_insert_unipair(q, l, p2[k]);
498
                                        if (err1) {
499
                                                p->refcount++;
500
                                                *conp->vc_uni_pagedir_loc = (unsigned long)p;
501
                                                con_release_unimap(q);
502
                                                kfree(q);
503
                                                return err1;
504
                                        }
505
                                }
506
                p = q;
507
        } else if (p == dflt)
508
                dflt = NULL;
509
 
510
        while (ct--) {
511
                unsigned short unicode, fontpos;
512
                __get_user(unicode, &list->unicode);
513
                __get_user(fontpos, &list->fontpos);
514
                if ((err1 = con_insert_unipair(p, unicode,fontpos)) != 0)
515
                        err = err1;
516
                        list++;
517
        }
518
 
519
        if (con_unify_unimap(conp, p))
520
                return err;
521
 
522
        for (i = 0; i <= 3; i++)
523
                set_inverse_transl(conp, p, i); /* Update all inverse translations */
524
 
525
        return err;
526
}
527
 
528
/* Loads the unimap for the hardware font, as defined in uni_hash.tbl.
529
   The representation used was the most compact I could come up
530
   with.  This routine is executed at sys_setup time, and when the
531
   PIO_FONTRESET ioctl is called. */
532
 
533
int
534
con_set_default_unimap(int con)
535
{
536
        int i, j, err = 0, err1;
537
        u16 *q;
538
        struct uni_pagedir *p;
539
        struct vc_data *conp = vc_cons[con].d;
540
 
541
        if (dflt) {
542
                p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
543
                if (p == dflt)
544
                        return 0;
545
                dflt->refcount++;
546
                *conp->vc_uni_pagedir_loc = (unsigned long)dflt;
547
                if (p && --p->refcount) {
548
                        con_release_unimap(p);
549
                        kfree(p);
550
                }
551
                return 0;
552
        }
553
 
554
        /* The default font is always 256 characters */
555
 
556
        err = con_clear_unimap(con,NULL);
557
        if (err) return err;
558
 
559
        p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
560
        q = dfont_unitable;
561
 
562
        for (i = 0; i < 256; i++)
563
                for (j = dfont_unicount[i]; j; j--) {
564
                        err1 = con_insert_unipair(p, *(q++), i);
565
                        if (err1)
566
                                err = err1;
567
                }
568
 
569
        if (con_unify_unimap(conp, p)) {
570
                dflt = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
571
                return err;
572
        }
573
 
574
        for (i = 0; i <= 3; i++)
575
                set_inverse_transl(conp, p, i); /* Update all inverse translations */
576
        dflt = p;
577
        return err;
578
}
579
 
580
int
581
con_copy_unimap(int dstcon, int srccon)
582
{
583
        struct vc_data *sconp = vc_cons[srccon].d;
584
        struct vc_data *dconp = vc_cons[dstcon].d;
585
        struct uni_pagedir *q;
586
 
587
        if (!vc_cons_allocated(srccon) || !*sconp->vc_uni_pagedir_loc)
588
                return -EINVAL;
589
        if (*dconp->vc_uni_pagedir_loc == *sconp->vc_uni_pagedir_loc)
590
                return 0;
591
        con_free_unimap(dstcon);
592
        q = (struct uni_pagedir *)*sconp->vc_uni_pagedir_loc;
593
        q->refcount++;
594
        *dconp->vc_uni_pagedir_loc = (long)q;
595
        return 0;
596
}
597
 
598
int
599
con_get_unimap(int con, ushort ct, ushort *uct, struct unipair *list)
600
{
601
        int i, j, k, ect;
602
        u16 **p1, *p2;
603
        struct uni_pagedir *p;
604
        struct vc_data *conp = vc_cons[con].d;
605
 
606
        ect = 0;
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++)
612
                        if ((p2 = *(p1++)))
613
                                for (k = 0; k < 64; k++) {
614
                                        if (*p2 < MAX_GLYPH && ect++ < ct) {
615
                                                __put_user((u_short)((i<<11)+(j<<6)+k),
616
                                                           &list->unicode);
617
                                                __put_user((u_short) *p2,
618
                                                           &list->fontpos);
619
                                                list++;
620
                                        }
621
                                        p2++;
622
                                }
623
        }
624
        __put_user(ect, uct);
625
        return ((ect <= ct) ? 0 : -ENOMEM);
626
}
627
 
628
void con_protect_unimap(int con, int rdonly)
629
{
630
        struct uni_pagedir *p = (struct uni_pagedir *)
631
                *vc_cons[con].d->vc_uni_pagedir_loc;
632
 
633
        if (p) p->readonly = rdonly;
634
}
635
 
636
int
637
conv_uni_to_pc(struct vc_data *conp, long ucs)
638
{
639
        int h;
640
        u16 **p1, *p2;
641
        struct uni_pagedir *p;
642
 
643
        /* Only 16-bit codes supported at this time */
644
        if (ucs > 0xffff)
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 */
650
        /*
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.
654
         */
655
        else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
656
                return ucs & UNI_DIRECT_MASK;
657
 
658
        if (!*conp->vc_uni_pagedir_loc)
659
                return -3;
660
 
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)
665
                return h;
666
 
667
        return -4;              /* not found */
668
}
669
 
670
/*
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.
674
 */
675
void __init
676
console_map_init(void)
677
{
678
        int i;
679
 
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);
683
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.