aac_ioctl.c revision 382c8bca6eeec6112959d16142d3a20406c3ca9b
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright 2005-06 Adaptec, Inc.
* Copyright (c) 2005-06 Adaptec Inc., Achim Leubner
* Copyright (c) 2000 Michael Smith
* Copyright (c) 2001 Scott Long
* Copyright (c) 2000 BSDi
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/ddidmareq.h>
#include <sys/byteorder.h>
#include "aac_regs.h"
#include "aac.h"
#include "aac_ioctl.h"
/*
* External functions
*/
extern void aac_free_dmamap(struct aac_cmd *);
extern ddi_device_acc_attr_t aac_acc_attr;
extern int aac_check_dma_handle(ddi_dma_handle_t);
/*
* IOCTL command handling functions
*/
/*
* Warlock directives
*/
int
{
int status;
switch (cmd) {
break;
case FSACTL_SENDFIB:
goto send_fib;
case FSACTL_SEND_LARGE_FIB:
break;
break;
break;
break;
case FSACTL_SEND_RAW_SRB:
break;
case FSACTL_GET_PCI_INFO:
break;
case FSACTL_QUERY_DISK:
break;
case FSACTL_DELETE_DISK:
break;
case FSACTL_GET_FEATURES:
break;
default:
"!IOCTL cmd 0x%x not supported", cmd);
break;
}
return (status);
}
/*ARGSUSED*/
static int
{
struct aac_revision aac_rev;
/* Copyin the revision struct from userspace */
sizeof (struct aac_revision), mode) != 0)
return (EFAULT);
/* Doctor up the response struct */
sizeof (struct aac_revision), mode) != 0)
return (EFAULT);
return (0);
}
static int
{
int rval;
return (ENXIO);
}
if (rval == TRAN_ACCEPT) {
rval = 0;
} else if (rval == TRAN_BADPKT) {
}
return (rval);
}
static int
{
int hbalen;
int rval = 0;
/* Copy in FIB header */
return (ENOMEM);
sizeof (struct aac_fib_header), mode) != 0) {
goto finish;
}
goto finish;
}
/* Copy in FIB data */
goto finish;
}
/* Process FIB */
0, 0, 0, 0, NULL);
} else {
goto finish;
}
goto finish;
}
goto finish;
}
rval = 0;
return (rval);
}
static int
{
return (ENOMEM);
/* All elements are already 0, add to queue */
} else {
;
}
/* Evaluate unique value */
} else {
}
}
/* Set ctx_idx to the oldest AIF */
}
return (EFAULT);
return (0);
}
static int
{
int current;
return (EAGAIN); /* Empty */
return (EFAULT);
ctx->ctx_filled = 0;
return (0);
}
static int
{
struct aac_get_adapter_fib af;
struct aac_fib_context *ctx;
int rval;
return (EFAULT);
break;
}
if (ctx) {
#ifdef _LP64
#else
#endif
"aac_next_getadapter_fib(): waiting for AIF");
if (rval > 0) {
#ifdef _LP64
#else
#endif
} else {
}
}
} else {
}
return (rval);
}
static int
{
struct aac_fib_context *ctx;
continue;
else
break;
}
if (ctx)
return (0);
}
/*
* The following function comes from Adaptec:
*
* SRB is required for the new management tools
*/
static int
{
int hbalen;
struct aac_sg_entry *sgp;
struct aac_sg_entry64 *sg64p;
int rval;
return (ENOMEM);
/* Read srb size */
goto finish;
}
sizeof (struct aac_fib_header))) {
goto finish;
}
/* Copy in srb */
goto finish;
}
/* Only one sg element from userspace supported */
goto finish;
}
/* Check FIB size */
if (usr_fib_size != (sizeof (struct aac_srb) + \
goto finish;
}
/* Allocate and bind DMA memory space */
acp->left_cookien = 0;
if (rval != DDI_SUCCESS) {
"Can't allocate DMA handle, errno=%d", rval);
goto finish;
}
/* TODO: remove duplicate code with aac_tran_init_pkt() */
/* Allocate DMA buffer */
if (rval != DDI_SUCCESS) {
"Cannot alloc DMA to non-aligned buf");
goto finish;
}
(SRB_DataIn | SRB_DataOut))
if (rval != DDI_DMA_MAPPED) {
goto finish;
}
/* Copy in user srb buf content */
if (ddi_copyin(
#ifdef _LP64
(void *)srb_sg_address,
#else
(void *)(uint32_t)srb_sg_address,
#endif
goto finish;
}
}
}
acp->left_cookien);
goto finish;
}
/* Init FIB header */
fib_size = sizeof (struct aac_fib_header) + \
sizeof (struct aac_srb) - sizeof (struct aac_sg_entry);
/* Calculate FIB data size */
} else {
}
/* Fill in sg elements */
do {
sg64p++;
} else {
sgp++;
}
acp->left_cookien--;
if (acp->left_cookien > 0)
else
break;
/*CONSTCOND*/
} while (1);
/* Send FIB command */
goto finish;
goto finish;
}
#ifdef _LP64
(void *)srb_sg_address,
#else
(void *)(uint32_t)srb_sg_address,
#endif
srb_sg_bytecount, mode) != 0) {
goto finish;
}
}
/* Status struct */
sizeof (struct aac_srb_reply), mode) != 0) {
goto finish;
}
rval = 0;
return (rval);
}
/*ARGSUSED*/
static int
{
struct aac_pci_info resp;
sizeof (struct aac_pci_info), mode) != 0)
return (EFAULT);
return (0);
}
static int
{
struct aac_query_disk qdisk;
struct aac_container *dvp;
return (EFAULT);
return (EINVAL);
} else {
return (EINVAL);
}
return (EFAULT);
return (0);
}
static int
{
struct aac_delete_disk ddisk;
struct aac_container *dvp;
int rval = 0;
return (EFAULT);
return (EINVAL);
/*
* We don't trust the userland to tell us when to delete
* a container, rather we rely on an AIF coming from the
* controller.
*/
}
return (rval);
}
/*
* The following function comes from Adaptec to support creation of arrays
* bigger than 2TB.
*/
static int
{
struct aac_features f;
return (EFAULT);
/*
* When the management driver receives FSACTL_GET_FEATURES ioctl with
* ALL zero in the featuresState, the driver will return the current
* state of all the supported features, the data field will not be
* valid.
* When the management driver receives FSACTL_GET_FEATURES ioctl with
* a specific bit set in the featuresState, the driver will return the
* current state of this specific feature and whatever data that are
* associated with the feature in the data field or perform whatever
* action needed indicates in the data field.
*/
/* TODO: In the future, add other features state here as well */
} else {
/* TODO: Add other features state and data in the future */
}
return (EFAULT);
return (0);
}