/* ********************************************************************************************************* * MALLOC BUFFER FROM HEAP * * Description: malloc a buffer from heap. * * Aguments : num_bytes the size of the buffer need malloc; * * Returns : the po__s32er to buffer has malloc. ********************************************************************************************************* */ void *realloc(void *p, __u32 num_bytes) { struct alloc_struct_t *ptr, *prev; void *tmp; __u32 actual_bytes; if(!p) { return malloc(num_bytes); /* 如果传进的指针是空,则按照传进的字节数申请内存 */ } if (!num_bytes) { return p; /* 如果申请追加的内存字节数是0,则直接返回当前的指针 */ } ptr = &boot_heap_head; /* look for the node which po__s32 this memory block */ while (ptr && ptr->next) { if (ptr->next->address == (__u32)p) break; /* find the node which need to be release */ ptr = ptr->next; } //此时,ptr指向的是用户指针的前一个节点 prev = ptr; ptr = ptr->next; if(!ptr) { return 0; /* 如果没有找到用户传进的地址 */ } //用ptr指向用户节点 actual_bytes = MY_BYTE_ALIGN(ptr->o_size + num_bytes); if(actual_bytes == ptr->size) { return p; } if (ptr->next->address >= (ptr->address + actual_bytes + \ 2 * sizeof(struct alloc_struct_t))) { ptr->size = actual_bytes; ptr->o_size += num_bytes; return p; } tmp = malloc(actual_bytes); if(!tmp) { return 0; } memcpy(tmp, (void *)ptr->address, ptr->size); prev->next = ptr->next; /* delete the node which need be released from the memory block chain */ return tmp; }
void sunxi_di_free(void* virt_addr, unsigned long phys_addr, u32 num_bytes) { u32 actual_bytes; actual_bytes = MY_BYTE_ALIGN(num_bytes); if (phys_addr && virt_addr) dma_free_coherent(di_device, actual_bytes, virt_addr, (dma_addr_t)phys_addr); return ; }
void *disp_malloc(__u32 num_bytes) { struct alloc_struct_t *ptr, *newptr; __u32 actual_bytes; if (!num_bytes) { return 0; } actual_bytes = MY_BYTE_ALIGN(num_bytes); /* translate the byte count to size of long type */ ptr = &boot_heap_head; /* scan from the boot_heap_head of the heap */ while (ptr && ptr->next) /* look for enough memory for alloc */ { if (ptr->next->address >= (ptr->address + ptr->size + (8 * 1024) + actual_bytes)) { break; } /* find enough memory to alloc */ ptr = ptr->next; } if (!ptr->next) { __wrn(" it has reached the boot_heap_tail of the heap now\n"); return 0; /* it has reached the boot_heap_tail of the heap now */ } newptr = (struct alloc_struct_t *)(ptr->address + ptr->size); /* create a new node for the memory block */ if (!newptr) { __wrn(" create the node failed, can't manage the block\n"); return 0; /* create the node failed, can't manage the block */ } /* set the memory block chain, insert the node to the chain */ newptr->address = ptr->address + ptr->size + 4*1024; newptr->size = actual_bytes; newptr->o_size = num_bytes; newptr->next = ptr->next; ptr->next = newptr; return (void *)newptr->address; }
/* ********************************************************************************************************* * MALLOC BUFFER FROM HEAP * * Description: malloc a buffer from heap. * * Aguments : num_bytes the size of the buffer need malloc; * * Returns : the po__s32er to buffer has malloc. ********************************************************************************************************* */ void *eGon2_calloc(__u32 size, __u32 num_bytes) { __u32 bytes; void *tmp_ptr; bytes = MY_BYTE_ALIGN(size * num_bytes); /* translate the byte count to size of long type */ if(!bytes) { return 0; } tmp_ptr = eGon2_malloc(bytes); if(!tmp_ptr) { return 0; } memset(tmp_ptr, 0, bytes); return tmp_ptr; }
/* * sunxi-di.c DE-Interlace driver * * Copyright (C) 2013-2015 allwinner. * Ming Li<*****@*****.**> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include <linux/module.h> #include <linux/delay.h> #include <linux/clk.h> #include <linux/ioport.h> #include <linux/interrupt.h> #include <linux/err.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/major.h> #include <linux/poll.h> #include <linux/device.h> #include <linux/uaccess.h> #include <linux/sched.h> #include <linux/platform_device.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/sys_config.h> #include <linux/slab.h> #include <linux/dma-mapping.h> #include <asm/irq.h> #include "sunxi-di.h" static di_struct *di_data; static s32 sunxi_di_major = -1; static struct class *di_dev_class; static struct workqueue_struct *di_wq = NULL; static struct work_struct di_work; static struct timer_list *s_timer; static struct device *di_device = NULL; static struct clk *di_clk; static struct clk *di_clk_source; static u32 debug_mask = 0x0; static ssize_t di_timeout_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { unsigned long data; int error; error = strict_strtoul(buf, 10, &data); if(error) { pr_err("%s strict_strtoul error\n", __FUNCTION__); goto exit; } dprintk(DEBUG_DATA_INFO, "%s data = %ld \n", __func__, data); if(data) { di_data->time_value = data; } else { di_data->time_value = DI_TIMEOUT; } return count; exit: return error; } static DEVICE_ATTR(timeout, 0664, NULL, di_timeout_store); static struct attribute *di_attributes[] = { &dev_attr_timeout.attr, NULL }; static struct attribute_group di_attribute_group = { .attrs = di_attributes }; #ifdef DI_RESERVED_MEM #define MY_BYTE_ALIGN(x) ( ( (x + (4*1024-1)) >> 12) << 12) /* alloc based on 4K byte */ void *sunxi_di_alloc(u32 num_bytes, unsigned long phys_addr) { u32 actual_bytes; void* address = NULL; if (num_bytes != 0) { actual_bytes = MY_BYTE_ALIGN(num_bytes); address = dma_alloc_coherent(di_device, actual_bytes, (dma_addr_t*)phys_addr, GFP_KERNEL); if (address) { printk(KERN_ERR "dma_alloc_coherent ok, address=0x%p, size=0x%x\n", (void*)(*(unsigned long*)phys_addr), num_bytes); return address; } else { printk(KERN_ERR "dma_alloc_coherent fail, size=0x%x\n", num_bytes); return NULL; } } else { printk(KERN_ERR "%s size is zero\n", __func__); } return NULL; }