cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

gio.c (3251B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * arch/sh/boards/landisk/gio.c - driver for landisk
      4 *
      5 * This driver will also support the I-O DATA Device, Inc. LANDISK Board.
      6 * LANDISK and USL-5P Button, LED and GIO driver drive function.
      7 *
      8 *   Copylight (C) 2006 kogiidena
      9 *   Copylight (C) 2002 Atom Create Engineering Co., Ltd. *
     10 */
     11#include <linux/module.h>
     12#include <linux/init.h>
     13#include <linux/kdev_t.h>
     14#include <linux/cdev.h>
     15#include <linux/fs.h>
     16#include <asm/io.h>
     17#include <linux/uaccess.h>
     18#include <mach-landisk/mach/gio.h>
     19#include <mach-landisk/mach/iodata_landisk.h>
     20
     21#define DEVCOUNT                4
     22#define GIO_MINOR	        2	/* GIO minor no. */
     23
     24static dev_t dev;
     25static struct cdev *cdev_p;
     26static int openCnt;
     27
     28static int gio_open(struct inode *inode, struct file *filp)
     29{
     30	int minor = iminor(inode);
     31	int ret = -ENOENT;
     32
     33	preempt_disable();
     34	if (minor < DEVCOUNT) {
     35		if (openCnt > 0) {
     36			ret = -EALREADY;
     37		} else {
     38			openCnt++;
     39			ret = 0;
     40		}
     41	}
     42	preempt_enable();
     43	return ret;
     44}
     45
     46static int gio_close(struct inode *inode, struct file *filp)
     47{
     48	int minor = iminor(inode);
     49
     50	if (minor < DEVCOUNT) {
     51		openCnt--;
     52	}
     53	return 0;
     54}
     55
     56static long gio_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
     57{
     58	unsigned int data;
     59	static unsigned int addr = 0;
     60
     61	if (cmd & 0x01) {	/* write */
     62		if (copy_from_user(&data, (int *)arg, sizeof(int))) {
     63			return -EFAULT;
     64		}
     65	}
     66
     67	switch (cmd) {
     68	case GIODRV_IOCSGIOSETADDR:	/* address set */
     69		addr = data;
     70		break;
     71
     72	case GIODRV_IOCSGIODATA1:	/* write byte */
     73		__raw_writeb((unsigned char)(0x0ff & data), addr);
     74		break;
     75
     76	case GIODRV_IOCSGIODATA2:	/* write word */
     77		if (addr & 0x01) {
     78			return -EFAULT;
     79		}
     80		__raw_writew((unsigned short int)(0x0ffff & data), addr);
     81		break;
     82
     83	case GIODRV_IOCSGIODATA4:	/* write long */
     84		if (addr & 0x03) {
     85			return -EFAULT;
     86		}
     87		__raw_writel(data, addr);
     88		break;
     89
     90	case GIODRV_IOCGGIODATA1:	/* read byte */
     91		data = __raw_readb(addr);
     92		break;
     93
     94	case GIODRV_IOCGGIODATA2:	/* read word */
     95		if (addr & 0x01) {
     96			return -EFAULT;
     97		}
     98		data = __raw_readw(addr);
     99		break;
    100
    101	case GIODRV_IOCGGIODATA4:	/* read long */
    102		if (addr & 0x03) {
    103			return -EFAULT;
    104		}
    105		data = __raw_readl(addr);
    106		break;
    107	default:
    108		return -EFAULT;
    109		break;
    110	}
    111
    112	if ((cmd & 0x01) == 0) {	/* read */
    113		if (copy_to_user((int *)arg, &data, sizeof(int))) {
    114			return -EFAULT;
    115		}
    116	}
    117	return 0;
    118}
    119
    120static const struct file_operations gio_fops = {
    121	.owner = THIS_MODULE,
    122	.open = gio_open,	/* open */
    123	.release = gio_close,	/* release */
    124	.unlocked_ioctl = gio_ioctl,
    125	.llseek = noop_llseek,
    126};
    127
    128static int __init gio_init(void)
    129{
    130	int error;
    131
    132	printk(KERN_INFO "gio: driver initialized\n");
    133
    134	openCnt = 0;
    135
    136	if ((error = alloc_chrdev_region(&dev, 0, DEVCOUNT, "gio")) < 0) {
    137		printk(KERN_ERR
    138		       "gio: Couldn't alloc_chrdev_region, error=%d\n",
    139		       error);
    140		return 1;
    141	}
    142
    143	cdev_p = cdev_alloc();
    144	cdev_p->ops = &gio_fops;
    145	error = cdev_add(cdev_p, dev, DEVCOUNT);
    146	if (error) {
    147		printk(KERN_ERR
    148		       "gio: Couldn't cdev_add, error=%d\n", error);
    149		return 1;
    150	}
    151
    152	return 0;
    153}
    154
    155static void __exit gio_exit(void)
    156{
    157	cdev_del(cdev_p);
    158	unregister_chrdev_region(dev, DEVCOUNT);
    159}
    160
    161module_init(gio_init);
    162module_exit(gio_exit);
    163
    164MODULE_LICENSE("GPL");