void dma_breakup(int *xxstrategy ( struct buf *bp), struct buf *bp);
b_flagsis ORed with B_ERROR and B_DONE, and
b_erroris set to EAGAIN
b_erroris set to 0 (zero) if end of media occurs in transfer of second and subsequent blocks
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
An end of media fault, on second and subsequent blocks,
causes ENXIO to be cleared from
the number of blocks remaining to be transferred
to be put in
and B_ERROR to be set in
During DMA transfer,
is called to put the current buffer on the buffering mechanism.
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:
b_flagsto 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.