patch-2.3.35 linux/drivers/video/creatorfb.c

Next file: linux/drivers/video/fbmem.c
Previous file: linux/drivers/video/cgthreefb.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.34/linux/drivers/video/creatorfb.c linux/drivers/video/creatorfb.c
@@ -1,4 +1,4 @@
-/* $Id: creatorfb.c,v 1.29 1999/08/10 15:56:07 davem Exp $
+/* $Id: creatorfb.c,v 1.31 1999/11/19 09:57:12 davem Exp $
  * creatorfb.c: Creator/Creator3D frame buffer driver
  *
  * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
@@ -21,6 +21,8 @@
 
 #include <video/sbusfb.h>
 
+#include <asm/upa.h>
+
 #define	FFB_SFB8R_VOFF		0x00000000
 #define	FFB_SFB8G_VOFF		0x00400000
 #define	FFB_SFB8B_VOFF		0x00800000
@@ -49,24 +51,24 @@
 #define	FFB_PROM_VOFF		0x0bc08000
 #define	FFB_EXP_VOFF		0x0bc18000
 
-#define	FFB_SFB8R_POFF		0x04000000
-#define	FFB_SFB8G_POFF		0x04400000
-#define	FFB_SFB8B_POFF		0x04800000
-#define	FFB_SFB8X_POFF		0x04c00000
-#define	FFB_SFB32_POFF		0x05000000
-#define	FFB_SFB64_POFF		0x06000000
-#define	FFB_FBC_REGS_POFF	0x00600000
-#define	FFB_BM_FBC_REGS_POFF	0x00600000
-#define	FFB_DFB8R_POFF		0x01000000
-#define	FFB_DFB8G_POFF		0x01400000
-#define	FFB_DFB8B_POFF		0x01800000
-#define	FFB_DFB8X_POFF		0x01c00000
-#define	FFB_DFB24_POFF		0x02000000
-#define	FFB_DFB32_POFF		0x03000000
-#define	FFB_FBC_KREGS_POFF	0x00610000
-#define	FFB_DAC_POFF		0x00400000
-#define	FFB_PROM_POFF		0x00000000
-#define	FFB_EXP_POFF		0x00200000
+#define	FFB_SFB8R_POFF		0x04000000UL
+#define	FFB_SFB8G_POFF		0x04400000UL
+#define	FFB_SFB8B_POFF		0x04800000UL
+#define	FFB_SFB8X_POFF		0x04c00000UL
+#define	FFB_SFB32_POFF		0x05000000UL
+#define	FFB_SFB64_POFF		0x06000000UL
+#define	FFB_FBC_REGS_POFF	0x00600000UL
+#define	FFB_BM_FBC_REGS_POFF	0x00600000UL
+#define	FFB_DFB8R_POFF		0x01000000UL
+#define	FFB_DFB8G_POFF		0x01400000UL
+#define	FFB_DFB8B_POFF		0x01800000UL
+#define	FFB_DFB8X_POFF		0x01c00000UL
+#define	FFB_DFB24_POFF		0x02000000UL
+#define	FFB_DFB32_POFF		0x03000000UL
+#define	FFB_FBC_KREGS_POFF	0x00610000UL
+#define	FFB_DAC_POFF		0x00400000UL
+#define	FFB_PROM_POFF		0x00000000UL
+#define	FFB_EXP_POFF		0x00200000UL
 
 /* Draw operations */
 #define FFB_DRAWOP_DOT		0x00
@@ -132,10 +134,18 @@
 
 struct ffb_fbc {
 	/* Next vertex registers */
-	u32		xxx1[3]; volatile u32 alpha; volatile u32 red;
-	volatile u32 green; volatile u32 blue; volatile u32 depth; volatile
-	u32 y; volatile u32 x; u32 xxx2[2]; volatile u32 ryf; volatile u32
-	rxf; u32 xxx3[2];
+	u32		xxx1[3];
+	volatile u32	alpha;
+	volatile u32	red;
+	volatile u32	green;
+	volatile u32	blue;
+	volatile u32	depth;
+	volatile u32	y;
+	volatile u32	x;
+	u32		xxx2[2];
+	volatile u32	ryf;
+	volatile u32	rxf;
+	u32		xxx3[2];
 	
 	volatile u32	dmyf;
 	volatile u32	dmxf;
@@ -275,7 +285,7 @@
 
 	if (cache - n < 0) {
 		fbc = fb->s.ffb.fbc;
-		do {	cache = (fbc->ucsr & FFB_UCSR_FIFO_MASK) - 8;
+		do {	cache = (upa_readl(&fbc->ucsr) & FFB_UCSR_FIFO_MASK) - 8;
 		} while (cache - n < 0);
 	}
 	fb->s.ffb.fifo_cache = cache - n;
@@ -286,10 +296,11 @@
 	int limit = 10000;
 
 	do {
-		if((ffb->ucsr & FFB_UCSR_ALL_BUSY) == 0)
+		if ((upa_readl(&ffb->ucsr) & FFB_UCSR_ALL_BUSY) == 0)
 			break;
-		if((ffb->ucsr & FFB_UCSR_ALL_ERRORS) != 0)
-			ffb->ucsr = FFB_UCSR_ALL_ERRORS;
+		if ((upa_readl(&ffb->ucsr) & FFB_UCSR_ALL_ERRORS) != 0) {
+			upa_writel(FFB_UCSR_ALL_ERRORS, &ffb->ucsr);
+		}
 	} while(--limit > 0);
 }
 
@@ -333,13 +344,15 @@
 {
 	struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
 	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
+	unsigned long flags;
 	u64 yx, hw;
 	int fg;
 	
+	spin_lock_irqsave(&fb->lock, flags);
 	fg = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p,conp)];
 	if (fg != fb->s.ffb.fg_cache) {
 		FFBFifo(fb, 5);
-		fbc->fg = fg;
+		upa_writel(fg, &fbc->fg);
 		fb->s.ffb.fg_cache = fg;
 	} else
 		FFBFifo(fb, 4);
@@ -354,40 +367,46 @@
 	} else {
 		yx += sx * fontwidth(p); hw += width * fontwidth(p);
 	}
-	*(volatile u64 *)&fbc->by = yx + fb->s.ffb.yx_margin;
-	*(volatile u64 *)&fbc->bh = hw;
+	upa_writeq(yx + fb->s.ffb.yx_margin, &fbc->by);
+	upa_writeq(hw, &fbc->bh);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void ffb_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
 		     int count, unsigned short *boxes)
 {
 	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
+	unsigned long flags;
 	int fg;
 
+	spin_lock_irqsave(&fb->lock, flags);
 	fg = ((u32 *)p->dispsw_data)[attr_bgcol(p,s)];
 	if (fg != fb->s.ffb.fg_cache) {
 		FFBFifo(fb, 1);
-		fbc->fg = fg;
+		upa_writel(fg, &fbc->fg);
 		fb->s.ffb.fg_cache = fg;
 	}
 	while (count-- > 0) {
 		FFBFifo(fb, 4);
-		fbc->by = boxes[1];
-		fbc->bx = boxes[0];
-		fbc->bh = boxes[3] - boxes[1];
-		fbc->bw = boxes[2] - boxes[0];
+		upa_writel(boxes[1], &fbc->by);
+		upa_writel(boxes[0], &fbc->bx);
+		upa_writel(boxes[3] - boxes[1], &fbc->bh);
+		upa_writel(boxes[2] - boxes[0], &fbc->bw);
 		boxes += 4;
 	}
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 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));
@@ -407,21 +426,27 @@
 	       ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
 	if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) {
 		FFBFifo(fb, 2);
-		*(volatile u64 *)&fbc->fg = fgbg;
+		upa_writeq(fgbg, &fbc->fg);
 		*(u64 *)&fb->s.ffb.fg_cache = fgbg;
 	}
 	FFBFifo(fb, 2 + fontheight(p));
-	fbc->fontxy = xy;
-	fbc->fontw = fontwidth(p);
+	upa_writel(xy, &fbc->fontxy);
+	upa_writel(fontwidth(p), &fbc->fontw);
 	if (fontwidth(p) <= 8) {
-		for (i = 0; i < fontheight(p); i++)
-			fbc->font = *fd++ << 24;
+		for (i = 0; i < fontheight(p); i++) {
+			u32 val = *fd++ << 24;
+
+			upa_writel(val, &fbc->font);
+		}
 	} else {
 		for (i = 0; i < fontheight(p); i++) {
-			fbc->font = *(u16 *)fd << 16;
+			u32 val = *(u16 *)fd << 16;
+
+			upa_writel(val, &fbc->font);
 			fd += 2;
 		}
 	}
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
@@ -429,15 +454,17 @@
 {
 	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;
 	u64 fgbg;
 
+	spin_lock_irqsave(&fb->lock, flags);
 	fgbg = (((u64)(((u32 *)p->dispsw_data)[attr_fgcol(p,scr_readw(s))])) << 32) |
 	       ((u32 *)p->dispsw_data)[attr_bgcol(p,scr_readw(s))];
 	if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) {
 		FFBFifo(fb, 2);
-		*(volatile u64 *)&fbc->fg = fgbg;
+		upa_writeq(fgbg, &fbc->fg);
 		*(u64 *)&fb->s.ffb.fg_cache = fgbg;
 	}
 	xy = fb->s.ffb.xy_margin;
@@ -453,8 +480,8 @@
 		while (count >= 4) {
 			count -= 4;
 			FFBFifo(fb, 2 + fontheight(p));
-			fbc->fontw = 4 * fontwidth(p);
-			fbc->fontxy = xy;
+			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));
@@ -467,14 +494,20 @@
 				fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p));
 			}
 			if (fontwidth(p) == 8) {
-				for (i = 0; i < fontheight(p); i++)
-					fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
+				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++)
-					fbc->font = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) 
+				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);
 			}
 		}
@@ -482,8 +515,8 @@
 		while (count >= 2) {
 			count -= 2;
 			FFBFifo(fb, 2 + fontheight(p));
-			fbc->fontw = 2 * fontwidth(p);
-			fbc->fontxy = xy;
+			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));
@@ -492,7 +525,9 @@
 				fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1);
 			}
 			for (i = 0; i < fontheight(p); i++) {
-				fbc->font = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
+				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);
@@ -501,25 +536,31 @@
 	while (count) {
 		count--;
 		FFBFifo(fb, 2 + fontheight(p));
-		fbc->fontw = fontwidth(p);
-		fbc->fontxy = xy;
+		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++)
-				fbc->font = *fd1++ << 24;
+			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++) {
-				fbc->font = *(u16 *)fd1 << 16;
+				u32 val = *(u16 *)fd1 << 16;
+
+				upa_writel(val, &fbc->font);
 				fd1 += 2;
 			}
 		}
 		xy += fontwidth(p);
 	}
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void ffb_revc(struct display *p, int xx, int yy)
@@ -527,23 +568,61 @@
 	/* Not used if hw cursor */
 }
 
+#if 0
+static void ffb_blank(struct fb_info_sbusfb *fb)
+{
+	struct ffb_dac *dac = fb->s.ffb.dac;
+	unsigned long flags;
+	u32 tmp;
+
+	spin_lock_irqsave(&fb->lock, flags);
+	upa_writel(0x6000, &dac->type);
+	tmp = (upa_readl(&dac->value) & ~0x1);
+	upa_writel(0x6000, &dac->type);
+	upa_writel(tmp, &dac->value);
+	spin_unlock_irqrestore(&fb->lock, flags);
+}
+#endif
+
+static void ffb_unblank(struct fb_info_sbusfb *fb)
+{
+	struct ffb_dac *dac = fb->s.ffb.dac;
+	unsigned long flags;
+	u32 tmp;
+
+	spin_lock_irqsave(&fb->lock, flags);
+	upa_writel(0x6000, &dac->type);
+	tmp = (upa_readl(&dac->value) | 0x1);
+	upa_writel(0x6000, &dac->type);
+	upa_writel(tmp, &dac->value);
+	spin_unlock_irqrestore(&fb->lock, flags);
+}
+
 static void ffb_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
 {
 	struct ffb_dac *dac = fb->s.ffb.dac;
+	unsigned long flags;
 	int i, j = count;
 	
-	dac->type = 0x2000 | index;
-	for (i = index; j--; i++)
+	spin_lock_irqsave(&fb->lock, flags);
+	upa_writel(0x2000 | index, &dac->type);
+	for (i = index; j--; i++) {
+		u32 val;
+
 		/* Feed the colors in :)) */
-		dac->value = ((fb->color_map CM(i,0))) |
-			     ((fb->color_map CM(i,1)) << 8) |
-			     ((fb->color_map CM(i,2)) << 16);
+		val = ((fb->color_map CM(i,0))) |
+			((fb->color_map CM(i,1)) << 8) |
+			((fb->color_map CM(i,2)) << 16);
+		upa_writel(val, &dac->value);
+	}
 	if (!p)
-		return;
+		goto out;
 	for (i = index, j = count; i < 16 && j--; i++)
 		((u32 *)p->dispsw_data)[i] = ((fb->color_map CM(i,0))) |
 			      		     ((fb->color_map CM(i,1)) << 8) |
 					     ((fb->color_map CM(i,2)) << 16);
+out:
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static struct display_switch ffb_dispsw __initdata = {
@@ -554,53 +633,67 @@
 static void ffb_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
 {
 	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
+	unsigned long flags;
 
+	spin_lock_irqsave(&fb->lock, flags);
 	fb->s.ffb.xy_margin = (y_margin << 16) + x_margin;
 	fb->s.ffb.yx_margin = (((u64)y_margin) << 32) + x_margin;
 	p->screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin);
 	FFBWait(fbc);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
-static inline void ffb_curs_enable (struct fb_info_sbusfb *fb, int enable)
+static __inline__ void __ffb_curs_enable (struct fb_info_sbusfb *fb, int enable)
 {
 	struct ffb_dac *dac = fb->s.ffb.dac;
-	
-	dac->type2 = 0x100;
-	if (fb->s.ffb.dac_rev <= 2)
-		dac->value2 = enable ? 3 : 0;
-	else
-		dac->value2 = enable ? 0 : 3;
+	u32 val;
+
+	upa_writel(0x100, &dac->type2);
+	if (fb->s.ffb.dac_rev <= 2) {
+		val = enable ? 3 : 0;
+	} else {
+		val = enable ? 0 : 3;
+	}
+	upa_writel(val, &dac->value2);
 }
 
 static void ffb_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
 {
 	struct ffb_dac *dac = fb->s.ffb.dac;
+	unsigned long flags;
 	
-	ffb_curs_enable (fb, 0);
-	dac->type2 = 0x102;
-	dac->value2 = (red[0] | (green[0]<<8) | (blue[0]<<16));
-	dac->value2 = (red[1] | (green[1]<<8) | (blue[1]<<16));
+	spin_lock_irqsave(&fb->lock, flags);
+	__ffb_curs_enable (fb, 0);
+	upa_writel(0x102, &dac->type2);
+	upa_writel((red[0] | (green[0]<<8) | (blue[0]<<16)), &dac->value2);
+	upa_writel((red[1] | (green[1]<<8) | (blue[1]<<16)), &dac->value2);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 /* Set cursor shape */
 static void ffb_setcurshape (struct fb_info_sbusfb *fb)
 {
 	struct ffb_dac *dac = fb->s.ffb.dac;
+	unsigned long flags;
 	int i, j;
 
-	ffb_curs_enable (fb, 0);
+	spin_lock_irqsave(&fb->lock, flags);
+	__ffb_curs_enable (fb, 0);
 	for (j = 0; j < 2; j++) {
-		dac->type2 = j ? 0 : 0x80;
+		u32 val = j ? 0 : 0x80;
+
+		upa_writel(val, &dac->type2);
 		for (i = 0; i < 0x40; i++) {
 			if (fb->cursor.size.fbx <= 32) {
-				dac->value2 = fb->cursor.bits [j][i];
-				dac->value2 = 0;
+				upa_writel(fb->cursor.bits [j][i], &dac->value2);
+				upa_writel(0, &dac->value2);
 			} else {
-				dac->value2 = fb->cursor.bits [j][2*i];
-				dac->value2 = fb->cursor.bits [j][2*i+1];
+				upa_writel(fb->cursor.bits [j][2*i], &dac->value2);
+				upa_writel(fb->cursor.bits [j][2*i+1], &dac->value2);
 			}
 		}
 	}	
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 /* Load cursor information */
@@ -608,31 +701,41 @@
 {
 	struct ffb_dac *dac = fb->s.ffb.dac;
 	struct cg_cursor *c = &fb->cursor;
+	unsigned long flags;
+	u32 val;
 
-	dac->type2 = 0x104;
+	spin_lock_irqsave(&fb->lock, flags);
+	upa_writel(0x104, &dac->type2);
 	/* Should this be just 0x7ff?? 
 	   Should I do some margin handling and setcurshape in that case? */
-	dac->value2 = (((c->cpos.fby - c->chot.fby) & 0xffff) << 16)
-	              |((c->cpos.fbx - c->chot.fbx) & 0xffff);
-	ffb_curs_enable (fb, fb->cursor.enable);
+	val = (((c->cpos.fby - c->chot.fby) & 0xffff) << 16)
+		|((c->cpos.fbx - c->chot.fbx) & 0xffff);
+	upa_writel(val, &dac->value2);
+	__ffb_curs_enable (fb, fb->cursor.enable);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static void ffb_switch_from_graph (struct fb_info_sbusfb *fb)
 {
 	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
+	unsigned long flags;
 
+	spin_lock_irqsave(&fb->lock, flags);
 	FFBWait(fbc);
 	fb->s.ffb.fifo_cache = 0;
 	FFBFifo(fb, 8);
-	fbc->ppc = FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE|FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST;
-	fbc->fbc = 0x2000707f;
-	fbc->rop = FFB_ROP_NEW;
-	fbc->drawop = FFB_DRAWOP_RECTANGLE;
-	fbc->pmask = 0xffffffff;
-	fbc->fontinc = 0x10000;
-	fbc->fg = fb->s.ffb.fg_cache;
-	fbc->bg = fb->s.ffb.bg_cache;
+	upa_writel(FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE|
+		   FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST,
+		   &fbc->ppc);
+	upa_writel(0x2000707f, &fbc->fbc);
+	upa_writel(FFB_ROP_NEW, &fbc->rop);
+	upa_writel(FFB_DRAWOP_RECTANGLE, &fbc->drawop);
+	upa_writel(0xffffffff, &fbc->pmask);
+	upa_writel(0x10000, &fbc->fontinc);
+	upa_writel(fb->s.ffb.fg_cache, &fbc->fg);
+	upa_writel(fb->s.ffb.bg_cache, &fbc->bg);
 	FFBWait(fbc);
+	spin_unlock_irqrestore(&fb->lock, flags);
 }
 
 static int __init ffb_rasterimg (struct fb_info *info, int start)
@@ -659,12 +762,15 @@
 		return NULL;
 		
 	disp->dispsw_data = (void *)kmalloc(16 * sizeof(u32), GFP_KERNEL);
-	if (!disp->dispsw_data)
+	if (disp->dispsw_data == NULL)
 		return NULL;
 	memset(disp->dispsw_data, 0, 16 * sizeof(u32));
 
 	fbops = kmalloc(sizeof(*fbops), GFP_KERNEL);
-	if (!fbops) return NULL;
+	if (fbops == NULL) {
+		kfree(disp->dispsw_data);
+		return NULL;
+	}
 	
 	*fbops = *fb->info.fbops;
 	fbops->fb_rasterimg = ffb_rasterimg;
@@ -698,8 +804,8 @@
 	disp->screen_base = (char *)__va(regs[0].phys_addr) + FFB_DFB24_POFF + 8192 * fb->y_margin + 4 * fb->x_margin;
 	fb->s.ffb.xy_margin = (fb->y_margin << 16) + fb->x_margin;
 	fb->s.ffb.yx_margin = (((u64)fb->y_margin) << 32) + fb->x_margin;
-	fb->s.ffb.fbc = (struct ffb_fbc *)((char *)__va(regs[0].phys_addr) + FFB_FBC_REGS_POFF);
-	fb->s.ffb.dac = (struct ffb_dac *)((char *)__va(regs[0].phys_addr) + FFB_DAC_POFF);
+	fb->s.ffb.fbc = (struct ffb_fbc *)(regs[0].phys_addr + FFB_FBC_REGS_POFF);
+	fb->s.ffb.dac = (struct ffb_dac *)(regs[0].phys_addr + FFB_DAC_POFF);
 	fb->dispsw = ffb_dispsw;
 
 	fb->margins = ffb_margins;
@@ -709,12 +815,22 @@
 	fb->setcurshape = ffb_setcurshape;
 	fb->switch_from_graph = ffb_switch_from_graph;
 	fb->fill = ffb_fill;
+#if 0
+	/* XXX Can't enable this for now, I've seen cases
+	 * XXX where the VC was blanked, and Xsun24 was started
+	 * XXX via a remote login, the sunfb code did not
+	 * XXX unblank creator when it was mmap'd for some
+	 * XXX reason, investigate later... -DaveM
+	 */
+	fb->blank = ffb_blank;
+	fb->unblank = ffb_unblank;
+#endif
 	
 	/* If there are any read errors or fifo overflow conditions,
 	 * clear them now.
 	 */
-	if((fb->s.ffb.fbc->ucsr & FFB_UCSR_ALL_ERRORS) != 0)
-		fb->s.ffb.fbc->ucsr = FFB_UCSR_ALL_ERRORS;
+	if((upa_readl(&fb->s.ffb.fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0)
+		upa_writel(FFB_UCSR_ALL_ERRORS, &fb->s.ffb.fbc->ucsr);
 
 	ffb_switch_from_graph(fb);
 	
@@ -726,17 +842,25 @@
 	
 	type->fb_depth = 24;
 	
-	fb->s.ffb.dac->type = 0x8000;
-	fb->s.ffb.dac_rev = (fb->s.ffb.dac->value >> 0x1c);
+	upa_writel(0x8000, &fb->s.ffb.dac->type);
+	fb->s.ffb.dac_rev = (upa_readl(&fb->s.ffb.dac->value) >> 0x1c);
 	                
 	i = prom_getintdefault (fb->prom_node, "board_type", 8);
-	                                                        
-	sprintf(idstring, "%s at %016lx type %d DAC %d", fix->id, regs[0].phys_addr, i, fb->s.ffb.dac_rev);
+
+	sprintf(idstring, "%s at %016lx type %d DAC %d",
+		fix->id, regs[0].phys_addr, i, fb->s.ffb.dac_rev);
 	
 	/* Elite3D has different DAC revision numbering, and no DAC revisions
 	   have the reversed meaning of cursor enable */
 	if (afb)
 		fb->s.ffb.dac_rev = 10;
 	
+	/* Unblank it just to be sure.  When there are multiple
+	 * FFB/AFB cards in the system, or it is not the OBP
+	 * chosen console, it will have video outputs off in
+	 * the DAC.
+	 */
+	ffb_unblank(fb);
+
 	return idstring;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)