📄 kllad.c
字号:
/* struct gbus *gbus_open(struct llad *pllad) *//* { *//* if (pllad != NULL) *//* return pGBus; *//* } *//* EXPORT_SYMBOL(gbus_close); *//* void gbus_close(struct gbus *PGBUS) *//* { *//* } */#if (EM86XX_CHIP==EM86XX_CHIPID_TANGO2)static inline void gbus_mutex_lock(struct gbus *PGBUS, unsigned long mutex){ while (gbus_read_uint32(PGBUS, mutex));}#elsestatic inline void gbus_mutex_lock(struct gbus *PGBUS, unsigned long mutex){ unsigned long flags; while (1) { gbus_save_flags_clf(flags); if (gbus_read_uint32(PGBUS, mutex) == 0) { gbus_restore_flags(flags); break; } gbus_restore_flags(flags); }}#endifstatic inline void gbus_mutex_unlock(struct gbus *PGBUS, unsigned long mutex){ gbus_write_uint32(PGBUS, (unsigned long) mutex, 0);}EXPORT_SYMBOL(llad_get_config);void llad_get_config(struct llad *pllad, char *config, unsigned long size){ // accessing PCI device configuration `from inside' unsigned short vendor; unsigned short device; unsigned char revisionid; unsigned short subsystem_vendor; unsigned short subsystem_device; unsigned short pci_bus_id; unsigned int pci_class; vendor=gbus_read_uint32(pGBus,REG_BASE_HOST+PCI_devcfg_reg0)>>16; device=gbus_read_uint32(pGBus,REG_BASE_HOST+PCI_devcfg_reg0)&0xffff; revisionid=gbus_read_uint32(pGBus,REG_BASE_HOST+PCI_devcfg_reg1)&0xff; pci_class=gbus_read_uint32(pGBus,REG_BASE_HOST+PCI_devcfg_reg1)>>8; subsystem_vendor=gbus_read_uint32(pGBus,REG_BASE_HOST+PCI_devcfg_reg2)>>16; subsystem_device=gbus_read_uint32(pGBus,REG_BASE_HOST+PCI_devcfg_reg2)&0xffff; pci_bus_id=0; snprintf(config, size, "%02x:%02x.%01x %06x %04x:%04x %04x:%04x %02x", (pci_bus_id >> 8) & 0x00ff, (pci_bus_id >> 3) & 0x001f, pci_bus_id & 0x0007, pci_class, vendor, device, subsystem_vendor, subsystem_device, revisionid);}/********************* TO BE SYNCHRONIZED WITH emhwlib ****************************/#define CPU_RESET_jump 0x0020 #define CPU_undef_vec 0x0004 #define CPU_irq_vec 0x0018 #define DMEM_BASE_demux_engine 0x00150000#define DMEM_BASE_audio_engine_0 0x00190000#define DMEM_BASE_audio_engine_1 0x001b0000#define audio_mutex7 0x3e97 #define SOFT_IRQ_ORIGIN_PT110 0x10#define PCI_INTERRUPT_ENABLE 0x617f4#define HOST_INTERRUPT_STATUS 0x617f8#define LOG2_LLAD_WAIT_WRITE_COMPLETE 1#define LOG2_LLAD_SOFT_INTERRUPT 4#define EM86XX_MODEID_WITHHOST 1000#define EM86XX_MODEID_STANDALONE 2000#if ((EM86XX_CHIP==EM86XX_CHIPID_MAMBOLIGHT) || (EM86XX_CHIP==EM86XX_CHIPID_MAMBO))#define DMEM_BASE_audio_engine_1 0x001b0000#define DMEM_BASE_demux_engine 0x00150000#define audio_mutex3 0x3e93#define audio_mutex7 0x3e97 #define demux_mutex1 0x1e91 #define SOFT_IRQ_MUTEX_IRQ (DMEM_BASE_audio_engine_1 + 4 * audio_mutex7)#define SOFT_IRQ_MUTEX_FIQ (DMEM_BASE_demux_engine + 4 * demux_mutex1)#define PCI_IRQ_MUTEX (DMEM_BASE_audio_engine_1 + 4 * audio_mutex3)#elif ((EM86XX_CHIP==EM86XX_CHIPID_TANGO) || (EM86XX_CHIP==EM86XX_CHIPID_TANGOLIGHT) || (EM86XX_CHIP==EM86XX_CHIPID_TANGO15) || (EM86XX_CHIP==EM86XX_CHIPID_TANGO2))#define REG_BASE_host_interface 0x00020000#define host_mutex7 0x905c#define host_mutex8 0x9060#define host_mutex3 0x904c#define SOFT_IRQ_MUTEX_IRQ (REG_BASE_host_interface + host_mutex7)#define SOFT_IRQ_MUTEX_FIQ (REG_BASE_host_interface + host_mutex8)#define PCI_IRQ_MUTEX (REG_BASE_host_interface + host_mutex3)#if (EM86XX_CHIP!=EM86XX_CHIPID_TANGO2)#define demux_mutex1 0x1e91 /* For Tango2, it's been defined in emhwlib_registers_tango2.h */#endif#else#error EM86XX_CHIP is not set in RMCFLAGS: refer to emhwlib/include/emhwlib_chips.h.#endif#if (EM86XX_CHIP<EM86XX_CHIPID_TANGO2) && defined WITH_IRQHANDLER_BOOTLOADERstatic void clean_data_cache(void){ __asm("MCR p15, 0, r0, c7, c10, 0"); // drains write buffer __asm("LDR r3, =0"); // reset vector __asm("SWP r2, r0, [r3]"); // r2 = [r3], [r3] = r0 __asm("SWP r0, r2, [r3]"); // r0 = [r3], [r3] = r2}static void flush_instr_cache(void) { __asm("MCR p15, 0, r0, c7, c5, 0");}static RMuint32 install_handler(struct gbus *pgbus, RMuint32 handler, RMuint32 vector_index, RMuint32 *old_vector){ RMuint32 old_handler, old_vec; RMuint32 cpu_remap; RMuint32 vector; cpu_remap = gbus_read_uint32(pgbus, REG_BASE_cpu_block + CPU_remap); if (cpu_remap == REG_BASE_cpu_block) return 0; old_vec = gbus_read_uint32(pgbus, cpu_remap + vector_index); if ((old_vec & 0xfffff000) == 0xe59ff000) { RMuint32 location = (old_vec & 0x00000fff) + vector_index + 0x8; old_handler = gbus_read_uint32(pgbus, cpu_remap + location); } else if ((old_vec & 0xff000000) == 0xea000000) old_handler = ((old_vec & 0x00ffffff) << 2) + vector_index + 0x8; else return 0; *old_vector = old_vec; /* stores the new handler address in local RAM (jump table) */ gbus_write_uint32(pgbus, REG_BASE_cpu_block + CPU_RESET_jump + vector_index, handler); /* creates the instruction to execute new handler and stores it in local RAM vector */ vector = CPU_RESET_jump - 8; vector |= 0xe59ff000; gbus_write_uint32(pgbus, REG_BASE_cpu_block + vector_index, vector); /* creates the new vector and install it */ vector = REG_BASE_cpu_block - 8; /* branch to the vector in local RAM */ vector >>= 2; vector |= 0xea000000; gbus_write_uint32(pgbus, cpu_remap + vector_index, vector); return old_handler;}static void overload_IRQHandler(struct gbus *pgbus, RMuint32 handler, RMuint32 jump_table){ RMuint32 irq_set; RMuint32 old_handler, old_vector; irq_set = gbus_read_uint32(pgbus, REG_BASE_cpu_block + CPU_irq_enableset); gbus_write_uint32(pgbus, REG_BASE_cpu_block + CPU_irq_enableclr, 0xffffffff); old_handler = install_handler(pgbus, handler, CPU_irq_vec, &old_vector); if (old_handler) { gbus_write_uint32(pgbus, jump_table + CPU_irq_vec, old_handler); gbus_write_uint32(pgbus, UCLINUX_IRQ_VECTOR, old_vector); } else gbus_write_uint32(pgbus, REG_BASE_cpu_block + CPU_irq_vec, 0xdeadbeef); clean_data_cache(); flush_instr_cache(); gbus_write_uint32(pgbus, REG_BASE_cpu_block + CPU_irq_enableset, irq_set);}static void overload_UNDEFHandler(struct gbus *pgbus, RMuint32 handler, RMuint32 jump_table){ RMuint32 old_handler, old_vector; old_handler = install_handler(pgbus, handler, CPU_undef_vec, &old_vector); if (old_handler) { gbus_write_uint32(pgbus, jump_table + CPU_undef_vec, old_handler); gbus_write_uint32(pgbus, UCLINUX_UNDEF_VECTOR, old_vector); } else gbus_write_uint32(pgbus, REG_BASE_cpu_block + CPU_undef_vec, 0xdeadbeef); clean_data_cache(); flush_instr_cache();}static void restore_IRQHandler(struct gbus *pgbus){ RMuint32 irq_set; RMuint32 old_vector; irq_set = gbus_read_uint32(pgbus, REG_BASE_cpu_block + CPU_irq_enableset); gbus_write_uint32(pgbus, REG_BASE_cpu_block + CPU_irq_enableclr, 0xffffffff); old_vector = gbus_read_uint32(pgbus, UCLINUX_IRQ_VECTOR); gbus_write_uint32(pgbus, CPU_irq_vec, old_vector); clean_data_cache(); flush_instr_cache(); gbus_write_uint32(pgbus, REG_BASE_cpu_block + CPU_irq_enableset, irq_set);} static void restore_UNDEFHandler(struct gbus *pgbus){ RMuint32 old_vector; old_vector = gbus_read_uint32(pgbus, UCLINUX_UNDEF_VECTOR); gbus_write_uint32(pgbus, CPU_undef_vec, old_vector); clean_data_cache(); flush_instr_cache();}#endif/*************** TO BE SYNCHRONIZED WITH ../include/direct_kk.h" ******************/struct kc_tasklet_struct;void mumk_register_tasklet(struct gbus *PGBUS, struct kc_tasklet_struct *tasklet, unsigned long *irq_status, unsigned long mask);void mumk_unregister_tasklet(struct gbus *PGBUS, struct kc_tasklet_struct *kctasklet);int mumk_dmapool_release(struct gbus *PGBUS, unsigned long dmapool_id, unsigned long bus_address);/*************** TO BE SYNCHRONIZED WITH ../include/direct_uk.h" ******************/#define DIRECT_IOCTL_WAIT 2#define DIRECT_IOCTL_ENABLE_INTERRUPT 3#define DIRECT_IOCTL_DISABLE_INTERRUPT 4#define DIRECT_IOCTL_LLAD_GET_CONFIG 10#define DIRECT_IOCTL_LLAD_GET_OPEN_COUNT 11#define DIRECT_IOCTL_DMAPOOL_OPEN 33#define DIRECT_IOCTL_DMAPOOL_CLOSE 34#define DIRECT_IOCTL_DMAPOOL_RESET 42#define DIRECT_IOCTL_DMAPOOL_GET_BUFFER 36#define DIRECT_IOCTL_DMAPOOL_GET_PHYSICAL_ADDRESS 37#define DIRECT_IOCTL_DMAPOOL_GET_VIRTUAL_ADDRESS 35#define DIRECT_IOCTL_DMAPOOL_ACQUIRE 38#define DIRECT_IOCTL_DMAPOOL_RELEASE 39#define DIRECT_IOCTL_DMAPOOL_FLUSH_CACHE 40#define DIRECT_IOCTL_DMAPOOL_INVALIDATE_CACHE 41#define DIRECT_IOCTL_DMAPOOL_GET_AVAILABLE_BUFFER_COUNT 43#if (EM86XX_CHIP==EM86XX_CHIPID_TANGO2)#define DIRECT_IOCTL_GBUS_READ_UINT8 50#define DIRECT_IOCTL_GBUS_READ_UINT16 51#define DIRECT_IOCTL_GBUS_READ_UINT32 52#define DIRECT_IOCTL_GBUS_READ_DATA8 53#define DIRECT_IOCTL_GBUS_READ_DATA16 54#define DIRECT_IOCTL_GBUS_READ_DATA32 55#define DIRECT_IOCTL_GBUS_WRITE_UINT8 56#define DIRECT_IOCTL_GBUS_WRITE_UINT16 57#define DIRECT_IOCTL_GBUS_WRITE_UINT32 58#define DIRECT_IOCTL_GBUS_WRITE_DATA8 59#define DIRECT_IOCTL_GBUS_WRITE_DATA16 60#define DIRECT_IOCTL_GBUS_WRITE_DATA32 61#define DIRECT_IOCTL_GBUS_LOCK_AREA 70#define DIRECT_IOCTL_GBUS_GET_LOCKED_AREA 71#define DIRECT_IOCTL_GBUS_UNLOCK_REGION 72#define DIRECT_IOCTL_GBUS_GET_REGIONS_INFO 73#define DIRECT_IOCTL_GBUS_MMAP_REGION 74#define DIRECT_IOCTL_GBUS_GET_SYSTEM_PAGE_COUNT 75struct gbus_uint8 { unsigned long byte_address; unsigned char data;};struct gbus_uint16 { unsigned long byte_address; unsigned short data;};struct gbus_uint32 { unsigned long byte_address; unsigned long data;};struct gbus_data8 { unsigned long byte_address; unsigned char __user *data; unsigned long count;};struct gbus_data16 { unsigned long byte_address; unsigned short __user *data; unsigned long count;};struct gbus_data32 { unsigned long byte_address; unsigned long __user *data; unsigned long count;};struct gbus_regions_info { unsigned long region_count; unsigned long region_size;};struct gbus_lock_area { unsigned long byte_address; unsigned long size; unsigned long offset; unsigned long region_index; unsigned long region_count;};struct gbus_region_count { unsigned long region_index; unsigned long region_count;};#define KERNEL_PAGE_SIZE (1<<PAGE_SHIFT)#define DIRECT_REGION_SIZE (2*1024*1024)#define DIRECT_REGION_COUNT 512#define DIRECT_DUMMY_REGION_MAP_ADDRESS 0x200000#endif // EM86XX_CHIPstruct waitable { unsigned long timeout_microsecond; // no way to specify ``infinite'', sorry. unsigned long mask;}; struct llad_get_config { char *ConfigName; unsigned long ConfigNameSize;};struct kdmapool_dimension { unsigned long area; unsigned long buffercount; unsigned long buffersize; unsigned long dmapool_id;};struct kdmapool_getbuffer { unsigned long dmapool_id; unsigned char *ptr; unsigned long timeout_microsecond;};struct kdmapool_userbuffer { unsigned long dmapool_id; unsigned char *ptr; unsigned long size; unsigned long physical_address;};struct kdmapool_buffercount { unsigned long dmapool_id; unsigned long buffer_count;};struct kdmapool_physbuffer { unsigned long dmapool_id; unsigned long physical_address;};struct kdmapool_reset { unsigned long dmapool_id; unsigned long acquired_count;};struct region_info_struct { unsigned long region_count; unsigned long map_refcount; unsigned long direct_map; unsigned long area_offset; unsigned long area_size; unsigned long area_byte_address; }; #define DIRECT_DEVICE_NAME "mum0"#define LLAD_WAIT_WRITE_COMPLETE (1<<LOG2_LLAD_WAIT_WRITE_COMPLETE)#define LLAD_SOFT_INTERRUPT (1<<LOG2_LLAD_SOFT_INTERRUPT)#define MAX_OPENERS 8/* Number of supported tasklets */#define MAX_TASKLETS 4#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)#define CURRENT_DIRECT_ID (current->pgrp) #else#define CURRENT_DIRECT_ID (current->signal->pgrp)#endifstruct direct_opener { int direct_id; unsigned long open_count; unsigned dmapool_usage_mask;};static struct { int total_open_count; wait_queue_head_t irq_queue; unsigned long irq_bits;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) devfs_handle_t devfs_handle;#endif struct tasklet_struct *tasklet[MAX_TASKLETS]; unsigned long *tasklet_irq_status[MAX_TASKLETS]; unsigned long tasklet_mask[MAX_TASKLETS]; struct direct_opener openers[MAX_OPENERS];#if (EM86XX_CHIP==EM86XX_CHIPID_TANGO2) struct region_info_struct region_info[DIRECT_REGION_COUNT];#endif // EM86XX_CHIP} R;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -