patch-2.1.91 linux/drivers/video/fbcon-mac.c

Next file: linux/drivers/video/fbcon-mac.h
Previous file: linux/drivers/video/fbcon-iplan2p8.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.90/linux/drivers/video/fbcon-mac.c linux/drivers/video/fbcon-mac.c
@@ -0,0 +1,513 @@
+/*
+ *  linux/drivers/video/fbcon-mac.c -- Low level frame buffer operations for 
+ *				       x bpp packed pixels, font width != 8
+ *
+ *	Created 26 Dec 1997 by Michael Schmitz
+ *	Based on the old macfb.c 6x11 code by Randy Thelen
+ *
+ *	This driver is significantly slower than the 8bit font drivers 
+ *	and would probably benefit from splitting into drivers for each depth.
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive for
+ */
+
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/string.h>
+#include <linux/config.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+
+#include "fbcon.h"
+#include "fbcon-mac.h"
+
+
+    /*
+     *  variable bpp packed pixels
+     */
+
+static void plot_pixel_mac(struct display *p, int bw, int pixel_x,
+			   int pixel_y);
+static int get_pixel_mac(struct display *p, int pixel_x, int pixel_y);
+
+void fbcon_mac_setup(struct display *p)
+{
+    if (p->line_length)
+	p->next_line = p->line_length;
+    else
+    	p->next_line = p->var.xres_virtual>>3;
+    p->next_plane = 0;
+}
+
+
+   /*
+    *    Macintosh
+    */
+#define PIXEL_BLACK_MAC          0
+#define PIXEL_WHITE_MAC          1
+#define PIXEL_INVERT_MAC         2
+
+void fbcon_mac_bmove(struct display *p, int sy, int sx, int dy, int dx,
+		     int height, int width)
+{
+   int i, j;
+   u8 *dest, *src;
+   int l,r,t,b,w,lo,s;
+   int dl,dr,dt,db,dw,dlo;
+   int move_up;
+
+   src = (u8 *) (p->screen_base + sy * p->fontheight * p->next_line);
+   dest = (u8 *) (p->screen_base + dy * p->fontheight * p->next_line);
+
+   if( sx == 0 && width == p->conp->vc_cols) {
+     s = height * p->fontheight * p->next_line;
+     mymemmove(dest, src, s);
+     return;
+   }
+   
+   l = sx * p->fontwidth;
+   r = l + width * p->fontwidth;
+   t = sy * p->fontheight;
+   b = t + height * p->fontheight;
+
+   dl = dx * p->fontwidth;
+   dr = dl + width * p->fontwidth;
+   dt = dy * p->fontheight;
+   db = dt + height * p->fontheight;
+
+   /* w is the # pixels between two long-aligned points, left and right */
+   w = (r&~31) - ((l+31)&~31);
+   dw = (dr&~31) - ((dl+31)&~31);
+   /* lo is the # pixels between the left edge and a long-aligned left pixel */
+   lo = ((l+31)&~31) - l;
+   dlo = ((dl+31)&~31) - dl;
+   
+   /* if dx != sx then, logic has to align the left and right edges for fast moves */
+   if (lo != dlo) {
+     lo = ((l+7)&~7) - l;
+     dlo = ((dl+7)&~7) - dl;
+     w = (r&~7) - ((l+7)&~7);
+     dw = (dr&~7) - ((dl+7)&~7);
+     if (lo != dlo) {
+       char err_str[256];
+       unsigned long cnt;
+       sprintf( err_str, "ERROR: Shift algorithm: sx=%d,sy=%d,dx=%d,dy=%d,w=%d,h=%d,bpp=%d",
+		sx,sy,dx,dy,width,height,p->var.bits_per_pixel);
+       fbcon_mac_putcs(p->conp, p, err_str, strlen(err_str), 0, 0);
+       /* pause for the user */
+       for(cnt = 0; cnt < 50000; cnt++)
+		udelay(100);
+       return;
+     }
+   }
+
+   s = 0;
+   switch (p->var.bits_per_pixel) {
+   case 1:
+     s = w >> 3;
+     src += lo >> 3;
+     dest += lo >> 3;
+     break;
+   case 2:
+     s = w >> 2;
+     src += lo >> 2;
+     dest += lo >> 2;
+     break;
+   case 4:
+     s = w >> 1;
+     src += lo >> 1;
+     dest += lo >> 1;
+     break;
+   case 8:
+     s = w;
+     src += lo;
+     dest += lo;
+     break;
+   case 16:
+     s = w << 1;
+     src += lo << 1;
+     dest += lo << 1;
+     break;
+   case 32:
+     s = w << 2;
+     src += lo << 2;
+     dest += lo << 2;
+     break;
+   }
+
+   if (sy <= sx) {
+     i = b;
+     move_up = 0;
+     src += height * p->fontheight;
+     dest += height * p->fontheight;
+   } else {
+     i = t;
+     move_up = 1;
+   }
+
+   while (1) {
+     for (i = t; i < b; i++) {
+       j = l;
+
+       for (; j & 31 && j < r; j++)
+	 plot_pixel_mac(p, get_pixel_mac(p, j+(dx-sx), i+(dy-sy)), j, i);
+
+       if (j < r) {
+	 mymemmove(dest, src, s);
+	 if (move_up) {
+	   dest += p->next_line;
+	   src += p->next_line;
+	 } else {
+	   dest -= p->next_line;
+	   src -= p->next_line;
+	 }
+	 j += w;
+       }
+     
+       for (; j < r; j++)
+	 plot_pixel_mac(p, get_pixel_mac(p, j+(dx-sx), i+(dy-sy)), j, i);
+     }
+
+     if (move_up) {
+       i++;
+       if (i >= b)
+	 break;
+     } else {
+       i--;
+       if (i < t)
+	 break;
+     }
+   }
+}
+
+
+void fbcon_mac_clear(struct vc_data *conp, struct display *p, int sy, int sx,
+		     int height, int width)
+{
+   int pixel;
+   int i, j;
+   int inverse;
+   u8 *dest;
+   int l,r,t,b,w,lo,s;
+
+   inverse = attr_reverse(p,conp);
+   pixel = inverse ? PIXEL_WHITE_MAC : PIXEL_BLACK_MAC;
+   dest = (u8 *) (p->screen_base + sy * p->fontheight * p->next_line);
+
+   if( sx == 0 && width == p->conp->vc_cols) {
+     s = height * p->fontheight * p->next_line;
+     if (inverse)
+       mymemclear(dest, s);
+     else
+       mymemset(dest, s);
+   }
+   
+   l = sx * p->fontwidth;
+   r = l + width * p->fontwidth;
+   t = sy * p->fontheight;
+   b = t + height * p->fontheight;
+   /* w is the # pixels between two long-aligned points, left and right */
+   w = (r&~31) - ((l+31)&~31);
+   /* lo is the # pixels between the left edge and a long-aligned left pixel */
+   lo = ((l+31)&~31) - l;
+   s = 0;
+   switch (p->var.bits_per_pixel) {
+   case 1:
+     s = w >> 3;
+     dest += lo >> 3;
+     break;
+   case 2:
+     s = w >> 2;
+     dest += lo >> 2;
+     break;
+   case 4:
+     s = w >> 1;
+     dest += lo >> 1;
+     break;
+   case 8:
+     s = w;
+     dest += lo;
+     break;
+   case 16:
+     s = w << 1;
+     dest += lo << 1;
+     break;
+   case 32:
+     s = w << 2;
+     dest += lo << 2;
+     break;
+   }
+
+   for (i = t; i < b; i++) {
+     j = l;
+
+     for (; j & 31 && j < r; j++)
+       plot_pixel_mac(p, pixel, j, i);
+
+     if (j < r) {
+       if (PIXEL_WHITE_MAC == pixel)
+	 mymemclear(dest, s);
+       else
+	 mymemset(dest, s);
+       dest += p->next_line;
+       j += w;
+     }
+     
+     for (; j < r; j++)
+       plot_pixel_mac(p, pixel, j, i);
+   }
+}
+
+
+void fbcon_mac_putc(struct vc_data *conp, struct display *p, int c, int yy,
+		    int xx)
+{
+   u8 *cdat;
+   u_int rows, bold, ch_reverse, ch_underline;
+   u8 d;
+   int j;
+
+   c &= 0xff;
+
+   cdat = p->fontdata+c*p->fontheight;
+   bold = attr_bold(p,conp);
+   ch_reverse = attr_reverse(p,conp);
+   ch_underline = attr_underline(p,conp);
+
+   for (rows = 0; rows < p->fontheight; rows++) {
+      d = *cdat++;
+      if (!conp->vc_can_do_color) {
+	if (ch_underline && rows == (p->fontheight-2))
+	  d = 0xff;
+	else if (bold)
+	  d |= d>>1;
+	if (ch_reverse)
+	  d = ~d;
+      }
+      for (j = 0; j < p->fontwidth; j++) {
+	plot_pixel_mac(p, (d & 0x80) >> 7, (xx*p->fontwidth) + j, (yy*p->fontheight) + rows);
+	d <<= 1;
+      }
+   }
+}
+
+
+void fbcon_mac_putcs(struct vc_data *conp, struct display *p, const char *s,
+		     int count, int yy, int xx)
+{
+   u8 c;
+
+   while (count--) {
+      c = *s++;
+      fbcon_mac_putc(conp, p, c, yy, xx++);
+   }
+}
+
+
+void fbcon_mac_revc(struct display *p, int xx, int yy)
+{
+   u_int rows, j;
+
+   for (rows = 0; rows < p->fontheight; rows++) {
+     for (j = 0; j < p->fontwidth; j++) {
+       plot_pixel_mac (p, PIXEL_INVERT_MAC, (xx*p->fontwidth)+j, (yy*p->fontheight)+rows);
+     }
+   }
+}
+
+/*
+ * plot_pixel_mac
+ *
+ * bw == 0 = black
+ *       1 = white
+ *       2 = invert
+ */
+static void plot_pixel_mac(struct display *p, int bw, int pixel_x, int pixel_y)
+{
+  u8 *dest, bit;
+  u16 *dest16, pix16;
+  u32 *dest32, pix32;
+
+  if (pixel_x < 0 || pixel_y < 0 || pixel_x >= 832 || pixel_y >= 624) {
+    int cnt;
+    printk ("ERROR: pixel_x == %d, pixel_y == %d", pixel_x, pixel_y);
+    for(cnt = 0; cnt < 100000; cnt++)
+        udelay(100);
+    return;
+  }
+
+  switch (p->var.bits_per_pixel) {
+  case 1:
+    dest = (u8 *) ((pixel_x >> 3) + p->screen_base + pixel_y * p->next_line);
+    bit = 0x80 >> (pixel_x & 7);
+    switch (bw) {
+    case PIXEL_BLACK_MAC:
+      *dest |= bit;
+      break;
+    case PIXEL_WHITE_MAC:
+      *dest &= ~bit;
+      break;
+    case PIXEL_INVERT_MAC:
+      *dest ^= bit;
+      break;
+    default:
+      printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
+    }
+    break;
+
+  case 2:
+    dest = (u8 *) ((pixel_x >> 2) + p->screen_base + pixel_y * p->next_line);
+    bit = 0xC0 >> ((pixel_x & 3) << 1);
+    switch (bw) {
+    case PIXEL_BLACK_MAC:
+      *dest |= bit;
+      break;
+    case PIXEL_WHITE_MAC:
+      *dest &= ~bit;
+      break;
+    case PIXEL_INVERT_MAC:
+      *dest ^= bit;
+      break;
+    default:
+      printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
+    }
+    break;
+
+  case 4:
+    dest = (u8 *) ((pixel_x / 2) + p->screen_base + pixel_y * p->next_line);
+    bit = 0xF0 >> ((pixel_x & 1) << 2);
+    switch (bw) {
+    case PIXEL_BLACK_MAC:
+      *dest |= bit;
+      break;
+    case PIXEL_WHITE_MAC:
+      *dest &= ~bit;
+      break;
+    case PIXEL_INVERT_MAC:
+      *dest ^= bit;
+      break;
+    default:
+      printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
+    }
+    break;
+
+  case 8:
+    dest = (u8 *) (pixel_x + p->screen_base + pixel_y * p->next_line);
+    bit = 0xFF;
+    switch (bw) {
+    case PIXEL_BLACK_MAC:
+      *dest |= bit;
+      break;
+    case PIXEL_WHITE_MAC:
+      *dest &= ~bit;
+      break;
+    case PIXEL_INVERT_MAC:
+      *dest ^= bit;
+      break;
+    default:
+      printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
+    }
+    break;
+
+  case 16:
+    dest16 = (u16 *) ((pixel_x *2) + p->screen_base + pixel_y * p->next_line);
+    pix16 = 0xFFFF;
+    switch (bw) {
+    case PIXEL_BLACK_MAC:
+      *dest16 = ~pix16;
+      break;
+    case PIXEL_WHITE_MAC:
+      *dest16 = pix16;
+      break;
+    case PIXEL_INVERT_MAC:
+      *dest16 ^= pix16;
+      break;
+    default:
+      printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
+    }
+    break;
+
+  case 32:
+    dest32 = (u32 *) ((pixel_x *4) + p->screen_base + pixel_y * p->next_line);
+    pix32 = 0xFFFFFFFF;
+    switch (bw) {
+    case PIXEL_BLACK_MAC:
+      *dest32 = ~pix32;
+      break;
+    case PIXEL_WHITE_MAC:
+      *dest32 = pix32;
+      break;
+    case PIXEL_INVERT_MAC:
+      *dest32 ^= pix32;
+      break;
+    default:
+      printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
+    }
+    break;
+  }
+}
+
+static int get_pixel_mac(struct display *p, int pixel_x, int pixel_y)
+{
+  u8 *dest, bit;
+  u16 *dest16;
+  u32 *dest32;
+  u8 pixel;
+
+  switch (p->var.bits_per_pixel) {
+  case 1:
+    dest = (u8 *) ((pixel_x / 8) + p->screen_base + pixel_y * p->next_line);
+    bit = 0x80 >> (pixel_x & 7);
+    pixel = *dest & bit;
+    break;
+  case 2:
+    dest = (u8 *) ((pixel_x / 4) + p->screen_base + pixel_y * p->next_line);
+    bit = 0xC0 >> (pixel_x & 3);
+    pixel = *dest & bit;
+    break;
+  case 4:
+    dest = (u8 *) ((pixel_x / 2) + p->screen_base + pixel_y * p->next_line);
+    bit = 0xF0 >> (pixel_x & 1);
+    pixel = *dest & bit;
+    break;
+  case 8:
+    dest = (u8 *) (pixel_x + p->screen_base + pixel_y * p->next_line);
+    pixel = *dest;
+    break;
+  case 16:
+    dest16 = (u16 *) ((pixel_x *2) + p->screen_base + pixel_y * p->next_line);
+    pixel = *dest16 ? 1 : 0;
+    break;
+  case 32:
+    dest32 = (u32 *) ((pixel_x *4) + p->screen_base + pixel_y * p->next_line);
+    pixel = *dest32 ? 1 : 0;
+    break;
+  }
+
+  return pixel ? PIXEL_BLACK_MAC : PIXEL_WHITE_MAC;
+}
+
+
+    /*
+     *  `switch' for the low level operations
+     */
+
+struct display_switch fbcon_mac = {
+    fbcon_mac_setup, fbcon_mac_bmove, fbcon_mac_clear, fbcon_mac_putc,
+    fbcon_mac_putcs, fbcon_mac_revc
+};
+
+
+    /*
+     *  Visible symbols for modules
+     */
+
+EXPORT_SYMBOL(fbcon_mac);
+EXPORT_SYMBOL(fbcon_mac_setup);
+EXPORT_SYMBOL(fbcon_mac_bmove);
+EXPORT_SYMBOL(fbcon_mac_clear);
+EXPORT_SYMBOL(fbcon_mac_putc);
+EXPORT_SYMBOL(fbcon_mac_putcs);
+EXPORT_SYMBOL(fbcon_mac_revc);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov