[prev in list] [next in list] [prev in thread] [next in thread] 

List:       git-commits-24
Subject:    [PATCH] rivafb 0.9.4 update
From:       Linux Kernel Mailing List <linux-kernel () vger ! kernel ! org>
Date:       2003-02-26 20:59:14
[Download RAW message or body]

ChangeSet 1.1003, 2003/02/26 17:59:14-03:00, ajoshi@kernel.crashing.org

	[PATCH] rivafb 0.9.4 update
	
	Hi Marcelo,
	
	The attached patch updates rivafb to v0.9.4 which includes PowerPC
	support.  Also some hunks to update my email address.


# This patch includes the following deltas:
#	           ChangeSet	1.1002  -> 1.1003 
#	drivers/ieee1394/dv1394-private.h	1.5     -> 1.6    
#	drivers/ieee1394/ohci1394.h	1.11    -> 1.12   
#	             CREDITS	1.67    -> 1.68   
#	drivers/ieee1394/eth1394.h	1.3     -> 1.4    
#	drivers/video/riva/fbdev.c	1.13    -> 1.14   
#	drivers/ieee1394/ieee1394_core.h	1.11    -> 1.12   
#	drivers/ieee1394/hosts.h	1.8     -> 1.9    
#	drivers/ieee1394/dv1394.c	1.6     -> 1.7    
#	drivers/ieee1394/ieee1394_core.c	1.18    -> 1.19   
#	drivers/video/riva/riva_hw.c	1.5     -> 1.6    
#	drivers/video/riva/rivafb.h	1.2     -> 1.3    
#	drivers/video/riva/riva_hw.h	1.5     -> 1.6    
#	drivers/video/riva/riva_tbl.h	1.4     -> 1.5    
#	drivers/ieee1394/hosts.c	1.12    -> 1.13   
#	drivers/video/riva/accel.c	1.4     -> 1.5    
#	drivers/ieee1394/amdtp.h	1.3     -> 1.4    
#	         MAINTAINERS	1.94    -> 1.95   
#	drivers/ieee1394/dv1394.h	1.3     -> 1.4    
#	drivers/ieee1394/amdtp.c	1.8     -> 1.9    
#	drivers/ieee1394/ieee1394_types.h	1.9     -> 1.10   
#	drivers/ieee1394/eth1394.c	1.5     -> 1.6    
#	drivers/ieee1394/ohci1394.c	1.19    -> 1.20   
#	drivers/ieee1394/Makefile	1.9     -> 1.10   
#	               (new)	        -> 1.1     drivers/ieee1394/dma.h
#	               (new)	        -> 1.1     drivers/ieee1394/ieee1394-ioctl.h
#	               (new)	        -> 1.1     drivers/ieee1394/dma.c
#

 CREDITS                           |    2 
 MAINTAINERS                       |    2 
 drivers/ieee1394/Makefile         |    2 
 drivers/ieee1394/amdtp.c          |    2 
 drivers/ieee1394/amdtp.h          |    9 
 drivers/ieee1394/dma.c            |  236 +++++++++++
 drivers/ieee1394/dma.h            |   84 ++++
 drivers/ieee1394/dv1394-private.h |   50 --
 drivers/ieee1394/dv1394.c         |  753 ++++++++++++++++----------------------
 drivers/ieee1394/dv1394.h         |    1 
 drivers/ieee1394/eth1394.c        |    7 
 drivers/ieee1394/eth1394.h        |    2 
 drivers/ieee1394/hosts.c          |    2 
 drivers/ieee1394/hosts.h          |    3 
 drivers/ieee1394/ieee1394-ioctl.h |   71 +++
 drivers/ieee1394/ieee1394_core.c  |   33 +
 drivers/ieee1394/ieee1394_core.h  |    4 
 drivers/ieee1394/ieee1394_types.h |   30 -
 drivers/ieee1394/ohci1394.c       |   80 +++-
 drivers/ieee1394/ohci1394.h       |   13 
 drivers/video/riva/accel.c        |   21 +
 drivers/video/riva/fbdev.c        |  227 ++++++++++-
 drivers/video/riva/riva_hw.c      |   36 +
 drivers/video/riva/riva_hw.h      |   58 ++
 drivers/video/riva/riva_tbl.h     |   57 ++
 drivers/video/riva/rivafb.h       |   12 
 26 files changed, 1220 insertions(+), 577 deletions(-)


diff -Nru a/CREDITS b/CREDITS
--- a/CREDITS	Wed Feb 26 13:32:43 2003
+++ b/CREDITS	Wed Feb 26 13:32:43 2003
@@ -1495,7 +1495,7 @@
 S: United Kingdom
 
 N: Ani Joshi
-E: ajoshi@shell.unixbox.com
+E: ajoshi@kernel.crashing.org
 D: fbdev hacking
 
 N: Bernhard Kaindl
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	Wed Feb 26 13:32:43 2003
+++ b/MAINTAINERS	Wed Feb 26 13:32:43 2003
@@ -1202,7 +1202,7 @@
 
 NVIDIA (RIVA) FRAMEBUFFER DRIVER
 P:	Ani Joshi
-M:	ajoshi@shell.unixbox.com
+M:	ajoshi@kernel.crashing.org
 L:	linux-nvidia@lists.surfsouth.com
 S:	Maintained
 
diff -Nru a/drivers/ieee1394/Makefile b/drivers/ieee1394/Makefile
--- a/drivers/ieee1394/Makefile	Wed Feb 26 13:32:43 2003
+++ b/drivers/ieee1394/Makefile	Wed Feb 26 13:32:43 2003
@@ -8,7 +8,7 @@
 
 list-multi := ieee1394.o
 ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \
-		 highlevel.o csr.o nodemgr.o
+		 highlevel.o csr.o nodemgr.o dma.o
 
 obj-$(CONFIG_IEEE1394) += ieee1394.o
 obj-$(CONFIG_IEEE1394_PCILYNX) += pcilynx.o
diff -Nru a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c
--- a/drivers/ieee1394/amdtp.c	Wed Feb 26 13:32:43 2003
+++ b/drivers/ieee1394/amdtp.c	Wed Feb 26 13:32:43 2003
@@ -598,6 +598,8 @@
 	struct buffer *b;
 
 	b = kmalloc(sizeof *b + size, SLAB_KERNEL);
+	if (b == NULL)
+		return NULL;
 	b->head = 0;
 	b->tail = 0;
 	b->length = 0;
diff -Nru a/drivers/ieee1394/amdtp.h b/drivers/ieee1394/amdtp.h
--- a/drivers/ieee1394/amdtp.h	Wed Feb 26 13:32:43 2003
+++ b/drivers/ieee1394/amdtp.h	Wed Feb 26 13:32:43 2003
@@ -3,8 +3,8 @@
 #ifndef __AMDTP_H
 #define __AMDTP_H
 
-#include <asm/ioctl.h>
 #include <asm/types.h>
+#include "ieee1394-ioctl.h"
 
 /* The userspace interface for the Audio & Music Data Transmission
  * Protocol driver is really simple. First, open /dev/amdtp, use the
@@ -56,13 +56,6 @@
  *   | lsb | msb | lsb | msb | lsb | msb | lsb | msb | lsb | msb | ...
  *
  */
-
-/* We use '#' for our ioctl magic number because it's cool. */
-
-#define AMDTP_IOC_CHANNEL _IOW('#', 0, sizeof (struct amdtp_ioctl))
-#define AMDTP_IOC_PLUG    _IOW('#', 1, sizeof (struct amdtp_ioctl))
-#define AMDTP_IOC_PING    _IOW('#', 2, sizeof (struct amdtp_ioctl))
-#define AMDTP_IOC_ZAP     _IO('#', 3)
 
 enum {
 	AMDTP_FORMAT_RAW,
diff -Nru a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/ieee1394/dma.c	Wed Feb 26 13:32:43 2003
@@ -0,0 +1,236 @@
+/*
+ * DMA region bookkeeping routines
+ *
+ * Copyright (C) 2002 Maas Digital LLC
+ *
+ * This code is licensed under the GPL.  See the file COPYING in the root
+ * directory of the kernel sources for details.
+ */
+
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include "dma.h"
+
+/* dma_prog_region */
+
+void dma_prog_region_init(struct dma_prog_region *prog)
+{
+	prog->kvirt = NULL;
+	prog->dev = NULL;
+	prog->n_pages = 0;
+	prog->bus_addr = 0;
+}
+
+int  dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes, \
struct pci_dev *dev) +{
+	/* round up to page size */
+	n_bytes = round_up_to_page(n_bytes);
+
+	prog->n_pages = n_bytes / PAGE_SIZE;
+
+	prog->kvirt = pci_alloc_consistent(dev, prog->n_pages * PAGE_SIZE, \
&prog->bus_addr); +	if(!prog->kvirt) {
+		printk(KERN_ERR "dma_prog_region_alloc: pci_alloc_consistent() failed\n");
+		dma_prog_region_free(prog);
+		return -ENOMEM;
+	}
+
+	prog->dev = dev;
+
+	return 0;
+}
+
+void dma_prog_region_free(struct dma_prog_region *prog)
+{
+	if(prog->kvirt) {
+		pci_free_consistent(prog->dev, prog->n_pages * PAGE_SIZE, prog->kvirt, \
prog->bus_addr); +	}
+
+	prog->kvirt = NULL;
+	prog->dev = NULL;
+	prog->n_pages = 0;
+	prog->bus_addr = 0;
+}
+
+/* dma_region */
+
+void dma_region_init(struct dma_region *dma)
+{
+	dma->kvirt = NULL;
+	dma->dev = NULL;
+	dma->n_pages = 0;
+	dma->n_dma_pages = 0;
+	dma->sglist = NULL;
+}
+
+int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_dev \
*dev, int direction) +{
+	unsigned int i, n_pages;
+
+	/* round up to page size */
+	n_bytes = round_up_to_page(n_bytes);
+
+	n_pages = n_bytes / PAGE_SIZE;
+
+	dma->kvirt = vmalloc_32(n_pages * PAGE_SIZE);
+	if(!dma->kvirt) {
+		printk(KERN_ERR "dma_region_alloc: vmalloc_32() failed\n");
+		goto err;
+	}
+
+	dma->n_pages = n_pages;
+
+	/* Clear the ram out, no junk to the user */
+	memset(dma->kvirt, 0, n_pages * PAGE_SIZE);
+
+	/* allocate scatter/gather list */
+	dma->sglist = kmalloc(dma->n_pages * sizeof(struct scatterlist), GFP_KERNEL);
+	if(!dma->sglist) {
+		printk(KERN_ERR "dma_region_alloc: kmalloc(sglist) failed\n");
+		goto err;
+	}
+
+	/* just to be safe - this will become unnecessary once sglist->address goes away */
+	memset(dma->sglist, 0, dma->n_pages * sizeof(struct scatterlist));
+
+	/* fill scatter/gather list with pages */
+	for(i = 0; i < dma->n_pages; i++) {
+		unsigned long va = (unsigned long) dma->kvirt + i * PAGE_SIZE;
+			
+		dma->sglist[i].page = vmalloc_to_page((void *)va);
+		dma->sglist[i].length = PAGE_SIZE;
+	}
+
+	/* map sglist to the IOMMU */
+	dma->n_dma_pages = pci_map_sg(dev, &dma->sglist[0], dma->n_pages, direction);
+
+	if(dma->n_dma_pages == 0) {
+		printk(KERN_ERR "dma_region_alloc: pci_map_sg() failed\n");
+		goto err;
+	}
+
+	dma->dev = dev;
+	dma->direction = direction;
+
+	return 0;
+
+err:
+	dma_region_free(dma);
+	return -ENOMEM;
+}
+
+void dma_region_free(struct dma_region *dma)
+{
+	if(dma->n_dma_pages) {
+		pci_unmap_sg(dma->dev, dma->sglist, dma->n_pages, dma->direction);
+		dma->n_dma_pages = 0;
+		dma->dev = NULL;
+	}
+
+	if(dma->sglist) {
+		kfree(dma->sglist);
+		dma->sglist = NULL;
+	}
+
+	if(dma->kvirt) {
+		vfree(dma->kvirt);
+		dma->kvirt = NULL;
+		dma->n_pages = 0;
+	}
+}
+
+/* find the scatterlist index and remaining offset corresponding to a
+   given offset from the beginning of the buffer */
+static inline int dma_region_find(struct dma_region *dma, unsigned long offset, \
unsigned long *rem) +{
+	int i;
+	unsigned long off = offset;
+
+	for(i = 0; i < dma->n_dma_pages; i++) {
+		if(off < sg_dma_len(&dma->sglist[i])) {
+			*rem = off;
+			return i;
+		}
+
+		off -= sg_dma_len(&dma->sglist[i]);
+	}
+
+	panic("dma_region_find: offset %lu beyond end of DMA mapping\n", offset);
+}
+
+dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, unsigned long offset)
+{
+	unsigned long rem;
+
+	struct scatterlist *sg = &dma->sglist[dma_region_find(dma, offset, &rem)];
+	return sg_dma_address(sg) + rem;
+}
+
+void dma_region_sync(struct dma_region *dma, unsigned long offset, unsigned long \
len) +{
+	int first, last;
+	unsigned long rem;
+
+	if(!len)
+		len = 1;
+
+	first = dma_region_find(dma, offset, &rem);
+	last = dma_region_find(dma, offset + len - 1, &rem);
+
+	pci_dma_sync_sg(dma->dev, &dma->sglist[first], last - first + 1, dma->direction);
+}
+
+/* nopage() handler for mmap access */
+
+static struct page*
+dma_region_pagefault(struct vm_area_struct *area, unsigned long address, int \
write_access) +{
+	unsigned long offset;
+	unsigned long kernel_virt_addr;
+	struct page *ret = NOPAGE_SIGBUS;
+
+	struct dma_region *dma = (struct dma_region*) area->vm_private_data;
+
+	if(!dma->kvirt)
+		goto out;
+
+	if( (address < (unsigned long) area->vm_start) ||
+	    (address > (unsigned long) area->vm_start + (PAGE_SIZE * dma->n_pages)) )
+		goto out;
+
+	offset = address - area->vm_start;
+	kernel_virt_addr = (unsigned long) dma->kvirt + offset;
+	ret = vmalloc_to_page((void*) kernel_virt_addr);
+	get_page(ret);
+out:
+	return ret;
+}
+
+static struct vm_operations_struct dma_region_vm_ops = {
+	.nopage	= dma_region_pagefault,
+};
+
+int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_struct \
*vma) +{
+	unsigned long size;
+
+	if(!dma->kvirt)
+		return -EINVAL;
+
+	/* must be page-aligned */
+	if(vma->vm_pgoff != 0)
+		return -EINVAL;
+
+	/* check the length */
+	size = vma->vm_end - vma->vm_start;
+	if(size > (PAGE_SIZE * dma->n_pages))
+		return -EINVAL;
+
+	vma->vm_ops = &dma_region_vm_ops;
+	vma->vm_private_data = dma;
+	vma->vm_file = file;
+	vma->vm_flags |= VM_RESERVED;
+
+	return 0;
+}
diff -Nru a/drivers/ieee1394/dma.h b/drivers/ieee1394/dma.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/ieee1394/dma.h	Wed Feb 26 13:32:43 2003
@@ -0,0 +1,84 @@
+/*
+ * DMA region bookkeeping routines
+ *
+ * Copyright (C) 2002 Maas Digital LLC
+ *
+ * This code is licensed under the GPL.  See the file COPYING in the root
+ * directory of the kernel sources for details.
+ */
+
+#ifndef IEEE1394_DMA_H
+#define IEEE1394_DMA_H
+
+#include <linux/pci.h>
+#include <asm/scatterlist.h>
+
+/* struct dma_prog_region
+   
+   a small, physically-contiguous DMA buffer with random-access,
+   synchronous usage characteristics
+*/
+
+struct dma_prog_region {
+	unsigned char    *kvirt;     /* kernel virtual address */
+	struct pci_dev   *dev;       /* PCI device */
+	unsigned int      n_pages;   /* # of kernel pages */
+	dma_addr_t        bus_addr;  /* base bus address */
+};
+
+/* clear out all fields but do not allocate any memory */
+void dma_prog_region_init(struct dma_prog_region *prog);
+int  dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes, \
struct pci_dev *dev); +void dma_prog_region_free(struct dma_prog_region *prog);
+
+static inline dma_addr_t dma_prog_region_offset_to_bus(struct dma_prog_region *prog, \
unsigned long offset) +{
+	return prog->bus_addr + offset;
+}
+
+/* struct dma_region
+   
+   a large, non-physically-contiguous DMA buffer with streaming,
+   asynchronous usage characteristics
+*/
+
+struct dma_region {
+	unsigned char      *kvirt;       /* kernel virtual address */
+	struct pci_dev     *dev;         /* PCI device */
+	unsigned int        n_pages;     /* # of kernel pages */
+	unsigned int        n_dma_pages; /* # of IOMMU pages */
+	struct scatterlist *sglist;      /* IOMMU mapping */
+	int                 direction;   /* PCI_DMA_TODEVICE, etc */
+};
+
+/* clear out all fields but do not allocate anything */
+void dma_region_init(struct dma_region *dma);
+
+/* allocate the buffer and map it to the IOMMU */
+int  dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_dev \
*dev, int direction); +
+/* unmap and free the buffer */
+void dma_region_free(struct dma_region *dma);
+
+/* sync the IO bus' view of the buffer with the CPU's view */
+void dma_region_sync(struct dma_region *dma, unsigned long offset, unsigned long \
len); +
+/* map the buffer into a user space process */
+int  dma_region_mmap(struct dma_region *dma, struct file *file, struct \
vm_area_struct *vma); +
+/* macro to index into a DMA region (or dma_prog_region) */
+#define dma_region_i(_dma, _type, _index) ( ((_type*) ((_dma)->kvirt)) + (_index) )
+
+/* return the DMA bus address of the byte with the given offset
+   relative to the beginning of the dma_region */
+dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, unsigned long offset);
+
+/* round up a number of bytes to be a multiple of the PAGE_SIZE */
+static inline unsigned long round_up_to_page(unsigned long len)
+{
+	if(len % PAGE_SIZE)
+		len += PAGE_SIZE - (len % PAGE_SIZE);
+	return len;
+}
+
+#endif /* IEEE1394_DMA_H */
diff -Nru a/drivers/ieee1394/dv1394-private.h b/drivers/ieee1394/dv1394-private.h
--- a/drivers/ieee1394/dv1394-private.h	Wed Feb 26 13:32:43 2003
+++ b/drivers/ieee1394/dv1394-private.h	Wed Feb 26 13:32:43 2003
@@ -28,8 +28,7 @@
 
 #include "ieee1394.h"
 #include "ohci1394.h"
-#include <linux/pci.h>
-#include <asm/scatterlist.h>
+#include "dma.h"
 
 /* data structures private to the dv1394 driver */
 /* none of this is exposed to user-space */
@@ -167,12 +166,14 @@
 }
  
 static inline void fill_input_last(struct input_last *il,
+				    int want_interrupt,
 				    unsigned int data_size,
 				    unsigned long data_phys_addr)
 {
 	u32 temp =  3 << 28; /* INPUT_LAST */
 	temp |= 8 << 24; /* s = 1, update xferStatus and resCount */
-	temp |= 3 << 20; /* enable interrupts */
+	if (want_interrupt)
+		temp |= 3 << 20; /* enable interrupts */
 	temp |= 0xC << 16; /* enable branch to address */
 	                       /* disable wait on sync field, not used in DV :-( */
 	temp |= data_size;
@@ -301,8 +302,7 @@
 	unsigned long data; 
 
 	/* Max # of packets per frame */
-	/* 320 is enough for NTSC, need to check what PAL is */
-        #define MAX_PACKETS 500
+#define MAX_PACKETS 500
 
 
 	/* a PAGE_SIZE memory pool for allocating CIP headers
@@ -383,35 +383,6 @@
 /* reset f so that it can be used again */
 static void frame_reset(struct frame *f);
 
-
-/* structure for bookkeeping of a large non-physically-contiguous DMA buffer */
-
-struct dma_region {
-	unsigned int n_pages;
-	unsigned int n_dma_pages;
-	struct scatterlist *sglist;
-};
-
-/* return the DMA bus address of the byte with the given offset
-   relative to the beginning of the dma_region */
-
-static inline dma_addr_t dma_offset_to_bus(struct dma_region *dma, unsigned long \
                offset)
-{
-	int i;
-	struct scatterlist *sg;
-	
-	for(i = 0, sg = &dma->sglist[0]; i < dma->n_dma_pages; i++, sg++) {
-		if(offset < sg_dma_len(sg)) {
-			return sg_dma_address(sg) + offset;
-		} 
-		offset -= sg_dma_len(sg);
-	}
-	
-	printk(KERN_ERR "dv1394: dma_offset_to_bus failed for offset %lu!\n", offset);
-	return 0;
-}
-
-
 /* struct video_card contains all data associated with one instance
    of the dv1394 driver 
 */
@@ -508,9 +479,8 @@
 	
 	/* the large, non-contiguous (rvmalloc()) ringbuffer for DV
            data, exposed to user-space via mmap() */
-	unsigned char     *user_buf;
-	unsigned long      user_buf_size;
-	struct dma_region  user_dma;
+	unsigned long      dv_buf_size;
+	struct dma_region  dv_buf;
 	
 	/* next byte in the ringbuffer that a write() call will fill */
 	size_t write_off;
@@ -579,10 +549,8 @@
 
 	
 	/* physically contiguous packet ringbuffer for receive */
-#define MAX_PACKET_BUFFER 30
-	struct packet *packet_buffer;
-	dma_addr_t     packet_buffer_dma;
-	unsigned long  packet_buffer_size;
+	struct dma_region packet_buf;
+	unsigned long  packet_buf_size;
 	
 	unsigned int current_packet;
 	int first_frame; 	/* received first start frame marker? */
diff -Nru a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
--- a/drivers/ieee1394/dv1394.c	Wed Feb 26 13:32:43 2003
+++ b/drivers/ieee1394/dv1394.c	Wed Feb 26 13:32:43 2003
@@ -53,6 +53,12 @@
     via pci_alloc_consistent()
     
   DONE:
+  - during reception, better handling of dropped frames and continuity errors
+  - during reception, prevent DMA from bypassing the irq tasklets
+  - reduce irq rate during reception (1/250 packets).
+  - add many more internal buffers during reception with scatter/gather dma.
+  - add dbc (continuity) checking on receive, increment status.dropped_frames
+    if not continuous.
   - restart IT DMA after a bus reset
   - safely obtain and release ISO Tx channels in cooperation with OHCI driver
   - map received DIF blocks to their proper location in DV frame (ensure
@@ -91,9 +97,9 @@
 #include <linux/fs.h>
 #include <linux/poll.h>
 #include <linux/smp_lock.h>
+#include <linux/bitops.h>
 #include <asm/byteorder.h>
 #include <asm/atomic.h>
-#include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <linux/proc_fs.h>
@@ -132,7 +138,7 @@
        (will cause undeflows if your machine is too slow!)
 */
 
-#define DV1394_DEBUG_LEVEL 0
+#define DV1394_DEBUG_LEVEL 1
 
 /* for debugging use ONLY: allow more than one open() of the device */
 /* #define DV1394_ALLOW_MORE_THAN_ONE_OPEN 1 */
@@ -185,39 +191,6 @@
 	return (struct video_card*) file->private_data;
 }
 
-
-/*******************************/
-/* Memory management functions */
-/*******************************/
-
-/* note: we no longer use mem_map_reserve, because it causes a memory
-   leak, and setting vma->vm_flags to VM_RESERVED should be sufficient
-   to pin the pages in memory anyway. */
-
-static void * rvmalloc(unsigned long size)
-{
-	void * mem;
-
-	mem = vmalloc_32(size);
-
-	if(mem)
-		memset(mem, 0, size); /* Clear the ram out, 
-					 no junk to the user */
-	return mem;
-}
-
-static void rvfree(void * mem, unsigned long size)
-{
-	if (mem) {
-		vfree(mem);
-	}
-}
-
-/***********************************/
-/* END Memory management functions */
-/***********************************/
-
-
 /*** FRAME METHODS *********************************************************/
 
 static void frame_reset(struct frame *f)
@@ -446,11 +419,7 @@
 		/******************************/
 
 		/* first descriptor - OUTPUT_MORE_IMMEDIATE, for the controller's IT header */
-		fill_output_more_immediate( &(block->u.out.omi),
-					    /* tag - what is this??? */ 1,
-					    video->channel,
-					    /* sync tag - what is this??? */ 0,
-					    payload_size);
+		fill_output_more_immediate( &(block->u.out.omi), 1, video->channel, 0, \
payload_size);  
 		if(empty_packet) {
 			/* second descriptor - OUTPUT_LAST for CIP header */
@@ -501,8 +470,8 @@
 						  PAGE_SIZE - (data_p % PAGE_SIZE),
 
 						  /* DMA address of data_p */
-						  dma_offset_to_bus(&f->video->user_dma,
-								    data_p - (unsigned long) f->video->user_buf));
+						  dma_region_offset_to_bus(&video->dv_buf,
+									   data_p - (unsigned long) video->dv_buf.kvirt));
 
 				fill_output_last( &(block->u.out.u.full.u.cross.ol),
 					  
@@ -516,8 +485,8 @@
 						  480 - (PAGE_SIZE - (data_p % PAGE_SIZE)),
 
 						  /* DMA address of data_p + PAGE_SIZE - (data_p % PAGE_SIZE) */
-						  dma_offset_to_bus(&f->video->user_dma,
-								    data_p + PAGE_SIZE - (data_p % PAGE_SIZE) - (unsigned long) \
f->video->user_buf)); +						  dma_region_offset_to_bus(&video->dv_buf,
+									   data_p + PAGE_SIZE - (data_p % PAGE_SIZE) - (unsigned long) \
video->dv_buf.kvirt));  
 				if(first_packet)
 					f->frame_begin_timestamp = &(block->u.out.u.full.u.cross.ol.q[3]);
@@ -551,8 +520,8 @@
 
 						  
 						  /* DMA address of data_p */
-						  dma_offset_to_bus(&f->video->user_dma,
-								    data_p - (unsigned long) f->video->user_buf));
+						  dma_region_offset_to_bus(&video->dv_buf,
+									   data_p - (unsigned long) video->dv_buf.kvirt));
 				
 				if(first_packet)
 					f->frame_begin_timestamp = &(block->u.out.u.full.u.nocross.ol.q[3]);
@@ -593,13 +562,8 @@
 	   to loop back up to the top */
 	*(f->frame_end_branch) = cpu_to_le32(f->descriptor_pool_dma | \
f->first_n_descriptors);  
-
-	/* make the latest version of the frame buffer visible to the PCI card */
-	/* could optimize this by only syncing the pages associated with this frame */
-	pci_dma_sync_sg(video->ohci->dev,
-			&video->user_dma.sglist[0],
-			video->user_dma.n_dma_pages,
-			PCI_DMA_TODEVICE);
+	/* make the latest version of this frame visible to the PCI card */
+	dma_region_sync(&video->dv_buf, f->data - (unsigned long) video->dv_buf.kvirt, \
video->frame_size);  
 	/* lock against DMA interrupt */
 	spin_lock_irqsave(&video->spinlock, irq_flags);
@@ -798,6 +762,9 @@
 	int dif_sequence = p->data[1] >> 4;           /* dif sequence number is in bits 4 - \
7 */  int dif_block = p->data[2];
 
+	/* sanity check */
+	if (dif_sequence > 11 || dif_block > 149) return;
+		
 	switch (section_type) {
 	case 0:           /* 1 Header block */
 	        memcpy( (void *) f->data + dif_sequence * 150 * 80, p->data, 480);
@@ -825,47 +792,64 @@
 }
 
 
-static void start_dma_receive(struct video_card *video, struct frame *frame)
+static void start_dma_receive(struct video_card *video)
 {
-	/* reset iso recv control register */
-	reg_write(video->ohci, video->ohci_IsoRcvContextControlClear, 0xFFFFFFFF);
-	wmb();
-	
-	/* clear bufferFill, set isochHeader and speed (0=100) */
-	reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, 0x40000000);
-
-	/* match on all tags, listen on channel */
-	reg_write(video->ohci, video->ohci_IsoRcvContextMatch, 0xf0000000 | \
                video->channel);
-	
-	/* address and first descriptor block + Z=1 */
-	reg_write(video->ohci, video->ohci_IsoRcvCommandPtr,             
-		  frame->descriptor_pool_dma | 1); /* Z=1 */
-	wmb();
+	if (video->first_run == 1) {
+		video->first_run = 0;
+		
+		/* start DMA once all of the frames are READY */
+		video->n_clear_frames = 0;
+		video->first_clear_frame = -1;
+		video->current_packet = 0;
+		video->active_frame = 0;
+		
+		/* reset iso recv control register */
+		reg_write(video->ohci, video->ohci_IsoRcvContextControlClear, 0xFFFFFFFF);
+		wmb();
+		
+		/* clear bufferFill, set isochHeader and speed (0=100) */
+		reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, 0x40000000);
 	
-	/* run */
-	reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, 0x8000);
-	flush_pci_write(video->ohci);
+		/* match on all tags, listen on channel */
+		reg_write(video->ohci, video->ohci_IsoRcvContextMatch, 0xf0000000 | \
video->channel); +		
+		/* address and first descriptor block + Z=1 */
+		reg_write(video->ohci, video->ohci_IsoRcvCommandPtr,             
+			  video->frames[0]->descriptor_pool_dma | 1); /* Z=1 */
+		wmb();
+		
+		/* run */
+		reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, 0x8000);
+		flush_pci_write(video->ohci);
+		
+		debug_printk("dv1394: DMA started\n");
 	
-	debug_printk("dv1394: DMA started\n");
-
 #if DV1394_DEBUG_LEVEL >= 2
-	{
-		int i;
-	
-		for(i = 0; i < 1000; ++i) {
-			mdelay(1);
-			if(reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) {
-				printk("DMA ACTIVE after %d msec\n", i);
-				break;
+		{
+			int i;
+		
+			for(i = 0; i < 1000; ++i) {
+				mdelay(1);
+				if(reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) {
+					printk("DMA ACTIVE after %d msec\n", i);
+					break;
+				}
 			}
+			if( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) &  (1 << 11) ) {
+				printk("DEAD, event = %x\n", 
+					   reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & 0x1F);
+			} else
+				printk("RUNNING!\n");
 		}
-		if( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) &  (1 << 11) ) {
-			printk("DEAD, event = %x\n", 
-			       reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & 0x1F);
-		} else
-			printk("RUNNING!\n");
-	}
 #endif
+	} 
+	else if( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) &  (1 << 11) ) \
{ +		debug_printk("DEAD, event = %x\n", 
+			     reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & 0x1F);
+
+		/* wake */
+		reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, (1 << 12));
+	}
 }
 
 
@@ -873,7 +857,7 @@
    receive_packets() - build the DMA program for receiving
 */
 
-static void receive_packets(struct video_card *video, struct frame *f)
+static void receive_packets(struct video_card *video)
 {
 	struct DMA_descriptor_block *block = NULL;
 	dma_addr_t block_dma = 0;
@@ -881,52 +865,46 @@
 	dma_addr_t data_dma = 0;
 	u32 *last_branch_address = NULL;
 	unsigned long irq_flags;
+	int want_interrupt = 0;
+	struct frame *f = NULL;
+	int i, j;
 
 	spin_lock_irqsave(&video->spinlock, irq_flags);
 
-	video->n_clear_frames = 0;
-	video->first_clear_frame = -1;
-
-	for (video->current_packet = 0; video->current_packet < MAX_PACKET_BUFFER; \
                ++video->current_packet) {
-		/* locate a descriptor block and packet from the buffer */
-		block = &(f->descriptor_pool[video->current_packet]);
-		block_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + \
                f->descriptor_pool_dma;
-		
-		data = &(video->packet_buffer[video->current_packet]);
-		data_dma = ((unsigned long) data - (unsigned long) video->packet_buffer) + \
                video->packet_buffer_dma;
-		
-		/* setup DMA descriptor block */
-		fill_input_last( &(block->u.in.il), 512, data_dma);
+	for (j = 0; j < video->n_frames; j++) {
 
-		/* link descriptors */
-		last_branch_address = f->frame_end_branch;
-
-		if (last_branch_address)
-			*(last_branch_address) = cpu_to_le32(block_dma | 1); /* set Z=1 */
-
-		f->frame_end_branch = &(block->u.in.il.q[2]);
-	}
+		/* connect frames */
+		if (j > 0 && f != NULL && f->frame_end_branch != NULL)
+			*(f->frame_end_branch) = cpu_to_le32(video->frames[j]->descriptor_pool_dma | 1); \
/* set Z=1 */ +
+		f = video->frames[j];
+
+		for (i = 0; i < MAX_PACKETS; i++) {
+			/* locate a descriptor block and packet from the buffer */
+			block = &(f->descriptor_pool[i]);
+			block_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + \
f->descriptor_pool_dma; +			
+			data = ((struct packet*)video->packet_buf.kvirt) + f->frame_num * MAX_PACKETS + \
i; +			data_dma = dma_region_offset_to_bus( &video->packet_buf, 
+							     ((unsigned long) data - (unsigned long) video->packet_buf.kvirt) );
+			
+			/* setup DMA descriptor block */
+			want_interrupt = ((i % (MAX_PACKETS/2)) == 0 || i == (MAX_PACKETS-1));
+			fill_input_last( &(block->u.in.il), want_interrupt, 512, data_dma);
+	
+			/* link descriptors */
+			last_branch_address = f->frame_end_branch;
+	
+			if (last_branch_address != NULL)
+				*(last_branch_address) = cpu_to_le32(block_dma | 1); /* set Z=1 */
+	
+			f->frame_end_branch = &(block->u.in.il.q[2]);
+		}
 	
-	/* loop tail to head */
-	if (f->frame_end_branch)
-		*(f->frame_end_branch) = cpu_to_le32(f->descriptor_pool_dma | 1); /* set Z=1 */
+	} /* next j */
 
 	spin_unlock_irqrestore(&video->spinlock, irq_flags);
 
-	if (video->first_run) {
-		/* start DMA once all of the frames are READY */
-		video->first_run = 0;
-		video->current_packet = 0;
-		video->active_frame = f->frame_num;
-		start_dma_receive(video, f);
-	} 
-	else if( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) &  (1 << 11) ) \
                {
-		debug_printk("DEAD, event = %x\n", 
-			     reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & 0x1F);
-
-		/* wake */
-		reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, (1 << 12));
-	}
 }
 
 
@@ -940,6 +918,7 @@
 	u64 chan_mask;
 	int retval = -EINVAL;
 
+	debug_printk( "dv1394: initialising %d\n", video->id );
 	if(init->api_version != DV1394_API_VERSION)
 		goto err;
 	
@@ -969,10 +948,8 @@
 	if(new_buf_size % PAGE_SIZE) new_buf_size += PAGE_SIZE - (new_buf_size % \
PAGE_SIZE);  
 	/* don't allow the user to allocate the DMA buffer more than once */
-	if( (video->user_buf) &&
-	    (video->user_buf_size != new_buf_size) ) {
+	if(video->dv_buf.kvirt && video->dv_buf_size != new_buf_size)
 		goto err;
-	}
 	
 	/* shutdown the card if it's currently active */
 	/* (the card should not be reset if the parameters are screwy) */
@@ -1076,93 +1053,39 @@
 		}
 	}
 
-	
-
-	if(video->user_buf == NULL) {
-		unsigned int i;
-		
+	if(!video->dv_buf.kvirt) {
 		/* allocate the ringbuffer */
-		video->user_buf = rvmalloc(new_buf_size);
-		if(!video->user_buf) {
-			printk(KERN_ERR "dv1394: Cannot allocate frame buffers\n");
+		retval = dma_region_alloc(&video->dv_buf, new_buf_size, video->ohci->dev, \
PCI_DMA_TODEVICE); +		if(retval)
 			goto err_frames;
-		}
-		video->user_buf_size = new_buf_size;
-
-		/* allocate the sglist to hold the DMA addresses */
-		video->user_dma.n_pages = video->user_buf_size / PAGE_SIZE;
-		video->user_dma.sglist = kmalloc(video->user_dma.n_pages * sizeof(struct \
                scatterlist), GFP_KERNEL);
-		if(!video->user_dma.sglist) {
-			printk(KERN_ERR "dv1394: Cannot allocate sglist for user buffer\n");
-			goto err_user_buf;
-		}
-
-		/* initialize all fields of all sglist entries to zero
-		   (new requirement due to PCI changes in 2.4.13) */
-
-		memset(video->user_dma.sglist, 0, video->user_dma.n_pages * sizeof(struct \
scatterlist)); +					  
+		video->dv_buf_size = new_buf_size;
 
-		
-		/* fill the sglist with the kernel addresses of pages in the non-contiguous buffer \
                */
-		for(i = 0; i < video->user_dma.n_pages; i++) {
-			unsigned long va = (unsigned long) video->user_buf + i * PAGE_SIZE;
-			
-			video->user_dma.sglist[i].page = vmalloc_to_page((void *)va);
-			video->user_dma.sglist[i].length = PAGE_SIZE;
-		}
-		
-		/* map the buffer in the IOMMU */
-		/* the user_data buffer only allows DMA *to* the card for transmission;
-		   incoming DV data comes through the packet_buffer first, and then is copied to \
                user_data */
-		video->user_dma.n_dma_pages = pci_map_sg(video->ohci->dev,
-							 &video->user_dma.sglist[0],
-							 video->user_dma.n_pages,
-							 PCI_DMA_TODEVICE);
-		if(video->user_dma.n_dma_pages == 0) {
-			printk(KERN_ERR "dv1394: Error mapping user buffer to the IOMMU\n");
-			goto err_user_buf;
-		}
-		
 		debug_printk("dv1394: Allocated %d frame buffers, total %u pages (%u DMA pages), \
                %lu bytes\n", 
-			     video->n_frames, video->user_dma.n_pages,
-			     video->user_dma.n_dma_pages, video->user_buf_size);
+			     video->n_frames, video->dv_buf.n_pages,
+			     video->dv_buf.n_dma_pages, video->dv_buf_size);
 	}
 	
 	/* set up the frame->data pointers */
 	for(i = 0; i < video->n_frames; i++)
-		video->frames[i]->data = (unsigned long) video->user_buf + i * video->frame_size;
-
-	/* allocate packet buffers */
-	video->packet_buffer_size = sizeof(struct packet) * MAX_PACKET_BUFFER;
-	if (video->packet_buffer_size % PAGE_SIZE)
-		video->packet_buffer_size += PAGE_SIZE - (video->packet_buffer_size % PAGE_SIZE);
+		video->frames[i]->data = (unsigned long) video->dv_buf.kvirt + i * \
video->frame_size;  
-	
-	video->packet_buffer = kmalloc(video->packet_buffer_size, GFP_KERNEL);
-	
-	if(!video->packet_buffer) {
-		printk(KERN_ERR "dv1394: Cannot allocate packet buffers");
-		retval = -ENOMEM;
-		goto err_user_buf;
+	if(!video->packet_buf.kvirt) {
+		/* allocate packet buffer */
+		video->packet_buf_size = sizeof(struct packet) * video->n_frames * MAX_PACKETS;
+		if (video->packet_buf_size % PAGE_SIZE)
+			video->packet_buf_size += PAGE_SIZE - (video->packet_buf_size % PAGE_SIZE);
+		
+		retval = dma_region_alloc(&video->packet_buf, video->packet_buf_size,
+					  video->ohci->dev, PCI_DMA_FROMDEVICE);
+		if(retval)
+			goto err_dv_buf;
+		
+		debug_printk("dv1394: Allocated %d packets in buffer, total %u pages (%u DMA \
pages), %lu bytes\n",  +				 video->n_frames*MAX_PACKETS, video->packet_buf.n_pages,
+				 video->packet_buf.n_dma_pages, video->packet_buf_size);
 	}
-
-	/* map the packet buffer into the IOMMU */
-	video->packet_buffer_dma = pci_map_single(video->ohci->dev,
-						  video->packet_buffer,
-						  video->packet_buffer_size,
-						  PCI_DMA_FROMDEVICE);
-	if(!video->packet_buffer_dma) {
-		printk(KERN_ERR "dv1394: Cannot map packet buffer to IOMMU");
-		kfree(video->packet_buffer);
-		video->packet_buffer = NULL;
-		retval = -ENOMEM;
-		goto err_user_buf;
-	}
-
-	debug_printk("dv1394: Allocated %d packet buffers for receive, total %lu bytes\n", 
-		     MAX_PACKET_BUFFER, video->packet_buffer_size);
-
-
+	
 	/* set up register offsets for IT context */
 	/* IT DMA context registers are spaced 16 bytes apart */
 	video->ohci_IsoXmitContextControlSet = \
OHCI1394_IsoXmitContextControlSet+16*video->ohci_it_ctx; @@ -1186,26 +1109,9 @@
 	
 	return 0;
 
- err_user_buf:
-	if(video->user_buf) {
-		if(video->user_dma.sglist) {
-			if(video->user_dma.n_dma_pages > 0) {
-				/* unmap it from the IOMMU */
-				pci_unmap_sg(video->ohci->dev,
-					     video->user_dma.sglist,
-					     video->user_dma.n_pages,
-					     PCI_DMA_TODEVICE);
-				video->user_dma.n_dma_pages = 0;
-			}
-			kfree(video->user_dma.sglist);
-			video->user_dma.sglist = NULL;
-			video->user_dma.n_pages = 0;
-		}
-		rvfree(video->user_buf, video->user_buf_size);
-		video->user_buf = NULL;
-		video->user_buf_size = 0;
-	}
-		
+ err_dv_buf:
+	dma_region_free(&video->dv_buf);
+	
  err_frames:
 	for(i = 0; i < DV1394_MAX_FRAMES; i++) {
 		if(video->frames[i])
@@ -1238,7 +1144,7 @@
 	struct dv1394_init init;
 
 	init.api_version = DV1394_API_VERSION;
-	init.n_frames = 2;
+	init.n_frames = DV1394_MAX_FRAMES / 4;
 	/* the following are now set via proc_fs or devfs */
 	init.channel = video->channel;
 	init.format = video->pal_or_ntsc;
@@ -1270,7 +1176,6 @@
 		
 		video->active_frame = -1;
 		video->first_run = 1;
-
 		
 		/* wait until DMA really stops */
 		i = 0;
@@ -1282,6 +1187,7 @@
 			if( (reg_read(video->ohci, video->ohci_IsoXmitContextControlClear) & (1 << 10)) \
                ||
 			    (reg_read(video->ohci, video->ohci_IsoRcvContextControlClear)  & (1 << 10)) ) \
{  /* still active */
+				debug_printk("dv1394: stop_dma: DMA not stopped yet\n" );
 				mb();
 			} else {
 				debug_printk("dv1394: stop_dma: DMA stopped safely after %d ms\n", i/10);
@@ -1295,13 +1201,15 @@
 			printk(KERN_ERR "dv1394: stop_dma: DMA still going after %d ms!\n", i/10);
 		}
 	}
-
+	else
+		debug_printk("dv1394: stop_dma: already stopped.\n");
+		
 	spin_unlock_irqrestore(&video->spinlock, flags);
 }
 
 
 
-static int do_dv1394_shutdown(struct video_card *video, int free_user_buf)
+static int do_dv1394_shutdown(struct video_card *video, int free_dv_buf)
 {
 	int i;
 	unsigned long flags;
@@ -1322,7 +1230,8 @@
 		/* disable interrupts for IT context */
 		reg_write(video->ohci, OHCI1394_IsoXmitIntMaskClear, (1 << video->ohci_it_ctx));
 		
-		clear_bit(video->ohci_it_ctx, &video->ohci->it_ctx_usage);
+		/* remove tasklet */
+		ohci1394_unregister_iso_tasklet(video->ohci, &video->it_tasklet);
 		debug_printk("dv1394: IT context %d released\n", video->ohci_it_ctx);
 		video->ohci_it_ctx = -1;
 	}
@@ -1336,13 +1245,14 @@
 		/* disable interrupts for IR context */
 		reg_write(video->ohci, OHCI1394_IsoRecvIntMaskClear, (1 << video->ohci_ir_ctx));
 
-		clear_bit(video->ohci_ir_ctx, &video->ohci->ir_ctx_usage);
+		/* remove tasklet */
+		ohci1394_unregister_iso_tasklet(video->ohci, &video->ir_tasklet);
 		debug_printk("dv1394: IR context %d released\n", video->ohci_ir_ctx);
 		video->ohci_ir_ctx = -1;
 	}
 
 	spin_unlock_irqrestore(&video->spinlock, flags);
-	
+
 	/* release the ISO channel */
 	if(video->channel != -1) {
 		u64 chan_mask;
@@ -1369,42 +1279,20 @@
 	/* we can't free the DMA buffer unless it is guaranteed that
 	   no more user-space mappings exist */
 	
-	if(free_user_buf && video->user_buf) {
-		if(video->user_dma.sglist) {
-			if(video->user_dma.n_dma_pages > 0) {
-				/* unmap it from the IOMMU */
-				pci_unmap_sg(video->ohci->dev,
-					     video->user_dma.sglist,
-					     video->user_dma.n_pages,
-					     PCI_DMA_TODEVICE);
-				video->user_dma.n_dma_pages = 0;
-			}
-			kfree(video->user_dma.sglist);
-			video->user_dma.sglist = NULL;
-			video->user_dma.n_pages = 0;
-		}
-		rvfree(video->user_buf, video->user_buf_size);
-		video->user_buf = NULL;
-		video->user_buf_size = 0;
-	}
-	
-	if (video->packet_buffer) {
-		pci_unmap_single(video->ohci->dev,
-				 video->packet_buffer_dma,
-				 video->packet_buffer_size,
-				 PCI_DMA_FROMDEVICE);
-		kfree(video->packet_buffer);
-		video->packet_buffer = NULL;
-		video->packet_buffer_size = 0;
+	if(free_dv_buf) {
+		dma_region_free(&video->dv_buf);
+		video->dv_buf_size = 0;
 	}
 
+	/* free packet buffer */
+	dma_region_free(&video->packet_buf);
+	video->packet_buf_size = 0;
+
 	debug_printk("dv1394: shutdown complete\n");
 
 	return 0;
 }
 
-
-
 /*
        **********************************
        *** MMAP() THEORY OF OPERATION ***
@@ -1427,96 +1315,28 @@
 	force the user to choose one buffer size and stick with
 	it. This small sacrifice is worth the huge reduction in
 	error-prone code in dv1394.
-
-	Note: dv1394_mmap does no page table manipulation. The page
-	table entries are created by the dv1394_nopage() handler as
-	page faults are taken by the user.
-*/
-
-static struct page * dv1394_nopage(struct vm_area_struct * area, unsigned long \
                address, int write_access)
-{
-	unsigned long offset;
-	unsigned long kernel_virt_addr;
-	struct page *ret = NOPAGE_SIGBUS;
-
-	struct video_card *video = (struct video_card*) area->vm_private_data;
-	
-	/* guard against process-context operations and the interrupt */
-	/* (by definition page faults are taken in interrupt context) */
-	spin_lock(&video->spinlock);
-
-	if(!video->user_buf)
-		goto out;
-
-	if( (address < (unsigned long) area->vm_start) ||
-	    (address > (unsigned long) area->vm_start + video->user_buf_size) )
-		goto out;
-
-	offset = address - area->vm_start;
-	kernel_virt_addr = (unsigned long) video->user_buf + offset;
-	ret = vmalloc_to_page((void *)kernel_virt_addr);
-	get_page(ret);
-
- out:
-	spin_unlock(&video->spinlock);
-	return ret;
-}
-
-static struct vm_operations_struct dv1394_vm_ops = {
-	.nopage = dv1394_nopage
-};
-
-/*
-  dv1394_mmap does no page table manipulation. The page table entries
-  are created by the dv1394_nopage() handler as page faults are taken
-  by the user.
 */
 
 int dv1394_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct video_card *video = file_to_video_card(file);
-	unsigned long size;
-	int res = -EINVAL;
+	int retval = -EINVAL;
 
 	/* serialize mmap */
 	down(&video->sem);
 
 	if( ! video_card_initialized(video) ) {
-		res = do_dv1394_init_default(video);
-		if(res)
-			goto err;
+		retval = do_dv1394_init_default(video);
+		if(retval)
+			goto out;
 	}
 
-	/* region must be page-aligned */
-	if(vma->vm_pgoff != 0)
-		goto err;
-	
-	/* check the size the user is trying to map */
-	size = vma->vm_end - vma->vm_start;
-	if(size > video->user_buf_size)
-		goto err;
-
-	/* 
-	   we don't actually mess with the page tables here.
-	   (nopage() takes care of that from the page fault handler)
-	   Just set up the vma->vm_ops.
-	*/
-
-        vma->vm_ops = &dv1394_vm_ops;
-	vma->vm_private_data = video;
-	vma->vm_file = file;
-
-	/* don't try to swap this out =) */
-	vma->vm_flags |= VM_RESERVED;
-
-	up(&video->sem);
-	return 0;
- err:
+	retval = dma_region_mmap(&video->dv_buf, file, vma);
+out:
 	up(&video->sem);
-	return res;
+	return retval;
 }
 
-
 /*** DEVICE FILE INTERFACE *************************************************/
 
 /* no need to serialize, multiple threads OK */
@@ -1632,7 +1452,7 @@
 			continue; /* start over from 'while(count > 0)...' */
 		}
 
-		if(copy_from_user(video->user_buf + video->write_off, buffer, cnt)) {
+		if(copy_from_user(video->dv_buf.kvirt + video->write_off, buffer, cnt)) {
 			if(!ret)
 				ret = -EFAULT;
 			break;
@@ -1679,7 +1499,11 @@
 			up(&video->sem);
 			return ret;
 		}
-		receive_packets(video, video->frames[video->first_clear_frame]);
+		video->continuity_counter = -1;
+		
+		receive_packets(video);
+		
+		start_dma_receive(video);
 	}
 
 	ret = 0;
@@ -1732,7 +1556,7 @@
 			continue; /* start over from 'while(count > 0)...' */
 		}
 
-		if(copy_to_user(buffer, video->user_buf + video->write_off, cnt)) {
+		if(copy_to_user(buffer, video->dv_buf.kvirt + video->write_off, cnt)) {
 				if(!ret)
 					ret = -EFAULT;
 				break;
@@ -1784,7 +1608,8 @@
 
 	switch(cmd)
 	{
-	case DV1394_SUBMIT_FRAMES: {
+	case DV1394_SUBMIT_FRAMES:
+	case DV1394_IOC_SUBMIT_FRAMES: {
 		unsigned int n_submit;
 
 		if( !video_card_initialized(video) ) {
@@ -1837,8 +1662,8 @@
 		ret = 0;
 		break;
 	}
-
-	case DV1394_WAIT_FRAMES: {
+	case DV1394_WAIT_FRAMES:
+	case DV1394_IOC_WAIT_FRAMES: {
 		unsigned int n_wait;
 
 		if( !video_card_initialized(video) ) {
@@ -1886,8 +1711,8 @@
 		ret = 0;
 		break;
 	}
-
-	case DV1394_RECEIVE_FRAMES: {
+	case DV1394_RECEIVE_FRAMES:
+	case DV1394_IOC_RECEIVE_FRAMES: {
 		unsigned int n_recv;
 
 		if( !video_card_initialized(video) ) {
@@ -1919,22 +1744,25 @@
 		ret = 0;
 		break;
 	}
-
-	case DV1394_START_RECEIVE: {
-
+	case DV1394_START_RECEIVE:
+	case DV1394_IOC_START_RECEIVE: {
 		if( !video_card_initialized(video) ) {
 			ret = do_dv1394_init_default(video);
 			if(ret)
 				goto out;
 		}
 	
-		receive_packets(video, video->frames[video->first_clear_frame]);
+		video->continuity_counter = -1;
+		
+		receive_packets(video);
+		
+		start_dma_receive(video);
 
 		ret = 0;
 		break;
 	}
-
-	case DV1394_INIT: {
+	case DV1394_INIT:
+	case DV1394_IOC_INIT: {
 		struct dv1394_init init;
 		if(arg == (unsigned long) NULL) {
 			ret = do_dv1394_init_default(video);
@@ -1947,13 +1775,13 @@
 		}
 		break;
 	}
-
 	case DV1394_SHUTDOWN:
+	case DV1394_IOC_SHUTDOWN:
 		ret = do_dv1394_shutdown(video, 0);
 		break;
 
-
-        case DV1394_GET_STATUS: {
+	case DV1394_GET_STATUS:
+        case DV1394_IOC_GET_STATUS: {
 		struct dv1394_status status;
 
 		if( !video_card_initialized(video) ) {
@@ -2026,7 +1854,7 @@
 			struct video_card *p;
 			list_for_each(lh, &dv1394_cards) {
 				p = list_entry(lh, struct video_card, list);
-				if((p->id >> 2) == ieee1394_file_to_instance(file)) {
+				if((p->id) == ieee1394_file_to_instance(file)) {
 					video = p;
 					break;
 				}
@@ -2318,9 +2146,7 @@
 	struct video_card *video = (struct video_card*) data;
 
 	spin_lock(&video->spinlock);
-	
-	irq_printk("INTERRUPT! Video = %08lx Iso event Recv: %08x Xmit: %08x\n",
-		   (unsigned long) video, isoRecvIntEvent, isoXmitIntEvent);
+
 	irq_printk("ContextControl = %08x, CommandPtr = %08x\n", 
 	       reg_read(video->ohci, video->ohci_IsoXmitContextControlSet),
 	       reg_read(video->ohci, video->ohci_IsoXmitCommandPtr)
@@ -2462,82 +2288,149 @@
 	int wake = 0;
 	struct video_card *video = (struct video_card*) data;
 
-	if( (video->ohci_ir_ctx != -1) &&
-	    (reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) ) { 
+	spin_lock(&video->spinlock);
+
+	if( (video->ohci_ir_ctx != -1) 
+	    && (reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) ) 
+	{ 
 
 		int sof=0; /* start-of-frame flag */
 		struct frame *f;
 		u16 packet_length, packet_time;
-
-		packet_length = le16_to_cpu(video->packet_buffer[video->current_packet].data_length);
                
-		packet_time   = le16_to_cpu(video->packet_buffer[video->current_packet].timestamp);
                
-
-		irq_printk("received packet %02d, timestamp=%04x, length=%04x, sof=%02x%02x\n", \
                video->current_packet,
-			   packet_time, packet_length, 
-			   video->packet_buffer[video->current_packet].data[0], \
                video->packet_buffer[video->current_packet].data[1]);
-		
-		f = video->frames[video->active_frame];
-
-		/* exclude empty packet */
-		if (packet_length > 8) {
-		
-			/* check for start of frame */
-			sof = (video->packet_buffer[video->current_packet].data[0] == 0x1f &&
-				video->packet_buffer[video->current_packet].data[1] == 0x07);
-
-			if (!video->first_frame) {
-				if (sof) {
-					video->first_frame = 1;
-				}
-
-			} else if (sof) {
-				/* close current frame */
-				frame_reset(f);  /* f->state = STATE_CLEAR */
-				video->n_clear_frames++;
-				if (video->n_clear_frames > video->n_frames) {
-					video->n_clear_frames = video->n_frames;
-					video->dropped_frames++;
-				}
-				if (video->first_clear_frame == -1)
-					video->first_clear_frame = video->active_frame;
-
-				/* get the next frame */
-				video->active_frame = (video->active_frame + 1) % video->n_frames;
-				f = video->frames[video->active_frame];
-			
-				irq_printk("   frame received, active_frame = %d, n_clear_frames = %d, \
                first_clear_frame = %d\n",
-					   video->active_frame, video->n_clear_frames, video->first_clear_frame);
- 			}
-			if (video->first_frame) {
-				if (sof) {
-					/* open next frame */
-					f->state = FRAME_READY;
+		int i, dbc=0;
+		struct DMA_descriptor_block *block = NULL;
+		u16 xferstatus;
+
+		int next_i, prev_i;
+		struct DMA_descriptor_block *next = NULL;
+		dma_addr_t next_dma = 0;
+		struct DMA_descriptor_block *prev = NULL;
+
+		/* loop over all descriptors in all frames */
+		for (i = 0; i < video->n_frames*MAX_PACKETS; i++) {
+			struct packet *p = dma_region_i(&video->packet_buf, struct packet, \
video->current_packet); +
+			/* make sure we are seeing the latest changes to p */
+			dma_region_sync(&video->packet_buf,
+					(unsigned long) p - (unsigned long) video->packet_buf.kvirt,
+					sizeof(struct packet));
+					
+			packet_length = le16_to_cpu(p->data_length);
+			packet_time   = le16_to_cpu(p->timestamp);
+	
+			irq_printk("received packet %02d, timestamp=%04x, length=%04x, sof=%02x%02x\n", \
video->current_packet, +				   packet_time, packet_length, 
+				   p->data[0], p->data[1]);
+			
+			/* get the descriptor based on packet_buffer cursor */
+			f = video->frames[video->current_packet / MAX_PACKETS];
+			block = &(f->descriptor_pool[video->current_packet % MAX_PACKETS]);
+			xferstatus = le16_to_cpu(block->u.in.il.q[3] >> 16);
+			xferstatus &= 0x1F;
+
+			/* get the current frame */
+			f = video->frames[video->active_frame];
+		
+			/* exclude empty packet */
+			if (packet_length > 8 && xferstatus == 0x11) {
+				irq_printk("ir_tasklet_func: xferStatus/resCount [%d] = 0x%08x\n", i, \
le32_to_cpu(block->u.in.il.q[3]) ); +			
+				/* check for start of frame */
+				/* DRD> Changed to check section type ([0]>>5==0) 
+				   and dif sequence ([1]>>4==0) */
+				sof = ( (p->data[0] >> 5) == 0 && (p->data[1] >> 4) == 0);
+	
+				dbc = (int) (p->cip_h1 >> 24);
+				if ( video->continuity_counter != -1 && dbc > ((video->continuity_counter + 1) % \
256) ) +				{
+					printk(KERN_WARNING "dv1394: discontinuity detected, dropping all frames\n" );
+					video->dropped_frames += video->n_clear_frames + 1;
+					video->first_frame = 0;
+					video->n_clear_frames = 0;
+					video->first_clear_frame = -1;
 				}
+				video->continuity_counter = dbc;
 				
-				/* copy to buffer */
-				if (f->n_packets > (video->frame_size / 480)) {
-					printk(KERN_ERR "frame buffer overflow during receive\n");
+				if (!video->first_frame) {
+					if (sof) {
+						video->first_frame = 1;
+					}
+	
+				} else if (sof) {
+					/* close current frame */
+					frame_reset(f);  /* f->state = STATE_CLEAR */
+					video->n_clear_frames++;
+					if (video->n_clear_frames > video->n_frames) {
+						video->dropped_frames++;
+						printk(KERN_WARNING "dv1394: dropped a frame during reception\n" );
+						video->n_clear_frames = video->n_frames-1;
+						video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames;
+					}
+					if (video->first_clear_frame == -1)
+						video->first_clear_frame = video->active_frame;
+	
+					/* get the next frame */
+					video->active_frame = (video->active_frame + 1) % video->n_frames;
+					f = video->frames[video->active_frame];
+					irq_printk("   frame received, active_frame = %d, n_clear_frames = %d, \
first_clear_frame = %d\n", +						   video->active_frame, video->n_clear_frames, \
video->first_clear_frame);  }
+				if (video->first_frame) {
+					if (sof) {
+						/* open next frame */
+						f->state = FRAME_READY;
+					}
+					
+					/* copy to buffer */
+					if (f->n_packets > (video->frame_size / 480)) {
+						printk(KERN_ERR "frame buffer overflow during receive\n");
+					}
+					
+					frame_put_packet(f, p);
+					
+				} /* first_frame */
+			}
+			
+			/* stop, end of ready packets */
+			else if (xferstatus == 0) {
+				break;
+			}
+	 
+			/* reset xferStatus & resCount */
+			block->u.in.il.q[3] = cpu_to_le32(512);
 
-				/* make sure we are seeing the latest changes to packet_buffer */
-				pci_dma_sync_single(video->ohci->dev,
-						    video->packet_buffer_dma,
-						    video->packet_buffer_size,
-						    PCI_DMA_FROMDEVICE);
-				
-				frame_put_packet( f, &video->packet_buffer[video->current_packet]);
-				
-			} /* first_frame */
- 
-		} /* not empty packet */
- 
-		/* advance packet_buffer cursor */
-		video->current_packet = (video->current_packet + 1) % MAX_PACKET_BUFFER;
+			/* terminate dma chain at this (next) packet */
+			next_i = video->current_packet;
+			f = video->frames[next_i / MAX_PACKETS];
+			next = &(f->descriptor_pool[next_i % MAX_PACKETS]);
+			next_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + \
f->descriptor_pool_dma; +			next->u.in.il.q[0] |= 3 << 20; /* enable interrupt */
+			next->u.in.il.q[2] = 0; /* disable branch */
+			
+			/* link previous to next */
+			prev_i = (next_i == 0) ? (MAX_PACKETS * video->n_frames - 1) : (next_i - 1);
+			f = video->frames[prev_i / MAX_PACKETS];
+			prev = &(f->descriptor_pool[prev_i % MAX_PACKETS]);
+			if(prev_i % (MAX_PACKETS/2)) {
+				prev->u.in.il.q[0] &= ~(3 << 20); /* no interrupt */
+			} else {
+				prev->u.in.il.q[0] |= 3 << 20; /* enable interrupt */
+			}
+			prev->u.in.il.q[2] =  (cpu_to_le32(next_dma) | 1); /* set Z=1 */
+			wmb();
+
+			/* wake up DMA in case it fell asleep */
+			reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, (1 << 12));
+
+			/* advance packet_buffer cursor */
+			video->current_packet = (video->current_packet + 1) % (MAX_PACKETS * \
video->n_frames); +			
+		} /* for all packets */
  
 		wake = 1; /* why the hell not? */
-
+		
 	} /* receive interrupt */
-
+	
 	spin_unlock(&video->spinlock);
 	
 	if(wake) {
@@ -2716,6 +2609,10 @@
 	/* lower 2 bits of id indicate which of four "plugs"
 	   per host */
 	video->id = ohci->id << 2; 
+	if (format == DV1394_NTSC)
+		video->id |= mode;
+	else
+		video->id |= 2 + mode;
 
 	video->ohci_it_ctx = -1;
 	video->ohci_ir_ctx = -1;
@@ -2748,8 +2645,10 @@
 	for(i = 0; i < DV1394_MAX_FRAMES; i++)
 		video->frames[i] = NULL;
 
-	video->user_buf = NULL;
-	video->user_buf_size = 0;
+	dma_region_init(&video->dv_buf);
+	video->dv_buf_size = 0;
+	dma_region_init(&video->packet_buf);
+	video->packet_buf_size = 0;
 
 	clear_bit(0, &video->open);
 	spin_lock_init(&video->spinlock);
@@ -2762,10 +2661,6 @@
 	list_add_tail(&video->list, &dv1394_cards);
 	spin_unlock_irqrestore(&dv1394_cards_lock, flags);
 	
-	if (format == DV1394_NTSC)
-		video->id |= mode;
-	else video->id |= 2 + mode;
-
 #ifdef CONFIG_DEVFS_FS
 	if (dv1394_devfs_add_entry(video) < 0)
 			goto err_free;
diff -Nru a/drivers/ieee1394/dv1394.h b/drivers/ieee1394/dv1394.h
--- a/drivers/ieee1394/dv1394.h	Wed Feb 26 13:32:43 2003
+++ b/drivers/ieee1394/dv1394.h	Wed Feb 26 13:32:43 2003
@@ -242,6 +242,7 @@
 	DV1394_GET_STATUS,
 };
 
+#include "ieee1394-ioctl.h"
 
 
 enum pal_or_ntsc {
diff -Nru a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
--- a/drivers/ieee1394/eth1394.c	Wed Feb 26 13:32:43 2003
+++ b/drivers/ieee1394/eth1394.c	Wed Feb 26 13:32:43 2003
@@ -77,7 +77,7 @@
 	printk(KERN_ERR fmt, ## args)
 
 static char version[] __devinitdata =
-	"$Rev: 601 $ Ben Collins <bcollins@debian.org>";
+	"$Rev: 771 $ Ben Collins <bcollins@debian.org>";
 
 /* Our ieee1394 highlevel driver */
 #define ETHER1394_DRIVER_NAME "ether1394"
@@ -368,6 +368,7 @@
 	if (register_netdev (dev)) {
 		ETH1394_PRINT (KERN_ERR, dev->name, "Error registering network driver\n");
 		kfree (dev);
+		kfree (hi);
 		return;
 	}
 
@@ -682,8 +683,8 @@
 	ptask->skb = skb;
 	ptask->addr = addr;
 	ptask->dest_node = dest_node;
-	HPSB_INIT_WORK(&ptask->tq, hpsb_write_sched, ptask);
-	hpsb_schedule_work(&ptask->tq);
+	INIT_TQUEUE(&ptask->tq, hpsb_write_sched, ptask);
+	schedule_task(&ptask->tq);
 
 	return 0;
 fail:
diff -Nru a/drivers/ieee1394/eth1394.h b/drivers/ieee1394/eth1394.h
--- a/drivers/ieee1394/eth1394.h	Wed Feb 26 13:32:43 2003
+++ b/drivers/ieee1394/eth1394.h	Wed Feb 26 13:32:43 2003
@@ -56,7 +56,7 @@
 	struct sk_buff *skb;	/* Socket buffer we are sending */
 	nodeid_t dest_node;	/* Destination of the packet */
 	u64 addr;		/* Address */
-	struct hpsb_queue_struct tq;	/* The task */
+	struct tq_struct tq;	/* The task */
 };
 
 /* IP1394 headers */
diff -Nru a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c
--- a/drivers/ieee1394/hosts.c	Wed Feb 26 13:32:43 2003
+++ b/drivers/ieee1394/hosts.c	Wed Feb 26 13:32:43 2003
@@ -138,7 +138,7 @@
 
 	atomic_set(&h->generation, 0);
 
-	HPSB_INIT_WORK(&h->timeout_tq, (void (*)(void*))abort_timedouts, h);
+	INIT_TQUEUE(&h->timeout_tq, (void (*)(void*))abort_timedouts, h);
 
         h->topology_map = h->csr.topology_map + 3;
         h->speed_map = (u8 *)(h->csr.speed_map + 2);
diff -Nru a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h
--- a/drivers/ieee1394/hosts.h	Wed Feb 26 13:32:43 2003
+++ b/drivers/ieee1394/hosts.h	Wed Feb 26 13:32:43 2003
@@ -3,6 +3,7 @@
 
 #include <linux/wait.h>
 #include <linux/list.h>
+#include <linux/tqueue.h>
 #include <asm/semaphore.h>
 
 #include "ieee1394_types.h"
@@ -30,7 +31,7 @@
 
         struct list_head pending_packets;
         spinlock_t pending_pkt_lock;
-        struct hpsb_queue_struct timeout_tq;
+        struct tq_struct timeout_tq;
 
         /* A bitmask where a set bit means that this tlabel is in use.
          * FIXME - should be handled per node instead of per bus. */
diff -Nru a/drivers/ieee1394/ieee1394-ioctl.h b/drivers/ieee1394/ieee1394-ioctl.h
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/ieee1394/ieee1394-ioctl.h	Wed Feb 26 13:32:43 2003
@@ -0,0 +1,71 @@
+/* Base file for all ieee1394 ioctl's. Linux-1394 has allocated base '#'
+ * with a range of 0x00-0x3f. */
+
+#ifndef __IEEE1394_IOCTL_H
+#define __IEEE1394_IOCTL_H
+
+#include <asm/ioctl.h>
+#include <asm/types.h>
+
+
+/* AMDTP Gets 6 */
+#define AMDTP_IOC_CHANNEL	_IOW('#', 0x00, struct amdtp_ioctl)
+#define AMDTP_IOC_PLUG		_IOW('#', 0x01, struct amdtp_ioctl)
+#define AMDTP_IOC_PING		_IOW('#', 0x02, struct amdtp_ioctl)
+#define AMDTP_IOC_ZAP		_IO ('#', 0x03)
+
+
+/* DV1394 Gets 10 */
+
+/* Get the driver ready to transmit video.  pass a struct dv1394_init* as
+ * the parameter (see below), or NULL to get default parameters */
+#define DV1394_IOC_INIT			_IOW('#', 0x06, struct dv1394_init)
+
+/* Stop transmitting video and free the ringbuffer */
+#define DV1394_IOC_SHUTDOWN		_IO ('#', 0x07)
+
+/* Submit N new frames to be transmitted, where the index of the first new
+ * frame is first_clear_buffer, and the index of the last new frame is
+ * (first_clear_buffer + N) % n_frames */
+#define DV1394_IOC_SUBMIT_FRAMES	_IO ('#', 0x08)
+
+/* Block until N buffers are clear (pass N as the parameter) Because we
+ * re-transmit the last frame on underrun, there will at most be n_frames
+ * - 1 clear frames at any time */
+#define DV1394_IOC_WAIT_FRAMES		_IO ('#', 0x09)
+
+/* Capture new frames that have been received, where the index of the
+ * first new frame is first_clear_buffer, and the index of the last new
+ * frame is (first_clear_buffer + N) % n_frames */
+#define DV1394_IOC_RECEIVE_FRAMES	_IO ('#', 0x0a)
+
+/* Tell card to start receiving DMA */
+#define DV1394_IOC_START_RECEIVE	_IO ('#', 0x0b)
+
+/* Pass a struct dv1394_status* as the parameter */
+#define DV1394_IOC_GET_STATUS		_IOR('#', 0x0c, struct dv1394_status)
+
+
+/* Video1394 Gets 10 */
+
+#define VIDEO1394_IOC_LISTEN_CHANNEL		\
+	_IOWR('#', 0x10, struct video1394_mmap)
+#define VIDEO1394_IOC_UNLISTEN_CHANNEL		\
+	_IOW ('#', 0x11, int)
+#define VIDEO1394_IOC_LISTEN_QUEUE_BUFFER	\
+	_IOW ('#', 0x12, struct video1394_wait)
+#define VIDEO1394_IOC_LISTEN_WAIT_BUFFER	\
+	_IOWR('#', 0x13, struct video1394_wait)
+#define VIDEO1394_IOC_TALK_CHANNEL		\
+	_IOWR('#', 0x14, struct video1394_mmap)
+#define VIDEO1394_IOC_UNTALK_CHANNEL		\
+	_IOW ('#', 0x15, int)
+#define VIDEO1394_IOC_TALK_QUEUE_BUFFER 	\
+	_IOW ('#', 0x16, sizeof (struct video1394_wait) + \
+		sizeof (struct video1394_queue_variable))
+#define VIDEO1394_IOC_TALK_WAIT_BUFFER		\
+	_IOW ('#', 0x17, struct video1394_wait)
+#define VIDEO1394_IOC_LISTEN_POLL_BUFFER	\
+	_IOWR('#', 0x18, struct video1394_wait)
+
+#endif /* __IEEE1394_IOCTL_H */
diff -Nru a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
--- a/drivers/ieee1394/ieee1394_core.c	Wed Feb 26 13:32:43 2003
+++ b/drivers/ieee1394/ieee1394_core.c	Wed Feb 26 13:32:43 2003
@@ -42,6 +42,7 @@
 #include "csr.h"
 #include "nodemgr.h"
 #include "ieee1394_hotplug.h"
+#include "dma.h"
 
 /*
  * Disable the nodemgr detection and config rom reading functionality.
@@ -81,10 +82,10 @@
 	struct list_head *lh, *next;
 
 	list_for_each_safe(lh, next, &packet->complete_tq) {
-		struct hpsb_queue_struct *tq =
-			list_entry(lh, struct hpsb_queue_struct, hpsb_queue_list);
-		list_del(&tq->hpsb_queue_list);
-		hpsb_schedule_work(tq);
+		struct tq_struct *tq =
+			list_entry(lh, struct tq_struct, list);
+		list_del(&tq->list);
+		schedule_task(tq);
 	}
 
 	return;
@@ -93,11 +94,11 @@
 /**
  * hpsb_add_packet_complete_task - add a new task for when a packet completes
  * @packet: the packet whose completion we want the task added to
- * @tq: the hpsb_queue_struct describing the task to add
+ * @tq: the tq_struct describing the task to add
  */
-void hpsb_add_packet_complete_task(struct hpsb_packet *packet, struct \
hpsb_queue_struct *tq) +void hpsb_add_packet_complete_task(struct hpsb_packet \
*packet, struct tq_struct *tq)  {
-	list_add_tail(&tq->hpsb_queue_list, &packet->complete_tq);
+	list_add_tail(&tq->list, &packet->complete_tq);
 	return;
 }
 
@@ -437,7 +438,7 @@
         spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
 
         up(&packet->state_change);
-        hpsb_schedule_work(&host->timeout_tq);
+        schedule_task(&host->timeout_tq);
 }
 
 /**
@@ -881,7 +882,7 @@
         }
 
         if (!list_empty(&host->pending_packets))
-		hpsb_schedule_work(&host->timeout_tq);
+		schedule_task(&host->timeout_tq);
 
         spin_unlock_irqrestore(&host->pending_pkt_lock, flags);
 
@@ -1030,7 +1031,7 @@
 	   to get the index of the ieee1394_driver
 	   we want */
 	
-	blocknum = (minor(inode->i_rdev) >> 4) & 0xF;
+	blocknum = (MINOR(inode->i_rdev) >> 4) & 0xF;
 
 	/* look up the driver */
 
@@ -1218,3 +1219,15 @@
 EXPORT_SYMBOL(ieee1394_devfs_handle);
 
 EXPORT_SYMBOL(ieee1394_procfs_entry);
+
+/** dma.c **/
+EXPORT_SYMBOL(dma_prog_region_init);
+EXPORT_SYMBOL(dma_prog_region_alloc);
+EXPORT_SYMBOL(dma_prog_region_free);
+EXPORT_SYMBOL(dma_region_init);
+EXPORT_SYMBOL(dma_region_alloc);
+EXPORT_SYMBOL(dma_region_free);
+EXPORT_SYMBOL(dma_region_sync);
+EXPORT_SYMBOL(dma_region_mmap);
+EXPORT_SYMBOL(dma_region_offset_to_bus);
+
diff -Nru a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
--- a/drivers/ieee1394/ieee1394_core.h	Wed Feb 26 13:32:43 2003
+++ b/drivers/ieee1394/ieee1394_core.h	Wed Feb 26 13:32:43 2003
@@ -77,7 +77,7 @@
 };
 
 /* add a new task for when a packet completes */
-void hpsb_add_packet_complete_task(struct hpsb_packet *packet, struct \
hpsb_queue_struct *tq); +void hpsb_add_packet_complete_task(struct hpsb_packet \
*packet, struct tq_struct *tq);  
 static inline struct hpsb_packet *driver_packet(struct list_head *l)
 {
@@ -194,7 +194,7 @@
 /* return the index (within a minor number block) of a file */
 static inline unsigned char ieee1394_file_to_instance(struct file *file)
 {
-	unsigned char minor = minor(file->f_dentry->d_inode->i_rdev);
+	unsigned char minor = MINOR(file->f_dentry->d_inode->i_rdev);
 	
 	/* return lower 4 bits */
 	return minor & 0xF;
diff -Nru a/drivers/ieee1394/ieee1394_types.h b/drivers/ieee1394/ieee1394_types.h
--- a/drivers/ieee1394/ieee1394_types.h	Wed Feb 26 13:32:43 2003
+++ b/drivers/ieee1394/ieee1394_types.h	Wed Feb 26 13:32:43 2003
@@ -10,27 +10,6 @@
 #include <asm/byteorder.h>
 
 
-/* The great kdev_t changeover in 2.5.x */
-#include <linux/kdev_t.h>
-#ifndef minor
-#define minor(dev) MINOR(dev)
-#endif
-
-#ifndef __devexit_p
-#define __devexit_p(x) x
-#endif
-
-#include <linux/spinlock.h>
-
-#ifndef list_for_each_safe
-#define list_for_each_safe(pos, n, head) \
-	for (pos = (head)->next, n = pos->next; pos != (head); \
-		pos = n, n = pos->next)
-
-#endif
-
-#define pte_offset_kernel pte_offset
-
 #ifndef MIN
 #define MIN(a,b) ((a) < (b) ? (a) : (b))
 #endif
@@ -38,15 +17,6 @@
 #ifndef MAX
 #define MAX(a,b) ((a) > (b) ? (a) : (b))
 #endif
-
-
-/* Use task queue */
-#include <linux/tqueue.h>
-#define hpsb_queue_struct tq_struct
-#define hpsb_queue_list list
-#define hpsb_schedule_work(x) schedule_task(x)
-#define HPSB_INIT_WORK(x,y,z) INIT_TQUEUE(x,y,z)
-#define HPSB_PREPARE_WORK(x,y,z) PREPARE_TQUEUE(x,y,z)
 
 
 typedef u32 quadlet_t;
diff -Nru a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
--- a/drivers/ieee1394/ohci1394.c	Wed Feb 26 13:32:43 2003
+++ b/drivers/ieee1394/ohci1394.c	Wed Feb 26 13:32:43 2003
@@ -153,7 +153,7 @@
 printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args)
 
 static char version[] __devinitdata =
-	"$Rev: 693 $ Ben Collins <bcollins@debian.org>";
+	"$Rev: 758 $ Ben Collins <bcollins@debian.org>";
 
 /* Module Parameters */
 MODULE_PARM(attempt_root,"i");
@@ -1225,8 +1225,8 @@
 			PRINT(KERN_ERR, ohci->id,
 			      "SelfID received outside of bus reset sequence");
 
-		event &= ~OHCI1394_selfIDComplete;
 selfid_not_valid:
+		event &= ~OHCI1394_selfIDComplete;
 	}
 
 	/* Make sure we handle everything, just in case we accidentally
@@ -1439,7 +1439,7 @@
 	struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
 	struct hpsb_packet *packet;
 	unsigned long flags;
-	u32 ack;
+	u32 status, ack;
         size_t datasize;
 
 	spin_lock_irqsave(&d->lock, flags);
@@ -1448,25 +1448,16 @@
 		packet = driver_packet(d->fifo_list.next);
                 datasize = packet->data_size;
 		if (datasize && packet->type != hpsb_raw)
-			ack = le32_to_cpu(
+			status = le32_to_cpu(
 				d->prg_cpu[d->sent_ind]->end.status) >> 16;
 		else 
-			ack = le32_to_cpu(
+			status = le32_to_cpu(
 				d->prg_cpu[d->sent_ind]->begin.status) >> 16;
 
-		if (ack == 0) 
+		if (status == 0) 
 			/* this packet hasn't been sent yet*/
 			break;
 
-		if (!(ack & 0x10)) {
-			/* XXX: This is an OHCI evt_* code. We need to handle
-			 * this specially! For right now, we just fake an
-			 * ackx_send_error. */
-			PRINT(KERN_DEBUG, ohci->id, "Received OHCI evt_* error 0x%x",
-			       ack & 0xf);
-			ack = (ack & 0xffe0) | ACK_BUSY_A;
-		}
-
 #ifdef OHCI1394_DEBUG
 		if (datasize)
 			DBGMSG(ohci->id,
@@ -1478,7 +1469,7 @@
                                         >>4)&0xf,
                                 (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])
                                         >>10)&0x3f,
-                                ack&0x1f, (ack>>5)&0x3, 
+                                status&0x1f, (status>>5)&0x3, 
                                 le32_to_cpu(d->prg_cpu[d->sent_ind]->data[3])
                                         >>16,
                                 d->ctx);
@@ -1492,13 +1483,64 @@
                                         >>4)&0xf,
                                 (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])
                                         >>10)&0x3f,
-                                ack&0x1f, (ack>>5)&0x3, 
+                                status&0x1f, (status>>5)&0x3, 
                                 le32_to_cpu(d->prg_cpu[d->sent_ind]->data[3]),
                                 d->ctx);
 #endif		
 
+		if (status & 0x10) {
+			ack = status & 0xf;
+		} else {
+			switch (status & 0x1f) {
+			case EVT_NO_STATUS: /* that should never happen */
+			case EVT_RESERVED_A: /* that should never happen */
+			case EVT_LONG_PACKET: /* that should never happen */
+				PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f);
+				ack = ACKX_SEND_ERROR;
+				break;
+			case EVT_MISSING_ACK:
+				ack = ACKX_TIMEOUT;
+				break;
+			case EVT_UNDERRUN:
+				ack = ACKX_SEND_ERROR;
+				break;
+			case EVT_OVERRUN: /* that should never happen */
+				PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f);
+				ack = ACKX_SEND_ERROR;
+				break;
+			case EVT_DESCRIPTOR_READ:
+			case EVT_DATA_READ:
+			case EVT_DATA_WRITE:
+				ack = ACKX_SEND_ERROR;
+				break;
+			case EVT_BUS_RESET: /* that should never happen */
+				PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f);
+				ack = ACKX_SEND_ERROR;
+				break;
+			case EVT_TIMEOUT:
+				ack = ACKX_TIMEOUT;
+				break;
+			case EVT_TCODE_ERR:
+				ack = ACKX_SEND_ERROR;
+				break;
+			case EVT_RESERVED_B: /* that should never happen */
+			case EVT_RESERVED_C: /* that should never happen */
+				PRINT(KERN_WARNING, ohci->id, "Received OHCI evt_* error 0x%x", status & 0x1f);
+				ack = ACKX_SEND_ERROR;
+				break;
+			case EVT_UNKNOWN:
+			case EVT_FLUSHED:
+				ack = ACKX_SEND_ERROR;
+				break;
+			default:
+				PRINT(KERN_ERR, ohci->id, "Unhandled OHCI evt_* error 0x%x", status & 0x1f);
+				ack = ACKX_SEND_ERROR;
+				BUG();
+			}
+		}
+
                 list_del(&packet->driver_list);
-		hpsb_packet_sent(ohci->host, packet, ack & 0xf);
+		hpsb_packet_sent(ohci->host, packet, ack);
 
 		if (datasize) {
 			pci_unmap_single(ohci->dev, 
@@ -1739,7 +1781,7 @@
 	/* initialize tasklet */
 	if (type == DMA_CTX_ISO) {
 		ohci1394_init_iso_tasklet(&ohci->it_tasklet, OHCI_ISO_TRANSMIT,
-					  dma_rcv_tasklet, (unsigned long) d);
+					  dma_trm_tasklet, (unsigned long) d);
 		if (ohci1394_register_iso_tasklet(ohci,
 						  &ohci->it_tasklet) < 0) {
 			PRINT(KERN_ERR, ohci->id, "No IT DMA context available");
diff -Nru a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h
--- a/drivers/ieee1394/ohci1394.h	Wed Feb 26 13:32:43 2003
+++ b/drivers/ieee1394/ohci1394.h	Wed Feb 26 13:32:43 2003
@@ -380,7 +380,7 @@
 
 /* OHCI evt_* error types, table 3-2 of the OHCI 1.1 spec. */
 #define EVT_NO_STATUS		0x0	/* No event status */
-#define EVT_RESERVED		0x1	/* Reserved, not used !!! */
+#define EVT_RESERVED_A		0x1	/* Reserved, not used !!! */
 #define EVT_LONG_PACKET		0x2	/* The revc data was longer than the buf */
 #define EVT_MISSING_ACK		0x3	/* A subaction gap was detected before an ack
 					   arrived, or recv'd ack had a parity error */
@@ -399,6 +399,17 @@
 					   16-bit host memory write */
 #define EVT_BUS_RESET		0x9	/* Identifies a PHY packet in the recv buffer as
 					   being a synthesized bus reset packet */
+#define EVT_TIMEOUT		0xa	/* Indicates that the asynchronous transmit response
+					   packet expired and was not transmitted, or that an
+					   IT DMA context experienced a skip processing overflow */
+#define EVT_TCODE_ERR		0xb	/* A bad tCode is associated with this packet.
+					   The packet was flushed */
+#define EVT_RESERVED_B		0xc	/* Reserved, not used !!! */
+#define EVT_RESERVED_C		0xd	/* Reserved, not used !!! */
+#define EVT_UNKNOWN		0xe	/* An error condition has occurred that cannot be
+					   represented by any other event codes defined herein. */
+#define EVT_FLUSHED		0xf	/* Send by the link side of output FIFO when asynchronous
+					   packets are being flushed due to a bus reset. */
 
 #define OHCI1394_TCODE_PHY               0xE
 
diff -Nru a/drivers/video/riva/accel.c b/drivers/video/riva/accel.c
--- a/drivers/video/riva/accel.c	Wed Feb 26 13:32:43 2003
+++ b/drivers/video/riva/accel.c	Wed Feb 26 13:32:43 2003
@@ -243,10 +243,17 @@
 	setup:		fbcon_riva8_setup,
 	bmove:		fbcon_riva_bmove,
 	clear:		fbcon_riva8_clear,
+#ifdef __BIG_ENDIAN
+	putc:		fbcon_cfb8_putc,
+	putcs:		fbcon_cfb8_putcs,
+	revc:		fbcon_cfb8_revc,
+	clear_margins:	fbcon_cfb8_clear_margins,
+#else
 	putc:		fbcon_riva8_putc,
 	putcs:		fbcon_riva8_putcs,
 	revc:		fbcon_riva8_revc,
 	clear_margins:	fbcon_riva8_clear_margins,
+#endif	
 	fontwidthmask:	FONTWIDTHRANGE(4, 16)
 };
 #endif
@@ -346,10 +353,17 @@
 	setup:		fbcon_riva16_setup,
 	bmove:		fbcon_riva_bmove,
 	clear:		fbcon_riva16_clear,
+#ifdef __BIG_ENDIAN
+	putc:		fbcon_cfb16_putc,
+	putcs:		fbcon_cfb16_putcs,
+	revc:		fbcon_cfb16_revc,
+	clear_margins:	fbcon_cfb16_clear_margins,
+#else
 	putc:		fbcon_riva16_putc,
 	putcs:		fbcon_riva16_putcs,
 	revc:		fbcon_riva1632_revc,
 	clear_margins:	fbcon_riva16_clear_margins,
+#endif
 	fontwidthmask:	FONTWIDTHRANGE(4, 16)
 };
 #endif
@@ -420,10 +434,17 @@
 	setup:		fbcon_riva32_setup,
 	bmove:		fbcon_riva_bmove,
 	clear:		fbcon_riva32_clear,
+#ifdef __BIG_ENDIAN
+	putc:		fbcon_cfb32_putc,
+	putcs:		fbcon_cfb32_putcs,
+	revc:		fbcon_cfb32_revc,
+	clear_margins:	fbcon_cfb32_clear_margins,
+#else
 	putc:		fbcon_riva32_putc,
 	putcs:		fbcon_riva32_putcs,
 	revc:		fbcon_riva1632_revc,
 	clear_margins:	fbcon_riva32_clear_margins,
+#endif
 	fontwidthmask:	FONTWIDTHRANGE(4, 16)
 };
 #endif
diff -Nru a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
--- a/drivers/video/riva/fbdev.c	Wed Feb 26 13:32:43 2003
+++ b/drivers/video/riva/fbdev.c	Wed Feb 26 13:32:43 2003
@@ -1,9 +1,12 @@
 /*
- * linux/drivers/video/riva/fbdev.c - nVidia RIVA 128/TNT/TNT2 fb driver
+ * linux/drivers/video/riva/fbdev.c
  *
- * Maintained by Ani Joshi <ajoshi@shell.unixbox.com>
+ * nVidia RIVA 128/TNT/TNT2/GeForce2/3 fb driver
+ *
+ * Maintained by Ani Joshi <ajoshi@kernel.crashing.org>
  *
  * Copyright 1999-2000 Jeff Garzik
+ * Copyright 2000-2003 Ani Joshi
  *
  * Contributors:
  *
@@ -55,7 +58,7 @@
 
 
 /* version number of this driver */
-#define RIVAFB_VERSION "0.9.3"
+#define RIVAFB_VERSION "0.9.4"
 
 
 
@@ -95,7 +98,11 @@
 #define CURSOR_HIDE_DELAY		(20)
 #define CURSOR_SHOW_DELAY		(3)
 
+#ifdef __BIG_ENDIAN
+#define CURSOR_COLOR		0xff7f
+#else
 #define CURSOR_COLOR		0x7fff
+#endif
 #define TRANSPARENT_COLOR	0x0000
 #define MAX_CURS		32
 
@@ -863,6 +870,7 @@
 	struct riva_regs newmode;
 	int bpp, width, hDisplaySize, hDisplay, hStart,
 	    hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock;
+	int hBlankStart, hBlankEnd, vBlankStart, vBlankEnd;
 
 	/* time to calculate */
 
@@ -879,6 +887,8 @@
 		video_mode->hsync_len) / 8 - 1;
 	hTotal = (hDisplaySize + video_mode->right_margin +
 		  video_mode->hsync_len + video_mode->left_margin) / 8 - 1;
+	hBlankStart = hDisplay;
+	hBlankEnd = hTotal;
 	height = video_mode->yres_virtual;
 	vDisplay = video_mode->yres - 1;
 	vStart = video_mode->yres + video_mode->lower_margin - 1;
@@ -886,35 +896,63 @@
 	       video_mode->vsync_len - 1;
 	vTotal = video_mode->yres + video_mode->lower_margin +
 		 video_mode->vsync_len + video_mode->upper_margin + 2;
+	vBlankStart = vDisplay;
+	vBlankEnd = vTotal;
 	dotClock = 1000000000 / video_mode->pixclock;
 
 	memcpy(&newmode, &reg_template, sizeof(struct riva_regs));
 
+	newmode.ext.screen = SetBitField(hBlankEnd,6:6,4:4)
+                  | SetBitField(vBlankStart,10:10,3:3)
+                  | SetBitField(vStart,10:10,2:2)
+                  | SetBitField(vDisplay,10:10,1:1)
+                  | SetBitField(vTotal,10:10,0:0);
+    
+    	newmode.ext.horiz  = SetBitField(hTotal,8:8,0:0)
+                  | SetBitField(hDisplay,8:8,1:1)
+                  | SetBitField(hBlankStart,8:8,2:2)
+                  | SetBitField(hStart,8:8,3:3);
+
+    	newmode.ext.extra  = SetBitField(vTotal,11:11,0:0)
+                    | SetBitField(vDisplay,11:11,2:2)
+                    | SetBitField(vStart,11:11,4:4)
+                    | SetBitField(vBlankStart,11:11,6:6);
+
+	if (rinfo->riva.flatPanel) {
+		vStart = vTotal - 3;
+		vEnd = vTotal - 2;
+		vBlankStart = vStart;
+		hStart = hTotal - 3;
+		hEnd = hTotal - 2;
+		hBlankEnd = hTotal + 4;
+	}
+
 	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[0x2] = Set8Bits (hBlankStart);
+	newmode.crtc[0x3] = SetBitField(hBlankEnd,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[0x5] = SetBitField (hBlankEnd, 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)
+		| SetBitField (vBlankStart, 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)
+	newmode.crtc[0x9] = SetBitField (vBlankStart, 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.crtc[0x15] = Set8Bits (vBlankStart);
+	newmode.crtc[0x16] = Set8Bits (vBlankEnd);
 
 	newmode.ext.bpp = bpp;
 	newmode.ext.width = width;
@@ -925,11 +963,31 @@
 				  hTotal, height, vDisplay, vStart, vEnd,
 				  vTotal, dotClock);
 
+	newmode.ext.scale = rinfo->riva.PRAMDAC[0x00000848/4] & 0xfff000ff;
+
+	if (rinfo->riva.flatPanel) {
+		newmode.ext.pixel |= (1 << 7);
+		newmode.ext.scale |= (1 << 8);
+	}
+
+	newmode.ext.vpll2 = rinfo->riva.PRAMDAC[0x00000520/4];
+
+#if defined(__powerpc__)
+	/*
+	 * XXX only Mac cards use second DAC for flat panel
+	 */
+	if (rinfo->riva.flatPanel) {
+		newmode.ext.pllsel |= 0x20000800;
+		newmode.ext.vpll2 = newmode.ext.vpll;
+	}
+#endif
 	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);
+
+	rivafb_blank(0, (struct fb_info *)rinfo);
 }
 
 /**
@@ -1780,6 +1838,10 @@
 		fb_find_mode(&rinfo->disp.var, &rinfo->info, mode_option,
 			     NULL, 0, NULL, 8);
 #endif
+	if (rinfo->use_default_var)
+		/* We will use the modified default var */
+		rinfo->disp.var = rivafb_default_var;
+
 	return 0;
 }
 
@@ -1850,6 +1912,117 @@
 	return 0;
 }
 
+#ifdef CONFIG_ALL_PPC
+static int riva_get_EDID_OF(struct rivafb_info *rinfo)
+{
+	struct device_node *dp;
+	unsigned char *pedid = NULL;
+
+	dp = pci_device_to_OF_node(rinfo->pd);
+	pedid = (unsigned char *)get_property(dp, "EDID,B", 0);
+
+	if (pedid) {
+		rinfo->EDID = pedid;
+		return 1;
+	} else
+		return 0;
+}
+#endif /* CONFIG_ALL_PPC */
+
+static int riva_dfp_parse_EDID(struct rivafb_info *rinfo)
+{
+	unsigned char *block = rinfo->EDID;
+
+	if (!block)
+		return 0;
+
+	/* jump to detailed timing block section */
+	block += 54;
+
+        rinfo->clock = (block[0] + (block[1] << 8));
+        rinfo->panel_xres = (block[2] + ((block[4] & 0xf0) << 4));
+        rinfo->hblank = (block[3] + ((block[4] & 0x0f) << 8));
+        rinfo->panel_yres = (block[5] + ((block[7] & 0xf0) << 4));
+        rinfo->vblank = (block[6] + ((block[7] & 0x0f) << 8));
+        rinfo->hOver_plus = (block[8] + ((block[11] & 0xc0) << 2));
+        rinfo->hSync_width = (block[9] + ((block[11] & 0x30) << 4));
+        rinfo->vOver_plus = ((block[10] >> 4) + ((block[11] & 0x0c) << 2));
+        rinfo->vSync_width = ((block[10] & 0x0f) + ((block[11] & 0x03) << 4));
+        rinfo->interlaced = ((block[17] & 0x80) >> 7);
+        rinfo->synct = ((block[17] & 0x18) >> 3);
+        rinfo->misc = ((block[17] & 0x06) >> 1);
+        rinfo->hAct_high = rinfo->vAct_high = 0;
+        if (rinfo->synct == 3) {
+                if (rinfo->misc & 2)
+                        rinfo->hAct_high = 1;
+                if (rinfo->misc & 1)
+                        rinfo->vAct_high = 1;
+	}
+
+	printk("rivafb: detected DFP panel size from EDID: %dx%d\n",
+		rinfo->panel_xres, rinfo->panel_yres);
+
+	rinfo->got_dfpinfo = 1;
+
+	return 1;
+}
+
+static void riva_update_default_var(struct rivafb_info *rinfo)
+{
+	struct fb_var_screeninfo *var = &rivafb_default_var;
+
+        var->xres = rinfo->panel_xres;
+        var->yres = rinfo->panel_yres;
+        var->xres_virtual = rinfo->panel_xres;
+        var->yres_virtual = rinfo->panel_yres;
+        var->xoffset = var->yoffset = 0;
+        var->bits_per_pixel = 8;
+        var->pixclock = 100000000 / rinfo->clock;
+        var->left_margin = (rinfo->hblank - rinfo->hOver_plus - rinfo->hSync_width);
+        var->right_margin = rinfo->hOver_plus;
+        var->upper_margin = (rinfo->vblank - rinfo->vOver_plus - \
rinfo->vSync_width); +        var->lower_margin = rinfo->vOver_plus;
+        var->hsync_len = rinfo->hSync_width;
+        var->vsync_len = rinfo->vSync_width;
+        var->sync = 0;
+
+        if (rinfo->synct == 3) {
+                if (rinfo->hAct_high)
+                        var->sync |= FB_SYNC_HOR_HIGH_ACT;
+                if (rinfo->vAct_high)
+                        var->sync |= FB_SYNC_VERT_HIGH_ACT;
+        }
+ 
+        var->vmode = 0;
+        if (rinfo->interlaced)
+                var->vmode |= FB_VMODE_INTERLACED;
+
+	if (!noaccel)
+		var->accel_flags |= FB_ACCELF_TEXT;
+        
+        rinfo->use_default_var = 1;
+}
+
+
+static void riva_get_EDID(struct rivafb_info *rinfo)
+{
+#ifdef CONFIG_ALL_PPC
+	if (!riva_get_EDID_OF(rinfo))
+		printk("rivafb: could not retrieve EDID from OF\n");
+#else
+	/* XXX use other methods later */
+#endif
+}
+
+
+static void riva_get_dfpinfo(struct rivafb_info *rinfo)
+{
+	if (riva_dfp_parse_EDID(rinfo))
+		riva_update_default_var(rinfo);
+
+	rinfo->riva.flatPanel = rinfo->got_dfpinfo;
+}
+
 
 
 /* ------------------------------------------------------------------------- *
@@ -1880,15 +2053,18 @@
 	rinfo->base0_region_size = pci_resource_len(pd, 0);
 	rinfo->base1_region_size = pci_resource_len(pd, 1);
 
+	{
+		/* enable IO and mem if not already done */
+		unsigned short cmd;
+
+		pci_read_config_word(pd, PCI_COMMAND, &cmd);
+		cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+		pci_write_config_word(pd, PCI_COMMAND, cmd);
+	}
+ 
 	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;
-	}
-
 	rinfo->ctrl_base = ioremap(rinfo->ctrl_base_phys,
 				   rinfo->base0_region_size);
 	if (!rinfo->ctrl_base) {
@@ -1896,6 +2072,10 @@
 		goto err_out_free_base1;
 	}
 	
+	riva_get_EDID(rinfo);
+
+	riva_get_dfpinfo(rinfo);
+
 	rinfo->riva.EnableIRQ = 0;
 	rinfo->riva.PRAMDAC = (unsigned *)(rinfo->ctrl_base + 0x00680000);
 	rinfo->riva.PFB = (unsigned *)(rinfo->ctrl_base + 0x00100000);
@@ -1943,6 +2123,19 @@
 		rinfo->riva.PRAMIN = (unsigned *)(rinfo->ctrl_base + 0x00710000);
 		break;
 	}
+
+#if defined(__powerpc__)
+	/*
+	 * XXX Mac cards use the second DAC for the panel
+	 */
+	if (rinfo->riva.flatPanel) {
+		printk("rivafb: using second CRTC\n");
+		rinfo->riva.PCIO = rinfo->riva.PCIO + 0x2000;
+		rinfo->riva.PCRTC = rinfo->riva.PCRTC + 0x800;
+		rinfo->riva.PRAMDAC = rinfo->riva.PRAMDAC + 0x800;
+		rinfo->riva.PDIO = rinfo->riva.PDIO + 0x2000;
+	}
+#endif
 
 	RivaGetConfig(&rinfo->riva);
 
diff -Nru a/drivers/video/riva/riva_hw.c b/drivers/video/riva/riva_hw.c
--- a/drivers/video/riva/riva_hw.c	Wed Feb 26 13:32:43 2003
+++ b/drivers/video/riva/riva_hw.c	Wed Feb 26 13:32:43 2003
@@ -1449,6 +1449,16 @@
 		chip->PGRAPH[0x000009A4/4] = chip->PFB[0x00000200/4];
 		chip->PGRAPH[0x000009A8/4] = chip->PFB[0x00000204/4];
 	    }
+
+	    chip->PFB[0x00000240/4] = 0;
+	    chip->PFB[0x00000244/4] = 0;
+	    chip->PFB[0x00000248/4] = 0;
+	    chip->PFB[0x0000024C/4] = 0;
+	    chip->PFB[0x00000250/4] = 0;
+	    chip->PFB[0x00000244/4] = 0;
+	    chip->PFB[0x00000248/4] = 0;
+	    chip->PFB[0x0000024C/4] = 0;
+
             chip->PGRAPH[0x00000B00/4] = chip->PFB[0x00000240/4];
             chip->PGRAPH[0x00000B04/4] = chip->PFB[0x00000244/4];
             chip->PGRAPH[0x00000B08/4] = chip->PFB[0x00000248/4];
@@ -1522,6 +1532,15 @@
             chip->PGRAPH[0x00000F50/4] = 0x00000040;
             for (i = 0; i < 4; i++)
                 chip->PGRAPH[0x00000F54/4] = 0x00000000;
+
+	    if (chip->flatPanel) {
+		VGA_WR08(chip->PCIO, 0x3d4, 0x53);
+		VGA_WR08(chip->PCIO, 0x3d5, 0);
+		VGA_WR08(chip->PCIO, 0x3d4, 0x54);
+		VGA_WR08(chip->PCIO, 0x3d5, 0);
+		VGA_WR08(chip->PCIO, 0x3d4, 0x21);
+		VGA_WR08(chip->PCIO, 0x3d5, 0xfa);
+	    }
             break;
     }
     LOAD_FIXED_STATE(Riva,FIFO);
@@ -1547,6 +1566,16 @@
     VGA_WR08(chip->PCIO, 0x03D5, state->cursor0);
     VGA_WR08(chip->PCIO, 0x03D4, 0x31);
     VGA_WR08(chip->PCIO, 0x03D5, state->cursor1);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x41);
+    VGA_WR08(chip->PCIO, 0x03D5, state->extra);
+
+    if (!chip->flatPanel) {
+        chip->PRAMDAC[0x00000508/4]  = state->vpll;
+        chip->PRAMDAC[0x00000520/4]  = state->vpll2;
+        chip->PRAMDAC[0x0000050C/4]  = state->pllsel;
+    } else {
+	chip->PRAMDAC[0x00000848/4]  = state->scale;
+    }
     chip->PRAMDAC[0x00000300/4]  = state->cursor2;
     chip->PRAMDAC[0x00000508/4]  = state->vpll;
     chip->PRAMDAC[0x0000050C/4]  = state->pllsel;
@@ -1598,10 +1627,14 @@
     state->cursor0      = VGA_RD08(chip->PCIO, 0x03D5);
     VGA_WR08(chip->PCIO, 0x03D4, 0x31);
     state->cursor1      = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x41);
+    state->extra        = VGA_RD08(chip->PCIO, 0x03D5);
     state->cursor2      = chip->PRAMDAC[0x00000300/4];
     state->vpll         = chip->PRAMDAC[0x00000508/4];
+    state->vpll2        = chip->PRAMDAC[0x00000520/4];
     state->pllsel       = chip->PRAMDAC[0x0000050C/4];
     state->general      = chip->PRAMDAC[0x00000600/4];
+    state->scale	= chip->PRAMDAC[0x00000848/4];
     state->config       = chip->PFB[0x00000200/4];
     switch (chip->Architecture)
     {
@@ -1910,6 +1943,9 @@
     RIVA_HW_INST *chip
 )
 {
+#if defined(__BIG_ENDIAN)
+    chip->PMC[0x00000004/4] = 0x01000001;
+#endif
     /*
      * Fill in chip configuration.
      */
diff -Nru a/drivers/video/riva/riva_hw.h b/drivers/video/riva/riva_hw.h
--- a/drivers/video/riva/riva_hw.h	Wed Feb 26 13:32:43 2003
+++ b/drivers/video/riva/riva_hw.h	Wed Feb 26 13:32:43 2003
@@ -59,8 +59,14 @@
 /*
  * HW access macros.
  */
+#if defined(__powerpc__)
+#include <asm/io.h>
+#define NV_WR08(p,i,d)	out_8(p+i, d)
+#define NV_RD08(p,i)	in_8(p+i)
+#else
 #define NV_WR08(p,i,d)  (((U008 *)(p))[i]=(d))
 #define NV_RD08(p,i)    (((U008 *)(p))[i])
+#endif
 #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))
@@ -88,8 +94,12 @@
 typedef volatile struct
 {
     U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
     U016 FifoFree;
     U016 Nop;
+#endif 
     U032 reserved01[0x0BB];
     U032 Rop3;
 } RivaRop;
@@ -99,8 +109,12 @@
 typedef volatile struct
 {
     U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
     U016 FifoFree;
     U016 Nop;
+#endif
     U032 reserved01[0x0BD];
     U032 Shape;
     U032 reserved03[0x001];
@@ -114,8 +128,12 @@
 typedef volatile struct
 {
     U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
     U016 FifoFree;
     U016 Nop;
+#endif
     U032 reserved01[0x0BB];
     U032 TopLeft;
     U032 WidthHeight;
@@ -126,8 +144,12 @@
 typedef volatile struct
 {
     U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
     U016 FifoFree;
     U016 Nop[1];
+#endif
     U032 reserved01[0x0BC];
     U032 Color;
     U032 reserved03[0x03E];
@@ -140,8 +162,12 @@
 typedef volatile struct
 {
     U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
     U016 FifoFree;
     U016 Nop;
+#endif
     U032 reserved01[0x0BB];
     U032 TopLeftSrc;
     U032 TopLeftDst;
@@ -153,8 +179,12 @@
 typedef volatile struct
 {
     U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
     U016 FifoFree;
     U016 Nop[1];
+#endif
     U032 reserved01[0x0BC];
     U032 TopLeft;
     U032 WidthHeight;
@@ -168,8 +198,12 @@
 typedef volatile struct
 {
     U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
     U016 FifoFree;
     U016 Nop;
+#endif
     U032 reserved01[0x0BB];
     U032 reserved03[(0x040)-1];
     U032 Color1A;
@@ -230,8 +264,12 @@
 typedef volatile struct
 {
     U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
     U016 FifoFree;
     U016 Nop;
+#endif    
     U032 reserved01[0x0BC];
     U032 TextureOffset;
     U032 TextureFormat;
@@ -256,8 +294,12 @@
 typedef volatile struct
 {
     U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
     U016 FifoFree;
     U016 Nop;
+#endif    
     U032 reserved01[0x0BB];
     U032 ColorKey;
     U032 TextureOffset;
@@ -290,8 +332,12 @@
 typedef volatile struct
 {
     U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
     U016 FifoFree;
     U016 Nop[1];
+#endif    
     U032 reserved01[0x0BC];
     U032 Color;             /* source color               0304-0307*/
     U032 Reserved02[0x03e];
@@ -321,16 +367,24 @@
 typedef volatile struct
 {
     U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
     U016 FifoFree;
     U016 Nop;
+#endif
     U032 reserved01[0x0BE];
     U032 Offset;
 } RivaSurface;
 typedef volatile struct
 {
     U032 reserved00[4];
+#ifdef __BIG_ENDIAN
+    U032 FifoFree;
+#else
     U016 FifoFree;
     U016 Nop;
+#endif
     U032 reserved01[0x0BD];
     U032 Pitch;
     U032 RenderBufferOffset;
@@ -364,6 +418,7 @@
     U032 VBlankBit;
     U032 FifoFreeCount;
     U032 FifoEmptyCount;
+    U032 flatPanel;
     /*
      * Non-FIFO registers.
      */
@@ -424,11 +479,14 @@
     U032 repaint0;
     U032 repaint1;
     U032 screen;
+    U032 scale;
+    U032 extra;
     U032 pixel;
     U032 horiz;
     U032 arbitration0;
     U032 arbitration1;
     U032 vpll;
+    U032 vpll2;
     U032 pllsel;
     U032 general;
     U032 config;
diff -Nru a/drivers/video/riva/riva_tbl.h b/drivers/video/riva/riva_tbl.h
--- a/drivers/video/riva/riva_tbl.h	Wed Feb 26 13:32:43 2003
+++ b/drivers/video/riva/riva_tbl.h	Wed Feb 26 13:32:43 2003
@@ -830,29 +830,45 @@
     {0x00000501, 0x01FFFFFF},
     {0x00000502, 0x00000002},
     {0x00000503, 0x00000002},
+#ifdef __BIG_ENDIAN
+    {0x00000508, 0x01088043},
+#else
     {0x00000508, 0x01008043},
+#endif
     {0x0000050A, 0x00000000},
     {0x0000050B, 0x00000000},
+#ifdef __BIG_ENDIAN
+    {0x0000050C, 0x01088019},
+#else
     {0x0000050C, 0x01008019},
+#endif
     {0x0000050E, 0x00000000},
     {0x0000050F, 0x00000000},
-#if 1
-    {0x00000510, 0x01008018},
+#ifdef __BIG_ENDIAN
+    {0x00000510, 0x01088018},
 #else
-    {0x00000510, 0x01008044},
+    {0x00000510, 0x01008018},
 #endif
     {0x00000512, 0x00000000},
     {0x00000513, 0x00000000},
+#ifdef __BIG_ENDIAN
+    {0x00000514, 0x01088021},
+#else
     {0x00000514, 0x01008021},
+#endif
     {0x00000516, 0x00000000},
     {0x00000517, 0x00000000},
+#ifdef __BIG_ENDIAN
+    {0x00000518, 0x0108805F},
+#else
     {0x00000518, 0x0100805F},
+#endif
     {0x0000051A, 0x00000000},
     {0x0000051B, 0x00000000},
-#if 1
-    {0x0000051C, 0x0100804B},
+#ifdef __BIG_ENDIAN
+    {0x0000051C, 0x0108804B},
 #else
-    {0x0000051C, 0x0100804A},
+    {0x0000051C, 0x0100804B},
 #endif
     {0x0000051E, 0x00000000},
     {0x0000051F, 0x00000000},
@@ -868,10 +884,18 @@
     {0x00000529, 0x00000D01},
     {0x0000052A, 0x11401140},
     {0x0000052B, 0x00000000},
+#ifdef __BIG_ENDIAN
+    {0x0000052C, 0x00080058},
+#else
     {0x0000052C, 0x00000058},
+#endif
     {0x0000052E, 0x11401140},
     {0x0000052F, 0x00000000},
+#ifdef __BIG_ENDIAN
+    {0x00000530, 0x00080059},
+#else
     {0x00000530, 0x00000059},
+#endif
     {0x00000532, 0x11401140},
     {0x00000533, 0x00000000},
     {0x00000534, 0x0000005A},
@@ -882,7 +906,14 @@
     {0x0000053B, 0x00000000},
     {0x0000053C, 0x00000093},
     {0x0000053E, 0x11401140},
-    {0x0000053F, 0x00000000} 
+    {0x0000053F, 0x00000000},
+#ifdef __BIG_ENDIAN
+    {0x00000540, 0x0308A01C},
+#else
+    {0x00000540, 0x0300A01C},
+#endif
+    {0x00000542, 0x11401140},
+    {0x00000543, 0x00000000}
 };
 static unsigned nv10TablePRAMIN_8BPP[][2] =
 {
@@ -898,7 +929,8 @@
     {0x0000052E, 0x00000302},
     {0x00000535, 0x00000000},
     {0x00000539, 0x00000000},
-    {0x0000053D, 0x00000000} 
+    {0x0000053D, 0x00000000},
+    {0x00000541, 0x00000302}
 };
 static unsigned nv10TablePRAMIN_15BPP[][2] =
 {
@@ -914,7 +946,8 @@
     {0x0000052E, 0x00000902},
     {0x00000535, 0x00000902},
     {0x00000539, 0x00000902}, 
-    {0x0000053D, 0x00000902} 
+    {0x0000053D, 0x00000902}, 
+    {0x00000541, 0x00000902}
 };
 static unsigned nv10TablePRAMIN_16BPP[][2] =
 {
@@ -930,7 +963,8 @@
     {0x0000052E, 0x00000C02},
     {0x00000535, 0x00000C02},
     {0x00000539, 0x00000C02},
-    {0x0000053D, 0x00000C02} 
+    {0x0000053D, 0x00000C02},
+    {0x00000541, 0x00000C02}
 };
 static unsigned nv10TablePRAMIN_32BPP[][2] =
 {
@@ -946,6 +980,7 @@
     {0x0000052E, 0x00000E02},
     {0x00000535, 0x00000E02},
     {0x00000539, 0x00000E02},
-    {0x0000053D, 0x00000E02} 
+    {0x0000053D, 0x00000E02},
+    {0x00000541, 0x00000E02}
 };
 
diff -Nru a/drivers/video/riva/rivafb.h b/drivers/video/riva/rivafb.h
--- a/drivers/video/riva/rivafb.h	Wed Feb 26 13:32:43 2003
+++ b/drivers/video/riva/rivafb.h	Wed Feb 26 13:32:43 2003
@@ -51,6 +51,8 @@
 	struct riva_regs initial_state;	/* initial startup video mode */
 	struct riva_regs current_state;
 
+	unsigned char *EDID;
+
 	struct display disp;
 	int currcon;
 	struct display *currcon_display;
@@ -66,6 +68,16 @@
 	struct display_switch dispsw;
 
 	riva_cfb8_cmap_t palette[256];	/* VGA DAC palette cache */
+
+	int panel_xres, panel_yres;
+	int clock;
+	int hOver_plus, hSync_width, hblank;
+	int vOver_plus, vSync_width, vblank;
+	int hAct_high, vAct_high, interlaced;
+	int synct, misc;
+
+	int use_default_var;
+	int got_dfpinfo;
 
 #if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
 	union {
-
To unsubscribe from this list: send the line "unsubscribe bk-commits-24" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic