📄 mga_vid.c
字号:
} card = kmalloc(sizeof(mga_card_t), GFP_KERNEL); if(!card) { printk(KERN_ERR "mga_vid: memory allocation failed\n"); mga_cards_num--; break; } mga_cards[mga_cards_num - 1] = card; switch(dev->device) { case PCI_DEVICE_ID_MATROX_G550: mga_dev_name = "MGA G550"; printk(KERN_INFO "mga_vid: Found %s at %s [%s]\n", mga_dev_name, dev->slot_name, dev->name); cards_init(card, dev, mga_cards_num - 1, 1); break; case PCI_DEVICE_ID_MATROX_G400: mga_dev_name = "MGA G400/G450"; printk(KERN_INFO "mga_vid: Found %s at %s [%s]\n", mga_dev_name, dev->slot_name, dev->name); cards_init(card, dev, mga_cards_num - 1, 1); break; case PCI_DEVICE_ID_MATROX_G200_AGP: mga_dev_name = "MGA G200 AGP"; printk(KERN_INFO "mga_vid: Found %s at %s [%s]\n", mga_dev_name, dev->slot_name, dev->name); cards_init(card, dev, mga_cards_num - 1, 0); break; case PCI_DEVICE_ID_MATROX_G200_PCI: mga_dev_name = "MGA G200"; printk(KERN_INFO "mga_vid: Found %s at %s [%s]\n", mga_dev_name, dev->slot_name, dev->name); cards_init(card, dev, mga_cards_num - 1, 0); break; default: mga_cards_num--; printk(KERN_INFO "mga_vid: ignoring matrox device (%d) at %s [%s]\n", dev->device, dev->slot_name, dev->name); break; } } if(!mga_cards_num) { printk(KERN_ERR "mga_vid: No supported cards found\n"); } else { printk(KERN_INFO "mga_vid: %d supported cards found\n", mga_cards_num); } return mga_cards_num;}static void mga_param_buff_fill( mga_card_t * card ){ unsigned len; unsigned size = card->param_buff_size; char * buf = card->param_buff; len = 0; len += snprintf(&buf[len],size-len,"Interface version: %04X\n",MGA_VID_VERSION); len += snprintf(&buf[len],size-len,"Memory: %x:%dM\n",card->mem_base,(unsigned int) card->ram_size); len += snprintf(&buf[len],size-len,"MMIO: %p\n",card->mmio_base); len += snprintf(&buf[len],size-len,"Configurable stuff:\n"); len += snprintf(&buf[len],size-len,"~~~~~~~~~~~~~~~~~~~\n"); len += snprintf(&buf[len],size-len,PARAM_BRIGHTNESS"%d\n",card->brightness); len += snprintf(&buf[len],size-len,PARAM_CONTRAST"%d\n",card->contrast); len += snprintf(&buf[len],size-len,PARAM_BLACKIE"%s\n",card->regs.blackie?"on":"off"); card->param_buff_len = len; // check boundaries of mga_param_buff before writing to it!!!}static ssize_t mga_vid_read(struct file *file, char *buf, size_t count, loff_t *ppos){ uint32_t size; mga_card_t * card = (mga_card_t *) file->private_data; if(!card->param_buff) return -ESPIPE; if(!(*ppos)) mga_param_buff_fill(card); if(*ppos >= card->param_buff_len) return 0; size = min(count,card->param_buff_len-(uint32_t)(*ppos)); memcpy(buf,card->param_buff,size); *ppos += size; return size;}static ssize_t mga_vid_write(struct file *file, const char *buf, size_t count, loff_t *ppos){ mga_card_t * card = (mga_card_t *) file->private_data; if(memcmp(buf,PARAM_BRIGHTNESS,min(count,strlen(PARAM_BRIGHTNESS))) == 0) { short brightness; brightness=simple_strtol(&buf[strlen(PARAM_BRIGHTNESS)],NULL,10); if (brightness>127 || brightness<-128) { brightness=0;} // printk(KERN_DEBUG "mga_vid: brightness modified ( %d ) \n",brightness); card->brightness=brightness; } else if(memcmp(buf,PARAM_CONTRAST,min(count,strlen(PARAM_CONTRAST))) == 0) { short contrast; contrast=simple_strtol(&buf[strlen(PARAM_CONTRAST)],NULL,10); if (contrast>127 || contrast<-128) { contrast=0;} // printk(KERN_DEBUG "mga_vid: contrast modified ( %d ) \n",contrast); card->contrast=contrast; } else if(memcmp(buf,PARAM_BLACKIE,min(count,strlen(PARAM_BLACKIE))) == 0) { short blackie; blackie=simple_strtol(&buf[strlen(PARAM_BLACKIE)],NULL,10);// printk(KERN_DEBUG "mga_vid: shadow mode: ( %d ) \n",blackie); card->regs.blackie=(blackie>0)?1:0; } else count = -EIO; // TODO: reset settings return count;}static int mga_vid_mmap(struct file *file, struct vm_area_struct *vma){ mga_card_t * card = (mga_card_t *) file->private_data;#ifdef MP_DEBUG printk(KERN_DEBUG "mga_vid: mapping video memory into userspace\n");#endif if(!card->configured) { printk(KERN_ERR "mga_vid: card is not configured, cannot mmap\n"); return(-EAGAIN); } if(remap_page_range(vma->vm_start, card->mem_base + card->src_base, vma->vm_end - vma->vm_start, vma->vm_page_prot)) { printk(KERN_ERR "mga_vid: error mapping video memory\n"); return(-EAGAIN); } return(0);}static int mga_vid_release(struct inode *inode, struct file *file){ mga_card_t * card; //Close the window just in case#ifdef MP_DEBUG printk(KERN_DEBUG "mga_vid: Video OFF (release)\n");#endif card = (mga_card_t *) file->private_data; card->vid_src_ready = 0; card->regs.besctl &= ~1; card->regs.besglobctl &= ~(1<<6); // UYVY format selected// card->config.colkey_on=0; //!!! mga_vid_write_regs(card, 1); card->vid_in_use = 0; MOD_DEC_USE_COUNT; return 0;}static long long mga_vid_lseek(struct file *file, long long offset, int origin){ return -ESPIPE;} static int mga_vid_open(struct inode *inode, struct file *file){ mga_card_t * card; int minor = MINOR(inode->i_rdev); if(!file->private_data) { // we are not using devfs, use the minor // number to specify the card we are using // we don't have that many cards if(minor >= mga_cards_num) return(-ENXIO); file->private_data = mga_cards[minor];#ifdef MP_DEBUG printk(KERN_DEBUG "mga_vid: Not using devfs\n");#endif }#ifdef MP_DEBUG else { printk(KERN_DEBUG "mga_vid: Using devfs\n"); }#endif card = (mga_card_t *) file->private_data; if(card->vid_in_use == 1) return(-EBUSY); card->vid_in_use = 1; MOD_INC_USE_COUNT; return(0);}#if LINUX_VERSION_CODE >= 0x020400static struct file_operations mga_vid_fops ={ llseek: mga_vid_lseek, read: mga_vid_read, write: mga_vid_write, ioctl: mga_vid_ioctl, mmap: mga_vid_mmap, open: mga_vid_open, release: mga_vid_release};#elsestatic struct file_operations mga_vid_fops ={ mga_vid_lseek, mga_vid_read, mga_vid_write, NULL, NULL, mga_vid_ioctl, mga_vid_mmap, mga_vid_open, NULL, mga_vid_release};#endifstatic void cards_init(mga_card_t * card, struct pci_dev * dev, int card_number, int is_g400){ unsigned int card_option;// temp buffer for device filename creation used only by devfs#ifdef CONFIG_DEVFS_FS char buffer[16];#endif memset(card,0,sizeof(mga_card_t)); card->irq = -1; card->pci_dev = dev; card->irq = dev->irq; card->is_g400 = is_g400; card->param_buff = kmalloc(PARAM_BUFF_SIZE,GFP_KERNEL); if(card->param_buff) card->param_buff_size = PARAM_BUFF_SIZE; card->brightness = mga_brightness[card_number]; card->contrast = mga_contrast[card_number]; card->top_reserved = mga_top_reserved[card_number]; #if LINUX_VERSION_CODE >= 0x020300 card->mmio_base = ioremap_nocache(dev->resource[1].start,0x4000); card->mem_base = dev->resource[0].start;#else card->mmio_base = ioremap_nocache(dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK,0x4000); card->mem_base = dev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;#endif printk(KERN_INFO "mga_vid: MMIO at 0x%p IRQ: %d framebuffer: 0x%08X\n", card->mmio_base, card->irq, card->mem_base); pci_read_config_dword(dev, 0x40, &card_option); printk(KERN_INFO "mga_vid: OPTION word: 0x%08X mem: 0x%02X %s\n", card_option, (card_option>>10)&0x17, ((card_option>>14)&1)?"SGRAM":"SDRAM"); if (mga_ram_size[card_number]) { printk(KERN_INFO "mga_vid: RAMSIZE forced to %d MB\n", mga_ram_size[card_number]); card->ram_size=mga_ram_size[card_number]; } else {#ifdef MGA_MEMORY_SIZE card->ram_size = MGA_MEMORY_SIZE; printk(KERN_INFO "mga_vid: hard-coded RAMSIZE is %d MB\n", (unsigned int) card->ram_size);#else if (card->is_g400){ switch((card_option>>10)&0x17){ // SDRAM: case 0x00: case 0x04: card->ram_size = 16; break; case 0x03: case 0x05: card->ram_size = 32; break; // SGRAM: case 0x10: case 0x14: card->ram_size = 32; break; case 0x11: case 0x12: card->ram_size = 16; break; default: card->ram_size = 16; printk(KERN_INFO "mga_vid: Couldn't detect RAMSIZE, assuming 16MB!"); } /* Check for buggy 16MB cards reporting 32 MB */ if(card->ram_size != 16 && (dev->subsystem_device == PCI_SUBSYSTEM_ID_MATROX_G400_16MB_SDRAM || dev->subsystem_device == PCI_SUBSYSTEM_ID_MATROX_G400_16MB_SGRAM || dev->subsystem_device == PCI_SUBSYSTEM_ID_MATROX_G400_DH_16MB)) { printk(KERN_INFO "mga_vid: Detected 16MB card reporting %d MB RAMSIZE, overriding\n", card->ram_size); card->ram_size = 16; } }else{ switch((card_option>>10)&0x17){// case 0x10:// case 0x13: card->ram_size = 8; break; default: card->ram_size = 8; } } #if 0// printk("List resources -----------\n"); for(temp=0;temp<DEVICE_COUNT_RESOURCE;temp++){ struct resource *res=&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>card->ram_size && size<=64) card->ram_size=size; } } }#endif printk(KERN_INFO "mga_vid: detected RAMSIZE is %d MB\n", (unsigned int) card->ram_size);#endif }#ifdef MGA_ALLOW_IRQ if ( card->irq != -1 ) { int tmp = request_irq(card->irq, mga_handle_irq, SA_INTERRUPT | SA_SHIRQ, "Syncfb Time Base", card); if ( tmp ) { printk(KERN_INFO "syncfb (mga): cannot register irq %d (Err: %d)\n", card->irq, tmp); card->irq=-1; } else { printk(KERN_DEBUG "syncfb (mga): registered irq %d\n", card->irq); } } else { printk(KERN_INFO "syncfb (mga): No valid irq was found\n"); card->irq=-1; }#else printk(KERN_INFO "syncfb (mga): IRQ disabled in mga_vid.c\n"); card->irq=-1;#endif // register devfs, let the kernel give us major and minor numbers#ifdef CONFIG_DEVFS_FS snprintf(buffer, 16, "mga_vid%d", card_number); card->dev_handle = devfs_register(NULL, buffer, DEVFS_FL_AUTO_DEVNUM, 0, 0, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IFCHR, &mga_vid_fops, card);#endif}/* * Main Initialization Function */static int mga_vid_initialize(void){ int i;// printk(KERN_INFO "Matrox MGA G200/G400 YUV Video interface v0.01 (c) Aaron Holtzman \n"); printk(KERN_INFO "Matrox MGA G200/G400/G450/G550 YUV Video interface v2.01 (c) Aaron Holtzman & A'rpi\n"); for(i = 0; i < MGA_MAX_CARDS; i++) { if (mga_ram_size[i]) { if (mga_ram_size[i]<4 || mga_ram_size[i]>64) { printk(KERN_ERR "mga_vid: invalid RAMSIZE: %d MB\n", mga_ram_size[i]); return -EINVAL; } } } if(register_chrdev(major, "mga_vid", &mga_vid_fops)) { printk(KERN_ERR "mga_vid: unable to get major: %d\n", major); return -EIO; } if (!mga_vid_find_card()) { printk(KERN_ERR "mga_vid: no supported devices found\n"); unregister_chrdev(major, "mga_vid"); return -EINVAL; }#ifdef CONFIG_DEVFS_FS else { // we assume that this always succeedes dev_handle = devfs_register(NULL, "mga_vid", DEVFS_FL_AUTO_DEVNUM, 0,0, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IFCHR, &mga_vid_fops, mga_cards[0]); }#endif return(0);}int init_module(void){ return mga_vid_initialize();}void cleanup_module(void){ int i; mga_card_t * card; for (i = 0; i < MGA_MAX_CARDS; i++) { card = mga_cards[i]; if(card) {#ifdef MGA_ALLOW_IRQ if (card->irq != -1) free_irq(card->irq, &(card->irq));#endif if(card->mmio_base) iounmap(card->mmio_base); if(card->param_buff) kfree(card->param_buff);#ifdef CONFIG_DEVFS_FS if(card->dev_handle) devfs_unregister(card->dev_handle);#endif kfree(card); mga_cards[i]=NULL; } } //FIXME turn off BES printk(KERN_INFO "mga_vid: Cleaning up module\n");#ifdef CONFIG_DEVFS_FS if(dev_handle) devfs_unregister(dev_handle);#endif unregister_chrdev(major, "mga_vid");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -