staging: unisys: fix indentation of uisutil_copy_fragsinfo_from_skb()
[deliverable/linux.git] / drivers / staging / unisys / visorchipset / file.c
CommitLineData
12e364b9
KC
1/* file.c
2 *
f6d0c1e6 3 * Copyright (C) 2010 - 2013 UNISYS CORPORATION
12e364b9
KC
4 * All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or (at
9 * your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
14 * NON INFRINGEMENT. See the GNU General Public License for more
15 * details.
16 */
17
18/* This contains the implementation that allows a usermode program to
19 * communicate with the visorchipset driver using a device/file interface.
20 */
21
22#include "globals.h"
23#include "visorchannel.h"
24#include <linux/mm.h>
25#include <linux/fs.h>
26#include "uisutils.h"
bd5b9b32 27#include "file.h"
12e364b9
KC
28
29#define CURRENT_FILE_PC VISOR_CHIPSET_PC_file_c
30
af96e9c0
BR
31typedef u64 GUEST_PHYSICAL_ADDRESS;
32
12e364b9
KC
33static struct cdev Cdev;
34static VISORCHANNEL **PControlVm_channel;
35static dev_t MajorDev = -1; /**< indicates major num for device */
36static BOOL Registered = FALSE;
37
38static int visorchipset_open(struct inode *inode, struct file *file);
39static int visorchipset_release(struct inode *inode, struct file *file);
40static int visorchipset_mmap(struct file *file, struct vm_area_struct *vma);
41#ifdef HAVE_UNLOCKED_IOCTL
42long visorchipset_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
43#else
44int visorchipset_ioctl(struct inode *inode, struct file *file,
45 unsigned int cmd, unsigned long arg);
46#endif
47
48static const struct file_operations visorchipset_fops = {
49 .owner = THIS_MODULE,
50 .open = visorchipset_open,
51 .read = NULL,
52 .write = NULL,
53#ifdef HAVE_UNLOCKED_IOCTL
54 .unlocked_ioctl = visorchipset_ioctl,
55#else
56 .ioctl = visorchipset_ioctl,
57#endif
58 .release = visorchipset_release,
59 .mmap = visorchipset_mmap,
60};
61
62int
63visorchipset_file_init(dev_t majorDev, VISORCHANNEL **pControlVm_channel)
64{
65 int rc = -1;
66
67 PControlVm_channel = pControlVm_channel;
68 MajorDev = majorDev;
69 cdev_init(&Cdev, &visorchipset_fops);
70 Cdev.owner = THIS_MODULE;
71 if (MAJOR(MajorDev) == 0) {
72 /* dynamic major device number registration required */
73 if (alloc_chrdev_region(&MajorDev, 0, 1, MYDRVNAME) < 0) {
74 ERRDRV("Unable to allocate+register char device %s",
75 MYDRVNAME);
22ad57ba 76 goto Away;
12e364b9
KC
77 }
78 Registered = TRUE;
79 INFODRV("New major number %d registered\n", MAJOR(MajorDev));
80 } else {
81 /* static major device number registration required */
82 if (register_chrdev_region(MajorDev, 1, MYDRVNAME) < 0) {
83 ERRDRV("Unable to register char device %s", MYDRVNAME);
22ad57ba 84 goto Away;
12e364b9
KC
85 }
86 Registered = TRUE;
87 INFODRV("Static major number %d registered\n", MAJOR(MajorDev));
88 }
5e54c97d 89 if (cdev_add(&Cdev, MKDEV(MAJOR(MajorDev), 0), 1) < 0) {
22ad57ba 90 ERRDRV("failed to create char device: (status=%d)\n", rc);
5e54c97d
KC
91 goto Away;
92 }
12e364b9
KC
93 INFODRV("Registered char device for %s (major=%d)",
94 MYDRVNAME, MAJOR(MajorDev));
22ad57ba 95 rc = 0;
12e364b9
KC
96Away:
97 return rc;
98}
99
100void
101visorchipset_file_cleanup(void)
102{
103 if (Cdev.ops != NULL)
104 cdev_del(&Cdev);
105 Cdev.ops = NULL;
106 if (Registered) {
107 if (MAJOR(MajorDev) >= 0) {
108 unregister_chrdev_region(MajorDev, 1);
109 MajorDev = MKDEV(0, 0);
110 }
111 Registered = FALSE;
112 }
113}
114
115static int
116visorchipset_open(struct inode *inode, struct file *file)
117{
118 unsigned minor_number = iminor(inode);
119 int rc = -ENODEV;
120
121 DEBUGDRV("%s", __func__);
122 if (minor_number != 0)
22ad57ba 123 goto Away;
12e364b9 124 file->private_data = NULL;
22ad57ba 125 rc = 0;
12e364b9
KC
126Away:
127 if (rc < 0)
128 ERRDRV("%s minor=%d failed", __func__, minor_number);
129 return rc;
130}
131
132static int
133visorchipset_release(struct inode *inode, struct file *file)
134{
12e364b9 135 DEBUGDRV("%s", __func__);
22ad57ba 136 return 0;
12e364b9
KC
137}
138
139static int
140visorchipset_mmap(struct file *file, struct vm_area_struct *vma)
141{
142 ulong physAddr = 0;
143 ulong offset = vma->vm_pgoff << PAGE_SHIFT;
144 GUEST_PHYSICAL_ADDRESS addr = 0;
145
146 /* sv_enable_dfp(); */
147 DEBUGDRV("%s", __func__);
148 if (offset & (PAGE_SIZE - 1)) {
149 ERRDRV("%s virtual address NOT page-aligned!", __func__);
150 return -ENXIO; /* need aligned offsets */
151 }
152 switch (offset) {
153 case VISORCHIPSET_MMAP_CONTROLCHANOFFSET:
154 vma->vm_flags |= VM_IO;
155 if (*PControlVm_channel == NULL) {
156 ERRDRV("%s no controlvm channel yet", __func__);
157 return -ENXIO;
158 }
159 visorchannel_read(*PControlVm_channel,
160 offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
161 gpControlChannel), &addr,
162 sizeof(addr));
163 if (addr == 0) {
164 ERRDRV("%s control channel address is 0", __func__);
165 return -ENXIO;
166 }
167 physAddr = (ulong) (addr);
168 DEBUGDRV("mapping physical address = 0x%lx", physAddr);
169 if (remap_pfn_range(vma, vma->vm_start,
170 physAddr >> PAGE_SHIFT,
171 vma->vm_end - vma->vm_start,
172 /*pgprot_noncached */
173 (vma->vm_page_prot))) {
174 ERRDRV("%s remap_pfn_range failed", __func__);
175 return -EAGAIN;
176 }
177 break;
178 default:
179 return -ENOSYS;
180 }
181 DEBUGDRV("%s success!", __func__);
182 return 0;
183}
184
185#ifdef HAVE_UNLOCKED_IOCTL
186long
187visorchipset_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
188#else
189int
190visorchipset_ioctl(struct inode *inode, struct file *file,
191 unsigned int cmd, unsigned long arg)
192#endif
193{
194 int rc = SUCCESS;
ec03a7db
BR
195 s64 adjustment;
196 s64 vrtc_offset;
12e364b9
KC
197 DBGINF("entered visorchipset_ioctl, cmd=%d", cmd);
198 switch (cmd) {
199 case VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET:
200 /* get the physical rtc offset */
201 vrtc_offset = Issue_VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET();
202 if (copy_to_user
22ad57ba
KC
203 ((void __user *)arg, &vrtc_offset, sizeof(vrtc_offset))) {
204 rc = -EFAULT;
205 goto Away;
206 }
12e364b9
KC
207 DBGINF("insde visorchipset_ioctl, cmd=%d, vrtc_offset=%lld",
208 cmd, vrtc_offset);
209 break;
210 case VMCALL_UPDATE_PHYSICAL_TIME:
211 if (copy_from_user
22ad57ba
KC
212 (&adjustment, (void __user *)arg, sizeof(adjustment))) {
213 rc = -EFAULT;
214 goto Away;
215 }
12e364b9
KC
216 DBGINF("insde visorchipset_ioctl, cmd=%d, adjustment=%lld", cmd,
217 adjustment);
218 rc = Issue_VMCALL_UPDATE_PHYSICAL_TIME(adjustment);
219 break;
220 default:
221 LOGERR("visorchipset_ioctl received invalid command");
22ad57ba 222 rc = -EFAULT;
12e364b9
KC
223 break;
224 }
12e364b9
KC
225Away:
226 DBGINF("exiting %d!", rc);
227 return rc;
228}
This page took 0.140104 seconds and 5 git commands to generate.