507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * CDDL HEADER START
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * The contents of this file are subject to the terms of the
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Common Development and Distribution License (the "License").
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * You may not use this file except in compliance with the License.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * or http://www.opensolaris.org/os/licensing.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * See the License for the specific language governing permissions
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * and limitations under the License.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * When distributing Covered Code, include this CDDL HEADER in each
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * If applicable, add the following below this CDDL HEADER, with the
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * fields enclosed by brackets "[]" replaced with your own identifying
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * information: Portions Copyright [yyyy] [name of copyright owner]
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * CDDL HEADER END
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf/*
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Use is subject to license terms.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf#include "ghd.h"
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfvoid
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_dmafree_attr(gcmd_t *gcmdp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh GDBG_DMA(("ghd_dma_attr_free: gcmdp 0x%p\n", (void *)gcmdp));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (gcmdp->cmd_dma_handle != NULL) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ddi_dma_unbind_handle(gcmdp->cmd_dma_handle) !=
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf DDI_SUCCESS)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cmn_err(CE_WARN, "ghd dma free attr: "
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf "unbind handle failed");
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_dma_free_handle(&gcmdp->cmd_dma_handle);
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh GDBG_DMA(("ghd_dma_attr_free: ddi_dma_free 0x%p\n",
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh (void *)gcmdp));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp->cmd_dma_handle = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp->cmd_ccount = 0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp->cmd_totxfer = 0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_dma_buf_bind_attr(ccc_t *cccp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmd_t *gcmdp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf struct buf *bp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int dma_flags,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int (*callback)(),
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf caddr_t arg,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_dma_attr_t *sg_attrp)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int status;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf GDBG_DMA(("ghd_dma_attr_get: start: gcmdp 0x%p sg_attrp 0x%p\n",
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh (void *)gcmdp, (void *)sg_attrp));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * First time, need to establish the handle.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(gcmdp->cmd_dma_handle == NULL);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf status = ddi_dma_alloc_handle(cccp->ccc_hba_dip, sg_attrp, callback,
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh arg, &gcmdp->cmd_dma_handle);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (status != DDI_SUCCESS) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf bp->b_error = 0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf status = ddi_dma_buf_bind_handle(gcmdp->cmd_dma_handle, bp, dma_flags,
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh callback, arg, &gcmdp->cmd_first_cookie, &gcmdp->cmd_ccount);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf GDBG_DMA(("ghd_dma_attr_get: setup: gcmdp 0x%p status %d h 0x%p "
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh "c 0x%d\n", (void *)gcmdp, status, (void *)gcmdp->cmd_dma_handle,
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh gcmdp->cmd_ccount));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf switch (status) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case DDI_DMA_MAPPED:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* enable first (and only) call to ddi_dma_getwin */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp->cmd_wcount = 1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case DDI_DMA_PARTIAL_MAP:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* enable first call to ddi_dma_getwin */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (ddi_dma_numwin(gcmdp->cmd_dma_handle, &gcmdp->cmd_wcount) !=
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh DDI_SUCCESS) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf bp->b_error = 0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_dma_free_handle(&gcmdp->cmd_dma_handle);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp->cmd_dma_handle = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case DDI_DMA_NORESOURCES:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf bp->b_error = 0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_dma_free_handle(&gcmdp->cmd_dma_handle);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp->cmd_dma_handle = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case DDI_DMA_TOOBIG:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf bioerror(bp, EINVAL);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_dma_free_handle(&gcmdp->cmd_dma_handle);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp->cmd_dma_handle = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case DDI_DMA_NOMAPPING:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf case DDI_DMA_INUSE:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf default:
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf bioerror(bp, EFAULT);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_dma_free_handle(&gcmdp->cmd_dma_handle);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp->cmd_dma_handle = NULL;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* initialize the loop controls for ghd_dmaget_next_attr() */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp->cmd_windex = 0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp->cmd_cindex = 0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp->cmd_totxfer = 0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp->cmd_dma_flags = dma_flags;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp->use_first = 1;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfuint_t
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_dmaget_next_attr(ccc_t *cccp, gcmd_t *gcmdp, long max_transfer_cnt,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int sg_size, ddi_dma_cookie_t cookie)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ulong_t toxfer = 0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int num_segs = 0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int single_seg;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf GDBG_DMA(("ghd_dma_attr_get: start: gcmdp 0x%p h 0x%p c 0x%x\n",
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh (void *)gcmdp, (void *)gcmdp->cmd_dma_handle, gcmdp->cmd_ccount));
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * Disable single-segment Scatter/Gather option
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * if can't do this transfer in a single segment,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (gcmdp->cmd_cindex + 1 < gcmdp->cmd_ccount) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf single_seg = FALSE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf } else {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf single_seg = TRUE;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf for (;;) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * call the controller specific S/G function
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf (*cccp->ccc_sg_func)(gcmdp, &cookie, single_seg, num_segs);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /* take care of the loop-bookkeeping */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf toxfer += cookie.dmac_size;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf num_segs++;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp->cmd_cindex++;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * if this was the last cookie in the current window
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * set the loop controls start the next window and
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * exit so the HBA can do this partial transfer
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (gcmdp->cmd_cindex >= gcmdp->cmd_ccount) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp->cmd_windex++;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp->cmd_cindex = 0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(single_seg == FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (toxfer >= max_transfer_cnt)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (num_segs >= sg_size)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf break;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_dma_nextcookie(gcmdp->cmd_dma_handle, &cookie);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp->cmd_totxfer += toxfer;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
f304523c1c8b168f5db72cb0e24ee8318a974f8dzhongyan gu - Sun Microsystems - Beijing China return ((uint_t)toxfer);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfint
507c32411f3f101e90ca2120f042b5ee698ba1d5mlfghd_dmaget_attr(ccc_t *cccp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmd_t *gcmdp,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf long count,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int sg_size,
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf uint_t *xfer)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf{
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf int status;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_dma_cookie_t cookie;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *xfer = 0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (gcmdp->use_first == 1) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf cookie = gcmdp->cmd_first_cookie;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf gcmdp->use_first = 0;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf } else if (gcmdp->cmd_windex >= gcmdp->cmd_wcount) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * reached the end of buffer. This should not happen.
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ASSERT(gcmdp->cmd_windex < gcmdp->cmd_wcount);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf } else if (gcmdp->cmd_cindex == 0) {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf off_t offset;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf size_t length;
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * start the next window, and get its first cookie
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf status = ddi_dma_getwin(gcmdp->cmd_dma_handle,
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh gcmdp->cmd_windex, &offset, &length,
903a11ebdc8df157c4700150f41f1f262f4a8ae8rh &cookie, &gcmdp->cmd_ccount);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf if (status != DDI_SUCCESS)
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (FALSE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf } else {
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * get the next cookie in the current window
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf ddi_dma_nextcookie(gcmdp->cmd_dma_handle, &cookie);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf }
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf /*
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * start the Scatter/Gather loop passing in the first
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf * cookie obtained above
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf */
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf *xfer = ghd_dmaget_next_attr(cccp, gcmdp, count, sg_size, cookie);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf return (TRUE);
507c32411f3f101e90ca2120f042b5ee698ba1d5mlf}