Index: arch/arm/xscale/files.pxa2x0
===================================================================
RCS file: /cvsroot/src/sys/arch/arm/xscale/files.pxa2x0,v
retrieving revision 1.12
diff -u -r1.12 files.pxa2x0
--- arch/arm/xscale/files.pxa2x0	17 Dec 2006 16:03:33 -0000	1.12
+++ arch/arm/xscale/files.pxa2x0	18 Dec 2006 09:43:20 -0000
@@ -42,7 +42,7 @@
 file	arch/arm/sa11x0/sa11x0_ost.c		saost needs-flag
 
 # LCD controller
-device lcd: wsemuldisplaydev, rasops16, rasops8, rasops4
+device lcd: wsemuldisplaydev, rasops16, rasops8, rasops4, rasops_rotation
 file arch/arm/xscale/pxa2x0_lcd.c		lcd needs-flag
 
 # XXX this is a hack to use dev/pcmcia without fdc.c
Index: arch/zaurus/dev/zlcd.c
===================================================================
RCS file: /cvsroot/src/sys/arch/zaurus/dev/zlcd.c,v
retrieving revision 1.2
diff -u -r1.2 zlcd.c
--- arch/zaurus/dev/zlcd.c	17 Dec 2006 16:07:11 -0000	1.2
+++ arch/zaurus/dev/zlcd.c	18 Dec 2006 09:43:20 -0000
@@ -77,7 +77,7 @@
 		.capabilities = WSSCREEN_WSCOLORS,
 	},
 	.depth = 16,			/* bits per pixel */
-	.flags = 0/*RI_ROTATE_CW*/,	/* quarter clockwise rotation */
+	.flags = RI_ROTATE_CW,		/* quarter clockwise rotation */
 };
 
 static const struct wsscreen_descr *lcd_scr_descr[] = {
Index: conf/files
===================================================================
RCS file: /cvsroot/src/sys/conf/files,v
retrieving revision 1.820
diff -u -r1.820 files
--- conf/files	11 Dec 2006 15:24:28 -0000	1.820
+++ conf/files	18 Dec 2006 09:43:21 -0000
@@ -297,6 +297,7 @@
 define	rasops16
 define	rasops24
 define	rasops32
+define	rasops_rotation
 
 # splash screen support
 include "dev/splash/files.splash"
Index: dev/wsfont/files.wsfont
===================================================================
RCS file: /cvsroot/src/sys/dev/wsfont/files.wsfont,v
retrieving revision 1.14
diff -u -r1.14 files.wsfont
--- dev/wsfont/files.wsfont	11 Dec 2005 12:24:12 -0000	1.14
+++ dev/wsfont/files.wsfont	18 Dec 2006 09:43:21 -0000
@@ -2,7 +2,10 @@
 
 defpseudo wsfont
 
-file	dev/wsfont/wsfont.c	rasterconsole | wsdisplay | wsfont
+# Note: `wsfont_glue' is only here to force the header file's name
+#	hence it must be mentioned first  (shudder...)
+file	dev/wsfont/wsfont.c	(wsfont_glue & rasops_rotation) |
+    rasterconsole | wsdisplay | wsfont		needs-flag
 
 defflag	opt_wsfont.h		FONT_BOLD8x16
 				FONT_GALLANT12x22
Index: dev/wsfont/wsfont.c
===================================================================
RCS file: /cvsroot/src/sys/dev/wsfont/wsfont.c,v
retrieving revision 1.43
diff -u -r1.43 wsfont.c
--- dev/wsfont/wsfont.c	28 Aug 2006 21:35:12 -0000	1.43
+++ dev/wsfont/wsfont.c	18 Dec 2006 09:43:22 -0000
@@ -51,6 +51,8 @@
 #include <dev/wscons/wsconsio.h>
 #include <dev/wsfont/wsfont.h>
 
+#include "wsfont_glue.h"	/* NRASOPS_ROTATION */
+
 #undef HAVE_FONT
 
 #ifdef FONT_QVSS8x15
@@ -300,6 +302,100 @@
 	}
 }
 
+#if NRASOPS_ROTATION > 0
+
+struct wsdisplay_font *wsfont_rotate_internal(struct wsdisplay_font *);
+
+struct wsdisplay_font *
+wsfont_rotate_internal(struct wsdisplay_font *font)
+{
+	int b, n, r, newstride;
+	struct wsdisplay_font *newfont;
+	char *newbits;
+
+	/* Duplicate the existing font... */
+	newfont = malloc(sizeof(*font), M_DEVBUF, M_WAITOK);
+	if (newfont == NULL)
+		return (NULL);
+
+	memcpy(newfont, font, sizeof(*font));
+
+	/* Allocate a buffer big enough for the rotated font. */
+	newstride = (font->fontheight + 7) / 8;
+	newbits = malloc(newstride * font->fontwidth * font->numchars,
+	    M_DEVBUF, M_WAITOK);
+	if (newbits == NULL) {
+		free(newfont, M_DEVBUF);
+		return (NULL);
+	}
+
+	memset(newbits, 0, newstride * font->fontwidth * font->numchars);
+
+	/* Rotate the font a bit at a time. */
+	for (n = 0; n < font->numchars; n++) {
+		char *ch = (char *)font->data +
+		    (n * font->stride * font->fontheight);
+
+		for (r = 0; r < font->fontheight; r++) {
+			for (b = 0; b < font->fontwidth; b++) {
+				unsigned char *rb;
+
+				rb = ch + (font->stride * r) + (b / 8);
+				if (*rb & (0x80 >> (b % 8))) {
+					unsigned char *rrb;
+
+					rrb = newbits + newstride - 1 - (r / 8)
+					    + (n * newstride * font->fontwidth)
+					    + (newstride * b);
+					*rrb |= (1 << (r % 8));
+				}
+			}
+		}
+	}
+
+	newfont->data = newbits;
+
+	/* Update font sizes. */
+	newfont->stride = newstride;
+	newfont->fontwidth = font->fontheight;
+	newfont->fontheight = font->fontwidth;
+
+	if (wsfont_add(newfont, 0) != 0) {
+		/*
+		 * If we seem to have rotated this font already, drop the
+		 * new one...
+		 */
+		free(newbits, M_DEVBUF);
+		free(newfont, M_DEVBUF);
+		newfont = NULL;
+	}
+
+	return (newfont);
+}
+
+int
+wsfont_rotate(int cookie)
+{
+	int s, ncookie;
+	struct wsdisplay_font *font;
+	struct font *origfont;
+
+	s = splhigh();
+	origfont = wsfont_find0(cookie, 0xffffffff);
+	splx(s);
+
+	font = wsfont_rotate_internal(origfont->font);
+	if (font == NULL)
+		return (-1);
+
+	ncookie = wsfont_find(font->name, font->fontwidth, font->fontheight, 
+	    font->stride, 0, 0);
+
+	return (ncookie);
+}
+
+#endif	/* NRASOPS_ROTATION */
+
 void
 wsfont_init(void)
 {
Index: dev/wsfont/wsfont.h
===================================================================
RCS file: /cvsroot/src/sys/dev/wsfont/wsfont.h,v
retrieving revision 1.17
diff -u -r1.17 wsfont.h
--- dev/wsfont/wsfont.h	9 Feb 2003 10:29:38 -0000	1.17
+++ dev/wsfont/wsfont.h	18 Dec 2006 09:43:22 -0000
@@ -69,5 +69,6 @@
 int	wsfont_lock(int, struct wsdisplay_font **);
 int	wsfont_unlock(int);
 int	wsfont_map_unichar(struct wsdisplay_font *, int);
+int	wsfont_rotate(int);
 
 #endif	/* !_WSFONT_H_ */
Index: dev/rasops/files.rasops
===================================================================
RCS file: /cvsroot/src/sys/dev/rasops/files.rasops,v
retrieving revision 1.11
diff -u -r1.11 files.rasops
--- dev/rasops/files.rasops	11 Dec 2005 12:23:43 -0000	1.11
+++ dev/rasops/files.rasops	18 Dec 2006 09:43:22 -0000
@@ -4,7 +4,7 @@
 #       hence it must be mentioned first  (shudder...)
 file dev/rasops/rasops.c ( (rasops_glue |
     rasops1 | rasops2 | rasops4 | rasops8 | rasops15 | rasops16 | rasops24 |
-    rasops32) &
+    rasops32 | rasops_rotation) &
     (rasterconsole | wsdisplay)) needs-flag
 
 file dev/rasops/rasops_masks.c ((rasterconsole | wsdisplay) &
Index: dev/rasops/rasops.c
===================================================================
RCS file: /cvsroot/src/sys/dev/rasops/rasops.c,v
retrieving revision 1.54
diff -u -r1.54 rasops.c
--- dev/rasops/rasops.c	16 Nov 2006 01:33:26 -0000	1.54
+++ dev/rasops/rasops.c	18 Dec 2006 09:43:23 -0000
@@ -135,6 +135,26 @@
 static void	rasops_do_cursor(struct rasops_info *);
 static void	rasops_init_devcmap(struct rasops_info *);
 
+#if NRASOPS_ROTATION > 0
+static void	rasops_copychar(void *, int, int, int, int);
+static void	rasops_copycols_rotated(void *, int, int, int, int);
+static void	rasops_copyrows_rotated(void *, int, int, int);
+static void	rasops_erasecols_rotated(void *, int, int, int, long);
+static void	rasops_eraserows_rotated(void *, int, int, long);
+static void	rasops_putchar_rotated(void *, int, int, u_int, long);
+static void	rasops_rotate_font(int *);
+
+/*
+ * List of all rotated fonts
+ */
+SLIST_HEAD(, rotatedfont) rotatedfonts = SLIST_HEAD_INITIALIZER(rotatedfonts);
+struct rotatedfont {
+	SLIST_ENTRY(rotatedfont) rf_next;
+	int rf_cookie;
+	int rf_rotated;
+};
+#endif	/* NRASOPS_ROTATION > 0 */
+
 /*
  * Initialize a 'rasops_info' descriptor.
  */
@@ -163,6 +183,15 @@
 			return (-1);
 		}
 
+#if NRASOPS_ROTATION > 0
+		/*
+		 * Pick the rotated version of this font. This will create it
+		 * if necessary.
+		 */
+		if (ri->ri_flg & RI_ROTATE_CW)
+			rasops_rotate_font(&cookie);
+#endif
+
 		if (wsfont_lock(cookie, &ri->ri_font)) {
 			printf("rasops_init: couldn't lock font\n");
 			return (-1);
@@ -234,8 +263,17 @@
 	while ((ri->ri_emuwidth * bpp & 31) != 0)
 		ri->ri_emuwidth--;
 
-	ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth;
-	ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight;
+#if NRASOPS_ROTATION > 0
+	if (ri->ri_flg & RI_ROTATE_CW) {
+		ri->ri_rows = ri->ri_emuwidth / ri->ri_font->fontwidth;
+		ri->ri_cols = ri->ri_emuheight / ri->ri_font->fontheight;
+	} else
+#endif
+	{
+
+		ri->ri_cols = ri->ri_emuwidth / ri->ri_font->fontwidth;
+		ri->ri_rows = ri->ri_emuheight / ri->ri_font->fontheight;
+	}
 	ri->ri_emustride = ri->ri_emuwidth * bpp >> 3;
 	ri->ri_delta = ri->ri_stride - ri->ri_emustride;
 	ri->ri_ccol = 0;
@@ -334,6 +372,17 @@
 		return (-1);
 	}
 
+#if NRASOPS_ROTATION > 0
+	if (ri->ri_flg & RI_ROTATE_CW) {
+		ri->ri_real_ops = ri->ri_ops;
+		ri->ri_ops.copycols = rasops_copycols_rotated;
+		ri->ri_ops.copyrows = rasops_copyrows_rotated;
+		ri->ri_ops.erasecols = rasops_erasecols_rotated;
+		ri->ri_ops.eraserows = rasops_eraserows_rotated;
+		ri->ri_ops.putchar = rasops_putchar_rotated;
+	}
+#endif
+
 	ri->ri_flg |= RI_CFGDONE;
 	splx(s);
 	return (0);
@@ -853,8 +902,17 @@
 
 	hrp = hp = NULL;
 
-	row = ri->ri_crow;
-	col = ri->ri_ccol;
+#if NRASOPS_ROTATION > 0
+	if (ri->ri_flg & RI_ROTATE_CW) {
+		/* Rotate rows/columns */
+		row = ri->ri_ccol;
+		col = ri->ri_rows - ri->ri_crow - 1;
+	} else
+#endif
+	{
+		row = ri->ri_crow;
+		col = ri->ri_ccol;
+	}
 
 	rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
 	if (ri->ri_hwbits)
@@ -1114,3 +1172,175 @@
 		}
 	}
 }
+
+#if NRASOPS_ROTATION > 0
+/*
+ * Quarter clockwise rotation routines (originally intended for the
+ * built-in Zaurus C3x00 display in 16bpp).
+ */
+
+#include <sys/malloc.h>
+
+static void
+rasops_rotate_font(int *cookie)
+{
+	struct rotatedfont *f;
+	int ncookie;
+
+	SLIST_FOREACH(f, &rotatedfonts, rf_next) {
+		if (f->rf_cookie == *cookie) {
+			*cookie = f->rf_rotated;
+			return;
+		}
+	}
+
+	/*
+	 * We did not find a rotated version of this font. Ask the wsfont
+	 * code to compute one for us.
+	 */
+
+	f = malloc(sizeof(struct rotatedfont), M_DEVBUF, M_WAITOK);
+	if (f == NULL)
+		return;
+
+	if ((ncookie = wsfont_rotate(*cookie)) == -1)
+		return;
+
+	f->rf_cookie = *cookie;
+	f->rf_rotated = ncookie;
+	SLIST_INSERT_HEAD(&rotatedfonts, f, rf_next);
+
+	*cookie = ncookie;
+}
+
+static void
+rasops_copychar(cookie, srcrow, dstrow, srccol, dstcol)
+	void *cookie;
+	int srcrow, dstrow, srccol, dstcol;
+{
+	struct rasops_info *ri;
+	u_char *sp, *dp;
+	int height;
+	int r_srcrow, r_dstrow, r_srccol, r_dstcol;
+
+	ri = (struct rasops_info *)cookie;
+
+	r_srcrow = srccol;
+	r_dstrow = dstcol;
+	r_srccol = ri->ri_rows - srcrow - 1;
+	r_dstcol = ri->ri_rows - dstrow - 1;
+
+	r_srcrow *= ri->ri_yscale;
+	r_dstrow *= ri->ri_yscale;
+	height = ri->ri_font->fontheight;
+
+	sp = ri->ri_bits + r_srcrow + r_srccol * ri->ri_xscale;
+	dp = ri->ri_bits + r_dstrow + r_dstcol * ri->ri_xscale;
+
+	while (height--) {
+		memmove(dp, sp, ri->ri_xscale);
+		dp += ri->ri_stride;
+		sp += ri->ri_stride;
+	}
+}
+
+static void
+rasops_putchar_rotated(cookie, row, col, uc, attr)
+	void *cookie;
+	int row, col;
+	u_int uc;
+	long attr;
+{
+	struct rasops_info *ri;
+	u_char *rp;
+	int height;
+
+	ri = (struct rasops_info *)cookie;
+
+	/* Do rotated char sans (side)underline */
+	ri->ri_real_ops.putchar(cookie, col, ri->ri_rows - row - 1, uc,
+	    attr & ~1);
+
+	/* Do rotated underline */
+	rp = ri->ri_bits + col * ri->ri_yscale + (ri->ri_rows - row - 1) * 
+	    ri->ri_xscale;
+	height = ri->ri_font->fontheight;
+
+	/* XXX this assumes 16-bit color depth */
+	if ((attr & 1) != 0) {
+		int16_t c = (int16_t)ri->ri_devcmap[((u_int)attr >> 24) & 0xf];
+
+		while (height--) {
+			*(int16_t *)rp = c;
+			rp += ri->ri_stride;
+		}
+	}
+}
+
+static void
+rasops_erasecols_rotated(cookie, row, col, num, attr)
+	void *cookie;
+	int row, col, num;
+	long attr;
+{
+	struct rasops_info *ri;
+	int i;
+
+	ri = (struct rasops_info *)cookie;
+
+	for (i = col; i < col + num; i++)
+		ri->ri_ops.putchar(cookie, row, i, ' ', attr);
+}
+
+/* XXX: these could likely be optimised somewhat. */
+static void
+rasops_copyrows_rotated(cookie, src, dst, num)
+	void *cookie;
+	int src, dst, num;
+{
+	struct rasops_info *ri = (struct rasops_info *)cookie;
+	int col, roff;
+
+	if (src > dst)
+		for (roff = 0; roff < num; roff++)
+			for (col = 0; col < ri->ri_cols; col++)
+				rasops_copychar(cookie, src + roff, dst + roff,
+				    col, col);
+	else
+		for (roff = num - 1; roff >= 0; roff--)
+			for (col = 0; col < ri->ri_cols; col++)
+				rasops_copychar(cookie, src + roff, dst + roff,
+				    col, col);
+}
+
+static void
+rasops_copycols_rotated(cookie, row, src, dst, num)
+	void *cookie;
+	int row, src, dst, num;
+{
+	int coff;
+
+	if (src > dst)
+		for (coff = 0; coff < num; coff++)
+			rasops_copychar(cookie, row, row, src + coff, dst + coff);
+	else
+		for (coff = num - 1; coff >= 0; coff--)
+			rasops_copychar(cookie, row, row, src + coff, dst + coff);
+}
+
+static void
+rasops_eraserows_rotated(cookie, row, num, attr)
+	void *cookie;
+	int row, num;
+	long attr;
+{
+	struct rasops_info *ri;
+	int col, rn;
+
+	ri = (struct rasops_info *)cookie;
+
+	for (rn = row; rn < row + num; rn++)
+		for (col = 0; col < ri->ri_cols; col++)
+			ri->ri_ops.putchar(cookie, rn, col, ' ', attr);
+}
+#endif	/* NRASOPS_ROTATION */
Index: dev/rasops/rasops.h
===================================================================
RCS file: /cvsroot/src/sys/dev/rasops/rasops.h,v
retrieving revision 1.19
diff -u -r1.19 rasops.h
--- dev/rasops/rasops.h	18 Feb 2006 13:57:33 -0000	1.19
+++ dev/rasops/rasops.h	18 Dec 2006 09:43:23 -0000
@@ -50,6 +50,7 @@
 #define RI_CENTER	0x20	/* center onscreen output */
 #define RI_CURSORCLIP	0x40	/* cursor is currently clipped */
 #define RI_CFGDONE	0x80	/* rasops_reconfig() completed successfully */
+#define RI_ROTATE_CW	0x100	/* display is rotated, quarter clockwise */
 
 struct rasops_info {
 	/* These must be filled in by the caller */
@@ -110,6 +111,11 @@
 
 	/* Callbacks so we can share some code */
 	void	(*ri_do_cursor)(struct rasops_info *);
+
+#if NRASOPS_ROTATION > 0
+	/* Used to intercept putchar to permit display rotation */
+	struct	wsdisplay_emulops ri_real_ops;
+#endif
 };
 
 #define DELTA(p, d, cast) ((p) = (cast)((caddr_t)(p) + (d)))
