DOC HOME SITE MAP MAN PAGES GNU INFO SEARCH PRINT BOOK
 
SCO OpenServer

dma_breakup(D3oddi)


dma_breakup -- size DMA request into 512-byte blocks

Synopsis

   #include <sys/buf.h>
   

void dma_breakup(int *xxstrategy ( struct buf *bp), struct buf *bp);

Description

The dma_breakup( ) function breaks up Direct Memory Access (DMA) I/O requests into 512-byte units of contiguous memory to avoid limitations imposed by DMA controllers.

Arguments


xxstrategy
name of the strategy(D2oddi) entry point routine

bp
pointer to the buf structure.

Return values

None. However, the following values may change as side effects:

b_flags
if insufficient memory is available for allocation, b_flags is ORed with B_ERROR and B_DONE, and b_error is set to EAGAIN

b_error
has ENXIO set if end of media occurs in the first block transfer

b_flags
has B_ERROR set and b_error is set to 0 (zero) if end of media occurs in transfer of second and subsequent blocks

b_un.b_addr
set to the virtual kernel address

b_blkno
changed

b_bcount
changed

u.u_segflg
set to zero

u.u_base
is incremented by the number of characters transferred

u.u_count
is decremented by the number of characters transferred

u.u_offset
is incremented by the number of characters transferred

Usage

dma_breakup is called indirectly by the physio(D3oddi) function. Place the dma_breakup call in a subroutine and then call the name of that routine from physio.

dma_breakup first determines the correct block number of the data being passed.

If a read is being requested, the strategy(D2oddi) entry point is called to get a buffer header. If a buffer header is not available, dma_breakup( ) blocks sleep until one is free. While blocked, the request for a buffer is protected from signals and from interrupts occurring at or below spl6(D3oddi). When a buffer is free, data is read from user space.

A write request is similar, except that the data is copied to a kernel page from user space before the strategy( ) routine is called. Again, the driver blocks while waiting for a free buffer header.

After ensuring that a buffer header is free, DMA transfer starts. If an error is caused by reaching the end of the media during the first block transfer, ENXIO is set in bp->b_error when dma_breakup returns. An end of media fault, on second and subsequent blocks, causes ENXIO to be cleared from b_error, the number of blocks remaining to be transferred to be put in b_resid, and B_ERROR to be set in bp->b_flags. During DMA transfer, strategy( ) is called to put the current buffer on the buffering mechanism. Each time xxstrategy( ) is called, sleep is also called to wait until buffering occurs.

dma_breakup depends on the following fields of the user structure that are set up by the kernel when the I/O request is passed to the driver:


u.u_base
the virtual base address for the calling program in user space

u.u_count
the number of bytes to be transferred

u.u_offset
offset into the file from/to which data is transferred
In addition, the driver should set b_flags to indicate the type of transfer. Possible values are B_READ or B_WRITE.

Use splx(D3oddi) to save your spl setting before calling dma_breakup because dma_breakup calls spl0(D3oddi) and cancels all previously set spl levels.

Context and synchronization

User context.

Hardware applicability

All

Version applicability

oddi: 1, 2, 2mp

SVR5 DDI compatibility

This function is not supported for DDI drivers. buf_breakup(D3) provides similar functionality.

References

physio(D3oddi), strategy(D2oddi)
19 June 2005
© 2005 The SCO Group, Inc. All rights reserved.
OpenServer 5 HDK - June 2005