2 #include <linux/module.h>
3 #include <linux/kernel.h>
4 #include <linux/compiler.h>
6 #include <linux/init.h>
7 #include <linux/ioport.h>
8 #include <linux/completion.h>
10 #include <asm/uaccess.h>
13 #define HYPERCALL_DRIVER_NAME "Qumranet hypercall driver"
14 #define HYPERCALL_DRIVER_VERSION "1"
15 #define PCI_VENDOR_ID_HYPERCALL 0x5002
16 #define PCI_DEVICE_ID_HYPERCALL 0x2258
18 MODULE_AUTHOR ("Dor Laor <dor.laor@qumranet.com>");
19 MODULE_DESCRIPTION (HYPERCALL_DRIVER_NAME
);
20 MODULE_LICENSE("GPL");
21 MODULE_VERSION(HYPERCALL_DRIVER_VERSION
);
24 module_param(debug
, int, 0);
25 MODULE_PARM_DESC (debug
, "toggle debug flag");
27 #define HYPERCALL_DEBUG 1
29 # define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
30 # define assert(expr) \
31 if(unlikely(!(expr))) { \
32 printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \
33 #expr,__FILE__,__FUNCTION__,__LINE__); \
36 # define DPRINTK(fmt, args...)
37 # define assert(expr) do {} while (0)
40 static struct pci_device_id hypercall_pci_tbl
[] = {
41 {PCI_VENDOR_ID_HYPERCALL
, PCI_DEVICE_ID_HYPERCALL
, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0 },
44 MODULE_DEVICE_TABLE (pci
, hypercall_pci_tbl
);
46 struct hypercall_dev
{
47 struct pci_dev
*pci_dev
;
53 void __iomem
*mmio_addr
;
54 unsigned long base_addr
; /* device I/O address */
59 static void hypercall_cleanup_dev(struct hypercall_dev
*dev
);
62 static int __devinit
hypercall_init_board(struct pci_dev
*pdev
,
63 struct hypercall_dev
**dev_out
)
65 unsigned long *ioaddr
;
66 struct hypercall_dev
*dev
;
68 u32 disable_dev_on_err
= 0;
69 unsigned long pio_start
, pio_end
, pio_flags
, pio_len
;
70 unsigned long mmio_start
, mmio_end
, mmio_flags
, mmio_len
;
76 dev
= kzalloc(sizeof(*dev
), GFP_KERNEL
);
78 printk (KERN_ERR
"%s: Unable to alloc hypercall device\n", pci_name(pdev
));
82 rc
= pci_enable_device(pdev
);
85 disable_dev_on_err
= 1;
87 pio_start
= pci_resource_start (pdev
, 0);
88 pio_end
= pci_resource_end (pdev
, 0);
89 pio_flags
= pci_resource_flags (pdev
, 0);
90 pio_len
= pci_resource_len (pdev
, 0);
92 mmio_start
= pci_resource_start (pdev
, 1);
93 mmio_end
= pci_resource_end (pdev
, 1);
94 mmio_flags
= pci_resource_flags (pdev
, 1);
95 mmio_len
= pci_resource_len (pdev
, 1);
97 DPRINTK("PIO region size == 0x%02lX\n", pio_len
);
98 DPRINTK("MMIO region size == 0x%02lX\n", mmio_len
);
100 rc
= pci_request_regions (pdev
, "hypercall");
104 pci_set_master (pdev
);
108 ioaddr
= pci_iomap(pdev
, 0, 0);
110 printk(KERN_ERR
"%s: cannot map PIO, aborting\n", pci_name(pdev
));
114 dev
->base_addr
= (unsigned long)ioaddr
;
115 dev
->regs_len
= pio_len
;
117 ioaddr
= pci_iomap(pdev
, 1, 0);
118 if (ioaddr
== NULL
) {
119 printk(KERN_ERR
"%s: cannot remap MMIO, aborting\n", pci_name(pdev
));
123 dev
->base_addr
= ioaddr
;
124 dev
->regs_len
= mmio_len
;
125 #endif /* USE_IO_OPS */
131 hypercall_cleanup_dev(dev
);
132 if (disable_dev_on_err
)
133 pci_disable_device(pdev
);
137 static int __devinit
hypercall_init_one(struct pci_dev
*pdev
,
138 const struct pci_device_id
*ent
)
140 struct hypercall_dev
*dev
;
143 assert(pdev
!= NULL
);
146 pci_read_config_byte(pdev
, PCI_REVISION_ID
, &pci_rev
);
148 if (pdev
->vendor
== PCI_VENDOR_ID_HYPERCALL
&&
149 pdev
->device
== PCI_DEVICE_ID_HYPERCALL
) {
150 printk(KERN_INFO
"pci dev %s (id %04x:%04x rev %02x) is a guest hypercall device\n",
151 pci_name(pdev
), pdev
->vendor
, pdev
->device
, pci_rev
);
154 if (hypercall_init_board(pdev
, &dev
) != 0)
159 dev
->irq
= pdev
->irq
;
161 spin_lock_init(&dev
->lock
);
162 pci_set_drvdata(pdev
, dev
);
164 printk (KERN_INFO
"%s: 0x%lx, IRQ %d\n", dev
->name
, dev
->base_addr
, dev
->irq
);
168 static void __devexit
hypercall_remove_one(struct pci_dev
*pdev
)
170 struct hypercall_dev
*dev
= pci_get_drvdata(pdev
);
174 hypercall_cleanup_dev(dev
);
175 pci_disable_device(pdev
);
180 static int hypercall_suspend(struct pci_dev
*pdev
, pm_message_t state
)
182 pci_save_state(pdev
);
183 pci_set_power_state(pdev
, PCI_D3hot
);
184 DPRINTK("Power mgmt suspend, set power state to PCI_D3hot\n");
189 static int hypercall_resume(struct pci_dev
*pdev
)
191 pci_restore_state(pdev
);
192 pci_set_power_state(pdev
, PCI_D0
);
193 DPRINTK("Power mgmt resume, set power state to PCI_D0\n");
198 #endif /* CONFIG_PM */
200 static void hypercall_cleanup_dev(struct hypercall_dev
*dev
)
202 DPRINTK("cleaning up\n");
203 pci_release_regions(dev
->pci_dev
);
204 pci_iounmap(dev
->pci_dev
, (void*)dev
->base_addr
);
208 static struct pci_driver hypercall_pci_driver
= {
209 .name
= HYPERCALL_DRIVER_NAME
,
210 .id_table
= hypercall_pci_tbl
,
211 .probe
= hypercall_init_one
,
212 .remove
= __devexit_p(hypercall_remove_one
),
214 .suspend
= hypercall_suspend
,
215 .resume
= hypercall_resume
,
216 #endif /* CONFIG_PM */
219 static int __init
hypercall_init_module(void)
221 printk (KERN_INFO HYPERCALL_DRIVER_NAME
"\n");
222 return pci_module_init(&hypercall_pci_driver
);
225 static void __exit
hypercall_cleanup_module(void)
227 pci_unregister_driver(&hypercall_pci_driver
);
230 module_init(hypercall_init_module
);
231 module_exit(hypercall_cleanup_module
);