对于先前分配的包含待传送数据的包,tran_init_pkt(9E) 入口点在满足以下条件时必须重新分配 DMA 资源:
已分配部分 DMA 资源。
先前调用 tran_init_pkt(9E) 时返回了非零的 pkt_resid。
bp 不为 null。
bp->b_bcount 不为零。
重新分配下一个传送部分的 DMA 资源时,tran_init_pkt(9E) 必须在字段 pkt_resid 中返回未为此传送分配的 DMA 资源量。
如果在尝试移动 DMA 资源时出现错误,则 tran_init_pkt(9E) 决不能释放 scsi_pkt(9S)。在这种情况下,目标驱动程序负责释放包。
如果回调参数为 NULL_FUNC,则 tran_init_pkt(9E) 入口点决不能休眠或调用可能会休眠的任何函数。如果回调参数为 SLEEP_FUNC 并且资源不会立即可用,则 tran_init_pkt(9E) 入口点会休眠。除非无法满足请求,否则 tran_init_pkt() 将休眠,直到资源可用为止。
static int isp_i_dma_move( struct isp *isp, struct scsi_pkt *pkt, struct buf *bp) { struct isp_cmd *sp = (struct isp_cmd *)pkt->pkt_ha_private; int i; ASSERT(sp->cmd_flags & CFLAG_COMPLETED); sp->cmd_flags &= ~CFLAG_COMPLETED; /* * If there are no more cookies remaining in this window, * must move to the next window first. */ if (sp->cmd_cookie == sp->cmd_ncookies) { /* * For small pkts, leave things where they are */ if (sp->cmd_curwin == sp->cmd_nwin && sp->cmd_nwin == 1) return (1); /* * At last window, cannot move */ if (++sp->cmd_curwin >= sp->cmd_nwin) return (0); if (ddi_dma_getwin(sp->cmd_dmahandle, sp->cmd_curwin, &sp->cmd_dma_offset, &sp->cmd_dma_len, &sp->cmd_dmacookies[0], &sp->cmd_ncookies) == DDI_FAILURE) return (0); sp->cmd_cookie = 0; } else { /* * Still more cookies in this window - get the next one */ ddi_dma_nextcookie(sp->cmd_dmahandle, &sp->cmd_dmacookies[0]); } /* * Get remaining cookies in this window, up to our maximum */ i = 0; for (;;) { sp->cmd_dmacount += sp->cmd_dmacookies[i++].dmac_size; sp->cmd_cookie++; if (i == ISP_NDATASEGS || sp->cmd_cookie == sp->cmd_ncookies) break; ddi_dma_nextcookie(sp->cmd_dmahandle, &sp->cmd_dmacookies[i]); } sp->cmd_cookiecnt = i; pkt->pkt_resid = bp->b_bcount - sp->cmd_dmacount; return (1); }