summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/io/i2o/i2o_bs.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/io/i2o/i2o_bs.c')
-rw-r--r--usr/src/uts/common/io/i2o/i2o_bs.c3989
1 files changed, 0 insertions, 3989 deletions
diff --git a/usr/src/uts/common/io/i2o/i2o_bs.c b/usr/src/uts/common/io/i2o/i2o_bs.c
deleted file mode 100644
index dc6876a3c1..0000000000
--- a/usr/src/uts/common/io/i2o/i2o_bs.c
+++ /dev/null
@@ -1,3989 +0,0 @@
-/*
- * 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
- * or http://www.opensolaris.org/os/licensing.
- * 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/errno.h>
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/user.h>
-#include <sys/buf.h>
-#include <sys/ioctl.h>
-#include <sys/file.h>
-#include <sys/uio.h>
-#include <sys/kmem.h>
-#include <sys/cmn_err.h>
-#include <sys/debug.h>
-#include <sys/stat.h>
-#include <sys/sysmacros.h>
-
-
-#include <sys/hdio.h>
-#include <sys/dkio.h>
-#include <sys/cdio.h>
-#include <sys/dktp/dadkio.h>
-
-#include <sys/dklabel.h>
-
-#include <sys/vtoc.h>
-
-
-#include <sys/types.h>
-#include <sys/conf.h>
-#include <sys/dditypes.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-
-
-/* BSA specific header files */
-
-#include <sys/i2o/i2omstr.h>
-#include <sys/i2o/i2omsg.h>
-#include <sys/i2o/i2outil.h>
-#include <sys/dktp/fdisk.h>
-#include <sys/dktp/altsctr.h>
-#include "i2o_bs.h"
-
-
-char _depends_on[] = "misc/i2o_msg";
-
-static int bsa_read(dev_t, struct uio *, cred_t *);
-static int bsa_write(dev_t, struct uio *, cred_t *);
-static int bsa_strategy(register struct buf *);
-static int bsa_attach(dev_info_t *, ddi_attach_cmd_t);
-static int bsa_detach(dev_info_t *, ddi_detach_cmd_t);
-static int bsa_open(dev_t *, int, int, cred_t *);
-static int bsa_close(dev_t, int, int, cred_t *);
-static int bsa_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
-static int bsa_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
-static int bsa_prop_op(dev_t, dev_info_t *, ddi_prop_op_t,
- int, char *, caddr_t, int *);
-static int bsa_print(dev_t, char *);
-static int bsa_dump(dev_t, caddr_t, daddr_t, int);
-static int create_minor_node(dev_info_t *, bsa_data_t *);
-static int update_vtoc(struct bsa_data *, dev_t);
-static int redo_vtoc(struct buf *, struct bsa_data *);
-
-
-static int write_dskvtoc(struct bsa_data *, dev_t, dsk_label_t *,
- struct vtoc *, struct cb_ops *);
-static int translate_error(int, int, int);
-static void bsa_reply(void *, ddi_acc_handle_t);
-static int BsaPowerMgt(bsa_data_t *, int);
-static int bsa_buf_setup(void **, dev_t, enum uio_seg, int);
-static void cap_translation(uint64_t, int *, int *, int *);
-static int bsa_setup(struct bsa_data *);
-static int bsa_lbl_ioctl(dev_t, int, int, int);
-static void geom_prep(struct dk_geom *, struct bsa_unit *);
-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 UtilAbort(bsa_data_t *, int, uint8_t, uint64_t);
-static void UtilNOP(i2o_iop_handle_t, ddi_acc_handle_t,
- i2o_common_message_t *, i2o_msg_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 *);
-static int parse_lct(void *, size_t, bsa_data_t *, ddi_acc_handle_t);
-
-
-extern int parse_fdisk_lbl(struct buf *, dsk_label_t *, struct cb_ops *,
- struct dk_geom *, int);
-extern void dsklbl_read_label(struct buf *, dsk_label_t *, struct cb_ops *,
- struct dk_geom *, int type);
-extern int dsklbl_wrvtoc(dsk_label_t *, struct vtoc *, struct buf *,
- struct cb_ops *);
-extern void dsklbl_ondsklabel_to_vtoc(dsk_label_t *, struct vtoc *);
-extern void dsklbl_dgtoug(struct dk_geom *, struct dk_label *);
-extern void dsklbl_ugtodg(struct dk_geom *, struct dk_label *);
-
-/*
- * Debug flag definitions.
- */
-#define I2O_DEBUG_DIO 0x0001 /* disk specific info */
-#define I2O_DEBUG_DINT 0x0002 /* initialization */
-#define I2O_DEBUG_DLBL 0x0004 /* labeling info */
-#define I2O_DEBUG_GEN 0x0008 /* general debugging info */
-#define I2O_DEBUG_BADBLK 0x0009 /* Bad Block Debug */
-
-#ifdef BSA_DEBUG
-int bsa_debug = I2O_DEBUG_DIO;
-
-#define DEBUGF(flag, args) \
- { if (bsa_debug & (flag)) cmn_err args; }
-#else
-#define DEBUGF(level, args) /* nothing */
-#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 */
- D_64BIT|D_NEW | D_MTSAFE, /* driver compatibility flag */
- };
-
-static struct dev_ops bsa_ops = {
- 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,
- };
-
-char *i2o_bsa_name = I2O_BSA_NAME; /* Global not local */
-static void *bsa_soft = NULL;
-
-/*
- * 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 */
- (uint64_t)0xFFFFFFFe, /* dma_attr_addr_hi 64 bit address */
- (uint64_t)0xFFFFFFFe, /* dma_attr_count_max */
- 1, /* dma_attr_align. We do not care */
- 1, /* dma_attr_burstsizes.We do not care */
- 1, /* dma_attr_minxfer */
- (uint64_t)0xFFFFFFFF, /* dma_attr_maxxfer 64 bit address */
- (uint64_t)0xFFFFFFFF, /* dma_attr_seg 64 bit */
- 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 */
- (uint64_t)0xFFFFFFFe, /* dma_attr_addr_hi */
- (uint64_t)0xFFFFFFFe, /* dma_attr_count_max. */
- 1, /* dma_attr_align */
- 1, /* dma_attr_burstsizes */
- 1, /* dma_attr_minxfer */
- (uint64_t)0xFFFFFFFF, /* dma_attr_maxxfer */
- (uint64_t)0xFFFFFFFF, /* dma_attr_seg */
- 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 */
- (uint64_t)0xFFFFFFFe, /* dma_attr_addr_hi */
- (uint64_t)0xFFFFFFFe, /* dma_attr_count_max. 24 bit */
- 1, /* dma_attr_align */
- 1, /* dma_attr_burstsizes */
- 1, /* dma_attr_minxfer */
- (uint64_t)0xFFFFFFFF, /* dma_attr_maxxfer */
- (uint64_t)0xFFFFFFFF, /* dma_attr_seg */
- 1, /* dma_attr_sgllen */
- 1, /* dma_attr_granular */
- 0, /* dma_attr_flags */
-};
-
-
-/* DMA access attributes */
-static ddi_device_acc_attr_t accattr = {
- DDI_DEVICE_ATTR_V0,
- DDI_STRUCTURE_LE_ACC,
- DDI_STRICTORDER_ACC,
-};
-
-#include <sys/modctl.h>
-
-extern struct mod_ops mod_driverops;
-
-static struct modldrv modldrv = {
- &mod_driverops, /* Type of module. This one is a driver */
- "I2O Block Storage OSM %I%",
- &bsa_ops, /* driver ops */
-};
-
-static struct modlinkage modlinkage = {
- MODREV_1, (void *)&modldrv, NULL
-};
-
-/*
- * 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
- */
-
-#define setup_msghdr(func, replyfunc, mp, acc_hdl, veroff, tid, \
- msgflags, msgsize) \
- { \
- put_msg_Function((mp), (func), acc_hdl); \
- (mp)->VersionOffset = (veroff); \
- (mp)->MsgFlags = (msgflags); \
- ddi_put16(acc_handle, \
- &(mp)->MessageSize, (msgsize) >> 2); \
- put_msg_InitiatorAddress((mp), I2O_HOST_TID, \
- acc_hdl); \
- put_msg_TargetAddress((mp), tid, acc_hdl); \
- ddi_put32(acc_hdl, (uint32_t *)&(mp)->InitiatorContext. \
- initiator_context_32bits, (uint32_t)replyfunc); \
- }
-
-int
-_init(void)
-{
- int status;
-
- if (status = mod_install(&modlinkage))
- return (status);
-
- status = ddi_soft_state_init(&bsa_soft, sizeof (struct bsa_data), 1);
-
- return (status);
-}
-
-
-int
-_fini(void)
-{
- int status;
-
- status = mod_remove(&modlinkage);
- if (!status)
- ddi_soft_state_fini(&bsa_soft);
-
- return (status);
-}
-
-int
-_info(struct modinfo *modinfop)
-{
- return (mod_info(&modlinkage, modinfop));
-}
-
-/*
- * The Block storage strategy routine
- */
-
-int
-bsa_strategy(struct buf *bp)
-{
- struct bsa_unit *bsa_unit;
- struct bsa_data *bsadata;
- struct bsa_context *tcontextp = NULL;
- int instance;
- daddr_t blkno;
- unsigned long absblkno;
-
- i2o_msg_handle_t msg_handle;
- ddi_acc_handle_t acc_handle;
- ddi_acc_handle_t sgl_acchdl;
- uint_t nocookies;
- uint_t sgncookies;
- ddi_dma_cookie_t dma_cookie;
- ddi_dma_cookie_t dma_sgcookie;
- int bind = 0;
- int sgbind = 0;
- int flags;
- i2o_sge_simple_element_t *sglbuf = NULL;
- i2o_sge_simple_element_t *sgl = NULL;
- i2o_bsa_write_message_t *msgbuf = NULL;
- int sgsize;
- int numsgl;
- size_t real_length;
- ssize_t resid = 0;
- int ret = 0;
- int part;
- long secnt, count;
-
-#ifdef lint
- sgl_acchdl = NULL;
- acc_handle = sgl_acchdl;
-#endif
- /*
- * get instance number
- */
- instance = UNIT(bp->b_edev);
-
- if (!(bsadata = ddi_get_soft_state(bsa_soft, instance))) {
- ret = ENXIO;
- goto out;
- }
-
- if (bp->b_bcount & (NBPSCTR-1)) {
- ret = ENXIO;
- goto out;
- }
-
-
- bsa_unit = &bsadata->unitp;
-
- DEBUGF(I2O_DEBUG_DIO, (CE_CONT, "?bsa_strategy:cyl = %d acyl = %d"
- " head = %d" "sec = %d\n",
- bsadata->unitp.au_cyl,
- bsadata->unitp.au_acyl,
- bsadata->unitp.au_hd,
- bsadata->unitp.au_sec));
-
- DEBUGF(I2O_DEBUG_DIO, (CE_CONT, "?bsa_strategy:bp->b_private = %d"
- "\n", bp->b_private));
-
- /*
- * Reject CD write commands.
- */
-
- if ((bsadata->unitp.au_type == DKC_CDROM) && !(bp->b_flags & B_READ)) {
- ret = EIO;
- goto out;
- }
-
- if ((bp->b_flags & B_PAGEIO) || (bp->b_flags & B_PHYS))
- bp_mapin(bp);
-
- bp->b_resid = 0;
-
- DEBUGF(I2O_DEBUG_GEN, (CE_CONT, "?bsa_strategy: %s request for buf:"
- "%x\n", bp->b_flags & B_READ ? "read" : "write", bp));
-
- blkno = dkblock(bp);
-
- part = LPART(bp->b_edev);
-
- /*
- * Map block number within partition to absolute
- * block number.
- */
-
- DEBUGF(I2O_DEBUG_DIO, (CE_CONT, "?BS d%d%c%d: "
- "%s block %d mapped to %ld dev %lx\n",
- instance, (part > 15 ? 'p' : 's'),
- (part > 15 ? part - 16 : part),
- bp->b_flags & B_READ ? "read" : "write", blkno,
- blkno + bsadata->lbl.pmap[part].p_start,
- bp->b_edev));
- DEBUGF(I2O_DEBUG_DIO, (CE_CONT, "? p_size = <%ld> <0x%lx>\n",
- bsadata->lbl.pmap[part].p_size,
- bsadata->lbl.pmap[part].p_size));
-
- if (bsadata->lbl.pmap[part].p_flag & V_INVALID) {
- ret = ENXIO;
-
- DEBUGF(I2O_DEBUG_DLBL, (CE_CONT, "?bs_strategy:"
- "invalid slice bp 0x%x\n", bp));
- goto out;
- }
-
-
- /*
- * Make sure we don't run off the end of a partition.
- */
- if ((bsadata->lbl.vtocread == 1) && (bp->b_private != (void *)0xBEE)) {
- secnt = (bp->b_bcount + (DEV_BSIZE - 1)) >> DEV_BSHIFT;
- count = MIN(secnt, (bsadata->lbl.pmap[part].p_size - blkno));
-
- DEBUGF(I2O_DEBUG_DLBL, (CE_CONT, "?bs_strategy:"
- "secnt = %d count = %d part = %d b_bcount =%d\n",
- secnt, count, part, bp->b_bcount));
-
- if (count != secnt) {
- if (count >= 0) {
- resid = (secnt - count) << DEV_BSHIFT;
- cmn_err(CE_CONT, "overrun by %ld sectors\n",
- secnt - count);
- bp->b_bcount -= resid;
- } else {
- DEBUGF(I2O_DEBUG_DLBL, (CE_CONT,
- "I/O attempted beyond the end of partition"));
- ret = ENXIO;
- goto out;
- }
- }
- }
- absblkno = bsadata->lbl.pmap[part].p_start + blkno;
-
- /*
- * Allocate transaction context
- */
-
- tcontextp = (struct bsa_context *)kmem_zalloc(sizeof (bsa_context_t),
- KM_SLEEP);
- tcontextp->bsadata = bsadata;
-
-
- bind = 0;
- sgbind = 0;
-
- if (ddi_dma_alloc_handle(bsadata->dip, &dma_attr, DDI_DMA_SLEEP, 0,
- &tcontextp->dma_handle) != DDI_SUCCESS) {
- cmn_err(CE_CONT, "?BS_strategy: No resources available\n");
- ret = ENOMEM;
- goto out;
- }
-
- flags = (bp->b_flags & B_READ) ? DDI_DMA_READ | DDI_DMA_STREAMING:
- DDI_DMA_WRITE | DDI_DMA_STREAMING;
-
- ret = ddi_dma_buf_bind_handle(tcontextp->dma_handle, bp,
- flags, DDI_DMA_SLEEP, 0, &dma_cookie, &nocookies);
-
- 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:
- ret = ENOMEM;
- cmn_err(CE_CONT, "?bsa_strategy: No DMA resources available\n");
- goto out;
-
- case DDI_DMA_INUSE:
- case DDI_DMA_TOOBIG:
- ret = EINVAL;
- goto out;
-
- case DDI_DMA_NOMAPPING:
- default:
- ret = EFAULT;
- cmn_err(CE_CONT, "?bsa_strategy: DMA failed 0x%x\n", ret);
- goto out;
- }
-
- /*
- * Allocate a message frame from IOP's inbound queue
- * Sleep until the resource is available
- */
-
- if (i2o_msg_alloc(bsadata->iop, I2O_MSG_SLEEP, NULL, (void **)&msgbuf,
- &msg_handle, &acc_handle) == DDI_FAILURE) {
- cmn_err(CE_CONT, "?bsa_strategy: Frame buffer "
- "resource not available\n");
- ret = ENOMEM;
- goto out;
- }
-
- /*
- * Note that the MessageSize is multiples of 4 byte, hence the shift
- */
-
- sgsize = ((ddi_get16(acc_handle,
- &msgbuf->StdMessageFrame.MessageSize)) << 2) -
- (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.
- */
- if (nocookies <= (sgsize/sizeof (i2o_sge_simple_element_t))) {
- /* we can place the SGL within the MSG frame */
- sgl = &msgbuf->SGL.u1.Simple[0];
- sgl_acchdl = acc_handle;
- numsgl = nocookies;
- } else {
- i2o_sge_chain_element_t *sgl_chainp = NULL;
-
- /*
- * allocate buffer to hold the SGL list.
- * I2O only accepts one SGL chain buf. So we
- * need one contigous segment. (1 cookie).
- */
-
- if ((ddi_dma_alloc_handle(tcontextp->bsadata->dip,
- &dma_attr_sglfrm,
- DDI_DMA_SLEEP, 0, &tcontextp->dma_sghandle))
- != DDI_SUCCESS) {
- ret = ENOMEM;
- cmn_err(CE_CONT, "?bsa_strategy: No resources "
- "available\n");
- if (msgbuf)
- UtilNOP(bsadata->iop, acc_handle,
- (i2o_common_message_t *)msgbuf, msg_handle);
- goto out;
-
- }
-
- if ((ddi_dma_mem_alloc(tcontextp->dma_sghandle,
- (size_t)(nocookies * sizeof (i2o_sge_simple_element_t)),
- &accattr, DDI_DMA_STREAMING, DDI_DMA_SLEEP, 0,
- (caddr_t *)&sglbuf, &real_length,
- &tcontextp->acc_sghandle)) != DDI_SUCCESS) {
-
- ret = ENOMEM;
- cmn_err(CE_CONT, "?bsa_strategy: No resources "
- "available\n");
- if (msgbuf)
- UtilNOP(bsadata->iop, acc_handle,
- (i2o_common_message_t *)msgbuf, msg_handle);
- goto out;
- }
-
-
- ret = ddi_dma_addr_bind_handle(tcontextp->dma_sghandle, NULL,
- (caddr_t)sglbuf, real_length,
- DDI_DMA_READ | DDI_DMA_STREAMING, DDI_DMA_SLEEP, 0,
- &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:
- ret = ENOMEM;
- cmn_err(CE_CONT, "?bsa_strategy:"
- " No DMA resources available\n");
- if (msgbuf)
- UtilNOP(bsadata->iop, acc_handle,
- (i2o_common_message_t *)msgbuf, msg_handle);
- goto out;
-
- case DDI_DMA_INUSE:
- case DDI_DMA_TOOBIG:
- ret = ENOMEM;
- if (msgbuf)
- UtilNOP(bsadata->iop, acc_handle,
- (i2o_common_message_t *)msgbuf, msg_handle);
- goto out;
-
- case DDI_DMA_NOMAPPING:
- default:
- ret = EFAULT;
- cmn_err(CE_CONT, "?bsa_strategy:"
- " DMA failed 0x%x\n", ret);
- if (msgbuf)
- UtilNOP(bsadata->iop, acc_handle,
- (i2o_common_message_t *)msgbuf, msg_handle);
-
- goto out;
- }
-
- /*
- * In the MSG frame initialize the chain element and
- * followed by sgl_ignore element (this seems necessary?)
- */
- sgl_chainp = &msgbuf->SGL.u1.Chain;
-
- put_flags_count_Count(&sgl_chainp[0].FlagsCount,
- real_length, acc_handle);
-
-
- put_flags_count_Flags(&sgl_chainp[0].FlagsCount,
- I2O_SGL_FLAGS_CHAIN_POINTER_ELEMENT, acc_handle);
-
- ddi_put32(acc_handle, &sgl_chainp[0].PhysicalAddress,
- (uint32_t)dma_sgcookie.dmac_address);
-
-
- put_flags_count_Count(&sgl_chainp[1].FlagsCount,
- real_length, acc_handle);
-
-
- put_flags_count_Flags(&sgl_chainp[1].FlagsCount,
- I2O_SGL_FLAGS_IGNORE_ELEMENT | I2O_SGL_FLAGS_LAST_ELEMENT,
- acc_handle);
-
- /* set the SGL list pointer to the allocated buffer */
- sgl = (i2o_sge_simple_element_t *)sglbuf;
- sgl_acchdl = tcontextp->acc_sghandle;
- numsgl = 2;
- }
-
- /*
- * copy the cookies to the SGL list.
- */
-
- while (nocookies) {
- put_flags_count_Count(&sgl->FlagsCount, dma_cookie.dmac_size,
- sgl_acchdl);
- put_flags_count_Flags(&sgl->FlagsCount,
- I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT, sgl_acchdl);
- ddi_put32(acc_handle, &sgl->PhysicalAddress,
- dma_cookie.dmac_address);
-
- if (!(--nocookies)) {
- put_flags_count_Flags(&sgl->FlagsCount,
- I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT |
- I2O_SGL_FLAGS_LAST_ELEMENT |
- I2O_SGL_FLAGS_END_OF_BUFFER, sgl_acchdl);
- break;
- }
-
- ddi_dma_nextcookie(tcontextp->dma_handle, &dma_cookie);
- sgl++;
- }
-
-
- /*
- * Set up the Standard Message frame fields
- */
-
- setup_msghdr((bp->b_flags & B_READ ? I2O_BSA_BLOCK_READ :
- I2O_BSA_BLOCK_WRITE), bsa_reply, &msgbuf->StdMessageFrame,
- acc_handle, 0x81, bsadata->tid, 0,
- sizeof (i2o_bsa_write_message_t) +
- (numsgl * sizeof (i2o_sge_simple_element_t)) -
- sizeof (i2o_sg_element_t));
-
-
- ddi_put32(acc_handle, &msgbuf->TransferByteCount, bp->b_bcount);
- ddi_put64(acc_handle, &msgbuf->LogicalByteAddress,
- (((uint64_t)(absblkno)) * bsa_unit->au_blksize));
-
- ddi_put16(acc_handle, &msgbuf->ControlFlags, 0);
- ddi_put8(acc_handle, &msgbuf->TimeMultiplier, 1);
-
- /*
- * Set the Transaction Context field (used for reply correlation)
- */
-
-#if I2O_64BIT_CONTEXT
- ddi_put64(acc_handle, &msgbuf->TransactionContext,
- (uint32_t)tcontextp);
-#else
- ddi_put32(acc_handle, &msgbuf->TransactionContext,
- (uint32_t)(uintptr_t)tcontextp);
-#endif
-
- if (i2o_msg_send(bsadata->iop, msgbuf, msg_handle) == DDI_FAILURE) {
- cmn_err(CE_CONT, "?bsa_strategy: i2o_msg_send failed");
- ret = ENOMEM;
- goto out;
- }
-
- /*
- * Wait until the reply is done
- * do a cv_wait here from reply
- */
- mutex_enter(&bsadata->bsa_mutex);
- while (!(tcontextp->rwreplyflag & REPLY_DONE))
- cv_wait(&bsadata->rwreply_cv, &bsadata->bsa_mutex);
- mutex_exit(&bsadata->bsa_mutex);
-
- if ((ret = tcontextp->retval) != 0) {
- cmn_err(CE_CONT, "? bsa_strategy:Error %d. Operation on "
- "block %ld failed. det Error 0x%x."
- "\n", ret, absblkno, tcontextp->deterror);
- DEBUGF(I2O_DEBUG_BADBLK, (CE_CONT, "?bsa_strategy:Error %d."
- "Operation on block <%d> maped to %ld failed."
- "det Error %x.\n", ret, dkblock(bp), absblkno,
- tcontextp->deterror));
-
- DEBUGF(I2O_DEBUG_BADBLK, (CE_CONT, "?BS d%d%c%d: "
- "%s block %d mapped to %ld dev %lx\n",
- instance, (part > 15 ? 'p' : 's'),
- (part > 15 ? part - 16 : part),
- bp->b_flags & B_READ ? "read" : "write", dkblock(bp),
- dkblock(bp) + bsadata->lbl.pmap[part].p_start,
- bp->b_edev));
- DEBUGF(I2O_DEBUG_BADBLK, (CE_CONT, "? p_size = <%ld> <0x%lx>\n",
- bsadata->lbl.pmap[part].p_size,
- bsadata->lbl.pmap[part].p_size));
-
- goto out;
- }
-
- /*
- * free up the resources (unbind, free buff, free handle).
- */
- if (sgbind)
- (void) ddi_dma_unbind_handle(tcontextp->dma_sghandle);
- if (sglbuf)
- ddi_dma_mem_free(&tcontextp->acc_sghandle);
- if (tcontextp)
- if (tcontextp->dma_sghandle)
- ddi_dma_free_handle(&tcontextp->dma_sghandle);
- if (bind)
- (void) ddi_dma_unbind_handle(tcontextp->dma_handle);
- if (tcontextp)
- if (tcontextp->dma_handle)
- ddi_dma_free_handle(&tcontextp->dma_handle);
- if (tcontextp)
- kmem_free(tcontextp, sizeof (bsa_context_t));
-
-
- /*
- * 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)
- if (!(bp->b_flags & B_READ) &&
- ((bp->b_flags & B_ERROR) != B_ERROR) && absblkno == 0) {
- (void) redo_vtoc(bp, bsadata);
- }
-#endif
- biodone(bp);
- return (0);
-
-out:
- /* return FAILURE */
-
- if (sgbind)
- (void) ddi_dma_unbind_handle(tcontextp->dma_sghandle);
- if (sglbuf)
- ddi_dma_mem_free(&tcontextp->acc_sghandle);
- if (tcontextp)
- if (tcontextp->dma_sghandle)
- ddi_dma_free_handle(&tcontextp->dma_sghandle);
- if (bind)
- (void) ddi_dma_unbind_handle(tcontextp->dma_handle);
- if (tcontextp)
- if (tcontextp->dma_handle)
- ddi_dma_free_handle(&tcontextp->dma_handle);
- if (tcontextp)
- kmem_free(tcontextp, sizeof (bsa_context_t));
-
-
- bp->b_resid = bp->b_bcount;
- bioerror(bp, ret);
- biodone(bp);
- return (0);
-}
-
-/*
- * Redo the vtoc. This is done whenever the vtoc is changes under us.
- */
-
-static int
-redo_vtoc(struct buf *fdiskbp, struct bsa_data *bsadata)
-{
- struct dk_geom dkg;
- struct buf *bp;
- int status;
- dev_t dev;
- char *secbuf;
-
-
- dev = makedevice(getmajor(fdiskbp->b_edev),
- BSA_SETMINOR(bsadata->instance, FDISK_OFFSET));
-
- DEBUGF(I2O_DEBUG_DLBL, (CE_CONT, "?redo_vtoc: dev = %x\n", dev));
- /*
- * Allocate a temporary block for labeling use.
- */
-
- secbuf = kmem_zalloc(NBPSCTR, KM_SLEEP);
-
- bp = getrbuf(KM_SLEEP);
-
- bp->b_edev = dev;
- bp->b_dev = cmpdev(dev);
- bp->b_flags = B_BUSY;
- bp->b_resid = 0;
- bp->b_bcount = NBPSCTR;
- bp->b_un.b_addr = (caddr_t)secbuf;
-
- DEBUGF(I2O_DEBUG_DLBL, (CE_CONT, "?redo_vtoc"
- "edev = %x dev = %x\n", bp->b_edev, bp->b_dev));
-
- bcopy(fdiskbp->b_un.b_addr, bp->b_un.b_addr, NBPSCTR);
-
- geom_prep(&dkg, &bsadata->unitp);
-
- status = parse_fdisk_lbl(bp, &bsadata->lbl,
- &bsa_cb_ops, &dkg, bsadata->unitp.au_type);
-
- /*
- * Free the temporary block allocated for labeling purposes
- */
- kmem_free(bp->b_un.b_addr, NBPSCTR);
- freerbuf(bp);
-
-
- if (status == DDI_FAILURE)
- return (EFAULT);
- else
- return (0);
-}
-
-/*
- * Update the vtoc
- */
-
-static int
-update_vtoc(struct bsa_data *bsadata, dev_t dev)
-{
- struct dk_geom dkg;
- struct buf *bp;
- dev_t newdev;
- char *secbuf;
-
- /*
- * Get a dev with specific minor number
- */
-
- newdev = makedevice(getmajor(dev),
- BSA_SETMINOR(bsadata->instance, FDISK_OFFSET));
-
- DEBUGF(I2O_DEBUG_DLBL, (CE_CONT, "?update_vtoc newdev = %x\n", newdev));
- /*
- * Allocate a temporary block for labeling use.
- */
-
- secbuf = kmem_zalloc(NBPSCTR, KM_SLEEP);
-
- bp = getrbuf(KM_SLEEP);
-
- bp->b_edev = newdev;
- bp->b_dev = cmpdev(newdev);
- bp->b_flags = B_BUSY;
- bp->b_resid = 0;
- bp->b_bcount = NBPSCTR;
- bp->b_un.b_addr = (caddr_t)secbuf;
-
- DEBUGF(I2O_DEBUG_DLBL, (CE_CONT, "?update_vtoc:"
- "edev = %x newdev = %x\n", bp->b_edev, bp->b_dev));
-
- geom_prep(&dkg, &bsadata->unitp);
- dsklbl_read_label(bp, &bsadata->lbl, &bsa_cb_ops, &dkg,
- bsadata->unitp.au_type);
-
- /*
- * Free the temporary block allocated for labeling purposes
- */
- kmem_free(bp->b_un.b_addr, NBPSCTR);
- freerbuf(bp);
-
- return (0);
-}
-
-
-/*
- * Write the Vtoc
- */
-
-
-static int
-write_dskvtoc(struct bsa_data *bsadata, dev_t dev, dsk_label_t *lblp,
- struct vtoc *vtocp, struct cb_ops *dev_ops)
-{
- struct buf *bp;
- int status;
- char *secbuf;
-
-
- dev = makedevice(getmajor(dev),
- BSA_SETMINOR(bsadata->instance, FDISK_OFFSET));
- /*
- * Allocate a temporary block for labeling use.
- */
- secbuf = kmem_zalloc(NBPSCTR, KM_SLEEP);
-
- bp = getrbuf(KM_SLEEP);
-
- bp->b_edev = dev;
- bp->b_dev = cmpdev(dev);
- bp->b_flags = B_BUSY;
- bp->b_resid = 0;
- bp->b_bcount = NBPSCTR;
- bp->b_un.b_addr = (caddr_t)secbuf;
-
-
- DEBUGF(I2O_DEBUG_DLBL, (CE_CONT, "?write_dskvtoc:"
- "edev = %x dev = %x\n", bp->b_edev, bp->b_dev));
-
- status = dsklbl_wrvtoc(lblp, vtocp, bp, dev_ops);
-
- /*
- * Free the temporary block allocated for labeling purposes
- */
- kmem_free(bp->b_un.b_addr, NBPSCTR);
- freerbuf(bp);
-
- return (status);
-}
-
-
-/*
- * Reply call back function
- */
-
-static void
-bsa_reply(void *msg, ddi_acc_handle_t acc_handle)
-{
-
- bsa_context_t *tcontextp; /* Context field */
- 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
- */
-
-#if I2O_64BIT_CONTEXT
- tcontextp = (bsa_context_t *)ddi_get64(acc_handle,
- &(((i2o_single_reply_message_frame_t *)msg)->TransactionContext));
-#else
- tcontextp = (bsa_context_t *)(uintptr_t)ddi_get32(acc_handle,
- &(((i2o_single_reply_message_frame_t *)msg)->TransactionContext));
-#endif
-
- /*
- * Detailed status
- */
-
- detstatus = ddi_get16(acc_handle,
- &((i2o_single_reply_message_frame_t *)msg)->DetailedStatusCode);
-
- /*
- * reply status
- */
- reqstatus = ((i2o_single_reply_message_frame_t *)msg)->ReqStatus;
-
- tcontextp->retval = translate_error(reqstatus, detstatus, 0);
- tcontextp->deterror = detstatus;
-
- /*
- * Let the strategy routine to continue
- */
-
- mutex_enter(&tcontextp->bsadata->bsa_mutex);
- tcontextp->rwreplyflag |= REPLY_DONE;
- cv_broadcast(&tcontextp->bsadata->rwreply_cv);
- mutex_exit(&tcontextp->bsadata->bsa_mutex);
-}
-
-/*
- * Translate the error
- */
-
-
-#ifdef BSA_DEBUG
-struct err_map {
- int errorval;
- char *errstr;
-};
-
-static struct err_map i2o_errtab[] = {
- { I2O_REPLY_STATUS_SUCCESS,
- "SUCCESS" },
- { I2O_REPLY_STATUS_ABORT_DIRTY,
- "ABORT_DIRTY" },
- { I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER,
- "ABORT_NO_DATA_TRANSFER" },
- { I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER,
- "ABORT_PARTIAL_TRANSFER" },
- { I2O_REPLY_STATUS_ERROR_DIRTY,
- "ERROR_DIRTY" },
- { I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER,
- "ERROR_NO_DATA_TRANSFER" },
- { I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER,
- "ERROR_PARTIAL_TRANSFER" },
- { I2O_REPLY_STATUS_PROCESS_ABORT_DIRTY,
- "PROCESS_ABORT_DIRTY" },
- { I2O_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER,
- "PROCESS_ABORT_NO_DATA_TRANSFER" },
- { I2O_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER,
- "PROCESS_ABORT_PARTIAL_TRANSFER" },
- { I2O_REPLY_STATUS_TRANSACTION_ERROR,
- "TRANSACTION_ERROR" },
- { I2O_REPLY_STATUS_PROGRESS_REPORT,
- "PROGRESS_REPORT" },
-};
-
-
-
-static struct err_map util_errtab[] = {
- { I2O_DETAIL_STATUS_SUCCESS,
- "SUCCESS" },
- { I2O_DETAIL_STATUS_BAD_KEY,
- "BAD_KEY" },
- { I2O_DETAIL_STATUS_TCL_ERROR,
- "TCL_ERROR" },
- { I2O_DETAIL_STATUS_REPLY_BUFFER_FULL,
- "REPLY_BUFFER_FULL" },
- { I2O_DETAIL_STATUS_NO_SUCH_PAGE,
- "NO_SUCH_PAGE" },
- { I2O_DETAIL_STATUS_INSUFFICIENT_RESOURCE_SOFT,
- "INSUFFICIENT_RESOURCE_SOFT" },
- { I2O_DETAIL_STATUS_INSUFFICIENT_RESOURCE_HARD,
- "INSUFFICIENT_RESOURCE_HARD" },
- { I2O_DETAIL_STATUS_CHAIN_BUFFER_TOO_LARGE,
- "CHAIN_BUFFER_TOO_LARGE" },
- { I2O_DETAIL_STATUS_UNSUPPORTED_FUNCTION,
- "UNSUPPORTED_FUNCTION" },
- { I2O_DETAIL_STATUS_DEVICE_LOCKED,
- "DEVICE_LOCKED" },
- { I2O_DETAIL_STATUS_DEVICE_RESET,
- "DEVICE_RESET" },
- { I2O_DETAIL_STATUS_INAPPROPRIATE_FUNCTION,
- "INAPPROPRIATE_FUNCTION" },
- { I2O_DETAIL_STATUS_INVALID_INITIATOR_ADDRESS,
- "INVALID_INITIATOR_ADDRESS" },
- { I2O_DETAIL_STATUS_INVALID_MESSAGE_FLAGS,
- "INVALID_MESSAGE_FLAGS" },
- { I2O_DETAIL_STATUS_INVALID_OFFSET,
- "INVALID_OFFSET" },
- { I2O_DETAIL_STATUS_INVALID_PARAMETER,
- "INVALID_PARAMETER" },
- { I2O_DETAIL_STATUS_INVALID_REQUEST,
- "INVALID_REQUEST" },
- { I2O_DETAIL_STATUS_INVALID_TARGET_ADDRESS,
- "INVALID_TARGET_ADDRESS" },
- { I2O_DETAIL_STATUS_MESSAGE_TOO_LARGE,
- "MESSAGE_TOO_LARGE" },
- { I2O_DETAIL_STATUS_MESSAGE_TOO_SMALL,
- "MESSAGE_TOO_SMALL" },
- { I2O_DETAIL_STATUS_MISSING_PARAMETER,
- "MISSING_PARAMETER" },
- { I2O_DETAIL_STATUS_TIMEOUT,
- "TIMEOUT" },
- { I2O_DETAIL_STATUS_UNKNOWN_ERROR,
- "UNKNOWN_ERROR" },
- { I2O_DETAIL_STATUS_UNKNOWN_FUNCTION,
- "UNKNOWN_FUNCTION" },
- { I2O_DETAIL_STATUS_UNSUPPORTED_VERSION,
- "UNSUPPORTED_VERSION" },
- { I2O_DEATIL_STATUS_DEVICE_BUSY,
- "DEVICE_BUSY" },
- { I2O_DETAIL_STATUS_DEVICE_NOT_AVAILABLE,
- "DEVICE_NOT_AVAILABLE" },
-};
-
-static struct err_map bsa_errtab[] = {
- { I2O_BSA_DSC_SUCCESS,
- "SUCCESS" },
- { I2O_BSA_DSC_MEDIA_ERROR,
- "MEDIA_ERROR" },
- { I2O_BSA_DSC_ACCESS_ERROR,
- "ACCESS_ERROR" },
- { I2O_BSA_DSC_DEVICE_FAILURE,
- "DEVICE_FAILURE" },
- { I2O_BSA_DSC_DEVICE_NOT_READY,
- "DEVICE_NOT_READY" },
- { I2O_BSA_DSC_MEDIA_NOT_PRESENT,
- "MEDIA_NOT_PRESENT" },
- { I2O_BSA_DSC_MEDIA_LOCKED,
- "MEDIA_LOCKED" },
- { I2O_BSA_DSC_MEDIA_FAILURE,
- "MEDIA_FAILURE" },
- { I2O_BSA_DSC_PROTOCOL_FAILURE,
- "PROTOCOL_FAILURE" },
- { I2O_BSA_DSC_BUS_FAILURE,
- "BUS_FAILURE" },
- { I2O_BSA_DSC_ACCESS_VIOLATION,
- "ACCESS_VIOLATION" },
- { I2O_BSA_DSC_WRITE_PROTECTED,
- "WRITE_PROTECTED" },
- { I2O_BSA_DSC_DEVICE_RESET,
- "DEVICE_RESET" },
- { I2O_BSA_DSC_VOLUME_CHANGED,
- "VOLUME_CHANGED" },
- { I2O_BSA_DSC_TIMEOUT,
- "TIMEOUT" },
-};
-
-#endif
-
-/*
- * Translate the error
- */
-
-/*ARGSUSED*/
-static int
-translate_error(int reqstatus, int detstatus, int utilflag)
-{
-#ifdef BSA_DEBUG
- char *bsastr = "Unknown reason";
- char *i2ostr = "Unknown reason";
- char *utilstr = "Unknown reason";
- int i;
-#endif
-
- if (reqstatus == I2O_REPLY_STATUS_SUCCESS &&
- detstatus == I2O_BSA_DSC_SUCCESS)
- return (0);
-
-#ifdef BSA_DEBUG
-
- for (i = 0; i < sizeof (i2o_errtab)/sizeof (struct err_map); i++) {
- if (i2o_errtab[i].errorval == reqstatus) {
- i2ostr = i2o_errtab[i].errstr;
- break;
- }
- }
-
- /*
- * Util functions Detailed error
- */
-
- if (utilflag) {
- for (i = 0; i < sizeof (util_errtab)/sizeof (struct err_map);
- i++) {
- if (util_errtab[i].errorval == detstatus) {
- utilstr = util_errtab[i].errstr;
- break;
- }
- }
- } else {
-
- for (i = 0; i < sizeof (bsa_errtab)/sizeof (struct err_map);
- i++) {
- if (bsa_errtab[i].errorval == detstatus) {
- bsastr = bsa_errtab[i].errstr;
- break;
- }
- }
- }
-
- DEBUGF(I2O_DEBUG_GEN, (CE_CONT, "?i2o_bs: %s. Error code = 0x%x\n",
- i2ostr, reqstatus));
-
-
- if (utilflag) {
- DEBUGF(I2O_DEBUG_GEN, (CE_CONT, "?I2o_bs: %s. Error code = 0x%x"
- " \n", utilstr, detstatus));
- } else {
- DEBUGF(I2O_DEBUG_GEN, (CE_CONT, "?I2o_bs: %s. Error code = 0x%x"
- " \n", bsastr, detstatus));
- }
-#endif
- return (EIO);
-}
-
-
-/*
- * attach routine for Block Stroage
- */
-
-
-static int
-bsa_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
-{
-
- i2o_iop_handle_t handle = NULL; /* IOP handle to be initialized. */
- uint_t tid; /* Target id of I2O device */
- caddr_t *buf = NULL; /* Buffer that keeps the LCT table */
- size_t real_length;
- int instance;
- size_t buf_size = 0;
- size_t lct_size;
- size_t real_size;
- int mask = 0;
- major_t devmajor;
-
- ddi_acc_handle_t acc_handle = NULL;
- ddi_dma_handle_t dma_handle = NULL; /* DMA Handle */
-
- struct bsa_data *bsadata = NULL;
-
- /*
- * 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
- */
-
- instance = ddi_get_instance(dip);
- bsadata = ddi_get_soft_state(bsa_soft, instance);
-
- if (BsaPowerMgt(bsadata, I2O_BSA_POWER_MGT_POWER_UP_LOAD))
- return (DDI_FAILURE);
-
- return (DDI_SUCCESS);
- }
-
- if (cmd != DDI_ATTACH) {
- DEBUGF(I2O_DEBUG_GEN, (CE_CONT, "?bs_attach:"
- "returning FAILURE\n"));
- return (DDI_FAILURE);
- }
-
- /*
- * register the OSM with the IOP
- */
-
- if (i2o_msg_osm_register(dip, &handle) == DDI_FAILURE) {
- cmn_err(CE_CONT, "BSA OSM's registeration failed\n");
- return (DDI_FAILURE);
- }
-
- /*
- * Get the size of LCT
- */
-
- if (i2o_msg_get_lct(handle, NULL, buf_size, &lct_size, &real_size) ==
- DDI_FAILURE) {
- cmn_err(CE_CONT, "Could not acquire the configuration table\n");
- goto out;
- }
-
- /*
- * allocate buffer for LCT table
- */
-
- if (ddi_dma_alloc_handle(dip, &dma_attr_lcttbl,
- DDI_DMA_SLEEP, 0, &dma_handle) != DDI_SUCCESS) {
- cmn_err(CE_CONT, "?bsa_attach: No resources available\n");
- goto out;
- }
-
-
- if (ddi_dma_mem_alloc(dma_handle, lct_size,
- &accattr, DDI_DMA_STREAMING, DDI_DMA_SLEEP, 0,
- (caddr_t *)&buf, &real_length, &acc_handle)
- != DDI_SUCCESS) {
- cmn_err(CE_CONT, "?bsa_attach: No resources available\n");
- goto out;
- }
-
- /*
- * Get a copy of LCT
- */
-
- if (i2o_msg_get_lct(handle, buf, lct_size, NULL, NULL) ==
- DDI_FAILURE) {
- cmn_err(CE_CONT, "could not acquire the configuration table\n");
- goto out;
- }
-
-
- if ((tid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
- "i2o-device-id", -1)) == -1) {
-
- cmn_err(CE_CONT, "?bsa_attach: unable to get the Tid\n");
- goto out;
- }
-
- /*
- * Allocate soft state associated with this instance.
- */
- instance = ddi_get_instance(dip);
- if (ddi_soft_state_zalloc(bsa_soft, instance) != DDI_SUCCESS) {
- DEBUGF(I2O_DEBUG_GEN, (CE_CONT, "?bsa_attach:"
- "Unable to alloc state\n"));
- goto out;
- }
-
- /* Initialize the conditional variable and the mutex */
- bsadata = ddi_get_soft_state(bsa_soft, instance);
- bsadata->dip = dip;
- bsadata->instance = instance;
- bsadata->crashbuf = getrbuf(KM_SLEEP);
-
- bsadata->tid = tid; /* Target ID of the I2O dev */
- bsadata->iop = handle; /* IOP access handle */
- bsadata->open_flag = 0; /* open flag */
-
- cv_init(&bsadata->reply_cv, NULL, CV_DRIVER, NULL);
- cv_init(&bsadata->state_cv, NULL, CV_DRIVER, NULL);
- mutex_init(&bsadata->bsa_mutex, NULL, MUTEX_DRIVER, NULL);
- mutex_init(&bsadata->lbl.mutex, NULL, MUTEX_DRIVER, NULL);
-
- /*
- * parse the lct table to find out if the device is free or not
- */
-
- if (parse_lct(buf, lct_size, bsadata, acc_handle)) {
- goto out;
- }
-
- ddi_report_dev(dip); /* announce the drive */
-
- devmajor = ddi_name_to_major(i2o_bsa_name);
-
- /*
- * Create minor nodes.
- */
- if (create_minor_node(dip, bsadata) == DDI_FAILURE) {
- goto out;
- }
-
- /* get the capacity and type */
-
- if (bsa_setup(bsadata)) {
-
- cmn_err(CE_CONT, "?bsa_attach: Unable to setup geometry\n");
- goto out;
- }
-
- /*
- * read the label
- */
- mutex_enter(&bsadata->lbl.mutex);
- if (update_vtoc(bsadata, makedevice(devmajor,
- BSA_SETMINOR(bsadata->instance, FDISK_OFFSET)))) {
- mutex_exit(&bsadata->lbl.mutex);
- goto out;
- }
- mutex_exit(&bsadata->lbl.mutex);
-
-
- /*
- * Register to receive event notification
- */
-
- mask = I2O_EVENT_IND_STATE_CHANGE | I2O_EVENT_IND_DEVICE_STATE |
- I2O_EVENT_IND_DEVICE_RESET | I2O_EVENT_IND_CAPABILITY_CHANGE |
- I2O_BSA_EVENT_VOLUME_LOAD | I2O_BSA_EVENT_CAPACITY_CHANGE |
- I2O_UTIL_EVENT_ACKNOWLEDGE | I2O_BSA_EVENT_VOLUME_UNLOAD;
-
- if (UtilEventRegister(bsadata, mask))
- cmn_err(CE_CONT, "?Could not register for event notification"
- "for tid = %d\n", bsadata->tid);
-
- /* free up the resources */
- ddi_dma_mem_free(&acc_handle);
- ddi_dma_free_handle(&dma_handle);
-
- return (DDI_SUCCESS);
-
-out:
- /*
- * release all dma resources
- */
-
- if (buf)
- ddi_dma_mem_free(&acc_handle);
-
- if (dma_handle)
- ddi_dma_free_handle(&dma_handle);
-
- if (bsadata) {
- if (bsadata->flags & CLAIMED)
- if (UtilClaim_release(bsadata)) {
- cmn_err(CE_CONT, "?bsa_attach: Unable to"
- "unclaim the %d device\n",
- bsadata->tid);
-
- }
- /*
- * free the soft_state structure here.
- */
- ddi_soft_state_free(bsa_soft, instance);
- }
-
- if (handle)
- i2o_msg_osm_unregister(&handle);
-
- return (DDI_FAILURE);
-
-}
-
-/*
- * The detach routine for Block Storage
- */
-
-static int
-bsa_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
-{
- int instance = ddi_get_instance(devi);
- struct bsa_data *bsadata;
- int event;
-
-
- bsadata = ddi_get_soft_state(bsa_soft, instance);
-
- if (cmd == DDI_SUSPEND) {
- /*
- * Power down, unload: fully power down the device, unloading
- * the volume, if present.
- */
- if (BsaPowerMgt(bsadata, I2O_BSA_POWER_MGT_POWER_DOWN_UNLOAD))
- return (DDI_FAILURE);
-
- return (DDI_SUCCESS);
- }
-
- if (cmd != DDI_DETACH)
- return (EINVAL);
-
- /*
- * Stop receiving any events of any category
- */
- event = 0;
- if (UtilEventRegister(bsadata, event)) {
-
- cmn_err(CE_CONT, "?bs_detach: Unable to stop receiving"
- "events from IOP\n");
- return (DDI_FAILURE);
-
-
- }
-
- /*
- * Clean Wild Abort. Abort all messages form this initiator
- * (any function, and TransactionContext).
- */
-
- if (UtilAbort(bsadata, I2O_ABORT_TYPE_CLEAN_WILD_ABORT, NULL, NULL)) {
- cmn_err(CE_CONT, "?bs_detach: Unable to abort all messages\n");
- return (DDI_FAILURE);
- }
-
- /*
- * Release the device that Claimed in attach
- */
-
- if (UtilClaim_release(bsadata)) {
- cmn_err(CE_CONT, "?bs_detach: Unable to unclaim the %d"
- "device\n", bsadata->tid);
- return (DDI_FAILURE);
-
- }
-
- i2o_msg_osm_unregister(&bsadata->iop);
-
- /*
- * Remove all the minor nodes for this dip
- */
-
- ddi_remove_minor_node(devi, NULL);
-
- mutex_destroy(&bsadata->bsa_mutex);
- mutex_destroy(&bsadata->lbl.mutex);
- /*
- * free the soft_state structure here.
- */
- ddi_soft_state_free(bsa_soft, instance);
-
- DEBUGF(I2O_DEBUG_GEN, (CE_CONT, "?sucessfull detach\n"));
-
- return (DDI_SUCCESS);
-}
-
-
-
-/*
- * Parse the LCT to find the target id in bsadata. If the target id is
- * available claim it.
- */
-
-/*ARGSUSED3*/
-static int
-parse_lct(void * buf, size_t size, bsa_data_t *bsadata,
- ddi_acc_handle_t acc_handle)
-{
-
- i2o_lct_entry_t *lctp; /* pointer to Logical cofiguration table */
- int ent;
- int class; /* Class of the device */
- int localtid; /* The TID of the device */
- int usertid; /* User TID */
- int ret = 0;
-
-
- bsadata->flags &= ~CLAIMED;
- lctp = ((i2o_lct_t *)buf)->LCTEntry;
-
- /*
- * get number of entries in the table
- */
- ent = (size/sizeof (i2o_lct_entry_t));
-
- DEBUGF(I2O_DEBUG_DINT, (CE_CONT, "?parse_lct:"
- "parse_lct: number entries in the LCT = %d", ent));
-
- while (ent) {
-
- class = get_lct_entry_Class(lctp, acc_handle);
- if (class & I2O_CLASS_RANDOM_BLOCK_STORAGE) {
- localtid = get_lct_entry_LocalTID(lctp,
- acc_handle);
-
- /* Find the device by matching TID */
- if (localtid == bsadata->tid) {
- usertid = get_lct_entry_UserTID(lctp,
- acc_handle);
-
- /* If device is available claim it */
- if (usertid == 0xFFF) {
-
- if (ret = UtilClaim(bsadata)) {
- cmn_err(CE_CONT, "?parse_lct:"
- "could not claim the device"
- "0x%x\n", bsadata->tid);
-
- return (ret);
- }
- bsadata->flags |= CLAIMED;
- } else {
- cmn_err(CE_CONT, "?parse_lct:"
- "could not claim the device 0x%x."
- "Device not available\n",
- bsadata->tid);
- return (-1);
-
- }
-
- break;
- }
- }
- ent--;
- lctp++;
- }
-
- return (0);
-}
-
-/*
- * The open routine for Block storage
- */
-
-
-/*ARGSUSED*/
-static int
-bsa_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
-{
- bsa_data_t *bsadata;
- register dev_t dev = *dev_p;
- int instance;
- int ret = 0;
-
- /*
- * get instance number
- */
- instance = UNIT(dev);
-
- if ((bsadata = ddi_get_soft_state(bsa_soft, instance)) == NULL) {
- return (ENXIO);
- }
-
- mutex_enter(&bsadata->lbl.mutex);
- if (bsadata->lbl.vtocread != 1) {
- if (bsadata->lbl.geomread != 1)
- (void) bsa_setup(bsadata);
- (void) update_vtoc(bsadata, dev);
- }
- mutex_exit(&bsadata->lbl.mutex);
-
- mutex_enter(&bsadata->bsa_mutex);
-
- if (ISREMOVABLE(bsadata)) {
- if (flag & FWRITE) {
- if (ISCD(bsadata) || ISWRITEPROTECT(bsadata))
- return (EROFS); /* read only filesys */
- }
- /* lock the device (close the door) on first open */
- if (bsadata->open_flag == 0)
- ret = BsaMediaLock(bsadata);
- bsadata->open_flag |= (1 << LPART(dev));
- if (ISCD(bsadata) && ret != 0)
- return (ret);
- }
- mutex_exit(&bsadata->bsa_mutex);
-
- return (0);
-}
-
-/*
- * The close routine for Block Storage
- */
-
-/*ARGSUSED*/
-static int
-bsa_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
-{
- bsa_data_t *bsadata;
- int instance, ret;
-
-
- /*
- * get instance number
- */
- instance = UNIT(dev);
-
- bsadata = ddi_get_soft_state(bsa_soft, instance);
- if (ISREMOVABLE(bsadata)) {
- mutex_enter(&bsadata->bsa_mutex);
- bsadata->open_flag &= ~(1 << LPART(dev));
- if (bsadata->open_flag == 0) {
-
- ret = BsaMediaUnlock(bsadata);
- if (ISCD(bsadata) && ret != 0) {
- mutex_exit(&(bsadata)->bsa_mutex);
- return (ENXIO);
- }
-
- if (ISREMOVABLE(bsadata))
- (void) BsaMediaEject(bsadata);
-
- mutex_exit(&bsadata->bsa_mutex);
- }
- }
- return (0);
-}
-
-/*
- * Convert the dev information
- */
-
-/*ARGSUSED*/
-static int
-bsa_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void * arg,
- void **result)
-{
- bsa_data_t *bsadata;
-
- dev_t dev;
- int instance, error;
-
- switch (infocmd) {
- case DDI_INFO_DEVT2DEVINFO:
- dev = (dev_t)arg;
- instance = UNIT(dev);
- if ((bsadata = ddi_get_soft_state(bsa_soft, instance)) == NULL)
- return (DDI_FAILURE);
- *result = (void *)bsadata->dip;
- error = DDI_SUCCESS;
- break;
- case DDI_INFO_DEVT2INSTANCE:
- dev = (dev_t)arg;
- instance = UNIT(dev);
- *result = (void *)(uintptr_t)instance;
- 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},
- { "b", 1, S_IFBLK},
- { "c", 2, S_IFBLK},
- { "d", 3, S_IFBLK},
- { "e", 4, S_IFBLK},
- { "f", 5, S_IFBLK},
- { "g", 6, S_IFBLK},
- { "h", 7, S_IFBLK},
- { "a,raw", 0, S_IFCHR},
- { "b,raw", 1, S_IFCHR},
- { "c,raw", 2, S_IFCHR},
- { "d,raw", 3, S_IFCHR},
- { "e,raw", 4, S_IFCHR},
- { "f,raw", 5, S_IFCHR},
- { "g,raw", 6, S_IFCHR},
- { "h,raw", 7, S_IFCHR},
-#if defined(_SUNOS_VTOC_16)
- { "i", 8, S_IFBLK},
- { "j", 9, S_IFBLK},
- { "k", 10, S_IFBLK},
- { "l", 11, S_IFBLK},
- { "m", 12, S_IFBLK},
- { "n", 13, S_IFBLK},
- { "o", 14, S_IFBLK},
- { "p", 15, S_IFBLK},
- { "q", 16, S_IFBLK},
- { "r", 17, S_IFBLK},
- { "s", 18, S_IFBLK},
- { "t", 19, S_IFBLK},
- { "u", 20, S_IFBLK},
- { "i,raw", 8, S_IFCHR},
- { "j,raw", 9, S_IFCHR},
- { "k,raw", 10, S_IFCHR},
- { "l,raw", 11, S_IFCHR},
- { "m,raw", 12, S_IFCHR},
- { "n,raw", 13, S_IFCHR},
- { "o,raw", 14, S_IFCHR},
- { "p,raw", 15, S_IFCHR},
- { "q,raw", 16, S_IFCHR},
- { "r,raw", 17, S_IFCHR},
- { "s,raw", 18, S_IFCHR},
- { "t,raw", 19, S_IFCHR},
- { "u,raw", 20, S_IFCHR},
-#endif
- {0}
-
- };
-
-/*
- * Create the minor node for Block storage device
- */
-
-static int
-create_minor_node(dev_info_t *dip, bsa_data_t *bsadata)
-{
- char *node_type;
- char name[48];
- struct driver_minor_data *dmdp;
-
-
- if (bsadata->unitp.au_type == DKC_CDROM)
- node_type = DDI_NT_CD;
- else
- node_type = DDI_NT_BLOCK;
-
- for (dmdp = bsa_minor_data; dmdp->name != NULL; dmdp++) {
- (void) sprintf(name, "%s", dmdp->name);
- if (ddi_create_minor_node(dip, name, dmdp->type,
- BSA_SETMINOR(bsadata->instance, dmdp->minor),
- node_type, NULL) == DDI_FAILURE) {
- return (DDI_FAILURE);
- }
- }
-
- return (DDI_SUCCESS);
-}
-
-/*
- * Print routine for Block storage device
- */
-
-
-static int
-bsa_print(dev_t dev, char *str)
-{
- int instance;
- struct bsa_data *bsadata;
-
-
- /*
- * get instance number
- */
- instance = UNIT(dev);
-
- if (!(bsadata = ddi_get_soft_state(bsa_soft, instance))) {
- return (ENXIO);
- }
-
-
- cmn_err(CE_NOTE, "bsa_print: target id %d %s", bsadata->tid, str);
- 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
-bsa_rdrw(dev_t dev, struct uio *uio, int flag)
-{
- register int secmask;
- secmask = DEV_BSIZE - 1;
-
- if (uio->uio_loffset & ((offset_t)(secmask))) {
- DEBUGF(I2O_DEBUG_DIO, (CE_CONT, "?bsa_rdrw:"
- "file offset not modulo %d\n", DEV_BSIZE));
- return (EINVAL);
- } else if (uio->uio_iov->iov_len & (secmask)) {
- DEBUGF(I2O_DEBUG_DIO, (CE_CONT, "bsa_rdrw:"
- "transfer length not modulo %d\n", DEV_BSIZE));
- return (EINVAL);
- }
- return (physio(bsa_strategy, (struct buf *)0, dev, flag,
- minphys, uio));
-}
-
-/*
- * Read routine for Block Storage device
- */
-
-/*ARGSUSED2*/
-static int
-bsa_read(dev_t dev, struct uio *uio, cred_t *cred_p)
-{
- return (bsa_rdrw(dev, uio, B_READ));
-}
-
-/*
- * Write routine for Block Storage device
- */
-
-/*ARGSUSED2*/
-static int
-bsa_write(dev_t dev, struct uio *uio, cred_t *cred_p)
-{
- return (bsa_rdrw(dev, uio, B_WRITE));
-}
-
-/*
- * Dump routine for Block Storage device
- */
-
-static int
-bsa_dump(dev_t dev, caddr_t addr, daddr_t blkno, int nblk)
-{
- struct bsa_data *bsadata;
- struct buf *bp;
- int instance;
-
-
- /*
- * get instance number
- */
- instance = UNIT(dev);
-
- bsadata = ddi_get_soft_state(bsa_soft, instance);
-
-
- if (!bsadata) {
- return (ENXIO);
- }
-
- bp = bsadata->crashbuf;
- bp->b_un.b_addr = addr;
- bp->b_edev = dev;
- bp->b_dev = cmpdev(dev);
- bp->b_bcount = nblk * DEV_BSIZE;
- bp->b_flags = B_WRITE | B_PHYS;
- bp->b_blkno = blkno;
- bp->b_private = 0;
- (void) bsa_strategy(bp);
-
- for (;;) {
- drv_usecwait(1000);
- if (bp->b_flags & B_DONE) {
- if (bp->b_flags & B_ERROR)
- return (bp->b_error);
- else
- return (0);
- }
- }
-}
-
-
-/*
- * Get device parameters. This is where BSA acquire device information
- */
-static int
-UtilParamsGet(bsa_data_t *bsadata)
-{
- i2o_msg_handle_t msg_handle;
- ddi_acc_handle_t acc_handle;
- uint_t versionoffset;
- bsa_context_t *tcontextp;
- i2o_sge_simple_element_t *segemp = NULL;
- int sg2bind = 0;
- int sgbind = 0;
- void *resbuf, *opbuf = NULL; /* result buffer */
- size_t real_length;
- uint_t sg2ncookies = 0;
- uint_t sgncookies = 0;
- ddi_dma_cookie_t dma_sgcookie;
- ddi_dma_cookie_t dma_sg2cookie;
- struct bsa_unit *bsa_unitp; /* phsyical characteristics */
- i2o_util_params_get_message_t *msgbuf = NULL;
-
-
- void *resptr; /* opaque ptr */
-
- i2o_bsa_device_info_scalar_t *resptr1;
- i2o_param_operation_all_template_t *opbufptr1;
- i2o_param_operations_list_header_t *opbufptr;
-
- int ret = DDI_SUCCESS;
-
-#if I2O_64BIT_CONTEXT
- versionoffset = 0x71;
-#else
- versionoffset = 0x51;
-#endif
-
- /*
- * Allocate a message frame from IOP's inbound queue
- * Sleep until the resource is available
- */
-
- if (i2o_msg_alloc(bsadata->iop, I2O_MSG_SLEEP, NULL, (void **)&msgbuf,
- &msg_handle, &acc_handle) == DDI_FAILURE) {
- cmn_err(CE_CONT, "?UtilParamsGet: Frame buffer "
- "resource not available\n");
- return (-1);
-
- }
-
- /*
- * Set up the Standard Message frame fields
- */
-
- setup_msghdr(I2O_UTIL_PARAMS_GET, UtilParamsGet_reply,
- &msgbuf->StdMessageFrame, acc_handle, versionoffset,
- bsadata->tid, 0, sizeof (i2o_util_params_get_message_t) +
- (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 *)
- kmem_zalloc(sizeof (bsa_context_t), KM_SLEEP);
-
- tcontextp->bsadata = bsadata;
-
-#if I2O_64BIT_CONTEXT
- ddi_put64(acc_handle, &msgbuf->TransactionContext,
- (uint64_t)tcontextp);
-#else
- ddi_put32(acc_handle, &msgbuf->TransactionContext,
- (uint32_t)(uintptr_t)tcontextp);
-#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.
- */
-
- if ((ddi_dma_alloc_handle(tcontextp->bsadata->dip, &dma_attr_sglfrm,
- DDI_DMA_SLEEP, 0, &tcontextp->dma_sghandle)) != DDI_SUCCESS) {
-
- ret = ENOMEM;
- cmn_err(CE_CONT, "?UtilParamsGet: No resources "
- "available\n");
- if (msgbuf)
- UtilNOP(bsadata->iop, acc_handle,
- (i2o_common_message_t *)msgbuf, msg_handle);
- goto out;
- }
-
-
- if ((ddi_dma_mem_alloc(tcontextp->dma_sghandle,
- (sizeof (i2o_param_operations_list_header_t) +
- sizeof (i2o_param_operation_all_template_t)),
- &accattr, DDI_DMA_STREAMING, DDI_DMA_SLEEP, 0,
- (caddr_t *)&opbuf, &real_length, &tcontextp->acc_sghandle))
- != DDI_SUCCESS) {
-
- ret = ENOMEM;
- cmn_err(CE_CONT, "?UtilParamsGet: No resources "
- "available\n");
- if (msgbuf)
- UtilNOP(bsadata->iop, acc_handle,
- (i2o_common_message_t *)msgbuf, msg_handle);
- goto out;
- }
-
- /*
- * Initialize the Operation Block structure.
- * We only have one operation (which is for SCALAR INFO) so the
- * Operationcount is 1
- */
-
- ddi_put16(tcontextp->acc_sghandle,
- &((i2o_param_operations_list_header_t *)opbuf)->OperationCount, 1);
-
- opbufptr = (void *)((char *)opbuf
- + sizeof (i2o_param_operations_list_header_t));
-
- opbufptr1 = (i2o_param_operation_all_template_t *)opbufptr;
-
- ddi_put16(tcontextp->acc_sghandle,
- &opbufptr1->Operation, I2O_PARAMS_OPERATION_FIELD_GET);
-
- ddi_put16(tcontextp->acc_sghandle,
- &opbufptr1->GroupNumber, I2O_BSA_DEVICE_INFO_GROUP_NO);
-
- /*
- * For now lets return all fields we have 64-12 bytes available
- */
-
- ddi_put16(tcontextp->acc_sghandle, &opbufptr1->FieldCount, -1);
-
-
- ret = ddi_dma_addr_bind_handle(tcontextp->dma_sghandle, NULL,
- (caddr_t)opbuf, real_length,
- DDI_DMA_WRITE | DDI_DMA_STREAMING, DDI_DMA_SLEEP, 0,
- &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:
- ret = ENOMEM;
- cmn_err(CE_CONT, "?UtilParamsGet:"
- " No DMA resources available\n");
- if (msgbuf)
- UtilNOP(bsadata->iop, acc_handle,
- (i2o_common_message_t *)msgbuf, msg_handle);
- goto out;
-
- case DDI_DMA_INUSE:
- case DDI_DMA_TOOBIG:
- ret = ENOMEM;
- if (msgbuf)
- UtilNOP(bsadata->iop, acc_handle,
- (i2o_common_message_t *)msgbuf, msg_handle);
- goto out;
-
- case DDI_DMA_NOMAPPING:
- default:
- ret = EFAULT;
- cmn_err(CE_CONT, "?UtilParamsGet:"
- " DMA failed 0x%x\n", ret);
- if (msgbuf)
- UtilNOP(bsadata->iop, acc_handle,
- (i2o_common_message_t *)msgbuf, msg_handle);
-
- goto out;
- }
-
-
- segemp = msgbuf->SGL.u1.Simple;
-
-
- /*
- * fill out the first SG element in the frame
- */
-
- put_flags_count_Count(&segemp->FlagsCount,
- real_length, acc_handle);
-
- put_flags_count_Flags(&segemp->FlagsCount,
- I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT |
- I2O_SGL_FLAGS_END_OF_BUFFER,
- acc_handle);
-
- ddi_put32(acc_handle, &segemp->PhysicalAddress,
- dma_sgcookie.dmac_address);
-
-
- /*
- * Setup the result buffer.
- */
-
- if ((ddi_dma_alloc_handle(tcontextp->bsadata->dip, &dma_attr_sglfrm,
- DDI_DMA_SLEEP, 0, &tcontextp->dma_sg2handle)) != DDI_SUCCESS) {
-
- ret = ENOMEM;
- cmn_err(CE_CONT, "?UtilParamsGet: No resources "
- "available\n");
- if (msgbuf)
- UtilNOP(bsadata->iop, acc_handle,
- (i2o_common_message_t *)msgbuf, msg_handle);
- goto out;
- }
-
- /*
- * allocate the result buffer
- */
- if ((ddi_dma_mem_alloc(tcontextp->dma_sg2handle,
- ((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))),
- &accattr, DDI_DMA_STREAMING, DDI_DMA_SLEEP, 0,
- (caddr_t *)&resbuf, &real_length, &tcontextp->acc_sg2handle))
- != DDI_SUCCESS) {
-
- ret = ENOMEM;
- cmn_err(CE_CONT, "?UtilParamsGet: No resources "
- "available\n");
- if (msgbuf)
- UtilNOP(bsadata->iop, acc_handle,
- (i2o_common_message_t *)msgbuf, msg_handle);
- goto out;
- }
-
-
- ret = ddi_dma_addr_bind_handle(tcontextp->dma_sg2handle, NULL,
- (caddr_t)resbuf, real_length,
- DDI_DMA_READ | DDI_DMA_STREAMING, DDI_DMA_SLEEP, 0,
- &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:
- ret = ENOMEM;
- cmn_err(CE_CONT, "?UtilParamsGet:"
- " No DMA resources available\n");
- if (msgbuf)
- UtilNOP(bsadata->iop, acc_handle,
- (i2o_common_message_t *)msgbuf, msg_handle);
- goto out;
-
- case DDI_DMA_INUSE:
- case DDI_DMA_TOOBIG:
- ret = ENOMEM;
- if (msgbuf)
- UtilNOP(bsadata->iop, acc_handle,
- (i2o_common_message_t *)msgbuf, msg_handle);
- goto out;
-
- case DDI_DMA_NOMAPPING:
- default:
- ret = EFAULT;
- cmn_err(CE_CONT, "?UtilParamsGet:"
- " DMA failed 0x%x\n", ret);
- if (msgbuf)
- UtilNOP(bsadata->iop, acc_handle,
- (i2o_common_message_t *)msgbuf, msg_handle);
- goto out;
- }
-
- segemp++;
-
- /*
- * fill out the second SG element in the frame (The result buf)
- */
-
- put_flags_count_Count(&segemp->FlagsCount,
- real_length, acc_handle);
-
- put_flags_count_Flags(&segemp->FlagsCount,
- I2O_SGL_FLAGS_LAST_ELEMENT |
- I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT |
- I2O_SGL_FLAGS_END_OF_BUFFER,
- acc_handle);
-
- /*
- * Physical address for resbuf
- */
-
- ddi_put32(acc_handle, &segemp->PhysicalAddress,
- dma_sg2cookie.dmac_address);
-
-
- if (i2o_msg_send(bsadata->iop, msgbuf, msg_handle) == DDI_FAILURE) {
- cmn_err(CE_CONT, "?UtilParamsGet: i2o_msg_send failed");
- ret = DDI_FAILURE;
- goto out;
-
- }
-
- /*
- * do a cv_wait here for reply
- */
-
- mutex_enter(&bsadata->bsa_mutex);
- while (!(tcontextp->replyflag & REPLY_DONE))
- cv_wait(&bsadata->reply_cv, &bsadata->bsa_mutex);
- tcontextp->replyflag &= ~REPLY_DONE;
- mutex_exit(&bsadata->bsa_mutex);
-
- if ((ret = tcontextp->retval) != 0)
- goto out;
-
- resptr = (void *)((char *)resbuf
- + sizeof (i2o_param_results_list_header_t)
- + sizeof (i2o_param_read_operation_result_t));
-
- resptr1 = (i2o_bsa_device_info_scalar_t *)resptr;
-
- /*
- * Sync the DMA memory
- */
-
- (void) ddi_dma_sync(tcontextp->dma_sg2handle, 0, real_length,
- DDI_DMA_SYNC_FORCPU);
-
- /*
- * ParamsGet will be called only from attach(9F).
- */
-
- mutex_enter(&tcontextp->bsadata->bsa_mutex);
-
- bsa_unitp = &tcontextp->bsadata->unitp;
-
- bsa_unitp->au_blksize = ddi_get32(tcontextp->acc_sg2handle,
- &resptr1->BlockSize);
-
- bsa_unitp->au_type = ddi_get8(tcontextp->acc_sg2handle,
- &resptr1->DeviceType);
-
- bsa_unitp->au_capacity =
- ddi_get64(tcontextp->acc_sg2handle,
- &resptr1->DeviceCapacity);
-
- bsa_unitp->au_devicecapability =
- ddi_get32(tcontextp->acc_sg2handle,
- &resptr1->DeviceCapabilitySupport);
-
- mutex_exit(&tcontextp->bsadata->bsa_mutex);
-
- DEBUGF(I2O_DEBUG_DIO, (CE_CONT, "?ParamsGet:"
- "capability = 0x%x capacity = 0x%llx"
- "type = 0x%x block size = <%d> <%x>\n",
- bsa_unitp->au_devicecapability,
- bsa_unitp->au_capacity,
- bsa_unitp->au_type,
- bsa_unitp->au_blksize));
-
-
- if (tcontextp->dma_handle) {
- (void) ddi_dma_unbind_handle(tcontextp->dma_handle);
- ddi_dma_free_handle(&tcontextp->dma_handle);
- }
-
-
- (void) ddi_dma_unbind_handle(tcontextp->dma_sghandle);
-
- ddi_dma_mem_free(&tcontextp->acc_sghandle);
-
- ddi_dma_free_handle(&tcontextp->dma_sghandle);
-
- (void) ddi_dma_unbind_handle(tcontextp->dma_sg2handle);
-
- ddi_dma_mem_free(&tcontextp->acc_sg2handle);
-
- ddi_dma_free_handle(&tcontextp->dma_sg2handle);
-
- kmem_free(tcontextp, sizeof (bsa_context_t));
-
-
- return (DDI_SUCCESS);
-
-out:
-
- if (tcontextp->dma_handle) {
- (void) ddi_dma_unbind_handle(tcontextp->dma_handle);
- ddi_dma_free_handle(&tcontextp->dma_handle);
- }
-
- if (sgbind)
- (void) ddi_dma_unbind_handle(tcontextp->dma_sghandle);
- if (opbuf)
- ddi_dma_mem_free(&tcontextp->acc_sghandle);
- if (tcontextp->dma_sghandle)
- ddi_dma_free_handle(&tcontextp->dma_sghandle);
-
- if (sg2bind)
- (void) ddi_dma_unbind_handle(tcontextp->dma_sg2handle);
- if (resbuf)
- ddi_dma_free_handle(&tcontextp->dma_sg2handle);
-
- if (tcontextp)
- kmem_free(tcontextp, sizeof (bsa_context_t));
-
- return (ret);
-}
-
-/*
- * The reply message for UtilParamsGet
- */
-
-
-
-static void
-UtilParamsGet_reply(void *msg, ddi_acc_handle_t acc_handle)
-{
-
- bsa_context_t *tcontextp;
- int detstatus, reqstatus;
-
- /*
- * Get the Transacton Context field
- */
-
-#if I2O_64BIT_CONTEXT
- tcontextp = (bsa_context_t *)ddi_get64(acc_handle,
- &(((i2o_single_reply_message_frame_t *)msg)->TransactiontContext));
-#else
- tcontextp = (bsa_context_t *)(uintptr_t)ddi_get32(acc_handle,
- &(((i2o_single_reply_message_frame_t *)msg)->TransactionContext));
-#endif
-
- /*
- * Detailed status
- */
- detstatus = ddi_get16(acc_handle,
- &((i2o_single_reply_message_frame_t *)msg)->DetailedStatusCode);
-
- /*
- * reply status
- */
- reqstatus = ddi_get8(acc_handle,
- &((i2o_single_reply_message_frame_t *)
- msg)->ReqStatus);
-
- tcontextp->retval = translate_error(reqstatus, detstatus, 1);
-
- mutex_enter(&tcontextp->bsadata->bsa_mutex);
- tcontextp->replyflag |= REPLY_DONE;
- cv_broadcast(&tcontextp->bsadata->reply_cv);
- mutex_exit(&tcontextp->bsadata->bsa_mutex);
-
-}
-
-/*
- * Claim the BSA device.
- */
-
-static int
-UtilClaim(bsa_data_t *bsadata)
-{
- bsa_context_t *tcontextp;
- ddi_acc_handle_t acc_handle;
- i2o_msg_handle_t msg_handle;
- i2o_util_claim_message_t *msgbuf;
- int ret = DDI_SUCCESS;
-
- ret = 0;
-
- /*
- * Allocate a message frame from IOP's inbound queue
- * Sleep until the resource is available
- */
-
- if (i2o_msg_alloc(bsadata->iop, I2O_MSG_SLEEP, NULL, (void **)&msgbuf,
- &msg_handle, &acc_handle) == DDI_FAILURE) {
- cmn_err(CE_CONT, "?UtilClaim: Frame buffer "
- "resource not available\n");
- return (-1);
-
- }
-
- /*
- * Set up the Standard Message frame fields
- */
-
- setup_msghdr(I2O_UTIL_CLAIM, UtilClaim_reply,
- &msgbuf->StdMessageFrame, acc_handle, 0x01,
- bsadata->tid, 0, sizeof (i2o_util_claim_message_t));
-
-
- /*
- * For now be the exclusive user
- */
- ddi_put16(acc_handle, &msgbuf->ClaimFlags,
- I2O_CLAIM_FLAGS_EXCLUSIVE);
-
- /*
- * For now be the primary user
- */
- ddi_put8(acc_handle, &msgbuf->ClaimType,
- I2O_CLAIM_TYPE_PRIMARY_USER);
-
- /* Set the Transaction Context field (used for reply correlation) */
-
- tcontextp = (struct bsa_context *)
- kmem_zalloc(sizeof (bsa_context_t), KM_SLEEP);
- tcontextp->bsadata = bsadata;
-
-#if I2O_64BIT_CONTEXT
- ddi_put64(acc_handle, &msgbuf->TransactionContext,
- (uint64_t)tcontextp);
-#else
- ddi_put32(acc_handle, &msgbuf->TransactionContext,
- (uint32_t)(uintptr_t)tcontextp);
-#endif
-
- if (i2o_msg_send(bsadata->iop, msgbuf, msg_handle) == DDI_FAILURE) {
- cmn_err(CE_CONT, "?UtilClaim: i2o_msg_send failed");
- return (DDI_FAILURE);
- }
-
- /*
- * do a cv_wait here for reply
- */
- mutex_enter(&bsadata->bsa_mutex);
- while (!(tcontextp->replyflag & REPLY_DONE))
- cv_wait(&bsadata->reply_cv, &bsadata->bsa_mutex);
- tcontextp->replyflag &= ~REPLY_DONE;
- mutex_exit(&bsadata->bsa_mutex);
-
- ret = tcontextp->retval;
-
- kmem_free((caddr_t)tcontextp, sizeof (bsa_context_t));
-
- return (ret);
-}
-
-/*
- * Unclaim the device
- */
-
-static int
-UtilClaim_release(bsa_data_t *bsadata)
-{
- bsa_context_t *tcontextp;
- ddi_acc_handle_t acc_handle;
- i2o_msg_handle_t msg_handle;
-
- i2o_util_claim_release_message_t *msgbuf;
- int ret = DDI_SUCCESS;
-
- /*
- * Allocate a message frame from IOP's inbound queue
- * Sleep until the resource is available
- */
-
- if (i2o_msg_alloc(bsadata->iop, I2O_MSG_SLEEP, NULL, (void **)&msgbuf,
- &msg_handle, &acc_handle) == DDI_FAILURE) {
- cmn_err(CE_CONT, "?UtilClaim_release: Frame buffer "
- "resource not available\n");
- return (-1);
-
- }
-
- /*
- * Set up the Standard Message frame fields
- */
-
- setup_msghdr(I2O_UTIL_CLAIM_RELEASE, UtilClaim_release_reply,
- &msgbuf->StdMessageFrame, acc_handle, 0x01,
- bsadata->tid, 0, sizeof (i2o_util_claim_release_message_t));
-
-
- /*
- * For now be the primary user
- */
- ddi_put8(acc_handle, &msgbuf->ClaimType, I2O_CLAIM_TYPE_PRIMARY_USER);
-
- /*
- * Set the Transaction Context field (used for reply correlation)
- */
-
- tcontextp = (bsa_context_t *)kmem_zalloc(sizeof (bsa_context_t),
- KM_SLEEP);
- tcontextp->bsadata = bsadata;
-
-
-#if I2O_64BIT_CONTEXT
- ddi_put64(acc_handle, &msgbuf->TransactionContext,
- (uint64_t)tcontextp);
-#else
- ddi_put32(acc_handle, &msgbuf->TransactionContext,
- (uint32_t)(uintptr_t)tcontextp);
-#endif
-
- if (i2o_msg_send(bsadata->iop, msgbuf, msg_handle) == DDI_FAILURE) {
- cmn_err(CE_CONT, "?UtilClaim_release: i2o_msg_send failed");
- return (DDI_FAILURE);
- }
-
- /*
- * do a cv_wait here for reply
- */
- mutex_enter(&bsadata->bsa_mutex);
- while (!(tcontextp->replyflag & REPLY_DONE))
- cv_wait(&bsadata->reply_cv, &bsadata->bsa_mutex);
- tcontextp->replyflag &= ~REPLY_DONE;
- mutex_exit(&bsadata->bsa_mutex);
-
- ret = tcontextp->retval;
-
- kmem_free(tcontextp, sizeof (bsa_context_t));
-
- return (ret);
-
-}
-
-
-/*
- * UtilClaim_release reply. The reply routine for UtilClaim_release
- */
-
-static void
-UtilClaim_release_reply(void *msg, ddi_acc_handle_t acc_handle)
-{
-
- bsa_context_t *tcontextp;
- int detstatus, reqstatus;
-
-#if I2O_64BIT_CONTEXT
- tcontextp = (bsa_context_t *)ddi_get64(acc_handle,
- &(((i2o_single_reply_message_frame_t *)
- msg)->TransactiontContext));
-#else
- tcontextp = (bsa_context_t *)(uintptr_t)ddi_get32(acc_handle,
- &(((i2o_single_reply_message_frame_t *)
- msg)->TransactionContext));
-#endif
-
-
- /*
- * Detailed status
- */
- detstatus = ddi_get16(acc_handle,
- &((i2o_single_reply_message_frame_t *)
- msg)->DetailedStatusCode);
-
- /*
- * reply status
- */
- reqstatus = ddi_get8(acc_handle,
- &((i2o_single_reply_message_frame_t *)
- msg)->ReqStatus);
-
- tcontextp->retval = translate_error(reqstatus, detstatus, 1);
-
- mutex_enter(&tcontextp->bsadata->bsa_mutex);
- tcontextp->replyflag |= REPLY_DONE;
- cv_broadcast(&tcontextp->bsadata->reply_cv);
- mutex_exit(&tcontextp->bsadata->bsa_mutex);
-}
-
-/*
- * Reply routine for UtilClaim
- */
-
-static void
-UtilClaim_reply(void *msg, ddi_acc_handle_t acc_handle)
-{
- bsa_context_t *tcontextp;
- int detstatus, reqstatus;
-
-#if I2O_64BIT_CONTEXT
- tcontextp = (bsa_context_t *)ddi_get64(acc_handle,
- &(((i2o_single_reply_message_frame_t *)
- msg)->TransactiontContext));
-#else
- tcontextp = (bsa_context_t *)(uintptr_t)ddi_get32(acc_handle,
- &(((i2o_single_reply_message_frame_t *)
- msg)->TransactionContext));
-#endif
-
- /*
- * Detailed status
- */
- detstatus = ddi_get16(acc_handle,
- &((i2o_single_reply_message_frame_t *)
- msg)->DetailedStatusCode);
- /*
- * reply status
- */
- reqstatus = ddi_get8(acc_handle,
- &((i2o_single_reply_message_frame_t *)
- msg)->ReqStatus);
-
- tcontextp->retval = translate_error(reqstatus, detstatus, 1);
-
- mutex_enter(&tcontextp->bsadata->bsa_mutex);
- tcontextp->replyflag |= REPLY_DONE;
- cv_broadcast(&tcontextp->bsadata->reply_cv);
- mutex_exit(&tcontextp->bsadata->bsa_mutex);
-
-}
-
-/*
- * Abort specific messages. (ie. TransactionContext)
- */
-
-static int
-UtilAbort(bsa_data_t *bsadata, int aborttype, uint8_t functoabort,
- uint64_t TransactionContextToAbort)
-{
- bsa_context_t *tcontextp;
- ddi_acc_handle_t acc_handle;
- i2o_msg_handle_t msg_handle;
- i2o_util_abort_message_t *msgbuf;
- int ret = DDI_SUCCESS;
-
- /*
- * Allocate a message frame from IOP's inbound queue
- * Sleep until the resource is available
- */
-
- if (i2o_msg_alloc(bsadata->iop, I2O_MSG_SLEEP, NULL, (void **)&msgbuf,
- &msg_handle, &acc_handle) == DDI_FAILURE) {
- cmn_err(CE_CONT, "?UtilAbort: Frame buffer "
- "resource not available\n");
- return (-1);
- }
-
- /*
- * Set up the Standard Message frame fields
- */
-
- setup_msghdr(I2O_UTIL_ABORT, UtilAbort_reply,
- &msgbuf->StdMessageFrame, acc_handle, 0x01,
- bsadata->tid, 0, sizeof (i2o_util_abort_message_t));
-
- ddi_put8(acc_handle, &msgbuf->AbortType, aborttype);
-
- ddi_put8(acc_handle, &msgbuf->FunctionToAbort, functoabort);
-
-#if I2O_64BIT_CONTEXT
- ddi_put64(acc_handle, &msgbuf->TransactionContextToAbort,
- TransactionContextToAbort);
-#else
- ddi_put32(acc_handle, &msgbuf->TransactionContextToAbort,
- TransactionContextToAbort);
-
-#endif
-
- /*
- * Set the Transaction Context field (used for reply correlation)
- */
-
- tcontextp = (bsa_context_t *)kmem_zalloc(sizeof (bsa_context_t),
- KM_SLEEP);
- tcontextp->bsadata = bsadata;
-
-
-#if I2O_64BIT_CONTEXT
- ddi_put64(acc_handle, &msgbuf->TransactionContext,
- (uint64_t)tcontextp);
-#else
- ddi_put32(acc_handle, &msgbuf->TransactionContext,
- (uint32_t)(uintptr_t)tcontextp);
-#endif
-
- if (i2o_msg_send(bsadata->iop, msgbuf, msg_handle) == DDI_FAILURE) {
- cmn_err(CE_CONT, "?UtilAbort: i2o_msg_send failed");
- return (DDI_FAILURE);
- }
-
- /*
- * do a cv_wait here for reply
- */
- mutex_enter(&bsadata->bsa_mutex);
- while (!(tcontextp->replyflag & REPLY_DONE))
- cv_wait(&bsadata->reply_cv, &bsadata->bsa_mutex);
- tcontextp->replyflag &= ~REPLY_DONE;
- mutex_exit(&bsadata->bsa_mutex);
-
- kmem_free(tcontextp, sizeof (bsa_context_t));
-
- return (ret);
-}
-
-/*
- * The reply routine for UtilAbort
- */
-
-static void
-UtilAbort_reply(void *msg, ddi_acc_handle_t acc_handle)
-{
-
- bsa_context_t *tcontextp;
- int count;
-
- /*
- * Get the Transacton Context field
- */
-#if I2O_64BIT_CONTEXT
- tcontextp = (bsa_context_t *)ddi_get64(acc_handle,
- &(((i2o_util_abort_reply_t *)
- msg)->TransactiontContext));
-#else
- tcontextp = (bsa_context_t *)(uintptr_t)ddi_get32(acc_handle,
- &(((i2o_util_abort_reply_t *)
- msg)->TransactionContext));
-#endif
-
- /*
- * count of aborted messages
- */
- count = ddi_get32(acc_handle,
- &((i2o_util_abort_reply_t *)
- msg)->CountOfAbortedMessages);
-
- cmn_err(CE_CONT, "?UtilAbort: number of messages aborted 0x%x", count);
-
- mutex_enter(&tcontextp->bsadata->bsa_mutex);
- tcontextp->replyflag |= REPLY_DONE;
- cv_broadcast(&tcontextp->bsadata->reply_cv);
- mutex_exit(&tcontextp->bsadata->bsa_mutex);
-}
-
-/*
- * 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
-UtilEventRegister(bsa_data_t *bsadata, int event)
-{
-
- ddi_acc_handle_t acc_handle;
- i2o_msg_handle_t msg_handle;
- i2o_util_event_register_message_t *msgbuf;
- int ret = DDI_SUCCESS;
-
- mutex_enter(&bsadata->bsa_mutex);
-
- /*
- * Allocate a message frame from IOP's inbound queue
- * Sleep until the resource is available
- */
-
- if (i2o_msg_alloc(bsadata->iop, I2O_MSG_SLEEP, NULL, (void **)&msgbuf,
- &msg_handle, &acc_handle) == DDI_FAILURE) {
- cmn_err(CE_CONT, "?UtilEventRegister: Frame buffer "
- "resource not available\n");
- return (-1);
- }
-
- /*
- * Set up the Standard Message frame fields
- */
-
- setup_msghdr(I2O_UTIL_EVENT_REGISTER, UtilEventRegister_reply,
- &msgbuf->StdMessageFrame, acc_handle, 0x01,
- bsadata->tid, 0, sizeof (i2o_util_event_register_message_t));
-
-
- ddi_put32(acc_handle, &msgbuf->EventMask, event);
-
- /* Set the Transaction Context field (used for reply correlation) */
-
-#if I2O_64BIT_CONTEXT
- ddi_put64(acc_handle, &msgbuf->TransactionContext,
- (uint64_t)bsadata);
-#else
- ddi_put32(acc_handle, &msgbuf->TransactionContext,
- (uint32_t)(uintptr_t)bsadata);
-#endif
-
- if (i2o_msg_send(bsadata->iop, msgbuf, msg_handle) == DDI_FAILURE) {
- cmn_err(CE_CONT, "?UtilEventRegister: i2o_msg_send failed");
- return (DDI_FAILURE);
- }
-
- mutex_exit(&bsadata->bsa_mutex);
-
- return (ret);
-}
-
-/*
- * Reply routine for UtilEventRegister routine
- */
-
-
-static void
-UtilEventRegister_reply(void *msg, ddi_acc_handle_t acc_handle)
-{
-
- uint32_t eventind;
- uint32_t eventdata;
- bsa_data_t *bsadata;
-
- /*
- * Get the Transacton Context field
- */
-#if I2O_64BIT_CONTEXT
- bsadata = (bsa_context_t *)ddi_get64(acc_handle,
- &(((i2o_single_reply_message_frame_t *)
- msg)->TransactiontContext));
-#else
- bsadata = (bsa_data_t *)(uintptr_t)ddi_get32(acc_handle,
- &(((i2o_single_reply_message_frame_t *)
- msg)->TransactionContext));
-#endif
- /*
- * Event indicator status
- */
- eventind = ddi_get32(acc_handle,
- &((i2o_util_event_register_reply_t *)
- msg)->EventIndicator);
-
- switch (eventind) {
-
- case I2O_EVENT_IND_STATE_CHANGE:
- eventdata = ddi_get32(acc_handle,
- ((i2o_util_event_register_reply_t *)
- msg)->EventData);
- cmn_err(CE_CONT, "? The state of the device has changed"
- "Error Code 0x%x\n", eventdata);
- break;
- case I2O_EVENT_IND_DEVICE_STATE:
- eventdata = ddi_get32(acc_handle,
- ((i2o_util_event_register_reply_t *)
- msg)->EventData);
- cmn_err(CE_CONT, "? The generic state of the device"
- "has changed. Error Code 0x%x\n", eventdata);
- break;
- case I2O_EVENT_IND_DEVICE_RESET:
- cmn_err(CE_CONT, "? A device reset has occured\n");
- break;
- case I2O_EVENT_IND_CAPABILITY_CHANGE:
- eventdata = ddi_get32(acc_handle,
- ((i2o_util_event_register_reply_t *)
- msg)->EventData);
- cmn_err(CE_WARN, "?One or more capability has changed."
- "Error Code 0x%x\n", eventdata);
- break;
- case I2O_BSA_EVENT_VOLUME_LOAD:
- cmn_err(CE_CONT, "?New medium has been loaded"
- "onto the device\n");
- mutex_enter(&bsadata->bsa_mutex);
- bsadata->state = DKIO_INSERTED;
- bsadata->flags |= STATE_CHANGE;
- cv_broadcast(&bsadata->state_cv);
- mutex_exit(&bsadata->bsa_mutex);
- break;
- case I2O_BSA_EVENT_CAPACITY_CHANGE:
- cmn_err(CE_WARN, "?The capacity of the device has changed\n");
- break;
- case I2O_BSA_EVENT_VOLUME_UNLOAD:
- cmn_err(CE_CONT, "?The medium on the device has been"
- "unloaded\n");
- mutex_enter(&bsadata->bsa_mutex);
- bsadata->state = DKIO_EJECTED;
- bsadata->flags |= STATE_CHANGE;
- cv_broadcast(&bsadata->state_cv);
- mutex_exit(&bsadata->bsa_mutex);
- break;
- }
-}
-
-/*
- * This Media Eject routine
- */
-
-
-static int
-BsaMediaEject(bsa_data_t *bsadata)
-{
- bsa_context_t *tcontextp;
- ddi_acc_handle_t acc_handle;
- i2o_msg_handle_t msg_handle;
- i2o_bsa_media_eject_message_t *msgbuf;
- int ret = DDI_SUCCESS;
-
-
- /*
- * Allocate a message frame from IOP's inbound queue
- * Sleep until the resource is available
- */
-
- if (i2o_msg_alloc(bsadata->iop, I2O_MSG_SLEEP, NULL, (void **)&msgbuf,
- &msg_handle, &acc_handle) == DDI_FAILURE) {
- cmn_err(CE_CONT, "?BsaMediaEject: Frame buffer "
- "resource not available\n");
- return (-1);
- }
-
- /*
- * Set up the Standard Message frame fields
- */
-
- setup_msghdr(I2O_BSA_MEDIA_EJECT, BsaMediaEject_reply,
- &msgbuf->StdMessageFrame, acc_handle, 0x01,
- bsadata->tid, 0, sizeof (i2o_bsa_media_eject_message_t));
-
- /*
- * Eject whatever currently mounted on the drive
- */
- ddi_put32(acc_handle, &msgbuf->MediaIdentifier,
- I2O_BSA_MEDIA_ID_CURRENT_MOUNTED);
-
- /*
- * Set the Transaction Context field (used for reply correlation)
- */
-
- tcontextp = (bsa_context_t *)kmem_zalloc(sizeof (bsa_context_t),
- KM_SLEEP);
- tcontextp->bsadata = bsadata;
-
-
-#if I2O_64BIT_CONTEXT
- ddi_put64(acc_handle, &msgbuf->TransactionContext,
- (uint64_t)tcontextp);
-#else
- ddi_put32(acc_handle, &msgbuf->TransactionContext,
- (uint32_t)(uintptr_t)tcontextp);
-#endif
-
-
- if (i2o_msg_send(bsadata->iop, msgbuf, msg_handle) == DDI_FAILURE) {
- cmn_err(CE_CONT, "?BsaMediaEject: i2o_msg_send failed");
- return (DDI_FAILURE);
- }
-
- /*
- * do a cv_wait here for reply
- */
- mutex_enter(&bsadata->bsa_mutex);
- while (!(tcontextp->replyflag & REPLY_DONE))
- cv_wait(&bsadata->reply_cv, &bsadata->bsa_mutex);
- tcontextp->replyflag &= ~REPLY_DONE;
- mutex_exit(&bsadata->bsa_mutex);
-
- ret = tcontextp->retval;
-
- kmem_free(tcontextp, sizeof (bsa_context_t));
-
- return (ret);
-}
-
-/*
- * Media Eject reply routine
- */
-
-static void
-BsaMediaEject_reply(void *msg, ddi_acc_handle_t acc_handle)
-{
- bsa_context_t *tcontextp;
- int detstatus, reqstatus;
-
- /*
- * Get the Transacton Context field
- */
-#if I2O_64BIT_CONTEXT
- tcontextp = (bsa_context_t *)ddi_get64(acc_handle,
- &(((i2o_single_reply_message_frame_t *)
- msg)->TransactiontContext));
-#else
- tcontextp = (bsa_context_t *)(uintptr_t)ddi_get32(acc_handle,
- &(((i2o_single_reply_message_frame_t *)
- msg)->TransactionContext));
-#endif
-
- /*
- * Detailed status
- */
- detstatus = ddi_get16(acc_handle,
- &((i2o_single_reply_message_frame_t *)
- msg)->DetailedStatusCode);
-
- /*
- * reply status
- */
- reqstatus = ddi_get8(acc_handle,
- &((i2o_single_reply_message_frame_t *)
- msg)->ReqStatus);
-
- mutex_enter(&tcontextp->bsadata->bsa_mutex);
- if (reqstatus & I2O_REPLY_STATUS_SUCCESS)
- tcontextp->bsadata->state = DKIO_EJECTED;
-
- tcontextp->retval = translate_error(reqstatus, detstatus, 0);
-
- tcontextp->replyflag |= REPLY_DONE;
- cv_broadcast(&tcontextp->bsadata->reply_cv);
- mutex_exit(&tcontextp->bsadata->bsa_mutex);
-}
-
-
-/*
- * 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
-BsaPowerMgt(bsa_data_t *bsadata, int operation)
-{
- bsa_context_t *tcontextp;
- ddi_acc_handle_t acc_handle;
- i2o_msg_handle_t msg_handle;
- i2o_bsa_power_management_message_t *msgbuf;
- int ret = DDI_SUCCESS;
-
- /*
- * Allocate a message frame from IOP's inbound queue
- * Sleep until the resource is available
- */
-
- if (i2o_msg_alloc(bsadata->iop, I2O_MSG_SLEEP, NULL, (void **)&msgbuf,
- &msg_handle, &acc_handle) == DDI_FAILURE) {
- cmn_err(CE_CONT, "?BsaPowerMgt: Frame buffer "
- "resource not available\n");
- return (-1);
- }
-
- /*
- * Set up the Standard Message frame fields
- */
-
- setup_msghdr(I2O_BSA_POWER_MANAGEMENT, BsaPowerMgt_reply,
- &msgbuf->StdMessageFrame, acc_handle, 0x01,
- bsadata->tid, 0, sizeof (i2o_bsa_power_management_message_t));
-
-
- ddi_put8(acc_handle, &msgbuf->Operation, operation);
-
- /*
- * Set the Transaction Context field (used for reply correlation)
- */
-
- tcontextp = (bsa_context_t *)kmem_zalloc(sizeof (bsa_context_t),
- KM_SLEEP);
- tcontextp->bsadata = bsadata;
-
-#if I2O_64BIT_CONTEXT
- ddi_put64(acc_handle, &msgbuf->TransactionContext,
- (uint64_t)tcontextp);
-#else
- ddi_put32(acc_handle, &msgbuf->TransactionContext,
- (uint32_t)(uintptr_t)tcontextp);
-#endif
- ddi_put8(acc_handle, &msgbuf->TimeMultiplier, 1);
-
-
- if (i2o_msg_send(bsadata->iop, msgbuf, msg_handle) == DDI_FAILURE) {
- cmn_err(CE_CONT, "?BsaPowerMgt: i2o_msg_send failed");
- return (DDI_FAILURE);
- }
-
- /*
- * do a cv_wait here from reply
- */
- mutex_enter(&bsadata->bsa_mutex);
- while (!(tcontextp->replyflag & REPLY_DONE))
- cv_wait(&bsadata->reply_cv, &bsadata->bsa_mutex);
- tcontextp->replyflag &= ~REPLY_DONE;
- mutex_exit(&bsadata->bsa_mutex);
-
- ret = tcontextp->retval;
-
- kmem_free(tcontextp, sizeof (bsa_context_t));
-
- return (ret);
-}
-
-/*
- * Power management reply routine
- */
-
-static void
-BsaPowerMgt_reply(void *msg, ddi_acc_handle_t acc_handle)
-{
-
-
- bsa_context_t *tcontextp;
- int detstatus, reqstatus;
-
-
- /*
- * Get the Transacton Context field
- */
-#if I2O_64BIT_CONTEXT
- tcontextp = (bsa_context_t *)ddi_get64(acc_handle,
- &(((i2o_single_reply_message_frame_t *)
- msg)->TransactiontContext));
-#else
- tcontextp = (bsa_context_t *)(uintptr_t)ddi_get32(acc_handle,
- &(((i2o_single_reply_message_frame_t *)
- msg)->TransactionContext));
-#endif
-
- /*
- * Detailed status
- */
- detstatus = ddi_get16(acc_handle,
- &((i2o_single_reply_message_frame_t *)
- msg)->DetailedStatusCode);
-
- /*
- * reply status
- */
- reqstatus = ddi_get8(acc_handle,
- &((i2o_single_reply_message_frame_t *)
- msg)->ReqStatus);
-
- tcontextp->retval = translate_error(reqstatus, detstatus, 0);
-
- mutex_enter(&tcontextp->bsadata->bsa_mutex);
- tcontextp->replyflag |= REPLY_DONE;
- cv_broadcast(&tcontextp->bsadata->reply_cv);
- mutex_exit(&tcontextp->bsadata->bsa_mutex);
-}
-
-/*
- * The Media lock routine for BSA
- */
-
-static int
-BsaMediaLock(bsa_data_t *bsadata)
-{
- bsa_context_t *tcontextp;
- ddi_acc_handle_t acc_handle;
- i2o_msg_handle_t msg_handle;
- i2o_bsa_media_lock_message_t *msgbuf;
- int ret = DDI_SUCCESS;
-
- /*
- * Allocate a message frame from IOP's inbound queue
- * Sleep until the resource is available
- */
-
- if (i2o_msg_alloc(bsadata->iop, I2O_MSG_SLEEP, NULL, (void **)&msgbuf,
- &msg_handle, &acc_handle) == DDI_FAILURE) {
- cmn_err(CE_CONT, "?BsaMediaLock: Frame buffer "
- "resource not available\n");
- return (-1);
- }
-
- /*
- * Set up the Standard Message frame fields
- */
-
- setup_msghdr(I2O_BSA_MEDIA_LOCK, BsaMediaLock_reply,
- &msgbuf->StdMessageFrame, acc_handle, 0x01,
- bsadata->tid, 0, sizeof (i2o_bsa_media_lock_message_t));
-
- /* Lock whatever currently mounted on the drive */
- ddi_put32(acc_handle, &msgbuf->MediaIdentifier,
- I2O_BSA_MEDIA_ID_CURRENT_MOUNTED);
-
- /*
- * Set the Transaction Context field (used for reply correlation)
- */
-
- tcontextp = (bsa_context_t *)kmem_zalloc(sizeof (bsa_context_t),
- KM_SLEEP);
-
- tcontextp->bsadata = bsadata;
-
-#if I2O_64BIT_CONTEXT
- ddi_put64(acc_handle, &msgbuf->TransactionContext, (unit64_t)
- tcontextp);
-#else
- ddi_put32(acc_handle, &msgbuf->TransactionContext,
- (uint32_t)(uintptr_t)tcontextp);
-#endif
-
- if (i2o_msg_send(bsadata->iop, msgbuf, msg_handle) == DDI_FAILURE) {
- cmn_err(CE_CONT, "?BsaMediaLock: i2o_msg_send failed ");
- return (DDI_FAILURE);
- }
-
- /*
- * do a cv_wait here from reply
- */
- mutex_enter(&bsadata->bsa_mutex);
- while (!(tcontextp->replyflag & REPLY_DONE))
- cv_wait(&bsadata->reply_cv, &bsadata->bsa_mutex);
- tcontextp->replyflag &= ~REPLY_DONE;
- mutex_exit(&bsadata->bsa_mutex);
-
- ret = tcontextp->retval;
-
- kmem_free(tcontextp, sizeof (bsa_context_t));
-
- return (ret);
-}
-
-/*
- * This is the reply routine for BsaMediaLock
- */
-
-
-static void
-BsaMediaLock_reply(void *msg, ddi_acc_handle_t acc_handle)
-{
-
-
- bsa_context_t *tcontextp;
- int detstatus, reqstatus;
-
- /*
- * Get the Transacton Context field
- */
-#if I2O_64BIT_CONTEXT
- tcontextp = (bsa_context_t *)ddi_get64(acc_handle,
- &(((i2o_single_reply_message_frame_t *)
- msg)->TransactiontContext));
-#else
- tcontextp = (bsa_context_t *)(uintptr_t)ddi_get32(acc_handle,
- &(((i2o_single_reply_message_frame_t *)
- msg)->TransactionContext));
-#endif
-
- /*
- * Detailed status
- */
- detstatus = ddi_get16(acc_handle,
- &((i2o_single_reply_message_frame_t *)
- msg)->DetailedStatusCode);
-
- /*
- * reply status
- */
- reqstatus = ddi_get8(acc_handle,
- &((i2o_single_reply_message_frame_t *)
- msg)->ReqStatus);
-
- tcontextp->retval = translate_error(reqstatus, detstatus, 0);
-
- mutex_enter(&tcontextp->bsadata->bsa_mutex);
- tcontextp->replyflag |= REPLY_DONE;
- cv_broadcast(&tcontextp->bsadata->reply_cv);
- mutex_exit(&tcontextp->bsadata->bsa_mutex);
-}
-
-/*
- * Unlock the Media
- */
-static int
-BsaMediaUnlock(bsa_data_t *bsadata)
-{
- bsa_context_t *tcontextp;
- ddi_acc_handle_t acc_handle;
- i2o_msg_handle_t msg_handle;
- i2o_bsa_media_unlock_message_t *msgbuf;
- int ret = DDI_SUCCESS;
-
- /*
- * Allocate a message frame from IOP's inbound queue
- * Sleep until the resource is available
- */
- if (i2o_msg_alloc(bsadata->iop, I2O_MSG_SLEEP, NULL, (void **)&msgbuf,
- &msg_handle, &acc_handle) == DDI_FAILURE) {
- cmn_err(CE_CONT, "?BsaMediaUnlock: Frame buffer "
- "resource not available\n");
- return (-1);
- }
-
- /*
- * Set up the Standard Message frame fields
- */
- setup_msghdr(I2O_BSA_MEDIA_UNLOCK, BsaMediaUnlock_reply,
- &msgbuf->StdMessageFrame, acc_handle, 0x01,
- bsadata->tid, 0, sizeof (i2o_bsa_media_unlock_message_t));
-
-
- /*
- * Unlock whatever currently mounted on the drive
- */
- ddi_put32(acc_handle, &msgbuf->MediaIdentifier,
- I2O_BSA_MEDIA_ID_CURRENT_MOUNTED);
-
- /*
- * Set the Transaction Context field (used for reply correlation)
- */
-
- tcontextp = (bsa_context_t *)kmem_zalloc(sizeof (bsa_context_t),
- KM_SLEEP);
- tcontextp->bsadata = bsadata;
-
-#if I2O_64BIT_CONTEXT
- ddi_put64(acc_handle, &msgbuf->TransactionContext, (uint64_t)
- tcontextp);
-#else
- ddi_put32(acc_handle, &msgbuf->TransactionContext,
- (uint32_t)(uintptr_t)tcontextp);
-#endif
-
- if (i2o_msg_send(bsadata->iop, msgbuf, msg_handle) == DDI_FAILURE) {
- cmn_err(CE_CONT, "?BsaMediaUnlock: i2o_msg_send failed");
- return (DDI_FAILURE);
- }
-
- /*
- * do a cv_wait here from reply
- */
- mutex_enter(&bsadata->bsa_mutex);
- while (!(tcontextp->replyflag & REPLY_DONE))
- cv_wait(&bsadata->reply_cv, &bsadata->bsa_mutex);
- tcontextp->replyflag &= ~REPLY_DONE;
- mutex_exit(&bsadata->bsa_mutex);
-
- ret = tcontextp->retval;
-
- kmem_free(tcontextp, sizeof (bsa_context_t));
-
- return (ret);
-}
-
-/*
- * This function is the reply function for Media unlock request
- */
-
-static void
-BsaMediaUnlock_reply(void *msg, ddi_acc_handle_t acc_handle)
-{
-
-
- bsa_context_t *tcontextp;
- int detstatus, reqstatus;
-
- /*
- * Get the Transacton Context field
- */
-#if I2O_64BIT_CONTEXT
- tcontextp = (bsa_context_t *)ddi_get64(acc_handle,
- &(((i2o_single_reply_message_frame_t *)
- msg)->TransactiontContext));
-#else
- tcontextp = (bsa_context_t *)(uintptr_t)ddi_get32(acc_handle,
- &(((i2o_single_reply_message_frame_t *)
- msg)->TransactionContext));
-#endif
- /*
- * Detailed status
- */
- detstatus = ddi_get16(acc_handle,
- &((i2o_single_reply_message_frame_t *)
- msg)->DetailedStatusCode);
-
- /*
- * reply status
- */
- reqstatus = ddi_get8(acc_handle,
- &((i2o_single_reply_message_frame_t *)
- msg)->ReqStatus);
-
- tcontextp->retval = translate_error(reqstatus, detstatus, 0);
-
- mutex_enter(&tcontextp->bsadata->bsa_mutex);
- tcontextp->replyflag |= REPLY_DONE;
- cv_broadcast(&tcontextp->bsadata->reply_cv);
- mutex_exit(&tcontextp->bsadata->bsa_mutex);
-}
-
-
-/*
- * 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
-UtilNOP(i2o_iop_handle_t handle, ddi_acc_handle_t acc_handle,
- i2o_common_message_t *msgp, i2o_msg_handle_t msg_handle)
-{
- /* send the UtilNop message to return the unused Message frame */
- msgp->StdMessageFrame.VersionOffset = I2O_VERSION_11;
- msgp->StdMessageFrame.MsgFlags = 0;
- ddi_put16(acc_handle, &msgp->StdMessageFrame.MessageSize, 3);
- put_msg_Function(&msgp->StdMessageFrame, I2O_UTIL_NOP, acc_handle);
- put_msg_InitiatorAddress(&msgp->StdMessageFrame,
- I2O_HOST_TID, acc_handle);
- put_msg_TargetAddress(&msgp->StdMessageFrame,
- I2O_IOP_TID, acc_handle);
-
- (void) i2o_msg_send(handle, msgp, msg_handle);
-}
-
-/*
- * Pass the geom information
- */
-
-static void
-geom_prep(struct dk_geom *dkg, struct bsa_unit *bsa_unit)
-{
- bzero((caddr_t)dkg, sizeof (struct dk_geom));
- dkg->dkg_ncyl = bsa_unit->au_cyl;
- dkg->dkg_nhead = bsa_unit->au_hd;
- dkg->dkg_nsect = bsa_unit->au_sec;
-}
-
-#define COPYOUT(a, b, c, f) \
- ddi_copyout((caddr_t)(a), (caddr_t)(b), sizeof (c), f)
-
-/*
- * This function performs all the Block storage ioctls
- */
-
-/*ARGSUSED4*/
-static int
-bsa_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cred_p,
- int *rval_p)
-{
-
- register struct bsa_unit *un;
- auto long data[512 / (sizeof (long))];
- int instance;
- struct bsa_data *bsadata;
- struct dk_cinfo *info;
- int i, status, ret;
-
- /*
- * get instance number
- */
- instance = UNIT(dev);
-
- if (!(bsadata = ddi_get_soft_state(bsa_soft, instance))) {
- return (ENXIO);
- }
-
-#ifdef BSA_DEBUG
- {
- char *cmdname;
-
- switch (cmd) {
- case DKIOCINFO: cmdname = "DKIOCINFO "; break;
- case DKIOCGGEOM: cmdname = "DKIOCGGEOM "; break;
- case DKIOCGAPART: cmdname = "DKIOCGAPART "; break;
- case DKIOCSAPART: cmdname = "DKIOCSAPART "; break;
- case DKIOCGVTOC: cmdname = "DKIOCGVTOC "; break;
- case DKIOCSVTOC: cmdname = "DKIOCSVTOC "; break;
- case DKIOCG_VIRTGEOM: cmdname = "DKIOCG_VIRTGEOM "; break;
- case DKIOCG_PHYGEOM: cmdname = "DKIOCG_PHYGEOM "; break;
- case DKIOCEJECT: cmdname = "DKIOCEJECT *"; break;
- case DKIOCSGEOM: cmdname = "DKIOCSGEOM *"; break;
- case DKIOCSTATE: cmdname = "DKIOCSTATE *"; break;
- case DKIOCADDBAD: cmdname = "DKIOCADDBAD *"; break;
- case DKIOCGETDEF: cmdname = "DKIOCGETDEF *"; break;
- case DKIOCPARTINFO: cmdname = "DKIOCPARTINFO *"; break;
- case DIOCTL_RWCMD: cmdname = "DIOCTL_RWCMD "; break;
- default: cmdname = "UNKNOWN *"; break;
- }
- cmn_err(CE_CONT, "?bsa_ioctl%d: cmd %x(%s) arg %x bsadata %x\n",
- instance, cmd, cmdname, arg, bsadata);
- }
-#endif
-
- un = &bsadata->unitp;
- bzero((caddr_t)data, sizeof (data));
-
- switch (cmd) {
- case DKIOCGGEOM:
- case DKIOCSGEOM:
- case DKIOCGAPART:
- case DKIOCSAPART:
- case DKIOCGVTOC:
- case DKIOCSVTOC:
- mutex_enter(&bsadata->lbl.mutex);
- status = bsa_lbl_ioctl(dev, cmd, (int)arg, flag);
- mutex_exit(&bsadata->lbl.mutex);
- return (status);
- }
-
- switch (cmd) {
- case DKIOCSTATE:
- {
- enum dkio_state state;
- mutex_enter(&bsadata->bsa_mutex);
- if (bsadata->state & DKIO_EJECTED)
- state = DKIO_EJECTED;
- else
- state = DKIO_INSERTED;
- while (!(bsadata->flags & STATE_CHANGE))
- cv_wait(&bsadata->state_cv,
- &bsadata->bsa_mutex);
- mutex_exit(&bsadata->bsa_mutex);
-
- if (bsadata->state & DKIO_EJECTED)
- state = DKIO_EJECTED;
- else
- state = DKIO_INSERTED;
-
- bsadata->flags &= ~STATE_CHANGE;
-
- if (ddi_copyout(&state, (caddr_t)arg, sizeof (int),
- flag)) {
- return (EFAULT);
- }
- }
- break;
- case DKIOCINFO:
-
- info = (struct dk_cinfo *)data;
- /*
- * Controller Information
- */
- info->dki_ctype = un->au_type;
- info->dki_cnum = ddi_get_instance(bsadata->dip);
- (void) strcpy(info->dki_cname,
- ddi_get_name(ddi_get_parent(bsadata->dip)));
- /*
- * Unit Information
- */
- info->dki_unit = ddi_get_instance(bsadata->dip);
- info->dki_slave = 0;
- (void) strcpy(info->dki_dname, "card");
- info->dki_flags = 0;
- info->dki_partition = LPART(dev);
-
- /*
- * We can give the OSM's transfer rate, which is
- * maxphys (maxphys/DEV_BSIZE).
- */
- info->dki_maxtransfer = maxphys/DEV_BSIZE;
-
- /*
- * We can't get from here to there yet
- */
- info->dki_addr = 0;
- info->dki_space = 0;
- info->dki_prio = 0;
- info->dki_vec = 0;
-
- if (COPYOUT(data, (uintptr_t)arg, struct dk_cinfo, flag))
- return (EFAULT);
- break;
-
- case DKIOCG_VIRTGEOM:
- case DKIOCG_PHYGEOM:
-
- {
- struct dk_geom dkg;
-
- bzero((caddr_t)&dkg, sizeof (struct dk_geom));
-
- dkg.dkg_ncyl = un->au_cyl;
- dkg.dkg_acyl = un->au_acyl;
- dkg.dkg_pcyl = un->au_cyl+un->au_acyl;
- dkg.dkg_nhead = un->au_hd;
- dkg.dkg_nsect = un->au_sec;
-
- if (ddi_copyout((caddr_t)&dkg, (caddr_t)arg,
- sizeof (struct dk_geom), flag))
- return (EFAULT);
- else
- return (0);
- }
-
- case DIOCTL_RWCMD:
- {
- struct dadkio_rwcmd rwcmd;
- int status, rw;
-
- i = sizeof (rwcmd);
- if (ddi_copyin((caddr_t)arg, (caddr_t)&rwcmd, i, flag))
- return (EFAULT);
-
- switch (rwcmd.cmd) {
- case DADKIO_RWCMD_READ :
- case DADKIO_RWCMD_WRITE:
- rw = ((rwcmd.cmd == DADKIO_RWCMD_WRITE) ?
- B_WRITE : B_READ);
- status = bsa_buf_setup((void **)&rwcmd, dev,
- ((flag & FKIOCTL) ? UIO_SYSSPACE :
- 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 &
- I2O_BSA_DEV_CAP_REMOVABLE_MEDIA);
-
- if (ddi_copyout((caddr_t)&i, (caddr_t)arg,
- 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 &
- I2O_BSA_DEV_CAP_REMOVABLE_MEDIA ||
- un->au_devicecapability &
- I2O_BSA_DEV_CAP_REMOVEABLE_DEVICE))
-
- return (ENOSYS);
- /*
- * First need to unlock before eject
- */
-
- if (ret = (BsaMediaUnlock(bsadata)))
- 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
-bsa_lbl_ioctl(dev_t dev, int cmd, int arg, int flag)
-{
- auto long data[512 / (sizeof (long))];
- int instance;
- struct bsa_data *bsadata;
- int i;
-
- /*
- * get instance number
- */
- instance = UNIT(dev);
-
-
- if (!(bsadata = ddi_get_soft_state(bsa_soft, instance))) {
- return (ENXIO);
- }
- /*
- * For future hot plugging make sure the device exist
- */
-
- bzero((caddr_t)data, sizeof (data));
-
- switch (cmd) {
- case DKIOCGGEOM:
- case DKIOCGAPART:
- case DKIOCGVTOC:
- if (update_vtoc(bsadata, dev))
- return (EFAULT);
- }
-
- switch (cmd) {
- case DKIOCGGEOM:
- {
- struct dk_geom up;
-
- dsklbl_dgtoug(&up, &bsadata->lbl.ondsklbl);
- if (COPYOUT(&up, (uintptr_t)arg, struct dk_geom,
- flag))
- return (EFAULT);
- break;
- }
-
- case DKIOCSGEOM:
- i = sizeof (struct dk_geom);
- if (ddi_copyin((caddr_t)(uintptr_t)arg, (caddr_t)data, i, flag))
- return (EFAULT);
- dsklbl_ugtodg((struct dk_geom *)data, &bsadata->lbl.ondsklbl);
- break;
-
- case DKIOCGAPART:
- /*
- * Return the map for all logical partitions.
- */
- i = NDKMAP * sizeof (struct dk_map);
- if (ddi_copyout((caddr_t)bsadata->lbl.un_map,
- (caddr_t)(uintptr_t)arg, i, flag)) {
- return (EFAULT);
- }
- break;
-
- case DKIOCSAPART:
- /*
- * Set the map for all logical partitions.
- */
- i = NDKMAP * sizeof (struct dk_map);
- if (ddi_copyin((caddr_t)(uintptr_t)arg, (caddr_t)data, i, flag))
- return (EFAULT);
- bcopy((caddr_t)data, (caddr_t)bsadata->lbl.un_map, i);
- break;
-
- case DKIOCGVTOC:
- i = sizeof (struct vtoc);
- dsklbl_ondsklabel_to_vtoc(&bsadata->lbl, (struct vtoc *)data);
- if (ddi_copyout((caddr_t)data, (caddr_t)(uintptr_t)arg, i,
- flag))
- return (EFAULT);
- else
- return (0);
- case DKIOCSVTOC:
- i = sizeof (struct vtoc);
- if (ddi_copyin((caddr_t)(uintptr_t)arg, (caddr_t)data, i,
- flag))
- return (EFAULT);
-
- if (write_dskvtoc(bsadata, dev, &bsadata->lbl,
- (struct vtoc *)data, &bsa_cb_ops)) {
- return (EFAULT);
- }
- break;
- }
- return (0);
-}
-
-static int bsa_prop_op(dev_t dev, dev_info_t *dip, ddi_prop_op_t prop_op,
- int mod_flags, char *name, caddr_t valuep, int *lengthp)
-{
- int instance = ddi_get_instance(dip);
- struct bsa_data *bsadata;
- uint64_t nblocks64;
-
- /*
- * 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.
- */
- bsadata = ddi_get_soft_state(bsa_soft, instance);
- if ((dev == DDI_DEV_T_ANY) || (bsadata == NULL) ||
- !(bsadata->lbl.pmap[LPART(dev)].p_flag & V_INVALID)) {
- return (ddi_prop_op(dev, dip, prop_op, mod_flags,
- name, valuep, lengthp));
- } else {
- /* get nblocks value */
- nblocks64 = (ulong_t)bsadata->lbl.pmap[LPART(dev)].p_size;
-
- return (ddi_prop_op_nblocks(dev, dip, prop_op, mod_flags,
- name, valuep, lengthp, nblocks64));
- }
-}
-
-/*
- * Setup the capacity and type information
- */
-
-static int
-bsa_setup(struct bsa_data *bsadata)
-{
-
- struct bsa_unit *bsa_unitp;
-
- bsa_unitp = &bsadata->unitp;
-
- /*
- * 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
- */
-
- mutex_enter(&bsadata->bsa_mutex);
-
- if (bsa_unitp->au_type == I2O_BSA_DEVICE_TYPE_DIRECT)
- bsa_unitp->au_type = DKC_DIRECT;
- else if (bsa_unitp->au_type == I2O_BSA_DEVICE_TYPE_CDROM)
- bsa_unitp->au_type = DKC_CDROM;
- 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)
- cap_translation(bsa_unitp->au_capacity, &(bsa_unitp->au_cyl),
- &(bsa_unitp->au_hd), &(bsa_unitp->au_sec));
- else
- return (DDI_FAILURE);
-
- bsa_unitp->au_acyl = 2;
-
- mutex_exit(&bsadata->bsa_mutex);
-
- mutex_enter(&bsadata->lbl.mutex);
- bsadata->lbl.geomread = 1;
- mutex_exit(&bsadata->lbl.mutex);
-
- DEBUGF(I2O_DEBUG_DIO, (CE_CONT, "?bsa_setup:targ = %d cyl = %d"
- "acyl = %d head = %d"
- " sec = %d\n",
- bsadata->tid,
- bsa_unitp->au_cyl,
- bsa_unitp->au_acyl,
- bsa_unitp->au_hd,
- bsa_unitp->au_sec));
- return (DDI_SUCCESS);
-
-}
-
-/*
- * The following is according to Intel's int13 translation for I2O.
- * (This needs more investigation).
- */
-
-
-#define MB (63 * 16 * 512 * 1023LL) /* 528MB */
-#define CAPACITY0 (63 * 32 * 512 * 1023LL) /* (1*GB) */
-#define CAPACITY1 (63 * 64 * 512 * 1023ULL) /* (2.1*GB) */
-#define CAPACITY2 (63 * 128 * 512 * 1023ULL) /* (4.2*GB) */
-#define CAPACITY3 (63 * 255 * 512 * 1023ULL) /* (8.4*GB) */
-#define FIXED_SECSIZE 512
-#define FIXED_SECNUM 63
-#define FIXED_MAXHEAD 255
-
-static void
-cap_translation(uint64_t capacity, int *cyls, int *hds, int *secs)
-{
-
-
- *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; */
-/* } */
-
-
-
- *cyls = (capacity/(*secs * *hds * FIXED_SECSIZE));
-
- DEBUGF(I2O_DEBUG_DIO, (CE_CONT, "?translation:capacity =%lld cyl = %d"
- "head = %d"
- " sec = %d\n",
- capacity,
- *cyls,
- *hds,
- *secs));
-
-}
-
-
-/*
- * Setup the read write buffer
- */
-
-static int
-bsa_buf_setup(void **cmdp, dev_t dev, enum uio_seg dataspace, int rw)
-{
- register struct dadkio_rwcmd *rwcmdp = (struct dadkio_rwcmd *)cmdp;
- register struct buf *bp;
- int status;
- auto struct iovec aiov;
- auto struct uio auio;
- register struct uio *uio = &auio;
-
- bp = getrbuf(KM_SLEEP);
-
- bp->b_back = (struct buf *)rwcmdp; /* ioctl packet */
- bp->b_private = (void *)0xBEE;
-
- bzero((caddr_t)&auio, sizeof (struct uio));
- bzero((caddr_t)&aiov, sizeof (struct iovec));
- aiov.iov_base = rwcmdp->bufaddr;
- aiov.iov_len = rwcmdp->buflen;
- uio->uio_iov = &aiov;
-
- uio->uio_iovcnt = 1;
- uio->uio_resid = rwcmdp->buflen;
- uio->uio_segflg = dataspace;
-
- /*
- * Let physio do the rest...
- */
- status = physio(bsa_strategy, bp, dev, rw, minphys, uio);
-
- freerbuf(bp);
- return (status);
-}