Re: Patch for Linux on 64 Bit system.

Bernhard Praschinger <[email protected]> Mon, 07 Jun 2010 19:10:41 +0200
Newsgroups gmane.comp.video.mjpeg.devel
Message-ID <[email protected]>
Hallo

Sorry for the delay.

>> Mauro is maintaining the kernel driver as part of the video4linux
>> project nowadays, so he can probably take care of that. Is that OK,
>> Mauro?
>
> Sure.
>
> Bernhard,
>
> Please submit the modified patch to [email protected].

I have changed the patch so most parts of it can be applied without 
problems to the 2.6.34 Kernel. As you might have guessed I have problems 
with some parts. of the patch where it seems to me that some of the 
changes made it already to the kernel. And some the few remaining 
changes are quite difficult. So can you please take a look at the 
changed patch.

auf hoffentlich bald,

Berni the Chaos of Woodquarter

Email: [email protected]
www: http://www.lysator.liu.se/~gz/bernhard

------------------------------------------------------------------------------
ThinkGeek and WIRED's GeekDad team up for the Ultimate 
GeekDad Father's Day Giveaway. ONE MASSIVE PRIZE to the 
lucky parental unit.  See the prize list and enter to win: 
http://p.sf.net/sfu/thinkgeek-promo

_______________________________________________
Mjpeg-developer mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mjpeg-developer
zoran_dma_patch_2.6.34.diff (text/x-patch, 20.7 KB)
diff -Naur linux-2.6.34/drivers/media/video/zoran_card.c linux-2.6.34_orinal/drivers/media/video/zoran/zoran_card.c
--- linux-2.6.34/drivers/media/video/zoran/zoran_card.c	2008-05-17 15:41:39.000000000 +0200
+++ linux-2.6.34_original/drivers/media/video/zoran/zoran_card.c	2008-05-17 13:09:14.000000000 +0200
@@ -1087,6 +1087,14 @@
 		"%s: zr36057_init() - initializing card[%d], zr=%p\n",
 		ZR_DEVNAME(zr), zr->id, zr);
 
+	if (pci_set_dma_mask(zr->pci_dev, DMA_32BIT_MASK)) {
+		dprintk(1,
+			KERN_ERR
+			"%s: zr36057_init() - failed to set DMA mask to 32 bits.\n",
+			ZR_DEVNAME(zr));
+		return -EIO;
+	}
+
 	/* default setup of all parameters which will persist between opens */
 	zr->user = 0;
 
@@ -1136,7 +1144,8 @@
 
 	/* allocate memory *before* doing anything to the hardware
 	 * in case allocation fails */
-	zr->stat_com = kzalloc(BUZ_NUM_STAT_COM * 4, GFP_KERNEL);
+	zr->stat_com = pci_alloc_consistent(zr->pci_dev, 
+		BUZ_NUM_STAT_COM * 4, &zr->stat_com_bus);
 	zr->video_dev = kmalloc(sizeof(struct video_device), GFP_KERNEL);
 	if (!zr->stat_com || !zr->video_dev) {
 		dprintk(1,
@@ -1175,7 +1184,8 @@
 exit_unregister:
 	zoran_unregister_i2c(zr);
 exit_free:
-	kfree(zr->stat_com);
+	pci_free_consistent(zr->pci_dev, BUZ_NUM_STAT_COM * 4, zr->stat_com,
+		zr->stat_com_bus);
 	kfree(zr->video_dev);
 	return err;
 }
@@ -1207,7 +1217,8 @@
 	btwrite(0, ZR36057_SPGPPCR);
 	free_irq(zr->pci_dev->irq, zr);
 	/* unmap and free memory */
-	kfree(zr->stat_com);
+	pci_free_consistent(zr->pci_dev, BUZ_NUM_STAT_COM * 4, zr->stat_com,
+		zr->stat_com_bus);
 	zoran_proc_cleanup(zr);
 	iounmap(zr->zr36057_mem);
 	pci_disable_device(zr->pci_dev);
diff -Naur linux-2.6.34/drivers/media/video/zoran/zoran_device.c linux-2.6.34_original/drivers/media/video/zoran/zoran_device.c
--- linux-2.6.34/drivers/media/video/zoran/zoran_device.c	2008-01-24 23:58:37.000000000 +0100
+++ linux-2.6.34_original/drivers/media/video/zoran/zoran_device.c	2008-05-17 13:09:14.000000000 +0200
@@ -458,9 +458,9 @@
 		 * zr->overlay_settings.width instead of video_width */
 
 		mask_line_size = (BUZ_MAX_WIDTH + 31) / 32;
-		reg = virt_to_bus(zr->overlay_mask);
+		reg = cpu_to_le32(zr->overlay_mask_bus);
 		btwrite(reg, ZR36057_MMTR);
-		reg = virt_to_bus(zr->overlay_mask + mask_line_size);
+		reg = cpu_to_le32(zr->overlay_mask_bus + mask_line_size);
 		btwrite(reg, ZR36057_MMBR);
 		reg =
 		    mask_line_size - (zr->overlay_settings.width +
@@ -468,7 +468,7 @@
 		if (DispMode == 0)
 			reg += mask_line_size;
 		reg <<= ZR36057_OCR_MaskStride;
-		btwrite(reg, ZR36057_OCR);
+		btwrite(cpu_to_le32(reg), ZR36057_OCR);
 	}
 
 	zr36057_adjust_vfe(zr, zr->codec_mode);
@@ -809,7 +809,7 @@
 	//btor(ZR36057_VFESPFR_VCLKPol, ZR36057_VFESPFR);
 
 	/* code base address */
-	reg = virt_to_bus(zr->stat_com);
+	reg = zr->stat_com_bus;
 	btwrite(reg, ZR36057_JCBA);
 
 	/* FIFO threshold (FIFO is 160. double words) */
@@ -1150,12 +1150,28 @@
 			zr->stat_com[i + 1] =
 			    cpu_to_le32(zr->jpg_buffers.buffer[frame].frag_tab_bus);
 		}
+		if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) {
+			if (zr->jpg_buffers.need_contiguous) {
+				pci_dma_sync_single_for_device(
+				    zr->pci_dev,
+				    le32_to_cpu(zr->jpg_buffers.buffer[frame].frag_tab[0]),
+				    zr->jpg_buffers.buffer_size,
+				    DMA_BIDIRECTIONAL);
+			} else {
+				pci_dma_sync_sg_for_device(zr->pci_dev,
+				    zr->jpg_buffers.buffer[frame].frag_tab_sg,
+				    zr->jpg_buffers.buffer_size / PAGE_SIZE,
+				    DMA_BIDIRECTIONAL);
+			}
+		}
 		zr->jpg_buffers.buffer[frame].state = BUZ_STATE_DMA;
 		zr->jpg_dma_head++;
 
 	}
-	if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS)
+
+	if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS) {
 		zr->jpg_queued_num++;
+	}
 }
 
 /* when this is called the spinlock must be held */
@@ -1195,6 +1211,19 @@
 		do_gettimeofday(&buffer->bs.timestamp);
 
 		if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
+			if (zr->jpg_buffers.need_contiguous) {
+				pci_dma_sync_single_for_cpu(
+				    zr->pci_dev,
+				    le32_to_cpu(zr->jpg_buffers.buffer[frame].frag_tab[0]),
+				    zr->jpg_buffers.buffer_size,
+				    DMA_BIDIRECTIONAL);
+			} else {
+				pci_dma_sync_sg_for_cpu(zr->pci_dev,
+				    zr->jpg_buffers.buffer[frame].frag_tab_sg,
+				    zr->jpg_buffers.buffer_size / PAGE_SIZE,
+				    DMA_BIDIRECTIONAL);
+			}
+			
 			buffer->bs.length = (stat_com & 0x7fffff) >> 1;
 
 			/* update sequence number with the help of the counter in stat_com */
diff -Naur linux-2.6.34/drivers/media/video/zoran/zoran_driver.c linux-2.6.34_original/drivers/media/video/zoran/zoran_driver.c
--- linux-2.6.34/drivers/media/video/zoran/zoran_driver.c	2008-01-24 23:58:37.000000000 +0100
+++ linux-2.6.34_original/drivers/media/video/zoran/zoran_driver.c	2008-05-17 13:20:40.000000000 +0200
@@ -49,6 +49,7 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/scatterlist.h>
 #include <linux/smp_lock.h>
 #include <linux/pci.h>
 #include <linux/vmalloc.h>
@@ -350,6 +352,5 @@
 		fh->buffers.buffer[i].v4l.fbuffer = mem;
 		fh->buffers.buffer[i].v4l.fbuffer_phys = virt_to_phys(mem);
-		fh->buffers.buffer[i].v4l.fbuffer_bus = virt_to_bus(mem);
		for (off = 0; off < fh->buffers.buffer_size;
 		     off += PAGE_SIZE)
 			SetPageReserved(MAP_NR(mem + off));
@@ -359,7 +359,7 @@
 			KERN_INFO
 			"%s: %s - V4L frame %d mem 0x%lx (bus: 0x%llx)\n",
 			ZR_DEVNAME(zr), __func__, i, (unsigned long) mem,
-			(unsigned long long)virt_to_bus(mem));
+			(unsigned long)fh->buffers.buffer[i].v4l.fbuffer_bus);
	}
 
 	fh->buffers.allocated = 1;
@@ -423,15 +423,19 @@
 		if (!fh->v4l_buffers.buffer[i].fbuffer)
 			continue;
 
-		if (fh->v4l_buffers.buffer_size <= MAX_KMALLOC_MEM) {
-			mem = fh->v4l_buffers.buffer[i].fbuffer;
+  		if (fh->v4l_buffers.buffer_size <= MAX_KMALLOC_MEM) {
+			mem = (unsigned char*)fh->v4l_buffers.buffer[i].fbuffer_phys;
 			for (off = 0; off < fh->v4l_buffers.buffer_size;
-			     off += PAGE_SIZE)
+			    off += PAGE_SIZE)
 				ClearPageReserved(MAP_NR(mem + off));
-			kfree((void *) fh->v4l_buffers.buffer[i].fbuffer);
+			
+			pci_free_consistent(zr->pci_dev,
+			    fh->v4l_buffers.buffer_size, mem,
+			    fh->v4l_buffers.buffer[i].fbuffer_bus);
 		}
 		fh->v4l_buffers.buffer[i].fbuffer = NULL;
-	}
+		fh->v4l_buffers.buffer[i].fbuffer_bus = 0;
+  	}
 
 	fh->v4l_buffers.allocated = 0;
 	fh->v4l_buffers.ready_to_be_freed = 0;
@@ -476,8 +480,9 @@
 {
 	struct zoran_fh *fh = file->private_data;
 	struct zoran *zr = fh->zr;
-	int i, j, off;
-	unsigned long mem;
+	int i, j, off, sgcount = fh->jpg_buffers.buffer_size / PAGE_SIZE;
+	unsigned char *mem;
+	struct zoran_jpg_buffer *jpg_buffer;
 
 	/* we might have old buffers lying around */
 	if (fh->jpg_buffers.ready_to_be_freed) {
@@ -485,33 +490,38 @@
 	}
 
 	for (i = 0; i < fh->jpg_buffers.num_buffers; i++) {
-		if (fh->jpg_buffers.buffer[i].frag_tab)
+		jpg_buffer = fh->jpg_buffers.buffer + i;
+		if (jpg_buffer->frag_tab)
 			dprintk(2,
 				KERN_WARNING
 				"%s: jpg_fbuffer_alloc() - buffer %d allready allocated!?\n",
 				ZR_DEVNAME(zr), i);
 
 		/* Allocate fragment table for this buffer */
+		mem = pci_alloc_consistent(zr->pci_dev, 8 * sgcount,
+			&jpg_buffer->frag_tab_bus);
+		jpg_buffer->frag_tab_sg =
+			kzalloc((sizeof(struct scatterlist) + sizeof(void*))
+				* sgcount, GFP_KERNEL);
 
-		mem = get_zeroed_page(GFP_KERNEL);
-		if (mem == 0) {
+		if (mem == 0 || jpg_buffer->frag_tab_sg == 0) {
 			dprintk(1,
 				KERN_ERR
-				"%s: jpg_fbuffer_alloc() - get_zeroed_page (frag_tab) failed for buffer %d\n",
+				"%s: jpg_fbuffer_alloc() - kmalloc (frag_tab) failed for buffer %d\n",
 				ZR_DEVNAME(zr), i);
 			jpg_fbuffer_free(file);
 			return -ENOBUFS;
 		}
-		fh->jpg_buffers.buffer[i].frag_tab = (u32 *) mem;
-		fh->jpg_buffers.buffer[i].frag_tab_bus =
-		    virt_to_bus((void *) mem);
+		memset(mem, 0, 8 * sgcount);
+		jpg_buffer->frag_tab = (u32*)mem;
+		mem = (unsigned char*)jpg_buffer->frag_tab_sg;
+		jpg_buffer->frag_tab_allocs = (void**)(mem 
+		    + sgcount * sizeof(struct scatterlist));
 
-		//if (alloc_contig) {
 		if (fh->jpg_buffers.need_contiguous) {
-			mem =
-			    (unsigned long) kmalloc(fh->jpg_buffers.
-						    buffer_size,
-						    GFP_KERNEL);
+			dma_addr_t dma_mem;
+			mem = kmalloc(fh->jpg_buffers.buffer_size, GFP_KERNEL);
+			
 			if (mem == 0) {
 				dprintk(1,
 					KERN_ERR
@@ -520,19 +530,32 @@
 				jpg_fbuffer_free(file);
 				return -ENOBUFS;
 			}
-			fh->jpg_buffers.buffer[i].frag_tab[0] =
-			    cpu_to_le32(virt_to_bus((void *) mem));
-			fh->jpg_buffers.buffer[i].frag_tab[1] =
-			    cpu_to_le32(((fh->jpg_buffers.buffer_size / 4) << 1) | 1);
+			jpg_buffer->frag_tab_allocs[0] = mem;
 			for (off = 0; off < fh->jpg_buffers.buffer_size;
 			     off += PAGE_SIZE)
 				SetPageReserved(MAP_NR(mem + off));
+			
+			dma_mem = pci_map_single(zr->pci_dev, mem,
+			    fh->jpg_buffers.buffer_size,
+			    DMA_BIDIRECTIONAL);
+			if (dma_mem == 0) {
+				dprintk(1,
+					KERN_ERR
+					"%s: Mapping PCI DMA for jpeg buffer %d failed.\n",
+					ZR_DEVNAME(zr), i);
+				jpg_fbuffer_free(file);
+				return -ENOBUFS;
+			}
+			jpg_buffer->frag_tab[0] = cpu_to_le32(dma_mem);
+			jpg_buffer->frag_tab[1] = cpu_to_le32(((
+			    fh->jpg_buffers.buffer_size / 4) << 1) | 1);
 		} else {
 			/* jpg_bufsize is allreay page aligned */
-			for (j = 0;
-			     j < fh->jpg_buffers.buffer_size / PAGE_SIZE;
-			     j++) {
-				mem = get_zeroed_page(GFP_KERNEL);
+			int real_fragments;
+
+			for (j = 0; j < sgcount; j++) {
+				mem = (unsigned char*)get_zeroed_page(
+				    GFP_KERNEL);
 				if (mem == 0) {
 					dprintk(1,
 						KERN_ERR
@@ -541,16 +564,35 @@
 					jpg_fbuffer_free(file);
 					return -ENOBUFS;
 				}
-
-				fh->jpg_buffers.buffer[i].frag_tab[2 * j] =
-				    cpu_to_le32(virt_to_bus((void *) mem));
-				fh->jpg_buffers.buffer[i].frag_tab[2 * j +
-								   1] =
-				    cpu_to_le32((PAGE_SIZE / 4) << 1);
+				jpg_buffer->frag_tab_allocs[j] = mem;
+				sg_set_buf(jpg_buffer->frag_tab_sg + j, 
+					   mem, PAGE_SIZE);
 				SetPageReserved(MAP_NR(mem));
 			}
 
-			fh->jpg_buffers.buffer[i].frag_tab[2 * j - 1] |= cpu_to_le32(1);
+			real_fragments = pci_map_sg(zr->pci_dev,
+						    jpg_buffer->frag_tab_sg,
+						    sgcount,
+						    DMA_BIDIRECTIONAL);
+			if (real_fragments == 0) {
+				dprintk(1,
+					KERN_ERR
+					"%s: Mapping PCI DMA scatterlist for jpeg buffer %d failed.\n",
+					ZR_DEVNAME(zr), i);
+				jpg_fbuffer_free(file);
+				return -ENOBUFS;
+			}
+			jpg_buffer->scatterlist_entries = real_fragments;
+			for (j = 0; j < real_fragments; j++) {
+				jpg_buffer->frag_tab[2 * j] =
+				    cpu_to_le32(sg_dma_address(
+						jpg_buffer->frag_tab_sg + j));
+				jpg_buffer->frag_tab[2 * j + 1] =
+				    cpu_to_le32((sg_dma_len(
+					jpg_buffer->frag_tab_sg + j)
+					/ 4) << 1);
+			}
+			jpg_buffer->frag_tab[2 * j - 1] |= cpu_to_le32(1);
 		}
 	}
 
@@ -571,58 +613,75 @@
 {
 	struct zoran_fh *fh = file->private_data;
 	struct zoran *zr = fh->zr;
-	int i, j, off;
+	int i, j, off, sgcount = fh->jpg_buffers.buffer_size / PAGE_SIZE;
 	unsigned char *mem;
+	struct zoran_jpg_buffer *jpg_buffer;
 
 	dprintk(4, KERN_DEBUG "%s: jpg_fbuffer_free()\n", ZR_DEVNAME(zr));
 
 	for (i = 0; i < fh->jpg_buffers.num_buffers; i++) {
-		if (!fh->jpg_buffers.buffer[i].frag_tab)
+		jpg_buffer = fh->jpg_buffers.buffer + i;
+		if (! jpg_buffer->frag_tab) {
+			if (jpg_buffer->frag_tab_sg) {
+				kfree(jpg_buffer->frag_tab_sg);
+			}
 			continue;
+		}
 
-		//if (alloc_contig) {
+		if (! jpg_buffer->frag_tab_sg) {
+			pci_free_consistent(zr->pci_dev, 8 * sgcount,
+			    jpg_buffer->frag_tab, jpg_buffer->frag_tab_bus);
+			continue;
+		}
+		
 		if (fh->jpg_buffers.need_contiguous) {
-			if (fh->jpg_buffers.buffer[i].frag_tab[0]) {
-				mem = (unsigned char *) bus_to_virt(le32_to_cpu(
-					fh->jpg_buffers.buffer[i].frag_tab[0]));
+			mem = jpg_buffer->frag_tab_allocs[0];
+			if (jpg_buffer->frag_tab[0]) {
+				pci_unmap_single(zr->pci_dev,
+				    le32_to_cpu(jpg_buffer->frag_tab[0]),
+				    fh->jpg_buffers.buffer_size,
+				    DMA_BIDIRECTIONAL);
+				jpg_buffer->frag_tab[0] = 0;
+				jpg_buffer->frag_tab[1] = 0;
+			}
+			if (mem) {
 				for (off = 0;
 				     off < fh->jpg_buffers.buffer_size;
 				     off += PAGE_SIZE)
 					ClearPageReserved(MAP_NR
 							  (mem + off));
 				kfree(mem);
-				fh->jpg_buffers.buffer[i].frag_tab[0] = 0;
-				fh->jpg_buffers.buffer[i].frag_tab[1] = 0;
 			}
 		} else {
-			for (j = 0;
-			     j < fh->jpg_buffers.buffer_size / PAGE_SIZE;
-			     j++) {
-				if (!fh->jpg_buffers.buffer[i].
-				    frag_tab[2 * j])
+			if (fh->jpg_buffers.buffer[i].scatterlist_entries) {
+				pci_unmap_sg(zr->pci_dev,
+				    jpg_buffer->frag_tab_sg, sgcount,
+				    DMA_BIDIRECTIONAL);
+			}
+			for (j = 0; j < sgcount; j++) {
+				if (! jpg_buffer->frag_tab_allocs[j])
 					break;
-				ClearPageReserved(MAP_NR
-						  (bus_to_virt
-						   (le32_to_cpu
-						    (fh->jpg_buffers.
-						     buffer[i].frag_tab[2 *
-								       j]))));
+
+				ClearPageReserved(MAP_NR(
+				    jpg_buffer->frag_tab_allocs[j]));
 				free_page((unsigned long)
-					  bus_to_virt
-						  (le32_to_cpu
-						   (fh->jpg_buffers.
-						      buffer[i].
-						      frag_tab[2 * j])));
-				fh->jpg_buffers.buffer[i].frag_tab[2 * j] =
-				    0;
-				fh->jpg_buffers.buffer[i].frag_tab[2 * j +
-								   1] = 0;
+					  jpg_buffer->frag_tab_allocs[j]);
+				jpg_buffer->frag_tab_allocs[j] = NULL;
+				jpg_buffer->frag_tab[2 * j] = 0;
+				jpg_buffer->frag_tab[2 * j + 1] = 0;
 			}
 		}
 
-		free_page((unsigned long) fh->jpg_buffers.buffer[i].
-			  frag_tab);
-		fh->jpg_buffers.buffer[i].frag_tab = NULL;
+		pci_free_consistent(zr->pci_dev, 8 * sgcount,
+				    jpg_buffer->frag_tab,
+				    jpg_buffer->frag_tab_bus);
+		jpg_buffer->frag_tab = NULL;
+		jpg_buffer->frag_tab_bus = 0;
+		
+		if (jpg_buffer->frag_tab_sg != NULL) {
+			kfree(jpg_buffer->frag_tab_sg);
+			jpg_buffer->frag_tab_sg = NULL;
+		}
 	}
 
 	fh->jpg_buffers.allocated = 0;
@@ -1170,6 +1229,7 @@
 		if (!zr->v4l_memgrab_active)
 			zr36057_overlay(zr, 0);
 		zr->overlay_mask = NULL;
+		zr->overlay_mask_bus = 0;
 	}
 
 	/* v4l capture */
@@ -1299,7 +1359,9 @@
 	/* used to be BUZ_MAX_WIDTH/HEIGHT, but that gives overflows
 	 * on norm-change! */
 	fh->overlay_mask =
-	    kmalloc(((768 + 31) / 32) * 576 * 4, GFP_KERNEL);
+//	    kmalloc(((768 + 31) / 32) * 576 * 4, GFP_KERNEL);
+	    pci_alloc_consistent(zr->pci_dev, ((768 + 31) / 32) * 576 * 4,
+				 &fh->overlay_mask_bus);
 	if (!fh->overlay_mask) {
 		dprintk(1,
 			KERN_ERR
@@ -1382,6 +1444,7 @@
 		zr->v4l_overlay_active = 0;
 		zr36057_overlay(zr, 0);
 		zr->overlay_mask = NULL;
+		zr->overlay_mask_bus = 0;
 
 		/* capture off */
 		wake_up_interruptible(&zr->v4l_capq);
@@ -1398,7 +1461,8 @@
 	}
 
 	file->private_data = NULL;
-	kfree(fh->overlay_mask);
+	pci_free_consistent(zr->pci_dev, ((768 + 31) / 32) * 576 * 4,
+			    fh->overlay_mask, fh->overlay_mask_bus);
 	kfree(fh);
 
 	/* release locks on the i2c modules */
@@ -1680,6 +1744,7 @@
 		if (!zr->v4l_memgrab_active)
 			zr36057_overlay(zr, 0);
 		zr->overlay_mask = NULL;
+		zr->overlay_mask_bus = 0;
 	} else {
 		if (!zr->buffer.base || !fh->overlay_settings.is_set) {
 			dprintk(1,
@@ -1698,6 +1763,7 @@
 		zr->overlay_active = fh->overlay_active = ZORAN_LOCKED;
 		zr->v4l_overlay_active = 1;
 		zr->overlay_mask = fh->overlay_mask;
+		zr->overlay_mask_bus = fh->overlay_mask_bus;
 		zr->overlay_settings = fh->overlay_settings;
 		if (!zr->v4l_memgrab_active)
 			zr36057_overlay(zr, 1);
@@ -4430,7 +4496,7 @@
 	unsigned long size = (vma->vm_end - vma->vm_start);
 	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
 	int i, j;
-	unsigned long page, start = vma->vm_start, todo, pos, fraglen;
+	unsigned long page, start = vma->vm_start, todo, fraglen;
 	int first, last;
 	struct zoran_mapping *map;
 	int res = 0;
@@ -4508,41 +4574,32 @@
 		vma->vm_private_data = map;
 
 		for (i = first; i <= last; i++) {
-			for (j = 0;
-			     j < fh->jpg_buffers.buffer_size / PAGE_SIZE;
-			     j++) {
-				fraglen =
-				    (le32_to_cpu(fh->jpg_buffers.buffer[i].
-				     frag_tab[2 * j + 1]) & ~1) << 1;
-				todo = size;
-				if (todo > fraglen)
-					todo = fraglen;
-				pos =
-				    le32_to_cpu((unsigned long) fh->jpg_buffers.
-				    buffer[i].frag_tab[2 * j]);
-				/* should just be pos on i386 */
-				page = virt_to_phys(bus_to_virt(pos))
-								>> PAGE_SHIFT;
-				if (remap_pfn_range(vma, start, page,
-							todo, PAGE_SHARED)) {
-					dprintk(1,
-						KERN_ERR
-						"%s: zoran_mmap(V4L) - remap_pfn_range failed\n",
-						ZR_DEVNAME(zr));
-					res = -EAGAIN;
-					goto jpg_mmap_unlock_and_return;
-				}
-				size -= todo;
-				start += todo;
-				if (size == 0)
-					break;
-				if (le32_to_cpu(fh->jpg_buffers.buffer[i].
-				    frag_tab[2 * j + 1]) & 1)
-					break;	/* was last fragment */
-			}
-			fh->jpg_buffers.buffer[i].map = map;
-			if (size == 0)
-				break;
+                        for (j = 0;
+                             j < fh->jpg_buffers.buffer_size / PAGE_SIZE;
+                             j++) {
+                                fraglen = PAGE_SIZE;
+                                todo = size;
+                                if (todo > fraglen)
+                                        todo = fraglen;
+                                page = virt_to_phys(fh->jpg_buffers.buffer[i].
+					frag_tab_allocs[j]) >> PAGE_SHIFT;
+                                if (remap_pfn_range(vma, start, page,
+                                                        todo, PAGE_SHARED)) {
+                                        dprintk(1,
+                                                KERN_ERR
+                                                "%s: zoran_mmap(V4L) - remap_pfn_range failed\n",
+                                                ZR_DEVNAME(zr));
+                                        res = -EAGAIN;
+                                        goto jpg_mmap_unlock_and_return;
+                                }
+                                size -= todo;
+                                start += todo;
+                                if (size == 0)
+                                        break;
+                        }
+                        fh->jpg_buffers.buffer[i].map = map;
+                        if (size == 0)
+                                break;
 
 		}
 	jpg_mmap_unlock_and_return:
diff -Naur linux-2.6.34/drivers/media/video/zoran/zoran.h linux-2.6.34_original/drivers/media/video/zoran/zoran.h
--- linux-2.6.34/drivers/media/video/zoran/zoran.h	2008-01-24 23:58:37.000000000 +0100
+++ linux-2.6.34_original/drivers/media/video/zoran/zoran.h	2008-05-17 13:09:14.000000000 +0200
@@ -301,17 +301,20 @@
 
 struct zoran_jpg_buffer {
 	struct zoran_mapping *map;
-	u32 *frag_tab;		/* addresses of frag table */
-	u32 frag_tab_bus;	/* same value cached to save time in ISR */
-	enum zoran_buffer_state state;	/* non-zero if corresponding buffer is in use in grab queue */
-	struct zoran_sync bs;	/* DONE: info to return to application */
+	u32 *frag_tab;			  /* virtual addresses of frag table */
+	dma_addr_t frag_tab_bus;	  /* same value cached to save time in ISR */
+	struct scatterlist *frag_tab_sg;  /* fragment table containing virtual addresses */
+	int scatterlist_entries;	  /* indicates whether the scatterlist is mapped and how many entries */
+	void **frag_tab_allocs;		  /* allocations done for the fragment table */
+	enum zoran_buffer_state state;	  /* non-zero if corresponding buffer is in use in grab queue */
+	struct zoran_sync bs;		  /* DONE: info to return to application */
 };
 
 struct zoran_v4l_buffer {
 	struct zoran_mapping *map;
 	char *fbuffer;		/* virtual  address of frame buffer */
 	unsigned long fbuffer_phys;	/* physical address of frame buffer */
-	unsigned long fbuffer_bus;	/* bus      address of frame buffer */
+	dma_addr_t fbuffer_bus;		/* bus      address of frame buffer */
 	enum zoran_buffer_state state;	/* state: unused/pending/done */
 	struct zoran_sync bs;	/* DONE: info to return to application */
 };
@@ -349,7 +352,8 @@
 	enum zoran_map_mode map_mode;	/* Flag which bufferset will map by next mmap() */
 
 	struct zoran_overlay_settings overlay_settings;
-	u32 *overlay_mask;	/* overlay mask */
+	u32 *overlay_mask;	 /* overlay mask */
+	dma_addr_t overlay_mask_bus;  /* bus address of overlay mask */
 	enum zoran_lock_activity overlay_active;	/* feature currently in use? */
 
 	struct zoran_v4l_settings v4l_settings;	/* structure with a lot of things to play with */
@@ -428,6 +432,7 @@

 	struct zoran_overlay_settings overlay_settings;
 	u32 *overlay_mask;	/* overlay mask */
+	dma_addr_t overlay_mask_bus;  /* bus address of overlay mask */
 	enum zoran_lock_activity overlay_active;	/* feature currently in use? */
 
 	wait_queue_head_t v4l_capq;
@@ -466,7 +471,8 @@
 	/* zr36057's code buffer table */
	__le32 *stat_com;		 /* stat_com[i] is indexed by dma_head/tail & BUZ_MASK_STAT_COM */
+	dma_addr_t stat_com_bus; /* stat_com mapping for pci bus */
 
 	/* (value & BUZ_MASK_FRAME) corresponds to index in pend[] queue */
 	int jpg_pend[BUZ_MAX_FRAME];