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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [char/] [consolemap.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
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/module.h>
15
#include <linux/kd.h>
16
#include <linux/errno.h>
17
#include <linux/mm.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>
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, 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
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
        u16             *inverse_trans_unicode;
181
        int             readonly;
182
};
183
 
184
static struct uni_pagedir *dflt;
185
 
186
static 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
 
211
static void set_inverse_trans_unicode(struct vc_data *conp,
212
                                      struct uni_pagedir *p)
213
{
214
        int i, j, k, glyph;
215
        u16 **p1, *p2;
216
        u16 *q;
217
 
218
        if (!p) return;
219
        q = p->inverse_trans_unicode;
220
        if (!q) {
221
                q = p->inverse_trans_unicode =
222
                        kmalloc(MAX_GLYPH * sizeof(u16), GFP_KERNEL);
223
                if (!q)
224
                        return;
225
        }
226
        memset(q, 0, MAX_GLYPH * sizeof(u16));
227
 
228
        for (i = 0; i < 32; i++) {
229
                p1 = p->uni_pgdir[i];
230
                if (!p1)
231
                        continue;
232
                for (j = 0; j < 32; j++) {
233
                        p2 = p1[j];
234
                        if (!p2)
235
                                continue;
236
                        for (k = 0; k < 64; k++) {
237
                                glyph = p2[k];
238
                                if (glyph >= 0 && glyph < MAX_GLYPH
239
                                               && q[glyph] < 32)
240
                                        q[glyph] = (i << 11) + (j << 6) + k;
241
                        }
242
                }
243
        }
244
}
245
 
246
unsigned short *set_translate(int m, struct vc_data *vc)
247
{
248
        inv_translate[vc->vc_num] = m;
249
        return translations[m];
250
}
251
 
252
/*
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
256
 *    was active.
257
 * Still, it is now possible to a certain extent to cut and paste non-ASCII.
258
 */
259
u16 inverse_translate(struct vc_data *conp, int glyph, int use_unicode)
260
{
261
        struct uni_pagedir *p;
262
        int m;
263
        if (glyph < 0 || glyph >= MAX_GLYPH)
264
                return 0;
265
        else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc))
266
                return glyph;
267
        else if (use_unicode) {
268
                if (!p->inverse_trans_unicode)
269
                        return glyph;
270
                else
271
                        return p->inverse_trans_unicode[glyph];
272
        } else {
273
                m = inv_translate[conp->vc_num];
274
                if (!p->inverse_translations[m])
275
                        return glyph;
276
                else
277
                        return p->inverse_translations[m][glyph];
278
        }
279
}
280
 
281
static void update_user_maps(void)
282
{
283
        int i;
284
        struct uni_pagedir *p, *q = NULL;
285
 
286
        for (i = 0; i < MAX_NR_CONSOLES; i++) {
287
                if (!vc_cons_allocated(i))
288
                        continue;
289
                p = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
290
                if (p && p != q) {
291
                        set_inverse_transl(vc_cons[i].d, p, USER_MAP);
292
                        set_inverse_trans_unicode(vc_cons[i].d, p);
293
                        q = p;
294
                }
295
        }
296
}
297
 
298
/*
299
 * Load customizable translation table
300
 * arg points to a 256 byte translation table.
301
 *
302
 * The "old" variants are for translation directly to font (using the
303
 * 0xf000-0xf0ff "transparent" Unicodes) whereas the "new" variants set
304
 * Unicodes explicitly.
305
 */
306
int con_set_trans_old(unsigned char __user * arg)
307
{
308
        int i;
309
        unsigned short *p = translations[USER_MAP];
310
 
311
        if (!access_ok(VERIFY_READ, arg, E_TABSZ))
312
                return -EFAULT;
313
 
314
        for (i=0; i<E_TABSZ ; i++) {
315
                unsigned char uc;
316
                __get_user(uc, arg+i);
317
                p[i] = UNI_DIRECT_BASE | uc;
318
        }
319
 
320
        update_user_maps();
321
        return 0;
322
}
323
 
324
int con_get_trans_old(unsigned char __user * arg)
325
{
326
        int i, ch;
327
        unsigned short *p = translations[USER_MAP];
328
 
329
        if (!access_ok(VERIFY_WRITE, arg, E_TABSZ))
330
                return -EFAULT;
331
 
332
        for (i=0; i<E_TABSZ ; i++)
333
          {
334
            ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
335
            __put_user((ch & ~0xff) ? 0 : ch, arg+i);
336
          }
337
        return 0;
338
}
339
 
340
int con_set_trans_new(ushort __user * arg)
341
{
342
        int i;
343
        unsigned short *p = translations[USER_MAP];
344
 
345
        if (!access_ok(VERIFY_READ, arg, E_TABSZ*sizeof(unsigned short)))
346
                return -EFAULT;
347
 
348
        for (i=0; i<E_TABSZ ; i++) {
349
                unsigned short us;
350
                __get_user(us, arg+i);
351
                p[i] = us;
352
        }
353
 
354
        update_user_maps();
355
        return 0;
356
}
357
 
358
int con_get_trans_new(ushort __user * arg)
359
{
360
        int i;
361
        unsigned short *p = translations[USER_MAP];
362
 
363
        if (!access_ok(VERIFY_WRITE, arg, E_TABSZ*sizeof(unsigned short)))
364
                return -EFAULT;
365
 
366
        for (i=0; i<E_TABSZ ; i++)
367
          __put_user(p[i], arg+i);
368
 
369
        return 0;
370
}
371
 
372
/*
373
 * Unicode -> current font conversion
374
 *
375
 * A font has at most 512 chars, usually 256.
376
 * But one font position may represent several Unicode chars.
377
 * A hashtable is somewhat of a pain to deal with, so use a
378
 * "paged table" instead.  Simulation has shown the memory cost of
379
 * this 3-level paged table scheme to be comparable to a hash table.
380
 */
381
 
382
extern u8 dfont_unicount[];     /* Defined in console_defmap.c */
383
extern u16 dfont_unitable[];
384
 
385
static void con_release_unimap(struct uni_pagedir *p)
386
{
387
        u16 **p1;
388
        int i, j;
389
 
390
        if (p == dflt) dflt = NULL;
391
        for (i = 0; i < 32; i++) {
392
                if ((p1 = p->uni_pgdir[i]) != NULL) {
393
                        for (j = 0; j < 32; j++)
394
                                kfree(p1[j]);
395
                        kfree(p1);
396
                }
397
                p->uni_pgdir[i] = NULL;
398
        }
399
        for (i = 0; i < 4; i++) {
400
                kfree(p->inverse_translations[i]);
401
                p->inverse_translations[i] = NULL;
402
        }
403
        if (p->inverse_trans_unicode) {
404
                kfree(p->inverse_trans_unicode);
405
                p->inverse_trans_unicode = NULL;
406
        }
407
}
408
 
409
void con_free_unimap(struct vc_data *vc)
410
{
411
        struct uni_pagedir *p;
412
 
413
        p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
414
        if (!p)
415
                return;
416
        *vc->vc_uni_pagedir_loc = 0;
417
        if (--p->refcount)
418
                return;
419
        con_release_unimap(p);
420
        kfree(p);
421
}
422
 
423
static int con_unify_unimap(struct vc_data *conp, struct uni_pagedir *p)
424
{
425
        int i, j, k;
426
        struct uni_pagedir *q;
427
 
428
        for (i = 0; i < MAX_NR_CONSOLES; i++) {
429
                if (!vc_cons_allocated(i))
430
                        continue;
431
                q = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
432
                if (!q || q == p || q->sum != p->sum)
433
                        continue;
434
                for (j = 0; j < 32; j++) {
435
                        u16 **p1, **q1;
436
                        p1 = p->uni_pgdir[j]; q1 = q->uni_pgdir[j];
437
                        if (!p1 && !q1)
438
                                continue;
439
                        if (!p1 || !q1)
440
                                break;
441
                        for (k = 0; k < 32; k++) {
442
                                if (!p1[k] && !q1[k])
443
                                        continue;
444
                                if (!p1[k] || !q1[k])
445
                                        break;
446
                                if (memcmp(p1[k], q1[k], 64*sizeof(u16)))
447
                                        break;
448
                        }
449
                        if (k < 32)
450
                                break;
451
                }
452
                if (j == 32) {
453
                        q->refcount++;
454
                        *conp->vc_uni_pagedir_loc = (unsigned long)q;
455
                        con_release_unimap(p);
456
                        kfree(p);
457
                        return 1;
458
                }
459
        }
460
        return 0;
461
}
462
 
463
static int
464
con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
465
{
466
        int i, n;
467
        u16 **p1, *p2;
468
 
469
        if (!(p1 = p->uni_pgdir[n = unicode >> 11])) {
470
                p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);
471
                if (!p1) return -ENOMEM;
472
                for (i = 0; i < 32; i++)
473
                        p1[i] = NULL;
474
        }
475
 
476
        if (!(p2 = p1[n = (unicode >> 6) & 0x1f])) {
477
                p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
478
                if (!p2) return -ENOMEM;
479
                memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */
480
        }
481
 
482
        p2[unicode & 0x3f] = fontpos;
483
 
484
        p->sum += (fontpos << 20) + unicode;
485
 
486
        return 0;
487
}
488
 
489
/* ui is a leftover from using a hashtable, but might be used again */
490
int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
491
{
492
        struct uni_pagedir *p, *q;
493
 
494
        p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
495
        if (p && p->readonly) return -EIO;
496
        if (!p || --p->refcount) {
497
                q = kzalloc(sizeof(*p), GFP_KERNEL);
498
                if (!q) {
499
                        if (p) p->refcount++;
500
                        return -ENOMEM;
501
                }
502
                q->refcount=1;
503
                *vc->vc_uni_pagedir_loc = (unsigned long)q;
504
        } else {
505
                if (p == dflt) dflt = NULL;
506
                p->refcount++;
507
                p->sum = 0;
508
                con_release_unimap(p);
509
        }
510
        return 0;
511
}
512
 
513
int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
514
{
515
        int err = 0, err1, i;
516
        struct uni_pagedir *p, *q;
517
 
518
        p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
519
        if (p->readonly) return -EIO;
520
 
521
        if (!ct) return 0;
522
 
523
        if (p->refcount > 1) {
524
                int j, k;
525
                u16 **p1, *p2, l;
526
 
527
                err1 = con_clear_unimap(vc, NULL);
528
                if (err1) return err1;
529
 
530
                q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
531
                for (i = 0, l = 0; i < 32; i++)
532
                if ((p1 = p->uni_pgdir[i]))
533
                        for (j = 0; j < 32; j++)
534
                        if ((p2 = p1[j]))
535
                                for (k = 0; k < 64; k++, l++)
536
                                if (p2[k] != 0xffff) {
537
                                        err1 = con_insert_unipair(q, l, p2[k]);
538
                                        if (err1) {
539
                                                p->refcount++;
540
                                                *vc->vc_uni_pagedir_loc = (unsigned long)p;
541
                                                con_release_unimap(q);
542
                                                kfree(q);
543
                                                return err1;
544
                                        }
545
                                }
546
                p = q;
547
        } else if (p == dflt)
548
                dflt = NULL;
549
 
550
        while (ct--) {
551
                unsigned short unicode, fontpos;
552
                __get_user(unicode, &list->unicode);
553
                __get_user(fontpos, &list->fontpos);
554
                if ((err1 = con_insert_unipair(p, unicode,fontpos)) != 0)
555
                        err = err1;
556
                        list++;
557
        }
558
 
559
        if (con_unify_unimap(vc, p))
560
                return err;
561
 
562
        for (i = 0; i <= 3; i++)
563
                set_inverse_transl(vc, p, i); /* Update all inverse translations */
564
        set_inverse_trans_unicode(vc, p);
565
 
566
        return err;
567
}
568
 
569
/* Loads the unimap for the hardware font, as defined in uni_hash.tbl.
570
   The representation used was the most compact I could come up
571
   with.  This routine is executed at sys_setup time, and when the
572
   PIO_FONTRESET ioctl is called. */
573
 
574
int con_set_default_unimap(struct vc_data *vc)
575
{
576
        int i, j, err = 0, err1;
577
        u16 *q;
578
        struct uni_pagedir *p;
579
 
580
        if (dflt) {
581
                p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
582
                if (p == dflt)
583
                        return 0;
584
                dflt->refcount++;
585
                *vc->vc_uni_pagedir_loc = (unsigned long)dflt;
586
                if (p && --p->refcount) {
587
                        con_release_unimap(p);
588
                        kfree(p);
589
                }
590
                return 0;
591
        }
592
 
593
        /* The default font is always 256 characters */
594
 
595
        err = con_clear_unimap(vc, NULL);
596
        if (err) return err;
597
 
598
        p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
599
        q = dfont_unitable;
600
 
601
        for (i = 0; i < 256; i++)
602
                for (j = dfont_unicount[i]; j; j--) {
603
                        err1 = con_insert_unipair(p, *(q++), i);
604
                        if (err1)
605
                                err = err1;
606
                }
607
 
608
        if (con_unify_unimap(vc, p)) {
609
                dflt = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
610
                return err;
611
        }
612
 
613
        for (i = 0; i <= 3; i++)
614
                set_inverse_transl(vc, p, i);   /* Update all inverse translations */
615
        set_inverse_trans_unicode(vc, p);
616
        dflt = p;
617
        return err;
618
}
619
EXPORT_SYMBOL(con_set_default_unimap);
620
 
621
int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
622
{
623
        struct uni_pagedir *q;
624
 
625
        if (!*src_vc->vc_uni_pagedir_loc)
626
                return -EINVAL;
627
        if (*dst_vc->vc_uni_pagedir_loc == *src_vc->vc_uni_pagedir_loc)
628
                return 0;
629
        con_free_unimap(dst_vc);
630
        q = (struct uni_pagedir *)*src_vc->vc_uni_pagedir_loc;
631
        q->refcount++;
632
        *dst_vc->vc_uni_pagedir_loc = (long)q;
633
        return 0;
634
}
635
 
636
int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list)
637
{
638
        int i, j, k, ect;
639
        u16 **p1, *p2;
640
        struct uni_pagedir *p;
641
 
642
        ect = 0;
643
        if (*vc->vc_uni_pagedir_loc) {
644
                p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
645
                for (i = 0; i < 32; i++)
646
                if ((p1 = p->uni_pgdir[i]))
647
                        for (j = 0; j < 32; j++)
648
                        if ((p2 = *(p1++)))
649
                                for (k = 0; k < 64; k++) {
650
                                        if (*p2 < MAX_GLYPH && ect++ < ct) {
651
                                                __put_user((u_short)((i<<11)+(j<<6)+k),
652
                                                           &list->unicode);
653
                                                __put_user((u_short) *p2,
654
                                                           &list->fontpos);
655
                                                list++;
656
                                        }
657
                                        p2++;
658
                                }
659
        }
660
        __put_user(ect, uct);
661
        return ((ect <= ct) ? 0 : -ENOMEM);
662
}
663
 
664
void con_protect_unimap(struct vc_data *vc, int rdonly)
665
{
666
        struct uni_pagedir *p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
667
 
668
        if (p)
669
                p->readonly = rdonly;
670
}
671
 
672
/*
673
 * Always use USER_MAP. These functions are used by the keyboard,
674
 * which shouldn't be affected by G0/G1 switching, etc.
675
 * If the user map still contains default values, i.e. the
676
 * direct-to-font mapping, then assume user is using Latin1.
677
 */
678
/* may be called during an interrupt */
679
u32 conv_8bit_to_uni(unsigned char c)
680
{
681
        unsigned short uni = translations[USER_MAP][c];
682
        return uni == (0xf000 | c) ? c : uni;
683
}
684
 
685
int conv_uni_to_8bit(u32 uni)
686
{
687
        int c;
688
        for (c = 0; c < 0x100; c++)
689
                if (translations[USER_MAP][c] == uni ||
690
                   (translations[USER_MAP][c] == (c | 0xf000) && uni == c))
691
                        return c;
692
        return -1;
693
}
694
 
695
int
696
conv_uni_to_pc(struct vc_data *conp, long ucs)
697
{
698
        int h;
699
        u16 **p1, *p2;
700
        struct uni_pagedir *p;
701
 
702
        /* Only 16-bit codes supported at this time */
703
        if (ucs > 0xffff)
704
                return -4;              /* Not found */
705
        else if (ucs < 0x20)
706
                return -1;              /* Not a printable character */
707
        else if (ucs == 0xfeff || (ucs >= 0x200b && ucs <= 0x200f))
708
                return -2;                      /* Zero-width space */
709
        /*
710
         * UNI_DIRECT_BASE indicates the start of the region in the User Zone
711
         * which always has a 1:1 mapping to the currently loaded font.  The
712
         * UNI_DIRECT_MASK indicates the bit span of the region.
713
         */
714
        else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
715
                return ucs & UNI_DIRECT_MASK;
716
 
717
        if (!*conp->vc_uni_pagedir_loc)
718
                return -3;
719
 
720
        p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
721
        if ((p1 = p->uni_pgdir[ucs >> 11]) &&
722
            (p2 = p1[(ucs >> 6) & 0x1f]) &&
723
            (h = p2[ucs & 0x3f]) < MAX_GLYPH)
724
                return h;
725
 
726
        return -4;              /* not found */
727
}
728
 
729
/*
730
 * This is called at sys_setup time, after memory and the console are
731
 * initialized.  It must be possible to call kmalloc(..., GFP_KERNEL)
732
 * from this function, hence the call from sys_setup.
733
 */
734
void __init
735
console_map_init(void)
736
{
737
        int i;
738
 
739
        for (i = 0; i < MAX_NR_CONSOLES; i++)
740
                if (vc_cons_allocated(i) && !*vc_cons[i].d->vc_uni_pagedir_loc)
741
                        con_set_default_unimap(vc_cons[i].d);
742
}
743
 
744
EXPORT_SYMBOL(con_copy_unimap);

powered by: WebSVN 2.1.0

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