DMA_BREAKUP(K) UNIX System V DMA_BREAKUP(K)
Name
dma_breakup - sizes DMA request into 512-byte blocks
Syntax
int
dma_breakup(xxstrategy, bp)
int (*xxstrategy)();
struct buf *bp;
Description
The dma_breakup routine breaks up Direct Memory Access (DMA)
I/O requests into 512-byte units of contiguous memory to
avoid limitations imposed by DMA controllers. dma_breakup
is called by the physio(K) routine, indirectly. 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, xxstrategy is called to get a
buffer header. If a buffer header is not available from the
call to xxstrategy, dma_breakup goes to sleep until one is
free. While sleeping, the request for a buffer is protected
from signals, and from interrupts occurring at or below
spl6(K). 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 xxstrategy is
called. Again, sleep is called to wait 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, ENXIO is returned. During DMA transfer, xxstrategy
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.
NOTE: Use splx(K) to save your spl setting before calling
dma_breakup because dma_breakup calls spl0(K) and cancels
all previously set spl levels.
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.
dma_breakup calls sleep(K) and therefore can only be called
from a non-interrupt routine.
Parameters
The parameters to dma_breakup are as follows:
xxstrategy The name of the xxstrategy driver
routine.
bp A pointer to the buf structure.
Return Value
None. However, the following values may change:
+ 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_un.b_addr - set to the virtual kernel address.
+ b_blkno - changed.
+ b_bcount - changed.
+ u.u_segflg - set to zero.
+ u.u_base, u.u_count, u.u_offset - u.u_base and
u.u_offset are incremented by the number of characters
to be transferred; u.u_count is decremented.
(printed 7/6/89)