~ubuntu-branches/ubuntu/lucid/linux-qcm-msm/lucid

« back to all changes in this revision

Viewing changes to drivers/video/console/promcon.c

  • Committer: Bazaar Package Importer
  • Author(s): Andy Whitcroft, Andy Whitcroft, Ubuntu: 2.6.31-21.59, Ubuntu: 2.6.31-20.58
  • Date: 2010-03-31 18:43:39 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100331184339-q3ee013jxywlf5ln
Tags: 2.6.31-800.2
[ Andy Whitcroft ]

* getabis -- get the correct source package
* rebase to Ubuntu-2.6.31-21.59

[ Ubuntu: 2.6.31-21.59 ]

* [Config] generic-pae switch to M586TSC
  - LP: #519448
* (pre-stable) drm/i915: Increase fb alignment to 64k
  - LP: #404064
* Input: i8042 - bypass AUX IRQ delivery test on laptops
  - LP: #534448
* SAUCE: Fix volume hotkeys for Dell Studio 1557
  - LP: #465250
* SAUCE: aufs: Fix header files inclusion in debug.h
  - LP: #517151
* [Config] Enable all CGROUP configuration options
  - LP: #480739
* Revert "[Upstream] acerhdf: Limit modalias matching to supported
  boards"
  - LP: #509730
* [Config] ext3 defaults to ordered mode
  - LP: #510067
* [Config] Fix sub-flavours package conflicts
  - LP: #454827
* PCI/cardbus: Add a fixup hook and fix powerpc
  - LP: #455723
* fnctl: f_modown should call write_lock_irqsave/restore
  - LP: #519436
* ACPI: enable C2 and Turbo-mode on Nehalem notebooks on A/C
  - LP: #516325
* tg3: Add 57788, remove 57720
  - LP: #515390
* HID: ignore all recent SoundGraph iMON devices
  - LP: #488443
* Input: ALPS - add interleaved protocol support (Dell E6x00 series)
  - LP: #296610
* acerhdf: limit modalias matching to supported
  - LP: #509730
* ASoC: Do not write to invalid registers on the wm9712.
  - LP: #509730
* cifs: NULL out tcon, pSesInfo, and srvTcp pointers when chasing DFS
  referrals
  - LP: #509730
* clockevents: Prevent clockevent_devices list corruption on cpu hotplug
  - LP: #509730
* dma: at_hdmac: correct incompatible type for argument 1 of
  'spin_lock_bh'
  - LP: #509730
* drivers/net/usb: Correct code taking the size of a pointer
  - LP: #509730
* Libertas: fix buffer overflow in lbs_get_essid()
  - LP: #509730
* md: Fix unfortunate interaction with evms
  - LP: #509730
* pata_cmd64x: fix overclocking of UDMA0-2 modes
  - LP: #509730
* pata_hpt3x2n: fix clock turnaround
  - LP: #509730
* SCSI: fc class: fix fc_transport_init error handling
  - LP: #509730
* sound: sgio2audio/pdaudiocf/usb-audio: initialize PCM buffer
  - LP: #509730
* USB: emi62: fix crash when trying to load EMI 6|2 firmware
  - LP: #509730
* USB: Fix a bug on appledisplay.c regarding signedness
  - LP: #509730
* USB: musb: gadget_ep0: avoid SetupEnd interrupt
  - LP: #509730
* USB: option: support hi speed for modem Haier CE100
  - LP: #490068, #509730
* x86, cpuid: Add "volatile" to asm in native_cpuid()
  - LP: #509730
* e100: Use pci pool to work around GFP_ATOMIC order 5 memory allocation
  failure
  - LP: #509730
* e100: Fix broken cbs accounting due to missing memset.
  - LP: #509730
* hostap: Revert a toxic part of the conversion to net_device_ops
  - LP: #509730
* hwmon: (fschmd) Fix check on unsigned in watchdog_write()
  - LP: #509730
* hwmon: (sht15) Off-by-one error in array index + incorrect constants
  - LP: #509730
* i2c/tsl2550: Fix lux value in extended mode
  - LP: #509730
* ipv6: reassembly: use seperate reassembly queues for conntrack and
  local delivery
  - LP: #509730
* S390: dasd: support DIAG access for read-only devices
  - LP: #509730
* udf: Try harder when looking for VAT inode
  - LP: #509730
* V4L/DVB (13596): ov511.c typo: lock => unlock
  - LP: #509730
* x86/ptrace: make genregs[32]_get/set more robust
  - LP: #509730
* XFS bug in log recover with quota (bugzilla id 855)
  - LP: #509730
* generic_permission: MAY_OPEN is not write access
  - LP: #509730
* memcg: avoid oom-killing innocent task in case of use_hierarchy
  - LP: #509730
* Input: atkbd - add force relese key quirk for Samsung R59P/R60P/R61P
  - LP: #253874, #509730
* Add unlocked version of inode_add_bytes() function
  - LP: #509730
* ext4: fix sleep inside spinlock issue with quota and dealloc (#14739)
  - LP: #509730
* Linux 2.6.31.10
  - LP: #509730
* Linux 2.6.31.11
  - LP: #509730
* quota: decouple fs reserved space from quota reservation
  - LP: #510674
* ext4: Convert to generic reserved quota's space management.
  - LP: #510674
* hwmon: (adt7462) Fix pin 28 monitoring
  - LP: #510674
* netfilter: nf_ct_ftp: fix out of bounds read in update_nl_seq()
  - LP: #510674
* quota: Fix dquot_transfer for filesystems different from ext4
  - LP: #510674
* fix braindamage in audit_tree.c untag_chunk()
  - LP: #510674
* fix more leaks in audit_tree.c tag_chunk()
  - LP: #510674
* ACPI: sleep: another HP DMI entry for init_set_sci_en_on_resume
  - LP: #453963, #510674
* ACPI: add DMI entry for SCI_EN resume quirk on HP dv4
  - LP: #453963, #510674
* ACPI: sleep: another HP/Compaq DMI entries for
  init_set_sci_en_on_resume
  - LP: #453963, #510674
* ACPI: DMI init_set_sci_en_on_resume for HP-Compaq C700
  - LP: #453963, #510674
* Linux 2.6.31.12
  - LP: #510674

[ Ubuntu: 2.6.31-20.58 ]

* Revert "[Upstream] e1000: enhance frame fragment detection"
  - CVE-2009-4536
* Revert "[Upstream] e1000e: enhance frame fragment detection"
  - CVE-2009-4538
* e1000: enhance frame fragment detection
  - CVE-2009-4536
* e1000/e1000e: don't use small hardware rx buffers
  - CVE-2009-4536
* e1000e: enhance frame fragment detection
  - CVE-2009-4538
* KVM: PIT: control word is write-only
  - CVE-2010-0309
* connector: Delete buggy notification code.
  - CVE-2010-0410
* Fix potential crash with sys_move_pages
  - CVE-2010-0415
* futex: Handle user space corruption gracefully
  - CVE-2010-0622
* futex_lock_pi() key refcnt fix
  - CVE-2010-0623
* Split 'flush_old_exec' into two functions
  - CVE-2010-0307
* Fix 'flush_old_exec()/setup_new_exec()' split
  - CVE-2010-0307
* x86: get rid of the insane TIF_ABI_PENDING bit
  - CVE-2010-0307
* powerpc: TIF_ABI_PENDING bit removal
  - CVE-2010-0307
* sparc: TIF_ABI_PENDING bit removal
  - CVE-2010-0307
* x86: set_personality_ia32() misses force_personality32
  - CVE-2010-0307

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: promcon.c,v 1.17 2000/07/26 23:02:52 davem Exp $
 
2
 * Console driver utilizing PROM sun terminal emulation
 
3
 *
 
4
 * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
 
5
 * Copyright (C) 1998  Jakub Jelinek  (jj@ultra.linux.cz)
 
6
 */
 
7
 
 
8
#include <linux/module.h>
 
9
#include <linux/kernel.h>
 
10
#include <linux/errno.h>
 
11
#include <linux/string.h>
 
12
#include <linux/mm.h>
 
13
#include <linux/slab.h>
 
14
#include <linux/delay.h>
 
15
#include <linux/console.h>
 
16
#include <linux/vt_kern.h>
 
17
#include <linux/selection.h>
 
18
#include <linux/fb.h>
 
19
#include <linux/init.h>
 
20
#include <linux/kd.h>
 
21
 
 
22
#include <asm/oplib.h>
 
23
#include <asm/uaccess.h>
 
24
 
 
25
static short pw = 80 - 1, ph = 34 - 1;
 
26
static short px, py;
 
27
static unsigned long promcon_uni_pagedir[2];
 
28
 
 
29
extern u8 promfont_unicount[];
 
30
extern u16 promfont_unitable[];
 
31
 
 
32
#define PROMCON_COLOR 0
 
33
 
 
34
#if PROMCON_COLOR
 
35
#define inverted(s)     ((((s) & 0x7700) == 0x0700) ? 0 : 1)
 
36
#else
 
37
#define inverted(s)     (((s) & 0x0800) ? 1 : 0)
 
38
#endif
 
39
 
 
40
static __inline__ void
 
41
promcon_puts(char *buf, int cnt)
 
42
{
 
43
        prom_printf("%*.*s", cnt, cnt, buf);
 
44
}
 
45
 
 
46
static int
 
47
promcon_start(struct vc_data *conp, char *b)
 
48
{
 
49
        unsigned short *s = (unsigned short *)
 
50
                        (conp->vc_origin + py * conp->vc_size_row + (px << 1));
 
51
        u16 cs;
 
52
 
 
53
        cs = scr_readw(s);
 
54
        if (px == pw) {
 
55
                unsigned short *t = s - 1;
 
56
                u16 ct = scr_readw(t);
 
57
 
 
58
                if (inverted(cs) && inverted(ct))
 
59
                        return sprintf(b, "\b\033[7m%c\b\033[@%c\033[m", cs,
 
60
                                       ct);
 
61
                else if (inverted(cs))
 
62
                        return sprintf(b, "\b\033[7m%c\033[m\b\033[@%c", cs,
 
63
                                       ct);
 
64
                else if (inverted(ct))
 
65
                        return sprintf(b, "\b%c\b\033[@\033[7m%c\033[m", cs,
 
66
                                       ct);
 
67
                else
 
68
                        return sprintf(b, "\b%c\b\033[@%c", cs, ct);
 
69
        }
 
70
 
 
71
        if (inverted(cs))
 
72
                return sprintf(b, "\033[7m%c\033[m\b", cs);
 
73
        else
 
74
                return sprintf(b, "%c\b", cs);
 
75
}
 
76
 
 
77
static int
 
78
promcon_end(struct vc_data *conp, char *b)
 
79
{
 
80
        unsigned short *s = (unsigned short *)
 
81
                        (conp->vc_origin + py * conp->vc_size_row + (px << 1));
 
82
        char *p = b;
 
83
        u16 cs;
 
84
 
 
85
        b += sprintf(b, "\033[%d;%dH", py + 1, px + 1);
 
86
 
 
87
        cs = scr_readw(s);
 
88
        if (px == pw) {
 
89
                unsigned short *t = s - 1;
 
90
                u16 ct = scr_readw(t);
 
91
 
 
92
                if (inverted(cs) && inverted(ct))
 
93
                        b += sprintf(b, "\b%c\b\033[@\033[7m%c\033[m", cs, ct);
 
94
                else if (inverted(cs))
 
95
                        b += sprintf(b, "\b%c\b\033[@%c", cs, ct);
 
96
                else if (inverted(ct))
 
97
                        b += sprintf(b, "\b\033[7m%c\b\033[@%c\033[m", cs, ct);
 
98
                else
 
99
                        b += sprintf(b, "\b\033[7m%c\033[m\b\033[@%c", cs, ct);
 
100
                return b - p;
 
101
        }
 
102
 
 
103
        if (inverted(cs))
 
104
                b += sprintf(b, "%c\b", cs);
 
105
        else
 
106
                b += sprintf(b, "\033[7m%c\033[m\b", cs);
 
107
        return b - p;
 
108
}
 
109
 
 
110
const char *promcon_startup(void)
 
111
{
 
112
        const char *display_desc = "PROM";
 
113
        int node;
 
114
        char buf[40];
 
115
        
 
116
        node = prom_getchild(prom_root_node);
 
117
        node = prom_searchsiblings(node, "options");
 
118
        if (prom_getproperty(node,  "screen-#columns", buf, 40) != -1) {
 
119
                pw = simple_strtoul(buf, NULL, 0);
 
120
                if (pw < 10 || pw > 256)
 
121
                        pw = 80;
 
122
                pw--;
 
123
        }
 
124
        if (prom_getproperty(node,  "screen-#rows", buf, 40) != -1) {
 
125
                ph = simple_strtoul(buf, NULL, 0);
 
126
                if (ph < 10 || ph > 256)
 
127
                        ph = 34;
 
128
                ph--;
 
129
        }
 
130
        promcon_puts("\033[H\033[J", 6);
 
131
        return display_desc;
 
132
}
 
133
 
 
134
static void
 
135
promcon_init_unimap(struct vc_data *conp)
 
136
{
 
137
        mm_segment_t old_fs = get_fs();
 
138
        struct unipair *p, *p1;
 
139
        u16 *q;
 
140
        int i, j, k;
 
141
        
 
142
        p = kmalloc(256*sizeof(struct unipair), GFP_KERNEL);
 
143
        if (!p) return;
 
144
        
 
145
        q = promfont_unitable;
 
146
        p1 = p;
 
147
        k = 0;
 
148
        for (i = 0; i < 256; i++)
 
149
                for (j = promfont_unicount[i]; j; j--) {
 
150
                        p1->unicode = *q++;
 
151
                        p1->fontpos = i;
 
152
                        p1++;
 
153
                        k++;
 
154
                }
 
155
        set_fs(KERNEL_DS);
 
156
        con_clear_unimap(conp, NULL);
 
157
        con_set_unimap(conp, k, p);
 
158
        con_protect_unimap(conp, 1);
 
159
        set_fs(old_fs);
 
160
        kfree(p);
 
161
}
 
162
 
 
163
static void
 
164
promcon_init(struct vc_data *conp, int init)
 
165
{
 
166
        unsigned long p;
 
167
        
 
168
        conp->vc_can_do_color = PROMCON_COLOR;
 
169
        if (init) {
 
170
                conp->vc_cols = pw + 1;
 
171
                conp->vc_rows = ph + 1;
 
172
        }
 
173
        p = *conp->vc_uni_pagedir_loc;
 
174
        if (conp->vc_uni_pagedir_loc == &conp->vc_uni_pagedir ||
 
175
            !--conp->vc_uni_pagedir_loc[1])
 
176
                con_free_unimap(conp);
 
177
        conp->vc_uni_pagedir_loc = promcon_uni_pagedir;
 
178
        promcon_uni_pagedir[1]++;
 
179
        if (!promcon_uni_pagedir[0] && p) {
 
180
                promcon_init_unimap(conp);
 
181
        }
 
182
        if (!init) {
 
183
                if (conp->vc_cols != pw + 1 || conp->vc_rows != ph + 1)
 
184
                        vc_resize(conp, pw + 1, ph + 1);
 
185
        }
 
186
}
 
187
 
 
188
static void
 
189
promcon_deinit(struct vc_data *conp)
 
190
{
 
191
        /* When closing the last console, reset video origin */
 
192
        if (!--promcon_uni_pagedir[1])
 
193
                con_free_unimap(conp);
 
194
        conp->vc_uni_pagedir_loc = &conp->vc_uni_pagedir;
 
195
        con_set_default_unimap(conp);
 
196
}
 
197
 
 
198
static int
 
199
promcon_switch(struct vc_data *conp)
 
200
{
 
201
        return 1;
 
202
}
 
203
 
 
204
static unsigned short *
 
205
promcon_repaint_line(unsigned short *s, unsigned char *buf, unsigned char **bp)
 
206
{
 
207
        int cnt = pw + 1;
 
208
        int attr = -1;
 
209
        unsigned char *b = *bp;
 
210
 
 
211
        while (cnt--) {
 
212
                u16 c = scr_readw(s);
 
213
                if (attr != inverted(c)) {
 
214
                        attr = inverted(c);
 
215
                        if (attr) {
 
216
                                strcpy (b, "\033[7m");
 
217
                                b += 4;
 
218
                        } else {
 
219
                                strcpy (b, "\033[m");
 
220
                                b += 3;
 
221
                        }
 
222
                }
 
223
                *b++ = c;
 
224
                s++;
 
225
                if (b - buf >= 224) {
 
226
                        promcon_puts(buf, b - buf);
 
227
                        b = buf;
 
228
                }
 
229
        }
 
230
        *bp = b;
 
231
        return s;
 
232
}
 
233
 
 
234
static void
 
235
promcon_putcs(struct vc_data *conp, const unsigned short *s,
 
236
              int count, int y, int x)
 
237
{
 
238
        unsigned char buf[256], *b = buf;
 
239
        unsigned short attr = scr_readw(s);
 
240
        unsigned char save;
 
241
        int i, last = 0;
 
242
 
 
243
        if (console_blanked)
 
244
                return;
 
245
        
 
246
        if (count <= 0)
 
247
                return;
 
248
 
 
249
        b += promcon_start(conp, b);
 
250
 
 
251
        if (x + count >= pw + 1) {
 
252
                if (count == 1) {
 
253
                        x -= 1;
 
254
                        save = scr_readw((unsigned short *)(conp->vc_origin
 
255
                                                   + y * conp->vc_size_row
 
256
                                                   + (x << 1)));
 
257
 
 
258
                        if (px != x || py != y) {
 
259
                                b += sprintf(b, "\033[%d;%dH", y + 1, x + 1);
 
260
                                px = x;
 
261
                                py = y;
 
262
                        }
 
263
 
 
264
                        if (inverted(attr))
 
265
                                b += sprintf(b, "\033[7m%c\033[m", scr_readw(s++));
 
266
                        else
 
267
                                b += sprintf(b, "%c", scr_readw(s++));
 
268
 
 
269
                        strcpy(b, "\b\033[@");
 
270
                        b += 4;
 
271
 
 
272
                        if (inverted(save))
 
273
                                b += sprintf(b, "\033[7m%c\033[m", save);
 
274
                        else
 
275
                                b += sprintf(b, "%c", save);
 
276
 
 
277
                        px++;
 
278
 
 
279
                        b += promcon_end(conp, b);
 
280
                        promcon_puts(buf, b - buf);
 
281
                        return;
 
282
                } else {
 
283
                        last = 1;
 
284
                        count = pw - x - 1;
 
285
                }
 
286
        }
 
287
 
 
288
        if (inverted(attr)) {
 
289
                strcpy(b, "\033[7m");
 
290
                b += 4;
 
291
        }
 
292
 
 
293
        if (px != x || py != y) {
 
294
                b += sprintf(b, "\033[%d;%dH", y + 1, x + 1);
 
295
                px = x;
 
296
                py = y;
 
297
        }
 
298
 
 
299
        for (i = 0; i < count; i++) {
 
300
                if (b - buf >= 224) {
 
301
                        promcon_puts(buf, b - buf);
 
302
                        b = buf;
 
303
                }
 
304
                *b++ = scr_readw(s++);
 
305
        }
 
306
 
 
307
        px += count;
 
308
 
 
309
        if (last) {
 
310
                save = scr_readw(s++);
 
311
                b += sprintf(b, "%c\b\033[@%c", scr_readw(s++), save);
 
312
                px++;
 
313
        }
 
314
 
 
315
        if (inverted(attr)) {
 
316
                strcpy(b, "\033[m");
 
317
                b += 3;
 
318
        }
 
319
 
 
320
        b += promcon_end(conp, b);
 
321
        promcon_puts(buf, b - buf);
 
322
}
 
323
 
 
324
static void
 
325
promcon_putc(struct vc_data *conp, int c, int y, int x)
 
326
{
 
327
        unsigned short s;
 
328
 
 
329
        if (console_blanked)
 
330
                return;
 
331
        
 
332
        scr_writew(c, &s);
 
333
        promcon_putcs(conp, &s, 1, y, x);
 
334
}
 
335
 
 
336
static void
 
337
promcon_clear(struct vc_data *conp, int sy, int sx, int height, int width)
 
338
{
 
339
        unsigned char buf[256], *b = buf;
 
340
        int i, j;
 
341
 
 
342
        if (console_blanked)
 
343
                return;
 
344
        
 
345
        b += promcon_start(conp, b);
 
346
 
 
347
        if (!sx && width == pw + 1) {
 
348
 
 
349
                if (!sy && height == ph + 1) {
 
350
                        strcpy(b, "\033[H\033[J");
 
351
                        b += 6;
 
352
                        b += promcon_end(conp, b);
 
353
                        promcon_puts(buf, b - buf);
 
354
                        return;
 
355
                } else if (sy + height == ph + 1) {
 
356
                        b += sprintf(b, "\033[%dH\033[J", sy + 1);
 
357
                        b += promcon_end(conp, b);
 
358
                        promcon_puts(buf, b - buf);
 
359
                        return;
 
360
                }
 
361
 
 
362
                b += sprintf(b, "\033[%dH", sy + 1);
 
363
                for (i = 1; i < height; i++) {
 
364
                        strcpy(b, "\033[K\n");
 
365
                        b += 4;
 
366
                }
 
367
 
 
368
                strcpy(b, "\033[K");
 
369
                b += 3;
 
370
 
 
371
                b += promcon_end(conp, b);
 
372
                promcon_puts(buf, b - buf);
 
373
                return;
 
374
 
 
375
        } else if (sx + width == pw + 1) {
 
376
 
 
377
                b += sprintf(b, "\033[%d;%dH", sy + 1, sx + 1);
 
378
                for (i = 1; i < height; i++) {
 
379
                        strcpy(b, "\033[K\n");
 
380
                        b += 4;
 
381
                }
 
382
 
 
383
                strcpy(b, "\033[K");
 
384
                b += 3;
 
385
 
 
386
                b += promcon_end(conp, b);
 
387
                promcon_puts(buf, b - buf);
 
388
                return;
 
389
        }
 
390
 
 
391
        for (i = sy + 1; i <= sy + height; i++) {
 
392
                b += sprintf(b, "\033[%d;%dH", i, sx + 1);
 
393
                for (j = 0; j < width; j++)
 
394
                        *b++ = ' ';
 
395
                if (b - buf + width >= 224) {
 
396
                        promcon_puts(buf, b - buf);
 
397
                        b = buf;
 
398
                }
 
399
        }
 
400
 
 
401
        b += promcon_end(conp, b);
 
402
        promcon_puts(buf, b - buf);
 
403
}
 
404
                        
 
405
static void
 
406
promcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
 
407
              int height, int width)
 
408
{
 
409
        char buf[256], *b = buf;
 
410
 
 
411
        if (console_blanked)
 
412
                return;
 
413
        
 
414
        b += promcon_start(conp, b);
 
415
        if (sy == dy && height == 1) {
 
416
                if (dx > sx && dx + width == conp->vc_cols)
 
417
                        b += sprintf(b, "\033[%d;%dH\033[%d@\033[%d;%dH",
 
418
                                     sy + 1, sx + 1, dx - sx, py + 1, px + 1);
 
419
                else if (dx < sx && sx + width == conp->vc_cols)
 
420
                        b += sprintf(b, "\033[%d;%dH\033[%dP\033[%d;%dH",
 
421
                                     dy + 1, dx + 1, sx - dx, py + 1, px + 1);
 
422
 
 
423
                b += promcon_end(conp, b);
 
424
                promcon_puts(buf, b - buf);
 
425
                return;
 
426
        }
 
427
 
 
428
        /*
 
429
         * FIXME: What to do here???
 
430
         * Current console.c should not call it like that ever.
 
431
         */
 
432
        prom_printf("\033[7mFIXME: bmove not handled\033[m\n");
 
433
}
 
434
 
 
435
static void
 
436
promcon_cursor(struct vc_data *conp, int mode)
 
437
{
 
438
        char buf[32], *b = buf;
 
439
 
 
440
        switch (mode) {
 
441
        case CM_ERASE:
 
442
                break;
 
443
 
 
444
        case CM_MOVE:
 
445
        case CM_DRAW:
 
446
                b += promcon_start(conp, b);
 
447
                if (px != conp->vc_x || py != conp->vc_y) {
 
448
                        px = conp->vc_x;
 
449
                        py = conp->vc_y;
 
450
                        b += sprintf(b, "\033[%d;%dH", py + 1, px + 1);
 
451
                }
 
452
                promcon_puts(buf, b - buf);
 
453
                break;
 
454
        }
 
455
}
 
456
 
 
457
static int
 
458
promcon_blank(struct vc_data *conp, int blank, int mode_switch)
 
459
{
 
460
        if (blank) {
 
461
                promcon_puts("\033[H\033[J\033[7m \033[m\b", 15);
 
462
                return 0;
 
463
        } else {
 
464
                /* Let console.c redraw */
 
465
                return 1;
 
466
        }
 
467
}
 
468
 
 
469
static int
 
470
promcon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
 
471
{
 
472
        unsigned char buf[256], *p = buf;
 
473
        unsigned short *s;
 
474
        int i;
 
475
 
 
476
        if (console_blanked)
 
477
                return 0;
 
478
        
 
479
        p += promcon_start(conp, p);
 
480
 
 
481
        switch (dir) {
 
482
        case SM_UP:
 
483
                if (b == ph + 1) {
 
484
                        p += sprintf(p, "\033[%dH\033[%dM", t + 1, count);
 
485
                        px = 0;
 
486
                        py = t;
 
487
                        p += promcon_end(conp, p);
 
488
                        promcon_puts(buf, p - buf);
 
489
                        break;
 
490
                }
 
491
 
 
492
                s = (unsigned short *)(conp->vc_origin
 
493
                                       + (t + count) * conp->vc_size_row);
 
494
 
 
495
                p += sprintf(p, "\033[%dH", t + 1);
 
496
 
 
497
                for (i = t; i < b - count; i++)
 
498
                        s = promcon_repaint_line(s, buf, &p);
 
499
 
 
500
                for (; i < b - 1; i++) {
 
501
                        strcpy(p, "\033[K\n");
 
502
                        p += 4;
 
503
                        if (p - buf >= 224) {
 
504
                                promcon_puts(buf, p - buf);
 
505
                                p = buf;
 
506
                        }
 
507
                }
 
508
 
 
509
                strcpy(p, "\033[K");
 
510
                p += 3;
 
511
 
 
512
                p += promcon_end(conp, p);
 
513
                promcon_puts(buf, p - buf);
 
514
                break;
 
515
 
 
516
        case SM_DOWN:
 
517
                if (b == ph + 1) {
 
518
                        p += sprintf(p, "\033[%dH\033[%dL", t + 1, count);
 
519
                        px = 0;
 
520
                        py = t;
 
521
                        p += promcon_end(conp, p);
 
522
                        promcon_puts(buf, p - buf);
 
523
                        break;
 
524
                }
 
525
 
 
526
                s = (unsigned short *)(conp->vc_origin + t * conp->vc_size_row);
 
527
 
 
528
                p += sprintf(p, "\033[%dH", t + 1);
 
529
 
 
530
                for (i = t; i < t + count; i++) {
 
531
                        strcpy(p, "\033[K\n");
 
532
                        p += 4;
 
533
                        if (p - buf >= 224) {
 
534
                                promcon_puts(buf, p - buf);
 
535
                                p = buf;
 
536
                        }
 
537
                }
 
538
 
 
539
                for (; i < b; i++)
 
540
                        s = promcon_repaint_line(s, buf, &p);
 
541
 
 
542
                p += promcon_end(conp, p);
 
543
                promcon_puts(buf, p - buf);
 
544
                break;
 
545
        }
 
546
 
 
547
        return 0;
 
548
}
 
549
 
 
550
#if !(PROMCON_COLOR)
 
551
static u8 promcon_build_attr(struct vc_data *conp, u8 _color, u8 _intensity,
 
552
    u8 _blink, u8 _underline, u8 _reverse, u8 _italic)
 
553
{
 
554
        return (_reverse) ? 0xf : 0x7;
 
555
}
 
556
#endif
 
557
 
 
558
/*
 
559
 *  The console 'switch' structure for the VGA based console
 
560
 */
 
561
 
 
562
static int promcon_dummy(void)
 
563
{
 
564
        return 0;
 
565
}
 
566
 
 
567
#define DUMMY (void *) promcon_dummy
 
568
 
 
569
const struct consw prom_con = {
 
570
        .owner =                THIS_MODULE,
 
571
        .con_startup =          promcon_startup,
 
572
        .con_init =             promcon_init,
 
573
        .con_deinit =           promcon_deinit,
 
574
        .con_clear =            promcon_clear,
 
575
        .con_putc =             promcon_putc,
 
576
        .con_putcs =            promcon_putcs,
 
577
        .con_cursor =           promcon_cursor,
 
578
        .con_scroll =           promcon_scroll,
 
579
        .con_bmove =            promcon_bmove,
 
580
        .con_switch =           promcon_switch,
 
581
        .con_blank =            promcon_blank,
 
582
        .con_set_palette =      DUMMY,
 
583
        .con_scrolldelta =      DUMMY,
 
584
#if !(PROMCON_COLOR)
 
585
        .con_build_attr =       promcon_build_attr,
 
586
#endif
 
587
};
 
588
 
 
589
void __init prom_con_init(void)
 
590
{
 
591
#ifdef CONFIG_DUMMY_CONSOLE
 
592
        if (conswitchp == &dummy_con)
 
593
                take_over_console(&prom_con, 0, MAX_NR_CONSOLES-1, 1);
 
594
        else
 
595
#endif
 
596
        if (conswitchp == &prom_con)
 
597
                promcon_init_unimap(vc_cons[fg_console].d);
 
598
}