Specifications

D
evice Driver Programming
12-4
count. Also construct a new chain pair if the addition of this count to the
previous pair would result in the count exceeding the maximum permitted.
The HSA driver's implementation of the preceding pseudo-code follows. Comments
within the code explain each step of the routine.
/*
* Convert the virtual address range [va, va+len) into the series
* of contiguous memory areas in its physical mapping.
*/
u_int
hshd_virt2chain (va, len, proc, mcb)
caddr_t va;
u_int len;
struct proc *proc;
hshd_mcb_type *mcb;
{
int chn = 0;
paddr_t prevpa;
u_int prevbc;
/*
* byte count of 0 is not an error
*/
if (len == 0) {
mcb->hdw.chain[0].ta = 0;
mcb->hdw.chain[0].tc = 0;
return (0);
}
do {
/*
* get the physical address of the current
* virtual buffer 'chunk'
*/
paddr_t pa = vtop (va, proc);
/*
* if this address is not page aligned, then reduce
* the associated byte count for this pair accordingly.
* this should be true on the first address only.
*
* never assign more than 'len' bytes to the pair.
*/
u_int bc = min (PAGESIZE - (pa & PAGEOFFSET), len);
/*
* if this is not the first pair, and the current
* chunk is contiguous with the last chunk, and
* the inclusion of this transfer would not
* exceed the maximum byte count for a single chain
* pair, then add the count for this chunk to the
* last one.
*
* Always set the LWC_DATA_CHAIN flag indicating that
* there are more pairs in the list.
*/
if ((chn > 0) && ((prevpa + prevbc) == pa) && ((prevbc + bc) < HSHD_MAXBC)) {
prevbc += bc;
mcb->hdw.chain[chn-1].tc = prevbc | LWC_DATA_CHAIN;
}