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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [arch/] [m68knommu/] [console/] [fbcon.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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