Resent-Date: Thu, 26 Aug 1999 21:27:27 +0200 (MET DST)
Sender: jgarzik@ext1.nea-fast.com
Date: Thu, 26 Aug 1999 15:25:49 -0400
From: Jeff Garzik <jgarzik@pobox.com>
Organization: none
X-Accept-Language: en
To: linux-fbdev <linux-fbdev@vuser.vu.union.edu>,
        linux-m68k@lists.linux-m68k.org, linux-apus@sunsite.auc.dk
Subject: Updated cyberfb
Resent-From: linux-m68k@phil.uni-sb.de

This is a multi-part message in MIME format.
--------------C66FF20F2AF84AD93378EE84
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

The attached patch adds PCI support to S3 Trio devices.  The patch is
against 2.3.15 but hopefully will apply to earlier kernel versions as
well, since cyberfb isn't updated too often.

Would it be possible for someone with a CyberVision64 board to test
this, and make sure that my patch does not break Zorro platforms?

Thanks,

	Jeff


P.S. Does anybody have an updated e-mail address for Alan Bair, the
cyberfb author?  I wanted to make sure he got a copy of these changes,
but the e-mail address I have for him bounces.

-- 
"Nuclear war can ruin your whole compile."
                -- Karl Lehenbauer
--------------C66FF20F2AF84AD93378EE84
Content-Type: text/plain; charset=us-ascii;
 name="cyberfb.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="cyberfb.patch"

diff -urN /g/vanilla/v2.3.15/linux/drivers/video/Config.in linux/drivers/video/Config.in
--- /g/vanilla/v2.3.15/linux/drivers/video/Config.in	Thu Aug 26 14:06:50 1999
+++ linux/drivers/video/Config.in	Thu Aug 26 15:18:35 1999
@@ -91,6 +91,7 @@
         bool '  Multihead support' CONFIG_FB_MATROX_MULTIHEAD
       fi
       tristate 'ATI Mach64 display support' CONFIG_FB_ATY
+      tristate 'S3 Trio 64V+/64V2 support' CONFIG_FB_CYBER
     fi
   fi
   if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
diff -urN /g/vanilla/v2.3.15/linux/drivers/video/cyberfb.c linux/drivers/video/cyberfb.c
--- /g/vanilla/v2.3.15/linux/drivers/video/cyberfb.c	Thu Aug 26 14:06:53 1999
+++ linux/drivers/video/cyberfb.c	Thu Aug 26 15:18:35 1999
@@ -84,20 +84,27 @@
 #include <linux/tty.h>
 #include <linux/malloc.h>
 #include <linux/delay.h>
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#endif
+#ifdef CONFIG_ZORRO
 #include <linux/zorro.h>
+#endif
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/pgtable.h>
+#ifdef CONFIG_AMIGA
 #include <asm/amigahw.h>
+#endif
 #include <asm/io.h>
 
-#include "cyberfb.h"
 #include <video/fbcon.h>
 #include <video/fbcon-cfb8.h>
 #include <video/fbcon-cfb16.h>
+#include "cyberfb.h"
 
 /*#define CYBERFBDEBUG*/
 #ifdef CYBERFBDEBUG
@@ -108,11 +115,26 @@
 #endif
 
 #define arraysize(x)    (sizeof(x)/sizeof(*(x)))
+#define IO_OUT16VAL(v, r)       (((v) << 8) | (r))
 
-#define wb_64(regs,reg,dat) (*(((volatile unsigned char *)regs) + reg) = dat)
-#define rb_64(regs, reg) (*(((volatile unsigned char *)regs) + reg))
+static inline void wb_64 (char *regs, unsigned short reg, unsigned char dat)
+{
+	writeb (dat, regs + reg);
+}
+
+static inline unsigned char rb_64 (char *regs, unsigned short reg)
+{
+	return readb (regs + reg);
+}
 
-#define ww_64(regs,reg,dat) (*((volatile unsigned short *)(regs + reg) = dat)
+static inline void ww_64 (char *regs, unsigned short reg, unsigned short dat)
+{
+#ifdef CONFIG_PCI
+	writew (dat, regs + reg);
+#else
+	(*((volatile unsigned short *)(regs + reg) = dat)
+#endif
+}
 
 struct cyberfb_par {
 	struct fb_var_screeninfo var;
@@ -144,9 +166,9 @@
 
 static unsigned char Cyber_colour_table [256][3];
 static unsigned long CyberSize;
-static volatile unsigned char *CyberBase;
-static volatile unsigned char *CyberMem;
-static volatile unsigned char *CyberRegs;
+static unsigned char *CyberBase;
+static unsigned char *CyberMem;
+static unsigned char *CyberRegs;
 static unsigned long CyberMem_phys;
 static unsigned long CyberRegs_phys;
 
@@ -319,8 +341,8 @@
 
 /* For cvision_core.c */
 static unsigned short cv64_compute_clock(unsigned long);
-static int cv_has_4mb (volatile unsigned char *);
-static void cv64_board_init (void);
+static int cv_has_4mb (unsigned char *);
+static int cv64_board_init (void);
 static void cv64_load_video_mode (struct fb_var_screeninfo *);
 
 
@@ -336,8 +358,8 @@
 
 static int Cyber_init(void)
 {
-	volatile unsigned char *regs = CyberRegs;
-	volatile unsigned long *CursorBase;
+	unsigned char *regs = CyberRegs;
+	unsigned char *CursorBase;
 	int i;
 	DPRINTK("ENTER\n");
 
@@ -349,7 +371,9 @@
 	}
 
 /* Initialize the board and determine fbmem size */
-	cv64_board_init(); 
+	if (cv64_board_init() != 0)
+		return -1;
+		
 #ifdef CYBERFBDEBUG
 	DPRINTK("Register state after initing board\n");
 	cv64_dump();
@@ -371,20 +395,20 @@
 
 /* Initialize hardware cursor */
 	DPRINTK("Init HW cursor\n");
-	CursorBase = (u_long *)((char *)(CyberMem) + CyberSize - 0x400);
+	CursorBase = CyberMem + CyberSize - 0x400;
 	for (i=0; i < 8; i++)
 	{
-		*(CursorBase  +(i*4)) = 0xffffff00;
-		*(CursorBase+1+(i*4)) = 0xffff0000;
-		*(CursorBase+2+(i*4)) = 0xffff0000;
-		*(CursorBase+3+(i*4)) = 0xffff0000;
+		writel (0xffffff00, CursorBase  +(i*4));
+		writel (0xffff0000, CursorBase+1+(i*4));
+		writel (0xffff0000, CursorBase+2+(i*4));
+		writel (0xffff0000, CursorBase+3+(i*4));
 	}
 	for (i=8; i < 64; i++)
 	{
-		*(CursorBase  +(i*4)) = 0xffff0000;
-		*(CursorBase+1+(i*4)) = 0xffff0000;
-		*(CursorBase+2+(i*4)) = 0xffff0000;
-		*(CursorBase+3+(i*4)) = 0xffff0000;
+		writel (0xffff0000, CursorBase  +(i*4));
+		writel (0xffff0000, CursorBase+1+(i*4));
+		writel (0xffff0000, CursorBase+2+(i*4));
+		writel (0xffff0000, CursorBase+3+(i*4));
 	}
 
 	Cyber_setcolreg (255, 56<<8, 100<<8, 160<<8, 0, NULL /* unused */);
@@ -528,7 +552,7 @@
 static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 			   u_int transp, struct fb_info *info)
 {
-	volatile unsigned char *regs = CyberRegs;
+	unsigned char *regs = CyberRegs;
 
 	/*DPRINTK("ENTER\n");*/
 	if (regno > 255) {
@@ -591,7 +615,7 @@
 
 void Cyberfb_blank(int blank, struct fb_info *info)
 {
-	volatile unsigned char *regs = CyberRegs;
+	unsigned char *regs = CyberRegs;
 	int i;
 
 	DPRINTK("ENTER\n");
@@ -620,6 +644,12 @@
 }
 
 
+static inline
+unsigned short Cyber_ReadGpStat (void)
+{
+	return readw(CyberRegs + S3_GP_STAT);
+}
+
 /**************************************************************
  * We are waiting for "fifo" FIFO-slots empty
  */
@@ -629,7 +659,7 @@
 
 	DPRINTK("ENTER\n");
 	do {
-		status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
+		status = Cyber_ReadGpStat();
 	} while (status & fifo);
 	DPRINTK("EXIT\n");
 }
@@ -640,11 +670,12 @@
 static void Cyber_WaitBlit (void)
 {
 	unsigned short status;
+	unsigned limit = 100000;
 
 	DPRINTK("ENTER\n");
 	do {
-		status = *((u_short volatile *)(CyberRegs + S3_GP_STAT));
-	} while (status & S3_HDW_BUSY);
+		status = Cyber_ReadGpStat();
+	} while ((status & S3_HDW_BUSY) && (--limit > 0));
 	DPRINTK("EXIT\n");
 }
 
@@ -655,7 +686,7 @@
 			  u_short desty, u_short width, u_short height,
 			  u_short mode)
 {
-	volatile unsigned char *regs = CyberRegs;
+	unsigned char *regs = CyberRegs;
 	u_short blitcmd = S3_BITBLT;
 
 	DPRINTK("ENTER\n");
@@ -677,19 +708,19 @@
 
 	Cyber_WaitQueue (0x8000);
 
-	*((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000;
-	*((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0060 | mode);
+	writew (0xa000, regs + S3_PIXEL_CNTL);
+	writew ((0x0060 | mode), regs + S3_FRGD_MIX);
 
-	*((u_short volatile *)(regs + S3_CUR_X)) = curx;
-	*((u_short volatile *)(regs + S3_CUR_Y)) = cury;
+	writew (curx, regs + S3_CUR_X);
+	writew (cury, regs + S3_CUR_Y);
 
-	*((u_short volatile *)(regs + S3_DESTX_DIASTP)) = destx;
-	*((u_short volatile *)(regs + S3_DESTY_AXSTP)) = desty;
+	writew (destx, regs + S3_DESTX_DIASTP);
+	writew (desty, regs + S3_DESTY_AXSTP);
 
-	*((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1;
-	*((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width  - 1;
+	writew (height - 1, regs + S3_MIN_AXIS_PCNT);
+	writew (width  - 1, regs + S3_MAJ_AXIS_PCNT);
 
-	*((u_short volatile *)(regs + S3_CMD)) = blitcmd;
+	writew (blitcmd, regs + S3_CMD);
 	DPRINTK("EXIT\n");
 }
 
@@ -699,25 +730,25 @@
 static void Cyber_RectFill (u_short x, u_short y, u_short width,
 			    u_short height, u_short mode, u_short color)
 {
-	volatile unsigned char *regs = CyberRegs;
+	unsigned char *regs = CyberRegs;
 	u_short blitcmd = S3_FILLEDRECT;
 
 	DPRINTK("ENTER\n");
 	Cyber_WaitQueue (0x8000);
 
-	*((u_short volatile *)(regs + S3_PIXEL_CNTL)) = 0xa000;
-	*((u_short volatile *)(regs + S3_FRGD_MIX)) = (0x0020 | mode);
+	writew (0xa000, regs + S3_PIXEL_CNTL);
+	writew ((0x0020 | mode), regs + S3_FRGD_MIX);
 
-	*((u_short volatile *)(regs + S3_MULT_MISC)) = 0xe000;
-	*((u_short volatile *)(regs + S3_FRGD_COLOR)) = color;
+	writew (0xe000, regs + S3_MULT_MISC);
+	writew (color, regs + S3_FRGD_COLOR);
 
-	*((u_short volatile *)(regs + S3_CUR_X)) = x;
-	*((u_short volatile *)(regs + S3_CUR_Y)) = y;
+	writew (x, regs + S3_CUR_X);
+	writew (y, regs + S3_CUR_Y);
 
-	*((u_short volatile *)(regs + S3_MIN_AXIS_PCNT)) = height - 1;
-	*((u_short volatile *)(regs + S3_MAJ_AXIS_PCNT)) = width  - 1;
+	writew (height - 1, regs + S3_MIN_AXIS_PCNT);
+	writew (width  - 1, regs + S3_MAJ_AXIS_PCNT);
 
-	*((u_short volatile *)(regs + S3_CMD)) = blitcmd;
+	writew (blitcmd, regs + S3_CMD);
 	DPRINTK("EXIT\n");
 }
 
@@ -730,18 +761,13 @@
 {
 	volatile unsigned char *regs = CyberRegs;
 	DPRINTK("ENTER\n");
-	*(regs + S3_CRTC_ADR)  = 0x39;
-	*(regs + S3_CRTC_DATA) = 0xa0;
+	WCrt (regs, 0x39, 0xa0);
 
-	*(regs + S3_CRTC_ADR)  = S3_HWGC_ORGX_H;
-	*(regs + S3_CRTC_DATA) = (char)((x & 0x0700) >> 8);
-	*(regs + S3_CRTC_ADR)  = S3_HWGC_ORGX_L;
-	*(regs + S3_CRTC_DATA) = (char)(x & 0x00ff);
-
-	*(regs + S3_CRTC_ADR)  = S3_HWGC_ORGY_H;
-	*(regs + S3_CRTC_DATA) = (char)((y & 0x0700) >> 8);
-	*(regs + S3_CRTC_ADR)  = S3_HWGC_ORGY_L;
-	*(regs + S3_CRTC_DATA) = (char)(y & 0x00ff);
+	WCrt (regs, S3_HWGC_ORGX_H, (char)((x & 0x0700) >> 8));
+	WCrt (regs, S3_HWGC_ORGX_L, (char)(x & 0x00ff));
+
+	WCrt (regs, S3_HWGC_ORGY_H, (char)((y & 0x0700) >> 8));
+	WCrt (regs, S3_HWGC_ORGY_L, (char)(y & 0x00ff));
 	DPRINTK("EXIT\n");
 }
 #endif
@@ -1107,10 +1133,21 @@
 	struct cyberfb_par par;
 	unsigned long board_addr;
 	unsigned long board_size;
+#ifdef CONFIG_ZORRO
 	const struct ConfigDev *cd;
 	unsigned int CyberKey = 0;
+#endif
+#ifdef CONFIG_PCI
+	struct pci_dev *pdev;
+#endif
+
+	/*
+	 * XXX multiple boards not supported
+	 */
+
 	DPRINTK("ENTER\n");
 
+#ifdef CONFIG_ZORRO
 	if (!(CyberKey = zorro_find(ZORRO_PROD_PHASE5_CYBERVISION64, 0, 0))) {
 		DPRINTK("EXIT - zorro_find failed\n");
 		return -ENXIO;
@@ -1133,6 +1170,67 @@
 	CyberRegs_phys = CyberMem_phys + 0x00c00000;
 	DPRINTK("CyberMem=%08lx CyberRegs=%08lx\n", CyberMem,
 		(long unsigned int)CyberRegs);
+#endif
+
+#ifdef CONFIG_PCI
+	pdev = pci_find_device(PCI_VENDOR_ID_S3,
+			       PCI_DEVICE_ID_S3_TRIO, NULL);
+	if (!pdev)
+		pdev = pci_find_device(PCI_VENDOR_ID_S3,
+				       PCI_DEVICE_ID_S3_TRIO64V2, NULL);
+	if (!pdev)
+		pdev = pci_find_device(PCI_VENDOR_ID_S3,
+				       PCI_DEVICE_ID_S3_TRIO64UVP, NULL);
+	if (!pdev) {
+		DPRINTK("EXIT - pci_find_device failed\n");
+		return -ENXIO;
+	}
+	DPRINTK("Found S3 Trio PCI device\n");
+
+	board_addr = pdev->resource[0].start;
+	board_size = pdev->resource[0].end - pdev->resource[0].start + 1;
+	DPRINTK("board_addr=%08lx\n", board_addr);
+	DPRINTK("board_size=%08lx\n", board_size);
+
+	CyberBase = ioremap(board_addr, board_size);
+	CyberRegs = CyberBase + 0x1008000;
+	CyberMem = CyberBase;
+	DPRINTK("CyberBase=%p CyberRegs=%p CyberMem=%p\n",
+		CyberBase, CyberRegs, CyberMem);
+
+	CyberMem_phys = board_addr;
+	CyberRegs_phys = CyberMem_phys + 0x1008000;
+	DPRINTK("CyberMem=%p CyberRegs=%p\n", CyberMem, CyberRegs);
+
+	pci_write_config_word(pdev, PCI_COMMAND,
+			      PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+
+	/* unlock s3 */
+
+	outb(0x01, 0x3C3);
+
+	outb(inb(0x03CC) | 1, 0x3c2);
+
+	outw(IO_OUT16VAL(0x48, 0x38),0x03D4);
+	outw(IO_OUT16VAL(0xA0, 0x39),0x03D4);
+	outb(0x33,0x3d4);
+	outw(IO_OUT16VAL((inb(0x3d5) & ~(0x2 | 0x10 |  0x40)) |
+			  0x20, 0x33), 0x3d4);
+
+	outw(IO_OUT16VAL(0x6, 0x8), 0x3c4);
+
+	/* switch to MMIO only mode */
+
+	outb(0x58, 0x3d4);
+	outw(IO_OUT16VAL(inb(0x3d5) | 3 | 0x10, 0x58), 0x3d4);
+	outw(IO_OUT16VAL(8, 0x53), 0x3d4);
+
+	/* disable PIO */
+	outw(IO_OUT16VAL(0x80, 0x9), 0x3c4);
+	pci_write_config_word(pdev, PCI_COMMAND, PCI_COMMAND_MEMORY);
+
+
+#endif
 
 #ifdef CYBERFBDEBUG
 	DPRINTK("Register state just after mapping memory\n");
@@ -1148,7 +1246,9 @@
 	fb_info.updatevar = &Cyberfb_updatevar;
 	fb_info.blank = &Cyberfb_blank;
 
-	Cyber_init();
+	if (Cyber_init() != 0)
+		return -ENXIO;
+		
 	/* ++Andre: set cyberfb default mode */
 	if (!cyberfb_usermode) {
 		cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var;
@@ -1309,6 +1409,9 @@
 	/* Not reached because the usecount will never be
 	   decremented to zero */
 	unregister_framebuffer(&fb_info);
+#ifdef CONFIG_PCI
+	iounmap(CyberBase);
+#endif
 	/* TODO: clean up ... */
 }
 #endif /* MODULE */
@@ -1420,7 +1523,7 @@
 /* -------------------- Hardware specific routines ------------------------- */
 
 /* Read Attribute Controller Register=idx */
-inline unsigned char RAttr (volatile unsigned char *regs, short idx)
+inline unsigned char RAttr (unsigned char *regs, short idx)
 {
 	wb_64 (regs, ACT_ADDRESS_W, idx);
 	mb();
@@ -1429,7 +1532,7 @@
 }
 
 /* Read Sequencer Register=idx */
-inline unsigned char RSeq (volatile unsigned char *regs, short idx)
+inline unsigned char RSeq (unsigned char *regs, short idx)
 {
 	wb_64 (regs, SEQ_ADDRESS, idx);
 	mb();
@@ -1437,7 +1540,7 @@
 }
 
 /* Read CRT Controller Register=idx */
-inline unsigned char RCrt (volatile unsigned char *regs, short idx)
+inline unsigned char RCrt (unsigned char *regs, short idx)
 {
 	wb_64 (regs, CRT_ADDRESS, idx);
 	mb();
@@ -1445,7 +1548,7 @@
 }
 
 /* Read Graphics Controller Register=idx */
-inline unsigned char RGfx (volatile unsigned char *regs, short idx)
+inline unsigned char RGfx (unsigned char *regs, short idx)
 {
 	wb_64 (regs, GCT_ADDRESS, idx);
 	mb();
@@ -1459,6 +1562,7 @@
 inline void cv64_write_port (unsigned short bits,
 			     volatile unsigned char *base)
 {
+#ifdef CONFIG_ZORRO
 	volatile unsigned char *addr;
 	static unsigned char cvportbits = 0; /* Mirror port bits here */
 	DPRINTK("ENTER\n");
@@ -1476,6 +1580,7 @@
 
 	*addr = cvportbits;
 	DPRINTK("EXIT\n");
+#endif /* CONFIG_ZORRO */
 }
 
 /*
@@ -1489,6 +1594,7 @@
  */
 inline void cvscreen (int toggle, volatile unsigned char *board)
 {
+#ifdef CONFIG_ZORRO
 	DPRINTK("ENTER\n");
 	if (toggle == 1) {
 		DPRINTK("Show Amiga video\n");
@@ -1498,12 +1604,13 @@
 		cv64_write_port (0x8010, board);
 	}
 	DPRINTK("EXIT\n");
+#endif /* CONFIG_ZORRO */
 }
 
 /* Control screen display */
 /* toggle: 0 = on, 1 = off */
 /* board = registerbase */
-inline void gfx_on_off(int toggle, volatile unsigned char *regs)
+inline void gfx_on_off(int toggle, unsigned char *regs)
 {
 	int r;
 	DPRINTK("ENTER\n");
@@ -1516,6 +1623,7 @@
 	r &= 0xdf;	/* Set bit 5 to 0 */
 	
 	WSeq (regs, SEQ_ID_CLOCKING_MODE, r | toggle);
+	udelay(10000);
 	DPRINTK("EXIT\n");
 }
 
@@ -1571,7 +1679,7 @@
 	return (erg);
 }
 
-static int cv_has_4mb (volatile unsigned char *fb)
+static int cv_has_4mb (unsigned char *fb)
 {
 	volatile unsigned long *tr, *tw;
 	DPRINTK("ENTER\n");
@@ -1616,12 +1724,12 @@
 	return (1);
 }
 
-static void cv64_board_init (void)
+static int cv64_board_init (void)
 {
-	volatile unsigned char *regs = CyberRegs;
+	unsigned char *regs = CyberRegs;
 	int i;
 	unsigned int clockpar;
-	unsigned char test;
+	unsigned char test, revision;
 	
 	DPRINTK("ENTER\n");
 
@@ -1676,8 +1784,9 @@
 	
 	/* Reset. This does nothing on Trio, but standard VGA practice */
 	/* WSeq (CyberRegs, SEQ_ID_RESET, 0x03); */
-	/* Character clocks 8 dots wide */
-	WSeq (regs, SEQ_ID_CLOCKING_MODE, 0x01);
+	/* Character clocks 8 dots wide, turn screen off */
+	WSeq (regs, SEQ_ID_CLOCKING_MODE, 0x01 | 0x20);
+	udelay(10000);
 	/* Enable cpu write to all color planes */
 	WSeq (regs, SEQ_ID_MAP_MASK, 0x0F);
 	/* Font table in 1st 8k of plane 2, font A=B disables swtich */
@@ -1687,6 +1796,15 @@
 	/* Unlock S3 extensions to VGA Sequencer regs */
 	WSeq (regs, SEQ_ID_UNLOCK_EXT, 0x6);
 	
+	revision = RCrt (regs, CRT_ID_REVISION);
+
+#ifdef CONFIG_PCI
+	if (!(revision & 0x40)) {
+		printk(KERN_ERR "Non-64V+ Trio found, aborting, unsupported\n");
+		return -1;
+	}
+#endif
+
 	/* Enable 4MB fast page mode */
 	test = RSeq (regs, SEQ_ID_BUS_REQ_CNTL);
 	test = test | 1 << 6;
@@ -1795,8 +1913,8 @@
 
 	wb_64 (regs, VDAC_MASK, 0xFF);
 
-	*((unsigned long *) (regs + ECR_FRGD_COLOR)) = 0xFF;
-	*((unsigned long *) (regs + ECR_BKGD_COLOR)) = 0;
+	writel (0xFF, regs + ECR_FRGD_COLOR);
+	writel (0, regs + ECR_BKGD_COLOR);
 
 	/* Colors initially set to grayscale */
 
@@ -1812,6 +1930,7 @@
 
 	/* Set first to 4MB, so test will work */
 	WCrt (regs, CRT_ID_LAW_CNTL, 0x13);
+
 	/* Find "correct" size of fbmem of Z3 board */
 	if (cv_has_4mb (CyberMem)) {
 		CyberSize = 1024 * 1024 * 4;
@@ -1823,6 +1942,28 @@
 		DPRINTK("2MB board\n");
 	}
 
+#ifdef CONFIG_PCI
+	/* force enhanced mode mappings (dword addressing),
+	 * high speed text display */
+	WCrt (regs, CRT_ID_MEMORY_CONF, 0x08 | 0x40);
+	
+	/* reset graphics engine via CR66, enable enh. func, PCI disconnect */
+	WCrt (regs, CRT_ID_EXT_MISC_CNTL_1, 0x01 | 0x02 | 0x08 | 0x80);
+	udelay(10000);
+	Cyber_WaitBlit();
+	WCrt (regs, CRT_ID_EXT_MISC_CNTL_1, 0x01 | 0x08 | 0x80);
+
+	/* set graphics engine to normal */
+	vgaw16 (regs, ECR_SUBSYSTEM_CNTL, 1 << 14);
+	
+	/* enhanced, 8bpp, linear addressing */
+	vgaw16 (regs, ECR_ADV_FUNC_CNTL, 0x01 | 0x04 | 0x10);
+
+	/* enable PCI read bursts, must be done after CR66 */
+	WCrt (regs, CRT_ID_MISC_1,
+		RCrt (regs, CRT_ID_MISC_1) | 0x80);
+#endif
+
 	/* Initialize graphics engine */
 	Cyber_WaitBlit();
 	vgaw16 (regs, ECR_FRGD_MIX, 0x27);
@@ -1871,11 +2012,13 @@
 	cvscreen (0, CyberBase);
 
 	DPRINTK("EXIT\n");
+	
+	return 0;
 }
 
 static void cv64_load_video_mode (struct fb_var_screeninfo *video_mode)
 {
-  volatile unsigned char *regs = CyberRegs;
+  unsigned char *regs = CyberRegs;
   int fx, fy;
   unsigned short mnr;
   unsigned short HT, HDE, HBS, HBE, HSS, HSE, VDE, VBS, VBE, VSS, VSE, VT;
@@ -1974,6 +2117,7 @@
     VT  = yres + vfront + vsync + vback - 2;
   }
 
+  Cyber_WaitBlit();
   wb_64 (regs, ECR_ADV_FUNC_CNTL, (TEXT ? 0x00 : 0x31));
 	
   if (TEXT)
@@ -2103,7 +2247,7 @@
   cr50 = 0x00;
 	
   test = RCrt (regs, CRT_ID_EXT_MISC_CNTL_2);
-  test &= 0xD;
+  test &= 0x01;
 	
   /* Clear roxxler byte-swapping... */
   cv64_write_port (0x0040, CyberBase);
@@ -2249,7 +2393,7 @@
   WAttr (regs, 0x33, 0);
 	
   /* Turn gfx on again */
-  gfx_on_off (0, (volatile unsigned char *) regs);
+  gfx_on_off (0, regs);
 	
   /* Pass-through */
   cvscreen (0, CyberBase);
@@ -2260,7 +2404,7 @@
 void cvision_bitblt (u_short sx, u_short sy, u_short dx, u_short dy,
 		     u_short w, u_short h)
 {
-	volatile unsigned char *regs = CyberRegs;
+	unsigned char *regs = CyberRegs;
 	unsigned short drawdir = 0;
 	
 	DPRINTK("ENTER\n");
@@ -2298,7 +2442,7 @@
 
 void cvision_clear (u_short dx, u_short dy, u_short w, u_short h, u_short bg)
 {
-	volatile unsigned char *regs = CyberRegs;
+	unsigned char *regs = CyberRegs;
 	DPRINTK("ENTER\n");
 	Cyber_WaitBlit();
 	vgaw16 (regs, ECR_FRGD_MIX, 0x0027);
@@ -2318,84 +2462,57 @@
  */
 static void cv64_dump (void)
 {
-	volatile unsigned char *regs = CyberRegs;
+	unsigned char *regs = CyberRegs;
 	DPRINTK("ENTER\n");
         /* Dump the VGA setup values */
-	*(regs + S3_CRTC_ADR) = 0x00;
-	DPRINTK("CR00 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x01;
-	DPRINTK("CR01 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x02;
-	DPRINTK("CR02 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x03;
-	DPRINTK("CR03 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x04;
-	DPRINTK("CR04 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x05;
-	DPRINTK("CR05 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x06;
-	DPRINTK("CR06 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x07;
-	DPRINTK("CR07 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x08;
-	DPRINTK("CR08 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x09;
-	DPRINTK("CR09 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x10;
-	DPRINTK("CR10 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x11;
-	DPRINTK("CR11 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x12;
-	DPRINTK("CR12 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x13;
-	DPRINTK("CR13 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x15;
-	DPRINTK("CR15 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x16;
-	DPRINTK("CR16 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x36;
-	DPRINTK("CR36 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x37;
-	DPRINTK("CR37 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x42;
-	DPRINTK("CR42 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x43;
-	DPRINTK("CR43 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x50;
-	DPRINTK("CR50 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x51;
-	DPRINTK("CR51 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x53;
-	DPRINTK("CR53 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x58;
-	DPRINTK("CR58 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x59;
-	DPRINTK("CR59 = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x5A;
-	DPRINTK("CR5A = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x5D;
-	DPRINTK("CR5D = %x\n", *(regs + S3_CRTC_DATA));
-	*(regs + S3_CRTC_ADR) = 0x5E;
-	DPRINTK("CR5E = %x\n", *(regs + S3_CRTC_DATA));
-	DPRINTK("MISC = %x\n", *(regs + GREG_MISC_OUTPUT_R));
-	*(regs + SEQ_ADDRESS) = 0x01;
-	DPRINTK("SR01 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x02;
-	DPRINTK("SR02 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x03;
-	DPRINTK("SR03 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x09;
-	DPRINTK("SR09 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x10;
-	DPRINTK("SR10 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x11;
-	DPRINTK("SR11 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x12;
-	DPRINTK("SR12 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x13;
-	DPRINTK("SR13 = %x\n", *(regs + SEQ_ADDRESS_R));
-	*(regs + SEQ_ADDRESS) = 0x15;
-	DPRINTK("SR15 = %x\n", *(regs + SEQ_ADDRESS_R));
+	DPRINTK("CR00 = %x\n", RCrt (regs, 0x00));
+	DPRINTK("CR01 = %x\n", RCrt (regs, 0x01));
+	DPRINTK("CR02 = %x\n", RCrt (regs, 0x02));
+	DPRINTK("CR03 = %x\n", RCrt (regs, 0x03));
+	DPRINTK("CR04 = %x\n", RCrt (regs, 0x04));
+	DPRINTK("CR05 = %x\n", RCrt (regs, 0x05));
+	DPRINTK("CR06 = %x\n", RCrt (regs, 0x06));
+	DPRINTK("CR07 = %x\n", RCrt (regs, 0x07));
+	DPRINTK("CR08 = %x\n", RCrt (regs, 0x08));
+	DPRINTK("CR09 = %x\n", RCrt (regs, 0x09));
+	DPRINTK("CR10 = %x\n", RCrt (regs, 0x10));
+	DPRINTK("CR11 = %x\n", RCrt (regs, 0x11));
+	DPRINTK("CR12 = %x\n", RCrt (regs, 0x12));
+	DPRINTK("CR13 = %x\n", RCrt (regs, 0x13));
+	DPRINTK("CR15 = %x\n", RCrt (regs, 0x15));
+	DPRINTK("CR16 = %x\n", RCrt (regs, 0x16));
+	DPRINTK("CR31 = %x\n", RCrt (regs, 0x31));
+	DPRINTK("CR35 = %x\n", RCrt (regs, 0x35));
+	DPRINTK("CR36 = %x\n", RCrt (regs, 0x36));
+	DPRINTK("CR37 = %x\n", RCrt (regs, 0x37));
+	DPRINTK("CR38 = %x\n", RCrt (regs, 0x38));
+	DPRINTK("CR39 = %x\n", RCrt (regs, 0x39));
+	DPRINTK("CR3A = %x\n", RCrt (regs, 0x3A));
+	DPRINTK("CR40 = %x\n", RCrt (regs, 0x40));
+	DPRINTK("CR42 = %x\n", RCrt (regs, 0x42));
+	DPRINTK("CR43 = %x\n", RCrt (regs, 0x43));
+	DPRINTK("CR50 = %x\n", RCrt (regs, 0x50));
+	DPRINTK("CR51 = %x\n", RCrt (regs, 0x51));
+	DPRINTK("CR53 = %x\n", RCrt (regs, 0x53));
+	DPRINTK("CR58 = %x\n", RCrt (regs, 0x58));
+	DPRINTK("CR59 = %x\n", RCrt (regs, 0x59));
+	DPRINTK("CR5A = %x\n", RCrt (regs, 0x5A));
+	DPRINTK("CR5D = %x\n", RCrt (regs, 0x5D));
+	DPRINTK("CR5E = %x\n", RCrt (regs, 0x5E));
+	DPRINTK("CR66 = %x\n", RCrt (regs, 0x66));
+	DPRINTK("CR67 = %x\n", RCrt (regs, 0x67));
+	DPRINTK("MISC = %x\n", rb_64 (regs, GREG_MISC_OUTPUT_R));
+	DPRINTK("SR01 = %x\n", RSeq (regs, 0x01));
+	DPRINTK("SR02 = %x\n", RSeq (regs, 0x02));
+	DPRINTK("SR03 = %x\n", RSeq (regs, 0x03));
+	DPRINTK("SR09 = %x\n", RSeq (regs, 0x09));
+	DPRINTK("SR10 = %x\n", RSeq (regs, 0x10));
+	DPRINTK("SR11 = %x\n", RSeq (regs, 0x11));
+	DPRINTK("SR12 = %x\n", RSeq (regs, 0x12));
+	DPRINTK("SR13 = %x\n", RSeq (regs, 0x13));
+	DPRINTK("SR15 = %x\n", RSeq (regs, 0x15));
+	DPRINTK("SUBSYS STAT = %x\n", readw (regs + ECR_SUBSYSTEM_STAT));
+	DPRINTK("GFX STAT = %x\n", readw (regs + ECR_GP_STAT));
 	
 	return;
 }
diff -urN /g/vanilla/v2.3.15/linux/drivers/video/cyberfb.h linux/drivers/video/cyberfb.h
--- /g/vanilla/v2.3.15/linux/drivers/video/cyberfb.h	Mon Aug  9 14:39:38 1999
+++ linux/drivers/video/cyberfb.h	Thu Aug 26 15:18:35 1999
@@ -129,8 +129,12 @@
 
 
 /* Write 16 Bit VGA register */
-#define vgaw16(ba, reg, val) \
-*((unsigned short *)  (((volatile unsigned char *)ba)+reg)) = val
+extern inline
+void vgaw16 (unsigned char *ba, unsigned short reg, unsigned short val)
+{
+	writew (val, ba + reg);
+}
+
 
 /*
  * Defines for the used register addresses (mw)
@@ -321,9 +325,15 @@
 #define CRT_ID_EXT_BIOS_FLAG_4	0x6C
 
 /* Enhanced Commands Registers: */
+#ifdef CONFIG_PCI
+#define ECR_SUBSYSTEM_STAT	0x8504 /* newmmio */
+#define ECR_SUBSYSTEM_CNTL	0x8504 /* newmmio */
+#define ECR_ADV_FUNC_CNTL	0x850C /* newmmio */
+#else
 #define ECR_SUBSYSTEM_STAT	0x42E8
 #define ECR_SUBSYSTEM_CNTL	0x42E8
 #define ECR_ADV_FUNC_CNTL	0x4AE8
+#endif
 #define ECR_CURRENT_Y_POS	0x82E8
 #define ECR_CURRENT_Y_POS2	0x82EA	/* Trio64 only */
 #define ECR_CURRENT_X_POS	0x86E8
@@ -403,14 +413,14 @@
      /* prototypes                        */
      /* --------------------------------- */
 
-inline unsigned char RAttr(volatile unsigned char * board, short idx);
-inline unsigned char RSeq(volatile unsigned char * board, short idx);
-inline unsigned char RCrt(volatile unsigned char * board, short idx);
-inline unsigned char RGfx(volatile unsigned char * board, short idx);
+inline unsigned char RAttr(unsigned char * board, short idx);
+inline unsigned char RSeq(unsigned char * board, short idx);
+inline unsigned char RCrt(unsigned char * board, short idx);
+inline unsigned char RGfx(unsigned char * board, short idx);
 inline void cv64_write_port(unsigned short bits,
 			    volatile unsigned char *board);
 inline void cvscreen(int toggle, volatile unsigned char *board);
-inline void gfx_on_off(int toggle, volatile unsigned char *board);
+inline void gfx_on_off(int toggle, unsigned char *board);
 #if 0
 unsigned short cv64_compute_clock(unsigned long freq);
 int cv_has_4mb(volatile unsigned char * fb);

--------------C66FF20F2AF84AD93378EE84--

