root/arch/m68k/console/fbcon.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. CURSOR_UNDRAWN
  2. fbcon_startup
  3. fbcon_init
  4. fbcon_deinit
  5. fbcon_changevar
  6. fbcon_setup
  7. mymemclear_small
  8. mymemclear
  9. mymemset
  10. mymemmove
  11. fast_memmove
  12. memclear_4p_col
  13. memset_even_4p
  14. memmove_4p_col
  15. expand4l
  16. expand4dl
  17. dup4l
  18. memclear_8p_col
  19. memset_even_8p
  20. memmove_8p_col
  21. expand8dl
  22. memclear_2p_col
  23. memset_even_2p
  24. memmove_2p_col
  25. expand2w
  26. expand2l
  27. dup2w
  28. real_y
  29. fbcon_clear
  30. fbcon_putc
  31. fbcon_putcs
  32. fbcon_cursor
  33. fbcon_vbl_handler
  34. fbcon_scroll
  35. fbcon_bmove
  36. fbcon_bmove_rec
  37. fbcon_switch
  38. fbcon_blank
  39. bmove_mono
  40. clear_mono
  41. putc_mono
  42. putcs_mono
  43. rev_char_mono
  44. bmove_ilbm
  45. clear_ilbm
  46. putc_ilbm
  47. putcs_ilbm
  48. rev_char_ilbm
  49. bmove_plan
  50. clear_plan
  51. putc_plan
  52. putcs_plan
  53. rev_char_plan
  54. bmove_2_plane
  55. clear_2_plane
  56. putc_2_plane
  57. putcs_2_plane
  58. rev_char_2_plane
  59. bmove_4_plane
  60. clear_4_plane
  61. putc_4_plane
  62. putcs_4_plane
  63. rev_char_4_plane
  64. bmove_8_plane
  65. clear_8_plane
  66. putc_8_plane
  67. putcs_8_plane
  68. rev_char_8_plane
  69. bmove_8_packed
  70. clear_8_packed
  71. putc_8_packed
  72. putcs_8_packed
  73. rev_char_8_packed
  74. bmove_16_packed
  75. clear_16_packed
  76. putc_16_packed
  77. putcs_16_packed
  78. rev_char_16_packed
  79. bmove_cyber
  80. clear_cyber
  81. putc_cyber
  82. putcs_cyber
  83. rev_char_cyber

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

/* [previous][next][first][last][top][bottom][index][help] */