fbcon-mac.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:11k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/drivers/video/fbcon-mac.c -- Low level frame buffer operations for 
  3.  *        x bpp packed pixels, font width != 8
  4.  *
  5.  * Created 26 Dec 1997 by Michael Schmitz
  6.  * Based on the old macfb.c 6x11 code by Randy Thelen
  7.  *
  8.  * This driver is significantly slower than the 8bit font drivers 
  9.  * and would probably benefit from splitting into drivers for each depth.
  10.  *
  11.  *  This file is subject to the terms and conditions of the GNU General Public
  12.  *  License.  See the file COPYING in the main directory of this archive for
  13.  */
  14. #include <linux/module.h>
  15. #include <linux/tty.h>
  16. #include <linux/console.h>
  17. #include <linux/string.h>
  18. #include <linux/fb.h>
  19. #include <linux/delay.h>
  20. #include <video/fbcon.h>
  21. #include <video/fbcon-mac.h>
  22.     /*
  23.      *  variable bpp packed pixels
  24.      */
  25. static void plot_pixel_mac(struct display *p, int bw, int pixel_x,
  26.    int pixel_y);
  27. static int get_pixel_mac(struct display *p, int pixel_x, int pixel_y);
  28. void fbcon_mac_setup(struct display *p)
  29. {
  30.     if (p->line_length)
  31. p->next_line = p->line_length;
  32.     else
  33.      p->next_line = p->var.xres_virtual>>3;
  34.     p->next_plane = 0;
  35. }
  36.    /*
  37.     *    Macintosh
  38.     */
  39. #define PIXEL_BLACK_MAC          0
  40. #define PIXEL_WHITE_MAC          1
  41. #define PIXEL_INVERT_MAC         2
  42. void fbcon_mac_bmove(struct display *p, int sy, int sx, int dy, int dx,
  43.      int height, int width)
  44. {
  45.    int i, j;
  46.    u8 *dest, *src;
  47.    int l,r,t,b,w,lo,s;
  48.    int dl,dr,dt,db,dw,dlo;
  49.    int move_up;
  50.    src = (u8 *) (p->screen_base + sy * fontheight(p) * p->next_line);
  51.    dest = (u8 *) (p->screen_base + dy * fontheight(p) * p->next_line);
  52.    if( sx == 0 && width == p->conp->vc_cols) {
  53.      s = height * fontheight(p) * p->next_line;
  54.      fb_memmove(dest, src, s);
  55.      return;
  56.    }
  57.    
  58.    l = sx * fontwidth(p);
  59.    r = l + width * fontwidth(p);
  60.    t = sy * fontheight(p);
  61.    b = t + height * fontheight(p);
  62.    dl = dx * fontwidth(p);
  63.    dr = dl + width * fontwidth(p);
  64.    dt = dy * fontheight(p);
  65.    db = dt + height * fontheight(p);
  66.    /* w is the # pixels between two long-aligned points, left and right */
  67.    w = (r&~31) - ((l+31)&~31);
  68.    dw = (dr&~31) - ((dl+31)&~31);
  69.    /* lo is the # pixels between the left edge and a long-aligned left pixel */
  70.    lo = ((l+31)&~31) - l;
  71.    dlo = ((dl+31)&~31) - dl;
  72.    
  73.    /* if dx != sx then, logic has to align the left and right edges for fast moves */
  74.    if (lo != dlo) {
  75.      lo = ((l+7)&~7) - l;
  76.      dlo = ((dl+7)&~7) - dl;
  77.      w = (r&~7) - ((l+7)&~7);
  78.      dw = (dr&~7) - ((dl+7)&~7);
  79.      if (lo != dlo) {
  80.        unsigned char err_str[128];
  81.        unsigned short err_buf[256];
  82.        unsigned long cnt, len;
  83.        sprintf( err_str, "ERROR: Shift algorithm: sx=%d,sy=%d,dx=%d,dy=%d,w=%d,h=%d,bpp=%d",
  84. sx,sy,dx,dy,width,height,p->var.bits_per_pixel);
  85.        len = strlen(err_str);
  86.        for (cnt = 0; cnt < len; cnt++)
  87.          err_buf[cnt] = 0x700 | err_str[cnt];
  88.        fbcon_mac_putcs(p->conp, p, err_buf, len, 0, 0);
  89.        /* pause for the user */
  90.        printk( "ERROR: shift algorithm...n" );
  91.        mdelay(5000);
  92.        return;
  93.      }
  94.    }
  95.    s = 0;
  96.    switch (p->var.bits_per_pixel) {
  97.    case 1:
  98.      s = w >> 3;
  99.      src += lo >> 3;
  100.      dest += lo >> 3;
  101.      break;
  102.    case 2:
  103.      s = w >> 2;
  104.      src += lo >> 2;
  105.      dest += lo >> 2;
  106.      break;
  107.    case 4:
  108.      s = w >> 1;
  109.      src += lo >> 1;
  110.      dest += lo >> 1;
  111.      break;
  112.    case 8:
  113.      s = w;
  114.      src += lo;
  115.      dest += lo;
  116.      break;
  117.    case 16:
  118.      s = w << 1;
  119.      src += lo << 1;
  120.      dest += lo << 1;
  121.      break;
  122.    case 32:
  123.      s = w << 2;
  124.      src += lo << 2;
  125.      dest += lo << 2;
  126.      break;
  127.    }
  128.    if (sy <= sx) {
  129.      i = b;
  130.      move_up = 0;
  131.      src += height * fontheight(p);
  132.      dest += height * fontheight(p);
  133.    } else {
  134.      i = t;
  135.      move_up = 1;
  136.    }
  137.    while (1) {
  138.      for (i = t; i < b; i++) {
  139.        j = l;
  140.        for (; j & 31 && j < r; j++)
  141.  plot_pixel_mac(p, get_pixel_mac(p, j+(dx-sx), i+(dy-sy)), j, i);
  142.        if (j < r) {
  143.  fb_memmove(dest, src, s);
  144.  if (move_up) {
  145.    dest += p->next_line;
  146.    src += p->next_line;
  147.  } else {
  148.    dest -= p->next_line;
  149.    src -= p->next_line;
  150.  }
  151.  j += w;
  152.        }
  153.      
  154.        for (; j < r; j++)
  155.  plot_pixel_mac(p, get_pixel_mac(p, j+(dx-sx), i+(dy-sy)), j, i);
  156.      }
  157.      if (move_up) {
  158.        i++;
  159.        if (i >= b)
  160.  break;
  161.      } else {
  162.        i--;
  163.        if (i < t)
  164.  break;
  165.      }
  166.    }
  167. }
  168. void fbcon_mac_clear(struct vc_data *conp, struct display *p, int sy, int sx,
  169.      int height, int width)
  170. {
  171.    int pixel;
  172.    int i, j;
  173.    int inverse;
  174.    u8 *dest;
  175.    int l,r,t,b,w,lo,s;
  176.    inverse = conp ? attr_reverse(p,conp->vc_attr) : 0;
  177.    pixel = inverse ? PIXEL_WHITE_MAC : PIXEL_BLACK_MAC;
  178.    dest = (u8 *) (p->screen_base + sy * fontheight(p) * p->next_line);
  179.    if( sx == 0 && width == p->conp->vc_cols) {
  180.      s = height * fontheight(p) * p->next_line;
  181.      if (inverse)
  182.        fb_memclear(dest, s);
  183.      else
  184.        fb_memset255(dest, s);
  185.    }
  186.    
  187.    l = sx * fontwidth(p);
  188.    r = l + width * fontwidth(p);
  189.    t = sy * fontheight(p);
  190.    b = t + height * fontheight(p);
  191.    /* w is the # pixels between two long-aligned points, left and right */
  192.    w = (r&~31) - ((l+31)&~31);
  193.    /* lo is the # pixels between the left edge and a long-aligned left pixel */
  194.    lo = ((l+31)&~31) - l;
  195.    s = 0;
  196.    switch (p->var.bits_per_pixel) {
  197.    case 1:
  198.      s = w >> 3;
  199.      dest += lo >> 3;
  200.      break;
  201.    case 2:
  202.      s = w >> 2;
  203.      dest += lo >> 2;
  204.      break;
  205.    case 4:
  206.      s = w >> 1;
  207.      dest += lo >> 1;
  208.      break;
  209.    case 8:
  210.      s = w;
  211.      dest += lo;
  212.      break;
  213.    case 16:
  214.      s = w << 1;
  215.      dest += lo << 1;
  216.      break;
  217.    case 32:
  218.      s = w << 2;
  219.      dest += lo << 2;
  220.      break;
  221.    }
  222.    for (i = t; i < b; i++) {
  223.      j = l;
  224.      for (; j & 31 && j < r; j++)
  225.        plot_pixel_mac(p, pixel, j, i);
  226.      if (j < r) {
  227.        if (PIXEL_WHITE_MAC == pixel)
  228.  fb_memclear(dest, s);
  229.        else
  230.  fb_memset255(dest, s);
  231.        dest += p->next_line;
  232.        j += w;
  233.      }
  234.      
  235.      for (; j < r; j++)
  236.        plot_pixel_mac(p, pixel, j, i);
  237.    }
  238. }
  239. void fbcon_mac_putc(struct vc_data *conp, struct display *p, int c, int yy,
  240.     int xx)
  241. {
  242.    u8 *cdat;
  243.    u_int rows, bold, ch_reverse, ch_underline;
  244.    u8 d;
  245.    int j;
  246.    cdat = p->fontdata+(c&p->charmask)*fontheight(p);
  247.    bold = attr_bold(p,c);
  248.    ch_reverse = attr_reverse(p,c);
  249.    ch_underline = attr_underline(p,c);
  250.    for (rows = 0; rows < fontheight(p); rows++) {
  251.       d = *cdat++;
  252.       if (!conp->vc_can_do_color) {
  253. if (ch_underline && rows == (fontheight(p)-2))
  254.   d = 0xff;
  255. else if (bold)
  256.   d |= d>>1;
  257. if (ch_reverse)
  258.   d = ~d;
  259.       }
  260.       for (j = 0; j < fontwidth(p); j++) {
  261. plot_pixel_mac(p, (d & 0x80) >> 7, (xx*fontwidth(p)) + j, (yy*fontheight(p)) + rows);
  262. d <<= 1;
  263.       }
  264.    }
  265. }
  266. void fbcon_mac_putcs(struct vc_data *conp, struct display *p, 
  267.      const unsigned short *s, int count, int yy, int xx)
  268. {
  269.    u16 c;
  270.    while (count--) {
  271.       c = scr_readw(s++);
  272.       fbcon_mac_putc(conp, p, c, yy, xx++);
  273.    }
  274. }
  275. void fbcon_mac_revc(struct display *p, int xx, int yy)
  276. {
  277.    u_int rows, j;
  278.    for (rows = 0; rows < fontheight(p); rows++) {
  279.      for (j = 0; j < fontwidth(p); j++) {
  280.        plot_pixel_mac (p, PIXEL_INVERT_MAC, (xx*fontwidth(p))+j, (yy*fontheight(p))+rows);
  281.      }
  282.    }
  283. }
  284. static inline void plot_helper(u8 *dest, u8 bit, int bw)
  285. {
  286.     switch (bw) {
  287.     case PIXEL_BLACK_MAC:
  288.       fb_writeb( fb_readb(dest) | bit, dest );
  289.       break;
  290.     case PIXEL_WHITE_MAC:
  291.       fb_writeb( fb_readb(dest) & (~bit), dest );
  292.       break;
  293.     case PIXEL_INVERT_MAC:
  294.       fb_writeb( fb_readb(dest) ^ bit, dest );
  295.       break;
  296.     default:
  297.       printk( "ERROR: Unknown pixel value in plot_pixel_macn");
  298.     }
  299. }
  300. /*
  301.  * plot_pixel_mac
  302.  */
  303. static void plot_pixel_mac(struct display *p, int bw, int pixel_x, int pixel_y)
  304. {
  305.   u8 *dest, bit;
  306.   u16 *dest16, pix16;
  307.   u32 *dest32, pix32;
  308.   /* There *are* 68k Macs that support more than 832x624, you know :-) */
  309.   if (pixel_x < 0 || pixel_y < 0 || pixel_x >= p->var.xres || pixel_y >= p->var.yres) {
  310.     printk ("ERROR: pixel_x == %d, pixel_y == %d", pixel_x, pixel_y);
  311.     mdelay(1000);
  312.     return;
  313.   }
  314.   switch (p->var.bits_per_pixel) {
  315.   case 1:
  316.     dest = (u8 *) ((pixel_x >> 3) + p->screen_base + pixel_y * p->next_line);
  317.     bit = 0x80 >> (pixel_x & 7);
  318.     plot_helper(dest, bit, bw);
  319.     break;
  320.   case 2:
  321.     dest = (u8 *) ((pixel_x >> 2) + p->screen_base + pixel_y * p->next_line);
  322.     bit = 0xC0 >> ((pixel_x & 3) << 1);
  323.     plot_helper(dest, bit, bw);
  324.     break;
  325.   case 4:
  326.     dest = (u8 *) ((pixel_x >> 1) + p->screen_base + pixel_y * p->next_line);
  327.     bit = 0xF0 >> ((pixel_x & 1) << 2);
  328.     plot_helper(dest, bit, bw);
  329.     break;
  330.   case 8:
  331.     dest = (u8 *) (pixel_x + p->screen_base + pixel_y * p->next_line);
  332.     bit = 0xFF;
  333.     plot_helper(dest, bit, bw);
  334.     break;
  335. /* FIXME: You can't access framebuffer directly like this! */
  336.   case 16:
  337.     dest16 = (u16 *) ((pixel_x *2) + p->screen_base + pixel_y * p->next_line);
  338.     pix16 = 0xFFFF;
  339.     switch (bw) {
  340.     case PIXEL_BLACK_MAC:  *dest16 = ~pix16; break;
  341.     case PIXEL_WHITE_MAC:  *dest16 = pix16;  break;
  342.     case PIXEL_INVERT_MAC: *dest16 ^= pix16; break;
  343.     default: printk( "ERROR: Unknown pixel value in plot_pixel_macn");
  344.     }
  345.     break;
  346.   case 32:
  347.     dest32 = (u32 *) ((pixel_x *4) + p->screen_base + pixel_y * p->next_line);
  348.     pix32 = 0xFFFFFFFF;
  349.     switch (bw) {
  350.     case PIXEL_BLACK_MAC:  *dest32 = ~pix32; break;
  351.     case PIXEL_WHITE_MAC:  *dest32 = pix32;  break;
  352.     case PIXEL_INVERT_MAC: *dest32 ^= pix32; break;
  353.     default: printk( "ERROR: Unknown pixel value in plot_pixel_macn");
  354.     }
  355.     break;
  356.   }
  357. }
  358. static int get_pixel_mac(struct display *p, int pixel_x, int pixel_y)
  359. {
  360.   u8 *dest, bit;
  361.   u16 *dest16;
  362.   u32 *dest32;
  363.   u8 pixel=0;
  364.   switch (p->var.bits_per_pixel) {
  365.   case 1:
  366.     dest = (u8 *) ((pixel_x / 8) + p->screen_base + pixel_y * p->next_line);
  367.     bit = 0x80 >> (pixel_x & 7);
  368.     pixel = *dest & bit;
  369.     break;
  370.   case 2:
  371.     dest = (u8 *) ((pixel_x / 4) + p->screen_base + pixel_y * p->next_line);
  372.     bit = 0xC0 >> (pixel_x & 3);
  373.     pixel = *dest & bit;
  374.     break;
  375.   case 4:
  376.     dest = (u8 *) ((pixel_x / 2) + p->screen_base + pixel_y * p->next_line);
  377.     bit = 0xF0 >> (pixel_x & 1);
  378.     pixel = *dest & bit;
  379.     break;
  380.   case 8:
  381.     dest = (u8 *) (pixel_x + p->screen_base + pixel_y * p->next_line);
  382.     pixel = *dest;
  383.     break;
  384.   case 16:
  385.     dest16 = (u16 *) ((pixel_x *2) + p->screen_base + pixel_y * p->next_line);
  386.     pixel = *dest16 ? 1 : 0;
  387.     break;
  388.   case 32:
  389.     dest32 = (u32 *) ((pixel_x *4) + p->screen_base + pixel_y * p->next_line);
  390.     pixel = *dest32 ? 1 : 0;
  391.     break;
  392.   }
  393.   return pixel ? PIXEL_BLACK_MAC : PIXEL_WHITE_MAC;
  394. }
  395.     /*
  396.      *  `switch' for the low level operations
  397.      */
  398. struct display_switch fbcon_mac = {
  399.     setup: fbcon_mac_setup,
  400.     bmove: fbcon_redraw_bmove,
  401.     clear: fbcon_redraw_clear,
  402.     putc: fbcon_mac_putc,
  403.     putcs: fbcon_mac_putcs,
  404.     revc: fbcon_mac_revc,
  405.     fontwidthmask: FONTWIDTHRANGE(1,8)
  406. };
  407. #ifdef MODULE
  408. MODULE_LICENSE("GPL");
  409. int init_module(void)
  410. {
  411.     return 0;
  412. }
  413. void cleanup_module(void)
  414. {}
  415. #endif /* MODULE */
  416.     /*
  417.      *  Visible symbols for modules
  418.      */
  419. EXPORT_SYMBOL(fbcon_mac);
  420. EXPORT_SYMBOL(fbcon_mac_setup);
  421. EXPORT_SYMBOL(fbcon_mac_bmove);
  422. EXPORT_SYMBOL(fbcon_mac_clear);
  423. EXPORT_SYMBOL(fbcon_mac_putc);
  424. EXPORT_SYMBOL(fbcon_mac_putcs);
  425. EXPORT_SYMBOL(fbcon_mac_revc);