tdfx_vid.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,029 行 · 第 1/2 页
C
1,029 行
#include <linux/config.h>#include <linux/version.h>#include <linux/module.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/mm.h>#include "mplaylib.h"#include <linux/errno.h>#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10)#include <linux/malloc.h>#else#include <linux/slab.h>#endif#include <linux/pci.h>#include <linux/ioport.h>#include <linux/init.h>#include <linux/agp_backend.h>#include <asm/uaccess.h>#include <asm/system.h>#include <asm/io.h>#include "tdfx_vid.h"#include "3dfx.h"#define TDFX_VID_MAJOR 178MODULE_AUTHOR("Albeu");MODULE_DESCRIPTION("A driver for Banshee targeted for video app");#ifdef MODULE_LICENSEMODULE_LICENSE("GPL");#endif#ifndef min#define min(x,y) (((x)<(y))?(x):(y))#endifstatic struct pci_dev *pci_dev;static uint8_t *tdfx_mmio_base = 0;static uint32_t tdfx_mem_base = 0;static uint32_t tdfx_io_base = 0;static int tdfx_ram_size = 0;static int tdfx_vid_in_use = 0;static drm_agp_t *drm_agp = NULL;static agp_kern_info agp_info;static agp_memory *agp_mem = NULL;static __initdata int tdfx_map_io = 1;static __initdata unsigned long map_start = 0; //0x7300000;static __initdata unsigned long map_max = (10*1024*1024);MODULE_PARM(tdfx_map_io,"i");MODULE_PARM_DESC(tdfx_map_io, "Set to 0 to use the page fault handler (you need to patch agpgart_be.c to allow the mapping in user space)\n");MODULE_PARM(map_start,"l");MODULE_PARM_DESC(map_start,"Use a block of physical mem instead of the agp arerture.");MODULE_PARM(map_max,"l");MODULE_PARM_DESC(map_max, "Maximum amout of physical memory (in bytes) that can be used\n");static inline u32 tdfx_inl(unsigned int reg) { return readl(tdfx_mmio_base + reg);}static inline void tdfx_outl(unsigned int reg, u32 val) { writel(val,tdfx_mmio_base + reg);}static inline void banshee_make_room(int size) { while((tdfx_inl(STATUS) & 0x1f) < size);} static inline void banshee_wait_idle(void) { int i = 0; banshee_make_room(1); tdfx_outl(COMMAND_3D, COMMAND_3D_NOP); while(1) { i = (tdfx_inl(STATUS) & STATUS_BUSY) ? 0 : i + 1; if(i == 3) break; }}static unsigned long get_lfb_size(void) { u32 draminit0 = 0; u32 draminit1 = 0; // u32 miscinit1 = 0; u32 lfbsize = 0; int sgram_p = 0; draminit0 = tdfx_inl(DRAMINIT0); draminit1 = tdfx_inl(DRAMINIT1); if ((pci_dev->device == PCI_DEVICE_ID_3DFX_BANSHEE) || (pci_dev->device == PCI_DEVICE_ID_3DFX_VOODOO3)) { sgram_p = (draminit1 & DRAMINIT1_MEM_SDRAM) ? 0 : 1; lfbsize = sgram_p ? (((draminit0 & DRAMINIT0_SGRAM_NUM) ? 2 : 1) * ((draminit0 & DRAMINIT0_SGRAM_TYPE) ? 8 : 4) * 1024 * 1024) : 16 * 1024 * 1024; } else { /* Voodoo4/5 */ u32 chips, psize, banks; chips = ((draminit0 & (1 << 26)) == 0) ? 4 : 8; psize = 1 << ((draminit0 & 0x38000000) >> 28); banks = ((draminit0 & (1 << 30)) == 0) ? 2 : 4; lfbsize = chips * psize * banks; lfbsize <<= 20; }#if 0 /* disable block writes for SDRAM (why?) */ miscinit1 = tdfx_inl(MISCINIT1); miscinit1 |= sgram_p ? 0 : MISCINIT1_2DBLOCK_DIS; miscinit1 |= MISCINIT1_CLUT_INV; banshee_make_room(1); tdfx_outl(MISCINIT1, miscinit1);#endif return lfbsize;}static int tdfx_vid_find_card(void){ struct pci_dev *dev = NULL; // unsigned int card_option; if((dev = pci_find_device(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE, NULL))) printk(KERN_INFO "tdfx_vid: Found VOODOO BANSHEE\n"); else if((dev = pci_find_device(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3, NULL))) printk(KERN_INFO "tdfx_vid: Found VOODOO 3 \n"); else return 0; pci_dev = dev;#if LINUX_VERSION_CODE >= 0x020300 tdfx_mmio_base = ioremap_nocache(dev->resource[0].start,1 << 24); tdfx_mem_base = dev->resource[1].start; tdfx_io_base = dev->resource[2].start;#else tdfx_mmio_base = ioremap_nocache(dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK,0x4000); tdfx_mem_base = dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK; tdfx_io_base = dev->base_address[2] & PCI_BASE_ADDRESS_MEM_MASK;#endif printk(KERN_INFO "tdfx_vid: MMIO at 0x%p\n", tdfx_mmio_base); tdfx_ram_size = get_lfb_size(); printk(KERN_INFO "tdfx_vid: Found %d MB (%d bytes) of memory\n", tdfx_ram_size / 1024 / 1024,tdfx_ram_size); #if 0 { int temp; printk("List resources -----------\n"); for(temp=0;temp<DEVICE_COUNT_RESOURCE;temp++){ struct resource *res=&pci_dev->resource[temp]; if(res->flags){ int size=(1+res->end-res->start)>>20; printk(KERN_DEBUG "res %d: start: 0x%X end: 0x%X (%d MB) flags=0x%X\n",temp,res->start,res->end,size,res->flags); if(res->flags&(IORESOURCE_MEM|IORESOURCE_PREFETCH)){ if(size>tdfx_ram_size && size<=64) tdfx_ram_size=size; } } } }#endif return 1;}static int agp_init(void) { drm_agp = (drm_agp_t*)inter_module_get("drm_agp"); if(!drm_agp) { printk(KERN_ERR "tdfx_vid: Unable to get drm_agp pointer\n"); return 0; } if(drm_agp->acquire()) { printk(KERN_ERR "tdfx_vid: Unable to acquire the agp backend\n"); drm_agp = NULL; return 0; } drm_agp->copy_info(&agp_info);#if 0 printk(KERN_DEBUG "AGP Version : %d %d\n" "AGP Mode: %#X\nAperture Base: %p\nAperture Size: %d\n" "Max memory = %d\nCurrent mem = %d\nCan use perture : %s\n" "Page mask = %#X\n", agp_info.version.major,agp_info.version.minor, agp_info.mode,agp_info.aper_base,agp_info.aper_size, agp_info.max_memory,agp_info.current_memory, agp_info.cant_use_aperture ? "no" : "yes", agp_info.page_mask);#endif drm_agp->enable(agp_info.mode); printk(KERN_INFO "AGP Enabled\n"); return 1;} static void agp_close(void) { if(!drm_agp) return; if(agp_mem) { drm_agp->unbind_memory(agp_mem); drm_agp->free_memory(agp_mem); agp_mem = NULL; } drm_agp->release(); inter_module_put("drm_agp");}static int agp_move(tdfx_vid_agp_move_t* m) { u32 src = 0; u32 src_h,src_l; if(!(agp_mem||map_start)) return (-EAGAIN); if(m->move2 > 3) { printk(KERN_DEBUG "tdfx_vid: AGP move invalid destination %d\n", m->move2); return (-EAGAIN); } if(map_start) src = map_start + m->src; else src = agp_info.aper_base + m->src; src_l = (u32)src; src_h = (m->width | (m->src_stride << 14)) & 0x0FFFFFFF; // banshee_wait_idle(); banshee_make_room(6); tdfx_outl(AGPHOSTADDRESSHIGH,src_h); tdfx_outl(AGPHOSTADDRESSLOW,src_l); tdfx_outl(AGPGRAPHICSADDRESS, m->dst); tdfx_outl(AGPGRAPHICSSTRIDE, m->dst_stride); tdfx_outl(AGPREQSIZE,m->src_stride*m->height); tdfx_outl(AGPMOVECMD,m->move2 << 3); banshee_wait_idle(); return 0;}static void setup_fifo(u32 offset,ssize_t pages) { long addr = agp_info.aper_base + offset; u32 size = pages | 0x700; // fifo on, in agp mem, disable hole cnt banshee_wait_idle(); tdfx_outl(CMDBASEADDR0,addr >> 4); tdfx_outl(CMDRDPTRL0, addr << 4); tdfx_outl(CMDRDPTRH0, addr >> 28); tdfx_outl(CMDAMIN0, (addr - 4) & 0xFFFFFF); tdfx_outl(CMDAMAX0, (addr - 4) & 0xFFFFFF); tdfx_outl(CMDFIFODEPTH0, 0); tdfx_outl(CMDHOLECNT0, 0); tdfx_outl(CMDBASESIZE0,size); banshee_wait_idle(); }static int bump_fifo(u16 size) { banshee_wait_idle(); tdfx_outl(CMDBUMP0 , size); banshee_wait_idle(); return 0;}static void tdfx_vid_get_config(tdfx_vid_config_t* cfg) { u32 in; cfg->version = TDFX_VID_VERSION; cfg->ram_size = tdfx_ram_size; in = tdfx_inl(VIDSCREENSIZE); cfg->screen_width = in & 0xFFF; cfg->screen_height = (in >> 12) & 0xFFF; in = (tdfx_inl(VIDPROCCFG)>> 18)& 0x7; switch(in) { case 0: cfg->screen_format = TDFX_VID_FORMAT_BGR8; break; case 1: cfg->screen_format = TDFX_VID_FORMAT_BGR16; break; case 2: cfg->screen_format = TDFX_VID_FORMAT_BGR24; break; case 3: cfg->screen_format = TDFX_VID_FORMAT_BGR32; break; default: printk(KERN_INFO "tdfx_vid: unknown screen format %d\n",in); cfg->screen_format = 0; break; } cfg->screen_stride = tdfx_inl(VIDDESKSTRIDE) & 0x7FFF; cfg->screen_start = tdfx_inl(VIDDESKSTART);}inline static u32 tdfx_vid_make_format(int src,u16 stride,u32 fmt) { u32 r = stride & 0xFFF3; u32 tdfx_fmt = 0; // src and dest formats switch(fmt) { case TDFX_VID_FORMAT_BGR8: tdfx_fmt = 1; break; case TDFX_VID_FORMAT_BGR16: tdfx_fmt = 3; break; case TDFX_VID_FORMAT_BGR24: tdfx_fmt = 4; break; case TDFX_VID_FORMAT_BGR32: tdfx_fmt = 5; break; } if(!src && !tdfx_fmt) { printk(KERN_INFO "tdfx_vid: Invalid destination format %#X\n",fmt); return 0; } if(src && !tdfx_fmt) { // src only format switch(fmt){ case TDFX_VID_FORMAT_BGR1: tdfx_fmt = 0; break; case TDFX_VID_FORMAT_BGR15: // To check tdfx_fmt = 2; break; case TDFX_VID_FORMAT_YUY2: tdfx_fmt = 8; break; case TDFX_VID_FORMAT_UYVY: tdfx_fmt = 9; break; default: printk(KERN_INFO "tdfx_vid: Invalid source format %#X\n",fmt); return 0; } } r |= tdfx_fmt << 16; return r;}static int tdfx_vid_blit(tdfx_vid_blit_t* blit) { u32 src_fmt,dst_fmt,cmd = 2; u32 cmin,cmax,srcbase,srcxy,srcfmt,srcsize; u32 dstbase,dstxy,dstfmt,dstsize = 0; u32 cmd_extra = 0,src_ck[2],dst_ck[2],rop123=0; //printk(KERN_INFO "tdfx_vid: Make src fmt 0x%x\n",blit->src_format); src_fmt = tdfx_vid_make_format(1,blit->src_stride,blit->src_format); if(!src_fmt) return 0; //printk(KERN_INFO "tdfx_vid: Make dst fmt 0x%x\n", blit->dst_format); dst_fmt = tdfx_vid_make_format(0,blit->dst_stride,blit->dst_format); if(!dst_fmt) return 0; blit->colorkey &= 0x3; // Be nice if user just want a simple blit if((!blit->colorkey) && (!blit->rop[0])) blit->rop[0] = TDFX_VID_ROP_COPY; // No stretch : fix me the cmd should be 1 but it // doesn't work. Maybe some other regs need to be set // as non-stretch blit have more options if(((!blit->dst_w) && (!blit->dst_h)) || ((blit->dst_w == blit->src_w) && (blit->dst_h == blit->src_h))) cmd = 2; // Save the regs otherwise fb get crazy // we can perhaps avoid some ... banshee_wait_idle(); cmin = tdfx_inl(CLIP0MIN); cmax = tdfx_inl(CLIP0MAX); srcbase = tdfx_inl(SRCBASE); srcxy = tdfx_inl(SRCXY); srcfmt = tdfx_inl(SRCFORMAT); srcsize = tdfx_inl(SRCSIZE); dstbase = tdfx_inl(DSTBASE); dstxy = tdfx_inl(DSTXY); dstfmt = tdfx_inl(DSTFORMAT); if(cmd == 2) dstsize = tdfx_inl(DSTSIZE); if(blit->colorkey & TDFX_VID_SRC_COLORKEY) { src_ck[0] = tdfx_inl(SRCCOLORKEYMIN); src_ck[1] = tdfx_inl(SRCCOLORKEYMAX); tdfx_outl(SRCCOLORKEYMIN,blit->src_colorkey[0]); tdfx_outl(SRCCOLORKEYMAX,blit->src_colorkey[1]); } if(blit->colorkey & TDFX_VID_DST_COLORKEY) { dst_ck[0] = tdfx_inl(DSTCOLORKEYMIN); dst_ck[1] = tdfx_inl(DSTCOLORKEYMAX); tdfx_outl(SRCCOLORKEYMIN,blit->dst_colorkey[0]); tdfx_outl(SRCCOLORKEYMAX,blit->dst_colorkey[1]); } if(blit->colorkey) { cmd_extra = tdfx_inl(COMMANDEXTRA_2D); rop123 = tdfx_inl(ROP123); tdfx_outl(COMMANDEXTRA_2D, blit->colorkey); tdfx_outl(ROP123,(blit->rop[1] | (blit->rop[2] << 8) | blit->rop[3] << 16)); } // Get rid of the clipping at the moment tdfx_outl(CLIP0MIN,0); tdfx_outl(CLIP0MAX,0x0fff0fff); // Setup the src tdfx_outl(SRCBASE,blit->src & 0x00FFFFFF); tdfx_outl(SRCXY,XYREG(blit->src_x,blit->src_y)); tdfx_outl(SRCFORMAT,src_fmt); tdfx_outl(SRCSIZE,XYREG(blit->src_w,blit->src_h)); // Setup the dst tdfx_outl(DSTBASE,blit->dst & 0x00FFFFFF); tdfx_outl(DSTXY,XYREG(blit->dst_x,blit->dst_y)); tdfx_outl(DSTFORMAT,dst_fmt); if(cmd == 2) tdfx_outl(DSTSIZE,XYREG(blit->dst_w,blit->dst_h)); // Send the command tdfx_outl(COMMAND_2D,cmd | 0x100 | (blit->rop[0] << 24)); banshee_wait_idle(); // Now restore the regs to make fb happy tdfx_outl(CLIP0MIN, cmin); tdfx_outl(CLIP0MAX, cmax); tdfx_outl(SRCBASE, srcbase); tdfx_outl(SRCXY, srcxy); tdfx_outl(SRCFORMAT, srcfmt); tdfx_outl(SRCSIZE, srcsize); tdfx_outl(DSTBASE, dstbase); tdfx_outl(DSTXY, dstxy); tdfx_outl(DSTFORMAT, dstfmt); if(cmd == 2) tdfx_outl(DSTSIZE, dstsize); if(blit->colorkey & TDFX_VID_SRC_COLORKEY) { tdfx_outl(SRCCOLORKEYMIN,src_ck[0]); tdfx_outl(SRCCOLORKEYMAX,src_ck[1]); } if(blit->colorkey & TDFX_VID_DST_COLORKEY) { tdfx_outl(SRCCOLORKEYMIN,dst_ck[0]); tdfx_outl(SRCCOLORKEYMAX,dst_ck[1]); } if(blit->colorkey) { tdfx_outl(COMMANDEXTRA_2D,cmd_extra); tdfx_outl(ROP123,rop123); } return 1;}static int tdfx_vid_set_yuv(unsigned long arg) { tdfx_vid_yuv_t yuv; if(copy_from_user(&yuv,(tdfx_vid_yuv_t*)arg,sizeof(tdfx_vid_yuv_t))) { printk(KERN_DEBUG "tdfx_vid:failed copy from userspace\n"); return(-EFAULT); } banshee_make_room(2); tdfx_outl(YUVBASEADDRESS,yuv.base & 0x01FFFFFF); tdfx_outl(YUVSTRIDE, yuv.stride & 0x3FFF); banshee_wait_idle(); return 0;}static int tdfx_vid_get_yuv(unsigned long arg) { tdfx_vid_yuv_t yuv; yuv.base = tdfx_inl(YUVBASEADDRESS) & 0x01FFFFFF; yuv.stride = tdfx_inl(YUVSTRIDE) & 0x3FFF; if(copy_to_user((tdfx_vid_yuv_t*)arg,&yuv,sizeof(tdfx_vid_yuv_t))) { printk(KERN_INFO "tdfx_vid:failed copy to userspace\n"); return(-EFAULT); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?