[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, ®_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