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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [or32/] [console/] [fbcon.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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