11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* sbuslib.c: Helper library for SBUS framebuffer drivers.
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2003 David S. Miller (davem@redhat.com)
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
69ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig#include <linux/compat.h>
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fb.h>
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h>
12631a9dca60ddd7d84a08171a14828e9cfb667d48Robert Reif#include <linux/uaccess.h>
136cd5a86b56ec8fc8651c043bdb05ea0c662fb704Robert Reif#include <linux/of_device.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/fbio.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sbuslib.h"
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
196cd5a86b56ec8fc8651c043bdb05ea0c662fb704Robert Reifvoid sbusfb_fill_var(struct fb_var_screeninfo *var, struct device_node *dp,
206cd5a86b56ec8fc8651c043bdb05ea0c662fb704Robert Reif		     int bpp)
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(var, 0, sizeof(*var));
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
246cd5a86b56ec8fc8651c043bdb05ea0c662fb704Robert Reif	var->xres = of_getintprop_default(dp, "width", 1152);
256cd5a86b56ec8fc8651c043bdb05ea0c662fb704Robert Reif	var->yres = of_getintprop_default(dp, "height", 900);
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->xres_virtual = var->xres;
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->yres_virtual = var->yres;
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	var->bits_per_pixel = bpp;
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(sbusfb_fill_var);
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long sbusfb_mmapsize(long size, unsigned long fbsize)
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (size == SBUS_MMAP_EMPTY) return 0;
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (size >= 0) return size;
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return fbsize * (-size);
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint sbusfb_mmap_helper(struct sbus_mmap_map *map,
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       unsigned long physbase,
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       unsigned long fbsize,
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       unsigned long iospace,
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       struct vm_area_struct *vma)
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int size, page, r, map_size;
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long map_offset = 0;
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long off;
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51e445ee65cbefaa19131c972ae7fe221c95cf4cc4David S. Miller	if (!(vma->vm_flags & (VM_SHARED | VM_MAYSHARE)))
52e445ee65cbefaa19131c972ae7fe221c95cf4cc4David S. Miller		return -EINVAL;
53e445ee65cbefaa19131c972ae7fe221c95cf4cc4David S. Miller
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	size = vma->vm_end - vma->vm_start;
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	off = vma->vm_pgoff << PAGE_SHIFT;
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
60314e51b9851b4f4e8ab302243ff5a6fc6147f379Konstantin Khlebnikov	/* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */
61314e51b9851b4f4e8ab302243ff5a6fc6147f379Konstantin Khlebnikov
6214778d9072e53d2171f66ffd9657daff41acfaedDavid S. Miller	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
6314778d9072e53d2171f66ffd9657daff41acfaedDavid S. Miller
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Each page, see which map applies */
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (page = 0; page < size; ){
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		map_size = 0;
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; map[i].size; i++)
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (map[i].voff == off+page) {
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				map_size = sbusfb_mmapsize(map[i].size, fbsize);
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef __sparc_v9__
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define POFF_MASK	(PAGE_MASK|0x1UL)
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define POFF_MASK	(PAGE_MASK)
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				map_offset = (physbase + map[i].poff) & POFF_MASK;
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
782dfd7cf6ce581621c5c0103f96cca7a9924b5f94Zac Storer		if (!map_size) {
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			page += PAGE_SIZE;
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			continue;
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (page + map_size > size)
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			map_size = size - page;
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		r = io_remap_pfn_range(vma,
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					vma->vm_start + page,
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					MK_IOSPACE_PFN(iospace,
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						map_offset >> PAGE_SHIFT),
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					map_size,
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					vma->vm_page_prot);
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (r)
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EAGAIN;
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		page += map_size;
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(sbusfb_mmap_helper);
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct fb_info *info,
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int type, int fb_depth, unsigned long fb_size)
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch(cmd) {
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FBIOGTYPE: {
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct fbtype __user *f = (struct fbtype __user *) arg;
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (put_user(type, &f->fb_type) ||
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    __put_user(info->var.yres, &f->fb_height) ||
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    __put_user(info->var.xres, &f->fb_width) ||
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    __put_user(fb_depth, &f->fb_depth) ||
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    __put_user(0, &f->fb_cmsize) ||
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    __put_user(fb_size, &f->fb_cmsize))
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FBIOPUTCMAP_SPARC: {
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct fbcmap __user *c = (struct fbcmap __user *) arg;
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct fb_cmap cmap;
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u16 red, green, blue;
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u8 red8, green8, blue8;
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned char __user *ured;
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned char __user *ugreen;
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned char __user *ublue;
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int index, count, i;
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (get_user(index, &c->index) ||
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    __get_user(count, &c->count) ||
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    __get_user(ured, &c->red) ||
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    __get_user(ugreen, &c->green) ||
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    __get_user(ublue, &c->blue))
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cmap.len = 1;
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cmap.red = &red;
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cmap.green = &green;
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cmap.blue = &blue;
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cmap.transp = NULL;
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < count; i++) {
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			int err;
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (get_user(red8, &ured[i]) ||
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    get_user(green8, &ugreen[i]) ||
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    get_user(blue8, &ublue[i]))
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return -EFAULT;
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			red = red8 << 8;
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			green = green8 << 8;
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			blue = blue8 << 8;
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cmap.start = index + i;
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err = fb_set_cmap(&cmap, info);
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (err)
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return err;
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case FBIOGETCMAP_SPARC: {
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct fbcmap __user *c = (struct fbcmap __user *) arg;
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned char __user *ured;
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned char __user *ugreen;
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned char __user *ublue;
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct fb_cmap *cmap = &info->cmap;
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int index, count, i;
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u8 red, green, blue;
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (get_user(index, &c->index) ||
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    __get_user(count, &c->count) ||
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    __get_user(ured, &c->red) ||
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    __get_user(ugreen, &c->green) ||
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    __get_user(ublue, &c->blue))
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EFAULT;
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (index + count > cmap->len)
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -EINVAL;
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < count; i++) {
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			red = cmap->red[index + i] >> 8;
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			green = cmap->green[index + i] >> 8;
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			blue = cmap->blue[index + i] >> 8;
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (put_user(red, &ured[i]) ||
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    put_user(green, &ugreen[i]) ||
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			    put_user(blue, &ublue[i]))
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				return -EFAULT;
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 0;
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
189cf6ac4ce1bdf2d0718d5f33d62f695e105706a5dJoe Perches	}
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL(sbusfb_ioctl_helper);
1929ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig
1939ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig#ifdef CONFIG_COMPAT
194c7006638a50cbf16bb420fa91e5af2dd22d28621David S. Millerstatic int fbiogetputcmap(struct fb_info *info, unsigned int cmd, unsigned long arg)
1959ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig{
1969ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	struct fbcmap32 __user *argp = (void __user *)arg;
1979ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	struct fbcmap __user *p = compat_alloc_user_space(sizeof(*p));
1989ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	u32 addr;
1999ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	int ret;
2009ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig
2019ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	ret = copy_in_user(p, argp, 2 * sizeof(int));
2029ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	ret |= get_user(addr, &argp->red);
2039ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	ret |= put_user(compat_ptr(addr), &p->red);
2049ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	ret |= get_user(addr, &argp->green);
2059ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	ret |= put_user(compat_ptr(addr), &p->green);
2069ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	ret |= get_user(addr, &argp->blue);
2079ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	ret |= put_user(compat_ptr(addr), &p->blue);
2089ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	if (ret)
2099ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig		return -EFAULT;
2105ebdce726baf17eb66c5a1bf402ae6f161a082edChristoph Hellwig	return info->fbops->fb_ioctl(info,
2119ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig			(cmd == FBIOPUTCMAP32) ?
2129ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig			FBIOPUTCMAP_SPARC : FBIOGETCMAP_SPARC,
2135ebdce726baf17eb66c5a1bf402ae6f161a082edChristoph Hellwig			(unsigned long)p);
2149ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig}
2159ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig
216c7006638a50cbf16bb420fa91e5af2dd22d28621David S. Millerstatic int fbiogscursor(struct fb_info *info, unsigned long arg)
2179ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig{
2189ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	struct fbcursor __user *p = compat_alloc_user_space(sizeof(*p));
2199ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	struct fbcursor32 __user *argp =  (void __user *)arg;
2209ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	compat_uptr_t addr;
2219ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	int ret;
2229ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig
2239ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	ret = copy_in_user(p, argp,
2249ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig			      2 * sizeof (short) + 2 * sizeof(struct fbcurpos));
2259ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	ret |= copy_in_user(&p->size, &argp->size, sizeof(struct fbcurpos));
2269ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	ret |= copy_in_user(&p->cmap, &argp->cmap, 2 * sizeof(int));
2279ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	ret |= get_user(addr, &argp->cmap.red);
2289ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	ret |= put_user(compat_ptr(addr), &p->cmap.red);
2299ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	ret |= get_user(addr, &argp->cmap.green);
2309ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	ret |= put_user(compat_ptr(addr), &p->cmap.green);
2319ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	ret |= get_user(addr, &argp->cmap.blue);
2329ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	ret |= put_user(compat_ptr(addr), &p->cmap.blue);
2339ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	ret |= get_user(addr, &argp->mask);
2349ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	ret |= put_user(compat_ptr(addr), &p->mask);
2359ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	ret |= get_user(addr, &argp->image);
2369ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	ret |= put_user(compat_ptr(addr), &p->image);
2379ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	if (ret)
2389ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig		return -EFAULT;
2395ebdce726baf17eb66c5a1bf402ae6f161a082edChristoph Hellwig	return info->fbops->fb_ioctl(info, FBIOSCURSOR, (unsigned long)p);
2409ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig}
2419ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig
242c7006638a50cbf16bb420fa91e5af2dd22d28621David S. Millerint sbusfb_compat_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
2439ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig{
2449ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	switch (cmd) {
2459ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	case FBIOGTYPE:
2469ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	case FBIOSATTR:
2479ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	case FBIOGATTR:
2489ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	case FBIOSVIDEO:
2499ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	case FBIOGVIDEO:
2509ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	case FBIOGCURSOR32:	/* This is not implemented yet.
2519ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig				   Later it should be converted... */
2529ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	case FBIOSCURPOS:
2539ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	case FBIOGCURPOS:
2549ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	case FBIOGCURMAX:
2555ebdce726baf17eb66c5a1bf402ae6f161a082edChristoph Hellwig		return info->fbops->fb_ioctl(info, cmd, arg);
2569ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	case FBIOPUTCMAP32:
2575ebdce726baf17eb66c5a1bf402ae6f161a082edChristoph Hellwig		return fbiogetputcmap(info, cmd, arg);
2589ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	case FBIOGETCMAP32:
2595ebdce726baf17eb66c5a1bf402ae6f161a082edChristoph Hellwig		return fbiogetputcmap(info, cmd, arg);
2609ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	case FBIOSCURSOR32:
2615ebdce726baf17eb66c5a1bf402ae6f161a082edChristoph Hellwig		return fbiogscursor(info, arg);
2629ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	default:
2639ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig		return -ENOIOCTLCMD;
2649ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig	}
2659ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig}
2669ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph HellwigEXPORT_SYMBOL(sbusfb_compat_ioctl);
2679ffb83bcc5c5337f980dc0576bf13ac9bd4fd33dChristoph Hellwig#endif
268