>
> ----- Original Message ----
> From: Ricardo Lugo <[EMAIL PROTECTED]>
> To: Discussion list for development of the IVTV driver
> <[email protected]>
> Sent: Sunday, January 21, 2007 7:13:42 PM
> Subject: Re: [ivtv-devel] trunk on PPC - "couldn't find start of buffer"
>
> Well, after some more testing, it seems that DMA doesn't work on 0.9
> for PPC, it just backs down and attempts to get the data via PIO when
> DMA doesn't work.
>
> Anything I can do to get the new DMA code to work on PPC?
>
looks like this is the same issue I'm having on my ARM (big-endian) platform.
The attached patch fixes endian issues for me regarding the DMA_MAGIC_COOKIE
check as well as endian issues with DMA setup that I found, however I'm still
working with Hans to find a dma memory/sync issue that appears on my platform -
so I'm not sure this will fix the PPC DMA or not. Please test this and if it
doesn't work show us a log with ivtv_debug=79
If this does not solve your issue then perhaps its similar to my issue I'm
still working on regarding dma memory sync. There is definitely some issues in
ivtv-svn (and most likely past versions) with regards to sync'ing memory
between device/cpu. I'm still working with Hans on the issue and don't have an
elegant solution yet that works on my ARM big-endian platform, but I can work
around the issue by changing the allocation of the SGarray in ivtv-queue.c as
follows:
Index: driver/ivtv-queue.c
===================================================================
--- driver/ivtv-queue.c (revision 3739)
+++ driver/ivtv-queue.c (working copy)
@@ -225,13 +225,14 @@
/* Allocate DMA SG Arrays */
if (s->dma != PCI_DMA_NONE) {
- s->SGarray = (struct ivtv_SG_element *)kzalloc(SGsize,
GFP_KERNEL);
+// s->SGarray = (struct ivtv_SG_element *)kzalloc(SGsize,
GFP_KERNEL);
+ s->SGarray = (struct ivtv_SG_element
*)pci_alloc_consistent(itv->dev, SGsize, &s->SG_handle);
if (s->SGarray == NULL) {
IVTV_ERR("Could not allocate SGarray for %s stream\n",
s->name);
return -ENOMEM;
}
s->SG_length = 0;
- s->SG_handle = pci_map_single(itv->dev, s->SGarray, SGsize,
s->dma);
+// s->SG_handle = pci_map_single(itv->dev, s->SGarray, SGsize,
s->dma);
}
/* allocate stream buffers. Initially all buffers are in q_free. */
You might want to try this as well. The above patch is only for the MPEG
stream, so I believe there would be other changes for YUV etc but again this
patch is not intended to be the permanent fix.
Tim
> - Rick
>
> On Jan 21, 2007, at 6:36 PM, Ricardo Lugo wrote:
>
> > Hi Hans, Chris, any other developers working on the new DMA code,
> >
> > I tried the trunk on my PPC ivtv machine and can't get it to capture
> > anything. MythTV complains that the driver has stopped recording, and
> > I get the following kernel message:
> >
> > ivtv0 warning: encoder MPEG: Couldn't find start of buffer within
> > the first 256 bytes
> >
> > Fortunately, ivtv-0.9.x works just fine on my PPC machine, so it must
> > be a new change in the trunk. I think the cause is the buffer
> > (pointer?) being byteswapped and the DMA_MAGIC_COOKIE never gets
> > found.... This could be a result of using a char instead of a
> > v4l2_buffer in ivtv_buffer in ivtv-driver.h. Typecasting chars to
> > pointers always result in endian issues....
> >
> > trunk ivtv-irq.c 218: u32buf = (u32 *)buf->buf;
> > 0.9 ivtv-irq.c 296: (u32 *)(buf->buffer.m.userptr)
> >
> > trunk struct ivtv_buffer {
> > struct list_head list;
> > dma_addr_t dma_handle;
> > unsigned long b_flags;
> > char *buf; // leads to endian issues...
> >
> > u32 bytesused;
> > u32 readpos;
> > };
> >
> > 0.9 struct ivtv_buffer {
> > size_t readpos;
> > dma_addr_t dma_handle;
> > struct v4l2_buffer buffer; // conversion handled by
> > v4l2_buffer!
> > struct list_head list;
> > unsigned long ts;
> > unsigned long b_flags;
> > unsigned long *page;
> > unsigned char **vpage;
> > };
> >
> > The "0.9" way of doing the buffer looks much safer to me... hope this
> > helps.
> >
> > - Rick
> >
> > _______________________________________________
> > ivtv-devel mailing list
> > [email protected]
> > http://ivtvdriver.org/mailman/listinfo/ivtv-devel
>
>
> _______________________________________________
> ivtv-devel mailing list
> [email protected]
> http://ivtvdriver.org/mailman/listinfo/ivtv-devel
>
[EMAIL PROTECTED] ivtv-svn]$
Index: driver/ivtv-yuv.c
===================================================================
--- driver/ivtv-yuv.c (revision 3739)
+++ driver/ivtv-yuv.c (working copy)
@@ -91,15 +91,15 @@
/* If we've offset the y plane, ensure top area is blanked */
if (args->src_h + args->src_y < 512-16) {
if (itv->yuv_info.blanking_dmaptr) {
- dma->SGarray[dma->SG_length].size = 720*16;
- dma->SGarray[dma->SG_length].src = itv->yuv_info.blanking_dmaptr;
- dma->SGarray[dma->SG_length].dst = IVTV_DEC_MEM_START + yuv_offset[frame];
+ dma->SGarray[dma->SG_length].size = cpu_to_le32(720*16);
+ dma->SGarray[dma->SG_length].src = cpu_to_le32(itv->yuv_info.blanking_dmaptr);
+ dma->SGarray[dma->SG_length].dst = cpu_to_le32(IVTV_DEC_MEM_START + yuv_offset[frame]);
dma->SG_length++;
}
}
/* Tag SG Array with Interrupt Bit */
- dma->SGarray[dma->SG_length - 1].size |= 0x80000000;
+ dma->SGarray[dma->SG_length - 1].size |= cpu_to_le32(0x80000000);
pci_dma_sync_single_for_device((struct pci_dev *)itv->dev, dma->SG_handle,
sizeof(dma->SGarray), PCI_DMA_TODEVICE);
Index: driver/ivtv-irq.c
===================================================================
--- driver/ivtv-irq.c (revision 3739)
+++ driver/ivtv-irq.c (working copy)
@@ -122,11 +122,11 @@
if (itv->has_cx23415 && (s->type == IVTV_ENC_STREAM_TYPE_PCM ||
s->type == IVTV_DEC_STREAM_TYPE_VBI)) {
s->dma_backup = read_dec(offset - IVTV_DECODER_OFFSET);
- write_dec(DMA_MAGIC_COOKIE, offset - IVTV_DECODER_OFFSET);
+ write_dec(cpu_to_le32(DMA_MAGIC_COOKIE), offset - IVTV_DECODER_OFFSET);
}
else {
s->dma_backup = read_enc(offset);
- write_enc(DMA_MAGIC_COOKIE, offset);
+ write_enc(cpu_to_le32(DMA_MAGIC_COOKIE), offset);
}
s->dma_offset = offset;
}
@@ -165,9 +165,9 @@
if (skip_bufs-- > 0)
continue;
if (!ivtv_use_pio(s)) {
- s->SGarray[idx].dst = buf->dma_handle;
- s->SGarray[idx].src = offset;
- s->SGarray[idx].size = s->buf_size;
+ s->SGarray[idx].dst = cpu_to_le32(buf->dma_handle);
+ s->SGarray[idx].src = cpu_to_le32(offset);
+ s->SGarray[idx].size = cpu_to_le32(s->buf_size);
}
buf->bytesused = (size < s->buf_size) ? size : s->buf_size;
@@ -222,7 +222,8 @@
if (x == 0) {
offset = s->dma_last_offset;
- if (u32buf[offset / 4] != DMA_MAGIC_COOKIE) {
+ if (u32buf[offset / 4] != DMA_MAGIC_COOKIE)
+ {
for (offset = 0; offset < 64; offset++) {
if (u32buf[offset] == DMA_MAGIC_COOKIE) {
break;
@@ -312,9 +313,9 @@
offset = uv_offset;
y_done = 1;
}
- s->SGarray[idx].src = buf->dma_handle;
- s->SGarray[idx].dst = offset;
- s->SGarray[idx].size = buf->bytesused;
+ s->SGarray[idx].src = cpu_to_le32(buf->dma_handle);
+ s->SGarray[idx].dst = cpu_to_le32(offset);
+ s->SGarray[idx].size = cpu_to_le32(buf->bytesused);
offset += buf->bytesused;
bytes_written += buf->bytesused;
@@ -326,7 +327,7 @@
s->SG_length = idx;
/* Mark last buffer size for Interrupt flag */
- s->SGarray[s->SG_length - 1].size |= 0x80000000;
+ s->SGarray[s->SG_length - 1].size |= cpu_to_le32(0x80000000);
/* Sync Hardware SG List of buffers */
pci_dma_sync_single_for_device((struct pci_dev *)itv->dev,
@@ -353,7 +354,7 @@
if (s->q_predma.bytesused)
ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
IVTV_DEBUG_DMA("start DMA for %s\n", s->name);
- s->SGarray[s->SG_length - 1].size += 256;
+ s->SGarray[s->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s->SGarray[s->SG_length - 1].size) + 256);
/* If this is an MPEG stream, and VBI data is also pending, then append the
VBI DMA to the MPEG DMA and transfer both sets of data at once.
@@ -367,7 +368,7 @@
if (s->type == IVTV_ENC_STREAM_TYPE_MPG && s_vbi->SG_length &&
s->SG_length + s_vbi->SG_length <= s->buffers) {
ivtv_queue_move(s_vbi, &s_vbi->q_predma, NULL, &s_vbi->q_dma, s_vbi->q_predma.bytesused);
- s_vbi->SGarray[s_vbi->SG_length - 1].size += 256;
+ s_vbi->SGarray[s_vbi->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s_vbi->SGarray[s->SG_length - 1].size) + 256);
for (i = 0; i < s_vbi->SG_length; i++) {
s->SGarray[s->SG_length++] = s_vbi->SGarray[i];
}
@@ -377,7 +378,7 @@
}
/* Mark last buffer size for Interrupt flag */
- s->SGarray[s->SG_length - 1].size |= 0x80000000;
+ s->SGarray[s->SG_length - 1].size |= cpu_to_le32(0x80000000);
/* Sync Hardware SG List of buffers */
pci_dma_sync_single_for_device((struct pci_dev *)itv->dev,
Index: driver/ivtv-udma.c
===================================================================
--- driver/ivtv-udma.c (revision 3739)
+++ driver/ivtv-udma.c (working copy)
@@ -61,12 +61,12 @@
struct scatterlist *sg;
for (i = 0, sg = dma->SGlist; i < dma->SG_length; i++, sg++) {
- dma->SGarray[i].size = sg_dma_len(sg);
- dma->SGarray[i].src = sg_dma_address(sg);
- dma->SGarray[i].dst = buffer_offset;
- buffer_offset += dma->SGarray[i].size;
+ dma->SGarray[i].size = cpu_to_le32(sg_dma_len(sg));
+ dma->SGarray[i].src = cpu_to_le32(sg_dma_address(sg));
+ dma->SGarray[i].dst = cpu_to_le32(buffer_offset);
+ buffer_offset += sg_dma_len(sg);
- split -= dma->SGarray[i].size;
+ split -= sg_dma_len(sg);
if (split == 0)
buffer_offset = buffer_offset_2;
}
@@ -130,7 +130,7 @@
ivtv_udma_fill_sg_array (dma, ivtv_dest_addr, 0, -1);
/* Tag SG Array with Interrupt Bit */
- dma->SGarray[dma->SG_length - 1].size |= 0x80000000;
+ dma->SGarray[dma->SG_length - 1].size |= cpu_to_le32(0x80000000);
pci_dma_sync_single_for_device((struct pci_dev *)itv->dev, dma->SG_handle,
sizeof(dma->SGarray), PCI_DMA_TODEVICE);
_______________________________________________
ivtv-devel mailing list
[email protected]
http://ivtvdriver.org/mailman/listinfo/ivtv-devel