sis_main.c
来自「讲述linux的初始化过程」· C语言 代码 · 共 2,375 行 · 第 1/4 页
C
2,375 行
do_set_var(&fb_display[con].var, 1, info); sisfb_set_disp(con, &fb_display[con].var); /* Install new colormap */ do_install_cmap(con, info); cols = sisbios_mode[mode_idx].cols; rows = sisbios_mode[mode_idx].rows; vc_resize_con(rows, cols, fb_display[con].conp->vc_num); sisfb_update_var(con, info); return 1;}/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */static void sisfb_blank(int blank, struct fb_info *info){ u8 CRData; vgawb(CRTC_ADR, 0x17); CRData = vgarb(CRTC_DATA); if (blank > 0) /* turn off CRT1 */ CRData &= 0x7f; else /* turn on CRT1 */ CRData |= 0x80; vgawb(CRTC_ADR, 0x17); vgawb(CRTC_DATA, CRData);}int has_VB(void){ u8 uSR38, uSR39, uVBChipID; vgawb(SEQ_ADR, 0x38); uSR38 = vgarb(SEQ_DATA); vgawb(SEQ_ADR, 0x39); uSR39 = vgarb(SEQ_DATA); vgawb(IND_SIS_CRT2_PORT_14, 0x0); uVBChipID = vgarb(IND_SIS_CRT2_PORT_14+1); if ( ( (HwExt.jChipID == SIS_Glamour) && (uSR38 & 0x20) ) /* 300 */ || ( (HwExt.jChipID >= SIS_Trojan ) && (uSR38 & 0x20) && (!(uSR39 & 0x80)) ) /* 630/540 */ || ( (HwExt.jChipID == SIS_Trojan ) && ((HwExt.revision_id & 0xf0) == 0x30) && (uVBChipID == 1) ) /* 630s */ || ( (HwExt.jChipID == SIS_730) && (uVBChipID == 1) ) /* 730 */ ) { ivideo.hasVB = HASVB_301; return TRUE; } else { ivideo.hasVB = HASVB_NONE; return FALSE; }}void sis_get301info(void){ u8 uCRData; unsigned long disp_state=0; if (HwExt.jChipID >= SIS_Trojan) { if (!has_VB()) { vgawb(CRTC_ADR, 0x37); uCRData = vgarb(CRTC_DATA); switch((uCRData >> 1) & 0x07) { case 2: ivideo.hasVB = HASVB_LVDS; break; case 4: ivideo.hasVB = HASVB_LVDS_CHRONTEL; break; case 3: ivideo.hasVB = HASVB_TRUMPION; break; default: break; } } } else { has_VB(); } vgawb(CRTC_ADR, 0x32); uCRData = vgarb(CRTC_DATA); switch(uDispType) { case MASK_DISPTYPE_CRT2: disp_state = DISPTYPE_CRT2; break; case MASK_DISPTYPE_LCD: disp_state = DISPTYPE_LCD; break; case MASK_DISPTYPE_TV: disp_state = DISPTYPE_TV; break; } if(disp_state & 0x7) { if(crt1off) disp_state |= DISPMODE_SINGLE; else disp_state |= (DISPMODE_MIRROR | DISPTYPE_CRT1); } else disp_state = DISPMODE_SINGLE | DISPTYPE_CRT1; ivideo.disp_state = disp_state;}int __init sisfb_init(void){ struct pci_dev *pdev = NULL; struct board *b; int pdev_valid = 0; unsigned char jTemp; u8 uSRData, uCRData; outb(0x77, 0x80); if (sisfb_off) return -ENXIO; pci_for_each_dev(pdev) { for (b = dev_list; b->vendor; b++) { if ((b->vendor == pdev->vendor) && (b->device == pdev->device)) { pdev_valid = 1; strcpy(fb_info.modename, b->name); ivideo.chip_id = pdev->device; pci_read_config_byte(pdev, PCI_REVISION_ID, &HwExt.revision_id); break; } } if (pdev_valid) break; } if (!pdev_valid) return -1; switch(ivideo.chip_id) { case PCI_DEVICE_ID_SI_300: HwExt.jChipID = SIS_Glamour; break; case PCI_DEVICE_ID_SI_630_VGA: HwExt.jChipID = SIS_Trojan; break; case PCI_DEVICE_ID_SI_540_VGA: HwExt.jChipID = SIS_Spartan; break; case PCI_DEVICE_ID_SI_730_VGA: HwExt.jChipID = SIS_730; break; } ivideo.video_base = pci_resource_start(pdev, 0); ivideo.mmio_base = pci_resource_start(pdev, 1); ivideo.vga_base = pci_resource_start(pdev, 2) + 0x30; HwExt.IOAddress = (unsigned short)ivideo.vga_base; rom_base = 0x000C0000; MMIO_SIZE = pci_resource_len(pdev, 1);#ifdef NOBIOS if (pci_enable_device(pdev)) return -EIO; /* Image file instead of VGA-bios */ HwExt.VirtualRomBase = rom_vbase = (unsigned long) RomData;#else#ifdef CONFIG_FB_SIS_LINUXBIOS if (pci_enable_device(pdev)) return -EIO; HwExt.VirtualRomBase = rom_vbase = 0;#else request_region(rom_base, 32, "sisfb"); HwExt.VirtualRomBase = rom_vbase = (unsigned long) ioremap(rom_base, MAX_ROM_SCAN);#endif#endif /* set passwd */ vgawb(SEQ_ADR, IND_SIS_PASSWORD); vgawb(SEQ_DATA, SIS_PASSWORD); /* Enable MMIO & PCI linear address */ vgawb(SEQ_ADR, IND_SIS_PCI_ADDRESS_SET); jTemp = vgarb(SEQ_DATA); jTemp |= SIS_PCI_ADDR_ENABLE; jTemp |= SIS_MEM_MAP_IO_ENABLE; vgawb(SEQ_DATA, jTemp);#ifdef CONFIG_FB_SIS_LINUXBIOS pdev_valid = 0; pci_for_each_dev(pdev) { u8 uPCIData=0; if ((pdev->vendor == PCI_VENDOR_ID_SI) && (pdev->device==0x630)) { pci_read_config_byte(pdev, 0x63, &uPCIData); uPCIData = (uPCIData & 0x70) >> 4; ivideo.video_size = (unsigned int)(1 << (uPCIData+21)); pdev_valid = 1; break; } } if (!pdev_valid) return -1;#else vgawb(SEQ_ADR, IND_SIS_DRAM_SIZE); ivideo.video_size = ((unsigned int) ((vgarb(SEQ_DATA) & 0x3f) + 1) << 20);#endif /* get CRT2 connection state */ vgawb(SEQ_ADR, 0x17); uSRData = vgarb(SEQ_DATA); vgawb(CRTC_ADR, 0x32); uCRData = vgarb(CRTC_DATA); ivideo.TV_plug = ivideo.TV_type = 0; if((uSRData&0x0F) && (HwExt.jChipID>=SIS_Trojan)) { /* CRT1 connect detection */ if((uSRData & 0x01) && !crt1off) crt1off = 0; else { if(uSRData&0x0E) /* DISP2 connected */ crt1off = 1; else crt1off = 0; } /* detection priority : CRT2 > LCD > TV */ if(uSRData & 0x08 ) uDispType = MASK_DISPTYPE_CRT2; else if(uSRData & 0x02) uDispType = MASK_DISPTYPE_LCD; else if(uSRData & 0x04) { if(uSRData & 0x80) { ivideo.TV_type = TVMODE_HIVISION; ivideo.TV_plug = TVPLUG_SVIDEO; } else if(uSRData & 0x20) ivideo.TV_plug = TVPLUG_SVIDEO; else if(uSRData & 0x10) ivideo.TV_plug = TVPLUG_COMPOSITE; else if(uSRData & 0x40) ivideo.TV_plug = TVPLUG_SCART; if(ivideo.TV_type == 0) { u8 uSR16; vgawb(SEQ_ADR, 0x16); uSR16 = vgarb(SEQ_DATA); if(uSR16 & 0x20) ivideo.TV_type = TVMODE_PAL; else ivideo.TV_type = TVMODE_NTSC; } uDispType = MASK_DISPTYPE_TV; } } else { if((uCRData & 0x20) && !crt1off) crt1off = 0; else { if(uCRData&0x5F) /* DISP2 connected */ crt1off = 1; else crt1off = 0; } if(uCRData & 0x10) uDispType = MASK_DISPTYPE_CRT2; else if(uCRData & 0x08) uDispType = MASK_DISPTYPE_LCD; else if(uCRData & 0x47) { uDispType = MASK_DISPTYPE_TV; if(uCRData & 0x40) { ivideo.TV_type = TVMODE_HIVISION; ivideo.TV_plug = TVPLUG_SVIDEO; } else if(uCRData & 0x02) ivideo.TV_plug = TVPLUG_SVIDEO; else if(uCRData & 0x01) ivideo.TV_plug = TVPLUG_COMPOSITE; else if(uCRData & 0x04) ivideo.TV_plug = TVPLUG_SCART; if(ivideo.TV_type == 0) { u8 uTemp; uTemp = *((u8 *)(HwExt.VirtualRomBase+0x52)); if(uTemp&0x40) { uTemp=*((u8 *)(HwExt.VirtualRomBase+0x53)); } else { vgawb(SEQ_ADR, 0x38); uTemp = vgarb(SEQ_DATA); } if(uTemp & 0x01) ivideo.TV_type = TVMODE_PAL; else ivideo.TV_type = TVMODE_NTSC; } } } if(uDispType == MASK_DISPTYPE_LCD) // LCD conntected { // TODO: set LCDType by EDID HwExt.usLCDType = LCD1024; } if (HwExt.jChipID >= SIS_Trojan) { vgawb(SEQ_ADR, 0x1A); uSRData = vgarb(SEQ_DATA); if (uSRData & 0x10) HwExt.bIntegratedMMEnabled = TRUE; else HwExt.bIntegratedMMEnabled = FALSE; } if(mode_idx >= 0) /* mode found */ { /* Filtering mode for VB */ switch(uDispType & MASK_DISPTYPE_DISP2) { case MASK_DISPTYPE_LCD: switch(HwExt.usLCDType) { case LCD1024: if(sisbios_mode[mode_idx].xres > 1024) mode_idx = -1; break; case LCD1280: if(sisbios_mode[mode_idx].xres > 1280) mode_idx = -1; break; case LCD2048: if(sisbios_mode[mode_idx].xres > 2048) mode_idx = -1; break; case LCD1920: if(sisbios_mode[mode_idx].xres > 1920) mode_idx = -1; break; case LCD1600: if(sisbios_mode[mode_idx].xres > 1600) mode_idx = -1; break; case LCD800: if(sisbios_mode[mode_idx].xres > 800) mode_idx = -1; break; case LCD640: if(sisbios_mode[mode_idx].xres > 640) mode_idx = -1; break; default: mode_idx = -1; } if(sisbios_mode[mode_idx].xres == 720) /* only for TV */ mode_idx = -1; break; case MASK_DISPTYPE_TV: switch(sisbios_mode[mode_idx].xres) { case 800: case 640: break; case 720: if(ivideo.TV_type == TVMODE_NTSC) { if(sisbios_mode[mode_idx].yres != 480) mode_idx = -1; } else if(ivideo.TV_type == TVMODE_PAL) { if(sisbios_mode[mode_idx].yres != 576) mode_idx = -1; } break; default: /* illegal mode */ mode_idx = -1; } break; } } if (mode_idx < 0) { switch(uDispType & MASK_DISPTYPE_DISP2) { case MASK_DISPTYPE_LCD: mode_idx = DEFAULT_LCDMODE; break; case MASK_DISPTYPE_TV: mode_idx = DEFAULT_TVMODE; break; default: mode_idx = DEFAULT_MODE; } }#ifdef CONFIG_FB_SIS_LINUXBIOS mode_idx = DEFAULT_MODE; rate_idx = sisbios_mode[mode_idx].rate_idx; /* set to default refresh rate 60MHz */ ivideo.refresh_rate = 60;#endif mode_no = sisbios_mode[mode_idx].mode_no; if (ivideo.refresh_rate != 0) search_refresh_rate(ivideo.refresh_rate); if (rate_idx == 0) { rate_idx = sisbios_mode[mode_idx].rate_idx; /* set to default refresh rate 60MHz */ ivideo.refresh_rate = 60; } ivideo.video_bpp = sisbios_mode[mode_idx].bpp; ivideo.video_vwidth = ivideo.video_width = sisbios_mode[mode_idx].xres; ivideo.video_vheight = ivideo.video_height = sisbios_mode[mode_idx].yres; ivideo.org_x = ivideo.org_y = 0; video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3); printk(KERN_DEBUG "FB base: 0x%lx, size: 0x%dK\n", ivideo.video_base, (unsigned int)ivideo.video_size/1024); printk(KERN_DEBUG "MMIO base: 0x%lx, size: 0x%dK\n", ivideo.mmio_base, (unsigned int)MMIO_SIZE/1024); if (!request_mem_region(ivideo.video_base, ivideo.video_size, "sisfb FB")) { printk(KERN_ERR "sisfb: cannot reserve frame buffer memory\n"); return -ENODEV; } if (!request_mem_region(ivideo.mmio_base, MMIO_SIZE, "sisfb MMIO")) { printk(KERN_ERR "sisfb: cannot reserve MMIO region\n"); release_mem_region(ivideo.video_base, ivideo.video_size); return -ENODEV; } HwExt.VirtualVideoMemoryAddress = ivideo.video_vbase = ioremap(ivideo.video_base, ivideo.video_size); ivideo.mmio_vbase = ioremap(ivideo.mmio_base, MMIO_SIZE);#ifdef NOBIOS SiSInit300(&HwExt);#else#ifdef CONFIG_FB_SIS_LINUXBIOS SiSInit300(&HwExt);#endif#endif printk(KERN_INFO "sisfb: framebuffer at 0x%lx, mapped to 0x%p, size %dk\n", ivideo.video_base, ivideo.video_vbase, ivideo.video_size / 1024); printk(KERN_INFO "sisfb: mode is %dx%dx%d, linelength=%d\n", ivideo.video_width, ivideo.video_height, ivideo.video_bpp, video_linelength); /* enable 2D engine */ vgawb(SEQ_ADR, IND_SIS_MODULE_ENABLE); jTemp = vgarb(SEQ_DATA); jTemp |= SIS_2D_ENABLE; vgawb(SEQ_DATA, jTemp); pre_setmode(); if (SiSSetMode(&HwExt, mode_no)) { DPRINTK("sisfb: set mode[0x%x]: failed\n", mode_no); return -1; } post_setmode(); /* Get VB functions */ sis_get301info(); crtc_to_var(&default_var); fb_info.changevar = NULL; fb_info.node = -1; fb_info.fbops = &sisfb_ops; fb_info.disp = &disp; fb_info.switch_con = &sisfb_switch; fb_info.updatevar = &sisfb_update_var; fb_info.blank = &sisfb_blank; fb_info.flags = FBINFO_FLAG_DEFAULT; sisfb_set_disp(-1, &default_var); if (sisfb_heap_init()) { DPRINTK("sisfb: Failed to enable offscreen heap\n"); } /* to avoid the inversed bgcolor bug of the initial state */ vc_resize_con(1, 1, 0); if (register_framebuffer(&fb_info) < 0) return -EINVAL; printk(KERN_INFO "fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node), fb_info.modename); return 0;}#ifdef MODULEstatic char *mode = NULL;static unsigned int rate = 0;static unsigned int crt1 = 1;MODULE_PARM(mode, "s");MODULE_PARM(rate, "i");MODULE_PARM(crt1, "i"); /* default: CRT1 enable */int init_module(void){ if (mode) search_mode(mode); ivideo.refresh_rate = rate; if(crt1 == 0) crt1off = 1; else crt1off = 0; sisfb_init(); return 0;}void cleanup_module(void){ unregister_framebuffer(&fb_info);}#endif /* MODULE */EXPORT_SYMBOL(sis_malloc);EXPORT_SYMBOL(sis_free);EXPORT_SYMBOL(ivideo);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?