diff options
-rw-r--r-- | pci.c | 41 | ||||
-rw-r--r-- | private_data.h | 6 |
2 files changed, 47 insertions, 0 deletions
@@ -2,6 +2,7 @@ #include <linux/kernel.h> #include <linux/pci.h> +#include <linux/interrupt.h> #include "char.h" #include "harddoom.h" @@ -9,6 +10,34 @@ #include "harddoomdev.h" #include "private_data.h" +void handle_pong_sync(struct doom_data *doom_data) +{ + up(&doom_data->pong_sem); +} + +irqreturn_t doom_irq(int irq, void *dev) +{ + uint32_t interrupts; + struct doom_data *doom_data; + + + doom_data = dev; + + interrupts = get_interrupts(doom_data->iomem); + if (!interrupts) { + return IRQ_NONE; + } + + if (interrupts & HARDDOOM_INTR_PONG_SYNC) { + handle_pong_sync(doom_data); + interrupts &= ~HARDDOOM_INTR_PONG_SYNC; + } + + deactivate_intr(doom_data->iomem, HARDDOOM_INTR_MASK); + + return IRQ_HANDLED; +} + int init_pci(struct pci_dev *dev) { struct doom_data *doom_data; @@ -30,8 +59,19 @@ int init_pci(struct pci_dev *dev) pci_set_dma_mask(dev, DMA_BIT_MASK(32)); pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(32)); + mutex_init(&doom_data->mutex); + sema_init(&doom_data->ping_sem, 1); + sema_init(&doom_data->pong_sem, 0); + + ORFAIL(request_irq(dev->irq, doom_irq, IRQF_SHARED, + "doom", doom_data), error_irq); + return 0; +error_irq: + pci_clear_master(dev); + pci_iounmap(dev, doom_data->iomem); + kfree(doom_data); error_kmalloc: pci_release_regions(dev); error_regions: @@ -46,6 +86,7 @@ void cleanup_pci(struct pci_dev *dev) doom_data = pci_get_drvdata(dev); + free_irq(dev->irq, doom_data); pci_clear_master(dev); pci_iounmap(dev, doom_data->iomem); kfree(doom_data); diff --git a/private_data.h b/private_data.h index 38148bd..39ceba8 100644 --- a/private_data.h +++ b/private_data.h @@ -9,13 +9,19 @@ struct doom_data { struct device *device; struct device *pci_device; void __iomem *iomem; + struct mutex mutex; + struct semaphore ping_sem; + struct semaphore pong_sem; }; struct surface_data { struct doom_data *doom_data; int surface_size; + int width; + int height; int pages; + int total_bytes; uint8_t *surface_cpu; uint32_t *page_table_cpu; |