igafb.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:22k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/drivers/video/igafb.c -- Frame buffer device for IGA 1682
  3.  *
  4.  *      Copyright (C) 1998  Vladimir Roganov and Gleb Raiko
  5.  *
  6.  *  This driver is partly based on the Frame buffer device for ATI Mach64
  7.  *  and partially on VESA-related code.
  8.  *
  9.  *      Copyright (C) 1997-1998  Geert Uytterhoeven
  10.  *      Copyright (C) 1998  Bernd Harries
  11.  *      Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
  12.  *
  13.  *  This file is subject to the terms and conditions of the GNU General Public
  14.  *  License. See the file COPYING in the main directory of this archive for
  15.  *  more details.
  16.  */
  17. /******************************************************************************
  18.   TODO:
  19.        Despite of IGA Card has advanced graphic acceleration, 
  20.        initial version is almost dummy and does not support it.
  21.        Support for video modes and acceleration must be added
  22.        together with accelerated X-Windows driver implementation.
  23.        Most important thing at this moment is that we have working
  24.        JavaEngine1  console & X  with new console interface.
  25. ******************************************************************************/
  26. #include <linux/module.h>
  27. #include <linux/kernel.h>
  28. #include <linux/errno.h>
  29. #include <linux/string.h>
  30. #include <linux/mm.h>
  31. #include <linux/tty.h>
  32. #include <linux/slab.h>
  33. #include <linux/vmalloc.h>
  34. #include <linux/delay.h>
  35. #include <linux/interrupt.h>
  36. #include <linux/fb.h>
  37. #include <linux/selection.h>
  38. #include <linux/console.h>
  39. #include <linux/init.h>
  40. #include <linux/pci.h>
  41. #include <linux/nvram.h>
  42. #include <linux/kd.h>
  43. #include <linux/vt_kern.h>
  44. #include <asm/io.h>
  45. #ifdef __sparc__
  46. #include <asm/pbm.h>
  47. #include <asm/pcic.h>
  48. #endif
  49. #include <video/fbcon.h>
  50. #include <video/fbcon-cfb8.h>
  51. #include <video/fbcon-cfb16.h>
  52. #include <video/fbcon-cfb24.h>
  53. #include <video/fbcon-cfb32.h>
  54. #include "iga.h"
  55. static char igafb_name[16] = "IGA 1682";
  56. static char fontname[40] __initdata = { 0 };
  57. struct pci_mmap_map {
  58.     unsigned long voff;
  59.     unsigned long poff;
  60.     unsigned long size;
  61.     unsigned long prot_flag;
  62.     unsigned long prot_mask;
  63. };
  64. struct fb_info_iga {
  65.     struct fb_info fb_info;
  66.     unsigned long frame_buffer_phys;
  67.     char *frame_buffer;
  68.     unsigned long io_base_phys;
  69.     unsigned long io_base;
  70.     u32 total_vram;
  71.     struct pci_mmap_map *mmap_map;
  72.     struct { u_short blue, green, red, pad; } palette[256];
  73.     int video_cmap_len;
  74.     int currcon;
  75.     struct display disp;
  76.     struct display_switch dispsw; 
  77.     union {
  78. #ifdef FBCON_HAS_CFB16
  79.     u16 cfb16[16];  
  80. #endif
  81. #ifdef FBCON_HAS_CFB24
  82.     u32 cfb24[16];
  83. #endif
  84. #ifdef FBCON_HAS_CFB32
  85.     u32 cfb32[16];
  86. #endif
  87.     } fbcon_cmap;
  88. #ifdef __sparc__
  89.     u8 open;
  90.     u8 mmaped;
  91.     int vtconsole;
  92.     int consolecnt;
  93. #endif
  94. };
  95. struct fb_var_screeninfo default_var = {
  96.     /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
  97.     640, 480, 640, 480, 0, 0, 8, 0,
  98.     {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  99.     0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
  100.     0, FB_VMODE_NONINTERLACED
  101. };
  102. #ifdef __sparc__
  103. struct fb_var_screeninfo default_var_1024x768 __initdata = {
  104.     /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
  105.     1024, 768, 1024, 768, 0, 0, 8, 0,
  106.     {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  107.     0, 0, -1, -1, 0, 12699, 176, 16, 28, 1, 96, 3,
  108.     FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
  109. };
  110. struct fb_var_screeninfo default_var_1152x900 __initdata = {
  111.     /* 1152x900, 76 Hz, Non-Interlaced (110.0 MHz dotclock) */
  112.     1152, 900, 1152, 900, 0, 0, 8, 0,
  113.     {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  114.     0, 0, -1, -1, 0, 9091, 234, 24, 34, 3, 100, 3,
  115.     FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
  116. };
  117. struct fb_var_screeninfo default_var_1280x1024 __initdata = {
  118.     /* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */
  119.     1280, 1024, 1280, 1024, 0, 0, 8, 0,
  120.     {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
  121.     0, 0, -1, -1, 0, 7408, 248, 16, 38, 1, 144, 3,
  122.     FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
  123. };
  124. /*
  125.  *   Memory-mapped I/O functions for Sparc PCI
  126.  *
  127.  * On sparc we happen to access I/O with memory mapped functions too.
  128.  */ 
  129. #define pci_inb(info, reg)        readb(info->io_base+(reg))
  130. #define pci_outb(info, val, reg)  writeb(val, info->io_base+(reg))
  131. static inline unsigned int iga_inb(struct fb_info_iga *info,
  132.    unsigned int reg, unsigned int idx )
  133. {
  134.         pci_outb(info, idx, reg);
  135.         return pci_inb(info, reg + 1);
  136. }
  137. static inline void iga_outb(struct fb_info_iga *info, unsigned char val,
  138.     unsigned int reg, unsigned int idx )
  139. {
  140.         pci_outb(info, idx, reg);
  141.         pci_outb(info, val, reg+1);
  142. }
  143. #endif /* __sparc__ */
  144. /*
  145.  *  Very important functionality for the JavaEngine1 computer:
  146.  *  make screen border black (usign special IGA registers) 
  147.  */
  148. static void iga_blank_border(struct fb_info_iga *info)
  149. {
  150.         int i;
  151. #if 0
  152. /*
  153.  * PROM does this for us, so keep this code as a reminder
  154.  * about required read from 0x3DA and writing of 0x20 in the end.
  155.  */
  156. (void) pci_inb(info, 0x3DA); /* required for every access */
  157. pci_outb(info, IGA_IDX_VGA_OVERSCAN, IGA_ATTR_CTL);
  158. (void) pci_inb(info, IGA_ATTR_CTL+1);
  159. pci_outb(info, 0x38, IGA_ATTR_CTL);
  160. pci_outb(info, 0x20, IGA_ATTR_CTL); /* re-enable visual */
  161. #endif
  162. /*
  163.  * This does not work as it was designed because the overscan
  164.  * color is looked up in the palette. Therefore, under X11
  165.  * overscan changes color.
  166.  */
  167. for (i=0; i < 3; i++)
  168. iga_outb(info, 0, IGA_EXT_CNTRL, IGA_IDX_OVERSCAN_COLOR + i);
  169. }
  170. /*
  171.  *  Frame buffer device API
  172.  */
  173. static int igafb_update_var(int con, struct fb_info *info)
  174. {
  175.         return 0;
  176. }
  177. static int igafb_get_fix(struct fb_fix_screeninfo *fix, int con,
  178.                          struct fb_info *info)
  179. {
  180.         struct fb_info_iga *fb = (struct fb_info_iga*)info;
  181.         memset(fix, 0, sizeof(struct fb_fix_screeninfo));
  182.         strcpy(fix->id, igafb_name);
  183.         fix->smem_start = (unsigned long) fb->frame_buffer;
  184.         fix->smem_len = fb->total_vram;
  185.         fix->xpanstep = 0;
  186.         fix->ypanstep = 0;
  187.         fix->ywrapstep = 0;
  188. fix->type = FB_TYPE_PACKED_PIXELS;
  189. fix->type_aux = 0;
  190. fix->line_length = default_var.xres * (default_var.bits_per_pixel/8);
  191. fix->visual = default_var.bits_per_pixel <= 8 ? FB_VISUAL_PSEUDOCOLOR
  192.                                       : FB_VISUAL_DIRECTCOLOR;
  193.         return 0;
  194. }
  195. static int igafb_get_var(struct fb_var_screeninfo *var, int con,
  196.                          struct fb_info *info)
  197. {
  198.         if(con == -1)
  199.                 memcpy(var, &default_var, sizeof(struct fb_var_screeninfo));
  200.         else
  201.                 *var = fb_display[con].var;
  202.         return 0;
  203. }
  204. static int igafb_set_var(struct fb_var_screeninfo *var, int con,
  205.                          struct fb_info *info)
  206. {
  207.         memcpy(var, &default_var, sizeof(struct fb_var_screeninfo));
  208.         return 0;
  209. }
  210. #ifdef __sparc__
  211. static int igafb_mmap(struct fb_info *info, struct file *file,
  212.       struct vm_area_struct *vma)
  213. {
  214. struct fb_info_iga *fb = (struct fb_info_iga *)info;
  215. unsigned int size, page, map_size = 0;
  216. unsigned long map_offset = 0;
  217. int i;
  218. if (!fb->mmap_map)
  219. return -ENXIO;
  220. size = vma->vm_end - vma->vm_start;
  221. /* To stop the swapper from even considering these pages. */
  222. vma->vm_flags |= (VM_SHM | VM_LOCKED);
  223. /* Each page, see which map applies */
  224. for (page = 0; page < size; ) {
  225. map_size = 0;
  226. for (i = 0; fb->mmap_map[i].size; i++) {
  227. unsigned long start = fb->mmap_map[i].voff;
  228. unsigned long end = start + fb->mmap_map[i].size;
  229. unsigned long offset = (vma->vm_pgoff << PAGE_SHIFT) + page;
  230. if (start > offset)
  231. continue;
  232. if (offset >= end)
  233. continue;
  234. map_size = fb->mmap_map[i].size - (offset - start);
  235. map_offset = fb->mmap_map[i].poff + (offset - start);
  236. break;
  237. }
  238. if (!map_size) {
  239. page += PAGE_SIZE;
  240. continue;
  241. }
  242. if (page + map_size > size)
  243. map_size = size - page;
  244. pgprot_val(vma->vm_page_prot) &= ~(fb->mmap_map[i].prot_mask);
  245. pgprot_val(vma->vm_page_prot) |= fb->mmap_map[i].prot_flag;
  246. if (remap_page_range(vma->vm_start + page, map_offset,
  247.      map_size, vma->vm_page_prot))
  248. return -EAGAIN;
  249. page += map_size;
  250. }
  251. if (!map_size)
  252. return -EINVAL;
  253. if (!fb->mmaped) {
  254. int lastconsole = 0;
  255. if (info->display_fg)
  256. lastconsole = info->display_fg->vc_num;
  257. fb->mmaped = 1;
  258. if (fb->consolecnt && fb_display[lastconsole].fb_info ==info) {
  259. fb->vtconsole = lastconsole;
  260. vt_cons[lastconsole]->vc_mode = KD_GRAPHICS;
  261. }
  262. }
  263. return 0;
  264. }
  265. #endif /* __sparc__ */
  266. static int iga_getcolreg(unsigned regno, unsigned *red, unsigned *green,
  267.                           unsigned *blue, unsigned *transp,
  268.                           struct fb_info *fb_info)
  269. {
  270.         /*
  271.          *  Read a single color register and split it into colors/transparent.
  272.          *  Return != 0 for invalid regno.
  273.          */
  274. struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
  275.         if (regno >= info->video_cmap_len)
  276.                 return 1;
  277. *red    = info->palette[regno].red;
  278. *green  = info->palette[regno].green;
  279. *blue   = info->palette[regno].blue;
  280. *transp = 0;
  281. return 0;
  282. }
  283. static int iga_setcolreg(unsigned regno, unsigned red, unsigned green,
  284.                           unsigned blue, unsigned transp,
  285.                           struct fb_info *fb_info)
  286. {
  287.         /*
  288.          *  Set a single color register. The values supplied are
  289.          *  already rounded down to the hardware's capabilities
  290.          *  (according to the entries in the `var' structure). Return
  291.          *  != 0 for invalid regno.
  292.          */
  293.         
  294. struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
  295.         if (regno >= info->video_cmap_len)
  296.                 return 1;
  297.         info->palette[regno].red   = red;
  298.         info->palette[regno].green = green;
  299.         info->palette[regno].blue  = blue;
  300. pci_outb(info, regno, DAC_W_INDEX);
  301. pci_outb(info, red,   DAC_DATA);
  302. pci_outb(info, green, DAC_DATA);
  303. pci_outb(info, blue,  DAC_DATA);
  304. if (regno < 16) {
  305. switch (default_var.bits_per_pixel) {
  306. #ifdef FBCON_HAS_CFB16
  307. case 16:
  308. info->fbcon_cmap.cfb16[regno] = 
  309. (regno << 10) | (regno << 5) | regno;
  310. break;
  311. #endif
  312. #ifdef FBCON_HAS_CFB24
  313. case 24:
  314. info->fbcon_cmap.cfb24[regno] = 
  315. (regno << 16) | (regno << 8) | regno;
  316. break;
  317. #endif
  318. #ifdef FBCON_HAS_CFB32
  319. case 32:
  320. { int i;
  321. i = (regno << 8) | regno;
  322. info->fbcon_cmap.cfb32[regno] = (i << 16) | i;
  323. }
  324. break;
  325. #endif
  326. }
  327. }
  328. return 0;
  329. }
  330. static void do_install_cmap(int con, struct fb_info *fb_info)
  331. {
  332. struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
  333.         if (con != info->currcon)
  334.                 return;
  335.         if (fb_display[con].cmap.len)
  336.                 fb_set_cmap(&fb_display[con].cmap, 1,
  337.                             iga_setcolreg, &info->fb_info);
  338.         else
  339.                 fb_set_cmap(fb_default_cmap(info->video_cmap_len), 1, 
  340.     iga_setcolreg, &info->fb_info);
  341. }
  342. static int igafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
  343.                            struct fb_info *fb_info)
  344. {
  345. struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
  346.         if (con == info->currcon) /* current console? */
  347.                 return fb_get_cmap(cmap, kspc, iga_getcolreg, &info->fb_info);
  348.         else if (fb_display[con].cmap.len) /* non default colormap? */
  349.                 fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
  350.         else
  351.                 fb_copy_cmap(fb_default_cmap(info->video_cmap_len),
  352.                      cmap, kspc ? 0 : 2);
  353.         return 0;
  354. }
  355. static int igafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
  356.                   struct fb_info *info)
  357. {
  358.         int err;
  359. struct fb_info_iga *fb = (struct fb_info_iga*) info;
  360.         if (!fb_display[con].cmap.len) {        /* no colormap allocated? */
  361.                 err = fb_alloc_cmap(&fb_display[con].cmap,
  362.     fb->video_cmap_len,0);
  363.                 if (err)
  364.                         return err;
  365.         }
  366.         if (con == fb->currcon)                     /* current console? */
  367.                 return fb_set_cmap(cmap, kspc, iga_setcolreg, info);
  368.         else
  369.                 fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
  370.         return 0;
  371. }
  372. /*
  373.  * Framebuffer option structure
  374.  */
  375. static struct fb_ops igafb_ops = {
  376. owner: THIS_MODULE,
  377. fb_get_fix: igafb_get_fix,
  378. fb_get_var: igafb_get_var,
  379. fb_set_var: igafb_set_var,
  380. fb_get_cmap: igafb_get_cmap,
  381. fb_set_cmap: igafb_set_cmap,
  382. #ifdef __sparc__
  383. fb_mmap: igafb_mmap,
  384. #endif
  385. };
  386. static void igafb_set_disp(int con, struct fb_info_iga *info)
  387. {
  388.         struct fb_fix_screeninfo fix;
  389.         struct display *display;
  390.         struct display_switch *sw;
  391.         if (con >= 0)
  392.                 display = &fb_display[con];
  393.         else 
  394.                 display = &info->disp;        /* used during initialization */
  395.         igafb_get_fix(&fix, con, &info->fb_info);
  396.         memset(display, 0, sizeof(struct display));
  397.         display->screen_base = info->frame_buffer;
  398.         display->visual = fix.visual;
  399.         display->type = fix.type;
  400.         display->type_aux = fix.type_aux;
  401.         display->ypanstep = fix.ypanstep;
  402.         display->ywrapstep = fix.ywrapstep;
  403.         display->line_length = fix.line_length;
  404.         display->next_line = fix.line_length;
  405.         display->can_soft_blank = 0; 
  406.         display->inverse = 0;
  407.         igafb_get_var(&display->var, -1, &info->fb_info);
  408.         switch (default_var.bits_per_pixel) {
  409. #ifdef FBCON_HAS_CFB8
  410.         case 8:
  411.                 sw = &fbcon_cfb8;
  412.                 break;
  413. #endif
  414. #ifdef FBCON_HAS_CFB16
  415.         case 15:
  416.         case 16:
  417.                 sw = &fbcon_cfb16;
  418. display->dispsw_data = info->fbcon_cmap.cfb16;
  419.                 break;
  420. #endif
  421. #ifdef FBCON_HAS_CFB24
  422. case 24:
  423. sw = &fbcon_cfb24;
  424. display->dispsw_data = info->fbcon_cmap.cfb24;
  425. break;
  426. #endif
  427. #ifdef FBCON_HAS_CFB32
  428.         case 32:
  429.                 sw = &fbcon_cfb32;
  430. display->dispsw_data = info->fbcon_cmap.cfb32;
  431.                 break;
  432. #endif
  433.         default:
  434. printk(KERN_WARNING "igafb_set_disp: unknown resolution %dn",
  435.     default_var.bits_per_pixel);
  436.                 return;
  437.         }
  438.         memcpy(&info->dispsw, sw, sizeof(*sw));
  439.         display->dispsw = &info->dispsw;
  440. display->scrollmode = SCROLL_YREDRAW;
  441. info->dispsw.bmove = fbcon_redraw_bmove;
  442. }
  443. static int igafb_switch(int con, struct fb_info *fb_info)
  444. {
  445. struct fb_info_iga *info = (struct fb_info_iga*) fb_info;
  446.         /* Do we have to save the colormap? */
  447.         if (fb_display[info->currcon].cmap.len)
  448.                 fb_get_cmap(&fb_display[info->currcon].cmap, 1,
  449.                             iga_getcolreg, fb_info);
  450. info->currcon = con;
  451. /* Install new colormap */
  452. do_install_cmap(con, fb_info);
  453. igafb_update_var(con, fb_info);
  454.         return 1;
  455. }
  456. /* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
  457. static void igafb_blank(int blank, struct fb_info *info)
  458. {
  459.         /* Not supported */
  460. }
  461. static int __init iga_init(struct fb_info_iga *info)
  462. {
  463.         char vramsz = iga_inb(info, IGA_EXT_CNTRL, IGA_IDX_EXT_BUS_CNTL) 
  464.                                          & MEM_SIZE_ALIAS;
  465.         switch (vramsz) {
  466.         case MEM_SIZE_1M:
  467.                 info->total_vram = 0x100000;
  468.                 break;
  469.         case MEM_SIZE_2M:
  470.                 info->total_vram = 0x200000;
  471.                 break;
  472.         case MEM_SIZE_4M:
  473.         case MEM_SIZE_RESERVED:
  474.                 info->total_vram = 0x400000;
  475.                 break;
  476.         }
  477.         if (default_var.bits_per_pixel > 8) {
  478.                 info->video_cmap_len = 16;
  479.         } else {
  480.                 info->video_cmap_len = 256;
  481.         }
  482. {
  483. int j, k;
  484. for (j = 0; j < 16; j++) {
  485. k = color_table[j];
  486. info->palette[j].red = default_red[k];
  487. info->palette[j].green = default_grn[k];
  488. info->palette[j].blue = default_blu[k];
  489. }
  490. }
  491. strcpy(info->fb_info.modename, igafb_name);
  492. info->fb_info.node = -1;
  493. info->fb_info.fbops = &igafb_ops;
  494. info->fb_info.disp = &info->disp;
  495. strcpy(info->fb_info.fontname, fontname);
  496. info->fb_info.changevar = NULL;
  497. info->fb_info.switch_con = &igafb_switch;
  498. info->fb_info.updatevar = &igafb_update_var;
  499. info->fb_info.blank = &igafb_blank;
  500. info->fb_info.flags=FBINFO_FLAG_DEFAULT;
  501. igafb_set_disp(-1, info);
  502. if (register_framebuffer(&info->fb_info) < 0)
  503. return 0;
  504. printk("fb%d: %s frame buffer device at 0x%08lx [%dMB VRAM]n",
  505.        GET_FB_IDX(info->fb_info.node), igafb_name, 
  506.        info->frame_buffer_phys, info->total_vram >> 20);
  507. iga_blank_border(info); 
  508. return 1;
  509. }
  510. int __init igafb_init(void)
  511. {
  512.         struct pci_dev *pdev;
  513.         struct fb_info_iga *info;
  514.         unsigned long addr;
  515.         extern int con_is_present(void);
  516. int iga2000 = 0;
  517.         /* Do not attach when we have a serial console. */
  518.         if (!con_is_present())
  519.                 return -ENXIO;
  520.         pdev = pci_find_device(PCI_VENDOR_ID_INTERG, 
  521.                                PCI_DEVICE_ID_INTERG_1682, 0);
  522. if (pdev == NULL) {
  523. /*
  524.  * XXX We tried to use cyber2000fb.c for IGS 2000.
  525.  * But it does not initialize the chip in JavaStation-E, alas.
  526.  */
  527.          pdev = pci_find_device(PCI_VENDOR_ID_INTERG, 0x2000, 0);
  528.          if(pdev == NULL) {
  529.                  return -ENXIO;
  530. }
  531. iga2000 = 1;
  532. }
  533.         info = kmalloc(sizeof(struct fb_info_iga), GFP_ATOMIC);
  534.         if (!info) {
  535.                 printk("igafb_init: can't alloc fb_info_igan");
  536.                 return -ENOMEM;
  537.         }
  538.         memset(info, 0, sizeof(struct fb_info_iga));
  539. if ((addr = pdev->resource[0].start) == 0) {
  540.                 printk("igafb_init: no memory startn");
  541. kfree(info);
  542. return -ENXIO;
  543. }
  544. if ((info->frame_buffer = ioremap(addr, 1024*1024*2)) == 0) {
  545.                 printk("igafb_init: can't remap %lx[2M]n", addr);
  546. kfree(info);
  547. return -ENXIO;
  548. }
  549. info->frame_buffer_phys = addr & PCI_BASE_ADDRESS_MEM_MASK;
  550. #ifdef __sparc__
  551. /*
  552.  * The following is sparc specific and this is why:
  553.  *
  554.  * IGS2000 has its I/O memory mapped and we want
  555.  * to generate memory cycles on PCI, e.g. do ioremap(),
  556.  * then readb/writeb() as in Documentation/IO-mapping.txt.
  557.  *
  558.  * IGS1682 is more traditional, it responds to PCI I/O
  559.  * cycles, so we want to access it with inb()/outb().
  560.  *
  561.  * On sparc, PCIC converts CPU memory access within
  562.  * phys window 0x3000xxxx into PCI I/O cycles. Therefore
  563.  * we may use readb/writeb to access them with IGS1682.
  564.  *
  565.  * We do not take io_base_phys from resource[n].start
  566.  * on IGS1682 because that chip is BROKEN. It does not
  567.  * have a base register for I/O. We just "know" what its
  568.  * I/O addresses are.
  569.  */
  570. if (iga2000) {
  571. info->io_base_phys = info->frame_buffer_phys | 0x00800000;
  572. } else {
  573. info->io_base_phys = 0x30000000; /* XXX */
  574. }
  575. if ((info->io_base = (int) ioremap(info->io_base_phys, 0x1000)) == 0) {
  576.                 printk("igafb_init: can't remap %lx[4K]n", info->io_base_phys);
  577. iounmap((void *)info->frame_buffer);
  578.                 kfree(info);
  579. return -ENXIO;
  580. }
  581. /*
  582.  * Figure mmap addresses from PCI config space.
  583.  * We need two regions: for video memory and for I/O ports.
  584.  * Later one can add region for video coprocessor registers.
  585.  * However, mmap routine loops until size != 0, so we put
  586.  * one additional region with size == 0. 
  587.  */
  588. info->mmap_map = kmalloc(4 * sizeof(*info->mmap_map), GFP_ATOMIC);
  589. if (!info->mmap_map) {
  590. printk("igafb_init: can't alloc mmap_mapn");
  591. iounmap((void *)info->io_base);
  592. iounmap(info->frame_buffer);
  593.                 kfree(info);
  594. return -ENOMEM;
  595. }
  596. memset(info->mmap_map, 0, 4 * sizeof(*info->mmap_map));
  597. /*
  598.  * Set default vmode and cmode from PROM properties.
  599.  */
  600. {
  601.                 struct pcidev_cookie *cookie = pdev->sysdata;
  602.                 int node = cookie->prom_node;
  603.                 int width = prom_getintdefault(node, "width", 1024);
  604.                 int height = prom_getintdefault(node, "height", 768);
  605.                 int depth = prom_getintdefault(node, "depth", 8);
  606.                 switch (width) {
  607.                     case 1024:
  608.                         if (height == 768)
  609.                             default_var = default_var_1024x768;
  610.                         break;
  611.                     case 1152:
  612.                         if (height == 900)
  613.                             default_var = default_var_1152x900;
  614.                         break;
  615.                     case 1280:
  616.                         if (height == 1024)
  617.                             default_var = default_var_1280x1024;
  618.                         break;
  619.                     default:
  620.                         break;
  621.                 }
  622.                 switch (depth) {
  623.                     case 8:
  624.                         default_var.bits_per_pixel = 8;
  625.                         break;
  626.                     case 16:
  627.                         default_var.bits_per_pixel = 16;
  628.                         break;
  629.                     case 24:
  630.                         default_var.bits_per_pixel = 24;
  631.                         break;
  632.                     case 32:
  633.                         default_var.bits_per_pixel = 32;
  634.                         break;
  635.                     default:
  636.                         break;
  637.                 }
  638.             }
  639. #endif
  640. if (!iga_init(info)) {
  641. iounmap((void *)info->io_base);
  642. iounmap(info->frame_buffer);
  643. if (info->mmap_map)
  644. kfree(info->mmap_map);
  645. kfree(info);
  646.         }
  647. #ifdef __sparc__
  648.     /*
  649.      * Add /dev/fb mmap values.
  650.      */
  651.     
  652.     /* First region is for video memory */
  653.     info->mmap_map[0].voff = 0x0;  
  654.     info->mmap_map[0].poff = info->frame_buffer_phys & PAGE_MASK;
  655.     info->mmap_map[0].size = info->total_vram   & PAGE_MASK;
  656.     info->mmap_map[0].prot_mask = SRMMU_CACHE;
  657.     info->mmap_map[0].prot_flag = SRMMU_WRITE;
  658.     /* Second region is for I/O ports */
  659.     info->mmap_map[1].voff = info->frame_buffer_phys & PAGE_MASK;
  660.     info->mmap_map[1].poff = info->io_base_phys & PAGE_MASK;
  661.     info->mmap_map[1].size = PAGE_SIZE * 2; /* X wants 2 pages */
  662.     info->mmap_map[1].prot_mask = SRMMU_CACHE;
  663.     info->mmap_map[1].prot_flag = SRMMU_WRITE;
  664. #endif /* __sparc__ */
  665. return 0;
  666. }
  667. int __init igafb_setup(char *options)
  668. {
  669.     char *this_opt;
  670.     if (!options || !*options)
  671.         return 0;
  672.     while ((this_opt = strsep(&options, ",")) != NULL) {
  673.         if (!strncmp(this_opt, "font:", 5)) {
  674.                 char *p;
  675.                 int i;
  676.                 p = this_opt + 5;
  677.                 for (i = 0; i < sizeof(fontname) - 1; i++)
  678.                         if (!*p || *p == ' ' || *p == ',')
  679.                                 break;
  680.                 memcpy(fontname, this_opt + 5, i);
  681.                 fontname[i] = 0;
  682.         }
  683.     }
  684.     return 0;
  685. }
  686. MODULE_LICENSE("GPL");