diff -u --recursive --new-file v2.4.1/linux/CREDITS linux/CREDITS
--- v2.4.1/linux/CREDITS	Sat Feb  3 19:51:21 2001
+++ linux/CREDITS	Sat Feb  3 11:32:55 2001
@@ -2270,6 +2270,13 @@
 S: D-68789 St.Leon-Rot
 S: Germany
 
+N: Thiago Berlitz Rondon
+E: maluco@mileniumnet.com.br
+D: Miscellaneous kernel hacker
+S: R. Anhanguera, 1487 - Ipiranga
+S: 79080-740 - Campo Grande - Mato Grosso do Sul
+S: Brazil
+
 N: Stephen Rothwell
 E: sfr@linuxcare.com.au
 W: http://linuxcare.com.au/sfr
diff -u --recursive --new-file v2.4.1/linux/Documentation/Changes linux/Documentation/Changes
--- v2.4.1/linux/Documentation/Changes	Sat Feb  3 19:51:21 2001
+++ linux/Documentation/Changes	Sat Feb  3 12:10:37 2001
@@ -52,7 +52,7 @@
 o  Gnu make               3.77                    # make --version
 o  binutils               2.9.1.0.25              # ld -v
 o  util-linux             2.10o                   # fdformat --version
-o  modutils               2.4.0                   # insmod -V
+o  modutils               2.4.2                   # insmod -V
 o  e2fsprogs              1.19                    # tune2fs --version
 o  pcmcia-cs              3.1.21                  # cardmgr -V
 o  PPP                    2.4.0                   # pppd --version
diff -u --recursive --new-file v2.4.1/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.4.1/linux/Documentation/Configure.help	Sat Feb  3 19:51:21 2001
+++ linux/Documentation/Configure.help	Sat Feb  3 12:48:00 2001
@@ -3104,7 +3104,7 @@
 
 nVidia Riva support (EXPERIMENTAL)
 CONFIG_FB_RIVA
-  This driver supports graphics boards with the nVidia Riva (aka TNTx)
+  This driver supports graphics boards with the nVidia Riva/Geforce
   chips.
   Say Y if you have such a graphics board.
 
@@ -5119,7 +5119,7 @@
 
 Compaq Smart Array support
 CONFIG_BLK_CPQ_CISS_DA
-   This is the driver for Compaq Smart Array controllers.
+   This is the driver for Compaq Smart Array 5xxx controllers.
    Everyone using these boards should say Y here.
    See Documentation/cciss.txt for the current list of
    boards supported by this driver, and for further information
diff -u --recursive --new-file v2.4.1/linux/Documentation/DocBook/Makefile linux/Documentation/DocBook/Makefile
--- v2.4.1/linux/Documentation/DocBook/Makefile	Sat Dec 30 18:16:13 2000
+++ linux/Documentation/DocBook/Makefile	Sat Feb  3 12:43:55 2001
@@ -81,6 +81,7 @@
 		$(TOPDIR)/fs/devfs/base.c \
 		$(TOPDIR)/kernel/pm.c \
 		$(TOPDIR)/kernel/ksyms.c \
+		$(TOPDIR)/kernel/kmod.c \
 		$(TOPDIR)/net/netsyms.c
  
 kernel-api.sgml: kernel-api.tmpl $(APISOURCES)
diff -u --recursive --new-file v2.4.1/linux/Documentation/cciss.txt linux/Documentation/cciss.txt
--- v2.4.1/linux/Documentation/cciss.txt	Fri Sep 22 17:11:37 2000
+++ linux/Documentation/cciss.txt	Sat Feb  3 12:13:19 2001
@@ -6,6 +6,8 @@
 This driver is known to work with the following cards:
 
 	* SA 5300
+	* SA 5i 
+	* SA 532
 
 If notes are not already created in the /dev/cciss directory
 
diff -u --recursive --new-file v2.4.1/linux/Makefile linux/Makefile
--- v2.4.1/linux/Makefile	Sat Feb  3 19:51:21 2001
+++ linux/Makefile	Sat Feb  3 19:52:09 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
-SUBLEVEL = 1
-EXTRAVERSION =
+SUBLEVEL = 2
+EXTRAVERSION =-pre1
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -u --recursive --new-file v2.4.1/linux/arch/i386/kernel/i387.c linux/arch/i386/kernel/i387.c
--- v2.4.1/linux/arch/i386/kernel/i387.c	Sat Feb  3 19:51:22 2001
+++ linux/arch/i386/kernel/i387.c	Sat Feb  3 12:09:34 2001
@@ -216,7 +216,7 @@
 void set_fpu_mxcsr( struct task_struct *tsk, unsigned short mxcsr )
 {
 	if ( cpu_has_xmm ) {
-		tsk->thread.i387.fxsave.mxcsr = mxcsr;
+		tsk->thread.i387.fxsave.mxcsr = (mxcsr & 0xffbf);
 	}
 }
 
@@ -354,6 +354,8 @@
 	if ( __copy_from_user( &tsk->thread.i387.fxsave, &buf->_fxsr_env[0],
 			       sizeof(struct i387_fxsave_struct) ) )
 		return 1;
+	/* mxcsr bit 6 and 31-16 must be zero for security reasons */
+	tsk->thread.i387.fxsave.mxcsr &= 0xffbf;
 	return convert_fxsr_from_user( &tsk->thread.i387.fxsave, buf );
 }
 
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/cmbatt.c linux/drivers/acpi/cmbatt.c
--- v2.4.1/linux/drivers/acpi/cmbatt.c	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/cmbatt.c	Sat Feb  3 12:07:21 2001
@@ -163,11 +163,13 @@
 	result->battery_capacity_granularity_1=objs[7].integer.value;
 	result->battery_capacity_granularity_2=objs[8].integer.value;
 
+#define Xstrncpy(a, b, c) if (b) strncpy(a,b,c); else strncpy(a, "unknown", c);
+
 	/* BUG: trailing NULL issue */
-	strncpy(result->model_number, objs[9].string.pointer, MAX_BATT_STRLEN-1);
-	strncpy(result->serial_number, objs[10].string.pointer, MAX_BATT_STRLEN-1);
-	strncpy(result->battery_type, objs[11].string.pointer, MAX_BATT_STRLEN-1);
-	strncpy(result->oem_info, objs[12].string.pointer, MAX_BATT_STRLEN-1);
+	Xstrncpy(result->model_number, objs[9].string.pointer, MAX_BATT_STRLEN-1);
+	Xstrncpy(result->serial_number, objs[10].string.pointer, MAX_BATT_STRLEN-1);
+	Xstrncpy(result->battery_type, objs[11].string.pointer, MAX_BATT_STRLEN-1);
+	Xstrncpy(result->oem_info, objs[12].string.pointer, MAX_BATT_STRLEN-1);
 	
 	kfree(buf.pointer);
 
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/interpreter/amfldio.c linux/drivers/acpi/interpreter/amfldio.c
--- v2.4.1/linux/drivers/acpi/interpreter/amfldio.c	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/interpreter/amfldio.c	Sat Feb  3 12:11:41 2001
@@ -415,7 +415,8 @@
 
 		/* Check if update rule needs to be applied (not if mask is all ones) */
 
-		if (((1 << bit_granularity) -1) & ~mask) {
+		/* The left shift drops the bits we want to ignore. */
+	  	if ((~mask << (sizeof(mask)*8 - bit_granularity)) != 0) {
 			/*
 			 * Read the current contents of the byte/word/dword containing
 			 * the field, and merge with the new field value.
diff -u --recursive --new-file v2.4.1/linux/drivers/block/Config.in linux/drivers/block/Config.in
--- v2.4.1/linux/drivers/block/Config.in	Fri Sep 22 17:11:37 2000
+++ linux/drivers/block/Config.in	Sat Feb  3 12:13:19 2001
@@ -34,7 +34,7 @@
    source drivers/block/paride/Config.in
 fi
 dep_tristate 'Compaq SMART2 support' CONFIG_BLK_CPQ_DA $CONFIG_PCI
-dep_tristate 'Compaq CISS Array support' CONFIG_BLK_CPQ_CISS_DA $CONFIG_PCI 
+dep_tristate 'Compaq Smart Array 5xxx support' CONFIG_BLK_CPQ_CISS_DA $CONFIG_PCI 
 dep_tristate 'Mylex DAC960/DAC1100 PCI RAID Controller support' CONFIG_BLK_DEV_DAC960 $CONFIG_PCI
 
 tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
diff -u --recursive --new-file v2.4.1/linux/drivers/block/cciss.c linux/drivers/block/cciss.c
--- v2.4.1/linux/drivers/block/cciss.c	Sat Feb  3 19:51:26 2001
+++ linux/drivers/block/cciss.c	Sat Feb  3 12:13:19 2001
@@ -44,8 +44,8 @@
 #include <linux/genhd.h>
 
 #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
-#define DRIVER_NAME "Compaq CISS Driver (v 2.4.0)"
-#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,4,0)
+#define DRIVER_NAME "Compaq CISS Driver (v 2.4.2)"
+#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,4,2)
 
 /* Embedded module documentation macros - see modules.h */
 MODULE_AUTHOR("Charles M. White III - Compaq Computer Corporation");
@@ -63,6 +63,8 @@
  */
 static struct board_type products[] = {
 	{ 0x40700E11, "Smart Array 5300",	&SA5_access },
+	{ 0x40800E11, "Smart Array 5i", &SA5B_access},
+	{ 0x40820E11, "Smart Array 532", &SA5B_access},
 };
 
 /* How long to wait (in millesconds) for board to go into simple mode */
@@ -76,23 +78,7 @@
 
 static struct proc_dir_entry *proc_cciss;
 
-static void do_cciss_request(int i);
-/*
- * This is a hack.  This driver eats a major number for each controller, and
- * sets blkdev[xxx].request_fn to each one of these so the real request
- * function knows what controller its working with.
- */
-#define DO_CCISS_REQUEST(x) { do_cciss_request(x); }
-
-static void do_cciss_request0(request_queue_t * q) DO_CCISS_REQUEST(0);
-static void do_cciss_request1(request_queue_t * q) DO_CCISS_REQUEST(1);
-static void do_cciss_request2(request_queue_t * q) DO_CCISS_REQUEST(2);
-static void do_cciss_request3(request_queue_t * q) DO_CCISS_REQUEST(3);
-static void do_cciss_request4(request_queue_t * q) DO_CCISS_REQUEST(4);
-static void do_cciss_request5(request_queue_t * q) DO_CCISS_REQUEST(5);
-static void do_cciss_request6(request_queue_t * q) DO_CCISS_REQUEST(6);
-static void do_cciss_request7(request_queue_t * q) DO_CCISS_REQUEST(7);
-
+static void do_cciss_request(request_queue_t *q);
 static int cciss_open(struct inode *inode, struct file *filep);
 static int cciss_release(struct inode *inode, struct file *filep);
 static int cciss_ioctl(struct inode *inode, struct file *filep, 
@@ -693,7 +679,7 @@
         spin_lock_irqsave(&io_request_lock, flags);
         if (hba[ctlr]->drv[target].usage_count > maxusage) {
                 spin_unlock_irqrestore(&io_request_lock, flags);
-                printk(KERN_WARNING "cpqarray: Device busy for "
+                printk(KERN_WARNING "cciss: Device busy for "
                         "revalidation (usage=%d)\n",
                         hba[ctlr]->drv[target].usage_count);
                 return -EBUSY;
@@ -1175,48 +1161,85 @@
 	}
 	complete_buffers(cmd->bh, status);
 }
+
+
+static inline int cpq_new_segment(request_queue_t *q, struct request *rq,
+                                  int max_segments)
+{
+        if (rq->nr_segments < MAXSGENTRIES) {
+                rq->nr_segments++;
+                return 1;
+        }
+        return 0;
+}
+
+static int cpq_back_merge_fn(request_queue_t *q, struct request *rq,
+                             struct buffer_head *bh, int max_segments)
+{
+        if (rq->bhtail->b_data + rq->bhtail->b_size == bh->b_data)
+                return 1;
+        return cpq_new_segment(q, rq, max_segments);
+}
+
+static int cpq_front_merge_fn(request_queue_t *q, struct request *rq,
+                             struct buffer_head *bh, int max_segments)
+{
+        if (bh->b_data + bh->b_size == rq->bh->b_data)
+                return 1;
+        return cpq_new_segment(q, rq, max_segments);
+}
+
+static int cpq_merge_requests_fn(request_queue_t *q, struct request *rq,
+                                 struct request *nxt, int max_segments)
+{
+        int total_segments = rq->nr_segments + nxt->nr_segments;
+
+        if (rq->bhtail->b_data + rq->bhtail->b_size == nxt->bh->b_data)
+                total_segments--;
+
+        if (total_segments > MAXSGENTRIES)
+                return 0;
+
+        rq->nr_segments = total_segments;
+        return 1;
+}
+
 /* 
  * Get a request and submit it to the controller. 
  * Currently we do one request at a time.  Ideally we would like to send
  * everything to the controller on the first call, but there is a danger
  * of holding the io_request_lock for to long.  
  */
-static void do_cciss_request(int ctlr)
+static void do_cciss_request(request_queue_t *q)
 {
-	ctlr_info_t *h= hba[ctlr];
+	ctlr_info_t *h= q->queuedata; 
 	CommandList_struct *c;
 	int log_unit, start_blk, seg, sect;
 	char *lastdataend;
 	struct buffer_head *bh;
-	struct list_head *queue_head;
+	struct list_head *queue_head = &q->queue_head;
 	struct request *creq;
 	u64bit temp64;
 
-	queue_head = &blk_dev[MAJOR_NR+ctlr].request_queue.queue_head;	
-	if (list_empty(queue_head))
-	{
-		/* nothing to do... */
-		start_io(h);
-		return;
-	}
+	if (q->plugged || list_empty(queue_head)) {
+                start_io(h);
+                return;
+        }
+
 	creq =	blkdev_entry_next_request(queue_head); 
-	if ((creq == NULL) || (creq->rq_status == RQ_INACTIVE))
-	{
-		/* nothing to do... restart processing and return */ 
-		start_io(h);
-		return;
-	}
-	if ((ctlr != (MAJOR(creq->rq_dev)-MAJOR_NR)) || (ctlr > nr_ctlr)
-		|| (h == NULL))
-	{
-#ifdef CCISS_DEBUG
-		printk(KERN_WARNING "cciss: doreq cmd of %d, %x at %p\n",
-			ctlr, creq->rq_dev, creq);
-#endif /* CCISS_DEBUG */
-		complete_buffers(creq->bh, 0);
-		start_io(h); 
-		return;
-	}
+	if (creq->nr_segments > MAXSGENTRIES)
+                BUG();
+
+        if ((h->ctlr != MAJOR(creq->rq_dev)-MAJOR_NR) || (h->ctlr > nr_ctlr))
+        {
+                printk(KERN_WARNING "doreq cmd for %d, %x at %p\n",
+                                h->ctlr, creq->rq_dev, creq);
+                blkdev_dequeue_request(creq);
+                complete_buffers(creq->bh, 0);
+                start_io(h);
+                return;
+        }
+
 	if (( c = cmd_alloc(h)) == NULL)
 	{
 		start_io(h);
@@ -1229,7 +1252,7 @@
 	log_unit = MINOR(creq->rq_dev) >> NWD_SHIFT; 
 	c->Header.ReplyQueue = 0;  // unused in simple mode
 	c->Header.Tag.lower = c->busaddr;  // use the physical address the cmd block for tag
-	c->Header.LUN.LogDev.VolId= hba[ctlr]->drv[log_unit].LunID;
+	c->Header.LUN.LogDev.VolId= hba[h->ctlr]->drv[log_unit].LunID;
 	c->Header.LUN.LogDev.Mode = 1;
 	c->Request.CDBLen = 10; // 12 byte commands not in FW yet;
 	c->Request.Type.Type =  TYPE_CMD; // It is a command. 
@@ -1238,10 +1261,10 @@
 		(creq->cmd == READ) ? XFER_READ: XFER_WRITE; 
 	c->Request.Timeout = 0; // Don't time out	
 	c->Request.CDB[0] = (creq->cmd == READ) ? CCISS_READ : CCISS_WRITE;
-	start_blk = hba[ctlr]->hd[MINOR(creq->rq_dev)].start_sect + creq->sector;
+	start_blk = hba[h->ctlr]->hd[MINOR(creq->rq_dev)].start_sect + creq->sector;
+#ifdef CCISS_DEBUG
 	if (bh == NULL)
 		panic("cciss: bh== NULL?");
-#ifdef CCISS_DEBUG
 	printk(KERN_DEBUG "ciss: sector =%d nr_sectors=%d\n",(int) creq->sector,
 		(int) creq->nr_sectors);	
 #endif /* CCISS_DEBUG */
@@ -1251,28 +1274,21 @@
 	while(bh)
 	{
 		sect += bh->b_size/512;
-		if (bh->b_size % 512)
-		{
-			printk(KERN_CRIT "cciss:  Oh Man.  %d+%d, size=%d\n", 
-				(int) creq->sector, sect, (int) bh->b_size);
-			panic("b_size 512 != 0\n");
-		}
 		if (bh->b_data == lastdataend)
 		{  // tack it on to the last segment 
 			c->SG[seg-1].Len +=bh->b_size;
 			lastdataend += bh->b_size;
 		} else
 		{
+			if (seg == MAXSGENTRIES)
+				BUG();
 			c->SG[seg].Len = bh->b_size;
 			temp64.val = (__u64) virt_to_bus(bh->b_data);
 			c->SG[seg].Addr.lower = temp64.val32.lower;
 			c->SG[seg].Addr.upper = temp64.val32.upper;
 			c->SG[0].Ext = 0;  // we are not chaining
 			lastdataend = bh->b_data + bh->b_size;
-			if( ++seg == MAXSGENTRIES)
-			{
-				break; 
-			}
+			seg++;
 		}
 		bh = bh->b_reqnext;
 	}
@@ -1280,10 +1296,6 @@
 	if( seg > h->maxSG)
 		h->maxSG = seg; 
 
-	/* adjusting the remaining request, if any */ 
-	creq-> sector+= sect;
-	creq->nr_sectors -= sect; 
-
 #ifdef CCISS_DEBUG
 	printk(KERN_DEBUG "cciss: Submitting %d sectors in %d segments\n", sect, seg);
 #endif /* CCISS_DEBUG */
@@ -1295,31 +1307,23 @@
 	c->Request.CDB[4]= (start_blk >>  8) & 0xff;
 	c->Request.CDB[5]= start_blk & 0xff;
 	c->Request.CDB[6]= 0; // (sect >> 24) & 0xff; MSB
-	// c->Request.CDB[7]= (sect >> 16) & 0xff; 
 	c->Request.CDB[7]= (sect >>  8) & 0xff; 
 	c->Request.CDB[8]= sect & 0xff; 
 	c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0;
 
-	/* check to see if we going to complete the entire request */ 
-	/* if so, mark this request as Done and ready the next one */ 
-	if (creq->nr_sectors)
-	{
-#ifdef CCISS_DEBUG
-		printk(KERN_DEBUG "cciss: More to do on the same request %p %ld\n", 
-			creq, creq->nr_sectors);
-#endif /* CCISS_DEBUG */
+			
+	blkdev_dequeue_request(creq);
 
-		creq->bh = bh->b_reqnext;
-		bh->b_reqnext = NULL;
-	} else
-	{
+	
+        /*
+         * ehh, we can't really end the request here since it's not
+         * even started yet. for now it shouldn't hurt though
+         */
 #ifdef CCISS_DEBUG
-		printk("cciss: Done with %p, queueing %p\n", creq);
-#endif /* CCISS_DEBUG */
-			
-		blkdev_dequeue_request(creq);
-		end_that_request_last(creq);
-	}
+	printk("Done with %p\n", creq);
+#endif /* CCISS_DEBUG */ 
+	end_that_request_last(creq);
+
 	addQ(&(h->reqQ),c);
 	h->Qdepth++;
 	if(h->Qdepth > h->maxQsinceinit)
@@ -1352,7 +1356,7 @@
 			a &= ~3;
 			if ((c = h->cmpQ) == NULL)
 			{  
-				printk(KERN_WARNING "cpqarray: Completion of %08lx ignored\n", (unsigned long)a1);
+				printk(KERN_WARNING "cciss: Completion of %08lx ignored\n", (unsigned long)a1);
 				continue;	
 			} 
 			while(c->busaddr != a) {
@@ -1379,7 +1383,7 @@
 	/*
 	 * See if we can queue up some more IO
 	 */
-	do_cciss_request(h->ctlr);
+	do_cciss_request(BLK_DEFAULT_QUEUE(MAJOR_NR + h->ctlr));
 	spin_unlock_irqrestore(&io_request_lock, flags);
 }
 /* 
@@ -1420,7 +1424,7 @@
 	printk("   Heartbeat Counter = 0x%x\n\n\n", 
 			readl(&(tb->HeartBeat)));
 }
-#endif /* CCISS_DEBUG */
+#endif /* CCISS_DEBUG */ 
 
 static int cciss_pci_init(ctlr_info_t *c, unchar bus, unchar device_fn)
 {
@@ -1430,7 +1434,9 @@
 	uint addr[6];
 	__u32 board_id;
 	struct pci_dev *pdev;
-
+	int cfg_offset;
+	int cfg_base_addr;
+	int cfg_base_addr_index;
 	int i;
 
 	pdev = pci_find_slot(bus, device_fn);
@@ -1473,15 +1479,38 @@
 	 * Memory base addr is first addr , the second points to the config
          *   table
 	 */
-	c->paddr = pci_resource_start(pdev, 0);
-	c->vaddr = remap_pci_mem(c->paddr, 128);
-	c->cfgtable = (CfgTable_struct *) remap_pci_mem(addr[1], 
-						sizeof(CfgTable_struct));
+
+	c->paddr = addr[0] & 0xfffffff0; /* remove the addressing mode bits */
+#ifdef CCISS_DEBUG
+	printk("address 0 = %x\n", c->paddr);
+#endif /* CCISS_DEBUG */ 
+	c->vaddr = remap_pci_mem(c->paddr, 200);
+
+	/* get the address index number */
+	cfg_base_addr = readl(c->vaddr + SA5_CTCFG_OFFSET);
+	/* I am not prepared to deal with a 64 bit address value */
+	cfg_base_addr &= 0xffff;
+#ifdef CCISS_DEBUG
+	printk("cfg base address = %x\n", cfg_base_addr);
+#endif /* CCISS_DEBUG */
+	cfg_base_addr_index = (cfg_base_addr  - PCI_BASE_ADDRESS_0)/4;
+#ifdef CCISS_DEBUG
+	printk("cfg base address index = %x\n", cfg_base_addr_index);
+#endif /* CCISS_DEBUG */
+
+	cfg_offset = readl(c->vaddr + SA5_CTMEM_OFFSET);
+#ifdef CCISS_DEBUG
+	printk("cfg offset = %x\n", cfg_offset);
+#endif /* CCISS_DEBUG */
+	c->cfgtable = (CfgTable_struct *) 
+		remap_pci_mem((addr[cfg_base_addr_index] & 0xfffffff0)
+				+ cfg_offset, sizeof(CfgTable_struct));
 	c->board_id = board_id;
 
 #ifdef CCISS_DEBUG
 	print_cfg_table(c->cfgtable); 
 #endif /* CCISS_DEBUG */
+
 	for(i=0; i<NR_PRODUCTS; i++) {
 		if (board_id == products[i].board_id) {
 			c->product_name = products[i].product_name;
@@ -1495,6 +1524,14 @@
 				(unsigned long)board_id);
 		return -1;
 	}
+	if (  (readb(&c->cfgtable->Signature[0]) != 'C') ||
+	      (readb(&c->cfgtable->Signature[1]) != 'I') ||
+	      (readb(&c->cfgtable->Signature[2]) != 'S') ||
+	      (readb(&c->cfgtable->Signature[3]) != 'S') )
+	{
+		printk("Does not appear to be a valid CISS config table\n");
+		return -1;
+	}
 #ifdef CCISS_DEBUG
 	printk("Trying to put board into Simple mode\n");
 #endif /* CCISS_DEBUG */ 
@@ -1536,14 +1573,22 @@
 
 	int index;
 	unchar bus=0, dev_fn=0;
-	
+
+	#define CCISS_BOARD_TYPES 2
+	static int cciss_device_id[CCISS_BOARD_TYPES] = { 
+		PCI_DEVICE_ID_COMPAQ_CISS, PCI_DEVICE_ID_COMPAQ_CISSB};
+	int brdtype;
+
+	/* search for all PCI board types that could be for this driver */
+	for(brdtype=0; brdtype<CCISS_BOARD_TYPES; brdtype++)
+	{
 		for(index=0; ; index++) {
 			if (pcibios_find_device(PCI_VENDOR_ID_COMPAQ,
-			 	PCI_DEVICE_ID_COMPAQ_CISS, 
+			 	cciss_device_id[brdtype], 
 					index, &bus, &dev_fn))
 				break;
 			printk(KERN_DEBUG "cciss: Device %x has been found at %x %x\n",
-				PCI_DEVICE_ID_COMPAQ_CISS, bus, dev_fn);
+				cciss_device_id[brdtype], bus, dev_fn);
 			if (index == 1000000) break;
 			if (nr_ctlr == 8) {
 				printk(KERN_WARNING "cciss: This driver"
@@ -1569,6 +1614,7 @@
 			nr_ctlr++;
 
 		}
+	}
 	return nr_ctlr;
 
 }
@@ -1698,8 +1744,8 @@
 			printk(KERN_WARNING "cciss: read capacity failed\n");
 			total_size = block_size = 0; 
 		}	
-		printk("      blocks= %d block_size= %d\n", total_size,
-					block_size);
+		printk(KERN_INFO "      blocks= %d block_size= %d\n", 
+					total_size, block_size);
 
 		/* Execute the command to read the disk geometry */
 		memset(inq_buff, 0, sizeof(InquiryData_struct));
@@ -1759,13 +1805,7 @@
 {
 	int num_cntlrs_reg = 0;
 	int i,j;
-
-	void (*request_fns[MAX_CTLR])(request_queue_t *) = {
-                do_cciss_request0, do_cciss_request1,
-                do_cciss_request2, do_cciss_request3,
-                do_cciss_request4, do_cciss_request5,
-                do_cciss_request6, do_cciss_request7,
-        };
+	request_queue_t *q;
 
 	/* detect controllers */
 	cciss_pci_detect();
@@ -1834,15 +1874,22 @@
 		hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON);
 
 		cciss_procinit(i);
-		
-		blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR+i),
-				request_fns[i]);
-		blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR+i), 0);
+
+		q = BLK_DEFAULT_QUEUE(MAJOR_NR + i);
+                q->queuedata = hba[i];
+                blk_init_queue(q, do_cciss_request);
+                blk_queue_headactive(q, 0);		
 
 		/* fill in the other Kernel structs */
 		blksize_size[MAJOR_NR+i] = hba[i]->blocksizes;
                 hardsect_size[MAJOR_NR+i] = hba[i]->hardsizes;
                 read_ahead[MAJOR_NR+i] = READ_AHEAD;
+
+		/* Set the pointers to queue functions */ 
+		q->back_merge_fn = cpq_back_merge_fn;
+                q->front_merge_fn = cpq_front_merge_fn;
+                q->merge_requests_fn = cpq_merge_requests_fn;
+
 
 		/* Fill in the gendisk data */ 	
 		hba[i]->gendisk.major = MAJOR_NR + i;
diff -u --recursive --new-file v2.4.1/linux/drivers/block/cciss.h linux/drivers/block/cciss.h
--- v2.4.1/linux/drivers/block/cciss.h	Mon Dec 11 12:50:40 2000
+++ linux/drivers/block/cciss.h	Sat Feb  3 12:13:19 2001
@@ -94,8 +94,13 @@
 #define SA5_REPLY_PORT_OFFSET		0x44
 #define SA5_INTR_STATUS		0x30
 
+#define SA5_CTCFG_OFFSET	0xB4
+#define SA5_CTMEM_OFFSET	0xB8
+
 #define SA5_INTR_OFF		0x08
+#define SA5B_INTR_OFF		0x04
 #define SA5_INTR_PENDING	0x08
+#define SA5B_INTR_PENDING	0x04
 #define FIFO_EMPTY		0xffffffff	
 
 #define  CISS_ERROR_BIT		0x02
@@ -133,6 +138,22 @@
 	}
 }
 /*
+ *  This card is the oposite of the other cards.
+ *   0 turns interrupts on...
+ *   0x04 turns them off...
+ */
+static void SA5B_intr_mask(ctlr_info_t *h, unsigned long val)
+{
+        if (val)
+        { /* Turn interrupts on */
+                writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
+        } else /* Turn them off */
+        {
+                writel( SA5B_INTR_OFF,
+                        h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
+        }
+}
+/*
  *  Returns true if fifo is full.  
  * 
  */ 
@@ -183,6 +204,21 @@
 	return 0 ;
 }
 
+/*
+ *      Returns true if an interrupt is pending..
+ */
+static unsigned long SA5B_intr_pending(ctlr_info_t *h)
+{
+        unsigned long register_value  =
+                readl(h->vaddr + SA5_INTR_STATUS);
+#ifdef CCISS_DEBUG
+        printk("cciss: intr_pending %lx\n", register_value);
+#endif  /* CCISS_DEBUG */
+        if( register_value &  SA5B_INTR_PENDING)
+                return  1;
+        return 0 ;
+}
+
 
 static struct access_method SA5_access = {
 	SA5_submit_command,
@@ -190,6 +226,14 @@
 	SA5_fifo_full,
 	SA5_intr_pending,
 	SA5_completed,
+};
+
+static struct access_method SA5B_access = {
+        SA5_submit_command,
+        SA5B_intr_mask,
+        SA5_fifo_full,
+        SA5B_intr_pending,
+        SA5_completed,
 };
 
 struct board_type {
diff -u --recursive --new-file v2.4.1/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v2.4.1/linux/drivers/char/serial.c	Wed Dec  6 12:06:18 2000
+++ linux/drivers/char/serial.c	Sat Feb  3 12:44:43 2001
@@ -54,6 +54,9 @@
  *  7/00: fix some returns on failure not using MOD_DEC_USE_COUNT.
  *	  Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  *
+ * 10/00: add in optional hardware flow control for serial console.
+ *	  Kanoj Sarcar <kanoj@sgi.com>
+ *
  * This module exports the following rs232 io functions:
  *
  *	int rs_init(void);
@@ -5252,6 +5255,36 @@
 }
 
 /*
+ * This is for use by architectures that know their serial port
+ * attributes only at run time. Not to be invoked after rs_init().
+ */
+int __init early_serial_setup(struct serial_struct *req)
+{
+	int i = req->line;
+
+	if (i >= NR_IRQS)
+		return(-ENOENT);
+	rs_table[i].magic = 0;
+	rs_table[i].baud_base = req->baud_base;
+	rs_table[i].port = req->port;
+	if (HIGH_BITS_OFFSET)
+		rs_table[i].port += (unsigned long) req->port_high << 
+							HIGH_BITS_OFFSET;
+	rs_table[i].irq = req->irq;
+	rs_table[i].flags = req->flags;
+	rs_table[i].close_delay = req->close_delay;
+	rs_table[i].io_type = req->io_type;
+	rs_table[i].hub6 = req->hub6;
+	rs_table[i].iomem_base = req->iomem_base;
+	rs_table[i].iomem_reg_shift = req->iomem_reg_shift;
+	rs_table[i].type = req->type;
+	rs_table[i].xmit_fifo_size = req->xmit_fifo_size;
+	rs_table[i].custom_divisor = req->custom_divisor;
+	rs_table[i].closing_wait = req->closing_wait;
+	return(0);
+}
+
+/*
  * register_serial and unregister_serial allows for 16x50 serial ports to be
  * configured at run-time, to support PCMCIA modems.
  */
@@ -5461,6 +5494,10 @@
 		if (--tmout == 0)
 			break;
 	} while((status & BOTH_EMPTY) != BOTH_EMPTY);
+	if (info->flags & ASYNC_NO_FLOW)
+		return;
+	tmout = 1000000;
+	while (--tmout && ((serial_in(info, UART_MSR) & UART_MSR_CTS) == 0));
 }
 
 
@@ -5543,7 +5580,7 @@
 }
 
 /*
- *	Setup initial baud/bits/parity. We do two things here:
+ *	Setup initial baud/bits/parity/flow. We do two things here:
  *	- construct a cflag setting for the first rs_open()
  *	- initialize the serial port
  *	Return non-zero if we didn't find a serial port.
@@ -5556,6 +5593,7 @@
 	int	baud = 9600;
 	int	bits = 8;
 	int	parity = 'n';
+	int	doflow = 0;
 	int	cflag = CREAD | HUPCL | CLOCAL;
 	int	quot = 0;
 	char	*s;
@@ -5566,7 +5604,9 @@
 		while(*s >= '0' && *s <= '9')
 			s++;
 		if (*s) parity = *s++;
-		if (*s) bits   = *s - '0';
+		if (*s) bits   = *s++ - '0';
+		if ((*s) && (!strcmp(s, "rtscts")))
+			doflow = 1;
 	}
 
 	/*
@@ -5622,6 +5662,8 @@
 	 *	Divisor, bytesize and parity
 	 */
 	state = rs_table + co->index;
+	if (doflow == 0)
+		state->flags |= ASYNC_NO_FLOW;
 	info = &async_sercons;
 	info->magic = SERIAL_MAGIC;
 	info->state = state;
diff -u --recursive --new-file v2.4.1/linux/drivers/ide/ide-cd.c linux/drivers/ide/ide-cd.c
--- v2.4.1/linux/drivers/ide/ide-cd.c	Sat Feb  3 19:51:27 2001
+++ linux/drivers/ide/ide-cd.c	Sat Feb  3 12:35:32 2001
@@ -1872,6 +1872,9 @@
 	   If it is, just return. */
 	(void) cdrom_check_status(drive, sense);
 
+	if (CDROM_STATE_FLAGS(drive)->toc_valid)
+		return 0;
+
 	/* First read just the header, so we know how long the TOC is. */
 	stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr,
 				    sizeof(struct atapi_toc_header), sense);
diff -u --recursive --new-file v2.4.1/linux/drivers/ide/ide-timing.h linux/drivers/ide/ide-timing.h
--- v2.4.1/linux/drivers/ide/ide-timing.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ide/ide-timing.h	Sat Feb  3 11:27:43 2001
@@ -0,0 +1,279 @@
+#ifndef _IDE_TIMING_H
+#define _IDE_TIMING_H
+
+/*
+ * $Id: ide-timing.h,v 1.5 2001/01/15 21:48:56 vojtech Exp $
+ *
+ *  Copyright (c) 1999-2000 Vojtech Pavlik
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/hdreg.h>
+
+#ifndef XFER_PIO_5
+#define XFER_PIO_5		0x0d
+#define XFER_UDMA_SLOW		0x4f
+#endif
+
+struct ide_timing {
+	short mode;
+	short setup;	/* t1 */
+	short act8b;	/* t2 for 8-bit io */
+	short rec8b;	/* t2i for 8-bit io */
+	short cyc8b;	/* t0 for 8-bit io */
+	short active;	/* t2 or tD */
+	short recover;	/* t2i or tK */
+	short cycle;	/* t0 */
+	short udma;	/* t2CYCTYP/2 */
+};
+
+/*
+ * PIO 0-5, MWDMA 0-2 and UDMA 0-5 timings (in nanoseconds).
+ * These were taken from ATA/ATAPI-6 standard, rev 0a, except
+ * for PIO 5, which is a nonstandard extension.
+ */
+
+static struct ide_timing ide_timing[] = {
+
+	{ XFER_UDMA_5,     0,   0,   0,   0,   0,   0,   0,  20 },
+	{ XFER_UDMA_4,     0,   0,   0,   0,   0,   0,   0,  30 },
+	{ XFER_UDMA_3,     0,   0,   0,   0,   0,   0,   0,  45 },
+
+	{ XFER_UDMA_2,     0,   0,   0,   0,   0,   0,   0,  60 },
+	{ XFER_UDMA_1,     0,   0,   0,   0,   0,   0,   0,  80 },
+	{ XFER_UDMA_0,     0,   0,   0,   0,   0,   0,   0, 120 },
+
+	{ XFER_UDMA_SLOW,  0,   0,   0,   0,   0,   0,   0, 150 },
+                                          
+	{ XFER_MW_DMA_2,  25,   0,   0,   0,  70,  25, 120,   0 },
+	{ XFER_MW_DMA_1,  45,   0,   0,   0,  80,  50, 150,   0 },
+	{ XFER_MW_DMA_0,  60,   0,   0,   0, 215, 215, 480,   0 },
+                                          
+	{ XFER_SW_DMA_2,  60,   0,   0,   0, 120, 120, 240,   0 },
+	{ XFER_SW_DMA_1,  90,   0,   0,   0, 240, 240, 480,   0 },
+	{ XFER_SW_DMA_0, 120,   0,   0,   0, 480, 480, 960,   0 },
+
+	{ XFER_PIO_5,     20,  50,  30, 100,  50,  30, 100,   0 },
+	{ XFER_PIO_4,     25,  70,  25, 120,  70,  25, 120,   0 },
+	{ XFER_PIO_3,     30,  80,  70, 180,  80,  70, 180,   0 },
+
+	{ XFER_PIO_2,     30, 290,  40, 330, 100,  90, 240,   0 },
+	{ XFER_PIO_1,     50, 290,  93, 383, 125, 100, 383,   0 },
+	{ XFER_PIO_0,     70, 290, 240, 600, 165, 150, 600,   0 },
+
+	{ XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 960,   0 },
+
+	{ -1 }
+};
+
+#define IDE_TIMING_SETUP	0x01
+#define IDE_TIMING_ACT8B	0x02
+#define IDE_TIMING_REC8B	0x04
+#define IDE_TIMING_CYC8B	0x08
+#define IDE_TIMING_8BIT		0x0e
+#define IDE_TIMING_ACTIVE	0x10
+#define IDE_TIMING_RECOVER	0x20
+#define IDE_TIMING_CYCLE	0x40
+#define IDE_TIMING_UDMA		0x80
+#define IDE_TIMING_ALL		0xff
+
+#define MIN(a,b)	((a)<(b)?(a):(b))
+#define MAX(a,b)	((a)>(b)?(a):(b))
+#define FIT(v,min,max)	MAX(MIN(v,max),min)
+#define ENOUGH(v,unit)	(((v)-1)/(unit)+1)
+#define EZ(v,unit)	((v)?ENOUGH(v,unit):0)
+
+#define XFER_MODE	0xf0
+#define XFER_UDMA_100	0x44
+#define XFER_UDMA_66	0x42
+#define XFER_UDMA	0x40
+#define XFER_MWDMA	0x20
+#define XFER_SWDMA	0x10
+#define XFER_EPIO	0x01
+#define XFER_PIO	0x00
+
+static short ide_find_best_mode(ide_drive_t *drive, int map)
+{
+	struct hd_driveid *id = drive->id;
+	short best = 0;
+
+	if (!id)
+		return XFER_PIO_SLOW;
+
+	if ((map & XFER_UDMA) && (id->field_valid & 4)) {	/* Want UDMA and UDMA bitmap valid */
+
+		if ((map & XFER_UDMA_100) == XFER_UDMA_100)
+			if ((best = (id->dma_ultra & 0x0020) ? XFER_UDMA_5 : 0)) return best;
+
+		if ((map & XFER_UDMA_66) == XFER_UDMA_66)
+			if ((best = (id->dma_ultra & 0x0010) ? XFER_UDMA_4 :
+                	    	    (id->dma_ultra & 0x0008) ? XFER_UDMA_3 : 0)) return best;
+
+                if ((best = (id->dma_ultra & 0x0004) ? XFER_UDMA_2 :
+                	    (id->dma_ultra & 0x0002) ? XFER_UDMA_1 :
+                	    (id->dma_ultra & 0x0001) ? XFER_UDMA_0 : 0)) return best;
+	}
+
+	if ((map & XFER_MWDMA) && (id->field_valid & 2)) {	/* Want MWDMA and drive has EIDE fields */
+
+		if ((best = (id->dma_mword & 0x0004) ? XFER_MW_DMA_2 :
+                	    (id->dma_mword & 0x0002) ? XFER_MW_DMA_1 :
+                	    (id->dma_mword & 0x0001) ? XFER_MW_DMA_0 : 0)) return best;
+	}
+
+	if (map & XFER_SWDMA) {					/* Want SWDMA */
+
+ 		if (id->field_valid & 2) {			/* EIDE SWDMA */
+
+			if ((best = (id->dma_1word & 0x0004) ? XFER_SW_DMA_2 :
+      				    (id->dma_1word & 0x0002) ? XFER_SW_DMA_1 :
+				    (id->dma_1word & 0x0001) ? XFER_SW_DMA_0 : 0)) return best;
+		}
+
+		if (id->capability & 1) {			/* Pre-EIDE style SWDMA */
+
+			if ((best = (id->tDMA == 2) ? XFER_SW_DMA_2 :
+				    (id->tDMA == 1) ? XFER_SW_DMA_1 :
+				    (id->tDMA == 0) ? XFER_SW_DMA_0 : 0)) return best;
+		}
+	}
+
+
+	if ((map & XFER_EPIO) && (id->field_valid & 2)) {	/* EIDE PIO modes */
+
+		if ((best = (drive->id->eide_pio_modes & 4) ? XFER_PIO_5 :
+			    (drive->id->eide_pio_modes & 2) ? XFER_PIO_4 :
+			    (drive->id->eide_pio_modes & 1) ? XFER_PIO_3 : 0)) return best;
+	}
+	
+	return  (drive->id->tPIO == 2) ? XFER_PIO_2 :
+		(drive->id->tPIO == 1) ? XFER_PIO_1 :
+		(drive->id->tPIO == 0) ? XFER_PIO_0 : XFER_PIO_SLOW;
+}
+
+static void ide_timing_quantize(struct ide_timing *t, struct ide_timing *q, int T, int UT)
+{
+	q->setup   = EZ(t->setup,   T);
+	q->act8b   = EZ(t->act8b,   T);
+	q->rec8b   = EZ(t->rec8b,   T);
+	q->cyc8b   = EZ(t->cyc8b,   T);
+	q->active  = EZ(t->active,  T);
+	q->recover = EZ(t->recover, T);
+	q->cycle   = EZ(t->cycle,   T);
+	q->udma    = EZ(t->udma,   UT);
+}
+
+static void ide_timing_merge(struct ide_timing *a, struct ide_timing *b, struct ide_timing *m, unsigned int what)
+{
+	if (what & IDE_TIMING_SETUP  ) m->setup   = MAX(a->setup,   b->setup);
+	if (what & IDE_TIMING_ACT8B  ) m->act8b   = MAX(a->act8b,   b->act8b);
+	if (what & IDE_TIMING_REC8B  ) m->rec8b   = MAX(a->rec8b,   b->rec8b);
+	if (what & IDE_TIMING_CYC8B  ) m->cyc8b   = MAX(a->cyc8b,   b->cyc8b);
+	if (what & IDE_TIMING_ACTIVE ) m->active  = MAX(a->active,  b->active);
+	if (what & IDE_TIMING_RECOVER) m->recover = MAX(a->recover, b->recover);
+	if (what & IDE_TIMING_CYCLE  ) m->cycle   = MAX(a->cycle,   b->cycle);
+	if (what & IDE_TIMING_UDMA   ) m->udma    = MAX(a->udma,    b->udma);
+}
+
+static struct ide_timing* ide_timing_find_mode(short speed)
+{
+	struct ide_timing *t;
+
+	for (t = ide_timing; t->mode != speed; t++)
+		if (t->mode < 0)
+			return NULL;
+	return t; 
+}
+
+static int ide_timing_compute(ide_drive_t *drive, short speed, struct ide_timing *t, int T, int UT)
+{
+	struct hd_driveid *id = drive->id;
+	struct ide_timing *s, p;
+
+/*
+ * Find the mode.
+ */
+
+	if (!(s = ide_timing_find_mode(speed)))
+		return -EINVAL;
+
+/*
+ * If the drive is an EIDE drive, it can tell us it needs extended
+ * PIO/MWDMA cycle timing.
+ */
+
+	if (id && id->field_valid & 2) {	/* EIDE drive */
+
+		memset(&p, 0, sizeof(p));
+
+		switch (speed & XFER_MODE) {
+
+			case XFER_PIO:
+				if (speed <= XFER_PIO_2) p.cycle = p.cyc8b = id->eide_pio;
+						    else p.cycle = p.cyc8b = id->eide_pio_iordy;
+				break;
+
+			case XFER_MWDMA:
+				p.cycle = id->eide_dma_min;
+				break;
+		}
+
+		ide_timing_merge(&p, t, t, IDE_TIMING_CYCLE | IDE_TIMING_CYC8B);
+	}
+
+/*
+ * Convert the timing to bus clock counts.
+ */
+
+	ide_timing_quantize(s, t, T, UT);
+
+/*
+ * Even in DMA/UDMA modes we still use PIO access for IDENTIFY, S.M.A.R.T
+ * and some other commands. We have to ensure that the DMA cycle timing is
+ * slower/equal than the fastest PIO timing.
+ */
+
+	if ((speed & XFER_MODE) != XFER_PIO) {
+		ide_timing_compute(drive, ide_find_best_mode(drive, XFER_PIO | XFER_EPIO), &p, T, UT);
+		ide_timing_merge(&p, t, t, IDE_TIMING_ALL);
+	}
+
+/*
+ * Lenghten active & recovery time so that cycle time is correct.
+ */
+
+	if (t->act8b + t->rec8b < t->cyc8b) {
+		t->act8b += (t->cyc8b - (t->act8b + t->rec8b)) / 2;
+		t->rec8b = t->cyc8b - t->act8b;
+	}
+
+	if (t->active + t->recover < t->cycle) {
+		t->active += (t->cycle - (t->active + t->recover)) / 2;
+		t->recover = t->cycle - t->active;
+	}
+
+	return 0;
+}
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/drivers/ide/via82cxxx.c linux/drivers/ide/via82cxxx.c
--- v2.4.1/linux/drivers/ide/via82cxxx.c	Sat Feb  3 19:51:27 2001
+++ linux/drivers/ide/via82cxxx.c	Sat Feb  3 11:27:43 2001
@@ -1,7 +1,7 @@
 /*
- * $Id: via82cxxx.c,v 2.1e 2000/10/03 10:01:00 vojtech Exp $
+ * $Id: via82cxxx.c,v 3.20 2001/01/27 10:13:60 vojtech Exp $
  *
- *  Copyright (c) 2000 Vojtech Pavlik
+ *  Copyright (c) 2000-2001 Vojtech Pavlik
  *
  *  Based on the work of:
  *	Michel Aubry
@@ -12,23 +12,34 @@
  */
 
 /*
- * VIA vt82c586 IDE driver for Linux. Supports
+ * VIA IDE driver for Linux. Supports
  *
- *   vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b, vt82c686a, vt8231
+ *   vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b,
+ *   vt82c686, vt82c686a, vt82c686b, vt8231, vt8233
  *
  * southbridges, which can be found in
  *
- *  VIA Apollo VP, VPX, VPX/97, VP2, VP2/97, VP3, MVP3, MVP4
- *  VIA Apollo Pro, Pro Plus, Pro 133, Pro 133A, ProMedia 601, ProSavage 605
- *  VIA Apollo KX133, KT133
- *  AMD-640, AMD-750 IronGate
- *
- * chipsets. Supports PIO 0-5, MWDMA 0-2, SWDMA 0-2 and
- * UDMA 0-5 (includes UDMA33, 66 and 100) modes. UDMA100 isn't possible
- * on any of the supported chipsets yet.
- *
- * UDMA66 and higher modes are autodetected only in case the BIOS has enabled them.
- * To force UDMA66, use 'ide0=ata66' or 'ide1=ata66' on the kernel command line.
+ *  VIA Apollo VP, VPX, VPX/97, VP2, VP2/97, VP3, MVP3, MVP4, P6, Pro,
+ *  Pro Plus, Pro 133, Pro 133A, ProMedia PM601, ProSavage PM133, PLE133,
+ *  Pro 266, KX133, KT133, ProSavage KM133, KT133A, KT266
+ *  PC-Chips VXPro, VXPro+, TXPro-III, TXPro-AGP, ViaGra, BXToo, BXTel
+ *  AMD 640, 640 AGP, 750 IronGate
+ *  ETEQ 6618, 6628, 6638
+ *  Micron Samurai
+ *
+ * chipsets. Supports
+ *
+ *   PIO 0-5, MWDMA 0-2, SWDMA 0-2 and UDMA 0-5
+ *
+ * (this includes UDMA33, 66 and 100) modes. UDMA66 and higher modes are
+ * autodetected only in case the BIOS has detected a 80 wire cable. To ignore
+ * the BIOS data, use 'ide0=ata66' or 'ide1=ata66' on the kernel command line.
+ *
+ * For correct operation it's needed to tell the driver the speed of the PCI
+ * bus. The default, and most common value is 33 MHz. Most likely, your system
+ * is using this value and you don't need to use any command line options. If
+ * you run your PCI bus speed at 25, 30, 37, 40 or 42 MHz, use the 'idebus=xx'
+ * option of the IDE driver. Note that this has nothing to do with UDMA66.
  */
 
 /*
@@ -52,23 +63,16 @@
  */
 
 #include <linux/config.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
 #include <linux/ioport.h>
-#include <linux/interrupt.h>
 #include <linux/blkdev.h>
-#include <linux/hdreg.h>
 #include <linux/pci.h>
 #include <linux/init.h>
-#include <linux/delay.h>
 #include <linux/ide.h>
 #include <asm/io.h>
 
-#include "ide_modes.h"
+#include "ide-timing.h"
 
-#define VIA_BM_BASE		0x20
 #define VIA_IDE_ENABLE		0x40
 #define VIA_IDE_CONFIG		0x41
 #define VIA_FIFO_CONFIG		0x43
@@ -76,90 +80,49 @@
 #define VIA_MISC_2		0x45
 #define VIA_MISC_3		0x46
 #define VIA_DRIVE_TIMING	0x48
+#define VIA_8BIT_TIMING		0x4e
 #define VIA_ADDRESS_SETUP	0x4c
 #define VIA_UDMA_TIMING		0x50
-#define VIA_PRI_SECTOR_SIZE	0x60
-#define VIA_SEC_SECTOR_SIZE	0x68
+
+#define VIA_UDMA		0x07
+#define VIA_UDMA_NONE		0x00
+#define VIA_UDMA_33		0x01
+#define VIA_UDMA_66		0x02
+#define VIA_UDMA_100		0x03
+#define VIA_BAD_PREQ		0x10
+#define VIA_BAD_CLK66		0x20
+#define VIA_SET_FIFO		0x40
+#define VIA_SET_THRESH		0x80
 
 /*
  * VIA SouthBridge chips.
  */
 
-static const struct {
+static struct via_isa_bridge {
 	char *name;
 	unsigned short id;
-	unsigned char speed;
+	unsigned char rev_min;
+	unsigned char rev_max;
+	unsigned char flags;
 } via_isa_bridges[] = {
-	{ "vt8231",	PCI_DEVICE_ID_VIA_8231,     XFER_UDMA_4 },
-	{ "vt82c686a",	PCI_DEVICE_ID_VIA_82C686,   XFER_UDMA_4 },
-	{ "vt82c596b",	PCI_DEVICE_ID_VIA_82C596,   XFER_UDMA_4 },
-	{ "vt82c596a",	PCI_DEVICE_ID_VIA_82C596,   XFER_UDMA_2 },
-	{ "vt82c586b",	PCI_DEVICE_ID_VIA_82C586_0, XFER_UDMA_2 },
-	{ "vt82c586a",	PCI_DEVICE_ID_VIA_82C586_0, XFER_UDMA_2 },
-	{ "vt82c586",	PCI_DEVICE_ID_VIA_82C586_0, XFER_MW_DMA_2 },
-	{ "Unknown SouthBridge",	0,	    XFER_UDMA_2 },
+	{ "vt8233",	PCI_DEVICE_ID_VIA_8233_0,   0x00, 0x2f, VIA_UDMA_100 },
+	{ "vt8231",	PCI_DEVICE_ID_VIA_8231,     0x00, 0x2f, VIA_UDMA_66 },
+	{ "vt82c686b",	PCI_DEVICE_ID_VIA_82C686,   0x40, 0x4f, VIA_UDMA_100 },
+	{ "vt82c686a",	PCI_DEVICE_ID_VIA_82C686,   0x10, 0x2f, VIA_UDMA_66 },
+	{ "vt82c686",	PCI_DEVICE_ID_VIA_82C686,   0x00, 0x0f, VIA_UDMA_66 },
+	{ "vt82c596b",	PCI_DEVICE_ID_VIA_82C596,   0x10, 0x2f, VIA_UDMA_66 },
+	{ "vt82c596a",	PCI_DEVICE_ID_VIA_82C596,   0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 },
+	{ "vt82c586b",	PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x4f, VIA_UDMA_33 | VIA_SET_FIFO | VIA_BAD_PREQ },
+	{ "vt82c586b",	PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, VIA_UDMA_33 | VIA_SET_FIFO },
+	{ "vt82c586a",	PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, VIA_UDMA_33 | VIA_SET_FIFO },
+	{ "vt82c586",	PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, VIA_UDMA_NONE | VIA_SET_FIFO },
+	{ NULL }
 };
 
-static unsigned char via_config;
+static struct via_isa_bridge *via_config;
 static unsigned char via_enabled;
-static unsigned int via_ata66;
-
-/*
- * PIO 0-5, MWDMA 0-2 and UDMA 0-5 timings (in nanoseconds).
- * These were taken from ATA/ATAPI-6 standard, rev 0a, except
- * for PIO 5, which is a nonstandard extension.
- *
- * Dilemma: 8-bit (register) PIO accesses need more relaxed timing.
- * Hopefully the chipset is taking care of that. If it doesn't
- * do so, define VIA_USE_8_BIT_TIMING to see if it helps.
- */
-
-#ifndef XFER_PIO_5
-#define XFER_PIO_5		0x0d
-#endif
-
-static const struct {
-	int mode;
-	char *name;
-	short setup;	/* t1 */
-	short active;	/* t2  or tD */
-	short recover;	/* t2i or tK */
-	short cycle;	/* t0 */
-	short udma;	/* t2CYCTYP/2 */
-} via_timing[] = {
-	{ XFER_UDMA_5,    "UDMA5", 25,  70,  25, 120,  20 },
-	{ XFER_UDMA_4,    "UDMA4", 25,  70,  25, 120,  30 },
-	{ XFER_UDMA_3,    "UDMA3", 25,  70,  25, 120,  45 },
-
-	{ XFER_UDMA_2,    "UDMA2", 25,  70,  25, 120,  60 },
-	{ XFER_UDMA_1,    "UDMA1", 25,  70,  25, 120,  80 },
-	{ XFER_UDMA_0,    "UDMA0", 25,  70,  25, 120, 120 },
-
-	{ XFER_MW_DMA_2,  "MDMA2", 25,  70,  25, 120,   0 },
-	{ XFER_MW_DMA_1,  "MDMA1", 45,  80,  50, 150,   0 },
-	{ XFER_MW_DMA_0,  "MDMA0", 60, 215, 215, 480,   0 },
-
-	{ XFER_SW_DMA_2,  "SDMA2", 60, 120, 120, 240,   0 },
-	{ XFER_SW_DMA_1,  "SDMA1", 90, 240, 240, 480,   0 },
-	{ XFER_SW_DMA_0,  "SDMA0",120, 480, 480, 960,   0 },
-
-	{ XFER_PIO_5,     "PIO5",  20,  50,  30, 100,   0 },
-	{ XFER_PIO_4,     "PIO4",  25,  70,  25, 120,   0 },
-	{ XFER_PIO_3,     "PIO3",  30,  80,  70, 180,   0 },
-
-#ifdef VIA_USE_8_BIT_TIMING
-	{ XFER_PIO_2,     "PIO2",  30, 290,  60, 330,   0 },
-	{ XFER_PIO_1,     "PIO1",  50, 290, 100, 383,   0 },
-	{ XFER_PIO_0,     "PIO0",  70, 290, 300, 600,   0 },
-#else
-	{ XFER_PIO_2,     "PIO2",  30, 100,  90, 240,   0 },
-	{ XFER_PIO_1,     "PIO1",  50, 125, 100, 383,   0 },
-	{ XFER_PIO_0,     "PIO0",  70, 165, 150, 600,   0 },
-#endif
-
-	{ XFER_PIO_SLOW,  "SLOW", 120, 290, 240, 960,   0 },
-	{ 0 }
-};
+static unsigned int via_80w;
+static unsigned int via_clock;
 
 /*
  * VIA /proc entry.
@@ -170,11 +133,10 @@
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
 
-int via_proc = 0;
+int via_proc, via_base;
 static struct pci_dev *bmide_dev, *isa_dev;
 extern int (*via_display_info)(char *, char **, off_t, int); /* ide-proc.c */
 
-static char *via_fifo[] = { " 1 ", "3/4", "1/2", "1/4" };
 static char *via_control3[] = { "No limit", "64", "128", "192" };
 
 #define via_print(format, arg...) p += sprintf(p, format "\n" , ## arg)
@@ -183,89 +145,89 @@
 
 static int via_get_info(char *buffer, char **addr, off_t offset, int count)
 {
-	short pci_clock, speed[4], cycle[4], setup[4], active[4], recover[4], umul[4], uen[4], udma[4];
+	short speed[4], cycle[4], setup[4], active[4],
+		recover[4], uen[4], udma[4], active8b[4], recover8b[4];
 	struct pci_dev *dev = bmide_dev;
-	unsigned int v, u, i, base;
-	unsigned short c, size0, size1;
-	unsigned char t, c0, c1;
+	unsigned int v, u, i;
+	unsigned short c, w;
+	unsigned char t, x;
 	char *p = buffer;
 
 	via_print("----------VIA BusMastering IDE Configuration----------------");
 
-	via_print("Driver Version:                     2.1e");
+	via_print("Driver Version:                     3.20");
+	via_print("South Bridge:                       VIA %s", via_config->name);
 
 	pci_read_config_byte(isa_dev, PCI_REVISION_ID, &t);
-	via_print("South Bridge:                       VIA %s rev %#x", via_isa_bridges[via_config].name, t);
-
-	pci_read_config_word(dev, PCI_COMMAND, &c);
-	via_print("Command register:                   %#x", c);
-
-	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &t);
-	via_print("Latency timer:                      %d", t);
+	pci_read_config_byte(dev, PCI_REVISION_ID, &x);
+	via_print("Revision:                           ISA %#x IDE %#x", t, x);
 
-	pci_clock = system_bus_clock();
-	via_print("PCI clock:                          %dMHz", pci_clock);
+	via_print("BM-DMA base:                        %#x", via_base);
+	via_print("PCI clock:                          %dMHz", via_clock);
 
 	pci_read_config_byte(dev, VIA_MISC_1, &t);
-	via_print("Master Read  Cycle IRDY:            %dws", (t & 64) >>6 );
-	via_print("Master Write Cycle IRDY:            %dws", (t & 32) >> 5 );
-	via_print("FIFO Output Data 1/2 Clock Advance: %s", (t & 16) ? "on" : "off" );
-	via_print("BM IDE Status Register Read Retry:  %s", (t & 8) ? "on" : "off" );
+	via_print("Master Read  Cycle IRDY:            %dws", (t & 64) >> 6);
+	via_print("Master Write Cycle IRDY:            %dws", (t & 32) >> 5);
+	via_print("BM IDE Status Register Read Retry:  %s", (t & 8) ? "yes" : "no");
 
 	pci_read_config_byte(dev, VIA_MISC_3, &t);
-	via_print("Max DRDY Pulse Width:               %s%s", via_control3[(t & 0x03)], (t & 0x03) ? "PCI clocks" : "");
+	via_print("Max DRDY Pulse Width:               %s%s", via_control3[(t & 0x03)], (t & 0x03) ? " PCI clocks" : "");
 
 	via_print("-----------------------Primary IDE-------Secondary IDE------");
-	via_print("Read DMA FIFO flush:   %10s%20s", (t & 0x80) ? "on" : "off", (t & 0x40) ? "on" : "off" );
-	via_print("End Sect. FIFO flush:  %10s%20s", (t & 0x20) ? "on" : "off", (t & 0x10) ? "on" : "off" );
+	via_print("Read DMA FIFO flush:   %10s%20s", (t & 0x80) ? "yes" : "no", (t & 0x40) ? "yes" : "no");
+	via_print("End Sector FIFO flush: %10s%20s", (t & 0x20) ? "yes" : "no", (t & 0x10) ? "yes" : "no");
 
 	pci_read_config_byte(dev, VIA_IDE_CONFIG, &t);
-	via_print("Prefetch Buffer:       %10s%20s", (t & 0x80) ? "on" : "off", (t & 0x20) ? "on" : "off" );
-	via_print("Post Write Buffer:     %10s%20s", (t & 0x40) ? "on" : "off", (t & 0x10) ? "on" : "off" );
+	via_print("Prefetch Buffer:       %10s%20s", (t & 0x80) ? "yes" : "no", (t & 0x20) ? "yes" : "no");
+	via_print("Post Write Buffer:     %10s%20s", (t & 0x40) ? "yes" : "no", (t & 0x10) ? "yes" : "no");
 
-	pci_read_config_byte(dev, VIA_FIFO_CONFIG, &t);
-	via_print("FIFO size:             %10d%20d", 16 - (((t >> 5) & 1) + ((t >> 6) & 1)) * 8,
-							  (((t >> 5) & 1) + ((t >> 6) & 1)) * 8);
-	via_print("Threshold Prim.:       %10s%20s", via_fifo[(t >> 2) & 3], via_fifo[t & 3]);
-
-	pci_read_config_word(dev, VIA_PRI_SECTOR_SIZE, &size0);
-	pci_read_config_word(dev, VIA_SEC_SECTOR_SIZE, &size1);
-	via_print("Bytes Per Sector:      %10d%20d", size0 & 0xfff, size1 & 0xfff);
+	pci_read_config_byte(dev, VIA_IDE_ENABLE, &t);
+	via_print("Enabled:               %10s%20s", (t & 0x02) ? "yes" : "no", (t & 0x01) ? "yes" : "no");
 
-	pci_read_config_dword(dev, VIA_BM_BASE, &base);
-	base = (base & 0xfff0) ;
+	c = inb(via_base + 0x02) | (inb(via_base + 0x0a) << 8);
+	via_print("Simplex only:          %10s%20s", (c & 0x80) ? "yes" : "no", (c & 0x8000) ? "yes" : "no");
 
-	c0 = inb((unsigned short)base + 0x02);
-	c1 = inb((unsigned short)base + 0x0a);
-
-	via_print("Both channels togth:   %10s%20s", (c0 & 0x80) ? "no" : "yes", (c1 & 0x80) ? "no" : "yes" );
+	via_print("Cable Type:            %10s%20s", (via_80w & 1) ? "80w" : "40w", (via_80w & 2) ? "80w" : "40w");
 
 	via_print("-------------------drive0----drive1----drive2----drive3-----");
 
-	via_print("BMDMA enabled: %10s%10s%10s%10s", (c0 & 0x20) ? "yes" : "no", (c0 & 0x40) ? "yes" : "no",
-						     (c1 & 0x20) ? "yes" : "no", (c1 & 0x40) ? "yes" : "no" );
-
 	pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t);
 	pci_read_config_dword(dev, VIA_DRIVE_TIMING, &v);
-	pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
+	pci_read_config_word(dev, VIA_8BIT_TIMING, &w);
+
+	if (via_config->flags & VIA_UDMA)
+		pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
+	else u = 0;
 
 	for (i = 0; i < 4; i++) {
-		setup[i]   = ((t >>  ((3 - i) << 1)     ) & 0x3) + 1;
-		active[i]  = ((v >> (((3 - i) << 3) + 4)) & 0xf) + 1;
-		recover[i] = ((v >>  ((3 - i) << 3)     ) & 0xf) + 1;
-		udma[i]    = ((u >>  ((3 - i) << 3)     ) & 0x7) + 2;
-		umul[i]    = ((u >> (((3 - i) & 2) << 3)) & 0x8) ? 2 : 1;
-		uen[i]     = ((u >> ((3 - i) << 3)) & 0x20) ? 1 : 0;
-		speed[i] = uen[i] ? 20 * pci_clock * umul[i] / udma[i] :
-				    20 * pci_clock / (active[i] + recover[i]);
-		cycle[i] = uen[i] ? 1000 / (pci_clock * umul[i]) * udma[i] :
-				    1000 / pci_clock * (active[i] + recover[i]);
-	}
-
-	via_print_drive("Transfer Mode: ", "%10s", uen[i] ? "UDMA" : "DMA/PIO");
-	via_print_drive("Address Setup: ", "%8dns", (1000 / pci_clock) * setup[i]);
-	via_print_drive("Active Pulse:  ", "%8dns", (1000 / pci_clock) * active[i]);
-	via_print_drive("Recovery Time: ", "%8dns", (1000 / pci_clock) * recover[i]);
+		setup[i]     = ((t >> ((3 - i) << 1)) & 0x3) + 1;
+		recover8b[i] = ((w >> ((1 - (i >> 1)) << 3)) & 0xf) + 1;
+		active8b[i]  = ((w >> (((1 - (i >> 1)) << 3) + 4)) & 0xf) + 1;
+		active[i]    = ((v >> (((3 - i) << 3) + 4)) & 0xf) + 1;
+		recover[i]   = ((v >> ((3 - i) << 3)) & 0xf) + 1;
+		udma[i]      = ((u >> ((3 - i) << 3)) & 0x7) + 2;
+
+		if ((via_config->flags & VIA_UDMA) == VIA_UDMA_100) {
+			speed[i] = 2000 / udma[i];
+			cycle[i] = 10 * udma[i];
+			continue;
+		}
+
+		uen[i]   = (u >> ((3 - i) << 3)) & 0x20;
+		udma[i] *= ((u >> (((3 - i) & 2) << 3)) & 0x8) ? 1 : 2;
+
+		speed[i] = 40 * via_clock / (uen[i] ? udma[i] : (active[i] + recover[i]) * 2);
+		cycle[i] = 1000 / via_clock * (uen[i] ? udma[i] : (active[i] + recover[i]) * 2) / 2;
+	}
+
+	via_print_drive("Transfer Mode: ", "%10s",
+			(c & ((i & 1) ? 0x40 : 0x20) << ((i & 2) << 2)) ? (uen[i] ? "UDMA" : "DMA") : "PIO");
+
+	via_print_drive("Address Setup: ", "%8dns", (1000 / via_clock) * setup[i]);
+	via_print_drive("Cmd Active:    ", "%8dns", (1000 / via_clock) * active8b[i]);
+	via_print_drive("Cmd Recovery:  ", "%8dns", (1000 / via_clock) * recover8b[i]);
+	via_print_drive("Data Active:   ", "%8dns", (1000 / via_clock) * active[i]);
+	via_print_drive("Data Recovery: ", "%8dns", (1000 / via_clock) * recover[i]);
 	via_print_drive("Cycle Time:    ", "%8dns", cycle[i]);
 	via_print_drive("Transfer Rate: ", "%4d.%dMB/s", speed[i] / 10, speed[i] % 10);
 
@@ -274,302 +236,243 @@
 
 #endif
 
-#define FIT(v,min,max) ((v)>(max)?(max):((v)<(min)?(min):(v)))
-#define ENOUGH(v,un) (((v)-1)/(un)+1)
-
-#ifdef DEBUG
-#define via_write_config_byte(dev,number,value) do {\
-		printk(KERN_DEBUG "VP_IDE: Setting register %#x to %#x\n", number, value);\
-		pci_write_config_byte(dev,number,value); } while (0)
-#else
-#define via_write_config_byte	pci_write_config_byte
-#endif
+/*
+ * via_set_speed() writes timing values to the chipset registers
+ */
 
-static int via_set_speed(ide_drive_t *drive, byte speed)
+static void via_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timing *timing)
 {
-	struct pci_dev *dev = HWIF(drive)->pci_dev;
-	int i, T, err = 0;
-	unsigned char t, setup, active, recover, cycle;
-
-	if (drive->dn > 3) return -1;
-
-	T = 1000 / system_bus_clock();
-
-	if (speed > via_isa_bridges[via_config].speed)
-		speed = via_isa_bridges[via_config].speed;
+	unsigned char t;
 
-	for (i = 0; via_timing[i].mode && via_timing[i].mode != speed; i++);
+	pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t);
+	t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1));
+	pci_write_config_byte(dev, VIA_ADDRESS_SETUP, t);
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "VP_IDE: Setting drive %d to %s\n", drive->dn, via_timing[i].name);
-#endif
+	pci_write_config_byte(dev, VIA_8BIT_TIMING + (1 - (dn >> 1)),
+		((FIT(timing->act8b, 1, 16) - 1) << 4) | (FIT(timing->rec8b, 1, 16) - 1));
 
-	setup   = ENOUGH(via_timing[i].setup,   T);
-	active  = ENOUGH(via_timing[i].active,  T);
-	recover = ENOUGH(via_timing[i].recover, T);
-	cycle   = ENOUGH(via_timing[i].cycle,   T);
+	pci_write_config_byte(dev, VIA_DRIVE_TIMING + (3 - dn),
+		((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1));
 
-	if (active + recover < cycle) {
-		active += (cycle - (active + recover)) / 2;
-		recover = cycle - active;
+	switch (via_config->flags & VIA_UDMA) {
+		case VIA_UDMA_33:  t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
+		case VIA_UDMA_66:  t = timing->udma ? (0xe8 | (FIT(timing->udma, 2, 9) - 2)) : 0x0f; break;
+		case VIA_UDMA_100: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
+		default: return;
 	}
 
-/*
- * PIO address setup
- */
-
-	pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t);
-	t = (t & ~(3 << ((3 - drive->dn) << 1))) | (FIT(setup - 1, 0, 3) << ((3 - drive->dn) << 1));
-	via_write_config_byte(dev, VIA_ADDRESS_SETUP, t);
+	pci_write_config_byte(dev, VIA_UDMA_TIMING + (3 - dn), t);
+}
 
 /*
- * PIO active & recover
+ * via_set_drive() computes timing values configures the drive and
+ * the chipset to a desired transfer mode. It also can be called
+ * by upper layers.
  */
 
-	via_write_config_byte(dev, VIA_DRIVE_TIMING + (3 - drive->dn),
-		(FIT(active - 1, 0, 0xf) << 4) | FIT(recover - 1, 0, 0xf));
-
-/*
- * UDMA cycle
- */
+static int via_set_drive(ide_drive_t *drive, unsigned char speed)
+{
+	ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1);
+	struct ide_timing t, p;
+	int T, UT;
+
+	if (speed != XFER_PIO_SLOW && speed != drive->current_speed)
+		if (ide_config_drive_speed(drive, speed))
+			printk(KERN_WARNING "ide%d: Drive %d didn't accept speed setting. Oh, well.\n",
+				drive->dn >> 1, drive->dn & 1);
+
+	T = 1000 / via_clock;
+
+	switch (via_config->flags & VIA_UDMA) {
+		case VIA_UDMA_33:   UT = T;   break;
+		case VIA_UDMA_66:   UT = T/2; break;
+		case VIA_UDMA_100:  UT = 10;  break;
+		default:	    UT = T;   break;
+	}
 
-	switch(via_isa_bridges[via_config].speed) {
-		case XFER_UDMA_2: t = via_timing[i].udma ? (0xe0 | (FIT(ENOUGH(via_timing[i].udma, T), 2, 5) - 2)) : 0x03; break;
-		case XFER_UDMA_4: t = via_timing[i].udma ? (0xe8 | (FIT(ENOUGH(via_timing[i].udma, T/2), 2, 9) - 2)) : 0x0f; break;
-        }
+	ide_timing_compute(drive, speed, &t, T, UT);
 
-	if (via_isa_bridges[via_config].speed != XFER_MW_DMA_2)
-		via_write_config_byte(dev, VIA_UDMA_TIMING + (3 - drive->dn), t);
+	if (peer->present) {
+		ide_timing_compute(peer, peer->current_speed, &p, T, UT);
+		ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT);
+	}
 
-/*
- * Drive init
- */
+	via_set_speed(HWIF(drive)->pci_dev, drive->dn, &t);
 
-	if (!drive->init_speed) drive->init_speed = speed;
-	if ((err = ide_config_drive_speed(drive, speed)))
-		return err;
+	if (!drive->init_speed)
+		drive->init_speed = speed;
 	drive->current_speed = speed;
 
 	return 0;
 }
 
-static void config_chipset_for_pio(ide_drive_t *drive)
-{
-	short eide_pio_timing[] = {600, 383, 240, 180, 120, 100};
-	signed char pio, ide_pio;
-
-	if (drive->id->eide_pio_iordy > 0) {	/* Has timing table */
-		for (pio = 5; pio >= 0; pio--)
-			if (drive->id->eide_pio_iordy <= eide_pio_timing[pio])
-				break;
-	} else {				/* No timing table -> use mode capabilities */
-		pio = (drive->id->eide_pio_modes & 4) ? 5 :
-		      (drive->id->eide_pio_modes & 2) ? 4 :
-		      (drive->id->eide_pio_modes & 1) ? 3 :
-		      (drive->id->tPIO == 2) ? 2 :
-		      (drive->id->tPIO == 1) ? 1 : 0;
-	}
-
-	ide_pio = ide_get_best_pio_mode(drive, 255, 5, NULL);
-	pio = (pio >= ide_pio) ? pio : ide_pio;	/* Phew. What about the blacklist? */
-
-	if (!pio) pio = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW;
-		else pio += XFER_PIO_0;
-
-	/* Fixup because of broken ide-probe.c */
-	drive->dn = HWIF(drive)->channel * 2 + (drive->select.b.unit & 1); 
-
-	via_set_speed(drive, pio);
-}
+/*
+ * via82cxxx_tune_drive() is a callback from upper layers for
+ * PIO-only tuning.
+ */
 
-static void via82cxxx_tune_drive(ide_drive_t *drive, byte pio)
+static void via82cxxx_tune_drive(ide_drive_t *drive, unsigned char pio)
 {
+	if (!((via_enabled >> HWIF(drive)->channel) & 1))
+		return;
+
 	if (pio == 255) {
-		config_chipset_for_pio(drive);
+		via_set_drive(drive, ide_find_best_mode(drive, XFER_PIO | XFER_EPIO));
 		return;
 	}
-	
-	if (pio > 5) pio = 5;
-	
-	via_set_speed(drive, XFER_PIO_0 + pio);
+
+	via_set_drive(drive, XFER_PIO_0 + MIN(pio, 5));
 }
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 
-static int config_chipset_for_dma(ide_drive_t *drive)
+/*
+ * via82cxxx_dmaproc() is a callback from upper layers that can do
+ * a lot, but we use it for DMA/PIO tuning only, delegating everything
+ * else to the default ide_dmaproc().
+ */
+
+int via82cxxx_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
 {
-	struct hd_driveid *id = drive->id;
-	unsigned char ultra66 = eighty_ninty_three(drive);
-	unsigned char speed =
-
-		((id->dma_ultra & 0x0010) && ultra66) ? XFER_UDMA_4 :
-		((id->dma_ultra & 0x0008) && ultra66) ? XFER_UDMA_3 :
-		(id->dma_ultra & 0x0004) ? XFER_UDMA_2 :
-		(id->dma_ultra & 0x0002) ? XFER_UDMA_1 :
-		(id->dma_ultra & 0x0001) ? XFER_UDMA_0 :
-		(id->dma_mword & 0x0004) ? XFER_MW_DMA_2 :
-		(id->dma_mword & 0x0002) ? XFER_MW_DMA_1 :
-		(id->dma_mword & 0x0001) ? XFER_MW_DMA_0 :
-		(id->dma_1word & 0x0004) ? XFER_SW_DMA_2 :
-		(id->dma_1word & 0x0002) ? XFER_SW_DMA_1 :
-		(id->dma_1word & 0x0001) ? XFER_SW_DMA_0 : 0;
-		
-	if (!speed) return (int) ide_dma_off_quietly;
 
-	via_set_speed(drive, speed);
+	if (func == ide_dma_check) {
 
-	return (int) ide_dma_on;
-}
+		short w80 = HWIF(drive)->udma_four;
 
-/*
- * Almost a library function.
- */
+		short speed = ide_find_best_mode(drive,
+			XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA |
+			(via_config->flags & VIA_UDMA ? XFER_UDMA : 0) |
+			(w80 && (via_config->flags & VIA_UDMA) == VIA_UDMA_66 ? XFER_UDMA_66 : 0) |
+			(w80 && (via_config->flags & VIA_UDMA) == VIA_UDMA_100 ? XFER_UDMA_100 : 0));
 
-static int config_drive_xfer_rate(ide_drive_t *drive)
-{
-	struct hd_driveid *id = drive->id;
-	ide_dma_action_t dma_func = ide_dma_on;
+		func = ((speed & XFER_MODE) != XFER_PIO) ? ide_dma_on : ide_dma_off_quietly;
 
-	if (id && (id->capability & 1) && HWIF(drive)->autodma) {
-		/* Consult the list of known "bad" drives */
-		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
-			dma_func = ide_dma_off;
-			goto fast_ata_pio;
-		}
-		dma_func = ide_dma_off_quietly;
-		if (id->field_valid & 4) {
-			if (id->dma_ultra & 0x002F) {
-				/* Force if Capable UltraDMA */
-				dma_func = config_chipset_for_dma(drive);
-				if ((id->field_valid & 2) &&
-				    (dma_func != ide_dma_on))
-					goto try_dma_modes;
-			}
-		} else if (id->field_valid & 2) {
-try_dma_modes:
-			if (id->dma_mword & 0x0007) {
-				/* Force if Capable regular DMA modes */
-				dma_func = config_chipset_for_dma(drive);
-				if (dma_func != ide_dma_on)
-					goto no_dma_set;
-			}
-		} else if (ide_dmaproc(ide_dma_good_drive, drive)) {
-			if (id->eide_dma_time > 150) {
-				goto no_dma_set;
-			}
-			/* Consult the list of known "good" drives */
-			dma_func = config_chipset_for_dma(drive);
-			if (dma_func != ide_dma_on)
-				goto no_dma_set;
-		} else {
-			goto fast_ata_pio;
-		}
-	} else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
-		dma_func = ide_dma_off_quietly;
-no_dma_set:
-		config_chipset_for_pio(drive);
+		via_set_drive(drive, speed);
 	}
-	return HWIF(drive)->dmaproc(dma_func, drive);
-}
 
-
-int via82cxxx_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
-{
-	if (func == ide_dma_check)
-			return config_drive_xfer_rate(drive);
 	return ide_dmaproc(func, drive);
 }
+
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
+/*
+ * The initialization callback. Here we determine the IDE chip type
+ * and initialize its drive independent registers.
+ */
+
 unsigned int __init pci_init_via82cxxx(struct pci_dev *dev, const char *name)
 {
 	struct pci_dev *isa = NULL;
-	unsigned char f, t, m;
-	unsigned int u, i;
+	unsigned char t, v;
+	unsigned int u;
+	int i;
 
 /*
- * Find ISA bridge to see how good the IDE is.
+ * Find the ISA bridge to see how good the IDE is.
  */
 
-	for (via_config = 0; via_isa_bridges[via_config].id; via_config++)
-		if ((isa = pci_find_device(PCI_VENDOR_ID_VIA, via_isa_bridges[via_config].id, NULL)))	
-			break;
-/*
- * Read revision.
- */
-
-	if (via_isa_bridges[via_config].id == PCI_DEVICE_ID_VIA_82C586_0) {
-		pci_read_config_byte(isa, PCI_REVISION_ID, &t);
-		if (t < 0x30) via_config++;			/* vt82c586a */
-		if (t < 0x20) via_config++;			/* vt82c586 */
-	}
+	for (via_config = via_isa_bridges; via_config->id; via_config++)
+		if ((isa = pci_find_device(PCI_VENDOR_ID_VIA, via_config->id, NULL))) {
+			pci_read_config_byte(isa, PCI_REVISION_ID, &t);
+			if (t >= via_config->rev_min && t <= via_config->rev_max)
+				break;
+		}
 
-	if (via_isa_bridges[via_config].id == PCI_DEVICE_ID_VIA_82C596) {
-		pci_read_config_byte(isa, PCI_REVISION_ID, &t);
-		if (t < 0x10) via_config++;			/* vt82c596a */
+	if (!via_config->id) {
+		printk(KERN_WARNING "VP_IDE: Unknown VIA SouthBridge, contact Vojtech Pavlik <vojtech@suse.cz>\n");
+		return -ENODEV;
 	}
 
 /*
- * Check UDMA66 mode set by BIOS.
+ * Check 80-wire cable presence and setup Clk66.
  */
 
-	pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
+	switch (via_config->flags & VIA_UDMA) {
 
-	for (i = 0; i < 4; i++) {
-		pci_read_config_byte(dev, VIA_UDMA_TIMING + (3 - i), &t);
-		if ((u & (0x80000 >> ((i >> 1) << 4))) && ((t & 7) < 2)) via_ata66 |= (1 << (i >> 1));
-	} 
-
-#ifdef DEBUG
-	printk(KERN_DEBUG "VP_IDE: BIOS enabled ATA66: primary: %s, secondary: %s\n",
-		via_ata66 & 1 ? "yes" : "no", via_ata66 & 2 ? "yes" : "no");
-#endif
+		case VIA_UDMA_100:
+
+			pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
+			for (i = 24; i >= 0; i -= 8)
+				if (((u >> i) & 0x10) || (((u >> i) & 0x20) && (((u >> i) & 7) < 3)))
+					via_80w |= (1 << (1 - (i >> 4)));	/* BIOS 80-wire bit or UDMA w/ < 50ns/cycle */
+			break;
+
+		case VIA_UDMA_66:
+
+			pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);	/* Enable Clk66 */
+			pci_write_config_dword(dev, VIA_UDMA_TIMING, u | 0x80008);
+			for (i = 24; i >= 0; i -= 8)
+				if (((u >> (i & 16)) & 8) && ((u >> i) & 0x20) && (((u >> i) & 7) < 2))
+					via_80w |= (1 << (1 - (i >> 4)));	/* 2x PCI clock and UDMA w/ < 3T/cycle */
+			break;
+	}
+
+	if (via_config->flags & VIA_BAD_CLK66) {			/* Disable Clk66 */
+		pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);	/* Would cause trouble on 596a */
+		pci_write_config_dword(dev, VIA_UDMA_TIMING, u & ~0x80008);
+	}
 
 /*
- * Set UDMA66 double clock bits.
+ * Check whether interfaces are enabled.
  */
-	if (via_isa_bridges[via_config].speed == XFER_UDMA_4)
-		pci_write_config_dword(dev, VIA_UDMA_TIMING, u | 0x80008);
+
+	pci_read_config_byte(dev, VIA_IDE_ENABLE, &v);
+	via_enabled = ((v & 1) ? 2 : 0) | ((v & 2) ? 1 : 0);
 
 /*
- * Set up FIFO, flush, prefetch and post-writes.
+ * Set up FIFO sizes and thresholds.
  */
 
-	pci_read_config_dword(dev, VIA_IDE_ENABLE, &u);
-	pci_read_config_byte(dev, VIA_FIFO_CONFIG, &f);
-	pci_read_config_byte(dev, VIA_IDE_CONFIG, &t);
-	pci_read_config_byte(dev, VIA_MISC_3, &m);
+	pci_read_config_byte(dev, VIA_FIFO_CONFIG, &t);
 
-	f &= 0x90; t &= 0x0f; m &= 0x0f;
+	if (via_config->flags & VIA_BAD_PREQ)				/* Disable PREQ# till DDACK# */
+		t &= 0x7f;						/* Would crash on 586b rev 41 */
 
-	switch (u & 3) {
-		case 2: via_enabled = 1; f |= 0x06; t |= 0xc0; m |= 0xa0; break;	/* primary only, 3/4 */
-		case 1: via_enabled = 2; f |= 0x69; t |= 0x30; m |= 0x50; break;	/* secondary only, 3/4 */
-		case 3: via_enabled = 3;
-		default:                 f |= 0x2a; t |= 0xf0; m |= 0xf0; break;	/* fifo evenly distributed */
+	if (via_config->flags & VIA_SET_FIFO) {				/* Fix FIFO split between channels */
+		t &= (t & 0x9f);
+		switch (via_enabled) {
+			case 1: t |= 0x00; break;			/* 16 on primary */
+			case 2: t |= 0x60; break;			/* 16 on secondary */
+			case 3: t |= 0x20; break;			/* 8 pri 8 sec */
+		}
 	}
 
-	via_write_config_byte(dev, VIA_FIFO_CONFIG, f);
-	via_write_config_byte(dev, VIA_IDE_CONFIG, t);
-	via_write_config_byte(dev, VIA_MISC_3, m);
+	if (via_config->flags & VIA_SET_THRESH)				/* 1/2 FIFO full to trigger xmit */
+		t = (t & 0xf0) | 0x0a;
+
+	pci_write_config_byte(dev, VIA_FIFO_CONFIG, t);
+
+/*
+ * Determine system bus clock.
+ */
+
+	via_clock = system_bus_clock();
+	if (via_clock < 20 || via_clock > 50) {
+		printk(KERN_WARNING "VP_IDE: User given PCI clock speed impossible (%d), using 33 MHz instead.\n", via_clock);
+		printk(KERN_WARNING "VP_IDE: Use ide0=ata66 if you want to force UDMA66/UDMA100.\n");
+		via_clock = 33;
+	}
 
 /*
  * Print the boot message.
  */
 
-	printk(KERN_INFO "VP_IDE: VIA %s IDE %s controller on pci%d:%d.%d\n",
-			via_isa_bridges[via_config].name,
-			via_isa_bridges[via_config].speed >= XFER_UDMA_4 ? "UDMA66" :
-			via_isa_bridges[via_config].speed >= XFER_UDMA_2 ? "UDMA33" : "MWDMA16",
-			dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+	pci_read_config_byte(isa, PCI_REVISION_ID, &t);
+	printk(KERN_INFO "VP_IDE: VIA %s (rev %02x) IDE %s controller on pci%s\n",
+			via_config->name, t,
+			(via_config->flags & VIA_UDMA) == VIA_UDMA_100 ? "UDMA100" :
+			(via_config->flags & VIA_UDMA) == VIA_UDMA_66 ? "UDMA66" :
+			(via_config->flags & VIA_UDMA) == VIA_UDMA_33 ? "UDMA33" : "MWDMA16",
+			dev->slot_name);
+
 /*
- * Register /proc/ide/via entry
+ * Setup /proc/ide/via entry.
  */
 
-#if defined(CONFIG_PROC_FS)
+#ifdef CONFIG_PROC_FS
 	if (!via_proc) {
 		via_proc = 1;
+		via_base = pci_resource_start(dev, 4);
 		bmide_dev = dev;
 		isa_dev = isa;
 		via_display_info = &via_get_info;
@@ -579,26 +482,26 @@
 	return 0;
 }
 
-/*
- * Since we don't have a way to detect the 80-wire ribbon cable
- * we rely on the BIOS detection. We also check the IDENTIFY byte
- * 93 to check the drive's point of view. I think we could return
- * '1' here 
- */
-
 unsigned int __init ata66_via82cxxx(ide_hwif_t *hwif)
 {
-	return ((via_enabled & via_ata66) >> hwif->channel) & 1;
+	return ((via_enabled & via_80w) >> hwif->channel) & 1;
 }
 
 void __init ide_init_via82cxxx(ide_hwif_t *hwif)
 {
+	int i;
+
 	hwif->tuneproc = &via82cxxx_tune_drive;
-	hwif->speedproc = &via_set_speed;
-	hwif->drives[0].autotune = 1;
-	hwif->drives[1].autotune = 1;
+	hwif->speedproc = &via_set_drive;
 	hwif->autodma = 0;
 
+	for (i = 0; i < 2; i++) {
+		hwif->drives[i].io_32bit = 1;
+		hwif->drives[i].unmask = 1;
+		hwif->drives[i].autotune = 1;
+		hwif->drives[i].dn = hwif->channel * 2 + i;
+	}
+
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (hwif->dma_base) {
 		hwif->dmaproc = &via82cxxx_dmaproc;
@@ -610,7 +513,7 @@
 }
 
 /*
- * We allow the BM-DMA driver only work on enabled interfaces.
+ * We allow the BM-DMA driver to only work on enabled interfaces.
  */
 
 void __init ide_dmacapable_via82cxxx(ide_hwif_t *hwif, unsigned long dmabase)
diff -u --recursive --new-file v2.4.1/linux/drivers/md/raid5.c linux/drivers/md/raid5.c
--- v2.4.1/linux/drivers/md/raid5.c	Sat Feb  3 19:51:27 2001
+++ linux/drivers/md/raid5.c	Sat Feb  3 11:20:25 2001
@@ -1076,7 +1076,7 @@
 		bh->b_end_io(bh, 1);
 	}
 	while ((bh=return_fail)) {
-		return_ok = bh->b_reqnext;
+		return_fail = bh->b_reqnext;
 		bh->b_reqnext = NULL;
 		bh->b_end_io(bh, 0);
 	}
diff -u --recursive --new-file v2.4.1/linux/drivers/net/Config.in linux/drivers/net/Config.in
--- v2.4.1/linux/drivers/net/Config.in	Thu Jan  4 13:00:55 2001
+++ linux/drivers/net/Config.in	Sat Feb  3 12:45:10 2001
@@ -52,7 +52,7 @@
    if [ "$CONFIG_SGI_IP27" = "y" ]; then
       bool '  SGI IOC3 Ethernet' CONFIG_SGI_IOC3_ETH
    fi
-   if [ "CONFIG_IA64_SGI_SN1" = "y" ]; then
+   if [ "$CONFIG_IA64_SGI_SN1" = "y" ]; then
       bool '  SGI IOC3 Ethernet' CONFIG_SGI_IOC3_ETH
    fi
    if [ "$CONFIG_SUPERH" = "y" ]; then
diff -u --recursive --new-file v2.4.1/linux/drivers/net/acenic.c linux/drivers/net/acenic.c
--- v2.4.1/linux/drivers/net/acenic.c	Thu Jan  4 15:25:55 2001
+++ linux/drivers/net/acenic.c	Sat Feb  3 12:45:52 2001
@@ -44,6 +44,8 @@
  *   Val Henson <vhenson@esscom.com>:    Reset Jumbo skb producer and
  *                                       rx producer index when
  *                                       flushing the Jumbo ring.
+ *   Hans Grobler <grobh@sun.ac.za>:     Memory leak fixes in the
+ *                                       driver init path.
  */
 
 #include <linux/config.h>
@@ -77,7 +79,6 @@
 
 
 #undef INDEX_DEBUG
-#define TX_HOST_RING	1
 
 #ifdef CONFIG_ACENIC_OMIT_TIGON_I
 #define ACE_IS_TIGON_I(ap)	0
@@ -151,6 +152,11 @@
 #define __exit
 #endif
 
+#ifndef __devinit
+#define __devinit	__init
+#endif
+
+
 #ifndef SMP_CACHE_BYTES
 #define SMP_CACHE_BYTES	L1_CACHE_BYTES
 #endif
@@ -188,6 +194,8 @@
 	void *virt_ptr;
 
 	virt_ptr = kmalloc(size, GFP_KERNEL);
+	if (!virt_ptr)
+		return NULL;
 	*dma_handle = virt_to_bus(virt_ptr);
 	return virt_ptr;
 }
@@ -481,15 +489,15 @@
 static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1};
 
 static char version[] __initdata = 
-  "acenic.c: v0.49 12/13/2000  Jes Sorensen, linux-acenic@SunSITE.auc.dk\n"
+  "acenic.c: v0.50 02/02/2001  Jes Sorensen, linux-acenic@SunSITE.dk\n"
   "                            http://home.cern.ch/~jes/gige/acenic.html\n";
 
-static struct net_device *root_dev = NULL;
+static struct net_device *root_dev;
 
 static int probed __initdata = 0;
 
 
-int __init acenic_probe (ACE_PROBE_ARG)
+int __devinit acenic_probe (ACE_PROBE_ARG)
 {
 #ifdef NEW_NETINIT
 	struct net_device *dev;
@@ -658,12 +666,19 @@
 			printk(KERN_ERR "%s: Driver compiled without Tigon I"
 			       " support - NIC disabled\n", dev->name);
 			ace_init_cleanup(dev);
+			kfree(dev);
 			continue;
 		}
 #endif
 
-		if (ace_allocate_descriptors(dev))
+		if (ace_allocate_descriptors(dev)) {
+			/*
+			 * ace_allocate_descriptors() calls
+			 * ace_init_cleanup() on error.
+			 */
+			kfree(dev);
 			continue;
+		}
 
 #ifdef MODULE
 		if (boards_found >= ACE_MAX_MOD_PARMS)
@@ -674,8 +689,13 @@
 		ap->board_idx = BOARD_IDX_STATIC;
 #endif
 
-		if (ace_init(dev))
+		if (ace_init(dev)) {
+			/*
+			 * ace_init() calls ace_init_cleanup() on error.
+			 */
+			kfree(dev);
 			continue;
+		}
 
 		boards_found++;
 	}
@@ -705,7 +725,7 @@
 #endif
 
 
-void __exit ace_module_cleanup(void)
+static void __exit ace_module_cleanup(void)
 {
 	struct ace_private *ap;
 	struct ace_regs *regs;
@@ -1006,10 +1026,15 @@
 	 * This will most likely need BYTE_SWAP once we switch
 	 * to using __raw_writel()
 	 */
-	writel((WORD_SWAP | CLR_INT |
-		((WORD_SWAP | CLR_INT) << 24)),
+#ifdef __parisc__
+	writel((WORD_SWAP | BYTE_SWAP | CLR_INT |
+		((WORD_SWAP | BYTE_SWAP | CLR_INT) << 24)),
 	       &regs->HostCtrl);
 #else
+	writel((WORD_SWAP | CLR_INT | ((WORD_SWAP | CLR_INT) << 24)),
+	       &regs->HostCtrl);
+#endif
+#else
 	writel((CLR_INT | WORD_SWAP | ((CLR_INT | WORD_SWAP) << 24)),
 	       &regs->HostCtrl);
 #endif
@@ -1026,7 +1051,7 @@
 	switch(tig_ver){
 #ifndef CONFIG_ACENIC_OMIT_TIGON_I
 	case 4:
-		printk(KERN_INFO"  Tigon I  (Rev. 4), Firmware: %i.%i.%i, ",
+		printk(KERN_INFO "  Tigon I  (Rev. 4), Firmware: %i.%i.%i, ",
 		       tigonFwReleaseMajor, tigonFwReleaseMinor,
 		       tigonFwReleaseFix);
 		writel(0, &regs->LocalCtrl);
@@ -1034,7 +1059,7 @@
 		break;
 #endif
 	case 6:
-		printk(KERN_INFO"  Tigon II (Rev. %i), Firmware: %i.%i.%i, ",
+		printk(KERN_INFO "  Tigon II (Rev. %i), Firmware: %i.%i.%i, ",
 		       tig_ver, tigon2FwReleaseMajor, tigon2FwReleaseMinor,
 		       tigon2FwReleaseFix);
 		writel(readl(&regs->CpuBCtrl) | CPU_HALT, &regs->CpuBCtrl);
@@ -1048,8 +1073,8 @@
 		ap->version = 2;
 		break;
 	default:
-		printk(KERN_INFO"  Unsupported Tigon version detected (%i), ",
-		       tig_ver);
+		printk(KERN_WARNING "  Unsupported Tigon version detected "
+		       "(%i), ", tig_ver);
 		ecode = -ENODEV;
 		goto init_error;
 	}
@@ -2040,6 +2065,7 @@
 
 		netif_rx(skb);		/* send it up */
 
+		dev->last_rx = jiffies;
 		ap->stats.rx_packets++;
 		ap->stats.rx_bytes += retdesc->size;
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/ne2k-pci.c linux/drivers/net/ne2k-pci.c
--- v2.4.1/linux/drivers/net/ne2k-pci.c	Tue Dec  5 12:29:38 2000
+++ linux/drivers/net/ne2k-pci.c	Sat Feb  3 11:44:58 2001
@@ -202,6 +202,10 @@
 	if (fnd_cnt++ == 0)
 		printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2);
 
+	i = pci_enable_device (pdev);
+	if (i)
+		return i;
+
 	ioaddr = pci_resource_start (pdev, 0);
 	irq = pdev->irq;
 
@@ -209,10 +213,6 @@
 		printk (KERN_ERR "ne2k-pci: no I/O resource at PCI BAR #0\n");
 		return -ENODEV;
 	}
-
-	i = pci_enable_device (pdev);
-	if (i)
-		return i;
 
 	if (request_region (ioaddr, NE_IO_EXTENT, "ne2k-pci") == NULL) {
 		printk (KERN_ERR "ne2k-pci: I/O resource 0x%x @ 0x%lx busy\n",
diff -u --recursive --new-file v2.4.1/linux/drivers/net/sis900.c linux/drivers/net/sis900.c
--- v2.4.1/linux/drivers/net/sis900.c	Fri Dec 29 14:07:22 2000
+++ linux/drivers/net/sis900.c	Sat Feb  3 12:12:30 2001
@@ -1,6 +1,6 @@
 /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux.
    Copyright 1999 Silicon Integrated System Corporation 
-   Revision:	1.07.07	Nov. 29 2000
+   Revision:	1.07.08	Jan. 8 2001
    
    Modified from the driver which is originally written by Donald Becker.
    
@@ -18,6 +18,7 @@
    preliminary Rev. 1.0 Jan. 18, 1998
    http://www.sis.com.tw/support/databook.htm
 
+   Rev 1.07.08 Jan.  8 2001 Lei-Chun Chang added RTL8201 PHY support
    Rev 1.07.07 Nov. 29 2000 Lei-Chun Chang added kernel-doc extractable documentation and 630 workaround fix
    Rev 1.07.06 Nov.  7 2000 Jeff Garzik <jgarzik@mandrakesoft.com> some bug fix and cleaning
    Rev 1.07.05 Nov.  6 2000 metapirat<metapirat@gmx.de> contribute media type select by ifconfig
@@ -59,7 +60,7 @@
 #include "sis900.h"
 
 static const char *version =
-"sis900.c: v1.07.07  11/29/2000\n";
+"sis900.c: v1.07.08  1/8/2001\n";
 
 static int max_interrupt_work = 20;
 static int multicast_filter_limit = 128;
@@ -92,6 +93,7 @@
 static void sis900_read_mode(struct net_device *net_dev, int phy_addr, int *speed, int *duplex);
 static void amd79c901_read_mode(struct net_device *net_dev, int phy_addr, int *speed, int *duplex);
 static void ics1893_read_mode(struct net_device *net_dev, int phy_addr, int *speed, int *duplex);
+static void rtl8201_read_mode(struct net_device *net_dev, int phy_addr, int *speed, int *duplex);
 
 static struct mii_chip_info {
 	const char * name;
@@ -104,6 +106,7 @@
 	{"AMD 79C901 10BASE-T PHY",  0x0000, 0x35b9, amd79c901_read_mode},
 	{"AMD 79C901 HomePNA PHY",   0x0000, 0x35c8, amd79c901_read_mode},
 	{"ICS 1893 Integrated PHYceiver"   , 0x0015, 0xf441,ics1893_read_mode},
+	{"RTL 8201 10/100Mbps Phyceiver"   , 0x0000, 0x8201,rtl8201_read_mode},
 	{0,},
 };
 
@@ -270,6 +273,7 @@
 	net_dev = init_etherdev(NULL, sizeof(struct sis900_private));
 	if (!net_dev)
 		return -ENOMEM;
+	SET_MODULE_OWNER(net_dev);
 
 	if (!request_region(ioaddr, SIS900_TOTAL_SIZE, net_dev->name)) {
 		printk(KERN_ERR "sis900.c: can't allocate I/O space at 0x%lX\n", ioaddr);
@@ -368,7 +372,8 @@
 
 		/* search our mii table for the current mii */ 
 		for (i = 0; mii_chip_table[i].phy_id1; i++)
-			if (phy_id0 == mii_chip_table[i].phy_id0) {
+			if (phy_id0 == mii_chip_table[i].phy_id0 &&
+			    phy_id1 == mii_chip_table[i].phy_id1) {
 				struct mii_phy * mii_phy;
 
 				printk(KERN_INFO
@@ -606,8 +611,7 @@
 	struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv;
 	long ioaddr = net_dev->base_addr;
 	u8  revision;
-
-	MOD_INC_USE_COUNT;
+	int ret;
 
 	/* Soft reset the chip. */
 	sis900_reset(net_dev);
@@ -618,10 +622,9 @@
 	    revision == SIS630A_900_REV)
 		sis630_set_eq(net_dev,revision);
 
-	if (request_irq(net_dev->irq, &sis900_interrupt, SA_SHIRQ, net_dev->name, net_dev)) {
-		MOD_DEC_USE_COUNT;
-		return -EAGAIN;
-	}
+	ret = request_irq(net_dev->irq, &sis900_interrupt, SA_SHIRQ, net_dev->name, net_dev);
+	if (ret)
+		return ret;
 
 	sis900_init_rxfilter(net_dev);
 
@@ -1112,6 +1115,51 @@
 }
 
 /**
+ *	rtl8201_read_mode: - read media mode for rtl8201 phy
+ *	@net_dev: the net device to read mode for
+ *	@phy_addr: mii phy address
+ *	@speed: the transmit speed to be determined
+ *	@duplex: the duplex mode to be determined
+ *
+ *	read MII_STATUS register from rtl8201 phy
+ *	to determine the speed and duplex mode for sis900
+ */
+
+static void rtl8201_read_mode(struct net_device *net_dev, int phy_addr, int *speed, int *duplex)
+{
+	u32 status;
+
+	status = mdio_read(net_dev, phy_addr, MII_STATUS);
+
+	if (status & MII_STAT_CAN_TX_FDX) {
+		*speed = HW_SPEED_100_MBPS;
+		*duplex = FDX_CAPABLE_FULL_SELECTED;
+	}
+	else if (status & MII_STAT_CAN_TX) {
+		*speed = HW_SPEED_100_MBPS;
+		*duplex = FDX_CAPABLE_HALF_SELECTED;
+	}
+	else if (status & MII_STAT_CAN_T_FDX) {
+		*speed = HW_SPEED_10_MBPS;
+		*duplex = FDX_CAPABLE_FULL_SELECTED;
+	}
+	else if (status & MII_STAT_CAN_T) {
+		*speed = HW_SPEED_10_MBPS;
+		*duplex = FDX_CAPABLE_HALF_SELECTED;
+	}
+
+	if (status & MII_STAT_LINK)
+		printk(KERN_INFO "%s: Media Link On %s %s-duplex \n",
+		       net_dev->name,
+		       *speed == HW_SPEED_100_MBPS ?
+		       "100mbps" : "10mbps",
+		       *duplex == FDX_CAPABLE_FULL_SELECTED ?
+		       "full" : "half");
+	else
+		printk(KERN_INFO "%s: Media Link Off\n", net_dev->name);
+}
+
+/**
  *	sis900_tx_timeout: - sis900 transmit timeout routine
  *	@net_dev: the net device to transmit
  *
@@ -1505,8 +1553,6 @@
 	}
 
 	/* Green! Put the chip in low-power mode. */
-
-	MOD_DEC_USE_COUNT;
 
 	return 0;
 }
diff -u --recursive --new-file v2.4.1/linux/drivers/parport/Config.in linux/drivers/parport/Config.in
--- v2.4.1/linux/drivers/parport/Config.in	Mon Jun 19 13:42:38 2000
+++ linux/drivers/parport/Config.in	Sat Feb  3 12:43:52 2001
@@ -12,8 +12,8 @@
 if [ "$CONFIG_PARPORT" != "n" ]; then
    dep_tristate '  PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT
    if [ "$CONFIG_PARPORT_PC" != "n" ]; then
-      bool '    Use FIFO/DMA if available' CONFIG_PARPORT_PC_FIFO
       if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+         bool '    Use FIFO/DMA if available (EXPERIMENTAL)' CONFIG_PARPORT_PC_FIFO
          bool '    SuperIO chipset support (EXPERIMENTAL)' CONFIG_PARPORT_PC_SUPERIO
       fi
    fi
diff -u --recursive --new-file v2.4.1/linux/drivers/parport/probe.c linux/drivers/parport/probe.c
--- v2.4.1/linux/drivers/parport/probe.c	Thu Jan  4 13:12:53 2001
+++ linux/drivers/parport/probe.c	Sat Feb  3 12:43:37 2001
@@ -75,8 +75,9 @@
 			char *u;
 			*(sep++) = 0;
 			/* Get rid of trailing blanks */
-			u = strchr (sep, ' ');
-			if (u) *u = '\0';
+			u = sep + strlen (sep) - 1;
+			while (u >= p && *u == ' ')
+				*u-- = '\0';
 			u = p;
 			while (*u) {
 				*u = toupper(*u);
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/cs.c linux/drivers/pcmcia/cs.c
--- v2.4.1/linux/drivers/pcmcia/cs.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/pcmcia/cs.c	Sat Feb  3 11:32:55 2001
@@ -1458,6 +1458,8 @@
 	    s->functions = 1;
 	s->config = kmalloc(sizeof(config_t) * s->functions,
 			    GFP_KERNEL);
+	if (!s->config)
+		return CS_OUT_OF_RESOURCE;
 	memset(s->config, 0, sizeof(config_t) * s->functions);
     }
     
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/ds.c linux/drivers/pcmcia/ds.c
--- v2.4.1/linux/drivers/pcmcia/ds.c	Sat Sep  2 00:13:49 2000
+++ linux/drivers/pcmcia/ds.c	Sat Feb  3 11:32:55 2001
@@ -414,6 +414,8 @@
     /* Add binding to list for this socket */
     driver->use_count++;
     b = kmalloc(sizeof(socket_bind_t), GFP_KERNEL);
+    if (!b) 
+      return -ENOMEM;
     b->driver = driver;
     b->function = bind_info->function;
     b->instance = NULL;
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c
--- v2.4.1/linux/drivers/scsi/aha152x.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/scsi/aha152x.c	Sat Feb  3 20:00:45 2001
@@ -1784,7 +1784,7 @@
 			if (info[0] == 255 && !EXT_TRANS) {
 				printk(KERN_NOTICE
 				       "aha152x: current partition table is using extended translation.\n"
-				       "         using it also, although it's not explictly enabled.\n");
+				       "         using it also, although it's not explicitly enabled.\n");
 			}
 		}
 	}
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v2.4.1/linux/drivers/scsi/sd.c	Thu Oct 26 23:35:48 2000
+++ linux/drivers/scsi/sd.c	Sat Feb  3 11:45:55 2001
@@ -798,9 +798,9 @@
 				SRpnt->sr_data_direction = SCSI_DATA_READ;
 				scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,
 					    0/*512*/, SD_TIMEOUT, MAX_RETRIES);
+				spintime_value = jiffies;
 			}
 			spintime = 1;
-			spintime_value = jiffies;
 			time1 = HZ;
 			/* Wait 1 second for next try */
 			do {
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/ultrastor.c linux/drivers/scsi/ultrastor.c
--- v2.4.1/linux/drivers/scsi/ultrastor.c	Mon Sep 18 13:36:25 2000
+++ linux/drivers/scsi/ultrastor.c	Sat Feb  3 11:32:54 2001
@@ -328,7 +328,7 @@
 {
   static char fmt[80] = "abort %d (%x); MSCP free pool: %x;";
   register int i;
-  int flags;
+  unsigned long flags;
   save_flags(flags);
   cli();
 
@@ -676,7 +676,7 @@
     int mscp_index;
 #endif
     unsigned int status;
-    int flags;
+    unsigned long flags;
 
     /* Next test is for debugging; "can't happen" */
     if ((config.mscp_free & ((1U << ULTRASTOR_MAX_CMDS) - 1)) == 0)
@@ -848,7 +848,7 @@
       {
 	int port0 = (config.slot << 12) | 0xc80;
 	int i;
-	int flags;
+	unsigned long flags;
 	save_flags(flags);
 	cli();
 	strcpy(out, "OGM %d:%x ICM %d:%x ports:  ");
@@ -874,7 +874,7 @@
     if (config.slot ? inb(config.icm_address - 1) == 2 :
 	(inb(SYS_DOORBELL_INTR(config.doorbell_address)) & 1))
       {
-	int flags;
+	unsigned long flags;
 	save_flags(flags);
 	printk("Ux4F: abort while completed command pending\n");
 	restore_flags(flags);
@@ -896,7 +896,7 @@
        and the interrupt handler will call done.  */
     if (config.slot && inb(config.ogm_address - 1) == 0)
       {
-	int flags;
+	unsigned long flags;
 
 	save_flags(flags);
 	cli();
@@ -948,7 +948,7 @@
 
 int ultrastor_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
 {
-    int flags;
+    unsigned long flags;
     register int i;
 #if (ULTRASTOR_DEBUG & UD_RESET)
     printk("US14F: reset: called\n");
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/storage/scsiglue.c linux/drivers/usb/storage/scsiglue.c
--- v2.4.1/linux/drivers/usb/storage/scsiglue.c	Sat Feb  3 19:51:30 2001
+++ linux/drivers/usb/storage/scsiglue.c	Sat Feb  3 11:46:33 2001
@@ -248,7 +248,7 @@
         for (i = 0; i < us->pusb_dev->actconfig->bNumInterfaces; i++) {
  		struct usb_interface *intf =
 			&us->pusb_dev->actconfig->interface[i];
-		struct usb_device_id *id;
+		const struct usb_device_id *id;
 
 		/* if this is an unclaimed interface, skip it */
 		if (!intf->driver) {
diff -u --recursive --new-file v2.4.1/linux/drivers/video/riva/Makefile linux/drivers/video/riva/Makefile
--- v2.4.1/linux/drivers/video/riva/Makefile	Fri Dec 29 14:07:23 2000
+++ linux/drivers/video/riva/Makefile	Sat Feb  3 12:48:00 2001
@@ -9,7 +9,7 @@
 
 O_TARGET := rivafb.o
 
-obj-y    := fbdev.o riva_hw.o
+obj-y    := fbdev.o riva_hw.o accel.o
 obj-m    := $(O_TARGET)
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/drivers/video/riva/accel.c linux/drivers/video/riva/accel.c
--- v2.4.1/linux/drivers/video/riva/accel.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/riva/accel.c	Sat Feb  3 12:48:00 2001
@@ -0,0 +1,424 @@
+/*
+ * linux/drivers/video/accel.c - nVidia RIVA 128/TNT/TNT2 fb driver
+ *
+ * Copyright 2000 Jindrich Makovicka, Ani Joshi
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ */
+
+#include "rivafb.h"
+
+/* acceleration routines */
+
+inline void wait_for_idle(struct rivafb_info *rinfo)
+{
+	while (rinfo->riva.Busy(&rinfo->riva));
+}
+
+/* set copy ROP, no mask */
+static void riva_setup_ROP(struct rivafb_info *rinfo)
+{
+	RIVA_FIFO_FREE(rinfo->riva, Patt, 5);
+	rinfo->riva.Patt->Shape = 0;
+	rinfo->riva.Patt->Color0 = 0xffffffff;
+	rinfo->riva.Patt->Color1 = 0xffffffff;
+	rinfo->riva.Patt->Monochrome[0] = 0xffffffff;
+	rinfo->riva.Patt->Monochrome[1] = 0xffffffff;
+
+	RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
+	rinfo->riva.Rop->Rop3 = 0xCC;
+}
+
+void riva_setup_accel(struct rivafb_info *rinfo)
+{
+	RIVA_FIFO_FREE(rinfo->riva, Clip, 2);
+	rinfo->riva.Clip->TopLeft     = 0x0;
+	rinfo->riva.Clip->WidthHeight = 0x80008000;
+	riva_setup_ROP(rinfo);
+	wait_for_idle(rinfo);
+}
+
+static void riva_rectfill(struct rivafb_info *rinfo, int sy,
+			  int sx, int height, int width, u_int color)
+{
+	RIVA_FIFO_FREE(rinfo->riva, Bitmap, 1);
+	rinfo->riva.Bitmap->Color1A = color;
+
+	RIVA_FIFO_FREE(rinfo->riva, Bitmap, 2);
+	rinfo->riva.Bitmap->UnclippedRectangle[0].TopLeft     = (sx << 16) | sy; 
+	rinfo->riva.Bitmap->UnclippedRectangle[0].WidthHeight = (width << 16) | height;
+}
+
+static void fbcon_riva_bmove(struct display *p, int sy, int sx, int dy, int dx,
+			    int height, int width)
+{
+	struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
+
+	sx *= fontwidth(p);
+	sy *= fontheight(p);
+	dx *= fontwidth(p);
+	dy *= fontheight(p);
+	width *= fontwidth(p);
+	height *= fontheight(p);
+
+	RIVA_FIFO_FREE(rinfo->riva, Blt, 3);
+	rinfo->riva.Blt->TopLeftSrc  = (sy << 16) | sx;
+	rinfo->riva.Blt->TopLeftDst  = (dy << 16) | dx;
+	rinfo->riva.Blt->WidthHeight = (height  << 16) | width;
+}
+
+static void riva_clear_margins(struct vc_data *conp, struct display *p,
+				int bottom_only, u32 bgx)
+{
+	struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
+
+	unsigned int right_start = conp->vc_cols*fontwidth(p);
+	unsigned int bottom_start = conp->vc_rows*fontheight(p);
+	unsigned int right_width, bottom_width;
+
+	if (!bottom_only && (right_width = p->var.xres - right_start))
+		riva_rectfill(rinfo, 0, right_start, p->var.yres_virtual,
+			      right_width, bgx);
+	if ((bottom_width = p->var.yres - bottom_start))
+		riva_rectfill(rinfo, p->var.yoffset + bottom_start, 0,
+			      bottom_width, right_start, bgx);
+}
+
+static u8 byte_rev[256] = {
+	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 
+	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 
+	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 
+	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 
+	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 
+	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 
+	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 
+	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 
+	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 
+	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 
+	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 
+	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 
+	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 
+	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 
+	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
+};
+
+static inline void fbcon_reverse_order(u32 *l)
+{
+	u8 *a = (u8 *)l;
+	*a++ = byte_rev[*a];
+/*	*a++ = byte_rev[*a];
+	*a++ = byte_rev[*a];*/
+	*a = byte_rev[*a];
+}
+
+static void fbcon_riva_writechr(struct vc_data *conp, struct display *p,
+			        int c, int fgx, int bgx, int yy, int xx)
+{
+	u8 *cdat;
+	struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
+	int w, h;
+	volatile u32 *d;
+	u32 cdat2;
+	int i, j, cnt;
+
+	w = fontwidth(p);
+	h = fontheight(p);
+
+	if (w <= 8)
+		cdat = p->fontdata + (c & p->charmask) * h;
+	else
+		cdat = p->fontdata + ((c & p->charmask) * h << 1);
+
+        RIVA_FIFO_FREE(rinfo->riva, Bitmap, 7);
+        rinfo->riva.Bitmap->ClipE.TopLeft     = (yy << 16) | (xx & 0xFFFF);
+        rinfo->riva.Bitmap->ClipE.BottomRight = ((yy+h) << 16) | ((xx+w) & 0xffff);
+        rinfo->riva.Bitmap->Color0E           = bgx;
+        rinfo->riva.Bitmap->Color1E           = fgx;
+        rinfo->riva.Bitmap->WidthHeightInE  = (h << 16) | 32;
+        rinfo->riva.Bitmap->WidthHeightOutE = (h << 16) | 32;
+        rinfo->riva.Bitmap->PointE          = (yy << 16) | (xx & 0xFFFF);
+	
+	d = &rinfo->riva.Bitmap->MonochromeData01E;
+	for (i = h; i > 0; i-=16) {
+		if (i >= 16)
+			cnt = 16;
+		else
+			cnt = i;
+		RIVA_FIFO_FREE(rinfo->riva, Bitmap, cnt);
+		for (j = 0; j < cnt; j++) {
+			if (w <= 8) 
+				cdat2 = *cdat++;
+			else
+				cdat2 = *((u16*)cdat)++;
+			fbcon_reverse_order(&cdat2);
+			d[j] = cdat2;
+		}
+	}
+}
+
+#ifdef FBCON_HAS_CFB8
+void fbcon_riva8_setup(struct display *p)
+{
+    p->next_line = p->line_length ? p->line_length : p->var.xres_virtual;
+    p->next_plane = 0;
+}
+
+static void fbcon_riva8_clear(struct vc_data *conp, struct display *p, int sy,
+			     int sx, int height, int width)
+{
+	u32 bgx;
+
+	struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
+
+	bgx = attr_bgcol_ec(p, conp);
+
+	sx *= fontwidth(p);
+	sy *= fontheight(p);
+	width *= fontwidth(p);
+	height *= fontheight(p);
+
+	riva_rectfill(rinfo, sy, sx, height, width, bgx);
+}
+
+static void fbcon_riva8_putc(struct vc_data *conp, struct display *p, int c,
+			    int yy, int xx)
+{
+	u32 fgx,bgx;
+
+	fgx = attr_fgcol(p,c);
+	bgx = attr_bgcol(p,c);
+	
+	xx *= fontwidth(p);
+	yy *= fontheight(p);
+
+	fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
+}
+
+static void fbcon_riva8_putcs(struct vc_data *conp, struct display *p,
+			     const unsigned short *s, int count, int yy,
+			     int xx)
+{
+	u16 c;
+	u32 fgx,bgx;
+
+	xx *= fontwidth(p);
+	yy *= fontheight(p);
+
+	while (count--) {
+		c = scr_readw(s++);
+		fgx = attr_fgcol(p,c);
+		bgx = attr_bgcol(p,c);
+		fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
+		xx += fontwidth(p);
+	}
+}
+
+static void fbcon_riva8_revc(struct display *p, int xx, int yy)
+{
+	struct rivafb_info *rinfo = (struct rivafb_info *) (p->fb_info);
+
+	xx *= fontwidth(p);
+	yy *= fontheight(p);
+
+	RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
+	rinfo->riva.Rop->Rop3 = 0x66; // XOR
+	riva_rectfill(rinfo, yy, xx, fontheight(p), fontwidth(p), 0x0f);
+	RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
+	rinfo->riva.Rop->Rop3 = 0xCC; // back to COPY
+}
+
+static void fbcon_riva8_clear_margins(struct vc_data *conp, struct display *p,
+				       int bottom_only)
+{
+	riva_clear_margins(conp, p, bottom_only, attr_bgcol_ec(p, conp));
+}
+
+struct display_switch fbcon_riva8 = {
+	setup:		fbcon_riva8_setup,
+	bmove:		fbcon_riva_bmove,
+	clear:		fbcon_riva8_clear,
+	putc:		fbcon_riva8_putc,
+	putcs:		fbcon_riva8_putcs,
+	revc:		fbcon_riva8_revc,
+	clear_margins:	fbcon_riva8_clear_margins,
+	fontwidthmask:	FONTWIDTHRANGE(4, 16)
+};
+#endif
+
+#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
+static void fbcon_riva1632_revc(struct display *p, int xx, int yy)
+{
+	struct rivafb_info *rinfo = (struct rivafb_info *) (p->fb_info);
+
+	xx *= fontwidth(p);
+	yy *= fontheight(p);
+
+	RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
+	rinfo->riva.Rop->Rop3 = 0x66; // XOR
+	riva_rectfill(rinfo, yy, xx, fontheight(p), fontwidth(p), 0xffffffff);
+	RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
+	rinfo->riva.Rop->Rop3 = 0xCC; // back to COPY
+}
+#endif
+
+#ifdef FBCON_HAS_CFB16
+void fbcon_riva16_setup(struct display *p)
+{
+    p->next_line = p->line_length ? p->line_length : p->var.xres_virtual<<1;
+    p->next_plane = 0;
+}
+
+static void fbcon_riva16_clear(struct vc_data *conp, struct display *p, int sy,
+			     int sx, int height, int width)
+{
+	u32 bgx;
+
+	struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
+
+	bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+
+	sx *= fontwidth(p);
+	sy *= fontheight(p);
+	width *= fontwidth(p);
+	height *= fontheight(p);
+
+	riva_rectfill(rinfo, sy, sx, height, width, bgx);
+}
+
+static inline void convert_bgcolor_16(u32 *col)
+{
+	*col = ((*col & 0x00007C00) << 9)
+             | ((*col & 0x000003E0) << 6)
+             | ((*col & 0x0000001F) << 3)
+             |          0xFF000000;
+}
+
+static void fbcon_riva16_putc(struct vc_data *conp, struct display *p, int c,
+			    int yy, int xx)
+{
+	u32 fgx,bgx;
+
+	fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p,c)];
+	bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p,c)];
+	if (p->var.green.length == 6)
+		convert_bgcolor_16(&bgx);
+	xx *= fontwidth(p);
+	yy *= fontheight(p);
+
+	fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
+}
+
+static void fbcon_riva16_putcs(struct vc_data *conp, struct display *p,
+			     const unsigned short *s, int count, int yy,
+			     int xx)
+{
+	u16 c;
+	u32 fgx,bgx;
+
+	xx *= fontwidth(p);
+	yy *= fontheight(p);
+
+	while (count--) {
+		c = scr_readw(s++);
+		fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p,c)];
+		bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p,c)];
+		if (p->var.green.length == 6)
+			convert_bgcolor_16(&bgx);
+		fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
+		xx += fontwidth(p);
+	}
+}
+
+static void fbcon_riva16_clear_margins(struct vc_data *conp, struct display *p,
+				       int bottom_only)
+{
+	riva_clear_margins(conp, p, bottom_only, ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]);
+}
+
+struct display_switch fbcon_riva16 = {
+	setup:		fbcon_riva16_setup,
+	bmove:		fbcon_riva_bmove,
+	clear:		fbcon_riva16_clear,
+	putc:		fbcon_riva16_putc,
+	putcs:		fbcon_riva16_putcs,
+	revc:		fbcon_riva1632_revc,
+	clear_margins:	fbcon_riva16_clear_margins,
+	fontwidthmask:	FONTWIDTHRANGE(4, 16)
+};
+#endif
+
+#ifdef FBCON_HAS_CFB32
+void fbcon_riva32_setup(struct display *p)
+{
+    p->next_line = p->line_length ? p->line_length : p->var.xres_virtual<<2;
+    p->next_plane = 0;
+}
+
+static void fbcon_riva32_clear(struct vc_data *conp, struct display *p, int sy,
+			     int sx, int height, int width)
+{
+	u32 bgx;
+
+	struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
+
+	bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+
+	sx *= fontwidth(p);
+	sy *= fontheight(p);
+	width *= fontwidth(p);
+	height *= fontheight(p);
+
+	riva_rectfill(rinfo, sy, sx, height, width, bgx);
+}
+
+static void fbcon_riva32_putc(struct vc_data *conp, struct display *p, int c,
+			    int yy, int xx)
+{
+	u32 fgx,bgx;
+
+	fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p,c)];
+	bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
+	xx *= fontwidth(p);
+	yy *= fontheight(p);
+	fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
+}
+
+static void fbcon_riva32_putcs(struct vc_data *conp, struct display *p,
+			     const unsigned short *s, int count, int yy,
+			     int xx)
+{
+	u16 c;
+	u32 fgx,bgx;
+
+	xx *= fontwidth(p);
+	yy *= fontheight(p);
+
+	while (count--) {
+		c = scr_readw(s++);
+		fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p,c)];
+		bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
+		fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
+		xx += fontwidth(p);
+	}
+}
+
+static void fbcon_riva32_clear_margins(struct vc_data *conp, struct display *p,
+				       int bottom_only)
+{
+	riva_clear_margins(conp, p, bottom_only, ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]);
+}
+
+struct display_switch fbcon_riva32 = {
+	setup:		fbcon_riva32_setup,
+	bmove:		fbcon_riva_bmove,
+	clear:		fbcon_riva32_clear,
+	putc:		fbcon_riva32_putc,
+	putcs:		fbcon_riva32_putcs,
+	revc:		fbcon_riva1632_revc,
+	clear_margins:	fbcon_riva32_clear_margins,
+	fontwidthmask:	FONTWIDTHRANGE(4, 16)
+};
+#endif
diff -u --recursive --new-file v2.4.1/linux/drivers/video/riva/fbdev.c linux/drivers/video/riva/fbdev.c
--- v2.4.1/linux/drivers/video/riva/fbdev.c	Tue Nov 14 11:28:39 2000
+++ linux/drivers/video/riva/fbdev.c	Sat Feb  3 12:48:00 2001
@@ -12,6 +12,8 @@
  *
  *	Ferenc Bakonyi:  Bug fixes, cleanup, modularization
  *
+ *	Jindrich Makovicka:  Accel code help, hw cursor, mtrr
+ *
  * Initial template from skeletonfb.c, created 28 Dec 1997 by Geert Uytterhoeven
  * Includes riva_hw.c from nVidia, see copyright below.
  * KGI code provided the basis for state storage, init, and mode switching.
@@ -19,11 +21,13 @@
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file COPYING in the main directory of this archive
  * for more details.
+ *
+ * Known bugs and issues:
+ *	restoring text mode fails
+ *	doublescan modes are broken
+ *	option 'noaccel' has no effect
  */
 
-/* version number of this driver */
-#define RIVAFB_VERSION "0.7.3"
-
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -37,29 +41,31 @@
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-
-#include <video/fbcon.h>
-
-#include "riva_hw.h"
-#include "nv4ref.h"
+#include <linux/console.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+#include "rivafb.h"
 #include "nvreg.h"
-#include "../vga.h"
-#include <video/fbcon-cfb4.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb16.h>
-#include <video/fbcon-cfb32.h>
 
 #ifndef CONFIG_PCI		/* sanity check */
 #error This driver requires PCI support.
 #endif
 
-/*****************************************************************
+
+
+/* version number of this driver */
+#define RIVAFB_VERSION "0.9.2"
+
+
+
+/* ------------------------------------------------------------------------- *
  *
  * various helpful macros and constants
  *
- */
+ * ------------------------------------------------------------------------- */
 
-/* #define RIVAFBDEBUG */
+#undef RIVAFBDEBUG
 #ifdef RIVAFBDEBUG
 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
 #else
@@ -69,31 +75,50 @@
 #ifndef RIVA_NDEBUG
 #define assert(expr) \
 	if(!(expr)) { \
-        printk( "Assertion failed! %s,%s,%s,line=%d\n",\
-        #expr,__FILE__,__FUNCTION__,__LINE__); \
+	printk( "Assertion failed! %s,%s,%s,line=%d\n",\
+	#expr,__FILE__,__FUNCTION__,__LINE__); \
 	BUG(); \
-        }
+	}
 #else
 #define assert(expr)
 #endif
 
-/* GGI compatibility macros */
-#define io_out8			outb
-#define io_in8			inb
-#define NUM_SEQ_REGS		0x05
-#define NUM_CRT_REGS		0x41
-#define NUM_GRC_REGS		0x09
-#define NUM_ATC_REGS		0x15
-
 #define PFX "rivafb: "
 
-#define CNVT_TOHW(val,width)	((((val)<<(width))+0x7FFF-(val))>>16)
-
 /* macro that allows you to set overflow bits */
 #define SetBitField(value,from,to) SetBF(to,GetBF(value,from))
 #define SetBit(n)		(1<<(n))
 #define Set8Bits(value)		((value)&0xff)
 
+/* HW cursor parameters */
+#define DEFAULT_CURSOR_BLINK_RATE	(40)
+#define CURSOR_HIDE_DELAY		(20)
+#define CURSOR_SHOW_DELAY		(3)
+
+#define CURSOR_COLOR		0x7fff
+#define TRANSPARENT_COLOR	0x0000
+#define MAX_CURS		32
+
+
+
+/* ------------------------------------------------------------------------- *
+ *
+ * prototypes
+ *
+ * ------------------------------------------------------------------------- */
+
+static void rivafb_blank(int blank, struct fb_info *info);
+
+extern void riva_setup_accel(struct rivafb_info *rinfo);
+extern inline void wait_for_idle(struct rivafb_info *rinfo);
+
+
+
+/* ------------------------------------------------------------------------- *
+ *
+ * card identification
+ *
+ * ------------------------------------------------------------------------- */
 
 enum riva_chips {
 	CH_RIVA_128 = 0,
@@ -103,187 +128,170 @@
 	CH_RIVA_VTNT2,	/* VTNT2 */
 	CH_RIVA_UVTNT2,	/* VTNT2 */
 	CH_RIVA_ITNT2,	/* ITNT2 */
+	CH_GEFORCE_SDR,
+	CH_GEFORCE_DDR,
+	CH_QUADRO,
+	CH_GEFORCE2_MX,
+	CH_QUADRO2_MXR,
+	CH_GEFORCE2_GTS,
+	CH_GEFORCE2_ULTRA,
+	CH_QUADRO2_PRO,
 };
 
-
 /* directly indexed by riva_chips enum, above */
 static struct riva_chip_info {
 	const char *name;
 	unsigned arch_rev;
 } riva_chip_info[] __devinitdata = {
-	{ "RIVA-128", 3 },
-	{ "RIVA-TNT", 4 },
-	{ "RIVA-TNT2", 5 },
-	{ "RIVA-UTNT2", 5 },
-	{ "RIVA-VTNT2", 5 },
-	{ "RIVA-UVTNT2", 5 },
-	{ "RIVA-ITNT2", 5 },
+	{ "RIVA-128", NV_ARCH_03 },
+	{ "RIVA-TNT", NV_ARCH_04 },
+	{ "RIVA-TNT2", NV_ARCH_04 },
+	{ "RIVA-UTNT2", NV_ARCH_04 },
+	{ "RIVA-VTNT2", NV_ARCH_04 },
+	{ "RIVA-UVTNT2", NV_ARCH_04 },
+	{ "RIVA-ITNT2", NV_ARCH_04 },
+	{ "GeForce-SDR", NV_ARCH_10},
+	{ "GeForce-DDR", NV_ARCH_10},
+	{ "Quadro", NV_ARCH_10},
+	{ "GeForce2-MX", NV_ARCH_10},
+	{ "Quadro2-MXR", NV_ARCH_10},
+	{ "GeForce2-GTS", NV_ARCH_10},
+	{ "GeForce2-ULTRA", NV_ARCH_10},
+	{ "Quadro2-PRO", NV_ARCH_10},
 };
 
-
 static struct pci_device_id rivafb_pci_tbl[] __devinitdata = {
-	{ PCI_VENDOR_ID_NVIDIA_SGS, PCI_DEVICE_ID_NVIDIA_SGS_RIVA128, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_128 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_TNT },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_TNT2 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UTNT2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_UTNT2 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_VTNT2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_VTNT2 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UVTNT2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_VTNT2 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_ITNT2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_ITNT2 },
+	{ PCI_VENDOR_ID_NVIDIA_SGS, PCI_DEVICE_ID_NVIDIA_SGS_RIVA128,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_128 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_TNT },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_TNT2 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UTNT2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_UTNT2 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_VTNT2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_VTNT2 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UVTNT2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_VTNT2 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_ITNT2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_ITNT2 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE_SDR },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE_DDR },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_MX },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_MX },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO2_MXR },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_GTS },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_GTS },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO2_PRO },
 	{ 0, } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);
 
 
-/* holds the state of the VGA core and extended Riva hw state from riva_hw.c.
- * From KGI originally. */
-struct riva_regs {
-	u8 attr[NUM_ATC_REGS];
-	u8 crtc[NUM_CRT_REGS];
-	u8 gra[NUM_GRC_REGS];
-	u8 seq[NUM_SEQ_REGS];
-	u8 misc_output;
-	RIVA_HW_STATE ext;
-};
 
+/* ------------------------------------------------------------------------- *
+ *
+ * framebuffer related structures
+ *
+ * ------------------------------------------------------------------------- */
 
-/*
- * describes the state of a Riva board
- */
+#ifdef FBCON_HAS_CFB8
+struct display_switch fbcon_riva8;
+#endif
+#ifdef FBCON_HAS_CFB16
+struct display_switch fbcon_riva16;
+#endif
+#ifdef FBCON_HAS_CFB32
+struct display_switch fbcon_riva32;
+#endif
+
+#if 0
+/* describes the state of a Riva board */
 struct rivafb_par {
 	struct riva_regs state;	/* state of hw board */
 	__u32 visual;		/* FB_VISUAL_xxx */
 	unsigned depth;		/* bpp of current mode */
 };
-
-typedef struct {
-	unsigned char red, green, blue, transp;
-} riva_cfb8_cmap_t;
-
-
-
-struct rivafb_info;
-struct rivafb_info {
-	struct fb_info info;	/* kernel framebuffer info */
-
-	RIVA_HW_INST riva;	/* interface to riva_hw.c */
-
-	const char *drvr_name;	/* Riva hardware board type */
-
-	unsigned long ctrl_base_phys;	/* physical control register base addr */
-	unsigned long fb_base_phys;	/* physical framebuffer base addr */
-
-	caddr_t ctrl_base;	/* virtual control register base addr */
-	caddr_t fb_base;	/* virtual framebuffer base addr */
-
-	unsigned ram_amount;	/* amount of RAM on card, in bytes */
-	unsigned dclk_max;	/* max DCLK */
-
-	struct riva_regs initial_state;	/* initial startup video mode */
-
-	struct display disp;
-	int currcon;
-	struct display *currcon_display;
-
-	struct rivafb_info *next;
-
-	struct pci_dev *pd;	/* pointer to board's pci info */
-	unsigned base0_region_size;	/* size of control register region */
-	unsigned base1_region_size;	/* size of framebuffer region */
-
-	riva_cfb8_cmap_t palette[256];	/* VGA DAC palette cache */
-
-#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
-	union {
-#ifdef FBCON_HAS_CFB16
-		u_int16_t cfb16[16];
-#endif
-#ifdef FBCON_HAS_CFB32
-		u_int32_t cfb32[16];
 #endif
-	} con_cmap;
-#endif				/* FBCON_HAS_CFB16 | FBCON_HAS_CFB32 */
+
+struct riva_cursor {
+	int enable;
+	int on;
+	int vbl_cnt;
+	int last_move_delay;
+	int blink_rate;
+	struct {
+		u16 x, y;
+	} pos, size;
+	unsigned short image[MAX_CURS*MAX_CURS];
+	struct timer_list *timer;
 };
 
-/* ------------------- global variables ------------------------ */
 
 
-static struct rivafb_info *riva_boards = NULL;
+/* ------------------------------------------------------------------------- *
+ *
+ * global variables
+ *
+ * ------------------------------------------------------------------------- */
+
+struct rivafb_info *riva_boards = NULL;
 
 /* command line data, set in rivafb_setup() */
 static char fontname[40] __initdata = { 0 };
+static char noaccel __initdata = 0;
+static char nomove = 0;
+static char nohwcursor __initdata = 0;
+static char noblink = 0;
+#ifdef CONFIG_MTRR
+static char nomtrr __initdata = 0;
+#endif
+
 #ifndef MODULE
-static char noaccel __initdata = 0;	/* unused */
 static const char *mode_option __initdata = NULL;
+#else
+static char *font = NULL;
 #endif
 
 static struct fb_var_screeninfo rivafb_default_var = {
-	/* 640x480-8@60, yres_virtual=2400 (fits for all Riva cards */
-	640, 480, 640, 2400, 0, 0, 8, 0,
-	{0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
-	0, 0, -1, -1, 0, 39721, 40, 24, 32, 11, 96, 2,
-	0, FB_VMODE_NONINTERLACED
-};
-
-
-/* ------------------- prototypes ------------------------------ */
-
-static int rivafb_get_fix (struct fb_fix_screeninfo *fix, int con,
-		    struct fb_info *info);
-static int rivafb_get_var (struct fb_var_screeninfo *var, int con,
-		    struct fb_info *info);
-static int rivafb_set_var (struct fb_var_screeninfo *var, int con,
-		    struct fb_info *info);
-static int rivafb_get_cmap (struct fb_cmap *cmap, int kspc, int con,
-		     struct fb_info *info);
-static int rivafb_set_cmap (struct fb_cmap *cmap, int kspc, int con,
-		     struct fb_info *info);
-static int rivafb_pan_display (struct fb_var_screeninfo *var, int con,
-			struct fb_info *info);
-static int rivafb_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
-		  unsigned long arg, int con, struct fb_info *info);
-static int rivafb_switch (int con, struct fb_info *info);
-static int rivafb_updatevar (int con, struct fb_info *info);
-static void rivafb_blank (int blank, struct fb_info *info);
-
-static void riva_load_video_mode (struct rivafb_info *rivainfo,
-				  struct fb_var_screeninfo *video_mode);
-static int riva_getcolreg (unsigned regno, unsigned *red, unsigned *green,
-			   unsigned *blue, unsigned *transp,
-			   struct fb_info *info);
-static int riva_setcolreg (unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp,
-			   struct fb_info *info);
-static int riva_get_cmap_len (const struct fb_var_screeninfo *var);
-
-static int riva_set_fbinfo (struct rivafb_info *rinfo);
-
-static void riva_save_state (struct rivafb_info *rinfo, struct riva_regs *regs);
-static void riva_load_state (struct rivafb_info *rinfo, struct riva_regs *regs);
-static struct rivafb_info *riva_board_list_add (struct rivafb_info *board_list,
-					 struct rivafb_info *new_node);
-static struct rivafb_info *riva_board_list_del (struct rivafb_info *board_list,
-					 struct rivafb_info *del_node);
-static void riva_wclut (unsigned char regnum, unsigned char red,
-			unsigned char green, unsigned char blue);
-
-
-
-
-/* kernel interface */
-static struct fb_ops riva_fb_ops = {
-	owner:		THIS_MODULE,
-	fb_get_fix:	rivafb_get_fix,
-	fb_get_var:	rivafb_get_var,
-	fb_set_var:	rivafb_set_var,
-	fb_get_cmap:	rivafb_get_cmap,
-	fb_set_cmap:	rivafb_set_cmap,
-	fb_pan_display:	rivafb_pan_display,
-	fb_ioctl:	rivafb_ioctl,
+	xres:		640,
+	yres:		480,
+	xres_virtual:	640,
+	yres_virtual:	480,
+	xoffset:	0,
+	yoffset:	0,
+	bits_per_pixel:	8,
+	grayscale:	0,
+	red:		{0, 6, 0},
+	green:		{0, 6, 0},
+	blue:		{0, 6, 0},
+	transp:		{0, 0, 0},
+	nonstd:		0,
+	activate:	0,
+	height:		-1,
+	width:		-1,
+	accel_flags:	0,
+	pixclock:	39721,
+	left_margin:	40,
+	right_margin:	24,
+	upper_margin:	32,
+	lower_margin:	11,
+	hsync_len:	96,
+	vsync_len:	2,
+	sync:		0,
+	vmode:		FB_VMODE_NONINTERLACED
 };
 
-
-
-
 /* from GGI */
 static const struct riva_regs reg_template = {
 	{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,	/* ATTR */
@@ -297,425 +305,1003 @@
 	 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 0x30 */
 	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00,			/* 0x40 */
+	 0x00,							/* 0x40 */
 	 },
 	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,	/* GRA  */
 	 0xFF},
-	{0x03, 0x01, 0x0F, 0x00, 0x0E},	/* SEQ  */
-	0xEB			/* MISC */
+	{0x03, 0x01, 0x0F, 0x00, 0x0E},				/* SEQ  */
+	0xEB							/* MISC */
 };
 
 
 
-/* ------------------- general utility functions -------------------------- */
-
-/**
- * riva_set_dispsw
- * @rinfo: pointer to internal driver struct for a given Riva card
+/* ------------------------------------------------------------------------- *
  *
- * DESCRIPTION:
- * Sets up console Low level operations depending on the current? color depth
- * of the display
- */
+ * MMIO access macros
+ *
+ * ------------------------------------------------------------------------- */
 
-static void riva_set_dispsw (struct rivafb_info *rinfo)
+static inline void CRTCout(struct rivafb_info *rinfo, unsigned char index,
+			   unsigned char val)
 {
-	struct display *disp = &rinfo->disp;
+	VGA_WR08(rinfo->riva.PCIO, 0x3d4, index);
+	VGA_WR08(rinfo->riva.PCIO, 0x3d5, val);
+}
 
-	DPRINTK ("ENTER\n");
+static inline unsigned char CRTCin(struct rivafb_info *rinfo,
+				   unsigned char index)
+{
+	VGA_WR08(rinfo->riva.PCIO, 0x3d4, index);
+	return (VGA_RD08(rinfo->riva.PCIO, 0x3d5));
+}
 
-	assert (rinfo != NULL);
+static inline void GRAout(struct rivafb_info *rinfo, unsigned char index,
+			  unsigned char val)
+{
+	VGA_WR08(rinfo->riva.PVIO, 0x3ce, index);
+	VGA_WR08(rinfo->riva.PVIO, 0x3cf, val);
+}
 
-	disp->dispsw_data = NULL;
+static inline unsigned char GRAin(struct rivafb_info *rinfo,
+				  unsigned char index)
+{
+	VGA_WR08(rinfo->riva.PVIO, 0x3ce, index);
+	return (VGA_RD08(rinfo->riva.PVIO, 0x3cf));
+}
 
-	switch (disp->var.bits_per_pixel) {
-#ifdef FBCON_HAS_MFB
-	case 1:
-		disp->dispsw = &fbcon_mfb;
-		break;
-#endif
-#ifdef FBCON_HAS_CFB4
-	case 4:
-		disp->dispsw = &fbcon_cfb4;
-		break;
-#endif
-#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 = &rinfo->con_cmap.cfb16;
-		break;
-#endif
-#ifdef FBCON_HAS_CFB24
-	case 24:
-		disp->dispsw = &fbcon_cfb24;
-		disp->dispsw_data = rinfo->con_cmap.cfb24;
-		break;
-#endif
-#ifdef FBCON_HAS_CFB32
-	case 32:
-		disp->dispsw = &fbcon_cfb32;
-		disp->dispsw_data = rinfo->con_cmap.cfb32;
-		break;
-#endif
-	default:
-		DPRINTK ("Setting fbcon_dummy renderer\n");
-		disp->dispsw = &fbcon_dummy;
-	}
+static inline void SEQout(struct rivafb_info *rinfo, unsigned char index,
+			  unsigned char val)
+{
+	VGA_WR08(rinfo->riva.PVIO, 0x3c4, index);
+	VGA_WR08(rinfo->riva.PVIO, 0x3c5, val);
+}
 
-	DPRINTK ("EXIT\n");
+static inline unsigned char SEQin(struct rivafb_info *rinfo,
+				  unsigned char index)
+{
+	VGA_WR08(rinfo->riva.PVIO, 0x3c4, index);
+	return (VGA_RD08(rinfo->riva.PVIO, 0x3c5));
 }
 
+static inline void ATTRout(struct rivafb_info *rinfo, unsigned char index,
+			   unsigned char val)
+{
+	VGA_WR08(rinfo->riva.PCIO, 0x3c0, index);
+	VGA_WR08(rinfo->riva.PCIO, 0x3c0, val);
+}
 
+static inline unsigned char ATTRin(struct rivafb_info *rinfo,
+				   unsigned char index)
+{
+	VGA_WR08(rinfo->riva.PCIO, 0x3c0, index);
+	return (VGA_RD08(rinfo->riva.PCIO, 0x3c1));
+}
 
+static inline void MISCout(struct rivafb_info *rinfo, unsigned char val)
+{
+	VGA_WR08(rinfo->riva.PVIO, 0x3c2, val);
+}
 
-static int riva_init_disp_var (struct rivafb_info *rinfo)
+static inline unsigned char MISCin(struct rivafb_info *rinfo)
 {
-#ifndef MODULE
-	if (mode_option)
-		fb_find_mode (&rinfo->disp.var, &rinfo->info, mode_option,
-			      NULL, 0, NULL, 8);
-#endif				/* !MODULE */
-	return 0;
+	return (VGA_RD08(rinfo->riva.PVIO, 0x3cc));
 }
 
 
 
+/* ------------------------------------------------------------------------- *
+ *
+ * cursor stuff
+ *
+ * ------------------------------------------------------------------------- */
 
-static int __devinit riva_init_disp (struct rivafb_info *rinfo)
+/**
+ * riva_cursor_timer_handler - blink timer
+ * @dev_addr: pointer to rivafb_info object containing info for current riva board
+ *
+ * DESCRIPTION:
+ * Cursor blink timer.
+ */
+static void riva_cursor_timer_handler(unsigned long dev_addr)
 {
-	struct fb_info *info;
-	struct display *disp;
-
-	DPRINTK ("ENTER\n");
-
-	assert (rinfo != NULL);
+	struct rivafb_info *rinfo = (struct rivafb_info *)dev_addr;
 
-	info = &rinfo->info;
-	disp = &rinfo->disp;
-
-	disp->var = rivafb_default_var;
-	info->disp = disp;
+	if (!rinfo->cursor) return;
 
-	/* FIXME: assure that disp->cmap is completely filled out */
+	if (!rinfo->cursor->enable) goto out;
 
-	disp->screen_base = rinfo->fb_base;
-	disp->visual = FB_VISUAL_PSEUDOCOLOR;
-	disp->type = FB_TYPE_PACKED_PIXELS;
-	disp->type_aux = 0;
-	disp->ypanstep = 1;
-	disp->ywrapstep = 0;
-	disp->next_line = disp->line_length =
-	    (disp->var.xres_virtual * disp->var.bits_per_pixel) >> 3;
-	disp->can_soft_blank = 1;
-	disp->inverse = 0;
+	if (rinfo->cursor->last_move_delay < 1000)
+		rinfo->cursor->last_move_delay++;
 
-	riva_set_dispsw (rinfo);
+	if (rinfo->cursor->vbl_cnt && --rinfo->cursor->vbl_cnt == 0) {
+		rinfo->cursor->on ^= 1;
+		if (rinfo->cursor->on)
+			*(rinfo->riva.CURSORPOS) = (rinfo->cursor->pos.x & 0xFFFF)
+						   | (rinfo->cursor->pos.y << 16);
+		rinfo->riva.ShowHideCursor(&rinfo->riva, rinfo->cursor->on);
+		if (!noblink)
+			rinfo->cursor->vbl_cnt = rinfo->cursor->blink_rate;
+	}
+out:
+	rinfo->cursor->timer->expires = jiffies + (HZ / 100);
+	add_timer(rinfo->cursor->timer);
+}
 
-	disp->scrollmode = 0;
+/**
+ * rivafb_init_cursor - allocates cursor structure and starts blink timer
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
+ *
+ * DESCRIPTION:
+ * Allocates cursor structure and starts blink timer.
+ *
+ * RETURNS:
+ * Pointer to allocated cursor structure.
+ *
+ * CALLED FROM:
+ * rivafb_init_one()
+ */
+static struct riva_cursor * __init rivafb_init_cursor(struct rivafb_info *rinfo)
+{
+	struct riva_cursor *cursor;
 
-	rinfo->currcon_display = disp;
+	cursor = kmalloc(sizeof(struct riva_cursor), GFP_KERNEL);
+	if (!cursor) return 0;
+	memset(cursor, 0, sizeof(*cursor));
 
-	if ((riva_init_disp_var (rinfo)) < 0) {	/* must be done last */
-		DPRINTK ("EXIT, returning -1\n");
-		return -1;
+	cursor->timer = kmalloc(sizeof(*cursor->timer), GFP_KERNEL);
+	if (!cursor->timer) {
+		kfree(cursor);
+		return 0;
 	}
+	memset(cursor->timer, 0, sizeof(*cursor->timer));
 
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
+	cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE;
 
+	init_timer(cursor->timer);
+	cursor->timer->expires = jiffies + (HZ / 100);
+	cursor->timer->data = (unsigned long)rinfo;
+	cursor->timer->function = riva_cursor_timer_handler;
+	add_timer(cursor->timer);
+
+	return cursor;
 }
 
+/**
+ * rivafb_exit_cursor - stops blink timer and releases cursor structure
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
+ *
+ * DESCRIPTION:
+ * Stops blink timer and releases cursor structure.
+ *
+ * CALLED FROM:
+ * rivafb_init_one()
+ * rivafb_remove_one()
+ */
+static void rivafb_exit_cursor(struct rivafb_info *rinfo)
+{
+	struct riva_cursor *cursor = rinfo->cursor;
 
+	if (cursor) {
+		if (cursor->timer) {
+			del_timer_sync(cursor->timer);
+			kfree(cursor->timer);
+		}
+		kfree(cursor);
+		rinfo->cursor = 0;
+	}
+}
 
-static int __devinit riva_set_fbinfo (struct rivafb_info *rinfo)
+/**
+ * rivafb_download_cursor - writes cursor shape into card registers
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
+ *
+ * DESCRIPTION:
+ * Writes cursor shape into card registers.
+ *
+ * CALLED FROM:
+ * riva_load_video_mode()
+ */
+static void rivafb_download_cursor(struct rivafb_info *rinfo)
 {
-	struct fb_info *info;
+	int i, save;
+	int *image;
+	
+	if (!rinfo->cursor) return;
 
-	assert (rinfo != NULL);
+	image = (int *)rinfo->cursor->image;
+	save = rinfo->riva.ShowHideCursor(&rinfo->riva, 0);
+	for (i = 0; i < (MAX_CURS*MAX_CURS*2)/sizeof(int); i++)
+		writel(image[i], rinfo->riva.CURSOR + i);
 
-	info = &rinfo->info;
+	rinfo->riva.ShowHideCursor(&rinfo->riva, save);
+}
 
-	strcpy (info->modename, rinfo->drvr_name);
-	info->node = -1;
-	info->flags = FBINFO_FLAG_DEFAULT;
-	info->fbops = &riva_fb_ops;
+/**
+ * rivafb_create_cursor - sets rectangular cursor
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
+ * @width: cursor width in pixels
+ * @height: cursor height in pixels
+ *
+ * DESCRIPTION:
+ * Sets rectangular cursor.
+ *
+ * CALLED FROM:
+ * rivafb_set_font()
+ * rivafb_set_var()
+ */
+static void rivafb_create_cursor(struct rivafb_info *rinfo, int width, int height)
+{
+	struct riva_cursor *c = rinfo->cursor;
+	int i, j, idx;
 
-	/* FIXME: set monspecs to what??? */
+	if (c) {
+		if (width <= 0 || height <= 0) {
+			width = 8;
+			height = 16;
+		}
+		if (width > MAX_CURS) width = MAX_CURS;
+		if (height > MAX_CURS) height = MAX_CURS;
 
-	info->display_fg = NULL;
-	strncpy (info->fontname, fontname, sizeof (info->fontname));
-	info->fontname[sizeof (info->fontname) - 1] = 0;
+		c->size.x = width;
+		c->size.y = height;
+		
+		idx = 0;
 
-	info->changevar = NULL;
-	info->switch_con = rivafb_switch;
-	info->updatevar = rivafb_updatevar;
-	info->blank = rivafb_blank;
+		for (i = 0; i < height; i++) {
+			for (j = 0; j < width; j++,idx++)
+				c->image[idx] = CURSOR_COLOR;
+			for (j = width; j < MAX_CURS; j++,idx++)
+				c->image[idx] = TRANSPARENT_COLOR;
+		}
+		for (i = height; i < MAX_CURS; i++)
+			for (j = 0; j < MAX_CURS; j++,idx++)
+				c->image[idx] = TRANSPARENT_COLOR;
+	}
+}
 
-	if (riva_init_disp (rinfo) < 0)	/* must be done last */
-		return -1;
+/**
+ * rivafb_set_font - change font size
+ * @p: pointer to display object
+ * @width: font width in pixels
+ * @height: font height in pixels
+ *
+ * DESCRIPTION:
+ * Callback function called if font settings changed.
+ *
+ * RETURNS:
+ * 1 (Always succeeds.)
+ */
+static int rivafb_set_font(struct display *p, int width, int height)
+{
+	struct rivafb_info *fb = (struct rivafb_info *)(p->fb_info);
 
-	return 0;
+	rivafb_create_cursor(fb, width, height);
+	return 1;
 }
 
+/**
+ * rivafb_cursor - cursor handler
+ * @p: pointer to display object
+ * @mode: cursor mode (see CM_*)
+ * @x: cursor x coordinate in characters
+ * @y: cursor y coordinate in characters
+ *
+ * DESCRIPTION:
+ * Cursor handler.
+ */
+static void rivafb_cursor(struct display *p, int mode, int x, int y)
+{
+	struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
+	struct riva_cursor *c = rinfo->cursor;
+
+	if (!c)	return;
 
+	x = x * fontwidth(p) - p->var.xoffset;
+	y = y * fontheight(p) - p->var.yoffset;
+
+	if (c->pos.x == x && c->pos.y == y && (mode == CM_ERASE) == !c->enable)
+		return;
 
+	c->enable = 0;
+	if (c->on) rinfo->riva.ShowHideCursor(&rinfo->riva, 0);
+		
+	c->pos.x = x;
+	c->pos.y = y;
 
-/* ----------------------------- PCI bus ----------------------------- */
+	switch (mode) {
+	case CM_ERASE:
+		c->on = 0;
+		break;
+	case CM_DRAW:
+	case CM_MOVE:
+		if (c->last_move_delay <= 1) { /* rapid cursor movement */
+			c->vbl_cnt = CURSOR_SHOW_DELAY;
+		} else {
+			*(rinfo->riva.CURSORPOS) = (x & 0xFFFF) | (y << 16);
+			rinfo->riva.ShowHideCursor(&rinfo->riva, 1);
+			if (!noblink) c->vbl_cnt = CURSOR_HIDE_DELAY;
+			c->on = 1;
+		}
+		c->last_move_delay = 0;
+		c->enable = 1;
+		break;
+	}
+}
 
 
 
+/* ------------------------------------------------------------------------- *
+ *
+ * general utility functions
+ *
+ * ------------------------------------------------------------------------- */
 
-static int __devinit rivafb_init_one (struct pci_dev *pd,
-				      const struct pci_device_id *ent)
+/**
+ * riva_set_dispsw - sets dispsw
+ * @rinfo: pointer to internal driver struct for a given Riva card
+ * @disp: pointer to display object
+ *
+ * DESCRIPTION:
+ * Sets up console low level operations depending on the current? color depth
+ * of the display.
+ *
+ * CALLED FROM:
+ * rivafb_set_var()
+ * rivafb_switch()
+ * riva_init_disp()
+ */
+static void riva_set_dispsw(struct rivafb_info *rinfo, struct display *disp)
 {
-	struct rivafb_info *rinfo;
-	struct riva_chip_info *rci = &riva_chip_info[ent->driver_data];
+	int accel = disp->var.accel_flags & FB_ACCELF_TEXT;
 
-	assert (pd != NULL);
-	assert (rci != NULL);
+	DPRINTK("ENTER\n");
 
-	rinfo = kmalloc (sizeof (struct rivafb_info), GFP_KERNEL);
-	if (!rinfo)
-		goto err_out;
+	assert(rinfo != NULL);
 
-	memset (rinfo, 0, sizeof (struct rivafb_info));
+	disp->dispsw_data = NULL;
 
-	rinfo->drvr_name = rci->name;
-	rinfo->riva.Architecture = rci->arch_rev;
-
-	rinfo->pd = pd;
-	rinfo->base0_region_size = pci_resource_len (pd, 0);
-	rinfo->base1_region_size = pci_resource_len (pd, 1);
+	disp->screen_base = rinfo->fb_base;
+	disp->type = FB_TYPE_PACKED_PIXELS;
+	disp->type_aux = 0;
+	disp->ypanstep = 1;
+	disp->ywrapstep = 0;
+	disp->can_soft_blank = 1;
+	disp->inverse = 0;
 
-	assert (rinfo->base0_region_size >= 0x00800000);	/* from GGI */
-	assert (rinfo->base1_region_size >= 0x01000000);	/* from GGI */
+	switch (disp->var.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB8
+	case 8:
+		rinfo->dispsw = accel ? fbcon_riva8 : fbcon_cfb8;
+		disp->dispsw = &rinfo->dispsw;
+		disp->line_length = disp->var.xres_virtual;
+		disp->visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB16
+	case 16:
+		rinfo->dispsw = accel ? fbcon_riva16 : fbcon_cfb16;
+		disp->dispsw_data = &rinfo->con_cmap.cfb16;
+		disp->dispsw = &rinfo->dispsw;
+		disp->line_length = disp->var.xres_virtual * 2;
+		disp->visual = FB_VISUAL_DIRECTCOLOR;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB32
+	case 32:
+		rinfo->dispsw = accel ? fbcon_riva32 : fbcon_cfb32;
+		disp->dispsw_data = rinfo->con_cmap.cfb32;
+		disp->dispsw = &rinfo->dispsw;
+		disp->line_length = disp->var.xres_virtual * 4;
+		disp->visual = FB_VISUAL_DIRECTCOLOR;
+		break;
+#endif
+	default:
+		DPRINTK("Setting fbcon_dummy renderer\n");
+		rinfo->dispsw = fbcon_dummy;
+		disp->dispsw = &rinfo->dispsw;
+	}
 
-	rinfo->ctrl_base_phys = pci_resource_start (rinfo->pd, 0);
-	rinfo->fb_base_phys = pci_resource_start (rinfo->pd, 1);
+	/* FIXME: verify that the above code sets dsp->* fields correctly */
 
-	if (!request_mem_region (rinfo->ctrl_base_phys,
-				 rinfo->base0_region_size, "rivafb")) {
-		printk (KERN_ERR PFX "cannot reserve MMIO region\n");
-		goto err_out_kfree;
+	if (rinfo->cursor) {
+		rinfo->dispsw.cursor = rivafb_cursor;
+		rinfo->dispsw.set_font = rivafb_set_font;
 	}
 
-	if (!request_mem_region (rinfo->fb_base_phys,
-				 rinfo->base1_region_size, "rivafb")) {
-		printk (KERN_ERR PFX "cannot reserve FB region\n");
-		goto err_out_free_base0;
+	DPRINTK("EXIT\n");
+}
+
+/**
+ * riva_wclut - set CLUT entry
+ * @chip: pointer to RIVA_HW_INST object
+ * @regnum: register number
+ * @red: red component
+ * @green: green component
+ * @blue: blue component
+ *
+ * DESCRIPTION:
+ * Sets color register @regnum.
+ *
+ * CALLED FROM:
+ * riva_setcolreg()
+ */
+static void riva_wclut(RIVA_HW_INST *chip,
+		       unsigned char regnum, unsigned char red,
+		       unsigned char green, unsigned char blue)
+{
+	VGA_WR08(chip->PDIO, 0x3c8, regnum);
+	VGA_WR08(chip->PDIO, 0x3c9, red);
+	VGA_WR08(chip->PDIO, 0x3c9, green);
+	VGA_WR08(chip->PDIO, 0x3c9, blue);
+}
+
+/**
+ * riva_save_state - saves current chip state
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
+ * @regs: pointer to riva_regs object
+ *
+ * DESCRIPTION:
+ * Saves current chip state to @regs.
+ *
+ * CALLED FROM:
+ * rivafb_init_one()
+ */
+/* from GGI */
+static void riva_save_state(struct rivafb_info *rinfo, struct riva_regs *regs)
+{
+	int i;
+
+	rinfo->riva.LockUnlock(&rinfo->riva, 0);
+
+	rinfo->riva.UnloadStateExt(&rinfo->riva, &regs->ext);
+
+	regs->misc_output = MISCin(rinfo);
+
+	for (i = 0; i < NUM_CRT_REGS; i++) {
+		regs->crtc[i] = CRTCin(rinfo, i);
 	}
 
-	rinfo->ctrl_base = ioremap (rinfo->ctrl_base_phys,
-				    rinfo->base0_region_size);
-	if (!rinfo->ctrl_base) {
-		printk (KERN_ERR PFX "cannot ioremap MMIO base\n");
-		goto err_out_free_base1;
+	for (i = 0; i < NUM_ATC_REGS; i++) {
+		regs->attr[i] = ATTRin(rinfo, i);
 	}
-	
-	rinfo->fb_base = ioremap (rinfo->fb_base_phys,
-				  rinfo->base1_region_size);
-	if (!rinfo->fb_base) {
-		printk (KERN_ERR PFX "cannot ioremap FB base\n");
-		goto err_out_iounmap_ctrl;
+
+	for (i = 0; i < NUM_GRC_REGS; i++) {
+		regs->gra[i] = GRAin(rinfo, i);
 	}
-	
-	rinfo->riva.EnableIRQ = 0;
-	rinfo->riva.IO = (inb (0x3CC) & 0x01) ? 0x3D0 : 0x3B0;
-	rinfo->riva.PRAMDAC = (unsigned *) (rinfo->ctrl_base + 0x00680000);
-	rinfo->riva.PFB = (unsigned *) (rinfo->ctrl_base + 0x00100000);
-	rinfo->riva.PFIFO = (unsigned *) (rinfo->ctrl_base + 0x00002000);
-	rinfo->riva.PGRAPH = (unsigned *) (rinfo->ctrl_base + 0x00400000);
-	rinfo->riva.PEXTDEV = (unsigned *) (rinfo->ctrl_base + 0x00101000);
-	rinfo->riva.PTIMER = (unsigned *) (rinfo->ctrl_base + 0x00009000);
-	rinfo->riva.PMC = (unsigned *) (rinfo->ctrl_base + 0x00000000);
-	rinfo->riva.FIFO = (unsigned *) (rinfo->ctrl_base + 0x00800000);
 
-	switch (rinfo->riva.Architecture) {
-	case 3:
-		rinfo->riva.PRAMIN =
-		    (unsigned *) (rinfo->fb_base + 0x00C00000);
-		break;
-	case 4:
-	case 5:
-		rinfo->riva.PCRTC =
-		    (unsigned *) (rinfo->ctrl_base + 0x00600000);
-		rinfo->riva.PRAMIN =
-		    (unsigned *) (rinfo->ctrl_base + 0x00710000);
-		break;
+	for (i = 0; i < NUM_SEQ_REGS; i++) {
+		regs->seq[i] = SEQin(rinfo, i);
 	}
+}
 
-	RivaGetConfig (&rinfo->riva);
+/**
+ * riva_load_state - loads current chip state
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
+ * @regs: pointer to riva_regs object
+ *
+ * DESCRIPTION:
+ * Loads chip state from @regs.
+ *
+ * CALLED FROM:
+ * riva_load_video_mode()
+ * rivafb_init_one()
+ * rivafb_remove_one()
+ */
+/* from GGI */
+static void riva_load_state(struct rivafb_info *rinfo, struct riva_regs *regs)
+{
+	int i;
+	RIVA_HW_STATE *state = &regs->ext;
 
-	/* back to normal */
+	CRTCout(rinfo, 0x11, 0x00);
 
-	assert (rinfo->pd != NULL);
+	rinfo->riva.LockUnlock(&rinfo->riva, 0);
 
-	/* unlock io */
-	vga_io_wcrt (0x11, 0xFF);	/* vgaHWunlock() + riva unlock (0x7F) */
-	outb (rinfo->riva.LockUnlockIndex, rinfo->riva.LockUnlockIO);
-	outb (0x57, rinfo->riva.LockUnlockIO + 1);
-
-	memcpy (&rinfo->initial_state, &reg_template,
-		sizeof (reg_template));
-	riva_save_state (rinfo, &rinfo->initial_state);
+	rinfo->riva.LoadStateExt(&rinfo->riva, state);
 
-	rinfo->ram_amount = rinfo->riva.RamAmountKBytes * 1024;
-	rinfo->dclk_max = rinfo->riva.MaxVClockFreqKHz * 1000;
+	MISCout(rinfo, regs->misc_output);
 
-	riva_set_fbinfo (rinfo);
+	for (i = 0; i < NUM_CRT_REGS; i++) {
+		switch (i) {
+		case 0x19:
+		case 0x20 ... 0x40:
+			break;
+		default:
+			CRTCout(rinfo, i, regs->crtc[i]);
+		}
+	}
 
-	fb_memset (rinfo->fb_base, 0, rinfo->ram_amount);
+	for (i = 0; i < NUM_ATC_REGS; i++) {
+		ATTRout(rinfo, i, regs->attr[i]);
+	}
 
-	riva_load_video_mode (rinfo, &rinfo->disp.var);
+	for (i = 0; i < NUM_GRC_REGS; i++) {
+		GRAout(rinfo, i, regs->gra[i]);
+	}
 
-	if (register_framebuffer ((struct fb_info *) rinfo) < 0) {
-		printk (KERN_ERR PFX
-			"error registering riva framebuffer\n");
-		goto err_out_iounmap_fb;
+	for (i = 0; i < NUM_SEQ_REGS; i++) {
+		SEQout(rinfo, i, regs->seq[i]);
 	}
+}
 
-	riva_boards = riva_board_list_add(riva_boards, rinfo);
+/**
+ * riva_load_video_mode - calculate timings
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
+ * @video_mode: video mode to set
+ *
+ * DESCRIPTION:
+ * Calculate some timings and then send em off to riva_load_state().
+ *
+ * CALLED FROM:
+ * rivafb_set_var()
+ */
+static void riva_load_video_mode(struct rivafb_info *rinfo,
+				 struct fb_var_screeninfo *video_mode)
+{
+	struct riva_regs newmode;
+	int bpp, width, hDisplaySize, hDisplay, hStart,
+	    hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock;
 
-	pci_set_drvdata (pd, rinfo);
+	/* time to calculate */
 
-	printk (KERN_INFO PFX
-		"PCI Riva NV%d framebuffer ver %s (%s, %dMB @ 0x%lX)\n",
-		rinfo->riva.Architecture,
-		RIVAFB_VERSION,
-		rinfo->drvr_name,
-		rinfo->ram_amount / (1024 * 1024) + 1,
-		rinfo->fb_base_phys);
+	rivafb_blank(1, (struct fb_info *)rinfo);
 
-	return 0;
+	bpp = video_mode->bits_per_pixel;
+	if (bpp == 16 && video_mode->green.length == 5)
+		bpp = 15;
+	width = video_mode->xres_virtual;
+	hDisplaySize = video_mode->xres;
+	hDisplay = (hDisplaySize / 8) - 1;
+	hStart = (hDisplaySize + video_mode->right_margin) / 8 + 2;
+	hEnd = (hDisplaySize + video_mode->right_margin +
+		video_mode->hsync_len) / 8 - 1;
+	hTotal = (hDisplaySize + video_mode->right_margin +
+		  video_mode->hsync_len + video_mode->left_margin) / 8 - 1;
+	height = video_mode->yres_virtual;
+	vDisplay = video_mode->yres - 1;
+	vStart = video_mode->yres + video_mode->lower_margin - 1;
+	vEnd = video_mode->yres + video_mode->lower_margin +
+	       video_mode->vsync_len - 1;
+	vTotal = video_mode->yres + video_mode->lower_margin +
+		 video_mode->vsync_len + video_mode->upper_margin + 2;
+	dotClock = 1000000000 / video_mode->pixclock;
 
-err_out_iounmap_fb:
-	iounmap (rinfo->fb_base);
-err_out_iounmap_ctrl:
-	iounmap (rinfo->ctrl_base);
-err_out_free_base1:
-	release_mem_region (rinfo->fb_base_phys, rinfo->base1_region_size);
-err_out_free_base0:
-	release_mem_region (rinfo->ctrl_base_phys, rinfo->base0_region_size);
-err_out_kfree:
-	kfree (rinfo);
-err_out:
-	return -ENODEV;
+	memcpy(&newmode, &reg_template, sizeof(struct riva_regs));
+
+	newmode.crtc[0x0] = Set8Bits (hTotal - 4);
+	newmode.crtc[0x1] = Set8Bits (hDisplay);
+	newmode.crtc[0x2] = Set8Bits (hDisplay);
+	newmode.crtc[0x3] = SetBitField (hTotal, 4: 0, 4:0) | SetBit (7);
+	newmode.crtc[0x4] = Set8Bits (hStart);
+	newmode.crtc[0x5] = SetBitField (hTotal, 5: 5, 7:7)
+		| SetBitField (hEnd, 4: 0, 4:0);
+	newmode.crtc[0x6] = SetBitField (vTotal, 7: 0, 7:0);
+	newmode.crtc[0x7] = SetBitField (vTotal, 8: 8, 0:0)
+		| SetBitField (vDisplay, 8: 8, 1:1)
+		| SetBitField (vStart, 8: 8, 2:2)
+		| SetBitField (vDisplay, 8: 8, 3:3)
+		| SetBit (4)
+		| SetBitField (vTotal, 9: 9, 5:5)
+		| SetBitField (vDisplay, 9: 9, 6:6)
+		| SetBitField (vStart, 9: 9, 7:7);
+	newmode.crtc[0x9] = SetBitField (vDisplay, 9: 9, 5:5)
+		| SetBit (6);
+	newmode.crtc[0x10] = Set8Bits (vStart);
+	newmode.crtc[0x11] = SetBitField (vEnd, 3: 0, 3:0)
+		| SetBit (5);
+	newmode.crtc[0x12] = Set8Bits (vDisplay);
+	newmode.crtc[0x13] = ((width / 8) * ((bpp + 1) / 8)) & 0xFF;
+	newmode.crtc[0x15] = Set8Bits (vDisplay);
+	newmode.crtc[0x16] = Set8Bits (vTotal + 1);
+
+	newmode.ext.bpp = bpp;
+	newmode.ext.width = width;
+	newmode.ext.height = height;
+
+	rinfo->riva.CalcStateExt(&rinfo->riva, &newmode.ext, bpp, width,
+				  hDisplaySize, hDisplay, hStart, hEnd,
+				  hTotal, height, vDisplay, vStart, vEnd,
+				  vTotal, dotClock);
+
+	rinfo->current_state = newmode;
+	riva_load_state(rinfo, &rinfo->current_state);
+
+	rinfo->riva.LockUnlock(&rinfo->riva, 0); /* important for HW cursor */
+	rivafb_download_cursor(rinfo);
 }
 
+/**
+ * riva_board_list_add - maintains board list
+ * @board_list: root node of list of boards
+ * @new_node: new node to be added
+ *
+ * DESCRIPTION:
+ * Adds @new_node to the list referenced by @board_list.
+ *
+ * RETURNS:
+ * New root node
+ *
+ * CALLED FROM:
+ * rivafb_init_one()
+ */
+static struct rivafb_info *riva_board_list_add(struct rivafb_info *board_list,
+					       struct rivafb_info *new_node)
+{
+	struct rivafb_info *i_p = board_list;
+
+	new_node->next = NULL;
+
+	if (board_list == NULL)
+		return new_node;
+
+	while (i_p->next != NULL)
+		i_p = i_p->next;
+	i_p->next = new_node;
+
+	return board_list;
+}
 
-static void __devexit rivafb_remove_one (struct pci_dev *pd)
+/**
+ * riva_board_list_del - maintains board list
+ * @board_list: root node of list of boards
+ * @del_node: node to be removed
+ *
+ * DESCRIPTION:
+ * Removes @del_node from the list referenced by @board_list.
+ *
+ * RETURNS:
+ * New root node
+ *
+ * CALLED FROM:
+ * rivafb_remove_one()
+ */
+static struct rivafb_info *riva_board_list_del(struct rivafb_info *board_list,
+					       struct rivafb_info *del_node)
 {
-	struct rivafb_info *board = pci_get_drvdata (pd);
-	
-	if (!board)
-		return;
-		
-	riva_boards = riva_board_list_del(riva_boards, board);
+	struct rivafb_info *i_p = board_list;
 
-	riva_load_state (board, &board->initial_state);
+	if (board_list == del_node)
+		return del_node->next;
 
-	unregister_framebuffer ((struct fb_info *) board);
+	while (i_p->next != del_node)
+		i_p = i_p->next;
+	i_p->next = del_node->next;
 
-	iounmap (board->ctrl_base);
-	iounmap (board->fb_base);
+	return board_list;
+}
 
-	release_mem_region (board->ctrl_base_phys,
-			    board->base0_region_size);
-	release_mem_region (board->fb_base_phys,
-			    board->base1_region_size);
+/**
+ * rivafb_do_maximize - 
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
+ * @var:
+ * @v:
+ * @nom:
+ * @den:
+ *
+ * DESCRIPTION:
+ * .
+ *
+ * RETURNS:
+ * -EINVAL on failure, 0 on success
+ * 
+ *
+ * CALLED FROM:
+ * rivafb_set_var()
+ */
+static int rivafb_do_maximize(struct rivafb_info *rinfo,
+			      struct fb_var_screeninfo *var,
+			      struct fb_var_screeninfo *v,
+			      int nom, int den)
+{
+	static struct {
+		int xres, yres;
+	} modes[] = {
+		{1600, 1280},
+		{1280, 1024},
+		{1024, 768},
+		{800, 600},
+		{640, 480},
+		{-1, -1}
+	};
+	int i;
 
-	kfree (board);
+	/* use highest possible virtual resolution */
+	if (v->xres_virtual == -1 && v->yres_virtual == -1) {
+		printk(KERN_WARNING PFX
+		       "using maximum available virtual resolution\n");
+		for (i = 0; modes[i].xres != -1; i++) {
+			if (modes[i].xres * nom / den * modes[i].yres <
+			    rinfo->ram_amount / 2)
+				break;
+		}
+		if (modes[i].xres == -1) {
+			printk(KERN_ERR PFX
+			       "could not find a virtual resolution that fits into video memory!!\n");
+			DPRINTK("EXIT - EINVAL error\n");
+			return -EINVAL;
+		}
+		v->xres_virtual = modes[i].xres;
+		v->yres_virtual = modes[i].yres;
 
-	pci_set_drvdata (pd, NULL);
+		printk(KERN_INFO PFX
+		       "virtual resolution set to maximum of %dx%d\n",
+		       v->xres_virtual, v->yres_virtual);
+	} else if (v->xres_virtual == -1) {
+		v->xres_virtual = (rinfo->ram_amount * den /
+			(nom * v->yres_virtual * 2)) & ~15;
+		printk(KERN_WARNING PFX
+		       "setting virtual X resolution to %d\n", v->xres_virtual);
+	} else if (v->yres_virtual == -1) {
+		v->xres_virtual = (v->xres_virtual + 15) & ~15;
+		v->yres_virtual = rinfo->ram_amount * den /
+			(nom * v->xres_virtual * 2);
+		printk(KERN_WARNING PFX
+		       "setting virtual Y resolution to %d\n", v->yres_virtual);
+	} else {
+		v->xres_virtual = (v->xres_virtual + 15) & ~15;
+		if (v->xres_virtual * nom / den * v->yres_virtual > rinfo->ram_amount) {
+			printk(KERN_ERR PFX
+			       "mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
+			       var->xres, var->yres, var->bits_per_pixel);
+			DPRINTK("EXIT - EINVAL error\n");
+			return -EINVAL;
+		}
+	}
+	
+	if (v->xres_virtual * nom / den >= 8192) {
+		printk(KERN_WARNING PFX
+		       "virtual X resolution (%d) is too high, lowering to %d\n",
+		       v->xres_virtual, 8192 * den / nom - 16);
+		v->xres_virtual = 8192 * den / nom - 16;
+	}
+	
+	if (v->xres_virtual < v->xres) {
+		printk(KERN_ERR PFX
+		       "virtual X resolution (%d) is smaller than real\n", v->xres_virtual);
+		return -EINVAL;
+	}
+
+	if (v->yres_virtual < v->yres) {
+		printk(KERN_ERR PFX
+		       "virtual Y resolution (%d) is smaller than real\n", v->yres_virtual);
+		return -EINVAL;
+	}
+	
+	return 0;
 }
 
 
-/*** riva_wclut - set CLUT entry ***/
-static void riva_wclut (unsigned char regnum, unsigned char red,
-			unsigned char green, unsigned char blue)
+
+/* ------------------------------------------------------------------------- *
+ *
+ * internal fb_ops helper functions
+ *
+ * ------------------------------------------------------------------------- */
+
+/**
+ * riva_get_cmap_len - query current color map length
+ * @var: standard kernel fb changeable data
+ *
+ * DESCRIPTION:
+ * Get current color map length.
+ *
+ * RETURNS:
+ * Length of color map
+ *
+ * CALLED FROM:
+ * riva_getcolreg()
+ * riva_setcolreg()
+ * rivafb_get_cmap()
+ * rivafb_set_cmap()
+ */
+static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
 {
-	unsigned int data = VGA_PEL_D;
+	int rc = 16;		/* reasonable default */
 
-	/* address write mode register is not translated.. */
-	vga_io_w (VGA_PEL_IW, regnum);
+	assert(var != NULL);
+
+	switch (var->bits_per_pixel) {
+#ifdef FBCON_HAS_CFB8
+	case 8:
+		rc = 256;	/* pseudocolor... 256 entries HW palette */
+		break;
+#endif
+#ifdef FBCON_HAS_CFB16
+	case 16:
+		rc = 16;	/* directcolor... 16 entries SW palette */
+		break;		/* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
+#endif
+#ifdef FBCON_HAS_CFB32
+	case 32:
+		rc = 16;	/* directcolor... 16 entries SW palette */
+		break;		/* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
+#endif
+	default:
+		assert(0);
+		/* should not occur */
+		break;
+	}
 
-	vga_io_w (data, red);
-	vga_io_w (data, green);
-	vga_io_w (data, blue);
+	return rc;
 }
 
+/**
+ * riva_getcolreg
+ * @regno: register index
+ * @red: red component
+ * @green: green component
+ * @blue: blue component
+ * @transp: transparency
+ * @info: pointer to rivafb_info object containing info for current riva board
+ *
+ * DESCRIPTION:
+ * Read a single color register and split it into colors/transparent.
+ * The return values must have a 16 bit magnitude.
+ *
+ * RETURNS:
+ * Return != 0 for invalid regno.
+ *
+ * CALLED FROM:
+ * rivafb_get_cmap()
+ * rivafb_switch()
+ * fbcmap.c:fb_get_cmap()
+ *	fbgen.c:fbgen_get_cmap()
+ *	fbgen.c:fbgen_switch()
+ */
+static int riva_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+			  unsigned *blue, unsigned *transp,
+			  struct fb_info *info)
+{
+	struct rivafb_info *rivainfo = (struct rivafb_info *)info;
+
+	if (regno >= riva_get_cmap_len(&rivainfo->currcon_display->var))
+		return 1;
 
+	*red = rivainfo->palette[regno].red;
+	*green = rivainfo->palette[regno].green;
+	*blue = rivainfo->palette[regno].blue;
+	*transp = 0;
 
-/* ------------ Hardware Independent Functions ------------ */
+	return 0;
+}
 
-#ifndef MODULE
-int __init rivafb_setup (char *options)
+/**
+ * riva_setcolreg
+ * @regno: register index
+ * @red: red component
+ * @green: green component
+ * @blue: blue component
+ * @transp: transparency
+ * @info: pointer to rivafb_info object containing info for current riva board
+ *
+ * DESCRIPTION:
+ * Set a single color register. The values supplied have a 16 bit
+ * magnitude.
+ *
+ * RETURNS:
+ * Return != 0 for invalid regno.
+ *
+ * CALLED FROM:
+ * rivafb_set_cmap()
+ * fbcmap.c:fb_set_cmap()
+ *	fbgen.c:fbgen_get_cmap()
+ *	fbgen.c:fbgen_install_cmap()
+ *		fbgen.c:fbgen_set_var()
+ *		fbgen.c:fbgen_switch()
+ *		fbgen.c:fbgen_blank()
+ *	fbgen.c:fbgen_blank()
+ */
+static int riva_setcolreg(unsigned regno, unsigned red, unsigned green,
+			  unsigned blue, unsigned transp,
+			  struct fb_info *info)
 {
-	char *this_opt;
+	struct rivafb_info *rivainfo = (struct rivafb_info *)info;
+	RIVA_HW_INST *chip = &rivainfo->riva;
+	struct display *p;
 
-	if (!options || !*options)
-		return 0;
+	DPRINTK("ENTER\n");
 
-	for (this_opt = strtok (options, ","); this_opt;
-	     this_opt = strtok (NULL, ",")) {
-		if (!strncmp (this_opt, "font:", 5)) {
-			char *p;
-			int i;
+	assert(rivainfo != NULL);
+	assert(rivainfo->currcon_display != NULL);
 
-			p = this_opt + 5;
-			for (i = 0; i < sizeof (fontname) - 1; i++)
-				if (!*p || *p == ' ' || *p == ',')
-					break;
-			memcpy (fontname, this_opt + 5, i);
-			fontname[i] = 0;
-		}
+	p = rivainfo->currcon_display;
 
-		else if (!strncmp (this_opt, "noaccel", 7)) {
-			noaccel = 1;
+	if (regno >= riva_get_cmap_len(&p->var))
+		return -EINVAL;
+
+	rivainfo->palette[regno].red = red;
+	rivainfo->palette[regno].green = green;
+	rivainfo->palette[regno].blue = blue;
+
+	if (p->var.grayscale) {
+		/* gray = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue =
+		    (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	switch (p->var.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB8
+	case 8:
+		/* "transparent" stuff is completely ignored. */
+		riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8);
+		break;
+#endif /* FBCON_HAS_CFB8 */
+#ifdef FBCON_HAS_CFB16
+	case 16:
+		assert(regno < 16);
+		if (p->var.green.length == 5) {
+#ifdef CONFIG_PREP	/* gggbbbbb 0rrrrrgg */
+			rivainfo->con_cmap.cfb16[regno] =
+			    ((red & 0xf800) >> 9) |
+			    ((green & 0xf800) >> 14) |
+			    ((green & 0xf800) << 2) | ((blue & 0xf800) >> 3);
+#else			/* 0rrrrrgg gggbbbbb */
+			rivainfo->con_cmap.cfb16[regno] =
+			    ((red & 0xf800) >> 1) |
+			    ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
+#endif
+		} else {
+#ifdef CONFIG_PREP	/* gggbbbbb rrrrrggg */
+			rivainfo->con_cmap.cfb16[regno] =
+			    ((red & 0xf800) >> 8) |
+			    ((green & 0xfc00) >> 13) |
+			    ((green & 0xfc00) << 3) | ((blue & 0xf800) >> 3);
+#else			/* rrrrrggg gggbbbbb */
+			rivainfo->con_cmap.cfb16[regno] =
+			    ((red & 0xf800) >> 0) |
+			    ((green & 0xf800) >> 5) | ((blue & 0xf800) >> 11);
+#endif
 		}
-
-		else
-			mode_option = this_opt;
+		break;
+#endif /* FBCON_HAS_CFB16 */
+#ifdef FBCON_HAS_CFB32
+	case 32:
+		assert(regno < 16);
+#ifdef CONFIG_PREP
+		rivainfo->con_cmap.cfb32[regno] =
+		    ((red & 0xff00)) |
+		    ((green & 0xff00) << 8) | ((blue & 0xff00) << 16);
+#else
+		rivainfo->con_cmap.cfb32[regno] =
+		    ((red & 0xff00) << 8) |
+		    ((green & 0xff00)) | ((blue & 0xff00) >> 8);
+#endif
+		break;
+#endif /* FBCON_HAS_CFB32 */
+	default:
+		/* do nothing */
+		break;
 	}
+
 	return 0;
 }
-#endif				/* !MODULE */
 
-    /*
-     *  Initialization
-     */
 
-/* ------------------------------------------------------------------------- */
 
+/* ------------------------------------------------------------------------- *
+ *
+ * framebuffer operations
+ *
+ * ------------------------------------------------------------------------- */
 
-    /*
-     *  Frame buffer operations
-     */
-
-static int rivafb_get_fix (struct fb_fix_screeninfo *fix, int con,
-		    struct fb_info *info)
+static int rivafb_get_fix(struct fb_fix_screeninfo *fix, int con,
+			  struct fb_info *info)
 {
-	struct rivafb_info *rivainfo = (struct rivafb_info *) info;
+	struct rivafb_info *rivainfo = (struct rivafb_info *)info;
 	struct display *p;
 
-	DPRINTK ("ENTER\n");
+	DPRINTK("ENTER\n");
 
-	assert (fix != NULL);
-	assert (info != NULL);
-	assert (rivainfo->drvr_name && rivainfo->drvr_name[0]);
-	assert (rivainfo->fb_base_phys > 0);
-	assert (rivainfo->ram_amount > 0);
+	assert(fix != NULL);
+	assert(info != NULL);
+	assert(rivainfo->drvr_name && rivainfo->drvr_name[0]);
+	assert(rivainfo->fb_base_phys > 0);
+	assert(rivainfo->ram_amount > 0);
 
 	p = (con < 0) ? rivainfo->info.disp : &fb_display[con];
 
-	memset (fix, 0, sizeof (struct fb_fix_screeninfo));
-	sprintf (fix->id, "Riva %s", rivainfo->drvr_name);
+	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+	sprintf(fix->id, "nVidia %s", rivainfo->drvr_name);
 
 	fix->smem_start = rivainfo->fb_base_phys;
 	fix->smem_len = rivainfo->ram_amount;
@@ -730,71 +1316,70 @@
 
 	fix->line_length = p->line_length;
 
-	/* FIXME: set up MMIO region, export via FB_ACCEL_xxx */
-	fix->mmio_start = 0;
-	fix->mmio_len = 0;
-	fix->accel = FB_ACCEL_NONE;
+	fix->mmio_start = rivainfo->ctrl_base_phys;
+	fix->mmio_len = rivainfo->base0_region_size;
+	fix->smem_start = rivainfo->fb_base_phys;
+	fix->smem_len = rivainfo->base1_region_size;
+
+	switch (rivainfo->riva.Architecture) {
+	case NV_ARCH_03:
+		fix->accel = FB_ACCEL_NV3;
+		break;
+	case NV_ARCH_04:	/* riva_hw.c now doesn't distinguish between TNT & TNT2 */
+		fix->accel = FB_ACCEL_NV4;
+		break;
+	case NV_ARCH_10:	/* FIXME: ID for GeForce */
+		fix->accel = FB_ACCEL_NV4;
+		break;
+
+	}
 
-	DPRINTK ("EXIT, returning 0\n");
+	DPRINTK("EXIT, returning 0\n");
 
 	return 0;
 }
 
-
-static int rivafb_get_var (struct fb_var_screeninfo *var, int con,
-		    struct fb_info *info)
+static int rivafb_get_var(struct fb_var_screeninfo *var, int con,
+			  struct fb_info *info)
 {
-	struct rivafb_info *rivainfo = (struct rivafb_info *) info;
+	struct rivafb_info *rivainfo = (struct rivafb_info *)info;
 
-	DPRINTK ("ENTER\n");
+	DPRINTK("ENTER\n");
 
-	assert (info != NULL);
-	assert (var != NULL);
+	assert(info != NULL);
+	assert(var != NULL);
 
 	*var = (con < 0) ? rivainfo->disp.var : fb_display[con].var;
 
-	DPRINTK ("EXIT, returning 0\n");
+	DPRINTK("EXIT, returning 0\n");
 
 	return 0;
 }
 
-
-
-static int rivafb_set_var (struct fb_var_screeninfo *var, int con,
-		    struct fb_info *info)
+static int rivafb_set_var(struct fb_var_screeninfo *var, int con,
+			  struct fb_info *info)
 {
-	struct rivafb_info *rivainfo = (struct rivafb_info *) info;
+	struct rivafb_info *rivainfo = (struct rivafb_info *)info;
 	struct display *dsp;
 	struct fb_var_screeninfo v;
 	int nom, den;		/* translating from pixels->bytes */
-	int i;
+	int accel;
 	unsigned chgvar = 0;
-	static struct {
-		int xres, yres;
-	} modes[] = {
-		{
-		1600, 1280}, {
-		1280, 1024}, {
-		1024, 768}, {
-		800, 600}, {
-		640, 480}, {
-		-1, -1}
-	};
 
-	DPRINTK ("ENTER\n");
+	DPRINTK("ENTER\n");
 
-	assert (info != NULL);
-	assert (var != NULL);
+	assert(info != NULL);
+	assert(var != NULL);
 
-	DPRINTK ("Requested: %dx%dx%d\n", var->xres, var->yres,
-		 var->bits_per_pixel);
-	DPRINTK ("  virtual: %dx%d\n", var->xres_virtual,
-		 var->yres_virtual);
-	DPRINTK ("   offset: (%d,%d)\n", var->xoffset, var->yoffset);
-	DPRINTK ("grayscale: %d\n", var->grayscale);
+	DPRINTK("Requested: %dx%dx%d\n", var->xres, var->yres,
+		var->bits_per_pixel);
+	DPRINTK("  virtual: %dx%d\n", var->xres_virtual,
+		var->yres_virtual);
+	DPRINTK("   offset: (%d,%d)\n", var->xoffset, var->yoffset);
+	DPRINTK("grayscale: %d\n", var->grayscale);
 
 	dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
-	assert (dsp != NULL);
+	assert(dsp != NULL);
 
 	/* if var has changed, we should call changevar() later */
 	if (con >= 0) {
@@ -802,78 +1387,76 @@
 			  (dsp->var.yres != var->yres) ||
 			  (dsp->var.xres_virtual != var->xres_virtual) ||
 			  (dsp->var.yres_virtual != var->yres_virtual) ||
+			  (dsp->var.accel_flags != var->accel_flags) ||
 			  (dsp->var.bits_per_pixel != var->bits_per_pixel)
-			  || memcmp (&dsp->var.red, &var->red,
-				     sizeof (var->red))
-			  || memcmp (&dsp->var.green, &var->green,
-				     sizeof (var->green))
-			  || memcmp (&dsp->var.blue, &var->blue,
-				     sizeof (var->blue)));
+			  || memcmp(&dsp->var.red, &var->red,
+				    sizeof(var->red))
+			  || memcmp(&dsp->var.green, &var->green,
+				    sizeof(var->green))
+			  || memcmp(&dsp->var.blue, &var->blue,
+				    sizeof(var->blue)));
 	}
 
-	memcpy (&v, var, sizeof (v));
+	memcpy(&v, var, sizeof(v));
 
-	switch (v.bits_per_pixel) {
-#ifdef FBCON_HAS_MFB
-	case 1:
-		dsp->dispsw = &fbcon_mfb;
-		dsp->line_length = v.xres_virtual / 8;
-		dsp->visual = FB_VISUAL_MONO10;
-		nom = 4;
-		den = 8;
-		break;
-#endif
+	accel = v.accel_flags & FB_ACCELF_TEXT;
 
+	switch (v.bits_per_pixel) {
 #ifdef FBCON_HAS_CFB8
-	case 2 ... 8:
+	case 1 ... 8:
 		v.bits_per_pixel = 8;
-		dsp->dispsw = &fbcon_cfb8;
 		nom = 1;
 		den = 1;
-		dsp->line_length = v.xres_virtual;
-		dsp->visual = FB_VISUAL_PSEUDOCOLOR;
 		v.red.offset = 0;
-		v.red.length = 6;
+		v.red.length = 8;
 		v.green.offset = 0;
-		v.green.length = 6;
+		v.green.length = 8;
 		v.blue.offset = 0;
-		v.blue.length = 6;
+		v.blue.length = 8;
 		break;
 #endif
-
 #ifdef FBCON_HAS_CFB16
-	case 9 ... 16:
+	case 9 ... 15:
+		v.green.length = 5;
+		/* fall through */
+	case 16:
 		v.bits_per_pixel = 16;
-		dsp->dispsw = &fbcon_cfb16;
-		dsp->dispsw_data = &rivainfo->con_cmap.cfb16;
 		nom = 2;
 		den = 1;
-		dsp->line_length = v.xres_virtual * 2;
-		dsp->visual = FB_VISUAL_DIRECTCOLOR;
-#ifdef CONFIG_PREP
-		v.red.offset = 2;
-		v.green.offset = -3;
-		v.blue.offset = 8;
-#else
-		v.red.offset = 10;
-		v.green.offset = 5;
-		v.blue.offset = 0;
-#endif
-		v.red.length = 5;
-		v.green.length = 5;
-		v.blue.length = 5;
+		if (v.green.length == 5) {
+#ifdef CONFIG_PREP			/* gggbbbbb 0rrrrrgg */
+			v.red.offset = 2;
+			v.green.offset = -3;
+			v.blue.offset = 8;
+#else					/* 0rrrrrgg gggbbbbb */
+			v.red.offset = 10;
+			v.green.offset = 5;
+			v.blue.offset = 0;
+#endif
+			v.red.length = 5;
+			v.green.length = 5;
+			v.blue.length = 5;
+		} else {
+#ifdef CONFIG_PREP			/* gggbbbbb rrrrrggg */
+			v.red.offset = 3;
+			v.green.offset = -3;
+			v.blue.offset = 8;
+#else					/* rrrrrggg gggbbbbb */
+			v.red.offset = 11;
+			v.green.offset = 5;
+			v.blue.offset = 0;
+#endif
+			v.red.length = 5;
+			v.green.length = 6;
+			v.blue.length = 5;
+		}
 		break;
 #endif
-
 #ifdef FBCON_HAS_CFB32
 	case 17 ... 32:
 		v.bits_per_pixel = 32;
-		dsp->dispsw = &fbcon_cfb32;
-		dsp->dispsw_data = rivainfo->con_cmap.cfb32;
 		nom = 4;
 		den = 1;
-		dsp->line_length = v.xres_virtual * 4;
-		dsp->visual = FB_VISUAL_DIRECTCOLOR;
 #ifdef CONFIG_PREP
 		v.red.offset = 8;
 		v.green.offset = 16;
@@ -888,49 +1471,16 @@
 		v.blue.length = 8;
 		break;
 #endif
-
 	default:
-		printk (KERN_ERR PFX
-			"mode %dx%dx%d rejected...color depth not supported.\n",
-			var->xres, var->yres, var->bits_per_pixel);
-		DPRINTK ("EXIT, returning -EINVAL\n");
+		printk(KERN_ERR PFX
+		       "mode %dx%dx%d rejected...color depth not supported.\n",
+		       var->xres, var->yres, var->bits_per_pixel);
+		DPRINTK("EXIT, returning -EINVAL\n");
 		return -EINVAL;
 	}
 
-	if (v.xres * nom / den * v.yres > rivainfo->ram_amount) {
-		printk (KERN_ERR PFX
-			"mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
-			var->xres, var->yres, var->bits_per_pixel);
-		DPRINTK ("EXIT - EINVAL error\n");
+	if (rivafb_do_maximize(rivainfo, var, &v, nom, den) < 0)
 		return -EINVAL;
-	}
-
-	/* use highest possible virtual resolution */
-	if (v.xres_virtual == -1 && v.yres_virtual == -1) {
-		printk (KERN_WARNING PFX
-			"using maximum available virtual resolution\n");
-		for (i = 0; modes[i].xres != -1; i++) {
-			if (modes[i].xres * nom / den * modes[i].yres <
-			    rivainfo->ram_amount / 2)
-				break;
-		}
-		if (modes[i].xres == -1) {
-			printk (KERN_ERR PFX
-				"could not find a virtual resolution that fits into video memory!!\n");
-			DPRINTK ("EXIT - EINVAL error\n");
-			return -EINVAL;
-		}
-		v.xres_virtual = modes[i].xres;
-		v.yres_virtual = modes[i].yres;
-
-		printk (KERN_INFO PFX
-			"virtual resolution set to maximum of %dx%d\n",
-			v.xres_virtual, v.yres_virtual);
-	} else if (v.xres_virtual == -1) {
-		/* FIXME: maximize X virtual resolution only */
-	} else if (v.yres_virtual == -1) {
-		/* FIXME: maximize Y virtual resolution only */
-	}
 
 	if (v.xoffset < 0)
 		v.xoffset = 0;
@@ -951,103 +1501,107 @@
 
 	switch (v.activate & FB_ACTIVATE_MASK) {
 	case FB_ACTIVATE_TEST:
-		DPRINTK ("EXIT - FB_ACTIVATE_TEST\n");
+		DPRINTK("EXIT - FB_ACTIVATE_TEST\n");
 		return 0;
 	case FB_ACTIVATE_NXTOPEN:	/* ?? */
 	case FB_ACTIVATE_NOW:
 		break;		/* continue */
 	default:
-		DPRINTK ("EXIT - unknown activation type\n");
+		DPRINTK("EXIT - unknown activation type\n");
 		return -EINVAL;	/* unknown */
 	}
 
-	dsp->type = FB_TYPE_PACKED_PIXELS;
-
-	/* FIXME: verify that the above code sets dsp->* fields correctly */
-
-	memcpy (&dsp->var, &v, sizeof (v));
+	memcpy(&dsp->var, &v, sizeof(v));
+	if (chgvar) {
+		riva_set_dispsw(rivainfo, dsp);
+
+		if (accel) {
+			if (nomove)
+				dsp->scrollmode = SCROLL_YNOMOVE;
+			else
+				dsp->scrollmode = 0;
+		} else
+			dsp->scrollmode = SCROLL_YREDRAW;
+
+		if (info && info->changevar)
+			info->changevar(con);
+	}
+
+	rivafb_create_cursor(rivainfo, fontwidth(dsp), fontheight(dsp));
+	riva_load_video_mode(rivainfo, &v);
+	if (accel) riva_setup_accel(rivainfo);
 
-	riva_load_video_mode (rivainfo, &v);
-
-	if (chgvar && info && info->changevar)
-		info->changevar (con);
-
-	DPRINTK ("EXIT, returning 0\n");
+	DPRINTK("EXIT, returning 0\n");
 	return 0;
 }
 
-
-
-static int rivafb_get_cmap (struct fb_cmap *cmap, int kspc, int con,
-		     struct fb_info *info)
+static int rivafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+			   struct fb_info *info)
 {
-	struct rivafb_info *rivainfo = (struct rivafb_info *) info;
+	struct rivafb_info *rivainfo = (struct rivafb_info *)info;
 	struct display *dsp;
 
-	DPRINTK ("ENTER\n");
+	DPRINTK("ENTER\n");
 
-	assert (rivainfo != NULL);
-	assert (cmap != NULL);
+	assert(rivainfo != NULL);
+	assert(cmap != NULL);
 
 	dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
 
 	if (con == rivainfo->currcon) {	/* current console? */
-		int rc = fb_get_cmap (cmap, kspc, riva_getcolreg, info);
-		DPRINTK ("EXIT - returning %d\n", rc);
+		int rc = fb_get_cmap(cmap, kspc, riva_getcolreg, info);
+		DPRINTK("EXIT - returning %d\n", rc);
 		return rc;
 	} else if (dsp->cmap.len)	/* non default colormap? */
-		fb_copy_cmap (&dsp->cmap, cmap, kspc ? 0 : 2);
+		fb_copy_cmap(&dsp->cmap, cmap, kspc ? 0 : 2);
 	else
-		fb_copy_cmap (fb_default_cmap
-			      (riva_get_cmap_len (&dsp->var)), cmap,
-			      kspc ? 0 : 2);
+		fb_copy_cmap(fb_default_cmap
+			     (riva_get_cmap_len(&dsp->var)), cmap,
+			     kspc ? 0 : 2);
 
-	DPRINTK ("EXIT, returning 0\n");
+	DPRINTK("EXIT, returning 0\n");
 
 	return 0;
 }
 
-
-static int rivafb_set_cmap (struct fb_cmap *cmap, int kspc, int con,
-		     struct fb_info *info)
+static int rivafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+			   struct fb_info *info)
 {
-	struct rivafb_info *rivainfo = (struct rivafb_info *) info;
+	struct rivafb_info *rivainfo = (struct rivafb_info *)info;
 	struct display *dsp;
 	unsigned int cmap_len;
 
-	DPRINTK ("ENTER\n");
-
-	assert (rivainfo != NULL);
-	assert (cmap != NULL);
+	DPRINTK("ENTER\n");
+	
+	assert(rivainfo != NULL);
+	assert(cmap != NULL);
 
 	dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
 
-	cmap_len = riva_get_cmap_len (&dsp->var);
+	cmap_len = riva_get_cmap_len(&dsp->var);
 	if (dsp->cmap.len != cmap_len) {
-		int err = fb_alloc_cmap (&dsp->cmap, cmap_len, 0);
+		int err = fb_alloc_cmap(&dsp->cmap, cmap_len, 0);
 		if (err) {
-			DPRINTK ("EXIT - returning %d\n", err);
+			DPRINTK("EXIT - returning %d\n", err);
 			return err;
 		}
 	}
 	if (con == rivainfo->currcon) {	/* current console? */
-		int rc = fb_set_cmap (cmap, kspc, riva_setcolreg, info);
-		DPRINTK ("EXIT - returning %d\n", rc);
+		int rc = fb_set_cmap(cmap, kspc, riva_setcolreg, info);
+		DPRINTK("EXIT - returning %d\n", rc);
 		return rc;
 	} else
-		fb_copy_cmap (cmap, &dsp->cmap, kspc ? 0 : 1);
+		fb_copy_cmap(cmap, &dsp->cmap, kspc ? 0 : 1);
 
-	DPRINTK ("EXIT, returning 0\n");
+	DPRINTK("EXIT, returning 0\n");
 
 	return 0;
 }
 
-
-
 /**
  * rivafb_pan_display
  * @var: standard kernel fb changeable data
- * @con:
+ * @con: TODO
  * @info: pointer to rivafb_info object containing info for current riva board
  *
  * DESCRIPTION:
@@ -1057,17 +1611,16 @@
  *
  * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
  */
-
-static int rivafb_pan_display (struct fb_var_screeninfo *var, int con,
-			struct fb_info *info)
+static int rivafb_pan_display(struct fb_var_screeninfo *var, int con,
+			      struct fb_info *info)
 {
 	unsigned int base;
 	struct display *dsp;
-	struct rivafb_info *rivainfo = (struct rivafb_info *) info;
+	struct rivafb_info *rivainfo = (struct rivafb_info *)info;
 
-	DPRINTK ("ENTER\n");
+	DPRINTK("ENTER\n");
 
-	assert (rivainfo != NULL);
+	assert(rivainfo != NULL);
 
 	if (var->xoffset > (var->xres_virtual - var->xres))
 		return -EINVAL;
@@ -1089,7 +1642,7 @@
 	base = var->yoffset * dsp->line_length + var->xoffset;
 
 	if (con == rivainfo->currcon) {
-		rivainfo->riva.SetStartAddress (&rivainfo->riva, base);
+		rivainfo->riva.SetStartAddress(&rivainfo->riva, base);
 	}
 
 	dsp->var.xoffset = var->xoffset;
@@ -1100,606 +1653,512 @@
 	else
 		dsp->var.vmode &= ~FB_VMODE_YWRAP;
 
-	DPRINTK ("EXIT, returning 0\n");
+	DPRINTK("EXIT, returning 0\n");
 
 	return 0;
 }
 
-
-static int rivafb_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
-		  unsigned long arg, int con, struct fb_info *info)
+static int rivafb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+			unsigned long arg, int con, struct fb_info *info)
 {
-	struct rivafb_info *rivainfo = (struct rivafb_info *) info;
+	struct rivafb_info *rivainfo = (struct rivafb_info *)info;
 
-	DPRINTK ("ENTER\n");
+	DPRINTK("ENTER\n");
 
-	assert (rivainfo != NULL);
+	assert(rivainfo != NULL);
 
 	/* no rivafb-specific ioctls */
 
-	DPRINTK ("EXIT, returning -EINVAL\n");
+	DPRINTK("EXIT, returning -EINVAL\n");
 
 	return -EINVAL;
 }
 
+static int rivafb_rasterimg(struct fb_info *info, int start)
+{
+	struct rivafb_info *rinfo = (struct rivafb_info *)info;
+
+	wait_for_idle(rinfo);
+
+	return 0;
+}
 
-static int rivafb_switch (int con, struct fb_info *info)
+static int rivafb_switch(int con, struct fb_info *info)
 {
-	struct rivafb_info *rivainfo = (struct rivafb_info *) info;
+	struct rivafb_info *rivainfo = (struct rivafb_info *)info;
 	struct fb_cmap *cmap;
 	struct display *dsp;
-
-	DPRINTK ("ENTER\n");
-
-	assert (rivainfo != NULL);
+	
+	DPRINTK("ENTER\n");
+	
+	assert(rivainfo != NULL);
 
 	dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
 
 	if (rivainfo->currcon >= 0) {
 		/* Do we have to save the colormap? */
 		cmap = &(rivainfo->currcon_display->cmap);
-		DPRINTK ("switch1: con = %d, cmap.len = %d\n",
+		DPRINTK("switch1: con = %d, cmap.len = %d\n",
 			 rivainfo->currcon, cmap->len);
 
 		if (cmap->len) {
-			DPRINTK ("switch1a: %p %p %p %p\n", cmap->red,
+			DPRINTK("switch1a: %p %p %p %p\n", cmap->red,
 				 cmap->green, cmap->blue, cmap->transp);
-			fb_get_cmap (cmap, 1, riva_getcolreg, info);
-#ifdef DEBUG
-			if (cmap->red) {
-				DPRINTK ("switch1r: %X\n", cmap->red[0]);
-			}
-#endif
+			fb_get_cmap(cmap, 1, riva_getcolreg, info);
 		}
 	}
 	rivainfo->currcon = con;
 	rivainfo->currcon_display = dsp;
-	dsp->var.activate = FB_ACTIVATE_NOW;
-
-#ifdef riva_DEBUG
-	cmap = &dsp->cmap;
-	DPRINTK ("switch2: con = %d, cmap.len = %d\n", con, cmap->len);
-	DPRINTK ("switch2a: %p %p %p %p\n", cmap->red, cmap->green,
-		 cmap->blue, cmap->transp);
-	if (dsp->cmap.red) {
-		DPRINTK ("switch2r: %X\n", cmap->red[0]);
-	}
-#endif
 
-	rivafb_set_var (&dsp->var, con, info);
-
-#ifdef riva_DEBUG
-	DPRINTK ("switch3: con = %d, cmap.len = %d\n", con, cmap->len);
-	DPRINTK ("switch3a: %p %p %p %p\n", cmap->red, cmap->green,
-		 cmap->blue, cmap->transp);
-	if (dsp->cmap.red) {
-		DPRINTK ("switch3r: %X\n", cmap->red[0]);
-	}
-#endif
+	rivafb_set_var(&dsp->var, con, info);
+	riva_set_dispsw(rivainfo, dsp);
 
-	DPRINTK ("EXIT, returning 0\n");
+	DPRINTK("EXIT, returning 0\n");
 	return 0;
 }
 
-static int rivafb_updatevar (int con, struct fb_info *info)
+static int rivafb_updatevar(int con, struct fb_info *info)
 {
 	int rc;
 
-	DPRINTK ("ENTER\n");
+	DPRINTK("ENTER\n");
 
-	rc = (con <
-		0) ? -EINVAL : rivafb_pan_display (&fb_display[con].var,
-						   con, info);
-	DPRINTK ("EXIT, returning %d\n", rc);
+	rc = (con < 0) ? -EINVAL : rivafb_pan_display(&fb_display[con].var,
+						      con, info);
+	DPRINTK("EXIT, returning %d\n", rc);
 	return rc;
 }
 
-
-static void rivafb_blank (int blank, struct fb_info *info)
+static void rivafb_blank(int blank, struct fb_info *info)
 {
-	unsigned char tmp;
-	struct rivafb_info *rivainfo = (struct rivafb_info *) info;
-
-	DPRINTK ("ENTER\n");
-
-	assert (rivainfo != NULL);
-
-	tmp = vga_io_rseq (VGA_SEQ_CLOCK_MODE) & ~VGA_SR01_SCREEN_OFF;
-
-	if (blank)
-		tmp |= VGA_SR01_SCREEN_OFF;
-
-	vga_io_wseq (VGA_SEQ_CLOCK_MODE, tmp);
-
-	DPRINTK ("EXIT\n");
-}
-
-
-/* -------------------------------------------------------------------------
- *
- * internal fb_ops helper functions
- *
- * -------------------------------------------------------------------------
- */
-
+	unsigned char tmp, vesa;
+	struct rivafb_info *rinfo = (struct rivafb_info *)info;
 
-/**
- * riva_get_cmap_len
- * @var:
- *
- * DESCRIPTION:
- */
-
-static int riva_get_cmap_len (const struct fb_var_screeninfo *var)
-{
-	int rc = 16;		/* reasonable default */
+	DPRINTK("ENTER\n");
 
-	assert (var != NULL);
+	assert(rinfo != NULL);
 
-	switch (var->bits_per_pixel) {
-#ifdef FBCON_HAS_CFB4
-	case 4:
-		rc = 16;	/* pseudocolor... 16 entries HW palette */
-		break;
-#endif
-#ifdef FBCON_HAS_CFB8
-	case 8:
-		rc = 256;	/* pseudocolor... 256 entries HW palette */
-		break;
-#endif
-#ifdef FBCON_HAS_CFB16
-	case 16:
-		rc = 16;	/* directcolor... 16 entries SW palette */
-		break;		/* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
-#endif
-#ifdef FBCON_HAS_CFB32
-	case 32:
-		rc = 16;	/* directcolor... 16 entries SW palette */
-		break;		/* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
-#endif
-	default:
-		assert (0);
-		/* should not occur */
-		break;
+	tmp = SEQin(rinfo, 0x01) & ~0x20;	/* screen on/off */
+	vesa = CRTCin(rinfo, 0x1a) & ~0xc0;	/* sync on/off */
+
+	if (blank) {
+		tmp |= 0x20;
+		switch (blank - 1) {
+		case VESA_NO_BLANKING:
+			break;
+		case VESA_VSYNC_SUSPEND:
+			vesa |= 0x80;
+			break;
+		case VESA_HSYNC_SUSPEND:
+			vesa |= 0x40;
+			break;
+		case VESA_POWERDOWN:
+			vesa |= 0xc0;
+			break;
+		}
 	}
 
-	return rc;
-}
-
-
-/**
- * riva_getcolreg
- * @regno:
- * @red:
- * @green:
- * @blue:
- * @transp:
- * @info: pointer to rivafb_info object containing info for current riva board
- *
- * DESCRIPTION:
- * Read a single color register and split it into colors/transparent.
- * The return values must have a 16 bit magnitude.
- * Return != 0 for invalid regno.
- *
- * CALLED FROM:
- * fbcmap.c:fb_get_cmap()
- *	fbgen.c:fbgen_get_cmap()
- *	fbgen.c:fbgen_switch()
- */
-
-static int riva_getcolreg (unsigned regno, unsigned *red, unsigned *green,
-			   unsigned *blue, unsigned *transp,
-			   struct fb_info *info)
-{
-	struct rivafb_info *rivainfo = (struct rivafb_info *) info;
-
-	if (regno >= riva_get_cmap_len(&rivainfo->currcon_display->var))
-		return 1;
-
-	*red = rivainfo->palette[regno].red;
-	*green = rivainfo->palette[regno].green;
-	*blue = rivainfo->palette[regno].blue;
-	*transp = 0;
+	SEQout(rinfo, 0x01, tmp);
+	CRTCout(rinfo, 0x1a, vesa);
 
-	return 0;
+	DPRINTK("EXIT\n");
 }
 
 
-/**
- * riva_setcolreg
- * @regno:
- * @red:
- * @green:
- * @blue:
- * @transp:
- * @info: pointer to rivafb_info object containing info for current riva board
+
+/* ------------------------------------------------------------------------- *
  *
- * DESCRIPTION:
- * Set a single color register. The values supplied have a 16 bit
- * magnitude.
- * Return != 0 for invalid regno.
+ * initialization helper functions
  *
- * CALLED FROM:
- * fbcmap.c:fb_set_cmap()
- *	fbgen.c:fbgen_get_cmap()
- *	fbgen.c:fbgen_install_cmap()
- *		fbgen.c:fbgen_set_var()
- *		fbgen.c:fbgen_switch()
- *		fbgen.c:fbgen_blank()
- *	fbgen.c:fbgen_blank()
- */
-
-static int riva_setcolreg (unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp,
-			   struct fb_info *info)
-{
-	struct rivafb_info *rivainfo = (struct rivafb_info *) info;
-	struct display *p;
-	unsigned shift = 8;
-
-	DPRINTK ("ENTER\n");
-
-	assert (rivainfo != NULL);
-	assert (rivainfo->currcon_display != NULL);
-
-	p = rivainfo->currcon_display;
-
-	if (regno >= riva_get_cmap_len(&p->var))
-		return -EINVAL;
-
-	rivainfo->palette[regno].red = red;
-	rivainfo->palette[regno].green = green;
-	rivainfo->palette[regno].blue = blue;
-
-	if (p->var.grayscale) {
-		/* gray = 0.30*R + 0.59*G + 0.11*B */
-		red = green = blue =
-		    (red * 77 + green * 151 + blue * 28) >> 8;
-	}
-
-	switch (rivainfo->riva.Architecture) {
-	case 3:
-		shift = 10;
-		break;
-	case 4:
-	case 5:
-		shift = 8;
-		break;
-	}
-
-	switch (p->var.bits_per_pixel) {
-#ifdef FBCON_HAS_CFB8
-	case 8:
-		/* "transparent" stuff is completely ignored. */
-		riva_wclut (regno, red >> shift, green >> shift, blue >> shift);
-		break;
-#endif				/* FBCON_HAS_CFB8 */
-
-#ifdef FBCON_HAS_CFB16
-	case 16:
-		assert (regno < 16);
-#ifdef CONFIG_PREP
-		rivainfo->con_cmap.cfb16[regno] =
-		    ((red & 0xf800) >> 9) |
-		    ((green & 0xf800) >> 14) |
-		    ((green & 0xf800) << 2) | ((blue & 0xf800) >> 3);
-#else
-		rivainfo->con_cmap.cfb16[regno] =
-		    ((red & 0xf800) >> 1) |
-		    ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
-#endif
-		break;
-#endif				/* FBCON_HAS_CFB16 */
-
-#ifdef FBCON_HAS_CFB32
-	case 32:
-		assert (regno < 16);
-#ifdef CONFIG_PREP
-		rivainfo->con_cmap.cfb32[regno] =
-		    ((red & 0xff00)) |
-		    ((green & 0xff00) << 8) | ((blue & 0xff00) << 16);
-#else
-		rivainfo->con_cmap.cfb32[regno] =
-		    ((red & 0xff00) << 8) |
-		    ((green & 0xff00)) | ((blue & 0xff00) >> 8);
-#endif
-		break;
-#endif				/* FBCON_HAS_CFB32 */
+ * ------------------------------------------------------------------------- */
 
-	default:
-		/* do nothing */
-		break;
-	}
+/* kernel interface */
+static struct fb_ops riva_fb_ops = {
+	owner:		THIS_MODULE,
+	fb_get_fix:	rivafb_get_fix,
+	fb_get_var:	rivafb_get_var,
+	fb_set_var:	rivafb_set_var,
+	fb_get_cmap:	rivafb_get_cmap,
+	fb_set_cmap:	rivafb_set_cmap,
+	fb_pan_display:	rivafb_pan_display,
+	fb_ioctl:	rivafb_ioctl,
+	fb_rasterimg:	rivafb_rasterimg,
+};
 
+static int __devinit riva_init_disp_var(struct rivafb_info *rinfo)
+{
+#ifndef MODULE
+	if (mode_option)
+		fb_find_mode(&rinfo->disp.var, &rinfo->info, mode_option,
+			     NULL, 0, NULL, 8);
+#endif
 	return 0;
 }
 
+static int __devinit riva_init_disp(struct rivafb_info *rinfo)
+{
+	struct fb_info *info;
+	struct display *disp;
 
+	DPRINTK("ENTER\n");
 
-/*
- * riva_load_video_mode()
- *
- * calculate some timings and then send em off to riva_load_state()
- */
+	assert(rinfo != NULL);
 
-static void riva_load_video_mode (struct rivafb_info *rinfo,
-				  struct fb_var_screeninfo *video_mode)
-{
-	struct riva_regs newmode;
-	int bpp, width, hDisplaySize, hDisplay, hStart,
-	    hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock;
+	info = &rinfo->info;
+	disp = &rinfo->disp;
 
-	/* time to calculate */
+	disp->var = rivafb_default_var;
+	
+	if (noaccel)
+		disp->var.accel_flags &= ~FB_ACCELF_TEXT;
+	else
+		disp->var.accel_flags |= FB_ACCELF_TEXT;
+	
+	info->disp = disp;
 
-	bpp = video_mode->bits_per_pixel;
-	width = hDisplaySize = video_mode->xres;
-	hDisplay = (hDisplaySize / 8) - 1;
-	hStart = (hDisplaySize + video_mode->right_margin) / 8 + 2;
-	hEnd = (hDisplaySize + video_mode->right_margin +
-		video_mode->hsync_len) / 8 - 1;
-	hTotal = (hDisplaySize + video_mode->right_margin +
-		  video_mode->hsync_len + video_mode->left_margin) / 8 - 1;
-	height = video_mode->yres;
-	vDisplay = video_mode->yres - 1;
-	vStart = video_mode->yres + video_mode->lower_margin - 1;
-	vEnd = video_mode->yres + video_mode->lower_margin +
-	    video_mode->vsync_len - 1;
-	vTotal = video_mode->yres + video_mode->lower_margin +
-	    video_mode->vsync_len + video_mode->upper_margin + 2;
-	dotClock = 1000000000 / video_mode->pixclock;
+	/* FIXME: assure that disp->cmap is completely filled out */
 
-	memcpy (&newmode, &reg_template, sizeof (struct riva_regs));
+	rinfo->currcon_display = disp;
 
-	newmode.crtc[0x0] = Set8Bits (hTotal - 4);
-	newmode.crtc[0x1] = Set8Bits (hDisplay);
-	newmode.crtc[0x2] = Set8Bits (hDisplay);
-	newmode.crtc[0x3] = SetBitField (hTotal, 4: 0, 4:0) | SetBit (7);
-	newmode.crtc[0x4] = Set8Bits (hStart);
-	newmode.crtc[0x5] = SetBitField (hTotal, 5: 5, 7:7)
-		| SetBitField (hEnd, 4: 0, 4:0);
-	newmode.crtc[0x6] = SetBitField (vTotal, 7: 0, 7:0);
-	newmode.crtc[0x7] = SetBitField (vTotal, 8: 8, 0:0)
-		| SetBitField (vDisplay, 8: 8, 1:1)
-		| SetBitField (vStart, 8: 8, 2:2)
-		| SetBitField (vDisplay, 8: 8, 3:3)
-		| SetBit (4)
-		| SetBitField (vTotal, 9: 9, 5:5)
-		| SetBitField (vDisplay, 9: 9, 6:6)
-		| SetBitField (vStart, 9: 9, 7:7);
-	newmode.crtc[0x9] = SetBitField (vDisplay, 9: 9, 5:5)
-		| SetBit (6);
-	newmode.crtc[0x10] = Set8Bits (vStart);
-	newmode.crtc[0x11] = SetBitField (vEnd, 3: 0, 3:0)
-		| SetBit (5);
-	newmode.crtc[0x12] = Set8Bits (vDisplay);
-	newmode.crtc[0x13] = ((width / 8) * (bpp / 8)) & 0xFF;
-	newmode.crtc[0x15] = Set8Bits (vDisplay);
-	newmode.crtc[0x16] = Set8Bits (vTotal + 1);
+	if ((riva_init_disp_var(rinfo)) < 0) {
+		DPRINTK("EXIT, returning -1\n");
+		return -1;
+	}
 
-	newmode.ext.bpp = bpp;
-	newmode.ext.width = width;
-	newmode.ext.height = height;
+	riva_set_dispsw(rinfo, disp);
 
-	rinfo->riva.CalcStateExt (&rinfo->riva, &newmode.ext, bpp, width,
-				  hDisplaySize, hDisplay, hStart, hEnd,
-				  hTotal, height, vDisplay, vStart, vEnd,
-				  vTotal, dotClock);
+	DPRINTK("EXIT, returning 0\n");
+	return 0;
 
-	rinfo->initial_state = newmode;
-	riva_load_state (rinfo, &newmode);
 }
 
+static int __devinit riva_set_fbinfo(struct rivafb_info *rinfo)
+{
+	struct fb_info *info;
 
-/* ------------------------------------------------------------------------- */
+	assert(rinfo != NULL);
 
+	info = &rinfo->info;
 
-    /*
-     *  Modularization
-     */
+	strcpy(info->modename, rinfo->drvr_name);
+	info->node = -1;
+	info->flags = FBINFO_FLAG_DEFAULT;
+	info->fbops = &riva_fb_ops;
 
-static struct pci_driver rivafb_driver = {
-	name:		"rivafb",
-	id_table:	rivafb_pci_tbl,
-	probe:		rivafb_init_one,
-	remove:		rivafb_remove_one,
-};
+	/* FIXME: set monspecs to what??? */
 
+	info->display_fg = NULL;
+	strncpy(info->fontname, fontname, sizeof(info->fontname));
+	info->fontname[sizeof(info->fontname) - 1] = 0;
 
-int __init rivafb_init (void)
-{
-	return pci_module_init (&rivafb_driver);
-}
+	info->changevar = NULL;
+	info->switch_con = rivafb_switch;
+	info->updatevar = rivafb_updatevar;
+	info->blank = rivafb_blank;
 
+	if (riva_init_disp(rinfo) < 0)	/* must be done last */
+		return -1;
 
-static void __exit rivafb_exit (void)
-{
-	pci_unregister_driver (&rivafb_driver);
+	return 0;
 }
 
 
-#ifdef MODULE
-module_init(rivafb_init);
-#endif				/* MODULE */
-module_exit(rivafb_exit);
-
-MODULE_AUTHOR("Ani Joshi, maintainer");
-MODULE_DESCRIPTION("Framebuffer driver for nVidia Riva 128, TNT, TNT2");
 
+/* ------------------------------------------------------------------------- *
+ *
+ * PCI bus
+ *
+ * ------------------------------------------------------------------------- */
 
-/* from GGI */
-static void riva_save_state (struct rivafb_info *rinfo, struct riva_regs *regs)
+static int __devinit rivafb_init_one(struct pci_dev *pd,
+				     const struct pci_device_id *ent)
 {
-	int i;
+	struct rivafb_info *rinfo;
+	struct riva_chip_info *rci = &riva_chip_info[ent->driver_data];
 
-	outb (rinfo->riva.LockUnlockIndex, rinfo->riva.LockUnlockIO);
-	outb (0x57, rinfo->riva.LockUnlockIO + 1);
+	assert(pd != NULL);
+	assert(rci != NULL);
 
-	rinfo->riva.UnloadStateExt (&rinfo->riva, &regs->ext);
+	rinfo = kmalloc(sizeof(struct rivafb_info), GFP_KERNEL);
+	if (!rinfo)
+		goto err_out;
 
-	regs->misc_output = io_in8 (0x3CC);
+	memset(rinfo, 0, sizeof(struct rivafb_info));
 
-	for (i = 0; i < NUM_CRT_REGS; i++) {
-		io_out8 (i, 0x3D4);
-		regs->crtc[i] = io_in8 (0x3D5);
-	}
+	rinfo->drvr_name = rci->name;
+	rinfo->riva.Architecture = rci->arch_rev;
 
-	for (i = 0; i < NUM_ATC_REGS; i++) {
-		io_out8 (i, 0x3C0);
-		regs->attr[i] = io_in8 (0x3C1);
+	rinfo->pd = pd;
+	rinfo->base0_region_size = pci_resource_len(pd, 0);
+	rinfo->base1_region_size = pci_resource_len(pd, 1);
+
+	assert(rinfo->base0_region_size >= 0x00800000);	/* from GGI */
+	assert(rinfo->base1_region_size >= 0x01000000);	/* from GGI */
+
+	rinfo->ctrl_base_phys = pci_resource_start(rinfo->pd, 0);
+	rinfo->fb_base_phys = pci_resource_start(rinfo->pd, 1);
+
+	if (!request_mem_region(rinfo->ctrl_base_phys,
+				rinfo->base0_region_size, "rivafb")) {
+		printk(KERN_ERR PFX "cannot reserve MMIO region\n");
+		goto err_out_kfree;
 	}
 
-	for (i = 0; i < NUM_GRC_REGS; i++) {
-		io_out8 (i, 0x3CE);
-		regs->gra[i] = io_in8 (0x3CF);
+	if (!request_mem_region(rinfo->fb_base_phys,
+				rinfo->base1_region_size, "rivafb")) {
+		printk(KERN_ERR PFX "cannot reserve FB region\n");
+		goto err_out_free_base0;
+	}
+	
+	rinfo->ctrl_base = ioremap(rinfo->ctrl_base_phys,
+				   rinfo->base0_region_size);
+	if (!rinfo->ctrl_base) {
+		printk(KERN_ERR PFX "cannot ioremap MMIO base\n");
+		goto err_out_free_base1;
+	}
+	
+	rinfo->fb_base = ioremap(rinfo->fb_base_phys,
+				 rinfo->base1_region_size);
+	if (!rinfo->fb_base) {
+		printk(KERN_ERR PFX "cannot ioremap FB base\n");
+		goto err_out_iounmap_ctrl;
+	}
+	
+#ifdef CONFIG_MTRR
+	if (!nomtrr) {
+		rinfo->mtrr.vram = mtrr_add(rinfo->fb_base_phys,
+					    rinfo->base1_region_size, MTRR_TYPE_WRCOMB, 1);
+		if (rinfo->mtrr.vram < 0) {
+			printk(KERN_ERR PFX "unable to setup MTRR\n");
+		} else {
+			rinfo->mtrr.vram_valid = 1;
+			/* let there be speed */
+			printk(KERN_INFO PFX "RIVA MTRR set to ON\n");
+		}
 	}
+#endif /* CONFIG_MTRR */
 
+	rinfo->riva.EnableIRQ = 0;
+	rinfo->riva.PRAMDAC = (unsigned *)(rinfo->ctrl_base + 0x00680000);
+	rinfo->riva.PFB = (unsigned *)(rinfo->ctrl_base + 0x00100000);
+	rinfo->riva.PFIFO = (unsigned *)(rinfo->ctrl_base + 0x00002000);
+	rinfo->riva.PGRAPH = (unsigned *)(rinfo->ctrl_base + 0x00400000);
+	rinfo->riva.PEXTDEV = (unsigned *)(rinfo->ctrl_base + 0x00101000);
+	rinfo->riva.PTIMER = (unsigned *)(rinfo->ctrl_base + 0x00009000);
+	rinfo->riva.PMC = (unsigned *)(rinfo->ctrl_base + 0x00000000);
+	rinfo->riva.FIFO = (unsigned *)(rinfo->ctrl_base + 0x00800000);
+
+	rinfo->riva.PCIO = (U008 *)(rinfo->ctrl_base + 0x00601000);
+	rinfo->riva.PDIO = (U008 *)(rinfo->ctrl_base + 0x00681000);
+	rinfo->riva.PVIO = (U008 *)(rinfo->ctrl_base + 0x000C0000);
 
-	for (i = 0; i < NUM_SEQ_REGS; i++) {
-		io_out8 (i, 0x3C4);
-		regs->seq[i] = io_in8 (0x3C5);
+	rinfo->riva.IO = (MISCin(rinfo) & 0x01) ? 0x3D0 : 0x3B0;
+
+	switch (rinfo->riva.Architecture) {
+	case NV_ARCH_03:
+		rinfo->riva.PRAMIN = (unsigned *)(rinfo->fb_base + 0x00C00000);
+		break;
+	case NV_ARCH_04:
+	case NV_ARCH_10:
+		rinfo->riva.PCRTC = (unsigned *)(rinfo->ctrl_base + 0x00600000);
+		rinfo->riva.PRAMIN = (unsigned *)(rinfo->ctrl_base + 0x00710000);
+		break;
 	}
-}
 
+	RivaGetConfig(&rinfo->riva);
 
-/* from GGI */
-static
-void riva_load_state (struct rivafb_info *rinfo, struct riva_regs *regs)
-{
-	int i;
-	RIVA_HW_STATE *state = &regs->ext;
+	/* back to normal */
 
-	io_out8 (0x11, 0x3D4);
-	io_out8 (0x00, 0x3D5);
+	assert(rinfo->pd != NULL);
 
-	outb (rinfo->riva.LockUnlockIndex, rinfo->riva.LockUnlockIO);
-	outb (0x57, rinfo->riva.LockUnlockIO + 1);
+	/* unlock io */
+	CRTCout(rinfo, 0x11, 0xFF);	/* vgaHWunlock() + riva unlock (0x7F) */
+	rinfo->riva.LockUnlock(&rinfo->riva, 0);
 
-	rinfo->riva.LoadStateExt (&rinfo->riva, state);
+	riva_save_state(rinfo, &rinfo->initial_state);
 
-	io_out8 (regs->misc_output, 0x3C2);
+	rinfo->ram_amount = rinfo->riva.RamAmountKBytes * 1024;
+	rinfo->dclk_max = rinfo->riva.MaxVClockFreqKHz * 1000;
 
-	for (i = 0; i < NUM_CRT_REGS; i++) {
-		if (i < 0x19) {
-			io_out8 (i, 0x3D4);
-			io_out8 (regs->crtc[i], 0x3D5);
-		} else {
-			switch (i) {
-			case 0x19:
-			case 0x20:
-			case 0x21:
-			case 0x22:
-			case 0x23:
-			case 0x24:
-			case 0x25:
-			case 0x26:
-			case 0x27:
-			case 0x28:
-			case 0x29:
-			case 0x2a:
-			case 0x2b:
-			case 0x2c:
-			case 0x2d:
-			case 0x2e:
-			case 0x2f:
-			case 0x30:
-			case 0x31:
-			case 0x32:
-			case 0x33:
-			case 0x34:
-			case 0x35:
-			case 0x36:
-			case 0x37:
-			case 0x38:
-			case 0x39:
-			case 0x3a:
-			case 0x3b:
-			case 0x3c:
-			case 0x3d:
-			case 0x3e:
-			case 0x3f:
-			case 0x40:
-				break;
-			default:
-				io_out8 (i, 0x3D4);
-				io_out8 (regs->crtc[i], 0x3D5);
-			}
-		}
-	}
+	if (!nohwcursor) rinfo->cursor = rivafb_init_cursor(rinfo);
 
-	for (i = 0; i < NUM_ATC_REGS; i++) {
-		io_out8 (i, 0x3C0);
-		io_out8 (regs->attr[i], 0x3C0);
+	if (riva_set_fbinfo(rinfo) < 0) {
+		printk(KERN_ERR PFX "error setting initial video mode\n");
+		goto err_out_cursor;
 	}
 
-	for (i = 0; i < NUM_GRC_REGS; i++) {
-		io_out8 (i, 0x3CE);
-		io_out8 (regs->gra[i], 0x3CF);
+	if (register_framebuffer((struct fb_info *)rinfo) < 0) {
+		printk(KERN_ERR PFX
+			"error registering riva framebuffer\n");
+		goto err_out_load_state;
 	}
 
-	for (i = 0; i < NUM_SEQ_REGS; i++) {
-		io_out8 (i, 0x3C4);
-		io_out8 (regs->seq[i], 0x3C5);
-	}
+	riva_boards = riva_board_list_add(riva_boards, rinfo);
+
+	pci_set_drvdata(pd, rinfo);
+
+	printk(KERN_INFO PFX
+		"PCI nVidia NV%d framebuffer ver %s (%s, %dMB @ 0x%lX)\n",
+		rinfo->riva.Architecture,
+		RIVAFB_VERSION,
+		rinfo->drvr_name,
+		rinfo->ram_amount / (1024 * 1024),
+		rinfo->fb_base_phys);
+
+	return 0;
+
+err_out_load_state:
+	riva_load_state(rinfo, &rinfo->initial_state);
+err_out_cursor:
+	rivafb_exit_cursor(rinfo);
+/* err_out_iounmap_fb: */
+	iounmap(rinfo->fb_base);
+err_out_iounmap_ctrl:
+	iounmap(rinfo->ctrl_base);
+err_out_free_base1:
+	release_mem_region(rinfo->fb_base_phys, rinfo->base1_region_size);
+err_out_free_base0:
+	release_mem_region(rinfo->ctrl_base_phys, rinfo->base0_region_size);
+err_out_kfree:
+	kfree(rinfo);
+err_out:
+	return -ENODEV;
 }
 
+static void __devexit rivafb_remove_one(struct pci_dev *pd)
+{
+	struct rivafb_info *board = pci_get_drvdata(pd);
+	
+	if (!board)
+		return;
+
+	riva_boards = riva_board_list_del(riva_boards, board);
 
+	riva_load_state(board, &board->initial_state);
 
+	unregister_framebuffer((struct fb_info *)board);
 
-/**
- * riva_board_list_add
- * @board_list: Root node of list of boards
- * @new_node: New node to be added
+	rivafb_exit_cursor(board);
+
+#ifdef CONFIG_MTRR
+	if (board->mtrr.vram_valid)
+		mtrr_del(board->mtrr.vram, board->fb_base_phys,
+			 board->base1_region_size);
+#endif /* CONFIG_MTRR */
+
+	iounmap(board->ctrl_base);
+	iounmap(board->fb_base);
+
+	release_mem_region(board->ctrl_base_phys,
+			   board->base0_region_size);
+	release_mem_region(board->fb_base_phys,
+			   board->base1_region_size);
+
+	kfree(board);
+
+	pci_set_drvdata(pd, NULL);
+}
+
+
+
+/* ------------------------------------------------------------------------- *
  *
- * DESCRIPTION:
- * Adds @new_node to the list referenced by @board_list
+ * initialization
  *
- * RETURNS:
- * New root node
- */
-static
-struct rivafb_info *riva_board_list_add (struct rivafb_info *board_list,
-					 struct rivafb_info *new_node)
+ * ------------------------------------------------------------------------- */
+
+#ifndef MODULE
+int __init rivafb_setup(char *options)
 {
-	struct rivafb_info *i_p = board_list;
+	char *this_opt;
 
-	new_node->next = NULL;
+	if (!options || !*options)
+		return 0;
 
-	if (board_list == NULL)
-		return new_node;
+	for (this_opt = strtok(options, ","); this_opt;
+	     this_opt = strtok(NULL, ",")) {
+		if (!strncmp(this_opt, "font:", 5)) {
+			char *p;
+			int i;
 
-	while (i_p->next != NULL)
-		i_p = i_p->next;
-	i_p->next = new_node;
+			p = this_opt + 5;
+			for (i = 0; i < sizeof(fontname) - 1; i++)
+				if (!*p || *p == ' ' || *p == ',')
+					break;
+			memcpy(fontname, this_opt + 5, i);
+			fontname[i] = 0;
 
-	return board_list;
+		} else if (!strncmp(this_opt, "noblink", 7)) {
+			noblink = 1;
+		} else if (!strncmp(this_opt, "noaccel", 7)) {
+			noaccel = 1;
+		} else if (!strncmp(this_opt, "nomove", 6)) {
+			nomove = 1;
+#ifdef CONFIG_MTRR
+		} else if (!strncmp(this_opt, "nomtrr", 6)) {
+			nomtrr = 1;
+#endif
+		} else if (!strncmp(this_opt, "nohwcursor", 10)) {
+			nohwcursor = 1;
+		} else
+			mode_option = this_opt;
+	}
+	return 0;
 }
+#endif /* !MODULE */
+
+static struct pci_driver rivafb_driver = {
+	name:		"rivafb",
+	id_table:	rivafb_pci_tbl,
+	probe:		rivafb_init_one,
+	remove:		rivafb_remove_one,
+};
 
 
 
-/**
- * riva_board_list_del
- * @board_list: Root node of list of boards
- * @del_node: Node to be removed
+/* ------------------------------------------------------------------------- *
  *
- * DESCRIPTION:
- * Removes @del_node from the list referenced by @board_list
+ * modularization
  *
- * RETURNS:
- * New root node
- */
-static
-struct rivafb_info *riva_board_list_del (struct rivafb_info *board_list,
-					 struct rivafb_info *del_node)
-{
-	struct rivafb_info *i_p = board_list;
+ * ------------------------------------------------------------------------- */
 
-	if (board_list == del_node)
-		return del_node->next;
+int __init rivafb_init(void)
+{
+	int err;
+#ifdef MODULE
+	if (font) strncpy(fontname, font, sizeof(fontname)-1);
+#endif
+	err = pci_module_init(&rivafb_driver);
+	if (err)
+		return err;
+	return 0;
+}
 
-	while (i_p->next != del_node)
-		i_p = i_p->next;
-	i_p->next = del_node->next;
 
-	return board_list;
+#ifdef MODULE
+static void __exit rivafb_exit(void)
+{
+	pci_unregister_driver(&rivafb_driver);
 }
 
+module_init(rivafb_init);
+module_exit(rivafb_exit);
+
+MODULE_PARM(font, "s");
+MODULE_PARM_DESC(font, "Specifies one of the compiled-in fonts (default=none)");
+MODULE_PARM(noaccel, "i");
+MODULE_PARM_DESC(noaccel, "Disables hardware acceleration (0 or 1=disabled) (default=0)");
+MODULE_PARM(nomove, "i");
+MODULE_PARM_DESC(nomove, "Enables YSCROLL_NOMOVE (0 or 1=enabled) (default=0)");
+MODULE_PARM(nohwcursor, "i");
+MODULE_PARM_DESC(nohwcursor, "Disables hardware cursor (0 or 1=disabled) (default=0)");
+MODULE_PARM(noblink, "i");
+MODULE_PARM_DESC(noblink, "Disables hardware cursor blinking (0 or 1=disabled) (default=0)");
+#ifdef CONFIG_MTRR
+MODULE_PARM(nomtrr, "i");
+MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)");
+#endif
+#endif /* MODULE */
+
+MODULE_AUTHOR("Ani Joshi, maintainer");
+MODULE_DESCRIPTION("Framebuffer driver for nVidia Riva 128, TNT, TNT2");
diff -u --recursive --new-file v2.4.1/linux/drivers/video/riva/riva_hw.c linux/drivers/video/riva/riva_hw.c
--- v2.4.1/linux/drivers/video/riva/riva_hw.c	Wed Jul  5 10:56:12 2000
+++ linux/drivers/video/riva/riva_hw.c	Sat Feb  3 12:48:00 2001
@@ -1,6 +1,6 @@
  /***************************************************************************\
 |*                                                                           *|
-|*       Copyright 1993-1998 NVIDIA, Corporation.  All rights reserved.      *|
+|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
 |*                                                                           *|
 |*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
 |*     international laws.  Users and possessors of this source code are     *|
@@ -11,7 +11,7 @@
 |*     tion and  internal comments to the code,  notices to the end user     *|
 |*     as follows:                                                           *|
 |*                                                                           *|
-|*       Copyright 1993-1998 NVIDIA, Corporation.  All rights reserved.      *|
+|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
 |*                                                                           *|
 |*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
 |*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
@@ -36,52 +36,76 @@
 |*     those rights set forth herein.                                        *|
 |*                                                                           *|
  \***************************************************************************/
-/* 
- * GPL licensing note -- nVidia is allowing a liberal interpretation of 
- * the documentation restriction above, to merely say that this nVidia's
- * copyright and disclaimer should be included with all code derived 
- * from this source.  -- Jeff Garzik <jgarzik@mandrakesoft.com>, 01/Nov/99
- */
-
-/* $XFree86: xc/programs/Xserver/hw/xfree86/vga256/drivers/nv/riva_hw.c,v 1.1.2.3 1998/12/26 00:12:39 dawes Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_hw.c,v 1.8 2000/02/08 17:19:11 dawes Exp $ */
 
-#include <linux/kernel.h>
-#include <asm/io.h>
 #include "riva_hw.h"
 #include "riva_tbl.h"
-
-
 /*
  * This file is an OS-agnostic file used to make RIVA 128 and RIVA TNT
  * operate identically (except TNT has more memory and better 3D quality.
  */
-
 static int nv3Busy
 (
     RIVA_HW_INST *chip
 )
 {
-    return ((!(chip->PFIFO[0x00001214/4] & 0x10)) | (chip->PGRAPH[0x000006B0/4] & 0x01));
+    return ((chip->Rop->FifoFree < chip->FifoEmptyCount) || (chip->PGRAPH[0x000006B0/4] & 0x01));
 }
 static int nv4Busy
 (
     RIVA_HW_INST *chip
 )
 {
-    return ((!(chip->PFIFO[0x00001214/4] & 0x10)) | (chip->PGRAPH[0x00000700/4] & 0x01));
+    return ((chip->Rop->FifoFree < chip->FifoEmptyCount) || (chip->PGRAPH[0x00000700/4] & 0x01));
 }
+static int nv10Busy
+(
+    RIVA_HW_INST *chip
+)
+{
+    return ((chip->Rop->FifoFree < chip->FifoEmptyCount) || (chip->PGRAPH[0x00000700/4] & 0x01));
+}
+static void nv3LockUnlock
+(
+    RIVA_HW_INST *chip,
+    int           LockUnlock
+)
+{
+    VGA_WR08(chip->PVIO, 0x3C4, 0x06);
+    VGA_WR08(chip->PVIO, 0x3C5, LockUnlock ? 0x99 : 0x57);
+}
+static void nv4LockUnlock
+(
+    RIVA_HW_INST *chip,
+    int           LockUnlock
+)
+{
+    VGA_WR08(chip->PCIO, 0x3D4, 0x1F);
+    VGA_WR08(chip->PCIO, 0x3D5, LockUnlock ? 0x99 : 0x57);
+}
+static void nv10LockUnlock
+(
+    RIVA_HW_INST *chip,
+    int           LockUnlock
+)
+{
+    VGA_WR08(chip->PCIO, 0x3D4, 0x1F);
+    VGA_WR08(chip->PCIO, 0x3D5, LockUnlock ? 0x99 : 0x57);
+}
+
 static int ShowHideCursor
 (
     RIVA_HW_INST *chip,
     int           ShowHide
 )
 {
-    int xcurrent;
-    xcurrent                     =  chip->CurrentState->cursor1;
-    chip->CurrentState->cursor1 = (chip->CurrentState->cursor1 & 0xFE) | (ShowHide & 0x01);
-    outb(0x31, 0x3D4);
-    outb(chip->CurrentState->cursor1, 0x3D5);
-    return (xcurrent & 0x01);
+    int current;
+    current                     =  chip->CurrentState->cursor1;
+    chip->CurrentState->cursor1 = (chip->CurrentState->cursor1 & 0xFE) |
+	                          (ShowHide & 0x01);
+    VGA_WR08(chip->PCIO, 0x3D4, 0x31);
+    VGA_WR08(chip->PCIO, 0x3D5, chip->CurrentState->cursor1);
+    return (current & 0x01);
 }
 
 /****************************************************************************\
@@ -171,6 +195,27 @@
   char mem_aligned;
   char enable_mp;
 } nv4_sim_state;
+typedef struct {
+  int graphics_lwm;
+  int video_lwm;
+  int graphics_burst_size;
+  int video_burst_size;
+  int valid;
+} nv10_fifo_info;
+typedef struct {
+  int pclk_khz;
+  int mclk_khz;
+  int nvclk_khz;
+  char mem_page_miss;
+  char mem_latency;
+  int memory_type;
+  int memory_width;
+  char enable_video;
+  char gr_during_vid;
+  char pix_bpp;
+  char mem_aligned;
+  char enable_mp;
+} nv10_sim_state;
 static int nv3_iterate(nv3_fifo_info *res_info, nv3_sim_state * state, nv3_arb_info *ainfo)
 {
     int iter = 0;
@@ -215,7 +260,7 @@
             if (ainfo->wcglwm > glwm) ainfo->wcglwm = glwm ;
             if (ainfo->wcgocc > ainfo->gocc) ainfo->wcgocc = ainfo->gocc;
             ns = 1000000 * (ainfo->gburst_size/(state->memory_width/8))/state->mclk_khz;
-            gfsize = ns *ainfo->gdrain_rate/1000000;
+            gfsize = (ns * (long) ainfo->gdrain_rate)/1000000;
             gfsize = ainfo->wcglwm - ainfo->gburst_size + gfsize;
         }
         mfsize = 0;
@@ -312,7 +357,7 @@
         }
         ns = 1000000*ainfo->gburst_size/(state->memory_width/8)/state->mclk_khz;
         tmp = ns * ainfo->gdrain_rate/1000000;
-        if (ABS(ainfo->gburst_size) + ((ABS(ainfo->wcglwm) + 16 ) & ~0x7)    - tmp > max_gfsize)
+        if (ABS(ainfo->gburst_size) + ((ABS(ainfo->wcglwm) + 16 ) & ~0x7) - tmp > max_gfsize)
         {
             ainfo->converged = 0;
             return (1);
@@ -468,32 +513,27 @@
     int done, g,v, p;
     
     done = 0;
-    if (state->gr_during_vid && ainfo->vid_en)
-        ainfo->priority = MPORT;
-    else
-        ainfo->priority = ainfo->gdrain_rate < ainfo->vdrain_rate ? VIDEO: GRAPHICS;
-    for (p=0; p < 2 && done != 1; p++)
+    for (p=0; p < 2; p++)
     {
-        for (g=128 ; (g > 32) && (done != 1); g= g>> 1)
+        for (g=128 ; g > 32; g= g>> 1)
         {
-            for (v=128; (v >=32) && (done !=1); v = v>> 1)
+            for (v=128; v >=32; v = v>> 1)
             {
                 ainfo->priority = p;
                 ainfo->gburst_size = g;     
                 ainfo->vburst_size = v;
                 done = nv3_arb(res_info, state,ainfo);
-                if (g==128)
-                {
+                if (done && (g==128))
                     if ((res_info->graphics_lwm + g) > 256)
                         done = 0;
-                }
+                if (done)
+                    goto Done;
             }
         }
     }
-    if (!done)
-        return (0);
-    else
-        return (1);
+
+ Done:
+    return done;
 }
 static void nv3CalcArbitration 
 (
@@ -509,7 +549,7 @@
     ainfo.vid_en = state->enable_video;
     ainfo.vid_only_once = 0;
     ainfo.gr_only_once = 0;
-    ainfo.gdrain_rate = (int) state->pclk_khz * state -> pix_bpp/8;
+    ainfo.gdrain_rate = (int) state->pclk_khz * (state->pix_bpp/8);
     ainfo.vdrain_rate = (int) state->pclk_khz * 2;
     if (state->video_scale != 0)
         ainfo.vdrain_rate = ainfo.vdrain_rate/state->video_scale;
@@ -527,7 +567,7 @@
         ainfo.vid_en = 1;
         ainfo.vid_only_once = 1;
         ainfo.gr_en = 1;
-        ainfo.gdrain_rate = (int) state->pclk_khz * state -> pix_bpp/8;
+        ainfo.gdrain_rate = (int) state->pclk_khz * (state->pix_bpp/8);
         ainfo.vdrain_rate = 0;
         res_gr = nv3_get_param(res_info, state,  &ainfo);
         res_gr = ainfo.converged;
@@ -543,7 +583,7 @@
         res_info->valid = ainfo.converged;
     }
 }
-void nv3UpdateArbitrationSettings
+static void nv3UpdateArbitrationSettings
 (
     unsigned      VClk, 
     unsigned      pixelDepth, 
@@ -565,9 +605,10 @@
     sim_data.video_scale    = 1;
     sim_data.memory_width   = (chip->PEXTDEV[0x00000000/4] & 0x10) ? 128 : 64;
     sim_data.memory_width   = 128;
-    sim_data.mem_latency    = 11;
+
+    sim_data.mem_latency    = 9;
     sim_data.mem_aligned    = 1;
-    sim_data.mem_page_miss  = 9;
+    sim_data.mem_page_miss  = 11;
     sim_data.gr_during_vid  = 0;
     sim_data.pclk_khz       = VClk;
     sim_data.mclk_khz       = MClk;
@@ -582,7 +623,7 @@
     else
     {
         *lwm   = 0x24;
-        *burst = 0x02;
+        *burst = 0x2;
     }
 }
 static void nv4CalcArbitration 
@@ -592,7 +633,7 @@
 )
 {
     int data, pagemiss, cas,width, video_enable, color_key_enable, bpp, align;
-    int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs=0;
+    int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
     int found, mclk_extra, mclk_loop, cbs, m1, p1;
     int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
     int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate;
@@ -636,6 +677,7 @@
     nvclks += 0;
     pclks += 0;
     found = 0;
+    vbs = 0;
     while (found != 1)
     {
         fifo->valid = 1;
@@ -768,6 +810,268 @@
         *lwm   = fifo_data.graphics_lwm >> 3;
     }
 }
+static void nv10CalcArbitration 
+(
+    nv10_fifo_info *fifo,
+    nv10_sim_state *arb
+)
+{
+    int data, pagemiss, cas,width, video_enable, color_key_enable, bpp, align;
+    int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
+    int nvclk_fill, us_extra;
+    int found, mclk_extra, mclk_loop, cbs, m1;
+    int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
+    int us_m, us_m_min, us_n, us_p, video_drain_rate, crtc_drain_rate;
+    int vus_m, vus_n, vus_p;
+    int vpm_us, us_video, vlwm, cpm_us, us_crt,clwm;
+    int clwm_rnd_down;
+    int craw, m2us, us_pipe, us_pipe_min, vus_pipe, p1clk, p2;
+    int pclks_2_top_fifo, min_mclk_extra;
+    int us_min_mclk_extra;
+
+    fifo->valid = 1;
+    pclk_freq = arb->pclk_khz; /* freq in KHz */
+    mclk_freq = arb->mclk_khz;
+    nvclk_freq = arb->nvclk_khz;
+    pagemiss = arb->mem_page_miss;
+    cas = arb->mem_latency;
+    width = arb->memory_width/64;
+    video_enable = arb->enable_video;
+    color_key_enable = arb->gr_during_vid;
+    bpp = arb->pix_bpp;
+    align = arb->mem_aligned;
+    mp_enable = arb->enable_mp;
+    clwm = 0;
+    vlwm = 1024;
+
+    cbs = 512;
+    vbs = 512;
+
+    pclks = 4; /* lwm detect. */
+
+    nvclks = 3; /* lwm -> sync. */
+    nvclks += 2; /* fbi bus cycles (1 req + 1 busy) */
+
+    mclks  = 1;   /* 2 edge sync.  may be very close to edge so just put one. */
+
+    mclks += 1;   /* arb_hp_req */
+    mclks += 5;   /* ap_hp_req   tiling pipeline */
+
+    mclks += 2;    /* tc_req     latency fifo */
+    mclks += 2;    /* fb_cas_n_  memory request to fbio block */
+    mclks += 7;    /* sm_d_rdv   data returned from fbio block */
+
+    /* fb.rd.d.Put_gc   need to accumulate 256 bits for read */
+    if (arb->memory_type == 0)
+      if (arb->memory_width == 64) /* 64 bit bus */
+        mclks += 4;
+      else
+        mclks += 2;
+    else
+      if (arb->memory_width == 64) /* 64 bit bus */
+        mclks += 2;
+      else
+        mclks += 1;
+
+    if ((!video_enable) && (arb->memory_width == 128))
+    {  
+      mclk_extra = (bpp == 32) ? 31 : 42; /* Margin of error */
+      min_mclk_extra = 17;
+    }
+    else
+    {
+      mclk_extra = (bpp == 32) ? 8 : 4; /* Margin of error */
+      /* mclk_extra = 4; */ /* Margin of error */
+      min_mclk_extra = 18;
+    }
+
+    nvclks += 1; /* 2 edge sync.  may be very close to edge so just put one. */
+    nvclks += 1; /* fbi_d_rdv_n */
+    nvclks += 1; /* Fbi_d_rdata */
+    nvclks += 1; /* crtfifo load */
+
+    if(mp_enable)
+      mclks+=4; /* Mp can get in with a burst of 8. */
+    /* Extra clocks determined by heuristics */
+
+    nvclks += 0;
+    pclks += 0;
+    found = 0;
+    while(found != 1) {
+      fifo->valid = 1;
+      found = 1;
+      mclk_loop = mclks+mclk_extra;
+      us_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
+      us_m_min = mclks * 1000*1000 / mclk_freq; /* Minimum Mclk latency in us */
+      us_min_mclk_extra = min_mclk_extra *1000*1000 / mclk_freq;
+      us_n = nvclks*1000*1000 / nvclk_freq;/* nvclk latency in us */
+      us_p = pclks*1000*1000 / pclk_freq;/* nvclk latency in us */
+      us_pipe = us_m + us_n + us_p;
+      us_pipe_min = us_m_min + us_n + us_p;
+      us_extra = 0;
+
+      vus_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
+      vus_n = (4)*1000*1000 / nvclk_freq;/* nvclk latency in us */
+      vus_p = 0*1000*1000 / pclk_freq;/* pclk latency in us */
+      vus_pipe = vus_m + vus_n + vus_p;
+
+      if(video_enable) {
+        video_drain_rate = pclk_freq * 4; /* MB/s */
+        crtc_drain_rate = pclk_freq * bpp/8; /* MB/s */
+
+        vpagemiss = 1; /* self generating page miss */
+        vpagemiss += 1; /* One higher priority before */
+
+        crtpagemiss = 2; /* self generating page miss */
+        if(mp_enable)
+            crtpagemiss += 1; /* if MA0 conflict */
+
+        vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
+
+        us_video = vpm_us + vus_m; /* Video has separate read return path */
+
+        cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
+        us_crt =
+          us_video  /* Wait for video */
+          +cpm_us /* CRT Page miss */
+          +us_m + us_n +us_p /* other latency */
+          ;
+
+        clwm = us_crt * crtc_drain_rate/(1000*1000);
+        clwm++; /* fixed point <= float_point - 1.  Fixes that */
+      } else {
+        crtc_drain_rate = pclk_freq * bpp/8; /* bpp * pclk/8 */
+
+        crtpagemiss = 1; /* self generating page miss */
+        crtpagemiss += 1; /* MA0 page miss */
+        if(mp_enable)
+            crtpagemiss += 1; /* if MA0 conflict */
+        cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
+        us_crt =  cpm_us + us_m + us_n + us_p ;
+        clwm = us_crt * crtc_drain_rate/(1000*1000);
+        clwm++; /* fixed point <= float_point - 1.  Fixes that */
+
+  /*
+          //
+          // Another concern, only for high pclks so don't do this
+          // with video:
+          // What happens if the latency to fetch the cbs is so large that
+          // fifo empties.  In that case we need to have an alternate clwm value
+          // based off the total burst fetch
+          //
+          us_crt = (cbs * 1000 * 1000)/ (8*width)/mclk_freq ;
+          us_crt = us_crt + us_m + us_n + us_p + (4 * 1000 * 1000)/mclk_freq;
+          clwm_mt = us_crt * crtc_drain_rate/(1000*1000);
+          clwm_mt ++;
+          if(clwm_mt > clwm)
+              clwm = clwm_mt;
+  */
+          /* Finally, a heuristic check when width == 64 bits */
+          if(width == 1){
+              nvclk_fill = nvclk_freq * 8;
+              if(crtc_drain_rate * 100 >= nvclk_fill * 102)
+                      clwm = 0xfff; /*Large number to fail */
+
+              else if(crtc_drain_rate * 100  >= nvclk_fill * 98) {
+                  clwm = 1024;
+                  cbs = 512;
+                  us_extra = (cbs * 1000 * 1000)/ (8*width)/mclk_freq ;
+              }
+          }
+      }
+
+
+      /*
+        Overfill check:
+
+        */
+
+      clwm_rnd_down = ((int)clwm/8)*8;
+      if (clwm_rnd_down < clwm)
+          clwm += 8;
+
+      m1 = clwm + cbs -  1024; /* Amount of overfill */
+      m2us = us_pipe_min + us_min_mclk_extra;
+      pclks_2_top_fifo = (1024-clwm)/(8*width);
+
+      /* pclk cycles to drain */
+      p1clk = m2us * pclk_freq/(1000*1000); 
+      p2 = p1clk * bpp / 8; /* bytes drained. */
+
+      if((p2 < m1) && (m1 > 0)) {
+          fifo->valid = 0;
+          found = 0;
+          if(min_mclk_extra == 0)   {
+            if(cbs <= 32) {
+              found = 1; /* Can't adjust anymore! */
+            } else {
+              cbs = cbs/2;  /* reduce the burst size */
+            }
+          } else {
+            min_mclk_extra--;
+          }
+      } else {
+        if (clwm > 1023){ /* Have some margin */
+          fifo->valid = 0;
+          found = 0;
+          if(min_mclk_extra == 0)   
+              found = 1; /* Can't adjust anymore! */
+          else 
+              min_mclk_extra--;
+        }
+      }
+      craw = clwm;
+
+      if(clwm < (1024-cbs+8)) clwm = 1024-cbs+8;
+      data = (int)(clwm);
+      /*  printf("CRT LWM: %f bytes, prog: 0x%x, bs: 256\n", clwm, data ); */
+      fifo->graphics_lwm = data;   fifo->graphics_burst_size = cbs;
+
+      /*  printf("VID LWM: %f bytes, prog: 0x%x, bs: %d\n, ", vlwm, data, vbs ); */
+      fifo->video_lwm = 1024;  fifo->video_burst_size = 512;
+    }
+}
+static void nv10UpdateArbitrationSettings
+(
+    unsigned      VClk, 
+    unsigned      pixelDepth, 
+    unsigned     *burst,
+    unsigned     *lwm,
+    RIVA_HW_INST *chip
+)
+{
+    nv10_fifo_info fifo_data;
+    nv10_sim_state sim_data;
+    unsigned int M, N, P, pll, MClk, NVClk, cfg1;
+
+    pll = chip->PRAMDAC[0x00000504/4];
+    M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
+    MClk  = (N * chip->CrystalFreqKHz / M) >> P;
+    pll = chip->PRAMDAC[0x00000500/4];
+    M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
+    NVClk  = (N * chip->CrystalFreqKHz / M) >> P;
+    cfg1 = chip->PFB[0x00000204/4];
+    sim_data.pix_bpp        = (char)pixelDepth;
+    sim_data.enable_video   = 0;
+    sim_data.enable_mp      = 0;
+    sim_data.memory_type    = (chip->PFB[0x00000200/4] & 0x01) ? 1 : 0;
+    sim_data.memory_width   = (chip->PEXTDEV[0x00000000/4] & 0x10) ? 128 : 64;
+    sim_data.mem_latency    = (char)cfg1 & 0x0F;
+    sim_data.mem_aligned    = 1;
+    sim_data.mem_page_miss  = (char)(((cfg1 >> 4) &0x0F) + ((cfg1 >> 31) & 0x01));
+    sim_data.gr_during_vid  = 0;
+    sim_data.pclk_khz       = VClk;
+    sim_data.mclk_khz       = MClk;
+    sim_data.nvclk_khz      = NVClk;
+    nv10CalcArbitration(&fifo_data, &sim_data);
+    if (fifo_data.valid)
+    {
+        int  b = fifo_data.graphics_burst_size >> 4;
+        *burst = 0;
+        while (b >>= 1) (*burst)++;
+        *lwm   = fifo_data.graphics_lwm >> 3;
+    }
+}
 
 /****************************************************************************\
 *                                                                            *
@@ -781,6 +1085,7 @@
 static int CalcVClock
 (
     int           clockIn,
+    int           double_scan,
     int          *clockOut,
     int          *mOut,
     int          *nOut,
@@ -794,18 +1099,23 @@
     unsigned M, N, P;
     
     DeltaOld = 0xFFFFFFFF;
+
     VClk     = (unsigned)clockIn;
+    if (double_scan)
+        VClk *= 2;
+    
     if (chip->CrystalFreqKHz == 14318)
     {
         lowM  = 8;
-        highM = 14 - (chip->Architecture == 3);
+        highM = 14 - (chip->Architecture == NV_ARCH_03);
     }
     else
     {
         lowM  = 7;
-        highM = 13 - (chip->Architecture == 3);
+        highM = 13 - (chip->Architecture == NV_ARCH_03);
     }                      
-    highP = 4 - (chip->Architecture == 3);
+
+    highP = 4 - (chip->Architecture == NV_ARCH_03);
     for (P = 0; P <= highP; P ++)
     {
         Freq = VClk << P;
@@ -866,10 +1176,12 @@
      * Extended RIVA registers.
      */
     pixelDepth = (bpp + 1)/8;
-    CalcVClock(dotClock, &VClk, &m, &n, &p, chip);
+    CalcVClock(dotClock, hDisplaySize < 512,  /* double scan? */
+               &VClk, &m, &n, &p, chip);
+
     switch (chip->Architecture)
     {
-	    case 3:
+        case NV_ARCH_03:
             nv3UpdateArbitrationSettings(VClk, 
                                          pixelDepth * 8, 
                                         &(state->arbitration0),
@@ -882,11 +1194,10 @@
             state->config   = ((width + 31)/32)
                             | (((pixelDepth > 2) ? 3 : pixelDepth) << 8)
                             | 0x1000;
-            state->general  = 0x00000100;
+            state->general  = 0x00100100;
             state->repaint1 = hDisplaySize < 1280 ? 0x06 : 0x02;
             break;
-	    case 4:
-	    case 5:
+        case NV_ARCH_04:
             nv4UpdateArbitrationSettings(VClk, 
                                          pixelDepth * 8, 
                                         &(state->arbitration0),
@@ -900,6 +1211,20 @@
             state->general  = bpp == 16 ? 0x00101100 : 0x00100100;
             state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
             break;
+        case NV_ARCH_10:
+            nv10UpdateArbitrationSettings(VClk, 
+                                          pixelDepth * 8, 
+                                         &(state->arbitration0),
+                                         &(state->arbitration1),
+                                          chip);
+            state->cursor0  = 0x00;
+            state->cursor1  = 0xFC;
+            state->cursor2  = 0x00000000;
+            state->pllsel   = 0x10000700;
+            state->config   = chip->PFB[0x00000200/4];
+            state->general  = bpp == 16 ? 0x00101100 : 0x00100100;
+            state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
+            break;
     }
     state->vpll     = (p << 16) | (n << 8) | m;
     state->screen   = ((hTotal   & 0x040) >> 2)
@@ -909,7 +1234,7 @@
                     | ((vTotal   & 0x400) >> 10);
     state->repaint0 = (((width/8)*pixelDepth) & 0x700) >> 3;
     state->horiz    = hTotal     < 260 ? 0x00 : 0x01;
-    state->pixel    = (pixelDepth > 2 ? 3 : pixelDepth) | 0x40;
+    state->pixel    = pixelDepth > 2   ? 3    : pixelDepth;
     state->offset0  =
     state->offset1  =
     state->offset2  =
@@ -937,6 +1262,31 @@
 #define LOAD_FIXED_STATE_32BPP(tbl,dev)                                 \
     for (i = 0; i < sizeof(tbl##Table##dev##_32BPP)/8; i++)           \
         chip->dev[tbl##Table##dev##_32BPP[i][0]] = tbl##Table##dev##_32BPP[i][1]
+static void UpdateFifoState
+(
+    RIVA_HW_INST  *chip
+)
+{
+    int i;
+
+    switch (chip->Architecture)
+    {
+        case NV_ARCH_04:
+            LOAD_FIXED_STATE(nv4,FIFO);
+            chip->Tri03 = 0L;
+            chip->Tri05 = (RivaTexturedTriangle05 *)&(chip->FIFO[0x0000E000/4]);
+            break;
+        case NV_ARCH_10:
+            /*
+             * Initialize state for the RivaTriangle3D05 routines.
+             */
+            LOAD_FIXED_STATE(nv10tri05,PGRAPH);
+            LOAD_FIXED_STATE(nv10,FIFO);
+            chip->Tri03 = 0L;
+            chip->Tri05 = (RivaTexturedTriangle05 *)&(chip->FIFO[0x0000E000/4]);
+            break;
+    }
+}
 static void LoadStateExt
 (
     RIVA_HW_INST  *chip,
@@ -944,18 +1294,19 @@
 )
 {
     int i;
+
     /*
      * Load HW fixed function state.
      */
     LOAD_FIXED_STATE(Riva,PMC);
     LOAD_FIXED_STATE(Riva,PTIMER);
-    /*
-     * Make sure frame buffer config gets set before loading PRAMIN.
-     */
-    chip->PFB[0x00000200/4] = state->config;
     switch (chip->Architecture)
     {
-        case 3:
+        case NV_ARCH_03:
+            /*
+             * Make sure frame buffer config gets set before loading PRAMIN.
+             */
+            chip->PFB[0x00000200/4] = state->config;
             LOAD_FIXED_STATE(nv3,PFIFO);
             LOAD_FIXED_STATE(nv3,PRAMIN);
             LOAD_FIXED_STATE(nv3,PGRAPH);
@@ -991,8 +1342,11 @@
             chip->PGRAPH[0x00000658/4] = state->pitch2;
             chip->PGRAPH[0x0000065C/4] = state->pitch3;
             break;
-	    case 4:
-	    case 5:
+        case NV_ARCH_04:
+            /*
+             * Make sure frame buffer config gets set before loading PRAMIN.
+             */
+            chip->PFB[0x00000200/4] = state->config;
             LOAD_FIXED_STATE(nv4,PFIFO);
             LOAD_FIXED_STATE(nv4,PRAMIN);
             LOAD_FIXED_STATE(nv4,PGRAPH);
@@ -1030,22 +1384,142 @@
             chip->PGRAPH[0x00000678/4] = state->pitch2;
             chip->PGRAPH[0x0000067C/4] = state->pitch3;
             break;
+        case NV_ARCH_10:
+            LOAD_FIXED_STATE(nv10,PFIFO);
+            LOAD_FIXED_STATE(nv10,PRAMIN);
+            LOAD_FIXED_STATE(nv10,PGRAPH);
+            switch (state->bpp)
+            {
+                case 15:
+                    LOAD_FIXED_STATE_15BPP(nv10,PRAMIN);
+                    LOAD_FIXED_STATE_15BPP(nv10,PGRAPH);
+                    chip->Tri03 = (RivaTexturedTriangle03  *)&(chip->FIFO[0x0000E000/4]);
+                    break;
+                case 16:
+                    LOAD_FIXED_STATE_16BPP(nv10,PRAMIN);
+                    LOAD_FIXED_STATE_16BPP(nv10,PGRAPH);
+                    chip->Tri03 = (RivaTexturedTriangle03  *)&(chip->FIFO[0x0000E000/4]);
+                    break;
+                case 24:
+                case 32:
+                    LOAD_FIXED_STATE_32BPP(nv10,PRAMIN);
+                    LOAD_FIXED_STATE_32BPP(nv10,PGRAPH);
+                    chip->Tri03 = 0L;
+                    break;
+                case 8:
+                default:
+                    LOAD_FIXED_STATE_8BPP(nv10,PRAMIN);
+                    LOAD_FIXED_STATE_8BPP(nv10,PGRAPH);
+                    chip->Tri03 = 0L;
+                    break;
+            }
+            chip->PGRAPH[0x00000640/4] = state->offset0;
+            chip->PGRAPH[0x00000644/4] = state->offset1;
+            chip->PGRAPH[0x00000648/4] = state->offset2;
+            chip->PGRAPH[0x0000064C/4] = state->offset3;
+            chip->PGRAPH[0x00000670/4] = state->pitch0;
+            chip->PGRAPH[0x00000674/4] = state->pitch1;
+            chip->PGRAPH[0x00000678/4] = state->pitch2;
+            chip->PGRAPH[0x0000067C/4] = state->pitch3;
+            chip->PGRAPH[0x00000680/4] = state->pitch3;
+            chip->PGRAPH[0x00000B00/4] = chip->PFB[0x00000240/4];
+            chip->PGRAPH[0x00000B04/4] = chip->PFB[0x00000244/4];
+            chip->PGRAPH[0x00000B08/4] = chip->PFB[0x00000248/4];
+            chip->PGRAPH[0x00000B0C/4] = chip->PFB[0x0000024C/4];
+            chip->PGRAPH[0x00000B10/4] = chip->PFB[0x00000250/4];
+            chip->PGRAPH[0x00000B14/4] = chip->PFB[0x00000254/4];
+            chip->PGRAPH[0x00000B18/4] = chip->PFB[0x00000258/4];
+            chip->PGRAPH[0x00000B1C/4] = chip->PFB[0x0000025C/4];
+            chip->PGRAPH[0x00000B20/4] = chip->PFB[0x00000260/4];
+            chip->PGRAPH[0x00000B24/4] = chip->PFB[0x00000264/4];
+            chip->PGRAPH[0x00000B28/4] = chip->PFB[0x00000268/4];
+            chip->PGRAPH[0x00000B2C/4] = chip->PFB[0x0000026C/4];
+            chip->PGRAPH[0x00000B30/4] = chip->PFB[0x00000270/4];
+            chip->PGRAPH[0x00000B34/4] = chip->PFB[0x00000274/4];
+            chip->PGRAPH[0x00000B38/4] = chip->PFB[0x00000278/4];
+            chip->PGRAPH[0x00000B3C/4] = chip->PFB[0x0000027C/4];
+            chip->PGRAPH[0x00000B40/4] = chip->PFB[0x00000280/4];
+            chip->PGRAPH[0x00000B44/4] = chip->PFB[0x00000284/4];
+            chip->PGRAPH[0x00000B48/4] = chip->PFB[0x00000288/4];
+            chip->PGRAPH[0x00000B4C/4] = chip->PFB[0x0000028C/4];
+            chip->PGRAPH[0x00000B50/4] = chip->PFB[0x00000290/4];
+            chip->PGRAPH[0x00000B54/4] = chip->PFB[0x00000294/4];
+            chip->PGRAPH[0x00000B58/4] = chip->PFB[0x00000298/4];
+            chip->PGRAPH[0x00000B5C/4] = chip->PFB[0x0000029C/4];
+            chip->PGRAPH[0x00000B60/4] = chip->PFB[0x000002A0/4];
+            chip->PGRAPH[0x00000B64/4] = chip->PFB[0x000002A4/4];
+            chip->PGRAPH[0x00000B68/4] = chip->PFB[0x000002A8/4];
+            chip->PGRAPH[0x00000B6C/4] = chip->PFB[0x000002AC/4];
+            chip->PGRAPH[0x00000B70/4] = chip->PFB[0x000002B0/4];
+            chip->PGRAPH[0x00000B74/4] = chip->PFB[0x000002B4/4];
+            chip->PGRAPH[0x00000B78/4] = chip->PFB[0x000002B8/4];
+            chip->PGRAPH[0x00000B7C/4] = chip->PFB[0x000002BC/4];
+            chip->PGRAPH[0x00000F40/4] = 0x10000000;
+            chip->PGRAPH[0x00000F44/4] = 0x00000000;
+            chip->PGRAPH[0x00000F50/4] = 0x00000040;
+            chip->PGRAPH[0x00000F54/4] = 0x00000008;
+            chip->PGRAPH[0x00000F50/4] = 0x00000200;
+            for (i = 0; i < (3*16); i++)
+                chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            chip->PGRAPH[0x00000F50/4] = 0x00000040;
+            chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            chip->PGRAPH[0x00000F50/4] = 0x00000800;
+            for (i = 0; i < (16*16); i++)
+                chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            chip->PGRAPH[0x00000F40/4] = 0x30000000;
+            chip->PGRAPH[0x00000F44/4] = 0x00000004;
+            chip->PGRAPH[0x00000F50/4] = 0x00006400;
+            for (i = 0; i < (59*4); i++)
+                chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            chip->PGRAPH[0x00000F50/4] = 0x00006800;
+            for (i = 0; i < (47*4); i++)
+                chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            chip->PGRAPH[0x00000F50/4] = 0x00006C00;
+            for (i = 0; i < (3*4); i++)
+                chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            chip->PGRAPH[0x00000F50/4] = 0x00007000;
+            for (i = 0; i < (19*4); i++)
+                chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            chip->PGRAPH[0x00000F50/4] = 0x00007400;
+            for (i = 0; i < (12*4); i++)
+                chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            chip->PGRAPH[0x00000F50/4] = 0x00007800;
+            for (i = 0; i < (12*4); i++)
+                chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            chip->PGRAPH[0x00000F50/4] = 0x00004400;
+            for (i = 0; i < (8*4); i++)
+                chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            chip->PGRAPH[0x00000F50/4] = 0x00000000;
+            for (i = 0; i < 16; i++)
+                chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            chip->PGRAPH[0x00000F50/4] = 0x00000040;
+            for (i = 0; i < 4; i++)
+                chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            break;
     }
-//NOTICE("8");
-//    LOAD_FIXED_STATE(Riva,FIFO); /* FIX ME*/
-//NOTICE("9");
+    LOAD_FIXED_STATE(Riva,FIFO);
+    UpdateFifoState(chip);
     /*
      * Load HW mode state.
      */
-    outb(0x19, 0x3D4); outb(state->repaint0, 0x3D5);
-    outb(0x1A, 0x3D4); outb(state->repaint1, 0x3D5);
-    outb(0x25, 0x3D4); outb(state->screen, 0x3D5);
-    outb(0x28, 0x3D4); outb(state->pixel, 0x3D5);
-    outb(0x2D, 0x3D4); outb(state->horiz, 0x3D5);
-    outb(0x1B, 0x3D4); outb(state->arbitration0, 0x3D5);
-    outb(0x20, 0x3D4); outb(state->arbitration1, 0x3D5);
-    outb(0x30, 0x3D4); outb(state->cursor0, 0x3D5);
-    outb(0x31, 0x3D4); outb(state->cursor1, 0x3D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x19);
+    VGA_WR08(chip->PCIO, 0x03D5, state->repaint0);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x1A);
+    VGA_WR08(chip->PCIO, 0x03D5, state->repaint1);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x25);
+    VGA_WR08(chip->PCIO, 0x03D5, state->screen);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x28);
+    VGA_WR08(chip->PCIO, 0x03D5, state->pixel);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x2D);
+    VGA_WR08(chip->PCIO, 0x03D5, state->horiz);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x1B);
+    VGA_WR08(chip->PCIO, 0x03D5, state->arbitration0);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x20);
+    VGA_WR08(chip->PCIO, 0x03D5, state->arbitration1);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x30);
+    VGA_WR08(chip->PCIO, 0x03D5, state->cursor0);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x31);
+    VGA_WR08(chip->PCIO, 0x03D5, state->cursor1);
     chip->PRAMDAC[0x00000300/4]  = state->cursor2;
     chip->PRAMDAC[0x00000508/4]  = state->vpll;
     chip->PRAMDAC[0x0000050C/4]  = state->pllsel;
@@ -1053,8 +1527,8 @@
     /*
      * Turn off VBlank enable and reset.
      */
-//    *(chip->VBLANKENABLE) = 0;		/* FIXME*/
-//    *(chip->VBLANK)       = chip->VBlankBit; /*FIXME*/
+    *(chip->VBLANKENABLE) = 0;
+    *(chip->VBLANK)       = chip->VBlankBit;
     /*
      * Set interrupt enable.
      */    
@@ -1064,9 +1538,11 @@
      */
     chip->CurrentState = state;
     /*
-     * Reset FIFO free count.
+     * Reset FIFO free and empty counts.
      */
-    chip->FifoFreeCount = 0;
+    chip->FifoFreeCount  = 0;
+    /* Free count from first subchannel */
+    chip->FifoEmptyCount = chip->Rop->FifoFree; 
 }
 static void UnloadStateExt
 (
@@ -1077,44 +1553,62 @@
     /*
      * Save current HW state.
      */
-    outb(0x19, 0x3D4); state->repaint0     = inb(0x3D5);
-    outb(0x1A, 0x3D4); state->repaint1     = inb(0x3D5);
-    outb(0x25, 0x3D4); state->screen       = inb(0x3D5);
-    outb(0x28, 0x3D4); state->pixel        = inb(0x3D5);
-    outb(0x2D, 0x3D4); state->horiz        = inb(0x3D5);
-    outb(0x1B, 0x3D4); state->arbitration0 = inb(0x3D5);
-    outb(0x20, 0x3D4); state->arbitration1 = inb(0x3D5);
-    outb(0x30, 0x3D4); state->cursor0      = inb(0x3D5);
-    outb(0x31, 0x3D4); state->cursor1      = inb(0x3D5);
-                      state->cursor2      = chip->PRAMDAC[0x00000300/4];
-                      state->vpll         = chip->PRAMDAC[0x00000508/4];
-                      state->pllsel       = chip->PRAMDAC[0x0000050C/4];
-                      state->general      = chip->PRAMDAC[0x00000600/4];
-                      state->config       = chip->PFB[0x00000200/4];
-                      switch (chip->Architecture)
-                      {
-			      case 3:
-                              state->offset0  = chip->PGRAPH[0x00000630/4];
-                              state->offset1  = chip->PGRAPH[0x00000634/4];
-                              state->offset2  = chip->PGRAPH[0x00000638/4];
-                              state->offset3  = chip->PGRAPH[0x0000063C/4];
-                              state->pitch0   = chip->PGRAPH[0x00000650/4];
-                              state->pitch1   = chip->PGRAPH[0x00000654/4];
-                              state->pitch2   = chip->PGRAPH[0x00000658/4];
-                              state->pitch3   = chip->PGRAPH[0x0000065C/4];
-                              break;
-			      case 4:
-			      case 5:
-                              state->offset0  = chip->PGRAPH[0x00000640/4];
-                              state->offset1  = chip->PGRAPH[0x00000644/4];
-                              state->offset2  = chip->PGRAPH[0x00000648/4];
-                              state->offset3  = chip->PGRAPH[0x0000064C/4];
-                              state->pitch0   = chip->PGRAPH[0x00000670/4];
-                              state->pitch1   = chip->PGRAPH[0x00000674/4];
-                              state->pitch2   = chip->PGRAPH[0x00000678/4];
-                              state->pitch3   = chip->PGRAPH[0x0000067C/4];
-                              break;
-                      }
+    VGA_WR08(chip->PCIO, 0x03D4, 0x19);
+    state->repaint0     = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x1A);
+    state->repaint1     = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x25);
+    state->screen       = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x28);
+    state->pixel        = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x2D);
+    state->horiz        = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x1B);
+    state->arbitration0 = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x20);
+    state->arbitration1 = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x30);
+    state->cursor0      = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x31);
+    state->cursor1      = VGA_RD08(chip->PCIO, 0x03D5);
+    state->cursor2      = chip->PRAMDAC[0x00000300/4];
+    state->vpll         = chip->PRAMDAC[0x00000508/4];
+    state->pllsel       = chip->PRAMDAC[0x0000050C/4];
+    state->general      = chip->PRAMDAC[0x00000600/4];
+    state->config       = chip->PFB[0x00000200/4];
+    switch (chip->Architecture)
+    {
+        case NV_ARCH_03:
+            state->offset0  = chip->PGRAPH[0x00000630/4];
+            state->offset1  = chip->PGRAPH[0x00000634/4];
+            state->offset2  = chip->PGRAPH[0x00000638/4];
+            state->offset3  = chip->PGRAPH[0x0000063C/4];
+            state->pitch0   = chip->PGRAPH[0x00000650/4];
+            state->pitch1   = chip->PGRAPH[0x00000654/4];
+            state->pitch2   = chip->PGRAPH[0x00000658/4];
+            state->pitch3   = chip->PGRAPH[0x0000065C/4];
+            break;
+        case NV_ARCH_04:
+            state->offset0  = chip->PGRAPH[0x00000640/4];
+            state->offset1  = chip->PGRAPH[0x00000644/4];
+            state->offset2  = chip->PGRAPH[0x00000648/4];
+            state->offset3  = chip->PGRAPH[0x0000064C/4];
+            state->pitch0   = chip->PGRAPH[0x00000670/4];
+            state->pitch1   = chip->PGRAPH[0x00000674/4];
+            state->pitch2   = chip->PGRAPH[0x00000678/4];
+            state->pitch3   = chip->PGRAPH[0x0000067C/4];
+            break;
+        case NV_ARCH_10:
+            state->offset0  = chip->PGRAPH[0x00000640/4];
+            state->offset1  = chip->PGRAPH[0x00000644/4];
+            state->offset2  = chip->PGRAPH[0x00000648/4];
+            state->offset3  = chip->PGRAPH[0x0000064C/4];
+            state->pitch0   = chip->PGRAPH[0x00000670/4];
+            state->pitch1   = chip->PGRAPH[0x00000674/4];
+            state->pitch2   = chip->PGRAPH[0x00000678/4];
+            state->pitch3   = chip->PGRAPH[0x0000067C/4];
+            break;
+    }
 }
 static void SetStartAddress
 (
@@ -1129,24 +1623,24 @@
     /*
      * Unlock extended registers.
      */
-    outb(chip->LockUnlockIndex, chip->LockUnlockIO);
-    outb(0x57, chip->LockUnlockIO + 1);
+    chip->LockUnlock(chip, 0);
     /*
      * Set start address.
      */
-    outb(0x0D, 0x3D4);
-    outb(offset, 0x3D5);
-    outb(0x0C, 0x3D4);
-    outb(offset >> 8, 0x3D5);
-    outb(0x19, 0x3D4);
-    tmp = inb(0x3D5);
-    outb(((offset >> 16) & 0x0F) | (tmp & 0xF0), 0x3D5);
+    VGA_WR08(chip->PCIO, 0x3D4, 0x0D); VGA_WR08(chip->PCIO, 0x3D5, offset);
+    offset >>= 8;
+    VGA_WR08(chip->PCIO, 0x3D4, 0x0C); VGA_WR08(chip->PCIO, 0x3D5, offset);
+    offset >>= 8;
+    VGA_WR08(chip->PCIO, 0x3D4, 0x19); tmp = VGA_RD08(chip->PCIO, 0x3D5);
+    VGA_WR08(chip->PCIO, 0x3D5, (offset & 0x01F) | (tmp & ~0x1F));
+    VGA_WR08(chip->PCIO, 0x3D4, 0x2D); tmp = VGA_RD08(chip->PCIO, 0x3D5);
+    VGA_WR08(chip->PCIO, 0x3D5, (offset & 0x60) | (tmp & ~0x60));
     /*
      * 4 pixel pan register.
      */
-    offset = inb(chip->IO + 0x0A);
-    outb(0x13, 0x3C0);
-    outb(pan, 0x3C0);
+    offset = VGA_RD08(chip->PCIO, chip->IO + 0x0A);
+    VGA_WR08(chip->PCIO, 0x3C0, 0x13);
+    VGA_WR08(chip->PCIO, 0x3C0, pan);
 }
 static void nv3SetSurfaces2D
 (
@@ -1155,9 +1649,14 @@
     unsigned     surf1
 )
 {
-    while (nv3Busy(chip));
-    chip->PGRAPH[0x00000630/4] = surf0;
-    chip->PGRAPH[0x00000634/4] = surf1;
+    RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]);
+
+    RIVA_FIFO_FREE(*chip,Tri03,5);
+    chip->FIFO[0x00003800] = 0x80000003;
+    Surface->Offset        = surf0;
+    chip->FIFO[0x00003800] = 0x80000004;
+    Surface->Offset        = surf1;
+    chip->FIFO[0x00003800] = 0x80000013;
 }
 static void nv4SetSurfaces2D
 (
@@ -1166,9 +1665,28 @@
     unsigned     surf1
 )
 {
-    while (nv4Busy(chip));
-    chip->PGRAPH[0x00000640/4] = surf0;
-    chip->PGRAPH[0x00000644/4] = surf1;
+    RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]);
+
+    chip->FIFO[0x00003800] = 0x80000003;
+    Surface->Offset        = surf0;
+    chip->FIFO[0x00003800] = 0x80000004;
+    Surface->Offset        = surf1;
+    chip->FIFO[0x00003800] = 0x80000014;
+}
+static void nv10SetSurfaces2D
+(
+    RIVA_HW_INST *chip,
+    unsigned     surf0,
+    unsigned     surf1
+)
+{
+    RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]);
+
+    chip->FIFO[0x00003800] = 0x80000003;
+    Surface->Offset        = surf0;
+    chip->FIFO[0x00003800] = 0x80000004;
+    Surface->Offset        = surf1;
+    chip->FIFO[0x00003800] = 0x80000014;
 }
 static void nv3SetSurfaces3D
 (
@@ -1177,9 +1695,14 @@
     unsigned     surf1
 )
 {
-    while (nv3Busy(chip));
-    chip->PGRAPH[0x00000638/4] = surf0;
-    chip->PGRAPH[0x0000063C/4] = surf1;
+    RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]);
+
+    RIVA_FIFO_FREE(*chip,Tri03,5);
+    chip->FIFO[0x00003800] = 0x80000005;
+    Surface->Offset        = surf0;
+    chip->FIFO[0x00003800] = 0x80000006;
+    Surface->Offset        = surf1;
+    chip->FIFO[0x00003800] = 0x80000013;
 }
 static void nv4SetSurfaces3D
 (
@@ -1188,9 +1711,28 @@
     unsigned     surf1
 )
 {
-    while (nv4Busy(chip));
-    chip->PGRAPH[0x00000648/4] = surf0;
-    chip->PGRAPH[0x0000064C/4] = surf1;
+    RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]);
+
+    chip->FIFO[0x00003800] = 0x80000005;
+    Surface->Offset        = surf0;
+    chip->FIFO[0x00003800] = 0x80000006;
+    Surface->Offset        = surf1;
+    chip->FIFO[0x00003800] = 0x80000014;
+}
+static void nv10SetSurfaces3D
+(
+    RIVA_HW_INST *chip,
+    unsigned     surf0,
+    unsigned     surf1
+)
+{
+    RivaSurface3D *Surfaces3D = (RivaSurface3D *)&(chip->FIFO[0x0000E000/4]);
+
+    RIVA_FIFO_FREE(*chip,Tri03,4);
+    chip->FIFO[0x00003800]         = 0x80000007;
+    Surfaces3D->RenderBufferOffset = surf0;
+    Surfaces3D->ZBufferOffset      = surf1;
+    chip->FIFO[0x00003800]         = 0x80000014;
 }
 
 /****************************************************************************\
@@ -1199,7 +1741,7 @@
 *                                                                            *
 \****************************************************************************/
 
-void nv3GetConfig
+static void nv3GetConfig
 (
     RIVA_HW_INST *chip
 )
@@ -1219,20 +1761,20 @@
             switch (chip->PFB[0x00000000/4] & 0x03)
             {
                 case 2:
-                    chip->RamAmountKBytes = 1024 * 4 - 32;
+                    chip->RamAmountKBytes = 1024 * 4;
                     break;
                 case 1:
-                    chip->RamAmountKBytes = 1024 * 2 - 32;
+                    chip->RamAmountKBytes = 1024 * 2;
                     break;
                 default:
-                    chip->RamAmountKBytes = 1024 * 8 - 32;
+                    chip->RamAmountKBytes = 1024 * 8;
                     break;
             }
         }            
         else            
         {
             chip->RamBandwidthKBytesPerSec = 1000000;
-            chip->RamAmountKBytes          = 1024 * 8 - 32;
+            chip->RamAmountKBytes          = 1024 * 8;
         }            
     }
     else
@@ -1244,13 +1786,13 @@
         switch (chip->PFB[0x00000000/4] & 0x00000003)
         {
             case 0:
-                chip->RamAmountKBytes = 1024 * 8 - 32;
+                chip->RamAmountKBytes = 1024 * 8;
                 break;
             case 2:
-                chip->RamAmountKBytes = 1024 * 4 - 32;
+                chip->RamAmountKBytes = 1024 * 4;
                 break;
             default:
-                chip->RamAmountKBytes = 1024 * 2 - 32;
+                chip->RamAmountKBytes = 1024 * 2;
                 break;
         }
     }        
@@ -1260,9 +1802,7 @@
     chip->VBLANKENABLE     = &(chip->PGRAPH[0x0140/4]);
     chip->VBLANK           = &(chip->PGRAPH[0x0100/4]);
     chip->VBlankBit        = 0x00000100;
-    chip->MaxVClockFreqKHz = 230000;
-    chip->LockUnlockIO     = 0x3C4;
-    chip->LockUnlockIndex  = 0x06;
+    chip->MaxVClockFreqKHz = 256000;
     /*
      * Set chip functions.
      */
@@ -1274,9 +1814,9 @@
     chip->SetStartAddress = SetStartAddress;
     chip->SetSurfaces2D   = nv3SetSurfaces2D;
     chip->SetSurfaces3D   = nv3SetSurfaces3D;
+    chip->LockUnlock      = nv3LockUnlock;
 }
-
-void nv4GetConfig
+static void nv4GetConfig
 (
     RIVA_HW_INST *chip
 )
@@ -1284,21 +1824,29 @@
     /*
      * Fill in chip configuration.
      */
-    switch (chip->PFB[0x00000000/4] & 0x00000003)
+    if (chip->PFB[0x00000000/4] & 0x00000100)
     {
-        case 0:
-            chip->RamAmountKBytes = 1024 * 32 - 128;
-            break;
-        case 1:
-            chip->RamAmountKBytes = 1024 * 4 - 128;
-            break;
-        case 2:
-            chip->RamAmountKBytes = 1024 * 8 - 128;
-            break;
-        case 3:
-        default:
-            chip->RamAmountKBytes = 1024 * 16 - 128;
-            break;
+        chip->RamAmountKBytes = ((chip->PFB[0x00000000/4] >> 12) & 0x0F) * 1024 * 2
+                              + 1024 * 2;
+    }
+    else
+    {
+        switch (chip->PFB[0x00000000/4] & 0x00000003)
+        {
+            case 0:
+                chip->RamAmountKBytes = 1024 * 32;
+                break;
+            case 1:
+                chip->RamAmountKBytes = 1024 * 4;
+                break;
+            case 2:
+                chip->RamAmountKBytes = 1024 * 8;
+                break;
+            case 3:
+            default:
+                chip->RamAmountKBytes = 1024 * 16;
+                break;
+        }
     }
     switch ((chip->PFB[0x00000000/4] >> 3) & 0x00000003)
     {
@@ -1315,9 +1863,7 @@
     chip->VBLANKENABLE     = &(chip->PCRTC[0x0140/4]);
     chip->VBLANK           = &(chip->PCRTC[0x0100/4]);
     chip->VBlankBit        = 0x00000001;
-    chip->MaxVClockFreqKHz = 250000;
-    chip->LockUnlockIO     = 0x3D4;
-    chip->LockUnlockIndex  = 0x1F;
+    chip->MaxVClockFreqKHz = 350000;
     /*
      * Set chip functions.
      */
@@ -1329,9 +1875,9 @@
     chip->SetStartAddress = SetStartAddress;
     chip->SetSurfaces2D   = nv4SetSurfaces2D;
     chip->SetSurfaces3D   = nv4SetSurfaces3D;
+    chip->LockUnlock      = nv4LockUnlock;
 }
-
-void nv5GetConfig
+static void nv10GetConfig
 (
     RIVA_HW_INST *chip
 )
@@ -1339,20 +1885,31 @@
     /*
      * Fill in chip configuration.
      */
-    switch (chip->PFB[0x00000000/4] & 0x00000003)
+    switch ((chip->PFB[0x0000020C/4] >> 20) & 0x000000FF)
     {
-        case 0:
-            chip->RamAmountKBytes = 1024 * 32 - 128;
+        case 0x02:
+            chip->RamAmountKBytes = 1024 * 2;
             break;
-        case 1:
-            chip->RamAmountKBytes = 1024 * 4 - 128;
+        case 0x04:
+            chip->RamAmountKBytes = 1024 * 4;
             break;
-        case 2:
-            chip->RamAmountKBytes = 1024 * 8 - 128;
+        case 0x08:
+            chip->RamAmountKBytes = 1024 * 8;
+            break;
+        case 0x10:
+            chip->RamAmountKBytes = 1024 * 16;
+            break;
+        case 0x20:
+            chip->RamAmountKBytes = 1024 * 32;
+            break;
+        case 0x40:
+            chip->RamAmountKBytes = 1024 * 64;
+            break;
+        case 0x80:
+            chip->RamAmountKBytes = 1024 * 128;
             break;
-        case 3:
         default:
-            chip->RamAmountKBytes = 1024 * 16 - 128;
+            chip->RamAmountKBytes = 1024 * 16;
             break;
     }
     switch ((chip->PFB[0x00000000/4] >> 3) & 0x00000003)
@@ -1370,22 +1927,20 @@
     chip->VBLANKENABLE     = &(chip->PCRTC[0x0140/4]);
     chip->VBLANK           = &(chip->PCRTC[0x0100/4]);
     chip->VBlankBit        = 0x00000001;
-    chip->MaxVClockFreqKHz = 250000;
-    chip->LockUnlockIO     = 0x3D4;
-    chip->LockUnlockIndex  = 0x1F;
+    chip->MaxVClockFreqKHz = 350000;
     /*
      * Set chip functions.
      */
-    chip->Busy            = nv4Busy;
+    chip->Busy            = nv10Busy;
     chip->ShowHideCursor  = ShowHideCursor;
     chip->CalcStateExt    = CalcStateExt;
     chip->LoadStateExt    = LoadStateExt;
     chip->UnloadStateExt  = UnloadStateExt;
     chip->SetStartAddress = SetStartAddress;
-    chip->SetSurfaces2D   = nv4SetSurfaces2D;
-    chip->SetSurfaces3D   = nv4SetSurfaces3D;
+    chip->SetSurfaces2D   = nv10SetSurfaces2D;
+    chip->SetSurfaces3D   = nv10SetSurfaces3D;
+    chip->LockUnlock      = nv10LockUnlock;
 }
-
 int RivaGetConfig
 (
     RIVA_HW_INST *chip
@@ -1400,14 +1955,15 @@
      */
     switch (chip->Architecture)
     {
-        case 3:
+        case NV_ARCH_03:
             nv3GetConfig(chip);
             break;
-        case 4:
+        case NV_ARCH_04:
             nv4GetConfig(chip);
             break;
-	    case 5:
-	    nv5GetConfig(chip);
+        case NV_ARCH_10:
+            nv10GetConfig(chip);
+            break;
         default:
             return (-1);
     }
@@ -1420,6 +1976,7 @@
     chip->Pixmap = (RivaPixmap              *)&(chip->FIFO[0x00006000/4]);
     chip->Blt    = (RivaScreenBlt           *)&(chip->FIFO[0x00008000/4]);
     chip->Bitmap = (RivaBitmap              *)&(chip->FIFO[0x0000A000/4]);
+    chip->Line   = (RivaLine                *)&(chip->FIFO[0x0000C000/4]);
     chip->Tri03  = (RivaTexturedTriangle03  *)&(chip->FIFO[0x0000E000/4]);
     return (0);
 }
diff -u --recursive --new-file v2.4.1/linux/drivers/video/riva/riva_hw.h linux/drivers/video/riva/riva_hw.h
--- v2.4.1/linux/drivers/video/riva/riva_hw.h	Tue Feb 29 11:07:04 2000
+++ linux/drivers/video/riva/riva_hw.h	Sat Feb  3 12:48:00 2001
@@ -1,6 +1,6 @@
 /***************************************************************************\
 |*                                                                           *|
-|*       Copyright 1993-1998 NVIDIA, Corporation.  All rights reserved.      *|
+|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
 |*                                                                           *|
 |*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
 |*     international laws.  Users and possessors of this source code are     *|
@@ -11,7 +11,7 @@
 |*     tion and  internal comments to the code,  notices to the end user     *|
 |*     as follows:                                                           *|
 |*                                                                           *|
-|*       Copyright 1993-1998 NVIDIA, Corporation.  All rights reserved.      *|
+|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
 |*                                                                           *|
 |*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
 |*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
@@ -36,18 +36,36 @@
 |*     those rights set forth herein.                                        *|
 |*                                                                           *|
 \***************************************************************************/
-/* 
- * GPL licensing note -- nVidia is allowing a liberal interpretation of 
- * the documentation restriction above, to merely say that this nVidia's
- * copyright and disclaimer should be included with all code derived 
- * from this source.  -- Jeff Garzik <jgarzik@mandrakesoft.com>, 01/Nov/99
- */
-
-/* $XFree86: xc/programs/Xserver/hw/xfree86/vga256/drivers/nv/riva_hw.h,v 1.1.2.2 1998/12/22 16:33:19 hohndel Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_hw.h,v 1.6 2000/02/08 17:19:12 dawes Exp $ */
 #ifndef __RIVA_HW_H__
 #define __RIVA_HW_H__
-#define RIVA_SW_VERSION 0x00010000
+#define RIVA_SW_VERSION 0x00010003
 
+/*
+ * Typedefs to force certain sized values.
+ */
+typedef unsigned char  U008;
+typedef unsigned short U016;
+typedef unsigned int   U032;
+
+/*
+ * HW access macros.
+ */
+#define NV_WR08(p,i,d)  (((U008 *)(p))[i]=(d))
+#define NV_RD08(p,i)    (((U008 *)(p))[i])
+#define NV_WR16(p,i,d)  (((U016 *)(p))[(i)/2]=(d))
+#define NV_RD16(p,i)    (((U016 *)(p))[(i)/2])
+#define NV_WR32(p,i,d)  (((U032 *)(p))[(i)/4]=(d))
+#define NV_RD32(p,i)    (((U032 *)(p))[(i)/4])
+#define VGA_WR08(p,i,d) NV_WR08(p,i,d)
+#define VGA_RD08(p,i)   NV_RD08(p,i)
+
+/*
+ * Define supported architectures.
+ */
+#define NV_ARCH_03  0x03
+#define NV_ARCH_04  0x04
+#define NV_ARCH_10  0x10
 /***************************************************************************\
 *                                                                           *
 *                             FIFO registers.                               *
@@ -59,161 +77,165 @@
  */
 typedef volatile struct
 {
-    unsigned reserved00[4];
-    unsigned short FifoFree;
-    unsigned short Nop;
-    unsigned reserved01[0x0BB];
-    unsigned Rop3;
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop;
+    U032 reserved01[0x0BB];
+    U032 Rop3;
 } RivaRop;
 /*
  * 8X8 Monochrome pattern.
  */
 typedef volatile struct
 {
-    unsigned reserved00[4];
-    unsigned short FifoFree;
-    unsigned short Nop;
-    unsigned reserved01[0x0BD];
-    unsigned Shape;
-    unsigned reserved03[0x001];
-    unsigned Color0;
-    unsigned Color1;
-    unsigned Monochrome[2];
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop;
+    U032 reserved01[0x0BD];
+    U032 Shape;
+    U032 reserved03[0x001];
+    U032 Color0;
+    U032 Color1;
+    U032 Monochrome[2];
 } RivaPattern;
 /*
  * Scissor clip rectangle.
  */
 typedef volatile struct
 {
-    unsigned reserved00[4];
-    unsigned short FifoFree;
-    unsigned short Nop;
-    unsigned reserved01[0x0BB];
-    unsigned TopLeft;
-    unsigned WidthHeight;
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop;
+    U032 reserved01[0x0BB];
+    U032 TopLeft;
+    U032 WidthHeight;
 } RivaClip;
 /*
  * 2D filled rectangle.
  */
 typedef volatile struct
 {
-    unsigned reserved00[4];
-    unsigned short FifoFree;
-    unsigned short Nop[1];
-    unsigned reserved01[0x0BC];
-    unsigned Color;
-    unsigned reserved03[0x03E];
-    unsigned TopLeft;
-    unsigned WidthHeight;
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop[1];
+    U032 reserved01[0x0BC];
+    U032 Color;
+    U032 reserved03[0x03E];
+    U032 TopLeft;
+    U032 WidthHeight;
 } RivaRectangle;
 /*
  * 2D screen-screen BLT.
  */
 typedef volatile struct
 {
-    unsigned reserved00[4];
-    unsigned short FifoFree;
-    unsigned short Nop;
-    unsigned reserved01[0x0BB];
-    unsigned TopLeftSrc;
-    unsigned TopLeftDst;
-    unsigned WidthHeight;
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop;
+    U032 reserved01[0x0BB];
+    U032 TopLeftSrc;
+    U032 TopLeftDst;
+    U032 WidthHeight;
 } RivaScreenBlt;
 /*
  * 2D pixel BLT.
  */
 typedef volatile struct
 {
-    unsigned reserved00[4];
-    unsigned short FifoFree;
-    unsigned short Nop[1];
-    unsigned reserved01[0x0BC];
-    unsigned TopLeft;
-    unsigned WidthHeight;
-    unsigned WidthHeightIn;
-    unsigned reserved02[0x03C];
-    unsigned Pixels;
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop[1];
+    U032 reserved01[0x0BC];
+    U032 TopLeft;
+    U032 WidthHeight;
+    U032 WidthHeightIn;
+    U032 reserved02[0x03C];
+    U032 Pixels;
 } RivaPixmap;
 /*
  * Filled rectangle combined with monochrome expand.  Useful for glyphs.
  */
 typedef volatile struct
 {
-    unsigned reserved00[4];
-    unsigned short FifoFree;
-    unsigned short Nop;
-    unsigned reserved01[0x0BB];
-    unsigned reserved03[(0x040)-1];
-    unsigned Color1A;
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop;
+    U032 reserved01[0x0BB];
+    U032 reserved03[(0x040)-1];
+    U032 Color1A;
     struct
     {
-        unsigned TopLeft;
-        unsigned WidthHeight;
+        U032 TopLeft;
+        U032 WidthHeight;
     } UnclippedRectangle[64];
-    unsigned reserved04[(0x080)-3];
+    U032 reserved04[(0x080)-3];
     struct
     {
-        unsigned TopLeft;
-        unsigned BottomRight;
+        U032 TopLeft;
+        U032 BottomRight;
     } ClipB;
-    unsigned Color1B;
+    U032 Color1B;
     struct
     {
-        unsigned TopLeft;
-        unsigned BottomRight;
+        U032 TopLeft;
+        U032 BottomRight;
     } ClippedRectangle[64];
-    unsigned reserved05[(0x080)-5];
+    U032 reserved05[(0x080)-5];
     struct
     {
-        unsigned TopLeft;
-        unsigned BottomRight;
+        U032 TopLeft;
+        U032 BottomRight;
     } ClipC;
-    unsigned Color1C;
-    unsigned WidthHeightC;
-    unsigned PointC;
-    unsigned MonochromeData1C;
-    unsigned reserved06[(0x080)+121];
+    U032 Color1C;
+    U032 WidthHeightC;
+    U032 PointC;
+    U032 MonochromeData1C;
+    U032 reserved06[(0x080)+121];
     struct
     {
-        unsigned TopLeft;
-        unsigned BottomRight;
+        U032 TopLeft;
+        U032 BottomRight;
     } ClipD;
-    unsigned Color1D;
-    unsigned WidthHeightInD;
-    unsigned WidthHeightOutD;
-    unsigned PointD;
-    unsigned MonochromeData1D;
-    unsigned reserved07[(0x080)+120];
+    U032 Color1D;
+    U032 WidthHeightInD;
+    U032 WidthHeightOutD;
+    U032 PointD;
+    U032 MonochromeData1D;
+    U032 reserved07[(0x080)+120];
     struct
     {
-        unsigned TopLeft;
-        unsigned BottomRight;
+        U032 TopLeft;
+        U032 BottomRight;
     } ClipE;
-    unsigned Color0E;
-    unsigned Color1E;
-    unsigned WidthHeightInE;
-    unsigned WidthHeightOutE;
-    unsigned PointE;
-    unsigned MonochromeData01E;
+    U032 Color0E;
+    U032 Color1E;
+    U032 WidthHeightInE;
+    U032 WidthHeightOutE;
+    U032 PointE;
+    U032 MonochromeData01E;
 } RivaBitmap;
 /*
  * 3D textured, Z buffered triangle.
  */
 typedef volatile struct
 {
-    unsigned reserved00[4];
-    unsigned short FifoFree;
-    unsigned short Nop;
-    unsigned reserved01[0x0BC];
-    unsigned TextureOffset;
-    unsigned TextureFormat;
-    unsigned TextureFilter;
-    unsigned FogColor;
-    unsigned Control;
-    unsigned AlphaTest;
-    unsigned reserved02[0x339];
-    unsigned FogAndIndex;
-    unsigned Color;
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop;
+    U032 reserved01[0x0BC];
+    U032 TextureOffset;
+    U032 TextureFormat;
+    U032 TextureFilter;
+    U032 FogColor;
+/* This is a problem on LynxOS */
+#ifdef Control
+#undef Control
+#endif
+    U032 Control;
+    U032 AlphaTest;
+    U032 reserved02[0x339];
+    U032 FogAndIndex;
+    U032 Color;
     float ScreenX;
     float ScreenY;
     float ScreenZ;
@@ -221,7 +243,90 @@
     float TextureS;
     float TextureT;
 } RivaTexturedTriangle03;
-
+typedef volatile struct
+{
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop;
+    U032 reserved01[0x0BB];
+    U032 ColorKey;
+    U032 TextureOffset;
+    U032 TextureFormat;
+    U032 TextureFilter;
+    U032 Blend;
+/* This is a problem on LynxOS */
+#ifdef Control
+#undef Control
+#endif
+    U032 Control;
+    U032 FogColor;
+    U032 reserved02[0x39];
+    struct
+    {
+        float ScreenX;
+        float ScreenY;
+        float ScreenZ;
+        float EyeM;
+        U032 Color;
+        U032 Specular;
+        float TextureS;
+        float TextureT;
+    } Vertex[16];
+    U032 DrawTriangle3D;
+} RivaTexturedTriangle05;
+/*
+ * 2D line.
+ */
+typedef volatile struct
+{
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop[1];
+    U032 reserved01[0x0BC];
+    U032 Color;             /* source color               0304-0307*/
+    U032 Reserved02[0x03e];
+    struct {                /* start aliased methods in array   0400-    */
+        U032 point0;        /* y_x S16_S16 in pixels            0-   3*/
+        U032 point1;        /* y_x S16_S16 in pixels            4-   7*/
+    } Lin[16];              /* end of aliased methods in array      -047f*/
+    struct {                /* start aliased methods in array   0480-    */
+        U032 point0X;       /* in pixels, 0 at left                0-   3*/
+        U032 point0Y;       /* in pixels, 0 at top                 4-   7*/
+        U032 point1X;       /* in pixels, 0 at left                8-   b*/
+        U032 point1Y;       /* in pixels, 0 at top                 c-   f*/
+    } Lin32[8];             /* end of aliased methods in array      -04ff*/
+    U032 PolyLin[32];       /* y_x S16_S16 in pixels         0500-057f*/
+    struct {                /* start aliased methods in array   0580-    */
+        U032 x;             /* in pixels, 0 at left                0-   3*/
+        U032 y;             /* in pixels, 0 at top                 4-   7*/
+    } PolyLin32[16];        /* end of aliased methods in array      -05ff*/
+    struct {                /* start aliased methods in array   0600-    */
+        U032 color;         /* source color                     0-   3*/
+        U032 point;         /* y_x S16_S16 in pixels            4-   7*/
+    } ColorPolyLin[16];     /* end of aliased methods in array      -067f*/
+} RivaLine;
+/*
+ * 2D/3D surfaces
+ */
+typedef volatile struct
+{
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop;
+    U032 reserved01[0x0BE];
+    U032 Offset;
+} RivaSurface;
+typedef volatile struct
+{
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop;
+    U032 reserved01[0x0BD];
+    U032 Pitch;
+    U032 RenderBufferOffset;
+    U032 ZBufferOffset;
+} RivaSurface3D;
+    
 /***************************************************************************\
 *                                                                           *
 *                        Virtualized RIVA H/W interface.                    *
@@ -238,35 +343,37 @@
     /*
      * Chip specific settings.
      */
-    unsigned Architecture;
-    unsigned Version;
-    unsigned CrystalFreqKHz;
-    unsigned RamAmountKBytes;
-    unsigned MaxVClockFreqKHz;
-    unsigned RamBandwidthKBytesPerSec;
-    unsigned EnableIRQ;
-    unsigned IO;
-    unsigned LockUnlockIO;
-    unsigned LockUnlockIndex;
-    unsigned VBlankBit;
-    unsigned FifoFreeCount;
+    U032 Architecture;
+    U032 Version;
+    U032 CrystalFreqKHz;
+    U032 RamAmountKBytes;
+    U032 MaxVClockFreqKHz;
+    U032 RamBandwidthKBytesPerSec;
+    U032 EnableIRQ;
+    U032 IO;
+    U032 VBlankBit;
+    U032 FifoFreeCount;
+    U032 FifoEmptyCount;
     /*
      * Non-FIFO registers.
      */
-    volatile unsigned *PCRTC;
-    volatile unsigned *PRAMDAC;
-    volatile unsigned *PFB;
-    volatile unsigned *PFIFO;
-    volatile unsigned *PGRAPH;
-    volatile unsigned *PEXTDEV;
-    volatile unsigned *PTIMER;
-    volatile unsigned *PMC;
-    volatile unsigned *PRAMIN;
-    volatile unsigned *FIFO;
-    volatile unsigned *CURSOR;
-    volatile unsigned *CURSORPOS;
-    volatile unsigned *VBLANKENABLE;
-    volatile unsigned *VBLANK;
+    volatile U032 *PCRTC;
+    volatile U032 *PRAMDAC;
+    volatile U032 *PFB;
+    volatile U032 *PFIFO;
+    volatile U032 *PGRAPH;
+    volatile U032 *PEXTDEV;
+    volatile U032 *PTIMER;
+    volatile U032 *PMC;
+    volatile U032 *PRAMIN;
+    volatile U032 *FIFO;
+    volatile U032 *CURSOR;
+    volatile U032 *CURSORPOS;
+    volatile U032 *VBLANKENABLE;
+    volatile U032 *VBLANK;
+    volatile U008 *PCIO;
+    volatile U008 *PVIO;
+    volatile U008 *PDIO;
     /*
      * Common chip functions.
      */
@@ -274,10 +381,11 @@
     void (*CalcStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *,int,int,int,int,int,int,int,int,int,int,int,int,int);
     void (*LoadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *);
     void (*UnloadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *);
-    void (*SetStartAddress)(struct _riva_hw_inst *,unsigned);
-    void (*SetSurfaces2D)(struct _riva_hw_inst *,unsigned,unsigned);
-    void (*SetSurfaces3D)(struct _riva_hw_inst *,unsigned,unsigned);
+    void (*SetStartAddress)(struct _riva_hw_inst *,U032);
+    void (*SetSurfaces2D)(struct _riva_hw_inst *,U032,U032);
+    void (*SetSurfaces3D)(struct _riva_hw_inst *,U032,U032);
     int  (*ShowHideCursor)(struct _riva_hw_inst *,int);
+    void (*LockUnlock)(struct _riva_hw_inst *, int);
     /*
      * Current extended mode settings.
      */
@@ -291,38 +399,40 @@
     RivaPixmap              *Pixmap;
     RivaScreenBlt           *Blt;
     RivaBitmap              *Bitmap;
+    RivaLine                *Line;
     RivaTexturedTriangle03  *Tri03;
+    RivaTexturedTriangle05  *Tri05;
 } RIVA_HW_INST;
 /*
  * Extended mode state information.
  */
 typedef struct _riva_hw_state
 {
-    unsigned bpp;
-    unsigned width;
-    unsigned height;
-    unsigned repaint0;
-    unsigned repaint1;
-    unsigned screen;
-    unsigned pixel;
-    unsigned horiz;
-    unsigned arbitration0;
-    unsigned arbitration1;
-    unsigned vpll;
-    unsigned pllsel;
-    unsigned general;
-    unsigned config;
-    unsigned cursor0;
-    unsigned cursor1;
-    unsigned cursor2;
-    unsigned offset0;
-    unsigned offset1;
-    unsigned offset2;
-    unsigned offset3;
-    unsigned pitch0;
-    unsigned pitch1;
-    unsigned pitch2;
-    unsigned pitch3;
+    U032 bpp;
+    U032 width;
+    U032 height;
+    U032 repaint0;
+    U032 repaint1;
+    U032 screen;
+    U032 pixel;
+    U032 horiz;
+    U032 arbitration0;
+    U032 arbitration1;
+    U032 vpll;
+    U032 pllsel;
+    U032 general;
+    U032 config;
+    U032 cursor0;
+    U032 cursor1;
+    U032 cursor2;
+    U032 offset0;
+    U032 offset1;
+    U032 offset2;
+    U032 offset3;
+    U032 pitch0;
+    U032 pitch1;
+    U032 pitch2;
+    U032 pitch3;
 } RIVA_HW_STATE;
 /*
  * External routines.
@@ -331,13 +441,12 @@
 /*
  * FIFO Free Count. Should attempt to yield processor if RIVA is busy.
  */
-#define RIVA_FIFO_FREE(hwinst,hwptr,cnt)                                    \
-{                                                                           \
-while ((hwinst).FifoFreeCount < (cnt))                                      \
-{                                                                           \
-    (hwinst).FifoFreeCount = (hwinst).hwptr->FifoFree >> 2;                 \
-}                                                                           \
-(hwinst).FifoFreeCount -= (cnt);                                            \
+
+#define RIVA_FIFO_FREE(hwinst,hwptr,cnt)                           \
+{                                                                  \
+   while ((hwinst).FifoFreeCount < (cnt))                          \
+	(hwinst).FifoFreeCount = (hwinst).hwptr->FifoFree >> 2;        \
+   (hwinst).FifoFreeCount -= (cnt);                                \
 }
 #endif /* __RIVA_HW_H__ */
 
diff -u --recursive --new-file v2.4.1/linux/drivers/video/riva/riva_tbl.h linux/drivers/video/riva/riva_tbl.h
--- v2.4.1/linux/drivers/video/riva/riva_tbl.h	Wed Jul  5 10:56:12 2000
+++ linux/drivers/video/riva/riva_tbl.h	Sat Feb  3 12:48:00 2001
@@ -1,6 +1,6 @@
  /***************************************************************************\
 |*                                                                           *|
-|*       Copyright 1993-1998 NVIDIA, Corporation.  All rights reserved.      *|
+|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
 |*                                                                           *|
 |*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
 |*     international laws.  Users and possessors of this source code are     *|
@@ -11,7 +11,7 @@
 |*     tion and  internal comments to the code,  notices to the end user     *|
 |*     as follows:                                                           *|
 |*                                                                           *|
-|*       Copyright 1993-1998 NVIDIA, Corporation.  All rights reserved.      *|
+|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
 |*                                                                           *|
 |*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
 |*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
@@ -36,14 +36,7 @@
 |*     those rights set forth herein.                                        *|
 |*                                                                           *|
  \***************************************************************************/
-/* 
- * GPL licensing note -- nVidia is allowing a liberal interpretation of 
- * the documentation restriction above, to merely say that this nVidia's
- * copyright and disclaimer should be included with all code derived 
- * from this source.  -- Jeff Garzik <jgarzik@mandrakesoft.com>, 01/Nov/99
- */
-
-/* $XFree86: xc/programs/Xserver/hw/xfree86/vga256/drivers/nv/riva_tbl.h,v 1.1.2.2 1998/12/22 16:33:20 hohndel Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_tbl.h,v 1.5 2000/02/08 17:19:12 dawes Exp $ */
 /*
  * RIVA Fixed Functionality Init Tables.
  */
@@ -60,8 +53,6 @@
     {0x00000050, 0x00000000},
     {0x00000040, 0xFFFFFFFF}
 };
-
-#if 0
 static unsigned RivaTableFIFO[][2] =
 {
     {0x00000000, 0x80000000},
@@ -72,8 +63,6 @@
     {0x00002800, 0x80000012},
     {0x00003800, 0x80000013}
 };
-#endif
-
 static unsigned nv3TablePFIFO[][2] =
 {
     {0x00000140, 0x00000000},
@@ -161,6 +150,14 @@
     {0x00000205, 0x00C50342},
     {0x00000208, 0x80000002},
     {0x00000209, 0x00C60343},
+    {0x0000020C, 0x80000003},
+    {0x0000020D, 0x00DC0348},
+    {0x00000210, 0x80000004},
+    {0x00000211, 0x00DC0349},
+    {0x00000214, 0x80000005},
+    {0x00000215, 0x00DC034A},
+    {0x00000218, 0x80000006},
+    {0x00000219, 0x00DC034B},
     {0x00000240, 0x80000010},
     {0x00000241, 0x00D10344},
     {0x00000244, 0x80000011},
@@ -189,13 +186,31 @@
     {0x00000D1B, 0x00000000},
     {0x00000D1D, 0x00000140},
     {0x00000D1E, 0x00000000},
-    {0x00000D1F, 0x00000000}
+    {0x00000D1F, 0x00000000},
+    {0x00000D20, 0x10100200},
+    {0x00000D21, 0x00000000},
+    {0x00000D22, 0x00000000},
+    {0x00000D23, 0x00000000},
+    {0x00000D24, 0x10210200},
+    {0x00000D25, 0x00000000},
+    {0x00000D26, 0x00000000},
+    {0x00000D27, 0x00000000},
+    {0x00000D28, 0x10420200},
+    {0x00000D29, 0x00000000},
+    {0x00000D2A, 0x00000000},
+    {0x00000D2B, 0x00000000},
+    {0x00000D2C, 0x10830200},
+    {0x00000D2D, 0x00000000},
+    {0x00000D2E, 0x00000000},
+    {0x00000D2F, 0x00000000} 
 };
 static unsigned nv3TablePRAMIN_8BPP[][2] =
 {
+    /*           0xXXXXX3XX For  MSB mono format */
+    /*           0xXXXXX2XX For  LSB mono format */
     {0x00000D04, 0x10110203},
     {0x00000D08, 0x10110203},
-    {0x00000D0C, 0x10110203},
+    {0x00000D0C, 0x1011020B},
     {0x00000D10, 0x10118203},
     {0x00000D14, 0x10110203},
     {0x00000D18, 0x10110203},
@@ -203,9 +218,11 @@
 };
 static unsigned nv3TablePRAMIN_15BPP[][2] =
 {
+    /*           0xXXXXX2XX For  MSB mono format */
+    /*           0xXXXXX3XX For  LSB mono format */
     {0x00000D04, 0x10110200},
     {0x00000D08, 0x10110200},
-    {0x00000D0C, 0x10110200},
+    {0x00000D0C, 0x10110208},
     {0x00000D10, 0x10118200},
     {0x00000D14, 0x10110200},
     {0x00000D18, 0x10110200},
@@ -213,19 +230,27 @@
 };
 static unsigned nv3TablePRAMIN_32BPP[][2] =
 {
+    /*           0xXXXXX3XX For  MSB mono format */
+    /*           0xXXXXX2XX For  LSB mono format */
     {0x00000D04, 0x10110201},
     {0x00000D08, 0x10110201},
-    {0x00000D0C, 0x10110201},
+    {0x00000D0C, 0x10110209},
     {0x00000D10, 0x10118201},
     {0x00000D14, 0x10110201},
     {0x00000D18, 0x10110201},
     {0x00000D1C, 0x10419208}
 };
+static unsigned nv4TableFIFO[][2] =
+{
+    {0x00003800, 0x80000014}
+};
 static unsigned nv4TablePFIFO[][2] =
 {
     {0x00000140, 0x00000000},
     {0x00000480, 0x00000000},
     {0x00000494, 0x00000000},
+    {0x00000481, 0x00000000},
+    {0x0000048B, 0x00000000},
     {0x00000400, 0x00000000},
     {0x00000414, 0x00000000},
     {0x00000084, 0x03000100},  
@@ -284,45 +309,44 @@
     {0x0000005A, 0x00000000},
     {0x0000005B, 0x00000000},
     {0x00000196, 0x00000000},
-    {0x000001A1, 0x00FFFFFF},
+    {0x000001A1, 0x01FFFFFF},
     {0x00000197, 0x00000000},
-    {0x000001A2, 0x00FFFFFF},
+    {0x000001A2, 0x01FFFFFF},
     {0x00000198, 0x00000000},
-    {0x000001A3, 0x00FFFFFF},
+    {0x000001A3, 0x01FFFFFF},
     {0x00000199, 0x00000000},
-    {0x000001A4, 0x00FFFFFF},
+    {0x000001A4, 0x01FFFFFF},
     {0x00000050, 0x00000000},
     {0x00000040, 0xFFFFFFFF},
     {0x0000005C, 0x10010100},
-    {0x000001C8, 0x00000001}
+    {0x000001C4, 0xFFFFFFFF},
+    {0x000001C8, 0x00000001},
+    {0x00000204, 0x00000000},
+    {0x000001C3, 0x00000001}
 };
 static unsigned nv4TablePGRAPH_8BPP[][2] =
 {
-    {0x000001C4, 0xFFFFFFFF},
     {0x000001C9, 0x00111111},
     {0x00000186, 0x00001010},
-    {0x0000020C, 0x01010101}
+    {0x0000020C, 0x03020202}
 };
 static unsigned nv4TablePGRAPH_15BPP[][2] =
 {
-    {0x000001C4, 0xFFFFFFFF},
     {0x000001C9, 0x00226222},
     {0x00000186, 0x00002071},
-    {0x0000020C, 0x09090909}
+    {0x0000020C, 0x09080808}
 };
 static unsigned nv4TablePGRAPH_16BPP[][2] =
 {
-    {0x000001C4, 0xFFFFFFFF},
     {0x000001C9, 0x00556555},
     {0x00000186, 0x000050C2},
-    {0x0000020C, 0x0C0C0C0C}
+    {0x0000020C, 0x0C0B0B0B}
 };
 static unsigned nv4TablePGRAPH_32BPP[][2] =
 {
-    {0x000001C4, 0xFFFFFFFF},
     {0x000001C9, 0x0077D777},
     {0x00000186, 0x000070E5},
-    {0x0000020C, 0x07070707}
+    {0x0000020C, 0x0E0D0D0D}
 };
 static unsigned nv4TablePRAMIN[][2] =
 {
@@ -334,14 +358,26 @@
     {0x00000005, 0x80011147},
     {0x00000006, 0x80000013},
     {0x00000007, 0x80011148},
+    {0x00000008, 0x80000014},
+    {0x00000009, 0x80011149},
+    {0x0000000A, 0x80000015},
+    {0x0000000B, 0x8001114A},
     {0x00000020, 0x80000000},
     {0x00000021, 0x80011142},
     {0x00000022, 0x80000001},
     {0x00000023, 0x80011143},
     {0x00000024, 0x80000002},
     {0x00000025, 0x80011144}, 
+    {0x00000026, 0x80000003},
+    {0x00000027, 0x8001114B},
+    {0x00000028, 0x80000004},
+    {0x00000029, 0x8001114C},
+    {0x0000002A, 0x80000005},
+    {0x0000002B, 0x8001114D},
+    {0x0000002C, 0x80000006},
+    {0x0000002D, 0x8001114E},
     {0x00000500, 0x00003000},
-    {0x00000501, 0x02FFFFFF},
+    {0x00000501, 0x01FFFFFF},
     {0x00000502, 0x00000002},
     {0x00000503, 0x00000002},
     {0x00000508, 0x01008043},
@@ -350,57 +386,558 @@
     {0x0000050C, 0x01008019},
     {0x0000050E, 0x00000000},
     {0x0000050F, 0x00000000},
+#if 1
     {0x00000510, 0x01008018},
+#else
+    {0x00000510, 0x01008044},
+#endif
     {0x00000512, 0x00000000},
     {0x00000513, 0x00000000},
-    {0x00000514, 0x0100A033},
+    {0x00000514, 0x01008021},
     {0x00000516, 0x00000000},
     {0x00000517, 0x00000000},
     {0x00000518, 0x0100805F},
     {0x0000051A, 0x00000000},
     {0x0000051B, 0x00000000},
+#if 1
     {0x0000051C, 0x0100804B},
+#else
+    {0x0000051C, 0x0100804A},
+#endif
     {0x0000051E, 0x00000000},
     {0x0000051F, 0x00000000},
     {0x00000520, 0x0100A048},
     {0x00000521, 0x00000D01},
     {0x00000522, 0x11401140},
-    {0x00000523, 0x00000000}
+    {0x00000523, 0x00000000},
+    {0x00000524, 0x0300A054},
+    {0x00000525, 0x00000D01},
+    {0x00000526, 0x11401140},
+    {0x00000527, 0x00000000},
+    {0x00000528, 0x0300A055},
+    {0x00000529, 0x00000D01},
+    {0x0000052A, 0x11401140},
+    {0x0000052B, 0x00000000},
+    {0x0000052C, 0x00000058},
+    {0x0000052E, 0x11401140},
+    {0x0000052F, 0x00000000},
+    {0x00000530, 0x00000059},
+    {0x00000532, 0x11401140},
+    {0x00000533, 0x00000000},
+    {0x00000534, 0x0000005A},
+    {0x00000536, 0x11401140},
+    {0x00000537, 0x00000000},
+    {0x00000538, 0x0000005B},
+    {0x0000053A, 0x11401140},
+    {0x0000053B, 0x00000000} 
 };
 static unsigned nv4TablePRAMIN_8BPP[][2] =
 {
-    {0x00000509, 0x00000301},
-    {0x0000050D, 0x00000301},
-    {0x00000511, 0x00000301},
-    {0x00000515, 0x00000301},
-    {0x00000519, 0x00000301},
-    {0x0000051D, 0x00000301}
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000302},
+    {0x0000050D, 0x00000302},
+    {0x00000511, 0x00000202},
+    {0x00000515, 0x00000302},
+    {0x00000519, 0x00000302},
+    {0x0000051D, 0x00000302},
+    {0x0000052D, 0x00000302},
+    {0x0000052E, 0x00000302},
+    {0x00000535, 0x00000000},
+    {0x00000539, 0x00000000} 
 };
 static unsigned nv4TablePRAMIN_15BPP[][2] =
 {
-    {0x00000509, 0x00000901},
-    {0x0000050D, 0x00000901},
-    {0x00000511, 0x00000901},
-    {0x00000515, 0x00000901},
-    {0x00000519, 0x00000901},
-    {0x0000051D, 0x00000901}
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000902},
+    {0x0000050D, 0x00000902},
+    {0x00000511, 0x00000802},
+    {0x00000515, 0x00000902},
+    {0x00000519, 0x00000902},
+    {0x0000051D, 0x00000902},
+    {0x0000052D, 0x00000902},
+    {0x0000052E, 0x00000902},
+    {0x00000535, 0x00000702},
+    {0x00000539, 0x00000702} 
 };
 static unsigned nv4TablePRAMIN_16BPP[][2] =
 {
-    {0x00000509, 0x00000C01},
-    {0x0000050D, 0x00000C01},
-    {0x00000511, 0x00000C01},
-    {0x00000515, 0x00000C01},
-    {0x00000519, 0x00000C01},
-    {0x0000051D, 0x00000C01}
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000C02},
+    {0x0000050D, 0x00000C02},
+    {0x00000511, 0x00000B02},
+    {0x00000515, 0x00000C02},
+    {0x00000519, 0x00000C02},
+    {0x0000051D, 0x00000C02},
+    {0x0000052D, 0x00000C02},
+    {0x0000052E, 0x00000C02},
+    {0x00000535, 0x00000702},
+    {0x00000539, 0x00000702} 
 };
 static unsigned nv4TablePRAMIN_32BPP[][2] =
 {
-    {0x00000509, 0x00000E01},
-    {0x0000050D, 0x00000E01},
-    {0x00000511, 0x00000E01},
-    {0x00000515, 0x00000E01},
-    {0x00000519, 0x00000E01},
-    {0x0000051D, 0x00000E01}
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000E02},
+    {0x0000050D, 0x00000E02},
+    {0x00000511, 0x00000D02},
+    {0x00000515, 0x00000E02},
+    {0x00000519, 0x00000E02},
+    {0x0000051D, 0x00000E02},
+    {0x0000052D, 0x00000E02},
+    {0x0000052E, 0x00000E02},
+    {0x00000535, 0x00000E02},
+    {0x00000539, 0x00000E02} 
+};
+static unsigned nv10TableFIFO[][2] =
+{
+    {0x00003800, 0x80000014}
+};
+static unsigned nv10TablePFIFO[][2] =
+{
+    {0x00000140, 0x00000000},
+    {0x00000480, 0x00000000},
+    {0x00000494, 0x00000000},
+    {0x00000481, 0x00000000},
+    {0x0000048B, 0x00000000},
+    {0x00000400, 0x00000000},
+    {0x00000414, 0x00000000},
+    {0x00000084, 0x03000100},
+    {0x00000085, 0x00000110},
+    {0x00000086, 0x00000112},
+    {0x00000143, 0x0000FFFF},
+    {0x00000496, 0x0000FFFF},
+    {0x00000050, 0x00000000},
+    {0x00000040, 0xFFFFFFFF},
+    {0x00000415, 0x00000001},
+    {0x00000480, 0x00000001},
+    {0x00000494, 0x00000001},
+    {0x00000495, 0x00000001},
+    {0x00000140, 0x00000001}
+};
+static unsigned nv10TablePGRAPH[][2] =
+{
+    {0x00000020, 0x0003FFFF},
+    {0x00000021, 0x00118701},
+    {0x00000022, 0x24F82AD9},
+    {0x00000023, 0x55DE0030},
+    {0x00000020, 0x00000000},
+    {0x00000024, 0x00000000},
+    {0x00000058, 0x00000000},
+    {0x00000060, 0x00000000},
+    {0x00000068, 0x00000000},
+    {0x00000070, 0x00000000},
+    {0x00000078, 0x00000000},
+    {0x00000059, 0x00000000},
+    {0x00000061, 0x00000000},
+    {0x00000069, 0x00000000},
+    {0x00000071, 0x00000000},
+    {0x00000079, 0x00000000},
+    {0x0000005A, 0x00000000},
+    {0x00000062, 0x00000000},
+    {0x0000006A, 0x00000000},
+    {0x00000072, 0x00000000},
+    {0x0000007A, 0x00000000},
+    {0x0000005B, 0x00000000},
+    {0x00000063, 0x00000000},
+    {0x0000006B, 0x00000000},
+    {0x00000073, 0x00000000},
+    {0x0000007B, 0x00000000},
+    {0x0000005C, 0x00000000},
+    {0x00000064, 0x00000000},
+    {0x0000006C, 0x00000000},
+    {0x00000074, 0x00000000},
+    {0x0000007C, 0x00000000},
+    {0x0000005D, 0x00000000},
+    {0x00000065, 0x00000000},
+    {0x0000006D, 0x00000000},
+    {0x00000075, 0x00000000},
+    {0x0000007D, 0x00000000},
+    {0x0000005E, 0x00000000},
+    {0x00000066, 0x00000000},
+    {0x0000006E, 0x00000000},
+    {0x00000076, 0x00000000},
+    {0x0000007E, 0x00000000},
+    {0x0000005F, 0x00000000},
+    {0x00000067, 0x00000000},
+    {0x0000006F, 0x00000000},
+    {0x00000077, 0x00000000},
+    {0x0000007F, 0x00000000},
+    {0x00000053, 0x00000000},
+    {0x00000054, 0x00000000},
+    {0x00000055, 0x00000000},
+    {0x00000056, 0x00000000},
+    {0x00000057, 0x00000000},
+    {0x00000196, 0x00000000},
+    {0x000001A1, 0x01FFFFFF},
+    {0x00000197, 0x00000000},
+    {0x000001A2, 0x01FFFFFF},
+    {0x00000198, 0x00000000},
+    {0x000001A3, 0x01FFFFFF},
+    {0x00000199, 0x00000000},
+    {0x000001A4, 0x01FFFFFF},
+    {0x0000019A, 0x00000000},
+    {0x000001A5, 0x01FFFFFF},
+    {0x0000019B, 0x00000000},
+    {0x000001A6, 0x01FFFFFF},
+    {0x00000050, 0x01111111},
+    {0x00000040, 0xFFFFFFFF},
+    {0x00000051, 0x10010100},
+    {0x000001C5, 0xFFFFFFFF},
+    {0x000001C8, 0x00000001},
+    {0x00000204, 0x00000000},
+    {0x000001C4, 0x00000001}
+};
+static unsigned nv10TablePGRAPH_8BPP[][2] =
+{
+    {0x000001C9, 0x00111111},
+    {0x00000186, 0x00001010},
+    {0x0000020C, 0x03020202}
+};
+static unsigned nv10TablePGRAPH_15BPP[][2] =
+{
+    {0x000001C9, 0x00226222},
+    {0x00000186, 0x00002071},
+    {0x0000020C, 0x09080808}
+};
+static unsigned nv10TablePGRAPH_16BPP[][2] =
+{
+    {0x000001C9, 0x00556555},
+    {0x00000186, 0x000050C2},
+    {0x0000020C, 0x000B0B0C}
+};
+static unsigned nv10TablePGRAPH_32BPP[][2] =
+{
+    {0x000001C9, 0x0077D777},
+    {0x00000186, 0x000070E5},
+    {0x0000020C, 0x0E0D0D0D}
+};
+static unsigned nv10tri05TablePGRAPH[][2] =
+{
+    {(0x00000E00/4), 0x00000000},
+    {(0x00000E04/4), 0x00000000},
+    {(0x00000E08/4), 0x00000000},
+    {(0x00000E0C/4), 0x00000000},
+    {(0x00000E10/4), 0x00001000},
+    {(0x00000E14/4), 0x00001000},
+    {(0x00000E18/4), 0x4003ff80},
+    {(0x00000E1C/4), 0x00000000},
+    {(0x00000E20/4), 0x00000000},
+    {(0x00000E24/4), 0x00000000},
+    {(0x00000E28/4), 0x00000000},
+    {(0x00000E2C/4), 0x00000000},
+    {(0x00000E30/4), 0x00080008},
+    {(0x00000E34/4), 0x00080008},
+    {(0x00000E38/4), 0x00000000},
+    {(0x00000E3C/4), 0x00000000},
+    {(0x00000E40/4), 0x00000000},
+    {(0x00000E44/4), 0x00000000},
+    {(0x00000E48/4), 0x00000000},
+    {(0x00000E4C/4), 0x00000000},
+    {(0x00000E50/4), 0x00000000},
+    {(0x00000E54/4), 0x00000000},
+    {(0x00000E58/4), 0x00000000},
+    {(0x00000E5C/4), 0x00000000},
+    {(0x00000E60/4), 0x00000000},
+    {(0x00000E64/4), 0x10000000},
+    {(0x00000E68/4), 0x00000000},
+    {(0x00000E6C/4), 0x00000000},
+    {(0x00000E70/4), 0x00000000},
+    {(0x00000E74/4), 0x00000000},
+    {(0x00000E78/4), 0x00000000},
+    {(0x00000E7C/4), 0x00000000},
+    {(0x00000E80/4), 0x00000000},
+    {(0x00000E84/4), 0x00000000},
+    {(0x00000E88/4), 0x08000000},
+    {(0x00000E8C/4), 0x00000000},
+    {(0x00000E90/4), 0x00000000},
+    {(0x00000E94/4), 0x00000000},
+    {(0x00000E98/4), 0x00000000},
+    {(0x00000E9C/4), 0x4B7FFFFF},
+    {(0x00000EA0/4), 0x00000000},
+    {(0x00000EA4/4), 0x00000000},
+    {(0x00000EA8/4), 0x00000000},
+    {(0x00000F00/4), 0x07FF0800},
+    {(0x00000F04/4), 0x07FF0800},
+    {(0x00000F08/4), 0x07FF0800},
+    {(0x00000F0C/4), 0x07FF0800},
+    {(0x00000F10/4), 0x07FF0800},
+    {(0x00000F14/4), 0x07FF0800},
+    {(0x00000F18/4), 0x07FF0800},
+    {(0x00000F1C/4), 0x07FF0800},
+    {(0x00000F20/4), 0x07FF0800},
+    {(0x00000F24/4), 0x07FF0800},
+    {(0x00000F28/4), 0x07FF0800},
+    {(0x00000F2C/4), 0x07FF0800},
+    {(0x00000F30/4), 0x07FF0800},
+    {(0x00000F34/4), 0x07FF0800},
+    {(0x00000F38/4), 0x07FF0800},
+    {(0x00000F3C/4), 0x07FF0800},
+    {(0x00000F40/4), 0x10000000},
+    {(0x00000F44/4), 0x00000000},
+    {(0x00000F50/4), 0x00006740},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F50/4), 0x00006750},
+    {(0x00000F54/4), 0x40000000},
+    {(0x00000F54/4), 0x40000000},
+    {(0x00000F54/4), 0x40000000},
+    {(0x00000F54/4), 0x40000000},
+    {(0x00000F50/4), 0x00006760},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x00006770},
+    {(0x00000F54/4), 0xC5000000},
+    {(0x00000F54/4), 0xC5000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x00006780},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x000067A0},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F50/4), 0x00006AB0},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F50/4), 0x00006AC0},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x00006C10},
+    {(0x00000F54/4), 0xBF800000},
+    {(0x00000F50/4), 0x00007030},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x00007040},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x00007050},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x00007060},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x00007070},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x00007080},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x00007090},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x000070A0},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x00006A80},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F50/4), 0x00006AA0},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x00000040},
+    {(0x00000F54/4), 0x00000005},
+    {(0x00000F50/4), 0x00006400},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x4B7FFFFF},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x00006410},
+    {(0x00000F54/4), 0xC5000000},
+    {(0x00000F54/4), 0xC5000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x00006420},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x00006430},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x000064C0},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x477FFFFF},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F50/4), 0x000064D0},
+    {(0x00000F54/4), 0xC5000000},
+    {(0x00000F54/4), 0xC5000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x000064E0},
+    {(0x00000F54/4), 0xC4FFF000},
+    {(0x00000F54/4), 0xC4FFF000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x000064F0},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F40/4), 0x30000000},
+    {(0x00000F44/4), 0x00000004},
+    {(0x00000F48/4), 0x10000000},
+    {(0x00000F4C/4), 0x00000000}
+};
+static unsigned nv10TablePRAMIN[][2] =
+{
+    {0x00000000, 0x80000010},
+    {0x00000001, 0x80011145},
+    {0x00000002, 0x80000011},
+    {0x00000003, 0x80011146},
+    {0x00000004, 0x80000012},
+    {0x00000005, 0x80011147},
+    {0x00000006, 0x80000013},
+    {0x00000007, 0x80011148},
+    {0x00000008, 0x80000014},
+    {0x00000009, 0x80011149},
+    {0x0000000A, 0x80000015},
+    {0x0000000B, 0x8001114A},
+    {0x00000020, 0x80000000},
+    {0x00000021, 0x80011142},
+    {0x00000022, 0x80000001},
+    {0x00000023, 0x80011143},
+    {0x00000024, 0x80000002},
+    {0x00000025, 0x80011144},
+    {0x00000026, 0x80000003},
+    {0x00000027, 0x8001114B},
+    {0x00000028, 0x80000004},
+    {0x00000029, 0x8001114C},
+    {0x0000002A, 0x80000005},
+    {0x0000002B, 0x8001114D},
+    {0x0000002C, 0x80000006},
+    {0x0000002D, 0x8001114E},
+    {0x0000002E, 0x80000007},
+    {0x0000002F, 0x8001114F},
+    {0x00000500, 0x00003000},
+    {0x00000501, 0x01FFFFFF},
+    {0x00000502, 0x00000002},
+    {0x00000503, 0x00000002},
+    {0x00000508, 0x01008043},
+    {0x0000050A, 0x00000000},
+    {0x0000050B, 0x00000000},
+    {0x0000050C, 0x01008019},
+    {0x0000050E, 0x00000000},
+    {0x0000050F, 0x00000000},
+#if 1
+    {0x00000510, 0x01008018},
+#else
+    {0x00000510, 0x01008044},
+#endif
+    {0x00000512, 0x00000000},
+    {0x00000513, 0x00000000},
+    {0x00000514, 0x01008021},
+    {0x00000516, 0x00000000},
+    {0x00000517, 0x00000000},
+    {0x00000518, 0x0100805F},
+    {0x0000051A, 0x00000000},
+    {0x0000051B, 0x00000000},
+#if 1
+    {0x0000051C, 0x0100804B},
+#else
+    {0x0000051C, 0x0100804A},
+#endif
+    {0x0000051E, 0x00000000},
+    {0x0000051F, 0x00000000},
+    {0x00000520, 0x0100A048},
+    {0x00000521, 0x00000D01},
+    {0x00000522, 0x11401140},
+    {0x00000523, 0x00000000},
+    {0x00000524, 0x0300A094},
+    {0x00000525, 0x00000D01},
+    {0x00000526, 0x11401140},
+    {0x00000527, 0x00000000},
+    {0x00000528, 0x0300A095},
+    {0x00000529, 0x00000D01},
+    {0x0000052A, 0x11401140},
+    {0x0000052B, 0x00000000},
+    {0x0000052C, 0x00000058},
+    {0x0000052E, 0x11401140},
+    {0x0000052F, 0x00000000},
+    {0x00000530, 0x00000059},
+    {0x00000532, 0x11401140},
+    {0x00000533, 0x00000000},
+    {0x00000534, 0x0000005A},
+    {0x00000536, 0x11401140},
+    {0x00000537, 0x00000000},
+    {0x00000538, 0x0000005B},
+    {0x0000053A, 0x11401140},
+    {0x0000053B, 0x00000000},
+    {0x0000053C, 0x00000093},
+    {0x0000053E, 0x11401140},
+    {0x0000053F, 0x00000000} 
+};
+static unsigned nv10TablePRAMIN_8BPP[][2] =
+{
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000302},
+    {0x0000050D, 0x00000302},
+    {0x00000511, 0x00000202},
+    {0x00000515, 0x00000302},
+    {0x00000519, 0x00000302},
+    {0x0000051D, 0x00000302},
+    {0x0000052D, 0x00000302},
+    {0x0000052E, 0x00000302},
+    {0x00000535, 0x00000000},
+    {0x00000539, 0x00000000},
+    {0x0000053D, 0x00000000} 
+};
+static unsigned nv10TablePRAMIN_15BPP[][2] =
+{
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000902},
+    {0x0000050D, 0x00000902},
+    {0x00000511, 0x00000802},
+    {0x00000515, 0x00000902},
+    {0x00000519, 0x00000902},
+    {0x0000051D, 0x00000902},
+    {0x0000052D, 0x00000902},
+    {0x0000052E, 0x00000902},
+    {0x00000535, 0x00000902},
+    {0x00000539, 0x00000902}, 
+    {0x0000053D, 0x00000902} 
+};
+static unsigned nv10TablePRAMIN_16BPP[][2] =
+{
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000C02},
+    {0x0000050D, 0x00000C02},
+    {0x00000511, 0x00000B02},
+    {0x00000515, 0x00000C02},
+    {0x00000519, 0x00000C02},
+    {0x0000051D, 0x00000C02},
+    {0x0000052D, 0x00000C02},
+    {0x0000052E, 0x00000C02},
+    {0x00000535, 0x00000C02},
+    {0x00000539, 0x00000C02},
+    {0x0000053D, 0x00000C02} 
+};
+static unsigned nv10TablePRAMIN_32BPP[][2] =
+{
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000E02},
+    {0x0000050D, 0x00000E02},
+    {0x00000511, 0x00000D02},
+    {0x00000515, 0x00000E02},
+    {0x00000519, 0x00000E02},
+    {0x0000051D, 0x00000E02},
+    {0x0000052D, 0x00000E02},
+    {0x0000052E, 0x00000E02},
+    {0x00000535, 0x00000E02},
+    {0x00000539, 0x00000E02},
+    {0x0000053D, 0x00000E02} 
 };
 
diff -u --recursive --new-file v2.4.1/linux/drivers/video/riva/rivafb.h linux/drivers/video/riva/rivafb.h
--- v2.4.1/linux/drivers/video/riva/rivafb.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/riva/rivafb.h	Sat Feb  3 12:48:00 2001
@@ -0,0 +1,85 @@
+#ifndef __RIVAFB_H
+#define __RIVAFB_H
+
+#include <linux/config.h>
+#include <linux/fb.h>
+#include <video/fbcon.h>
+#include <video/fbcon-cfb4.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb32.h>
+#include "riva_hw.h"
+
+/* GGI compatibility macros */
+#define NUM_SEQ_REGS		0x05
+#define NUM_CRT_REGS		0x41
+#define NUM_GRC_REGS		0x09
+#define NUM_ATC_REGS		0x15
+
+/* holds the state of the VGA core and extended Riva hw state from riva_hw.c.
+ * From KGI originally. */
+struct riva_regs {
+	u8 attr[NUM_ATC_REGS];
+	u8 crtc[NUM_CRT_REGS];
+	u8 gra[NUM_GRC_REGS];
+	u8 seq[NUM_SEQ_REGS];
+	u8 misc_output;
+	RIVA_HW_STATE ext;
+};
+
+typedef struct {
+	unsigned char red, green, blue, transp;
+} riva_cfb8_cmap_t;
+
+struct rivafb_info;
+struct rivafb_info {
+	struct fb_info info;	/* kernel framebuffer info */
+
+	RIVA_HW_INST riva;	/* interface to riva_hw.c */
+
+	const char *drvr_name;	/* Riva hardware board type */
+
+	unsigned long ctrl_base_phys;	/* physical control register base addr */
+	unsigned long fb_base_phys;	/* physical framebuffer base addr */
+
+	caddr_t ctrl_base;	/* virtual control register base addr */
+	caddr_t fb_base;	/* virtual framebuffer base addr */
+
+	unsigned ram_amount;	/* amount of RAM on card, in bytes */
+	unsigned dclk_max;	/* max DCLK */
+
+	struct riva_regs initial_state;	/* initial startup video mode */
+	struct riva_regs current_state;
+
+	struct display disp;
+	int currcon;
+	struct display *currcon_display;
+
+	struct rivafb_info *next;
+
+	struct pci_dev *pd;	/* pointer to board's pci info */
+	unsigned base0_region_size;	/* size of control register region */
+	unsigned base1_region_size;	/* size of framebuffer region */
+
+	struct riva_cursor *cursor;
+
+	struct display_switch dispsw;
+
+	riva_cfb8_cmap_t palette[256];	/* VGA DAC palette cache */
+
+#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
+	union {
+#ifdef FBCON_HAS_CFB16
+		u_int16_t cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+		u_int32_t cfb32[16];
+#endif
+	} con_cmap;
+#endif				/* FBCON_HAS_CFB16 | FBCON_HAS_CFB32 */
+#ifdef CONFIG_MTRR
+	struct { int vram; int vram_valid; } mtrr;
+#endif
+};
+
+#endif /* __RIVAFB_H */
\ No newline at end of file
diff -u --recursive --new-file v2.4.1/linux/fs/inode.c linux/fs/inode.c
--- v2.4.1/linux/fs/inode.c	Sat Feb  3 19:51:30 2001
+++ linux/fs/inode.c	Sat Feb  3 10:24:29 2001
@@ -728,7 +728,7 @@
 
 static inline unsigned long hash(struct super_block *sb, unsigned long i_ino)
 {
-	unsigned long tmp = i_ino | ((unsigned long) sb / L1_CACHE_BYTES);
+	unsigned long tmp = i_ino + ((unsigned long) sb / L1_CACHE_BYTES);
 	tmp = tmp + (tmp >> I_HASHBITS) + (tmp >> I_HASHBITS*2);
 	return tmp & I_HASHMASK;
 }
diff -u --recursive --new-file v2.4.1/linux/include/asm-alpha/socket.h linux/include/asm-alpha/socket.h
--- v2.4.1/linux/include/asm-alpha/socket.h	Sun Jul  9 22:30:40 2000
+++ linux/include/asm-alpha/socket.h	Sat Feb  3 11:26:44 2001
@@ -29,6 +29,7 @@
 #define	SO_SNDLOWAT	0x1011
 #define	SO_RCVTIMEO	0x1012
 #define	SO_SNDTIMEO	0x1013
+#define SO_ACCEPTCONN	0x1014
 
 /* linux-specific, might as well be the same as on i386 */
 #define SO_NO_CHECK	11
diff -u --recursive --new-file v2.4.1/linux/include/asm-alpha/termios.h linux/include/asm-alpha/termios.h
--- v2.4.1/linux/include/asm-alpha/termios.h	Fri Sep 22 14:21:17 2000
+++ linux/include/asm-alpha/termios.h	Sat Feb  3 20:00:45 2001
@@ -78,7 +78,7 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
 #define N_SYNC_PPP	14
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/socket.h linux/include/asm-arm/socket.h
--- v2.4.1/linux/include/asm-arm/socket.h	Sun Jul  9 22:30:40 2000
+++ linux/include/asm-arm/socket.h	Sat Feb  3 11:26:44 2001
@@ -43,6 +43,8 @@
 #define SO_TIMESTAMP		29
 #define SCM_TIMESTAMP		SO_TIMESTAMP
 
+#define SO_ACCEPTCONN		30
+
 /* Nast libc5 fixup - bletch */
 #if defined(__KERNEL__)
 /* Socket types. */
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/termios.h linux/include/asm-arm/termios.h
--- v2.4.1/linux/include/asm-arm/termios.h	Sun Aug 13 09:54:15 2000
+++ linux/include/asm-arm/termios.h	Sat Feb  3 20:00:45 2001
@@ -61,7 +61,7 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
 #define N_SYNC_PPP	14
diff -u --recursive --new-file v2.4.1/linux/include/asm-i386/socket.h linux/include/asm-i386/socket.h
--- v2.4.1/linux/include/asm-i386/socket.h	Sun Jul  9 22:30:40 2000
+++ linux/include/asm-i386/socket.h	Sat Feb  3 11:26:44 2001
@@ -43,6 +43,8 @@
 #define SO_TIMESTAMP		29
 #define SCM_TIMESTAMP		SO_TIMESTAMP
 
+#define SO_ACCEPTCONN		30
+
 /* Nasty libc5 fixup - bletch */
 #if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
 /* Socket types. */
diff -u --recursive --new-file v2.4.1/linux/include/asm-i386/termios.h linux/include/asm-i386/termios.h
--- v2.4.1/linux/include/asm-i386/termios.h	Thu Jan 27 16:40:09 2000
+++ linux/include/asm-i386/termios.h	Sat Feb  3 20:00:45 2001
@@ -51,7 +51,7 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IR - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IR - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
 #define N_SYNC_PPP	14	/* synchronous PPP */
diff -u --recursive --new-file v2.4.1/linux/include/asm-ia64/socket.h linux/include/asm-ia64/socket.h
--- v2.4.1/linux/include/asm-ia64/socket.h	Sun Jul  9 22:30:40 2000
+++ linux/include/asm-ia64/socket.h	Sat Feb  3 11:26:44 2001
@@ -50,6 +50,8 @@
 #define SO_TIMESTAMP		29
 #define SCM_TIMESTAMP		SO_TIMESTAMP
 
+#define SO_ACCEPTCONN		30
+
 /* Nast libc5 fixup - bletch */
 #if defined(__KERNEL__)
 /* Socket types. */
diff -u --recursive --new-file v2.4.1/linux/include/asm-ia64/termios.h linux/include/asm-ia64/termios.h
--- v2.4.1/linux/include/asm-ia64/termios.h	Sun Feb  6 18:42:40 2000
+++ linux/include/asm-ia64/termios.h	Sat Feb  3 20:00:45 2001
@@ -58,7 +58,7 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IR - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IR - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS msgs */
 #define N_HDLC		13	/* synchronous HDLC */
 #define N_SYNC_PPP	14	/* synchronous PPP */
diff -u --recursive --new-file v2.4.1/linux/include/asm-m68k/bitops.h linux/include/asm-m68k/bitops.h
--- v2.4.1/linux/include/asm-m68k/bitops.h	Mon Nov 27 18:00:49 2000
+++ linux/include/asm-m68k/bitops.h	Sat Feb  3 11:26:44 2001
@@ -228,7 +228,7 @@
 {
 	int cnt;
 
-	asm ("bfffo %1{#0:#0}" : "=d" (cnt) : "dm" (x & -x));
+	asm ("bfffo %1{#0:#0},%0" : "=d" (cnt) : "dm" (x & -x));
 
 	return 32 - cnt;
 }
diff -u --recursive --new-file v2.4.1/linux/include/asm-m68k/errno.h linux/include/asm-m68k/errno.h
--- v2.4.1/linux/include/asm-m68k/errno.h	Mon Apr 14 16:28:19 1997
+++ linux/include/asm-m68k/errno.h	Sat Feb  3 11:26:44 2001
@@ -129,4 +129,6 @@
 #define	ENOMEDIUM	123	/* No medium found */
 #define	EMEDIUMTYPE	124	/* Wrong medium type */
 
+#define	EHASHCOLLISION	125	/* Number of hash collisons exceeds maximum generation counter value.  */
+
 #endif /* _M68K_ERRNO_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-m68k/socket.h linux/include/asm-m68k/socket.h
--- v2.4.1/linux/include/asm-m68k/socket.h	Sun Jul  9 22:30:40 2000
+++ linux/include/asm-m68k/socket.h	Sat Feb  3 11:26:44 2001
@@ -43,6 +43,8 @@
 #define SO_TIMESTAMP		29
 #define SCM_TIMESTAMP		SO_TIMESTAMP
 
+#define SO_ACCEPTCONN		30
+
 /* Nast libc5 fixup - bletch */
 #if defined(__KERNEL__)
 /* Socket types. */
diff -u --recursive --new-file v2.4.1/linux/include/asm-m68k/termios.h linux/include/asm-m68k/termios.h
--- v2.4.1/linux/include/asm-m68k/termios.h	Thu Jan 27 16:40:09 2000
+++ linux/include/asm-m68k/termios.h	Sat Feb  3 20:00:45 2001
@@ -61,7 +61,7 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
 #define N_SYNC_PPP	14
diff -u --recursive --new-file v2.4.1/linux/include/asm-mips/socket.h linux/include/asm-mips/socket.h
--- v2.4.1/linux/include/asm-mips/socket.h	Sun Jul  9 22:32:15 2000
+++ linux/include/asm-mips/socket.h	Sat Feb  3 11:26:44 2001
@@ -33,6 +33,7 @@
 #define SO_RCVLOWAT	0x1004	/* receive low-water mark */
 #define SO_SNDTIMEO	0x1005	/* send timeout */
 #define SO_RCVTIMEO 	0x1006	/* receive timeout */
+#define SO_ACCEPTCONN	0x1007
 
 /* linux-specific, might as well be the same as on i386 */
 #define SO_NO_CHECK	11
diff -u --recursive --new-file v2.4.1/linux/include/asm-mips/termios.h linux/include/asm-mips/termios.h
--- v2.4.1/linux/include/asm-mips/termios.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/termios.h	Sat Feb  3 20:00:45 2001
@@ -97,7 +97,7 @@
 #define N_MASC		8	/* Reserved fo Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
 #define N_SYNC_PPP	14	/* synchronous PPP */
diff -u --recursive --new-file v2.4.1/linux/include/asm-mips64/socket.h linux/include/asm-mips64/socket.h
--- v2.4.1/linux/include/asm-mips64/socket.h	Tue Jul 11 11:17:45 2000
+++ linux/include/asm-mips64/socket.h	Sat Feb  3 11:26:44 2001
@@ -41,6 +41,7 @@
 #define SO_RCVLOWAT	0x1004	/* receive low-water mark */
 #define SO_SNDTIMEO	0x1005	/* send timeout */
 #define SO_RCVTIMEO 	0x1006	/* receive timeout */
+#define SO_ACCEPTCONN	0x1007
 
 /* linux-specific, might as well be the same as on i386 */
 #define SO_NO_CHECK	11
diff -u --recursive --new-file v2.4.1/linux/include/asm-mips64/termios.h linux/include/asm-mips64/termios.h
--- v2.4.1/linux/include/asm-mips64/termios.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips64/termios.h	Sat Feb  3 20:00:45 2001
@@ -97,7 +97,7 @@
 #define N_MASC		8	/* Reserved fo Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
 #define N_SYNC_PPP	14	/* synchronous PPP */
diff -u --recursive --new-file v2.4.1/linux/include/asm-parisc/socket.h linux/include/asm-parisc/socket.h
--- v2.4.1/linux/include/asm-parisc/socket.h	Tue Dec  5 12:29:39 2000
+++ linux/include/asm-parisc/socket.h	Sat Feb  3 11:26:44 2001
@@ -43,6 +43,8 @@
 #define SO_ATTACH_FILTER        0x401a
 #define SO_DETACH_FILTER        0x401b
 
+#define SO_ACCEPTCONN		0x401c
+
 #if defined(__KERNEL__)
 #define SOCK_STREAM	1	/* stream (connection) socket	*/
 #define SOCK_DGRAM	2	/* datagram (conn.less) socket	*/
diff -u --recursive --new-file v2.4.1/linux/include/asm-parisc/termios.h linux/include/asm-parisc/termios.h
--- v2.4.1/linux/include/asm-parisc/termios.h	Tue Dec  5 12:29:39 2000
+++ linux/include/asm-parisc/termios.h	Sat Feb  3 20:00:45 2001
@@ -51,7 +51,7 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IR - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IR - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 
 #ifdef __KERNEL__
diff -u --recursive --new-file v2.4.1/linux/include/asm-ppc/socket.h linux/include/asm-ppc/socket.h
--- v2.4.1/linux/include/asm-ppc/socket.h	Sun Jul  9 22:30:40 2000
+++ linux/include/asm-ppc/socket.h	Sat Feb  3 11:26:44 2001
@@ -49,6 +49,8 @@
 #define SO_TIMESTAMP		29
 #define SCM_TIMESTAMP		SO_TIMESTAMP
 
+#define SO_ACCEPTCONN		30
+
 /* Nast libc5 fixup - bletch */
 #if defined(__KERNEL__)
 /* Socket types. */
diff -u --recursive --new-file v2.4.1/linux/include/asm-ppc/termios.h linux/include/asm-ppc/termios.h
--- v2.4.1/linux/include/asm-ppc/termios.h	Sat Feb  3 19:51:31 2001
+++ linux/include/asm-ppc/termios.h	Sat Feb  3 20:00:45 2001
@@ -186,7 +186,7 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
 #define N_SYNC_PPP	14
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/socket.h linux/include/asm-s390/socket.h
--- v2.4.1/linux/include/asm-s390/socket.h	Sun Jul  9 22:30:40 2000
+++ linux/include/asm-s390/socket.h	Sat Feb  3 11:26:44 2001
@@ -51,6 +51,8 @@
 #define SO_TIMESTAMP		29
 #define SCM_TIMESTAMP		SO_TIMESTAMP
 
+#define SO_ACCEPTCONN		30
+
 /* Nast libc5 fixup - bletch */
 #if defined(__KERNEL__)
 /* Socket types. */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/termios.h linux/include/asm-s390/termios.h
--- v2.4.1/linux/include/asm-s390/termios.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/termios.h	Sat Feb  3 20:00:45 2001
@@ -60,7 +60,7 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IR - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IR - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC         13	/* synchronous HDLC */
 
diff -u --recursive --new-file v2.4.1/linux/include/asm-sh/socket.h linux/include/asm-sh/socket.h
--- v2.4.1/linux/include/asm-sh/socket.h	Sun Jul  9 22:30:40 2000
+++ linux/include/asm-sh/socket.h	Sat Feb  3 11:26:44 2001
@@ -43,6 +43,8 @@
 #define SO_TIMESTAMP		29
 #define SCM_TIMESTAMP		SO_TIMESTAMP
 
+#define SO_ACCEPTCONN		30
+
 /* Nast libc5 fixup - bletch */
 #if defined(__KERNEL__)
 /* Socket types. */
diff -u --recursive --new-file v2.4.1/linux/include/asm-sh/termios.h linux/include/asm-sh/termios.h
--- v2.4.1/linux/include/asm-sh/termios.h	Sun Mar  5 09:33:55 2000
+++ linux/include/asm-sh/termios.h	Sat Feb  3 20:00:45 2001
@@ -51,7 +51,7 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IR - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IR - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
 #define N_SYNC_PPP	14
diff -u --recursive --new-file v2.4.1/linux/include/asm-sparc/socket.h linux/include/asm-sparc/socket.h
--- v2.4.1/linux/include/asm-sparc/socket.h	Sun Jul  9 22:30:40 2000
+++ linux/include/asm-sparc/socket.h	Sat Feb  3 11:26:44 2001
@@ -1,4 +1,4 @@
-/* $Id: socket.h,v 1.15 2000/07/08 00:20:43 davem Exp $ */
+/* $Id: socket.h,v 1.16 2001/01/30 07:48:30 davem Exp $ */
 #ifndef _ASM_SOCKET_H
 #define _ASM_SOCKET_H
 
@@ -22,6 +22,7 @@
 #define SO_SNDLOWAT     0x1000
 #define SO_RCVTIMEO     0x2000
 #define SO_SNDTIMEO     0x4000
+#define SO_ACCEPTCONN	0x8000
 
 /* wha!??? */
 #define SO_DONTLINGER   (~SO_LINGER)  /* Older SunOS compat. hack */
diff -u --recursive --new-file v2.4.1/linux/include/asm-sparc/termios.h linux/include/asm-sparc/termios.h
--- v2.4.1/linux/include/asm-sparc/termios.h	Mon Dec 20 22:05:52 1999
+++ linux/include/asm-sparc/termios.h	Sat Feb  3 20:00:45 2001
@@ -66,7 +66,7 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
 #define N_SYNC_PPP	14	/* synchronous PPP */
diff -u --recursive --new-file v2.4.1/linux/include/asm-sparc64/socket.h linux/include/asm-sparc64/socket.h
--- v2.4.1/linux/include/asm-sparc64/socket.h	Sun Jul  9 22:30:40 2000
+++ linux/include/asm-sparc64/socket.h	Sat Feb  3 11:26:44 2001
@@ -1,4 +1,4 @@
-/* $Id: socket.h,v 1.8 2000/07/08 00:20:43 davem Exp $ */
+/* $Id: socket.h,v 1.9 2001/01/30 07:48:30 davem Exp $ */
 #ifndef _ASM_SOCKET_H
 #define _ASM_SOCKET_H
 
@@ -22,6 +22,7 @@
 #define SO_SNDLOWAT     0x1000
 #define SO_RCVTIMEO     0x2000
 #define SO_SNDTIMEO     0x4000
+#define SO_ACCEPTCONN	0x8000
 
 /* wha!??? */
 #define SO_DONTLINGER   (~SO_LINGER)  /* Older SunOS compat. hack */
diff -u --recursive --new-file v2.4.1/linux/include/asm-sparc64/termios.h linux/include/asm-sparc64/termios.h
--- v2.4.1/linux/include/asm-sparc64/termios.h	Mon Dec 20 22:05:52 1999
+++ linux/include/asm-sparc64/termios.h	Sat Feb  3 20:00:45 2001
@@ -66,7 +66,7 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
 #define N_SYNC_PPP	14	/* synchronous PPP */
diff -u --recursive --new-file v2.4.1/linux/include/linux/module.h linux/include/linux/module.h
--- v2.4.1/linux/include/linux/module.h	Thu Jan  4 14:50:46 2001
+++ linux/include/linux/module.h	Sat Feb  3 18:30:08 2001
@@ -249,12 +249,6 @@
   __attribute__ ((unused)) = name
 #define MODULE_DEVICE_TABLE(type,name)		\
   MODULE_GENERIC_TABLE(type##_device,name)
-/* not put to .modinfo section to avoid section type conflicts */
-
-/* The attributes of a section are set the first time the section is
-   seen; we want .modinfo to not be allocated.  */
-
-__asm__(".section .modinfo\n\t.previous");
 
 /* Define the module variable, and usage macros.  */
 extern struct module __this_module;
diff -u --recursive --new-file v2.4.1/linux/include/linux/pci_ids.h linux/include/linux/pci_ids.h
--- v2.4.1/linux/include/linux/pci_ids.h	Tue Jan  2 16:58:45 2001
+++ linux/include/linux/pci_ids.h	Sat Feb  3 12:48:00 2001
@@ -141,6 +141,7 @@
 #define PCI_DEVICE_ID_COMPAQ_NETEL100PI	0xae43
 #define PCI_DEVICE_ID_COMPAQ_NETEL100I	0xb011
 #define PCI_DEVICE_ID_COMPAQ_CISS	0xb060
+#define PCI_DEVICE_ID_COMPAQ_CISSB	0xb178
 #define PCI_DEVICE_ID_COMPAQ_THUNDER	0xf130
 #define PCI_DEVICE_ID_COMPAQ_NETFLEX3B	0xf150
 
@@ -688,13 +689,23 @@
 #define PCI_DEVICE_ID_CERN_HIPPI_DST	0x0021
 #define PCI_DEVICE_ID_CERN_HIPPI_SRC	0x0022
 
-#define PCI_VENDOR_ID_NVIDIA		0x10de
-#define PCI_DEVICE_ID_NVIDIA_TNT	0x0020
-#define PCI_DEVICE_ID_NVIDIA_TNT2	0x0028
-#define PCI_DEVICE_ID_NVIDIA_UTNT2	0x0029
-#define PCI_DEVICE_ID_NVIDIA_VTNT2	0x002C
-#define PCI_DEVICE_ID_NVIDIA_UVTNT2	0x002D
-#define PCI_DEVICE_ID_NVIDIA_ITNT2	0x00A0
+#define PCI_VENDOR_ID_NVIDIA			0x10de
+#define PCI_DEVICE_ID_NVIDIA_TNT		0x0020
+#define PCI_DEVICE_ID_NVIDIA_TNT2		0x0028
+#define PCI_DEVICE_ID_NVIDIA_UTNT2		0x0029
+#define PCI_DEVICE_ID_NVIDIA_VTNT2		0x002C
+#define PCI_DEVICE_ID_NVIDIA_UVTNT2		0x002D
+#define PCI_DEVICE_ID_NVIDIA_ITNT2		0x00A0
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR	0x0100
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR	0x0101
+#define PCI_DEVICE_ID_NVIDIA_QUADRO		0x0103
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX	0x0110
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2	0x0111
+#define PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR	0x0113
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS	0x0150
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2	0x0151
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA	0x0152
+#define PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO	0x0153
 
 #define PCI_VENDOR_ID_IMS		0x10e0
 #define PCI_DEVICE_ID_IMS_8849		0x8849
diff -u --recursive --new-file v2.4.1/linux/include/linux/serial.h linux/include/linux/serial.h
--- v2.4.1/linux/include/linux/serial.h	Thu Jan  4 14:50:47 2001
+++ linux/include/linux/serial.h	Sat Feb  3 18:30:08 2001
@@ -139,8 +139,9 @@
 #define ASYNC_CHECK_CD		0x02000000 /* i.e., CLOCAL */
 #define ASYNC_SHARE_IRQ		0x01000000 /* for multifunction cards
 					     --- no longer used */
+#define ASYNC_NO_FLOW		0x00800000 /* No flow control serial console */
 
-#define ASYNC_INTERNAL_FLAGS	0xFF000000 /* Internal flags */
+#define ASYNC_INTERNAL_FLAGS	0xFF800000 /* Internal flags */
 
 /*
  * Multiport serial configuration structure --- external structure
@@ -177,5 +178,7 @@
 extern int register_serial(struct serial_struct *req);
 extern void unregister_serial(int line);
 
+/* Allow complicated architectures to specify rs_table[] at run time */
+extern int early_serial_setup(struct serial_struct *req);
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SERIAL_H */
diff -u --recursive --new-file v2.4.1/linux/mm/memory.c linux/mm/memory.c
--- v2.4.1/linux/mm/memory.c	Sat Feb  3 19:51:32 2001
+++ linux/mm/memory.c	Sat Feb  3 19:02:26 2001
@@ -1200,6 +1200,7 @@
 	pgd_t *pgd;
 	pmd_t *pmd;
 
+	current->state = TASK_RUNNING;
 	pgd = pgd_offset(mm, address);
 	pmd = pmd_alloc(pgd, address);
 
diff -u --recursive --new-file v2.4.1/linux/net/core/datagram.c linux/net/core/datagram.c
--- v2.4.1/linux/net/core/datagram.c	Sat Nov 11 19:02:40 2000
+++ linux/net/core/datagram.c	Sat Feb  3 10:39:12 2001
@@ -72,19 +72,19 @@
 	/* Socket errors? */
 	error = sock_error(sk);
 	if (error)
-		goto out;
+		goto out_err;
 
 	if (!skb_queue_empty(&sk->receive_queue))
 		goto ready;
 
 	/* Socket shut down? */
 	if (sk->shutdown & RCV_SHUTDOWN)
-		goto out;
+		goto out_noerr;
 
 	/* Sequenced packets can come disconnected. If so we report the problem */
 	error = -ENOTCONN;
 	if(connection_based(sk) && !(sk->state==TCP_ESTABLISHED || sk->state==TCP_LISTEN))
-		goto out;
+		goto out_err;
 
 	/* handle signals */
 	if (signal_pending(current))
@@ -99,11 +99,16 @@
 
 interrupted:
 	error = sock_intr_errno(*timeo_p);
+out_err:
+	*err = error;
 out:
 	current->state = TASK_RUNNING;
 	remove_wait_queue(sk->sleep, &wait);
-	*err = error;
 	return error;
+out_noerr:
+	*err = 0;
+	error = 1;
+	goto out;
 }
 
 /*
diff -u --recursive --new-file v2.4.1/linux/net/core/sock.c linux/net/core/sock.c
--- v2.4.1/linux/net/core/sock.c	Fri Dec 29 14:07:24 2000
+++ linux/net/core/sock.c	Sat Feb  3 11:26:44 2001
@@ -7,7 +7,7 @@
  *		handler for protocols to use and generic option handler.
  *
  *
- * Version:	$Id: sock.c,v 1.102 2000/12/11 23:00:24 davem Exp $
+ * Version:	$Id: sock.c,v 1.104 2001/01/30 07:48:30 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -549,6 +549,13 @@
 				return -EFAULT;
 			goto lenout;
 		}
+
+		/* Dubious BSD thing... Probably nobody even uses it, but
+		 * the UNIX standard wants it for whatever reason... -DaveM
+		 */
+		case SO_ACCEPTCONN:
+			v.val = (sk->state == TCP_LISTEN);
+			break;
 
 		default:
 			return(-ENOPROTOOPT);
diff -u --recursive --new-file v2.4.1/linux/net/ipv4/netfilter/ip_nat_standalone.c linux/net/ipv4/netfilter/ip_nat_standalone.c
--- v2.4.1/linux/net/ipv4/netfilter/ip_nat_standalone.c	Mon Oct 30 14:27:49 2000
+++ linux/net/ipv4/netfilter/ip_nat_standalone.c	Sat Feb  3 11:45:55 2001
@@ -330,11 +330,9 @@
 module_init(init);
 module_exit(fini);
 
-#ifdef MODULE
 EXPORT_SYMBOL(ip_nat_setup_info);
 EXPORT_SYMBOL(ip_nat_helper_register);
 EXPORT_SYMBOL(ip_nat_helper_unregister);
 EXPORT_SYMBOL(ip_nat_expect_register);
 EXPORT_SYMBOL(ip_nat_expect_unregister);
 EXPORT_SYMBOL(ip_nat_cheat_check);
-#endif
