i2o_bs.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/sysmacros.h>
#include <sys/dditypes.h>
/* BSA specific header files */
#include "i2o_bs.h"
char _depends_on[] = "misc/i2o_msg";
static int bsa_strategy(register struct buf *);
int, char *, caddr_t, int *);
static int translate_error(int, int, int);
static void bsa_reply(void *, ddi_acc_handle_t);
static int BsaPowerMgt(bsa_data_t *, int);
static void cap_translation(uint64_t, int *, int *, int *);
static int bsa_lbl_ioctl(dev_t, int, int, int);
static void BsaMediaUnlock_reply(void *, ddi_acc_handle_t);
static int BsaMediaUnlock(bsa_data_t *);
static void BsaMediaLock_reply(void *, ddi_acc_handle_t);
static int BsaMediaLock(bsa_data_t *);
static void BsaPowerMgt_reply(void *, ddi_acc_handle_t);
static int BsaPowerMgt(bsa_data_t *, int);
static void BsaMediaEject_reply(void *, ddi_acc_handle_t);
static int BsaMediaEject(bsa_data_t *);
static int UtilEventRegister(bsa_data_t *, int);
static void UtilEventRegister_reply(void *, ddi_acc_handle_t);
static void UtilAbort_reply(void *, ddi_acc_handle_t);
static int UtilClaim_release(bsa_data_t *);
static void UtilClaim_release_reply(void *, ddi_acc_handle_t);
static int UtilClaim(bsa_data_t *);
static void UtilClaim_reply(void *, ddi_acc_handle_t);
static void UtilParamsGet_reply(void *, ddi_acc_handle_t);
static int UtilParamsGet(bsa_data_t *);
struct dk_geom *, int);
struct cb_ops *);
/*
* Debug flag definitions.
*/
#ifdef BSA_DEBUG
int bsa_debug = I2O_DEBUG_DIO;
#else
#endif
struct cb_ops bsa_cb_ops = {
bsa_open, /* driver open routine */
bsa_close, /* driver close routine */
bsa_strategy, /* driver strategy routine */
bsa_print, /* driver print routine */
bsa_dump, /* driver dump routine */
bsa_read, /* driver read routine */
bsa_write, /* driver write routine */
bsa_ioctl, /* driver ioctl routine */
nodev, /* driver devmap routine */
nodev, /* driver mmap routine */
nodev, /* driver segmap routine */
nochpoll, /* driver chpoll routine */
bsa_prop_op, /* driver prop_op routine */
0, /* driver cb_str - STREAMS only */
};
DEVO_REV, /* devo_rev, */
0, /* refcnt */
bsa_getinfo, /* info */
nulldev, /* identify */
nulldev, /* probe */
bsa_attach, /* attach */
bsa_detach, /* detach */
nulldev, /* reset */
&bsa_cb_ops, /* driver operations */
0,
};
/*
* The following is used for buffers allocated by ddi_dma_mem_alloc()
*/
/*
* Several bugs in dma the -1 can not be used for sgllen since it is
* defined as short and the count_max and addr_hi because of the bug
* in the nexus can not be set to FFFFFFF. It will over flow.
*/
static ddi_dma_attr_t dma_attr = {
DMA_ATTR_V0, /* dma_attr version */
0, /* dma_attr_addr_lo */
1, /* dma_attr_align. We do not care */
1, /* dma_attr_burstsizes.We do not care */
1, /* dma_attr_minxfer */
0xFFF, /* dma_attr_sgllen. No limit in I2O */
1, /* dma_attr_granular */
0, /* dma_attr_flags */
};
/*
* For SGL gain, we need one contiguous buffer
*/
static ddi_dma_attr_t dma_attr_sglfrm = {
DMA_ATTR_V0, /* dma_attr version */
0, /* dma_attr_addr_lo */
1, /* dma_attr_align */
1, /* dma_attr_burstsizes */
1, /* dma_attr_minxfer */
1, /* dma_attr_sgllen */
1, /* dma_attr_granular */
0, /* dma_attr_flags */
};
/*
* For LCT table. We need one contiguous buffer
*/
static ddi_dma_attr_t dma_attr_lcttbl = {
DMA_ATTR_V0, /* dma_attr version */
0, /* dma_attr_addr_lo */
1, /* dma_attr_align */
1, /* dma_attr_burstsizes */
1, /* dma_attr_minxfer */
1, /* dma_attr_sgllen */
1, /* dma_attr_granular */
0, /* dma_attr_flags */
};
/* DMA access attributes */
static ddi_device_acc_attr_t accattr = {
};
extern struct mod_ops mod_driverops;
&mod_driverops, /* Type of module. This one is a driver */
"I2O Block Storage OSM %I%",
&bsa_ops, /* driver ops */
};
static struct modlinkage modlinkage = {
};
/*
* Set up the message
* - set up the Standard Message frame fields:
* MsgFlags, InitiatorContext, Function, msgsize and TID
* MsgFlags need to be 0x2 in case of 64 bit
*/
{ \
acc_hdl); \
}
int
_init(void)
{
int status;
return (status);
return (status);
}
int
_fini(void)
{
int status;
if (!status)
return (status);
}
int
{
}
/*
* The Block storage strategy routine
*/
int
{
int instance;
unsigned long absblkno;
int bind = 0;
int sgbind = 0;
int flags;
int sgsize;
int numsgl;
int ret = 0;
int part;
#ifdef lint
sgl_acchdl = NULL;
#endif
/*
* get instance number
*/
goto out;
}
goto out;
}
" head = %d" "sec = %d\n",
/*
* Reject CD write commands.
*/
goto out;
}
/*
* Map block number within partition to absolute
* block number.
*/
"%s block %d mapped to %ld dev %lx\n",
"invalid slice bp 0x%x\n", bp));
goto out;
}
/*
* Make sure we don't run off the end of a partition.
*/
"secnt = %d count = %d part = %d b_bcount =%d\n",
if (count >= 0) {
} else {
"I/O attempted beyond the end of partition"));
goto out;
}
}
}
/*
* Allocate transaction context
*/
KM_SLEEP);
bind = 0;
sgbind = 0;
goto out;
}
switch (ret) {
case DDI_DMA_MAPPED:
/*
* This flag used in case of error to unbind the DMA handle
* The address is bound to DMA handle
*/
bind = 1;
break;
case DDI_DMA_NORESOURCES:
goto out;
case DDI_DMA_INUSE:
case DDI_DMA_TOOBIG:
goto out;
case DDI_DMA_NOMAPPING:
default:
goto out;
}
/*
* Allocate a message frame from IOP's inbound queue
* Sleep until the resource is available
*/
"resource not available\n");
goto out;
}
/*
* Note that the MessageSize is multiples of 4 byte, hence the shift
*/
(sizeof (i2o_message_frame_t) +
sizeof (i2o_transaction_context_t) +
sizeof (i2o_bsa_read_flags_t) +
(2 * (sizeof (uint8_t)))+
sizeof (uint32_t) +
sizeof (uint64_t));
/*
* If we can not fit all the SGL elements in the Frame we need to
* create a SGL chain which will contain all the SGL elements.
*/
/* we can place the SGL within the MSG frame */
} else {
/*
* allocate buffer to hold the SGL list.
* I2O only accepts one SGL chain buf. So we
* need one contigous segment. (1 cookie).
*/
!= DDI_SUCCESS) {
"available\n");
if (msgbuf)
goto out;
}
"available\n");
if (msgbuf)
goto out;
}
&dma_sgcookie, &sgncookies);
/*
* This flag used in case of error to unbind
*/
switch (ret) {
case DDI_DMA_MAPPED:
/*
* This flag used in case of error to unbind the DMA
* handle The address is bound to DMA handle
*/
sgbind = 1;
break;
case DDI_DMA_NORESOURCES:
" No DMA resources available\n");
if (msgbuf)
goto out;
case DDI_DMA_INUSE:
case DDI_DMA_TOOBIG:
if (msgbuf)
goto out;
case DDI_DMA_NOMAPPING:
default:
" DMA failed 0x%x\n", ret);
if (msgbuf)
goto out;
}
/*
* In the MSG frame initialize the chain element and
* followed by sgl_ignore element (this seems necessary?)
*/
/* set the SGL list pointer to the allocated buffer */
numsgl = 2;
}
/*
* copy the cookies to the SGL list.
*/
while (nocookies) {
if (!(--nocookies)) {
break;
}
sgl++;
}
/*
* Set up the Standard Message frame fields
*/
sizeof (i2o_bsa_write_message_t) +
(numsgl * sizeof (i2o_sge_simple_element_t)) -
sizeof (i2o_sg_element_t));
/*
* Set the Transaction Context field (used for reply correlation)
*/
#else
#endif
goto out;
}
/*
* Wait until the reply is done
* do a cv_wait here from reply
*/
"block %ld failed. det Error 0x%x."
"Operation on block <%d> maped to %ld failed."
"%s block %d mapped to %ld dev %lx\n",
goto out;
}
/*
* free up the resources (unbind, free buff, free handle).
*/
if (sgbind)
if (sglbuf)
if (tcontextp)
if (tcontextp->dma_sghandle)
if (bind)
if (tcontextp)
if (tcontextp->dma_handle)
if (tcontextp)
/*
* In Intel land if the disk block to be written to is disk block 0,
* it would mean the partition table is changing from underneath us
* we shoud trap and update the in memory image.
* By now the buffer is mapped in and we should be able to
* use the contents as the new fdisk partition.
*/
#if defined(_SUNOS_VTOC_16)
}
#endif
return (0);
out:
/* return FAILURE */
if (sgbind)
if (sglbuf)
if (tcontextp)
if (tcontextp->dma_sghandle)
if (bind)
if (tcontextp)
if (tcontextp->dma_handle)
if (tcontextp)
return (0);
}
/*
* Redo the vtoc. This is done whenever the vtoc is changes under us.
*/
static int
{
int status;
char *secbuf;
/*
* Allocate a temporary block for labeling use.
*/
/*
* Free the temporary block allocated for labeling purposes
*/
if (status == DDI_FAILURE)
return (EFAULT);
else
return (0);
}
/*
* Update the vtoc
*/
static int
{
char *secbuf;
/*
* Get a dev with specific minor number
*/
/*
* Allocate a temporary block for labeling use.
*/
/*
* Free the temporary block allocated for labeling purposes
*/
return (0);
}
/*
* Write the Vtoc
*/
static int
{
int status;
char *secbuf;
/*
* Allocate a temporary block for labeling use.
*/
/*
* Free the temporary block allocated for labeling purposes
*/
return (status);
}
/*
* Reply call back function
*/
static void
{
int detstatus; /* detailed status */
int reqstatus; /* request status */
/*
* Correlate replies with appropriate request, based on
* the content of the Transaction Context field. 3.4.1.2.1
* Used context structure in strategy routine. Which bp is part
* of it.
*/
/*
* Get the Transacton Context field
*/
#else
#endif
/*
* Detailed status
*/
/*
* reply status
*/
/*
* Let the strategy routine to continue
*/
}
/*
* Translate the error
*/
#ifdef BSA_DEBUG
struct err_map {
int errorval;
char *errstr;
};
static struct err_map i2o_errtab[] = {
"SUCCESS" },
"ABORT_DIRTY" },
"ABORT_NO_DATA_TRANSFER" },
"ABORT_PARTIAL_TRANSFER" },
"ERROR_DIRTY" },
"ERROR_NO_DATA_TRANSFER" },
"ERROR_PARTIAL_TRANSFER" },
"PROCESS_ABORT_DIRTY" },
"PROCESS_ABORT_NO_DATA_TRANSFER" },
"PROCESS_ABORT_PARTIAL_TRANSFER" },
"TRANSACTION_ERROR" },
"PROGRESS_REPORT" },
};
static struct err_map util_errtab[] = {
"SUCCESS" },
"BAD_KEY" },
"TCL_ERROR" },
"REPLY_BUFFER_FULL" },
"NO_SUCH_PAGE" },
"INSUFFICIENT_RESOURCE_SOFT" },
"INSUFFICIENT_RESOURCE_HARD" },
"CHAIN_BUFFER_TOO_LARGE" },
"UNSUPPORTED_FUNCTION" },
"DEVICE_LOCKED" },
"DEVICE_RESET" },
"INAPPROPRIATE_FUNCTION" },
"INVALID_INITIATOR_ADDRESS" },
"INVALID_MESSAGE_FLAGS" },
"INVALID_OFFSET" },
"INVALID_PARAMETER" },
"INVALID_REQUEST" },
"INVALID_TARGET_ADDRESS" },
"MESSAGE_TOO_LARGE" },
"MESSAGE_TOO_SMALL" },
"MISSING_PARAMETER" },
"TIMEOUT" },
"UNKNOWN_ERROR" },
"UNKNOWN_FUNCTION" },
"UNSUPPORTED_VERSION" },
"DEVICE_BUSY" },
"DEVICE_NOT_AVAILABLE" },
};
static struct err_map bsa_errtab[] = {
"SUCCESS" },
"MEDIA_ERROR" },
"ACCESS_ERROR" },
"DEVICE_FAILURE" },
"DEVICE_NOT_READY" },
"MEDIA_NOT_PRESENT" },
"MEDIA_LOCKED" },
"MEDIA_FAILURE" },
"PROTOCOL_FAILURE" },
"BUS_FAILURE" },
"ACCESS_VIOLATION" },
"WRITE_PROTECTED" },
"DEVICE_RESET" },
"VOLUME_CHANGED" },
"TIMEOUT" },
};
#endif
/*
* Translate the error
*/
/*ARGSUSED*/
static int
{
#ifdef BSA_DEBUG
char *bsastr = "Unknown reason";
char *i2ostr = "Unknown reason";
char *utilstr = "Unknown reason";
int i;
#endif
if (reqstatus == I2O_REPLY_STATUS_SUCCESS &&
return (0);
#ifdef BSA_DEBUG
for (i = 0; i < sizeof (i2o_errtab)/sizeof (struct err_map); i++) {
break;
}
}
/*
* Util functions Detailed error
*/
if (utilflag) {
for (i = 0; i < sizeof (util_errtab)/sizeof (struct err_map);
i++) {
break;
}
}
} else {
for (i = 0; i < sizeof (bsa_errtab)/sizeof (struct err_map);
i++) {
break;
}
}
}
if (utilflag) {
} else {
}
#endif
return (EIO);
}
/*
* attach routine for Block Stroage
*/
static int
{
int instance;
int mask = 0;
/*
* resume from a checkpoint none of the DDM provided this so just ignor
*/
if (cmd == DDI_RESUME) {
/*
* Power Up, load: power up the device completely and load
* medium, if present. We assume all the pointers are
* correct. Since we are resuming
*/
return (DDI_FAILURE);
return (DDI_SUCCESS);
}
if (cmd != DDI_ATTACH) {
"returning FAILURE\n"));
return (DDI_FAILURE);
}
/*
* register the OSM with the IOP
*/
return (DDI_FAILURE);
}
/*
* Get the size of LCT
*/
DDI_FAILURE) {
goto out;
}
/*
* allocate buffer for LCT table
*/
goto out;
}
!= DDI_SUCCESS) {
goto out;
}
/*
* Get a copy of LCT
*/
DDI_FAILURE) {
goto out;
}
"i2o-device-id", -1)) == -1) {
goto out;
}
/*
* Allocate soft state associated with this instance.
*/
"Unable to alloc state\n"));
goto out;
}
/* Initialize the conditional variable and the mutex */
/*
* parse the lct table to find out if the device is free or not
*/
goto out;
}
/*
* Create minor nodes.
*/
goto out;
}
/* get the capacity and type */
goto out;
}
/*
* read the label
*/
goto out;
}
/*
* Register to receive event notification
*/
/* free up the resources */
return (DDI_SUCCESS);
out:
/*
* release all dma resources
*/
if (buf)
if (dma_handle)
if (bsadata) {
if (UtilClaim_release(bsadata)) {
"unclaim the %d device\n",
}
/*
* free the soft_state structure here.
*/
}
if (handle)
return (DDI_FAILURE);
}
/*
* The detach routine for Block Storage
*/
static int
{
int event;
if (cmd == DDI_SUSPEND) {
/*
* Power down, unload: fully power down the device, unloading
* the volume, if present.
*/
return (DDI_FAILURE);
return (DDI_SUCCESS);
}
if (cmd != DDI_DETACH)
return (EINVAL);
/*
* Stop receiving any events of any category
*/
event = 0;
"events from IOP\n");
return (DDI_FAILURE);
}
/*
* Clean Wild Abort. Abort all messages form this initiator
* (any function, and TransactionContext).
*/
return (DDI_FAILURE);
}
/*
* Release the device that Claimed in attach
*/
if (UtilClaim_release(bsadata)) {
return (DDI_FAILURE);
}
/*
* Remove all the minor nodes for this dip
*/
/*
* free the soft_state structure here.
*/
return (DDI_SUCCESS);
}
/*
* Parse the LCT to find the target id in bsadata. If the target id is
* available claim it.
*/
/*ARGSUSED3*/
static int
{
int ent;
int class; /* Class of the device */
int localtid; /* The TID of the device */
int usertid; /* User TID */
int ret = 0;
/*
* get number of entries in the table
*/
"parse_lct: number entries in the LCT = %d", ent));
while (ent) {
if (class & I2O_CLASS_RANDOM_BLOCK_STORAGE) {
/* Find the device by matching TID */
/* If device is available claim it */
if (usertid == 0xFFF) {
"could not claim the device"
return (ret);
}
} else {
"could not claim the device 0x%x."
"Device not available\n",
return (-1);
}
break;
}
}
ent--;
lctp++;
}
return (0);
}
/*
* The open routine for Block storage
*/
/*ARGSUSED*/
static int
{
int instance;
int ret = 0;
/*
* get instance number
*/
return (ENXIO);
}
}
if (ISREMOVABLE(bsadata)) {
return (EROFS); /* read only filesys */
}
/* lock the device (close the door) on first open */
return (ret);
}
return (0);
}
/*
* The close routine for Block Storage
*/
/*ARGSUSED*/
static int
{
/*
* get instance number
*/
if (ISREMOVABLE(bsadata)) {
return (ENXIO);
}
if (ISREMOVABLE(bsadata))
(void) BsaMediaEject(bsadata);
}
}
return (0);
}
/*
* Convert the dev information
*/
/*ARGSUSED*/
static int
void **result)
{
switch (infocmd) {
case DDI_INFO_DEVT2DEVINFO:
return (DDI_FAILURE);
error = DDI_SUCCESS;
break;
case DDI_INFO_DEVT2INSTANCE:
error = DDI_SUCCESS;
break;
default:
error = DDI_FAILURE;
}
return (error);
}
static struct driver_minor_data {
char *name;
int minor;
int type;
} bsa_minor_data[] = {
{ "a", 0, S_IFBLK},
{ "a,raw", 0, S_IFCHR},
#if defined(_SUNOS_VTOC_16)
#endif
{0}
};
/*
* Create the minor node for Block storage device
*/
static int
{
char *node_type;
char name[48];
struct driver_minor_data *dmdp;
else
return (DDI_FAILURE);
}
}
return (DDI_SUCCESS);
}
/*
* Print routine for Block storage device
*/
static int
{
int instance;
/*
* get instance number
*/
return (ENXIO);
}
return (0);
}
/*
* Used the minphys (MAX transfer for the system) for the MAX transfer since
* the OSM sends everthing to IOP. It is the responsibility of HDM or ISM
* (DDM) to take care of limitation of the device.
*/
static int
{
register int secmask;
"file offset not modulo %d\n", DEV_BSIZE));
return (EINVAL);
"transfer length not modulo %d\n", DEV_BSIZE));
return (EINVAL);
}
}
/*
* Read routine for Block Storage device
*/
/*ARGSUSED2*/
static int
{
}
/*
* Write routine for Block Storage device
*/
/*ARGSUSED2*/
static int
{
}
/*
* Dump routine for Block Storage device
*/
static int
{
int instance;
/*
* get instance number
*/
if (!bsadata) {
return (ENXIO);
}
(void) bsa_strategy(bp);
for (;;) {
drv_usecwait(1000);
else
return (0);
}
}
}
/*
* Get device parameters. This is where BSA acquire device information
*/
static int
{
int sg2bind = 0;
int sgbind = 0;
uint_t sg2ncookies = 0;
uint_t sgncookies = 0;
void *resptr; /* opaque ptr */
int ret = DDI_SUCCESS;
versionoffset = 0x71;
#else
versionoffset = 0x51;
#endif
/*
* Allocate a message frame from IOP's inbound queue
* Sleep until the resource is available
*/
"resource not available\n");
return (-1);
}
/*
* Set up the Standard Message frame fields
*/
(2 * sizeof (i2o_sge_simple_element_t)) -
sizeof (i2o_sg_element_t));
/*
* Set the Transaction Context field (used for reply correlation)
*/
tcontextp = (struct bsa_context *)
#else
#endif
/*
* Allocate buffer for the Operation list which consist of
* Operation_list_header and operation_specific_template
* Later on may want to use immediate Data Element.
*/
"available\n");
if (msgbuf)
goto out;
}
(sizeof (i2o_param_operations_list_header_t) +
sizeof (i2o_param_operation_all_template_t)),
!= DDI_SUCCESS) {
"available\n");
if (msgbuf)
goto out;
}
/*
* Initialize the Operation Block structure.
* We only have one operation (which is for SCALAR INFO) so the
* Operationcount is 1
*/
+ sizeof (i2o_param_operations_list_header_t));
/*
* For now lets return all fields we have 64-12 bytes available
*/
&dma_sgcookie, &sgncookies);
switch (ret) {
case DDI_DMA_MAPPED:
/*
* This flag used in case of error to unbind the DMA
* handle The address is bound to DMA handle
*/
sgbind = 1;
break;
case DDI_DMA_NORESOURCES:
" No DMA resources available\n");
if (msgbuf)
goto out;
case DDI_DMA_INUSE:
case DDI_DMA_TOOBIG:
if (msgbuf)
goto out;
case DDI_DMA_NOMAPPING:
default:
" DMA failed 0x%x\n", ret);
if (msgbuf)
goto out;
}
/*
* fill out the first SG element in the frame
*/
/*
* Setup the result buffer.
*/
"available\n");
if (msgbuf)
goto out;
}
/*
* allocate the result buffer
*/
((sizeof (i2o_param_results_list_header_t)) +
(sizeof (i2o_param_read_operation_result_t)) +
(sizeof (i2o_bsa_device_info_scalar_t)) +
(sizeof (i2o_param_error_info_template_t))),
!= DDI_SUCCESS) {
"available\n");
if (msgbuf)
goto out;
}
&dma_sg2cookie, &sg2ncookies);
switch (ret) {
case DDI_DMA_MAPPED:
/*
* This flag used in case of error to unbind the DMA
* handle The address is bound to DMA handle
*/
sg2bind = 1;
break;
case DDI_DMA_NORESOURCES:
" No DMA resources available\n");
if (msgbuf)
goto out;
case DDI_DMA_INUSE:
case DDI_DMA_TOOBIG:
if (msgbuf)
goto out;
case DDI_DMA_NOMAPPING:
default:
" DMA failed 0x%x\n", ret);
if (msgbuf)
goto out;
}
segemp++;
/*
* fill out the second SG element in the frame (The result buf)
*/
/*
* Physical address for resbuf
*/
ret = DDI_FAILURE;
goto out;
}
/*
* do a cv_wait here for reply
*/
goto out;
+ sizeof (i2o_param_results_list_header_t)
+ sizeof (i2o_param_read_operation_result_t));
/*
* Sync the DMA memory
*/
/*
* ParamsGet will be called only from attach(9F).
*/
&resptr1->DeviceType);
"capability = 0x%x capacity = 0x%llx"
"type = 0x%x block size = <%d> <%x>\n",
bsa_unitp->au_blksize));
if (tcontextp->dma_handle) {
}
return (DDI_SUCCESS);
out:
if (tcontextp->dma_handle) {
}
if (sgbind)
if (opbuf)
if (tcontextp->dma_sghandle)
if (sg2bind)
if (resbuf)
if (tcontextp)
return (ret);
}
/*
* The reply message for UtilParamsGet
*/
static void
{
/*
* Get the Transacton Context field
*/
#else
#endif
/*
* Detailed status
*/
/*
* reply status
*/
}
/*
* Claim the BSA device.
*/
static int
{
int ret = DDI_SUCCESS;
ret = 0;
/*
* Allocate a message frame from IOP's inbound queue
* Sleep until the resource is available
*/
"resource not available\n");
return (-1);
}
/*
* Set up the Standard Message frame fields
*/
/*
* For now be the exclusive user
*/
/*
* For now be the primary user
*/
/* Set the Transaction Context field (used for reply correlation) */
tcontextp = (struct bsa_context *)
#else
#endif
return (DDI_FAILURE);
}
/*
* do a cv_wait here for reply
*/
return (ret);
}
/*
* Unclaim the device
*/
static int
{
int ret = DDI_SUCCESS;
/*
* Allocate a message frame from IOP's inbound queue
* Sleep until the resource is available
*/
"resource not available\n");
return (-1);
}
/*
* Set up the Standard Message frame fields
*/
/*
* For now be the primary user
*/
/*
* Set the Transaction Context field (used for reply correlation)
*/
KM_SLEEP);
#else
#endif
return (DDI_FAILURE);
}
/*
* do a cv_wait here for reply
*/
return (ret);
}
/*
* UtilClaim_release reply. The reply routine for UtilClaim_release
*/
static void
{
msg)->TransactiontContext));
#else
msg)->TransactionContext));
#endif
/*
* Detailed status
*/
/*
* reply status
*/
}
/*
* Reply routine for UtilClaim
*/
static void
{
msg)->TransactiontContext));
#else
msg)->TransactionContext));
#endif
/*
* Detailed status
*/
/*
* reply status
*/
}
/*
* Abort specific messages. (ie. TransactionContext)
*/
static int
{
int ret = DDI_SUCCESS;
/*
* Allocate a message frame from IOP's inbound queue
* Sleep until the resource is available
*/
"resource not available\n");
return (-1);
}
/*
* Set up the Standard Message frame fields
*/
#else
#endif
/*
* Set the Transaction Context field (used for reply correlation)
*/
KM_SLEEP);
#else
#endif
return (DDI_FAILURE);
}
/*
* do a cv_wait here for reply
*/
return (ret);
}
/*
* The reply routine for UtilAbort
*/
static void
{
int count;
/*
* Get the Transacton Context field
*/
&(((i2o_util_abort_reply_t *)
msg)->TransactiontContext));
#else
&(((i2o_util_abort_reply_t *)
msg)->TransactionContext));
#endif
/*
* count of aborted messages
*/
&((i2o_util_abort_reply_t *)
}
/*
* Register all the events you want to be informed of
* Note that a single OSM must use the same InitiatorContext and
* TransactionCOntext for all UtilEventRegoster requests (6-14)
*/
static int
{
int ret = DDI_SUCCESS;
/*
* Allocate a message frame from IOP's inbound queue
* Sleep until the resource is available
*/
"resource not available\n");
return (-1);
}
/*
* Set up the Standard Message frame fields
*/
/* Set the Transaction Context field (used for reply correlation) */
#else
#endif
return (DDI_FAILURE);
}
return (ret);
}
/*
* Reply routine for UtilEventRegister routine
*/
static void
{
/*
* Get the Transacton Context field
*/
msg)->TransactiontContext));
#else
msg)->TransactionContext));
#endif
/*
* Event indicator status
*/
msg)->EventIndicator);
switch (eventind) {
"Error Code 0x%x\n", eventdata);
break;
"has changed. Error Code 0x%x\n", eventdata);
break;
break;
"Error Code 0x%x\n", eventdata);
break;
"onto the device\n");
break;
break;
"unloaded\n");
break;
}
}
/*
* This Media Eject routine
*/
static int
{
int ret = DDI_SUCCESS;
/*
* Allocate a message frame from IOP's inbound queue
* Sleep until the resource is available
*/
"resource not available\n");
return (-1);
}
/*
* Set up the Standard Message frame fields
*/
/*
* Eject whatever currently mounted on the drive
*/
/*
* Set the Transaction Context field (used for reply correlation)
*/
KM_SLEEP);
#else
#endif
return (DDI_FAILURE);
}
/*
* do a cv_wait here for reply
*/
return (ret);
}
/*
* Media Eject reply routine
*/
static void
{
/*
* Get the Transacton Context field
*/
msg)->TransactiontContext));
#else
msg)->TransactionContext));
#endif
/*
* Detailed status
*/
/*
* reply status
*/
}
/*
* Power management for I2O
* DDI_RESUME: I2O_BSA_POWER_MGT_POWER_UP_LOAD:
* Power up, load: power up the device completely and load medium,
* if present.
* DDI_SUSPEND: I2O_BSA_POWER_MGT_POWER_DOWN_UNLOAD:
* Power down, unload: fully power down the device, unloading the
* valume, if present.
*/
static int
{
int ret = DDI_SUCCESS;
/*
* Allocate a message frame from IOP's inbound queue
* Sleep until the resource is available
*/
"resource not available\n");
return (-1);
}
/*
* Set up the Standard Message frame fields
*/
/*
* Set the Transaction Context field (used for reply correlation)
*/
KM_SLEEP);
#else
#endif
return (DDI_FAILURE);
}
/*
* do a cv_wait here from reply
*/
return (ret);
}
/*
* Power management reply routine
*/
static void
{
/*
* Get the Transacton Context field
*/
msg)->TransactiontContext));
#else
msg)->TransactionContext));
#endif
/*
* Detailed status
*/
/*
* reply status
*/
}
/*
* The Media lock routine for BSA
*/
static int
{
int ret = DDI_SUCCESS;
/*
* Allocate a message frame from IOP's inbound queue
* Sleep until the resource is available
*/
"resource not available\n");
return (-1);
}
/*
* Set up the Standard Message frame fields
*/
/* Lock whatever currently mounted on the drive */
/*
* Set the Transaction Context field (used for reply correlation)
*/
KM_SLEEP);
#else
#endif
return (DDI_FAILURE);
}
/*
* do a cv_wait here from reply
*/
return (ret);
}
/*
* This is the reply routine for BsaMediaLock
*/
static void
{
/*
* Get the Transacton Context field
*/
msg)->TransactiontContext));
#else
msg)->TransactionContext));
#endif
/*
* Detailed status
*/
/*
* reply status
*/
}
/*
* Unlock the Media
*/
static int
{
int ret = DDI_SUCCESS;
/*
* Allocate a message frame from IOP's inbound queue
* Sleep until the resource is available
*/
"resource not available\n");
return (-1);
}
/*
* Set up the Standard Message frame fields
*/
/*
* Unlock whatever currently mounted on the drive
*/
/*
* Set the Transaction Context field (used for reply correlation)
*/
KM_SLEEP);
#else
#endif
return (DDI_FAILURE);
}
/*
* do a cv_wait here from reply
*/
return (ret);
}
/*
* This function is the reply function for Media unlock request
*/
static void
{
/*
* Get the Transacton Context field
*/
msg)->TransactiontContext));
#else
msg)->TransactionContext));
#endif
/*
* Detailed status
*/
/*
* reply status
*/
}
/*
* This function releases the frame which was allocated by the OSM but was
* not used. This frame usually is freed by IOP after IOP sent the info to
* DDM or ISM. UtilNOP does not have a reply function.
*/
static void
{
/* send the UtilNop message to return the unused Message frame */
}
/*
* Pass the geom information
*/
static void
{
}
#define COPYOUT(a, b, c, f) \
/*
* This function performs all the Block storage ioctls
*/
/*ARGSUSED4*/
static int
int *rval_p)
{
auto long data[512 / (sizeof (long))];
int instance;
/*
* get instance number
*/
return (ENXIO);
}
#ifdef BSA_DEBUG
{
char *cmdname;
switch (cmd) {
default: cmdname = "UNKNOWN *"; break;
}
}
#endif
switch (cmd) {
case DKIOCGGEOM:
case DKIOCSGEOM:
case DKIOCGAPART:
case DKIOCSAPART:
case DKIOCGVTOC:
case DKIOCSVTOC:
return (status);
}
switch (cmd) {
case DKIOCSTATE:
{
enum dkio_state state;
else
else
flag)) {
return (EFAULT);
}
}
break;
case DKIOCINFO:
/*
* Controller Information
*/
/*
* Unit Information
*/
/*
* We can give the OSM's transfer rate, which is
*/
/*
* We can't get from here to there yet
*/
return (EFAULT);
break;
case DKIOCG_VIRTGEOM:
case DKIOCG_PHYGEOM:
{
return (EFAULT);
else
return (0);
}
case DIOCTL_RWCMD:
{
struct dadkio_rwcmd rwcmd;
i = sizeof (rwcmd);
return (EFAULT);
case DADKIO_RWCMD_READ :
case DADKIO_RWCMD_WRITE:
UIO_USERSPACE), rw);
return (status);
default:
return (EINVAL);
}
}
case DKIOCADDBAD:
break;
/*
* Generic lock
*/
case DKIOCLOCK:
return (BsaMediaLock(bsadata));
/*
* Generic unlock
*/
case DKIOCUNLOCK:
return (BsaMediaUnlock(bsadata));
case DKIOCREMOVABLE:
{
int i;
/*
* Get the information from Unit structure.
* The information was gathered at attach time
* through UtilParamsGet()
*/
i = (un->au_devicecapability &
sizeof (int), flag)) {
return (EFAULT);
}
return (0);
}
case DKIOCEJECT:
case CDROMEJECT:
/*
* If it is not a removable media or device this ioctl
* does not exist.
*/
if (!(un->au_devicecapability &
return (ENOSYS);
/*
* First need to unlock before eject
*/
return (ret);
return (BsaMediaEject(bsadata));
case HDKIOCSCMD:
case HDKIOCGDIAG:
break;
default:
return (ENOTTY);
}
return (0);
}
/*
* This function contains all the ioctls for labeling
*/
static int
{
auto long data[512 / (sizeof (long))];
int instance;
int i;
/*
* get instance number
*/
return (ENXIO);
}
/*
* For future hot plugging make sure the device exist
*/
switch (cmd) {
case DKIOCGGEOM:
case DKIOCGAPART:
case DKIOCGVTOC:
return (EFAULT);
}
switch (cmd) {
case DKIOCGGEOM:
{
flag))
return (EFAULT);
break;
}
case DKIOCSGEOM:
i = sizeof (struct dk_geom);
return (EFAULT);
break;
case DKIOCGAPART:
/*
* Return the map for all logical partitions.
*/
return (EFAULT);
}
break;
case DKIOCSAPART:
/*
* Set the map for all logical partitions.
*/
return (EFAULT);
break;
case DKIOCGVTOC:
i = sizeof (struct vtoc);
flag))
return (EFAULT);
else
return (0);
case DKIOCSVTOC:
i = sizeof (struct vtoc);
flag))
return (EFAULT);
return (EFAULT);
}
break;
}
return (0);
}
{
/*
* Our dynamic properties are all device specific and size oriented.
* Requests issued under conditions where size is valid are passed
* to ddi_prop_op_nblocks with the size information, otherwise the
* request is passed to ddi_prop_op. Size depends on valid geometry.
*/
} else {
/* get nblocks value */
}
}
/*
* Setup the capacity and type information
*/
static int
{
/*
* Use 6-43 GroupNumber 0000h and GroupType SCALAR and Name: DEVICE
* INFORMATION. Basically need DeviceType and BlockSize and
* DeviceCapacity. Probably want to setup the SGL here and put hte
* parameters that want to send. If provide one SGL buffer the
* result will be in the payload reply. Decide what you want to do
*/
if (UtilParamsGet(bsadata))
return (DDI_FAILURE);
/*
* bsa_setup will be called from attach and whenver receive an event
* for change of device parameres
*/
else {
/*
* In dadk has DDI_PROB_FAILURE These are WORM and OPTICAL
* that we do not have support under Solaris. We may not
* need to do any extra stuff. that case DKC_DIRECT should
* work.
*/
return (DDI_FAILURE);
}
if (bsa_unitp->au_capacity > 0)
else
return (DDI_FAILURE);
"acyl = %d head = %d"
" sec = %d\n",
return (DDI_SUCCESS);
}
/*
* The following is according to Intel's int13 translation for I2O.
* (This needs more investigation).
*/
#define FIXED_SECSIZE 512
#define FIXED_SECNUM 63
#define FIXED_MAXHEAD 255
static void
{
*secs = FIXED_SECNUM;
*hds = 16;
/* */
/* if (capacity <= (MB)) */
/* *hds = 16; */
/* else if (capacity <= (CAPACITY0)) */
/* *hds *= 2; */
/* else if (capacity <= (CAPACITY1)) */
/* *hds *= 4; */
/* else if (capacity <= (CAPACITY2)) */
/* *hds *= 8; */
/* else if (capacity <= (CAPACITY3)) */
/* *hds = FIXED_MAXHEAD; */
/* else { (capacity > CAPACITY3) */
/* cmn_err(CE_WARN, "?cap_translation: The drive is greater" */
/* "than 8.4 GB. int13 only support up to 8.4 GB \n"); */
/* *hds = FIXED_MAXHEAD; */
/* } */
"head = %d"
" sec = %d\n",
*cyls,
*hds,
*secs));
}
/*
* Setup the read write buffer
*/
static int
{
int status;
/*
* Let physio do the rest...
*/
return (status);
}