qlt_dma.c revision fcf3ce441efd61da9bb2884968af01cb7c1452cc
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <stmf_defines.h>
#include <fct_defines.h>
#include <stmf.h>
#include <portif.h>
#include <fct.h>
#include <qlt.h>
#include <qlt_dma.h>
#define BUF_COUNT_2K 2048
#define BUF_COUNT_8K 512
#define BUF_COUNT_64K 128
#define BUF_COUNT_128K 64
#define BUF_COUNT_256K 8
#define QLT_DMEM_NBUCKETS 5
int qlt_256k_nbufs = 0;
static ddi_device_acc_attr_t acc;
static ddi_dma_attr_t qlt_scsi_dma_attr = {
DMA_ATTR_V0, /* dma_attr_version */
0, /* low DMA address range */
0xffffffffffffffff, /* high DMA address range */
0xffffffff, /* DMA counter register */
8192, /* DMA address alignment */
0xff, /* DMA burstsizes */
1, /* min effective DMA size */
0xffffffff, /* max DMA xfer size */
0xffffffff, /* segment boundary */
1, /* s/g list length */
1, /* granularity of device */
0 /* DMA transfer flags */
};
{
int ndx, i;
if (qlt_256k_nbufs) {
}
bsize = sizeof (dmem_buckets);
/*
* The reason it is ndx - 1 everywhere is becasue the last bucket
* pointer is NULL.
*/
for (i = 0; i < (ndx - 1); i++) {
(i*sizeof (qlt_dmem_bucket_t)));
sizeof (qlt_dmem_bucket_t));
}
sizeof (qlt_dmem_bctl_t), KM_NOSLEEP);
goto alloc_bctl_failed;
p->dmem_bctls_mem = bctl;
goto alloc_handle_failed;
goto mem_alloc_failed;
goto addr_bind_handle_failed;
if (ncookie != 1)
goto dmem_init_failed;
bsize = p->dmem_buf_size;
p->dmem_bctl_free_list = bctl;
p->dmem_nbufs_free = p->dmem_nbufs;
for (i = 0; i < p->dmem_nbufs; i++) {
bctl->bctl_bucket = p;
0, 0);
bctl++;
}
}
return (QLT_SUCCESS);
while (bc) {
}
(void) ddi_dma_unbind_handle(p->dmem_dma_handle);
mutex_destroy(&p->dmem_lock);
if (--ndx >= 0) {
bctl = p->dmem_bctl_free_list;
goto dmem_failure_loop;
}
((sizeof (dmem_buckets)/sizeof (void *))
*sizeof (qlt_dmem_bucket_t)));
return (QLT_FAILURE);
}
void
{
int ndx;
bctl = p->dmem_bctl_free_list;
while (bctl) {
}
bctl = p->dmem_bctl_free_list;
(void) ddi_dma_unbind_handle(p->dmem_dma_handle);
p->dmem_nbufs * sizeof (qlt_dmem_bctl_t));
mutex_destroy(&p->dmem_lock);
}
(((sizeof (dmem_buckets)/sizeof (void *))-1)*
sizeof (qlt_dmem_bucket_t)));
}
{
return (qlt_i_dmem_alloc((qlt_state_t *)
flags));
}
/* ARGSUSED */
{
int i;
uint32_t size_possible = 0;
if (size > QLT_DMEM_MAX_BUF_SIZE) {
goto qlt_try_partial_alloc;
}
/* 1st try to do a full allocation */
mutex_enter(&p->dmem_lock);
bctl = p->dmem_bctl_free_list;
mutex_exit(&p->dmem_lock);
continue;
}
p->dmem_nbufs_free--;
mutex_exit(&p->dmem_lock);
}
}
/* Now go from high to low */
for (i = QLT_DMEM_NBUCKETS - 1; i >= 0; i--) {
p = qlt->dmem_buckets[i];
if (p->dmem_nbufs_free == 0)
continue;
if (!size_possible) {
size_possible = p->dmem_buf_size;
}
if (*pminsize > p->dmem_buf_size) {
/* At this point we know the request is failing. */
if (size_possible) {
/*
* This caller is asking too much. We already
* know what we can give, so get out.
*/
break;
} else {
/*
* Lets continue to find out and tell what
* we can give.
*/
continue;
}
}
mutex_enter(&p->dmem_lock);
if (*pminsize <= p->dmem_buf_size) {
bctl = p->dmem_bctl_free_list;
/* Someone took it. */
size_possible = 0;
mutex_exit(&p->dmem_lock);
continue;
}
p->dmem_nbufs_free--;
mutex_exit(&p->dmem_lock);
}
}
return (NULL);
}
/* ARGSUSED */
void
{
qlt_dmem_free(0, dbuf);
}
/* ARGSUSED */
void
{
mutex_enter(&p->dmem_lock);
p->dmem_bctl_free_list = bctl;
p->dmem_nbufs_free++;
mutex_exit(&p->dmem_lock);
}
void
{
(void) ddi_dma_sync(p->dmem_dma_handle, (unsigned long)
}