1 /* sbuslib.c: Helper library for SBUS framebuffer drivers.
3 * Copyright (C) 2003 David S. Miller (davem@redhat.com)
6 #include <linux/kernel.h>
7 #include <linux/module.h>
8 #include <linux/string.h>
12 #include <asm/oplib.h>
17 void sbusfb_fill_var(struct fb_var_screeninfo
*var
, int prom_node
, int bpp
)
19 memset(var
, 0, sizeof(*var
));
21 var
->xres
= prom_getintdefault(prom_node
, "width", 1152);
22 var
->yres
= prom_getintdefault(prom_node
, "height", 900);
23 var
->xres_virtual
= var
->xres
;
24 var
->yres_virtual
= var
->yres
;
25 var
->bits_per_pixel
= bpp
;
28 EXPORT_SYMBOL(sbusfb_fill_var
);
30 static unsigned long sbusfb_mmapsize(long size
, unsigned long fbsize
)
32 if (size
== SBUS_MMAP_EMPTY
) return 0;
33 if (size
>= 0) return size
;
34 return fbsize
* (-size
);
37 int sbusfb_mmap_helper(struct sbus_mmap_map
*map
,
38 unsigned long physbase
,
40 unsigned long iospace
,
41 struct vm_area_struct
*vma
)
43 unsigned int size
, page
, r
, map_size
;
44 unsigned long map_offset
= 0;
48 size
= vma
->vm_end
- vma
->vm_start
;
49 if (vma
->vm_pgoff
> (~0UL >> PAGE_SHIFT
))
52 off
= vma
->vm_pgoff
<< PAGE_SHIFT
;
54 /* To stop the swapper from even considering these pages */
55 vma
->vm_flags
|= (VM_SHM
| VM_IO
| VM_LOCKED
);
57 /* Each page, see which map applies */
58 for (page
= 0; page
< size
; ){
60 for (i
= 0; map
[i
].size
; i
++)
61 if (map
[i
].voff
== off
+page
) {
62 map_size
= sbusfb_mmapsize(map
[i
].size
, fbsize
);
64 #define POFF_MASK (PAGE_MASK|0x1UL)
66 #define POFF_MASK (PAGE_MASK)
68 map_offset
= (physbase
+ map
[i
].poff
) & POFF_MASK
;
75 if (page
+ map_size
> size
)
76 map_size
= size
- page
;
77 r
= io_remap_page_range(vma
,
80 vma
->vm_page_prot
, iospace
);
88 EXPORT_SYMBOL(sbusfb_mmap_helper
);
90 int sbusfb_ioctl_helper(unsigned long cmd
, unsigned long arg
,
92 int type
, int fb_depth
, unsigned long fb_size
)
96 struct fbtype __user
*f
= (struct fbtype __user
*) arg
;
98 if (put_user(type
, &f
->fb_type
) ||
99 __put_user(info
->var
.yres
, &f
->fb_height
) ||
100 __put_user(info
->var
.xres
, &f
->fb_width
) ||
101 __put_user(fb_depth
, &f
->fb_depth
) ||
102 __put_user(0, &f
->fb_cmsize
) ||
103 __put_user(fb_size
, &f
->fb_cmsize
))
107 case FBIOPUTCMAP_SPARC
: {
108 struct fbcmap __user
*c
= (struct fbcmap __user
*) arg
;
110 u16 red
, green
, blue
;
111 unsigned char __user
*ured
;
112 unsigned char __user
*ugreen
;
113 unsigned char __user
*ublue
;
116 if (get_user(index
, &c
->index
) ||
117 __get_user(count
, &c
->count
) ||
118 __get_user(ured
, &c
->red
) ||
119 __get_user(ugreen
, &c
->green
) ||
120 __get_user(ublue
, &c
->blue
))
128 for (i
= 0; i
< count
; i
++) {
131 if (get_user(red
, &ured
[i
]) ||
132 get_user(green
, &ugreen
[i
]) ||
133 get_user(blue
, &ublue
[i
]))
136 cmap
.start
= index
+ i
;
137 err
= fb_set_cmap(&cmap
, info
);
143 case FBIOGETCMAP_SPARC
: {
144 struct fbcmap __user
*c
= (struct fbcmap __user
*) arg
;
145 unsigned char __user
*ured
;
146 unsigned char __user
*ugreen
;
147 unsigned char __user
*ublue
;
148 struct fb_cmap
*cmap
= &info
->cmap
;
151 if (get_user(index
, &c
->index
) ||
152 __get_user(count
, &c
->count
) ||
153 __get_user(ured
, &c
->red
) ||
154 __get_user(ugreen
, &c
->green
) ||
155 __get_user(ublue
, &c
->blue
))
158 if (index
+ count
> cmap
->len
)
161 for (i
= 0; i
< count
; i
++) {
162 if (put_user(cmap
->red
[index
+ i
], &ured
[i
]) ||
163 put_user(cmap
->green
[index
+ i
], &ugreen
[i
]) ||
164 put_user(cmap
->blue
[index
+ i
], &ublue
[i
]))
173 EXPORT_SYMBOL(sbusfb_ioctl_helper
);