
/*******************************************************************
 * This file is part of the Emulex Linux Device Driver for         *
 * Enterprise Fibre Channel Host Bus Adapters.                     *
 * Refer to the README file included with this package for         *
 * driver version and adapter support.                             *
 * Copyright (C) 2003 Emulex Corporation.                          *
 * www.emulex.com                                                  *
 *                                                                 *
 * This program is free software; you can redistribute it and/or   *
 * modify it under the terms of the GNU General Public License     *
 * as published by the Free Software Foundation; either version 2  *
 * of the License, or (at your option) any later version.          *
 *                                                                 *
 * This program is distributed in the hope that it will be useful, *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of  *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   *
 * GNU General Public License for more details, a copy of which    *
 * can be found in the file COPYING included with this package.    *
 *******************************************************************/

#include "dfc.h"

/*************************************************************************/
/*  Global data structures                                               */
/*************************************************************************/

   int  rc = 0;                         
   int  do_cp = 0;                      

#ifdef DFC_SUBSYSTEM

struct dfc {
   uint32               dfc_init;
   uint32               dfc_pad;
   uchar                dfc_buffer[4096];
   struct dfc_info      dfc_info[MAX_FC_BRDS];
};

_static_ struct dfc dfc;

struct dfc_mem {
   uint32               fc_outsz;
   uint32               fc_filler;
   void               * fc_dataout;
};

extern uint32   fc_dbg_flag;
uint32   fc_out_event = 4;

/* Routine Declaration - Local */
_local_ fc_dev_ctl_t  * dfc_getpdev(struct cmd_input *ci);
_local_ int             dfc_msdelay(fc_dev_ctl_t *p, ulong ms);
_local_ int             dfc_issue_mbox( fc_dev_ctl_t *p, MAILBOX * mb, ulong *ipri);
_local_ DMATCHMAP     * dfc_cmd_data_alloc(fc_dev_ctl_t *p, uchar *inp, ULP_BDE64 *bpl, uint32 size);
_local_ int             dfc_cmd_data_free(fc_dev_ctl_t *p, DMATCHMAP *mlist);
_local_ int             dfc_rsp_data_copy(fc_dev_ctl_t *p, uchar * op, DMATCHMAP *mlist, uint32 size);
_local_ DMATCHMAP     * dfc_fcp_data_alloc(fc_dev_ctl_t *p, ULP_BDE64 *bpl);
_local_ int             dfc_fcp_data_free(fc_dev_ctl_t *p, DMATCHMAP *fcpmp);
_forward_ int           dfc_data_alloc(fc_dev_ctl_t * p_dev_ctl, struct dfc_mem *dm, uint32 size);
_forward_ int          dfc_hba_rnid(fc_dev_ctl_t * p_dev_ctl, struct dfc_mem *dm, struct cmd_input *cip, struct dfccmdinfo *infop, MBUF_INFO *buf_info, ulong ipri);
_forward_ int          dfc_hba_sendmgmt_ct(fc_dev_ctl_t * p_dev_ctl, struct dfc_mem *dm, struct cmd_input *cip, struct dfccmdinfo *infop, ulong ipri);
_forward_ int          dfc_hba_fcpbind(fc_dev_ctl_t * p_dev_ctl, struct dfc_mem *dm, struct cmd_input *cip, struct dfccmdinfo *infop, ulong ipri);
_forward_ int          dfc_hba_targetmapping(fc_dev_ctl_t * p_dev_ctl, struct dfc_mem *dm, struct cmd_input *cip, struct dfccmdinfo *infop, ulong ipri);
_forward_ int          dfc_hba_sendscsi_fcp(fc_dev_ctl_t * p_dev_ctl, struct dfc_mem *dm, struct cmd_input *cip, struct dfccmdinfo *infop, ulong ipri);
_forward_ int          dfc_hba_set_event(fc_dev_ctl_t * p_dev_ctl, struct dfc_mem *dm, struct cmd_input *cip, struct dfccmdinfo *infop, ulong ipri);
_forward_ int           dfc_data_free(fc_dev_ctl_t * p_dev_ctl, struct dfc_mem *dm);
_forward_ uint32        dfc_getLunId(node_t *nodep, uint32 lunIndex);
/* End Routine Declaration - Local */

/*****************************************************************************/
/*
 * NAME:     dfc_ioctl
 *
 * FUNCTION: diagnostic ioctl interface
 *
 * EXECUTION ENVIRONMENT: process only
 *
 * NOTES:
 *
 * CALLED FROM:
 *      dfc_config
 *
 * RETURNS:  
 *      0 - successful
 *      EINVAL - invalid parameter was passed
 *
 */
/*****************************************************************************/
_static_ int
dfc_ioctl(
struct dfccmdinfo *infop,
struct cmd_input *cip)
{
   uint32 outshift;
   int  i, j;                           /* loop index */
   ulong ipri;
   int max;
   FC_BRD_INFO         * binfo;
   uint32              * lptr;
   MBUF_INFO           * buf_info;
   MBUF_INFO           * dmdata_info;
   MBUF_INFO           * mbox_info;
   uchar               * bp;
   uint32 		 incr;
   uint32 		 size;
   uint32		 buf1sz;
   int 			 total_mem;
   uint32 		 offset;
   uint32 		 cnt;
   NODELIST            * nlp;
   node_t              * nodep;
   dvi_t               * dev_ptr;
   void                * ioa;
   fc_dev_ctl_t        * p_dev_ctl;
   iCfgParam           * clp;
   RING                * rp;
   MAILBOX             * mb;
   MATCHMAP            * mm;
   node_t              * node_ptr;
   fcipbuf_t           * fbp;
   struct out_fcp_io   * fp;
   struct out_fcp_devp * dp;
   struct dfc_info     * di;
   struct dfc_mem      * dm;
   HBA_PORTATTRIBUTES  * hp;
   fc_vpd_t            * vp;
   MAILBOX             * mbox;
   MBUF_INFO    bufinfo;

   if ((p_dev_ctl = dfc_getpdev(cip)) == 0) {
      return(EINVAL);
   }

   binfo = &BINFO;
   cnt = binfo->fc_brd_no;
   clp = DD_CTL.p_config[cnt];
   di = &dfc.dfc_info[cip->c_brd];
   buf_info = &bufinfo;

   dmdata_info  = &bufinfo;
   dmdata_info->virt = 0;
   dmdata_info->phys = 0;
   dmdata_info->flags  = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
   dmdata_info->align = sizeof(void *);
   dmdata_info->size = sizeof(* dm);
   dmdata_info->dma_handle = 0;
   fc_malloc(p_dev_ctl, dmdata_info);
   if (buf_info->virt == NULL) {
      return (ENOMEM);
   }
   dm = (struct dfc_mem *)dmdata_info->virt;
   fc_bzero((void *)dm, sizeof(struct dfc_mem));
   
   mbox_info = &bufinfo;
   mbox_info->virt = 0;
   mbox_info->phys = 0;
   mbox_info->flags  = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
   mbox_info->align = sizeof(void *);
   mbox_info->size = sizeof(* mbox);
   mbox_info->dma_handle = 0;
   fc_malloc(p_dev_ctl, mbox_info);
   if (mbox_info->virt == NULL) {
      return (ENOMEM);
   }
   mbox = (MAILBOX *)mbox_info->virt;


   /* dfc_ioctl entry */
   
   fc_log_printf_msg_vargs( binfo->fc_brd_no,
          &fc_msgBlk0400,                   /* ptr to msg structure */
           fc_mes0400,                      /* ptr to msg */
            fc_msgBlk0400.msgPreambleStr,   /* begin varargs */
             infop->c_cmd,
              (uint32)((ulong)cip->c_arg1),
               (uint32)((ulong)cip->c_arg2),
                infop->c_outsz);            /* end varargs */

   outshift = 0;
   if(infop->c_outsz) {
      if(infop->c_outsz <= (64 * 1024))
         total_mem = infop->c_outsz;
      else
         total_mem = 64 * 1024; 
      if(dfc_data_alloc(p_dev_ctl, dm, total_mem)) {
         return(ENOMEM);
      }
   }
   else {
      /* Allocate memory for ioctl data */
      if(dfc_data_alloc(p_dev_ctl, dm, 4096)) {
         return(ENOMEM);
      }
      total_mem = 4096;
   }

   /* Make sure driver instance is attached */
   if(p_dev_ctl != DD_CTL.p_dev[cnt]) {
      return(ENODEV);
   }
   ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
   di->fc_refcnt++;


   switch (infop->c_cmd) {
   /* Diagnostic Interface Library Support */

   case C_WRITE_PCI:
      offset = (uint32)((ulong)cip->c_arg1);
      if (!(binfo->fc_flag & FC_OFFLINE_MODE)) {
         rc = EPERM;
         break;
      }
      if (offset > 255) {
         rc = ERANGE;
         break;
      }
      cnt = (uint32)((ulong)cip->c_arg2);
      if ((cnt + offset) > 256) {
         rc = ERANGE;
         break;
      }

      dfc_unlock_enable(ipri, &CMD_LOCK);
      if (fc_copyin((uchar *)infop->c_dataout, (uchar *)dfc.dfc_buffer, (ulong)cnt)) {
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         rc = EIO;
         break;
      }
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
      rc = fc_writepci(di, offset, (char *)dfc.dfc_buffer, (cnt >> 2));
      break;

   case C_READ_PCI:
      offset = (uint32)((ulong)cip->c_arg1);
      if (offset > 255) {
         rc = ERANGE;
         break;
      }
      cnt = (uint32)((ulong)cip->c_arg2);
      if ((cnt + offset) > 256) {
         rc = ERANGE;
         break;
      }
      rc = fc_readpci(di, offset, (char *)dm->fc_dataout, (cnt >> 2));
      break;

   case C_WRITE_MEM:
      offset = (uint32)((ulong)cip->c_arg1);
      if (!(binfo->fc_flag & FC_OFFLINE_MODE)) {
         if (offset != 256) {
            rc = EPERM;
            break;
         }
         if (cnt > 128) {
            rc = EPERM;
            break;
         }
      }
      if (offset >= 4096) {
         rc = ERANGE;
         break;
      }
      cnt = (uint32)((ulong)cip->c_arg2);
      if ((cnt + offset) > 4096) {
         rc = ERANGE;
         break;
      }

      dfc_unlock_enable(ipri, &CMD_LOCK);
      if (fc_copyin((uchar *)infop->c_dataout, (uchar *)dfc.dfc_buffer, (ulong)cnt)) {
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         rc = EIO;
         break;
      }
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

      binfo = &BINFO;
      if ((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE))) {
         fc_pcimem_bcopy((uint32 * )dfc.dfc_buffer,
             (uint32 * )(((char *)(binfo->fc_slim2.virt)) + offset), cnt);
      } else {
         ioa = (void *)FC_MAP_MEM(&di->fc_iomap_mem);  /* map in slim */
         WRITE_SLIM_COPY(binfo, (uint32 * )dfc.dfc_buffer,
             (volatile uint32 * )((volatile char *)ioa + offset),
             (cnt / sizeof(uint32)));
         FC_UNMAP_MEMIO(ioa);
      }

      break;

   case C_READ_MEM:
      offset = (uint32)((ulong)cip->c_arg1);
      if (offset >= 4096) {
         rc = ERANGE;
         break;
      }
      cnt = (uint32)((ulong)cip->c_arg2);
      if ((cnt + offset) > 4096) {
         rc = ERANGE;
         break;
      }

      binfo = &BINFO;
      if ((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE))) {
         fc_pcimem_bcopy((uint32 * )(((char *)(binfo->fc_slim2.virt)) + offset), 
             (uint32 * )dm->fc_dataout, cnt);
      } else {
         ioa = (void *)FC_MAP_MEM(&di->fc_iomap_mem);  /* map in slim */
         READ_SLIM_COPY(binfo, (uint32 * )dm->fc_dataout,
             (volatile uint32 * )((volatile char *)ioa + offset),
             (cnt / sizeof(uint32)));
         FC_UNMAP_MEMIO(ioa);
      }
      break;

   case C_WRITE_CTLREG:
      offset = (uint32)((ulong)cip->c_arg1);
      if (!(binfo->fc_flag & FC_OFFLINE_MODE)) {
         rc = EPERM;
         break;
      }
      if (offset > 255) {
         rc = ERANGE;
         break;
      }
      incr = (uint32)((ulong)cip->c_arg2);
      ioa = (void *)FC_MAP_IO(&di->fc_iomap_io);  /* map in io registers */
      WRITE_CSR_REG(binfo,
          ((volatile uint32 * )((volatile char *)ioa + (offset))), incr);
      FC_UNMAP_MEMIO(ioa);

      break;

   case C_READ_CTLREG:
      offset = (uint32)((ulong)cip->c_arg1);
      if (offset > 255) {
         rc = ERANGE;
         break;
      }
      ioa = (void *)FC_MAP_IO(&di->fc_iomap_io);  /* map in io registers */
      incr = READ_CSR_REG(binfo,
          ((volatile uint32 * )((volatile char *)ioa + (offset))));
      FC_UNMAP_MEMIO(ioa);
      *((uint32 * )dm->fc_dataout) = incr;
      break;

   case C_INITBRDS:
      dfc_unlock_enable(ipri, &CMD_LOCK);
      if (fc_copyin((uchar*)infop->c_dataout, (uchar*)&di->fc_ba, sizeof(brdinfo))) {
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         rc = EIO;
         break;
      }
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

      if (fc_initpci(di, p_dev_ctl)) {
         rc = EIO;
         break;
      }
      if (binfo->fc_flag & FC_OFFLINE_MODE)
         di->fc_ba.a_offmask |= OFFDI_OFFLINE;

      fc_bcopy((uchar * ) & di->fc_ba, dm->fc_dataout, sizeof(brdinfo));
      infop->c_outsz = sizeof(brdinfo);
      break;

   case C_SETDIAG:
      dfc_unlock_enable(ipri, &CMD_LOCK);
      offset = (uint32)((ulong)cip->c_arg1);
      switch (offset) {
      case DDI_ONDI:
         if (fc_diag_state == DDI_OFFDI) {
            fc_online(0);
         }
         *((uint32 * )(dm->fc_dataout)) = fc_diag_state;
         break;
      case DDI_OFFDI:
         if (fc_diag_state == DDI_ONDI) {
            fc_offline(0);
         }
         *((uint32 * )(dm->fc_dataout)) = fc_diag_state;
         break;
      case DDI_SHOW:
         *((uint32 * )(dm->fc_dataout)) = fc_diag_state;
         break;
      case DDI_BRD_ONDI:
         if (binfo->fc_flag & FC_OFFLINE_MODE) {
            fc_online(p_dev_ctl);
         }
         *((uint32 * )(dm->fc_dataout)) = DDI_ONDI;
         break;
      case DDI_BRD_OFFDI:
         if (!(binfo->fc_flag & FC_OFFLINE_MODE)) {
            fc_offline(p_dev_ctl);
         }
         *((uint32 * )(dm->fc_dataout)) = DDI_OFFDI;
         break;
      case DDI_BRD_SHOW:
         if (binfo->fc_flag & FC_OFFLINE_MODE) {
            *((uint32 * )(dm->fc_dataout)) = DDI_OFFDI;
         }
         else {
            *((uint32 * )(dm->fc_dataout)) = DDI_ONDI;
         }
         break;
      default:
         rc = ERANGE;
         break;
      }
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
      break;

   case C_LIP:
      binfo = &BINFO;
      mb = (MAILBOX * )mbox;
      fc_bzero((void *)mb, sizeof(MAILBOX));
      
      if ((binfo->fc_ffstate == FC_READY) && (binfo->fc_process_LA)) {
         /* Turn off link attentions */
         binfo->fc_process_LA = 0;
         ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io);  /* map in io registers */
         offset = READ_CSR_REG(binfo, FC_HC_REG(binfo, ioa));
         offset &= ~HC_LAINT_ENA;
         WRITE_CSR_REG(binfo, FC_HC_REG(binfo, ioa), offset);
         FC_UNMAP_MEMIO(ioa);

         switch (clp[CFG_TOPOLOGY].a_current) {
            case FLAGS_TOPOLOGY_MODE_LOOP_PT:
               mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
               mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER;
               break;
            case FLAGS_TOPOLOGY_MODE_PT_PT:
               mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
               break;
            case FLAGS_TOPOLOGY_MODE_LOOP:
               mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
               break;
            case FLAGS_TOPOLOGY_MODE_PT_LOOP:
               mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
               mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER;
               break;
         }

         vp = &VPD;
         if (binfo->fc_flag & FC_2G_CAPABLE) {
            if ((vp->rev.feaLevelHigh >= 0x02) &&
               (clp[CFG_LINK_SPEED].a_current > 0)) {
               mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED;
               mb->un.varInitLnk.link_speed = clp[CFG_LINK_SPEED].a_current;
            }
         }
         mb->mbxCommand = MBX_INIT_LINK;
         mb->mbxOwner = OWN_HOST;
         goto mbxbegin;
      }
      mb->mbxStatus = MBXERR_ERROR;
      fc_bcopy((char *) & mb->mbxStatus, dm->fc_dataout, sizeof(ushort));
      break;

   case C_FAILIO:
      {
      uint32 tgt;
      uint32 lun;
      uint32 dev_index;

      binfo = &BINFO;
      i   = (uint32)((ulong)cip->c_arg1);
      tgt = (uint32)((ulong)cip->c_arg2);
      lun = (uint32)((ulong)cip->c_arg3);
      switch(i) {
      case 1:
         fc_failio(p_dev_ctl);
         break;
      case 2:  /* stop */
         dev_index = INDEX(0, tgt);
         dev_ptr = fc_find_lun(binfo, dev_index, lun);
         if(dev_ptr == 0) {
            rc = ERANGE;
            goto out;
         }
         dev_ptr->stop_send_io = 1;
         break;
      case 3:  /* start */
         dev_index = INDEX(0, tgt);
         dev_ptr = fc_find_lun(binfo, dev_index, lun);
         if(dev_ptr == 0) {
            rc = ERANGE;
            goto out;
         }
         if(dev_ptr->stop_send_io == 1) {
            dev_ptr->stop_send_io = 0;
            fc_restart_device(dev_ptr);
         }
         break;
      }
      break;
      }

   case C_RSTQDEPTH:
      fc_reset_dev_q_depth(p_dev_ctl);
      break;

   case C_OUTFCPIO:
      {
      max = (infop->c_outsz / sizeof(struct out_fcp_devp)) - 1;

      binfo = &BINFO;
      fp = (struct out_fcp_io *)dm->fc_dataout;
      dp = (struct out_fcp_devp *)((uchar *)fp + sizeof(struct out_fcp_io));
      rp = &binfo->fc_ring[FC_FCP_RING];
      fp->tx_head = rp->fc_tx.q_first;
      fp->tx_tail = rp->fc_tx.q_last;
      fp->txp_head = rp->fc_txp.q_first;
      fp->txp_tail = rp->fc_txp.q_last;
      fp->tx_count = rp->fc_tx.q_cnt;
      fp->txp_count = rp->fc_txp.q_cnt;
      fp->timeout_head = p_dev_ctl->timeout_head;
      fp->timeout_count = p_dev_ctl->timeout_count;
      fp->devp_count = 0;
      for (i = 0; i < MAX_FC_TARGETS; i++) {
         if ((node_ptr = binfo->device_queue_hash[i].node_ptr) != NULL) {
            for (dev_ptr = node_ptr->lunlist; dev_ptr != NULL; 
               dev_ptr = dev_ptr->next) {
               if(fp->devp_count++ >= max)
                  goto outio;
               dp->target = dev_ptr->nodep->scsi_id;
               dp->lun = (ushort)(dev_ptr->lun_id);
               dp->standby_queue_head = dev_ptr->standby_queue_head;
               dp->standby_queue_tail = dev_ptr->standby_queue_tail;
               dp->standby_count = dev_ptr->standby_count;
               dp->pend_head = dev_ptr->pend_head;
               dp->pend_tail = dev_ptr->pend_tail;
               dp->pend_count = dev_ptr->pend_count;
               dp->clear_head = dev_ptr->clear_head;
               dp->clear_count = dev_ptr->clear_count;
               dp++;
            }
         }
      }
outio:
      infop->c_outsz = (sizeof(struct out_fcp_io) +
         (fp->devp_count * sizeof(struct out_fcp_devp)));
      }
      break;

   case C_HBA_SEND_SCSI:
   case C_HBA_SEND_FCP:
      ipri = dfc_hba_sendscsi_fcp(p_dev_ctl, dm, cip, infop, ipri);
      break;

   case C_SEND_ELS:
      {
      uint32 did;
      uint32 opcode;

      binfo = &BINFO;
      did    = (uint32)((ulong)cip->c_arg1);
      opcode = (uint32)((ulong)cip->c_arg2);
      did = (did & Mask_DID);

      if(((nlp = fc_findnode_odid(binfo, NLP_SEARCH_ALL, did))) == 0) { 
         if((nlp = (NODELIST *)fc_mem_get(binfo, MEM_NLP))) {
            fc_bzero((void *)nlp, sizeof(NODELIST));
            nlp->sync = binfo->fc_sync;
            nlp->capabilities = binfo->fc_capabilities;
            nlp->nlp_DID = did;
            nlp->nlp_state = NLP_LIMBO;
            fc_nlp_bind(binfo, nlp);
         }
         else {
            rc = ENOMEM;
            break;
         }
      }

      fc_els_cmd(binfo, opcode, (void *)((ulong)did), (uint32)0, (ushort)0, nlp);
      }
      break;

   case C_SEND_MGMT_RSP:
      {
      ULP_BDE64     * bpl;
      MATCHMAP      * bmp;
      DMATCHMAP     * indmp;
      uint32          tag;

      tag = (uint32)cip->c_flag;  /* XRI for XMIT_SEQUENCE */
      buf1sz = (uint32)((ulong)cip->c_arg2);

      if((buf1sz == 0) ||
         (buf1sz > (80 * 4096))) {
         rc = ERANGE;
         goto out;
      }

      /* Allocate buffer for Buffer ptr list */
      if ((bmp = (MATCHMAP * )fc_mem_get(binfo, MEM_BPL)) == 0) {
         rc = ENOMEM;
         goto out;
      }
      bpl = (ULP_BDE64 * )bmp->virt;
      dfc_unlock_enable(ipri, &CMD_LOCK);

      if((indmp = dfc_cmd_data_alloc(p_dev_ctl, (uchar *)cip->c_arg1, bpl, buf1sz)) == 0) {
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         fc_mem_put(binfo, MEM_BPL, (uchar * )bmp);
         rc = ENOMEM;
         goto out;
      }
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
      if((rc=fc_issue_ct_rsp(binfo, tag, bmp, indmp))) {
         if(rc == ENODEV)
            rc = EACCES;
         goto xmout1;
      }

      j = 0;
      dfc_unlock_enable(ipri, &CMD_LOCK);
      dfc_msdelay(p_dev_ctl, 1);
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

      /* Wait for CT request to complete or timeout */
      while(indmp->dfc_flag == 0) {
         dfc_unlock_enable(ipri, &CMD_LOCK);
         dfc_msdelay(p_dev_ctl, 50);
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         if(j >= 600) {  
            indmp->dfc_flag = -1;
            break;
         }
         j++;
      }

      j = indmp->dfc_flag;
      if(j == -1) {
         rc = ETIMEDOUT;
      }

xmout1:
      dfc_unlock_enable(ipri, &CMD_LOCK);
      dfc_cmd_data_free(p_dev_ctl, indmp);
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
      fc_mem_put(binfo, MEM_BPL, (uchar * )bmp);
      }
      break;

   case C_SEND_MGMT_CMD:
   case C_CT:
     ipri = dfc_hba_sendmgmt_ct(p_dev_ctl, dm, cip, infop, ipri);
     break;

   case C_MBOX:
      binfo = &BINFO;
      mb = (MAILBOX * )mbox;

      dfc_unlock_enable(ipri, &CMD_LOCK);
      if (fc_copyin((uchar *)cip->c_arg1, (uchar *)mb,
          MAILBOX_CMD_WSIZE * sizeof(uint32))) {
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         rc = EIO;
         goto out;
      }
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

mbxbegin:

      cnt = 0;
      while ((binfo->fc_mbox_active) || (di->fc_flag & DFC_MBOX_ACTIVE)) {
         dfc_unlock_enable(ipri, &CMD_LOCK);
         dfc_msdelay(p_dev_ctl, 5);
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         if(cnt++ == 200)  
            break;
      }

      if (cnt >= 200) {
         mb->mbxStatus = MBXERR_ERROR;
      }
      else {
         binfo->fc_mbox_active = 2;
#ifdef _LP64
         if((mb->mbxCommand == MBX_READ_SPARM) ||
         (mb->mbxCommand == MBX_READ_RPI) ||
         (mb->mbxCommand == MBX_REG_LOGIN) ||
         (mb->mbxCommand == MBX_READ_LA)) {
             mb->mbxStatus = MBXERR_ERROR;
             rc = ENODEV;
             binfo->fc_mbox_active = 0;
             goto mbout;
         }
#endif
         lptr = 0;
         size = 0;
         switch (mb->mbxCommand) {
         /* Offline only */
         case MBX_WRITE_NV:
         case MBX_INIT_LINK:
         case MBX_DOWN_LINK:
         case MBX_CONFIG_LINK:
         case MBX_PART_SLIM:
         case MBX_CONFIG_RING:
         case MBX_RESET_RING:
         case MBX_UNREG_LOGIN:
         case MBX_CLEAR_LA:
         case MBX_DUMP_CONTEXT:
         case MBX_RUN_DIAGS:
         case MBX_RESTART:
         case MBX_FLASH_WR_ULA:
         case MBX_SET_MASK:
         case MBX_SET_SLIM:
         case MBX_SET_DEBUG:
            if (!(binfo->fc_flag & FC_OFFLINE_MODE)) {
               if (infop->c_cmd != C_LIP) {
                  mb->mbxStatus = MBXERR_ERROR;
                  binfo->fc_mbox_active = 0;
                  goto mbout;
               }
            }
            break;

         /* Online / Offline */
         case MBX_LOAD_SM:
         case MBX_READ_NV:
         case MBX_READ_CONFIG:
         case MBX_READ_RCONFIG:
         case MBX_READ_STATUS:
         case MBX_READ_XRI:
         case MBX_READ_REV:
         case MBX_READ_LNK_STAT:
         case MBX_DUMP_MEMORY:
         case MBX_DOWN_LOAD:
         case MBX_UPDATE_CFG:
         case MBX_LOAD_AREA:
         case MBX_LOAD_EXP_ROM:
            break;

         /* Offline only - with DMA */
         case MBX_REG_LOGIN:
            if (!(binfo->fc_flag & FC_OFFLINE_MODE)) {
               mb->mbxStatus = MBXERR_ERROR;
               binfo->fc_mbox_active = 0;
               goto mbout;
            }
            lptr = (uint32 * )((ulong)mb->un.varRegLogin.un.sp.bdeAddress);
            size = (int)mb->un.varRegLogin.un.sp.bdeSize;
            if (lptr) {
               buf_info->virt = (void * )dfc.dfc_buffer;
               buf_info->flags = (FC_MBUF_PHYSONLY | FC_MBUF_DMA |
                                  FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
               buf_info->align = DMA_READ;
               buf_info->size = sizeof(SERV_PARM);
               buf_info->dma_handle = 0;

               dfc_unlock_enable(ipri, &CMD_LOCK);
               fc_malloc(p_dev_ctl, buf_info);
               ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

               if (buf_info->phys == NULL) {
                  mb->mbxStatus = MBXERR_ERROR; 
                  binfo->fc_mbox_active = 0;
                  goto mbout;
               }
               mb->un.varRegLogin.un.sp.bdeAddress =
                 (uint32)putPaddrLow(buf_info->phys);
            }
            break;
         case MBX_RUN_BIU_DIAG:
            if (!(binfo->fc_flag & FC_OFFLINE_MODE)) {
               mb->mbxStatus = MBXERR_ERROR;
               binfo->fc_mbox_active = 0;
               goto mbout;
            }
            mb->mbxStatus = MBXERR_ERROR; 
            binfo->fc_mbox_active = 0;
            goto mbout;

         /* Online / Offline - with DMA */
         case MBX_READ_SPARM64:
            if (!((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE)))) {
               mb->mbxStatus = MBXERR_ERROR;
               binfo->fc_mbox_active = 0;
               goto mbout;
            }
         case MBX_READ_SPARM:
            if ((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE))) {
               if (mb->mbxCommand == MBX_READ_SPARM) {
                  mb->mbxStatus = MBXERR_ERROR;
                  binfo->fc_mbox_active = 0;
                  goto mbout;
               }
               lptr = (uint32 * )getPaddr(mb->un.varRdSparm.un.sp64.addrHigh,
                                          mb->un.varRdSparm.un.sp64.addrLow);
               size = (int)mb->un.varRdSparm.un.sp64.tus.f.bdeSize;
            } else {
               lptr = (uint32 * )((ulong)mb->un.varRdSparm.un.sp.bdeAddress);
               size = (int)mb->un.varRdSparm.un.sp.bdeSize;
            }
            if (lptr) {
               buf_info->virt = (void * )dfc.dfc_buffer;
               buf_info->flags = (FC_MBUF_PHYSONLY | FC_MBUF_DMA |
                                  FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
               buf_info->align = DMA_READ;
               buf_info->size = sizeof(SERV_PARM);
               buf_info->dma_handle = 0;
               buf_info->phys = 0;

               dfc_unlock_enable(ipri, &CMD_LOCK);
               fc_malloc(p_dev_ctl, buf_info);
               ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

               if (buf_info->phys == NULL) {
                  mb->mbxStatus = MBXERR_ERROR; 
                  binfo->fc_mbox_active = 0;
                  goto mbout;
               }
               if ((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE))) {
                  mb->un.varRdSparm.un.sp64.addrHigh =
                     (uint32)putPaddrHigh(buf_info->phys);
                  mb->un.varRdSparm.un.sp64.addrLow =
                     (uint32)putPaddrLow(buf_info->phys);
               }
               else
                  mb->un.varRdSparm.un.sp.bdeAddress = 
                     (uint32)putPaddrLow(buf_info->phys);
            }
            break;
         case MBX_READ_RPI64:
            if (!((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE)))) {
               mb->mbxStatus = MBXERR_ERROR;
               binfo->fc_mbox_active = 0;
               goto mbout;
            }
         case MBX_READ_RPI:
            if ((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE))) {
               if (mb->mbxCommand == MBX_READ_RPI) {
                  mb->mbxStatus = MBXERR_ERROR;
                  binfo->fc_mbox_active = 0;
                  goto mbout;
               }
               lptr = (uint32 * )getPaddr(mb->un.varRdRPI.un.sp64.addrHigh,
                                          mb->un.varRdRPI.un.sp64.addrLow);
               size = (int)mb->un.varRdRPI.un.sp64.tus.f.bdeSize;
            } else {
               lptr = (uint32 * )((ulong)mb->un.varRdRPI.un.sp.bdeAddress);
               size = (int)mb->un.varRdRPI.un.sp.bdeSize;
            }
            if (lptr) {
               buf_info->virt = (void * )dfc.dfc_buffer;
               buf_info->flags = (FC_MBUF_PHYSONLY | FC_MBUF_DMA |
                                  FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
               buf_info->align = DMA_READ;
               buf_info->size = sizeof(SERV_PARM);
               buf_info->dma_handle = 0;

               dfc_unlock_enable(ipri, &CMD_LOCK);
               fc_malloc(p_dev_ctl, buf_info);
               ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

               if (buf_info->phys == NULL) {
                  mb->mbxStatus = MBXERR_ERROR; 
                  binfo->fc_mbox_active = 0;
                  goto mbout;
               }
               if ((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE))) {
                  mb->un.varRdRPI.un.sp64.addrHigh =
                    (uint32)putPaddrHigh(buf_info->phys);
                  mb->un.varRdRPI.un.sp64.addrLow =
                    (uint32)putPaddrLow(buf_info->phys);
               }
               else
                  mb->un.varRdRPI.un.sp.bdeAddress =
                    (uint32)putPaddrLow(buf_info->phys);
            }
            break;
         case MBX_READ_LA:
            if (!(binfo->fc_flag & FC_OFFLINE_MODE)) {
               mb->mbxStatus = MBXERR_ERROR;
               binfo->fc_mbox_active = 0;
               goto mbout;
            }
            lptr = (uint32 * )((ulong)mb->un.varReadLA.un.lilpBde.bdeAddress);
            size = (int)mb->un.varReadLA.un.lilpBde.bdeSize;
            if (lptr) {
               buf_info->virt = (void * )dfc.dfc_buffer;
               buf_info->flags = (FC_MBUF_PHYSONLY | FC_MBUF_DMA |
                                  FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
               buf_info->align = DMA_READ;
               buf_info->size = 128;
               buf_info->dma_handle = 0;

               dfc_unlock_enable(ipri, &CMD_LOCK);
               fc_malloc(p_dev_ctl, buf_info);
               ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

               if (buf_info->phys == NULL) {
                  mb->mbxStatus = MBXERR_ERROR; 
                  binfo->fc_mbox_active = 0;
                  goto mbout;
               }
               mb->un.varReadLA.un.lilpBde.bdeAddress =
                    (uint32)putPaddrLow(buf_info->phys);
            }
            break;

         case MBX_CONFIG_PORT:
         case MBX_REG_LOGIN64:
         case MBX_READ_LA64:
            mb->mbxStatus = MBXERR_ERROR;
            binfo->fc_mbox_active = 0;
            goto mbout;

         default:
            if (!(binfo->fc_flag & FC_OFFLINE_MODE)) {
               mb->mbxStatus = MBXERR_ERROR;
               binfo->fc_mbox_active = 0;
               goto mbout;
            }
            break;
         }

         binfo->fc_mbox_active = 0;
         if(dfc_issue_mbox(p_dev_ctl, mb, &ipri))
            goto mbout;

         if (lptr) {
            buf_info->virt = 0;
            buf_info->flags = (FC_MBUF_PHYSONLY | FC_MBUF_DMA |
                               FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
            buf_info->dma_handle = 0;
            switch (mb->mbxCommand) {
            case MBX_REG_LOGIN:
               buf_info->phys = (uint32 * )
                  ((ulong)mb->un.varRegLogin.un.sp.bdeAddress);
               buf_info->size = sizeof(SERV_PARM);
               break;

            case MBX_READ_SPARM:
               buf_info->phys = (uint32 * )
                  ((ulong)mb->un.varRdSparm.un.sp.bdeAddress);
               buf_info->size = sizeof(SERV_PARM);
               break;

            case MBX_READ_RPI:
               buf_info->phys = (uint32 * )
                  ((ulong)mb->un.varRdRPI.un.sp.bdeAddress);
               buf_info->size = sizeof(SERV_PARM);
               break;

            case MBX_READ_LA:
               buf_info->phys = (uint32 * )
                  ((ulong)mb->un.varReadLA.un.lilpBde.bdeAddress);
               buf_info->size = 128;
               break;
            }

            dfc_unlock_enable(ipri, &CMD_LOCK);
            fc_free(p_dev_ctl, buf_info);

            if ((fc_copyout((uchar *)dfc.dfc_buffer, (uchar *)lptr, (ulong)size))) {
               rc = EIO;
            }
            ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         }
      }

mbout:
      if (infop->c_cmd == C_LIP) {
         /* Turn on Link Attention interrupts */
         binfo->fc_process_LA = 1;
         ioa = (void *)FC_MAP_IO(&binfo->fc_iomap_io);  /* map in io registers */
         offset = READ_CSR_REG(binfo, FC_HC_REG(binfo, ioa));
         offset |= HC_LAINT_ENA;
         WRITE_CSR_REG(binfo, FC_HC_REG(binfo, ioa), offset);
         FC_UNMAP_MEMIO(ioa);
      }

      if (infop->c_cmd == C_LIP)
         fc_bcopy((char *) & mb->mbxStatus, dm->fc_dataout, sizeof(ushort));
      else
         fc_bcopy((char *)mb, dm->fc_dataout, MAILBOX_CMD_WSIZE * sizeof(uint32));
      break;


   case C_DISPLAY_PCI_ALL:

      if ((rc = fc_readpci(di, 0, (char *)dm->fc_dataout, 64)))
         break;
      break;

   case C_SET:
      if(cip->c_iocb == 0) {
         bp = binfo->fc_portname.IEEE;
      }
      else {
         cnt = 0;
         bp = 0;
         nlp = binfo->fc_nlpunmap_start;
         if(nlp == (NODELIST *)&binfo->fc_nlpunmap_start)
            nlp = binfo->fc_nlpmap_start;
         while(nlp != (NODELIST *)&binfo->fc_nlpmap_start) {
            if((int)cnt == cip->c_iocb-1) {
               if ((nlp->nlp_type & NLP_IP_NODE) && (nlp->nlp_Rpi) &&
                  (nlp->nlp_Xri)) {
                  bp = nlp->nlp_nodename.IEEE;
               }
               else {
                  bp = binfo->fc_portname.IEEE;
               }
               break;
            }
            cnt++;
            nlp = (NODELIST *)nlp->nlp_listp_next;
            if(nlp == (NODELIST *)&binfo->fc_nlpunmap_start)
               nlp = binfo->fc_nlpmap_start;
         }
      }
      break;

   case C_WRITE_HC:
      incr = (uint32)((ulong)cip->c_arg1);
      ioa = (void *)FC_MAP_IO(&di->fc_iomap_io);  /* map in io registers */
      WRITE_CSR_REG(binfo,
          ((volatile uint32 * )((volatile char *)ioa + (sizeof(uint32) * HC_REG_OFFSET))), incr);
      FC_UNMAP_MEMIO(ioa);
   case C_READ_HC:
      ioa = (void *)FC_MAP_IO(&di->fc_iomap_io);  /* map in io registers */
      offset  = READ_CSR_REG(binfo, FC_HC_REG(binfo, ioa));
      FC_UNMAP_MEMIO(ioa);

      *((uint32 * )dm->fc_dataout) = offset;
      break;

   case C_WRITE_HS:
      incr = (uint32)((ulong)cip->c_arg1);
      ioa = (void *)FC_MAP_IO(&di->fc_iomap_io);  /* map in io registers */
      WRITE_CSR_REG(binfo,
          ((volatile uint32 * )((volatile char *)ioa + (sizeof(uint32) * HS_REG_OFFSET))), incr);
      FC_UNMAP_MEMIO(ioa);
   case C_READ_HS:
      ioa = (void *)FC_MAP_IO(&di->fc_iomap_io);  /* map in io registers */
      offset  = READ_CSR_REG(binfo, FC_STAT_REG(binfo, ioa));
      FC_UNMAP_MEMIO(ioa);

      *((uint32 * )dm->fc_dataout) = offset;
      break;

   case C_WRITE_HA:
      incr = (uint32)((ulong)cip->c_arg1);
      ioa = (void *)FC_MAP_IO(&di->fc_iomap_io);  /* map in io registers */
      WRITE_CSR_REG(binfo,
          ((volatile uint32 * )((volatile char *)ioa + (sizeof(uint32) * HA_REG_OFFSET))), incr);
      FC_UNMAP_MEMIO(ioa);
   case C_READ_HA:
      ioa = (void *)FC_MAP_IO(&di->fc_iomap_io);  /* map in io registers */
      offset  = READ_CSR_REG(binfo, FC_HA_REG(binfo, ioa));
      FC_UNMAP_MEMIO(ioa);

      *((uint32 * )dm->fc_dataout) = offset;
      break;

   case C_WRITE_CA:
      incr = (uint32)((ulong)cip->c_arg1);
      ioa = (void *)FC_MAP_IO(&di->fc_iomap_io);  /* map in io registers */
      WRITE_CSR_REG(binfo,
          ((volatile uint32 * )((volatile char *)ioa + (sizeof(uint32) * CA_REG_OFFSET))), incr);
      FC_UNMAP_MEMIO(ioa);
   case C_READ_CA:
      ioa = (void *)FC_MAP_IO(&di->fc_iomap_io);  /* map in io registers */
      offset  = READ_CSR_REG(binfo, FC_FF_REG(binfo, ioa));
      FC_UNMAP_MEMIO(ioa);

      *((uint32 * )dm->fc_dataout) = offset;
      break;

   case C_READ_MB:
      binfo = &BINFO;
      if ((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE))) {
         mb = FC_SLI2_MAILBOX(binfo);
         fc_pcimem_bcopy((uint32 * )mb, (uint32 * )dm->fc_dataout, 128);
      } else {
         ioa = (void *)FC_MAP_MEM(&di->fc_iomap_mem);  /* map in slim */
         READ_SLIM_COPY(binfo, (uint32 * )dm->fc_dataout, (uint32 * )ioa,
            MAILBOX_CMD_WSIZE);
         FC_UNMAP_MEMIO(ioa);
      }
      break;

   case C_DBG:
      offset = (uint32)((ulong)cip->c_arg1);
      switch (offset) {
      case 0xffffffff:
         break;
      default:
         fc_dbg_flag = offset;
         break;
      }

      fc_bcopy((uchar * ) & fc_dbg_flag , dm->fc_dataout, sizeof(uint32));
      break;

   case C_INST:
      fc_bcopy((uchar * ) &fcinstcnt, dm->fc_dataout, sizeof(int));
      fc_bcopy((uchar * ) fcinstance, ((uchar *)dm->fc_dataout) + sizeof(int), sizeof(int) * MAX_FC_BRDS);
      break;

   case C_READ_RING:
      fc_bcopy(&binfo->fc_ring[cip->c_ring], dm->fc_dataout, sizeof(RING));
      break;

   case C_LISTN:
      {
      NODELIST *npp;
      ulong lcnt;
      ulong *lcntp;

      offset = (uint32)((ulong)cip->c_arg1);
      total_mem -= sizeof(NODELIST);
      lcnt = 0;
      switch (offset) {
      case 1: /* bind */
         lcntp = dm->fc_dataout;
         fc_bcopy((uchar * ) &lcnt , dm->fc_dataout, sizeof(ulong));
         npp = (NODELIST *)((char *)(dm->fc_dataout) + sizeof(ulong));
         nlp = binfo->fc_nlpbind_start;
         while((nlp != (NODELIST *)&binfo->fc_nlpbind_start) && (total_mem > 0)) {
            fc_bcopy((char *)nlp, npp, (sizeof(NODELIST)));
            total_mem -= sizeof(NODELIST);
            npp++;
            lcnt++;
            nlp = (NODELIST *)nlp->nlp_listp_next;
         }
         *lcntp = lcnt;
         break;
      case 2: /* unmap */
         lcntp = dm->fc_dataout;
         fc_bcopy((uchar * ) &lcnt , dm->fc_dataout, sizeof(ulong));
         npp = (NODELIST *)((char *)(dm->fc_dataout) + sizeof(ulong));
         nlp = binfo->fc_nlpunmap_start;
         while((nlp != (NODELIST *)&binfo->fc_nlpunmap_start) && (total_mem > 0)) {
            fc_bcopy((char *)nlp, npp, (sizeof(NODELIST)));
            total_mem -= sizeof(NODELIST);
            npp++;
            lcnt++;
            nlp = (NODELIST *)nlp->nlp_listp_next;
         }
         *lcntp = lcnt;
         break;
      case 3: /* map */
         lcntp = dm->fc_dataout;
         fc_bcopy((uchar * ) &lcnt , dm->fc_dataout, sizeof(ulong));
         npp = (NODELIST *)((char *)(dm->fc_dataout) + sizeof(ulong));
         nlp = binfo->fc_nlpmap_start;
         while((nlp != (NODELIST *)&binfo->fc_nlpmap_start) && (total_mem > 0)) {
            fc_bcopy((char *)nlp, npp, (sizeof(NODELIST)));
            total_mem -= sizeof(NODELIST);
            npp++;
            lcnt++;
            nlp = (NODELIST *)nlp->nlp_listp_next;
         }
         *lcntp = lcnt;
         break;
      case 4: /* all */
         lcntp = dm->fc_dataout;
         fc_bcopy((uchar * ) &lcnt , dm->fc_dataout, sizeof(ulong));
         npp = (NODELIST *)((char *)(dm->fc_dataout) + sizeof(ulong));
         nlp = binfo->fc_nlpbind_start;
         while((nlp != (NODELIST *)&binfo->fc_nlpbind_start) && (total_mem > 0)) {
            fc_bcopy((char *)nlp, npp, (sizeof(NODELIST)));
            total_mem -= sizeof(NODELIST);
            npp++;
            lcnt++;
            nlp = (NODELIST *)nlp->nlp_listp_next;
         }
         nlp = binfo->fc_nlpunmap_start;
         while((nlp != (NODELIST *)&binfo->fc_nlpunmap_start) && (total_mem > 0)) {
            fc_bcopy((char *)nlp, npp, (sizeof(NODELIST)));
            total_mem -= sizeof(NODELIST);
            npp++;
            lcnt++;
            nlp = (NODELIST *)nlp->nlp_listp_next;
         }
         nlp = binfo->fc_nlpmap_start;
         while((nlp != (NODELIST *)&binfo->fc_nlpmap_start) && (total_mem > 0)) {
            fc_bcopy((char *)nlp, npp, (sizeof(NODELIST)));
            total_mem -= sizeof(NODELIST);
            npp++;
            lcnt++;
            nlp = (NODELIST *)nlp->nlp_listp_next;
         }
         *lcntp = lcnt;
         break;
      default:
         rc = ERANGE;
         break;
      }
      infop->c_outsz = (sizeof(ulong) + (lcnt * sizeof(NODELIST)));
      break;
      }

   case C_LISTEVT:
      {
      uint32 ehdcnt;
      uint32 ecnt;
      uint32 *ehdcntp;
      uint32 *ecntp;
      fcEvent *ep;
      fcEvent_header *ehp;

      offset = (uint32)((ulong)cip->c_arg1);
      total_mem -= sizeof(uint32);
      infop->c_outsz = sizeof(uint32);
      ehdcnt = 0;
      ehdcntp = (uint32 *)dm->fc_dataout;
      bp = (uchar *)((char *)(dm->fc_dataout) + sizeof(uint32));
      switch (offset) {
      case 1: /* link */
         offset = FC_REG_LINK_EVENT;
         break;
      case 2: /* rscn */
         offset = FC_REG_RSCN_EVENT;
         break;
      case 3: /* ct */
         offset = FC_REG_CT_EVENT;
         break;
      case 7: /* all */
	 offset = 0;
         break;
      default:
         rc = ERANGE;
         goto out;
      }
      ehp = (fcEvent_header *)p_dev_ctl->fc_evt_head;
      while (ehp) {
        if ((offset == 0) || (ehp->e_mask == offset)) {
          ehdcnt++;
          fc_bcopy((char *)ehp, bp, (sizeof(fcEvent_header)));
          bp += (sizeof(fcEvent_header));
          total_mem -= sizeof(fcEvent_header);
	  if(total_mem <= 0) {
             rc = ENOMEM;
             goto out;
          }
          infop->c_outsz += sizeof(fcEvent_header);
          ecnt = 0;
          ecntp = (uint32 *)bp;
          bp += (sizeof(uint32));
          total_mem -= sizeof(uint32);
          infop->c_outsz += sizeof(uint32);
          ep = ehp->e_head;
          while(ep) {
             ecnt++;
             fc_bcopy((char *)ehp, bp, (sizeof(fcEvent)));
             bp += (sizeof(fcEvent));
             total_mem -= sizeof(fcEvent);
	     if(total_mem <= 0) {
                rc = ENOMEM;
                goto out;
             }
             infop->c_outsz += sizeof(fcEvent);
             ep = ep->evt_next;
          }
	  *ecntp = ecnt;
        }
        ehp = (fcEvent_header *)ehp->e_next_header;
      }

      *ehdcntp = ehdcnt;
      break;
      }

   case C_READ_RPILIST:
      {
      NODELIST *npp;

      cnt = 0;
      npp = (NODELIST *)(dm->fc_dataout);
      nlp = binfo->fc_nlpbind_start;
      if(nlp == (NODELIST *)&binfo->fc_nlpbind_start)
        nlp = binfo->fc_nlpunmap_start;
      if(nlp == (NODELIST *)&binfo->fc_nlpunmap_start)
         nlp = binfo->fc_nlpmap_start;
      while((nlp != (NODELIST *)&binfo->fc_nlpmap_start) && (total_mem > 0)) {
         fc_bcopy((char *)nlp, (char *)npp, sizeof(NODELIST));
         npp++;
         cnt++;
         nlp = (NODELIST *)nlp->nlp_listp_next;
         if(nlp == (NODELIST *)&binfo->fc_nlpbind_start)
           nlp = binfo->fc_nlpunmap_start;
         if(nlp == (NODELIST *)&binfo->fc_nlpunmap_start)
            nlp = binfo->fc_nlpmap_start;
      }
      if(cnt) {
         infop->c_outsz = (uint32)(cnt * sizeof(NODELIST));
      }
      }
      break;

   case C_READ_BPLIST:
      rp = &binfo->fc_ring[cip->c_ring];
      lptr = (uint32 * )dm->fc_dataout;

      mm = (MATCHMAP * )rp->fc_mpoff;
      total_mem -=  (3*sizeof(ulong));
      while ((mm) && (total_mem > 0)) {
         if (cip->c_ring == FC_ELS_RING) {
            *lptr++ = (uint32)((ulong)mm);
            *lptr++ = (uint32)((ulong)mm->virt);
            *lptr++ = (uint32)((ulong)mm->phys);
            mm = (MATCHMAP * )mm->fc_mptr;
         }
         if (cip->c_ring == FC_IP_RING) {
            fbp = (fcipbuf_t * )mm;
            *lptr++ = (uint32)((ulong)fbp);
            *lptr++ = (uint32)((ulong)fcdata(fbp));
            *lptr++ = (uint32)((ulong)fcnextpkt(fbp));
            mm = (MATCHMAP * )fcnextdata(fbp);
         }
         total_mem -= (3 * sizeof(ulong));
      }
      *lptr++ = 0;
      *lptr++ = (uint32)((ulong)rp->fc_mpon);

      infop->c_outsz = ((uchar * )lptr - (uchar *)(dm->fc_dataout));
      break;

   case C_READ_MEMSEG:
      fc_bcopy(&binfo->fc_memseg, dm->fc_dataout, (sizeof(MEMSEG) * FC_MAX_SEG));
      break;

   case C_RESET:
      offset = (uint32)((ulong)cip->c_arg1);
      switch (offset) {
      case 1: /* hba */
         fc_brdreset(p_dev_ctl);
         break;
      case 2: /* link */
         fc_rlip(p_dev_ctl);
         break;
      case 3: /* target */
         fc_fcp_abort(p_dev_ctl, TARGET_RESET, (int)((ulong)cip->c_arg2), -1);
         break;
      case 4: /* lun */
         fc_fcp_abort(p_dev_ctl, LUN_RESET, (int)((ulong)cip->c_arg2),
            (int)((ulong)cip->c_arg3));
         break;
      case 5: /* task set */
         fc_fcp_abort(p_dev_ctl, ABORT_TASK_SET, (int)((ulong)cip->c_arg2),
            (int)((ulong)cip->c_arg3));
         break;
      case 6: /* bus */
         fc_fcp_abort(p_dev_ctl, TARGET_RESET, -1, -1);
         break;
      default:
         rc = ERANGE;
         break;
      }
      break;

   case C_READ_BINFO:
   case C_FC_STAT:
      fc_bcopy(binfo, dm->fc_dataout, sizeof(FC_BRD_INFO));
      break;

   case C_NODE:
      break;

   case C_DEVP:
      offset = (uint32)((ulong)cip->c_arg1);
      cnt = (uint32)((ulong)cip->c_arg2);
      if ((offset >= (MAX_FC_TARGETS)) || (cnt >= 128)) {
         rc = ERANGE;
         break;
      }
      fc_bzero(dm->fc_dataout, (sizeof(dvi_t))+(sizeof(nodeh_t))+(sizeof(node_t)));
      fc_bcopy((char *)&binfo->device_queue_hash[offset], (uchar *)dm->fc_dataout, (sizeof(nodeh_t)));

      nodep = binfo->device_queue_hash[offset].node_ptr;
      if (nodep == 0) {
         break;
      }
      dev_ptr = nodep->lunlist;
      while ((dev_ptr != 0)) {
         if(dev_ptr->lun_id == cnt)
            break;
         dev_ptr = dev_ptr->next;
      }
      if (dev_ptr == 0) {
         break;
      }

      fc_bcopy((char *)&binfo->device_queue_hash[offset], (uchar *)dm->fc_dataout,
         (sizeof(nodeh_t)));
      fc_bcopy((char *)nodep, ((uchar *)dm->fc_dataout + sizeof(nodeh_t)),
         (sizeof(node_t)));
      fc_bcopy((char *)dev_ptr,
         ((uchar *)dm->fc_dataout + sizeof(nodeh_t) + sizeof(node_t)),
         (sizeof(dvi_t)));
      break;

   case C_NDD_STAT:
      fc_bcopy(&NDDSTAT, dm->fc_dataout, sizeof(ndd_genstats_t));
      break;

   case C_LINKINFO:
linfo:
      {
      LinkInfo *linkinfo;

      linkinfo = (LinkInfo *)dm->fc_dataout;
      linkinfo->a_linkEventTag = binfo->fc_eventTag;
      linkinfo->a_linkUp = FCSTATCTR.LinkUp;
      linkinfo->a_linkDown = FCSTATCTR.LinkDown;
      linkinfo->a_linkMulti = FCSTATCTR.LinkMultiEvent;
      linkinfo->a_DID = binfo->fc_myDID;
      if (binfo->fc_topology == TOPOLOGY_LOOP) {
         if(binfo->fc_flag & FC_PUBLIC_LOOP) {
            linkinfo->a_topology = LNK_PUBLIC_LOOP;
            fc_bcopy((uchar * )binfo->alpa_map,
               (uchar *)linkinfo->a_alpaMap, 128);
            linkinfo->a_alpaCnt = binfo->alpa_map[0];
         }
         else {
            linkinfo->a_topology = LNK_LOOP;
            fc_bcopy((uchar * )binfo->alpa_map,
               (uchar *)linkinfo->a_alpaMap, 128);
            linkinfo->a_alpaCnt = binfo->alpa_map[0];
         }
      }
      else {
         fc_bzero((uchar *)linkinfo->a_alpaMap, 128);
         linkinfo->a_alpaCnt = 0;
         if(binfo->fc_flag & FC_FABRIC) {
            linkinfo->a_topology = LNK_FABRIC;
         }
         else {
            linkinfo->a_topology = LNK_PT2PT;
         }
      }
      linkinfo->a_linkState = 0;
      switch (binfo->fc_ffstate) {
      case FC_INIT_START:
      case FC_INIT_NVPARAMS:
      case FC_INIT_REV:
      case FC_INIT_PARTSLIM:
      case FC_INIT_CFGRING:
      case FC_INIT_INITLINK:
      case FC_LINK_DOWN:
         linkinfo->a_linkState = LNK_DOWN;
         fc_bzero((uchar *)linkinfo->a_alpaMap, 128);
         linkinfo->a_alpaCnt = 0;
         break;
      case FC_LINK_UP:
      case FC_INIT_SPARAM:
      case FC_CFG_LINK:
         linkinfo->a_linkState = LNK_UP;
         break;
      case FC_FLOGI:
         linkinfo->a_linkState = LNK_FLOGI;
         break;
      case FC_LOOP_DISC:
      case FC_NS_REG:
      case FC_NS_QRY:
      case FC_NODE_DISC:
      case FC_REG_LOGIN:
      case FC_CLEAR_LA:
         linkinfo->a_linkState = LNK_DISCOVERY;
         break;
      case FC_READY:
         linkinfo->a_linkState = LNK_READY;
         break;
      }
      linkinfo->a_alpa = (uchar)(binfo->fc_myDID & 0xff);
      fc_bcopy((uchar * )&binfo->fc_portname, (uchar *)linkinfo->a_wwpName, 8);
      fc_bcopy((uchar * )&binfo->fc_nodename, (uchar *)linkinfo->a_wwnName, 8);
      }
      break;

   case C_IOINFO:
      {
      IOinfo *ioinfo;

      ioinfo = (IOinfo *)dm->fc_dataout;
      ioinfo->a_mbxCmd = FCSTATCTR.issueMboxCmd;
      ioinfo->a_mboxCmpl = FCSTATCTR.mboxEvent;
      ioinfo->a_mboxErr = FCSTATCTR.mboxStatErr;
      ioinfo->a_iocbCmd = FCSTATCTR.IssueIocb;
      ioinfo->a_iocbRsp = FCSTATCTR.iocbRsp;
      ioinfo->a_adapterIntr = (FCSTATCTR.linkEvent + FCSTATCTR.iocbRsp + 
         FCSTATCTR.mboxEvent);
      ioinfo->a_fcpCmd = FCSTATCTR.fcpCmd;
      ioinfo->a_fcpCmpl = FCSTATCTR.fcpCmpl;
      ioinfo->a_fcpErr = FCSTATCTR.fcpRspErr + FCSTATCTR.fcpRemoteStop +
         FCSTATCTR.fcpPortRjt + FCSTATCTR.fcpPortBusy + FCSTATCTR.fcpError +
         FCSTATCTR.fcpLocalErr;
      ioinfo->a_seqXmit = NDDSTAT.ndd_ifOutUcastPkts_lsw;
      ioinfo->a_seqRcv = NDDSTAT.ndd_recvintr_lsw;
      ioinfo->a_bcastXmit = NDDSTAT.ndd_ifOutBcastPkts_lsw +
         NDDSTAT.ndd_ifOutMcastPkts_lsw;
      ioinfo->a_bcastRcv = FCSTATCTR.frameRcvBcast;
      ioinfo->a_elsXmit = FCSTATCTR.elsXmitFrame;
      ioinfo->a_elsRcv = FCSTATCTR.elsRcvFrame;
      ioinfo->a_RSCNRcv = FCSTATCTR.elsRcvRSCN;
      ioinfo->a_seqXmitErr = NDDSTAT.ndd_oerrors;
      ioinfo->a_elsXmitErr = FCSTATCTR.elsXmitErr;
      ioinfo->a_elsBufPost = binfo->fc_ring[FC_ELS_RING].fc_bufcnt;
      ioinfo->a_ipBufPost =  binfo->fc_ring[FC_IP_RING].fc_bufcnt;
      ioinfo->a_cnt1 = 0;
      ioinfo->a_cnt2 = 0;
      ioinfo->a_cnt3 = 0;
      ioinfo->a_cnt4 = 0;
      }
      break;

   case C_NODEINFO:
      {
      NodeInfo * np;

      /* First uint32 word will be count */
      np = (NodeInfo *)dm->fc_dataout;
      cnt = 0;
      total_mem -= sizeof(NODELIST);

      nlp = binfo->fc_nlpbind_start;
      if(nlp == (NODELIST *)&binfo->fc_nlpbind_start)
        nlp = binfo->fc_nlpunmap_start;
      if(nlp == (NODELIST *)&binfo->fc_nlpunmap_start)
         nlp = binfo->fc_nlpmap_start;
      while((nlp != (NODELIST *)&binfo->fc_nlpmap_start) && (total_mem > 0)) {
         fc_bzero((uchar *)np, sizeof(NODELIST));
         if(nlp->nlp_flag & NLP_NS_REMOVED)
            np->a_flag |= NODE_NS_REMOVED;
         if(nlp->nlp_flag & NLP_RPI_XRI)
            np->a_flag |= NODE_RPI_XRI;
         if(nlp->nlp_flag & NLP_REQ_SND)
            np->a_flag |= NODE_REQ_SND;
         if(nlp->nlp_flag & NLP_RM_ENTRY)
            np->a_flag |= NODE_RM_ENTRY;
         if(nlp->nlp_flag & NLP_FARP_SND)
            np->a_flag |= NODE_FARP_SND;
         if(nlp->nlp_type & NLP_FABRIC)
            np->a_flag |= NODE_FABRIC;
         if(nlp->nlp_type & NLP_FCP_TARGET)
            np->a_flag |= NODE_FCP_TARGET;
         if(nlp->nlp_type & NLP_IP_NODE)
            np->a_flag |= NODE_IP_NODE;
         if(nlp->nlp_type & NLP_SEED_WWPN)
            np->a_flag |= NODE_SEED_WWPN;
         if(nlp->nlp_type & NLP_SEED_WWNN)
            np->a_flag |= NODE_SEED_WWNN;
         if(nlp->nlp_type & NLP_SEED_DID)
            np->a_flag |= NODE_SEED_DID;
         if(nlp->nlp_type & NLP_AUTOMAP)
            np->a_flag |= NODE_AUTOMAP;
         if(nlp->nlp_action & NLP_DO_DISC_START)
            np->a_flag |= NODE_DISC_START;
         if(nlp->nlp_action & NLP_DO_ADDR_AUTH)
            np->a_flag |= NODE_ADDR_AUTH;
         np->a_state = nlp->nlp_state;
         np->a_did = nlp->nlp_DID;
         np->a_targetid = FC_SCSID(nlp->id.nlp_pan, nlp->id.nlp_sid);
         fc_bcopy(&nlp->nlp_portname, np->a_wwpn, 8);
         fc_bcopy(&nlp->nlp_nodename, np->a_wwnn, 8);
         total_mem -= sizeof(NODELIST);
         np++;
         cnt++;
         nlp = (NODELIST *)nlp->nlp_listp_next;
         if(nlp == (NODELIST *)&binfo->fc_nlpbind_start)
           nlp = binfo->fc_nlpunmap_start;
         if(nlp == (NODELIST *)&binfo->fc_nlpunmap_start)
            nlp = binfo->fc_nlpmap_start;
      }
      if(cnt) {
         infop->c_outsz = (uint32)(cnt * sizeof(NodeInfo));
      }
      }
      break;

   case C_HBA_ADAPTERATRIBUTES:
      {
      HBA_ADAPTERATTRIBUTES * ha;

      vp = &VPD;
      ha = (HBA_ADAPTERATTRIBUTES *)dm->fc_dataout;
      fc_bzero(dm->fc_dataout, (sizeof(HBA_ADAPTERATTRIBUTES)));
      ha->NumberOfPorts = 1;
      ha->VendorSpecificID = di->fc_ba.a_pci;
      fc_bcopy(di->fc_ba.a_drvrid,  ha->DriverVersion, 16);
      fc_bcopy(di->fc_ba.a_fwname, ha->FirmwareVersion, 32);
      fc_bcopy((uchar * )&binfo->fc_sparam.nodeName, (uchar * )&ha->NodeWWN,
       sizeof(HBA_WWN));
      fc_bcopy("Emulex Corporation", ha->Manufacturer, 20);

      switch(((SWAP_LONG(ha->VendorSpecificID))>>16) & 0xffff) {
      case PCI_DEVICE_ID_SUPERFLY:
         if((vp->rev.biuRev == 1) ||
            (vp->rev.biuRev == 2) || (vp->rev.biuRev == 3)) {
            fc_bcopy("LP7000",  ha->Model, 8);
            fc_bcopy("Emulex LightPulse LP7000 1 Gigabit PCI Fibre Channel Adapter",  ha->ModelDescription, 62);
         }
         else {
            fc_bcopy("LP7000E",  ha->Model, 9);
            fc_bcopy("Emulex LightPulse LP7000E 1 Gigabit PCI Fibre Channel Adapter",  ha->ModelDescription, 62);
         }
         break;
      case PCI_DEVICE_ID_DRAGONFLY:
         fc_bcopy("LP8000",  ha->Model, 8);
         fc_bcopy("Emulex LightPulse LP8000 1 Gigabit PCI Fibre Channel Adapter",  ha->ModelDescription, 62);
         break;
      case PCI_DEVICE_ID_CENTAUR:
         if(FC_JEDEC_ID(vp->rev.biuRev) == CENTAUR_2G_JEDEC_ID) {
            fc_bcopy("LP9002",  ha->Model, 8);
            fc_bcopy("Emulex LightPulse LP9002 2 Gigabit PCI Fibre Channel Adapter",  ha->ModelDescription, 62);
         }
         else {
            fc_bcopy("LP9000",  ha->Model, 8);
            fc_bcopy("Emulex LightPulse LP9000 1 Gigabit PCI Fibre Channel Adapter",  ha->ModelDescription, 62);
         }
         break;
      case PCI_DEVICE_ID_PEGASUS:
         fc_bcopy("LP9802",  ha->Model, 8);
         fc_bcopy("Emulex LightPulse LP9802 2 Gigabit PCI Fibre Channel Adapter",  ha->ModelDescription, 62);
         break;
      case PCI_DEVICE_ID_THOR:
         fc_bcopy("LP10000",  ha->Model, 9);
         fc_bcopy("Emulex LightPulse LP10000 2 Gigabit PCI Fibre Channel Adapter",  ha->ModelDescription, 63);
         break;
      case PCI_DEVICE_ID_PFLY:
         fc_bcopy("LP982",  ha->Model, 7);
         fc_bcopy("Emulex LightPulse LP982 2 Gigabit PCI Fibre Channel Adapter",  ha->ModelDescription, 62);
         break;
      case PCI_DEVICE_ID_TFLY:
         fc_bcopy("LP1050",  ha->Model, 8);
         fc_bcopy("Emulex LightPulse LP1050 2 Gigabit PCI Fibre Channel Adapter",  ha->ModelDescription, 63);
         break;
      }
      fc_bcopy("lpfcdd",  ha->DriverName, 7);
      fc_bcopy(binfo->fc_SerialNumber, ha->SerialNumber, 32);
      fc_bcopy(binfo->fc_OptionROMVersion, ha->OptionROMVersion, 32);

      /* Convert JEDEC ID to ascii for hardware version */
      incr = vp->rev.biuRev;
      for(i=0;i<8;i++) {
         j = (incr & 0xf);
         if(j <= 9)
            ha->HardwareVersion[7-i] = (char)((uchar)0x30 + (uchar)j);
         else
            ha->HardwareVersion[7-i] = (char)((uchar)0x61 + (uchar)(j-10));
         incr = (incr >> 4);
      }
      ha->HardwareVersion[8] = 0;

      }
      break;

   case C_HBA_PORTATRIBUTES:
      {
      SERV_PARM          * hsp;
      HBA_OSDN           * osdn;

localport:
      vp = &VPD;
      hsp = (SERV_PARM *)&binfo->fc_sparam;
      hp = (HBA_PORTATTRIBUTES *)dm->fc_dataout;
      fc_bzero(dm->fc_dataout, (sizeof(HBA_PORTATTRIBUTES)));
      fc_bcopy((uchar * )&binfo->fc_sparam.nodeName, (uchar * )&hp->NodeWWN,
       sizeof(HBA_WWN));
      fc_bcopy((uchar * )&binfo->fc_sparam.portName, (uchar * )&hp->PortWWN,
       sizeof(HBA_WWN));

      if( binfo->fc_linkspeed == LA_2GHZ_LINK)
         hp->PortSpeed = HBA_PORTSPEED_2GBIT;
      else
         hp->PortSpeed = HBA_PORTSPEED_1GBIT;

      if(FC_JEDEC_ID(vp->rev.biuRev) == CENTAUR_2G_JEDEC_ID)
         hp->PortSupportedSpeed = HBA_PORTSPEED_2GBIT;
      else
         hp->PortSupportedSpeed = HBA_PORTSPEED_1GBIT;

      hp->PortFcId = binfo->fc_myDID;
      hp->PortType = HBA_PORTTYPE_UNKNOWN;
      if (binfo->fc_topology == TOPOLOGY_LOOP) {
         if(binfo->fc_flag & FC_PUBLIC_LOOP) {
            hp->PortType = HBA_PORTTYPE_NLPORT;
            fc_bcopy((uchar * )&binfo->fc_fabparam.nodeName,
               (uchar * )&hp->FabricName, sizeof(HBA_WWN));
         }
         else {
            hp->PortType = HBA_PORTTYPE_LPORT;
         }
      }
      else {
         if(binfo->fc_flag & FC_FABRIC) {
            hp->PortType = HBA_PORTTYPE_NPORT;
            fc_bcopy((uchar * )&binfo->fc_fabparam.nodeName,
               (uchar * )&hp->FabricName, sizeof(HBA_WWN));
         }
         else {
            hp->PortType = HBA_PORTTYPE_PTP;
         }
      }

      if (binfo->fc_flag & FC_BYPASSED_MODE) {
         hp->PortState = HBA_PORTSTATE_BYPASSED;
      }
      else if (binfo->fc_flag & FC_OFFLINE_MODE) {
         hp->PortState = HBA_PORTSTATE_DIAGNOSTICS;
      }
      else {
         switch (binfo->fc_ffstate) {
         case FC_INIT_START:
         case FC_INIT_NVPARAMS:
         case FC_INIT_REV:
         case FC_INIT_PARTSLIM:
         case FC_INIT_CFGRING:
         case FC_INIT_INITLINK:
            hp->PortState = HBA_PORTSTATE_UNKNOWN;
         case FC_LINK_DOWN:
         case FC_LINK_UP:
         case FC_INIT_SPARAM:
         case FC_CFG_LINK:
         case FC_FLOGI:
         case FC_LOOP_DISC:
         case FC_NS_REG:
         case FC_NS_QRY:
         case FC_NODE_DISC:
         case FC_REG_LOGIN:
         case FC_CLEAR_LA:
            hp->PortState = HBA_PORTSTATE_LINKDOWN;
            break;
         case FC_READY:
            hp->PortState = HBA_PORTSTATE_ONLINE;
            break;
         default:
            hp->PortState = HBA_PORTSTATE_ERROR;
            break;
         }
      }
      cnt = binfo->fc_map_cnt + binfo->fc_unmap_cnt;
      hp->NumberofDiscoveredPorts = cnt;
      if (hsp->cls1.classValid) {
         hp->PortSupportedClassofService |= 1; /* bit 1 */
      }
      if (hsp->cls2.classValid) {
         hp->PortSupportedClassofService |= 2; /* bit 2 */
      }
      if (hsp->cls3.classValid) {
         hp->PortSupportedClassofService |= 4; /* bit 3 */
      }
      hp->PortMaxFrameSize = (((uint32)hsp->cmn.bbRcvSizeMsb) << 8) |
         (uint32)hsp->cmn.bbRcvSizeLsb;

      hp->PortSupportedFc4Types.bits[2] = 0x1;
      hp->PortSupportedFc4Types.bits[3] = 0x20;
      hp->PortSupportedFc4Types.bits[7] = 0x1;
      if(clp[CFG_FCP_ON].a_current) {
         hp->PortActiveFc4Types.bits[2] = 0x1;
      }
      if(clp[CFG_NETWORK_ON].a_current) {
         hp->PortActiveFc4Types.bits[3] = 0x20;
      }
      hp->PortActiveFc4Types.bits[7] = 0x1;


      /* OSDeviceName is the device info filled into the HBA_OSDN structure */
      osdn = (HBA_OSDN *)&hp->OSDeviceName[0];
      fc_bcopy("lpfc", osdn->drvname, 4);
      osdn->instance = fc_brd_to_inst(binfo->fc_brd_no);
      osdn->target = (HBA_UINT32)(-1);
      osdn->lun = (HBA_UINT32)(-1);

      }
      break;

   case C_HBA_PORTSTATISTICS:
      {
      HBA_PORTSTATISTICS * hs;
      FCCLOCK_INFO * clock_info;

      hs = (HBA_PORTSTATISTICS *)dm->fc_dataout;
      fc_bzero(dm->fc_dataout, (sizeof(HBA_PORTSTATISTICS)));

      mb = (MAILBOX * )mbox;
      fc_read_status(binfo, mb);
      mb->un.varRdStatus.clrCounters = 0;
      if(dfc_issue_mbox(p_dev_ctl, mb, &ipri)) {
         rc = ENODEV;
         break;
      }
      hs->TxFrames = mb->un.varRdStatus.xmitFrameCnt;
      hs->RxFrames = mb->un.varRdStatus.rcvFrameCnt;
      /* Convert KBytes to words */
      hs->TxWords = (mb->un.varRdStatus.xmitByteCnt * 256);
      hs->RxWords = (mb->un.varRdStatus.rcvbyteCnt * 256);
      fc_read_lnk_stat(binfo, mb);
      if(dfc_issue_mbox(p_dev_ctl, mb, &ipri)) {
         rc = ENODEV;
         break;
      }
      hs->LinkFailureCount = mb->un.varRdLnk.linkFailureCnt;
      hs->LossOfSyncCount = mb->un.varRdLnk.lossSyncCnt;
      hs->LossOfSignalCount = mb->un.varRdLnk.lossSignalCnt;
      hs->PrimitiveSeqProtocolErrCount = mb->un.varRdLnk.primSeqErrCnt;
      hs->InvalidTxWordCount = mb->un.varRdLnk.invalidXmitWord;
      hs->InvalidCRCCount = mb->un.varRdLnk.crcCnt;
      hs->ErrorFrames = mb->un.varRdLnk.crcCnt;

      if (binfo->fc_topology == TOPOLOGY_LOOP) {
         hs->LIPCount = (binfo->fc_eventTag >> 1);
         hs->NOSCount = -1;
      }
      else {
         hs->LIPCount = -1;
         hs->NOSCount = (binfo->fc_eventTag >> 1);
      }

      hs->DumpedFrames = -1;
      clock_info = &DD_CTL.fc_clock_info;
      hs->SecondsSinceLastReset = clock_info->ticks;

      }
      break;

   case C_HBA_WWPNPORTATRIBUTES:
      {
      HBA_WWN findwwn;

      hp = (HBA_PORTATTRIBUTES *)dm->fc_dataout;
      vp = &VPD;
      fc_bzero(dm->fc_dataout, (sizeof(HBA_PORTATTRIBUTES)));

      dfc_unlock_enable(ipri, &CMD_LOCK);
      if (fc_copyin((uchar *)cip->c_arg1, (uchar *)&findwwn, (ulong)(sizeof(HBA_WWN)))) {
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         rc = EIO;
         break;
      }
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

      /* First Mapped ports, then unMapped ports */
      nlp = binfo->fc_nlpmap_start;
      if(nlp == (NODELIST *)&binfo->fc_nlpmap_start)
         nlp = binfo->fc_nlpunmap_start;
      while(nlp != (NODELIST *)&binfo->fc_nlpunmap_start) {
         if (fc_geportname(&nlp->nlp_portname, (NAME_TYPE *)&findwwn) == 2)
            goto foundit;
         nlp = (NODELIST *)nlp->nlp_listp_next;
         if(nlp == (NODELIST *)&binfo->fc_nlpmap_start)
            nlp = binfo->fc_nlpunmap_start;
      }
      rc = ERANGE;
      break;
      }

   case C_HBA_DISCPORTATRIBUTES:
      {
      SERV_PARM          * hsp;
      MATCHMAP           * mp;
      HBA_OSDN           * osdn;
      uint32         refresh;

      vp = &VPD;
      hp = (HBA_PORTATTRIBUTES *)dm->fc_dataout;
      fc_bzero(dm->fc_dataout, (sizeof(HBA_PORTATTRIBUTES)));
      offset = (uint32)((ulong)cip->c_arg2);
      refresh = (uint32)((ulong)cip->c_arg3);
      if(refresh != binfo->nlptimer) {
         hp->PortFcId = 0xffffffff;
         break;
      }
      cnt = 0;
      /* First Mapped ports, then unMapped ports */
      nlp = binfo->fc_nlpmap_start;
      if(nlp == (NODELIST *)&binfo->fc_nlpmap_start)
         nlp = binfo->fc_nlpunmap_start;
      while(nlp != (NODELIST *)&binfo->fc_nlpunmap_start) {
         if(cnt == offset)
            goto foundit;
         cnt++;
         nlp = (NODELIST *)nlp->nlp_listp_next;
         if(nlp == (NODELIST *)&binfo->fc_nlpmap_start)
            nlp = binfo->fc_nlpunmap_start;
      }
      rc = ERANGE;
      break;

foundit:
      /* Check if its the local port */
      if(binfo->fc_myDID == nlp->nlp_DID) {
         goto localport;
      }

      mb = (MAILBOX * )mbox;
      fc_read_rpi(binfo, (uint32)nlp->nlp_Rpi, 
          (MAILBOX * )mb, (uint32)0);

      if ((mp = (MATCHMAP * )fc_mem_get(binfo, MEM_BUF)) == 0) {
         rc = ENOMEM;
         break;
      }
      hsp = (SERV_PARM *)mp->virt;
      if (binfo->fc_flag & FC_SLI2) {
         mb->un.varRdRPI.un.sp64.addrHigh =
           (uint32)putPaddrHigh(mp->phys);
         mb->un.varRdRPI.un.sp64.addrLow =
           (uint32)putPaddrLow(mp->phys);
         mb->un.varRdRPI.un.sp64.tus.f.bdeSize = sizeof(SERV_PARM);
      }
      else {
         mb->un.varRdRPI.un.sp.bdeAddress =
           (uint32)putPaddrLow(mp->phys);
         mb->un.varRdRPI.un.sp.bdeSize = sizeof(SERV_PARM);
      }

      if(dfc_issue_mbox(p_dev_ctl, mb, &ipri)) {
         rc = ENODEV;
         break;
      }

      if (hsp->cls1.classValid) {
         hp->PortSupportedClassofService |= 1; /* bit 1 */
      }
      if (hsp->cls2.classValid) {
         hp->PortSupportedClassofService |= 2; /* bit 2 */
      }
      if (hsp->cls3.classValid) {
         hp->PortSupportedClassofService |= 4; /* bit 3 */
      }
      hp->PortMaxFrameSize = (((uint32)hsp->cmn.bbRcvSizeMsb) << 8) |
         (uint32)hsp->cmn.bbRcvSizeLsb;

      fc_mem_put(binfo, MEM_BUF, (uchar * )mp);

      fc_bcopy((uchar * )&nlp->nlp_nodename, (uchar * )&hp->NodeWWN,
       sizeof(HBA_WWN));
      fc_bcopy((uchar * )&nlp->nlp_portname, (uchar * )&hp->PortWWN,
       sizeof(HBA_WWN));

      hp->PortSpeed = 0;
      if(((binfo->fc_myDID & 0xffff00) == (nlp->nlp_DID & 0xffff00)) &&
         (binfo->fc_topology == TOPOLOGY_LOOP)) { 
         if( binfo->fc_linkspeed == LA_2GHZ_LINK)
            hp->PortSpeed = HBA_PORTSPEED_2GBIT;
         else
            hp->PortSpeed = HBA_PORTSPEED_1GBIT;
      }

      hp->PortFcId = nlp->nlp_DID;
      if((binfo->fc_flag & FC_FABRIC) &&
         ((binfo->fc_myDID & 0xff0000) == (nlp->nlp_DID & 0xff0000))) {
         fc_bcopy((uchar * )&binfo->fc_fabparam.nodeName,
            (uchar * )&hp->FabricName, sizeof(HBA_WWN));
      }
      hp->PortState = HBA_PORTSTATE_ONLINE;
      if (nlp->nlp_type & NLP_FCP_TARGET) {
         hp->PortActiveFc4Types.bits[2] = 0x1;
      }
      if (nlp->nlp_type & NLP_IP_NODE) {
         hp->PortActiveFc4Types.bits[3] = 0x20;
      }
      hp->PortActiveFc4Types.bits[7] = 0x1;

      hp->PortType = HBA_PORTTYPE_UNKNOWN;
      if (binfo->fc_topology == TOPOLOGY_LOOP) {
         if(binfo->fc_flag & FC_PUBLIC_LOOP) {
            /* Check if Fabric port */
            if (fc_geportname(&nlp->nlp_nodename, (NAME_TYPE *)&(binfo->fc_fabparam.nodeName)) == 2) {
               hp->PortType = HBA_PORTTYPE_FLPORT;
            }
            else {
               /* Based on DID */
               if((nlp->nlp_DID & 0xff) == 0) {
                  hp->PortType = HBA_PORTTYPE_NPORT;
               }
               else {
                  if((nlp->nlp_DID & 0xff0000) != 0xff0000) {
                     hp->PortType = HBA_PORTTYPE_NLPORT;
                  }
               }
            }
         }
         else {
            hp->PortType = HBA_PORTTYPE_LPORT;
         }
      }
      else {
         if(binfo->fc_flag & FC_FABRIC) {
            /* Check if Fabric port */
            if (fc_geportname(&nlp->nlp_nodename, (NAME_TYPE *)&(binfo->fc_fabparam.nodeName)) == 2) {
               hp->PortType = HBA_PORTTYPE_FPORT;
            }
            else {
               /* Based on DID */
               if((nlp->nlp_DID & 0xff) == 0) {
                  hp->PortType = HBA_PORTTYPE_NPORT;
               }
               else {
                  if((nlp->nlp_DID & 0xff0000) != 0xff0000) {
                     hp->PortType = HBA_PORTTYPE_NLPORT;
                  }
               }
            }
         }
         else {
            hp->PortType = HBA_PORTTYPE_PTP;
         }
      }

      /* for mapped devices OSDeviceName is device info filled into HBA_OSDN structure */
      if(nlp->nlp_flag & NLP_MAPPED) {
         osdn = (HBA_OSDN *)&hp->OSDeviceName[0];
         fc_bcopy("lpfc", osdn->drvname, 4);
         osdn->instance = fc_brd_to_inst(binfo->fc_brd_no);
         osdn->target = FC_SCSID(nlp->id.nlp_pan, nlp->id.nlp_sid);
         osdn->lun = (HBA_UINT32)(-1);
      }

      }
      break;

   case C_HBA_INDEXPORTATRIBUTES:
      {
      uint32         refresh;

      vp = &VPD;
      hp = (HBA_PORTATTRIBUTES *)dm->fc_dataout;
      fc_bzero(dm->fc_dataout, (sizeof(HBA_PORTATTRIBUTES)));
      offset = (uint32)((ulong)cip->c_arg2);
      refresh = (uint32)((ulong)cip->c_arg3);
      if(refresh != binfo->nlptimer) {
         hp->PortFcId = 0xffffffff;
         break;
      }
      cnt = 0;
      /* Mapped NPorts only */
      nlp = binfo->fc_nlpmap_start;
      while(nlp != (NODELIST *)&binfo->fc_nlpmap_start) {
         if(cnt == offset)
            goto foundit;
         cnt++;
         nlp = (NODELIST *)nlp->nlp_listp_next;
      }
      rc = ERANGE;
      }
      break;

   case C_HBA_SETMGMTINFO:
      {
      HBA_MGMTINFO *mgmtinfo;

      mgmtinfo = (HBA_MGMTINFO *)dfc.dfc_buffer;

      dfc_unlock_enable(ipri, &CMD_LOCK);
      if (fc_copyin((uchar *)cip->c_arg1, (uchar *)mgmtinfo, sizeof(HBA_MGMTINFO))) {
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         rc = EIO;
         break;
      }
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

      binfo->ipVersion = mgmtinfo->IPVersion;
      binfo->UDPport = mgmtinfo->UDPPort;
      if(binfo->ipVersion == RNID_IPV4) {
         fc_bcopy((uchar *)&mgmtinfo->IPAddress[0],
            (uchar * )&binfo->ipAddr[0], 4);
      }
      else {
         fc_bcopy((uchar *)&mgmtinfo->IPAddress[0],
            (uchar * )&binfo->ipAddr[0], 16);
      }
      }
      break;

   case C_HBA_GETMGMTINFO:
      {
      HBA_MGMTINFO *mgmtinfo;

      mgmtinfo = (HBA_MGMTINFO *)dm->fc_dataout;
      fc_bcopy((uchar * )&binfo->fc_nodename, (uchar *)&mgmtinfo->wwn, 8);
      mgmtinfo->unittype = RNID_HBA;
      mgmtinfo->PortId = binfo->fc_myDID;
      mgmtinfo->NumberOfAttachedNodes = 0;
      mgmtinfo->TopologyDiscoveryFlags = 0;
      mgmtinfo->IPVersion = binfo->ipVersion;
      mgmtinfo->UDPPort = binfo->UDPport;
      if(binfo->ipVersion == RNID_IPV4) {
         fc_bcopy((void *) & binfo->ipAddr[0],
               (void *) & mgmtinfo->IPAddress[0], 4);
      }
      else {
         fc_bcopy((void *) & binfo->ipAddr[0],
               (void *) & mgmtinfo->IPAddress[0], 16);
      }
      }
      break;

   case C_HBA_REFRESHINFO:
      {
      lptr = (uint32 *)dm->fc_dataout;
      *lptr = binfo->nlptimer;
      }
      break;

   case C_HBA_RNID:
      ipri = dfc_hba_rnid( p_dev_ctl, dm, cip, infop, buf_info, ipri);
      break;

   case C_HBA_GETEVENT:
      {
      HBA_UINT32 outsize;
      HBAEVENT *rec;
      HBAEVENT *recout;

      size = (uint32)((ulong)cip->c_arg1); /* size is number of event entries */

      recout = (HBAEVENT * )dm->fc_dataout;
      for(j=0;j<MAX_HBAEVENT;j++) {
         if((j == (int)size) ||
           (p_dev_ctl->hba_event_get == p_dev_ctl->hba_event_put))
            break;
         rec = &p_dev_ctl->hbaevent[p_dev_ctl->hba_event_get];
         fc_bcopy((uchar * )rec, (uchar *)recout, sizeof(HBAEVENT));
         recout++;
         p_dev_ctl->hba_event_get++;
         if(p_dev_ctl->hba_event_get >= MAX_HBAEVENT) {
            p_dev_ctl->hba_event_get = 0;
         }
      }
      outsize = j;

      /* copy back size of response */
      dfc_unlock_enable(ipri, &CMD_LOCK);
      if (fc_copyout((uchar *)&outsize, (uchar *)cip->c_arg2, sizeof(HBA_UINT32))) {
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         rc = EIO;
         break;
      }
      /* copy back number of missed records */
      if (fc_copyout((uchar *)&p_dev_ctl->hba_event_missed, (uchar *)cip->c_arg3, sizeof(HBA_UINT32))) {
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         rc = EIO;
         break;
      }
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

      p_dev_ctl->hba_event_missed = 0;
      infop->c_outsz = (uint32)(outsize * sizeof(HBA_EVENTINFO));
      }

      break;

   case C_HBA_FCPTARGETMAPPING:
      ipri = dfc_hba_targetmapping(p_dev_ctl, dm, cip, infop, ipri); 
      break;

   case C_HBA_FCPBINDING:
      ipri = dfc_hba_fcpbind(p_dev_ctl, dm, cip, infop, ipri);
      break;

   case C_GETCFG:
      {
      CfgParam * cp;
      iCfgParam * icp;

      /* First uint32 word will be count */
      cp = (CfgParam *)dm->fc_dataout;
      cnt = 0;
      for (i = 0; i < NUM_CFG_PARAM; i++) {
         icp = &clp[i];
         cp->a_low   = icp->a_low;
         cp->a_hi    = icp->a_hi;
         cp->a_flag  = icp->a_flag;
         cp->a_default  = icp->a_default;
         cp->a_current  = icp->a_current;
         cp->a_changestate  = icp->a_changestate;
         fc_bcopy(icp->a_string, cp->a_string, 32);
         fc_bcopy(icp->a_help, cp->a_help, 80);
         cp++;
         cnt++;
      }
      if(cnt) {
         infop->c_outsz = (uint32)(cnt * sizeof(CfgParam));
      }
      }
      break;

   case C_SETCFG:
      {
      RING  * rp;
      iCfgParam * icp;

      offset = (uint32)((ulong)cip->c_arg1);
      cnt = (uint32)((ulong)cip->c_arg2);
      if (offset >= NUM_CFG_PARAM) {
         rc = ERANGE;
         break;
      }
      icp = &clp[offset];
      if(icp->a_changestate != CFG_DYNAMIC) {
         rc = EPERM;
         break;
      }
      if (((icp->a_low != 0) && (cnt < icp->a_low)) || (cnt > icp->a_hi)) {
         rc = ERANGE;
         break;
      }
      switch(offset) {
      case CFG_FCP_CLASS:
         switch (cnt) {
         case 1:
            clp[CFG_FCP_CLASS].a_current = CLASS1;
            break;
         case 2:
            clp[CFG_FCP_CLASS].a_current = CLASS2;
            break;
         case 3:
            clp[CFG_FCP_CLASS].a_current = CLASS3;
            break;
         }
         icp->a_current  = cnt;
         break;

      case CFG_IP_CLASS:
         switch (cnt) {
         case 1:
            clp[CFG_IP_CLASS].a_current = CLASS1;
            break;
         case 2:
            clp[CFG_IP_CLASS].a_current = CLASS2;
            break;
         case 3:
            clp[CFG_IP_CLASS].a_current = CLASS3;
            break;
         }
         icp->a_current  = cnt;
         break;

      case CFG_LINKDOWN_TMO:
         icp->a_current  = cnt;
         rp = &binfo->fc_ring[FC_FCP_RING];
         if(clp[CFG_LINKDOWN_TMO].a_current) {
            rp->fc_ringtmo = clp[CFG_LINKDOWN_TMO].a_current;
         }
         break;

      default:
         icp->a_current  = cnt;
      }
      }
      break;

   case C_GET_EVENT:
      {
      fcEvent *ep;
      fcEvent *oep;
      fcEvent_header *ehp;
      uchar *cp;
      MATCHMAP *omm;
      int     no_more;

      no_more = 1;

      offset = ((uint32)((ulong)cip->c_arg3) & FC_REG_EVENT_MASK);  /* event mask */
      incr = (uint32)cip->c_flag;             /* event id   */
      size = (uint32)cip->c_iocb;             /* process requesting event  */
      ehp = (fcEvent_header *)p_dev_ctl->fc_evt_head;
      while (ehp) {
       if (ehp->e_mask == offset)
         break;
       ehp = (fcEvent_header *)ehp->e_next_header;
      }

      if (!ehp) {
        rc = ENOENT;
        break;
      }

      ep = ehp->e_head;
      oep = 0;
      while(ep) {
         /* Find an event that matches the event mask */
         if(ep->evt_sleep == 0) {
            /* dequeue event from event list */
            if(oep == 0) {
               ehp->e_head = ep->evt_next;
            } else {
               oep->evt_next = ep->evt_next;
            }
            if(ehp->e_tail == ep)
               ehp->e_tail = oep;

            switch(offset) {
            case FC_REG_LINK_EVENT:
               break;
            case FC_REG_RSCN_EVENT:
               /* Return data length */
               cnt = sizeof(uint32);

               dfc_unlock_enable(ipri, &CMD_LOCK);
               if (fc_copyout((uchar *)&cnt, (uchar *)cip->c_arg1, sizeof(uint32))) {
                  ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
                  rc = EIO;
               }
               ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

               fc_bcopy((char *)&ep->evt_data0, dm->fc_dataout, cnt);
               infop->c_outsz = (uint32)cnt;
               break;
            case FC_REG_CT_EVENT:
               /* Return data length */
               cnt = (ulong)(ep->evt_data2);

               dfc_unlock_enable(ipri, &CMD_LOCK);
               if (fc_copyout((uchar *)&cnt, (uchar *)cip->c_arg1, sizeof(uint32))) {
                  rc = EIO;
               }
               else {
                  if (fc_copyout((uchar *)&ep->evt_data0, (uchar *)cip->c_arg2,
                     sizeof(uint32))) {
                     rc = EIO;
                  }
               }
               ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

               infop->c_outsz = (uint32)cnt;
               i = cnt;
               mm = (MATCHMAP * )ep->evt_data1;
               cp = (uchar *)dm->fc_dataout;
               while(mm) {

                  if(cnt > FCELSSIZE)
                     i = FCELSSIZE;
                  else
                     i = cnt;

                  if(total_mem > 0) {
                     fc_bcopy((char *)mm->virt, cp, i);
                     total_mem -= i;
                  }

                  omm = mm;
                  mm = (MATCHMAP *)mm->fc_mptr;
                  cp += i;
                  fc_mem_put(binfo, MEM_BUF, (uchar * )omm);
               }
               break;
            }

            if((offset == FC_REG_CT_EVENT) && (ep->evt_next) && 
               (((fcEvent *)(ep->evt_next))->evt_sleep == 0)) {
               ep->evt_data0 |= 0x80000000; /* More event is waiting */   
               if (fc_copyout((uchar *)&ep->evt_data0, (uchar *)cip->c_arg2,
                     sizeof(uint32))) {
                     rc = EIO;
               }
               no_more = 0;
            }

            /* Requeue event entry */
            ep->evt_next = 0;
            ep->evt_data0 = 0;
            ep->evt_data1 = 0;
            ep->evt_data2 = 0;
            ep->evt_sleep = 1;
            ep->evt_flags = 0;

            if(ehp->e_head == 0) {
               ehp->e_head = ep;
               ehp->e_tail = ep;
            }
            else {
               ehp->e_tail->evt_next = ep;
               ehp->e_tail = ep;
            }

            if(offset == FC_REG_LINK_EVENT) {
               ehp->e_flag &= ~E_GET_EVENT_ACTIVE;
               goto linfo;
            }

            dfc_unlock_enable(ipri, &CMD_LOCK);
            if (fc_copyout((char *)dm->fc_dataout, infop->c_dataout, (int)infop->c_outsz)) {
              rc = EIO;
            }
            dfc_data_free(p_dev_ctl, dm);

            ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
            if (no_more) 
              ehp->e_flag &= ~E_GET_EVENT_ACTIVE;
            di->fc_refcnt--;
            dfc_unlock_enable(ipri, &CMD_LOCK);

            return (rc);
         }
         oep = ep;
         ep = ep->evt_next;
      }
      if(ep == 0) {
         /* No event found */
         rc = ENOENT;
      }
      }
      break;

   case C_SET_EVENT:
      ipri = dfc_hba_set_event(p_dev_ctl, dm, cip, infop, ipri);
      break;

   default:
      rc = EINVAL;
      break;
   }

out:
   /* dfc_ioctl exit */
   fc_log_printf_msg_vargs( binfo->fc_brd_no,
          &fc_msgBlk0401,                   /* ptr to msg structure */
           fc_mes0401,                      /* ptr to msg */
            fc_msgBlk0401.msgPreambleStr,   /* begin varargs */
             rc,
              infop->c_outsz,
               (uint32)((ulong)infop->c_dataout)); /* end varargs */

   di->fc_refcnt--;
   dfc_unlock_enable(ipri, &CMD_LOCK);

   /* Copy data to user space config method */
   if ((rc == 0) || (do_cp == 1)) { 
      if (infop->c_outsz) {
         if (fc_copyout((char *)dm->fc_dataout, infop->c_dataout, (int)infop->c_outsz)) {
            rc = EIO;
         }
      }
   }

   /* Now free the space for these structures */
   dmdata_info->virt = (struct dfc_mem *)dm;
   dmdata_info->phys = 0;
   dmdata_info->flags  = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
   dmdata_info->size = sizeof(* dm);
   dmdata_info->dma_handle = 0;
   dmdata_info->data_handle = 0;
   fc_free(p_dev_ctl, dmdata_info);
   
   mbox_info->virt = (char *)mbox;
   mbox_info->phys = 0;
   mbox_info->flags  = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
   mbox_info->size = sizeof(* mbox);
   mbox_info->dma_handle = 0;
   mbox_info->data_handle = 0;
   fc_free(p_dev_ctl, mbox_info);

   dfc_data_free(p_dev_ctl, dm);
   return (rc);
}


uint32
dfc_getLunId(
node_t *nodep, uint32 lunIndex)
{
   static uint32 lun;
   static int i;
   static dvi_t *dev_ptr;
   static FCP_CMND *tmp;    

   tmp = (FCP_CMND *)nodep->virtRptLunData;

   if(tmp == 0) {
      dev_ptr = nodep->lunlist;
      lun = dev_ptr->lun_id;
   } else {
      i = (lunIndex + 1) * 8;
      tmp = (FCP_CMND *)(((uchar *)nodep->virtRptLunData) + i);
      lun = ((tmp->fcpLunMsl >> FC_LUN_SHIFT) & 0xff);
   }
   return lun;  
}

_static_ int
dfc_bcopy(
uint32 *lsrc,
uint32 *ldest,
int     cnt,
int     incr)
{
   static ushort * ssrc;
   static ushort * sdest;
   static uchar * csrc;
   static uchar * cdest;
   static int  i;

   csrc = (uchar * )lsrc;
   cdest = (uchar * )ldest;
   ssrc = (ushort * )lsrc;
   sdest = (ushort * )ldest;

   for (i = 0; i < cnt; i += incr) {
      if (incr == sizeof(char)) {
         *cdest++ = *csrc++;
      } else if (incr == sizeof(short)) {
         *sdest++ = *ssrc++;
      } else {
         *ldest++ = *lsrc++;
      }
   }
   return(0);
}


_static_ fc_dev_ctl_t  *
dfc_getpdev(
struct cmd_input *ci)
{
   static fc_dev_ctl_t  * p_dev_ctl;/* pointer to dev_ctl area */
   static FC_BRD_INFO  * binfo;

   p_dev_ctl = DD_CTL.p_dev[ci->c_brd];
   binfo = &BINFO;

   if (p_dev_ctl == 0) {
      return(0);
   }

   /* Make sure command specified ring is within range */
   if (ci->c_ring >= binfo->fc_ffnumrings) {
      return(0);
   }

   return(p_dev_ctl);
}


_static_ int
fc_inst_to_brd(
int ddiinst)
{
   int  i;

   for (i = 0; i < fcinstcnt; i++)
      if (fcinstance[i] == ddiinst)
         return(i);

   return(MAX_FC_BRDS);
}


_static_ int
dfc_msdelay(
fc_dev_ctl_t  * p_dev_ctl,
ulong ms)
{
   DELAYMSctx(ms);
   return(0);
}

_local_ int
dfc_issue_mbox(
fc_dev_ctl_t * p_dev_ctl,
MAILBOX      * mb,
ulong        * ipri)
{
   static int  j;
   static MAILBOX      * mbslim;
   static FC_BRD_INFO  * binfo;
   static iCfgParam    * clp;
   struct dfc_info * di;
   static volatile uint32 word0, ldata;
   static uint32         ha_copy;
   static void         * ioa;

   binfo = &BINFO;
   clp = DD_CTL.p_config[binfo->fc_brd_no];
   di = &dfc.dfc_info[binfo->fc_brd_no];
   if (binfo->fc_ffstate == FC_ERROR) {
      mb->mbxStatus = MBXERR_ERROR;
      return(1);
   }
   j = 0;
   while((binfo->fc_mbox_active) || (di->fc_flag & DFC_MBOX_ACTIVE)) {
      dfc_unlock_enable(*ipri, &CMD_LOCK);

      if (j < 10) {
         dfc_msdelay(p_dev_ctl, 1);
      } else {
         dfc_msdelay(p_dev_ctl, 50);
      }

      *ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
      if (j++ >= 600) {
         mb->mbxStatus = MBXERR_ERROR;
         return(1);
      }
   }
   binfo->fc_mbox_active = 2;
   di->fc_flag |= DFC_MBOX_ACTIVE;

retrycmd:
   /* next set own bit for the adapter and copy over command word */
   mb->mbxOwner = OWN_CHIP;

   if ((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE))) {
      /* First copy command data */
      mbslim = FC_SLI2_MAILBOX(binfo);
      fc_pcimem_bcopy((uint32 * )mb, (uint32 * )mbslim,
          (sizeof(uint32) * (MAILBOX_CMD_WSIZE)));
   } else {
      /* First copy command data */
      ioa = (void *)FC_MAP_MEM(&di->fc_iomap_mem);  /* map in SLIM */
      mbslim = FC_MAILBOX(binfo, ioa);
      WRITE_SLIM_COPY(binfo, &mb->un.varWords, &mbslim->un.varWords,
          (MAILBOX_CMD_WSIZE - 1));

      /* copy over last word, with mbxOwner set */
      ldata = *((volatile uint32 * )mb);


      WRITE_SLIM_ADDR(binfo, ((volatile uint32 * )mbslim), ldata);
      FC_UNMAP_MEMIO(ioa);
   }

   fc_bcopy((char *)(mb), (char *)&p_dev_ctl->dfcmb[0],
          (sizeof(uint32) * (MAILBOX_CMD_WSIZE)));

   /* interrupt board to doit right away */
   ioa = (void *)FC_MAP_IO(&di->fc_iomap_io);  /* map in io registers */
   WRITE_CSR_REG(binfo, FC_FF_REG(binfo, ioa), CA_MBATT);
   FC_UNMAP_MEMIO(ioa);

   FCSTATCTR.issueMboxCmd++;

   if ((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE))) {
      /* First copy command data */
      word0 = p_dev_ctl->dfcmb[0];
   } else {
      /* First copy command data */
      ioa = (void *)FC_MAP_MEM(&di->fc_iomap_mem);  /* map in SLIM */
      mbslim = FC_MAILBOX(binfo, ioa);
      word0 = READ_SLIM_ADDR(binfo, ((volatile uint32 * )mbslim));
      FC_UNMAP_MEMIO(ioa);
   }

   ioa = (void *)FC_MAP_IO(&di->fc_iomap_io);  /* map in io registers */
   ha_copy = READ_CSR_REG(binfo, FC_HA_REG(binfo, ioa));
   FC_UNMAP_MEMIO(ioa);

   /* Wait for command to complete */
   while (((word0 & OWN_CHIP) == OWN_CHIP) || !(ha_copy & HA_MBATT)) {
      dfc_unlock_enable(*ipri, &CMD_LOCK);

      if ((j < 20) && (mb->mbxCommand != MBX_INIT_LINK)) {
         dfc_msdelay(p_dev_ctl, 1);
      } else {
         dfc_msdelay(p_dev_ctl, 50);
      }

      *ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
      if (j++ >= 600) {
         mb->mbxStatus = MBXERR_ERROR;
         binfo->fc_mbox_active = 0;
         di->fc_flag &= ~DFC_MBOX_ACTIVE;
         return(1);
      }

      if ((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE))) {
         /* First copy command data */
         word0 = p_dev_ctl->dfcmb[0];
      } else {
         /* First copy command data */
         ioa = (void *)FC_MAP_MEM(&di->fc_iomap_mem);  /* map in SLIM */
         mbslim = FC_MAILBOX(binfo, ioa);
         word0 = READ_SLIM_ADDR(binfo, ((volatile uint32 * )mbslim));
         FC_UNMAP_MEMIO(ioa);
      }
      ha_copy = HA_MBATT;
   }

   mbslim = (MAILBOX * ) & word0;
   if (mbslim->mbxCommand != mb->mbxCommand) {
      j++;
      if(mb->mbxCommand == MBX_INIT_LINK) {
         /* Do not retry init_link's */
         mb->mbxStatus = 0;
         binfo->fc_mbox_active = 0;
         di->fc_flag &= ~DFC_MBOX_ACTIVE;
         return(1);
      }
      goto retrycmd;
   }

   /* copy results back to user */
   if ((binfo->fc_flag & FC_SLI2) && (!(binfo->fc_flag & FC_OFFLINE_MODE))) {
      /* First copy command data */
      fc_bcopy((char *)&p_dev_ctl->dfcmb[0], (char *)mb,
          (sizeof(uint32) * (MAILBOX_CMD_WSIZE)));
   } else {
      /* First copy command data */
      ioa = (void *)FC_MAP_MEM(&di->fc_iomap_mem);  /* map in SLIM */
      mbslim = FC_MAILBOX(binfo, ioa);
      /* copy results back to user */
      READ_SLIM_COPY(binfo, (uint32 * )mb, (uint32 * )mbslim,
         MAILBOX_CMD_WSIZE);
      FC_UNMAP_MEMIO(ioa);
   }

   ioa = (void *)FC_MAP_IO(&di->fc_iomap_io);  /* map in io registers */
   WRITE_CSR_REG(binfo, FC_HA_REG(binfo, ioa), HA_MBATT);
   FC_UNMAP_MEMIO(ioa);


   binfo->fc_mbox_active = 0;
   di->fc_flag &= ~DFC_MBOX_ACTIVE;

   return(0);
}

int
dfc_put_event(
fc_dev_ctl_t * p_dev_ctl,
uint32 evcode,
uint32 evdata0,
void * evdata1,
void * evdata2)
{
   static fcEvent *ep;
   static fcEvent *oep;
   static fcEvent_header *ehp = NULL;
   static int found;
   static MATCHMAP *mp;
   static uint32 fstype;
   static SLI_CT_REQUEST * ctp;

   ehp = (fcEvent_header *)p_dev_ctl->fc_evt_head;

   while (ehp) {
     if (ehp->e_mask == evcode)
       break;
     ehp = (fcEvent_header *)ehp->e_next_header;
   }

   if (!ehp) {
     return (0);
   }

   ep = ehp->e_head;
   oep = 0;
   found = 0;
   
   while(ep && (!found)) {
      if(ep->evt_sleep) {
         switch(evcode) {
         case FC_REG_CT_EVENT:
            mp = (MATCHMAP *)evdata1;
            ctp = (SLI_CT_REQUEST *)mp->virt;
            fstype = (uint32)(ctp->FsType);
            if((ep->evt_type == FC_FSTYPE_ALL) ||
               (ep->evt_type == fstype)) {
               found++;
               ep->evt_data0 = evdata0;  /* tag */
               ep->evt_data1 = evdata1;  /* buffer ptr */
               ep->evt_data2 = evdata2;  /* count */
               ep->evt_sleep = 0;
               if ((ehp->e_mode & E_SLEEPING_MODE) && !(ehp->e_flag & E_GET_EVENT_ACTIVE)) {
                 ehp->e_flag |= E_GET_EVENT_ACTIVE;
                 dfc_wakeup(p_dev_ctl, ehp);
               }

            }
            break;
         default:
            found++;
            ep->evt_data0 = evdata0;
            ep->evt_data1 = evdata1;
            ep->evt_data2 = evdata2;
            ep->evt_sleep = 0;
            if ((ehp->e_mode & E_SLEEPING_MODE) && !(ehp->e_flag & E_GET_EVENT_ACTIVE)) {
              ehp->e_flag |= E_GET_EVENT_ACTIVE;
              dfc_wakeup(p_dev_ctl, ehp);
            }
            break;
         }
      }
      oep = ep;
      ep = ep->evt_next;
   }
   return(found);
}

int
dfc_wakeupall(
fc_dev_ctl_t * p_dev_ctl,
int flag)
{
   static fcEvent *ep;
   static fcEvent *oep;
   static fcEvent_header *ehp = NULL;
   static int found;

   ehp = (fcEvent_header *)p_dev_ctl->fc_evt_head;
   found = 0;

   while (ehp) {
      ep = ehp->e_head;
      oep = 0;
      while(ep) {
         ep->evt_sleep = 0;
         if(flag) {
           dfc_wakeup(p_dev_ctl, ehp);
         }
         else if (!(ehp->e_flag & E_GET_EVENT_ACTIVE)) {
           found++;
           ehp->e_flag |= E_GET_EVENT_ACTIVE;
           dfc_wakeup(p_dev_ctl, ehp);
         }
         oep = ep;
         ep = ep->evt_next;
      }
     ehp = (fcEvent_header *)ehp->e_next_header;
   }
   return(found);
}

int
dfc_hba_put_event(
fc_dev_ctl_t * p_dev_ctl,
uint32 evcode,
uint32 evdata1,
uint32 evdata2,
uint32 evdata3,
uint32 evdata4)
{
   static HBAEVENT *rec;
   static FC_BRD_INFO     * binfo;

   binfo = &BINFO;
   rec = &p_dev_ctl->hbaevent[p_dev_ctl->hba_event_put];
   rec->fc_eventcode = evcode;

   rec->fc_evdata1   = evdata1;
   rec->fc_evdata2   = evdata2;
   rec->fc_evdata3   = evdata3;
   rec->fc_evdata4   = evdata4;
   p_dev_ctl->hba_event_put++;
   if(p_dev_ctl->hba_event_put >= MAX_HBAEVENT) {
      p_dev_ctl->hba_event_put = 0;
   }
   if(p_dev_ctl->hba_event_put == p_dev_ctl->hba_event_get) {
      p_dev_ctl->hba_event_missed++;
      p_dev_ctl->hba_event_get++;
      if(p_dev_ctl->hba_event_get >= MAX_HBAEVENT) {
         p_dev_ctl->hba_event_get = 0;
      }
   }

   return(0);
}       /* End dfc_hba_put_event */

int 
dfc_hba_set_event(
fc_dev_ctl_t * p_dev_ctl,
struct dfc_mem *dm,
struct cmd_input *cip,
struct dfccmdinfo *infop,
ulong ipri)
{
      static fcEvent *evp;
      static fcEvent *ep;
      static fcEvent *oep;
      static fcEvent_header *ehp;
      static fcEvent_header *oehp;
      static int found;
      static MBUF_INFO     * buf_info;
      static MBUF_INFO        bufinfo;
      static uint32           offset;
      static uint32           incr;

      offset = ((uint32)((ulong)cip->c_arg3) & FC_REG_EVENT_MASK); 
      incr = (uint32)cip->c_flag;    

      switch(offset) {
      case FC_REG_CT_EVENT:
         found = fc_out_event;  
         break;
      case FC_REG_RSCN_EVENT:
         found = fc_out_event;  
         break;
      case FC_REG_LINK_EVENT:
         found = 2;  
         break;
      default:
         found = 0;
         rc = EINTR;
         return(ipri);
      }

      oehp = 0;
      ehp = (fcEvent_header *)p_dev_ctl->fc_evt_head;
      while (ehp) {
        if (ehp->e_mask == offset) {
          found = 0;
          break; 
        }
        oehp = ehp;
        ehp = (fcEvent_header *)ehp->e_next_header;
      }

      if (!ehp) {
	 buf_info = &bufinfo;
         buf_info->virt = 0;
         buf_info->phys = 0;
         buf_info->flags  = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
         buf_info->align = sizeof(void *);
         buf_info->size = sizeof(fcEvent_header);
         buf_info->dma_handle = 0;

         dfc_unlock_enable(ipri, &CMD_LOCK);
         fc_malloc(p_dev_ctl, buf_info);
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         if (buf_info->virt == NULL) {
            rc = EINTR;
            return(ipri);
         }
         ehp = (fcEvent_header *)(buf_info->virt);
         fc_bzero((char *)ehp, sizeof(fcEvent_header));
         if(p_dev_ctl->fc_evt_head == 0) {
            p_dev_ctl->fc_evt_head = ehp;
            p_dev_ctl->fc_evt_tail = ehp;
         } else {
            ((fcEvent_header *)(p_dev_ctl->fc_evt_tail))->e_next_header = ehp;
            p_dev_ctl->fc_evt_tail = (void *)ehp;
         }
         ehp->e_handle = incr;
         ehp->e_mask = offset;

      }

      while(found) {
         /* Save event id for C_GET_EVENT */
	 buf_info = &bufinfo;
         buf_info->virt = 0;
         buf_info->phys = 0;
         buf_info->flags  = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
         buf_info->align = sizeof(void *);
         buf_info->size = sizeof(fcEvent);
         buf_info->dma_handle = 0;

         dfc_unlock_enable(ipri, &CMD_LOCK);
         fc_malloc(p_dev_ctl, buf_info);
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         if (buf_info->virt == NULL) {
            rc = EINTR;
            break;
         }
         oep = (fcEvent *)(buf_info->virt);
         fc_bzero((char *)oep, sizeof(fcEvent));

         oep->evt_sleep = 1;
         oep->evt_handle = incr;
         oep->evt_mask = offset;
         switch(offset) {
         case FC_REG_CT_EVENT:
            oep->evt_type = (uint32)((ulong)cip->c_arg2);   /* fstype for CT  */
            break;
         default:
            oep->evt_type = 0;
         }

         if(ehp->e_head == 0) {
            ehp->e_head = oep;
            ehp->e_tail = oep;
         } else {
            ehp->e_tail->evt_next = (void *)oep;
            ehp->e_tail = oep;
         }
	 oep->evt_next = 0;
         found--;
      }

      switch(offset) {
      case FC_REG_CT_EVENT:
      case FC_REG_RSCN_EVENT:
      case FC_REG_LINK_EVENT:
            if(dfc_sleep(p_dev_ctl, ehp)) {
               ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
               rc = EINTR;
               /* Remove all eventIds from queue */
               ep = ehp->e_head;
               oep = 0;
               found = 0;
               while(ep) {
                  if(ep->evt_handle == incr) {
                     /* dequeue event from event list */
                     if(oep == 0) {
                        ehp->e_head = ep->evt_next;
                     }
                     else {
                        oep->evt_next = ep->evt_next;
                     }
                     if(ehp->e_tail == ep)
                        ehp->e_tail = oep;
                     evp = ep;
                     ep = ep->evt_next;
                     dfc_unlock_enable(ipri, &CMD_LOCK);
                     buf_info = &bufinfo;
                     buf_info->virt = (uchar *)evp;
                     buf_info->size = sizeof(fcEvent);
                     buf_info->phys = 0;
                     buf_info->flags = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
                     buf_info->align = 0;
                     buf_info->dma_handle = 0;
                     fc_free(p_dev_ctl, buf_info);
                     ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
                  } else {
                     oep = ep;
                     ep = ep->evt_next;
                  }
               }
               if (ehp->e_head == 0) {

                 if (oehp == 0) {
                   p_dev_ctl->fc_evt_head = ehp->e_next_header;
                 } else {
                   oehp->e_next_header = ehp->e_next_header;
                 }
                 if (p_dev_ctl->fc_evt_tail == ehp)
                   p_dev_ctl->fc_evt_tail = oehp;

                 dfc_unlock_enable(ipri, &CMD_LOCK);
                 buf_info = &bufinfo;
                 buf_info->virt = (uchar *)ehp;
                 buf_info->size = sizeof(fcEvent_header);
                 buf_info->phys = 0;
                 buf_info->flags = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
                 buf_info->align = 0;
                 buf_info->dma_handle = 0;
                 fc_free(p_dev_ctl, buf_info);
                 ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
               }
               return(ipri);
            }
         return(ipri);
      }
      return(ipri);
}

int 
dfc_hba_sendscsi_fcp(
fc_dev_ctl_t * p_dev_ctl,
struct dfc_mem *dm,
struct cmd_input *cip,
struct dfccmdinfo *infop,
ulong ipri)
{
      static HBA_WWN       findwwn;
      static DMATCHMAP   * fcpmp;
      static RING        * rp;
      static fc_buf_t    * fcptr;
      static FCP_CMND    * fcpCmnd;
      static FCP_RSP     * fcpRsp;
      static ULP_BDE64   * bpl;
      static MATCHMAP    * bmp;
      static DMATCHMAP   * outdmp;
      static MBUF_INFO   * buf_info;
      static MBUF_INFO     bufinfo;
      static uint32	   buf1sz;
      static uint32	   buf2sz;
      static uint32 	   j;
      static uint32      * lptr;
      static char        * bp;
      static uint32        max;
      static struct {
         uint32     rspcnt;
         uint32     snscnt;
      } count;
      static struct dev_info *dev_info; 
      static FC_BRD_INFO     * binfo;

      binfo = &BINFO;
      lptr = (uint32 *)&cip->c_string[0];
      buf1sz = *lptr++;  /* Request data size */
      buf2sz = *lptr;    /* Sns / rsp buffer size */
      if((buf1sz + infop->c_outsz) > (80 * 4096)) {
         rc = ERANGE;
         return(ipri);
      }

      dfc_unlock_enable(ipri, &CMD_LOCK);
      if (fc_copyin((uchar *)cip->c_arg3, (uchar *)&findwwn, (ulong)(sizeof(HBA_WWN)))) {
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         rc = EIO;
         return(ipri);
      }

      buf_info = &bufinfo;
      buf_info->virt = 0;
      buf_info->phys = 0;
      buf_info->flags  = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
      buf_info->align = sizeof(void *);
      buf_info->size = sizeof(struct dev_info);
      buf_info->dma_handle = 0;

      fc_malloc(p_dev_ctl, buf_info);
      if (buf_info->virt == NULL) {
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         rc = ENOMEM;
         return(ipri);
      }
      dev_info = (struct dev_info *)buf_info->virt;

      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
      /* Allocate buffer for Buffer ptr list */
      if ((bmp = (MATCHMAP * )fc_mem_get(binfo, MEM_BPL)) == 0) {
         rc = ENOMEM;
         goto ssout3;
      }
      bpl = (ULP_BDE64 * )bmp->virt;
      dfc_unlock_enable(ipri, &CMD_LOCK);

      if((fcpmp = dfc_fcp_data_alloc(p_dev_ctl, bpl)) == 0) {
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         fc_mem_put(binfo, MEM_BUF, (uchar * )bmp);
         rc = ENOMEM;
         goto ssout3;
      }
      bpl += 2;  /* Cmnd and Rsp ptrs */
      fcpCmnd = (FCP_CMND *)fcpmp->dfc.virt;
      fcpRsp  = (FCP_RSP *)((uchar *)fcpCmnd + sizeof(FCP_CMND));

{
lptr = (uint32 *)bmp->virt;
}
      if (fc_copyin((uchar *)cip->c_arg1, (uchar *)fcpCmnd, (ulong)(buf1sz))) {
         dfc_fcp_data_free(p_dev_ctl, fcpmp);
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         fc_mem_put(binfo, MEM_BUF, (uchar * )bmp);
         rc = ENOMEM;
         goto ssout3;
      }
{
lptr = (uint32 *)fcpCmnd;
}
      fc_mpdata_sync(fcpmp->dfc.dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV);

      if(fcpCmnd->fcpCntl3 == WRITE_DATA) {
         bp = (uchar *)infop->c_dataout;
      }
      else {
         bp = 0;
      }

      if(infop->c_outsz == 0)
         outdmp = dfc_cmd_data_alloc(p_dev_ctl, bp, bpl, 512); 
      else
         outdmp = dfc_cmd_data_alloc(p_dev_ctl, bp, bpl, infop->c_outsz);

      if(!(outdmp)) {
         dfc_fcp_data_free(p_dev_ctl, fcpmp);
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         fc_mem_put(binfo, MEM_BUF, (uchar * )bmp);
         rc = ENOMEM;
         goto ssout3;
      }

      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

      max = 0;
redoss:
{
lptr = (uint32 *)bmp->virt;
}

      if((rc=fc_snd_scsi_req(p_dev_ctl, (NAME_TYPE *)&findwwn, bmp, fcpmp, outdmp, infop->c_outsz, dev_info)))
      {
         if((rc == ENODEV) && (max < 4)) {
            max++;
            dfc_unlock_enable(ipri, &CMD_LOCK);
            dfc_msdelay(p_dev_ctl, 500);
            ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
            goto redoss;
         }
         if(rc == ENODEV)
            rc = EACCES;
         dfc_unlock_enable(ipri, &CMD_LOCK);
         dfc_cmd_data_free(p_dev_ctl, outdmp);
         dfc_fcp_data_free(p_dev_ctl, fcpmp);
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         fc_mem_put(binfo, MEM_BUF, (uchar * )bmp);
         rc = ENOMEM;
         goto ssout3;
      }

      rp = &binfo->fc_ring[FC_FCP_RING];
      fcptr = (fc_buf_t *)fcpmp->dfc.virt;

      j = 0;
      dfc_unlock_enable(ipri, &CMD_LOCK);
      dfc_msdelay(p_dev_ctl, 1);
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

      /* Wait for FCP I/O to complete or timeout */
      while(dev_info->queue_state == ACTIVE_PASSTHRU) {
         dfc_unlock_enable(ipri, &CMD_LOCK);
         dfc_msdelay(p_dev_ctl, 50);
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         if(j >= 600) {  
            break;
         }
         j++;
      }

      /* Check for timeout conditions */
      if(dev_info->queue_state == ACTIVE_PASSTHRU) {
         /* Free resources */
         fc_deq_fcbuf_active(rp, fcptr->iotag);
         rc = ETIMEDOUT;
         dfc_unlock_enable(ipri, &CMD_LOCK);
         dfc_cmd_data_free(p_dev_ctl, outdmp);
         dfc_fcp_data_free(p_dev_ctl, fcpmp);
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         goto ssout3;
      }
      if ((infop->c_cmd == C_HBA_SEND_FCP) &&
          (dev_info->ioctl_event != IOSTAT_LOCAL_REJECT)) {
         if(buf2sz < sizeof(FCP_RSP))
            count.snscnt = buf2sz;
         else
            count.snscnt = sizeof(FCP_RSP);
{
lptr = (uint32 *)fcpRsp;
}
         dfc_unlock_enable(ipri, &CMD_LOCK);
         if (fc_copyout((uchar *)fcpRsp, (uchar *)cip->c_arg2, count.snscnt)) {
            ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
            rc = EIO;
            goto ssout0;
         }
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
      }

      switch(dev_info->ioctl_event) {
      case IOSTAT_SUCCESS:
cpdata:
         /* copy back response data */
         if(infop->c_outsz < dev_info->clear_count) {
            infop->c_outsz = 0;
            rc = ERANGE;
            goto ssout0;
         }
         infop->c_outsz = dev_info->clear_count;

         if (infop->c_cmd == C_HBA_SEND_SCSI) {
            count.rspcnt = infop->c_outsz;
            count.snscnt = 0;
         } else {        
            /* For C_HBA_SEND_FCP, snscnt is already set */
            count.rspcnt = infop->c_outsz;
         }

         /* Return data length */
         dfc_unlock_enable(ipri, &CMD_LOCK);
         if (fc_copyout((uchar *)&count, (uchar *)cip->c_arg3, (2*sizeof(uint32)))) {
            ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
            rc = EIO;
            goto ssout0;
         }

         infop->c_outsz = 0;
         if(count.rspcnt) {
            if(dfc_rsp_data_copy(p_dev_ctl, (uchar *)infop->c_dataout, outdmp, count.rspcnt)) {
               ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
               rc = EIO;
               goto ssout0;
            }
         }
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         break;
      case IOSTAT_LOCAL_REJECT:
         infop->c_outsz = 0;
         if(dev_info->ioctl_errno == IOERR_SEQUENCE_TIMEOUT) {
            rc = ETIMEDOUT;
            goto ssout0;
         }
         rc = EFAULT;
         goto ssout0;
      case IOSTAT_FCP_RSP_ERROR:
         j = 0;

         if(fcpCmnd->fcpCntl3 == READ_DATA) {
            dev_info->clear_count = infop->c_outsz - dev_info->clear_count;
            if ((fcpRsp->rspStatus2 & RESID_UNDER) && 
                (dev_info->clear_count)) {
               goto cpdata;
            }
         }
         else
            dev_info->clear_count = 0;

         count.rspcnt = (uint32)dev_info->clear_count;
         infop->c_outsz = 0;

         if (fcpRsp->rspStatus2 & RSP_LEN_VALID) {
            j = SWAP_DATA(fcpRsp->rspRspLen);
         }
         if (fcpRsp->rspStatus2 & SNS_LEN_VALID) {
            if (infop->c_cmd == C_HBA_SEND_SCSI) {
               if(buf2sz < (int)dev_info->sense_length)
                  count.snscnt = buf2sz;
               else
                  count.snscnt = dev_info->sense_length;

               /* Return sense info from rsp packet */
               dfc_unlock_enable(ipri, &CMD_LOCK);
               if (fc_copyout(((uchar *)&fcpRsp->rspInfo0) + j, 
                              (uchar *)cip->c_arg2, count.snscnt)) {
                  ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
                  rc = EIO;
                  goto ssout0;
               }
               ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
            }
         }
         else {
            rc = EFAULT;
            goto ssout0;
         }

         /* Return data length */
         dfc_unlock_enable(ipri, &CMD_LOCK);
         if (fc_copyout((uchar *)&count, (uchar *)cip->c_arg3, (2*sizeof(uint32)))) {
            ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
            rc = EIO;
            goto ssout0;
         }

     /* return data for read */
         if(count.rspcnt) {
            if(dfc_rsp_data_copy(p_dev_ctl, (uchar *)infop->c_dataout, outdmp, count.rspcnt)) {
               ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
               rc = EIO;
               goto ssout0;
            }
         }
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         break;

      default:
         infop->c_outsz = 0;
         rc = EFAULT;
         goto ssout0;
      }

ssout0:
      dfc_unlock_enable(ipri, &CMD_LOCK);
      dfc_cmd_data_free(p_dev_ctl, outdmp);
      dfc_fcp_data_free(p_dev_ctl, fcpmp);
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
ssout3:
      dfc_unlock_enable(ipri, &CMD_LOCK);
      buf_info->size = sizeof(struct dev_info);
      buf_info->virt = (uint32 * )dev_info;
      buf_info->phys = 0;
      buf_info->flags = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK);

      fc_free(p_dev_ctl, buf_info);
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
      return(ipri);
}

int
dfc_hba_fcpbind(
fc_dev_ctl_t * p_dev_ctl,
struct dfc_mem *dm,
struct cmd_input *cip,
struct dfccmdinfo *infop,
ulong ipri)
{
      static HBA_FCPBINDING * hb;
      static HBA_FCPBINDINGENTRY *ep;
      static uint32 room;
      static uint32 total;
      static uint32 lunIndex, totalLuns;   /* these 2 vars are per target id */
      static uint32 lunId;                 /* what we get back at lunIndex in virtRptLunData */
      static int    memsz, mapList;
      static char  *appPtr;
      static uint32 cnt;
      static node_t * nodep;
      static dvi_t  * dev_ptr;
      static uint32 total_mem;
      static uint32 offset, j;
      static NODELIST * nlp;
      static FC_BRD_INFO     * binfo;

      binfo = &BINFO;
      hb = (HBA_FCPBINDING *)dm->fc_dataout;
      ep = &hb->entry[0];
      room = (uint32)((ulong)cip->c_arg1);
      cnt = 0;
      total = 0;
      memsz = 0; 
      lunIndex = 0;
      totalLuns = 0;
      appPtr = ((char *)infop->c_dataout) + sizeof(ulong); 
      mapList = 1;

      /* First Mapped ports, then unMapped ports, then binding list */
      nlp = binfo->fc_nlpmap_start;
      if(nlp == (NODELIST *)&binfo->fc_nlpmap_start) {
         nlp = binfo->fc_nlpunmap_start;
	 mapList = 0;
      }
      if(nlp == (NODELIST *)&binfo->fc_nlpunmap_start)
         nlp = binfo->fc_nlpbind_start;
      while(nlp != (NODELIST *)&binfo->fc_nlpbind_start) {

         if (nlp->nlp_type & NLP_SEED_MASK) {
            offset = FC_SCSID(nlp->id.nlp_pan, nlp->id.nlp_sid);
            if(offset > MAX_FC_TARGETS) {
               goto nextbind;
            }
            nodep = binfo->device_queue_hash[offset].node_ptr;
            if(nodep)
               dev_ptr = nodep->lunlist;
            else
               dev_ptr = 0;
 
            if((!nodep) || (!dev_ptr)) {
               dev_ptr=fc_alloc_devp(p_dev_ctl, offset, 0);
               nodep = dev_ptr->nodep;
            }

            if(mapList) {
               /* For devices on the map list, we need to issue REPORT_LUN 
		* in case the device's config has changed */
               nodep->rptlunstate = REPORT_LUN_ONGOING;
               issue_report_lun(p_dev_ctl, dev_ptr, 0);

               j = 0;
               dfc_unlock_enable(ipri, &CMD_LOCK);
               dfc_msdelay(p_dev_ctl, 1);
               ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

               /* Wait for ReportLun request to complete or timeout */
               while(nodep->rptlunstate == REPORT_LUN_ONGOING) {
                  dfc_unlock_enable(ipri, &CMD_LOCK);
                  dfc_msdelay(p_dev_ctl, 50);
                  ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
                  if(j >= 600) {
                     break;
                  }
                  j++;
               }
               if(nodep->rptlunstate == REPORT_LUN_ONGOING) {
                  break;
               }
               /*
               * If nodep->virtRptLunData is null, then we just report 1 lun.
               * If not null, we will report luns from virtRptLunData buffer.
               */
               lunIndex = 0;
               totalLuns = 1;
	       dev_ptr = 0;
               if (nodep->virtRptLunData) {
                  uint32 *tmp;
                  tmp = (uint32*)nodep->virtRptLunData;
                  totalLuns = SWAP_DATA(*tmp) / 8;
               }
            }

            while(((mapList) && (lunIndex < totalLuns)) ||
                  (dev_ptr)) {
               if(mapList) {
                  lunId = dfc_getLunId(nodep, lunIndex);
                  dev_ptr = fc_find_lun(binfo, offset, lunId);
	       } else
                  lunId = dev_ptr->lun_id;

               if((mapList) ||
                  ((dev_ptr) && (dev_ptr->opened)))
                                                    {
                  if(cnt < room) {
                     HBA_OSDN *osdn;
                     HBA_UINT32 fcpLun[2];      
                     if(total_mem - memsz < sizeof(HBA_FCPBINDINGENTRY)) {
                        dfc_unlock_enable(ipri, &CMD_LOCK);
                        fc_copyout((char *)(&hb->entry[0]), appPtr, memsz);
                        ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

                        appPtr = appPtr + memsz;
                        ep = &hb->entry[0];
                        memsz = 0;
                     }
                     fc_bzero((void *)ep->ScsiId.OSDeviceName, 256);
                     if(nlp->nlp_flag & NLP_MAPPED) {
                        osdn = (HBA_OSDN *)&ep->ScsiId.OSDeviceName[0];
                        fc_bcopy("lpfc", osdn->drvname, 4);
                        osdn->instance = fc_brd_to_inst(binfo->fc_brd_no);
                        osdn->target = FC_SCSID(nlp->id.nlp_pan, nlp->id.nlp_sid);
                        osdn->lun = (HBA_UINT32)(lunId);
                     }

                     ep->ScsiId.ScsiTargetNumber =
                        FC_SCSID(nlp->id.nlp_pan, nlp->id.nlp_sid);
                     ep->ScsiId.ScsiOSLun = (HBA_UINT32)(lunId);
                     ep->ScsiId.ScsiBusNumber = 0;
                     
                     fc_bzero((char *)fcpLun, sizeof(HBA_UINT64));
                     fcpLun[0] = (lunId << FC_LUN_SHIFT);
                     if (nodep->addr_mode == VOLUME_SET_ADDRESSING) {
                        fcpLun[0] |= SWAP_DATA(0x40000000);
                     }
                     fc_bcopy((char *)&fcpLun[0], (char *)&ep->FcpId.FcpLun, sizeof(HBA_UINT64));
                     if (nlp->nlp_type & NLP_SEED_DID) {
                        ep->type = TO_D_ID;
                        ep->FcpId.FcId = nlp->nlp_DID;
                        ep->FcId = nlp->nlp_DID;
                        fc_bzero((uchar *)&ep->FcpId.PortWWN, sizeof(HBA_WWN));
                        fc_bzero((uchar *)&ep->FcpId.NodeWWN, sizeof(HBA_WWN));
                     }
                     else {
                        ep->type = TO_WWN;
                        ep->FcId = 0;
                        ep->FcpId.FcId = 0;
                        if (nlp->nlp_type & NLP_SEED_WWPN)
                           fc_bcopy(&nlp->nlp_portname, (uchar *)&ep->FcpId.PortWWN, sizeof(HBA_WWN));
                        else
                           fc_bcopy(&nlp->nlp_nodename, (uchar *)&ep->FcpId.NodeWWN, sizeof(HBA_WWN));
                     }
                     if (nlp->nlp_state == NLP_ALLOC) {
                        ep->FcpId.FcId = nlp->nlp_DID;
                        fc_bcopy(&nlp->nlp_portname, (uchar *)&ep->FcpId.PortWWN, sizeof(HBA_WWN));
                        fc_bcopy(&nlp->nlp_nodename, (uchar *)&ep->FcpId.NodeWWN, sizeof(HBA_WWN));
                     }
                     ep++;
                     cnt++;
                     memsz = memsz + sizeof(HBA_FCPBINDINGENTRY);
                     total++;
                  }
               }
               if(mapList) {
                  /* for map list, we want the while loop to go stricly
		   * based on lunIndex and totalLuns. */
                  lunIndex++;
                  dev_ptr = 0;
               } else
                  dev_ptr = dev_ptr->next;
            } /* while loop */
         }

nextbind:
         nlp = (NODELIST *)nlp->nlp_listp_next;
         if(nlp == (NODELIST *)&binfo->fc_nlpmap_start) {
            nlp = binfo->fc_nlpunmap_start;
            mapList = 0;
         }
         if(nlp == (NODELIST *)&binfo->fc_nlpunmap_start)
           nlp = binfo->fc_nlpbind_start;
      }

      dfc_unlock_enable(ipri, &CMD_LOCK);
      fc_copyout((char *)(&hb->entry[0]), appPtr, memsz);
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

      hb->NumberOfEntries = (HBA_UINT32)total;
      dfc_unlock_enable(ipri, &CMD_LOCK);
      fc_copyout((char *)(&hb->NumberOfEntries), infop->c_dataout, sizeof(ulong));
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

      infop->c_outsz = 0;            
      if (total > room) {
         rc = ERANGE;
         do_cp = 1;
      }
      return (ipri);
}

int
dfc_hba_sendmgmt_ct(
fc_dev_ctl_t * p_dev_ctl,
struct dfc_mem *dm,
struct cmd_input *cip,
struct dfccmdinfo *infop,
ulong ipri)

{
      static ULP_BDE64     * bpl;
      static MATCHMAP      * bmp;
      static DMATCHMAP     * indmp;
      static DMATCHMAP     * outdmp;
      static uint32          portid;
      static HBA_WWN         findwwn;
      static uint32	     buf1sz;
      static uint32	    buf2sz;
      static int 	    j;
      static uint32 	    max;
      static uint32 	    incr;
      static uint32      *  lptr;
      static NODELIST    * nlp;
      static FC_BRD_INFO     * binfo;

      binfo = &BINFO;
      incr = (uint32)cip->c_flag;  /* timeout for CT request */
      lptr = (uint32 *)&cip->c_string[0];
      buf1sz = *lptr++;
      buf2sz = *lptr;

      if((buf1sz == 0) ||
         (buf2sz == 0) ||
         (buf1sz + buf2sz > (80 * 4096))) {
         rc = ERANGE;
         return(ipri);
      }

      dfc_unlock_enable(ipri, &CMD_LOCK);

      if(infop->c_cmd == C_SEND_MGMT_CMD) {
         if (fc_copyin((uchar *)cip->c_arg3, (uchar *)&findwwn, (ulong)(sizeof(HBA_WWN)))) {
            ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
            rc = EIO;
            return(ipri);
         }
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

         /* First Mapped ports, then unMapped ports */
         nlp = binfo->fc_nlpmap_start;
         if(nlp == (NODELIST *)&binfo->fc_nlpmap_start)
            nlp = binfo->fc_nlpunmap_start;
         while(nlp != (NODELIST *)&binfo->fc_nlpunmap_start) {
            if (fc_geportname(&nlp->nlp_portname, (NAME_TYPE *)&findwwn) == 2)
               goto gotit;
            nlp = (NODELIST *)nlp->nlp_listp_next;
            if(nlp == (NODELIST *)&binfo->fc_nlpmap_start)
               nlp = binfo->fc_nlpunmap_start;
         }
         rc = ERANGE;
         return(ipri); 
gotit:
         portid = nlp->nlp_DID;
         dfc_unlock_enable(ipri, &CMD_LOCK);
      }
      else {
         portid = (uint32)((ulong)cip->c_arg3);
      }

      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
      /* Allocate buffer for Buffer ptr list */
      if ((bmp = (MATCHMAP * )fc_mem_get(binfo, MEM_BPL)) == 0) {
         rc = ENOMEM;
         return(ipri);
      }
      bpl = (ULP_BDE64 * )bmp->virt;
      dfc_unlock_enable(ipri, &CMD_LOCK);

      if((indmp = dfc_cmd_data_alloc(p_dev_ctl, (uchar *)cip->c_arg1, bpl, buf1sz)) == 0) {
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         fc_mem_put(binfo, MEM_BPL, (uchar * )bmp);
         rc = ENOMEM;
         return(ipri);
      }
      bpl += indmp->dfc_flag;

      if((outdmp = dfc_cmd_data_alloc(p_dev_ctl, 0, bpl, buf2sz)) == 0) {
         dfc_cmd_data_free(p_dev_ctl, indmp);
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         fc_mem_put(binfo, MEM_BPL, (uchar * )bmp);
         rc = ENOMEM;
         return(ipri); 
      }

      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
      max = 0;
redoct:
      if((rc=fc_issue_ct_req(binfo, portid, bmp, indmp, outdmp, incr))) {
         if((rc == ENODEV) && (max < 4)) {
            max++;
            dfc_unlock_enable(ipri, &CMD_LOCK);
            dfc_msdelay(p_dev_ctl, 500);
            ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
            goto redoct;
         }
         if(rc == ENODEV)
            rc = EACCES;
         goto ctout1;
      }

      j = 0;
      dfc_unlock_enable(ipri, &CMD_LOCK);
      dfc_msdelay(p_dev_ctl, 1);
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

      /* Wait for CT request to complete or timeout */
      while(outdmp->dfc_flag == 0) {
         dfc_unlock_enable(ipri, &CMD_LOCK);
         dfc_msdelay(p_dev_ctl, 50);
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         if(j >= 600) {  
            outdmp->dfc_flag = -1;
            break;
         }
         j++;
      }

      j = outdmp->dfc_flag;
      if(j == -1) {
         rc = ETIMEDOUT;
         goto ctout1;
      }

      if(j == -2) {
         rc = EFAULT;
         goto ctout1;
      }

      /* copy back response data */
      if(j > buf2sz) {
         rc = ERANGE;
         /* C_CT Request error */
         fc_log_printf_msg_vargs( binfo->fc_brd_no,
                &fc_msgBlk1208,                   /* ptr to msg structure */
                 fc_mes1208,                      /* ptr to msg */
                  fc_msgBlk1208.msgPreambleStr,   /* begin varargs */
                    outdmp->dfc_flag,
                     4096);                       /* end varargs */
         goto ctout1;
      }
      fc_bcopy((char *)&j, dm->fc_dataout, sizeof(int));

      /* copy back data */
      dfc_unlock_enable(ipri, &CMD_LOCK);
      if(dfc_rsp_data_copy(p_dev_ctl, (uchar *)cip->c_arg2, outdmp, j))
         rc = EIO;
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

ctout1:
      dfc_unlock_enable(ipri, &CMD_LOCK);
      dfc_cmd_data_free(p_dev_ctl, indmp);
      dfc_cmd_data_free(p_dev_ctl, outdmp);
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
      fc_mem_put(binfo, MEM_BPL, (uchar * )bmp);
      return(ipri); 
}

int
dfc_hba_rnid(
fc_dev_ctl_t * p_dev_ctl,
struct dfc_mem *dm,
struct cmd_input *cip,
struct dfccmdinfo *infop,
MBUF_INFO   *buf_info,
ulong ipri)
{
      static HBA_WWN findwwn;
      static ELS_PKT    * ep;
      static DMATCHMAP    inmatp;
      static DMATCHMAP    outmatp;
      static MATCHMAP   * bmptr;
      static uint32      * lptr;
      static NODELIST    * nlp;
      static int        j;
      static uint32      size, incr;
      static uint32      max;
      static FC_BRD_INFO     * binfo;

      binfo = &BINFO;
      dfc_unlock_enable(ipri, &CMD_LOCK);
      if (fc_copyin((uchar *)cip->c_arg1, (uchar *)&findwwn, (ulong)(sizeof(HBA_WWN)))) {
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         rc = EIO;
         return(ipri);
      }
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

      size = NLP_ALLOC;
      incr = 0;
nlpchk:
      nlp = binfo->fc_nlpbind_start;
      if(nlp == (NODELIST *)&binfo->fc_nlpbind_start)
        nlp = binfo->fc_nlpunmap_start;
      if(nlp == (NODELIST *)&binfo->fc_nlpunmap_start)
         nlp = binfo->fc_nlpmap_start;
      while(nlp != (NODELIST *)&binfo->fc_nlpmap_start) {
         if(cip->c_flag == NODE_WWN) {
            if (fc_geportname(&nlp->nlp_nodename, (NAME_TYPE *)&findwwn) == 2)
               goto foundrnid;
         }
         else {
            if (fc_geportname(&nlp->nlp_portname, (NAME_TYPE *)&findwwn) == 2)
               goto foundrnid;
         }
         nlp = (NODELIST *)nlp->nlp_listp_next;
         if(nlp == (NODELIST *)&binfo->fc_nlpbind_start)
           nlp = binfo->fc_nlpunmap_start;
         if(nlp == (NODELIST *)&binfo->fc_nlpunmap_start)
            nlp = binfo->fc_nlpmap_start;
      }
      rc = ERANGE;
      return(ipri);

foundrnid:
      if(nlp->nlp_action & NLP_DO_RNID)
         goto waitloop;

      if(nlp->nlp_Rpi == 0) {
         int wait_sec;

         size = nlp->nlp_DID;
         if(size == 0) {
            size = nlp->nlp_oldDID;
         }
         if((size == 0) || (size == 0xffffffff) || (size == 0xffffff) ||
            (incr == 3)) {
            rc = ERANGE;
            return(ipri);
         }
         incr++;
         nlp->nlp_action |= NLP_DO_RNID;
         fc_els_cmd(binfo, ELS_CMD_PLOGI, (void *)((ulong)size),
            (uint32)0, (ushort)0, nlp);
waitloop:
         wait_sec = 0;
         while(nlp->nlp_action & NLP_DO_RNID) {
            dfc_unlock_enable(ipri, &CMD_LOCK);
            dfc_msdelay(p_dev_ctl, 1000);
            ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
            if(wait_sec++ == 10)
               return(ipri);
         }
         nlp->nlp_action &= ~NLP_DO_RNID;
         goto nlpchk;
      }

      buf_info->virt = 0;
      buf_info->phys = 0;
      buf_info->flags  = (FC_MBUF_DMA | FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
      buf_info->align = (int)FCELSSIZE;
      buf_info->size = (int)FCELSSIZE;
      buf_info->dma_handle = 0;

      dfc_unlock_enable(ipri, &CMD_LOCK);
      fc_malloc(p_dev_ctl, buf_info);
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

      if (buf_info->phys == NULL) {
         rc = ENOMEM;
         return(ipri);
      }
      inmatp.dfc.virt = buf_info->virt;
      if (buf_info->dma_handle) {
         inmatp.dfc.dma_handle = buf_info->dma_handle;
         inmatp.dfc.data_handle = buf_info->data_handle;
      }
      inmatp.dfc.phys = (uchar * )buf_info->phys;

      /* Save size of RNID request in this field */
      inmatp.dfc.fc_mptr = (uchar *)((ulong)(2*sizeof(uint32)));
      fc_bzero((void *)inmatp.dfc.virt, (2 * sizeof(uint32)));

      buf_info->virt = 0;
      buf_info->phys = 0;
      buf_info->flags  = (FC_MBUF_DMA | FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
      buf_info->align = 4096;
      buf_info->size = infop->c_outsz + sizeof(uint32);
      buf_info->dma_handle = 0;

      dfc_unlock_enable(ipri, &CMD_LOCK);
      fc_malloc(p_dev_ctl, buf_info);
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

      if (buf_info->phys == NULL) {
         rc = ENOMEM;
         goto rnidout2;
      }
      outmatp.dfc.virt = buf_info->virt;
      if (buf_info->dma_handle) {
         outmatp.dfc.dma_handle = buf_info->dma_handle;
         outmatp.dfc.data_handle = buf_info->data_handle;
      }
      outmatp.dfc.phys = (uchar * )buf_info->phys;

      /* Save size in this field */
      outmatp.dfc.fc_mptr = (uchar *)((ulong)(infop->c_outsz + sizeof(uint32)));

      /* Setup RNID command */
      lptr = (uint32 *)inmatp.dfc.virt;
      *lptr = ELS_CMD_RNID;
      ep = (ELS_PKT * )lptr;
      ep->un.rnid.Format = RNID_TOPOLOGY_DISC;

      max = 0;
      bmptr = 0;
redornid:
      outmatp.dfc_flag = 0;
      if((rc=fc_rnid_req( binfo, &inmatp, &outmatp, &bmptr, nlp->nlp_Rpi))) {
         if(bmptr)
            fc_mem_put(binfo, MEM_BPL, (uchar * )bmptr);

         if((rc == ENODEV) && (max < 4)) {
            max++;
            dfc_unlock_enable(ipri, &CMD_LOCK);
            dfc_msdelay(p_dev_ctl, 500);
            ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
            goto redornid;
         }
         if(rc == ENODEV)
            rc = EACCES;
         goto rnidout1;
      }

      j = 0;
      dfc_unlock_enable(ipri, &CMD_LOCK);
      dfc_msdelay(p_dev_ctl, 1);
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

      /* Wait for RNID request to complete or timeout */
      while(outmatp.dfc_flag == 0) {
         dfc_unlock_enable(ipri, &CMD_LOCK);
         dfc_msdelay(p_dev_ctl, 50);
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         if(j >= 600) {  
            outmatp.dfc_flag = -1;
            return(ipri);
         }
         j++;
      }

      if(bmptr)
         fc_mem_put(binfo, MEM_BPL, (uchar * )bmptr);

      j = (int)((ulong)outmatp.dfc_flag);
      if(outmatp.dfc_flag == -1) {

         rc = ETIMEDOUT;
         goto rnidout1;
      }

      if(outmatp.dfc_flag == -2) {

         rc = EFAULT;
         goto rnidout1;
      }

      /* copy back response data */
      if(j > 4096) {
         rc = ERANGE;
         /* RNID Request error */
         fc_log_printf_msg_vargs( binfo->fc_brd_no,
                &fc_msgBlk1209,                   /* ptr to msg structure */
                 fc_mes1209,                      /* ptr to msg */
                  fc_msgBlk1209.msgPreambleStr,   /* begin varargs */
                   (int)((ulong)outmatp.dfc.fc_mptr),
                     4096);                       /* end varargs */
         goto rnidout1;
      }
      lptr = (uint32 *)outmatp.dfc.virt;
      if(*lptr != ELS_CMD_ACC) {
         rc = EFAULT;
         goto rnidout1;
      }
      lptr++; 
      j -= sizeof(uint32);
      fc_bcopy((char *)lptr, dm->fc_dataout, j);

      /* copy back size of response */
      dfc_unlock_enable(ipri, &CMD_LOCK);
      if (fc_copyout((uchar *)&j, (uchar *)cip->c_arg2, sizeof(int))) {
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
         rc = EIO;
         goto rnidout1;
      }
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

      infop->c_outsz = (uint32)((ulong)outmatp.dfc.fc_mptr);

rnidout1:
      buf_info->size = (int)((ulong)outmatp.dfc.fc_mptr);
      buf_info->virt = (uint32 * )outmatp.dfc.virt;
      buf_info->phys = (uint32 * )outmatp.dfc.phys;
      buf_info->flags  = (FC_MBUF_DMA | FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
      if (outmatp.dfc.dma_handle) {
         buf_info->dma_handle = outmatp.dfc.dma_handle;
         buf_info->data_handle = outmatp.dfc.data_handle;
      }
      dfc_unlock_enable(ipri, &CMD_LOCK);
      fc_free(p_dev_ctl, buf_info);
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

rnidout2:
      buf_info->size = (int)((ulong)inmatp.dfc.fc_mptr);
      buf_info->virt = (uint32 * )inmatp.dfc.virt;
      buf_info->phys = (uint32 * )inmatp.dfc.phys;
      buf_info->flags  = (FC_MBUF_DMA | FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
      if (inmatp.dfc.dma_handle) {
         buf_info->dma_handle = inmatp.dfc.dma_handle;
         buf_info->data_handle = inmatp.dfc.data_handle;
      }
      dfc_unlock_enable(ipri, &CMD_LOCK);
      fc_free(p_dev_ctl, buf_info);
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
      return(ipri);
}

int
dfc_hba_targetmapping(
fc_dev_ctl_t * p_dev_ctl,
struct dfc_mem *dm,
struct cmd_input *cip,
struct dfccmdinfo *infop,
ulong ipri)
{
      static HBA_FCPTARGETMAPPING * hf;
      static HBA_FCPSCSIENTRY *ep;
      static uint32 room;
      static uint32 total;
      static uint32 lunIndex, totalLuns;   /* these 2 vars are per target id */
      static uint32 lunId;                 /* what we get back at lunIndex in virtRptLunData */
      static int    memsz;
      static char  *appPtr;
      static NODELIST            * nlp;
      static node_t              * nodep;
      static dvi_t               * dev_ptr;
      static FC_BRD_INFO     * binfo;
      static uint32 offset;
      static uint32 total_mem;
      static uint32 j;
      static uint32 cnt; 

      binfo = &BINFO;
      hf = (HBA_FCPTARGETMAPPING *)dm->fc_dataout;
      ep = &hf->entry[0];
      room = (uint32)((ulong)cip->c_arg1);
      cnt = 0;
      total = 0;
      memsz = 0; 
      appPtr = ((char *)infop->c_dataout) + sizeof(ulong); 

      /* Mapped ports only */
      nlp = binfo->fc_nlpmap_start;
      while(nlp != (NODELIST *)&binfo->fc_nlpmap_start) {
         offset = FC_SCSID(nlp->id.nlp_pan, nlp->id.nlp_sid);
         if(offset > MAX_FC_TARGETS) {
            nlp = (NODELIST *)nlp->nlp_listp_next;
            continue;
         }
         nodep = binfo->device_queue_hash[offset].node_ptr;
         if(nodep)
            dev_ptr = nodep->lunlist;
         else
            dev_ptr = 0;

         if((!nodep) || (!dev_ptr)) {
            dev_ptr=fc_alloc_devp(p_dev_ctl, offset, 0);
	    nodep = dev_ptr->nodep;
         }

	 /* we need to issue REPORT_LUN here in case the device's 
          * config has changed */
	 nodep->rptlunstate = REPORT_LUN_ONGOING;
	 issue_report_lun(p_dev_ctl, dev_ptr, 0);

         j = 0;
         dfc_unlock_enable(ipri, &CMD_LOCK);
         dfc_msdelay(p_dev_ctl, 1);
         ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

         /* Wait for ReportLun request to complete or timeout */
         while(nodep->rptlunstate == REPORT_LUN_ONGOING) {
            dfc_unlock_enable(ipri, &CMD_LOCK);
            dfc_msdelay(p_dev_ctl, 50);
            ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);
            if(j >= 600) {  
               break;
            }
            j++;
         }
         if(nodep->rptlunstate == REPORT_LUN_ONGOING) {
	    break;
         }

	 lunIndex = 0;
	 totalLuns = 1;
	 if (nodep->virtRptLunData) {
	    uint32 *tmp;
	    tmp = (uint32*)nodep->virtRptLunData;
	    totalLuns = SWAP_DATA(*tmp) / 8;
         }

         while(lunIndex < totalLuns) {
	    lunId = dfc_getLunId(nodep, lunIndex);
            dev_ptr = fc_find_lun(binfo, offset, lunId);

            if((!dev_ptr) ||
	       ((dev_ptr) && (dev_ptr->opened) && (dev_ptr->queue_state == ACTIVE))) {
               if(cnt < room) {
                  HBA_OSDN *osdn;
                  HBA_UINT32 fcpLun[2];    

                  if(total_mem - memsz < sizeof(HBA_FCPSCSIENTRY)) {
                     dfc_unlock_enable(ipri, &CMD_LOCK);
                     fc_copyout((char *)(&hf->entry[0]), appPtr,memsz);
                     ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

		     appPtr = appPtr + memsz;
                     ep = &hf->entry[0];
                     memsz = 0;
                  }

                  fc_bzero((void *)ep->ScsiId.OSDeviceName, 256);
                  osdn = (HBA_OSDN *)&ep->ScsiId.OSDeviceName[0];
                  fc_bcopy("lpfc", osdn->drvname, 4);
                  osdn->instance = fc_brd_to_inst(binfo->fc_brd_no);
                  osdn->target = FC_SCSID(nlp->id.nlp_pan, nlp->id.nlp_sid);
                  osdn->lun = (HBA_UINT32)(lunId);
                  osdn->flags = 0;
                  ep->ScsiId.ScsiTargetNumber =
                     FC_SCSID(nlp->id.nlp_pan, nlp->id.nlp_sid);
                  ep->ScsiId.ScsiOSLun = (HBA_UINT32)(lunId);
                  ep->ScsiId.ScsiBusNumber = 0;
                  ep->FcpId.FcId = nlp->nlp_DID;
                  fc_bzero((char *)fcpLun, sizeof(HBA_UINT64));

                  fcpLun[0] = (lunId << FC_LUN_SHIFT);
                  if (nodep->addr_mode == VOLUME_SET_ADDRESSING) {
                     fcpLun[0] |= SWAP_DATA(0x40000000);
                  }
                  fc_bcopy((char *)&fcpLun[0], (char *)&ep->FcpId.FcpLun, sizeof(HBA_UINT64));
                  fc_bcopy(&nlp->nlp_portname, (uchar *)&ep->FcpId.PortWWN, sizeof(HBA_WWN));
                  fc_bcopy(&nlp->nlp_nodename, (uchar *)&ep->FcpId.NodeWWN, sizeof(HBA_WWN));
                  cnt++;
                  ep++;
                  memsz = memsz + sizeof(HBA_FCPSCSIENTRY);
               }
               total++;
            }
	    lunIndex++;
         }
         nlp = (NODELIST *)nlp->nlp_listp_next;
      }
      dfc_unlock_enable(ipri, &CMD_LOCK);
      fc_copyout((char *)(&hf->entry[0]), appPtr,memsz);
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

      hf->NumberOfEntries = (HBA_UINT32)total;
      dfc_unlock_enable(ipri, &CMD_LOCK);
      fc_copyout((char *)(&hf->NumberOfEntries), infop->c_dataout, sizeof(ulong));
      ipri = dfc_disable_lock(FC_LVL, &CMD_LOCK);

      infop->c_outsz = 0;                /* no more copy needed */ 
      if (total > room) {
         rc = ERANGE;
         do_cp = 1;
      }
      return(ipri);
}

int
dfc_data_alloc(
fc_dev_ctl_t * p_dev_ctl,
struct dfc_mem *dm,
uint32 size)
{
   static FC_BRD_INFO     * binfo;
#ifndef powerpc
   static MBUF_INFO       * buf_info;
   static MBUF_INFO       bufinfo;
#endif

   binfo = &BINFO;

   if(dm->fc_dataout)
      return(EACCES);

#ifdef powerpc
   dm->fc_dataout = p_dev_ctl->dfc_kernel_buf; 
   dm->fc_outsz = size;
#else
   size = ((size + 0xfff) & 0xfffff000);
   buf_info = &bufinfo;
   buf_info->virt = 0;
   buf_info->phys = 0;
   buf_info->flags  = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
   buf_info->align = sizeof(void *);
   buf_info->size = (int)size;
   buf_info->dma_handle = 0;

   fc_malloc(p_dev_ctl, buf_info);
   if (buf_info->virt == NULL) {
      return(ENOMEM);
   }
   dm->fc_dataout = buf_info->virt;
   dm->fc_outsz = size;
   /* dfc_data_alloc */
   fc_log_printf_msg_vargs( binfo->fc_brd_no,
          &fc_msgBlk0402,                   /* ptr to msg structure */
           fc_mes0402,                      /* ptr to msg */
            fc_msgBlk0402.msgPreambleStr,   /* begin varargs */
             (uint32)((ulong)dm->fc_dataout),
               dm->fc_outsz);               /* end varargs */
#endif

   return(0);
}

int
dfc_data_free(
fc_dev_ctl_t * p_dev_ctl,
struct dfc_mem *dm)
{
   static FC_BRD_INFO     * binfo;
#ifndef powerpc
   static MBUF_INFO       * buf_info;
   static MBUF_INFO       bufinfo;
#endif

   binfo = &BINFO;

   /* dfc_data_free */
   fc_log_printf_msg_vargs( binfo->fc_brd_no,
          &fc_msgBlk0403,                   /* ptr to msg structure */
           fc_mes0403,                      /* ptr to msg */
            fc_msgBlk0403.msgPreambleStr,   /* begin varargs */
             (uint32)((ulong)dm->fc_dataout),
               dm->fc_outsz);               /* end varargs */
   if(dm->fc_dataout == 0)
      return(EACCES);

#ifdef powerpc
   dm->fc_dataout = 0;
   dm->fc_outsz = 0;
#else
   buf_info = &bufinfo;
   buf_info->virt = dm->fc_dataout;
   buf_info->size = dm->fc_outsz;
   buf_info->phys = 0;
   buf_info->flags = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
   buf_info->align = 0;
   buf_info->dma_handle = 0;
   fc_free(p_dev_ctl, buf_info);
   dm->fc_dataout = 0;
   dm->fc_outsz = 0;
#endif
   return(0);
}

DMATCHMAP *
dfc_cmd_data_alloc(
fc_dev_ctl_t * p_dev_ctl,
uchar        * indataptr,
ULP_BDE64    * bpl,
uint32         size)
{
   static FC_BRD_INFO     * binfo;
   static MBUF_INFO       * buf_info;
   static MBUF_INFO       bufinfo;
   static DMATCHMAP       * mlist;
   static DMATCHMAP       * mlast;
   static DMATCHMAP       * dmp;
   static int               cnt, offset, i;

   binfo = &BINFO;
   buf_info = &bufinfo;
   mlist = 0;
   mlast = 0;
   i = 0;
   offset = 0;

   while(size) {

      if(size > 4096)
         cnt = 4096;
      else
         cnt = size;

      /* allocate DMATCHMAP buffer header */
      buf_info->virt = 0;
      buf_info->phys = 0;
      buf_info->flags  = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
      buf_info->align = (int)sizeof(long);
      buf_info->size = (int)sizeof(DMATCHMAP);
      buf_info->dma_handle = 0;

      fc_malloc(p_dev_ctl, buf_info);

      if (buf_info->virt == NULL) {
         goto out;
      }
      dmp = buf_info->virt;
      dmp->dfc.fc_mptr = 0;
      dmp->dfc.virt = 0;

      /* Queue it to a linked list */
      if(mlast == 0) {
         mlist = dmp;
         mlast = dmp;
      }
      else {
         mlast->dfc.fc_mptr = (uchar *)dmp;
         mlast = dmp;
      }
      dmp->dfc.fc_mptr = 0;

      /* allocate buffer */
      buf_info->virt = 0;
      buf_info->phys = 0;
      buf_info->flags  = (FC_MBUF_DMA | FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
      buf_info->align = (int)4096;
      buf_info->size = (int)cnt;
      buf_info->dma_handle = 0;

      fc_malloc(p_dev_ctl, buf_info);

      if (buf_info->phys == NULL) {
         goto out;
      }
      dmp->dfc.virt = buf_info->virt;
      if (buf_info->dma_handle) {
         dmp->dfc.dma_handle = buf_info->dma_handle;
         dmp->dfc.data_handle = buf_info->data_handle;
      }
      dmp->dfc.phys = (uchar * )buf_info->phys;
      dmp->dfc_size = cnt;

      if(indataptr) {
         /* Copy data from user space in */
         if (fc_copyin((indataptr+offset), (uchar *)dmp->dfc.virt, (ulong)cnt)) {
            goto out;
         }
         bpl->tus.f.bdeFlags = 0;
         fc_mpdata_sync(dmp->dfc.dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV);
      }
      else {
         bpl->tus.f.bdeFlags = BUFF_USE_RCV;
      }

      /* build buffer ptr list for IOCB */
      bpl->addrLow = PCIMEM_LONG(putPaddrLow((ulong)dmp->dfc.phys));
      bpl->addrHigh = PCIMEM_LONG(putPaddrHigh((ulong)dmp->dfc.phys));
      bpl->tus.f.bdeSize = (ushort)cnt;
      bpl->tus.w = PCIMEM_LONG(bpl->tus.w);
      bpl++;

      i++;
      offset += cnt;
      size -= cnt;
   }

   mlist->dfc_flag = i;
   return(mlist);
out:
   dfc_cmd_data_free(p_dev_ctl, mlist);
   return(0);
}

DMATCHMAP *
dfc_fcp_data_alloc(
fc_dev_ctl_t * p_dev_ctl,
ULP_BDE64    * bpl)
{
   static DMATCHMAP       * fcpmp;
   static fc_buf_t        * fcptr;
   static FC_BRD_INFO     * binfo;
   static MBUF_INFO       * buf_info;
   static MBUF_INFO       bufinfo;

   binfo = &BINFO;
   buf_info = &bufinfo;

   /* allocate DMATCHMAP buffer header */
   buf_info->virt = 0;
   buf_info->phys = 0;
   buf_info->flags  = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
   buf_info->align = (int)sizeof(long);
   buf_info->size = (int)sizeof(DMATCHMAP);
   buf_info->dma_handle = 0;

   fc_malloc(p_dev_ctl, buf_info);

   if (buf_info->virt == NULL) {
      return(0);
   }
   fcpmp = buf_info->virt;
   fc_bzero((char *)fcpmp, sizeof(DMATCHMAP));

   /* allocate buffer */
   buf_info->virt = 0;
   buf_info->phys = 0;
   buf_info->flags  = (FC_MBUF_DMA | FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
   buf_info->align = (int)4096;
   buf_info->size = (int)4096;
   buf_info->dma_handle = 0;

   fc_malloc(p_dev_ctl, buf_info);

   if (buf_info->phys == NULL) {
      buf_info->flags  = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
      buf_info->size = (int)sizeof(DMATCHMAP);
      buf_info->virt = (uint32 * )fcpmp;
      buf_info->phys = (uint32 * )0;
      buf_info->dma_handle = 0;
      buf_info->data_handle = 0;
      fc_free(p_dev_ctl, buf_info);
      return(0);
   }
   fcpmp->dfc.virt = buf_info->virt;
   if (buf_info->dma_handle) {
      fcpmp->dfc.dma_handle = buf_info->dma_handle;
      fcpmp->dfc.data_handle = buf_info->data_handle;
   }
   fcpmp->dfc.phys = (uchar * )buf_info->phys;
   fcpmp->dfc_size = 4096;
   fc_bzero((char *)fcpmp->dfc.virt, 4096);

   fcptr = (fc_buf_t *)fcpmp->dfc.virt;
   fcptr->phys_adr = (char *)fcpmp->dfc.phys;

   bpl->addrHigh = PCIMEM_LONG((uint32)putPaddrHigh(GET_PAYLOAD_PHYS_ADDR(fcptr)));
   bpl->addrLow = PCIMEM_LONG((uint32)putPaddrLow(GET_PAYLOAD_PHYS_ADDR(fcptr)));
   bpl->tus.f.bdeSize = sizeof(FCP_CMND);
   bpl->tus.f.bdeFlags = BUFF_USE_CMND;
   bpl->tus.w = PCIMEM_LONG(bpl->tus.w);
   bpl++;
   bpl->addrHigh = PCIMEM_LONG((uint32)putPaddrHigh(GET_PAYLOAD_PHYS_ADDR(fcptr)+sizeof(FCP_CMND)));
   bpl->addrLow = PCIMEM_LONG((uint32)putPaddrLow(GET_PAYLOAD_PHYS_ADDR(fcptr)+sizeof(FCP_CMND)));
   bpl->tus.f.bdeSize = sizeof(FCP_RSP);
   bpl->tus.f.bdeFlags = (BUFF_USE_CMND | BUFF_USE_RCV);
   bpl->tus.w = PCIMEM_LONG(bpl->tus.w);
   return(fcpmp);
}

int
dfc_fcp_data_free(
fc_dev_ctl_t * p_dev_ctl,
DMATCHMAP    * fcpmp)
{
   static FC_BRD_INFO     * binfo;
   static MBUF_INFO       * buf_info;
   static MBUF_INFO       bufinfo;

   binfo = &BINFO;
   buf_info = &bufinfo;

   if(fcpmp->dfc.virt) {
      buf_info->size = fcpmp->dfc_size;
      buf_info->virt = (uint32 * )fcpmp->dfc.virt;
      buf_info->phys = (uint32 * )fcpmp->dfc.phys;
      buf_info->flags  = (FC_MBUF_DMA | FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
      if (fcpmp->dfc.dma_handle) {
         buf_info->dma_handle = fcpmp->dfc.dma_handle;
         buf_info->data_handle = fcpmp->dfc.data_handle;
      }
      fc_free(p_dev_ctl, buf_info);
   }
   buf_info->flags  = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
   buf_info->size = (int)sizeof(DMATCHMAP);
   buf_info->virt = (uint32 * )fcpmp;
   buf_info->phys = (uint32 * )0;
   buf_info->dma_handle = 0;
   buf_info->data_handle = 0;
   fc_free(p_dev_ctl, buf_info);

   return(0);
}

int
dfc_rsp_data_copy(
fc_dev_ctl_t * p_dev_ctl,
uchar        * outdataptr,
DMATCHMAP    * mlist,
uint32         size)
{
   static FC_BRD_INFO     * binfo;
   static DMATCHMAP       * mlast;
   static int               cnt, offset;

   binfo = &BINFO;
   mlast = 0;
   offset = 0;

   while(mlist && size) {
      if(size > 4096)
         cnt = 4096;
      else
         cnt = size;

      mlast = mlist;
      mlist = (DMATCHMAP *)mlist->dfc.fc_mptr;

      if(outdataptr) {
         fc_mpdata_sync(mlast->dfc.dma_handle, 0, 0, DDI_DMA_SYNC_FORKERNEL);
         /* Copy data to user space */
         if (fc_copyout((uchar *)mlast->dfc.virt, (outdataptr+offset), (ulong)cnt)) {
            return(1);
         }
      }
      offset += cnt;
      size -= cnt;
   }
   return(0);
}

int
dfc_cmd_data_free(
fc_dev_ctl_t * p_dev_ctl,
DMATCHMAP       * mlist)
{
   static FC_BRD_INFO     * binfo;
   static MBUF_INFO       * buf_info;
   static MBUF_INFO       bufinfo;
   static DMATCHMAP       * mlast;

   binfo = &BINFO;
   buf_info = &bufinfo;
   while(mlist) {
      mlast = mlist;
      mlist = (DMATCHMAP *)mlist->dfc.fc_mptr;
      if(mlast->dfc.virt) {
         buf_info->size = mlast->dfc_size;
         buf_info->virt = (uint32 * )mlast->dfc.virt;
         buf_info->phys = (uint32 * )mlast->dfc.phys;
         buf_info->flags  = (FC_MBUF_DMA | FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
         if (mlast->dfc.dma_handle) {
            buf_info->dma_handle = mlast->dfc.dma_handle;
            buf_info->data_handle = mlast->dfc.data_handle;
         }
         fc_free(p_dev_ctl, buf_info);
      }
      buf_info->flags  = (FC_MBUF_IOCTL | FC_MBUF_UNLOCK);
      buf_info->size = (int)sizeof(DMATCHMAP);
      buf_info->virt = (uint32 * )mlast;
      buf_info->phys = (uint32 * )0;
      buf_info->dma_handle = 0;
      buf_info->data_handle = 0;
      fc_free(p_dev_ctl, buf_info);
   }
   return(0);
}


_static_ int
dfc_fmw_rev(
fc_dev_ctl_t * p_dev_ctl)
{
   FC_BRD_INFO     * binfo;
   struct dfc_info     * di;

   binfo = &BINFO;
   di = &dfc.dfc_info[binfo->fc_brd_no];
   decode_firmware_rev( binfo, &VPD);
   fc_bcopy((uchar *)fwrevision, di->fc_ba.a_fwname, 32);
   return(0);
}


#else  /* DFC_SUBSYSTEM */

_static_ int
dfc_ioctl(
struct dfccmdinfo *infop,
struct cmd_input *cip)
{
   return (ENODEV);
}

int
dfc_put_event(
fc_dev_ctl_t * p_dev_ctl,
uint32 evcode,
uint32 evdata0,
void * evdata1,
void * evdata2)
{
   return(0);
}

int
dfc_hba_put_event(
fc_dev_ctl_t * p_dev_ctl,
uint32 evcode,
uint32 evdata1,
uint32 evdata2,
uint32 evdata3,
uint32 evdata4)
{
   return(0);
}       /* End dfc_hba_put_event */

_static_ int
dfc_fmw_rev(
fc_dev_ctl_t * p_dev_ctl)
{
   return(0);
}

#endif /* DFC_SUBSYSTEM */

