3 * Copyright © 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 static struct cdev Cdev
;
32 static VISORCHANNEL
**PControlVm_channel
;
33 static dev_t MajorDev
= -1; /**< indicates major num for device */
34 static BOOL Registered
= FALSE
;
36 static int visorchipset_open(struct inode
*inode
, struct file
*file
);
37 static int visorchipset_release(struct inode
*inode
, struct file
*file
);
38 static int visorchipset_mmap(struct file
*file
, struct vm_area_struct
*vma
);
39 #ifdef HAVE_UNLOCKED_IOCTL
40 long visorchipset_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
);
42 int visorchipset_ioctl(struct inode
*inode
, struct file
*file
,
43 unsigned int cmd
, unsigned long arg
);
46 static const struct file_operations visorchipset_fops
= {
48 .open
= visorchipset_open
,
51 #ifdef HAVE_UNLOCKED_IOCTL
52 .unlocked_ioctl
= visorchipset_ioctl
,
54 .ioctl
= visorchipset_ioctl
,
56 .release
= visorchipset_release
,
57 .mmap
= visorchipset_mmap
,
61 visorchipset_file_init(dev_t majorDev
, VISORCHANNEL
**pControlVm_channel
)
65 PControlVm_channel
= pControlVm_channel
;
67 cdev_init(&Cdev
, &visorchipset_fops
);
68 Cdev
.owner
= THIS_MODULE
;
69 if (MAJOR(MajorDev
) == 0) {
70 /* dynamic major device number registration required */
71 if (alloc_chrdev_region(&MajorDev
, 0, 1, MYDRVNAME
) < 0) {
72 ERRDRV("Unable to allocate+register char device %s",
77 INFODRV("New major number %d registered\n", MAJOR(MajorDev
));
79 /* static major device number registration required */
80 if (register_chrdev_region(MajorDev
, 1, MYDRVNAME
) < 0) {
81 ERRDRV("Unable to register char device %s", MYDRVNAME
);
85 INFODRV("Static major number %d registered\n", MAJOR(MajorDev
));
87 if (cdev_add(&Cdev
, MKDEV(MAJOR(MajorDev
), 0), 1) < 0)
88 FAIL("failed to create char device", -1);
89 INFODRV("Registered char device for %s (major=%d)",
90 MYDRVNAME
, MAJOR(MajorDev
));
97 visorchipset_file_cleanup(void)
103 if (MAJOR(MajorDev
) >= 0) {
104 unregister_chrdev_region(MajorDev
, 1);
105 MajorDev
= MKDEV(0, 0);
112 visorchipset_open(struct inode
*inode
, struct file
*file
)
114 unsigned minor_number
= iminor(inode
);
117 DEBUGDRV("%s", __func__
);
118 if (minor_number
!= 0)
120 file
->private_data
= NULL
;
124 ERRDRV("%s minor=%d failed", __func__
, minor_number
);
129 visorchipset_release(struct inode
*inode
, struct file
*file
)
132 DEBUGDRV("%s", __func__
);
139 visorchipset_mmap(struct file
*file
, struct vm_area_struct
*vma
)
142 ulong offset
= vma
->vm_pgoff
<< PAGE_SHIFT
;
143 GUEST_PHYSICAL_ADDRESS addr
= 0;
145 /* sv_enable_dfp(); */
146 DEBUGDRV("%s", __func__
);
147 if (offset
& (PAGE_SIZE
- 1)) {
148 ERRDRV("%s virtual address NOT page-aligned!", __func__
);
149 return -ENXIO
; /* need aligned offsets */
152 case VISORCHIPSET_MMAP_CONTROLCHANOFFSET
:
153 vma
->vm_flags
|= VM_IO
;
154 if (*PControlVm_channel
== NULL
) {
155 ERRDRV("%s no controlvm channel yet", __func__
);
158 visorchannel_read(*PControlVm_channel
,
159 offsetof(ULTRA_CONTROLVM_CHANNEL_PROTOCOL
,
160 gpControlChannel
), &addr
,
163 ERRDRV("%s control channel address is 0", __func__
);
166 physAddr
= (ulong
) (addr
);
167 DEBUGDRV("mapping physical address = 0x%lx", physAddr
);
168 if (remap_pfn_range(vma
, vma
->vm_start
,
169 physAddr
>> PAGE_SHIFT
,
170 vma
->vm_end
- vma
->vm_start
,
171 /*pgprot_noncached */
172 (vma
->vm_page_prot
))) {
173 ERRDRV("%s remap_pfn_range failed", __func__
);
180 DEBUGDRV("%s success!", __func__
);
184 #ifdef HAVE_UNLOCKED_IOCTL
186 visorchipset_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
189 visorchipset_ioctl(struct inode
*inode
, struct file
*file
,
190 unsigned int cmd
, unsigned long arg
)
196 DBGINF("entered visorchipset_ioctl, cmd=%d", cmd
);
198 case VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET
:
199 /* get the physical rtc offset */
200 vrtc_offset
= Issue_VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET();
202 ((void __user
*)arg
, &vrtc_offset
, sizeof(vrtc_offset
)))
204 DBGINF("insde visorchipset_ioctl, cmd=%d, vrtc_offset=%lld",
207 case VMCALL_UPDATE_PHYSICAL_TIME
:
209 (&adjustment
, (void __user
*)arg
, sizeof(adjustment
)))
211 DBGINF("insde visorchipset_ioctl, cmd=%d, adjustment=%lld", cmd
,
213 rc
= Issue_VMCALL_UPDATE_PHYSICAL_TIME(adjustment
);
216 LOGERR("visorchipset_ioctl received invalid command");
222 DBGINF("exiting %d!", rc
);