diff options
Diffstat (limited to 'usr/src/uts/common/io/i2o/i2o_bs.c')
-rw-r--r-- | usr/src/uts/common/io/i2o/i2o_bs.c | 3989 |
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); -} |