aac_ioctl.c revision f42c2f535d941f602630ea3db3eaf6e956bd4138
/*
* Copyright 2009 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.
*/
#include <sys/ddidmareq.h>
#include <sys/byteorder.h>
#include "aac_regs.h"
#include "aac.h"
#include "aac_ioctl.h"
struct aac_umem_sge {
};
/*
* 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 mode)
{
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
{
union aac_revision_align un;
/* 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;
/* Copy in FIB header */
return (ENOMEM);
sizeof (struct aac_fib_header), mode) != 0) {
goto finish;
}
if (fib_size < fib_sender_size)
goto finish;
}
/* Copy in FIB data */
fib_data_size, mode) != 0) {
goto finish;
}
/* Process FIB */
if (fib_command == TakeABreakPt) {
#ifdef DEBUG
fib_size);
#endif
0, 0, 0, 0, NULL);
} else {
#ifdef DEBUG
#endif
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
{
union aac_get_adapter_fib_align un;
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
* Note: SRB passed down from IOCTL is always in CPU endianness.
*/
static int
{
struct aac_umem_sge *usge;
int umem_flags = 0;
int direct = 0;
int locked = 0;
int sg64;
int rval;
/* Read srb size */
return (EFAULT);
sizeof (struct aac_fib_header)))
return (EINVAL);
return (ENOMEM);
/* Copy in srb */
goto finish;
}
if (srb_sgcount == 0)
goto send_fib;
/* Check FIB size */
if (usr_fib_size == (sizeof (struct aac_srb) + \
srb_sgcount * sizeof (struct aac_sg_entry64) - \
sizeof (struct aac_sg_entry))) {
sg64 = 1;
} else if (usr_fib_size == (sizeof (struct aac_srb) + \
sg64 = 0;
} else {
goto finish;
}
/* Read user SG table */
KM_NOSLEEP)) == NULL) {
goto finish;
}
if (sg64) {
struct aac_sg_entry64 *sg64p =
#ifndef _LP64
(uint32_t)
#endif
} else {
#ifdef _LP64
(uint64_t)
#endif
}
}
goto finish;
}
/* Lock user buffers */
}
}
if (rval != 0) {
rval);
goto finish;
}
locked = 1;
/* Allocate DMA for user buffers */
goto finish;
}
0) != AACOK) {
goto finish;
}
acp->left_cookien);
goto finish;
}
}
/* Construct aac cmd SG table */
KM_NOSLEEP)) == NULL) {
goto finish;
}
}
/* Send FIB command */
#ifdef DEBUG
#endif
goto finish;
/* Status struct */
sizeof (struct aac_srb_reply), mode) != 0) {
goto finish;
}
rval = 0;
acp->left_cookien);
if (usgt) {
sizeof (struct aac_sge) * \
}
}
if (locked)
sizeof (struct aac_fib_header));
return (rval);
}
/*ARGSUSED*/
static int
{
union aac_pci_info_align un;
return (EINVAL);
if (num < (sizeof (pci_regspec_t) / sizeof (int))) {
return (EINVAL);
}
sizeof (struct aac_pci_info), mode) != 0)
return (EFAULT);
return (0);
}
static int
{
union aac_query_disk_align un;
struct aac_container *dvp;
return (EFAULT);
return (EINVAL);
} else {
return (EINVAL);
}
return (EFAULT);
return (0);
}
static int
{
union aac_delete_disk_align un;
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
{
union aac_features_align un;
struct aac_features *f = &un.d;
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);
}