Enscript Output

extractedLnx/linux-2.6.20/drivers/video/sis/sis_main.c_sisfb_probe.c

static int __devinit
sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	struct sisfb_chip_info	*chipinfo = &sisfb_chip_info[ent->driver_data];
	struct sis_video_info	*ivideo = NULL;
	struct fb_info		*sis_fb_info = NULL;
	u16 reg16;
	u8  reg;
	int i, ret;

	if(sisfb_off)
		return -ENXIO;

	sis_fb_info = framebuffer_alloc(sizeof(*ivideo), &pdev->dev);
	if(!sis_fb_info)
		return -ENOMEM;

	ivideo = (struct sis_video_info *)sis_fb_info->par;
	ivideo->memyselfandi = sis_fb_info;

	ivideo->sisfb_id = SISFB_ID;

	if(card_list == NULL) {
		ivideo->cardnumber = 0;
	} else {
		struct sis_video_info *countvideo = card_list;
		ivideo->cardnumber = 1;
		while((countvideo = countvideo->next) != 0)
			ivideo->cardnumber++;
	}

	strncpy(ivideo->myid, chipinfo->chip_name, 30);

	ivideo->warncount = 0;
	ivideo->chip_id = pdev->device;
	ivideo->chip_vendor = pdev->vendor;
	pci_read_config_byte(pdev, PCI_REVISION_ID, &ivideo->revision_id);
	ivideo->SiS_Pr.ChipRevision = ivideo->revision_id;
	pci_read_config_word(pdev, PCI_COMMAND, &reg16);
	ivideo->sisvga_enabled = reg16 & 0x01;
	ivideo->pcibus = pdev->bus->number;
	ivideo->pcislot = PCI_SLOT(pdev->devfn);
	ivideo->pcifunc = PCI_FUNC(pdev->devfn);
	ivideo->subsysvendor = pdev->subsystem_vendor;
	ivideo->subsysdevice = pdev->subsystem_device;
#ifdef SIS_OLD_CONFIG_COMPAT
	ivideo->ioctl32registered = 0;
#endif

#ifndef MODULE
	if(sisfb_mode_idx == -1) {
		sisfb_get_vga_mode_from_kernel();
	}
#endif

	ivideo->chip = chipinfo->chip;
	ivideo->sisvga_engine = chipinfo->vgaengine;
	ivideo->hwcursor_size = chipinfo->hwcursor_size;
	ivideo->CRT2_write_enable = chipinfo->CRT2_write_enable;
	ivideo->mni = chipinfo->mni;

	ivideo->detectedpdc  = 0xff;
	ivideo->detectedpdca = 0xff;
	ivideo->detectedlcda = 0xff;

	ivideo->sisfb_thismonitor.datavalid = FALSE;

	ivideo->current_base = 0;

	ivideo->engineok = 0;

	ivideo->sisfb_was_boot_device = 0;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12))
	if(pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW) {
		if(ivideo->sisvga_enabled)
			ivideo->sisfb_was_boot_device = 1;
		else {
			printk(KERN_DEBUG "sisfb: PCI device is disabled, "
				"but marked as boot video device ???\n");
			printk(KERN_DEBUG "sisfb: I will not accept this "
				"as the primary VGA device\n");
		}
	}
#endif

	ivideo->sisfb_parm_mem = sisfb_parm_mem;
	ivideo->sisfb_accel = sisfb_accel;
	ivideo->sisfb_ypan = sisfb_ypan;
	ivideo->sisfb_max = sisfb_max;
	ivideo->sisfb_userom = sisfb_userom;
	ivideo->sisfb_useoem = sisfb_useoem;
	ivideo->sisfb_mode_idx = sisfb_mode_idx;
	ivideo->sisfb_parm_rate = sisfb_parm_rate;
	ivideo->sisfb_crt1off = sisfb_crt1off;
	ivideo->sisfb_forcecrt1 = sisfb_forcecrt1;
	ivideo->sisfb_crt2type = sisfb_crt2type;
	ivideo->sisfb_crt2flags = sisfb_crt2flags;
	/* pdc(a), scalelcd, special timing, lvdshl handled below */
	ivideo->sisfb_dstn = sisfb_dstn;
	ivideo->sisfb_fstn = sisfb_fstn;
	ivideo->sisfb_tvplug = sisfb_tvplug;
	ivideo->sisfb_tvstd = sisfb_tvstd;
	ivideo->tvxpos = sisfb_tvxposoffset;
	ivideo->tvypos = sisfb_tvyposoffset;
	ivideo->sisfb_nocrt2rate = sisfb_nocrt2rate;
	ivideo->refresh_rate = 0;
	if(ivideo->sisfb_parm_rate != -1) {
		ivideo->refresh_rate = ivideo->sisfb_parm_rate;
	}

	ivideo->SiS_Pr.UsePanelScaler = sisfb_scalelcd;
	ivideo->SiS_Pr.CenterScreen = -1;
	ivideo->SiS_Pr.SiS_CustomT = sisfb_specialtiming;
	ivideo->SiS_Pr.LVDSHL = sisfb_lvdshl;

	ivideo->SiS_Pr.SiS_Backup70xx = 0xff;
	ivideo->SiS_Pr.SiS_CHOverScan = -1;
	ivideo->SiS_Pr.SiS_ChSW = FALSE;
	ivideo->SiS_Pr.SiS_UseLCDA = FALSE;
	ivideo->SiS_Pr.HaveEMI = FALSE;
	ivideo->SiS_Pr.HaveEMILCD = FALSE;
	ivideo->SiS_Pr.OverruleEMI = FALSE;
	ivideo->SiS_Pr.SiS_SensibleSR11 = FALSE;
	ivideo->SiS_Pr.SiS_MyCR63 = 0x63;
	ivideo->SiS_Pr.PDC  = -1;
	ivideo->SiS_Pr.PDCA = -1;
	ivideo->SiS_Pr.DDCPortMixup = FALSE;
#ifdef CONFIG_FB_SIS_315
	if(ivideo->chip >= SIS_330) {
		ivideo->SiS_Pr.SiS_MyCR63 = 0x53;
		if(ivideo->chip >= SIS_661) {
			ivideo->SiS_Pr.SiS_SensibleSR11 = TRUE;
		}
	}
#endif

	memcpy(&ivideo->default_var, &my_default_var, sizeof(my_default_var));

	pci_set_drvdata(pdev, ivideo);

	/* Patch special cases */
	if((ivideo->nbridge = sisfb_get_northbridge(ivideo->chip))) {
		switch(ivideo->nbridge->device) {
#ifdef CONFIG_FB_SIS_300
		case PCI_DEVICE_ID_SI_730:
			ivideo->chip = SIS_730;
			strcpy(ivideo->myid, "SiS 730");
			break;
#endif
#ifdef CONFIG_FB_SIS_315
		case PCI_DEVICE_ID_SI_651:
			/* ivideo->chip is ok */
			strcpy(ivideo->myid, "SiS 651");
			break;
		case PCI_DEVICE_ID_SI_740:
			ivideo->chip = SIS_740;
			strcpy(ivideo->myid, "SiS 740");
			break;
		case PCI_DEVICE_ID_SI_661:
			ivideo->chip = SIS_661;
			strcpy(ivideo->myid, "SiS 661");
			break;
		case PCI_DEVICE_ID_SI_741:
			ivideo->chip = SIS_741;
			strcpy(ivideo->myid, "SiS 741");
			break;
		case PCI_DEVICE_ID_SI_760:
			ivideo->chip = SIS_760;
			strcpy(ivideo->myid, "SiS 760");
			break;
		case PCI_DEVICE_ID_SI_761:
			ivideo->chip = SIS_761;
			strcpy(ivideo->myid, "SiS 761");
			break;
#endif
		default:
			break;
		}
	}

	ivideo->SiS_Pr.ChipType = ivideo->chip;

	ivideo->SiS_Pr.ivideo = (void *)ivideo;

#ifdef CONFIG_FB_SIS_315
	if((ivideo->SiS_Pr.ChipType == SIS_315PRO) ||
	   (ivideo->SiS_Pr.ChipType == SIS_315)) {
		ivideo->SiS_Pr.ChipType = SIS_315H;
	}
#endif

	if(!ivideo->sisvga_enabled) {
		if(pci_enable_device(pdev)) {
			if(ivideo->nbridge) SIS_PCI_PUT_DEVICE(ivideo->nbridge);
			pci_set_drvdata(pdev, NULL);
			kfree(sis_fb_info);
			return -EIO;
		}
	}

	ivideo->video_base = pci_resource_start(pdev, 0);
	ivideo->mmio_base  = pci_resource_start(pdev, 1);
	ivideo->mmio_size  = pci_resource_len(pdev, 1);
	ivideo->SiS_Pr.RelIO = pci_resource_start(pdev, 2) + 0x30;
	ivideo->SiS_Pr.IOAddress = ivideo->vga_base = ivideo->SiS_Pr.RelIO;

	SiSRegInit(&ivideo->SiS_Pr, ivideo->SiS_Pr.IOAddress);

#ifdef CONFIG_FB_SIS_300
	/* Find PCI systems for Chrontel/GPIO communication setup */
	if(ivideo->chip == SIS_630) {
		i = 0;
        	do {
			if(mychswtable[i].subsysVendor == ivideo->subsysvendor &&
			   mychswtable[i].subsysCard   == ivideo->subsysdevice) {
				ivideo->SiS_Pr.SiS_ChSW = TRUE;
				printk(KERN_DEBUG "sisfb: Identified [%s %s] "
					"requiring Chrontel/GPIO setup\n",
					mychswtable[i].vendorName,
					mychswtable[i].cardName);
				ivideo->lpcdev = SIS_PCI_GET_DEVICE(PCI_VENDOR_ID_SI, 0x0008, NULL);
				break;
			}
			i++;
		} while(mychswtable[i].subsysVendor != 0);
	}
#endif

#ifdef CONFIG_FB_SIS_315
	if((ivideo->chip == SIS_760) && (ivideo->nbridge)) {
		ivideo->lpcdev = SIS_PCI_GET_SLOT(ivideo->nbridge->bus, (2 << 3));
	}
#endif

	outSISIDXREG(SISSR, 0x05, 0x86);

	if( (!ivideo->sisvga_enabled)
#if !defined(__i386__) && !defined(__x86_64__)
			      || (sisfb_resetcard)
#endif
						   ) {
		for(i = 0x30; i <= 0x3f; i++) {
			outSISIDXREG(SISCR, i, 0x00);
		}
	}

	/* Find out about current video mode */
	ivideo->modeprechange = 0x03;
	inSISIDXREG(SISCR, 0x34, reg);
	if(reg & 0x7f) {
		ivideo->modeprechange = reg & 0x7f;
	} else if(ivideo->sisvga_enabled) {
#if defined(__i386__) || defined(__x86_64__)
		unsigned char SIS_IOTYPE2 *tt = ioremap(0x400, 0x100);
		if(tt) {
			ivideo->modeprechange = readb(tt + 0x49);
			iounmap(tt);
		}
#endif
	}

	/* Search and copy ROM image */
	ivideo->bios_abase = NULL;
	ivideo->SiS_Pr.VirtualRomBase = NULL;
	ivideo->SiS_Pr.UseROM = FALSE;
	ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = FALSE;
	if(ivideo->sisfb_userom) {
		ivideo->SiS_Pr.VirtualRomBase = sisfb_find_rom(pdev);
		ivideo->bios_abase = ivideo->SiS_Pr.VirtualRomBase;
		ivideo->SiS_Pr.UseROM = (ivideo->SiS_Pr.VirtualRomBase) ? TRUE : FALSE;
		printk(KERN_INFO "sisfb: Video ROM %sfound\n",
			ivideo->SiS_Pr.UseROM ? "" : "not ");
		if((ivideo->SiS_Pr.UseROM) && (ivideo->chip >= XGI_20)) {
		   ivideo->SiS_Pr.UseROM = FALSE;
		   ivideo->haveXGIROM = ivideo->SiS_Pr.SiS_XGIROM = TRUE;
		   if( (ivideo->revision_id == 2) &&
		       (!(ivideo->bios_abase[0x1d1] & 0x01)) ) {
			ivideo->SiS_Pr.DDCPortMixup = TRUE;
		   }
		}
	} else {
		printk(KERN_INFO "sisfb: Video ROM usage disabled\n");
	}

	/* Find systems for special custom timing */
	if(ivideo->SiS_Pr.SiS_CustomT == CUT_NONE) {
		sisfb_detect_custom_timing(ivideo);
	}

	/* POST card in case this has not been done by the BIOS */
	if( (!ivideo->sisvga_enabled)
#if !defined(__i386__) && !defined(__x86_64__)
			     || (sisfb_resetcard)
#endif
						 ) {
#ifdef CONFIG_FB_SIS_300
		if(ivideo->sisvga_engine == SIS_300_VGA) {
			if(ivideo->chip == SIS_300) {
				sisfb_post_sis300(pdev);
				ivideo->sisfb_can_post = 1;
			}
		}
#endif

#ifdef CONFIG_FB_SIS_315
		if(ivideo->sisvga_engine == SIS_315_VGA) {
			int result = 1;
		/*	if((ivideo->chip == SIS_315H)   ||
			   (ivideo->chip == SIS_315)    ||
			   (ivideo->chip == SIS_315PRO) ||
			   (ivideo->chip == SIS_330)) {
				sisfb_post_sis315330(pdev);
			} else */ if(ivideo->chip == XGI_20) {
				result = sisfb_post_xgi(pdev);
				ivideo->sisfb_can_post = 1;
			} else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
				result = sisfb_post_xgi(pdev);
				ivideo->sisfb_can_post = 1;
			} else {
				printk(KERN_INFO "sisfb: Card is not "
					"POSTed and sisfb can't do this either.\n");
			}
			if(!result) {
				printk(KERN_ERR "sisfb: Failed to POST card\n");
				ret = -ENODEV;
				goto error_3;
			}
		}
#endif
	}

	ivideo->sisfb_card_posted = 1;

	/* Find out about RAM size */
	if(sisfb_get_dram_size(ivideo)) {
		printk(KERN_INFO "sisfb: Fatal error: Unable to determine VRAM size.\n");
		ret = -ENODEV;
		goto error_3;
	}


	/* Enable PCI addressing and MMIO */
	if((ivideo->sisfb_mode_idx < 0) ||
	   ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {
		/* Enable PCI_LINEAR_ADDRESSING and MMIO_ENABLE  */
		orSISIDXREG(SISSR, IND_SIS_PCI_ADDRESS_SET, (SIS_PCI_ADDR_ENABLE | SIS_MEM_MAP_IO_ENABLE));
		/* Enable 2D accelerator engine */
		orSISIDXREG(SISSR, IND_SIS_MODULE_ENABLE, SIS_ENABLE_2D);
	}

	if(sisfb_pdc != 0xff) {
		if(ivideo->sisvga_engine == SIS_300_VGA)
			sisfb_pdc &= 0x3c;
		else
			sisfb_pdc &= 0x1f;
		ivideo->SiS_Pr.PDC = sisfb_pdc;
	}
#ifdef CONFIG_FB_SIS_315
	if(ivideo->sisvga_engine == SIS_315_VGA) {
		if(sisfb_pdca != 0xff)
			ivideo->SiS_Pr.PDCA = sisfb_pdca & 0x1f;
	}
#endif

	if(!request_mem_region(ivideo->video_base, ivideo->video_size, "sisfb FB")) {
		printk(KERN_ERR "sisfb: Fatal error: Unable to reserve %dMB framebuffer memory\n",
				(int)(ivideo->video_size >> 20));
		printk(KERN_ERR "sisfb: Is there another framebuffer driver active?\n");
		ret = -ENODEV;
		goto error_3;
	}

	if(!request_mem_region(ivideo->mmio_base, ivideo->mmio_size, "sisfb MMIO")) {
		printk(KERN_ERR "sisfb: Fatal error: Unable to reserve MMIO region\n");
		ret = -ENODEV;
		goto error_2;
	}

	ivideo->video_vbase = ioremap(ivideo->video_base, ivideo->video_size);
	ivideo->SiS_Pr.VideoMemoryAddress = ivideo->video_vbase;
	if(!ivideo->video_vbase) {
		printk(KERN_ERR "sisfb: Fatal error: Unable to map framebuffer memory\n");
		ret = -ENODEV;
		goto error_1;
	}

	ivideo->mmio_vbase = ioremap(ivideo->mmio_base, ivideo->mmio_size);
	if(!ivideo->mmio_vbase) {
		printk(KERN_ERR "sisfb: Fatal error: Unable to map MMIO region\n");
		ret = -ENODEV;
error_0:	iounmap(ivideo->video_vbase);
error_1:	release_mem_region(ivideo->video_base, ivideo->video_size);
error_2:	release_mem_region(ivideo->mmio_base, ivideo->mmio_size);
error_3:	vfree(ivideo->bios_abase);
		if(ivideo->lpcdev)
			SIS_PCI_PUT_DEVICE(ivideo->lpcdev);
		if(ivideo->nbridge)
			SIS_PCI_PUT_DEVICE(ivideo->nbridge);
		pci_set_drvdata(pdev, NULL);
		if(!ivideo->sisvga_enabled)
			pci_disable_device(pdev);
		kfree(sis_fb_info);
		return ret;
	}

	printk(KERN_INFO "sisfb: Video RAM at 0x%lx, mapped to 0x%lx, size %ldk\n",
		ivideo->video_base, (unsigned long)ivideo->video_vbase, ivideo->video_size / 1024);

	if(ivideo->video_offset) {
		printk(KERN_INFO "sisfb: Viewport offset %ldk\n",
			ivideo->video_offset / 1024);
	}

	printk(KERN_INFO "sisfb: MMIO at 0x%lx, mapped to 0x%lx, size %ldk\n",
		ivideo->mmio_base, (unsigned long)ivideo->mmio_vbase, ivideo->mmio_size / 1024);


	/* Determine the size of the command queue */
	if(ivideo->sisvga_engine == SIS_300_VGA) {
		ivideo->cmdQueueSize = TURBO_QUEUE_AREA_SIZE;
	} else {
		if(ivideo->chip == XGI_20) {
			ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE_Z7;
		} else {
			ivideo->cmdQueueSize = COMMAND_QUEUE_AREA_SIZE;
		}
	}

	/* Engines are no longer initialized here; this is
	 * now done after the first mode-switch (if the
	 * submitted var has its acceleration flags set).
	 */

	/* Calculate the base of the (unused) hw cursor */
	ivideo->hwcursor_vbase = ivideo->video_vbase
				 + ivideo->video_size
				 - ivideo->cmdQueueSize
				 - ivideo->hwcursor_size;
	ivideo->caps |= HW_CURSOR_CAP;

	/* Initialize offscreen memory manager */
	if((ivideo->havenoheap = sisfb_heap_init(ivideo))) {
		printk(KERN_WARNING "sisfb: Failed to initialize offscreen memory heap\n");
	}

	/* Used for clearing the screen only, therefore respect our mem limit */
	ivideo->SiS_Pr.VideoMemoryAddress += ivideo->video_offset;
	ivideo->SiS_Pr.VideoMemorySize = ivideo->sisfb_mem;

	ivideo->mtrr = -1;

	ivideo->vbflags = 0;
	ivideo->lcddefmodeidx = DEFAULT_LCDMODE;
	ivideo->tvdefmodeidx  = DEFAULT_TVMODE;
	ivideo->defmodeidx    = DEFAULT_MODE;

	ivideo->newrom = 0;
	if(ivideo->chip < XGI_20) {
		if(ivideo->bios_abase) {
			ivideo->newrom = SiSDetermineROMLayout661(&ivideo->SiS_Pr);
		}
	}

	if((ivideo->sisfb_mode_idx < 0) ||
	   ((sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni]) != 0xFF)) {

		sisfb_sense_crt1(ivideo);

		sisfb_get_VB_type(ivideo);

		if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
			sisfb_detect_VB_connect(ivideo);
		}

		ivideo->currentvbflags = ivideo->vbflags & (VB_VIDEOBRIDGE | TV_STANDARD);

		/* Decide on which CRT2 device to use */
		if(ivideo->vbflags2 & VB2_VIDEOBRIDGE) {
			if(ivideo->sisfb_crt2type != -1) {
				if((ivideo->sisfb_crt2type == CRT2_LCD) &&
				   (ivideo->vbflags & CRT2_LCD)) {
					ivideo->currentvbflags |= CRT2_LCD;
				} else if(ivideo->sisfb_crt2type != CRT2_LCD) {
					ivideo->currentvbflags |= ivideo->sisfb_crt2type;
				}
			} else {
				/* Chrontel 700x TV detection often unreliable, therefore
				 * use a different default order on such machines
				 */
				if((ivideo->sisvga_engine == SIS_300_VGA) &&
				   (ivideo->vbflags2 & VB2_CHRONTEL)) {
					if(ivideo->vbflags & CRT2_LCD)
						ivideo->currentvbflags |= CRT2_LCD;
					else if(ivideo->vbflags & CRT2_TV)
						ivideo->currentvbflags |= CRT2_TV;
					else if(ivideo->vbflags & CRT2_VGA)
						ivideo->currentvbflags |= CRT2_VGA;
				} else {
					if(ivideo->vbflags & CRT2_TV)
						ivideo->currentvbflags |= CRT2_TV;
					else if(ivideo->vbflags & CRT2_LCD)
						ivideo->currentvbflags |= CRT2_LCD;
					else if(ivideo->vbflags & CRT2_VGA)
						ivideo->currentvbflags |= CRT2_VGA;
				}
			}
		}

		if(ivideo->vbflags & CRT2_LCD) {
			sisfb_detect_lcd_type(ivideo);
		}

		sisfb_save_pdc_emi(ivideo);

		if(!ivideo->sisfb_crt1off) {
			sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 0);
		} else {
			if((ivideo->vbflags2 & VB2_SISTMDSBRIDGE) &&
			   (ivideo->vbflags & (CRT2_VGA | CRT2_LCD))) {
				sisfb_handle_ddc(ivideo, &ivideo->sisfb_thismonitor, 1);
			}
		}

		if(ivideo->sisfb_mode_idx >= 0) {
			int bu = ivideo->sisfb_mode_idx;
			ivideo->sisfb_mode_idx = sisfb_validate_mode(ivideo,
					ivideo->sisfb_mode_idx, ivideo->currentvbflags);
			if(bu != ivideo->sisfb_mode_idx) {
				printk(KERN_ERR "Mode %dx%dx%d failed validation\n",
					sisbios_mode[bu].xres,
					sisbios_mode[bu].yres,
					sisbios_mode[bu].bpp);
			}
		}

		if(ivideo->sisfb_mode_idx < 0) {
			switch(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {
			   case CRT2_LCD:
				ivideo->sisfb_mode_idx = ivideo->lcddefmodeidx;
				break;
			   case CRT2_TV:
				ivideo->sisfb_mode_idx = ivideo->tvdefmodeidx;
				break;
			   default:
				ivideo->sisfb_mode_idx = ivideo->defmodeidx;
				break;
			}
		}

		ivideo->mode_no = sisbios_mode[ivideo->sisfb_mode_idx].mode_no[ivideo->mni];

		if(ivideo->refresh_rate != 0) {
			sisfb_search_refresh_rate(ivideo, ivideo->refresh_rate,
						ivideo->sisfb_mode_idx);
		}

		if(ivideo->rate_idx == 0) {
			ivideo->rate_idx = sisbios_mode[ivideo->sisfb_mode_idx].rate_idx;
			ivideo->refresh_rate = 60;
		}

		if(ivideo->sisfb_thismonitor.datavalid) {
			if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor,
						ivideo->sisfb_mode_idx,
						ivideo->rate_idx,
						ivideo->refresh_rate)) {
				printk(KERN_INFO "sisfb: WARNING: Refresh rate "
							"exceeds monitor specs!\n");
			}
		}

		ivideo->video_bpp = sisbios_mode[ivideo->sisfb_mode_idx].bpp;
		ivideo->video_width = sisbios_mode[ivideo->sisfb_mode_idx].xres;
		ivideo->video_height = sisbios_mode[ivideo->sisfb_mode_idx].yres;

		sisfb_set_vparms(ivideo);

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)

		/* ---------------- For 2.4: Now switch the mode ------------------ */

		printk(KERN_INFO "sisfb: Setting mode %dx%dx%d (%dHz)\n",
			ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
			ivideo->refresh_rate);

		/* Determine whether or not acceleration is to be
		 * used. Need to know before pre/post_set_mode()
		 */
		ivideo->accel = 0;
		ivideo->default_var.accel_flags &= ~FB_ACCELF_TEXT;
		if(ivideo->sisfb_accel) {
			ivideo->accel = -1;
			ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
		}

		/* Now switch the mode */
		sisfb_pre_setmode(ivideo);

		if(SiSSetMode(&ivideo->SiS_Pr, ivideo->mode_no) == 0) {
			printk(KERN_ERR "sisfb: Fatal error: Setting mode[0x%x] failed\n",
									ivideo->mode_no);
			ret = -EINVAL;
			iounmap(ivideo->mmio_vbase);
			goto error_0;
		}

		outSISIDXREG(SISSR, IND_SIS_PASSWORD, SIS_PASSWORD);

		sisfb_post_setmode(ivideo);

		/* Maximize regardless of sisfb_max at startup */
		ivideo->default_var.yres_virtual = 32767;

		/* Force reset of x virtual in crtc_to_var */
		ivideo->default_var.xres_virtual = 0;

		/* Copy mode timing to var */
		sisfb_crtc_to_var(ivideo, &ivideo->default_var);

		/* Find out about screen pitch */
		sisfb_calc_pitch(ivideo, &ivideo->default_var);
		sisfb_set_pitch(ivideo);

		/* Init the accelerator (does nothing currently) */
		sisfb_initaccel(ivideo);

		/* Init some fbinfo entries */
		sis_fb_info->node  = -1;
		sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
		sis_fb_info->fbops = &sisfb_ops;
		sis_fb_info->disp  = &ivideo->sis_disp;
		sis_fb_info->blank = &sisfb_blank;
		sis_fb_info->switch_con = &sisfb_switch;
		sis_fb_info->updatevar  = &sisfb_update_var;
		sis_fb_info->changevar  = NULL;
		strcpy(sis_fb_info->fontname, sisfb_fontname);

		sisfb_set_disp(-1, &ivideo->default_var, sis_fb_info);

#else		/* --------- For 2.6: Setup a somewhat sane default var ------------ */

		printk(KERN_INFO "sisfb: Default mode is %dx%dx%d (%dHz)\n",
			ivideo->video_width, ivideo->video_height, ivideo->video_bpp,
			ivideo->refresh_rate);

		/* Set up the default var according to chosen default display mode */
		ivideo->default_var.xres = ivideo->default_var.xres_virtual = ivideo->video_width;
		ivideo->default_var.yres = ivideo->default_var.yres_virtual = ivideo->video_height;
		ivideo->default_var.bits_per_pixel = ivideo->video_bpp;

		sisfb_bpp_to_var(ivideo, &ivideo->default_var);

		ivideo->default_var.pixclock = (u32) (1000000000 /
			sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr, ivideo->mode_no, ivideo->rate_idx));

		if(sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, ivideo->mode_no,
						ivideo->rate_idx, &ivideo->default_var)) {
			if((ivideo->default_var.vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {
				ivideo->default_var.pixclock <<= 1;
			}
		}

		if(ivideo->sisfb_ypan) {
			/* Maximize regardless of sisfb_max at startup */
			ivideo->default_var.yres_virtual =
				sisfb_calc_maxyres(ivideo, &ivideo->default_var);
			if(ivideo->default_var.yres_virtual < ivideo->default_var.yres) {
				ivideo->default_var.yres_virtual = ivideo->default_var.yres;
			}
		}

		sisfb_calc_pitch(ivideo, &ivideo->default_var);

		ivideo->accel = 0;
		if(ivideo->sisfb_accel) {
			ivideo->accel = -1;
#ifdef STUPID_ACCELF_TEXT_SHIT
			ivideo->default_var.accel_flags |= FB_ACCELF_TEXT;
#endif
		}
		sisfb_initaccel(ivideo);

#if defined(FBINFO_HWACCEL_DISABLED) && defined(FBINFO_HWACCEL_XPAN)
		sis_fb_info->flags = FBINFO_DEFAULT 		|
				     FBINFO_HWACCEL_YPAN 	|
				     FBINFO_HWACCEL_XPAN 	|
				     FBINFO_HWACCEL_COPYAREA 	|
				     FBINFO_HWACCEL_FILLRECT 	|
				     ((ivideo->accel) ? 0 : FBINFO_HWACCEL_DISABLED);
#else
		sis_fb_info->flags = FBINFO_FLAG_DEFAULT;
#endif
		sis_fb_info->var = ivideo->default_var;
		sis_fb_info->fix = ivideo->sisfb_fix;
		sis_fb_info->screen_base = ivideo->video_vbase + ivideo->video_offset;
		sis_fb_info->fbops = &sisfb_ops;
		sisfb_get_fix(&sis_fb_info->fix, -1, sis_fb_info);
		sis_fb_info->pseudo_palette = ivideo->pseudo_palette;

		fb_alloc_cmap(&sis_fb_info->cmap, 256 , 0);
#endif		/* 2.6 */

		printk(KERN_DEBUG "sisfb: Initial vbflags 0x%x\n", (int)ivideo->vbflags);

#ifdef CONFIG_MTRR
		ivideo->mtrr = mtrr_add(ivideo->video_base, ivideo->video_size,
					MTRR_TYPE_WRCOMB, 1);
		if(ivideo->mtrr < 0) {
			printk(KERN_DEBUG "sisfb: Failed to add MTRRs\n");
		}
#endif

		if(register_framebuffer(sis_fb_info) < 0) {
			printk(KERN_ERR "sisfb: Fatal error: Failed to register framebuffer\n");
			ret = -EINVAL;
			iounmap(ivideo->mmio_vbase);
			goto error_0;
		}

		ivideo->registered = 1;

		/* Enlist us */
		ivideo->next = card_list;
		card_list = ivideo;

#ifdef SIS_OLD_CONFIG_COMPAT
		{
		int ret;
		/* Our ioctls are all "32/64bit compatible" */
		ret =  register_ioctl32_conversion(FBIO_ALLOC,             NULL);
		ret |= register_ioctl32_conversion(FBIO_FREE,              NULL);
		ret |= register_ioctl32_conversion(FBIOGET_VBLANK,         NULL);
		ret |= register_ioctl32_conversion(SISFB_GET_INFO_SIZE,    NULL);
		ret |= register_ioctl32_conversion(SISFB_GET_INFO,         NULL);
		ret |= register_ioctl32_conversion(SISFB_GET_TVPOSOFFSET,  NULL);
		ret |= register_ioctl32_conversion(SISFB_SET_TVPOSOFFSET,  NULL);
		ret |= register_ioctl32_conversion(SISFB_SET_LOCK,         NULL);
		ret |= register_ioctl32_conversion(SISFB_GET_VBRSTATUS,    NULL);
		ret |= register_ioctl32_conversion(SISFB_GET_AUTOMAXIMIZE, NULL);
		ret |= register_ioctl32_conversion(SISFB_SET_AUTOMAXIMIZE, NULL);
		ret |= register_ioctl32_conversion(SISFB_COMMAND,          NULL);
		if(ret)
			printk(KERN_ERR
				"sisfb: Error registering ioctl32 translations\n");
		else
			ivideo->ioctl32registered = 1;
		}
#endif

		printk(KERN_INFO "sisfb: 2D acceleration is %s, y-panning %s\n",
			ivideo->sisfb_accel ? "enabled" : "disabled",
			ivideo->sisfb_ypan  ?
				(ivideo->sisfb_max ? "enabled (auto-max)" :
						"enabled (no auto-max)") :
									"disabled");


		printk(KERN_INFO "fb%d: %s frame buffer device version %d.%d.%d\n",
			sis_fb_info->node, ivideo->myid, VER_MAJOR, VER_MINOR, VER_LEVEL);

		printk(KERN_INFO "sisfb: Copyright (C) 2001-2005 Thomas Winischhofer\n");

	}	/* if mode = "none" */

	return 0;
}

Generated by GNU enscript 1.6.4.