1 /* sbuslib.c: Helper library for SBUS framebuffer drivers.
3 * Copyright (C) 2003 David S. Miller (davem@redhat.com)
6 #include <linux/compat.h>
7 #include <linux/kernel.h>
8 #include <linux/module.h>
9 #include <linux/string.h>
13 #include <asm/oplib.h>
18 void sbusfb_fill_var(struct fb_var_screeninfo
*var
, int prom_node
, int bpp
)
20 memset(var
, 0, sizeof(*var
));
22 var
->xres
= prom_getintdefault(prom_node
, "width", 1152);
23 var
->yres
= prom_getintdefault(prom_node
, "height", 900);
24 var
->xres_virtual
= var
->xres
;
25 var
->yres_virtual
= var
->yres
;
26 var
->bits_per_pixel
= bpp
;
29 EXPORT_SYMBOL(sbusfb_fill_var
);
31 static unsigned long sbusfb_mmapsize(long size
, unsigned long fbsize
)
33 if (size
== SBUS_MMAP_EMPTY
) return 0;
34 if (size
>= 0) return size
;
35 return fbsize
* (-size
);
38 int sbusfb_mmap_helper(struct sbus_mmap_map
*map
,
39 unsigned long physbase
,
41 unsigned long iospace
,
42 struct vm_area_struct
*vma
)
44 unsigned int size
, page
, r
, map_size
;
45 unsigned long map_offset
= 0;
49 if (!(vma
->vm_flags
& (VM_SHARED
| VM_MAYSHARE
)))
52 size
= vma
->vm_end
- vma
->vm_start
;
53 if (vma
->vm_pgoff
> (~0UL >> PAGE_SHIFT
))
56 off
= vma
->vm_pgoff
<< PAGE_SHIFT
;
58 /* To stop the swapper from even considering these pages */
59 vma
->vm_flags
|= (VM_IO
| VM_RESERVED
);
61 /* Each page, see which map applies */
62 for (page
= 0; page
< size
; ){
64 for (i
= 0; map
[i
].size
; i
++)
65 if (map
[i
].voff
== off
+page
) {
66 map_size
= sbusfb_mmapsize(map
[i
].size
, fbsize
);
68 #define POFF_MASK (PAGE_MASK|0x1UL)
70 #define POFF_MASK (PAGE_MASK)
72 map_offset
= (physbase
+ map
[i
].poff
) & POFF_MASK
;
79 if (page
+ map_size
> size
)
80 map_size
= size
- page
;
81 r
= io_remap_pfn_range(vma
,
83 MK_IOSPACE_PFN(iospace
,
84 map_offset
>> PAGE_SHIFT
),
94 EXPORT_SYMBOL(sbusfb_mmap_helper
);
96 int sbusfb_ioctl_helper(unsigned long cmd
, unsigned long arg
,
98 int type
, int fb_depth
, unsigned long fb_size
)
102 struct fbtype __user
*f
= (struct fbtype __user
*) arg
;
104 if (put_user(type
, &f
->fb_type
) ||
105 __put_user(info
->var
.yres
, &f
->fb_height
) ||
106 __put_user(info
->var
.xres
, &f
->fb_width
) ||
107 __put_user(fb_depth
, &f
->fb_depth
) ||
108 __put_user(0, &f
->fb_cmsize
) ||
109 __put_user(fb_size
, &f
->fb_cmsize
))
113 case FBIOPUTCMAP_SPARC
: {
114 struct fbcmap __user
*c
= (struct fbcmap __user
*) arg
;
116 u16 red
, green
, blue
;
117 u8 red8
, green8
, blue8
;
118 unsigned char __user
*ured
;
119 unsigned char __user
*ugreen
;
120 unsigned char __user
*ublue
;
123 if (get_user(index
, &c
->index
) ||
124 __get_user(count
, &c
->count
) ||
125 __get_user(ured
, &c
->red
) ||
126 __get_user(ugreen
, &c
->green
) ||
127 __get_user(ublue
, &c
->blue
))
135 for (i
= 0; i
< count
; i
++) {
138 if (get_user(red8
, &ured
[i
]) ||
139 get_user(green8
, &ugreen
[i
]) ||
140 get_user(blue8
, &ublue
[i
]))
147 cmap
.start
= index
+ i
;
148 err
= fb_set_cmap(&cmap
, info
);
154 case FBIOGETCMAP_SPARC
: {
155 struct fbcmap __user
*c
= (struct fbcmap __user
*) arg
;
156 unsigned char __user
*ured
;
157 unsigned char __user
*ugreen
;
158 unsigned char __user
*ublue
;
159 struct fb_cmap
*cmap
= &info
->cmap
;
163 if (get_user(index
, &c
->index
) ||
164 __get_user(count
, &c
->count
) ||
165 __get_user(ured
, &c
->red
) ||
166 __get_user(ugreen
, &c
->green
) ||
167 __get_user(ublue
, &c
->blue
))
170 if (index
+ count
> cmap
->len
)
173 for (i
= 0; i
< count
; i
++) {
174 red
= cmap
->red
[index
+ i
] >> 8;
175 green
= cmap
->green
[index
+ i
] >> 8;
176 blue
= cmap
->blue
[index
+ i
] >> 8;
177 if (put_user(red
, &ured
[i
]) ||
178 put_user(green
, &ugreen
[i
]) ||
179 put_user(blue
, &ublue
[i
]))
188 EXPORT_SYMBOL(sbusfb_ioctl_helper
);
192 int index
; /* first element (0 origin) */
199 #define FBIOPUTCMAP32 _IOW('F', 3, struct fbcmap32)
200 #define FBIOGETCMAP32 _IOW('F', 4, struct fbcmap32)
202 static int fbiogetputcmap(struct file
*file
, struct fb_info
*info
,
203 unsigned int cmd
, unsigned long arg
)
205 struct fbcmap32 __user
*argp
= (void __user
*)arg
;
206 struct fbcmap __user
*p
= compat_alloc_user_space(sizeof(*p
));
210 ret
= copy_in_user(p
, argp
, 2 * sizeof(int));
211 ret
|= get_user(addr
, &argp
->red
);
212 ret
|= put_user(compat_ptr(addr
), &p
->red
);
213 ret
|= get_user(addr
, &argp
->green
);
214 ret
|= put_user(compat_ptr(addr
), &p
->green
);
215 ret
|= get_user(addr
, &argp
->blue
);
216 ret
|= put_user(compat_ptr(addr
), &p
->blue
);
219 return info
->fbops
->fb_ioctl(file
->f_dentry
->d_inode
, file
,
220 (cmd
== FBIOPUTCMAP32
) ?
221 FBIOPUTCMAP_SPARC
: FBIOGETCMAP_SPARC
,
222 (unsigned long)p
, info
);
226 short set
; /* what to set, choose from the list above */
227 short enable
; /* cursor on/off */
228 struct fbcurpos pos
; /* cursor position */
229 struct fbcurpos hot
; /* cursor hot spot */
230 struct fbcmap32 cmap
; /* color map info */
231 struct fbcurpos size
; /* cursor bit map size */
232 u32 image
; /* cursor image bits */
233 u32 mask
; /* cursor mask bits */
236 #define FBIOSCURSOR32 _IOW('F', 24, struct fbcursor32)
237 #define FBIOGCURSOR32 _IOW('F', 25, struct fbcursor32)
239 static int fbiogscursor(struct file
*file
, struct fb_info
*info
,
242 struct fbcursor __user
*p
= compat_alloc_user_space(sizeof(*p
));
243 struct fbcursor32 __user
*argp
= (void __user
*)arg
;
247 ret
= copy_in_user(p
, argp
,
248 2 * sizeof (short) + 2 * sizeof(struct fbcurpos
));
249 ret
|= copy_in_user(&p
->size
, &argp
->size
, sizeof(struct fbcurpos
));
250 ret
|= copy_in_user(&p
->cmap
, &argp
->cmap
, 2 * sizeof(int));
251 ret
|= get_user(addr
, &argp
->cmap
.red
);
252 ret
|= put_user(compat_ptr(addr
), &p
->cmap
.red
);
253 ret
|= get_user(addr
, &argp
->cmap
.green
);
254 ret
|= put_user(compat_ptr(addr
), &p
->cmap
.green
);
255 ret
|= get_user(addr
, &argp
->cmap
.blue
);
256 ret
|= put_user(compat_ptr(addr
), &p
->cmap
.blue
);
257 ret
|= get_user(addr
, &argp
->mask
);
258 ret
|= put_user(compat_ptr(addr
), &p
->mask
);
259 ret
|= get_user(addr
, &argp
->image
);
260 ret
|= put_user(compat_ptr(addr
), &p
->image
);
263 return info
->fbops
->fb_ioctl(file
->f_dentry
->d_inode
, file
,
264 FBIOSCURSOR
, (unsigned long)p
, info
);
267 long sbusfb_compat_ioctl(struct file
*file
, unsigned int cmd
,
268 unsigned long arg
, struct fb_info
*info
)
276 case FBIOGCURSOR32
: /* This is not implemented yet.
277 Later it should be converted... */
281 return info
->fbops
->fb_ioctl(file
->f_dentry
->d_inode
,
282 file
, cmd
, arg
, info
);
284 return fbiogetputcmap(file
, info
, cmd
, arg
);
286 return fbiogetputcmap(file
, info
, cmd
, arg
);
288 return fbiogscursor(file
, info
, arg
);
293 EXPORT_SYMBOL(sbusfb_compat_ioctl
);