예제 #1
0
void fbcon_ega_planes_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
{
	int fg = attr_fgcol(p,c);
	int bg = attr_bgcol(p,c);

	int y;
	u8 *cdat = p->fontdata + (c & p->charmask) * fontheight(p);
	char *where = p->screen_base + xx + yy * p->line_length * fontheight(p);

	setmode(0);
	setop(0);
	setsr(0xf);
	setcolor(bg);
	selectmask();

	setmask(0xff);
	for (y = 0; y < fontheight(p); y++, where += p->line_length) 
		rmw(where);

	where -= p->line_length * y;
	setcolor(fg);
	selectmask();
	for (y = 0; y < fontheight(p); y++, where += p->line_length) 
		if (cdat[y]) {
			setmask(cdat[y]);
			rmw(where);
		}
}
예제 #2
0
void fbcon_vga_planes_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
{
	int fg = attr_fgcol(p,c);
	int bg = attr_bgcol(p,c);

	int y;
	u8 *cdat = p->fontdata + (c & p->charmask) * fontheight(p);
	char *where = p->screen_base + xx + yy * p->line_length * fontheight(p);

	setmode(2);
	setop(0);
	setsr(0xf);
	setcolor(fg);
	selectmask();

	setmask(0xff);
	writeb(bg, where);
	rmb();
	readb(where); /* fill latches */
	setmode(3);
	wmb();
	for (y = 0; y < fontheight(p); y++, where += p->line_length) 
		writeb(cdat[y], where);
	wmb();
}
예제 #3
0
void fbcon_ilbm_putc(struct vc_data *conp, struct display *p, int c, int yy,
		     int xx)
{
    u8 *dest, *cdat;
    u_int rows, i;
    u8 d;
    int fg0, bg0, fg, bg;

    dest = p->screen_base+yy*fontheight(p)*p->next_line+xx;
    cdat = p->fontdata+(c&p->charmask)*fontheight(p);
    fg0 = attr_fgcol(p,c);
    bg0 = attr_bgcol(p,c);

    for (rows = fontheight(p); rows--;) {
	d = *cdat++;
	fg = fg0;
	bg = bg0;
	for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
	    if (bg & 1){
		if (fg & 1)
		    *dest = 0xff;
		else
		    *dest = ~d;
	    }else{
		if (fg & 1)
		    *dest = d;
		else
		    *dest = 0x00;
	    }
	    bg >>= 1;
	    fg >>= 1;
	}
    }
}
예제 #4
0
static void fbcon_riva32_putc(struct vc_data *conp, struct display *p, int c,
			    int yy, int xx)
{
	u32 fgx,bgx;

	fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p,c)];
	bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
	xx *= fontwidth(p);
	yy *= fontheight(p);
	fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
}
예제 #5
0
static void ffb_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
{
	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
	unsigned long flags;
	int i, xy;
	u8 *fd;
	u64 fgbg;

	spin_lock_irqsave(&fb->lock, flags);
	if (fontheightlog(p)) {
		xy = (yy << (16 + fontheightlog(p)));
		i = ((c & p->charmask) << fontheightlog(p));
	} else {
		xy = ((yy * fontheight(p)) << 16);
		i = (c & p->charmask) * fontheight(p);
	}
	if (fontwidth(p) <= 8)
		fd = p->fontdata + i;
	else
		fd = p->fontdata + (i << 1);
	if (fontwidthlog(p))
		xy += (xx << fontwidthlog(p)) + fb->s.ffb.xy_margin;
	else
		xy += (xx * fontwidth(p)) + fb->s.ffb.xy_margin;
	fgbg = (((u64)(((u32 *)p->dispsw_data)[attr_fgcol(p,c)])) << 32) |
	       ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
	if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) {
		FFBFifo(fb, 2);
		upa_writeq(fgbg, &fbc->fg);
		*(u64 *)&fb->s.ffb.fg_cache = fgbg;
	}
	FFBFifo(fb, 2 + fontheight(p));
	upa_writel(xy, &fbc->fontxy);
	upa_writel(fontwidth(p), &fbc->fontw);
	if (fontwidth(p) <= 8) {
		for (i = 0; i < fontheight(p); i++) {
			u32 val = *fd++ << 24;

			upa_writel(val, &fbc->font);
		}
	} else {
		for (i = 0; i < fontheight(p); i++) {
			u32 val = *(u16 *)fd << 16;

			upa_writel(val, &fbc->font);
			fd += 2;
		}
	}
	spin_unlock_irqrestore(&fb->lock, flags);
}
예제 #6
0
static void leo_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
{
	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
	unsigned long flags;
	int i, x, y;
	u8 *fd;
	u32 *u;

	spin_lock_irqsave(&fb->lock, flags);
	if (fontheightlog(p)) {
		y = yy << (fontheightlog(p) + 11);
		i = (c & p->charmask) << fontheightlog(p);
	} else {
		y = (yy * fontheight(p)) << 11;
		i = (c & p->charmask) * fontheight(p);
	}
	if (fontwidth(p) <= 8)
		fd = p->fontdata + i;
	else
		fd = p->fontdata + (i << 1);
	if (fontwidthlog(p))
		x = xx << fontwidthlog(p);
	else
		x = xx * fontwidth(p);
	do {
		i = sbus_readl(&us->csr);
	} while (i & 0x20000000);
	sbus_writel(attr_fgcol(p,c) << 24, &ss->fg);
	sbus_writel(attr_bgcol(p,c) << 24, &ss->bg);
	sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)),
		    &us->fontmsk);
	u = ((u32 *)p->screen_base) + y + x;
	if (fontwidth(p) <= 8) {
		for (i = 0; i < fontheight(p); i++, u += 2048) {
			u32 val = *fd++ << 24;

			sbus_writel(val, u);
		}
	} else {
		for (i = 0; i < fontheight(p); i++, u += 2048) {
			u32 val = *(u16 *)fd << 16;

			sbus_writel(val, u);
			fd += 2;
		}
	}
	spin_unlock_irqrestore(&fb->lock, flags);
}
예제 #7
0
static void fbcon_riva16_putc(struct vc_data *conp, struct display *p, int c,
			    int yy, int xx)
{
	u32 fgx,bgx;

	fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p,c)];
	bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p,c)];
	if (p->var.green.length == 6)
		convert_bgcolor_16(&bgx);
	xx *= fontwidth(p);
	yy *= fontheight(p);

	fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
}
예제 #8
0
static void fbcon_riva32_putcs(struct vc_data *conp, struct display *p,
			     const unsigned short *s, int count, int yy,
			     int xx)
{
	u16 c;
	u32 fgx,bgx;

	xx *= fontwidth(p);
	yy *= fontheight(p);

	c = scr_readw(s);
	fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, c)];
	bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, c)];
	while (count--) {
		c = scr_readw(s++);
		fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
		xx += fontwidth(p);
	}
}
예제 #9
0
void fbcon_ilbm_putcs(struct vc_data *conp, struct display *p, 
		      const unsigned short *s, int count, int yy, int xx)
{
    u8 *dest0, *dest, *cdat1, *cdat2, *cdat3, *cdat4;
    u_int rows, i;
    u16 c1, c2, c3, c4;
    u32 d;
    int fg0, bg0, fg, bg;

    dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
    fg0 = attr_fgcol(p,*s);
    bg0 = attr_bgcol(p,*s);

    while (count--)
	if (xx&3 || count < 3) {	/* Slow version */
	    c1 = *s++ & p->charmask;
	    dest = dest0++;
	    xx++;

	    cdat1 = p->fontdata+c1*fontheight(p);
	    for (rows = fontheight(p); rows--;) {
		d = *cdat1++;
		fg = fg0;
		bg = bg0;
		for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
		    if (bg & 1){
			if (fg & 1)
			    *dest = 0xff;
			else
			    *dest = ~d;
		    }else{
			if (fg & 1)
			    *dest = d;
			else
			    *dest = 0x00;
		    }
		    bg >>= 1;
		    fg >>= 1;
		}
	    }
	} else {		/* Fast version */
예제 #10
0
static void fbcon_riva16_putcs(struct vc_data *conp, struct display *p,
			     const unsigned short *s, int count, int yy,
			     int xx)
{
	u16 c;
	u32 fgx,bgx;

	xx *= fontwidth(p);
	yy *= fontheight(p);

	c = scr_readw(s);
	fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, c)];
	bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, c)];
	if (p->var.green.length == 6)
		convert_bgcolor_16(&bgx);
	while (count--) {
		c = scr_readw(s++);
		fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
		xx += fontwidth(p);
	}
}
예제 #11
0
static void i810_accel_revc(struct display *p, int xx, int yy)
{
    struct blit_data rect;
    int depth, c, fg;

    if (i810_accel->lockup || not_safe())
        return;

    c = scr_readw((u16 *) p->conp->vc_pos);
    fg = (int) attr_fgcol(p,c);

    depth = (p->var.bits_per_pixel + 7) >> 3;

    switch (depth) {
    case 1:
        rect.fg = fg;
        rect.blit_bpp = BPP8;
        break;
    case 2:
        rect.fg = (int) ((u16 *)p->dispsw_data)[fg];
        rect.blit_bpp = BPP16;
        break;
    case 3:
        rect.fg = ((int *)p->dispsw_data)[fg];
        rect.blit_bpp = BPP24;
        break;
    }


    rect.dpitch = p->next_line;
    rect.dwidth = fontwidth(p)*depth;
    rect.dheight = fontheight(p);
    rect.d_addr = (i810_accel->fb_offset << 12) +
                  (yy * rect.dheight * p->next_line) +
                  (xx * rect.dwidth);
    rect.rop = XOR_ROP;
    color_blit(&rect);
}
예제 #12
0
/* 6.96 in my test */
void fbcon_vga_planes_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
		   int count, int yy, int xx)
{
	int fg = attr_fgcol(p,*s);
	int bg = attr_bgcol(p,*s);

	char *where;
	int n;

	setmode(2);
	setop(0);
	setsr(0xf);
	setcolor(fg);
	selectmask();

	setmask(0xff);
	where = p->screen_base + xx + yy * p->line_length * fontheight(p);
	writeb(bg, where);
	rmb();
	readb(where); /* fill latches */
	setmode(3);	
	wmb();
	for (n = 0; n < count; n++) {
		int y;
		int c = *s++ & p->charmask;
		u8 *cdat = p->fontdata + (c & p->charmask) * fontheight(p);

		for (y = 0; y < fontheight(p); y++, cdat++) {
			writeb (*cdat, where);
			where += p->line_length;
		}
		where += 1 - p->line_length * fontheight(p);
	}
	
	wmb();
}
예제 #13
0
/* 28.50 in my test */
void fbcon_ega_planes_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
		   int count, int yy, int xx)
{
	int fg = attr_fgcol(p,scr_readw(s));
	int bg = attr_bgcol(p,scr_readw(s));

	char *where;
	int n;

	setmode(2);
	setop(0);
	selectmask();

	setmask(0xff);
	where = p->screen_base + xx + yy * p->line_length * fontheight(p);
	writeb(bg, where);
	rmb();
	readb(where); /* fill latches */
	wmb();
	selectmask();
	for (n = 0; n < count; n++) {
		int c = scr_readw(s++) & p->charmask;
		u8 *cdat = p->fontdata + c * fontheight(p);
		u8 *end = cdat + fontheight(p);

		while (cdat < end) {
			outb(*cdat++, GRAPHICS_DATA_REG);	
			wmb();
			writeb(fg, where);
			where += p->line_length;
		}
		where += 1 - p->line_length * fontheight(p);
	}
	
	wmb();
}
예제 #14
0
static void i810_accel_putc(struct vc_data *conp, struct display *p,
                            int c, int yy, int xx)
{
    struct blit_data data;
    int width, height, depth, d_addr, d_pitch, s_pitch;
    void (*move_data)(void *dst, void *src, int dpitch, int spitch, int size);
    char *s_addr;

    if (i810_accel->lockup || not_safe())
        return;

    depth = (p->var.bits_per_pixel + 7) >> 3;
    switch (depth) {
    case 1:
        data.fg = (int) attr_fgcol(p,c);
        data.bg = (int) attr_bgcol(p,c);
        data.blit_bpp = BPP8;
        break;
    case 2:
        data.bg = (int) ((u16 *)p->dispsw_data)[attr_bgcol(p, c)];
        data.fg = (int) ((u16 *)p->dispsw_data)[attr_fgcol(p, c)];
        data.blit_bpp = BPP16;
        break;
    case 3:
        data.fg = ((int *) p->dispsw_data)[attr_fgcol(p, c)];
        data.bg = ((int *) p->dispsw_data)[attr_bgcol(p, c)];
        data.blit_bpp = BPP24;
    }

    height = fontheight(p);
    width = (fontwidth(p) + 7) & ~7;

    switch (width) {
    case 8:
        move_data = i810fb_moveb;
        break;
    case 16:
        move_data = i810fb_movew;
        break;
    case 32:
        move_data = i810fb_movel;
        break;
    default:
        move_data = i810fb_move;
        break;
    }

    s_pitch = width >> 3;
    d_pitch = ((s_pitch) + 1) & ~1;

    data.dwidth = width * depth;
    data.dheight = height;
    data.dpitch = p->next_line;
    data.rop = PAT_COPY_ROP;
    data.dsize = (d_pitch * height) >> 2;
    data.d_addr = (i810_accel->fb_offset << 12) + (yy * height * p->next_line) + (xx * width * depth);
    data.s_addr[0] = d_addr = i810_accel->text_buffer;

    s_addr = p->fontdata + ((c & p->charmask) * s_pitch * height);
    move_data((void *) d_addr, s_addr, d_pitch, s_pitch, height);

    mono_src_copy_imm_blit(&data);
}
예제 #15
0
static void i810_accel_putcs(struct vc_data *conp, struct display *p,
                             const unsigned short *s, int count, int yy, int xx)
{
    struct blit_data text;
    int depth, c, d_addr, s_pitch, d_pitch, f_width, cell;
    char *s_addr;
    void (*move_data)(void *dst, void *src, int dpitch, int spitch, int size);

    if (i810_accel->lockup || not_safe())
        return;

    c = scr_readw(s);
    depth = (p->var.bits_per_pixel + 7) >> 3;

    switch (depth) {
    case 1:
        text.fg = (int) attr_fgcol(p,c);
        text.bg = (int) attr_bgcol(p,c);
        text.blit_bpp = BPP8;
        break;
    case 2:
        text.bg = (int) ((u16 *)p->dispsw_data)[attr_bgcol(p, c)];
        text.fg = (int) ((u16 *)p->dispsw_data)[attr_fgcol(p, c)];
        text.blit_bpp = BPP16;
        break;
    case 3:
        text.fg = ((int *) p->dispsw_data)[attr_fgcol(p, c)];
        text.bg = ((int *) p->dispsw_data)[attr_bgcol(p, c)];
        text.blit_bpp = BPP24;
    }

    f_width = (fontwidth(p) + 7) & ~7;

    switch (f_width) {
    case 8:
        move_data = i810fb_moveb;
        break;
    case 16:
        move_data = i810fb_movew;
        break;
    case 32:
        move_data = i810fb_movel;
        break;
    default:
        move_data = i810fb_move;
        break;
    }

    s_pitch = f_width >> 3;
    d_pitch = ((s_pitch * count) + 1) & ~1;

    text.dwidth = f_width * depth * count;
    text.dheight = fontheight(p);
    text.dpitch = p->next_line;
    text.dsize = ((d_pitch * text.dheight) + 7) & ~7;
    text.dsize >>= 2;
    text.rop = PAT_COPY_ROP;
    text.d_addr = (i810_accel->fb_offset << 12) + (yy * text.dheight * p->next_line) +
                  (xx * f_width * depth);
    text.s_addr[0] = d_addr = i810_accel->text_buffer;

    cell = s_pitch * text.dheight;
    if (s_pitch == 1 && count > 3) {
        int i, d_addr0;
        char *s1, *s2, *s3, *s4;

        while (count > 3) {
            s1 = p->fontdata + (scr_readw(s++) & p->charmask) * cell;
            s2 = p->fontdata + (scr_readw(s++) & p->charmask) * cell;
            s3 = p->fontdata + (scr_readw(s++) & p->charmask) * cell;
            s4 = p->fontdata + (scr_readw(s++) & p->charmask) * cell;
            d_addr0 = d_addr;

            for (i = text.dheight; i--; ) {
                *(unsigned long *) d_addr0 =
                    (unsigned long) ((*s1++ & 0xff)       |
                                     (*s2++ & 0xff) << 8  |
                                     (*s3++ & 0xff) << 16 |
                                     (*s4++ & 0xff) << 24   );
                d_addr0 += d_pitch;
            }
            d_addr += 4;
            count -= 4;
        }
    }

    while (count--) {
        c = scr_readw(s++) & p->charmask;
        s_addr = p->fontdata + (c * cell);
        move_data((void *) d_addr, s_addr, d_pitch, s_pitch, text.dheight);
        d_addr += s_pitch;
    }

    mono_src_copy_imm_blit(&text);
}
예제 #16
0
static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
		      int count, int yy, int xx)
{
	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
	unsigned long flags;
	int i, xy;
	u8 *fd1, *fd2, *fd3, *fd4;
	u16 c;
	u64 fgbg;

	spin_lock_irqsave(&fb->lock, flags);
	c = scr_readw(s);
	fgbg = (((u64)(((u32 *)p->dispsw_data)[attr_fgcol(p, c)])) << 32) |
	       ((u32 *)p->dispsw_data)[attr_bgcol(p, c)];
	if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) {
		FFBFifo(fb, 2);
		upa_writeq(fgbg, &fbc->fg);
		*(u64 *)&fb->s.ffb.fg_cache = fgbg;
	}
	xy = fb->s.ffb.xy_margin;
	if (fontwidthlog(p))
		xy += (xx << fontwidthlog(p));
	else
		xy += xx * fontwidth(p);
	if (fontheightlog(p))
		xy += (yy << (16 + fontheightlog(p)));
	else
		xy += ((yy * fontheight(p)) << 16);
	if (fontwidth(p) <= 8) {
		while (count >= 4) {
			count -= 4;
			FFBFifo(fb, 2 + fontheight(p));
			upa_writel(4 * fontwidth(p), &fbc->fontw);
			upa_writel(xy, &fbc->fontxy);
			if (fontheightlog(p)) {
				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
				fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
				fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
			} else {
				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
				fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
				fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
			}
			if (fontwidth(p) == 8) {
				for (i = 0; i < fontheight(p); i++) {
					u32 val;

					val = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
						<< 8)) << 8)) << 8);
					upa_writel(val, &fbc->font);
				}
				xy += 32;
			} else {
				for (i = 0; i < fontheight(p); i++) {
					u32 val = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
						<< fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p));
					upa_writel(val, &fbc->font);
				}
				xy += 4 * fontwidth(p);
			}
		}
	} else {
		while (count >= 2) {
			count -= 2;
			FFBFifo(fb, 2 + fontheight(p));
			upa_writel(2 * fontwidth(p), &fbc->fontw);
			upa_writel(xy, &fbc->fontxy);
			if (fontheightlog(p)) {
				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
			} else {
				fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
				fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
			}
			for (i = 0; i < fontheight(p); i++) {
				u32 val = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));

				upa_writel(val, &fbc->font);
				fd1 += 2; fd2 += 2;
			}
			xy += 2 * fontwidth(p);
		}
	}
	while (count) {
		count--;
		FFBFifo(fb, 2 + fontheight(p));
		upa_writel(fontwidth(p), &fbc->fontw);
		upa_writel(xy, &fbc->fontxy);
		if (fontheightlog(p))
			i = ((scr_readw(s++) & p->charmask) << fontheightlog(p));
		else
			i = ((scr_readw(s++) & p->charmask) * fontheight(p));
		if (fontwidth(p) <= 8) {
			fd1 = p->fontdata + i;
			for (i = 0; i < fontheight(p); i++) {
				u32 val = *fd1++ << 24;

				upa_writel(val, &fbc->font);
			}
		} else {
			fd1 = p->fontdata + (i << 1);
			for (i = 0; i < fontheight(p); i++) {
				u32 val = *(u16 *)fd1 << 16;

				upa_writel(val, &fbc->font);
				fd1 += 2;
			}
		}
		xy += fontwidth(p);
	}
	spin_unlock_irqrestore(&fb->lock, flags);
}
예제 #17
0
static void leo_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
		      int count, int yy, int xx)
{
	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
	register struct leo_lc_ss0_usr *us = fb->s.leo.lc_ss0_usr;
	register struct leo_ld *ss = (struct leo_ld *) fb->s.leo.ld_ss0;
	unsigned long flags;
	int i, x, y;
	u8 *fd1, *fd2, *fd3, *fd4;
	u16 c;
	u32 *u;

	spin_lock_irqsave(&fb->lock, flags);
	do {
		i = sbus_readl(&us->csr);
	} while (i & 0x20000000);
	c = scr_readw(s);
	sbus_writel(attr_fgcol(p, c) << 24, &ss->fg);
	sbus_writel(attr_bgcol(p, c) << 24, &ss->bg);
	sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)), &us->fontmsk);
	if (fontwidthlog(p))
		x = (xx << fontwidthlog(p));
	else
		x = xx * fontwidth(p);
	if (fontheightlog(p))
		y = yy << (fontheightlog(p) + 11);
	else
		y = (yy * fontheight(p)) << 11;
	u = ((u32 *)p->screen_base) + y + x;
	if (fontwidth(p) <= 8) {
		sbus_writel(0xFFFFFFFF<<(32-4*fontwidth(p)), &us->fontmsk);
		x = 4*fontwidth(p) - fontheight(p)*2048;
		while (count >= 4) {
			count -= 4;
			if (fontheightlog(p)) {
				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
				fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
				fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p));
			} else {
				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
				fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
				fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
			}
			if (fontwidth(p) == 8) {
				for (i = 0; i < fontheight(p); i++, u += 2048) {
					u32 val;

					val = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
						<< 8)) << 8)) << 8);
					sbus_writel(val, u);
				}
				u += x;
			} else {
				for (i = 0; i < fontheight(p); i++, u += 2048) {
					u32 val;

					val = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
						<< fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p));
					sbus_writel(val, u);
				}
				u += x;
			}
		}
	} else {
		sbus_writel(0xFFFFFFFF<<(32-2*fontwidth(p)), &us->fontmsk);
		x = 2*fontwidth(p) - fontheight(p)*2048;
		while (count >= 2) {
			count -= 2;
			if (fontheightlog(p)) {
				fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
				fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1));
			} else {
				fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
				fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
			}
			for (i = 0; i < fontheight(p); i++, u += 2048) {
				u32 val;

				val = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
				sbus_writel(val, u);
				fd1 += 2; fd2 += 2;
			}
			u += x;
		}
	}
	sbus_writel(0xFFFFFFFF<<(32-fontwidth(p)), &us->fontmsk);
	x = fontwidth(p) - fontheight(p)*2048;
	while (count) {
		count--;
		if (fontheightlog(p))
			i = ((scr_readw(s++) & p->charmask) << fontheightlog(p));
		else
			i = ((scr_readw(s++) & p->charmask) * fontheight(p));
		if (fontwidth(p) <= 8) {
			fd1 = p->fontdata + i;
			for (i = 0; i < fontheight(p); i++, u += 2048) {
				u32 val = *fd1++ << 24;

				sbus_writel(val, u);
			}
		} else {
			fd1 = p->fontdata + (i << 1);
			for (i = 0; i < fontheight(p); i++, u += 2048) {
				u32 val = *(u16 *)fd1 << 16;

				sbus_writel(val, u);
				fd1 += 2;
			}
		}
		u += x;
	}
	spin_unlock_irqrestore(&fb->lock, flags);
}