Technical question on PVR DMA

If you have any questions on programming, this is the place to ask them, whether you're a newbie or an experienced programmer. Discussion on programming in general is also welcome. We will help you with programming homework, but we will not do your work for you! Any porting requests must be made in Developmental Ideas.
Post Reply
Chilly Willy
DC Developer
DC Developer
Posts: 414
https://www.artistsworkshop.eu/meble-kuchenne-na-wymiar-warszawa-gdzie-zamowic/
Joined: Thu Aug 20, 2009 11:00 am
Has thanked: 0
Been thanked: 2 times

Technical question on PVR DMA

Post by Chilly Willy »

The PVR driver uses one of the DMA channels in the SH4 to do its transfers, but in looking at the code, I saw this

Code: Select all

    val = shdma[DMAC_CHCR2];

    if(val & 0x1)  /* DE bit set so we must clear it */
        shdma[DMAC_CHCR2] = val | 0x1;

    if(val & 0x2)  /* TE bit set so we must clear it */
        shdma[DMAC_CHCR2] = val | 0x2;
Now I know that's totally wrong on the SH2 as I've done lots of DMA code on the 32X. I wasn't sure about the SH4, so I went and checked the manuals and it SHOULD be the same as the 32X as far as DE/TE go - you should write 0 to CHCR2 to clear TE and DE, like this

Code: Select all

    val = shdma[DMAC_CHCR2];
    shdma[DMAC_CHCR2] = 0; /* clear DE and TE */
Reading CHCR and immediately writing a 0 is the only thing that makes DMA work correctly on the 32X. That the DMA works in KOS indicates the SH4 in the DC either doesn't match the docs, or it's not as critical that you clear it as on the SH2. The SH2 literally won't do another DMA operation until you both read CHCR and write a 0 to it.

Page 447 of the SH4 Hardware manual clearly states that the clearing condition of TE is when a 0 is written to TE after reading TE set. DE doesn't have a clearing condition - it's a straight control: 0 = DMA off, 1 = DMA on, and you need to turn it off while setting up the next DMA (assuming it's still set for some reason).
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5658
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has thanked: 9 times
Been thanked: 69 times
Contact:

Re: Technical question on PVR DMA

Post by BlueCrab »

Later on in the same function, TE is cleared to 0:

Code: Select all

    shdma[DMAC_SAR2] = src_addr;
    shdma[DMAC_DMATCR2] = count / 32;
    shdma[DMAC_CHCR2] = 0x12c1;

    val = shdma[DMAC_DMAOR];
I'm not sure what that code earlier in the function is actually doing, as I've not mucked around with the DMA code, personally.

It appears pretty much superfluous though, since it is cleared properly later anyway. It is possible that whoever wrote it just made a mistake (and really wanted & ~0x02 rather than | 0x02)...
Chilly Willy
DC Developer
DC Developer
Posts: 414
Joined: Thu Aug 20, 2009 11:00 am
Has thanked: 0
Been thanked: 2 times

Re: Technical question on PVR DMA

Post by Chilly Willy »

That's one thing I thought - doing val & ~2 and val & ~1 makes sense there, but the code as it is doesn't match the docs at all. In my experience on the 32X with the SH2, reading the CHCR and immediately writing back 0 let's you then setup the next DMA operation. Not doing that makes it ignore you. That doesn't seem like the case on the SH4 - they seem to have made the DMA less finicky, but it would still be in everyone's best interest to use the right code. :grin:

The DMA on the SH family is actually pretty nice and flexible. You get a source and destination. You can increment or decrement or hold both separately. You can set the size of each transfer to a number of sizes (1, 2, 4, and 16 on the SH2 - 1, 2, 4, and 32 on the SH4). You can set it to interrupt when done. You can set the source of the DMA request along with the type of signal it is (edge, level, etc), and how to do the DMA acknowledge. You can also set it to auto (no requests or ack) for things like memory to memory transfers. And you can tell it to share the bus or hog the bus. All pretty standard for DMA controllers, and pretty useful for consoles for a number of things. On the 32X, I use one channel to DMA stereo samples from a double-buffer to the PWM audio registers, and refill the buffers using the DMA int. I use the other channel for transferring the screen buffer from SDRAM to vram (on Wolf3D). On the Dreamcast, it looks like the asic has some FIFO buffers that can be DMA sources/targets for transferring to/from various subsystems, like the PVR memory. From the kos code, it looks like it handles 32 bytes at a time - just right for the 32 byte per transfer mode of the SH4 DMA.
Post Reply