3 * Copyright (C) 2010 - 2013 UNISYS CORPORATION
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.
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
18 /* This contains the implementation that allows a usermode program to
19 * communicate with the visorchipset driver using a device/file interface.
23 #include "visorchannel.h"
29 #define CURRENT_FILE_PC VISOR_CHIPSET_PC_file_c
31 typedef u64 GUEST_PHYSICAL_ADDRESS;
33 static struct cdev Cdev;
34 static VISORCHANNEL **PControlVm_channel;
35 static dev_t MajorDev = -1; /**< indicates major num for device */
36 static BOOL Registered = FALSE;
38 static int visorchipset_open(struct inode *inode, struct file *file);
39 static int visorchipset_release(struct inode *inode, struct file *file);
40 static int visorchipset_mmap(struct file *file, struct vm_area_struct *vma);
41 #ifdef HAVE_UNLOCKED_IOCTL
42 long visorchipset_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
44 int visorchipset_ioctl(struct inode *inode, struct file *file,
45 unsigned int cmd, unsigned long arg);
48 static const struct file_operations visorchipset_fops = {
50 .open = visorchipset_open,
53 #ifdef HAVE_UNLOCKED_IOCTL
54 .unlocked_ioctl = visorchipset_ioctl,
56 .ioctl = visorchipset_ioctl,
58 .release = visorchipset_release,
59 .mmap = visorchipset_mmap,
63 visorchipset_file_init(dev_t majorDev, VISORCHANNEL **pControlVm_channel)
67 PControlVm_channel = pControlVm_channel;
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",
79 INFODRV("New major number %d registered\n", MAJOR(MajorDev));
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);
87 INFODRV("Static major number %d registered\n", MAJOR(MajorDev));
89 if (cdev_add(&Cdev, MKDEV(MAJOR(MajorDev), 0), 1) < 0) {
90 ERRDRV("failed to create char device: (status=%d)\n", rc);
93 INFODRV("Registered char device for %s (major=%d)",
94 MYDRVNAME, MAJOR(MajorDev));
101 visorchipset_file_cleanup(void)
103 if (Cdev.ops != NULL)
107 if (MAJOR(MajorDev) >= 0) {
108 unregister_chrdev_region(MajorDev, 1);
109 MajorDev = MKDEV(0, 0);
116 visorchipset_open(struct inode *inode, struct file *file)
118 unsigned minor_number = iminor(inode);
121 DEBUGDRV("%s", __func__);
122 if (minor_number != 0)
124 file->private_data = NULL;
128 ERRDRV("%s minor=%d failed", __func__, minor_number);
133 visorchipset_release(struct inode *inode, struct file *file)
135 DEBUGDRV("%s", __func__);
140 visorchipset_mmap(struct file *file, struct vm_area_struct *vma)
143 ulong offset = vma->vm_pgoff << PAGE_SHIFT;
144 GUEST_PHYSICAL_ADDRESS addr = 0;
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 */
153 case VISORCHIPSET_MMAP_CONTROLCHANOFFSET:
154 vma->vm_flags |= VM_IO;
155 if (*PControlVm_channel == NULL) {
156 ERRDRV("%s no controlvm channel yet", __func__);
159 visorchannel_read(*PControlVm_channel,
160 offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL,
161 gpControlChannel), &addr,
164 ERRDRV("%s control channel address is 0", __func__);
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__);
181 DEBUGDRV("%s success!", __func__);
185 #ifdef HAVE_UNLOCKED_IOCTL
187 visorchipset_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
190 visorchipset_ioctl(struct inode *inode, struct file *file,
191 unsigned int cmd, unsigned long arg)
197 DBGINF("entered visorchipset_ioctl, cmd=%d", 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();
203 ((void __user *)arg, &vrtc_offset, sizeof(vrtc_offset))) {
207 DBGINF("insde visorchipset_ioctl, cmd=%d, vrtc_offset=%lld",
210 case VMCALL_UPDATE_PHYSICAL_TIME:
212 (&adjustment, (void __user *)arg, sizeof(adjustment))) {
216 DBGINF("insde visorchipset_ioctl, cmd=%d, adjustment=%lld", cmd,
218 rc = Issue_VMCALL_UPDATE_PHYSICAL_TIME(adjustment);
221 LOGERR("visorchipset_ioctl received invalid command");
226 DBGINF("exiting %d!", rc);