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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [m68k/] [console/] [fbcon.c] - Blame information for rev 1623

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1623 jcastillo
/*
2
 * linux/arch/m68k/console/fbcon.c -- Low level frame buffer based console
3
 *                                    driver
4
 *
5
 *    Copyright (C) 1995 Geert Uytterhoeven
6
 *
7
 *
8
 * This file is based on the original Amiga console driver (amicon.c):
9
 *
10
 *    Copyright (C) 1993 Hamish Macdonald
11
 *                       Greg Harp
12
 *    Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk]
13
 *
14
 *          with work by William Rucklidge (wjr@cs.cornell.edu)
15
 *                       Geert Uytterhoeven
16
 *                       Jes Sorensen (jds@kom.auc.dk)
17
 *                       Martin Apel
18
 *
19
 * and on the original Atari console driver (atacon.c):
20
 *
21
 *    Copyright (C) 1993 Bjoern Brauel
22
 *                       Roman Hodek
23
 *
24
 *          with work by Guenther Kelleter
25
 *                       Martin Schaller
26
 *                       Andreas Schwab
27
 *
28
 *
29
 * This file is subject to the terms and conditions of the GNU General Public
30
 * License.  See the file COPYING in the main directory of this archive
31
 * for more details.
32
 */
33
 
34
/*
35
 * To do:
36
 *  - Implement 16 plane mode.
37
 *  - Add support for 16/24/32 bit packed pixels
38
 *  - Hardware cursor
39
 */
40
 
41
 
42
#include <linux/types.h>
43
#include <linux/fs.h>
44
#include <linux/kernel.h>
45
#include <linux/tty.h>
46
#include <linux/console.h>
47
#include <linux/string.h>
48
#include <linux/config.h>
49
#include <linux/kd.h>
50
#include <linux/malloc.h>
51
 
52
#include <asm/bootinfo.h>
53
#include <asm/irq.h>
54
#ifdef CONFIG_AMIGA
55
#include <asm/amigahw.h>
56
#include <asm/amigaints.h>
57
#endif /* CONFIG_AMIGA */
58
#ifdef CONFIG_ATARI
59
#include <asm/atariints.h>
60
#endif
61
#ifdef CONFIG_FB_CYBER
62
#include "../amiga/s3blit.h"
63
#endif /* CONFIG_FB_CYBER */
64
#include <linux/fb.h>
65
#include <asm/font.h>
66
#include <asm/machdep.h>
67
 
68
#include <asm/system.h>
69
 
70
#include "../../../drivers/char/vt_kern.h"   /* vt_cons and vc_resize_con() */
71
 
72
 
73
/* Import console_blanked from console.c */
74
 
75
extern int console_blanked;
76
 
77
 
78
   /*
79
    *    The following symbols select what modes are supported. They should
80
    *    be settable by the user ("make config") later.
81
    */
82
 
83
/* Clear all definitions */
84
 
85
#undef CONFIG_FBCON_MONO
86
#undef CONFIG_FBCON_ILBM
87
#undef CONFIG_FBCON_PLANES
88
#undef CONFIG_FBCON_2PLANE
89
#undef CONFIG_FBCON_4PLANE
90
#undef CONFIG_FBCON_8PLANE
91
#undef CONFIG_FBCON_8PACKED
92
#undef CONFIG_FBCON_16PACKED
93
#undef CONFIG_FBCON_24PACKED
94
#undef CONFIG_FBCON_32PACKED
95
#undef CONFIG_FBCON_CYBER
96
 
97
 
98
/* Monochrome is default */
99
 
100
#define CONFIG_FBCON_MONO
101
 
102
/* Amiga support */
103
 
104
#ifdef CONFIG_AMIGA
105
#ifndef CONFIG_FBCON_ILBM
106
#define CONFIG_FBCON_ILBM
107
#endif
108
#ifndef CONFIG_FBCON_PLANES
109
#define CONFIG_FBCON_PLANES
110
#endif
111
 
112
/* Cybervision Graphics Board */
113
 
114
#ifdef CONFIG_FB_CYBER
115
#ifndef CONFIG_FBCON_CYBER
116
#define CONFIG_FBCON_CYBER
117
#endif
118
#endif /* CONFIG_FB_CYBER */
119
 
120
#endif /* CONFIG_AMIGA */
121
 
122
/* Atari support */
123
 
124
#ifdef CONFIG_ATARI
125
#ifndef CONFIG_FBCON_2PLANE
126
#define CONFIG_FBCON_2PLANE
127
#endif
128
#ifndef CONFIG_FBCON_4PLANE
129
#define CONFIG_FBCON_4PLANE
130
#endif
131
#ifndef CONFIG_FBCON_8PLANE
132
#define CONFIG_FBCON_8PLANE
133
#endif
134
#ifndef CONFIG_FBCON_8PACKED
135
#define CONFIG_FBCON_8PACKED
136
#endif
137
#ifndef CONFIG_FBCON_16PACKED
138
#define CONFIG_FBCON_16PACKED
139
#endif
140
#endif /* CONFIG_ATARI */
141
 
142
 
143
/* Extra definitions to make the code more readable */
144
 
145
#if defined(CONFIG_FBCON_2PLANE) || defined(CONFIG_FBCON_4PLANE) || \
146
    defined(CONFIG_FBCON_8PLANE)
147
#define CONFIG_FBCON_IPLAN2
148
#else
149
#undef CONFIG_FBCON_IPLAN2
150
#endif
151
 
152
#if defined(CONFIG_FBCON_CYBER) || defined(CONFIG_FBCON_8PACKED) || \
153
    defined(CONFIG_FBCON_16PACKED) || defined(CONFIG_FBCON_24PACKED) || \
154
    defined(CONFIG_FBCON_32PACKED)
155
#define CONFIG_FBCON_PACKED
156
#else
157
#undef CONFIG_FBCON_PACKED
158
#endif
159
 
160
 
161
struct fb_info *fb_info;
162
struct display *disp;
163
 
164
 
165
/* ++Geert: Sorry, no hardware cursor support at the moment;
166
   use Atari alike software cursor */
167
 
168
static int cursor_drawn = 0;
169
 
170
#define CURSOR_DRAW_DELAY           (2)
171
 
172
/* # VBL ints between cursor state changes */
173
#define AMIGA_CURSOR_BLINK_RATE   (20)
174
#define ATARI_CURSOR_BLINK_RATE   (42)
175
 
176
static int vbl_cursor_cnt = 0;
177
static int cursor_on = 0;
178
static int cursor_blink_rate;
179
 
180
static __inline__ int CURSOR_UNDRAWN(void)
181
{
182
   int cursor_was_drawn;
183
   vbl_cursor_cnt = 0;
184
   cursor_was_drawn = cursor_drawn;
185
   cursor_drawn = 0;
186
   return(cursor_was_drawn);
187
}
188
 
189
   /*
190
    *    Attribute Decoding
191
    */
192
 
193
/* Color */
194
#define attr_fgcol(p,conp)    \
195
        (((conp)->vc_attr >> ((p)->inverse ? 4 : 0)) & 0x0f)
196
#define attr_bgcol(p,conp)    \
197
        (((conp)->vc_attr >> ((p)->inverse ? 0 : 4)) & 0x0f)
198
#define attr_bgcol_ec(p,conp) \
199
        (((conp)->vc_video_erase_char >> ((p)->inverse ? 8 : 12)) & 0x0f)
200
 
201
/* Monochrome */
202
#define attr_bold(p,conp)     \
203
        (((conp)->vc_attr & 3) == 2)
204
#define attr_reverse(p,conp)  \
205
        (((conp)->vc_attr & 8) ^ ((p)->inverse ? 8 : 0))
206
#define attr_underline(p,conp) \
207
        (((conp)->vc_attr) & 4)
208
 
209
 
210
   /*
211
    *    Scroll Method
212
    */
213
 
214
#define SCROLL_YWRAP          (0)
215
#define SCROLL_YPAN           (1)
216
#define SCROLL_YMOVE          (2)
217
 
218
#define divides(a, b)         ((!(a) || (b)%(a)) ? 0 : 1)
219
 
220
 
221
   /*
222
    *    Interface used by the world
223
    */
224
 
225
static u_long fbcon_startup(u_long kmem_start, char **display_desc);
226
static void fbcon_init(struct vc_data *conp);
227
static int fbcon_deinit(struct vc_data *conp);
228
static int fbcon_changevar(int con);
229
static int fbcon_clear(struct vc_data *conp, int sy, int sx, int height,
230
                       int width);
231
static int fbcon_putc(struct vc_data *conp, int c, int y, int x);
232
static int fbcon_putcs(struct vc_data *conp, const char *s, int count, int y,
233
                       int x);
234
static int fbcon_cursor(struct vc_data *conp, int mode);
235
static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, int count);
236
static int fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
237
                       int height, int width);
238
static int fbcon_switch(struct vc_data *conp);
239
static int fbcon_blank(int blank);
240
 
241
 
242
   /*
243
    *    Internal routines
244
    */
245
 
246
static void fbcon_setup(int con, int setcol, int cls);
247
static __inline__ void *mymemclear_small(void *s, size_t count);
248
static __inline__ void *mymemclear(void *s, size_t count);
249
static __inline__ void *mymemset(void *s, size_t count);
250
static __inline__ void *mymemmove(void *d, void *s, size_t count);
251
static __inline__ void fast_memmove(char *dst, char *src, size_t size);
252
static __inline__ void memclear_4p_col(void *d, size_t h, u_long val, int bpr);
253
static __inline__ void memset_even_4p(void *d, size_t count, u_long val1,
254
                                      u_long val2);
255
static __inline__ void memmove_4p_col(void *d, void *s, int h, int bpr);
256
static __inline__ u_long expand4l(u_char c);
257
static __inline__ void expand4dl(u_char c, u_long *ret1, u_long *ret2);
258
static __inline__ u_long dup4l(u_char c);
259
static __inline__ void memclear_8p_col(void *d, size_t h, u_long val1,
260
                                       u_long val2, int bpr);
261
static __inline__ void memset_even_8p(void *d, size_t count, u_long val1,
262
                                      u_long val2, u_long val3, u_long val4);
263
static __inline__ void memmove_8p_col(void *d, void *s, int h, int bpr);
264
static __inline__ void expand8dl(u_char c, u_long *ret1, u_long *ret2);
265
static __inline__ void memclear_2p_col(void *d, size_t h, u_short val, int bpr);
266
static __inline__ void memset_even_2p(void *d, size_t count, u_long val);
267
static __inline__ void memmove_2p_col(void *d, void *s, int h, int bpr);
268
static __inline__ u_short expand2w(u_char c);
269
static __inline__ u_long expand2l(u_char c);
270
static __inline__ u_short dup2w(u_char c);
271
static __inline__ int real_y(struct display *p, int y);
272
static void fbcon_vbl_handler(int irq, struct pt_regs *fp, void *dummy);
273
static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy, int dx,
274
                            int height, int width, u_int y_break);
275
 
276
 
277
   /*
278
    *    Monochrome
279
    */
280
 
281
#ifdef CONFIG_FBCON_MONO
282
static void bmove_mono(struct display *p, int sy, int sx, int dy, int dx,
283
                       int height, int width);
284
static void clear_mono(struct vc_data *conp, struct display *p, int sy, int sx,
285
                       int height, int width);
286
static void putc_mono(struct vc_data *conp, struct display *p, int c, int y,
287
                      int x);
288
static void putcs_mono(struct vc_data *conp, struct display *p, const char *s,
289
                       int count, int y, int x);
290
static void rev_char_mono(struct display *p, int x, int y);
291
#endif /* CONFIG_FBCON_MONO */
292
 
293
 
294
   /*
295
    *    Color Interleaved Planes
296
    */
297
 
298
#ifdef CONFIG_FBCON_ILBM
299
static void bmove_ilbm(struct display *p, int sy, int sx, int dy, int dx,
300
                       int height, int width);
301
static void clear_ilbm(struct vc_data *conp, struct display *p, int sy, int sx,
302
                       int height, int width);
303
static void putc_ilbm(struct vc_data *conp, struct display *p, int c, int y,
304
                      int x);
305
static void putcs_ilbm(struct vc_data *conp, struct display *p, const char *s,
306
                       int count, int y, int x);
307
static void rev_char_ilbm(struct display *p, int x, int y);
308
#endif /* CONFIG_FBCON_ILBM */
309
 
310
 
311
   /*
312
    *    Color Planes
313
    */
314
 
315
#ifdef CONFIG_FBCON_PLANES
316
static void bmove_plan(struct display *p, int sy, int sx, int dy, int dx,
317
                       int height, int width);
318
static void clear_plan(struct vc_data *conp, struct display *p, int sy, int sx,
319
                       int height, int width);
320
static void putc_plan(struct vc_data *conp, struct display *p, int c, int y,
321
                      int x);
322
static void putcs_plan(struct vc_data *conp, struct display *p, const char *s,
323
                       int count, int y, int x);
324
static void rev_char_plan(struct display *p, int x, int y);
325
#endif /* CONFIG_FBCON_PLANES */
326
 
327
 
328
   /*
329
    *    2 Planes (2-bytes interleave)
330
    */
331
 
332
#ifdef CONFIG_FBCON_2PLANE
333
static void bmove_2_plane(struct display *p, int sy, int sx, int dy, int dx,
334
                          int height, int width);
335
static void clear_2_plane(struct vc_data *conp, struct display *p, int sy,
336
                          int sx, int height, int width);
337
static void putc_2_plane(struct vc_data *conp, struct display *p, int c, int y,
338
                         int x);
339
static void putcs_2_plane(struct vc_data *conp, struct display *p,
340
                          const char *s, int count, int y, int x);
341
static void rev_char_2_plane(struct display *display, int x, int y);
342
#endif /* CONFIG_FBCON_2PLANE */
343
 
344
 
345
   /*
346
    *    4 Planes (2-bytes interleave)
347
    */
348
 
349
#ifdef CONFIG_FBCON_4PLANE
350
static void bmove_4_plane(struct display *p, int sy, int sx, int dy, int dx,
351
                          int height, int width);
352
static void clear_4_plane(struct vc_data *conp, struct display *p, int sy,
353
                          int sx, int height, int width);
354
static void putc_4_plane(struct vc_data *conp, struct display *p, int c, int y,
355
                         int x);
356
static void putcs_4_plane(struct vc_data *conp, struct display *p,
357
                          const char *s, int count, int y, int x);
358
static void rev_char_4_plane(struct display *p, int x, int y);
359
#endif /* CONFIG_FBCON_4PLANE */
360
 
361
 
362
   /*
363
    *    8 Planes (2-bytes interleave)
364
    */
365
 
366
#ifdef CONFIG_FBCON_8PLANE
367
static void bmove_8_plane(struct display *p, int sy, int sx, int dy, int dx,
368
                          int height, int width);
369
static void clear_8_plane(struct vc_data *conp, struct display *p, int sy,
370
                          int sx, int height, int width);
371
static void putc_8_plane(struct vc_data *conp, struct display *p, int c, int y,
372
                         int x);
373
static void putcs_8_plane(struct vc_data *conp, struct display *p,
374
                          const char *s, int count, int y, int x);
375
static void rev_char_8_plane(struct display *display, int x, int y);
376
#endif /* CONFIG_FBCON_8PLANE */
377
 
378
 
379
   /*
380
    *    8 bpp Packed Pixels
381
    */
382
 
383
#ifdef CONFIG_FBCON_8PACKED
384
static void bmove_8_packed(struct display *p, int sy, int sx, int dy, int dx,
385
                           int height, int width);
386
static void clear_8_packed(struct vc_data *conp, struct display *p, int sy,
387
                           int sx, int height, int width);
388
static void putc_8_packed(struct vc_data *conp, struct display *p, int c, int y,
389
                          int x);
390
static void putcs_8_packed(struct vc_data *conp, struct display *p,
391
                           const char *s, int count, int y, int x);
392
static void rev_char_8_packed(struct display *p, int x, int y);
393
#endif /* CONFIG_FBCON_8PACKED */
394
 
395
 
396
   /*
397
    *    16 bpp Packed Pixels
398
    */
399
 
400
#ifdef CONFIG_FBCON_16PACKED
401
static void bmove_16_packed(struct display *p, int sy, int sx, int dy, int dx,
402
                            int height, int width);
403
static void clear_16_packed(struct vc_data *conp, struct display *p, int sy,
404
                            int sx, int height, int width);
405
static void putc_16_packed(struct vc_data *conp, struct display *p, int c,
406
                           int y, int x);
407
static void putcs_16_packed(struct vc_data *conp, struct display *p,
408
                            const char *s, int count, int y, int x);
409
static void rev_char_16_packed(struct display *p, int x, int y);
410
#endif */ CONFIG_FBCON_8PACKED */
411
 
412
 
413
   /*
414
    *    Cybervision (accelerated)
415
    */
416
 
417
#ifdef CONFIG_FBCON_CYBER
418
static void bmove_cyber(struct display *p, int sy, int sx, int dy, int dx,
419
                        int height, int width);
420
static void clear_cyber(struct vc_data *conp, struct display *p, int sy, int sx,
421
                        int height, int width);
422
static void putc_cyber(struct vc_data *conp, struct display *p, int c, int y,
423
                       int x);
424
static void putcs_cyber(struct vc_data *conp, struct display *p, const char *s,
425
                        int count, int y, int x);
426
static void rev_char_cyber(struct display *p, int x, int y);
427
 
428
extern void Cyber_WaitQueue(u_short fifo);
429
extern void Cyber_WaitBlit(void);
430
extern void Cyber_BitBLT(u_short curx, u_short cury, u_short destx,
431
                         u_short desty, u_short width, u_short height,
432
                         u_short mode);
433
extern void Cyber_RectFill(u_short x, u_short y, u_short width, u_short height,
434
                           u_short mode, u_short color);
435
extern void Cyber_MoveCursor(u_short x, u_short y);
436
#endif /* CONFIG_FBCON_CYBER */
437
 
438
 
439
   /*
440
    *    `switch' for the Low Level Operations
441
    */
442
 
443
struct display_switch {
444
    void (*bmove)(struct display *p, int sy, int sx, int dy, int dx, int height,
445
                  int width);
446
    void (*clear)(struct vc_data *conp, struct display *p, int sy, int sx,
447
                  int height, int width);
448
    void (*putc)(struct vc_data *conp, struct display *p, int c, int y, int x);
449
    void (*putcs)(struct vc_data *conp, struct display *p, const char *s,
450
                  int count, int y, int x);
451
    void (*rev_char)(struct display *p, int x, int y);
452
};
453
 
454
 
455
#ifdef CONFIG_FBCON_MONO
456
struct display_switch dispsw_mono = {
457
   bmove_mono, clear_mono, putc_mono, putcs_mono, rev_char_mono
458
};
459
#endif /* CONFIG_FBCON_MONO */
460
 
461
#ifdef CONFIG_FBCON_ILBM
462
struct display_switch dispsw_ilbm = {
463
   bmove_ilbm, clear_ilbm, putc_ilbm, putcs_ilbm, rev_char_ilbm
464
};
465
#endif /* CONFIG_FBCON_ILBM */
466
 
467
#ifdef CONFIG_FBCON_PLANES
468
struct display_switch dispsw_plan = {
469
   bmove_plan, clear_plan, putc_plan, putcs_plan, rev_char_plan
470
};
471
#endif /* CONFIG_FBCON_PLANES */
472
 
473
#ifdef CONFIG_FBCON_2PLANE
474
struct display_switch dispsw_2_plane = {
475
   bmove_2_plane, clear_2_plane, putc_2_plane, putcs_2_plane, rev_char_2_plane
476
};
477
#endif /* CONFIG_FBCON_2PLANE */
478
 
479
#ifdef CONFIG_FBCON_4PLANE
480
struct display_switch dispsw_4_plane = {
481
   bmove_4_plane, clear_4_plane, putc_4_plane, putcs_4_plane, rev_char_4_plane
482
};
483
#endif /* CONFIG_FBCON_4PLANE */
484
 
485
#ifdef CONFIG_FBCON_8PLANE
486
struct display_switch dispsw_8_plane = {
487
   bmove_8_plane, clear_8_plane, putc_8_plane, putcs_8_plane, rev_char_8_plane
488
};
489
#endif /* CONFIG_FBCON_8PLANE */
490
 
491
#ifdef CONFIG_FBCON_8PACKED
492
struct display_switch dispsw_8_packed = {
493
   bmove_8_packed, clear_8_packed, putc_8_packed, putcs_8_packed, rev_char_8_packed
494
};
495
#endif /* CONFIG_FBCON_8PACKED */
496
 
497
#ifdef CONFIG_FBCON_16PACKED
498
struct display_switch dispsw_16_packed = {
499
   bmove_16_packed, clear_16_packed, putc_16_packed, putcs_16_packed,
500
   rev_char_16_packed
501
};
502
#endif /* CONFIG_FBCON_16PACKED */
503
 
504
#ifdef CONFIG_FBCON_CYBER
505
struct display_switch dispsw_cyber = {
506
   bmove_cyber, clear_cyber, putc_cyber, putcs_cyber, rev_char_cyber
507
};
508
#endif /* CONFIG_FBCON_CYBER */
509
 
510
 
511
static u_long fbcon_startup(u_long kmem_start, char **display_desc)
512
{
513
   int irqres = 0;
514
 
515
   fb_info = mach_fb_init(&kmem_start);
516
   disp = fb_info->disp;
517
   *display_desc = fb_info->modename;
518
   fb_info->changevar = &fbcon_changevar;
519
 
520
#ifdef CONFIG_AMIGA
521
   if (MACH_IS_AMIGA) {
522
      cursor_blink_rate = AMIGA_CURSOR_BLINK_RATE;
523
      irqres = add_isr(IRQ_AMIGA_VERTB, fbcon_vbl_handler, 0, NULL,
524
                       "console/cursor");
525
   }
526
#endif /* CONFIG_AMIGA */
527
#ifdef CONFIG_ATARI
528
   if (MACH_IS_ATARI) {
529
      cursor_blink_rate = ATARI_CURSOR_BLINK_RATE;
530
      irqres = add_isr(IRQ_AUTO_4, fbcon_vbl_handler, IRQ_TYPE_PRIO, NULL,
531
                       "console/cursor");
532
   }
533
#endif /* CONFIG_ATARI */
534
 
535
   if (!irqres)
536
      panic("fbcon_startup: Couldn't add vblank interrupt");
537
 
538
   return(kmem_start);
539
}
540
 
541
 
542
static void fbcon_init(struct vc_data *conp)
543
{
544
   int unit = conp->vc_num;
545
 
546
   if (unit)
547
      disp[unit] = disp[0];
548
   disp[unit].conp = conp;
549
   fbcon_setup(unit, 1, 0);
550
}
551
 
552
 
553
static int fbcon_deinit(struct vc_data *conp)
554
{
555
   disp[conp->vc_num].conp = 0;
556
   return(0);
557
}
558
 
559
 
560
static int fbcon_changevar(int con)
561
{
562
   fbcon_setup(con, 1, 1);
563
   return(0);
564
}
565
 
566
 
567
static void fbcon_setup(int con, int setcol, int cls)
568
{
569
   struct display *p = &disp[con];
570
   struct vc_data *conp = p->conp;
571
 
572
   p->var.xoffset = p->var.yoffset = p->yscroll = 0;  /* reset wrap/pan */
573
 
574
   if (!fb_info->fontname[0] ||
575
       !findsoftfont(fb_info->fontname, &p->fontwidth, &p->fontheight,
576
                     &p->fontdata) || p->fontwidth != 8)
577
           getdefaultfont(p->var.xres, p->var.yres, NULL, &p->fontwidth,
578
                          &p->fontheight, &p->fontdata);
579
   if (p->fontwidth != 8)
580
      panic("fbcon_setup: No support for fontwidth != 8");
581
 
582
   if (divides(p->ywrapstep, p->fontheight) && divides(p->fontheight, p->var.yres_virtual))
583
      p->scrollmode = SCROLL_YWRAP;
584
   else if (divides(p->ypanstep, p->fontheight) &&
585
            p->var.yres_virtual >= p->var.yres+p->fontheight)
586
      p->scrollmode = SCROLL_YPAN;
587
   else
588
      p->scrollmode = SCROLL_YMOVE;
589
 
590
   conp->vc_cols = p->var.xres/p->fontwidth;
591
   conp->vc_rows = p->var.yres/p->fontheight;
592
   p->vrows = p->var.yres_virtual/p->fontheight;
593
   conp->vc_can_do_color = p->var.bits_per_pixel != 1;
594
 
595
#ifdef CONFIG_FBCON_MONO
596
   if (p->var.bits_per_pixel == 1) {
597
      if (p->line_length)
598
         p->next_line = p->line_length;
599
      else
600
         p->next_line = p->var.xres_virtual>>3;
601
      p->next_plane = 0;
602
      p->dispsw = &dispsw_mono;
603
   } else
604
#endif /* CONFIG_FBCON_MONO */
605
#ifdef CONFIG_FBCON_IPLAN2
606
   if (p->type == FB_TYPE_INTERLEAVED_PLANES && p->type_aux == 2) {
607
      p->next_line = p->var.xres_virtual*p->var.bits_per_pixel>>3;
608
      p->next_plane = 0;
609
#ifdef CONFIG_FBCON_2PLANE
610
      if (p->var.bits_per_pixel == 2)
611
         p->dispsw = &dispsw_2_plane;
612
      else
613
#endif /* CONFIG_FBCON_2PLANE */
614
#ifdef CONFIG_FBCON_4PLANE
615
      if (p->var.bits_per_pixel == 4)
616
         p->dispsw = &dispsw_4_plane;
617
      else
618
#endif /* CONFIG_FBCON_4PLANE */
619
#ifdef CONFIG_FBCON_8PLANE
620
      if (p->var.bits_per_pixel == 8)
621
         p->dispsw = &dispsw_8_plane;
622
      else
623
#endif /* CONFIG_FBCON_8PLANE */
624
      goto fail;
625
   } else
626
#endif /* CONFIG_FBCON_IPLAN2 */
627
#ifdef CONFIG_FBCON_ILBM
628
   if (p->type == FB_TYPE_INTERLEAVED_PLANES && p->type_aux != 2) {
629
      if (p->line_length) {
630
         p->next_line = p->line_length*p->var.bits_per_pixel;
631
         p->next_plane = p->line_length;
632
      } else {
633
         p->next_line = p->type_aux;
634
         p->next_plane = p->type_aux/p->var.bits_per_pixel;
635
      }
636
      p->dispsw = &dispsw_ilbm;
637
   } else
638
#endif /* CONFIG_FBCON_ILBM */
639
#ifdef CONFIG_FBCON_PLANES
640
   if (p->type == FB_TYPE_PLANES) {
641
      if (p->line_length)
642
         p->next_line = p->line_length;
643
      else
644
         p->next_line = p->var.xres_virtual>>3;
645
      p->next_plane = p->var.yres_virtual*p->next_line;
646
      p->dispsw = &dispsw_plan;
647
   } else
648
#endif /* CONFIG_FBCON_PLANES */
649
#ifdef CONFIG_FBCON_PACKED
650
   if (p->type == FB_TYPE_PACKED_PIXELS) {
651
      p->next_line = p->var.xres_virtual*p->var.bits_per_pixel>>3;
652
      p->next_plane = 0;
653
#ifdef CONFIG_FBCON_CYBER
654
      if (p->var.accel == FB_ACCEL_CYBERVISION)
655
         p->dispsw = &dispsw_cyber;
656
      else
657
#endif /* CONFIG_FBCON_CYBER */
658
#ifdef CONFIG_FBCON_8PACKED
659
      if (p->var.bits_per_pixel == 8)
660
         p->dispsw = &dispsw_8_packed;
661
      else
662
#endif /* CONFIG_FBCON_8PACKED */
663
#ifdef CONFIG_FBCON_16PACKED
664
      if (p->var.bits_per_pixel == 16)
665
         p->dispsw = &dispsw_16_packed;
666
      else
667
#endif /* CONFIG_FBCON_16PACKED */
668
#ifdef CONFIG_FBCON_24PACKED
669
      if (p->var.bits_per_pixel == 24)
670
         p->dispsw = &dispsw_24_packed;
671
      else
672
#endif /* CONFIG_FBCON_24PACKED */
673
#ifdef CONFIG_FBCON_32PACKED
674
      if (p->var.bits_per_pixel == 32)
675
         p->dispsw = &dispsw_32_packed;
676
      else
677
#endif /* CONFIG_FBCON_32PACKED */
678
      goto fail;
679
   } else
680
#endif /* CONFIG_FBCON_PACKED */
681
   {
682
fail:
683
#ifdef CONFIG_FBCON_MONO
684
      printk("fbcon_setup: type %d (aux %d) not supported, trying mono\n",
685
             p->type, p->type_aux);
686
      if (p->line_length)
687
         p->next_line = p->line_length;
688
      else
689
         p->next_line = p->var.xres_virtual>>3;
690
      p->next_plane = 0;
691
      p->var.bits_per_pixel = 1;
692
      p->dispsw = &dispsw_mono;
693
#else /* CONFIG_FBCON_MONO */
694
      panic("fbcon_setup: no default driver");
695
#endif /* CONFIG_FBCON_MONO */
696
   }
697
 
698
   if (setcol) {
699
      p->fgcol = p->var.bits_per_pixel > 2 ? 7 : (1<<p->var.bits_per_pixel)-1;
700
      p->bgcol = 0;
701
   }
702
 
703
   if (cls)
704
      vc_resize_con(conp->vc_rows, conp->vc_cols, con);
705
}
706
 
707
 
708
/* ================================================================= */
709
/*                      Utility Assembler Functions                  */
710
/* ================================================================= */
711
 
712
 
713
/* ====================================================================== */
714
 
715
/* Those of a delicate disposition might like to skip the next couple of
716
 * pages.
717
 *
718
 * These functions are drop in replacements for memmove and
719
 * memset(_, 0, _). However their five instances add at least a kilobyte
720
 * to the object file. You have been warned.
721
 *
722
 * Not a great fan of assembler for the sake of it, but I think
723
 * that these routines are at least 10 times faster than their C
724
 * equivalents for large blits, and that's important to the lowest level of
725
 * a graphics driver. Question is whether some scheme with the blitter
726
 * would be faster. I suspect not for simple text system - not much
727
 * asynchrony.
728
 *
729
 * Code is very simple, just gruesome expansion. Basic strategy is to
730
 * increase data moved/cleared at each step to 16 bytes to reduce
731
 * instruction per data move overhead. movem might be faster still
732
 * For more than 15 bytes, we try to align the write direction on a
733
 * longword boundary to get maximum speed. This is even more gruesome.
734
 * Unaligned read/write used requires 68020+ - think this is a problem?
735
 *
736
 * Sorry!
737
 */
738
 
739
 
740
/* ++roman: I've optimized Robert's original versions in some minor
741
 * aspects, e.g. moveq instead of movel, let gcc choose the registers,
742
 * use movem in some places...
743
 * For other modes than 1 plane, lots of more such assembler functions
744
 * were needed (e.g. the ones using movep or expanding color values).
745
 */
746
 
747
/* ++andreas: more optimizations:
748
   subl #65536,d0 replaced by clrw d0; subql #1,d0 for dbcc
749
   addal is faster than addaw
750
   movep is rather expensive compared to ordinary move's
751
   some functions rewritten in C for clarity, no speed loss */
752
 
753
static __inline__ void *mymemclear_small(void *s, size_t count)
754
{
755
   if (!count)
756
      return(0);
757
 
758
   __asm__ __volatile__(
759
         "lsrl   #1,%1 ; jcc 1f ; moveb %2,%0@-\n\t"
760
      "1: lsrl   #1,%1 ; jcc 1f ; movew %2,%0@-\n\t"
761
      "1: lsrl   #1,%1 ; jcc 1f ; movel %2,%0@-\n\t"
762
      "1: lsrl   #1,%1 ; jcc 1f ; movel %2,%0@- ; movel %2,%0@-\n\t"
763
      "1: subql  #1,%1 ; jcs 3f\n\t"
764
      "2: moveml %2/%3/%4/%5,%0@-\n\t"
765
         "dbra %1,2b\n\t"
766
      "3:"
767
         : "=a" (s), "=d" (count)
768
         :  "d" (0), "d" (0), "d" (0), "d" (0),
769
            "0" ((char *)s+count), "1" (count)
770
  );
771
 
772
   return(0);
773
}
774
 
775
 
776
static __inline__ void *mymemclear(void *s, size_t count)
777
{
778
   if (!count)
779
      return(0);
780
 
781
   if (count < 16) {
782
      __asm__ __volatile__(
783
            "lsrl   #1,%1 ; jcc 1f ; clrb %0@+\n\t"
784
         "1: lsrl   #1,%1 ; jcc 1f ; clrw %0@+\n\t"
785
         "1: lsrl   #1,%1 ; jcc 1f ; clrl %0@+\n\t"
786
         "1: lsrl   #1,%1 ; jcc 1f ; clrl %0@+ ; clrl %0@+\n\t"
787
         "1:"
788
            : "=a" (s), "=d" (count)
789
            : "0" (s), "1" (count)
790
     );
791
   } else {
792
      long tmp;
793
      __asm__ __volatile__(
794
            "movel %1,%2\n\t"
795
            "lsrl   #1,%2 ; jcc 1f ; clrb %0@+ ; subqw #1,%1\n\t"
796
            "lsrl   #1,%2 ; jcs 2f\n\t"  /* %0 increased=>bit 2 switched*/
797
            "clrw   %0@+  ; subqw  #2,%1 ; jra 2f\n\t"
798
         "1: lsrl   #1,%2 ; jcc 2f\n\t"
799
            "clrw   %0@+  ; subqw  #2,%1\n\t"
800
         "2: movew %1,%2; lsrl #2,%1 ; jeq 6f\n\t"
801
            "lsrl   #1,%1 ; jcc 3f ; clrl %0@+\n\t"
802
         "3: lsrl   #1,%1 ; jcc 4f ; clrl %0@+ ; clrl %0@+\n\t"
803
         "4: subql  #1,%1 ; jcs 6f\n\t"
804
         "5: clrl %0@+; clrl %0@+ ; clrl %0@+ ; clrl %0@+\n\t"
805
            "dbra %1,5b   ; clrw %1; subql #1,%1; jcc 5b\n\t"
806
         "6: movew %2,%1; btst #1,%1 ; jeq 7f ; clrw %0@+\n\t"
807
         "7:            ; btst #0,%1 ; jeq 8f ; clrb %0@+\n\t"
808
         "8:"
809
            : "=a" (s), "=d" (count), "=d" (tmp)
810
            : "0" (s), "1" (count)
811
     );
812
   }
813
 
814
   return(0);
815
}
816
 
817
 
818
static __inline__ void *mymemset(void *s, size_t count)
819
{
820
   if (!count)
821
      return(0);
822
 
823
   __asm__ __volatile__(
824
         "lsrl   #1,%1 ; jcc 1f ; moveb %2,%0@-\n\t"
825
      "1: lsrl   #1,%1 ; jcc 1f ; movew %2,%0@-\n\t"
826
      "1: lsrl   #1,%1 ; jcc 1f ; movel %2,%0@-\n\t"
827
      "1: lsrl   #1,%1 ; jcc 1f ; movel %2,%0@- ; movel %2,%0@-\n\t"
828
      "1: subql  #1,%1 ; jcs 3f\n\t"
829
      "2: moveml %2/%3/%4/%5,%0@-\n\t"
830
         "dbra %1,2b\n\t"
831
      "3:"
832
         : "=a" (s), "=d" (count)
833
         :  "d" (-1), "d" (-1), "d" (-1), "d" (-1),
834
            "0" ((char *) s + count), "1" (count)
835
  );
836
 
837
   return(0);
838
}
839
 
840
 
841
static __inline__ void *mymemmove(void *d, void *s, size_t count)
842
{
843
   if (d < s) {
844
      if (count < 16) {
845
         __asm__ __volatile__(
846
               "lsrl   #1,%2 ; jcc 1f ; moveb %1@+,%0@+\n\t"
847
            "1: lsrl   #1,%2 ; jcc 1f ; movew %1@+,%0@+\n\t"
848
            "1: lsrl   #1,%2 ; jcc 1f ; movel %1@+,%0@+\n\t"
849
            "1: lsrl   #1,%2 ; jcc 1f ; movel %1@+,%0@+ ; movel %1@+,%0@+\n\t"
850
            "1:"
851
               : "=a" (d), "=a" (s), "=d" (count)
852
               : "0" (d), "1" (s), "2" (count)
853
        );
854
      } else {
855
         long tmp;
856
         __asm__ __volatile__(
857
               "movel  %0,%3\n\t"
858
               "lsrl   #1,%3 ; jcc 1f ; moveb %1@+,%0@+ ; subqw #1,%2\n\t"
859
               "lsrl   #1,%3 ; jcs 2f\n\t"  /* %0 increased=>bit 2 switched*/
860
               "movew  %1@+,%0@+  ; subqw  #2,%2 ; jra 2f\n\t"
861
            "1: lsrl   #1,%3 ; jcc 2f\n\t"
862
               "movew  %1@+,%0@+  ; subqw  #2,%2\n\t"
863
            "2: movew  %2,%-; lsrl #2,%2 ; jeq 6f\n\t"
864
               "lsrl   #1,%2 ; jcc 3f ; movel %1@+,%0@+\n\t"
865
            "3: lsrl   #1,%2 ; jcc 4f ; movel %1@+,%0@+ ; movel %1@+,%0@+\n\t"
866
            "4: subql  #1,%2 ; jcs 6f\n\t"
867
            "5: movel  %1@+,%0@+;movel %1@+,%0@+\n\t"
868
               "movel  %1@+,%0@+;movel %1@+,%0@+\n\t"
869
               "dbra   %2,5b ; clrw %2; subql #1,%2; jcc 5b\n\t"
870
            "6: movew  %+,%2; btst #1,%2 ; jeq 7f ; movew %1@+,%0@+\n\t"
871
            "7:              ; btst #0,%2 ; jeq 8f ; moveb %1@+,%0@+\n\t"
872
            "8:"
873
               : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
874
               : "0" (d), "1" (s), "2" (count)
875
        );
876
      }
877
   } else {
878
      if (count < 16) {
879
         __asm__ __volatile__(
880
               "lsrl   #1,%2 ; jcc 1f ; moveb %1@-,%0@-\n\t"
881
            "1: lsrl   #1,%2 ; jcc 1f ; movew %1@-,%0@-\n\t"
882
            "1: lsrl   #1,%2 ; jcc 1f ; movel %1@-,%0@-\n\t"
883
            "1: lsrl   #1,%2 ; jcc 1f ; movel %1@-,%0@- ; movel %1@-,%0@-\n\t"
884
            "1:"
885
               : "=a" (d), "=a" (s), "=d" (count)
886
               : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count)
887
        );
888
      } else {
889
         long tmp;
890
         __asm__ __volatile__(
891
               "movel %0,%3\n\t"
892
               "lsrl   #1,%3 ; jcc 1f ; moveb %1@-,%0@- ; subqw #1,%2\n\t"
893
               "lsrl   #1,%3 ; jcs 2f\n\t"  /* %0 increased=>bit 2 switched*/
894
               "movew  %1@-,%0@-  ; subqw  #2,%2 ; jra 2f\n\t"
895
            "1: lsrl   #1,%3 ; jcc 2f\n\t"
896
               "movew  %1@-,%0@-  ; subqw  #2,%2\n\t"
897
            "2: movew %2,%-; lsrl #2,%2 ; jeq 6f\n\t"
898
               "lsrl   #1,%2 ; jcc 3f ; movel %1@-,%0@-\n\t"
899
            "3: lsrl   #1,%2 ; jcc 4f ; movel %1@-,%0@- ; movel %1@-,%0@-\n\t"
900
            "4: subql  #1,%2 ; jcs 6f\n\t"
901
            "5: movel %1@-,%0@-;movel %1@-,%0@-\n\t"
902
               "movel %1@-,%0@-;movel %1@-,%0@-\n\t"
903
               "dbra %2,5b ; clrw %2; subql #1,%2; jcc 5b\n\t"
904
            "6: movew %+,%2; btst #1,%2 ; jeq 7f ; movew %1@-,%0@-\n\t"
905
            "7:              ; btst #0,%2 ; jeq 8f ; moveb %1@-,%0@-\n\t"
906
            "8:"
907
               : "=a" (d), "=a" (s), "=d" (count), "=d" (tmp)
908
               : "0" ((char *) d + count), "1" ((char *) s + count), "2" (count)
909
        );
910
      }
911
   }
912
 
913
   return(0);
914
}
915
 
916
 
917
/* ++andreas: Simple and fast version of memmove, assumes size is
918
   divisible by 16, suitable for moving the whole screen bitplane */
919
static __inline__ void fast_memmove(char *dst, char *src, size_t size)
920
{
921
  if (!size)
922
    return;
923
  if (dst < src)
924
    __asm__ __volatile__
925
      ("1:"
926
       "  moveml %0@+,%/d0/%/d1/%/a0/%/a1\n"
927
       "  moveml %/d0/%/d1/%/a0/%/a1,%1@\n"
928
       "  addql #8,%1; addql #8,%1\n"
929
       "  dbra %2,1b\n"
930
       "  clrw %2; subql #1,%2\n"
931
       "  jcc 1b"
932
       : "=a" (src), "=a" (dst), "=d" (size)
933
       : "0" (src), "1" (dst), "2" (size / 16 - 1)
934
       : "d0", "d1", "a0", "a1", "memory");
935
  else
936
    __asm__ __volatile__
937
      ("1:"
938
       "  subql #8,%0; subql #8,%0\n"
939
       "  moveml %0@,%/d0/%/d1/%/a0/%/a1\n"
940
       "  moveml %/d0/%/d1/%/a0/%/a1,%1@-\n"
941
       "  dbra %2,1b\n"
942
       "  clrw %2; subql #1,%2\n"
943
       "  jcc 1b"
944
       : "=a" (src), "=a" (dst), "=d" (size)
945
       : "0" (src + size), "1" (dst + size), "2" (size / 16 - 1)
946
       : "d0", "d1", "a0", "a1", "memory");
947
}
948
 
949
 
950
/* Sets the bytes in the visible column at d, height h, to the value
951
 * val for a 4 plane screen. The the bis of the color in 'color' are
952
 * moved (8 times) to the respective bytes. This means:
953
 *
954
 * for(h times; d += bpr)
955
 *   *d     = (color & 1) ? 0xff : 0;
956
 *   *(d+2) = (color & 2) ? 0xff : 0;
957
 *   *(d+4) = (color & 4) ? 0xff : 0;
958
 *   *(d+6) = (color & 8) ? 0xff : 0;
959
 */
960
 
961
static __inline__ void memclear_4p_col(void *d, size_t h, u_long val, int bpr)
962
{
963
        __asm__ __volatile__
964
                ("1: movepl %4,%0@(0)\n\t"
965
                  "addal  %5,%0\n\t"
966
                  "dbra   %1,1b"
967
                  : "=a" (d), "=d" (h)
968
                  : "0" (d), "1" (h - 1), "d" (val), "r" (bpr)
969
                );
970
}
971
 
972
/* Sets a 4 plane region from 'd', length 'count' bytes, to the color
973
 * in val1/val2. 'd' has to be an even address and count must be divisible
974
 * by 8, because only whole words and all planes are accessed. I.e.:
975
 *
976
 * for(count/8 times)
977
 *   *d     = *(d+1) = (color & 1) ? 0xff : 0;
978
 *   *(d+2) = *(d+3) = (color & 2) ? 0xff : 0;
979
 *   *(d+4) = *(d+5) = (color & 4) ? 0xff : 0;
980
 *   *(d+6) = *(d+7) = (color & 8) ? 0xff : 0;
981
 */
982
 
983
static __inline__ void memset_even_4p(void *d, size_t count, u_long val1,
984
                                      u_long val2)
985
{
986
  u_long *dd = d;
987
 
988
  count /= 8;
989
  while (count--)
990
    {
991
      *dd++ = val1;
992
      *dd++ = val2;
993
    }
994
}
995
 
996
/* Copies a 4 plane column from 's', height 'h', to 'd'. */
997
 
998
static __inline__ void memmove_4p_col (void *d, void *s, int h, int bpr)
999
{
1000
  u_char *dd = d, *ss = s;
1001
 
1002
  while (h--)
1003
    {
1004
      dd[0] = ss[0];
1005
      dd[2] = ss[2];
1006
      dd[4] = ss[4];
1007
      dd[6] = ss[6];
1008
      dd += bpr;
1009
      ss += bpr;
1010
    }
1011
}
1012
 
1013
 
1014
/* This expands a 4 bit color into a long for movepl (4 plane) operations. */
1015
 
1016
static __inline__ u_long expand4l(u_char c)
1017
{
1018
        u_long  rv;
1019
 
1020
        __asm__ __volatile__
1021
                ("lsrb   #1,%2\n\t"
1022
                  "scs   %0\n\t"
1023
                  "lsll  #8,%0\n\t"
1024
                  "lsrb  #1,%2\n\t"
1025
                  "scs   %0\n\t"
1026
                  "lsll  #8,%0\n\t"
1027
                  "lsrb  #1,%2\n\t"
1028
                  "scs   %0\n\t"
1029
                  "lsll  #8,%0\n\t"
1030
                  "lsrb  #1,%2\n\t"
1031
                  "scs   %0\n\t"
1032
                  : "=&d" (rv), "=d" (c)
1033
                  : "1" (c)
1034
                );
1035
        return(rv);
1036
}
1037
 
1038
/* This expands a 4 bit color into two longs for two movel operations
1039
 * (4 planes).
1040
 */
1041
 
1042
static __inline__ void expand4dl(u_char c, u_long *ret1, u_long *ret2)
1043
{
1044
        u_long  rv1, rv2;
1045
 
1046
        __asm__ __volatile__
1047
                ("lsrb   #1,%3\n\t"
1048
                  "scs   %0\n\t"
1049
                  "extw  %0\n\t"
1050
                  "swap  %0\n\t"
1051
                  "lsrb  #1,%3\n\t"
1052
                  "scs   %0\n\t"
1053
                  "extw  %0\n\t"
1054
                  "lsrb  #1,%3\n\t"
1055
                  "scs   %1\n\t"
1056
                  "extw  %1\n\t"
1057
                  "swap  %1\n\t"
1058
                  "lsrb  #1,%3\n\t"
1059
                  "scs   %1\n\t"
1060
                  "extw  %1"
1061
                  : "=&d" (rv1), "=&d" (rv2), "=d" (c)
1062
                  : "2" (c)
1063
                );
1064
        *ret1 = rv1;
1065
        *ret2 = rv2;
1066
}
1067
 
1068
 
1069
/* This duplicates a byte 4 times into a long. */
1070
 
1071
static __inline__ u_long dup4l(u_char c)
1072
{
1073
        ushort  tmp;
1074
        ulong   rv;
1075
 
1076
        __asm__ __volatile__
1077
                ("moveb  %2,%0\n\t"
1078
                  "lslw   #8,%0\n\t"
1079
                  "moveb  %2,%0\n\t"
1080
                  "movew  %0,%1\n\t"
1081
                  "swap   %0\n\t"
1082
                  "movew  %1,%0"
1083
                  : "=&d" (rv), "=d" (tmp)
1084
                  : "d" (c)
1085
                );
1086
 
1087
        return(rv);
1088
}
1089
 
1090
 
1091
/* Sets the bytes in the visible column at d, height h, to the value
1092
 * val1,val2 for a 8 plane screen. The the bis of the color in 'color' are
1093
 * moved (8 times) to the respective bytes. This means:
1094
 *
1095
 * for(h times; d += bpr)
1096
 *   *d      = (color & 1) ? 0xff : 0;
1097
 *   *(d+2)  = (color & 2) ? 0xff : 0;
1098
 *   *(d+4)  = (color & 4) ? 0xff : 0;
1099
 *   *(d+6)  = (color & 8) ? 0xff : 0;
1100
 *   *(d+8)  = (color & 16) ? 0xff : 0;
1101
 *   *(d+10) = (color & 32) ? 0xff : 0;
1102
 *   *(d+12) = (color & 64) ? 0xff : 0;
1103
 *   *(d+14) = (color & 128) ? 0xff : 0;
1104
 */
1105
 
1106
static __inline__ void memclear_8p_col(void *d, size_t h, u_long val1,
1107
                                       u_long val2, int bpr)
1108
{
1109
        __asm__ __volatile__
1110
                ("1: movepl %4,%0@(0)\n\t"
1111
              "movepl %5,%0@(8)\n\t"
1112
                  "addal  %6,%0\n\t"
1113
                  "dbra   %1,1b"
1114
                  : "=a" (d), "=d" (h)
1115
                  : "0" (d), "1" (h - 1), "d" (val1), "d" (val2), "r" (bpr)
1116
                );
1117
}
1118
 
1119
/* Sets a 8 plane region from 'd', length 'count' bytes, to the color
1120
 * val1..val4. 'd' has to be an even address and count must be divisible
1121
 * by 16, because only whole words and all planes are accessed. I.e.:
1122
 *
1123
 * for(count/16 times)
1124
 *   *d      = *(d+1)  = (color & 1) ? 0xff : 0;
1125
 *   *(d+2)  = *(d+3)  = (color & 2) ? 0xff : 0;
1126
 *   *(d+4)  = *(d+5)  = (color & 4) ? 0xff : 0;
1127
 *   *(d+6)  = *(d+7)  = (color & 8) ? 0xff : 0;
1128
 *   *(d+8)  = *(d+9)  = (color & 16) ? 0xff : 0;
1129
 *   *(d+10) = *(d+11) = (color & 32) ? 0xff : 0;
1130
 *   *(d+12) = *(d+13) = (color & 64) ? 0xff : 0;
1131
 *   *(d+14) = *(d+15) = (color & 128) ? 0xff : 0;
1132
 */
1133
 
1134
static __inline__ void memset_even_8p(void *d, size_t count, u_long val1,
1135
                                      u_long val2, u_long val3, u_long val4)
1136
{
1137
  u_long *dd = d;
1138
 
1139
  count /= 16;
1140
  while (count--)
1141
    {
1142
      *dd++ = val1;
1143
      *dd++ = val2;
1144
      *dd++ = val3;
1145
      *dd++ = val4;
1146
    }
1147
}
1148
 
1149
/* Copies a 8 plane column from 's', height 'h', to 'd'. */
1150
 
1151
static __inline__ void memmove_8p_col (void *d, void *s, int h, int bpr)
1152
{
1153
  u_char *dd = d, *ss = s;
1154
 
1155
  while (h--)
1156
    {
1157
      dd[0] = ss[0];
1158
      dd[2] = ss[2];
1159
      dd[4] = ss[4];
1160
      dd[6] = ss[6];
1161
      dd[8] = ss[8];
1162
      dd[10] = ss[10];
1163
      dd[12] = ss[12];
1164
      dd[14] = ss[14];
1165
      dd += bpr;
1166
      ss += bpr;
1167
    }
1168
}
1169
 
1170
 
1171
/* This expands a 8 bit color into two longs for two movepl (8 plane)
1172
 * operations.
1173
 */
1174
 
1175
static __inline__ void expand8dl(u_char c, u_long *ret1, u_long *ret2)
1176
{
1177
        u_long  rv1, rv2;
1178
 
1179
        __asm__ __volatile__
1180
                ("lsrb   #1,%3\n\t"
1181
                  "scs   %0\n\t"
1182
                  "lsll  #8,%0\n\t"
1183
                  "lsrb  #1,%3\n\t"
1184
                  "scs   %0\n\t"
1185
                  "lsll  #8,%0\n\t"
1186
                  "lsrb  #1,%3\n\t"
1187
                  "scs   %0\n\t"
1188
                  "lsll  #8,%0\n\t"
1189
                  "lsrb  #1,%3\n\t"
1190
                  "scs   %0\n\t"
1191
                  "lsrb  #1,%3\n\t"
1192
                  "scs   %1\n\t"
1193
                  "lsll  #8,%1\n\t"
1194
                  "lsrb  #1,%3\n\t"
1195
                  "scs   %1\n\t"
1196
                  "lsll  #8,%1\n\t"
1197
                  "lsrb  #1,%3\n\t"
1198
                  "scs   %1\n\t"
1199
                  "lsll  #8,%1\n\t"
1200
                  "lsrb  #1,%3\n\t"
1201
                  "scs   %1"
1202
                  : "=&d" (rv1), "=&d" (rv2),"=d" (c)
1203
                  : "2" (c)
1204
                );
1205
 
1206
        *ret1 = rv1;
1207
        *ret2 = rv2;
1208
}
1209
 
1210
/* This expands a 8 bit color into four longs for four movel operations
1211
 * (8 planes).
1212
 */
1213
 
1214
/* ++andreas: use macro to avoid taking address of return values */
1215
#define expand8ql(c, rv1, rv2, rv3, rv4) \
1216
do {    u_char tmp = c;                                         \
1217
        __asm__ __volatile__                                    \
1218
                ("lsrb   #1,%5\n\t"                             \
1219
                  "scs   %0\n\t"                                \
1220
                  "extw  %0\n\t"                                \
1221
                  "swap  %0\n\t"                                \
1222
                  "lsrb  #1,%5\n\t"                             \
1223
                  "scs   %0\n\t"                                \
1224
                  "extw  %0\n\t"                                \
1225
                  "lsrb  #1,%5\n\t"                             \
1226
                  "scs   %1\n\t"                                \
1227
                  "extw  %1\n\t"                                \
1228
                  "swap  %1\n\t"                                \
1229
                  "lsrb  #1,%5\n\t"                             \
1230
                  "scs   %1\n\t"                                \
1231
                  "extw  %1\n\t"                                \
1232
                  "lsrb  #1,%5\n\t"                             \
1233
                  "scs   %2\n\t"                                \
1234
                  "extw  %2\n\t"                                \
1235
                  "swap  %2\n\t"                                \
1236
                  "lsrb  #1,%5\n\t"                             \
1237
                  "scs   %2\n\t"                                \
1238
                  "extw  %2\n\t"                                \
1239
                  "lsrb  #1,%5\n\t"                             \
1240
                  "scs   %3\n\t"                                \
1241
                  "extw  %3\n\t"                                \
1242
                  "swap  %3\n\t"                                \
1243
                  "lsrb  #1,%5\n\t"                             \
1244
                  "scs   %3\n\t"                                \
1245
                  "extw  %3"                                    \
1246
                  : "=&d" (rv1), "=&d" (rv2), "=&d" (rv3),      \
1247
                    "=&d" (rv4), "=d" (tmp)                     \
1248
                  : "4" (tmp)                                   \
1249
                );                                              \
1250
} while (0)
1251
 
1252
 
1253
/* Sets the bytes in the visible column at d, height h, to the value
1254
 * val for a 2 plane screen. The the bis of the color in 'color' are
1255
 * moved (8 times) to the respective bytes. This means:
1256
 *
1257
 * for(h times; d += bpr)
1258
 *   *d     = (color & 1) ? 0xff : 0;
1259
 *   *(d+2) = (color & 2) ? 0xff : 0;
1260
 */
1261
 
1262
static __inline__ void memclear_2p_col(void *d, size_t h, u_short val, int bpr)
1263
{
1264
        __asm__ __volatile__
1265
                ("1: movepw %4,%0@(0)\n\t"
1266
                  "addal  %5,%0\n\t"
1267
                  "dbra   %1,1b"
1268
                  : "=a" (d), "=d" (h)
1269
                  : "0" (d), "1" (h - 1), "d" (val), "r" (bpr)
1270
                );
1271
}
1272
 
1273
/* Sets a 2 plane region from 'd', length 'count' bytes, to the color
1274
 * in val1. 'd' has to be an even address and count must be divisible
1275
 * by 8, because only whole words and all planes are accessed. I.e.:
1276
 *
1277
 * for(count/4 times)
1278
 *   *d     = *(d+1) = (color & 1) ? 0xff : 0;
1279
 *   *(d+2) = *(d+3) = (color & 2) ? 0xff : 0;
1280
 */
1281
 
1282
static __inline__ void memset_even_2p(void *d, size_t count, u_long val)
1283
{
1284
  u_long *dd = d;
1285
 
1286
  count /= 4;
1287
  while (count--)
1288
    *dd++ = val;
1289
}
1290
 
1291
/* Copies a 2 plane column from 's', height 'h', to 'd'. */
1292
 
1293
static __inline__ void memmove_2p_col (void *d, void *s, int h, int bpr)
1294
{
1295
  u_char *dd = d, *ss = s;
1296
 
1297
  while (h--)
1298
    {
1299
      dd[0] = ss[0];
1300
      dd[2] = ss[2];
1301
      dd += bpr;
1302
      ss += bpr;
1303
    }
1304
}
1305
 
1306
 
1307
/* This expands a 2 bit color into a short for movepw (2 plane) operations. */
1308
 
1309
static __inline__ u_short expand2w(u_char c)
1310
{
1311
        u_short rv;
1312
 
1313
        __asm__ __volatile__
1314
                ("lsrb   #1,%2\n\t"
1315
                  "scs   %0\n\t"
1316
                  "lsll  #8,%0\n\t"
1317
                  "lsrb  #1,%2\n\t"
1318
                  "scs   %0\n\t"
1319
                  : "=&d" (rv), "=d" (c)
1320
                  : "1" (c)
1321
                );
1322
        return(rv);
1323
}
1324
 
1325
/* This expands a 2 bit color into one long for a movel operation
1326
 * (2 planes).
1327
 */
1328
 
1329
static __inline__ u_long expand2l(u_char c)
1330
{
1331
        u_long  rv;
1332
 
1333
        __asm__ __volatile__
1334
                ("lsrb   #1,%2\n\t"
1335
                  "scs   %0\n\t"
1336
                  "extw  %0\n\t"
1337
                  "swap  %0\n\t"
1338
                  "lsrb  #1,%2\n\t"
1339
                  "scs   %0\n\t"
1340
                  "extw  %0\n\t"
1341
                  : "=&d" (rv), "=d" (c)
1342
                  : "1" (c)
1343
                );
1344
 
1345
        return rv;
1346
}
1347
 
1348
 
1349
/* This duplicates a byte 2 times into a short. */
1350
 
1351
static __inline__ u_short dup2w(u_char c)
1352
{
1353
    ushort  rv;
1354
 
1355
    __asm__ __volatile__
1356
        ( "moveb  %1,%0\n\t"
1357
          "lslw   #8,%0\n\t"
1358
          "moveb  %1,%0\n\t"
1359
          : "=&d" (rv)
1360
          : "d" (c)
1361
        );
1362
 
1363
    return( rv );
1364
}
1365
 
1366
 
1367
/* ====================================================================== */
1368
 
1369
/* fbcon_XXX routines - interface used by the world
1370
 *
1371
 * This system is now divided into two levels because of complications
1372
 * caused by hardware scrolling. Top level functions:
1373
 *
1374
 *    fbcon_bmove(), fbcon_clear(), fbcon_putc()
1375
 *
1376
 * handles y values in range [0, scr_height-1] that correspond to real
1377
 * screen positions. y_wrap shift means that first line of bitmap may be
1378
 * anywhere on this display. These functions convert lineoffsets to
1379
 * bitmap offsets and deal with the wrap-around case by splitting blits.
1380
 *
1381
 *    fbcon_bmove_physical_8()   -- These functions fast implementations
1382
 *    fbcon_clear_physical_8()   -- of original fbcon_XXX fns.
1383
 *    fbcon_putc_physical_8()    -- (fontwidth != 8) may be added later
1384
 *
1385
 * WARNING:
1386
 *
1387
 * At the moment fbcon_putc() cannot blit across vertical wrap boundary
1388
 * Implies should only really hardware scroll in rows. Only reason for
1389
 * restriction is simplicity & efficiency at the moment.
1390
 */
1391
 
1392
static __inline__ int real_y(struct display *p, int y)
1393
{
1394
   int rows = p->vrows;
1395
 
1396
   y += p->yscroll;
1397
   return(y < rows ? y : y-rows);
1398
}
1399
 
1400
 
1401
static int fbcon_clear(struct vc_data *conp, int sy, int sx, int height,
1402
                       int width)
1403
{
1404
   int unit = conp->vc_num;
1405
   struct display *p = &disp[unit];
1406
   u_int y_break;
1407
 
1408
   if (!p->can_soft_blank && console_blanked)
1409
      return(0);
1410
 
1411
   if ((sy <= p->cursor_y) && (p->cursor_y < sy+height) &&
1412
       (sx <= p->cursor_x) && (p->cursor_x < sx+width))
1413
      CURSOR_UNDRAWN();
1414
 
1415
   /* Split blits that cross physical y_wrap boundary */
1416
 
1417
   y_break = p->vrows-p->yscroll;
1418
   if (sy < y_break && sy+height-1 >= y_break) {
1419
      u_int b = y_break-sy;
1420
      p->dispsw->clear(conp, p, real_y(p, sy), sx, b, width);
1421
      p->dispsw->clear(conp, p, real_y(p, sy+b), sx, height-b, width);
1422
   } else
1423
      p->dispsw->clear(conp, p, real_y(p, sy), sx, height, width);
1424
 
1425
   return(0);
1426
}
1427
 
1428
 
1429
static int fbcon_putc(struct vc_data *conp, int c, int y, int x)
1430
{
1431
   int unit = conp->vc_num;
1432
   struct display *p = &disp[unit];
1433
 
1434
   if (!p->can_soft_blank && console_blanked)
1435
      return(0);
1436
 
1437
   if ((p->cursor_x == x) && (p->cursor_y == y))
1438
       CURSOR_UNDRAWN();
1439
 
1440
   p->dispsw->putc(conp, p, c, real_y(p, y), x);
1441
 
1442
   return(0);
1443
}
1444
 
1445
 
1446
static int fbcon_putcs(struct vc_data *conp, const char *s, int count, int y,
1447
                       int x)
1448
{
1449
   int unit = conp->vc_num;
1450
   struct display *p = &disp[unit];
1451
 
1452
   if (!p->can_soft_blank && console_blanked)
1453
      return(0);
1454
 
1455
   if ((p->cursor_y == y) && (x <= p->cursor_x) && (p->cursor_x < x+count))
1456
      CURSOR_UNDRAWN();
1457
 
1458
   p->dispsw->putcs(conp, p, s, count, real_y(p, y), x);
1459
 
1460
   return(0);
1461
}
1462
 
1463
 
1464
static int fbcon_cursor(struct vc_data *conp, int mode)
1465
{
1466
   int unit = conp->vc_num;
1467
   struct display *p = &disp[unit];
1468
 
1469
   if (CURSOR_UNDRAWN ())
1470
      p->dispsw->rev_char(p, p->cursor_x, real_y(p, p->cursor_y));
1471
   p->cursor_x = conp->vc_x;
1472
   p->cursor_y = conp->vc_y;
1473
 
1474
   switch (mode) {
1475
      case CM_ERASE:
1476
         cursor_on = 0;
1477
         break;
1478
 
1479
      case CM_MOVE:
1480
      case CM_DRAW:
1481
         vbl_cursor_cnt = CURSOR_DRAW_DELAY;
1482
         cursor_on = 1;
1483
         break;
1484
   }
1485
 
1486
   return(0);
1487
}
1488
 
1489
 
1490
static void fbcon_vbl_handler(int irq, struct pt_regs *fp, void *dummy)
1491
{
1492
   struct display *p;
1493
 
1494
   if (!cursor_on)
1495
      return;
1496
 
1497
   if (vbl_cursor_cnt && --vbl_cursor_cnt == 0) {
1498
      /* Here no check is possible for console changing. The console
1499
       * switching code should set vbl_cursor_cnt to an appropriate value.
1500
       */
1501
      p = &disp[fg_console];
1502
      p->dispsw->rev_char(p, p->cursor_x, real_y(p, p->cursor_y));
1503
      cursor_drawn ^= 1;
1504
      vbl_cursor_cnt = cursor_blink_rate;
1505
   }
1506
}
1507
 
1508
 
1509
static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
1510
{
1511
   int unit = conp->vc_num;
1512
   struct display *p = &disp[unit];
1513
 
1514
   if (!p->can_soft_blank && console_blanked)
1515
      return(0);
1516
 
1517
   fbcon_cursor(conp, CM_ERASE);
1518
 
1519
   /*
1520
    * ++Geert: Only use ywrap/ypan if the console is in text mode
1521
    */
1522
 
1523
   switch (dir) {
1524
      case SM_UP:
1525
         if (t == 0 && b == conp->vc_rows &&
1526
             vt_cons[unit]->vc_mode == KD_TEXT) {
1527
            if (count > conp->vc_rows)             /* Maximum realistic size */
1528
               count = conp->vc_rows;
1529
            switch (p->scrollmode) {
1530
               case SCROLL_YWRAP:
1531
                  p->yscroll += count;
1532
                  if (p->yscroll >= p->vrows) /* Deal with wrap */
1533
                     p->yscroll -= p->vrows;
1534
                  p->var.xoffset = 0;
1535
                  p->var.yoffset = p->yscroll*p->fontheight;
1536
                  p->var.vmode |= FB_VMODE_YWRAP;
1537
                  fb_info->updatevar(unit);
1538
                  break;
1539
 
1540
               case SCROLL_YPAN:
1541
                  p->yscroll += count;
1542
                  if (p->yscroll+conp->vc_rows > p->vrows) {
1543
                     p->dispsw->bmove(p, p->yscroll, 0, 0, 0, b-count,
1544
                                      conp->vc_cols);
1545
                     p->yscroll = 0;
1546
                  }
1547
                  p->var.xoffset = 0;
1548
                  p->var.yoffset = p->yscroll*p->fontheight;
1549
                  p->var.vmode &= ~FB_VMODE_YWRAP;
1550
                  fb_info->updatevar(unit);
1551
                  break;
1552
 
1553
               case SCROLL_YMOVE:
1554
                  p->dispsw->bmove(p, count, 0, 0, 0, b-count, conp->vc_cols);
1555
                  break;
1556
            }
1557
         } else
1558
            fbcon_bmove(conp, t+count, 0, t, 0, b-t-count, conp->vc_cols);
1559
         fbcon_clear(conp, b-count, 0, count, conp->vc_cols);
1560
         break;
1561
 
1562
      case SM_DOWN:
1563
         if (t == 0 && b == conp->vc_rows &&
1564
             vt_cons[unit]->vc_mode == KD_TEXT) {
1565
            if (count > conp->vc_rows)             /* Maximum realistic size */
1566
               count = conp->vc_rows;
1567
            switch (p->scrollmode) {
1568
               case SCROLL_YWRAP:
1569
                  p->yscroll -= count;
1570
                  if (p->yscroll < 0)              /* Deal with wrap */
1571
                     p->yscroll += p->vrows;
1572
                  p->var.xoffset = 0;
1573
                  p->var.yoffset = p->yscroll*p->fontheight;
1574
                  p->var.vmode |= FB_VMODE_YWRAP;
1575
                  fb_info->updatevar(unit);
1576
                  break;
1577
 
1578
               case SCROLL_YPAN:
1579
                  p->yscroll -= count;
1580
                  if (p->yscroll < 0) {
1581
                     p->yscroll = p->vrows-conp->vc_rows;
1582
                     p->dispsw->bmove(p, 0, 0, p->yscroll+count, 0, b-count,
1583
                                      conp->vc_cols);
1584
                  }
1585
                  p->var.xoffset = 0;
1586
                  p->var.yoffset = p->yscroll*p->fontheight;
1587
                  p->var.vmode &= ~FB_VMODE_YWRAP;
1588
                  fb_info->updatevar(unit);
1589
                  break;
1590
 
1591
               case SCROLL_YMOVE:
1592
                  p->dispsw->bmove(p, 0, 0, count, 0, b-count, conp->vc_cols);
1593
                  break;
1594
            }
1595
         } else
1596
            fbcon_bmove(conp, t, 0, t+count, 0, b-t-count, conp->vc_cols);
1597
 
1598
         /* Fixed bmove() should end Arno's frustration with copying?
1599
          * Confucius says:
1600
          *    Man who copies in wrong direction, end up with trashed data
1601
          */
1602
         fbcon_clear(conp, t, 0, count, conp->vc_cols);
1603
         break;
1604
 
1605
      case SM_LEFT:
1606
         fbcon_bmove(conp, 0, t+count, 0, t, conp->vc_rows, b-t-count);
1607
         fbcon_clear(conp, 0, b-count, conp->vc_rows, count);
1608
         break;
1609
 
1610
      case SM_RIGHT:
1611
         fbcon_bmove(conp, 0, t, 0, t+count, conp->vc_rows, b-t-count);
1612
         fbcon_clear(conp, 0, t, conp->vc_rows, count);
1613
         break;
1614
   }
1615
 
1616
   return(0);
1617
}
1618
 
1619
 
1620
static int fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
1621
                       int height, int width)
1622
{
1623
   int unit = conp->vc_num;
1624
   struct display *p = &disp[unit];
1625
 
1626
   if (!p->can_soft_blank && console_blanked)
1627
      return(0);
1628
 
1629
   if (((sy <= p->cursor_y) && (p->cursor_y < sy+height) &&
1630
        (sx <= p->cursor_x) && (p->cursor_x < sx+width)) ||
1631
       ((dy <= p->cursor_y) && (p->cursor_y < dy+height) &&
1632
        (dx <= p->cursor_x) && (p->cursor_x < dx+width)))
1633
      fbcon_cursor(conp, CM_ERASE);
1634
 
1635
   /* Split blits that cross physical y_wrap case.
1636
    * Pathological case involves 4 blits, better to use recursive
1637
    * code rather than unrolled case
1638
    *
1639
    * Recursive invocations don't need to erase the cursor over and
1640
    * over again, so we use fbcon_bmove_rec()
1641
    */
1642
   fbcon_bmove_rec(p, sy, sx, dy, dx, height, width, p->vrows-p->yscroll);
1643
 
1644
   return(0);
1645
}
1646
 
1647
 
1648
static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy, int dx,
1649
                            int height, int width, u_int y_break)
1650
{
1651
   u_int b;
1652
 
1653
   if (sy < y_break && sy+height > y_break) {
1654
      b = y_break-sy;
1655
      if (dy < sy) {       /* Avoid trashing self */
1656
         fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break);
1657
         fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break);
1658
      } else {
1659
         fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break);
1660
         fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break);
1661
      }
1662
      return;
1663
   }
1664
 
1665
   if (dy < y_break && dy+height > y_break) {
1666
      b = y_break-dy;
1667
      if (dy < sy) {       /* Avoid trashing self */
1668
         fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break);
1669
         fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break);
1670
      } else {
1671
         fbcon_bmove_rec(p, sy+b, sx, dy+b, dx, height-b, width, y_break);
1672
         fbcon_bmove_rec(p, sy, sx, dy, dx, b, width, y_break);
1673
      }
1674
      return;
1675
   }
1676
   p->dispsw->bmove(p, real_y(p, sy), sx, real_y(p, dy), dx, height, width);
1677
}
1678
 
1679
 
1680
static int fbcon_switch(struct vc_data *conp)
1681
{
1682
   if (fb_info && fb_info->switch_con)
1683
      (*fb_info->switch_con)(conp->vc_num);
1684
   return(0);
1685
}
1686
 
1687
 
1688
static int fbcon_blank(int blank)
1689
{
1690
   struct display *p = &disp[fg_console];
1691
 
1692
   fbcon_cursor(p->conp, blank ? CM_ERASE : CM_DRAW);
1693
 
1694
   if (!p->can_soft_blank)
1695
      if (blank) {
1696
         if (p->visual == FB_VISUAL_MONO01)
1697
             mymemset(p->screen_base, p->var.xres_virtual*p->var.yres_virtual*
1698
                                      p->var.bits_per_pixel>>3);
1699
          else
1700
             mymemclear(p->screen_base, p->var.xres_virtual*p->var.yres_virtual*
1701
                                        p->var.bits_per_pixel>>3);
1702
         return(0);
1703
      } else {
1704
         /* Tell console.c that it has to restore the screen itself */
1705
         return(1);
1706
      }
1707
   (*fb_info->blank)(blank);
1708
   return(0);
1709
}
1710
 
1711
 
1712
static int fbcon_get_font(struct vc_data *conp, int *w, int *h, char *data)
1713
{
1714
        int unit = conp->vc_num;
1715
        struct display *p = &disp[unit];
1716
        int i, size, alloc;
1717
 
1718
        size = (p->fontwidth+7)/8 * p->fontheight * 256;
1719
        alloc = (*w+7)/8 * *h * 256;
1720
        *w = p->fontwidth;
1721
        *h = p->fontheight;
1722
 
1723
        if (alloc < size)
1724
                /* allocation length not sufficient */
1725
                return( -ENAMETOOLONG );
1726
 
1727
        if ((i = verify_area( VERIFY_WRITE, (void *)data, size )))
1728
                return i;
1729
 
1730
        memcpy_tofs( data, p->fontdata, size );
1731
        return( 0 );
1732
}
1733
 
1734
 
1735
#define REFCOUNT(fd)    (((int *)(fd))[-1])
1736
 
1737
static int fbcon_set_font(struct vc_data *conp, int w, int h, char *data)
1738
{
1739
        int unit = conp->vc_num;
1740
        struct display *p = &disp[unit];
1741
        int i, size, userspace = 1, resize;
1742
        char *old_data = NULL, *new_data;
1743
 
1744
        if (w < 0)
1745
                w = p->fontwidth;
1746
        if (h < 0)
1747
                h = p->fontheight;
1748
 
1749
        if (w == 0) {
1750
                /* engage predefined font, name in 'data' */
1751
                char name[MAX_FONT_NAME+1];
1752
 
1753
                if ((i = verify_area( VERIFY_READ, (void *)data, MAX_FONT_NAME )))
1754
                        return i;
1755
                memcpy_fromfs( name, data, MAX_FONT_NAME );
1756
                name[sizeof(name)-1] = 0;
1757
 
1758
                if (!findsoftfont( name, &w, &h, (u_char **)&data ))
1759
                        return( -ENOENT );
1760
                userspace = 0;
1761
        }
1762
        else if (w == 1) {
1763
                /* copy font from some other console in 'h'*/
1764
                struct display *op;
1765
 
1766
                if (h < 0 || !vc_cons_allocated( h ))
1767
                        return( -ENOTTY );
1768
                if (h == unit)
1769
                        return( 0 ); /* nothing to do */
1770
                op = &disp[h];
1771
                if (op->fontdata == p->fontdata)
1772
                        return( 0 ); /* already the same font... */
1773
 
1774
                resize = (op->fontwidth != p->fontwidth) ||
1775
                             (op->fontheight != p->fontheight);
1776
                if (p->userfont)
1777
                        old_data = p->fontdata;
1778
                p->fontdata = op->fontdata;
1779
                w = p->fontwidth = op->fontwidth;
1780
                h = p->fontheight = op->fontheight;
1781
                if ((p->userfont = op->userfont))
1782
                        REFCOUNT(p->fontdata)++; /* increment usage counter */
1783
                goto activate;
1784
        }
1785
 
1786
        if (w != 8)
1787
                /* Currently only fontwidth == 8 supported */
1788
                return( -ENXIO );
1789
 
1790
        resize = (w != p->fontwidth) || (h != p->fontheight);
1791
        size = (w+7)/8 * h * 256;
1792
 
1793
        if (p->userfont)
1794
                old_data = p->fontdata;
1795
 
1796
        if (userspace) {
1797
                if ((i = verify_area( VERIFY_READ, (void *)data, size )))
1798
                        return i;
1799
                if (!(new_data = kmalloc( sizeof(int)+size, GFP_USER )))
1800
                        return( -ENOMEM );
1801
                new_data += sizeof(int);
1802
                REFCOUNT(new_data) = 1; /* usage counter */
1803
                memcpy_fromfs( new_data, data, size );
1804
                p->fontdata = new_data;
1805
                p->userfont = 1;
1806
        }
1807
        else {
1808
                p->fontdata = data;
1809
                p->userfont = 0;
1810
        }
1811
        p->fontwidth = w;
1812
        p->fontheight = h;
1813
 
1814
  activate:
1815
        if (resize) {
1816
                p->var.xoffset = p->var.yoffset = p->yscroll = 0;  /* reset wrap/pan */
1817
                if (divides(p->ywrapstep, p->fontheight))
1818
                        p->scrollmode = SCROLL_YWRAP;
1819
                else if (divides(p->ypanstep, p->fontheight) &&
1820
                                 p->var.yres_virtual >= p->var.yres+p->fontheight)
1821
                        p->scrollmode = SCROLL_YPAN;
1822
                else
1823
                        p->scrollmode = SCROLL_YMOVE;
1824
 
1825
                vc_resize_con( p->var.yres/h, p->var.xres/w, unit );
1826
        }
1827
        else if (unit == fg_console)
1828
                update_screen( unit );
1829
 
1830
        if (old_data) {
1831
                if (--REFCOUNT(old_data) == 0) {
1832
                        kfree( old_data - sizeof(int) );
1833
                }
1834
        }
1835
 
1836
        return( 0 );
1837
}
1838
 
1839
 
1840
/* ====================================================================== */
1841
 
1842
/*
1843
 *    Low Level Operations for the various display memory organizations.
1844
 *
1845
 *    Currently only the following organizations are supported here:
1846
 *
1847
 *      - Monochrome
1848
 *      - Color Interleaved Planes à la Amiga
1849
 *      - Color Normal Planes
1850
 *      - Color Interleaved Planes à la Atari (2, 4 and 8 planes)
1851
 *      - Color Packed Pixels (8 and 16 bpp)
1852
 *      - Cybervision Color Packed Pixels (accelerated)
1853
 */
1854
 
1855
#ifdef CONFIG_FBCON_MONO
1856
 
1857
   /*
1858
    *    Monochrome
1859
    */
1860
 
1861
static void bmove_mono(struct display *p, int sy, int sx, int dy, int dx,
1862
                       int height, int width)
1863
{
1864
   u_char *src, *dest;
1865
   u_int rows;
1866
 
1867
   if (sx == 0 && sy == 0 && width == p->next_line) {
1868
      src = p->screen_base;
1869
      dest = p->screen_base+dy*p->fontheight*width;
1870
      mymemmove(dest, src, height*p->fontheight*width);
1871
   } else if (dy <= sy) {
1872
      src = p->screen_base+sy*p->fontheight*p->next_line+sx;
1873
      dest = p->screen_base+dy*p->fontheight*p->next_line+dx;
1874
      for (rows = height*p->fontheight; rows--;) {
1875
         mymemmove(dest, src, width);
1876
         src += p->next_line;
1877
         dest += p->next_line;
1878
      }
1879
   } else {
1880
      src = p->screen_base+((sy+height)*p->fontheight-1)*p->next_line+sx;
1881
      dest = p->screen_base+((dy+height)*p->fontheight-1)*p->next_line+dx;
1882
      for (rows = height*p->fontheight; rows--;) {
1883
         mymemmove(dest, src, width);
1884
         src -= p->next_line;
1885
         dest -= p->next_line;
1886
      }
1887
   }
1888
}
1889
 
1890
 
1891
static void clear_mono(struct vc_data *conp, struct display *p, int sy, int sx,
1892
                       int height, int width)
1893
{
1894
   u_char *dest;
1895
   u_int rows;
1896
 
1897
   dest = p->screen_base+sy*p->fontheight*p->next_line+sx;
1898
 
1899
   if (sx == 0 && width == p->next_line)
1900
      if (attr_reverse(p,conp))
1901
         mymemset(dest, height*p->fontheight*width);
1902
      else
1903
         mymemclear(dest, height*p->fontheight*width);
1904
   else
1905
      for (rows = height*p->fontheight; rows--; dest += p->next_line)
1906
         if (attr_reverse(p,conp))
1907
            mymemset(dest, width);
1908
         else
1909
            mymemclear_small(dest, width);
1910
}
1911
 
1912
 
1913
static void putc_mono(struct vc_data *conp, struct display *p, int c, int y,
1914
                      int x)
1915
{
1916
   u_char *dest, *cdat;
1917
   u_int rows, bold, reverse, underline;
1918
   u_char d;
1919
 
1920
   c &= 0xff;
1921
 
1922
   dest = p->screen_base+y*p->fontheight*p->next_line+x;
1923
   cdat = p->fontdata+c*p->fontheight;
1924
   bold = attr_bold(p,conp);
1925
   reverse = attr_reverse(p,conp);
1926
   underline = attr_underline(p,conp);
1927
 
1928
   for (rows = p->fontheight; rows--; dest += p->next_line) {
1929
      d = *cdat++;
1930
      if (underline && !rows)
1931
         d = 0xff;
1932
      else if (bold)
1933
         d |= d>>1;
1934
      if (reverse)
1935
         d = ~d;
1936
      *dest = d;
1937
   }
1938
}
1939
 
1940
 
1941
static void putcs_mono(struct vc_data *conp, struct display *p, const char *s,
1942
                       int count, int y, int x)
1943
{
1944
   u_char *dest, *dest0, *cdat;
1945
   u_int rows, bold, reverse, underline;
1946
   u_char c, d;
1947
 
1948
   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
1949
   bold = attr_bold(p,conp);
1950
   reverse = attr_reverse(p,conp);
1951
   underline = attr_underline(p,conp);
1952
 
1953
   while (count--) {
1954
      c = *s++;
1955
      dest = dest0++;
1956
      cdat = p->fontdata+c*p->fontheight;
1957
      for (rows = p->fontheight; rows--; dest += p->next_line) {
1958
         d = *cdat++;
1959
         if (underline && !rows)
1960
            d = 0xff;
1961
         else if (bold)
1962
            d |= d>>1;
1963
         if (reverse)
1964
            d = ~d;
1965
         *dest = d;
1966
      }
1967
   }
1968
}
1969
 
1970
 
1971
static void rev_char_mono(struct display *p, int x, int y)
1972
{
1973
   u_char *dest;
1974
   u_int rows;
1975
 
1976
   dest = p->screen_base+y*p->fontheight*p->next_line+x;
1977
   for (rows = p->fontheight; rows--; dest += p->next_line)
1978
      *dest = ~*dest;
1979
}
1980
 
1981
#endif /* CONFIG_FBCON_MONO */
1982
 
1983
 
1984
/* ====================================================================== */
1985
 
1986
#ifdef CONFIG_FBCON_ILBM
1987
 
1988
   /*
1989
    *    Color Interleaved Planes
1990
    *
1991
    *    This code heavily relies on the fact that
1992
    *
1993
    *       next_line == interleave == next_plane*bits_per_pixel
1994
    *
1995
    *    But maybe it can be merged with the code for normal bitplanes without
1996
    *    much performance loss?
1997
    */
1998
 
1999
static void bmove_ilbm(struct display *p, int sy, int sx, int dy, int dx,
2000
                       int height, int width)
2001
{
2002
   if (sx == 0 && sy == 0 && width == p->next_plane)
2003
      mymemmove(p->screen_base+dy*p->fontheight*p->next_line, p->screen_base,
2004
                height*p->fontheight*p->next_line);
2005
   else {
2006
      u_char *src, *dest;
2007
      u_int i;
2008
 
2009
      if (dy <= sy) {
2010
         src = p->screen_base+sy*p->fontheight*p->next_line+sx;
2011
         dest = p->screen_base+dy*p->fontheight*p->next_line+dx;
2012
         for (i = p->var.bits_per_pixel*height*p->fontheight; i--;) {
2013
            mymemmove(dest, src, width);
2014
            src += p->next_plane;
2015
            dest += p->next_plane;
2016
         }
2017
      } else {
2018
         src = p->screen_base+(sy+height)*p->fontheight*p->next_line+sx;
2019
         dest = p->screen_base+(dy+height)*p->fontheight*p->next_line+dx;
2020
         for (i = p->var.bits_per_pixel*height*p->fontheight; i--;) {
2021
            src -= p->next_plane;
2022
            dest -= p->next_plane;
2023
            mymemmove(dest, src, width);
2024
         }
2025
      }
2026
   }
2027
}
2028
 
2029
 
2030
static void clear_ilbm(struct vc_data *conp, struct display *p, int sy, int sx,
2031
                       int height, int width)
2032
{
2033
   u_char *dest;
2034
   u_int i, rows;
2035
   int bg, bg0;
2036
 
2037
   dest = p->screen_base+sy*p->fontheight*p->next_line+sx;
2038
 
2039
   bg0 = attr_bgcol_ec(p,conp);
2040
   for (rows = height*p->fontheight; rows--;) {
2041
      bg = bg0;
2042
      for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
2043
         if (bg & 1)
2044
            mymemset(dest, width);
2045
         else
2046
            mymemclear(dest, width);
2047
         bg >>= 1;
2048
      }
2049
   }
2050
}
2051
 
2052
 
2053
static void putc_ilbm(struct vc_data *conp, struct display *p, int c, int y,
2054
                      int x)
2055
{
2056
   u_char *dest, *cdat;
2057
   u_int rows, i;
2058
   u_char d;
2059
   int fg0, bg0, fg, bg;
2060
 
2061
   c &= 0xff;
2062
 
2063
   dest = p->screen_base+y*p->fontheight*p->next_line+x;
2064
   cdat = p->fontdata+c*p->fontheight;
2065
   fg0 = attr_fgcol(p,conp);
2066
   bg0 = attr_bgcol(p,conp);
2067
 
2068
   for (rows = p->fontheight; rows--;) {
2069
      d = *cdat++;
2070
      fg = fg0;
2071
      bg = bg0;
2072
      for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
2073
         if (bg & 1)
2074
            if (fg & 1)
2075
               *dest = 0xff;
2076
            else
2077
               *dest = ~d;
2078
         else
2079
            if (fg & 1)
2080
               *dest = d;
2081
            else
2082
               *dest = 0x00;
2083
         bg >>= 1;
2084
         fg >>= 1;
2085
      }
2086
   }
2087
}
2088
 
2089
 
2090
/*
2091
 *    I split the console character loop in two parts:
2092
 *
2093
 *      - slow version: this blits one character at a time
2094
 *
2095
 *      - fast version: this blits 4 characters at a time at a longword aligned
2096
 *                      address, to reduce the number of expensive Chip RAM
2097
 *                      accesses.
2098
 *
2099
 *    Experiments on my A4000/040 revealed that this makes a console switch on a
2100
 *    640x400 screen with 256 colors about 3 times faster.
2101
 *
2102
 *                                                                Geert
2103
 */
2104
 
2105
static void putcs_ilbm(struct vc_data *conp, struct display *p, const char *s,
2106
                       int count, int y, int x)
2107
{
2108
   u_char *dest0, *dest, *cdat1, *cdat2, *cdat3, *cdat4;
2109
   u_int rows, i;
2110
   u_char c1, c2, c3, c4;
2111
   u_long d;
2112
   int fg0, bg0, fg, bg;
2113
 
2114
   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
2115
   fg0 = attr_fgcol(p,conp);
2116
   bg0 = attr_bgcol(p,conp);
2117
 
2118
   while (count--)
2119
      if (x&3 || count < 3) {   /* Slow version */
2120
         c1 = *s++;
2121
         dest = dest0++;
2122
         x++;
2123
 
2124
         cdat1 = p->fontdata+c1*p->fontheight;
2125
         for (rows = p->fontheight; rows--;) {
2126
            d = *cdat1++;
2127
            fg = fg0;
2128
            bg = bg0;
2129
            for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
2130
               if (bg & 1)
2131
                  if (fg & 1)
2132
                     *dest = 0xff;
2133
                  else
2134
                     *dest = ~d;
2135
               else
2136
                  if (fg & 1)
2137
                     *dest = d;
2138
                  else
2139
                     *dest = 0x00;
2140
               bg >>= 1;
2141
               fg >>= 1;
2142
            }
2143
         }
2144
      } else {                      /* Fast version */
2145
         c1 = s[0];
2146
         c2 = s[1];
2147
         c3 = s[2];
2148
         c4 = s[3];
2149
 
2150
         dest = dest0;
2151
         cdat1 = p->fontdata+c1*p->fontheight;
2152
         cdat2 = p->fontdata+c2*p->fontheight;
2153
         cdat3 = p->fontdata+c3*p->fontheight;
2154
         cdat4 = p->fontdata+c4*p->fontheight;
2155
         for (rows = p->fontheight; rows--;) {
2156
            d = *cdat1++<<24 | *cdat2++<<16 | *cdat3++<<8 | *cdat4++;
2157
            fg = fg0;
2158
            bg = bg0;
2159
            for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
2160
               if (bg & 1)
2161
                  if (fg & 1)
2162
                     *(u_long *)dest = 0xffffffff;
2163
                  else
2164
                     *(u_long *)dest = ~d;
2165
               else
2166
                  if (fg & 1)
2167
                     *(u_long *)dest = d;
2168
                  else
2169
                     *(u_long *)dest = 0x00000000;
2170
               bg >>= 1;
2171
               fg >>= 1;
2172
            }
2173
         }
2174
         s += 4;
2175
         dest0 += 4;
2176
         x += 4;
2177
         count -= 3;
2178
      }
2179
}
2180
 
2181
 
2182
static void rev_char_ilbm(struct display *p, int x, int y)
2183
{
2184
   u_char *dest, *dest0;
2185
   u_int rows, i;
2186
   int mask;
2187
 
2188
   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
2189
   mask = p->fgcol ^ p->bgcol;
2190
 
2191
   /*
2192
    *    This should really obey the individual character's
2193
    *    background and foreground colors instead of simply
2194
    *    inverting.
2195
    */
2196
 
2197
   for (i = p->var.bits_per_pixel; i--; dest0 += p->next_plane) {
2198
      if (mask & 1) {
2199
         dest = dest0;
2200
         for (rows = p->fontheight; rows--; dest += p->next_line)
2201
            *dest = ~*dest;
2202
      }
2203
      mask >>= 1;
2204
   }
2205
}
2206
 
2207
#endif /* CONFIG_FBCON_ILBM */
2208
 
2209
 
2210
/* ====================================================================== */
2211
 
2212
#ifdef CONFIG_FBCON_PLANES
2213
 
2214
   /*
2215
    *    Color Planes
2216
    */
2217
 
2218
static void bmove_plan(struct display *p, int sy, int sx, int dy, int dx,
2219
                       int height, int width)
2220
{
2221
   u_char *src, *dest, *src0, *dest0;
2222
   u_int i, rows;
2223
 
2224
   if (sx == 0 && sy == 0 && width == p->next_line) {
2225
      src = p->screen_base;
2226
      dest = p->screen_base+dy*p->fontheight*width;
2227
      for (i = p->var.bits_per_pixel; i--;) {
2228
         mymemmove(dest, src, height*p->fontheight*width);
2229
         src += p->next_plane;
2230
         dest += p->next_plane;
2231
      }
2232
   } else if (dy <= sy) {
2233
      src0 = p->screen_base+sy*p->fontheight*p->next_line+sx;
2234
      dest0 = p->screen_base+dy*p->fontheight*p->next_line+dx;
2235
      for (i = p->var.bits_per_pixel; i--;) {
2236
         src = src0;
2237
         dest = dest0;
2238
         for (rows = height*p->fontheight; rows--;) {
2239
            mymemmove(dest, src, width);
2240
            src += p->next_line;
2241
            dest += p->next_line;
2242
         }
2243
         src0 += p->next_plane;
2244
         dest0 += p->next_plane;
2245
      }
2246
   } else {
2247
      src0 = p->screen_base+(sy+height)*p->fontheight*p->next_line+sx;
2248
      dest0 = p->screen_base+(dy+height)*p->fontheight*p->next_line+dx;
2249
      for (i = p->var.bits_per_pixel; i--;) {
2250
         src = src0;
2251
         dest = dest0;
2252
         for (rows = height*p->fontheight; rows--;) {
2253
            src -= p->next_line;
2254
            dest -= p->next_line;
2255
            mymemmove(dest, src, width);
2256
         }
2257
         src0 += p->next_plane;
2258
         dest0 += p->next_plane;
2259
      }
2260
   }
2261
}
2262
 
2263
 
2264
static void clear_plan(struct vc_data *conp, struct display *p, int sy, int sx,
2265
                       int height, int width)
2266
{
2267
   u_char *dest, *dest0;
2268
   u_int i, rows;
2269
   int bg;
2270
 
2271
   dest0 = p->screen_base+sy*p->fontheight*p->next_line+sx;
2272
 
2273
   bg = attr_bgcol_ec(p,conp);
2274
   for (i = p->var.bits_per_pixel; i--; dest0 += p->next_plane) {
2275
      dest = dest0;
2276
      for (rows = height*p->fontheight; rows--; dest += p->next_line)
2277
         if (bg & 1)
2278
            mymemset(dest, width);
2279
         else
2280
            mymemclear(dest, width);
2281
      bg >>= 1;
2282
   }
2283
}
2284
 
2285
 
2286
static void putc_plan(struct vc_data *conp, struct display *p, int c, int y,
2287
                      int x)
2288
{
2289
   u_char *dest, *dest0, *cdat, *cdat0;
2290
   u_int rows, i;
2291
   u_char d;
2292
   int fg, bg;
2293
 
2294
   c &= 0xff;
2295
 
2296
   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
2297
   cdat0 = p->fontdata+c*p->fontheight;
2298
   fg = attr_fgcol(p,conp);
2299
   bg = attr_bgcol(p,conp);
2300
 
2301
   for (i = p->var.bits_per_pixel; i--; dest0 += p->next_plane) {
2302
      dest = dest0;
2303
      cdat = cdat0;
2304
      for (rows = p->fontheight; rows--; dest += p->next_line) {
2305
         d = *cdat++;
2306
         if (bg & 1)
2307
            if (fg & 1)
2308
               *dest = 0xff;
2309
            else
2310
               *dest = ~d;
2311
         else
2312
            if (fg & 1)
2313
               *dest = d;
2314
            else
2315
               *dest = 0x00;
2316
      }
2317
      bg >>= 1;
2318
      fg >>= 1;
2319
   }
2320
}
2321
 
2322
 
2323
/*
2324
 *    I split the console character loop in two parts
2325
 *    (cfr. fbcon_putcs_ilbm())
2326
 */
2327
 
2328
static void putcs_plan(struct vc_data *conp, struct display *p, const char *s,
2329
                       int count, int y, int x)
2330
{
2331
   u_char *dest, *dest0, *dest1;
2332
   u_char *cdat1, *cdat2, *cdat3, *cdat4, *cdat10, *cdat20, *cdat30, *cdat40;
2333
   u_int rows, i;
2334
   u_char c1, c2, c3, c4;
2335
   u_long d;
2336
   int fg0, bg0, fg, bg;
2337
 
2338
   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
2339
   fg0 = attr_fgcol(p,conp);
2340
   bg0 = attr_bgcol(p,conp);
2341
 
2342
   while (count--)
2343
      if (x&3 || count < 3) {   /* Slow version */
2344
         c1 = *s++;
2345
         dest1 = dest0++;
2346
         x++;
2347
 
2348
         cdat10 = p->fontdata+c1*p->fontheight;
2349
         fg = fg0;
2350
         bg = bg0;
2351
 
2352
         for (i = p->var.bits_per_pixel; i--; dest1 += p->next_plane) {
2353
            dest = dest1;
2354
            cdat1 = cdat10;
2355
            for (rows = p->fontheight; rows--; dest += p->next_line) {
2356
               d = *cdat1++;
2357
               if (bg & 1)
2358
                  if (fg & 1)
2359
                     *dest = 0xff;
2360
                  else
2361
                     *dest = ~d;
2362
               else
2363
                  if (fg & 1)
2364
                     *dest = d;
2365
                  else
2366
                     *dest = 0x00;
2367
            }
2368
            bg >>= 1;
2369
            fg >>= 1;
2370
         }
2371
      } else {                      /* Fast version */
2372
         c1 = s[0];
2373
         c2 = s[1];
2374
         c3 = s[2];
2375
         c4 = s[3];
2376
 
2377
         dest1 = dest0;
2378
         cdat10 = p->fontdata+c1*p->fontheight;
2379
         cdat20 = p->fontdata+c2*p->fontheight;
2380
         cdat30 = p->fontdata+c3*p->fontheight;
2381
         cdat40 = p->fontdata+c4*p->fontheight;
2382
         fg = fg0;
2383
         bg = bg0;
2384
 
2385
         for (i = p->var.bits_per_pixel; i--; dest1 += p->next_plane) {
2386
            dest = dest1;
2387
            cdat1 = cdat10;
2388
            cdat2 = cdat20;
2389
            cdat3 = cdat30;
2390
            cdat4 = cdat40;
2391
            for (rows = p->fontheight; rows--; dest += p->next_line) {
2392
               d = *cdat1++<<24 | *cdat2++<<16 | *cdat3++<<8 | *cdat4++;
2393
               if (bg & 1)
2394
                  if (fg & 1)
2395
                     *(u_long *)dest = 0xffffffff;
2396
                  else
2397
                     *(u_long *)dest = ~d;
2398
               else
2399
                  if (fg & 1)
2400
                     *(u_long *)dest = d;
2401
                  else
2402
                     *(u_long *)dest = 0x00000000;
2403
            }
2404
            bg >>= 1;
2405
            fg >>= 1;
2406
         }
2407
         s += 4;
2408
         dest0 += 4;
2409
         x += 4;
2410
         count -= 3;
2411
      }
2412
}
2413
 
2414
 
2415
static void rev_char_plan(struct display *p, int x, int y)
2416
{
2417
   u_char *dest, *dest0;
2418
   u_int rows, i;
2419
   int mask;
2420
 
2421
   dest0 = p->screen_base+y*p->fontheight*p->next_line+x;
2422
   mask = p->fgcol ^ p->bgcol;
2423
 
2424
   /*
2425
    *    This should really obey the individual character's
2426
    *    background and foreground colors instead of simply
2427
    *    inverting.
2428
    */
2429
 
2430
   for (i = p->var.bits_per_pixel; i--; dest0 += p->next_plane) {
2431
      if (mask & 1) {
2432
         dest = dest0;
2433
         for (rows = p->fontheight; rows--; dest += p->next_line)
2434
            *dest = ~*dest;
2435
      }
2436
      mask >>= 1;
2437
   }
2438
}
2439
 
2440
#endif /* CONFIG_FBCON_PLANES */
2441
 
2442
 
2443
/* ====================================================================== */
2444
 
2445
#ifdef CONFIG_FBCON_2PLANE
2446
 
2447
   /*
2448
    *    2 Planes (2-bytes interleave)
2449
    */
2450
 
2451
/* Increment/decrement 2 plane addresses */
2452
 
2453
#define INC_2P(p)       do { if (!((long)(++(p)) & 1)) (p) += 2; } while(0)
2454
#define DEC_2P(p)       do { if ((long)(--(p)) & 1) (p) -= 2; } while(0)
2455
 
2456
/* Convert a standard 4 bit color to our 2 bit color assignment:
2457
 * If at least two RGB channels are active, the low bit is turned on;
2458
 * The intensity bit (b3) is shifted into b1.
2459
 */
2460
 
2461
#define COLOR_2P(c)     (((c & 7) >= 3 && (c & 7) != 4) | (c & 8) >> 2)
2462
 
2463
 
2464
static void bmove_2_plane(struct display *p, int sy, int sx, int dy, int dx,
2465
                          int height, int width)
2466
{
2467
        /* bmove() has to distinguish two major cases: If both, source and
2468
         * destination, start at even addresses or both are at odd
2469
         * addresses, just the first odd and last even column (if present)
2470
         * require special treatment (memmove_col()). The rest between
2471
         * then can be copied by normal operations, because all adjacent
2472
         * bytes are affected and are to be stored in the same order.
2473
         *   The pathological case is when the move should go from an odd
2474
         * address to an even or vice versa. Since the bytes in the plane
2475
         * words must be assembled in new order, it seems wisest to make
2476
         * all movements by memmove_col().
2477
         */
2478
 
2479
    if (sx == 0 && dx == 0 && width == p->next_line/2) {
2480
                /* Special (but often used) case: Moving whole lines can be
2481
                 * done with memmove()
2482
                 */
2483
                mymemmove(p->screen_base + dy * p->next_line * p->fontheight,
2484
                                   p->screen_base + sy * p->next_line * p->fontheight,
2485
                                   p->next_line * height * p->fontheight);
2486
    } else {
2487
        int rows, cols;
2488
        u_char *src;
2489
        u_char *dst;
2490
        int bytes = p->next_line;
2491
        int linesize = bytes * p->fontheight;
2492
                       u_int colsize  = height * p->fontheight;
2493
                       u_int upwards  = (dy < sy) || (dy == sy && dx < sx);
2494
 
2495
                if ((sx & 1) == (dx & 1)) {
2496
                        /* odd->odd or even->even */
2497
 
2498
                        if (upwards) {
2499
 
2500
                                src = p->screen_base + sy * linesize + (sx>>1)*4 + (sx & 1);
2501
                                dst = p->screen_base + dy * linesize + (dx>>1)*4 + (dx & 1);
2502
 
2503
                                if (sx & 1) {
2504
                                        memmove_2p_col(dst, src, colsize, bytes);
2505
                                        src += 3;
2506
                                        dst += 3;
2507
                                        --width;
2508
                                }
2509
 
2510
                                if (width > 1) {
2511
                                        for(rows = colsize; rows > 0; --rows) {
2512
                                                mymemmove(dst, src, (width>>1)*4);
2513
                                                src += bytes;
2514
                                                dst += bytes;
2515
                                        }
2516
                                }
2517
 
2518
                                if (width & 1) {
2519
                                        src -= colsize * bytes;
2520
                                        dst -= colsize * bytes;
2521
                                        memmove_2p_col(dst + (width>>1)*4, src + (width>>1)*4,
2522
                                                                        colsize, bytes);
2523
                                }
2524
                        }
2525
                        else {
2526
 
2527
                                if (!((sx+width-1) & 1)) {
2528
                                        src = p->screen_base + sy * linesize + ((sx+width-1)>>1)*4;
2529
                                        dst = p->screen_base + dy * linesize + ((dx+width-1)>>1)*4;
2530
                                        memmove_2p_col(dst, src, colsize, bytes);
2531
                                        --width;
2532
                                }
2533
 
2534
                                src = p->screen_base + sy * linesize + (sx>>1)*4 + (sx & 1);
2535
                                dst = p->screen_base + dy * linesize + (dx>>1)*4 + (dx & 1);
2536
 
2537
                                if (width > 1) {
2538
                                        src += colsize * bytes + (sx & 1)*3;
2539
                                        dst += colsize * bytes + (sx & 1)*3;
2540
                                        for(rows = colsize; rows > 0; --rows) {
2541
                                                src -= bytes;
2542
                                                dst -= bytes;
2543
                                                mymemmove(dst, src, (width>>1)*4);
2544
                                        }
2545
                                }
2546
 
2547
                                if (width & 1) {
2548
                                        memmove_2p_col(dst-3, src-3, colsize, bytes);
2549
                                }
2550
 
2551
                        }
2552
                }
2553
                else {
2554
                        /* odd->even or even->odd */
2555
 
2556
                        if (upwards) {
2557
                                src = p->screen_base + sy * linesize + (sx>>1)*4 + (sx & 1);
2558
                                dst = p->screen_base + dy * linesize + (dx>>1)*4 + (dx & 1);
2559
                                for(cols = width; cols > 0; --cols) {
2560
                                        memmove_2p_col(dst, src, colsize, bytes);
2561
                                        INC_2P(src);
2562
                                        INC_2P(dst);
2563
                                }
2564
                        }
2565
                        else {
2566
                                sx += width-1;
2567
                                dx += width-1;
2568
                                src = p->screen_base + sy * linesize + (sx>>1)*4 + (sx & 1);
2569
                                dst = p->screen_base + dy * linesize + (dx>>1)*4 + (dx & 1);
2570
                                for(cols = width; cols > 0; --cols) {
2571
                                        memmove_2p_col(dst, src, colsize, bytes);
2572
                                        DEC_2P(src);
2573
                                        DEC_2P(dst);
2574
                                }
2575
                        }
2576
                }
2577
 
2578
 
2579
    }
2580
}
2581
 
2582
 
2583
static void clear_2_plane(struct vc_data *conp, struct display *p, int sy,
2584
                          int sx, int height, int width)
2585
{
2586
    ulong offset;
2587
    u_char *start;
2588
    int rows;
2589
    int bytes = p->next_line;
2590
    int lines = height * p->fontheight;
2591
    ulong  size;
2592
        u_long          cval;
2593
        u_short                 pcval;
2594
 
2595
    cval = expand2l (COLOR_2P (attr_bgcol_ec(p,conp)));
2596
 
2597
    if (sx == 0 && width == bytes/2) {
2598
 
2599
        offset = sy * bytes * p->fontheight;
2600
        size   = lines * bytes;
2601
                memset_even_2p(p->screen_base+offset, size, cval);
2602
 
2603
    } else {
2604
 
2605
        offset = (sy * bytes * p->fontheight) + (sx>>1)*4 + (sx & 1);
2606
                start = p->screen_base + offset;
2607
                pcval = expand2w(COLOR_2P(attr_bgcol_ec(p,conp)));
2608
 
2609
                /* Clears are split if the region starts at an odd column or
2610
                 * end at an even column. These extra columns are spread
2611
                 * across the interleaved planes. All in between can be
2612
                 * cleared by normal mymemclear_small(), because both bytes of
2613
                 * the single plane words are affected.
2614
                 */
2615
 
2616
                if (sx & 1) {
2617
                        memclear_2p_col(start, lines, pcval, bytes);
2618
                        start += 3;
2619
                        width--;
2620
                }
2621
 
2622
                if (width & 1) {
2623
                        memclear_2p_col(start + (width>>1)*4, lines, pcval, bytes);
2624
                        width--;
2625
                }
2626
 
2627
                if (width) {
2628
                        for(rows = lines; rows-- ; start += bytes)
2629
                                memset_even_2p(start, width*2, cval);
2630
                }
2631
    }
2632
}
2633
 
2634
 
2635
static void putc_2_plane(struct vc_data *conp, struct display *p, int c, int y,
2636
                         int x)
2637
{
2638
   u_char   *dest;
2639
    u_char   *cdat;
2640
    int rows;
2641
    int bytes = p->next_line;
2642
        ulong                     eorx, fgx, bgx, fdx;
2643
 
2644
        c &= 0xff;
2645
 
2646
    dest  = p->screen_base + y * p->fontheight * bytes + (x>>1)*4 + (x & 1);
2647
    cdat  = p->fontdata + (c * p->fontheight);
2648
 
2649
        fgx   = expand2w(COLOR_2P(attr_fgcol(p,conp)));
2650
        bgx   = expand2w(COLOR_2P(attr_bgcol(p,conp)));
2651
        eorx  = fgx ^ bgx;
2652
 
2653
    for(rows = p->fontheight ; rows-- ; dest += bytes) {
2654
                fdx = dup2w(*cdat++);
2655
                __asm__ __volatile__ ("movepw %1,%0@(0)" : /* no outputs */
2656
                                                           : "a" (dest), "d" ((fdx & eorx) ^ bgx));
2657
        }
2658
}
2659
 
2660
 
2661
static void putcs_2_plane(struct vc_data *conp, struct display *p,
2662
                          const char *s, int count, int y, int x)
2663
{
2664
        u_char   *dest, *dest0;
2665
    u_char   *cdat, c;
2666
    int rows;
2667
    int bytes;
2668
        ulong                     eorx, fgx, bgx, fdx;
2669
 
2670
    bytes = p->next_line;
2671
    dest0 = p->screen_base + y * p->fontheight * bytes + (x>>1)*4 + (x & 1);
2672
        fgx   = expand2w(COLOR_2P(attr_fgcol(p,conp)));
2673
        bgx   = expand2w(COLOR_2P(attr_bgcol(p,conp)));
2674
        eorx  = fgx ^ bgx;
2675
 
2676
        while (count--) {
2677
 
2678
                c = *s++;
2679
                cdat  = p->fontdata + (c * p->fontheight);
2680
 
2681
                for(rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
2682
                        fdx = dup2w(*cdat++);
2683
                        __asm__ __volatile__ ("movepw %1,%0@(0)" : /* no outputs */
2684
                                                                   : "a" (dest), "d" ((fdx & eorx) ^ bgx));
2685
                }
2686
                INC_2P(dest0);
2687
        }
2688
}
2689
 
2690
 
2691
static void rev_char_2_plane(struct display *p, int x, int y)
2692
{
2693
   u_char *dest;
2694
   int j;
2695
   int bytes;
2696
 
2697
   dest = p->screen_base + y * p->fontheight * p->next_line + (x>>1)*4 + (x & 1);
2698
   j = p->fontheight;
2699
   bytes = p->next_line;
2700
   while (j--)
2701
     {
2702
      /* This should really obey the individual character's
2703
       * background and foreground colors instead of simply
2704
       * inverting.
2705
       */
2706
       dest[0] = ~dest[0];
2707
       dest[2] = ~dest[2];
2708
       dest += bytes;
2709
     }
2710
}
2711
#endif /* CONFIG_FBCON_2PLANE */
2712
 
2713
 
2714
/* ====================================================================== */
2715
 
2716
#ifdef CONFIG_FBCON_4PLANE
2717
 
2718
   /*
2719
    *    4 Planes (2-bytes interleave)
2720
    */
2721
 
2722
/* Increment/decrement 4 plane addresses */
2723
 
2724
#define INC_4P(p)       do { if (!((long)(++(p)) & 1)) (p) += 6; } while(0)
2725
#define DEC_4P(p)       do { if ((long)(--(p)) & 1) (p) -= 6; } while(0)
2726
 
2727
 
2728
static void bmove_4_plane(struct display *p, int sy, int sx, int dy, int dx,
2729
                          int height, int width)
2730
{
2731
        /* bmove() has to distinguish two major cases: If both, source and
2732
         * destination, start at even addresses or both are at odd
2733
         * addresses, just the first odd and last even column (if present)
2734
         * require special treatment (memmove_col()). The rest between
2735
         * then can be copied by normal operations, because all adjacent
2736
         * bytes are affected and are to be stored in the same order.
2737
         *   The pathological case is when the move should go from an odd
2738
         * address to an even or vice versa. Since the bytes in the plane
2739
         * words must be assembled in new order, it seems wisest to make
2740
         * all movements by memmove_col().
2741
         */
2742
 
2743
    if (sx == 0 && dx == 0 && width == p->next_line/4) {
2744
                /* Special (but often used) case: Moving whole lines can be
2745
                 * done with memmove()
2746
                 */
2747
                mymemmove(p->screen_base + dy * p->next_line * p->fontheight,
2748
                                   p->screen_base + sy * p->next_line * p->fontheight,
2749
                                   p->next_line * height * p->fontheight);
2750
    } else {
2751
        int rows, cols;
2752
        u_char *src;
2753
        u_char *dst;
2754
        int bytes = p->next_line;
2755
        int linesize = bytes * p->fontheight;
2756
                       u_int colsize  = height * p->fontheight;
2757
                       u_int upwards  = (dy < sy) || (dy == sy && dx < sx);
2758
 
2759
                if ((sx & 1) == (dx & 1)) {
2760
                        /* odd->odd or even->even */
2761
 
2762
                        if (upwards) {
2763
 
2764
                                src = p->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1);
2765
                                dst = p->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1);
2766
 
2767
                                if (sx & 1) {
2768
                                        memmove_4p_col(dst, src, colsize, bytes);
2769
                                        src += 7;
2770
                                        dst += 7;
2771
                                        --width;
2772
                                }
2773
 
2774
                                if (width > 1) {
2775
                                        for(rows = colsize; rows > 0; --rows) {
2776
                                                mymemmove(dst, src, (width>>1)*8);
2777
                                                src += bytes;
2778
                                                dst += bytes;
2779
                                        }
2780
                                }
2781
 
2782
                                if (width & 1) {
2783
                                        src -= colsize * bytes;
2784
                                        dst -= colsize * bytes;
2785
                                        memmove_4p_col(dst + (width>>1)*8, src + (width>>1)*8,
2786
                                                                        colsize, bytes);
2787
                                }
2788
                        }
2789
                        else {
2790
 
2791
                                if (!((sx+width-1) & 1)) {
2792
                                        src = p->screen_base + sy * linesize + ((sx+width-1)>>1)*8;
2793
                                        dst = p->screen_base + dy * linesize + ((dx+width-1)>>1)*8;
2794
                                        memmove_4p_col(dst, src, colsize, bytes);
2795
                                        --width;
2796
                                }
2797
 
2798
                                src = p->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1);
2799
                                dst = p->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1);
2800
 
2801
                                if (width > 1) {
2802
                                        src += colsize * bytes + (sx & 1)*7;
2803
                                        dst += colsize * bytes + (sx & 1)*7;
2804
                                        for(rows = colsize; rows > 0; --rows) {
2805
                                                src -= bytes;
2806
                                                dst -= bytes;
2807
                                                mymemmove(dst, src, (width>>1)*8);
2808
                                        }
2809
                                }
2810
 
2811
                                if (width & 1) {
2812
                                        memmove_4p_col(dst-7, src-7, colsize, bytes);
2813
                                }
2814
 
2815
                        }
2816
                }
2817
                else {
2818
                        /* odd->even or even->odd */
2819
 
2820
                        if (upwards) {
2821
                                src = p->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1);
2822
                                dst = p->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1);
2823
                                for(cols = width; cols > 0; --cols) {
2824
                                        memmove_4p_col(dst, src, colsize, bytes);
2825
                                        INC_4P(src);
2826
                                        INC_4P(dst);
2827
                                }
2828
                        }
2829
                        else {
2830
                                sx += width-1;
2831
                                dx += width-1;
2832
                                src = p->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1);
2833
                                dst = p->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1);
2834
                                for(cols = width; cols > 0; --cols) {
2835
                                        memmove_4p_col(dst, src, colsize, bytes);
2836
                                        DEC_4P(src);
2837
                                        DEC_4P(dst);
2838
                                }
2839
                        }
2840
                }
2841
 
2842
 
2843
    }
2844
}
2845
 
2846
 
2847
static void clear_4_plane(struct vc_data *conp, struct display *p, int sy,
2848
                          int sx, int height, int width)
2849
{
2850
    ulong offset;
2851
    u_char *start;
2852
    int rows;
2853
    int bytes = p->next_line;
2854
    int lines = height * p->fontheight;
2855
    ulong  size;
2856
        u_long          cval1, cval2, pcval;
2857
 
2858
        expand4dl(attr_bgcol_ec(p,conp), &cval1, &cval2);
2859
 
2860
    if (sx == 0 && width == bytes/4) {
2861
 
2862
        offset = sy * bytes * p->fontheight;
2863
        size   = lines * bytes;
2864
                memset_even_4p(p->screen_base+offset, size, cval1, cval2);
2865
 
2866
    } else {
2867
 
2868
        offset = (sy * bytes * p->fontheight) + (sx>>1)*8 + (sx & 1);
2869
                start = p->screen_base + offset;
2870
                pcval = expand4l(attr_bgcol_ec(p,conp));
2871
 
2872
                /* Clears are split if the region starts at an odd column or
2873
                 * end at an even column. These extra columns are spread
2874
                 * across the interleaved planes. All in between can be
2875
                 * cleared by normal mymemclear_small(), because both bytes of
2876
                 * the single plane words are affected.
2877
                 */
2878
 
2879
                if (sx & 1) {
2880
                        memclear_4p_col(start, lines, pcval, bytes);
2881
                        start += 7;
2882
                        width--;
2883
                }
2884
 
2885
                if (width & 1) {
2886
                        memclear_4p_col(start + (width>>1)*8, lines, pcval, bytes);
2887
                        width--;
2888
                }
2889
 
2890
                if (width) {
2891
                        for(rows = lines; rows-- ; start += bytes)
2892
                                memset_even_4p(start, width*4, cval1, cval2);
2893
                }
2894
    }
2895
}
2896
 
2897
 
2898
static void putc_4_plane(struct vc_data *conp, struct display *p, int c, int y,
2899
                         int x)
2900
{
2901
        u_char   *dest;
2902
    u_char   *cdat;
2903
    int rows;
2904
    int bytes = p->next_line;
2905
        ulong                     eorx, fgx, bgx, fdx;
2906
 
2907
        c &= 0xff;
2908
 
2909
    dest  = p->screen_base + y * p->fontheight * bytes + (x>>1)*8 + (x & 1);
2910
    cdat  = p->fontdata + (c * p->fontheight);
2911
 
2912
        fgx   = expand4l(attr_fgcol(p,conp));
2913
        bgx   = expand4l(attr_bgcol(p,conp));
2914
        eorx  = fgx ^ bgx;
2915
 
2916
    for(rows = p->fontheight ; rows-- ; dest += bytes) {
2917
                fdx = dup4l(*cdat++);
2918
                __asm__ __volatile__ ("movepl %1,%0@(0)" : /* no outputs */
2919
                                                           : "a" (dest), "d" ((fdx & eorx) ^ bgx));
2920
        }
2921
}
2922
 
2923
 
2924
static void putcs_4_plane(struct vc_data *conp, struct display *p,
2925
                          const char *s, int count, int y, int x)
2926
{
2927
        u_char   *dest, *dest0;
2928
    u_char   *cdat, c;
2929
    int rows;
2930
    int bytes;
2931
        ulong                     eorx, fgx, bgx, fdx;
2932
 
2933
    bytes = p->next_line;
2934
    dest0 = p->screen_base + y * p->fontheight * bytes + (x>>1)*8 + (x & 1);
2935
        fgx   = expand4l(attr_fgcol(p,conp));
2936
        bgx   = expand4l(attr_bgcol(p,conp));
2937
        eorx  = fgx ^ bgx;
2938
 
2939
        while (count--) {
2940
 
2941
                /* I think, unrolling the loops like in the 1 plane case isn't
2942
                 * practicable here, because the body is much longer for 4
2943
                 * planes (mostly the dup4l()). I guess, unrolling this would
2944
                 * need more than 256 bytes and so exceed the instruction
2945
                 * cache :-(
2946
                 */
2947
 
2948
                c = *s++;
2949
                cdat  = p->fontdata + (c * p->fontheight);
2950
 
2951
                for(rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
2952
                        fdx = dup4l(*cdat++);
2953
                        __asm__ __volatile__ ("movepl %1,%0@(0)" : /* no outputs */
2954
                                                                   : "a" (dest), "d" ((fdx & eorx) ^ bgx));
2955
                }
2956
                INC_4P(dest0);
2957
        }
2958
}
2959
 
2960
 
2961
static void rev_char_4_plane(struct display *p, int x, int y)
2962
{
2963
   u_char *dest;
2964
   int j;
2965
   int bytes;
2966
 
2967
   dest = p->screen_base + y * p->fontheight * p->next_line + (x>>1)*8 + (x & 1);
2968
   j = p->fontheight;
2969
   bytes = p->next_line;
2970
 
2971
   while (j--)
2972
     {
2973
      /* This should really obey the individual character's
2974
       * background and foreground colors instead of simply
2975
       * inverting.
2976
       */
2977
       dest[0] = ~dest[0];
2978
       dest[2] = ~dest[2];
2979
       dest[4] = ~dest[4];
2980
       dest[6] = ~dest[6];
2981
       dest += bytes;
2982
     }
2983
}
2984
#endif /* CONFIG_FBCON_4PLANE */
2985
 
2986
 
2987
/* ====================================================================== */
2988
 
2989
#ifdef CONFIG_FBCON_8PLANE
2990
 
2991
   /*
2992
    *    8 Planes (2-bytes interleave)
2993
    */
2994
 
2995
/* In 8 plane mode, 256 colors would be possible, but only the first
2996
 * 16 are used by the console code (the upper 4 bits are
2997
 * background/unused). For that, the following functions mask off the
2998
 * higher 4 bits of each color.
2999
 */
3000
 
3001
/* Increment/decrement 8 plane addresses */
3002
 
3003
#define INC_8P(p)       do { if (!((long)(++(p)) & 1)) (p) += 14; } while(0)
3004
#define DEC_8P(p)       do { if ((long)(--(p)) & 1) (p) -= 14; } while(0)
3005
 
3006
 
3007
static void bmove_8_plane(struct display *p, int sy, int sx, int dy, int dx,
3008
                          int height, int width)
3009
{
3010
        /* bmove() has to distinguish two major cases: If both, source and
3011
         * destination, start at even addresses or both are at odd
3012
         * addresses, just the first odd and last even column (if present)
3013
         * require special treatment (memmove_col()). The rest between
3014
         * then can be copied by normal operations, because all adjacent
3015
         * bytes are affected and are to be stored in the same order.
3016
         *   The pathological case is when the move should go from an odd
3017
         * address to an even or vice versa. Since the bytes in the plane
3018
         * words must be assembled in new order, it seems wisest to make
3019
         * all movements by memmove_col().
3020
         */
3021
 
3022
    if (sx == 0 && dx == 0 && width == p->next_line/8) {
3023
                /* Special (but often used) case: Moving whole lines can be
3024
                 * done with memmove()
3025
                 */
3026
      fast_memmove (p->screen_base + dy * p->next_line * p->fontheight,
3027
                    p->screen_base + sy * p->next_line * p->fontheight,
3028
                    p->next_line * height * p->fontheight);
3029
    } else {
3030
        int rows, cols;
3031
        u_char *src;
3032
        u_char *dst;
3033
        int bytes = p->next_line;
3034
        int linesize = bytes * p->fontheight;
3035
                       u_int colsize  = height * p->fontheight;
3036
                       u_int upwards  = (dy < sy) || (dy == sy && dx < sx);
3037
 
3038
                if ((sx & 1) == (dx & 1)) {
3039
                        /* odd->odd or even->even */
3040
 
3041
                        if (upwards) {
3042
 
3043
                                src = p->screen_base + sy * linesize + (sx>>1)*16 + (sx & 1);
3044
                                dst = p->screen_base + dy * linesize + (dx>>1)*16 + (dx & 1);
3045
 
3046
                                if (sx & 1) {
3047
                                        memmove_8p_col(dst, src, colsize, bytes);
3048
                                        src += 15;
3049
                                        dst += 15;
3050
                                        --width;
3051
                                }
3052
 
3053
                                if (width > 1) {
3054
                                        for(rows = colsize; rows > 0; --rows) {
3055
                                                fast_memmove (dst, src, (width >> 1) * 16);
3056
                                                src += bytes;
3057
                                                dst += bytes;
3058
                                        }
3059
                                }
3060
 
3061
                                if (width & 1) {
3062
                                        src -= colsize * bytes;
3063
                                        dst -= colsize * bytes;
3064
                                        memmove_8p_col(dst + (width>>1)*16, src + (width>>1)*16,
3065
                                                                        colsize, bytes);
3066
                                }
3067
                        }
3068
                        else {
3069
 
3070
                                if (!((sx+width-1) & 1)) {
3071
                                        src = p->screen_base + sy * linesize + ((sx+width-1)>>1)*16;
3072
                                        dst = p->screen_base + dy * linesize + ((dx+width-1)>>1)*16;
3073
                                        memmove_8p_col(dst, src, colsize, bytes);
3074
                                        --width;
3075
                                }
3076
 
3077
                                src = p->screen_base + sy * linesize + (sx>>1)*16 + (sx & 1);
3078
                                dst = p->screen_base + dy * linesize + (dx>>1)*16 + (dx & 1);
3079
 
3080
                                if (width > 1) {
3081
                                        src += colsize * bytes + (sx & 1)*15;
3082
                                        dst += colsize * bytes + (sx & 1)*15;
3083
                                        for(rows = colsize; rows > 0; --rows) {
3084
                                                src -= bytes;
3085
                                                dst -= bytes;
3086
                                                fast_memmove (dst, src, (width>>1)*16);
3087
                                        }
3088
                                }
3089
 
3090
                                if (width & 1) {
3091
                                        memmove_8p_col(dst-15, src-15, colsize, bytes);
3092
                                }
3093
 
3094
                        }
3095
                }
3096
                else {
3097
                        /* odd->even or even->odd */
3098
 
3099
                        if (upwards) {
3100
                                src = p->screen_base + sy * linesize + (sx>>1)*16 + (sx & 1);
3101
                                dst = p->screen_base + dy * linesize + (dx>>1)*16 + (dx & 1);
3102
                                for(cols = width; cols > 0; --cols) {
3103
                                        memmove_8p_col(dst, src, colsize, bytes);
3104
                                        INC_8P(src);
3105
                                        INC_8P(dst);
3106
                                }
3107
                        }
3108
                        else {
3109
                                sx += width-1;
3110
                                dx += width-1;
3111
                                src = p->screen_base + sy * linesize + (sx>>1)*16 + (sx & 1);
3112
                                dst = p->screen_base + dy * linesize + (dx>>1)*16 + (dx & 1);
3113
                                for(cols = width; cols > 0; --cols) {
3114
                                        memmove_8p_col(dst, src, colsize, bytes);
3115
                                        DEC_8P(src);
3116
                                        DEC_8P(dst);
3117
                                }
3118
                        }
3119
                }
3120
 
3121
 
3122
    }
3123
}
3124
 
3125
 
3126
static void clear_8_plane(struct vc_data *conp, struct display *p, int sy,
3127
                          int sx, int height, int width)
3128
{
3129
    ulong offset;
3130
    u_char *start;
3131
    int rows;
3132
    int bytes = p->next_line;
3133
    int lines = height * p->fontheight;
3134
    ulong  size;
3135
        u_long          cval1, cval2, cval3, cval4, pcval1, pcval2;
3136
 
3137
        expand8ql(attr_bgcol_ec(p,conp), cval1, cval2, cval3, cval4);
3138
 
3139
    if (sx == 0 && width == bytes/8) {
3140
 
3141
        offset = sy * bytes * p->fontheight;
3142
        size   = lines * bytes;
3143
                memset_even_8p(p->screen_base+offset, size, cval1, cval2, cval3, cval4);
3144
 
3145
    } else {
3146
 
3147
        offset = (sy * bytes * p->fontheight) + (sx>>1)*16 + (sx & 1);
3148
                start = p->screen_base + offset;
3149
                expand8dl(attr_bgcol_ec(p,conp), &pcval1, &pcval2);
3150
 
3151
                /* Clears are split if the region starts at an odd column or
3152
                 * end at an even column. These extra columns are spread
3153
                 * across the interleaved planes. All in between can be
3154
                 * cleared by normal mymemclear_small(), because both bytes of
3155
                 * the single plane words are affected.
3156
                 */
3157
 
3158
                if (sx & 1) {
3159
                        memclear_8p_col(start, lines, pcval1, pcval2, bytes);
3160
                        start += 7;
3161
                        width--;
3162
                }
3163
 
3164
                if (width & 1) {
3165
                        memclear_8p_col(start + (width>>1)*16, lines, pcval1,
3166
                                                         pcval2, bytes);
3167
                        width--;
3168
                }
3169
 
3170
                if (width) {
3171
                        for(rows = lines; rows-- ; start += bytes)
3172
                                memset_even_8p(start, width*8, cval1, cval2, cval3, cval4);
3173
                }
3174
    }
3175
}
3176
 
3177
 
3178
static void putc_8_plane(struct vc_data *conp, struct display *p, int c, int y,
3179
                         int x)
3180
{
3181
        u_char   *dest;
3182
    u_char   *cdat;
3183
    int rows;
3184
    int bytes = p->next_line;
3185
        ulong                     eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx;
3186
 
3187
        c &= 0xff;
3188
 
3189
    dest  = p->screen_base + y * p->fontheight * bytes + (x>>1)*16 + (x & 1);
3190
    cdat  = p->fontdata + (c * p->fontheight);
3191
 
3192
        expand8dl(attr_fgcol(p,conp), &fgx1, &fgx2);
3193
        expand8dl(attr_bgcol(p,conp), &bgx1, &bgx2);
3194
        eorx1  = fgx1 ^ bgx1; eorx2  = fgx2 ^ bgx2;
3195
 
3196
    for(rows = p->fontheight ; rows-- ; dest += bytes) {
3197
                fdx = dup4l(*cdat++);
3198
                __asm__ __volatile__
3199
                        ("movepl %1,%0@(0)\n\t"
3200
                          "movepl %2,%0@(8)"
3201
                          : /* no outputs */
3202
                          : "a" (dest), "d" ((fdx & eorx1) ^ bgx1),
3203
                            "d" ((fdx & eorx2) ^ bgx2)
3204
                        );
3205
        }
3206
}
3207
 
3208
 
3209
static void putcs_8_plane(struct vc_data *conp, struct display *p,
3210
                          const char *s, int count, int y, int x)
3211
{
3212
        u_char   *dest, *dest0;
3213
    u_char   *cdat, c;
3214
    int rows;
3215
    int bytes;
3216
        ulong                     eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx;
3217
 
3218
    bytes = p->next_line;
3219
    dest0 = p->screen_base + y * p->fontheight * bytes + (x>>1)*16 + (x & 1);
3220
 
3221
        expand8dl(attr_fgcol(p,conp), &fgx1, &fgx2);
3222
        expand8dl(attr_bgcol(p,conp), &bgx1, &bgx2);
3223
        eorx1  = fgx1 ^ bgx1; eorx2  = fgx2 ^ bgx2;
3224
 
3225
        while (count--) {
3226
 
3227
                /* I think, unrolling the loops like in the 1 plane case isn't
3228
                 * practicable here, because the body is much longer for 4
3229
                 * planes (mostly the dup4l()). I guess, unrolling this would
3230
                 * need more than 256 bytes and so exceed the instruction
3231
                 * cache :-(
3232
                 */
3233
 
3234
                c = *s++;
3235
                cdat  = p->fontdata + (c * p->fontheight);
3236
 
3237
                for(rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
3238
                        fdx = dup4l(*cdat++);
3239
                        __asm__ __volatile__
3240
                                ("movepl %1,%0@(0)\n\t"
3241
                                  "movepl %2,%0@(8)"
3242
                                  : /* no outputs */
3243
                                  : "a" (dest), "d" ((fdx & eorx1) ^ bgx1),
3244
                                  "d" ((fdx & eorx2) ^ bgx2)
3245
                                );
3246
                }
3247
                INC_8P(dest0);
3248
        }
3249
}
3250
 
3251
 
3252
static void rev_char_8_plane(struct display *p, int x, int y)
3253
{
3254
   u_char *dest;
3255
   int j;
3256
   int bytes;
3257
 
3258
   dest = p->screen_base + y * p->fontheight * p->next_line + (x>>1)*16 + (x & 1);
3259
   j = p->fontheight;
3260
   bytes = p->next_line;
3261
 
3262
   while (j--)
3263
     {
3264
      /* This should really obey the individual character's
3265
       * background and foreground colors instead of simply
3266
       * inverting. For 8 plane mode, only the lower 4 bits of the
3267
       * color are inverted, because only that color registers have
3268
       * been set up.
3269
       */
3270
       dest[0] = ~dest[0];
3271
       dest[2] = ~dest[2];
3272
       dest[4] = ~dest[4];
3273
       dest[6] = ~dest[6];
3274
       dest += bytes;
3275
     }
3276
}
3277
#endif /* CONFIG_FBCON_8PLANE */
3278
 
3279
 
3280
/* ====================================================================== */
3281
 
3282
#ifdef CONFIG_FBCON_8PACKED
3283
 
3284
   /*
3285
    *    8 bpp Packed Pixels
3286
    */
3287
 
3288
static u_long nibbletab_8_packed[]={
3289
0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
3290
0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
3291
0xff000000,0xff0000ff,0xff00ff00,0xff00ffff,
3292
0xffff0000,0xffff00ff,0xffffff00,0xffffffff};
3293
 
3294
static void bmove_8_packed(struct display *p, int sy, int sx, int dy, int dx,
3295
                           int height, int width)
3296
{
3297
        int bytes = p->next_line, linesize = bytes * p->fontheight, rows;
3298
        u_char *src,*dst;
3299
 
3300
        if (sx == 0 && dx == 0 && width * 8 == bytes) {
3301
                mymemmove(p->screen_base + dy * linesize,
3302
                          p->screen_base + sy * linesize,
3303
                          height * linesize);
3304
        }
3305
        else {
3306
                if (dy < sy || (dy == sy && dx < sx)) {
3307
                        src = p->screen_base + sy * linesize + sx * 8;
3308
                        dst = p->screen_base + dy * linesize + dx * 8;
3309
                        for (rows = height * p->fontheight ; rows-- ;) {
3310
                                mymemmove(dst, src, width * 8);
3311
                                src += bytes;
3312
                                dst += bytes;
3313
                        }
3314
                }
3315
                else {
3316
                        src = p->screen_base + (sy+height) * linesize + sx * 8
3317
                                - bytes;
3318
                        dst = p->screen_base + (dy+height) * linesize + dx * 8
3319
                                - bytes;
3320
                        for (rows = height * p->fontheight ; rows-- ;) {
3321
                                mymemmove(dst, src, width * 8);
3322
                                src -= bytes;
3323
                                dst -= bytes;
3324
                        }
3325
                }
3326
        }
3327
}
3328
 
3329
 
3330
static void clear_8_packed(struct vc_data *conp, struct display *p, int sy,
3331
                           int sx, int height, int width)
3332
{
3333
        u_char *dest0,*dest;
3334
        int bytes=p->next_line,lines=height * p->fontheight, rows, i;
3335
        u_long bgx;
3336
 
3337
        dest = p->screen_base + sy * p->fontheight * bytes + sx * 8;
3338
 
3339
        bgx=attr_bgcol_ec(p,conp);
3340
        bgx |= (bgx << 8);
3341
        bgx |= (bgx << 16);
3342
 
3343
        if (sx == 0 && width * 8 == bytes) {
3344
                for (i = 0 ; i < lines * width ; i++) {
3345
                        ((u_long *)dest)[0]=bgx;
3346
                        ((u_long *)dest)[1]=bgx;
3347
                        dest+=8;
3348
                }
3349
        } else {
3350
                dest0=dest;
3351
                for (rows = lines; rows-- ; dest0 += bytes) {
3352
                        dest=dest0;
3353
                        for (i = 0 ; i < width ; i++) {
3354
                                ((u_long *)dest)[0]=bgx;
3355
                                ((u_long *)dest)[1]=bgx;
3356
                                dest+=8;
3357
                        }
3358
                }
3359
        }
3360
}
3361
 
3362
 
3363
static void putc_8_packed(struct vc_data *conp, struct display *p, int c, int y,
3364
                          int x)
3365
{
3366
        u_char *dest,*cdat;
3367
        int bytes=p->next_line,rows;
3368
        ulong eorx,fgx,bgx;
3369
 
3370
        c &= 0xff;
3371
 
3372
        dest = p->screen_base + y * p->fontheight * bytes + x * 8;
3373
        cdat = p->fontdata + c * p->fontheight;
3374
 
3375
        fgx=attr_fgcol(p,conp);
3376
        bgx=attr_bgcol(p,conp);
3377
        fgx |= (fgx << 8);
3378
        fgx |= (fgx << 16);
3379
        bgx |= (bgx << 8);
3380
        bgx |= (bgx << 16);
3381
        eorx = fgx ^ bgx;
3382
 
3383
        for (rows = p->fontheight ; rows-- ; dest += bytes) {
3384
                ((u_long *)dest)[0]=
3385
                        (nibbletab_8_packed[*cdat >> 4] & eorx) ^ bgx;
3386
                ((u_long *)dest)[1]=
3387
                        (nibbletab_8_packed[*cdat++ & 0xf] & eorx) ^ bgx;
3388
        }
3389
}
3390
 
3391
 
3392
static void putcs_8_packed(struct vc_data *conp, struct display *p,
3393
                           const char *s, int count, int y, int x)
3394
{
3395
        u_char *cdat, c, *dest, *dest0;
3396
        int rows,bytes=p->next_line;
3397
        u_long eorx, fgx, bgx;
3398
 
3399
        dest0 = p->screen_base + y * p->fontheight * bytes + x * 8;
3400
        fgx=attr_fgcol(p,conp);
3401
        bgx=attr_bgcol(p,conp);
3402
        fgx |= (fgx << 8);
3403
        fgx |= (fgx << 16);
3404
        bgx |= (bgx << 8);
3405
        bgx |= (bgx << 16);
3406
        eorx = fgx ^ bgx;
3407
        while (count--) {
3408
                c = *s++;
3409
                cdat = p->fontdata + c * p->fontheight;
3410
 
3411
                for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
3412
                        ((u_long *)dest)[0]=
3413
                        (nibbletab_8_packed[*cdat >> 4] & eorx) ^ bgx;
3414
                        ((u_long *)dest)[1]=
3415
                        (nibbletab_8_packed[*cdat++ & 0xf] & eorx) ^ bgx;
3416
                }
3417
                dest0+=8;
3418
        }
3419
}
3420
 
3421
 
3422
static void rev_char_8_packed(struct display *p, int x, int y)
3423
{
3424
        u_char *dest;
3425
        int bytes=p->next_line, rows;
3426
 
3427
        dest = p->screen_base + y * p->fontheight * bytes + x * 8;
3428
        for (rows = p->fontheight ; rows-- ; dest += bytes) {
3429
                ((u_long *)dest)[0] ^= 0x0f0f0f0f;
3430
                ((u_long *)dest)[1] ^= 0x0f0f0f0f;
3431
        }
3432
}
3433
 
3434
#endif /* CONFIG_FBCON_8PACKED */
3435
 
3436
 
3437
/* ====================================================================== */
3438
 
3439
#ifdef CONFIG_FBCON_16PACKED
3440
 
3441
   /*
3442
    *    16 bpp Packed Pixels
3443
    */
3444
 
3445
u_short packed16_cmap[16];
3446
 
3447
static u_long tab_16_packed[]={
3448
0x00000000,0x0000ffff,0xffff0000,0xffffffff};
3449
 
3450
static void bmove_16_packed(struct display *p, int sy, int sx, int dy, int dx,
3451
                            int height, int width)
3452
{
3453
        int bytes = p->next_line, linesize = bytes * p->fontheight, rows;
3454
        u_char *src,*dst;
3455
 
3456
        if (sx == 0 && dx == 0 && width * 16 == bytes) {
3457
                mymemmove(p->screen_base + dy * linesize,
3458
                          p->screen_base + sy * linesize,
3459
                          height * linesize);
3460
        }
3461
        else {
3462
                if (dy < sy || (dy == sy && dx < sx)) {
3463
                        src = p->screen_base + sy * linesize + sx * 16;
3464
                        dst = p->screen_base + dy * linesize + dx * 16;
3465
                        for (rows = height * p->fontheight ; rows-- ;) {
3466
                                mymemmove(dst, src, width * 16);
3467
                                src += bytes;
3468
                                dst += bytes;
3469
                        }
3470
                }
3471
                else {
3472
                        src = p->screen_base + (sy+height) * linesize + sx * 16
3473
                                - bytes;
3474
                        dst = p->screen_base + (dy+height) * linesize + dx * 16
3475
                                - bytes;
3476
                        for (rows = height * p->fontheight ; rows-- ;) {
3477
                                mymemmove(dst, src, width * 16);
3478
                                src -= bytes;
3479
                                dst -= bytes;
3480
                        }
3481
                }
3482
        }
3483
}
3484
 
3485
 
3486
static void clear_16_packed(struct vc_data *conp, struct display *p, int sy,
3487
                            int sx, int height, int width)
3488
{
3489
        u_char *dest0,*dest;
3490
        int bytes=p->next_line,lines=height * p->fontheight, rows, i;
3491
        u_long bgx;
3492
 
3493
        dest = p->screen_base + sy * p->fontheight * bytes + sx * 16;
3494
 
3495
        bgx = attr_bgcol_ec(p,conp);
3496
        bgx = packed16_cmap[bgx];
3497
        bgx |= (bgx << 16);
3498
 
3499
        if (sx == 0 && width * 16 == bytes) {
3500
                for (i = 0 ; i < lines * width ; i++) {
3501
                        ((u_long *)dest)[0]=bgx;
3502
                        ((u_long *)dest)[1]=bgx;
3503
                        ((u_long *)dest)[2]=bgx;
3504
                        ((u_long *)dest)[3]=bgx;
3505
                        dest+=16;
3506
                }
3507
        } else {
3508
                dest0=dest;
3509
                for (rows = lines; rows-- ; dest0 += bytes) {
3510
                        dest=dest0;
3511
                        for (i = 0 ; i < width ; i++) {
3512
                                ((u_long *)dest)[0]=bgx;
3513
                                ((u_long *)dest)[1]=bgx;
3514
                                ((u_long *)dest)[2]=bgx;
3515
                                ((u_long *)dest)[3]=bgx;
3516
                                dest+=16;
3517
                        }
3518
                }
3519
        }
3520
}
3521
 
3522
 
3523
static void putc_16_packed(struct vc_data *conp, struct display *p, int c,
3524
                           int y, int x)
3525
{
3526
        u_char *dest,*cdat;
3527
        int bytes=p->next_line,rows;
3528
        ulong eorx,fgx,bgx;
3529
 
3530
        c &= 0xff;
3531
 
3532
        dest = p->screen_base + y * p->fontheight * bytes + x * 16;
3533
        cdat = p->fontdata + c * p->fontheight;
3534
 
3535
        fgx = attr_fgcol(p,conp);
3536
        fgx = packed16_cmap[fgx];
3537
        bgx = attr_bgcol(p,conp);
3538
        bgx = packed16_cmap[bgx];
3539
        fgx |= (fgx << 16);
3540
        bgx |= (bgx << 16);
3541
        eorx = fgx ^ bgx;
3542
 
3543
        for (rows = p->fontheight ; rows-- ; dest += bytes) {
3544
                ((u_long *)dest)[0]=
3545
                        (tab_16_packed[*cdat >> 6] & eorx) ^ bgx;
3546
                ((u_long *)dest)[1]=
3547
                        (tab_16_packed[*cdat >> 4 & 0x3] & eorx) ^ bgx;
3548
                ((u_long *)dest)[2]=
3549
                        (tab_16_packed[*cdat >> 2 & 0x3] & eorx) ^ bgx;
3550
                ((u_long *)dest)[3]=
3551
                        (tab_16_packed[*cdat++ & 0x3] & eorx) ^ bgx;
3552
        }
3553
}
3554
 
3555
 
3556
/* TODO */
3557
static void putcs_16_packed(struct vc_data *conp, struct display *p,
3558
                            const char *s, int count, int y, int x)
3559
{
3560
        u_char *cdat, c, *dest, *dest0;
3561
        int rows,bytes=p->next_line;
3562
        u_long eorx, fgx, bgx;
3563
 
3564
        dest0 = p->screen_base + y * p->fontheight * bytes + x * 16;
3565
        fgx = attr_fgcol(p,conp);
3566
        fgx = packed16_cmap[fgx];
3567
        bgx = attr_bgcol(p,conp);
3568
        bgx = packed16_cmap[bgx];
3569
        fgx |= (fgx << 16);
3570
        bgx |= (bgx << 16);
3571
        eorx = fgx ^ bgx;
3572
        while (count--) {
3573
                c = *s++;
3574
                cdat = p->fontdata + c * p->fontheight;
3575
 
3576
                for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) {
3577
                        ((u_long *)dest)[0]=
3578
                                (tab_16_packed[*cdat >> 6] & eorx) ^ bgx;
3579
                        ((u_long *)dest)[1]=
3580
                                (tab_16_packed[*cdat >> 4 & 0x3] & eorx) ^ bgx;
3581
                        ((u_long *)dest)[2]=
3582
                                (tab_16_packed[*cdat >> 2 & 0x3] & eorx) ^ bgx;
3583
                        ((u_long *)dest)[3]=
3584
                                (tab_16_packed[*cdat++ & 0x3] & eorx) ^ bgx;
3585
                }
3586
                dest0+=16;
3587
        }
3588
}
3589
 
3590
 
3591
static void rev_char_16_packed(struct display *p, int x, int y)
3592
{
3593
        u_char *dest;
3594
        int bytes=p->next_line, rows;
3595
 
3596
        dest = p->screen_base + y * p->fontheight * bytes + x * 16;
3597
        for (rows = p->fontheight ; rows-- ; dest += bytes) {
3598
                ((u_long *)dest)[0] ^= 0xffffffff;
3599
                ((u_long *)dest)[1] ^= 0xffffffff;
3600
                ((u_long *)dest)[2] ^= 0xffffffff;
3601
                ((u_long *)dest)[3] ^= 0xffffffff;
3602
        }
3603
}
3604
 
3605
#endif /* CONFIG_FBCON_16PACKED */
3606
 
3607
 
3608
/* ====================================================================== */
3609
 
3610
#ifdef CONFIG_FBCON_CYBER
3611
 
3612
   /*
3613
    *    Cybervision (accelerated)
3614
    */
3615
 
3616
static void bmove_cyber(struct display *p, int sy, int sx, int dy, int dx,
3617
                        int height, int width)
3618
{
3619
        sx *= 8; dx *= 8; width *= 8;
3620
        Cyber_BitBLT((u_short)sx, (u_short)(sy*p->fontheight), (u_short)dx,
3621
                (u_short)(dy*p->fontheight), (u_short)width,
3622
                (u_short)(height*p->fontheight), (u_short)S3_NEW);
3623
}
3624
 
3625
 
3626
static void clear_cyber(struct vc_data *conp, struct display *p, int sy, int sx,
3627
                        int height, int width)
3628
{
3629
   u_char bg;
3630
 
3631
        sx *= 8; width *= 8;
3632
        bg = attr_bgcol_ec(p,conp);
3633
   Cyber_RectFill((u_short)sx, (u_short)(sy*p->fontheight), (u_short)width,
3634
                  (u_short)(height*p->fontheight), (u_short)S3_NEW,
3635
                  (u_short)bg);
3636
}
3637
 
3638
 
3639
static void putc_cyber(struct vc_data *conp, struct display *p, int c, int y,
3640
                       int x)
3641
{
3642
        u_char *dest, *cdat;
3643
        u_long tmp;
3644
        u_int rows, reverse, underline;
3645
        u_char d;
3646
   u_char fg, bg;
3647
 
3648
   c &= 0xff;
3649
 
3650
        dest = p->screen_base+y*p->fontheight*p->next_line+8*x;
3651
        cdat = p->fontdata+(c*p->fontheight);
3652
   fg = disp->fgcol;
3653
   bg = disp->bgcol;
3654
        reverse = conp->vc_reverse;
3655
        underline = conp->vc_underline;
3656
 
3657
   Cyber_WaitBlit();
3658
        for (rows = p->fontheight; rows--; dest += p->next_line) {
3659
                d = *cdat++;
3660
 
3661
                if (underline && !rows)
3662
                        d = 0xff;
3663
                if (reverse)
3664
                        d = ~d;
3665
 
3666
      tmp =  ((d & 0x80) ? fg : bg) << 24;
3667
      tmp |= ((d & 0x40) ? fg : bg) << 16;
3668
      tmp |= ((d & 0x20) ? fg : bg) << 8;
3669
      tmp |= ((d & 0x10) ? fg : bg);
3670
      *((u_long*) dest) = tmp;
3671
      tmp =  ((d & 0x8) ? fg : bg) << 24;
3672
      tmp |= ((d & 0x4) ? fg : bg) << 16;
3673
      tmp |= ((d & 0x2) ? fg : bg) << 8;
3674
      tmp |= ((d & 0x1) ? fg : bg);
3675
      *((u_long*) dest + 1) = tmp;
3676
        }
3677
}
3678
 
3679
 
3680
static void putcs_cyber(struct vc_data *conp, struct display *p, const char *s,
3681
                        int count, int y, int x)
3682
{
3683
        u_char *dest, *dest0, *cdat;
3684
   u_long tmp;
3685
        u_int rows, reverse, underline;
3686
        u_char c, d;
3687
   u_char fg, bg;
3688
 
3689
        dest0 = p->screen_base+y*p->fontheight*p->next_line+8*x;
3690
   fg = disp->fgcol;
3691
   bg = disp->bgcol;
3692
        reverse = conp->vc_reverse;
3693
        underline = conp->vc_underline;
3694
 
3695
   Cyber_WaitBlit();
3696
        while (count--) {
3697
                c = *s++;
3698
                dest = dest0;
3699
      dest0 += 8;
3700
                cdat = p->fontdata+(c*p->fontheight);
3701
                for (rows = p->fontheight; rows--; dest += p->next_line) {
3702
                        d = *cdat++;
3703
 
3704
                        if (underline && !rows)
3705
                                d = 0xff;
3706
                        if (reverse)
3707
                                d = ~d;
3708
 
3709
         tmp =  ((d & 0x80) ? fg : bg) << 24;
3710
         tmp |= ((d & 0x40) ? fg : bg) << 16;
3711
         tmp |= ((d & 0x20) ? fg : bg) << 8;
3712
         tmp |= ((d & 0x10) ? fg : bg);
3713
         *((u_long*) dest) = tmp;
3714
         tmp =  ((d & 0x8) ? fg : bg) << 24;
3715
         tmp |= ((d & 0x4) ? fg : bg) << 16;
3716
         tmp |= ((d & 0x2) ? fg : bg) << 8;
3717
         tmp |= ((d & 0x1) ? fg : bg);
3718
         *((u_long*) dest + 1) = tmp;
3719
                }
3720
        }
3721
}
3722
 
3723
 
3724
static void rev_char_cyber(struct display *p, int x, int y)
3725
{
3726
        u_char *dest;
3727
        u_int rows;
3728
   u_char fg, bg;
3729
 
3730
   fg = disp->fgcol;
3731
   bg = disp->bgcol;
3732
 
3733
        dest = p->screen_base+y*p->fontheight*p->next_line+8*x;
3734
   Cyber_WaitBlit();
3735
        for (rows = p->fontheight; rows--; dest += p->next_line) {
3736
                *dest = (*dest == fg) ? bg : fg;
3737
      *(dest+1) = (*(dest + 1) == fg) ? bg : fg;
3738
      *(dest+2) = (*(dest + 2) == fg) ? bg : fg;
3739
      *(dest+3) = (*(dest + 3) == fg) ? bg : fg;
3740
      *(dest+4) = (*(dest + 4) == fg) ? bg : fg;
3741
      *(dest+5) = (*(dest + 5) == fg) ? bg : fg;
3742
      *(dest+6) = (*(dest + 6) == fg) ? bg : fg;
3743
      *(dest+7) = (*(dest + 7) == fg) ? bg : fg;
3744
        }
3745
}
3746
 
3747
#endif /* CONFIG_FBCON_CYBER */
3748
 
3749
 
3750
/* ====================================================================== */
3751
 
3752
   /*
3753
    *    The console `switch' structure for the frame buffer based console
3754
    */
3755
 
3756
struct consw fb_con = {
3757
   fbcon_startup, fbcon_init, fbcon_deinit, fbcon_clear, fbcon_putc,
3758
   fbcon_putcs, fbcon_cursor, fbcon_scroll, fbcon_bmove, fbcon_switch,
3759
   fbcon_blank, fbcon_get_font, fbcon_set_font
3760
};

powered by: WebSVN 2.1.0

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