| This page describes the structures and procedures used by the cx2341x DMA |
| engine. |
| |
| Introduction |
| ============ |
| |
| The cx2341x PCI interface is busmaster capable. This means it has a DMA |
| engine to efficiently transfer large volumes of data between the card and main |
| memory without requiring help from a CPU. Like most hardware, it must operate |
| on contiguous physical memory. This is difficult to come by in large quantities |
| on virtual memory machines. |
| |
| Therefore, it also supports a technique called "scatter-gather". The card can |
| transfer multiple buffers in one operation. Instead of allocating one large |
| contiguous buffer, the driver can allocate several smaller buffers. |
| |
| In practice, I've seen the average transfer to be roughly 80K, but transfers |
| above 128K were not uncommon, particularly at startup. The 128K figure is |
| important, because that is the largest block that the kernel can normally |
| allocate. Even still, 128K blocks are hard to come by, so the driver writer is |
| urged to choose a smaller block size and learn the scatter-gather technique. |
| |
| Mailbox #10 is reserved for DMA transfer information. |
| |
| Note: the hardware expects little-endian data ('intel format'). |
| |
| Flow |
| ==== |
| |
| This section describes, in general, the order of events when handling DMA |
| transfers. Detailed information follows this section. |
| |
| - The card raises the Encoder interrupt. |
| - The driver reads the transfer type, offset and size from Mailbox #10. |
| - The driver constructs the scatter-gather array from enough free dma buffers |
| to cover the size. |
| - The driver schedules the DMA transfer via the ScheduleDMAtoHost API call. |
| - The card raises the DMA Complete interrupt. |
| - The driver checks the DMA status register for any errors. |
| - The driver post-processes the newly transferred buffers. |
| |
| NOTE! It is possible that the Encoder and DMA Complete interrupts get raised |
| simultaneously. (End of the last, start of the next, etc.) |
| |
| Mailbox #10 |
| =========== |
| |
| The Flags, Command, Return Value and Timeout fields are ignored. |
| |
| Name: Mailbox #10 |
| Results[0]: Type: 0: MPEG. |
| Results[1]: Offset: The position relative to the card's memory space. |
| Results[2]: Size: The exact number of bytes to transfer. |
| |
| My speculation is that since the StartCapture API has a capture type of "RAW" |
| available, that the type field will have other values that correspond to YUV |
| and PCM data. |
| |
| Scatter-Gather Array |
| ==================== |
| |
| The scatter-gather array is a contiguously allocated block of memory that |
| tells the card the source and destination of each data-block to transfer. |
| Card "addresses" are derived from the offset supplied by Mailbox #10. Host |
| addresses are the physical memory location of the target DMA buffer. |
| |
| Each S-G array element is a struct of three 32-bit words. The first word is |
| the source address, the second is the destination address. Both take up the |
| entire 32 bits. The lowest 18 bits of the third word is the transfer byte |
| count. The high-bit of the third word is the "last" flag. The last-flag tells |
| the card to raise the DMA_DONE interrupt. From hard personal experience, if |
| you forget to set this bit, the card will still "work" but the stream will |
| most likely get corrupted. |
| |
| The transfer count must be a multiple of 256. Therefore, the driver will need |
| to track how much data in the target buffer is valid and deal with it |
| accordingly. |
| |
| Array Element: |
| |
| - 32-bit Source Address |
| - 32-bit Destination Address |
| - 14-bit reserved (high bit is the last flag) |
| - 18-bit byte count |
| |
| DMA Transfer Status |
| =================== |
| |
| Register 0x0004 holds the DMA Transfer Status: |
| |
| Bit |
| 0 read completed |
| 1 write completed |
| 2 DMA read error |
| 3 DMA write error |
| 4 Scatter-Gather array error |