brintos

brintos / linux-shallow public Read only

0
0
Text · 6.7 KiB · 4c79654 Raw
288 lines · c
1// SPDX-License-Identifier: GPL-2.02/* sbuslib.c: Helper library for SBUS framebuffer drivers.3 *4 * Copyright (C) 2003 David S. Miller (davem@redhat.com)5 */6 7#include <linux/compat.h>8#include <linux/kernel.h>9#include <linux/module.h>10#include <linux/string.h>11#include <linux/fb.h>12#include <linux/mm.h>13#include <linux/uaccess.h>14#include <linux/of.h>15 16#include <asm/fbio.h>17 18#include "sbuslib.h"19 20void sbusfb_fill_var(struct fb_var_screeninfo *var, struct device_node *dp,21		     int bpp)22{23	memset(var, 0, sizeof(*var));24 25	var->xres = of_getintprop_default(dp, "width", 1152);26	var->yres = of_getintprop_default(dp, "height", 900);27	var->xres_virtual = var->xres;28	var->yres_virtual = var->yres;29	var->bits_per_pixel = bpp;30}31 32EXPORT_SYMBOL(sbusfb_fill_var);33 34static unsigned long sbusfb_mmapsize(long size, unsigned long fbsize)35{36	if (size == SBUS_MMAP_EMPTY) return 0;37	if (size >= 0) return size;38	return fbsize * (-size);39}40 41int sbusfb_mmap_helper(const struct sbus_mmap_map *map,42		       unsigned long physbase,43		       unsigned long fbsize,44		       unsigned long iospace,45		       struct vm_area_struct *vma)46{47	unsigned int size, page, r, map_size;48	unsigned long map_offset = 0;49	unsigned long off;50	int i;51 52	if (!(vma->vm_flags & (VM_SHARED | VM_MAYSHARE)))53		return -EINVAL;54 55	size = vma->vm_end - vma->vm_start;56	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))57		return -EINVAL;58 59	off = vma->vm_pgoff << PAGE_SHIFT;60 61	/* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */62 63	vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);64	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);65 66	/* Each page, see which map applies */67	for (page = 0; page < size; ){68		map_size = 0;69		for (i = 0; map[i].size; i++)70			if (map[i].voff == off+page) {71				map_size = sbusfb_mmapsize(map[i].size, fbsize);72#ifdef __sparc_v9__73#define POFF_MASK	(PAGE_MASK|0x1UL)74#else75#define POFF_MASK	(PAGE_MASK)76#endif77				map_offset = (physbase + map[i].poff) & POFF_MASK;78				break;79			}80		if (!map_size) {81			page += PAGE_SIZE;82			continue;83		}84		if (page + map_size > size)85			map_size = size - page;86		r = io_remap_pfn_range(vma,87					vma->vm_start + page,88					MK_IOSPACE_PFN(iospace,89						map_offset >> PAGE_SHIFT),90					map_size,91					vma->vm_page_prot);92		if (r)93			return -EAGAIN;94		page += map_size;95	}96 97	return 0;98}99EXPORT_SYMBOL(sbusfb_mmap_helper);100 101int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,102			struct fb_info *info,103			int type, int fb_depth, unsigned long fb_size)104{105	switch(cmd) {106	case FBIOGTYPE: {107		struct fbtype __user *f = (struct fbtype __user *) arg;108 109		if (put_user(type, &f->fb_type) ||110		    put_user(info->var.yres, &f->fb_height) ||111		    put_user(info->var.xres, &f->fb_width) ||112		    put_user(fb_depth, &f->fb_depth) ||113		    put_user(0, &f->fb_cmsize) ||114		    put_user(fb_size, &f->fb_cmsize))115			return -EFAULT;116		return 0;117	}118	case FBIOPUTCMAP_SPARC: {119		struct fbcmap __user *c = (struct fbcmap __user *) arg;120		struct fb_cmap cmap;121		u16 red, green, blue;122		u8 red8, green8, blue8;123		unsigned char __user *ured;124		unsigned char __user *ugreen;125		unsigned char __user *ublue;126		unsigned int index, count, i;127 128		if (get_user(index, &c->index) ||129		    get_user(count, &c->count) ||130		    get_user(ured, &c->red) ||131		    get_user(ugreen, &c->green) ||132		    get_user(ublue, &c->blue))133			return -EFAULT;134 135		cmap.len = 1;136		cmap.red = &red;137		cmap.green = &green;138		cmap.blue = &blue;139		cmap.transp = NULL;140		for (i = 0; i < count; i++) {141			int err;142 143			if (get_user(red8, &ured[i]) ||144			    get_user(green8, &ugreen[i]) ||145			    get_user(blue8, &ublue[i]))146				return -EFAULT;147 148			red = red8 << 8;149			green = green8 << 8;150			blue = blue8 << 8;151 152			cmap.start = index + i;153			err = fb_set_cmap(&cmap, info);154			if (err)155				return err;156		}157		return 0;158	}159	case FBIOGETCMAP_SPARC: {160		struct fbcmap __user *c = (struct fbcmap __user *) arg;161		unsigned char __user *ured;162		unsigned char __user *ugreen;163		unsigned char __user *ublue;164		struct fb_cmap *cmap = &info->cmap;165		unsigned int index, count, i;166		u8 red, green, blue;167 168		if (get_user(index, &c->index) ||169		    get_user(count, &c->count) ||170		    get_user(ured, &c->red) ||171		    get_user(ugreen, &c->green) ||172		    get_user(ublue, &c->blue))173			return -EFAULT;174 175		if (index > cmap->len || count > cmap->len - index)176			return -EINVAL;177 178		for (i = 0; i < count; i++) {179			red = cmap->red[index + i] >> 8;180			green = cmap->green[index + i] >> 8;181			blue = cmap->blue[index + i] >> 8;182			if (put_user(red, &ured[i]) ||183			    put_user(green, &ugreen[i]) ||184			    put_user(blue, &ublue[i]))185				return -EFAULT;186		}187		return 0;188	}189	default:190		return -EINVAL;191	}192}193EXPORT_SYMBOL(sbusfb_ioctl_helper);194 195#ifdef CONFIG_COMPAT196int sbusfb_compat_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)197{198	switch (cmd) {199	case FBIOGTYPE:200	case FBIOSATTR:201	case FBIOGATTR:202	case FBIOSVIDEO:203	case FBIOGVIDEO:204	case FBIOSCURSOR32:205	case FBIOGCURSOR32:	/* This is not implemented yet.206				   Later it should be converted... */207	case FBIOSCURPOS:208	case FBIOGCURPOS:209	case FBIOGCURMAX:210		return info->fbops->fb_ioctl(info, cmd, arg);211	case FBIOPUTCMAP32:212	case FBIOPUTCMAP_SPARC: {213		struct fbcmap32 c;214		struct fb_cmap cmap;215		u16 red, green, blue;216		u8 red8, green8, blue8;217		unsigned char __user *ured;218		unsigned char __user *ugreen;219		unsigned char __user *ublue;220		unsigned int i;221 222		if (copy_from_user(&c, compat_ptr(arg), sizeof(c)))223			return -EFAULT;224		ured = compat_ptr(c.red);225		ugreen = compat_ptr(c.green);226		ublue = compat_ptr(c.blue);227 228		cmap.len = 1;229		cmap.red = &red;230		cmap.green = &green;231		cmap.blue = &blue;232		cmap.transp = NULL;233		for (i = 0; i < c.count; i++) {234			int err;235 236			if (get_user(red8, &ured[i]) ||237			    get_user(green8, &ugreen[i]) ||238			    get_user(blue8, &ublue[i]))239				return -EFAULT;240 241			red = red8 << 8;242			green = green8 << 8;243			blue = blue8 << 8;244 245			cmap.start = c.index + i;246			err = fb_set_cmap(&cmap, info);247			if (err)248				return err;249		}250		return 0;251	}252	case FBIOGETCMAP32: {253		struct fbcmap32 c;254		unsigned char __user *ured;255		unsigned char __user *ugreen;256		unsigned char __user *ublue;257		struct fb_cmap *cmap = &info->cmap;258		unsigned int index, i;259		u8 red, green, blue;260 261		if (copy_from_user(&c, compat_ptr(arg), sizeof(c)))262			return -EFAULT;263		index = c.index;264		ured = compat_ptr(c.red);265		ugreen = compat_ptr(c.green);266		ublue = compat_ptr(c.blue);267 268		if (index > cmap->len || c.count > cmap->len - index)269			return -EINVAL;270 271		for (i = 0; i < c.count; i++) {272			red = cmap->red[index + i] >> 8;273			green = cmap->green[index + i] >> 8;274			blue = cmap->blue[index + i] >> 8;275			if (put_user(red, &ured[i]) ||276			    put_user(green, &ugreen[i]) ||277			    put_user(blue, &ublue[i]))278				return -EFAULT;279		}280		return 0;281	}282	default:283		return -ENOIOCTLCMD;284	}285}286EXPORT_SYMBOL(sbusfb_compat_ioctl);287#endif288