⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kllad.c

📁 1. 8623L平台
💻 C
📖 第 1 页 / 共 5 页
字号:
/*Copyright (C) 2003  Sigma Designs, Inc.This library is free software; you can redistribute it and/ormodify it under the terms of the GNU Lesser General PublicLicense as published by the Free Software Foundation; eitherversion 2.1 of the License, or (at your option) any later version.This library is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNULesser General Public License for more details.You should have received a copy of the GNU Lesser General PublicLicense along with this library; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*/#include <linux/init.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/version.h>#include <linux/fs.h>#include <linux/sched.h>#include <linux/interrupt.h>#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)#include <linux/devfs_fs_kernel.h>#endif#include <asm/io.h>#include <asm/irq.h>#include <asm/uaccess.h>#include <asm/semaphore.h>#define ALLOW_OS_CODE 1#ifdef WITH_PROC#ifdef WITH_MONITORING#include "kllad_proc.h"#endif#endif#define DIRECT_MAJOR 126unsigned long max_dmapool_memory_size = 4*1024*1024;unsigned long max_dmabuffer_log2_size = 17;/* Major number */static int major = DIRECT_MAJOR;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)MODULE_PARM(max_dmapool_memory_size, "i");MODULE_PARM(max_dmabuffer_log2_size, "i");MODULE_PARM(major, "i");#elsemodule_param(max_dmapool_memory_size, ulong, S_IRUGO|S_IWUSR);module_param(max_dmabuffer_log2_size, ulong, S_IRUGO|S_IWUSR);module_param(major, int, S_IRUGO|S_IRUSR);#endifMODULE_PARM_DESC(max_dmapool_memory_size, "Sets the maximum amount of memory shared by the all dmapools");MODULE_PARM_DESC(max_dmabuffer_log2_size, "Sets the dmapool buffers maximum size (ex: set 15 for 32kB)");MODULE_PARM_DESC(major, "Sets the major number");/* the main chip ids */#define EM86XX_CHIPID_MAMBO      1000#define EM86XX_CHIPID_MAMBOLIGHT 2000#define EM86XX_CHIPID_TANGO      3000#define EM86XX_CHIPID_TANGOLIGHT 4000#define EM86XX_CHIPID_TANGO15    4500#define EM86XX_CHIPID_TANGO2     5000#define EM86XX_CHIPID_TANGO3    10000#if (EM86XX_CHIP==EM86XX_CHIPID_TANGO2)#include <asm/tango2/hardware.h>#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)#include <asm/tango2/rmdefs.h>#include <asm/tango2/tango2_gbus.h>#endif#include <linux/mm.h>#ifndef XLAT_G2P // Subject to redefinition in kernel#if (EM86XX_CHIP==EM86XX_CHIPID_TANGO2)#if defined(CONFIG_TANGO2_USE_TLB_REMAP_DRAM1) || defined(CONFIG_TANGOX_USE_TLB_REMAP_DRAM1) // In Tango 2, we need to remap addresses greater than 0x20000000. For this, the kernel is currently // - subject to change - setting the TLB so that @ > 0x20000000 is remapped to em86xx_tlb_dram1_map_base. // Therefore for the kernel point of view GBUS address is equal to PHYSICAL address.#define XLAT_G2P(g) (g)#else// In Tango 2, we need to remap addresses greater than 0x20000000. For this, the kernel is currently // - subject to change - setting the remap register so that @ > 0x20000000 is remapped to // 0x08000000. Therefore @ becomes @ -  0x20000000 + 0x08000000" (== 0x18000000) when @ > 0x20000000.#define XLAT_G2P(g) (((g) >= 0x20000000) ? ((g) - 0x18000000) : (g)) #endif#else#define XLAT_G2P(g) (g)#endif#endif#define REG_BASE_CPU REG_BASE_cpu_block//#include "../../../emhwlib_hal/include/emhwlib_registers.h"#define REG_BASE_HOST 0x20000#define PCI_devcfg_reg0 0xfee8#define PCI_devcfg_reg1 0xfeec#define PCI_devcfg_reg2 0xfef0#define PCI_devcfg_reg3 0xfef4#define SOFTIRQMASK_VALID               0xf010#define IRQ_SOFTINT                     (IRQ_CONTROLLER_IRQ_BASE+0)   // Software interrupt#define IRQ_TIMER1                      (IRQ_CONTROLLER_IRQ_BASE+6)   // Timer 1#define IRQ_MBUS_W1                     (IRQ_CONTROLLER_IRQ_BASE+10)  // Host interface MBUS W1 channel#define IRQ_MBUS_R1                     (IRQ_CONTROLLER_IRQ_BASE+12)  // Host interface MBUS R1 channel#define IRQ_GRAPHICACCEL                (IRQ_CONTROLLER_IRQ_BASE+23)  // Graphic accelerator#define IRQ_VSYNC0                      (IRQ_CONTROLLER_IRQ_BASE+24)  // Vsync 0#define IRQ_VSYNC1                      (IRQ_CONTROLLER_IRQ_BASE+25)  // Vsync 1#define IRQ_VSYNC2                      (IRQ_CONTROLLER_IRQ_BASE+26)  // Vsync 2#define IRQ_VSYNC3                      (IRQ_CONTROLLER_IRQ_BASE+27)  // Vsync 3#if 0unsigned long loop_cnt = 5000;MODULE_PARM(loop_cnt, "i");MODULE_PARM_DESC(loop_cnt, "Sets the loop counter for vsync workaround");#endif/* buffer size for large data transfer transition into kernel */#define GBUS_BUF_SIZE (32 * 1024)static unsigned char gbus_buf[GBUS_BUF_SIZE] __attribute__ ((__aligned__(PAGE_SIZE)));#else  /* (EM86XX_CHIP==EM86XX_CHIPID_TANGO2) */#include <asm/hardware.h>#undef REG_BASE_cpu_block /* avoid redefinition */#define REG_BASE_cpu_block REG_BASE_CPU#endif /* (EM86XX_CHIP==EM86XX_CHIPID_TANGO2) */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)#ifndef __user#define __user#endif#endifstatic struct semaphore gbus_buf_sem;static spinlock_t open_lock;struct llad;struct gbus;#ifndef pGBus#define pGBus ((struct gbus *) 1)#endif#ifndef pLLAD#define pLLAD ((struct llad *) 1)#endif#include "kernelcalls.h"#include "../../include/kdmapool.h"// Update the value in emhwlib/include/emhwlib_resources.h as well#define UCLINUX_LLAD_IRQHANDLER_HANDSHAKE    (REG_BASE_CPU + 0x006C)#define IRQHANDLER_ENTRY                     (REG_BASE_CPU + 0x0070) #define FIQHANDLER_ENTRY                     (REG_BASE_CPU + 0x0074) #define UNDEFHANDLER_ENTRY                   (REG_BASE_CPU + 0x0078) #define JUMPTABLE_ADDRESS                    (REG_BASE_CPU + 0x007c)#define UCLINUX_UNDEF_VECTOR   (REG_BASE_CPU + 0x0048)#define UCLINUX_IRQ_VECTOR     (REG_BASE_CPU + 0x005c)MODULE_DESCRIPTION("llad kernel module for standalone configuration");MODULE_AUTHOR("Mambo standalone team");MODULE_LICENSE("LGPL");#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)static inline int ctu(void __user *x, void *y, unsigned long z) { 	if (!access_ok(VERIFY_WRITE, x, z))		return -EFAULT;	memcpy(x,y,z); 	return 0; }static inline int cfu(void *x, void __user *y, unsigned long z) { 	if (!access_ok(VERIFY_READ, y, z))		return -EFAULT;	memcpy(x,y,z); 	return 0;}#elsestatic inline int ctu(void __user *x, void *y, unsigned long z) { 	int rc;	if ((rc=copy_to_user(x,y,z))!=0)		printk("copy_to_user %p %p %ld failed\n",x,y,z);	return rc;}static inline int cfu(void *x, void __user *y, unsigned long z) { 	int rc;	if ((rc=copy_from_user(x,y,z))!=0)		printk("copy_from_user %p %p %ld failed\n",x,y,z);	return rc;}#endifunsigned long long kc_longlongdiv(unsigned long long a, unsigned long long b);// For long long division// Otherwise We can not link _udivdi3 from libgcc.a due to a pic and non-pic problem.EXPORT_SYMBOL(kc_longlongdiv);unsigned long long kc_longlongdiv(unsigned long long a, unsigned long long b){        unsigned long long remainder = 0, quotient = 0;        unsigned long r32,d,b_low;        int i;        unsigned char nbits = sizeof(unsigned long long)*8;                                                                                                                                                                        if ( ((b >> 32 ) == 0) && ( (a >> 32 ) == 0) )                /* Simplest Case, 32 bits division */                return (unsigned long long)( (unsigned long) a / (unsigned long) b );                                                                                                                                                                        if ( (b >> 28) == 0){                /* Divisor is less than 28bit length */                b_low = (unsigned long)b;                d = a >> 32;                quotient = (d / b_low);                r32 = d % b_low;                                                                                                                                                                                for (i = 0; i < 8; i++) {                        d = (r32 << 4) | ((a >> (7-i)*4) & 0xf);                        quotient = (quotient << 4) | (d / b_low);                        r32 = d % b_low;                }                return quotient;        }                                                                                                                                                                        /* Skip first zeros */        quotient = ( (unsigned long long) 1 << ( nbits-1 ) );        while( quotient && ((a & quotient) == 0) ){                nbits--;                quotient = quotient >> 1;        }                                                                                                                                                                        /* Compute, simple 2-radix */        quotient = 0;        for ( i = (nbits-1) ; i >=0 ; i--){                remainder = remainder << 1 | (( a >> i ) & 1);                quotient = quotient << 1 ;                if ( remainder >= b ){                        remainder = remainder - b;                        quotient |=  1 ;                }        }        return quotient;}/** US_TO_JIFFIES abstraction * Microseconds are converted in jiffies. * 1 jiffie = 1000000/HZ us, where HZ = number of PC real timer interrupts per second. * If u < 1000000/HZ => 0 jiffies * Conversion is done using 64bit mult&div => maximum timeout is 71 min. * Usually HZ=100 => 1 jiffie = 10 ms. For HZ=512 => 1 jiffie = 1953.125 us */EXPORT_SYMBOL(US_TO_JIFFIES);unsigned long US_TO_JIFFIES(unsigned long u){ 	return (unsigned long)( kc_longlongdiv((unsigned long long)u * (unsigned long long)HZ, (unsigned long long)1000000) ); }//static unsigned long JIFFIES_TO_US(unsigned long j){ return j*(unsigned long)1000000/HZ; };EXPORT_SYMBOL(JIFFIES_TO_US);unsigned long JIFFIES_TO_US(unsigned long j){ 	return (unsigned long)( kc_longlongdiv((unsigned long long)j * (unsigned long long)1000000, (unsigned long long)HZ) ); }/******************* USEFUL FUNCTION TO ACCESS MAMBO REGISTER *********************/void llad_get_config(struct llad *pllad, char *config, unsigned long size);struct llad *llad_open(char *dev);void llad_close(struct llad *pllad);struct gbus *gbus_open(struct llad *pllad);void gbus_close(struct gbus *PGBUS);EXPORT_SYMBOL(llad_open);struct llad *llad_open(char *dev){	if (*dev == '0')		return pLLAD;	else		return (struct llad *) NULL;}EXPORT_SYMBOL(llad_close);void llad_close(struct llad *pllad){}EXPORT_SYMBOL(gbus_open);struct gbus *gbus_open(struct llad *pllad){	if (pllad != NULL)		return pGBus;        return NULL;}EXPORT_SYMBOL(gbus_close);void gbus_close(struct gbus *PGBUS){}#if (EM86XX_CHIP!=EM86XX_CHIPID_TANGO2) #define RMuint32 unsigned longstatic inline void gbus_write_uint32(struct gbus *h, unsigned long byte_address, unsigned long data){	*((volatile unsigned long *) byte_address) = data;}static inline unsigned long gbus_read_uint32(struct gbus *h, unsigned long byte_address){	return *((volatile unsigned long *) byte_address);}#define gbus_save_flags_clf(x)          \        {                               \                unsigned long tmp;           \                __asm__(                \                "mrs    %0, cpsr\n"     \                "orr    %1, %0, #64\n"  \                "msr    cpsr_c, %1\n"   \                : "=r" (x), "=r" (tmp)  \                :                       \                : "memory");            \        }/*  * Restore the saved value back to CPSR register. */#define gbus_restore_flags(x)           \        __asm__(                        \        "msr    cpsr_c, %0\n"           \        :                               \        : "r" (x))#else#define RMPanic(x)#include "../../../init_4ke/helpers_4ke_mipsel.h"#define RMuint8 unsigned char#define RMuint16 unsigned short#define RMmin(x,y) (((x) < (y)) ? (x) : (y))/* gbus_read_uint* and gbus_write_uint* functions are defined in Linux  * header file include/linux/config.h for TANGO2 */static inline void gbus_read_data8 (struct gbus *h, RMuint32 byte_address, RMuint8  *data, RMuint32 count){	RMuint32 i;	for (i=0 ; i<count ; i++) {		*(data+i) = gbus_read_uint8(h, byte_address + i);	}}static inline void gbus_read_data16(struct gbus *h, RMuint32 byte_address, RMuint16 *data, RMuint32 count){	RMuint32 i;	for (i=0 ; i<count ; i++) {		*(data+i) = gbus_read_uint16(h, byte_address + 2*i);	}}static inline void gbus_read_data32(struct gbus *h, RMuint32 byte_address, RMuint32 *data, RMuint32 count){	RMuint32 i;	for (i=0 ; i<count ; i++) {		*(data+i) = gbus_read_uint32(h, byte_address + 4*i);	}}static inline void gbus_write_data8 (struct gbus *h, RMuint32 byte_address, const RMuint8  *data, RMuint32 count){	RMuint32 i;	for (i=0 ; i<count ; i++) {		gbus_write_uint8(h, byte_address + i, *(data+i));	}}static inline void gbus_write_data16(struct gbus *h, RMuint32 byte_address, const RMuint16 *data, RMuint32 count){	RMuint32 i;	for (i=0 ; i<count ; i++) {		gbus_write_uint16(h, byte_address + 2*i, *(data+i));	}}static inline void gbus_write_data32(struct gbus *h, RMuint32 byte_address, const RMuint32 *data, RMuint32 count){	RMuint32 i;	for (i=0 ; i<count ; i++) {		gbus_write_uint32(h, byte_address + 4*i, *(data+i));	}}#endif/* struct llad; *//* #define pGBus ((struct gbus *) 1) *//* #define pLLAD ((struct llad *) 1) *//* struct llad *llad_open(char *dev); *//* void llad_close(struct llad *pllad); *//* void llad_get_config(struct llad *pllad, char *config, unsigned long size); *//* struct gbus *gbus_open(struct llad *pllad); *//* void gbus_close(struct gbus *PGBUS); *//* EXPORT_SYMBOL(llad_open); *//* struct llad *llad_open(char *dev) *//* { *//*         if (*dev == '0') *//*                 return pLLAD; *//*         else *//*                 return (struct llad *) NULL; *//* } *//* EXPORT_SYMBOL(llad_close); *//* void llad_close(struct llad *pllad) *//* { *//* } *//* EXPORT_SYMBOL(gbus_open); */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -