linux-old/drivers/video/fbcon-sti.c
<<
>>
Prefs
   1/*
   2 * linux/drivers/video/fbcon-sti.c -- Low level frame buffer
   3 *      operations for generic HP video boards using STI (standard
   4 *      text interface) firmware
   5 *
   6 *  Based on linux/drivers/video/fbcon-artist.c
   7 *      Created 5 Apr 1997 by Geert Uytterhoeven
   8 *      Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
   9 *
  10 * This file is subject to the terms and conditions of the GNU General Public
  11 * License.  See the file COPYING in the main directory of this archive for
  12 * more details.  */
  13
  14#include <linux/module.h>
  15#include <linux/tty.h>
  16#include <linux/console.h>
  17#include <linux/string.h>
  18#include <linux/fb.h>
  19#include <linux/delay.h>
  20#include <asm/gsc.h>            /* for gsc_read/write */
  21#include <asm/types.h>
  22
  23#include <video/fbcon.h>
  24#include <video/fbcon-mfb.h>
  25
  26#include "sti/sticore.h"
  27
  28/* Translate an address as it would be found in a 2048x2048x1 bit frame
  29 * buffer into a logical address Artist actually expects.  Addresses fed
  30 * into Artist look like this:
  31 *  fixed          Y               X
  32 * FFFF FFFF LLLL LLLL LLLC CCCC CCCC CC00
  33 *
  34 * our "RAM" addresses look like this:
  35 * 
  36 * FFFF FFFF 0000 0LLL LLLL LLLL CCCC CCCC [CCC]
  37 *
  38 * */
  39
  40static inline u32
  41ram2log(void * addr)
  42{
  43#if 1
  44        return (unsigned long) addr;
  45#else   
  46        u32 a = (unsigned long) addr;
  47        u32 r;
  48
  49#if 1 
  50        r  =   a & 0xff000000;          /* fixed part */
  51        r += ((a & 0x000000ff) << 5);
  52        r += ((a & 0x00ffff00) << 3);
  53#else
  54        r  =   a & 0xff000000;          /* fixed part */
  55        r += ((a & 0x000000ff) << 5);
  56        r += ((a & 0x0007ff00) << 5);
  57#endif
  58
  59        return r;
  60#endif
  61}
  62
  63/* All those functions need better names. */
  64
  65static void
  66memcpy_fromhp_tohp(void *dest, void *src, int count)
  67{
  68        unsigned long d = ram2log(dest);
  69        unsigned long s = ram2log(src);
  70
  71        count += 3;
  72        count &= ~3; /* XXX */
  73
  74        while(count) {
  75                count --;
  76                gsc_writel(~gsc_readl(s), d);
  77                d += 32*4;
  78                s += 32*4;
  79        }
  80}
  81
  82
  83static void
  84memset_tohp(void *dest, u32 word, int count)
  85{
  86        unsigned long d = ram2log(dest);
  87
  88        count += 3;
  89        count &= ~3;
  90
  91        while(count) {
  92                count--;
  93                gsc_writel(word, d);
  94                d += 32;
  95        }
  96}
  97
  98static u8
  99readb_hp(void *src)
 100{
 101        unsigned long s = ram2log(src);
 102
 103        return ~gsc_readb(s);
 104}
 105
 106static void
 107writeb_hp(u8 b, void *dst)
 108{
 109        unsigned long d = ram2log(dst);
 110
 111        if((d&0xf0000000) != 0xf0000000) {
 112                printk("writeb_hp %02x %p (%08lx) (%p)\n",
 113                        b, dst, d, __builtin_return_address(0));
 114                return;
 115        }
 116
 117        gsc_writeb(b, d);
 118}
 119
 120static void
 121fbcon_sti_setup(struct display *p)
 122{
 123        if (p->line_length)
 124                p->next_line = p->line_length;
 125        else
 126                p->next_line = p->var.xres_virtual>>3;
 127        p->next_plane = 0;
 128}
 129
 130static void
 131fbcon_sti_bmove(struct display *p, int sy, int sx,
 132                int dy, int dx,
 133                int height, int width)
 134{
 135#if 0 /* Unfortunately, still broken */
 136        sti_bmove(default_sti /* FIXME */, sy, sx, dy, dx, height, width);
 137#else
 138        u8 *src, *dest;
 139        u_int rows;
 140
 141        if (sx == 0 && dx == 0 && width == p->next_line) {
 142                src = p->screen_base+sy*fontheight(p)*width;
 143                dest = p->screen_base+dy*fontheight(p)*width;
 144                memcpy_fromhp_tohp(dest, src, height*fontheight(p)*width);
 145        } else if (dy <= sy) {
 146                src = p->screen_base+sy*fontheight(p)*p->next_line+sx;
 147                dest = p->screen_base+dy*fontheight(p)*p->next_line+dx;
 148                for (rows = height*fontheight(p); rows--;) {
 149                        memcpy_fromhp_tohp(dest, src, width);
 150                        src += p->next_line;
 151                        dest += p->next_line;
 152                }
 153        } else {
 154                src = p->screen_base+((sy+height)*fontheight(p)-1)*p->next_line+sx;
 155                dest = p->screen_base+((dy+height)*fontheight(p)-1)*p->next_line+dx;
 156                for (rows = height*fontheight(p); rows--;) {
 157                        memcpy_fromhp_tohp(dest, src, width);
 158                        src -= p->next_line;
 159                        dest -= p->next_line;
 160                }
 161        }
 162#endif
 163}
 164
 165static void
 166fbcon_sti_clear(struct vc_data *conp,
 167                struct display *p, int sy, int sx,
 168                int height, int width)
 169{
 170        u8 *dest;
 171        u_int rows;
 172        int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0;
 173
 174        dest = p->screen_base+sy*fontheight(p)*p->next_line+sx;
 175
 176        if (sx == 0 && width == p->next_line) {
 177                if (inverse)
 178                        memset_tohp(dest, ~0, height*fontheight(p)*width);
 179                else
 180                        memset_tohp(dest,  0, height*fontheight(p)*width);
 181        } else
 182                for (rows = height*fontheight(p); rows--; dest += p->next_line)
 183                        if (inverse)
 184                                memset_tohp(dest, 0xffffffff, width);
 185                        else
 186                                memset_tohp(dest, 0x00000000, width);
 187}
 188
 189static void fbcon_sti_putc(struct vc_data *conp,
 190                           struct display *p, int c,
 191                           int yy, int xx)
 192{
 193        u8 *dest, *cdat;
 194        u_int rows, bold, revs, underl;
 195        u8 d;
 196
 197        dest = p->screen_base+yy*fontheight(p)*p->next_line+xx;
 198        cdat = p->fontdata+(c&p->charmask)*fontheight(p);
 199        bold = attr_bold(p,c);
 200        revs = attr_reverse(p,c);
 201        underl = attr_underline(p,c);
 202
 203        for (rows = fontheight(p); rows--; dest += p->next_line) {
 204                d = *cdat++;
 205                if (underl && !rows)
 206                        d = 0xff;
 207                else if (bold)
 208                        d |= d>>1;
 209                if (revs)
 210                        d = ~d;
 211                writeb_hp (d, dest);
 212        }
 213}
 214
 215static void fbcon_sti_putcs(struct vc_data *conp,
 216                            struct display *p, 
 217                            const unsigned short *s,
 218                            int count, int yy, int xx)
 219{
 220        u8 *dest, *dest0, *cdat;
 221        u_int rows, bold, revs, underl;
 222        u8 d;
 223        u16 c;
 224
 225        if(((unsigned)xx > 200) || ((unsigned) yy > 200)) {
 226                printk("refusing to putcs %p %p %p %d %d %d (%p)\n",
 227                        conp, p, s, count, yy, xx, __builtin_return_address(0));
 228                return;
 229        }       
 230
 231
 232        dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
 233        if(((u32)dest0&0xf0000000)!=0xf0000000) {
 234                printk("refusing to putcs %p %p %p %d %d %d (%p) %p = %p + %d * %d * %ld + %d\n",
 235                        conp, p, s, count, yy, xx, __builtin_return_address(0),
 236                        dest0, p->screen_base, yy, fontheight(p), p->next_line,
 237                        xx);
 238                return;
 239        }       
 240
 241        c = scr_readw(s);
 242        bold = attr_bold(p, c);
 243        revs = attr_reverse(p, c);
 244        underl = attr_underline(p, c);
 245
 246        while (count--) {
 247                c = scr_readw(s++) & p->charmask;
 248                dest = dest0++;
 249                cdat = p->fontdata+c*fontheight(p);
 250                for (rows = fontheight(p); rows--; dest += p->next_line) {
 251                        d = *cdat++;
 252                        if (0 && underl && !rows)
 253                                d = 0xff;
 254                        else if (0 && bold)
 255                                d |= d>>1;
 256                        if (revs)
 257                                d = ~d;
 258                        writeb_hp (d, dest);
 259                }
 260        }
 261}
 262
 263static void fbcon_sti_revc(struct display *p,
 264                           int xx, int yy)
 265{
 266        u8 *dest, d;
 267        u_int rows;
 268
 269
 270        dest = p->screen_base+yy*fontheight(p)*p->next_line+xx;
 271        for (rows = fontheight(p); rows--; dest += p->next_line) {
 272                d = readb_hp(dest);
 273                writeb_hp (~d, dest);
 274        }
 275}
 276
 277static void
 278fbcon_sti_clear_margins(struct vc_data *conp,
 279                        struct display *p,
 280                        int bottom_only)
 281{
 282        u8 *dest;
 283        int height, bottom;
 284        int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0;
 285
 286
 287        /* XXX Need to handle right margin? */
 288
 289        height = p->var.yres - conp->vc_rows * fontheight(p);
 290        if (!height)
 291                return;
 292        bottom = conp->vc_rows + p->yscroll;
 293        if (bottom >= p->vrows)
 294                bottom -= p->vrows;
 295        dest = p->screen_base + bottom * fontheight(p) * p->next_line;
 296        if (inverse)
 297                memset_tohp(dest, 0xffffffff, height * p->next_line);
 298        else
 299                memset_tohp(dest, 0x00000000, height * p->next_line);
 300}
 301
 302
 303    /*
 304     *  `switch' for the low level operations
 305     */
 306
 307struct display_switch fbcon_sti = {
 308        setup:          fbcon_sti_setup, 
 309        bmove:          fbcon_sti_bmove, 
 310        clear:          fbcon_sti_clear,
 311        putc:           fbcon_sti_putc, 
 312        putcs:          fbcon_sti_putcs, 
 313        revc:           fbcon_sti_revc,
 314        clear_margins:  fbcon_sti_clear_margins,
 315        fontwidthmask:  FONTWIDTH(8)
 316};
 317
 318MODULE_LICENSE("GPL");
 319
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.