From c614ed4cfd0eb732f900bc457cd4f141b733f613 Mon Sep 17 00:00:00 2001 From: Li-Ta Lo Date: Tue, 3 Sep 2002 02:56:32 +0000 Subject: [PATCH] added kernel patch and config file for 2.4.19 --- src/kernel_patches/config-2.4.19-sis | 609 ++ src/kernel_patches/linux-2.4.19-sis.patch | 8092 +++++++++++++++++++++ 2 files changed, 8701 insertions(+) create mode 100644 src/kernel_patches/config-2.4.19-sis create mode 100644 src/kernel_patches/linux-2.4.19-sis.patch diff --git a/src/kernel_patches/config-2.4.19-sis b/src/kernel_patches/config-2.4.19-sis new file mode 100644 index 0000000000..a42325a697 --- /dev/null +++ b/src/kernel_patches/config-2.4.19-sis @@ -0,0 +1,609 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_X86=y +CONFIG_ISA=y +# CONFIG_SBUS is not set +CONFIG_UID16=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# Processor type and features +# +# CONFIG_M386 is not set +# CONFIG_M486 is not set +# CONFIG_M586 is not set +CONFIG_M586TSC=y +# CONFIG_M586MMX is not set +# CONFIG_M686 is not set +# CONFIG_MPENTIUMIII is not set +# CONFIG_MPENTIUM4 is not set +# CONFIG_MK6 is not set +# CONFIG_MK7 is not set +# CONFIG_MELAN is not set +# CONFIG_MCRUSOE is not set +# CONFIG_MWINCHIPC6 is not set +# CONFIG_MWINCHIP2 is not set +# CONFIG_MWINCHIP3D is not set +# CONFIG_MCYRIXIII is not set +CONFIG_X86_WP_WORKS_OK=y +CONFIG_X86_INVLPG=y +CONFIG_X86_CMPXCHG=y +CONFIG_X86_XADD=y +CONFIG_X86_BSWAP=y +CONFIG_X86_POPAD_OK=y +# CONFIG_RWSEM_GENERIC_SPINLOCK is not set +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_X86_L1_CACHE_SHIFT=5 +CONFIG_X86_USE_STRING_486=y +CONFIG_X86_ALIGNMENT_16=y +CONFIG_X86_TSC=y +CONFIG_X86_PPRO_FENCE=y +CONFIG_X86_MCE=y +# CONFIG_TOSHIBA is not set +# CONFIG_I8K is not set +# CONFIG_MICROCODE is not set +# CONFIG_X86_MSR is not set +# CONFIG_X86_CPUID is not set +CONFIG_NOHIGHMEM=y +# CONFIG_HIGHMEM4G is not set +# CONFIG_HIGHMEM64G is not set +# CONFIG_MATH_EMULATION is not set +# CONFIG_MTRR is not set +# CONFIG_SMP is not set +# CONFIG_X86_UP_APIC is not set + +# +# General setup +# +CONFIG_NET=y +CONFIG_PCI=y +# CONFIG_PCI_GOBIOS is not set +CONFIG_PCI_GODIRECT=y +# CONFIG_PCI_GOANY is not set +CONFIG_PCI_DIRECT=y +CONFIG_PCI_NAMES=y +# CONFIG_EISA is not set +# CONFIG_MCA is not set +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set +# CONFIG_HOTPLUG_PCI is not set +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_PM is not set +# CONFIG_APM_IGNORE_USER_SUSPEND is not set +# CONFIG_APM_DO_ENABLE is not set +# CONFIG_APM_CPU_IDLE is not set +# CONFIG_APM_DISPLAY_BLANK is not set +# CONFIG_APM_RTC_IS_GMT is not set +# CONFIG_APM_ALLOW_INTS is not set +# CONFIG_APM_REAL_MODE_POWER_OFF is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set + +# +# Appletalk devices +# +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# ATA/IDE/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_IDE is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set +# CONFIG_BLK_DEV_COMMERIAL is not set +CONFIG_BLK_DEV_IDECD=y +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_RZ1000 is not set +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_PCI_WIP is not set +CONFIG_BLK_DEV_ADMA=y +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_PDC202XX is not set +# CONFIG_BLK_DEV_SVWKS is not set +CONFIG_BLK_DEV_SIS5513=y +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_CHIPSETS is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_IDEDMA_IVB is not set +# CONFIG_DMA_NONPCI is not set +CONFIG_BLK_DEV_IDE_MODES=y +# CONFIG_BLK_DEV_ATARAID is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION_BOOT is not set +# CONFIG_FUSION_ISENSE is not set +# CONFIG_FUSION_CTL is not set +# CONFIG_FUSION_LAN is not set + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +CONFIG_DUMMY=m +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set +# CONFIG_TULIP is not set +# CONFIG_TC35815 is not set +# CONFIG_DE4X5 is not set +# CONFIG_DGRS is not set +# CONFIG_DM9102 is not set +# CONFIG_EEPRO100 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +CONFIG_SIS900=y +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Input core support +# +# CONFIG_INPUT is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +CONFIG_MOUSE=y +CONFIG_PSMOUSE=y +# CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set +# CONFIG_MK712_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set + +# +# Input core support is needed for gameports +# + +# +# Input core support is needed for joysticks +# +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_AMD_RNG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_SONYPI is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_MWAVE is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=y +# CONFIG_REISERFS_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_FAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +CONFIG_TMPFS=y +CONFIG_RAMFS=y +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_SUNRPC is not set +# CONFIG_LOCKD is not set +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_ZISOFS_FS is not set +# CONFIG_ZLIB_FS_INFLATE is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SMB_NLS is not set +# CONFIG_NLS is not set + +# +# Console drivers +# +CONFIG_VGA_CONSOLE=y +CONFIG_VIDEO_SELECT=y +# CONFIG_MDA_CONSOLE is not set + +# +# Frame-buffer support +# +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FB_RIVA is not set +# CONFIG_FB_CLGEN is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_PM3 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_VESA is not set +# CONFIG_FB_VGA16 is not set +# CONFIG_FB_HGA is not set +CONFIG_VIDEO_SELECT=y +# CONFIG_FB_MATROX is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set + +# +# SiSFB Lite support +# +CONFIG_FB_SIS=y +CONFIG_FB_SIS_300=y +CONFIG_FB_SIS_315=y +# CONFIG_FB_SIS_VIDEO is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB16=y +CONFIG_FBCON_CFB32=y +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +# CONFIG_FBCON_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Sound +# +CONFIG_SOUND=y +# CONFIG_SOUND_BT878 is not set +# CONFIG_SOUND_CMPCI is not set +# CONFIG_SOUND_EMU10K1 is not set +# CONFIG_SOUND_FUSION is not set +# CONFIG_SOUND_CS4281 is not set +# CONFIG_SOUND_ES1370 is not set +CONFIG_SOUND_ES1371=y +# CONFIG_SOUND_ESSSOLO1 is not set +# CONFIG_SOUND_MAESTRO is not set +# CONFIG_SOUND_MAESTRO3 is not set +# CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_RME96XX is not set +# CONFIG_SOUND_SONICVIBES is not set +# CONFIG_SOUND_TRIDENT is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_VIA82CXXX is not set +# CONFIG_SOUND_OSS is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# Bluetooth support +# +# CONFIG_BLUEZ is not set + +# +# Kernel hacking +# +# CONFIG_DEBUG_KERNEL is not set + +# +# LinuxBIOS +# +CONFIG_LINUXBIOS=y + +# +# Linuxbios Options +# +CONFIG_LINUXBIOS_PM=y +CONFIG_LINUXBIOS_PM_SIS503=y +# CONFIG_LINUXBIOS_PM_PIIX4E is not set diff --git a/src/kernel_patches/linux-2.4.19-sis.patch b/src/kernel_patches/linux-2.4.19-sis.patch new file mode 100644 index 0000000000..cfeaae4b64 --- /dev/null +++ b/src/kernel_patches/linux-2.4.19-sis.patch @@ -0,0 +1,8092 @@ +diff -urN linux-2.4.19/arch/i386/Linuxbios.in linux-2.4.19-linuxbios/arch/i386/Linuxbios.in +--- linux-2.4.19/arch/i386/Linuxbios.in Thu Jan 1 08:00:00 1970 ++++ linux-2.4.19-linuxbios/arch/i386/Linuxbios.in Mon Sep 2 13:29:06 2002 +@@ -0,0 +1,8 @@ ++mainmenu_option next_comment ++comment 'Linuxbios Options' ++bool 'Linuxbios Power Management support?' CONFIG_LINUXBIOS_PM ++if [ "$CONFIG_LINUXBIOS_PM" = "y" ]; then ++ bool ' SIS 503 support?' CONFIG_LINUXBIOS_PM_SIS503 ++ bool ' PIIX4E support?' CONFIG_LINUXBIOS_PM_PIIX4E ++fi ++endmenu +diff -urN linux-2.4.19/arch/i386/config.in linux-2.4.19-linuxbios/arch/i386/config.in +--- linux-2.4.19/arch/i386/config.in Sat Aug 3 08:39:42 2002 ++++ linux-2.4.19-linuxbios/arch/i386/config.in Mon Sep 2 13:29:06 2002 +@@ -426,3 +426,13 @@ + fi + + endmenu ++ ++mainmenu_option next_comment ++comment 'LinuxBIOS' ++ ++tristate 'LinuxBIOS Support' CONFIG_LINUXBIOS ++if [ "$CONFIG_LINUXBIOS" != "n" ]; then ++ source arch/i386/Linuxbios.in ++fi ++ ++endmenu +diff -urN linux-2.4.19/arch/i386/kernel/process.c linux-2.4.19-linuxbios/arch/i386/kernel/process.c +--- linux-2.4.19/arch/i386/kernel/process.c Sat Aug 3 08:39:42 2002 ++++ linux-2.4.19-linuxbios/arch/i386/kernel/process.c Mon Sep 2 13:29:06 2002 +@@ -50,6 +50,158 @@ + + #include + ++#ifdef CONFIG_LINUXBIOS_PM ++#include ++#ifdef CONFIG_LINUXBIOS_PM_SIS503 ++void ++sis503_reset(struct pci_dev *dev) ++{ ++ unsigned char b; ++ unsigned short acpi_base; ++ ++ printk(KERN_ERR __FUNCTION__ ": starting reset operation. \n"); ++ ++ /* Enable ACPI by set B7 on Reg 0x40, LPC */ ++ pci_read_config_byte(dev, 0x40, &b); ++ pci_write_config_byte(dev, 0x40, b | 0x80); ++ printk(KERN_ERR __FUNCTION__ ": enabled ACPI. \n"); ++ ++ /* get the ACPI base address for register 0x74,0x75 of LPC */ ++ pci_read_config_word(dev, 0x74, &acpi_base); ++ printk(KERN_ERR __FUNCTION__ ":acpi base: %x\n", acpi_base); ++ ++ /* Set software watchdog timer init value */ ++ outb(0x03, 0x4a + acpi_base); ++ printk(KERN_ERR __FUNCTION__ ": set the dog. \n"); ++ ++ printk(KERN_ERR __FUNCTION__ ": enabling dog. \n"); ++ /* Software watchdog enable, issue PCIRST# when time expire */ ++ outb(0x8f, 0x4b + acpi_base); ++ ++ printk(KERN_ERR __FUNCTION__ ": We should reset soon. \n"); ++} ++ ++void ++sis503_off(struct pci_dev *dev) ++{ ++ unsigned char b; ++ unsigned short acpi_base; ++ ++ printk(KERN_ERR __FUNCTION__ ": starting reset operation. \n"); ++ /* Enable ACPI by set B7 on Reg 0x40, LPC */ ++ pci_read_config_byte(dev, 0x40, &b); ++ pci_write_config_byte(dev, 0x40, b | 0x80); ++ printk(KERN_ERR __FUNCTION__ ": enabled ACPI. \n"); ++ ++ /* get the ACPI base address for register 0x74,0x75 of LPC */ ++ pci_read_config_word(dev, 0x74, &acpi_base); ++ printk (KERN_ERR __FUNCTION__ ":acpi base: %x\n", acpi_base); ++ ++ /* ACPI Register 5, Bit 10-12, Sleeping Type, ++ set to 101 -> S5, soft_off */ ++ outb(0x14, 0x05 + acpi_base); ++ printk(KERN_ERR __FUNCTION__ ": DONE setting sleep type. \n"); ++ ++ /* ACPI Register 5, Bit 13, Sleep Enable */ ++ outb(0x20 | 0x14, 0x05 + acpi_base); ++ printk(KERN_ERR __FUNCTION__ ": DONE sleep enable. \n"); ++} ++#endif // CONFIG_LINUXBIOS_PM_SIS503 ++#ifdef CONFIG_LINUXBIOS_PM_PIIX4E ++void ++piix4e_reset(struct pci_dev *dev) ++{ ++ // simple on this part. outb 0x6 to 0xcf9 ++ ++ printk(KERN_ERR __FUNCTION__ ": starting reset operation. \n"); ++ outb(0x6, 0xcf9); ++ printk(KERN_ERR __FUNCTION__ ": We should reset soon. \n"); ++} ++ ++void ++piix4e_off(struct pci_dev *dev) ++{ ++ unsigned char b; ++ unsigned short acpi_base; ++ ++ printk(KERN_ERR __FUNCTION__ ": no power off on this chip! \n"); ++} ++#endif ++struct pci_dev * pci_find_device(unsigned int vendor, unsigned int device, ++ const struct pci_dev *from); ++ ++struct linuxbios_control { ++ u_short vendor, device; ++ void (*poweroff)(struct pci_dev *); ++ void (*reset)(struct pci_dev *); ++}; ++ ++struct linuxbios_control controls[] = { ++#ifdef CONFIG_LINUXBIOS_PM_SIS503 ++ {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, sis503_off, sis503_reset}, ++#endif ++#ifdef CONFIG_LINUXBIOS_PM_PIIX4E ++ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, ++ piix4e_off, piix4e_reset}, ++#endif ++ {0} ++}; ++ ++struct linuxbios_control *findcontrol(struct pci_dev **d) ++{ ++ struct linuxbios_control *lb = controls, *retval = 0; ++ int i; ++ ++ printk(KERN_ERR __FUNCTION__ ": Find vendor 0x%x device 0x%x\n", ++ lb->vendor, lb->device); ++ for(lb = controls, i = 0; ++ (i < sizeof(controls)/sizeof(controls[0])) && (! retval); ++ i++, lb++) ++ { ++ *d = pci_find_device(lb->vendor, lb->device, 0); ++ if (*d) ++ retval = lb; ++ } ++ ++ printk(KERN_ERR __FUNCTION__ ": result of find is %p\n", retval); ++ return retval; ++} ++ ++void ++linuxbios_poweroff(void) ++{ ++ struct linuxbios_control *lb = 0; ++ struct pci_dev *dev; ++ ++ printk(KERN_ERR __FUNCTION__ ": find an lb\n"); ++ lb = findcontrol(&dev); ++ ++ printk(KERN_ERR __FUNCTION__ ": found lb %p, call %p\n", ++ lb, lb ? lb->poweroff : 0); ++ if (lb && (lb->poweroff)) ++ lb->poweroff(dev); ++ printk(KERN_ERR __FUNCTION__ ": Returning? Can't happen, I thought?\n"); ++} ++ ++void ++linuxbios_reset(void) ++{ ++ struct linuxbios_control *lb = 0; ++ struct pci_dev *dev; ++ ++ printk(KERN_ERR __FUNCTION__ ": find an lb\n"); ++ lb = findcontrol(&dev); ++ ++ printk(KERN_ERR __FUNCTION__ ": found lb %p, call %p\n", ++ lb, lb ? lb->reset : 0); ++ if (lb && (lb->reset)) ++ lb->reset(dev); ++ printk(KERN_ERR __FUNCTION__ ": Returning? Can't happen, I thought?\n"); ++} ++ ++#endif // CONFIG_LINUXBIOS_PM ++ ++ + asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); + + int hlt_counter; +@@ -401,6 +553,9 @@ + smp_send_stop(); + disable_IO_APIC(); + #endif ++#ifdef CONFIG_LINUXBIOS_PM ++ linuxbios_reset(); ++#endif + + if(!reboot_thru_bios) { + /* rebooting needs to touch the page at absolute addr 0 */ +@@ -430,6 +585,9 @@ + { + if (pm_power_off) + pm_power_off(); ++#ifdef CONFIG_LINUXBIOS_PM ++ linuxbios_poweroff(); ++#endif + } + + extern void show_trace(unsigned long* esp); +diff -urN linux-2.4.19/drivers/ide/sis5513.c linux-2.4.19-linuxbios/drivers/ide/sis5513.c +--- linux-2.4.19/drivers/ide/sis5513.c Sat Aug 3 08:39:44 2002 ++++ linux-2.4.19-linuxbios/drivers/ide/sis5513.c Mon Sep 2 14:20:46 2002 +@@ -180,6 +180,7 @@ + { "SiS640", PCI_DEVICE_ID_SI_640, ATA_66, SIS5513_LATENCY }, + { "SiS630", PCI_DEVICE_ID_SI_630, ATA_66, SIS5513_LATENCY }, + { "SiS620", PCI_DEVICE_ID_SI_620, ATA_66, SIS5513_LATENCY }, ++ { "SiS550", PCI_DEVICE_ID_SI_550, ATA_100a, SIS5513_LATENCY }, + { "SiS540", PCI_DEVICE_ID_SI_540, ATA_66, 0}, + { "SiS530", PCI_DEVICE_ID_SI_530, ATA_66, 0}, + { "SiS5600", PCI_DEVICE_ID_SI_5600, ATA_33, 0}, +diff -urN linux-2.4.19/drivers/video/Config.in linux-2.4.19-linuxbios/drivers/video/Config.in +--- linux-2.4.19/drivers/video/Config.in Sat Aug 3 08:39:45 2002 ++++ linux-2.4.19-linuxbios/drivers/video/Config.in Mon Sep 2 15:26:00 2002 +@@ -141,11 +141,17 @@ + fi + tristate ' ATI Radeon display support (EXPERIMENTAL)' CONFIG_FB_RADEON + tristate ' ATI Rage128 display support (EXPERIMENTAL)' CONFIG_FB_ATY128 +- tristate ' SIS acceleration (EXPERIMENTAL)' CONFIG_FB_SIS ++ ++ mainmenu_option next_comment ++ comment 'SiSFB Lite support' ++ tristate ' SIS FB Lite' CONFIG_FB_SIS + if [ "$CONFIG_FB_SIS" != "n" ]; then +- bool ' SIS 630/540/730 support' CONFIG_FB_SIS_300 +- bool ' SIS 315H/315 support' CONFIG_FB_SIS_315 ++ # bool ' SIS 630/540/730 support' CONFIG_FB_SIS_300 ++ # bool ' SIS 315H/315 support' CONFIG_FB_SIS_315 ++ source drivers/video/sis/Config.in + fi ++ endmenu ++ + tristate ' NeoMagic display support (EXPERIMENTAL)' CONFIG_FB_NEOMAGIC + tristate ' 3Dfx Banshee/Voodoo3 display support (EXPERIMENTAL)' CONFIG_FB_3DFX + tristate ' 3Dfx Voodoo Graphics (sst1) support (EXPERIMENTAL)' CONFIG_FB_VOODOO1 +diff -urN linux-2.4.19/drivers/video/sis/Config.in linux-2.4.19-linuxbios/drivers/video/sis/Config.in +--- linux-2.4.19/drivers/video/sis/Config.in Thu Jan 1 08:00:00 1970 ++++ linux-2.4.19-linuxbios/drivers/video/sis/Config.in Mon Sep 2 17:23:31 2002 +@@ -0,0 +1,7 @@ ++ bool ' SIS 630/540/730 support' CONFIG_FB_SIS_300 ++ bool ' SIS 315H/315 support' CONFIG_FB_SIS_315 ++ tristate ' SIS Video Overlay Acceleration (EXPERIMENTAL)' CONFIG_FB_SIS_VIDEO ++ if [ "$CONFIG_FB_SIS_VIDEO" != "n" ]; then ++ bool ' MGA Video API support' CONFIG_FB_SIS_MGA_VID ++ bool ' SyncFB API support' CONFIG_FB_SIS_SYNCFB ++ fi +\ No newline at end of file +diff -urN linux-2.4.19/drivers/video/sis/Makefile linux-2.4.19-linuxbios/drivers/video/sis/Makefile +--- linux-2.4.19/drivers/video/sis/Makefile Sat Nov 10 06:11:14 2001 ++++ linux-2.4.19-linuxbios/drivers/video/sis/Makefile Mon Sep 2 17:23:10 2002 +@@ -4,11 +4,25 @@ + + O_TARGET := sisfb.o + +-export-objs := sis_main.o ++obj-$(CONFIG_FB_SIS) += sisfb_lite.o sisfb_utils.o sisfb_accel.o sisfb_legacy_init.o ++obj-$(CONFIG_FB_SIS_VIDEO) += sisfb_video.o sisfb_overlay.o ++obj-$(CONFIG_FB_SIS_MGA_VID) += sisfb_mgavid.o ++obj-$(CONFIG_FB_SIS_SYNCFB) += sisfb_syncfb.o ++ ++ ++obj-$(CONFIG_FB_SIS_300) += sisfb_300_init.o sisfb_300_core.o sisfb_530_accel.o ++ifneq ($(CONFIG_FB_SIS_VIDEO),n) ++ obj-$(CONFIG_FB_SIS_VIDEO) += sisfb_300_overlay.o ++endif ++ ++obj-$(CONFIG_FB_SIS_315) += sisfb_315_init.o sisfb_300_core.o sisfb_315_accel.o ++ifneq ($(CONFIG_FB_SIS_VIDEO),n) ++ obj-$(CONFIG_FB_SIS_VIDEO) += sisfb_315_overlay.o ++endif + +-obj-y := sis_main.o init.o init301.o + obj-m := $(O_TARGET) + + include $(TOPDIR)/Rules.make + +- ++clean: ++ rm -f core *.o *.a *.s +diff -urN linux-2.4.19/drivers/video/sis/sisfb_300_core.c linux-2.4.19-linuxbios/drivers/video/sis/sisfb_300_core.c +--- linux-2.4.19/drivers/video/sis/sisfb_300_core.c Thu Jan 1 08:00:00 1970 ++++ linux-2.4.19-linuxbios/drivers/video/sis/sisfb_300_core.c Mon Sep 2 17:23:10 2002 +@@ -0,0 +1,564 @@ ++/* sisfb_300_core.c: Setting Video Mode for SiS 540/550/630/730 Integrated VGA ++ * ++ * Copyright 2001 Ollie Lho ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ * This driver is implemented by the Author for his own personal interests and is NOT a ++ * commitment NOR supported officially by Silicon Integrated Systems Corp. Please direct ++ * any bug report/question to the Author and don't bother SiS Technical Support Personell. ++ * ++ * ++ * Reference: ++ * 1. Glamour Design Guideline V0.8 ++ * 2. Programmer's Guide to the EGA, VGA, and Super VGA Card. Third Edition, ++ * Richard F. Ferraro, Addison-Welsey, Aug. 1994 ++ * 3. sis86c201.c in XFree86 3.3.6 ++ */ ++ ++#include "sisfb_lite.h" ++#include "sisfb_300_core.h" ++ ++static void sisfb_get_clock(struct sisfb_info * sisfb, struct sisfb_clock_param * clock, int which); ++static void sisfb_set_clock(struct sisfb_info * sisfb, struct sisfb_clock_param * clock, int which); ++static void sisfb_set_memory_clocks(struct sisfb_info * sisfb); ++static int sisfb_get_memory_size(struct sisfb_info * sisfb); ++static void sisfb_set_crt1_crtc_regs(struct sisfb_info * sisfb, struct sisfb_par * par); ++static void sisfb_set_crt1_mode_regs(struct sisfb_info * sisfb, struct sisfb_par * par); ++static void sisfb_set_crt1_pitch(struct sisfb_info * sisfb, struct sisfb_par * par); ++static void sisfb_set_crt1_offset(struct sisfb_info * sisfb, struct sisfb_par * par); ++static void sisfb_set_crt1_vclk(struct sisfb_info * sisfb, struct sisfb_par * par); ++static int sisfb_set_fifo_thresholds(struct sisfb_info * sisfb, struct sisfb_par * par); ++ ++/** ++ * sisfb_get_clock: - Read the clock generator parameters ++ * @sisfb: SiS Frame Buffer structure ++ * @clock: Paramters of the clock generator (return) ++ * @which: Which clock generator to be read. ++ * ++ * Read the clock generator parameters to @clock form the hardware. The desired ++ * clock generator is specified by @which. Valid values are MCLK for memory clock, ++ * VCLK for video dot clock and ECLK for 3D engine. ++ */ ++static void ++sisfb_get_clock(struct sisfb_info * sisfb, struct sisfb_clock_param * clock, int which) ++{ ++ u8 data; ++ ++ /* get divider and numerator */ ++ data = sisfb_get_seq_reg(sisfb, which); ++ clock->divider = ((data & 0x80) >> 7) + 1; ++ clock->numerator = (data & ~0x80) + 1; ++ ++ /* get denumerator and post scalar */ ++ data = sisfb_get_seq_reg(sisfb, which + 1); ++ clock->denumerator = (data & 0x1F) + 1; ++ clock->post_scalar = ((data & 0xE0) >> 5) + 1; ++ ++ /* get VCO gain */ ++ data = sisfb_get_seq_reg(sisfb, which + 2); ++ clock->vco_gain = (data >> 7); ++} ++ ++/** ++ * sisfb_set_clock: - Set the clock generator parameters ++ * @sisfb: SiS Frame Buffer structure ++ * @clock: Paramters of the clock generator ++ * @which: Which clock generator to be read. ++ * ++ * Set the clock generator parameters @clock to the hardware. The desired clock ++ * generator is specified by @which. Valid values are MCLK for memory clock, ++ * VCLK for video dot clock and ECLK for 3D engine. ++ */ ++static void ++sisfb_set_clock(struct sisfb_info * sisfb, struct sisfb_clock_param * clock, int which) ++{ ++ u8 data; ++ ++ /* set divider and numerator */ ++ data = (clock->numerator - 1) & 0x7F; ++ data |= (clock->divider - 1) ? 0x80 : 0x00; ++ sisfb_set_seq_reg(sisfb, which, data); ++ ++ /* set denumerator and post scalar */ ++ data = (clock->denumerator - 1) & 0x1F; ++ data |= (clock->post_scalar - 1) << 5; ++ sisfb_set_seq_reg(sisfb, which + 1, data); ++ ++ /* set VCO gain */ ++ data = clock->vco_gain ? 0x80 : 0x00; ++ sisfb_set_seq_reg(sisfb, which + 2, data); ++} ++ ++/** ++ * sisfb_set_memory_clocks: - Set memory bus clock rate ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Set the memory clocks for VGA core. Form SiS 300 and up, the VGA core has ++ * 2 independent clocks for 2D and 3D engines. We can set them to different ++ * rates seperatly. ++ */ ++extern unsigned long mclk, eclk; ++static void __devinit ++sisfb_set_memory_clocks(struct sisfb_info * sisfb) ++{ ++ struct sisfb_clock_param clock; ++ ++ /* set the clock rate according to the option */ ++ sisfb_calc_clock_param(&clock, mclk); ++ sisfb_set_clock(sisfb, &clock, SIS300_MCLK); ++ ++ sisfb_calc_clock_param(&clock, eclk); ++ sisfb_set_clock(sisfb, &clock, SIS300_ECLK); ++ ++ /* read the clock rate back and show to user */ ++ sisfb_get_clock(sisfb, &clock, SIS300_MCLK); ++ printk(KERN_INFO "sisfb_lite: 2D Memory Clock = %6ld KHz\n", ++ sisfb_calc_clock_freq(&clock)); ++ ++ sisfb_get_clock(sisfb, &clock, SIS300_ECLK); ++ printk(KERN_INFO "sisfb_lite: 3D Memory Clock = %6ld KHz\n", ++ sisfb_calc_clock_freq(&clock)); ++} ++/** ++ * sisfb_config_memory: - Configure Framebuffer Memory ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Return 0 on Success, -ENODEV on Failure ++ * ++ * Configure the frame buffer memory. ++ * If Memory Type Range Registers (MTRR) is configured in the kernel. We set the ++ * Frame Buffer area as "Write Combine" to boost the perfromance. ++ */ ++int __devinit ++sisfb_config_memory(struct sisfb_info * sisfb) ++{ ++ int ret; ++ u8 data = 0; ++ ++ //sisfb_set_memory_clocks(sisfb); ++ ++ /* Check if we have SMA configured correctly and HOW MUCH */ ++ if ((ret = sisfb_get_memory_size(sisfb)) < 0) ++ return ret; ++ ++ /* Enable PCI Relocated IO, Memory Mapped IO and Linear Framebuffer Addressing */ ++ //data = SIS300_PCI_VGA_MEM_DISABLE | SIS300_PCI_VGA_IO_DISABLE; ++ data = SIS300_PCI_PCI_IO_ENABLE | SIS300_PCI_PCI_MMIO_ENABLE; ++ data |= SIS300_PCI_LINEAR_ENABLE; ++ sisfb_set_seq_reg(sisfb, SIS300_PCI_ADDR_SET, data); ++ ++ /* ioremap MMIO and Framebuffer Area */ ++ sisfb->video_base_virt = ++ ioremap(sisfb->video_base_phy, sisfb->video_size_virt); ++ sisfb->mmio_base_virt = ++ ioremap(sisfb->mmio_base_phy, sisfb->mmio_size_phy); ++ ++ printk(KERN_INFO "sisfb_lite: framebuffer at 0x%lx, mapped to 0x%p, size %lu KB\n", ++ sisfb->video_base_phy, (char *) sisfb->video_base_virt, ++ sisfb->video_size_virt / 1024); ++ ++#ifdef CONFIG_MTRR ++ /* Use MTRR to boost performance */ ++ sisfb->mtrr = mtrr_add(sisfb->video_base_phy, sisfb->video_size_virt, ++ MTRR_TYPE_WRCOMB, 1); ++ if (sisfb->mtrr >= 0) { ++ printk(KERN_INFO "sisfb_lite: Turned on MTRR Write Combine for framebuffer\n"); ++ } ++#endif /* CONFIG_MTRR */ ++ ++ return 0; ++} ++ ++/** ++ * sisfb_set_crt1_crtc_regs: - Set CRTC Registers of CRT1 ++ * @sisfb: SiS Frame Buffer structure ++ * @par: Haedware parameters for CRT1 ++ * ++ * Historically, CRTC registers defined by standard VGA accepts values ++ * (in units of characters or whatever) slightly different from the ++ * "physical" ones (in units of dots), so we have to transform hardware ++ * paramters before programming CRTC. Those CRTC registers alos have different ++ * "overflow" bits due to higher and higher screen resolution supported along ++ * the evloution process. These overflow bits are defined differently across ++ * different generations of SiS VGA core implementation. ++ */ ++static void ++sisfb_set_crt1_crtc_regs(struct sisfb_info * sisfb, struct sisfb_par * par) ++{ ++ u16 htotal, hdispend, hsyncstart, hsyncend, hblankstart, hblankend; ++ u16 vtotal, vdispend, vsyncstart, vsyncend, vblankstart, vblankend; ++ u16 overflow, overflow_h1, overflow_h2, overflow_v; ++ ++ /* first convert 'par' to "screen" unit */ ++ htotal = (par->htotal >> 3) - 5; ++ hdispend = (par->hdispend >> 3) - 1; ++ hblankstart = (par->hsyncstart >> 3) - 1; ++ hblankend = (par->hsyncend >> 3); ++ hsyncstart = (par->hsyncstart >> 3); ++ hsyncend = (par->hsyncend >> 3); ++ ++ vtotal = par->vtotal - 2; ++ vdispend = par->vdispend - 1; ++ vsyncstart = par->vsyncstart; ++ vsyncend = par->vsyncend; ++ vblankstart = par->vsyncstart; ++ vblankend = par->vsyncend + 1; ++ ++ /* the "overlow" bits (8:15) of the screen parameters are spread all over ++ * various registers */ ++ overflow = ++ ((vsyncstart & 0x200) >> 2) | /* Bit 7, Vertical Retrace Start Bit 9 */ ++ ((vdispend & 0x200) >> 3) | /* Bit 6, Vertical Display End Bit 9 */ ++ ((vtotal & 0x200) >> 4) | /* Bit 5, Vertical Total Bit 9 */ ++ 0x10 | /* Bit 4, line compare Bit 8 */ ++ ((vblankstart & 0x100) >> 5) | /* Bit 3, Vertical Blank Start Bit 8 */ ++ ((vsyncstart & 0x100) >> 6) | /* Bit 2, Vertical Retrace Start Bit 8 */ ++ ((vdispend & 0x100) >> 7) | /* Bit 1, Vertical Display End Bit 8 */ ++ ((vtotal & 0x100) >> 8); /* Bit 0, Vertical Total Bit 8 */ ++ ++ overflow_v = ++ ((vsyncend & 0x010) << 1) | /* Bit 5, Vertical Retrace End Bit 4 */ ++ ((vblankend & 0x100) >> 4) | /* Bit 4, Vertical Blank End Bit 8 */ ++ ((vsyncstart & 0x400) >> 7) | /* Bit 3, Vertical Retrace Start Bit 10 */ ++ ((vblankstart & 0x400) >> 8) | /* Bit 2, Vertical Blank Start Bit 10 */ ++ ((vdispend & 0x400) >> 9) | /* Bit 1, Vertical Display End Bit 10 */ ++ ((vtotal & 0x400) >> 10); /* Bit 0, Vertical Total Bit 10 */ ++ ++ overflow_h1 = ++ ((hsyncstart & 0x300) >> 2) | /* Bit 6,7 Horizontal Retrace Start Bit 8,9 */ ++ ((hblankstart & 0x300) >> 4) | /* Bit 4,5 Horizontal Blank Start Bit 8,9 */ ++ ((hdispend & 0x300) >> 6) | /* Bit 2,3 Horizontal Display End Bit 8,9 */ ++ ((htotal & 0x300) >> 8); /* Bit 0,1 Horizontal Total Bit 8,9 */ ++ ++ overflow_h2 = ++ ((hsyncend & 0x020) >> 3) | /* Bit 2 Horizontal Retrace End Bit 5 */ ++ ((hblankend & 0x0C0) >> 6); /* Bit 0,1 Horizontal Blank End Bit 6,7 */ ++ ++ /* write 'par' to hardware registers, Standard VGA part, low order bits */ ++ sisfb_set_crtc_reg(sisfb, 0x00, htotal); ++ sisfb_set_crtc_reg(sisfb, 0x01, hdispend); ++ sisfb_set_crtc_reg(sisfb, 0x02, hblankstart); ++ sisfb_set_crtc_reg(sisfb, 0x03, ++ 0x80 | /* Bit 7, Enable Vertical Retrace Start/End */ ++ (hblankend & 0x1f)); /* Bit 0:4, Horizontal Blank End Bit 0:4 */ ++ ++ sisfb_set_crtc_reg(sisfb, 0x04, hsyncstart); ++ if (par->interlace == 1) { ++ sisfb_set_crtc_reg(sisfb, 0x19, hsyncstart); ++ sisfb_set_crtc_reg(sisfb, 0x1a, hsyncstart >> 8); ++ } ++ ++ sisfb_set_crtc_reg(sisfb, 0x05, ++ (hblankend & 0x20) << 2 | /* Bit 7, Horizontal Blank End Bit 5 */ ++ (hsyncend & 0x1f)); /* Bit 0:4, Horizontal Retrace End Bit 0:4 */ ++ sisfb_set_crtc_reg(sisfb, 0x06, vtotal); ++ sisfb_set_crtc_reg(sisfb, 0x09, ++ 0x40 | /* Bit 6, line compare Bit 9 */ ++ (vblankstart & 0x200) >> 4); /* Bit 5, Vertical Blank Start Bit 9 */ ++ sisfb_set_crtc_reg(sisfb, 0x10, vsyncstart); ++ sisfb_set_crtc_reg(sisfb, 0x11, (vsyncend & 0x0F) | 0x20); ++ sisfb_set_crtc_reg(sisfb, 0x12, vdispend); ++ sisfb_set_crtc_reg(sisfb, 0x15, vblankstart); ++ sisfb_set_crtc_reg(sisfb, 0x16, vblankend); ++ ++ /* Standard VGA part, overflow bits */ ++ sisfb_set_crtc_reg(sisfb, 0x07, overflow); ++ ++ /* Extended Registers, overflow bits */ ++ sisfb_set_seq_reg(sisfb, 0x0A, overflow_v); ++ sisfb_set_seq_reg(sisfb, 0x0B, overflow_h1); ++ sisfb_set_seq_reg(sisfb, 0x0C, overflow_h2); ++} ++ ++/** ++ * sisfb_set_crt1_mode_regs: - Set misc video mode registers ++ * @sisfb: SiS Frame Buffer structure ++ * @par: hardware specific parameters ++ * ++ * Set color depth and enable 2D engine. The display line width register SR 0x10 ++ * is also enabled. ++ */ ++static void ++sisfb_set_crt1_mode_regs(struct sisfb_info * sisfb, struct sisfb_par * par) ++{ ++ u8 tmp; ++ ++ /* enable Enhanced Graphics Mode and Auto Line Width Counter */ ++ tmp = 0x03; ++ switch (par->bits_per_pixel) { ++ case 32: ++ tmp |= 0x10; ++ break; ++ case 16: ++ tmp |= 0x08; ++ break; ++ case 8: ++ default: ++ break; ++ } ++ ++ if (par->interlace == 1) ++ tmp |= 0x20; ++ ++ sisfb_set_seq_reg(sisfb, 0x06, tmp); ++ ++ /* enable 2D engine */ ++ sisfb_set_seq_reg(sisfb, 0x1E, 0x40); ++} ++ ++/** ++ * sisfb_set_crt1_pitch: - Set screen pitch registers for CRT1 ++ * @sisfb: SiS Frame Buffer structure ++ * @par: hardware specific parameters ++ * ++ * Set the screen pitch registers for CRT1. Screen pitch refers to the memory address ++ * difference between two dots of the same col on two vertically neighboring scan lines. ++ * The CRTC 0x13 is called "offset register" in VGA literatures. SiS VGA also defines ++ * its own screen line width register SR 0x10 which is enabled by Bit 0 of SR 0x06. ++ */ ++static void ++sisfb_set_crt1_pitch(struct sisfb_info * sisfb, struct sisfb_par * par) ++{ ++ u16 pitch = par->line_length >> 3; ++ u8 line_length = ((par->line_length + 63) >> 6) + 1; ++ ++ if (par->interlace == 1) { ++ pitch <<= 1; ++ } ++ ++ /* disable line compare */ ++ sisfb_set_seq_reg(sisfb, 0x0F, 0x08); ++ ++ /* screen pitch, in units of double word */ ++ sisfb_set_crtc_reg(sisfb, 0x13, pitch & 0xFF); ++ sisfb_set_seq_reg(sisfb, 0x0E, (pitch >> 8) & 0x0F); ++ ++ /* display line length, in units of 64 bytes */ ++ sisfb_set_seq_reg(sisfb, 0x10, line_length); ++} ++ ++/** ++ * sisfb_set_crt1_offset: - Set screen start offset register for CRT1 ++ * @sisfb: SiS Frame Buffer structure ++ * @par: hardware specific parameters ++ * ++ * Set the screen start offset registers for CRT1. Screen start offset refers to the ++ * memory address of the pixel (0, 0) on the current vitrual screen. This address ++ * is calculated when the virtual screen is panned by pan_display() or when the var ++ * is changed and decoded by decode_var(). This value is stored in the ++ * par->screen_offset member of the current display. par->screen_offset is in the ++ * unit of byte while the VGA hardware uses Double Word. ++ */ ++static void ++sisfb_set_crt1_offset(struct sisfb_info * sisfb, struct sisfb_par * par) ++{ ++ u32 offset; ++ ++ /* convert offset address from units of byte to double word */ ++ offset = par->screen_offset >> 2; ++ ++ /* set screen start memory address in units of double word, ++ bit 23:16 in SR0D, bit 15:8 in CR0C, bit 7:0 in CR0D */ ++ sisfb_set_crtc_reg(sisfb, 0x0C, offset >> 8); ++ sisfb_set_crtc_reg(sisfb, 0x0D, offset); ++ sisfb_set_seq_reg(sisfb, 0x0D, offset >> 16); ++ ++ /* FixME: SR37 Bit 0 for SiS 315 ?? */ ++} ++ ++/** ++ * sisfb_set_crt1_vclk: - Set video dot clock frequence for CRT1 ++ * @sisfb: SiS Frame Buffer structure ++ * @par: hardware specific parameters ++ * ++ * Select normal clock generator as DCLK source. Set the clock frequence as ++ * specified in @par->dot_clock. Also set the DAC slew rate according to DCLK ++ * frequence. ++ */ ++static void ++sisfb_set_crt1_vclk(struct sisfb_info * sisfb, struct sisfb_par * par) ++{ ++ /* FixME: Use clock_param for par->dot_clock */ ++ u32 vclk = par->dot_clock / 1000; ++ u8 tmp = 0x10, tmp1; ++ struct sisfb_clock_param clock; ++ ++ /* Select normal DCLK clock generator */ ++ sisfb_set_seq_reg(sisfb, 0x31, 0x00); ++ ++ /* set vclk frequence, FixME: do error check */ ++ sisfb_calc_clock_param(&clock, vclk); ++ sisfb_set_clock(sisfb, &clock, SIS300_DCLK); ++ ++ sisfb_get_clock(sisfb, &clock, SIS300_DCLK); ++ printk(KERN_INFO "sisfb_lite: Video Dot Clock = %6ld KHz\n", ++ sisfb_calc_clock_freq(&clock)); ++ ++ /* set DAC slew rate, the statesment in Glamour Design Guideline V.08 ++ * is totally contracted to the true hardware implementation */ ++ if (vclk < 100000) ++ tmp |= 0x03; ++ else if (vclk < 200000) ++ tmp |= 0x02; ++ else if (vclk < 250000) ++ tmp |= 0x01; ++ ++ /* FixME: Set half DCLK if VCLK is too high, ++ * need to be updated for SiS 315 */ ++ if (vclk > 150000) { ++ tmp |= 0x80; ++ tmp1 = 0x08; ++ } else { ++ tmp &= 0x7F; ++ tmp1 = 0x00; ++ } ++ ++ sisfb_set_seq_reg(sisfb, 0x07, tmp); ++ sisfb_set_seq_reg(sisfb, 0x32, tmp1); ++} ++ ++static u8 latency_factor[] = { ++ 97, 88, 86, 79, 77, 0, ++ 0, 87, 85, 78, 76, 54, ++ 80, 72, 69, 63, 61, 0, ++ 0, 70, 68, 62, 59, 37, ++}; ++ ++static int ++sisfb_set_fifo_thresholds(struct sisfb_info * sisfb, struct sisfb_par * par) ++{ ++ u32 vclk = par->dot_clock / 1000; ++ unsigned int i = 0, threshold; ++ int grant_timer, fg_queue, bg_queue; ++ struct pci_dev * host = NULL; ++ u8 queue, srf; ++ ++ if ((host = pci_find_slot(0, 0)) == NULL) { ++ printk(KERN_EMERG "sisfb_lite: Can not find Host Controller !!!\n"); ++ return -ENODEV; ++ } ++ ++ pci_read_config_byte(host, 0x53, &queue); ++ queue &= 0xF0; ++ ++ for (grant_timer = 1; grant_timer >= 0; grant_timer--) { ++ for (fg_queue = 0; fg_queue <= 5; fg_queue++) { ++ for (bg_queue = 0; bg_queue <= 1; bg_queue++) { ++ threshold = latency_factor[i++] * vclk; ++ threshold *= (par->bits_per_pixel >> 3); ++ threshold /= (mclk * 16); ++ if (threshold > 0x13 || threshold == 0x00) ++ ; ++ else ++ goto set_threshold; ++ } ++ } ++ } ++ ++ return -EINVAL; ++ ++ set_threshold: ++ /* write froeground and backgroudn queue, GUI grant timer */ ++ queue |= ((fg_queue << 1) | bg_queue); ++ pci_write_config_byte(host, 0x53, queue); ++ pci_write_config_byte(host, 0xA3, grant_timer); ++ ++ /* Write CRT/CPU threshold low, CRT/Engine threshold high */ ++ threshold += 1; ++ srf = sisfb_get_seq_reg(sisfb, 0x0F); ++ sisfb_set_seq_reg(sisfb, 0x08, ((threshold & 0x0F) << 4 | 0x0F)); ++ sisfb_set_seq_reg(sisfb, 0x0F, ((threshold & 0x10) << 1 | srf )); ++ ++ /* Write CRT/CPU threshold high */ ++ threshold += 3; ++ if (threshold > 0x0F) ++ threshold = 0x0F; ++ sisfb_set_seq_reg(sisfb, 0x09, (threshold & 0x0F)); ++ ++ return 0; ++} ++ ++ ++/** ++ * sisfb_pan_var: - Set screen start offset ++ * @var: Frame Buffer changable part ++ * @info: Frame Buffer structure ++ * ++ * Set the screen start offset accroding to xoffset, yoffset, xres_virtual ++ * ++ * Virtual Screen: ++ * ++ * -------------------------------------------> xres_vitrual ++ * | O ++ * | ----------------------------------------- ++ * | | O' | ++ * | | ------------------------ | ++ * | | | | | ++ * | | | | | ++ * | | | | | ++ * | | | | | ++ * | | | | | ++ * | | | | | ++ * | | | | | ++ * | | ------------------------ | ++ * | | D' | ++ * | | | ++ * | | | ++ * v ----------------------------------------- D ++ * yres_virtual ++ */ ++int ++sisfb_pan_display_300(struct fb_var_screeninfo * var, struct sisfb_info * sisfb) ++{ ++ u32 offset; ++ ++ /* offset address in units of "pixels" */ ++ offset = var->yoffset * var->xres_virtual + var->xoffset; ++ /* offset address in units of byte */ ++ offset = offset * (var->bits_per_pixel >> 3); ++ ++ /* update screen_offset member of current par structure */ ++ sisfb->current_par.screen_offset = offset; ++ ++ sisfb_set_crt1_offset(sisfb, &sisfb->current_par); ++ ++ return 0; ++} ++ ++/* ++ * Set the hardware according to 'par'. ++ */ ++void ++sisfb_set_par_300(struct sisfb_par *par, struct sisfb_info * sisfb) ++{ ++ sisfb_display_off(sisfb); ++ ++ /* Standard VGA CRTC Registers */ ++ sisfb_set_crt1_crtc_regs(sisfb, par); ++ ++ /* Extended Registers, other stuff */ ++ sisfb_set_crt1_pitch(sisfb, par); ++ sisfb_set_crt1_offset(sisfb, par); ++ sisfb_set_crt1_vclk(sisfb, par); ++ sisfb_set_crt1_mode_regs(sisfb, par); ++ sisfb_set_fifo_thresholds(sisfb, par); ++ ++ /* makes 'par' values as the current_par of this framebuffer */ ++ sisfb->current_par = *par; ++ ++ sisfb_display_on(sisfb); ++} +diff -urN linux-2.4.19/drivers/video/sis/sisfb_300_core.h linux-2.4.19-linuxbios/drivers/video/sis/sisfb_300_core.h +--- linux-2.4.19/drivers/video/sis/sisfb_300_core.h Thu Jan 1 08:00:00 1970 ++++ linux-2.4.19-linuxbios/drivers/video/sis/sisfb_300_core.h Mon Sep 2 17:23:10 2002 +@@ -0,0 +1,24 @@ ++#ifndef __SISFB_300_CORE__ ++#define __SISFB_300_CORE__ ++ ++#define SIS300_PCI_ADDR_SET 0x20 ++#define SIS300_PCI_PCI_MMIO_ENABLE 0x01 ++#define SIS300_PCI_VGA_MEM_DISABLE 0x04 ++#define SIS300_PCI_VGA_IO_DISABLE 0x10 ++#define SIS300_PCI_PCI_IO_ENABLE 0x20 ++#define SIS300_PCI_LINEAR_ENABLE 0x80 ++ ++#define TURBO_QUEUE_AREA_SIZE 0x80000 /* 512K */ ++#define HW_CURSOR_AREA_SIZE 0x1000 /* 4K */ ++ ++enum clock_gen_base { ++ SIS300_MCLK = 0x28, ++ SIS300_DCLK = 0x2B, ++ SIS300_ECLK = 0x2E ++}; ++ ++extern int sisfb_config_memory(struct sisfb_info * sisfb); ++extern int sisfb_pan_display_300(struct fb_var_screeninfo * var, struct sisfb_info * sisfb); ++extern void sisfb_set_par_300(struct sisfb_par *par, struct sisfb_info * sisfb); ++ ++#endif /* __SISFB_300_CORE__ */ +diff -urN linux-2.4.19/drivers/video/sis/sisfb_300_init.c linux-2.4.19-linuxbios/drivers/video/sis/sisfb_300_init.c +--- linux-2.4.19/drivers/video/sis/sisfb_300_init.c Thu Jan 1 08:00:00 1970 ++++ linux-2.4.19-linuxbios/drivers/video/sis/sisfb_300_init.c Mon Sep 2 17:23:10 2002 +@@ -0,0 +1,203 @@ ++/* sisfb_300_init.c: Initialization Code for SiS 540/630/730 Integrated VGA ++ * ++ * Copyright 2001 Ollie Lho ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ * This driver is implemented by the Author for his own personal interests and is NOT a ++ * commitment NOR supported officially by Silicon Integrated Systems Corp. Please direct ++ * any bug report/question to the Author and don't bother SiS Technical Support Personell. ++ * ++ * ++ * Reference: ++ * 1. Glamour Design Guideline V0.8 ++ */ ++ ++#include "sisfb_lite.h" ++#include "sisfb_300_core.h" ++#include "sisfb_530_accel.h" ++ ++static void sisfb_set_pci_agp_timming(struct sisfb_info * sisfb); ++static void sisfb_enable_turbo_queue(struct sisfb_info * sisfb); ++static void sisfb_fake_vgabios(struct sisfb_info * sisfb); ++ ++/* Default values for PCI/AGP Timming control registers: SR21-SR25, SR32 */ ++static u8 pci_timming[] __initdata = { ++ 0xB6, 0xB2, 0xF6, 0x0D, 0x00, 0x11 ++}; ++ ++/** ++ * sisfb_set_pci_agp_timming: - Set AGP/PCI timming control registers ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Initialize PCI and AGP timming control registers. Most of them are ++ * dumped form normal BIOS setting. ++ */ ++static void __devinit ++sisfb_set_pci_agp_timming(struct sisfb_info * sisfb) ++{ ++ u8 AGP, tmp; ++ ++ /* SR3A, Hardware Trap III */ ++ tmp = sisfb_get_seq_reg(sisfb, 0x3A); ++ if ((tmp & 0x30) == 0x30) ++ // PCI Mode ++ AGP = 0; ++ else ++ // AGP Mode; ++ AGP = 1; ++ ++ tmp = pci_timming[0]; ++ if (AGP == 0) ++ // Disable AGP Request High Priority ++ tmp &= ~0x10; ++ sisfb_set_seq_reg(sisfb, 0x21, tmp); ++ ++ tmp = pci_timming[1]; ++ if (AGP == 1) ++ // Enable PCI Burst memory write ++ tmp |= 0x20; ++ sisfb_set_seq_reg(sisfb, 0x22, tmp); ++ ++ sisfb_set_seq_reg(sisfb, 0x23, pci_timming[2]); ++ sisfb_set_seq_reg(sisfb, 0x24, pci_timming[3]); ++ sisfb_set_seq_reg(sisfb, 0x25, pci_timming[4]); ++ sisfb_set_seq_reg(sisfb, 0x32, pci_timming[5]); ++} ++ ++/** ++ * sisfb_enable_turbo_queue: - Set Turbo Queue size and enable it ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Commands to the Graphics Engine (2D, 3D, etc) are buffered in ++ * the Video Memory which is called Turbo Queue in SiS VGA Specs. ++ * Usually this buffer area takes the last few KBs in the Video RAM. ++ */ ++/* default turbo queue size == 64KB */ ++static int tqueue_size = 0x10000; ++static void __devinit ++sisfb_enable_turbo_queue(struct sisfb_info * sisfb) ++{ ++ u32 tqueue_pos; ++ u8 tqueue_status; ++ ++ /* turbo queue position, in units of 64KB */ ++ tqueue_pos = sisfb->video_size_virt - tqueue_size; ++ tqueue_pos /= 0x10000; ++ ++ /* enable Turbo Tueue */ ++ tqueue_status = 0x80 | (tqueue_pos >> 8); ++ ++ sisfb_set_seq_reg(sisfb, 0x26, tqueue_pos); ++ sisfb_set_seq_reg(sisfb, 0x27, tqueue_status); ++ ++ printk(KERN_INFO "sisfb_lite: Use %dKB off-screen memory for Turbo Queue\n", ++ tqueue_size / 1024); ++} ++ ++/** ++ * sisfb_fake_vgabios: - Pretend we still have VGA BIOS ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Many of the Extended Sequencer Registers and Externded CRT Controller Registers ++ * are used by traditional System/VGA BIOS and Drivers to pass information back and ++ * forth. We have to fake some resonable values for these registers in order to let ++ * some stupid applications like XFree 3.3.6 work properly. ++ */ ++static void __devinit ++sisfb_fake_vgabios(struct sisfb_info * sisfb) ++{ ++ int i; ++ u8 data, sma_size; ++ u8 fake_bios[] = {0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F}; ++ ++ /* SR 14 is used as "protocol" by VGA BIOS and XFree86 for passing SMA size ++ and bus width, we have to fake them :~-( */ ++ sma_size = sisfb->video_size_virt >> 21; ++ data = fake_bios[ffs(sma_size) - 1]; ++ data |= 0x40; // 64-bit bus ++ sisfb_set_seq_reg(sisfb, 0x14, data); ++ ++ /* SR16-SR19 are used as "protocol" by VGA BIOS and System BIOS for passing ++ information about TV-out, we have to clear them :~-( */ ++ for (i = 0x16; i <= 0x19; i++) { ++ sisfb_set_seq_reg(sisfb, i, 0x00); ++ } ++ ++ /* SR1A are used as "protocol" by VGA BIOS and System BIOS for passing ++ information about M/B frequence, we have to fake them :~-( */ ++ sisfb_set_seq_reg(sisfb, 0x1A, 0x12); ++ ++ /* set MD out enable to 1T (what the hell ??) */ ++ sisfb_set_seq_reg(sisfb, 0x15, 0x01); ++ ++ /* SR1B, SR1C are not used by SiS 630 (used by SiS 300 ??), ++ clear them. */ ++ sisfb_set_seq_reg(sisfb, 0x1B, 0x00); ++ sisfb_set_seq_reg(sisfb, 0x1C, 0x00); ++ ++ /* CR30-CR37 are used by VGA BIOS to pass information ++ about SiS 301, clean them */ ++ for (i = 0x30; i <= 0x37; i++) { ++ sisfb_set_crtc_reg(sisfb, i, 0x00); ++ } ++} ++ ++/** ++ * sisfb_init_300: - Initialize the SiS300 VGA Core in SiS300, SiS630,540,730 ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Return 0 on Success, -ENODEV if SMA is incorrectly/not configured ++ * ++ * SiS 300 VGA core is used in SiS540/630/730 chipsets. This routine inits ++ * the very SiS300 specific stuff. ++ */ ++int __devinit ++sisfb_init_300(struct sisfb_info * sisfb) ++{ ++ int ret; ++ ++ if ((ret = sisfb_config_memory(sisfb)) < 0) ++ return ret; ++ ++ sisfb_init_legacy_vga(sisfb); ++ ++ /* set to High Speed DAC by default */ ++ sisfb_set_seq_reg(sisfb, 0x07, 0x13); ++ ++ /* Disable DAC pedestal */ ++ sisfb_set_seq_reg(sisfb, 0x1F, 0x00); ++ ++ sisfb_set_pci_agp_timming(sisfb); ++ ++ /* disable power management mode */ ++ sisfb_set_seq_reg(sisfb, 0x11, 0x0F); ++ ++ /* set screen start memory address bit 23:16 to 0, bit 15:0 are in CR0C, CR0D */ ++ sisfb_set_seq_reg(sisfb, 0x0D, 0x00); ++ ++ sisfb_enable_turbo_queue(sisfb); ++ ++ sisfb_fake_vgabios(sisfb); ++ ++ /* set hardware specific functions */ ++ sisfb->accelerator = &sis530_accelerator; ++ sisfb->set_par = sisfb_set_par_300; ++ sisfb->pan_display = sisfb_pan_display_300; ++ sisfb->set_disp = sisfb_set_dispsw_accel; ++ ++ return 0; ++} +diff -urN linux-2.4.19/drivers/video/sis/sisfb_300_overlay.c linux-2.4.19-linuxbios/drivers/video/sis/sisfb_300_overlay.c +--- linux-2.4.19/drivers/video/sis/sisfb_300_overlay.c Thu Jan 1 08:00:00 1970 ++++ linux-2.4.19-linuxbios/drivers/video/sis/sisfb_300_overlay.c Mon Sep 2 17:23:10 2002 +@@ -0,0 +1,294 @@ ++/* sisfb_300_overlay.c: Low-level utility function for accessing Video Overlay Accelerator ++ * for SiS 300/540/630/730 ++ * ++ * Copyright 2001 Ollie Lho ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ * This driver is implemented by the Author for his own personal interests and is NOT a ++ * commitment NOR supported officially by Silicon Integrated Systems Corp. Please direct ++ * any bug report/question to the Author and don't bother SiS Technical Support Personell. ++ * ++ * ++ * ToDo: ++ * 1. Preset for various buffer ++ * 2. Line buffer size and merge ++ * 3. More pixel format support ++ * 4. Source image crop (with preset ??) ++ * 5. Scale down for more than 1/2, with decimation ++ * 6. HW interrupt for page flip (exists ??) ++ */ ++ ++#include "sisfb_300_video.h" ++ ++ ++/** ++ * sisfb_video_set_window: - Set the video overlay window on screen ++ * @sisfb: SiS Frame Buffer structure ++ * @startx: x coordinate of upper-left corner ++ * @starty: y coordinate of upper-left cornet ++ * @endx: x coordinate of lower-right corner ++ * @endy: y coordinate of lower-right corner ++ * ++ * The coordinates of upper-left and lower-right corners of the overlay ++ * window are in units of screen pixel. ++ * ++ * The registers have to be set in order. Upon the writing of first ++ * window coodinate register all Video register are locked. They will be ++ * unlocked when the last register is programmed. ++ */ ++static void ++sisfb_video_set_window(struct sisfb_info * sisfb, ++ u16 startx, u16 starty, u16 endx, u16 endy) ++{ ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_WIN_HOR_DISP_START_LOW, startx & 0xff); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_WIN_HOR_DISP_END_LOW, endx & 0xff); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_WIN_HOR_DISP_OVERFLOW, ++ ((endx >> 4) & 0xf0) | ((startx >> 8) & 0x0f) ); ++ ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_WIN_VER_DISP_START_LOW, starty & 0xff); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_WIN_VER_DISP_END_LOW, endy & 0xff); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_WIN_VER_DISP_OVERFLOW, ++ ((endy >> 4) & 0xf0) | ((starty >> 8) & 0x0f) ); ++} ++ ++/** ++ * sisfb_video_set_start_offset: - Set the YUV buffer start offset ++ * @sisfb: SiS Frame Buffer structure ++ * @y: start offset of Y buffer, in byte address ++ * @u: start offset of U buffer, in byte address ++ * @v: start offset of V buffer, in byte address ++ * ++ * The start offsets of YUV buffers have to convert to Dobule Word unit first. ++ */ ++void ++sisfb_video_set_start_offset(struct sisfb_info * sisfb, u32 y, u32 u, u32 v) ++{ ++ u32 data; ++ ++ /* Convert byte address to unit of double word */ ++ y >>= 2; ++ u >>= 2; ++ v >>= 2; ++ ++ /* FixME: lock address register ?? */ ++ data = sisfb_get_video_reg(sisfb, SIS300_VIDEO_MISC_CONTROL_1); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_MISC_CONTROL_1, ++ data | SIS300_BUF_ADDR_LOCK); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_MISC_CONTROL_1, ++ data | SIS300_BUF_ADDR_LOCK); ++ ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_Y_BUF_START_LOW, y & 0xff); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_Y_BUF_START_MIDDLE, (y >> 8) & 0xff); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_Y_BUF_START_HIGH, (y >> 16) & 0xff); ++ ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_U_BUF_START_LOW, u & 0xff); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_U_BUF_START_MIDDLE, (u >> 8) & 0xff); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_U_BUF_START_HIGH, (u >> 16) & 0xff); ++ ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_V_BUF_START_LOW, v & 0xff); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_V_BUF_START_MIDDLE, (v >> 8) & 0xff); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_V_BUF_START_HIGH, (v >> 16) & 0xff); ++ ++ /* FixME: unlock address register ?? */ ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_MISC_CONTROL_1, data); ++} ++ ++/** ++ * sisfb_video_set_pitch: - Set the YUV buffer pitch ++ * @sisfb: SiS Frame Buffer structure ++ * @y: pitch of Y buffer, in byte address ++ * @uv: pitch of U and V buffers, in byte address ++ * ++ * The buffer pitch of YUV buffers have to convert to Dobule Word unit first. ++ */ ++static void ++sisfb_video_set_pitch(struct sisfb_info * sisfb, u32 y, u32 uv) ++{ ++ /* Convert byte address to unit of double word */ ++ y >>= 2; ++ uv >>= 2; ++ ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_Y_BUF_PITCH_LOW, y & 0xff); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_UV_BUF_PITCH_LOW, uv & 0xff); ++ ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_Y_UV_BUF_PITCH_MIDDLE, ++ ((uv >> 4) & 0xf0) | ((y >> 8) & 0x0f) ); ++} ++ ++static void ++sisfb_video_set_preset(struct sisfb_info * sisfb, u32 y, u32 uv) ++{ ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_Y_BUF_PRESET_LOW, y & 0xff); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_Y_BUF_PRESET_MIDDLE, (y >> 8) & 0xff); ++ ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_UV_BUF_PRESET_LOW, uv & 0xff); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_UV_BUF_PRESET_MIDDLE, (uv >> 8) & 0xff); ++ ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_Y_UV_BUF_PRESET_HIGH, ++ ((uv >> 12) & 0xf0) | ((y >> 16) & 0x0f) ); ++} ++ ++ ++static void ++sisfb_video_set_scale_factor(struct sisfb_info * sisfb, ++ u32 src_width, u32 src_height, ++ u32 dst_width, u32 dst_height) ++{ ++ struct sisfb_scale_param param; ++ u8 scale_ctrl = 0x00; ++ ++ sisfb_calc_scale_parm(sisfb, ¶m, src_width, src_height, ++ dst_width, dst_height); ++ ++ /* set fractional part of Horizonatl and Vertical scale factor */ ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_HOR_SCALE_LOW, ++ param.hor_fract & 0xff); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_HOR_SCALE_HIGH, ++ (param.hor_fract >> 8) & 0xff); ++ ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_VER_SCALE_LOW, ++ param.ver_fract & 0xff); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_VER_SCALE_HIGH, ++ (param.ver_fract >> 8) & 0xff); ++ ++ /* Bit 2:0 Horz Preset Interger Part */ ++ scale_ctrl |= param.hor_preset_int; ++ /* Set Horz and Vert Interger Part */ ++ scale_ctrl |= (param.hor_int & 0x01) << 3; ++ scale_ctrl |= (param.ver_int & 0x01) << 4; ++ /* Set Horz and Vert DDA Enable */ ++ scale_ctrl |= (param.hor_dda & 0x01) << 5; ++ scale_ctrl |= (param.ver_dda & 0x01) << 6; ++ ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_SCALE_CONTROL, scale_ctrl); ++} ++ ++void ++sisfb_video_set_colorkey_mode(struct sisfb_info * sisfb, u8 rop) ++{ ++ u8 data; ++ ++ data = sisfb_get_video_reg(sisfb, SIS300_VIDEO_OVERLAY_COLORKEY_MODE); ++ data &= 0xf0; ++ ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_OVERLAY_COLORKEY_MODE, data | rop); ++} ++ ++void ++sisfb_video_set_colorkey(struct sisfb_info * sisfb, u8 red, u8 green, u8 blue) ++{ ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_OVERLAY_COLORKEY_RED_MIN, red); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_OVERLAY_COLORKEY_BLUE_MIN, green); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_OVERLAY_COLORKEY_GREEN_MIN, blue); ++ ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_OVERLAY_COLORKEY_RED_MAX, red); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_OVERLAY_COLORKEY_BLUE_MAX, green); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_OVERLAY_COLORKEY_GREEN_MAX, blue); ++ ++ sisfb_video_set_colorkey_mode(sisfb, ROP_DESTKEY); ++} ++ ++void ++sisfb_video_set_pixel_format(struct sisfb_info * sisfb, u32 fmt) ++{ ++ u8 data; ++ ++ data = sisfb_get_video_reg(sisfb, SIS300_VIDEO_MISC_CONTROL_0); ++ data &= 0x03; ++ ++ switch (fmt) { ++ case 0x32315659: ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_MISC_CONTROL_0, ++ data | SIS300_PIX_FMT_YVU420P); ++ break; ++ default: ++ } ++} ++ ++void ++sisfb_video_set_geometry(struct sisfb_info * sisfb, u32 startx, u32 starty, ++ u32 src_width, u32 src_height, ++ u32 dst_width, u32 dst_height) ++{ ++ u32 endx, endy; ++ u32 screen_width, screen_height; ++ u32 pitch; ++ ++ screen_width = sisfb_300_get_screen_width(sisfb); ++ screen_height = sisfb_300_get_screen_height(sisfb); ++ ++ if (startx < 0) ++ startx = 0; ++ if (starty < 0) ++ starty = 0; ++ ++ if (startx + dst_width > screen_width) { ++ endx = screen_width; ++ } else { ++ endx = startx + dst_width; ++ } ++ ++ if (starty + dst_height > screen_height) { ++ endy = screen_height; ++ } else { ++ endy = starty + dst_height; ++ } ++ ++ /* make pitch 32 bytes aligned, to be compatable with MGA BES */ ++ pitch = (src_width + 31) & ~31; ++ ++ sisfb_video_set_window(sisfb, startx, starty, endx, endy); ++ sisfb_video_set_pitch(sisfb, pitch, pitch/2); ++ sisfb_video_set_scale_factor(sisfb, src_width, src_height, ++ dst_width, dst_height); ++ ++ /* FixME: How to calculate ?? */ ++ sisfb_video_set_preset(sisfb, 0, 0); ++ ++ /* FixME: How to calculate ?? */ ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_PLAYBACK_THRESHOLD_LOW, 0x00); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_PLAYBACK_THRESHOLD_HIGH, 0x00); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_PLAYBACK_LINE_BUF_SIZE, 0x5f); ++} ++ ++static void ++sisfb_video_init(struct sisfb_info * sisfb) ++{ ++ sisfb_unlock_video_regs(sisfb); ++ ++ /* FixME: figure these registers out */ ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_MISC_CONTROL_1, 0x10); ++ sisfb_set_video_reg(sisfb, SIS300_VIDEO_MISC_CONTROL_2, 0x90); ++} ++ ++static const char im_funcname[] = "sisfb_300_overlay_init"; ++ ++int __init ++init_sisfb_300_overlay(void) ++{ ++ inter_module_register(im_funcname, THIS_MODULE, &sisfb_video_init); ++ return 0; ++} ++ ++static void __exit ++cleanup_sisfb_300_overlay(void) ++{ ++ inter_module_unregister(im_funcname); ++} ++ ++module_exit(cleanup_sisfb_300_overlay); ++module_init(init_sisfb_300_overlay); +diff -urN linux-2.4.19/drivers/video/sis/sisfb_300_overlay.h linux-2.4.19-linuxbios/drivers/video/sis/sisfb_300_overlay.h +--- linux-2.4.19/drivers/video/sis/sisfb_300_overlay.h Thu Jan 1 08:00:00 1970 ++++ linux-2.4.19-linuxbios/drivers/video/sis/sisfb_300_overlay.h Mon Sep 2 17:23:10 2002 +@@ -0,0 +1,39 @@ ++#ifndef __SISFB_300_OVERLAY__ ++#define __SISFB_300_OVERLAY__ ++ ++#include "sisfb_overlay.h" ++ ++/* 0x82 = rgb 565 */ ++enum sis300_video_misc0_bits { ++ SIS300_OVERLAY_ENABLE = 0x02, /* Turns On/Off Video Overlay */ ++ SIS300_420_PLANE_ENABLE = 0x04, /* Select Plane or Packed mode */ ++ SIS300_YUV_FMT_ENABLE = 0x08, /* Select YUV or RGB mode */ ++ ++ //SIS300_422_ENABLE = 0x20, /* Select 422 or 411 mode */ ++ ++ SIS300_PIX_FMT_YVU420P = 0x0c, /* YUV 420 Planar */ ++ SIS300_PIX_FMT_YUYV = 0x28, /* YUYV Packed */ ++ SIS300_PIX_FMT_UYVY = 0x08, ++}; ++ ++enum sis300_video_misc1_bits { ++ SIS300_BOB_ENABLE = 0x02, ++ SIS300_INDIV_LINE_MERGE = 0x04, ++ SIS300_FIELD_MODE = 0x08, ++ SIS300_BOTTOM_FIELD = 0x10, ++ SIS300_BUF_ADDR_LOCK = 0x20 /* YUV buffer start address access lock */ ++}; ++ ++enum sis300_video_misc2_bits { ++ SIS300_SELECT_VIDEO_2 = 0x01, ++ SIS300_VIDEO2_ON_TOP = 0x02, ++ SIS300_VIDEO_ONLY = 0x04, ++ SIS300_VERTICAL_INTERP_ENABLE = 0x08, ++ ++ SIS300_DUAL_LINE_MERGE = 0x10, ++ SIS300_ALL_LINE_MERGE = 0x20, ++ SIS300_AUTO_FLIP_ENABLE = 0x40, ++ SIS300_VIDEO_REG_WRITE_ENABLE = 0x80 ++}; ++ ++#endif /* __SISFB_300_OVERLAY__ */ +diff -urN linux-2.4.19/drivers/video/sis/sisfb_315_accel.c linux-2.4.19-linuxbios/drivers/video/sis/sisfb_315_accel.c +--- linux-2.4.19/drivers/video/sis/sisfb_315_accel.c Thu Jan 1 08:00:00 1970 ++++ linux-2.4.19-linuxbios/drivers/video/sis/sisfb_315_accel.c Mon Sep 2 17:23:10 2002 +@@ -0,0 +1,538 @@ ++/* sisfb_315_accel.c: 2D Hardware Acceleration for SiS 550 ++ * ++ * Copyright 2001 Ollie Lho ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ * This driver is implemented by the Author for his own personal interests and is NOT a ++ * commitment NOR supported officially by Silicon Integrated Systems Corp. Please direct ++ * any bug report/question to the Author and don't bother SiS Technical Support Personell. ++ * ++ * ++ * Reference: ++ * 1. SiS 315 2D Engine Register, Version 0.30, Jun. 12, 2000 ++ * 2. sis315_accel.c in XFree86 4.0.2 ++ */ ++ ++#include "sisfb_315_accel.h" ++ ++/** ++ * sisfb_wait_idle: - Wait for 2D and 3D engine being idle ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Polling the Connamd Queue Status register until all the following condition is ++ * meat. ++ * bit 31 2D/3D engine, Hardware/Software Queue: 1 is idle and empty ++ * bit 30 Hardware Command Queue: 1 is empty, ++ * bit 29 2D Engine: 1 idle ++ * bit 28 3D Engine: 1 idle ++ */ ++static inline void ++sisfb_wait_idle(struct sisfb_info *sisfb) ++{ ++ int count = 0x10; ++ volatile u32 dummy = 0x00000000; ++ ++ while (dummy != 0x80000000 && --count) { ++ dummy = sisfb_readl(sisfb, SIS315_2D_CMD_QUEUE_STATUS) & 0x80000000; ++ } ++} ++ ++static inline void ++sisfb_set_agp_base(struct sisfb_info *sisfb) ++{ ++ u16 base; ++ ++ switch (sisfb->current_par.bits_per_pixel) { ++ case 8: ++ case 24: ++ default: ++ base = 0x0000; ++ break; ++ case 16: ++ base = 0x8000; ++ break; ++ case 32: ++ base = 0xC000; ++ break; ++ } ++ sisfb_writew(sisfb, SIS315_2D_AGP_BASE, base); ++} ++ ++static inline u32 ++sisfb_command_bpp(struct sisfb_info *sisfb) ++{ ++ switch (sisfb->current_par.bits_per_pixel) { ++ case 8: ++ default: ++ return SIS315_2D_CMD_CFB_8; ++ case 16: ++ return SIS315_2D_CMD_CFB_16; ++ case 32: ++ return SIS315_2D_CMD_CFB_32; ++ } ++} ++ ++/** ++ * sisfb_fillrect: - Fill a rectangle area on framebuffer ++ * @sisfb: SiS Frame Buffer structure ++ * @x: X origin ++ * @y: Y origin ++ * @width: width ++ * @height: height ++ * @color: color to fill ++ * @rop: Raster Operation for the fill ++ * ++ * Fille a rectangle area on(off ??) the screen starting from (@x, @y) to ++ * (@x + @width, @y + @height) with @color. ++ * The raster operation @rop is used for solid fill or invert (via ROP_XOR). ++ * ++ * Note: ++ * 1. The Source Pitch is dummy in this case. ++ * 2. We have to use Pattern ROPs with color in Pattern FG/BG Color Register. ++ */ ++static void ++sisfb_fillrect(struct sisfb_info *sisfb, u32 x, u32 y, ++ u32 width, u32 height, u32 color, u8 rop) ++{ ++ u32 cmd; ++ u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; ++ ++ /* FixMe: What the hell is this ?? */ ++ sisfb_set_agp_base(sisfb); ++ ++ /* setup Source & Desination Pitch */ ++ sisfb_writew(sisfb, SIS315_2D_SRC_PITCH, 0 /* dummy*/); ++ sisfb_writew(sisfb, SIS315_2D_DST_PITCH, pitch); ++ ++ /* disable merge clipping */ ++ sisfb_writew(sisfb, SIS315_2D_DST_HEIGHT, -1); ++ ++ /* setup Source & Destination Base Address == (0, screen_offset) */ ++ sisfb_writel(sisfb, SIS315_2D_SRC_ADDR, 0); ++ sisfb_writel(sisfb, SIS315_2D_DST_ADDR, base); ++ ++ /* setup Source X and Y origin == (0, 0) */ ++ sisfb_writew(sisfb, SIS315_2D_SRC_X, 0); ++ sisfb_writew(sisfb, SIS315_2D_SRC_Y, 0); ++ ++ /* setup Destination X and Y origin == (x, y) */ ++ sisfb_writew(sisfb, SIS315_2D_DST_X, x); ++ sisfb_writew(sisfb, SIS315_2D_DST_Y, y); ++ ++ /* setup Rectangle Width and Height */ ++ sisfb_writew(sisfb, SIS315_2D_RECT_WIDTH, width); ++ sisfb_writew(sisfb, SIS315_2D_RECT_HEIGHT, height); ++ ++ /* setup the foreground color in Pattern Foreground Color Register */ ++ sisfb_writel(sisfb, SIS315_2D_PAT_FG_COLOR, color); ++ ++ /* Command = BitBlt, X++, Y++, pattern = Pattern Foreground Color Register, ROP = rop */ ++ cmd = SIS315_2D_CMD_BITBLT | SIS315_2D_CMD_PAT_FG_REG | ++ sisfb_command_bpp(sisfb) | (rop << 8); ++ ++ /* Fire The Command !! */ ++ sisfb_writel(sisfb, SIS315_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS315_2D_CMD, cmd); ++} ++ ++/** ++ * sisfb_copyrect: - Copy a rectangle area ++ * @sisfb: SiS Frame Buffer structure ++ * @srcx: X origin of source rectangle ++ * @srcy: Y origin of source rectangle ++ * @sdst: X origin of destination rectangle ++ * @sdst: Y origin of destination rectangle ++ * @width: width ++ * @height: height ++ * ++ * Copy a rectangle area on(off ??) the screen starting from (@xsrc, @ysrc) to ++ * (@xsrc + @width, @ysrc + @height) to (@xdst, @ydst). ++ * ++ * FixMe: Do we need to set up x,y direction ?? ++ */ ++static void ++sisfb_copyrect(struct sisfb_info *sisfb, u32 srcx, u32 srcy, ++ u32 dstx, u32 dsty, u32 width, u32 height, u8 rop) ++{ ++ u32 cmd; ++ u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; ++ ++ /* FixMe: What the hell is this ?? */ ++ sisfb_set_agp_base(sisfb); ++ ++ /* setup Source & Desination Pitch */ ++ sisfb_writew(sisfb, SIS315_2D_SRC_PITCH, pitch); ++ sisfb_writew(sisfb, SIS315_2D_DST_PITCH, pitch); ++ ++ /* disable merge clipping */ ++ sisfb_writew(sisfb, SIS315_2D_DST_HEIGHT, -1); ++ ++ /* setup Source & Destination Base Address == (screen_offset, screen_offset) */ ++ sisfb_writel(sisfb, SIS315_2D_SRC_ADDR, base); ++ sisfb_writel(sisfb, SIS315_2D_DST_ADDR, base); ++ ++ /* setup Source X and Y origin == (srcx, srcy) */ ++ sisfb_writew(sisfb, SIS315_2D_SRC_X, srcx); ++ sisfb_writew(sisfb, SIS315_2D_SRC_Y, srcy); ++ ++ /* setup Destination X and Y origin == (dstx, dsty) */ ++ sisfb_writew(sisfb, SIS315_2D_DST_X, dstx); ++ sisfb_writew(sisfb, SIS315_2D_DST_Y, dsty); ++ ++ /* setup Rectangle Width and Height */ ++ sisfb_writew(sisfb, SIS315_2D_RECT_WIDTH, width); ++ sisfb_writew(sisfb, SIS315_2D_RECT_HEIGHT, height); ++ ++ /* Command = BitBlt, X Dir, Y Dir, bitblt from video memory (ScrenToScreen), ROP = rop */ ++ cmd = SIS315_2D_CMD_BITBLT | SIS315_2D_CMD_SRC_VIDEO | ++ sisfb_command_bpp(sisfb) | (rop << 8); ++ ++ /* Fire The Command !! */ ++ sisfb_writel(sisfb, SIS315_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS315_2D_CMD, cmd); ++} ++ ++static void ++sisfb_copyrect_transparent(struct sisfb_info *sisfb, u32 srcx, u32 srcy, ++ u32 dstx, u32 dsty, u32 width, u32 height, ++ u32 src_hi, u32 src_low, ++ u32 dst_hi, u32 dst_low, ++ u8 key_mode) ++{ ++ u32 cmd; ++ u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; ++ ++ /* FixMe: What the hell is this ?? */ ++ sisfb_set_agp_base(sisfb); ++ ++ /* setup Source & Desination Pitch */ ++ sisfb_writew(sisfb, SIS315_2D_SRC_PITCH, pitch); ++ sisfb_writew(sisfb, SIS315_2D_DST_PITCH, pitch); ++ ++ /* disable merge clipping */ ++ sisfb_writew(sisfb, SIS315_2D_DST_HEIGHT, -1); ++ ++ /* setup Source & Destination Base Address == (screen_offset, screen_offset) */ ++ sisfb_writel(sisfb, SIS315_2D_SRC_ADDR, base); ++ sisfb_writel(sisfb, SIS315_2D_DST_ADDR, base); ++ ++ /* setup Source X and Y origin == (srcx, srcy) */ ++ sisfb_writew(sisfb, SIS315_2D_SRC_X, srcx); ++ sisfb_writew(sisfb, SIS315_2D_SRC_Y, srcy); ++ ++ /* setup Destination X and Y origin == (dstx, dsty) */ ++ sisfb_writew(sisfb, SIS315_2D_DST_X, dstx); ++ sisfb_writew(sisfb, SIS315_2D_DST_Y, dsty); ++ ++ /* setup Rectangle Width and Height */ ++ sisfb_writew(sisfb, SIS315_2D_RECT_WIDTH, width); ++ sisfb_writew(sisfb, SIS315_2D_RECT_HEIGHT, height); ++ ++ /* setup Source Color Key */ ++ sisfb_writew(sisfb, SIS315_2D_TRANS_SRC_KEY_HIGH, src_hi); ++ sisfb_writew(sisfb, SIS315_2D_TRANS_SRC_KEY_LOW, src_low); ++ ++ /* setup Destination Color Key */ ++ sisfb_writew(sisfb, SIS315_2D_TRANS_DEST_KEY_HIGH, dst_hi); ++ sisfb_writew(sisfb, SIS315_2D_TRANS_DEST_KEY_LOW, dst_low); ++ ++ /* Command = BitBlt, X Dir, Y Dir, bitblt from video memory (ScrenToScreen), ROP = key_mode */ ++ cmd = SIS315_2D_CMD_TRANSPARENT_BITBLT | SIS315_2D_CMD_SRC_VIDEO | ++ sisfb_command_bpp(sisfb) | (key_mode << 8); ++ ++ /* Fire The Command !! */ ++ sisfb_writel(sisfb, SIS315_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS315_2D_CMD, cmd); ++} ++ ++/** ++ * sisfb_8x8_color_expand: - Color expand with 8x8 monochrome bit mask ++ * @sisfb: SiS Frame Buffer structure ++ * @x: X origin ++ * @y: Y origin ++ * @width: width ++ * @height: height ++ * @fg: foreground color to expand ++ * @bg: background color to expand ++ * @rop: Raster Operation for the expand ++ * @bitmap: 8x8 monochrom bitmap (64 bits) ++ * ++ * Color expand the 8x8 bitmap @bitmap by setting bits with value 1 to @fg while bits ++ * with value 0 to @bg. If @bg == -1 then background pixels are not expanded. Also fill ++ * the rectangle (@x, @y) - (@x + @width, @y + @height) with the expanded pattern. ++ * ++ * Note: ++ * 1. The Source Pitch is width/8 then rounded up. ++ * 2. We have to use Pattern ROPs with color in Pattern FG/BG Color Register. ++ */ ++static void ++sisfb_8x8_color_expand(struct sisfb_info * sisfb, u32 x, u32 y, u32 width, ++ u32 height, u32 fg, u32 bg, u8 rop, u8 * bitmap) ++{ ++ u32 cmd; ++ u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; ++ ++ /* FixMe: What the hell is this ?? */ ++ sisfb_set_agp_base(sisfb); ++ ++ /* setup Source & Desination Pitch */ ++ sisfb_writew(sisfb, SIS315_2D_SRC_PITCH, (width + 7) >> 3); ++ sisfb_writew(sisfb, SIS315_2D_DST_PITCH, pitch); ++ ++ /* disable merge clipping */ ++ sisfb_writew(sisfb, SIS315_2D_DST_HEIGHT, -1); ++ ++ /* setup Source & Destination Base Address == (0, screen_offset) */ ++ sisfb_writel(sisfb, SIS315_2D_SRC_ADDR, 0); ++ sisfb_writel(sisfb, SIS315_2D_DST_ADDR, base); ++ ++ /* setup Source X and Y origin == (0, 0) */ ++ sisfb_writew(sisfb, SIS315_2D_SRC_X, 0); ++ sisfb_writew(sisfb, SIS315_2D_SRC_Y, 0); ++ ++ /* setup Destination X and Y origin == (x, y) */ ++ sisfb_writew(sisfb, SIS315_2D_DST_X, x); ++ sisfb_writew(sisfb, SIS315_2D_DST_Y, y); ++ ++ /* setup Rectangle Width and Height */ ++ sisfb_writew(sisfb, SIS315_2D_RECT_WIDTH, width); ++ sisfb_writew(sisfb, SIS315_2D_RECT_HEIGHT, height); ++ ++ /* setup the foreground color in Pattern Foreground Color Register */ ++ sisfb_writel(sisfb, SIS315_2D_PAT_FG_COLOR, fg); ++ ++ /* setup the foreground color in Pattern Background Color Register */ ++ sisfb_writel(sisfb, SIS315_2D_PAT_BG_COLOR, bg); ++ ++ /* store 8x8 mono bitmap to Mono Mask Register */ ++ sisfb_writel(sisfb, SIS315_2D_MONO_MASK, *(u32 *) bitmap); ++ sisfb_writel(sisfb, SIS315_2D_MONO_MASK + 4, *(u32 *) (bitmap + 4)); ++ ++ /* Command = Color Expand, X++, Y++, color = Pattern Register, ROP = rop */ ++ cmd = SIS315_2D_CMD_COLOREXP | SIS315_2D_CMD_PAT_MONO_MASK | ++ sisfb_command_bpp(sisfb) | (rop << 8); ++ ++ /* if background color == -1 then don't expand background pixels */ ++ if (bg == -1) ++ cmd |= SIS315_2D_CMD_TRANSPARENT; ++ ++ /* Fire The Command !! */ ++ sisfb_writel(sisfb, SIS315_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS315_2D_CMD, cmd); ++} ++ ++/** ++ * sisfb_color_expand: - Color expand with Pattern Register ++ * @sisfb: SiS Frame Buffer structure ++ * @x: X origin ++ * @y: Y origin ++ * @width: width ++ * @height: height ++ * @fg: foreground color to expand ++ * @bg: background color to expand ++ * @rop: Raster Operation for the expand ++ * @bitmap: monochrom bitmap (384 bytes max) ++ * @bitmap_pitch: pitch of @bitmap ++ * ++ * Color expand the bitmap @bitmap by setting bits with value 1 to @fg while bits ++ * with value 0 to @bg. If @bg == -1 then background pixels are not expanded. The ++ * bitmap is transfered to hardware Pattern Register and can be as large as 384 bytes, ++ * effectively expanding 3072 pixels in a single operation. ++ * ++ * The rectangle (@x, @y) - (@x + @width, @y + @height) is filled with the expanded pattern. ++ * If the size of @bitmap is samller then 384 bytes and the size of the rectangle is larger ++ * then 3072 pixels, some pixels in the rectangle are filled with "garbage". ++ * ++ * Note: ++ * 1. The Source Pitch is width/8 then rounded up (i.e. in units of byte). ++ * 2. We have to use Normal ROPs with color in Source FG/BG Color Register. ++ */ ++static void ++sisfb_color_expand(struct sisfb_info * sisfb, u32 x, u32 y, u32 width, u32 height, ++ u32 fg, u32 bg, u8 rop, u8 * bitmap, u32 bitmap_pitch) ++{ ++ u32 cmd; ++ u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; ++ ++ /* FixMe: What the hell is this ?? */ ++ sisfb_set_agp_base(sisfb); ++ ++ /* setup Source & Desination Pitch */ ++ sisfb_writew(sisfb, SIS315_2D_SRC_PITCH, bitmap_pitch); ++ sisfb_writew(sisfb, SIS315_2D_DST_PITCH, pitch); ++ ++ /* disable merge clipping */ ++ sisfb_writew(sisfb, SIS315_2D_DST_HEIGHT, -1); ++ ++ /* setup Source & Destination Base Address == (0, screem_offset) */ ++ sisfb_writel(sisfb, SIS315_2D_SRC_ADDR, 0); ++ sisfb_writel(sisfb, SIS315_2D_DST_ADDR, base); ++ ++ /* setup Source X and Y origin == (0, 0) */ ++ sisfb_writew(sisfb, SIS315_2D_SRC_X, 0); ++ sisfb_writew(sisfb, SIS315_2D_SRC_Y, 0); ++ ++ /* setup Destination X and Y origin == (x, y) */ ++ sisfb_writew(sisfb, SIS315_2D_DST_X, x); ++ sisfb_writew(sisfb, SIS315_2D_DST_Y, y); ++ ++ /* setup Rectangle Width and Height */ ++ sisfb_writew(sisfb, SIS315_2D_RECT_WIDTH, width); ++ sisfb_writew(sisfb, SIS315_2D_RECT_HEIGHT, height); ++ ++ /* setup the foreground color in Source Foreground Color Register */ ++ sisfb_writel(sisfb, SIS315_2D_SRC_FG_COLOR, fg); ++ ++ /* setup the foreground color in Source Background Color Register */ ++ sisfb_writel(sisfb, SIS315_2D_SRC_BG_COLOR, bg); ++ ++ /* transfer bitmap pattern to pattern register */ ++ memcpy_toio(sisfb->mmio_base_virt + SIS315_2D_PATTERN_REG, ++ bitmap, bitmap_pitch * height); ++ ++ /* Command = Color Expand, X++, Y++, color = Pattern Register, ROP = rop */ ++ cmd = SIS315_2D_CMD_COLOREXP | SIS315_2D_CMD_PAT_PAT_REG | ++ sisfb_command_bpp(sisfb) | (rop << 8); ++ ++ /* if background color == -1 then don't expand background pixels */ ++ if (bg == -1) ++ cmd |= SIS315_2D_CMD_TRANSPARENT; ++ ++ /* Fire The Command !! */ ++ sisfb_writel(sisfb, SIS315_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS315_2D_CMD, cmd); ++} ++ ++static void ++sisfb_drawline(struct sisfb_info * sisfb, u32 srcx, u32 srcy, ++ u32 dstx, u32 dsty, u32 fg, u32 bg, u8 rop) ++{ ++ u32 cmd; ++ u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; ++ ++ /* FixMe: What the hell is this ?? */ ++ sisfb_set_agp_base(sisfb); ++ ++ /* setup Source & Desination Pitch */ ++ sisfb_writew(sisfb, SIS315_2D_SRC_PITCH, 1); ++ sisfb_writew(sisfb, SIS315_2D_DST_PITCH, pitch); ++ ++ /* disable merge clipping */ ++ sisfb_writew(sisfb, SIS315_2D_DST_HEIGHT, -1); ++ ++ /* setup Source & Destination Base Address == (0, screen_offset) */ ++ sisfb_writel(sisfb, SIS315_2D_SRC_ADDR, 0); ++ sisfb_writel(sisfb, SIS315_2D_DST_ADDR, base); ++ ++ /* setup Source X and Y origin == (srcx, srcy) */ ++ sisfb_writew(sisfb, SIS315_2D_LINE_X0, srcx); ++ sisfb_writew(sisfb, SIS315_2D_LINE_Y0, srcy); ++ ++ /* setup Destination X and Y origin == (dstx, dsty) */ ++ sisfb_writew(sisfb, SIS315_2D_LINE_X1, dstx); ++ sisfb_writew(sisfb, SIS315_2D_LINE_Y1, dsty); ++ ++ /* setup Line Segement Count == 1 */ ++ sisfb_writew(sisfb, SIS315_2D_LINE_COUNT, 1); ++ sisfb_writew(sisfb, SIS315_2D_LINE_STYLE_PERIOD, 0); ++ ++ /* setup the foreground color in Pattern Foreground Color Register */ ++ sisfb_writel(sisfb, SIS315_2D_PAT_FG_COLOR, fg); ++ ++ /* setup the foreground color in Pattern Background Color Register */ ++ sisfb_writel(sisfb, SIS315_2D_PAT_BG_COLOR, bg); ++ ++ /* Command = Color Expand, X++, Y++, color = Pattern Foreground Register, ROP = rop */ ++ cmd = SIS315_2D_CMD_LINE_DRAW | SIS315_2D_CMD_PAT_FG_REG | ++ sisfb_command_bpp(sisfb) | (rop << 8); ++ ++ /* Fire The Command !! */ ++ sisfb_writel(sisfb, SIS315_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS315_2D_CMD, cmd); ++} ++ ++static void ++sisfb_drawline_style(struct sisfb_info * sisfb, u32 srcx, u32 srcy, ++ u32 dstx, u32 dsty, u32 fg, u32 bg, u8 rop, u8 * bitmap) ++{ ++ u32 cmd; ++ u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; ++ ++ /* FixMe: What the hell is this ?? */ ++ sisfb_set_agp_base(sisfb); ++ ++ /* setup Source & Desination Pitch */ ++ sisfb_writew(sisfb, SIS315_2D_SRC_PITCH, 1); ++ sisfb_writew(sisfb, SIS315_2D_DST_PITCH, pitch); ++ ++ /* disable merge clipping */ ++ sisfb_writew(sisfb, SIS315_2D_DST_HEIGHT, -1); ++ ++ /* setup Source & Destination Base Address == (0, 0) */ ++ sisfb_writel(sisfb, SIS315_2D_SRC_ADDR, 0); ++ sisfb_writel(sisfb, SIS315_2D_DST_ADDR, base); ++ ++ /* setup Source X and Y origin == (srcx, srcy) */ ++ sisfb_writew(sisfb, SIS315_2D_LINE_X0, srcx); ++ sisfb_writew(sisfb, SIS315_2D_LINE_Y0, srcy); ++ ++ /* setup Destination X and Y origin == (dstx, dsty) */ ++ sisfb_writew(sisfb, SIS315_2D_LINE_X1, dstx); ++ sisfb_writew(sisfb, SIS315_2D_LINE_Y1, dsty); ++ ++ /* setup Line Segment Count == 1 */ ++ sisfb_writew(sisfb, SIS315_2D_LINE_COUNT, 1); ++ sisfb_writew(sisfb, SIS315_2D_LINE_STYLE_PERIOD, 0); ++ ++ /* setup the foreground color in Pattern Foreground Color Register */ ++ sisfb_writel(sisfb, SIS315_2D_PAT_FG_COLOR, fg); ++ ++ /* setup the foreground color in Pattern Background Color Register */ ++ sisfb_writel(sisfb, SIS315_2D_PAT_BG_COLOR, bg); ++ ++ /* transfer bitmap pattern to Line Style register */ ++ sisfb_writel(sisfb, SIS315_2D_LINE_STYLE_0, * bitmap); ++ sisfb_writel(sisfb, SIS315_2D_LINE_STYLE_1, *(bitmap + 1)); ++ ++ /* Command = Color Expand, X++, Y++, color = Pattern Register, ROP = rop */ ++ cmd = SIS315_2D_CMD_LINE_DRAW | SIS315_2D_CMD_PAT_FG_REG ++ | sisfb_command_bpp(sisfb) | SIS315_2D_CMD_LINE_STLYE_ENABLE ++ | (rop << 8); ++ ++ /* Fire The Command !! */ ++ sisfb_writel(sisfb, SIS315_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS315_2D_CMD, cmd); ++} ++ ++struct sisfb_accelerator sis315_accelerator = { ++ fillrect: sisfb_fillrect, ++ copyrect: sisfb_copyrect, ++ copyrect_transparent: sisfb_copyrect_transparent, ++ ++ color_expand_8x8: sisfb_8x8_color_expand, ++ color_expand: sisfb_color_expand, ++ ++ drawline: sisfb_drawline, ++ drawline_style: sisfb_drawline_style, ++}; +diff -urN linux-2.4.19/drivers/video/sis/sisfb_315_accel.h linux-2.4.19-linuxbios/drivers/video/sis/sisfb_315_accel.h +--- linux-2.4.19/drivers/video/sis/sisfb_315_accel.h Thu Jan 1 08:00:00 1970 ++++ linux-2.4.19-linuxbios/drivers/video/sis/sisfb_315_accel.h Mon Sep 2 17:23:10 2002 +@@ -0,0 +1,89 @@ ++#ifndef __SISFB_315_ACCEL__ ++#define __SISFB_315_ACCEL__ ++ ++#include "sisfb_accel.h" ++ ++enum sis315_2d_registers { ++ SIS315_2D_SRC_ADDR = 0x8200, ++ SIS315_2D_SRC_PITCH = 0x8204, SIS315_2D_AGP_BASE = 0x8206, ++ SIS315_2D_SRC_Y = 0x8208, SIS315_2D_SRC_X = 0x820A, ++ SIS315_2D_DST_Y = 0x820C, SIS315_2D_DST_X = 0x820E, ++ SIS315_2D_DST_ADDR = 0x8210, ++ SIS315_2D_DST_PITCH = 0x8214, SIS315_2D_DST_HEIGHT = 0x8216, ++ SIS315_2D_RECT_WIDTH = 0x8218, SIS315_2D_RECT_HEIGHT = 0x821A, ++ SIS315_2D_PAT_FG_COLOR = 0x821C, ++ SIS315_2D_PAT_BG_COLOR = 0x8220, ++ SIS315_2D_SRC_FG_COLOR = 0x8224, ++ SIS315_2D_SRC_BG_COLOR = 0x8228, ++ SIS315_2D_MONO_MASK = 0x822C, ++ SIS315_2D_LEFT_CLIP = 0x8234, SIS315_2D_TOP_CLIP = 0x8236, ++ SIS315_2D_RIGHT_CLIP = 0x8238, SIS315_2D_BOT_CLIP = 0x823A, ++ SIS315_2D_CMD = 0x823C, ++ SIS315_2D_PATTERN_REG = 0x8300 ++}; ++ ++enum sis315_2d_registers_spanfill { ++ SIS315_2D_SPAN_X1_START = 0x8244, SIS315_2D_SPAN_X1_END = 0x8246, ++ SIS315_2D_SPAN_Xn_START = 0x8300, SIS315_2D_SPAN_Xn_END = 0x8302, ++}; ++ ++enum sis315_2d_registers_drawline { ++ SIS315_2D_LINE_X0 = 0x8208, SIS315_2D_LINE_Y0 = 0x820A, ++ SIS315_2D_LINE_X1 = 0x820C, SIS315_2D_LINE_Y1 = 0x820E, ++ SIS315_2D_LINE_COUNT = 0x8218, SIS315_2D_LINE_STYLE_PERIOD = 0x821A, ++ SIS315_2D_LINE_STYLE_0 = 0x822C, ++ SIS315_2D_LINE_STYLE_1 = 0x8230, ++ SIS315_2D_LINE_Xn = 0x8300, SIS315_2D_LINE_Yn = 0x8302, ++}; ++ ++enum sis315_2d_register_transparent_bitblt { ++ SIS315_2D_TRANS_DEST_KEY_HIGH = 0x821C, ++ SIS315_2D_TRANS_DEST_KEY_LOW = 0x8220, ++ SIS315_2D_TRANS_SRC_KEY_HIGH = 0x8224, ++ SIS315_2D_TRANS_SRC_KEY_LOW = 0x8228, ++}; ++ ++enum sis315_2d_cmd_type { ++ SIS315_2D_CMD_BITBLT = 0x00, SIS315_2D_CMD_COLOREXP = 0x01, ++ SIS315_2D_CMD_ENCOLOREXP = 0x02, SIS315_2D_CMD_MULTIPLE_SCANLINE = 0x03, ++ SIS315_2D_CMD_LINE_DRAW = 0x04, SIS315_2D_CMD_TRAPEZOID_FILL = 0x05, ++ SIS315_2D_CMD_TRANSPARENT_BITBLT = 0x06, SIS315_2D_CMD_ALPHA_BLENDING = 0x07, ++ SIS315_2D_CMD_3D_FUNCTION = 0x08, SIS315_2D_CMD_CLEAR_Z_BUFFER = 0x09, ++ SIS315_2D_CMD_GRADIENT_FILL = 0x0A, SIS315_2D_CMD_STRETCH_BITBLT = 0x0B ++}; ++ ++enum sis315_2d_cmd_control { ++ SIS315_2D_CMD_SRC_VIDEO = 0x00, ++ SIS315_2D_CMD_SRC_SYSTEM = 0x10, ++ SIS315_2D_CMD_SRC_AGP = 0x20, ++ ++ SIS315_2D_CMD_PAT_FG_REG = 0x00, ++ SIS315_2D_CMD_PAT_PAT_REG = 0x40, ++ SIS315_2D_CMD_PAT_MONO_MASK = 0x80, ++ ++ SIS315_2D_CMD_CFB_8 = 0x00000000, ++ SIS315_2D_CMD_CFB_16 = 0x00010000, ++ SIS315_2D_CMD_CFB_32 = 0x00020000, ++ ++ SIS315_2D_CMD_RECT_CLIP_EN = 0x00040000, ++ SIS315_2D_CMD_TRANSPARENT = 0x00100000, ++ ++ /* Subfunction for Color/Enhanced Color Expansion */ ++ SIS315_2D_CMD_COLOR_TO_MONO = 0x00100000, ++ SIS315_2D_CMD_AA_TEXT = 0x00200000, ++ ++ SIS315_2D_CMD_MERGE_CLIP_DIS = 0x04000000, ++ ++ SIS315_2D_CMD_LINE_STLYE_ENABLE = 0x00800000 ++}; ++ ++enum sis315_command_queue_registers { ++ SIS315_2D_CMD_QUEUE_BASE_ADDRESS = 0x85C0, ++ SIS315_2D_CMD_QUEUE_WRITE_POINTER = 0x85C4, ++ SIS315_2D_CMD_QUEUE_READ_POINTER = 0x85C8, ++ SIS315_2D_CMD_QUEUE_STATUS = 0x85CC ++}; ++ ++extern struct sisfb_accelerator sis315_accelerator; ++ ++#endif /* __SISFB_315_ACCEL__ */ +diff -urN linux-2.4.19/drivers/video/sis/sisfb_315_init.c linux-2.4.19-linuxbios/drivers/video/sis/sisfb_315_init.c +--- linux-2.4.19/drivers/video/sis/sisfb_315_init.c Thu Jan 1 08:00:00 1970 ++++ linux-2.4.19-linuxbios/drivers/video/sis/sisfb_315_init.c Mon Sep 2 17:23:10 2002 +@@ -0,0 +1,241 @@ ++/* sisfb_315_init.c: Initialization Code for SiS 550 Integrated VGA ++ * ++ * Copyright 2001 Ollie Lho ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ * This driver is implemented by the Author for his own personal interests and is NOT a ++ * commitment NOR supported officially by Silicon Integrated Systems Corp. Please direct ++ * any bug report/question to the Author and don't bother SiS Technical Support Personell. ++ * ++ * ++ * Reference: ++ * 1. Glamour II Design Guideline V.12 ++ */ ++ ++#include "sisfb_lite.h" ++#include "sisfb_300_core.h" ++#include "sisfb_315_accel.h" ++ ++static void sisfb_set_pci_agp_timming(struct sisfb_info * sisfb); ++static void sisfb_set_dram_config(struct sisfb_info * sisfb); ++static void sisfb_enable_turbo_queue(struct sisfb_info * sisfb); ++static void sisfb_fake_vgabios(struct sisfb_info * sisfb); ++ ++/* Default values for PCI/AGP Timming control registers: SR21-SR25, SR32 */ ++static u8 pci_timming[] __initdata = { ++ /* SR 0x21 - 0x25, 0x31 - 0x33 */ ++ 0xB6, 0xB2, 0xF6, 0x0D, 0x30, 0x00, 0x01, 0x10 ++}; ++ ++/** ++ * sisfb_set_pci_agp_timming: - Set AGP/PCI timming control registers ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Initialize PCI and AGP timming control registers. Most of them are ++ * dumped form normal BIOS setting. ++ */ ++static void __devinit ++sisfb_set_pci_agp_timming(struct sisfb_info * sisfb) ++{ ++ u8 AGP, tmp; ++ ++ /* SR3A, Hardware Trap III */ ++ tmp = sisfb_get_seq_reg(sisfb, 0x3A); ++ if ((tmp & 0x30) == 0x30) ++ // PCI Mode ++ AGP = 0; ++ else ++ // AGP Mode; ++ AGP = 1; ++ ++ tmp = pci_timming[0]; ++ if (AGP == 0) ++ // Disable AGP Request High Priority ++ tmp &= ~0x10; ++ sisfb_set_seq_reg(sisfb, 0x21, tmp); ++ ++ tmp = pci_timming[1]; ++ if (AGP == 1) ++ // Enable PCI Burst memory write ++ tmp |= 0x20; ++ sisfb_set_seq_reg(sisfb, 0x22, tmp); ++ ++ sisfb_set_seq_reg(sisfb, 0x23, pci_timming[2]); ++ sisfb_set_seq_reg(sisfb, 0x24, pci_timming[3]); ++ sisfb_set_seq_reg(sisfb, 0x25, pci_timming[4]); ++ sisfb_set_seq_reg(sisfb, 0x31, pci_timming[5]); ++ sisfb_set_seq_reg(sisfb, 0x32, pci_timming[6]); ++ sisfb_set_seq_reg(sisfb, 0x33, pci_timming[7]); ++ ++ /* command queue threshold, max = 11111b */ ++ sisfb_set_seq_reg(sisfb, 0x27, 0x1F); ++} ++ ++static u8 dram_config1[] __initdata = { ++ /* SR 0x15-0x1B */ ++ 0x00, 0x0F, 0x5E, 0xA9, 0xA0, 0x00, 0x30 ++}; ++ ++static u8 dram_config2[] __initdata = { ++ /* CR 0x40-0x44 */ ++ 0x33, 0x33, 0x00, 0x03, 0x00 ++}; ++ ++static void __devinit ++sisfb_set_dram_config(struct sisfb_info * sisfb) ++{ ++ int i; ++ ++ for (i = 0x15; i <= 0x1B; i++) ++ sisfb_set_seq_reg(sisfb, i, dram_config1[i - 0x15]); ++ ++ for (i = 0x40; i <= 0x44; i++) ++ sisfb_set_crtc_reg(sisfb, i, dram_config2[i - 0x40]); ++} ++ ++/** ++ * sisfb_enable_turbo_queue: - Set Turbo Queue size and enable it ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Commands to the Graphics Engine (2D, 3D, etc) are buffered in ++ * the Video Memory which is called Turbo Queue in SiS VGA Specs. ++ * Usually this buffer area takes the last few KBs in the Video RAM. ++ * ++ * For SiS 315 and later, the Command Queue can be place on both Video RAM ++ * or System AGP memory. ++ */ ++/* default turbo queue size == 512KB */ ++static int tqueue_size = 0x80000; ++static void __devinit ++sisfb_enable_turbo_queue(struct sisfb_info * sisfb) ++{ ++ u32 tqueue_pos; ++ volatile u32 dummy; ++ ++ tqueue_pos = sisfb->video_size_virt - tqueue_size; ++ ++ /* set Command Queue threshold to max value 11111b */ ++ sisfb_set_seq_reg(sisfb, 0x27, 0x1F); ++ /* synchronous reset for Connamd Queue */ ++ sisfb_set_seq_reg(sisfb, 0x26, 0x01); ++ ++ /* Sync Read and Write pointers of Turbo Queue */ ++ dummy = sisfb_readl(sisfb, 0x85C8); ++ sisfb_writel(sisfb, 0x85C4, dummy); ++ ++ /* enable Command Queue (on Video RAM) , MMIO Commands */ ++ sisfb_set_seq_reg(sisfb, 0x26, 0x22); ++ ++ /* set Command Queue Base Address */ ++ sisfb_writel(sisfb, 0x85C0, tqueue_pos); ++ ++ printk(KERN_INFO "sisfb_lite: Use %dKB off-screen memory for Turbo Queue\n", ++ tqueue_size / 1024); ++} ++ ++/** ++ * sisfb_fake_vgabios: - Pretend we still have VGA BIOS ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Many of the Extended Sequencer Registers and Externded CRT Controller Registers ++ * are used by traditional System/VGA BIOS and Drivers to pass information back and ++ * forth. We have to fake some resonable values for these registers in order to let ++ * some stupid applications like XFree 3.3.6 work properly. ++ */ ++static void __devinit ++sisfb_fake_vgabios(struct sisfb_info * sisfb) ++{ ++ int i; ++ u8 data, sma_size; ++ u8 fake_bios[] = {0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F}; ++ ++ /* SR 14 is used as "protocol" by VGA BIOS and XFree86 for passing SMA size ++ and bus width, we have to fake them :~-( */ ++ sma_size = sisfb->video_size_virt >> 21; ++ data = fake_bios[ffs(sma_size) - 1]; ++ data |= 0x40; // 64-bit bus ++ sisfb_set_seq_reg(sisfb, 0x14, data); ++ ++ /* SR16-SR19 are used as "protocol" by VGA BIOS and System BIOS for passing ++ information about TV-out, we have to clear them :~-( */ ++ for (i = 0x16; i <= 0x19; i++) { ++ sisfb_set_seq_reg(sisfb, i, 0x00); ++ } ++ ++ /* SR1A are used as "protocol" by VGA BIOS and System BIOS for passing ++ information about M/B frequence, we have to fake them :~-( */ ++ sisfb_set_seq_reg(sisfb, 0x1A, 0x12); ++ ++ /* set MD out enable to 1T (what the hell ??) */ ++ sisfb_set_seq_reg(sisfb, 0x15, 0x01); ++ ++ /* SR1B, SR1C are not used by SiS 630 (used by SiS 300 ??), ++ clear them. */ ++ sisfb_set_seq_reg(sisfb, 0x1B, 0x00); ++ sisfb_set_seq_reg(sisfb, 0x1C, 0x00); ++ ++ /* CR30-CR37 are used by VGA BIOS to pass information ++ about SiS 301, clean them */ ++ for (i = 0x30; i <= 0x3F; i++) { ++ sisfb_set_crtc_reg(sisfb, i, 0x00); ++ } ++} ++ ++/** ++ * sisfb_init_315: - Initialize the SiS315 VGA Core in SiS550 ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Return 0 on Success, -ENODEV if SMA is incorrectly/not configured ++ * ++ * SiS 315 VGA core is used in SiS550 chipsets. This routine inits ++ * the very SiS315 specific stuff. ++ */ ++int __devinit ++sisfb_init_315(struct sisfb_info * sisfb) ++{ ++ int ret; ++ ++ if ((ret = sisfb_config_memory(sisfb)) < 0) ++ return ret; ++ ++ sisfb_init_legacy_vga(sisfb); ++ ++ /* set to High Speed DAC by default */ ++ sisfb_set_seq_reg(sisfb, 0x07, 0x10); ++ ++ /* Disable DAC pedestal */ ++ sisfb_set_seq_reg(sisfb, 0x1F, 0x00); ++ ++ sisfb_set_pci_agp_timming(sisfb); ++ ++ sisfb_set_dram_config(sisfb); ++ ++ /* disable power management mode */ ++ sisfb_set_seq_reg(sisfb, 0x11, 0x0F); ++ ++ sisfb_enable_turbo_queue(sisfb); ++ ++ sisfb_fake_vgabios(sisfb); ++ ++ /* set hardware specific functions */ ++ sisfb->accelerator = &sis315_accelerator; ++ sisfb->set_par = sisfb_set_par_300; ++ sisfb->pan_display = sisfb_pan_display_300; ++ sisfb->set_disp = sisfb_set_dispsw_fbcon; ++ ++ return 0; ++} +diff -urN linux-2.4.19/drivers/video/sis/sisfb_315_overlay.c linux-2.4.19-linuxbios/drivers/video/sis/sisfb_315_overlay.c +--- linux-2.4.19/drivers/video/sis/sisfb_315_overlay.c Thu Jan 1 08:00:00 1970 ++++ linux-2.4.19-linuxbios/drivers/video/sis/sisfb_315_overlay.c Mon Sep 2 17:23:10 2002 +@@ -0,0 +1,375 @@ ++/* sisfb_300_overlay.c: Low-level utility function for accessing Video Overlay Accelerator ++ * for SiS 315/550 ++ * ++ * Copyright 2001 Ollie Lho ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ * This driver is implemented by the Author for his own personal interests and is NOT a ++ * commitment NOR supported officially by Silicon Integrated Systems Corp. Please direct ++ * any bug report/question to the Author and don't bother SiS Technical Support Personell. ++ * ++ * ++ * ToDo: ++ * 1. Preset for various buffer ++ * 2. Line buffer size and merge ++ * 3. More pixel format support ++ * 4. Source image crop (with preset ??) ++ * 5. Scale down for more than 1/2, with decimation ++ * 6. HW interrupt for page flip (exists ??) ++ */ ++ ++#include "sisfb_315_video.h" ++ ++ ++/** ++ * sisfb_video_set_window: - Set the video overlay window on screen ++ * @sisfb: SiS Frame Buffer structure ++ * @startx: x coordinate of upper-left corner ++ * @starty: y coordinate of upper-left cornet ++ * @endx: x coordinate of lower-right corner ++ * @endy: y coordinate of lower-right corner ++ * ++ * The coordinates of upper-left and lower-right corners of the overlay ++ * window are in units of screen pixel. ++ * ++ * The registers have to be set in order. Upon the writing of first ++ * window coodinate register all Video register are locked. They will be ++ * unlocked when the last register is programmed. ++ */ ++static void ++sisfb_video_set_window(struct sisfb_info * sisfb, ++ u16 startx, u16 starty, u16 endx, u16 endy) ++{ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_WIN_HOR_DISP_START_LOW, startx & 0xff); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_WIN_HOR_DISP_END_LOW, endx & 0xff); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_WIN_HOR_DISP_OVERFLOW, ++ ((endx >> 4) & 0xf0) | ((startx >> 8) & 0x0f) ); ++ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_WIN_VER_DISP_START_LOW, starty & 0xff); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_WIN_VER_DISP_END_LOW, endy & 0xff); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_WIN_VER_DISP_OVERFLOW, ++ ((endy >> 4) & 0xf0) | ((starty >> 8) & 0x0f) ); ++} ++ ++/** ++ * sisfb_video_set_start_offset: - Set the YUV buffer start offset ++ * @sisfb: SiS Frame Buffer structure ++ * @y: start offset of Y buffer, in byte address ++ * @u: start offset of U buffer, in byte address ++ * @v: start offset of V buffer, in byte address ++ * ++ * The start offsets of YUV buffers have to convert to Dobule Word unit first. ++ */ ++void ++sisfb_video_set_start_offset(struct sisfb_info * sisfb, u32 y, u32 u, u32 v) ++{ ++ u32 data; ++ ++ /* Convert byte address to unit of word */ ++ y >>= 1; ++ u >>= 1; ++ v >>= 1; ++ ++ /* lock address register ?? */ ++ data = sisfb_get_video_reg(sisfb, SIS315_VIDEO_MISC_CONTROL_1); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_MISC_CONTROL_1, data | 0x20); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_MISC_CONTROL_1, data | 0x20); ++ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_Y_BUF_START_LOW, y & 0xff); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_Y_BUF_START_MIDDLE, (y >> 8) & 0xff); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_Y_BUF_START_HIGH, (y >> 16) & 0xff); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_Y_BUF_START_OVERFLOW, (y >> 24) & 0x01); ++ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_U_BUF_START_LOW, u & 0xff); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_U_BUF_START_MIDDLE, (u >> 8) & 0xff); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_U_BUF_START_HIGH, (u >> 16) & 0xff); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_U_BUF_START_OVERFLOW, (u >> 24) & 0x01); ++ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_V_BUF_START_LOW, v & 0xff); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_V_BUF_START_MIDDLE, (v >> 8) & 0xff); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_V_BUF_START_HIGH, (v >> 16) & 0xff); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_V_BUF_START_OVERFLOW, (v >> 24) & 0x01); ++ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_MISC_CONTROL_1, data); ++} ++ ++/** ++ * sisfb_video_set_pitch: - Set the YUV buffer pitch ++ * @sisfb: SiS Frame Buffer structure ++ * @y: pitch of Y buffer, in byte address ++ * @uv: pitch of U and V buffers, in byte address ++ * ++ * The start offsets of YUV buffers have to convert to Dobule Word unit first. ++ * ++ * FixME: Should we convert to word or dowble aliged ?? ++ */ ++static void ++sisfb_video_set_pitch(struct sisfb_info * sisfb, u32 y, u32 uv) ++{ ++ /* Convert byte address to unit of double word */ ++ y >>= 1; ++ uv >>= 1; ++ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_Y_BUF_PITCH_LOW, y & 0xff); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_UV_BUF_PITCH_LOW, uv & 0xff); ++ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_Y_UV_BUF_PITCH_MIDDLE, ++ ((uv >> 4) & 0xf0) | ((y >> 8) & 0x0f) ); ++ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_Y_BUF_PITCH_HIGH, (y >> 12) & 0xff); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_UV_BUF_PITCH_HIGH, (uv >> 12) & 0xff); ++} ++ ++static void ++sisfb_video_set_preset(struct sisfb_info * sisfb, u32 y, u32 uv) ++{ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_Y_BUF_PRESET_LOW, y & 0xff); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_Y_BUF_PRESET_MIDDLE, (y >> 8) & 0xff); ++ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_UV_BUF_PRESET_LOW, uv & 0xff); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_UV_BUF_PRESET_MIDDLE, (uv >> 8) & 0xff); ++ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_Y_UV_BUF_PRESET_HIGH, ++ ((uv >> 12) & 0xf0) | ((y >> 16) & 0x0f) ); ++} ++ ++#define log2(n) ffz(~(n)) ++ ++struct sisfb_scale_param { ++ u8 hor_int; ++ u16 hor_fract; ++ u8 ver_int; ++ u16 ver_fract; ++ ++ u8 hor_preset_int; ++ ++ /* DDA Enable, used for Scale >= 1 */ ++ u8 hor_dda; ++ u8 ver_dda; ++}; ++ ++/** ++ * sisfb_video_set_window: - Set the video overlay scale parameter ++ * @sisfb: SiS Frame Buffer structure ++ * @src_width: Source image width ++ * @src_height: Source image height ++ * @dest_width: Destination image width ++ * @dest_height: Destination image height ++ * ++ * dst 1 ++ * ----- = ------------------------ ++ * src Int_part + Fract_part ++ * ------------ ++ * 0xFFFF ++ */ ++static void ++sisfb_calc_scale_parm(struct sisfb_info * sisfb, struct sisfb_scale_param * param, ++ u32 src_width, u32 src_height, ++ u32 dest_width, u32 dest_height) ++{ ++ param->hor_preset_int = 0; ++ ++ /* Horizontal Scale Factors*/ ++ if (src_width == dest_width) { ++ param->hor_int = 0x01; ++ param->hor_fract = 0x00; ++ param->hor_dda = 0x01; ++ } else if (src_width < dest_width) { ++ param->hor_int = 0x00; ++ param->hor_fract = 0xFFFF * src_width / dest_width; ++ param->hor_dda = 0x01; ++ } else { ++ param->hor_int = 0x01; ++ param->hor_fract = (src_width - dest_width) * 0xFFFF / dest_width; ++ param->hor_dda = 0x00; ++ ++ /* FixME: Scale down more than 1/2 */ ++ //param->hor_preset_int = log2(src_width/dest_width); ++ } ++ ++ /* Vertical Scale Factors*/ ++ if (src_height == dest_height) { ++ param->ver_int = 0x01; ++ param->ver_fract = 0x00; ++ param->ver_dda = 0x01; ++ } else if (src_height < dest_height) { ++ param->ver_int = 0x00; ++ param->ver_fract = 0xFFFF * src_height / dest_height; ++ param->ver_dda = 0x01; ++ } else { ++ param->ver_int = 0x01; ++ param->ver_fract = (src_height - dest_height) * 0xFFFF / dest_height; ++ param->ver_dda = 0x00; ++ ++ /* FixME: Scale down more than 1/2 */ ++ } ++ ++} ++ ++static void ++sisfb_video_set_scale_factor(struct sisfb_info * sisfb, ++ u32 src_width, u32 src_height, ++ u32 dst_width, u32 dst_height) ++{ ++ struct sisfb_scale_param param; ++ u8 scale_ctrl = 0x00; ++ ++ sisfb_calc_scale_parm(sisfb, ¶m, src_width, src_height, ++ dst_width, dst_height); ++ ++ /* set fractional part of Horizonatl and Vertical scale factor */ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_HOR_SCALE_LOW, ++ param.hor_fract & 0xff); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_HOR_SCALE_HIGH, ++ (param.hor_fract >> 8) & 0xff); ++ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_VER_SCALE_LOW, ++ param.ver_fract & 0xff); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_VER_SCALE_HIGH, ++ (param.ver_fract >> 8) & 0xff); ++ ++ /* Bit 2:0 Horz Preset Interger Part */ ++ scale_ctrl |= param.hor_preset_int; ++ /* Set Horz and Vert Interger Part */ ++ scale_ctrl |= (param.hor_int & 0x01) << 3; ++ scale_ctrl |= (param.ver_int & 0x01) << 4; ++ /* Set Horz and Vert DDA Enable */ ++ scale_ctrl |= (param.hor_dda & 0x01) << 5; ++ scale_ctrl |= (param.ver_dda & 0x01) << 6; ++ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_SCALE_CONTROL, scale_ctrl); ++} ++ ++void ++sisfb_video_set_colorkey_mode(struct sisfb_info * sisfb, u8 rop) ++{ ++ u8 data; ++ ++ data = sisfb_get_video_reg(sisfb, SIS315_VIDEO_OVERLAY_COLORKEY_MODE); ++ data &= 0xf0; ++ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_OVERLAY_COLORKEY_MODE, data | rop); ++} ++ ++void ++sisfb_video_set_colorkey(struct sisfb_info * sisfb, u8 red, u8 green, u8 blue) ++{ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_OVERLAY_COLORKEY_RED_MIN, red); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_OVERLAY_COLORKEY_BLUE_MIN, green); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_OVERLAY_COLORKEY_GREEN_MIN, blue); ++ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_OVERLAY_COLORKEY_RED_MAX, red); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_OVERLAY_COLORKEY_BLUE_MAX, green); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_OVERLAY_COLORKEY_GREEN_MAX, blue); ++ ++ sisfb_video_set_colorkey_mode(sisfb, ROP_DESTKEY); ++} ++ ++void ++sisfb_video_set_pixel_format(struct sisfb_info * sisfb, u32 fmt) ++{ ++ u8 data; ++ ++ data = sisfb_get_video_reg(sisfb, SIS315_VIDEO_MISC_CONTROL_0); ++ data &= 0x03; ++ ++ switch (fmt) { ++ case 0x32315659: ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_MISC_CONTROL_0, ++ data | SIS315_PIX_FMT_YVU420P); ++ break; ++ default: ++ } ++} ++ ++void ++sisfb_video_set_geometry(struct sisfb_info * sisfb, u32 startx, u32 starty, ++ u32 src_width, u32 src_height, ++ u32 dst_width, u32 dst_height) ++{ ++ u32 endx, endy; ++ u32 screen_width, screen_height; ++ u32 pitch; ++ ++ screen_width = sisfb_300_get_screen_width(sisfb); ++ screen_height = sisfb_300_get_screen_height(sisfb); ++ ++ if (startx < 0) ++ startx = 0; ++ if (starty < 0) ++ starty = 0; ++ ++ if (startx + dst_width > screen_width) { ++ endx = screen_width; ++ } else { ++ endx = startx + dst_width; ++ } ++ ++ if (starty + dst_height > screen_height) { ++ endy = screen_height; ++ } else { ++ endy = starty + dst_height; ++ } ++ ++ /* make pitch 32 bytes aligned, to be compatable with MGA BES */ ++ pitch = (src_width + 31) & ~31; ++ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_MISC_CONTROL_3, 0x00); ++ sisfb_video_set_window(sisfb, startx, starty, endx, endy); ++ sisfb_video_set_pitch(sisfb, pitch, pitch/2); ++ sisfb_video_set_scale_factor(sisfb, src_width, src_height, ++ dst_width, dst_height); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_MISC_CONTROL_3, 0x07); ++ ++ /* FixME: How to calculate ?? */ ++ sisfb_video_set_preset(sisfb, 0, 0); ++ ++ /* FixME: How to calculate ?? */ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_PLAYBACK_THRESHOLD_LOW, 0x00); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_PLAYBACK_THRESHOLD_HIGH, 0x00); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_PLAYBACK_LINE_BUF_SIZE, 0x5f); ++} ++ ++static void ++sisfb_video_init(struct sisfb_info * sisfb) ++{ ++ sisfb_unlock_video_regs(sisfb); ++ ++ /* FixME: figure this registers out */ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_MISC_CONTROL_1, 0x10); ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_MISC_CONTROL_2, 0x90); ++ ++ sisfb_video_set_preset(sisfb, 0, 0); ++} ++ ++static const char im_funcname[] = "sisfb_300_overlay_init"; ++ ++int __init ++init_sisfb_300_overlay(void) ++{ ++ inter_module_register(im_funcname, THIS_MODULE, &sisfb_video_init); ++ return 0; ++} ++ ++static void __exit ++cleanup_sisfb_300_overlay(void) ++{ ++ inter_module_unregister(im_funcname); ++} ++ ++module_exit(cleanup_sisfb_300_overlay); ++module_init(init_sisfb_300_overlay); +diff -urN linux-2.4.19/drivers/video/sis/sisfb_315_overlay.h linux-2.4.19-linuxbios/drivers/video/sis/sisfb_315_overlay.h +--- linux-2.4.19/drivers/video/sis/sisfb_315_overlay.h Thu Jan 1 08:00:00 1970 ++++ linux-2.4.19-linuxbios/drivers/video/sis/sisfb_315_overlay.h Mon Sep 2 17:23:10 2002 +@@ -0,0 +1,111 @@ ++#ifndef __SISFB_315_OVERLAY__ ++#define __SISFB_315_OVERLAY__ ++ ++#include "sisfb_overlay.h" ++ ++enum sis315_overlay_registers { ++ /* Bit 16:24 of Y_U_V Buffer start address */ ++ SIS315_VIDEO_Y_BUF_START_OVERFLOW = 0x6B, ++ SIS315_VIDEO_U_BUF_START_OVERFLOW = 0x6C, ++ SIS315_VIDEO_V_BUF_START_OVERFLOW = 0x6D, ++ ++ SIS315_VIDEO_Y_BUF_PITCH_HIGH = 0x6E, ++ SIS315_VIDEO_UV_BUF_PITCH_HIGH = 0x6F, ++ ++ /* Hue and Saturation value */ ++ SIS315_VIDEO_HUE_VALUE = 0x70, ++ SIS315_VIDEO_SATURATION_VALUE = 0x71, ++ ++ SIS315_VIDEO_SUB_BUF_START_OVERFLOW = 0x72, ++ SIS315_VIDEO_SUB_BUF_PITCH_HIGH = 0x73, ++ ++ SIS315_VIDEO_MISC_CONTROL_3 = 0x74 ++}; ++ ++/* 0x82 = rgb 565 */ ++enum sis315_video_misc0_bits { ++ SIS315_OVERLAY_ENABLE = 0x02, /* Turns On/Off Video Overlay */ ++ SIS315_420_PLANE_ENABLE = 0x04, /* Select Plane or Packed mode */ ++ SIS315_YUV_FMT_ENABLE = 0x08, /* Select YUV or RGB mode */ ++ ++ //SIS315_422_ENABLE = 0x20, /* Select 422 or 411 mode */ ++ ++ SIS315_PIX_FMT_YVU420P = 0x0c, /* YUV 420 Planar */ ++ SIS315_PIX_FMT_YUYV = 0x28, /* YUYV Packed */ ++ SIS315_PIX_FMT_UYVY = 0x08, ++}; ++ ++enum sis315_video_misc1_bits { ++ SIS315_BOB_ENABLE = 0x02, ++ SIS315_INDIV_LINE_MERGE = 0x04, ++ SIS315_FIELD_MODE = 0x08, ++ ++ SIS315_BOTTOM_FIELD = 0x10, ++ SIS315_NON_INTERLEAVE = 0x20, ++}; ++ ++enum sis315_video_misc2_bits { ++ SIS315_SELECT_VIDEO_2 = 0x01, ++ SIS315_VIDEO2_ON_TOP = 0x02, ++ ++ SIS315_VIDEO_ONLY = 0x04, ++ SIS315_VERTICAL_INTERP_ENABLE = 0x08, ++ ++ SIS315_DUAL_LINE_MERGE = 0x10, ++ SIS315_ALL_LINE_MERGE = 0x20, ++ ++ SIS315_AUTO_FLIP_ENABLE = 0x40, ++}; ++ ++enum sis315_video_misc3_bits { ++ SIS315_SUBMIT_VIDEO1 = 0x01, ++ SIS315_SUBMIT_VIDEO2 = 0x02, ++ SIS315_SUBMIT_SUBPICT = 0x04 ++}; ++ ++static inline void ++sisfb_video_set_alpha_value(struct sisfb_info * sisfb, u8 alpha) ++{ ++ u8 data; ++ ++ alpha &= 0x0f; ++ ++ data = sisfb_get_video_reg(sisfb, SIS315_VIDEO_OVERLAY_COLORKEY_MODE); ++ data &= 0x0f; ++ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_OVERLAY_COLORKEY_MODE, ++ data | (alpha << 4)); ++} ++ ++static inline void ++sisfb_overlay_set_hue(struct sisfb_info * sisfb, u8 hue) ++{ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_HUE_VALUE, hue); ++} ++ ++static inline u8 ++sisfb_overlay_get_hue(struct sisfb_info * sisfb) ++{ ++ return sisfb_get_video_reg(sisfb, SIS315_VIDEO_HUE_VALUE); ++} ++ ++static inline void ++sisfb_overlay_set_saturation(struct sisfb_info * sisfb, u8 saturation) ++{ ++ sisfb_set_video_reg(sisfb, SIS315_VIDEO_SATURATION_VALUE, saturation); ++} ++ ++static inline u8 ++sisfb_overlay_get_saturation(struct sisfb_info * sisfb) ++{ ++ return sisfb_get_video_reg(sisfb, SIS315_VIDEO_SATURATION_VALUE); ++} ++ ++extern void sisfb_video_set_colorkey_mode(struct sisfb_info * sisfb, u8 rop); ++extern void sisfb_video_set_colorkey(struct sisfb_info * sisfb, u8 red, u8 green, u8 blue); ++extern void sisfb_video_set_pixel_format(struct sisfb_info * sisfb, u32 fmt); ++extern void sisfb_video_set_geometry(struct sisfb_info * sisfb, u32 startx, u32 starty, ++ u32 src_width, u32 src_height, ++ u32 dst_width, u32 dst_height); ++extern void sisfb_video_set_start_offset(struct sisfb_info * sisfb, u32 y, u32 u, u32 v); ++#endif /* __SISFB_315_OVERLAY__ */ +diff -urN linux-2.4.19/drivers/video/sis/sisfb_530_accel.c linux-2.4.19-linuxbios/drivers/video/sis/sisfb_530_accel.c +--- linux-2.4.19/drivers/video/sis/sisfb_530_accel.c Thu Jan 1 08:00:00 1970 ++++ linux-2.4.19-linuxbios/drivers/video/sis/sisfb_530_accel.c Mon Sep 2 17:23:10 2002 +@@ -0,0 +1,573 @@ ++/* sisfb_530_accel.c: 2D Hardware Acceleration for SiS 530/620/540/630/730 ++ * ++ * Copyright 2001 Ollie Lho ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ * This driver is implemented by the Author for his own personal interests and is NOT a ++ * commitment NOR supported officially by Silicon Integrated Systems Corp. Please direct ++ * any bug report/question to the Author and don't bother SiS Technical Support Personell. ++ * ++ * ++ * Reference: ++ * 1. SiS 6326 AGP/PCI Graphics & Video Acclerator. Rev 1.0, May 12, 1997 ++ * 2. SiS 530 Host, PCI, 3D Graphics & Memory Controller Datasheet, ++ * Preliminary v1.0 Nov. 10, 1998 ++ * 3. sis_accel2.c in XFree86 3.3.6 ++ * 4. sis300_accel.c in XFree86 4.0.2 ++ */ ++ ++#include "sisfb_530_accel.h" ++ ++/** ++ * sisfb_wait_idle: - Wait for 2D and 3D engine being idle ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Polling the Connamd Status register until all the following condition is ++ * meat. ++ * bit 31 2D engine: 1 is idle, ++ * bit 30 3D engine: 1 is idle, ++ * bit 29 Command queue: 1 is empty ++ */ ++static inline void ++sisfb_wait_idle(struct sisfb_info *sisfb) ++{ ++ int count = 0x10; ++ volatile u32 dummy = 0x00000000; ++ ++ while (dummy != 0xe0000000 && --count) { ++ dummy = sisfb_readl(sisfb, SIS530_2D_CMD_STATUS) & 0xe0000000; ++ } ++} ++ ++/** ++ * sisfb_wait_cmd_queue: - Wait for command queue space ++ * @sisfb: SiS Frame Buffer structure ++ * @length: Space need for command queue ++ * ++ * Polling the Command Status register until there is more space ++ * left for @length of command ++ */ ++static inline void ++sisfb_wait_cmd_queue(struct sisfb_info *sisfb, unsigned length) ++{ ++ do { ++ /* nothing */ ++ } while ((sisfb_readl(sisfb, SIS530_2D_CMD_STATUS) & 0x1FFF) < (length)); ++} ++ ++static inline void ++sisfb_set_agp_base(struct sisfb_info *sisfb) ++{ ++ u16 base; ++ ++ switch (sisfb->current_par.bits_per_pixel) { ++ case 8: ++ case 24: ++ default: ++ base = 0x0000; ++ break; ++ case 16: ++ base = 0x8000; ++ break; ++ case 32: ++ base = 0xC000; ++ break; ++ } ++ sisfb_writew(sisfb, SIS530_2D_AGP_BASE, base); ++} ++ ++/** ++ * sisfb_fillrect: - Fill a rectangle area on framebuffer ++ * @sisfb: SiS Frame Buffer structure ++ * @x: X origin ++ * @y: Y origin ++ * @width: width ++ * @height: height ++ * @color: color to fill ++ * @rop: Raster Operation for the fill ++ * ++ * Fill a rectangle area on(off ??) the screen starting from (@x, @y) to ++ * (@x + @width, @y + @height) with @color. ++ * The raster operation @rop is used for solid fill or invert (via ROP_XOR). ++ * ++ * Note: ++ * 1. The Source Pitch is dummy in this case. ++ * 2. We have to use Pattern ROPs with color in Pattern FG/BG Color Register. ++ */ ++static void ++sisfb_fillrect(struct sisfb_info *sisfb, u32 x, u32 y, ++ u32 width, u32 height, u32 color, u8 rop) ++{ ++ u32 cmd; ++ u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; ++ ++ /* FixMe: What the hell is this ?? */ ++ sisfb_set_agp_base(sisfb); ++ ++ /* setup Source & Desination Pitch */ ++ sisfb_writew(sisfb, SIS530_2D_SRC_PITCH, 0 /* dummy*/); ++ sisfb_writew(sisfb, SIS530_2D_DST_PITCH, pitch); ++ ++ /* disable merge clipping */ ++ sisfb_writew(sisfb, SIS530_2D_DST_HEIGHT, -1); ++ ++ /* setup Source & Destination Base Address == (0, screen_offset) */ ++ sisfb_writel(sisfb, SIS530_2D_SRC_ADDR, 0); ++ sisfb_writel(sisfb, SIS530_2D_DST_ADDR, base); ++ ++ /* setup Source X and Y origin == (0, 0) */ ++ sisfb_writew(sisfb, SIS530_2D_SRC_X, 0); ++ sisfb_writew(sisfb, SIS530_2D_SRC_Y, 0); ++ ++ /* setup Destination X and Y origin == (x, y) */ ++ sisfb_writew(sisfb, SIS530_2D_DST_X, x); ++ sisfb_writew(sisfb, SIS530_2D_DST_Y, y); ++ ++ /* setup Rectangle Width and Height */ ++ sisfb_writew(sisfb, SIS530_2D_RECT_WIDTH, width); ++ sisfb_writew(sisfb, SIS530_2D_RECT_HEIGHT, height); ++ ++ /* setup the foreground color in Pattern Foreground Color Register */ ++ sisfb_writel(sisfb, SIS530_2D_PAT_FG_COLOR, color); ++ ++ /* Command = BitBlt, X++, Y++, pattern = Pattern Foreground Color Register, ROP = rop */ ++ cmd = SIS530_2D_CMD_BITBLT | SIS530_2D_CMD_PAT_FG_REG | ++ SIS530_2D_CMD_DIR_X_INC | SIS530_2D_CMD_DIR_Y_INC | (rop << 8); ++ ++ /* Fire The Command !! */ ++ sisfb_writel(sisfb, SIS530_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS530_2D_CMD_STATUS, 0); ++} ++ ++/** ++ * sisfb_copyrect: - Copy a rectangle area ++ * @sisfb: SiS Frame Buffer structure ++ * @srcx: X origin of source rectangle ++ * @srcy: Y origin of source rectangle ++ * @sdst: X origin of destination rectangle ++ * @sdst: Y origin of destination rectangle ++ * @width: width ++ * @height: height ++ * ++ * Copy a rectangle area on(off ??) the screen starting from (@xsrc, @ysrc) to ++ * (@xsrc + @width, @ysrc + @height) to (@xdst, @ydst). ++ */ ++static void ++sisfb_copyrect(struct sisfb_info *sisfb, u32 srcx, u32 srcy, ++ u32 dstx, u32 dsty, u32 width, u32 height, u8 rop) ++{ ++ u32 cmd; ++ u32 x_dir = SIS530_2D_CMD_DIR_X_INC, y_dir = SIS530_2D_CMD_DIR_Y_INC; ++ u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; ++ ++ /* If the direction is "decreasing", the chip wants the addresses ++ * to be at the other end, so we must be aware of that in our ++ * calculations. */ ++ if (srcx <= dstx) { ++ x_dir = SIS530_2D_CMD_DIR_X_DEC; ++ srcx += width - 1; ++ dstx += width - 1; ++ } ++ ++ if (srcy <= dsty) { ++ y_dir = SIS530_2D_CMD_DIR_Y_DEC; ++ srcy += height - 1; ++ dsty += height - 1; ++ } ++ ++ /* FixMe: What the hell is this ?? */ ++ sisfb_set_agp_base(sisfb); ++ ++ /* setup Source & Desination Pitch */ ++ sisfb_writew(sisfb, SIS530_2D_SRC_PITCH, pitch); ++ sisfb_writew(sisfb, SIS530_2D_DST_PITCH, pitch); ++ ++ /* disable merge clipping */ ++ sisfb_writew(sisfb, SIS530_2D_DST_HEIGHT, -1); ++ ++ /* setup Source & Destination Base Address == (screen_offset, screen_offset) */ ++ sisfb_writel(sisfb, SIS530_2D_SRC_ADDR, base); ++ sisfb_writel(sisfb, SIS530_2D_DST_ADDR, base); ++ ++ /* setup Source X and Y origin == (srcx, srcy) */ ++ sisfb_writew(sisfb, SIS530_2D_SRC_X, srcx); ++ sisfb_writew(sisfb, SIS530_2D_SRC_Y, srcy); ++ ++ /* setup Destination X and Y origin == (dstx, dsty) */ ++ sisfb_writew(sisfb, SIS530_2D_DST_X, dstx); ++ sisfb_writew(sisfb, SIS530_2D_DST_Y, dsty); ++ ++ /* setup Rectangle Width and Height */ ++ sisfb_writew(sisfb, SIS530_2D_RECT_WIDTH, width); ++ sisfb_writew(sisfb, SIS530_2D_RECT_HEIGHT, height); ++ ++ /* Command = BitBlt, X Dir, Y Dir, bitblt from video memory (ScrenToScreen), ROP = rop */ ++ cmd = SIS530_2D_CMD_BITBLT | SIS530_2D_CMD_SRC_VIDEO | ++ x_dir | y_dir | (rop << 8); ++ ++ /* Fire The Command !! */ ++ sisfb_writel(sisfb, SIS530_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS530_2D_CMD_STATUS, 0); ++} ++ ++static void ++sisfb_copyrect_transparent(struct sisfb_info *sisfb, u32 srcx, u32 srcy, ++ u32 dstx, u32 dsty, u32 width, u32 height, ++ u32 src_hi, u32 src_low, ++ u32 dst_hi, u32 dst_low, ++ u8 key_mode) ++{ ++ u32 cmd; ++ u32 x_dir = SIS530_2D_CMD_DIR_X_INC, y_dir = SIS530_2D_CMD_DIR_Y_INC; ++ u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; ++ ++ /* If the direction is "decreasing", the chip wants the addresses ++ * to be at the other end, so we must be aware of that in our ++ * calculations. */ ++ if (srcx <= dstx) { ++ x_dir = SIS530_2D_CMD_DIR_X_DEC; ++ srcx += width - 1; ++ dstx += width - 1; ++ } ++ ++ if (srcy <= dsty) { ++ y_dir = SIS530_2D_CMD_DIR_Y_DEC; ++ srcy += height - 1; ++ dsty += height - 1; ++ } ++ ++ /* FixMe: What the hell is this ?? */ ++ sisfb_set_agp_base(sisfb); ++ ++ /* setup Source & Desination Pitch */ ++ sisfb_writew(sisfb, SIS530_2D_SRC_PITCH, pitch); ++ sisfb_writew(sisfb, SIS530_2D_DST_PITCH, pitch); ++ ++ /* disable merge clipping */ ++ sisfb_writew(sisfb, SIS530_2D_DST_HEIGHT, -1); ++ ++ /* setup Source & Destination Base Address == (screen_offset, screen_offset) */ ++ sisfb_writel(sisfb, SIS530_2D_SRC_ADDR, base); ++ sisfb_writel(sisfb, SIS530_2D_DST_ADDR, base); ++ ++ /* setup Source X and Y origin == (srcx, srcy) */ ++ sisfb_writew(sisfb, SIS530_2D_SRC_X, srcx); ++ sisfb_writew(sisfb, SIS530_2D_SRC_Y, srcy); ++ ++ /* setup Destination X and Y origin == (dstx, dsty) */ ++ sisfb_writew(sisfb, SIS530_2D_DST_X, dstx); ++ sisfb_writew(sisfb, SIS530_2D_DST_Y, dsty); ++ ++ /* setup Rectangle Width and Height */ ++ sisfb_writew(sisfb, SIS530_2D_RECT_WIDTH, width); ++ sisfb_writew(sisfb, SIS530_2D_RECT_HEIGHT, height); ++ ++ /* setup Source Color Key */ ++ sisfb_writew(sisfb, SIS530_2D_TRANS_SRC_KEY_HIGH, src_hi); ++ sisfb_writew(sisfb, SIS530_2D_TRANS_SRC_KEY_LOW, src_low); ++ ++ /* setup Destination Color Key */ ++ sisfb_writew(sisfb, SIS530_2D_TRANS_DEST_KEY_HIGH, dst_hi); ++ sisfb_writew(sisfb, SIS530_2D_TRANS_DEST_KEY_LOW, dst_low); ++ ++ /* Command = BitBlt, X Dir, Y Dir, bitblt from video memory (ScrenToScreen), ROP = key_mode */ ++ cmd = SIS530_2D_CMD_TRANSPARENT_BITBLT | SIS530_2D_CMD_SRC_VIDEO | ++ x_dir | y_dir | (key_mode << 8); ++ ++ /* Fire The Command !! */ ++ sisfb_writel(sisfb, SIS530_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS530_2D_CMD_STATUS, 0); ++} ++ ++/** ++ * sisfb_8x8_color_expand: - Color expand with 8x8 monochrome bit mask ++ * @sisfb: SiS Frame Buffer structure ++ * @x: X origin ++ * @y: Y origin ++ * @width: width ++ * @height: height ++ * @fg: foreground color to expand ++ * @bg: background color to expand ++ * @rop: Raster Operation for the expand ++ * @bitmap: 8x8 monochrom bitmap (64 bits) ++ * ++ * Color expand the 8x8 bitmap @bitmap by setting bits with value 1 to @fg while bits ++ * with value 0 to @bg. If @bg == -1 then background pixels are not expanded. Also fill ++ * the rectangle (@x, @y) - (@x + @width, @y + @height) with the expanded pattern. ++ * ++ * Note: ++ * 1. The Source Pitch is dummy in this case. ++ * 2. We have to use Pattern ROPs with color in Pattern FG/BG Color Register. ++ */ ++static void ++sisfb_8x8_color_expand(struct sisfb_info * sisfb, u32 x, u32 y, u32 width, ++ u32 height, u32 fg, u32 bg, u8 rop, u8 * bitmap) ++{ ++ u32 cmd; ++ u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; ++ ++ /* FixMe: What the hell is this ?? */ ++ sisfb_set_agp_base(sisfb); ++ ++ /* setup Source & Desination Pitch */ ++ sisfb_writew(sisfb, SIS530_2D_SRC_PITCH, 0 /*dummy*/); ++ sisfb_writew(sisfb, SIS530_2D_DST_PITCH, pitch); ++ ++ /* disable merge clipping */ ++ sisfb_writew(sisfb, SIS530_2D_DST_HEIGHT, -1); ++ ++ /* setup Source & Destination Base Address == (0, screen_offset) */ ++ sisfb_writel(sisfb, SIS530_2D_SRC_ADDR, 0); ++ sisfb_writel(sisfb, SIS530_2D_DST_ADDR, base); ++ ++ /* setup Source X and Y origin == (0, 0) */ ++ sisfb_writew(sisfb, SIS530_2D_SRC_X, 0); ++ sisfb_writew(sisfb, SIS530_2D_SRC_Y, 0); ++ ++ /* setup Destination X and Y origin == (x, y) */ ++ sisfb_writew(sisfb, SIS530_2D_DST_X, x); ++ sisfb_writew(sisfb, SIS530_2D_DST_Y, y); ++ ++ /* setup Rectangle Width and Height */ ++ sisfb_writew(sisfb, SIS530_2D_RECT_WIDTH, width); ++ sisfb_writew(sisfb, SIS530_2D_RECT_HEIGHT, height); ++ ++ /* setup the foreground color in Pattern Foreground Color Register */ ++ sisfb_writel(sisfb, SIS530_2D_PAT_FG_COLOR, fg); ++ ++ /* setup the foreground color in Pattern Background Color Register */ ++ sisfb_writel(sisfb, SIS530_2D_PAT_BG_COLOR, bg); ++ ++ /* store 8x8 mono bitmap to Mono Mask Register */ ++ sisfb_writel(sisfb, SIS530_2D_MONO_MASK, *(u32 *) bitmap); ++ sisfb_writel(sisfb, SIS530_2D_MONO_MASK + 4, *(u32 *) (bitmap + 4)); ++ ++ /* Command = Color Expand, X++, Y++, color = Mono Mask, ROP = rop */ ++ cmd = SIS530_2D_CMD_COLOREXP | SIS530_2D_CMD_PAT_MONO_MASK | ++ SIS530_2D_CMD_DIR_X_INC | SIS530_2D_CMD_DIR_Y_INC | (rop << 8); ++ ++ /* if background color == -1 then don't expand background pixels */ ++ if (bg == -1) ++ cmd |= SIS530_2D_CMD_TRANSPARENT; ++ ++ /* Fire The Command !! */ ++ sisfb_writel(sisfb, SIS530_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS530_2D_CMD_STATUS, 0); ++} ++ ++/** ++ * sisfb_color_expand: - Color expand with Pattern Register ++ * @sisfb: SiS Frame Buffer structure ++ * @x: X origin ++ * @y: Y origin ++ * @width: width ++ * @height: height ++ * @fg: foreground color to expand ++ * @bg: background color to expand ++ * @rop: Raster Operation for the expand ++ * @bitmap: monochrom bitmap (384 bytes max) ++ * @bitmap_pitch: pitch of @bitmap ++ * ++ * Color expand the bitmap @bitmap by setting bits with value 1 to @fg while bits ++ * with value 0 to @bg. If @bg == -1 then background pixels are not expanded. The ++ * bitmap is transfered to hardware Pattern Register and can be as large as 384 bytes, ++ * effectively expanding 3072 pixels in a single operation. ++ * ++ * The rectangle (@x, @y) - (@x + @width, @y + @height) is filled with the expanded ++ * pattern. If the size of @bitmap is samller then 384 bytes and the size of the ++ * rectangle is larger then 3072 pixels, some pixels in the rectangle are filled ++ * with "garbage". ++ * ++ * Note: ++ * 1. The Source Pitch is width/8 then rounded up (i.e. in units of byte). ++ * 2. We have to use Normal ROPs with color in Source FG/BG Color Register. ++ * ++ */ ++static void ++sisfb_color_expand(struct sisfb_info * sisfb, u32 x, u32 y, u32 width, u32 height, ++ u32 fg, u32 bg, u8 rop, u8 * bitmap, u32 bitmap_pitch) ++{ ++ u32 cmd; ++ u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; ++ ++ /* FixMe: What the hell is this ?? */ ++ sisfb_set_agp_base(sisfb); ++ ++ /* setup Source & Desination Pitch */ ++ sisfb_writew(sisfb, SIS530_2D_SRC_PITCH, bitmap_pitch); ++ sisfb_writew(sisfb, SIS530_2D_DST_PITCH, pitch); ++ ++ /* disable merge clipping */ ++ sisfb_writew(sisfb, SIS530_2D_DST_HEIGHT, -1); ++ ++ /* setup Source & Destination Base Address == (0, screen_offset) */ ++ sisfb_writel(sisfb, SIS530_2D_SRC_ADDR, 0); ++ sisfb_writel(sisfb, SIS530_2D_DST_ADDR, base); ++ ++ /* setup Source X and Y origin == (0, 0) */ ++ sisfb_writew(sisfb, SIS530_2D_SRC_X, 0); ++ sisfb_writew(sisfb, SIS530_2D_SRC_Y, 0); ++ ++ /* setup Destination X and Y origin == (x, y) */ ++ sisfb_writew(sisfb, SIS530_2D_DST_X, x); ++ sisfb_writew(sisfb, SIS530_2D_DST_Y, y); ++ ++ /* setup Rectangle Width and Height */ ++ sisfb_writew(sisfb, SIS530_2D_RECT_WIDTH, width); ++ sisfb_writew(sisfb, SIS530_2D_RECT_HEIGHT, height); ++ ++ /* setup the foreground color in Source Foreground Color Register */ ++ sisfb_writel(sisfb, SIS530_2D_SRC_FG_COLOR, fg); ++ ++ /* setup the foreground color in Source Background Color Register */ ++ sisfb_writel(sisfb, SIS530_2D_SRC_BG_COLOR, bg); ++ ++ /* transfer bitmap pattern to pattern register */ ++ memcpy_toio(sisfb->mmio_base_virt + SIS530_2D_PATTERN_REG, ++ bitmap, bitmap_pitch * height); ++ ++ /* Command = Color Expand, X++, Y++, color = Pattern Register, ROP = rop */ ++ cmd = SIS530_2D_CMD_COLOREXP |SIS530_2D_CMD_PAT_PAT_REG | ++ SIS530_2D_CMD_DIR_X_INC | SIS530_2D_CMD_DIR_Y_INC | (rop << 8); ++ ++ /* if background color == -1 then don't expand background pixels */ ++ if (bg == -1) ++ cmd |= SIS530_2D_CMD_TRANSPARENT; ++ ++ /* Fire The Command !! */ ++ sisfb_writel(sisfb, SIS530_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS530_2D_CMD_STATUS, 0); ++} ++ ++static void ++sisfb_drawline(struct sisfb_info * sisfb, u32 srcx, u32 srcy, ++ u32 dstx, u32 dsty, u32 fg, u32 bg, u8 rop) ++{ ++ u32 cmd; ++ u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; ++ ++ /* FixMe: What the hell is this ?? */ ++ sisfb_set_agp_base(sisfb); ++ ++ /* setup Source & Desination Pitch */ ++ sisfb_writew(sisfb, SIS530_2D_SRC_PITCH, 1); ++ sisfb_writew(sisfb, SIS530_2D_DST_PITCH, pitch); ++ ++ /* disable merge clipping */ ++ sisfb_writew(sisfb, SIS530_2D_DST_HEIGHT, -1); ++ ++ /* setup Source & Destination Base Address == (0, screen_offset) */ ++ sisfb_writel(sisfb, SIS530_2D_SRC_ADDR, 0); ++ sisfb_writel(sisfb, SIS530_2D_DST_ADDR, base); ++ ++ /* setup Source X and Y origin == (srcx, srcy) */ ++ sisfb_writew(sisfb, SIS530_2D_LINE_X0, srcx); ++ sisfb_writew(sisfb, SIS530_2D_LINE_Y0, srcy); ++ ++ /* setup Destination X and Y origin == (dstx, dsty) */ ++ sisfb_writew(sisfb, SIS530_2D_LINE_X1, dstx); ++ sisfb_writew(sisfb, SIS530_2D_LINE_Y1, dsty); ++ ++ /* setup Line Segement Count == 1 */ ++ sisfb_writew(sisfb, SIS530_2D_LINE_COUNT, 1); ++ sisfb_writew(sisfb, SIS530_2D_LINE_STYLE_PERIOD, 0); ++ ++ /* setup the foreground color in Pattern Foreground Color Register */ ++ sisfb_writel(sisfb, SIS530_2D_PAT_FG_COLOR, fg); ++ ++ /* setup the foreground color in Pattern Background Color Register */ ++ sisfb_writel(sisfb, SIS530_2D_PAT_BG_COLOR, bg); ++ ++ /* Command = Color Expand, X++, Y++, color = Pattern Foreground Register, ROP = rop */ ++ cmd = SIS530_2D_CMD_LINE_DRAW | SIS530_2D_CMD_PAT_FG_REG | ++ (rop << 8); ++ ++ /* Fire The Command !! */ ++ sisfb_writel(sisfb, SIS530_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS530_2D_CMD_STATUS, 0); ++} ++ ++static void ++sisfb_drawline_style(struct sisfb_info * sisfb, u32 srcx, u32 srcy, ++ u32 dstx, u32 dsty, u32 fg, u32 bg, u8 rop, u8 * bitmap) ++{ ++ u32 cmd; ++ u16 pitch = sisfb->current_par.line_length; ++ u32 base = sisfb->current_par.screen_offset; ++ ++ /* FixMe: What the hell is this ?? */ ++ sisfb_set_agp_base(sisfb); ++ ++ /* setup Source & Desination Pitch */ ++ sisfb_writew(sisfb, SIS530_2D_SRC_PITCH, 1); ++ sisfb_writew(sisfb, SIS530_2D_DST_PITCH, pitch); ++ ++ /* disable merge clipping */ ++ sisfb_writew(sisfb, SIS530_2D_DST_HEIGHT, -1); ++ ++ /* setup Source & Destination Base Address == (0, 0) */ ++ sisfb_writel(sisfb, SIS530_2D_SRC_ADDR, 0); ++ sisfb_writel(sisfb, SIS530_2D_DST_ADDR, base); ++ ++ /* setup Source X and Y origin == (srcx, srcy) */ ++ sisfb_writew(sisfb, SIS530_2D_LINE_X0, srcx); ++ sisfb_writew(sisfb, SIS530_2D_LINE_Y0, srcy); ++ ++ /* setup Destination X and Y origin == (dstx, dsty) */ ++ sisfb_writew(sisfb, SIS530_2D_LINE_X1, dstx); ++ sisfb_writew(sisfb, SIS530_2D_LINE_Y1, dsty); ++ ++ /* setup Line Segment Count == 1 */ ++ sisfb_writew(sisfb, SIS530_2D_LINE_COUNT, 1); ++ sisfb_writew(sisfb, SIS530_2D_LINE_STYLE_PERIOD, 0); ++ ++ /* setup the foreground color in Pattern Foreground Color Register */ ++ sisfb_writel(sisfb, SIS530_2D_PAT_FG_COLOR, fg); ++ ++ /* setup the foreground color in Pattern Background Color Register */ ++ sisfb_writel(sisfb, SIS530_2D_PAT_BG_COLOR, bg); ++ ++ /* transfer bitmap pattern to Line Style register */ ++ sisfb_writel(sisfb, SIS530_2D_LINE_STYLE_0, * bitmap); ++ sisfb_writel(sisfb, SIS530_2D_LINE_STYLE_1, *(bitmap + 1)); ++ ++ /* Command = Color Expand, X++, Y++, color = Pattern Register, ROP = rop */ ++ cmd = SIS530_2D_CMD_LINE_DRAW | SIS530_2D_CMD_PAT_FG_REG | ++ SIS530_2D_CMD_LINE_STLYE_ENABLE | (rop << 8); ++ ++ /* Fire The Command !! */ ++ sisfb_writel(sisfb, SIS530_2D_CMD, cmd); ++ sisfb_writel(sisfb, SIS530_2D_CMD_STATUS, 0); ++} ++ ++struct sisfb_accelerator sis530_accelerator = { ++ fillrect: sisfb_fillrect, ++ copyrect: sisfb_copyrect, ++ copyrect_transparent: sisfb_copyrect_transparent, ++ ++ color_expand_8x8: sisfb_8x8_color_expand, ++ color_expand: sisfb_color_expand, ++ ++ drawline: sisfb_drawline, ++ drawline_style: sisfb_drawline_style, ++}; +diff -urN linux-2.4.19/drivers/video/sis/sisfb_530_accel.h linux-2.4.19-linuxbios/drivers/video/sis/sisfb_530_accel.h +--- linux-2.4.19/drivers/video/sis/sisfb_530_accel.h Thu Jan 1 08:00:00 1970 ++++ linux-2.4.19-linuxbios/drivers/video/sis/sisfb_530_accel.h Mon Sep 2 17:23:10 2002 +@@ -0,0 +1,72 @@ ++#ifndef __SISFB_530_ACCEL__ ++#define __SISFB_530_ACCEL__ ++ ++#include "sisfb_accel.h" ++ ++enum sis530_2d_registers { ++ SIS530_2D_SRC_ADDR = 0x8200, ++ SIS530_2D_SRC_PITCH = 0x8204, SIS530_2D_AGP_BASE = 0x8206, ++ SIS530_2D_SRC_Y = 0x8208, SIS530_2D_SRC_X = 0x820A, ++ SIS530_2D_DST_Y = 0x820C, SIS530_2D_DST_X = 0x820E, ++ SIS530_2D_DST_ADDR = 0x8210, ++ SIS530_2D_DST_PITCH = 0x8214, SIS530_2D_DST_HEIGHT = 0x8216, ++ SIS530_2D_RECT_WIDTH = 0x8218, SIS530_2D_RECT_HEIGHT = 0x821A, ++ SIS530_2D_PAT_FG_COLOR = 0x821C, ++ SIS530_2D_PAT_BG_COLOR = 0x8220, ++ SIS530_2D_SRC_FG_COLOR = 0x8224, ++ SIS530_2D_SRC_BG_COLOR = 0x8228, ++ SIS530_2D_MONO_MASK = 0x822C, ++ SIS530_2D_LEFT_CLIP = 0x8234, SIS530_2D_TOP_CLIP = 0x8236, ++ SIS530_2D_RIGHT_CLIP = 0x8238, SIS530_2D_BOT_CLIP = 0x823A, ++ SIS530_2D_CMD = 0x823C, ++ SIS530_2D_CMD_STATUS = 0x8240, ++ SIS530_2D_PATTERN_REG = 0x8300 ++}; ++ ++enum sis530_2d_registers_drawline { ++ SIS530_2D_LINE_X0 = 0x8208, SIS530_2D_LINE_Y0 = 0x820A, ++ SIS530_2D_LINE_X1 = 0x820C, SIS530_2D_LINE_Y1 = 0x820E, ++ SIS530_2D_LINE_COUNT = 0x8218, SIS530_2D_LINE_STYLE_PERIOD = 0x821A, ++ SIS530_2D_LINE_STYLE_0 = 0x822C, ++ SIS530_2D_LINE_STYLE_1 = 0x8230, ++ SIS530_2D_LINE_Xn = 0x8300, SIS530_2D_LINE_Yn = 0x8302, ++}; ++ ++enum sis530_2d_register_transparent_bitblt { ++ SIS530_2D_TRANS_DEST_KEY_HIGH = 0x821C, ++ SIS530_2D_TRANS_DEST_KEY_LOW = 0x8220, ++ SIS530_2D_TRANS_SRC_KEY_HIGH = 0x8224, ++ SIS530_2D_TRANS_SRC_KEY_LOW = 0x8228, ++}; ++ ++enum sis530_2d_cmd_type { ++ SIS530_2D_CMD_BITBLT = 0x00, SIS530_2D_CMD_COLOREXP = 0x01, ++ SIS530_2D_CMD_ENCOLOREXP = 0x02, SIS530_2D_CMD_MULTIPLE_SCANLINE = 0x03, ++ SIS530_2D_CMD_LINE_DRAW = 0x04, SIS530_2D_CMD_TRAPEZOID_FILL = 0x05, ++ SIS530_2D_CMD_TRANSPARENT_BITBLT = 0x06 ++}; ++ ++enum sis530_2d_cmd_control { ++ SIS530_2D_CMD_SRC_VIDEO = 0x00, ++ SIS530_2D_CMD_SRC_SYSTEM = 0x10, ++ SIS530_2D_CMD_SRC_AGP = 0x20, ++ ++ SIS530_2D_CMD_PAT_FG_REG = 0x00, ++ SIS530_2D_CMD_PAT_PAT_REG = 0x40, ++ SIS530_2D_CMD_PAT_MONO_MASK = 0x80, ++ ++ SIS530_2D_CMD_DIR_X_INC = 0x00010000, ++ SIS530_2D_CMD_DIR_X_DEC = 0x00000000, ++ SIS530_2D_CMD_DIR_Y_INC = 0x00020000, ++ SIS530_2D_CMD_DIR_Y_DEC = 0x00000000, ++ ++ SIS530_2D_CMD_RECT_CLIP_EN = 0x00040000, ++ SIS530_2D_CMD_MERGE_CLIP_DIS = 0x04000000, ++ SIS530_2D_CMD_TRANSPARENT = 0x00100000, ++ ++ SIS530_2D_CMD_LINE_STLYE_ENABLE = 0x00800000 ++}; ++ ++extern struct sisfb_accelerator sis530_accelerator; ++ ++#endif /* __SISFB_530_ACCEL__ */ +diff -urN linux-2.4.19/drivers/video/sis/sisfb_530_core.c linux-2.4.19-linuxbios/drivers/video/sis/sisfb_530_core.c +--- linux-2.4.19/drivers/video/sis/sisfb_530_core.c Thu Jan 1 08:00:00 1970 ++++ linux-2.4.19-linuxbios/drivers/video/sis/sisfb_530_core.c Mon Sep 2 17:23:10 2002 +@@ -0,0 +1,333 @@ ++/* sisfb_530_core.c: Setting Video Mode for SiS 530/620 Integrated VGA ++ * ++ * Copyright 2001 Ollie Lho ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ * This driver is implemented by the Author for his own personal interests and is NOT a ++ * commitment NOR supported officially by Silicon Integrated Systems Corp. Please direct ++ * any bug report/question to the Author and don't bother SiS Technical Support Personell. ++ * ++ * ++ * Reference: ++ * 1. SiS 530 Host, PCI, 3D Graphics & Memory Controller Datasheet, ++ * Preliminary v1.0 Nov. 10, 1998 ++ */ ++ ++#include "sisfb_lite.h" ++#include "sisfb_530_core.h" ++ ++static void sisfb_get_clock(struct sisfb_info * sisfb, struct sisfb_clock_param * clock, int which); ++static void sisfb_set_clock(struct sisfb_info * sisfb, struct sisfb_clock_param * clock, int which); ++static void sisfb_set_memory_clocks(struct sisfb_info * sisfb); ++static int sisfb_get_memory_size(struct sisfb_info * sisfb); ++static void sisfb_set_crt1_crtc_regs(struct sisfb_info * sisfb, struct sisfb_par * par); ++static void sisfb_set_crt1_mode_regs(struct sisfb_info * sisfb, struct sisfb_par * par); ++static void sisfb_set_crt1_pitch(struct sisfb_info * sisfb, struct sisfb_par * par); ++static void sisfb_set_crt1_offset(struct sisfb_info * sisfb, struct sisfb_par * par); ++static void sisfb_set_crt1_vclk(struct sisfb_info * sisfb, struct sisfb_par * par); ++static int sisfb_set_fifo_thresholds(struct sisfb_info * sisfb, struct sisfb_par * par); ++ ++/** ++ * sisfb_get_clock: - Read the clock generator parameters ++ * @sisfb: SiS Frame Buffer structure ++ * @clock: Paramters of the clock generator (return) ++ * @which: Which clock generator to be read. ++ * ++ * Read the clock generator parameters to @clock form the hardware. The desired ++ * clock generator is specified by @which. Valid values are MCLK for memory clock, ++ * VCLK for video dot clock. ++ */ ++static void ++sisfb_get_clock(struct sisfb_info * sisfb, struct sisfb_clock_param * clock, int which) ++{ ++ u8 data, data1; ++ ++ /* get divider and numerator */ ++ data = sisfb_get_seq_reg(sisfb, which); ++ clock->divider = ((data & 0x80) >> 7) + 1; ++ clock->numerator = (data & ~0x80) + 1; ++ ++ /* get denumerator and post scalar */ ++ data = sisfb_get_seq_reg(sisfb, which + 1); ++ clock->denumerator = (data & 0x1F) + 1; ++ ++ /* Bit 2 of post scaler is in SR13 */ ++ data1 = sisfb_get_seq_reg(sisfb, SIS530_CLK); ++ if (which == SIS530_MCLK) { ++ data1 &= 0x80; ++ data1 >>= 5; ++ } else { ++ data1 &= 0x40; ++ data1 >>= 4; ++ } ++ clock->post_scalar = ((data & 0x60) >> 5) | data1; ++ ++ /* get VCO gain */ ++ data = sisfb_get_seq_reg(sisfb, which + 1); ++ clock->vco_gain = (data >> 7); ++} ++ ++/** ++ * sisfb_set_clock: - Set the clock generator parameters ++ * @sisfb: SiS Frame Buffer structure ++ * @clock: Paramters of the clock generator ++ * @which: Which clock generator to be read. ++ * ++ * Set the clock generator parameters @clock to the hardware. The desired clock ++ * generator is specified by @which. Valid values are MCLK for memory clock, ++ * VCLK for video dot clock. ++ */ ++static void ++sisfb_set_clock(struct sisfb_info * sisfb, struct sisfb_clock_param * clock, int which) ++{ ++ u8 data, data1; ++ ++ /* set divider and numerator */ ++ data = (clock->numerator - 1) & 0x7F; ++ data |= (clock->divider - 1) ? 0x80 : 0x00; ++ sisfb_set_seq_reg(sisfb, which, data); ++ ++ /* set denumerator and post scalar */ ++ data = (clock->denumerator - 1) & 0x1F; ++ data |= ((clock->post_scalar - 1) & 0x03) << 5; ++ /* set VCO gain */ ++ data |= clock->vco_gain ? 0x80 : 0x00; ++ sisfb_set_seq_reg(sisfb, which + 1, data); ++ ++ /* set Bit 2 of post scalar ++ * FixMe: sis86c201.c says SIS530_CLK should be set fist */ ++ data = sisfb_get_seq_reg(sisfb, SIS530_CLK); ++ if (which == SIS530_MCLK) { ++ data &= ~0x80; ++ data |= ((clock->post_scalar - 1) & 0x04) << 5; ++ } else { ++ data &= ~0x40; ++ data |= ((clock->post_scalar - 1) & 0x04) << 4; ++ } ++ sisfb_set_seq_reg(sisfb, SIS530_CLK, data); ++} ++ ++/** ++ * sisfb_set_memory_clocks: - Set memory bus clock rate ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Set the memory clocks for VGA core. ++ */ ++extern unsigned long mclk, eclk; ++static void __devinit ++sisfb_set_memory_clocks(struct sisfb_info * sisfb) ++{ ++ struct sisfb_clock_param clock; ++ ++ /* set the clock rate according to the option */ ++ sisfb_calc_clock_param(&clock, mclk); ++ sisfb_set_clock(sisfb, &clock, SIS530_MCLK); ++ ++ /* read the clock rate back and show to user */ ++ sisfb_get_clock(sisfb, &clock, SIS300_MCLK); ++ printk(KERN_INFO "sisfb_lite: 2D Memory Clock = %6ld KHz\n", ++ sisfb_calc_clock_freq(&clock)); ++} ++ ++/** ++ * sisfb_get_memory_size: - Get framebuffer memory size ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Return 0 on Success, -ENODEV if SMA is incorrectly/not configured ++ * ++ * Get the framebuffer memory size from host controller. For SiS 530/620 Families, ++ * the Shared Memory Area (SMA) is enabled in Bit 6, size is stored in Bit 4..5 of ++ * Register 0x63, Host Bridge (i.e. PCI 0:0.0). ++ * ++ * The register is set by DRAM initialzation code during boot process and can ++ * not be re-configured once the DRAM has been turned on. ++ */ ++#define SIS530_BANKENABLE 0x63 ++static int __devinit ++sisfb_get_memory_size(struct sisfb_info * sisfb) ++{ ++ struct pci_dev * host = NULL; ++ u8 dram_status, sma_size, sma_size_bits; ++ ++ if ((host = pci_find_slot(0, 0)) == NULL) { ++ printk(KERN_EMERG "sisfb_lite: Can not find Host Controller !!!\n"); ++ return -ENODEV; ++ } ++ ++ /* get SMA configuration from register 0x63 */ ++ pci_read_config_byte(host, SIS530_BANKENABLE, &dram_status); ++ ++ /* SMA not enabled */ ++ if ((dram_status & 0x40) != 0x40) ++ return -ENODEV; ++ ++ /* compute Shared Menory Area (SMA) size in Mega Bytes */ ++ sma_size_bits = (dram_status >> 4) & 0x3; ++ sma_size = (2 << sma_size_bits); ++ sisfb->video_size_virt = sma_size * 1024 * 1024; ++ ++ return 0; ++} ++ ++static void ++sisfb_set_crt1_crtc_regs(struct sisfb_info * sisfb, struct sisfb_par * par) ++{ ++ u8 data; ++ u16 htotal, hdispend, hsyncstart, hsyncend, hblankstart, hblankend; ++ u16 vtotal, vdispend, vsyncstart, vsyncend, vblankstart, vblankend; ++ u16 overflow, overflow_h1, overflow_h2, overflow_v; ++ ++ /* first convert 'par' to "screen" unit */ ++ htotal = (par->htotal >> 3) - 5; ++ hdispend = (par->hdispend >> 3) - 1; ++ hblankstart = (par->hsyncstart >> 3) - 1; ++ hblankend = (par->hsyncend >> 3); ++ hsyncstart = (par->hsyncstart >> 3); ++ hsyncend = (par->hsyncend >> 3); ++ ++ vtotal = par->vtotal - 2; ++ vdispend = par->vdispend - 1; ++ vsyncstart = par->vsyncstart; ++ vsyncend = par->vsyncend; ++ vblankstart = par->vsyncstart; ++ vblankend = par->vsyncend + 1; ++ ++ /* the "overlow" bits (8:15) of the screen parameters are spread all over ++ * various registers */ ++ overflow = ++ ((vsyncstart & 0x200) >> 2) | /* Bit 7, Vertical Retrace Start Bit 9 */ ++ ((vdispend & 0x200) >> 3) | /* Bit 6, Vertical Display End Bit 9 */ ++ ((vtotal & 0x200) >> 4) | /* Bit 5, Vertical Total Bit 9 */ ++ 0x10 | /* Bit 4, line compare Bit 8 */ ++ ((vblankstart & 0x100) >> 5) | /* Bit 3, Vertical Blank Start Bit 8 */ ++ ((vsyncstart & 0x100) >> 6) | /* Bit 2, Vertical Retrace Start Bit 8 */ ++ ((vdispend & 0x100) >> 7) | /* Bit 1, Vertical Display End Bit 8 */ ++ ((vtotal & 0x100) >> 8); /* Bit 0, Vertical Total Bit 8 */ ++ ++ overflow_v = ++ ((vsyncstart & 0x400) >> 7) | /* Bit 3, Vertical Retrace Start Bit 10 */ ++ ((vblankstart & 0x400) >> 8) | /* Bit 2, Vertical Blank Start Bit 10 */ ++ ((vdispend & 0x400) >> 9) | /* Bit 1, Vertical Display End Bit 10 */ ++ ((vtotal & 0x400) >> 10); /* Bit 0, Vertical Total Bit 10 */ ++ ++ overflow_h = ++ ((hblankend & 0x040) >> 2) | /* Bit 4, Horizontal Blank End Bit 6 */ ++ ((hsyncstart & 0x100) >> 5) | /* Bit 3, Horizontal Retrace Start Bit 8 */ ++ ((hblankstart & 0x100) >> 6) | /* Bit 2, Horizontal Blank Start Bit 8 */ ++ ((hdispend & 0x100) >> 7) | /* Bit 1, Horizontal Display End Bit 8 */ ++ ((htotal & 0x100) >> 8); /* Bit 0, Horizontal Total Bit 8 */ ++ ++ /* write 'par' to hardware registers, Standard VGA part, low order bits */ ++ sisfb_set_crtc_reg(sisfb, 0x00, htotal); ++ sisfb_set_crtc_reg(sisfb, 0x01, hdispend); ++ sisfb_set_crtc_reg(sisfb, 0x02, hblankstart); ++ sisfb_set_crtc_reg(sisfb, 0x03, ++ 0x80 | /* Bit 7, Enable Vertical Retrace Start/End */ ++ (hblankend & 0x1f)); /* Bit 0:4, Horizontal Blank End Bit 0:4 */ ++ sisfb_set_crtc_reg(sisfb, 0x04, hsyncstart); ++ sisfb_set_crtc_reg(sisfb, 0x05, ++ (hblankend & 0x20) << 2 | /* Bit 7, Horizontal Blank End Bit 5 */ ++ (hsyncend & 0x1f)); /* Bit 0:4, Horizontal Retrace End Bit 0:4 */ ++ sisfb_set_crtc_reg(sisfb, 0x06, vtotal); ++ sisfb_set_crtc_reg(sisfb, 0x09, ++ 0x40 | /* Bit 6, line compare Bit 9 */ ++ (vblankstart & 0x200) >> 4); /* Bit 5, Vertical Blank Start Bit 9 */ ++ sisfb_set_crtc_reg(sisfb, 0x10, vsyncstart); ++ sisfb_set_crtc_reg(sisfb, 0x11, (vsyncend & 0x0F) | 0x20); ++ sisfb_set_crtc_reg(sisfb, 0x12, vdispend); ++ sisfb_set_crtc_reg(sisfb, 0x15, vblankstart); ++ sisfb_set_crtc_reg(sisfb, 0x16, vblankend); ++ ++ /* Standard VGA part, overflow bits */ ++ sisfb_set_crtc_reg(sisfb, 0x07, overflow); ++ ++ /* Extended Registers, overflow bits */ ++ data = sisfb_get_seq_reg(sisfb, 0x0A) & 0xF0; ++ sisfb_set_seq_reg(sisfb, 0x0A, data | overflow_v); ++ data = sisfb_get_seq_reg(sisfb, 0x12) & 0xE0; ++ sisfb_set_seq_reg(sisfb, 0x0B, data | overflow_h); ++} ++ ++/** ++ * sisfb_set_crt1_mode_regs: - Set misc video mode registers ++ * @sisfb: SiS Frame Buffer structure ++ * @par: hardware specific parameters ++ * ++ * Set color depth and enable 2D engine. The display line width register SR 0x10 ++ * is also enabled. ++ */ ++static void ++sisfb_set_crt1_mode_regs(struct sisfb_info * sisfb, struct sisfb_par * par) ++{ ++ u8 tmp; ++ ++ /* enable Linear Addressing, Enhanced Graphics/Text Mode */ ++ tmp = 0x83; ++ switch (par->bits_per_pixel) { ++ case 32: ++ tmp |= 0x10; ++ break; ++ case 16: ++ tmp |= 0x08; ++ break; ++ case 8: ++ default: ++ break; ++ } ++ sisfb_set_seq_reg(sisfb, 0x06, tmp); ++ ++ /* enable 32 bpp ture color (instead of 24 ??) */ ++ if (par->bits_per_pixel == 32) { ++ tmp = sisfb_get_seq_reg(sisfb, 0x09) | 0x80; ++ sisfb_set_seq_reg(sisfb, 0x09, tmp); ++ tmp = sisfb_get_seq_reg(sisfb, 0x0B) | 0x80; ++ sisfb_set_seq_reg(sisfb, 0x0B, tmp); ++ } ++ ++ /* enable 2D engine programming, disable logical screen width ++ * FixMe: move to init.c */ ++ tmp = sisfb_get_seq_reg(sisfb, 0x27) | 0x70; ++ sisfb_set_seq_reg(sisfb, 0x27, tmp); ++} ++ ++/** ++ * sisfb_set_crt1_pitch: - Set screen pitch registers for CRT1 ++ * @sisfb: SiS Frame Buffer structure ++ * @par: hardware specific parameters ++ * ++ * Set the screen pitch registers for CRT1. Screen pitch refers to the memory address ++ * difference between two dots of the same col on two vertically neighboring scan lines. ++ * The CRTC 0x13 is called "offset register" in VGA literatures. ++ */ ++static void ++sisfb_set_crt1_pitch(struct sisfb_info * sisfb, struct sisfb_par * par) ++{ ++ u8 data; ++ u16 pitch = par->line_length >> 3; ++ u8 line_length = ((par->line_length + 63) >> 6) + 1; ++ ++ /* disable line compare ++ * FixMe: move to init.c */ ++ data = sisfb_get_seq_reg(sisfb, 0x38) | 0x20; ++ sisfb_set_seq_reg(sisfb, 0x38, data); ++ ++ /* screen pitch, in units of double word */ ++ sisfb_set_crtc_reg(sisfb, 0x13, pitch & 0xFF); ++ tmp = sisfb_get_seq_reg(sisfb, 0x0A); ++ sisfb_set_seq_reg(sisfb, 0x0A, (pitch >> 8) & tmp); ++} ++ +diff -urN linux-2.4.19/drivers/video/sis/sisfb_530_core.h linux-2.4.19-linuxbios/drivers/video/sis/sisfb_530_core.h +--- linux-2.4.19/drivers/video/sis/sisfb_530_core.h Thu Jan 1 08:00:00 1970 ++++ linux-2.4.19-linuxbios/drivers/video/sis/sisfb_530_core.h Mon Sep 2 17:23:10 2002 +@@ -0,0 +1,17 @@ ++#ifndef __SISFB_530_CORE__ ++#define __SISFB_530_CORE__ ++ ++#define TURBO_QUEUE_AREA_SIZE 0x80000 /* 512K */ ++#define HW_CURSOR_AREA_SIZE 0x1000 /* 4K */ ++ ++enum clock_gen_base { ++ SIS530_CLK = 0x13, ++ SIS530_MCLK = 0x28, ++ SIS530_DCLK = 0x2A, ++}; ++ ++extern int sisfb_config_memory(struct sisfb_info * sisfb); ++extern int sisfb_pan_display_300(struct fb_var_screeninfo * var, struct sisfb_info * sisfb); ++extern void sisfb_set_par_300(struct sisfb_par *par, struct sisfb_info * sisfb); ++ ++#endif /* __SISFB_300_CORE__ */ +diff -urN linux-2.4.19/drivers/video/sis/sisfb_530_init.c linux-2.4.19-linuxbios/drivers/video/sis/sisfb_530_init.c +--- linux-2.4.19/drivers/video/sis/sisfb_530_init.c Thu Jan 1 08:00:00 1970 ++++ linux-2.4.19-linuxbios/drivers/video/sis/sisfb_530_init.c Mon Sep 2 17:23:10 2002 +@@ -0,0 +1,113 @@ ++/* sisfb_530_init.c: Initialization code for SiS 530/620 Integrated VGA ++ * ++ * Copyright 2001 Ollie Lho ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ * This driver is implemented by the Author for his own personal interests and is NOT a ++ * commitment NOR supported officially by Silicon Integrated Systems Corp. Please direct ++ * any bug report/question to the Author and don't bother SiS Technical Support Personell. ++ * ++ * ++ * Reference: ++ * 1. SiS 6326 AGP/PCI Graphics & Video Acclerator. Rev 1.0, May 12, 1997 ++ * 2. SiS 530 Host, PCI, 3D Graphics & Memory Controller Datasheet, ++ * Preliminary v1.0 Nov. 10, 1998 ++ */ ++ ++#include "sisfb_lite.h" ++#include "sisfb_530_core.h" ++#include "sisfb_530_accel.h" ++ ++/** ++ * sisfb_enable_turbo_queue: - Set Turbo Queue size and enable it ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Commands to the Graphics Engine (2D, 3D, etc) are buffered in ++ * the Video Memory which is called Turbo Queue in SiS VGA Specs. ++ * Usually this buffer area takes the last few KBs in the Video RAM. ++ */ ++/* default turbo queue size == 32KB */ ++static int tqueue_size = 0x8000; ++static void __devinit ++sisfb_enable_turbo_queue(struct sisfb_info * sisfb) ++{ ++ u32 tqueue_pos; ++ u8 tqueue_status; ++ ++ /* turbo queue position, in units of 32KB */ ++ tqueue_pos = sisfb->video_size_virt - tqueue_size; ++ tqueue_pos /= 0x8000; ++ ++ /* enable Turbo Tueue and Graphics Engine Programming */ ++ tqueue_status = sisfb_get_seq_reg(sisfb, 0x27); ++ tqueue_status |= 0x80; ++ ++ sisfb_set_seq_reg(sisfb, 0x27, tqueue_status); ++ sisfb_set_seq_reg(sisfb, 0x2C, tqueue_pos); ++ ++ printk(KERN_INFO "sisfb_lite: Use %dKB off-screen memory for Turbo Queue\n", ++ tqueue_size / 1024); ++ ++} ++ ++/** ++ * sisfb_init_530: - Initialize the SiS530 VGA Core in SiS 530/620 ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Return 0 on Success, -ENODEV if SMA is incorrectly/not configured ++ * ++ * SiS 300 VGA core is used in SiS 530/620 chipsets. This routine inits ++ * the very SiS300 specific stuff. ++ */ ++int __devinit ++sisfb_init_530(struct sisfb_info * sisfb) ++{ ++ int ret; ++ ++ if ((ret = sisfb_config_memory(sisfb)) < 0) ++ return ret; ++ ++ sisfb_init_legacy_vga(sisfb); ++ ++#if 0 ++ /* set to High Speed DAC by default */ ++ sisfb_set_seq_reg(sisfb, 0x07, 0x13); ++ ++ /* Disable DAC pedestal */ ++ sisfb_set_seq_reg(sisfb, 0x1F, 0x00); ++ ++ sisfb_set_pci_agp_timming(sisfb); ++ ++ /* disable power management mode */ ++ sisfb_set_seq_reg(sisfb, 0x11, 0x0F); ++ ++ /* set screen start memory address bit 23:16 to 0, bit 15:0 are in CR0C, CR0D */ ++ sisfb_set_seq_reg(sisfb, 0x0D, 0x00); ++ ++ sisfb_enable_turbo_queue(sisfb); ++ ++ sisfb_fake_vgabios(sisfb); ++#endif ++ ++ /* set hardware specific functions */ ++ sisfb->accelerator = &sis530_accelerator; ++ sisfb->set_par = sisfb_set_par_530; ++ sisfb->pan_display = sisfb_pan_display_53; ++ sisfb->set_disp = sisfb_set_dispsw_accel; ++ ++ return 0; ++} +diff -urN linux-2.4.19/drivers/video/sis/sisfb_accel.c linux-2.4.19-linuxbios/drivers/video/sis/sisfb_accel.c +--- linux-2.4.19/drivers/video/sis/sisfb_accel.c Thu Jan 1 08:00:00 1970 ++++ linux-2.4.19-linuxbios/drivers/video/sis/sisfb_accel.c Mon Sep 2 17:23:10 2002 +@@ -0,0 +1,359 @@ ++/* sisfb_accel.c: Generic 2D Hardware Acceleration Layer for Text Mode Console (fbcon) ++ * ++ * Copyright 2001 Ollie Lho ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ * This driver is implemented by the Author for his own personal interests and is NOT a ++ * commitment NOR supported officially by Silicon Integrated Systems Corp. Please direct ++ * any bug report/question to the Author and don't bother SiS Technical Support Personell. ++ * ++ * ++ * Reference: ++ */ ++ ++#include "sisfb_accel.h" ++ ++static void ++sisfb_cfbX_bmove(struct display *disp, int sy, int sx, int dy, int dx, ++ int height, int width) ++{ ++ struct sisfb_info *sisfb = (struct sisfb_info *) (disp->fb_info); ++ struct sisfb_accelerator * accel = ++ (struct sisfb_accelerator *) (sisfb->accelerator); ++ ++ sx *= fontwidth(disp); ++ sy *= fontheight(disp); ++ dx *= fontwidth(disp); ++ dy *= fontheight(disp); ++ width *= fontwidth(disp); ++ height *= fontheight(disp); ++ ++ accel->copyrect(sisfb, sx, sy, dx, dy, width, height, ROP_COPY); ++} ++ ++static void ++sisfb_cfbX_clear(struct display *disp, int sy, int sx, int height, ++ int width, u32 color) ++{ ++ struct sisfb_info *sisfb = (struct sisfb_info *) (disp->fb_info); ++ struct sisfb_accelerator * accel = ++ (struct sisfb_accelerator *) (sisfb->accelerator); ++ ++ sx *= fontwidth(disp); ++ sy *= fontheight(disp); ++ width *= fontwidth(disp); ++ height *= fontheight(disp); ++ ++ accel->fillrect(sisfb, sx, sy, width, height, color, ROP_COPY_PAT); ++} ++ ++static void ++sisfb_cfbX_putc(struct display *disp, int c, int sy, int sx, u32 fg, u32 bg) ++{ ++ struct sisfb_info *sisfb = (struct sisfb_info *) (disp->fb_info); ++ struct sisfb_accelerator * accel = ++ (struct sisfb_accelerator *) (sisfb->accelerator); ++ int width = fontwidth(disp); ++ int height = fontheight(disp); ++ int width_b = (width + 7) >> 3; ++ u8 * bitmap = disp->fontdata + (c & disp->charmask) * height * width_b; ++ ++ sx *= fontwidth(disp); ++ sy *= fontheight(disp); ++ ++ accel->color_expand(sisfb, sx, sy, width, height, fg, bg, ++ ROP_COPY, bitmap, width_b); ++} ++ ++static void ++sisfb_cfbX_putcs(struct display *disp, unsigned short * s, int count, ++ int sy, int sx, u32 fg, u32 bg) ++{ ++ struct sisfb_info *sisfb = (struct sisfb_info *) (disp->fb_info); ++ struct sisfb_accelerator * accel = ++ (struct sisfb_accelerator *) (sisfb->accelerator); ++ int width = fontwidth(disp); ++ int height = fontheight(disp); ++ int width_b = (width + 7) >> 3; ++ ++ sx *= fontwidth(disp); ++ sy *= fontheight(disp); ++ ++ while (count--) { ++ u16 c; ++ u8 * bitmap; ++ ++ c = scr_readw(s++) & disp->charmask; ++ bitmap = disp->fontdata + c * height * width_b; ++ ++ accel->color_expand(sisfb, sx, sy, width, height, fg, bg, ++ ROP_COPY, bitmap, width_b); ++ ++ sx += fontwidth(disp); ++ } ++} ++ ++static void ++sisfb_cfbX_revc(struct display *disp, int sx, int sy) ++{ ++ struct sisfb_info *sisfb = (struct sisfb_info *) (disp->fb_info); ++ struct sisfb_accelerator * accel = ++ (struct sisfb_accelerator *) (sisfb->accelerator); ++ int width = fontwidth(disp); ++ int height = fontheight(disp); ++ int bpp = sisfb->current_par.bits_per_pixel; ++ ++ accel->fillrect(sisfb, sx * width, sy * height, width, height, ++ (bpp == 8) ? 0x0f : 0xffffffff, ROP_XOR_PAT); ++} ++ ++#ifdef FBCON_HAS_CFB8 ++static void ++sisfb_cfb8_clear(struct vc_data *conp, struct display *disp, ++ int sy, int sx, int height, int width) ++{ ++ u32 color; ++ ++ color = attr_bgcol_ec(disp, conp); ++ ++ sisfb_cfbX_clear(disp, sy, sx, height, width, color); ++} ++#endif ++ ++#ifdef FBCON_HAS_CFB16 ++static void ++sisfb_cfb16_clear(struct vc_data *conp, struct display *disp, ++ int sy, int sx, int height, int width) ++{ ++ u32 color; ++ ++ color = ((u16 *) disp->dispsw_data)[attr_bgcol_ec(disp, conp)]; ++ ++ sisfb_cfbX_clear(disp, sy, sx, height, width, color); ++} ++#endif ++ ++#ifdef FBCON_HAS_CFB32 ++static void ++sisfb_cfb32_clear(struct vc_data * conp, struct display * disp, ++ int sy, int sx, int height, int width) ++{ ++ u32 color; ++ ++ color = ((u32 *) disp->dispsw_data)[attr_bgcol_ec(disp, conp)]; ++ sisfb_cfbX_clear(disp, sy, sx, height, width, color); ++} ++#endif ++ ++#ifdef FBCON_HAS_CFB8 ++static void ++sisfb_cfb8_putc(struct vc_data * conp, struct display * disp, int c, int sy, int sx) ++{ ++ u32 fg, bg; ++ ++ fg = attr_fgcol(disp, c); ++ bg = attr_bgcol(disp, c); ++ ++ sisfb_cfbX_putc(disp, c, sy, sx, fg, bg); ++} ++#endif ++ ++#ifdef FBCON_HAS_CFB16 ++static void ++sisfb_cfb16_putc(struct vc_data * conp, struct display * disp, int c, int sy, int sx) ++{ ++ u32 fg, bg; ++ ++ fg = ((u16 *)disp->dispsw_data)[attr_fgcol(disp, c)]; ++ bg = ((u16 *)disp->dispsw_data)[attr_bgcol(disp, c)]; ++ ++ sisfb_cfbX_putc(disp, c, sy, sx, fg, bg); ++} ++#endif ++ ++#ifdef FBCON_HAS_CFB32 ++static void ++sisfb_cfb32_putc(struct vc_data * conp, struct display * disp, int c, int sy, int sx) ++{ ++ u32 fg, bg; ++ ++ fg = ((u32 *)disp->dispsw_data)[attr_fgcol(disp, c)]; ++ bg = ((u32 *)disp->dispsw_data)[attr_bgcol(disp, c)]; ++ ++ sisfb_cfbX_putc(disp, c, sy, sx, fg, bg); ++} ++#endif ++ ++#ifdef FBCON_HAS_CFB8 ++static void ++sisfb_cfb8_putcs(struct vc_data * conp, struct display * disp, const unsigned short *s, ++ int count, int sy, int sx) ++{ ++ u32 fg, bg; ++ ++ fg = attr_fgcol(disp, *s); ++ bg = attr_bgcol(disp, *s); ++ ++ sisfb_cfbX_putcs(disp, s, count, sy, sx, fg, bg); ++} ++#endif ++ ++#ifdef FBCON_HAS_CFB16 ++static void ++sisfb_cfb16_putcs(struct vc_data * conp, struct display * disp, const unsigned short *s, ++ int count, int sy, int sx) ++{ ++ u32 fg, bg; ++ ++ fg = ((u16 *)disp->dispsw_data)[attr_fgcol(disp, *s)]; ++ bg = ((u16 *)disp->dispsw_data)[attr_bgcol(disp, *s)]; ++ ++ sisfb_cfbX_putcs(disp, s, count, sy, sx, fg, bg); ++} ++#endif ++ ++#ifdef FBCON_HAS_CFB32 ++static void ++sisfb_cfb32_putcs(struct vc_data * conp, struct display * disp, const unsigned short *s, ++ int count, int sy, int sx) ++{ ++ u32 fg, bg; ++ ++ fg = ((u32 *)disp->dispsw_data)[attr_fgcol(disp, *s)]; ++ bg = ((u32 *)disp->dispsw_data)[attr_bgcol(disp, *s)]; ++ ++ sisfb_cfbX_putcs(disp, s, count, sy, sx, fg, bg); ++} ++#endif ++ ++/** ++ * sisfb_cfbX_clear_margins: - Clear the margin of the text console ++ * @conp: ++ * @disp: ++ * @bottom_onlly: ++ * ++ * It's used to clear the margins around the region used for the emulated text ++ * console, when the resolution of the (virtual) screen is not a multiple of the ++ * font size, or when you want a small text console in the center of the screen ++ * (on Sparc). `bottom_only' means clear the bottom area only, which is useful ++ * when panning (using the virtual screen). ++ */ ++static void ++sisfb_cfbX_clear_margins(struct vc_data * conp, struct display * disp, ++ int bottom_only) ++{ ++ struct sisfb_info *sisfb = (struct sisfb_info *) (disp->fb_info); ++ struct sisfb_accelerator * accel = ++ (struct sisfb_accelerator *) (sisfb->accelerator); ++ unsigned int cell_w = fontwidth(disp); ++ unsigned int cell_h = fontheight(disp); ++ unsigned int right_width = disp->var.xres % cell_w; ++ unsigned int bottom_height = disp->var.yres % cell_h; ++ unsigned int right_start = disp->var.xres - right_width; ++ unsigned int bottom_start = disp->var.yres - bottom_height; ++ ++ if (!bottom_only && right_width) { ++ /* clear whole right margin, not only visible portion */ ++ accel->fillrect(sisfb, ++ disp->var.xoffset + right_start, 0, ++ right_width, disp->var.yres_virtual, ++ 0x0000, ROP_COPY_PAT); ++ } ++ ++ if (bottom_height) { ++ accel->fillrect(sisfb, ++ disp->var.xoffset, disp->var.yoffset + bottom_start, ++ right_start, bottom_height, ++ 0x0000, ROP_COPY_PAT); ++ } ++} ++ ++#ifdef FBCON_HAS_CFB8 ++static struct display_switch sisfb_cfb8 = { ++ setup: fbcon_cfb8_setup, ++ bmove: sisfb_cfbX_bmove, ++ clear: sisfb_cfb8_clear, ++ putc: sisfb_cfb8_putc, ++ putcs: sisfb_cfb8_putcs, ++ revc: sisfb_cfbX_revc, ++ cursor: NULL, ++ clear_margins: sisfb_cfbX_clear_margins, ++ fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) ++}; ++#endif ++ ++#ifdef FBCON_HAS_CFB16 ++static struct display_switch sisfb_cfb16 = { ++ setup: fbcon_cfb16_setup, ++ bmove: sisfb_cfbX_bmove, ++ clear: sisfb_cfb16_clear, ++ putc: sisfb_cfb16_putc, ++ putcs: sisfb_cfb16_putcs, ++ revc: sisfb_cfbX_revc, ++ cursor: NULL, ++ clear_margins: sisfb_cfbX_clear_margins, ++ fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) ++}; ++#endif ++ ++#ifdef FBCON_HAS_CFB32 ++static struct display_switch sisfb_cfb32 = { ++ setup: fbcon_cfb32_setup, ++ bmove: sisfb_cfbX_bmove, ++ clear: sisfb_cfb32_clear, ++ putc: sisfb_cfb32_putc, ++ putcs: sisfb_cfb32_putcs, ++ revc: sisfb_cfbX_revc, ++ cursor: NULL, ++ clear_margins: sisfb_cfbX_clear_margins, ++ fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) ++}; ++#endif ++ ++void ++sisfb_set_dispsw_accel(struct display *disp, struct sisfb_info *sisfb, ++ int bpp, int accel) ++{ ++ switch (bpp) { ++#ifdef FBCON_HAS_CFB8 ++ case 8: ++ disp->dispsw = &sisfb_cfb8; ++ break; ++#endif ++ ++#ifdef FBCON_HAS_CFB16 ++ case 15: ++ case 16: ++ disp->dispsw = &sisfb_cfb16; ++ disp->dispsw_data = sisfb->fbcon_cmap.cfb16; ++ break; ++#endif ++ ++#ifdef FBCON_HAS_CFB32 ++ case 32: ++ disp->dispsw = &sisfb_cfb32; ++ disp->dispsw_data = sisfb->fbcon_cmap.cfb32; ++ break; ++#endif ++ ++ default: ++ disp->dispsw = &fbcon_dummy; ++ return; ++ } ++ ++ disp->scrollmode = SCROLL_YREDRAW; ++} +diff -urN linux-2.4.19/drivers/video/sis/sisfb_accel.h linux-2.4.19-linuxbios/drivers/video/sis/sisfb_accel.h +--- linux-2.4.19/drivers/video/sis/sisfb_accel.h Thu Jan 1 08:00:00 1970 ++++ linux-2.4.19-linuxbios/drivers/video/sis/sisfb_accel.h Mon Sep 2 17:23:10 2002 +@@ -0,0 +1,96 @@ ++#ifndef __SISFB_ACCEL__ ++#define __SISFB_ACCEL__ ++ ++#ifdef __KERNEL__ ++#include "sisfb_lite.h" ++#endif /* __KERNEL__ */ ++ ++#define PAT_REG_SIZE 384 ++ ++enum sisfb_raster_op_bitblt { ++ ROP_CLEAR = 0x00, /* dst = 0, 0 */ ++ ROP_AND = 0x88, /* dst = dst & src, DSa */ ++ ROP_AND_REVERSE = 0x44, /* dst = ~dst & src, SDna */ ++ ROP_COPY = 0xCC, /* dst = src, S */ ++ ROP_AND_INVERTED = 0x22, /* dst = dst & ~src, DSna */ ++ ROP_NOOP = 0xAA, /* dst = dst, D */ ++ ROP_XOR = 0x66, /* dst = dst ^ src, DSx */ ++ ROP_OR = 0xEE, /* dst = dst | src, DSo */ ++ ROP_NOR = 0x11, /* dst = ~(dst | src), DSon */ ++ ROP_EQUIV = 0x99, /* dst = dst ^ ~src, DSxn */ ++ ROP_INVERT = 0x55, /* dst = ~dst, Dn */ ++ ROP_OR_INVERSE = 0xDD, /* dst = ~dst | src, SDno */ ++ ROP_COPY_INVERTED = 0x33, /* dst = ~src, Sn */ ++ ROP_OR_INVERTED = 0xBB, /* dst = ~src | dst, DSno */ ++ ROP_NAND = 0x77, /* dst = ~(dst & src), DSan */ ++ ROP_SET = 0xFF, /* dst = 1, 1 */ ++ ++ /* same as above, but with pattern as source */ ++ ROP_CLEAR_PAT = 0x00, /* dst = 0, 0 */ ++ ROP_AND_PAT = 0xA0, /* dst = dst & src, DSa */ ++ ROP_AND_REVERSE_PAT = 0x50, /* dst = ~dst & src, SDna */ ++ ROP_COPY_PAT = 0xF0, /* dst = src, S */ ++ ROP_AND_INVERTED_PAT = 0x0A, /* dst = dst & ~src, DSna */ ++ ROP_NOOP_PAT = 0xAA, /* dst = dst, D */ ++ ROP_XOR_PAT = 0x5A, /* dst = dst ^ src, DSx */ ++ ROP_OR_PAT = 0xFA, /* dst = dst | src, DSo */ ++ ROP_NOR_PAT = 0x05, /* dst = ~(dst | src), DSon */ ++ ROP_EQUIV_PAT = 0xA5, /* dst = dst ^ ~src, DSxn */ ++ ROP_INVERT_PAT = 0x55, /* dst = ~dst, Dn */ ++ ROP_OR_REVERSE_PAT = 0xDD, /* dst = ~dst | src, SDno */ ++ ROP_COPY_INVERTED_PAT = 0x0F, /* dst = ~src, Sn */ ++ ROP_OR_INVERTED_PAT = 0xAF, /* dst = ~src | dst, DSno */ ++ ROP_NAND_PAT = 0x5F, /* dst = ~(dst & src), DSan */ ++ ROP_SET_PAT = 0xFF, /* dst = 1, 1 */ ++}; ++ ++enum sisfb_color_key_mode { ++ KEYMODE_NEVER = 0x00, ++ KEYMODE_DESTKEY_NOTSRCKEY = 0x02, ++ KEYMODE_DESTKEY = 0x03, ++ KEYMODE_NOTSRCKEY = 0x0A, ++ KEYMODE_ALWAYS = 0x0F ++}; ++ ++struct sisfb_accelerator { ++ void (*fillrect)(struct sisfb_info *sisfb, u32 x, u32 y, ++ u32 width, u32 height, u32 color, u8 rop); ++ void (*copyrect)(struct sisfb_info *sisfb, u32 srcx, u32 srcy, ++ u32 dstx, u32 dsty, u32 width, u32 height, u8 rop); ++ void (*copyrect_transparent)(struct sisfb_info *sisfb, u32 srcx, u32 srcy, ++ u32 dstx, u32 dsty, u32 width, u32 height, ++ u32 src_hi, u32 src_low, ++ u32 dst_hi, u32 dst_low, ++ u8 key_mode); ++ ++ void (*color_expand_8x8)(struct sisfb_info * sisfb, u32 x, u32 y, u32 width, ++ u32 height, u32 fg, u32 bg, u8 rop, u8 * bitmap); ++ void (*color_expand)(struct sisfb_info * sisfb, u32 x, u32 y, u32 width, ++ u32 height, u32 fg, u32 bg, u8 rop, u8 * bitmap, ++ u32 bitmap_pitch); ++ ++ void (*drawline)(struct sisfb_info * sisfb, u32 srcx, u32 srcy, ++ u32 dstx, u32 dsty, u32 fg, u32 bg, u8 rop); ++ void (*drawline_style)(struct sisfb_info * sisfb, u32 srcx, u32 srcy, ++ u32 dstx, u32 dsty, u32 fg, u32 bg, u8 rop, ++ u8 * bitmap); ++ ++#if 0 ++ /* not implemented yet */ ++ void (color_expand_enhanced)(struct sisfb_info * sisfb, u32 x, u32 y, u32 width, ++ u32 height, u32 fg, u32 bg, u8 rop, ++ u8 * bitmap, u32 bitmap_pitch) ++ ++ void (*span_fill)(struct sisfb_info * sisfb, u32 srcy, u32 fg, u32 bg, ++ u32 *span, u8 rop, u8 * bitmap); ++ ++ void (*trapezoid_fill)(struct sisfb_info * sisfb, ...); ++#endif ++}; ++ ++#ifdef __KERNEL__ ++void sisfb_set_dispsw_accel(struct display *disp, struct sisfb_info *sisfb, int bpp, int accel); ++ ++#endif /* __KERNEL_ */ ++ ++#endif /* __SISFB_ACCEL__ */ +diff -urN linux-2.4.19/drivers/video/sis/sisfb_legacy_init.c linux-2.4.19-linuxbios/drivers/video/sis/sisfb_legacy_init.c +--- linux-2.4.19/drivers/video/sis/sisfb_legacy_init.c Thu Jan 1 08:00:00 1970 ++++ linux-2.4.19-linuxbios/drivers/video/sis/sisfb_legacy_init.c Mon Sep 2 17:23:10 2002 +@@ -0,0 +1,313 @@ ++/* sisfb_legacy_init.c: Initialization code for Legacy VGA Registers ++ * ++ * Copyright 2001 Ollie Lho ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * ++ * This driver is implemented by the Author for his own personal interests and is NOT a ++ * commitment NOR supported officially by Silicon Integrated Systems Corp. Please direct ++ * any bug report/question to the Author and don't bother SiS Technical Support Personell. ++ * ++ * ++ * Reference: ++ * 1. SiS 6326 AGP/PCI Graphics & Video Acclerator. Rev 1.0, May 12, 1997 ++ * 2. SiS 530 Host, PCI, 3D Graphics & Memory Controller Datasheet, ++ * Preliminary v1.0 Nov. 10, 1998 ++ * 3. Programmer's Guide to the EGA, VGA, and Super VGA Card. Third Edition, ++ * Richard F. Ferraro, Addison-Welsey, Aug. 1994 ++ */ ++ ++#include "sisfb_lite.h" ++ ++static void sisfb_set_default_misc_reg(struct sisfb_info * sisfb); ++static void sisfb_set_default_seq_regs(struct sisfb_info * sisfb); ++static void sisfb_set_default_crtc_regs(struct sisfb_info * sisfb); ++static void sisfb_set_default_grc_regs(struct sisfb_info * sisfb); ++static void sisfb_set_default_attr_regs(struct sisfb_info * sisfb); ++static void sisfb_permute_dac_rgb(struct sisfb_info * sisfb, u8 * colors); ++static void sisfb_load_default_palette(struct sisfb_info * sisfb); ++void sisfb_init_legacy_vga(struct sisfb_info * sisfb); ++ ++static u8 default_vga_palette[] __initdata = { ++ /* Palette 0-15, original EGA 16 colors stored as 00bbggrr where ++ * bbggrr are 2 bits index to the color values {0, 42, 21, 63} */ ++ 0x00, 0x10, 0x04, 0x14, 0x01, 0x11, 0x09, 0x15, ++ 0x2A, 0x3A, 0x2E, 0x3E, 0x2B, 0x3B, 0x2F, 0x3F, ++ ++ /* Palette 16-31, 16 evenly spaced shades of gray */ ++ 0x00, 0x05, 0x08, 0x0B, 0x0E, 0x11, 0x14, 0x18, ++ 0x1C, 0x20, 0x24, 0x28, 0x2D, 0x32, 0x38, 0x3F, ++ ++ /* Palette 32-247, 24 colors group generated form 5 elements, ++ * each group has 3 intensity and 3 saturation levels */ ++ 0x00, 0x10, 0x1F, 0x2F, 0x3F, ++ 0x1F, 0x27, 0x2F, 0x37, 0x3F, ++ 0x2D, 0x31, 0x36, 0x3A, 0x3F, ++ 0x00, 0x07, 0x0E, 0x15, 0x1C, ++ 0x0E, 0x11, 0x15, 0x18, 0x1C, ++ 0x14, 0x16, 0x18, 0x1A, 0x1C, ++ 0x00, 0x04, 0x08, 0x0C, 0x10, ++ 0x08, 0x0A, 0x0C, 0x0E, 0x10, ++ 0x0B, 0x0C, 0x0D, 0x0F, 0x10 ++}; ++ ++/** ++ * sisfb_set_default_misc_reg: - Set default value for standard VGA Miscellaneouse ++ * Output Register ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Miscellaneouse Output Register is used for selecting Sync Polarity, Clock Generator ++ * and Enable/Disable IO/MEM address space. ++ * ++ * The Miscellaneouse Output Register is programmed with 0x6F => VGA 400 lines, ++ * internal clock generator, MEM/IO address enabled. ++ * ++ * This function is needed to be called once at driver initialization. ++ */ ++static void __devinit ++sisfb_set_default_misc_reg(struct sisfb_info * sisfb) ++{ ++ sisfb_set_gen_reg(sisfb, 0x3c2, 0x6F); ++} ++ ++/** ++ * sisfb_set_default_seq_regs: - Set default values for standard VGA Sequencer Registers ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Most of the Seqencer Registers are used for "backward compability" with EGA cards. ++ * The really essential registers are SR0 for reset and SR1 for turnning on/off the ++ * display. ++ * ++ * This function is needed to be called once at driver initialization. ++ */ ++static void __devinit ++sisfb_set_default_seq_regs(struct sisfb_info * sisfb) ++{ ++ /* recover from Reset state */ ++ sisfb_set_seq_reg(sisfb, 0x00, 0x03); ++ ++ /* set SR1 Bit5: Screen Off , Bit 0, 9 dots/char (why not 8 ??) */ ++ sisfb_set_seq_reg(sisfb, 0x01, 0x21); ++ ++ /* Enable bit plane 0-3 */ ++ sisfb_set_seq_reg(sisfb, 0x02, 0x0F); ++ ++ /* Use Character Table 0 */ ++ sisfb_set_seq_reg(sisfb, 0x03, 0x00); ++ ++ /* Enable 4-Chain Mode, Disable Odd/Even Mode, Enable 256KB Memory */ ++ sisfb_set_seq_reg(sisfb, 0x04, 0x0E); ++} ++ ++/** ++ * sisfb_set_default_crtc_regs: - Set default values for standard VGA CRT ++ * Controller Registers ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Most of the CRT Controllers Registers are display mode specific, they are set ++ * in various node setting routines. ++ * ++ * This function is needed to be called once at driver initialization. ++ */ ++static void __devinit ++sisfb_set_default_crtc_regs(struct sisfb_info * sisfb) ++{ ++ /* Disable Vertical Panning */ ++ sisfb_set_crtc_reg(sisfb, 0x08, 0x00); ++ ++ /* No text cursor */ ++ sisfb_set_crtc_reg(sisfb, 0x0A, 0x00); ++ sisfb_set_crtc_reg(sisfb, 0x0B, 0x00); ++ ++ /* Screen start from 0 */ ++ sisfb_set_crtc_reg(sisfb, 0x0C, 0x00); ++ sisfb_set_crtc_reg(sisfb, 0x0D, 0x00); ++ ++ /* Text cursor at 0 */ ++ sisfb_set_crtc_reg(sisfb, 0x0E, 0x00); ++ sisfb_set_crtc_reg(sisfb, 0x0F, 0x00); ++ ++ /* Enable Double Word Mode */ ++ sisfb_set_crtc_reg(sisfb, 0x14, 0x40); ++ ++ /* Enable vertical and horizonal retrace, ++ sequential memory addressing */ ++ sisfb_set_crtc_reg(sisfb, 0x17, 0xA3); ++ /* set line compare Bit 0..7 to 0xFF */ ++ sisfb_set_crtc_reg(sisfb, 0x18, 0xFF); ++} ++ ++/** ++ * sisfb_set_default_grc_regs: - Set default values for standard VGA Graphics ++ * Controller Registers ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Graphics Controller Registers are used for "backward compability" with EGA cards. ++ * These registers are not actually used by this driver. Set them to some sane values ++ * or clear to 0. ++ * ++ * This function is needed to be called once at driver initialization. ++ * ++ * FixME: GR05 Bit 6 seem to be used for 256-color stuff, is it really needed ?? ++ */ ++static void __devinit ++sisfb_set_default_grc_regs(struct sisfb_info * sisfb) ++{ ++ int i; ++ ++ /* GR0-GR4 are not used by VGA, clear them */ ++ for (i = 0; i <= 0x04; i++) { ++ sisfb_set_grc_reg(sisfb, i, 0x00); ++ } ++ ++ /* enable 256-color mode */ ++ sisfb_set_grc_reg(sisfb, 0x05, 0x40); ++ ++ /* Graphics Mode, Memory Address 0xA0000 to 0xAFFFF */ ++ sisfb_set_grc_reg(sisfb, 0x06, 0x05); ++ sisfb_set_grc_reg(sisfb, 0x07, 0x0F); ++ sisfb_set_grc_reg(sisfb, 0x08, 0xFF); ++} ++ ++/** ++ * sisfb_set_default_attr_regs: - Set default values for standard VGA Attribute Registers ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Attribute Registers are used for "backward compability" with EGA cards. These ++ * registers are not actually used by this driver. Set them to some sane values ++ * or clear to 0. ++ * ++ * This function is needed to be called once at driver initialization. ++ */ ++static void __devinit ++sisfb_set_default_attr_regs(struct sisfb_info * sisfb) ++{ ++ int i; ++ ++ /* Color Palette Registers AR0-ARF are used for EGA compability, ++ * set them as "identical mapping" */ ++ for (i = 0; i <= 0x0F; i++) { ++ sisfb_set_attr_reg(sisfb, i, i); ++ } ++ ++ /* AR10-AR14 are not used by VGA, clear them */ ++ for (i = 0x10; i <= 0x14; i++) { ++ sisfb_set_attr_reg(sisfb, i, 0x00); ++ } ++ ++ /* Set the Palette Address Source to Video Memory */ ++ sisfb_get_gen_reg(sisfb, 0x3DA); ++ sisfb_set_gen_reg(sisfb, 0x3C0, 0x20); ++} ++ ++/** ++ * sisfb_permute_dac_rgb: - Program the DAC color registers for a color group ++ * @sisfb: SiS Frame Buffer structure ++ * @colors: Color elements in a color group ++ * ++ * Generate the 24 permutation of the colors in each color group and program the ++ * DAC color registers in the pre-defined order. ++ */ ++static void __devinit ++sisfb_permute_dac_rgb(struct sisfb_info * sisfb, u8 * colors) ++{ ++ int i; ++ ++ for (i = 0; i < 5; i++) ++ sisfb_set_dac_rgb(sisfb, colors[i], colors[0], colors[4]); ++ for (i = 3; i > 0; i--) ++ sisfb_set_dac_rgb(sisfb, colors[4], colors[0], colors[i]); ++ ++ for (i = 0; i < 5; i++) ++ sisfb_set_dac_rgb(sisfb, colors[4], colors[i], colors[0]); ++ for (i = 3; i > 0; i--) ++ sisfb_set_dac_rgb(sisfb, colors[i], colors[4], colors[0]); ++ ++ for (i = 0; i < 5; i++) ++ sisfb_set_dac_rgb(sisfb, colors[0], colors[4], colors[i]); ++ for (i = 3; i > 0; i--) ++ sisfb_set_dac_rgb(sisfb, colors[0], colors[i], colors[4]); ++} ++ ++/** ++ * sisfb_load_default_palette: - Load the default VGA Palette. ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Load the pre-defined standard VGA Palette default_vga_palette by writing ++ * to DAC color registers. ++ */ ++static void __devinit ++sisfb_load_default_palette(struct sisfb_info * sisfb) ++{ ++ int i, level; ++ u8 data; ++ u8 * table = default_vga_palette; ++ ++ /* set PEL Mask */ ++ sisfb_set_gen_reg(sisfb, 0x3C6, 0xFF); ++ sisfb_set_dac_index(sisfb, 0x00); ++ ++ /* 0-15, 16 colors initially loaded to EGA color palette */ ++ for (i = 0; i < 16; i++) { ++ u8 ega_colors[] = {0, 42, 21, 63}; ++ u8 red, green, blue; ++ ++ /* data == 00bbggrr */ ++ data = table[i]; ++ red = ega_colors[((data >> 0) & 0x03)]; ++ green = ega_colors[((data >> 2) & 0x03)]; ++ blue = ega_colors[((data >> 4) & 0x03)]; ++ sisfb_set_dac_rgb(sisfb, red, green, blue); ++ } ++ ++ /* 16-31, 16 evenly spaced shades of gray */ ++ for (i = 16; i < 32; i++) { ++ data = table[i]; ++ sisfb_set_dac_rgb(sisfb, data, data, data); ++ } ++ ++ /* for each of 3 intensity x 3 saturation == 9 levels */ ++ for (level = 0; level < 9; level++) { ++ u8 * colors = table + 32; ++ sisfb_permute_dac_rgb(sisfb, colors); ++ colors += 5; ++ } ++ ++ /* last 8 entries are cleared to 0 for black */ ++ for (i = 0; i < 8; i++) { ++ sisfb_set_dac_rgb(sisfb, 0x00, 0x00, 0x00); ++ } ++} ++ ++/** ++ * sisfb_init_legacy_vga: - Initialize the Standard VGA Registers ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Call other help functions to initialize the standard/legacy VGA registers. ++ */ ++void __devinit ++sisfb_init_legacy_vga(struct sisfb_info * sisfb) ++{ ++ sisfb_set_default_seq_regs(sisfb); ++ sisfb_set_default_misc_reg(sisfb); ++ sisfb_set_default_attr_regs(sisfb); ++ sisfb_set_default_grc_regs(sisfb); ++ sisfb_load_default_palette(sisfb); ++ ++ /* you have to load CRTC registers last or SiS 630E and SiS 630S ++ will not work. I have no idea why */ ++ sisfb_set_default_crtc_regs(sisfb); ++} +diff -urN linux-2.4.19/drivers/video/sis/sisfb_legacy_vga.h linux-2.4.19-linuxbios/drivers/video/sis/sisfb_legacy_vga.h +--- linux-2.4.19/drivers/video/sis/sisfb_legacy_vga.h Thu Jan 1 08:00:00 1970 ++++ linux-2.4.19-linuxbios/drivers/video/sis/sisfb_legacy_vga.h Mon Sep 2 17:23:10 2002 +@@ -0,0 +1,300 @@ ++#ifndef __SISFB_LEGACY_VGA__ ++#define __SISFB_LEGACY_VGA__ ++ ++/* VGA register Offsets */ ++#define ATTR_WRITE 0x40 ++#define ATTR_READ 0x41 ++#define MISC_OUT_W 0x42 ++#define SEQ_ADDR 0x44 ++#define SEQ_DATA 0x45 ++#define PEL_MASK 0x46 ++#define DACR_ADDR 0x47 ++#define DACW_ADDR 0x48 ++#define DAC_DATA 0x49 ++#define MISC_OUT_R 0x4C ++#define GRC_ADDR 0x4E ++#define GRC_DATA 0x4F ++#define CRTC_ADDR 0x54 ++#define CRTC_DATA 0x55 ++ ++#define FEATURE_READ 0x4A ++#define FEATURE_WRITE 0x5A ++ ++#define SIS_PASSWD 0x05 ++#define SIS_PASSWD_LOCK 0x21 ++#define SIS_PASSWD_UNLOCK 0x86 ++ ++static inline void ++sisfb_writeb(struct sisfb_info *sisfb, u32 offset, u8 val) ++{ ++ writeb(val, sisfb->mmio_base_virt + offset); ++} ++ ++static inline void ++sisfb_writew(struct sisfb_info *sisfb, u32 offset, u16 val) ++{ ++ writew(val, sisfb->mmio_base_virt + offset); ++} ++ ++static inline void ++sisfb_writel(struct sisfb_info *sisfb, u32 offset, u32 val) ++{ ++ writel(val, sisfb->mmio_base_virt + offset); ++} ++ ++static inline u8 ++sisfb_readb(struct sisfb_info *sisfb, u32 offset) ++{ ++ return readb(sisfb->mmio_base_virt + offset); ++} ++ ++static inline u16 ++sisfb_readw(struct sisfb_info *sisfb, u32 offset) ++{ ++ return readw(sisfb->mmio_base_virt + offset); ++} ++ ++static inline u32 ++sisfb_readl(struct sisfb_info *sisfb, u32 offset) ++{ ++ return readl(sisfb->mmio_base_virt + offset); ++} ++ ++static inline void ++sisfb_set_gen_reg(struct sisfb_info * sisfb, u16 port, u8 data) ++{ ++ u16 base = sisfb->vga_io_base; ++ ++ outb(data, port + base - 0x380); ++} ++ ++static inline u8 ++sisfb_get_gen_reg(struct sisfb_info * sisfb, u16 port) ++{ ++ u16 base = sisfb->vga_io_base; ++ ++ return inb(port + base - 0x380); ++} ++ ++static inline void ++sisfb_set_seq_reg(struct sisfb_info * sisfb, u8 index, u8 data) ++{ ++ u16 port = sisfb->vga_io_base; ++ ++ outb(index, port + SEQ_ADDR); ++ outb(data, port + SEQ_DATA); ++} ++ ++static inline u8 ++sisfb_get_seq_reg(struct sisfb_info * sisfb, u8 index) ++{ ++ u16 port = sisfb->vga_io_base; ++ ++ outb(index, port + SEQ_ADDR); ++ return inb(port + SEQ_DATA); ++} ++ ++static inline void ++sisfb_set_crtc_reg(struct sisfb_info * sisfb, u8 index, u8 data) ++{ ++ u16 port = sisfb->vga_io_base; ++ ++ outb(index, port + CRTC_ADDR); ++ outb(data, port + CRTC_DATA); ++} ++ ++static inline u8 ++sisfb_get_crtc_reg(struct sisfb_info * sisfb, u8 index) ++{ ++ u16 port = sisfb->vga_io_base; ++ ++ outb(index, port + CRTC_ADDR); ++ return inb(port + CRTC_DATA); ++} ++ ++static inline void ++sisfb_set_grc_reg(struct sisfb_info * sisfb, u8 index, u8 data) ++{ ++ u16 port = sisfb->vga_io_base; ++ ++ outb(index, port + GRC_ADDR); ++ outb(data, port + GRC_DATA); ++} ++ ++static inline u8 ++sisfb_get_grc_reg(struct sisfb_info * sisfb, u8 index) ++{ ++ u16 port = sisfb->vga_io_base; ++ ++ outb(index, port + GRC_ADDR); ++ return inb(port + GRC_DATA); ++} ++ ++static inline void ++sisfb_set_attr_reg(struct sisfb_info * sisfb, u8 index, u8 data) ++{ ++ u16 port = sisfb->vga_io_base; ++ volatile u8 dummy; ++ ++ /* Read port 0x3DA, to set the Adderss flip-flop */ ++ dummy = sisfb_get_gen_reg(sisfb, 0x3DA); ++ outb(index, port + ATTR_WRITE); ++ outb(data, port + ATTR_WRITE); ++} ++ ++static inline u8 ++sisfb_get_attr_reg(struct sisfb_info * sisfb, u8 index) ++{ ++ u16 port = sisfb->vga_io_base; ++ volatile u8 dummy; ++ ++ /* Read port 0x3DA, to set the Adderss flip-flop */ ++ dummy = sisfb_get_gen_reg(sisfb, 0x3DA); ++ outb(index, port + ATTR_READ); ++ return inb(port + ATTR_READ); ++} ++ ++/** ++ * sisfb_set_dac_index: - Select DAC color register to be loaded ++ * @sisfb: SiS Frame Buffer structure ++ * @index: Index of the DAC color Register to be loaded ++ * ++ * Select the DAC color register to be loaded by programming the ++ * DAC Write Address Register. ++ */ ++static inline void ++sisfb_set_dac_index(struct sisfb_info * sisfb, u8 index) ++{ ++ u16 port = sisfb->vga_io_base; ++ ++ outb(index, port + DACW_ADDR); ++} ++ ++/** ++ * sisfb_set_dac_rgb: - Load the DAC color register ++ * @sisfb: SiS Frame Buffer structure ++ * @red: Red component ++ * @green: Green component ++ * @blue: Blue compoenet ++ * ++ * Load the DAC color register with (@red, @green, @blue) by writing to the DAC Data ++ * Register. The color register to be loaded is implicitely selected by the DAC Write ++ * Address Register. ++ */ ++static inline void ++sisfb_set_dac_rgb(struct sisfb_info * sisfb, u8 red, u8 green, u8 blue) ++{ ++ u16 port = sisfb->vga_io_base; ++ ++ outb(red, port + DAC_DATA); ++ outb(green, port + DAC_DATA); ++ outb(blue, port + DAC_DATA); ++} ++ ++/** ++ * sisfb_lock_regs: - Lock the CRTC Registers 0-7 and Extended Sequencer Registers ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Lock CRTC 0-7 by setting Bit 7 of CRTC 0x11. ++ * Lock Extended Registers by writing 0x21 (%SIS_PASSWD_LOCK) to ++ * SR 0x05 (%SIS_PASSWD) ++ */ ++static inline void ++sisfb_lock_regs(struct sisfb_info * sisfb) ++{ ++ u8 data; ++ ++ /* Set Bit 7 to enable Write Protect for CR0 to CR7 */ ++ data = sisfb_get_crtc_reg(sisfb, 0x11); ++ data = data | 0x80; ++ sisfb_set_crtc_reg(sisfb, 0x11, data); ++ ++ /* lock the access to Extended Registers SR5-SR3C and/or CR30-CR37 ?? */ ++ sisfb_set_seq_reg(sisfb, SIS_PASSWD, SIS_PASSWD_LOCK); ++} ++ ++/** ++ * sisfb_unlock_regs: - Unlock the CRTC Registers 0-7 and Extended Sequencer Registers ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Unlock CRTC 0-7 by clearing Bit 7 of CRTC 0x11. ++ * Unlock Extended Registers by writing 0x86 (%SIS_PASSWD_UNLOCK) to ++ * SR 0x05 (%SIS_PASSWD) ++ */ ++static inline void ++sisfb_unlock_regs(struct sisfb_info * sisfb) ++{ ++ u8 data; ++ ++ /* clear Bit 7 to disable Write Protect for CR0 to CR7 */ ++ data = sisfb_get_crtc_reg(sisfb, 0x11); ++ data = data & 0x7f; ++ sisfb_set_crtc_reg(sisfb, 0x11, data); ++ ++ /* unlock the access to Extended Registers SR5-SR3C and/or CR30-CR37 ?? */ ++ sisfb_set_seq_reg(sisfb, SIS_PASSWD, SIS_PASSWD_UNLOCK); ++} ++ ++/** ++ * sisfb_display_on: - Turn the monitor on. ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Turn on the monitor by clearing Bit 5 of Seqencer Register 0x01 ++ */ ++static inline void ++sisfb_display_on(struct sisfb_info * sisfb) ++{ ++ u8 data; ++ ++ data = sisfb_get_seq_reg(sisfb, 0x01); ++ ++ /* clear SR1 Bit 5: Screen Off ==> Screen On */ ++ data &= ~0x20; ++ sisfb_set_seq_reg(sisfb, 0x01, data); ++} ++ ++/** ++ * sisfb_display_off: - Turn the monitor off. ++ * @sisfb: SiS Frame Buffer structure ++ * ++ * Turn off the monitor by settng Bit 5 of Seqencer Register 0x01 ++ */ ++static inline void ++sisfb_display_off(struct sisfb_info * sisfb) ++{ ++ u8 data; ++ ++ data = sisfb_get_seq_reg(sisfb, 0x01); ++ ++ /* set SR1 Bit5: Screen Off */ ++ data |= 0x20; ++ sisfb_set_seq_reg(sisfb, 0x01, data); ++} ++ ++static inline u32 ++sisfb_get_screen_width(struct sisfb_info * sisfb) ++{ ++ u8 sr_b, cr_1; ++ ++ sr_b = sisfb_get_seq_reg(sisfb, 0x0B) & 0x0c; ++ cr_1 = sisfb_get_crtc_reg(sisfb, 0x01); ++ ++ return ((((sr_b << 6) | cr_1) & 0x3ff) + 1) << 3; ++} ++ ++static inline u32 ++sisfb_get_screen_height(struct sisfb_info * sisfb) ++{ ++ u8 sr_a, cr_7, cr_12; ++ ++ sr_a = sisfb_get_seq_reg(sisfb, 0x0A) & 0x02; ++ cr_7 = sisfb_get_crtc_reg(sisfb, 0x07); ++ cr_12 = sisfb_get_crtc_reg(sisfb, 0x12); ++ ++ return ((((sr_a << 9) | ((cr_7 & 0x40) << 3) | ++ ((cr_7 & 0x02) << 7) | cr_12) & 0x7ff) + 1); ++} ++ ++extern void sisfb_init_legacy_vga(struct sisfb_info * sisfb); ++ ++#endif /* __SISFB_LEGACY_VGA__ */ +diff -urN linux-2.4.19/drivers/video/sis/sisfb_lite.c linux-2.4.19-linuxbios/drivers/video/sis/sisfb_lite.c +--- linux-2.4.19/drivers/video/sis/sisfb_lite.c Thu Jan 1 08:00:00 1970 ++++ linux-2.4.19-linuxbios/drivers/video/sis/sisfb_lite.c Mon Sep 2 17:23:10 2002 +@@ -0,0 +1,1043 @@ ++/* sisfb_lite.c: SiSFB Lite, Frame Buffer Device Driver for SiS 540/630/730 requires no VGA BIOS ++ * ++ * Copyright 2000 Ollie Lho ++ * ++ * This driver is derived form an eraly version of sisfb.c which is: ++ * This driver is partly based on the VBE 2.0 compliant graphic ++ * boards framebuffer driver, which is ++ * ++ * (c) 1998 Gerd Knorr ++ * ++ * This driver is implemented by the Author for his own personal interests and is NOT a ++ * commitment NOR supported officially by Silicon Integrated Systems Corp. Please direct ++ * any bug report/question to the Author and don't bother SiS Technical Support Personell. ++ * ++ * ++ * Reference: ++ * 1. SiS 6326 AGP/PCI Graphics & Video Acclerator. Rev 1.0, May 12, 1997 ++ * 2. Programmer's Guide to the EGA, VGA, and Super VGA Card. Third Edition, ++ * Richard F. Ferraro, Addison-Welsey, Aug. 1994 ++ * 3. Glamour Design Guideline V0.8 ++ * 4. Graphics Hardware by Geert Uytterhoeven ++ * 5. sis86c201.c in XFree86 3.3.6 ++ * ++ * ToDo: ++ * 0. make sure that this file contains only /dev/fb API code ++ */ ++ ++/* make checkconfig does not check included files... */ ++#include ++#include "sisfb_lite.h" ++ ++#define PCI_DEVICE_ID_SI_550_VGA 0x5315 ++ ++static struct pci_device_id sisfb_pci_tbl [] __devinitdata = { ++#ifdef CONFIG_FB_SIS_300 ++ {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630_VGA, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, SISFB_LITE_300}, ++ {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_540_VGA, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, SISFB_LITE_300}, ++#endif /* CONFIG_FB_SIS_300 */ ++#ifdef CONFIG_FB_SIS_315 ++ {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_550_VGA, ++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, SISFB_LITE_315}, ++#endif /* CONFIG_FB_SIS_300 */ ++ {0,} ++}; ++MODULE_DEVICE_TABLE (pci, sisfb_pci_tbl); ++ ++static char fontname[40] __initdata; ++static const char * mode_option __initdata; ++ ++static struct fb_var_screeninfo default_var __initdata = { ++ /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ ++ xres: 640, ++ yres: 480, ++ xres_virtual: 640, ++ yres_virtual: 480, ++ xoffset: 0, ++ yoffset: 0, ++ bits_per_pixel: 8, ++ grayscale: 0, ++ red: {0, 8, 0}, ++ green: {0, 8, 0}, ++ blue: {0, 8, 0}, ++ transp: {0, 0, 0}, ++ nonstd: 0, ++ activate: FB_ACTIVATE_NOW, ++ height: -1, ++ width: -1, ++ accel_flags: 0, ++ ++ /* timming, virtually the same as sisfb_default_mode */ ++ pixclock: 39722, ++ left_margin: 48, ++ right_margin: 16, ++ upper_margin: 33, ++ lower_margin: 10, ++ hsync_len: 96, ++ vsync_len: 2, ++ sync: 0, ++ vmode: FB_VMODE_NONINTERLACED ++}; ++ ++static struct fb_videomode sisfb_default_mode __initdata = { ++ name: "640x480-8@60", ++ refresh: 60, ++ xres: 640, ++ yres: 480, ++ pixclock: 39722, ++ left_margin: 48, ++ right_margin: 16, ++ upper_margin: 33, ++ lower_margin: 10, ++ hsync_len: 96, ++ vsync_len: 2, ++ sync: 0, ++ vmode: FB_VMODE_NONINTERLACED ++}; ++ ++static int inverse; ++ ++unsigned long mclk = 100000, eclk = 100000; ++ ++extern int sisfb_init_300(struct sisfb_info * sisfb); ++extern int sisfb_init_315(struct sisfb_info * sisfb); ++ ++/* Interface used by the world */ ++int sisfb_setup(char *options); ++int sisfb_init(void); ++ ++/* Internal routines */ ++static void do_install_cmap(struct display * disp, struct fb_info *info); ++/* ---------------------------------------------------------------------------------- */ ++static int sisfb_encode_fix(struct fb_fix_screeninfo * fix, struct sisfb_par * par, ++ struct sisfb_info * sisfb); ++static int sisfb_decode_var(struct fb_var_screeninfo * var, struct sisfb_par * par, ++ const struct sisfb_info * sisfb); ++static int sisfb_encode_var(struct fb_var_screeninfo * var, const struct sisfb_par * par, ++ const struct sisfb_info * sisfb); ++static int sisfb_getcolreg(unsigned regno, unsigned * red, unsigned * green, unsigned * blue, ++ unsigned * transp, struct fb_info * info); ++static int sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, ++ unsigned transp, struct fb_info * info); ++/* ---------------------------------------------------------------------------------- */ ++static int sisfb_switch_con(int con, struct fb_info * info); ++static void sisfb_blank(int blank, struct fb_info * info); ++/* ----------------------------------------- fb_ops --------------------------------- */ ++static int sisfb_get_fix(struct fb_fix_screeninfo * fix, int con, struct fb_info * info); ++static int sisfb_get_var(struct fb_var_screeninfo * var, int con, struct fb_info * info); ++static int sisfb_set_var(struct fb_var_screeninfo * var, int con, struct fb_info * info); ++static int sisfb_get_cmap(struct fb_cmap * cmap, int kspc, int con, struct fb_info * info); ++static int sisfb_set_cmap(struct fb_cmap * cmap, int kspc, int con, struct fb_info * info); ++static int sisfb_ioctl(struct inode * inode, struct file * file, unsigned int cmd, ++ unsigned long arg, int con, struct fb_info * info); ++ ++ ++/** ++ * do_install_cmap: - Install colormap ++ * @disp: Display structure of current console ++ * @info: Frame Buffer structure ++ * ++ * Install colormap for the current console. This function is called every ++ * time the display mode is changed (by set_var or switch_con). ++ */ ++static void ++do_install_cmap(struct display * disp, struct fb_info *info) ++{ ++ struct sisfb_info * sisfb = (struct sisfb_info *) info; ++ ++ if (disp->cmap.len) ++ fb_set_cmap(&disp->cmap, 1, sisfb_setcolreg, info); ++ else { ++ fb_set_cmap(fb_default_cmap(sisfb->current_par.cmap_len), 1, ++ sisfb_setcolreg, info); ++ } ++} ++ ++void ++sisfb_set_dispsw_fbcon(struct display * disp, struct sisfb_info * sisfb, int bpp, int accel) ++{ ++ switch (bpp) { ++#ifdef FBCON_HAS_CFB8 ++ case 8: ++ disp->dispsw = &fbcon_cfb8; ++ break; ++#endif ++ ++#ifdef FBCON_HAS_CFB16 ++ case 15: ++ case 16: ++ disp->dispsw = &fbcon_cfb16; ++ disp->dispsw_data = sisfb->fbcon_cmap.cfb16; ++ break; ++#endif ++ ++#ifdef FBCON_HAS_CFB32 ++ case 32: ++ disp->dispsw = &fbcon_cfb32; ++ disp->dispsw_data = sisfb->fbcon_cmap.cfb32; ++ break; ++#endif ++ ++ default: ++ disp->dispsw = &fbcon_dummy; ++ return; ++ } ++ ++ disp->scrollmode = SCROLL_YREDRAW; ++} ++ ++/** ++ * sisfb_encode_fix: - Encode the Fixed Part of the Display ++ * @fix: Fixed screen info (return) ++ * @con: Console number ++ * @info: Frame Buffer structure ++ * ++ * Return the fixed part of the display information in @fix. The struct of @fix is ++ * defined in linux/fb.h. ++ */ ++static int ++sisfb_encode_fix(struct fb_fix_screeninfo * fix, struct sisfb_par * par, struct sisfb_info * sisfb) ++{ ++ memset(fix, 0, sizeof(struct fb_fix_screeninfo)); ++ strcpy(fix->id, "SiSFB Lite"); ++ ++ fix->smem_start = sisfb->video_base_phy; ++ fix->smem_len = sisfb->video_size_virt; ++ ++ fix->type = FB_TYPE_PACKED_PIXELS; ++ fix->type_aux = 0; ++ ++ if (par->bits_per_pixel == 8) ++ fix->visual = FB_VISUAL_PSEUDOCOLOR; ++ else ++ fix->visual = FB_VISUAL_TRUECOLOR; ++ ++ fix->xpanstep = 8; ++ fix->ypanstep = 1; ++ fix->ywrapstep = 0; ++ ++ fix->line_length = par->line_length; ++ ++ fix->mmio_start = sisfb->mmio_base_phy; ++ fix->mmio_len = sisfb->mmio_size_phy; ++ ++ fix->accel = FB_ACCEL_SIS_GLAMOUR; ++ ++ return 0; ++} ++ ++/** ++ * sisfb_decode_var: - Convert @var to @par ++ * @var: ++ * @par: ++ * @info: Frame Buffer structure ++ * ++ * Get the video parammeters @par from @var. If a value doesn't fit, round it up, ++ * if it's too big, return -EINVAL. ++ * ++ * The device's default par i.e. sisfb->default_par is converted from default_var by ++ * this function during driver initialization. Default_var is either predefined or ++ * provided by find_mode(). ++ */ ++static int ++sisfb_decode_var(struct fb_var_screeninfo * var, ++ struct sisfb_par * par, const struct sisfb_info * sisfb) ++{ ++ if (var->bits_per_pixel != 8 && var->bits_per_pixel != 16 && ++ var->bits_per_pixel != 32) { ++ printk(KERN_ERR "sisfb_lite: depth not supported: %u\n", ++ var->bits_per_pixel); ++ return -EINVAL; ++ } ++ ++ /* make sure there is enough video ram for the mode */ ++ if ((u32)(var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8) > ++ sisfb->video_size_virt) { ++ printk(KERN_ERR "sisfb_lite: Not enough memory for mode\n"); ++ return -EINVAL; ++ } ++ ++ /* FixMe: virtual X resolution can only be 2^N for SiS530/620 */ ++ ++ memset(par, 0, sizeof(struct sisfb_par)); ++ ++ par->hdispend = var->xres; ++ par->xvirt = var->xres_virtual; ++ par->hsyncstart = par->hdispend + var->right_margin; ++ par->hsyncend = par->hsyncstart + var->hsync_len; ++ par->htotal = par->hsyncend + var->left_margin; ++ ++ par->vdispend = var->yres; ++ par->yvirt = var->yres_virtual; ++ par->vsyncstart = par->vdispend + var->lower_margin; ++ par->vsyncend = par->vsyncstart + var->vsync_len; ++ par->vtotal = par->vsyncend + var->upper_margin; ++ ++ par->dot_clock = 1E12 / var->pixclock; ++ ++ par->bits_per_pixel = var->bits_per_pixel; ++ par->cmap_len = (par->bits_per_pixel == 8) ? 256 : 16; ++ ++ par->line_length = var->xres_virtual * (var->bits_per_pixel >> 3); ++ ++ /* update screen_offset member of current par structure */ ++ par->screen_offset = (var->yoffset * var->xres_virtual + var->xoffset) * ++ (var->bits_per_pixel >> 3); ++ ++ if (var->vmode & FB_VMODE_INTERLACED) ++ par->interlace = 1; ++ else ++ par->interlace = 0; ++ ++#if 0 ++ if (var->sync & FB_SYNC_HOR_HIGH_ACT) ++ par->sync_mode |= SISFB_HSYNC_ACT_HIGH; ++ else ++ par->sunc_mode |= SISFB_HSYNC_ACT_LOW; ++ if (var->sync & FB_SYNC_VERT_HIGH_ACT) ++ par->sync_mode |= SISFB_VSYNC_ACT_HIGH; ++ else ++ par->sync_mode |= SISFB_VSYNC_ACT_LOW; ++#endif ++ ++ return 0; ++} ++ ++/** ++ * sisfb_encode_var: - Convert @par to @var ++ * @var: ++ * @par: ++ * @info: Frame Buffer structure ++ * ++ * Fill the @var structure based on the values in the hardware specific @par. ++ */ ++static int ++sisfb_encode_var(struct fb_var_screeninfo * var, const struct sisfb_par * par, ++ const struct sisfb_info * sisfb) ++{ ++ memset(var, 0, sizeof(struct fb_var_screeninfo)); ++ ++ var->xres = par->hdispend; ++ var->yres = par->vdispend; ++ var->xres_virtual = par->xvirt; ++ var->yres_virtual = par->yvirt; ++ var->right_margin = par->hsyncstart - par->hdispend; ++ var->hsync_len = par->hsyncend - par->hsyncstart; ++ var->left_margin = par->htotal - par->hsyncend; ++ var->lower_margin = par->vsyncstart - par->vdispend; ++ var->vsync_len = par->vsyncend - par->vsyncstart; ++ var->upper_margin = par->vtotal - par->vsyncend; ++ var->bits_per_pixel = par->bits_per_pixel; ++ var->height = -1; ++ var->width = -1; ++ ++ switch (par->bits_per_pixel) { ++#ifdef FBCON_HAS_CFB8 ++ case 8: ++ var->red.length = 6; ++ var->green.length = 6; ++ var->blue.length = 6; ++ break; ++#endif ++#ifdef FBCON_HAS_CFB16 ++ case 16: /* RGB 565 */ ++ var->red.offset = 11; ++ var->red.length = 5; ++ var->green.offset = 5; ++ var->green.length = 6; ++ var->blue.offset = 0; ++ var->blue.length = 5; ++ var->transp.offset = 0; ++ var->transp.length = 0; ++ break; ++#endif ++#ifdef FBCON_HAS_CFB32 ++ case 32: ++ var->red.offset = 16; ++ var->red.length = 8; ++ var->green.offset = 8; ++ var->green.length = 8; ++ var->blue.offset = 0; ++ var->blue.length = 8; ++ var->transp.offset = 24; ++ var->transp.length = 8; ++ break; ++#endif ++ } ++ ++ var->pixclock = (u32) (1E12 / par->dot_clock); ++ ++ if (par->sync_mode & 0x80) ++ var->sync &= ~FB_SYNC_VERT_HIGH_ACT; ++ else ++ var->sync |= FB_SYNC_VERT_HIGH_ACT; ++ ++ if (par->sync_mode & 0x40) ++ var->sync &= ~FB_SYNC_HOR_HIGH_ACT; ++ else ++ var->sync |= FB_SYNC_HOR_HIGH_ACT; ++ ++ return 0; ++} ++ ++/** ++ * sisfb_getcolreg: - Read color register ++ * @regno: Color register number ++ * @red: Red component (return) ++ * @green: Green component (return) ++ * @blue: Blue component (return) ++ * @trans: Alpha component (return) ++ * @info: Frame Buffer structure ++ * ++ * Return != 0 for invalid register number. ++ * ++ * Read a single color register form the driver's color palette and split ++ * it into colors/transparent components. sisfb_get_cmap() uses this function ++ * to query the colormap. ++ */ ++static int ++sisfb_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue, ++ unsigned *transp, struct fb_info * info) ++{ ++ struct sisfb_info * sisfb = (struct sisfb_info *) info; ++ struct sisfb_par * par = (struct sisfb_par *) &sisfb->current_par; ++ ++ if (regno >= par->cmap_len) ++ return 1; ++ ++ *red = (sisfb->palette[regno].red << 8) | sisfb->palette[regno].red; ++ *green = (sisfb->palette[regno].green << 8) | sisfb->palette[regno].green; ++ *blue = (sisfb->palette[regno].blue << 8) | sisfb->palette[regno].blue; ++ *transp = 0; ++ ++ return 0; ++} ++ ++/** ++ * sisfb_getcolreg: - Set color register ++ * @regno: Color register number ++ * @red: Red component (return) ++ * @green: Green component (return) ++ * @blue: Blue component (return) ++ * @trans: Alpha component (return) ++ * @info: Frame Buffer structure ++ * ++ * Return != 0 for invalid register number. ++ * ++ * Set a single color register to the driver's color palette (HW for 256 color ++ * mode, SW otherwise) according to colors/transparent components supplied. ++ * The values supplied are already rounded down to the hardware's capabilities ++ * (according to the entries in the var structure) ++ * ++ * sisfb_set_cmap() uses this function to set the colormap. ++ */ ++static int ++sisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, ++ unsigned transp, struct fb_info * info) ++{ ++ struct sisfb_info * sisfb = (struct sisfb_info *) info; ++ struct sisfb_par * par = (struct sisfb_par *) &sisfb->current_par; ++ ++ if (regno >= par->cmap_len) ++ return 1; ++ ++ red >>= 8; ++ green >>= 8; ++ blue >>= 8; ++ ++ sisfb->palette[regno].red = red; ++ sisfb->palette[regno].green = green; ++ sisfb->palette[regno].blue = blue; ++ ++ switch (par->bits_per_pixel) { ++#ifdef FBCON_HAS_CFB8 ++ case 8: ++ sisfb_set_dac_index(sisfb, regno); ++ sisfb_set_dac_rgb(sisfb, red >> 2, green >> 2, blue >> 2); ++ break; ++#endif ++#ifdef FBCON_HAS_CFB16 ++ case 15: ++ case 16: ++ sisfb->fbcon_cmap.cfb16[regno] = ++ ((red & 0xF8) << 8) | ++ ((green & 0xFC) << 3) | ++ ((blue & 0xF8) >> 3); ++ break; ++#endif ++#ifdef FBCON_HAS_CFB32 ++ case 32: ++ sisfb->fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | (blue); ++ break; ++#endif ++ } ++ ++ return 0; ++} ++ ++/* ++ * Switch Console (called by fbcon.c) ++ */ ++static int ++sisfb_switch_con(int con, struct fb_info * info) ++{ ++ struct sisfb_info * sisfb = (struct sisfb_info *) info; ++ struct sisfb_par par; ++ ++ /* unlock VGA registers, XFree86 3.3.6 leave the registers locked ++ * during console switch */ ++ sisfb_unlock_regs(sisfb); ++ ++ /* backup colormap of current console */ ++ if (fb_display[sisfb->currcon].cmap.len) ++ fb_get_cmap(&fb_display[sisfb->currcon].cmap, ++ 1, sisfb_getcolreg, info); ++ ++ /* same mode, needn't change mode actually */ ++ if (!memcmp(&fb_display[con].var, &fb_display[sisfb->currcon].var, ++ sizeof(struct fb_var_screeninfo))) { ++ sisfb->currcon = con; ++ return 1; ++ } ++ ++ sisfb->currcon = con; ++ ++ /* convert var to par and set the hardware by set_par */ ++ sisfb_decode_var(&fb_display[con].var, &par, sisfb); ++ sisfb->set_par(&par, sisfb); ++ ++ /* set display switch for current bits_per_pixel */ ++ sisfb->set_disp(&fb_display[con], sisfb, fb_display[con].var.bits_per_pixel, 0); ++ ++ /* Install new colormap for current console */ ++ do_install_cmap(&fb_display[con], info); ++ ++ return 1; ++} ++ ++static int ++sisfb_updatevar(int con, struct fb_info * info) ++{ ++ struct sisfb_info * sisfb = (struct sisfb_info *) info; ++ ++ if (con == sisfb->currcon) ++ sisfb->pan_display(&fb_display[con].var, sisfb); ++ ++ return 0; ++} ++ ++/** ++ * sisfb_blank: - Blanking or Unblanking the CRT ++ * @blank: 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off ++ * @info: Frame Buffer structure ++ * ++ * The documents on bit 6..7 of SR11 and SR1F are ambigiuos. They are either marked as ++ * "reserved" or conflicts with each other from different sources. It is possible that ++ * all these bits are "wired" altogether in the actual circuit implementation (HW bug ??). ++ * And the VGA guys just choose one to document/program on their own will. ++ * ++ * In SiS 315 documentation, SR1F is the power management register. ++ */ ++static void ++sisfb_blank(int blank, struct fb_info * info) ++{ ++ u8 display, power, retrace; ++ struct sisfb_info * sisfb = (struct sisfb_info *) info; ++ ++ display = sisfb_get_seq_reg(sisfb, 0x01); ++ power = sisfb_get_seq_reg(sisfb, 0x1F); ++ retrace = sisfb_get_crtc_reg(sisfb, 0x17); ++ ++ /* Turn the display off */ ++ display |= 0x20; ++ ++ switch (blank) { ++ case 0: ++ /* Turn the display on */ ++ display &= ~0x20; ++ /* Disable DPMS mode */ ++ power &= ~0xC0; ++ /* Enable horizontal and vertical retrace signals */ ++ retrace |= 0x80; ++ break; ++ case 1: ++ break; ++ case 2: ++ /* Enter DPMS Suspend Mode -> no vsync */ ++ power |= 0x80; ++ break; ++ case 3: ++ /* Enter DPMS standby Mode -> no hsync */ ++ power |= 0x40; ++ break; ++ case 4: ++ default: ++ /* Enter DPMS Power Off Mode -> no hsync,vsync */ ++ power |= 0xC0; ++ /* Disable horizontal and vertical retrace signals */ ++ retrace &= ~0x80; ++ break; ++ } ++ ++ sisfb_set_seq_reg(sisfb, 0x01, display); ++ sisfb_set_seq_reg(sisfb, 0x1F, power); ++ sisfb_set_crtc_reg(sisfb, 0x17, retrace); ++} ++ ++/** ++ * sisfb_get_fix: - Get the Fixed Part of the Display ++ * @fix: Fixed screen info (return) ++ * @con: Console number ++ * @info: Frame Buffer structure ++ * ++ * Return the fixed part of the display information in @fix. The struct of @fix is ++ * defined in linux/fb.h. ++ * ++ * This function calls sisfb_encode_fix() to encode @fix from current 'var' or 'par' ++ */ ++static int ++sisfb_get_fix(struct fb_fix_screeninfo * fix, int con, struct fb_info * info) ++{ ++ struct sisfb_info * sisfb = (struct sisfb_info *) info; ++ struct sisfb_par par; ++ ++ if (con == -1) ++ par = sisfb->default_par; ++ else ++ sisfb_decode_var(&fb_display[con].var, &par, sisfb); ++ ++ sisfb_encode_fix(fix, &par, sisfb); ++ ++ return 0; ++} ++ ++/** ++ * sisfb_get_var: - Convert @var to @par ++ * @var: ++ * @par: ++ * @info: Frame Buffer structure ++ * ++ * Get the video params out of 'var'. If a value doesn't fit, round it up, ++ * if it's too big, return -EINVAL. ++ * ++ * The driver's default par i.e. sisfb->default_par is convert from default_var ++ * during initialization. Default_var is either predefined or provided by find_mode(). ++ */ ++static int ++sisfb_get_var(struct fb_var_screeninfo * var, int con, struct fb_info * info) ++{ ++ const struct sisfb_info * sisfb = (struct sisfb_info *) info; ++ ++ if (con == -1) ++ /* initialization, get the var from default_par */ ++ sisfb_encode_var(var, &sisfb->default_par, sisfb); ++ else ++ *var = fb_display[con].var; ++ return 0; ++} ++ ++/* ++ * Set the User Defined Part of the Display ++ */ ++static int sisfb_set_var(struct fb_var_screeninfo * var, int con, struct fb_info * info) ++{ ++ struct sisfb_info * sisfb = (struct sisfb_info *) info; ++ struct sisfb_par par; ++ struct display * display; ++ int err, oldbpp; ++ ++ if (con == -1) ++ display = &sisfb->disp; ++ else ++ display = &fb_display[con]; ++ ++ /* try to convert var to HW register values (par) */ ++ if ((err = sisfb_decode_var(var, &par, sisfb))) ++ /* HW does not support this display mode */ ++ return err; ++ ++ /* return current mode to user */ ++ sisfb_encode_var(var, &par, sisfb); ++ ++ if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) ++ return 0; ++ ++ oldbpp = display->var.bits_per_pixel; ++ ++ if (display->var.xres != var->xres || ++ display->var.yres != var->yres || ++ display->var.xres_virtual != var->xres_virtual || ++ display->var.yres_virtual != var->yres_virtual || ++ display->var.bits_per_pixel != var->bits_per_pixel || ++ display->var.accel_flags != var->accel_flags) { ++ struct fb_fix_screeninfo fix; ++ ++ sisfb_encode_fix(&fix, &par, sisfb); ++ ++ display->screen_base = (char *) sisfb->video_base_virt; ++ display->visual = fix.visual; ++ display->type = fix.type; ++ display->type_aux = fix.type_aux; ++ display->ypanstep = fix.ypanstep; ++ display->ywrapstep = fix.ywrapstep; ++ display->line_length = fix.line_length; ++ display->next_line = fix.line_length; ++ display->can_soft_blank = 1; ++ display->inverse = inverse; ++ display->var = *var; ++ ++ sisfb->set_disp(display, sisfb, var->bits_per_pixel, 0); ++ ++ if (info->changevar) ++ (*info->changevar) (con); ++ } ++ ++ /* call sisfb_set_par if the console is visible (foreground) console ++ or during initialization */ ++ if (!sisfb->info.display_fg || sisfb->info.display_fg->vc_num == con || con < 0) ++ sisfb->set_par(&par, sisfb); ++ ++ /* clear OnScreen */ ++ memset((unsigned char *) sisfb->video_base_virt + par.screen_offset, 0, ++ par.line_length * var->yres); ++ ++ /* if we have changed the color depth, install new colormap ++ FixME: We only alloc_cmap but never free one ?? */ ++ if (oldbpp != var->bits_per_pixel || con < 0) { ++ if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) ++ return err; ++ do_install_cmap(display, info); ++ } ++ ++ return 0; ++} ++ ++/** ++ * sisfb_get_cmap: - Get the Colormap ++ * @cmap: Colormap to be get (return) ++ * @kspc: ++ * @con: Console number ++ * @info: Frame Buffer structure ++ * ++ * Get the colormap of console @con to @cmap. If the @con is the current console, ++ * get the colormap from the hardware registers otherwise we return the private ++ * colormap of the console. If the console does not have a private colormap we ++ * return the "default colormap". ++ */ ++static int ++sisfb_get_cmap(struct fb_cmap * cmap, int kspc, int con, struct fb_info * info) ++{ ++ struct sisfb_info * sisfb = (struct sisfb_info *) info; ++ struct display *disp; ++ ++ if (con == -1) ++ disp = &sisfb->disp; ++ else ++ disp = &fb_display[con]; ++ ++ if (con == sisfb->currcon) ++ /* current console, use getcolreg to get the HW colormap */ ++ return fb_get_cmap(cmap, kspc, sisfb_getcolreg, info); ++ else if (fb_display[con].cmap.len) ++ /* non default colormap? */ ++ fb_copy_cmap(&disp->cmap, cmap, kspc ? 0 : 2); ++ else ++ fb_copy_cmap(fb_default_cmap(sisfb->current_par.cmap_len), cmap, ++ kspc ? 0 : 2); ++ ++ return 0; ++} ++ ++/** ++ * sisfb_set_cmap: - Set the Colormap ++ * @cmap: Colormap to be set ++ * @kspc: ++ * @con: Console number ++ * @info: Frame Buffer structure ++ * ++ * Set the colormap of console @con to @cmap. If the colormap of console @con is ++ * not allocated yet, allocate it. If the @con is the current console, really set ++ * the hardware registers otherwise only set to the private colormap "in memory". ++ */ ++static int ++sisfb_set_cmap(struct fb_cmap * cmap, int kspc, int con, struct fb_info * info) ++{ ++ int err = 0; ++ struct sisfb_info * sisfb = (struct sisfb_info *) info; ++ struct display *disp; ++ ++ if (con == -1) ++ disp = &sisfb->disp; ++ else ++ disp = &fb_display[con]; ++ ++ if (disp->cmap.len == 0) { ++ /* no colormap allocated, allocate it */ ++ err = fb_alloc_cmap(&disp->cmap, sisfb->current_par.cmap_len, 0); ++ if (err) ++ return err; ++ } ++ ++ if (con == sisfb->currcon) ++ /* current console, use setcolreg to set the HW colormap */ ++ err = fb_set_cmap(cmap, kspc, sisfb_setcolreg, info); ++ else ++ /* not current console, don't touch the HW, make a copy instead */ ++ fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1); ++ ++ return err; ++} ++ ++/* ++ * Pan or Wrap the Display ++ * ++ * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag ++ */ ++static int ++sisfb_pan_display(struct fb_var_screeninfo * var, int con, struct fb_info * info) ++{ ++ struct sisfb_info * sisfb = (struct sisfb_info *) info; ++ struct display *disp; ++ ++ if (con == -1) ++ disp = &sisfb->disp; ++ else ++ disp = &fb_display[con]; ++ ++ if (var->xoffset > (var->xres_virtual - var->xres)) ++ return -EINVAL; ++ if (var->yoffset > (var->yres_virtual - var->yres)) ++ return -EINVAL; ++ ++ if (var->vmode & FB_VMODE_YWRAP) { ++ if (var->yoffset < 0 || ++ var->yoffset >= disp->var.yres_virtual || ++ var->xoffset) ++ return -EINVAL; ++ } else { ++ if (var->xoffset + disp->var.xres > disp->var.xres_virtual || ++ var->yoffset + disp->var.yres > disp->var.yres_virtual) ++ return -EINVAL; ++ } ++ ++ if (con == sisfb->currcon) ++ sisfb->pan_display(var, sisfb); ++ ++ /* update xoffset, yoffset and vmode members of var structure for current ++ * console this is neceressary since this function is called by a seperate ++ * ioctl function than set_var (actually, set_var doesn't care about these ++ * members at all) */ ++ disp->var.xoffset = var->xoffset; ++ disp->var.yoffset = var->yoffset; ++ ++ if (var->vmode & FB_VMODE_YWRAP) ++ disp->var.vmode |= FB_VMODE_YWRAP; ++ else ++ disp->var.vmode &= ~FB_VMODE_YWRAP; ++ ++ return 0; ++} ++ ++static int sisfb_ioctl(struct inode * inode, struct file * file, unsigned int cmd, ++ unsigned long arg, int con, struct fb_info * info) ++{ ++ return 0; ++} ++ ++static struct fb_ops sisfb_ops = { ++ owner: THIS_MODULE, ++ fb_get_fix: sisfb_get_fix, ++ fb_get_var: sisfb_get_var, ++ fb_set_var: sisfb_set_var, ++ fb_get_cmap: sisfb_get_cmap, ++ fb_set_cmap: sisfb_set_cmap, ++ fb_pan_display: sisfb_pan_display, ++ fb_ioctl: sisfb_ioctl, ++}; ++ ++int sisfb_setup(char * options) ++{ ++ char *this_opt; ++ ++ if (!options || !*options) ++ return 0; ++ ++ for (this_opt = strtok(options, ","); this_opt; ++ this_opt = strtok(NULL, ",")) { ++ if (!*this_opt) ++ continue; ++ ++ if (!strcmp(this_opt, "inverse")) { ++ inverse = 1; ++ fb_invert_cmaps(); ++ } else if (!strncmp(this_opt, "font:", 5)) { ++ strncpy(fontname, this_opt + 5, 40); ++ } else { ++ mode_option = this_opt; ++ } ++ } ++ return 0; ++} ++ ++static int __devinit ++sisfb_probe(struct pci_dev * pci_dev, const struct pci_device_id * pci_id) ++{ ++ struct sisfb_info * sisfb; ++ struct fb_var_screeninfo var; ++ ++ if (pci_enable_device(pci_dev)) ++ return -ENODEV; ++ ++ if ((sisfb = kmalloc(sizeof(struct sisfb_info), GFP_KERNEL)) == NULL) ++ return -ENOMEM; ++ memset(sisfb, 0, sizeof(struct sisfb_info)); ++ ++ sisfb->pci_dev = pci_dev; ++ ++ sisfb->video_base_phy = pci_resource_start(pci_dev, 0); ++ sisfb->video_size_phy = pci_resource_len(pci_dev, 0); ++ if (!request_mem_region(sisfb->video_base_phy, sisfb->video_size_phy, "sisfb FB")) { ++ printk(KERN_ERR "sisfb_lite: cannot reserve frame buffer memory\n"); ++ return -ENODEV; ++ } ++ ++ sisfb->mmio_base_phy = pci_resource_start(pci_dev, 1); ++ sisfb->mmio_size_phy = pci_resource_len(pci_dev, 1); ++ if (!request_mem_region(sisfb->mmio_base_phy, sisfb->mmio_size_phy, "sisfb MMIO")) { ++ printk(KERN_ERR "sisfb_lite: cannot reserve MMIO region\n"); ++ release_mem_region(sisfb->video_base_phy, sisfb->video_size_phy); ++ return -ENODEV; ++ } ++ ++ sisfb->vga_io_base = pci_resource_start(pci_dev, 2); ++ sisfb->vga_io_size = pci_resource_len(pci_dev, 2); ++ if (!request_region(sisfb->vga_io_base, sisfb->vga_io_size, "sisfb IO")) { ++ printk(KERN_ERR "sisfb_lite: cannot reserve I/O ports\n"); ++ release_mem_region(sisfb->video_base_phy, sisfb->video_size_phy); ++ release_mem_region(sisfb->mmio_base_phy, sisfb->mmio_size_phy); ++ return -ENODEV; ++ } ++ ++ sisfb_unlock_regs(sisfb); ++ ++ switch (pci_id->driver_data) { ++#ifdef CONFIG_FB_SIS_300 ++ case SISFB_LITE_300: ++ sisfb_init_300(sisfb); ++ break; ++#endif /* CONFIG_FB_SIS_300 */ ++#ifdef CONFIG_FB_SIS_315 ++ case SISFB_LITE_315: ++ sisfb_init_315(sisfb); ++ break; ++#endif /* CONFIG_FB_SIS_530 */ ++ case SISFB_LITE_530: ++ default: ++ printk(KERN_ERR "UnSupupported SiS VGA Core\n"); ++ goto failed; ++ } ++ ++ strcpy(sisfb->info.modename, "SiSFB Lite"); ++ ++ sisfb->info.changevar = NULL; ++ sisfb->info.node = -1; ++ sisfb->info.fbops = &sisfb_ops; ++ sisfb->info.disp = &sisfb->disp; ++ strcpy(sisfb->info.fontname, fontname); ++ sisfb->info.switch_con = &sisfb_switch_con; ++ sisfb->info.updatevar = &sisfb_updatevar; ++ sisfb->info.blank = &sisfb_blank; ++ sisfb->info.flags = FBINFO_FLAG_DEFAULT; ++ ++ sisfb->currcon = -1; ++ ++ memset(&var, 0, sizeof(var)); ++ if (fb_find_mode(&var, &sisfb->info, mode_option, NULL, 0, &sisfb_default_mode, 8) == 0) ++ var = default_var; ++ ++ /* get the default_par and make it as our current_par */ ++ sisfb_decode_var(&var, &sisfb->default_par, sisfb); ++ sisfb->current_par = sisfb->default_par; ++ sisfb->disp.var = var; ++ ++ sisfb->currcon = 0; ++ ++ if (register_framebuffer((struct fb_info *) sisfb) < 0) { ++ goto failed; ++ } ++ ++ /* make sisfb a driver_data of the PCI device */ ++ pci_set_drvdata(pci_dev, sisfb); ++ ++ return 0; ++ ++ failed: ++ /* clean things up when failed to register frame buffer */ ++ pci_dev->driver_data = NULL; ++ release_mem_region(sisfb->video_base_phy, sisfb->video_size_phy); ++ release_mem_region(sisfb->mmio_base_phy, sisfb->mmio_size_phy); ++ release_region(sisfb->vga_io_base, sisfb->vga_io_size); ++ ++ iounmap(sisfb->video_base_virt); ++ iounmap(sisfb->mmio_base_virt); ++ ++#ifdef CONFIG_MTRR ++ mtrr_del(sisfb->mtrr, sisfb->video_base_phy, sisfb->video_size_virt); ++#endif /* CONFIG_MTRR */ ++ ++ kfree(sisfb); ++ return -EINVAL; ++} ++ ++static void __devexit ++sisfb_remove(struct pci_dev * pci_dev) ++{ ++ struct sisfb_info * sisfb = pci_get_drvdata(pci_dev); ++ ++ unregister_framebuffer((struct fb_info *) sisfb); ++ ++ release_mem_region(sisfb->video_base_phy, sisfb->video_size_phy); ++ release_mem_region(sisfb->mmio_base_phy, sisfb->mmio_size_phy); ++ release_region(sisfb->vga_io_base, sisfb->vga_io_size); ++ ++ iounmap(sisfb->video_base_virt); ++ iounmap(sisfb->mmio_base_virt); ++ ++#ifdef CONFIG_MTRR ++ mtrr_del(sisfb->mtrr, sisfb->video_base_phy, sisfb->video_size_virt); ++#endif /* CONFIG_MTRR */ ++ ++ kfree(sisfb); ++ pci_set_drvdata(pci_dev, NULL); ++} ++ ++#define SISFB_MODULE_NAME "sisfb_lite" ++ ++static struct pci_driver sisfb_pci_driver = { ++ name: SISFB_MODULE_NAME, ++ id_table: sisfb_pci_tbl, ++ probe: sisfb_probe, ++ remove: sisfb_remove, ++}; ++ ++static const char * version = "$Id$"; ++ ++int __init sisfb_init(void) ++{ ++ printk(KERN_INFO "sisfb_lite: %s\n", version); ++ ++ return pci_module_init(&sisfb_pci_driver); ++} ++ ++static void __exit sisfb_cleanup(void) ++{ ++ pci_unregister_driver(&sisfb_pci_driver); ++} ++ ++#ifdef MODULE ++module_init(sisfb_init); ++#endif /* MODULE */ ++ ++module_exit(sisfb_cleanup); +diff -urN linux-2.4.19/drivers/video/sis/sisfb_lite.h linux-2.4.19-linuxbios/drivers/video/sis/sisfb_lite.h +--- linux-2.4.19/drivers/video/sis/sisfb_lite.h Thu Jan 1 08:00:00 1970 ++++ linux-2.4.19-linuxbios/drivers/video/sis/sisfb_lite.h Mon Sep 2 17:23:10 2002 +@@ -0,0 +1,214 @@ ++#ifndef __SISFB_LITE__ ++#define __SISFB_LITE__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#ifdef CONFIG_MTRR ++#include ++#endif ++ ++#include