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 static struct cdev file_cdev
;
32 static struct visorchannel
**file_controlvm_channel
;
34 static int visorchipset_open(struct inode
*inode
, struct file
*file
);
35 static int visorchipset_release(struct inode
*inode
, struct file
*file
);
36 static int visorchipset_mmap(struct file
*file
, struct vm_area_struct
*vma
);
37 static long visorchipset_ioctl(struct file
*file
, unsigned int cmd
,
40 static const struct file_operations visorchipset_fops
= {
42 .open
= visorchipset_open
,
45 .unlocked_ioctl
= visorchipset_ioctl
,
46 .release
= visorchipset_release
,
47 .mmap
= visorchipset_mmap
,
51 visorchipset_file_init(dev_t major_dev
, struct visorchannel
**controlvm_channel
)
55 file_controlvm_channel
= controlvm_channel
;
56 cdev_init(&file_cdev
, &visorchipset_fops
);
57 file_cdev
.owner
= THIS_MODULE
;
58 if (MAJOR(major_dev
) == 0) {
59 /* dynamic major device number registration required */
60 if (alloc_chrdev_region(&major_dev
, 0, 1, MYDRVNAME
) < 0)
63 /* static major device number registration required */
64 if (register_chrdev_region(major_dev
, 1, MYDRVNAME
) < 0)
67 rc
= cdev_add(&file_cdev
, MKDEV(MAJOR(major_dev
), 0), 1);
69 unregister_chrdev_region(major_dev
, 1);
76 visorchipset_file_cleanup(dev_t major_dev
)
78 if (file_cdev
.ops
!= NULL
)
81 unregister_chrdev_region(major_dev
, 1);
85 visorchipset_open(struct inode
*inode
, struct file
*file
)
87 unsigned minor_number
= iminor(inode
);
89 if (minor_number
!= 0)
91 file
->private_data
= NULL
;
96 visorchipset_release(struct inode
*inode
, struct file
*file
)
102 visorchipset_mmap(struct file
*file
, struct vm_area_struct
*vma
)
105 ulong offset
= vma
->vm_pgoff
<< PAGE_SHIFT
;
106 GUEST_PHYSICAL_ADDRESS addr
= 0;
108 /* sv_enable_dfp(); */
109 if (offset
& (PAGE_SIZE
- 1))
110 return -ENXIO
; /* need aligned offsets */
113 case VISORCHIPSET_MMAP_CONTROLCHANOFFSET
:
114 vma
->vm_flags
|= VM_IO
;
115 if (*file_controlvm_channel
== NULL
) {
118 visorchannel_read(*file_controlvm_channel
,
119 offsetof(struct spar_controlvm_channel_protocol
,
121 &addr
, sizeof(addr
));
125 physaddr
= (ulong
)addr
;
126 if (remap_pfn_range(vma
, vma
->vm_start
,
127 physaddr
>> PAGE_SHIFT
,
128 vma
->vm_end
- vma
->vm_start
,
129 /*pgprot_noncached */
130 (vma
->vm_page_prot
))) {
140 static long visorchipset_ioctl(struct file
*file
, unsigned int cmd
,
147 case VMCALL_QUERY_GUEST_VIRTUAL_TIME_OFFSET
:
148 /* get the physical rtc offset */
149 vrtc_offset
= issue_vmcall_query_guest_virtual_time_offset();
151 ((void __user
*)arg
, &vrtc_offset
, sizeof(vrtc_offset
))) {
155 case VMCALL_UPDATE_PHYSICAL_TIME
:
157 (&adjustment
, (void __user
*)arg
, sizeof(adjustment
))) {
160 return issue_vmcall_update_physical_time(adjustment
);