Mercurial > illumos > illumos-gate
changeset 4059:bad304cb4af7
PSARC/2007/045 I2O EOL and EOF
4863632 Hey Hey! Ho Ho! I2O Has Got to Go!
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/uts/common/io/i2o/i2o_bs.c Wed Apr 18 11:32:14 2007 -0700 @@ -0,0 +1,3989 @@ +/* + * 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); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/uts/common/io/i2o/i2o_bs.conf Wed Apr 18 11:32:14 2007 -0700 @@ -0,0 +1,29 @@ +# +# 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 (c) 1998 by Sun Microsystems, Inc. +# All rights reserved. +# + +#pragma ident "%Z%%M% %I% %E% SMI" + +name="i2o_bs" class="i2o";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/uts/common/io/i2o/i2o_bs.h Wed Apr 18 11:32:14 2007 -0700 @@ -0,0 +1,156 @@ +/* + * 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 (c) 1998-1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef _I2O_BS_H +#define _I2O_BS_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ROUNDUP(a, n) (((a) + ((n) - 1)) & ~((n) - 1)) +#define UNIT(dev) (getminor((dev)) >> UNITSHF) +#define BSA_SETMINOR(skt, part) ((skt << UNITSHF) | (part)) + +#if defined(_SUNOS_VTOC_16) +#define UNITSHF 6 +#define MAXPART (1 << UNITSHF) +#define LPART(dev) (getminor((dev)) & (MAXPART - 1)) +#elif defined(_SUNOS_VTOC_8) +#define UNITSHF 3 +#define PART_MASK 7 +#define LPART(dev) (getminor((dev)) & PART_MASK) +#else +#error No VTOC format defined. +#endif + + +#define V_INVALID 0x80 +#define FDISK_OFFSET MAX_SLICES +#if defined(_SUNOS_VTOC_16) +#define MAX_SLICES 16 +#define VTOC_OFFSET 1 +#elif defined(_SUNOS_VTOC_8) +#define VTOC_OFFSET 0 +#define MAX_SLICES 8 +#else +#error No VTOC format defined. +#endif +#define USLICE_WHOLE 2 +#define FPART_WHOLE 0 +#define NUM_PARTS (MAX_SLICES + FD_NUMPART + 1) + +#define REPLY_DONE 1 /* The reply is done */ +#define STATE_CHANGE 0x0001 /* STATE has changned */ +#define CLAIMED 0x0002 /* device is claimed */ +#define I2O_BSA_NAME "i2o_bs" + + +#define ISCD(p) ((p)->unitp.au_type == DKC_CDROM) +#define ISREMOVABLE(p) \ + ((p)->unitp.au_devicecapability & I2O_BSA_DEV_CAP_REMOVABLE_MEDIA) + +#define ISWRITEPROTECT(p) \ + ((p)->unitp.au_devicecapability & I2O_BSA_DEV_CAP_READ_ONLY) + + + +typedef struct dsk_label { + struct dk_label ondsklbl; + struct partition pmap[NUM_PARTS]; + struct dk_map un_map[NDKMAP]; /* logical partitions */ + int uidx; + int fdiskpresent; + int vtocread; + int geomread; + kmutex_t mutex; + +} dsk_label_t; + + +struct bsa_unit { + int au_cyl; + int au_acyl; + int au_hd; + int au_sec; + long au_blksize; + short au_bytes_per_block; + int au_type; + uint64_t au_capacity; + long au_devicecapability; +}; + +typedef struct bsa_data { + int flags; /* misc state info */ + int tid; /* local targer id ( From LCT) */ + int instance; /* instantiation of ourselves */ + int open_flag; /* open flag used for rem media */ + unsigned long state; /* State of removable media */ + struct buf *crashbuf; /* used when dumping to root device */ + i2o_iop_handle_t iop; /* IOP access handle */ + dev_info_t *dip; /* pointer to our own device node */ + dsk_label_t lbl; /* per targer label information */ + struct bsa_unit unitp; /* phsyical characteristics */ + kcondvar_t reply_cv; /* conditional variable */ + kcondvar_t rwreply_cv; /* read/write cond variable */ + kcondvar_t state_cv; /* state cond variable */ + kmutex_t bsa_mutex; /* bs mutex */ +} bsa_data_t; + + +typedef struct bsa_context { + struct bsa_data *bsadata; + int deterror; /* detail error */ + int retval; /* return value from reply */ + int replyflag; /* reply flag */ + int rwreplyflag; /* reply flag */ + ddi_dma_handle_t dma_handle; /* DMA Handle */ + ddi_acc_handle_t acc_handle; /* DMA Handle */ + ddi_dma_handle_t dma_sghandle; /* DMA Handle */ + ddi_acc_handle_t acc_sghandle; /* DMA Handle */ + ddi_dma_handle_t dma_sg2handle; /* DMA Handle */ + ddi_acc_handle_t acc_sg2handle; /* DMA Handle */ +} bsa_context_t; + +typedef struct i2o_common_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; +} i2o_common_message_t; + +typedef struct i2o_reassign_addr_message { + uint32_t ByteCount; + uint64_t LogicalByteAddress; +} i2o_reassign_addr_message_t; + + + +#ifdef __cplusplus +} +#endif + +#endif /* _I2O_BS_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/uts/common/io/i2o/i2o_impl.h Wed Apr 18 11:32:14 2007 -0700 @@ -0,0 +1,131 @@ +/* + * 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 (c) 1998 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef _I2O_IMPL_H +#define _I2O_IMPL_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#include <sys/types.h> +#include <sys/dditypes.h> +#include <sys/i2o/i2omsg.h> +#include <sys/i2o/i2outil.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef DEBUG +#define I2O_DEBUG +#endif + +/* + * ***************************************************************** + * Definitions used in the implementation of I2O nexus driver and + * I2O Message module. These are implementation specific definitions. + * ***************************************************************** + */ + +/* + * i2o_msg_trans structure: + * + * version I2O_MSG_TRANS_VER0 (version of this structure). + * + * iop_base_addr Base (virtual) address of device memory where + * inbound message frames are allocated. The MFA + * read from the inbound FIFO is an offset from + * this base address. + * + * iop_inbound_fifo_paddr + * Inbound Fifo port address (physical). + * + * acc_handle DDI access handle to access any message frame + * from the inbound queue. + * + * nexus_handle I2O Nexus handle argument to nexus transport + * functions. + * + * iblock_cookie Cookie needed for mutex_init(). + * + * i2o_trans_msg_alloc + * Allocates a message frame from the inbound + * queue. It reads the inbound FIFO register + * and returns the MFA. + * + * i2o_trans_msg_send + * Write the MFA to the inbound queue of the IOP. + * + * i2o_trans_msg_recv + * Reads the outbound queue for the reply + * messages and returns the MFA. The MFA is + * -1 if there are no reply messages. + * + * i2o_trans_msg_freebuf + * Writes the MFA into the outbound queue. + * + * i2o_trans_disable_intr + * Disables the IOP hardware interrupts. + * + * i2o_trans_enable_intr + * Enables the IOP hardware interrupts. + */ + +#define I2O_MSG_TRANS_VER0 0 +#define I2O_MSG_TRANS_VER I2O_MSG_TRANS_VER0 + +typedef void *i2o_nexus_handle_t; + +typedef struct i2o_msg_trans { + int version; + caddr_t iop_base_addr; + uint32_t iop_inbound_fifo_paddr; + ddi_acc_handle_t acc_handle; + i2o_nexus_handle_t nexus_handle; + ddi_iblock_cookie_t iblock_cookie; + uint_t (* i2o_trans_msg_alloc)(i2o_nexus_handle_t + nexus_handle); + int (* i2o_trans_msg_send)(i2o_nexus_handle_t nexus_handle, + uint_t mfa); + uint_t (* i2o_trans_msg_recv)(i2o_nexus_handle_t nexus_handle); + void (* i2o_trans_msg_freebuf)(i2o_nexus_handle_t + nexus_handle, uint_t mfa); + void (* i2o_trans_disable_intr)(i2o_nexus_handle_t + nexus_handle); + void (* i2o_trans_enable_intr)(i2o_nexus_handle_t + nexus_handle); +} i2o_msg_trans_t; + + +i2o_iop_handle_t i2o_msg_iop_init(dev_info_t *rdip, i2o_msg_trans_t *trans); +void i2o_msg_process_reply_queue(i2o_iop_handle_t iop); +int i2o_msg_iop_uninit(i2o_iop_handle_t *iop); +void i2o_msg_get_lct_info(i2o_iop_handle_t *, i2o_lct_t **, ddi_acc_handle_t *); + +#ifdef __cplusplus +} +#endif + +#endif /* _I2O_IMPL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/uts/common/io/i2o/i2o_msg.c Wed Apr 18 11:32:14 2007 -0700 @@ -0,0 +1,3307 @@ +/* + * 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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * I2O Message module, which implements OSM interfaces to provides + * transport functionality for the OSMs. It depends on the I2O nexus + * driver for bus specific transport mechanisms. + * + * Note: The current implementation assumes only 32bit virtual + * addresses and 32bit context fields in I2O messages. + */ + +#include <sys/types.h> +#include <sys/cmn_err.h> +#include <sys/conf.h> +#include <sys/debug.h> +#include <sys/modctl.h> +#include <sys/errno.h> +#include <sys/ddidmareq.h> +#include <sys/ddi_impldefs.h> +#include <sys/ddi.h> +#include <sys/sunddi.h> +#include <sys/pci.h> +#include <sys/avintr.h> +#include <sys/bustypes.h> +#include <sys/kmem.h> +#include <sys/archsystm.h> +#include <sys/disp.h> + +#include "i2o_impl.h" +#include <sys/i2o/i2oexec.h> + +#ifndef I2O_BOOT_SUPPORT +#include <sys/sunndi.h> + +char _depends_on[] = "misc/busra"; +#endif + +/* + * ************************************************************************ + * *** Implementation specific data structures/definitions. *** + * ************************************************************************ + */ + +/* + * Implementation of i2o_iop_handle_t data structure. + * + * dip devinfo node pointer of the I2O device + * tid IOP assigned TID for this device. + * iop pointer to iop_instance_t data structure. + */ + +typedef struct i2o_iop_impl_hdl { + dev_info_t *dip; + uint32_t tid; + struct iop_instance *iop; +} i2o_iop_impl_hdl_t; + +/* + * Implementation of i2o_msg_handle_t data structure. + * + * next pointer to the next handle (used when the requests + * are queued up) + * dma_handle DMA handle associated with this message buffer + * msgp pointer to the message frame. + * acc_hdl DDI access handle for this message frame. + */ + +typedef struct i2o_msg_impl_hdl { + struct i2o_msg_impl_hdl *next; + ddi_dma_handle_t dma_handle; + ddi_acc_handle_t acc_hdl; + void *msgp; +} i2o_msg_impl_hdl_t; + +/* + * Per IOP instance data structure maintained by the I2O Message + * module. + * + * Locks used: + * iop_ib_mutex Used to serialize access to the inbound message + * queue and to protect send_queue_* fields. + * + * iop_ob_mutex Used to serialize access to the outbound message + * queue. + */ +typedef struct iop_instance { + + struct iop_instance *next; + uint_t iop_id; + volatile int iop_flags; + i2o_msg_trans_t *nexus_trans; + dev_info_t *dip; + kmutex_t iop_ib_mutex; + kmutex_t iop_ob_mutex; + uint32_t event_mask; + uint_t ib_msg_frame_size; + + /* IOP Status Block structure */ + struct { + i2o_exec_status_get_reply_t *bufp; + ddi_acc_handle_t acc_hdl; + ddi_dma_handle_t dma_handle; + } status; + + /* Logical Configuration Table (LCT) */ + struct { + i2o_lct_t *bufp; + ddi_acc_handle_t acc_hdl; + size_t size; + ddi_dma_handle_t dma_handle; + kmutex_t lct_mutex; + } lct; + + /* Hardware Resource Table (HRT) */ + struct { + i2o_hrt_t *bufp; + ddi_acc_handle_t acc_hdl; + uint_t size; + ddi_dma_handle_t dma_handle; + } hrt; + + /* outbound message queue */ + struct { + caddr_t base_addr; + uint_t base_paddr; + ddi_acc_handle_t acc_hdl; + uint_t nframes; + uint_t framesize; + ddi_dma_handle_t dma_handle; + } ob_msg_queue; + + /* private memory/io space allocated for IOP hw configuration */ + struct { + uint_t mem_base; + uint_t mem_size; + uint_t io_base; + uint_t io_size; + } hw_config; + + /* System Table Entry for this IOP */ + struct { + ddi_dma_handle_t dma_handle; + i2o_iop_entry_t *bufp; + ddi_acc_handle_t acc_hdl; + } systab; + + /* OSM registration book keeping */ + struct { + i2o_iop_impl_hdl_t *iop_handle_tab; + uint_t max_tid; + kmutex_t osm_mutex; + } osm_registry; + + /* + * i2o_send_msg() queue information. The fields send_queue_head + * and send_queue_tail are protected under iop_ib_mutex. + */ + i2o_msg_impl_hdl_t *send_queue_head; + i2o_msg_impl_hdl_t *send_queue_tail; + ulong_t send_queue_count; + kcondvar_t send_queue_cv; +} iop_instance_t; + +/* common transaction context structure */ + +typedef struct tcontext { + iop_instance_t *iop; + kmutex_t cv_mutex; + kcondvar_t cv; + int status; + int done_flag; +} tcontext_t; + +/* definitions for iop_flags values */ +#define IOP_IS_IN_INIT 1 /* IOP is being initialized */ +#define IOP_IS_ONLINE 2 /* IOP is initilized */ +#define IOP_IS_IN_UNINIT 4 /* IOP is being uninitialized */ +#define IOP_SEND_QUEUE_PROC_RUNNING 8 /* i2o_msg_send_proc() running */ + +/* + * DMA attribute structure for I2O Spec version 1.5. + * + * (Note: Specifies sg list length to 1 to get contiguous memory) + */ +static ddi_dma_attr_t dma_attr_contig = { + DMA_ATTR_VERSION, /* version number */ + (uint64_t)0, /* low DMA address range */ + (uint64_t)0xFFFFFFFF, /* high DMA address range */ + (uint64_t)0x00FFFFFF, /* DMA counter register */ + 1, /* DMA address alignment */ + 1, /* DMA burstsizes */ + 1, /* min effective DMA size */ + (uint64_t)0xFFFFFFFF, /* max DMA xfer size */ + (uint64_t)0xFFFFFFFF, /* segment boundary */ + 0x1, /* s/g length */ + 1, /* granularity of device */ + 0 /* Bus specific DMA flags */ +}; + +/* + * Device attribute structure for I2O version 1.5. + * + * I2O data structures (whether it is in IOP's memory or host memory) + * are in Little Endian format. + */ +static ddi_device_acc_attr_t i2o_dev_acc_attr = { + DDI_DEVICE_ATTR_V0, + DDI_STRUCTURE_LE_ACC, /* devacc_attr_endian_flags for LE access */ + DDI_STRICTORDER_ACC /* devacc_attr_dataorder */ +}; + +/* Function prototypes for local functions */ + +static int i2o_get_iop_status(iop_instance_t *iop); +static int i2o_init_outbound_queue(iop_instance_t *iop); +static int i2o_get_hrt(iop_instance_t *iop); +static int i2o_create_systab(iop_instance_t *iop); +static int i2o_send_exec_enable(iop_instance_t *iop); +static int i2o_get_lct(iop_instance_t *iop); +static int i2o_iop_event_register(iop_instance_t *iop); +static void i2o_msg_iop_event_reply(void *p, ddi_acc_handle_t acc_hdl); +static void i2o_msg_common_reply(void *p, ddi_acc_handle_t acc_hdl); +static int i2o_send_exec_iop_reset(iop_instance_t *iop); +static void i2o_msg_send_proc(iop_instance_t *iop); + +static void i2o_return_mem(dev_info_t *, uint_t, uint_t); +static uint_t i2o_get_mem(dev_info_t *, uint_t, uint_t *); +static uint_t i2o_get_io(dev_info_t *, uint_t, uint_t *); +static void i2o_return_io(dev_info_t *, uint_t, uint_t); + +#ifdef I2O_DEBUG +/* function prototypes for debug functions */ +static void dump_reply_message(iop_instance_t *iop, + i2o_single_reply_message_frame_t *rmp); +static void dump_hrt(iop_instance_t *iop); +static void dump_lct(iop_instance_t *iop); +static void dump_iop_status_buf(iop_instance_t *iop); +static void dump_message(uint32_t *mp, char *name); +#endif + +/* + * Local Data definitions. + * + * niop + * number of active IOPs initialized to OP state. + * + * next_iop_id + * Counter to assign unique ID (IOP_ID) to the next IOP that + * gets initialized by the i2o nexus. + * + * ioplist + * pointer to the linked list of IOP data structures (i.e iop_instance + * structures) that are initilized. + * + * iop_reset_time_delay_in_ticks + * This is the time delay to get a valid mfa from the inbound freelist + * after doing ExecIopReset. This delay really depends on the platform + * specific hardware. Here we are using 2 seconds and this seems to + * work fine for the Madrona platform. + */ + +#define BASE_IOP_ID 2 /* IOP IDs 0 and 1 are reserved */ + +static uint_t niop = 0; +static uint_t next_iop_id = BASE_IOP_ID; +static iop_instance_t *ioplist; +int iop_reset_time_delay_in_ticks = 200; + +kmutex_t i2o_mutex; /* protects common data like ioplist, etc. */ + +/* + * Debug flag definitions. + */ +#define I2O_DEBUG_DEBUG 0x80000000 /* general debugging info */ +#define I2O_DEBUG_MSG 0x00000001 /* dump message frames */ +#define I2O_DEBUG_HRT 0x40000000 /* dump HRT table */ +#define I2O_DEBUG_STATUS 0x20000000 /* dump IOP Status block */ +#define I2O_DEBUG_LCT 0x10000000 /* dump LCT table */ +#define I2O_DEBUG_IOP_PARAMS 0x08000000 /* dump IOP parameters */ + +#ifdef I2O_DEBUG +int i2o_debug = I2O_DEBUG_LCT; + +#define DEBUGF(flag, args) \ + { if (i2o_debug & (flag)) cmn_err args; } +#else +#define DEBUGF(level, args) /* nothing */ +#endif + +#define SUCCESS 1 +#define FAILURE 0 + +/* + * Module linkage information for the kernel. + */ +extern struct mod_ops mod_miscops; +static struct modlmisc modlmisc = { + &mod_miscops, + "I2O Message Module version 1.5", +}; + + +static struct modlinkage modlinkage = { + MODREV_1, + &modlmisc, + NULL +}; + +int +_init(void) +{ + int error; + + mutex_init(&i2o_mutex, NULL, MUTEX_DRIVER, NULL); + + if ((error = mod_install(&modlinkage)) != 0) + mutex_destroy(&i2o_mutex); + + return (error); +} + +int +_fini(void) +{ + int error; + + if ((error = mod_remove(&modlinkage)) == 0) + mutex_destroy(&i2o_mutex); + + return (error); +} + +int +_info(struct modinfo *modinfop) +{ + return (mod_info(&modlinkage, modinfop)); +} + + +/* + * Utility macros to initialize message structures. + */ +/* initialize standard message header */ +#define init_std_msghdr(iop, mp, ver_off, msg_flags, msg_size, func) \ + { \ + (mp)->VersionOffset = (ver_off) | I2O_VERSION_11; \ + (mp)->MsgFlags = (msg_flags); \ + ddi_put16((iop)->nexus_trans->acc_handle, \ + &(mp)->MessageSize, (msg_size) >> 2); \ + put_msg_Function((mp), (func), (iop)->nexus_trans->acc_hdl); \ + put_msg_InitiatorAddress((mp), I2O_HOST_TID, \ + (iop)->nexus_trans->acc_hdl); \ + put_msg_TargetAddress((mp), I2O_IOP_TID, \ + (iop)->nexus_trans->acc_hdl); \ + } + +/* initialize standard SGL Simple Element structure */ +#define init_sgl_simple_ele(iop, sgl, flags, count, addr) \ + { \ + put_flags_count_Flags(&(sgl)->FlagsCount, \ + (flags) | I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT, \ + (iop)->nexus_trans->acc_hdl); \ + ddi_put32((iop)->nexus_trans->acc_handle, \ + &(sgl)->PhysicalAddress, (uint_t)(addr)); \ + put_flags_count_Count(&(sgl)->FlagsCount, (count), \ + (iop)->nexus_trans->acc_hdl); \ + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, "SGL(0x%p): %x %x", \ + (void *)sgl, ((uint32_t *)sgl)[0], ((uint32_t *)sgl)[1])); \ + } + +/* + * ************************************************************************ + * Tunable parameters/properties. + * ob_msg_framesize_default + * Default frame size for Outbound Message queue. The minimum + * size is 64 bytes. It should be multiple of 4. + * ob_msg_queue_length_default + * Default size (i.e #of MFAs) in the Outbound Queue. The + * minimum is 16. + * ************************************************************************ + */ +int ob_msg_framesize_default = 128; +int ob_msg_queue_length_default = 32; + +/* + * ************************************************************************ + * Transport utility functions/macros used in IOP initialization. + * ************************************************************************ + */ + +#define iop_msg_send(iop, msgp) \ + (* iop->nexus_trans->i2o_trans_msg_send) \ + (iop->nexus_trans->nexus_handle, \ + (caddr_t)(msgp) - iop->nexus_trans->iop_base_addr) + + +#define iop_msg_free(iop, rmp) \ + (* iop->nexus_trans->i2o_trans_msg_freebuf) \ + (iop->nexus_trans->nexus_handle, \ + ((caddr_t)(rmp) - iop->ob_msg_queue.base_addr) + \ + iop->ob_msg_queue.base_paddr) + +static i2o_single_reply_message_frame_t * +iop_poll_reply_msg(iop_instance_t *iop) +{ + uint_t mfa; + uint_t ticks = 10000; /* time out polling for 10 seconds */ + + mfa = (* iop->nexus_trans->i2o_trans_msg_recv) + (iop->nexus_trans->nexus_handle); + + while (mfa == (uint_t)0xFFFFFFFF) { + delay(1); + mfa = (* iop->nexus_trans->i2o_trans_msg_recv) + (iop->nexus_trans->nexus_handle); + if (--ticks == 0) { + DEBUGF(I2O_DEBUG_DEBUG, + (CE_CONT, "iop_poll_reply_msg: timed out")); + return (NULL); /* time out - possible hang? */ + } + } + + return ((i2o_single_reply_message_frame_t *) + ((mfa - iop->ob_msg_queue.base_paddr) + + iop->ob_msg_queue.base_addr)); +} + +void * +iop_msg_alloc(iop_instance_t *iop) +{ + uint32_t mfa; + + mfa = (* iop->nexus_trans->i2o_trans_msg_alloc) + (iop->nexus_trans->nexus_handle); + + /* + * If we don't have a valid frame then wait for a while and + * try again. This may be necessary at the beginning if + * the IOP is in the INITIALIZATION state. + */ + if (mfa == (uint_t)0xFFFFFFFF) { + delay(100); + mfa = (* iop->nexus_trans->i2o_trans_msg_alloc) + (iop->nexus_trans->nexus_handle); + } + + return (mfa == (uint_t)0xFFFFFFFF ? NULL : + (void *)(mfa + iop->nexus_trans->iop_base_addr)); +} + + +/* + * ************************************************************************ + * ********* Private interfaces used by the I2O Nexus driver. *********** + * ************************************************************************ + */ + +/* + * i2o_msg_iop_init() + * + * Called from the attach(9E) function in the i2o nexus driver. + * Initializes the IOP to the OPERATIONAL state. Returns an access + * handle (i.e i2o_iop_handle_t) for successful initialization, + * otherwise it returns NULL. + * + * Assumption(s): + * 1. The IOP interrupts are not enabled when this function is + * called. The caller (i.e attach(9E)) enables the IOP interrupts + * upon the successful return from this function. + * 2. It is assumed that the I2O nexus driver will create the + * devinfo nodes for the I2O devices if necessary. i.e the + * caller of this function will create the devinfo tree + * based on the LCT/HRT information if the boot firmware hasn't + * already created it. + */ + +i2o_iop_handle_t +i2o_msg_iop_init(dev_info_t *dip, i2o_msg_trans_t *trans) +{ + iop_instance_t *iop; + uint32_t priv_mem_size; + uint32_t priv_io_size; + i2o_iop_impl_hdl_t *hdl; + i2o_lct_entry_t *lct_entp; + uint_t lct_entries; + int i; + int reset_done = 0; /* only one IOP_RESET operation */ + int init_time; + + /* + * Allocate an iop instance data. + */ + iop = (iop_instance_t *)kmem_zalloc(sizeof (iop_instance_t), KM_SLEEP); + + mutex_enter(&i2o_mutex); + + iop->dip = dip; + iop->iop_flags |= IOP_IS_IN_INIT; /* IOP is being initialized */ + iop->nexus_trans = trans; + + niop++; + iop->iop_id = next_iop_id++; /* assign a unique ID to this IOP */ + + mutex_init(&iop->iop_ib_mutex, NULL, MUTEX_DRIVER, + (void *)iop->nexus_trans->iblock_cookie); + mutex_init(&iop->iop_ob_mutex, NULL, MUTEX_DRIVER, + (void *)iop->nexus_trans->iblock_cookie); + mutex_init(&iop->osm_registry.osm_mutex, NULL, MUTEX_DRIVER, + (void *)iop->nexus_trans->iblock_cookie); + mutex_init(&iop->lct.lct_mutex, NULL, MUTEX_DRIVER, + (void *)iop->nexus_trans->iblock_cookie); + + /* + * ************************************************************** + * Step 1: Get the IOP status block by sending ExecStatusGet + * message. + * + * NOTE: Normally we expect IOP to be in 'RESET' state or 'OP' + * state. Any other state is really doubtful! + * ************************************************************** + */ + + /* + * We give 5 minutes for IOP to reset before complaining to user; + * the time for IOP to come to RESET state after it receives the + * EXEC_IOP_RESET really depends on the I2O hardware configured + * under the IOP. + */ + init_time = 5 * 60 * 100; /* ~5 min of clock ticks */ + +try_again: + if (i2o_get_iop_status(iop) == FAILURE) + goto cleanup; + + /* Check for I2O Version; we only support version 1.5 */ + if (get_i2o_exec_status_reply_I2oVersion(iop->status.bufp, + iop->status.acc_hdl) != I2O_VERSION_11) + goto cleanup; + + DEBUGF(I2O_DEBUG_DEBUG, + (CE_CONT, "i2o_msg_iop_init: Initial IOP state %x", + iop->status.bufp->IopState)); + + switch (iop->status.bufp->IopState) { + case I2O_IOP_STATE_RESET: + break; + + case I2O_IOP_STATE_INITIALIZING: + if (init_time <= 0) + cmn_err(CE_WARN, + "IOP is still in I2O_IOP_STATE_INITIALIZING state!!"); + else + init_time -= 100; + delay(100); + goto try_again; + + case I2O_IOP_STATE_OPERATIONAL: + /* reset the IOP and wait for a while for the IOP to reset */ + if (reset_done || i2o_send_exec_iop_reset(iop) != SUCCESS) + goto cleanup; + reset_done = 1; + delay(iop_reset_time_delay_in_ticks); + goto try_again; + + case I2O_IOP_STATE_HOLD: + case I2O_IOP_STATE_READY: + case I2O_IOP_STATE_FAILED: + case I2O_IOP_STATE_FAULTED: + /* reset the IOP and try again */ + if (!reset_done && i2o_send_exec_iop_reset(iop) == SUCCESS) { + delay(iop_reset_time_delay_in_ticks); + reset_done = 1; + goto try_again; + } + default: + cmn_err(CE_CONT, "?i2o_msg_iop_init: Invalid IOP state %x", + iop->status.bufp->IopState); + goto cleanup; + } + +#ifdef I2O_DEBUG + if (i2o_debug & I2O_DEBUG_STATUS) + dump_iop_status_buf(iop); +#endif + + /* + * ************************************************************** + * Step 2: Initialize the Outbound message queue. + * ************************************************************** + */ + if (i2o_init_outbound_queue(iop) == FAILURE) + goto cleanup; + + /* + * ************************************************************** + * Step 3: Get the Hardware Resource Table (HRT). + * ************************************************************** + */ + if (i2o_get_hrt(iop) == FAILURE) + goto cleanup; + +#if !defined(I2O_BOOT_SUPPORT) + /* + * ************************************************************** + * Step 4: Allocate Memory/IO spaces required by the IOP to + * configure the hidden adapters. The IOP status buffer + * has the required information. + * + * XXX Does IOP handle multiple chunks for PCI memory/io space + * allocated by the host? Currently the IRTOS always reports + * the CurrentPrivateMemSize as zero. + * ************************************************************** + */ + priv_mem_size = ddi_get32(iop->status.acc_hdl, + &iop->status.bufp->DesiredPrivateMemSize); + if (priv_mem_size > (uint32_t)0) { + /* need to allocate PCI memory space */ + if (i2o_get_mem(dip, priv_mem_size, &iop->hw_config.mem_base) == 0) + goto cleanup; + iop->hw_config.mem_size = priv_mem_size; + } + + priv_io_size = ddi_get32(iop->status.acc_hdl, + &iop->status.bufp->DesiredPrivateIOSize); + if (priv_io_size > (uint32_t)0) { + /* need to allocate PCI i/o space */ + if (i2o_get_io(dip, priv_io_size, &iop->hw_config.io_base) == 0) + goto cleanup; + iop->hw_config.io_size = priv_io_size; + } +#endif + + /* + * ************************************************************** + * Step 5: Create the System Table entry for this IOP and send + * ExecSysTabSet to all the IOPs. It enables the IOP + * to OPERATIONAL state. + * ************************************************************** + */ + if (i2o_create_systab(iop) == FAILURE) + goto cleanup; + + ASSERT(iop->status.bufp->IopState == I2O_IOP_STATE_OPERATIONAL); + + /* + * ************************************************************** + * Step 6: Read LCT by sending ExecLctNotify message. + * ************************************************************** + */ + if (i2o_get_lct(iop) == FAILURE) + goto cleanup; + + /* + * ************************************************************** + * Step 7: Set event notification request for the events that + * we are interested. + * ************************************************************** + */ + if (i2o_iop_event_register(iop) == FAILURE) + goto cleanup; + + if (ioplist == NULL) { + ioplist = iop; + iop->next = NULL; + } else { + iop->next = ioplist; + ioplist = iop; + } + iop->iop_flags |= IOP_IS_ONLINE; + iop->ib_msg_frame_size = ddi_get16(iop->nexus_trans->acc_handle, + &iop->status.bufp->InboundMFrameSize) << 2; + + /* find the max TIDs allocated by the IOP */ + iop->osm_registry.max_tid = 0; + lct_entries = + ((ddi_get16(iop->lct.acc_hdl, &iop->lct.bufp->TableSize) << 2) - + sizeof (i2o_lct_t) + sizeof (i2o_lct_entry_t)) / + sizeof (i2o_lct_entry_t); + lct_entp = iop->lct.bufp->LCTEntry; + for (i = 0; i < lct_entries; i++) { + uint_t tid; + + tid = get_lct_entry_LocalTID(&lct_entp[i], iop->lct.acc_hdl); + if (tid > iop->osm_registry.max_tid) + iop->osm_registry.max_tid = tid; + } + + /* allocate the IOP handle table */ + iop->osm_registry.iop_handle_tab = (i2o_iop_impl_hdl_t *) + kmem_zalloc(sizeof (i2o_iop_impl_hdl_t) * + (iop->osm_registry.max_tid + 1), KM_SLEEP); + /* + * initialize the IOP handle (i2o_iop_handle_t) for the nexus to use and + * return the handle. + */ + hdl = &iop->osm_registry.iop_handle_tab[I2O_IOP_TID]; + hdl->dip = dip; + hdl->iop = iop; + hdl->tid = I2O_IOP_TID; + + mutex_exit(&i2o_mutex); + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, "i2o_msg_iop_init: SUCCEEDED")); + + return ((i2o_iop_handle_t *)hdl); + + /* + * Error return; free up the allocated resources and return NULL. + */ +cleanup: + + if (iop->status.bufp != NULL) { + ddi_dma_mem_free(&iop->status.acc_hdl); + ddi_dma_free_handle(&iop->status.dma_handle); + } + + if (iop->lct.bufp != NULL) { + ddi_dma_mem_free(&iop->lct.acc_hdl); + ddi_dma_free_handle(&iop->lct.dma_handle); + } + + if (iop->hrt.bufp != NULL) { + ddi_dma_mem_free(&iop->hrt.acc_hdl); + ddi_dma_free_handle(&iop->hrt.dma_handle); + } + + if (iop->ob_msg_queue.base_addr != NULL) { + ddi_dma_mem_free(&iop->ob_msg_queue.acc_hdl); + ddi_dma_free_handle(&iop->ob_msg_queue.dma_handle); + } + + if (iop->hw_config.mem_base != NULL) { + i2o_return_mem(dip, iop->hw_config.mem_base, + iop->hw_config.mem_size); + } + + if (iop->hw_config.io_base != NULL) { + i2o_return_io(dip, iop->hw_config.io_base, + iop->hw_config.io_size); + } + + mutex_destroy(&iop->iop_ib_mutex); + mutex_destroy(&iop->iop_ob_mutex); + mutex_destroy(&iop->lct.lct_mutex); + + kmem_free((void *)iop, sizeof (iop_instance_t)); + + --niop; + + mutex_exit(&i2o_mutex); + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, "i2o_msg_iop_init: FAILED")); + + return (NULL); +} + +/* + * i2o_msg_iop_unint() + * + * Called from the detach(9E) function in the i2o nexus driver. + * It would uninitialize IOP by sending ExecIopReset to bring the + * IOP to RESET state. And then it will free up any resources/data-structures + * allocated for this IOP instance. + * + * Assumption(s): + * 1. It is assumed that all the I2O devices are quiesced before calling + * this function. Which means all OSMs have already done the + * i2o_msg_osm_unregister() for the devices they claimed. + */ + +int +i2o_msg_iop_uninit(i2o_iop_handle_t *handlep) +{ + i2o_iop_handle_t h = *handlep; + iop_instance_t *iop = ((i2o_iop_impl_hdl_t *)(h))->iop; + ddi_dma_handle_t dma_handle = NULL; + ddi_acc_handle_t acc_hdl; + i2o_exec_iop_reset_status_t *buf = NULL; + i2o_exec_sys_quiesce_message_t *qmsgp; + i2o_single_reply_message_frame_t *rmp = NULL; + iop_instance_t *p; + + mutex_enter(&iop->iop_ib_mutex); + mutex_enter(&iop->iop_ob_mutex); + mutex_enter(&iop->osm_registry.osm_mutex); + mutex_enter(&iop->lct.lct_mutex); + mutex_enter(&i2o_mutex); + + /* + * First, disable the IOP hardware interrupts. + */ + (* iop->nexus_trans->i2o_trans_disable_intr) + (iop->nexus_trans->nexus_handle); + + /* + * ********************************************************* + * if there are multiple IOPs then we need to send + * ExecPathQuiesce message to other IOPs before + * resetting this IOP. + * ********************************************************* + */ + + if (niop > 1) { /* we have multiple IOPs */ + tcontext_t tcxt; /* transaction context structure */ + + cv_init(&tcxt.cv, NULL, CV_DEFAULT, NULL); + mutex_init(&tcxt.cv_mutex, NULL, MUTEX_DRIVER, NULL); + + for (p = ioplist; p != NULL; p = p->next) { + i2o_exec_path_quiesce_message_t *mp; + + if (p == iop) + continue; + + /* + * Send ExecPathQuiesce message to this IOP. + */ + + mp = (i2o_exec_path_quiesce_message_t *)iop_msg_alloc(p); + + if (mp == NULL) { + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_msg_iop_uninit: trans_msg_alloc failed")); + cv_destroy(&tcxt.cv); + mutex_destroy(&tcxt.cv_mutex); + goto cleanup; + } + + /* initialize the transcation context structure */ + tcxt.iop = p; + tcxt.done_flag = 0; + + /* construct the ExecPathQuiesce message */ + + init_std_msghdr(p, &mp->StdMessageFrame, 0x0, 0, + sizeof (i2o_exec_path_quiesce_message_t), + I2O_EXEC_PATH_QUIESCE); + ddi_put32(p->nexus_trans->acc_handle, + &mp->TransactionContext, (uint32_t)(uintptr_t)&tcxt); + ddi_put32(p->nexus_trans->acc_handle, + (uint32_t *)&mp->StdMessageFrame.InitiatorContext. + initiator_context_32bits, + (uint32_t)i2o_msg_common_reply); + put_i2o_exec_path_quiesce_IOP_ID(mp, iop->iop_id, + p->nexus_trans->acc_handle); + ddi_put16(p->nexus_trans->acc_handle, + &mp->HostUnitID, iop->status.bufp->HostUnitID); + + /* send the message to the IOP and wait for the reply */ + + (void) iop_msg_send(p, (void *)mp); + + mutex_enter(&tcxt.cv_mutex); + while (!tcxt.done_flag) /* wait for the reply */ + cv_wait(&tcxt.cv, &tcxt.cv_mutex); + mutex_exit(&tcxt.cv_mutex); + } + + cv_destroy(&tcxt.cv); + mutex_destroy(&tcxt.cv_mutex); + } + + + /* + * ********************************************************* + * Send an ExecSysQuiesce message to the IOP. + * ********************************************************* + */ + + /* allocate a message frame from Inbound queue */ + qmsgp = (i2o_exec_sys_quiesce_message_t *)iop_msg_alloc(iop); + if (qmsgp == NULL) { + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_msg_iop_uninit: trans_msg_alloc failed")); + goto cleanup; + } + + /* construct the ExecSysQuiesce message */ + init_std_msghdr(iop, &qmsgp->StdMessageFrame, 0x0, 0, + sizeof (i2o_exec_sys_quiesce_message_t), + I2O_EXEC_SYS_QUIESCE); + +#ifdef I2O_DEBUG + if (i2o_debug & I2O_DEBUG_MSG) + dump_message((uint32_t *)qmsgp, "ExecSysQuiesce"); +#endif + + /* send the message to the IOP */ + (void) iop_msg_send(iop, (void *)qmsgp); + + /* + * Since interrupts are disabled, we poll for the reply message + * for ExecSysQuiesce request. Could we expect any other reply + * messages for previous activity on this IOP (like some + * event notification)? For now, we can safely ignore any other + * reply messages. + */ + for (;;) { + + if ((rmp = iop_poll_reply_msg(iop)) == NULL) + goto cleanup; + + /* ignore reply messages other than for ExecSysQuiesce */ + if (get_msg_Function((i2o_message_frame_t *)rmp, + iop->ob_msg_queue.acc_hdl) != I2O_EXEC_SYS_QUIESCE) { + iop_msg_free(iop, rmp); + continue; + } + + if (rmp->ReqStatus == I2O_REPLY_STATUS_SUCCESS) + break; /* successful */ + + /* message failed */ + iop_msg_free(iop, rmp); + goto cleanup; + } + + /* free up the reply message buffer */ + iop_msg_free(iop, rmp); + + /* + * ********************************************************* + * Now, send an ExecIopReset message to the IOP. + * ********************************************************* + */ + + if (i2o_send_exec_iop_reset(iop) == FAILURE) + goto cleanup; + + iop->iop_flags |= IOP_IS_IN_UNINIT; + + /* + * ********************************************************* + * Free up the system resources. + * ********************************************************* + */ + if (iop->status.bufp != NULL) { + ddi_dma_mem_free(&iop->status.acc_hdl); + ddi_dma_free_handle(&iop->status.dma_handle); + } + + if (iop->lct.bufp != NULL) { + ddi_dma_mem_free(&iop->lct.acc_hdl); + ddi_dma_free_handle(&iop->lct.dma_handle); + } + + if (iop->hrt.bufp != NULL) { + ddi_dma_mem_free(&iop->hrt.acc_hdl); + ddi_dma_free_handle(&iop->hrt.dma_handle); + } + + if (iop->ob_msg_queue.base_addr != NULL) { + ddi_dma_mem_free(&iop->ob_msg_queue.acc_hdl); + ddi_dma_free_handle(&iop->ob_msg_queue.dma_handle); + } + + if (iop->hw_config.mem_base != NULL) { + i2o_return_mem(iop->dip, iop->hw_config.mem_base, + iop->hw_config.mem_size); + } + + if (iop->hw_config.io_base != NULL) { + i2o_return_io(iop->dip, iop->hw_config.io_base, + iop->hw_config.io_size); + } + + /* + * If i2o_msg_send_proc() is running then wait for it to exit. + */ + if (iop->iop_flags & IOP_SEND_QUEUE_PROC_RUNNING) { + + mutex_exit(&iop->iop_ib_mutex); + + /* wake up the i2o_msg_send_proc() thread */ + cv_broadcast(&iop->send_queue_cv); + + /* wait until the i2o_msg_send_proc() stops running */ + while (iop->iop_flags & IOP_SEND_QUEUE_PROC_RUNNING) + delay(1); + + cv_destroy(&iop->send_queue_cv); + } + + mutex_destroy(&iop->iop_ib_mutex); + mutex_destroy(&iop->iop_ob_mutex); + mutex_destroy(&iop->osm_registry.osm_mutex); + mutex_destroy(&iop->lct.lct_mutex); + + if (iop == ioplist) { + ioplist = ioplist->next; + } else { + iop_instance_t *p, *prev; + + for (prev = ioplist, p = ioplist->next; p; p = p->next) { + if (p == iop) { + prev->next = iop->next; + break; + } + prev = p; + } + + ASSERT((p != NULL) && (p == iop)); + } + + --niop; /* number of active IOPs */ + + mutex_exit(&i2o_mutex); + + /* free up the IOP handle table */ + kmem_free((void *)iop->osm_registry.iop_handle_tab, + sizeof (i2o_iop_impl_hdl_t) * (iop->osm_registry.max_tid + 1)); + + *handlep = NULL; + + kmem_free((void *)iop, sizeof (iop_instance_t)); + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, "i2o_msg_iop_uninit: SUCCEEDED")); + + return (DDI_SUCCESS); + + /* + * Error return; free up the allocated resources and return NULL. + */ +cleanup: + if (buf != NULL) + ddi_dma_mem_free(&acc_hdl); + + if (dma_handle != NULL) + ddi_dma_free_handle(&dma_handle); + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, "i2o_msg_iop_uninit: FAILED")); + + mutex_exit(&i2o_mutex); + mutex_exit(&iop->lct.lct_mutex); + mutex_exit(&iop->osm_registry.osm_mutex); + mutex_exit(&iop->iop_ob_mutex); + mutex_exit(&iop->iop_ib_mutex); + + return (DDI_FAILURE); +} + +/* + * Send ExecStatusGet message to get IOP status. It allocates the + * buffer resources if they are not already allocated. + * + * Returns SUCCESS if it succeeds in getting the IOP status. + */ +static int +i2o_get_iop_status(iop_instance_t *iop) +{ + size_t real_length; + ddi_dma_cookie_t dma_cookie; + uint_t ncookies; + i2o_exec_status_get_message_t *msgp; + i2o_exec_status_get_reply_t *s = 0; + + if (iop->status.dma_handle == NULL) { + + /* allocate a DMA handle */ + if (ddi_dma_alloc_handle(iop->dip, &dma_attr_contig, DDI_DMA_SLEEP, + NULL, &iop->status.dma_handle) != DDI_SUCCESS) { + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_get_iop_status: ddi_dma_alloc_handle failed")); + goto cleanup; + } + } + + if (iop->status.bufp == NULL) { + + /* allocate the buffer for the IOP status block */ + if (ddi_dma_mem_alloc(iop->status.dma_handle, + sizeof (i2o_exec_status_get_reply_t), &i2o_dev_acc_attr, + DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, + (caddr_t *)&iop->status.bufp, &real_length, + &iop->status.acc_hdl) != DDI_SUCCESS) { + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_get_iop_status: ddi_dma_mem_alloc failed")); + goto cleanup; + } + + bzero((caddr_t)iop->status.bufp, real_length); + } + + if (ddi_dma_addr_bind_handle(iop->status.dma_handle, NULL, + (caddr_t)iop->status.bufp, sizeof (i2o_exec_status_get_reply_t), + DDI_DMA_READ | DDI_DMA_STREAMING, DDI_DMA_SLEEP, + NULL, &dma_cookie, &ncookies) != DDI_SUCCESS) { + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_get_iop_status: cannot bind memory")); + goto cleanup; + } + + ASSERT(ncookies == 1); + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_get_iop_status: dma_bind (vaddr %p paddr %x length %x)", + (void *)iop->status.bufp, dma_cookie.dmac_address, + (int)dma_cookie.dmac_size)); + + /* allocate a message frame from Inbound queue */ + msgp = (i2o_exec_status_get_message_t *)iop_msg_alloc(iop); + if (msgp == NULL) { + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_get_iop_status: trans_msg_alloc failed")); + (void) ddi_dma_unbind_handle(iop->status.dma_handle); + goto cleanup; + } + + /* construct the ExecStatusGet message */ + init_std_msghdr(iop, (i2o_message_frame_t *)msgp, 0x0, 0, + sizeof (i2o_exec_status_get_message_t), + I2O_EXEC_STATUS_GET); + ddi_put32(iop->nexus_trans->acc_handle, &msgp->ReplyBufferAddressLow, + dma_cookie.dmac_address); + ddi_put32(iop->nexus_trans->acc_handle, + &msgp->ReplyBufferAddressHigh, 0); + ddi_put32(iop->nexus_trans->acc_handle, &msgp->ReplyBufferLength, + sizeof (i2o_exec_status_get_reply_t)); + iop->status.bufp->SyncByte = 0; + +#ifdef I2O_DEBUG + if (i2o_debug & I2O_DEBUG_MSG) + dump_message((uint32_t *)msgp, "ExecStatusGet"); +#endif + + /* send the message to the IOP */ + (void) iop_msg_send(iop, (void *)msgp); + + /* + * Poll on the status block field 'SyncByte' because there is + * no reply to ExecStatusGet message. The IOP writes '0xFF' + * to 'SyncByte' field when it finished writing to the status + * block structure. + */ + + while (iop->status.bufp->SyncByte != 0xFF) { + delay(1); + /* sync DMA memory */ + (void) ddi_dma_sync(iop->status.dma_handle, + (off_t)&s->SyncByte, 1, DDI_DMA_SYNC_FORCPU); + } + + (void) ddi_dma_unbind_handle(iop->status.dma_handle); + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, "i2o_get_iop_status: SUCCEEDED")); + + return (SUCCESS); + + /* + * Error return; free up the allocated resources and return NULL. + */ +cleanup: + + if (iop->status.bufp != NULL) { + ddi_dma_mem_free(&iop->status.acc_hdl); + iop->status.bufp = NULL; + } + + if (iop->status.dma_handle != NULL) { + ddi_dma_free_handle(&iop->status.dma_handle); + iop->status.dma_handle = NULL; + } + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, "i2o_get_iop_status: FAILED")); + + return (FAILURE); +} + +/* + * Allocate message frames for the Outbound queue and send ExecOutboundInit + * message to the IOP. + * + * Description: + * Since we don't know how to determine how many frames to be + * allocated, we either depend on the user specified property + * (i.e ob-msg-queue-length) or use the current IOP's default. + * Allocate the message queue as one physically contiguous chunk. + * Send ExecOutboundInit message with the list of MFAs. + */ +static int +i2o_init_outbound_queue(iop_instance_t *iop) +{ + size_t real_length; + ddi_dma_cookie_t dma_cookie; + uint_t ncookies; + i2o_exec_outbound_init_message_t *msgp; + int nframes, max_nframes; + int frame_size; + i2o_sge_simple_element_t *sgl; + i2o_exec_outbound_init_status_t *stat; + uint_t mfa; + int count; + + if (iop->ob_msg_queue.dma_handle == NULL) { + + /* allocate a DMA handle */ + if (ddi_dma_alloc_handle(iop->dip, &dma_attr_contig, DDI_DMA_SLEEP, + NULL, &iop->ob_msg_queue.dma_handle) != DDI_SUCCESS) { + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_init_outbound_queue: ddi_dma_alloc_handle failed")); + goto cleanup; + } + } + + if (iop->ob_msg_queue.base_addr == NULL) { + + nframes = ddi_prop_get_int(DDI_DEV_T_ANY, iop->dip, + DDI_PROP_DONTPASS, "ob-msg-queue-length", + ob_msg_queue_length_default); + + max_nframes = ddi_get32(iop->status.acc_hdl, + &iop->status.bufp->MaxOutboundMFrames); + + if (nframes == 0 || nframes > max_nframes) + nframes = max_nframes; + + frame_size = ddi_prop_get_int(DDI_DEV_T_ANY, iop->dip, + DDI_PROP_DONTPASS, "ob-msg-framesize", + ob_msg_framesize_default); + + /* allocate the buffer for the message frames */ + if (ddi_dma_mem_alloc(iop->ob_msg_queue.dma_handle, + (size_t)(nframes * frame_size), &i2o_dev_acc_attr, + DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, + (caddr_t *)&iop->ob_msg_queue.base_addr, &real_length, + &iop->ob_msg_queue.acc_hdl) != DDI_SUCCESS) { + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_init_outbound_queue: ddi_dma_mem_alloc failed")); + goto cleanup; + } + bzero((caddr_t)iop->ob_msg_queue.base_addr, real_length); + iop->ob_msg_queue.nframes = nframes; + iop->ob_msg_queue.framesize = frame_size; + } + + if (ddi_dma_addr_bind_handle(iop->ob_msg_queue.dma_handle, NULL, + iop->ob_msg_queue.base_addr, + (iop->ob_msg_queue.nframes * iop->ob_msg_queue.framesize), + DDI_DMA_READ | DDI_DMA_STREAMING, DDI_DMA_SLEEP, + NULL, &dma_cookie, &ncookies) != DDI_SUCCESS) { + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_init_outbound_queue: cannot bind memory")); + goto cleanup; + } + + ASSERT(ncookies == 1); + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_init_outbound_queue: dma_bind (vaddr %p paddr %x length %x)", + (void *)iop->ob_msg_queue.base_addr, dma_cookie.dmac_address, + (int)dma_cookie.dmac_size)); + + iop->ob_msg_queue.base_paddr = (uint_t)dma_cookie.dmac_address; + + /* allocate a message frame from Inbound queue */ + msgp = (i2o_exec_outbound_init_message_t *)iop_msg_alloc(iop); + if (msgp == NULL) { + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_init_outbound_queue: trans_msg_alloc failed")); + + (void) ddi_dma_unbind_handle(iop->ob_msg_queue.dma_handle); + goto cleanup; + } + + /* + * Construct the ExecOutboundInit message. Use the base address + * of the outbound message queue buffer for the status word structure + * instead of allocating a new word. + */ + init_std_msghdr(iop, &msgp->StdMessageFrame, 0x60, 0, + sizeof (i2o_exec_outbound_init_message_t), + I2O_EXEC_OUTBOUND_INIT); + ddi_put32(iop->nexus_trans->acc_handle, &msgp->HostPageFrameSize, + MMU_PAGESIZE); + msgp->InitCode = I2O_MESSAGE_IF_INIT_CODE_OS; + ddi_put16(iop->nexus_trans->acc_handle, &msgp->OutboundMFrameSize, + ((uint16_t)frame_size) >> 2); + + sgl = (i2o_sge_simple_element_t *)&msgp->SGL; + init_sgl_simple_ele(iop, sgl, + I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, + 4, (uint_t)iop->ob_msg_queue.base_paddr); + + stat = (i2o_exec_outbound_init_status_t *)iop->ob_msg_queue.base_addr; + stat->InitStatus = 0; + +#ifdef I2O_DEBUG + if (i2o_debug & I2O_DEBUG_MSG) + dump_message((uint32_t *)msgp, "ExecOutboundInit"); +#endif + + /* send the message to the IOP */ + (void) iop_msg_send(iop, (void *)msgp); + + /* + * Poll on the status word for completion. + */ + while ((stat->InitStatus == 0) || + (stat->InitStatus == I2O_EXEC_OUTBOUND_INIT_IN_PROGRESS)) { + + delay(2); + /* sync DMA memory */ + (void) ddi_dma_sync(iop->ob_msg_queue.dma_handle, + 0, 1, DDI_DMA_SYNC_FORCPU); + } + + (void) ddi_dma_unbind_handle(iop->ob_msg_queue.dma_handle); + + if (stat->InitStatus != I2O_EXEC_OUTBOUND_INIT_COMPLETE) { + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_init_outbound_queue: FAILED (InitStatus %x)", + stat->InitStatus)); + goto cleanup; + } + + /* + * Now, write the MFAs to the Outbound FIFO. + */ + mfa = iop->ob_msg_queue.base_paddr; + for (count = 0; count < iop->ob_msg_queue.nframes; count ++) { + (* iop->nexus_trans->i2o_trans_msg_freebuf) + (iop->nexus_trans->nexus_handle, mfa); + mfa += iop->ob_msg_queue.framesize; + } + + DEBUGF(I2O_DEBUG_DEBUG, + (CE_CONT, "i2o_init_outbound_queue: SUCCEEDED")); + + return (SUCCESS); + + + /* + * Error return; free up the allocated resources and return NULL. + */ +cleanup: + + if (iop->ob_msg_queue.base_addr != NULL) { + ddi_dma_mem_free(&iop->ob_msg_queue.acc_hdl); + iop->ob_msg_queue.base_addr = NULL; + } + + if (iop->ob_msg_queue.dma_handle != NULL) { + ddi_dma_free_handle(&iop->ob_msg_queue.dma_handle); + iop->ob_msg_queue.dma_handle = NULL; + } + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, "i2o_init_outbound_queue: FAILED")); + + return (FAILURE); +} + +/* + * Get HRT by sending ExecHrtGet message to the IOP. + * It is assumed that Outbound queue is already initialized + * so that the IOP can send a reply to the ExecHrtGet message. + * Also it is assumed that the IOP interrupts are disabled. + */ +static int +i2o_get_hrt(iop_instance_t *iop) +{ + size_t real_length; + ddi_dma_cookie_t dma_cookie; + uint_t ncookies; + i2o_exec_hrt_get_message_t *msgp; + i2o_hrt_t *buf = NULL; + ddi_acc_handle_t acc_hdl; + i2o_single_reply_message_frame_t *rmp = NULL; + uint_t hrt_size; + + /* allocate a DMA handle if necessary */ + if (iop->hrt.dma_handle == NULL) { + if (ddi_dma_alloc_handle(iop->dip, &dma_attr_contig, DDI_DMA_SLEEP, + NULL, &iop->hrt.dma_handle) != DDI_SUCCESS) { + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_get_hrt: ddi_dma_alloc_handle failed")); + goto cleanup; + } + } + + /* + * Allocate a temporary buffer to get the HRT size information + * (i.e only header part of the HRT). + */ + if (ddi_dma_mem_alloc(iop->hrt.dma_handle, + sizeof (i2o_hrt_t), &i2o_dev_acc_attr, + DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, (caddr_t *)&buf, + &real_length, &acc_hdl) != DDI_SUCCESS) { + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_get_hrt: ddi_dma_mem_alloc failed")); + goto cleanup; + } + + bzero((caddr_t)buf, real_length); + + if (ddi_dma_addr_bind_handle(iop->hrt.dma_handle, NULL, (caddr_t)buf, + real_length, DDI_DMA_READ | DDI_DMA_STREAMING, DDI_DMA_SLEEP, + NULL, &dma_cookie, &ncookies) != DDI_SUCCESS) { + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_get_hrt: cannot bind memory")); + goto cleanup; + } + + ASSERT(ncookies == 1); + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_get_hrt: dma_bind (vaddr %p paddr %x length %x)", + (void *)buf, dma_cookie.dmac_address, + (int)dma_cookie.dmac_size)); + + /* allocate a message frame from Inbound queue */ + msgp = (i2o_exec_hrt_get_message_t *)iop_msg_alloc(iop); + if (msgp == NULL) { + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_get_hrt: trans_msg_alloc failed")); + (void) ddi_dma_unbind_handle(iop->hrt.dma_handle); + goto cleanup; + } + + /* + * Construct the ExecHrtGet message. + */ + init_std_msghdr(iop, &msgp->StdMessageFrame, 0x40, 0, + sizeof (i2o_exec_hrt_get_message_t), I2O_EXEC_HRT_GET); + init_sgl_simple_ele(iop, msgp->SGL.u1.Simple, + I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, + sizeof (i2o_hrt_t), (uint_t)dma_cookie.dmac_address); + +#ifdef I2O_DEBUG + if (i2o_debug & I2O_DEBUG_MSG) + dump_message((uint32_t *)msgp, "ExecHrtGet"); +#endif + + /* send the message to the IOP */ + (void) iop_msg_send(iop, (void *)msgp); + + /* since interrupts are disabled, we poll for the reply message */ + rmp = iop_poll_reply_msg(iop); + if ((rmp == NULL) || (rmp->ReqStatus != I2O_REPLY_STATUS_SUCCESS)) { + if (rmp) + iop_msg_free(iop, rmp); + (void) ddi_dma_unbind_handle(iop->hrt.dma_handle); + goto cleanup; + } + + ASSERT(get_msg_Function((i2o_message_frame_t *)rmp, + iop->ob_msg_queue.acc_hdl) == I2O_EXEC_HRT_GET); /* paranoia? */ + + /* free up the reply message buffer */ + iop_msg_free(iop, rmp); + + ASSERT(buf->HRTVersion == 0); /* HRT version for 1.5 is 0x00 */ + + hrt_size = (sizeof (i2o_hrt_t) - sizeof (i2o_hrt_entry_t)) + + (sizeof (i2o_hrt_entry_t) * + ddi_get16(acc_hdl, &buf->NumberEntries)); + + /* + * NOTE: Some old versions of RTOS is not setting the EntryLength + * correctly. Also, I am not sure if all implementations of RTOS + * set this field. So, the following ASSERTION is disabled. + * + * ASSERT((buf->EntryLength * 4) == sizeof (i2o_hrt_entry_t)); + */ + + /* free up the temporary buffer */ + (void) ddi_dma_unbind_handle(iop->hrt.dma_handle); + ddi_dma_mem_free(&acc_hdl); + buf = NULL; + + /* + * Now, allocate the correct size buffer for HRT and send another + * ExecHrtGet message. + */ + if (iop->hrt.bufp == NULL || (iop->hrt.size < hrt_size)) { + + /* free up any old buffer */ + if (iop->hrt.bufp != NULL) { + ddi_dma_mem_free(&iop->hrt.acc_hdl); + iop->hrt.bufp = NULL; + } + + iop->hrt.size = hrt_size; + + /* allocate a new buffer for HRT */ + if (ddi_dma_mem_alloc(iop->hrt.dma_handle, + iop->hrt.size, &i2o_dev_acc_attr, DDI_DMA_CONSISTENT, + DDI_DMA_SLEEP, NULL, (caddr_t *)&iop->hrt.bufp, + &real_length, &iop->hrt.acc_hdl) != DDI_SUCCESS) { + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_get_hrt: ddi_dma_mem_alloc failed")); + goto cleanup; + } + bzero((caddr_t)iop->hrt.bufp, real_length); + } + + if (ddi_dma_addr_bind_handle(iop->hrt.dma_handle, NULL, + (caddr_t)iop->hrt.bufp, iop->hrt.size, + DDI_DMA_READ | DDI_DMA_STREAMING, DDI_DMA_SLEEP, + NULL, &dma_cookie, &ncookies) != DDI_SUCCESS) { + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_get_hrt: cannot bind memory")); + goto cleanup; + } + + ASSERT(ncookies == 1); + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_get_hrt: dma_bind (vaddr %p paddr %x length %x)", + (void *)iop->hrt.bufp, dma_cookie.dmac_address, + (int)dma_cookie.dmac_size)); + + /* allocate a message frame from Inbound queue */ + msgp = (i2o_exec_hrt_get_message_t *)iop_msg_alloc(iop); + if (msgp == NULL) { + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_get_hrt: trans_msg_alloc failed")); + (void) ddi_dma_unbind_handle(iop->hrt.dma_handle); + goto cleanup; + } + + /* + * Construct the ExecHrtGet message (again!). + */ + init_std_msghdr(iop, &msgp->StdMessageFrame, 0x40, 0, + sizeof (i2o_exec_hrt_get_message_t), I2O_EXEC_HRT_GET); + init_sgl_simple_ele(iop, msgp->SGL.u1.Simple, + I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, + hrt_size, (uint_t)dma_cookie.dmac_address); + +#ifdef I2O_DEBUG + if (i2o_debug & I2O_DEBUG_MSG) + dump_message((uint32_t *)msgp, "ExecHrtGet"); +#endif + + /* send the message to the IOP */ + (void) iop_msg_send(iop, (void *)msgp); + + /* since interrupts are disabled, we poll for the reply message */ + rmp = iop_poll_reply_msg(iop); + if ((rmp == NULL) || (rmp->ReqStatus != I2O_REPLY_STATUS_SUCCESS)) { + if (rmp) + iop_msg_free(iop, rmp); +#ifdef I2O_DEBUG + if (i2o_debug & I2O_DEBUG_MSG) + dump_reply_message(iop, rmp); +#endif + (void) ddi_dma_unbind_handle(iop->hrt.dma_handle); + goto cleanup; + } + + ASSERT(get_msg_Function((i2o_message_frame_t *)rmp, + iop->ob_msg_queue.acc_hdl) == I2O_EXEC_HRT_GET); /* paranoia? */ + + /* free up the reply message buffer */ + iop_msg_free(iop, rmp); + + (void) ddi_dma_unbind_handle(iop->hrt.dma_handle); + +#ifdef I2O_DEBUG + if (i2o_debug & I2O_DEBUG_HRT) + dump_hrt(iop); +#endif + + return (SUCCESS); + + /* + * Error return; free up the allocated resources and return NULL. + */ +cleanup: + + if (buf != NULL) + ddi_dma_mem_free(&acc_hdl); + + if (iop->hrt.bufp != NULL) { + ddi_dma_mem_free(&iop->hrt.acc_hdl); + iop->hrt.bufp = NULL; + } + + if (iop->hrt.dma_handle != NULL) { + ddi_dma_free_handle(&iop->hrt.dma_handle); + iop->hrt.dma_handle = NULL; + } + + return (FAILURE); +} + + +/* + * Create the system table entry for the IOP and update all IOPs with + * the latest System Table. It sends ExecSysTabSet message to all + * IOPs. If necessary it sends the ExecSysEnable to the new IOP that + * is being initialized. + * + * Note: It is assumed that this routine is called from the IOP init + * routine. + */ +static int +i2o_create_systab(iop_instance_t *iop) +{ + ddi_dma_handle_t dma_handle = NULL; + ddi_acc_handle_t acc_hdl; + size_t real_length; + ddi_dma_cookie_t dma_cookie; + uint_t ncookies; + i2o_iop_entry_t *entp; + i2o_set_systab_header_t *systab = NULL; + i2o_iop_entry_t *systab_entryp; + int i; + iop_instance_t *p; + i2o_exec_sys_tab_set_message_t *msgp; + i2o_single_reply_message_frame_t *rmp = NULL; + uint_t systab_size; + tcontext_t tcxt; /* transaction context structure */ + + + /* + * ********************************************************* + * Create SysTab entry for this IOP. + * ********************************************************* + */ + if (ddi_dma_alloc_handle(iop->dip, &dma_attr_contig, DDI_DMA_SLEEP, + NULL, &iop->systab.dma_handle) != DDI_SUCCESS) { + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_create_systab: ddi_dma_alloc_handle failed")); + goto cleanup; + } + + /* allocate the buffer for systab entry */ + if (ddi_dma_mem_alloc(iop->systab.dma_handle, sizeof (i2o_iop_entry_t), + &i2o_dev_acc_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, + (caddr_t *)&iop->systab.bufp, &real_length, + &iop->systab.acc_hdl) != DDI_SUCCESS) { + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_create_systab: ddi_dma_mem_alloc failed")); + goto cleanup; + } + + bzero((caddr_t)iop->systab.bufp, real_length); + + /* + * initialize the systab entry with the information from the iop + * status buffer. + */ + entp = iop->systab.bufp; + entp->OrganizationID = iop->status.bufp->OrganizationID; + entp->IopCapabilities = iop->status.bufp->IopCapabilities; + entp->InboundMessageFrameSize = + iop->status.bufp->InboundMFrameSize; + entp->MessengerType = iop->status.bufp->MessengerType; + entp->IopState = I2O_IOP_STATE_OPERATIONAL; /* expected state */ + put_i2o_iop_entry_I2oVersion(entp, + get_i2o_exec_status_reply_I2oVersion(iop->status.bufp, + iop->status.acc_hdl), iop->systab.acc_hdl); + put_i2o_iop_entry_SegmentNumber(entp, + get_i2o_exec_status_reply_SegmentNumber(iop->status.bufp, + iop->status.acc_hdl), iop->systab.acc_hdl); + put_i2o_iop_entry_IOP_ID(entp, iop->iop_id, iop->systab.acc_hdl); + ddi_put32(iop->systab.acc_hdl, + &entp->MessengerInfo.InboundMessagePortAddressLow, + iop->nexus_trans->iop_inbound_fifo_paddr); + ddi_put32(iop->systab.acc_hdl, + &entp->MessengerInfo.InboundMessagePortAddressHigh, 0); + + /* + * ********************************************************* + * Create a System Table for sending ExecSysTabSet message + * to all IOP(s). + * ********************************************************* + */ + /* allocate the buffer for systab header and for the systab entries */ + systab_size = sizeof (i2o_set_systab_header_t) + + (niop * sizeof (i2o_iop_entry_t)); + + if (ddi_dma_alloc_handle(iop->dip, &dma_attr_contig, DDI_DMA_SLEEP, + NULL, &dma_handle) != DDI_SUCCESS) { + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_create_systab: ddi_dma_alloc_handle failed")); + goto cleanup; + } + + if (ddi_dma_mem_alloc(dma_handle, systab_size, + &i2o_dev_acc_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, + (caddr_t *)&systab, &real_length, + &acc_hdl) != DDI_SUCCESS) { + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_create_systab: ddi_dma_mem_alloc failed")); + goto cleanup; + } + + bzero((caddr_t)systab, real_length); + + /* fill in the systab header and systab entries */ + systab->NumberEntries = niop; + systab->SysTabVersion = I2O_VERSION_11; + ddi_put32(iop->systab.acc_hdl, &systab->CurrentChangeIndicator, + (uint32_t)(iop->iop_id - BASE_IOP_ID)); + + systab_entryp = (i2o_iop_entry_t *)&systab[1]; + iop->next = ioplist; + + for (p = iop, i = 0; i < niop; i++) { + systab_entryp[i] = p->systab.bufp[0]; + p = p->next; + } + + if (ddi_dma_addr_bind_handle(dma_handle, NULL, (caddr_t)systab, + real_length, DDI_DMA_WRITE | DDI_DMA_STREAMING, DDI_DMA_SLEEP, + NULL, &dma_cookie, &ncookies) != DDI_SUCCESS) { + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_create_systab: cannot bind memory")); + goto cleanup; + } + + ASSERT(ncookies == 1); + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_create_systab: dma_bind (vaddr %p paddr %x length %x)", + (void *)systab, dma_cookie.dmac_address, + (int)dma_cookie.dmac_size)); + + /* Now, send ExecSysTabSet message to each of the IOPs */ + for (p = iop, i = 0; i < niop; i++) { + + /* allocate a message frame from Inbound queue */ + msgp = (i2o_exec_sys_tab_set_message_t *)iop_msg_alloc(p); + if (msgp == NULL) { + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_create_systab: trans_msg_alloc failed")); + (void) ddi_dma_unbind_handle(dma_handle); + goto cleanup; + } + /* + * Construct the ExecSysTabSet message. + * + * Note: The implied assumption is that the message frame has + * enough room for 3 SGL elements. + */ + + init_std_msghdr(p, &msgp->StdMessageFrame, 0x40, 0, + sizeof (i2o_exec_sys_tab_set_message_t) + + 2 * sizeof (i2o_sg_element_t), I2O_EXEC_SYS_TAB_SET); + msgp->HostUnitID = 0; + put_i2o_exec_sys_tab_set_SegmentNumber(msgp, + get_i2o_exec_status_reply_SegmentNumber(p->status.bufp, + p->status.acc_hdl), p->systab.acc_hdl); + put_i2o_exec_sys_tab_set_IOP_ID(msgp, p->iop_id, + p->systab.acc_hdl); + + if (p != iop) { + /* + * For other IOPs we don't poll the reply, so + * setup the InitiatorContext/TransactionContext. + */ + cv_init(&tcxt.cv, NULL, CV_DEFAULT, NULL); + mutex_init(&tcxt.cv_mutex, NULL, MUTEX_DRIVER, NULL); + /* initialize the transcation context structure */ + tcxt.iop = p; + tcxt.done_flag = 0; + ddi_put32(p->nexus_trans->acc_handle, + &msgp->TransactionContext, + (uint32_t)(uintptr_t)&tcxt); + ddi_put32(p->nexus_trans->acc_handle, + (uint32_t *)&msgp->StdMessageFrame.InitiatorContext. + initiator_context_32bits, + (uint32_t)i2o_msg_common_reply); + } + + /* First buffer is for systab itself */ + init_sgl_simple_ele(p, &msgp->SGL.u1.Simple[0], + I2O_SGL_FLAGS_END_OF_BUFFER, systab_size, + (uint_t)dma_cookie.dmac_address); + + /* + * Second buffer is for Private Memory Space allocation. + * + * Note: The spec is not clear if this buffer can be NULL + * for the IOP which was already initialized to OP state + * and there is no change to its configuration. Here, we + * will set it to NULL assuming that it is ignored. + */ + if (p == iop) { + init_sgl_simple_ele(p, &msgp->SGL.u1.Simple[1], + I2O_SGL_FLAGS_END_OF_BUFFER, + p->hw_config.mem_size, (uint_t)p->hw_config.mem_base); + } else { + init_sgl_simple_ele(p, &msgp->SGL.u1.Simple[1], + I2O_SGL_FLAGS_END_OF_BUFFER, 0, 0); + } + + /* + * Third buffer is for Private IO Space allocation. + * + * Note: The spec is not clear if this buffer can be NULL + * for the IOP which was already initialized to OP state + * and there is no change to its configuration. Here, we + * will set it to NULL assuming that it is ignored. + */ + if (p == iop) { + init_sgl_simple_ele(p, &msgp->SGL.u1.Simple[2], + I2O_SGL_FLAGS_LAST_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER, + p->hw_config.io_size, (uint_t)p->hw_config.io_base); + } else { + init_sgl_simple_ele(p, &msgp->SGL.u1.Simple[2], + I2O_SGL_FLAGS_LAST_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER, 0, 0); + } + +#ifdef I2O_DEBUG + if (i2o_debug & I2O_DEBUG_MSG) + dump_message((uint32_t *)msgp, "ExecSysTabSet"); +#endif + + /* send the message to the IOP */ + (void) iop_msg_send(p, (void *)msgp); + + /* wait for the reply message */ + if (p == iop) { + /* + * For this IOP, interrupts are disabled. So, we poll + * for the reply message. + */ + rmp = iop_poll_reply_msg(p); + + if ((rmp == NULL) || + (rmp->ReqStatus != I2O_REPLY_STATUS_SUCCESS)) { + + if (rmp) + iop_msg_free(p, rmp); +#ifdef I2O_DEBUG + if (i2o_debug & I2O_DEBUG_MSG) + dump_reply_message(p, rmp); +#endif + (void) ddi_dma_unbind_handle(dma_handle); + goto cleanup; + } + + /* paranoia? */ + ASSERT(get_msg_Function((i2o_message_frame_t *)rmp, + iop->ob_msg_queue.acc_hdl) == I2O_EXEC_SYS_TAB_SET); + + /* free up the reply message buffer */ + iop_msg_free(p, rmp); + + } else { + /* For other IOPs, wait for the reply message */ + mutex_enter(&tcxt.cv_mutex); + while (!tcxt.done_flag) /* wait for the reply */ + cv_wait(&tcxt.cv, &tcxt.cv_mutex); + mutex_exit(&tcxt.cv_mutex); + + cv_destroy(&tcxt.cv); + mutex_destroy(&tcxt.cv_mutex); + + /* check the status for SUCCESS */ + if (tcxt.status != I2O_REPLY_STATUS_SUCCESS) { + (void) ddi_dma_unbind_handle(dma_handle); + goto cleanup; + } + } + + /* + * For the new IOP, send the ExecSysEnable message. + */ + if (p == iop) { + if (i2o_send_exec_enable(iop) != SUCCESS) { + (void) ddi_dma_unbind_handle(dma_handle); + goto cleanup; + } + } + } + + (void) ddi_dma_unbind_handle(dma_handle); + + if (iop->status.bufp->IopState != I2O_IOP_STATE_OPERATIONAL) { + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_create_systab: invalid IOP state")); + goto cleanup; + } + + ddi_dma_mem_free(&acc_hdl); /* free the systab buffer */ + + ddi_dma_free_handle(&dma_handle); + + return (SUCCESS); + + /* + * Error return; free up the allocated resources and return NULL. + */ +cleanup: + + if (iop->systab.bufp != NULL) { + ddi_dma_mem_free(&iop->systab.acc_hdl); + iop->systab.bufp = NULL; + } + + if (iop->systab.dma_handle != NULL) { + ddi_dma_free_handle(&iop->systab.dma_handle); + iop->systab.dma_handle = NULL; + } + + if (systab != NULL) + ddi_dma_mem_free(&acc_hdl); + + if (dma_handle != NULL) + ddi_dma_free_handle(&dma_handle); + + return (FAILURE); +} + +/* + * Send the ExecSysEnable message to the IOP if it is in the + * READY state. It assumes that the IOP interrupts are disabled. + */ +static int +i2o_send_exec_enable(iop_instance_t *iop) +{ + i2o_exec_sys_enable_message_t *mp; + i2o_single_reply_message_frame_t *rmp = NULL; + + /* + * Get the current state of IOP. + */ + if (i2o_get_iop_status(iop) == FAILURE) + goto cleanup; + + if (iop->status.bufp->IopState == I2O_IOP_STATE_READY) { + /* allocate a message frame from Inbound queue */ + mp = (i2o_exec_sys_enable_message_t *)iop_msg_alloc(iop); + if (mp == NULL) { + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_create_systab: trans_msg_alloc failed")); + goto cleanup; + } + + /* Construct the ExecSysEanble message. */ + init_std_msghdr(iop, &mp->StdMessageFrame, 0x0, 0, + sizeof (i2o_exec_sys_enable_message_t), I2O_EXEC_SYS_ENABLE); + +#ifdef I2O_DEBUG + if (i2o_debug & I2O_DEBUG_MSG) + dump_message((uint32_t *)mp, "ExecSysEnable"); +#endif + + /* send the message to the IOP */ + (void) iop_msg_send(iop, (void *)mp); + + /* since interrupts are disabled, we poll for the reply message */ + rmp = iop_poll_reply_msg(iop); + if ((rmp == NULL) || (rmp->ReqStatus != I2O_REPLY_STATUS_SUCCESS)) { +#ifdef I2O_DEBUG + if (i2o_debug & I2O_DEBUG_MSG) + dump_reply_message(iop, rmp); +#endif + if (rmp) + iop_msg_free(iop, rmp); + goto cleanup; + } + + /* paranoia? */ + ASSERT(get_msg_Function((i2o_message_frame_t *)rmp, + iop->ob_msg_queue.acc_hdl) == I2O_EXEC_SYS_ENABLE); + + iop_msg_free(iop, rmp); /* free up the reply message buffer */ + + /* get the IOP state now; it should be in OPERATIONAL state */ + if (i2o_get_iop_status(iop) == FAILURE) + goto cleanup; + } + + return (SUCCESS); + +cleanup: + return (FAILURE); +} + +/* + * Send an ExecIopReset message. This function is called from the + * i2o_msg_iop_init() with interrupts disabled. + */ +static int +i2o_send_exec_iop_reset(iop_instance_t *iop) +{ + ddi_dma_handle_t dma_handle = NULL; + ddi_acc_handle_t acc_hdl; + i2o_exec_iop_reset_status_t *buf = NULL; + i2o_exec_iop_reset_message_t *rmsgp; + size_t real_length; + ddi_dma_cookie_t dma_cookie; + uint_t ncookies; + + /* allocate a DMA handle */ + if (ddi_dma_alloc_handle(iop->dip, &dma_attr_contig, DDI_DMA_SLEEP, + NULL, &dma_handle) != DDI_SUCCESS) { + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_send_exec_iop_reset: ddi_dma_alloc_handle failed")); + goto cleanup; + } + + /* + * Allocate a temporary buffer for the status word structure. + */ + if (ddi_dma_mem_alloc(dma_handle, + sizeof (i2o_exec_iop_reset_status_t), &i2o_dev_acc_attr, + DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, (caddr_t *)&buf, + &real_length, &acc_hdl) != DDI_SUCCESS) { + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_send_exec_iop_reset: ddi_dma_mem_alloc failed")); + goto cleanup; + } + + if (ddi_dma_addr_bind_handle(dma_handle, NULL, (caddr_t)buf, + real_length, DDI_DMA_READ | DDI_DMA_STREAMING, DDI_DMA_SLEEP, + NULL, &dma_cookie, &ncookies) != DDI_SUCCESS) { + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_send_exec_iop_reset: cannot bind memory")); + goto cleanup; + } + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_send_exec_iop_reset: dma_bind (vaddr %p paddr %x length %x)", + (void *)buf, dma_cookie.dmac_address, (int)dma_cookie.dmac_size)); + + /* allocate a message frame from Inbound queue */ + rmsgp = (i2o_exec_iop_reset_message_t *)iop_msg_alloc(iop); + if (rmsgp == NULL) { + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_send_exec_iop_reset: trans_msg_alloc failed")); + (void) ddi_dma_unbind_handle(dma_handle); + goto cleanup; + } + + /* construct the ExecIopReset message */ + init_std_msghdr(iop, (i2o_message_frame_t *)rmsgp, 0x0, 0, + sizeof (i2o_exec_iop_reset_message_t), + I2O_EXEC_IOP_RESET); + ddi_put32(iop->nexus_trans->acc_handle, &rmsgp->StatusWordLowAddress, + dma_cookie.dmac_address); + ddi_put32(iop->nexus_trans->acc_handle, + &rmsgp->StatusWordHighAddress, 0); + buf->ResetStatus = 0; + +#ifdef I2O_DEBUG + if (i2o_debug & I2O_DEBUG_MSG) + dump_message((uint32_t *)rmsgp, "ExecIopReset"); +#endif + + /* send the message to the IOP */ + (void) iop_msg_send(iop, (void *)rmsgp); + + /* poll on the status word for IN_PROGRESS state */ + while (buf->ResetStatus != I2O_EXEC_IOP_RESET_IN_PROGRESS) { + int mseconds = 60000; /* 60 seconds */ + + if (buf->ResetStatus == I2O_EXEC_IOP_RESET_REJECTED) + goto cleanup; + + if (--mseconds < 0) { + DEBUGF(I2O_DEBUG_DEBUG, + (CE_CONT, "iop_reset: timed out")); + goto cleanup; + } + + drv_usecwait(1000); /* wait for 1msec */ + + /* sync DMA memory */ + (void) ddi_dma_sync(dma_handle, 0, 1, DDI_DMA_SYNC_FORCPU); + } + + (void) ddi_dma_unbind_handle(dma_handle); + + ddi_dma_mem_free(&acc_hdl); + + ddi_dma_free_handle(&dma_handle); + + return (SUCCESS); + + /* + * Error return; free up the allocated resources and return NULL. + */ +cleanup: + if (buf != NULL) + ddi_dma_mem_free(&acc_hdl); + + if (dma_handle != NULL) + ddi_dma_free_handle(&dma_handle); + + return (FAILURE); +} + + +static int +i2o_get_lct(iop_instance_t *iop) +{ + size_t real_length; + ddi_dma_cookie_t dma_cookie; + uint_t ncookies; + i2o_exec_lct_notify_message_t *msgp; + i2o_single_reply_message_frame_t *rmp = NULL; + uint_t lct_size; + + /* allocate a DMA handle if necessary */ + if (iop->lct.dma_handle == NULL) { + if (ddi_dma_alloc_handle(iop->dip, &dma_attr_contig, DDI_DMA_SLEEP, + NULL, &iop->lct.dma_handle) != DDI_SUCCESS) { + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_get_lct: ddi_dma_alloc_handle failed")); + goto cleanup; + } + } + + lct_size = ddi_get32(iop->status.acc_hdl, + &iop->status.bufp->ExpectedLCTSize); + /* + * Allocate the buffer for LCT and send ExecLctNotify message. + */ + if (iop->lct.bufp == NULL || (iop->lct.size < lct_size)) { + + /* free up any old buffer */ + if (iop->lct.bufp != NULL) { + ddi_dma_mem_free(&iop->lct.acc_hdl); + iop->lct.bufp = NULL; + } + + iop->lct.size = lct_size; + + /* allocate a new buffer for LCT */ + if (ddi_dma_mem_alloc(iop->lct.dma_handle, + iop->lct.size, &i2o_dev_acc_attr, DDI_DMA_CONSISTENT, + DDI_DMA_SLEEP, NULL, (caddr_t *)&iop->lct.bufp, + &real_length, &iop->lct.acc_hdl) != DDI_SUCCESS) { + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_get_lct: ddi_dma_mem_alloc failed")); + goto cleanup; + } + + bzero((caddr_t)iop->lct.bufp, real_length); + } + + if (ddi_dma_addr_bind_handle(iop->lct.dma_handle, NULL, + (caddr_t)iop->lct.bufp, iop->lct.size, + DDI_DMA_READ | DDI_DMA_STREAMING, DDI_DMA_SLEEP, + NULL, &dma_cookie, &ncookies) != DDI_SUCCESS) { + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_get_lct: cannot bind memory")); + goto cleanup; + } + + ASSERT(ncookies == 1); + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_get_lct: dma_bind (vaddr %p paddr %x length %x)", + (void *)iop->lct.bufp, dma_cookie.dmac_address, + (int)dma_cookie.dmac_size)); + + /* allocate a message frame from Inbound queue */ + msgp = (i2o_exec_lct_notify_message_t *)iop_msg_alloc(iop); + if (msgp == NULL) { + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_get_lct: trans_msg_alloc failed")); + (void) ddi_dma_unbind_handle(iop->lct.dma_handle); + goto cleanup; + } + + /* + * Construct the ExecLctNotify message. + */ + init_std_msghdr(iop, &msgp->StdMessageFrame, 0x60, 0, + sizeof (i2o_exec_lct_notify_message_t), I2O_EXEC_LCT_NOTIFY); + msgp->ClassIdentifier = (uint32_t)0xFFFFFFFF; + msgp->LastReportedChangeIndicator = 0x0; + init_sgl_simple_ele(iop, msgp->SGL.u1.Simple, + I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, + iop->lct.size, (uint_t)dma_cookie.dmac_address); + +#ifdef I2O_DEBUG + if (i2o_debug & I2O_DEBUG_MSG) + dump_message((uint32_t *)msgp, "ExecLctNotify"); +#endif + + /* send the message to the IOP */ + (void) iop_msg_send(iop, (void *)msgp); + + /* since interrupts are disabled, we poll for the reply message */ + rmp = iop_poll_reply_msg(iop); + if ((rmp == NULL) || (rmp->ReqStatus != I2O_REPLY_STATUS_SUCCESS)) { + +#ifdef I2O_DEBUG + if (i2o_debug & I2O_DEBUG_MSG) + dump_reply_message(iop, rmp); +#endif + if (rmp) + iop_msg_free(iop, rmp); + (void) ddi_dma_unbind_handle(iop->lct.dma_handle); + goto cleanup; + } + + /* paranoia? */ + ASSERT(get_msg_Function((i2o_message_frame_t *)rmp, + iop->ob_msg_queue.acc_hdl) == I2O_EXEC_LCT_NOTIFY); + + /* free up the reply message buffer */ + iop_msg_free(iop, rmp); + + (void) ddi_dma_unbind_handle(iop->lct.dma_handle); + +#ifdef I2O_DEBUG + if (i2o_debug & I2O_DEBUG_LCT) + dump_lct(iop); +#endif + + return (SUCCESS); + + /* + * Error return; free up the allocated resources and return NULL. + */ +cleanup: + + if (iop->lct.bufp != NULL) { + ddi_dma_mem_free(&iop->lct.acc_hdl); + iop->lct.bufp = NULL; + } + + if (iop->lct.dma_handle != NULL) { + ddi_dma_free_handle(&iop->lct.dma_handle); + iop->lct.dma_handle = NULL; + } + + return (FAILURE); +} + +#define EXEC_CLASS_EVENT_MASK \ + (I2O_EVENT_IND_RESOURCE_LIMIT | I2O_EVENT_IND_CONNECTION_FAIL | \ + I2O_EVENT_IND_ADAPTER_FAULT | I2O_EVENT_IND_POWER_FAIL | \ + I2O_EVENT_IND_RESET_PENDING | I2O_EVENT_IND_RESET_IMMINENT | \ + I2O_EVENT_IND_HARDWARE_FAIL | I2O_EVENT_IND_XCT_CHANGE | \ + I2O_EVENT_IND_NEW_LCT_ENTRY | I2O_EVENT_IND_MODIFIED_LCT | \ + I2O_EVENT_IND_DDM_AVAILABILITY) + +/* + * Register Executive Class events to get notified by the IOP when + * any of these events occur. + * + * Assumpition: IOP interrupts are disabled. + */ +static int +i2o_iop_event_register(iop_instance_t *iop) +{ + i2o_util_event_register_message_t *msgp; + + /* allocate a message frame from Inbound queue */ + msgp = (i2o_util_event_register_message_t *)iop_msg_alloc(iop); + if (msgp == NULL) { + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_iop_event_register: trans_msg_alloc failed")); + return (FAILURE); + } + + /* + * Construct the UtilEventRegister message. There is no reply + * to this message until one of the specified events occurs. + */ + init_std_msghdr(iop, &msgp->StdMessageFrame, 0x0, 0, + sizeof (i2o_util_event_register_message_t), + I2O_UTIL_EVENT_REGISTER); + ddi_put32(iop->nexus_trans->acc_handle, + &msgp->TransactionContext, (uint32_t)(uintptr_t)iop); + ddi_put32(iop->nexus_trans->acc_handle, + (uint32_t *)&msgp->StdMessageFrame.InitiatorContext. + initiator_context_32bits, (uint32_t)i2o_msg_iop_event_reply); + /* Fow now, specify only the Executive Class events and */ + /* Config Dialog request event */ + ddi_put32(iop->nexus_trans->acc_handle, &msgp->EventMask, + EXEC_CLASS_EVENT_MASK | I2O_EVENT_IND_CONFIGURATION_FLAG); + + iop->event_mask = EXEC_CLASS_EVENT_MASK; + +#ifdef I2O_DEBUG + if (i2o_debug & I2O_DEBUG_MSG) + dump_message((uint32_t *)msgp, "UtilEventRegister"); +#endif + + /* send the message to the IOP */ + (void) iop_msg_send(iop, (void *)msgp); + + return (SUCCESS); +} + +/* + * called by the I2O nexus driver from i2o_create_devinfo(). + */ +void +i2o_msg_get_lct_info(i2o_iop_handle_t *handlep, i2o_lct_t **lctp, + ddi_acc_handle_t *acc_handlep) +{ + iop_instance_t *iop = ((i2o_iop_impl_hdl_t *)handlep)->iop; + + if (lctp) + *lctp = iop->lct.bufp; + + if (acc_handlep) + *acc_handlep = iop->lct.acc_hdl; +} + + +/* + * ************************************************************************ + * *** Reply Message Processing functions *** + * ************************************************************************ + */ + +/* + * Call back function to process the Executive Class event notification + * messages. + * + * For now, we process only the MODIFY_LCT event to update the local + * copy of the LCT. For other events we simply print the event information + * and ignore it. XXX FIX IT WHEN NEEDED XXX + */ +static void +i2o_msg_iop_event_reply(void *p, ddi_acc_handle_t acc_hdl) +{ + i2o_util_event_register_reply_t *msgp; + iop_instance_t *iop; + uint32_t event_indicator; + i2o_hrt_entry_t *hrt_entp; + i2o_lct_entry_t *lct_entp; + i2o_lct_entry_t *lp; + uint_t tid; + int i, n; + uint32_t event_data; + + msgp = (i2o_util_event_register_reply_t *)p; + iop = (iop_instance_t *) + (uintptr_t)ddi_get32(acc_hdl, &msgp->TransactionContext); + event_indicator = ddi_get32(acc_hdl, &msgp->EventIndicator); + + switch (event_indicator) { + + case I2O_EVENT_IND_ADAPTER_FAULT: + hrt_entp = (i2o_hrt_entry_t *)msgp->EventData; + cmn_err(CE_CONT, + "^Received ADAPTER_FAULT event from the IOP %x", + iop->iop_id); + cmn_err(CE_CONT, "^\tAdapterID: %x\n", ddi_get32(acc_hdl, + &hrt_entp->AdapterID)); + cmn_err(CE_CONT, "^\tControllingTID: %x\n", + get_hrt_entry_ControllingTID(hrt_entp, acc_hdl)); + cmn_err(CE_CONT, "^\tAdapterState: %x\n", + get_hrt_entry_AdapterState(hrt_entp, acc_hdl)); + cmn_err(CE_CONT, "^\tBusType: %x\n", hrt_entp->BusType); + cmn_err(CE_CONT, "^\tBusNumber: %x\n", hrt_entp->BusNumber); + break; + + case I2O_EVENT_IND_CONNECTION_FAIL: + cmn_err(CE_CONT, + "^Received CONNECTION_FAIL event from the IOP %x", + iop->iop_id); + break; + + case I2O_EVENT_IND_DDM_AVAILABILITY: + cmn_err(CE_CONT, + "^Received DDM_AVAILABILITY event from the IOP %x", + iop->iop_id); + event_data = ddi_get32(acc_hdl, msgp->EventData); + cmn_err(CE_CONT, "^\tTID %x Error Code %x", event_data & 0xFFF, + (event_data >> 12) & 0xF); + break; + + case I2O_EVENT_IND_HARDWARE_FAIL: + cmn_err(CE_CONT, + "^Received HARDWARE_FAIL event from the IOP %x", + iop->iop_id); + event_data = ddi_get32(acc_hdl, msgp->EventData); + cmn_err(CE_CONT, "^\tError Code %x", event_data); + break; + + case I2O_EVENT_IND_MODIFIED_LCT: + /* + * LCT entry is modified. Need to update the local + * copy of the LCT. + */ + + lct_entp = (i2o_lct_entry_t *)msgp->EventData; + tid = get_lct_entry_LocalTID(lct_entp, acc_hdl); + + /* + * locate the entry in the local copy of the LCT that + * matches the TID that has changed. And update the entry. + */ + mutex_enter(&iop->lct.lct_mutex); + + lp = iop->lct.bufp->LCTEntry; + n = ((ddi_get16(iop->lct.acc_hdl, &iop->lct.bufp->TableSize) << + 2) - sizeof (i2o_lct_t) + sizeof (i2o_lct_entry_t)) / + sizeof (i2o_lct_entry_t); + + for (i = 0; i < n; i++) { + if (tid == get_lct_entry_LocalTID(&lp[i], iop->lct.acc_hdl)) + break; + } + + ASSERT(i < n); + + /* copy the modified entry */ + lp[i] = *lct_entp; + + mutex_exit(&iop->lct.lct_mutex); + +#ifdef I2O_DEBUG + cmn_err(CE_CONT, "!Received MODIFY_LCT event from the IOP %x", + iop->iop_id); + cmn_err(CE_CONT, "!\tLocalTID: %x\n", + get_lct_entry_LocalTID(lct_entp, acc_hdl)); + cmn_err(CE_CONT, "!\tDeviceFlags: %x\n", + ddi_get32(acc_hdl, &lct_entp->DeviceFlags)); + cmn_err(CE_CONT, "!\tChangeIndicator: %x\n", + ddi_get32(acc_hdl, &lct_entp->ChangeIndicator)); + cmn_err(CE_CONT, "!\tClass: %x\n", + get_lct_entry_Class(lct_entp, acc_hdl)); + cmn_err(CE_CONT, "!\tSubClassInfo: %x\n", + ddi_get32(acc_hdl, &lct_entp->SubClassInfo)); + cmn_err(CE_CONT, "!\tParentTID: %x\n", + get_lct_entry_ParentTID(lct_entp, acc_hdl)); + cmn_err(CE_CONT, "!\tUserTID: %x\n", + get_lct_entry_UserTID(lct_entp, acc_hdl)); + cmn_err(CE_CONT, "!\tEventCapabilities: %x\n", + ddi_get32(acc_hdl, &lct_entp->EventCapabilities)); +#endif + break; + + case I2O_EVENT_IND_NEW_LCT_ENTRY: + cmn_err(CE_CONT, + "^Received NEW_LCT_ENTRY event from the IOP %x", + iop->iop_id); + lct_entp = (i2o_lct_entry_t *)msgp->EventData; + cmn_err(CE_CONT, "^\tLocalTID: %x\n", + get_lct_entry_LocalTID(lct_entp, acc_hdl)); + cmn_err(CE_CONT, "^\tDeviceFlags: %x\n", + ddi_get32(acc_hdl, &lct_entp->DeviceFlags)); + cmn_err(CE_CONT, "^\tChangeIndicator: %x\n", + ddi_get32(acc_hdl, &lct_entp->ChangeIndicator)); + cmn_err(CE_CONT, "^\tClass: %x\n", + get_lct_entry_Class(lct_entp, acc_hdl)); + cmn_err(CE_CONT, "^\tSubClassInfo: %x\n", + ddi_get32(acc_hdl, &lct_entp->SubClassInfo)); + cmn_err(CE_CONT, "^\tParentTID: %x\n", + get_lct_entry_ParentTID(lct_entp, acc_hdl)); + cmn_err(CE_CONT, "^\tUserTID: %x\n", + get_lct_entry_UserTID(lct_entp, acc_hdl)); + cmn_err(CE_CONT, "^\tEventCapabilities: %x\n", + ddi_get32(acc_hdl, &lct_entp->EventCapabilities)); + break; + + case I2O_EVENT_IND_POWER_FAIL: + cmn_err(CE_CONT, "^Received POWER_FAIL event from the IOP %x", + iop->iop_id); + break; + + case I2O_EVENT_IND_RESOURCE_LIMIT: + cmn_err(CE_CONT, + "^Received RESOURCE_LIMITS event from the IOP %x", + iop->iop_id); + event_data = ddi_get32(acc_hdl, msgp->EventData); + cmn_err(CE_CONT, "^\tError Code %x", event_data); + break; + + case I2O_EVENT_IND_XCT_CHANGE: + cmn_err(CE_CONT, "^Received XCT_CHANGE event from the IOP %x", + iop->iop_id); + break; + + case I2O_EVENT_IND_RESET_IMMINENT: + cmn_err(CE_CONT, + "^Received RESET_IMMINENT event from the IOP %x", + iop->iop_id); + break; + + case I2O_EVENT_IND_RESET_PENDING: + cmn_err(CE_CONT, + "^Received RESET_PENDING event from the IOP %x", + iop->iop_id); + break; + + case I2O_EVENT_IND_CONFIGURATION_FLAG: + cmn_err(CE_CONT, + "^Received CONFIGURATION_FLAG event from the IOP %x", + iop->iop_id); + break; + } +} + +/* + * Common reply message processing function: It simply copies the status + * code and sets the done_flag in the tcontext structure. + */ +static void +i2o_msg_common_reply(void *p, ddi_acc_handle_t acc_hdl) +{ + tcontext_t *tp; + + tp = (tcontext_t *)(uintptr_t)ddi_get32(acc_hdl, + &((i2o_single_reply_message_frame_t *)p)->TransactionContext); + + mutex_enter(&tp->cv_mutex); + tp->status = (int)((i2o_single_reply_message_frame_t *)p)->ReqStatus; + tp->done_flag = 1; + cv_broadcast(&tp->cv); + mutex_exit(&tp->cv_mutex); +} + +/* + * ************************************************************************ + * *** Implementation of OSM interfaces (PSARC: 1997/173) *** + * ************************************************************************ + */ + +/* + * Register the OSM for the specified I2O device. + * + * Implementation: The simplest implementation is to use the TID of + * the I2O device as the key to avoid multiple registrations. Since + * the max number of TIDs allocated is not big (< 32) we can simply + * maintain an array and use TID as the index. From the dip we need + * to find the IOP that this device belongs to. Currently, we do + * this by looking into the ioplist that matches with the devinfo + * node pointer of the parent for this device. + */ +int +i2o_msg_osm_register(dev_info_t *dip, i2o_iop_handle_t *handlep) +{ + uint_t tid; + dev_info_t *pdip; + iop_instance_t *iop; + i2o_iop_impl_hdl_t *hdl; + + /* get the TID for this device */ + tid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, + DDI_PROP_DONTPASS, "i2o-device-id", -1); + if (tid == (uint_t)-1) + return (DDI_FAILURE); + + /* + * Find the IOP that matches the parent of this device. + */ + pdip = ddi_get_parent(dip); + mutex_enter(&i2o_mutex); + for (iop = ioplist; iop; iop = iop->next) { + if (iop->dip == pdip) + break; + } + mutex_exit(&i2o_mutex); + + if (iop == NULL) + return (DDI_FAILURE); + + mutex_enter(&iop->osm_registry.osm_mutex); + + ASSERT(tid <= iop->osm_registry.max_tid); + + hdl = &iop->osm_registry.iop_handle_tab[tid]; + + /* verify that the device is not already registerd. */ + if (hdl->dip != NULL) { + mutex_exit(&iop->osm_registry.osm_mutex); + return (DDI_FAILURE); + } + + hdl->dip = dip; + hdl->iop = iop; + hdl->tid = tid; + + mutex_exit(&iop->osm_registry.osm_mutex); + + *handlep = (i2o_iop_handle_t *)hdl; + + return (DDI_SUCCESS); +} + +void +i2o_msg_osm_unregister(i2o_iop_handle_t *handlep) +{ + iop_instance_t *iop; + i2o_iop_impl_hdl_t *hdl = *(i2o_iop_impl_hdl_t **)handlep; + + iop = hdl->iop; + + ASSERT(hdl->tid <= iop->osm_registry.max_tid); + + mutex_enter(&iop->osm_registry.osm_mutex); + + hdl->dip = NULL; + hdl->iop = NULL; + hdl->tid = NULL; + + mutex_exit(&iop->osm_registry.osm_mutex); + + *handlep = NULL; +} + +/* + * Allocate a message frame for sending an I2O request message. + * + * Description: We allocate a system memory buffer so that the caller + * can take his own time to prepare the message. When the caller + * calls i2o_msg_send() then we allocate the real message frame + * from the inbound queue and free up the system memory buffer + * after copying the data. + */ +int +i2o_msg_alloc(i2o_iop_handle_t iop_hdl, int (*waitfp)(caddr_t), + caddr_t arg, void **msgp, i2o_msg_handle_t *msg_handlep, + ddi_acc_handle_t *acc_handlep) +{ + iop_instance_t *iop = ((i2o_iop_impl_hdl_t *)iop_hdl)->iop; + i2o_msg_impl_hdl_t *hdl; + ddi_acc_handle_t acc_hdl; + ddi_dma_handle_t dma_handle; + caddr_t buf; + size_t real_length; + size_t size; + + /* + * Allocate the message frame buffer from the system memory. + * + * Note: + * For now, the allocation is done by directly calling + * the DDI framework. Later this should be fixed to allocate + * it from a local pool for performance reasons. + */ + + if (ddi_dma_alloc_handle(iop->dip, &dma_attr_contig, waitfp, + arg, &dma_handle) != DDI_SUCCESS) + return (DDI_FAILURE); + + /* size of the buffer includes the i2o_msg_impl_hdl_t structure */ + size = iop->ib_msg_frame_size + sizeof (i2o_msg_impl_hdl_t); + + if (ddi_dma_mem_alloc(dma_handle, size, &i2o_dev_acc_attr, + DDI_DMA_CONSISTENT, waitfp, arg, &buf, + &real_length, &acc_hdl) != DDI_SUCCESS) { + + ddi_dma_free_handle(&dma_handle); + return (DDI_FAILURE); + } + + hdl = (i2o_msg_impl_hdl_t *)buf; + hdl->dma_handle = dma_handle; + hdl->acc_hdl = acc_hdl; + hdl->msgp = (void *)(buf + sizeof (i2o_msg_impl_hdl_t)); + + /* set the message size field in the message header */ + ddi_put16(hdl->acc_hdl, + &((i2o_message_frame_t *)(hdl->msgp))->MessageSize, + iop->ib_msg_frame_size >> 2); + + *msg_handlep = (i2o_msg_handle_t *)hdl; + *acc_handlep = acc_hdl; + *msgp = hdl->msgp; + + return (DDI_SUCCESS); +} + + +/* + * Send the I2O message to the IOP. + * + * Description: We need to do the following. + * 1. If the inbound message queue freelist is empty (i.e no + * valid mfa available) then queue up this request for + * the i2o_msg_send_process() thread and return DDI_SUCCESS. + * 2. We have a valid mfa. Copy the data from the system memory + * message buffer into the real message frame and send the + * message. + * 3. Free up the system memory message buffer. + * + * Note: + * For now, we return the system memory buffer back to the DDI + * framework. Fix this later to put the buffer into the local pool + * for better performance. + */ +int +i2o_msg_send(i2o_iop_handle_t iop_hdl, void *msg, i2o_msg_handle_t msg_hdl) +{ + uint32_t mfa; + iop_instance_t *iop = ((i2o_iop_impl_hdl_t *)iop_hdl)->iop; + i2o_msg_impl_hdl_t *hdl = (i2o_msg_impl_hdl_t *)msg_hdl; + i2o_message_frame_t *real_msgp; + size_t msg_size; + ddi_acc_handle_t acc_hdl; + ddi_dma_handle_t dma_handle; + + ASSERT(hdl->msgp == msg); + + mutex_enter(&iop->iop_ib_mutex); + + /* get a valid mfa from the inbound message freelist FIFO */ + + mfa = (* iop->nexus_trans->i2o_trans_msg_alloc) + (iop->nexus_trans->nexus_handle); + + if (mfa == (uint_t)0xFFFFFFFF) { + /* + * No valid MFA available. Queue up the request. + */ + if (iop->send_queue_head == NULL) { + iop->send_queue_head = iop->send_queue_tail = hdl; + hdl->next = NULL; + } else { + hdl->next = NULL; + iop->send_queue_tail->next = hdl; + iop->send_queue_tail = hdl; + } + + if (iop->iop_flags & IOP_SEND_QUEUE_PROC_RUNNING) + /* wakeup the i2o_msg_send_proc() */ + cv_broadcast(&iop->send_queue_cv); + else { + /* + * Create the i2o_msg_send_proc() thread and + * run it. + */ + cv_init(&iop->send_queue_cv, NULL, CV_DEFAULT, NULL); + (void) thread_create(NULL, 0, i2o_msg_send_proc, + iop, 0, &p0, TS_RUN, minclsyspri); + iop->iop_flags |= IOP_SEND_QUEUE_PROC_RUNNING; + } + + iop->send_queue_count++; + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, "i2o_msg_send: req queued")); + + mutex_exit(&iop->iop_ib_mutex); + + return (DDI_SUCCESS); + } + + mutex_exit(&iop->iop_ib_mutex); + + real_msgp = (i2o_message_frame_t *) + (mfa + iop->nexus_trans->iop_base_addr); + + /* + * Copy the message to the real message frame. + */ + msg_size = ddi_get16(hdl->acc_hdl, + &((i2o_message_frame_t *)msg)->MessageSize) << 2; + ASSERT(msg_size <= iop->ib_msg_frame_size); + bcopy(msg, (void *)real_msgp, msg_size); + + /* send the message to the IOP */ + (void) (* iop->nexus_trans->i2o_trans_msg_send) + (iop->nexus_trans->nexus_handle, + (caddr_t)(real_msgp) - iop->nexus_trans->iop_base_addr); + + /* + * Now, free up the system resources allocated for this message + */ + acc_hdl = hdl->acc_hdl; + dma_handle = hdl->dma_handle; + ddi_dma_mem_free(&acc_hdl); + ddi_dma_free_handle(&dma_handle); + + return (DDI_SUCCESS); +} + +/* + * Copy the LCT contents to the specified buffer. + */ +int +i2o_msg_get_lct(i2o_iop_handle_t iop_hdl, void *buf, size_t buf_size, + size_t *lct_sizep, size_t *real_sizep) +{ + iop_instance_t *iop = ((i2o_iop_impl_hdl_t *)iop_hdl)->iop; + size_t copy_size; + + mutex_enter(&iop->lct.lct_mutex); + + if (lct_sizep != NULL) + *lct_sizep = iop->lct.size; + + if (buf == NULL) + copy_size = 0; + else { + copy_size = min(buf_size, iop->lct.size); + bcopy((void *)iop->lct.bufp, buf, copy_size); + } + + if (real_sizep) + *real_sizep = copy_size; + + mutex_exit(&iop->lct.lct_mutex); + + return (DDI_SUCCESS); +} + +/* + * Process the reply message queue. This routine is called at the time of + * IOP hw interrupt. Current implementation is a simple while loop which + * reads the outbound postlist FIFO and if the MFA is a valid MFA + * (i.e MFA != 0xFFFFFFFF) then it calls the callback function in the + * InitiatorContext field of the message. + */ +void +i2o_msg_process_reply_queue(i2o_iop_handle_t handle) +{ + uint32_t mfa; + iop_instance_t *iop = ((i2o_iop_impl_hdl_t *)handle)->iop; + void (* initiator_context)(); + i2o_single_reply_message_frame_t *rmp; + + mutex_enter(&iop->iop_ob_mutex); + + mfa = (* iop->nexus_trans->i2o_trans_msg_recv) + (iop->nexus_trans->nexus_handle); + + /* + * WORKAROUND for i960 chip bug. It seems that sometimes the i960 + * is dropping the write request when IxWorks writes the MFA to + * the FIFO before generating the interrupt. As a workaround, IxWorks + * writes 0xFFFFFFFF first and then correct MFA. Two successive + * reads to the postlist FIFO should confirm if the FIFO is + * really empty. In the absence of reading the FIFO second time + * results in another call to IOP interrupt service routine. + * For better performance we do the second read of FIFO here. + */ + if (mfa == (uint_t)0xFFFFFFFF) { + /* read the FIFO again */ + mfa = (* iop->nexus_trans->i2o_trans_msg_recv) + (iop->nexus_trans->nexus_handle); + } + + while (mfa != (uint_t)0xFFFFFFFF) { + + rmp = (i2o_single_reply_message_frame_t *) + ((mfa - iop->ob_msg_queue.base_paddr) + + iop->ob_msg_queue.base_addr); + + initiator_context = (void (*)()) + (uintptr_t)ddi_get32(iop->ob_msg_queue.acc_hdl, + (uint32_t *)&rmp->StdMessageFrame.InitiatorContext); + + /* + * Check for NULL Initiator Context field. If it is NULL + * (should not happen) then ignore the message. + */ + if (initiator_context == NULL) { + cmn_err(CE_WARN, "I2O: No Initiator Context in the MSG" + " (Function: 0x%x Transaction Context: 0x%x" + " TID: 0x%x) - reply msg ignored", + get_msg_Function((i2o_message_frame_t *)rmp, + iop->ob_msg_queue.acc_hdl), + ddi_get32(iop->ob_msg_queue.acc_hdl, + (uint32_t *)&rmp->TransactionContext), + get_msg_TargetAddress((i2o_message_frame_t *)rmp, + iop->ob_msg_queue.acc_hdl)); + } else { + + /* + * We need to do the DMA sync for the message frame + * because the reply message buffers are allocated + * from the system memory and the IOP does DMA to + * write to this memory. + */ + (void) ddi_dma_sync(iop->ob_msg_queue.dma_handle, + (off_t)(mfa - iop->ob_msg_queue.base_paddr), + (size_t)iop->ob_msg_queue.framesize, + DDI_DMA_SYNC_FORCPU); + + /* + * Call the callback function of the OSM to process + * the message. + */ + (* initiator_context)((void *)rmp, + iop->ob_msg_queue.acc_hdl); + + } + + /* Now, putback the MFA into the outbound freelist FIFO */ + (* iop->nexus_trans->i2o_trans_msg_freebuf) + (iop->nexus_trans->nexus_handle, mfa); + + /* get the next MFA from the FIFO */ + mfa = (* iop->nexus_trans->i2o_trans_msg_recv) + (iop->nexus_trans->nexus_handle); + } + + mutex_exit(&iop->iop_ob_mutex); +} + +/* + * Process the I2O request message queue. The request messages are + * queued up for this IOP because there was no free mfa available + * from the inbound freelist. Currently, there is no mechanism + * where IOP can inform the host when the freelist is not empty. + * So, we just have to poll on the inbound message queue fifo until + * we find a valid frame. But, starvation on the inbound MFAs should + * not happen with the current implementations of IRTOS where the + * IRTOS copies the message into local buffer and puts the MFA back + * on the freelist immediately. So, this code may never get executed + * in practice! + * + */ +static void +i2o_msg_send_proc(iop_instance_t *iop) +{ + uint32_t mfa; + i2o_message_frame_t *real_msgp; + size_t msg_size; + ddi_acc_handle_t acc_hdl; + ddi_dma_handle_t dma_handle; + i2o_msg_impl_hdl_t *q; + + mutex_enter(&iop->iop_ib_mutex); + + for (;;) { + + q = iop->send_queue_head; /* head of the queue */ + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, "i2o_msg_send_proc: called")); + + while (q != NULL) { + + ASSERT((iop->iop_flags & IOP_IS_IN_UNINIT) != 0); + + /* + * get a valid mfa from the inbound message + * freelist FIFO + */ + + mfa = (* iop->nexus_trans->i2o_trans_msg_alloc) + (iop->nexus_trans->nexus_handle); + + if (mfa == (uint_t)0xFFFFFFFF) { + /* + * No valid MFA available. Wait for a while + * and try again. + */ + delay(1); + continue; /* try again */ + } + + real_msgp = (i2o_message_frame_t *) + (mfa + iop->nexus_trans->iop_base_addr); + + /* Copy the message to the real message frame */ + msg_size = 4 * ddi_get16(q->acc_hdl, + &((i2o_message_frame_t *)(q->msgp))->MessageSize); + ASSERT(msg_size <= iop->ib_msg_frame_size); + bcopy(q->msgp, (void *)real_msgp, msg_size); + + + /* send the message to the IOP */ + (void) (* iop->nexus_trans->i2o_trans_msg_send) + (iop->nexus_trans->nexus_handle, + (caddr_t)(real_msgp) - + iop->nexus_trans->iop_base_addr); + + /* free up the associated system resources */ + acc_hdl = q->acc_hdl; + dma_handle = q->dma_handle; + q = q->next; + ddi_dma_mem_free(&acc_hdl); + ddi_dma_free_handle(&dma_handle); + } + + iop->send_queue_head = NULL; + iop->send_queue_tail = NULL; + + /* if the IOP is being uninitialized then exit */ + + if (iop->iop_flags & IOP_IS_IN_UNINIT) { + iop->iop_flags &= ~IOP_SEND_QUEUE_PROC_RUNNING; + + thread_exit(); + + DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, + "i2o_msg_send_proc: exit...")); + } + + /* otherwise, wait for the wakeup call from i2o_msg_send() */ + cv_wait(&iop->send_queue_cv, &iop->iop_ib_mutex); + } +} + +/* + * ************************************************************************ + * *** Functions used for Debugging only *** + * ************************************************************************ + */ + +#ifdef I2O_DEBUG + +static void +dump_iop_status_buf(iop_instance_t *iop) +{ + int i; + uint32_t *p = (uint32_t *)iop->status.bufp; + + cmn_err(CE_CONT, "?IOP Status Block: "); + for (i = 0; i < sizeof (i2o_exec_status_get_reply_t); i += 4) + cmn_err(CE_CONT, "0x%x", *p++); + cmn_err(CE_CONT, + "?\tOrganizationID: %x\n", ddi_get16(iop->status.acc_hdl, + &iop->status.bufp->OrganizationID)); + cmn_err(CE_CONT, "?\tIOP_ID: %x\n", + get_i2o_exec_status_reply_IOP_ID(iop->status.bufp, + iop->status.acc_hdl)); + cmn_err(CE_CONT, "?\tHostUnitID: %x\n", ddi_get16(iop->status.acc_hdl, + &iop->status.bufp->HostUnitID)); + cmn_err(CE_CONT, "?\tI2oVersion: %x\n", + get_i2o_exec_status_reply_I2oVersion(iop->status.bufp, + iop->status.acc_hdl)); + cmn_err(CE_CONT, "?\tSegmentNumber: %x\n", + get_i2o_exec_status_reply_SegmentNumber(iop->status.bufp, + iop->status.acc_hdl)); + cmn_err(CE_CONT, "?\tIopState: %x\n", ddi_get8(iop->status.acc_hdl, + &iop->status.bufp->IopState)); + cmn_err(CE_CONT, "?\tMessengerType: %x\n", ddi_get8(iop->status.acc_hdl, + &iop->status.bufp->MessengerType)); + cmn_err(CE_CONT, + "?\tInboundMFrameSize: %x\n", ddi_get16(iop->status.acc_hdl, + &iop->status.bufp->InboundMFrameSize)); + cmn_err(CE_CONT, "?\tInitCode: %x\n", ddi_get8(iop->status.acc_hdl, + &iop->status.bufp->InitCode)); + cmn_err(CE_CONT, + "?\tMaxInboundMFrames: %x\n", ddi_get32(iop->status.acc_hdl, + &iop->status.bufp->MaxInboundMFrames)); + cmn_err(CE_CONT, + "?\tCurrentInboundMFrames: %x\n", ddi_get32(iop->status.acc_hdl, + &iop->status.bufp->CurrentInboundMFrames)); + cmn_err(CE_CONT, + "?\tMaxOutboundMFrames: %x\n", ddi_get32(iop->status.acc_hdl, + &iop->status.bufp->MaxOutboundMFrames)); + cmn_err(CE_CONT, + "?\tProductIDString: %s\n", iop->status.bufp->ProductIDString); + cmn_err(CE_CONT, + "?\tExpectedLCTSize: %x\n", ddi_get32(iop->status.acc_hdl, + &iop->status.bufp->ExpectedLCTSize)); + cmn_err(CE_CONT, + "?\tIopCapabilities: %x\n", ddi_get32(iop->status.acc_hdl, + &iop->status.bufp->IopCapabilities)); + cmn_err(CE_CONT, + "?\tDesiredPrivateMemSize: %x\n", ddi_get32(iop->status.acc_hdl, + &iop->status.bufp->DesiredPrivateMemSize)); + cmn_err(CE_CONT, + "?\tCurrentPrivateMemSize: %x\n", ddi_get32(iop->status.acc_hdl, + &iop->status.bufp->CurrentPrivateMemSize)); + cmn_err(CE_CONT, + "?\tCurrentPrivateMemBase: %x\n", ddi_get32(iop->status.acc_hdl, + &iop->status.bufp->CurrentPrivateMemBase)); + cmn_err(CE_CONT, + "?\tDesiredPrivateIOSize: %x\n", ddi_get32(iop->status.acc_hdl, + &iop->status.bufp->DesiredPrivateIOSize)); + cmn_err(CE_CONT, + "?\tCurrentPrivateIOSize: %x\n", ddi_get32(iop->status.acc_hdl, + &iop->status.bufp->CurrentPrivateIOSize)); + cmn_err(CE_CONT, + "?\tCurrentPrivateIOBase: %x\n", ddi_get32(iop->status.acc_hdl, + &iop->status.bufp->CurrentPrivateIOBase)); +} + +static void +dump_hrt(iop_instance_t *iop) +{ + int i, n; + i2o_hrt_entry_t *entp; + uint32_t *p; + + n = ddi_get16(iop->hrt.acc_hdl, &iop->hrt.bufp->NumberEntries); + + entp = &iop->hrt.bufp->HRTEntry[0]; + + cmn_err(CE_CONT, + "?Hardware Resource Table (IOP_ID %x HRTVersion %x #ent %x):\n", + iop->iop_id, iop->hrt.bufp->HRTVersion, n); + + for (i = 0; i < n; i++, entp++) { + + p = (uint32_t *)entp; + + if (get_hrt_entry_AdapterState(entp, iop->hrt.acc_hdl) == 0) + continue; + + cmn_err(CE_CONT, "0x%x 0x%x 0x%x 0x%x", p[0], p[1], + p[2], p[3]); + cmn_err(CE_CONT, + "?\tAdapterID: %x\n", ddi_get32(iop->hrt.acc_hdl, + &entp->AdapterID)); + cmn_err(CE_CONT, "?\tControllingTID: %x\n", + get_hrt_entry_ControllingTID(entp, iop->hrt.acc_hdl)); + cmn_err(CE_CONT, "?\tAdapterState: %x\n", + get_hrt_entry_AdapterState(entp, iop->hrt.acc_hdl)); + cmn_err(CE_CONT, "?\tBusType: %x\n", entp->BusType); + cmn_err(CE_CONT, "?\tBusNumber: %x\n", entp->BusNumber); + + switch (entp->BusType) { + case I2O_PCI_BUS: + cmn_err(CE_CONT, "?\t\tPciFunctionNumber: %x", + entp->uBus.PCIBus.PciFunctionNumber); + cmn_err(CE_CONT, "?\t\tPciDeviceNumber: %x", + entp->uBus.PCIBus.PciDeviceNumber); + cmn_err(CE_CONT, "?\t\tPciBusNumber: %x", + entp->uBus.PCIBus.PciBusNumber); + cmn_err(CE_CONT, "?\t\tPciVendorID: %x", + entp->uBus.PCIBus.PciVendorID); + cmn_err(CE_CONT, "?\t\tPciDeviceID: %x", + entp->uBus.PCIBus.PciDeviceID); + break; + default: + break; + } + } +} + + +static void +dump_lct(iop_instance_t *iop) +{ + int i, j, n; + i2o_lct_entry_t *entp; + + n = (ddi_get16(iop->lct.acc_hdl, &iop->lct.bufp->TableSize) * 4) / + sizeof (i2o_lct_entry_t); + entp = &iop->lct.bufp->LCTEntry[0]; + + cmn_err(CE_CONT, "?Logical Config Table (IopFlags %x LctVer %x)\n", + ddi_get32(iop->lct.acc_hdl, &iop->lct.bufp->IopFlags), + get_lct_LctVer(iop->lct.bufp, iop->lct.acc_hdl)); + + for (i = 0; i < n; i++) { + cmn_err(CE_CONT, "?\tLocalTID: %x\n", + get_lct_entry_LocalTID(entp, iop->lct.acc_hdl)); + cmn_err(CE_CONT, "?\tDeviceFlags: %x\n", + ddi_get32(iop->lct.acc_hdl, &entp->DeviceFlags)); + cmn_err(CE_CONT, "?\tChangeIndicator: %x\n", + ddi_get32(iop->lct.acc_hdl, &entp->ChangeIndicator)); + cmn_err(CE_CONT, "?\tClass: %x\n", + get_lct_entry_Class(entp, iop->lct.acc_hdl)); + cmn_err(CE_CONT, "?\tVersion: %x\n", + get_lct_entry_Version(entp, iop->lct.acc_hdl)); + cmn_err(CE_CONT, "?\tOrganizationID: %x\n", + get_lct_entry_OrganizationID(entp, iop->lct.acc_hdl)); + cmn_err(CE_CONT, "?\tSubClassInfo: %x\n", + ddi_get32(iop->lct.acc_hdl, &entp->SubClassInfo)); + cmn_err(CE_CONT, "?\tBiosInfo: %x\n", + get_lct_entry_BiosInfo(entp, iop->lct.acc_hdl)); + cmn_err(CE_CONT, "?\tParentTID: %x\n", + get_lct_entry_ParentTID(entp, iop->lct.acc_hdl)); + cmn_err(CE_CONT, "?\tUserTID: %x\n", + get_lct_entry_UserTID(entp, iop->lct.acc_hdl)); + cmn_err(CE_CONT, "?\tEventCapabilities: %x\n", + ddi_get32(iop->lct.acc_hdl, &entp->EventCapabilities)); + cmn_err(CE_CONT, "?\tIdentityTag: "); + for (j = 0; j < 8; j++) + cmn_err(CE_CONT, "?\t%x ", entp->IdentityTag[j]); + cmn_err(CE_CONT, "?\n"); + + entp++; + } +} + + +static void +dump_message(uint32_t *mp, char *name) +{ + cmn_err(CE_CONT, "%s: MSGHDR(%p): %x %x %x %x", name, (void *)mp, mp[0], + mp[1], mp[2], mp[3]); + cmn_err(CE_CONT, "PAYLOAD(%p): %x %x %x %x %x %x", + (void *)&mp[4], mp[4], mp[5], mp[6], mp[7], mp[8], mp[9]); +} + +static void +dump_reply_message(iop_instance_t *iop, i2o_single_reply_message_frame_t *rmp) +{ + if (rmp == NULL) + return; + + cmn_err(CE_CONT, + "?Reply Message Frame (IOP %x Function %x):", iop->iop_id, + get_msg_Function(&rmp->StdMessageFrame, iop->ob_msg_queue.acc_hdl)); + cmn_err(CE_CONT, + "?\tReqStatus: %x DetailedStatusCode %x\n", rmp->ReqStatus, + ddi_get16(iop->ob_msg_queue.acc_hdl, &rmp->DetailedStatusCode)); +} + +#endif + + + +static uint_t +i2o_get_mem(dev_info_t *dip, uint_t len, uint_t *base) +{ + ndi_ra_request_t req; + uint64_t retlen; + uint64_t retbase; +#ifdef lint + dip = dip; +#endif + + bzero((caddr_t)&req, sizeof (req)); + + req.ra_addr = (uint64_t)*base; + if (*base != 0) + req.ra_flags |= NDI_RA_ALLOC_SPECIFIED; + req.ra_len = (uint64_t)len; + req.ra_boundbase = 0; + req.ra_boundlen = 0xffffffffUL; + req.ra_flags |= NDI_RA_ALLOC_BOUNDED; + + if (ndi_ra_alloc(ddi_root_node(), &req, &retbase, &retlen, + NDI_RA_TYPE_MEM, 0) == NDI_FAILURE) { + *base = 0; + return (0); + } else { + *base = retbase; + return (*base); + } +} + + +static void +i2o_return_mem(dev_info_t *dip, uint_t base, uint_t len) +{ +#ifdef lint + dip = dip; +#endif + (void) ndi_ra_free(ddi_root_node(), (uint64_t)base, (uint64_t)len, + NDI_RA_TYPE_MEM, 0); +} + + +static uint_t +i2o_get_io(dev_info_t *dip, uint_t len, uint_t *base) +{ + ndi_ra_request_t req; + uint64_t retbase, retlen; + +#ifdef lint + dip = dip; +#endif + bzero((caddr_t)&req, sizeof (req)); + if (*base != 0) + req.ra_flags |= NDI_RA_ALLOC_SPECIFIED; + req.ra_flags |= NDI_RA_ALIGN_SIZE; + req.ra_addr = (uint64_t)*base; + req.ra_boundbase = 0; + req.ra_boundlen = 0xffffffffUL; + req.ra_flags |= NDI_RA_ALLOC_BOUNDED; + req.ra_len = (uint64_t)len; + if (ndi_ra_alloc(ddi_root_node(), &req, &retbase, &retlen, + NDI_RA_TYPE_IO, 0) == NDI_FAILURE) { + *base = 0; + return (0); + } else { + *base = retbase; + return (*base); + } +} + +static void +i2o_return_io(dev_info_t *dip, uint_t base, uint_t len) +{ +#ifdef lint + dip = dip; +#endif + (void) ndi_ra_free(ddi_root_node(), (uint64_t)base, (uint64_t)len, + NDI_RA_TYPE_IO, 0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/uts/common/io/i2o/i2o_scsi.c Wed Apr 18 11:32:14 2007 -0700 @@ -0,0 +1,4440 @@ +/* + * 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 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + + +/* + * I2O SCSI HBA OSM + * + * I2O Scsi Host Bus Adapter Operating System Module (OSM) + * conforms to I2O and converts SCSI pkt information send by + * the target driver through SCSA to I2O message format and send it + * down to the IOP. This driver utilized the I2O messaging framework, + * i2o_msg. Currently only support on x86. + * + */ + +/* + * debugging code + */ +#ifdef DEBUG +#define I2OHBA_DEBUG +#endif + +#ifdef I2OHBA_DEBUG +int i2ohbadebugflag = 0; +int ddi_dma_alloc_hdl = 0; +int ddi_dma_alloc_mem = 0; +int ddi_dma_bind_hdl = 0; +int ddi_dma_unbind = 0; +int ddi_dma_free_mem = 0; +int ddi_dma_bind_free = 0; +int ddi_dma_bufalloc = 0; +int ddi_dma_buf_bind = 0; +int ddi_dma_buf_unbind = 0; +int ddi_dma_buf_free_hdl = 0; +#define DEBUGF(level, args) \ + { if (i2ohbadebugflag >= (level)) cmn_err args; } +#else +#define DEBUGF(leve, args) /* nothing */ +#endif + +#include <sys/types.h> +#include <sys/conf.h> +#include <sys/varargs.h> +#include <sys/modctl.h> +#include <sys/scsi/scsi.h> +#include <sys/scsi/scsi_ctl.h> +#include <sys/scsi/impl/scsi_reset_notify.h> + +#include <sys/i2o/i2obscsi.h> +#include <sys/i2o/i2oadptr.h> +#include <sys/i2o/i2omsg.h> +#include <sys/i2o/i2outil.h> + +#include "i2o_scsi_var.h" +#include "i2o_scsi_util.h" +#include "i2o_scsi_cmd.h" + +/* + * dev_ops functions prototypes + */ +static int i2ohba_info(dev_info_t *dip, ddi_info_cmd_t infocmd, + void *arg, void **result); +static int i2ohba_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); +static int i2ohba_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); + +/* + * Function prototypes + * + * SCSA functions exported by means of the transport table + */ +static int i2ohba_tran_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, + scsi_hba_tran_t *tran, struct scsi_device *sd); +static int i2ohba_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt); +static int i2ohba_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt); +static int i2ohba_scsi_reset(struct scsi_address *ap, int level); +static int i2ohba_scsi_getcap(struct scsi_address *ap, char *cap, int whom); +static int i2ohba_scsi_setcap(struct scsi_address *ap, char *cap, int value, + int whom); +static struct scsi_pkt *i2ohba_scsi_init_pkt(struct scsi_address *ap, + struct scsi_pkt *pkt, struct buf *bp, int cmdlen, int statuslen, + int tgtlen, int flags, int (*callback)(), caddr_t arg); +static void i2ohba_scsi_destroy_pkt(struct scsi_address *ap, + struct scsi_pkt *pkt); +static void i2ohba_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt); +static void i2ohba_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt); +static int i2ohba_scsi_reset_notify(struct scsi_address *ap, int flag, + void (*callback)(caddr_t), caddr_t arg); + +/* + * i2ohba's complete function for sending the SCSI pkt. + */ +static void i2ohba_callback(i2o_message_frame_t *msg, ddi_acc_handle_t + acc_handle); + + +/* + * Internal Functions + */ +/* tid map to scsi convertion function */ +static int i2ohba_i_tid_to_scsi(dev_info_t *dip, struct i2ohba *i2ohba, + i2o_lct_t *lct_buf, size_t lct_real_size, + ddi_acc_handle_t lctbuf_dmaacchandle); + +/* capability/prop functions */ +static void i2ohba_i_updatesync(struct i2ohba *i2ohba, int tgt); +static void i2ohba_i_update_props(struct i2ohba *i2ohba, int tgt); +static void i2ohba_i_update_this_prop(struct i2ohba *i2ohba, char *property, + int value); +static void i2ohba_i_initcap(struct i2ohba *i2ohba); + +/* dma engine funcitons */ +static int i2ohba_i_dma_alloc(struct i2ohba *i2ohba, struct scsi_pkt *pkt, + struct buf *bp, int flags, int (*callback)()); +static int i2ohba_i_dma_move(struct i2ohba *i2ohba, struct scsi_pkt *pkt, + struct buf *bp); + +/* timer and recovery functions */ +static void i2ohba_i_watch(void *); +static void i2ohba_i_fatal_error(struct i2ohba *i2ohba); +static int i2ohba_i_reset_interface(struct i2ohba *i2ohba, int action); +static int i2ohba_i_reset_abort(struct i2ohba *i2ohba, uint16_t tid, int action, + struct i2ohba_cmd *cmd); + +/* command processing functions */ +static void i2ohba_i_polled_cmd_start(struct i2ohba *i2ohba, + struct i2ohba_cmd *sp); +static void i2ohba_i_req_insert(struct i2ohba *i2ohba, struct i2ohba_cmd *sp); +static void i2ohba_i_req_remove(struct i2ohba *i2ohba, struct i2ohba_cmd *sp); +static void i2ohba_i_pkt_comp(i2o_single_reply_message_frame_t *reply, + ddi_acc_handle_t acc_handle, struct i2ohba_cmd *sp); +static void i2ohba_i_handle_arq(i2o_scsi_error_reply_message_frame_t *replyerr, + struct i2ohba_cmd *sp, int aqcount); +static void i2ohba_i_qflush(struct i2ohba *i2ohba, uint16_t start_tgt, + uint16_t end_tgt); +/*PRINTFLIKE3*/ +static void i2ohba_i_log(struct i2ohba *i2ohba, int level, char *fmt, ...); +static void i2ohba_i_print_state(struct i2ohba *i2ohba); + +/* utility parameter functions */ +static int i2ohba_utilparamset_msg(struct i2ohba *i2ohba, int tgt, + uint16_t tid, uint16_t group, uint16_t idx, uint16_t value); +static int i2ohba_utilparamget_msg(struct i2ohba *i2ohba, uint16_t tidx, + char flag); +static void i2ohba_utilmsg_comp(i2o_message_frame_t *msg, ddi_acc_handle_t + acc_handle); +static int i2ohba_utilclaim_msg(struct i2ohba *i2ohba, uint16_t tid, + int action); + +/* + * mutex for protecting variables shared by all instances of the driver + */ +static kmutex_t i2ohba_log_mutex; + +/* + * Local static data + */ +static void *i2ohba_state = NULL; +static clock_t i2ohba_tick; /* watch interval in HZ */ +static clock_t i2ohba_watchdog_tick = 15; /* watch interval in sec */ +static int i2ohba_scsi_reset_delay = 3000; +ddi_device_acc_attr_t dev_attr; /* dev_attr */ +static char i2ohba_log_buf[256]; /* buffer used in i2ohba_i_log */ + + + +/* + * DMA Attribute for data buffers + */ +static ddi_dma_attr_t i2ohba_dma_attr = { + DMA_ATTR_VERSION, /* dma_attr_version */ + 0, /* dma_attr_addr_lo */ + 0xffffffffull, /* dma_attr_addr_hi */ + 0x00ffffffull, /* dma_attr_count_max */ + 1, /* dma_attr_align */ + 1, /* dma_attr_burstsizes */ + 1, /* dma_attr_minxfer */ + 0xffffffffull, /* dma_attr_maxxfer */ + 0x00ffffffull, /* dma_attr_seg */ + I2OHBA_CMD_NSEGS, /* dma_attr_sgllen */ + 512, /* dma_attr_granular */ + 0 /* dma_attr_flags */ +}; + +/* + * DMA attributes for SGL buffer + */ +static ddi_dma_attr_t i2ohba_dmasgl_attr = { + DMA_ATTR_VERSION, /* dma_attr_version */ + 0, /* dma_attr_addr_lo */ + 0xffffffffull, /* dma_attr_addr_hi */ + 0x00ffffffull, /* dma_attr_count_max */ + 1, /* dma_attr_align */ + 1, /* dma_attr_burstsizes */ + 1, /* dma_attr_minxfer */ + 0xffffffffull, /* dma_attr_maxxfer */ + 0x00ffffffull, /* dma_attr_seg */ + 0x1, /* dma_attr_sgllen */ + 1, /* dma_attr_granular */ + 0 /* dma_attr_flags */ +}; + +/* + * Hotplug support + * Leaf ops (hotplug controls for target devices) + * XXXLWXXX currently doesn't support any hotpluging + */ + +static struct cb_ops i2ohba_cb_ops = { + nodev, /* open */ + nodev, /* close */ + nodev, /* strategy */ + nodev, /* print */ + nodev, /* dump */ + nodev, /* read */ + nodev, /* write */ + nodev, /* ioctl */ + nodev, /* devmap */ + nodev, /* mmap */ + nodev, /* segmap */ + nochpoll, /* poll */ + ddi_prop_op, /* prop_op */ + NULL, + D_NEW | D_MP | D_HOTPLUG +}; + +/* + * autoconfiguration routines. + */ + +static struct dev_ops i2ohba_ops = { + DEVO_REV, /* rev, */ + 0, /* refcnt */ + i2ohba_info, /* getinfo */ + nulldev, /* identify */ + nulldev, /* probe */ + i2ohba_attach, /* attach */ + i2ohba_detach, /* detach */ + nodev, /* reset */ + &i2ohba_cb_ops, /* driver operations */ + NULL, /* bus ops */ + NULL /* power ops */ +}; + +char _depends_on[] = "misc/scsi misc/i2o_msg"; + +static struct modldrv modldrv = { + &mod_driverops, /* Type of module */ + "I2O SCSI HBA OSM version %I%", /* module name */ + &i2ohba_ops, /* driver ops */ + +}; + +static struct modlinkage modlinkage = { + MODREV_1, + (void *)&modldrv, + NULL +}; + +int +_init(void) +{ + int ret; + + ret = ddi_soft_state_init(&i2ohba_state, sizeof (struct i2ohba), + I2OHBA_INITIAL_SOFT_SPACE); + + if (ret != 0) + return (ret); + + mutex_init(&i2ohba_log_mutex, NULL, MUTEX_DRIVER, NULL); + + i2ohba_tick = drv_usectohz(i2ohba_watchdog_tick * 1000000); + + if ((ret = scsi_hba_init(&modlinkage)) != 0) { + mutex_destroy(&i2ohba_log_mutex); + ddi_soft_state_fini(&i2ohba_state); + return (ret); + } + + if ((ret = mod_install(&modlinkage)) != 0) { + scsi_hba_fini(&modlinkage); + mutex_destroy(&i2ohba_log_mutex); + ddi_soft_state_fini(&i2ohba_state); + } + + return (ret); +} + +int +_info(struct modinfo *modinfop) +{ + return (mod_info(&modlinkage, modinfop)); +} + +int +_fini(void) +{ + + int ret; + + if ((ret = mod_remove(&modlinkage)) != 0) + return (ret); + + scsi_hba_fini(&modlinkage); + + mutex_destroy(&i2ohba_log_mutex); + ddi_soft_state_fini(&i2ohba_state); + + return (ret); +} + +/* + * Given the device number return the devinfo pointer + * from the scsi_device structure. + */ +/*ARGSUSED*/ +static int +i2ohba_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) +{ + return (DDI_FAILURE); +} + + +/* + * Attach an instance of an i2o hba OSM module. Allocate data structures, + * initialize the OSM and send commands to IOP to bring I2O on line. + */ +/*ARGSUSED*/ +static int +i2ohba_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) +{ + scsi_hba_tran_t *tran = NULL; + char prop_str[32]; + int i, id, tid2scsi; + int freecount = 0; + int ishdlalloc = 0; + struct i2ohba *i2ohba; + int instance; + size_t lct_size, lct_real_size, lct_rlen; + i2o_lct_t *lct_buf; + ddi_dma_handle_t lctbuf_dmahandle; + ddi_acc_handle_t lctbuf_dmaacchandle; + + instance = ddi_get_instance(dip); + + switch (cmd) { + case DDI_ATTACH: + dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; + dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; + /* currently for x86 PCI, we'll use little endian */ + dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; + break; + + /* XXXLWXXX will work on it more */ + case DDI_RESUME: + case DDI_PM_RESUME: + + default: + i2ohba_i_log(NULL, CE_WARN, "?i2ohba_attach%d: " + "cmd != DDI_ATTACH", instance); + return (DDI_FAILURE); + } + + /* + * I2O comes in at intr level 5 + */ + if (ddi_intr_hilevel(dip, 0) != 0) { + i2ohba_i_log(NULL, CE_WARN, "?i2ohba_attach%d: high-level " + "interrupt not supported", instance); + return (DDI_FAILURE); + } + + /* + * Allocate i2ohba data structure. + */ + if (ddi_soft_state_zalloc(i2ohba_state, instance) != DDI_SUCCESS) { + i2ohba_i_log(NULL, CE_WARN, "?i2ohba%d: Failed to alloc" + " soft state", instance); + return (DDI_FAILURE); + } + + i2ohba = ddi_get_soft_state(i2ohba_state, instance); + + if (i2ohba == (struct i2ohba *)NULL) { + i2ohba_i_log(NULL, CE_WARN, "?i2ohba%d: Bad soft state", + instance); + ddi_soft_state_free(i2ohba_state, instance); + return (DDI_FAILURE); + } + + /* + * save the dip info + */ + i2ohba->i2ohba_dip = dip; + + /* + * register OSM with message layer + */ + if (i2o_msg_osm_register(dip, &i2ohba->i2ohba_iophdl) + != DDI_SUCCESS) { + i2ohba_i_log(NULL, CE_WARN, "?i2ohba%d: Registeration Fail " + "with IOP", instance); + goto cleanup; + } + + /* + * get the LCT from iop + */ + if (i2o_msg_get_lct(i2ohba->i2ohba_iophdl, NULL, NULL, + &lct_size, NULL) != DDI_SUCCESS) { + i2ohba_i_log(NULL, CE_WARN, "?i2ohba%d: Can't get LCT SIZE " + "info from IOP", instance); + goto cleanup; + } + +retry: + /* + * first get the size from IOP, then + * DMA Allocate it. + */ + if (lct_size) { + if (!ishdlalloc) { + if (ddi_dma_alloc_handle(dip, &i2ohba_dmasgl_attr, + DDI_DMA_SLEEP, NULL, &lctbuf_dmahandle) != + DDI_SUCCESS) + goto cleanup; + } + ishdlalloc = 1; +#ifdef I2OHBA_DEBUG + ddi_dma_alloc_hdl++; +#endif + if (ddi_dma_mem_alloc(lctbuf_dmahandle, (size_t) + lct_size, &dev_attr, DDI_DMA_STREAMING, + DDI_DMA_SLEEP, NULL, (caddr_t *)&lct_buf, &lct_rlen, + &lctbuf_dmaacchandle) != DDI_SUCCESS) + goto cleanup; +#ifdef I2OHBA_DEBUG + ddi_dma_alloc_mem++; +#endif + freecount = 1; + + } else { + i2ohba_i_log(NULL, CE_WARN, "?i2ohba%d: Invalid LCT size", + instance); + goto cleanup; + } + + /* + * with the right size buffer, now get the table + */ + if (i2o_msg_get_lct(i2ohba->i2ohba_iophdl, lct_buf, lct_size, + NULL, &lct_real_size) != DDI_SUCCESS) { + i2ohba_i_log(NULL, CE_WARN, "?i2ohba%d: Getting LCT table " + "info failed", instance); + goto cleanup; + } + + /* + * partial transfer + */ + if (lct_real_size > lct_size) { + ddi_dma_mem_free(&lctbuf_dmaacchandle); +#ifdef I2OHBA_DEBUG + ddi_dma_free_mem++; +#endif + lct_size = lct_real_size; + goto retry; + } + + /* + * Set up TID->SCSI info map, query all unclaimed SCSI devices + */ + if (tid2scsi = i2ohba_i_tid_to_scsi(dip, i2ohba, lct_buf, + lct_real_size, lctbuf_dmaacchandle)) { + i2ohba_i_log(NULL, CE_WARN, "?i2ohba%d: Setup TID to SCSI " + "info map failed", instance); + goto cleanup; + } + + /* free dma, may be XXLWXX we can keep it for later LCT update */ + freecount = 0; + ddi_dma_mem_free(&lctbuf_dmaacchandle); +#ifdef I2OHBA_DEBUG + ddi_dma_free_mem++; +#endif + ishdlalloc = 0; + ddi_dma_free_handle(&lctbuf_dmahandle); +#ifdef I2OHBA_DEBUG + ddi_dma_bind_free++; +#endif + + /* + * Allocate a transport structure + */ + tran = scsi_hba_tran_alloc(dip, SCSI_HBA_CANSLEEP); + + i2ohba->i2ohba_tran = tran; + i2ohba->i2ohba_dip = dip; + + tran->tran_hba_private = i2ohba; + tran->tran_tgt_private = NULL; + tran->tran_tgt_init = i2ohba_tran_tgt_init; + tran->tran_tgt_probe = (int (*)())scsi_hba_probe; + tran->tran_tgt_free = (void (*)())NULL; + + tran->tran_start = i2ohba_scsi_start; + tran->tran_abort = i2ohba_scsi_abort; + tran->tran_reset = i2ohba_scsi_reset; + tran->tran_getcap = i2ohba_scsi_getcap; + tran->tran_setcap = i2ohba_scsi_setcap; + tran->tran_init_pkt = i2ohba_scsi_init_pkt; + tran->tran_destroy_pkt = i2ohba_scsi_destroy_pkt; + tran->tran_dmafree = i2ohba_scsi_dmafree; + tran->tran_sync_pkt = i2ohba_scsi_sync_pkt; + tran->tran_reset_notify = i2ohba_scsi_reset_notify; + tran->tran_get_bus_addr = NULL; + tran->tran_get_name = NULL; + + + /* + * Attach this instance of the hba + */ + if (scsi_hba_attach_setup(dip, &i2ohba_dma_attr, tran, + 0) != DDI_SUCCESS) { + i2ohba_i_log(NULL, CE_WARN, "?scsi_hba_attach failed"); + goto cleanup; + } + + /* + * find scsi host id property + */ + id = ddi_getprop(DDI_DEV_T_ANY, dip, 0, + "scsi-initiator-id", -1); + if (id != scsi_host_id && + (id >= 0 && id < N_I2OHBA_TARGETS_WIDE)) { + i2ohba->i2ohba_initiator_id = (uint8_t)id; + } else { + i2ohba->i2ohba_initiator_id = (uint8_t)scsi_host_id; + } + + /* + * property: look up the scsi-options property + */ + i2ohba->i2ohba_scsi_options = + ddi_getprop(DDI_DEV_T_ANY, dip, 0, "scsi-options", + I2OHBA_DEFAULT_SCSI_OPTIONS); + + /* + * property: if target<n>-scsi-options property exists, use it; + * otherwise use the i2o_scsi_options + */ + for (i = 0; i < N_I2OHBA_TARGETS_WIDE; i++) { + (void) sprintf(prop_str, "target%x-scsi-options", i); + i2ohba->i2ohba_target_scsi_option[i] = ddi_getprop( + DDI_DEV_T_ANY, dip, 0, prop_str, + i2ohba->i2ohba_scsi_options); + + if (i2ohba->i2ohba_target_scsi_option[i] != + i2ohba->i2ohba_scsi_options) { + i2ohba_i_log(NULL, CE_CONT, + "?i2ohba:target%x-scsi-options=0x%x", + i, i2ohba->i2ohba_target_scsi_option[i]); + } + } + + + i2ohba->i2ohba_scsi_reset_delay = + ddi_getprop(DDI_DEV_T_ANY, dip, 0, "scsi-reset-delay", + i2ohba_scsi_reset_delay); + + if (i2ohba->i2ohba_scsi_reset_delay != i2ohba_scsi_reset_delay) { + i2ohba_i_log(NULL, CE_CONT, + "?i2ohba_scsi-reset-delay=%d", + i2ohba->i2ohba_scsi_reset_delay); + } + + + + /* + * set up watchdog for this i2o + */ + i2ohba->i2ohba_timeout_id = timeout(i2ohba_i_watch, (caddr_t)i2ohba, + i2ohba_tick); + + /* + * initialized I2OHBA request mutex and reset mutex + */ + mutex_init(I2OHBA_REQ_MUTEX(i2ohba), NULL, MUTEX_DRIVER, NULL); + mutex_init(I2OHBA_RESET_MUTEX(i2ohba), NULL, MUTEX_DRIVER, NULL); + cv_init(I2OHBA_RESET_CV(i2ohba), NULL, CV_DRIVER, NULL); + + I2OHBA_MUTEX_ENTER(i2ohba); + /* + * Initialize the default Target Capabilites and Sync Rates + */ + (void) i2ohba_i_initcap(i2ohba); + + /* + * reset i2ohba/bus and initialize capabilities + * if (i2ohba_i_reset_interface(i2ohba, I2OHBA_FORCE_BUS_RESET)) { + * goto cleanup; + * } + */ + I2OHBA_MUTEX_EXIT(i2ohba); + + ddi_report_dev(dip); + i2ohba->i2ohba_throttle = 0; + + DEBUGF(1, (CE_CONT, "i2ohba_attach%d: Succeeded", instance)); + + return (DDI_SUCCESS); + +cleanup: + DEBUGF(1, (CE_CONT, "?i2ohba_attach%d: Unable to attach", instance)); + + if (tid2scsi) { + i2o_tid_scsi_ent_t *map = i2ohba->i2ohba_tid_scsi_map; + + /* + * if tid_to_scsi has succeeded, then at least + * we have the HBA node claimed. + */ + (void) i2ohba_utilclaim_msg(i2ohba, i2ohba->i2ohba_tid, + I2O_UTIL_CLAIM_RELEASE); + + DEBUGF(1, (CE_CONT, "?Utilunclaim %d", i2ohba->i2ohba_tid)); + + for (i = 0; i < N_I2OHBA_TARGETS_WIDE; i++) { + if (map[i].tid != 0) + (void) i2ohba_utilclaim_msg(i2ohba, + map[i].tid, + I2O_UTIL_CLAIM_RELEASE); + } + + } + + if (freecount) { + ddi_dma_mem_free(&lctbuf_dmaacchandle); + } + if (ishdlalloc) { + ddi_dma_free_handle(&lctbuf_dmahandle); + } + + if (i2ohba->i2ohba_timeout_id != 0) { + i2ohba->i2ohba_shutdown = 1; + (void) untimeout(i2ohba->i2ohba_timeout_id); + i2ohba->i2ohba_timeout_id = 0; + } + + if (tran) { + scsi_hba_tran_free(tran); + } + + if (i2ohba->i2ohba_iophdl) + i2o_msg_osm_unregister(&i2ohba->i2ohba_iophdl); + + ddi_soft_state_free(i2ohba_state, instance); + + return (DDI_FAILURE); +} + +/* + * Function name: i2ohba_i_tid_to_scsi + * + * Return Values: -1 Failed + * 0 Success + * + * Description : Take in the LCT (logical configuration table), and + * parse it through to find the appropriated SCSI target + * devices that belongs to this HBA. Then send a + * I2O_UTIL_PARAM_GET message to the target device to + * to get its parameters, ie SCSI ID and build a + * tid-to-scsi.id map. + */ +/*ARGSUSED*/ +static int +i2ohba_i_tid_to_scsi(dev_info_t *dip, struct i2ohba *i2ohba, + i2o_lct_t *lct_buf, size_t lct_real_size, + ddi_acc_handle_t lctbuf_dmaacchandle) +{ + i2o_tid_scsi_ent_t *map = i2ohba->i2ohba_tid_scsi_map; + uint_t tablesize, actualtbl; + i2o_lct_entry_t *lctentptr; + int i, count, entries = 0, rval = -1; + + /* + * translating dev_addr field in the dev_info struct to TID + */ + + i2ohba->i2ohba_tid = ddi_getprop(DDI_DEV_T_ANY, dip, 0, + "i2o-device-id", -1); + + /* + * scan the table for SCSI bus/devices + */ + tablesize = ddi_get16(lctbuf_dmaacchandle, &lct_buf->TableSize); + + if (!tablesize) { + i2ohba_i_log(NULL, CE_WARN, "?i2o_i_tid_to_scsi: Invalid " + "tablesize"); + return (rval); + } + + /* + * lct table size in WORDS + */ + actualtbl = (tablesize << 2) - sizeof (i2o_lct_t) + + sizeof (i2o_lct_entry_t); + + actualtbl = actualtbl/sizeof (i2o_lct_entry_t); + + /* scan through the table */ + for (count = 0; count < actualtbl; count++) { + uint16_t userid, parentid = 0; + + lctentptr = &(lct_buf->LCTEntry[count]); + userid = get_lct_entry_UserTID(lctentptr, lctbuf_dmaacchandle); + parentid = get_lct_entry_ParentTID(lctentptr, + lctbuf_dmaacchandle); + + /* unclaim devices */ + if (userid == 0xFFF) { + int class; + uint16_t tid; + + class = get_lct_entry_Class(lctentptr, + lctbuf_dmaacchandle); + tid = get_lct_entry_LocalTID(lctentptr, + lctbuf_dmaacchandle); + + /* + * search for SCSI Peripheral with Parent ID + * as the same as hba's TID and unclaimed devices + */ + + if ((parentid == i2ohba->i2ohba_tid) && + (class == I2O_CLASS_SCSI_PERIPHERAL)) { + /* claim it */ + if (i2ohba_utilclaim_msg(i2ohba, tid, + I2O_UTIL_CLAIM)) { + i2ohba_i_log(NULL, CE_WARN, + "?i2ohba_i_tid_to_scsi: " + "i2ohba_utilclaim_msg failed"); + } else { + i2ohba_i_log(NULL, CE_CONT, + "?utilclaim:" + "Tid: 0x%x, SCSI_PERIPHERAL", tid); + /* claim succeed */ + map[entries].tid = tid; + entries++; + } + } + + /* + * find our own bus adapter port and + * claim it as well + */ + if ((tid == i2ohba->i2ohba_tid) && + (class == I2O_CLASS_BUS_ADAPTER_PORT)) { + if (i2ohba_utilclaim_msg(i2ohba, tid, + I2O_UTIL_CLAIM)) { + i2ohba_i_log(NULL, CE_WARN, + "?i2ohba_i_tid_to_scsi: " + "i2ohba_utilclaim_msg failed"); + /* + * it is pointless to continue here + * because if we can't claim the bus port + * then we can't do anything except for + * sending utilgetparm and busreset msgs + */ + break; + } else { + i2ohba_i_log(NULL, CE_CONT, + "?utilclaim:" + "Tid: 0x%x, BUS_ADAPTER_PORT", tid); + rval = 0; + } + } + + } /* userid == 0xFFF */ + } /* for loop */ + + /* + * initialized all utilparam message's mutex's + */ + for (i = 0; i < N_I2OHBA_TARGETS_WIDE; i++) { + mutex_init(I2OHBA_UTILPARAM_MUTEX(i2ohba, i), NULL, + MUTEX_DRIVER, NULL); + cv_init(I2OHBA_UTILPARAM_CV(i2ohba, i), NULL, + CV_DRIVER, NULL); + } + + /* + * Now allocated parameter for each qualified peripheral + */ + for (i = 0; i < entries; i++) { + /* + * call i2ohba_utilparamget_msg to get + * parameters + */ + rval = i2ohba_utilparamget_msg(i2ohba, i, ALL_UTILPARAMS); + if (rval) { + i2ohba_i_log(NULL, CE_WARN, "?i2ohba_i_tid_to_scsi:" + " i2ohba_utilparamget_msg failed"); + } + + } /* for loop */ + + if (i > 0) + rval = 0; + return (rval); + +} + +/* + * Function name: i2ohba_utilcliam_msg() + * + * Return Values: 0 - success + * -1 - fail to claim the device + * + * Description : send a utilclaim or utilclaim_release msg + * to the device + * + * This function is called from i2ohba_i_tid_to_scsi() + */ +static int +i2ohba_utilclaim_msg(struct i2ohba *i2ohba, uint16_t tid, int action) +{ + int rval = -1; + i2o_util_claim_message_t *msgptr; + i2o_msg_handle_t msg_handle; + ddi_acc_handle_t acc_handle; + struct i2ohba_util *sp; + + if (i2o_msg_alloc(i2ohba->i2ohba_iophdl, I2O_MSG_SLEEP, NULL, + (void *)&msgptr, &msg_handle, &acc_handle) != DDI_SUCCESS) { + i2ohba_i_log(NULL, CE_WARN, "?i2ohba_utilclaim_msg: " + "i2o_msg_alloc failed"); + return (rval); + } + + /* + * construct a i2o_hba_bus_reset_message + */ + msgptr->StdMessageFrame.VersionOffset = 0x01; + msgptr->StdMessageFrame.MsgFlags = 0; + ddi_put16(acc_handle, &msgptr->StdMessageFrame.MessageSize, + sizeof (i2o_util_claim_message_t) >> 2); + put_msg_TargetAddress(&msgptr->StdMessageFrame, tid, acc_handle); + put_msg_InitiatorAddress(&msgptr->StdMessageFrame, I2O_OSM_TID, + acc_handle); + put_msg_Function(&msgptr->StdMessageFrame, action, acc_handle); + ddi_put32(acc_handle, + (uint32_t *)&msgptr->StdMessageFrame.InitiatorContext, + (uint32_t)i2ohba_utilmsg_comp); + ddi_put8(acc_handle, &msgptr->ClaimType, I2O_CLAIM_TYPE_PRIMARY_USER); + + /* + * allocating synchronized status buffer + */ + sp = kmem_alloc(sizeof (struct i2ohba_util), KM_SLEEP); + + ddi_put32(acc_handle, &msgptr->TransactionContext, + (uint32_t)(uintptr_t)sp); + + /* + * initialized a mutex and cond variable to + * send message to IOP, and wait for it to signal back + */ + sp->mutex = I2OHBA_UTILPARAM_MUTEX(i2ohba, 0); + sp->cv = I2OHBA_UTILPARAM_CV(i2ohba, 0); + mutex_enter(sp->mutex); + sp->wakeup = UTIL_MSG_SLEEP; + sp->status = 0; + (void) i2o_msg_send(i2ohba->i2ohba_iophdl, msgptr, msg_handle); + while (!sp->wakeup) + cv_wait(sp->cv, sp->mutex); + mutex_exit(sp->mutex); + + /* + * process reply message + */ + + switch (sp->status) { + case I2O_REPLY_STATUS_SUCCESS: + rval = 0; + DEBUGF(1, (CE_CONT, "Reset Succeeded")); + break; + default: + i2ohba_i_log(NULL, CE_CONT, "Reset Failed"); + /* + * Failed the reset for now, + * we can also parse the AdapterStatus + * and retry if needed + */ + break; + } + +cleanup: + if (sp) + kmem_free(sp, sizeof (struct i2ohba_util)); + return (rval); +} + +/* + * i2ohba_utilmsg_comp + * passed the status back to the caller to decided + * what to do with the error code. + */ +/*ARGSUSED*/ +static void +i2ohba_utilmsg_comp(i2o_message_frame_t *msg, ddi_acc_handle_t acc_handle) +{ + + i2o_single_reply_message_frame_t *reply; + int type, reqstatus, detailstatus, adptrstatus; + struct i2ohba_util *sp; + + + reply = (i2o_single_reply_message_frame_t *)msg; + sp = (struct i2ohba_util *)(uintptr_t)ddi_get32(acc_handle, + &reply->TransactionContext); + + type = get_msg_Function(&reply->StdMessageFrame, acc_handle); + + switch (type) { + /* + * Bus Reset + */ + case I2O_HBA_BUS_RESET: + detailstatus = ddi_get16(acc_handle, + &reply->DetailedStatusCode); + adptrstatus = detailstatus & I2O_SCSI_HBA_DSC_MASK; + if (adptrstatus != I2O_HBA_DSC_BUS_RESET) + reqstatus = I2O_REPLY_STATUS_TRANSACTION_ERROR; + else + reqstatus = reply->ReqStatus; + break; + + /* + * Utility Class Function + */ + case I2O_UTIL_PARAMS_GET: + case I2O_UTIL_PARAMS_SET: + case I2O_UTIL_CLAIM: + case I2O_UTIL_CLAIM_RELEASE: + /* + * Adapter Class Function + */ + case I2O_HBA_ADAPTER_RESET: + case I2O_SCSI_DEVICE_RESET: + reqstatus = reply->ReqStatus; + break; + + default: + DEBUGF(2, (CE_CONT, "Error! Not Supported")); + return; + + } + + mutex_enter(sp->mutex); + sp->wakeup = UTIL_MSG_WAKEUP; + sp->status = reqstatus; + cv_broadcast(sp->cv); + mutex_exit(sp->mutex); +} + +/*ARGSUSED*/ +static int +i2ohba_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) +{ + + struct i2ohba *i2ohba; + scsi_hba_tran_t *tran; + int instance = ddi_get_instance(dip); + int i; + + switch (cmd) { + case DDI_DETACH: + { + if ((tran = ddi_get_driver_private(dip)) == NULL) + return (DDI_FAILURE); + + i2ohba = TRAN2I2OHBA(tran); + if (!i2ohba) { + return (DDI_FAILURE); + } + + if (i2ohba->i2ohba_iophdl) + i2o_msg_osm_unregister(&i2ohba->i2ohba_iophdl); + + /* + * deallocate reset notify callback list + */ + scsi_hba_reset_notify_tear_down( + i2ohba->i2ohba_reset_notify_listf); + + if (i2ohba->i2ohba_timeout_id != 0) { + (void) untimeout(i2ohba->i2ohba_timeout_id); + i2ohba->i2ohba_timeout_id = NULL; + } + + /* + * remove device MT locks + */ + mutex_destroy(I2OHBA_REQ_MUTEX(i2ohba)); + mutex_destroy(I2OHBA_RESET_MUTEX(i2ohba)); + cv_destroy(I2OHBA_RESET_CV(i2ohba)); + + for (i = 0; i < N_I2OHBA_TARGETS_WIDE; i++) { + + mutex_destroy(I2OHBA_UTILPARAM_MUTEX(i2ohba, i)); + cv_destroy(I2OHBA_UTILPARAM_CV(i2ohba, i)); + } + + /* + * remove properties created druing attach() + */ + ddi_prop_remove_all(dip); + + /* + * Delete the DMA limits, transport vectors and remove the + * device links to the scsi_transport layer. + * -- ddi_set_driver_private(dip, NULL) + */ + (void) scsi_hba_detach(dip); + + /* + * Free the scsi_transport structure for this device. + */ + scsi_hba_tran_free(tran); + + i2ohba->i2ohba_dip = (dev_info_t *)NULL; + i2ohba->i2ohba_tran = (scsi_hba_tran_t *)NULL; + + ddi_soft_state_free(i2ohba_state, instance); + ddi_remove_minor_node(dip, NULL); + + return (DDI_SUCCESS); + } + /* XXXLWXXX */ + case DDI_SUSPEND: + case DDI_PM_SUSPEND: + default: + return (DDI_FAILURE); + } +} + + +/* + * Function name : i2ohba_tran_tgt_init + * + * Return Values : DDI_SUCCESS if target supported, DDI_FAILURE otherwise + * + */ +/*ARGSUSED*/ +static int +i2ohba_tran_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, + scsi_hba_tran_t *tran, struct scsi_device *sd) +{ + return ((sd->sd_address.a_target < N_I2OHBA_TARGETS_WIDE && + sd->sd_address.a_lun == 0) ? DDI_SUCCESS : + DDI_FAILURE); +} + + +/* + * Function name : i2ohba_i_initcap + * + * Return Values : NONE + * Description : Initializes the default target capabilites and + * Sync Rates. + * + * Context : Called from the user thread through attach. + * + */ +static void +i2ohba_i_initcap(struct i2ohba *i2ohba) +{ + int i, option; + uint16_t cap, synch; + uint8_t offset; + i2o_tid_scsi_ent_t **map = i2ohba->i2ohba_tgt_id_map; + + for (i = 0; i < N_I2OHBA_TARGETS_WIDE; i++) { + cap = 0; + synch = 0; + option = 0; + offset = 0; + + if (map[i] == NULL) + continue; + + /* + * Check for connect/disconnect + */ + if (map[i]->scsi_info_scalar.Flags & + I2O_SCSI_ENABLE_DISCONNECT) { + option |= SCSI_OPTIONS_DR; + cap |= I2OHBA_CAP_DISCONNECT; + } else { + option &= ~SCSI_OPTIONS_DR; + } + + /* + * Check for Wide data + */ + if (map[i]->scsi_info_scalar.Flags & + I2O_SCSI_DATA_WIDTH_MASK) { + option |= SCSI_OPTIONS_WIDE; + cap |= I2OHBA_CAP_WIDE; + } else { + option &= ~SCSI_OPTIONS_WIDE; + } + + /* + * Check for synchronization + */ + if (map[i]->scsi_info_scalar.Flags & + I2O_SCSI_ENABLE_SYNC_NEGOTIATION) { + option |= SCSI_OPTIONS_SYNC; + cap |= I2OHBA_CAP_SYNC; + } else { + option &= ~SCSI_OPTIONS_SYNC; + } + + synch = (uint16_t)map[i]->scsi_info_scalar.NegSyncRate; + offset = (uint8_t)map[i]->scsi_info_scalar.NegOffset; + + /* + * Check for tag queuing capability + */ + if (map[i]->scsi_info_scalar.QueueDepth) { + option |= SCSI_OPTIONS_TAG; + cap |= I2OHBA_CAP_TAG; + } else { + option &= ~SCSI_OPTIONS_TAG; + } + + i2ohba->i2ohba_target_scsi_option[i] = option; + i2ohba->i2ohba_cap[i] = cap; + i2ohba->i2ohba_synch[i] = synch; + i2ohba->i2ohba_offset[i] = offset; + } +} + + + +/* + * Function name : i2ohba_scsi_getcap() + * + * Return Values : current value of capability, if defined + * -1 if capability is not defined + * + * Description : returns current capability value + * + * Context : Can be called from different kernel process threads. + * Can be called by interrupt thread. + */ +static int +i2ohba_scsi_getcap(struct scsi_address *ap, char *cap, int whom) +{ + struct i2ohba *i2ohba = ADDR2I2OHBA(ap); + i2o_tid_scsi_ent_t **map = i2ohba->i2ohba_tgt_id_map; + uint8_t tgt = ap->a_target; + int rval = 0; + + /* + * We don't allow inquiring about capabilities for other targets + */ + if (cap == NULL || whom == 0 || map[tgt] == NULL) { + return (-1); + } + + I2OHBA_MUTEX_ENTER(i2ohba); + + switch (scsi_hba_lookup_capstr(cap)) { + case SCSI_CAP_GEOMETRY: + { /* left this code from adp driver */ + uint32_t total_sectors, c, h, s, t; + c = 1024L; + s = 62L; + + total_sectors = i2ohba->i2ohba_totsec[tgt]; + + t = c * s; + h = total_sectors / t; + if (total_sectors % t) { + h ++; + t = c * h; + s = total_sectors / t; + if (total_sectors % t) { + s++; + t = h * s; + c = total_sectors / t; + } + } + if (c == 0) rval = 1; + + rval = ((h << 16) | s); + break; + } + case SCSI_CAP_DMA_MAX: + rval = 1 << 24; /* Limit to 16MB max transfer */ + break; + case SCSI_CAP_MSG_OUT: + rval = 1; + break; + case SCSI_CAP_DISCONNECT: + if ((i2ohba->i2ohba_target_scsi_option[tgt] & + SCSI_OPTIONS_DR) == 0) { + break; + } else if ((i2ohba->i2ohba_cap[tgt] & I2OHBA_CAP_DISCONNECT) + == 0) { + break; + } + rval = 1; + break; + case SCSI_CAP_SYNCHRONOUS: + if ((i2ohba->i2ohba_target_scsi_option[tgt] & + SCSI_OPTIONS_SYNC) == 0) { + break; + } else if ((i2ohba->i2ohba_cap[tgt] & I2OHBA_CAP_SYNC) == 0) { + break; + } + rval = 1; + break; + case SCSI_CAP_WIDE_XFER: + if ((i2ohba->i2ohba_target_scsi_option[tgt] & + SCSI_OPTIONS_WIDE) == 0) { + break; + } else if ((i2ohba->i2ohba_cap[tgt] & I2OHBA_CAP_WIDE) == 0) { + break; + } + rval = 1; + break; + case SCSI_CAP_TAGGED_QING: + if ((i2ohba->i2ohba_target_scsi_option[tgt] & + SCSI_OPTIONS_DR) == 0 || + (i2ohba->i2ohba_target_scsi_option[tgt] & + SCSI_OPTIONS_TAG) == 0) { + break; + } else if ((i2ohba->i2ohba_cap[tgt] & I2OHBA_CAP_TAG) == 0) { + break; + } + rval = 1; + break; + case SCSI_CAP_UNTAGGED_QING: + rval = 0; + break; + case SCSI_CAP_PARITY: + if (i2ohba->i2ohba_target_scsi_option[tgt] & + SCSI_OPTIONS_PARITY) { + rval = 1; + } + break; + case SCSI_CAP_INITIATOR_ID: + rval = i2ohba->i2ohba_initiator_id; + break; + case SCSI_CAP_ARQ: + rval = 1; + break; + case SCSI_CAP_LINKED_CMDS: + break; + case SCSI_CAP_RESET_NOTIFICATION: + rval = 1; + break; + default: + rval = -1; + break; + } + + I2OHBA_MUTEX_EXIT(i2ohba); + + return (rval); +} + + +/* + * Function name : i2ohba_scsi_setcap() + * + * Return Values : 1 - capability exists and can be set to new value + * 0 - capability could not be set to new value + * -1 - no such capability + * + * Description : sets a capability for a target + * + * Context : Can be called from different kernel process threads. + * Can be called by interrupt thread. + */ +static int +i2ohba_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom) +{ + struct i2ohba *i2ohba = ADDR2I2OHBA(ap); + i2o_tid_scsi_ent_t **map = i2ohba->i2ohba_tgt_id_map; + uint8_t tgt = ap->a_target; + int update = 0; + int sync = 0; + int rval = 0; + + /* + * We don't allow setting capabilities for other targets + * and the targets that are not in this OSM's control + */ + if (cap == NULL || whom == 0 || map[tgt] == NULL) { + return (-1); + } + + I2OHBA_MUTEX_ENTER(i2ohba); + + switch (scsi_hba_lookup_capstr(cap)) { + case SCSI_CAP_DMA_MAX: + case SCSI_CAP_MSG_OUT: + case SCSI_CAP_PARITY: + case SCSI_CAP_UNTAGGED_QING: + case SCSI_CAP_LINKED_CMDS: + case SCSI_CAP_RESET_NOTIFICATION: + case SCSI_CAP_GEOMETRY: + /* + * None of these are settable via + * the capability interface. + */ + break; + + case SCSI_CAP_SECTOR_SIZE: + if (value) { + i2ohba->i2ohba_secsz[tgt] = value; + rval = 1; + } + break; + + case SCSI_CAP_TOTAL_SECTORS: + if (value) { + i2ohba->i2ohba_totsec[tgt] = value; + rval = 1; + } + break; + case SCSI_CAP_ARQ: + if (value) { + i2ohba->i2ohba_cap[tgt] |= I2OHBA_CAP_AUTOSENSE; + } else { + i2ohba->i2ohba_cap[tgt] &= ~I2OHBA_CAP_AUTOSENSE; + } + rval = 1; + break; + + /* disconnect/reconncet either the target supports or doesn't */ + case SCSI_CAP_DISCONNECT: + if ((i2ohba->i2ohba_target_scsi_option[tgt] & + SCSI_OPTIONS_DR) == 0) { + break; + } else { + if (value) { + if ((i2ohba->i2ohba_cap[tgt] & + I2OHBA_CAP_DISCONNECT) == 0) { + if (i2ohba_utilparamset_msg(i2ohba, + tgt, map[tgt]->tid, + I2O_SCSI_DEVICE_INFO_GROUP_NO, 0x1, + I2O_SCSI_ENABLE_DISCONNECT) != 0) + break; + i2ohba->i2ohba_cap[tgt] |= + I2OHBA_CAP_DISCONNECT; + } + } else { + if ((i2ohba->i2ohba_cap[tgt] & + I2OHBA_CAP_DISCONNECT) == 1) { + if (i2ohba_utilparamset_msg(i2ohba, + tgt, map[tgt]->tid, + I2O_SCSI_DEVICE_INFO_GROUP_NO, 0x1, + I2O_SCSI_DISABLE_DISCONNECT) != 0) + break; + i2ohba->i2ohba_cap[tgt] &= + ~I2OHBA_CAP_DISCONNECT; + } + } + } + rval = 1; + break; + + /* these can be set through UtilParamSet message */ + case SCSI_CAP_SYNCHRONOUS: + if ((i2ohba->i2ohba_target_scsi_option[tgt] & + SCSI_OPTIONS_SYNC) == 0) { + break; + } else { + if (value) { + if ((i2ohba->i2ohba_cap[tgt] & + I2OHBA_CAP_SYNC) == 0) { + if (i2ohba_utilparamset_msg(i2ohba, + tgt, map[tgt]->tid, + I2O_SCSI_DEVICE_INFO_GROUP_NO, 0x1, + I2O_SCSI_ENABLE_SYNC_NEGOTIATION) + != 0) + break; + /* set sync speed to Max */ + if (i2ohba_utilparamset_msg(i2ohba, + tgt, map[tgt]->tid, + I2O_SCSI_DEVICE_INFO_GROUP_NO, 0xA, + 0xFFFF) != 0) + break; + /* read the set value */ + if (i2ohba_utilparamget_msg(i2ohba, + tgt, SYNC_UTILPARAM) != 0) + break; + i2ohba->i2ohba_cap[tgt] |= + I2OHBA_CAP_SYNC; + sync++; + update++; + } + } else { + if ((i2ohba->i2ohba_cap[tgt] & + I2OHBA_CAP_SYNC) == 1) { + if (i2ohba_utilparamset_msg(i2ohba, + tgt, map[tgt]->tid, + I2O_SCSI_DEVICE_INFO_GROUP_NO, 0x1, + I2O_SCSI_DISABLE_SYNC_NEGOTIATION) + != 0) + break; + i2ohba->i2ohba_cap[tgt] &= + ~I2OHBA_CAP_SYNC; + update++; + } + } + } + rval = 1; + break; + case SCSI_CAP_TAGGED_QING: + if ((i2ohba->i2ohba_target_scsi_option[tgt] & + SCSI_OPTIONS_DR) == 0 || + (i2ohba->i2ohba_target_scsi_option[tgt] & + SCSI_OPTIONS_TAG) == 0) { + break; + } else { + if (value) { + if ((i2ohba->i2ohba_cap[tgt] & + I2OHBA_CAP_TAG) == 0) { + if (i2ohba_utilparamset_msg(i2ohba, + tgt, map[tgt]->tid, + I2O_SCSI_DEVICE_INFO_GROUP_NO, 0x5, + 0) != 0) + break; + i2ohba->i2ohba_cap[tgt] |= + I2OHBA_CAP_TAG; + update++; + } + } else { + if ((i2ohba->i2ohba_cap[tgt] & + I2OHBA_CAP_TAG) == 1) { + if (i2ohba_utilparamset_msg(i2ohba, + tgt, map[tgt]->tid, + I2O_SCSI_DEVICE_INFO_GROUP_NO, 0x5, + (uint16_t)1) != 0) + break; + i2ohba->i2ohba_cap[tgt] &= + ~I2OHBA_CAP_TAG; + update++; + } + } + } + rval = 1; + break; + case SCSI_CAP_WIDE_XFER: + if ((i2ohba->i2ohba_target_scsi_option[tgt] & + SCSI_OPTIONS_WIDE) == 0) { + break; + } else { + if (value) { + if ((i2ohba->i2ohba_cap[tgt] & + I2OHBA_CAP_WIDE) == 0) { + if (i2ohba_utilparamset_msg(i2ohba, + tgt, map[tgt]->tid, + I2O_SCSI_DEVICE_INFO_GROUP_NO, 0x1, + I2O_SCSI_DATA_WIDTH_16) != 0) + break; + i2ohba->i2ohba_cap[tgt] |= + I2OHBA_CAP_WIDE; + update++; + } + } else { + if ((i2ohba->i2ohba_cap[tgt] & + I2OHBA_CAP_WIDE) == 1) { + if (i2ohba_utilparamset_msg(i2ohba, + tgt, map[tgt]->tid, + I2O_SCSI_DEVICE_INFO_GROUP_NO, 0x1, + I2O_SCSI_DATA_WIDTH_8) != 0) + break; + i2ohba->i2ohba_cap[tgt] &= + ~I2OHBA_CAP_WIDE; + update++; + } + } + } + rval = 1; + break; + case SCSI_CAP_INITIATOR_ID: + if (value < N_I2OHBA_TARGETS_WIDE) { + if (i2ohba->i2ohba_initiator_id != (uint16_t)value) { + /* + * set Initiator SCSI ID + */ + if (i2ohba_utilparamset_msg(i2ohba, + i2ohba->i2ohba_initiator_id, + i2ohba->i2ohba_tid, + I2O_HBA_SCSI_CONTROLLER_INFO_GROUP_NO, 0x4, + value) == 0) { + rval = 1; + i2ohba->i2ohba_initiator_id = value; + } + } + } + break; + + default: + rval = -1; + break; + } + + + /* + * now set flag so latter in i2ohba_i_watch(), + * we can set prop_update + */ + if ((rval == 1) && (update > 0)) { + i2ohba->i2ohba_need_prop_update |= 1 << tgt; + if (sync) + i2ohba_i_updatesync(i2ohba, tgt); + } + + I2OHBA_MUTEX_EXIT(i2ohba); + + return (rval); +} + +/* + * Function name : i2ohba_i_updatesync() + * + * Return Values : -1 failed + * 0 success + * + * Description : modifies/update target sync mode speed, widexfer, + * and TQ. + * + * Context : Can be called from different kernel process threads. + * Can not be called by interrupt thread + */ +static void +i2ohba_i_updatesync(struct i2ohba *i2ohba, int tgt) +{ + uint16_t synch; + uint8_t offset; + i2o_tid_scsi_ent_t **map = i2ohba->i2ohba_tgt_id_map; + + if (map[tgt] == NULL) + return; + + if (map[tgt]->scsi_info_scalar.Flags & + I2O_SCSI_ENABLE_SYNC_NEGOTIATION) { + synch = (uint16_t)map[tgt]->scsi_info_scalar.NegSyncRate; + offset = (uint8_t)map[tgt]->scsi_info_scalar.NegOffset; + + i2ohba->i2ohba_synch[tgt] = synch; + i2ohba->i2ohba_offset[tgt] = offset; + } +} + +/* + * Function name : i2ohba_i_update_props() + * + * Description : Creates/modifies/removes a target sync mode speed, + * wide, and TQ properties + * If offset is 0 then asynchronous mode is assumed and the + * property is removed, if it existed. + * + * Context : Can be called from different kernel process threads. + * Can not be called by interrupt thread + */ +static void +i2ohba_i_update_props(struct i2ohba *i2ohba, int tgt) +{ + static char property[32]; + int xfer_speed = 0; + int wide_enabled; + int tq_enabled; + uint16_t cap; + uint16_t synch; + uint8_t offset; + + cap = i2ohba->i2ohba_cap[tgt]; + synch = i2ohba->i2ohba_synch[tgt]; + offset = i2ohba->i2ohba_offset[tgt]; + + tq_enabled = cap & I2OHBA_CAP_TAG; + wide_enabled = cap & I2OHBA_CAP_WIDE; + + if (offset && synch) { + if (wide_enabled) { + /* double xfer speed if wide has been enabled */ + xfer_speed = ((int)synch * 2); + } else { + xfer_speed = (int)(synch); + } + } + + (void) sprintf(property, "target%x-sync-speed", tgt); + i2ohba_i_update_this_prop(i2ohba, property, xfer_speed); + + (void) sprintf(property, "target%x-wide", tgt); + i2ohba_i_update_this_prop(i2ohba, property, wide_enabled); + + (void) sprintf(property, "target%x-TQ", tgt); + i2ohba_i_update_this_prop(i2ohba, property, tq_enabled); +} + +/* + * Update a property's value + */ +static void +i2ohba_i_update_this_prop(struct i2ohba *i2ohba, char *property, int value) +{ + dev_info_t *dip = i2ohba->i2ohba_dip; + + + if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, + property, value) != DDI_PROP_SUCCESS) { + i2ohba_i_log(NULL, CE_CONT, "?i2ohba_i_update_this_prop:" + " can't update %s property to 0x%x", + property, value); + } +} + + +/* + * Function name : i2ohba_scsi_init_pkt + * + * Return Values : pointer to scsi_pkt, or NULL + * Description : Called by kernel on behalf of a target driver + * calling scsi_init_pkt(9F). + * Refer to tran_init_pkt(9E) man page + * + * Context : Can be called from different kernel process threads. + * Can be called by interrupt thread. + */ +static struct scsi_pkt * +i2ohba_scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt, + struct buf *bp, int cmdlen, int statuslen, int tgtlen, + int flags, int (*callback)(), caddr_t arg) +{ + struct i2ohba_cmd *sp; + struct i2ohba *i2ohba = ADDR2I2OHBA(ap); + struct scsi_pkt *new_pkt; + + ASSERT(callback == NULL_FUNC || callback == SLEEP_FUNC); + + /* + * First step of i2ohba_scsi_init_pkt: pkt allocation + */ + if (pkt == NULL) { + pkt = scsi_hba_pkt_alloc(i2ohba->i2ohba_dip, ap, cmdlen, + statuslen, tgtlen, sizeof (struct i2ohba_cmd), callback, + arg); + + if (pkt == NULL) { + return (NULL); + } + + sp = PKT2CMD(pkt); + + /* + * Initialize the new pkt - we redundantly initialize + * all the fields for illustrative purposes. + */ + sp->cmd_pkt = pkt; + sp->cmd_flags = 0; + sp->cmd_scblen = statuslen; + sp->cmd_cdblen = (uint8_t)cmdlen; + sp->cmd_privlen = tgtlen; + sp->cmd_dmahandle = NULL; + sp->cmd_dmacount = 0; + sp->cmd_cookie = 0; + pkt->pkt_address = *ap; + pkt->pkt_comp = (void (*)())NULL; + pkt->pkt_flags = 0; + pkt->pkt_time = 0; + pkt->pkt_resid = 0; + pkt->pkt_statistics = 0; + pkt->pkt_reason = 0; + + new_pkt = pkt; + } else { + sp = PKT2CMD(pkt); + new_pkt = NULL; + } + + /* + * Second step of i2ohba_scsi_init_pkt: dma allocation/move + */ + if (bp && bp->b_bcount != 0) { + if (sp->cmd_dmahandle == NULL) { + ASSERT((sp->cmd_flags & CFLAG_DMAVALID) == 0); + if (i2ohba_i_dma_alloc(i2ohba, pkt, bp, + flags, callback) == -1) { + if (new_pkt) { + scsi_hba_pkt_free(ap, new_pkt); + } + return ((struct scsi_pkt *)NULL); + } + } else { + ASSERT(new_pkt == NULL); + ASSERT(sp->cmd_flags & CFLAG_DMAVALID); + if (i2ohba_i_dma_move(i2ohba, pkt, bp) < 0) { + return ((struct scsi_pkt *)NULL); + } + } + ASSERT(sp->cmd_flags & CFLAG_DMAVALID); + DEBUGF(3, (CE_CONT, "init: bcount = %lx, resid = %lx", + bp->b_bcount, pkt->pkt_resid)); + } + + return (pkt); +} + +/* + * Function name : i2ohba_i_dma_alloc + * + * Return Values : 0 if successful, -1 if failure + * Description : allocate DMA resources + * + * Context : Can only be called from i2ohba_scsi_init_pkt() + */ +static int +i2ohba_i_dma_alloc(struct i2ohba *i2ohba, struct scsi_pkt *pkt, + struct buf *bp, int flags, int (*callback)()) +{ + struct i2ohba_cmd *sp = PKT2CMD(pkt); + int dma_flags; + int (*cb)(caddr_t); + int i; + + ASSERT(callback == NULL_FUNC || callback == SLEEP_FUNC); + + if (bp->b_flags & B_READ) { + sp->cmd_flags &= ~CFLAG_DMASEND; + dma_flags = DDI_DMA_READ; + } else { + sp->cmd_flags |= CFLAG_DMASEND; + dma_flags = DDI_DMA_WRITE; + } + + if (flags & PKT_CONSISTENT) { + sp->cmd_flags |= CFLAG_CMDIOPB; + dma_flags |= DDI_DMA_CONSISTENT; + } + + if (flags & PKT_DMA_PARTIAL) { + dma_flags |= DDI_DMA_PARTIAL; + } + + dma_flags |= DDI_DMA_REDZONE; + + cb = (callback == NULL_FUNC) ? DDI_DMA_DONTWAIT : DDI_DMA_SLEEP; + + if ((i = ddi_dma_alloc_handle(i2ohba->i2ohba_dip, + &i2ohba_dma_attr, cb, NULL, &sp->cmd_dmahandle)) + != DDI_SUCCESS) { + switch (i) { + case DDI_DMA_BADATTR: + bioerror(bp, EFAULT); + return (-1); + + case DDI_DMA_NORESOURCES: + bioerror(bp, 0); + return (-1); + + default: + i2ohba_i_log(NULL, CE_WARN, + "?ddi_dma_alloc_handle:" + " 0x%x impossible", i); + /*NOTREACHED*/ + } + } + +#ifdef I2OHBA_DEBUG + ddi_dma_bufalloc++; +#endif + + i = ddi_dma_buf_bind_handle(sp->cmd_dmahandle, bp, dma_flags, + cb, NULL, &sp->cmd_dmacookies[0], &sp->cmd_ncookies); +#ifdef I2OHBA_DEBUG + ddi_dma_buf_bind++; +#endif + + DEBUGF(3, (CE_CONT, "dma_alloc: cmd_ncookies is %d\n", + sp->cmd_ncookies)); + + switch (i) { + case DDI_DMA_PARTIAL_MAP: + ASSERT(dma_flags & DDI_DMA_PARTIAL); + + if (ddi_dma_numwin(sp->cmd_dmahandle, &sp->cmd_nwin) == + DDI_FAILURE) { + i2ohba_i_log(NULL, CE_WARN, + "?ddi_dma_numwin() failed"); + /*NOTREACHED*/ + } + + if (ddi_dma_getwin(sp->cmd_dmahandle, sp->cmd_curwin, + &sp->cmd_dma_offset, &sp->cmd_dma_len, + &sp->cmd_dmacookies[0], &sp->cmd_ncookies) == + DDI_FAILURE) { + i2ohba_i_log(NULL, CE_WARN, + "?ddi_dma_getwin() failed"); + /*NOTREACHED*/ + } + goto get_dma_cookies; + + case DDI_DMA_MAPPED: + sp->cmd_nwin = 1; + sp->cmd_dma_len = 0; + sp->cmd_dma_offset = 0; + +get_dma_cookies: + i = 0; + sp->cmd_dmacount = 0; + for (;;) { + sp->cmd_dmacount += sp->cmd_dmacookies[i++].dmac_size; + + if (i == I2OHBA_CMD_NSEGS || i == sp->cmd_ncookies) + break; + ddi_dma_nextcookie(sp->cmd_dmahandle, + &sp->cmd_dmacookies[i]); + } + + sp->cmd_cookie = i; + sp->cmd_cookiecnt = i; + + sp->cmd_flags |= CFLAG_DMAVALID; + pkt->pkt_resid = bp->b_bcount - sp->cmd_dmacount; + + DEBUGF(3, (CE_CONT, "bcount is %lx, dmacount is %lx," + " resid is %lx\n", + bp->b_bcount, sp->cmd_dmacount, pkt->pkt_resid)); + + return (0); + + case DDI_DMA_NORESOURCES: + bioerror(bp, 0); + break; + + case DDI_DMA_NOMAPPING: + bioerror(bp, EFAULT); + break; + + case DDI_DMA_TOOBIG: + bioerror(bp, EINVAL); + break; + + case DDI_DMA_INUSE: + i2ohba_i_log(NULL, CE_WARN, "?ddi_dma_buf_bind_handle:" + " DDI_DMA_INUSE impossible"); + /*NOTREACHED*/ + + default: + i2ohba_i_log(NULL, CE_WARN, "?ddi_dma_buf_bind_handle:" + " 0x%x impossible", i); + /*NOTREACHED*/ + } + + ddi_dma_free_handle(&sp->cmd_dmahandle); + sp->cmd_dmahandle = NULL; + sp->cmd_flags &= ~CFLAG_DMAVALID; + return (-1); +} + + +/* + * Function name : i2ohba_i_dma_move + * + * Return Values : 0 if successful, -1 if failure + * Description : move DMA resources to next DMA window + * + * Context : Can only be called from i2ohba_scsi_init_pkt() + */ +/*ARGSUSED*/ +static int +i2ohba_i_dma_move(struct i2ohba *i2ohba, struct scsi_pkt *pkt, struct buf *bp) +{ + struct i2ohba_cmd *sp = PKT2CMD(pkt); + int i; + + ASSERT(sp->cmd_flags & CFLAG_COMPLETED); + sp->cmd_flags &= ~CFLAG_COMPLETED; + + /* + * If there are no more cookies remaining in this window, + * must move to the next window first. + */ + if (sp->cmd_cookie == sp->cmd_ncookies) { + /* + * 1217340: cmdk reuses pkts incorrectly + */ + if (sp->cmd_curwin == sp->cmd_nwin && sp->cmd_nwin == 1) + return (0); + + /* + * At last window, cannot move + */ + if (++sp->cmd_curwin >= sp->cmd_nwin) + return (-1); + + if (ddi_dma_getwin(sp->cmd_dmahandle, sp->cmd_curwin, + &sp->cmd_dma_offset, &sp->cmd_dma_len, + &sp->cmd_dmacookies[0], &sp->cmd_ncookies) == DDI_FAILURE) + return (-1); + + sp->cmd_cookie = 0; + } else { + /* + * Still more cookies in this window - get the next one + */ + ddi_dma_nextcookie(sp->cmd_dmahandle, &sp->cmd_dmacookies[0]); + } + + /* + * Get remaining cookies in this window, up to our maximum + */ + i = 0; + for (;;) { + sp->cmd_dmacount += sp->cmd_dmacookies[i++].dmac_size; + sp->cmd_cookie++; + if (i == I2OHBA_CMD_NSEGS || sp->cmd_cookie == sp->cmd_ncookies) + break; + ddi_dma_nextcookie(sp->cmd_dmahandle, &sp->cmd_dmacookies[i]); + } + sp->cmd_cookiecnt = i; + + pkt->pkt_resid = bp->b_bcount - sp->cmd_dmacount; + return (0); +} + + +/* + * Function name : i2ohba_scsi_destroy_pkt + * + * Return Values : none + * Description : Called by kernel on behalf of a target driver + * calling scsi_destroy_pkt(9F). + * Refer to tran_destroy_pkt(9E) man page + * + * Context : Can be called from different kernel process threads. + * Can be called by interrupt thread. + */ +static void +i2ohba_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) +{ + struct i2ohba_cmd *sp = PKT2CMD(pkt); + struct i2ohba *i2ohba = ADDR2I2OHBA(ap); + i2o_tid_scsi_ent_t **map = i2ohba->i2ohba_tgt_id_map; + uint8_t tgt = ap->a_target; + + if (map[tgt] != NULL) { + + /* + * i2o_scsi_dmafree inline to make things faster + */ + if (sp->cmd_flags & CFLAG_DMAVALID) { + /* + * Free the mapping + */ + sp->cmd_flags &= ~CFLAG_DMAVALID; + if (ddi_dma_unbind_handle(sp->cmd_dmahandle) + != DDI_SUCCESS) { + i2ohba_i_log(NULL, CE_WARN, + "?i2ohba_scsi_destroy_pkt: " + "ddi_dma_unbind_handle() for dataseg" + " failed"); + /*NOTREACHED*/ + } +#ifdef I2OHBA_DEBUG + ddi_dma_buf_unbind++; +#endif + ddi_dma_free_handle(&sp->cmd_dmahandle); +#ifdef I2OHBA_DEBUG + ddi_dma_buf_free_hdl++; +#endif + sp->cmd_dmahandle = NULL; + } + } + + /* + * Free the pkt + */ + scsi_hba_pkt_free(ap, pkt); +} + + +/* + * Function name : i2ohba_scsi_dmafree() + * + * Return Values : none + * Description : free dvma resources + * + * Context : Can be called from different kernel process threads. + * Can be called by interrupt thread. + */ +/*ARGSUSED*/ +static void +i2ohba_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt) +{ + struct i2ohba_cmd *sp = PKT2CMD(pkt); + struct i2ohba *i2ohba = ADDR2I2OHBA(ap); + i2o_tid_scsi_ent_t **map = i2ohba->i2ohba_tgt_id_map; + uint8_t tgt = ap->a_target; + + if (map[tgt] != NULL) { + if (sp->cmd_flags & CFLAG_DMAVALID) { + /* + * Free the mapping. + */ + sp->cmd_flags &= ~CFLAG_DMAVALID; + if (ddi_dma_unbind_handle(sp->cmd_dmahandle) + != DDI_SUCCESS) { + i2ohba_i_log(NULL, CE_WARN, + "?i2ohba_scsi_dmafree: " + "ddi_dma_unbind_handle() for dataseg" + " failed"); + /*NOTREACHED*/ + } +#ifdef I2OHBA_DEBUG + ddi_dma_buf_unbind++; +#endif + ddi_dma_free_handle(&sp->cmd_dmahandle); +#ifdef I2OHBA_DEBUG + ddi_dma_buf_free_hdl++; +#endif + sp->cmd_dmahandle = NULL; + } + } +} + +/* + * Function name: i2ohba_scsi_sync_pkt() + * + * Return Values: none + * Description : sync dma + * + * Context : Can be called from different kernel process threads. + * Can be called by interrupt thread. + */ +/*ARGSUSED*/ +static void +i2ohba_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) +{ + int i; + struct i2ohba_cmd *sp = PKT2CMD(pkt); + struct i2ohba *i2ohba = ADDR2I2OHBA(ap); + i2o_tid_scsi_ent_t **map = i2ohba->i2ohba_tgt_id_map; + uint8_t tgt = ap->a_target; + + if (map[tgt] != NULL) { + if (sp->cmd_flags & CFLAG_DMAVALID) { + i = ddi_dma_sync(sp->cmd_dmahandle, sp->cmd_dma_offset, + sp->cmd_dma_len, + (sp->cmd_flags & CFLAG_DMASEND) ? + DDI_DMA_SYNC_FORDEV : DDI_DMA_SYNC_FORCPU); + if (i != DDI_SUCCESS) { + i2ohba_i_log(NULL, CE_WARN, + "?i2ohba_scsi_sync_pkt: sync pkt failed"); + } + } + } +} + + +/* + * routine for reset notification setup, to register or cancel. + */ +static int +i2ohba_scsi_reset_notify(struct scsi_address *ap, int flag, +void (*callback)(caddr_t), caddr_t arg) +{ + struct i2ohba *i2ohba = ADDR2I2OHBA(ap); + return (scsi_hba_reset_notify_setup(ap, flag, callback, arg, + I2OHBA_REQ_MUTEX(i2ohba), &i2ohba->i2ohba_reset_notify_listf)); +} + +/* + * Function name : i2ohba_scsi_start() + * + * Return Values : TRAN_FATAL_ERROR - i2o has been shutdown + * TRAN_BUSY - request queue is full + * TRAN_ACCEPT - pkt has been submitted to i2o + * + * Description : init pkt, start the request + * + * Context : Can be called from different kernel process threads. + * Can be called by interrupt thread. + */ +static int +i2ohba_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt) +{ + struct i2ohba_cmd *sp = PKT2CMD(pkt); + int rval = TRAN_ACCEPT; + struct i2ohba *i2ohba = ADDR2I2OHBA(ap); + dev_info_t *dip = (PKT2I2OHBA(pkt))->i2ohba_dip; + i2o_tid_scsi_ent_t **tgtmap = i2ohba->i2ohba_tgt_id_map; + i2o_scsi_scb_execute_message_t *req; + i2o_sge_chain_element_t *sgl; + i2o_sge_ignore_element_t *sgl2; + i2o_msg_handle_t msg_handle; + i2o_sge_chain_element_t *cpsgl; + ddi_acc_handle_t acc_handle; + clock_t cur_lbolt; + uint16_t tid; + uint16_t flags = 0, msgsize; + int i, val, bound = 0; + size_t sglen; + uint_t count; + + + ASSERT(I2OHBA_MUTEX_OWNED(i2ohba) == 0 || ddi_in_panic()); + + /* + * if we have a shutdown, return packet + */ + if (i2ohba->i2ohba_shutdown) { + return (TRAN_FATAL_ERROR); + } + + if (i2ohba->i2ohba_throttle) { + return (TRAN_BUSY); + } + /* + * if the target id is not in our map, don't bother composing + * the message, return fail + */ + if (tgtmap[TGT(sp)] == NULL) { + return (TRAN_FATAL_ERROR); + } else { + tid = tgtmap[TGT(sp)]->tid; + } + + i2ohba->i2ohba_counter++; + if (i2ohba->i2ohba_counter > 64) { + DEBUGF(1, (CE_CONT, "i2ohba_counter > 64\n")); + DEBUGF(1, (CE_CONT, "sp = %p\n", (void *)sp)); + i2ohba->i2ohba_counter--; + return (TRAN_BUSY); + } + + ASSERT(!(sp->cmd_flags & CFLAG_IN_TRANSPORT)); + sp->cmd_flags = (sp->cmd_flags & ~CFLAG_TRANFLAG) | + CFLAG_IN_TRANSPORT; + pkt->pkt_reason = CMD_CMPLT; + + /* + * Set up request in i2ohba_reqhead area so it is ready to + * go once we have the request mutex, + * The reason we don't allocate the msg buffer in scsi_init_pkt + * is that the msg buffer is a resource from the FIFO of the IOP + * we don't want to give that ptr around + */ + + if (i2o_msg_alloc(i2ohba->i2ohba_iophdl, I2O_MSG_DONTWAIT, + NULL, (void *)&req, &msg_handle, &acc_handle) != DDI_SUCCESS) { + i2ohba_i_log(NULL, CE_WARN, "?i2ohba_scsi_start: " + " i2o_msg_alloc failed"); + sp->cmd_flags = (sp->cmd_flags & ~CFLAG_IN_TRANSPORT); + pkt->pkt_reason = 0; + i2ohba->i2ohba_counter--; + return (TRAN_BUSY); + } + + + /* + * Constructed a scsi_scb_execute_message + */ + + /* StdMessageFrame */ + req->StdMessageFrame.VersionOffset = 0xA1; + req->StdMessageFrame.MsgFlags = 0; + + if (sp->cmd_flags & CFLAG_DMAVALID) { + msgsize = ((sizeof (i2o_scsi_scb_execute_message_t) - + sizeof (i2o_sg_element_t) + + sizeof (i2o_sge_chain_element_t) + + sizeof (i2o_sge_ignore_element_t)) >> 2); + } else { + msgsize = ((sizeof (i2o_scsi_scb_execute_message_t) - + sizeof (i2o_sg_element_t)) >> 2); + } + + /* + * To get actual allocation msg size + */ + ASSERT(msgsize <= ddi_get16(acc_handle, + &req->StdMessageFrame.MessageSize)); + + ddi_put16(acc_handle, &req->StdMessageFrame.MessageSize, msgsize); + put_msg_TargetAddress(&req->StdMessageFrame, tid, acc_handle); + put_msg_InitiatorAddress(&req->StdMessageFrame, I2O_OSM_TID, + acc_handle); + put_msg_Function(&req->StdMessageFrame, I2O_SCSI_SCB_EXEC, acc_handle); + ddi_put32(acc_handle, + (uint32_t *)&req->StdMessageFrame.InitiatorContext, + (uint32_t)i2ohba_callback); + + /* TransactionContext */ + ddi_put32(acc_handle, &req->TransactionContext, + (uint32_t)(uintptr_t)sp); + + /* Set up CDB in the request */ + + bzero(req->CDB, I2O_SCSI_CDB_LENGTH); + if (sp->cmd_cdblen > I2O_SCSI_CDB_LENGTH) { + req->CDBLength = I2O_SCSI_CDB_LENGTH; + } else { + req->CDBLength = sp->cmd_cdblen; + } + bcopy(pkt->pkt_cdbp, req->CDB, sp->cmd_cdblen); + bcopy(pkt->pkt_cdbp, sp->cmd_cdb, sp->cmd_cdblen); + +#ifdef I2OHBA_DEBUG + if (sp->cmd_cdblen == 0x6) { + DEBUGF(1, (CE_CONT, "%d: %x %x %x %x %x %x\n", + sp->cmd_cdblen, + pkt->pkt_cdbp[0], pkt->pkt_cdbp[1], + pkt->pkt_cdbp[2], pkt->pkt_cdbp[3], + pkt->pkt_cdbp[4], pkt->pkt_cdbp[5])); + } else { + DEBUGF(1, (CE_CONT, "10: %x %x %x %x %x %x %x %x %x %x\n", + pkt->pkt_cdbp[0], pkt->pkt_cdbp[1], + pkt->pkt_cdbp[2], pkt->pkt_cdbp[3], + pkt->pkt_cdbp[4], pkt->pkt_cdbp[5], + pkt->pkt_cdbp[6], pkt->pkt_cdbp[7], + pkt->pkt_cdbp[8], pkt->pkt_cdbp[9])); + } +#endif + + DEBUGF(1, (CE_CONT, "pkt_flags = 0x%x\n", pkt->pkt_flags)); + /* Tag queuing */ + if (pkt->pkt_flags & FLAG_STAG) + flags |= I2O_SCB_FLAG_SIMPLE_QUEUE_TAG; + + else if (pkt->pkt_flags & FLAG_OTAG) + flags |= I2O_SCB_FLAG_ORDERED_QUEUE_TAG; + + else if (pkt->pkt_flags & FLAG_HTAG) + flags |= I2O_SCB_FLAG_HEAD_QUEUE_TAG; + + else if (pkt->pkt_flags & FLAG_ACA) + flags |= I2O_SCB_FLAG_ACA_QUEUE_TAG; + + if ((pkt->pkt_flags & FLAG_SENSING) || + (i2ohba->i2ohba_cap[TGT(sp)] & I2OHBA_CAP_AUTOSENSE)) + flags |= I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE; + + /* DISCONNECT enable by default especially with TAGQ */ + if (pkt->pkt_flags & FLAG_NODISCON) + flags &= ~I2O_SCB_FLAG_ENABLE_DISCONNECT; + else + flags |= I2O_SCB_FLAG_ENABLE_DISCONNECT; + + if (sp->cmd_flags & CFLAG_DMASEND) { + flags |= I2O_SCB_FLAG_XFER_TO_DEVICE; + } else { + flags |= I2O_SCB_FLAG_XFER_FROM_DEVICE; + } + + ddi_put16(acc_handle, &req->SCBFlags, flags); + DEBUGF(1, (CE_CONT, "SCBflags = 0x%x\n", flags)); + + /* + * All msg are using chain pointer. + * Setup dma transfers data segments. + */ + + sgl = (i2o_sge_chain_element_t *)&req->SGL; + sgl2 = (i2o_sge_ignore_element_t *)((caddr_t)sgl + + sizeof (i2o_sge_chain_element_t)); + if (sp->cmd_flags & CFLAG_DMAVALID) { + + if (sp->cmd_flags & CFLAG_CMDIOPB) { + (void) ddi_dma_sync(sp->cmd_dmahandle, + sp->cmd_dma_offset, sp->cmd_dma_len, + DDI_DMA_SYNC_FORDEV); + } + + ASSERT(sp->cmd_cookiecnt > 0); + + /* size of the next SGL chain elements list */ + sglen = sp->cmd_cookiecnt * sizeof (i2o_sge_chain_element_t); + + /* flags */ + put_flags_count_Flags(&sgl->FlagsCount, + I2O_SGL_FLAGS_CHAIN_POINTER_ELEMENT, acc_handle); + + /* + * instead of allocating a chuck of dma + * address here like isp driver, the + * trade of speed vs managing the free + * memory list. I don't want this + * to become kmem_alloc functions. + */ + if (ddi_dma_alloc_handle(dip, &i2ohba_dmasgl_attr, + DDI_DMA_DONTWAIT, NULL, &sp->sglbuf_dmahandle) + != DDI_SUCCESS) { + i2ohba_i_log(NULL, CE_WARN, "?i2ohba_scsi_start: " + "cannot allocate SGL's chain buffer handle"); + goto cleanup; + } + bound++; +#ifdef I2OHBA_DEBUG + ddi_dma_alloc_hdl++; +#endif + + if (ddi_dma_mem_alloc(sp->sglbuf_dmahandle, (size_t) + sglen, &dev_attr, DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, + NULL, (caddr_t *)&sp->sglbuf, &sp->sglrlen, + &sp->sglbuf_dmaacchandle) != DDI_SUCCESS) { + i2ohba_i_log(NULL, CE_WARN, "?i2ohba_scsi_start: " + "cannot allocate SGL's chain buffer memory"); + goto cleanup; + } + bound++; +#ifdef I2OHBA_DEBUG + ddi_dma_alloc_mem++; +#endif + + /* + * we passed in the sgl real length in transaction + * context because we need it to free the dma, + * but we set the chain element header with sglen + */ + put_flags_count_Count(&sgl->FlagsCount, sglen, acc_handle); + + put_flags_count_Flags(&sgl2->FlagsCount, + I2O_SGL_FLAGS_IGNORE_ELEMENT | + I2O_SGL_FLAGS_LAST_ELEMENT, acc_handle); + + put_flags_count_Count(&sgl2->FlagsCount, 0x1, acc_handle); + + /* fill in the SGL chain headers */ + sp->cmd_xfercount = 0; + cpsgl = (i2o_sge_chain_element_t *)sp->sglbuf; + + for (i = 0; i < sp->cmd_cookiecnt; i++, cpsgl++) { + + put_flags_count_Flags(&cpsgl->FlagsCount, + I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT, + sp->sglbuf_dmaacchandle); + + put_flags_count_Count(&cpsgl->FlagsCount, + sp->cmd_dmacookies[i].dmac_size, + sp->sglbuf_dmaacchandle); + + ddi_put32(sp->sglbuf_dmaacchandle, + &cpsgl->PhysicalAddress, + sp->cmd_dmacookies[i].dmac_address); + + sp->cmd_xfercount += + sp->cmd_dmacookies[i].dmac_size; + } + + DEBUGF(3, (CE_CONT, "cookiecnt is %x, ncookie is %x," + "cookie# is %d\n", sp->cmd_cookiecnt, sp->cmd_ncookies, + sp->cmd_cookie)); + DEBUGF(3, (CE_CONT, "cmd_xfercount is %lx\n", + sp->cmd_xfercount)); + + + /* mark the last chain pointer header as the last one */ + + cpsgl--; + put_flags_count_Flags(&cpsgl->FlagsCount, + I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | + I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, + sp->sglbuf_dmaacchandle); + + if (ddi_dma_addr_bind_handle(sp->sglbuf_dmahandle, NULL, + (caddr_t)sp->sglbuf, sp->sglrlen, DDI_DMA_RDWR | + DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, NULL, + &sp->sglbuf_dmacookie, &count) != DDI_DMA_MAPPED) { + i2ohba_i_log(NULL, CE_WARN, "?i2ohba_scsi_start: " + "cannot bind SGL's bind handle"); + goto cleanup; + } +#ifdef I2OHBA_DEBUG + ddi_dma_bind_hdl++; +#endif + + DEBUGF(1, (CE_CONT, "start: cmd_dmacount=%lx," + " cmd_xfercount=%lx\n", + sp->cmd_dmacount, sp->cmd_xfercount)); + + ddi_put32(acc_handle, &req->ByteCount, sp->cmd_xfercount); + + ddi_put32(acc_handle, &sgl->PhysicalAddress, + (uint32_t)sp->sglbuf_dmacookie.dmac_address); + + } else { + ddi_put32(acc_handle, &req->ByteCount, 0); + put_flags_count_Flags(&sgl->FlagsCount, 0, acc_handle); + put_flags_count_Count(&sgl->FlagsCount, 0, acc_handle); + put_flags_count_Flags(&sgl2->FlagsCount, 0, acc_handle); + put_flags_count_Count(&sgl2->FlagsCount, 0, acc_handle); + } + + /* + * calculate deadline from pkt_time + * Instead of multiplying by 100 (ie. HZ), we multiply by 128 so + * we can shift and at the same time have a 28% grace period + * we ignore the rare case of pkt_time == 0 and deal with it + * in i2ohba_i_watch() + */ + cur_lbolt = ddi_get_lbolt(); + sp->cmd_deadline = cur_lbolt + (clock_t)(pkt->pkt_time * 256); + + I2OHBA_MUTEX_ENTER(i2ohba); + (void) i2ohba_i_req_insert(i2ohba, sp); + I2OHBA_MUTEX_EXIT(i2ohba); + /* + * Start the cmd. If NO_INTR, must wait for cmd reply/completion. + */ + if ((pkt->pkt_flags & FLAG_NOINTR) == 0) { + + /* + * need a list (or some sort of queue) so that + * when we need to flash the queue, ie: SCSI_BUS_RESET + * we'll have a way to do it (link list) + */ + val = i2o_msg_send(i2ohba->i2ohba_iophdl, req, msg_handle); + if (val != DDI_SUCCESS) + rval = TRAN_BUSY; /* I/O couldnot be started */ + } else { + val = i2o_msg_send(i2ohba->i2ohba_iophdl, req, msg_handle); + /* poll command */ + if (val == DDI_SUCCESS) { + i2ohba_i_polled_cmd_start(i2ohba, sp); + } else { + rval = TRAN_BUSY; + } + } + return (rval); + +cleanup: + + if (sp) { + if (bound) { + (void) ddi_dma_unbind_handle(sp->sglbuf_dmahandle); +#ifdef I2OHBA_DEBUG + ddi_dma_unbind++; +#endif + if (bound > 1) { + ddi_dma_mem_free(&sp->sglbuf_dmaacchandle); +#ifdef I2OHBA_DEBUG + ddi_dma_free_mem++; +#endif + } + ddi_dma_free_handle(&sp->sglbuf_dmahandle); +#ifdef I2OHBA_DEBUG + ddi_dma_bind_free++; +#endif + } + + sp->cmd_flags = (sp->cmd_flags & ~CFLAG_IN_TRANSPORT); + i2ohba->i2ohba_counter--; + pkt->pkt_reason = 0; + } + + /* return MFA to IOP */ + if (req) { + req->StdMessageFrame.VersionOffset = 0; + req->StdMessageFrame.MsgFlags = 0; + ddi_put16(acc_handle, &req->StdMessageFrame.MessageSize, 3); + put_msg_TargetAddress(&req->StdMessageFrame, 0, acc_handle); + put_msg_InitiatorAddress(&req->StdMessageFrame, 0, acc_handle); + put_msg_Function(&req->StdMessageFrame, I2O_UTIL_NOP, + acc_handle); + (void) i2o_msg_send(i2ohba->i2ohba_iophdl, req, msg_handle); + } + + ASSERT(I2OHBA_MUTEX_OWNED(i2ohba) == 0 || ddi_in_panic()); + return (TRAN_BUSY); +} + + +/* + * Function name : i2ohba_i_req_insert() + * + * Return Values : void + * + * Usage : called by i2ohba_scsi_start(). + * + * Description : Insert the i2ohba_cmd into the double + * link list in FIFO fashion. + * + * Context : called by SCSA frame work. + */ +static void +i2ohba_i_req_insert(struct i2ohba *i2ohba, struct i2ohba_cmd *sp) +{ + struct i2ohba_cmd *head = i2ohba->i2ohba_reqhead; + + sp->cmd_forw = head; + if (head != NULL) { + i2ohba->i2ohba_reqhead->cmd_backw = sp; + } else { + i2ohba->i2ohba_reqtail = sp; + } + i2ohba->i2ohba_reqhead = sp; + sp->cmd_backw = NULL; + +} + + +/* + * Function name : i2ohba_i_req_remove() + * + * Return Values : void + * + * Usage : called by i2ohba_callback(). + * called by i2ohba_scsi_start() if i2o_msg_send() + * failed. + * Description : remove a i2ohba_cmd from the double link list + * + * Context : called by SCSA frame work. + */ +static void +i2ohba_i_req_remove(struct i2ohba *i2ohba, struct i2ohba_cmd *sp) +{ + struct i2ohba_cmd *tail = i2ohba->i2ohba_reqtail; + struct i2ohba_cmd *tmp; + + for (tmp = tail; tmp != NULL; tmp = tmp->cmd_backw) { + if (tmp == sp) { + if (tmp->cmd_backw) + tmp->cmd_backw->cmd_forw = tmp->cmd_forw; + else + i2ohba->i2ohba_reqhead = tmp->cmd_forw; + + if (tmp->cmd_forw) + tmp->cmd_forw->cmd_backw = tmp->cmd_backw; + else + i2ohba->i2ohba_reqtail = tmp->cmd_backw; + + tmp->cmd_backw = NULL; + tmp->cmd_forw = NULL; + break; + + } + } +} + +/* + * Function name : i2ohba_callback() + * + * Return Values : None + * + * Context: : called by interrupt thread. + */ + +void +i2ohba_callback(i2o_message_frame_t *msg, ddi_acc_handle_t acc_handle) +{ + + i2o_single_reply_message_frame_t *reply; + struct i2ohba *i2ohba; + struct scsi_pkt *pkt; + struct i2ohba_cmd *sp; + uint8_t reqstatus; + + reply = (i2o_single_reply_message_frame_t *)msg; + + + ASSERT(I2O_SCSI_SCB_EXEC == get_msg_Function( + &reply->StdMessageFrame, acc_handle)); + + sp = (struct i2ohba_cmd *)(uintptr_t)ddi_get32(acc_handle, + &reply->TransactionContext); + + ASSERT(sp); + + i2ohba = CMD2I2OHBA(sp); + I2OHBA_MUTEX_ENTER(i2ohba); + (void) i2ohba_i_req_remove(i2ohba, sp); + I2OHBA_MUTEX_EXIT(i2ohba); + + if (sp->cmd_dmahandle) { + (void) ddi_dma_sync(sp->cmd_dmahandle, + sp->cmd_dma_offset, sp->cmd_dma_len, + DDI_DMA_SYNC_FORKERNEL); + } + + reqstatus = ddi_get8(acc_handle, &reply->ReqStatus); + DEBUGF(1, (CE_CONT, "reqstatus %x\n", reqstatus)); + pkt = CMD2PKT(sp); + + /* + * First filter the reqstatus + * check for any special errors + */ + switch (reqstatus) { + + case I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER: + /* + * With paritial transfer, we want to make + * sure it is an USCSI cmd + */ + if ((pkt->pkt_flags >> 16) == 0) + pkt->pkt_reason = CMD_TRAN_ERR; + + sp->cmd_flags |= CFLAG_FINISHED; + i2ohba_i_pkt_comp(reply, acc_handle, sp); + + return; + + case I2O_REPLY_STATUS_SUCCESS: + /* + * With successful completetion, only the ReqStatus + * field is set to reflect sucessful completion, the + * DetailedStatusCode is set to zero, the TransferCount + * field indicates the actual amount of data transferred. + * There is no StatusData. + */ + + sp->cmd_flags |= CFLAG_FINISHED; + i2ohba_i_pkt_comp(reply, acc_handle, sp); + + return; + + /* XXLWXX Error code handling */ + case I2O_REPLY_STATUS_ABORT_DIRTY: + case I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER: + case I2O_REPLY_STATUS_ERROR_DIRTY: + case I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER: + case I2O_REPLY_STATUS_PROCESS_ABORT_DIRTY: + case I2O_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER: + case I2O_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER: + case I2O_REPLY_STATUS_PROGRESS_REPORT: + /* + * If message has failed due to aborted by hosts, + * error in execution, due to system command or reconfig. + * failed the request. + */ + case I2O_REPLY_STATUS_TRANSACTION_ERROR: + default: + pkt->pkt_reason = CMD_TRAN_ERR; + sp->cmd_flags |= CFLAG_FINISHED; + i2ohba_i_pkt_comp(reply, acc_handle, sp); +#ifdef I2OHBA_DEBUG + DEBUGF(1, (CE_CONT, + "?i2ohba_callback: Reply Failed")); +#endif + break; + + } +} + +/* + * Function name : i2ohba_i_pkt_complete() + * + * Return Values : none + * + * Description : + * callback into target driver + * argument is a NULL-terminated list of packets + * copy over stuff from response packet + * + * Context : Can be called by interrupt thread. + */ +static void +i2ohba_i_pkt_comp(i2o_single_reply_message_frame_t *reply, ddi_acc_handle_t + acc_handle, struct i2ohba_cmd *sp) +{ + i2o_scsi_success_reply_message_frame_t *replysuc; + i2o_scsi_error_reply_message_frame_t *replyerr; + struct i2ohba *i2ohba; + struct scsi_pkt *pkt; + uint32_t transcount; + uint32_t autocount; + uint16_t adptrstatus; + uint16_t detailstat; + uint16_t messagesize; + uint8_t devstatus; + + i2ohba = CMD2I2OHBA(sp); + ASSERT(I2OHBA_MUTEX_OWNED(i2ohba) == 0 || ddi_in_panic()); + + pkt = CMD2PKT(sp); + + ASSERT(sp->cmd_flags & CFLAG_FINISHED); + + if (sp->cmd_flags & CFLAG_DMAVALID) { + if (ddi_dma_unbind_handle(sp->sglbuf_dmahandle) != + DDI_SUCCESS) { + i2ohba_i_log(NULL, CE_WARN, "?i2ohba_scsi_dmafree: " + "ddi_dma_unbind_handle() for sglbuf failed"); + /*NOTREACHED*/ + } +#ifdef I2OHBA_DEBUG + ddi_dma_unbind++; +#endif + ddi_dma_mem_free(&sp->sglbuf_dmaacchandle); +#ifdef I2OHBA_DEBUG + ddi_dma_free_mem++; +#endif + ddi_dma_free_handle(&sp->sglbuf_dmahandle); +#ifdef I2OHBA_DEBUG + ddi_dma_bind_free++; +#endif + sp->sglbuf_dmahandle = NULL; + } + + replysuc = (i2o_scsi_success_reply_message_frame_t *)reply; + + detailstat = ddi_get16(acc_handle, &reply->DetailedStatusCode); + devstatus = (uint8_t)(detailstat & I2O_SCSI_DEVICE_DSC_MASK); + /* this is a workaround for 0x3 and 0x9 LSB is being ORed */ + devstatus = devstatus & 0xfe; + DEBUGF(1, (CE_CONT, "devstatus %x\n", devstatus)); + adptrstatus = detailstat & I2O_SCSI_HBA_DSC_MASK; + DEBUGF(1, (CE_CONT, "adptrstatus %x\n", adptrstatus)); + + transcount = ddi_get32(acc_handle, &replysuc->TransferCount); + + if (detailstat == 0) { + pkt->pkt_scbp[0] = + (uint8_t)(detailstat & I2O_SCSI_DEVICE_DSC_MASK); + pkt->pkt_reason = CMD_CMPLT; + pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET | + STATE_SENT_CMD | STATE_XFERRED_DATA; + pkt->pkt_statistics = 0; + pkt->pkt_resid = sp->cmd_xfercount - transcount; + } else { + replyerr = (i2o_scsi_error_reply_message_frame_t *)reply; + + /* + * devstatus: SCSI_SUCESS 0, SCSI_CHECK_COND 2, + * SCSI_BUSY 8, SCSI_RES_CONFLICT 18, + * SCSI_CMD_TERM 22, SCSI_TASK_SET_FULL 28, + * SCSI_ACA_ACTIVE 30 + */ + messagesize = ddi_get16(acc_handle, + &replyerr->StdReplyFrame.StdMessageFrame.MessageSize); + + pkt->pkt_scbp[0] = devstatus; + + if (devstatus == I2O_SCSI_DSC_CHECK_CONDITION) { + pkt->pkt_reason = CMD_CMPLT; + pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET | + STATE_SENT_CMD | STATE_XFERRED_DATA; + pkt->pkt_statistics = 0; + goto arqchk; + } + + /* SYM HDM problem, can't recognized USCSI cmd well */ + if ((devstatus == I2O_SCSI_DSC_BUSY) && + (transcount != 0) && ((pkt->pkt_flags >> 16) != 0)) { + pkt->pkt_reason = CMD_CMPLT; + pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET | + STATE_SENT_CMD | STATE_XFERRED_DATA; + pkt->pkt_statistics = 0; + pkt->pkt_resid = sp->cmd_xfercount - transcount; + pkt->pkt_scbp[0] = STATUS_GOOD; + goto done; + } + + + switch (adptrstatus) { + + case I2O_SCSI_HBA_DSC_AUTOSENSE_FAILED: + pkt->pkt_reason = CMD_INCOMPLETE; + pkt->pkt_state |= STATE_ARQ_DONE; + break; + + /* bus reset */ + case I2O_SCSI_HBA_DSC_SCSI_BUS_RESET: + pkt->pkt_reason = CMD_RESET; + pkt->pkt_statistics |= STAT_BUS_RESET; + /* Do we need to call notify_callback? */ + scsi_hba_reset_notify_callback( + I2OHBA_REQ_MUTEX(i2ohba), + &i2ohba->i2ohba_reset_notify_listf); + break; + + /* cmd terminated */ + case I2O_SCSI_HBA_DSC_REQUEST_TERMINATED: + pkt->pkt_reason = CMD_TERMINATED; + + pkt->pkt_statistics |= STAT_TERMINATED; + break; + + /* request aborted */ + case I2O_SCSI_HBA_DSC_NO_NEXUS: + pkt->pkt_reason = CMD_ABORTED; + pkt->pkt_statistics |= STAT_ABORTED; + break; + + /* parity error */ + case I2O_SCSI_HBA_DSC_PARITY_ERROR_FAILURE: + pkt->pkt_reason = CMD_TRAN_ERR; + pkt->pkt_statistics |= STAT_PERR; + i2ohba_i_log(NULL, CE_WARN, "?Parity Error"); + break; + + /* data overrun */ + case I2O_SCSI_HBA_DSC_DATA_OVERRUN: + pkt->pkt_reason = CMD_DATA_OVR; + pkt->pkt_state |= STATE_GOT_BUS | + STATE_GOT_TARGET | STATE_SENT_CMD | + STATE_XFERRED_DATA; + break; + + /* cmd complete with error */ + case I2O_SCSI_HBA_DSC_LUN_ALREADY_ENABLED: + case I2O_SCSI_HBA_DSC_COMPLETE_WITH_ERROR: + /* devstatus should be busy/checkcond */ + pkt->pkt_reason = CMD_CMPLT; + break; + + /* cmd aborted by request or aborted by time */ + case I2O_SCSI_HBA_DSC_REQUEST_ABORTED: + if (sp->cmd_flags & CFLAG_DELAY_TIMEOUT) { + pkt->pkt_reason = CMD_TIMEOUT; + pkt->pkt_statistics |= STAT_TIMEOUT + | STAT_ABORTED; + } else { + pkt->pkt_reason = CMD_ABORTED; + pkt->pkt_statistics |= STAT_ABORTED; + } + break; + + /* cmd timeout */ + case I2O_SCSI_HBA_DSC_COMMAND_TIMEOUT: + pkt->pkt_reason = CMD_TIMEOUT; + pkt->pkt_statistics |= STAT_TIMEOUT; + break; + + /* CDB received */ + case I2O_SCSI_HBA_DSC_CDB_RECEIVED: + pkt->pkt_reason = CMD_INCOMPLETE; + pkt->pkt_state |= STATE_SENT_CMD | + STATE_GOT_BUS | STATE_GOT_TARGET | + STATE_XFERRED_DATA; + break; + + /* device reset msg send */ + case I2O_SCSI_HBA_DSC_BDR_MESSAGE_SENT: + pkt->pkt_reason = CMD_RESET; + pkt->pkt_statistics |= STAT_DEV_RESET; + break; + + /* unexpected bus free */ + case I2O_SCSI_HBA_DSC_UNEXPECTED_BUS_FREE: + pkt->pkt_reason = CMD_UNX_BUS_FREE; + break; + + /* cmd failed, transport error */ + case I2O_SCSI_HBA_DSC_ADAPTER_BUSY: + case I2O_SCSI_HBA_DSC_SEQUENCE_FAILURE: + case I2O_SCSI_HBA_DSC_BUS_BUSY: + case I2O_SCSI_HBA_DSC_QUEUE_FROZEN: + case I2O_SCSI_HBA_DSC_UNABLE_TO_ABORT: + case I2O_SCSI_HBA_DSC_UNABLE_TO_TERMINATE: + case I2O_SCSI_HBA_DSC_RESOURCE_UNAVAILABLE: + pkt->pkt_reason = CMD_TRAN_ERR; + break; + + /* failed command, retry? */ + case I2O_SCSI_HBA_DSC_REQUEST_INVALID: + case I2O_SCSI_HBA_DSC_PATH_INVALID: + case I2O_SCSI_HBA_DSC_INVALID_CDB: + case I2O_SCSI_HBA_DSC_LUN_INVALID: + case I2O_SCSI_HBA_DSC_SELECTION_TIMEOUT: + pkt->pkt_state |= STATE_GOT_BUS; + pkt->pkt_reason = CMD_INCOMPLETE; + break; + + case I2O_SCSI_HBA_DSC_DEVICE_NOT_PRESENT: + case I2O_SCSI_HBA_DSC_FUNCTION_UNAVAILABLE: + pkt->pkt_reason = CMD_INCOMPLETE; + break; + + /* what? NO adapter! shutdown now! */ + case I2O_SCSI_HBA_DSC_NO_ADAPTER: + i2ohba->i2ohba_shutdown = 1; + break; + + case I2O_SCSI_HBA_DSC_SCSI_TID_INVALID: + case I2O_SCSI_HBA_DSC_SCSI_IID_INVALID: + default: /* failed cmd, retry */ + pkt->pkt_state |= STATE_GOT_BUS; + pkt->pkt_reason = CMD_TRAN_ERR; + break; + + + } + + pkt->pkt_resid = sp->cmd_xfercount; + + /* + * was there auto request sense info? + */ +arqchk: if (messagesize > + sizeof (i2o_scsi_success_reply_message_frame_t)) { + autocount = ddi_get32(acc_handle, + &replyerr->AutoSenseTransferCount); + + /* currently uses the DATA_IN_MESSAGE, only 40 bytes */ + if (autocount) { + pkt->pkt_state |= STATE_ARQ_DONE; + i2ohba_i_handle_arq(replyerr, sp, autocount); + } + } + + } + + +done: DEBUGF(1, (CE_CONT, "transfer=0x%x, resid=0x%lx\n", transcount, + pkt->pkt_resid)); + + /* + * if data was xferred and this was an IOPB, we need + * to do a dma sync + */ + if ((sp->cmd_flags & CFLAG_CMDIOPB) && + (pkt->pkt_state & STATE_XFERRED_DATA)) { + (void) ddi_dma_sync(sp->cmd_dmahandle, + sp->cmd_dma_offset, sp->cmd_dma_len, + DDI_DMA_SYNC_FORCPU); + } + + + ASSERT(sp->cmd_flags & CFLAG_IN_TRANSPORT); + ASSERT(sp->cmd_flags & CFLAG_FINISHED); + ASSERT((sp->cmd_flags & CFLAG_COMPLETED) == 0); + + sp->cmd_flags = ((sp->cmd_flags & ~CFLAG_IN_TRANSPORT) & + ~CFLAG_DELAY_TIMEOUT) | CFLAG_COMPLETED; + i2ohba->i2ohba_counter--; + + /* + * Call packet completion routine if FLAG_NOINTR is not set. + * If FLAG_NOINTR is set turning on CFLAG_COMPLETED in line + * above will cause busy wait loop in + * i2ohba_i_polled_cmd_start() to exit. + */ + if (((pkt->pkt_flags & FLAG_NOINTR) == 0) && + pkt->pkt_comp) { + (*pkt->pkt_comp)(pkt); + } + + ASSERT(I2OHBA_MUTEX_OWNED(i2ohba) == 0 || ddi_in_panic()); +} + + +/* + * Function name : i2ohba_i_handle_arq() + * + * Description : called on an autorequest sense condition, sets up arqstat + * + * Context : Can be called from different kernel process threads. + * Can be called by interrupt thread. + */ +static void +i2ohba_i_handle_arq(i2o_scsi_error_reply_message_frame_t *replyerr, + struct i2ohba_cmd *sp, int aqcount) +{ + char status; + struct scsi_pkt *pkt = CMD2PKT(sp); + + if (sp->cmd_scblen >= sizeof (struct scsi_arq_status)) { + struct scsi_arq_status *arqstat; + + DEBUGF(1, (CE_CONT, "tgt %d.%d: auto request sense", + TGT(sp), LUN(sp))); + + /* clear the pkt_scbp struct */ + arqstat = (struct scsi_arq_status *)(pkt->pkt_scbp); + status = pkt->pkt_scbp[0]; + bzero(arqstat, sizeof (struct scsi_arq_status)); + + /* + * I2O does not provide statistics for request sense, + * so use same statistics as the original cmd. + */ + arqstat->sts_rqpkt_statistics = pkt->pkt_statistics; + arqstat->sts_rqpkt_state = + (STATE_GOT_BUS | STATE_GOT_TARGET | + STATE_SENT_CMD | STATE_XFERRED_DATA | STATE_GOT_STATUS); + if (aqcount < sizeof (struct scsi_extended_sense)) { + arqstat->sts_rqpkt_resid = + sizeof (struct scsi_extended_sense) - aqcount; + + } + bcopy(replyerr->SenseData, + &arqstat->sts_sensedata, + (sizeof (struct scsi_extended_sense) < + I2O_SCSI_SENSE_DATA_SZ) ? + sizeof (struct scsi_extended_sense) : + I2O_SCSI_SENSE_DATA_SZ); + + /* + * restore status which was wiped out by bzero + */ + pkt->pkt_scbp[0] = status; + + DEBUGF(1, (CE_CONT, "arq: %x %x %x %x %x %x %x", + replyerr->SenseData[0], replyerr->SenseData[1], + replyerr->SenseData[2], replyerr->SenseData[3], + replyerr->SenseData[4], replyerr->SenseData[5], + replyerr->SenseData[6])); + return; + } + /* + * Failed cmd auto sense data; can't copy over ARQ data, + */ + DEBUGF(1, (CE_CONT, "Failed cmd, possible sense data")); + DEBUGF(1, (CE_CONT, "arq: %x %x %x %x %x %x %x", + replyerr->SenseData[0], replyerr->SenseData[1], + replyerr->SenseData[2], replyerr->SenseData[3], + replyerr->SenseData[4], replyerr->SenseData[5], + replyerr->SenseData[6])); +} + + +/* + * Function name : i2ohba_i_polled_cmd_start() + * + * Return Values : TRAN_ACCEPT if transaction was accepted + * TRAN_BUSY if I/O could not be started + * TRAN_ACCEPT if I/O timed out, pkt fields indicate error + * + * Description : Busy waits for I/O to complete or timeout. + * NOTE: This function returns void because the cmd + * has already started in scsi_start() before this + * function is called. So no need to return rval. + * + * Context : Can be called from different kernel process threads. + * Can be called by interrupt thread. + */ +static void +i2ohba_i_polled_cmd_start(struct i2ohba *i2ohba, struct i2ohba_cmd *sp) +{ + int delay_loops; + struct scsi_pkt *pkt = CMD2PKT(sp); + + ASSERT(I2OHBA_MUTEX_OWNED(i2ohba) == 0 || ddi_in_panic()); + + /* + * set timeout to SCSI_POLL_TIMEOUT for non-polling + * commands that do not have this field set + */ + if (pkt->pkt_time == 0) { + pkt->pkt_time = SCSI_POLL_TIMEOUT; + } + + ASSERT(pkt->pkt_flags & FLAG_NOINTR); + + delay_loops = I2OHBA_TIMEOUT_DELAY( + (pkt->pkt_time + (2 * I2OHBA_GRACE)), + I2OHBA_NOINTR_POLL_DELAY_TIME); + + /* + * busy wait for command to finish + * ie. till CFLAG_COMPLETED is set + */ + while ((sp->cmd_flags & CFLAG_COMPLETED) == 0) { + drv_usecwait(I2OHBA_NOINTR_POLL_DELAY_TIME); + if (--delay_loops <= 0) { + + if ((i2ohba_scsi_reset(&pkt->pkt_address, + RESET_TARGET)) == 0) { + mutex_enter(I2OHBA_REQ_MUTEX(i2ohba)); + i2ohba_i_fatal_error(i2ohba); + mutex_exit(I2OHBA_REQ_MUTEX(i2ohba)); + } + pkt->pkt_reason = CMD_TIMEOUT; + pkt->pkt_statistics |= STAT_BUS_RESET | + STAT_TIMEOUT; + sp->cmd_flags = ((sp->cmd_flags & + ~CFLAG_IN_TRANSPORT) & ~CFLAG_DELAY_TIMEOUT) + | CFLAG_COMPLETED | CFLAG_FINISHED; + i2ohba->i2ohba_counter--; + break; + } + } + + ASSERT(I2OHBA_MUTEX_OWNED(i2ohba) == 0 || ddi_in_panic()); + +} + + + +/* + * Function name : i2ohba_i_watch() + * + * Return Values : none + * Description : I2OHBA deadman timer routine. + * + * Given that the i2ohba's request queue is double link list + * in FIFO fashion, the tail should be pointing at the oldest + * cmd. However, each command has different timeout value set + * by the target driver, if any of them has timeout then we + * will call fatal_error(). + * + * A hung i2ohba controller is detected by failure to complete + * cmds within a timeout interval (including grace period for + * i2ohba error recovery). All target error recovery is handled + * directly by the i2ohba. + * + * If i2ohba hungs, restart by resetting the i2ohba's HBA/BUS and + * flushing the double linked list (via i2ohba_i_qflush()). + * + * Tagged queueing gives us other headaches since we cannot know + * exactly when a command starts. For example, a command with a + * 2-hour timeout, will cause a second command with a 60-second timeout + * to be timed-out. We won't worry about it now, but will later + * + * Context : Can be called by timeout thread. + */ + +static void +i2ohba_i_watch(void *arg) +{ + struct i2ohba *i2ohba = (struct i2ohba *)arg; + clock_t cur_lbolt; + clock_t deadline; + struct i2ohba_cmd *sp; + struct scsi_pkt *pkt; + + + if (i2ohba->i2ohba_shutdown) { + return; + } + + I2OHBA_MUTEX_ENTER(i2ohba); + + if ((cur_lbolt = ddi_get_lbolt()) != 0) { + for (sp = i2ohba->i2ohba_reqtail; sp != NULL; + sp = sp->cmd_backw) { + pkt = CMD2PKT(sp); + deadline = sp->cmd_deadline; + if ((deadline - cur_lbolt <= 0) && (pkt->pkt_time)) { + if (!(sp->cmd_flags & CFLAG_DELAY_TIMEOUT)) { + /* report time out */ + i2ohba_i_log(NULL, CE_CONT, + "?i2ohba_i_watch: " + "Exend cmd timeout on target %d.%d", + TGT(sp), LUN(sp)); + /* reset timeout vaule for delay */ + sp->cmd_deadline = cur_lbolt + + (clock_t)(pkt->pkt_time * 192); + /* set DELAY_TIMEOUT indicator */ + sp->cmd_flags |= CFLAG_DELAY_TIMEOUT; + /* set throttle on */ + i2ohba->i2ohba_throttle++; + } else { + i2ohba_i_req_remove(i2ohba, sp); + pkt->pkt_reason = CMD_TIMEOUT; + pkt->pkt_statistics |= STAT_TIMEOUT; + sp->cmd_flags = ((sp->cmd_flags + & ~CFLAG_DELAY_TIMEOUT) + & ~CFLAG_IN_TRANSPORT) + | CFLAG_COMPLETED | CFLAG_FINISHED; + i2ohba_i_log(NULL, CE_WARN, + "?i2ohba_i_watch: " + "Cmd timeout on target %d.%d", + TGT(sp), LUN(sp)); + I2OHBA_MUTEX_EXIT(i2ohba); + if (((pkt->pkt_flags & FLAG_NOINTR) + == 0) && pkt->pkt_comp) { + (*pkt->pkt_comp)(pkt); + } + I2OHBA_MUTEX_ENTER(i2ohba); + } + } + } + + DEBUGF(2, (CE_CONT, "?throttle=%d", i2ohba->i2ohba_throttle)); + if ((i2ohba->i2ohba_reqtail == NULL) && + (i2ohba->i2ohba_reqhead == NULL)) { + i2ohba->i2ohba_throttle = 0; + } + + } + + if (i2ohba->i2ohba_need_prop_update) { + int i; + + for (i = 0; i < N_I2OHBA_TARGETS_WIDE; i++) { + if (i2ohba->i2ohba_need_prop_update & (1 << i)) { + i2ohba_i_update_props(i2ohba, i); + } + } + + i2ohba->i2ohba_need_prop_update = 0; + + } + + /* + * Set up next timeout + */ + i2ohba->i2ohba_timeout_id = timeout(i2ohba_i_watch, i2ohba, + i2ohba_tick); + I2OHBA_MUTEX_EXIT(i2ohba); +} + + + +/* + * Function name : i2ohba_i_fatal_error() + * + * Return Values : none + * + * Description : + * Isp fatal error recovery: + * Reset the i2o and flush the active queues and attempt restart. + * This should only happen in case of a firmware bug or hardware + * death. Flushing is from backup queue as I2O cannot be trusted. + * + * Context : Can be called from different kernel process threads. + * Can be called by interrupt thread. + * i2ohba_request_mutex is held. + */ +static void +i2ohba_i_fatal_error(struct i2ohba *i2ohba) +{ + /* + * hold off starting new requests by grabbing the request mutex + */ + ASSERT(I2OHBA_MUTEX_OWNED(i2ohba)); + + /* + * If shutdown flag is set than no need to do + * fatal error recovery. + */ + if (i2ohba->i2ohba_shutdown) { + return; + } + + i2ohba_i_log(NULL, CE_WARN, "?i2ohba_i_fatal_error: " + "Fatal error, resetting interface"); + + i2ohba_i_print_state(i2ohba); + + (void) i2ohba_i_reset_interface(i2ohba, I2OHBA_FORCE_BUS_RESET); + + i2ohba_i_qflush(i2ohba, (uint16_t)0, (uint16_t)N_I2OHBA_TARGETS_WIDE); + + (void) scsi_hba_reset_notify_callback(I2OHBA_REQ_MUTEX(i2ohba), + &i2ohba->i2ohba_reset_notify_listf); + + ASSERT(I2OHBA_MUTEX_OWNED(i2ohba)); +} + + +/* + * Function name : i2ohba_i_qflush() + * + * Return Values : none + * Description : + * Flush i2ohba queues over range specified + * from start_tgt to end_tgt. Flushing goes from oldest to newest + * to preserve some cmd ordering. + * This is used for i2o crash recovery as normally i2o takes + * care of target or bus problems. + * + * Context : Can be called from different kernel process threads. + * i2ohba_i_fatal_error() + * i2ohba_i_reset_interface() + * Can be called by interrupt thread. + */ +static void +i2ohba_i_qflush(struct i2ohba *i2ohba, uint16_t start_tgt, uint16_t end_tgt) +{ + struct i2ohba_cmd *sp; + struct scsi_pkt *pkt; + + ASSERT(start_tgt <= end_tgt); + ASSERT(I2OHBA_MUTEX_OWNED(i2ohba)); + + + /* + * If flushing active queue, start with current free slot + * ie. oldest request, to preserve some order. + */ + sp = i2ohba->i2ohba_reqtail; + for (; sp != NULL; sp = i2ohba->i2ohba_reqtail->cmd_backw) { + if ((TGT(sp) >= start_tgt) && (TGT(sp) <= end_tgt)) { + + pkt = CMD2PKT(sp); + pkt->pkt_reason = CMD_RESET; + pkt->pkt_statistics |= STAT_DEV_RESET; + (void) i2ohba_i_req_remove(i2ohba, sp); + sp->cmd_flags |= CFLAG_FINISHED; + sp->cmd_flags = ((sp->cmd_flags & ~CFLAG_IN_TRANSPORT) + & ~CFLAG_DELAY_TIMEOUT) | CFLAG_COMPLETED; + i2ohba->i2ohba_counter--; + if (((pkt->pkt_flags & FLAG_NOINTR) == 0) && + pkt->pkt_comp) { + (*pkt->pkt_comp)(pkt); + } + + } + } + + ASSERT(I2OHBA_MUTEX_OWNED(i2ohba)); +} + + +/* + * Function name : i2ohba_scsi_abort() + * + * Return Values : 0 - abort failed + * 1 - abort succeeded + * Description : + * SCSA interface routine to abort pkt(s) in progress. + * Abort the pkt specified or NULL pkt, abort ALL pkts. + * + * Context : Can be called from different kernel process threads. + * Can be called by interrupt thread. + */ +static int +i2ohba_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt) +{ + struct i2ohba *i2ohba = ADDR2I2OHBA(ap); + struct i2ohba_cmd *sp = PKT2CMD(pkt); + uint16_t arg, tid; + int rval = 0; + + ASSERT(mutex_owned(I2OHBA_REQ_MUTEX(i2ohba)) == 0 || ddi_in_panic()); + + arg = (uint16_t)ap->a_target; + + if (i2ohba->i2ohba_tgt_id_map[arg] == NULL) + return (rval); + + tid = i2ohba->i2ohba_tgt_id_map[arg]->tid; + + /* + * hold off new requests, we need the req mutex anyway so noone + * can access the queue. + */ + I2OHBA_MUTEX_ENTER(i2ohba); + + i2ohba_i_log(NULL, CE_CONT, "?i2ohba_scsi_abort: " + "aborting pkt 0x%p", (void *)pkt); + + + if (pkt) { + if (i2ohba_i_reset_abort(i2ohba, tid, I2O_SCSI_SCB_ABORT, sp)) { + I2OHBA_MUTEX_EXIT(i2ohba); + return (0); + } + } else { + if (i2ohba_i_reset_abort(i2ohba, tid, I2O_SCSI_SCB_ABORT, 0)) { + I2OHBA_MUTEX_EXIT(i2ohba); + return (0); + } + } + + I2OHBA_MUTEX_EXIT(i2ohba); + return (1); +} + + +/* + * Function name : i2ohba_scsi_reset() + * + * Return Values : 0 - reset failed + * 1 - reset succeeded + * Description : + * SCSA interface routine to perform scsi resets on either + * a specified target or the bus (default). + * + * Context : Can be called from different kernel process threads. + * Can be called by interrupt thread. + */ +static int +i2ohba_scsi_reset(struct scsi_address *ap, int level) +{ + struct i2ohba *i2ohba = ADDR2I2OHBA(ap); + uint16_t arg, tid; + int rval = 0; + + ASSERT(mutex_owned(I2OHBA_REQ_MUTEX(i2ohba)) == 0 || ddi_in_panic()); + + arg = (uint16_t)ap->a_target; + + if (i2ohba->i2ohba_tgt_id_map[arg] == NULL) + return (rval); + + tid = i2ohba->i2ohba_tgt_id_map[arg]->tid; + + I2OHBA_MUTEX_ENTER(i2ohba); + /* + * hold off new requests, we need the req mutex. + */ + + if (level == RESET_TARGET) { + i2ohba_i_log(NULL, CE_CONT, + "?i2ohba_scsi_reset: reset target %d", ap->a_target); + + if (i2ohba_i_reset_abort(i2ohba, tid, + I2O_SCSI_DEVICE_RESET, 0)) { + return (rval); + } + } else { + i2ohba_i_log(NULL, CE_CONT, "?i2ohba_scsi_reset: reset bus"); + + tid = i2ohba->i2ohba_tid; + if (i2ohba_i_reset_abort(i2ohba, tid, I2O_HBA_BUS_RESET, 0)) { + return (rval); + } + (void) scsi_hba_reset_notify_callback( + I2OHBA_REQ_MUTEX(i2ohba), + &i2ohba->i2ohba_reset_notify_listf); + /* wait for 3 sec after a reset */ + drv_usecwait((clock_t)i2ohba->i2ohba_scsi_reset_delay * 1000); + } + I2OHBA_MUTEX_EXIT(i2ohba); + return (1); +} + +/* + * Function name: i2ohba_i_reset_abort() + * + * Return Values: 0 - success + * -1 - fail reset + * + * Description : + * Reset either the HBA Adpter or Bus Reset + * This function is called from i2ohba_i_reset_interface() + * i2ohba_scsi_abort() + * i2ohba_scsi_reset() + * + * Context : Can be called from different kernel process threads. + * Can not be called by interrupt thread because it + * waits on the reply message. + */ +static int +i2ohba_i_reset_abort(struct i2ohba *i2ohba, uint16_t tid, int action, + struct i2ohba_cmd *cmd) +{ + int rval = -1; + i2o_message_frame_t *msgptr; + i2o_scsi_scb_abort_message_t *abortmsg; + i2o_msg_handle_t msg_handle; + ddi_acc_handle_t acc_handle; + struct i2ohba_util *sp; + + if (i2o_msg_alloc(i2ohba->i2ohba_iophdl, I2O_MSG_SLEEP, NULL, + (void *)&msgptr, &msg_handle, &acc_handle) != DDI_SUCCESS) { + i2ohba_i_log(NULL, CE_WARN, "?i2ohba_i_reset_abort: " + "i2o_msg_alloc failed"); + return (rval); + } + + if ((action == I2O_SCSI_SCB_ABORT) && (cmd == NULL)) + action = I2O_SCSI_DEVICE_RESET; + + abortmsg = (i2o_scsi_scb_abort_message_t *)msgptr; + /* + * construct a i2o_hba_bus_reset_message + */ + abortmsg->StdMessageFrame.VersionOffset = 0x01; + abortmsg->StdMessageFrame.MsgFlags = 0; + if (action == I2O_SCSI_SCB_ABORT) + ddi_put16(acc_handle, &abortmsg->StdMessageFrame.MessageSize, + sizeof (i2o_scsi_scb_abort_message_t) >> 2); + else + ddi_put16(acc_handle, &abortmsg->StdMessageFrame.MessageSize, + sizeof (i2o_scsi_device_reset_message_t) >> 2); + put_msg_TargetAddress(&abortmsg->StdMessageFrame, tid, acc_handle); + put_msg_InitiatorAddress(&abortmsg->StdMessageFrame, I2O_OSM_TID, + acc_handle); + put_msg_Function(&abortmsg->StdMessageFrame, action, acc_handle); + ddi_put32(acc_handle, + (uint32_t *)&abortmsg->StdMessageFrame.InitiatorContext, + (uint32_t)i2ohba_utilmsg_comp); + + /* + * allocating synchronized status buffer + */ + sp = kmem_alloc(sizeof (struct i2ohba_util), KM_SLEEP); + + ddi_put32(acc_handle, &abortmsg->TransactionContext, + (uint32_t)(uintptr_t)sp); + + if (cmd) + ddi_put32(acc_handle, &abortmsg->TransactionContextToAbort, + (uint32_t)(uintptr_t)cmd); + + /* + * initialized a mutex and cond variable to + * send message to IOP, and wait for it to signal back + */ + sp->mutex = I2OHBA_RESET_MUTEX(i2ohba); + sp->cv = I2OHBA_RESET_CV(i2ohba); + mutex_enter(sp->mutex); + sp->wakeup = UTIL_MSG_SLEEP; + sp->status = 0; + (void) i2o_msg_send(i2ohba->i2ohba_iophdl, msgptr, msg_handle); + while (!sp->wakeup) + cv_wait(sp->cv, sp->mutex); + mutex_exit(sp->mutex); + + /* + * process reply message + */ + + switch (sp->status) { + case I2O_REPLY_STATUS_SUCCESS: + rval = 0; + break; + default: + /* + * Failed the reset for now, + * we can also parse the AdapterStatus + * and retry if needed + */ + break; + } + +cleanup: + if (sp) + kmem_free(sp, sizeof (struct i2ohba_util)); + + return (rval); +} + + +/* + * Function name : i2ohba_i_reset_interface() + * + * Return Values : 0 - success + * -1 - hw failure + * + * Description : + * Master reset routine for hardware/software. Resets softc struct, + * i2ohba; and scsi bus and the scsi adapter. The works! + * This function is called from i2ohba_attach with no mutexes held or + * from i2ohba_i_fatal_error with request mutex held + * + * NOTE: it is up to the caller to flush the response queue + * + * Context : Can be called from different kernel process threads. + * i2ohba_attach() - single thread, no mutex held + * i2ohba_i_fatal_error() + * Can be called by interrupt thread. + */ +static int +i2ohba_i_reset_interface(struct i2ohba *i2ohba, int action) +{ + int i; + int rval = -1; + + /* + * Handle reset recovery; reset the bus before we reset the + * adapter chip + */ + /* + * send command Bus Reset + */ + DEBUGF(1, (CE_CONT, "Resetting i2o SCSI BUS")); + + if (action == I2OHBA_FORCE_BUS_RESET) { + if (i2ohba_i_reset_abort(i2ohba, i2ohba->i2ohba_tid, + I2O_HBA_BUS_RESET, 0)) { + i2ohba_i_log(NULL, CE_WARN, + "?i2ohba_i_reset_interface: bus reset failed"); + goto cleanup; + } + (void) scsi_hba_reset_notify_callback( + I2OHBA_REQ_MUTEX(i2ohba), + &i2ohba->i2ohba_reset_notify_listf); + drv_usecwait((clock_t)i2ohba->i2ohba_scsi_reset_delay * 1000); + } + + /* + * Handle resetting i2o host adapter. + */ + DEBUGF(1, (CE_CONT, "Resetting i2o SCSI Host Adapter")); + + /* + * Reset the i2o host adapter. + */ + if (i2ohba_i_reset_abort(i2ohba, i2ohba->i2ohba_tid, + I2O_HBA_ADAPTER_RESET, 0)) { + i2ohba_i_log(NULL, CE_WARN, "?i2ohba_i_reset_interface: " + "adapter reset failed"); + goto cleanup; + } + drv_usecwait((clock_t)i2ohba->i2ohba_scsi_reset_delay * 1000); + + + /* + * set Initiator SCSI ID using utilparamset + */ + +/* + * DEBUGF(1, (CE_CONT, "Initializing SCSI HBA ID")); + * + * i = i2ohba->i2ohba_initiator_id; + * if (i2ohba_utilparamset_msg(i2ohba, 7, i2ohba->i2ohba_tid, + * I2O_HBA_SCSI_CONTROLLER_INFO_GROUP_NO, 0x4, i) != 0) { + * i2ohba_i_log(NULL, CE_WARN, "?i2ohba_i_reset_interface: " + * "resetting initiator id failed"); + * goto cleanup; + * } + * + */ + + /* + * Update sync/offset from i2ohba utilparmas to + * global per target sync area. + */ + DEBUGF(1, (CE_CONT, "Initializing i2ohba capabilities")); + + for (i = 0; i < N_I2OHBA_TARGETS_WIDE; i++) { + (void) i2ohba_i_updatesync(i2ohba, i); + } + rval = 0; + +cleanup: + if (rval) { + DEBUGF(1, (CE_WARN, "reset interface failed")); + i2ohba->i2ohba_shutdown = 1; + DEBUGF(1, (CE_WARN, "interface going offline")); + i2ohba_i_qflush(i2ohba, (uint16_t)0, + (uint16_t)N_I2OHBA_TARGETS_WIDE); + } + + return (rval); +} + + + +static void +i2ohba_i_print_state(struct i2ohba *i2ohba) +{ + char buf[128]; + int i; + + + /* + * Print out sync scsi info and suppress trailing zero + * period and offset entries. + */ + if (i2ohba->i2ohba_scsi_options & SCSI_OPTIONS_SYNC) { + (void) sprintf(buf, "period/offset:"); + for (i = 0; i < N_I2OHBA_TARGETS; i++) { + (void) sprintf(&buf[strlen(buf)], " %d/%d", + i2ohba->i2ohba_synch[i], i2ohba->i2ohba_offset[i]); + } + DEBUGF(1, (CE_CONT, buf)); + (void) sprintf(buf, "period/offset:"); + for (i = N_I2OHBA_TARGETS; i < N_I2OHBA_TARGETS_WIDE; i++) { + (void) sprintf(&buf[strlen(buf)], " %d/%d", + i2ohba->i2ohba_synch[i], i2ohba->i2ohba_offset[i]); + } + DEBUGF(1, (CE_CONT, buf)); + } +} + +/* + * Function name: i2ohba_utilparamset_msg() + * + * Return Values: 0 - success + * -1 - set prarmeter failed + * Description : common UtilParamSet function. + * However, only one param at a time. Pass in + * the Tid, GroupNumber, and the FieldIdx, and + * value, then compose the Message frame, + * then send it off through i2o_message_send(). + * + * Message Format: + * + * Building a param_set message requires: + * Buffer#1 SGL-immediate data (Request) + * 1. i2o_param_operations_list_header_t(1W) + * u16 OperationCount (1) + * u16 Reserved + * 2. i2o_param_operation_specific_template_t(2W) + * u16 Operation (FIELD_SET) + * u16 GroupNumber (group) + * u16 FieldCount 0x1 + * u16 FieldIdx (idx) + * u16 value of idx + * + * Buffer#2 SGL-Simple addressing (Reply) + * 1. i2o_param_results_list_header_t(1W) + * u16 ResultCount + * u16 Reserved + * 2. i2o_param_modify_operation_result_t(9W) + * u16 BlockSize + * u8 BlockStatus + * u8 ErrorInfoSize + * ... ErrorInformation + * + * + * Context : Can be called from i2ohba_i_reset_interface() + * Can be called from i2ohba_i_updatecap() or + * i2ohba_scsi_setcap() + */ + + +static int +i2ohba_utilparamset_msg(struct i2ohba *i2ohba, int tgt, uint16_t tid, + uint16_t group, uint16_t idx, uint16_t value) +{ + + i2o_setparam_t *msgptr; + i2o_msg_handle_t msg_handle; + ddi_acc_handle_t acc_handle; + struct i2ohba_util *sp = NULL; + uint_t count; + int rval = -1; + int bound = 0; + uint16_t allocmsgsize; + + + /* + * allocate a message frame + */ + if (i2o_msg_alloc(i2ohba->i2ohba_iophdl, I2O_MSG_SLEEP, + NULL, (void *)&msgptr, &msg_handle, &acc_handle) + != DDI_SUCCESS) { + i2ohba_i_log(NULL, CE_WARN, "?i2ohba_utilparamset_msg: " + "i2o_msg_alloc failed"); + return (rval); + } + + /* + * To get the actual allocation msg size + */ + allocmsgsize = (ddi_get16(acc_handle, &msgptr->MessageSize) << 2); + + if (allocmsgsize < sizeof (i2o_setparam_t)) { + i2ohba_i_log(NULL, CE_WARN, "?i2ohba_utilparamset_msg: " + "msg size alloc is smaller than what setparam needed"); + goto fail; + } + + /* + * Construct a utilparamset message + */ + msgptr->VersionOffset = ContextSize32; + msgptr->MsgFlags = 0; + ddi_put16(acc_handle, &msgptr->MessageSize, + (sizeof (i2o_setparam_t) >> 2)); + put_msg_TargetAddress(msgptr, tid, acc_handle); + put_msg_InitiatorAddress(msgptr, I2O_OSM_TID, acc_handle); + put_msg_Function(msgptr, I2O_UTIL_PARAMS_SET, acc_handle); + ddi_put32(acc_handle, (uint32_t *)&msgptr->InitiatorContext, + (uint32_t)i2ohba_utilmsg_comp); + + /* + * allocating sychronize status buffer + */ + sp = kmem_alloc(sizeof (struct i2ohba_util), KM_SLEEP); + + ddi_put32(acc_handle, &msgptr->TransactionContext, + (uint32_t)(uintptr_t)sp); + + /* + * First message buffer's SGL and operation parameters + */ + + /* + * Buf1 SGL header: + * Immediate Data for the operation + */ + put_flags_count_Flags(&msgptr->FlagsCount1, + I2O_SGL_FLAGS_IMMEDIATE_DATA_ELEMENT + | I2O_SGL_FLAGS_END_OF_BUFFER, acc_handle); + put_flags_count_Count(&msgptr->FlagsCount1, ONE_PARAM_BLOCK, + acc_handle); + + /* + * Fill in the modify operation param for in the sgl1 payload + */ + + ddi_put16(acc_handle, &msgptr->OperationCount, 1); + ddi_put16(acc_handle, &msgptr->Operation, + I2O_PARAMS_OPERATION_FIELD_SET); + ddi_put16(acc_handle, &msgptr->GroupNumber, group); + ddi_put16(acc_handle, &msgptr->FieldCount, 0x1); + ddi_put16(acc_handle, &msgptr->FieldIdx, idx); + ddi_put16(acc_handle, &msgptr->Value, value); + + + /* + * Buf2 SGL header: + * Simple addressing + * 1. allocate the buffer for reply msg + * 2. setup the SGL header + */ + + sp->i2ohba_util_buffer = NULL; + + if (ddi_dma_alloc_handle(i2ohba->i2ohba_dip, &i2ohba_dmasgl_attr, + DDI_DMA_SLEEP, NULL, &sp->dmahandle) != + DDI_SUCCESS) { + i2ohba_i_log(NULL, CE_WARN, "?i2ohba_utilparam_set: " + "cannot alloc dma handle"); + goto fail; + } + bound++; + if (ddi_dma_mem_alloc(sp->dmahandle, (size_t) + sizeof (i2o_param_results_list_header_t) + (size_t) + sizeof (i2o_param_modify_operation_result_t), + &dev_attr, DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, + (caddr_t *)&sp->i2ohba_util_buffer, &sp->rlen, + &sp->dma_acc_handle) != DDI_SUCCESS) { + i2ohba_i_log(NULL, CE_WARN, "?i2ohba_utilparamset_msg: " + "cannot allocate param buffer"); + goto fail; + } + bound++; + put_flags_count_Flags(&msgptr->FlagsCount2, + I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER | + I2O_SGL_FLAGS_LAST_ELEMENT, acc_handle); + + put_flags_count_Count(&msgptr->FlagsCount2, sp->rlen, acc_handle); + + + if (ddi_dma_addr_bind_handle(sp->dmahandle, NULL, + sp->i2ohba_util_buffer, (size_t) + sizeof (i2o_param_results_list_header_t) + (size_t) + sizeof (i2o_param_modify_operation_result_t) + (size_t) + sizeof (i2o_scsi_device_info_scalar_t), + DDI_DMA_RDWR|DDI_DMA_STREAMING, DDI_DMA_SLEEP, + NULL, &sp->dmacookie, &count) != DDI_DMA_MAPPED) { + /* + * currently assume simple + * addring with one physical + * continuous address buffer. + */ + i2ohba_i_log(NULL, CE_WARN, "?i2ohba_utilparamset_msg: " + "cannot bind buffer"); + goto fail; + } + + ddi_put32(acc_handle, &msgptr->PhysicalAddress, + (uint32_t)sp->dmacookie.dmac_address); + /* + * initialized a mutex and condvariable to + * send message to IOP, and wait for it + * to signal back + */ + sp->mutex = I2OHBA_UTILPARAM_MUTEX(i2ohba, tgt); + sp->cv = I2OHBA_UTILPARAM_CV(i2ohba, tgt); + mutex_enter(sp->mutex); + sp->wakeup = UTIL_MSG_SLEEP; + sp->status = 0; + (void) i2o_msg_send(i2ohba->i2ohba_iophdl, msgptr, msg_handle); + while (!sp->wakeup) + cv_wait(sp->cv, sp->mutex); + mutex_exit(sp->mutex); + + /* clear msg pointer */ + msgptr = NULL; + + /* + * process the data + */ + switch (sp->status) { + + i2o_setparam_reply_t *result; + uint16_t count; + uint8_t blockstatus, errinfosize; + + case I2O_REPLY_STATUS_SUCCESS: + /* + * since the reply is successful, will check + * for the opeation reulsts + */ + result = (i2o_setparam_reply_t *)sp->i2ohba_util_buffer; + count = ddi_get16(sp->dma_acc_handle, + &result->ResultCount); + if (!count) { + i2ohba_i_log(NULL, CE_WARN, + "?i2ohba_utilparamset_msg: No Results"); + break; + } + + blockstatus = ddi_get8(sp->dma_acc_handle, + &result->BlockStatus); + + errinfosize = ddi_get8(sp->dma_acc_handle, + &result->ErrorInfoSize); + + if ((blockstatus != 0) || (errinfosize != 0)) { + i2ohba_i_log(NULL, CE_WARN, + "?i2ohba_utilparamset_msg: Error " + "occured during Modify Operation"); + /* + * retrived errorinfo and possibily retry + * XXLWLXX + */ + break; + } + rval = 0; + break; + + default: + rval = -1; + break; + } + +fail: + + if (sp) { + if (bound) { + (void) ddi_dma_unbind_handle(sp->dmahandle); + if (bound > 1) + (void) ddi_dma_mem_free(&sp->dma_acc_handle); + (void) ddi_dma_free_handle(&sp->dmahandle); + } + kmem_free(sp, sizeof (struct i2ohba_util)); + } + + /* return MFA to IOP */ + if (msgptr) { + msgptr->VersionOffset = 0; + msgptr->MsgFlags = 0; + ddi_put16(acc_handle, &msgptr->MessageSize, 3); + put_msg_TargetAddress(msgptr, 0, acc_handle); + put_msg_InitiatorAddress(msgptr, 0, acc_handle); + put_msg_Function(msgptr, I2O_UTIL_NOP, acc_handle); + (void) i2o_msg_send(i2ohba->i2ohba_iophdl, msgptr, msg_handle); + } + return (rval); +} + +/* + * Function name: i2ohba_utilparamget_msg() + * + * Return Values: 0 - success + * -1 - get prarmeter failed + * + * Description : common UtilParamGet function. + * However, only one param at a time. Pass in + * the Tid, GroupNumber, and the FieldIdx, and + * value, then compose the Message frame, + * then send it off through i2o_message_send(). + * + * Message Format: + * + * building a param_get message requires + * Buffer#1 SGL-immediate data + * 1. i2o_param_operations_list_header_t(1W) + * u16 OperationCount + * u16 Reserved + * 2. i2o_param_operation_speicific_template_t(2W) + * u16 Operation (FIELD_GET) + * u16 GroupNumber + * u16 FieldCount 0xFFFF + * u16 Pad + * + * Buffer#2 SGL-Simple addressing + * Reply Message: + * 1. i2o_param_results_list_header_t(1W) + * u16 ResultCount + * u16 Reserved + * 2. i2o_param_read_operation_result_t(9W) + * u16 BlockSize + * u8 BlockStatus + * u8 ErrorInfoSize + * ... Total 8W for (ALL_PARAM_BLOCK) + * u32 Identifier + * u64 LUN + * ... + * OR Total 9 bytes (ONE_PARAM_BLOCK) + * u8 NegOffset + * u64 NegSynch + */ + +static int +i2ohba_utilparamget_msg(struct i2ohba *i2ohba, uint16_t tidx, char flag) +{ + + i2o_tid_scsi_ent_t *map = i2ohba->i2ohba_tid_scsi_map; + i2o_tid_scsi_ent_t **tgtmap = i2ohba->i2ohba_tgt_id_map; + + i2o_getsyncparam_t *msgptr; + i2o_msg_handle_t msg_handle; + ddi_acc_handle_t acc_handle; + struct i2ohba_util *sp = NULL; + uint_t count; + uint16_t allocmsgsize; + uint16_t tid; + int rval = -1; + int bound = 0; + + /* + * allocate a message frame + */ + if (i2o_msg_alloc(i2ohba->i2ohba_iophdl, I2O_MSG_SLEEP, + NULL, (void *)&msgptr, &msg_handle, &acc_handle) + != DDI_SUCCESS) { + i2ohba_i_log(NULL, CE_WARN, "?i2ohba_utilparamget_msg: " + "i2o_msg_alloc failed"); + return (rval); + } + + /* + * NOTE: + * "tidx" is either the entry number for the tid to scsi map + * or tidx is the target id, which needs tgt to id map to + * find the tid. + */ + if (flag == ALL_UTILPARAMS) { + tid = map[tidx].tid; + } else { + tid = tgtmap[tidx]->tid; + } + + /* + * To get the actual allocation msg + * size (in WORDS) + */ + allocmsgsize = (ddi_get16(acc_handle, &msgptr->MessageSize) << 2); + + + /* + * Construct a utilparamget message + */ + /* msgptr->VersionOffset = ContextSize32; */ + msgptr->VersionOffset = I2O_VERSION_11; + msgptr->MsgFlags = 0; + put_msg_TargetAddress(msgptr, tid, acc_handle); + put_msg_InitiatorAddress(msgptr, I2O_OSM_TID, acc_handle); + put_msg_Function(msgptr, I2O_UTIL_PARAMS_GET, acc_handle); + ddi_put32(acc_handle, + (uint32_t *)&msgptr->InitiatorContext.initiator_context_32bits, + (uint32_t)i2ohba_utilmsg_comp); + /* + * allocating sychroniz status buffer + */ + sp = kmem_alloc(sizeof (struct i2ohba_util), KM_SLEEP); + + ddi_put32(acc_handle, &msgptr->TransactionContext, + (uint32_t)(uintptr_t)sp); + + /* + * Buf1 SGL header: + * Immediate Data + */ + put_flags_count_Flags(&msgptr->FlagsCount1, + I2O_SGL_FLAGS_IMMEDIATE_DATA_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER, acc_handle); + + /* + * Fill in the read operation param for + * in the payload + */ + + ddi_put16(acc_handle, &msgptr->OperationCount, 1); + + ddi_put16(acc_handle, &msgptr->Operation, + I2O_PARAMS_OPERATION_FIELD_GET); + + ddi_put16(acc_handle, &msgptr->GroupNumber, + I2O_SCSI_DEVICE_INFO_GROUP_NO); + + /* + * End of message sending + */ + + /* + * Buf2 SGL header: + * Simple Addressing + * 1. allocating the buffer + * 2. set up the SGL header + */ + + sp->i2ohba_util_buffer = NULL; + + if (ddi_dma_alloc_handle(i2ohba->i2ohba_dip, &i2ohba_dmasgl_attr, + DDI_DMA_SLEEP, NULL, &sp->dmahandle) != + DDI_SUCCESS) { + i2ohba_i_log(NULL, CE_WARN, "?i2ohba_utilparamget_msg: " + "cannot alloc dma handle"); + goto fail; + } + bound++; + if (flag == ALL_UTILPARAMS) { + + if (allocmsgsize < sizeof (i2o_getallparam_t)) + return (rval); + + if (ddi_dma_mem_alloc(sp->dmahandle, (size_t) + sizeof (i2o_getallparam_reply_t), &dev_attr, + DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, + (caddr_t *)&sp->i2ohba_util_buffer, &sp->rlen, + &sp->dma_acc_handle) != DDI_SUCCESS) { + i2ohba_i_log(NULL, CE_WARN, + "?i2ohba_utilparamget_msg: " + "cannot allocate param buffer"); + goto fail; + } + bound++; + /* StdMessageFrame */ + ddi_put16(acc_handle, &msgptr->MessageSize, + (sizeof (i2o_getallparam_t) >> 2)); + + /* i2o_sge_immediate_data_element */ + put_flags_count_Count(&msgptr->FlagsCount1, ALL_PARAM_BLOCK, + acc_handle); + + /* i2o_param_operation_all_template */ + ddi_put16(acc_handle, &msgptr->FieldCount, 0xFFFF); + + /* i2o_sge_simple_element */ + put_flags_count_Flags( + &((i2o_getallparam_t *)msgptr)->FlagsCount2, + I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER | + I2O_SGL_FLAGS_LAST_ELEMENT, acc_handle); + + put_flags_count_Count( + &((i2o_getallparam_t *)msgptr)->FlagsCount2, + sp->rlen, acc_handle); + + if (ddi_dma_addr_bind_handle(sp->dmahandle, NULL, + sp->i2ohba_util_buffer, (size_t) + sizeof (i2o_getallparam_reply_t), + DDI_DMA_READ|DDI_DMA_STREAMING, DDI_DMA_SLEEP, + NULL, &sp->dmacookie, &count) != DDI_SUCCESS) { + /* + * currently assume simple + * addring with one physical + * continuous address buffer. + */ + i2ohba_i_log(NULL, CE_WARN, + "?i2ohba_utilparamget_msg: " + "cannot bind buffer"); + goto fail; + } + + ddi_put32(acc_handle, + &((i2o_getallparam_t *)msgptr)->PhysicalAddress, + (uint32_t)sp->dmacookie.dmac_address); + + /* + * initialized the target param_mutex and cv. + * note: given that we don't have target id + * yet, (that is why we are here), we'll just + * use target[0]'s mutex & cv. + */ + sp->mutex = I2OHBA_UTILPARAM_MUTEX(i2ohba, 0); + sp->cv = I2OHBA_UTILPARAM_CV(i2ohba, 0); + } else { + if (allocmsgsize < sizeof (i2o_getsyncparam_t)) + return (rval); + + if (ddi_dma_mem_alloc(sp->dmahandle, (size_t) + sizeof (i2o_getsyncparam_reply_t), &dev_attr, + DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, + (void *)&sp->i2ohba_util_buffer, &sp->rlen, + &sp->dma_acc_handle) != DDI_SUCCESS) { + i2ohba_i_log(NULL, CE_WARN, + "?i2ohba_utilparamget_msg: " + "cannot allocate param buffer"); + goto fail; + } + bound++; + /* StdMessageFrame */ + ddi_put16(acc_handle, &msgptr->MessageSize, + (sizeof (i2o_getsyncparam_t) >> 2)); + + /* i2o_sge_immediate_data_element */ + put_flags_count_Count(&msgptr->FlagsCount1, ONE_PARAM_BLOCK, + acc_handle); + + /* i2o_param_operation_specific_template */ + ddi_put16(acc_handle, &msgptr->FieldCount, 0x0002); + ddi_put16(acc_handle, &msgptr->FieldIdx, 0x000A); + ddi_put16(acc_handle, &msgptr->FieldIdx, 0x0007); + + /* i2o_sge_simple_element */ + put_flags_count_Flags(&msgptr->FlagsCount2, + I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER | + I2O_SGL_FLAGS_LAST_ELEMENT, acc_handle); + + put_flags_count_Count(&msgptr->FlagsCount2, sp->rlen, + acc_handle); + + if (ddi_dma_addr_bind_handle(sp->dmahandle, NULL, + sp->i2ohba_util_buffer, (size_t) + sizeof (i2o_getsyncparam_reply_t), + DDI_DMA_RDWR|DDI_DMA_STREAMING, DDI_DMA_SLEEP, + NULL, &sp->dmacookie, &count) != DDI_DMA_MAPPED) { + /* + * currently assume simple + * addring with one physical + * continuous address buffer. + */ + i2ohba_i_log(NULL, CE_WARN, + "?i2ohba_utilparamget_msg: " + "cannot bind buffer"); + goto fail; + } + + ddi_put32(acc_handle, &msgptr->PhysicalAddress, + (uint32_t)sp->dmacookie.dmac_address); + + /* + * initialized the target param_mutex and cv + * tidx holds the target id number + */ + sp->mutex = I2OHBA_UTILPARAM_MUTEX(i2ohba, tidx); + sp->cv = I2OHBA_UTILPARAM_CV(i2ohba, tidx); + } + +#ifdef I2OHBA_DEBUG + DEBUGF(2, (CE_CONT, "\nmsgptr: 0x%p\n", (void *)msgptr)); + DEBUGF(2, (CE_CONT, "msgptr->VersionOffset: %x\n", + msgptr->VersionOffset)); + DEBUGF(2, (CE_CONT, "msgptr->MsgFlags: %x\n", msgptr->MsgFlags)); + DEBUGF(2, (CE_CONT, "msgptr->MessageSize: %x\n", ddi_get16(acc_handle, + &msgptr->MessageSize))); + DEBUGF(2, (CE_CONT, "msgptr->TargetAddress: %x\n", + get_msg_TargetAddress(msgptr, acc_handle))); + DEBUGF(2, (CE_CONT, "msgptr->InitiatorAddress: %x\n", + get_msg_InitiatorAddress(msgptr, acc_handle))); + DEBUGF(2, (CE_CONT, "msgptr->Function: %x\n", + get_msg_Function(msgptr, acc_handle))); + DEBUGF(2, (CE_CONT, "msgptr->InitContext: %x\n", + ddi_get32(acc_handle, + &msgptr->InitiatorContext.initiator_context_32bits))); + DEBUGF(2, (CE_CONT, "msgptr->TransContext: %x\n", + ddi_get32(acc_handle, &msgptr->TransactionContext))); + DEBUGF(2, (CE_CONT, "msgptr->OperationFlags: Resevered\n")); + DEBUGF(2, (CE_CONT, "msgptr->FlagsCount1.Flags: %x\n", + get_flags_count_Flags(&msgptr->FlagsCount1, acc_handle))); + DEBUGF(2, (CE_CONT, "msgptr->FlagsCount1.Count: %x\n", + get_flags_count_Count(&msgptr->FlagsCount1, acc_handle))); + DEBUGF(2, (CE_CONT, "msgptr->OperationCount: %x\n", + ddi_get16(acc_handle, &msgptr->OperationCount))); + DEBUGF(2, (CE_CONT, "msgptr->Operation: %x\n", + ddi_get16(acc_handle, &msgptr->Operation))); + DEBUGF(2, (CE_CONT, "msgptr->GroupNumber: %x\n", + ddi_get16(acc_handle, &msgptr->GroupNumber))); + DEBUGF(2, (CE_CONT, "msgptr->FieldCount: %x\n", + ddi_get16(acc_handle, &msgptr->FieldCount))); + DEBUGF(2, (CE_CONT, "msgptr->FlagsCount2.Flags: %x\n", + get_flags_count_Flags(&((i2o_getallparam_t *)msgptr)->FlagsCount2, + acc_handle))); + DEBUGF(2, (CE_CONT, "msgptr->FlagsCount2.Count: %x\n", + get_flags_count_Count(&((i2o_getallparam_t *)msgptr)->FlagsCount2, + acc_handle))); + DEBUGF(2, (CE_CONT, "msgptr->PhyAddr: %x\n", ddi_get32(acc_handle, + &((i2o_getallparam_t *)msgptr)->PhysicalAddress))); +#endif + /* + * initialized a mutex and condvariable to + * send message to IOP, and wait for it + * to signal back + */ + mutex_enter(sp->mutex); + sp->wakeup = UTIL_MSG_SLEEP; + sp->status = 0; + (void) i2o_msg_send(i2ohba->i2ohba_iophdl, msgptr, msg_handle); + while (!sp->wakeup) + cv_wait(sp->cv, sp->mutex); + mutex_exit(sp->mutex); + + msgptr = NULL; + + /* + * process the data + */ + switch (sp->status) { + case I2O_REPLY_STATUS_SUCCESS: + /* + * Success: + * 0) read the reply headers XXLWXX + * 1) copy buffer over to the map + * 2) unbind dma buffer + */ + + if (sp->i2ohba_util_buffer) { + uint_t tgtid; + + if (flag == ALL_UTILPARAMS) { + i2o_getallparam_reply_t *reply; + + reply = (i2o_getallparam_reply_t *) + sp->i2ohba_util_buffer; + map[tidx].scsi_info_scalar.DeviceType = + reply->DeviceType; + DEBUGF(2, (CE_CONT, "/tDeviceType:" + " 0x%x", reply->DeviceType)); + map[tidx].scsi_info_scalar.Flags = + reply->Flags; + DEBUGF(2, (CE_CONT, "/tFlags:" + " 0x%x", reply->Flags)); + map[tidx].scsi_info_scalar.Identifier = + tgtid = + ddi_get32(sp->dma_acc_handle, + &reply->Identifier); + DEBUGF(2, (CE_CONT, "/tSCSI Id: 0x%x", + tgtid)); + map[tidx].scsi_info_scalar.LunInfo[0] = 0; + map[tidx].scsi_info_scalar.QueueDepth = + ddi_get32(sp->dma_acc_handle, + &reply->QueueDepth); + DEBUGF(2, (CE_CONT, "/tQueueDepth: 0x%x", + map[tidx].scsi_info_scalar.QueueDepth)); + map[tidx].scsi_info_scalar.NegOffset = + reply->NegOffset; + DEBUGF(2, (CE_CONT, "/tQueueDepth: 0x%x", + reply->NegOffset)); + map[tidx].scsi_info_scalar.NegDataWidth = + reply->NegDataWidth; + DEBUGF(2, (CE_CONT, "/tNegDataWidth: 0x%x", + reply->NegDataWidth)); + map[tidx].scsi_info_scalar.NegSyncRate = + ddi_get64(sp->dma_acc_handle, + &reply->NegSyncRate); + DEBUGF(2, (CE_CONT, "/tNegSyncRate: 0x%x", + (uint32_t) + map[tidx].scsi_info_scalar.NegSyncRate)); + + tgtmap[tgtid] = &map[tidx]; + + } else { + i2o_getsyncparam_reply_t *reply; + + reply = (i2o_getsyncparam_reply_t *) + sp->i2ohba_util_buffer; + tgtmap[tidx]->scsi_info_scalar.NegSyncRate = + ddi_get64(sp->dma_acc_handle, + &reply->NegSyncRate); + DEBUGF(2, (CE_CONT, "/tNegSyncRate: 0x%x", + (uint32_t) + map[tidx].scsi_info_scalar.NegSyncRate)); + tgtmap[tidx]->scsi_info_scalar.NegOffset = + reply->NegOffset; + DEBUGF(2, (CE_CONT, "/tNegOffset: 0x%x", + reply->NegOffset)); + } + } + rval = 0; + break; + + case I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER: + case I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER: + default: + i2ohba_i_log(NULL, CE_WARN, "?I2O_PARAM_UTIL_GET on " + "Target %d failed", tidx); + break; + + } + +fail: + + if (sp) { + if (bound) { + (void) ddi_dma_unbind_handle(sp->dmahandle); + if (bound > 1) + (void) ddi_dma_mem_free(&sp->dma_acc_handle); + (void) ddi_dma_free_handle(&sp->dmahandle); + + } + kmem_free(sp, sizeof (struct i2ohba_util)); + } + + /* return MFA to IOP */ + if (msgptr) { + msgptr->VersionOffset = 0; + msgptr->MsgFlags = 0; + ddi_put16(acc_handle, &msgptr->MessageSize, 3); + put_msg_TargetAddress(msgptr, 0, acc_handle); + put_msg_InitiatorAddress(msgptr, 0, acc_handle); + put_msg_Function(msgptr, I2O_UTIL_NOP, acc_handle); + (void) i2o_msg_send(i2ohba->i2ohba_iophdl, msgptr, msg_handle); + } + + return (rval); +} + +/*PRINTFLIKE3*/ +static void +i2ohba_i_log(struct i2ohba *i2ohba, int level, char *fmt, ...) +{ + dev_info_t *dip; + va_list ap; + + ASSERT((mutex_owned(&i2ohba_log_mutex)) == 0 || ddi_in_panic()); + + if (i2ohba) { + dip = i2ohba->i2ohba_dip; + } else { + dip = 0; + } + + mutex_enter(&i2ohba_log_mutex); + va_start(ap, fmt); + (void) vsprintf(i2ohba_log_buf, fmt, ap); + va_end(ap); + + if (level == CE_WARN) { + scsi_log(dip, "i2o_scsi", level, "%s", i2ohba_log_buf); + } else { + scsi_log(dip, "i2o_scsi", level, "%s\n", i2ohba_log_buf); + } + mutex_exit(&i2ohba_log_mutex); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/uts/common/io/i2o/i2o_scsi.conf Wed Apr 18 11:32:14 2007 -0700 @@ -0,0 +1,35 @@ +# +# 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 (c) 1998 by Sun Microsystems, Inc. +# All rights reserved. +# +#pragma ident "%Z%%M% %I% %E% SMI" + +# +# i2o_scsi.conf +# +# global definitions + +name="i2o_scsi" class="i2o"; +flow_control="dmult" queue="qsort" tape="sctp";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/uts/common/io/i2o/i2o_scsi_cmd.h Wed Apr 18 11:32:14 2007 -0700 @@ -0,0 +1,98 @@ +/* + * 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 (c) 1998 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef _I2O_SCSI_CMD_H +#define _I2O_SCSI_CMD_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#define PKT_PRIV_LEN 8 /* preferred pkt_private length */ +#define PKT2CMD(pkt) ((struct i2ohba_cmd *)(pkt)->pkt_ha_private) +#define CMD2PKT(sp) ((sp)->cmd_pkt) + +/* + * These are the defined flags for this structure. + */ +#define CFLAG_FINISHED 0x0001 /* command completed */ +#define CFLAG_COMPLETED 0x0002 /* completion routine called */ +#define CFLAG_IN_TRANSPORT 0x0004 /* in use by isp driver */ +#define CFLAG_DELAY_TIMEOUT 0x0008 /* delay timeout */ +#define CFLAG_TRANFLAG 0x000f /* transport part of flags */ +#define CFLAG_DMAVALID 0x0010 /* dma mapping valid */ +#define CFLAG_DMASEND 0x0020 /* data is going 'out' */ +#define CFLAG_CMDIOPB 0x0040 /* this is an 'iopb' packet */ +#define CFLAG_FREE 0x0080 /* packet is on free list */ +#define CFLAG_DMA_PARTIAL 0x0100 /* partial xfer OK */ + + +/* + * I2O command struct to keep the request and response + * + * the preferred cbd size is 12, but I2O standard defined based on + * SCSI 3. + */ + +struct i2ohba_cmd { + i2o_scsi_scb_execute_message_t *cmd_i2o_request; + struct scsi_pkt *cmd_pkt; + struct i2ohba_cmd *cmd_forw; /* forward ptr */ + struct i2ohba_cmd *cmd_backw; /* backward ptr */ + + ddi_dma_handle_t sglbuf_dmahandle; /* SGL chain buffer */ + ddi_acc_handle_t sglbuf_dmaacchandle; /* SGL chain buffer */ + ddi_dma_cookie_t sglbuf_dmacookie; + i2o_sge_chain_element_t *sglbuf; /* the buffer that holds the SGL */ + size_t sglrlen; /* the buffer that holds the SGL */ + size_t cmd_dmacount; /* totl # of bytes transfer */ + size_t cmd_xfercount; /* cur # of bytes transfer */ + ddi_dma_handle_t cmd_dmahandle; /* dma handle */ + uint_t cmd_cookie; /* next cookie */ + uint_t cmd_ncookies; /* cookies per window */ + uint_t cmd_cookiecnt; /* cookies per sub-window */ + uint_t cmd_nwin; /* number of dma windows */ + uint_t cmd_curwin; /* current dma window */ + off_t cmd_dma_offset; /* current window offset */ + ulong_t cmd_dma_len; /* current window length */ + ddi_dma_cookie_t cmd_dmacookies[I2OHBA_CMD_NSEGS]; + /* current dma cookies */ + clock_t cmd_deadline; + uint16_t cmd_flags; /* Internal state flag */ + uint8_t cmd_cdblen; + uint_t cmd_scblen; + uchar_t cmd_cdb[I2O_SCSI_CDB_LENGTH]; /* 16-SCSI3 */ + uint_t cmd_privlen; + uchar_t cmd_pkt_private[PKT_PRIV_LEN]; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _I2O_SCSI_CMD_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/uts/common/io/i2o/i2o_scsi_util.h Wed Apr 18 11:32:14 2007 -0700 @@ -0,0 +1,274 @@ +/* + * 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 (c) 1998 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef _I2O_SCSI_UTIL_H +#define _I2O_SCSI_UTIL_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Utility msg synchronization condvar + */ +#define UTIL_MSG_SLEEP 0 +#define UTIL_MSG_WAKEUP 1 + +/* + * Utility Parameter's mutex + */ +#define I2OHBA_UTILPARAM_MUTEX(i2ohba, i) (&i2ohba->util_param_mutex[i]) +#define I2OHBA_UTILPARAM_CV(i2ohba, i) (&i2ohba->util_param_cv[i]) + + +/* + * Defines for parameter size + */ +#define ONE_PARAM_BLOCK (sizeof (i2o_param_operations_list_header_t)\ + + sizeof (i2o_param_operation_specific_template_t) \ + + sizeof (uint32_t)) + +#define ALL_PARAM_BLOCK (sizeof (i2o_param_operations_list_header_t)\ + + sizeof (i2o_param_operation_all_template_t) \ + + sizeof (uint16_t)) + +/* + * Utility message's transaction context + */ +struct i2ohba_util { + int wakeup; /* value */ + int status; /* status of reply msg */ + kmutex_t *mutex; /* per request mutex */ + kcondvar_t *cv; /* per request signal */ + void *i2ohba_util_buffer; /* result operation block */ + size_t rlen; /* length of the result block */ + ddi_dma_cookie_t dmacookie; /* dma cookie for result block */ + ddi_dma_handle_t dmahandle; /* dma handle for result block */ + ddi_acc_handle_t dma_acc_handle; /* dma access handle */ +}; + +/* + * Util_Params_Get Op on all Parameters + */ + +typedef struct i2o_setparam { + + /* i2o_message_frame_t */ + uint8_t VersionOffset; + uint8_t MsgFlags; + uint16_t MessageSize; + union { + struct { + uint_t TargetAddress:12; + uint_t InitiatorAddress:12; + uint_t Function:8; + } s2; + uint32_t w2; + } u2; + i2o_initiator_context_t InitiatorContext; + + /* i2o_util_params_set_message */ + i2o_transaction_context_t TransactionContext; + uint32_t OperationFlags; + + /* SGL: i2o_sge_immediate_data_elememnt */ + i2o_flags_count_t FlagsCount1; /* 32 bits */ + /* size == ONE_PARAM_BLOCK */ + /* i2o_param_operation_list_header */ + uint16_t OperationCount; + uint16_t Reserved; + + /* i2o_param_operation_specific_template */ + uint16_t Operation; + uint16_t GroupNumber; + uint16_t FieldCount; + uint16_t FieldIdx; + uint16_t Value; /* not in struct */ + uint16_t pad; /* not in struct */ + + /* SGL: i2o_sge_simple_element */ + i2o_flags_count_t FlagsCount2; /* 32 bits */ + uint32_t PhysicalAddress; + +} i2o_setparam_t; + + +typedef struct i2o_setparam_reply { + + /* i2o_param_results_list_header_t */ + uint16_t ResultCount; + uint16_t Reserved; + + /* i2o_param_modify_operation_result */ + uint16_t BlockSize; + uint8_t BlockStatus; + uint8_t ErrorInfoSize; + /* ErrorInformation (if any) */ +} i2o_setparam_reply_t; + +#define ALL_UTILPARAMS 0x01 +#define SYNC_UTILPARAM 0x02 + +/* + * Util_Params_Get Op on all Parameters + */ + +typedef struct i2o_getallparam { + + /* i2o_message_frame_t */ + uint8_t VersionOffset; + uint8_t MsgFlags; + uint16_t MessageSize; + union { + struct { + uint_t TargetAddress:12; + uint_t InitiatorAddress:12; + uint_t Function:8; + } s2; + uint32_t w2; + } u2; + i2o_initiator_context_t InitiatorContext; + + /* i2o_util_params_get_message */ + i2o_transaction_context_t TransactionContext; + uint32_t OperationFlags; + + /* SGL: i2o_sge_immediate_data_elememnt */ + i2o_flags_count_t FlagsCount1; /* 32 bits */ + /* size == ALL_PARAM_BLOCK */ + /* i2o_param_operation_list_header */ + uint16_t OperationCount; + uint16_t Reserved; + + /* i2o_param_operation_all_template */ + uint16_t Operation; + uint16_t GroupNumber; + uint16_t FieldCount; /* (0xffff) */ + uint16_t Pad; /* not part of all temp struct */ + + /* SGL: i2o_sge_simple_element */ + i2o_flags_count_t FlagsCount2; /* 32 bits */ + uint32_t PhysicalAddress; + +} i2o_getallparam_t; + + +typedef struct i2o_getallparam_reply { + + /* i2o_param_results_list_header_t */ + uint16_t ResultCount; + uint16_t Reserved; + + /* i2o_param_read_operation_result */ + uint16_t BlockSize; + uint8_t BlockStatus; + uint8_t ErrorInfoSize; + + /* ListOfValues */ + uint8_t DeviceType; + uint8_t Flags; + uint16_t Reserved1; + uint32_t Identifier; + uint8_t LUN[8]; + uint32_t QueueDepth; + uint8_t Reserved2; + uint8_t NegOffset; + uint8_t NegDataWidth; + uint8_t Reserved3; + uint64_t NegSyncRate; + +} i2o_getallparam_reply_t; + + +/* + * Util_Params_Get Op on Synch and Offset + */ +typedef struct i2o_getsyncparam { + + /* i2o_message_frame_t */ + uint8_t VersionOffset; + uint8_t MsgFlags; + uint16_t MessageSize; + union { + struct { + uint_t TargetAddress:12; + uint_t InitiatorAddress:12; + uint_t Function:8; + } s2; + uint32_t w2; + } u2; + i2o_initiator_context_t InitiatorContext; + + /* i2o_util_params_get_message */ + i2o_transaction_context_t TransactionContext; + uint32_t OperationFlags; + + /* SGL: i2o_sge_immediate_data_elememnt */ + i2o_flags_count_t FlagsCount1; /* 32 bits */ + /* size == ONE_PARAM_BLOCK */ + /* i2o_param_operation_list_header */ + uint16_t OperationCount; + uint16_t Reserved; + + /* i2o_param_operation_specific_template */ + uint16_t Operation; + uint16_t GroupNumber; + uint16_t FieldCount; + uint16_t FieldIdx; /* field #10 */ + uint16_t FieldIdx2; /* field #7 not in struct */ + uint16_t Pad; /* not in struct */ + + /* SGL: i2o_sge_simple_element */ + i2o_flags_count_t FlagsCount2; /* 32 bits */ + uint32_t PhysicalAddress; + +} i2o_getsyncparam_t; + + +typedef struct i2o_getsyncparam_reply { + + /* i2o_param_results_list_header_t */ + uint16_t ResultCount; + uint16_t Reserved; + + /* i2o_param_read_operation_result */ + uint16_t BlockSize; + uint8_t BlockStatus; + uint8_t ErrorInfoSize; + + /* ListOfValues */ + uint64_t NegSyncRate; + uint8_t NegOffset; + +} i2o_getsyncparam_reply_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _I2O_SCSI_UTIL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/uts/common/io/i2o/i2o_scsi_var.h Wed Apr 18 11:32:14 2007 -0700 @@ -0,0 +1,246 @@ +/* + * 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 (c) 1998, by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef _I2O_SCSI_VAR_H +#define _I2O_SCSI_VAR_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Convenient defines + */ + +/* + * Local static data + */ + +#define I2OHBA_INITIAL_SOFT_SPACE 2 /* assume 2 instances of hba */ +#define I2OHBA_CMD_NSEGS 17 +#define I2O_OSM_TID 0x01 + +#define TGT(sp) (CMD2PKT(sp)->pkt_address.a_target) +#define LUN(sp) (CMD2PKT(sp)->pkt_address.a_lun) + +/* + * Targets supported + */ +#define N_I2OHBA_LUNS 8 +#define N_I2OHBA_TARGETS 8 +#define N_I2OHBA_TARGETS_WIDE 16 + +/* + * message module defines + */ +#define ContextSize32 0x51 +#define ContextSize64 0x71 + +/* + * Default scsi-options + */ +#define I2OHBA_DEFAULT_SCSI_OPTIONS \ + SCSI_OPTIONS_PARITY | \ + SCSI_OPTIONS_DR | \ + SCSI_OPTIONS_SYNC | \ + SCSI_OPTIONS_TAG | \ + SCSI_OPTIONS_FAST | \ + SCSI_OPTIONS_WIDE + + +/* + * Mutex short hands + */ +#define I2OHBA_REQ_MUTEX(i2ohba) (&i2ohba->i2ohba_request_mutex) +#define I2OHBA_MUTEX_OWNED(i2ohba) mutex_owned(I2OHBA_REQ_MUTEX(i2ohba)) +#define I2OHBA_MUTEX_ENTER(i2ohba) mutex_enter(I2OHBA_REQ_MUTEX(i2ohba)) +#define I2OHBA_MUTEX_EXIT(i2ohba) mutex_exit(I2OHBA_REQ_MUTEX(i2ohba)) + +#define I2OHBA_RESET_MUTEX(i2ohba) (&i2ohba->reset_mutex) +#define I2OHBA_RESET_CV(i2ohba) (&i2ohba->reset_cv) + +/* + * HBA interface macros + */ +#define SDEV2TRAN(sd) ((sd)->sd_address.a_hba_tran) +#define SDEV2ADDR(sd) (&((sd)->sd_address)) +#define PKT2TRAN(pkt) ((pkt)->pkt_address.a_hba_tran) +#define ADDR2TRAN(ap) ((ap)->a_hba_tran) + +#define TRAN2I2OHBA(tran) ((struct i2ohba *)(tran)->tran_hba_private) +#define SDEV2I2OHBA(sd) (TRAN2I2OHBA(SDEV2TRAN(sd))) +#define PKT2I2OHBA(pkt) (TRAN2I2OHBA(PKT2TRAN(pkt))) +#define ADDR2I2OHBA(ap) (TRAN2I2OHBA(ADDR2TRAN(ap))) + +#define CMD2ADDR(cmd) (&CMD2PKT(cmd)->pkt_address) +#define CMD2TRAN(cmd) (CMD2PKT(cmd)->pkt_address.a_hba_tran) +#define CMD2I2OHBA(cmd) (TRAN2I2OHBA(CMD2TRAN(cmd))) + +/* + * Capability defines + */ +#define I2OHBA_CAP_DISCONNECT 0x8000 +#define I2OHBA_CAP_PARITY 0x4000 +#define I2OHBA_CAP_WIDE 0x2000 +#define I2OHBA_CAP_SYNC 0x1000 +#define I2OHBA_CAP_TAG 0x0800 +#define I2OHBA_CAP_AUTOSENSE 0x0400 +#define I2OHBA_CAP_ERRSTOP 0x0200 +#define I2OHBA_CAP_ERRSYNC 0x0100 + +/* + * delay time for polling loops + */ +#define I2OHBA_NOINTR_POLL_DELAY_TIME 1000 /* usecs */ + +/* + * value used to force bus reset in i2ohab_i_reset_interface() + */ +#define I2OHBA_FORCE_BUS_RESET 0x02 +#define PERIOD_MASK(val) ((val) & 0xff) +#define OFFSET_MASK(val) (((val) >> 8) & 0xff) + +/* + * timeout values + */ +#define I2OHBA_GRACE 10 /* Timeout margin (sec.) */ +#define I2OHBA_TIMEOUT_DELAY(secs, delay) (secs * (1000000 / delay)) + +typedef struct i2o_tid_scsi_ent { + uint16_t tid; /* associated TID */ + i2o_scsi_device_info_scalar_t scsi_info_scalar; +} i2o_tid_scsi_ent_t; + +struct i2ohba { + + /* + * Message request double link list chain + */ + struct i2ohba_cmd *i2ohba_reqhead; + struct i2ohba_cmd *i2ohba_reqtail; + + /* + * Mutex for the request or reply link list + */ + kmutex_t i2ohba_request_mutex; + /* + * Mutex for utilparam msg or reset param msg + */ + kmutex_t util_param_mutex[N_I2OHBA_TARGETS_WIDE]; + kmutex_t reset_mutex; + kcondvar_t util_param_cv[N_I2OHBA_TARGETS_WIDE]; + kcondvar_t reset_cv; + + /* + * Bus Adapter's Tid + */ + uint16_t i2ohba_tid; + + /* + * i2ohba shutdown flag + */ + uint8_t i2ohba_shutdown; + + /* + * i2ohba clear queue + */ + uint32_t i2ohba_throttle; + uint32_t i2ohba_counter; + + /* + * i2ohba timeout id + */ + timeout_id_t i2ohba_timeout_id; + + /* + * flag for updating properties in i2ohba_i_watch() + * to avoid updating in interrupt context + */ + uint16_t i2ohba_need_prop_update; + + /* + * Host adapter capabilities and offset/period values per target + * (dynamically changed by the target) + */ + uint16_t i2ohba_cap[N_I2OHBA_TARGETS_WIDE]; + uint16_t i2ohba_synch[N_I2OHBA_TARGETS_WIDE]; + uint8_t i2ohba_offset[N_I2OHBA_TARGETS_WIDE]; + uint32_t i2ohba_totsec[N_I2OHBA_TARGETS_WIDE]; + uint32_t i2ohba_secsz[N_I2OHBA_TARGETS_WIDE]; + + /* + * Transport structure for this instance of the hba + */ + scsi_hba_tran_t *i2ohba_tran; + + /* + * dev_info_t reference can be found in the transport structure + */ + dev_info_t *i2ohba_dip; + + /* + * IOP access handle (The IOP controls/associated with dip) + */ + i2o_iop_handle_t i2ohba_iophdl; + + /* + * Bus Adapter's Param + */ + i2o_hba_scsi_controller_info_scalar_t *i2ohba_scsi_controller; + + /* + * TID to SCSI/LUN target map, this hba can have upto 15 devices + */ + i2o_tid_scsi_ent_t i2ohba_tid_scsi_map[N_I2OHBA_TARGETS_WIDE]; + + i2o_tid_scsi_ent_t *i2ohba_tgt_id_map[N_I2OHBA_TARGETS_WIDE]; + + /* + * scsi options, etc from ddi_getprop() + * default value from the UtilParamGet + */ + int i2ohba_scsi_options; /* default one */ + int i2ohba_target_scsi_option[N_I2OHBA_TARGETS_WIDE]; + int i2ohba_initiator_id; + + /* + * scsi_reset_delay for i2o + */ + uint32_t i2ohba_scsi_reset_delay; + + + struct scsi_reset_notify_entry *i2ohba_reset_notify_listf; + + +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _I2O_SCSI_VAR_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/uts/common/io/i2o/label.c Wed Apr 18 11:32:14 2007 -0700 @@ -0,0 +1,915 @@ +/* + * 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 2004 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/file.h> +#include <sys/cmn_err.h> +#include <sys/uio.h> +#include <sys/kmem.h> +#include <sys/sysmacros.h> +#include <sys/stat.h> +#include <sys/scsi/scsi.h> +#include <sys/stat.h> + +#include <sys/fdio.h> + +#include <sys/errno.h> +#include <sys/open.h> +#include <sys/varargs.h> +#include <sys/fs/pc_label.h> + +#include <sys/hdio.h> +#include <sys/dkio.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> + +#include <sys/dktp/fdisk.h> + + +#include <sys/fs/pc_label.h> + +#include <sys/i2o/i2omsg.h> +#include "i2o_bs.h" + + +static int dsklbl_chk(struct dk_label *, unsigned short *); +static void dsklbl_preplb(dsk_label_t *, dev_t, struct cb_ops *, int); +static void dsklbl_convert_lbl_to_pmap(struct dk_label *, dsk_label_t *); +static void dsklbl_savelb(struct dk_label *, dsk_label_t *); +static int dsklbl_rdvtoc(dsk_label_t *, struct buf *, struct cb_ops *); +char *partition_type(unsigned char); +void dsklbl_read_label(struct buf *, dsk_label_t *, struct cb_ops *, + struct dk_geom *, int); +void dsklbl_mprint(struct partition *); +int dsklbl_wrvtoc(dsk_label_t *, struct vtoc *, struct buf *, + struct cb_ops *); +void dsklbl_ondsklabel_to_vtoc(dsk_label_t *, struct vtoc *); +void dsklbl_vtoc_to_ondsklabel(dsk_label_t *, struct vtoc *); +void dsklbl_dgtoug(struct dk_geom *, struct dk_label *); +void dsklbl_ugtodg(struct dk_geom *, struct dk_label *); + +#ifdef DLBL_DEBUG +int label_debug = 1; + +#define DEBUGF(flag, args) \ + { if (label_debug & (flag)) cmn_err args; } +#else +#define DEBUGF(level, args) /* nothing */ +#endif + +static int +dsklbl_chk(struct dk_label *lbp, unsigned short *cksum) +{ + short *sp; + short count; + unsigned short sum; + + /* + * Check magic number of the label + */ + if (lbp->dkl_magic != DKL_MAGIC) { + DEBUGF(1, (CE_CONT, "?dsklbl_chk: magic: %x not MAGIC:" + "%x\n", lbp->dkl_magic, DKL_MAGIC)); + return (DDI_FAILURE); + } + if (lbp->dkl_vtoc.v_sanity != VTOC_SANE) { + DEBUGF(1, (CE_CONT, "?dsklbl_chk:sanity: %x not SANE:" + "%x\n", lbp->dkl_vtoc.v_sanity, VTOC_SANE)); + return (DDI_FAILURE); + } + if (lbp->dkl_vtoc.v_version != V_VERSION) { + DEBUGF(1, (CE_CONT, "?dsklbl_chk:version: %x not %x\n", + lbp->dkl_vtoc.v_version, V_VERSION)); + return (DDI_FAILURE); + } + + /* + * Check the checksum of the label + */ + sp = (short *)lbp; + sum = 0; + count = sizeof (struct dk_label) / sizeof (short); + while (count--) { + sum ^= *sp++; + } + + *cksum = sum; + if (sum) + return (DDI_FAILURE); + return (DDI_SUCCESS); +} + +/* + * We have this wonderful scenario where there exists two different kind + * of labeling scheme the x86/ppc vs. Sparc they are sufficiently different + * (read broken) that it justifies having two completely different preplb + * routines. + */ + +static void +dsklbl_preplb(dsk_label_t *lblp, dev_t dev, struct cb_ops *dev_ops, int type) +{ + long disksize; + struct dk_geom dkg; + int rval; + int s2size; + + + DEBUGF(1, (CE_CONT, "?dlbl_preplb(%x, %x)\n", lblp, dev)); + + bzero(&dkg, sizeof (struct dk_geom)); + bzero(&lblp->ondsklbl, sizeof (struct dk_label)); + + (*dev_ops->cb_ioctl)(dev, DKIOCG_PHYGEOM, + (uintptr_t)&dkg, FKIOCTL, (cred_t *)0, &rval); + + +#if defined(_SUNOS_VTOC_16) + lblp->ondsklbl.dkl_pcyl = lblp->pmap[FDISK_OFFSET+lblp->uidx].p_size / + (dkg.dkg_nhead * dkg.dkg_nsect); + + DEBUGF(1, (CE_CONT, "?dsklbl_preplb(p_size = %d, nhead = %d" + "nsect = %d)\n", + (lblp->pmap[FDISK_OFFSET+lblp->uidx].p_size), dkg.dkg_nhead, + dkg.dkg_nsect)); + +#elif defined(_SUNOS_VTOC_8) + lblp->ondsklbl.dkl_pcyl = (unsigned short)(lblp->pmap[FDISK_OFFSET+ + lblp->uidx].p_size / + (long)(dkg.dkg_nhead * dkg.dkg_nsect)); +#endif + + + + lblp->ondsklbl.dkl_acyl = 2; + lblp->ondsklbl.dkl_ncyl = lblp->ondsklbl.dkl_pcyl - + lblp->ondsklbl.dkl_acyl; + + /* or can use the size saved in ata_data (consider generic case */ + disksize = lblp->ondsklbl.dkl_ncyl * dkg.dkg_nhead * dkg.dkg_nsect; + + + lblp->ondsklbl.dkl_intrlv = 1; + lblp->ondsklbl.dkl_apc = 0; + lblp->ondsklbl.dkl_vtoc.v_nparts = V_NUMPAR; + lblp->ondsklbl.dkl_magic = DKL_MAGIC; + + lblp->ondsklbl.dkl_vtoc.v_sanity = VTOC_SANE; + lblp->ondsklbl.dkl_vtoc.v_version = V_VERSION; + + + /* + * Set up the p0 partition + */ + lblp->pmap[FPART_WHOLE+FDISK_OFFSET].p_start = 0; + lblp->pmap[FPART_WHOLE+FDISK_OFFSET].p_size = disksize; + lblp->pmap[FPART_WHOLE+FDISK_OFFSET].p_flag = V_UNMNT; + + + + /* NEEDS WORK add support for SPARC for CD */ + /* + * If CD-ROM, special-case: + * - lie about head/sect/cyl to get at every block on the disk + * - add full disk as slices 0 and 2 to the label + */ + + if (type == DKC_CDROM) { + /* + * Not heads * sectors * cyls, but the whole thing + * This applies later, to s2, as well. + */ + + + lblp->ondsklbl.dkl_nhead = 1; + lblp->ondsklbl.dkl_nsect = 1; + + /* NEEDS WORK get it from IOP probably not SD uses it too */ + lblp->ondsklbl.dkl_rpm = 200; + +#if defined(_SUNOS_VTOC_16) + + lblp->ondsklbl.dkl_vtoc.v_part[USLICE_WHOLE].p_start = 0; + lblp->ondsklbl.dkl_vtoc.v_part[USLICE_WHOLE].p_size = disksize; + lblp->ondsklbl.dkl_vtoc.v_part[USLICE_WHOLE].p_tag = V_BACKUP; + lblp->ondsklbl.dkl_vtoc.v_part[USLICE_WHOLE].p_flag = V_UNMNT; + + lblp->ondsklbl.dkl_vtoc.v_part[0].p_start = 0; + lblp->ondsklbl.dkl_vtoc.v_part[0].p_size = disksize; + lblp->ondsklbl.dkl_vtoc.v_part[0].p_tag = V_BACKUP; + lblp->ondsklbl.dkl_vtoc.v_part[0].p_flag = V_UNMNT; + + +#elif defined(_SUNOS_VTOC_8) + + /* Add full disk slice as slice 2 to the disk */ + + lblp->ondsklbl.dkl_map[USLICE_WHOLE].dkl_cylno = 0; + lblp->ondsklbl.dkl_map[USLICE_WHOLE].dkl_nblk = disksize; + + lblp->ondsklbl.dkl_map[0].dkl_cylno = 0; + lblp->ondsklbl.dkl_map[USLICE_WHOLE].dkl_nblk = disksize; + + + +#else +#error No VTOC format defined. +#endif + } else { + + /* NONE CD case */ + + + lblp->ondsklbl.dkl_nhead = dkg.dkg_nhead; + lblp->ondsklbl.dkl_nsect = dkg.dkg_nsect; + + lblp->ondsklbl.dkl_rpm = 3600; + + /* Add boot disk slice as slice 8 to the disk */ + + + /* + * There is a number of cases we have to worry about: + * + * 1) There is an fdisk partition but no Solaris partition. + * In this case the s2 slice size is zero since a valid + * Solaris partition must be present for us to decide the + * the size of the Solaris partition. + * + * 2) There is an fdisk parition and a Solaris partition. + * We got here because the Solaris partition was not labeled + * or the label has been corrupted, declare the entire Solaris + * parition as the s2 slice + * + * 3) There is no fdisk partition. + * We have to declare the entire disk as the s2 slice, + * with some room for the fdisk partition (I think) + */ + + if (lblp->fdiskpresent) { + if (lblp->uidx == 0) { /* FDISK - Solaris (1 above) */ + s2size = 0; + } else { /* FDISK + Solaris (2 above) */ + s2size = lblp->pmap[lblp->uidx+FDISK_OFFSET].p_size; + } + } else { /* No FDISK (3 above) */ + s2size = disksize; + } +#if defined(_SUNOS_VTOC_16) + /* + * If this is x86/PowerPC format label + */ + + lblp->ondsklbl.dkl_vtoc.v_sectorsz = NBPSCTR; + + /* Add full disk slice as slice 2 to the disk */ + + lblp->ondsklbl.dkl_vtoc.v_part[USLICE_WHOLE].p_start = 0; + lblp->ondsklbl.dkl_vtoc.v_part[USLICE_WHOLE].p_size = s2size; + lblp->ondsklbl.dkl_vtoc.v_part[USLICE_WHOLE].p_tag = V_BACKUP; + lblp->ondsklbl.dkl_vtoc.v_part[USLICE_WHOLE].p_flag = V_UNMNT; + + lblp->ondsklbl.dkl_vtoc.v_part[8].p_start = 0; + lblp->ondsklbl.dkl_vtoc.v_part[8].p_size = + dkg.dkg_nhead * dkg.dkg_nsect; + lblp->ondsklbl.dkl_vtoc.v_part[8].p_tag = V_BOOT; + lblp->ondsklbl.dkl_vtoc.v_part[8].p_flag = V_UNMNT; + + /* For now this is not a requirenment */ + /* Add Alternates disk slice as slice 9 to the disk */ + + lblp->ondsklbl.dkl_vtoc.v_part[9].p_start = + dkg.dkg_nhead * dkg.dkg_nsect; + lblp->ondsklbl.dkl_vtoc.v_part[9].p_size = + 2 * dkg.dkg_nhead * dkg.dkg_nsect; + lblp->ondsklbl.dkl_vtoc.v_part[9].p_tag = V_ALTSCTR; + lblp->ondsklbl.dkl_vtoc.v_part[9].p_flag = 0; + + (void) sprintf(lblp->ondsklbl.dkl_vtoc.v_asciilabel, + "DEFAULT cyl %d alt %d hd %d sec %d", + lblp->ondsklbl.dkl_ncyl, + lblp->ondsklbl.dkl_acyl, + lblp->ondsklbl.dkl_nhead, + lblp->ondsklbl.dkl_nsect); +#elif defined(_SUNOS_VTOC_8) + + /* Add full disk slice as slice 2 to the disk */ + + lblp->ondsklbl.dkl_map[USLICE_WHOLE].dkl_cylno = 0; + lblp->ondsklbl.dkl_map[USLICE_WHOLE].dkl_nblk = s2size; + + (void) sprintf(lblp->ondsklbl.dkl_asciilabel, + "DEFAULT cyl %d alt %d hd %d sec %d", + lblp->ondsklbl.dkl_ncyl, + lblp->ondsklbl.dkl_acyl, + lblp->ondsklbl.dkl_nhead, + lblp->ondsklbl.dkl_nsect); +#else +#error No VTOC format defined. +#endif + + + + } + + (void) dsklbl_chk(&lblp->ondsklbl, &(lblp->ondsklbl.dkl_cksum)); + /* + * now that an on disk label is manufactured, convert so + * that we start using right away + * is this the right thing to do, we also need a mutex + * to protext it. + * + * dsklbl_convert_lbl_to_pmap(&lblp->ondsklbl, lblp); + * + */ + +} + +static void +dsklbl_convert_lbl_to_pmap(struct dk_label *lbp, dsk_label_t *lblp) +{ + int i; +#if defined(_SUNOS_VTOC_16) + bcopy((caddr_t)&lbp->dkl_vtoc.v_part, + (caddr_t)lblp->pmap, sizeof (lbp->dkl_vtoc.v_part)); +#elif defined(_SUNOS_VTOC_8) + for (i = 0; i < NDKMAP; i++) { + lblp->pmap[i].p_tag = lbp->dkl_vtoc.v_part[i].p_tag; + lblp->pmap[i].p_flag = lbp->dkl_vtoc.v_part[i].p_flag; + lblp->pmap[i].p_start = lbp->dkl_map[i].dkl_cylno * + lblp->ondsklbl.dkl_nhead * lblp->ondsklbl.dkl_nsect; + lblp->pmap[i].p_size = lbp->dkl_map[i].dkl_nblk; + } +#else +#error No VTOC format defined. +#endif + for (i = 0; i < NDKMAP; i++) { + lblp->pmap[i].p_start += + lblp->pmap[lblp->uidx+FDISK_OFFSET].p_start; + } +} + +static void +dsklbl_savelb(struct dk_label *lbp, dsk_label_t *lblp) +{ + /* + * save the disk label in memory + */ + + bcopy((caddr_t)lbp, (caddr_t)&lblp->ondsklbl, sizeof (*lbp)); + + dsklbl_convert_lbl_to_pmap(lbp, lblp); +#ifdef DLBL_DEBUG + dsklbl_mprint(lblp->pmap); +#endif +} + +static int +dsklbl_rdvtoc(dsk_label_t *lblp, struct buf *bp, struct cb_ops *dev_ops) +{ + struct dk_label *lbp; + unsigned short sum; + + /* + * read the label + */ + DEBUGF(1, (CE_CONT, "?dsklbl_rdvtoc(%x, %x)\n", lblp, bp)); + bp->b_bcount = 1 * DEV_BSIZE; + bp->b_flags = B_READ; + bp->b_blkno = lblp->pmap[FDISK_OFFSET+lblp->uidx].p_start+VTOC_OFFSET; + + (*dev_ops->cb_strategy)(bp); + (void) biowait(bp); + + + lbp = (struct dk_label *)bp->b_un.b_addr; + + /* + * check label + */ + if ((!lbp) || (dsklbl_chk(lbp, &sum) == DDI_FAILURE)) { + DEBUGF(1, (CE_CONT, + "?label does not have a valid checksum\n")); + return (DDI_FAILURE); + } + /* + * record label information + */ + dsklbl_savelb(lbp, lblp); + lblp->vtocread = 1; + + return (DDI_SUCCESS); +} + + +struct { + unsigned char id; + char *name; +} partitionname[] = { + { 0x01, "DOS 12-bit FAT" }, + { 0x02, "XENIX /" }, + { 0x03, "XENIX /usr" }, + { 0x04, "DOS 16-bit FAT <32M" }, + { 0x05, "DOS Extended Partition" }, + { 0x06, "DOS 16-bit FAT >=32M" }, + { 0x07, "OS/2 IFS (e.g., HPFS) or NTFS or QNX2.x or Advanced UNIX" }, + { 0x08, "AIX boot or SplitDrive" }, + { 0x09, "AIX data or Coherent" }, + { 0x0a, "OS/2 Boot Manager" }, + { 0x0e, "DOS 16-bit FAT, CHS-mapped" }, + { 0x0f, "Extended partition, CHS-mapped" }, + { 0x10, "OPUS" }, + { 0x11, "OS/2 BM: Hidden DOS 12-bit FAT" }, + { 0x12, "Compaq config partition" }, + { 0x14, "OS/2 BM: Hidden DOS 16-bit FAT <32M" }, + { 0x16, "OS/2 BM: Hidden DOS 16-bit FAT >=32M" }, + { 0x17, "OS/2 BM: Hidden IFS (e.g., HPFS)" }, + { 0x18, "AST Windows swapfile" }, + { 0x24, "NEC DOS" }, + { 0x3c, "PartitionMagic recovery partition" }, + { 0x40, "Venix 80286" }, + { 0x41, "Linux/MINIX (sharing disk with DRDOS)" }, + { 0x42, "Linux swap (sharing disk with DRDOS) or SFS" }, + { 0x43, "Linux native (sharing disk with DRDOS)" }, + { 0x50, "OnTrack DM RO" }, + { 0x51, "OnTrack DM RW (DM6 Aux1) or Novell" }, + { 0x52, "CP/M or Microport SysV/AT" }, + { 0x53, "DM6 Aux3" }, + { 0x54, "DM6" }, + { 0x55, "EZ-Drive" }, + { 0x56, "Golden Bow VFeature Partitioned Volume." }, + { 0x5C, "Priam EDisk" }, + { 0x61, "SpeedStor" }, + { 0x63, "Unix System V (SCO, ISC UNIX, UnixWare, ...)" }, + { 0x64, "Novell Netware 2.xx" }, + { 0x65, "Novell Netware 3.xx or 4.xx" }, + { 0x70, "DiskSecure Multi-Boot" }, + { 0x75, "PC/IX" }, + { 0x77, "QNX4.x" }, + { 0x78, "QNX4.x 2nd part" }, + { 0x79, "QNX4.x 3rd part" }, + { 0x80, "MINIX until 1.4a" }, + { 0x81, "MINIX since 1.4b, early Linux, Mitac dmgr" }, + { 0x82, "Solaris" }, + { 0x83, "Linux native" }, + { 0x84, "OS/2 hidden C: drive" }, + { 0x85, "Linux extended partition" }, + { 0x86, "NTFS volume set??" }, + { 0x87, "NTFS volume set??" }, + { 0x93, "Amoeba" }, + { 0x94, "Amoeba bad track table" }, + { 0xa0, "IBM Thinkpad hibernation partition" }, + { 0xa5, "BSD/386, 386BSD, NetBSD, FreeBSD" }, + { 0xa7, "NEXTSTEP" }, + { 0xb7, "BSDI fs" }, + { 0xb8, "BSDI swap" }, + { 0xc1, "DRDOS/sec (FAT-12)" }, + { 0xc4, "DRDOS/sec (FAT-16, < 32M)" }, + { 0xc6, "DRDOS/sec (FAT-16, >= 32M)" }, + { 0xc7, "Syrinx" }, + { 0xdb, "Concurrent CP/M or Concurrent DOS or CTOS" }, + { 0xe1, "DOS access or SpeedStor 12-bit FAT extended partition" }, + { 0xe3, "DOS R/O or SpeedStor" }, + { 0xe4, "SpeedStor 16-bit FAT extended partition < 1024 cyl." }, + { 0xf1, "SpeedStor" }, + { 0xf2, "DOS 3.3+ secondary" }, + { 0xf4, "SpeedStor large partition" }, + { 0xfe, "SpeedStor >1024 cyl. or LANstep" }, + { 0xff, "Xenix Bad Block Table" } +}; + +char * +partition_type(unsigned char systid) +{ + int i; + + for (i = 0; i < sizeof (partitionname)/sizeof (partitionname[0]); i++) + if (partitionname[i].id == systid) + return (partitionname[i].name); + + return ("Unknown"); +} + +int +parse_fdisk_lbl(struct buf *bp, dsk_label_t *lblp, struct cb_ops *dev_ops, + struct dk_geom *dkg, int type) +{ + struct mboot *mbp; + struct ipart *fdp; + int i, uidx; + struct ipart fdisk[FD_NUMPART]; + + /* + * The whole disk is represented here (this is the p0 partition.) + */ + lblp->pmap[FPART_WHOLE+FDISK_OFFSET].p_start = 0; + lblp->pmap[FPART_WHOLE+FDISK_OFFSET].p_size = + dkg->dkg_ncyl * dkg->dkg_nhead * dkg->dkg_nsect; + lblp->pmap[FPART_WHOLE+FDISK_OFFSET].p_flag = V_UNMNT; + + mbp = (struct mboot *)bp->b_un.b_addr; + + if (!mbp || ltohs(mbp->signature) != MBB_MAGIC) { + + DEBUGF(1, (CE_CONT, + "?lbl 0x%x does not have an fdisk table.\n", + bp->b_edev)); +#ifdef DLBL_DEBUG + if (mbp) + DEBUGF(1, (CE_CONT, "?lbl " + "expteced magic: 0x%x got 0x%x\n", + MBB_MAGIC, ltohs(mbp->signature))); +#endif + DEBUGF(1, (CE_CONT, + "parse_label: b_edev %x " + "b_dev = %x\n", + bp->b_edev, bp->b_dev)); + + lblp->fdiskpresent = 0; + lblp->uidx = 0; + if (dsklbl_rdvtoc(lblp, bp, dev_ops) == DDI_FAILURE) { + bp->b_dev = cmpdev(bp->b_edev); + dsklbl_preplb(lblp, bp->b_edev, dev_ops, type); + } + return (DDI_SUCCESS); + } + /* + * The fdisk table does not begin on a 4-byte boundary within + * the master boot record; so, we need to recopy its contents to + * another data structure to avoid an alignment exception. + * This is not necessary for x86, but it avoids ifdefs + */ + fdp = fdisk; + bcopy((caddr_t)&(mbp->parts[0]), (caddr_t)fdp, sizeof (fdisk)); + + DEBUGF(1, (CE_CONT, + "?---------------------- Partition Table -----------------\n")); + DEBUGF(1, (CE_CONT, "?index relsect numsect type\n")); + DEBUGF(1, (CE_CONT, + "?------- ------- ------- -----------------------------\n")); + + for (uidx = 0, i = 1; i <= FD_NUMPART; i++, fdp++) { + if (!fdp->numsect) { + lblp->pmap[i+FDISK_OFFSET].p_flag = V_INVALID; + continue; + } + lblp->pmap[i+FDISK_OFFSET].p_start = ltohi(fdp->relsect); + lblp->pmap[i+FDISK_OFFSET].p_size = ltohi(fdp->numsect); + DEBUGF(1, (CE_CONT, "?%7d %7d %7d %4x (%s)\n", i, + ltohi(fdp->relsect), + ltohi(fdp->numsect), + fdp->systid, partition_type(fdp->systid))); + if (fdp->systid == SUNIXOS || fdp->systid == SUNIXOS2) { + if (uidx == 0) + uidx = i; + else if (fdp->bootid == ACTIVE) + uidx = i; + } + } + + lblp->fdiskpresent = 1; + lblp->uidx = uidx; + if (dsklbl_rdvtoc(lblp, bp, dev_ops) == DDI_FAILURE) { + bp->b_dev = cmpdev(bp->b_edev); + dsklbl_preplb(lblp, bp->b_edev, dev_ops, type); + + } + return (DDI_SUCCESS); +} + +void +dsklbl_read_label(struct buf *bp, dsk_label_t *lblp, struct cb_ops *dev_ops, + struct dk_geom *dkg, int type) +{ + /* + * read the label + */ + + bp->b_bcount = 1 * DEV_BSIZE; + bp->b_flags = B_READ; + bp->b_blkno = 0; + (*dev_ops->cb_strategy)(bp); + (void) biowait(bp); + (void) parse_fdisk_lbl(bp, lblp, dev_ops, dkg, type); +} + +#ifdef DLBL_DEBUG +void +dsklbl_mprint(struct partition *pp) +{ + int i; + + cmn_err(CE_CONT, "?----- UNIX slices -----\n"); + cmn_err(CE_CONT, "?slice start size\n"); + cmn_err(CE_CONT, "?----- ------ --------\n"); + for (i = 0; i < NDKMAP; i++, pp++) { + if (pp->p_size) { + cmn_err(CE_CONT, "?%5d %6x %x\n", i, pp->p_start, + pp->p_size); + } + } +} +#endif + + +int +dsklbl_wrvtoc(dsk_label_t *lblp, struct vtoc *vtocp, struct buf *bp, + struct cb_ops *dev_ops) +{ + register struct dk_label *lbp, *dp; + int status; + int backup_block; + int count; + + /* + * Data is originated from vtoc. One copy of the data is stored in + * lblp->ondsklbl. This is what we think of as the copy of the lable + * on this held in memory. The other copy (to the lbp) is to be + * written out to the disk. + */ + dp = &lblp->ondsklbl; + + bp->b_bcount = 1 * DEV_BSIZE; + bp->b_flags = B_WRITE | B_BUSY; + + lbp = (struct dk_label *)bp->b_un.b_addr; + + dsklbl_vtoc_to_ondsklabel(lblp, vtocp); + *lbp = lblp->ondsklbl; + + /* + * check label + */ + if (lblp->uidx) + bp->b_blkno = lblp->pmap[FDISK_OFFSET+lblp->uidx].p_start; + else + bp->b_blkno = 0; + bp->b_blkno += VTOC_OFFSET; + + + (*dev_ops->cb_strategy)(bp); + status = biowait(bp); + + if (status != 0 || dp->dkl_acyl == 0) + return (status); + + /* + * DO backup copies of vtoc + */ + + backup_block = ((dp->dkl_ncyl + dp->dkl_acyl - 1) * + (dp->dkl_nhead * dp->dkl_nsect)) + + ((dp->dkl_nhead - 1) * dp->dkl_nsect) + 1; + + bcopy((caddr_t)&(lblp->ondsklbl), (caddr_t)lbp, sizeof (*lbp)); + for (count = 1; count < 6; count++) { + + bp->b_blkno = + lblp->pmap[FDISK_OFFSET+lblp->uidx].p_start+backup_block; + bp->b_flags = B_WRITE | B_BUSY; + + (*dev_ops->cb_strategy)(bp); + (void) biowait(bp); + + backup_block += 2; + } + return (0); +} + + + +void +dsklbl_ondsklabel_to_vtoc(dsk_label_t *lblp, struct vtoc *vtocp) +{ +#if defined(_SUNOS_VTOC_16) + bcopy((caddr_t)&lblp->ondsklbl.dkl_vtoc, (caddr_t)vtocp, + sizeof (*vtocp)); +#elif defined(_SUNOS_VTOC_8) + int i; + long nblks; + struct dk_map2 *lpart; + struct dk_map *lmap; + struct partition *vpart; + + + /* + * Data is originated from vtoc. One copy of the data is stored in + * lblp->ondsklbl. This is what we think of as the copy of the label + * on the disk held in memory. The other copy (to the lbp) is to be + * written out to the disk. + */ + + /* + * Put appropriate vtoc structure fields into the disk label + * + */ + bcopy((caddr_t)(lblp->ondsklbl.dkl_vtoc.v_bootinfo), + (caddr_t)vtocp->v_bootinfo, sizeof (vtocp->v_bootinfo)); + + /* For now may want to add the sectorsz field to the generic structur */ + vtocp->v_sectorsz = NBPSCTR; /* sector size in bytes */ + + vtocp->v_sanity = lblp->ondsklbl.dkl_vtoc.v_sanity; + vtocp->v_version = lblp->ondsklbl.dkl_vtoc.v_version; + + bcopy((caddr_t)lblp->ondsklbl.dkl_vtoc.v_volume, + (caddr_t)vtocp->v_volume, LEN_DKL_VVOL); + + vtocp->v_nparts = lblp->ondsklbl.dkl_vtoc.v_nparts; + + bcopy((caddr_t)lblp->ondsklbl.dkl_vtoc.v_reserved, + (caddr_t)vtocp->v_reserved, sizeof (vtocp->v_reserved)); + + /* + * Note the conversion from starting sector number + * to starting cylinder number. + */ + nblks = lblp->ondsklbl.dkl_nsect * lblp->ondsklbl.dkl_nhead; + + lmap = lblp->ondsklbl.dkl_map; + lpart = (struct dk_map2 *)lblp->ondsklbl.dkl_vtoc.v_part; + vpart = vtocp->v_part; + + for (i = 0; i < (int)vtocp->v_nparts; i++) { + vpart->p_tag = lpart->p_tag; + vpart->p_flag = lpart->p_flag; + vpart->p_start = lmap->dkl_cylno * nblks; + vpart->p_size = lmap->dkl_nblk; + + lmap++; + lpart++; + vpart++; + } + + bcopy((caddr_t)lblp->ondsklbl.dkl_vtoc.v_timestamp, + (caddr_t)vtocp->timestamp, sizeof (vtocp->timestamp)); + + bcopy((caddr_t)lblp->ondsklbl.dkl_asciilabel, + (caddr_t)vtocp->v_asciilabel, + LEN_DKL_ASCII); + +#else +#error No VTOC format defined. +#endif +} + +void +dsklbl_vtoc_to_ondsklabel(dsk_label_t *lblp, struct vtoc *vtocp) +{ +#if defined(_SUNOS_VTOC_16) + bcopy((caddr_t)vtocp, (caddr_t)&(lblp->ondsklbl.dkl_vtoc), + sizeof (*vtocp)); +#elif defined(_SUNOS_VTOC_8) + /* + * Put appropriate vtoc structure fields into the disk label + * + */ + int i; + long nblks; + struct dk_map2 *lpart; + struct dk_map *lmap; + struct partition *vpart; + register struct dk_label *dp; + + /* + * Data is originated from vtoc. One copy of the data is stored in + * lblp->ondsklbl. This is what we think of as the copy of the label + * on this disk held in memory. The other copy (to the lbp) is to be + * written out to the disk. + */ + dp = &lblp->ondsklbl; + + + bcopy((caddr_t)vtocp->v_bootinfo, + (caddr_t)(lblp->ondsklbl.dkl_vtoc.v_bootinfo), + sizeof (vtocp->v_bootinfo)); + + lblp->ondsklbl.dkl_vtoc.v_sanity = vtocp->v_sanity; + lblp->ondsklbl.dkl_vtoc.v_version = vtocp->v_version; + + bcopy((caddr_t)vtocp->v_volume, + (caddr_t)lblp->ondsklbl.dkl_vtoc.v_volume, + LEN_DKL_VVOL); + + lblp->ondsklbl.dkl_vtoc.v_nparts = vtocp->v_nparts; + + bcopy((caddr_t)vtocp->v_reserved, + (caddr_t)lblp->ondsklbl.dkl_vtoc.v_reserved, + sizeof (vtocp->v_reserved)); + + /* + * Note the conversion from starting sector number + * to starting cylinder number. + */ + nblks = dp->dkl_nsect * dp->dkl_nhead; + lmap = lblp->ondsklbl.dkl_map; + lpart = (struct dk_map2 *)lblp->ondsklbl.dkl_vtoc.v_part; + vpart = vtocp->v_part; + + for (i = 0; i < (int)vtocp->v_nparts; i++) { + lpart->p_tag = vpart->p_tag; + lpart->p_flag = vpart->p_flag; + lmap->dkl_cylno = vpart->p_start / nblks; + lmap->dkl_nblk = vpart->p_size; + + lmap++; + lpart++; + vpart++; + } + + bcopy((caddr_t)vtocp->timestamp, + (caddr_t)lblp->ondsklbl.dkl_vtoc.v_timestamp, + sizeof (vtocp->timestamp)); + + bcopy((caddr_t)vtocp->v_asciilabel, + (caddr_t)lblp->ondsklbl.dkl_asciilabel, + LEN_DKL_ASCII); + +#else +#error No VTOC format defined. +#endif + + lblp->ondsklbl.dkl_cksum = 0; + (void) dsklbl_chk(&lblp->ondsklbl, &(lblp->ondsklbl.dkl_cksum)); +} + +void +dsklbl_dgtoug(struct dk_geom *up, struct dk_label *dp) +{ + DEBUGF(1, (CE_CONT, "?dsklbl_dgtoug: pcyl = %d ncyl = %d acyl = %d\n", + dp->dkl_pcyl, dp->dkl_ncyl, dp->dkl_acyl)); + + up->dkg_pcyl = dp->dkl_pcyl; + up->dkg_ncyl = dp->dkl_ncyl; + up->dkg_acyl = dp->dkl_acyl; +#if !defined(__sparc) + up->dkg_bcyl = dp->dkl_bcyl; +#endif + up->dkg_nhead = dp->dkl_nhead; + up->dkg_nsect = dp->dkl_nsect; + up->dkg_intrlv = dp->dkl_intrlv; + up->dkg_apc = dp->dkl_apc; + up->dkg_rpm = dp->dkl_rpm; + up->dkg_write_reinstruct = dp->dkl_write_reinstruct; + up->dkg_read_reinstruct = dp->dkl_read_reinstruct; +} + + + + +void +dsklbl_ugtodg(struct dk_geom *up, struct dk_label *dp) +{ + dp->dkl_pcyl = up->dkg_pcyl; + dp->dkl_ncyl = up->dkg_ncyl; + dp->dkl_acyl = up->dkg_acyl; +#if !defined(__sparc) + dp->dkl_bcyl = up->dkg_bcyl; +#endif + dp->dkl_nhead = up->dkg_nhead; + dp->dkl_nsect = up->dkg_nsect; + dp->dkl_intrlv = up->dkg_intrlv; + dp->dkl_apc = up->dkg_apc; + dp->dkl_rpm = up->dkg_rpm; + dp->dkl_write_reinstruct = up->dkg_write_reinstruct; + dp->dkl_read_reinstruct = up->dkg_read_reinstruct; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/uts/common/io/i2o/pci_to_i2o.c Wed Apr 18 11:32:14 2007 -0700 @@ -0,0 +1,1137 @@ +/* + * 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" + +/* + * PCI-to-I2O bus nexus driver. + * + * The current implementation complies with the I2O Specification + * Version 1.5. So, it assumes only 32bit virtual addresses and + * 32bit context fields in I2O messages. + */ + +#include <sys/types.h> +#include <sys/cmn_err.h> +#include <sys/conf.h> +#include <sys/debug.h> +#include <sys/errno.h> +#include <sys/modctl.h> +#include <sys/ddidmareq.h> +#include <sys/ddi_impldefs.h> +#include <sys/ddi.h> +#include <sys/sunddi.h> +#include <sys/sunndi.h> +#include <sys/pci.h> +#include <sys/avintr.h> +#include <sys/bustypes.h> +#include <sys/kmem.h> +#include <sys/archsystm.h> +#include <sys/i2o/i2oexec.h> +#include "i2o_impl.h" + +char _depends_on[] = "misc/i2o_msg"; + +/* + * function prototypes for bus ops routines: + */ +static int +i2o_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr, + int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep); + +static int +i2o_bus_ctl(dev_info_t *dip, dev_info_t *rdip, + ddi_ctl_enum_t opt, void *a, void *v); + +static int +i2o_intr_op(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op, + ddi_intr_handle_impl_t *hdlp, void *result); + +struct bus_ops i2o_bus_ops = { + BUSO_REV, + nullbusmap, + NULL, + NULL, + NULL, + i_ddi_map_fault, + ddi_no_dma_map, /* 2.4 DDI only - not supported */ + i2o_dma_allochdl, + ddi_dma_freehdl, + ddi_dma_bindhdl, + ddi_dma_unbindhdl, + ddi_dma_flush, + ddi_dma_win, + ddi_dma_mctl, + i2o_bus_ctl, + ddi_bus_prop_op, + NULL, /* (* bus_get_eventcookie)() */ + NULL, /* (* bus_add_eventcall)() */ + NULL, /* (* bus_remove_eventcall)() */ + NULL, /* (* bus_post_event)() */ + NULL, /* interrupt control */ + 0, /* bus_config */ + 0, /* bus_unconfig */ + 0, /* bus_fm_init */ + 0, /* bus_fm_fini */ + 0, /* bus_fm_access_enter */ + 0, /* bus_fm_access_exit */ + 0, /* bus_power */ + i2o_intr_op /* bus_intr_op */ +}; + + +/* + * Function prototypes for dev_ops entry points. + */ + +static int i2o_probe(dev_info_t *); +static int i2o_attach(dev_info_t *, ddi_attach_cmd_t); +static int i2o_detach(dev_info_t *, ddi_detach_cmd_t); + +struct dev_ops i2o_dev_ops = { + DEVO_REV, /* devo_rev */ + 0, /* refcnt */ + ddi_no_info, /* info */ + nulldev, /* identify */ + i2o_probe, /* probe */ + i2o_attach, /* attach */ + i2o_detach, /* detach */ + nodev, /* reset */ + (struct cb_ops *)0, /* driver operations */ + &i2o_bus_ops /* bus operations */ +}; + +/* + * Per IOP instance data maintained by the i2o nexus driver. + */ + +typedef struct iop_nexus_instance { + dev_info_t *dip; /* devinfo pointer */ + caddr_t iop_base_addr; /* base address of shared memory */ + int iop_state; /* state of IOP */ + off_t shared_memsize; /* size of shared memory */ + int iop_intr_pri; /* interrupt priority */ + ddi_acc_handle_t acc_handle; /* DDI access handle for shared mem */ + i2o_iop_handle_t i2o_iop_handle; /* IOP handle from the i2o_msg module */ + ddi_iblock_cookie_t iblock_cookie; + ddi_idevice_cookie_t idevice_cookie; + i2o_msg_trans_t i2o_msg_trans; +#ifdef I2O_DEBUG + uint_t intr_count; /* IOP interrupt counter */ +#endif +} iop_nexus_instance_t; + + +/* Function prototypes for local functions */ + +static uint_t i2o_intr(caddr_t); +static uint_t i2o_alloc_msg(i2o_nexus_handle_t handle); +static int i2o_send_msg(i2o_nexus_handle_t handle, uint_t mfa); +static uint_t i2o_recv_msg(i2o_nexus_handle_t handle); +static void i2o_disable_intr(i2o_nexus_handle_t handle); +static void i2o_enable_intr(i2o_nexus_handle_t handle); +static void i2o_free_msg(i2o_nexus_handle_t handle, uint_t mfa); +static void i2o_create_devinfo(iop_nexus_instance_t *iop); +#ifdef I2O_DEBUG +static void dump_exec_params_0001(iop_nexus_instance_t *iop); +void i2o_msg_reply(void *m, ddi_acc_handle_t acc_hdl); +#endif + +/* + * DMA attribute structure for I2O Spec version 1.5. + */ +static ddi_dma_attr_t i2o_dma_attr = { + DMA_ATTR_VERSION, /* version number */ + (uint64_t)0, /* low DMA address range */ + (uint64_t)0xFFFFFFFF, /* high DMA address range */ + (uint64_t)0x00FFFFFF, /* DMA counter register */ + 1, /* DMA address alignment */ + 1, /* DMA burstsizes */ + 1, /* min effective DMA size */ + (uint64_t)0xFFFFFFFF, /* max DMA xfer size */ + (uint64_t)0xFFFFFFFF, /* segment boundary */ + 0xFFFF, /* s/g length */ + 1, /* granularity of device */ + 0 /* Bus specific DMA flags */ +}; + + +/* local definitions for iop_state values */ +#define IOP_INIT 0 /* IOP is being initialized */ +#define IOP_ONLINE 1 /* IOP initialization is complete */ + + +/* Default interrupt priority for IOP interrupt */ +#define IOP_INTR_PRI_DEFAULT 5 + + +#ifdef I2O_DEBUG +int i2o_nexus_debug = 0; +#define DEBUGF(level, args) \ + { if (i2o_nexus_debug >= (level)) cmn_err args; } +#else +#define DEBUGF(level, args) /* nothing */ +#endif + + +/* + * Module linkage information for the kernel. + */ +static struct modldrv modldrv = { + &mod_driverops, + "Nexus for I2O Spec v1.5, driver %I%", + &i2o_dev_ops, +}; + + +/* + * Device attribute structure for I2O version 1.5. + * + * I2O data structures (whether it is in IOP's memory or host memory) + * are in Little Endian format. + */ +static ddi_device_acc_attr_t i2o_dev_acc_attr = { + DDI_DEVICE_ATTR_V0, + DDI_STRUCTURE_LE_ACC, /* devacc_attr_endian_flags for LE access */ + DDI_STRICTORDER_ACC /* devacc_attr_dataorder */ +}; + + +static struct modlinkage modlinkage = { + MODREV_1, + &modldrv, + NULL +}; + +static void *i2o_nexus_state; + +int +_init(void) +{ + int error; + + if ((error = ddi_soft_state_init(&i2o_nexus_state, + sizeof (struct iop_nexus_instance), 1)) != 0) + return (error); + + if ((error = mod_install(&modlinkage)) != 0) + ddi_soft_state_fini(&i2o_nexus_state); + + return (error); +} + +int +_fini(void) +{ + int error; + + if ((error = mod_remove(&modlinkage)) == 0) + ddi_soft_state_fini(&i2o_nexus_state); + + return (error); +} + +int +_info(struct modinfo *modinfop) +{ + return (mod_info(&modlinkage, modinfop)); +} + + +/* + * ********************************************************************** + * * bus_ops entry points * + * ********************************************************************** + */ + + +/* + * NOTE: THIS FUNCTION IS NOT APPLICABLE FOR I2O. RETURN ERROR. + */ +/*ARGSUSED*/ +static int +i2o_intr_op(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op, + ddi_intr_handle_impl_t *hdlp, void *result) +{ + return (DDI_FAILURE); +} + +static int +i2o_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr, + int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep) +{ + /* + * Adjust DMA attributes structure as per I2O Spec version 1.5. + */ + ddi_dma_attr_merge(attr, &i2o_dma_attr); + + return (ddi_dma_allochdl(dip, rdip, attr, waitfp, arg, handlep)); +} + +static int +i2o_bus_ctl(dev_info_t *dip, dev_info_t *rdip, + ddi_ctl_enum_t opt, void *a, void *v) +{ + char name[16]; + uint_t tid; + int error; + + switch (opt) { + case DDI_CTLOPS_INITCHILD: + tid = ddi_prop_get_int(DDI_DEV_T_ANY, (dev_info_t *)a, + DDI_PROP_DONTPASS, "i2o-device-id", -1); + if (tid == (uint_t)-1) + return (DDI_FAILURE); + (void) sprintf(name, "%x", tid); + error = impl_ddi_sunbus_initchild((dev_info_t *)a); + if (error != DDI_SUCCESS) + return (DDI_FAILURE); + ddi_set_name_addr((dev_info_t *)a, name); + return (DDI_SUCCESS); + + case DDI_CTLOPS_UNINITCHILD: + impl_ddi_sunbus_removechild(a); + return (DDI_SUCCESS); + + case DDI_CTLOPS_REPORTDEV: + { + cmn_err(CE_CONT, "?%s%d at %s%d: TID %s\n", + ddi_driver_name(rdip), ddi_get_instance(rdip), + ddi_driver_name(dip), ddi_get_instance(dip), + ddi_get_name_addr(rdip)); + + return (DDI_SUCCESS); + } + + /* + * These functions shouldn't be called by the OSMs. Return error. + */ + case DDI_CTLOPS_DMAPMAPC: + case DDI_CTLOPS_SIDDEV: + case DDI_CTLOPS_SLAVEONLY: + case DDI_CTLOPS_AFFINITY: + case DDI_CTLOPS_REGSIZE: + case DDI_CTLOPS_NREGS: + case DDI_CTLOPS_POKE: + case DDI_CTLOPS_PEEK: + return (DDI_FAILURE); + + default: + /* let the parent handle the rest */ + return (ddi_ctlops(dip, rdip, opt, a, v)); + } +} + +/* + * ********************************************************************** + * * dev_ops entry points * + * ********************************************************************** + */ + +/* + * Determine if the IOP is present. + */ +static int +i2o_probe(dev_info_t *dip) +{ + ddi_acc_handle_t handle; + uint8_t base_class, sub_class, prog_class; + + if (pci_config_setup(dip, &handle) != DDI_SUCCESS) + return (DDI_PROBE_FAILURE); + + base_class = pci_config_get8(handle, PCI_CONF_BASCLASS); + sub_class = pci_config_get8(handle, PCI_CONF_SUBCLASS); + prog_class = pci_config_get8(handle, PCI_CONF_PROGCLASS); + + pci_config_teardown(&handle); + + if ((base_class != PCI_I2O_BASE_CLASS) || + (sub_class != PCI_I2O_SUB_CLASS) || + (prog_class != PCI_I2O_PROG_CLASS1)) + + return (DDI_PROBE_FAILURE); + + return (DDI_PROBE_SUCCESS); +} + +/* + * attach(9E) + */ + +static int +i2o_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) +{ + iop_nexus_instance_t *iop = NULL; + ddi_acc_handle_t handle; + int nregs; + int csr; + uint32_t base_reg0; + int instance; + + if (cmd != DDI_ATTACH) + return (DDI_FAILURE); + + if (pci_config_setup(dip, &handle) != DDI_SUCCESS) + return (DDI_FAILURE); + + /* + * turn on Master Enable and Memory Access Enable bits. + */ + csr = pci_config_get32(handle, PCI_CONF_COMM); + pci_config_put32(handle, PCI_CONF_COMM, + csr | PCI_COMM_ME | PCI_COMM_MAE); + + base_reg0 = pci_config_get32(handle, PCI_CONF_BASE0); + + ASSERT((base_reg0 & PCI_BASE_SPACE_M) == 0); + + pci_config_teardown(&handle); + + /* + * Allocate iop_nexus_instance soft state structure for this + * IOP instance. + */ + instance = ddi_get_instance(dip); + if (ddi_soft_state_zalloc(i2o_nexus_state, instance) != DDI_SUCCESS) + return (DDI_FAILURE); + iop = (iop_nexus_instance_t *)ddi_get_soft_state(i2o_nexus_state, + instance); + + iop->dip = dip; + iop->iop_state = IOP_INIT; + + /* + * Map the device memory (i.e IOP's shared local memory). + * + * ISSUE: Mapping the whole shared memory (4 to 16M) may be too + * much. But, to map the pages that we really need it requires + * reading the inbound FIFO to find out the range of offsets used + * for allocating inbound message frames by the IOP. It is possible + * to find the range of MFAs and then map only those pages. But, + * this will bring up the following issues: + * + * 1. IOP reset may reallocate the message frames so the + * range may change. (Note: currently i2o_msg_iop_init() + * does IOP reset so it will be a problem.) + * 2. I2O Spec doesn't restrict the IOP allocating inbound + * message frames dynamically. + * 3. Reading the MFAs should be done when no other external + * agent (e.g other IOPs) is accessing the IOP. + * + * This issue is addressed by the I2O Spec version 2.0 where + * IOP gives additional parameters which gives us the information + * we need to map only the pages that have the MFAs. For now, we + * will map the whole thing. + */ + + if ((ddi_dev_nregs(dip, &nregs) != DDI_SUCCESS) || (nregs < 2) || + (ddi_dev_regsize(dip, 1, &iop->shared_memsize) != DDI_SUCCESS)) + goto cleanup; + + DEBUGF(1, (CE_CONT, "!i2o_attach: IOP shared memory size 0x%x", + (int)iop->shared_memsize)); + + if (ddi_regs_map_setup(dip, 1, &iop->iop_base_addr, 0, + iop->shared_memsize, &i2o_dev_acc_attr, + &iop->acc_handle) != DDI_SUCCESS) { + DEBUGF(1, (CE_CONT, "i2o_attach: ddi_regs_map_setup failed")); + goto cleanup; + } + + /* + * Initialize i2o_msg_trans data structure for i2o_msg module. + */ + iop->i2o_msg_trans.version = I2O_MSG_TRANS_VER; + iop->i2o_msg_trans.iop_base_addr = iop->iop_base_addr; + iop->i2o_msg_trans.iop_inbound_fifo_paddr = + (base_reg0 & PCI_BASE_M_ADDR_M) + PCI_IOP_INBOUND_FREELIST_FIFO; + iop->i2o_msg_trans.acc_handle = iop->acc_handle; + iop->i2o_msg_trans.nexus_handle = (i2o_nexus_handle_t)iop; + iop->i2o_msg_trans.iblock_cookie = iop->iblock_cookie; + iop->i2o_msg_trans.i2o_trans_msg_alloc = i2o_alloc_msg; + iop->i2o_msg_trans.i2o_trans_msg_send = i2o_send_msg; + iop->i2o_msg_trans.i2o_trans_msg_recv = i2o_recv_msg; + iop->i2o_msg_trans.i2o_trans_msg_freebuf = i2o_free_msg; + iop->i2o_msg_trans.i2o_trans_disable_intr = i2o_disable_intr; + iop->i2o_msg_trans.i2o_trans_enable_intr = i2o_enable_intr; + + /* Disable IOP interrupts */ + i2o_disable_intr((i2o_nexus_handle_t)iop); + + /* + * Register an interrupt handler for IOP interrupts. If the + * property 'iop_intr_pri' is set then use that otherwise + * set the priority to 5. + */ + iop->iop_intr_pri = ddi_prop_get_int(DDI_DEV_T_ANY, dip, + DDI_PROP_DONTPASS, "iop_intr_pri", IOP_INTR_PRI_DEFAULT); + + if (ddi_add_intr(dip, 0, &iop->iblock_cookie, &iop->idevice_cookie, + i2o_intr, (caddr_t)iop) != DDI_SUCCESS) + goto cleanup; + + /* + * Call i2o_msg_iop_init() to initialize the IOP. + */ + + cmn_err(CE_CONT, "\rI2O Nexus: Initializing IO Processor %d...", + instance); + + iop->i2o_iop_handle = i2o_msg_iop_init(dip, &iop->i2o_msg_trans); + + if (iop->i2o_iop_handle == NULL) { /* IOP Initialization failed */ + ddi_remove_intr(dip, 0, iop->iblock_cookie); + cmn_err(CE_CONT, "FAILED.\n"); + goto cleanup; + } + + cmn_err(CE_CONT, "done.\n"); + + /* Enable IOP interrupts now */ + i2o_enable_intr((i2o_nexus_handle_t)iop); + + iop->iop_state = IOP_ONLINE; /* now IOP is ready */ + + ddi_report_dev(dip); + +#ifdef I2O_DEBUG + if (i2o_nexus_debug >= 2) + dump_exec_params_0001(iop); +#endif + +#ifndef I2O_BOOT_SUPPORT + + /* + * Create the devinfo nodes for the I2O devices. + */ + i2o_create_devinfo(iop); + +#endif + return (DDI_SUCCESS); + +cleanup: + /* + * free up the allocated resources and return error. + */ + + if (iop->iop_base_addr != 0) + ddi_regs_map_free(&iop->acc_handle); + + /* free up the soft state structure for this instance */ + ddi_soft_state_free(i2o_nexus_state, instance); + + return (DDI_FAILURE); +} + +/* + * detach(9E) + */ + +static int +i2o_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) +{ + iop_nexus_instance_t *iop = NULL; + int instance; + + instance = ddi_get_instance(dip); + iop = (iop_nexus_instance_t *)ddi_get_soft_state(i2o_nexus_state, + instance); + + if (iop == NULL) + return (DDI_FAILURE); + + switch (cmd) { + case DDI_DETACH: + + /* reset the IOP */ + if (i2o_msg_iop_uninit(iop->i2o_iop_handle) != DDI_SUCCESS) + return (DDI_FAILURE); + + /* unregister the interrupt handler */ + ddi_remove_intr(dip, 0, iop->iblock_cookie); + + /* unmap the shared device memory */ + ddi_regs_map_free(&iop->acc_handle); + + /* free up the soft state structure for this instance */ + ddi_soft_state_free(i2o_nexus_state, instance); + + return (DDI_SUCCESS); + + case DDI_SUSPEND: /* XXX FIX IT LATER */ + case DDI_PM_SUSPEND: /* XXX FIX IT LATER */ + /* fall thru */ + + default: + return (DDI_FAILURE); + } +} + +/* + * IOP interrupt handler. + * + * Note: In the current I2O Spec (version 1.5) only Outbound PostList + * service interrupt is defined. So, this routine handles this + * interrupt. + * + * This function simply calls i2o_msg_process_reply_queue() to process + * the reply messages. It is assumed that the i2o_msg_process_reply_queue() + * will putback the processed messages into the freelist. + */ + +static uint_t +i2o_intr(caddr_t arg) +{ + register iop_nexus_instance_t *iop; + uint32_t intr_state; + uint32_t intr_mask; + + iop = (iop_nexus_instance_t *)arg; + + if (iop->iop_state != IOP_ONLINE) + return (DDI_INTR_UNCLAIMED); + + intr_state = ddi_get32(iop->acc_handle, + (uint32_t *)(iop->iop_base_addr + PCI_IOP_INTR_STATUS_REG)); + + intr_mask = ddi_get32(iop->acc_handle, + (uint32_t *)(iop->iop_base_addr + PCI_IOP_INTR_MASK_REG)); + + if (((intr_state & I2O_OUTBOUND_POSTLIST_SERVICE_INTR_MASK) == 0) || + ((intr_mask & I2O_OUTBOUND_POSTLIST_SERVICE_INTR_MASK) != 0)) + /* No interrupt from this IOP */ + return (DDI_INTR_UNCLAIMED); + + /* Let the I2O Message module process the reply message queue */ + i2o_msg_process_reply_queue(iop->i2o_iop_handle); + +#ifdef I2O_DEBUG + iop->intr_count++; /* debugging */ +#endif + + return (DDI_INTR_CLAIMED); +} + +/* + * *********************************************************************** + * ** Transport functions to support the I2O Message module ** + * ** ** + * ** NOTE: Locking for these functions are done within the I2O ** + * ** Message module. ** + * *********************************************************************** + */ + +/* + * Get an MFA from the Inbound FreeList FIFO. + */ +static uint_t +i2o_alloc_msg(i2o_nexus_handle_t handle) +{ + register iop_nexus_instance_t *iop; + + iop = (iop_nexus_instance_t *)handle; + + return (ddi_get32(iop->acc_handle, (uint32_t *)(iop->iop_base_addr + + PCI_IOP_INBOUND_FREELIST_FIFO))); +} + +/* + * Post the MFA to Inbound PostList FIFO. + */ +static int +i2o_send_msg(i2o_nexus_handle_t handle, uint_t mfa) +{ + register iop_nexus_instance_t *iop; + + iop = (iop_nexus_instance_t *)handle; + + if (mfa < iop->shared_memsize) { + ddi_put32(iop->acc_handle, (uint32_t *)(iop->iop_base_addr + + PCI_IOP_INBOUND_POSTLIST_FIFO), mfa); + + return (DDI_SUCCESS); + } + + return (DDI_FAILURE); /* invalid argument(s) */ +} + +/* + * Get the reply MFA from the Outbound PostList FIFO. + */ +static uint_t +i2o_recv_msg(i2o_nexus_handle_t handle) +{ + register iop_nexus_instance_t *iop; + + iop = (iop_nexus_instance_t *)handle; + + return (ddi_get32(iop->acc_handle, (uint32_t *)(iop->iop_base_addr + + PCI_IOP_OUTBOUND_POSTLIST_FIFO))); +} + +/* + * Return reply MFA to the Outbound FreeList FIFO. + */ +static void +i2o_free_msg(i2o_nexus_handle_t handle, uint_t mfa) +{ + register iop_nexus_instance_t *iop; + + iop = (iop_nexus_instance_t *)handle; + + ddi_put32(iop->acc_handle, (uint32_t *)(iop->iop_base_addr + + PCI_IOP_OUTBOUND_FREELIST_FIFO), mfa); +} + +/* + * Disable IOP hardware interrupts. Currently only bit 3 in the Interrupt + * Mask register is defined and it is for outbound postlist service + * interrupt. (See section 4.2.1.5). + */ + +static void +i2o_disable_intr(i2o_nexus_handle_t handle) +{ + register iop_nexus_instance_t *iop; + uint_t intr_mask; + + iop = (iop_nexus_instance_t *)handle; + + intr_mask = ddi_get32(iop->acc_handle, + (uint32_t *)(iop->iop_base_addr + PCI_IOP_INTR_MASK_REG)); + + ddi_put32(iop->acc_handle, + (uint32_t *)(iop->iop_base_addr + PCI_IOP_INTR_MASK_REG), + intr_mask | I2O_OUTBOUND_POSTLIST_SERVICE_INTR_MASK); +} + +/* + * Enable IOP hardware interrupts. Currently only bit 3 in the Interrupt + * Mask register is defined and it is for outbound postlist service + * interrupt. (See section 4.2.1.5). + */ + +static void +i2o_enable_intr(i2o_nexus_handle_t handle) +{ + register iop_nexus_instance_t *iop; + uint_t intr_mask; + + iop = (iop_nexus_instance_t *)handle; + + intr_mask = ddi_get32(iop->acc_handle, + (uint32_t *)(iop->iop_base_addr + PCI_IOP_INTR_MASK_REG)); + + ddi_put32(iop->acc_handle, (uint32_t *)(iop->iop_base_addr + + PCI_IOP_INTR_MASK_REG), + intr_mask & ~I2O_OUTBOUND_POSTLIST_SERVICE_INTR_MASK); +} + +#ifndef I2O_BOOT_SUPPORT + +/* + * Since we don't have boot support yet, we need to create the devinfo + * nodes for the I2O devices here. No devinfo nodes are created for + * SCSI Peripheral class devices. For adapter devices, if the adapter + * is host visible (HRT has this information) then there may be a + * devinfo node else where in the devinfo tree. For each host visible + * adapter device we need to prune any other devinfo nodes for this + * adapter in the system. + */ + +static void +i2o_create_devinfo(iop_nexus_instance_t *iop) +{ + i2o_lct_t *lct; + ddi_acc_handle_t acc_hdl; + uint_t nent; + uint_t local_tid; + uint_t user_tid; + uint_t class; + uint_t sub_class; + dev_info_t *cdip; + char *nodename, *compat_name, *dev_type; + int i; + + /* + * Step 1 + * + * Get HRT and look for any adapters that are present, assigned to + * IOP but not hidden. For each of those adapters we need to + * remove any devinfo nodes that may be present else where in + * devinfo tree. + */ + + /* + * For now, we assume that all adpaters that are controlled + * by the IOP are hidden from the host. This step can be + * implemented easily in the boot system (i.e devconf on x86) + * when that phase is implemented. + */ + + /* XXX DEFER IT FOR NOW XXX */ + + /* + * Step 2 + * + * Create the devinfo nodes for each I2O class device that + * is not claimed (i.e UserTID == 0xFFF) and is not of + * SCSI peripheral type. + */ + + i2o_msg_get_lct_info(iop->i2o_iop_handle, &lct, &acc_hdl); + nent = ((ddi_get16(acc_hdl, &lct->TableSize) << 2) - sizeof (i2o_lct_t) + + sizeof (i2o_lct_entry_t)) / sizeof (i2o_lct_entry_t); + + for (i = 0; i < nent; i++) { + + /* If the device is already claimed then continue */ + user_tid = get_lct_entry_UserTID(&lct->LCTEntry[i], acc_hdl); + if (user_tid != 0xFFF) + continue; + + class = get_lct_entry_Class(&lct->LCTEntry[i], acc_hdl); + sub_class = ddi_get32(acc_hdl, &lct->LCTEntry[i].SubClassInfo); + + switch (class) { + case I2O_CLASS_EXECUTIVE: + case I2O_CLASS_DDM: + continue; + + case I2O_CLASS_ATE_PORT: + case I2O_CLASS_ATE_PERIPHERAL: + case I2O_CLASS_FLOPPY_CONTROLLER: + case I2O_CLASS_FLOPPY_DEVICE: + case I2O_CLASS_SEQUENTIAL_STORAGE: + case I2O_CLASS_LAN: + case I2O_CLASS_WAN: + case I2O_CLASS_FIBRE_CHANNEL_PORT: + case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL: + /* For now, ingore these types */ + continue; + + case I2O_CLASS_SCSI_PERIPHERAL: + continue; + + case I2O_CLASS_RANDOM_BLOCK_STORAGE: + nodename = "disk"; + compat_name = "i2o_bs"; + dev_type = "block"; + break; + case I2O_CLASS_BUS_ADAPTER_PORT: + nodename = "adapter"; + compat_name = "i2o_scsi"; + /* + * sub_class should indicate the type of bus. + * XXX Check this with Symbios. + */ + if (sub_class == 0x3) + dev_type = "scsi-3"; + else if (sub_class == 0x2) + dev_type = "scsi-2"; + else + dev_type = "scsi"; + break; + default: + continue; + } + + local_tid = get_lct_entry_LocalTID(&lct->LCTEntry[i], acc_hdl); + + cdip = NULL; + + /* create the devinfo node */ + if (ndi_devi_alloc(iop->dip, nodename, + (pnode_t)DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) { + cmn_err(CE_WARN, + "i2o_create_devinfo: ndi_devi_alloc failed"); + goto fail; + } + + /* create the properties */ + + if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "i2o-device-id", + local_tid) != DDI_PROP_SUCCESS) + goto fail; + if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, "device-type", + dev_type) != DDI_PROP_SUCCESS) + goto fail; + if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, + "compatible", compat_name) != DDI_PROP_SUCCESS) + goto fail; + + /* now, attach the driver */ + (void) ndi_devi_online(cdip, NDI_ONLINE_ATTACH); + } + + return; + +fail: + if (cdip != NULL) { + (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, "i2o-device-id"); + (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, "compatible"); + (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, "device-type"); + if (ndi_devi_free(cdip) != NDI_SUCCESS) { + cmn_err(CE_WARN, + "i2o_create_devinfo: ndi_devi_free failed"); + } + } +} + +#endif + +#ifdef I2O_DEBUG + +static ddi_dma_attr_t i2o_dma_attr_contig = { + DMA_ATTR_VERSION, /* version number */ + (uint64_t)0, /* low DMA address range */ + (uint64_t)0xFFFFFFFF, /* high DMA address range */ + (uint64_t)0x00FFFFFF, /* DMA counter register */ + 1, /* DMA address alignment */ + 1, /* DMA burstsizes */ + 1, /* min effective DMA size */ + (uint64_t)0xFFFFFFFF, /* max DMA xfer size */ + (uint64_t)0xFFFFFFFF, /* segment boundary */ + 0x1, /* s/g length */ + 1, /* granularity of device */ + 0 /* Bus specific DMA flags */ +}; + +kmutex_t test_mutex; +kcondvar_t test_cv; +volatile int test_result; + +static void +dump_exec_params_0001(iop_nexus_instance_t *iop) +{ + ddi_dma_handle_t dma_handle = NULL; + ddi_acc_handle_t acc_hdl, acc_hdl2; + size_t real_length; + ddi_dma_cookie_t dma_cookie; + uint_t ncookies; + caddr_t buf = NULL; + uint32_t ops_block_size, results_block_size; + i2o_util_params_get_message_t *msgp; + i2o_sge_simple_element_t *sgl; + /* operations block info */ + i2o_param_operations_list_header_t *ops_block_head; + i2o_param_operation_all_template_t *ops_block; + /* scalar parameters */ + i2o_exec_iop_message_if_scalar_t *message_if; + i2o_msg_handle_t msg_handle; + + /* allocate a DMA handle */ + if (ddi_dma_alloc_handle(iop->dip, &i2o_dma_attr_contig, DDI_DMA_SLEEP, + NULL, &dma_handle) != DDI_SUCCESS) { + goto cleanup; + } + + ops_block_size = sizeof (*ops_block_head) + sizeof (*ops_block); + + results_block_size = + sizeof (i2o_param_results_list_header_t) + + sizeof (i2o_param_read_operation_result_t) + + sizeof (*message_if) + + sizeof (i2o_param_error_info_template_t); + + /* Allocate a buffer for operation block */ + if (ddi_dma_mem_alloc(dma_handle, ops_block_size + results_block_size, + &i2o_dev_acc_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, + &buf, &real_length, &acc_hdl) != DDI_SUCCESS) { + goto cleanup; + } + + bzero((caddr_t)buf, real_length); + + if (ddi_dma_addr_bind_handle(dma_handle, NULL, buf, + real_length, DDI_DMA_READ | DDI_DMA_STREAMING, DDI_DMA_SLEEP, + NULL, &dma_cookie, &ncookies) != DDI_SUCCESS) { + + DEBUGF(1, (CE_CONT, + "dump_exec_params_0001: cannot bind memory")); + goto cleanup; + } + + DEBUGF(1, (CE_CONT, + "dump_exec_params_0001: dma_bind (vaddr %p paddr %x length %x)", + (void *)buf, dma_cookie.dmac_address, + (int)dma_cookie.dmac_size)); + + ops_block_head = (i2o_param_operations_list_header_t *)buf; + ops_block = (i2o_param_operation_all_template_t *) + (buf + sizeof (*ops_block_head)); + + /* initialize the operations block header */ + ddi_put16(acc_hdl, &ops_block_head->OperationCount, 1); + + /* initialize operations block for group 0001 */ + ddi_put16(acc_hdl, &ops_block[0].Operation, + I2O_PARAMS_OPERATION_FIELD_GET); + ddi_put16(acc_hdl, &ops_block[0].GroupNumber, + I2O_EXEC_IOP_MESSAGE_IF_GROUP_NO); + ddi_put16(acc_hdl, &ops_block[0].FieldCount, -1); /* all fields */ + + /* allocate the message frame */ + if (i2o_msg_alloc(iop->i2o_iop_handle, I2O_MSG_SLEEP, NULL, + (void **)&msgp, &msg_handle, &acc_hdl2) != DDI_SUCCESS) { + DEBUGF(1, (CE_CONT, + "dump_exec_params_0001: i2o_msg_alloc failed")); + (void) ddi_dma_unbind_handle(dma_handle); + goto cleanup; + } + + /* construct the UtilParamsGet message */ + msgp->StdMessageFrame.VersionOffset = I2O_VERSION_11; + msgp->StdMessageFrame.MsgFlags = 0; + ddi_put16(acc_hdl2, &msgp->StdMessageFrame.MessageSize, + (sizeof (i2o_util_params_get_message_t) + + sizeof (i2o_sg_element_t)) >> 2); + put_msg_Function(&msgp->StdMessageFrame, I2O_UTIL_PARAMS_GET, acc_hdl2); + put_msg_InitiatorAddress(&msgp->StdMessageFrame, + I2O_HOST_TID, acc_hdl2); + put_msg_TargetAddress(&msgp->StdMessageFrame, + I2O_IOP_TID, acc_hdl2); + ddi_put32(acc_hdl2, + &msgp->StdMessageFrame.InitiatorContext.initiator_context_32bits, + (uint32_t)i2o_msg_reply); + + sgl = msgp->SGL.u1.Simple; + + put_flags_count_Flags(&sgl->FlagsCount, I2O_SGL_FLAGS_END_OF_BUFFER | + I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT, acc_hdl2); + put_flags_count_Count(&sgl->FlagsCount, ops_block_size, acc_hdl2); + ddi_put32(acc_hdl2, &sgl->PhysicalAddress, + (uint_t)dma_cookie.dmac_address); + + put_flags_count_Flags(&sgl[1].FlagsCount, + I2O_SGL_FLAGS_LAST_ELEMENT | + I2O_SGL_FLAGS_END_OF_BUFFER | + I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT, acc_hdl2); + put_flags_count_Count(&sgl[1].FlagsCount, + results_block_size, acc_hdl2); + ddi_put32(acc_hdl2, &sgl[1].PhysicalAddress, + (uint_t)dma_cookie.dmac_address + ops_block_size); + + mutex_init(&test_mutex, NULL, MUTEX_DRIVER, NULL); + cv_init(&test_cv, NULL, CV_DEFAULT, NULL); + + mutex_enter(&test_mutex); + + test_result = 0; + + /* send the message to the IOP */ + (void) i2o_msg_send(iop->i2o_iop_handle, (void *)msgp, msg_handle); + + /* wait for the reply */ + if (test_result == 0) + cv_wait(&test_cv, &test_mutex); + + mutex_exit(&test_mutex); + + (void) ddi_dma_unbind_handle(dma_handle); + + /* + * ************************************************************** + * Now, print all the parameters. + * ************************************************************** + */ + + /* group 0001h - Message Interface */ + + message_if = (i2o_exec_iop_message_if_scalar_t *) + (buf + ops_block_size + + sizeof (i2o_param_results_list_header_t) + + sizeof (i2o_param_read_operation_result_t)); + cmn_err(CE_CONT, + "?IOP Message Interface Parameters - Group 0001h:"); + cmn_err(CE_CONT, "?\tInboundFrameSize: %x\n", ddi_get32(acc_hdl, + &message_if->InboundFrameSize)); + cmn_err(CE_CONT, "?\tInboundSizeTarget: %x\n", ddi_get32(acc_hdl, + &message_if->InboundSizeTarget)); + cmn_err(CE_CONT, "?\tInboundMax: %x\n", ddi_get32(acc_hdl, + &message_if->InboundMax)); + cmn_err(CE_CONT, "?\tInboundTarget: %x\n", ddi_get32(acc_hdl, + &message_if->InboundTarget)); + cmn_err(CE_CONT, "?\tInboundPoolCount: %x\n", ddi_get32(acc_hdl, + &message_if->InboundPoolCount)); + cmn_err(CE_CONT, "?\tInboundCurrentFree: %x\n", ddi_get32(acc_hdl, + &message_if->InboundCurrentFree)); + cmn_err(CE_CONT, "?\tInboundCurrentPost: %x\n", ddi_get32(acc_hdl, + &message_if->InboundCurrentPost)); + cmn_err(CE_CONT, "?\tStaticCount: %x\n", ddi_get16(acc_hdl, + &message_if->StaticCount)); + cmn_err(CE_CONT, "?\tStaticInstanceCount: %x\n", ddi_get16(acc_hdl, + &message_if->StaticInstanceCount)); + cmn_err(CE_CONT, "?\tStaticLimit: %x\n", ddi_get16(acc_hdl, + &message_if->StaticLimit)); + cmn_err(CE_CONT, "?\tStaticInstanceLimit: %x\n", ddi_get16(acc_hdl, + &message_if->StaticInstanceLimit)); + cmn_err(CE_CONT, "?\tOutboundFrameSize: %x\n", ddi_get32(acc_hdl, + &message_if->OutboundFrameSize)); + cmn_err(CE_CONT, "?\tOutboundMax: %x\n", ddi_get32(acc_hdl, + &message_if->OutboundMax)); + cmn_err(CE_CONT, "?\tOutboundTarget: %x\n", ddi_get32(acc_hdl, + &message_if->OutboundMaxTarget)); + cmn_err(CE_CONT, "?\tOutboundCurrentFree: %x\n", ddi_get32(acc_hdl, + &message_if->OutboundCurrentFree)); + cmn_err(CE_CONT, "?\tInboundCurrentPost: %x\n", ddi_get32(acc_hdl, + &message_if->InboundCurrentPost)); + cmn_err(CE_CONT, "?\tInitCode: %x\n", message_if->InitCode); + +cleanup: + if (buf != NULL) + ddi_dma_mem_free(&acc_hdl); + + if (dma_handle != NULL) + ddi_dma_free_handle(&dma_handle); +} + +void +i2o_msg_reply(void *m, ddi_acc_handle_t acc_hdl) +{ + i2o_single_reply_message_frame_t *rmp; + + mutex_enter(&test_mutex); + + rmp = (i2o_single_reply_message_frame_t *)m; + if (rmp->ReqStatus != I2O_REPLY_STATUS_SUCCESS) { + cmn_err(CE_CONT, "i2o_msg_reply: Reply Message Frame:"); + cmn_err(CE_CONT, + "?Reply Message Frame (Function %x):", + get_msg_Function(&rmp->StdMessageFrame, acc_hdl)); + cmn_err(CE_CONT, + "?\tReqStatus: %x DetailedStatusCode %x\n", rmp->ReqStatus, + ddi_get16(acc_hdl, &rmp->DetailedStatusCode)); + } + + test_result = 1; + + cv_broadcast(&test_cv); + + mutex_exit(&test_mutex); +} +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/uts/common/io/i2o/pci_to_i2o.conf Wed Apr 18 11:32:14 2007 -0700 @@ -0,0 +1,42 @@ +# +# 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 (c) 1998 by Sun Microsystems, Inc. +# All rights reserved. +# + +#pragma ident "%Z%%M% %I% %E% SMI" + +# Configuration properties for the I2O Nexus driver. +# +# ob-msg-queue-length +# Specifies the number of outbound message frames to be allocated. +# The minimum is 16. Since the max. size is determined by the IOP +# the system will set this parameter upto that maximum. +# +# ob-msg-frame-size +# Specifies the size in bytes of the outbound message frame. The +# minimum size 64 bytes. +# + +ob-msg-frame-size=64 ob-msg-queue-length=128;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/uts/common/sys/i2o/i2oadptr.h Wed Apr 18 11:32:14 2007 -0700 @@ -0,0 +1,323 @@ +/* + * **************************************************************************** + * I2O SIG All rights reserved. + * + * These header files are provided, pursuant to your I2O SIG membership + * agreement, free of charge on an as-is basis without warranty of any kind, + * either express or implied, including but not limited to, implied warranties + * or merchantability and fitness for a particular purpose. I2O SIG does not + * warrant that this program will meet the user's requirements or that the + * operation of these programs will be uninterrupted or error-free. + * Acceptance and use of this program constitutes the user's understanding + * that he will have no recourse to I2O SIG for any actual or consequential + * damages including, but not limited to, loss profits arising out of use + * or inability to use this program. + * + * Member is permitted to create derivative works to this header-file program. + * However, all copies of the program and its derivative works must contain the + * I2O SIG copyright notice. + * + * **************************************************************************** + */ + +/* + * ************************************************************************** + * + * i2oadptr.h -- I2O Adapter Class Message defintion file + * + * This file contains information presented in Chapter 6 of + * the I2o Specification. + * + * *************************************************************************** + */ + +/* + * Copyright (c) 1998 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef _SYS_I2OADPTR_H +#define _SYS_I2OADPTR_H + +#pragma ident "%W% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#define I2OADPTR_REV 1_5_1 /* Header file revision string */ + +/* + * NOTES: See i2omsg.h for more info + */ + +#include <sys/i2o/i2omsg.h> /* Include the Base Message file */ +#include <sys/types.h> /* For system types defines */ + + + +/* + * BUS ADAPTER CLASS SPECIFIC FUNCTIONS + */ + +#define I2O_HBA_ADAPTER_RESET 0x85 +#define I2O_HBA_BUS_QUIESCE 0x8b +#define I2O_HBA_BUS_RESET 0x87 +#define I2O_HBA_BUS_SCAN 0x89 + + +/* + * Detailed Status Codes for HBA operations + * + * Note: + * The 16-bit Detailed Status Code field for HBA operations is divided + * into two separate 8-bit fields. The lower 8 bits are reserved. The + * upper 8 bits are used to report Adapter Status information. The + * definitions for these two fields, however, will be consistent with + * the standard reply message frame structure declaration, which treats + * this as a single 16-bit field. In addition, the values used will be + * consistent with the Adapter Status codes defined for the SCSI + * Peripheral class. Theses codes are based on CAM-1. In other words, + * these definitions are a subset of the SCSI peripheral class codes. + * Where applicable, "SCSI" has been removed from the definition. + * + */ + +#define I2O_HBA_DSC_MASK 0xFF00 + +#define I2O_HBA_DSC_SUCCESS 0x0000 +#define I2O_HBA_DSC_ADAPTER_BUSY 0x0500 +#define I2O_HBA_DSC_COMMAND_TIMEOUT 0x0B00 +#define I2O_HBA_DSC_COMPLETE_WITH_ERROR 0x0400 +#define I2O_HBA_DSC_FUNCTION_UNAVAILABLE 0x3A00 +#define I2O_HBA_DSC_NO_ADAPTER 0x1100 +#define I2O_HBA_DSC_PARITY_ERROR_FAILURE 0x0F00 +#define I2O_HBA_DSC_PATH_INVALID 0x0700 +#define I2O_HBA_DSC_PROVIDE_FAILURE 0x1600 +#define I2O_HBA_DSC_QUEUE_FROZEN 0x4000 +#define I2O_HBA_DSC_REQUEST_ABORTED 0x0200 +#define I2O_HBA_DSC_REQUEST_INVALID 0x0600 +#define I2O_HBA_DSC_REQUEST_LENGTH_ERROR 0x1500 +#define I2O_HBA_DSC_REQUEST_TERMINATED 0x1800 +#define I2O_HBA_DSC_RESOURCE_UNAVAILABLE 0x3400 +#define I2O_HBA_DSC_BUS_BUSY 0x3F00 +#define I2O_HBA_DSC_BUS_RESET 0x0E00 +#define I2O_HBA_DSC_ID_INVALID 0x3900 +#define I2O_HBA_DSC_SEQUENCE_FAILURE 0x1400 +#define I2O_HBA_DSC_UNABLE_TO_ABORT 0x0300 +#define I2O_HBA_DSC_UNABLE_TO_TERMINATE 0x0900 +#define I2O_HBA_DSC_UNACKNOWLEDGED_EVENT 0x3500 +#define I2O_HBA_DSC_UNEXPECTED_BUS_FREE 0x1300 + +/* + * Bus Adapter Parameter Groups + */ + +#define I2O_HBA_CONTROLLER_INFO_GROUP_NO 0x0000 +#define I2O_HBA_HISTORICAL_STATS_GROUP_NO 0x0100 +#define I2O_HBA_SCSI_CONTROLLER_INFO_GROUP_NO 0x0200 +#define I2O_HBA_SCSI_BUS_PORT_INFO_GROUP_NO 0x0201 +#define I2O_HBA_FCA_CONTROLLER_INFO_GROUP_NO 0x0300 +#define I2O_HBA_FCA_PORT_INFO_GROUP_NO 0x0301 + +/* + * - 0000h - HBA Controller Information Parameter Group + */ + +/* + * Bus Type + */ + +#define I2O_HBA_BUS_TYPE_GENERIC 0x00 +#define I2O_HBA_BUS_TYPE_SCSI 0x01 +#define I2O_HBA_BUS_TYPE_FCA 0x10 + +typedef struct i2o_hba_controller_info_scalar { + uint8_t BusType; + uint8_t BusState; + uint16_t Reserved2; + uint8_t BusName[12]; +} i2o_hba_controller_info_scalar_t; + +/* + * - 0100h - HBA Historical Stats Parameter Group + */ + +typedef struct i2o_hba_hist_stats_scalar { + uint32_t TimeLastPoweredUp; + uint32_t TimeLastReset; +} i2o_hba_hist_stats_scalar_t; + +/* + * - 0200h - HBA SCSI Controller Information Parameter Group + */ + +/* + * SCSI Type + */ + +#define I2O_SCSI_TYPE_UNKNOWN 0x00 +#define I2O_SCSI_TYPE_SCSI_1 0x01 +#define I2O_SCSI_TYPE_SCSI_2 0x02 +#define I2O_SCSI_TYPE_SCSI_3 0x03 + +/* + * Protection Management + */ + +#define I2O_SCSI_PORT_PROT_OTHER 0x00 +#define I2O_SCSI_PORT_PROT_UNKNOWN 0x01 +#define I2O_SCSI_PORT_PROT_UNPROTECTED 0x02 +#define I2O_SCSI_PORT_PROT_PROTECTED 0x03 +#define I2O_SCSI_PORT_PROT_SCC 0x04 + +/* + * Settings + */ + +#define I2O_SCSI_PORT_PARITY_FLAG 0x01 +#define I2O_SCSI_PORT_PARITY_DISABLED 0x00 +#define I2O_SCSI_PORT_PARITY_ENABLED 0x01 + +#define I2O_SCSI_PORT_SCAN_ORDER_FLAG 0x02 +#define I2O_SCSI_PORT_SCAN_LOW_TO_HIGH 0x00 +#define I2O_SCSI_PORT_SCAN_HIGH_TO_LOW 0x02 + +#define I2O_SCSI_PORT_IID_FLAG 0x04 +#define I2O_SCSI_PORT_IID_DEFAULT 0x00 +#define I2O_SCSI_PORT_IID_SPECIFIED 0x04 + +#define I2O_SCSI_PORT_SCAM_FLAG 0x08 +#define I2O_SCSI_PORT_SCAM_DISABLED 0x00 +#define I2O_SCSI_PORT_SCAM_ENABLED 0x08 + +#define I2O_SCSI_PORT_TYPE_FLAG 0x80 +#define I2O_SCSI_PORT_TYPE_PARALLEL 0x00 +#define I2O_SCSI_PORT_TYPE_SERIAL 0x80 + +typedef struct i2o_hba_scsi_controller_info_scalar { + uint8_t SCSIType; + uint8_t ProtectionManagement; + uint8_t Settings; + uint8_t Reserved1; + uint32_t InitiatorID; + uint64_t ScanLun0Only; + uint16_t DisableDevice; + uint8_t MaxOffset; + uint8_t MaxDataWidth; + uint64_t MaxSyncRate; +} i2o_hba_scsi_controller_info_scalar_t; + +/* + * - 0201h - HBA SCSI Bus Port Information Parameter Group + */ + +/* + * NOTE: Refer to the SCSI Peripheral Class Bus Port Information + * Parameter Group field definitions for HBA SCSI Bus Port + * field definitions. + */ + +typedef struct i2o_hba_scsi_bus_port_info_scalar { + uint8_t PhysicalInterface; + uint8_t ElectricalInterface; + uint8_t Isochronous; + uint8_t ConnectorType; + uint8_t ConnectorGender; + uint8_t Reserved1; + uint16_t Reserved2; + uint32_t MaxNumberDevices; + uint32_t DeviceIdBegin; + uint32_t DeviceIdEnd; + uint8_t LunBegin[8]; + uint8_t LunEnd[8]; +} i2o_hba_scsi_bus_port_info_scalar_t; + +/* + * - 0300h - HBA FCA Controller Information Parameters Group defines + */ + +/* + * SCSI Type + */ + +#define I2O_FCA_TYPE_UNKNOWN 0x00 +#define I2O_FCA_TYPE_FCAL 0x01 + +typedef struct i2o_hba_fca_controller_info_scalar { + uint8_t FcaType; + uint8_t Reserved1; + uint16_t Reserved2; +} i2o_hba_fca_controller_info_scalar_t; + +/* + * - 0301h - HBA FCA Port Information Parameters Group defines + */ + +typedef struct i2o_hba_fca_port_info_scalar { + uint32_t Reserved4; +} i2o_hba_fca_port_info_scalar_t; + +/* + * I2O BUS ADAPTER CLASS SPECIFIC MESSAGE DEFINITIONS + */ + +/* + * I2O Bus Adapter Class Reply Message Frame + */ + +typedef struct i2o_hba_reply_message_frame { + i2o_single_reply_message_frame_t StdReplyFrame; +} i2o_hba_reply_message_frame_t; + +/* + * I2O HBA Adapter Reset Message Frame + */ + +typedef struct i2o_hba_adapter_reset_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; +} i2o_hba_adapter_reset_message_t; + +/* + * I2O HBA Bus Quiesce Message Frame + */ + +typedef uint32_t i2o_hbq_flags_t; + +#define I2O_HBQ_FLAG_NORMAL 0x0000 +#define I2O_HBQ_FLAG_QUIESCE 0x0001 + +typedef struct i2o_hba_bus_quiesce_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + i2o_hbq_flags_t Flags; +} i2o_hba_bus_quiesce_message_t; + +/* + * I2O HBA Bus Reset Message Frame + */ + +typedef struct i2o_hba_bus_reset_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; +} i2o_hba_bus_reset_message_t; + +/* + * I2O HBA Bus Scan Message Frame + */ + +/* + * NOTE: SCSI-2 8-bit scalar LUN goes into offset 1 of Lun arrays + */ + +typedef struct i2o_hba_bus_scan_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; +} i2o_hba_bus_scan_message_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_I2OADPTR_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/uts/common/sys/i2o/i2obscsi.h Wed Apr 18 11:32:14 2007 -0700 @@ -0,0 +1,400 @@ +/* + * ***************************************************************************** + * I2O SIG All rights reserved. + * + * These header files are provided, pursuant to your I2O SIG membership + * agreement, free of charge on an as-is basis without warranty of any kind, + * either express or implied, including but not limited to, implied warranties + * or merchantability and fitness for a particular purpose. I2O SIG does not + * warrant that this program will meet the user's requirements or that the + * operation of these programs will be uninterrupted or error-free. + * Acceptance and use of this program constitutes the user's understanding + * that he will have no recourse to I2O SIG for any actual or consequential + * damages including, but not limited to, loss profits arising out of use + * or inability to use this program. + * + * Member is permitted to create derivative works to this header-file program. + * However, all copies of the program and its derivative works must contain the + * I2O SIG copyright notice. + * + * ***************************************************************************** + */ + +/* + * *************************************************************************** + * + * I2OBSCSI.h -- I2O Base SCSI Device Class Message defintion file + * + * This file contains information presented in Chapter 6, Section 6 & 7 of + * the I2O Specification. + * + * *************************************************************************** + */ + +/* + * Copyright (c) 1998 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef _SYS_I2OBSCSI_H +#define _SYS_I2OBSCSI_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#define I2OBSCSI_REV 1_5_1 /* Header file revision string */ + +/* + * NOTES: See i2omsg.h for more info + */ + +#include <sys/i2o/i2omsg.h> /* Include the Base Message file */ +#include <sys/types.h> /* For system types defined */ + +/* + * SCSI Peripheral Class specific functions + * + * Although the names are SCSI Peripheral class specific, the values + * assigned are common with other classes when applicable. + */ + +#define I2O_SCSI_DEVICE_RESET 0x27 +#define I2O_SCSI_SCB_ABORT 0x83 +#define I2O_SCSI_SCB_EXEC 0x81 + +/* + * Detailed Status Codes for SCSI operations + * + * The 16-bit Detailed Status Code field for SCSI operations is divided + * into two separate 8-bit fields. The lower 8 bits are used to report + * Device Status information. The upper 8 bits are used to report + * Adapter Status information. The definitions for these two fields, + * however, will be consistent with the standard reply message frame + * structure declaration, which treats this as a single 16-bit field. + */ + + +/* + * SCSI Device Completion Status Codes (defined by SCSI-2/3) + */ + +#define I2O_SCSI_DEVICE_DSC_MASK 0x00FF + +#define I2O_SCSI_DSC_SUCCESS 0x0000 +#define I2O_SCSI_DSC_CHECK_CONDITION 0x0002 +#define I2O_SCSI_DSC_BUSY 0x0008 +#define I2O_SCSI_DSC_RESERVATION_CONFLICT 0x0018 +#define I2O_SCSI_DSC_COMMAND_TERMINATED 0x0022 +#define I2O_SCSI_DSC_TASK_SET_FULL 0x0028 +#define I2O_SCSI_DSC_ACA_ACTIVE 0x0030 + +/* + * SCSI Adapter Status Codes (based on CAM-1) + */ + +#define I2O_SCSI_HBA_DSC_MASK 0xFF00 + +#define I2O_SCSI_HBA_DSC_SUCCESS 0x0000 + +#define I2O_SCSI_HBA_DSC_REQUEST_ABORTED 0x0200 +#define I2O_SCSI_HBA_DSC_UNABLE_TO_ABORT 0x0300 +#define I2O_SCSI_HBA_DSC_COMPLETE_WITH_ERROR 0x0400 +#define I2O_SCSI_HBA_DSC_ADAPTER_BUSY 0x0500 +#define I2O_SCSI_HBA_DSC_REQUEST_INVALID 0x0600 +#define I2O_SCSI_HBA_DSC_PATH_INVALID 0x0700 +#define I2O_SCSI_HBA_DSC_DEVICE_NOT_PRESENT 0x0800 +#define I2O_SCSI_HBA_DSC_UNABLE_TO_TERMINATE 0x0900 +#define I2O_SCSI_HBA_DSC_SELECTION_TIMEOUT 0x0A00 +#define I2O_SCSI_HBA_DSC_COMMAND_TIMEOUT 0x0B00 + +#define I2O_SCSI_HBA_DSC_MR_MESSAGE_RECEIVED 0x0D00 +#define I2O_SCSI_HBA_DSC_SCSI_BUS_RESET 0x0E00 +#define I2O_SCSI_HBA_DSC_PARITY_ERROR_FAILURE 0x0F00 +#define I2O_SCSI_HBA_DSC_AUTOSENSE_FAILED 0x1000 +#define I2O_SCSI_HBA_DSC_NO_ADAPTER 0x1100 +#define I2O_SCSI_HBA_DSC_DATA_OVERRUN 0x1200 +#define I2O_SCSI_HBA_DSC_UNEXPECTED_BUS_FREE 0x1300 +#define I2O_SCSI_HBA_DSC_SEQUENCE_FAILURE 0x1400 +#define I2O_SCSI_HBA_DSC_REQUEST_LENGTH_ERROR 0x1500 +#define I2O_SCSI_HBA_DSC_PROVIDE_FAILURE 0x1600 +#define I2O_SCSI_HBA_DSC_BDR_MESSAGE_SENT 0x1700 +#define I2O_SCSI_HBA_DSC_REQUEST_TERMINATED 0x1800 + +#define I2O_SCSI_HBA_DSC_IDE_MESSAGE_SENT 0x3300 +#define I2O_SCSI_HBA_DSC_RESOURCE_UNAVAILABLE 0x3400 +#define I2O_SCSI_HBA_DSC_UNACKNOWLEDGED_EVENT 0x3500 +#define I2O_SCSI_HBA_DSC_MESSAGE_RECEIVED 0x3600 +#define I2O_SCSI_HBA_DSC_INVALID_CDB 0x3700 +#define I2O_SCSI_HBA_DSC_LUN_INVALID 0x3800 +#define I2O_SCSI_HBA_DSC_SCSI_TID_INVALID 0x3900 +#define I2O_SCSI_HBA_DSC_FUNCTION_UNAVAILABLE 0x3A00 +#define I2O_SCSI_HBA_DSC_NO_NEXUS 0x3B00 +#define I2O_SCSI_HBA_DSC_SCSI_IID_INVALID 0x3C00 +#define I2O_SCSI_HBA_DSC_CDB_RECEIVED 0x3D00 +#define I2O_SCSI_HBA_DSC_LUN_ALREADY_ENABLED 0x3E00 +#define I2O_SCSI_HBA_DSC_BUS_BUSY 0x3F00 + +#define I2O_SCSI_HBA_DSC_QUEUE_FROZEN 0x4000 + +/* + * SCSI Peripheral Device Parameter Groups + */ + +/* + * SCSI Configuration and Operating Structures and Defines + */ + +#define I2O_SCSI_DEVICE_INFO_GROUP_NO 0x0000 +#define I2O_SCSI_DEVICE_BUS_PORT_INFO_GROUP_NO 0x0001 + +/* + * - 0000h - SCSI Device Information Parameters Group defines + */ + +/* + * Device Type + */ + +#define I2O_SCSI_DEVICE_TYPE_DIRECT 0x00 +#define I2O_SCSI_DEVICE_TYPE_SEQUENTIAL 0x01 +#define I2O_SCSI_DEVICE_TYPE_PRINTER 0x02 +#define I2O_SCSI_DEVICE_TYPE_PROCESSOR 0x03 +#define I2O_SCSI_DEVICE_TYPE_WORM 0x04 +#define I2O_SCSI_DEVICE_TYPE_CDROM 0x05 +#define I2O_SCSI_DEVICE_TYPE_SCANNER 0x06 +#define I2O_SCSI_DEVICE_TYPE_OPTICAL 0x07 +#define I2O_SCSI_DEVICE_TYPE_MEDIA_CHANGER 0x08 +#define I2O_SCSI_DEVICE_TYPE_COMM 0x09 +#define I2O_SCSI_DEVICE_GRAPHICS_1 0x0A +#define I2O_SCSI_DEVICE_GRAPHICS_2 0x0B +#define I2O_SCSI_DEVICE_TYPE_ARRAY_CONT 0x0C +#define I2O_SCSI_DEVICE_TYPE_UNKNOWN 0x1F + +/* + * Flags + */ + +#define I2O_SCSI_PERIPHERAL_TYPE_FLAG 0x01 +#define I2O_SCSI_PERIPHERAL_TYPE_PARALLEL 0x00 +#define I2O_SCSI_PERIPHERAL_TYPE_SERIAL 0x01 + +#define I2O_SCSI_RESERVED_FLAG 0x02 + +#define I2O_SCSI_DISCONNECT_FLAG 0x04 +#define I2O_SCSI_DISABLE_DISCONNECT 0x00 +#define I2O_SCSI_ENABLE_DISCONNECT 0x04 + +#define I2O_SCSI_MODE_MASK 0x18 +#define I2O_SCSI_MODE_SET_DATA 0x00 +#define I2O_SCSI_MODE_SET_DEFAULT 0x08 +#define I2O_SCSI_MODE_SET_SAFEST 0x10 + +#define I2O_SCSI_DATA_WIDTH_MASK 0x60 +#define I2O_SCSI_DATA_WIDTH_8 0x00 +#define I2O_SCSI_DATA_WIDTH_16 0x20 +#define I2O_SCSI_DATA_WIDTH_32 0x40 + +#define I2O_SCSI_SYNC_NEGOTIATION_FLAG 0x80 +#define I2O_SCSI_DISABLE_SYNC_NEGOTIATION 0x00 +#define I2O_SCSI_ENABLE_SYNC_NEGOTIATION 0x80 + +/* + * - 0001h - SCSI Device Bus Port Info Parameters Group defines + */ + +/* + * Physical + */ + +#define I2O_SCSI_PORT_PHYS_OTHER 0x01 +#define I2O_SCSI_PORT_PHYS_UNKNOWN 0x02 +#define I2O_SCSI_PORT_PHYS_PARALLEL 0x03 +#define I2O_SCSI_PORT_PHYS_FIBRE_CHANNEL 0x04 +#define I2O_SCSI_PORT_PHYS_SERIAL_P1394 0x05 +#define I2O_SCSI_PORT_PHYS_SERIAL_SSA 0x06 + +/* + * Electrical + */ + +#define I2O_SCSI_PORT_ELEC_OTHER 0x01 +#define I2O_SCSI_PORT_ELEC_UNKNOWN 0x02 +#define I2O_SCSI_PORT_ELEC_SINGLE_ENDED 0x03 +#define I2O_SCSI_PORT_ELEC_DIFFERENTIAL 0x04 +#define I2O_SCSI_PORT_ELEC_LOW_VOLT_DIFF 0x05 +#define I2O_SCSI_PORT_ELEC_OPTICAL 0x06 + +/* + * Isochronous + */ + +#define I2O_SCSI_PORT_ISOC_NO 0x00 +#define I2O_SCSI_PORT_ISOC_YES 0x01 +#define I2O_SCSI_PORT_ISOC_UNKNOWN 0x02 + +/* + * Connector Type + */ + +#define I2O_SCSI_PORT_CONN_OTHER 0x01 +#define I2O_SCSI_PORT_CONN_UNKNOWN 0x02 +#define I2O_SCSI_PORT_CONN_NONE 0x03 +#define I2O_SCSI_PORT_CONN_SHIELDED_A_HD 0x04 +#define I2O_SCSI_PORT_CONN_UNSHIELDED_A_HD 0x05 +#define I2O_SCSI_PORT_CONN_SHIELDED_A_LD 0x06 +#define I2O_SCSI_PORT_CONN_UNSHIELDED_A_LD 0x07 +#define I2O_SCSI_PORT_CONN_SHIELDED_P_HD 0x08 +#define I2O_SCSI_PORT_CONN_UNSHIELDED_P_HD 0x09 +#define I2O_SCSI_PORT_CONN_SCA_I 0x0A +#define I2O_SCSI_PORT_CONN_SCA_II 0x0B +#define I2O_SCSI_PORT_CONN_FC_DB9 0x0C +#define I2O_SCSI_PORT_CONN_FC_FIBRE 0x0D +#define I2O_SCSI_PORT_CONN_FC_SCA_II_40 0x0E +#define I2O_SCSI_PORT_CONN_FC_SCA_II_20 0x0F +#define I2O_SCSI_PORT_CONN_FC_BNC 0x10 + +/* + * Connector Gender + */ + +#define I2O_SCSI_PORT_CONN_GENDER_OTHER 0x01 +#define I2O_SCSI_PORT_CONN_GENDER_UNKOWN 0x02 +#define I2O_SCSI_PORT_CONN_GENDER_FEMALE 0x03 +#define I2O_SCSI_PORT_CONN_GENDER_MALE 0x04 + + +/* + * SCSI Device Group 0000h - Device Information Parameter Group + */ + +typedef struct i2o_scsi_device_info_scalar { + uint8_t DeviceType; + uint8_t Flags; + uint16_t Reserved2; + uint32_t Identifier; + uint8_t LunInfo[8]; /* SCSI2 8-bit scalar LUN goes into */ + /* offset 1 */ + uint32_t QueueDepth; + uint8_t Reserved1a; + uint8_t NegOffset; + uint8_t NegDataWidth; + uint8_t Reserved1b; + uint64_t NegSyncRate; +} i2o_scsi_device_info_scalar_t; + +/* + * SCSI Device Group 0001h - Bus Port Information Parameter Group + */ + +typedef struct i2o_scsi_bus_port_info_scalar { + uint8_t PhysicalInterface; + uint8_t ElectricalInterface; + uint8_t Isochronous; + uint8_t ConnectorType; + uint8_t ConnectorGender; + uint8_t Reserved1; + uint16_t Reserved2; + uint32_t MaxNumberDevices; +} i2o_scsi_bus_port_info_scalar_t; + +/* + * I2O SCSI Peripheral Event Indicator Assignment + */ + +#define I2O_SCSI_EVENT_SCSI_SMART 0x00000010 + +/* + * SCSI Peripheral Class Specific Message Definitions + */ + +/* + * I2O SCSI Peripheral Successful Completion Reply Message Frame + */ + +typedef struct i2o_scsi_success_reply_message_frame { + i2o_single_reply_message_frame_t StdReplyFrame; + uint32_t TransferCount; +} i2o_scsi_success_reply_message_frame_t; + + + +/* + * I2O SCSI Peripheral Error Report Reply Message Frame + */ + +#define I2O_SCSI_SENSE_DATA_SZ 40 + +typedef struct i2o_scsi_error_reply_message_frame { + i2o_single_reply_message_frame_t StdReplyFrame; + uint32_t TransferCount; + uint32_t AutoSenseTransferCount; + uint8_t SenseData[I2O_SCSI_SENSE_DATA_SZ]; +} i2o_scsi_error_reply_message_frame_t; + + + +/* + * I2O SCSI Device Reset Message Frame + */ + +typedef struct i2o_scsi_device_reset_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; +} i2o_scsi_device_reset_message_t; + + + +/* + * I2O SCSI Control Block Abort Message Frame + */ + +typedef struct i2o_scsi_scb_abort_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + i2o_transaction_context_t TransactionContextToAbort; +} i2o_scsi_scb_abort_message_t; + +/* + * I2O SCSI Control Block Execute Message Frame + */ + +#define I2O_SCSI_CDB_LENGTH 16 + +#define I2O_SCB_FLAG_XFER_DIR_MASK 0xC000 +#define I2O_SCB_FLAG_NO_DATA_XFER 0x0000 +#define I2O_SCB_FLAG_XFER_FROM_DEVICE 0x4000 +#define I2O_SCB_FLAG_XFER_TO_DEVICE 0x8000 + +#define I2O_SCB_FLAG_ENABLE_DISCONNECT 0x2000 + +#define I2O_SCB_FLAG_TAG_TYPE_MASK 0x0380 +#define I2O_SCB_FLAG_NO_TAG_QUEUEING 0x0000 +#define I2O_SCB_FLAG_SIMPLE_QUEUE_TAG 0x0080 +#define I2O_SCB_FLAG_HEAD_QUEUE_TAG 0x0100 +#define I2O_SCB_FLAG_ORDERED_QUEUE_TAG 0x0180 +#define I2O_SCB_FLAG_ACA_QUEUE_TAG 0x0200 + +#define I2O_SCB_FLAG_AUTOSENSE_MASK 0x0060 +#define I2O_SCB_FLAG_DISABLE_AUTOSENSE 0x0000 +#define I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE 0x0020 +#define I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER 0x0060 + +typedef struct i2o_scsi_scb_execute_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint8_t CDBLength; + uint8_t Reserved; + uint16_t SCBFlags; + uint8_t CDB[I2O_SCSI_CDB_LENGTH]; + uint32_t ByteCount; + i2o_sg_element_t SGL; +} i2o_scsi_scb_execute_message_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_I2OBSCSI_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/uts/common/sys/i2o/i2oexec.h Wed Apr 18 11:32:14 2007 -0700 @@ -0,0 +1,2478 @@ +/* + * ***************************************************************************** + * + * All software on this website is made available under the following terms and + * conditions. By downloading this software, you agree to abide by these terms + * and conditions with respect to this software. + * + * I2O SIG All rights reserved. + * + * These header files are provided, pursuant to your I2O SIG membership + * agreement, free of charge on an as-is basis without warranty of any kind, + * either express or implied, including but not limited to, implied warranties + * or merchantability and fitness for a particular purpose. I2O SIG does not + * warrant that this program will meet the user's requirements or that the + * operation of these programs will be uninterrupted or error-free. + * Acceptance and use of this program constitutes the user's understanding + * that he will have no recourse to I2O SIG for any actual or consequential + * damages including, but not limited to, loss profits arising out of use + * or inability to use this program. + * + * Member is permitted to create derivative works to this header-file program. + * However, all copies of the program and its derivative works must contain the + * I2O SIG copyright notice. + * + * ***************************************************************************** + */ + +/* + * ******************************************************************** + * I2OExec.h -- I2O Executive Class Message definition file + * + * This file contains information presented in Chapter 4 of the I2O(tm) + * Specification. + * ******************************************************************** + */ + +/* + * Copyright (c) 1998 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef _SYS_I2OEXEC_H +#define _SYS_I2OEXEC_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/i2o/i2omsg.h> /* the Base Message file */ +#include <sys/i2o/i2outil.h> +#include <sys/types.h> + + +#define I2OEXEC_REV 1_5_4 /* I2OExec header file revision string */ + + +/* + * **************************************************************************** + * NOTES: + * + * Gets, reads, receives, etc. are all even numbered functions. + * Sets, writes, sends, etc. are all odd numbered functions. + * Functions that both send and receive data can be either but an attempt + * is made to use the function number that indicates the greater transfer + * amount. Functions that do not send or receive data use odd function + * numbers. + * + * Some functions are synonyms like read, receive and send, write. + * + * All common functions will have a code of less than 0x80. + * Unique functions to a class will start at 0x80. + * Executive Functions start at 0xA0. + * + * Utility Message function codes range from 0 - 0x1f + * Base Message function codes range from 0x20 - 0xfe + * Private Message function code is 0xff. + * ***************************************************************************** + */ + +/* I2O Executive Function Codes. */ + +#define I2O_EXEC_ADAPTER_ASSIGN 0xB3 +#define I2O_EXEC_ADAPTER_READ 0xB2 +#define I2O_EXEC_ADAPTER_RELEASE 0xB5 +#define I2O_EXEC_BIOS_INFO_SET 0xA5 +#define I2O_EXEC_BOOT_DEVICE_SET 0xA7 +#define I2O_EXEC_CONFIG_VALIDATE 0xBB +#define I2O_EXEC_CONN_SETUP 0xCA +#define I2O_EXEC_DDM_DESTROY 0xB1 +#define I2O_EXEC_DDM_ENABLE 0xD5 +#define I2O_EXEC_DDM_QUIESCE 0xC7 +#define I2O_EXEC_DDM_RESET 0xD9 +#define I2O_EXEC_DDM_SUSPEND 0xAF +#define I2O_EXEC_DEVICE_ASSIGN 0xB7 +#define I2O_EXEC_DEVICE_RELEASE 0xB9 +#define I2O_EXEC_HRT_GET 0xA8 +#define I2O_EXEC_IOP_CLEAR 0xBE +#define I2O_EXEC_IOP_CONNECT 0xC9 +#define I2O_EXEC_IOP_RESET 0xBD +#define I2O_EXEC_LCT_NOTIFY 0xA2 +#define I2O_EXEC_OUTBOUND_INIT 0xA1 +#define I2O_EXEC_PATH_ENABLE 0xD3 +#define I2O_EXEC_PATH_QUIESCE 0xC5 +#define I2O_EXEC_PATH_RESET 0xD7 +#define I2O_EXEC_STATIC_MF_CREATE 0xDD +#define I2O_EXEC_STATIC_MF_RELEASE 0xDF +#define I2O_EXEC_STATUS_GET 0xA0 +#define I2O_EXEC_SW_DOWNLOAD 0xA9 +#define I2O_EXEC_SW_UPLOAD 0xAB +#define I2O_EXEC_SW_REMOVE 0xAD +#define I2O_EXEC_SYS_ENABLE 0xD1 +#define I2O_EXEC_SYS_MODIFY 0xC1 +#define I2O_EXEC_SYS_QUIESCE 0xC3 +#define I2O_EXEC_SYS_TAB_SET 0xA3 + + +/* I2O Get Status State values */ + +#define I2O_IOP_STATE_INITIALIZING 0x01 +#define I2O_IOP_STATE_RESET 0x02 +#define I2O_IOP_STATE_HOLD 0x04 +#define I2O_IOP_STATE_READY 0x05 +#define I2O_IOP_STATE_OPERATIONAL 0x08 +#define I2O_IOP_STATE_FAILED 0x10 +#define I2O_IOP_STATE_FAULTED 0x11 + + +/* Event Indicator Assignments for the Executive Class. */ + +#define I2O_EVENT_IND_RESOURCE_LIMIT 0x00000001 +#define I2O_EVENT_IND_CONNECTION_FAIL 0x00000002 +#define I2O_EVENT_IND_ADAPTER_FAULT 0x00000004 +#define I2O_EVENT_IND_POWER_FAIL 0x00000008 +#define I2O_EVENT_IND_RESET_PENDING 0x00000010 +#define I2O_EVENT_IND_RESET_IMMINENT 0x00000020 +#define I2O_EVENT_IND_HARDWARE_FAIL 0x00000040 +#define I2O_EVENT_IND_XCT_CHANGE 0x00000080 +#define I2O_EVENT_IND_NEW_LCT_ENTRY 0x00000100 +#define I2O_EVENT_IND_MODIFIED_LCT 0x00000200 +#define I2O_EVENT_IND_DDM_AVAILABILITY 0x00000400 + +/* Resource Limit Event Data */ + +#define I2O_EVENT_RESOURCE_LIMIT_LOW_MEMORY 0x00000001 +#define I2O_EVENT_RESOURCE_LIMIT_INBOUND_POOL_LOW 0x00000002 +#define I2O_EVENT_RESOURCE_LIMIT_OUTBOUND_POOL_LOW 0x00000004 + +/* Connection Fail Event Data */ + +#define I2O_EVENT_CONNECTION_FAIL_REPOND_NORMAL 0x00000000 +#define I2O_EVENT_CONNECTION_FAIL_NOT_REPONDING 0x00000001 +#define I2O_EVENT_CONNECTION_FAIL_NO_AVAILABLE_FRAMES 0x00000002 + +/* Reset Pending Event Data */ + +#define I2O_EVENT_RESET_PENDING_POWER_LOSS 0x00000001 +#define I2O_EVENT_RESET_PENDING_CODE_VIOLATION 0x00000002 + +/* Reset Imminent Event Data */ + +#define I2O_EVENT_RESET_IMMINENT_UNKNOWN_CAUSE 0x00000000 +#define I2O_EVENT_RESET_IMMINENT_POWER_LOSS 0x00000001 +#define I2O_EVENT_RESET_IMMINENT_CODE_VIOLATION 0x00000002 +#define I2O_EVENT_RESET_IMMINENT_PARITY_ERROR 0x00000003 +#define I2O_EVENT_RESET_IMMINENT_CODE_EXCEPTION 0x00000004 +#define I2O_EVENT_RESET_IMMINENT_WATCHDOG_TIMEOUT 0x00000005 + +/* Hardware Fail Event Data */ + +#define I2O_EVENT_HARDWARE_FAIL_UNKNOWN_CAUSE 0x00000000 +#define I2O_EVENT_HARDWARE_FAIL_CPU_FAILURE 0x00000001 +#define I2O_EVENT_HARDWARE_FAIL_MEMORY_FAULT 0x00000002 +#define I2O_EVENT_HARDWARE_FAIL_DMA_FAILURE 0x00000003 +#define I2O_EVENT_HARDWARE_FAIL_IO_BUS_FAILURE 0x00000004 + +/* DDM Availability Event Data */ + +#define I2O_EVENT_DDM_AVAILIBILITY_RESPOND_NORMAL 0x00000000 +#define I2O_EVENT_DDM_AVAILIBILITY_CONGESTED 0x00000001 +#define I2O_EVENT_DDM_AVAILIBILITY_NOT_RESPONDING 0x00000002 +#define I2O_EVENT_DDM_AVAILIBILITY_PROTECTION_VIOLATION 0x00000003 +#define I2O_EVENT_DDM_AVAILIBILITY_CODE_VIOLATION 0x00000004 + + +#define I2O_OPERATION_FLAG_ASSIGN_PERMANENT 0x01 + +/* ExecAdapterAssign Function Message Frame structure. */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_exec_adapter_assign_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint32_t DdmTID:12; + uint32_t reserved:12; + uint32_t OperationFlags:8; + } s; + uint32_t w; + } u1; + i2o_hrt_entry_t HRTEntry; +} i2o_exec_adappter_assign_message_t; + +/* macros to access the bit fields in exec adapter assign message */ + +#define get_i2o_exec_adapter_DdmTID(mp, hdl) \ + (mp)->u1.s.DdmTID +#define put_i2o_exec_adapter_DdmTID(mp, id, hdl) \ + ((mp)->u1.s.DdmTID = (id)) +#define get_i2o_exec_adapter_OperationFlags(mp, hdl) \ + (mp)->u1.s.OperationFlags +#define put_i2o_exec_adapter_OperationFlags(mp, n, hdl) \ + ((mp)->u1.s.OperationFlags = (n)) + +#endif + + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_exec_adapter_assign_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint32_t OperationFlags:8; + uint32_t reserved:12; + uint32_t DdmTID:12; + } s; + uint32_t w; + } u1; + i2o_hrt_entry_t HRTEntry; +} i2o_exec_adappter_assign_message_t; + +/* macros to access the bit fields in exec adapter assign message */ + + +#define get_i2o_exec_adapter_OperationFlags(mp, hdl) \ + (mp)->u1.s.OperationFlags +#define put_i2o_exec_adapter_OperatonFlags(mp, n, hdl) \ + ((mp)->u1.s.OperationFlags = (n)) + +#define get_i2o_exec_adapter_DdmTID(mp, hdl) \ + (ddi_get32(hdl, &(mp)->u1.w) & 0xFFF) +#define put_i2o_exec_adapter_DdmTID(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u1.w, \ + (ddi_get32(hdl, &(mp)->u1.w) & ~0xFFF) | ((id) & 0xFFF)) + +#endif + +#define I2O_REQUEST_FLAG_CONFIG_REGISTER 0x00000000 +#define I2O_REQUEST_FLAG_IO_REGISTER 0x00000001 +#define I2O_REQUEST_FLAG_ADAPTER_MEMORY 0x00000002 + +/* ExecAdapterRead Function Message Frame structure. */ + +typedef struct i2o_exec_adapter_read_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint32_t AdapterID; + uint32_t RequestFlags; + uint32_t Offset; + uint32_t Length; + i2o_sg_element_t SGL; +} i2o_exec_adapter_read_message_t; + + +#define I2O_OPERATION_FLAG_RELEASE_PERMANENT 0x01 + +/* ExecAdapterRelease Function Message Frame structure. */ + +typedef struct i2o_exec_dapater_release_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint8_t reserved[3]; + uint8_t OperationFlags; + i2o_hrt_entry_t HRTEntry; +} i2o_exec_adapter_release_message_t; + + + +/* ExecBiosInfoSet Function Message Frame structure. */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_exec_bios_info_set_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint32_t DeviceTID:12; + uint32_t reserved:12; + uint32_t BiosInfo:8; + } s; + uint32_t w; + } u1; +} i2o_exec_bios_info_set_message_t; + +/* macros to access the bit fields in exec bios info set message structure */ + +#define get_i2o_exec_bios_DeviceTID(mp, hdl) \ + (mp)->u1.s.DeviceTID +#define put_i2o_exec_bios_DeviceTID(mp, id, hdl) \ + ((mp)->u1.s.DeviceTID = (id)) +#define get_i2o_exec_BiosInfo(mp, hdl) \ + (mp)->u1.s.BiosInfo +#define put_i2o_exec_BiosInfo(mp, n, hdl) \ + ((mp)->u1.s.BiosInfo = (id)) +#endif + + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_exec_bios_info_set_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint32_t BiosInfo:8; + uint32_t reserved:12; + uint32_t DeviceTID:12; + } s; + uint32_t w; + } u1; +} i2o_exec_bios_info_set_message_t; + +/* macros to access the bit fields in exec bios info set message structure */ + +#define get_i2o_exec_BiosInfo(mp, hdl) \ + (mp)->u1.s.BiosInfo +#define put_i2o_exec_BiosInfo(mp, n, hdl) \ + ((mp)->u1.s.BiosInfo = (n)) + +#define get_i2o_exec_bios_DeviceID(mp, hdl) \ + (ddi_get32(hdl, &(mp)->u1.w) & 0xFFF) +#define put_i2o_exec_bios_DeviceID(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u1.w, \ + (ddi_get32(hdl, &(mp)->u1.w) & ~0xFFF) | ((id) & 0xFFF)) + +#endif + + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +/* ExecBootDeviceSet Function Message Frame structure. */ + +typedef struct i2o_exec_boot_device_set_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint32_t BootDevice:12; + uint32_t reserved:20; + } s; + uint32_t w; + } u1; +} i2o_exec_boot_device_set_message_t; + +/* macros to access the bit fields in exec boot set message structure */ + +#define get_i2o_exec_boot_BootDevice(mp, hdl) \ + (mp)->u1.s.BootDevice +#define put_i2o_exec_boot_BootDevice(mp, id, hdl) \ + ((mp)->u1.s.BootDevice = (id)) + +#endif + + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_exec_boot_device_set_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint32_t reserved:20; + uint32_t BootDevice:12; + } s; + uint32_t w; + } u1; +} i2o_exec_boot_device_set_message_t; + +#define get_i2o_exec_boot_BootDevice(mp, hdl) \ + (ddi_get32(hdl, &(mp)->u1.w) & 0xFFF) +#define put_i2o_exec_boot_BootDevice(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u1.w, \ + (ddi_get32(hdl, &(mp)->u1.w) & ~0xFFF) | ((id) & 0xFFF)) + +#endif + + +/* ExecConfigValidate Function Message Frame structure. */ + +typedef struct i2o_exec_config_validate_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; +} i2o_exec_config_validate_message_t; + + + +/* ExecConnSetup Requestor */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_alias_connect_setup { + union { + struct { + uint32_t IOP1AliasForTargetDevice:12; + uint32_t IOP2AliasForInitiatorDevice:12; + uint32_t reserved:8; + } s; + uint32_t w; + } u1; +} i2o_alias_connect_setup_t; + +/* macros to access the bit fields in alias connect setup structure */ + +#define get_i2o_exec_setup_IOP1AliasForTargetDevice(mp, hdl) \ + (mp)->u1.s.IOP1AliasForTargetDevice +#define put_i2o_exec_setup_IOP1AliasForTargetDevice(mp, id, hdl) \ + ((mp)->u1.s.IOP1AliasForTargetDevice = (id)) +#define get_i2o_exec_setup_IOP2AliasForInitiatorDevice(mp, hdl) \ + (mp)->u1.s.IOP2AliasForInitiatorDevice +#define put_i2o_exec_setup_IOP2AliasForInitiatortDevice(mp, n, hdl) \ + ((mp)->u1.s.IOP2AliasForInitiatortDevice = (id)) +#endif + + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_alias_connect_setup { + union { + struct { + uint32_t reserved:8; + uint32_t IOP2AliasForInitiatorDevice:12; + uint32_t IOP1AliasForTargetDevice:12; + } s; + uint32_t w; + } u1; +} i2o_alias_connect_setup_t; + +/* macros to access the bit fields in alias connect setup structure */ + +#define get_i2o_exec_setup_IOP2ForInitiatorDevice(mp, hdl) \ + ((ddi_get32(hdl, &(mp)->u1.w) >> 12) & 0xFFF) +#define put_i2o_exec_setup_IOP2ForInitiatorDevice(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u1.w, (ddi_get32(hdl, &(mp)->u.w) & \ + ~0xFFF000) | (((id) & 0xFFF) << 12)) + +#define get_i2o_exec_setup_IOP1AliasForTargetDevice(mp, hdl) \ + (ddi_get32(hdl, &(mp)->u1.w) & 0xFFF) +#define put_i2o_exec_setup_IOP1AliasForTargetDevice(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u1.w, \ + (ddi_get32(hdl, &(mp)->u1.w) & ~0xFFF) | ((id) & 0xFFF)) + +#endif + + +#define I2O_OPERATION_FLAG_PEER_TO_PEER_BIDIRECTIONAL 0x01 + +/* ExecConnSetup Object */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_object_connect_setup { + union { + struct { + uint32_t TargetDevice:12; + uint32_t InitiatorDevice:12; + uint32_t OperationFlags:8; + } s; + uint32_t w; + } u1; +} i2o_object_connect_setup_t; + +/* macros to access the bit fields in object connect setup structure */ + +#define get_i2o_exec_setup_TargetDevice(mp, hdl) \ + (mp)->u1.s.TargetDevice +#define put_i2o_exec_setup_TargetDevice(mp, id, hdl) \ + ((mp)->u1.s.TargetDevice = (id)) +#define get_i2o_exec_setup_InitiatorDevice(mp, hdl) \ + (mp)->u1.s.InitiatorDevice +#define put_i2o_exec_setup_InitiatorDevice(mp, n, hdl) \ + ((mp)->u1.s.InitiatorDevice = (id)) +#define get_i2o_exec_setup_OperationFlags(mp, hdl) \ + (mp)->u1.s.OpetationFlags +#define put_i2o_exec_setup_OperationFlags(mp, id, hdl) \ + ((mp)->u1.s.OperationFlags = (id)) +#endif + + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_object_connect_setup { + union { + struct { + uint32_t OperationFlags:8; + uint32_t InitiatorDevice:12; + uint32_t TargetDevice:12; + } s; + uint32_t w; + } u1; +} i2o_object_connect_setup_t; + +/* macros to access the bit fields in object connect setup structure */ + +#define get_i2o_exec_setup_OperationFlags(mp, hdl) \ + (mp)->u1.s.OperationFlags +#define put_i2o_exec_setup_OperationFlags(mp, n, hdl) \ + ((mp)->u1.s.OperationFlags = (n)) + +#define get_i2o_exec_setup_InitiatorDevice(mp, hdl) \ + ((ddi_get32(hdl, &(mp)->u1.w) >> 12) & 0xFFF) +#define put_i2o_exec_setup_InitiatorDevice(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u1.w, (ddi_get32(hdl, &(mp)->u.w) & \ + ~0xFFF000) | (((id) & 0xFFF) << 12)) + +#define get_i2o_exec_setup_TargetDevice(mp, hdl) \ + (ddi_get32(hdl, &(mp)->u1.w) & 0xFFF) +#define put_i2o_exec_setup_TargetDevice(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u1.w, \ + (ddi_get32(hdl, &(mp)->u1.w) & ~0xFFF) | ((id) & 0xFFF)) + +#endif + + +/* ExecConnSetup Function Message Frame structure. */ + +typedef struct i2o_exec_conn_setup_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + i2o_object_connect_setup_t ObjectInfo; + i2o_alias_connect_setup_t AliasInfo; + uint16_t IOP2InboundMFrameSize; + uint16_t reserved; + uint32_t MessageClass; +} i2o_exec_conn_setup_message_t; + + +/* ExecConnSetup Object Reply */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_object_connect_reply { + union { + struct { + uint32_t TargetDevice:12; + uint32_t InitiatorDevice:12; + uint32_t ReplyStatusCode:8; + } s; + uint32_t w; + } u1; +} i2o_object_connect_reply_t; + +/* macros to access the bit fields in object connect reply structure */ + +#define get_connect_reply_TargetDevice(mp, hdl) \ + (mp)->u1.s.TargetDevice +#define get_connect_reply_InitiatorDevice(mp, hdl) \ + (mp)->u1.s.InitiatorDevice +#define get_connect_reply_RepluStatus(mp, hdl) \ + (mp)->u1.s.ReplyStatusCode + +#endif + + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_object_connect_reply { + union { + struct { + uint32_t ReplyStatusCode:8; + uint32_t InitiatorDevice:12; + uint32_t TargetDevice:12; + } s; + uint32_t w; + } u1; +} i2o_object_connect_reply_t; + +/* macros to access the bit fields in object connect reply structure */ + +#define get_connect_reply_ReplyStatusCode(mp, hdl) \ + (mp)->u1.s.ReplyStatusCode + +#define get_connect_reply_InitiatorDevice(mp, hdl) \ + ((ddi_get32(hdl, &(mp)->u1.w) >> 12) & 0xFFF) + +#define get_connect_reply_TargetDevice(mp, hdl) \ + (ddi_get32(hdl, &(mp)->u1.w) & 0xFFF) + +#endif + + +/* ExecConnSetup reply structure. */ + +typedef struct i2o_exec_conn_setup_reply { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + i2o_object_connect_reply_t ObjectInfo; + i2o_alias_connect_setup_t AliasInfo; + uint16_t IOP2InboundMFrameSize; + uint16_t reserved; +} i2o_exec_conn_setup_reply_t; + + +/* ExecDdmDestroy Function Message Frame structure. */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_exec_ddm_destroy_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint32_t DdmTID:12; + uint32_t reserved:20; + } s; + uint32_t w; + } u1; +} i2o_exec_ddm_destroy_message_t; + +/* macros to access the bit fields in exec ddm destroy message structure */ + +#define get_i2o_exec_ddm_destroy_DdmTID(mp, hdl) \ + (mp)->u1.s.DdmTID +#define put_i2o_exec_ddm_destroy_DdmTID(mp, id, hdl) \ + ((mp)->u1.s.DdmTID = (id)) + +#endif + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_exec_ddm_destroy_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint32_t reserved:20; + uint32_t DdmTID:12; + } s; + uint32_t w; + } u1; +} i2o_exec_ddm_destroy_message_t; + +/* macros to access the bit fields in exec ddm destroy message structure */ + +#define get_i2o_exec_ddm_destroy_DdmTID(mp, hdl) \ + (ddi_get32(hdl, &(mp)->u1.w) & 0xFFF) +#define put_i2o_exec_ddm_destroy_DdmTID(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u1.w, \ + (ddi_get32(hdl, &(mp)->u1.w) & ~0xFFF) | ((id) & 0xFFF)) + +#endif + + +/* ExecDdmEnable Function Message Frame structure. */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_exec_ddm_enable_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint32_t DeviceTID:12; + uint32_t reserved1:20; + } s2; + uint32_t w2; + } u2; + union { + struct { + uint16_t IOP_ID:12; + uint16_t reserved:4; + } s3; + uint16_t h1; + } u3; + uint16_t HostUnitID; +} i2o_exec_ddm_enable_message_t; + +/* macros to access the bit fields in exec ddm enable message structure */ + +#define get_i2o_exec_ddm_enable_DeviceTID(mp, hdl) \ + (mp)->u2.s2.DeviceTID +#define put_i2o_exec_ddm_enable_DeviceTID(mp, id, hdl) \ + ((mp)->u2.s2.DeviceTID = (id)) + +#define get_i2o_exec_ddm_enable_IOP_ID(mp, hdl) \ + (mp)->u3.s3.IOP_ID +#define put_i2o_exec_ddm_enable_IOP_ID(mp, id, hdl) \ + ((mp)->u3.s3.IOP_ID = (id)) + +#endif + + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_exec_ddm_enable_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint32_t reserved1:20; + uint32_t DeviceTID:12; + } s2; + uint32_t w2; + } u2; + union { + struct { + uint16_t reserved:4; + uint16_t IOP_ID:12; + } s3; + uint16_t h1; + } u3; + uint16_t HostUnitID; +} i2o_exec_ddm_enable_message_t; + +/* macros to access the bit fields in exec ddm enable message structure */ + +#define get_i2o_exec_ddm_enable_DeviceTID(mp, hdl) \ + (ddi_get32(hdl, &(mp)->u2.w2) & 0xFFF) +#define put_i2o_exec_ddm_enable_DeviceTID(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u2.w2, \ + (ddi_get32(hdl, &(mp)->u2.w2) & ~0xFFF) | ((id) & 0xFFF)) + +#define get_i2o_exec_ddm_enable_IOP_ID(p, hdl) \ + (ddi_get16(hdl, &(p)->u3.h1) & 0xFFF) + +#define put_i2o_exec_ddm_enable_IOP_ID(mp, id, hdl) \ + ddi_put16(hdl, &(mp)->u3.h1, \ + (ddi_get16(hdl, &(mp)->u3.h1) & ~0xFFF) | ((id) & 0xFFF)) + +#endif + +/* ExecDdmQuiesce Function Message Frame structure. */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_exec_ddm_quiesce_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint32_t DeviceTID:12; + uint32_t reserved1:20; + } s2; + uint32_t w2; + } u2; + union { + struct { + uint16_t IOP_ID:12; + uint16_t reserved:4; + } s3; + uint16_t h1; + } u3; + uint16_t HostUnitID; +} i2o_exec_ddm_quiesce_message_t; + +/* macros to access the bit fields in exec ddm quiesce message structure */ + +#define get_i2o_exec_ddm_quiesce_DeviceTID(mp, hdl) \ + (mp)->u2.s2.DeviceTID +#define put_i2o_exec_ddm_quiesce_DeviceTID(mp, id, hdl) \ + ((mp)->u2.s2.DeviceTID = (id)) + +#define get_i2o_exec_ddm_quiesce_IOP_ID(mp, hdl) \ + (mp)->u3.s3.IOP_ID +#define put_i2o_exec_ddm_quiesce_IOP_ID(mp, id, hdl) \ + ((mp)->u3.s3.IOP_ID = (id)) + +#endif + + +/* ExecDdmQuiesce Function Message Frame structure. */ + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_exec_ddm_quiesce_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint32_t reserved1:20; + uint32_t DeviceTID:12; + } s2; + uint32_t w2; + } u2; + union { + struct { + uint16_t reserved:4; + uint16_t IOP_ID:12; + } s3; + uint16_t h1; + } u3; + uint16_t HostUnitID; +} i2o_exec_ddm_quiesce_message_t; + +/* macros to access the bit fields in exec ddm quiesce message structure */ + +#define get_i2o_exec_ddm_quiesce_DeviceTID(mp, hdl) \ + (ddi_get32(hdl, &(mp)->u2.w2) & 0xFFF) +#define put_i2o_exec_ddm_quiesce_DeviceTID(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u2.w2, \ + (ddi_get32(hdl, &(mp)->u2.w2) & ~0xFFF) | ((id) & 0xFFF)) + +#define get_i2o_exec_ddm_quiesce_IOP_ID(p, hdl) \ + (ddi_get16(hdl, &(p)->u3.h1) & 0xFFF) + +#define put_i2o_exec_ddm_quiesce_IOP_ID(mp, id, hdl) \ + ddi_put16(hdl, &(mp)->u3.h1, \ + (ddi_get16(hdl, &(mp)->u3.h1) & ~0xFFF) | ((id) & 0xFFF)) + +#endif + + +/* ExecDdmReset Function Message Frame structure. */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_exec_ddm_reset_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint32_t DeviceTID:12; + uint32_t reserved1:20; + } s2; + uint32_t w2; + } u2; + union { + struct { + uint16_t IOP_ID:12; + uint16_t reserved:4; + } s3; + uint16_t h1; + } u3; + uint16_t HostUnitID; +} i2o_exec_ddm_reset_message_t; + +/* macros to access the bit fields in exec ddm reset message structure */ + +#define get_i2o_exec_ddm_reset_DeviceTID(mp, hdl) \ + (mp)->u2.s2.DeviceTID +#define put_i2o_exec_ddm_reset_DeviceTID(mp, id, hdl) \ + ((mp)->u2.s2.DeviceTID = (id)) + +#define get_i2o_exec_ddm_reset_IOP_ID(mp, hdl) \ + (mp)->u3.s3.IOP_ID +#define put_i2o_exec_ddm_resetquiesce_IOP_ID(mp, id, hdl) \ + ((mp)->u3.s3.IOP_ID = (id)) + +#endif + + +/* ExecDdmReset Function Message Frame structure. */ + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_exec_ddm_reset_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint32_t reserved1:20; + uint32_t DeviceTID:12; + } s2; + uint32_t w2; + } u2; + union { + struct { + uint16_t reserved:4; + uint16_t IOP_ID:12; + } s3; + uint16_t h1; + } u3; + uint16_t HostUnitID; +} i2o_exec_ddm_reset_message_t; + +/* macros to access the bit fields in exec ddm reset message structure */ + +#define get_i2o_exec_ddm_reset_DeviceTID(mp, hdl) \ + (ddi_get32(hdl, &(mp)->u2.w2) & 0xFFF) +#define put_i2o_exec_ddm_reset_DeviceTID(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u2.w2, \ + (ddi_get32(hdl, &(mp)->u2.w2) & ~0xFFF) | ((id) & 0xFFF)) + +#define get_i2o_exec_ddm_reset_IOP_ID(p, hdl) \ + (ddi_get16(hdl, &(p)->u3.h1) & 0xFFF) + +#define put_i2o_exec_ddm_reset_IOP_ID(mp, id, hdl) \ + ddi_put16(hdl, &(mp)->u3.h1, \ + (ddi_get16(hdl, &(mp)->u3.h1) & ~0xFFF) | ((id) & 0xFFF)) + +#endif + + +/* ExecDdmSuspend Function Message Frame structure. */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_exec_ddm_suspend_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint32_t DdmTID:12; + uint32_t reserved:20; + } s; + uint32_t w; + } u1; +} i2o_exec_ddm_suspend_message_t; + +/* macros to access the bit fields in exec ddm suspend message structure */ + +#define get_i2o_exec_ddm_suspend_DdmTID(mp, hdl) \ + (mp)->u1.s.DdmTID +#define put_i2o_exec_ddm_suspend_DdmTID(mp, id, hdl) \ + ((mp)->u1.s.DdmTID = (id)) + +#endif + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_exec_ddm_suspend_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint32_t reserved:20; + uint32_t DdmTID:12; + } s; + uint32_t w; + } u1; +} i2o_exec_ddm_suspend_message_t; + +/* macros to access the bit fields in exec ddm suspend message structure */ + +#define get_i2o_exec_ddm_suspend_DdmTID(mp, hdl) \ + (ddi_get32(hdl, &(mp)->u1.w) & 0xFFF) +#define put_i2o_exec_ddm_suspend_DdmTID(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u1.w, \ + (ddi_get32(hdl, &(mp)->u1.w) & ~0xFFF) | ((id) & 0xFFF)) + +#endif + + +#define I2O_OPERATION_FLAG_ASSIGN_PERMANENT 0x01 + + +/* ExecDeviceAssign Function Message Frame structure. */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_exec_device_assign_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint32_t DeviceTID:12; + uint32_t DdmTID:12; + uint32_t OperationFlags:8; + } s2; + uint32_t w2; + } u2; + union { + struct { + uint16_t IOP_ID:12; + uint16_t reserved:4; + } s3; + uint16_t h1; + } u3; + uint16_t HostUnitID; +} i2o_exec_device_assign_message_t; + + +/* macros to access the bit fields in device assign message structure */ + +#define get_i2o_exec_device_assign_DeviceTID(mp, hdl) \ + (mp)->u2.s2.DeviceTID +#define put_i2o_exec_device_assign_DeviceTID(mp, id, hdl) \ + ((mp)->u2.s2.DeviceTID = (id)) +#define get_i2o_exec_device_assign_DdmTID(mp, hdl) \ + (mp)->u2.s2.DdmTID +#define put_i2o_exec_device_assign_DdmTID(mp, n, hdl) \ + ((mp)->u2.s2.DdmTID = (id)) +#define get_i2o_exec_device_assign_OperationFlags(mp, hdl) \ + (mp)->u2.s2.OpetationFlags +#define put_i2o_exec_device_assign_OperationFlags(mp, id, hdl) \ + ((mp)->u2.s2.OperationFlags = (id)) + +#define get_i2o_exec_device_assign_IOP_ID(mp, hdl) \ + (mp)->u3.s3.IOP_ID +#define put_i2o_exec_device_assign_IOP_ID(mp, id, hdl) \ + ((mp)->u3.s3.IOP_ID = (id)) +#endif + + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + + +typedef struct i2o_exec_device_assign_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint32_t OperationFlags:8; + uint32_t DdmTID:12; + uint32_t DeviceTID:12; + } s2; + uint32_t w2; + } u2; + union { + struct { + uint16_t reserved:4; + uint16_t IOP_ID:12; + } s3; + uint16_t h1; + } u3; + uint16_t HostUnitID; +} i2o_exec_device_assign_message_t; + +/* macros to access the bit fields in device assign message structure */ + +#define get_i2o_exec_device_assign_OperationFlags(mp, hdl) \ + (mp)->u2.s2.OperationFlags +#define put_i2o_exec_device_assign_OperationFlags(mp, n, hdl) \ + ((mp)->u2.s2.OperationFlags = (n)) + +#define get_i2o_exec_device_assign_DdmTID(mp, hdl) \ + ((ddi_get32(hdl, &(mp)->u2.w2) >> 12) & 0xFFF) +#define put_i2o_exec_device_assign_DdmTID(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u2.w2, (ddi_get32(hdl, &(mp)->u2.w2) & \ + ~0xFFF000) | (((id) & 0xFFF) << 12)) + +#define get_i2o_exec_device_assign_DeviceTID(mp, hdl) \ + (ddi_get32(hdl, &(mp)->u2.w2) & 0xFFF) +#define put_i2o_exec_device_assign_DeviceTID(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u2.w2, \ + (ddi_get32(hdl, &(mp)->u2.w2) & ~0xFFF) | ((id) & 0xFFF)) + +#define get_i2o_exec_device_assign_IOP_ID(p, hdl) \ + (ddi_get16(hdl, &(p)->u3.h1) & 0xFFF) +#define put_i2o_exec_device_assign_IOP_ID(mp, id, hdl) \ + ddi_put16(hdl, &(mp)->u3.h1, \ + (ddi_get16(hdl, &(mp)->u3.h1) & ~0xFFF) | ((id) & 0xFFF)) + +#endif + + +#define I2O_OPERATION_FLAG_RELEASE_PERMANENT 0x01 + +/* ExecDeviceRelease Function Message Frame structure. */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_exec_device_release_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint32_t DeviceTID:12; + uint32_t DdmTID:12; + uint32_t OperationFlags:8; + } s2; + uint32_t w2; + } u2; + union { + struct { + uint16_t IOP_ID:12; + uint16_t reserved:4; + } s3; + uint16_t h1; + } u3; + uint16_t HostUnitID; +} i2o_exec_device_release_message_t; + + +/* macros to access the bit fields in device release message structure */ + +#define get_i2o_exec_device_release_DeviceTID(mp, hdl) \ + (mp)->u2.s2.DeviceTID +#define put_i2o_exec_device_release_DeviceTID(mp, id, hdl) \ + ((mp)->u2.s2.DeviceTID = (id)) +#define get_i2o_exec_device_release_DdmTID(mp, hdl) \ + (mp)->u2.s2.DdmTID +#define put_i2o_exec_device_release_DdmTID(mp, n, hdl) \ + ((mp)->u2.s2.DdmTID = (id)) +#define get_i2o_exec_device_release_OperationFlags(mp, hdl) \ + (mp)->u2.s2.OpetationFlags +#define put_i2o_exec_device_release_OperationFlags(mp, id, hdl) \ + ((mp)->u2.s2.OperationFlags = (id)) + +#define get_i2o_exec_device_release_IOP_ID(mp, hdl) \ + (mp)->u3.s3.IOP_ID +#define put_i2o_exec_device_release_IOP_ID(mp, id, hdl) \ + ((mp)->u3.s3.IOP_ID = (id)) +#endif + + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + + +typedef struct i2o_exec_device_release_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint32_t OperationFlags:8; + uint32_t DdmTID:12; + uint32_t DeviceTID:12; + } s2; + uint32_t w2; + } u2; + union { + struct { + uint16_t reserved:4; + uint16_t IOP_ID:12; + } s3; + uint16_t h1; + } u3; + uint16_t HostUnitID; +} i2o_exec_device_release_message_t; + +/* macros to access the bit fields in device assign message structure */ + + +#define get_i2o_exec_device_release_OperationFlags(mp, hdl) \ + (mp)->u2.s2.OperationFlags +#define put_i2o_exec_device_release_OperationFlags(mp, n, hdl) \ + ((mp)->u2.s2.OperationFlags = (n)) + +#define get_i2o_exec_device_release_DdmTID(mp, hdl) \ + ((ddi_get32(hdl, &(mp)->u2.w2) >> 12) & 0xFFF) +#define put_i2o_exec_device_release_DdmTID(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u2.w2, (ddi_get32(hdl, &(mp)->u2.w2) & \ + ~0xFFF000) | (((id) & 0xFFF) << 12)) + +#define get_i2o_exec_device_release_DeviceTID(mp, hdl) \ + (ddi_get32(hdl, &(mp)->u2.w2) & 0xFFF) +#define put_i2o_exec_device_release_DeviceTID(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u2.w2, \ + (ddi_get32(hdl, &(mp)->u2.w2) & ~0xFFF) | ((id) & 0xFFF)) + +#define get_i2o_exec_device_release_IOP_ID(p, hdl) \ + (ddi_get16(hdl, &(p)->u3.h1) & 0xFFF) + +#define put_i2o_exec_device_release_IOP_ID(mp, id, hdl) \ + ddi_put16(hdl, &(mp)->u3.h1, \ + (ddi_get16(hdl, &(mp)->u3.h1) & ~0xFFF) | ((id) & 0xFFF)) + +#endif + + +/* HRT Entry Structure defined in I2OMSG.H */ + +/* ExecHrtGet Function Message Frame structure. */ + +typedef struct i2o_exec_hrt_get_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + i2o_sg_element_t SGL; +} i2o_exec_hrt_get_message_t; + + + +/* ExecIopClear Function Message Frame structure. */ + +typedef struct i2o_exec_iop_clear_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; +} i2o_exec_iop_clear_message_t; + + +/* ExecIopConnect Function Message Frame structure. */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_exec_iop_connect_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint32_t reserved:24; + uint32_t IOP1MsgerType:8; + + } s2; + uint32_t w2; + } u2; + uint16_t IOP1InboundMFrameSize; + union { + struct { + uint16_t IOP1AliasForIOP2:12; + uint16_t reserved1:4; + } s3; + uint16_t h2; + } u3; + union { + struct { + uint16_t IOP_ID1:12; + uint16_t reserved2:4; + } s4; + uint16_t h1; + } u4; + uint16_t HostUnitID1; +} i2o_exec_iop_connect_message_t; + + +/* macros to access the bit fields in exec iop connect message structure */ + +#define get_i2o_exec_iop_connect_IOP1MsgerType(p, hdl) \ + (mp)->u2.s2.IOP1MsgerType + +#define put_i2o_exec_iop_connect_IOP1MsgerType(mp, id, hdl) \ + ((mp)->u2.s2.IOP1MsgerType = (id)) + + +#define get_i2o_exec_iop_connect_IOP1AliasForIOP2(p, hdl) \ + (mp)->u3.s3.IOP1AliasForIOP2 + +#define put_i2o_exec_iop_connect_IOP1AliasForIOP2(mp, id, hdl) \ + ((mp)->u3.s3.IOP1AliasForIOP2 = (id)) + +#define get_i2o_exec_iop_connect_IOP_ID1(p, hdl) \ + (mp)->u4.s4.IOP_ID1 + +#define put_i2o_exec_iop_connect_IOP_ID1(mp, id, hdl) \ + ((mp)->u4.s4.IOP_ID1 = (id)) + + +#endif + + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_exec_iop_connect_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint32_t IOP1MsgerType:8; + uint32_t reserved:24; + } s2; + uint32_t w2; + } u2; + + uint16_t IOP1InboundMFrameSize; + union { + struct { + uint16_t reserved1:8; + uint16_t IOP1AliasForIOP2:12; + } s3; + uint16_t h2; + } u3; + union { + struct { + uint16_t reserved2:4; + uint16_t IOP_ID1:12; + } s4; + uint16_t h1; + } u4; + uint16_t HostUnitID1; +} i2o_exec_iop_connect_message_t; + +/* macros to access the bit fields in exec iop connect message structure */ + +#define get_i2o_exec_iop_connect_IOP1MsgerType(p, hdl) \ + ((ddi_get32(hdl, &(p)->u2.w2) >> 24) & 0xFF) + +#define put_i2o_exec_iop_connect_IOP1MsgerType(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u2.w2, \ + (ddi_get32(hdl, &(mp)->u2.w2) & ~0xFF) | (((id) & 0xFF) << 24)) + + +#define get_i2o_exec_iop_connect_IOP1AliasForIOP2(p, hdl) \ + (ddi_get16(hdl, &(p)->u3.h2) & 0xFFF) + +#define put_i2o_exec_iop_connect_IOP1AliasForIOP2(mp, id, hdl) \ + ddi_put16(hdl, &(mp)->u3.h2, \ + (ddi_get16(hdl, &(mp)->u3.h2) & ~0xFFF) | ((id) & 0xFFF)) + +#define get_i2o_exec_iop_connect_IOP_ID1(p, hdl) \ + (ddi_get32(hdl, &(p)->u4.h1) & 0xFFF) + +#define put_i2o_exec_iop_connect_IOP_ID1(mp, id, hdl) \ + ddi_put16(hdl, &(mp)->u4.h1, \ + (ddi_get16(hdl, &(mp)->u4.h1) & ~0xFFF) | ((id) & 0xFFF)) + +#endif + + +/* ExecIopConnect reply structure */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_exec_iop_connect_iop_reply { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint16_t DetailedStatusCode; + uint8_t reserved; + uint8_t ReqStatus; + uint16_t IOP2InboundMFrameSize; + union { + struct { + uint16_t IOP2AliasForIOP1:12; + uint16_t reserved1:4; + } s3; + uint16_t h2; + } u3; + union { + struct { + uint16_t IOP_ID2:12; + uint16_t reserved2:4; + } s4; + uint16_t w4; + } u4; + uint16_t HostUnitID2; +} i2o_exec_iop_connect_reply_t; + +/* macros to access the bit fields in exec iop connect reply structure */ + +#define get_i2o_exec_iop_connect_reply_IOP2AliasForIOP1(p, hdl) \ + (mp)->u3.s3.IOP2AliasForIOP1 + +#define put_i2o_exec_iop_connect_reply_IOP2AliasForIOP1(mp, id, hdl) \ + ((mp)->u3.s3.IOP2AliasForIOP1 = (id)) + +#define get_i2o_exec_iop_connect_reply_IOP_ID2(p, hdl) \ + (mp)->u4.s4.IOP_ID2 + +#define put_i2o_exec_iop_connect_reply_IOP_ID2(mp, id, hdl) \ + ((mp)->u4.s4.IOP_ID2 = (id)) + +#endif + + + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_exec_iop_connect_iop_reply { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint16_t DetailedStatusCode; + uint8_t reserved; + uint8_t ReqStatus; + uint16_t IOP2InboundMFrameSize; + union { + struct { + uint16_t reserved1:8; + uint16_t IOP2AliasForIOP1:12; + } s3; + uint16_t h2; + } u3; + union { + struct { + uint16_t reserved2:4; + uint16_t IOP_ID2:12; + } s4; + uint16_t h1; + } u4; + uint16_t HostUnitID2; +} i2o_exec_iop_connect_reply_t; + +/* macros to access the bit fields in exec iop connect reply structure */ + +#define get_i2o_exec_iop_connect_reply_IOP2AliasForIOP1(p, hdl) \ + (ddi_get16(hdl, &(p)->u3.h2) & 0xFFF) + +#define put_i2o_exec_iop_connect_reply_IOP2AliasForIOP1(mp, id, hdl) \ + ddi_put16(hdl, &(mp)->u3.h2, \ + (ddi_get16(hdl, &(mp)->u3.h2) & ~0xFFF) | ((id) & 0xFFF)) + +#define get_i2o_exec_iop_connect_reply_IOP_ID2(p, hdl) \ + (ddi_get32(hdl, &(p)->u4.h1) & 0xFFF) + +#define put_i2o_exec_iop_connect_reply_IOP_ID2(mp, id, hdl) \ + ddi_put16(hdl, &(mp)->u4.h1, \ + (ddi_get16(hdl, &(mp)->u4.h1) & ~0xFFF) | ((id) & 0xFFF)) + +#endif + + +#define I2O_EXEC_IOP_RESET_RESERVED_SZ 16 + +#define I2O_EXEC_IOP_RESET_IN_PROGRESS 0x01 +#define I2O_EXEC_IOP_RESET_REJECTED 0x02 + +#define I2O_EXEC_IOP_RESET_STATUS_RESERVED_SZ 3 + +typedef struct i2o_exec_iop_reset_status { + volatile uint8_t ResetStatus; + uint8_t reserved[I2O_EXEC_IOP_RESET_STATUS_RESERVED_SZ]; +} i2o_exec_iop_reset_status_t; + + +/* ExecIopReset Function Message Frame structure. */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_exec_iop_reset_message { + uint8_t VersionOffset; + uint8_t MsgFlags; + uint16_t MessageSize; + union { + struct { + uint32_t TargetAddress:12; + uint32_t InitiatorAddress:12; + uint32_t Function:8; + } s2; + uint32_t w2; + } u2; + uint8_t Reserved[I2O_EXEC_IOP_RESET_RESERVED_SZ]; + uint32_t StatusWordLowAddress; + uint32_t StatusWordHighAddress; +} i2o_exec_iop_reset_message_t; + +/* macros to access the bit fields in iop reset message */ + +#define get_i2o_exec_reset_TargetAddress(mp, hdl) \ + (mp)->u2.s2.TargetAddress +#define put_i2o_exec_reset_TargetAddress(mp, id, hdl) \ + ((mp)->u2.s2.TargetAddress = (id)) +#define get_i2o_exec_reset_InitiatorAddress(mp, hdl) \ + (mp)->u2.s2.InitiatorAddress +#define put_i2o_exec_reset_InitiatorAddress(mp, id, hdl) \ + ((mp)->u2.s2.InitiatorAddress = (id)) +#define get_i2o_exec_reset_Function(mp, hdl) \ + (mp)->u2.s2.Function +#define put_i2o_exec_reset_Function(mp, n, hdl) \ + ((mp)->u2.s2.Function = (n)) +#endif + + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_exec_iop_reset_message { + uint8_t VersionOffset; + uint8_t MsgFlags; + uint16_t MessageSize; + union { + struct { + uint32_t Function:8; + uint32_t InitiatorAddress:12; + uint32_t TargetAddress:12; + } s2; + uint32_t w2; + } u2; + + uint8_t Reserved[I2O_EXEC_IOP_RESET_RESERVED_SZ]; + uint32_t StatusWordLowAddress; + uint32_t StatusWordHighAddress; +} i2o_exec_iop_reset_message_t; + +/* macros to access the bit fields in iop reset message */ + +#define get_i2o_exec_reset_Function(mp, hdl) \ + (mp)->u2.s2.Function +#define put_i2o_exec_reset_Function(mp, n, hdl) \ + ((mp)->u2.s2.Function = (n)) + +#define get_i2o_exec_reset_TargetAddress(mp, hdl) \ + (ddi_get32(hdl, &(mp)->u2.w2) & 0xFFF) +#define put_i2o_exec_reset_TargetAddress(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u2.w2, \ + (ddi_get32(hdl, &(mp)->u2.w2) & ~0xFFF) | ((id) & 0xFFF)) + +#define get_i2o_exec_reset_InitiatorAddress(mp, hdl) \ + ((ddi_get32(hdl, &(mp)->u2.w2) >> 12) & 0xFFF) +#define put_i2o_exec_reset_InitiatorAddress(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u2.w2, (ddi_get32(hdl, &(mp)->u2.w2) & \ + ~0xFFF000) | (((id) & 0xFFF) << 12)) + +#endif + + +/* LCT Entry Structure defined in I2OMSG.H */ + +/* ExecLCTNotify Function Message Frame structure. */ + +typedef struct i2o_exec_lct_notify_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint32_t ClassIdentifier; + uint32_t LastReportedChangeIndicator; + i2o_sg_element_t SGL; +} i2o_exec_lct_notify_message_t; + + +/* ExecOutboundInit Function Message Frame structure. */ + +typedef struct i2o_exec_outbound_init_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint32_t HostPageFrameSize; + uint8_t InitCode; + uint8_t reserved; + uint16_t OutboundMFrameSize; + i2o_sg_element_t SGL; +} i2o_exec_outbound_init_message_t; + + +#define I2O_EXEC_OUTBOUND_INIT_IN_PROGRESS 0x01 +#define I2O_EXEC_OUTBOUND_INIT_REJECTED 0x02 +#define I2O_EXEC_OUTBOUND_INIT_FAILED 0x03 +#define I2O_EXEC_OUTBOUND_INIT_COMPLETE 0x04 + +#define I2O_EXEC_OUTBOUND_INIT_RESERVED_SZ 3 + + +typedef struct i2o_exec_outbound_init_status { + uint8_t InitStatus; + uint8_t reserved[I2O_EXEC_OUTBOUND_INIT_RESERVED_SZ]; +} i2o_exec_outbound_init_status_t; + + +typedef struct i2o_exec_outbound_init_reclaim_list { + uint32_t MFACount; + uint32_t MFAReleaseCount; + uint32_t MFAAddress[1]; +} i2o_exec_outbound_init_reclaim_list_t; + + +/* ExecPathEnable Function Message Frame structure. */ + + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_exec_path_enable_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint16_t IOP_ID:12; + uint16_t reserved:4; + } s2; + uint16_t h1; + } u2; + uint16_t HostUnitID; +} i2o_exec_path_enable_message_t; + +/* macros to access the bit fields in exec path enable message structure */ + +#define get_i2o_exec_path_enable_IOP_ID(mp, hdl) \ + (mp)->u2.s2.IOP_ID +#define put_i2o_exec_path_enable_IOP_ID(mp, id, hdl) \ + ((mp)->u2.s2.IOP_ID = (id)) +#endif + + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_exec_path_enable_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint16_t reserved:4; + uint16_t IOP_ID:12; + } s2; + uint16_t h1; + } u2; + uint16_t HostUnitID; +} i2o_exec_path_enable_message_t; + +/* macros to access the bit fields in exec path enable message structure */ + +#define get_i2o_exec_path_enable_IOP_ID(p, hdl) \ + (ddi_get32(hdl, &(p)->u2.h1) & 0xFFF) + +#define put_i2o_exec_path_enable_IOP_ID(mp, id, hdl) \ + ddi_put16(hdl, &(mp)->u2.h1, \ + (ddi_get16(hdl, &(mp)->u2.h1) & ~0xFFF) | ((id) & 0xFFF)) + +#endif + + +/* ExecPathQuiesce Function Message Frame structure. */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_exec_path_quiesce_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint16_t IOP_ID:12; + uint16_t reserved:4; + } s2; + uint16_t h1; + } u2; + uint16_t HostUnitID; +} i2o_exec_path_quiesce_message_t; + +/* macros to access the bit fields in exec path quiesce message structure */ + +#define get_i2o_exec_path_quiesce_IOP_ID(mp, hdl) \ + (mp)->u2.s2.IOP_ID +#define put_i2o_exec_path_quiesce_IOP_ID(mp, id, hdl) \ + ((mp)->u2.s2.IOP_ID = (id)) + +#endif + + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_exec_path_quiesce_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint16_t reserved:4; + uint16_t IOP_ID:12; + } s2; + uint16_t h1; + } u2; + uint16_t HostUnitID; +} i2o_exec_path_quiesce_message_t; + +/* macros to access the bit fields in exec path quiesce message structure */ + +#define get_i2o_exec_path_quiesce_IOP_ID(p, hdl) \ + (ddi_get16(hdl, &(p)->u2.h1) & 0xFFF) + +#define put_i2o_exec_path_quiesce_IOP_ID(mp, id, hdl) \ + ddi_put16(hdl, &(mp)->u2.h1, \ + (ddi_get16(hdl, &(mp)->u2.h1) & ~0xFFF) | ((id) & 0xFFF)) + +#endif + + +/* ExecPathReset Function Message Frame structure. */ + + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_exec_path_reset_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint16_t IOP_ID:12; + uint16_t reserved:4; + } s2; + uint16_t h1; + } u2; + uint16_t HostUnitID; +} i2o_exec_path_reset_message_t; + +/* macros to access the bit fields in exec path reset message structure */ + +#define get_i2o_exec_path_reset_IOP_ID(mp, hdl) \ + (mp)->u2.s2.IOP_ID +#define put_i2o_exec_path_reset_IOP_ID(mp, id, hdl) \ + ((mp)->u2.s2.IOP_ID = (id)) +#endif + + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_exec_path_reset_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint16_t reserved:4; + uint16_t IOP_ID:12; + } s2; + uint16_t h1; + } u2; + uint16_t HostUnitID; +} i2o_exec_path_reset_message_t; + +/* macros to access the bit fields in exec path reset message structure */ + +#define get_i2o_exec_path_reset_IOP_ID(p, hdl) \ + (ddi_get16(hdl, &(p)->u2.h1) & 0xFFF) + +#define put_i2o_exec_path_reset_IOP_ID(mp, id, hdl) \ + ddi_put16(hdl, &(mp)->u2.h1, \ + (ddi_get16(hdl, &(mp)->u2.h1) & ~0xFFF) | ((id) & 0xFFF)) + + +#endif + + +#define I2O_EXEC_STATIC_MF_CREATE_RESERVED_SZ 3 + +/* ExecStaticMfCreate Message Frame structure */ + +typedef struct i2o_exec_static_mf_create_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint8_t MaxOutstanding; + uint8_t reserved[I2O_EXEC_STATIC_MF_CREATE_RESERVED_SZ]; + i2o_message_frame_t StaticMessageFrame; +} i2o_exec_static_mf_create_message_t; + + +/* ExecStaticMfCreate Message Frame reply */ + +typedef struct i2o_exec_static_mf_create_reply { + i2o_single_reply_message_frame_t StdReplyFrame; + i2o_message_frame_t StaticMFA; +} i2o_exec_static_mf_create_reply_t; + + +/* ExecStaticMfRelease Message Frame structure */ + +typedef struct i2o_exec_static_mf_release_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + i2o_message_frame_t StaticMFA; +} i2o_exec_static_mf_release_message_t; + + + +#define I2O_EXEC_STATUS_GET_RESERVED_SZ 16 + +/* ExecStatusGet Function Message Frame structure. */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_exec_status_get_message { + uint8_t VersionOffset; + uint8_t MsgFlags; + uint16_t MessageSize; + union { + struct { + uint32_t Function:8; + uint32_t InitiatorAddress:12; + uint32_t TargetAddress:12; + } s2; + uint32_t w2; + } u2; + uint8_t Reserved[I2O_EXEC_STATUS_GET_RESERVED_SZ]; + uint32_t ReplyBufferAddressLow; + uint32_t ReplyBufferAddressHigh; + uint32_t ReplyBufferLength; +} i2o_exec_status_get_message_t; + +/* macros to access the bit fields in i2o exec status get message */ + +#define get_i2o_exec_status_TargetAddress(mp, hdl) \ + (mp)->u2.s2.TargetAddress +#define put_i2o_exec_status_TargetAddress(mp, id, hdl) \ + ((mp)->u2.s2.TargetAddress = (id)) +#define get_i2o_exec_status_InitiatorAddress(mp, hdl) \ + (mp)->u2.s2.InitiatorAddress +#define put_i2o_exec_status_InitiatorAddress(mp, id, hdl) \ + ((mp)->u2.s2.InitiatorAddress = (id)) +#define get_i2o_exec_status_Function(mp, hdl) \ + (mp)->u2.s2.Function +#define put_i2o_exec_status_Function(mp, n, hdl) \ + ((mp)->u2.s2.Function = (n)) + +#endif + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_exec_status_get_message { + uint8_t VersionOffset; + uint8_t MsgFlags; + uint16_t MessageSize; + union { + struct { + uint32_t Function:8; + uint32_t InitiatorAddress:12; + uint32_t TargetAddress:12; + } s2; + uint32_t w2; + } u2; + uint8_t Reserved[I2O_EXEC_STATUS_GET_RESERVED_SZ]; + uint32_t ReplyBufferAddressLow; + uint32_t ReplyBufferAddressHigh; + uint32_t ReplyBufferLength; +} i2o_exec_status_get_message_t; + +/* macros to access the bit fields in i2o exec status get message */ + +#define get_i2o_exec_status_Function(mp, hdl) \ + (mp)->u2.s2.Function +#define put_i2o_exec_status_Function(mp, n, hdl) \ + ((mp)->u2.s2.Function = (n)) + +#define get_i2o_exec_status_TargetAddress(mp, hdl) \ + (ddi_get32(hdl, &(mp)->u2.w2) & 0xFFF) +#define put_i2o_exec_status_TargetAddress(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u2.w2, \ + (ddi_get32(hdl, &(mp)->u2.w2) & ~0xFFF) | ((id) & 0xFFF)) + +#define get_i2o_exec_status_InitiatorAddress(mp, hdl) \ + ((ddi_get32(hdl, &(mp)->u2.w2) >> 12) & 0xFFF) +#define put_i2o_exec_status_InitiatorAddress(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u2.w2, (ddi_get32(hdl, &(mp)->u2.w2) & \ + ~0xFFF000) | (((id) & 0xFFF) << 12)) + +#endif + + +#define I2O_IOP_STATUS_PROD_ID_STR_SZ 24 +#define I2O_EXEC_STATUS_GET_REPLY_RESERVED_SZ 6 + +/* ExecStatusGet reply Structure */ + +#define I2O_IOP_CAP_CONTEXT_32_ONLY 0x00000000 +#define I2O_IOP_CAP_CONTEXT_64_ONLY 0x00000001 +#define I2O_IOP_CAP_CONTEXT_32_64_NOT_CURRENTLY 0x00000002 +#define I2O_IOP_CAP_CONTEXT_32_64_CURRENTLY 0x00000003 +#define I2O_IOP_CAP_CURRENT_CONTEXT_NOT_CONFIG 0x00000000 +#define I2O_IOP_CAP_CURRENT_CONTEXT_32_ONLY 0x00000004 +#define I2O_IOP_CAP_CURRENT_CONTEXT_64_ONLY 0x00000008 +#define I2O_IOP_CAP_CURRENT_CONTEXT_32_64 0x0000000C +#define I2O_IOP_CAP_INBOUND_PEER_SUPPORT 0x00000010 +#define I2O_IOP_CAP_OUTBOUND_PEER_SUPPORT 0x00000020 +#define I2O_IOP_CAP_PEER_TO_PEER_SUPPORT 0x00000040 + + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_exec_status_get_reply { + uint16_t OrganizationID; + uint16_t reserved; + union { + struct { + uint16_t IOP_ID:12; + uint16_t reserved1:4; + } s2; + uint16_t h1; + } u2; + uint16_t HostUnitID; + union { + struct { + uint16_t SegmentNumber:12; + uint16_t I2oVersion:4; + } s3; + uint16_t h1; + } u3; + uint8_t IopState; + uint8_t MessengerType; + uint16_t InboundMFrameSize; + uint8_t InitCode; + uint8_t reserved2; + uint32_t MaxInboundMFrames; + uint32_t CurrentInboundMFrames; + uint32_t MaxOutboundMFrames; + uint8_t ProductIDString[I2O_IOP_STATUS_PROD_ID_STR_SZ]; + uint32_t ExpectedLCTSize; + uint32_t IopCapabilities; + uint32_t DesiredPrivateMemSize; + uint32_t CurrentPrivateMemSize; + uint32_t CurrentPrivateMemBase; + uint32_t DesiredPrivateIOSize; + uint32_t CurrentPrivateIOSize; + uint32_t CurrentPrivateIOBase; + uint8_t reserved3[3]; + volatile uint8_t SyncByte; +} i2o_exec_status_get_reply_t; + +#define get_i2o_exec_status_reply_IOP_ID(p, hdl) (p)->u2.s2.IOP_ID +#define get_i2o_exec_status_reply_SegmentNumber(p, hdl)(p)->u3.s3.SegmentNumber +#define get_i2o_exec_status_reply_I2oVersion(p, hdl)(p)->u3.s3.I2oVersion + +#endif + + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_exec_status_get_reply { + uint16_t OrganizationID; + uint16_t reserved; + union { + struct { + uint16_t reserved1:4; + uint16_t IOP_ID:12; + } s2; + uint16_t h1; + } u2; + uint16_t HostUnitID; + union { + struct { + uint16_t I2oVersion:4; + uint16_t SegmentNumber:12; + } s3; + uint16_t h1; + } u3; + uint8_t IopState; + uint8_t MessengerType; + uint16_t InboundMFrameSize; + uint8_t InitCode; + uint8_t reserved2; + uint32_t MaxInboundMFrames; + uint32_t CurrentInboundMFrames; + uint32_t MaxOutboundMFrames; + uint8_t ProductIDString[I2O_IOP_STATUS_PROD_ID_STR_SZ]; + uint32_t ExpectedLCTSize; + uint32_t IopCapabilities; + uint32_t DesiredPrivateMemSize; + uint32_t CurrentPrivateMemSize; + uint32_t CurrentPrivateMemBase; + uint32_t DesiredPrivateIOSize; + uint32_t CurrentPrivateIOSize; + uint32_t CurrentPrivateIOBase; + uint8_t reserved3[3]; + uint8_t SyncByte; +} i2o_exec_status_get_reply_t; + +#define get_i2o_exec_status_reply_IOP_ID(p, hdl) \ + (ddi_get16(hdl, &(p)->u2.h1) & 0xFFF) + +#define get_i2o_exec_status_reply_I2oVersion(p, hdl) \ + (ddi_get16(hdl, &(p)->u3.h1) >> 4) +#define get_i2o_exec_staus_reply_SegmentNumber(p, hdl) \ + (ddi_get16(hdl, &(p)->u3.h1) & 0xFFF) + +#endif + + +#define I2O_EXEC_SW_DOWNLOAD_FLAG_LOAD_MEMORY 0x00 +#define I2O_EXEC_SW_DOWNLOAD_FLAG_PERMANENT_STORE 0x01 +#define I2O_EXEC_SW_DOWNLOAD_FLAG_EXPERIMENTAL 0x00 +#define I2O_EXEC_SW_DOWNLOAD_FLAG_OVERRIDE 0x02 + +#define I2O_EXEC_SW_TYPE_DDM 0x01 +#define I2O_EXEC_SW_TYPE_DDM_MPB 0x02 +#define I2O_EXEC_SW_TYPE_DDM_CONFIG_TABLE 0x03 +#define I2O_EXEC_SW_TYPE_IRTOS 0x11 +#define I2O_EXEC_SW_TYPE_IRTOS_PRIVATE_MODULE 0x12 +#define I2O_EXEC_SW_TYPE_IRTOS_DIALOG_TABLE 0x13 +#define I2O_EXEC_SW_TYPE_IOP_PRIVATE_MODULE 0x22 +#define I2O_EXEC_SW_TYPE_IOP_DIALOG_TABLE 0x23 + + +/* I2O ExecSwDownload/Upload/Remove SwID Structure */ + +typedef struct i2o_sw_id { + uint16_t ModuleID; + uint16_t OrganizationID; +} i2o_sw_id_t; + + +/* ExecSwDownload Function Message Frame structure. */ + +typedef struct i2o_exec_sw_donwload_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint8_t CurrentFragment; + uint8_t TotalFragments; + uint8_t SwType; + uint8_t DownloadFlags; + uint32_t SWSize; + i2o_sw_id_t SwID; + i2o_sg_element_t SGL; +} i2o_exec_sw_download_message_t; + + + + +/* ExecSwUpload Function Message Frame structure. */ + +typedef struct i2o_exec_sw_upload_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint8_t CurrentFragment; + uint8_t TotalFragments; + uint8_t SwType; + uint8_t UploadFlags; + uint32_t SWSize; + i2o_sw_id_t SwID; + i2o_sg_element_t SGL; +} i2o_exec_sw_upload_message_t; + + +/* ExecSwRemove Function Message Frame structure. */ + +typedef struct i2o_exec_sw_remove_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint16_t reserved; + uint8_t SwType; + uint8_t RemoveFlags; + uint32_t SWSize; + i2o_sw_id_t SwID; +} i2o_exec_sw_remove_message_t; + + +/* ExecSysEnable Function Message Frame structure. */ + +typedef struct i2o_exec_sys_enable_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; +} i2o_exec_sys_enable_message_t; + + +/* ExecSysModify Function Message Frame structure. */ + +typedef struct i2o_exec_sys_modify_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + i2o_sg_element_t SGL; +} i2o_exec_sys_modify_message_t; + + +/* ExecSysQuiesce Function Message Frame structure. */ + +typedef struct i2o_exec_sys_quiesce_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; +} i2o_exec_sys_quiesce_message_t; + + +/* ExecSysTabSet (System Table) Function Message Frame structure. */ + +#define I2O_EXEC_SYS_TAB_IOP_ID_LOCAL_IOP 0x000 +#define I2O_EXEC_SYS_TAB_IOP_ID_LOCAL_HOST 0x001 +#define I2O_EXEC_SYS_TAB_IOP_ID_UNKNOWN_IOP 0xFFF +#define I2O_EXEC_SYS_TAB_HOST_UNIT_ID_LOCAL_UNIT 0x0000 +#define I2O_EXEC_SYS_TAB_HOST_UNIT_ID_UNKNOWN_UNIT 0xffff +#define I2O_EXEC_SYS_TAB_SEG_NUMBER_LOCAL_SEGMENT 0x000 +#define I2O_EXEC_SYS_TAB_SEG_NUMBER_UNKNOWN_SEGMENT 0xfff + + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_exec_sys_tab_set_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint16_t IOP_ID:12; + uint16_t reserved:4; + } s2; + uint16_t h1; + } u2; + uint16_t HostUnitID; + union { + struct { + uint32_t SegmentNumber:12; + uint32_t reserved1:20; + } s3; + uint32_t w3; + } u3; + i2o_sg_element_t SGL; +} i2o_exec_sys_tab_set_message_t; + +/* macros to access the bit fields in exec ddm enable message structure */ + +#define get_i2o_exec_sys_tab_set_IOP_ID(mp, hdl) \ + (mp)->u2.s2.IOP_ID +#define put_i2o_exec_sys_tab_set_IOP_ID(mp, id, hdl) \ + ((mp)->u2.s2.IOP_ID = (id)) + +#define get_i2o_exec_sys_tab_set_SegmentNumber(mp, hdl) \ + (mp)->u3.s3.SegmentNumber +#define put_i2o_exec_sys_tab_set_SegmentNumber(mp, id, hdl) \ + ((mp)->u3.s3.SegmentNumber = (id)) +#endif + + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_exec_sys_tab_set_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + union { + struct { + uint16_t reserved:4; + uint16_t IOP_ID:12; + } s2; + uint16_t h1; + } u2; + uint16_t HostUnitID; + union { + struct { + uint32_t reserved1:20; + uint32_t SegmentNumnber:12; + } s3; + uint32_t w3; + } u3; + i2o_sg_element_t SGL; +} i2o_exec_sys_tab_set_message_t; + +/* macros to access the bit fields in exec ddm enable message structure */ + +#define get_i2o_exec_sys_tab_set_IOP_ID(p, hdl) \ + (ddi_get16(hdl, &(p)->u2.h1) & 0xFFF) + +#define put_i2o_exec_sys_tab_set_IOP_ID(mp, id, hdl) \ + ddi_put16(hdl, &(mp)->u2.h1, \ + (ddi_get16(hdl, &(mp)->u2.h1) & ~0xFFF) | ((id) & 0xFFF)) + +#define get_i2o_exec_sys_tab_set_SegmentNumber(mp, hdl) \ + (ddi_get32(hdl, &(mp)->u3.w3) & 0xFFF) +#define put_i2o_exec_sys_tab_set_SegmentNumber(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u3.w3, \ + (ddi_get32(hdl, &(mp)->u3.w3) & ~0xFFF) | ((id) & 0xFFF)) + +#endif + + +/* ExecSysTabSet (System Table) Header Reply structure. */ + +#define I2O_SET_SYSTAB_RESERVED_SZ 8 + +typedef struct i2o_set_systab_header { + uint8_t NumberEntries; + uint8_t SysTabVersion; + uint16_t reserved; + uint32_t CurrentChangeIndicator; + uint8_t reserved1[I2O_SET_SYSTAB_RESERVED_SZ]; +/* I2O_SYSTAB_ENTRY SysTabEntry[1]; */ +} i2o_set_systab_header_t; + + +#define I2O_RESOURCE_MANAGER_VERSION 0 + +typedef struct i2o_messenger_info { + uint32_t InboundMessagePortAddressLow; + uint32_t InboundMessagePortAddressHigh; +} i2o_messenger_info_t; + +/* ExecSysTabSet IOP Descriptor Entry structure. */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_iop_entry { + uint16_t OrganizationID; + uint16_t reserved; + union { + struct { + uint32_t IOP_ID:12; + uint32_t reserved1:20; + } s2; + uint32_t w2; + } u2; + union { + struct { + uint16_t SegmentNumber:12; + uint16_t I2oVersion:4; + } s3; + uint16_t h1; + } u3; + uint8_t IopState; + uint8_t MessengerType; + uint16_t InboundMessageFrameSize; + uint16_t reserved2; + uint32_t LastChanged; + uint32_t IopCapabilities; + i2o_messenger_info_t MessengerInfo; +} i2o_iop_entry_t; + + +#define get_i2o_iop_entry_IOP_ID(mp, hdl) \ + ((mp)->u2.s2.IOP_ID) + +#define put_i2o_iop_entry_IOP_ID(mp, v, hdl) \ + ((mp)->u2.s2.IOP_ID) = (v) + +#define get_i2o_iop_entry_SegmentNumber(mp, hdl) \ + ((mp)->u3.s3.SegmentNumber) + +#define put_i2o_iop_entry_SegmentNumber(mp, v, hdl) \ + ((mp)->u3.s3.SegmentNumber) = (v) + +#define get_i2o_iop_entry_I2oVersion(mp, hdl) \ + ((mp)->u3.s3.I2oVersion) + +#define put_i2o_iop_entry_I2oVersion(mp, v, hdl) \ + ((mp)->u3.s3.I2oVersion) = (v) + +#endif + + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_iop_entry { + uint16_t OrganizationID; + uint16_t reserved; + union { + struct { + uint32_t reserved1:20; + uint32_t IOP_ID:12; + } s2; + uint32_t w2; + } u2; + union { + struct { + uint16_t I2oVersion:4; + uint16_t SegmentNumber:12; + } s3; + uint16_t h1; + } u3; + uint8_t IopState; + uint8_t MessengerType; + uint16_t InboundMessageFrameSize; + uint16_t reserved2; + uint32_t LastChanged; + uint32_t IopCapabilities; + i2o_messenger_info_t MessengerInfo; +} i2o_iop_entry_t; + + +#define get_i2o_iop_entry_IOP_ID(mp, hdl) \ + (ddi_get32(hdl, &(mp)->u2.w2) & 0xFFF) + +#define put_i2o_iop_entry_IOP_ID(mp, v, hdl) \ + (ddi_put32(hdl, &(mp)->u2.w2) & 0xFFF, (v)) + +#define get_i2o_iop_entry_SegmentNumber(mp, hdl) \ + (ddi_get16(hdl, &(mp)->u3.h1) & 0xFFF) + +#define put_i2o_iop_entry_SegmentNumber(mp, v, hdl) \ + (ddi_put16(hdl, &(mp)->u3.h1) & 0xFFF, (v)) + +#define get_i2o_iop_entry_I2oVersion(mp, hdl) \ + ((ddi_get16(hdl, &(mp)->u3.h1) >> 12) & 0xF) + +#define put_i2o_iop_entry_I2oVersion(mp, v, hdl) \ + ((ddi_put16(hdl, &(mp)->u3.h1) >> 12) & 0xF, (v)) + +#endif + + +/* ************************************************************************** */ +/* Executive Parameter Groups */ +/* ************************************************************************** */ + + +#define I2O_EXEC_IOP_HARDWARE_GROUP_NO 0x0000 +#define I2O_EXEC_IOP_MESSAGE_IF_GROUP_NO 0x0001 +#define I2O_EXEC_EXECUTING_ENVIRONMENT_GROUP_NO 0x0002 +#define I2O_EXEC_EXECUTING_DDM_LIST_GROUP_NO 0x0003 +#define I2O_EXEC_DRIVER_STORE_GROUP_NO 0x0004 +#define I2O_EXEC_DRIVER_STORE_TABLE_GROUP_NO 0x0005 +#define I2O_EXEC_IOP_BUS_ATTRIBUTES_GROUP_NO 0x0006 +#define I2O_EXEC_IOP_SW_ATTRIBUTES_GROUP_NO 0x0007 +#define I2O_EXEC_HARDWARE_RESOURCE_TABLE_GROUP_NO 0x0100 +#define I2O_EXEC_LCT_SCALAR_GROUP_NO 0x0101 +#define I2O_EXEC_LCT_TABLE_GROUP_NO 0x0102 +#define I2O_EXEC_SYSTEM_TABLE_GROUP_NO 0x0103 +#define I2O_EXEC_EXTERNAL_CONN_TABLE_GROUP_NO 0x0104 + + +/* EXEC Group 0000h - IOP Hardware Parameter Group */ + +/* IOP HardWare Capabilities defines */ + +#define I2O_IOP_HW_CAP_SELF_BOOT 0x00000001 +#define I2O_IOP_HW_CAP_IRTOS_UPGRADEABLE 0x00000002 +#define I2O_IOP_HW_CAP_DOWNLOADABLE_DDM 0x00000004 +#define I2O_IOP_HW_CAP_INSTALLABLE_DDM 0x00000008 +#define I2O_IOP_HW_CAP_BATTERY_BACKUP_RAM 0x00000010 + +/* IOP Processor Type defines */ + +#define I2O_IOP_PROC_TYPE_INTEL_80960 0x00 +#define I2O_IOP_PROC_TYPE_AMD_29000 0x01 +#define I2O_IOP_PROC_TYPE_MOTOROLA_68000 0x02 +#define I2O_IOP_PROC_TYPE_ARM 0x03 +#define I2O_IOP_PROC_TYPE_MIPS 0x04 +#define I2O_IOP_PROC_TYPE_SPARC 0x05 +#define I2O_IOP_PROC_TYPE_POWER_PC 0x06 +#define I2O_IOP_PROC_TYPE_ALPHA 0x07 +#define I2O_IOP_PROC_TYPE_INTEL_X86 0x08 +#define I2O_IOP_PROC_TYPE_OTHER 0xFF + + +typedef struct i2o_exec_iop_hardware_scalar { + uint16_t I2oVendorID; + uint16_t ProductID; + uint32_t ProcessorMemory; + uint32_t PermMemory; + uint32_t HWCapabilities; + uint8_t ProcessorType; + uint8_t ProcessorVersion; +} i2o_exec_iop_hardware_scalar_t; + + +/* EXEC Group 0001h - IOP Message Interface Parameter Group */ + +/* InitCode defines */ +#define I2O_MESSAGE_IF_INIT_CODE_NO_OWNER 0x00 +#define I2O_MESSAGE_IF_INIT_CODE_BIOS 0x10 +#define I2O_MESSAGE_IF_INIT_CODE_OEM_BIOS_EXTENSION 0x20 +#define I2O_MESSAGE_IF_INIT_CODE_ROM_BIOS_EXTENSION 0x30 +#define I2O_MESSAGE_IF_INIT_CODE_OS 0x80 + +typedef struct i2o_exec_iop_message_if_scalar { + uint32_t InboundFrameSize; + uint32_t InboundSizeTarget; + uint32_t InboundMax; + uint32_t InboundTarget; + uint32_t InboundPoolCount; + uint32_t InboundCurrentFree; + uint32_t InboundCurrentPost; + uint16_t StaticCount; + uint16_t StaticInstanceCount; + uint16_t StaticLimit; + uint16_t StaticInstanceLimit; + uint32_t OutboundFrameSize; + uint32_t OutboundMax; + uint32_t OutboundMaxTarget; + uint32_t OutboundCurrentFree; + uint32_t OutboundCurrentPost; + uint8_t InitCode; +} i2o_exec_iop_message_if_scalar_t; + + +/* EXEC Group 0002h - Executing Environment Parameter Group */ + +typedef struct i2o_exec_execute_environment_scalar { + uint32_t MemTotal; + uint32_t MemFree; + uint32_t PageSize; + uint32_t EventQMax; + uint32_t EventQCurrent; + uint32_t DDMLoadMax; +} i2o_exec_execute_environment_scalar_t; + + +/* EXEC Group 0003h - Executing DDM's Parameter Group */ + +/* ModuleType Defines */ + +#define I2O_EXEC_DDM_MODULE_TYPE_OTHER 0x00 +#define I2O_EXEC_DDM_MODULE_TYPE_DOWNLOAD 0x01 +#define I2O_EXEC_DDM_MODULE_TYPE_EMBEDDED 0x22 + + +typedef struct i2o_exec_execute_ddm_table { + uint16_t DdmTID; + uint8_t ModuleType; + uint8_t reserved; + uint16_t I2oVendorID; + uint16_t ModuleID; + uint8_t ModuleName[I2O_MODULE_NAME_SZ]; + uint32_t ModuleVersion; + uint32_t DataSize; + uint32_t CodeSize; +} i2o_exec_execute_ddm_table_t; + + +/* EXEC Group 0004h - Driver Store Environment Parameter Group */ + + +typedef struct i2o_exec_driver_store_scalar { + uint32_t ModuleLimit; + uint32_t ModuleCount; + uint32_t CurrentSpace; + uint32_t FreeSpace; +} i2o_exec_driver_store_scalar_t; + + +/* EXEC Group 0005h - Driver Store Parameter Group */ + + +typedef struct i2o_exec_driver_store_table { + uint16_t StoredDdmIndex; + uint8_t ModuleType; + uint8_t reserved; + uint16_t I2oVendorID; + uint16_t ModuleID; + uint8_t ModuleName[I2O_MODULE_NAME_SZ]; + uint32_t ModuleVersion; + uint16_t DateDay; + uint16_t DateMonth; + uint32_t DateYear; + uint32_t ModuleSize; + uint32_t MpbSize; + uint32_t ModuleFlags; +} i2o_exec_driver_store_table_t; + + +/* EXEC Group 0006h - IOP's Bus Attributes Parameter Group */ + +#define I2O_EXEC_IOP_BUS_ATTRIB_SYSTEM_BUS 0x00 +#define I2O_EXEC_IOP_BUS_ATTRIB_BRIDGED_SYSTEM_BUS 0x01 +#define I2O_EXEC_IOP_BUS_ATTRIB_PRIVATE 0x02 + +typedef struct i2o_exec_iop_bus_attribute_table { + uint32_t BusID; + uint8_t BusType; + uint8_t MaxAdapters; + uint8_t AdapterCount; + uint8_t BusAttributes; +} i2o_exec_iop_bus_attribute_table_t; + + +/* EXEC Group 0007h - IOP's Bus Attributes Parameter Group */ + +#define I2O_EXEC_IOP_SW_CAP_IRTOS_I2O_COMPLIANT 0x00000001 +#define I2O_EXEC_IOP_SW_CAP_IRTOS_UPGRADEABLE 0x00000002 +#define I2O_EXEC_IOP_SW_CAP_DOWNLOADABLE_DDM 0x00000004 +#define I2O_EXEC_IOP_SW_CAP_INSTALLABLE_DDM 0x00000008 + +typedef struct i2o_exec_iop_sw_attributes_scalar { + uint16_t I2oVendorID; + uint16_t ProductID; + uint32_t CodeSize; + uint32_t SWCapabilities; +} i2o_exec_iop_sw_attributes_scalar_t; + + +/* EXEC Group 0100h - Hardware Resource Table Parameter Group */ + +typedef struct i2o_exec_hardware_resource_table { + uint32_t AdapterID; + uint16_t StateInfo; /* AdapterState plus Local TID */ + uint8_t BusNumber; + uint8_t BusType; + u_longlong_t PhysicalLocation; + uint32_t MemorySpace; + uint32_t IoSpace; +} i2o_exec_hardware_resource_table_t; + +/* EXEC Group 0101h - Logical Configuration Table Scalar Parameter Group */ + +typedef struct i2o_exec_lct_scalar { + uint16_t BootDevice; + uint32_t IopFlags; + uint32_t CurrentChangeIndicator; +} i2o_exec_lct_scalar_t; + +/* EXEC Group 0102h - Logical Configuration Table Parameter Group */ + +typedef struct i2o_exec_lct_table { + uint16_t LocalTID; + uint16_t UserTID; + uint16_t ParentTID; + uint16_t DdmTID; + uint32_t ChangeIndicator; + uint32_t DeviceFlags; + uint32_t ClassID; + uint32_t SubClass; + uint8_t IdentityTag[I2O_IDENTITY_TAG_SZ]; + uint32_t EventCapabilities; + uint8_t BiosInfo; +} i2o_exec_lct_table_t; + +/* EXEC Group 0103h - System Table Parameter Group */ + +#define I2O_MESSENGER_TYPE_MEMORY_MAPPED_MESSAGE_UNIT 0x0 + +typedef struct i2o_exec_system_table { + uint16_t IOP_ID; + uint16_t OrganizationID; + uint16_t SegmentNumber; + uint8_t Version; + uint8_t IopState; + uint8_t MessengerType; + uint8_t reserved; + uint32_t InboundMessagePortAddress; + uint16_t InboundMessageFrameSize; + uint32_t IopCapabilities; + i2o_messenger_info_t MessengerInfo; +} i2o_exec_system_table_t; + + +/* EXEC Group 0104h - External Connection Table Parameter Group */ + +#define I2O_EXEC_XCT_FLAGS_REMOTE_IOP_CREATED_CONNECTION 0x00 +#define I2O_EXEC_XCT_FLAGS_THIS_IOP_CREATED_CONNECTION 0x01 + +typedef struct i2o_exec_external_connection_table { + uint16_t LocalAliasTID; + uint16_t RemoteTID; + uint16_t RemoteIOP; + uint16_t RemoteUnitID; + uint8_t Flags; + uint8_t reserved; +} i2o_exec_external_connection_table_t; + + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_I2OEXEC_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/uts/common/sys/i2o/i2omsg.h Wed Apr 18 11:32:14 2007 -0700 @@ -0,0 +1,1570 @@ +/* + * Copyright (c) 1998-1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * ************************************************************************* + * All software on this website is made available under the following + * terms and conditions. By downloading this software, you agree to + * abide by these terms and conditions with respect to this software. + * + * I2O SIG All rights reserved. + * + * These header files are provided, pursuant to your I2O SIG membership + * agreement, free of charge on an as-is basis without warranty of any + * kind, either express or implied, including but not limited to, + * implied warranties or merchantability and fitness for a particular + * purpose. I2O SIG does not warrant that this program will meet the + * user's requirements or that the operation of these programs will be + * uninterrupted or error-free. Acceptance and use of this program + * constitutes the user's understanding that he will have no recourse + * to I2O SIG for any actual or consequential damages including, but + * not limited to, loss profits arising out of use or inability to use + * this program. + * + * Member is permitted to create deriavative works to this header-file + * program. However, all copies of the program and its derivative + * works must contain the I2O SIG copyright notice. + * ************************************************************************* + */ + +/* + * ************************************************************************* + * i2omsg.h -- I2O Message defintion file + * + * This file contains information presented in Chapter 3, 4 and 6 of + * the I2O(tm) Specification and most of the I2O Global defines and + * Typedefs. + * ************************************************************************* + */ + +#ifndef _SYS_I2OMSG_H +#define _SYS_I2OMSG_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#define I2OMSG_REV 1_5_4 /* I2OMsg header file revision string */ + +/* + * ************************************************************************* + * NOTES: + * + * Gets, reads, receives, etc. are all even numbered functions. + * Sets, writes, sends, etc. are all odd numbered functions. + * Functions that both send and receive data can be either but an attempt is + * made to use the function number that indicates the greater transfer amount. + * Functions that do not send or receive data use odd function numbers. + * + * Some functions are synonyms like read, receive and send, write. + * + * All common functions will have a code of less than 0x80. + * Unique functions to a class will start at 0x80. + * Executive Functions start at 0xA0. + * + * Utility Message function codes range from 0 - 0x1f + * Base Message function codes range from 0x20 - 0xfe + * Private Message function code is 0xff. + * ************************************************************************* + */ + +#include <sys/types.h> +#include <sys/dditypes.h> + +/* Set to 1 for 64 bit Context Fields */ +#define I2O_64BIT_CONTEXT 0 + +/* ************************************************************************** */ + +/* Common functions accross all classes. */ + +#define I2O_PRIVATE_MESSAGE 0xFF + +/* ************************************************************************** */ +/* Class ID and Code Assignments */ + + +#define I2O_CLASS_VERSION_10 0x00 +#define I2O_CLASS_VERSION_11 0x01 + +/* Class Code Names: Table 6-1 Class Code Assignments. */ + +#define I2O_CLASS_EXECUTIVE 0x000 +#define I2O_CLASS_DDM 0x001 +#define I2O_CLASS_RANDOM_BLOCK_STORAGE 0x010 +#define I2O_CLASS_SEQUENTIAL_STORAGE 0x011 +#define I2O_CLASS_LAN 0x020 +#define I2O_CLASS_WAN 0x030 +#define I2O_CLASS_FIBRE_CHANNEL_PORT 0x040 +#define I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL 0x041 +#define I2O_CLASS_SCSI_PERIPHERAL 0x051 +#define I2O_CLASS_ATE_PORT 0x060 +#define I2O_CLASS_ATE_PERIPHERAL 0x061 +#define I2O_CLASS_FLOPPY_CONTROLLER 0x070 +#define I2O_CLASS_FLOPPY_DEVICE 0x071 +#define I2O_CLASS_BUS_ADAPTER_PORT 0x080 +/* Class Codes 0x090 - 0x09f are reserved for Peer-to-Peer classes */ +#define I2O_CLASS_MATCH_ANYCLASS 0xffffffff + +#define I2O_SUBCLASS_i960 0x001 +#define I2O_SUBCLASS_HDM 0x020 +#define I2O_SUBCLASS_ISM 0x021 + +/* ************************************************************************** */ +/* Message Frame defines and structures */ + +/* Defines for the Version_Status field. */ + +#define I2O_VERSION_10 0x00 +#define I2O_VERSION_11 0x01 + +#define I2O_VERSION_OFFSET_NUMBER_MASK 0x07 +#define I2O_VERSION_OFFSET_SGL_TRL_OFFSET_MASK 0xF0 + +/* + * Defines for the Message Flags Field. + * Please Note that the FAIL bit is only set in the Transport Fail Message. + */ +#define I2O_MESSAGE_FLAGS_STATIC 0x01 +#define I2O_MESSAGE_FLAGS_64BIT_CONTEXT 0x02 +#define I2O_MESSAGE_FLAGS_MULTIPLE 0x10 +#define I2O_MESSAGE_FLAGS_FAIL 0x20 +#define I2O_MESSAGE_FLAGS_LAST 0x40 +#define I2O_MESSAGE_FLAGS_REPLY 0x80 + +/* Defines for Request Status Codes: Table 3-1 Reply Status Codes. */ + +#define I2O_REPLY_STATUS_SUCCESS 0x00 +#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01 +#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02 +#define I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER 0x03 +#define I2O_REPLY_STATUS_ERROR_DIRTY 0x04 +#define I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER 0x05 +#define I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER 0x06 +#define I2O_REPLY_STATUS_PROCESS_ABORT_DIRTY 0x08 +#define I2O_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER 0x09 +#define I2O_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER 0x0A +#define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0B +#define I2O_REPLY_STATUS_PROGRESS_REPORT 0x80 + +/* + * DetailedStatusCode defines for ALL messages: Table 3-2 Detailed Status Codes. + */ + +#define I2O_DETAIL_STATUS_SUCCESS 0x0000 +#define I2O_DETAIL_STATUS_BAD_KEY 0x0002 +#define I2O_DETAIL_STATUS_TCL_ERROR 0x0003 +#define I2O_DETAIL_STATUS_REPLY_BUFFER_FULL 0x0004 +#define I2O_DETAIL_STATUS_NO_SUCH_PAGE 0x0005 +#define I2O_DETAIL_STATUS_INSUFFICIENT_RESOURCE_SOFT 0x0006 +#define I2O_DETAIL_STATUS_INSUFFICIENT_RESOURCE_HARD 0x0007 +#define I2O_DETAIL_STATUS_CHAIN_BUFFER_TOO_LARGE 0x0009 +#define I2O_DETAIL_STATUS_UNSUPPORTED_FUNCTION 0x000A +#define I2O_DETAIL_STATUS_DEVICE_LOCKED 0x000B +#define I2O_DETAIL_STATUS_DEVICE_RESET 0x000C +#define I2O_DETAIL_STATUS_INAPPROPRIATE_FUNCTION 0x000D +#define I2O_DETAIL_STATUS_INVALID_INITIATOR_ADDRESS 0x000E +#define I2O_DETAIL_STATUS_INVALID_MESSAGE_FLAGS 0x000F +#define I2O_DETAIL_STATUS_INVALID_OFFSET 0x0010 +#define I2O_DETAIL_STATUS_INVALID_PARAMETER 0x0011 +#define I2O_DETAIL_STATUS_INVALID_REQUEST 0x0012 +#define I2O_DETAIL_STATUS_INVALID_TARGET_ADDRESS 0x0013 +#define I2O_DETAIL_STATUS_MESSAGE_TOO_LARGE 0x0014 +#define I2O_DETAIL_STATUS_MESSAGE_TOO_SMALL 0x0015 +#define I2O_DETAIL_STATUS_MISSING_PARAMETER 0x0016 +#define I2O_DETAIL_STATUS_TIMEOUT 0x0017 +#define I2O_DETAIL_STATUS_UNKNOWN_ERROR 0x0018 +#define I2O_DETAIL_STATUS_UNKNOWN_FUNCTION 0x0019 +#define I2O_DETAIL_STATUS_UNSUPPORTED_VERSION 0x001A +#define I2O_DEATIL_STATUS_DEVICE_BUSY 0x001B +#define I2O_DETAIL_STATUS_DEVICE_NOT_AVAILABLE 0x001C + +/* Common I2O Field sizes */ + +#define I2O_TID_SZ 12 +#define I2O_FUNCTION_SZ 8 +#define I2O_UNIT_ID_SZ 16 +#define I2O_SEGMENT_NUMBER_SZ 12 + +#define I2O_IOP_ID_SZ 12 +#define I2O_GROUP_ID_SZ 16 +#define I2O_IOP_STATE_SZ 8 +#define I2O_MESSENGER_TYPE_SZ 8 + +#define I2O_CLASS_ID_SZ 12 +#define I2O_CLASS_ORGANIZATION_ID_SZ 16 + +#define I2O_4BIT_VERSION_SZ 4 +#define I2O_8BIT_FLAGS_SZ 8 +#define I2O_COMMON_LENGTH_FIELD_SZ 16 + +#define I2O_DEVID_DESCRIPTION_SZ 16 +#define I2O_DEVID_VENDOR_INFO_SZ 16 +#define I2O_DEVID_PRODUCT_INFO_SZ 16 +#define I2O_DEVID_REV_LEVEL_SZ 8 +#define I2O_MODULE_NAME_SZ 24 + +#define I2O_BIOS_INFO_SZ 8 + +#define I2O_RESERVED_4BITS 4 +#define I2O_RESERVED_8BITS 8 +#define I2O_RESERVED_12BITS 12 +#define I2O_RESERVED_16BITS 16 +#define I2O_RESERVED_20BITS 20 +#define I2O_RESERVED_24BITS 24 +#define I2O_RESERVED_28BITS 28 + +typedef uint32_t I2O_PARAMETER_TID; + +#if I2O_64BIT_CONTEXT + +typedef union { + void (* i2o_msg_complete)(void *, ddi_acc_handle_t); + uint64_t initiator_context_64bits; +} i2o_initiator_context_t; + +typedef uint64_t i2o_transaction_context_t; + +#else + +typedef union { + void (* i2o_msg_complete)(void *, ddi_acc_handle_t); + uint32_t initiator_context_32bits; +} i2o_initiator_context_t; + +typedef uint32_t i2o_transaction_context_t; + +#endif + +/* Serial Number format defines */ + +#define I2O_SERIAL_FORMAT_UNKNOWN 0 +#define I2O_SERIAL_FORMAT_BINARY 1 +#define I2O_SERIAL_FORMAT_ASCII 2 +#define I2O_SERIAL_FORMAT_UNICODE 3 +#define I2O_SERIAL_FORMAT_LAN_MAC 4 +#define I2O_SERIAL_FORMAT_WAN 5 + +/* Special TID Assignments */ + +#define I2O_IOP_TID 0 +#define I2O_HOST_TID 1 + + +/* ************************************************************************** */ + +/* I2O Message Frame common for all messages */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_message_frame { + uint8_t VersionOffset; + uint8_t MsgFlags; + uint16_t MessageSize; + union { + struct { + uint32_t TargetAddress:12; + uint32_t InitiatorAddress:12; + uint32_t Function:8; + } s2; + uint32_t w2; + } u2; + i2o_initiator_context_t InitiatorContext; +} i2o_message_frame_t; + +/* macros to access the bit fields in Message Frame */ + +#define get_msg_TargetAddress(mp, hdl) \ + (mp)->u2.s2.TargetAddress +#define put_msg_TargetAddress(mp, id, hdl) \ + ((mp)->u2.s2.TargetAddress = (id)) +#define get_msg_InitiatorAddress(mp, hdl) \ + (mp)->u2.s2.InitiatorAddress +#define put_msg_InitiatorAddress(mp, id, hdl) \ + ((mp)->u2.s2.InitiatorAddress = (id)) +#define get_msg_Function(mp, hdl) \ + (mp)->u2.s2.Function +#define put_msg_Function(mp, n, hdl) \ + ((mp)->u2.s2.Function = (n)) +#endif + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_message_frame { + uint8_t VersionOffset; + uint8_t MsgFlags; + uint16_t MessageSize; + union { + struct { + uint32_t Function:8; + uint32_t InitiatorAddress:12; + uint32_t TargetAddress:12; + } s2; + uint32_t w2; + } u2; + i2o_initiator_context_t InitiatorContext; +} i2o_message_frame_t; + +/* macros to access the bit fields in Message Frame */ + +#define get_msg_Function(mp, hdl) \ + (mp)->u2.s2.Function +#define put_msg_Function(mp, n, hdl) \ + ((mp)->u2.s2.Function = (n)) + +#define get_msg_TargetAddress(mp, hdl) \ + (ddi_get32(hdl, &(mp)->u2.w2) & 0xFFF) +#define put_msg_TargetAddress(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u2.w2, \ + (ddi_get32(hdl, &(mp)->u2.w2) & ~0xFFF) | ((id) & 0xFFF)) + +#define get_msg_InitiatorAddress(mp, hdl) \ + ((ddi_get32(hdl, &(mp)->u2.w2) >> 12) & 0xFFF) +#define put_msg_InitiatorAddress(mp, id, hdl) \ + ddi_put32(hdl, &(mp)->u2.w2, (ddi_get32(hdl, &(mp)->u2.w2) & \ + ~0xFFF000) | (((id) & 0xFFF) << 12)) +#endif + + +/* ************************************************************************** */ + +/* Transaction Reply Lists (TRL) Control Word structure */ + +#define I2O_TRL_FLAGS_SINGLE_FIXED_LENGTH 0x00 +#define I2O_TRL_FLAGS_SINGLE_VARIABLE_LENGTH 0x40 +#define I2O_TRL_FLAGS_MULTIPLE_FIXED_LENGTH 0x80 + +typedef struct i2o_trl_control_word { + uint8_t TrlCount; + uint8_t TrlElementSize; + uint8_t reserved; + uint8_t TrlFlags; +#if I2O_64BIT_CONTEXT + uint32_t Padding; /* Padding for 64 bit */ +#endif +} i2o_trl_control_word_t; + +/* ************************************************************************** */ + +/* I2O Successful Single Transaction Reply Message Frame structure. */ + +typedef struct i2o_single_reply_message_frame { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint16_t DetailedStatusCode; + uint8_t reserved; + uint8_t ReqStatus; + /* ReplyPayload */ +} i2o_single_reply_message_frame_t; + +/* ************************************************************************** */ + +/* I2O Successful Multiple Transaction Reply Message Frame structure. */ + +typedef struct i2o_multiple_reply_message_frame { + i2o_message_frame_t StdMessageFrame; + i2o_trl_control_word_t TrlControlWord; + uint16_t DetailedStatusCode; + uint8_t reserved; + uint8_t ReqStatus; + /* TransactionDetails[] */ +} i2o_multiple_reply_message_frame_t; + +/* ************************************************************************** */ + +/* I2O Private Message Frame structure. */ + +typedef struct i2o_private_message_frame { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint16_t XFunctionCode; + uint16_t OrganizationID; + /* PrivatePayload[] */ +} i2o_private_message_frame_t; + +/* ************************************************************************** */ + +/* Message Failure Severity Codes */ + +#define I2O_SEVERITY_FORMAT_ERROR 0x1 +#define I2O_SEVERITY_PATH_ERROR 0x2 +#define I2O_SEVERITY_PATH_STATE 0x4 +#define I2O_SEVERITY_CONGESTION 0x8 + +/* Transport Failure Codes: Table 3-3 Mesasge Failure Codes */ + +#define I2O_FAILURE_CODE_TRANSPORT_SERVICE_SUSPENDED 0x81 +#define I2O_FAILURE_CODE_TRANSPORT_SERVICE_TERMINATED 0x82 +#define I2O_FAILURE_CODE_TRANSPORT_CONGESTION 0x83 +#define I2O_FAILURE_CODE_TRANSPORT_FAIL 0x84 +#define I2O_FAILURE_CODE_TRANSPORT_STATE_ERROR 0x85 +#define I2O_FAILURE_CODE_TRANSPORT_TIME_OUT 0x86 +#define I2O_FAILURE_CODE_TRANSPORT_ROUTING_FAILURE 0x87 +#define I2O_FAILURE_CODE_TRANSPORT_INVALID_VERSION 0x88 +#define I2O_FAILURE_CODE_TRANSPORT_INVALID_OFFSET 0x89 +#define I2O_FAILURE_CODE_TRANSPORT_INVALID_MSG_FLAGS 0x8A +#define I2O_FAILURE_CODE_TRANSPORT_FRAME_TOO_SMALL 0x8B +#define I2O_FAILURE_CODE_TRANSPORT_FRAME_TOO_LARGE 0x8C +#define I2O_FAILURE_CODE_TRANSPORT_INVALID_TARGET_ID 0x8D +#define I2O_FAILURE_CODE_TRANSPORT_INVALID_INITIATOR_ID 0x8E +#define I2O_FAILURE_CODE_TRANSPORT_INVALID_INITIATOR_CONTEXT 0x8F +#define I2O_FAILURE_CODE_TRANSPORT_UNKNOWN_FAILURE 0xFF + +/* IOP_ID and Severity sizes */ + +#define I2O_FAILCODE_SEVERITY_SZ 8 +#define I2O_FAILCODE_CODE_SZ 8 + +/* I2O Transport Message Reply for Message Failure. */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_failure_reply_message_frame { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint8_t LowestVersion; + uint8_t HighestVersion; + uint8_t Severity; + uint8_t FailureCode; + union { + struct { + uint16_t FailingIOP_ID:12; + uint16_t reserved:4; + } s; + uint16_t h; + } u1; + uint16_t FailingHostUnitID; + uint32_t AgeLimit; + i2o_message_frame_t *PreservedMFA; +} i2o_failure_reply_message_frame_t; + +/* macros to access the bit field(s) */ + +#define get_reply_msg_FailingIOP_ID(p, hdl) \ + ((p)->u1.s.FailingIOP_ID) +#endif + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_failure_reply_message_frame { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint8_t LowestVersion; + uint8_t HighestVersion; + uint8_t Severity; + uint8_t FailureCode; + union { + struct { + uint16_t reserved:4; + uint16_t FailingIOP_ID:12; + } s; + uint16_t h; + } u1; + uint16_t FailingHostUnitID; + uint32_t AgeLimit; + i2o_message_frame_t *PreservedMFA; +} i2o_failure_reply_message_frame_t; + +/* macros to access the bit field(s) */ + +#define get_reply_msg_FailingIOP_ID(p, hdl) \ + (ddi_get16(hdl, &(p)->u1.h) & 0xFFF) +#endif + +/* I2O Transport Message Reply for Transaction Error. */ + +typedef struct i2o_transaction_error_reply_message_frame { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint16_t DetailedStatusCode; + uint8_t reserved; + uint8_t ReqStatus; /* Should Transaction Error */ + uint32_t ErrorOffset; + uint8_t BitOffset; + uint8_t reserved1; + uint16_t reserved2; +} i2o_transaction_error_reply_message_frame_t; + +/* ************************************************************************** */ + +/* Misc. commonly used structures */ + +#define I2O_MAX_SERIAL_NUMBER_SZ 256 + +typedef struct i2o_serial_info { + uint8_t SerialNumberLength; + uint8_t SerialNumberFormat; + uint8_t SerialNumber[I2O_MAX_SERIAL_NUMBER_SZ]; +} i2o_serial_info_t; + + +/* ************************************************************************** */ +/* Hardware Resource Table (HRT) and Logical Configuration Table (LCT) */ +/* ************************************************************************** */ + +/* Bus Type Code defines */ + +#define I2O_LOCAL_BUS 0 +#define I2O_ISA_BUS 1 +#define I2O_EISA_BUS 2 +#define I2O_PCI_BUS 4 +#define I2O_PCMCIA_BUS 5 +#define I2O_NUBUS_BUS 6 +#define I2O_CARDBUS_BUS 7 +#define I2O_OTHER_BUS 0x80 + +#define I2O_HRT_STATE_SZ 4 +#define I2O_HRT_BUS_NUMBER_SZ 8 +#define I2O_HRT_BUS_TYPE_SZ 8 + + +/* Bus Structures */ + +/* PCI Bus */ +typedef struct i2o_pci_bus_info { + uint8_t PciFunctionNumber; + uint8_t PciDeviceNumber; + uint8_t PciBusNumber; + uint8_t reserved; + uint16_t PciVendorID; + uint16_t PciDeviceID; +} i2o_pci_bus_info_t; + +/* Local Bus */ +typedef struct i2o_local_bus_info { + uint16_t LbBaseIOPort; + uint16_t reserved; + uint32_t LbBaseMemoryAddress; +} i2o_local_bus_info_t; + +/* ISA Bus */ +typedef struct i2o_isa_bus_info { + uint16_t IsaBaseIOPort; + uint8_t CSN; + uint8_t reserved; + uint32_t IsaBaseMemoryAddress; +} i2o_isa_bus_info_t; + +/* EISA Bus */ +typedef struct i2o_eisa_bus_info { + uint16_t EisaBaseIOPort; + uint8_t reserved; + uint8_t EisaSlotNumber; + uint32_t EisaBaseMemoryAddress; +} i2o_eisa_bus_info_t; + +/* Other Bus */ +typedef struct i2o_other_bus_info { + uint16_t BaseIOPort; + uint16_t reserved; + uint32_t BaseMemoryAddress; +} i2o_other_bus_info_t; + + +/* HRT Entry Block */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_hrt_entry { + uint32_t AdapterID; + union { + struct { + uint16_t ControllingTID:12; + uint16_t AdapterState:4; + } s2; + uint16_t h2; + } u2; + uint8_t BusNumber; + uint8_t BusType; + union { + /* PCI Bus */ + i2o_pci_bus_info_t PCIBus; + + /* Local Bus */ + i2o_local_bus_info_t LocalBus; + + /* ISA Bus */ + i2o_isa_bus_info_t ISABus; + + /* EISA Bus */ + i2o_eisa_bus_info_t EISABus; + + /* Other. */ + i2o_other_bus_info_t OtherBus; + } uBus; +} i2o_hrt_entry_t; + +/* macros to access the bit fields */ + +#define get_hrt_entry_ControllingTID(p, hdl) (p)->u2.s2.ControllingTID +#define get_hrt_entry_AdapterState(p, hdl) (p)->u2.s2.AdapterState + +#endif + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_hrt_entry { + uint32_t AdapterID; + union { + struct { + uint16_t AdapterState:4; + uint16_t ControllingTID:12; + } s2; + uint16_t h2; + } u2; + uint8_t BusNumber; + uint8_t BusType; + union { + /* PCI Bus */ + i2o_pci_bus_info_t PCIBus; + + /* Local Bus */ + i2o_local_bus_info_t LocalBus; + + /* ISA Bus */ + i2o_isa_bus_info_t ISABus; + + /* EISA Bus */ + i2o_eisa_bus_info_t EISABus; + + /* Other. */ + i2o_other_bus_info_t OtherBus; + } uBus; +} i2o_hrt_entry_t; + +/* macros to access the bit fields */ + +#define get_hrt_entry_ControllingTID(p, hdl) \ + (ddi_get16(hdl, &(p)->u2.h2) & 0xFFF) +#define get_hrt_entry_AdapterState(p, hdl) \ + ((ddi_get16(hdl, &(p)->u2.h2) >> 12) & 0xF) +#endif + +/* I2O Hardware Resource Table structure. */ + +typedef struct i2o_hrt { + uint16_t NumberEntries; + uint8_t EntryLength; + uint8_t HRTVersion; + uint32_t CurrentChangeIndicator; + i2o_hrt_entry_t HRTEntry[1]; +} i2o_hrt_t; + + +/* ************************************************************************** */ +/* Logical Configuration Table */ +/* ************************************************************************** */ + +/* I2O Logical Configuration Table structures. */ + +#define I2O_IDENTITY_TAG_SZ 8 + +/* I2O Logical Configuration Table Device Flags */ + +#define I2O_LCT_DEVICE_FLAGS_CONF_DIALOG_REQUEST 0x01 +#define I2O_LCT_DEVICE_FLAGS_MORE_THAN_1_USER 0x02 +#define I2O_LCT_DEVICE_FLAGS_PEER_SERVICE_DISABLED 0x10 +#define I2O_LCT_DEVICE_FLAGS_MANAGEMENT_SERVICE_DISABLED 0x20 + +/* LCT Entry Block */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_lct_entry { + union { + struct { + uint32_t TableEntrySize:16; + uint32_t LocalTID:12; + uint32_t reserved:4; + } s1; + uint32_t w1; + } u1; + uint32_t ChangeIndicator; + uint32_t DeviceFlags; + union { + struct i2o_class_id { + uint32_t Class:12; + uint32_t Version:4; + uint32_t OrganizationID:16; + } s4; + uint32_t w4; + } u4; + uint32_t SubClassInfo; + union { + struct { + uint32_t UserTID:12; + uint32_t ParentTID:12; + uint32_t BiosInfo:8; + } s6; + uint32_t w6; + } u6; + uint8_t IdentityTag[I2O_IDENTITY_TAG_SZ]; + uint32_t EventCapabilities; +} i2o_lct_entry_t; + +/* macros to access the bit fields */ + +#define get_lct_entry_LocalTID(p, hdl) (p)->u1.s1.LocalTID +#define get_lct_entry_TableEntrySize(p, hdl) (p)->u1.s1.TableEntrySize + +#define get_lct_entry_Class(p, hdl) (p)->u4.s4.Class +#define get_lct_entry_Version(p, hdl) (p)->u4.s4.Version +#define get_lct_entry_OrganizationID(p, hdl) (p)->u4.s4.OrganizationID + +#define get_lct_entry_BiosInfo(p, hdl) (p)->u6.s6.BiosInfo +#define get_lct_entry_ParentTID(p, hdl) (p)->u6.s6.ParentTID +#define get_lct_entry_UserTID(p, hdl) (p)->u6.s6.UserTID + +#endif + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_lct_entry { + union { + struct { + uint32_t reserved:4; + uint32_t LocalTID:12; + uint32_t TableEntrySize:16; + } s1; + uint32_t w1; + } u1; + uint32_t ChangeIndicator; + uint32_t DeviceFlags; + union { + struct i2o_class_id { + uint32_t OrganizationID:16; + uint32_t Version:4; + uint32_t Class:12; + } s4; + uint32_t w4; + } u4; + uint32_t SubClassInfo; + union { + struct { + uint32_t BiosInfo:8; + uint32_t ParentTID:12; + uint32_t UserTID:12; + } s6; + uint32_t w6; + } u6; + uint8_t IdentityTag[I2O_IDENTITY_TAG_SZ]; + uint32_t EventCapabilities; +} i2o_lct_entry_t; + +/* macros to access the bit fields */ + +#define get_lct_entry_TableEntrySize(p, hdl) \ + (ddi_get32(hdl, &(p)->u1.w1) & 0xFFFF) +#define get_lct_entry_LocalTID(p, hdl) \ + ((ddi_get32(hdl, (p)->u1.w1) >> 16) & 0xFFF) + +#define get_lct_entry_OrganizationID(p, hdl) \ + ((ddi_get16(hdl, (p)->u4.w4) >> 16) & 0xFFFF) +#define get_lct_entry_Version(p, hdl) \ + ((ddi_get32(hdl, &(p)->u4.w4) >> 12) & 0xF) +#define get_lct_entry_Class(p, hdl) \ + (ddi_get32(hdl, &(p)->u4.w4) & 0xFFF) + +#define get_lct_entry_BiosInfo(p, hdl) (p)->u6.s6.BiosInfo +#define get_lct_entry_ParentTID(p, hdl) \ + ((ddi_get32(hdtl, &(p)->u6.w6) >> 12) & 0xFFF) +#define get_lct_entry_UserTID(p, hdl) \ + (ddi_get32(hdtl, &(p)->u6.w6) & 0xFFF) + +#endif + +/* I2O Logical Configuration Table structure. */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_lct { + uint16_t TableSize; + union { + struct { + uint16_t BootDeviceTID:12; + uint16_t LctVer:4; + } s1; + uint16_t h1; + } u1; + uint32_t IopFlags; + uint32_t CurrentChangeIndicator; + i2o_lct_entry_t LCTEntry[1]; +} i2o_lct_t; + +/* macros to access the bit fields */ + +#define get_lct_BootDeviceTID(p, hdl) (p)->u1.s1.BootDeviceTID +#define get_lct_LctVer(p, hdl) (p)->u1.s1.LctVer + +#endif + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_lct { + uint16_t TableSize; + union { + struct { + uint16_t LctVer:4; + uint16_t BootDeviceTID:12; + } s1; + uint16_t h1; + } u1; + uint32_t IopFlags; + uint32_t CurrentChangeIndicator; + i2o_lct_entry_t LCTEntry[1]; +} i2o_lct_t; + +/* macros to access the bit fields */ + +#define get_lct_BootDeviceTID(p, hdl) \ + ((ddi_get32(hdl, &(p)->u1.w1) >> 16) & 0xFFF) +#define get_lct_LctVer(p, hdl) \ + ((ddi_get32(hdl, &(p)->u1.w1) >> 28) & 0xF) + +#endif + +/* ************************************************************************** */ + +/* Memory Addressing structures and defines. */ + +/* SglFlags defines. */ + +#define I2O_SGL_FLAGS_LAST_ELEMENT 0x80 +#define I2O_SGL_FLAGS_END_OF_BUFFER 0x40 + +#define I2O_SGL_FLAGS_IGNORE_ELEMENT 0x00 +#define I2O_SGL_FLAGS_TRANSPORT_ELEMENT 0x04 +#define I2O_SGL_FLAGS_BIT_BUCKET_ELEMENT 0x08 +#define I2O_SGL_FLAGS_IMMEDIATE_DATA_ELEMENT 0x0C +#define I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT 0x10 +#define I2O_SGL_FLAGS_PAGE_LIST_ADDRESS_ELEMENT 0x20 +#define I2O_SGL_FLAGS_CHAIN_POINTER_ELEMENT 0x30 +#define I2O_SGL_FLAGS_LONG_TRANSACTION_ELEMENT 0x40 +#define I2O_SGL_FLAGS_SHORT_TRANSACTION_ELEMENT 0x70 +#define I2O_SGL_FLAGS_SGL_ATTRIBUTES_ELEMENT 0x7C + +#define I2O_SGL_FLAGS_BC0 0x01 +#define I2O_SGL_FLAGS_BC1 0x02 +#define I2O_SGL_FLAGS_DIR 0x04 +#define I2O_SGL_FLAGS_LOCAL_ADDRESS 0x08 + +#define I2O_SGL_FLAGS_CONTEXT_COUNT_MASK 0x03 +#define I2O_SGL_FLAGS_ADDRESS_MODE_MASK 0x3C +#define I2O_SGL_FLAGS_NO_CONTEXT 0x00 + +/* Scatter/Gather Truth Table */ + +/* + * + * typedef enum _SG_TYPE { + * INVALID, + * Ignore, + * TransportDetails, + * BitBucket, + * ImmediateData, + * Simple, + * PageList, + * ChainPointer, + * ShortTransaction, + * LongTransaction, + * SGLAttributes, + * INVALID/ReservedLongFormat, + * INVALID/ReservedShortFormat + * } SG_TYPE, *PSG_TYPE; + * + * + * 0x00 Ignore; + * 0x04 TransportDetails; + * 0x08 BitBucket; + * 0x0C ImmediateData; + * 0x10 Simple; + * 0x14 Simple; + * 0x18 Simple; + * 0x1C Simple; + * 0x20 PageList; + * 0x24 PageList; + * 0x28 PageList; + * 0x2C PageList; + * 0x30 ChainPointer; + * 0x34 INVALID; + * 0x38 ChainPointer; + * 0x3C INVALID; + * 0x40 LongTransaction; + * 0x44 INVALID/ReservedLongFormat; + * 0x48 BitBucket; + * 0x4C ImmediateData; + * 0x50 Simple; + * 0x54 Simple; + * 0x58 Simple; + * 0x5C Simple; + * 0x60 PageList; + * 0x64 PageList; + * 0x68 PageList; + * 0x6C PageList; + * 0x70 ShortTransaction; + * 0x74 INVALID/ReservedShortFormat; + * 0x78 INVALID/ReservedShortFormat; + * 0X7C SGLATTRIBUTES; + */ + + +/* 32 Bit Context Field defines */ + +#define I2O_SGL_FLAGS_CONTEXT32_NULL 0x00 +#define I2O_SGL_FLAGS_CONTEXT32_U32 0x01 +#define I2O_SGL_FLAGS_CONTEXT32_U64 0x02 +#define I2O_SGL_FLAGS_CONTEXT32_U96 0x03 + +#define I2O_SGL_FLAGS_CONTEXT32_NULL_SZ 0x00 +#define I2O_SGL_FLAGS_CONTEXT32_U32_SZ 0x04 +#define I2O_SGL_FLAGS_CONTEXT32_U64_SZ 0x08 +#define I2O_SGL_FLAGS_CONTEXT32_U96_SZ 0x0C + +/* 64 Bit Context Field defines */ + +#define I2O_SGL_FLAGS_CONTEXT64_NULL 0x00 +#define I2O_SGL_FLAGS_CONTEXT64_U64 0x01 +#define I2O_SGL_FLAGS_CONTEXT64_U128 0x02 +#define I2O_SGL_FLAGS_CONTEXT64_U192 0x03 + +#define I2O_SGL_FLAGS_CONTEXT64_NULL_SZ 0x00 +#define I2O_SGL_FLAGS_CONTEXT64_U64_SZ 0x08 +#define I2O_SGL_FLAGS_CONTEXT64_U128_SZ 0x10 +#define I2O_SGL_FLAGS_CONTEXT64_U192_SZ 0x18 + +/* SGL Attribute Element defines */ + +#define I2O_SGL_ATTRIBUTE_FLAGS_BIT_BUCKET_HINT 0x0400 +#define I2O_SGL_ATTRIBUTE_FLAGS_IMMEDIATE_DATA_HINT 0x0200 +#define I2O_SGL_ATTRIBUTE_FLAGS_LOCAL_ADDRESS_HINT 0x0100 +#define I2O_SGL_ATTRIBUTE_FLAGS_32BIT_TRANSACTION 0x0000 +#define I2O_SGL_ATTRIBUTE_FLAGS_64BIT_TRANSACTION 0x0004 +#define I2O_SGL_ATTRIBUTE_FLAGS_32BIT_LOCAL_ADDRESS 0x0000 + +/* SG Size defines */ + +#define I2O_SG_COUNT_SZ 24 +#define I2O_SG_FLAGS_SZ 8 + +/* Standard Flags and Count fields for SG Elements */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef union i2o_flags_count { + struct { + uint32_t Count:24; + uint32_t Flags:8; + } flags_count; + uint32_t cword; +} i2o_flags_count_t; + +#define get_flags_count_Count(p, hdl) (p)->flags_count.Count +#define put_flags_count_Count(p, v, hdl) ((p)->flags_count.Count = (v)) +#define get_flags_count_Flags(p, hdl) (p)->flags_count.Flags +#define put_flags_count_Flags(p, v, hdl) ((p)->flags_count.Flags = (v)) + +#endif + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef union i2o_flags_count { + struct { + uint32_t Flags:8; + uint32_t Count:24; + } flags_count; + uint32_t cword; +} i2o_flags_count_t; + +#define get_flags_count_Count(p, hdl) \ + (ddi_get32(hdl, &(p)->cword) & 0xFFFFFF) +#define put_flags_count_Count(p, v, hdl) \ + ddi_put32(hdl, &(p)->cword, \ + (ddi_get32(hdl, &(p)->cword) & ~0xFFFFFF) | \ + ((uint32_t)(v) & 0xFFFFFF)) +#define get_flags_count_Flags(p, hdl) \ + ((ddi_get32(hdl, &(p)->cword) >> 24) & 0xFF) +#define put_flags_count_Flags(p, v, hdl) \ + ddi_put32(hdl, &(p)->cword, \ + (ddi_get32(hdl, &(p)->cword) & ~0xFF000000) | ((uint32_t)(v) << 24)) +#endif + +/* Bit Bucket Element */ + +typedef struct i2o_sge_bit_bucket_element { + i2o_flags_count_t FlagsCount; + uint32_t BufferContext; +} i2o_sge_bit_bucket_element_t; + +/* Chain Addressing Scatter-Gather Element */ + +typedef struct i2o_sge_chain_element { + i2o_flags_count_t FlagsCount; + uint32_t PhysicalAddress; +} i2o_sge_chain_element_t; + +/* Chain Addressing with Context Scatter-Gather Element */ + +typedef struct i2o_sge_chain_context_element { + i2o_flags_count_t FlagsCount; + uint32_t Context[1]; + uint32_t PhysicalAddress; +} i2o_sge_chain_context_element_t; + +/* Ignore Scatter-Gather Element */ + +typedef struct i2o_sge_ignore_element { + i2o_flags_count_t FlagsCount; +} i2o_sge_ignore_element_t; + +/* Immediate Data Element */ + +typedef struct i2o_sge_immediate_data_element { + i2o_flags_count_t FlagsCount; +} i2o_sge_immediate_data_element_t; + +/* Immediate Data with Context Element */ + +typedef struct i2o_sge_immediate_data_context_element { + i2o_flags_count_t FlagsCount; + uint32_t BufferContext; +} i2o_sge_immediate_data_context_element_t; + +/* Long Transaction Parameters Element */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_sge_long_transaction_element { + union { + struct { + uint32_t LongElementLength:24; + uint32_t Flags:8; + } s1; + uint32_t w1; + } u1; + uint32_t BufferContext; +} i2o_sge_long_transaction_element_t; + +#define get_sge_long_LongElementLength(p, hdl) \ + (p)->u1.s1.LongElementLength +#define put_sge_long_LongElementLength(p, v, hdl) \ + ((p)->u1.s1.LongElementLength = (v)) +#define get_sge_long_Flags(p, hdl) \ + (p)->u1.s1.Flags +#define put_sge_long_Flags(p, v, hdl) \ + ((p)->u1.s1.Flags = (v)) + +#endif + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_sge_long_transaction_element { + union { + struct { + uint32_t Flags:8; + uint32_t LongElementLength:24; + } s1; + uint32_t w1; + } u1; + uint32_t BufferContext; +} i2o_sge_long_transaction_element_t; + +#define get_sge_long_LongElementLength(p, hdl) \ + (ddi_get32(hdl, &(p)->u1.w1) & 0xFFFFFF) +#define put_sge_long_LongElementLength(p, v, hdl) \ + ddi_put32(hdl, &(p)->u1.w1, \ + (ddi_get32(hdl, &(p)->u1.w1) & ~0xFFFFFF) | \ + ((uint32_t)(v) & 0xFFFFFF)) +#define get_sge_long_Flags(p, hdl) \ + (ddi_get32(hdl, &(p)->u1.w1) >> 24) +#define put_sge_long_Flags(p, v, hdl) \ + ddi_put32(hdl, &(p)->u1.w1, \ + (ddi_get32(hdl, &(p)->u1.w1) & ~0xFF000000) | \ + ((uint32_t)(v) << 24)) +#endif + +/* Page List Scatter-Gather Element */ + +typedef struct i2o_sge_page_element { + i2o_flags_count_t FlagsCount; + uint32_t PhysicalAddress[1]; +} i2o_sge_page_element_t; + +/* Page List with Context Scatter-Gather Element */ + +typedef struct i2o_sge_page_context_element { + i2o_flags_count_t FlagsCount; + uint32_t BufferContext[1]; + uint32_t PhysicalAddress[1]; +} i2o_sge_page_context_element_t; + +/* SGL Attribute Element */ + +typedef struct i2o_sge_sgl_attributes_element { + uint16_t SglAttributeFlags; + uint8_t ElementLength; + uint8_t Flags; + uint32_t PageFrameSize; +} i2o_sge_sgl_attributes_element_t; + +/* Short Transaction Parameters Element */ + +typedef struct i2o_sge_short_transaction_element { + uint16_t ClassFields; + uint8_t ElementLength; + uint8_t Flags; + uint32_t BufferContext; +} i2o_sge_short_transaction_element_t; + +/* Simple Addressing Scatter-Gather Element */ + +typedef struct i2o_sge_simple_element { + i2o_flags_count_t FlagsCount; + uint32_t PhysicalAddress; +} i2o_sge_simple_element_t; + +/* Simple Addressing with Context Scatter-Gather Element */ + +typedef struct i2o_sge_simple_context_element { + i2o_flags_count_t FlagsCount; + uint32_t BufferContext[1]; + uint32_t PhysicalAddress; +} i2o_sge_simple_context_element_t; + +/* Transport Detail Element */ + +typedef struct i2o_sge_transport_element { + uint_t LongElementLength:24; + uint_t Flags:8; +} i2o_sge_transport_element_t; + +typedef struct i2o_sg_element { + union { + /* Bit Bucket Element */ + i2o_sge_bit_bucket_element_t BitBucket; + + /* Chain Addressing Element */ + i2o_sge_chain_element_t Chain; + + /* Chain Addressing with Context Element */ + i2o_sge_chain_context_element_t ChainContext; + + /* Ignore Scatter-Gather Element */ + i2o_sge_ignore_element_t Ignore; + + /* Immediate Data Element */ + i2o_sge_immediate_data_element_t ImmediateData; + + /* Immediate Data with Context Element */ + i2o_sge_immediate_data_context_element_t ImmediateDataContext; + + /* Long Transaction Parameters Element */ + i2o_sge_long_transaction_element_t LongTransaction; + + /* Page List Element */ + i2o_sge_page_element_t Page; + + /* Page List with Context Element */ + i2o_sge_page_context_element_t PageContext; + + /* SGL Attribute Element */ + i2o_sge_sgl_attributes_element_t SGLAttribute; + + /* Short Transaction Parameters Element */ + i2o_sge_short_transaction_element_t ShortTransaction; + + /* Simple Addressing Element */ + i2o_sge_simple_element_t Simple[1]; + + /* Simple Addressing with Context Element */ + i2o_sge_simple_context_element_t SimpleContext[1]; + + /* Transport Detail Element */ + i2o_sge_transport_element_t Transport; + } u1; +} i2o_sg_element_t; + +/* ************************************************************************** */ +/* Basic Parameter Group Access */ +/* ************************************************************************** */ + +/* Operation Function Numbers */ + +#define I2O_PARAMS_OPERATION_FIELD_GET 0x0001 +#define I2O_PARAMS_OPERATION_LIST_GET 0x0002 +#define I2O_PARAMS_OPERATION_MORE_GET 0x0003 +#define I2O_PARAMS_OPERATION_SIZE_GET 0x0004 +#define I2O_PARAMS_OPERATION_TABLE_GET 0x0005 +#define I2O_PARAMS_OPERATION_FIELD_SET 0x0006 +#define I2O_PARAMS_OPERATION_LIST_SET 0x0007 +#define I2O_PARAMS_OPERATION_ROW_ADD 0x0008 +#define I2O_PARAMS_OPERATION_ROW_DELETE 0x0009 +#define I2O_PARAMS_OPERATION_TABLE_CLEAR 0x000A + +/* Operations List Header */ + +typedef struct i2o_param_operations_list_header { + uint16_t OperationCount; + uint16_t Reserved; +} i2o_param_operations_list_header_t; + +/* Results List Header */ + +typedef struct i2o_param_results_list_header { + uint16_t ResultCount; + uint16_t Reserved; +} i2o_param_results_list_header_t; + +/* Read Operation Result Block Template Structure */ + +typedef struct i2o_param_read_operation_result { + uint16_t BlockSize; + uint8_t BlockStatus; + uint8_t ErrorInfoSize; + /* Operations Results */ + /* Pad (if any) */ + /* ErrorInformation (if any) */ +} i2o_param_read_operation_result_t; + +typedef struct i2o_table_read_operation_result { + uint16_t BlockSize; + uint8_t BlockStatus; + uint8_t ErrorInfoSize; + uint16_t RowCount; + uint16_t MoreFlag; + /* Operations Results */ + /* Pad (if any) */ + /* ErrorInformation (if any) */ +} i2o_table_read_operation_result_t; + +/* Error Information Template Structure */ + +typedef struct i2o_param_error_info_template { + uint16_t OperationCode; + uint16_t GroupNumber; + uint16_t FieldIdx; + uint8_t AdditionalStatus; + uint8_t NumberKeys; + /* List of Key Values (variable) */ + /* Pad (if any) */ +} i2o_param_error_info_template_t; + +/* Operation Template for Specific Fields */ + +typedef struct i2o_param_operation_specific_template { + uint16_t Operation; + uint16_t GroupNumber; + uint16_t FieldCount; + uint16_t FieldIdx[1]; + /* Pad (if any) */ +} i2o_param_operation_specific_template_t; + +/* Operation Template for All Fields */ + +typedef struct i2o_param_operation_all_template { + uint16_t Operation; + uint16_t GroupNumber; + uint16_t FieldCount; + /* Pad (if any) */ +} i2o_param_operation_all_template_t; + +/* Operation Template for All List Fields */ + +typedef struct i2o_param_operation_all_list_template { + uint16_t Operation; + uint16_t GroupNumber; + uint16_t FieldCount; + uint16_t KeyCount; + uint8_t KeyValue; + /* Pad (if any) */ +} i2o_param_operation_all_list_template_t; + +/* Modify Operation Result Block Template Structure */ + +typedef struct i2o_param_modify_operation_result { + uint16_t BlockSize; + uint8_t BlockStatus; + uint8_t ErrorInfoSize; + /* ErrorInformation (if any) */ +} i2o_param_modify_operation_result_t; + +/* Operation Template for Row Delete */ + +typedef struct i2o_param_operation_row_delete_template { + uint16_t Operation; + uint16_t GroupNumber; + uint16_t RowCount; + uint8_t KeyValue; +} i2o_param_operation_row_delete_template_t; + +/* Operation Template for Table Clear */ + +typedef struct i2o_param_operation_table_clear_template { + uint16_t Operation; + uint16_t GroupNumber; +} i2o_param_operation_table_clear_template_t; + +/* Status codes and Error Information for Parameter functions */ + +#define I2O_PARAMS_STATUS_SUCCESS 0x00 +#define I2O_PARAMS_STATUS_BAD_KEY_ABORT 0x01 +#define I2O_PARAMS_STATUS_BAD_KEY_CONTINUE 0x02 +#define I2O_PARAMS_STATUS_BUFFER_FULL 0x03 +#define I2O_PARAMS_STATUS_BUFFER_TOO_SMALL 0x04 +#define I2O_PARAMS_STATUS_FIELD_UNREADABLE 0x05 +#define I2O_PARAMS_STATUS_FIELD_UNWRITEABLE 0x06 +#define I2O_PARAMS_STATUS_INSUFFICIENT_FIELDS 0x07 +#define I2O_PARAMS_STATUS_INVALID_GROUP_ID 0x08 +#define I2O_PARAMS_STATUS_INVALID_OPERATION 0x09 +#define I2O_PARAMS_STATUS_NO_KEY_FIELD 0x0A +#define I2O_PARAMS_STATUS_NO_SUCH_FIELD 0x0B +#define I2O_PARAMS_STATUS_NON_DYNAMIC_GROUP 0x0C +#define I2O_PARAMS_STATUS_OPERATION_ERROR 0x0D +#define I2O_PARAMS_STATUS_SCALAR_ERROR 0x0E +#define I2O_PARAMS_STATUS_TABLE_ERROR 0x0F +#define I2O_PARAMS_STATUS_WRONG_GROUP_TYPE 0x10 + + +/* ************************************************************************** */ +/* GROUP Parameter Groups */ +/* ************************************************************************** */ + +/* GROUP Configuration and Operating Structures and Defines */ + +/* Groups Numbers */ + +#define I2O_UTIL_PARAMS_DESCRIPTOR_GROUP_NO 0xF000 +#define I2O_UTIL_PHYSICAL_DEVICE_TABLE_GROUP_NO 0xF001 +#define I2O_UTIL_CLAIMED_TABLE_GROUP_NO 0xF002 +#define I2O_UTIL_USER_TABLE_GROUP_NO 0xF003 +#define I2O_UTIL_PRIVATE_MESSAGE_EXTENSIONS_GROUP_NO 0xF005 +#define I2O_UTIL_AUTHORIZED_USER_TABLE_GROUP_NO 0xF006 +#define I2O_UTIL_DEVICE_IDENTITY_GROUP_NO 0xF100 +#define I2O_UTIL_DDM_IDENTITY_GROUP_NO 0xF101 +#define I2O_UTIL_USER_INFORMATION_GROUP_NO 0xF102 +#define I2O_UTIL_SGL_OPERATING_LIMITS_GROUP_NO 0xF103 +#define I2O_UTIL_SENSORS_GROUP_NO 0xF200 + +/* UTIL Group F000h - GROUP DESCRIPTORS Parameter Group */ + +#define I2O_UTIL_GROUP_PROPERTIES_GROUP_TABLE 0x01 +#define I2O_UTIL_GROUP_PROPERTIES_ROW_ADDITION 0x02 +#define I2O_UTIL_GROUP_PROPERTIES_ROW_DELETION 0x04 +#define I2O_UTIL_GROUP_PROPERTIES_CLEAR_OPERATION 0x08 + +typedef struct i2o_util_group_descriptor_table { + uint16_t GroupNumber; + uint16_t FieldCount; + uint16_t RowCount; + uint8_t Properties; + uint8_t reserved; +} i2o_util_group_descriptor_table_t; + +/* UTIL Group F001h - Physical Device Table Parameter Group */ + +typedef struct i2o_util_physical_device_table { + uint32_t AdapterID; +} i2o_util_physical_device_table_t; + +/* UTIL Group F002h - Claimed Table Parameter Group */ + +typedef struct i2o_util_claimed_table { + uint16_t ClaimedTID; +} i2o_util_claimed_table_t; + +/* UTIL Group F003h - User Table Parameter Group */ + +typedef struct i2o_util_user_table { + uint16_t Instance; + uint16_t UserTID; + uint8_t ClaimType; + uint8_t reserved1; + uint16_t reserved2; +} i2o_util_user_table_t; + +/* UTIL Group F005h - Private Message Extensions Parameter Group */ + +typedef struct i2o_util_private_message_extensions_table { + uint16_t ExtInstance; + uint16_t OrganizationID; + uint16_t XFunctionCode; +} i2o_util_private_message_extensions_table_t; + +/* UTIL Group F006h - Authorized User Table Parameter Group */ + +typedef struct i2o_util_authorized_user_table { + uint16_t AlternateTID; +} i2o_util_authorized_user_table_t; + +/* UTIL Group F100h - Device Identity Parameter Group */ + +typedef struct i2o_util_device_identity_scalar { + uint32_t ClassID; + uint16_t OwnerTID; + uint16_t ParentTID; + uint8_t VendorInfo[I2O_DEVID_VENDOR_INFO_SZ]; + uint8_t ProductInfo[I2O_DEVID_PRODUCT_INFO_SZ]; + uint8_t Description[I2O_DEVID_DESCRIPTION_SZ]; + uint8_t ProductRevLevel[I2O_DEVID_REV_LEVEL_SZ]; + uint8_t SNFormat; + uint8_t SerialNumber[I2O_MAX_SERIAL_NUMBER_SZ]; +} i2o_util_device_identity_scalar_t; + +/* UTIL Group F101h - DDM Identity Parameter Group */ + +typedef struct i2o_util_ddm_identity_scalar { + uint16_t DdmTID; + uint8_t ModuleName[I2O_MODULE_NAME_SZ]; + uint8_t ModuleRevLevel[I2O_DEVID_REV_LEVEL_SZ]; + uint8_t SNFormat; + uint8_t SerialNumber[I2O_MAX_SERIAL_NUMBER_SZ]; +} i2o_util_ddm_identity_scalar_t; + +/* UTIL Group F102h - User Information Parameter Group */ + +#define I2O_USER_DEVICE_NAME_SZ 64 +#define I2O_USER_SERVICE_NAME_SZ 64 +#define I2O_USER_PHYSICAL_LOCATION_SZ 64 + +typedef struct i2o_util_user_information_scalar { + uint8_t DeviceName[I2O_USER_DEVICE_NAME_SZ]; + uint8_t ServiceName[I2O_USER_SERVICE_NAME_SZ]; + uint8_t PhysicalLocation[I2O_USER_PHYSICAL_LOCATION_SZ]; + uint32_t InstanceNumber; +} i2o_util_user_information_scalar_t; + +/* UTIL Group F103h - SGL Operating Limits Parameter Group */ + +typedef struct i2o_util_sgl_operating_limits_scalar { + uint32_t SglChainSize; + uint32_t SglChainSizeMax; + uint32_t SglChainSizeTarget; + uint16_t SglFragCount; + uint16_t SglFragCountMax; + uint16_t SglFragCountTarget; +} i2o_util_sgl_operating_limits_scalar_t; + +/* UTIL Group F200h - Sensors Parameter Group */ + +#define I2O_SENSOR_COMPONENT_OTHER 0x00 +#define I2O_SENSOR_COMPONENT_PLANAR_LOGIC_BOARD 0x01 +#define I2O_SENSOR_COMPONENT_CPU 0x02 +#define I2O_SENSOR_COMPONENT_CHASSIS 0x03 +#define I2O_SENSOR_COMPONENT_POWER_SUPPLY 0x04 +#define I2O_SENSOR_COMPONENT_STORAGE 0x05 +#define I2O_SENSOR_COMPONENT_EXTERNAL 0x06 + +#define I2O_SENSOR_SENSOR_CLASS_ANALOG 0x00 +#define I2O_SENSOR_SENSOR_CLASS_DIGITAL 0x01 + +#define I2O_SENSOR_SENSOR_TYPE_OTHER 0x00 +#define I2O_SENSOR_SENSOR_TYPE_THERMAL 0x01 +#define I2O_SENSOR_SENSOR_TYPE_DC_VOLTAGE 0x02 +#define I2O_SENSOR_SENSOR_TYPE_AC_VOLTAGE 0x03 +#define I2O_SENSOR_SENSOR_TYPE_DC_CURRENT 0x04 +#define I2O_SENSOR_SENSOR_TYPE_AC_CURRENT 0x05 +#define I2O_SENSOR_SENSOR_TYPE_DOOR_OPEN 0x06 +#define I2O_SENSOR_SENSOR_TYPE_FAN_OPERATIONAL 0x07 + +#define I2O_SENSOR_SENSOR_STATE_NORMAL 0x00 +#define I2O_SENSOR_SENSOR_STATE_ABNORMAL 0x01 +#define I2O_SENSOR_SENSOR_STATE_UNKNOWN 0x02 +#define I2O_SENSOR_SENSOR_STATE_LOW_CAT 0x03 +#define I2O_SENSOR_SENSOR_STATE_LOW 0x04 +#define I2O_SENSOR_SENSOR_STATE_LOW_WARNING 0x05 +#define I2O_SENSOR_SENSOR_STATE_HIGH_WARNING 0x06 +#define I2O_SENSOR_SENSOR_STATE_HIGH 0x07 +#define I2O_SENSOR_SENSOR_STATE_HIGH_CAT 0x08 + +#define I2O_SENSOR_EVENT_ENABLE_STATE_CHANGE 0x0001 +#define I2O_SENSOR_EVENT_ENABLE_LOW_CATASTROPHIC 0x0002 +#define I2O_SENSOR_EVENT_ENABLE_LOW_READING 0x0004 +#define I2O_SENSOR_EVENT_ENABLE_LOW_WARNING 0x0008 +#define I2O_SENSOR_EVENT_ENABLE_CHANGE_TO_NORMAL 0x0010 +#define I2O_SENSOR_EVENT_ENABLE_HIGH_WARNING 0x0020 +#define I2O_SENSOR_EVENT_ENABLE_HIGH_READING 0x0040 +#define I2O_SENSOR_EVENT_ENABLE_HIGH_CATASTROPHIC 0x0080 + +typedef struct i2o_util_sensors_table { + uint16_t SensorInstance; + uint8_t Component; + uint16_t ComponentInstance; + uint8_t SensorClass; + uint8_t SensorType; + int8_t ScalingExponent; + int32_t ActualReading; + int32_t MinimumReading; + int32_t Low2LowCatThreshold; + int32_t LowCat2LowThreshold; + int32_t LowWarn2LowThreshold; + int32_t Low2LowWarnThreshold; + int32_t Norm2LowWarnThreshold; + int32_t LowWarn2NormThreshold; + int32_t NominalReading; + int32_t HiWarn2NormThreshold; + int32_t Norm2HiWarnThreshold; + int32_t High2HiWarnThreshold; + int32_t HiWarn2HighThreshold; + int32_t HiCat2HighThreshold; + int32_t Hi2HiCatThreshold; + int32_t MaximumReading; + uint8_t SensorState; + uint16_t EventEnable; +} i2o_util_sensors_table_t; + +/* + * ************************************************************************* + * Definitions used in Solaris for I2O Framework support. + * + * (NOTE: Current commitment level is PROJECT PRIVATE.) + * ************************************************************************* + */ + +#define I2O_MSG_SLEEP DDI_DMA_SLEEP +#define I2O_MSG_DONTWAIT DDI_DMA_DONTWAIT + +typedef void *i2o_iop_handle_t; +typedef void *i2o_msg_handle_t; + +int i2o_msg_osm_register(dev_info_t *dip, i2o_iop_handle_t *handlep); +int i2o_msg_get_lct(i2o_iop_handle_t iop, void *buf, + size_t buf_size, size_t *lct_sizep, size_t *real_sizep); +int i2o_msg_alloc(i2o_iop_handle_t iop, int (*waitfp)(caddr_t), caddr_t arg, + void **msgp, i2o_msg_handle_t *msg_handlep, + ddi_acc_handle_t *acc_handlep); +int i2o_msg_send(i2o_iop_handle_t iop, void *msg, i2o_msg_handle_t handle); +void i2o_msg_osm_unregister(i2o_iop_handle_t *iop); + +/* + * PCI Extensions to I2O Spec 1.5. + * + * (Note: Should these definitons go into pci.h?) + */ +#define PCI_I2O_BASE_CLASS 0x0E +#define PCI_I2O_SUB_CLASS 0x00 +#define PCI_I2O_PROG_CLASS0 0x00 /* no IOP interrupt */ +#define PCI_I2O_PROG_CLASS1 0x01 /* IOP interrupt supported */ + +/* Offset definitions for FIFO registers in IOP's shared memory */ + +#define PCI_IOP_INBOUND_FREELIST_FIFO 0x40 +#define PCI_IOP_INBOUND_POSTLIST_FIFO 0x40 +#define PCI_IOP_OUTBOUND_FREELIST_FIFO 0x44 +#define PCI_IOP_OUTBOUND_POSTLIST_FIFO 0x44 + +/* Offset definitions for Interrupt Control registers in IOP's shared memory */ + +#define PCI_IOP_INTR_MASK_REG 0x34 +#define PCI_IOP_INTR_STATUS_REG 0x30 + +/* Bit definitions in Interrupt Mask Register */ +#define I2O_OUTBOUND_POSTLIST_SERVICE_INTR_MASK 0x08 + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_I2OMSG_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/uts/common/sys/i2o/i2omstr.h Wed Apr 18 11:32:14 2007 -0700 @@ -0,0 +1,920 @@ +/* + * Copyright (c) 1998-1999 by Sun Microsystems, Inc. + * All rights reserved. + */ + +/* + * ***************************************************************************** + * + * All software on this website is made available under the following terms and + * conditions. By downloading this software, you agree to abide by these terms + * and conditions with respect to this software. + * + * I2O SIG All rights reserved. + * + * These header files are provided, pursuant to your I2O SIG membership + * agreement, free of charge on an as-is basis without warranty of any kind, + * either express or implied, including but not limited to, implied warranties + * or merchantability and fitness for a particular purpose. I2O SIG does not + * warrant that this program will meet the user's requirements or that the + * operation of these programs will be uninterrupted or error-free. + * Acceptance and use of this program constitutes the user's understanding + * that he will have no recourse to I2O SIG for any actual or consequential + * damages including, but not limited to, loss profits arising out of use + * or inability to use this program. + * + * Member is permitted to create derivative works to this header-file program. + * However, all copies of the program and its derivative works must contain the + * I2O SIG copyright notice. + * + * ***************************************************************************** + */ + +#ifndef _SYS_I2OMSTOR_H +#define _SYS_I2OMSTOR_H + +#pragma ident "%Z%%M% %I% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#include <sys/i2o/i2omsg.h> /* the Base Message file */ +#include <sys/types.h> + + + +#define I2OMSTOR_REV 1_5_1 /* Header file revision string */ + + +/* + * **************************************************************************** + * + * I2OMStor.h -- I2O Random Block Storage Devices Class Message defintion + * file + * + * This file contains information presented in Chapter 6, Section 4 of + * the I2O Specification. + * + * Revision History: (Revision History tracks the revision number of the I2O + * specification) + * + * .92 - First marked revsion used for Proof of Concept. + * .93 - Change to match the rev .93 of the spec. + * .95 - Updated to Rev .95 of 2/5/96. + * 1.00 - Checked and Updated against spec version 1.00 4/9/96. + * 1.xx - Updated to the 1.x version of the I2O Specification (11/04/96). + * (RAID disk parameter group definition is not complete.) + * 1.xx - 11/06/96 1) Changed to new SGL addressing nomenclature. + * 2) Changed I2O_BSA_FLAGS reference to i2o_bsa_ctl_flags_t. + * 3) Added BSA request message definitions. + * 4) Commented out subclass and RAID request message definitions. + * 1.xx - 11/11/96 + * 1) Updated BSA Cache Control parameters group definitions. + * 1.xx - 11/13/96 + * 1) Changed messages definitions from "I20" to "I2O". + * 2) Fixed I2O_BSA_MEDIA_EJECT references. + * 3) Added "DSC" to Detailed Status Code definitions. + * 1.xx 11/15/96 - Added #pragma statments for i960. + * 1.5d 03/05/97 - Update for spec. draft version 1.5d. + * 1) Added "_BSA" designation to the three reply messages. + * 2) Added BSA_TIMEOUT DSC. + * 1.5d 04/11/97 - Corrections from review cycle: + * 1) Added reserved1 field to OPERATIONAL_CONTROL parameter group. + * 2) Added reserved2 field to ERROR_LOG parameter group. + * 3) Added reserved1 field to HIST_STATS parameter group. + * 4) Added reserved2 field to HIST_STATS parameter group. + * 5) Added reserved1 field to STORAGE_HIST_STATS parameter group. + * 6) Added reserved2 field to STORAGE_HIST_STATS parameter group. + * 7) Removed double underscore from MEDIA_INFO parameter group. + * 1.5.1 05/02/97 - Corrections from review cycle: + * 1) Change reply templates to include RetryCount field. + * 2) Add Aborted Operation reply message. + * 3) Remove #include for i2outil.h. + * 4) Add field to 32-bit align CACHE_CONTROL parameter group. + * 5) Add optional RAID parameter group definitions. + * 6) Add fields to 32-bit align REDUNDANCY parameter group. + * 7) Add fields to 32-bit align COMPONENT_SPARES parm group. + * 8) Add fields to 32-bit align ASSOCIATION parameter group. + * 9) Add revision string. + * 10) Convert tabs to spaces. + * 11) New disclaimer. + * + * **************************************************************************** + */ + +/* + * **************************************************************************** + * NOTES: + * + * Gets, reads, receives, etc. are all even numbered functions. + * Sets, writes, sends, etc. are all odd numbered functions. + * Functions that both send and receive data can be either but an attempt + * is made to use the function number that indicates the greater transfer + * amount. Functions that do not send or receive data use odd function + * numbers. + * + * Some functions are synonyms like read, receive and send, write. + * + * All common functions will have a code of less than 0x80. + * Unique functions to a class will start at 0x80. + * Executive Functions start at 0xA0. + * + * Utility Message function codes range from 0 - 0x1f + * Base Message function codes range from 0x20 - 0xfe + * Private Message function code is 0xff. + * ***************************************************************************** + */ + + + + +/* + * Random Block Storage Class specific functions + * + * Although the names are block storage class specific, the values + * assigned are common with other classes when applicable. + */ + +#define I2O_BSA_BLOCK_READ 0x30 +#define I2O_BSA_BLOCK_REASSIGN 0x71 +#define I2O_BSA_BLOCK_WRITE 0x31 +#define I2O_BSA_BLOCK_WRITE_VERIFY 0x33 +#define I2O_BSA_CACHE_FLUSH 0x37 +#define I2O_BSA_DEVICE_RESET 0x27 +#define I2O_BSA_MEDIA_EJECT 0x43 +#define I2O_BSA_MEDIA_FORMAT 0x45 +#define I2O_BSA_MEDIA_LOCK 0x49 +#define I2O_BSA_MEDIA_MOUNT 0x41 +#define I2O_BSA_MEDIA_UNLOCK 0x4B +#define I2O_BSA_MEDIA_VERIFY 0x35 +#define I2O_BSA_POWER_MANAGEMENT 0x70 +#define I2O_BSA_STATUS_CHECK 0x25 + +/* RAID Additions. */ +/* + * #define I2O_MANAGEMENT 0x81 + * #define I2O_DIAGNOSTICS 0x83 + * #define I2O_INSTRUMENTATION 0x85 + */ + +/* Detailed Status Codes for Random Block Storage operations */ + +#define I2O_BSA_DSC_SUCCESS 0x0000 +#define I2O_BSA_DSC_MEDIA_ERROR 0x0001 +#define I2O_BSA_DSC_ACCESS_ERROR 0x0002 +#define I2O_BSA_DSC_DEVICE_FAILURE 0x0003 +#define I2O_BSA_DSC_DEVICE_NOT_READY 0x0004 +#define I2O_BSA_DSC_MEDIA_NOT_PRESENT 0x0005 +#define I2O_BSA_DSC_MEDIA_LOCKED 0x0006 +#define I2O_BSA_DSC_MEDIA_FAILURE 0x0007 +#define I2O_BSA_DSC_PROTOCOL_FAILURE 0x0008 +#define I2O_BSA_DSC_BUS_FAILURE 0x0009 +#define I2O_BSA_DSC_ACCESS_VIOLATION 0x000A +#define I2O_BSA_DSC_WRITE_PROTECTED 0x000B +#define I2O_BSA_DSC_DEVICE_RESET 0x000C +#define I2O_BSA_DSC_VOLUME_CHANGED 0x000D +#define I2O_BSA_DSC_TIMEOUT 0x000E + + +/* ************************************************************************** */ + +/* Block Storage Parameter Groups */ + +/* ************************************************************************* */ + +/* Block Storage Configuration and Operating Structures and Defines */ + +/* Block Storage Parameter Groups */ + +#define I2O_BSA_DEVICE_INFO_GROUP_NO 0x0000 +#define I2O_BSA_OPERATIONAL_CONTROL_GROUP_NO 0x0001 +#define I2O_BSA_POWER_CONTROL_GROUP_NO 0x0002 +#define I2O_BSA_CACHE_CONTROL_GROUP_NO 0x0003 +#define I2O_BSA_MEDIA_INFO_GROUP_NO 0x0004 +#define I2O_BSA_ERROR_LOG_GROUP_NO 0x0005 + +/* Block Storage Optional Historical Statistics Parameter Groups */ + +#define I2O_BSA_HISTORICAL_STATS_CONTROL_GROUP_NO 0x0180 +#define I2O_BSA_STORAGE_HISTORICAL_STATS_GROUP_NO 0x0181 +#define I2O_BSA_CACHE_HISTORICAL_STATS_GROUP_NO 0x0182 + +/* Block Storage Optional RAID Disk Parameter Groups */ + +#define I2O_BSA_VOLUME_SET_INFORMATION_GROUP_NO 0x0200 +#define I2O_BSA_PROTECTED_SPACE_EXTENT_GROUP_NO 0x0201 +#define I2O_BSA_AGGREGATE_PROT_SPACE_EXT_GROUP_NO 0x0202 +#define I2O_BSA_PHYSICAL_EXTENT_GROUP_NO 0x0203 +#define I2O_BSA_AGGREGATE_PHYSICAL_EXT_GROUP_NO 0x0204 +#define I2O_BSA_REDUNDANCY_GROUP_NO 0x0205 +#define I2O_BSA_COMPONENT_SPARES_GROUP_NO 0x0206 +#define I2O_BSA_ASSOCIATION_TABLE_GROUP_NO 0x0207 + + +/* - 0000h - Device Information Parameters Group defines */ + +/* Device Type */ + +#define I2O_BSA_DEVICE_TYPE_DIRECT 0x00 +#define I2O_BSA_DEVICE_TYPE_WORM 0x04 +#define I2O_BSA_DEVICE_TYPE_CDROM 0x05 +#define I2O_BSA_DEVICE_TYPE_OPTICAL 0x07 + +/* Device Capability Support */ + +#define I2O_BSA_DEV_CAP_CACHING 0x00000001 +#define I2O_BSA_DEV_CAP_MULTI_PATH 0x00000002 +#define I2O_BSA_DEV_CAP_DYNAMIC_CAPACITY 0x00000004 +#define I2O_BSA_DEV_CAP_REMOVABLE_MEDIA 0x00000008 +#define I2O_BSA_DEV_CAP_REMOVEABLE_DEVICE 0x00000010 +#define I2O_BSA_DEV_CAP_READ_ONLY 0x00000020 +#define I2O_BSA_DEV_CAP_LOCKOUT 0x00000040 +#define I2O_BSA_DEV_CAP_BOOT_BYPASS 0x00000080 +#define I2O_BSA_DEV_CAP_COMPRESSION 0x00000100 +#define I2O_BSA_DEV_CAP_DATA_SECURITY 0x00000200 +#define I2O_BSA_DEV_CAP_RAID 0x00000400 + +/* Device States */ + +#define I2O_BSA_DEV_STATE_CACHING 0x00000001 +#define I2O_BSA_DEV_STATE_POWERED_ON 0x00000002 +#define I2O_BSA_DEV_STATE_READY 0x00000004 +#define I2O_BSA_DEV_STATE_MEDIA_LOADED 0x00000008 +#define I2O_BSA_DEV_STATE_DEVICE_LOADED 0x00000010 +#define I2O_BSA_DEV_STATE_READ_ONLY 0x00000020 +#define I2O_BSA_DEV_STATE_LOCKOUT 0x00000040 +#define I2O_BSA_DEV_STATE_BOOT_BYPASS 0x00000080 +#define I2O_BSA_DEV_STATE_COMPRESSION 0x00000100 +#define I2O_BSA_DEV_STATE_DATA_SECURITY 0x00000200 +#define I2O_BSA_DEV_STATE_RAID 0x00000400 + + +/* - 0001h - Operational Control Parameters Group defines */ + +/* No definition required */ + + +/* - 0002h - Power Control Parameters Group defines */ + +/* On Access */ + +#define I2O_BSA_POWERED_UP_ON_ACCESS 0x00000001 +#define I2O_BSA_LOAD_ON_ACCESS 0x00000002 + + +/* - 0003h - Cache Control Parameters Group defines */ + +/* Write Policy */ + +#define I2O_BSA_NO_WRITE_CACHE 0x00 +#define I2O_BSA_WRITE_TO_CACHE 0x01 +#define I2O_BSA_WRITE_THRU_CACHE 0x02 + +/* Read Policy */ + +#define I2O_BSA_NO_READ_CACHE 0x00 +#define I2O_BSA_READ_CACHE 0x01 +#define I2O_BSA_READ_AHEAD_CACHE 0x02 +#define I2O_BSA_READ_READ_AHEAD_CACHE 0x03 + +/* Error Correction */ + +#define I2O_BSA_ERR_COR_NONE 0x00 +#define I2O_BSA_ERR_COR_UNKNOWN 0x01 +#define I2O_BSA_ERR_COR_OTHER 0x02 +#define I2O_BSA_ERR_COR_PARITY 0x03 +#define I2O_BSA_ERR_COR_SINGLE_BIT_ECC 0x04 +#define I2O_BSA_ERR_COR_MULTI_BIT_ECC 0x05 + + +/* - 0004h - Media Information Parameters Group defines */ + +/* No definition required */ + + +/* - 0005h - Error Log Parameters Group defines */ + +/* No definition required */ + + +/* - 0180h - Historical Statistics Control Parameters Group defines */ + +/* Statistis Control */ + +#define I2O_BSA_STAT_CTL_STORAGE_ENABLE 0x01 +#define I2O_BSA_STAT_CTL_CACHE_ENABLE 0x02 + + +/* - 0181h - Storage Historical Statistics Parameter Group defines */ + +/* No definition required */ + + +/* - 0182h - Cache Historical Statistics Parameter Group defines */ + +/* No definition required */ + + +/* - 0200H - Volume Set Information Parameter Group defines */ + +/* No definition required */ + + +/* - 0201h - Protected Space Extent Parameter Group defines */ + +/* Data Stripe Granularity */ + +#define I2O_BSA_DATA_STRIPE_OTHER 0x00 +#define I2O_BSA_DATA_STRIPE_UNKNOWN 0x01 +#define I2O_BSA_DATA_STRIPE_BITS 0x02 +#define I2O_BSA_DATA_STRIPE_BYTES 0x03 +#define I2O_BSA_DATA_STRIPE_16BIT_WORDS 0x04 +#define I2O_BSA_DATA_STRIPE_32BIT_DWORDS 0x05 +#define I2O_BSA_DATA_STRIPE_BLOCKS 0x06 + +/* - 0202h - Aggregate Protected Space Extent Parameter Group defines */ + +/* No definition required */ + + +/* - 0203h - Physical Extent Parameter Group defines */ + +/* Granularity Unit */ + +#define I2O_BSA_GRANULARITY_OTHER 0x00 +#define I2O_BSA_GRANULARITY_UNKNOWN 0x01 +#define I2O_BSA_GRANULARITY_BITS 0x02 +#define I2O_BSA_GRANULARITY_BYTES 0x03 +#define I2O_BSA_GRANULARITY_16BIT_WORDS 0x04 +#define I2O_BSA_GRANULARITY_32BIT_DWORDS 0x05 +#define I2O_BSA_GRANULARITY_BLOCKS 0x06 + + +/* - 0204h - Aggregate Physical Extent Parameter Group defines */ + +/* No definition required */ + + +/* - 0205h - Redundancy Parameter Group defines */ + +/* Redundancy Type */ + +#define I2O_BSA_REDUNDANCY_OTHER 0x00 +#define I2O_BSA_REDUNDANCY_UNKNOWN 0x01 +#define I2O_BSA_REDUNDANCY_NONE 0x02 +#define I2O_BSA_REDUNDANCY_COPY 0x03 +#define I2O_BSA_REDUNDANCY_XOR 0x04 +#define I2O_BSA_REDUNDANCY_P_Q 0x05 +#define I2O_BSA_REDUNDANCY_S 0x06 +#define I2O_BSA_REDUNDANCY_P_S 0x07 + + +/* - 0206h - Component Spares Parameter Group defines */ + +/* Spare Functioning State */ + +#define I2O_BSA_SPARE_STATE_OTHER 0x00 +#define I2O_BSA_SPARE_STATE_UNKNOWN 0x01 +#define I2O_BSA_SPARE_STATE_INACTIVE 0x02 +#define I2O_BSA_SPARE_STATE_ACTIVE 0x03 +#define I2O_BSA_SPARE_STATE_LOAD_BALANCE 0x04 + + +/* - 0207h - Association Table Parameter Group defines */ + +/* Type */ + +#define I2O_BSA_ASSOC_TYPE_PHYSICAL 0x00 +#define I2O_BSA_ASSOC_TYPE_LOGICAL 0x01 +#define I2O_BSA_ASSOC_TYPE_LOG_TO_PHYS 0x02 +#define I2O_BSA_ASSOC_TYPE_PROTECTION 0x03 +#define I2O_BSA_ASSOC_TYPE_SPARE 0x04 +#define I2O_BSA_ASSOC_TYPE_CACHE 0x05 +#define I2O_BSA_ASSOC_TYPE_SOFTWARE 0x06 + +/* Object 1 Type */ + +#define I2O_BSA_OBJECT_1_CONTROLLER 0x00 +#define I2O_BSA_OBJECT_1_DEVICE 0x01 +#define I2O_BSA_OBJECT_1_BUS_PORT 0x02 +#define I2O_BSA_OBJECT_1_VOLUME_SET 0x03 +#define I2O_BSA_OBJECT_1_PROT_SPACE_EXT 0x04 +#define I2O_BSA_OBJECT_1_AGG_PROT_SPACE_EXT 0x05 +#define I2O_BSA_OBJECT_1_PHYSICAL_EXT 0x06 +#define I2O_BSA_OBJECT_1_AGG_PHYSICAL_EXT 0x07 +#define I2O_BSA_OBJECT_1_REDUNDANCY 0x08 +#define I2O_BSA_OBJECT_1_CACHE 0x09 +#define I2O_BSA_OBJECT_1_SOFTWARE 0x0A + +/* Object 2 Type */ + +#define I2O_BSA_OBJECT_2_CONTROLLER 0x00 +#define I2O_BSA_OBJECT_2_DEVICE 0x01 +#define I2O_BSA_OBJECT_2_BUS_PORT 0x02 +#define I2O_BSA_OBJECT_2_VOLUME_SET 0x03 +#define I2O_BSA_OBJECT_2_PROT_SPACE_EXT 0x04 +#define I2O_BSA_OBJECT_2_AGG_PROT_SPACE_EXT 0x05 +#define I2O_BSA_OBJECT_2_PHYSICAL_EXT 0x06 +#define I2O_BSA_OBJECT_2_AGG_PHYSICAL_EXT 0x07 +#define I2O_BSA_OBJECT_2_REDUNDANCY 0x08 +#define I2O_BSA_OBJECT_2_CACHE 0x09 +#define I2O_BSA_OBJECT_2_SOFTWARE 0x0A + + + + +/* Block Storage Group 0000h - Device Information Parameter Group */ + +typedef struct i2o_bsa_device_info_scalar { + uint8_t DeviceType; + uint8_t NumberOfPaths; + uint16_t PowerState; + uint32_t BlockSize; + uint64_t DeviceCapacity; + uint32_t DeviceCapabilitySupport; + uint32_t DeviceState; +} i2o_bsa_device_info_scalar_t; + + +/* Block Storage Group 0001h - Operational Control Parameter Group */ + +typedef struct i2o_bsa_operational_control_scalar { + uint8_t AutoReassign; + uint8_t ReassignTolerance; + uint8_t RetryAttempts; + uint8_t reserved1; + uint32_t ReassignSize; + uint32_t ExpectedTimeout; + uint32_t RWVTimeout; + uint32_t RWVTimeoutBase; + uint32_t TimeoutBase; + uint32_t OrderedRequestDepth; + uint32_t AtomicWriteSize; +} i2o_bsa_operational_control_scalar_t; + + +/* Block Storage Group 0002h - Power Control Parameter Group */ + +typedef struct i2o_bsa_power_control_scalar { + uint32_t PowerdownTimeout; + uint32_t OnAccess; +} i2o_bsa_power_control_scalar_t; + + +/* Block Storage Group 0003h - Cache Control Parameter Group */ + +typedef struct i2o_bsa_cache_control_scalar { + uint32_t TotalCacheSize; + uint32_t ReadCacheSize; + uint32_t WriteCacheSize; + uint8_t WritePolicy; + uint8_t ReadPolicy; + uint8_t ErrorCorrection; + uint8_t reserved1; /* Note: not in 1.5 spec. */ +} i2o_bsa_cache_control_scalar_t; + + +/* Block Storage Group 0004h - Media Information Parameter Group */ + +typedef struct i2o_bsa_media_info_scalar { + uint64_t Capacity; + uint32_t BlockSize; +} i2o_bsa_media_info_scalar_t; + + +/* Block Storage Group 0005h - Error Log Parameter Group */ + +typedef struct i2o_bsa_error_log_table { + uint16_t ErrorDataIndex; + uint8_t Function; + uint8_t RetryCount; + uint16_t DetailedErrorCode; + uint16_t reserved2; + uint64_t TimeStamp; + uint32_t UserInfo; +} i2o_bsa_error_log_table_t; + + +/* Block Storage Group 0180h - Optional Historical STATS Support/Control */ + +typedef struct i2o_bsa_hist_stats_scalar { + uint8_t StatisticsControl; + uint8_t reserved1; + uint16_t reserved2; + uint32_t StorageStatistics; + uint32_t CacheStatistics; +} i2o_bsa_hist_stats_scalar_t; + + +/* Block Storage Group 0181h - Optional Storage Historical STATS */ + +typedef struct i2o_bsa_storage_hist_stats_scalar { + uint64_t ReadCommands; + uint64_t WriteCommands; + uint8_t DataUnit; + uint8_t reserved1; + uint16_t reserved2; + uint64_t IORange1Read; + uint64_t IORange2Read; + uint64_t IORange3Read; + uint64_t IORange4Read; + uint64_t IORange1Write; + uint64_t IORange2Write; + uint64_t IORange3Write; + uint64_t IORange4Write; + uint64_t NumberSeeks; +} i2o_bsa_storage_hist_stats_scalar_t; + + +/* Block Storage Group 0182h - Optional Cache Historical STATS */ + +typedef struct i2o_bsa_cache_hist_stats_scalar { + uint64_t CacheAccess; + uint64_t CacheHit; + uint64_t PartialCacheHit; + uint64_t HitDataSize; + uint32_t ValidUsage; + uint32_t DirtyUsage; + uint32_t TimeLastFault; + uint32_t LastFaultFailure; +} i2o_bsa_cache_hist_stats_scalar_t; + + +/* Block Storage Group 0200h - Optional Volume Set Information */ + +typedef struct i2o_bsa_volume_info_scalar { + uint8_t Name[64]; + uint64_t TotalStorageCapacity; + uint64_t StripeLength; + uint64_t InterleaveDepth; +} i2o_bsa_volume_info_scalar_t; + + +/* Block Storage Group 0201h - Optional Protected Space Extent */ + +typedef struct i2o_bsa_pro_space_ext_scalar { + uint64_t StartAddress; + uint64_t NumberBlocks; + uint32_t BlockSize; + uint32_t DataStripeGranularity; + uint32_t DataStripeLength; +} i2o_bsa_pro_space_ext_scalar_t; + + +/* Block Storage Group 0202h - Optional Aggregate Protected Space Extent */ + +typedef struct i2o_bsa_agg_prot_space_ext_scalar { + uint64_t NumberBlocks; +} i2o_bsa_agg_prot_space_ext_scalar_t; + + +/* Block Storage Group 0203h - Optional Physical Extent */ + +typedef struct i2o_bsa_phys_ext_scalar { + uint64_t StartAddress; + uint64_t NumberBlocks; + uint32_t BlockSize; + uint32_t GranularityUnit; + uint64_t CheckDataInterleave; + uint64_t CheckData; + uint64_t UserData; +} i2o_bsa_phys_ext_scalar_t; + + +/* Block Storage Group 0204h - Optional Aggregate Physical Extent */ + +typedef struct i2o_bsa_agg_phys_ext_scalar { + uint64_t NumberBlocks; + uint64_t CheckData; +} i2o_bsa_agg_phys_ext_scalar_t; + + +/* Block Storage Group 0205h - Optional Redundancy Table */ + +typedef struct i2o_bsa_redundancy_scalar { + uint8_t RedundancyType; + uint8_t reserved1; /* Note: not in 1.5 spec. */ + uint16_t reserved2; /* Note: not in 1.5 spec. */ +} i2o_bsa_redundancy_scalar_t; + + +/* Block Storage Group 0206h - Optional Component Spares */ + +typedef struct i2o_bsa_component_spares_table { + uint8_t RowNumber; + uint8_t SpareType; + uint8_t ToBeSparedIndex; + uint8_t SparedIndex; + uint8_t SpareFunctioningState; + uint8_t reserved1; /* Note: not in 1.5 spec. */ + uint16_t reserved2; /* Note: not in 1.5 spec. */ +} i2o_bsa_component_spares_table_t; + + +/* Block Storage Group 0207h - Optional Association Table */ + +typedef struct i2o_bsa_association_table { + uint8_t RowNumber; + uint8_t Type; + uint8_t Object1Type; + uint8_t Object1Index; + uint8_t Object2Type; + uint8_t Object2Index; + uint16_t reserved2; /* Note: not in 1.5 spec. */ +} i2o_bsa_association_table_t; + + + +/* I2O BSA Block Storage Event Indicator Assignment */ + +#define I2O_BSA_EVENT_VOLUME_LOAD 0x00000001 +#define I2O_BSA_EVENT_VOLUME_UNLOAD 0x00000002 +#define I2O_BSA_EVENT_VOLUME_UNLOAD_REQUEST 0x00000004 +#define I2O_BSA_EVENT_CAPACITY_CHANGE 0x00000008 +#define I2O_BSA_EVENT_SCSI_SMART 0x00000010 + + + + +/* Block Storage Class Specific Message Definitions */ + + +/* I2O Block Storage Reply Message Frame Template */ + +typedef struct i2o_bsa_reply_message_frame { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint16_t DetailedStatusCode; + uint8_t RetryCount; + uint8_t ReqStatus; +/* ReplyPayload */ +} i2o_bsa_reply_message_frame_t; + + + +/* I2O Block Storage Successful Completion Reply Message Frame */ + +typedef struct i2o_bsa_success_reply_message_frame { + i2o_bsa_reply_message_frame_t BsaReplyFrame; + uint32_t TransferCount; +} i2o_bsa_success_reply_message_frame_t; + + + +/* I2O Block Storage Aborted Operation Reply Message Frame */ + +typedef struct i2o_bsa_abort_reply_message_frame { + i2o_bsa_reply_message_frame_t BsaReplyFrame; +} i2o_bsa_abort_reply_message_frame_t; + + + +/* I2O Block Storage Progress Report Reply Message Frame */ + +typedef struct i2o_bsa_progress_reply_message_frame { + i2o_bsa_reply_message_frame_t BsaReplyFrame; + uint8_t PercentComplete; + uint8_t Reserved[3]; +} i2o_bsa_progress_reply_message_frame_t; + + +/* I2O Block Storage Error Report Reply Message Frame */ + +typedef struct i2o_bsa_error_reply_message_frame { + i2o_bsa_reply_message_frame_t BsaReplyFrame; + uint32_t TransferCount; + uint64_t LogicalByteAddress; +} i2o_bsa_error_reply_message_frame_t; + + + + +/* I2O BSA request message flag definitions */ + +/* I2O BSA Control Flags */ + +typedef uint16_t i2o_bsa_ctl_flags_t; + +#define I2O_BSA_FLAG_PROGRESS_REPORT 0x0080 + +/* I2O BSA Block Read Message Control Flags */ + +typedef uint16_t i2o_bsa_read_flags_t; +#define I2O_BSA_RD_FLAG_DONT_RETRY 0x0001 +#define I2O_BSA_RD_FLAG_SOLO 0x0002 +#define I2O_BSA_RD_FLAG_CACHE_READ 0x0004 +#define I2O_BSA_RD_FLAG_READ_PREFETCH 0x0008 +#define I2O_BSA_RD_FLAG_CACHE_DATA 0x0010 + +/* I2O BSA Block Write Message Control Flags */ + +typedef uint16_t i2o_bsa_write_flags_t; +#define I2O_BSA_WR_FLAG_DONT_RETRY 0x0001 +#define I2O_BSA_WR_FLAG_SOLO 0x0002 +#define I2O_BSA_WR_FLAG_DONT_CACHE 0x0004 +#define I2O_BSA_WR_FLAG_WRITE_THRU 0x0008 +#define I2O_BSA_WR_FLAG_WRITE_TO 0x0010 + +/* I2O BSA Device Reset Message Control Flags */ + +typedef uint16_t i2o_bsa_reset_flags_t; +#define I2O_BSA_FLAG_HARD_RESET 0x0001 + +/* I2O BSA Media Verify Message Control Flags */ + +typedef uint16_t i2o_bsa_verify_flags_t; +/* Progress Report flag definition is valid */ +#define I2O_BSA_ERROR_CORRECTION 0x0040 + + +/* I2O BSA Removeable Media Identifier values */ + +typedef uint32_t i2o_bsa_media_id_t; +#define I2O_BSA_MEDIA_ID_CURRENT_MOUNTED 0xFFFFFFFF + + +/* I2O BSA Removeable Media Load Flags */ + +typedef uint8_t i2o_bsa_load_flags_t; +#define I2O_BSA_LOAD_FLAG_MEDIA_LOCK 0x80 + + +/* I2O BSA Power Management Operation values */ + +typedef uint8_t i2o_bsa_operation_t; +#define I2O_BSA_POWER_MGT_PARTIAL_POWER_UP 0x01 +#define I2O_BSA_POWER_MGT_POWER_UP 0x02 +#define I2O_BSA_POWER_MGT_POWER_UP_LOAD 0x03 +#define I2O_BSA_POWER_MGT_QUIESCE_DEVICE 0x20 +#define I2O_BSA_POWER_MGT_PARTIAL_POWER_DOWN 0x21 +#define I2O_BSA_POWER_MGT_PARTIAL_POWER_DOWN_UNLOAD 0x22 +#define I2O_BSA_POWER_MGT_POWER_DOWN_UNLOAD 0x23 +#define I2O_BSA_POWER_MGT_POWER_DOWN_RETAIN 0x24 + + + +/* I2O BSA Block Read Message Frame */ + +typedef struct i2o_bsa_read_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + i2o_bsa_read_flags_t ControlFlags; + uint8_t TimeMultiplier; + uint8_t FetchAhead; + uint32_t TransferByteCount; + uint64_t LogicalByteAddress; + i2o_sg_element_t SGL; +} i2o_bsa_read_message_t; + + + +/* I2O BSA Block Reassign Message Frame */ + +typedef struct i2o_bsa_block_reassign_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint16_t Reserved1; + uint8_t TimeMultiplier; + uint8_t Reserved2; + i2o_sg_element_t SGL; +} i2o_bsa_block_reassign_message_t; + + + +/* I2O BSA Block Write Message Frame */ + +typedef struct i2o_bsa_write_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + i2o_bsa_write_flags_t ControlFlags; + uint8_t TimeMultiplier; + uint8_t Reserved; + uint32_t TransferByteCount; + uint64_t LogicalByteAddress; + i2o_sg_element_t SGL; +} i2o_bsa_write_message_t; + + + +/* I2O BSA Block Write and Verify Message Frame */ + +typedef struct i2o_bsa_write_verify_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + i2o_bsa_write_flags_t ControlFlags; + uint8_t TimeMultiplier; + uint8_t Reserved; + uint32_t TransferByteCount; + uint64_t LogicalByteAddress; + i2o_sg_element_t SGL; +} i2o_bsa_write_verify_message_t; + + + +/* I2O BSA Cache Flush Message Frame */ + +typedef struct i2o_bsa_cache_flush_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + i2o_bsa_ctl_flags_t ControlFlags; + uint8_t TimeMultiplier; + uint8_t Reserved; +} i2o_bsa_cache_flush_message_t; + + + +/* I2O BSA Device Reset Message Frame */ + +typedef struct _12o_bsa_device_reset_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + i2o_bsa_reset_flags_t ControlFlags; + uint8_t TimeMultiplier; + uint8_t Reserved; +} i2o_bsa_device_reset_message_t; + + + +/* I2O BSA Media Eject for Removeable Media Message Frame */ + +typedef struct i2o_bsa_media_eject_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + i2o_bsa_media_id_t MediaIdentifier; +} i2o_bsa_media_eject_message_t; + + + +/* I2O BSA Media Lock Message Frame */ + +typedef struct i2o_bsa_media_lock_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + i2o_bsa_media_id_t MediaIdentifier; +} i2o_bsa_media_lock_message_t; + + + +/* I2O BSA Media Mount for Removeable Media Message Frame */ + +typedef struct i2o_bsa_media_mount_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + i2o_bsa_media_id_t MediaIdentifier; + i2o_bsa_load_flags_t LoadFlags; + uint8_t Reserved[3]; +} i2o_bsa_media_mount_message_t; + + + +/* I2O BSA Media Unlock Message Frame */ + +typedef struct i2o_bsa_media_unlock_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + i2o_bsa_media_id_t MediaIdentifier; +} i2o_bsa_media_unlock_message_t; + + + +/* I2O BSA Media Verify Message Frame */ + +typedef struct i2o_bsa_media_verify_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + i2o_bsa_verify_flags_t ControlFlags; + uint8_t TimeMultiplier; + uint8_t Reserved; + uint32_t ByteCount; + uint64_t LogicalByteAddress; +} i2o_bsa_media_verify_message_t; + + + +/* I2O BSA Power Management Message Frame */ + +typedef struct i2o_bsa_power_management_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + i2o_bsa_ctl_flags_t ControlFlags; + uint8_t TimeMultiplier; + uint8_t ReplyType; + i2o_bsa_operation_t Operation; +} i2o_bsa_power_management_message_t; + + + +/* I2O BSA Status Check Message Frame */ + +typedef struct i2o_bsa_status_check_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; +} i2o_bsa_status_check_message_t; + + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_I2OMSTOR_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/uts/common/sys/i2o/i2outil.h Wed Apr 18 11:32:14 2007 -0700 @@ -0,0 +1,391 @@ +/* + * ********************************************************************* + * All software on this website is made available under the following + * terms and conditions. By downloading this software, you agree to + * abide by these terms and conditions with respect to this software. + * + * I2O SIG All rights reserved. + * + * These header files are provided, pursuant to your I2O SIG membership + * agreement, free of charge on an as-is basis without warranty of any + * kind, either express or implied, including but not limited to, + * implied warranties or merchantability and fitness for a particular + * purpose. I2O SIG does not warrant that this program will meet the + * user's requirements or that the operation of these programs will be + * uninterrupted or error-free. Acceptance and use of this program + * constitutes the user's understanding that he will have no recourse + * to I2O SIG for any actual or consequential damages including, but + * not limited to, loss profits arising out of use or inability to use + * this program. + * + * Member is permitted to create deriavative works to this header-file + * program. However, all copies of the program and its derivative + * works must contain the I2O SIG copyright notice. + * ******************************************************************** + */ + +/* + * ******************************************************************** + * I2OUtil.h -- I2O Utility Class Message defintion file + * + * This file contains information presented in Chapter 6 of the I2O + * Specification. + * ******************************************************************** + */ + +/* + * Copyright (c) 1998 by Sun Microsystems, Inc. + * All rights reserved. + */ + +#ifndef _SYS_I2OUTIL_H +#define _SYS_I2OUTIL_H + +#pragma ident "%W% %E% SMI" + +#ifdef __cplusplus +extern "C" { +#endif + +#define I2OUTIL_REV 1_5_4 /* I2OUtil header file revision string */ + +#include <sys/i2o/i2omsg.h> /* Include the Base Message file */ + +/* + * ******************************************************************** + * NOTES: + * + * Gets, reads, receives, etc. are all even numbered functions. + * Sets, writes, sends, etc. are all odd numbered functions. + * Functions that both send and receive data can be either but an attempt is + * made to use the function number that indicates the greater transfer amount. + * Functions that do not send or receive data use odd function numbers. + * + * Some functions are synonyms like read, receive and send, write. + * + * All common functions will have a code of less than 0x80. + * Unique functions to a class will start at 0x80. + * Executive Functions start at 0xA0. + * + * Utility Message function codes range from 0 - 0x1f + * Base Message function codes range from 0x20 - 0xfe + * Private Message function code is 0xff. + * ******************************************************************** + */ + +/* Utility Message class functions. */ + +#define I2O_UTIL_NOP 0x00 +#define I2O_UTIL_ABORT 0x01 +#define I2O_UTIL_CLAIM 0x09 +#define I2O_UTIL_CLAIM_RELEASE 0x0B +#define I2O_UTIL_CONFIG_DIALOG 0x10 +#define I2O_UTIL_DEVICE_RESERVE 0x0D +#define I2O_UTIL_DEVICE_RELEASE 0x0F +#define I2O_UTIL_EVENT_ACKNOWLEDGE 0x14 +#define I2O_UTIL_EVENT_REGISTER 0x13 +#define I2O_UTIL_LOCK 0x17 +#define I2O_UTIL_LOCK_RELEASE 0x19 +#define I2O_UTIL_PARAMS_GET 0x06 +#define I2O_UTIL_PARAMS_SET 0x05 +#define I2O_UTIL_REPLY_FAULT_NOTIFY 0x15 + +/* ************************************************************************** */ + +/* ABORT Abort type defines. */ + +#define I2O_ABORT_TYPE_EXACT_ABORT 0x00 +#define I2O_ABORT_TYPE_FUNCTION_ABORT 0x01 +#define I2O_ABORT_TYPE_TRANSACTION_ABORT 0x02 +#define I2O_ABORT_TYPE_WILD_ABORT 0x03 +#define I2O_ABORT_TYPE_CLEAN_EXACT_ABORT 0x04 +#define I2O_ABORT_TYPE_CLEAN_FUNCTION_ABORT 0x05 +#define I2O_ABORT_TYPE_CLEAN_TRANSACTION_ABORT 0x06 +#define I2O_ABORT_TYPE_CLEAN_WILD_ABORT 0x07 + +/* UtilAbort Function Message Frame structure. */ + +typedef struct i2o_util_abort_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint16_t reserved; + uint8_t AbortType; + uint8_t FunctionToAbort; + i2o_transaction_context_t TransactionContextToAbort; +} i2o_util_abort_message_t; + +typedef struct i2o_util_abort_reply { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint32_t CountOfAbortedMessages; +} i2o_util_abort_reply_t; + +/* ************************************************************************** */ + +/* Claim Flag defines */ + +#define I2O_CLAIM_FLAGS_EXCLUSIVE 0x0001 /* Reserved */ +#define I2O_CLAIM_FLAGS_RESET_SENSITIVE 0x0002 +#define I2O_CLAIM_FLAGS_STATE_SENSITIVE 0x0004 +#define I2O_CLAIM_FLAGS_CAPACITY_SENSITIVE 0x0008 +#define I2O_CLAIM_FLAGS_PEER_SERVICE_DISABLED 0x0010 +#define I2O_CLAIM_FLAGS_MGMT_SERVICE_DISABLED 0x0020 + +/* Claim Type defines */ + +#define I2O_CLAIM_TYPE_PRIMARY_USER 0x01 +#define I2O_CLAIM_TYPE_AUTHORIZED_USER 0x02 +#define I2O_CLAIM_TYPE_SECONDARY_USER 0x03 +#define I2O_CLAIM_TYPE_MANAGEMENT_USER 0x04 + +/* UtilClaim Function Message Frame structure. */ + +typedef struct i2o_util_claim_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint16_t ClaimFlags; + uint8_t reserved; + uint8_t ClaimType; +} i2o_util_claim_message_t; + +/* ************************************************************************** */ + +/* Claim Release Flag defines */ + +#define I2O_RELEASE_FLAGS_CONDITIONAL 0x0001 + +/* UtilClaimRelease Function Message Frame structure. */ + +typedef struct i2o_util_claim_release_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint16_t ReleaseFlags; + uint8_t reserved; + uint8_t ClaimType; +} i2o_util_claim_release_message_t; + +/* ************************************************************************** */ + +/* UtilConfigDialog Function Message Frame structure */ + +typedef struct i2o_util_config_dialog_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint32_t PageNumber; + i2o_sg_element_t SGL; +} i2o_util_config_dialog_message_t; + +/* ************************************************************************** */ + +/* Event Acknowledge Function Message Frame structure */ + +typedef struct i2o_util_event_ack_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint32_t EventIndicator; + uint32_t EventData[1]; +} i2o_util_event_ack_message_t; + +/* Event Ack Reply structure */ + +typedef struct i2o_util_event_ack_reply { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint32_t EventIndicator; + uint32_t EventData[1]; +} i2o_util_event_ack_reply_t; + +/* ************************************************************************** */ + +/* Event Indicator Mask Flags */ + +#define I2O_EVENT_IND_STATE_CHANGE 0x80000000 +#define I2O_EVENT_IND_GENERAL_WARNING 0x40000000 +#define I2O_EVENT_IND_CONFIGURATION_FLAG 0x20000000 +/* #define I2O_EVENT_IND_RESERVE_RELEASE 0x10000000 */ +#define I2O_EVENT_IND_LOCK_RELEASE 0x10000000 +#define I2O_EVENT_IND_CAPABILITY_CHANGE 0x08000000 +#define I2O_EVENT_IND_DEVICE_RESET 0x04000000 +#define I2O_EVENT_IND_EVENT_MASK_MODIFIED 0x02000000 +#define I2O_EVENT_IND_FIELD_MODIFIED 0x01000000 +#define I2O_EVENT_IND_VENDOR_EVENT 0x00800000 +#define I2O_EVENT_IND_DEVICE_STATE 0x00400000 + +/* Event Data for generic Events */ + +#define I2O_EVENT_STATE_CHANGE_NORMAL 0x00 +#define I2O_EVENT_STATE_CHANGE_SUSPENDED 0x01 +#define I2O_EVENT_STATE_CHANGE_RESTART 0x02 +#define I2O_EVENT_STATE_CHANGE_NA_RECOVER 0x03 +#define I2O_EVENT_STATE_CHANGE_NA_NO_RECOVER 0x04 +#define I2O_EVENT_STATE_CHANGE_QUIESCE_REQUEST 0x05 +#define I2O_EVENT_STATE_CHANGE_FAILED 0x10 +#define I2O_EVENT_STATE_CHANGE_FAULTED 0x11 + +#define I2O_EVENT_GEN_WARNING_NORMAL 0x00 +#define I2O_EVENT_GEN_WARNING_ERROR_THRESHOLD 0x01 +#define I2O_EVENT_GEN_WARNING_MEDIA_FAULT 0x02 + +#define I2O_EVENT_CAPABILITY_OTHER 0x01 +#define I2O_EVENT_CAPABILITY_CHANGED 0x02 + +#define I2O_EVENT_SENSOR_STATE_CHANGED 0x01 + +/* UtilEventRegister Function Message Frame structure */ + +typedef struct i2o_util_event_register_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint32_t EventMask; +} i2o_util_event_register_message_t; + +/* UtilEventRegister Reply structure */ + +typedef struct i2o_util_event_register_reply { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint32_t EventIndicator; + uint32_t EventData[1]; +} i2o_util_event_register_reply_t; + +/* ************************************************************************** */ + +/* UtilLock Function Message Frame structure. */ + +typedef struct i2o_util_lock_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; +} i2o_util_lock_message_t; + +/* ************************************************************************** */ + +/* UtilLockRelease Function Message Frame structure. */ + +typedef struct i2o_util_lock_release_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; +} i2o_util_lock_release_message_t; + +/* ************************************************************************** */ + +/* UtilNOP Function Message Frame structure. */ + +typedef struct i2o_util_nop_message { + i2o_message_frame_t StdMessageFrame; +} i2o_util_nop_message_t; + +/* ************************************************************************** */ + +/* UtilParamsGet Message Frame structure. */ + +typedef struct i2o_util_params_get_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint32_t OperationFlags; + i2o_sg_element_t SGL; +} i2o_util_params_get_message_t; + +/* ************************************************************************** */ + +/* UtilParamsSet Message Frame structure. */ + +typedef struct i2o_util_params_set_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint32_t OperationFlags; + i2o_sg_element_t SGL; +} i2o_util_params_set_message_t; + + +/* ************************************************************************** */ + +/* UtilReplyFaultNotify Message for Message Failure. */ + +#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) + +typedef struct i2o_util_reply_fault_notify_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint8_t LowestVersion; + uint8_t HighestVersion; + uint8_t Severity; + uint8_t FailureCode; + union { + struct { + uint16_t FailingIOP_ID:12; + uint16_t reserved:4; + } s; + uint16_t h1; + } u1; + uint16_t FailingHostUnitID; + uint32_t AgeLimit; +#if I2O_64BIT_CONTEXT + i2o_message_frame_t *OriginalMFA; +#else + i2o_message_frame_t *OriginalMFALowPart; + uint32_t OriginalMFAHighPart; /* Always 0000 */ +#endif +} i2o_util_reply_fault_notify_message_t; + +#define get_i2o_util_FailingIOP_ID(p, hdl) (p)->u1.s.FailingIOP_ID + +#endif + +#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) + +typedef struct i2o_util_reply_fault_notify_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; + uint8_t LowestVersion; + uint8_t HighestVersion; + uint8_t Severity; + uint8_t FailureCode; + union { + struct { + uint16_t reserved:4; + uint16_t FailingIOP_ID:12; + } s; + uint32_t h1; + } u1; + uint16_t FailingHostUnitID; + uint32_t AgeLimit; +#if I2O_64BIT_CONTEXT + i2o_message_frame_t *OriginalMFA; +#else + i2o_message_frame_t *OriginalMFALowPart; + uint32_t OriginalMFAHighPart; /* Always 0000 */ +#endif +} i2o_util_reply_fault_notify_message_t; + +#define get_i2o_util_FailingIOP_ID(p, hdl) \ + (ddi_get16(hdl, &(p)->u1.h1) & 0xFFF) + +#endif + +/* ************************************************************************** */ + +/* Device Reserve Function Message Frame structure. */ +/* NOTE: This was previously called the Reserve Message */ + +typedef struct i2o_util_device_reserve_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; +} i2o_util_device_reserve_message_t; + +/* ************************************************************************** */ + +/* Device Release Function Message Frame structure. */ +/* NOTE: This was previously called the ReserveRelease Message */ + +typedef struct i2o_util_device_release_message { + i2o_message_frame_t StdMessageFrame; + i2o_transaction_context_t TransactionContext; +} i2o_util_device_release_message_t; + +/* ************************************************************************** */ + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_I2OUTIL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/uts/intel/i2o_bs/Makefile Wed Apr 18 11:32:14 2007 -0700 @@ -0,0 +1,101 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (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 +# +# +# uts/intel/i2o_bs/Makefile +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# This makefile drives the production of the i2o_bs (I2O BS-OSM) +# driver kernel module. +# +# intel implementation architecture dependent +# + +# +# Path to the base of the uts directory tree (usually /usr/src/uts). +# +UTSBASE = ../.. + +# +# Define the module and object file sets. +# +MODULE = i2o_bs +OBJECTS = $(I2O_BS_OBJS:%=$(OBJS_DIR)/%) +LINTS = $(I2O_BS_OBJS:%.o=$(LINTS_DIR)/%.ln) +ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) +CONF_SRCDIR = $(UTSBASE)/common/io/i2o + +# +# Include common rules. +# +include $(UTSBASE)/intel/Makefile.intel + +# +# Define targets +# +ALL_TARGET = $(BINARY) $(SRC_CONFILE) +LINT_TARGET = $(MODULE).lint +INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) + +# +# Overrides +# +DEF_BUILDS = $(DEF_BUILDS32) +ALL_BUILDS = $(ALL_BUILDS32) + +# +# For now, disable these lint checks; maintainers should endeavor +# to investigate and remove these for maximum lint coverage. +# Please do not carry these forward to new Makefiles. +# +LINTTAGS += -erroff=E_SUSPICIOUS_COMPARISON +LINTTAGS += -erroff=E_BAD_PTR_CAST_ALIGN +LINTTAGS += -erroff=E_PTRDIFF_OVERFLOW +LINTTAGS += -erroff=E_ASSIGN_NARROW_CONV + +# +# Default build targets. +# +.KEEP_STATE: + +def: $(DEF_DEPS) + +all: $(ALL_DEPS) + +clean: $(CLEAN_DEPS) + +clobber: $(CLOBBER_DEPS) + +lint: $(LINT_DEPS) + +modlintlib: $(MODLINTLIB_DEPS) + +clean.lint: $(CLEAN_LINT_DEPS) + +install: $(INSTALL_DEPS) + +# +# Include common targets. +# +include $(UTSBASE)/intel/Makefile.targ
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/uts/intel/i2o_msg/Makefile Wed Apr 18 11:32:14 2007 -0700 @@ -0,0 +1,97 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (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 +# +# +# uts/intel/i2o_msg/Makefile +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# This file makes the i2o_msg kernel misc module for an intel system +# +# intel architecture dependent +# + +# +# Path to the base of the uts directory tree (usually /usr/src/uts). +# +UTSBASE = ../.. +# +# Define the module and object file sets. +# +MODULE = i2o_msg +OBJECTS = $(I2OMSG_OBJS:%=$(OBJS_DIR)/%) +LINTS = $(I2OMSG_OBJS:%.o=$(LINTS_DIR)/%.ln) +ROOTMODULE = $(ROOT_MISC_DIR)/$(MODULE) + +# +# Include common rules. +# +include $(UTSBASE)/intel/Makefile.intel + +# +# Define targets +# +ALL_TARGET = $(BINARY) +LINT_TARGET = $(MODULE).lint +INSTALL_TARGET = $(BINARY) $(ROOTMODULE) + +# +# Overrides +# +DEF_BUILDS = $(DEF_BUILDS32) +ALL_BUILDS = $(ALL_BUILDS32) + +# +# For now, disable these lint checks; maintainers should endeavor +# to investigate and remove these for maximum lint coverage. +# Please do not carry these forward to new Makefiles. +# +LINTTAGS += -erroff=E_BAD_PTR_CAST_ALIGN +LINTTAGS += -erroff=E_PTRDIFF_OVERFLOW +LINTTAGS += -erroff=E_ASSIGN_NARROW_CONV + +# +# Default build targets. +# +.KEEP_STATE: + +def: $(DEF_DEPS) + +all: $(ALL_DEPS) + +clean: $(CLEAN_DEPS) + +clobber: $(CLOBBER_DEPS) + +lint: $(LINT_DEPS) + +modlintlib: $(MODLINTLIB_DEPS) + +clean.lint: $(CLEAN_LINT_DEPS) + +install: $(INSTALL_DEPS) + +# +# Include common targets. +# +include $(UTSBASE)/intel/Makefile.targ
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/uts/intel/i2o_scsi/Makefile Wed Apr 18 11:32:14 2007 -0700 @@ -0,0 +1,105 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (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 +# +# +# uts/intel/i2o_scsi/Makefile +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# This makefile drives the production of the i2o_scsi (SCSI HBA) +# driver kernel module. +# +# intel implementation architecture dependent +# + +# +# Path to the base of the uts directory tree (usually /usr/src/uts). +# +UTSBASE = ../.. + +# +# Define the module and object file sets. +# +MODULE = i2o_scsi +OBJECTS = $(I2O_SCSI_OBJS:%=$(OBJS_DIR)/%) +LINTS = $(I2O_SCSI_OBJS:%.o=$(LINTS_DIR)/%.ln) +ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) +CONF_SRCDIR = $(UTSBASE)/common/io/i2o + +# +# Include common rules. +# +include $(UTSBASE)/intel/Makefile.intel + +# +# Define targets +# +ALL_TARGET = $(BINARY) $(SRC_CONFILE) +LINT_TARGET = $(MODULE).lint +INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) + +# +# Overrides +# +DEF_BUILDS = $(DEF_BUILDS32) +ALL_BUILDS = $(ALL_BUILDS32) + +# +# Override defaults to build a unique, local modstubs.o. +# +MODSTUBS_DIR = $(OBJS_DIR) +CLEANFILES += $(MODSTUBS_O) + +# +# For now, disable these lint checks; maintainers should endeavor +# to investigate and remove these for maximum lint coverage. +# Please do not carry these forward to new Makefiles. +# +LINTTAGS += -erroff=E_BAD_PTR_CAST_ALIGN + +# +# Default build targets. +# +.KEEP_STATE: + +all: $(ALL_DEPS) + +def: $(DEF_DEPS) + +clean: $(CLEAN_DEPS) + +clobber: $(CLOBBER_DEPS) + +lint: $(LINT_DEPS) + +modlintlib: $(MODLINTLIB_DEPS) + +clean.lint: $(CLEAN_LINT_DEPS) + +install: $(INSTALL_DEPS) + +# +# Include common targets. +# +include $(UTSBASE)/intel/Makefile.targ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/deleted_files/usr/src/uts/intel/pci_to_i2o/Makefile Wed Apr 18 11:32:14 2007 -0700 @@ -0,0 +1,106 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (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 +# +# +# uts/intel/pci_to_i2o/Makefile +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +#ident "%Z%%M% %I% %E% SMI" +# +# This makefile drives the production of the pci_to_i2o nexus driver +# kernel module. +# + +# +# Path to the base of the uts directory tree (usually /usr/src/uts). +# +UTSBASE = ../.. + +# +# Define the module and object file sets. +# +MODULE = pci_to_i2o +OBJECTS = $(PCI_I2ONEXUS_OBJS:%=$(OBJS_DIR)/%) +LINTS = $(PCI_I2ONEXUS_OBJS:%.o=$(LINTS_DIR)/%.ln) +ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) +CONF_SRCDIR = $(UTSBASE)/common/io/i2o + +# +# Include common rules. +# +include $(UTSBASE)/intel/Makefile.intel + +# +# Define targets +# +ALL_TARGET = $(BINARY) $(SRC_CONFILE) +LINT_TARGET = $(MODULE).lint +INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) + +# +# Overrides +# +DEF_BUILDS = $(DEF_BUILDS32) +ALL_BUILDS = $(ALL_BUILDS32) + +# +# Override defaults to build a unique, local modstubs.o. +# +MODSTUBS_DIR = $(OBJS_DIR) +CLEANFILES += $(MODSTUBS_O) + +# +# For now, disable these lint checks; maintainers should endeavor +# to investigate and remove these for maximum lint coverage. +# Please do not carry these forward to new Makefiles. +# +LINTTAGS += -erroff=E_SUSPICIOUS_COMPARISON +LINTTAGS += -erroff=E_BAD_PTR_CAST_ALIGN +LINTTAGS += -erroff=E_PTRDIFF_OVERFLOW +LINTTAGS += -erroff=E_ASSIGN_NARROW_CONV + +# +# Default build targets. +# +.KEEP_STATE: + +def: $(DEF_DEPS) + +all: $(ALL_DEPS) + +clean: $(CLEAN_DEPS) + +clobber: $(CLOBBER_DEPS) + +lint: $(LINT_DEPS) + +modlintlib: $(MODLINTLIB_DEPS) + +clean.lint: $(CLEAN_LINT_DEPS) + +install: $(INSTALL_DEPS) + +# +# Include common targets. +# +include $(UTSBASE)/intel/Makefile.targ +
--- a/usr/src/pkgdefs/SUNWckr/prototype_i386 Wed Apr 18 03:07:55 2007 -0700 +++ b/usr/src/pkgdefs/SUNWckr/prototype_i386 Wed Apr 18 11:32:14 2007 -0700 @@ -79,10 +79,6 @@ f none kernel/drv/cryptoadm 755 root sys f none kernel/drv/devinfo 755 root sys f none kernel/drv/dld 755 root sys -f none kernel/drv/i2o_bs 755 root sys -f none kernel/drv/i2o_bs.conf 644 root sys -f none kernel/drv/i2o_scsi 755 root sys -f none kernel/drv/i2o_scsi.conf 644 root sys f none kernel/drv/i8042 755 root sys f none kernel/drv/icmp 755 root sys f none kernel/drv/icmp6 755 root sys @@ -106,8 +102,6 @@ f none kernel/drv/openeepr 755 root sys f none kernel/drv/options 755 root sys f none kernel/drv/pci_pci 755 root sys -f none kernel/drv/pci_to_i2o 755 root sys -f none kernel/drv/pci_to_i2o.conf 644 root sys f none kernel/drv/pcie_pci 755 root sys f none kernel/drv/pcie_pci.conf 644 root sys f none kernel/drv/physmem 755 root sys @@ -181,7 +175,6 @@ f none kernel/misc/gld 755 root sys f none kernel/misc/hook 755 root sys f none kernel/misc/hpcsvc 755 root sys -f none kernel/misc/i2o_msg 755 root sys f none kernel/misc/ipc 755 root sys f none kernel/misc/kbtrans 755 root sys f none kernel/misc/kcf 755 root sys
--- a/usr/src/pkgdefs/SUNWhea/prototype_i386 Wed Apr 18 03:07:55 2007 -0700 +++ b/usr/src/pkgdefs/SUNWhea/prototype_i386 Wed Apr 18 11:32:14 2007 -0700 @@ -85,13 +85,6 @@ f none usr/include/sys/dktp/fdisk.h 644 root bin f none usr/include/sys/dma_engine.h 644 root bin f none usr/include/sys/fp.h 644 root bin -d none usr/include/sys/i2o 755 root bin -f none usr/include/sys/i2o/i2omsg.h 644 root bin -f none usr/include/sys/i2o/i2outil.h 644 root bin -f none usr/include/sys/i2o/i2oexec.h 644 root bin -f none usr/include/sys/i2o/i2oadptr.h 644 root bin -f none usr/include/sys/i2o/i2obscsi.h 644 root bin -f none usr/include/sys/i2o/i2omstr.h 644 root bin f none usr/include/sys/i8272A.h 644 root bin f none usr/include/sys/kd.h 644 root bin f none usr/include/sys/mc.h 644 root bin
--- a/usr/src/pkgdefs/common_files/i.drvalias Wed Apr 18 03:07:55 2007 -0700 +++ b/usr/src/pkgdefs/common_files/i.drvalias Wed Apr 18 11:32:14 2007 -0700 @@ -21,7 +21,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -159,7 +159,9 @@ -e '/^[ ]*smartii[ ][ ]*"pcie11,4030"$/d' \ -e '/^[ ]*smartii[ ][ ]*"pcie11,4030"[ #].*$/d' \ -e '/^[ ]*smartii[ ][ ]*"pcie11,4031"$/d' \ - -e '/^[ ]*smartii[ ][ ]*"pcie11,4031"[ #].*$/d' + -e '/^[ ]*smartii[ ][ ]*"pcie11,4031"[ #].*$/d' \ + -e '/^[ ]*pci_to_i2o[ ][ ]*"pciclass,0e0001"$/d' \ + -e '/^[ ]*pci_to_i2o[ ][ ]*"pciclass,0e0001"[ #].*$/d' } #
--- a/usr/src/pkgdefs/common_files/i.kclasses_i386 Wed Apr 18 03:07:55 2007 -0700 +++ b/usr/src/pkgdefs/common_files/i.kclasses_i386 Wed Apr 18 11:32:14 2007 -0700 @@ -66,6 +66,8 @@ -e '/^trantor[ ].*scsi/d' \ -e '/^corvette[ ].*scsi/d' \ -e '/^mpt[ ].*scsi/d' \ + -e '/^pci_to_i2o[ ].*i2o/d' \ + -e '/^i2o_scsi[ ].*scsi/d' \ $dest > /tmp/c.$$ if cmp -s /tmp/c.$$ $dest > /dev/null 2>&1 then @@ -89,14 +91,6 @@ if [ $? != 0 ] ; then echo 'mscsi scsi' >> $dest fi - grep '^pci_to_i2o[ ].*i2o' $dest > /dev/null 2>&1 - if [ $? != 0 ] ; then - echo 'pci_to_i2o i2o' >> $dest - fi - grep '^i2o_scsi[ ].*scsi' $dest > /dev/null 2>&1 - if [ $? != 0 ] ; then - echo 'i2o_scsi scsi' >> $dest - fi fi done
--- a/usr/src/pkgdefs/common_files/i.minorperm_i386 Wed Apr 18 03:07:55 2007 -0700 +++ b/usr/src/pkgdefs/common_files/i.minorperm_i386 Wed Apr 18 11:32:14 2007 -0700 @@ -159,6 +159,7 @@ profile:profile asy:[a-z] asy:[a-z],cu +i2o_bs:* EOF } @@ -180,7 +181,6 @@ st:* pm:* devinfo:devinfo -i2o_bs:* openeepr:openprom wc:* ip:ip
--- a/usr/src/pkgdefs/common_files/i.nametomajor Wed Apr 18 03:07:55 2007 -0700 +++ b/usr/src/pkgdefs/common_files/i.nametomajor Wed Apr 18 11:32:14 2007 -0700 @@ -21,7 +21,7 @@ # # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" @@ -175,6 +175,9 @@ obs["tiqmouse"] = 1; obs["tr"] = 1; obs["trantor"] = 1; + obs["pci_to_i2o"] = 1; + obs["i2o_scsi"] = 1; + obs["i2o_bs"] = 1; } !($1 in obs) { print $0 }' }
--- a/usr/src/tools/scripts/bfu.sh Wed Apr 18 03:07:55 2007 -0700 +++ b/usr/src/tools/scripts/bfu.sh Wed Apr 18 11:32:14 2007 -0700 @@ -6584,6 +6584,19 @@ # rm -f $root/dev/cfg/*pci* + # + # Remove I2O. + # + rm -f $root/kernel/drv/i2o_bs + rm -f $root/kernel/drv/i2o_bs.conf + rm -f $root/kernel/drv/i2o_scsi + rm -f $root/kernel/drv/i2o_scsi.conf + rm -f $root/kernel/drv/pci_to_i2o + rm -f $root/kernel/drv/pci_to_i2o.conf + rm -f $root/kernel/misc/i2o_msg + rm -f $root/usr/include/sys/i2o/* + rmdir $root/usr/include/sys/i2o/ 2>/dev/null + # End of pre-archive extraction hacks. if [ $diskless = no -a $zone = global ]; then
--- a/usr/src/uts/common/Makefile.files Wed Apr 18 03:07:55 2007 -0700 +++ b/usr/src/uts/common/Makefile.files Wed Apr 18 11:32:14 2007 -0700 @@ -1273,14 +1273,6 @@ PSET_OBJS += pset.o -PCI_I2ONEXUS_OBJS += pci_to_i2o.o - -I2OMSG_OBJS += i2o_msg.o - -I2O_SCSI_OBJS += i2o_scsi.o - -I2O_BS_OBJS += i2o_bs.o label.o - OHCI_OBJS += ohci.o ohci_hub.o ohci_polled.o UHCI_OBJS += uhci.o uhciutil.o uhcitgt.o uhcihub.o uhcipolled.o
--- a/usr/src/uts/common/Makefile.rules Wed Apr 18 03:07:55 2007 -0700 +++ b/usr/src/uts/common/Makefile.rules Wed Apr 18 11:32:14 2007 -0700 @@ -495,10 +495,6 @@ $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) -$(OBJS_DIR)/%.o: $(UTSBASE)/common/io/i2o/%.c - $(COMPILE.c) -o $@ $< - $(CTFCONVERT_O) - $(OBJS_DIR)/%.o: $(UTSBASE)/common/io/ib/clients/rds/%.c $(COMPILE.c) -o $@ $< $(CTFCONVERT_O) @@ -1291,9 +1287,6 @@ $(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/hotplug/pcihp/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL)) -$(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/i2o/%.c - @($(LHEAD) $(LINT.c) $< $(LTAIL)) - $(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/ib/clients/rds/%.c @($(LHEAD) $(LINT.c) $< $(LTAIL))
--- a/usr/src/uts/common/io/i2o/i2o_bs.c Wed Apr 18 03:07:55 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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); -}
--- a/usr/src/uts/common/io/i2o/i2o_bs.conf Wed Apr 18 03:07:55 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +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 (c) 1998 by Sun Microsystems, Inc. -# All rights reserved. -# - -#pragma ident "%Z%%M% %I% %E% SMI" - -name="i2o_bs" class="i2o";
--- a/usr/src/uts/common/io/i2o/i2o_bs.h Wed Apr 18 03:07:55 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,156 +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 (c) 1998-1999 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _I2O_BS_H -#define _I2O_BS_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ROUNDUP(a, n) (((a) + ((n) - 1)) & ~((n) - 1)) -#define UNIT(dev) (getminor((dev)) >> UNITSHF) -#define BSA_SETMINOR(skt, part) ((skt << UNITSHF) | (part)) - -#if defined(_SUNOS_VTOC_16) -#define UNITSHF 6 -#define MAXPART (1 << UNITSHF) -#define LPART(dev) (getminor((dev)) & (MAXPART - 1)) -#elif defined(_SUNOS_VTOC_8) -#define UNITSHF 3 -#define PART_MASK 7 -#define LPART(dev) (getminor((dev)) & PART_MASK) -#else -#error No VTOC format defined. -#endif - - -#define V_INVALID 0x80 -#define FDISK_OFFSET MAX_SLICES -#if defined(_SUNOS_VTOC_16) -#define MAX_SLICES 16 -#define VTOC_OFFSET 1 -#elif defined(_SUNOS_VTOC_8) -#define VTOC_OFFSET 0 -#define MAX_SLICES 8 -#else -#error No VTOC format defined. -#endif -#define USLICE_WHOLE 2 -#define FPART_WHOLE 0 -#define NUM_PARTS (MAX_SLICES + FD_NUMPART + 1) - -#define REPLY_DONE 1 /* The reply is done */ -#define STATE_CHANGE 0x0001 /* STATE has changned */ -#define CLAIMED 0x0002 /* device is claimed */ -#define I2O_BSA_NAME "i2o_bs" - - -#define ISCD(p) ((p)->unitp.au_type == DKC_CDROM) -#define ISREMOVABLE(p) \ - ((p)->unitp.au_devicecapability & I2O_BSA_DEV_CAP_REMOVABLE_MEDIA) - -#define ISWRITEPROTECT(p) \ - ((p)->unitp.au_devicecapability & I2O_BSA_DEV_CAP_READ_ONLY) - - - -typedef struct dsk_label { - struct dk_label ondsklbl; - struct partition pmap[NUM_PARTS]; - struct dk_map un_map[NDKMAP]; /* logical partitions */ - int uidx; - int fdiskpresent; - int vtocread; - int geomread; - kmutex_t mutex; - -} dsk_label_t; - - -struct bsa_unit { - int au_cyl; - int au_acyl; - int au_hd; - int au_sec; - long au_blksize; - short au_bytes_per_block; - int au_type; - uint64_t au_capacity; - long au_devicecapability; -}; - -typedef struct bsa_data { - int flags; /* misc state info */ - int tid; /* local targer id ( From LCT) */ - int instance; /* instantiation of ourselves */ - int open_flag; /* open flag used for rem media */ - unsigned long state; /* State of removable media */ - struct buf *crashbuf; /* used when dumping to root device */ - i2o_iop_handle_t iop; /* IOP access handle */ - dev_info_t *dip; /* pointer to our own device node */ - dsk_label_t lbl; /* per targer label information */ - struct bsa_unit unitp; /* phsyical characteristics */ - kcondvar_t reply_cv; /* conditional variable */ - kcondvar_t rwreply_cv; /* read/write cond variable */ - kcondvar_t state_cv; /* state cond variable */ - kmutex_t bsa_mutex; /* bs mutex */ -} bsa_data_t; - - -typedef struct bsa_context { - struct bsa_data *bsadata; - int deterror; /* detail error */ - int retval; /* return value from reply */ - int replyflag; /* reply flag */ - int rwreplyflag; /* reply flag */ - ddi_dma_handle_t dma_handle; /* DMA Handle */ - ddi_acc_handle_t acc_handle; /* DMA Handle */ - ddi_dma_handle_t dma_sghandle; /* DMA Handle */ - ddi_acc_handle_t acc_sghandle; /* DMA Handle */ - ddi_dma_handle_t dma_sg2handle; /* DMA Handle */ - ddi_acc_handle_t acc_sg2handle; /* DMA Handle */ -} bsa_context_t; - -typedef struct i2o_common_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; -} i2o_common_message_t; - -typedef struct i2o_reassign_addr_message { - uint32_t ByteCount; - uint64_t LogicalByteAddress; -} i2o_reassign_addr_message_t; - - - -#ifdef __cplusplus -} -#endif - -#endif /* _I2O_BS_H */
--- a/usr/src/uts/common/io/i2o/i2o_impl.h Wed Apr 18 03:07:55 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +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 (c) 1998 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _I2O_IMPL_H -#define _I2O_IMPL_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/types.h> -#include <sys/dditypes.h> -#include <sys/i2o/i2omsg.h> -#include <sys/i2o/i2outil.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef DEBUG -#define I2O_DEBUG -#endif - -/* - * ***************************************************************** - * Definitions used in the implementation of I2O nexus driver and - * I2O Message module. These are implementation specific definitions. - * ***************************************************************** - */ - -/* - * i2o_msg_trans structure: - * - * version I2O_MSG_TRANS_VER0 (version of this structure). - * - * iop_base_addr Base (virtual) address of device memory where - * inbound message frames are allocated. The MFA - * read from the inbound FIFO is an offset from - * this base address. - * - * iop_inbound_fifo_paddr - * Inbound Fifo port address (physical). - * - * acc_handle DDI access handle to access any message frame - * from the inbound queue. - * - * nexus_handle I2O Nexus handle argument to nexus transport - * functions. - * - * iblock_cookie Cookie needed for mutex_init(). - * - * i2o_trans_msg_alloc - * Allocates a message frame from the inbound - * queue. It reads the inbound FIFO register - * and returns the MFA. - * - * i2o_trans_msg_send - * Write the MFA to the inbound queue of the IOP. - * - * i2o_trans_msg_recv - * Reads the outbound queue for the reply - * messages and returns the MFA. The MFA is - * -1 if there are no reply messages. - * - * i2o_trans_msg_freebuf - * Writes the MFA into the outbound queue. - * - * i2o_trans_disable_intr - * Disables the IOP hardware interrupts. - * - * i2o_trans_enable_intr - * Enables the IOP hardware interrupts. - */ - -#define I2O_MSG_TRANS_VER0 0 -#define I2O_MSG_TRANS_VER I2O_MSG_TRANS_VER0 - -typedef void *i2o_nexus_handle_t; - -typedef struct i2o_msg_trans { - int version; - caddr_t iop_base_addr; - uint32_t iop_inbound_fifo_paddr; - ddi_acc_handle_t acc_handle; - i2o_nexus_handle_t nexus_handle; - ddi_iblock_cookie_t iblock_cookie; - uint_t (* i2o_trans_msg_alloc)(i2o_nexus_handle_t - nexus_handle); - int (* i2o_trans_msg_send)(i2o_nexus_handle_t nexus_handle, - uint_t mfa); - uint_t (* i2o_trans_msg_recv)(i2o_nexus_handle_t nexus_handle); - void (* i2o_trans_msg_freebuf)(i2o_nexus_handle_t - nexus_handle, uint_t mfa); - void (* i2o_trans_disable_intr)(i2o_nexus_handle_t - nexus_handle); - void (* i2o_trans_enable_intr)(i2o_nexus_handle_t - nexus_handle); -} i2o_msg_trans_t; - - -i2o_iop_handle_t i2o_msg_iop_init(dev_info_t *rdip, i2o_msg_trans_t *trans); -void i2o_msg_process_reply_queue(i2o_iop_handle_t iop); -int i2o_msg_iop_uninit(i2o_iop_handle_t *iop); -void i2o_msg_get_lct_info(i2o_iop_handle_t *, i2o_lct_t **, ddi_acc_handle_t *); - -#ifdef __cplusplus -} -#endif - -#endif /* _I2O_IMPL_H */
--- a/usr/src/uts/common/io/i2o/i2o_msg.c Wed Apr 18 03:07:55 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3307 +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 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * I2O Message module, which implements OSM interfaces to provides - * transport functionality for the OSMs. It depends on the I2O nexus - * driver for bus specific transport mechanisms. - * - * Note: The current implementation assumes only 32bit virtual - * addresses and 32bit context fields in I2O messages. - */ - -#include <sys/types.h> -#include <sys/cmn_err.h> -#include <sys/conf.h> -#include <sys/debug.h> -#include <sys/modctl.h> -#include <sys/errno.h> -#include <sys/ddidmareq.h> -#include <sys/ddi_impldefs.h> -#include <sys/ddi.h> -#include <sys/sunddi.h> -#include <sys/pci.h> -#include <sys/avintr.h> -#include <sys/bustypes.h> -#include <sys/kmem.h> -#include <sys/archsystm.h> -#include <sys/disp.h> - -#include "i2o_impl.h" -#include <sys/i2o/i2oexec.h> - -#ifndef I2O_BOOT_SUPPORT -#include <sys/sunndi.h> - -char _depends_on[] = "misc/busra"; -#endif - -/* - * ************************************************************************ - * *** Implementation specific data structures/definitions. *** - * ************************************************************************ - */ - -/* - * Implementation of i2o_iop_handle_t data structure. - * - * dip devinfo node pointer of the I2O device - * tid IOP assigned TID for this device. - * iop pointer to iop_instance_t data structure. - */ - -typedef struct i2o_iop_impl_hdl { - dev_info_t *dip; - uint32_t tid; - struct iop_instance *iop; -} i2o_iop_impl_hdl_t; - -/* - * Implementation of i2o_msg_handle_t data structure. - * - * next pointer to the next handle (used when the requests - * are queued up) - * dma_handle DMA handle associated with this message buffer - * msgp pointer to the message frame. - * acc_hdl DDI access handle for this message frame. - */ - -typedef struct i2o_msg_impl_hdl { - struct i2o_msg_impl_hdl *next; - ddi_dma_handle_t dma_handle; - ddi_acc_handle_t acc_hdl; - void *msgp; -} i2o_msg_impl_hdl_t; - -/* - * Per IOP instance data structure maintained by the I2O Message - * module. - * - * Locks used: - * iop_ib_mutex Used to serialize access to the inbound message - * queue and to protect send_queue_* fields. - * - * iop_ob_mutex Used to serialize access to the outbound message - * queue. - */ -typedef struct iop_instance { - - struct iop_instance *next; - uint_t iop_id; - volatile int iop_flags; - i2o_msg_trans_t *nexus_trans; - dev_info_t *dip; - kmutex_t iop_ib_mutex; - kmutex_t iop_ob_mutex; - uint32_t event_mask; - uint_t ib_msg_frame_size; - - /* IOP Status Block structure */ - struct { - i2o_exec_status_get_reply_t *bufp; - ddi_acc_handle_t acc_hdl; - ddi_dma_handle_t dma_handle; - } status; - - /* Logical Configuration Table (LCT) */ - struct { - i2o_lct_t *bufp; - ddi_acc_handle_t acc_hdl; - size_t size; - ddi_dma_handle_t dma_handle; - kmutex_t lct_mutex; - } lct; - - /* Hardware Resource Table (HRT) */ - struct { - i2o_hrt_t *bufp; - ddi_acc_handle_t acc_hdl; - uint_t size; - ddi_dma_handle_t dma_handle; - } hrt; - - /* outbound message queue */ - struct { - caddr_t base_addr; - uint_t base_paddr; - ddi_acc_handle_t acc_hdl; - uint_t nframes; - uint_t framesize; - ddi_dma_handle_t dma_handle; - } ob_msg_queue; - - /* private memory/io space allocated for IOP hw configuration */ - struct { - uint_t mem_base; - uint_t mem_size; - uint_t io_base; - uint_t io_size; - } hw_config; - - /* System Table Entry for this IOP */ - struct { - ddi_dma_handle_t dma_handle; - i2o_iop_entry_t *bufp; - ddi_acc_handle_t acc_hdl; - } systab; - - /* OSM registration book keeping */ - struct { - i2o_iop_impl_hdl_t *iop_handle_tab; - uint_t max_tid; - kmutex_t osm_mutex; - } osm_registry; - - /* - * i2o_send_msg() queue information. The fields send_queue_head - * and send_queue_tail are protected under iop_ib_mutex. - */ - i2o_msg_impl_hdl_t *send_queue_head; - i2o_msg_impl_hdl_t *send_queue_tail; - ulong_t send_queue_count; - kcondvar_t send_queue_cv; -} iop_instance_t; - -/* common transaction context structure */ - -typedef struct tcontext { - iop_instance_t *iop; - kmutex_t cv_mutex; - kcondvar_t cv; - int status; - int done_flag; -} tcontext_t; - -/* definitions for iop_flags values */ -#define IOP_IS_IN_INIT 1 /* IOP is being initialized */ -#define IOP_IS_ONLINE 2 /* IOP is initilized */ -#define IOP_IS_IN_UNINIT 4 /* IOP is being uninitialized */ -#define IOP_SEND_QUEUE_PROC_RUNNING 8 /* i2o_msg_send_proc() running */ - -/* - * DMA attribute structure for I2O Spec version 1.5. - * - * (Note: Specifies sg list length to 1 to get contiguous memory) - */ -static ddi_dma_attr_t dma_attr_contig = { - DMA_ATTR_VERSION, /* version number */ - (uint64_t)0, /* low DMA address range */ - (uint64_t)0xFFFFFFFF, /* high DMA address range */ - (uint64_t)0x00FFFFFF, /* DMA counter register */ - 1, /* DMA address alignment */ - 1, /* DMA burstsizes */ - 1, /* min effective DMA size */ - (uint64_t)0xFFFFFFFF, /* max DMA xfer size */ - (uint64_t)0xFFFFFFFF, /* segment boundary */ - 0x1, /* s/g length */ - 1, /* granularity of device */ - 0 /* Bus specific DMA flags */ -}; - -/* - * Device attribute structure for I2O version 1.5. - * - * I2O data structures (whether it is in IOP's memory or host memory) - * are in Little Endian format. - */ -static ddi_device_acc_attr_t i2o_dev_acc_attr = { - DDI_DEVICE_ATTR_V0, - DDI_STRUCTURE_LE_ACC, /* devacc_attr_endian_flags for LE access */ - DDI_STRICTORDER_ACC /* devacc_attr_dataorder */ -}; - -/* Function prototypes for local functions */ - -static int i2o_get_iop_status(iop_instance_t *iop); -static int i2o_init_outbound_queue(iop_instance_t *iop); -static int i2o_get_hrt(iop_instance_t *iop); -static int i2o_create_systab(iop_instance_t *iop); -static int i2o_send_exec_enable(iop_instance_t *iop); -static int i2o_get_lct(iop_instance_t *iop); -static int i2o_iop_event_register(iop_instance_t *iop); -static void i2o_msg_iop_event_reply(void *p, ddi_acc_handle_t acc_hdl); -static void i2o_msg_common_reply(void *p, ddi_acc_handle_t acc_hdl); -static int i2o_send_exec_iop_reset(iop_instance_t *iop); -static void i2o_msg_send_proc(iop_instance_t *iop); - -static void i2o_return_mem(dev_info_t *, uint_t, uint_t); -static uint_t i2o_get_mem(dev_info_t *, uint_t, uint_t *); -static uint_t i2o_get_io(dev_info_t *, uint_t, uint_t *); -static void i2o_return_io(dev_info_t *, uint_t, uint_t); - -#ifdef I2O_DEBUG -/* function prototypes for debug functions */ -static void dump_reply_message(iop_instance_t *iop, - i2o_single_reply_message_frame_t *rmp); -static void dump_hrt(iop_instance_t *iop); -static void dump_lct(iop_instance_t *iop); -static void dump_iop_status_buf(iop_instance_t *iop); -static void dump_message(uint32_t *mp, char *name); -#endif - -/* - * Local Data definitions. - * - * niop - * number of active IOPs initialized to OP state. - * - * next_iop_id - * Counter to assign unique ID (IOP_ID) to the next IOP that - * gets initialized by the i2o nexus. - * - * ioplist - * pointer to the linked list of IOP data structures (i.e iop_instance - * structures) that are initilized. - * - * iop_reset_time_delay_in_ticks - * This is the time delay to get a valid mfa from the inbound freelist - * after doing ExecIopReset. This delay really depends on the platform - * specific hardware. Here we are using 2 seconds and this seems to - * work fine for the Madrona platform. - */ - -#define BASE_IOP_ID 2 /* IOP IDs 0 and 1 are reserved */ - -static uint_t niop = 0; -static uint_t next_iop_id = BASE_IOP_ID; -static iop_instance_t *ioplist; -int iop_reset_time_delay_in_ticks = 200; - -kmutex_t i2o_mutex; /* protects common data like ioplist, etc. */ - -/* - * Debug flag definitions. - */ -#define I2O_DEBUG_DEBUG 0x80000000 /* general debugging info */ -#define I2O_DEBUG_MSG 0x00000001 /* dump message frames */ -#define I2O_DEBUG_HRT 0x40000000 /* dump HRT table */ -#define I2O_DEBUG_STATUS 0x20000000 /* dump IOP Status block */ -#define I2O_DEBUG_LCT 0x10000000 /* dump LCT table */ -#define I2O_DEBUG_IOP_PARAMS 0x08000000 /* dump IOP parameters */ - -#ifdef I2O_DEBUG -int i2o_debug = I2O_DEBUG_LCT; - -#define DEBUGF(flag, args) \ - { if (i2o_debug & (flag)) cmn_err args; } -#else -#define DEBUGF(level, args) /* nothing */ -#endif - -#define SUCCESS 1 -#define FAILURE 0 - -/* - * Module linkage information for the kernel. - */ -extern struct mod_ops mod_miscops; -static struct modlmisc modlmisc = { - &mod_miscops, - "I2O Message Module version 1.5", -}; - - -static struct modlinkage modlinkage = { - MODREV_1, - &modlmisc, - NULL -}; - -int -_init(void) -{ - int error; - - mutex_init(&i2o_mutex, NULL, MUTEX_DRIVER, NULL); - - if ((error = mod_install(&modlinkage)) != 0) - mutex_destroy(&i2o_mutex); - - return (error); -} - -int -_fini(void) -{ - int error; - - if ((error = mod_remove(&modlinkage)) == 0) - mutex_destroy(&i2o_mutex); - - return (error); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} - - -/* - * Utility macros to initialize message structures. - */ -/* initialize standard message header */ -#define init_std_msghdr(iop, mp, ver_off, msg_flags, msg_size, func) \ - { \ - (mp)->VersionOffset = (ver_off) | I2O_VERSION_11; \ - (mp)->MsgFlags = (msg_flags); \ - ddi_put16((iop)->nexus_trans->acc_handle, \ - &(mp)->MessageSize, (msg_size) >> 2); \ - put_msg_Function((mp), (func), (iop)->nexus_trans->acc_hdl); \ - put_msg_InitiatorAddress((mp), I2O_HOST_TID, \ - (iop)->nexus_trans->acc_hdl); \ - put_msg_TargetAddress((mp), I2O_IOP_TID, \ - (iop)->nexus_trans->acc_hdl); \ - } - -/* initialize standard SGL Simple Element structure */ -#define init_sgl_simple_ele(iop, sgl, flags, count, addr) \ - { \ - put_flags_count_Flags(&(sgl)->FlagsCount, \ - (flags) | I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT, \ - (iop)->nexus_trans->acc_hdl); \ - ddi_put32((iop)->nexus_trans->acc_handle, \ - &(sgl)->PhysicalAddress, (uint_t)(addr)); \ - put_flags_count_Count(&(sgl)->FlagsCount, (count), \ - (iop)->nexus_trans->acc_hdl); \ - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, "SGL(0x%p): %x %x", \ - (void *)sgl, ((uint32_t *)sgl)[0], ((uint32_t *)sgl)[1])); \ - } - -/* - * ************************************************************************ - * Tunable parameters/properties. - * ob_msg_framesize_default - * Default frame size for Outbound Message queue. The minimum - * size is 64 bytes. It should be multiple of 4. - * ob_msg_queue_length_default - * Default size (i.e #of MFAs) in the Outbound Queue. The - * minimum is 16. - * ************************************************************************ - */ -int ob_msg_framesize_default = 128; -int ob_msg_queue_length_default = 32; - -/* - * ************************************************************************ - * Transport utility functions/macros used in IOP initialization. - * ************************************************************************ - */ - -#define iop_msg_send(iop, msgp) \ - (* iop->nexus_trans->i2o_trans_msg_send) \ - (iop->nexus_trans->nexus_handle, \ - (caddr_t)(msgp) - iop->nexus_trans->iop_base_addr) - - -#define iop_msg_free(iop, rmp) \ - (* iop->nexus_trans->i2o_trans_msg_freebuf) \ - (iop->nexus_trans->nexus_handle, \ - ((caddr_t)(rmp) - iop->ob_msg_queue.base_addr) + \ - iop->ob_msg_queue.base_paddr) - -static i2o_single_reply_message_frame_t * -iop_poll_reply_msg(iop_instance_t *iop) -{ - uint_t mfa; - uint_t ticks = 10000; /* time out polling for 10 seconds */ - - mfa = (* iop->nexus_trans->i2o_trans_msg_recv) - (iop->nexus_trans->nexus_handle); - - while (mfa == (uint_t)0xFFFFFFFF) { - delay(1); - mfa = (* iop->nexus_trans->i2o_trans_msg_recv) - (iop->nexus_trans->nexus_handle); - if (--ticks == 0) { - DEBUGF(I2O_DEBUG_DEBUG, - (CE_CONT, "iop_poll_reply_msg: timed out")); - return (NULL); /* time out - possible hang? */ - } - } - - return ((i2o_single_reply_message_frame_t *) - ((mfa - iop->ob_msg_queue.base_paddr) + - iop->ob_msg_queue.base_addr)); -} - -void * -iop_msg_alloc(iop_instance_t *iop) -{ - uint32_t mfa; - - mfa = (* iop->nexus_trans->i2o_trans_msg_alloc) - (iop->nexus_trans->nexus_handle); - - /* - * If we don't have a valid frame then wait for a while and - * try again. This may be necessary at the beginning if - * the IOP is in the INITIALIZATION state. - */ - if (mfa == (uint_t)0xFFFFFFFF) { - delay(100); - mfa = (* iop->nexus_trans->i2o_trans_msg_alloc) - (iop->nexus_trans->nexus_handle); - } - - return (mfa == (uint_t)0xFFFFFFFF ? NULL : - (void *)(mfa + iop->nexus_trans->iop_base_addr)); -} - - -/* - * ************************************************************************ - * ********* Private interfaces used by the I2O Nexus driver. *********** - * ************************************************************************ - */ - -/* - * i2o_msg_iop_init() - * - * Called from the attach(9E) function in the i2o nexus driver. - * Initializes the IOP to the OPERATIONAL state. Returns an access - * handle (i.e i2o_iop_handle_t) for successful initialization, - * otherwise it returns NULL. - * - * Assumption(s): - * 1. The IOP interrupts are not enabled when this function is - * called. The caller (i.e attach(9E)) enables the IOP interrupts - * upon the successful return from this function. - * 2. It is assumed that the I2O nexus driver will create the - * devinfo nodes for the I2O devices if necessary. i.e the - * caller of this function will create the devinfo tree - * based on the LCT/HRT information if the boot firmware hasn't - * already created it. - */ - -i2o_iop_handle_t -i2o_msg_iop_init(dev_info_t *dip, i2o_msg_trans_t *trans) -{ - iop_instance_t *iop; - uint32_t priv_mem_size; - uint32_t priv_io_size; - i2o_iop_impl_hdl_t *hdl; - i2o_lct_entry_t *lct_entp; - uint_t lct_entries; - int i; - int reset_done = 0; /* only one IOP_RESET operation */ - int init_time; - - /* - * Allocate an iop instance data. - */ - iop = (iop_instance_t *)kmem_zalloc(sizeof (iop_instance_t), KM_SLEEP); - - mutex_enter(&i2o_mutex); - - iop->dip = dip; - iop->iop_flags |= IOP_IS_IN_INIT; /* IOP is being initialized */ - iop->nexus_trans = trans; - - niop++; - iop->iop_id = next_iop_id++; /* assign a unique ID to this IOP */ - - mutex_init(&iop->iop_ib_mutex, NULL, MUTEX_DRIVER, - (void *)iop->nexus_trans->iblock_cookie); - mutex_init(&iop->iop_ob_mutex, NULL, MUTEX_DRIVER, - (void *)iop->nexus_trans->iblock_cookie); - mutex_init(&iop->osm_registry.osm_mutex, NULL, MUTEX_DRIVER, - (void *)iop->nexus_trans->iblock_cookie); - mutex_init(&iop->lct.lct_mutex, NULL, MUTEX_DRIVER, - (void *)iop->nexus_trans->iblock_cookie); - - /* - * ************************************************************** - * Step 1: Get the IOP status block by sending ExecStatusGet - * message. - * - * NOTE: Normally we expect IOP to be in 'RESET' state or 'OP' - * state. Any other state is really doubtful! - * ************************************************************** - */ - - /* - * We give 5 minutes for IOP to reset before complaining to user; - * the time for IOP to come to RESET state after it receives the - * EXEC_IOP_RESET really depends on the I2O hardware configured - * under the IOP. - */ - init_time = 5 * 60 * 100; /* ~5 min of clock ticks */ - -try_again: - if (i2o_get_iop_status(iop) == FAILURE) - goto cleanup; - - /* Check for I2O Version; we only support version 1.5 */ - if (get_i2o_exec_status_reply_I2oVersion(iop->status.bufp, - iop->status.acc_hdl) != I2O_VERSION_11) - goto cleanup; - - DEBUGF(I2O_DEBUG_DEBUG, - (CE_CONT, "i2o_msg_iop_init: Initial IOP state %x", - iop->status.bufp->IopState)); - - switch (iop->status.bufp->IopState) { - case I2O_IOP_STATE_RESET: - break; - - case I2O_IOP_STATE_INITIALIZING: - if (init_time <= 0) - cmn_err(CE_WARN, - "IOP is still in I2O_IOP_STATE_INITIALIZING state!!"); - else - init_time -= 100; - delay(100); - goto try_again; - - case I2O_IOP_STATE_OPERATIONAL: - /* reset the IOP and wait for a while for the IOP to reset */ - if (reset_done || i2o_send_exec_iop_reset(iop) != SUCCESS) - goto cleanup; - reset_done = 1; - delay(iop_reset_time_delay_in_ticks); - goto try_again; - - case I2O_IOP_STATE_HOLD: - case I2O_IOP_STATE_READY: - case I2O_IOP_STATE_FAILED: - case I2O_IOP_STATE_FAULTED: - /* reset the IOP and try again */ - if (!reset_done && i2o_send_exec_iop_reset(iop) == SUCCESS) { - delay(iop_reset_time_delay_in_ticks); - reset_done = 1; - goto try_again; - } - default: - cmn_err(CE_CONT, "?i2o_msg_iop_init: Invalid IOP state %x", - iop->status.bufp->IopState); - goto cleanup; - } - -#ifdef I2O_DEBUG - if (i2o_debug & I2O_DEBUG_STATUS) - dump_iop_status_buf(iop); -#endif - - /* - * ************************************************************** - * Step 2: Initialize the Outbound message queue. - * ************************************************************** - */ - if (i2o_init_outbound_queue(iop) == FAILURE) - goto cleanup; - - /* - * ************************************************************** - * Step 3: Get the Hardware Resource Table (HRT). - * ************************************************************** - */ - if (i2o_get_hrt(iop) == FAILURE) - goto cleanup; - -#if !defined(I2O_BOOT_SUPPORT) - /* - * ************************************************************** - * Step 4: Allocate Memory/IO spaces required by the IOP to - * configure the hidden adapters. The IOP status buffer - * has the required information. - * - * XXX Does IOP handle multiple chunks for PCI memory/io space - * allocated by the host? Currently the IRTOS always reports - * the CurrentPrivateMemSize as zero. - * ************************************************************** - */ - priv_mem_size = ddi_get32(iop->status.acc_hdl, - &iop->status.bufp->DesiredPrivateMemSize); - if (priv_mem_size > (uint32_t)0) { - /* need to allocate PCI memory space */ - if (i2o_get_mem(dip, priv_mem_size, &iop->hw_config.mem_base) == 0) - goto cleanup; - iop->hw_config.mem_size = priv_mem_size; - } - - priv_io_size = ddi_get32(iop->status.acc_hdl, - &iop->status.bufp->DesiredPrivateIOSize); - if (priv_io_size > (uint32_t)0) { - /* need to allocate PCI i/o space */ - if (i2o_get_io(dip, priv_io_size, &iop->hw_config.io_base) == 0) - goto cleanup; - iop->hw_config.io_size = priv_io_size; - } -#endif - - /* - * ************************************************************** - * Step 5: Create the System Table entry for this IOP and send - * ExecSysTabSet to all the IOPs. It enables the IOP - * to OPERATIONAL state. - * ************************************************************** - */ - if (i2o_create_systab(iop) == FAILURE) - goto cleanup; - - ASSERT(iop->status.bufp->IopState == I2O_IOP_STATE_OPERATIONAL); - - /* - * ************************************************************** - * Step 6: Read LCT by sending ExecLctNotify message. - * ************************************************************** - */ - if (i2o_get_lct(iop) == FAILURE) - goto cleanup; - - /* - * ************************************************************** - * Step 7: Set event notification request for the events that - * we are interested. - * ************************************************************** - */ - if (i2o_iop_event_register(iop) == FAILURE) - goto cleanup; - - if (ioplist == NULL) { - ioplist = iop; - iop->next = NULL; - } else { - iop->next = ioplist; - ioplist = iop; - } - iop->iop_flags |= IOP_IS_ONLINE; - iop->ib_msg_frame_size = ddi_get16(iop->nexus_trans->acc_handle, - &iop->status.bufp->InboundMFrameSize) << 2; - - /* find the max TIDs allocated by the IOP */ - iop->osm_registry.max_tid = 0; - lct_entries = - ((ddi_get16(iop->lct.acc_hdl, &iop->lct.bufp->TableSize) << 2) - - sizeof (i2o_lct_t) + sizeof (i2o_lct_entry_t)) / - sizeof (i2o_lct_entry_t); - lct_entp = iop->lct.bufp->LCTEntry; - for (i = 0; i < lct_entries; i++) { - uint_t tid; - - tid = get_lct_entry_LocalTID(&lct_entp[i], iop->lct.acc_hdl); - if (tid > iop->osm_registry.max_tid) - iop->osm_registry.max_tid = tid; - } - - /* allocate the IOP handle table */ - iop->osm_registry.iop_handle_tab = (i2o_iop_impl_hdl_t *) - kmem_zalloc(sizeof (i2o_iop_impl_hdl_t) * - (iop->osm_registry.max_tid + 1), KM_SLEEP); - /* - * initialize the IOP handle (i2o_iop_handle_t) for the nexus to use and - * return the handle. - */ - hdl = &iop->osm_registry.iop_handle_tab[I2O_IOP_TID]; - hdl->dip = dip; - hdl->iop = iop; - hdl->tid = I2O_IOP_TID; - - mutex_exit(&i2o_mutex); - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, "i2o_msg_iop_init: SUCCEEDED")); - - return ((i2o_iop_handle_t *)hdl); - - /* - * Error return; free up the allocated resources and return NULL. - */ -cleanup: - - if (iop->status.bufp != NULL) { - ddi_dma_mem_free(&iop->status.acc_hdl); - ddi_dma_free_handle(&iop->status.dma_handle); - } - - if (iop->lct.bufp != NULL) { - ddi_dma_mem_free(&iop->lct.acc_hdl); - ddi_dma_free_handle(&iop->lct.dma_handle); - } - - if (iop->hrt.bufp != NULL) { - ddi_dma_mem_free(&iop->hrt.acc_hdl); - ddi_dma_free_handle(&iop->hrt.dma_handle); - } - - if (iop->ob_msg_queue.base_addr != NULL) { - ddi_dma_mem_free(&iop->ob_msg_queue.acc_hdl); - ddi_dma_free_handle(&iop->ob_msg_queue.dma_handle); - } - - if (iop->hw_config.mem_base != NULL) { - i2o_return_mem(dip, iop->hw_config.mem_base, - iop->hw_config.mem_size); - } - - if (iop->hw_config.io_base != NULL) { - i2o_return_io(dip, iop->hw_config.io_base, - iop->hw_config.io_size); - } - - mutex_destroy(&iop->iop_ib_mutex); - mutex_destroy(&iop->iop_ob_mutex); - mutex_destroy(&iop->lct.lct_mutex); - - kmem_free((void *)iop, sizeof (iop_instance_t)); - - --niop; - - mutex_exit(&i2o_mutex); - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, "i2o_msg_iop_init: FAILED")); - - return (NULL); -} - -/* - * i2o_msg_iop_unint() - * - * Called from the detach(9E) function in the i2o nexus driver. - * It would uninitialize IOP by sending ExecIopReset to bring the - * IOP to RESET state. And then it will free up any resources/data-structures - * allocated for this IOP instance. - * - * Assumption(s): - * 1. It is assumed that all the I2O devices are quiesced before calling - * this function. Which means all OSMs have already done the - * i2o_msg_osm_unregister() for the devices they claimed. - */ - -int -i2o_msg_iop_uninit(i2o_iop_handle_t *handlep) -{ - i2o_iop_handle_t h = *handlep; - iop_instance_t *iop = ((i2o_iop_impl_hdl_t *)(h))->iop; - ddi_dma_handle_t dma_handle = NULL; - ddi_acc_handle_t acc_hdl; - i2o_exec_iop_reset_status_t *buf = NULL; - i2o_exec_sys_quiesce_message_t *qmsgp; - i2o_single_reply_message_frame_t *rmp = NULL; - iop_instance_t *p; - - mutex_enter(&iop->iop_ib_mutex); - mutex_enter(&iop->iop_ob_mutex); - mutex_enter(&iop->osm_registry.osm_mutex); - mutex_enter(&iop->lct.lct_mutex); - mutex_enter(&i2o_mutex); - - /* - * First, disable the IOP hardware interrupts. - */ - (* iop->nexus_trans->i2o_trans_disable_intr) - (iop->nexus_trans->nexus_handle); - - /* - * ********************************************************* - * if there are multiple IOPs then we need to send - * ExecPathQuiesce message to other IOPs before - * resetting this IOP. - * ********************************************************* - */ - - if (niop > 1) { /* we have multiple IOPs */ - tcontext_t tcxt; /* transaction context structure */ - - cv_init(&tcxt.cv, NULL, CV_DEFAULT, NULL); - mutex_init(&tcxt.cv_mutex, NULL, MUTEX_DRIVER, NULL); - - for (p = ioplist; p != NULL; p = p->next) { - i2o_exec_path_quiesce_message_t *mp; - - if (p == iop) - continue; - - /* - * Send ExecPathQuiesce message to this IOP. - */ - - mp = (i2o_exec_path_quiesce_message_t *)iop_msg_alloc(p); - - if (mp == NULL) { - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_msg_iop_uninit: trans_msg_alloc failed")); - cv_destroy(&tcxt.cv); - mutex_destroy(&tcxt.cv_mutex); - goto cleanup; - } - - /* initialize the transcation context structure */ - tcxt.iop = p; - tcxt.done_flag = 0; - - /* construct the ExecPathQuiesce message */ - - init_std_msghdr(p, &mp->StdMessageFrame, 0x0, 0, - sizeof (i2o_exec_path_quiesce_message_t), - I2O_EXEC_PATH_QUIESCE); - ddi_put32(p->nexus_trans->acc_handle, - &mp->TransactionContext, (uint32_t)(uintptr_t)&tcxt); - ddi_put32(p->nexus_trans->acc_handle, - (uint32_t *)&mp->StdMessageFrame.InitiatorContext. - initiator_context_32bits, - (uint32_t)i2o_msg_common_reply); - put_i2o_exec_path_quiesce_IOP_ID(mp, iop->iop_id, - p->nexus_trans->acc_handle); - ddi_put16(p->nexus_trans->acc_handle, - &mp->HostUnitID, iop->status.bufp->HostUnitID); - - /* send the message to the IOP and wait for the reply */ - - (void) iop_msg_send(p, (void *)mp); - - mutex_enter(&tcxt.cv_mutex); - while (!tcxt.done_flag) /* wait for the reply */ - cv_wait(&tcxt.cv, &tcxt.cv_mutex); - mutex_exit(&tcxt.cv_mutex); - } - - cv_destroy(&tcxt.cv); - mutex_destroy(&tcxt.cv_mutex); - } - - - /* - * ********************************************************* - * Send an ExecSysQuiesce message to the IOP. - * ********************************************************* - */ - - /* allocate a message frame from Inbound queue */ - qmsgp = (i2o_exec_sys_quiesce_message_t *)iop_msg_alloc(iop); - if (qmsgp == NULL) { - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_msg_iop_uninit: trans_msg_alloc failed")); - goto cleanup; - } - - /* construct the ExecSysQuiesce message */ - init_std_msghdr(iop, &qmsgp->StdMessageFrame, 0x0, 0, - sizeof (i2o_exec_sys_quiesce_message_t), - I2O_EXEC_SYS_QUIESCE); - -#ifdef I2O_DEBUG - if (i2o_debug & I2O_DEBUG_MSG) - dump_message((uint32_t *)qmsgp, "ExecSysQuiesce"); -#endif - - /* send the message to the IOP */ - (void) iop_msg_send(iop, (void *)qmsgp); - - /* - * Since interrupts are disabled, we poll for the reply message - * for ExecSysQuiesce request. Could we expect any other reply - * messages for previous activity on this IOP (like some - * event notification)? For now, we can safely ignore any other - * reply messages. - */ - for (;;) { - - if ((rmp = iop_poll_reply_msg(iop)) == NULL) - goto cleanup; - - /* ignore reply messages other than for ExecSysQuiesce */ - if (get_msg_Function((i2o_message_frame_t *)rmp, - iop->ob_msg_queue.acc_hdl) != I2O_EXEC_SYS_QUIESCE) { - iop_msg_free(iop, rmp); - continue; - } - - if (rmp->ReqStatus == I2O_REPLY_STATUS_SUCCESS) - break; /* successful */ - - /* message failed */ - iop_msg_free(iop, rmp); - goto cleanup; - } - - /* free up the reply message buffer */ - iop_msg_free(iop, rmp); - - /* - * ********************************************************* - * Now, send an ExecIopReset message to the IOP. - * ********************************************************* - */ - - if (i2o_send_exec_iop_reset(iop) == FAILURE) - goto cleanup; - - iop->iop_flags |= IOP_IS_IN_UNINIT; - - /* - * ********************************************************* - * Free up the system resources. - * ********************************************************* - */ - if (iop->status.bufp != NULL) { - ddi_dma_mem_free(&iop->status.acc_hdl); - ddi_dma_free_handle(&iop->status.dma_handle); - } - - if (iop->lct.bufp != NULL) { - ddi_dma_mem_free(&iop->lct.acc_hdl); - ddi_dma_free_handle(&iop->lct.dma_handle); - } - - if (iop->hrt.bufp != NULL) { - ddi_dma_mem_free(&iop->hrt.acc_hdl); - ddi_dma_free_handle(&iop->hrt.dma_handle); - } - - if (iop->ob_msg_queue.base_addr != NULL) { - ddi_dma_mem_free(&iop->ob_msg_queue.acc_hdl); - ddi_dma_free_handle(&iop->ob_msg_queue.dma_handle); - } - - if (iop->hw_config.mem_base != NULL) { - i2o_return_mem(iop->dip, iop->hw_config.mem_base, - iop->hw_config.mem_size); - } - - if (iop->hw_config.io_base != NULL) { - i2o_return_io(iop->dip, iop->hw_config.io_base, - iop->hw_config.io_size); - } - - /* - * If i2o_msg_send_proc() is running then wait for it to exit. - */ - if (iop->iop_flags & IOP_SEND_QUEUE_PROC_RUNNING) { - - mutex_exit(&iop->iop_ib_mutex); - - /* wake up the i2o_msg_send_proc() thread */ - cv_broadcast(&iop->send_queue_cv); - - /* wait until the i2o_msg_send_proc() stops running */ - while (iop->iop_flags & IOP_SEND_QUEUE_PROC_RUNNING) - delay(1); - - cv_destroy(&iop->send_queue_cv); - } - - mutex_destroy(&iop->iop_ib_mutex); - mutex_destroy(&iop->iop_ob_mutex); - mutex_destroy(&iop->osm_registry.osm_mutex); - mutex_destroy(&iop->lct.lct_mutex); - - if (iop == ioplist) { - ioplist = ioplist->next; - } else { - iop_instance_t *p, *prev; - - for (prev = ioplist, p = ioplist->next; p; p = p->next) { - if (p == iop) { - prev->next = iop->next; - break; - } - prev = p; - } - - ASSERT((p != NULL) && (p == iop)); - } - - --niop; /* number of active IOPs */ - - mutex_exit(&i2o_mutex); - - /* free up the IOP handle table */ - kmem_free((void *)iop->osm_registry.iop_handle_tab, - sizeof (i2o_iop_impl_hdl_t) * (iop->osm_registry.max_tid + 1)); - - *handlep = NULL; - - kmem_free((void *)iop, sizeof (iop_instance_t)); - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, "i2o_msg_iop_uninit: SUCCEEDED")); - - return (DDI_SUCCESS); - - /* - * Error return; free up the allocated resources and return NULL. - */ -cleanup: - if (buf != NULL) - ddi_dma_mem_free(&acc_hdl); - - if (dma_handle != NULL) - ddi_dma_free_handle(&dma_handle); - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, "i2o_msg_iop_uninit: FAILED")); - - mutex_exit(&i2o_mutex); - mutex_exit(&iop->lct.lct_mutex); - mutex_exit(&iop->osm_registry.osm_mutex); - mutex_exit(&iop->iop_ob_mutex); - mutex_exit(&iop->iop_ib_mutex); - - return (DDI_FAILURE); -} - -/* - * Send ExecStatusGet message to get IOP status. It allocates the - * buffer resources if they are not already allocated. - * - * Returns SUCCESS if it succeeds in getting the IOP status. - */ -static int -i2o_get_iop_status(iop_instance_t *iop) -{ - size_t real_length; - ddi_dma_cookie_t dma_cookie; - uint_t ncookies; - i2o_exec_status_get_message_t *msgp; - i2o_exec_status_get_reply_t *s = 0; - - if (iop->status.dma_handle == NULL) { - - /* allocate a DMA handle */ - if (ddi_dma_alloc_handle(iop->dip, &dma_attr_contig, DDI_DMA_SLEEP, - NULL, &iop->status.dma_handle) != DDI_SUCCESS) { - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_get_iop_status: ddi_dma_alloc_handle failed")); - goto cleanup; - } - } - - if (iop->status.bufp == NULL) { - - /* allocate the buffer for the IOP status block */ - if (ddi_dma_mem_alloc(iop->status.dma_handle, - sizeof (i2o_exec_status_get_reply_t), &i2o_dev_acc_attr, - DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, - (caddr_t *)&iop->status.bufp, &real_length, - &iop->status.acc_hdl) != DDI_SUCCESS) { - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_get_iop_status: ddi_dma_mem_alloc failed")); - goto cleanup; - } - - bzero((caddr_t)iop->status.bufp, real_length); - } - - if (ddi_dma_addr_bind_handle(iop->status.dma_handle, NULL, - (caddr_t)iop->status.bufp, sizeof (i2o_exec_status_get_reply_t), - DDI_DMA_READ | DDI_DMA_STREAMING, DDI_DMA_SLEEP, - NULL, &dma_cookie, &ncookies) != DDI_SUCCESS) { - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_get_iop_status: cannot bind memory")); - goto cleanup; - } - - ASSERT(ncookies == 1); - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_get_iop_status: dma_bind (vaddr %p paddr %x length %x)", - (void *)iop->status.bufp, dma_cookie.dmac_address, - (int)dma_cookie.dmac_size)); - - /* allocate a message frame from Inbound queue */ - msgp = (i2o_exec_status_get_message_t *)iop_msg_alloc(iop); - if (msgp == NULL) { - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_get_iop_status: trans_msg_alloc failed")); - (void) ddi_dma_unbind_handle(iop->status.dma_handle); - goto cleanup; - } - - /* construct the ExecStatusGet message */ - init_std_msghdr(iop, (i2o_message_frame_t *)msgp, 0x0, 0, - sizeof (i2o_exec_status_get_message_t), - I2O_EXEC_STATUS_GET); - ddi_put32(iop->nexus_trans->acc_handle, &msgp->ReplyBufferAddressLow, - dma_cookie.dmac_address); - ddi_put32(iop->nexus_trans->acc_handle, - &msgp->ReplyBufferAddressHigh, 0); - ddi_put32(iop->nexus_trans->acc_handle, &msgp->ReplyBufferLength, - sizeof (i2o_exec_status_get_reply_t)); - iop->status.bufp->SyncByte = 0; - -#ifdef I2O_DEBUG - if (i2o_debug & I2O_DEBUG_MSG) - dump_message((uint32_t *)msgp, "ExecStatusGet"); -#endif - - /* send the message to the IOP */ - (void) iop_msg_send(iop, (void *)msgp); - - /* - * Poll on the status block field 'SyncByte' because there is - * no reply to ExecStatusGet message. The IOP writes '0xFF' - * to 'SyncByte' field when it finished writing to the status - * block structure. - */ - - while (iop->status.bufp->SyncByte != 0xFF) { - delay(1); - /* sync DMA memory */ - (void) ddi_dma_sync(iop->status.dma_handle, - (off_t)&s->SyncByte, 1, DDI_DMA_SYNC_FORCPU); - } - - (void) ddi_dma_unbind_handle(iop->status.dma_handle); - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, "i2o_get_iop_status: SUCCEEDED")); - - return (SUCCESS); - - /* - * Error return; free up the allocated resources and return NULL. - */ -cleanup: - - if (iop->status.bufp != NULL) { - ddi_dma_mem_free(&iop->status.acc_hdl); - iop->status.bufp = NULL; - } - - if (iop->status.dma_handle != NULL) { - ddi_dma_free_handle(&iop->status.dma_handle); - iop->status.dma_handle = NULL; - } - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, "i2o_get_iop_status: FAILED")); - - return (FAILURE); -} - -/* - * Allocate message frames for the Outbound queue and send ExecOutboundInit - * message to the IOP. - * - * Description: - * Since we don't know how to determine how many frames to be - * allocated, we either depend on the user specified property - * (i.e ob-msg-queue-length) or use the current IOP's default. - * Allocate the message queue as one physically contiguous chunk. - * Send ExecOutboundInit message with the list of MFAs. - */ -static int -i2o_init_outbound_queue(iop_instance_t *iop) -{ - size_t real_length; - ddi_dma_cookie_t dma_cookie; - uint_t ncookies; - i2o_exec_outbound_init_message_t *msgp; - int nframes, max_nframes; - int frame_size; - i2o_sge_simple_element_t *sgl; - i2o_exec_outbound_init_status_t *stat; - uint_t mfa; - int count; - - if (iop->ob_msg_queue.dma_handle == NULL) { - - /* allocate a DMA handle */ - if (ddi_dma_alloc_handle(iop->dip, &dma_attr_contig, DDI_DMA_SLEEP, - NULL, &iop->ob_msg_queue.dma_handle) != DDI_SUCCESS) { - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_init_outbound_queue: ddi_dma_alloc_handle failed")); - goto cleanup; - } - } - - if (iop->ob_msg_queue.base_addr == NULL) { - - nframes = ddi_prop_get_int(DDI_DEV_T_ANY, iop->dip, - DDI_PROP_DONTPASS, "ob-msg-queue-length", - ob_msg_queue_length_default); - - max_nframes = ddi_get32(iop->status.acc_hdl, - &iop->status.bufp->MaxOutboundMFrames); - - if (nframes == 0 || nframes > max_nframes) - nframes = max_nframes; - - frame_size = ddi_prop_get_int(DDI_DEV_T_ANY, iop->dip, - DDI_PROP_DONTPASS, "ob-msg-framesize", - ob_msg_framesize_default); - - /* allocate the buffer for the message frames */ - if (ddi_dma_mem_alloc(iop->ob_msg_queue.dma_handle, - (size_t)(nframes * frame_size), &i2o_dev_acc_attr, - DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, - (caddr_t *)&iop->ob_msg_queue.base_addr, &real_length, - &iop->ob_msg_queue.acc_hdl) != DDI_SUCCESS) { - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_init_outbound_queue: ddi_dma_mem_alloc failed")); - goto cleanup; - } - bzero((caddr_t)iop->ob_msg_queue.base_addr, real_length); - iop->ob_msg_queue.nframes = nframes; - iop->ob_msg_queue.framesize = frame_size; - } - - if (ddi_dma_addr_bind_handle(iop->ob_msg_queue.dma_handle, NULL, - iop->ob_msg_queue.base_addr, - (iop->ob_msg_queue.nframes * iop->ob_msg_queue.framesize), - DDI_DMA_READ | DDI_DMA_STREAMING, DDI_DMA_SLEEP, - NULL, &dma_cookie, &ncookies) != DDI_SUCCESS) { - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_init_outbound_queue: cannot bind memory")); - goto cleanup; - } - - ASSERT(ncookies == 1); - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_init_outbound_queue: dma_bind (vaddr %p paddr %x length %x)", - (void *)iop->ob_msg_queue.base_addr, dma_cookie.dmac_address, - (int)dma_cookie.dmac_size)); - - iop->ob_msg_queue.base_paddr = (uint_t)dma_cookie.dmac_address; - - /* allocate a message frame from Inbound queue */ - msgp = (i2o_exec_outbound_init_message_t *)iop_msg_alloc(iop); - if (msgp == NULL) { - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_init_outbound_queue: trans_msg_alloc failed")); - - (void) ddi_dma_unbind_handle(iop->ob_msg_queue.dma_handle); - goto cleanup; - } - - /* - * Construct the ExecOutboundInit message. Use the base address - * of the outbound message queue buffer for the status word structure - * instead of allocating a new word. - */ - init_std_msghdr(iop, &msgp->StdMessageFrame, 0x60, 0, - sizeof (i2o_exec_outbound_init_message_t), - I2O_EXEC_OUTBOUND_INIT); - ddi_put32(iop->nexus_trans->acc_handle, &msgp->HostPageFrameSize, - MMU_PAGESIZE); - msgp->InitCode = I2O_MESSAGE_IF_INIT_CODE_OS; - ddi_put16(iop->nexus_trans->acc_handle, &msgp->OutboundMFrameSize, - ((uint16_t)frame_size) >> 2); - - sgl = (i2o_sge_simple_element_t *)&msgp->SGL; - init_sgl_simple_ele(iop, sgl, - I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, - 4, (uint_t)iop->ob_msg_queue.base_paddr); - - stat = (i2o_exec_outbound_init_status_t *)iop->ob_msg_queue.base_addr; - stat->InitStatus = 0; - -#ifdef I2O_DEBUG - if (i2o_debug & I2O_DEBUG_MSG) - dump_message((uint32_t *)msgp, "ExecOutboundInit"); -#endif - - /* send the message to the IOP */ - (void) iop_msg_send(iop, (void *)msgp); - - /* - * Poll on the status word for completion. - */ - while ((stat->InitStatus == 0) || - (stat->InitStatus == I2O_EXEC_OUTBOUND_INIT_IN_PROGRESS)) { - - delay(2); - /* sync DMA memory */ - (void) ddi_dma_sync(iop->ob_msg_queue.dma_handle, - 0, 1, DDI_DMA_SYNC_FORCPU); - } - - (void) ddi_dma_unbind_handle(iop->ob_msg_queue.dma_handle); - - if (stat->InitStatus != I2O_EXEC_OUTBOUND_INIT_COMPLETE) { - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_init_outbound_queue: FAILED (InitStatus %x)", - stat->InitStatus)); - goto cleanup; - } - - /* - * Now, write the MFAs to the Outbound FIFO. - */ - mfa = iop->ob_msg_queue.base_paddr; - for (count = 0; count < iop->ob_msg_queue.nframes; count ++) { - (* iop->nexus_trans->i2o_trans_msg_freebuf) - (iop->nexus_trans->nexus_handle, mfa); - mfa += iop->ob_msg_queue.framesize; - } - - DEBUGF(I2O_DEBUG_DEBUG, - (CE_CONT, "i2o_init_outbound_queue: SUCCEEDED")); - - return (SUCCESS); - - - /* - * Error return; free up the allocated resources and return NULL. - */ -cleanup: - - if (iop->ob_msg_queue.base_addr != NULL) { - ddi_dma_mem_free(&iop->ob_msg_queue.acc_hdl); - iop->ob_msg_queue.base_addr = NULL; - } - - if (iop->ob_msg_queue.dma_handle != NULL) { - ddi_dma_free_handle(&iop->ob_msg_queue.dma_handle); - iop->ob_msg_queue.dma_handle = NULL; - } - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, "i2o_init_outbound_queue: FAILED")); - - return (FAILURE); -} - -/* - * Get HRT by sending ExecHrtGet message to the IOP. - * It is assumed that Outbound queue is already initialized - * so that the IOP can send a reply to the ExecHrtGet message. - * Also it is assumed that the IOP interrupts are disabled. - */ -static int -i2o_get_hrt(iop_instance_t *iop) -{ - size_t real_length; - ddi_dma_cookie_t dma_cookie; - uint_t ncookies; - i2o_exec_hrt_get_message_t *msgp; - i2o_hrt_t *buf = NULL; - ddi_acc_handle_t acc_hdl; - i2o_single_reply_message_frame_t *rmp = NULL; - uint_t hrt_size; - - /* allocate a DMA handle if necessary */ - if (iop->hrt.dma_handle == NULL) { - if (ddi_dma_alloc_handle(iop->dip, &dma_attr_contig, DDI_DMA_SLEEP, - NULL, &iop->hrt.dma_handle) != DDI_SUCCESS) { - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_get_hrt: ddi_dma_alloc_handle failed")); - goto cleanup; - } - } - - /* - * Allocate a temporary buffer to get the HRT size information - * (i.e only header part of the HRT). - */ - if (ddi_dma_mem_alloc(iop->hrt.dma_handle, - sizeof (i2o_hrt_t), &i2o_dev_acc_attr, - DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, (caddr_t *)&buf, - &real_length, &acc_hdl) != DDI_SUCCESS) { - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_get_hrt: ddi_dma_mem_alloc failed")); - goto cleanup; - } - - bzero((caddr_t)buf, real_length); - - if (ddi_dma_addr_bind_handle(iop->hrt.dma_handle, NULL, (caddr_t)buf, - real_length, DDI_DMA_READ | DDI_DMA_STREAMING, DDI_DMA_SLEEP, - NULL, &dma_cookie, &ncookies) != DDI_SUCCESS) { - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_get_hrt: cannot bind memory")); - goto cleanup; - } - - ASSERT(ncookies == 1); - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_get_hrt: dma_bind (vaddr %p paddr %x length %x)", - (void *)buf, dma_cookie.dmac_address, - (int)dma_cookie.dmac_size)); - - /* allocate a message frame from Inbound queue */ - msgp = (i2o_exec_hrt_get_message_t *)iop_msg_alloc(iop); - if (msgp == NULL) { - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_get_hrt: trans_msg_alloc failed")); - (void) ddi_dma_unbind_handle(iop->hrt.dma_handle); - goto cleanup; - } - - /* - * Construct the ExecHrtGet message. - */ - init_std_msghdr(iop, &msgp->StdMessageFrame, 0x40, 0, - sizeof (i2o_exec_hrt_get_message_t), I2O_EXEC_HRT_GET); - init_sgl_simple_ele(iop, msgp->SGL.u1.Simple, - I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, - sizeof (i2o_hrt_t), (uint_t)dma_cookie.dmac_address); - -#ifdef I2O_DEBUG - if (i2o_debug & I2O_DEBUG_MSG) - dump_message((uint32_t *)msgp, "ExecHrtGet"); -#endif - - /* send the message to the IOP */ - (void) iop_msg_send(iop, (void *)msgp); - - /* since interrupts are disabled, we poll for the reply message */ - rmp = iop_poll_reply_msg(iop); - if ((rmp == NULL) || (rmp->ReqStatus != I2O_REPLY_STATUS_SUCCESS)) { - if (rmp) - iop_msg_free(iop, rmp); - (void) ddi_dma_unbind_handle(iop->hrt.dma_handle); - goto cleanup; - } - - ASSERT(get_msg_Function((i2o_message_frame_t *)rmp, - iop->ob_msg_queue.acc_hdl) == I2O_EXEC_HRT_GET); /* paranoia? */ - - /* free up the reply message buffer */ - iop_msg_free(iop, rmp); - - ASSERT(buf->HRTVersion == 0); /* HRT version for 1.5 is 0x00 */ - - hrt_size = (sizeof (i2o_hrt_t) - sizeof (i2o_hrt_entry_t)) + - (sizeof (i2o_hrt_entry_t) * - ddi_get16(acc_hdl, &buf->NumberEntries)); - - /* - * NOTE: Some old versions of RTOS is not setting the EntryLength - * correctly. Also, I am not sure if all implementations of RTOS - * set this field. So, the following ASSERTION is disabled. - * - * ASSERT((buf->EntryLength * 4) == sizeof (i2o_hrt_entry_t)); - */ - - /* free up the temporary buffer */ - (void) ddi_dma_unbind_handle(iop->hrt.dma_handle); - ddi_dma_mem_free(&acc_hdl); - buf = NULL; - - /* - * Now, allocate the correct size buffer for HRT and send another - * ExecHrtGet message. - */ - if (iop->hrt.bufp == NULL || (iop->hrt.size < hrt_size)) { - - /* free up any old buffer */ - if (iop->hrt.bufp != NULL) { - ddi_dma_mem_free(&iop->hrt.acc_hdl); - iop->hrt.bufp = NULL; - } - - iop->hrt.size = hrt_size; - - /* allocate a new buffer for HRT */ - if (ddi_dma_mem_alloc(iop->hrt.dma_handle, - iop->hrt.size, &i2o_dev_acc_attr, DDI_DMA_CONSISTENT, - DDI_DMA_SLEEP, NULL, (caddr_t *)&iop->hrt.bufp, - &real_length, &iop->hrt.acc_hdl) != DDI_SUCCESS) { - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_get_hrt: ddi_dma_mem_alloc failed")); - goto cleanup; - } - bzero((caddr_t)iop->hrt.bufp, real_length); - } - - if (ddi_dma_addr_bind_handle(iop->hrt.dma_handle, NULL, - (caddr_t)iop->hrt.bufp, iop->hrt.size, - DDI_DMA_READ | DDI_DMA_STREAMING, DDI_DMA_SLEEP, - NULL, &dma_cookie, &ncookies) != DDI_SUCCESS) { - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_get_hrt: cannot bind memory")); - goto cleanup; - } - - ASSERT(ncookies == 1); - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_get_hrt: dma_bind (vaddr %p paddr %x length %x)", - (void *)iop->hrt.bufp, dma_cookie.dmac_address, - (int)dma_cookie.dmac_size)); - - /* allocate a message frame from Inbound queue */ - msgp = (i2o_exec_hrt_get_message_t *)iop_msg_alloc(iop); - if (msgp == NULL) { - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_get_hrt: trans_msg_alloc failed")); - (void) ddi_dma_unbind_handle(iop->hrt.dma_handle); - goto cleanup; - } - - /* - * Construct the ExecHrtGet message (again!). - */ - init_std_msghdr(iop, &msgp->StdMessageFrame, 0x40, 0, - sizeof (i2o_exec_hrt_get_message_t), I2O_EXEC_HRT_GET); - init_sgl_simple_ele(iop, msgp->SGL.u1.Simple, - I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, - hrt_size, (uint_t)dma_cookie.dmac_address); - -#ifdef I2O_DEBUG - if (i2o_debug & I2O_DEBUG_MSG) - dump_message((uint32_t *)msgp, "ExecHrtGet"); -#endif - - /* send the message to the IOP */ - (void) iop_msg_send(iop, (void *)msgp); - - /* since interrupts are disabled, we poll for the reply message */ - rmp = iop_poll_reply_msg(iop); - if ((rmp == NULL) || (rmp->ReqStatus != I2O_REPLY_STATUS_SUCCESS)) { - if (rmp) - iop_msg_free(iop, rmp); -#ifdef I2O_DEBUG - if (i2o_debug & I2O_DEBUG_MSG) - dump_reply_message(iop, rmp); -#endif - (void) ddi_dma_unbind_handle(iop->hrt.dma_handle); - goto cleanup; - } - - ASSERT(get_msg_Function((i2o_message_frame_t *)rmp, - iop->ob_msg_queue.acc_hdl) == I2O_EXEC_HRT_GET); /* paranoia? */ - - /* free up the reply message buffer */ - iop_msg_free(iop, rmp); - - (void) ddi_dma_unbind_handle(iop->hrt.dma_handle); - -#ifdef I2O_DEBUG - if (i2o_debug & I2O_DEBUG_HRT) - dump_hrt(iop); -#endif - - return (SUCCESS); - - /* - * Error return; free up the allocated resources and return NULL. - */ -cleanup: - - if (buf != NULL) - ddi_dma_mem_free(&acc_hdl); - - if (iop->hrt.bufp != NULL) { - ddi_dma_mem_free(&iop->hrt.acc_hdl); - iop->hrt.bufp = NULL; - } - - if (iop->hrt.dma_handle != NULL) { - ddi_dma_free_handle(&iop->hrt.dma_handle); - iop->hrt.dma_handle = NULL; - } - - return (FAILURE); -} - - -/* - * Create the system table entry for the IOP and update all IOPs with - * the latest System Table. It sends ExecSysTabSet message to all - * IOPs. If necessary it sends the ExecSysEnable to the new IOP that - * is being initialized. - * - * Note: It is assumed that this routine is called from the IOP init - * routine. - */ -static int -i2o_create_systab(iop_instance_t *iop) -{ - ddi_dma_handle_t dma_handle = NULL; - ddi_acc_handle_t acc_hdl; - size_t real_length; - ddi_dma_cookie_t dma_cookie; - uint_t ncookies; - i2o_iop_entry_t *entp; - i2o_set_systab_header_t *systab = NULL; - i2o_iop_entry_t *systab_entryp; - int i; - iop_instance_t *p; - i2o_exec_sys_tab_set_message_t *msgp; - i2o_single_reply_message_frame_t *rmp = NULL; - uint_t systab_size; - tcontext_t tcxt; /* transaction context structure */ - - - /* - * ********************************************************* - * Create SysTab entry for this IOP. - * ********************************************************* - */ - if (ddi_dma_alloc_handle(iop->dip, &dma_attr_contig, DDI_DMA_SLEEP, - NULL, &iop->systab.dma_handle) != DDI_SUCCESS) { - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_create_systab: ddi_dma_alloc_handle failed")); - goto cleanup; - } - - /* allocate the buffer for systab entry */ - if (ddi_dma_mem_alloc(iop->systab.dma_handle, sizeof (i2o_iop_entry_t), - &i2o_dev_acc_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, - (caddr_t *)&iop->systab.bufp, &real_length, - &iop->systab.acc_hdl) != DDI_SUCCESS) { - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_create_systab: ddi_dma_mem_alloc failed")); - goto cleanup; - } - - bzero((caddr_t)iop->systab.bufp, real_length); - - /* - * initialize the systab entry with the information from the iop - * status buffer. - */ - entp = iop->systab.bufp; - entp->OrganizationID = iop->status.bufp->OrganizationID; - entp->IopCapabilities = iop->status.bufp->IopCapabilities; - entp->InboundMessageFrameSize = - iop->status.bufp->InboundMFrameSize; - entp->MessengerType = iop->status.bufp->MessengerType; - entp->IopState = I2O_IOP_STATE_OPERATIONAL; /* expected state */ - put_i2o_iop_entry_I2oVersion(entp, - get_i2o_exec_status_reply_I2oVersion(iop->status.bufp, - iop->status.acc_hdl), iop->systab.acc_hdl); - put_i2o_iop_entry_SegmentNumber(entp, - get_i2o_exec_status_reply_SegmentNumber(iop->status.bufp, - iop->status.acc_hdl), iop->systab.acc_hdl); - put_i2o_iop_entry_IOP_ID(entp, iop->iop_id, iop->systab.acc_hdl); - ddi_put32(iop->systab.acc_hdl, - &entp->MessengerInfo.InboundMessagePortAddressLow, - iop->nexus_trans->iop_inbound_fifo_paddr); - ddi_put32(iop->systab.acc_hdl, - &entp->MessengerInfo.InboundMessagePortAddressHigh, 0); - - /* - * ********************************************************* - * Create a System Table for sending ExecSysTabSet message - * to all IOP(s). - * ********************************************************* - */ - /* allocate the buffer for systab header and for the systab entries */ - systab_size = sizeof (i2o_set_systab_header_t) + - (niop * sizeof (i2o_iop_entry_t)); - - if (ddi_dma_alloc_handle(iop->dip, &dma_attr_contig, DDI_DMA_SLEEP, - NULL, &dma_handle) != DDI_SUCCESS) { - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_create_systab: ddi_dma_alloc_handle failed")); - goto cleanup; - } - - if (ddi_dma_mem_alloc(dma_handle, systab_size, - &i2o_dev_acc_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, - (caddr_t *)&systab, &real_length, - &acc_hdl) != DDI_SUCCESS) { - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_create_systab: ddi_dma_mem_alloc failed")); - goto cleanup; - } - - bzero((caddr_t)systab, real_length); - - /* fill in the systab header and systab entries */ - systab->NumberEntries = niop; - systab->SysTabVersion = I2O_VERSION_11; - ddi_put32(iop->systab.acc_hdl, &systab->CurrentChangeIndicator, - (uint32_t)(iop->iop_id - BASE_IOP_ID)); - - systab_entryp = (i2o_iop_entry_t *)&systab[1]; - iop->next = ioplist; - - for (p = iop, i = 0; i < niop; i++) { - systab_entryp[i] = p->systab.bufp[0]; - p = p->next; - } - - if (ddi_dma_addr_bind_handle(dma_handle, NULL, (caddr_t)systab, - real_length, DDI_DMA_WRITE | DDI_DMA_STREAMING, DDI_DMA_SLEEP, - NULL, &dma_cookie, &ncookies) != DDI_SUCCESS) { - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_create_systab: cannot bind memory")); - goto cleanup; - } - - ASSERT(ncookies == 1); - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_create_systab: dma_bind (vaddr %p paddr %x length %x)", - (void *)systab, dma_cookie.dmac_address, - (int)dma_cookie.dmac_size)); - - /* Now, send ExecSysTabSet message to each of the IOPs */ - for (p = iop, i = 0; i < niop; i++) { - - /* allocate a message frame from Inbound queue */ - msgp = (i2o_exec_sys_tab_set_message_t *)iop_msg_alloc(p); - if (msgp == NULL) { - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_create_systab: trans_msg_alloc failed")); - (void) ddi_dma_unbind_handle(dma_handle); - goto cleanup; - } - /* - * Construct the ExecSysTabSet message. - * - * Note: The implied assumption is that the message frame has - * enough room for 3 SGL elements. - */ - - init_std_msghdr(p, &msgp->StdMessageFrame, 0x40, 0, - sizeof (i2o_exec_sys_tab_set_message_t) + - 2 * sizeof (i2o_sg_element_t), I2O_EXEC_SYS_TAB_SET); - msgp->HostUnitID = 0; - put_i2o_exec_sys_tab_set_SegmentNumber(msgp, - get_i2o_exec_status_reply_SegmentNumber(p->status.bufp, - p->status.acc_hdl), p->systab.acc_hdl); - put_i2o_exec_sys_tab_set_IOP_ID(msgp, p->iop_id, - p->systab.acc_hdl); - - if (p != iop) { - /* - * For other IOPs we don't poll the reply, so - * setup the InitiatorContext/TransactionContext. - */ - cv_init(&tcxt.cv, NULL, CV_DEFAULT, NULL); - mutex_init(&tcxt.cv_mutex, NULL, MUTEX_DRIVER, NULL); - /* initialize the transcation context structure */ - tcxt.iop = p; - tcxt.done_flag = 0; - ddi_put32(p->nexus_trans->acc_handle, - &msgp->TransactionContext, - (uint32_t)(uintptr_t)&tcxt); - ddi_put32(p->nexus_trans->acc_handle, - (uint32_t *)&msgp->StdMessageFrame.InitiatorContext. - initiator_context_32bits, - (uint32_t)i2o_msg_common_reply); - } - - /* First buffer is for systab itself */ - init_sgl_simple_ele(p, &msgp->SGL.u1.Simple[0], - I2O_SGL_FLAGS_END_OF_BUFFER, systab_size, - (uint_t)dma_cookie.dmac_address); - - /* - * Second buffer is for Private Memory Space allocation. - * - * Note: The spec is not clear if this buffer can be NULL - * for the IOP which was already initialized to OP state - * and there is no change to its configuration. Here, we - * will set it to NULL assuming that it is ignored. - */ - if (p == iop) { - init_sgl_simple_ele(p, &msgp->SGL.u1.Simple[1], - I2O_SGL_FLAGS_END_OF_BUFFER, - p->hw_config.mem_size, (uint_t)p->hw_config.mem_base); - } else { - init_sgl_simple_ele(p, &msgp->SGL.u1.Simple[1], - I2O_SGL_FLAGS_END_OF_BUFFER, 0, 0); - } - - /* - * Third buffer is for Private IO Space allocation. - * - * Note: The spec is not clear if this buffer can be NULL - * for the IOP which was already initialized to OP state - * and there is no change to its configuration. Here, we - * will set it to NULL assuming that it is ignored. - */ - if (p == iop) { - init_sgl_simple_ele(p, &msgp->SGL.u1.Simple[2], - I2O_SGL_FLAGS_LAST_ELEMENT | - I2O_SGL_FLAGS_END_OF_BUFFER, - p->hw_config.io_size, (uint_t)p->hw_config.io_base); - } else { - init_sgl_simple_ele(p, &msgp->SGL.u1.Simple[2], - I2O_SGL_FLAGS_LAST_ELEMENT | - I2O_SGL_FLAGS_END_OF_BUFFER, 0, 0); - } - -#ifdef I2O_DEBUG - if (i2o_debug & I2O_DEBUG_MSG) - dump_message((uint32_t *)msgp, "ExecSysTabSet"); -#endif - - /* send the message to the IOP */ - (void) iop_msg_send(p, (void *)msgp); - - /* wait for the reply message */ - if (p == iop) { - /* - * For this IOP, interrupts are disabled. So, we poll - * for the reply message. - */ - rmp = iop_poll_reply_msg(p); - - if ((rmp == NULL) || - (rmp->ReqStatus != I2O_REPLY_STATUS_SUCCESS)) { - - if (rmp) - iop_msg_free(p, rmp); -#ifdef I2O_DEBUG - if (i2o_debug & I2O_DEBUG_MSG) - dump_reply_message(p, rmp); -#endif - (void) ddi_dma_unbind_handle(dma_handle); - goto cleanup; - } - - /* paranoia? */ - ASSERT(get_msg_Function((i2o_message_frame_t *)rmp, - iop->ob_msg_queue.acc_hdl) == I2O_EXEC_SYS_TAB_SET); - - /* free up the reply message buffer */ - iop_msg_free(p, rmp); - - } else { - /* For other IOPs, wait for the reply message */ - mutex_enter(&tcxt.cv_mutex); - while (!tcxt.done_flag) /* wait for the reply */ - cv_wait(&tcxt.cv, &tcxt.cv_mutex); - mutex_exit(&tcxt.cv_mutex); - - cv_destroy(&tcxt.cv); - mutex_destroy(&tcxt.cv_mutex); - - /* check the status for SUCCESS */ - if (tcxt.status != I2O_REPLY_STATUS_SUCCESS) { - (void) ddi_dma_unbind_handle(dma_handle); - goto cleanup; - } - } - - /* - * For the new IOP, send the ExecSysEnable message. - */ - if (p == iop) { - if (i2o_send_exec_enable(iop) != SUCCESS) { - (void) ddi_dma_unbind_handle(dma_handle); - goto cleanup; - } - } - } - - (void) ddi_dma_unbind_handle(dma_handle); - - if (iop->status.bufp->IopState != I2O_IOP_STATE_OPERATIONAL) { - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_create_systab: invalid IOP state")); - goto cleanup; - } - - ddi_dma_mem_free(&acc_hdl); /* free the systab buffer */ - - ddi_dma_free_handle(&dma_handle); - - return (SUCCESS); - - /* - * Error return; free up the allocated resources and return NULL. - */ -cleanup: - - if (iop->systab.bufp != NULL) { - ddi_dma_mem_free(&iop->systab.acc_hdl); - iop->systab.bufp = NULL; - } - - if (iop->systab.dma_handle != NULL) { - ddi_dma_free_handle(&iop->systab.dma_handle); - iop->systab.dma_handle = NULL; - } - - if (systab != NULL) - ddi_dma_mem_free(&acc_hdl); - - if (dma_handle != NULL) - ddi_dma_free_handle(&dma_handle); - - return (FAILURE); -} - -/* - * Send the ExecSysEnable message to the IOP if it is in the - * READY state. It assumes that the IOP interrupts are disabled. - */ -static int -i2o_send_exec_enable(iop_instance_t *iop) -{ - i2o_exec_sys_enable_message_t *mp; - i2o_single_reply_message_frame_t *rmp = NULL; - - /* - * Get the current state of IOP. - */ - if (i2o_get_iop_status(iop) == FAILURE) - goto cleanup; - - if (iop->status.bufp->IopState == I2O_IOP_STATE_READY) { - /* allocate a message frame from Inbound queue */ - mp = (i2o_exec_sys_enable_message_t *)iop_msg_alloc(iop); - if (mp == NULL) { - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_create_systab: trans_msg_alloc failed")); - goto cleanup; - } - - /* Construct the ExecSysEanble message. */ - init_std_msghdr(iop, &mp->StdMessageFrame, 0x0, 0, - sizeof (i2o_exec_sys_enable_message_t), I2O_EXEC_SYS_ENABLE); - -#ifdef I2O_DEBUG - if (i2o_debug & I2O_DEBUG_MSG) - dump_message((uint32_t *)mp, "ExecSysEnable"); -#endif - - /* send the message to the IOP */ - (void) iop_msg_send(iop, (void *)mp); - - /* since interrupts are disabled, we poll for the reply message */ - rmp = iop_poll_reply_msg(iop); - if ((rmp == NULL) || (rmp->ReqStatus != I2O_REPLY_STATUS_SUCCESS)) { -#ifdef I2O_DEBUG - if (i2o_debug & I2O_DEBUG_MSG) - dump_reply_message(iop, rmp); -#endif - if (rmp) - iop_msg_free(iop, rmp); - goto cleanup; - } - - /* paranoia? */ - ASSERT(get_msg_Function((i2o_message_frame_t *)rmp, - iop->ob_msg_queue.acc_hdl) == I2O_EXEC_SYS_ENABLE); - - iop_msg_free(iop, rmp); /* free up the reply message buffer */ - - /* get the IOP state now; it should be in OPERATIONAL state */ - if (i2o_get_iop_status(iop) == FAILURE) - goto cleanup; - } - - return (SUCCESS); - -cleanup: - return (FAILURE); -} - -/* - * Send an ExecIopReset message. This function is called from the - * i2o_msg_iop_init() with interrupts disabled. - */ -static int -i2o_send_exec_iop_reset(iop_instance_t *iop) -{ - ddi_dma_handle_t dma_handle = NULL; - ddi_acc_handle_t acc_hdl; - i2o_exec_iop_reset_status_t *buf = NULL; - i2o_exec_iop_reset_message_t *rmsgp; - size_t real_length; - ddi_dma_cookie_t dma_cookie; - uint_t ncookies; - - /* allocate a DMA handle */ - if (ddi_dma_alloc_handle(iop->dip, &dma_attr_contig, DDI_DMA_SLEEP, - NULL, &dma_handle) != DDI_SUCCESS) { - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_send_exec_iop_reset: ddi_dma_alloc_handle failed")); - goto cleanup; - } - - /* - * Allocate a temporary buffer for the status word structure. - */ - if (ddi_dma_mem_alloc(dma_handle, - sizeof (i2o_exec_iop_reset_status_t), &i2o_dev_acc_attr, - DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, (caddr_t *)&buf, - &real_length, &acc_hdl) != DDI_SUCCESS) { - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_send_exec_iop_reset: ddi_dma_mem_alloc failed")); - goto cleanup; - } - - if (ddi_dma_addr_bind_handle(dma_handle, NULL, (caddr_t)buf, - real_length, DDI_DMA_READ | DDI_DMA_STREAMING, DDI_DMA_SLEEP, - NULL, &dma_cookie, &ncookies) != DDI_SUCCESS) { - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_send_exec_iop_reset: cannot bind memory")); - goto cleanup; - } - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_send_exec_iop_reset: dma_bind (vaddr %p paddr %x length %x)", - (void *)buf, dma_cookie.dmac_address, (int)dma_cookie.dmac_size)); - - /* allocate a message frame from Inbound queue */ - rmsgp = (i2o_exec_iop_reset_message_t *)iop_msg_alloc(iop); - if (rmsgp == NULL) { - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_send_exec_iop_reset: trans_msg_alloc failed")); - (void) ddi_dma_unbind_handle(dma_handle); - goto cleanup; - } - - /* construct the ExecIopReset message */ - init_std_msghdr(iop, (i2o_message_frame_t *)rmsgp, 0x0, 0, - sizeof (i2o_exec_iop_reset_message_t), - I2O_EXEC_IOP_RESET); - ddi_put32(iop->nexus_trans->acc_handle, &rmsgp->StatusWordLowAddress, - dma_cookie.dmac_address); - ddi_put32(iop->nexus_trans->acc_handle, - &rmsgp->StatusWordHighAddress, 0); - buf->ResetStatus = 0; - -#ifdef I2O_DEBUG - if (i2o_debug & I2O_DEBUG_MSG) - dump_message((uint32_t *)rmsgp, "ExecIopReset"); -#endif - - /* send the message to the IOP */ - (void) iop_msg_send(iop, (void *)rmsgp); - - /* poll on the status word for IN_PROGRESS state */ - while (buf->ResetStatus != I2O_EXEC_IOP_RESET_IN_PROGRESS) { - int mseconds = 60000; /* 60 seconds */ - - if (buf->ResetStatus == I2O_EXEC_IOP_RESET_REJECTED) - goto cleanup; - - if (--mseconds < 0) { - DEBUGF(I2O_DEBUG_DEBUG, - (CE_CONT, "iop_reset: timed out")); - goto cleanup; - } - - drv_usecwait(1000); /* wait for 1msec */ - - /* sync DMA memory */ - (void) ddi_dma_sync(dma_handle, 0, 1, DDI_DMA_SYNC_FORCPU); - } - - (void) ddi_dma_unbind_handle(dma_handle); - - ddi_dma_mem_free(&acc_hdl); - - ddi_dma_free_handle(&dma_handle); - - return (SUCCESS); - - /* - * Error return; free up the allocated resources and return NULL. - */ -cleanup: - if (buf != NULL) - ddi_dma_mem_free(&acc_hdl); - - if (dma_handle != NULL) - ddi_dma_free_handle(&dma_handle); - - return (FAILURE); -} - - -static int -i2o_get_lct(iop_instance_t *iop) -{ - size_t real_length; - ddi_dma_cookie_t dma_cookie; - uint_t ncookies; - i2o_exec_lct_notify_message_t *msgp; - i2o_single_reply_message_frame_t *rmp = NULL; - uint_t lct_size; - - /* allocate a DMA handle if necessary */ - if (iop->lct.dma_handle == NULL) { - if (ddi_dma_alloc_handle(iop->dip, &dma_attr_contig, DDI_DMA_SLEEP, - NULL, &iop->lct.dma_handle) != DDI_SUCCESS) { - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_get_lct: ddi_dma_alloc_handle failed")); - goto cleanup; - } - } - - lct_size = ddi_get32(iop->status.acc_hdl, - &iop->status.bufp->ExpectedLCTSize); - /* - * Allocate the buffer for LCT and send ExecLctNotify message. - */ - if (iop->lct.bufp == NULL || (iop->lct.size < lct_size)) { - - /* free up any old buffer */ - if (iop->lct.bufp != NULL) { - ddi_dma_mem_free(&iop->lct.acc_hdl); - iop->lct.bufp = NULL; - } - - iop->lct.size = lct_size; - - /* allocate a new buffer for LCT */ - if (ddi_dma_mem_alloc(iop->lct.dma_handle, - iop->lct.size, &i2o_dev_acc_attr, DDI_DMA_CONSISTENT, - DDI_DMA_SLEEP, NULL, (caddr_t *)&iop->lct.bufp, - &real_length, &iop->lct.acc_hdl) != DDI_SUCCESS) { - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_get_lct: ddi_dma_mem_alloc failed")); - goto cleanup; - } - - bzero((caddr_t)iop->lct.bufp, real_length); - } - - if (ddi_dma_addr_bind_handle(iop->lct.dma_handle, NULL, - (caddr_t)iop->lct.bufp, iop->lct.size, - DDI_DMA_READ | DDI_DMA_STREAMING, DDI_DMA_SLEEP, - NULL, &dma_cookie, &ncookies) != DDI_SUCCESS) { - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_get_lct: cannot bind memory")); - goto cleanup; - } - - ASSERT(ncookies == 1); - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_get_lct: dma_bind (vaddr %p paddr %x length %x)", - (void *)iop->lct.bufp, dma_cookie.dmac_address, - (int)dma_cookie.dmac_size)); - - /* allocate a message frame from Inbound queue */ - msgp = (i2o_exec_lct_notify_message_t *)iop_msg_alloc(iop); - if (msgp == NULL) { - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_get_lct: trans_msg_alloc failed")); - (void) ddi_dma_unbind_handle(iop->lct.dma_handle); - goto cleanup; - } - - /* - * Construct the ExecLctNotify message. - */ - init_std_msghdr(iop, &msgp->StdMessageFrame, 0x60, 0, - sizeof (i2o_exec_lct_notify_message_t), I2O_EXEC_LCT_NOTIFY); - msgp->ClassIdentifier = (uint32_t)0xFFFFFFFF; - msgp->LastReportedChangeIndicator = 0x0; - init_sgl_simple_ele(iop, msgp->SGL.u1.Simple, - I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, - iop->lct.size, (uint_t)dma_cookie.dmac_address); - -#ifdef I2O_DEBUG - if (i2o_debug & I2O_DEBUG_MSG) - dump_message((uint32_t *)msgp, "ExecLctNotify"); -#endif - - /* send the message to the IOP */ - (void) iop_msg_send(iop, (void *)msgp); - - /* since interrupts are disabled, we poll for the reply message */ - rmp = iop_poll_reply_msg(iop); - if ((rmp == NULL) || (rmp->ReqStatus != I2O_REPLY_STATUS_SUCCESS)) { - -#ifdef I2O_DEBUG - if (i2o_debug & I2O_DEBUG_MSG) - dump_reply_message(iop, rmp); -#endif - if (rmp) - iop_msg_free(iop, rmp); - (void) ddi_dma_unbind_handle(iop->lct.dma_handle); - goto cleanup; - } - - /* paranoia? */ - ASSERT(get_msg_Function((i2o_message_frame_t *)rmp, - iop->ob_msg_queue.acc_hdl) == I2O_EXEC_LCT_NOTIFY); - - /* free up the reply message buffer */ - iop_msg_free(iop, rmp); - - (void) ddi_dma_unbind_handle(iop->lct.dma_handle); - -#ifdef I2O_DEBUG - if (i2o_debug & I2O_DEBUG_LCT) - dump_lct(iop); -#endif - - return (SUCCESS); - - /* - * Error return; free up the allocated resources and return NULL. - */ -cleanup: - - if (iop->lct.bufp != NULL) { - ddi_dma_mem_free(&iop->lct.acc_hdl); - iop->lct.bufp = NULL; - } - - if (iop->lct.dma_handle != NULL) { - ddi_dma_free_handle(&iop->lct.dma_handle); - iop->lct.dma_handle = NULL; - } - - return (FAILURE); -} - -#define EXEC_CLASS_EVENT_MASK \ - (I2O_EVENT_IND_RESOURCE_LIMIT | I2O_EVENT_IND_CONNECTION_FAIL | \ - I2O_EVENT_IND_ADAPTER_FAULT | I2O_EVENT_IND_POWER_FAIL | \ - I2O_EVENT_IND_RESET_PENDING | I2O_EVENT_IND_RESET_IMMINENT | \ - I2O_EVENT_IND_HARDWARE_FAIL | I2O_EVENT_IND_XCT_CHANGE | \ - I2O_EVENT_IND_NEW_LCT_ENTRY | I2O_EVENT_IND_MODIFIED_LCT | \ - I2O_EVENT_IND_DDM_AVAILABILITY) - -/* - * Register Executive Class events to get notified by the IOP when - * any of these events occur. - * - * Assumpition: IOP interrupts are disabled. - */ -static int -i2o_iop_event_register(iop_instance_t *iop) -{ - i2o_util_event_register_message_t *msgp; - - /* allocate a message frame from Inbound queue */ - msgp = (i2o_util_event_register_message_t *)iop_msg_alloc(iop); - if (msgp == NULL) { - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_iop_event_register: trans_msg_alloc failed")); - return (FAILURE); - } - - /* - * Construct the UtilEventRegister message. There is no reply - * to this message until one of the specified events occurs. - */ - init_std_msghdr(iop, &msgp->StdMessageFrame, 0x0, 0, - sizeof (i2o_util_event_register_message_t), - I2O_UTIL_EVENT_REGISTER); - ddi_put32(iop->nexus_trans->acc_handle, - &msgp->TransactionContext, (uint32_t)(uintptr_t)iop); - ddi_put32(iop->nexus_trans->acc_handle, - (uint32_t *)&msgp->StdMessageFrame.InitiatorContext. - initiator_context_32bits, (uint32_t)i2o_msg_iop_event_reply); - /* Fow now, specify only the Executive Class events and */ - /* Config Dialog request event */ - ddi_put32(iop->nexus_trans->acc_handle, &msgp->EventMask, - EXEC_CLASS_EVENT_MASK | I2O_EVENT_IND_CONFIGURATION_FLAG); - - iop->event_mask = EXEC_CLASS_EVENT_MASK; - -#ifdef I2O_DEBUG - if (i2o_debug & I2O_DEBUG_MSG) - dump_message((uint32_t *)msgp, "UtilEventRegister"); -#endif - - /* send the message to the IOP */ - (void) iop_msg_send(iop, (void *)msgp); - - return (SUCCESS); -} - -/* - * called by the I2O nexus driver from i2o_create_devinfo(). - */ -void -i2o_msg_get_lct_info(i2o_iop_handle_t *handlep, i2o_lct_t **lctp, - ddi_acc_handle_t *acc_handlep) -{ - iop_instance_t *iop = ((i2o_iop_impl_hdl_t *)handlep)->iop; - - if (lctp) - *lctp = iop->lct.bufp; - - if (acc_handlep) - *acc_handlep = iop->lct.acc_hdl; -} - - -/* - * ************************************************************************ - * *** Reply Message Processing functions *** - * ************************************************************************ - */ - -/* - * Call back function to process the Executive Class event notification - * messages. - * - * For now, we process only the MODIFY_LCT event to update the local - * copy of the LCT. For other events we simply print the event information - * and ignore it. XXX FIX IT WHEN NEEDED XXX - */ -static void -i2o_msg_iop_event_reply(void *p, ddi_acc_handle_t acc_hdl) -{ - i2o_util_event_register_reply_t *msgp; - iop_instance_t *iop; - uint32_t event_indicator; - i2o_hrt_entry_t *hrt_entp; - i2o_lct_entry_t *lct_entp; - i2o_lct_entry_t *lp; - uint_t tid; - int i, n; - uint32_t event_data; - - msgp = (i2o_util_event_register_reply_t *)p; - iop = (iop_instance_t *) - (uintptr_t)ddi_get32(acc_hdl, &msgp->TransactionContext); - event_indicator = ddi_get32(acc_hdl, &msgp->EventIndicator); - - switch (event_indicator) { - - case I2O_EVENT_IND_ADAPTER_FAULT: - hrt_entp = (i2o_hrt_entry_t *)msgp->EventData; - cmn_err(CE_CONT, - "^Received ADAPTER_FAULT event from the IOP %x", - iop->iop_id); - cmn_err(CE_CONT, "^\tAdapterID: %x\n", ddi_get32(acc_hdl, - &hrt_entp->AdapterID)); - cmn_err(CE_CONT, "^\tControllingTID: %x\n", - get_hrt_entry_ControllingTID(hrt_entp, acc_hdl)); - cmn_err(CE_CONT, "^\tAdapterState: %x\n", - get_hrt_entry_AdapterState(hrt_entp, acc_hdl)); - cmn_err(CE_CONT, "^\tBusType: %x\n", hrt_entp->BusType); - cmn_err(CE_CONT, "^\tBusNumber: %x\n", hrt_entp->BusNumber); - break; - - case I2O_EVENT_IND_CONNECTION_FAIL: - cmn_err(CE_CONT, - "^Received CONNECTION_FAIL event from the IOP %x", - iop->iop_id); - break; - - case I2O_EVENT_IND_DDM_AVAILABILITY: - cmn_err(CE_CONT, - "^Received DDM_AVAILABILITY event from the IOP %x", - iop->iop_id); - event_data = ddi_get32(acc_hdl, msgp->EventData); - cmn_err(CE_CONT, "^\tTID %x Error Code %x", event_data & 0xFFF, - (event_data >> 12) & 0xF); - break; - - case I2O_EVENT_IND_HARDWARE_FAIL: - cmn_err(CE_CONT, - "^Received HARDWARE_FAIL event from the IOP %x", - iop->iop_id); - event_data = ddi_get32(acc_hdl, msgp->EventData); - cmn_err(CE_CONT, "^\tError Code %x", event_data); - break; - - case I2O_EVENT_IND_MODIFIED_LCT: - /* - * LCT entry is modified. Need to update the local - * copy of the LCT. - */ - - lct_entp = (i2o_lct_entry_t *)msgp->EventData; - tid = get_lct_entry_LocalTID(lct_entp, acc_hdl); - - /* - * locate the entry in the local copy of the LCT that - * matches the TID that has changed. And update the entry. - */ - mutex_enter(&iop->lct.lct_mutex); - - lp = iop->lct.bufp->LCTEntry; - n = ((ddi_get16(iop->lct.acc_hdl, &iop->lct.bufp->TableSize) << - 2) - sizeof (i2o_lct_t) + sizeof (i2o_lct_entry_t)) / - sizeof (i2o_lct_entry_t); - - for (i = 0; i < n; i++) { - if (tid == get_lct_entry_LocalTID(&lp[i], iop->lct.acc_hdl)) - break; - } - - ASSERT(i < n); - - /* copy the modified entry */ - lp[i] = *lct_entp; - - mutex_exit(&iop->lct.lct_mutex); - -#ifdef I2O_DEBUG - cmn_err(CE_CONT, "!Received MODIFY_LCT event from the IOP %x", - iop->iop_id); - cmn_err(CE_CONT, "!\tLocalTID: %x\n", - get_lct_entry_LocalTID(lct_entp, acc_hdl)); - cmn_err(CE_CONT, "!\tDeviceFlags: %x\n", - ddi_get32(acc_hdl, &lct_entp->DeviceFlags)); - cmn_err(CE_CONT, "!\tChangeIndicator: %x\n", - ddi_get32(acc_hdl, &lct_entp->ChangeIndicator)); - cmn_err(CE_CONT, "!\tClass: %x\n", - get_lct_entry_Class(lct_entp, acc_hdl)); - cmn_err(CE_CONT, "!\tSubClassInfo: %x\n", - ddi_get32(acc_hdl, &lct_entp->SubClassInfo)); - cmn_err(CE_CONT, "!\tParentTID: %x\n", - get_lct_entry_ParentTID(lct_entp, acc_hdl)); - cmn_err(CE_CONT, "!\tUserTID: %x\n", - get_lct_entry_UserTID(lct_entp, acc_hdl)); - cmn_err(CE_CONT, "!\tEventCapabilities: %x\n", - ddi_get32(acc_hdl, &lct_entp->EventCapabilities)); -#endif - break; - - case I2O_EVENT_IND_NEW_LCT_ENTRY: - cmn_err(CE_CONT, - "^Received NEW_LCT_ENTRY event from the IOP %x", - iop->iop_id); - lct_entp = (i2o_lct_entry_t *)msgp->EventData; - cmn_err(CE_CONT, "^\tLocalTID: %x\n", - get_lct_entry_LocalTID(lct_entp, acc_hdl)); - cmn_err(CE_CONT, "^\tDeviceFlags: %x\n", - ddi_get32(acc_hdl, &lct_entp->DeviceFlags)); - cmn_err(CE_CONT, "^\tChangeIndicator: %x\n", - ddi_get32(acc_hdl, &lct_entp->ChangeIndicator)); - cmn_err(CE_CONT, "^\tClass: %x\n", - get_lct_entry_Class(lct_entp, acc_hdl)); - cmn_err(CE_CONT, "^\tSubClassInfo: %x\n", - ddi_get32(acc_hdl, &lct_entp->SubClassInfo)); - cmn_err(CE_CONT, "^\tParentTID: %x\n", - get_lct_entry_ParentTID(lct_entp, acc_hdl)); - cmn_err(CE_CONT, "^\tUserTID: %x\n", - get_lct_entry_UserTID(lct_entp, acc_hdl)); - cmn_err(CE_CONT, "^\tEventCapabilities: %x\n", - ddi_get32(acc_hdl, &lct_entp->EventCapabilities)); - break; - - case I2O_EVENT_IND_POWER_FAIL: - cmn_err(CE_CONT, "^Received POWER_FAIL event from the IOP %x", - iop->iop_id); - break; - - case I2O_EVENT_IND_RESOURCE_LIMIT: - cmn_err(CE_CONT, - "^Received RESOURCE_LIMITS event from the IOP %x", - iop->iop_id); - event_data = ddi_get32(acc_hdl, msgp->EventData); - cmn_err(CE_CONT, "^\tError Code %x", event_data); - break; - - case I2O_EVENT_IND_XCT_CHANGE: - cmn_err(CE_CONT, "^Received XCT_CHANGE event from the IOP %x", - iop->iop_id); - break; - - case I2O_EVENT_IND_RESET_IMMINENT: - cmn_err(CE_CONT, - "^Received RESET_IMMINENT event from the IOP %x", - iop->iop_id); - break; - - case I2O_EVENT_IND_RESET_PENDING: - cmn_err(CE_CONT, - "^Received RESET_PENDING event from the IOP %x", - iop->iop_id); - break; - - case I2O_EVENT_IND_CONFIGURATION_FLAG: - cmn_err(CE_CONT, - "^Received CONFIGURATION_FLAG event from the IOP %x", - iop->iop_id); - break; - } -} - -/* - * Common reply message processing function: It simply copies the status - * code and sets the done_flag in the tcontext structure. - */ -static void -i2o_msg_common_reply(void *p, ddi_acc_handle_t acc_hdl) -{ - tcontext_t *tp; - - tp = (tcontext_t *)(uintptr_t)ddi_get32(acc_hdl, - &((i2o_single_reply_message_frame_t *)p)->TransactionContext); - - mutex_enter(&tp->cv_mutex); - tp->status = (int)((i2o_single_reply_message_frame_t *)p)->ReqStatus; - tp->done_flag = 1; - cv_broadcast(&tp->cv); - mutex_exit(&tp->cv_mutex); -} - -/* - * ************************************************************************ - * *** Implementation of OSM interfaces (PSARC: 1997/173) *** - * ************************************************************************ - */ - -/* - * Register the OSM for the specified I2O device. - * - * Implementation: The simplest implementation is to use the TID of - * the I2O device as the key to avoid multiple registrations. Since - * the max number of TIDs allocated is not big (< 32) we can simply - * maintain an array and use TID as the index. From the dip we need - * to find the IOP that this device belongs to. Currently, we do - * this by looking into the ioplist that matches with the devinfo - * node pointer of the parent for this device. - */ -int -i2o_msg_osm_register(dev_info_t *dip, i2o_iop_handle_t *handlep) -{ - uint_t tid; - dev_info_t *pdip; - iop_instance_t *iop; - i2o_iop_impl_hdl_t *hdl; - - /* get the TID for this device */ - tid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "i2o-device-id", -1); - if (tid == (uint_t)-1) - return (DDI_FAILURE); - - /* - * Find the IOP that matches the parent of this device. - */ - pdip = ddi_get_parent(dip); - mutex_enter(&i2o_mutex); - for (iop = ioplist; iop; iop = iop->next) { - if (iop->dip == pdip) - break; - } - mutex_exit(&i2o_mutex); - - if (iop == NULL) - return (DDI_FAILURE); - - mutex_enter(&iop->osm_registry.osm_mutex); - - ASSERT(tid <= iop->osm_registry.max_tid); - - hdl = &iop->osm_registry.iop_handle_tab[tid]; - - /* verify that the device is not already registerd. */ - if (hdl->dip != NULL) { - mutex_exit(&iop->osm_registry.osm_mutex); - return (DDI_FAILURE); - } - - hdl->dip = dip; - hdl->iop = iop; - hdl->tid = tid; - - mutex_exit(&iop->osm_registry.osm_mutex); - - *handlep = (i2o_iop_handle_t *)hdl; - - return (DDI_SUCCESS); -} - -void -i2o_msg_osm_unregister(i2o_iop_handle_t *handlep) -{ - iop_instance_t *iop; - i2o_iop_impl_hdl_t *hdl = *(i2o_iop_impl_hdl_t **)handlep; - - iop = hdl->iop; - - ASSERT(hdl->tid <= iop->osm_registry.max_tid); - - mutex_enter(&iop->osm_registry.osm_mutex); - - hdl->dip = NULL; - hdl->iop = NULL; - hdl->tid = NULL; - - mutex_exit(&iop->osm_registry.osm_mutex); - - *handlep = NULL; -} - -/* - * Allocate a message frame for sending an I2O request message. - * - * Description: We allocate a system memory buffer so that the caller - * can take his own time to prepare the message. When the caller - * calls i2o_msg_send() then we allocate the real message frame - * from the inbound queue and free up the system memory buffer - * after copying the data. - */ -int -i2o_msg_alloc(i2o_iop_handle_t iop_hdl, int (*waitfp)(caddr_t), - caddr_t arg, void **msgp, i2o_msg_handle_t *msg_handlep, - ddi_acc_handle_t *acc_handlep) -{ - iop_instance_t *iop = ((i2o_iop_impl_hdl_t *)iop_hdl)->iop; - i2o_msg_impl_hdl_t *hdl; - ddi_acc_handle_t acc_hdl; - ddi_dma_handle_t dma_handle; - caddr_t buf; - size_t real_length; - size_t size; - - /* - * Allocate the message frame buffer from the system memory. - * - * Note: - * For now, the allocation is done by directly calling - * the DDI framework. Later this should be fixed to allocate - * it from a local pool for performance reasons. - */ - - if (ddi_dma_alloc_handle(iop->dip, &dma_attr_contig, waitfp, - arg, &dma_handle) != DDI_SUCCESS) - return (DDI_FAILURE); - - /* size of the buffer includes the i2o_msg_impl_hdl_t structure */ - size = iop->ib_msg_frame_size + sizeof (i2o_msg_impl_hdl_t); - - if (ddi_dma_mem_alloc(dma_handle, size, &i2o_dev_acc_attr, - DDI_DMA_CONSISTENT, waitfp, arg, &buf, - &real_length, &acc_hdl) != DDI_SUCCESS) { - - ddi_dma_free_handle(&dma_handle); - return (DDI_FAILURE); - } - - hdl = (i2o_msg_impl_hdl_t *)buf; - hdl->dma_handle = dma_handle; - hdl->acc_hdl = acc_hdl; - hdl->msgp = (void *)(buf + sizeof (i2o_msg_impl_hdl_t)); - - /* set the message size field in the message header */ - ddi_put16(hdl->acc_hdl, - &((i2o_message_frame_t *)(hdl->msgp))->MessageSize, - iop->ib_msg_frame_size >> 2); - - *msg_handlep = (i2o_msg_handle_t *)hdl; - *acc_handlep = acc_hdl; - *msgp = hdl->msgp; - - return (DDI_SUCCESS); -} - - -/* - * Send the I2O message to the IOP. - * - * Description: We need to do the following. - * 1. If the inbound message queue freelist is empty (i.e no - * valid mfa available) then queue up this request for - * the i2o_msg_send_process() thread and return DDI_SUCCESS. - * 2. We have a valid mfa. Copy the data from the system memory - * message buffer into the real message frame and send the - * message. - * 3. Free up the system memory message buffer. - * - * Note: - * For now, we return the system memory buffer back to the DDI - * framework. Fix this later to put the buffer into the local pool - * for better performance. - */ -int -i2o_msg_send(i2o_iop_handle_t iop_hdl, void *msg, i2o_msg_handle_t msg_hdl) -{ - uint32_t mfa; - iop_instance_t *iop = ((i2o_iop_impl_hdl_t *)iop_hdl)->iop; - i2o_msg_impl_hdl_t *hdl = (i2o_msg_impl_hdl_t *)msg_hdl; - i2o_message_frame_t *real_msgp; - size_t msg_size; - ddi_acc_handle_t acc_hdl; - ddi_dma_handle_t dma_handle; - - ASSERT(hdl->msgp == msg); - - mutex_enter(&iop->iop_ib_mutex); - - /* get a valid mfa from the inbound message freelist FIFO */ - - mfa = (* iop->nexus_trans->i2o_trans_msg_alloc) - (iop->nexus_trans->nexus_handle); - - if (mfa == (uint_t)0xFFFFFFFF) { - /* - * No valid MFA available. Queue up the request. - */ - if (iop->send_queue_head == NULL) { - iop->send_queue_head = iop->send_queue_tail = hdl; - hdl->next = NULL; - } else { - hdl->next = NULL; - iop->send_queue_tail->next = hdl; - iop->send_queue_tail = hdl; - } - - if (iop->iop_flags & IOP_SEND_QUEUE_PROC_RUNNING) - /* wakeup the i2o_msg_send_proc() */ - cv_broadcast(&iop->send_queue_cv); - else { - /* - * Create the i2o_msg_send_proc() thread and - * run it. - */ - cv_init(&iop->send_queue_cv, NULL, CV_DEFAULT, NULL); - (void) thread_create(NULL, 0, i2o_msg_send_proc, - iop, 0, &p0, TS_RUN, minclsyspri); - iop->iop_flags |= IOP_SEND_QUEUE_PROC_RUNNING; - } - - iop->send_queue_count++; - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, "i2o_msg_send: req queued")); - - mutex_exit(&iop->iop_ib_mutex); - - return (DDI_SUCCESS); - } - - mutex_exit(&iop->iop_ib_mutex); - - real_msgp = (i2o_message_frame_t *) - (mfa + iop->nexus_trans->iop_base_addr); - - /* - * Copy the message to the real message frame. - */ - msg_size = ddi_get16(hdl->acc_hdl, - &((i2o_message_frame_t *)msg)->MessageSize) << 2; - ASSERT(msg_size <= iop->ib_msg_frame_size); - bcopy(msg, (void *)real_msgp, msg_size); - - /* send the message to the IOP */ - (void) (* iop->nexus_trans->i2o_trans_msg_send) - (iop->nexus_trans->nexus_handle, - (caddr_t)(real_msgp) - iop->nexus_trans->iop_base_addr); - - /* - * Now, free up the system resources allocated for this message - */ - acc_hdl = hdl->acc_hdl; - dma_handle = hdl->dma_handle; - ddi_dma_mem_free(&acc_hdl); - ddi_dma_free_handle(&dma_handle); - - return (DDI_SUCCESS); -} - -/* - * Copy the LCT contents to the specified buffer. - */ -int -i2o_msg_get_lct(i2o_iop_handle_t iop_hdl, void *buf, size_t buf_size, - size_t *lct_sizep, size_t *real_sizep) -{ - iop_instance_t *iop = ((i2o_iop_impl_hdl_t *)iop_hdl)->iop; - size_t copy_size; - - mutex_enter(&iop->lct.lct_mutex); - - if (lct_sizep != NULL) - *lct_sizep = iop->lct.size; - - if (buf == NULL) - copy_size = 0; - else { - copy_size = min(buf_size, iop->lct.size); - bcopy((void *)iop->lct.bufp, buf, copy_size); - } - - if (real_sizep) - *real_sizep = copy_size; - - mutex_exit(&iop->lct.lct_mutex); - - return (DDI_SUCCESS); -} - -/* - * Process the reply message queue. This routine is called at the time of - * IOP hw interrupt. Current implementation is a simple while loop which - * reads the outbound postlist FIFO and if the MFA is a valid MFA - * (i.e MFA != 0xFFFFFFFF) then it calls the callback function in the - * InitiatorContext field of the message. - */ -void -i2o_msg_process_reply_queue(i2o_iop_handle_t handle) -{ - uint32_t mfa; - iop_instance_t *iop = ((i2o_iop_impl_hdl_t *)handle)->iop; - void (* initiator_context)(); - i2o_single_reply_message_frame_t *rmp; - - mutex_enter(&iop->iop_ob_mutex); - - mfa = (* iop->nexus_trans->i2o_trans_msg_recv) - (iop->nexus_trans->nexus_handle); - - /* - * WORKAROUND for i960 chip bug. It seems that sometimes the i960 - * is dropping the write request when IxWorks writes the MFA to - * the FIFO before generating the interrupt. As a workaround, IxWorks - * writes 0xFFFFFFFF first and then correct MFA. Two successive - * reads to the postlist FIFO should confirm if the FIFO is - * really empty. In the absence of reading the FIFO second time - * results in another call to IOP interrupt service routine. - * For better performance we do the second read of FIFO here. - */ - if (mfa == (uint_t)0xFFFFFFFF) { - /* read the FIFO again */ - mfa = (* iop->nexus_trans->i2o_trans_msg_recv) - (iop->nexus_trans->nexus_handle); - } - - while (mfa != (uint_t)0xFFFFFFFF) { - - rmp = (i2o_single_reply_message_frame_t *) - ((mfa - iop->ob_msg_queue.base_paddr) + - iop->ob_msg_queue.base_addr); - - initiator_context = (void (*)()) - (uintptr_t)ddi_get32(iop->ob_msg_queue.acc_hdl, - (uint32_t *)&rmp->StdMessageFrame.InitiatorContext); - - /* - * Check for NULL Initiator Context field. If it is NULL - * (should not happen) then ignore the message. - */ - if (initiator_context == NULL) { - cmn_err(CE_WARN, "I2O: No Initiator Context in the MSG" - " (Function: 0x%x Transaction Context: 0x%x" - " TID: 0x%x) - reply msg ignored", - get_msg_Function((i2o_message_frame_t *)rmp, - iop->ob_msg_queue.acc_hdl), - ddi_get32(iop->ob_msg_queue.acc_hdl, - (uint32_t *)&rmp->TransactionContext), - get_msg_TargetAddress((i2o_message_frame_t *)rmp, - iop->ob_msg_queue.acc_hdl)); - } else { - - /* - * We need to do the DMA sync for the message frame - * because the reply message buffers are allocated - * from the system memory and the IOP does DMA to - * write to this memory. - */ - (void) ddi_dma_sync(iop->ob_msg_queue.dma_handle, - (off_t)(mfa - iop->ob_msg_queue.base_paddr), - (size_t)iop->ob_msg_queue.framesize, - DDI_DMA_SYNC_FORCPU); - - /* - * Call the callback function of the OSM to process - * the message. - */ - (* initiator_context)((void *)rmp, - iop->ob_msg_queue.acc_hdl); - - } - - /* Now, putback the MFA into the outbound freelist FIFO */ - (* iop->nexus_trans->i2o_trans_msg_freebuf) - (iop->nexus_trans->nexus_handle, mfa); - - /* get the next MFA from the FIFO */ - mfa = (* iop->nexus_trans->i2o_trans_msg_recv) - (iop->nexus_trans->nexus_handle); - } - - mutex_exit(&iop->iop_ob_mutex); -} - -/* - * Process the I2O request message queue. The request messages are - * queued up for this IOP because there was no free mfa available - * from the inbound freelist. Currently, there is no mechanism - * where IOP can inform the host when the freelist is not empty. - * So, we just have to poll on the inbound message queue fifo until - * we find a valid frame. But, starvation on the inbound MFAs should - * not happen with the current implementations of IRTOS where the - * IRTOS copies the message into local buffer and puts the MFA back - * on the freelist immediately. So, this code may never get executed - * in practice! - * - */ -static void -i2o_msg_send_proc(iop_instance_t *iop) -{ - uint32_t mfa; - i2o_message_frame_t *real_msgp; - size_t msg_size; - ddi_acc_handle_t acc_hdl; - ddi_dma_handle_t dma_handle; - i2o_msg_impl_hdl_t *q; - - mutex_enter(&iop->iop_ib_mutex); - - for (;;) { - - q = iop->send_queue_head; /* head of the queue */ - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, "i2o_msg_send_proc: called")); - - while (q != NULL) { - - ASSERT((iop->iop_flags & IOP_IS_IN_UNINIT) != 0); - - /* - * get a valid mfa from the inbound message - * freelist FIFO - */ - - mfa = (* iop->nexus_trans->i2o_trans_msg_alloc) - (iop->nexus_trans->nexus_handle); - - if (mfa == (uint_t)0xFFFFFFFF) { - /* - * No valid MFA available. Wait for a while - * and try again. - */ - delay(1); - continue; /* try again */ - } - - real_msgp = (i2o_message_frame_t *) - (mfa + iop->nexus_trans->iop_base_addr); - - /* Copy the message to the real message frame */ - msg_size = 4 * ddi_get16(q->acc_hdl, - &((i2o_message_frame_t *)(q->msgp))->MessageSize); - ASSERT(msg_size <= iop->ib_msg_frame_size); - bcopy(q->msgp, (void *)real_msgp, msg_size); - - - /* send the message to the IOP */ - (void) (* iop->nexus_trans->i2o_trans_msg_send) - (iop->nexus_trans->nexus_handle, - (caddr_t)(real_msgp) - - iop->nexus_trans->iop_base_addr); - - /* free up the associated system resources */ - acc_hdl = q->acc_hdl; - dma_handle = q->dma_handle; - q = q->next; - ddi_dma_mem_free(&acc_hdl); - ddi_dma_free_handle(&dma_handle); - } - - iop->send_queue_head = NULL; - iop->send_queue_tail = NULL; - - /* if the IOP is being uninitialized then exit */ - - if (iop->iop_flags & IOP_IS_IN_UNINIT) { - iop->iop_flags &= ~IOP_SEND_QUEUE_PROC_RUNNING; - - thread_exit(); - - DEBUGF(I2O_DEBUG_DEBUG, (CE_CONT, - "i2o_msg_send_proc: exit...")); - } - - /* otherwise, wait for the wakeup call from i2o_msg_send() */ - cv_wait(&iop->send_queue_cv, &iop->iop_ib_mutex); - } -} - -/* - * ************************************************************************ - * *** Functions used for Debugging only *** - * ************************************************************************ - */ - -#ifdef I2O_DEBUG - -static void -dump_iop_status_buf(iop_instance_t *iop) -{ - int i; - uint32_t *p = (uint32_t *)iop->status.bufp; - - cmn_err(CE_CONT, "?IOP Status Block: "); - for (i = 0; i < sizeof (i2o_exec_status_get_reply_t); i += 4) - cmn_err(CE_CONT, "0x%x", *p++); - cmn_err(CE_CONT, - "?\tOrganizationID: %x\n", ddi_get16(iop->status.acc_hdl, - &iop->status.bufp->OrganizationID)); - cmn_err(CE_CONT, "?\tIOP_ID: %x\n", - get_i2o_exec_status_reply_IOP_ID(iop->status.bufp, - iop->status.acc_hdl)); - cmn_err(CE_CONT, "?\tHostUnitID: %x\n", ddi_get16(iop->status.acc_hdl, - &iop->status.bufp->HostUnitID)); - cmn_err(CE_CONT, "?\tI2oVersion: %x\n", - get_i2o_exec_status_reply_I2oVersion(iop->status.bufp, - iop->status.acc_hdl)); - cmn_err(CE_CONT, "?\tSegmentNumber: %x\n", - get_i2o_exec_status_reply_SegmentNumber(iop->status.bufp, - iop->status.acc_hdl)); - cmn_err(CE_CONT, "?\tIopState: %x\n", ddi_get8(iop->status.acc_hdl, - &iop->status.bufp->IopState)); - cmn_err(CE_CONT, "?\tMessengerType: %x\n", ddi_get8(iop->status.acc_hdl, - &iop->status.bufp->MessengerType)); - cmn_err(CE_CONT, - "?\tInboundMFrameSize: %x\n", ddi_get16(iop->status.acc_hdl, - &iop->status.bufp->InboundMFrameSize)); - cmn_err(CE_CONT, "?\tInitCode: %x\n", ddi_get8(iop->status.acc_hdl, - &iop->status.bufp->InitCode)); - cmn_err(CE_CONT, - "?\tMaxInboundMFrames: %x\n", ddi_get32(iop->status.acc_hdl, - &iop->status.bufp->MaxInboundMFrames)); - cmn_err(CE_CONT, - "?\tCurrentInboundMFrames: %x\n", ddi_get32(iop->status.acc_hdl, - &iop->status.bufp->CurrentInboundMFrames)); - cmn_err(CE_CONT, - "?\tMaxOutboundMFrames: %x\n", ddi_get32(iop->status.acc_hdl, - &iop->status.bufp->MaxOutboundMFrames)); - cmn_err(CE_CONT, - "?\tProductIDString: %s\n", iop->status.bufp->ProductIDString); - cmn_err(CE_CONT, - "?\tExpectedLCTSize: %x\n", ddi_get32(iop->status.acc_hdl, - &iop->status.bufp->ExpectedLCTSize)); - cmn_err(CE_CONT, - "?\tIopCapabilities: %x\n", ddi_get32(iop->status.acc_hdl, - &iop->status.bufp->IopCapabilities)); - cmn_err(CE_CONT, - "?\tDesiredPrivateMemSize: %x\n", ddi_get32(iop->status.acc_hdl, - &iop->status.bufp->DesiredPrivateMemSize)); - cmn_err(CE_CONT, - "?\tCurrentPrivateMemSize: %x\n", ddi_get32(iop->status.acc_hdl, - &iop->status.bufp->CurrentPrivateMemSize)); - cmn_err(CE_CONT, - "?\tCurrentPrivateMemBase: %x\n", ddi_get32(iop->status.acc_hdl, - &iop->status.bufp->CurrentPrivateMemBase)); - cmn_err(CE_CONT, - "?\tDesiredPrivateIOSize: %x\n", ddi_get32(iop->status.acc_hdl, - &iop->status.bufp->DesiredPrivateIOSize)); - cmn_err(CE_CONT, - "?\tCurrentPrivateIOSize: %x\n", ddi_get32(iop->status.acc_hdl, - &iop->status.bufp->CurrentPrivateIOSize)); - cmn_err(CE_CONT, - "?\tCurrentPrivateIOBase: %x\n", ddi_get32(iop->status.acc_hdl, - &iop->status.bufp->CurrentPrivateIOBase)); -} - -static void -dump_hrt(iop_instance_t *iop) -{ - int i, n; - i2o_hrt_entry_t *entp; - uint32_t *p; - - n = ddi_get16(iop->hrt.acc_hdl, &iop->hrt.bufp->NumberEntries); - - entp = &iop->hrt.bufp->HRTEntry[0]; - - cmn_err(CE_CONT, - "?Hardware Resource Table (IOP_ID %x HRTVersion %x #ent %x):\n", - iop->iop_id, iop->hrt.bufp->HRTVersion, n); - - for (i = 0; i < n; i++, entp++) { - - p = (uint32_t *)entp; - - if (get_hrt_entry_AdapterState(entp, iop->hrt.acc_hdl) == 0) - continue; - - cmn_err(CE_CONT, "0x%x 0x%x 0x%x 0x%x", p[0], p[1], - p[2], p[3]); - cmn_err(CE_CONT, - "?\tAdapterID: %x\n", ddi_get32(iop->hrt.acc_hdl, - &entp->AdapterID)); - cmn_err(CE_CONT, "?\tControllingTID: %x\n", - get_hrt_entry_ControllingTID(entp, iop->hrt.acc_hdl)); - cmn_err(CE_CONT, "?\tAdapterState: %x\n", - get_hrt_entry_AdapterState(entp, iop->hrt.acc_hdl)); - cmn_err(CE_CONT, "?\tBusType: %x\n", entp->BusType); - cmn_err(CE_CONT, "?\tBusNumber: %x\n", entp->BusNumber); - - switch (entp->BusType) { - case I2O_PCI_BUS: - cmn_err(CE_CONT, "?\t\tPciFunctionNumber: %x", - entp->uBus.PCIBus.PciFunctionNumber); - cmn_err(CE_CONT, "?\t\tPciDeviceNumber: %x", - entp->uBus.PCIBus.PciDeviceNumber); - cmn_err(CE_CONT, "?\t\tPciBusNumber: %x", - entp->uBus.PCIBus.PciBusNumber); - cmn_err(CE_CONT, "?\t\tPciVendorID: %x", - entp->uBus.PCIBus.PciVendorID); - cmn_err(CE_CONT, "?\t\tPciDeviceID: %x", - entp->uBus.PCIBus.PciDeviceID); - break; - default: - break; - } - } -} - - -static void -dump_lct(iop_instance_t *iop) -{ - int i, j, n; - i2o_lct_entry_t *entp; - - n = (ddi_get16(iop->lct.acc_hdl, &iop->lct.bufp->TableSize) * 4) / - sizeof (i2o_lct_entry_t); - entp = &iop->lct.bufp->LCTEntry[0]; - - cmn_err(CE_CONT, "?Logical Config Table (IopFlags %x LctVer %x)\n", - ddi_get32(iop->lct.acc_hdl, &iop->lct.bufp->IopFlags), - get_lct_LctVer(iop->lct.bufp, iop->lct.acc_hdl)); - - for (i = 0; i < n; i++) { - cmn_err(CE_CONT, "?\tLocalTID: %x\n", - get_lct_entry_LocalTID(entp, iop->lct.acc_hdl)); - cmn_err(CE_CONT, "?\tDeviceFlags: %x\n", - ddi_get32(iop->lct.acc_hdl, &entp->DeviceFlags)); - cmn_err(CE_CONT, "?\tChangeIndicator: %x\n", - ddi_get32(iop->lct.acc_hdl, &entp->ChangeIndicator)); - cmn_err(CE_CONT, "?\tClass: %x\n", - get_lct_entry_Class(entp, iop->lct.acc_hdl)); - cmn_err(CE_CONT, "?\tVersion: %x\n", - get_lct_entry_Version(entp, iop->lct.acc_hdl)); - cmn_err(CE_CONT, "?\tOrganizationID: %x\n", - get_lct_entry_OrganizationID(entp, iop->lct.acc_hdl)); - cmn_err(CE_CONT, "?\tSubClassInfo: %x\n", - ddi_get32(iop->lct.acc_hdl, &entp->SubClassInfo)); - cmn_err(CE_CONT, "?\tBiosInfo: %x\n", - get_lct_entry_BiosInfo(entp, iop->lct.acc_hdl)); - cmn_err(CE_CONT, "?\tParentTID: %x\n", - get_lct_entry_ParentTID(entp, iop->lct.acc_hdl)); - cmn_err(CE_CONT, "?\tUserTID: %x\n", - get_lct_entry_UserTID(entp, iop->lct.acc_hdl)); - cmn_err(CE_CONT, "?\tEventCapabilities: %x\n", - ddi_get32(iop->lct.acc_hdl, &entp->EventCapabilities)); - cmn_err(CE_CONT, "?\tIdentityTag: "); - for (j = 0; j < 8; j++) - cmn_err(CE_CONT, "?\t%x ", entp->IdentityTag[j]); - cmn_err(CE_CONT, "?\n"); - - entp++; - } -} - - -static void -dump_message(uint32_t *mp, char *name) -{ - cmn_err(CE_CONT, "%s: MSGHDR(%p): %x %x %x %x", name, (void *)mp, mp[0], - mp[1], mp[2], mp[3]); - cmn_err(CE_CONT, "PAYLOAD(%p): %x %x %x %x %x %x", - (void *)&mp[4], mp[4], mp[5], mp[6], mp[7], mp[8], mp[9]); -} - -static void -dump_reply_message(iop_instance_t *iop, i2o_single_reply_message_frame_t *rmp) -{ - if (rmp == NULL) - return; - - cmn_err(CE_CONT, - "?Reply Message Frame (IOP %x Function %x):", iop->iop_id, - get_msg_Function(&rmp->StdMessageFrame, iop->ob_msg_queue.acc_hdl)); - cmn_err(CE_CONT, - "?\tReqStatus: %x DetailedStatusCode %x\n", rmp->ReqStatus, - ddi_get16(iop->ob_msg_queue.acc_hdl, &rmp->DetailedStatusCode)); -} - -#endif - - - -static uint_t -i2o_get_mem(dev_info_t *dip, uint_t len, uint_t *base) -{ - ndi_ra_request_t req; - uint64_t retlen; - uint64_t retbase; -#ifdef lint - dip = dip; -#endif - - bzero((caddr_t)&req, sizeof (req)); - - req.ra_addr = (uint64_t)*base; - if (*base != 0) - req.ra_flags |= NDI_RA_ALLOC_SPECIFIED; - req.ra_len = (uint64_t)len; - req.ra_boundbase = 0; - req.ra_boundlen = 0xffffffffUL; - req.ra_flags |= NDI_RA_ALLOC_BOUNDED; - - if (ndi_ra_alloc(ddi_root_node(), &req, &retbase, &retlen, - NDI_RA_TYPE_MEM, 0) == NDI_FAILURE) { - *base = 0; - return (0); - } else { - *base = retbase; - return (*base); - } -} - - -static void -i2o_return_mem(dev_info_t *dip, uint_t base, uint_t len) -{ -#ifdef lint - dip = dip; -#endif - (void) ndi_ra_free(ddi_root_node(), (uint64_t)base, (uint64_t)len, - NDI_RA_TYPE_MEM, 0); -} - - -static uint_t -i2o_get_io(dev_info_t *dip, uint_t len, uint_t *base) -{ - ndi_ra_request_t req; - uint64_t retbase, retlen; - -#ifdef lint - dip = dip; -#endif - bzero((caddr_t)&req, sizeof (req)); - if (*base != 0) - req.ra_flags |= NDI_RA_ALLOC_SPECIFIED; - req.ra_flags |= NDI_RA_ALIGN_SIZE; - req.ra_addr = (uint64_t)*base; - req.ra_boundbase = 0; - req.ra_boundlen = 0xffffffffUL; - req.ra_flags |= NDI_RA_ALLOC_BOUNDED; - req.ra_len = (uint64_t)len; - if (ndi_ra_alloc(ddi_root_node(), &req, &retbase, &retlen, - NDI_RA_TYPE_IO, 0) == NDI_FAILURE) { - *base = 0; - return (0); - } else { - *base = retbase; - return (*base); - } -} - -static void -i2o_return_io(dev_info_t *dip, uint_t base, uint_t len) -{ -#ifdef lint - dip = dip; -#endif - (void) ndi_ra_free(ddi_root_node(), (uint64_t)base, (uint64_t)len, - NDI_RA_TYPE_IO, 0); -}
--- a/usr/src/uts/common/io/i2o/i2o_scsi.c Wed Apr 18 03:07:55 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4440 +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 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - - -/* - * I2O SCSI HBA OSM - * - * I2O Scsi Host Bus Adapter Operating System Module (OSM) - * conforms to I2O and converts SCSI pkt information send by - * the target driver through SCSA to I2O message format and send it - * down to the IOP. This driver utilized the I2O messaging framework, - * i2o_msg. Currently only support on x86. - * - */ - -/* - * debugging code - */ -#ifdef DEBUG -#define I2OHBA_DEBUG -#endif - -#ifdef I2OHBA_DEBUG -int i2ohbadebugflag = 0; -int ddi_dma_alloc_hdl = 0; -int ddi_dma_alloc_mem = 0; -int ddi_dma_bind_hdl = 0; -int ddi_dma_unbind = 0; -int ddi_dma_free_mem = 0; -int ddi_dma_bind_free = 0; -int ddi_dma_bufalloc = 0; -int ddi_dma_buf_bind = 0; -int ddi_dma_buf_unbind = 0; -int ddi_dma_buf_free_hdl = 0; -#define DEBUGF(level, args) \ - { if (i2ohbadebugflag >= (level)) cmn_err args; } -#else -#define DEBUGF(leve, args) /* nothing */ -#endif - -#include <sys/types.h> -#include <sys/conf.h> -#include <sys/varargs.h> -#include <sys/modctl.h> -#include <sys/scsi/scsi.h> -#include <sys/scsi/scsi_ctl.h> -#include <sys/scsi/impl/scsi_reset_notify.h> - -#include <sys/i2o/i2obscsi.h> -#include <sys/i2o/i2oadptr.h> -#include <sys/i2o/i2omsg.h> -#include <sys/i2o/i2outil.h> - -#include "i2o_scsi_var.h" -#include "i2o_scsi_util.h" -#include "i2o_scsi_cmd.h" - -/* - * dev_ops functions prototypes - */ -static int i2ohba_info(dev_info_t *dip, ddi_info_cmd_t infocmd, - void *arg, void **result); -static int i2ohba_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); -static int i2ohba_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); - -/* - * Function prototypes - * - * SCSA functions exported by means of the transport table - */ -static int i2ohba_tran_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, - scsi_hba_tran_t *tran, struct scsi_device *sd); -static int i2ohba_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt); -static int i2ohba_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt); -static int i2ohba_scsi_reset(struct scsi_address *ap, int level); -static int i2ohba_scsi_getcap(struct scsi_address *ap, char *cap, int whom); -static int i2ohba_scsi_setcap(struct scsi_address *ap, char *cap, int value, - int whom); -static struct scsi_pkt *i2ohba_scsi_init_pkt(struct scsi_address *ap, - struct scsi_pkt *pkt, struct buf *bp, int cmdlen, int statuslen, - int tgtlen, int flags, int (*callback)(), caddr_t arg); -static void i2ohba_scsi_destroy_pkt(struct scsi_address *ap, - struct scsi_pkt *pkt); -static void i2ohba_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt); -static void i2ohba_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt); -static int i2ohba_scsi_reset_notify(struct scsi_address *ap, int flag, - void (*callback)(caddr_t), caddr_t arg); - -/* - * i2ohba's complete function for sending the SCSI pkt. - */ -static void i2ohba_callback(i2o_message_frame_t *msg, ddi_acc_handle_t - acc_handle); - - -/* - * Internal Functions - */ -/* tid map to scsi convertion function */ -static int i2ohba_i_tid_to_scsi(dev_info_t *dip, struct i2ohba *i2ohba, - i2o_lct_t *lct_buf, size_t lct_real_size, - ddi_acc_handle_t lctbuf_dmaacchandle); - -/* capability/prop functions */ -static void i2ohba_i_updatesync(struct i2ohba *i2ohba, int tgt); -static void i2ohba_i_update_props(struct i2ohba *i2ohba, int tgt); -static void i2ohba_i_update_this_prop(struct i2ohba *i2ohba, char *property, - int value); -static void i2ohba_i_initcap(struct i2ohba *i2ohba); - -/* dma engine funcitons */ -static int i2ohba_i_dma_alloc(struct i2ohba *i2ohba, struct scsi_pkt *pkt, - struct buf *bp, int flags, int (*callback)()); -static int i2ohba_i_dma_move(struct i2ohba *i2ohba, struct scsi_pkt *pkt, - struct buf *bp); - -/* timer and recovery functions */ -static void i2ohba_i_watch(void *); -static void i2ohba_i_fatal_error(struct i2ohba *i2ohba); -static int i2ohba_i_reset_interface(struct i2ohba *i2ohba, int action); -static int i2ohba_i_reset_abort(struct i2ohba *i2ohba, uint16_t tid, int action, - struct i2ohba_cmd *cmd); - -/* command processing functions */ -static void i2ohba_i_polled_cmd_start(struct i2ohba *i2ohba, - struct i2ohba_cmd *sp); -static void i2ohba_i_req_insert(struct i2ohba *i2ohba, struct i2ohba_cmd *sp); -static void i2ohba_i_req_remove(struct i2ohba *i2ohba, struct i2ohba_cmd *sp); -static void i2ohba_i_pkt_comp(i2o_single_reply_message_frame_t *reply, - ddi_acc_handle_t acc_handle, struct i2ohba_cmd *sp); -static void i2ohba_i_handle_arq(i2o_scsi_error_reply_message_frame_t *replyerr, - struct i2ohba_cmd *sp, int aqcount); -static void i2ohba_i_qflush(struct i2ohba *i2ohba, uint16_t start_tgt, - uint16_t end_tgt); -/*PRINTFLIKE3*/ -static void i2ohba_i_log(struct i2ohba *i2ohba, int level, char *fmt, ...); -static void i2ohba_i_print_state(struct i2ohba *i2ohba); - -/* utility parameter functions */ -static int i2ohba_utilparamset_msg(struct i2ohba *i2ohba, int tgt, - uint16_t tid, uint16_t group, uint16_t idx, uint16_t value); -static int i2ohba_utilparamget_msg(struct i2ohba *i2ohba, uint16_t tidx, - char flag); -static void i2ohba_utilmsg_comp(i2o_message_frame_t *msg, ddi_acc_handle_t - acc_handle); -static int i2ohba_utilclaim_msg(struct i2ohba *i2ohba, uint16_t tid, - int action); - -/* - * mutex for protecting variables shared by all instances of the driver - */ -static kmutex_t i2ohba_log_mutex; - -/* - * Local static data - */ -static void *i2ohba_state = NULL; -static clock_t i2ohba_tick; /* watch interval in HZ */ -static clock_t i2ohba_watchdog_tick = 15; /* watch interval in sec */ -static int i2ohba_scsi_reset_delay = 3000; -ddi_device_acc_attr_t dev_attr; /* dev_attr */ -static char i2ohba_log_buf[256]; /* buffer used in i2ohba_i_log */ - - - -/* - * DMA Attribute for data buffers - */ -static ddi_dma_attr_t i2ohba_dma_attr = { - DMA_ATTR_VERSION, /* dma_attr_version */ - 0, /* dma_attr_addr_lo */ - 0xffffffffull, /* dma_attr_addr_hi */ - 0x00ffffffull, /* dma_attr_count_max */ - 1, /* dma_attr_align */ - 1, /* dma_attr_burstsizes */ - 1, /* dma_attr_minxfer */ - 0xffffffffull, /* dma_attr_maxxfer */ - 0x00ffffffull, /* dma_attr_seg */ - I2OHBA_CMD_NSEGS, /* dma_attr_sgllen */ - 512, /* dma_attr_granular */ - 0 /* dma_attr_flags */ -}; - -/* - * DMA attributes for SGL buffer - */ -static ddi_dma_attr_t i2ohba_dmasgl_attr = { - DMA_ATTR_VERSION, /* dma_attr_version */ - 0, /* dma_attr_addr_lo */ - 0xffffffffull, /* dma_attr_addr_hi */ - 0x00ffffffull, /* dma_attr_count_max */ - 1, /* dma_attr_align */ - 1, /* dma_attr_burstsizes */ - 1, /* dma_attr_minxfer */ - 0xffffffffull, /* dma_attr_maxxfer */ - 0x00ffffffull, /* dma_attr_seg */ - 0x1, /* dma_attr_sgllen */ - 1, /* dma_attr_granular */ - 0 /* dma_attr_flags */ -}; - -/* - * Hotplug support - * Leaf ops (hotplug controls for target devices) - * XXXLWXXX currently doesn't support any hotpluging - */ - -static struct cb_ops i2ohba_cb_ops = { - nodev, /* open */ - nodev, /* close */ - nodev, /* strategy */ - nodev, /* print */ - nodev, /* dump */ - nodev, /* read */ - nodev, /* write */ - nodev, /* ioctl */ - nodev, /* devmap */ - nodev, /* mmap */ - nodev, /* segmap */ - nochpoll, /* poll */ - ddi_prop_op, /* prop_op */ - NULL, - D_NEW | D_MP | D_HOTPLUG -}; - -/* - * autoconfiguration routines. - */ - -static struct dev_ops i2ohba_ops = { - DEVO_REV, /* rev, */ - 0, /* refcnt */ - i2ohba_info, /* getinfo */ - nulldev, /* identify */ - nulldev, /* probe */ - i2ohba_attach, /* attach */ - i2ohba_detach, /* detach */ - nodev, /* reset */ - &i2ohba_cb_ops, /* driver operations */ - NULL, /* bus ops */ - NULL /* power ops */ -}; - -char _depends_on[] = "misc/scsi misc/i2o_msg"; - -static struct modldrv modldrv = { - &mod_driverops, /* Type of module */ - "I2O SCSI HBA OSM version %I%", /* module name */ - &i2ohba_ops, /* driver ops */ - -}; - -static struct modlinkage modlinkage = { - MODREV_1, - (void *)&modldrv, - NULL -}; - -int -_init(void) -{ - int ret; - - ret = ddi_soft_state_init(&i2ohba_state, sizeof (struct i2ohba), - I2OHBA_INITIAL_SOFT_SPACE); - - if (ret != 0) - return (ret); - - mutex_init(&i2ohba_log_mutex, NULL, MUTEX_DRIVER, NULL); - - i2ohba_tick = drv_usectohz(i2ohba_watchdog_tick * 1000000); - - if ((ret = scsi_hba_init(&modlinkage)) != 0) { - mutex_destroy(&i2ohba_log_mutex); - ddi_soft_state_fini(&i2ohba_state); - return (ret); - } - - if ((ret = mod_install(&modlinkage)) != 0) { - scsi_hba_fini(&modlinkage); - mutex_destroy(&i2ohba_log_mutex); - ddi_soft_state_fini(&i2ohba_state); - } - - return (ret); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} - -int -_fini(void) -{ - - int ret; - - if ((ret = mod_remove(&modlinkage)) != 0) - return (ret); - - scsi_hba_fini(&modlinkage); - - mutex_destroy(&i2ohba_log_mutex); - ddi_soft_state_fini(&i2ohba_state); - - return (ret); -} - -/* - * Given the device number return the devinfo pointer - * from the scsi_device structure. - */ -/*ARGSUSED*/ -static int -i2ohba_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) -{ - return (DDI_FAILURE); -} - - -/* - * Attach an instance of an i2o hba OSM module. Allocate data structures, - * initialize the OSM and send commands to IOP to bring I2O on line. - */ -/*ARGSUSED*/ -static int -i2ohba_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) -{ - scsi_hba_tran_t *tran = NULL; - char prop_str[32]; - int i, id, tid2scsi; - int freecount = 0; - int ishdlalloc = 0; - struct i2ohba *i2ohba; - int instance; - size_t lct_size, lct_real_size, lct_rlen; - i2o_lct_t *lct_buf; - ddi_dma_handle_t lctbuf_dmahandle; - ddi_acc_handle_t lctbuf_dmaacchandle; - - instance = ddi_get_instance(dip); - - switch (cmd) { - case DDI_ATTACH: - dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; - dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; - /* currently for x86 PCI, we'll use little endian */ - dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; - break; - - /* XXXLWXXX will work on it more */ - case DDI_RESUME: - case DDI_PM_RESUME: - - default: - i2ohba_i_log(NULL, CE_WARN, "?i2ohba_attach%d: " - "cmd != DDI_ATTACH", instance); - return (DDI_FAILURE); - } - - /* - * I2O comes in at intr level 5 - */ - if (ddi_intr_hilevel(dip, 0) != 0) { - i2ohba_i_log(NULL, CE_WARN, "?i2ohba_attach%d: high-level " - "interrupt not supported", instance); - return (DDI_FAILURE); - } - - /* - * Allocate i2ohba data structure. - */ - if (ddi_soft_state_zalloc(i2ohba_state, instance) != DDI_SUCCESS) { - i2ohba_i_log(NULL, CE_WARN, "?i2ohba%d: Failed to alloc" - " soft state", instance); - return (DDI_FAILURE); - } - - i2ohba = ddi_get_soft_state(i2ohba_state, instance); - - if (i2ohba == (struct i2ohba *)NULL) { - i2ohba_i_log(NULL, CE_WARN, "?i2ohba%d: Bad soft state", - instance); - ddi_soft_state_free(i2ohba_state, instance); - return (DDI_FAILURE); - } - - /* - * save the dip info - */ - i2ohba->i2ohba_dip = dip; - - /* - * register OSM with message layer - */ - if (i2o_msg_osm_register(dip, &i2ohba->i2ohba_iophdl) - != DDI_SUCCESS) { - i2ohba_i_log(NULL, CE_WARN, "?i2ohba%d: Registeration Fail " - "with IOP", instance); - goto cleanup; - } - - /* - * get the LCT from iop - */ - if (i2o_msg_get_lct(i2ohba->i2ohba_iophdl, NULL, NULL, - &lct_size, NULL) != DDI_SUCCESS) { - i2ohba_i_log(NULL, CE_WARN, "?i2ohba%d: Can't get LCT SIZE " - "info from IOP", instance); - goto cleanup; - } - -retry: - /* - * first get the size from IOP, then - * DMA Allocate it. - */ - if (lct_size) { - if (!ishdlalloc) { - if (ddi_dma_alloc_handle(dip, &i2ohba_dmasgl_attr, - DDI_DMA_SLEEP, NULL, &lctbuf_dmahandle) != - DDI_SUCCESS) - goto cleanup; - } - ishdlalloc = 1; -#ifdef I2OHBA_DEBUG - ddi_dma_alloc_hdl++; -#endif - if (ddi_dma_mem_alloc(lctbuf_dmahandle, (size_t) - lct_size, &dev_attr, DDI_DMA_STREAMING, - DDI_DMA_SLEEP, NULL, (caddr_t *)&lct_buf, &lct_rlen, - &lctbuf_dmaacchandle) != DDI_SUCCESS) - goto cleanup; -#ifdef I2OHBA_DEBUG - ddi_dma_alloc_mem++; -#endif - freecount = 1; - - } else { - i2ohba_i_log(NULL, CE_WARN, "?i2ohba%d: Invalid LCT size", - instance); - goto cleanup; - } - - /* - * with the right size buffer, now get the table - */ - if (i2o_msg_get_lct(i2ohba->i2ohba_iophdl, lct_buf, lct_size, - NULL, &lct_real_size) != DDI_SUCCESS) { - i2ohba_i_log(NULL, CE_WARN, "?i2ohba%d: Getting LCT table " - "info failed", instance); - goto cleanup; - } - - /* - * partial transfer - */ - if (lct_real_size > lct_size) { - ddi_dma_mem_free(&lctbuf_dmaacchandle); -#ifdef I2OHBA_DEBUG - ddi_dma_free_mem++; -#endif - lct_size = lct_real_size; - goto retry; - } - - /* - * Set up TID->SCSI info map, query all unclaimed SCSI devices - */ - if (tid2scsi = i2ohba_i_tid_to_scsi(dip, i2ohba, lct_buf, - lct_real_size, lctbuf_dmaacchandle)) { - i2ohba_i_log(NULL, CE_WARN, "?i2ohba%d: Setup TID to SCSI " - "info map failed", instance); - goto cleanup; - } - - /* free dma, may be XXLWXX we can keep it for later LCT update */ - freecount = 0; - ddi_dma_mem_free(&lctbuf_dmaacchandle); -#ifdef I2OHBA_DEBUG - ddi_dma_free_mem++; -#endif - ishdlalloc = 0; - ddi_dma_free_handle(&lctbuf_dmahandle); -#ifdef I2OHBA_DEBUG - ddi_dma_bind_free++; -#endif - - /* - * Allocate a transport structure - */ - tran = scsi_hba_tran_alloc(dip, SCSI_HBA_CANSLEEP); - - i2ohba->i2ohba_tran = tran; - i2ohba->i2ohba_dip = dip; - - tran->tran_hba_private = i2ohba; - tran->tran_tgt_private = NULL; - tran->tran_tgt_init = i2ohba_tran_tgt_init; - tran->tran_tgt_probe = (int (*)())scsi_hba_probe; - tran->tran_tgt_free = (void (*)())NULL; - - tran->tran_start = i2ohba_scsi_start; - tran->tran_abort = i2ohba_scsi_abort; - tran->tran_reset = i2ohba_scsi_reset; - tran->tran_getcap = i2ohba_scsi_getcap; - tran->tran_setcap = i2ohba_scsi_setcap; - tran->tran_init_pkt = i2ohba_scsi_init_pkt; - tran->tran_destroy_pkt = i2ohba_scsi_destroy_pkt; - tran->tran_dmafree = i2ohba_scsi_dmafree; - tran->tran_sync_pkt = i2ohba_scsi_sync_pkt; - tran->tran_reset_notify = i2ohba_scsi_reset_notify; - tran->tran_get_bus_addr = NULL; - tran->tran_get_name = NULL; - - - /* - * Attach this instance of the hba - */ - if (scsi_hba_attach_setup(dip, &i2ohba_dma_attr, tran, - 0) != DDI_SUCCESS) { - i2ohba_i_log(NULL, CE_WARN, "?scsi_hba_attach failed"); - goto cleanup; - } - - /* - * find scsi host id property - */ - id = ddi_getprop(DDI_DEV_T_ANY, dip, 0, - "scsi-initiator-id", -1); - if (id != scsi_host_id && - (id >= 0 && id < N_I2OHBA_TARGETS_WIDE)) { - i2ohba->i2ohba_initiator_id = (uint8_t)id; - } else { - i2ohba->i2ohba_initiator_id = (uint8_t)scsi_host_id; - } - - /* - * property: look up the scsi-options property - */ - i2ohba->i2ohba_scsi_options = - ddi_getprop(DDI_DEV_T_ANY, dip, 0, "scsi-options", - I2OHBA_DEFAULT_SCSI_OPTIONS); - - /* - * property: if target<n>-scsi-options property exists, use it; - * otherwise use the i2o_scsi_options - */ - for (i = 0; i < N_I2OHBA_TARGETS_WIDE; i++) { - (void) sprintf(prop_str, "target%x-scsi-options", i); - i2ohba->i2ohba_target_scsi_option[i] = ddi_getprop( - DDI_DEV_T_ANY, dip, 0, prop_str, - i2ohba->i2ohba_scsi_options); - - if (i2ohba->i2ohba_target_scsi_option[i] != - i2ohba->i2ohba_scsi_options) { - i2ohba_i_log(NULL, CE_CONT, - "?i2ohba:target%x-scsi-options=0x%x", - i, i2ohba->i2ohba_target_scsi_option[i]); - } - } - - - i2ohba->i2ohba_scsi_reset_delay = - ddi_getprop(DDI_DEV_T_ANY, dip, 0, "scsi-reset-delay", - i2ohba_scsi_reset_delay); - - if (i2ohba->i2ohba_scsi_reset_delay != i2ohba_scsi_reset_delay) { - i2ohba_i_log(NULL, CE_CONT, - "?i2ohba_scsi-reset-delay=%d", - i2ohba->i2ohba_scsi_reset_delay); - } - - - - /* - * set up watchdog for this i2o - */ - i2ohba->i2ohba_timeout_id = timeout(i2ohba_i_watch, (caddr_t)i2ohba, - i2ohba_tick); - - /* - * initialized I2OHBA request mutex and reset mutex - */ - mutex_init(I2OHBA_REQ_MUTEX(i2ohba), NULL, MUTEX_DRIVER, NULL); - mutex_init(I2OHBA_RESET_MUTEX(i2ohba), NULL, MUTEX_DRIVER, NULL); - cv_init(I2OHBA_RESET_CV(i2ohba), NULL, CV_DRIVER, NULL); - - I2OHBA_MUTEX_ENTER(i2ohba); - /* - * Initialize the default Target Capabilites and Sync Rates - */ - (void) i2ohba_i_initcap(i2ohba); - - /* - * reset i2ohba/bus and initialize capabilities - * if (i2ohba_i_reset_interface(i2ohba, I2OHBA_FORCE_BUS_RESET)) { - * goto cleanup; - * } - */ - I2OHBA_MUTEX_EXIT(i2ohba); - - ddi_report_dev(dip); - i2ohba->i2ohba_throttle = 0; - - DEBUGF(1, (CE_CONT, "i2ohba_attach%d: Succeeded", instance)); - - return (DDI_SUCCESS); - -cleanup: - DEBUGF(1, (CE_CONT, "?i2ohba_attach%d: Unable to attach", instance)); - - if (tid2scsi) { - i2o_tid_scsi_ent_t *map = i2ohba->i2ohba_tid_scsi_map; - - /* - * if tid_to_scsi has succeeded, then at least - * we have the HBA node claimed. - */ - (void) i2ohba_utilclaim_msg(i2ohba, i2ohba->i2ohba_tid, - I2O_UTIL_CLAIM_RELEASE); - - DEBUGF(1, (CE_CONT, "?Utilunclaim %d", i2ohba->i2ohba_tid)); - - for (i = 0; i < N_I2OHBA_TARGETS_WIDE; i++) { - if (map[i].tid != 0) - (void) i2ohba_utilclaim_msg(i2ohba, - map[i].tid, - I2O_UTIL_CLAIM_RELEASE); - } - - } - - if (freecount) { - ddi_dma_mem_free(&lctbuf_dmaacchandle); - } - if (ishdlalloc) { - ddi_dma_free_handle(&lctbuf_dmahandle); - } - - if (i2ohba->i2ohba_timeout_id != 0) { - i2ohba->i2ohba_shutdown = 1; - (void) untimeout(i2ohba->i2ohba_timeout_id); - i2ohba->i2ohba_timeout_id = 0; - } - - if (tran) { - scsi_hba_tran_free(tran); - } - - if (i2ohba->i2ohba_iophdl) - i2o_msg_osm_unregister(&i2ohba->i2ohba_iophdl); - - ddi_soft_state_free(i2ohba_state, instance); - - return (DDI_FAILURE); -} - -/* - * Function name: i2ohba_i_tid_to_scsi - * - * Return Values: -1 Failed - * 0 Success - * - * Description : Take in the LCT (logical configuration table), and - * parse it through to find the appropriated SCSI target - * devices that belongs to this HBA. Then send a - * I2O_UTIL_PARAM_GET message to the target device to - * to get its parameters, ie SCSI ID and build a - * tid-to-scsi.id map. - */ -/*ARGSUSED*/ -static int -i2ohba_i_tid_to_scsi(dev_info_t *dip, struct i2ohba *i2ohba, - i2o_lct_t *lct_buf, size_t lct_real_size, - ddi_acc_handle_t lctbuf_dmaacchandle) -{ - i2o_tid_scsi_ent_t *map = i2ohba->i2ohba_tid_scsi_map; - uint_t tablesize, actualtbl; - i2o_lct_entry_t *lctentptr; - int i, count, entries = 0, rval = -1; - - /* - * translating dev_addr field in the dev_info struct to TID - */ - - i2ohba->i2ohba_tid = ddi_getprop(DDI_DEV_T_ANY, dip, 0, - "i2o-device-id", -1); - - /* - * scan the table for SCSI bus/devices - */ - tablesize = ddi_get16(lctbuf_dmaacchandle, &lct_buf->TableSize); - - if (!tablesize) { - i2ohba_i_log(NULL, CE_WARN, "?i2o_i_tid_to_scsi: Invalid " - "tablesize"); - return (rval); - } - - /* - * lct table size in WORDS - */ - actualtbl = (tablesize << 2) - sizeof (i2o_lct_t) + - sizeof (i2o_lct_entry_t); - - actualtbl = actualtbl/sizeof (i2o_lct_entry_t); - - /* scan through the table */ - for (count = 0; count < actualtbl; count++) { - uint16_t userid, parentid = 0; - - lctentptr = &(lct_buf->LCTEntry[count]); - userid = get_lct_entry_UserTID(lctentptr, lctbuf_dmaacchandle); - parentid = get_lct_entry_ParentTID(lctentptr, - lctbuf_dmaacchandle); - - /* unclaim devices */ - if (userid == 0xFFF) { - int class; - uint16_t tid; - - class = get_lct_entry_Class(lctentptr, - lctbuf_dmaacchandle); - tid = get_lct_entry_LocalTID(lctentptr, - lctbuf_dmaacchandle); - - /* - * search for SCSI Peripheral with Parent ID - * as the same as hba's TID and unclaimed devices - */ - - if ((parentid == i2ohba->i2ohba_tid) && - (class == I2O_CLASS_SCSI_PERIPHERAL)) { - /* claim it */ - if (i2ohba_utilclaim_msg(i2ohba, tid, - I2O_UTIL_CLAIM)) { - i2ohba_i_log(NULL, CE_WARN, - "?i2ohba_i_tid_to_scsi: " - "i2ohba_utilclaim_msg failed"); - } else { - i2ohba_i_log(NULL, CE_CONT, - "?utilclaim:" - "Tid: 0x%x, SCSI_PERIPHERAL", tid); - /* claim succeed */ - map[entries].tid = tid; - entries++; - } - } - - /* - * find our own bus adapter port and - * claim it as well - */ - if ((tid == i2ohba->i2ohba_tid) && - (class == I2O_CLASS_BUS_ADAPTER_PORT)) { - if (i2ohba_utilclaim_msg(i2ohba, tid, - I2O_UTIL_CLAIM)) { - i2ohba_i_log(NULL, CE_WARN, - "?i2ohba_i_tid_to_scsi: " - "i2ohba_utilclaim_msg failed"); - /* - * it is pointless to continue here - * because if we can't claim the bus port - * then we can't do anything except for - * sending utilgetparm and busreset msgs - */ - break; - } else { - i2ohba_i_log(NULL, CE_CONT, - "?utilclaim:" - "Tid: 0x%x, BUS_ADAPTER_PORT", tid); - rval = 0; - } - } - - } /* userid == 0xFFF */ - } /* for loop */ - - /* - * initialized all utilparam message's mutex's - */ - for (i = 0; i < N_I2OHBA_TARGETS_WIDE; i++) { - mutex_init(I2OHBA_UTILPARAM_MUTEX(i2ohba, i), NULL, - MUTEX_DRIVER, NULL); - cv_init(I2OHBA_UTILPARAM_CV(i2ohba, i), NULL, - CV_DRIVER, NULL); - } - - /* - * Now allocated parameter for each qualified peripheral - */ - for (i = 0; i < entries; i++) { - /* - * call i2ohba_utilparamget_msg to get - * parameters - */ - rval = i2ohba_utilparamget_msg(i2ohba, i, ALL_UTILPARAMS); - if (rval) { - i2ohba_i_log(NULL, CE_WARN, "?i2ohba_i_tid_to_scsi:" - " i2ohba_utilparamget_msg failed"); - } - - } /* for loop */ - - if (i > 0) - rval = 0; - return (rval); - -} - -/* - * Function name: i2ohba_utilcliam_msg() - * - * Return Values: 0 - success - * -1 - fail to claim the device - * - * Description : send a utilclaim or utilclaim_release msg - * to the device - * - * This function is called from i2ohba_i_tid_to_scsi() - */ -static int -i2ohba_utilclaim_msg(struct i2ohba *i2ohba, uint16_t tid, int action) -{ - int rval = -1; - i2o_util_claim_message_t *msgptr; - i2o_msg_handle_t msg_handle; - ddi_acc_handle_t acc_handle; - struct i2ohba_util *sp; - - if (i2o_msg_alloc(i2ohba->i2ohba_iophdl, I2O_MSG_SLEEP, NULL, - (void *)&msgptr, &msg_handle, &acc_handle) != DDI_SUCCESS) { - i2ohba_i_log(NULL, CE_WARN, "?i2ohba_utilclaim_msg: " - "i2o_msg_alloc failed"); - return (rval); - } - - /* - * construct a i2o_hba_bus_reset_message - */ - msgptr->StdMessageFrame.VersionOffset = 0x01; - msgptr->StdMessageFrame.MsgFlags = 0; - ddi_put16(acc_handle, &msgptr->StdMessageFrame.MessageSize, - sizeof (i2o_util_claim_message_t) >> 2); - put_msg_TargetAddress(&msgptr->StdMessageFrame, tid, acc_handle); - put_msg_InitiatorAddress(&msgptr->StdMessageFrame, I2O_OSM_TID, - acc_handle); - put_msg_Function(&msgptr->StdMessageFrame, action, acc_handle); - ddi_put32(acc_handle, - (uint32_t *)&msgptr->StdMessageFrame.InitiatorContext, - (uint32_t)i2ohba_utilmsg_comp); - ddi_put8(acc_handle, &msgptr->ClaimType, I2O_CLAIM_TYPE_PRIMARY_USER); - - /* - * allocating synchronized status buffer - */ - sp = kmem_alloc(sizeof (struct i2ohba_util), KM_SLEEP); - - ddi_put32(acc_handle, &msgptr->TransactionContext, - (uint32_t)(uintptr_t)sp); - - /* - * initialized a mutex and cond variable to - * send message to IOP, and wait for it to signal back - */ - sp->mutex = I2OHBA_UTILPARAM_MUTEX(i2ohba, 0); - sp->cv = I2OHBA_UTILPARAM_CV(i2ohba, 0); - mutex_enter(sp->mutex); - sp->wakeup = UTIL_MSG_SLEEP; - sp->status = 0; - (void) i2o_msg_send(i2ohba->i2ohba_iophdl, msgptr, msg_handle); - while (!sp->wakeup) - cv_wait(sp->cv, sp->mutex); - mutex_exit(sp->mutex); - - /* - * process reply message - */ - - switch (sp->status) { - case I2O_REPLY_STATUS_SUCCESS: - rval = 0; - DEBUGF(1, (CE_CONT, "Reset Succeeded")); - break; - default: - i2ohba_i_log(NULL, CE_CONT, "Reset Failed"); - /* - * Failed the reset for now, - * we can also parse the AdapterStatus - * and retry if needed - */ - break; - } - -cleanup: - if (sp) - kmem_free(sp, sizeof (struct i2ohba_util)); - return (rval); -} - -/* - * i2ohba_utilmsg_comp - * passed the status back to the caller to decided - * what to do with the error code. - */ -/*ARGSUSED*/ -static void -i2ohba_utilmsg_comp(i2o_message_frame_t *msg, ddi_acc_handle_t acc_handle) -{ - - i2o_single_reply_message_frame_t *reply; - int type, reqstatus, detailstatus, adptrstatus; - struct i2ohba_util *sp; - - - reply = (i2o_single_reply_message_frame_t *)msg; - sp = (struct i2ohba_util *)(uintptr_t)ddi_get32(acc_handle, - &reply->TransactionContext); - - type = get_msg_Function(&reply->StdMessageFrame, acc_handle); - - switch (type) { - /* - * Bus Reset - */ - case I2O_HBA_BUS_RESET: - detailstatus = ddi_get16(acc_handle, - &reply->DetailedStatusCode); - adptrstatus = detailstatus & I2O_SCSI_HBA_DSC_MASK; - if (adptrstatus != I2O_HBA_DSC_BUS_RESET) - reqstatus = I2O_REPLY_STATUS_TRANSACTION_ERROR; - else - reqstatus = reply->ReqStatus; - break; - - /* - * Utility Class Function - */ - case I2O_UTIL_PARAMS_GET: - case I2O_UTIL_PARAMS_SET: - case I2O_UTIL_CLAIM: - case I2O_UTIL_CLAIM_RELEASE: - /* - * Adapter Class Function - */ - case I2O_HBA_ADAPTER_RESET: - case I2O_SCSI_DEVICE_RESET: - reqstatus = reply->ReqStatus; - break; - - default: - DEBUGF(2, (CE_CONT, "Error! Not Supported")); - return; - - } - - mutex_enter(sp->mutex); - sp->wakeup = UTIL_MSG_WAKEUP; - sp->status = reqstatus; - cv_broadcast(sp->cv); - mutex_exit(sp->mutex); -} - -/*ARGSUSED*/ -static int -i2ohba_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) -{ - - struct i2ohba *i2ohba; - scsi_hba_tran_t *tran; - int instance = ddi_get_instance(dip); - int i; - - switch (cmd) { - case DDI_DETACH: - { - if ((tran = ddi_get_driver_private(dip)) == NULL) - return (DDI_FAILURE); - - i2ohba = TRAN2I2OHBA(tran); - if (!i2ohba) { - return (DDI_FAILURE); - } - - if (i2ohba->i2ohba_iophdl) - i2o_msg_osm_unregister(&i2ohba->i2ohba_iophdl); - - /* - * deallocate reset notify callback list - */ - scsi_hba_reset_notify_tear_down( - i2ohba->i2ohba_reset_notify_listf); - - if (i2ohba->i2ohba_timeout_id != 0) { - (void) untimeout(i2ohba->i2ohba_timeout_id); - i2ohba->i2ohba_timeout_id = NULL; - } - - /* - * remove device MT locks - */ - mutex_destroy(I2OHBA_REQ_MUTEX(i2ohba)); - mutex_destroy(I2OHBA_RESET_MUTEX(i2ohba)); - cv_destroy(I2OHBA_RESET_CV(i2ohba)); - - for (i = 0; i < N_I2OHBA_TARGETS_WIDE; i++) { - - mutex_destroy(I2OHBA_UTILPARAM_MUTEX(i2ohba, i)); - cv_destroy(I2OHBA_UTILPARAM_CV(i2ohba, i)); - } - - /* - * remove properties created druing attach() - */ - ddi_prop_remove_all(dip); - - /* - * Delete the DMA limits, transport vectors and remove the - * device links to the scsi_transport layer. - * -- ddi_set_driver_private(dip, NULL) - */ - (void) scsi_hba_detach(dip); - - /* - * Free the scsi_transport structure for this device. - */ - scsi_hba_tran_free(tran); - - i2ohba->i2ohba_dip = (dev_info_t *)NULL; - i2ohba->i2ohba_tran = (scsi_hba_tran_t *)NULL; - - ddi_soft_state_free(i2ohba_state, instance); - ddi_remove_minor_node(dip, NULL); - - return (DDI_SUCCESS); - } - /* XXXLWXXX */ - case DDI_SUSPEND: - case DDI_PM_SUSPEND: - default: - return (DDI_FAILURE); - } -} - - -/* - * Function name : i2ohba_tran_tgt_init - * - * Return Values : DDI_SUCCESS if target supported, DDI_FAILURE otherwise - * - */ -/*ARGSUSED*/ -static int -i2ohba_tran_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, - scsi_hba_tran_t *tran, struct scsi_device *sd) -{ - return ((sd->sd_address.a_target < N_I2OHBA_TARGETS_WIDE && - sd->sd_address.a_lun == 0) ? DDI_SUCCESS : - DDI_FAILURE); -} - - -/* - * Function name : i2ohba_i_initcap - * - * Return Values : NONE - * Description : Initializes the default target capabilites and - * Sync Rates. - * - * Context : Called from the user thread through attach. - * - */ -static void -i2ohba_i_initcap(struct i2ohba *i2ohba) -{ - int i, option; - uint16_t cap, synch; - uint8_t offset; - i2o_tid_scsi_ent_t **map = i2ohba->i2ohba_tgt_id_map; - - for (i = 0; i < N_I2OHBA_TARGETS_WIDE; i++) { - cap = 0; - synch = 0; - option = 0; - offset = 0; - - if (map[i] == NULL) - continue; - - /* - * Check for connect/disconnect - */ - if (map[i]->scsi_info_scalar.Flags & - I2O_SCSI_ENABLE_DISCONNECT) { - option |= SCSI_OPTIONS_DR; - cap |= I2OHBA_CAP_DISCONNECT; - } else { - option &= ~SCSI_OPTIONS_DR; - } - - /* - * Check for Wide data - */ - if (map[i]->scsi_info_scalar.Flags & - I2O_SCSI_DATA_WIDTH_MASK) { - option |= SCSI_OPTIONS_WIDE; - cap |= I2OHBA_CAP_WIDE; - } else { - option &= ~SCSI_OPTIONS_WIDE; - } - - /* - * Check for synchronization - */ - if (map[i]->scsi_info_scalar.Flags & - I2O_SCSI_ENABLE_SYNC_NEGOTIATION) { - option |= SCSI_OPTIONS_SYNC; - cap |= I2OHBA_CAP_SYNC; - } else { - option &= ~SCSI_OPTIONS_SYNC; - } - - synch = (uint16_t)map[i]->scsi_info_scalar.NegSyncRate; - offset = (uint8_t)map[i]->scsi_info_scalar.NegOffset; - - /* - * Check for tag queuing capability - */ - if (map[i]->scsi_info_scalar.QueueDepth) { - option |= SCSI_OPTIONS_TAG; - cap |= I2OHBA_CAP_TAG; - } else { - option &= ~SCSI_OPTIONS_TAG; - } - - i2ohba->i2ohba_target_scsi_option[i] = option; - i2ohba->i2ohba_cap[i] = cap; - i2ohba->i2ohba_synch[i] = synch; - i2ohba->i2ohba_offset[i] = offset; - } -} - - - -/* - * Function name : i2ohba_scsi_getcap() - * - * Return Values : current value of capability, if defined - * -1 if capability is not defined - * - * Description : returns current capability value - * - * Context : Can be called from different kernel process threads. - * Can be called by interrupt thread. - */ -static int -i2ohba_scsi_getcap(struct scsi_address *ap, char *cap, int whom) -{ - struct i2ohba *i2ohba = ADDR2I2OHBA(ap); - i2o_tid_scsi_ent_t **map = i2ohba->i2ohba_tgt_id_map; - uint8_t tgt = ap->a_target; - int rval = 0; - - /* - * We don't allow inquiring about capabilities for other targets - */ - if (cap == NULL || whom == 0 || map[tgt] == NULL) { - return (-1); - } - - I2OHBA_MUTEX_ENTER(i2ohba); - - switch (scsi_hba_lookup_capstr(cap)) { - case SCSI_CAP_GEOMETRY: - { /* left this code from adp driver */ - uint32_t total_sectors, c, h, s, t; - c = 1024L; - s = 62L; - - total_sectors = i2ohba->i2ohba_totsec[tgt]; - - t = c * s; - h = total_sectors / t; - if (total_sectors % t) { - h ++; - t = c * h; - s = total_sectors / t; - if (total_sectors % t) { - s++; - t = h * s; - c = total_sectors / t; - } - } - if (c == 0) rval = 1; - - rval = ((h << 16) | s); - break; - } - case SCSI_CAP_DMA_MAX: - rval = 1 << 24; /* Limit to 16MB max transfer */ - break; - case SCSI_CAP_MSG_OUT: - rval = 1; - break; - case SCSI_CAP_DISCONNECT: - if ((i2ohba->i2ohba_target_scsi_option[tgt] & - SCSI_OPTIONS_DR) == 0) { - break; - } else if ((i2ohba->i2ohba_cap[tgt] & I2OHBA_CAP_DISCONNECT) - == 0) { - break; - } - rval = 1; - break; - case SCSI_CAP_SYNCHRONOUS: - if ((i2ohba->i2ohba_target_scsi_option[tgt] & - SCSI_OPTIONS_SYNC) == 0) { - break; - } else if ((i2ohba->i2ohba_cap[tgt] & I2OHBA_CAP_SYNC) == 0) { - break; - } - rval = 1; - break; - case SCSI_CAP_WIDE_XFER: - if ((i2ohba->i2ohba_target_scsi_option[tgt] & - SCSI_OPTIONS_WIDE) == 0) { - break; - } else if ((i2ohba->i2ohba_cap[tgt] & I2OHBA_CAP_WIDE) == 0) { - break; - } - rval = 1; - break; - case SCSI_CAP_TAGGED_QING: - if ((i2ohba->i2ohba_target_scsi_option[tgt] & - SCSI_OPTIONS_DR) == 0 || - (i2ohba->i2ohba_target_scsi_option[tgt] & - SCSI_OPTIONS_TAG) == 0) { - break; - } else if ((i2ohba->i2ohba_cap[tgt] & I2OHBA_CAP_TAG) == 0) { - break; - } - rval = 1; - break; - case SCSI_CAP_UNTAGGED_QING: - rval = 0; - break; - case SCSI_CAP_PARITY: - if (i2ohba->i2ohba_target_scsi_option[tgt] & - SCSI_OPTIONS_PARITY) { - rval = 1; - } - break; - case SCSI_CAP_INITIATOR_ID: - rval = i2ohba->i2ohba_initiator_id; - break; - case SCSI_CAP_ARQ: - rval = 1; - break; - case SCSI_CAP_LINKED_CMDS: - break; - case SCSI_CAP_RESET_NOTIFICATION: - rval = 1; - break; - default: - rval = -1; - break; - } - - I2OHBA_MUTEX_EXIT(i2ohba); - - return (rval); -} - - -/* - * Function name : i2ohba_scsi_setcap() - * - * Return Values : 1 - capability exists and can be set to new value - * 0 - capability could not be set to new value - * -1 - no such capability - * - * Description : sets a capability for a target - * - * Context : Can be called from different kernel process threads. - * Can be called by interrupt thread. - */ -static int -i2ohba_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom) -{ - struct i2ohba *i2ohba = ADDR2I2OHBA(ap); - i2o_tid_scsi_ent_t **map = i2ohba->i2ohba_tgt_id_map; - uint8_t tgt = ap->a_target; - int update = 0; - int sync = 0; - int rval = 0; - - /* - * We don't allow setting capabilities for other targets - * and the targets that are not in this OSM's control - */ - if (cap == NULL || whom == 0 || map[tgt] == NULL) { - return (-1); - } - - I2OHBA_MUTEX_ENTER(i2ohba); - - switch (scsi_hba_lookup_capstr(cap)) { - case SCSI_CAP_DMA_MAX: - case SCSI_CAP_MSG_OUT: - case SCSI_CAP_PARITY: - case SCSI_CAP_UNTAGGED_QING: - case SCSI_CAP_LINKED_CMDS: - case SCSI_CAP_RESET_NOTIFICATION: - case SCSI_CAP_GEOMETRY: - /* - * None of these are settable via - * the capability interface. - */ - break; - - case SCSI_CAP_SECTOR_SIZE: - if (value) { - i2ohba->i2ohba_secsz[tgt] = value; - rval = 1; - } - break; - - case SCSI_CAP_TOTAL_SECTORS: - if (value) { - i2ohba->i2ohba_totsec[tgt] = value; - rval = 1; - } - break; - case SCSI_CAP_ARQ: - if (value) { - i2ohba->i2ohba_cap[tgt] |= I2OHBA_CAP_AUTOSENSE; - } else { - i2ohba->i2ohba_cap[tgt] &= ~I2OHBA_CAP_AUTOSENSE; - } - rval = 1; - break; - - /* disconnect/reconncet either the target supports or doesn't */ - case SCSI_CAP_DISCONNECT: - if ((i2ohba->i2ohba_target_scsi_option[tgt] & - SCSI_OPTIONS_DR) == 0) { - break; - } else { - if (value) { - if ((i2ohba->i2ohba_cap[tgt] & - I2OHBA_CAP_DISCONNECT) == 0) { - if (i2ohba_utilparamset_msg(i2ohba, - tgt, map[tgt]->tid, - I2O_SCSI_DEVICE_INFO_GROUP_NO, 0x1, - I2O_SCSI_ENABLE_DISCONNECT) != 0) - break; - i2ohba->i2ohba_cap[tgt] |= - I2OHBA_CAP_DISCONNECT; - } - } else { - if ((i2ohba->i2ohba_cap[tgt] & - I2OHBA_CAP_DISCONNECT) == 1) { - if (i2ohba_utilparamset_msg(i2ohba, - tgt, map[tgt]->tid, - I2O_SCSI_DEVICE_INFO_GROUP_NO, 0x1, - I2O_SCSI_DISABLE_DISCONNECT) != 0) - break; - i2ohba->i2ohba_cap[tgt] &= - ~I2OHBA_CAP_DISCONNECT; - } - } - } - rval = 1; - break; - - /* these can be set through UtilParamSet message */ - case SCSI_CAP_SYNCHRONOUS: - if ((i2ohba->i2ohba_target_scsi_option[tgt] & - SCSI_OPTIONS_SYNC) == 0) { - break; - } else { - if (value) { - if ((i2ohba->i2ohba_cap[tgt] & - I2OHBA_CAP_SYNC) == 0) { - if (i2ohba_utilparamset_msg(i2ohba, - tgt, map[tgt]->tid, - I2O_SCSI_DEVICE_INFO_GROUP_NO, 0x1, - I2O_SCSI_ENABLE_SYNC_NEGOTIATION) - != 0) - break; - /* set sync speed to Max */ - if (i2ohba_utilparamset_msg(i2ohba, - tgt, map[tgt]->tid, - I2O_SCSI_DEVICE_INFO_GROUP_NO, 0xA, - 0xFFFF) != 0) - break; - /* read the set value */ - if (i2ohba_utilparamget_msg(i2ohba, - tgt, SYNC_UTILPARAM) != 0) - break; - i2ohba->i2ohba_cap[tgt] |= - I2OHBA_CAP_SYNC; - sync++; - update++; - } - } else { - if ((i2ohba->i2ohba_cap[tgt] & - I2OHBA_CAP_SYNC) == 1) { - if (i2ohba_utilparamset_msg(i2ohba, - tgt, map[tgt]->tid, - I2O_SCSI_DEVICE_INFO_GROUP_NO, 0x1, - I2O_SCSI_DISABLE_SYNC_NEGOTIATION) - != 0) - break; - i2ohba->i2ohba_cap[tgt] &= - ~I2OHBA_CAP_SYNC; - update++; - } - } - } - rval = 1; - break; - case SCSI_CAP_TAGGED_QING: - if ((i2ohba->i2ohba_target_scsi_option[tgt] & - SCSI_OPTIONS_DR) == 0 || - (i2ohba->i2ohba_target_scsi_option[tgt] & - SCSI_OPTIONS_TAG) == 0) { - break; - } else { - if (value) { - if ((i2ohba->i2ohba_cap[tgt] & - I2OHBA_CAP_TAG) == 0) { - if (i2ohba_utilparamset_msg(i2ohba, - tgt, map[tgt]->tid, - I2O_SCSI_DEVICE_INFO_GROUP_NO, 0x5, - 0) != 0) - break; - i2ohba->i2ohba_cap[tgt] |= - I2OHBA_CAP_TAG; - update++; - } - } else { - if ((i2ohba->i2ohba_cap[tgt] & - I2OHBA_CAP_TAG) == 1) { - if (i2ohba_utilparamset_msg(i2ohba, - tgt, map[tgt]->tid, - I2O_SCSI_DEVICE_INFO_GROUP_NO, 0x5, - (uint16_t)1) != 0) - break; - i2ohba->i2ohba_cap[tgt] &= - ~I2OHBA_CAP_TAG; - update++; - } - } - } - rval = 1; - break; - case SCSI_CAP_WIDE_XFER: - if ((i2ohba->i2ohba_target_scsi_option[tgt] & - SCSI_OPTIONS_WIDE) == 0) { - break; - } else { - if (value) { - if ((i2ohba->i2ohba_cap[tgt] & - I2OHBA_CAP_WIDE) == 0) { - if (i2ohba_utilparamset_msg(i2ohba, - tgt, map[tgt]->tid, - I2O_SCSI_DEVICE_INFO_GROUP_NO, 0x1, - I2O_SCSI_DATA_WIDTH_16) != 0) - break; - i2ohba->i2ohba_cap[tgt] |= - I2OHBA_CAP_WIDE; - update++; - } - } else { - if ((i2ohba->i2ohba_cap[tgt] & - I2OHBA_CAP_WIDE) == 1) { - if (i2ohba_utilparamset_msg(i2ohba, - tgt, map[tgt]->tid, - I2O_SCSI_DEVICE_INFO_GROUP_NO, 0x1, - I2O_SCSI_DATA_WIDTH_8) != 0) - break; - i2ohba->i2ohba_cap[tgt] &= - ~I2OHBA_CAP_WIDE; - update++; - } - } - } - rval = 1; - break; - case SCSI_CAP_INITIATOR_ID: - if (value < N_I2OHBA_TARGETS_WIDE) { - if (i2ohba->i2ohba_initiator_id != (uint16_t)value) { - /* - * set Initiator SCSI ID - */ - if (i2ohba_utilparamset_msg(i2ohba, - i2ohba->i2ohba_initiator_id, - i2ohba->i2ohba_tid, - I2O_HBA_SCSI_CONTROLLER_INFO_GROUP_NO, 0x4, - value) == 0) { - rval = 1; - i2ohba->i2ohba_initiator_id = value; - } - } - } - break; - - default: - rval = -1; - break; - } - - - /* - * now set flag so latter in i2ohba_i_watch(), - * we can set prop_update - */ - if ((rval == 1) && (update > 0)) { - i2ohba->i2ohba_need_prop_update |= 1 << tgt; - if (sync) - i2ohba_i_updatesync(i2ohba, tgt); - } - - I2OHBA_MUTEX_EXIT(i2ohba); - - return (rval); -} - -/* - * Function name : i2ohba_i_updatesync() - * - * Return Values : -1 failed - * 0 success - * - * Description : modifies/update target sync mode speed, widexfer, - * and TQ. - * - * Context : Can be called from different kernel process threads. - * Can not be called by interrupt thread - */ -static void -i2ohba_i_updatesync(struct i2ohba *i2ohba, int tgt) -{ - uint16_t synch; - uint8_t offset; - i2o_tid_scsi_ent_t **map = i2ohba->i2ohba_tgt_id_map; - - if (map[tgt] == NULL) - return; - - if (map[tgt]->scsi_info_scalar.Flags & - I2O_SCSI_ENABLE_SYNC_NEGOTIATION) { - synch = (uint16_t)map[tgt]->scsi_info_scalar.NegSyncRate; - offset = (uint8_t)map[tgt]->scsi_info_scalar.NegOffset; - - i2ohba->i2ohba_synch[tgt] = synch; - i2ohba->i2ohba_offset[tgt] = offset; - } -} - -/* - * Function name : i2ohba_i_update_props() - * - * Description : Creates/modifies/removes a target sync mode speed, - * wide, and TQ properties - * If offset is 0 then asynchronous mode is assumed and the - * property is removed, if it existed. - * - * Context : Can be called from different kernel process threads. - * Can not be called by interrupt thread - */ -static void -i2ohba_i_update_props(struct i2ohba *i2ohba, int tgt) -{ - static char property[32]; - int xfer_speed = 0; - int wide_enabled; - int tq_enabled; - uint16_t cap; - uint16_t synch; - uint8_t offset; - - cap = i2ohba->i2ohba_cap[tgt]; - synch = i2ohba->i2ohba_synch[tgt]; - offset = i2ohba->i2ohba_offset[tgt]; - - tq_enabled = cap & I2OHBA_CAP_TAG; - wide_enabled = cap & I2OHBA_CAP_WIDE; - - if (offset && synch) { - if (wide_enabled) { - /* double xfer speed if wide has been enabled */ - xfer_speed = ((int)synch * 2); - } else { - xfer_speed = (int)(synch); - } - } - - (void) sprintf(property, "target%x-sync-speed", tgt); - i2ohba_i_update_this_prop(i2ohba, property, xfer_speed); - - (void) sprintf(property, "target%x-wide", tgt); - i2ohba_i_update_this_prop(i2ohba, property, wide_enabled); - - (void) sprintf(property, "target%x-TQ", tgt); - i2ohba_i_update_this_prop(i2ohba, property, tq_enabled); -} - -/* - * Update a property's value - */ -static void -i2ohba_i_update_this_prop(struct i2ohba *i2ohba, char *property, int value) -{ - dev_info_t *dip = i2ohba->i2ohba_dip; - - - if (ddi_prop_update_int(DDI_DEV_T_NONE, dip, - property, value) != DDI_PROP_SUCCESS) { - i2ohba_i_log(NULL, CE_CONT, "?i2ohba_i_update_this_prop:" - " can't update %s property to 0x%x", - property, value); - } -} - - -/* - * Function name : i2ohba_scsi_init_pkt - * - * Return Values : pointer to scsi_pkt, or NULL - * Description : Called by kernel on behalf of a target driver - * calling scsi_init_pkt(9F). - * Refer to tran_init_pkt(9E) man page - * - * Context : Can be called from different kernel process threads. - * Can be called by interrupt thread. - */ -static struct scsi_pkt * -i2ohba_scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt, - struct buf *bp, int cmdlen, int statuslen, int tgtlen, - int flags, int (*callback)(), caddr_t arg) -{ - struct i2ohba_cmd *sp; - struct i2ohba *i2ohba = ADDR2I2OHBA(ap); - struct scsi_pkt *new_pkt; - - ASSERT(callback == NULL_FUNC || callback == SLEEP_FUNC); - - /* - * First step of i2ohba_scsi_init_pkt: pkt allocation - */ - if (pkt == NULL) { - pkt = scsi_hba_pkt_alloc(i2ohba->i2ohba_dip, ap, cmdlen, - statuslen, tgtlen, sizeof (struct i2ohba_cmd), callback, - arg); - - if (pkt == NULL) { - return (NULL); - } - - sp = PKT2CMD(pkt); - - /* - * Initialize the new pkt - we redundantly initialize - * all the fields for illustrative purposes. - */ - sp->cmd_pkt = pkt; - sp->cmd_flags = 0; - sp->cmd_scblen = statuslen; - sp->cmd_cdblen = (uint8_t)cmdlen; - sp->cmd_privlen = tgtlen; - sp->cmd_dmahandle = NULL; - sp->cmd_dmacount = 0; - sp->cmd_cookie = 0; - pkt->pkt_address = *ap; - pkt->pkt_comp = (void (*)())NULL; - pkt->pkt_flags = 0; - pkt->pkt_time = 0; - pkt->pkt_resid = 0; - pkt->pkt_statistics = 0; - pkt->pkt_reason = 0; - - new_pkt = pkt; - } else { - sp = PKT2CMD(pkt); - new_pkt = NULL; - } - - /* - * Second step of i2ohba_scsi_init_pkt: dma allocation/move - */ - if (bp && bp->b_bcount != 0) { - if (sp->cmd_dmahandle == NULL) { - ASSERT((sp->cmd_flags & CFLAG_DMAVALID) == 0); - if (i2ohba_i_dma_alloc(i2ohba, pkt, bp, - flags, callback) == -1) { - if (new_pkt) { - scsi_hba_pkt_free(ap, new_pkt); - } - return ((struct scsi_pkt *)NULL); - } - } else { - ASSERT(new_pkt == NULL); - ASSERT(sp->cmd_flags & CFLAG_DMAVALID); - if (i2ohba_i_dma_move(i2ohba, pkt, bp) < 0) { - return ((struct scsi_pkt *)NULL); - } - } - ASSERT(sp->cmd_flags & CFLAG_DMAVALID); - DEBUGF(3, (CE_CONT, "init: bcount = %lx, resid = %lx", - bp->b_bcount, pkt->pkt_resid)); - } - - return (pkt); -} - -/* - * Function name : i2ohba_i_dma_alloc - * - * Return Values : 0 if successful, -1 if failure - * Description : allocate DMA resources - * - * Context : Can only be called from i2ohba_scsi_init_pkt() - */ -static int -i2ohba_i_dma_alloc(struct i2ohba *i2ohba, struct scsi_pkt *pkt, - struct buf *bp, int flags, int (*callback)()) -{ - struct i2ohba_cmd *sp = PKT2CMD(pkt); - int dma_flags; - int (*cb)(caddr_t); - int i; - - ASSERT(callback == NULL_FUNC || callback == SLEEP_FUNC); - - if (bp->b_flags & B_READ) { - sp->cmd_flags &= ~CFLAG_DMASEND; - dma_flags = DDI_DMA_READ; - } else { - sp->cmd_flags |= CFLAG_DMASEND; - dma_flags = DDI_DMA_WRITE; - } - - if (flags & PKT_CONSISTENT) { - sp->cmd_flags |= CFLAG_CMDIOPB; - dma_flags |= DDI_DMA_CONSISTENT; - } - - if (flags & PKT_DMA_PARTIAL) { - dma_flags |= DDI_DMA_PARTIAL; - } - - dma_flags |= DDI_DMA_REDZONE; - - cb = (callback == NULL_FUNC) ? DDI_DMA_DONTWAIT : DDI_DMA_SLEEP; - - if ((i = ddi_dma_alloc_handle(i2ohba->i2ohba_dip, - &i2ohba_dma_attr, cb, NULL, &sp->cmd_dmahandle)) - != DDI_SUCCESS) { - switch (i) { - case DDI_DMA_BADATTR: - bioerror(bp, EFAULT); - return (-1); - - case DDI_DMA_NORESOURCES: - bioerror(bp, 0); - return (-1); - - default: - i2ohba_i_log(NULL, CE_WARN, - "?ddi_dma_alloc_handle:" - " 0x%x impossible", i); - /*NOTREACHED*/ - } - } - -#ifdef I2OHBA_DEBUG - ddi_dma_bufalloc++; -#endif - - i = ddi_dma_buf_bind_handle(sp->cmd_dmahandle, bp, dma_flags, - cb, NULL, &sp->cmd_dmacookies[0], &sp->cmd_ncookies); -#ifdef I2OHBA_DEBUG - ddi_dma_buf_bind++; -#endif - - DEBUGF(3, (CE_CONT, "dma_alloc: cmd_ncookies is %d\n", - sp->cmd_ncookies)); - - switch (i) { - case DDI_DMA_PARTIAL_MAP: - ASSERT(dma_flags & DDI_DMA_PARTIAL); - - if (ddi_dma_numwin(sp->cmd_dmahandle, &sp->cmd_nwin) == - DDI_FAILURE) { - i2ohba_i_log(NULL, CE_WARN, - "?ddi_dma_numwin() failed"); - /*NOTREACHED*/ - } - - if (ddi_dma_getwin(sp->cmd_dmahandle, sp->cmd_curwin, - &sp->cmd_dma_offset, &sp->cmd_dma_len, - &sp->cmd_dmacookies[0], &sp->cmd_ncookies) == - DDI_FAILURE) { - i2ohba_i_log(NULL, CE_WARN, - "?ddi_dma_getwin() failed"); - /*NOTREACHED*/ - } - goto get_dma_cookies; - - case DDI_DMA_MAPPED: - sp->cmd_nwin = 1; - sp->cmd_dma_len = 0; - sp->cmd_dma_offset = 0; - -get_dma_cookies: - i = 0; - sp->cmd_dmacount = 0; - for (;;) { - sp->cmd_dmacount += sp->cmd_dmacookies[i++].dmac_size; - - if (i == I2OHBA_CMD_NSEGS || i == sp->cmd_ncookies) - break; - ddi_dma_nextcookie(sp->cmd_dmahandle, - &sp->cmd_dmacookies[i]); - } - - sp->cmd_cookie = i; - sp->cmd_cookiecnt = i; - - sp->cmd_flags |= CFLAG_DMAVALID; - pkt->pkt_resid = bp->b_bcount - sp->cmd_dmacount; - - DEBUGF(3, (CE_CONT, "bcount is %lx, dmacount is %lx," - " resid is %lx\n", - bp->b_bcount, sp->cmd_dmacount, pkt->pkt_resid)); - - return (0); - - case DDI_DMA_NORESOURCES: - bioerror(bp, 0); - break; - - case DDI_DMA_NOMAPPING: - bioerror(bp, EFAULT); - break; - - case DDI_DMA_TOOBIG: - bioerror(bp, EINVAL); - break; - - case DDI_DMA_INUSE: - i2ohba_i_log(NULL, CE_WARN, "?ddi_dma_buf_bind_handle:" - " DDI_DMA_INUSE impossible"); - /*NOTREACHED*/ - - default: - i2ohba_i_log(NULL, CE_WARN, "?ddi_dma_buf_bind_handle:" - " 0x%x impossible", i); - /*NOTREACHED*/ - } - - ddi_dma_free_handle(&sp->cmd_dmahandle); - sp->cmd_dmahandle = NULL; - sp->cmd_flags &= ~CFLAG_DMAVALID; - return (-1); -} - - -/* - * Function name : i2ohba_i_dma_move - * - * Return Values : 0 if successful, -1 if failure - * Description : move DMA resources to next DMA window - * - * Context : Can only be called from i2ohba_scsi_init_pkt() - */ -/*ARGSUSED*/ -static int -i2ohba_i_dma_move(struct i2ohba *i2ohba, struct scsi_pkt *pkt, struct buf *bp) -{ - struct i2ohba_cmd *sp = PKT2CMD(pkt); - int i; - - ASSERT(sp->cmd_flags & CFLAG_COMPLETED); - sp->cmd_flags &= ~CFLAG_COMPLETED; - - /* - * If there are no more cookies remaining in this window, - * must move to the next window first. - */ - if (sp->cmd_cookie == sp->cmd_ncookies) { - /* - * 1217340: cmdk reuses pkts incorrectly - */ - if (sp->cmd_curwin == sp->cmd_nwin && sp->cmd_nwin == 1) - return (0); - - /* - * At last window, cannot move - */ - if (++sp->cmd_curwin >= sp->cmd_nwin) - return (-1); - - if (ddi_dma_getwin(sp->cmd_dmahandle, sp->cmd_curwin, - &sp->cmd_dma_offset, &sp->cmd_dma_len, - &sp->cmd_dmacookies[0], &sp->cmd_ncookies) == DDI_FAILURE) - return (-1); - - sp->cmd_cookie = 0; - } else { - /* - * Still more cookies in this window - get the next one - */ - ddi_dma_nextcookie(sp->cmd_dmahandle, &sp->cmd_dmacookies[0]); - } - - /* - * Get remaining cookies in this window, up to our maximum - */ - i = 0; - for (;;) { - sp->cmd_dmacount += sp->cmd_dmacookies[i++].dmac_size; - sp->cmd_cookie++; - if (i == I2OHBA_CMD_NSEGS || sp->cmd_cookie == sp->cmd_ncookies) - break; - ddi_dma_nextcookie(sp->cmd_dmahandle, &sp->cmd_dmacookies[i]); - } - sp->cmd_cookiecnt = i; - - pkt->pkt_resid = bp->b_bcount - sp->cmd_dmacount; - return (0); -} - - -/* - * Function name : i2ohba_scsi_destroy_pkt - * - * Return Values : none - * Description : Called by kernel on behalf of a target driver - * calling scsi_destroy_pkt(9F). - * Refer to tran_destroy_pkt(9E) man page - * - * Context : Can be called from different kernel process threads. - * Can be called by interrupt thread. - */ -static void -i2ohba_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) -{ - struct i2ohba_cmd *sp = PKT2CMD(pkt); - struct i2ohba *i2ohba = ADDR2I2OHBA(ap); - i2o_tid_scsi_ent_t **map = i2ohba->i2ohba_tgt_id_map; - uint8_t tgt = ap->a_target; - - if (map[tgt] != NULL) { - - /* - * i2o_scsi_dmafree inline to make things faster - */ - if (sp->cmd_flags & CFLAG_DMAVALID) { - /* - * Free the mapping - */ - sp->cmd_flags &= ~CFLAG_DMAVALID; - if (ddi_dma_unbind_handle(sp->cmd_dmahandle) - != DDI_SUCCESS) { - i2ohba_i_log(NULL, CE_WARN, - "?i2ohba_scsi_destroy_pkt: " - "ddi_dma_unbind_handle() for dataseg" - " failed"); - /*NOTREACHED*/ - } -#ifdef I2OHBA_DEBUG - ddi_dma_buf_unbind++; -#endif - ddi_dma_free_handle(&sp->cmd_dmahandle); -#ifdef I2OHBA_DEBUG - ddi_dma_buf_free_hdl++; -#endif - sp->cmd_dmahandle = NULL; - } - } - - /* - * Free the pkt - */ - scsi_hba_pkt_free(ap, pkt); -} - - -/* - * Function name : i2ohba_scsi_dmafree() - * - * Return Values : none - * Description : free dvma resources - * - * Context : Can be called from different kernel process threads. - * Can be called by interrupt thread. - */ -/*ARGSUSED*/ -static void -i2ohba_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt) -{ - struct i2ohba_cmd *sp = PKT2CMD(pkt); - struct i2ohba *i2ohba = ADDR2I2OHBA(ap); - i2o_tid_scsi_ent_t **map = i2ohba->i2ohba_tgt_id_map; - uint8_t tgt = ap->a_target; - - if (map[tgt] != NULL) { - if (sp->cmd_flags & CFLAG_DMAVALID) { - /* - * Free the mapping. - */ - sp->cmd_flags &= ~CFLAG_DMAVALID; - if (ddi_dma_unbind_handle(sp->cmd_dmahandle) - != DDI_SUCCESS) { - i2ohba_i_log(NULL, CE_WARN, - "?i2ohba_scsi_dmafree: " - "ddi_dma_unbind_handle() for dataseg" - " failed"); - /*NOTREACHED*/ - } -#ifdef I2OHBA_DEBUG - ddi_dma_buf_unbind++; -#endif - ddi_dma_free_handle(&sp->cmd_dmahandle); -#ifdef I2OHBA_DEBUG - ddi_dma_buf_free_hdl++; -#endif - sp->cmd_dmahandle = NULL; - } - } -} - -/* - * Function name: i2ohba_scsi_sync_pkt() - * - * Return Values: none - * Description : sync dma - * - * Context : Can be called from different kernel process threads. - * Can be called by interrupt thread. - */ -/*ARGSUSED*/ -static void -i2ohba_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) -{ - int i; - struct i2ohba_cmd *sp = PKT2CMD(pkt); - struct i2ohba *i2ohba = ADDR2I2OHBA(ap); - i2o_tid_scsi_ent_t **map = i2ohba->i2ohba_tgt_id_map; - uint8_t tgt = ap->a_target; - - if (map[tgt] != NULL) { - if (sp->cmd_flags & CFLAG_DMAVALID) { - i = ddi_dma_sync(sp->cmd_dmahandle, sp->cmd_dma_offset, - sp->cmd_dma_len, - (sp->cmd_flags & CFLAG_DMASEND) ? - DDI_DMA_SYNC_FORDEV : DDI_DMA_SYNC_FORCPU); - if (i != DDI_SUCCESS) { - i2ohba_i_log(NULL, CE_WARN, - "?i2ohba_scsi_sync_pkt: sync pkt failed"); - } - } - } -} - - -/* - * routine for reset notification setup, to register or cancel. - */ -static int -i2ohba_scsi_reset_notify(struct scsi_address *ap, int flag, -void (*callback)(caddr_t), caddr_t arg) -{ - struct i2ohba *i2ohba = ADDR2I2OHBA(ap); - return (scsi_hba_reset_notify_setup(ap, flag, callback, arg, - I2OHBA_REQ_MUTEX(i2ohba), &i2ohba->i2ohba_reset_notify_listf)); -} - -/* - * Function name : i2ohba_scsi_start() - * - * Return Values : TRAN_FATAL_ERROR - i2o has been shutdown - * TRAN_BUSY - request queue is full - * TRAN_ACCEPT - pkt has been submitted to i2o - * - * Description : init pkt, start the request - * - * Context : Can be called from different kernel process threads. - * Can be called by interrupt thread. - */ -static int -i2ohba_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt) -{ - struct i2ohba_cmd *sp = PKT2CMD(pkt); - int rval = TRAN_ACCEPT; - struct i2ohba *i2ohba = ADDR2I2OHBA(ap); - dev_info_t *dip = (PKT2I2OHBA(pkt))->i2ohba_dip; - i2o_tid_scsi_ent_t **tgtmap = i2ohba->i2ohba_tgt_id_map; - i2o_scsi_scb_execute_message_t *req; - i2o_sge_chain_element_t *sgl; - i2o_sge_ignore_element_t *sgl2; - i2o_msg_handle_t msg_handle; - i2o_sge_chain_element_t *cpsgl; - ddi_acc_handle_t acc_handle; - clock_t cur_lbolt; - uint16_t tid; - uint16_t flags = 0, msgsize; - int i, val, bound = 0; - size_t sglen; - uint_t count; - - - ASSERT(I2OHBA_MUTEX_OWNED(i2ohba) == 0 || ddi_in_panic()); - - /* - * if we have a shutdown, return packet - */ - if (i2ohba->i2ohba_shutdown) { - return (TRAN_FATAL_ERROR); - } - - if (i2ohba->i2ohba_throttle) { - return (TRAN_BUSY); - } - /* - * if the target id is not in our map, don't bother composing - * the message, return fail - */ - if (tgtmap[TGT(sp)] == NULL) { - return (TRAN_FATAL_ERROR); - } else { - tid = tgtmap[TGT(sp)]->tid; - } - - i2ohba->i2ohba_counter++; - if (i2ohba->i2ohba_counter > 64) { - DEBUGF(1, (CE_CONT, "i2ohba_counter > 64\n")); - DEBUGF(1, (CE_CONT, "sp = %p\n", (void *)sp)); - i2ohba->i2ohba_counter--; - return (TRAN_BUSY); - } - - ASSERT(!(sp->cmd_flags & CFLAG_IN_TRANSPORT)); - sp->cmd_flags = (sp->cmd_flags & ~CFLAG_TRANFLAG) | - CFLAG_IN_TRANSPORT; - pkt->pkt_reason = CMD_CMPLT; - - /* - * Set up request in i2ohba_reqhead area so it is ready to - * go once we have the request mutex, - * The reason we don't allocate the msg buffer in scsi_init_pkt - * is that the msg buffer is a resource from the FIFO of the IOP - * we don't want to give that ptr around - */ - - if (i2o_msg_alloc(i2ohba->i2ohba_iophdl, I2O_MSG_DONTWAIT, - NULL, (void *)&req, &msg_handle, &acc_handle) != DDI_SUCCESS) { - i2ohba_i_log(NULL, CE_WARN, "?i2ohba_scsi_start: " - " i2o_msg_alloc failed"); - sp->cmd_flags = (sp->cmd_flags & ~CFLAG_IN_TRANSPORT); - pkt->pkt_reason = 0; - i2ohba->i2ohba_counter--; - return (TRAN_BUSY); - } - - - /* - * Constructed a scsi_scb_execute_message - */ - - /* StdMessageFrame */ - req->StdMessageFrame.VersionOffset = 0xA1; - req->StdMessageFrame.MsgFlags = 0; - - if (sp->cmd_flags & CFLAG_DMAVALID) { - msgsize = ((sizeof (i2o_scsi_scb_execute_message_t) - - sizeof (i2o_sg_element_t) + - sizeof (i2o_sge_chain_element_t) + - sizeof (i2o_sge_ignore_element_t)) >> 2); - } else { - msgsize = ((sizeof (i2o_scsi_scb_execute_message_t) - - sizeof (i2o_sg_element_t)) >> 2); - } - - /* - * To get actual allocation msg size - */ - ASSERT(msgsize <= ddi_get16(acc_handle, - &req->StdMessageFrame.MessageSize)); - - ddi_put16(acc_handle, &req->StdMessageFrame.MessageSize, msgsize); - put_msg_TargetAddress(&req->StdMessageFrame, tid, acc_handle); - put_msg_InitiatorAddress(&req->StdMessageFrame, I2O_OSM_TID, - acc_handle); - put_msg_Function(&req->StdMessageFrame, I2O_SCSI_SCB_EXEC, acc_handle); - ddi_put32(acc_handle, - (uint32_t *)&req->StdMessageFrame.InitiatorContext, - (uint32_t)i2ohba_callback); - - /* TransactionContext */ - ddi_put32(acc_handle, &req->TransactionContext, - (uint32_t)(uintptr_t)sp); - - /* Set up CDB in the request */ - - bzero(req->CDB, I2O_SCSI_CDB_LENGTH); - if (sp->cmd_cdblen > I2O_SCSI_CDB_LENGTH) { - req->CDBLength = I2O_SCSI_CDB_LENGTH; - } else { - req->CDBLength = sp->cmd_cdblen; - } - bcopy(pkt->pkt_cdbp, req->CDB, sp->cmd_cdblen); - bcopy(pkt->pkt_cdbp, sp->cmd_cdb, sp->cmd_cdblen); - -#ifdef I2OHBA_DEBUG - if (sp->cmd_cdblen == 0x6) { - DEBUGF(1, (CE_CONT, "%d: %x %x %x %x %x %x\n", - sp->cmd_cdblen, - pkt->pkt_cdbp[0], pkt->pkt_cdbp[1], - pkt->pkt_cdbp[2], pkt->pkt_cdbp[3], - pkt->pkt_cdbp[4], pkt->pkt_cdbp[5])); - } else { - DEBUGF(1, (CE_CONT, "10: %x %x %x %x %x %x %x %x %x %x\n", - pkt->pkt_cdbp[0], pkt->pkt_cdbp[1], - pkt->pkt_cdbp[2], pkt->pkt_cdbp[3], - pkt->pkt_cdbp[4], pkt->pkt_cdbp[5], - pkt->pkt_cdbp[6], pkt->pkt_cdbp[7], - pkt->pkt_cdbp[8], pkt->pkt_cdbp[9])); - } -#endif - - DEBUGF(1, (CE_CONT, "pkt_flags = 0x%x\n", pkt->pkt_flags)); - /* Tag queuing */ - if (pkt->pkt_flags & FLAG_STAG) - flags |= I2O_SCB_FLAG_SIMPLE_QUEUE_TAG; - - else if (pkt->pkt_flags & FLAG_OTAG) - flags |= I2O_SCB_FLAG_ORDERED_QUEUE_TAG; - - else if (pkt->pkt_flags & FLAG_HTAG) - flags |= I2O_SCB_FLAG_HEAD_QUEUE_TAG; - - else if (pkt->pkt_flags & FLAG_ACA) - flags |= I2O_SCB_FLAG_ACA_QUEUE_TAG; - - if ((pkt->pkt_flags & FLAG_SENSING) || - (i2ohba->i2ohba_cap[TGT(sp)] & I2OHBA_CAP_AUTOSENSE)) - flags |= I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE; - - /* DISCONNECT enable by default especially with TAGQ */ - if (pkt->pkt_flags & FLAG_NODISCON) - flags &= ~I2O_SCB_FLAG_ENABLE_DISCONNECT; - else - flags |= I2O_SCB_FLAG_ENABLE_DISCONNECT; - - if (sp->cmd_flags & CFLAG_DMASEND) { - flags |= I2O_SCB_FLAG_XFER_TO_DEVICE; - } else { - flags |= I2O_SCB_FLAG_XFER_FROM_DEVICE; - } - - ddi_put16(acc_handle, &req->SCBFlags, flags); - DEBUGF(1, (CE_CONT, "SCBflags = 0x%x\n", flags)); - - /* - * All msg are using chain pointer. - * Setup dma transfers data segments. - */ - - sgl = (i2o_sge_chain_element_t *)&req->SGL; - sgl2 = (i2o_sge_ignore_element_t *)((caddr_t)sgl + - sizeof (i2o_sge_chain_element_t)); - if (sp->cmd_flags & CFLAG_DMAVALID) { - - if (sp->cmd_flags & CFLAG_CMDIOPB) { - (void) ddi_dma_sync(sp->cmd_dmahandle, - sp->cmd_dma_offset, sp->cmd_dma_len, - DDI_DMA_SYNC_FORDEV); - } - - ASSERT(sp->cmd_cookiecnt > 0); - - /* size of the next SGL chain elements list */ - sglen = sp->cmd_cookiecnt * sizeof (i2o_sge_chain_element_t); - - /* flags */ - put_flags_count_Flags(&sgl->FlagsCount, - I2O_SGL_FLAGS_CHAIN_POINTER_ELEMENT, acc_handle); - - /* - * instead of allocating a chuck of dma - * address here like isp driver, the - * trade of speed vs managing the free - * memory list. I don't want this - * to become kmem_alloc functions. - */ - if (ddi_dma_alloc_handle(dip, &i2ohba_dmasgl_attr, - DDI_DMA_DONTWAIT, NULL, &sp->sglbuf_dmahandle) - != DDI_SUCCESS) { - i2ohba_i_log(NULL, CE_WARN, "?i2ohba_scsi_start: " - "cannot allocate SGL's chain buffer handle"); - goto cleanup; - } - bound++; -#ifdef I2OHBA_DEBUG - ddi_dma_alloc_hdl++; -#endif - - if (ddi_dma_mem_alloc(sp->sglbuf_dmahandle, (size_t) - sglen, &dev_attr, DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, - NULL, (caddr_t *)&sp->sglbuf, &sp->sglrlen, - &sp->sglbuf_dmaacchandle) != DDI_SUCCESS) { - i2ohba_i_log(NULL, CE_WARN, "?i2ohba_scsi_start: " - "cannot allocate SGL's chain buffer memory"); - goto cleanup; - } - bound++; -#ifdef I2OHBA_DEBUG - ddi_dma_alloc_mem++; -#endif - - /* - * we passed in the sgl real length in transaction - * context because we need it to free the dma, - * but we set the chain element header with sglen - */ - put_flags_count_Count(&sgl->FlagsCount, sglen, acc_handle); - - put_flags_count_Flags(&sgl2->FlagsCount, - I2O_SGL_FLAGS_IGNORE_ELEMENT | - I2O_SGL_FLAGS_LAST_ELEMENT, acc_handle); - - put_flags_count_Count(&sgl2->FlagsCount, 0x1, acc_handle); - - /* fill in the SGL chain headers */ - sp->cmd_xfercount = 0; - cpsgl = (i2o_sge_chain_element_t *)sp->sglbuf; - - for (i = 0; i < sp->cmd_cookiecnt; i++, cpsgl++) { - - put_flags_count_Flags(&cpsgl->FlagsCount, - I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT, - sp->sglbuf_dmaacchandle); - - put_flags_count_Count(&cpsgl->FlagsCount, - sp->cmd_dmacookies[i].dmac_size, - sp->sglbuf_dmaacchandle); - - ddi_put32(sp->sglbuf_dmaacchandle, - &cpsgl->PhysicalAddress, - sp->cmd_dmacookies[i].dmac_address); - - sp->cmd_xfercount += - sp->cmd_dmacookies[i].dmac_size; - } - - DEBUGF(3, (CE_CONT, "cookiecnt is %x, ncookie is %x," - "cookie# is %d\n", sp->cmd_cookiecnt, sp->cmd_ncookies, - sp->cmd_cookie)); - DEBUGF(3, (CE_CONT, "cmd_xfercount is %lx\n", - sp->cmd_xfercount)); - - - /* mark the last chain pointer header as the last one */ - - cpsgl--; - put_flags_count_Flags(&cpsgl->FlagsCount, - I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | - I2O_SGL_FLAGS_LAST_ELEMENT | I2O_SGL_FLAGS_END_OF_BUFFER, - sp->sglbuf_dmaacchandle); - - if (ddi_dma_addr_bind_handle(sp->sglbuf_dmahandle, NULL, - (caddr_t)sp->sglbuf, sp->sglrlen, DDI_DMA_RDWR | - DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, NULL, - &sp->sglbuf_dmacookie, &count) != DDI_DMA_MAPPED) { - i2ohba_i_log(NULL, CE_WARN, "?i2ohba_scsi_start: " - "cannot bind SGL's bind handle"); - goto cleanup; - } -#ifdef I2OHBA_DEBUG - ddi_dma_bind_hdl++; -#endif - - DEBUGF(1, (CE_CONT, "start: cmd_dmacount=%lx," - " cmd_xfercount=%lx\n", - sp->cmd_dmacount, sp->cmd_xfercount)); - - ddi_put32(acc_handle, &req->ByteCount, sp->cmd_xfercount); - - ddi_put32(acc_handle, &sgl->PhysicalAddress, - (uint32_t)sp->sglbuf_dmacookie.dmac_address); - - } else { - ddi_put32(acc_handle, &req->ByteCount, 0); - put_flags_count_Flags(&sgl->FlagsCount, 0, acc_handle); - put_flags_count_Count(&sgl->FlagsCount, 0, acc_handle); - put_flags_count_Flags(&sgl2->FlagsCount, 0, acc_handle); - put_flags_count_Count(&sgl2->FlagsCount, 0, acc_handle); - } - - /* - * calculate deadline from pkt_time - * Instead of multiplying by 100 (ie. HZ), we multiply by 128 so - * we can shift and at the same time have a 28% grace period - * we ignore the rare case of pkt_time == 0 and deal with it - * in i2ohba_i_watch() - */ - cur_lbolt = ddi_get_lbolt(); - sp->cmd_deadline = cur_lbolt + (clock_t)(pkt->pkt_time * 256); - - I2OHBA_MUTEX_ENTER(i2ohba); - (void) i2ohba_i_req_insert(i2ohba, sp); - I2OHBA_MUTEX_EXIT(i2ohba); - /* - * Start the cmd. If NO_INTR, must wait for cmd reply/completion. - */ - if ((pkt->pkt_flags & FLAG_NOINTR) == 0) { - - /* - * need a list (or some sort of queue) so that - * when we need to flash the queue, ie: SCSI_BUS_RESET - * we'll have a way to do it (link list) - */ - val = i2o_msg_send(i2ohba->i2ohba_iophdl, req, msg_handle); - if (val != DDI_SUCCESS) - rval = TRAN_BUSY; /* I/O couldnot be started */ - } else { - val = i2o_msg_send(i2ohba->i2ohba_iophdl, req, msg_handle); - /* poll command */ - if (val == DDI_SUCCESS) { - i2ohba_i_polled_cmd_start(i2ohba, sp); - } else { - rval = TRAN_BUSY; - } - } - return (rval); - -cleanup: - - if (sp) { - if (bound) { - (void) ddi_dma_unbind_handle(sp->sglbuf_dmahandle); -#ifdef I2OHBA_DEBUG - ddi_dma_unbind++; -#endif - if (bound > 1) { - ddi_dma_mem_free(&sp->sglbuf_dmaacchandle); -#ifdef I2OHBA_DEBUG - ddi_dma_free_mem++; -#endif - } - ddi_dma_free_handle(&sp->sglbuf_dmahandle); -#ifdef I2OHBA_DEBUG - ddi_dma_bind_free++; -#endif - } - - sp->cmd_flags = (sp->cmd_flags & ~CFLAG_IN_TRANSPORT); - i2ohba->i2ohba_counter--; - pkt->pkt_reason = 0; - } - - /* return MFA to IOP */ - if (req) { - req->StdMessageFrame.VersionOffset = 0; - req->StdMessageFrame.MsgFlags = 0; - ddi_put16(acc_handle, &req->StdMessageFrame.MessageSize, 3); - put_msg_TargetAddress(&req->StdMessageFrame, 0, acc_handle); - put_msg_InitiatorAddress(&req->StdMessageFrame, 0, acc_handle); - put_msg_Function(&req->StdMessageFrame, I2O_UTIL_NOP, - acc_handle); - (void) i2o_msg_send(i2ohba->i2ohba_iophdl, req, msg_handle); - } - - ASSERT(I2OHBA_MUTEX_OWNED(i2ohba) == 0 || ddi_in_panic()); - return (TRAN_BUSY); -} - - -/* - * Function name : i2ohba_i_req_insert() - * - * Return Values : void - * - * Usage : called by i2ohba_scsi_start(). - * - * Description : Insert the i2ohba_cmd into the double - * link list in FIFO fashion. - * - * Context : called by SCSA frame work. - */ -static void -i2ohba_i_req_insert(struct i2ohba *i2ohba, struct i2ohba_cmd *sp) -{ - struct i2ohba_cmd *head = i2ohba->i2ohba_reqhead; - - sp->cmd_forw = head; - if (head != NULL) { - i2ohba->i2ohba_reqhead->cmd_backw = sp; - } else { - i2ohba->i2ohba_reqtail = sp; - } - i2ohba->i2ohba_reqhead = sp; - sp->cmd_backw = NULL; - -} - - -/* - * Function name : i2ohba_i_req_remove() - * - * Return Values : void - * - * Usage : called by i2ohba_callback(). - * called by i2ohba_scsi_start() if i2o_msg_send() - * failed. - * Description : remove a i2ohba_cmd from the double link list - * - * Context : called by SCSA frame work. - */ -static void -i2ohba_i_req_remove(struct i2ohba *i2ohba, struct i2ohba_cmd *sp) -{ - struct i2ohba_cmd *tail = i2ohba->i2ohba_reqtail; - struct i2ohba_cmd *tmp; - - for (tmp = tail; tmp != NULL; tmp = tmp->cmd_backw) { - if (tmp == sp) { - if (tmp->cmd_backw) - tmp->cmd_backw->cmd_forw = tmp->cmd_forw; - else - i2ohba->i2ohba_reqhead = tmp->cmd_forw; - - if (tmp->cmd_forw) - tmp->cmd_forw->cmd_backw = tmp->cmd_backw; - else - i2ohba->i2ohba_reqtail = tmp->cmd_backw; - - tmp->cmd_backw = NULL; - tmp->cmd_forw = NULL; - break; - - } - } -} - -/* - * Function name : i2ohba_callback() - * - * Return Values : None - * - * Context: : called by interrupt thread. - */ - -void -i2ohba_callback(i2o_message_frame_t *msg, ddi_acc_handle_t acc_handle) -{ - - i2o_single_reply_message_frame_t *reply; - struct i2ohba *i2ohba; - struct scsi_pkt *pkt; - struct i2ohba_cmd *sp; - uint8_t reqstatus; - - reply = (i2o_single_reply_message_frame_t *)msg; - - - ASSERT(I2O_SCSI_SCB_EXEC == get_msg_Function( - &reply->StdMessageFrame, acc_handle)); - - sp = (struct i2ohba_cmd *)(uintptr_t)ddi_get32(acc_handle, - &reply->TransactionContext); - - ASSERT(sp); - - i2ohba = CMD2I2OHBA(sp); - I2OHBA_MUTEX_ENTER(i2ohba); - (void) i2ohba_i_req_remove(i2ohba, sp); - I2OHBA_MUTEX_EXIT(i2ohba); - - if (sp->cmd_dmahandle) { - (void) ddi_dma_sync(sp->cmd_dmahandle, - sp->cmd_dma_offset, sp->cmd_dma_len, - DDI_DMA_SYNC_FORKERNEL); - } - - reqstatus = ddi_get8(acc_handle, &reply->ReqStatus); - DEBUGF(1, (CE_CONT, "reqstatus %x\n", reqstatus)); - pkt = CMD2PKT(sp); - - /* - * First filter the reqstatus - * check for any special errors - */ - switch (reqstatus) { - - case I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER: - /* - * With paritial transfer, we want to make - * sure it is an USCSI cmd - */ - if ((pkt->pkt_flags >> 16) == 0) - pkt->pkt_reason = CMD_TRAN_ERR; - - sp->cmd_flags |= CFLAG_FINISHED; - i2ohba_i_pkt_comp(reply, acc_handle, sp); - - return; - - case I2O_REPLY_STATUS_SUCCESS: - /* - * With successful completetion, only the ReqStatus - * field is set to reflect sucessful completion, the - * DetailedStatusCode is set to zero, the TransferCount - * field indicates the actual amount of data transferred. - * There is no StatusData. - */ - - sp->cmd_flags |= CFLAG_FINISHED; - i2ohba_i_pkt_comp(reply, acc_handle, sp); - - return; - - /* XXLWXX Error code handling */ - case I2O_REPLY_STATUS_ABORT_DIRTY: - case I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER: - case I2O_REPLY_STATUS_ERROR_DIRTY: - case I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER: - case I2O_REPLY_STATUS_PROCESS_ABORT_DIRTY: - case I2O_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER: - case I2O_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER: - case I2O_REPLY_STATUS_PROGRESS_REPORT: - /* - * If message has failed due to aborted by hosts, - * error in execution, due to system command or reconfig. - * failed the request. - */ - case I2O_REPLY_STATUS_TRANSACTION_ERROR: - default: - pkt->pkt_reason = CMD_TRAN_ERR; - sp->cmd_flags |= CFLAG_FINISHED; - i2ohba_i_pkt_comp(reply, acc_handle, sp); -#ifdef I2OHBA_DEBUG - DEBUGF(1, (CE_CONT, - "?i2ohba_callback: Reply Failed")); -#endif - break; - - } -} - -/* - * Function name : i2ohba_i_pkt_complete() - * - * Return Values : none - * - * Description : - * callback into target driver - * argument is a NULL-terminated list of packets - * copy over stuff from response packet - * - * Context : Can be called by interrupt thread. - */ -static void -i2ohba_i_pkt_comp(i2o_single_reply_message_frame_t *reply, ddi_acc_handle_t - acc_handle, struct i2ohba_cmd *sp) -{ - i2o_scsi_success_reply_message_frame_t *replysuc; - i2o_scsi_error_reply_message_frame_t *replyerr; - struct i2ohba *i2ohba; - struct scsi_pkt *pkt; - uint32_t transcount; - uint32_t autocount; - uint16_t adptrstatus; - uint16_t detailstat; - uint16_t messagesize; - uint8_t devstatus; - - i2ohba = CMD2I2OHBA(sp); - ASSERT(I2OHBA_MUTEX_OWNED(i2ohba) == 0 || ddi_in_panic()); - - pkt = CMD2PKT(sp); - - ASSERT(sp->cmd_flags & CFLAG_FINISHED); - - if (sp->cmd_flags & CFLAG_DMAVALID) { - if (ddi_dma_unbind_handle(sp->sglbuf_dmahandle) != - DDI_SUCCESS) { - i2ohba_i_log(NULL, CE_WARN, "?i2ohba_scsi_dmafree: " - "ddi_dma_unbind_handle() for sglbuf failed"); - /*NOTREACHED*/ - } -#ifdef I2OHBA_DEBUG - ddi_dma_unbind++; -#endif - ddi_dma_mem_free(&sp->sglbuf_dmaacchandle); -#ifdef I2OHBA_DEBUG - ddi_dma_free_mem++; -#endif - ddi_dma_free_handle(&sp->sglbuf_dmahandle); -#ifdef I2OHBA_DEBUG - ddi_dma_bind_free++; -#endif - sp->sglbuf_dmahandle = NULL; - } - - replysuc = (i2o_scsi_success_reply_message_frame_t *)reply; - - detailstat = ddi_get16(acc_handle, &reply->DetailedStatusCode); - devstatus = (uint8_t)(detailstat & I2O_SCSI_DEVICE_DSC_MASK); - /* this is a workaround for 0x3 and 0x9 LSB is being ORed */ - devstatus = devstatus & 0xfe; - DEBUGF(1, (CE_CONT, "devstatus %x\n", devstatus)); - adptrstatus = detailstat & I2O_SCSI_HBA_DSC_MASK; - DEBUGF(1, (CE_CONT, "adptrstatus %x\n", adptrstatus)); - - transcount = ddi_get32(acc_handle, &replysuc->TransferCount); - - if (detailstat == 0) { - pkt->pkt_scbp[0] = - (uint8_t)(detailstat & I2O_SCSI_DEVICE_DSC_MASK); - pkt->pkt_reason = CMD_CMPLT; - pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET | - STATE_SENT_CMD | STATE_XFERRED_DATA; - pkt->pkt_statistics = 0; - pkt->pkt_resid = sp->cmd_xfercount - transcount; - } else { - replyerr = (i2o_scsi_error_reply_message_frame_t *)reply; - - /* - * devstatus: SCSI_SUCESS 0, SCSI_CHECK_COND 2, - * SCSI_BUSY 8, SCSI_RES_CONFLICT 18, - * SCSI_CMD_TERM 22, SCSI_TASK_SET_FULL 28, - * SCSI_ACA_ACTIVE 30 - */ - messagesize = ddi_get16(acc_handle, - &replyerr->StdReplyFrame.StdMessageFrame.MessageSize); - - pkt->pkt_scbp[0] = devstatus; - - if (devstatus == I2O_SCSI_DSC_CHECK_CONDITION) { - pkt->pkt_reason = CMD_CMPLT; - pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET | - STATE_SENT_CMD | STATE_XFERRED_DATA; - pkt->pkt_statistics = 0; - goto arqchk; - } - - /* SYM HDM problem, can't recognized USCSI cmd well */ - if ((devstatus == I2O_SCSI_DSC_BUSY) && - (transcount != 0) && ((pkt->pkt_flags >> 16) != 0)) { - pkt->pkt_reason = CMD_CMPLT; - pkt->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET | - STATE_SENT_CMD | STATE_XFERRED_DATA; - pkt->pkt_statistics = 0; - pkt->pkt_resid = sp->cmd_xfercount - transcount; - pkt->pkt_scbp[0] = STATUS_GOOD; - goto done; - } - - - switch (adptrstatus) { - - case I2O_SCSI_HBA_DSC_AUTOSENSE_FAILED: - pkt->pkt_reason = CMD_INCOMPLETE; - pkt->pkt_state |= STATE_ARQ_DONE; - break; - - /* bus reset */ - case I2O_SCSI_HBA_DSC_SCSI_BUS_RESET: - pkt->pkt_reason = CMD_RESET; - pkt->pkt_statistics |= STAT_BUS_RESET; - /* Do we need to call notify_callback? */ - scsi_hba_reset_notify_callback( - I2OHBA_REQ_MUTEX(i2ohba), - &i2ohba->i2ohba_reset_notify_listf); - break; - - /* cmd terminated */ - case I2O_SCSI_HBA_DSC_REQUEST_TERMINATED: - pkt->pkt_reason = CMD_TERMINATED; - - pkt->pkt_statistics |= STAT_TERMINATED; - break; - - /* request aborted */ - case I2O_SCSI_HBA_DSC_NO_NEXUS: - pkt->pkt_reason = CMD_ABORTED; - pkt->pkt_statistics |= STAT_ABORTED; - break; - - /* parity error */ - case I2O_SCSI_HBA_DSC_PARITY_ERROR_FAILURE: - pkt->pkt_reason = CMD_TRAN_ERR; - pkt->pkt_statistics |= STAT_PERR; - i2ohba_i_log(NULL, CE_WARN, "?Parity Error"); - break; - - /* data overrun */ - case I2O_SCSI_HBA_DSC_DATA_OVERRUN: - pkt->pkt_reason = CMD_DATA_OVR; - pkt->pkt_state |= STATE_GOT_BUS | - STATE_GOT_TARGET | STATE_SENT_CMD | - STATE_XFERRED_DATA; - break; - - /* cmd complete with error */ - case I2O_SCSI_HBA_DSC_LUN_ALREADY_ENABLED: - case I2O_SCSI_HBA_DSC_COMPLETE_WITH_ERROR: - /* devstatus should be busy/checkcond */ - pkt->pkt_reason = CMD_CMPLT; - break; - - /* cmd aborted by request or aborted by time */ - case I2O_SCSI_HBA_DSC_REQUEST_ABORTED: - if (sp->cmd_flags & CFLAG_DELAY_TIMEOUT) { - pkt->pkt_reason = CMD_TIMEOUT; - pkt->pkt_statistics |= STAT_TIMEOUT - | STAT_ABORTED; - } else { - pkt->pkt_reason = CMD_ABORTED; - pkt->pkt_statistics |= STAT_ABORTED; - } - break; - - /* cmd timeout */ - case I2O_SCSI_HBA_DSC_COMMAND_TIMEOUT: - pkt->pkt_reason = CMD_TIMEOUT; - pkt->pkt_statistics |= STAT_TIMEOUT; - break; - - /* CDB received */ - case I2O_SCSI_HBA_DSC_CDB_RECEIVED: - pkt->pkt_reason = CMD_INCOMPLETE; - pkt->pkt_state |= STATE_SENT_CMD | - STATE_GOT_BUS | STATE_GOT_TARGET | - STATE_XFERRED_DATA; - break; - - /* device reset msg send */ - case I2O_SCSI_HBA_DSC_BDR_MESSAGE_SENT: - pkt->pkt_reason = CMD_RESET; - pkt->pkt_statistics |= STAT_DEV_RESET; - break; - - /* unexpected bus free */ - case I2O_SCSI_HBA_DSC_UNEXPECTED_BUS_FREE: - pkt->pkt_reason = CMD_UNX_BUS_FREE; - break; - - /* cmd failed, transport error */ - case I2O_SCSI_HBA_DSC_ADAPTER_BUSY: - case I2O_SCSI_HBA_DSC_SEQUENCE_FAILURE: - case I2O_SCSI_HBA_DSC_BUS_BUSY: - case I2O_SCSI_HBA_DSC_QUEUE_FROZEN: - case I2O_SCSI_HBA_DSC_UNABLE_TO_ABORT: - case I2O_SCSI_HBA_DSC_UNABLE_TO_TERMINATE: - case I2O_SCSI_HBA_DSC_RESOURCE_UNAVAILABLE: - pkt->pkt_reason = CMD_TRAN_ERR; - break; - - /* failed command, retry? */ - case I2O_SCSI_HBA_DSC_REQUEST_INVALID: - case I2O_SCSI_HBA_DSC_PATH_INVALID: - case I2O_SCSI_HBA_DSC_INVALID_CDB: - case I2O_SCSI_HBA_DSC_LUN_INVALID: - case I2O_SCSI_HBA_DSC_SELECTION_TIMEOUT: - pkt->pkt_state |= STATE_GOT_BUS; - pkt->pkt_reason = CMD_INCOMPLETE; - break; - - case I2O_SCSI_HBA_DSC_DEVICE_NOT_PRESENT: - case I2O_SCSI_HBA_DSC_FUNCTION_UNAVAILABLE: - pkt->pkt_reason = CMD_INCOMPLETE; - break; - - /* what? NO adapter! shutdown now! */ - case I2O_SCSI_HBA_DSC_NO_ADAPTER: - i2ohba->i2ohba_shutdown = 1; - break; - - case I2O_SCSI_HBA_DSC_SCSI_TID_INVALID: - case I2O_SCSI_HBA_DSC_SCSI_IID_INVALID: - default: /* failed cmd, retry */ - pkt->pkt_state |= STATE_GOT_BUS; - pkt->pkt_reason = CMD_TRAN_ERR; - break; - - - } - - pkt->pkt_resid = sp->cmd_xfercount; - - /* - * was there auto request sense info? - */ -arqchk: if (messagesize > - sizeof (i2o_scsi_success_reply_message_frame_t)) { - autocount = ddi_get32(acc_handle, - &replyerr->AutoSenseTransferCount); - - /* currently uses the DATA_IN_MESSAGE, only 40 bytes */ - if (autocount) { - pkt->pkt_state |= STATE_ARQ_DONE; - i2ohba_i_handle_arq(replyerr, sp, autocount); - } - } - - } - - -done: DEBUGF(1, (CE_CONT, "transfer=0x%x, resid=0x%lx\n", transcount, - pkt->pkt_resid)); - - /* - * if data was xferred and this was an IOPB, we need - * to do a dma sync - */ - if ((sp->cmd_flags & CFLAG_CMDIOPB) && - (pkt->pkt_state & STATE_XFERRED_DATA)) { - (void) ddi_dma_sync(sp->cmd_dmahandle, - sp->cmd_dma_offset, sp->cmd_dma_len, - DDI_DMA_SYNC_FORCPU); - } - - - ASSERT(sp->cmd_flags & CFLAG_IN_TRANSPORT); - ASSERT(sp->cmd_flags & CFLAG_FINISHED); - ASSERT((sp->cmd_flags & CFLAG_COMPLETED) == 0); - - sp->cmd_flags = ((sp->cmd_flags & ~CFLAG_IN_TRANSPORT) & - ~CFLAG_DELAY_TIMEOUT) | CFLAG_COMPLETED; - i2ohba->i2ohba_counter--; - - /* - * Call packet completion routine if FLAG_NOINTR is not set. - * If FLAG_NOINTR is set turning on CFLAG_COMPLETED in line - * above will cause busy wait loop in - * i2ohba_i_polled_cmd_start() to exit. - */ - if (((pkt->pkt_flags & FLAG_NOINTR) == 0) && - pkt->pkt_comp) { - (*pkt->pkt_comp)(pkt); - } - - ASSERT(I2OHBA_MUTEX_OWNED(i2ohba) == 0 || ddi_in_panic()); -} - - -/* - * Function name : i2ohba_i_handle_arq() - * - * Description : called on an autorequest sense condition, sets up arqstat - * - * Context : Can be called from different kernel process threads. - * Can be called by interrupt thread. - */ -static void -i2ohba_i_handle_arq(i2o_scsi_error_reply_message_frame_t *replyerr, - struct i2ohba_cmd *sp, int aqcount) -{ - char status; - struct scsi_pkt *pkt = CMD2PKT(sp); - - if (sp->cmd_scblen >= sizeof (struct scsi_arq_status)) { - struct scsi_arq_status *arqstat; - - DEBUGF(1, (CE_CONT, "tgt %d.%d: auto request sense", - TGT(sp), LUN(sp))); - - /* clear the pkt_scbp struct */ - arqstat = (struct scsi_arq_status *)(pkt->pkt_scbp); - status = pkt->pkt_scbp[0]; - bzero(arqstat, sizeof (struct scsi_arq_status)); - - /* - * I2O does not provide statistics for request sense, - * so use same statistics as the original cmd. - */ - arqstat->sts_rqpkt_statistics = pkt->pkt_statistics; - arqstat->sts_rqpkt_state = - (STATE_GOT_BUS | STATE_GOT_TARGET | - STATE_SENT_CMD | STATE_XFERRED_DATA | STATE_GOT_STATUS); - if (aqcount < sizeof (struct scsi_extended_sense)) { - arqstat->sts_rqpkt_resid = - sizeof (struct scsi_extended_sense) - aqcount; - - } - bcopy(replyerr->SenseData, - &arqstat->sts_sensedata, - (sizeof (struct scsi_extended_sense) < - I2O_SCSI_SENSE_DATA_SZ) ? - sizeof (struct scsi_extended_sense) : - I2O_SCSI_SENSE_DATA_SZ); - - /* - * restore status which was wiped out by bzero - */ - pkt->pkt_scbp[0] = status; - - DEBUGF(1, (CE_CONT, "arq: %x %x %x %x %x %x %x", - replyerr->SenseData[0], replyerr->SenseData[1], - replyerr->SenseData[2], replyerr->SenseData[3], - replyerr->SenseData[4], replyerr->SenseData[5], - replyerr->SenseData[6])); - return; - } - /* - * Failed cmd auto sense data; can't copy over ARQ data, - */ - DEBUGF(1, (CE_CONT, "Failed cmd, possible sense data")); - DEBUGF(1, (CE_CONT, "arq: %x %x %x %x %x %x %x", - replyerr->SenseData[0], replyerr->SenseData[1], - replyerr->SenseData[2], replyerr->SenseData[3], - replyerr->SenseData[4], replyerr->SenseData[5], - replyerr->SenseData[6])); -} - - -/* - * Function name : i2ohba_i_polled_cmd_start() - * - * Return Values : TRAN_ACCEPT if transaction was accepted - * TRAN_BUSY if I/O could not be started - * TRAN_ACCEPT if I/O timed out, pkt fields indicate error - * - * Description : Busy waits for I/O to complete or timeout. - * NOTE: This function returns void because the cmd - * has already started in scsi_start() before this - * function is called. So no need to return rval. - * - * Context : Can be called from different kernel process threads. - * Can be called by interrupt thread. - */ -static void -i2ohba_i_polled_cmd_start(struct i2ohba *i2ohba, struct i2ohba_cmd *sp) -{ - int delay_loops; - struct scsi_pkt *pkt = CMD2PKT(sp); - - ASSERT(I2OHBA_MUTEX_OWNED(i2ohba) == 0 || ddi_in_panic()); - - /* - * set timeout to SCSI_POLL_TIMEOUT for non-polling - * commands that do not have this field set - */ - if (pkt->pkt_time == 0) { - pkt->pkt_time = SCSI_POLL_TIMEOUT; - } - - ASSERT(pkt->pkt_flags & FLAG_NOINTR); - - delay_loops = I2OHBA_TIMEOUT_DELAY( - (pkt->pkt_time + (2 * I2OHBA_GRACE)), - I2OHBA_NOINTR_POLL_DELAY_TIME); - - /* - * busy wait for command to finish - * ie. till CFLAG_COMPLETED is set - */ - while ((sp->cmd_flags & CFLAG_COMPLETED) == 0) { - drv_usecwait(I2OHBA_NOINTR_POLL_DELAY_TIME); - if (--delay_loops <= 0) { - - if ((i2ohba_scsi_reset(&pkt->pkt_address, - RESET_TARGET)) == 0) { - mutex_enter(I2OHBA_REQ_MUTEX(i2ohba)); - i2ohba_i_fatal_error(i2ohba); - mutex_exit(I2OHBA_REQ_MUTEX(i2ohba)); - } - pkt->pkt_reason = CMD_TIMEOUT; - pkt->pkt_statistics |= STAT_BUS_RESET | - STAT_TIMEOUT; - sp->cmd_flags = ((sp->cmd_flags & - ~CFLAG_IN_TRANSPORT) & ~CFLAG_DELAY_TIMEOUT) - | CFLAG_COMPLETED | CFLAG_FINISHED; - i2ohba->i2ohba_counter--; - break; - } - } - - ASSERT(I2OHBA_MUTEX_OWNED(i2ohba) == 0 || ddi_in_panic()); - -} - - - -/* - * Function name : i2ohba_i_watch() - * - * Return Values : none - * Description : I2OHBA deadman timer routine. - * - * Given that the i2ohba's request queue is double link list - * in FIFO fashion, the tail should be pointing at the oldest - * cmd. However, each command has different timeout value set - * by the target driver, if any of them has timeout then we - * will call fatal_error(). - * - * A hung i2ohba controller is detected by failure to complete - * cmds within a timeout interval (including grace period for - * i2ohba error recovery). All target error recovery is handled - * directly by the i2ohba. - * - * If i2ohba hungs, restart by resetting the i2ohba's HBA/BUS and - * flushing the double linked list (via i2ohba_i_qflush()). - * - * Tagged queueing gives us other headaches since we cannot know - * exactly when a command starts. For example, a command with a - * 2-hour timeout, will cause a second command with a 60-second timeout - * to be timed-out. We won't worry about it now, but will later - * - * Context : Can be called by timeout thread. - */ - -static void -i2ohba_i_watch(void *arg) -{ - struct i2ohba *i2ohba = (struct i2ohba *)arg; - clock_t cur_lbolt; - clock_t deadline; - struct i2ohba_cmd *sp; - struct scsi_pkt *pkt; - - - if (i2ohba->i2ohba_shutdown) { - return; - } - - I2OHBA_MUTEX_ENTER(i2ohba); - - if ((cur_lbolt = ddi_get_lbolt()) != 0) { - for (sp = i2ohba->i2ohba_reqtail; sp != NULL; - sp = sp->cmd_backw) { - pkt = CMD2PKT(sp); - deadline = sp->cmd_deadline; - if ((deadline - cur_lbolt <= 0) && (pkt->pkt_time)) { - if (!(sp->cmd_flags & CFLAG_DELAY_TIMEOUT)) { - /* report time out */ - i2ohba_i_log(NULL, CE_CONT, - "?i2ohba_i_watch: " - "Exend cmd timeout on target %d.%d", - TGT(sp), LUN(sp)); - /* reset timeout vaule for delay */ - sp->cmd_deadline = cur_lbolt + - (clock_t)(pkt->pkt_time * 192); - /* set DELAY_TIMEOUT indicator */ - sp->cmd_flags |= CFLAG_DELAY_TIMEOUT; - /* set throttle on */ - i2ohba->i2ohba_throttle++; - } else { - i2ohba_i_req_remove(i2ohba, sp); - pkt->pkt_reason = CMD_TIMEOUT; - pkt->pkt_statistics |= STAT_TIMEOUT; - sp->cmd_flags = ((sp->cmd_flags - & ~CFLAG_DELAY_TIMEOUT) - & ~CFLAG_IN_TRANSPORT) - | CFLAG_COMPLETED | CFLAG_FINISHED; - i2ohba_i_log(NULL, CE_WARN, - "?i2ohba_i_watch: " - "Cmd timeout on target %d.%d", - TGT(sp), LUN(sp)); - I2OHBA_MUTEX_EXIT(i2ohba); - if (((pkt->pkt_flags & FLAG_NOINTR) - == 0) && pkt->pkt_comp) { - (*pkt->pkt_comp)(pkt); - } - I2OHBA_MUTEX_ENTER(i2ohba); - } - } - } - - DEBUGF(2, (CE_CONT, "?throttle=%d", i2ohba->i2ohba_throttle)); - if ((i2ohba->i2ohba_reqtail == NULL) && - (i2ohba->i2ohba_reqhead == NULL)) { - i2ohba->i2ohba_throttle = 0; - } - - } - - if (i2ohba->i2ohba_need_prop_update) { - int i; - - for (i = 0; i < N_I2OHBA_TARGETS_WIDE; i++) { - if (i2ohba->i2ohba_need_prop_update & (1 << i)) { - i2ohba_i_update_props(i2ohba, i); - } - } - - i2ohba->i2ohba_need_prop_update = 0; - - } - - /* - * Set up next timeout - */ - i2ohba->i2ohba_timeout_id = timeout(i2ohba_i_watch, i2ohba, - i2ohba_tick); - I2OHBA_MUTEX_EXIT(i2ohba); -} - - - -/* - * Function name : i2ohba_i_fatal_error() - * - * Return Values : none - * - * Description : - * Isp fatal error recovery: - * Reset the i2o and flush the active queues and attempt restart. - * This should only happen in case of a firmware bug or hardware - * death. Flushing is from backup queue as I2O cannot be trusted. - * - * Context : Can be called from different kernel process threads. - * Can be called by interrupt thread. - * i2ohba_request_mutex is held. - */ -static void -i2ohba_i_fatal_error(struct i2ohba *i2ohba) -{ - /* - * hold off starting new requests by grabbing the request mutex - */ - ASSERT(I2OHBA_MUTEX_OWNED(i2ohba)); - - /* - * If shutdown flag is set than no need to do - * fatal error recovery. - */ - if (i2ohba->i2ohba_shutdown) { - return; - } - - i2ohba_i_log(NULL, CE_WARN, "?i2ohba_i_fatal_error: " - "Fatal error, resetting interface"); - - i2ohba_i_print_state(i2ohba); - - (void) i2ohba_i_reset_interface(i2ohba, I2OHBA_FORCE_BUS_RESET); - - i2ohba_i_qflush(i2ohba, (uint16_t)0, (uint16_t)N_I2OHBA_TARGETS_WIDE); - - (void) scsi_hba_reset_notify_callback(I2OHBA_REQ_MUTEX(i2ohba), - &i2ohba->i2ohba_reset_notify_listf); - - ASSERT(I2OHBA_MUTEX_OWNED(i2ohba)); -} - - -/* - * Function name : i2ohba_i_qflush() - * - * Return Values : none - * Description : - * Flush i2ohba queues over range specified - * from start_tgt to end_tgt. Flushing goes from oldest to newest - * to preserve some cmd ordering. - * This is used for i2o crash recovery as normally i2o takes - * care of target or bus problems. - * - * Context : Can be called from different kernel process threads. - * i2ohba_i_fatal_error() - * i2ohba_i_reset_interface() - * Can be called by interrupt thread. - */ -static void -i2ohba_i_qflush(struct i2ohba *i2ohba, uint16_t start_tgt, uint16_t end_tgt) -{ - struct i2ohba_cmd *sp; - struct scsi_pkt *pkt; - - ASSERT(start_tgt <= end_tgt); - ASSERT(I2OHBA_MUTEX_OWNED(i2ohba)); - - - /* - * If flushing active queue, start with current free slot - * ie. oldest request, to preserve some order. - */ - sp = i2ohba->i2ohba_reqtail; - for (; sp != NULL; sp = i2ohba->i2ohba_reqtail->cmd_backw) { - if ((TGT(sp) >= start_tgt) && (TGT(sp) <= end_tgt)) { - - pkt = CMD2PKT(sp); - pkt->pkt_reason = CMD_RESET; - pkt->pkt_statistics |= STAT_DEV_RESET; - (void) i2ohba_i_req_remove(i2ohba, sp); - sp->cmd_flags |= CFLAG_FINISHED; - sp->cmd_flags = ((sp->cmd_flags & ~CFLAG_IN_TRANSPORT) - & ~CFLAG_DELAY_TIMEOUT) | CFLAG_COMPLETED; - i2ohba->i2ohba_counter--; - if (((pkt->pkt_flags & FLAG_NOINTR) == 0) && - pkt->pkt_comp) { - (*pkt->pkt_comp)(pkt); - } - - } - } - - ASSERT(I2OHBA_MUTEX_OWNED(i2ohba)); -} - - -/* - * Function name : i2ohba_scsi_abort() - * - * Return Values : 0 - abort failed - * 1 - abort succeeded - * Description : - * SCSA interface routine to abort pkt(s) in progress. - * Abort the pkt specified or NULL pkt, abort ALL pkts. - * - * Context : Can be called from different kernel process threads. - * Can be called by interrupt thread. - */ -static int -i2ohba_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt) -{ - struct i2ohba *i2ohba = ADDR2I2OHBA(ap); - struct i2ohba_cmd *sp = PKT2CMD(pkt); - uint16_t arg, tid; - int rval = 0; - - ASSERT(mutex_owned(I2OHBA_REQ_MUTEX(i2ohba)) == 0 || ddi_in_panic()); - - arg = (uint16_t)ap->a_target; - - if (i2ohba->i2ohba_tgt_id_map[arg] == NULL) - return (rval); - - tid = i2ohba->i2ohba_tgt_id_map[arg]->tid; - - /* - * hold off new requests, we need the req mutex anyway so noone - * can access the queue. - */ - I2OHBA_MUTEX_ENTER(i2ohba); - - i2ohba_i_log(NULL, CE_CONT, "?i2ohba_scsi_abort: " - "aborting pkt 0x%p", (void *)pkt); - - - if (pkt) { - if (i2ohba_i_reset_abort(i2ohba, tid, I2O_SCSI_SCB_ABORT, sp)) { - I2OHBA_MUTEX_EXIT(i2ohba); - return (0); - } - } else { - if (i2ohba_i_reset_abort(i2ohba, tid, I2O_SCSI_SCB_ABORT, 0)) { - I2OHBA_MUTEX_EXIT(i2ohba); - return (0); - } - } - - I2OHBA_MUTEX_EXIT(i2ohba); - return (1); -} - - -/* - * Function name : i2ohba_scsi_reset() - * - * Return Values : 0 - reset failed - * 1 - reset succeeded - * Description : - * SCSA interface routine to perform scsi resets on either - * a specified target or the bus (default). - * - * Context : Can be called from different kernel process threads. - * Can be called by interrupt thread. - */ -static int -i2ohba_scsi_reset(struct scsi_address *ap, int level) -{ - struct i2ohba *i2ohba = ADDR2I2OHBA(ap); - uint16_t arg, tid; - int rval = 0; - - ASSERT(mutex_owned(I2OHBA_REQ_MUTEX(i2ohba)) == 0 || ddi_in_panic()); - - arg = (uint16_t)ap->a_target; - - if (i2ohba->i2ohba_tgt_id_map[arg] == NULL) - return (rval); - - tid = i2ohba->i2ohba_tgt_id_map[arg]->tid; - - I2OHBA_MUTEX_ENTER(i2ohba); - /* - * hold off new requests, we need the req mutex. - */ - - if (level == RESET_TARGET) { - i2ohba_i_log(NULL, CE_CONT, - "?i2ohba_scsi_reset: reset target %d", ap->a_target); - - if (i2ohba_i_reset_abort(i2ohba, tid, - I2O_SCSI_DEVICE_RESET, 0)) { - return (rval); - } - } else { - i2ohba_i_log(NULL, CE_CONT, "?i2ohba_scsi_reset: reset bus"); - - tid = i2ohba->i2ohba_tid; - if (i2ohba_i_reset_abort(i2ohba, tid, I2O_HBA_BUS_RESET, 0)) { - return (rval); - } - (void) scsi_hba_reset_notify_callback( - I2OHBA_REQ_MUTEX(i2ohba), - &i2ohba->i2ohba_reset_notify_listf); - /* wait for 3 sec after a reset */ - drv_usecwait((clock_t)i2ohba->i2ohba_scsi_reset_delay * 1000); - } - I2OHBA_MUTEX_EXIT(i2ohba); - return (1); -} - -/* - * Function name: i2ohba_i_reset_abort() - * - * Return Values: 0 - success - * -1 - fail reset - * - * Description : - * Reset either the HBA Adpter or Bus Reset - * This function is called from i2ohba_i_reset_interface() - * i2ohba_scsi_abort() - * i2ohba_scsi_reset() - * - * Context : Can be called from different kernel process threads. - * Can not be called by interrupt thread because it - * waits on the reply message. - */ -static int -i2ohba_i_reset_abort(struct i2ohba *i2ohba, uint16_t tid, int action, - struct i2ohba_cmd *cmd) -{ - int rval = -1; - i2o_message_frame_t *msgptr; - i2o_scsi_scb_abort_message_t *abortmsg; - i2o_msg_handle_t msg_handle; - ddi_acc_handle_t acc_handle; - struct i2ohba_util *sp; - - if (i2o_msg_alloc(i2ohba->i2ohba_iophdl, I2O_MSG_SLEEP, NULL, - (void *)&msgptr, &msg_handle, &acc_handle) != DDI_SUCCESS) { - i2ohba_i_log(NULL, CE_WARN, "?i2ohba_i_reset_abort: " - "i2o_msg_alloc failed"); - return (rval); - } - - if ((action == I2O_SCSI_SCB_ABORT) && (cmd == NULL)) - action = I2O_SCSI_DEVICE_RESET; - - abortmsg = (i2o_scsi_scb_abort_message_t *)msgptr; - /* - * construct a i2o_hba_bus_reset_message - */ - abortmsg->StdMessageFrame.VersionOffset = 0x01; - abortmsg->StdMessageFrame.MsgFlags = 0; - if (action == I2O_SCSI_SCB_ABORT) - ddi_put16(acc_handle, &abortmsg->StdMessageFrame.MessageSize, - sizeof (i2o_scsi_scb_abort_message_t) >> 2); - else - ddi_put16(acc_handle, &abortmsg->StdMessageFrame.MessageSize, - sizeof (i2o_scsi_device_reset_message_t) >> 2); - put_msg_TargetAddress(&abortmsg->StdMessageFrame, tid, acc_handle); - put_msg_InitiatorAddress(&abortmsg->StdMessageFrame, I2O_OSM_TID, - acc_handle); - put_msg_Function(&abortmsg->StdMessageFrame, action, acc_handle); - ddi_put32(acc_handle, - (uint32_t *)&abortmsg->StdMessageFrame.InitiatorContext, - (uint32_t)i2ohba_utilmsg_comp); - - /* - * allocating synchronized status buffer - */ - sp = kmem_alloc(sizeof (struct i2ohba_util), KM_SLEEP); - - ddi_put32(acc_handle, &abortmsg->TransactionContext, - (uint32_t)(uintptr_t)sp); - - if (cmd) - ddi_put32(acc_handle, &abortmsg->TransactionContextToAbort, - (uint32_t)(uintptr_t)cmd); - - /* - * initialized a mutex and cond variable to - * send message to IOP, and wait for it to signal back - */ - sp->mutex = I2OHBA_RESET_MUTEX(i2ohba); - sp->cv = I2OHBA_RESET_CV(i2ohba); - mutex_enter(sp->mutex); - sp->wakeup = UTIL_MSG_SLEEP; - sp->status = 0; - (void) i2o_msg_send(i2ohba->i2ohba_iophdl, msgptr, msg_handle); - while (!sp->wakeup) - cv_wait(sp->cv, sp->mutex); - mutex_exit(sp->mutex); - - /* - * process reply message - */ - - switch (sp->status) { - case I2O_REPLY_STATUS_SUCCESS: - rval = 0; - break; - default: - /* - * Failed the reset for now, - * we can also parse the AdapterStatus - * and retry if needed - */ - break; - } - -cleanup: - if (sp) - kmem_free(sp, sizeof (struct i2ohba_util)); - - return (rval); -} - - -/* - * Function name : i2ohba_i_reset_interface() - * - * Return Values : 0 - success - * -1 - hw failure - * - * Description : - * Master reset routine for hardware/software. Resets softc struct, - * i2ohba; and scsi bus and the scsi adapter. The works! - * This function is called from i2ohba_attach with no mutexes held or - * from i2ohba_i_fatal_error with request mutex held - * - * NOTE: it is up to the caller to flush the response queue - * - * Context : Can be called from different kernel process threads. - * i2ohba_attach() - single thread, no mutex held - * i2ohba_i_fatal_error() - * Can be called by interrupt thread. - */ -static int -i2ohba_i_reset_interface(struct i2ohba *i2ohba, int action) -{ - int i; - int rval = -1; - - /* - * Handle reset recovery; reset the bus before we reset the - * adapter chip - */ - /* - * send command Bus Reset - */ - DEBUGF(1, (CE_CONT, "Resetting i2o SCSI BUS")); - - if (action == I2OHBA_FORCE_BUS_RESET) { - if (i2ohba_i_reset_abort(i2ohba, i2ohba->i2ohba_tid, - I2O_HBA_BUS_RESET, 0)) { - i2ohba_i_log(NULL, CE_WARN, - "?i2ohba_i_reset_interface: bus reset failed"); - goto cleanup; - } - (void) scsi_hba_reset_notify_callback( - I2OHBA_REQ_MUTEX(i2ohba), - &i2ohba->i2ohba_reset_notify_listf); - drv_usecwait((clock_t)i2ohba->i2ohba_scsi_reset_delay * 1000); - } - - /* - * Handle resetting i2o host adapter. - */ - DEBUGF(1, (CE_CONT, "Resetting i2o SCSI Host Adapter")); - - /* - * Reset the i2o host adapter. - */ - if (i2ohba_i_reset_abort(i2ohba, i2ohba->i2ohba_tid, - I2O_HBA_ADAPTER_RESET, 0)) { - i2ohba_i_log(NULL, CE_WARN, "?i2ohba_i_reset_interface: " - "adapter reset failed"); - goto cleanup; - } - drv_usecwait((clock_t)i2ohba->i2ohba_scsi_reset_delay * 1000); - - - /* - * set Initiator SCSI ID using utilparamset - */ - -/* - * DEBUGF(1, (CE_CONT, "Initializing SCSI HBA ID")); - * - * i = i2ohba->i2ohba_initiator_id; - * if (i2ohba_utilparamset_msg(i2ohba, 7, i2ohba->i2ohba_tid, - * I2O_HBA_SCSI_CONTROLLER_INFO_GROUP_NO, 0x4, i) != 0) { - * i2ohba_i_log(NULL, CE_WARN, "?i2ohba_i_reset_interface: " - * "resetting initiator id failed"); - * goto cleanup; - * } - * - */ - - /* - * Update sync/offset from i2ohba utilparmas to - * global per target sync area. - */ - DEBUGF(1, (CE_CONT, "Initializing i2ohba capabilities")); - - for (i = 0; i < N_I2OHBA_TARGETS_WIDE; i++) { - (void) i2ohba_i_updatesync(i2ohba, i); - } - rval = 0; - -cleanup: - if (rval) { - DEBUGF(1, (CE_WARN, "reset interface failed")); - i2ohba->i2ohba_shutdown = 1; - DEBUGF(1, (CE_WARN, "interface going offline")); - i2ohba_i_qflush(i2ohba, (uint16_t)0, - (uint16_t)N_I2OHBA_TARGETS_WIDE); - } - - return (rval); -} - - - -static void -i2ohba_i_print_state(struct i2ohba *i2ohba) -{ - char buf[128]; - int i; - - - /* - * Print out sync scsi info and suppress trailing zero - * period and offset entries. - */ - if (i2ohba->i2ohba_scsi_options & SCSI_OPTIONS_SYNC) { - (void) sprintf(buf, "period/offset:"); - for (i = 0; i < N_I2OHBA_TARGETS; i++) { - (void) sprintf(&buf[strlen(buf)], " %d/%d", - i2ohba->i2ohba_synch[i], i2ohba->i2ohba_offset[i]); - } - DEBUGF(1, (CE_CONT, buf)); - (void) sprintf(buf, "period/offset:"); - for (i = N_I2OHBA_TARGETS; i < N_I2OHBA_TARGETS_WIDE; i++) { - (void) sprintf(&buf[strlen(buf)], " %d/%d", - i2ohba->i2ohba_synch[i], i2ohba->i2ohba_offset[i]); - } - DEBUGF(1, (CE_CONT, buf)); - } -} - -/* - * Function name: i2ohba_utilparamset_msg() - * - * Return Values: 0 - success - * -1 - set prarmeter failed - * Description : common UtilParamSet function. - * However, only one param at a time. Pass in - * the Tid, GroupNumber, and the FieldIdx, and - * value, then compose the Message frame, - * then send it off through i2o_message_send(). - * - * Message Format: - * - * Building a param_set message requires: - * Buffer#1 SGL-immediate data (Request) - * 1. i2o_param_operations_list_header_t(1W) - * u16 OperationCount (1) - * u16 Reserved - * 2. i2o_param_operation_specific_template_t(2W) - * u16 Operation (FIELD_SET) - * u16 GroupNumber (group) - * u16 FieldCount 0x1 - * u16 FieldIdx (idx) - * u16 value of idx - * - * Buffer#2 SGL-Simple addressing (Reply) - * 1. i2o_param_results_list_header_t(1W) - * u16 ResultCount - * u16 Reserved - * 2. i2o_param_modify_operation_result_t(9W) - * u16 BlockSize - * u8 BlockStatus - * u8 ErrorInfoSize - * ... ErrorInformation - * - * - * Context : Can be called from i2ohba_i_reset_interface() - * Can be called from i2ohba_i_updatecap() or - * i2ohba_scsi_setcap() - */ - - -static int -i2ohba_utilparamset_msg(struct i2ohba *i2ohba, int tgt, uint16_t tid, - uint16_t group, uint16_t idx, uint16_t value) -{ - - i2o_setparam_t *msgptr; - i2o_msg_handle_t msg_handle; - ddi_acc_handle_t acc_handle; - struct i2ohba_util *sp = NULL; - uint_t count; - int rval = -1; - int bound = 0; - uint16_t allocmsgsize; - - - /* - * allocate a message frame - */ - if (i2o_msg_alloc(i2ohba->i2ohba_iophdl, I2O_MSG_SLEEP, - NULL, (void *)&msgptr, &msg_handle, &acc_handle) - != DDI_SUCCESS) { - i2ohba_i_log(NULL, CE_WARN, "?i2ohba_utilparamset_msg: " - "i2o_msg_alloc failed"); - return (rval); - } - - /* - * To get the actual allocation msg size - */ - allocmsgsize = (ddi_get16(acc_handle, &msgptr->MessageSize) << 2); - - if (allocmsgsize < sizeof (i2o_setparam_t)) { - i2ohba_i_log(NULL, CE_WARN, "?i2ohba_utilparamset_msg: " - "msg size alloc is smaller than what setparam needed"); - goto fail; - } - - /* - * Construct a utilparamset message - */ - msgptr->VersionOffset = ContextSize32; - msgptr->MsgFlags = 0; - ddi_put16(acc_handle, &msgptr->MessageSize, - (sizeof (i2o_setparam_t) >> 2)); - put_msg_TargetAddress(msgptr, tid, acc_handle); - put_msg_InitiatorAddress(msgptr, I2O_OSM_TID, acc_handle); - put_msg_Function(msgptr, I2O_UTIL_PARAMS_SET, acc_handle); - ddi_put32(acc_handle, (uint32_t *)&msgptr->InitiatorContext, - (uint32_t)i2ohba_utilmsg_comp); - - /* - * allocating sychronize status buffer - */ - sp = kmem_alloc(sizeof (struct i2ohba_util), KM_SLEEP); - - ddi_put32(acc_handle, &msgptr->TransactionContext, - (uint32_t)(uintptr_t)sp); - - /* - * First message buffer's SGL and operation parameters - */ - - /* - * Buf1 SGL header: - * Immediate Data for the operation - */ - put_flags_count_Flags(&msgptr->FlagsCount1, - I2O_SGL_FLAGS_IMMEDIATE_DATA_ELEMENT - | I2O_SGL_FLAGS_END_OF_BUFFER, acc_handle); - put_flags_count_Count(&msgptr->FlagsCount1, ONE_PARAM_BLOCK, - acc_handle); - - /* - * Fill in the modify operation param for in the sgl1 payload - */ - - ddi_put16(acc_handle, &msgptr->OperationCount, 1); - ddi_put16(acc_handle, &msgptr->Operation, - I2O_PARAMS_OPERATION_FIELD_SET); - ddi_put16(acc_handle, &msgptr->GroupNumber, group); - ddi_put16(acc_handle, &msgptr->FieldCount, 0x1); - ddi_put16(acc_handle, &msgptr->FieldIdx, idx); - ddi_put16(acc_handle, &msgptr->Value, value); - - - /* - * Buf2 SGL header: - * Simple addressing - * 1. allocate the buffer for reply msg - * 2. setup the SGL header - */ - - sp->i2ohba_util_buffer = NULL; - - if (ddi_dma_alloc_handle(i2ohba->i2ohba_dip, &i2ohba_dmasgl_attr, - DDI_DMA_SLEEP, NULL, &sp->dmahandle) != - DDI_SUCCESS) { - i2ohba_i_log(NULL, CE_WARN, "?i2ohba_utilparam_set: " - "cannot alloc dma handle"); - goto fail; - } - bound++; - if (ddi_dma_mem_alloc(sp->dmahandle, (size_t) - sizeof (i2o_param_results_list_header_t) + (size_t) - sizeof (i2o_param_modify_operation_result_t), - &dev_attr, DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, - (caddr_t *)&sp->i2ohba_util_buffer, &sp->rlen, - &sp->dma_acc_handle) != DDI_SUCCESS) { - i2ohba_i_log(NULL, CE_WARN, "?i2ohba_utilparamset_msg: " - "cannot allocate param buffer"); - goto fail; - } - bound++; - put_flags_count_Flags(&msgptr->FlagsCount2, - I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | - I2O_SGL_FLAGS_END_OF_BUFFER | - I2O_SGL_FLAGS_LAST_ELEMENT, acc_handle); - - put_flags_count_Count(&msgptr->FlagsCount2, sp->rlen, acc_handle); - - - if (ddi_dma_addr_bind_handle(sp->dmahandle, NULL, - sp->i2ohba_util_buffer, (size_t) - sizeof (i2o_param_results_list_header_t) + (size_t) - sizeof (i2o_param_modify_operation_result_t) + (size_t) - sizeof (i2o_scsi_device_info_scalar_t), - DDI_DMA_RDWR|DDI_DMA_STREAMING, DDI_DMA_SLEEP, - NULL, &sp->dmacookie, &count) != DDI_DMA_MAPPED) { - /* - * currently assume simple - * addring with one physical - * continuous address buffer. - */ - i2ohba_i_log(NULL, CE_WARN, "?i2ohba_utilparamset_msg: " - "cannot bind buffer"); - goto fail; - } - - ddi_put32(acc_handle, &msgptr->PhysicalAddress, - (uint32_t)sp->dmacookie.dmac_address); - /* - * initialized a mutex and condvariable to - * send message to IOP, and wait for it - * to signal back - */ - sp->mutex = I2OHBA_UTILPARAM_MUTEX(i2ohba, tgt); - sp->cv = I2OHBA_UTILPARAM_CV(i2ohba, tgt); - mutex_enter(sp->mutex); - sp->wakeup = UTIL_MSG_SLEEP; - sp->status = 0; - (void) i2o_msg_send(i2ohba->i2ohba_iophdl, msgptr, msg_handle); - while (!sp->wakeup) - cv_wait(sp->cv, sp->mutex); - mutex_exit(sp->mutex); - - /* clear msg pointer */ - msgptr = NULL; - - /* - * process the data - */ - switch (sp->status) { - - i2o_setparam_reply_t *result; - uint16_t count; - uint8_t blockstatus, errinfosize; - - case I2O_REPLY_STATUS_SUCCESS: - /* - * since the reply is successful, will check - * for the opeation reulsts - */ - result = (i2o_setparam_reply_t *)sp->i2ohba_util_buffer; - count = ddi_get16(sp->dma_acc_handle, - &result->ResultCount); - if (!count) { - i2ohba_i_log(NULL, CE_WARN, - "?i2ohba_utilparamset_msg: No Results"); - break; - } - - blockstatus = ddi_get8(sp->dma_acc_handle, - &result->BlockStatus); - - errinfosize = ddi_get8(sp->dma_acc_handle, - &result->ErrorInfoSize); - - if ((blockstatus != 0) || (errinfosize != 0)) { - i2ohba_i_log(NULL, CE_WARN, - "?i2ohba_utilparamset_msg: Error " - "occured during Modify Operation"); - /* - * retrived errorinfo and possibily retry - * XXLWLXX - */ - break; - } - rval = 0; - break; - - default: - rval = -1; - break; - } - -fail: - - if (sp) { - if (bound) { - (void) ddi_dma_unbind_handle(sp->dmahandle); - if (bound > 1) - (void) ddi_dma_mem_free(&sp->dma_acc_handle); - (void) ddi_dma_free_handle(&sp->dmahandle); - } - kmem_free(sp, sizeof (struct i2ohba_util)); - } - - /* return MFA to IOP */ - if (msgptr) { - msgptr->VersionOffset = 0; - msgptr->MsgFlags = 0; - ddi_put16(acc_handle, &msgptr->MessageSize, 3); - put_msg_TargetAddress(msgptr, 0, acc_handle); - put_msg_InitiatorAddress(msgptr, 0, acc_handle); - put_msg_Function(msgptr, I2O_UTIL_NOP, acc_handle); - (void) i2o_msg_send(i2ohba->i2ohba_iophdl, msgptr, msg_handle); - } - return (rval); -} - -/* - * Function name: i2ohba_utilparamget_msg() - * - * Return Values: 0 - success - * -1 - get prarmeter failed - * - * Description : common UtilParamGet function. - * However, only one param at a time. Pass in - * the Tid, GroupNumber, and the FieldIdx, and - * value, then compose the Message frame, - * then send it off through i2o_message_send(). - * - * Message Format: - * - * building a param_get message requires - * Buffer#1 SGL-immediate data - * 1. i2o_param_operations_list_header_t(1W) - * u16 OperationCount - * u16 Reserved - * 2. i2o_param_operation_speicific_template_t(2W) - * u16 Operation (FIELD_GET) - * u16 GroupNumber - * u16 FieldCount 0xFFFF - * u16 Pad - * - * Buffer#2 SGL-Simple addressing - * Reply Message: - * 1. i2o_param_results_list_header_t(1W) - * u16 ResultCount - * u16 Reserved - * 2. i2o_param_read_operation_result_t(9W) - * u16 BlockSize - * u8 BlockStatus - * u8 ErrorInfoSize - * ... Total 8W for (ALL_PARAM_BLOCK) - * u32 Identifier - * u64 LUN - * ... - * OR Total 9 bytes (ONE_PARAM_BLOCK) - * u8 NegOffset - * u64 NegSynch - */ - -static int -i2ohba_utilparamget_msg(struct i2ohba *i2ohba, uint16_t tidx, char flag) -{ - - i2o_tid_scsi_ent_t *map = i2ohba->i2ohba_tid_scsi_map; - i2o_tid_scsi_ent_t **tgtmap = i2ohba->i2ohba_tgt_id_map; - - i2o_getsyncparam_t *msgptr; - i2o_msg_handle_t msg_handle; - ddi_acc_handle_t acc_handle; - struct i2ohba_util *sp = NULL; - uint_t count; - uint16_t allocmsgsize; - uint16_t tid; - int rval = -1; - int bound = 0; - - /* - * allocate a message frame - */ - if (i2o_msg_alloc(i2ohba->i2ohba_iophdl, I2O_MSG_SLEEP, - NULL, (void *)&msgptr, &msg_handle, &acc_handle) - != DDI_SUCCESS) { - i2ohba_i_log(NULL, CE_WARN, "?i2ohba_utilparamget_msg: " - "i2o_msg_alloc failed"); - return (rval); - } - - /* - * NOTE: - * "tidx" is either the entry number for the tid to scsi map - * or tidx is the target id, which needs tgt to id map to - * find the tid. - */ - if (flag == ALL_UTILPARAMS) { - tid = map[tidx].tid; - } else { - tid = tgtmap[tidx]->tid; - } - - /* - * To get the actual allocation msg - * size (in WORDS) - */ - allocmsgsize = (ddi_get16(acc_handle, &msgptr->MessageSize) << 2); - - - /* - * Construct a utilparamget message - */ - /* msgptr->VersionOffset = ContextSize32; */ - msgptr->VersionOffset = I2O_VERSION_11; - msgptr->MsgFlags = 0; - put_msg_TargetAddress(msgptr, tid, acc_handle); - put_msg_InitiatorAddress(msgptr, I2O_OSM_TID, acc_handle); - put_msg_Function(msgptr, I2O_UTIL_PARAMS_GET, acc_handle); - ddi_put32(acc_handle, - (uint32_t *)&msgptr->InitiatorContext.initiator_context_32bits, - (uint32_t)i2ohba_utilmsg_comp); - /* - * allocating sychroniz status buffer - */ - sp = kmem_alloc(sizeof (struct i2ohba_util), KM_SLEEP); - - ddi_put32(acc_handle, &msgptr->TransactionContext, - (uint32_t)(uintptr_t)sp); - - /* - * Buf1 SGL header: - * Immediate Data - */ - put_flags_count_Flags(&msgptr->FlagsCount1, - I2O_SGL_FLAGS_IMMEDIATE_DATA_ELEMENT | - I2O_SGL_FLAGS_END_OF_BUFFER, acc_handle); - - /* - * Fill in the read operation param for - * in the payload - */ - - ddi_put16(acc_handle, &msgptr->OperationCount, 1); - - ddi_put16(acc_handle, &msgptr->Operation, - I2O_PARAMS_OPERATION_FIELD_GET); - - ddi_put16(acc_handle, &msgptr->GroupNumber, - I2O_SCSI_DEVICE_INFO_GROUP_NO); - - /* - * End of message sending - */ - - /* - * Buf2 SGL header: - * Simple Addressing - * 1. allocating the buffer - * 2. set up the SGL header - */ - - sp->i2ohba_util_buffer = NULL; - - if (ddi_dma_alloc_handle(i2ohba->i2ohba_dip, &i2ohba_dmasgl_attr, - DDI_DMA_SLEEP, NULL, &sp->dmahandle) != - DDI_SUCCESS) { - i2ohba_i_log(NULL, CE_WARN, "?i2ohba_utilparamget_msg: " - "cannot alloc dma handle"); - goto fail; - } - bound++; - if (flag == ALL_UTILPARAMS) { - - if (allocmsgsize < sizeof (i2o_getallparam_t)) - return (rval); - - if (ddi_dma_mem_alloc(sp->dmahandle, (size_t) - sizeof (i2o_getallparam_reply_t), &dev_attr, - DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, - (caddr_t *)&sp->i2ohba_util_buffer, &sp->rlen, - &sp->dma_acc_handle) != DDI_SUCCESS) { - i2ohba_i_log(NULL, CE_WARN, - "?i2ohba_utilparamget_msg: " - "cannot allocate param buffer"); - goto fail; - } - bound++; - /* StdMessageFrame */ - ddi_put16(acc_handle, &msgptr->MessageSize, - (sizeof (i2o_getallparam_t) >> 2)); - - /* i2o_sge_immediate_data_element */ - put_flags_count_Count(&msgptr->FlagsCount1, ALL_PARAM_BLOCK, - acc_handle); - - /* i2o_param_operation_all_template */ - ddi_put16(acc_handle, &msgptr->FieldCount, 0xFFFF); - - /* i2o_sge_simple_element */ - put_flags_count_Flags( - &((i2o_getallparam_t *)msgptr)->FlagsCount2, - I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | - I2O_SGL_FLAGS_END_OF_BUFFER | - I2O_SGL_FLAGS_LAST_ELEMENT, acc_handle); - - put_flags_count_Count( - &((i2o_getallparam_t *)msgptr)->FlagsCount2, - sp->rlen, acc_handle); - - if (ddi_dma_addr_bind_handle(sp->dmahandle, NULL, - sp->i2ohba_util_buffer, (size_t) - sizeof (i2o_getallparam_reply_t), - DDI_DMA_READ|DDI_DMA_STREAMING, DDI_DMA_SLEEP, - NULL, &sp->dmacookie, &count) != DDI_SUCCESS) { - /* - * currently assume simple - * addring with one physical - * continuous address buffer. - */ - i2ohba_i_log(NULL, CE_WARN, - "?i2ohba_utilparamget_msg: " - "cannot bind buffer"); - goto fail; - } - - ddi_put32(acc_handle, - &((i2o_getallparam_t *)msgptr)->PhysicalAddress, - (uint32_t)sp->dmacookie.dmac_address); - - /* - * initialized the target param_mutex and cv. - * note: given that we don't have target id - * yet, (that is why we are here), we'll just - * use target[0]'s mutex & cv. - */ - sp->mutex = I2OHBA_UTILPARAM_MUTEX(i2ohba, 0); - sp->cv = I2OHBA_UTILPARAM_CV(i2ohba, 0); - } else { - if (allocmsgsize < sizeof (i2o_getsyncparam_t)) - return (rval); - - if (ddi_dma_mem_alloc(sp->dmahandle, (size_t) - sizeof (i2o_getsyncparam_reply_t), &dev_attr, - DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, - (void *)&sp->i2ohba_util_buffer, &sp->rlen, - &sp->dma_acc_handle) != DDI_SUCCESS) { - i2ohba_i_log(NULL, CE_WARN, - "?i2ohba_utilparamget_msg: " - "cannot allocate param buffer"); - goto fail; - } - bound++; - /* StdMessageFrame */ - ddi_put16(acc_handle, &msgptr->MessageSize, - (sizeof (i2o_getsyncparam_t) >> 2)); - - /* i2o_sge_immediate_data_element */ - put_flags_count_Count(&msgptr->FlagsCount1, ONE_PARAM_BLOCK, - acc_handle); - - /* i2o_param_operation_specific_template */ - ddi_put16(acc_handle, &msgptr->FieldCount, 0x0002); - ddi_put16(acc_handle, &msgptr->FieldIdx, 0x000A); - ddi_put16(acc_handle, &msgptr->FieldIdx, 0x0007); - - /* i2o_sge_simple_element */ - put_flags_count_Flags(&msgptr->FlagsCount2, - I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT | - I2O_SGL_FLAGS_END_OF_BUFFER | - I2O_SGL_FLAGS_LAST_ELEMENT, acc_handle); - - put_flags_count_Count(&msgptr->FlagsCount2, sp->rlen, - acc_handle); - - if (ddi_dma_addr_bind_handle(sp->dmahandle, NULL, - sp->i2ohba_util_buffer, (size_t) - sizeof (i2o_getsyncparam_reply_t), - DDI_DMA_RDWR|DDI_DMA_STREAMING, DDI_DMA_SLEEP, - NULL, &sp->dmacookie, &count) != DDI_DMA_MAPPED) { - /* - * currently assume simple - * addring with one physical - * continuous address buffer. - */ - i2ohba_i_log(NULL, CE_WARN, - "?i2ohba_utilparamget_msg: " - "cannot bind buffer"); - goto fail; - } - - ddi_put32(acc_handle, &msgptr->PhysicalAddress, - (uint32_t)sp->dmacookie.dmac_address); - - /* - * initialized the target param_mutex and cv - * tidx holds the target id number - */ - sp->mutex = I2OHBA_UTILPARAM_MUTEX(i2ohba, tidx); - sp->cv = I2OHBA_UTILPARAM_CV(i2ohba, tidx); - } - -#ifdef I2OHBA_DEBUG - DEBUGF(2, (CE_CONT, "\nmsgptr: 0x%p\n", (void *)msgptr)); - DEBUGF(2, (CE_CONT, "msgptr->VersionOffset: %x\n", - msgptr->VersionOffset)); - DEBUGF(2, (CE_CONT, "msgptr->MsgFlags: %x\n", msgptr->MsgFlags)); - DEBUGF(2, (CE_CONT, "msgptr->MessageSize: %x\n", ddi_get16(acc_handle, - &msgptr->MessageSize))); - DEBUGF(2, (CE_CONT, "msgptr->TargetAddress: %x\n", - get_msg_TargetAddress(msgptr, acc_handle))); - DEBUGF(2, (CE_CONT, "msgptr->InitiatorAddress: %x\n", - get_msg_InitiatorAddress(msgptr, acc_handle))); - DEBUGF(2, (CE_CONT, "msgptr->Function: %x\n", - get_msg_Function(msgptr, acc_handle))); - DEBUGF(2, (CE_CONT, "msgptr->InitContext: %x\n", - ddi_get32(acc_handle, - &msgptr->InitiatorContext.initiator_context_32bits))); - DEBUGF(2, (CE_CONT, "msgptr->TransContext: %x\n", - ddi_get32(acc_handle, &msgptr->TransactionContext))); - DEBUGF(2, (CE_CONT, "msgptr->OperationFlags: Resevered\n")); - DEBUGF(2, (CE_CONT, "msgptr->FlagsCount1.Flags: %x\n", - get_flags_count_Flags(&msgptr->FlagsCount1, acc_handle))); - DEBUGF(2, (CE_CONT, "msgptr->FlagsCount1.Count: %x\n", - get_flags_count_Count(&msgptr->FlagsCount1, acc_handle))); - DEBUGF(2, (CE_CONT, "msgptr->OperationCount: %x\n", - ddi_get16(acc_handle, &msgptr->OperationCount))); - DEBUGF(2, (CE_CONT, "msgptr->Operation: %x\n", - ddi_get16(acc_handle, &msgptr->Operation))); - DEBUGF(2, (CE_CONT, "msgptr->GroupNumber: %x\n", - ddi_get16(acc_handle, &msgptr->GroupNumber))); - DEBUGF(2, (CE_CONT, "msgptr->FieldCount: %x\n", - ddi_get16(acc_handle, &msgptr->FieldCount))); - DEBUGF(2, (CE_CONT, "msgptr->FlagsCount2.Flags: %x\n", - get_flags_count_Flags(&((i2o_getallparam_t *)msgptr)->FlagsCount2, - acc_handle))); - DEBUGF(2, (CE_CONT, "msgptr->FlagsCount2.Count: %x\n", - get_flags_count_Count(&((i2o_getallparam_t *)msgptr)->FlagsCount2, - acc_handle))); - DEBUGF(2, (CE_CONT, "msgptr->PhyAddr: %x\n", ddi_get32(acc_handle, - &((i2o_getallparam_t *)msgptr)->PhysicalAddress))); -#endif - /* - * initialized a mutex and condvariable to - * send message to IOP, and wait for it - * to signal back - */ - mutex_enter(sp->mutex); - sp->wakeup = UTIL_MSG_SLEEP; - sp->status = 0; - (void) i2o_msg_send(i2ohba->i2ohba_iophdl, msgptr, msg_handle); - while (!sp->wakeup) - cv_wait(sp->cv, sp->mutex); - mutex_exit(sp->mutex); - - msgptr = NULL; - - /* - * process the data - */ - switch (sp->status) { - case I2O_REPLY_STATUS_SUCCESS: - /* - * Success: - * 0) read the reply headers XXLWXX - * 1) copy buffer over to the map - * 2) unbind dma buffer - */ - - if (sp->i2ohba_util_buffer) { - uint_t tgtid; - - if (flag == ALL_UTILPARAMS) { - i2o_getallparam_reply_t *reply; - - reply = (i2o_getallparam_reply_t *) - sp->i2ohba_util_buffer; - map[tidx].scsi_info_scalar.DeviceType = - reply->DeviceType; - DEBUGF(2, (CE_CONT, "/tDeviceType:" - " 0x%x", reply->DeviceType)); - map[tidx].scsi_info_scalar.Flags = - reply->Flags; - DEBUGF(2, (CE_CONT, "/tFlags:" - " 0x%x", reply->Flags)); - map[tidx].scsi_info_scalar.Identifier = - tgtid = - ddi_get32(sp->dma_acc_handle, - &reply->Identifier); - DEBUGF(2, (CE_CONT, "/tSCSI Id: 0x%x", - tgtid)); - map[tidx].scsi_info_scalar.LunInfo[0] = 0; - map[tidx].scsi_info_scalar.QueueDepth = - ddi_get32(sp->dma_acc_handle, - &reply->QueueDepth); - DEBUGF(2, (CE_CONT, "/tQueueDepth: 0x%x", - map[tidx].scsi_info_scalar.QueueDepth)); - map[tidx].scsi_info_scalar.NegOffset = - reply->NegOffset; - DEBUGF(2, (CE_CONT, "/tQueueDepth: 0x%x", - reply->NegOffset)); - map[tidx].scsi_info_scalar.NegDataWidth = - reply->NegDataWidth; - DEBUGF(2, (CE_CONT, "/tNegDataWidth: 0x%x", - reply->NegDataWidth)); - map[tidx].scsi_info_scalar.NegSyncRate = - ddi_get64(sp->dma_acc_handle, - &reply->NegSyncRate); - DEBUGF(2, (CE_CONT, "/tNegSyncRate: 0x%x", - (uint32_t) - map[tidx].scsi_info_scalar.NegSyncRate)); - - tgtmap[tgtid] = &map[tidx]; - - } else { - i2o_getsyncparam_reply_t *reply; - - reply = (i2o_getsyncparam_reply_t *) - sp->i2ohba_util_buffer; - tgtmap[tidx]->scsi_info_scalar.NegSyncRate = - ddi_get64(sp->dma_acc_handle, - &reply->NegSyncRate); - DEBUGF(2, (CE_CONT, "/tNegSyncRate: 0x%x", - (uint32_t) - map[tidx].scsi_info_scalar.NegSyncRate)); - tgtmap[tidx]->scsi_info_scalar.NegOffset = - reply->NegOffset; - DEBUGF(2, (CE_CONT, "/tNegOffset: 0x%x", - reply->NegOffset)); - } - } - rval = 0; - break; - - case I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER: - case I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER: - default: - i2ohba_i_log(NULL, CE_WARN, "?I2O_PARAM_UTIL_GET on " - "Target %d failed", tidx); - break; - - } - -fail: - - if (sp) { - if (bound) { - (void) ddi_dma_unbind_handle(sp->dmahandle); - if (bound > 1) - (void) ddi_dma_mem_free(&sp->dma_acc_handle); - (void) ddi_dma_free_handle(&sp->dmahandle); - - } - kmem_free(sp, sizeof (struct i2ohba_util)); - } - - /* return MFA to IOP */ - if (msgptr) { - msgptr->VersionOffset = 0; - msgptr->MsgFlags = 0; - ddi_put16(acc_handle, &msgptr->MessageSize, 3); - put_msg_TargetAddress(msgptr, 0, acc_handle); - put_msg_InitiatorAddress(msgptr, 0, acc_handle); - put_msg_Function(msgptr, I2O_UTIL_NOP, acc_handle); - (void) i2o_msg_send(i2ohba->i2ohba_iophdl, msgptr, msg_handle); - } - - return (rval); -} - -/*PRINTFLIKE3*/ -static void -i2ohba_i_log(struct i2ohba *i2ohba, int level, char *fmt, ...) -{ - dev_info_t *dip; - va_list ap; - - ASSERT((mutex_owned(&i2ohba_log_mutex)) == 0 || ddi_in_panic()); - - if (i2ohba) { - dip = i2ohba->i2ohba_dip; - } else { - dip = 0; - } - - mutex_enter(&i2ohba_log_mutex); - va_start(ap, fmt); - (void) vsprintf(i2ohba_log_buf, fmt, ap); - va_end(ap); - - if (level == CE_WARN) { - scsi_log(dip, "i2o_scsi", level, "%s", i2ohba_log_buf); - } else { - scsi_log(dip, "i2o_scsi", level, "%s\n", i2ohba_log_buf); - } - mutex_exit(&i2ohba_log_mutex); -}
--- a/usr/src/uts/common/io/i2o/i2o_scsi.conf Wed Apr 18 03:07:55 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,35 +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 (c) 1998 by Sun Microsystems, Inc. -# All rights reserved. -# -#pragma ident "%Z%%M% %I% %E% SMI" - -# -# i2o_scsi.conf -# -# global definitions - -name="i2o_scsi" class="i2o"; -flow_control="dmult" queue="qsort" tape="sctp";
--- a/usr/src/uts/common/io/i2o/i2o_scsi_cmd.h Wed Apr 18 03:07:55 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,98 +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 (c) 1998 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _I2O_SCSI_CMD_H -#define _I2O_SCSI_CMD_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#define PKT_PRIV_LEN 8 /* preferred pkt_private length */ -#define PKT2CMD(pkt) ((struct i2ohba_cmd *)(pkt)->pkt_ha_private) -#define CMD2PKT(sp) ((sp)->cmd_pkt) - -/* - * These are the defined flags for this structure. - */ -#define CFLAG_FINISHED 0x0001 /* command completed */ -#define CFLAG_COMPLETED 0x0002 /* completion routine called */ -#define CFLAG_IN_TRANSPORT 0x0004 /* in use by isp driver */ -#define CFLAG_DELAY_TIMEOUT 0x0008 /* delay timeout */ -#define CFLAG_TRANFLAG 0x000f /* transport part of flags */ -#define CFLAG_DMAVALID 0x0010 /* dma mapping valid */ -#define CFLAG_DMASEND 0x0020 /* data is going 'out' */ -#define CFLAG_CMDIOPB 0x0040 /* this is an 'iopb' packet */ -#define CFLAG_FREE 0x0080 /* packet is on free list */ -#define CFLAG_DMA_PARTIAL 0x0100 /* partial xfer OK */ - - -/* - * I2O command struct to keep the request and response - * - * the preferred cbd size is 12, but I2O standard defined based on - * SCSI 3. - */ - -struct i2ohba_cmd { - i2o_scsi_scb_execute_message_t *cmd_i2o_request; - struct scsi_pkt *cmd_pkt; - struct i2ohba_cmd *cmd_forw; /* forward ptr */ - struct i2ohba_cmd *cmd_backw; /* backward ptr */ - - ddi_dma_handle_t sglbuf_dmahandle; /* SGL chain buffer */ - ddi_acc_handle_t sglbuf_dmaacchandle; /* SGL chain buffer */ - ddi_dma_cookie_t sglbuf_dmacookie; - i2o_sge_chain_element_t *sglbuf; /* the buffer that holds the SGL */ - size_t sglrlen; /* the buffer that holds the SGL */ - size_t cmd_dmacount; /* totl # of bytes transfer */ - size_t cmd_xfercount; /* cur # of bytes transfer */ - ddi_dma_handle_t cmd_dmahandle; /* dma handle */ - uint_t cmd_cookie; /* next cookie */ - uint_t cmd_ncookies; /* cookies per window */ - uint_t cmd_cookiecnt; /* cookies per sub-window */ - uint_t cmd_nwin; /* number of dma windows */ - uint_t cmd_curwin; /* current dma window */ - off_t cmd_dma_offset; /* current window offset */ - ulong_t cmd_dma_len; /* current window length */ - ddi_dma_cookie_t cmd_dmacookies[I2OHBA_CMD_NSEGS]; - /* current dma cookies */ - clock_t cmd_deadline; - uint16_t cmd_flags; /* Internal state flag */ - uint8_t cmd_cdblen; - uint_t cmd_scblen; - uchar_t cmd_cdb[I2O_SCSI_CDB_LENGTH]; /* 16-SCSI3 */ - uint_t cmd_privlen; - uchar_t cmd_pkt_private[PKT_PRIV_LEN]; -}; - -#ifdef __cplusplus -} -#endif - -#endif /* _I2O_SCSI_CMD_H */
--- a/usr/src/uts/common/io/i2o/i2o_scsi_util.h Wed Apr 18 03:07:55 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,274 +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 (c) 1998 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _I2O_SCSI_UTIL_H -#define _I2O_SCSI_UTIL_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Utility msg synchronization condvar - */ -#define UTIL_MSG_SLEEP 0 -#define UTIL_MSG_WAKEUP 1 - -/* - * Utility Parameter's mutex - */ -#define I2OHBA_UTILPARAM_MUTEX(i2ohba, i) (&i2ohba->util_param_mutex[i]) -#define I2OHBA_UTILPARAM_CV(i2ohba, i) (&i2ohba->util_param_cv[i]) - - -/* - * Defines for parameter size - */ -#define ONE_PARAM_BLOCK (sizeof (i2o_param_operations_list_header_t)\ - + sizeof (i2o_param_operation_specific_template_t) \ - + sizeof (uint32_t)) - -#define ALL_PARAM_BLOCK (sizeof (i2o_param_operations_list_header_t)\ - + sizeof (i2o_param_operation_all_template_t) \ - + sizeof (uint16_t)) - -/* - * Utility message's transaction context - */ -struct i2ohba_util { - int wakeup; /* value */ - int status; /* status of reply msg */ - kmutex_t *mutex; /* per request mutex */ - kcondvar_t *cv; /* per request signal */ - void *i2ohba_util_buffer; /* result operation block */ - size_t rlen; /* length of the result block */ - ddi_dma_cookie_t dmacookie; /* dma cookie for result block */ - ddi_dma_handle_t dmahandle; /* dma handle for result block */ - ddi_acc_handle_t dma_acc_handle; /* dma access handle */ -}; - -/* - * Util_Params_Get Op on all Parameters - */ - -typedef struct i2o_setparam { - - /* i2o_message_frame_t */ - uint8_t VersionOffset; - uint8_t MsgFlags; - uint16_t MessageSize; - union { - struct { - uint_t TargetAddress:12; - uint_t InitiatorAddress:12; - uint_t Function:8; - } s2; - uint32_t w2; - } u2; - i2o_initiator_context_t InitiatorContext; - - /* i2o_util_params_set_message */ - i2o_transaction_context_t TransactionContext; - uint32_t OperationFlags; - - /* SGL: i2o_sge_immediate_data_elememnt */ - i2o_flags_count_t FlagsCount1; /* 32 bits */ - /* size == ONE_PARAM_BLOCK */ - /* i2o_param_operation_list_header */ - uint16_t OperationCount; - uint16_t Reserved; - - /* i2o_param_operation_specific_template */ - uint16_t Operation; - uint16_t GroupNumber; - uint16_t FieldCount; - uint16_t FieldIdx; - uint16_t Value; /* not in struct */ - uint16_t pad; /* not in struct */ - - /* SGL: i2o_sge_simple_element */ - i2o_flags_count_t FlagsCount2; /* 32 bits */ - uint32_t PhysicalAddress; - -} i2o_setparam_t; - - -typedef struct i2o_setparam_reply { - - /* i2o_param_results_list_header_t */ - uint16_t ResultCount; - uint16_t Reserved; - - /* i2o_param_modify_operation_result */ - uint16_t BlockSize; - uint8_t BlockStatus; - uint8_t ErrorInfoSize; - /* ErrorInformation (if any) */ -} i2o_setparam_reply_t; - -#define ALL_UTILPARAMS 0x01 -#define SYNC_UTILPARAM 0x02 - -/* - * Util_Params_Get Op on all Parameters - */ - -typedef struct i2o_getallparam { - - /* i2o_message_frame_t */ - uint8_t VersionOffset; - uint8_t MsgFlags; - uint16_t MessageSize; - union { - struct { - uint_t TargetAddress:12; - uint_t InitiatorAddress:12; - uint_t Function:8; - } s2; - uint32_t w2; - } u2; - i2o_initiator_context_t InitiatorContext; - - /* i2o_util_params_get_message */ - i2o_transaction_context_t TransactionContext; - uint32_t OperationFlags; - - /* SGL: i2o_sge_immediate_data_elememnt */ - i2o_flags_count_t FlagsCount1; /* 32 bits */ - /* size == ALL_PARAM_BLOCK */ - /* i2o_param_operation_list_header */ - uint16_t OperationCount; - uint16_t Reserved; - - /* i2o_param_operation_all_template */ - uint16_t Operation; - uint16_t GroupNumber; - uint16_t FieldCount; /* (0xffff) */ - uint16_t Pad; /* not part of all temp struct */ - - /* SGL: i2o_sge_simple_element */ - i2o_flags_count_t FlagsCount2; /* 32 bits */ - uint32_t PhysicalAddress; - -} i2o_getallparam_t; - - -typedef struct i2o_getallparam_reply { - - /* i2o_param_results_list_header_t */ - uint16_t ResultCount; - uint16_t Reserved; - - /* i2o_param_read_operation_result */ - uint16_t BlockSize; - uint8_t BlockStatus; - uint8_t ErrorInfoSize; - - /* ListOfValues */ - uint8_t DeviceType; - uint8_t Flags; - uint16_t Reserved1; - uint32_t Identifier; - uint8_t LUN[8]; - uint32_t QueueDepth; - uint8_t Reserved2; - uint8_t NegOffset; - uint8_t NegDataWidth; - uint8_t Reserved3; - uint64_t NegSyncRate; - -} i2o_getallparam_reply_t; - - -/* - * Util_Params_Get Op on Synch and Offset - */ -typedef struct i2o_getsyncparam { - - /* i2o_message_frame_t */ - uint8_t VersionOffset; - uint8_t MsgFlags; - uint16_t MessageSize; - union { - struct { - uint_t TargetAddress:12; - uint_t InitiatorAddress:12; - uint_t Function:8; - } s2; - uint32_t w2; - } u2; - i2o_initiator_context_t InitiatorContext; - - /* i2o_util_params_get_message */ - i2o_transaction_context_t TransactionContext; - uint32_t OperationFlags; - - /* SGL: i2o_sge_immediate_data_elememnt */ - i2o_flags_count_t FlagsCount1; /* 32 bits */ - /* size == ONE_PARAM_BLOCK */ - /* i2o_param_operation_list_header */ - uint16_t OperationCount; - uint16_t Reserved; - - /* i2o_param_operation_specific_template */ - uint16_t Operation; - uint16_t GroupNumber; - uint16_t FieldCount; - uint16_t FieldIdx; /* field #10 */ - uint16_t FieldIdx2; /* field #7 not in struct */ - uint16_t Pad; /* not in struct */ - - /* SGL: i2o_sge_simple_element */ - i2o_flags_count_t FlagsCount2; /* 32 bits */ - uint32_t PhysicalAddress; - -} i2o_getsyncparam_t; - - -typedef struct i2o_getsyncparam_reply { - - /* i2o_param_results_list_header_t */ - uint16_t ResultCount; - uint16_t Reserved; - - /* i2o_param_read_operation_result */ - uint16_t BlockSize; - uint8_t BlockStatus; - uint8_t ErrorInfoSize; - - /* ListOfValues */ - uint64_t NegSyncRate; - uint8_t NegOffset; - -} i2o_getsyncparam_reply_t; - -#ifdef __cplusplus -} -#endif - -#endif /* _I2O_SCSI_UTIL_H */
--- a/usr/src/uts/common/io/i2o/i2o_scsi_var.h Wed Apr 18 03:07:55 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,246 +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 (c) 1998, by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _I2O_SCSI_VAR_H -#define _I2O_SCSI_VAR_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Convenient defines - */ - -/* - * Local static data - */ - -#define I2OHBA_INITIAL_SOFT_SPACE 2 /* assume 2 instances of hba */ -#define I2OHBA_CMD_NSEGS 17 -#define I2O_OSM_TID 0x01 - -#define TGT(sp) (CMD2PKT(sp)->pkt_address.a_target) -#define LUN(sp) (CMD2PKT(sp)->pkt_address.a_lun) - -/* - * Targets supported - */ -#define N_I2OHBA_LUNS 8 -#define N_I2OHBA_TARGETS 8 -#define N_I2OHBA_TARGETS_WIDE 16 - -/* - * message module defines - */ -#define ContextSize32 0x51 -#define ContextSize64 0x71 - -/* - * Default scsi-options - */ -#define I2OHBA_DEFAULT_SCSI_OPTIONS \ - SCSI_OPTIONS_PARITY | \ - SCSI_OPTIONS_DR | \ - SCSI_OPTIONS_SYNC | \ - SCSI_OPTIONS_TAG | \ - SCSI_OPTIONS_FAST | \ - SCSI_OPTIONS_WIDE - - -/* - * Mutex short hands - */ -#define I2OHBA_REQ_MUTEX(i2ohba) (&i2ohba->i2ohba_request_mutex) -#define I2OHBA_MUTEX_OWNED(i2ohba) mutex_owned(I2OHBA_REQ_MUTEX(i2ohba)) -#define I2OHBA_MUTEX_ENTER(i2ohba) mutex_enter(I2OHBA_REQ_MUTEX(i2ohba)) -#define I2OHBA_MUTEX_EXIT(i2ohba) mutex_exit(I2OHBA_REQ_MUTEX(i2ohba)) - -#define I2OHBA_RESET_MUTEX(i2ohba) (&i2ohba->reset_mutex) -#define I2OHBA_RESET_CV(i2ohba) (&i2ohba->reset_cv) - -/* - * HBA interface macros - */ -#define SDEV2TRAN(sd) ((sd)->sd_address.a_hba_tran) -#define SDEV2ADDR(sd) (&((sd)->sd_address)) -#define PKT2TRAN(pkt) ((pkt)->pkt_address.a_hba_tran) -#define ADDR2TRAN(ap) ((ap)->a_hba_tran) - -#define TRAN2I2OHBA(tran) ((struct i2ohba *)(tran)->tran_hba_private) -#define SDEV2I2OHBA(sd) (TRAN2I2OHBA(SDEV2TRAN(sd))) -#define PKT2I2OHBA(pkt) (TRAN2I2OHBA(PKT2TRAN(pkt))) -#define ADDR2I2OHBA(ap) (TRAN2I2OHBA(ADDR2TRAN(ap))) - -#define CMD2ADDR(cmd) (&CMD2PKT(cmd)->pkt_address) -#define CMD2TRAN(cmd) (CMD2PKT(cmd)->pkt_address.a_hba_tran) -#define CMD2I2OHBA(cmd) (TRAN2I2OHBA(CMD2TRAN(cmd))) - -/* - * Capability defines - */ -#define I2OHBA_CAP_DISCONNECT 0x8000 -#define I2OHBA_CAP_PARITY 0x4000 -#define I2OHBA_CAP_WIDE 0x2000 -#define I2OHBA_CAP_SYNC 0x1000 -#define I2OHBA_CAP_TAG 0x0800 -#define I2OHBA_CAP_AUTOSENSE 0x0400 -#define I2OHBA_CAP_ERRSTOP 0x0200 -#define I2OHBA_CAP_ERRSYNC 0x0100 - -/* - * delay time for polling loops - */ -#define I2OHBA_NOINTR_POLL_DELAY_TIME 1000 /* usecs */ - -/* - * value used to force bus reset in i2ohab_i_reset_interface() - */ -#define I2OHBA_FORCE_BUS_RESET 0x02 -#define PERIOD_MASK(val) ((val) & 0xff) -#define OFFSET_MASK(val) (((val) >> 8) & 0xff) - -/* - * timeout values - */ -#define I2OHBA_GRACE 10 /* Timeout margin (sec.) */ -#define I2OHBA_TIMEOUT_DELAY(secs, delay) (secs * (1000000 / delay)) - -typedef struct i2o_tid_scsi_ent { - uint16_t tid; /* associated TID */ - i2o_scsi_device_info_scalar_t scsi_info_scalar; -} i2o_tid_scsi_ent_t; - -struct i2ohba { - - /* - * Message request double link list chain - */ - struct i2ohba_cmd *i2ohba_reqhead; - struct i2ohba_cmd *i2ohba_reqtail; - - /* - * Mutex for the request or reply link list - */ - kmutex_t i2ohba_request_mutex; - /* - * Mutex for utilparam msg or reset param msg - */ - kmutex_t util_param_mutex[N_I2OHBA_TARGETS_WIDE]; - kmutex_t reset_mutex; - kcondvar_t util_param_cv[N_I2OHBA_TARGETS_WIDE]; - kcondvar_t reset_cv; - - /* - * Bus Adapter's Tid - */ - uint16_t i2ohba_tid; - - /* - * i2ohba shutdown flag - */ - uint8_t i2ohba_shutdown; - - /* - * i2ohba clear queue - */ - uint32_t i2ohba_throttle; - uint32_t i2ohba_counter; - - /* - * i2ohba timeout id - */ - timeout_id_t i2ohba_timeout_id; - - /* - * flag for updating properties in i2ohba_i_watch() - * to avoid updating in interrupt context - */ - uint16_t i2ohba_need_prop_update; - - /* - * Host adapter capabilities and offset/period values per target - * (dynamically changed by the target) - */ - uint16_t i2ohba_cap[N_I2OHBA_TARGETS_WIDE]; - uint16_t i2ohba_synch[N_I2OHBA_TARGETS_WIDE]; - uint8_t i2ohba_offset[N_I2OHBA_TARGETS_WIDE]; - uint32_t i2ohba_totsec[N_I2OHBA_TARGETS_WIDE]; - uint32_t i2ohba_secsz[N_I2OHBA_TARGETS_WIDE]; - - /* - * Transport structure for this instance of the hba - */ - scsi_hba_tran_t *i2ohba_tran; - - /* - * dev_info_t reference can be found in the transport structure - */ - dev_info_t *i2ohba_dip; - - /* - * IOP access handle (The IOP controls/associated with dip) - */ - i2o_iop_handle_t i2ohba_iophdl; - - /* - * Bus Adapter's Param - */ - i2o_hba_scsi_controller_info_scalar_t *i2ohba_scsi_controller; - - /* - * TID to SCSI/LUN target map, this hba can have upto 15 devices - */ - i2o_tid_scsi_ent_t i2ohba_tid_scsi_map[N_I2OHBA_TARGETS_WIDE]; - - i2o_tid_scsi_ent_t *i2ohba_tgt_id_map[N_I2OHBA_TARGETS_WIDE]; - - /* - * scsi options, etc from ddi_getprop() - * default value from the UtilParamGet - */ - int i2ohba_scsi_options; /* default one */ - int i2ohba_target_scsi_option[N_I2OHBA_TARGETS_WIDE]; - int i2ohba_initiator_id; - - /* - * scsi_reset_delay for i2o - */ - uint32_t i2ohba_scsi_reset_delay; - - - struct scsi_reset_notify_entry *i2ohba_reset_notify_listf; - - -}; - -#ifdef __cplusplus -} -#endif - -#endif /* _I2O_SCSI_VAR_H */
--- a/usr/src/uts/common/io/i2o/label.c Wed Apr 18 03:07:55 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,915 +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 2004 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/file.h> -#include <sys/cmn_err.h> -#include <sys/uio.h> -#include <sys/kmem.h> -#include <sys/sysmacros.h> -#include <sys/stat.h> -#include <sys/scsi/scsi.h> -#include <sys/stat.h> - -#include <sys/fdio.h> - -#include <sys/errno.h> -#include <sys/open.h> -#include <sys/varargs.h> -#include <sys/fs/pc_label.h> - -#include <sys/hdio.h> -#include <sys/dkio.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> - -#include <sys/dktp/fdisk.h> - - -#include <sys/fs/pc_label.h> - -#include <sys/i2o/i2omsg.h> -#include "i2o_bs.h" - - -static int dsklbl_chk(struct dk_label *, unsigned short *); -static void dsklbl_preplb(dsk_label_t *, dev_t, struct cb_ops *, int); -static void dsklbl_convert_lbl_to_pmap(struct dk_label *, dsk_label_t *); -static void dsklbl_savelb(struct dk_label *, dsk_label_t *); -static int dsklbl_rdvtoc(dsk_label_t *, struct buf *, struct cb_ops *); -char *partition_type(unsigned char); -void dsklbl_read_label(struct buf *, dsk_label_t *, struct cb_ops *, - struct dk_geom *, int); -void dsklbl_mprint(struct partition *); -int dsklbl_wrvtoc(dsk_label_t *, struct vtoc *, struct buf *, - struct cb_ops *); -void dsklbl_ondsklabel_to_vtoc(dsk_label_t *, struct vtoc *); -void dsklbl_vtoc_to_ondsklabel(dsk_label_t *, struct vtoc *); -void dsklbl_dgtoug(struct dk_geom *, struct dk_label *); -void dsklbl_ugtodg(struct dk_geom *, struct dk_label *); - -#ifdef DLBL_DEBUG -int label_debug = 1; - -#define DEBUGF(flag, args) \ - { if (label_debug & (flag)) cmn_err args; } -#else -#define DEBUGF(level, args) /* nothing */ -#endif - -static int -dsklbl_chk(struct dk_label *lbp, unsigned short *cksum) -{ - short *sp; - short count; - unsigned short sum; - - /* - * Check magic number of the label - */ - if (lbp->dkl_magic != DKL_MAGIC) { - DEBUGF(1, (CE_CONT, "?dsklbl_chk: magic: %x not MAGIC:" - "%x\n", lbp->dkl_magic, DKL_MAGIC)); - return (DDI_FAILURE); - } - if (lbp->dkl_vtoc.v_sanity != VTOC_SANE) { - DEBUGF(1, (CE_CONT, "?dsklbl_chk:sanity: %x not SANE:" - "%x\n", lbp->dkl_vtoc.v_sanity, VTOC_SANE)); - return (DDI_FAILURE); - } - if (lbp->dkl_vtoc.v_version != V_VERSION) { - DEBUGF(1, (CE_CONT, "?dsklbl_chk:version: %x not %x\n", - lbp->dkl_vtoc.v_version, V_VERSION)); - return (DDI_FAILURE); - } - - /* - * Check the checksum of the label - */ - sp = (short *)lbp; - sum = 0; - count = sizeof (struct dk_label) / sizeof (short); - while (count--) { - sum ^= *sp++; - } - - *cksum = sum; - if (sum) - return (DDI_FAILURE); - return (DDI_SUCCESS); -} - -/* - * We have this wonderful scenario where there exists two different kind - * of labeling scheme the x86/ppc vs. Sparc they are sufficiently different - * (read broken) that it justifies having two completely different preplb - * routines. - */ - -static void -dsklbl_preplb(dsk_label_t *lblp, dev_t dev, struct cb_ops *dev_ops, int type) -{ - long disksize; - struct dk_geom dkg; - int rval; - int s2size; - - - DEBUGF(1, (CE_CONT, "?dlbl_preplb(%x, %x)\n", lblp, dev)); - - bzero(&dkg, sizeof (struct dk_geom)); - bzero(&lblp->ondsklbl, sizeof (struct dk_label)); - - (*dev_ops->cb_ioctl)(dev, DKIOCG_PHYGEOM, - (uintptr_t)&dkg, FKIOCTL, (cred_t *)0, &rval); - - -#if defined(_SUNOS_VTOC_16) - lblp->ondsklbl.dkl_pcyl = lblp->pmap[FDISK_OFFSET+lblp->uidx].p_size / - (dkg.dkg_nhead * dkg.dkg_nsect); - - DEBUGF(1, (CE_CONT, "?dsklbl_preplb(p_size = %d, nhead = %d" - "nsect = %d)\n", - (lblp->pmap[FDISK_OFFSET+lblp->uidx].p_size), dkg.dkg_nhead, - dkg.dkg_nsect)); - -#elif defined(_SUNOS_VTOC_8) - lblp->ondsklbl.dkl_pcyl = (unsigned short)(lblp->pmap[FDISK_OFFSET+ - lblp->uidx].p_size / - (long)(dkg.dkg_nhead * dkg.dkg_nsect)); -#endif - - - - lblp->ondsklbl.dkl_acyl = 2; - lblp->ondsklbl.dkl_ncyl = lblp->ondsklbl.dkl_pcyl - - lblp->ondsklbl.dkl_acyl; - - /* or can use the size saved in ata_data (consider generic case */ - disksize = lblp->ondsklbl.dkl_ncyl * dkg.dkg_nhead * dkg.dkg_nsect; - - - lblp->ondsklbl.dkl_intrlv = 1; - lblp->ondsklbl.dkl_apc = 0; - lblp->ondsklbl.dkl_vtoc.v_nparts = V_NUMPAR; - lblp->ondsklbl.dkl_magic = DKL_MAGIC; - - lblp->ondsklbl.dkl_vtoc.v_sanity = VTOC_SANE; - lblp->ondsklbl.dkl_vtoc.v_version = V_VERSION; - - - /* - * Set up the p0 partition - */ - lblp->pmap[FPART_WHOLE+FDISK_OFFSET].p_start = 0; - lblp->pmap[FPART_WHOLE+FDISK_OFFSET].p_size = disksize; - lblp->pmap[FPART_WHOLE+FDISK_OFFSET].p_flag = V_UNMNT; - - - - /* NEEDS WORK add support for SPARC for CD */ - /* - * If CD-ROM, special-case: - * - lie about head/sect/cyl to get at every block on the disk - * - add full disk as slices 0 and 2 to the label - */ - - if (type == DKC_CDROM) { - /* - * Not heads * sectors * cyls, but the whole thing - * This applies later, to s2, as well. - */ - - - lblp->ondsklbl.dkl_nhead = 1; - lblp->ondsklbl.dkl_nsect = 1; - - /* NEEDS WORK get it from IOP probably not SD uses it too */ - lblp->ondsklbl.dkl_rpm = 200; - -#if defined(_SUNOS_VTOC_16) - - lblp->ondsklbl.dkl_vtoc.v_part[USLICE_WHOLE].p_start = 0; - lblp->ondsklbl.dkl_vtoc.v_part[USLICE_WHOLE].p_size = disksize; - lblp->ondsklbl.dkl_vtoc.v_part[USLICE_WHOLE].p_tag = V_BACKUP; - lblp->ondsklbl.dkl_vtoc.v_part[USLICE_WHOLE].p_flag = V_UNMNT; - - lblp->ondsklbl.dkl_vtoc.v_part[0].p_start = 0; - lblp->ondsklbl.dkl_vtoc.v_part[0].p_size = disksize; - lblp->ondsklbl.dkl_vtoc.v_part[0].p_tag = V_BACKUP; - lblp->ondsklbl.dkl_vtoc.v_part[0].p_flag = V_UNMNT; - - -#elif defined(_SUNOS_VTOC_8) - - /* Add full disk slice as slice 2 to the disk */ - - lblp->ondsklbl.dkl_map[USLICE_WHOLE].dkl_cylno = 0; - lblp->ondsklbl.dkl_map[USLICE_WHOLE].dkl_nblk = disksize; - - lblp->ondsklbl.dkl_map[0].dkl_cylno = 0; - lblp->ondsklbl.dkl_map[USLICE_WHOLE].dkl_nblk = disksize; - - - -#else -#error No VTOC format defined. -#endif - } else { - - /* NONE CD case */ - - - lblp->ondsklbl.dkl_nhead = dkg.dkg_nhead; - lblp->ondsklbl.dkl_nsect = dkg.dkg_nsect; - - lblp->ondsklbl.dkl_rpm = 3600; - - /* Add boot disk slice as slice 8 to the disk */ - - - /* - * There is a number of cases we have to worry about: - * - * 1) There is an fdisk partition but no Solaris partition. - * In this case the s2 slice size is zero since a valid - * Solaris partition must be present for us to decide the - * the size of the Solaris partition. - * - * 2) There is an fdisk parition and a Solaris partition. - * We got here because the Solaris partition was not labeled - * or the label has been corrupted, declare the entire Solaris - * parition as the s2 slice - * - * 3) There is no fdisk partition. - * We have to declare the entire disk as the s2 slice, - * with some room for the fdisk partition (I think) - */ - - if (lblp->fdiskpresent) { - if (lblp->uidx == 0) { /* FDISK - Solaris (1 above) */ - s2size = 0; - } else { /* FDISK + Solaris (2 above) */ - s2size = lblp->pmap[lblp->uidx+FDISK_OFFSET].p_size; - } - } else { /* No FDISK (3 above) */ - s2size = disksize; - } -#if defined(_SUNOS_VTOC_16) - /* - * If this is x86/PowerPC format label - */ - - lblp->ondsklbl.dkl_vtoc.v_sectorsz = NBPSCTR; - - /* Add full disk slice as slice 2 to the disk */ - - lblp->ondsklbl.dkl_vtoc.v_part[USLICE_WHOLE].p_start = 0; - lblp->ondsklbl.dkl_vtoc.v_part[USLICE_WHOLE].p_size = s2size; - lblp->ondsklbl.dkl_vtoc.v_part[USLICE_WHOLE].p_tag = V_BACKUP; - lblp->ondsklbl.dkl_vtoc.v_part[USLICE_WHOLE].p_flag = V_UNMNT; - - lblp->ondsklbl.dkl_vtoc.v_part[8].p_start = 0; - lblp->ondsklbl.dkl_vtoc.v_part[8].p_size = - dkg.dkg_nhead * dkg.dkg_nsect; - lblp->ondsklbl.dkl_vtoc.v_part[8].p_tag = V_BOOT; - lblp->ondsklbl.dkl_vtoc.v_part[8].p_flag = V_UNMNT; - - /* For now this is not a requirenment */ - /* Add Alternates disk slice as slice 9 to the disk */ - - lblp->ondsklbl.dkl_vtoc.v_part[9].p_start = - dkg.dkg_nhead * dkg.dkg_nsect; - lblp->ondsklbl.dkl_vtoc.v_part[9].p_size = - 2 * dkg.dkg_nhead * dkg.dkg_nsect; - lblp->ondsklbl.dkl_vtoc.v_part[9].p_tag = V_ALTSCTR; - lblp->ondsklbl.dkl_vtoc.v_part[9].p_flag = 0; - - (void) sprintf(lblp->ondsklbl.dkl_vtoc.v_asciilabel, - "DEFAULT cyl %d alt %d hd %d sec %d", - lblp->ondsklbl.dkl_ncyl, - lblp->ondsklbl.dkl_acyl, - lblp->ondsklbl.dkl_nhead, - lblp->ondsklbl.dkl_nsect); -#elif defined(_SUNOS_VTOC_8) - - /* Add full disk slice as slice 2 to the disk */ - - lblp->ondsklbl.dkl_map[USLICE_WHOLE].dkl_cylno = 0; - lblp->ondsklbl.dkl_map[USLICE_WHOLE].dkl_nblk = s2size; - - (void) sprintf(lblp->ondsklbl.dkl_asciilabel, - "DEFAULT cyl %d alt %d hd %d sec %d", - lblp->ondsklbl.dkl_ncyl, - lblp->ondsklbl.dkl_acyl, - lblp->ondsklbl.dkl_nhead, - lblp->ondsklbl.dkl_nsect); -#else -#error No VTOC format defined. -#endif - - - - } - - (void) dsklbl_chk(&lblp->ondsklbl, &(lblp->ondsklbl.dkl_cksum)); - /* - * now that an on disk label is manufactured, convert so - * that we start using right away - * is this the right thing to do, we also need a mutex - * to protext it. - * - * dsklbl_convert_lbl_to_pmap(&lblp->ondsklbl, lblp); - * - */ - -} - -static void -dsklbl_convert_lbl_to_pmap(struct dk_label *lbp, dsk_label_t *lblp) -{ - int i; -#if defined(_SUNOS_VTOC_16) - bcopy((caddr_t)&lbp->dkl_vtoc.v_part, - (caddr_t)lblp->pmap, sizeof (lbp->dkl_vtoc.v_part)); -#elif defined(_SUNOS_VTOC_8) - for (i = 0; i < NDKMAP; i++) { - lblp->pmap[i].p_tag = lbp->dkl_vtoc.v_part[i].p_tag; - lblp->pmap[i].p_flag = lbp->dkl_vtoc.v_part[i].p_flag; - lblp->pmap[i].p_start = lbp->dkl_map[i].dkl_cylno * - lblp->ondsklbl.dkl_nhead * lblp->ondsklbl.dkl_nsect; - lblp->pmap[i].p_size = lbp->dkl_map[i].dkl_nblk; - } -#else -#error No VTOC format defined. -#endif - for (i = 0; i < NDKMAP; i++) { - lblp->pmap[i].p_start += - lblp->pmap[lblp->uidx+FDISK_OFFSET].p_start; - } -} - -static void -dsklbl_savelb(struct dk_label *lbp, dsk_label_t *lblp) -{ - /* - * save the disk label in memory - */ - - bcopy((caddr_t)lbp, (caddr_t)&lblp->ondsklbl, sizeof (*lbp)); - - dsklbl_convert_lbl_to_pmap(lbp, lblp); -#ifdef DLBL_DEBUG - dsklbl_mprint(lblp->pmap); -#endif -} - -static int -dsklbl_rdvtoc(dsk_label_t *lblp, struct buf *bp, struct cb_ops *dev_ops) -{ - struct dk_label *lbp; - unsigned short sum; - - /* - * read the label - */ - DEBUGF(1, (CE_CONT, "?dsklbl_rdvtoc(%x, %x)\n", lblp, bp)); - bp->b_bcount = 1 * DEV_BSIZE; - bp->b_flags = B_READ; - bp->b_blkno = lblp->pmap[FDISK_OFFSET+lblp->uidx].p_start+VTOC_OFFSET; - - (*dev_ops->cb_strategy)(bp); - (void) biowait(bp); - - - lbp = (struct dk_label *)bp->b_un.b_addr; - - /* - * check label - */ - if ((!lbp) || (dsklbl_chk(lbp, &sum) == DDI_FAILURE)) { - DEBUGF(1, (CE_CONT, - "?label does not have a valid checksum\n")); - return (DDI_FAILURE); - } - /* - * record label information - */ - dsklbl_savelb(lbp, lblp); - lblp->vtocread = 1; - - return (DDI_SUCCESS); -} - - -struct { - unsigned char id; - char *name; -} partitionname[] = { - { 0x01, "DOS 12-bit FAT" }, - { 0x02, "XENIX /" }, - { 0x03, "XENIX /usr" }, - { 0x04, "DOS 16-bit FAT <32M" }, - { 0x05, "DOS Extended Partition" }, - { 0x06, "DOS 16-bit FAT >=32M" }, - { 0x07, "OS/2 IFS (e.g., HPFS) or NTFS or QNX2.x or Advanced UNIX" }, - { 0x08, "AIX boot or SplitDrive" }, - { 0x09, "AIX data or Coherent" }, - { 0x0a, "OS/2 Boot Manager" }, - { 0x0e, "DOS 16-bit FAT, CHS-mapped" }, - { 0x0f, "Extended partition, CHS-mapped" }, - { 0x10, "OPUS" }, - { 0x11, "OS/2 BM: Hidden DOS 12-bit FAT" }, - { 0x12, "Compaq config partition" }, - { 0x14, "OS/2 BM: Hidden DOS 16-bit FAT <32M" }, - { 0x16, "OS/2 BM: Hidden DOS 16-bit FAT >=32M" }, - { 0x17, "OS/2 BM: Hidden IFS (e.g., HPFS)" }, - { 0x18, "AST Windows swapfile" }, - { 0x24, "NEC DOS" }, - { 0x3c, "PartitionMagic recovery partition" }, - { 0x40, "Venix 80286" }, - { 0x41, "Linux/MINIX (sharing disk with DRDOS)" }, - { 0x42, "Linux swap (sharing disk with DRDOS) or SFS" }, - { 0x43, "Linux native (sharing disk with DRDOS)" }, - { 0x50, "OnTrack DM RO" }, - { 0x51, "OnTrack DM RW (DM6 Aux1) or Novell" }, - { 0x52, "CP/M or Microport SysV/AT" }, - { 0x53, "DM6 Aux3" }, - { 0x54, "DM6" }, - { 0x55, "EZ-Drive" }, - { 0x56, "Golden Bow VFeature Partitioned Volume." }, - { 0x5C, "Priam EDisk" }, - { 0x61, "SpeedStor" }, - { 0x63, "Unix System V (SCO, ISC UNIX, UnixWare, ...)" }, - { 0x64, "Novell Netware 2.xx" }, - { 0x65, "Novell Netware 3.xx or 4.xx" }, - { 0x70, "DiskSecure Multi-Boot" }, - { 0x75, "PC/IX" }, - { 0x77, "QNX4.x" }, - { 0x78, "QNX4.x 2nd part" }, - { 0x79, "QNX4.x 3rd part" }, - { 0x80, "MINIX until 1.4a" }, - { 0x81, "MINIX since 1.4b, early Linux, Mitac dmgr" }, - { 0x82, "Solaris" }, - { 0x83, "Linux native" }, - { 0x84, "OS/2 hidden C: drive" }, - { 0x85, "Linux extended partition" }, - { 0x86, "NTFS volume set??" }, - { 0x87, "NTFS volume set??" }, - { 0x93, "Amoeba" }, - { 0x94, "Amoeba bad track table" }, - { 0xa0, "IBM Thinkpad hibernation partition" }, - { 0xa5, "BSD/386, 386BSD, NetBSD, FreeBSD" }, - { 0xa7, "NEXTSTEP" }, - { 0xb7, "BSDI fs" }, - { 0xb8, "BSDI swap" }, - { 0xc1, "DRDOS/sec (FAT-12)" }, - { 0xc4, "DRDOS/sec (FAT-16, < 32M)" }, - { 0xc6, "DRDOS/sec (FAT-16, >= 32M)" }, - { 0xc7, "Syrinx" }, - { 0xdb, "Concurrent CP/M or Concurrent DOS or CTOS" }, - { 0xe1, "DOS access or SpeedStor 12-bit FAT extended partition" }, - { 0xe3, "DOS R/O or SpeedStor" }, - { 0xe4, "SpeedStor 16-bit FAT extended partition < 1024 cyl." }, - { 0xf1, "SpeedStor" }, - { 0xf2, "DOS 3.3+ secondary" }, - { 0xf4, "SpeedStor large partition" }, - { 0xfe, "SpeedStor >1024 cyl. or LANstep" }, - { 0xff, "Xenix Bad Block Table" } -}; - -char * -partition_type(unsigned char systid) -{ - int i; - - for (i = 0; i < sizeof (partitionname)/sizeof (partitionname[0]); i++) - if (partitionname[i].id == systid) - return (partitionname[i].name); - - return ("Unknown"); -} - -int -parse_fdisk_lbl(struct buf *bp, dsk_label_t *lblp, struct cb_ops *dev_ops, - struct dk_geom *dkg, int type) -{ - struct mboot *mbp; - struct ipart *fdp; - int i, uidx; - struct ipart fdisk[FD_NUMPART]; - - /* - * The whole disk is represented here (this is the p0 partition.) - */ - lblp->pmap[FPART_WHOLE+FDISK_OFFSET].p_start = 0; - lblp->pmap[FPART_WHOLE+FDISK_OFFSET].p_size = - dkg->dkg_ncyl * dkg->dkg_nhead * dkg->dkg_nsect; - lblp->pmap[FPART_WHOLE+FDISK_OFFSET].p_flag = V_UNMNT; - - mbp = (struct mboot *)bp->b_un.b_addr; - - if (!mbp || ltohs(mbp->signature) != MBB_MAGIC) { - - DEBUGF(1, (CE_CONT, - "?lbl 0x%x does not have an fdisk table.\n", - bp->b_edev)); -#ifdef DLBL_DEBUG - if (mbp) - DEBUGF(1, (CE_CONT, "?lbl " - "expteced magic: 0x%x got 0x%x\n", - MBB_MAGIC, ltohs(mbp->signature))); -#endif - DEBUGF(1, (CE_CONT, - "parse_label: b_edev %x " - "b_dev = %x\n", - bp->b_edev, bp->b_dev)); - - lblp->fdiskpresent = 0; - lblp->uidx = 0; - if (dsklbl_rdvtoc(lblp, bp, dev_ops) == DDI_FAILURE) { - bp->b_dev = cmpdev(bp->b_edev); - dsklbl_preplb(lblp, bp->b_edev, dev_ops, type); - } - return (DDI_SUCCESS); - } - /* - * The fdisk table does not begin on a 4-byte boundary within - * the master boot record; so, we need to recopy its contents to - * another data structure to avoid an alignment exception. - * This is not necessary for x86, but it avoids ifdefs - */ - fdp = fdisk; - bcopy((caddr_t)&(mbp->parts[0]), (caddr_t)fdp, sizeof (fdisk)); - - DEBUGF(1, (CE_CONT, - "?---------------------- Partition Table -----------------\n")); - DEBUGF(1, (CE_CONT, "?index relsect numsect type\n")); - DEBUGF(1, (CE_CONT, - "?------- ------- ------- -----------------------------\n")); - - for (uidx = 0, i = 1; i <= FD_NUMPART; i++, fdp++) { - if (!fdp->numsect) { - lblp->pmap[i+FDISK_OFFSET].p_flag = V_INVALID; - continue; - } - lblp->pmap[i+FDISK_OFFSET].p_start = ltohi(fdp->relsect); - lblp->pmap[i+FDISK_OFFSET].p_size = ltohi(fdp->numsect); - DEBUGF(1, (CE_CONT, "?%7d %7d %7d %4x (%s)\n", i, - ltohi(fdp->relsect), - ltohi(fdp->numsect), - fdp->systid, partition_type(fdp->systid))); - if (fdp->systid == SUNIXOS || fdp->systid == SUNIXOS2) { - if (uidx == 0) - uidx = i; - else if (fdp->bootid == ACTIVE) - uidx = i; - } - } - - lblp->fdiskpresent = 1; - lblp->uidx = uidx; - if (dsklbl_rdvtoc(lblp, bp, dev_ops) == DDI_FAILURE) { - bp->b_dev = cmpdev(bp->b_edev); - dsklbl_preplb(lblp, bp->b_edev, dev_ops, type); - - } - return (DDI_SUCCESS); -} - -void -dsklbl_read_label(struct buf *bp, dsk_label_t *lblp, struct cb_ops *dev_ops, - struct dk_geom *dkg, int type) -{ - /* - * read the label - */ - - bp->b_bcount = 1 * DEV_BSIZE; - bp->b_flags = B_READ; - bp->b_blkno = 0; - (*dev_ops->cb_strategy)(bp); - (void) biowait(bp); - (void) parse_fdisk_lbl(bp, lblp, dev_ops, dkg, type); -} - -#ifdef DLBL_DEBUG -void -dsklbl_mprint(struct partition *pp) -{ - int i; - - cmn_err(CE_CONT, "?----- UNIX slices -----\n"); - cmn_err(CE_CONT, "?slice start size\n"); - cmn_err(CE_CONT, "?----- ------ --------\n"); - for (i = 0; i < NDKMAP; i++, pp++) { - if (pp->p_size) { - cmn_err(CE_CONT, "?%5d %6x %x\n", i, pp->p_start, - pp->p_size); - } - } -} -#endif - - -int -dsklbl_wrvtoc(dsk_label_t *lblp, struct vtoc *vtocp, struct buf *bp, - struct cb_ops *dev_ops) -{ - register struct dk_label *lbp, *dp; - int status; - int backup_block; - int count; - - /* - * Data is originated from vtoc. One copy of the data is stored in - * lblp->ondsklbl. This is what we think of as the copy of the lable - * on this held in memory. The other copy (to the lbp) is to be - * written out to the disk. - */ - dp = &lblp->ondsklbl; - - bp->b_bcount = 1 * DEV_BSIZE; - bp->b_flags = B_WRITE | B_BUSY; - - lbp = (struct dk_label *)bp->b_un.b_addr; - - dsklbl_vtoc_to_ondsklabel(lblp, vtocp); - *lbp = lblp->ondsklbl; - - /* - * check label - */ - if (lblp->uidx) - bp->b_blkno = lblp->pmap[FDISK_OFFSET+lblp->uidx].p_start; - else - bp->b_blkno = 0; - bp->b_blkno += VTOC_OFFSET; - - - (*dev_ops->cb_strategy)(bp); - status = biowait(bp); - - if (status != 0 || dp->dkl_acyl == 0) - return (status); - - /* - * DO backup copies of vtoc - */ - - backup_block = ((dp->dkl_ncyl + dp->dkl_acyl - 1) * - (dp->dkl_nhead * dp->dkl_nsect)) + - ((dp->dkl_nhead - 1) * dp->dkl_nsect) + 1; - - bcopy((caddr_t)&(lblp->ondsklbl), (caddr_t)lbp, sizeof (*lbp)); - for (count = 1; count < 6; count++) { - - bp->b_blkno = - lblp->pmap[FDISK_OFFSET+lblp->uidx].p_start+backup_block; - bp->b_flags = B_WRITE | B_BUSY; - - (*dev_ops->cb_strategy)(bp); - (void) biowait(bp); - - backup_block += 2; - } - return (0); -} - - - -void -dsklbl_ondsklabel_to_vtoc(dsk_label_t *lblp, struct vtoc *vtocp) -{ -#if defined(_SUNOS_VTOC_16) - bcopy((caddr_t)&lblp->ondsklbl.dkl_vtoc, (caddr_t)vtocp, - sizeof (*vtocp)); -#elif defined(_SUNOS_VTOC_8) - int i; - long nblks; - struct dk_map2 *lpart; - struct dk_map *lmap; - struct partition *vpart; - - - /* - * Data is originated from vtoc. One copy of the data is stored in - * lblp->ondsklbl. This is what we think of as the copy of the label - * on the disk held in memory. The other copy (to the lbp) is to be - * written out to the disk. - */ - - /* - * Put appropriate vtoc structure fields into the disk label - * - */ - bcopy((caddr_t)(lblp->ondsklbl.dkl_vtoc.v_bootinfo), - (caddr_t)vtocp->v_bootinfo, sizeof (vtocp->v_bootinfo)); - - /* For now may want to add the sectorsz field to the generic structur */ - vtocp->v_sectorsz = NBPSCTR; /* sector size in bytes */ - - vtocp->v_sanity = lblp->ondsklbl.dkl_vtoc.v_sanity; - vtocp->v_version = lblp->ondsklbl.dkl_vtoc.v_version; - - bcopy((caddr_t)lblp->ondsklbl.dkl_vtoc.v_volume, - (caddr_t)vtocp->v_volume, LEN_DKL_VVOL); - - vtocp->v_nparts = lblp->ondsklbl.dkl_vtoc.v_nparts; - - bcopy((caddr_t)lblp->ondsklbl.dkl_vtoc.v_reserved, - (caddr_t)vtocp->v_reserved, sizeof (vtocp->v_reserved)); - - /* - * Note the conversion from starting sector number - * to starting cylinder number. - */ - nblks = lblp->ondsklbl.dkl_nsect * lblp->ondsklbl.dkl_nhead; - - lmap = lblp->ondsklbl.dkl_map; - lpart = (struct dk_map2 *)lblp->ondsklbl.dkl_vtoc.v_part; - vpart = vtocp->v_part; - - for (i = 0; i < (int)vtocp->v_nparts; i++) { - vpart->p_tag = lpart->p_tag; - vpart->p_flag = lpart->p_flag; - vpart->p_start = lmap->dkl_cylno * nblks; - vpart->p_size = lmap->dkl_nblk; - - lmap++; - lpart++; - vpart++; - } - - bcopy((caddr_t)lblp->ondsklbl.dkl_vtoc.v_timestamp, - (caddr_t)vtocp->timestamp, sizeof (vtocp->timestamp)); - - bcopy((caddr_t)lblp->ondsklbl.dkl_asciilabel, - (caddr_t)vtocp->v_asciilabel, - LEN_DKL_ASCII); - -#else -#error No VTOC format defined. -#endif -} - -void -dsklbl_vtoc_to_ondsklabel(dsk_label_t *lblp, struct vtoc *vtocp) -{ -#if defined(_SUNOS_VTOC_16) - bcopy((caddr_t)vtocp, (caddr_t)&(lblp->ondsklbl.dkl_vtoc), - sizeof (*vtocp)); -#elif defined(_SUNOS_VTOC_8) - /* - * Put appropriate vtoc structure fields into the disk label - * - */ - int i; - long nblks; - struct dk_map2 *lpart; - struct dk_map *lmap; - struct partition *vpart; - register struct dk_label *dp; - - /* - * Data is originated from vtoc. One copy of the data is stored in - * lblp->ondsklbl. This is what we think of as the copy of the label - * on this disk held in memory. The other copy (to the lbp) is to be - * written out to the disk. - */ - dp = &lblp->ondsklbl; - - - bcopy((caddr_t)vtocp->v_bootinfo, - (caddr_t)(lblp->ondsklbl.dkl_vtoc.v_bootinfo), - sizeof (vtocp->v_bootinfo)); - - lblp->ondsklbl.dkl_vtoc.v_sanity = vtocp->v_sanity; - lblp->ondsklbl.dkl_vtoc.v_version = vtocp->v_version; - - bcopy((caddr_t)vtocp->v_volume, - (caddr_t)lblp->ondsklbl.dkl_vtoc.v_volume, - LEN_DKL_VVOL); - - lblp->ondsklbl.dkl_vtoc.v_nparts = vtocp->v_nparts; - - bcopy((caddr_t)vtocp->v_reserved, - (caddr_t)lblp->ondsklbl.dkl_vtoc.v_reserved, - sizeof (vtocp->v_reserved)); - - /* - * Note the conversion from starting sector number - * to starting cylinder number. - */ - nblks = dp->dkl_nsect * dp->dkl_nhead; - lmap = lblp->ondsklbl.dkl_map; - lpart = (struct dk_map2 *)lblp->ondsklbl.dkl_vtoc.v_part; - vpart = vtocp->v_part; - - for (i = 0; i < (int)vtocp->v_nparts; i++) { - lpart->p_tag = vpart->p_tag; - lpart->p_flag = vpart->p_flag; - lmap->dkl_cylno = vpart->p_start / nblks; - lmap->dkl_nblk = vpart->p_size; - - lmap++; - lpart++; - vpart++; - } - - bcopy((caddr_t)vtocp->timestamp, - (caddr_t)lblp->ondsklbl.dkl_vtoc.v_timestamp, - sizeof (vtocp->timestamp)); - - bcopy((caddr_t)vtocp->v_asciilabel, - (caddr_t)lblp->ondsklbl.dkl_asciilabel, - LEN_DKL_ASCII); - -#else -#error No VTOC format defined. -#endif - - lblp->ondsklbl.dkl_cksum = 0; - (void) dsklbl_chk(&lblp->ondsklbl, &(lblp->ondsklbl.dkl_cksum)); -} - -void -dsklbl_dgtoug(struct dk_geom *up, struct dk_label *dp) -{ - DEBUGF(1, (CE_CONT, "?dsklbl_dgtoug: pcyl = %d ncyl = %d acyl = %d\n", - dp->dkl_pcyl, dp->dkl_ncyl, dp->dkl_acyl)); - - up->dkg_pcyl = dp->dkl_pcyl; - up->dkg_ncyl = dp->dkl_ncyl; - up->dkg_acyl = dp->dkl_acyl; -#if !defined(__sparc) - up->dkg_bcyl = dp->dkl_bcyl; -#endif - up->dkg_nhead = dp->dkl_nhead; - up->dkg_nsect = dp->dkl_nsect; - up->dkg_intrlv = dp->dkl_intrlv; - up->dkg_apc = dp->dkl_apc; - up->dkg_rpm = dp->dkl_rpm; - up->dkg_write_reinstruct = dp->dkl_write_reinstruct; - up->dkg_read_reinstruct = dp->dkl_read_reinstruct; -} - - - - -void -dsklbl_ugtodg(struct dk_geom *up, struct dk_label *dp) -{ - dp->dkl_pcyl = up->dkg_pcyl; - dp->dkl_ncyl = up->dkg_ncyl; - dp->dkl_acyl = up->dkg_acyl; -#if !defined(__sparc) - dp->dkl_bcyl = up->dkg_bcyl; -#endif - dp->dkl_nhead = up->dkg_nhead; - dp->dkl_nsect = up->dkg_nsect; - dp->dkl_intrlv = up->dkg_intrlv; - dp->dkl_apc = up->dkg_apc; - dp->dkl_rpm = up->dkg_rpm; - dp->dkl_write_reinstruct = up->dkg_write_reinstruct; - dp->dkl_read_reinstruct = up->dkg_read_reinstruct; -}
--- a/usr/src/uts/common/io/i2o/pci_to_i2o.c Wed Apr 18 03:07:55 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1137 +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" - -/* - * PCI-to-I2O bus nexus driver. - * - * The current implementation complies with the I2O Specification - * Version 1.5. So, it assumes only 32bit virtual addresses and - * 32bit context fields in I2O messages. - */ - -#include <sys/types.h> -#include <sys/cmn_err.h> -#include <sys/conf.h> -#include <sys/debug.h> -#include <sys/errno.h> -#include <sys/modctl.h> -#include <sys/ddidmareq.h> -#include <sys/ddi_impldefs.h> -#include <sys/ddi.h> -#include <sys/sunddi.h> -#include <sys/sunndi.h> -#include <sys/pci.h> -#include <sys/avintr.h> -#include <sys/bustypes.h> -#include <sys/kmem.h> -#include <sys/archsystm.h> -#include <sys/i2o/i2oexec.h> -#include "i2o_impl.h" - -char _depends_on[] = "misc/i2o_msg"; - -/* - * function prototypes for bus ops routines: - */ -static int -i2o_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr, - int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep); - -static int -i2o_bus_ctl(dev_info_t *dip, dev_info_t *rdip, - ddi_ctl_enum_t opt, void *a, void *v); - -static int -i2o_intr_op(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op, - ddi_intr_handle_impl_t *hdlp, void *result); - -struct bus_ops i2o_bus_ops = { - BUSO_REV, - nullbusmap, - NULL, - NULL, - NULL, - i_ddi_map_fault, - ddi_no_dma_map, /* 2.4 DDI only - not supported */ - i2o_dma_allochdl, - ddi_dma_freehdl, - ddi_dma_bindhdl, - ddi_dma_unbindhdl, - ddi_dma_flush, - ddi_dma_win, - ddi_dma_mctl, - i2o_bus_ctl, - ddi_bus_prop_op, - NULL, /* (* bus_get_eventcookie)() */ - NULL, /* (* bus_add_eventcall)() */ - NULL, /* (* bus_remove_eventcall)() */ - NULL, /* (* bus_post_event)() */ - NULL, /* interrupt control */ - 0, /* bus_config */ - 0, /* bus_unconfig */ - 0, /* bus_fm_init */ - 0, /* bus_fm_fini */ - 0, /* bus_fm_access_enter */ - 0, /* bus_fm_access_exit */ - 0, /* bus_power */ - i2o_intr_op /* bus_intr_op */ -}; - - -/* - * Function prototypes for dev_ops entry points. - */ - -static int i2o_probe(dev_info_t *); -static int i2o_attach(dev_info_t *, ddi_attach_cmd_t); -static int i2o_detach(dev_info_t *, ddi_detach_cmd_t); - -struct dev_ops i2o_dev_ops = { - DEVO_REV, /* devo_rev */ - 0, /* refcnt */ - ddi_no_info, /* info */ - nulldev, /* identify */ - i2o_probe, /* probe */ - i2o_attach, /* attach */ - i2o_detach, /* detach */ - nodev, /* reset */ - (struct cb_ops *)0, /* driver operations */ - &i2o_bus_ops /* bus operations */ -}; - -/* - * Per IOP instance data maintained by the i2o nexus driver. - */ - -typedef struct iop_nexus_instance { - dev_info_t *dip; /* devinfo pointer */ - caddr_t iop_base_addr; /* base address of shared memory */ - int iop_state; /* state of IOP */ - off_t shared_memsize; /* size of shared memory */ - int iop_intr_pri; /* interrupt priority */ - ddi_acc_handle_t acc_handle; /* DDI access handle for shared mem */ - i2o_iop_handle_t i2o_iop_handle; /* IOP handle from the i2o_msg module */ - ddi_iblock_cookie_t iblock_cookie; - ddi_idevice_cookie_t idevice_cookie; - i2o_msg_trans_t i2o_msg_trans; -#ifdef I2O_DEBUG - uint_t intr_count; /* IOP interrupt counter */ -#endif -} iop_nexus_instance_t; - - -/* Function prototypes for local functions */ - -static uint_t i2o_intr(caddr_t); -static uint_t i2o_alloc_msg(i2o_nexus_handle_t handle); -static int i2o_send_msg(i2o_nexus_handle_t handle, uint_t mfa); -static uint_t i2o_recv_msg(i2o_nexus_handle_t handle); -static void i2o_disable_intr(i2o_nexus_handle_t handle); -static void i2o_enable_intr(i2o_nexus_handle_t handle); -static void i2o_free_msg(i2o_nexus_handle_t handle, uint_t mfa); -static void i2o_create_devinfo(iop_nexus_instance_t *iop); -#ifdef I2O_DEBUG -static void dump_exec_params_0001(iop_nexus_instance_t *iop); -void i2o_msg_reply(void *m, ddi_acc_handle_t acc_hdl); -#endif - -/* - * DMA attribute structure for I2O Spec version 1.5. - */ -static ddi_dma_attr_t i2o_dma_attr = { - DMA_ATTR_VERSION, /* version number */ - (uint64_t)0, /* low DMA address range */ - (uint64_t)0xFFFFFFFF, /* high DMA address range */ - (uint64_t)0x00FFFFFF, /* DMA counter register */ - 1, /* DMA address alignment */ - 1, /* DMA burstsizes */ - 1, /* min effective DMA size */ - (uint64_t)0xFFFFFFFF, /* max DMA xfer size */ - (uint64_t)0xFFFFFFFF, /* segment boundary */ - 0xFFFF, /* s/g length */ - 1, /* granularity of device */ - 0 /* Bus specific DMA flags */ -}; - - -/* local definitions for iop_state values */ -#define IOP_INIT 0 /* IOP is being initialized */ -#define IOP_ONLINE 1 /* IOP initialization is complete */ - - -/* Default interrupt priority for IOP interrupt */ -#define IOP_INTR_PRI_DEFAULT 5 - - -#ifdef I2O_DEBUG -int i2o_nexus_debug = 0; -#define DEBUGF(level, args) \ - { if (i2o_nexus_debug >= (level)) cmn_err args; } -#else -#define DEBUGF(level, args) /* nothing */ -#endif - - -/* - * Module linkage information for the kernel. - */ -static struct modldrv modldrv = { - &mod_driverops, - "Nexus for I2O Spec v1.5, driver %I%", - &i2o_dev_ops, -}; - - -/* - * Device attribute structure for I2O version 1.5. - * - * I2O data structures (whether it is in IOP's memory or host memory) - * are in Little Endian format. - */ -static ddi_device_acc_attr_t i2o_dev_acc_attr = { - DDI_DEVICE_ATTR_V0, - DDI_STRUCTURE_LE_ACC, /* devacc_attr_endian_flags for LE access */ - DDI_STRICTORDER_ACC /* devacc_attr_dataorder */ -}; - - -static struct modlinkage modlinkage = { - MODREV_1, - &modldrv, - NULL -}; - -static void *i2o_nexus_state; - -int -_init(void) -{ - int error; - - if ((error = ddi_soft_state_init(&i2o_nexus_state, - sizeof (struct iop_nexus_instance), 1)) != 0) - return (error); - - if ((error = mod_install(&modlinkage)) != 0) - ddi_soft_state_fini(&i2o_nexus_state); - - return (error); -} - -int -_fini(void) -{ - int error; - - if ((error = mod_remove(&modlinkage)) == 0) - ddi_soft_state_fini(&i2o_nexus_state); - - return (error); -} - -int -_info(struct modinfo *modinfop) -{ - return (mod_info(&modlinkage, modinfop)); -} - - -/* - * ********************************************************************** - * * bus_ops entry points * - * ********************************************************************** - */ - - -/* - * NOTE: THIS FUNCTION IS NOT APPLICABLE FOR I2O. RETURN ERROR. - */ -/*ARGSUSED*/ -static int -i2o_intr_op(dev_info_t *dip, dev_info_t *rdip, ddi_intr_op_t op, - ddi_intr_handle_impl_t *hdlp, void *result) -{ - return (DDI_FAILURE); -} - -static int -i2o_dma_allochdl(dev_info_t *dip, dev_info_t *rdip, ddi_dma_attr_t *attr, - int (*waitfp)(caddr_t), caddr_t arg, ddi_dma_handle_t *handlep) -{ - /* - * Adjust DMA attributes structure as per I2O Spec version 1.5. - */ - ddi_dma_attr_merge(attr, &i2o_dma_attr); - - return (ddi_dma_allochdl(dip, rdip, attr, waitfp, arg, handlep)); -} - -static int -i2o_bus_ctl(dev_info_t *dip, dev_info_t *rdip, - ddi_ctl_enum_t opt, void *a, void *v) -{ - char name[16]; - uint_t tid; - int error; - - switch (opt) { - case DDI_CTLOPS_INITCHILD: - tid = ddi_prop_get_int(DDI_DEV_T_ANY, (dev_info_t *)a, - DDI_PROP_DONTPASS, "i2o-device-id", -1); - if (tid == (uint_t)-1) - return (DDI_FAILURE); - (void) sprintf(name, "%x", tid); - error = impl_ddi_sunbus_initchild((dev_info_t *)a); - if (error != DDI_SUCCESS) - return (DDI_FAILURE); - ddi_set_name_addr((dev_info_t *)a, name); - return (DDI_SUCCESS); - - case DDI_CTLOPS_UNINITCHILD: - impl_ddi_sunbus_removechild(a); - return (DDI_SUCCESS); - - case DDI_CTLOPS_REPORTDEV: - { - cmn_err(CE_CONT, "?%s%d at %s%d: TID %s\n", - ddi_driver_name(rdip), ddi_get_instance(rdip), - ddi_driver_name(dip), ddi_get_instance(dip), - ddi_get_name_addr(rdip)); - - return (DDI_SUCCESS); - } - - /* - * These functions shouldn't be called by the OSMs. Return error. - */ - case DDI_CTLOPS_DMAPMAPC: - case DDI_CTLOPS_SIDDEV: - case DDI_CTLOPS_SLAVEONLY: - case DDI_CTLOPS_AFFINITY: - case DDI_CTLOPS_REGSIZE: - case DDI_CTLOPS_NREGS: - case DDI_CTLOPS_POKE: - case DDI_CTLOPS_PEEK: - return (DDI_FAILURE); - - default: - /* let the parent handle the rest */ - return (ddi_ctlops(dip, rdip, opt, a, v)); - } -} - -/* - * ********************************************************************** - * * dev_ops entry points * - * ********************************************************************** - */ - -/* - * Determine if the IOP is present. - */ -static int -i2o_probe(dev_info_t *dip) -{ - ddi_acc_handle_t handle; - uint8_t base_class, sub_class, prog_class; - - if (pci_config_setup(dip, &handle) != DDI_SUCCESS) - return (DDI_PROBE_FAILURE); - - base_class = pci_config_get8(handle, PCI_CONF_BASCLASS); - sub_class = pci_config_get8(handle, PCI_CONF_SUBCLASS); - prog_class = pci_config_get8(handle, PCI_CONF_PROGCLASS); - - pci_config_teardown(&handle); - - if ((base_class != PCI_I2O_BASE_CLASS) || - (sub_class != PCI_I2O_SUB_CLASS) || - (prog_class != PCI_I2O_PROG_CLASS1)) - - return (DDI_PROBE_FAILURE); - - return (DDI_PROBE_SUCCESS); -} - -/* - * attach(9E) - */ - -static int -i2o_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) -{ - iop_nexus_instance_t *iop = NULL; - ddi_acc_handle_t handle; - int nregs; - int csr; - uint32_t base_reg0; - int instance; - - if (cmd != DDI_ATTACH) - return (DDI_FAILURE); - - if (pci_config_setup(dip, &handle) != DDI_SUCCESS) - return (DDI_FAILURE); - - /* - * turn on Master Enable and Memory Access Enable bits. - */ - csr = pci_config_get32(handle, PCI_CONF_COMM); - pci_config_put32(handle, PCI_CONF_COMM, - csr | PCI_COMM_ME | PCI_COMM_MAE); - - base_reg0 = pci_config_get32(handle, PCI_CONF_BASE0); - - ASSERT((base_reg0 & PCI_BASE_SPACE_M) == 0); - - pci_config_teardown(&handle); - - /* - * Allocate iop_nexus_instance soft state structure for this - * IOP instance. - */ - instance = ddi_get_instance(dip); - if (ddi_soft_state_zalloc(i2o_nexus_state, instance) != DDI_SUCCESS) - return (DDI_FAILURE); - iop = (iop_nexus_instance_t *)ddi_get_soft_state(i2o_nexus_state, - instance); - - iop->dip = dip; - iop->iop_state = IOP_INIT; - - /* - * Map the device memory (i.e IOP's shared local memory). - * - * ISSUE: Mapping the whole shared memory (4 to 16M) may be too - * much. But, to map the pages that we really need it requires - * reading the inbound FIFO to find out the range of offsets used - * for allocating inbound message frames by the IOP. It is possible - * to find the range of MFAs and then map only those pages. But, - * this will bring up the following issues: - * - * 1. IOP reset may reallocate the message frames so the - * range may change. (Note: currently i2o_msg_iop_init() - * does IOP reset so it will be a problem.) - * 2. I2O Spec doesn't restrict the IOP allocating inbound - * message frames dynamically. - * 3. Reading the MFAs should be done when no other external - * agent (e.g other IOPs) is accessing the IOP. - * - * This issue is addressed by the I2O Spec version 2.0 where - * IOP gives additional parameters which gives us the information - * we need to map only the pages that have the MFAs. For now, we - * will map the whole thing. - */ - - if ((ddi_dev_nregs(dip, &nregs) != DDI_SUCCESS) || (nregs < 2) || - (ddi_dev_regsize(dip, 1, &iop->shared_memsize) != DDI_SUCCESS)) - goto cleanup; - - DEBUGF(1, (CE_CONT, "!i2o_attach: IOP shared memory size 0x%x", - (int)iop->shared_memsize)); - - if (ddi_regs_map_setup(dip, 1, &iop->iop_base_addr, 0, - iop->shared_memsize, &i2o_dev_acc_attr, - &iop->acc_handle) != DDI_SUCCESS) { - DEBUGF(1, (CE_CONT, "i2o_attach: ddi_regs_map_setup failed")); - goto cleanup; - } - - /* - * Initialize i2o_msg_trans data structure for i2o_msg module. - */ - iop->i2o_msg_trans.version = I2O_MSG_TRANS_VER; - iop->i2o_msg_trans.iop_base_addr = iop->iop_base_addr; - iop->i2o_msg_trans.iop_inbound_fifo_paddr = - (base_reg0 & PCI_BASE_M_ADDR_M) + PCI_IOP_INBOUND_FREELIST_FIFO; - iop->i2o_msg_trans.acc_handle = iop->acc_handle; - iop->i2o_msg_trans.nexus_handle = (i2o_nexus_handle_t)iop; - iop->i2o_msg_trans.iblock_cookie = iop->iblock_cookie; - iop->i2o_msg_trans.i2o_trans_msg_alloc = i2o_alloc_msg; - iop->i2o_msg_trans.i2o_trans_msg_send = i2o_send_msg; - iop->i2o_msg_trans.i2o_trans_msg_recv = i2o_recv_msg; - iop->i2o_msg_trans.i2o_trans_msg_freebuf = i2o_free_msg; - iop->i2o_msg_trans.i2o_trans_disable_intr = i2o_disable_intr; - iop->i2o_msg_trans.i2o_trans_enable_intr = i2o_enable_intr; - - /* Disable IOP interrupts */ - i2o_disable_intr((i2o_nexus_handle_t)iop); - - /* - * Register an interrupt handler for IOP interrupts. If the - * property 'iop_intr_pri' is set then use that otherwise - * set the priority to 5. - */ - iop->iop_intr_pri = ddi_prop_get_int(DDI_DEV_T_ANY, dip, - DDI_PROP_DONTPASS, "iop_intr_pri", IOP_INTR_PRI_DEFAULT); - - if (ddi_add_intr(dip, 0, &iop->iblock_cookie, &iop->idevice_cookie, - i2o_intr, (caddr_t)iop) != DDI_SUCCESS) - goto cleanup; - - /* - * Call i2o_msg_iop_init() to initialize the IOP. - */ - - cmn_err(CE_CONT, "\rI2O Nexus: Initializing IO Processor %d...", - instance); - - iop->i2o_iop_handle = i2o_msg_iop_init(dip, &iop->i2o_msg_trans); - - if (iop->i2o_iop_handle == NULL) { /* IOP Initialization failed */ - ddi_remove_intr(dip, 0, iop->iblock_cookie); - cmn_err(CE_CONT, "FAILED.\n"); - goto cleanup; - } - - cmn_err(CE_CONT, "done.\n"); - - /* Enable IOP interrupts now */ - i2o_enable_intr((i2o_nexus_handle_t)iop); - - iop->iop_state = IOP_ONLINE; /* now IOP is ready */ - - ddi_report_dev(dip); - -#ifdef I2O_DEBUG - if (i2o_nexus_debug >= 2) - dump_exec_params_0001(iop); -#endif - -#ifndef I2O_BOOT_SUPPORT - - /* - * Create the devinfo nodes for the I2O devices. - */ - i2o_create_devinfo(iop); - -#endif - return (DDI_SUCCESS); - -cleanup: - /* - * free up the allocated resources and return error. - */ - - if (iop->iop_base_addr != 0) - ddi_regs_map_free(&iop->acc_handle); - - /* free up the soft state structure for this instance */ - ddi_soft_state_free(i2o_nexus_state, instance); - - return (DDI_FAILURE); -} - -/* - * detach(9E) - */ - -static int -i2o_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) -{ - iop_nexus_instance_t *iop = NULL; - int instance; - - instance = ddi_get_instance(dip); - iop = (iop_nexus_instance_t *)ddi_get_soft_state(i2o_nexus_state, - instance); - - if (iop == NULL) - return (DDI_FAILURE); - - switch (cmd) { - case DDI_DETACH: - - /* reset the IOP */ - if (i2o_msg_iop_uninit(iop->i2o_iop_handle) != DDI_SUCCESS) - return (DDI_FAILURE); - - /* unregister the interrupt handler */ - ddi_remove_intr(dip, 0, iop->iblock_cookie); - - /* unmap the shared device memory */ - ddi_regs_map_free(&iop->acc_handle); - - /* free up the soft state structure for this instance */ - ddi_soft_state_free(i2o_nexus_state, instance); - - return (DDI_SUCCESS); - - case DDI_SUSPEND: /* XXX FIX IT LATER */ - case DDI_PM_SUSPEND: /* XXX FIX IT LATER */ - /* fall thru */ - - default: - return (DDI_FAILURE); - } -} - -/* - * IOP interrupt handler. - * - * Note: In the current I2O Spec (version 1.5) only Outbound PostList - * service interrupt is defined. So, this routine handles this - * interrupt. - * - * This function simply calls i2o_msg_process_reply_queue() to process - * the reply messages. It is assumed that the i2o_msg_process_reply_queue() - * will putback the processed messages into the freelist. - */ - -static uint_t -i2o_intr(caddr_t arg) -{ - register iop_nexus_instance_t *iop; - uint32_t intr_state; - uint32_t intr_mask; - - iop = (iop_nexus_instance_t *)arg; - - if (iop->iop_state != IOP_ONLINE) - return (DDI_INTR_UNCLAIMED); - - intr_state = ddi_get32(iop->acc_handle, - (uint32_t *)(iop->iop_base_addr + PCI_IOP_INTR_STATUS_REG)); - - intr_mask = ddi_get32(iop->acc_handle, - (uint32_t *)(iop->iop_base_addr + PCI_IOP_INTR_MASK_REG)); - - if (((intr_state & I2O_OUTBOUND_POSTLIST_SERVICE_INTR_MASK) == 0) || - ((intr_mask & I2O_OUTBOUND_POSTLIST_SERVICE_INTR_MASK) != 0)) - /* No interrupt from this IOP */ - return (DDI_INTR_UNCLAIMED); - - /* Let the I2O Message module process the reply message queue */ - i2o_msg_process_reply_queue(iop->i2o_iop_handle); - -#ifdef I2O_DEBUG - iop->intr_count++; /* debugging */ -#endif - - return (DDI_INTR_CLAIMED); -} - -/* - * *********************************************************************** - * ** Transport functions to support the I2O Message module ** - * ** ** - * ** NOTE: Locking for these functions are done within the I2O ** - * ** Message module. ** - * *********************************************************************** - */ - -/* - * Get an MFA from the Inbound FreeList FIFO. - */ -static uint_t -i2o_alloc_msg(i2o_nexus_handle_t handle) -{ - register iop_nexus_instance_t *iop; - - iop = (iop_nexus_instance_t *)handle; - - return (ddi_get32(iop->acc_handle, (uint32_t *)(iop->iop_base_addr + - PCI_IOP_INBOUND_FREELIST_FIFO))); -} - -/* - * Post the MFA to Inbound PostList FIFO. - */ -static int -i2o_send_msg(i2o_nexus_handle_t handle, uint_t mfa) -{ - register iop_nexus_instance_t *iop; - - iop = (iop_nexus_instance_t *)handle; - - if (mfa < iop->shared_memsize) { - ddi_put32(iop->acc_handle, (uint32_t *)(iop->iop_base_addr + - PCI_IOP_INBOUND_POSTLIST_FIFO), mfa); - - return (DDI_SUCCESS); - } - - return (DDI_FAILURE); /* invalid argument(s) */ -} - -/* - * Get the reply MFA from the Outbound PostList FIFO. - */ -static uint_t -i2o_recv_msg(i2o_nexus_handle_t handle) -{ - register iop_nexus_instance_t *iop; - - iop = (iop_nexus_instance_t *)handle; - - return (ddi_get32(iop->acc_handle, (uint32_t *)(iop->iop_base_addr + - PCI_IOP_OUTBOUND_POSTLIST_FIFO))); -} - -/* - * Return reply MFA to the Outbound FreeList FIFO. - */ -static void -i2o_free_msg(i2o_nexus_handle_t handle, uint_t mfa) -{ - register iop_nexus_instance_t *iop; - - iop = (iop_nexus_instance_t *)handle; - - ddi_put32(iop->acc_handle, (uint32_t *)(iop->iop_base_addr + - PCI_IOP_OUTBOUND_FREELIST_FIFO), mfa); -} - -/* - * Disable IOP hardware interrupts. Currently only bit 3 in the Interrupt - * Mask register is defined and it is for outbound postlist service - * interrupt. (See section 4.2.1.5). - */ - -static void -i2o_disable_intr(i2o_nexus_handle_t handle) -{ - register iop_nexus_instance_t *iop; - uint_t intr_mask; - - iop = (iop_nexus_instance_t *)handle; - - intr_mask = ddi_get32(iop->acc_handle, - (uint32_t *)(iop->iop_base_addr + PCI_IOP_INTR_MASK_REG)); - - ddi_put32(iop->acc_handle, - (uint32_t *)(iop->iop_base_addr + PCI_IOP_INTR_MASK_REG), - intr_mask | I2O_OUTBOUND_POSTLIST_SERVICE_INTR_MASK); -} - -/* - * Enable IOP hardware interrupts. Currently only bit 3 in the Interrupt - * Mask register is defined and it is for outbound postlist service - * interrupt. (See section 4.2.1.5). - */ - -static void -i2o_enable_intr(i2o_nexus_handle_t handle) -{ - register iop_nexus_instance_t *iop; - uint_t intr_mask; - - iop = (iop_nexus_instance_t *)handle; - - intr_mask = ddi_get32(iop->acc_handle, - (uint32_t *)(iop->iop_base_addr + PCI_IOP_INTR_MASK_REG)); - - ddi_put32(iop->acc_handle, (uint32_t *)(iop->iop_base_addr + - PCI_IOP_INTR_MASK_REG), - intr_mask & ~I2O_OUTBOUND_POSTLIST_SERVICE_INTR_MASK); -} - -#ifndef I2O_BOOT_SUPPORT - -/* - * Since we don't have boot support yet, we need to create the devinfo - * nodes for the I2O devices here. No devinfo nodes are created for - * SCSI Peripheral class devices. For adapter devices, if the adapter - * is host visible (HRT has this information) then there may be a - * devinfo node else where in the devinfo tree. For each host visible - * adapter device we need to prune any other devinfo nodes for this - * adapter in the system. - */ - -static void -i2o_create_devinfo(iop_nexus_instance_t *iop) -{ - i2o_lct_t *lct; - ddi_acc_handle_t acc_hdl; - uint_t nent; - uint_t local_tid; - uint_t user_tid; - uint_t class; - uint_t sub_class; - dev_info_t *cdip; - char *nodename, *compat_name, *dev_type; - int i; - - /* - * Step 1 - * - * Get HRT and look for any adapters that are present, assigned to - * IOP but not hidden. For each of those adapters we need to - * remove any devinfo nodes that may be present else where in - * devinfo tree. - */ - - /* - * For now, we assume that all adpaters that are controlled - * by the IOP are hidden from the host. This step can be - * implemented easily in the boot system (i.e devconf on x86) - * when that phase is implemented. - */ - - /* XXX DEFER IT FOR NOW XXX */ - - /* - * Step 2 - * - * Create the devinfo nodes for each I2O class device that - * is not claimed (i.e UserTID == 0xFFF) and is not of - * SCSI peripheral type. - */ - - i2o_msg_get_lct_info(iop->i2o_iop_handle, &lct, &acc_hdl); - nent = ((ddi_get16(acc_hdl, &lct->TableSize) << 2) - sizeof (i2o_lct_t) - + sizeof (i2o_lct_entry_t)) / sizeof (i2o_lct_entry_t); - - for (i = 0; i < nent; i++) { - - /* If the device is already claimed then continue */ - user_tid = get_lct_entry_UserTID(&lct->LCTEntry[i], acc_hdl); - if (user_tid != 0xFFF) - continue; - - class = get_lct_entry_Class(&lct->LCTEntry[i], acc_hdl); - sub_class = ddi_get32(acc_hdl, &lct->LCTEntry[i].SubClassInfo); - - switch (class) { - case I2O_CLASS_EXECUTIVE: - case I2O_CLASS_DDM: - continue; - - case I2O_CLASS_ATE_PORT: - case I2O_CLASS_ATE_PERIPHERAL: - case I2O_CLASS_FLOPPY_CONTROLLER: - case I2O_CLASS_FLOPPY_DEVICE: - case I2O_CLASS_SEQUENTIAL_STORAGE: - case I2O_CLASS_LAN: - case I2O_CLASS_WAN: - case I2O_CLASS_FIBRE_CHANNEL_PORT: - case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL: - /* For now, ingore these types */ - continue; - - case I2O_CLASS_SCSI_PERIPHERAL: - continue; - - case I2O_CLASS_RANDOM_BLOCK_STORAGE: - nodename = "disk"; - compat_name = "i2o_bs"; - dev_type = "block"; - break; - case I2O_CLASS_BUS_ADAPTER_PORT: - nodename = "adapter"; - compat_name = "i2o_scsi"; - /* - * sub_class should indicate the type of bus. - * XXX Check this with Symbios. - */ - if (sub_class == 0x3) - dev_type = "scsi-3"; - else if (sub_class == 0x2) - dev_type = "scsi-2"; - else - dev_type = "scsi"; - break; - default: - continue; - } - - local_tid = get_lct_entry_LocalTID(&lct->LCTEntry[i], acc_hdl); - - cdip = NULL; - - /* create the devinfo node */ - if (ndi_devi_alloc(iop->dip, nodename, - (pnode_t)DEVI_SID_NODEID, &cdip) != NDI_SUCCESS) { - cmn_err(CE_WARN, - "i2o_create_devinfo: ndi_devi_alloc failed"); - goto fail; - } - - /* create the properties */ - - if (ndi_prop_update_int(DDI_DEV_T_NONE, cdip, "i2o-device-id", - local_tid) != DDI_PROP_SUCCESS) - goto fail; - if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, "device-type", - dev_type) != DDI_PROP_SUCCESS) - goto fail; - if (ndi_prop_update_string(DDI_DEV_T_NONE, cdip, - "compatible", compat_name) != DDI_PROP_SUCCESS) - goto fail; - - /* now, attach the driver */ - (void) ndi_devi_online(cdip, NDI_ONLINE_ATTACH); - } - - return; - -fail: - if (cdip != NULL) { - (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, "i2o-device-id"); - (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, "compatible"); - (void) ndi_prop_remove(DDI_DEV_T_NONE, cdip, "device-type"); - if (ndi_devi_free(cdip) != NDI_SUCCESS) { - cmn_err(CE_WARN, - "i2o_create_devinfo: ndi_devi_free failed"); - } - } -} - -#endif - -#ifdef I2O_DEBUG - -static ddi_dma_attr_t i2o_dma_attr_contig = { - DMA_ATTR_VERSION, /* version number */ - (uint64_t)0, /* low DMA address range */ - (uint64_t)0xFFFFFFFF, /* high DMA address range */ - (uint64_t)0x00FFFFFF, /* DMA counter register */ - 1, /* DMA address alignment */ - 1, /* DMA burstsizes */ - 1, /* min effective DMA size */ - (uint64_t)0xFFFFFFFF, /* max DMA xfer size */ - (uint64_t)0xFFFFFFFF, /* segment boundary */ - 0x1, /* s/g length */ - 1, /* granularity of device */ - 0 /* Bus specific DMA flags */ -}; - -kmutex_t test_mutex; -kcondvar_t test_cv; -volatile int test_result; - -static void -dump_exec_params_0001(iop_nexus_instance_t *iop) -{ - ddi_dma_handle_t dma_handle = NULL; - ddi_acc_handle_t acc_hdl, acc_hdl2; - size_t real_length; - ddi_dma_cookie_t dma_cookie; - uint_t ncookies; - caddr_t buf = NULL; - uint32_t ops_block_size, results_block_size; - i2o_util_params_get_message_t *msgp; - i2o_sge_simple_element_t *sgl; - /* operations block info */ - i2o_param_operations_list_header_t *ops_block_head; - i2o_param_operation_all_template_t *ops_block; - /* scalar parameters */ - i2o_exec_iop_message_if_scalar_t *message_if; - i2o_msg_handle_t msg_handle; - - /* allocate a DMA handle */ - if (ddi_dma_alloc_handle(iop->dip, &i2o_dma_attr_contig, DDI_DMA_SLEEP, - NULL, &dma_handle) != DDI_SUCCESS) { - goto cleanup; - } - - ops_block_size = sizeof (*ops_block_head) + sizeof (*ops_block); - - results_block_size = - sizeof (i2o_param_results_list_header_t) + - sizeof (i2o_param_read_operation_result_t) + - sizeof (*message_if) + - sizeof (i2o_param_error_info_template_t); - - /* Allocate a buffer for operation block */ - if (ddi_dma_mem_alloc(dma_handle, ops_block_size + results_block_size, - &i2o_dev_acc_attr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, - &buf, &real_length, &acc_hdl) != DDI_SUCCESS) { - goto cleanup; - } - - bzero((caddr_t)buf, real_length); - - if (ddi_dma_addr_bind_handle(dma_handle, NULL, buf, - real_length, DDI_DMA_READ | DDI_DMA_STREAMING, DDI_DMA_SLEEP, - NULL, &dma_cookie, &ncookies) != DDI_SUCCESS) { - - DEBUGF(1, (CE_CONT, - "dump_exec_params_0001: cannot bind memory")); - goto cleanup; - } - - DEBUGF(1, (CE_CONT, - "dump_exec_params_0001: dma_bind (vaddr %p paddr %x length %x)", - (void *)buf, dma_cookie.dmac_address, - (int)dma_cookie.dmac_size)); - - ops_block_head = (i2o_param_operations_list_header_t *)buf; - ops_block = (i2o_param_operation_all_template_t *) - (buf + sizeof (*ops_block_head)); - - /* initialize the operations block header */ - ddi_put16(acc_hdl, &ops_block_head->OperationCount, 1); - - /* initialize operations block for group 0001 */ - ddi_put16(acc_hdl, &ops_block[0].Operation, - I2O_PARAMS_OPERATION_FIELD_GET); - ddi_put16(acc_hdl, &ops_block[0].GroupNumber, - I2O_EXEC_IOP_MESSAGE_IF_GROUP_NO); - ddi_put16(acc_hdl, &ops_block[0].FieldCount, -1); /* all fields */ - - /* allocate the message frame */ - if (i2o_msg_alloc(iop->i2o_iop_handle, I2O_MSG_SLEEP, NULL, - (void **)&msgp, &msg_handle, &acc_hdl2) != DDI_SUCCESS) { - DEBUGF(1, (CE_CONT, - "dump_exec_params_0001: i2o_msg_alloc failed")); - (void) ddi_dma_unbind_handle(dma_handle); - goto cleanup; - } - - /* construct the UtilParamsGet message */ - msgp->StdMessageFrame.VersionOffset = I2O_VERSION_11; - msgp->StdMessageFrame.MsgFlags = 0; - ddi_put16(acc_hdl2, &msgp->StdMessageFrame.MessageSize, - (sizeof (i2o_util_params_get_message_t) + - sizeof (i2o_sg_element_t)) >> 2); - put_msg_Function(&msgp->StdMessageFrame, I2O_UTIL_PARAMS_GET, acc_hdl2); - put_msg_InitiatorAddress(&msgp->StdMessageFrame, - I2O_HOST_TID, acc_hdl2); - put_msg_TargetAddress(&msgp->StdMessageFrame, - I2O_IOP_TID, acc_hdl2); - ddi_put32(acc_hdl2, - &msgp->StdMessageFrame.InitiatorContext.initiator_context_32bits, - (uint32_t)i2o_msg_reply); - - sgl = msgp->SGL.u1.Simple; - - put_flags_count_Flags(&sgl->FlagsCount, I2O_SGL_FLAGS_END_OF_BUFFER | - I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT, acc_hdl2); - put_flags_count_Count(&sgl->FlagsCount, ops_block_size, acc_hdl2); - ddi_put32(acc_hdl2, &sgl->PhysicalAddress, - (uint_t)dma_cookie.dmac_address); - - put_flags_count_Flags(&sgl[1].FlagsCount, - I2O_SGL_FLAGS_LAST_ELEMENT | - I2O_SGL_FLAGS_END_OF_BUFFER | - I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT, acc_hdl2); - put_flags_count_Count(&sgl[1].FlagsCount, - results_block_size, acc_hdl2); - ddi_put32(acc_hdl2, &sgl[1].PhysicalAddress, - (uint_t)dma_cookie.dmac_address + ops_block_size); - - mutex_init(&test_mutex, NULL, MUTEX_DRIVER, NULL); - cv_init(&test_cv, NULL, CV_DEFAULT, NULL); - - mutex_enter(&test_mutex); - - test_result = 0; - - /* send the message to the IOP */ - (void) i2o_msg_send(iop->i2o_iop_handle, (void *)msgp, msg_handle); - - /* wait for the reply */ - if (test_result == 0) - cv_wait(&test_cv, &test_mutex); - - mutex_exit(&test_mutex); - - (void) ddi_dma_unbind_handle(dma_handle); - - /* - * ************************************************************** - * Now, print all the parameters. - * ************************************************************** - */ - - /* group 0001h - Message Interface */ - - message_if = (i2o_exec_iop_message_if_scalar_t *) - (buf + ops_block_size + - sizeof (i2o_param_results_list_header_t) + - sizeof (i2o_param_read_operation_result_t)); - cmn_err(CE_CONT, - "?IOP Message Interface Parameters - Group 0001h:"); - cmn_err(CE_CONT, "?\tInboundFrameSize: %x\n", ddi_get32(acc_hdl, - &message_if->InboundFrameSize)); - cmn_err(CE_CONT, "?\tInboundSizeTarget: %x\n", ddi_get32(acc_hdl, - &message_if->InboundSizeTarget)); - cmn_err(CE_CONT, "?\tInboundMax: %x\n", ddi_get32(acc_hdl, - &message_if->InboundMax)); - cmn_err(CE_CONT, "?\tInboundTarget: %x\n", ddi_get32(acc_hdl, - &message_if->InboundTarget)); - cmn_err(CE_CONT, "?\tInboundPoolCount: %x\n", ddi_get32(acc_hdl, - &message_if->InboundPoolCount)); - cmn_err(CE_CONT, "?\tInboundCurrentFree: %x\n", ddi_get32(acc_hdl, - &message_if->InboundCurrentFree)); - cmn_err(CE_CONT, "?\tInboundCurrentPost: %x\n", ddi_get32(acc_hdl, - &message_if->InboundCurrentPost)); - cmn_err(CE_CONT, "?\tStaticCount: %x\n", ddi_get16(acc_hdl, - &message_if->StaticCount)); - cmn_err(CE_CONT, "?\tStaticInstanceCount: %x\n", ddi_get16(acc_hdl, - &message_if->StaticInstanceCount)); - cmn_err(CE_CONT, "?\tStaticLimit: %x\n", ddi_get16(acc_hdl, - &message_if->StaticLimit)); - cmn_err(CE_CONT, "?\tStaticInstanceLimit: %x\n", ddi_get16(acc_hdl, - &message_if->StaticInstanceLimit)); - cmn_err(CE_CONT, "?\tOutboundFrameSize: %x\n", ddi_get32(acc_hdl, - &message_if->OutboundFrameSize)); - cmn_err(CE_CONT, "?\tOutboundMax: %x\n", ddi_get32(acc_hdl, - &message_if->OutboundMax)); - cmn_err(CE_CONT, "?\tOutboundTarget: %x\n", ddi_get32(acc_hdl, - &message_if->OutboundMaxTarget)); - cmn_err(CE_CONT, "?\tOutboundCurrentFree: %x\n", ddi_get32(acc_hdl, - &message_if->OutboundCurrentFree)); - cmn_err(CE_CONT, "?\tInboundCurrentPost: %x\n", ddi_get32(acc_hdl, - &message_if->InboundCurrentPost)); - cmn_err(CE_CONT, "?\tInitCode: %x\n", message_if->InitCode); - -cleanup: - if (buf != NULL) - ddi_dma_mem_free(&acc_hdl); - - if (dma_handle != NULL) - ddi_dma_free_handle(&dma_handle); -} - -void -i2o_msg_reply(void *m, ddi_acc_handle_t acc_hdl) -{ - i2o_single_reply_message_frame_t *rmp; - - mutex_enter(&test_mutex); - - rmp = (i2o_single_reply_message_frame_t *)m; - if (rmp->ReqStatus != I2O_REPLY_STATUS_SUCCESS) { - cmn_err(CE_CONT, "i2o_msg_reply: Reply Message Frame:"); - cmn_err(CE_CONT, - "?Reply Message Frame (Function %x):", - get_msg_Function(&rmp->StdMessageFrame, acc_hdl)); - cmn_err(CE_CONT, - "?\tReqStatus: %x DetailedStatusCode %x\n", rmp->ReqStatus, - ddi_get16(acc_hdl, &rmp->DetailedStatusCode)); - } - - test_result = 1; - - cv_broadcast(&test_cv); - - mutex_exit(&test_mutex); -} -#endif
--- a/usr/src/uts/common/io/i2o/pci_to_i2o.conf Wed Apr 18 03:07:55 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +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 (c) 1998 by Sun Microsystems, Inc. -# All rights reserved. -# - -#pragma ident "%Z%%M% %I% %E% SMI" - -# Configuration properties for the I2O Nexus driver. -# -# ob-msg-queue-length -# Specifies the number of outbound message frames to be allocated. -# The minimum is 16. Since the max. size is determined by the IOP -# the system will set this parameter upto that maximum. -# -# ob-msg-frame-size -# Specifies the size in bytes of the outbound message frame. The -# minimum size 64 bytes. -# - -ob-msg-frame-size=64 ob-msg-queue-length=128;
--- a/usr/src/uts/common/sys/Makefile Wed Apr 18 03:07:55 2007 -0700 +++ b/usr/src/uts/common/sys/Makefile Wed Apr 18 11:32:14 2007 -0700 @@ -934,15 +934,6 @@ pit.h \ rtc.h -# I2O header files (currently used only on i386) -I2OHDRS= \ - i2oadptr.h \ - i2obscsi.h \ - i2oexec.h \ - i2omsg.h \ - i2omstr.h \ - i2outil.h - NXGEHDRS= \ nxge.h \ nxge_common.h \
--- a/usr/src/uts/common/sys/Makefile.syshdrs Wed Apr 18 03:07:55 2007 -0700 +++ b/usr/src/uts/common/sys/Makefile.syshdrs Wed Apr 18 11:32:14 2007 -0700 @@ -1,5 +1,24 @@ # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (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 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" @@ -129,7 +148,7 @@ $(ROOTDIR)/av i386_ROOTDIRS= $(ROOTDKTPDIR) $(ROOTDIR)/scsi/adapters $(ROOTDIR)/scsi/targets \ - $(ROOTDIR)/i2o $(ROOTDIR)/agp $(ROOTDIR)/sata + $(ROOTDIR)/agp $(ROOTDIR)/sata ROOTDIRS= \ $(ROOTDIR) \ @@ -244,7 +263,6 @@ ROOTSDKTPHDRS= $(SDKTPHDRS:%=$(ROOTDIR)/dktp/%) ROOTDKTPHDRS= $(DKTPHDRS:%=$(ROOTDIR)/dktp/%) ROOTPCHDRS= $(PCHDRS:%=$(ROOTDIR)/%) -ROOTI2OHDRS= $(I2OHDRS:%=$(ROOTDIR)/i2o/%) ROOTHOTPLUGHDRS= $(HOTPLUGHDRS:%=$(ROOTDIR)/hotplug/%) ROOTHOTPLUGPCIHDRS= $(HOTPLUGPCIHDRS:%=$(ROOTDIR)/hotplug/pci/%) @@ -258,7 +276,7 @@ i386_ROOTHDRS= $(ROOTDKTPHDRS) $(ROOTPCHDRS) $(ROOTSCSITARGETSHDRS) \ $(ROOTSCSIVHCIHDRS) $(ROOTFCHDRS) \ - $(ROOTI2OHDRS) $(ROOTPCMCIAHDRS) $(ROOTHOTPLUGHDRS) \ + $(ROOTPCMCIAHDRS) $(ROOTHOTPLUGHDRS) \ $(ROOTHOTPLUGPCIHDRS) $(ROOTSATAGENHDRS) # install rules
--- a/usr/src/uts/common/sys/i2o/i2oadptr.h Wed Apr 18 03:07:55 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,323 +0,0 @@ -/* - * **************************************************************************** - * I2O SIG All rights reserved. - * - * These header files are provided, pursuant to your I2O SIG membership - * agreement, free of charge on an as-is basis without warranty of any kind, - * either express or implied, including but not limited to, implied warranties - * or merchantability and fitness for a particular purpose. I2O SIG does not - * warrant that this program will meet the user's requirements or that the - * operation of these programs will be uninterrupted or error-free. - * Acceptance and use of this program constitutes the user's understanding - * that he will have no recourse to I2O SIG for any actual or consequential - * damages including, but not limited to, loss profits arising out of use - * or inability to use this program. - * - * Member is permitted to create derivative works to this header-file program. - * However, all copies of the program and its derivative works must contain the - * I2O SIG copyright notice. - * - * **************************************************************************** - */ - -/* - * ************************************************************************** - * - * i2oadptr.h -- I2O Adapter Class Message defintion file - * - * This file contains information presented in Chapter 6 of - * the I2o Specification. - * - * *************************************************************************** - */ - -/* - * Copyright (c) 1998 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _SYS_I2OADPTR_H -#define _SYS_I2OADPTR_H - -#pragma ident "%W% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#define I2OADPTR_REV 1_5_1 /* Header file revision string */ - -/* - * NOTES: See i2omsg.h for more info - */ - -#include <sys/i2o/i2omsg.h> /* Include the Base Message file */ -#include <sys/types.h> /* For system types defines */ - - - -/* - * BUS ADAPTER CLASS SPECIFIC FUNCTIONS - */ - -#define I2O_HBA_ADAPTER_RESET 0x85 -#define I2O_HBA_BUS_QUIESCE 0x8b -#define I2O_HBA_BUS_RESET 0x87 -#define I2O_HBA_BUS_SCAN 0x89 - - -/* - * Detailed Status Codes for HBA operations - * - * Note: - * The 16-bit Detailed Status Code field for HBA operations is divided - * into two separate 8-bit fields. The lower 8 bits are reserved. The - * upper 8 bits are used to report Adapter Status information. The - * definitions for these two fields, however, will be consistent with - * the standard reply message frame structure declaration, which treats - * this as a single 16-bit field. In addition, the values used will be - * consistent with the Adapter Status codes defined for the SCSI - * Peripheral class. Theses codes are based on CAM-1. In other words, - * these definitions are a subset of the SCSI peripheral class codes. - * Where applicable, "SCSI" has been removed from the definition. - * - */ - -#define I2O_HBA_DSC_MASK 0xFF00 - -#define I2O_HBA_DSC_SUCCESS 0x0000 -#define I2O_HBA_DSC_ADAPTER_BUSY 0x0500 -#define I2O_HBA_DSC_COMMAND_TIMEOUT 0x0B00 -#define I2O_HBA_DSC_COMPLETE_WITH_ERROR 0x0400 -#define I2O_HBA_DSC_FUNCTION_UNAVAILABLE 0x3A00 -#define I2O_HBA_DSC_NO_ADAPTER 0x1100 -#define I2O_HBA_DSC_PARITY_ERROR_FAILURE 0x0F00 -#define I2O_HBA_DSC_PATH_INVALID 0x0700 -#define I2O_HBA_DSC_PROVIDE_FAILURE 0x1600 -#define I2O_HBA_DSC_QUEUE_FROZEN 0x4000 -#define I2O_HBA_DSC_REQUEST_ABORTED 0x0200 -#define I2O_HBA_DSC_REQUEST_INVALID 0x0600 -#define I2O_HBA_DSC_REQUEST_LENGTH_ERROR 0x1500 -#define I2O_HBA_DSC_REQUEST_TERMINATED 0x1800 -#define I2O_HBA_DSC_RESOURCE_UNAVAILABLE 0x3400 -#define I2O_HBA_DSC_BUS_BUSY 0x3F00 -#define I2O_HBA_DSC_BUS_RESET 0x0E00 -#define I2O_HBA_DSC_ID_INVALID 0x3900 -#define I2O_HBA_DSC_SEQUENCE_FAILURE 0x1400 -#define I2O_HBA_DSC_UNABLE_TO_ABORT 0x0300 -#define I2O_HBA_DSC_UNABLE_TO_TERMINATE 0x0900 -#define I2O_HBA_DSC_UNACKNOWLEDGED_EVENT 0x3500 -#define I2O_HBA_DSC_UNEXPECTED_BUS_FREE 0x1300 - -/* - * Bus Adapter Parameter Groups - */ - -#define I2O_HBA_CONTROLLER_INFO_GROUP_NO 0x0000 -#define I2O_HBA_HISTORICAL_STATS_GROUP_NO 0x0100 -#define I2O_HBA_SCSI_CONTROLLER_INFO_GROUP_NO 0x0200 -#define I2O_HBA_SCSI_BUS_PORT_INFO_GROUP_NO 0x0201 -#define I2O_HBA_FCA_CONTROLLER_INFO_GROUP_NO 0x0300 -#define I2O_HBA_FCA_PORT_INFO_GROUP_NO 0x0301 - -/* - * - 0000h - HBA Controller Information Parameter Group - */ - -/* - * Bus Type - */ - -#define I2O_HBA_BUS_TYPE_GENERIC 0x00 -#define I2O_HBA_BUS_TYPE_SCSI 0x01 -#define I2O_HBA_BUS_TYPE_FCA 0x10 - -typedef struct i2o_hba_controller_info_scalar { - uint8_t BusType; - uint8_t BusState; - uint16_t Reserved2; - uint8_t BusName[12]; -} i2o_hba_controller_info_scalar_t; - -/* - * - 0100h - HBA Historical Stats Parameter Group - */ - -typedef struct i2o_hba_hist_stats_scalar { - uint32_t TimeLastPoweredUp; - uint32_t TimeLastReset; -} i2o_hba_hist_stats_scalar_t; - -/* - * - 0200h - HBA SCSI Controller Information Parameter Group - */ - -/* - * SCSI Type - */ - -#define I2O_SCSI_TYPE_UNKNOWN 0x00 -#define I2O_SCSI_TYPE_SCSI_1 0x01 -#define I2O_SCSI_TYPE_SCSI_2 0x02 -#define I2O_SCSI_TYPE_SCSI_3 0x03 - -/* - * Protection Management - */ - -#define I2O_SCSI_PORT_PROT_OTHER 0x00 -#define I2O_SCSI_PORT_PROT_UNKNOWN 0x01 -#define I2O_SCSI_PORT_PROT_UNPROTECTED 0x02 -#define I2O_SCSI_PORT_PROT_PROTECTED 0x03 -#define I2O_SCSI_PORT_PROT_SCC 0x04 - -/* - * Settings - */ - -#define I2O_SCSI_PORT_PARITY_FLAG 0x01 -#define I2O_SCSI_PORT_PARITY_DISABLED 0x00 -#define I2O_SCSI_PORT_PARITY_ENABLED 0x01 - -#define I2O_SCSI_PORT_SCAN_ORDER_FLAG 0x02 -#define I2O_SCSI_PORT_SCAN_LOW_TO_HIGH 0x00 -#define I2O_SCSI_PORT_SCAN_HIGH_TO_LOW 0x02 - -#define I2O_SCSI_PORT_IID_FLAG 0x04 -#define I2O_SCSI_PORT_IID_DEFAULT 0x00 -#define I2O_SCSI_PORT_IID_SPECIFIED 0x04 - -#define I2O_SCSI_PORT_SCAM_FLAG 0x08 -#define I2O_SCSI_PORT_SCAM_DISABLED 0x00 -#define I2O_SCSI_PORT_SCAM_ENABLED 0x08 - -#define I2O_SCSI_PORT_TYPE_FLAG 0x80 -#define I2O_SCSI_PORT_TYPE_PARALLEL 0x00 -#define I2O_SCSI_PORT_TYPE_SERIAL 0x80 - -typedef struct i2o_hba_scsi_controller_info_scalar { - uint8_t SCSIType; - uint8_t ProtectionManagement; - uint8_t Settings; - uint8_t Reserved1; - uint32_t InitiatorID; - uint64_t ScanLun0Only; - uint16_t DisableDevice; - uint8_t MaxOffset; - uint8_t MaxDataWidth; - uint64_t MaxSyncRate; -} i2o_hba_scsi_controller_info_scalar_t; - -/* - * - 0201h - HBA SCSI Bus Port Information Parameter Group - */ - -/* - * NOTE: Refer to the SCSI Peripheral Class Bus Port Information - * Parameter Group field definitions for HBA SCSI Bus Port - * field definitions. - */ - -typedef struct i2o_hba_scsi_bus_port_info_scalar { - uint8_t PhysicalInterface; - uint8_t ElectricalInterface; - uint8_t Isochronous; - uint8_t ConnectorType; - uint8_t ConnectorGender; - uint8_t Reserved1; - uint16_t Reserved2; - uint32_t MaxNumberDevices; - uint32_t DeviceIdBegin; - uint32_t DeviceIdEnd; - uint8_t LunBegin[8]; - uint8_t LunEnd[8]; -} i2o_hba_scsi_bus_port_info_scalar_t; - -/* - * - 0300h - HBA FCA Controller Information Parameters Group defines - */ - -/* - * SCSI Type - */ - -#define I2O_FCA_TYPE_UNKNOWN 0x00 -#define I2O_FCA_TYPE_FCAL 0x01 - -typedef struct i2o_hba_fca_controller_info_scalar { - uint8_t FcaType; - uint8_t Reserved1; - uint16_t Reserved2; -} i2o_hba_fca_controller_info_scalar_t; - -/* - * - 0301h - HBA FCA Port Information Parameters Group defines - */ - -typedef struct i2o_hba_fca_port_info_scalar { - uint32_t Reserved4; -} i2o_hba_fca_port_info_scalar_t; - -/* - * I2O BUS ADAPTER CLASS SPECIFIC MESSAGE DEFINITIONS - */ - -/* - * I2O Bus Adapter Class Reply Message Frame - */ - -typedef struct i2o_hba_reply_message_frame { - i2o_single_reply_message_frame_t StdReplyFrame; -} i2o_hba_reply_message_frame_t; - -/* - * I2O HBA Adapter Reset Message Frame - */ - -typedef struct i2o_hba_adapter_reset_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; -} i2o_hba_adapter_reset_message_t; - -/* - * I2O HBA Bus Quiesce Message Frame - */ - -typedef uint32_t i2o_hbq_flags_t; - -#define I2O_HBQ_FLAG_NORMAL 0x0000 -#define I2O_HBQ_FLAG_QUIESCE 0x0001 - -typedef struct i2o_hba_bus_quiesce_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - i2o_hbq_flags_t Flags; -} i2o_hba_bus_quiesce_message_t; - -/* - * I2O HBA Bus Reset Message Frame - */ - -typedef struct i2o_hba_bus_reset_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; -} i2o_hba_bus_reset_message_t; - -/* - * I2O HBA Bus Scan Message Frame - */ - -/* - * NOTE: SCSI-2 8-bit scalar LUN goes into offset 1 of Lun arrays - */ - -typedef struct i2o_hba_bus_scan_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; -} i2o_hba_bus_scan_message_t; - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_I2OADPTR_H */
--- a/usr/src/uts/common/sys/i2o/i2obscsi.h Wed Apr 18 03:07:55 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,400 +0,0 @@ -/* - * ***************************************************************************** - * I2O SIG All rights reserved. - * - * These header files are provided, pursuant to your I2O SIG membership - * agreement, free of charge on an as-is basis without warranty of any kind, - * either express or implied, including but not limited to, implied warranties - * or merchantability and fitness for a particular purpose. I2O SIG does not - * warrant that this program will meet the user's requirements or that the - * operation of these programs will be uninterrupted or error-free. - * Acceptance and use of this program constitutes the user's understanding - * that he will have no recourse to I2O SIG for any actual or consequential - * damages including, but not limited to, loss profits arising out of use - * or inability to use this program. - * - * Member is permitted to create derivative works to this header-file program. - * However, all copies of the program and its derivative works must contain the - * I2O SIG copyright notice. - * - * ***************************************************************************** - */ - -/* - * *************************************************************************** - * - * I2OBSCSI.h -- I2O Base SCSI Device Class Message defintion file - * - * This file contains information presented in Chapter 6, Section 6 & 7 of - * the I2O Specification. - * - * *************************************************************************** - */ - -/* - * Copyright (c) 1998 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _SYS_I2OBSCSI_H -#define _SYS_I2OBSCSI_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#define I2OBSCSI_REV 1_5_1 /* Header file revision string */ - -/* - * NOTES: See i2omsg.h for more info - */ - -#include <sys/i2o/i2omsg.h> /* Include the Base Message file */ -#include <sys/types.h> /* For system types defined */ - -/* - * SCSI Peripheral Class specific functions - * - * Although the names are SCSI Peripheral class specific, the values - * assigned are common with other classes when applicable. - */ - -#define I2O_SCSI_DEVICE_RESET 0x27 -#define I2O_SCSI_SCB_ABORT 0x83 -#define I2O_SCSI_SCB_EXEC 0x81 - -/* - * Detailed Status Codes for SCSI operations - * - * The 16-bit Detailed Status Code field for SCSI operations is divided - * into two separate 8-bit fields. The lower 8 bits are used to report - * Device Status information. The upper 8 bits are used to report - * Adapter Status information. The definitions for these two fields, - * however, will be consistent with the standard reply message frame - * structure declaration, which treats this as a single 16-bit field. - */ - - -/* - * SCSI Device Completion Status Codes (defined by SCSI-2/3) - */ - -#define I2O_SCSI_DEVICE_DSC_MASK 0x00FF - -#define I2O_SCSI_DSC_SUCCESS 0x0000 -#define I2O_SCSI_DSC_CHECK_CONDITION 0x0002 -#define I2O_SCSI_DSC_BUSY 0x0008 -#define I2O_SCSI_DSC_RESERVATION_CONFLICT 0x0018 -#define I2O_SCSI_DSC_COMMAND_TERMINATED 0x0022 -#define I2O_SCSI_DSC_TASK_SET_FULL 0x0028 -#define I2O_SCSI_DSC_ACA_ACTIVE 0x0030 - -/* - * SCSI Adapter Status Codes (based on CAM-1) - */ - -#define I2O_SCSI_HBA_DSC_MASK 0xFF00 - -#define I2O_SCSI_HBA_DSC_SUCCESS 0x0000 - -#define I2O_SCSI_HBA_DSC_REQUEST_ABORTED 0x0200 -#define I2O_SCSI_HBA_DSC_UNABLE_TO_ABORT 0x0300 -#define I2O_SCSI_HBA_DSC_COMPLETE_WITH_ERROR 0x0400 -#define I2O_SCSI_HBA_DSC_ADAPTER_BUSY 0x0500 -#define I2O_SCSI_HBA_DSC_REQUEST_INVALID 0x0600 -#define I2O_SCSI_HBA_DSC_PATH_INVALID 0x0700 -#define I2O_SCSI_HBA_DSC_DEVICE_NOT_PRESENT 0x0800 -#define I2O_SCSI_HBA_DSC_UNABLE_TO_TERMINATE 0x0900 -#define I2O_SCSI_HBA_DSC_SELECTION_TIMEOUT 0x0A00 -#define I2O_SCSI_HBA_DSC_COMMAND_TIMEOUT 0x0B00 - -#define I2O_SCSI_HBA_DSC_MR_MESSAGE_RECEIVED 0x0D00 -#define I2O_SCSI_HBA_DSC_SCSI_BUS_RESET 0x0E00 -#define I2O_SCSI_HBA_DSC_PARITY_ERROR_FAILURE 0x0F00 -#define I2O_SCSI_HBA_DSC_AUTOSENSE_FAILED 0x1000 -#define I2O_SCSI_HBA_DSC_NO_ADAPTER 0x1100 -#define I2O_SCSI_HBA_DSC_DATA_OVERRUN 0x1200 -#define I2O_SCSI_HBA_DSC_UNEXPECTED_BUS_FREE 0x1300 -#define I2O_SCSI_HBA_DSC_SEQUENCE_FAILURE 0x1400 -#define I2O_SCSI_HBA_DSC_REQUEST_LENGTH_ERROR 0x1500 -#define I2O_SCSI_HBA_DSC_PROVIDE_FAILURE 0x1600 -#define I2O_SCSI_HBA_DSC_BDR_MESSAGE_SENT 0x1700 -#define I2O_SCSI_HBA_DSC_REQUEST_TERMINATED 0x1800 - -#define I2O_SCSI_HBA_DSC_IDE_MESSAGE_SENT 0x3300 -#define I2O_SCSI_HBA_DSC_RESOURCE_UNAVAILABLE 0x3400 -#define I2O_SCSI_HBA_DSC_UNACKNOWLEDGED_EVENT 0x3500 -#define I2O_SCSI_HBA_DSC_MESSAGE_RECEIVED 0x3600 -#define I2O_SCSI_HBA_DSC_INVALID_CDB 0x3700 -#define I2O_SCSI_HBA_DSC_LUN_INVALID 0x3800 -#define I2O_SCSI_HBA_DSC_SCSI_TID_INVALID 0x3900 -#define I2O_SCSI_HBA_DSC_FUNCTION_UNAVAILABLE 0x3A00 -#define I2O_SCSI_HBA_DSC_NO_NEXUS 0x3B00 -#define I2O_SCSI_HBA_DSC_SCSI_IID_INVALID 0x3C00 -#define I2O_SCSI_HBA_DSC_CDB_RECEIVED 0x3D00 -#define I2O_SCSI_HBA_DSC_LUN_ALREADY_ENABLED 0x3E00 -#define I2O_SCSI_HBA_DSC_BUS_BUSY 0x3F00 - -#define I2O_SCSI_HBA_DSC_QUEUE_FROZEN 0x4000 - -/* - * SCSI Peripheral Device Parameter Groups - */ - -/* - * SCSI Configuration and Operating Structures and Defines - */ - -#define I2O_SCSI_DEVICE_INFO_GROUP_NO 0x0000 -#define I2O_SCSI_DEVICE_BUS_PORT_INFO_GROUP_NO 0x0001 - -/* - * - 0000h - SCSI Device Information Parameters Group defines - */ - -/* - * Device Type - */ - -#define I2O_SCSI_DEVICE_TYPE_DIRECT 0x00 -#define I2O_SCSI_DEVICE_TYPE_SEQUENTIAL 0x01 -#define I2O_SCSI_DEVICE_TYPE_PRINTER 0x02 -#define I2O_SCSI_DEVICE_TYPE_PROCESSOR 0x03 -#define I2O_SCSI_DEVICE_TYPE_WORM 0x04 -#define I2O_SCSI_DEVICE_TYPE_CDROM 0x05 -#define I2O_SCSI_DEVICE_TYPE_SCANNER 0x06 -#define I2O_SCSI_DEVICE_TYPE_OPTICAL 0x07 -#define I2O_SCSI_DEVICE_TYPE_MEDIA_CHANGER 0x08 -#define I2O_SCSI_DEVICE_TYPE_COMM 0x09 -#define I2O_SCSI_DEVICE_GRAPHICS_1 0x0A -#define I2O_SCSI_DEVICE_GRAPHICS_2 0x0B -#define I2O_SCSI_DEVICE_TYPE_ARRAY_CONT 0x0C -#define I2O_SCSI_DEVICE_TYPE_UNKNOWN 0x1F - -/* - * Flags - */ - -#define I2O_SCSI_PERIPHERAL_TYPE_FLAG 0x01 -#define I2O_SCSI_PERIPHERAL_TYPE_PARALLEL 0x00 -#define I2O_SCSI_PERIPHERAL_TYPE_SERIAL 0x01 - -#define I2O_SCSI_RESERVED_FLAG 0x02 - -#define I2O_SCSI_DISCONNECT_FLAG 0x04 -#define I2O_SCSI_DISABLE_DISCONNECT 0x00 -#define I2O_SCSI_ENABLE_DISCONNECT 0x04 - -#define I2O_SCSI_MODE_MASK 0x18 -#define I2O_SCSI_MODE_SET_DATA 0x00 -#define I2O_SCSI_MODE_SET_DEFAULT 0x08 -#define I2O_SCSI_MODE_SET_SAFEST 0x10 - -#define I2O_SCSI_DATA_WIDTH_MASK 0x60 -#define I2O_SCSI_DATA_WIDTH_8 0x00 -#define I2O_SCSI_DATA_WIDTH_16 0x20 -#define I2O_SCSI_DATA_WIDTH_32 0x40 - -#define I2O_SCSI_SYNC_NEGOTIATION_FLAG 0x80 -#define I2O_SCSI_DISABLE_SYNC_NEGOTIATION 0x00 -#define I2O_SCSI_ENABLE_SYNC_NEGOTIATION 0x80 - -/* - * - 0001h - SCSI Device Bus Port Info Parameters Group defines - */ - -/* - * Physical - */ - -#define I2O_SCSI_PORT_PHYS_OTHER 0x01 -#define I2O_SCSI_PORT_PHYS_UNKNOWN 0x02 -#define I2O_SCSI_PORT_PHYS_PARALLEL 0x03 -#define I2O_SCSI_PORT_PHYS_FIBRE_CHANNEL 0x04 -#define I2O_SCSI_PORT_PHYS_SERIAL_P1394 0x05 -#define I2O_SCSI_PORT_PHYS_SERIAL_SSA 0x06 - -/* - * Electrical - */ - -#define I2O_SCSI_PORT_ELEC_OTHER 0x01 -#define I2O_SCSI_PORT_ELEC_UNKNOWN 0x02 -#define I2O_SCSI_PORT_ELEC_SINGLE_ENDED 0x03 -#define I2O_SCSI_PORT_ELEC_DIFFERENTIAL 0x04 -#define I2O_SCSI_PORT_ELEC_LOW_VOLT_DIFF 0x05 -#define I2O_SCSI_PORT_ELEC_OPTICAL 0x06 - -/* - * Isochronous - */ - -#define I2O_SCSI_PORT_ISOC_NO 0x00 -#define I2O_SCSI_PORT_ISOC_YES 0x01 -#define I2O_SCSI_PORT_ISOC_UNKNOWN 0x02 - -/* - * Connector Type - */ - -#define I2O_SCSI_PORT_CONN_OTHER 0x01 -#define I2O_SCSI_PORT_CONN_UNKNOWN 0x02 -#define I2O_SCSI_PORT_CONN_NONE 0x03 -#define I2O_SCSI_PORT_CONN_SHIELDED_A_HD 0x04 -#define I2O_SCSI_PORT_CONN_UNSHIELDED_A_HD 0x05 -#define I2O_SCSI_PORT_CONN_SHIELDED_A_LD 0x06 -#define I2O_SCSI_PORT_CONN_UNSHIELDED_A_LD 0x07 -#define I2O_SCSI_PORT_CONN_SHIELDED_P_HD 0x08 -#define I2O_SCSI_PORT_CONN_UNSHIELDED_P_HD 0x09 -#define I2O_SCSI_PORT_CONN_SCA_I 0x0A -#define I2O_SCSI_PORT_CONN_SCA_II 0x0B -#define I2O_SCSI_PORT_CONN_FC_DB9 0x0C -#define I2O_SCSI_PORT_CONN_FC_FIBRE 0x0D -#define I2O_SCSI_PORT_CONN_FC_SCA_II_40 0x0E -#define I2O_SCSI_PORT_CONN_FC_SCA_II_20 0x0F -#define I2O_SCSI_PORT_CONN_FC_BNC 0x10 - -/* - * Connector Gender - */ - -#define I2O_SCSI_PORT_CONN_GENDER_OTHER 0x01 -#define I2O_SCSI_PORT_CONN_GENDER_UNKOWN 0x02 -#define I2O_SCSI_PORT_CONN_GENDER_FEMALE 0x03 -#define I2O_SCSI_PORT_CONN_GENDER_MALE 0x04 - - -/* - * SCSI Device Group 0000h - Device Information Parameter Group - */ - -typedef struct i2o_scsi_device_info_scalar { - uint8_t DeviceType; - uint8_t Flags; - uint16_t Reserved2; - uint32_t Identifier; - uint8_t LunInfo[8]; /* SCSI2 8-bit scalar LUN goes into */ - /* offset 1 */ - uint32_t QueueDepth; - uint8_t Reserved1a; - uint8_t NegOffset; - uint8_t NegDataWidth; - uint8_t Reserved1b; - uint64_t NegSyncRate; -} i2o_scsi_device_info_scalar_t; - -/* - * SCSI Device Group 0001h - Bus Port Information Parameter Group - */ - -typedef struct i2o_scsi_bus_port_info_scalar { - uint8_t PhysicalInterface; - uint8_t ElectricalInterface; - uint8_t Isochronous; - uint8_t ConnectorType; - uint8_t ConnectorGender; - uint8_t Reserved1; - uint16_t Reserved2; - uint32_t MaxNumberDevices; -} i2o_scsi_bus_port_info_scalar_t; - -/* - * I2O SCSI Peripheral Event Indicator Assignment - */ - -#define I2O_SCSI_EVENT_SCSI_SMART 0x00000010 - -/* - * SCSI Peripheral Class Specific Message Definitions - */ - -/* - * I2O SCSI Peripheral Successful Completion Reply Message Frame - */ - -typedef struct i2o_scsi_success_reply_message_frame { - i2o_single_reply_message_frame_t StdReplyFrame; - uint32_t TransferCount; -} i2o_scsi_success_reply_message_frame_t; - - - -/* - * I2O SCSI Peripheral Error Report Reply Message Frame - */ - -#define I2O_SCSI_SENSE_DATA_SZ 40 - -typedef struct i2o_scsi_error_reply_message_frame { - i2o_single_reply_message_frame_t StdReplyFrame; - uint32_t TransferCount; - uint32_t AutoSenseTransferCount; - uint8_t SenseData[I2O_SCSI_SENSE_DATA_SZ]; -} i2o_scsi_error_reply_message_frame_t; - - - -/* - * I2O SCSI Device Reset Message Frame - */ - -typedef struct i2o_scsi_device_reset_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; -} i2o_scsi_device_reset_message_t; - - - -/* - * I2O SCSI Control Block Abort Message Frame - */ - -typedef struct i2o_scsi_scb_abort_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - i2o_transaction_context_t TransactionContextToAbort; -} i2o_scsi_scb_abort_message_t; - -/* - * I2O SCSI Control Block Execute Message Frame - */ - -#define I2O_SCSI_CDB_LENGTH 16 - -#define I2O_SCB_FLAG_XFER_DIR_MASK 0xC000 -#define I2O_SCB_FLAG_NO_DATA_XFER 0x0000 -#define I2O_SCB_FLAG_XFER_FROM_DEVICE 0x4000 -#define I2O_SCB_FLAG_XFER_TO_DEVICE 0x8000 - -#define I2O_SCB_FLAG_ENABLE_DISCONNECT 0x2000 - -#define I2O_SCB_FLAG_TAG_TYPE_MASK 0x0380 -#define I2O_SCB_FLAG_NO_TAG_QUEUEING 0x0000 -#define I2O_SCB_FLAG_SIMPLE_QUEUE_TAG 0x0080 -#define I2O_SCB_FLAG_HEAD_QUEUE_TAG 0x0100 -#define I2O_SCB_FLAG_ORDERED_QUEUE_TAG 0x0180 -#define I2O_SCB_FLAG_ACA_QUEUE_TAG 0x0200 - -#define I2O_SCB_FLAG_AUTOSENSE_MASK 0x0060 -#define I2O_SCB_FLAG_DISABLE_AUTOSENSE 0x0000 -#define I2O_SCB_FLAG_SENSE_DATA_IN_MESSAGE 0x0020 -#define I2O_SCB_FLAG_SENSE_DATA_IN_BUFFER 0x0060 - -typedef struct i2o_scsi_scb_execute_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint8_t CDBLength; - uint8_t Reserved; - uint16_t SCBFlags; - uint8_t CDB[I2O_SCSI_CDB_LENGTH]; - uint32_t ByteCount; - i2o_sg_element_t SGL; -} i2o_scsi_scb_execute_message_t; - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_I2OBSCSI_H */
--- a/usr/src/uts/common/sys/i2o/i2oexec.h Wed Apr 18 03:07:55 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2478 +0,0 @@ -/* - * ***************************************************************************** - * - * All software on this website is made available under the following terms and - * conditions. By downloading this software, you agree to abide by these terms - * and conditions with respect to this software. - * - * I2O SIG All rights reserved. - * - * These header files are provided, pursuant to your I2O SIG membership - * agreement, free of charge on an as-is basis without warranty of any kind, - * either express or implied, including but not limited to, implied warranties - * or merchantability and fitness for a particular purpose. I2O SIG does not - * warrant that this program will meet the user's requirements or that the - * operation of these programs will be uninterrupted or error-free. - * Acceptance and use of this program constitutes the user's understanding - * that he will have no recourse to I2O SIG for any actual or consequential - * damages including, but not limited to, loss profits arising out of use - * or inability to use this program. - * - * Member is permitted to create derivative works to this header-file program. - * However, all copies of the program and its derivative works must contain the - * I2O SIG copyright notice. - * - * ***************************************************************************** - */ - -/* - * ******************************************************************** - * I2OExec.h -- I2O Executive Class Message definition file - * - * This file contains information presented in Chapter 4 of the I2O(tm) - * Specification. - * ******************************************************************** - */ - -/* - * Copyright (c) 1998 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _SYS_I2OEXEC_H -#define _SYS_I2OEXEC_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include <sys/i2o/i2omsg.h> /* the Base Message file */ -#include <sys/i2o/i2outil.h> -#include <sys/types.h> - - -#define I2OEXEC_REV 1_5_4 /* I2OExec header file revision string */ - - -/* - * **************************************************************************** - * NOTES: - * - * Gets, reads, receives, etc. are all even numbered functions. - * Sets, writes, sends, etc. are all odd numbered functions. - * Functions that both send and receive data can be either but an attempt - * is made to use the function number that indicates the greater transfer - * amount. Functions that do not send or receive data use odd function - * numbers. - * - * Some functions are synonyms like read, receive and send, write. - * - * All common functions will have a code of less than 0x80. - * Unique functions to a class will start at 0x80. - * Executive Functions start at 0xA0. - * - * Utility Message function codes range from 0 - 0x1f - * Base Message function codes range from 0x20 - 0xfe - * Private Message function code is 0xff. - * ***************************************************************************** - */ - -/* I2O Executive Function Codes. */ - -#define I2O_EXEC_ADAPTER_ASSIGN 0xB3 -#define I2O_EXEC_ADAPTER_READ 0xB2 -#define I2O_EXEC_ADAPTER_RELEASE 0xB5 -#define I2O_EXEC_BIOS_INFO_SET 0xA5 -#define I2O_EXEC_BOOT_DEVICE_SET 0xA7 -#define I2O_EXEC_CONFIG_VALIDATE 0xBB -#define I2O_EXEC_CONN_SETUP 0xCA -#define I2O_EXEC_DDM_DESTROY 0xB1 -#define I2O_EXEC_DDM_ENABLE 0xD5 -#define I2O_EXEC_DDM_QUIESCE 0xC7 -#define I2O_EXEC_DDM_RESET 0xD9 -#define I2O_EXEC_DDM_SUSPEND 0xAF -#define I2O_EXEC_DEVICE_ASSIGN 0xB7 -#define I2O_EXEC_DEVICE_RELEASE 0xB9 -#define I2O_EXEC_HRT_GET 0xA8 -#define I2O_EXEC_IOP_CLEAR 0xBE -#define I2O_EXEC_IOP_CONNECT 0xC9 -#define I2O_EXEC_IOP_RESET 0xBD -#define I2O_EXEC_LCT_NOTIFY 0xA2 -#define I2O_EXEC_OUTBOUND_INIT 0xA1 -#define I2O_EXEC_PATH_ENABLE 0xD3 -#define I2O_EXEC_PATH_QUIESCE 0xC5 -#define I2O_EXEC_PATH_RESET 0xD7 -#define I2O_EXEC_STATIC_MF_CREATE 0xDD -#define I2O_EXEC_STATIC_MF_RELEASE 0xDF -#define I2O_EXEC_STATUS_GET 0xA0 -#define I2O_EXEC_SW_DOWNLOAD 0xA9 -#define I2O_EXEC_SW_UPLOAD 0xAB -#define I2O_EXEC_SW_REMOVE 0xAD -#define I2O_EXEC_SYS_ENABLE 0xD1 -#define I2O_EXEC_SYS_MODIFY 0xC1 -#define I2O_EXEC_SYS_QUIESCE 0xC3 -#define I2O_EXEC_SYS_TAB_SET 0xA3 - - -/* I2O Get Status State values */ - -#define I2O_IOP_STATE_INITIALIZING 0x01 -#define I2O_IOP_STATE_RESET 0x02 -#define I2O_IOP_STATE_HOLD 0x04 -#define I2O_IOP_STATE_READY 0x05 -#define I2O_IOP_STATE_OPERATIONAL 0x08 -#define I2O_IOP_STATE_FAILED 0x10 -#define I2O_IOP_STATE_FAULTED 0x11 - - -/* Event Indicator Assignments for the Executive Class. */ - -#define I2O_EVENT_IND_RESOURCE_LIMIT 0x00000001 -#define I2O_EVENT_IND_CONNECTION_FAIL 0x00000002 -#define I2O_EVENT_IND_ADAPTER_FAULT 0x00000004 -#define I2O_EVENT_IND_POWER_FAIL 0x00000008 -#define I2O_EVENT_IND_RESET_PENDING 0x00000010 -#define I2O_EVENT_IND_RESET_IMMINENT 0x00000020 -#define I2O_EVENT_IND_HARDWARE_FAIL 0x00000040 -#define I2O_EVENT_IND_XCT_CHANGE 0x00000080 -#define I2O_EVENT_IND_NEW_LCT_ENTRY 0x00000100 -#define I2O_EVENT_IND_MODIFIED_LCT 0x00000200 -#define I2O_EVENT_IND_DDM_AVAILABILITY 0x00000400 - -/* Resource Limit Event Data */ - -#define I2O_EVENT_RESOURCE_LIMIT_LOW_MEMORY 0x00000001 -#define I2O_EVENT_RESOURCE_LIMIT_INBOUND_POOL_LOW 0x00000002 -#define I2O_EVENT_RESOURCE_LIMIT_OUTBOUND_POOL_LOW 0x00000004 - -/* Connection Fail Event Data */ - -#define I2O_EVENT_CONNECTION_FAIL_REPOND_NORMAL 0x00000000 -#define I2O_EVENT_CONNECTION_FAIL_NOT_REPONDING 0x00000001 -#define I2O_EVENT_CONNECTION_FAIL_NO_AVAILABLE_FRAMES 0x00000002 - -/* Reset Pending Event Data */ - -#define I2O_EVENT_RESET_PENDING_POWER_LOSS 0x00000001 -#define I2O_EVENT_RESET_PENDING_CODE_VIOLATION 0x00000002 - -/* Reset Imminent Event Data */ - -#define I2O_EVENT_RESET_IMMINENT_UNKNOWN_CAUSE 0x00000000 -#define I2O_EVENT_RESET_IMMINENT_POWER_LOSS 0x00000001 -#define I2O_EVENT_RESET_IMMINENT_CODE_VIOLATION 0x00000002 -#define I2O_EVENT_RESET_IMMINENT_PARITY_ERROR 0x00000003 -#define I2O_EVENT_RESET_IMMINENT_CODE_EXCEPTION 0x00000004 -#define I2O_EVENT_RESET_IMMINENT_WATCHDOG_TIMEOUT 0x00000005 - -/* Hardware Fail Event Data */ - -#define I2O_EVENT_HARDWARE_FAIL_UNKNOWN_CAUSE 0x00000000 -#define I2O_EVENT_HARDWARE_FAIL_CPU_FAILURE 0x00000001 -#define I2O_EVENT_HARDWARE_FAIL_MEMORY_FAULT 0x00000002 -#define I2O_EVENT_HARDWARE_FAIL_DMA_FAILURE 0x00000003 -#define I2O_EVENT_HARDWARE_FAIL_IO_BUS_FAILURE 0x00000004 - -/* DDM Availability Event Data */ - -#define I2O_EVENT_DDM_AVAILIBILITY_RESPOND_NORMAL 0x00000000 -#define I2O_EVENT_DDM_AVAILIBILITY_CONGESTED 0x00000001 -#define I2O_EVENT_DDM_AVAILIBILITY_NOT_RESPONDING 0x00000002 -#define I2O_EVENT_DDM_AVAILIBILITY_PROTECTION_VIOLATION 0x00000003 -#define I2O_EVENT_DDM_AVAILIBILITY_CODE_VIOLATION 0x00000004 - - -#define I2O_OPERATION_FLAG_ASSIGN_PERMANENT 0x01 - -/* ExecAdapterAssign Function Message Frame structure. */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_exec_adapter_assign_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint32_t DdmTID:12; - uint32_t reserved:12; - uint32_t OperationFlags:8; - } s; - uint32_t w; - } u1; - i2o_hrt_entry_t HRTEntry; -} i2o_exec_adappter_assign_message_t; - -/* macros to access the bit fields in exec adapter assign message */ - -#define get_i2o_exec_adapter_DdmTID(mp, hdl) \ - (mp)->u1.s.DdmTID -#define put_i2o_exec_adapter_DdmTID(mp, id, hdl) \ - ((mp)->u1.s.DdmTID = (id)) -#define get_i2o_exec_adapter_OperationFlags(mp, hdl) \ - (mp)->u1.s.OperationFlags -#define put_i2o_exec_adapter_OperationFlags(mp, n, hdl) \ - ((mp)->u1.s.OperationFlags = (n)) - -#endif - - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_exec_adapter_assign_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint32_t OperationFlags:8; - uint32_t reserved:12; - uint32_t DdmTID:12; - } s; - uint32_t w; - } u1; - i2o_hrt_entry_t HRTEntry; -} i2o_exec_adappter_assign_message_t; - -/* macros to access the bit fields in exec adapter assign message */ - - -#define get_i2o_exec_adapter_OperationFlags(mp, hdl) \ - (mp)->u1.s.OperationFlags -#define put_i2o_exec_adapter_OperatonFlags(mp, n, hdl) \ - ((mp)->u1.s.OperationFlags = (n)) - -#define get_i2o_exec_adapter_DdmTID(mp, hdl) \ - (ddi_get32(hdl, &(mp)->u1.w) & 0xFFF) -#define put_i2o_exec_adapter_DdmTID(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u1.w, \ - (ddi_get32(hdl, &(mp)->u1.w) & ~0xFFF) | ((id) & 0xFFF)) - -#endif - -#define I2O_REQUEST_FLAG_CONFIG_REGISTER 0x00000000 -#define I2O_REQUEST_FLAG_IO_REGISTER 0x00000001 -#define I2O_REQUEST_FLAG_ADAPTER_MEMORY 0x00000002 - -/* ExecAdapterRead Function Message Frame structure. */ - -typedef struct i2o_exec_adapter_read_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint32_t AdapterID; - uint32_t RequestFlags; - uint32_t Offset; - uint32_t Length; - i2o_sg_element_t SGL; -} i2o_exec_adapter_read_message_t; - - -#define I2O_OPERATION_FLAG_RELEASE_PERMANENT 0x01 - -/* ExecAdapterRelease Function Message Frame structure. */ - -typedef struct i2o_exec_dapater_release_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint8_t reserved[3]; - uint8_t OperationFlags; - i2o_hrt_entry_t HRTEntry; -} i2o_exec_adapter_release_message_t; - - - -/* ExecBiosInfoSet Function Message Frame structure. */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_exec_bios_info_set_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint32_t DeviceTID:12; - uint32_t reserved:12; - uint32_t BiosInfo:8; - } s; - uint32_t w; - } u1; -} i2o_exec_bios_info_set_message_t; - -/* macros to access the bit fields in exec bios info set message structure */ - -#define get_i2o_exec_bios_DeviceTID(mp, hdl) \ - (mp)->u1.s.DeviceTID -#define put_i2o_exec_bios_DeviceTID(mp, id, hdl) \ - ((mp)->u1.s.DeviceTID = (id)) -#define get_i2o_exec_BiosInfo(mp, hdl) \ - (mp)->u1.s.BiosInfo -#define put_i2o_exec_BiosInfo(mp, n, hdl) \ - ((mp)->u1.s.BiosInfo = (id)) -#endif - - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_exec_bios_info_set_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint32_t BiosInfo:8; - uint32_t reserved:12; - uint32_t DeviceTID:12; - } s; - uint32_t w; - } u1; -} i2o_exec_bios_info_set_message_t; - -/* macros to access the bit fields in exec bios info set message structure */ - -#define get_i2o_exec_BiosInfo(mp, hdl) \ - (mp)->u1.s.BiosInfo -#define put_i2o_exec_BiosInfo(mp, n, hdl) \ - ((mp)->u1.s.BiosInfo = (n)) - -#define get_i2o_exec_bios_DeviceID(mp, hdl) \ - (ddi_get32(hdl, &(mp)->u1.w) & 0xFFF) -#define put_i2o_exec_bios_DeviceID(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u1.w, \ - (ddi_get32(hdl, &(mp)->u1.w) & ~0xFFF) | ((id) & 0xFFF)) - -#endif - - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -/* ExecBootDeviceSet Function Message Frame structure. */ - -typedef struct i2o_exec_boot_device_set_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint32_t BootDevice:12; - uint32_t reserved:20; - } s; - uint32_t w; - } u1; -} i2o_exec_boot_device_set_message_t; - -/* macros to access the bit fields in exec boot set message structure */ - -#define get_i2o_exec_boot_BootDevice(mp, hdl) \ - (mp)->u1.s.BootDevice -#define put_i2o_exec_boot_BootDevice(mp, id, hdl) \ - ((mp)->u1.s.BootDevice = (id)) - -#endif - - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_exec_boot_device_set_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint32_t reserved:20; - uint32_t BootDevice:12; - } s; - uint32_t w; - } u1; -} i2o_exec_boot_device_set_message_t; - -#define get_i2o_exec_boot_BootDevice(mp, hdl) \ - (ddi_get32(hdl, &(mp)->u1.w) & 0xFFF) -#define put_i2o_exec_boot_BootDevice(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u1.w, \ - (ddi_get32(hdl, &(mp)->u1.w) & ~0xFFF) | ((id) & 0xFFF)) - -#endif - - -/* ExecConfigValidate Function Message Frame structure. */ - -typedef struct i2o_exec_config_validate_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; -} i2o_exec_config_validate_message_t; - - - -/* ExecConnSetup Requestor */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_alias_connect_setup { - union { - struct { - uint32_t IOP1AliasForTargetDevice:12; - uint32_t IOP2AliasForInitiatorDevice:12; - uint32_t reserved:8; - } s; - uint32_t w; - } u1; -} i2o_alias_connect_setup_t; - -/* macros to access the bit fields in alias connect setup structure */ - -#define get_i2o_exec_setup_IOP1AliasForTargetDevice(mp, hdl) \ - (mp)->u1.s.IOP1AliasForTargetDevice -#define put_i2o_exec_setup_IOP1AliasForTargetDevice(mp, id, hdl) \ - ((mp)->u1.s.IOP1AliasForTargetDevice = (id)) -#define get_i2o_exec_setup_IOP2AliasForInitiatorDevice(mp, hdl) \ - (mp)->u1.s.IOP2AliasForInitiatorDevice -#define put_i2o_exec_setup_IOP2AliasForInitiatortDevice(mp, n, hdl) \ - ((mp)->u1.s.IOP2AliasForInitiatortDevice = (id)) -#endif - - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_alias_connect_setup { - union { - struct { - uint32_t reserved:8; - uint32_t IOP2AliasForInitiatorDevice:12; - uint32_t IOP1AliasForTargetDevice:12; - } s; - uint32_t w; - } u1; -} i2o_alias_connect_setup_t; - -/* macros to access the bit fields in alias connect setup structure */ - -#define get_i2o_exec_setup_IOP2ForInitiatorDevice(mp, hdl) \ - ((ddi_get32(hdl, &(mp)->u1.w) >> 12) & 0xFFF) -#define put_i2o_exec_setup_IOP2ForInitiatorDevice(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u1.w, (ddi_get32(hdl, &(mp)->u.w) & \ - ~0xFFF000) | (((id) & 0xFFF) << 12)) - -#define get_i2o_exec_setup_IOP1AliasForTargetDevice(mp, hdl) \ - (ddi_get32(hdl, &(mp)->u1.w) & 0xFFF) -#define put_i2o_exec_setup_IOP1AliasForTargetDevice(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u1.w, \ - (ddi_get32(hdl, &(mp)->u1.w) & ~0xFFF) | ((id) & 0xFFF)) - -#endif - - -#define I2O_OPERATION_FLAG_PEER_TO_PEER_BIDIRECTIONAL 0x01 - -/* ExecConnSetup Object */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_object_connect_setup { - union { - struct { - uint32_t TargetDevice:12; - uint32_t InitiatorDevice:12; - uint32_t OperationFlags:8; - } s; - uint32_t w; - } u1; -} i2o_object_connect_setup_t; - -/* macros to access the bit fields in object connect setup structure */ - -#define get_i2o_exec_setup_TargetDevice(mp, hdl) \ - (mp)->u1.s.TargetDevice -#define put_i2o_exec_setup_TargetDevice(mp, id, hdl) \ - ((mp)->u1.s.TargetDevice = (id)) -#define get_i2o_exec_setup_InitiatorDevice(mp, hdl) \ - (mp)->u1.s.InitiatorDevice -#define put_i2o_exec_setup_InitiatorDevice(mp, n, hdl) \ - ((mp)->u1.s.InitiatorDevice = (id)) -#define get_i2o_exec_setup_OperationFlags(mp, hdl) \ - (mp)->u1.s.OpetationFlags -#define put_i2o_exec_setup_OperationFlags(mp, id, hdl) \ - ((mp)->u1.s.OperationFlags = (id)) -#endif - - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_object_connect_setup { - union { - struct { - uint32_t OperationFlags:8; - uint32_t InitiatorDevice:12; - uint32_t TargetDevice:12; - } s; - uint32_t w; - } u1; -} i2o_object_connect_setup_t; - -/* macros to access the bit fields in object connect setup structure */ - -#define get_i2o_exec_setup_OperationFlags(mp, hdl) \ - (mp)->u1.s.OperationFlags -#define put_i2o_exec_setup_OperationFlags(mp, n, hdl) \ - ((mp)->u1.s.OperationFlags = (n)) - -#define get_i2o_exec_setup_InitiatorDevice(mp, hdl) \ - ((ddi_get32(hdl, &(mp)->u1.w) >> 12) & 0xFFF) -#define put_i2o_exec_setup_InitiatorDevice(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u1.w, (ddi_get32(hdl, &(mp)->u.w) & \ - ~0xFFF000) | (((id) & 0xFFF) << 12)) - -#define get_i2o_exec_setup_TargetDevice(mp, hdl) \ - (ddi_get32(hdl, &(mp)->u1.w) & 0xFFF) -#define put_i2o_exec_setup_TargetDevice(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u1.w, \ - (ddi_get32(hdl, &(mp)->u1.w) & ~0xFFF) | ((id) & 0xFFF)) - -#endif - - -/* ExecConnSetup Function Message Frame structure. */ - -typedef struct i2o_exec_conn_setup_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - i2o_object_connect_setup_t ObjectInfo; - i2o_alias_connect_setup_t AliasInfo; - uint16_t IOP2InboundMFrameSize; - uint16_t reserved; - uint32_t MessageClass; -} i2o_exec_conn_setup_message_t; - - -/* ExecConnSetup Object Reply */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_object_connect_reply { - union { - struct { - uint32_t TargetDevice:12; - uint32_t InitiatorDevice:12; - uint32_t ReplyStatusCode:8; - } s; - uint32_t w; - } u1; -} i2o_object_connect_reply_t; - -/* macros to access the bit fields in object connect reply structure */ - -#define get_connect_reply_TargetDevice(mp, hdl) \ - (mp)->u1.s.TargetDevice -#define get_connect_reply_InitiatorDevice(mp, hdl) \ - (mp)->u1.s.InitiatorDevice -#define get_connect_reply_RepluStatus(mp, hdl) \ - (mp)->u1.s.ReplyStatusCode - -#endif - - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_object_connect_reply { - union { - struct { - uint32_t ReplyStatusCode:8; - uint32_t InitiatorDevice:12; - uint32_t TargetDevice:12; - } s; - uint32_t w; - } u1; -} i2o_object_connect_reply_t; - -/* macros to access the bit fields in object connect reply structure */ - -#define get_connect_reply_ReplyStatusCode(mp, hdl) \ - (mp)->u1.s.ReplyStatusCode - -#define get_connect_reply_InitiatorDevice(mp, hdl) \ - ((ddi_get32(hdl, &(mp)->u1.w) >> 12) & 0xFFF) - -#define get_connect_reply_TargetDevice(mp, hdl) \ - (ddi_get32(hdl, &(mp)->u1.w) & 0xFFF) - -#endif - - -/* ExecConnSetup reply structure. */ - -typedef struct i2o_exec_conn_setup_reply { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - i2o_object_connect_reply_t ObjectInfo; - i2o_alias_connect_setup_t AliasInfo; - uint16_t IOP2InboundMFrameSize; - uint16_t reserved; -} i2o_exec_conn_setup_reply_t; - - -/* ExecDdmDestroy Function Message Frame structure. */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_exec_ddm_destroy_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint32_t DdmTID:12; - uint32_t reserved:20; - } s; - uint32_t w; - } u1; -} i2o_exec_ddm_destroy_message_t; - -/* macros to access the bit fields in exec ddm destroy message structure */ - -#define get_i2o_exec_ddm_destroy_DdmTID(mp, hdl) \ - (mp)->u1.s.DdmTID -#define put_i2o_exec_ddm_destroy_DdmTID(mp, id, hdl) \ - ((mp)->u1.s.DdmTID = (id)) - -#endif - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_exec_ddm_destroy_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint32_t reserved:20; - uint32_t DdmTID:12; - } s; - uint32_t w; - } u1; -} i2o_exec_ddm_destroy_message_t; - -/* macros to access the bit fields in exec ddm destroy message structure */ - -#define get_i2o_exec_ddm_destroy_DdmTID(mp, hdl) \ - (ddi_get32(hdl, &(mp)->u1.w) & 0xFFF) -#define put_i2o_exec_ddm_destroy_DdmTID(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u1.w, \ - (ddi_get32(hdl, &(mp)->u1.w) & ~0xFFF) | ((id) & 0xFFF)) - -#endif - - -/* ExecDdmEnable Function Message Frame structure. */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_exec_ddm_enable_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint32_t DeviceTID:12; - uint32_t reserved1:20; - } s2; - uint32_t w2; - } u2; - union { - struct { - uint16_t IOP_ID:12; - uint16_t reserved:4; - } s3; - uint16_t h1; - } u3; - uint16_t HostUnitID; -} i2o_exec_ddm_enable_message_t; - -/* macros to access the bit fields in exec ddm enable message structure */ - -#define get_i2o_exec_ddm_enable_DeviceTID(mp, hdl) \ - (mp)->u2.s2.DeviceTID -#define put_i2o_exec_ddm_enable_DeviceTID(mp, id, hdl) \ - ((mp)->u2.s2.DeviceTID = (id)) - -#define get_i2o_exec_ddm_enable_IOP_ID(mp, hdl) \ - (mp)->u3.s3.IOP_ID -#define put_i2o_exec_ddm_enable_IOP_ID(mp, id, hdl) \ - ((mp)->u3.s3.IOP_ID = (id)) - -#endif - - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_exec_ddm_enable_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint32_t reserved1:20; - uint32_t DeviceTID:12; - } s2; - uint32_t w2; - } u2; - union { - struct { - uint16_t reserved:4; - uint16_t IOP_ID:12; - } s3; - uint16_t h1; - } u3; - uint16_t HostUnitID; -} i2o_exec_ddm_enable_message_t; - -/* macros to access the bit fields in exec ddm enable message structure */ - -#define get_i2o_exec_ddm_enable_DeviceTID(mp, hdl) \ - (ddi_get32(hdl, &(mp)->u2.w2) & 0xFFF) -#define put_i2o_exec_ddm_enable_DeviceTID(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u2.w2, \ - (ddi_get32(hdl, &(mp)->u2.w2) & ~0xFFF) | ((id) & 0xFFF)) - -#define get_i2o_exec_ddm_enable_IOP_ID(p, hdl) \ - (ddi_get16(hdl, &(p)->u3.h1) & 0xFFF) - -#define put_i2o_exec_ddm_enable_IOP_ID(mp, id, hdl) \ - ddi_put16(hdl, &(mp)->u3.h1, \ - (ddi_get16(hdl, &(mp)->u3.h1) & ~0xFFF) | ((id) & 0xFFF)) - -#endif - -/* ExecDdmQuiesce Function Message Frame structure. */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_exec_ddm_quiesce_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint32_t DeviceTID:12; - uint32_t reserved1:20; - } s2; - uint32_t w2; - } u2; - union { - struct { - uint16_t IOP_ID:12; - uint16_t reserved:4; - } s3; - uint16_t h1; - } u3; - uint16_t HostUnitID; -} i2o_exec_ddm_quiesce_message_t; - -/* macros to access the bit fields in exec ddm quiesce message structure */ - -#define get_i2o_exec_ddm_quiesce_DeviceTID(mp, hdl) \ - (mp)->u2.s2.DeviceTID -#define put_i2o_exec_ddm_quiesce_DeviceTID(mp, id, hdl) \ - ((mp)->u2.s2.DeviceTID = (id)) - -#define get_i2o_exec_ddm_quiesce_IOP_ID(mp, hdl) \ - (mp)->u3.s3.IOP_ID -#define put_i2o_exec_ddm_quiesce_IOP_ID(mp, id, hdl) \ - ((mp)->u3.s3.IOP_ID = (id)) - -#endif - - -/* ExecDdmQuiesce Function Message Frame structure. */ - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_exec_ddm_quiesce_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint32_t reserved1:20; - uint32_t DeviceTID:12; - } s2; - uint32_t w2; - } u2; - union { - struct { - uint16_t reserved:4; - uint16_t IOP_ID:12; - } s3; - uint16_t h1; - } u3; - uint16_t HostUnitID; -} i2o_exec_ddm_quiesce_message_t; - -/* macros to access the bit fields in exec ddm quiesce message structure */ - -#define get_i2o_exec_ddm_quiesce_DeviceTID(mp, hdl) \ - (ddi_get32(hdl, &(mp)->u2.w2) & 0xFFF) -#define put_i2o_exec_ddm_quiesce_DeviceTID(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u2.w2, \ - (ddi_get32(hdl, &(mp)->u2.w2) & ~0xFFF) | ((id) & 0xFFF)) - -#define get_i2o_exec_ddm_quiesce_IOP_ID(p, hdl) \ - (ddi_get16(hdl, &(p)->u3.h1) & 0xFFF) - -#define put_i2o_exec_ddm_quiesce_IOP_ID(mp, id, hdl) \ - ddi_put16(hdl, &(mp)->u3.h1, \ - (ddi_get16(hdl, &(mp)->u3.h1) & ~0xFFF) | ((id) & 0xFFF)) - -#endif - - -/* ExecDdmReset Function Message Frame structure. */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_exec_ddm_reset_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint32_t DeviceTID:12; - uint32_t reserved1:20; - } s2; - uint32_t w2; - } u2; - union { - struct { - uint16_t IOP_ID:12; - uint16_t reserved:4; - } s3; - uint16_t h1; - } u3; - uint16_t HostUnitID; -} i2o_exec_ddm_reset_message_t; - -/* macros to access the bit fields in exec ddm reset message structure */ - -#define get_i2o_exec_ddm_reset_DeviceTID(mp, hdl) \ - (mp)->u2.s2.DeviceTID -#define put_i2o_exec_ddm_reset_DeviceTID(mp, id, hdl) \ - ((mp)->u2.s2.DeviceTID = (id)) - -#define get_i2o_exec_ddm_reset_IOP_ID(mp, hdl) \ - (mp)->u3.s3.IOP_ID -#define put_i2o_exec_ddm_resetquiesce_IOP_ID(mp, id, hdl) \ - ((mp)->u3.s3.IOP_ID = (id)) - -#endif - - -/* ExecDdmReset Function Message Frame structure. */ - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_exec_ddm_reset_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint32_t reserved1:20; - uint32_t DeviceTID:12; - } s2; - uint32_t w2; - } u2; - union { - struct { - uint16_t reserved:4; - uint16_t IOP_ID:12; - } s3; - uint16_t h1; - } u3; - uint16_t HostUnitID; -} i2o_exec_ddm_reset_message_t; - -/* macros to access the bit fields in exec ddm reset message structure */ - -#define get_i2o_exec_ddm_reset_DeviceTID(mp, hdl) \ - (ddi_get32(hdl, &(mp)->u2.w2) & 0xFFF) -#define put_i2o_exec_ddm_reset_DeviceTID(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u2.w2, \ - (ddi_get32(hdl, &(mp)->u2.w2) & ~0xFFF) | ((id) & 0xFFF)) - -#define get_i2o_exec_ddm_reset_IOP_ID(p, hdl) \ - (ddi_get16(hdl, &(p)->u3.h1) & 0xFFF) - -#define put_i2o_exec_ddm_reset_IOP_ID(mp, id, hdl) \ - ddi_put16(hdl, &(mp)->u3.h1, \ - (ddi_get16(hdl, &(mp)->u3.h1) & ~0xFFF) | ((id) & 0xFFF)) - -#endif - - -/* ExecDdmSuspend Function Message Frame structure. */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_exec_ddm_suspend_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint32_t DdmTID:12; - uint32_t reserved:20; - } s; - uint32_t w; - } u1; -} i2o_exec_ddm_suspend_message_t; - -/* macros to access the bit fields in exec ddm suspend message structure */ - -#define get_i2o_exec_ddm_suspend_DdmTID(mp, hdl) \ - (mp)->u1.s.DdmTID -#define put_i2o_exec_ddm_suspend_DdmTID(mp, id, hdl) \ - ((mp)->u1.s.DdmTID = (id)) - -#endif - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_exec_ddm_suspend_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint32_t reserved:20; - uint32_t DdmTID:12; - } s; - uint32_t w; - } u1; -} i2o_exec_ddm_suspend_message_t; - -/* macros to access the bit fields in exec ddm suspend message structure */ - -#define get_i2o_exec_ddm_suspend_DdmTID(mp, hdl) \ - (ddi_get32(hdl, &(mp)->u1.w) & 0xFFF) -#define put_i2o_exec_ddm_suspend_DdmTID(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u1.w, \ - (ddi_get32(hdl, &(mp)->u1.w) & ~0xFFF) | ((id) & 0xFFF)) - -#endif - - -#define I2O_OPERATION_FLAG_ASSIGN_PERMANENT 0x01 - - -/* ExecDeviceAssign Function Message Frame structure. */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_exec_device_assign_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint32_t DeviceTID:12; - uint32_t DdmTID:12; - uint32_t OperationFlags:8; - } s2; - uint32_t w2; - } u2; - union { - struct { - uint16_t IOP_ID:12; - uint16_t reserved:4; - } s3; - uint16_t h1; - } u3; - uint16_t HostUnitID; -} i2o_exec_device_assign_message_t; - - -/* macros to access the bit fields in device assign message structure */ - -#define get_i2o_exec_device_assign_DeviceTID(mp, hdl) \ - (mp)->u2.s2.DeviceTID -#define put_i2o_exec_device_assign_DeviceTID(mp, id, hdl) \ - ((mp)->u2.s2.DeviceTID = (id)) -#define get_i2o_exec_device_assign_DdmTID(mp, hdl) \ - (mp)->u2.s2.DdmTID -#define put_i2o_exec_device_assign_DdmTID(mp, n, hdl) \ - ((mp)->u2.s2.DdmTID = (id)) -#define get_i2o_exec_device_assign_OperationFlags(mp, hdl) \ - (mp)->u2.s2.OpetationFlags -#define put_i2o_exec_device_assign_OperationFlags(mp, id, hdl) \ - ((mp)->u2.s2.OperationFlags = (id)) - -#define get_i2o_exec_device_assign_IOP_ID(mp, hdl) \ - (mp)->u3.s3.IOP_ID -#define put_i2o_exec_device_assign_IOP_ID(mp, id, hdl) \ - ((mp)->u3.s3.IOP_ID = (id)) -#endif - - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - - -typedef struct i2o_exec_device_assign_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint32_t OperationFlags:8; - uint32_t DdmTID:12; - uint32_t DeviceTID:12; - } s2; - uint32_t w2; - } u2; - union { - struct { - uint16_t reserved:4; - uint16_t IOP_ID:12; - } s3; - uint16_t h1; - } u3; - uint16_t HostUnitID; -} i2o_exec_device_assign_message_t; - -/* macros to access the bit fields in device assign message structure */ - -#define get_i2o_exec_device_assign_OperationFlags(mp, hdl) \ - (mp)->u2.s2.OperationFlags -#define put_i2o_exec_device_assign_OperationFlags(mp, n, hdl) \ - ((mp)->u2.s2.OperationFlags = (n)) - -#define get_i2o_exec_device_assign_DdmTID(mp, hdl) \ - ((ddi_get32(hdl, &(mp)->u2.w2) >> 12) & 0xFFF) -#define put_i2o_exec_device_assign_DdmTID(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u2.w2, (ddi_get32(hdl, &(mp)->u2.w2) & \ - ~0xFFF000) | (((id) & 0xFFF) << 12)) - -#define get_i2o_exec_device_assign_DeviceTID(mp, hdl) \ - (ddi_get32(hdl, &(mp)->u2.w2) & 0xFFF) -#define put_i2o_exec_device_assign_DeviceTID(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u2.w2, \ - (ddi_get32(hdl, &(mp)->u2.w2) & ~0xFFF) | ((id) & 0xFFF)) - -#define get_i2o_exec_device_assign_IOP_ID(p, hdl) \ - (ddi_get16(hdl, &(p)->u3.h1) & 0xFFF) -#define put_i2o_exec_device_assign_IOP_ID(mp, id, hdl) \ - ddi_put16(hdl, &(mp)->u3.h1, \ - (ddi_get16(hdl, &(mp)->u3.h1) & ~0xFFF) | ((id) & 0xFFF)) - -#endif - - -#define I2O_OPERATION_FLAG_RELEASE_PERMANENT 0x01 - -/* ExecDeviceRelease Function Message Frame structure. */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_exec_device_release_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint32_t DeviceTID:12; - uint32_t DdmTID:12; - uint32_t OperationFlags:8; - } s2; - uint32_t w2; - } u2; - union { - struct { - uint16_t IOP_ID:12; - uint16_t reserved:4; - } s3; - uint16_t h1; - } u3; - uint16_t HostUnitID; -} i2o_exec_device_release_message_t; - - -/* macros to access the bit fields in device release message structure */ - -#define get_i2o_exec_device_release_DeviceTID(mp, hdl) \ - (mp)->u2.s2.DeviceTID -#define put_i2o_exec_device_release_DeviceTID(mp, id, hdl) \ - ((mp)->u2.s2.DeviceTID = (id)) -#define get_i2o_exec_device_release_DdmTID(mp, hdl) \ - (mp)->u2.s2.DdmTID -#define put_i2o_exec_device_release_DdmTID(mp, n, hdl) \ - ((mp)->u2.s2.DdmTID = (id)) -#define get_i2o_exec_device_release_OperationFlags(mp, hdl) \ - (mp)->u2.s2.OpetationFlags -#define put_i2o_exec_device_release_OperationFlags(mp, id, hdl) \ - ((mp)->u2.s2.OperationFlags = (id)) - -#define get_i2o_exec_device_release_IOP_ID(mp, hdl) \ - (mp)->u3.s3.IOP_ID -#define put_i2o_exec_device_release_IOP_ID(mp, id, hdl) \ - ((mp)->u3.s3.IOP_ID = (id)) -#endif - - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - - -typedef struct i2o_exec_device_release_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint32_t OperationFlags:8; - uint32_t DdmTID:12; - uint32_t DeviceTID:12; - } s2; - uint32_t w2; - } u2; - union { - struct { - uint16_t reserved:4; - uint16_t IOP_ID:12; - } s3; - uint16_t h1; - } u3; - uint16_t HostUnitID; -} i2o_exec_device_release_message_t; - -/* macros to access the bit fields in device assign message structure */ - - -#define get_i2o_exec_device_release_OperationFlags(mp, hdl) \ - (mp)->u2.s2.OperationFlags -#define put_i2o_exec_device_release_OperationFlags(mp, n, hdl) \ - ((mp)->u2.s2.OperationFlags = (n)) - -#define get_i2o_exec_device_release_DdmTID(mp, hdl) \ - ((ddi_get32(hdl, &(mp)->u2.w2) >> 12) & 0xFFF) -#define put_i2o_exec_device_release_DdmTID(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u2.w2, (ddi_get32(hdl, &(mp)->u2.w2) & \ - ~0xFFF000) | (((id) & 0xFFF) << 12)) - -#define get_i2o_exec_device_release_DeviceTID(mp, hdl) \ - (ddi_get32(hdl, &(mp)->u2.w2) & 0xFFF) -#define put_i2o_exec_device_release_DeviceTID(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u2.w2, \ - (ddi_get32(hdl, &(mp)->u2.w2) & ~0xFFF) | ((id) & 0xFFF)) - -#define get_i2o_exec_device_release_IOP_ID(p, hdl) \ - (ddi_get16(hdl, &(p)->u3.h1) & 0xFFF) - -#define put_i2o_exec_device_release_IOP_ID(mp, id, hdl) \ - ddi_put16(hdl, &(mp)->u3.h1, \ - (ddi_get16(hdl, &(mp)->u3.h1) & ~0xFFF) | ((id) & 0xFFF)) - -#endif - - -/* HRT Entry Structure defined in I2OMSG.H */ - -/* ExecHrtGet Function Message Frame structure. */ - -typedef struct i2o_exec_hrt_get_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - i2o_sg_element_t SGL; -} i2o_exec_hrt_get_message_t; - - - -/* ExecIopClear Function Message Frame structure. */ - -typedef struct i2o_exec_iop_clear_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; -} i2o_exec_iop_clear_message_t; - - -/* ExecIopConnect Function Message Frame structure. */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_exec_iop_connect_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint32_t reserved:24; - uint32_t IOP1MsgerType:8; - - } s2; - uint32_t w2; - } u2; - uint16_t IOP1InboundMFrameSize; - union { - struct { - uint16_t IOP1AliasForIOP2:12; - uint16_t reserved1:4; - } s3; - uint16_t h2; - } u3; - union { - struct { - uint16_t IOP_ID1:12; - uint16_t reserved2:4; - } s4; - uint16_t h1; - } u4; - uint16_t HostUnitID1; -} i2o_exec_iop_connect_message_t; - - -/* macros to access the bit fields in exec iop connect message structure */ - -#define get_i2o_exec_iop_connect_IOP1MsgerType(p, hdl) \ - (mp)->u2.s2.IOP1MsgerType - -#define put_i2o_exec_iop_connect_IOP1MsgerType(mp, id, hdl) \ - ((mp)->u2.s2.IOP1MsgerType = (id)) - - -#define get_i2o_exec_iop_connect_IOP1AliasForIOP2(p, hdl) \ - (mp)->u3.s3.IOP1AliasForIOP2 - -#define put_i2o_exec_iop_connect_IOP1AliasForIOP2(mp, id, hdl) \ - ((mp)->u3.s3.IOP1AliasForIOP2 = (id)) - -#define get_i2o_exec_iop_connect_IOP_ID1(p, hdl) \ - (mp)->u4.s4.IOP_ID1 - -#define put_i2o_exec_iop_connect_IOP_ID1(mp, id, hdl) \ - ((mp)->u4.s4.IOP_ID1 = (id)) - - -#endif - - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_exec_iop_connect_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint32_t IOP1MsgerType:8; - uint32_t reserved:24; - } s2; - uint32_t w2; - } u2; - - uint16_t IOP1InboundMFrameSize; - union { - struct { - uint16_t reserved1:8; - uint16_t IOP1AliasForIOP2:12; - } s3; - uint16_t h2; - } u3; - union { - struct { - uint16_t reserved2:4; - uint16_t IOP_ID1:12; - } s4; - uint16_t h1; - } u4; - uint16_t HostUnitID1; -} i2o_exec_iop_connect_message_t; - -/* macros to access the bit fields in exec iop connect message structure */ - -#define get_i2o_exec_iop_connect_IOP1MsgerType(p, hdl) \ - ((ddi_get32(hdl, &(p)->u2.w2) >> 24) & 0xFF) - -#define put_i2o_exec_iop_connect_IOP1MsgerType(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u2.w2, \ - (ddi_get32(hdl, &(mp)->u2.w2) & ~0xFF) | (((id) & 0xFF) << 24)) - - -#define get_i2o_exec_iop_connect_IOP1AliasForIOP2(p, hdl) \ - (ddi_get16(hdl, &(p)->u3.h2) & 0xFFF) - -#define put_i2o_exec_iop_connect_IOP1AliasForIOP2(mp, id, hdl) \ - ddi_put16(hdl, &(mp)->u3.h2, \ - (ddi_get16(hdl, &(mp)->u3.h2) & ~0xFFF) | ((id) & 0xFFF)) - -#define get_i2o_exec_iop_connect_IOP_ID1(p, hdl) \ - (ddi_get32(hdl, &(p)->u4.h1) & 0xFFF) - -#define put_i2o_exec_iop_connect_IOP_ID1(mp, id, hdl) \ - ddi_put16(hdl, &(mp)->u4.h1, \ - (ddi_get16(hdl, &(mp)->u4.h1) & ~0xFFF) | ((id) & 0xFFF)) - -#endif - - -/* ExecIopConnect reply structure */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_exec_iop_connect_iop_reply { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint16_t DetailedStatusCode; - uint8_t reserved; - uint8_t ReqStatus; - uint16_t IOP2InboundMFrameSize; - union { - struct { - uint16_t IOP2AliasForIOP1:12; - uint16_t reserved1:4; - } s3; - uint16_t h2; - } u3; - union { - struct { - uint16_t IOP_ID2:12; - uint16_t reserved2:4; - } s4; - uint16_t w4; - } u4; - uint16_t HostUnitID2; -} i2o_exec_iop_connect_reply_t; - -/* macros to access the bit fields in exec iop connect reply structure */ - -#define get_i2o_exec_iop_connect_reply_IOP2AliasForIOP1(p, hdl) \ - (mp)->u3.s3.IOP2AliasForIOP1 - -#define put_i2o_exec_iop_connect_reply_IOP2AliasForIOP1(mp, id, hdl) \ - ((mp)->u3.s3.IOP2AliasForIOP1 = (id)) - -#define get_i2o_exec_iop_connect_reply_IOP_ID2(p, hdl) \ - (mp)->u4.s4.IOP_ID2 - -#define put_i2o_exec_iop_connect_reply_IOP_ID2(mp, id, hdl) \ - ((mp)->u4.s4.IOP_ID2 = (id)) - -#endif - - - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_exec_iop_connect_iop_reply { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint16_t DetailedStatusCode; - uint8_t reserved; - uint8_t ReqStatus; - uint16_t IOP2InboundMFrameSize; - union { - struct { - uint16_t reserved1:8; - uint16_t IOP2AliasForIOP1:12; - } s3; - uint16_t h2; - } u3; - union { - struct { - uint16_t reserved2:4; - uint16_t IOP_ID2:12; - } s4; - uint16_t h1; - } u4; - uint16_t HostUnitID2; -} i2o_exec_iop_connect_reply_t; - -/* macros to access the bit fields in exec iop connect reply structure */ - -#define get_i2o_exec_iop_connect_reply_IOP2AliasForIOP1(p, hdl) \ - (ddi_get16(hdl, &(p)->u3.h2) & 0xFFF) - -#define put_i2o_exec_iop_connect_reply_IOP2AliasForIOP1(mp, id, hdl) \ - ddi_put16(hdl, &(mp)->u3.h2, \ - (ddi_get16(hdl, &(mp)->u3.h2) & ~0xFFF) | ((id) & 0xFFF)) - -#define get_i2o_exec_iop_connect_reply_IOP_ID2(p, hdl) \ - (ddi_get32(hdl, &(p)->u4.h1) & 0xFFF) - -#define put_i2o_exec_iop_connect_reply_IOP_ID2(mp, id, hdl) \ - ddi_put16(hdl, &(mp)->u4.h1, \ - (ddi_get16(hdl, &(mp)->u4.h1) & ~0xFFF) | ((id) & 0xFFF)) - -#endif - - -#define I2O_EXEC_IOP_RESET_RESERVED_SZ 16 - -#define I2O_EXEC_IOP_RESET_IN_PROGRESS 0x01 -#define I2O_EXEC_IOP_RESET_REJECTED 0x02 - -#define I2O_EXEC_IOP_RESET_STATUS_RESERVED_SZ 3 - -typedef struct i2o_exec_iop_reset_status { - volatile uint8_t ResetStatus; - uint8_t reserved[I2O_EXEC_IOP_RESET_STATUS_RESERVED_SZ]; -} i2o_exec_iop_reset_status_t; - - -/* ExecIopReset Function Message Frame structure. */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_exec_iop_reset_message { - uint8_t VersionOffset; - uint8_t MsgFlags; - uint16_t MessageSize; - union { - struct { - uint32_t TargetAddress:12; - uint32_t InitiatorAddress:12; - uint32_t Function:8; - } s2; - uint32_t w2; - } u2; - uint8_t Reserved[I2O_EXEC_IOP_RESET_RESERVED_SZ]; - uint32_t StatusWordLowAddress; - uint32_t StatusWordHighAddress; -} i2o_exec_iop_reset_message_t; - -/* macros to access the bit fields in iop reset message */ - -#define get_i2o_exec_reset_TargetAddress(mp, hdl) \ - (mp)->u2.s2.TargetAddress -#define put_i2o_exec_reset_TargetAddress(mp, id, hdl) \ - ((mp)->u2.s2.TargetAddress = (id)) -#define get_i2o_exec_reset_InitiatorAddress(mp, hdl) \ - (mp)->u2.s2.InitiatorAddress -#define put_i2o_exec_reset_InitiatorAddress(mp, id, hdl) \ - ((mp)->u2.s2.InitiatorAddress = (id)) -#define get_i2o_exec_reset_Function(mp, hdl) \ - (mp)->u2.s2.Function -#define put_i2o_exec_reset_Function(mp, n, hdl) \ - ((mp)->u2.s2.Function = (n)) -#endif - - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_exec_iop_reset_message { - uint8_t VersionOffset; - uint8_t MsgFlags; - uint16_t MessageSize; - union { - struct { - uint32_t Function:8; - uint32_t InitiatorAddress:12; - uint32_t TargetAddress:12; - } s2; - uint32_t w2; - } u2; - - uint8_t Reserved[I2O_EXEC_IOP_RESET_RESERVED_SZ]; - uint32_t StatusWordLowAddress; - uint32_t StatusWordHighAddress; -} i2o_exec_iop_reset_message_t; - -/* macros to access the bit fields in iop reset message */ - -#define get_i2o_exec_reset_Function(mp, hdl) \ - (mp)->u2.s2.Function -#define put_i2o_exec_reset_Function(mp, n, hdl) \ - ((mp)->u2.s2.Function = (n)) - -#define get_i2o_exec_reset_TargetAddress(mp, hdl) \ - (ddi_get32(hdl, &(mp)->u2.w2) & 0xFFF) -#define put_i2o_exec_reset_TargetAddress(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u2.w2, \ - (ddi_get32(hdl, &(mp)->u2.w2) & ~0xFFF) | ((id) & 0xFFF)) - -#define get_i2o_exec_reset_InitiatorAddress(mp, hdl) \ - ((ddi_get32(hdl, &(mp)->u2.w2) >> 12) & 0xFFF) -#define put_i2o_exec_reset_InitiatorAddress(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u2.w2, (ddi_get32(hdl, &(mp)->u2.w2) & \ - ~0xFFF000) | (((id) & 0xFFF) << 12)) - -#endif - - -/* LCT Entry Structure defined in I2OMSG.H */ - -/* ExecLCTNotify Function Message Frame structure. */ - -typedef struct i2o_exec_lct_notify_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint32_t ClassIdentifier; - uint32_t LastReportedChangeIndicator; - i2o_sg_element_t SGL; -} i2o_exec_lct_notify_message_t; - - -/* ExecOutboundInit Function Message Frame structure. */ - -typedef struct i2o_exec_outbound_init_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint32_t HostPageFrameSize; - uint8_t InitCode; - uint8_t reserved; - uint16_t OutboundMFrameSize; - i2o_sg_element_t SGL; -} i2o_exec_outbound_init_message_t; - - -#define I2O_EXEC_OUTBOUND_INIT_IN_PROGRESS 0x01 -#define I2O_EXEC_OUTBOUND_INIT_REJECTED 0x02 -#define I2O_EXEC_OUTBOUND_INIT_FAILED 0x03 -#define I2O_EXEC_OUTBOUND_INIT_COMPLETE 0x04 - -#define I2O_EXEC_OUTBOUND_INIT_RESERVED_SZ 3 - - -typedef struct i2o_exec_outbound_init_status { - uint8_t InitStatus; - uint8_t reserved[I2O_EXEC_OUTBOUND_INIT_RESERVED_SZ]; -} i2o_exec_outbound_init_status_t; - - -typedef struct i2o_exec_outbound_init_reclaim_list { - uint32_t MFACount; - uint32_t MFAReleaseCount; - uint32_t MFAAddress[1]; -} i2o_exec_outbound_init_reclaim_list_t; - - -/* ExecPathEnable Function Message Frame structure. */ - - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_exec_path_enable_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint16_t IOP_ID:12; - uint16_t reserved:4; - } s2; - uint16_t h1; - } u2; - uint16_t HostUnitID; -} i2o_exec_path_enable_message_t; - -/* macros to access the bit fields in exec path enable message structure */ - -#define get_i2o_exec_path_enable_IOP_ID(mp, hdl) \ - (mp)->u2.s2.IOP_ID -#define put_i2o_exec_path_enable_IOP_ID(mp, id, hdl) \ - ((mp)->u2.s2.IOP_ID = (id)) -#endif - - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_exec_path_enable_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint16_t reserved:4; - uint16_t IOP_ID:12; - } s2; - uint16_t h1; - } u2; - uint16_t HostUnitID; -} i2o_exec_path_enable_message_t; - -/* macros to access the bit fields in exec path enable message structure */ - -#define get_i2o_exec_path_enable_IOP_ID(p, hdl) \ - (ddi_get32(hdl, &(p)->u2.h1) & 0xFFF) - -#define put_i2o_exec_path_enable_IOP_ID(mp, id, hdl) \ - ddi_put16(hdl, &(mp)->u2.h1, \ - (ddi_get16(hdl, &(mp)->u2.h1) & ~0xFFF) | ((id) & 0xFFF)) - -#endif - - -/* ExecPathQuiesce Function Message Frame structure. */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_exec_path_quiesce_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint16_t IOP_ID:12; - uint16_t reserved:4; - } s2; - uint16_t h1; - } u2; - uint16_t HostUnitID; -} i2o_exec_path_quiesce_message_t; - -/* macros to access the bit fields in exec path quiesce message structure */ - -#define get_i2o_exec_path_quiesce_IOP_ID(mp, hdl) \ - (mp)->u2.s2.IOP_ID -#define put_i2o_exec_path_quiesce_IOP_ID(mp, id, hdl) \ - ((mp)->u2.s2.IOP_ID = (id)) - -#endif - - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_exec_path_quiesce_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint16_t reserved:4; - uint16_t IOP_ID:12; - } s2; - uint16_t h1; - } u2; - uint16_t HostUnitID; -} i2o_exec_path_quiesce_message_t; - -/* macros to access the bit fields in exec path quiesce message structure */ - -#define get_i2o_exec_path_quiesce_IOP_ID(p, hdl) \ - (ddi_get16(hdl, &(p)->u2.h1) & 0xFFF) - -#define put_i2o_exec_path_quiesce_IOP_ID(mp, id, hdl) \ - ddi_put16(hdl, &(mp)->u2.h1, \ - (ddi_get16(hdl, &(mp)->u2.h1) & ~0xFFF) | ((id) & 0xFFF)) - -#endif - - -/* ExecPathReset Function Message Frame structure. */ - - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_exec_path_reset_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint16_t IOP_ID:12; - uint16_t reserved:4; - } s2; - uint16_t h1; - } u2; - uint16_t HostUnitID; -} i2o_exec_path_reset_message_t; - -/* macros to access the bit fields in exec path reset message structure */ - -#define get_i2o_exec_path_reset_IOP_ID(mp, hdl) \ - (mp)->u2.s2.IOP_ID -#define put_i2o_exec_path_reset_IOP_ID(mp, id, hdl) \ - ((mp)->u2.s2.IOP_ID = (id)) -#endif - - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_exec_path_reset_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint16_t reserved:4; - uint16_t IOP_ID:12; - } s2; - uint16_t h1; - } u2; - uint16_t HostUnitID; -} i2o_exec_path_reset_message_t; - -/* macros to access the bit fields in exec path reset message structure */ - -#define get_i2o_exec_path_reset_IOP_ID(p, hdl) \ - (ddi_get16(hdl, &(p)->u2.h1) & 0xFFF) - -#define put_i2o_exec_path_reset_IOP_ID(mp, id, hdl) \ - ddi_put16(hdl, &(mp)->u2.h1, \ - (ddi_get16(hdl, &(mp)->u2.h1) & ~0xFFF) | ((id) & 0xFFF)) - - -#endif - - -#define I2O_EXEC_STATIC_MF_CREATE_RESERVED_SZ 3 - -/* ExecStaticMfCreate Message Frame structure */ - -typedef struct i2o_exec_static_mf_create_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint8_t MaxOutstanding; - uint8_t reserved[I2O_EXEC_STATIC_MF_CREATE_RESERVED_SZ]; - i2o_message_frame_t StaticMessageFrame; -} i2o_exec_static_mf_create_message_t; - - -/* ExecStaticMfCreate Message Frame reply */ - -typedef struct i2o_exec_static_mf_create_reply { - i2o_single_reply_message_frame_t StdReplyFrame; - i2o_message_frame_t StaticMFA; -} i2o_exec_static_mf_create_reply_t; - - -/* ExecStaticMfRelease Message Frame structure */ - -typedef struct i2o_exec_static_mf_release_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - i2o_message_frame_t StaticMFA; -} i2o_exec_static_mf_release_message_t; - - - -#define I2O_EXEC_STATUS_GET_RESERVED_SZ 16 - -/* ExecStatusGet Function Message Frame structure. */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_exec_status_get_message { - uint8_t VersionOffset; - uint8_t MsgFlags; - uint16_t MessageSize; - union { - struct { - uint32_t Function:8; - uint32_t InitiatorAddress:12; - uint32_t TargetAddress:12; - } s2; - uint32_t w2; - } u2; - uint8_t Reserved[I2O_EXEC_STATUS_GET_RESERVED_SZ]; - uint32_t ReplyBufferAddressLow; - uint32_t ReplyBufferAddressHigh; - uint32_t ReplyBufferLength; -} i2o_exec_status_get_message_t; - -/* macros to access the bit fields in i2o exec status get message */ - -#define get_i2o_exec_status_TargetAddress(mp, hdl) \ - (mp)->u2.s2.TargetAddress -#define put_i2o_exec_status_TargetAddress(mp, id, hdl) \ - ((mp)->u2.s2.TargetAddress = (id)) -#define get_i2o_exec_status_InitiatorAddress(mp, hdl) \ - (mp)->u2.s2.InitiatorAddress -#define put_i2o_exec_status_InitiatorAddress(mp, id, hdl) \ - ((mp)->u2.s2.InitiatorAddress = (id)) -#define get_i2o_exec_status_Function(mp, hdl) \ - (mp)->u2.s2.Function -#define put_i2o_exec_status_Function(mp, n, hdl) \ - ((mp)->u2.s2.Function = (n)) - -#endif - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_exec_status_get_message { - uint8_t VersionOffset; - uint8_t MsgFlags; - uint16_t MessageSize; - union { - struct { - uint32_t Function:8; - uint32_t InitiatorAddress:12; - uint32_t TargetAddress:12; - } s2; - uint32_t w2; - } u2; - uint8_t Reserved[I2O_EXEC_STATUS_GET_RESERVED_SZ]; - uint32_t ReplyBufferAddressLow; - uint32_t ReplyBufferAddressHigh; - uint32_t ReplyBufferLength; -} i2o_exec_status_get_message_t; - -/* macros to access the bit fields in i2o exec status get message */ - -#define get_i2o_exec_status_Function(mp, hdl) \ - (mp)->u2.s2.Function -#define put_i2o_exec_status_Function(mp, n, hdl) \ - ((mp)->u2.s2.Function = (n)) - -#define get_i2o_exec_status_TargetAddress(mp, hdl) \ - (ddi_get32(hdl, &(mp)->u2.w2) & 0xFFF) -#define put_i2o_exec_status_TargetAddress(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u2.w2, \ - (ddi_get32(hdl, &(mp)->u2.w2) & ~0xFFF) | ((id) & 0xFFF)) - -#define get_i2o_exec_status_InitiatorAddress(mp, hdl) \ - ((ddi_get32(hdl, &(mp)->u2.w2) >> 12) & 0xFFF) -#define put_i2o_exec_status_InitiatorAddress(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u2.w2, (ddi_get32(hdl, &(mp)->u2.w2) & \ - ~0xFFF000) | (((id) & 0xFFF) << 12)) - -#endif - - -#define I2O_IOP_STATUS_PROD_ID_STR_SZ 24 -#define I2O_EXEC_STATUS_GET_REPLY_RESERVED_SZ 6 - -/* ExecStatusGet reply Structure */ - -#define I2O_IOP_CAP_CONTEXT_32_ONLY 0x00000000 -#define I2O_IOP_CAP_CONTEXT_64_ONLY 0x00000001 -#define I2O_IOP_CAP_CONTEXT_32_64_NOT_CURRENTLY 0x00000002 -#define I2O_IOP_CAP_CONTEXT_32_64_CURRENTLY 0x00000003 -#define I2O_IOP_CAP_CURRENT_CONTEXT_NOT_CONFIG 0x00000000 -#define I2O_IOP_CAP_CURRENT_CONTEXT_32_ONLY 0x00000004 -#define I2O_IOP_CAP_CURRENT_CONTEXT_64_ONLY 0x00000008 -#define I2O_IOP_CAP_CURRENT_CONTEXT_32_64 0x0000000C -#define I2O_IOP_CAP_INBOUND_PEER_SUPPORT 0x00000010 -#define I2O_IOP_CAP_OUTBOUND_PEER_SUPPORT 0x00000020 -#define I2O_IOP_CAP_PEER_TO_PEER_SUPPORT 0x00000040 - - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_exec_status_get_reply { - uint16_t OrganizationID; - uint16_t reserved; - union { - struct { - uint16_t IOP_ID:12; - uint16_t reserved1:4; - } s2; - uint16_t h1; - } u2; - uint16_t HostUnitID; - union { - struct { - uint16_t SegmentNumber:12; - uint16_t I2oVersion:4; - } s3; - uint16_t h1; - } u3; - uint8_t IopState; - uint8_t MessengerType; - uint16_t InboundMFrameSize; - uint8_t InitCode; - uint8_t reserved2; - uint32_t MaxInboundMFrames; - uint32_t CurrentInboundMFrames; - uint32_t MaxOutboundMFrames; - uint8_t ProductIDString[I2O_IOP_STATUS_PROD_ID_STR_SZ]; - uint32_t ExpectedLCTSize; - uint32_t IopCapabilities; - uint32_t DesiredPrivateMemSize; - uint32_t CurrentPrivateMemSize; - uint32_t CurrentPrivateMemBase; - uint32_t DesiredPrivateIOSize; - uint32_t CurrentPrivateIOSize; - uint32_t CurrentPrivateIOBase; - uint8_t reserved3[3]; - volatile uint8_t SyncByte; -} i2o_exec_status_get_reply_t; - -#define get_i2o_exec_status_reply_IOP_ID(p, hdl) (p)->u2.s2.IOP_ID -#define get_i2o_exec_status_reply_SegmentNumber(p, hdl)(p)->u3.s3.SegmentNumber -#define get_i2o_exec_status_reply_I2oVersion(p, hdl)(p)->u3.s3.I2oVersion - -#endif - - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_exec_status_get_reply { - uint16_t OrganizationID; - uint16_t reserved; - union { - struct { - uint16_t reserved1:4; - uint16_t IOP_ID:12; - } s2; - uint16_t h1; - } u2; - uint16_t HostUnitID; - union { - struct { - uint16_t I2oVersion:4; - uint16_t SegmentNumber:12; - } s3; - uint16_t h1; - } u3; - uint8_t IopState; - uint8_t MessengerType; - uint16_t InboundMFrameSize; - uint8_t InitCode; - uint8_t reserved2; - uint32_t MaxInboundMFrames; - uint32_t CurrentInboundMFrames; - uint32_t MaxOutboundMFrames; - uint8_t ProductIDString[I2O_IOP_STATUS_PROD_ID_STR_SZ]; - uint32_t ExpectedLCTSize; - uint32_t IopCapabilities; - uint32_t DesiredPrivateMemSize; - uint32_t CurrentPrivateMemSize; - uint32_t CurrentPrivateMemBase; - uint32_t DesiredPrivateIOSize; - uint32_t CurrentPrivateIOSize; - uint32_t CurrentPrivateIOBase; - uint8_t reserved3[3]; - uint8_t SyncByte; -} i2o_exec_status_get_reply_t; - -#define get_i2o_exec_status_reply_IOP_ID(p, hdl) \ - (ddi_get16(hdl, &(p)->u2.h1) & 0xFFF) - -#define get_i2o_exec_status_reply_I2oVersion(p, hdl) \ - (ddi_get16(hdl, &(p)->u3.h1) >> 4) -#define get_i2o_exec_staus_reply_SegmentNumber(p, hdl) \ - (ddi_get16(hdl, &(p)->u3.h1) & 0xFFF) - -#endif - - -#define I2O_EXEC_SW_DOWNLOAD_FLAG_LOAD_MEMORY 0x00 -#define I2O_EXEC_SW_DOWNLOAD_FLAG_PERMANENT_STORE 0x01 -#define I2O_EXEC_SW_DOWNLOAD_FLAG_EXPERIMENTAL 0x00 -#define I2O_EXEC_SW_DOWNLOAD_FLAG_OVERRIDE 0x02 - -#define I2O_EXEC_SW_TYPE_DDM 0x01 -#define I2O_EXEC_SW_TYPE_DDM_MPB 0x02 -#define I2O_EXEC_SW_TYPE_DDM_CONFIG_TABLE 0x03 -#define I2O_EXEC_SW_TYPE_IRTOS 0x11 -#define I2O_EXEC_SW_TYPE_IRTOS_PRIVATE_MODULE 0x12 -#define I2O_EXEC_SW_TYPE_IRTOS_DIALOG_TABLE 0x13 -#define I2O_EXEC_SW_TYPE_IOP_PRIVATE_MODULE 0x22 -#define I2O_EXEC_SW_TYPE_IOP_DIALOG_TABLE 0x23 - - -/* I2O ExecSwDownload/Upload/Remove SwID Structure */ - -typedef struct i2o_sw_id { - uint16_t ModuleID; - uint16_t OrganizationID; -} i2o_sw_id_t; - - -/* ExecSwDownload Function Message Frame structure. */ - -typedef struct i2o_exec_sw_donwload_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint8_t CurrentFragment; - uint8_t TotalFragments; - uint8_t SwType; - uint8_t DownloadFlags; - uint32_t SWSize; - i2o_sw_id_t SwID; - i2o_sg_element_t SGL; -} i2o_exec_sw_download_message_t; - - - - -/* ExecSwUpload Function Message Frame structure. */ - -typedef struct i2o_exec_sw_upload_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint8_t CurrentFragment; - uint8_t TotalFragments; - uint8_t SwType; - uint8_t UploadFlags; - uint32_t SWSize; - i2o_sw_id_t SwID; - i2o_sg_element_t SGL; -} i2o_exec_sw_upload_message_t; - - -/* ExecSwRemove Function Message Frame structure. */ - -typedef struct i2o_exec_sw_remove_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint16_t reserved; - uint8_t SwType; - uint8_t RemoveFlags; - uint32_t SWSize; - i2o_sw_id_t SwID; -} i2o_exec_sw_remove_message_t; - - -/* ExecSysEnable Function Message Frame structure. */ - -typedef struct i2o_exec_sys_enable_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; -} i2o_exec_sys_enable_message_t; - - -/* ExecSysModify Function Message Frame structure. */ - -typedef struct i2o_exec_sys_modify_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - i2o_sg_element_t SGL; -} i2o_exec_sys_modify_message_t; - - -/* ExecSysQuiesce Function Message Frame structure. */ - -typedef struct i2o_exec_sys_quiesce_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; -} i2o_exec_sys_quiesce_message_t; - - -/* ExecSysTabSet (System Table) Function Message Frame structure. */ - -#define I2O_EXEC_SYS_TAB_IOP_ID_LOCAL_IOP 0x000 -#define I2O_EXEC_SYS_TAB_IOP_ID_LOCAL_HOST 0x001 -#define I2O_EXEC_SYS_TAB_IOP_ID_UNKNOWN_IOP 0xFFF -#define I2O_EXEC_SYS_TAB_HOST_UNIT_ID_LOCAL_UNIT 0x0000 -#define I2O_EXEC_SYS_TAB_HOST_UNIT_ID_UNKNOWN_UNIT 0xffff -#define I2O_EXEC_SYS_TAB_SEG_NUMBER_LOCAL_SEGMENT 0x000 -#define I2O_EXEC_SYS_TAB_SEG_NUMBER_UNKNOWN_SEGMENT 0xfff - - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_exec_sys_tab_set_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint16_t IOP_ID:12; - uint16_t reserved:4; - } s2; - uint16_t h1; - } u2; - uint16_t HostUnitID; - union { - struct { - uint32_t SegmentNumber:12; - uint32_t reserved1:20; - } s3; - uint32_t w3; - } u3; - i2o_sg_element_t SGL; -} i2o_exec_sys_tab_set_message_t; - -/* macros to access the bit fields in exec ddm enable message structure */ - -#define get_i2o_exec_sys_tab_set_IOP_ID(mp, hdl) \ - (mp)->u2.s2.IOP_ID -#define put_i2o_exec_sys_tab_set_IOP_ID(mp, id, hdl) \ - ((mp)->u2.s2.IOP_ID = (id)) - -#define get_i2o_exec_sys_tab_set_SegmentNumber(mp, hdl) \ - (mp)->u3.s3.SegmentNumber -#define put_i2o_exec_sys_tab_set_SegmentNumber(mp, id, hdl) \ - ((mp)->u3.s3.SegmentNumber = (id)) -#endif - - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_exec_sys_tab_set_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - union { - struct { - uint16_t reserved:4; - uint16_t IOP_ID:12; - } s2; - uint16_t h1; - } u2; - uint16_t HostUnitID; - union { - struct { - uint32_t reserved1:20; - uint32_t SegmentNumnber:12; - } s3; - uint32_t w3; - } u3; - i2o_sg_element_t SGL; -} i2o_exec_sys_tab_set_message_t; - -/* macros to access the bit fields in exec ddm enable message structure */ - -#define get_i2o_exec_sys_tab_set_IOP_ID(p, hdl) \ - (ddi_get16(hdl, &(p)->u2.h1) & 0xFFF) - -#define put_i2o_exec_sys_tab_set_IOP_ID(mp, id, hdl) \ - ddi_put16(hdl, &(mp)->u2.h1, \ - (ddi_get16(hdl, &(mp)->u2.h1) & ~0xFFF) | ((id) & 0xFFF)) - -#define get_i2o_exec_sys_tab_set_SegmentNumber(mp, hdl) \ - (ddi_get32(hdl, &(mp)->u3.w3) & 0xFFF) -#define put_i2o_exec_sys_tab_set_SegmentNumber(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u3.w3, \ - (ddi_get32(hdl, &(mp)->u3.w3) & ~0xFFF) | ((id) & 0xFFF)) - -#endif - - -/* ExecSysTabSet (System Table) Header Reply structure. */ - -#define I2O_SET_SYSTAB_RESERVED_SZ 8 - -typedef struct i2o_set_systab_header { - uint8_t NumberEntries; - uint8_t SysTabVersion; - uint16_t reserved; - uint32_t CurrentChangeIndicator; - uint8_t reserved1[I2O_SET_SYSTAB_RESERVED_SZ]; -/* I2O_SYSTAB_ENTRY SysTabEntry[1]; */ -} i2o_set_systab_header_t; - - -#define I2O_RESOURCE_MANAGER_VERSION 0 - -typedef struct i2o_messenger_info { - uint32_t InboundMessagePortAddressLow; - uint32_t InboundMessagePortAddressHigh; -} i2o_messenger_info_t; - -/* ExecSysTabSet IOP Descriptor Entry structure. */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_iop_entry { - uint16_t OrganizationID; - uint16_t reserved; - union { - struct { - uint32_t IOP_ID:12; - uint32_t reserved1:20; - } s2; - uint32_t w2; - } u2; - union { - struct { - uint16_t SegmentNumber:12; - uint16_t I2oVersion:4; - } s3; - uint16_t h1; - } u3; - uint8_t IopState; - uint8_t MessengerType; - uint16_t InboundMessageFrameSize; - uint16_t reserved2; - uint32_t LastChanged; - uint32_t IopCapabilities; - i2o_messenger_info_t MessengerInfo; -} i2o_iop_entry_t; - - -#define get_i2o_iop_entry_IOP_ID(mp, hdl) \ - ((mp)->u2.s2.IOP_ID) - -#define put_i2o_iop_entry_IOP_ID(mp, v, hdl) \ - ((mp)->u2.s2.IOP_ID) = (v) - -#define get_i2o_iop_entry_SegmentNumber(mp, hdl) \ - ((mp)->u3.s3.SegmentNumber) - -#define put_i2o_iop_entry_SegmentNumber(mp, v, hdl) \ - ((mp)->u3.s3.SegmentNumber) = (v) - -#define get_i2o_iop_entry_I2oVersion(mp, hdl) \ - ((mp)->u3.s3.I2oVersion) - -#define put_i2o_iop_entry_I2oVersion(mp, v, hdl) \ - ((mp)->u3.s3.I2oVersion) = (v) - -#endif - - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_iop_entry { - uint16_t OrganizationID; - uint16_t reserved; - union { - struct { - uint32_t reserved1:20; - uint32_t IOP_ID:12; - } s2; - uint32_t w2; - } u2; - union { - struct { - uint16_t I2oVersion:4; - uint16_t SegmentNumber:12; - } s3; - uint16_t h1; - } u3; - uint8_t IopState; - uint8_t MessengerType; - uint16_t InboundMessageFrameSize; - uint16_t reserved2; - uint32_t LastChanged; - uint32_t IopCapabilities; - i2o_messenger_info_t MessengerInfo; -} i2o_iop_entry_t; - - -#define get_i2o_iop_entry_IOP_ID(mp, hdl) \ - (ddi_get32(hdl, &(mp)->u2.w2) & 0xFFF) - -#define put_i2o_iop_entry_IOP_ID(mp, v, hdl) \ - (ddi_put32(hdl, &(mp)->u2.w2) & 0xFFF, (v)) - -#define get_i2o_iop_entry_SegmentNumber(mp, hdl) \ - (ddi_get16(hdl, &(mp)->u3.h1) & 0xFFF) - -#define put_i2o_iop_entry_SegmentNumber(mp, v, hdl) \ - (ddi_put16(hdl, &(mp)->u3.h1) & 0xFFF, (v)) - -#define get_i2o_iop_entry_I2oVersion(mp, hdl) \ - ((ddi_get16(hdl, &(mp)->u3.h1) >> 12) & 0xF) - -#define put_i2o_iop_entry_I2oVersion(mp, v, hdl) \ - ((ddi_put16(hdl, &(mp)->u3.h1) >> 12) & 0xF, (v)) - -#endif - - -/* ************************************************************************** */ -/* Executive Parameter Groups */ -/* ************************************************************************** */ - - -#define I2O_EXEC_IOP_HARDWARE_GROUP_NO 0x0000 -#define I2O_EXEC_IOP_MESSAGE_IF_GROUP_NO 0x0001 -#define I2O_EXEC_EXECUTING_ENVIRONMENT_GROUP_NO 0x0002 -#define I2O_EXEC_EXECUTING_DDM_LIST_GROUP_NO 0x0003 -#define I2O_EXEC_DRIVER_STORE_GROUP_NO 0x0004 -#define I2O_EXEC_DRIVER_STORE_TABLE_GROUP_NO 0x0005 -#define I2O_EXEC_IOP_BUS_ATTRIBUTES_GROUP_NO 0x0006 -#define I2O_EXEC_IOP_SW_ATTRIBUTES_GROUP_NO 0x0007 -#define I2O_EXEC_HARDWARE_RESOURCE_TABLE_GROUP_NO 0x0100 -#define I2O_EXEC_LCT_SCALAR_GROUP_NO 0x0101 -#define I2O_EXEC_LCT_TABLE_GROUP_NO 0x0102 -#define I2O_EXEC_SYSTEM_TABLE_GROUP_NO 0x0103 -#define I2O_EXEC_EXTERNAL_CONN_TABLE_GROUP_NO 0x0104 - - -/* EXEC Group 0000h - IOP Hardware Parameter Group */ - -/* IOP HardWare Capabilities defines */ - -#define I2O_IOP_HW_CAP_SELF_BOOT 0x00000001 -#define I2O_IOP_HW_CAP_IRTOS_UPGRADEABLE 0x00000002 -#define I2O_IOP_HW_CAP_DOWNLOADABLE_DDM 0x00000004 -#define I2O_IOP_HW_CAP_INSTALLABLE_DDM 0x00000008 -#define I2O_IOP_HW_CAP_BATTERY_BACKUP_RAM 0x00000010 - -/* IOP Processor Type defines */ - -#define I2O_IOP_PROC_TYPE_INTEL_80960 0x00 -#define I2O_IOP_PROC_TYPE_AMD_29000 0x01 -#define I2O_IOP_PROC_TYPE_MOTOROLA_68000 0x02 -#define I2O_IOP_PROC_TYPE_ARM 0x03 -#define I2O_IOP_PROC_TYPE_MIPS 0x04 -#define I2O_IOP_PROC_TYPE_SPARC 0x05 -#define I2O_IOP_PROC_TYPE_POWER_PC 0x06 -#define I2O_IOP_PROC_TYPE_ALPHA 0x07 -#define I2O_IOP_PROC_TYPE_INTEL_X86 0x08 -#define I2O_IOP_PROC_TYPE_OTHER 0xFF - - -typedef struct i2o_exec_iop_hardware_scalar { - uint16_t I2oVendorID; - uint16_t ProductID; - uint32_t ProcessorMemory; - uint32_t PermMemory; - uint32_t HWCapabilities; - uint8_t ProcessorType; - uint8_t ProcessorVersion; -} i2o_exec_iop_hardware_scalar_t; - - -/* EXEC Group 0001h - IOP Message Interface Parameter Group */ - -/* InitCode defines */ -#define I2O_MESSAGE_IF_INIT_CODE_NO_OWNER 0x00 -#define I2O_MESSAGE_IF_INIT_CODE_BIOS 0x10 -#define I2O_MESSAGE_IF_INIT_CODE_OEM_BIOS_EXTENSION 0x20 -#define I2O_MESSAGE_IF_INIT_CODE_ROM_BIOS_EXTENSION 0x30 -#define I2O_MESSAGE_IF_INIT_CODE_OS 0x80 - -typedef struct i2o_exec_iop_message_if_scalar { - uint32_t InboundFrameSize; - uint32_t InboundSizeTarget; - uint32_t InboundMax; - uint32_t InboundTarget; - uint32_t InboundPoolCount; - uint32_t InboundCurrentFree; - uint32_t InboundCurrentPost; - uint16_t StaticCount; - uint16_t StaticInstanceCount; - uint16_t StaticLimit; - uint16_t StaticInstanceLimit; - uint32_t OutboundFrameSize; - uint32_t OutboundMax; - uint32_t OutboundMaxTarget; - uint32_t OutboundCurrentFree; - uint32_t OutboundCurrentPost; - uint8_t InitCode; -} i2o_exec_iop_message_if_scalar_t; - - -/* EXEC Group 0002h - Executing Environment Parameter Group */ - -typedef struct i2o_exec_execute_environment_scalar { - uint32_t MemTotal; - uint32_t MemFree; - uint32_t PageSize; - uint32_t EventQMax; - uint32_t EventQCurrent; - uint32_t DDMLoadMax; -} i2o_exec_execute_environment_scalar_t; - - -/* EXEC Group 0003h - Executing DDM's Parameter Group */ - -/* ModuleType Defines */ - -#define I2O_EXEC_DDM_MODULE_TYPE_OTHER 0x00 -#define I2O_EXEC_DDM_MODULE_TYPE_DOWNLOAD 0x01 -#define I2O_EXEC_DDM_MODULE_TYPE_EMBEDDED 0x22 - - -typedef struct i2o_exec_execute_ddm_table { - uint16_t DdmTID; - uint8_t ModuleType; - uint8_t reserved; - uint16_t I2oVendorID; - uint16_t ModuleID; - uint8_t ModuleName[I2O_MODULE_NAME_SZ]; - uint32_t ModuleVersion; - uint32_t DataSize; - uint32_t CodeSize; -} i2o_exec_execute_ddm_table_t; - - -/* EXEC Group 0004h - Driver Store Environment Parameter Group */ - - -typedef struct i2o_exec_driver_store_scalar { - uint32_t ModuleLimit; - uint32_t ModuleCount; - uint32_t CurrentSpace; - uint32_t FreeSpace; -} i2o_exec_driver_store_scalar_t; - - -/* EXEC Group 0005h - Driver Store Parameter Group */ - - -typedef struct i2o_exec_driver_store_table { - uint16_t StoredDdmIndex; - uint8_t ModuleType; - uint8_t reserved; - uint16_t I2oVendorID; - uint16_t ModuleID; - uint8_t ModuleName[I2O_MODULE_NAME_SZ]; - uint32_t ModuleVersion; - uint16_t DateDay; - uint16_t DateMonth; - uint32_t DateYear; - uint32_t ModuleSize; - uint32_t MpbSize; - uint32_t ModuleFlags; -} i2o_exec_driver_store_table_t; - - -/* EXEC Group 0006h - IOP's Bus Attributes Parameter Group */ - -#define I2O_EXEC_IOP_BUS_ATTRIB_SYSTEM_BUS 0x00 -#define I2O_EXEC_IOP_BUS_ATTRIB_BRIDGED_SYSTEM_BUS 0x01 -#define I2O_EXEC_IOP_BUS_ATTRIB_PRIVATE 0x02 - -typedef struct i2o_exec_iop_bus_attribute_table { - uint32_t BusID; - uint8_t BusType; - uint8_t MaxAdapters; - uint8_t AdapterCount; - uint8_t BusAttributes; -} i2o_exec_iop_bus_attribute_table_t; - - -/* EXEC Group 0007h - IOP's Bus Attributes Parameter Group */ - -#define I2O_EXEC_IOP_SW_CAP_IRTOS_I2O_COMPLIANT 0x00000001 -#define I2O_EXEC_IOP_SW_CAP_IRTOS_UPGRADEABLE 0x00000002 -#define I2O_EXEC_IOP_SW_CAP_DOWNLOADABLE_DDM 0x00000004 -#define I2O_EXEC_IOP_SW_CAP_INSTALLABLE_DDM 0x00000008 - -typedef struct i2o_exec_iop_sw_attributes_scalar { - uint16_t I2oVendorID; - uint16_t ProductID; - uint32_t CodeSize; - uint32_t SWCapabilities; -} i2o_exec_iop_sw_attributes_scalar_t; - - -/* EXEC Group 0100h - Hardware Resource Table Parameter Group */ - -typedef struct i2o_exec_hardware_resource_table { - uint32_t AdapterID; - uint16_t StateInfo; /* AdapterState plus Local TID */ - uint8_t BusNumber; - uint8_t BusType; - u_longlong_t PhysicalLocation; - uint32_t MemorySpace; - uint32_t IoSpace; -} i2o_exec_hardware_resource_table_t; - -/* EXEC Group 0101h - Logical Configuration Table Scalar Parameter Group */ - -typedef struct i2o_exec_lct_scalar { - uint16_t BootDevice; - uint32_t IopFlags; - uint32_t CurrentChangeIndicator; -} i2o_exec_lct_scalar_t; - -/* EXEC Group 0102h - Logical Configuration Table Parameter Group */ - -typedef struct i2o_exec_lct_table { - uint16_t LocalTID; - uint16_t UserTID; - uint16_t ParentTID; - uint16_t DdmTID; - uint32_t ChangeIndicator; - uint32_t DeviceFlags; - uint32_t ClassID; - uint32_t SubClass; - uint8_t IdentityTag[I2O_IDENTITY_TAG_SZ]; - uint32_t EventCapabilities; - uint8_t BiosInfo; -} i2o_exec_lct_table_t; - -/* EXEC Group 0103h - System Table Parameter Group */ - -#define I2O_MESSENGER_TYPE_MEMORY_MAPPED_MESSAGE_UNIT 0x0 - -typedef struct i2o_exec_system_table { - uint16_t IOP_ID; - uint16_t OrganizationID; - uint16_t SegmentNumber; - uint8_t Version; - uint8_t IopState; - uint8_t MessengerType; - uint8_t reserved; - uint32_t InboundMessagePortAddress; - uint16_t InboundMessageFrameSize; - uint32_t IopCapabilities; - i2o_messenger_info_t MessengerInfo; -} i2o_exec_system_table_t; - - -/* EXEC Group 0104h - External Connection Table Parameter Group */ - -#define I2O_EXEC_XCT_FLAGS_REMOTE_IOP_CREATED_CONNECTION 0x00 -#define I2O_EXEC_XCT_FLAGS_THIS_IOP_CREATED_CONNECTION 0x01 - -typedef struct i2o_exec_external_connection_table { - uint16_t LocalAliasTID; - uint16_t RemoteTID; - uint16_t RemoteIOP; - uint16_t RemoteUnitID; - uint8_t Flags; - uint8_t reserved; -} i2o_exec_external_connection_table_t; - - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_I2OEXEC_H */
--- a/usr/src/uts/common/sys/i2o/i2omsg.h Wed Apr 18 03:07:55 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1570 +0,0 @@ -/* - * Copyright (c) 1998-1999 by Sun Microsystems, Inc. - * All rights reserved. - */ - -/* - * ************************************************************************* - * All software on this website is made available under the following - * terms and conditions. By downloading this software, you agree to - * abide by these terms and conditions with respect to this software. - * - * I2O SIG All rights reserved. - * - * These header files are provided, pursuant to your I2O SIG membership - * agreement, free of charge on an as-is basis without warranty of any - * kind, either express or implied, including but not limited to, - * implied warranties or merchantability and fitness for a particular - * purpose. I2O SIG does not warrant that this program will meet the - * user's requirements or that the operation of these programs will be - * uninterrupted or error-free. Acceptance and use of this program - * constitutes the user's understanding that he will have no recourse - * to I2O SIG for any actual or consequential damages including, but - * not limited to, loss profits arising out of use or inability to use - * this program. - * - * Member is permitted to create deriavative works to this header-file - * program. However, all copies of the program and its derivative - * works must contain the I2O SIG copyright notice. - * ************************************************************************* - */ - -/* - * ************************************************************************* - * i2omsg.h -- I2O Message defintion file - * - * This file contains information presented in Chapter 3, 4 and 6 of - * the I2O(tm) Specification and most of the I2O Global defines and - * Typedefs. - * ************************************************************************* - */ - -#ifndef _SYS_I2OMSG_H -#define _SYS_I2OMSG_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#define I2OMSG_REV 1_5_4 /* I2OMsg header file revision string */ - -/* - * ************************************************************************* - * NOTES: - * - * Gets, reads, receives, etc. are all even numbered functions. - * Sets, writes, sends, etc. are all odd numbered functions. - * Functions that both send and receive data can be either but an attempt is - * made to use the function number that indicates the greater transfer amount. - * Functions that do not send or receive data use odd function numbers. - * - * Some functions are synonyms like read, receive and send, write. - * - * All common functions will have a code of less than 0x80. - * Unique functions to a class will start at 0x80. - * Executive Functions start at 0xA0. - * - * Utility Message function codes range from 0 - 0x1f - * Base Message function codes range from 0x20 - 0xfe - * Private Message function code is 0xff. - * ************************************************************************* - */ - -#include <sys/types.h> -#include <sys/dditypes.h> - -/* Set to 1 for 64 bit Context Fields */ -#define I2O_64BIT_CONTEXT 0 - -/* ************************************************************************** */ - -/* Common functions accross all classes. */ - -#define I2O_PRIVATE_MESSAGE 0xFF - -/* ************************************************************************** */ -/* Class ID and Code Assignments */ - - -#define I2O_CLASS_VERSION_10 0x00 -#define I2O_CLASS_VERSION_11 0x01 - -/* Class Code Names: Table 6-1 Class Code Assignments. */ - -#define I2O_CLASS_EXECUTIVE 0x000 -#define I2O_CLASS_DDM 0x001 -#define I2O_CLASS_RANDOM_BLOCK_STORAGE 0x010 -#define I2O_CLASS_SEQUENTIAL_STORAGE 0x011 -#define I2O_CLASS_LAN 0x020 -#define I2O_CLASS_WAN 0x030 -#define I2O_CLASS_FIBRE_CHANNEL_PORT 0x040 -#define I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL 0x041 -#define I2O_CLASS_SCSI_PERIPHERAL 0x051 -#define I2O_CLASS_ATE_PORT 0x060 -#define I2O_CLASS_ATE_PERIPHERAL 0x061 -#define I2O_CLASS_FLOPPY_CONTROLLER 0x070 -#define I2O_CLASS_FLOPPY_DEVICE 0x071 -#define I2O_CLASS_BUS_ADAPTER_PORT 0x080 -/* Class Codes 0x090 - 0x09f are reserved for Peer-to-Peer classes */ -#define I2O_CLASS_MATCH_ANYCLASS 0xffffffff - -#define I2O_SUBCLASS_i960 0x001 -#define I2O_SUBCLASS_HDM 0x020 -#define I2O_SUBCLASS_ISM 0x021 - -/* ************************************************************************** */ -/* Message Frame defines and structures */ - -/* Defines for the Version_Status field. */ - -#define I2O_VERSION_10 0x00 -#define I2O_VERSION_11 0x01 - -#define I2O_VERSION_OFFSET_NUMBER_MASK 0x07 -#define I2O_VERSION_OFFSET_SGL_TRL_OFFSET_MASK 0xF0 - -/* - * Defines for the Message Flags Field. - * Please Note that the FAIL bit is only set in the Transport Fail Message. - */ -#define I2O_MESSAGE_FLAGS_STATIC 0x01 -#define I2O_MESSAGE_FLAGS_64BIT_CONTEXT 0x02 -#define I2O_MESSAGE_FLAGS_MULTIPLE 0x10 -#define I2O_MESSAGE_FLAGS_FAIL 0x20 -#define I2O_MESSAGE_FLAGS_LAST 0x40 -#define I2O_MESSAGE_FLAGS_REPLY 0x80 - -/* Defines for Request Status Codes: Table 3-1 Reply Status Codes. */ - -#define I2O_REPLY_STATUS_SUCCESS 0x00 -#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01 -#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02 -#define I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER 0x03 -#define I2O_REPLY_STATUS_ERROR_DIRTY 0x04 -#define I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER 0x05 -#define I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER 0x06 -#define I2O_REPLY_STATUS_PROCESS_ABORT_DIRTY 0x08 -#define I2O_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER 0x09 -#define I2O_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER 0x0A -#define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0B -#define I2O_REPLY_STATUS_PROGRESS_REPORT 0x80 - -/* - * DetailedStatusCode defines for ALL messages: Table 3-2 Detailed Status Codes. - */ - -#define I2O_DETAIL_STATUS_SUCCESS 0x0000 -#define I2O_DETAIL_STATUS_BAD_KEY 0x0002 -#define I2O_DETAIL_STATUS_TCL_ERROR 0x0003 -#define I2O_DETAIL_STATUS_REPLY_BUFFER_FULL 0x0004 -#define I2O_DETAIL_STATUS_NO_SUCH_PAGE 0x0005 -#define I2O_DETAIL_STATUS_INSUFFICIENT_RESOURCE_SOFT 0x0006 -#define I2O_DETAIL_STATUS_INSUFFICIENT_RESOURCE_HARD 0x0007 -#define I2O_DETAIL_STATUS_CHAIN_BUFFER_TOO_LARGE 0x0009 -#define I2O_DETAIL_STATUS_UNSUPPORTED_FUNCTION 0x000A -#define I2O_DETAIL_STATUS_DEVICE_LOCKED 0x000B -#define I2O_DETAIL_STATUS_DEVICE_RESET 0x000C -#define I2O_DETAIL_STATUS_INAPPROPRIATE_FUNCTION 0x000D -#define I2O_DETAIL_STATUS_INVALID_INITIATOR_ADDRESS 0x000E -#define I2O_DETAIL_STATUS_INVALID_MESSAGE_FLAGS 0x000F -#define I2O_DETAIL_STATUS_INVALID_OFFSET 0x0010 -#define I2O_DETAIL_STATUS_INVALID_PARAMETER 0x0011 -#define I2O_DETAIL_STATUS_INVALID_REQUEST 0x0012 -#define I2O_DETAIL_STATUS_INVALID_TARGET_ADDRESS 0x0013 -#define I2O_DETAIL_STATUS_MESSAGE_TOO_LARGE 0x0014 -#define I2O_DETAIL_STATUS_MESSAGE_TOO_SMALL 0x0015 -#define I2O_DETAIL_STATUS_MISSING_PARAMETER 0x0016 -#define I2O_DETAIL_STATUS_TIMEOUT 0x0017 -#define I2O_DETAIL_STATUS_UNKNOWN_ERROR 0x0018 -#define I2O_DETAIL_STATUS_UNKNOWN_FUNCTION 0x0019 -#define I2O_DETAIL_STATUS_UNSUPPORTED_VERSION 0x001A -#define I2O_DEATIL_STATUS_DEVICE_BUSY 0x001B -#define I2O_DETAIL_STATUS_DEVICE_NOT_AVAILABLE 0x001C - -/* Common I2O Field sizes */ - -#define I2O_TID_SZ 12 -#define I2O_FUNCTION_SZ 8 -#define I2O_UNIT_ID_SZ 16 -#define I2O_SEGMENT_NUMBER_SZ 12 - -#define I2O_IOP_ID_SZ 12 -#define I2O_GROUP_ID_SZ 16 -#define I2O_IOP_STATE_SZ 8 -#define I2O_MESSENGER_TYPE_SZ 8 - -#define I2O_CLASS_ID_SZ 12 -#define I2O_CLASS_ORGANIZATION_ID_SZ 16 - -#define I2O_4BIT_VERSION_SZ 4 -#define I2O_8BIT_FLAGS_SZ 8 -#define I2O_COMMON_LENGTH_FIELD_SZ 16 - -#define I2O_DEVID_DESCRIPTION_SZ 16 -#define I2O_DEVID_VENDOR_INFO_SZ 16 -#define I2O_DEVID_PRODUCT_INFO_SZ 16 -#define I2O_DEVID_REV_LEVEL_SZ 8 -#define I2O_MODULE_NAME_SZ 24 - -#define I2O_BIOS_INFO_SZ 8 - -#define I2O_RESERVED_4BITS 4 -#define I2O_RESERVED_8BITS 8 -#define I2O_RESERVED_12BITS 12 -#define I2O_RESERVED_16BITS 16 -#define I2O_RESERVED_20BITS 20 -#define I2O_RESERVED_24BITS 24 -#define I2O_RESERVED_28BITS 28 - -typedef uint32_t I2O_PARAMETER_TID; - -#if I2O_64BIT_CONTEXT - -typedef union { - void (* i2o_msg_complete)(void *, ddi_acc_handle_t); - uint64_t initiator_context_64bits; -} i2o_initiator_context_t; - -typedef uint64_t i2o_transaction_context_t; - -#else - -typedef union { - void (* i2o_msg_complete)(void *, ddi_acc_handle_t); - uint32_t initiator_context_32bits; -} i2o_initiator_context_t; - -typedef uint32_t i2o_transaction_context_t; - -#endif - -/* Serial Number format defines */ - -#define I2O_SERIAL_FORMAT_UNKNOWN 0 -#define I2O_SERIAL_FORMAT_BINARY 1 -#define I2O_SERIAL_FORMAT_ASCII 2 -#define I2O_SERIAL_FORMAT_UNICODE 3 -#define I2O_SERIAL_FORMAT_LAN_MAC 4 -#define I2O_SERIAL_FORMAT_WAN 5 - -/* Special TID Assignments */ - -#define I2O_IOP_TID 0 -#define I2O_HOST_TID 1 - - -/* ************************************************************************** */ - -/* I2O Message Frame common for all messages */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_message_frame { - uint8_t VersionOffset; - uint8_t MsgFlags; - uint16_t MessageSize; - union { - struct { - uint32_t TargetAddress:12; - uint32_t InitiatorAddress:12; - uint32_t Function:8; - } s2; - uint32_t w2; - } u2; - i2o_initiator_context_t InitiatorContext; -} i2o_message_frame_t; - -/* macros to access the bit fields in Message Frame */ - -#define get_msg_TargetAddress(mp, hdl) \ - (mp)->u2.s2.TargetAddress -#define put_msg_TargetAddress(mp, id, hdl) \ - ((mp)->u2.s2.TargetAddress = (id)) -#define get_msg_InitiatorAddress(mp, hdl) \ - (mp)->u2.s2.InitiatorAddress -#define put_msg_InitiatorAddress(mp, id, hdl) \ - ((mp)->u2.s2.InitiatorAddress = (id)) -#define get_msg_Function(mp, hdl) \ - (mp)->u2.s2.Function -#define put_msg_Function(mp, n, hdl) \ - ((mp)->u2.s2.Function = (n)) -#endif - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_message_frame { - uint8_t VersionOffset; - uint8_t MsgFlags; - uint16_t MessageSize; - union { - struct { - uint32_t Function:8; - uint32_t InitiatorAddress:12; - uint32_t TargetAddress:12; - } s2; - uint32_t w2; - } u2; - i2o_initiator_context_t InitiatorContext; -} i2o_message_frame_t; - -/* macros to access the bit fields in Message Frame */ - -#define get_msg_Function(mp, hdl) \ - (mp)->u2.s2.Function -#define put_msg_Function(mp, n, hdl) \ - ((mp)->u2.s2.Function = (n)) - -#define get_msg_TargetAddress(mp, hdl) \ - (ddi_get32(hdl, &(mp)->u2.w2) & 0xFFF) -#define put_msg_TargetAddress(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u2.w2, \ - (ddi_get32(hdl, &(mp)->u2.w2) & ~0xFFF) | ((id) & 0xFFF)) - -#define get_msg_InitiatorAddress(mp, hdl) \ - ((ddi_get32(hdl, &(mp)->u2.w2) >> 12) & 0xFFF) -#define put_msg_InitiatorAddress(mp, id, hdl) \ - ddi_put32(hdl, &(mp)->u2.w2, (ddi_get32(hdl, &(mp)->u2.w2) & \ - ~0xFFF000) | (((id) & 0xFFF) << 12)) -#endif - - -/* ************************************************************************** */ - -/* Transaction Reply Lists (TRL) Control Word structure */ - -#define I2O_TRL_FLAGS_SINGLE_FIXED_LENGTH 0x00 -#define I2O_TRL_FLAGS_SINGLE_VARIABLE_LENGTH 0x40 -#define I2O_TRL_FLAGS_MULTIPLE_FIXED_LENGTH 0x80 - -typedef struct i2o_trl_control_word { - uint8_t TrlCount; - uint8_t TrlElementSize; - uint8_t reserved; - uint8_t TrlFlags; -#if I2O_64BIT_CONTEXT - uint32_t Padding; /* Padding for 64 bit */ -#endif -} i2o_trl_control_word_t; - -/* ************************************************************************** */ - -/* I2O Successful Single Transaction Reply Message Frame structure. */ - -typedef struct i2o_single_reply_message_frame { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint16_t DetailedStatusCode; - uint8_t reserved; - uint8_t ReqStatus; - /* ReplyPayload */ -} i2o_single_reply_message_frame_t; - -/* ************************************************************************** */ - -/* I2O Successful Multiple Transaction Reply Message Frame structure. */ - -typedef struct i2o_multiple_reply_message_frame { - i2o_message_frame_t StdMessageFrame; - i2o_trl_control_word_t TrlControlWord; - uint16_t DetailedStatusCode; - uint8_t reserved; - uint8_t ReqStatus; - /* TransactionDetails[] */ -} i2o_multiple_reply_message_frame_t; - -/* ************************************************************************** */ - -/* I2O Private Message Frame structure. */ - -typedef struct i2o_private_message_frame { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint16_t XFunctionCode; - uint16_t OrganizationID; - /* PrivatePayload[] */ -} i2o_private_message_frame_t; - -/* ************************************************************************** */ - -/* Message Failure Severity Codes */ - -#define I2O_SEVERITY_FORMAT_ERROR 0x1 -#define I2O_SEVERITY_PATH_ERROR 0x2 -#define I2O_SEVERITY_PATH_STATE 0x4 -#define I2O_SEVERITY_CONGESTION 0x8 - -/* Transport Failure Codes: Table 3-3 Mesasge Failure Codes */ - -#define I2O_FAILURE_CODE_TRANSPORT_SERVICE_SUSPENDED 0x81 -#define I2O_FAILURE_CODE_TRANSPORT_SERVICE_TERMINATED 0x82 -#define I2O_FAILURE_CODE_TRANSPORT_CONGESTION 0x83 -#define I2O_FAILURE_CODE_TRANSPORT_FAIL 0x84 -#define I2O_FAILURE_CODE_TRANSPORT_STATE_ERROR 0x85 -#define I2O_FAILURE_CODE_TRANSPORT_TIME_OUT 0x86 -#define I2O_FAILURE_CODE_TRANSPORT_ROUTING_FAILURE 0x87 -#define I2O_FAILURE_CODE_TRANSPORT_INVALID_VERSION 0x88 -#define I2O_FAILURE_CODE_TRANSPORT_INVALID_OFFSET 0x89 -#define I2O_FAILURE_CODE_TRANSPORT_INVALID_MSG_FLAGS 0x8A -#define I2O_FAILURE_CODE_TRANSPORT_FRAME_TOO_SMALL 0x8B -#define I2O_FAILURE_CODE_TRANSPORT_FRAME_TOO_LARGE 0x8C -#define I2O_FAILURE_CODE_TRANSPORT_INVALID_TARGET_ID 0x8D -#define I2O_FAILURE_CODE_TRANSPORT_INVALID_INITIATOR_ID 0x8E -#define I2O_FAILURE_CODE_TRANSPORT_INVALID_INITIATOR_CONTEXT 0x8F -#define I2O_FAILURE_CODE_TRANSPORT_UNKNOWN_FAILURE 0xFF - -/* IOP_ID and Severity sizes */ - -#define I2O_FAILCODE_SEVERITY_SZ 8 -#define I2O_FAILCODE_CODE_SZ 8 - -/* I2O Transport Message Reply for Message Failure. */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_failure_reply_message_frame { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint8_t LowestVersion; - uint8_t HighestVersion; - uint8_t Severity; - uint8_t FailureCode; - union { - struct { - uint16_t FailingIOP_ID:12; - uint16_t reserved:4; - } s; - uint16_t h; - } u1; - uint16_t FailingHostUnitID; - uint32_t AgeLimit; - i2o_message_frame_t *PreservedMFA; -} i2o_failure_reply_message_frame_t; - -/* macros to access the bit field(s) */ - -#define get_reply_msg_FailingIOP_ID(p, hdl) \ - ((p)->u1.s.FailingIOP_ID) -#endif - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_failure_reply_message_frame { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint8_t LowestVersion; - uint8_t HighestVersion; - uint8_t Severity; - uint8_t FailureCode; - union { - struct { - uint16_t reserved:4; - uint16_t FailingIOP_ID:12; - } s; - uint16_t h; - } u1; - uint16_t FailingHostUnitID; - uint32_t AgeLimit; - i2o_message_frame_t *PreservedMFA; -} i2o_failure_reply_message_frame_t; - -/* macros to access the bit field(s) */ - -#define get_reply_msg_FailingIOP_ID(p, hdl) \ - (ddi_get16(hdl, &(p)->u1.h) & 0xFFF) -#endif - -/* I2O Transport Message Reply for Transaction Error. */ - -typedef struct i2o_transaction_error_reply_message_frame { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint16_t DetailedStatusCode; - uint8_t reserved; - uint8_t ReqStatus; /* Should Transaction Error */ - uint32_t ErrorOffset; - uint8_t BitOffset; - uint8_t reserved1; - uint16_t reserved2; -} i2o_transaction_error_reply_message_frame_t; - -/* ************************************************************************** */ - -/* Misc. commonly used structures */ - -#define I2O_MAX_SERIAL_NUMBER_SZ 256 - -typedef struct i2o_serial_info { - uint8_t SerialNumberLength; - uint8_t SerialNumberFormat; - uint8_t SerialNumber[I2O_MAX_SERIAL_NUMBER_SZ]; -} i2o_serial_info_t; - - -/* ************************************************************************** */ -/* Hardware Resource Table (HRT) and Logical Configuration Table (LCT) */ -/* ************************************************************************** */ - -/* Bus Type Code defines */ - -#define I2O_LOCAL_BUS 0 -#define I2O_ISA_BUS 1 -#define I2O_EISA_BUS 2 -#define I2O_PCI_BUS 4 -#define I2O_PCMCIA_BUS 5 -#define I2O_NUBUS_BUS 6 -#define I2O_CARDBUS_BUS 7 -#define I2O_OTHER_BUS 0x80 - -#define I2O_HRT_STATE_SZ 4 -#define I2O_HRT_BUS_NUMBER_SZ 8 -#define I2O_HRT_BUS_TYPE_SZ 8 - - -/* Bus Structures */ - -/* PCI Bus */ -typedef struct i2o_pci_bus_info { - uint8_t PciFunctionNumber; - uint8_t PciDeviceNumber; - uint8_t PciBusNumber; - uint8_t reserved; - uint16_t PciVendorID; - uint16_t PciDeviceID; -} i2o_pci_bus_info_t; - -/* Local Bus */ -typedef struct i2o_local_bus_info { - uint16_t LbBaseIOPort; - uint16_t reserved; - uint32_t LbBaseMemoryAddress; -} i2o_local_bus_info_t; - -/* ISA Bus */ -typedef struct i2o_isa_bus_info { - uint16_t IsaBaseIOPort; - uint8_t CSN; - uint8_t reserved; - uint32_t IsaBaseMemoryAddress; -} i2o_isa_bus_info_t; - -/* EISA Bus */ -typedef struct i2o_eisa_bus_info { - uint16_t EisaBaseIOPort; - uint8_t reserved; - uint8_t EisaSlotNumber; - uint32_t EisaBaseMemoryAddress; -} i2o_eisa_bus_info_t; - -/* Other Bus */ -typedef struct i2o_other_bus_info { - uint16_t BaseIOPort; - uint16_t reserved; - uint32_t BaseMemoryAddress; -} i2o_other_bus_info_t; - - -/* HRT Entry Block */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_hrt_entry { - uint32_t AdapterID; - union { - struct { - uint16_t ControllingTID:12; - uint16_t AdapterState:4; - } s2; - uint16_t h2; - } u2; - uint8_t BusNumber; - uint8_t BusType; - union { - /* PCI Bus */ - i2o_pci_bus_info_t PCIBus; - - /* Local Bus */ - i2o_local_bus_info_t LocalBus; - - /* ISA Bus */ - i2o_isa_bus_info_t ISABus; - - /* EISA Bus */ - i2o_eisa_bus_info_t EISABus; - - /* Other. */ - i2o_other_bus_info_t OtherBus; - } uBus; -} i2o_hrt_entry_t; - -/* macros to access the bit fields */ - -#define get_hrt_entry_ControllingTID(p, hdl) (p)->u2.s2.ControllingTID -#define get_hrt_entry_AdapterState(p, hdl) (p)->u2.s2.AdapterState - -#endif - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_hrt_entry { - uint32_t AdapterID; - union { - struct { - uint16_t AdapterState:4; - uint16_t ControllingTID:12; - } s2; - uint16_t h2; - } u2; - uint8_t BusNumber; - uint8_t BusType; - union { - /* PCI Bus */ - i2o_pci_bus_info_t PCIBus; - - /* Local Bus */ - i2o_local_bus_info_t LocalBus; - - /* ISA Bus */ - i2o_isa_bus_info_t ISABus; - - /* EISA Bus */ - i2o_eisa_bus_info_t EISABus; - - /* Other. */ - i2o_other_bus_info_t OtherBus; - } uBus; -} i2o_hrt_entry_t; - -/* macros to access the bit fields */ - -#define get_hrt_entry_ControllingTID(p, hdl) \ - (ddi_get16(hdl, &(p)->u2.h2) & 0xFFF) -#define get_hrt_entry_AdapterState(p, hdl) \ - ((ddi_get16(hdl, &(p)->u2.h2) >> 12) & 0xF) -#endif - -/* I2O Hardware Resource Table structure. */ - -typedef struct i2o_hrt { - uint16_t NumberEntries; - uint8_t EntryLength; - uint8_t HRTVersion; - uint32_t CurrentChangeIndicator; - i2o_hrt_entry_t HRTEntry[1]; -} i2o_hrt_t; - - -/* ************************************************************************** */ -/* Logical Configuration Table */ -/* ************************************************************************** */ - -/* I2O Logical Configuration Table structures. */ - -#define I2O_IDENTITY_TAG_SZ 8 - -/* I2O Logical Configuration Table Device Flags */ - -#define I2O_LCT_DEVICE_FLAGS_CONF_DIALOG_REQUEST 0x01 -#define I2O_LCT_DEVICE_FLAGS_MORE_THAN_1_USER 0x02 -#define I2O_LCT_DEVICE_FLAGS_PEER_SERVICE_DISABLED 0x10 -#define I2O_LCT_DEVICE_FLAGS_MANAGEMENT_SERVICE_DISABLED 0x20 - -/* LCT Entry Block */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_lct_entry { - union { - struct { - uint32_t TableEntrySize:16; - uint32_t LocalTID:12; - uint32_t reserved:4; - } s1; - uint32_t w1; - } u1; - uint32_t ChangeIndicator; - uint32_t DeviceFlags; - union { - struct i2o_class_id { - uint32_t Class:12; - uint32_t Version:4; - uint32_t OrganizationID:16; - } s4; - uint32_t w4; - } u4; - uint32_t SubClassInfo; - union { - struct { - uint32_t UserTID:12; - uint32_t ParentTID:12; - uint32_t BiosInfo:8; - } s6; - uint32_t w6; - } u6; - uint8_t IdentityTag[I2O_IDENTITY_TAG_SZ]; - uint32_t EventCapabilities; -} i2o_lct_entry_t; - -/* macros to access the bit fields */ - -#define get_lct_entry_LocalTID(p, hdl) (p)->u1.s1.LocalTID -#define get_lct_entry_TableEntrySize(p, hdl) (p)->u1.s1.TableEntrySize - -#define get_lct_entry_Class(p, hdl) (p)->u4.s4.Class -#define get_lct_entry_Version(p, hdl) (p)->u4.s4.Version -#define get_lct_entry_OrganizationID(p, hdl) (p)->u4.s4.OrganizationID - -#define get_lct_entry_BiosInfo(p, hdl) (p)->u6.s6.BiosInfo -#define get_lct_entry_ParentTID(p, hdl) (p)->u6.s6.ParentTID -#define get_lct_entry_UserTID(p, hdl) (p)->u6.s6.UserTID - -#endif - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_lct_entry { - union { - struct { - uint32_t reserved:4; - uint32_t LocalTID:12; - uint32_t TableEntrySize:16; - } s1; - uint32_t w1; - } u1; - uint32_t ChangeIndicator; - uint32_t DeviceFlags; - union { - struct i2o_class_id { - uint32_t OrganizationID:16; - uint32_t Version:4; - uint32_t Class:12; - } s4; - uint32_t w4; - } u4; - uint32_t SubClassInfo; - union { - struct { - uint32_t BiosInfo:8; - uint32_t ParentTID:12; - uint32_t UserTID:12; - } s6; - uint32_t w6; - } u6; - uint8_t IdentityTag[I2O_IDENTITY_TAG_SZ]; - uint32_t EventCapabilities; -} i2o_lct_entry_t; - -/* macros to access the bit fields */ - -#define get_lct_entry_TableEntrySize(p, hdl) \ - (ddi_get32(hdl, &(p)->u1.w1) & 0xFFFF) -#define get_lct_entry_LocalTID(p, hdl) \ - ((ddi_get32(hdl, (p)->u1.w1) >> 16) & 0xFFF) - -#define get_lct_entry_OrganizationID(p, hdl) \ - ((ddi_get16(hdl, (p)->u4.w4) >> 16) & 0xFFFF) -#define get_lct_entry_Version(p, hdl) \ - ((ddi_get32(hdl, &(p)->u4.w4) >> 12) & 0xF) -#define get_lct_entry_Class(p, hdl) \ - (ddi_get32(hdl, &(p)->u4.w4) & 0xFFF) - -#define get_lct_entry_BiosInfo(p, hdl) (p)->u6.s6.BiosInfo -#define get_lct_entry_ParentTID(p, hdl) \ - ((ddi_get32(hdtl, &(p)->u6.w6) >> 12) & 0xFFF) -#define get_lct_entry_UserTID(p, hdl) \ - (ddi_get32(hdtl, &(p)->u6.w6) & 0xFFF) - -#endif - -/* I2O Logical Configuration Table structure. */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_lct { - uint16_t TableSize; - union { - struct { - uint16_t BootDeviceTID:12; - uint16_t LctVer:4; - } s1; - uint16_t h1; - } u1; - uint32_t IopFlags; - uint32_t CurrentChangeIndicator; - i2o_lct_entry_t LCTEntry[1]; -} i2o_lct_t; - -/* macros to access the bit fields */ - -#define get_lct_BootDeviceTID(p, hdl) (p)->u1.s1.BootDeviceTID -#define get_lct_LctVer(p, hdl) (p)->u1.s1.LctVer - -#endif - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_lct { - uint16_t TableSize; - union { - struct { - uint16_t LctVer:4; - uint16_t BootDeviceTID:12; - } s1; - uint16_t h1; - } u1; - uint32_t IopFlags; - uint32_t CurrentChangeIndicator; - i2o_lct_entry_t LCTEntry[1]; -} i2o_lct_t; - -/* macros to access the bit fields */ - -#define get_lct_BootDeviceTID(p, hdl) \ - ((ddi_get32(hdl, &(p)->u1.w1) >> 16) & 0xFFF) -#define get_lct_LctVer(p, hdl) \ - ((ddi_get32(hdl, &(p)->u1.w1) >> 28) & 0xF) - -#endif - -/* ************************************************************************** */ - -/* Memory Addressing structures and defines. */ - -/* SglFlags defines. */ - -#define I2O_SGL_FLAGS_LAST_ELEMENT 0x80 -#define I2O_SGL_FLAGS_END_OF_BUFFER 0x40 - -#define I2O_SGL_FLAGS_IGNORE_ELEMENT 0x00 -#define I2O_SGL_FLAGS_TRANSPORT_ELEMENT 0x04 -#define I2O_SGL_FLAGS_BIT_BUCKET_ELEMENT 0x08 -#define I2O_SGL_FLAGS_IMMEDIATE_DATA_ELEMENT 0x0C -#define I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT 0x10 -#define I2O_SGL_FLAGS_PAGE_LIST_ADDRESS_ELEMENT 0x20 -#define I2O_SGL_FLAGS_CHAIN_POINTER_ELEMENT 0x30 -#define I2O_SGL_FLAGS_LONG_TRANSACTION_ELEMENT 0x40 -#define I2O_SGL_FLAGS_SHORT_TRANSACTION_ELEMENT 0x70 -#define I2O_SGL_FLAGS_SGL_ATTRIBUTES_ELEMENT 0x7C - -#define I2O_SGL_FLAGS_BC0 0x01 -#define I2O_SGL_FLAGS_BC1 0x02 -#define I2O_SGL_FLAGS_DIR 0x04 -#define I2O_SGL_FLAGS_LOCAL_ADDRESS 0x08 - -#define I2O_SGL_FLAGS_CONTEXT_COUNT_MASK 0x03 -#define I2O_SGL_FLAGS_ADDRESS_MODE_MASK 0x3C -#define I2O_SGL_FLAGS_NO_CONTEXT 0x00 - -/* Scatter/Gather Truth Table */ - -/* - * - * typedef enum _SG_TYPE { - * INVALID, - * Ignore, - * TransportDetails, - * BitBucket, - * ImmediateData, - * Simple, - * PageList, - * ChainPointer, - * ShortTransaction, - * LongTransaction, - * SGLAttributes, - * INVALID/ReservedLongFormat, - * INVALID/ReservedShortFormat - * } SG_TYPE, *PSG_TYPE; - * - * - * 0x00 Ignore; - * 0x04 TransportDetails; - * 0x08 BitBucket; - * 0x0C ImmediateData; - * 0x10 Simple; - * 0x14 Simple; - * 0x18 Simple; - * 0x1C Simple; - * 0x20 PageList; - * 0x24 PageList; - * 0x28 PageList; - * 0x2C PageList; - * 0x30 ChainPointer; - * 0x34 INVALID; - * 0x38 ChainPointer; - * 0x3C INVALID; - * 0x40 LongTransaction; - * 0x44 INVALID/ReservedLongFormat; - * 0x48 BitBucket; - * 0x4C ImmediateData; - * 0x50 Simple; - * 0x54 Simple; - * 0x58 Simple; - * 0x5C Simple; - * 0x60 PageList; - * 0x64 PageList; - * 0x68 PageList; - * 0x6C PageList; - * 0x70 ShortTransaction; - * 0x74 INVALID/ReservedShortFormat; - * 0x78 INVALID/ReservedShortFormat; - * 0X7C SGLATTRIBUTES; - */ - - -/* 32 Bit Context Field defines */ - -#define I2O_SGL_FLAGS_CONTEXT32_NULL 0x00 -#define I2O_SGL_FLAGS_CONTEXT32_U32 0x01 -#define I2O_SGL_FLAGS_CONTEXT32_U64 0x02 -#define I2O_SGL_FLAGS_CONTEXT32_U96 0x03 - -#define I2O_SGL_FLAGS_CONTEXT32_NULL_SZ 0x00 -#define I2O_SGL_FLAGS_CONTEXT32_U32_SZ 0x04 -#define I2O_SGL_FLAGS_CONTEXT32_U64_SZ 0x08 -#define I2O_SGL_FLAGS_CONTEXT32_U96_SZ 0x0C - -/* 64 Bit Context Field defines */ - -#define I2O_SGL_FLAGS_CONTEXT64_NULL 0x00 -#define I2O_SGL_FLAGS_CONTEXT64_U64 0x01 -#define I2O_SGL_FLAGS_CONTEXT64_U128 0x02 -#define I2O_SGL_FLAGS_CONTEXT64_U192 0x03 - -#define I2O_SGL_FLAGS_CONTEXT64_NULL_SZ 0x00 -#define I2O_SGL_FLAGS_CONTEXT64_U64_SZ 0x08 -#define I2O_SGL_FLAGS_CONTEXT64_U128_SZ 0x10 -#define I2O_SGL_FLAGS_CONTEXT64_U192_SZ 0x18 - -/* SGL Attribute Element defines */ - -#define I2O_SGL_ATTRIBUTE_FLAGS_BIT_BUCKET_HINT 0x0400 -#define I2O_SGL_ATTRIBUTE_FLAGS_IMMEDIATE_DATA_HINT 0x0200 -#define I2O_SGL_ATTRIBUTE_FLAGS_LOCAL_ADDRESS_HINT 0x0100 -#define I2O_SGL_ATTRIBUTE_FLAGS_32BIT_TRANSACTION 0x0000 -#define I2O_SGL_ATTRIBUTE_FLAGS_64BIT_TRANSACTION 0x0004 -#define I2O_SGL_ATTRIBUTE_FLAGS_32BIT_LOCAL_ADDRESS 0x0000 - -/* SG Size defines */ - -#define I2O_SG_COUNT_SZ 24 -#define I2O_SG_FLAGS_SZ 8 - -/* Standard Flags and Count fields for SG Elements */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef union i2o_flags_count { - struct { - uint32_t Count:24; - uint32_t Flags:8; - } flags_count; - uint32_t cword; -} i2o_flags_count_t; - -#define get_flags_count_Count(p, hdl) (p)->flags_count.Count -#define put_flags_count_Count(p, v, hdl) ((p)->flags_count.Count = (v)) -#define get_flags_count_Flags(p, hdl) (p)->flags_count.Flags -#define put_flags_count_Flags(p, v, hdl) ((p)->flags_count.Flags = (v)) - -#endif - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef union i2o_flags_count { - struct { - uint32_t Flags:8; - uint32_t Count:24; - } flags_count; - uint32_t cword; -} i2o_flags_count_t; - -#define get_flags_count_Count(p, hdl) \ - (ddi_get32(hdl, &(p)->cword) & 0xFFFFFF) -#define put_flags_count_Count(p, v, hdl) \ - ddi_put32(hdl, &(p)->cword, \ - (ddi_get32(hdl, &(p)->cword) & ~0xFFFFFF) | \ - ((uint32_t)(v) & 0xFFFFFF)) -#define get_flags_count_Flags(p, hdl) \ - ((ddi_get32(hdl, &(p)->cword) >> 24) & 0xFF) -#define put_flags_count_Flags(p, v, hdl) \ - ddi_put32(hdl, &(p)->cword, \ - (ddi_get32(hdl, &(p)->cword) & ~0xFF000000) | ((uint32_t)(v) << 24)) -#endif - -/* Bit Bucket Element */ - -typedef struct i2o_sge_bit_bucket_element { - i2o_flags_count_t FlagsCount; - uint32_t BufferContext; -} i2o_sge_bit_bucket_element_t; - -/* Chain Addressing Scatter-Gather Element */ - -typedef struct i2o_sge_chain_element { - i2o_flags_count_t FlagsCount; - uint32_t PhysicalAddress; -} i2o_sge_chain_element_t; - -/* Chain Addressing with Context Scatter-Gather Element */ - -typedef struct i2o_sge_chain_context_element { - i2o_flags_count_t FlagsCount; - uint32_t Context[1]; - uint32_t PhysicalAddress; -} i2o_sge_chain_context_element_t; - -/* Ignore Scatter-Gather Element */ - -typedef struct i2o_sge_ignore_element { - i2o_flags_count_t FlagsCount; -} i2o_sge_ignore_element_t; - -/* Immediate Data Element */ - -typedef struct i2o_sge_immediate_data_element { - i2o_flags_count_t FlagsCount; -} i2o_sge_immediate_data_element_t; - -/* Immediate Data with Context Element */ - -typedef struct i2o_sge_immediate_data_context_element { - i2o_flags_count_t FlagsCount; - uint32_t BufferContext; -} i2o_sge_immediate_data_context_element_t; - -/* Long Transaction Parameters Element */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_sge_long_transaction_element { - union { - struct { - uint32_t LongElementLength:24; - uint32_t Flags:8; - } s1; - uint32_t w1; - } u1; - uint32_t BufferContext; -} i2o_sge_long_transaction_element_t; - -#define get_sge_long_LongElementLength(p, hdl) \ - (p)->u1.s1.LongElementLength -#define put_sge_long_LongElementLength(p, v, hdl) \ - ((p)->u1.s1.LongElementLength = (v)) -#define get_sge_long_Flags(p, hdl) \ - (p)->u1.s1.Flags -#define put_sge_long_Flags(p, v, hdl) \ - ((p)->u1.s1.Flags = (v)) - -#endif - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_sge_long_transaction_element { - union { - struct { - uint32_t Flags:8; - uint32_t LongElementLength:24; - } s1; - uint32_t w1; - } u1; - uint32_t BufferContext; -} i2o_sge_long_transaction_element_t; - -#define get_sge_long_LongElementLength(p, hdl) \ - (ddi_get32(hdl, &(p)->u1.w1) & 0xFFFFFF) -#define put_sge_long_LongElementLength(p, v, hdl) \ - ddi_put32(hdl, &(p)->u1.w1, \ - (ddi_get32(hdl, &(p)->u1.w1) & ~0xFFFFFF) | \ - ((uint32_t)(v) & 0xFFFFFF)) -#define get_sge_long_Flags(p, hdl) \ - (ddi_get32(hdl, &(p)->u1.w1) >> 24) -#define put_sge_long_Flags(p, v, hdl) \ - ddi_put32(hdl, &(p)->u1.w1, \ - (ddi_get32(hdl, &(p)->u1.w1) & ~0xFF000000) | \ - ((uint32_t)(v) << 24)) -#endif - -/* Page List Scatter-Gather Element */ - -typedef struct i2o_sge_page_element { - i2o_flags_count_t FlagsCount; - uint32_t PhysicalAddress[1]; -} i2o_sge_page_element_t; - -/* Page List with Context Scatter-Gather Element */ - -typedef struct i2o_sge_page_context_element { - i2o_flags_count_t FlagsCount; - uint32_t BufferContext[1]; - uint32_t PhysicalAddress[1]; -} i2o_sge_page_context_element_t; - -/* SGL Attribute Element */ - -typedef struct i2o_sge_sgl_attributes_element { - uint16_t SglAttributeFlags; - uint8_t ElementLength; - uint8_t Flags; - uint32_t PageFrameSize; -} i2o_sge_sgl_attributes_element_t; - -/* Short Transaction Parameters Element */ - -typedef struct i2o_sge_short_transaction_element { - uint16_t ClassFields; - uint8_t ElementLength; - uint8_t Flags; - uint32_t BufferContext; -} i2o_sge_short_transaction_element_t; - -/* Simple Addressing Scatter-Gather Element */ - -typedef struct i2o_sge_simple_element { - i2o_flags_count_t FlagsCount; - uint32_t PhysicalAddress; -} i2o_sge_simple_element_t; - -/* Simple Addressing with Context Scatter-Gather Element */ - -typedef struct i2o_sge_simple_context_element { - i2o_flags_count_t FlagsCount; - uint32_t BufferContext[1]; - uint32_t PhysicalAddress; -} i2o_sge_simple_context_element_t; - -/* Transport Detail Element */ - -typedef struct i2o_sge_transport_element { - uint_t LongElementLength:24; - uint_t Flags:8; -} i2o_sge_transport_element_t; - -typedef struct i2o_sg_element { - union { - /* Bit Bucket Element */ - i2o_sge_bit_bucket_element_t BitBucket; - - /* Chain Addressing Element */ - i2o_sge_chain_element_t Chain; - - /* Chain Addressing with Context Element */ - i2o_sge_chain_context_element_t ChainContext; - - /* Ignore Scatter-Gather Element */ - i2o_sge_ignore_element_t Ignore; - - /* Immediate Data Element */ - i2o_sge_immediate_data_element_t ImmediateData; - - /* Immediate Data with Context Element */ - i2o_sge_immediate_data_context_element_t ImmediateDataContext; - - /* Long Transaction Parameters Element */ - i2o_sge_long_transaction_element_t LongTransaction; - - /* Page List Element */ - i2o_sge_page_element_t Page; - - /* Page List with Context Element */ - i2o_sge_page_context_element_t PageContext; - - /* SGL Attribute Element */ - i2o_sge_sgl_attributes_element_t SGLAttribute; - - /* Short Transaction Parameters Element */ - i2o_sge_short_transaction_element_t ShortTransaction; - - /* Simple Addressing Element */ - i2o_sge_simple_element_t Simple[1]; - - /* Simple Addressing with Context Element */ - i2o_sge_simple_context_element_t SimpleContext[1]; - - /* Transport Detail Element */ - i2o_sge_transport_element_t Transport; - } u1; -} i2o_sg_element_t; - -/* ************************************************************************** */ -/* Basic Parameter Group Access */ -/* ************************************************************************** */ - -/* Operation Function Numbers */ - -#define I2O_PARAMS_OPERATION_FIELD_GET 0x0001 -#define I2O_PARAMS_OPERATION_LIST_GET 0x0002 -#define I2O_PARAMS_OPERATION_MORE_GET 0x0003 -#define I2O_PARAMS_OPERATION_SIZE_GET 0x0004 -#define I2O_PARAMS_OPERATION_TABLE_GET 0x0005 -#define I2O_PARAMS_OPERATION_FIELD_SET 0x0006 -#define I2O_PARAMS_OPERATION_LIST_SET 0x0007 -#define I2O_PARAMS_OPERATION_ROW_ADD 0x0008 -#define I2O_PARAMS_OPERATION_ROW_DELETE 0x0009 -#define I2O_PARAMS_OPERATION_TABLE_CLEAR 0x000A - -/* Operations List Header */ - -typedef struct i2o_param_operations_list_header { - uint16_t OperationCount; - uint16_t Reserved; -} i2o_param_operations_list_header_t; - -/* Results List Header */ - -typedef struct i2o_param_results_list_header { - uint16_t ResultCount; - uint16_t Reserved; -} i2o_param_results_list_header_t; - -/* Read Operation Result Block Template Structure */ - -typedef struct i2o_param_read_operation_result { - uint16_t BlockSize; - uint8_t BlockStatus; - uint8_t ErrorInfoSize; - /* Operations Results */ - /* Pad (if any) */ - /* ErrorInformation (if any) */ -} i2o_param_read_operation_result_t; - -typedef struct i2o_table_read_operation_result { - uint16_t BlockSize; - uint8_t BlockStatus; - uint8_t ErrorInfoSize; - uint16_t RowCount; - uint16_t MoreFlag; - /* Operations Results */ - /* Pad (if any) */ - /* ErrorInformation (if any) */ -} i2o_table_read_operation_result_t; - -/* Error Information Template Structure */ - -typedef struct i2o_param_error_info_template { - uint16_t OperationCode; - uint16_t GroupNumber; - uint16_t FieldIdx; - uint8_t AdditionalStatus; - uint8_t NumberKeys; - /* List of Key Values (variable) */ - /* Pad (if any) */ -} i2o_param_error_info_template_t; - -/* Operation Template for Specific Fields */ - -typedef struct i2o_param_operation_specific_template { - uint16_t Operation; - uint16_t GroupNumber; - uint16_t FieldCount; - uint16_t FieldIdx[1]; - /* Pad (if any) */ -} i2o_param_operation_specific_template_t; - -/* Operation Template for All Fields */ - -typedef struct i2o_param_operation_all_template { - uint16_t Operation; - uint16_t GroupNumber; - uint16_t FieldCount; - /* Pad (if any) */ -} i2o_param_operation_all_template_t; - -/* Operation Template for All List Fields */ - -typedef struct i2o_param_operation_all_list_template { - uint16_t Operation; - uint16_t GroupNumber; - uint16_t FieldCount; - uint16_t KeyCount; - uint8_t KeyValue; - /* Pad (if any) */ -} i2o_param_operation_all_list_template_t; - -/* Modify Operation Result Block Template Structure */ - -typedef struct i2o_param_modify_operation_result { - uint16_t BlockSize; - uint8_t BlockStatus; - uint8_t ErrorInfoSize; - /* ErrorInformation (if any) */ -} i2o_param_modify_operation_result_t; - -/* Operation Template for Row Delete */ - -typedef struct i2o_param_operation_row_delete_template { - uint16_t Operation; - uint16_t GroupNumber; - uint16_t RowCount; - uint8_t KeyValue; -} i2o_param_operation_row_delete_template_t; - -/* Operation Template for Table Clear */ - -typedef struct i2o_param_operation_table_clear_template { - uint16_t Operation; - uint16_t GroupNumber; -} i2o_param_operation_table_clear_template_t; - -/* Status codes and Error Information for Parameter functions */ - -#define I2O_PARAMS_STATUS_SUCCESS 0x00 -#define I2O_PARAMS_STATUS_BAD_KEY_ABORT 0x01 -#define I2O_PARAMS_STATUS_BAD_KEY_CONTINUE 0x02 -#define I2O_PARAMS_STATUS_BUFFER_FULL 0x03 -#define I2O_PARAMS_STATUS_BUFFER_TOO_SMALL 0x04 -#define I2O_PARAMS_STATUS_FIELD_UNREADABLE 0x05 -#define I2O_PARAMS_STATUS_FIELD_UNWRITEABLE 0x06 -#define I2O_PARAMS_STATUS_INSUFFICIENT_FIELDS 0x07 -#define I2O_PARAMS_STATUS_INVALID_GROUP_ID 0x08 -#define I2O_PARAMS_STATUS_INVALID_OPERATION 0x09 -#define I2O_PARAMS_STATUS_NO_KEY_FIELD 0x0A -#define I2O_PARAMS_STATUS_NO_SUCH_FIELD 0x0B -#define I2O_PARAMS_STATUS_NON_DYNAMIC_GROUP 0x0C -#define I2O_PARAMS_STATUS_OPERATION_ERROR 0x0D -#define I2O_PARAMS_STATUS_SCALAR_ERROR 0x0E -#define I2O_PARAMS_STATUS_TABLE_ERROR 0x0F -#define I2O_PARAMS_STATUS_WRONG_GROUP_TYPE 0x10 - - -/* ************************************************************************** */ -/* GROUP Parameter Groups */ -/* ************************************************************************** */ - -/* GROUP Configuration and Operating Structures and Defines */ - -/* Groups Numbers */ - -#define I2O_UTIL_PARAMS_DESCRIPTOR_GROUP_NO 0xF000 -#define I2O_UTIL_PHYSICAL_DEVICE_TABLE_GROUP_NO 0xF001 -#define I2O_UTIL_CLAIMED_TABLE_GROUP_NO 0xF002 -#define I2O_UTIL_USER_TABLE_GROUP_NO 0xF003 -#define I2O_UTIL_PRIVATE_MESSAGE_EXTENSIONS_GROUP_NO 0xF005 -#define I2O_UTIL_AUTHORIZED_USER_TABLE_GROUP_NO 0xF006 -#define I2O_UTIL_DEVICE_IDENTITY_GROUP_NO 0xF100 -#define I2O_UTIL_DDM_IDENTITY_GROUP_NO 0xF101 -#define I2O_UTIL_USER_INFORMATION_GROUP_NO 0xF102 -#define I2O_UTIL_SGL_OPERATING_LIMITS_GROUP_NO 0xF103 -#define I2O_UTIL_SENSORS_GROUP_NO 0xF200 - -/* UTIL Group F000h - GROUP DESCRIPTORS Parameter Group */ - -#define I2O_UTIL_GROUP_PROPERTIES_GROUP_TABLE 0x01 -#define I2O_UTIL_GROUP_PROPERTIES_ROW_ADDITION 0x02 -#define I2O_UTIL_GROUP_PROPERTIES_ROW_DELETION 0x04 -#define I2O_UTIL_GROUP_PROPERTIES_CLEAR_OPERATION 0x08 - -typedef struct i2o_util_group_descriptor_table { - uint16_t GroupNumber; - uint16_t FieldCount; - uint16_t RowCount; - uint8_t Properties; - uint8_t reserved; -} i2o_util_group_descriptor_table_t; - -/* UTIL Group F001h - Physical Device Table Parameter Group */ - -typedef struct i2o_util_physical_device_table { - uint32_t AdapterID; -} i2o_util_physical_device_table_t; - -/* UTIL Group F002h - Claimed Table Parameter Group */ - -typedef struct i2o_util_claimed_table { - uint16_t ClaimedTID; -} i2o_util_claimed_table_t; - -/* UTIL Group F003h - User Table Parameter Group */ - -typedef struct i2o_util_user_table { - uint16_t Instance; - uint16_t UserTID; - uint8_t ClaimType; - uint8_t reserved1; - uint16_t reserved2; -} i2o_util_user_table_t; - -/* UTIL Group F005h - Private Message Extensions Parameter Group */ - -typedef struct i2o_util_private_message_extensions_table { - uint16_t ExtInstance; - uint16_t OrganizationID; - uint16_t XFunctionCode; -} i2o_util_private_message_extensions_table_t; - -/* UTIL Group F006h - Authorized User Table Parameter Group */ - -typedef struct i2o_util_authorized_user_table { - uint16_t AlternateTID; -} i2o_util_authorized_user_table_t; - -/* UTIL Group F100h - Device Identity Parameter Group */ - -typedef struct i2o_util_device_identity_scalar { - uint32_t ClassID; - uint16_t OwnerTID; - uint16_t ParentTID; - uint8_t VendorInfo[I2O_DEVID_VENDOR_INFO_SZ]; - uint8_t ProductInfo[I2O_DEVID_PRODUCT_INFO_SZ]; - uint8_t Description[I2O_DEVID_DESCRIPTION_SZ]; - uint8_t ProductRevLevel[I2O_DEVID_REV_LEVEL_SZ]; - uint8_t SNFormat; - uint8_t SerialNumber[I2O_MAX_SERIAL_NUMBER_SZ]; -} i2o_util_device_identity_scalar_t; - -/* UTIL Group F101h - DDM Identity Parameter Group */ - -typedef struct i2o_util_ddm_identity_scalar { - uint16_t DdmTID; - uint8_t ModuleName[I2O_MODULE_NAME_SZ]; - uint8_t ModuleRevLevel[I2O_DEVID_REV_LEVEL_SZ]; - uint8_t SNFormat; - uint8_t SerialNumber[I2O_MAX_SERIAL_NUMBER_SZ]; -} i2o_util_ddm_identity_scalar_t; - -/* UTIL Group F102h - User Information Parameter Group */ - -#define I2O_USER_DEVICE_NAME_SZ 64 -#define I2O_USER_SERVICE_NAME_SZ 64 -#define I2O_USER_PHYSICAL_LOCATION_SZ 64 - -typedef struct i2o_util_user_information_scalar { - uint8_t DeviceName[I2O_USER_DEVICE_NAME_SZ]; - uint8_t ServiceName[I2O_USER_SERVICE_NAME_SZ]; - uint8_t PhysicalLocation[I2O_USER_PHYSICAL_LOCATION_SZ]; - uint32_t InstanceNumber; -} i2o_util_user_information_scalar_t; - -/* UTIL Group F103h - SGL Operating Limits Parameter Group */ - -typedef struct i2o_util_sgl_operating_limits_scalar { - uint32_t SglChainSize; - uint32_t SglChainSizeMax; - uint32_t SglChainSizeTarget; - uint16_t SglFragCount; - uint16_t SglFragCountMax; - uint16_t SglFragCountTarget; -} i2o_util_sgl_operating_limits_scalar_t; - -/* UTIL Group F200h - Sensors Parameter Group */ - -#define I2O_SENSOR_COMPONENT_OTHER 0x00 -#define I2O_SENSOR_COMPONENT_PLANAR_LOGIC_BOARD 0x01 -#define I2O_SENSOR_COMPONENT_CPU 0x02 -#define I2O_SENSOR_COMPONENT_CHASSIS 0x03 -#define I2O_SENSOR_COMPONENT_POWER_SUPPLY 0x04 -#define I2O_SENSOR_COMPONENT_STORAGE 0x05 -#define I2O_SENSOR_COMPONENT_EXTERNAL 0x06 - -#define I2O_SENSOR_SENSOR_CLASS_ANALOG 0x00 -#define I2O_SENSOR_SENSOR_CLASS_DIGITAL 0x01 - -#define I2O_SENSOR_SENSOR_TYPE_OTHER 0x00 -#define I2O_SENSOR_SENSOR_TYPE_THERMAL 0x01 -#define I2O_SENSOR_SENSOR_TYPE_DC_VOLTAGE 0x02 -#define I2O_SENSOR_SENSOR_TYPE_AC_VOLTAGE 0x03 -#define I2O_SENSOR_SENSOR_TYPE_DC_CURRENT 0x04 -#define I2O_SENSOR_SENSOR_TYPE_AC_CURRENT 0x05 -#define I2O_SENSOR_SENSOR_TYPE_DOOR_OPEN 0x06 -#define I2O_SENSOR_SENSOR_TYPE_FAN_OPERATIONAL 0x07 - -#define I2O_SENSOR_SENSOR_STATE_NORMAL 0x00 -#define I2O_SENSOR_SENSOR_STATE_ABNORMAL 0x01 -#define I2O_SENSOR_SENSOR_STATE_UNKNOWN 0x02 -#define I2O_SENSOR_SENSOR_STATE_LOW_CAT 0x03 -#define I2O_SENSOR_SENSOR_STATE_LOW 0x04 -#define I2O_SENSOR_SENSOR_STATE_LOW_WARNING 0x05 -#define I2O_SENSOR_SENSOR_STATE_HIGH_WARNING 0x06 -#define I2O_SENSOR_SENSOR_STATE_HIGH 0x07 -#define I2O_SENSOR_SENSOR_STATE_HIGH_CAT 0x08 - -#define I2O_SENSOR_EVENT_ENABLE_STATE_CHANGE 0x0001 -#define I2O_SENSOR_EVENT_ENABLE_LOW_CATASTROPHIC 0x0002 -#define I2O_SENSOR_EVENT_ENABLE_LOW_READING 0x0004 -#define I2O_SENSOR_EVENT_ENABLE_LOW_WARNING 0x0008 -#define I2O_SENSOR_EVENT_ENABLE_CHANGE_TO_NORMAL 0x0010 -#define I2O_SENSOR_EVENT_ENABLE_HIGH_WARNING 0x0020 -#define I2O_SENSOR_EVENT_ENABLE_HIGH_READING 0x0040 -#define I2O_SENSOR_EVENT_ENABLE_HIGH_CATASTROPHIC 0x0080 - -typedef struct i2o_util_sensors_table { - uint16_t SensorInstance; - uint8_t Component; - uint16_t ComponentInstance; - uint8_t SensorClass; - uint8_t SensorType; - int8_t ScalingExponent; - int32_t ActualReading; - int32_t MinimumReading; - int32_t Low2LowCatThreshold; - int32_t LowCat2LowThreshold; - int32_t LowWarn2LowThreshold; - int32_t Low2LowWarnThreshold; - int32_t Norm2LowWarnThreshold; - int32_t LowWarn2NormThreshold; - int32_t NominalReading; - int32_t HiWarn2NormThreshold; - int32_t Norm2HiWarnThreshold; - int32_t High2HiWarnThreshold; - int32_t HiWarn2HighThreshold; - int32_t HiCat2HighThreshold; - int32_t Hi2HiCatThreshold; - int32_t MaximumReading; - uint8_t SensorState; - uint16_t EventEnable; -} i2o_util_sensors_table_t; - -/* - * ************************************************************************* - * Definitions used in Solaris for I2O Framework support. - * - * (NOTE: Current commitment level is PROJECT PRIVATE.) - * ************************************************************************* - */ - -#define I2O_MSG_SLEEP DDI_DMA_SLEEP -#define I2O_MSG_DONTWAIT DDI_DMA_DONTWAIT - -typedef void *i2o_iop_handle_t; -typedef void *i2o_msg_handle_t; - -int i2o_msg_osm_register(dev_info_t *dip, i2o_iop_handle_t *handlep); -int i2o_msg_get_lct(i2o_iop_handle_t iop, void *buf, - size_t buf_size, size_t *lct_sizep, size_t *real_sizep); -int i2o_msg_alloc(i2o_iop_handle_t iop, int (*waitfp)(caddr_t), caddr_t arg, - void **msgp, i2o_msg_handle_t *msg_handlep, - ddi_acc_handle_t *acc_handlep); -int i2o_msg_send(i2o_iop_handle_t iop, void *msg, i2o_msg_handle_t handle); -void i2o_msg_osm_unregister(i2o_iop_handle_t *iop); - -/* - * PCI Extensions to I2O Spec 1.5. - * - * (Note: Should these definitons go into pci.h?) - */ -#define PCI_I2O_BASE_CLASS 0x0E -#define PCI_I2O_SUB_CLASS 0x00 -#define PCI_I2O_PROG_CLASS0 0x00 /* no IOP interrupt */ -#define PCI_I2O_PROG_CLASS1 0x01 /* IOP interrupt supported */ - -/* Offset definitions for FIFO registers in IOP's shared memory */ - -#define PCI_IOP_INBOUND_FREELIST_FIFO 0x40 -#define PCI_IOP_INBOUND_POSTLIST_FIFO 0x40 -#define PCI_IOP_OUTBOUND_FREELIST_FIFO 0x44 -#define PCI_IOP_OUTBOUND_POSTLIST_FIFO 0x44 - -/* Offset definitions for Interrupt Control registers in IOP's shared memory */ - -#define PCI_IOP_INTR_MASK_REG 0x34 -#define PCI_IOP_INTR_STATUS_REG 0x30 - -/* Bit definitions in Interrupt Mask Register */ -#define I2O_OUTBOUND_POSTLIST_SERVICE_INTR_MASK 0x08 - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_I2OMSG_H */
--- a/usr/src/uts/common/sys/i2o/i2omstr.h Wed Apr 18 03:07:55 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,920 +0,0 @@ -/* - * Copyright (c) 1998-1999 by Sun Microsystems, Inc. - * All rights reserved. - */ - -/* - * ***************************************************************************** - * - * All software on this website is made available under the following terms and - * conditions. By downloading this software, you agree to abide by these terms - * and conditions with respect to this software. - * - * I2O SIG All rights reserved. - * - * These header files are provided, pursuant to your I2O SIG membership - * agreement, free of charge on an as-is basis without warranty of any kind, - * either express or implied, including but not limited to, implied warranties - * or merchantability and fitness for a particular purpose. I2O SIG does not - * warrant that this program will meet the user's requirements or that the - * operation of these programs will be uninterrupted or error-free. - * Acceptance and use of this program constitutes the user's understanding - * that he will have no recourse to I2O SIG for any actual or consequential - * damages including, but not limited to, loss profits arising out of use - * or inability to use this program. - * - * Member is permitted to create derivative works to this header-file program. - * However, all copies of the program and its derivative works must contain the - * I2O SIG copyright notice. - * - * ***************************************************************************** - */ - -#ifndef _SYS_I2OMSTOR_H -#define _SYS_I2OMSTOR_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#include <sys/i2o/i2omsg.h> /* the Base Message file */ -#include <sys/types.h> - - - -#define I2OMSTOR_REV 1_5_1 /* Header file revision string */ - - -/* - * **************************************************************************** - * - * I2OMStor.h -- I2O Random Block Storage Devices Class Message defintion - * file - * - * This file contains information presented in Chapter 6, Section 4 of - * the I2O Specification. - * - * Revision History: (Revision History tracks the revision number of the I2O - * specification) - * - * .92 - First marked revsion used for Proof of Concept. - * .93 - Change to match the rev .93 of the spec. - * .95 - Updated to Rev .95 of 2/5/96. - * 1.00 - Checked and Updated against spec version 1.00 4/9/96. - * 1.xx - Updated to the 1.x version of the I2O Specification (11/04/96). - * (RAID disk parameter group definition is not complete.) - * 1.xx - 11/06/96 1) Changed to new SGL addressing nomenclature. - * 2) Changed I2O_BSA_FLAGS reference to i2o_bsa_ctl_flags_t. - * 3) Added BSA request message definitions. - * 4) Commented out subclass and RAID request message definitions. - * 1.xx - 11/11/96 - * 1) Updated BSA Cache Control parameters group definitions. - * 1.xx - 11/13/96 - * 1) Changed messages definitions from "I20" to "I2O". - * 2) Fixed I2O_BSA_MEDIA_EJECT references. - * 3) Added "DSC" to Detailed Status Code definitions. - * 1.xx 11/15/96 - Added #pragma statments for i960. - * 1.5d 03/05/97 - Update for spec. draft version 1.5d. - * 1) Added "_BSA" designation to the three reply messages. - * 2) Added BSA_TIMEOUT DSC. - * 1.5d 04/11/97 - Corrections from review cycle: - * 1) Added reserved1 field to OPERATIONAL_CONTROL parameter group. - * 2) Added reserved2 field to ERROR_LOG parameter group. - * 3) Added reserved1 field to HIST_STATS parameter group. - * 4) Added reserved2 field to HIST_STATS parameter group. - * 5) Added reserved1 field to STORAGE_HIST_STATS parameter group. - * 6) Added reserved2 field to STORAGE_HIST_STATS parameter group. - * 7) Removed double underscore from MEDIA_INFO parameter group. - * 1.5.1 05/02/97 - Corrections from review cycle: - * 1) Change reply templates to include RetryCount field. - * 2) Add Aborted Operation reply message. - * 3) Remove #include for i2outil.h. - * 4) Add field to 32-bit align CACHE_CONTROL parameter group. - * 5) Add optional RAID parameter group definitions. - * 6) Add fields to 32-bit align REDUNDANCY parameter group. - * 7) Add fields to 32-bit align COMPONENT_SPARES parm group. - * 8) Add fields to 32-bit align ASSOCIATION parameter group. - * 9) Add revision string. - * 10) Convert tabs to spaces. - * 11) New disclaimer. - * - * **************************************************************************** - */ - -/* - * **************************************************************************** - * NOTES: - * - * Gets, reads, receives, etc. are all even numbered functions. - * Sets, writes, sends, etc. are all odd numbered functions. - * Functions that both send and receive data can be either but an attempt - * is made to use the function number that indicates the greater transfer - * amount. Functions that do not send or receive data use odd function - * numbers. - * - * Some functions are synonyms like read, receive and send, write. - * - * All common functions will have a code of less than 0x80. - * Unique functions to a class will start at 0x80. - * Executive Functions start at 0xA0. - * - * Utility Message function codes range from 0 - 0x1f - * Base Message function codes range from 0x20 - 0xfe - * Private Message function code is 0xff. - * ***************************************************************************** - */ - - - - -/* - * Random Block Storage Class specific functions - * - * Although the names are block storage class specific, the values - * assigned are common with other classes when applicable. - */ - -#define I2O_BSA_BLOCK_READ 0x30 -#define I2O_BSA_BLOCK_REASSIGN 0x71 -#define I2O_BSA_BLOCK_WRITE 0x31 -#define I2O_BSA_BLOCK_WRITE_VERIFY 0x33 -#define I2O_BSA_CACHE_FLUSH 0x37 -#define I2O_BSA_DEVICE_RESET 0x27 -#define I2O_BSA_MEDIA_EJECT 0x43 -#define I2O_BSA_MEDIA_FORMAT 0x45 -#define I2O_BSA_MEDIA_LOCK 0x49 -#define I2O_BSA_MEDIA_MOUNT 0x41 -#define I2O_BSA_MEDIA_UNLOCK 0x4B -#define I2O_BSA_MEDIA_VERIFY 0x35 -#define I2O_BSA_POWER_MANAGEMENT 0x70 -#define I2O_BSA_STATUS_CHECK 0x25 - -/* RAID Additions. */ -/* - * #define I2O_MANAGEMENT 0x81 - * #define I2O_DIAGNOSTICS 0x83 - * #define I2O_INSTRUMENTATION 0x85 - */ - -/* Detailed Status Codes for Random Block Storage operations */ - -#define I2O_BSA_DSC_SUCCESS 0x0000 -#define I2O_BSA_DSC_MEDIA_ERROR 0x0001 -#define I2O_BSA_DSC_ACCESS_ERROR 0x0002 -#define I2O_BSA_DSC_DEVICE_FAILURE 0x0003 -#define I2O_BSA_DSC_DEVICE_NOT_READY 0x0004 -#define I2O_BSA_DSC_MEDIA_NOT_PRESENT 0x0005 -#define I2O_BSA_DSC_MEDIA_LOCKED 0x0006 -#define I2O_BSA_DSC_MEDIA_FAILURE 0x0007 -#define I2O_BSA_DSC_PROTOCOL_FAILURE 0x0008 -#define I2O_BSA_DSC_BUS_FAILURE 0x0009 -#define I2O_BSA_DSC_ACCESS_VIOLATION 0x000A -#define I2O_BSA_DSC_WRITE_PROTECTED 0x000B -#define I2O_BSA_DSC_DEVICE_RESET 0x000C -#define I2O_BSA_DSC_VOLUME_CHANGED 0x000D -#define I2O_BSA_DSC_TIMEOUT 0x000E - - -/* ************************************************************************** */ - -/* Block Storage Parameter Groups */ - -/* ************************************************************************* */ - -/* Block Storage Configuration and Operating Structures and Defines */ - -/* Block Storage Parameter Groups */ - -#define I2O_BSA_DEVICE_INFO_GROUP_NO 0x0000 -#define I2O_BSA_OPERATIONAL_CONTROL_GROUP_NO 0x0001 -#define I2O_BSA_POWER_CONTROL_GROUP_NO 0x0002 -#define I2O_BSA_CACHE_CONTROL_GROUP_NO 0x0003 -#define I2O_BSA_MEDIA_INFO_GROUP_NO 0x0004 -#define I2O_BSA_ERROR_LOG_GROUP_NO 0x0005 - -/* Block Storage Optional Historical Statistics Parameter Groups */ - -#define I2O_BSA_HISTORICAL_STATS_CONTROL_GROUP_NO 0x0180 -#define I2O_BSA_STORAGE_HISTORICAL_STATS_GROUP_NO 0x0181 -#define I2O_BSA_CACHE_HISTORICAL_STATS_GROUP_NO 0x0182 - -/* Block Storage Optional RAID Disk Parameter Groups */ - -#define I2O_BSA_VOLUME_SET_INFORMATION_GROUP_NO 0x0200 -#define I2O_BSA_PROTECTED_SPACE_EXTENT_GROUP_NO 0x0201 -#define I2O_BSA_AGGREGATE_PROT_SPACE_EXT_GROUP_NO 0x0202 -#define I2O_BSA_PHYSICAL_EXTENT_GROUP_NO 0x0203 -#define I2O_BSA_AGGREGATE_PHYSICAL_EXT_GROUP_NO 0x0204 -#define I2O_BSA_REDUNDANCY_GROUP_NO 0x0205 -#define I2O_BSA_COMPONENT_SPARES_GROUP_NO 0x0206 -#define I2O_BSA_ASSOCIATION_TABLE_GROUP_NO 0x0207 - - -/* - 0000h - Device Information Parameters Group defines */ - -/* Device Type */ - -#define I2O_BSA_DEVICE_TYPE_DIRECT 0x00 -#define I2O_BSA_DEVICE_TYPE_WORM 0x04 -#define I2O_BSA_DEVICE_TYPE_CDROM 0x05 -#define I2O_BSA_DEVICE_TYPE_OPTICAL 0x07 - -/* Device Capability Support */ - -#define I2O_BSA_DEV_CAP_CACHING 0x00000001 -#define I2O_BSA_DEV_CAP_MULTI_PATH 0x00000002 -#define I2O_BSA_DEV_CAP_DYNAMIC_CAPACITY 0x00000004 -#define I2O_BSA_DEV_CAP_REMOVABLE_MEDIA 0x00000008 -#define I2O_BSA_DEV_CAP_REMOVEABLE_DEVICE 0x00000010 -#define I2O_BSA_DEV_CAP_READ_ONLY 0x00000020 -#define I2O_BSA_DEV_CAP_LOCKOUT 0x00000040 -#define I2O_BSA_DEV_CAP_BOOT_BYPASS 0x00000080 -#define I2O_BSA_DEV_CAP_COMPRESSION 0x00000100 -#define I2O_BSA_DEV_CAP_DATA_SECURITY 0x00000200 -#define I2O_BSA_DEV_CAP_RAID 0x00000400 - -/* Device States */ - -#define I2O_BSA_DEV_STATE_CACHING 0x00000001 -#define I2O_BSA_DEV_STATE_POWERED_ON 0x00000002 -#define I2O_BSA_DEV_STATE_READY 0x00000004 -#define I2O_BSA_DEV_STATE_MEDIA_LOADED 0x00000008 -#define I2O_BSA_DEV_STATE_DEVICE_LOADED 0x00000010 -#define I2O_BSA_DEV_STATE_READ_ONLY 0x00000020 -#define I2O_BSA_DEV_STATE_LOCKOUT 0x00000040 -#define I2O_BSA_DEV_STATE_BOOT_BYPASS 0x00000080 -#define I2O_BSA_DEV_STATE_COMPRESSION 0x00000100 -#define I2O_BSA_DEV_STATE_DATA_SECURITY 0x00000200 -#define I2O_BSA_DEV_STATE_RAID 0x00000400 - - -/* - 0001h - Operational Control Parameters Group defines */ - -/* No definition required */ - - -/* - 0002h - Power Control Parameters Group defines */ - -/* On Access */ - -#define I2O_BSA_POWERED_UP_ON_ACCESS 0x00000001 -#define I2O_BSA_LOAD_ON_ACCESS 0x00000002 - - -/* - 0003h - Cache Control Parameters Group defines */ - -/* Write Policy */ - -#define I2O_BSA_NO_WRITE_CACHE 0x00 -#define I2O_BSA_WRITE_TO_CACHE 0x01 -#define I2O_BSA_WRITE_THRU_CACHE 0x02 - -/* Read Policy */ - -#define I2O_BSA_NO_READ_CACHE 0x00 -#define I2O_BSA_READ_CACHE 0x01 -#define I2O_BSA_READ_AHEAD_CACHE 0x02 -#define I2O_BSA_READ_READ_AHEAD_CACHE 0x03 - -/* Error Correction */ - -#define I2O_BSA_ERR_COR_NONE 0x00 -#define I2O_BSA_ERR_COR_UNKNOWN 0x01 -#define I2O_BSA_ERR_COR_OTHER 0x02 -#define I2O_BSA_ERR_COR_PARITY 0x03 -#define I2O_BSA_ERR_COR_SINGLE_BIT_ECC 0x04 -#define I2O_BSA_ERR_COR_MULTI_BIT_ECC 0x05 - - -/* - 0004h - Media Information Parameters Group defines */ - -/* No definition required */ - - -/* - 0005h - Error Log Parameters Group defines */ - -/* No definition required */ - - -/* - 0180h - Historical Statistics Control Parameters Group defines */ - -/* Statistis Control */ - -#define I2O_BSA_STAT_CTL_STORAGE_ENABLE 0x01 -#define I2O_BSA_STAT_CTL_CACHE_ENABLE 0x02 - - -/* - 0181h - Storage Historical Statistics Parameter Group defines */ - -/* No definition required */ - - -/* - 0182h - Cache Historical Statistics Parameter Group defines */ - -/* No definition required */ - - -/* - 0200H - Volume Set Information Parameter Group defines */ - -/* No definition required */ - - -/* - 0201h - Protected Space Extent Parameter Group defines */ - -/* Data Stripe Granularity */ - -#define I2O_BSA_DATA_STRIPE_OTHER 0x00 -#define I2O_BSA_DATA_STRIPE_UNKNOWN 0x01 -#define I2O_BSA_DATA_STRIPE_BITS 0x02 -#define I2O_BSA_DATA_STRIPE_BYTES 0x03 -#define I2O_BSA_DATA_STRIPE_16BIT_WORDS 0x04 -#define I2O_BSA_DATA_STRIPE_32BIT_DWORDS 0x05 -#define I2O_BSA_DATA_STRIPE_BLOCKS 0x06 - -/* - 0202h - Aggregate Protected Space Extent Parameter Group defines */ - -/* No definition required */ - - -/* - 0203h - Physical Extent Parameter Group defines */ - -/* Granularity Unit */ - -#define I2O_BSA_GRANULARITY_OTHER 0x00 -#define I2O_BSA_GRANULARITY_UNKNOWN 0x01 -#define I2O_BSA_GRANULARITY_BITS 0x02 -#define I2O_BSA_GRANULARITY_BYTES 0x03 -#define I2O_BSA_GRANULARITY_16BIT_WORDS 0x04 -#define I2O_BSA_GRANULARITY_32BIT_DWORDS 0x05 -#define I2O_BSA_GRANULARITY_BLOCKS 0x06 - - -/* - 0204h - Aggregate Physical Extent Parameter Group defines */ - -/* No definition required */ - - -/* - 0205h - Redundancy Parameter Group defines */ - -/* Redundancy Type */ - -#define I2O_BSA_REDUNDANCY_OTHER 0x00 -#define I2O_BSA_REDUNDANCY_UNKNOWN 0x01 -#define I2O_BSA_REDUNDANCY_NONE 0x02 -#define I2O_BSA_REDUNDANCY_COPY 0x03 -#define I2O_BSA_REDUNDANCY_XOR 0x04 -#define I2O_BSA_REDUNDANCY_P_Q 0x05 -#define I2O_BSA_REDUNDANCY_S 0x06 -#define I2O_BSA_REDUNDANCY_P_S 0x07 - - -/* - 0206h - Component Spares Parameter Group defines */ - -/* Spare Functioning State */ - -#define I2O_BSA_SPARE_STATE_OTHER 0x00 -#define I2O_BSA_SPARE_STATE_UNKNOWN 0x01 -#define I2O_BSA_SPARE_STATE_INACTIVE 0x02 -#define I2O_BSA_SPARE_STATE_ACTIVE 0x03 -#define I2O_BSA_SPARE_STATE_LOAD_BALANCE 0x04 - - -/* - 0207h - Association Table Parameter Group defines */ - -/* Type */ - -#define I2O_BSA_ASSOC_TYPE_PHYSICAL 0x00 -#define I2O_BSA_ASSOC_TYPE_LOGICAL 0x01 -#define I2O_BSA_ASSOC_TYPE_LOG_TO_PHYS 0x02 -#define I2O_BSA_ASSOC_TYPE_PROTECTION 0x03 -#define I2O_BSA_ASSOC_TYPE_SPARE 0x04 -#define I2O_BSA_ASSOC_TYPE_CACHE 0x05 -#define I2O_BSA_ASSOC_TYPE_SOFTWARE 0x06 - -/* Object 1 Type */ - -#define I2O_BSA_OBJECT_1_CONTROLLER 0x00 -#define I2O_BSA_OBJECT_1_DEVICE 0x01 -#define I2O_BSA_OBJECT_1_BUS_PORT 0x02 -#define I2O_BSA_OBJECT_1_VOLUME_SET 0x03 -#define I2O_BSA_OBJECT_1_PROT_SPACE_EXT 0x04 -#define I2O_BSA_OBJECT_1_AGG_PROT_SPACE_EXT 0x05 -#define I2O_BSA_OBJECT_1_PHYSICAL_EXT 0x06 -#define I2O_BSA_OBJECT_1_AGG_PHYSICAL_EXT 0x07 -#define I2O_BSA_OBJECT_1_REDUNDANCY 0x08 -#define I2O_BSA_OBJECT_1_CACHE 0x09 -#define I2O_BSA_OBJECT_1_SOFTWARE 0x0A - -/* Object 2 Type */ - -#define I2O_BSA_OBJECT_2_CONTROLLER 0x00 -#define I2O_BSA_OBJECT_2_DEVICE 0x01 -#define I2O_BSA_OBJECT_2_BUS_PORT 0x02 -#define I2O_BSA_OBJECT_2_VOLUME_SET 0x03 -#define I2O_BSA_OBJECT_2_PROT_SPACE_EXT 0x04 -#define I2O_BSA_OBJECT_2_AGG_PROT_SPACE_EXT 0x05 -#define I2O_BSA_OBJECT_2_PHYSICAL_EXT 0x06 -#define I2O_BSA_OBJECT_2_AGG_PHYSICAL_EXT 0x07 -#define I2O_BSA_OBJECT_2_REDUNDANCY 0x08 -#define I2O_BSA_OBJECT_2_CACHE 0x09 -#define I2O_BSA_OBJECT_2_SOFTWARE 0x0A - - - - -/* Block Storage Group 0000h - Device Information Parameter Group */ - -typedef struct i2o_bsa_device_info_scalar { - uint8_t DeviceType; - uint8_t NumberOfPaths; - uint16_t PowerState; - uint32_t BlockSize; - uint64_t DeviceCapacity; - uint32_t DeviceCapabilitySupport; - uint32_t DeviceState; -} i2o_bsa_device_info_scalar_t; - - -/* Block Storage Group 0001h - Operational Control Parameter Group */ - -typedef struct i2o_bsa_operational_control_scalar { - uint8_t AutoReassign; - uint8_t ReassignTolerance; - uint8_t RetryAttempts; - uint8_t reserved1; - uint32_t ReassignSize; - uint32_t ExpectedTimeout; - uint32_t RWVTimeout; - uint32_t RWVTimeoutBase; - uint32_t TimeoutBase; - uint32_t OrderedRequestDepth; - uint32_t AtomicWriteSize; -} i2o_bsa_operational_control_scalar_t; - - -/* Block Storage Group 0002h - Power Control Parameter Group */ - -typedef struct i2o_bsa_power_control_scalar { - uint32_t PowerdownTimeout; - uint32_t OnAccess; -} i2o_bsa_power_control_scalar_t; - - -/* Block Storage Group 0003h - Cache Control Parameter Group */ - -typedef struct i2o_bsa_cache_control_scalar { - uint32_t TotalCacheSize; - uint32_t ReadCacheSize; - uint32_t WriteCacheSize; - uint8_t WritePolicy; - uint8_t ReadPolicy; - uint8_t ErrorCorrection; - uint8_t reserved1; /* Note: not in 1.5 spec. */ -} i2o_bsa_cache_control_scalar_t; - - -/* Block Storage Group 0004h - Media Information Parameter Group */ - -typedef struct i2o_bsa_media_info_scalar { - uint64_t Capacity; - uint32_t BlockSize; -} i2o_bsa_media_info_scalar_t; - - -/* Block Storage Group 0005h - Error Log Parameter Group */ - -typedef struct i2o_bsa_error_log_table { - uint16_t ErrorDataIndex; - uint8_t Function; - uint8_t RetryCount; - uint16_t DetailedErrorCode; - uint16_t reserved2; - uint64_t TimeStamp; - uint32_t UserInfo; -} i2o_bsa_error_log_table_t; - - -/* Block Storage Group 0180h - Optional Historical STATS Support/Control */ - -typedef struct i2o_bsa_hist_stats_scalar { - uint8_t StatisticsControl; - uint8_t reserved1; - uint16_t reserved2; - uint32_t StorageStatistics; - uint32_t CacheStatistics; -} i2o_bsa_hist_stats_scalar_t; - - -/* Block Storage Group 0181h - Optional Storage Historical STATS */ - -typedef struct i2o_bsa_storage_hist_stats_scalar { - uint64_t ReadCommands; - uint64_t WriteCommands; - uint8_t DataUnit; - uint8_t reserved1; - uint16_t reserved2; - uint64_t IORange1Read; - uint64_t IORange2Read; - uint64_t IORange3Read; - uint64_t IORange4Read; - uint64_t IORange1Write; - uint64_t IORange2Write; - uint64_t IORange3Write; - uint64_t IORange4Write; - uint64_t NumberSeeks; -} i2o_bsa_storage_hist_stats_scalar_t; - - -/* Block Storage Group 0182h - Optional Cache Historical STATS */ - -typedef struct i2o_bsa_cache_hist_stats_scalar { - uint64_t CacheAccess; - uint64_t CacheHit; - uint64_t PartialCacheHit; - uint64_t HitDataSize; - uint32_t ValidUsage; - uint32_t DirtyUsage; - uint32_t TimeLastFault; - uint32_t LastFaultFailure; -} i2o_bsa_cache_hist_stats_scalar_t; - - -/* Block Storage Group 0200h - Optional Volume Set Information */ - -typedef struct i2o_bsa_volume_info_scalar { - uint8_t Name[64]; - uint64_t TotalStorageCapacity; - uint64_t StripeLength; - uint64_t InterleaveDepth; -} i2o_bsa_volume_info_scalar_t; - - -/* Block Storage Group 0201h - Optional Protected Space Extent */ - -typedef struct i2o_bsa_pro_space_ext_scalar { - uint64_t StartAddress; - uint64_t NumberBlocks; - uint32_t BlockSize; - uint32_t DataStripeGranularity; - uint32_t DataStripeLength; -} i2o_bsa_pro_space_ext_scalar_t; - - -/* Block Storage Group 0202h - Optional Aggregate Protected Space Extent */ - -typedef struct i2o_bsa_agg_prot_space_ext_scalar { - uint64_t NumberBlocks; -} i2o_bsa_agg_prot_space_ext_scalar_t; - - -/* Block Storage Group 0203h - Optional Physical Extent */ - -typedef struct i2o_bsa_phys_ext_scalar { - uint64_t StartAddress; - uint64_t NumberBlocks; - uint32_t BlockSize; - uint32_t GranularityUnit; - uint64_t CheckDataInterleave; - uint64_t CheckData; - uint64_t UserData; -} i2o_bsa_phys_ext_scalar_t; - - -/* Block Storage Group 0204h - Optional Aggregate Physical Extent */ - -typedef struct i2o_bsa_agg_phys_ext_scalar { - uint64_t NumberBlocks; - uint64_t CheckData; -} i2o_bsa_agg_phys_ext_scalar_t; - - -/* Block Storage Group 0205h - Optional Redundancy Table */ - -typedef struct i2o_bsa_redundancy_scalar { - uint8_t RedundancyType; - uint8_t reserved1; /* Note: not in 1.5 spec. */ - uint16_t reserved2; /* Note: not in 1.5 spec. */ -} i2o_bsa_redundancy_scalar_t; - - -/* Block Storage Group 0206h - Optional Component Spares */ - -typedef struct i2o_bsa_component_spares_table { - uint8_t RowNumber; - uint8_t SpareType; - uint8_t ToBeSparedIndex; - uint8_t SparedIndex; - uint8_t SpareFunctioningState; - uint8_t reserved1; /* Note: not in 1.5 spec. */ - uint16_t reserved2; /* Note: not in 1.5 spec. */ -} i2o_bsa_component_spares_table_t; - - -/* Block Storage Group 0207h - Optional Association Table */ - -typedef struct i2o_bsa_association_table { - uint8_t RowNumber; - uint8_t Type; - uint8_t Object1Type; - uint8_t Object1Index; - uint8_t Object2Type; - uint8_t Object2Index; - uint16_t reserved2; /* Note: not in 1.5 spec. */ -} i2o_bsa_association_table_t; - - - -/* I2O BSA Block Storage Event Indicator Assignment */ - -#define I2O_BSA_EVENT_VOLUME_LOAD 0x00000001 -#define I2O_BSA_EVENT_VOLUME_UNLOAD 0x00000002 -#define I2O_BSA_EVENT_VOLUME_UNLOAD_REQUEST 0x00000004 -#define I2O_BSA_EVENT_CAPACITY_CHANGE 0x00000008 -#define I2O_BSA_EVENT_SCSI_SMART 0x00000010 - - - - -/* Block Storage Class Specific Message Definitions */ - - -/* I2O Block Storage Reply Message Frame Template */ - -typedef struct i2o_bsa_reply_message_frame { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint16_t DetailedStatusCode; - uint8_t RetryCount; - uint8_t ReqStatus; -/* ReplyPayload */ -} i2o_bsa_reply_message_frame_t; - - - -/* I2O Block Storage Successful Completion Reply Message Frame */ - -typedef struct i2o_bsa_success_reply_message_frame { - i2o_bsa_reply_message_frame_t BsaReplyFrame; - uint32_t TransferCount; -} i2o_bsa_success_reply_message_frame_t; - - - -/* I2O Block Storage Aborted Operation Reply Message Frame */ - -typedef struct i2o_bsa_abort_reply_message_frame { - i2o_bsa_reply_message_frame_t BsaReplyFrame; -} i2o_bsa_abort_reply_message_frame_t; - - - -/* I2O Block Storage Progress Report Reply Message Frame */ - -typedef struct i2o_bsa_progress_reply_message_frame { - i2o_bsa_reply_message_frame_t BsaReplyFrame; - uint8_t PercentComplete; - uint8_t Reserved[3]; -} i2o_bsa_progress_reply_message_frame_t; - - -/* I2O Block Storage Error Report Reply Message Frame */ - -typedef struct i2o_bsa_error_reply_message_frame { - i2o_bsa_reply_message_frame_t BsaReplyFrame; - uint32_t TransferCount; - uint64_t LogicalByteAddress; -} i2o_bsa_error_reply_message_frame_t; - - - - -/* I2O BSA request message flag definitions */ - -/* I2O BSA Control Flags */ - -typedef uint16_t i2o_bsa_ctl_flags_t; - -#define I2O_BSA_FLAG_PROGRESS_REPORT 0x0080 - -/* I2O BSA Block Read Message Control Flags */ - -typedef uint16_t i2o_bsa_read_flags_t; -#define I2O_BSA_RD_FLAG_DONT_RETRY 0x0001 -#define I2O_BSA_RD_FLAG_SOLO 0x0002 -#define I2O_BSA_RD_FLAG_CACHE_READ 0x0004 -#define I2O_BSA_RD_FLAG_READ_PREFETCH 0x0008 -#define I2O_BSA_RD_FLAG_CACHE_DATA 0x0010 - -/* I2O BSA Block Write Message Control Flags */ - -typedef uint16_t i2o_bsa_write_flags_t; -#define I2O_BSA_WR_FLAG_DONT_RETRY 0x0001 -#define I2O_BSA_WR_FLAG_SOLO 0x0002 -#define I2O_BSA_WR_FLAG_DONT_CACHE 0x0004 -#define I2O_BSA_WR_FLAG_WRITE_THRU 0x0008 -#define I2O_BSA_WR_FLAG_WRITE_TO 0x0010 - -/* I2O BSA Device Reset Message Control Flags */ - -typedef uint16_t i2o_bsa_reset_flags_t; -#define I2O_BSA_FLAG_HARD_RESET 0x0001 - -/* I2O BSA Media Verify Message Control Flags */ - -typedef uint16_t i2o_bsa_verify_flags_t; -/* Progress Report flag definition is valid */ -#define I2O_BSA_ERROR_CORRECTION 0x0040 - - -/* I2O BSA Removeable Media Identifier values */ - -typedef uint32_t i2o_bsa_media_id_t; -#define I2O_BSA_MEDIA_ID_CURRENT_MOUNTED 0xFFFFFFFF - - -/* I2O BSA Removeable Media Load Flags */ - -typedef uint8_t i2o_bsa_load_flags_t; -#define I2O_BSA_LOAD_FLAG_MEDIA_LOCK 0x80 - - -/* I2O BSA Power Management Operation values */ - -typedef uint8_t i2o_bsa_operation_t; -#define I2O_BSA_POWER_MGT_PARTIAL_POWER_UP 0x01 -#define I2O_BSA_POWER_MGT_POWER_UP 0x02 -#define I2O_BSA_POWER_MGT_POWER_UP_LOAD 0x03 -#define I2O_BSA_POWER_MGT_QUIESCE_DEVICE 0x20 -#define I2O_BSA_POWER_MGT_PARTIAL_POWER_DOWN 0x21 -#define I2O_BSA_POWER_MGT_PARTIAL_POWER_DOWN_UNLOAD 0x22 -#define I2O_BSA_POWER_MGT_POWER_DOWN_UNLOAD 0x23 -#define I2O_BSA_POWER_MGT_POWER_DOWN_RETAIN 0x24 - - - -/* I2O BSA Block Read Message Frame */ - -typedef struct i2o_bsa_read_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - i2o_bsa_read_flags_t ControlFlags; - uint8_t TimeMultiplier; - uint8_t FetchAhead; - uint32_t TransferByteCount; - uint64_t LogicalByteAddress; - i2o_sg_element_t SGL; -} i2o_bsa_read_message_t; - - - -/* I2O BSA Block Reassign Message Frame */ - -typedef struct i2o_bsa_block_reassign_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint16_t Reserved1; - uint8_t TimeMultiplier; - uint8_t Reserved2; - i2o_sg_element_t SGL; -} i2o_bsa_block_reassign_message_t; - - - -/* I2O BSA Block Write Message Frame */ - -typedef struct i2o_bsa_write_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - i2o_bsa_write_flags_t ControlFlags; - uint8_t TimeMultiplier; - uint8_t Reserved; - uint32_t TransferByteCount; - uint64_t LogicalByteAddress; - i2o_sg_element_t SGL; -} i2o_bsa_write_message_t; - - - -/* I2O BSA Block Write and Verify Message Frame */ - -typedef struct i2o_bsa_write_verify_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - i2o_bsa_write_flags_t ControlFlags; - uint8_t TimeMultiplier; - uint8_t Reserved; - uint32_t TransferByteCount; - uint64_t LogicalByteAddress; - i2o_sg_element_t SGL; -} i2o_bsa_write_verify_message_t; - - - -/* I2O BSA Cache Flush Message Frame */ - -typedef struct i2o_bsa_cache_flush_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - i2o_bsa_ctl_flags_t ControlFlags; - uint8_t TimeMultiplier; - uint8_t Reserved; -} i2o_bsa_cache_flush_message_t; - - - -/* I2O BSA Device Reset Message Frame */ - -typedef struct _12o_bsa_device_reset_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - i2o_bsa_reset_flags_t ControlFlags; - uint8_t TimeMultiplier; - uint8_t Reserved; -} i2o_bsa_device_reset_message_t; - - - -/* I2O BSA Media Eject for Removeable Media Message Frame */ - -typedef struct i2o_bsa_media_eject_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - i2o_bsa_media_id_t MediaIdentifier; -} i2o_bsa_media_eject_message_t; - - - -/* I2O BSA Media Lock Message Frame */ - -typedef struct i2o_bsa_media_lock_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - i2o_bsa_media_id_t MediaIdentifier; -} i2o_bsa_media_lock_message_t; - - - -/* I2O BSA Media Mount for Removeable Media Message Frame */ - -typedef struct i2o_bsa_media_mount_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - i2o_bsa_media_id_t MediaIdentifier; - i2o_bsa_load_flags_t LoadFlags; - uint8_t Reserved[3]; -} i2o_bsa_media_mount_message_t; - - - -/* I2O BSA Media Unlock Message Frame */ - -typedef struct i2o_bsa_media_unlock_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - i2o_bsa_media_id_t MediaIdentifier; -} i2o_bsa_media_unlock_message_t; - - - -/* I2O BSA Media Verify Message Frame */ - -typedef struct i2o_bsa_media_verify_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - i2o_bsa_verify_flags_t ControlFlags; - uint8_t TimeMultiplier; - uint8_t Reserved; - uint32_t ByteCount; - uint64_t LogicalByteAddress; -} i2o_bsa_media_verify_message_t; - - - -/* I2O BSA Power Management Message Frame */ - -typedef struct i2o_bsa_power_management_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - i2o_bsa_ctl_flags_t ControlFlags; - uint8_t TimeMultiplier; - uint8_t ReplyType; - i2o_bsa_operation_t Operation; -} i2o_bsa_power_management_message_t; - - - -/* I2O BSA Status Check Message Frame */ - -typedef struct i2o_bsa_status_check_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; -} i2o_bsa_status_check_message_t; - - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_I2OMSTOR_H */
--- a/usr/src/uts/common/sys/i2o/i2outil.h Wed Apr 18 03:07:55 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,391 +0,0 @@ -/* - * ********************************************************************* - * All software on this website is made available under the following - * terms and conditions. By downloading this software, you agree to - * abide by these terms and conditions with respect to this software. - * - * I2O SIG All rights reserved. - * - * These header files are provided, pursuant to your I2O SIG membership - * agreement, free of charge on an as-is basis without warranty of any - * kind, either express or implied, including but not limited to, - * implied warranties or merchantability and fitness for a particular - * purpose. I2O SIG does not warrant that this program will meet the - * user's requirements or that the operation of these programs will be - * uninterrupted or error-free. Acceptance and use of this program - * constitutes the user's understanding that he will have no recourse - * to I2O SIG for any actual or consequential damages including, but - * not limited to, loss profits arising out of use or inability to use - * this program. - * - * Member is permitted to create deriavative works to this header-file - * program. However, all copies of the program and its derivative - * works must contain the I2O SIG copyright notice. - * ******************************************************************** - */ - -/* - * ******************************************************************** - * I2OUtil.h -- I2O Utility Class Message defintion file - * - * This file contains information presented in Chapter 6 of the I2O - * Specification. - * ******************************************************************** - */ - -/* - * Copyright (c) 1998 by Sun Microsystems, Inc. - * All rights reserved. - */ - -#ifndef _SYS_I2OUTIL_H -#define _SYS_I2OUTIL_H - -#pragma ident "%W% %E% SMI" - -#ifdef __cplusplus -extern "C" { -#endif - -#define I2OUTIL_REV 1_5_4 /* I2OUtil header file revision string */ - -#include <sys/i2o/i2omsg.h> /* Include the Base Message file */ - -/* - * ******************************************************************** - * NOTES: - * - * Gets, reads, receives, etc. are all even numbered functions. - * Sets, writes, sends, etc. are all odd numbered functions. - * Functions that both send and receive data can be either but an attempt is - * made to use the function number that indicates the greater transfer amount. - * Functions that do not send or receive data use odd function numbers. - * - * Some functions are synonyms like read, receive and send, write. - * - * All common functions will have a code of less than 0x80. - * Unique functions to a class will start at 0x80. - * Executive Functions start at 0xA0. - * - * Utility Message function codes range from 0 - 0x1f - * Base Message function codes range from 0x20 - 0xfe - * Private Message function code is 0xff. - * ******************************************************************** - */ - -/* Utility Message class functions. */ - -#define I2O_UTIL_NOP 0x00 -#define I2O_UTIL_ABORT 0x01 -#define I2O_UTIL_CLAIM 0x09 -#define I2O_UTIL_CLAIM_RELEASE 0x0B -#define I2O_UTIL_CONFIG_DIALOG 0x10 -#define I2O_UTIL_DEVICE_RESERVE 0x0D -#define I2O_UTIL_DEVICE_RELEASE 0x0F -#define I2O_UTIL_EVENT_ACKNOWLEDGE 0x14 -#define I2O_UTIL_EVENT_REGISTER 0x13 -#define I2O_UTIL_LOCK 0x17 -#define I2O_UTIL_LOCK_RELEASE 0x19 -#define I2O_UTIL_PARAMS_GET 0x06 -#define I2O_UTIL_PARAMS_SET 0x05 -#define I2O_UTIL_REPLY_FAULT_NOTIFY 0x15 - -/* ************************************************************************** */ - -/* ABORT Abort type defines. */ - -#define I2O_ABORT_TYPE_EXACT_ABORT 0x00 -#define I2O_ABORT_TYPE_FUNCTION_ABORT 0x01 -#define I2O_ABORT_TYPE_TRANSACTION_ABORT 0x02 -#define I2O_ABORT_TYPE_WILD_ABORT 0x03 -#define I2O_ABORT_TYPE_CLEAN_EXACT_ABORT 0x04 -#define I2O_ABORT_TYPE_CLEAN_FUNCTION_ABORT 0x05 -#define I2O_ABORT_TYPE_CLEAN_TRANSACTION_ABORT 0x06 -#define I2O_ABORT_TYPE_CLEAN_WILD_ABORT 0x07 - -/* UtilAbort Function Message Frame structure. */ - -typedef struct i2o_util_abort_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint16_t reserved; - uint8_t AbortType; - uint8_t FunctionToAbort; - i2o_transaction_context_t TransactionContextToAbort; -} i2o_util_abort_message_t; - -typedef struct i2o_util_abort_reply { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint32_t CountOfAbortedMessages; -} i2o_util_abort_reply_t; - -/* ************************************************************************** */ - -/* Claim Flag defines */ - -#define I2O_CLAIM_FLAGS_EXCLUSIVE 0x0001 /* Reserved */ -#define I2O_CLAIM_FLAGS_RESET_SENSITIVE 0x0002 -#define I2O_CLAIM_FLAGS_STATE_SENSITIVE 0x0004 -#define I2O_CLAIM_FLAGS_CAPACITY_SENSITIVE 0x0008 -#define I2O_CLAIM_FLAGS_PEER_SERVICE_DISABLED 0x0010 -#define I2O_CLAIM_FLAGS_MGMT_SERVICE_DISABLED 0x0020 - -/* Claim Type defines */ - -#define I2O_CLAIM_TYPE_PRIMARY_USER 0x01 -#define I2O_CLAIM_TYPE_AUTHORIZED_USER 0x02 -#define I2O_CLAIM_TYPE_SECONDARY_USER 0x03 -#define I2O_CLAIM_TYPE_MANAGEMENT_USER 0x04 - -/* UtilClaim Function Message Frame structure. */ - -typedef struct i2o_util_claim_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint16_t ClaimFlags; - uint8_t reserved; - uint8_t ClaimType; -} i2o_util_claim_message_t; - -/* ************************************************************************** */ - -/* Claim Release Flag defines */ - -#define I2O_RELEASE_FLAGS_CONDITIONAL 0x0001 - -/* UtilClaimRelease Function Message Frame structure. */ - -typedef struct i2o_util_claim_release_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint16_t ReleaseFlags; - uint8_t reserved; - uint8_t ClaimType; -} i2o_util_claim_release_message_t; - -/* ************************************************************************** */ - -/* UtilConfigDialog Function Message Frame structure */ - -typedef struct i2o_util_config_dialog_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint32_t PageNumber; - i2o_sg_element_t SGL; -} i2o_util_config_dialog_message_t; - -/* ************************************************************************** */ - -/* Event Acknowledge Function Message Frame structure */ - -typedef struct i2o_util_event_ack_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint32_t EventIndicator; - uint32_t EventData[1]; -} i2o_util_event_ack_message_t; - -/* Event Ack Reply structure */ - -typedef struct i2o_util_event_ack_reply { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint32_t EventIndicator; - uint32_t EventData[1]; -} i2o_util_event_ack_reply_t; - -/* ************************************************************************** */ - -/* Event Indicator Mask Flags */ - -#define I2O_EVENT_IND_STATE_CHANGE 0x80000000 -#define I2O_EVENT_IND_GENERAL_WARNING 0x40000000 -#define I2O_EVENT_IND_CONFIGURATION_FLAG 0x20000000 -/* #define I2O_EVENT_IND_RESERVE_RELEASE 0x10000000 */ -#define I2O_EVENT_IND_LOCK_RELEASE 0x10000000 -#define I2O_EVENT_IND_CAPABILITY_CHANGE 0x08000000 -#define I2O_EVENT_IND_DEVICE_RESET 0x04000000 -#define I2O_EVENT_IND_EVENT_MASK_MODIFIED 0x02000000 -#define I2O_EVENT_IND_FIELD_MODIFIED 0x01000000 -#define I2O_EVENT_IND_VENDOR_EVENT 0x00800000 -#define I2O_EVENT_IND_DEVICE_STATE 0x00400000 - -/* Event Data for generic Events */ - -#define I2O_EVENT_STATE_CHANGE_NORMAL 0x00 -#define I2O_EVENT_STATE_CHANGE_SUSPENDED 0x01 -#define I2O_EVENT_STATE_CHANGE_RESTART 0x02 -#define I2O_EVENT_STATE_CHANGE_NA_RECOVER 0x03 -#define I2O_EVENT_STATE_CHANGE_NA_NO_RECOVER 0x04 -#define I2O_EVENT_STATE_CHANGE_QUIESCE_REQUEST 0x05 -#define I2O_EVENT_STATE_CHANGE_FAILED 0x10 -#define I2O_EVENT_STATE_CHANGE_FAULTED 0x11 - -#define I2O_EVENT_GEN_WARNING_NORMAL 0x00 -#define I2O_EVENT_GEN_WARNING_ERROR_THRESHOLD 0x01 -#define I2O_EVENT_GEN_WARNING_MEDIA_FAULT 0x02 - -#define I2O_EVENT_CAPABILITY_OTHER 0x01 -#define I2O_EVENT_CAPABILITY_CHANGED 0x02 - -#define I2O_EVENT_SENSOR_STATE_CHANGED 0x01 - -/* UtilEventRegister Function Message Frame structure */ - -typedef struct i2o_util_event_register_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint32_t EventMask; -} i2o_util_event_register_message_t; - -/* UtilEventRegister Reply structure */ - -typedef struct i2o_util_event_register_reply { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint32_t EventIndicator; - uint32_t EventData[1]; -} i2o_util_event_register_reply_t; - -/* ************************************************************************** */ - -/* UtilLock Function Message Frame structure. */ - -typedef struct i2o_util_lock_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; -} i2o_util_lock_message_t; - -/* ************************************************************************** */ - -/* UtilLockRelease Function Message Frame structure. */ - -typedef struct i2o_util_lock_release_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; -} i2o_util_lock_release_message_t; - -/* ************************************************************************** */ - -/* UtilNOP Function Message Frame structure. */ - -typedef struct i2o_util_nop_message { - i2o_message_frame_t StdMessageFrame; -} i2o_util_nop_message_t; - -/* ************************************************************************** */ - -/* UtilParamsGet Message Frame structure. */ - -typedef struct i2o_util_params_get_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint32_t OperationFlags; - i2o_sg_element_t SGL; -} i2o_util_params_get_message_t; - -/* ************************************************************************** */ - -/* UtilParamsSet Message Frame structure. */ - -typedef struct i2o_util_params_set_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint32_t OperationFlags; - i2o_sg_element_t SGL; -} i2o_util_params_set_message_t; - - -/* ************************************************************************** */ - -/* UtilReplyFaultNotify Message for Message Failure. */ - -#if defined(_BIT_FIELDS_LTOH) && defined(_LITTLE_ENDIAN) - -typedef struct i2o_util_reply_fault_notify_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint8_t LowestVersion; - uint8_t HighestVersion; - uint8_t Severity; - uint8_t FailureCode; - union { - struct { - uint16_t FailingIOP_ID:12; - uint16_t reserved:4; - } s; - uint16_t h1; - } u1; - uint16_t FailingHostUnitID; - uint32_t AgeLimit; -#if I2O_64BIT_CONTEXT - i2o_message_frame_t *OriginalMFA; -#else - i2o_message_frame_t *OriginalMFALowPart; - uint32_t OriginalMFAHighPart; /* Always 0000 */ -#endif -} i2o_util_reply_fault_notify_message_t; - -#define get_i2o_util_FailingIOP_ID(p, hdl) (p)->u1.s.FailingIOP_ID - -#endif - -#if defined(_BIT_FIELDS_HTOL) && defined(_BIG_ENDIAN) - -typedef struct i2o_util_reply_fault_notify_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; - uint8_t LowestVersion; - uint8_t HighestVersion; - uint8_t Severity; - uint8_t FailureCode; - union { - struct { - uint16_t reserved:4; - uint16_t FailingIOP_ID:12; - } s; - uint32_t h1; - } u1; - uint16_t FailingHostUnitID; - uint32_t AgeLimit; -#if I2O_64BIT_CONTEXT - i2o_message_frame_t *OriginalMFA; -#else - i2o_message_frame_t *OriginalMFALowPart; - uint32_t OriginalMFAHighPart; /* Always 0000 */ -#endif -} i2o_util_reply_fault_notify_message_t; - -#define get_i2o_util_FailingIOP_ID(p, hdl) \ - (ddi_get16(hdl, &(p)->u1.h1) & 0xFFF) - -#endif - -/* ************************************************************************** */ - -/* Device Reserve Function Message Frame structure. */ -/* NOTE: This was previously called the Reserve Message */ - -typedef struct i2o_util_device_reserve_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; -} i2o_util_device_reserve_message_t; - -/* ************************************************************************** */ - -/* Device Release Function Message Frame structure. */ -/* NOTE: This was previously called the ReserveRelease Message */ - -typedef struct i2o_util_device_release_message { - i2o_message_frame_t StdMessageFrame; - i2o_transaction_context_t TransactionContext; -} i2o_util_device_release_message_t; - -/* ************************************************************************** */ - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_I2OUTIL_H */
--- a/usr/src/uts/intel/Makefile.intel.shared Wed Apr 18 03:07:55 2007 -0700 +++ b/usr/src/uts/intel/Makefile.intel.shared Wed Apr 18 11:32:14 2007 -0700 @@ -379,11 +379,6 @@ $(CLOSED_BUILD)CLOSED_DRV_KMODS += pcser # -# I2O specific module(s) -# -DRV_KMODS_32 += pci_to_i2o i2o_bs i2o_scsi - -# # SCSI Enclosure Services driver # DRV_KMODS += ses @@ -517,7 +512,6 @@ MISC_KMODS += hidparser MISC_KMODS += hook MISC_KMODS += hpcsvc -MISC_KMODS_32 += i2o_msg MISC_KMODS += ibcm MISC_KMODS += ibdm MISC_KMODS += ibmf
--- a/usr/src/uts/intel/i2o_bs/Makefile Wed Apr 18 03:07:55 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (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 -# -# -# uts/intel/i2o_bs/Makefile -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" -# -# This makefile drives the production of the i2o_bs (I2O BS-OSM) -# driver kernel module. -# -# intel implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = i2o_bs -OBJECTS = $(I2O_BS_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(I2O_BS_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) -CONF_SRCDIR = $(UTSBASE)/common/io/i2o - -# -# Include common rules. -# -include $(UTSBASE)/intel/Makefile.intel - -# -# Define targets -# -ALL_TARGET = $(BINARY) $(SRC_CONFILE) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) - -# -# Overrides -# -DEF_BUILDS = $(DEF_BUILDS32) -ALL_BUILDS = $(ALL_BUILDS32) - -# -# For now, disable these lint checks; maintainers should endeavor -# to investigate and remove these for maximum lint coverage. -# Please do not carry these forward to new Makefiles. -# -LINTTAGS += -erroff=E_SUSPICIOUS_COMPARISON -LINTTAGS += -erroff=E_BAD_PTR_CAST_ALIGN -LINTTAGS += -erroff=E_PTRDIFF_OVERFLOW -LINTTAGS += -erroff=E_ASSIGN_NARROW_CONV - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/intel/Makefile.targ
--- a/usr/src/uts/intel/i2o_msg/Makefile Wed Apr 18 03:07:55 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (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 -# -# -# uts/intel/i2o_msg/Makefile -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" -# -# This file makes the i2o_msg kernel misc module for an intel system -# -# intel architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. -# -# Define the module and object file sets. -# -MODULE = i2o_msg -OBJECTS = $(I2OMSG_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(I2OMSG_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_MISC_DIR)/$(MODULE) - -# -# Include common rules. -# -include $(UTSBASE)/intel/Makefile.intel - -# -# Define targets -# -ALL_TARGET = $(BINARY) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) - -# -# Overrides -# -DEF_BUILDS = $(DEF_BUILDS32) -ALL_BUILDS = $(ALL_BUILDS32) - -# -# For now, disable these lint checks; maintainers should endeavor -# to investigate and remove these for maximum lint coverage. -# Please do not carry these forward to new Makefiles. -# -LINTTAGS += -erroff=E_BAD_PTR_CAST_ALIGN -LINTTAGS += -erroff=E_PTRDIFF_OVERFLOW -LINTTAGS += -erroff=E_ASSIGN_NARROW_CONV - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/intel/Makefile.targ
--- a/usr/src/uts/intel/i2o_scsi/Makefile Wed Apr 18 03:07:55 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (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 -# -# -# uts/intel/i2o_scsi/Makefile -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" -# -# This makefile drives the production of the i2o_scsi (SCSI HBA) -# driver kernel module. -# -# intel implementation architecture dependent -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = i2o_scsi -OBJECTS = $(I2O_SCSI_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(I2O_SCSI_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) -CONF_SRCDIR = $(UTSBASE)/common/io/i2o - -# -# Include common rules. -# -include $(UTSBASE)/intel/Makefile.intel - -# -# Define targets -# -ALL_TARGET = $(BINARY) $(SRC_CONFILE) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) - -# -# Overrides -# -DEF_BUILDS = $(DEF_BUILDS32) -ALL_BUILDS = $(ALL_BUILDS32) - -# -# Override defaults to build a unique, local modstubs.o. -# -MODSTUBS_DIR = $(OBJS_DIR) -CLEANFILES += $(MODSTUBS_O) - -# -# For now, disable these lint checks; maintainers should endeavor -# to investigate and remove these for maximum lint coverage. -# Please do not carry these forward to new Makefiles. -# -LINTTAGS += -erroff=E_BAD_PTR_CAST_ALIGN - -# -# Default build targets. -# -.KEEP_STATE: - -all: $(ALL_DEPS) - -def: $(DEF_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/intel/Makefile.targ -
--- a/usr/src/uts/intel/os/driver_aliases Wed Apr 18 03:07:55 2007 -0700 +++ b/usr/src/uts/intel/os/driver_aliases Wed Apr 18 11:32:14 2007 -0700 @@ -6,7 +6,6 @@ pci_pci "pci1011,1" pci_pci "pci1011,21" pci_pci "pci1014,22" -pci_to_i2o "pciclass,0e0001" kb8042 "pnpPNP,303" mouse8042 "pnpPNP,f03" vgatext "pnpPNP,900"
--- a/usr/src/uts/intel/os/driver_classes Wed Apr 18 03:07:55 2007 -0700 +++ b/usr/src/uts/intel/os/driver_classes Wed Apr 18 11:32:14 2007 -0700 @@ -29,5 +29,3 @@ eisa sysbus pci pci pci_pci pci -pci_to_i2o i2o -i2o_scsi scsi
--- a/usr/src/uts/intel/os/minor_perm Wed Apr 18 03:07:55 2007 -0700 +++ b/usr/src/uts/intel/os/minor_perm Wed Apr 18 11:32:14 2007 -0700 @@ -89,7 +89,6 @@ tnf:tnfctl 0600 root sys tnf:tnfmap 0600 root sys pm:* 0666 root sys -i2o_bs:* 0640 root sys wc:* 0600 root sys poll:* 0666 root sys cpc:shared 0666 root sys
--- a/usr/src/uts/intel/os/name_to_major Wed Apr 18 03:07:55 2007 -0700 +++ b/usr/src/uts/intel/os/name_to_major Wed Apr 18 11:32:14 2007 -0700 @@ -65,9 +65,6 @@ st 129 mscsi 130 pm 131 -pci_to_i2o 132 -i2o_scsi 133 -i2o_bs 134 poll 135 keysock 136 ipsecah 137
--- a/usr/src/uts/intel/pci_to_i2o/Makefile Wed Apr 18 03:07:55 2007 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (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 -# -# -# uts/intel/pci_to_i2o/Makefile -# -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -#ident "%Z%%M% %I% %E% SMI" -# -# This makefile drives the production of the pci_to_i2o nexus driver -# kernel module. -# - -# -# Path to the base of the uts directory tree (usually /usr/src/uts). -# -UTSBASE = ../.. - -# -# Define the module and object file sets. -# -MODULE = pci_to_i2o -OBJECTS = $(PCI_I2ONEXUS_OBJS:%=$(OBJS_DIR)/%) -LINTS = $(PCI_I2ONEXUS_OBJS:%.o=$(LINTS_DIR)/%.ln) -ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE) -CONF_SRCDIR = $(UTSBASE)/common/io/i2o - -# -# Include common rules. -# -include $(UTSBASE)/intel/Makefile.intel - -# -# Define targets -# -ALL_TARGET = $(BINARY) $(SRC_CONFILE) -LINT_TARGET = $(MODULE).lint -INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE) - -# -# Overrides -# -DEF_BUILDS = $(DEF_BUILDS32) -ALL_BUILDS = $(ALL_BUILDS32) - -# -# Override defaults to build a unique, local modstubs.o. -# -MODSTUBS_DIR = $(OBJS_DIR) -CLEANFILES += $(MODSTUBS_O) - -# -# For now, disable these lint checks; maintainers should endeavor -# to investigate and remove these for maximum lint coverage. -# Please do not carry these forward to new Makefiles. -# -LINTTAGS += -erroff=E_SUSPICIOUS_COMPARISON -LINTTAGS += -erroff=E_BAD_PTR_CAST_ALIGN -LINTTAGS += -erroff=E_PTRDIFF_OVERFLOW -LINTTAGS += -erroff=E_ASSIGN_NARROW_CONV - -# -# Default build targets. -# -.KEEP_STATE: - -def: $(DEF_DEPS) - -all: $(ALL_DEPS) - -clean: $(CLEAN_DEPS) - -clobber: $(CLOBBER_DEPS) - -lint: $(LINT_DEPS) - -modlintlib: $(MODLINTLIB_DEPS) - -clean.lint: $(CLEAN_LINT_DEPS) - -install: $(INSTALL_DEPS) - -# -# Include common targets. -# -include $(UTSBASE)/intel/Makefile.targ -
--- a/usr/src/uts/intel/ses/Makefile Wed Apr 18 03:07:55 2007 -0700 +++ b/usr/src/uts/intel/ses/Makefile Wed Apr 18 11:32:14 2007 -0700 @@ -21,13 +21,13 @@ # # uts/intel/ses/Makefile # -# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" # -# This makefile drives the production of the i2o_bs (I2O BS-OSM) -# driver kernel module. +# This makefile drives the production of the ses (SCSI enclosure +# services) driver kernel module. # # intel implementation architecture dependent #