From a2d05131f0515e5c53c12c26549f5be2ef7777e7 Mon Sep 17 00:00:00 2001 From: Marcin Chrzanowski Date: Wed, 23 May 2018 21:24:03 +0200 Subject: Implement draw columns --- char.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 138 insertions(+), 1 deletion(-) (limited to 'char.c') diff --git a/char.c b/char.c index a4ba095..54fd8a3 100644 --- a/char.c +++ b/char.c @@ -1,10 +1,13 @@ #include "char.h" +#include #include #include #include +#include #include "doomdev.h" +#include "harddoom.h" #include "util.h" #include "pci.h" #include "surface.h" @@ -24,9 +27,143 @@ long doom_create_surface(struct file *filp, unsigned long arg) return new_surface(filp, params); } +void free_texture(struct texture_data *texture_data); +int texture_release(struct inode *inode, struct file *filp) +{ + struct texture_data *texture_data; + + texture_data = filp->private_data; + + free_texture(texture_data); + + kfree(texture_data); + + return 0; +} + +struct file_operations texture_fops = { + .owner = THIS_MODULE, + .release = texture_release + +}; + +int verify_texture_params(struct doomdev_ioctl_create_texture *params) +{ + if (params->size > 4 * 1024 * 1024) { + return -EOVERFLOW; + } + + if (params->height > 1023) { + return -EOVERFLOW; + } + + return 0; +} + +int alloc_texture(struct doomdev_ioctl_create_texture *params, + struct texture_data *texture_data) +{ + int err; + int i; + int not_written; + int pages_needed; + + texture_data->size = params->size; + texture_data->height = params->height; + + pages_needed = (params->size / HARDDOOM_PAGE_SIZE); + if (params->size % HARDDOOM_PAGE_SIZE != 0) { + pages_needed += 1; + } + + texture_data->pages = pages_needed; + texture_data->texture_cpu = + dma_alloc_coherent(texture_data->doom_data->pci_device, + params->size, &texture_data->texture_dev, + GFP_KERNEL); + ORFAIL_NULL(texture_data->texture_cpu, -ENOMEM, error_texture); + + texture_data->page_table_cpu = + dma_alloc_coherent(texture_data->doom_data->pci_device, + pages_needed * 4, &texture_data->page_table_dev, + GFP_KERNEL); + ORFAIL_NULL(texture_data->page_table_cpu, -ENOMEM, error_pt); + + for (i = 0; i < pages_needed; i++) { + texture_data->page_table_cpu[i] = + (HARDDOOM_PTE_PHYS_MASK & + (texture_data->texture_dev + HARDDOOM_PAGE_SIZE * i)) | + HARDDOOM_PTE_VALID; + } + + not_written = copy_from_user(texture_data->texture_cpu, + (void __user *) params->data_ptr, + params->size); + + + if (not_written) { + err = -EFAULT; + goto error_copy; + } + + return 0; + +error_copy: + dma_free_coherent(texture_data->doom_data->pci_device, + texture_data->pages * 4, texture_data->page_table_cpu, + texture_data->page_table_dev); +error_pt: + dma_free_coherent(texture_data->doom_data->pci_device, + texture_data->size, texture_data->texture_cpu, + texture_data->texture_dev); +error_texture: + return err; +} + +void free_texture(struct texture_data *texture_data) +{ + dma_free_coherent(texture_data->doom_data->pci_device, + texture_data->pages * 4, texture_data->page_table_cpu, + texture_data->page_table_dev); + + dma_free_coherent(texture_data->doom_data->pci_device, + texture_data->size, texture_data->texture_cpu, + texture_data->texture_dev); +} + long doom_create_texture(struct file *filp, unsigned long arg) { - return -1; + int err; + struct doomdev_ioctl_create_texture *params; + struct texture_data *texture_data; + int fd; + struct doom_data *doom_data; + + params = (struct doomdev_ioctl_create_texture *) arg; + + err = verify_texture_params(params); + if (err < 0) { + return err; + } + + texture_data = kmalloc(sizeof(*texture_data), GFP_KERNEL); + ORFAIL_NULL(texture_data, -ENOMEM, error_data); + doom_data = container_of(filp->f_inode->i_cdev, struct doom_data, cdev); + texture_data->doom_data = doom_data; + + ORFAIL(alloc_texture(params, texture_data), error_texture); + + fd = anon_inode_getfd("doom_texture", &texture_fops, texture_data, 0); + ORFAIL(fd, error_inode); + + return fd; + +error_inode: + free_texture(texture_data); +error_texture: + kfree(texture_data); +error_data: + return err; } long doom_create_flat(struct file *filp, unsigned long arg) -- cgit v1.2.3