h6. [[Hardware Abstraction Layer]] h6(. » [[HAL Device API]] h6((. » [[List of HAL devices]] h6(((. » DMA channel - buffer type h5. (HALDeviceSysPeri_DMAB) h4. Device API Currently, only API versions 0 and 1 are defined. h5. API version 0 <pre> struct dmachannel { /* Public interface */ struct device dev; uint32_t (*Features)(struct dmachannel *); dmacontroller *controller; void (*Abort)(struct dmachannel *); void (*SetOptions)(struct dmachannel *, uint32_t flags, uint32_t address); void (*SetCurrentTransfer)(struct dmachannel *, uint32_t address, uint32_t length, uint32_t flags); void (*SetNextTransfer)(struct dmachannel *, uint32_t address, uint32_t length, uint32_t flags); __value_in_regs struct { uint32_t address; uint32_t length; } (*TransferState)(struct dmachannel *); void (*IRQClear)(struct dmachannel *); uint32_t (*Status)(struct dmachannel *); void (*SetCurrentTransfer2)(struct dmachannel *, uint32_t srcaddress, uint32_t dstaddress, uint32_t length, uint32_t flags); void (*SetNextTransfer2)(struct dmachannel *, uint32_t srcaddress, uint32_t dstaddress, uint32_t length, uint32_t flags); __value_in_regs struct { uint32_t srcaddress; uint32_t dstaddress; uint32_t length; } (*TransferState2)(struct dmachannel *); } </pre> _dev_ is the standard [[HAL Device descriptor]]. The _address_ field is not used. Channels are activated/deactivated around each transfer (and are deactivated when a transfer is suspended). _dev.Activate_ enables this physical DMA channel, so that it can generate interrupts (typically this involves unmasking the DMA request line and unmasking a bit in an interrupt control register). If this is an interrupt-generating channel (i.e. _dev.devicenumber_ is not -1) then the channel must generate an interrupt if _Activate_ is called when no data has been scheduled for transfer. _dev.Deactivate_ must block until the transfer on this channel can safely be interrupted (due to [[Service_PagesUnsafe]] or SWI [[DMA_SuspendTransfer]]), then disable DMA at the DMA request line and interrupt generation levels. After it returns, the values returned from TransferState and Status must reflect the true state of the hardware - ie they must be suitable to use for resumption of the transfer using _SetCurrentTransfer_. _dev.Reset_ is called by the DMAManager between transfers (but not on OS resets). After this call, _Status_ must report an over/underrun condition. _Features_ returns a flag word. Defined bits are as followed: |_<. Bit |_<. Flag |_<. Meaning when set | |0 |DMAFeaturesFlag_DualAddress |Channel implements "dual address mode", i.e. it can only be used for DMA accelerated copies of blocks of memory. | Flag bits not mentioned are reserved and must be set to zero. _controller_ points to this channel's [[HALDeviceSysPeri_DMAC|DMA controller device]] _Abort_ should be considered a "forced" version of _dev.Deactivate_, and is only used for SWI _DMA_TerminateTransfer_. The call must not block, but the values subsequently returned from _TransferState_ and _Status_ are allowed to report inaccurate results, providing they underestimate the progress of the transfer. _SetOptions_ is used to control the behaviour of the channel. The _flags_ parameter specifies a flags word; defined bits are as follows: |_<. Bit(s) |_<. Meaning | |/3^. 0 |Bit set => memory to device | |Bit clear => device to memory | |(Ignored for memory-to-memory channel) | |1-5 |Transfer unit width, typically 1, 2 or 4 bytes (16 bytes can also be used for IOMD) | |6-8 |Cycle speed, on an arbitrary scale from 0-7 (0-3 maps to A-D cycles on IOMD)| |9-12 |Minimum delay required after a DMA transfer before the same physical channel is reused (required for 7200 and 9200) | |13 |Bit set => Disable burst transfers for this channel | |14 |Bit set => Bypass synchronisation to clock before initiating transfer (for synchronous peripherals - currently 7200 only) | Other bits are reserved and must be ignored. The _address_ parameter sets the physical address of the peripheral to DMA to/from (should be ignored by memory-to-memory channels) _SetCurrentTransfer_ sets up the first transfer to be executed for this channel. _address_ provides the physical address to start transfer from. _length_ is the number of bytes to transfer. _flags_ provides a flags word: |_<. Bit |_<. Meaning | |0 |Bit set => stop and raise the TC signal when this transfer completes (mandatory if the DMA controller has no interrupt of its own) | _address_ and _length_ should be multiples of the transfer unit size, and must not cross a page boundary. _SetNextTransfer_ sets up the next transfer to be executed for this channel, using similar parameters to _SetCurrentTransfer_. This will only be called for double-buffered channels. _TransferState_ reads the progress of the current transfer on this channel. If the DMA controller will not report accurate progress, report values corresponding to a pessimistic amount of progress. _IRQClear_ clears the interrupt for this physical DMA channel (unless some other action carried out during or since _TestIRQ_ has already done so). _Status_ returns status bits for the current channel: |_<. Bit |_<. Meaning | |0 |Bit set => There are no transfers programmed but not yet started (for a double-buffered controller, this is set when interrupting or for a single-buffered controller, this is always set) | |1 |Bit set => Channel has not yet been used, or is in over/underrun state (set on every interrupt for single-buffered DMA controllers) | |2 |Bit set => Channel entered over/underrun state before last call to _SetNextTransfer_ had effect (devices may determine this by monitoring any handle they may have on the physical double buffers, or failing this by calculating the final value of the current pointer of the current buffer, and comparing it to what would be expected from the last time the next buffer was programmed - but note that this latter algorithm will fail if a circular transfer from a single-entry scatter list is in use) so the DMA manager needs to program the same data again, but this time using _SetCurrentTransfer_. This bit must be clear if the last transfer was programmed using _SetCurrentTransfer_, or if bit 1 is clear. | Other bits are reserved and should be zero. _SetCurrentTransfer2_, _SetNextTransfer2_ and _TransferState2_ are the same as above but with two address arguments and one length argument. For use in memory-to-memory transfers only. h5. API version 1 API version 1 extends the set of flags returned by _Features_: |_<. Bit |_<. Flag |_<. Meaning when set | |4 |DMAFeaturesFlag_NoInitIRQ |Channel doesn't generate an IRQ if _Activate_ is called when the channel has no pending transfers | |5 |DMAFeaturesFlag_DoubleBuffered |The channel implements _SetNextTransfer_ in conjunction with _DMAFeaturesFlag_NoInitIRQ_ | h4. Support in RISC OS HALDeviceSysPeri_DMAB is supported by the trunk version of the [[DMAManager]] module. h4. Known implementations |_<. Device ID |_<. Description |_<. Implemented in | |HALDeviceID_DMAB_M1535 |Acer M1535+ legacy DMA channel <x> |HAL.Tungsten.s.M1535DMA | |HALDeviceID_DMAB_OMAP3 |OMAP3 system DMA channel <x> |HAL.OMAP3.s.SDMA | h6. Information sources: Kernel.Hdr.HALDevice, HWSupport.DMA.HAL_DMAAPI, HWSupport.DMA.hdr.DMADevice in CVS