sbuslib.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /* sbuslib.c: Helper library for SBUS framebuffer drivers.
  2. *
  3. * Copyright (C) 2003 David S. Miller (davem@redhat.com)
  4. */
  5. #include <linux/kernel.h>
  6. #include <linux/module.h>
  7. #include <linux/string.h>
  8. #include <linux/fb.h>
  9. #include <linux/mm.h>
  10. #include <asm/oplib.h>
  11. #include <asm/fbio.h>
  12. #include "sbuslib.h"
  13. void sbusfb_fill_var(struct fb_var_screeninfo *var, int prom_node, int bpp)
  14. {
  15. memset(var, 0, sizeof(*var));
  16. var->xres = prom_getintdefault(prom_node, "width", 1152);
  17. var->yres = prom_getintdefault(prom_node, "height", 900);
  18. var->xres_virtual = var->xres;
  19. var->yres_virtual = var->yres;
  20. var->bits_per_pixel = bpp;
  21. }
  22. EXPORT_SYMBOL(sbusfb_fill_var);
  23. static unsigned long sbusfb_mmapsize(long size, unsigned long fbsize)
  24. {
  25. if (size == SBUS_MMAP_EMPTY) return 0;
  26. if (size >= 0) return size;
  27. return fbsize * (-size);
  28. }
  29. int sbusfb_mmap_helper(struct sbus_mmap_map *map,
  30. unsigned long physbase,
  31. unsigned long fbsize,
  32. unsigned long iospace,
  33. struct vm_area_struct *vma)
  34. {
  35. unsigned int size, page, r, map_size;
  36. unsigned long map_offset = 0;
  37. unsigned long off;
  38. int i;
  39. size = vma->vm_end - vma->vm_start;
  40. if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
  41. return -EINVAL;
  42. off = vma->vm_pgoff << PAGE_SHIFT;
  43. /* To stop the swapper from even considering these pages */
  44. vma->vm_flags |= (VM_IO | VM_RESERVED);
  45. /* Each page, see which map applies */
  46. for (page = 0; page < size; ){
  47. map_size = 0;
  48. for (i = 0; map[i].size; i++)
  49. if (map[i].voff == off+page) {
  50. map_size = sbusfb_mmapsize(map[i].size, fbsize);
  51. #ifdef __sparc_v9__
  52. #define POFF_MASK (PAGE_MASK|0x1UL)
  53. #else
  54. #define POFF_MASK (PAGE_MASK)
  55. #endif
  56. map_offset = (physbase + map[i].poff) & POFF_MASK;
  57. break;
  58. }
  59. if (!map_size){
  60. page += PAGE_SIZE;
  61. continue;
  62. }
  63. if (page + map_size > size)
  64. map_size = size - page;
  65. r = io_remap_pfn_range(vma,
  66. vma->vm_start + page,
  67. MK_IOSPACE_PFN(iospace,
  68. map_offset >> PAGE_SHIFT),
  69. map_size,
  70. vma->vm_page_prot);
  71. if (r)
  72. return -EAGAIN;
  73. page += map_size;
  74. }
  75. return 0;
  76. }
  77. EXPORT_SYMBOL(sbusfb_mmap_helper);
  78. int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
  79. struct fb_info *info,
  80. int type, int fb_depth, unsigned long fb_size)
  81. {
  82. switch(cmd) {
  83. case FBIOGTYPE: {
  84. struct fbtype __user *f = (struct fbtype __user *) arg;
  85. if (put_user(type, &f->fb_type) ||
  86. __put_user(info->var.yres, &f->fb_height) ||
  87. __put_user(info->var.xres, &f->fb_width) ||
  88. __put_user(fb_depth, &f->fb_depth) ||
  89. __put_user(0, &f->fb_cmsize) ||
  90. __put_user(fb_size, &f->fb_cmsize))
  91. return -EFAULT;
  92. return 0;
  93. }
  94. case FBIOPUTCMAP_SPARC: {
  95. struct fbcmap __user *c = (struct fbcmap __user *) arg;
  96. struct fb_cmap cmap;
  97. u16 red, green, blue;
  98. u8 red8, green8, blue8;
  99. unsigned char __user *ured;
  100. unsigned char __user *ugreen;
  101. unsigned char __user *ublue;
  102. int index, count, i;
  103. if (get_user(index, &c->index) ||
  104. __get_user(count, &c->count) ||
  105. __get_user(ured, &c->red) ||
  106. __get_user(ugreen, &c->green) ||
  107. __get_user(ublue, &c->blue))
  108. return -EFAULT;
  109. cmap.len = 1;
  110. cmap.red = &red;
  111. cmap.green = &green;
  112. cmap.blue = &blue;
  113. cmap.transp = NULL;
  114. for (i = 0; i < count; i++) {
  115. int err;
  116. if (get_user(red8, &ured[i]) ||
  117. get_user(green8, &ugreen[i]) ||
  118. get_user(blue8, &ublue[i]))
  119. return -EFAULT;
  120. red = red8 << 8;
  121. green = green8 << 8;
  122. blue = blue8 << 8;
  123. cmap.start = index + i;
  124. err = fb_set_cmap(&cmap, info);
  125. if (err)
  126. return err;
  127. }
  128. return 0;
  129. }
  130. case FBIOGETCMAP_SPARC: {
  131. struct fbcmap __user *c = (struct fbcmap __user *) arg;
  132. unsigned char __user *ured;
  133. unsigned char __user *ugreen;
  134. unsigned char __user *ublue;
  135. struct fb_cmap *cmap = &info->cmap;
  136. int index, count, i;
  137. u8 red, green, blue;
  138. if (get_user(index, &c->index) ||
  139. __get_user(count, &c->count) ||
  140. __get_user(ured, &c->red) ||
  141. __get_user(ugreen, &c->green) ||
  142. __get_user(ublue, &c->blue))
  143. return -EFAULT;
  144. if (index + count > cmap->len)
  145. return -EINVAL;
  146. for (i = 0; i < count; i++) {
  147. red = cmap->red[index + i] >> 8;
  148. green = cmap->green[index + i] >> 8;
  149. blue = cmap->blue[index + i] >> 8;
  150. if (put_user(red, &ured[i]) ||
  151. put_user(green, &ugreen[i]) ||
  152. put_user(blue, &ublue[i]))
  153. return -EFAULT;
  154. }
  155. return 0;
  156. }
  157. default:
  158. return -EINVAL;
  159. };
  160. }
  161. EXPORT_SYMBOL(sbusfb_ioctl_helper);