Subject: Testers wanted for new TGA console code
To: None <port-alpha@netbsd.org>
From: Nathan J. Williams <nathanw@MIT.EDU>
List: port-alpha
Date: 04/07/2000 17:59:14
Hi, folks. I've put together some code to put up a text console on TGA
cards, based on the newish rasops code. I've been testing it on a
ZLXp-E2 (8M, 32-bpp), and I've been reasonably careful to make the
code work on an 8-bpp -E1 card, but I can't test it myself.

The code includes some accelerated text routines; tga_copyrows() gave
about a factor-of-20 improvement over the native rasops scrolling
(still kind of slow, though; "cat /usr/share/misc/termcap" clocked in
at 15 seconds on my 500 MHz pc164). However, tga_putchar() only gave
about a 30% improvement in non-scrolling character drawing
operations. I had expected much more.. anyone care to speculate on
the bottleneck?

Anyway, if people could test the code on TGA cards and let me know how
it goes, I'd appreciate it.

Patch is below. You'll also want rev 1.29 or later of
sys/dev/rasops/rasops.c. 

Enjoy!

        - Nathan

Index: ic/bt463.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/bt463.c,v
retrieving revision 1.1
diff -c -r1.1 bt463.c
*** bt463.c	2000/04/02 18:57:36	1.1
--- bt463.c	2000/04/07 21:34:30
***************
*** 155,160 ****
--- 155,168 ----
  	int window_type[16]; /* 16 24-bit window type table entries */
  };
  
+ /* When we're doing console initialization, there's no
+  * way to get our cookie back to the video card's softc
+  * before we call sched_update. So we stash it here, 
+  * and bt463_update will look for it here first.
+  */
+ static struct bt463data *console_data;
+ 
+ 
  #define BTWREG(data, addr, val) do { bt463_wraddr((data), (addr)); \
  	(data)->ramdac_wr((data)->cookie, BT463_REG_IREG_DATA, (val)); } while (0)
  #define BTWNREG(data, val) (data)->ramdac_wr((data)->cookie, \
***************
*** 228,234 ****
--- 236,247 ----
  	data->ramdac_sched_update = sched_update;
  	data->ramdac_wr = wr;
  	data->ramdac_rd = rd;
+ 	/* Set up console_data so that when bt463_update is called back,
+ 	 * it can use the right information.
+ 	 */
+ 	console_data = data;
  	bt463_init((struct ramdac_cookie *)data);
+ 	console_data = NULL;
  }
  
  void
***************
*** 550,555 ****
--- 563,575 ----
  {
  	struct bt463data *data = (struct bt463data *)p;
  	int i, v;
+ 
+ 	if (console_data != NULL) {
+ 		/* The cookie passed in from sched_update is incorrect. Use the
+ 		 * right one.
+ 		 */
+ 		data = console_data;
+ 	}
  
  	v = data->changed;
  
Index: pci/files.pci
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pci/files.pci,v
retrieving revision 1.84
diff -c -r1.84 files.pci
*** files.pci	2000/04/05 02:31:19	1.84
--- files.pci	2000/04/07 21:34:30
***************
*** 146,152 ****
  file	dev/pci/vga_pci.c		vga_pci	needs-flag
  
  # DEC TGA
! device	tga: wsemuldisplaydev, wsrasteremulops
  attach	tga at pci
  file	dev/pci/tga.c			tga needs-flag
  file	dev/pci/tga_conf.c		tga
--- 146,152 ----
  file	dev/pci/vga_pci.c		vga_pci	needs-flag
  
  # DEC TGA
! device	tga: wsemuldisplaydev, wsrasteremulops, rasops8, rasops32
  attach	tga at pci
  file	dev/pci/tga.c			tga needs-flag
  file	dev/pci/tga_conf.c		tga
Index: pci/tga.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pci/tga.c,v
retrieving revision 1.22
diff -c -r1.22 tga.c
*** tga.c	2000/04/02 19:01:11	1.22
--- tga.c	2000/04/07 21:34:30
***************
*** 27,32 ****
--- 27,35 ----
   * rights to redistribute these changes.
   */
  
+ #define NATHANW_RASOPS
+ 
+ 
  #include <sys/param.h>
  #include <sys/systm.h>
  #include <sys/kernel.h>
***************
*** 54,60 ****
  #include <dev/rcons/raster.h>
  #include <dev/wscons/wsconsio.h>
  #include <dev/wscons/wscons_raster.h>
! #include <dev/wscons/wsdisplayvar.h>
  
  #ifdef __alpha__
  #include <machine/pte.h>
--- 57,64 ----
  #include <dev/rcons/raster.h>
  #include <dev/wscons/wsconsio.h>
  #include <dev/wscons/wscons_raster.h>
! #include <dev/rasops/rasops.h>
! #include <dev/wsfont/wsfont.h>
  
  #ifdef __alpha__
  #include <machine/pte.h>
***************
*** 84,89 ****
--- 88,103 ----
  static void tga_free_screen __P((void *, void *));
  static int tga_show_screen __P((void *, void *, int,
  				void (*) (void *, int, int), void *));
+ #ifdef NATHANW_RASOPS
+ static int tga_rop __P((struct rasops_info *, int, int, int, int, int,
+ 	struct rasops_info *, int, int));
+ static int tga_rop_vtov __P((struct rasops_info *, int, int, int, int,
+ 	int, struct rasops_info *, int, int ));
+ static void tga_putchar __P((void *c, int row, int col,
+ 				u_int uc, long attr));
+ static void tga_eraserows __P((void *, int, int, long));
+ static void	tga_erasecols __P((void *, int, int, int, long));
+ #else 
  static int tga_rop __P((struct raster *, int, int, int, int, int,
  	struct raster *, int, int));
  static int tga_rop_nosrc __P((struct raster *, int, int, int, int, int));
***************
*** 91,96 ****
--- 105,111 ----
  	int, struct raster *, int, int ));
  static int tga_rop_vtov __P((struct raster *, int, int, int, int,
  	int, struct raster *, int, int ));
+ #endif
  void tga2_init __P((struct tga_devconfig *, int));
  
  static void tga_config_interrupts __P((struct device *));
***************
*** 107,112 ****
--- 122,142 ----
  /* Interrupt handler */
  static int	tga_intr __P((void *));
  
+ #ifdef NATHANW_RASOPS
+ /* The NULL entries will get filled in by rasops_init().
+  * XXX and the non-NULL ones will be overwritten; reset after calling it.
+  */
+ struct wsdisplay_emulops tga_emulops = {
+ 	NULL,
+ 	NULL,
+ 	tga_putchar,
+ 	tga_copycols,
+ 	tga_erasecols,
+ 	tga_copyrows,
+ 	tga_eraserows,
+ 	NULL,
+ };
+ #else
  struct wsdisplay_emulops tga_emulops = {
  	rcons_cursor,			/* could use hardware cursor; punt */
  	rcons_mapchar,
***************
*** 117,122 ****
--- 147,153 ----
  	rcons_eraserows,
  	rcons_alloc_attr
  };
+ #endif
  
  struct wsscreen_descr tga_stdscreen = {
  	"std",
***************
*** 176,183 ****
--- 207,219 ----
  	struct tga_devconfig *dc;
  {
  	const struct tga_conf *tgac;
+ #ifdef NATHANW_RASOPS
+ 	struct rasops_info *rip;
+ 	int cookie;
+ #else
  	struct raster *rap;
  	struct rcons *rcp;
+ #endif
  	bus_size_t pcisize;
  	int i, flags;
  
***************
*** 288,293 ****
--- 324,383 ----
  	for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t))
  		*(u_int32_t *)(dc->dc_videobase + i) = 0;
  
+ #ifdef NATHANW_RASOPS
+ 	rip = &dc->dc_rinfo;
+ 	rip->ri_flg = RI_CENTER;
+ 	rip->ri_depth = tgac->tgac_phys_depth;
+ 	rip->ri_bits = (void *)dc->dc_videobase;
+ 	rip->ri_width = dc->dc_wid;
+ 	rip->ri_height = dc->dc_ht;
+ 	rip->ri_stride = dc->dc_rowbytes;
+ 	rip->ri_hw = dc;
+ 
+ 	if (tgac->tgac_phys_depth == 32) {
+ 		rip->ri_rnum = 8;
+ 		rip->ri_gnum = 8;
+ 		rip->ri_bnum = 8;
+ 		rip->ri_rpos = 16;
+ 		rip->ri_gpos = 8;
+ 		rip->ri_bpos = 0;
+ 	}
+ 
+ 	wsfont_init();
+ 	/* prefer 8 pixel wide font */
+ 	if ((cookie = wsfont_find(NULL, 8, 0, 0)) <= 0)
+ 		cookie = wsfont_find(NULL, 0, 0, 0);
+ 	if (cookie <= 0) {
+ 		printf("tga: no appropriate fonts.\n");
+ 		return;
+ 	}
+ 
+ 	/* the accelerated tga_putchar() needs LSbit left */
+ 	if (wsfont_lock(cookie, &dc->dc_rinfo.ri_font,
+ 	    WSDISPLAY_FONTORDER_R2L, WSDISPLAY_FONTORDER_L2R) <= 0) {
+ 		printf("tga: couldn't lock font\n");
+ 		return;
+ 	}
+ 	dc->dc_rinfo.ri_wsfcookie = cookie;
+ 
+ 	rasops_init(rip, 34, 80);
+ 	
+ 	/* add our accelerated functions */
+ 	/* XXX shouldn't have to do this; rasops should leave non-NULL 
+ 	 * XXX entries alone.
+ 	 */
+ 	dc->dc_rinfo.ri_ops.copyrows = tga_copyrows;
+ 	dc->dc_rinfo.ri_ops.eraserows = tga_eraserows;
+ 	dc->dc_rinfo.ri_ops.erasecols = tga_erasecols;
+ 	dc->dc_rinfo.ri_ops.copycols = tga_copycols;
+ 	dc->dc_rinfo.ri_ops.putchar = tga_putchar;	
+ 
+ 	tga_stdscreen.nrows = dc->dc_rinfo.ri_rows;
+ 	tga_stdscreen.ncols = dc->dc_rinfo.ri_cols;
+ 	tga_stdscreen.textops = &dc->dc_rinfo.ri_ops;
+ 	tga_stdscreen.capabilities = dc->dc_rinfo.ri_caps;
+ 
+ #else /* NATHANW_RASOPS */
  	/* initialize the raster */
  	rap = &dc->dc_raster;
  	rap->width = dc->dc_wid;
***************
*** 307,312 ****
--- 397,403 ----
  
  	tga_stdscreen.nrows = dc->dc_rcons.rc_maxrow;
  	tga_stdscreen.ncols = dc->dc_rcons.rc_maxcol;
+ #endif /* NATHANW_RASOPS */
  
  	dc->dc_intrenabled = 0;
  }
***************
*** 605,616 ****
--- 696,717 ----
  	if (sc->nscreens > 0)
  		return (ENOMEM);
  
+ #ifdef NATHANW_RASOPS
+ 	*cookiep = &sc->sc_dc->dc_rinfo; /* one and only for now */
+ 	*curxp = 0;
+ 	*curyp = 0;
+ 	sc->sc_dc->dc_rinfo.ri_ops.alloc_attr(&sc->sc_dc->dc_rinfo, 
+ 		0, 0, 0, &defattr);
+ 	*attrp = defattr;
+ 	sc->nscreens++;
+ #else /* NATHANW_RASOPS */
  	*cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */
  	*curxp = 0;
  	*curyp = 0;
  	rcons_alloc_attr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr);
  	*attrp = defattr;
  	sc->nscreens++;
+ #endif /* NATHANW_RASOPS */
  	return (0);
  }
  
***************
*** 664,685 ****
  	 * Initialization includes disabling cursor, setting a sane
  	 * colormap, etc.  It will be reinitialized in tgaattach().
  	 */
- 
- 	/* XXX -- this only works for bt485, but then we only support that,
- 	 *  currently.
- 	 */
  	if (dcp->dc_tga2)
  		bt485_cninit(dcp, tga_sched_update, tga2_ramdac_wr,
  		    tga2_ramdac_rd);
! 	else
! 		bt485_cninit(dcp, tga_sched_update, tga_ramdac_wr,
! 		    tga_ramdac_rd);
! 
  	rcons_alloc_attr(&dcp->dc_rcons, 0, 0, 0, &defattr);
! 
! 	wsdisplay_cnattach(&tga_stdscreen, &dcp->dc_rcons,
! 			   0, 0, defattr);
! 
  	return(0);
  }
  
--- 765,790 ----
  	 * Initialization includes disabling cursor, setting a sane
  	 * colormap, etc.  It will be reinitialized in tgaattach().
  	 */
  	if (dcp->dc_tga2)
  		bt485_cninit(dcp, tga_sched_update, tga2_ramdac_wr,
  		    tga2_ramdac_rd);
! 	else {
! 		if (dcp->dc_tgaconf->ramdac_funcs == bt485_funcs)
! 			bt485_cninit(dcp, tga_sched_update, tga_ramdac_wr,
! 				tga_ramdac_rd);
! 		else {
! 			bt463_cninit(dcp, tga_sched_update, tga_bt463_wr,
! 				tga_bt463_rd);
! 		}
! 	}
! #ifdef NATHANW_RASOPS
! 	dcp->dc_rinfo.ri_ops.alloc_attr(&dcp->dc_rinfo, 0, 0, 0, &defattr);
! 	wsdisplay_cnattach(&tga_stdscreen, &dcp->dc_rinfo, 0, 0, defattr);
! #else /* NATHANW_RASOPS */
  	rcons_alloc_attr(&dcp->dc_rcons, 0, 0, 0, &defattr);
! 	wsdisplay_cnattach(&tga_stdscreen, &dcp->dc_rcons, 0, 0, defattr);
! #endif
! 	
  	return(0);
  }
  
***************
*** 830,835 ****
--- 935,1305 ----
  	return (0);
  }
  
+ #ifdef NATHANW_RASOPS
+ /*
+  * Copy columns (characters) in a row (line).
+  */
+ static void
+ tga_copycols(id, row, srccol, dstcol, ncols)
+ 	void *id;
+ 	int row, srccol, dstcol, ncols;
+ {
+ 	struct rasops_info *ri = id;
+ 	int y, srcx, dstx, nx;
+ 
+ 	y = ri->ri_font->fontheight * row;
+ 	srcx = ri->ri_font->fontwidth * srccol;
+ 	dstx = ri->ri_font->fontwidth * dstcol;
+ 	nx = ri->ri_font->fontwidth * ncols;
+ 
+ 	tga_rop(ri, dstx, y,
+ 	    nx, ri->ri_font->fontheight, RAS_SRC,
+ 	    ri, srcx, y);
+ }
+ 
+ /*
+  * Copy rows (lines).
+  */
+ static void
+ tga_copyrows(id, srcrow, dstrow, nrows)
+ 	void *id;
+ 	int srcrow, dstrow, nrows;
+ {
+ 	struct rasops_info *ri = id;
+ 	int srcy, dsty, ny;
+ 
+ 	srcy = ri->ri_font->fontheight * srcrow;
+ 	dsty = ri->ri_font->fontheight * dstrow;
+ 	ny = ri->ri_font->fontheight * nrows;
+ 
+ 	tga_rop(ri, 0, dsty,
+ 	    ri->ri_emuwidth, ny, RAS_SRC,
+ 	    ri, 0, srcy);
+ }
+ 
+ /* Do we need the src? */
+ static int needsrc[16] = { 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0 };
+ 
+ /* A mapping between our API and the TGA card */
+ static int map_rop[16] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6,
+ 	0xe, 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
+ };
+ 
+ /*
+  *  Generic TGA raster op.
+  *   This covers all possible raster ops, and
+  *   clips the sizes and all of that.
+  */
+ static int
+ tga_rop(dst, dx, dy, w, h, rop, src, sx, sy)
+ 	struct rasops_info *dst;
+ 	int dx, dy, w, h, rop;
+ 	struct rasops_info *src;
+ 	int sx, sy;
+ {
+ 	if (!dst)
+ 		return -1;
+ 	if (needsrc[RAS_GETOP(rop)]) {
+ 		if (src == NULL)
+ 			return -1;	/* We want a src */
+ 		/* Clip against src */
+ 		if (sx < 0) {
+ 			w += sx;
+ 			sx = 0;
+ 		}
+ 		if (sy < 0) {
+ 			h += sy;
+ 			sy = 0;
+ 		}
+ 		if (sx + w > src->ri_emuwidth)
+ 			w = src->ri_emuwidth - sx;
+ 		if (sy + h > src->ri_emuheight)
+ 			h = src->ri_emuheight - sy;
+ 	} else {
+ 		if (src != NULL)
+ 			return -1;	/* We need no src */
+ 	}
+ 	/* Clip against dst.  We modify src regardless of using it,
+ 	 * since it really doesn't matter.
+ 	 */
+ 	if (dx < 0) {
+ 		w += dx;
+ 		sx -= dx;
+ 		dx = 0;
+ 	}
+ 	if (dy < 0) {
+ 		h += dy;
+ 		sy -= dy;
+ 		dy = 0;
+ 	}
+ 	if (dx + w > dst->ri_emuwidth)
+ 		w = dst->ri_emuwidth - dx;
+ 	if (dy + h > dst->ri_emuheight)
+ 		h = dst->ri_emuheight - dy;
+ 	if (w <= 0 || h <= 0)
+ 		return 0;	/* Vacuously true; */
+ 	if (!src) {
+ 		/* XXX Punt! */
+ 		return -1;
+ 	}
+ 	return tga_rop_vtov(dst, dx, dy, w, h, rop, src, sx, sy);
+ }
+ 
+ 
+ 
+ /*
+  * Video to Video raster ops.
+  * This function deals with all raster ops that have a src and dst
+  * that are on the card.
+  */
+ static int
+ tga_rop_vtov(dst, dx, dy, w, h, rop, src, sx, sy)
+ 	struct rasops_info *dst;
+ 	int dx, dy, w, h, rop;
+ 	struct rasops_info *src;
+ 	int sx, sy;
+ {
+ 	struct tga_devconfig *dc = (struct tga_devconfig *)dst->ri_hw;
+ 	int srcb, dstb;
+ 	int x, y;
+ 	int xstart, xend, xdir, xinc;
+ 	int ystart, yend, ydir, yinc;
+ 	int offset = 1 * dc->dc_tgaconf->tgac_vvbr_units;
+ 
+ 	/*
+ 	 * I don't yet want to deal with unaligned guys, really.  And we don't
+ 	 * deal with copies from one card to another.
+ 	 */
+ 	if (dx % 8 != 0 || sx % 8 != 0 || src != dst) {
+ 		/* XXX Punt! */
+ 		return -1;
+ 	}
+ 
+ 	if (sy >= dy) {
+ 		ystart = 0;
+ 		yend = h;
+ 		ydir = 1;
+ 	} else {
+ 		ystart = h;
+ 		yend = 0;
+ 		ydir = -1;
+ 	}
+ 	if (sx >= dx) {
+ 		xstart = 0;
+ 		xend = w * (dst->ri_depth / 8);
+ 		xdir = 1;
+ 	} else {
+ 		xstart = w * (dst->ri_depth / 8);
+ 		xend = 0;
+ 		xdir = -1;
+ 	}
+ 	xinc = xdir * 4 * 64;
+ 	yinc = ydir * dst->ri_stride;
+ 	ystart *= dst->ri_stride;
+ 	yend *= dst->ri_stride;
+ 	srcb = offset + (sy + src->ri_yorigin) * src->ri_stride + 
+ 		            (sx + src->ri_xorigin) * (src->ri_depth/8);
+ 	dstb = offset + (dy + dst->ri_yorigin) * dst->ri_stride + 
+ 		            (dx + dst->ri_xorigin ) * (dst->ri_depth/8);
+ 	TGAWALREG(dc, TGA_REG_GMOR, 3, 0x0007); /* Copy mode */
+ 	TGAWALREG(dc, TGA_REG_GOPR, 3, map_rop[rop]);	/* Set up the op */
+ 	for (y = ystart; (ydir * y) < (ydir * yend); y += yinc) {
+ 		for (x = xstart; (xdir * x) < (xdir * xend); x += xinc) {
+ 		  /* XXX XXX Eight writes to different addresses should fill 
+ 		   * XXX XXX up the write buffers on 21064 and 21164 chips,
+ 		   * XXX XXX but later CPUs might have larger write buffers which
+ 		   * XXX XXX require further unrolling of this loop, or the
+ 		   * XXX XXX insertion of memory barriers.
+ 		   */
+ 			TGAWALREG(dc, TGA_REG_GCSR, 0, srcb + y + x + 3 * 64);
+ 			TGAWALREG(dc, TGA_REG_GCDR, 0, dstb + y + x + 3 * 64);
+ 			TGAWALREG(dc, TGA_REG_GCSR, 1, srcb + y + x + 2 * 64);
+ 			TGAWALREG(dc, TGA_REG_GCDR, 1, dstb + y + x + 2 * 64);
+ 			TGAWALREG(dc, TGA_REG_GCSR, 2, srcb + y + x + 1 * 64);
+ 			TGAWALREG(dc, TGA_REG_GCDR, 2, dstb + y + x + 1 * 64);
+ 			TGAWALREG(dc, TGA_REG_GCSR, 3, srcb + y + x + 0 * 64);
+ 			TGAWALREG(dc, TGA_REG_GCDR, 3, dstb + y + x + 0 * 64);
+ 		}
+ 	}
+ 	TGAWALREG(dc, TGA_REG_GOPR, 0, 0x0003); /* op -> dst = src */
+ 	TGAWALREG(dc, TGA_REG_GMOR, 0, 0x0000); /* Simple mode */
+ 	return 0;
+ }
+ 
+ 
+ void tga_putchar (c, row, col, uc, attr)
+ 	void *c;
+ 	int row, col;
+ 	u_int uc;
+ 	long attr;
+ {
+ 	struct rasops_info *ri = c;
+ 	struct tga_devconfig *dc = ri->ri_hw;
+ 	int fs, height, width;
+ 	u_char *fr;
+ 	int32_t *rp;
+ 
+ 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
+ 
+ 	height = ri->ri_font->fontheight;
+ 	width = ri->ri_font->fontwidth;
+ 
+ 	uc -= ri->ri_font->firstchar;
+ 	fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
+ 	fs = ri->ri_font->stride;
+ 
+ 	/* Set foreground and background color. XXX memoize this somehow?
+ 	 * The rasops code has already expanded the color entry to 32 bits
+ 	 * for us, even for 8-bit displays, so we don't have to do anything.
+ 	 */
+ 	TGAWREG(dc, TGA_REG_GFGR, ri->ri_devcmap[(attr >> 24) & 15]);
+ 	TGAWREG(dc, TGA_REG_GBGR, ri->ri_devcmap[(attr >> 16) & 15]);
+ 	
+ 	/* Set raster operation to "copy"... */
+ 	if (ri->ri_depth == 8)
+ 		TGAWREG(dc, TGA_REG_GOPR, 0x3);
+ 	else /* ... and in 24-bit mode, set the destination bitmap to 24-bit. */
+ 		TGAWREG(dc, TGA_REG_GOPR, 0x3 | (0x3 << 8));
+ 
+ 	/* Set which pixels we're drawing (of a possible 32). */
+ 	TGAWREG(dc, TGA_REG_GPXR_P, (1 << width) - 1);
+ 
+ 	/* Set drawing mode to opaque stipple. */
+ 	TGAWREG(dc, TGA_REG_GMOR, 0x1);
+ 	
+ 	/* Insert write barrier before actually sending data */
+ 	/* XXX Abuses the fact that there is only one write barrier on Alphas */
+ 	TGAREGWB(dc, TGA_REG_GMOR, 1);
+ 
+ 	while(height--) {
+ 		/* The actual stipple write */
+ 		*rp = fr[0] | (fr[1] << 8) | (fr[2] << 16) | (fr[3] << 24); 
+ 						  
+ 		fr += fs;
+ 		rp = (int32_t *)((caddr_t)rp + ri->ri_stride);
+ 	}
+ 
+ 	/* Do underline */
+ 	if ((attr & 1) != 0) {
+ 		rp = (int32_t *)((caddr_t)rp - (ri->ri_stride << 1));
+ 		*rp = 0xffffffff;
+ 	}
+ 
+ 	/* Set grapics mode back to normal. */
+ 	TGAWREG(dc, TGA_REG_GMOR, 0);
+ 	TGAWREG(dc, TGA_REG_GPXR_P, 0xffffffff);
+ 
+ }
+ 
+ static void
+ tga_eraserows(c, row, num, attr)
+ 	void *c;
+ 	int row, num;
+ 	long attr;
+ {
+ 	struct rasops_info *ri = c;
+ 	struct tga_devconfig *dc = ri->ri_hw;
+ 	int32_t color, lines, pixels;
+ 	int32_t *rp;
+ 
+ 	color = ri->ri_devcmap[(attr >> 16) & 15];
+ 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale);
+ 	lines = num * ri->ri_font->fontheight;
+ 	pixels = ri->ri_emuwidth - 1;
+ 
+ 	/* Set fill color in block-color registers */
+ 	TGAWREG(dc, TGA_REG_GBCR0, color);
+ 	TGAWREG(dc, TGA_REG_GBCR1, color);
+ 	if (ri->ri_depth != 8) {
+ 		TGAWREG(dc, TGA_REG_GBCR2, color);
+ 		TGAWREG(dc, TGA_REG_GBCR3, color);
+ 		TGAWREG(dc, TGA_REG_GBCR4, color);
+ 		TGAWREG(dc, TGA_REG_GBCR5, color);
+ 		TGAWREG(dc, TGA_REG_GBCR6, color);
+ 		TGAWREG(dc, TGA_REG_GBCR7, color);
+ 	}
+ 
+ 	/* Set raster operation to "copy"... */
+ 	if (ri->ri_depth == 8)
+ 		TGAWREG(dc, TGA_REG_GOPR, 0x3);
+ 	else /* ... and in 24-bit mode, set the destination bitmap to 24-bit. */
+ 		TGAWREG(dc, TGA_REG_GOPR, 0x3 | (0x3 << 8));
+ 
+ 	/* Set which pixels we're drawing (of a possible 32). */
+ 	TGAWREG(dc, TGA_REG_GDAR, 0xffffffff);
+ 
+ 	/* Set drawing mode to block fill. */
+ 	TGAWREG(dc, TGA_REG_GMOR, 0x2d);
+ 	
+ 	/* Insert write barrier before actually sending data */
+ 	/* XXX Abuses the fact that there is only one write barrier on Alphas */
+ 	TGAREGWB(dc, TGA_REG_GMOR, 1);
+ 
+ 	while (lines--) {
+ 		*rp = pixels;
+ 		rp = (int32_t *)((caddr_t)rp + ri->ri_stride);
+ 	}
+ 
+ 	/* Set grapics mode back to normal. */
+ 	TGAWREG(dc, TGA_REG_GMOR, 0);
+ 	
+ }
+ 
+ static void
+ tga_erasecols (c, row, col, num, attr)
+ void *c;
+ int row, col, num;
+ long attr;
+ {
+ 	struct rasops_info *ri = c;
+ 	struct tga_devconfig *dc = ri->ri_hw;
+ 	int32_t color, lines, pixels;
+ 	int32_t *rp;
+ 
+ 	color = ri->ri_devcmap[(attr >> 16) & 15];
+ 	rp = (int32_t *)(ri->ri_bits + row*ri->ri_yscale + col*ri->ri_xscale);
+ 	lines = ri->ri_font->fontheight;
+ 	pixels = (num * ri->ri_font->fontwidth) - 1;
+ 
+ 	/* Set fill color in block-color registers */
+ 	TGAWREG(dc, TGA_REG_GBCR0, color);
+ 	TGAWREG(dc, TGA_REG_GBCR1, color);
+ 	if (ri->ri_depth != 8) {
+ 		TGAWREG(dc, TGA_REG_GBCR2, color);
+ 		TGAWREG(dc, TGA_REG_GBCR3, color);
+ 		TGAWREG(dc, TGA_REG_GBCR4, color);
+ 		TGAWREG(dc, TGA_REG_GBCR5, color);
+ 		TGAWREG(dc, TGA_REG_GBCR6, color);
+ 		TGAWREG(dc, TGA_REG_GBCR7, color);
+ 	}
+ 
+ 	/* Set raster operation to "copy"... */
+ 	if (ri->ri_depth == 8)
+ 		TGAWREG(dc, TGA_REG_GOPR, 0x3);
+ 	else /* ... and in 24-bit mode, set the destination bitmap to 24-bit. */
+ 		TGAWREG(dc, TGA_REG_GOPR, 0x3 | (0x3 << 8));
+ 
+ 	/* Set which pixels we're drawing (of a possible 32). */
+ 	TGAWREG(dc, TGA_REG_GDAR, 0xffffffff);
+ 
+ 	/* Set drawing mode to block fill. */
+ 	TGAWREG(dc, TGA_REG_GMOR, 0x2d);
+ 	
+ 	/* Insert write barrier before actually sending data */
+ 	/* XXX Abuses the fact that there is only one write barrier on Alphas */
+ 	TGAREGWB(dc, TGA_REG_GMOR, 1);
+ 
+ 	while (lines--) {
+ 		*rp = pixels;
+ 		rp = (int32_t *)((caddr_t)rp + ri->ri_stride);
+ 	}
+ 
+ 	/* Set grapics mode back to normal. */
+ 	TGAWREG(dc, TGA_REG_GMOR, 0);
+ 
+ }
+ 
+ #else /* NATHANW_RASOPS */
  /*
   * Copy columns (characters) in a row (line).
   */
***************
*** 1042,1047 ****
--- 1512,1518 ----
  	TGAWALREG(dc, TGA_REG_GMOR, 0, 0x0000); /* Simple mode */
  	return 0;
  }
+ #endif /* NATHANW_RASOPS */
  
  static void
  tga_ramdac_wr(v, btreg, val)
Index: pci/tgavar.h
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pci/tgavar.h,v
retrieving revision 1.8
diff -c -r1.8 tgavar.h
*** tgavar.h	2000/04/02 19:01:11	1.8
--- tgavar.h	2000/04/07 21:34:31
***************
*** 32,37 ****
--- 32,39 ----
  #include <dev/rcons/raster.h>
  #include <dev/wscons/wsconsio.h>
  #include <dev/wscons/wscons_raster.h>
+ #include <dev/wscons/wsdisplayvar.h>
+ #include <dev/rasops/rasops.h>
  
  struct tga_devconfig;
  struct fbcmap;
***************
*** 83,90 ****
--- 85,96 ----
  
  	vaddr_t dc_videobase;	/* base of flat frame buffer */
  
+ #ifdef NATHANW_RASOPS
+ 	struct rasops_info dc_rinfo;	/* raster display data */
+ #else
  	struct raster	dc_raster;	/* raster description */
  	struct rcons	dc_rcons;	/* raster blitter control info */
+ #endif
  
  	int	    dc_blanked;		/* currently had video disabled */
  	void	    *dc_ramdac_private; /* RAMDAC private storage */