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>
9 #include <linux/interrupt.h>
11 #include <asm/uaccess.h>
14 #define HYPERCALL_DRIVER_NAME "Qumranet_hypercall_driver"
15 #define HYPERCALL_DRIVER_VERSION "1"
16 #define PCI_VENDOR_ID_HYPERCALL 0x5002
17 #define PCI_DEVICE_ID_HYPERCALL 0x2258
19 MODULE_AUTHOR ("Dor Laor <dor.laor@qumranet.com>");
20 MODULE_DESCRIPTION (HYPERCALL_DRIVER_NAME
);
21 MODULE_LICENSE("GPL");
22 MODULE_VERSION(HYPERCALL_DRIVER_VERSION
);
25 module_param(debug
, int, 0);
26 MODULE_PARM_DESC (debug
, "toggle debug flag");
28 #define HYPERCALL_DEBUG 1
30 # define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
31 # define assert(expr) \
32 if(unlikely(!(expr))) { \
33 printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \
34 #expr,__FILE__,__FUNCTION__,__LINE__); \
37 # define DPRINTK(fmt, args...)
38 # define assert(expr) do {} while (0)
41 static struct pci_device_id hypercall_pci_tbl
[] = {
42 {PCI_VENDOR_ID_HYPERCALL
, PCI_DEVICE_ID_HYPERCALL
, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0 },
45 MODULE_DEVICE_TABLE (pci
, hypercall_pci_tbl
);
49 /****** Hypercall device definitions ***************/
50 /* To be moved into a shared file with user space */
51 #define HP_CMD 0x00 // The command register WR
52 #define HP_ISRSTATUS 0x04 // Interrupt status reg RD
53 #define HP_TXSIZE 0x08
54 #define HP_TXBUFF 0x0c
55 #define HP_RXSIZE 0x10
56 #define HP_RXBUFF 0x14
58 // HP_CMD register commands
59 #define HP_CMD_DI 1 // disable interrupts
60 #define HP_CMD_EI 2 // enable interrupts
61 #define HP_CMD_INIT 4 // reset device
62 #define HP_CMD_RESET (HP_CMD_INIT|HP_CMD_DI)
64 /* Bits in HP_ISR - Interrupt status register */
65 #define HPISR_RX 0x01 // Data is ready to be read
67 #define HP_MEM_SIZE 0xE0
68 /******* End of Hypercall device definitions */
70 /* read PIO/MMIO register */
71 #define HIO_READ8(reg, ioaddr) ioread8(ioaddr + (reg))
72 #define HIO_READ16(reg, ioaddr) ioread16(ioaddr + (reg))
73 #define HIO_READ32(reg, ioaddr) ioread32(ioaddr + (reg))
75 /* write PIO/MMIO register */
76 #define HIO_WRITE8(reg, val8, ioaddr) iowrite8((val8), ioaddr + (reg))
77 #define HIO_WRITE16(reg, val16, ioaddr) iowrite16((val16), ioaddr + (reg))
78 #define HIO_WRITE32(reg, val32, ioaddr) iowrite32((val32), ioaddr + (reg))
81 struct hypercall_dev
{
82 struct pci_dev
*pci_dev
;
83 struct kobject kobject
;
89 void __iomem
*io_addr
;
90 unsigned long base_addr
; /* device I/O address */
95 static int hypercall_close(struct hypercall_dev
* dev
);
96 static int hypercall_open(struct hypercall_dev
*dev
);
97 static void hypercall_cleanup_dev(struct hypercall_dev
*dev
);
98 static irqreturn_t
hypercall_interrupt(int irq
, void *dev_instance
,
99 struct pt_regs
*regs
);
101 static void __exit
hypercall_sysfs_remove(struct hypercall_dev
*dev
);
102 static int hypercall_sysfs_add(struct hypercall_dev
*dev
);
105 static int __devinit
hypercall_init_board(struct pci_dev
*pdev
,
106 struct hypercall_dev
**dev_out
)
108 unsigned long ioaddr
;
109 struct hypercall_dev
*dev
;
111 u32 disable_dev_on_err
= 0;
112 unsigned long pio_start
, pio_end
, pio_flags
, pio_len
;
113 unsigned long mmio_start
, mmio_end
, mmio_flags
, mmio_len
;
115 assert(pdev
!= NULL
);
119 dev
= kzalloc(sizeof(*dev
), GFP_KERNEL
);
121 printk (KERN_ERR
"%s: Unable to alloc hypercall device\n", pci_name(pdev
));
125 rc
= pci_enable_device(pdev
);
128 disable_dev_on_err
= 1;
130 pio_start
= pci_resource_start (pdev
, 0);
131 pio_end
= pci_resource_end (pdev
, 0);
132 pio_flags
= pci_resource_flags (pdev
, 0);
133 pio_len
= pci_resource_len (pdev
, 0);
135 mmio_start
= pci_resource_start (pdev
, 1);
136 mmio_end
= pci_resource_end (pdev
, 1);
137 mmio_flags
= pci_resource_flags (pdev
, 1);
138 mmio_len
= pci_resource_len (pdev
, 1);
140 DPRINTK("PIO region size == 0x%02lX\n", pio_len
);
141 DPRINTK("MMIO region size == 0x%02lX\n", mmio_len
);
143 rc
= pci_request_regions (pdev
, "hypercall");
149 ioaddr
= (unsigned long)pci_iomap(pdev
, 0, 0);
150 //ioaddr = ioport_map(pio_start, pio_len);
152 printk(KERN_ERR
"%s: cannot map PIO, aborting\n", pci_name(pdev
));
156 dev
->base_addr
= (unsigned long)pio_start
;
157 dev
->io_addr
= (void*)ioaddr
;
158 dev
->regs_len
= pio_len
;
160 ioaddr
= pci_iomap(pdev
, 1, 0);
161 if (ioaddr
== NULL
) {
162 printk(KERN_ERR
"%s: cannot remap MMIO, aborting\n", pci_name(pdev
));
166 dev
->base_addr
= ioaddr
;
167 dev
->io_addr
= (void*)ioaddr
;
168 dev
->regs_len
= mmio_len
;
169 #endif /* USE_IO_OPS */
175 hypercall_cleanup_dev(dev
);
176 if (disable_dev_on_err
)
177 pci_disable_device(pdev
);
181 static int __devinit
hypercall_init_one(struct pci_dev
*pdev
,
182 const struct pci_device_id
*ent
)
184 struct hypercall_dev
*dev
;
187 assert(pdev
!= NULL
);
190 pci_read_config_byte(pdev
, PCI_REVISION_ID
, &pci_rev
);
192 if (pdev
->vendor
== PCI_VENDOR_ID_HYPERCALL
&&
193 pdev
->device
== PCI_DEVICE_ID_HYPERCALL
) {
194 printk(KERN_INFO
"pci dev %s (id %04x:%04x rev %02x) is a guest hypercall device\n",
195 pci_name(pdev
), pdev
->vendor
, pdev
->device
, pci_rev
);
198 if (hypercall_init_board(pdev
, &dev
) != 0)
203 dev
->irq
= pdev
->irq
;
205 spin_lock_init(&dev
->lock
);
206 pci_set_drvdata(pdev
, dev
);
208 printk (KERN_INFO
"name=%s: base_addr=0x%lx, io_addr=0x%lx, IRQ=%d\n",
209 dev
->name
, dev
->base_addr
, (unsigned long)dev
->io_addr
, dev
->irq
);
212 if (hypercall_sysfs_add(dev
) != 0)
218 static void __devexit
hypercall_remove_one(struct pci_dev
*pdev
)
220 struct hypercall_dev
*dev
= pci_get_drvdata(pdev
);
224 hypercall_close(dev
);
225 hypercall_sysfs_remove(dev
);
226 hypercall_cleanup_dev(dev
);
227 pci_disable_device(pdev
);
230 static int hypercall_tx(struct hypercall_dev
*dev
, unsigned char *buf
, size_t len
)
232 void __iomem
*ioaddr
= (void __iomem
*)dev
->io_addr
;
235 if (len
> HP_MEM_SIZE
)
238 spin_lock(&dev
->lock
);
239 HIO_WRITE8(HP_TXSIZE
, len
, ioaddr
);
240 for (i
=0; i
< len
; i
++)
241 HIO_WRITE8(HP_TXBUFF
, buf
[i
], ioaddr
);
242 spin_unlock(&dev
->lock
);
248 * The interrupt handler does all of the rx work and cleans up
251 static irqreturn_t
hypercall_interrupt(int irq
, void *dev_instance
,
252 struct pt_regs
*regs
)
254 struct hypercall_dev
*dev
= (struct hypercall_dev
*)dev_instance
;
255 void __iomem
*ioaddr
= (void __iomem
*)dev
->io_addr
;
257 int irq_handled
= IRQ_NONE
;
260 u8 buffer
[HP_MEM_SIZE
];
263 DPRINTK("base addr is 0x%lx, io_addr=0x%lx\n", dev
->base_addr
, (long)dev
->io_addr
);
265 spin_lock(&dev
->lock
);
266 status
= HIO_READ8(HP_ISRSTATUS
, ioaddr
);
267 DPRINTK("irq status is 0x%x\n", status
);
270 if (unlikely((status
& HPISR_RX
) == 0)) {
271 DPRINTK("not handeling irq, not ours\n");
275 /* Disable device interrupts */
276 HIO_WRITE8(HP_CMD
, HP_CMD_DI
, ioaddr
);
277 DPRINTK("disable device interrupts\n");
279 rx_buf_size
= HIO_READ8(HP_RXSIZE
, ioaddr
);
280 DPRINTK("Rx buffer size is %d\n", rx_buf_size
);
282 if (rx_buf_size
> HP_MEM_SIZE
)
283 rx_buf_size
= HP_MEM_SIZE
;
285 for (i
=0, pbuf
=buffer
; i
<rx_buf_size
; i
++, pbuf
++) {
286 *pbuf
= HIO_READ8(HP_RXBUFF
, ioaddr
+ i
);
287 DPRINTK("Read 0x%x as dword %d\n", *pbuf
, i
);
290 DPRINTK("Read buffer %s", (char*)buffer
);
292 HIO_WRITE8(HP_CMD
, HP_CMD_EI
, ioaddr
);
293 DPRINTK("Enable interrupt\n");
294 irq_handled
= IRQ_HANDLED
;
296 spin_unlock(&dev
->lock
);
299 hypercall_tx(dev
, "hello host", sizeof("hello host"));
304 static int hypercall_open(struct hypercall_dev
*dev
)
308 rc
= request_irq(dev
->irq
, &hypercall_interrupt
,
309 SA_SHIRQ
, dev
->name
, dev
);
311 printk(KERN_ERR
"%s failed to request an irq\n", __FUNCTION__
);
315 //hypercall_thread_start(dev);
320 static int hypercall_close(struct hypercall_dev
* dev
)
322 //hypercall_thread_stop(dev);
323 synchronize_irq(dev
->irq
);
324 free_irq(dev
->irq
, dev
);
331 static int hypercall_suspend(struct pci_dev
*pdev
, pm_message_t state
)
333 pci_save_state(pdev
);
334 pci_set_power_state(pdev
, PCI_D3hot
);
335 DPRINTK("Power mgmt suspend, set power state to PCI_D3hot\n");
340 static int hypercall_resume(struct pci_dev
*pdev
)
342 pci_restore_state(pdev
);
343 pci_set_power_state(pdev
, PCI_D0
);
344 DPRINTK("Power mgmt resume, set power state to PCI_D0\n");
349 #endif /* CONFIG_PM */
351 static void hypercall_cleanup_dev(struct hypercall_dev
*dev
)
353 DPRINTK("cleaning up\n");
354 pci_release_regions(dev
->pci_dev
);
355 pci_iounmap(dev
->pci_dev
, (void*)dev
->io_addr
);
356 pci_set_drvdata (dev
->pci_dev
, NULL
);
360 static struct pci_driver hypercall_pci_driver
= {
361 .name
= HYPERCALL_DRIVER_NAME
,
362 .id_table
= hypercall_pci_tbl
,
363 .probe
= hypercall_init_one
,
364 .remove
= __devexit_p(hypercall_remove_one
),
366 .suspend
= hypercall_suspend
,
367 .resume
= hypercall_resume
,
368 #endif /* CONFIG_PM */
371 static int __init
hypercall_init_module(void)
373 printk (KERN_INFO HYPERCALL_DRIVER_NAME
"\n");
374 return pci_module_init(&hypercall_pci_driver
);
377 static void __exit
hypercall_cleanup_module(void)
379 pci_unregister_driver(&hypercall_pci_driver
);
386 struct hypercall_attribute
{
387 struct attribute attr
;
388 ssize_t (*show
)(struct hypercall_dev
*, char *buf
);
389 ssize_t (*store
)(struct hypercall_dev
*, unsigned long val
);
392 static ssize_t
hypercall_attribute_show(struct kobject
*kobj
,
393 struct attribute
*attr
, char *buf
)
395 struct hypercall_attribute
*hypercall_attr
;
396 struct hypercall_dev
*hdev
;
398 hypercall_attr
= container_of(attr
, struct hypercall_attribute
, attr
);
399 hdev
= container_of(kobj
, struct hypercall_dev
, kobject
);
401 if (!hypercall_attr
->show
)
404 return hypercall_attr
->show(hdev
, buf
);
407 static ssize_t
hypercall_attribute_store(struct kobject
*kobj
,
408 struct attribute
*attr
, const char *buf
, size_t count
)
410 struct hypercall_attribute
*hypercall_attr
;
411 struct hypercall_dev
*hdev
;
416 val
= simple_strtoul(buf
, &endp
, 0);
418 hypercall_attr
= container_of(attr
, struct hypercall_attribute
, attr
);
419 hdev
= container_of(kobj
, struct hypercall_dev
, kobject
);
421 if (!hypercall_attr
->store
)
424 rc
= hypercall_attr
->store(hdev
, val
);
430 #define MAKE_HYPERCALL_R_ATTR(_name) \
431 static ssize_t _name##_show(struct hypercall_dev *hdev, char *buf) \
433 return sprintf(buf, "%lu\n", (unsigned long)hdev->_name); \
435 struct hypercall_attribute hypercall_attr_##_name = __ATTR_RO(_name)
437 #define MAKE_HYPERCALL_WR_ATTR(_name) \
438 static int _name##_store(struct hypercall_dev *hdev, unsigned long val) \
440 hdev->_name = (typeof(hdev->_name))val; \
443 static ssize_t _name##_show(struct hypercall_dev *hdev, char *buf) \
445 return sprintf(buf, "%lu\n", (unsigned long)hdev->_name); \
447 struct hypercall_attribute hypercall_attr_##_name = \
448 __ATTR(_name,S_IRUGO|S_IWUGO,_name##_show,_name##_store)
450 MAKE_HYPERCALL_R_ATTR(base_addr
);
451 MAKE_HYPERCALL_R_ATTR(irq
);
452 MAKE_HYPERCALL_WR_ATTR(cmd
);
454 #define GET_HYPERCALL_ATTR(_name) (&hypercall_attr_##_name.attr)
456 static struct attribute
*hypercall_default_attrs
[] = {
457 GET_HYPERCALL_ATTR(base_addr
),
458 GET_HYPERCALL_ATTR(irq
),
459 GET_HYPERCALL_ATTR(cmd
),
463 static struct sysfs_ops hypercall_sysfs_ops
= {
464 .show
= hypercall_attribute_show
,
465 .store
= hypercall_attribute_store
,
468 static void hypercall_sysfs_release(struct kobject
*kobj
)
470 DPRINTK(" called for obj name %s\n", kobj
->name
);
473 static struct kobj_type hypercall_ktype
= {
474 .release
= hypercall_sysfs_release
,
475 .sysfs_ops
= &hypercall_sysfs_ops
,
476 .default_attrs
= hypercall_default_attrs
480 static int hypercall_sysfs_add(struct hypercall_dev
*dev
)
484 kobject_init(&dev
->kobject
);
485 dev
->kobject
.ktype
= &hypercall_ktype
;
486 rc
= kobject_set_name(&dev
->kobject
, "%s", HYPERCALL_DRIVER_NAME
);
488 printk("%s: kobject_set_name failed, err=%d\n", __FUNCTION__
, rc
);
492 rc
= kobject_add(&dev
->kobject
);
494 printk("%s: kobject_add failed, err=%d\n", __FUNCTION__
, rc
);
498 rc
= sysfs_create_link(&dev
->pci_dev
->dev
.kobj
, &dev
->kobject
,
499 HYPERCALL_DRIVER_NAME
);
501 printk("%s: sysfs_create_link failed, err=%d\n", __FUNCTION__
, rc
);
502 kobject_del(&dev
->kobject
);
508 static void hypercall_sysfs_remove(struct hypercall_dev
*dev
)
510 sysfs_remove_link(&dev
->pci_dev
->dev
.kobj
, HYPERCALL_DRIVER_NAME
);
511 kobject_del(&dev
->kobject
);
514 module_init(hypercall_init_module
);
515 module_exit(hypercall_cleanup_module
);