arcmsr(4): Upgrade to Areca's Revision 1.40.00.00.
authorSascha Wildner <saw@online.de>
Mon, 6 Nov 2017 10:06:59 +0000 (11:06 +0100)
committerSascha Wildner <saw@online.de>
Mon, 6 Nov 2017 10:07:18 +0000 (11:07 +0100)
This adds support for various adapters: ARC1203, ARC1216, ARC1226, and
ARC1884.

Detailed list of changes:

1. fix ADAPTER_TYPE_D scanning device timeout.
2. fix ADAPTER_TYPE_D getting configuration data.
3. eliminate ending white-space of code.
4. align some code for more readable.
5. modify code of ADAPTER_TYPE_B for support ARC-1203
6. add a new ADAPTER_TYPE_E for support ARC-1884
7. adapter ARC-1215, 1225, 1216, 1226 are belong to ADAPTER_TYPE_C
   also support in this driver.
8. redefine ADAPTER_TYPE_A,B,C,D value

Thanks to Areca for actively supporting DragonFly!!

Submitted-by: Ching Huang <ching2048@areca.com.tw>
Tested-by: kerma (Michael)
share/man/man4/arcmsr.4
sys/dev/raid/arcmsr/arcmsr.c
sys/dev/raid/arcmsr/arcmsr.h

index 4430944..5317916 100644 (file)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD: head/share/man/man4/arcmsr.4 259564 2013-12-18 19:23:05Z delphij $
 .\"
-.Dd February 25, 2014
+.Dd November 6, 2017
 .Dt ARCMSR 4
 .Os
 .Sh NAME
@@ -100,6 +100,8 @@ ARC-1200
 .It
 ARC-1201
 .It
+ARC-1203
+.It
 ARC-1210
 .It
 ARC-1212
@@ -108,6 +110,8 @@ ARC-1213
 .It
 ARC-1214
 .It
+ARC-1216
+.It
 ARC-1220
 .It
 ARC-1222
@@ -116,6 +120,8 @@ ARC-1223
 .It
 ARC-1224
 .It
+ARC-1226
+.It
 ARC-1230
 .It
 ARC-1231
@@ -169,6 +175,8 @@ ARC-1880ixl
 ARC-1882
 .It
 ARC-1883
+.It
+ARC-1884
 .El
 .Sh FILES
 .Bl -tag -width ".Pa /dev/arcmsr?" -compact
index 1ee5036..78b14b1 100644 (file)
 ** 1.20.00.02   11/29/2004  Erich Chen      bug fix with arcmsr_bus_reset when PHY error
 ** 1.20.00.03   04/19/2005  Erich Chen      add SATA 24 Ports adapter type support
 **                                          clean unused function
-** 1.20.00.12   09/12/2005  Erich Chen      bug fix with abort command handling, 
-**                                          firmware version check 
+** 1.20.00.12   09/12/2005  Erich Chen      bug fix with abort command handling,
+**                                          firmware version check
 **                                          and firmware update notify for hardware bug fix
-**                                          handling if none zero high part physical address 
-**                                          of srb resource 
+**                                          handling if none zero high part physical address
+**                                          of srb resource
 ** 1.20.00.13   08/18/2006  Erich Chen      remove pending srb and report busy
-**                                          add iop message xfer 
+**                                          add iop message xfer
 **                                          with scsi pass-through command
-**                                          add new device id of sas raid adapters 
-**                                          code fit for SPARC64 & PPC 
+**                                          add new device id of sas raid adapters
+**                                          code fit for SPARC64 & PPC
 ** 1.20.00.14   02/05/2007  Erich Chen      bug fix for incorrect ccb_h.status report
 **                                          and cause g_vfs_done() read write error
 ** 1.20.00.15   10/10/2007  Erich Chen      support new RAID adapter type ARC120x
@@ -67,8 +67,8 @@
 **              02/14/2011  Ching Huang     Modified pktRequestCount
 ** 1.20.00.21   03/03/2011  Ching Huang     if a command timeout, then wait its ccb back before free it
 ** 1.20.00.22   07/04/2011  Ching Huang     Fixed multiple MTX panic
-** 1.20.00.23   10/28/2011  Ching Huang     Added TIMEOUT_DELAY in case of too many HDDs need to start 
-** 1.20.00.23   11/08/2011  Ching Huang     Added report device transfer speed 
+** 1.20.00.23   10/28/2011  Ching Huang     Added TIMEOUT_DELAY in case of too many HDDs need to start
+** 1.20.00.23   11/08/2011  Ching Huang     Added report device transfer speed
 ** 1.20.00.23   01/30/2012  Ching Huang     Fixed Request requeued and Retrying command
 ** 1.20.00.24   06/11/2012  Ching Huang     Fixed return sense data condition
 ** 1.20.00.25   08/17/2012  Ching Huang     Fixed hotplug device no function on type A adapter
 ** 1.20.00.27   05/06/2013  Ching Huang     Fixed out standing cmd full on ARC-12x4
 ** 1.20.00.28   09/13/2013  Ching Huang     Removed recursive mutex in arcmsr_abort_dr_ccbs
 ** 1.20.00.29   12/18/2013  Ching Huang     Change simq allocation number, support ARC1883
+** 1.30.00.00   11/30/2015  Ching Huang     Added support ARC1203
+** 1.40.00.00   10/26/2017  Ching Huang     Added support ARC1884
 ******************************************************************************************
 * $FreeBSD: head/sys/dev/arcmsr/arcmsr.c 259565 2013-12-18 19:25:40Z delphij $
 */
 #if 0
-#define ARCMSR_DEBUG1                  1
+#define ARCMSR_DEBUG1          1
 #endif
 #include <sys/param.h>
 #include <sys/systm.h>
 
 #define arcmsr_callout_init(a) callout_init_mp(a);
 
-#define ARCMSR_DRIVER_VERSION  "arcmsr version 1.20.00.29 2013-12-18"
+#define ARCMSR_DRIVER_VERSION  "arcmsr version 1.40.00.00 2017-10-26"
 #include <dev/raid/arcmsr/arcmsr.h>
 /*
 **************************************************************************
@@ -158,9 +160,11 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *p
 static int arcmsr_resume(device_t dev);
 static int arcmsr_suspend(device_t dev);
 static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb);
-static void    arcmsr_polling_devmap(void *arg);
-static void    arcmsr_srb_timeout(void *arg);
+static void arcmsr_polling_devmap(void *arg);
+static void arcmsr_srb_timeout(void *arg);
 static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb);
+static void arcmsr_hbe_postqueue_isr(struct AdapterControlBlock *acb);
+static void arcmsr_teardown_intr(device_t dev, struct AdapterControlBlock *acb);
 #ifdef ARCMSR_DEBUG1
 static void arcmsr_dump_data(struct AdapterControlBlock *acb);
 #endif
@@ -190,6 +194,8 @@ static device_method_t arcmsr_methods[]={
        DEVMETHOD(device_shutdown,      arcmsr_shutdown),
        DEVMETHOD(device_suspend,       arcmsr_suspend),
        DEVMETHOD(device_resume,        arcmsr_resume),
+       DEVMETHOD(bus_print_child,      bus_generic_print_child),
+       DEVMETHOD(bus_driver_added,     bus_generic_driver_added),
        DEVMETHOD_END
 };
 
@@ -205,23 +211,20 @@ MODULE_DEPEND(arcmsr, cam, 1, 1, 1);
 #ifndef BUS_DMA_COHERENT
        #define BUS_DMA_COHERENT        0x04    /* hint: map memory in a coherent way */
 #endif
-
 static struct dev_ops arcmsr_ops = {
        { "arcmsr", 0, D_MPSAFE },
-       .d_open =       arcmsr_open,                    /* open     */
-       .d_close =      arcmsr_close,                   /* close    */
-       .d_ioctl =      arcmsr_ioctl,                   /* ioctl    */
+       .d_open    = arcmsr_open,       /* open     */
+       .d_close   = arcmsr_close,      /* close    */
+       .d_ioctl   = arcmsr_ioctl,      /* ioctl    */
 };
 
 static int     arcmsr_msi_enable = 1;
 TUNABLE_INT("hw.arcmsr.msi.enable", &arcmsr_msi_enable);
 
-
 /*
 **************************************************************************
 **************************************************************************
 */
-
 static int
 arcmsr_open(struct dev_open_args *ap)
 {
@@ -233,12 +236,10 @@ arcmsr_open(struct dev_open_args *ap)
        }
        return (0);
 }
-
 /*
 **************************************************************************
 **************************************************************************
 */
-
 static int
 arcmsr_close(struct dev_close_args *ap)
 {
@@ -250,12 +251,10 @@ arcmsr_close(struct dev_close_args *ap)
        }
        return 0;
 }
-
 /*
 **************************************************************************
 **************************************************************************
 */
-
 static int
 arcmsr_ioctl(struct dev_ioctl_args *ap)
 {
@@ -269,7 +268,6 @@ arcmsr_ioctl(struct dev_ioctl_args *ap)
        }
        return (arcmsr_iop_ioctlcmd(acb, ioctl_cmd, arg));
 }
-
 /*
 **********************************************************************
 **********************************************************************
@@ -286,10 +284,11 @@ static u_int32_t arcmsr_disable_allintr( struct AdapterControlBlock *acb)
                }
                break;
        case ACB_ADAPTER_TYPE_B: {
+                       struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
                        /* disable all outbound interrupt */
-                       intmask_org = CHIP_REG_READ32(HBB_DOORBELL, 
-                       0, iop2drv_doorbell_mask) & (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); /* disable outbound message0 int */
-                       CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell_mask, 0); /* disable all interrupt */
+                       intmask_org = READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask)
+                                               & (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); /* disable outbound message0 int */
+                       WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask, 0); /* disable all interrupt */
                }
                break;
        case ACB_ADAPTER_TYPE_C: {
@@ -304,6 +303,12 @@ static u_int32_t arcmsr_disable_allintr( struct AdapterControlBlock *acb)
                        CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, ARCMSR_HBDMU_ALL_INT_DISABLE);
                }
                break;
+       case ACB_ADAPTER_TYPE_E: {
+                       /* disable all outbound interrupt */
+                       intmask_org = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_mask)        ; /* disable outbound message0 int */
+                       CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_mask, intmask_org | ARCMSR_HBEMU_ALL_INTMASKENABLE);
+               }
+               break;
        }
        return (intmask_org);
 }
@@ -324,9 +329,10 @@ static void arcmsr_enable_allintr( struct AdapterControlBlock *acb, u_int32_t in
                }
                break;
        case ACB_ADAPTER_TYPE_B: {
+                       struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
                        /* enable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */
                        mask = (ARCMSR_IOP2DRV_DATA_WRITE_OK|ARCMSR_IOP2DRV_DATA_READ_OK|ARCMSR_IOP2DRV_CDB_DONE|ARCMSR_IOP2DRV_MESSAGE_CMD_DONE);
-                       CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell_mask, intmask_org | mask); /*1=interrupt enable, 0=interrupt disable*/
+                       WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask, intmask_org | mask); /*1=interrupt enable, 0=interrupt disable*/
                        acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f;
                }
                break;
@@ -345,6 +351,13 @@ static void arcmsr_enable_allintr( struct AdapterControlBlock *acb, u_int32_t in
                        acb->outbound_int_enable = mask;
                }
                break;
+       case ACB_ADAPTER_TYPE_E: {
+                       /* enable outbound Post Queue, outbound doorbell Interrupt */
+                       mask = ~(ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR | ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR);
+                       CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_mask, intmask_org & mask);
+                       acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f;
+               }
+               break;
        }
 }
 /*
@@ -375,12 +388,13 @@ static u_int8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb)
 {
        u_int32_t Index;
        u_int8_t Retries = 0x00;
+       struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
 
        do {
                for(Index=0; Index < 100; Index++) {
-                       if(CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
-                               CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/
-                               CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
+                       if(READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
+                               WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/
+                               WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
                                return TRUE;
                        }
                        UDELAY(10000);
@@ -416,7 +430,7 @@ static u_int8_t arcmsr_hbd_wait_msgint_ready(struct AdapterControlBlock *acb)
 {
        u_int32_t Index;
        u_int8_t Retries = 0x00;
-       
+
        do {
                for(Index=0; Index < 100; Index++) {
                        if(CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) {
@@ -429,6 +443,28 @@ static u_int8_t arcmsr_hbd_wait_msgint_ready(struct AdapterControlBlock *acb)
        return (FALSE);
 }
 /*
+**********************************************************************
+**********************************************************************
+*/
+static u_int8_t arcmsr_hbe_wait_msgint_ready(struct AdapterControlBlock *acb)
+{
+       u_int32_t Index, read_doorbell;
+       u_int8_t Retries = 0x00;
+
+       do {
+               for(Index=0; Index < 100; Index++) {
+                       read_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell);
+                       if((read_doorbell ^ acb->in_doorbell) & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) {
+                               CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0);/*clear interrupt*/
+                               acb->in_doorbell = read_doorbell;
+                               return TRUE;
+                       }
+                       UDELAY(10000);
+               }/*max 1 seconds*/
+       }while(Retries++ < 20);/*max 20 sec*/
+       return (FALSE);
+}
+/*
 ************************************************************************
 ************************************************************************
 */
@@ -452,9 +488,9 @@ static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb)
 static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb)
 {
        int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */
+       struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
 
-       CHIP_REG_WRITE32(HBB_DOORBELL,
-       0, drv2iop_doorbell, ARCMSR_MESSAGE_FLUSH_CACHE);
+       WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_FLUSH_CACHE);
        do {
                if(arcmsr_hbb_wait_msgint_ready(acb)) {
                        break;
@@ -488,7 +524,7 @@ static void arcmsr_flush_hbc_cache(struct AdapterControlBlock *acb)
 static void arcmsr_flush_hbd_cache(struct AdapterControlBlock *acb)
 {
        int retry_count = 30; /* enlarge wait flush adapter cache time: 10 minute */
-       
+
        CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
        do {
                if(arcmsr_hbd_wait_msgint_ready(acb)) {
@@ -502,6 +538,25 @@ static void arcmsr_flush_hbd_cache(struct AdapterControlBlock *acb)
 ************************************************************************
 ************************************************************************
 */
+static void arcmsr_flush_hbe_cache(struct AdapterControlBlock *acb)
+{
+       int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */
+
+       CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
+       acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+       CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+       do {
+               if(arcmsr_hbe_wait_msgint_ready(acb)) {
+                       break;
+               } else {
+                       retry_count--;
+               }
+       }while(retry_count != 0);
+}
+/*
+************************************************************************
+************************************************************************
+*/
 static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
 {
        switch (acb->adapter_type) {
@@ -521,6 +576,10 @@ static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
                        arcmsr_flush_hbd_cache(acb);
                }
                break;
+       case ACB_ADAPTER_TYPE_E: {
+                       arcmsr_flush_hbe_cache(acb);
+               }
+               break;
        }
 }
 /*
@@ -549,31 +608,6 @@ static int arcmsr_resume(device_t dev)
        return(0);
 }
 /*
-*********************************************************************************
-*********************************************************************************
-*/
-static void arcmsr_async(void *cb_arg, u_int32_t code, struct cam_path *path, void *arg)
-{
-       struct AdapterControlBlock *acb;
-       u_int8_t target_id, target_lun;
-       struct cam_sim *sim;
-       
-       sim = (struct cam_sim *) cb_arg;
-       acb =(struct AdapterControlBlock *) cam_sim_softc(sim);
-       switch (code) {
-       case AC_LOST_DEVICE:
-               target_id = xpt_path_target_id(path);
-               target_lun = xpt_path_lun_id(path);
-               if((target_id > ARCMSR_MAX_TARGETID) || (target_lun > ARCMSR_MAX_TARGETLUN)) {
-                       break;
-               }
-       //      printf("%s:scsi id=%d lun=%d device lost \n", device_get_name(acb->pci_dev), target_id, target_lun);
-               break;
-       default:
-               break;
-       }
-}
-/*
 **********************************************************************
 **********************************************************************
 */
@@ -608,7 +642,8 @@ static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb)
 */
 static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb)
 {
-       CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_ABORT_CMD);
+       struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
+       WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_ABORT_CMD);
        if(!arcmsr_hbb_wait_msgint_ready(acb)) {
                kprintf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
        }
@@ -640,6 +675,19 @@ static void arcmsr_abort_hbd_allcmd(struct AdapterControlBlock *acb)
 *********************************************************************
 *********************************************************************
 */
+static void arcmsr_abort_hbe_allcmd(struct AdapterControlBlock *acb)
+{
+       CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD);
+       acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+       CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+       if(!arcmsr_hbe_wait_msgint_ready(acb)) {
+               kprintf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
+       }
+}
+/*
+*********************************************************************
+*********************************************************************
+*/
 static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb)
 {
        switch (acb->adapter_type) {
@@ -659,6 +707,10 @@ static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb)
                        arcmsr_abort_hbd_allcmd(acb);
                }
                break;
+       case ACB_ADAPTER_TYPE_E: {
+                       arcmsr_abort_hbe_allcmd(acb);
+               }
+               break;
        }
 }
 /*
@@ -681,7 +733,9 @@ static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag)
                        op = BUS_DMASYNC_POSTWRITE;
                }
                bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op);
+               ARCMSR_LOCK_ACQUIRE(&acb->io_lock);
                bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap);
+               ARCMSR_LOCK_RELEASE(&acb->io_lock);
        }
        if(stand_flag == 1) {
                atomic_subtract_int(&acb->srboutstandingcount, 1);
@@ -694,7 +748,9 @@ static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag)
        if(srb->srb_state != ARCMSR_SRB_TIMEOUT)
                arcmsr_free_srb(srb);
        acb->pktReturnCount++;
+       ARCMSR_LOCK_ACQUIRE(&acb->sim_lock);
        xpt_done(pccb);
+       ARCMSR_LOCK_RELEASE(&acb->sim_lock);
 }
 /*
 **************************************************************************
@@ -761,6 +817,9 @@ static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t fl
        case ACB_ADAPTER_TYPE_D:
                srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0)); /*frame must be 32 bytes aligned*/
                break;
+       case ACB_ADAPTER_TYPE_E:
+               srb = acb->psrb_pool[flag_srb];
+               break;
        case ACB_ADAPTER_TYPE_A:
        case ACB_ADAPTER_TYPE_B:
        default:
@@ -826,7 +885,7 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
                        outbound_intstatus = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable;
                        CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/
                        while(((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_queueport)) != 0xFFFFFFFF) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) {
-                error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
+                               error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
                                arcmsr_drain_donequeue(acb, flag_srb, error);
                        }
                }
@@ -835,11 +894,11 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
                        struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu;
 
                        /*clear all outbound posted Q*/
-                       CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */
+                       WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */
                        for(i=0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) {
                                if((flag_srb = phbbmu->done_qbuffer[i]) != 0) {
                                        phbbmu->done_qbuffer[i] = 0;
-                       error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
+                                       error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
                                        arcmsr_drain_donequeue(acb, flag_srb, error);
                                }
                                phbbmu->post_qbuffer[i] = 0;
@@ -852,7 +911,7 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
 
                        while((CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) {
                                flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low);
-                error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
+                               error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
                                arcmsr_drain_donequeue(acb, flag_srb, error);
                        }
                }
@@ -861,6 +920,10 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
                        arcmsr_hbd_postqueue_isr(acb);
                }
                break;
+       case ACB_ADAPTER_TYPE_E: {
+                       arcmsr_hbe_postqueue_isr(acb);
+               }
+               break;
        }
 }
 /*
@@ -984,8 +1047,8 @@ static void arcmsr_build_srb(struct CommandControlBlock *srb,
        } else {
                arcmsr_cdb->DataLength = 0;
        }
-    srb->arc_cdb_size = arccdbsize;
-    arcmsr_cdb->msgPages = (arccdbsize/256) + ((arccdbsize % 256) ? 1 : 0);
+       srb->arc_cdb_size = arccdbsize;
+       arcmsr_cdb->msgPages = (arccdbsize/256) + ((arccdbsize % 256) ? 1 : 0);
 }
 /*
 **************************************************************************
@@ -1024,26 +1087,26 @@ static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandContr
                        index++;
                        index %= ARCMSR_MAX_HBB_POSTQUEUE;     /*if last index number set it to 0 */
                        phbbmu->postq_index = index;
-                       CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED);
+                       WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED);
                }
                break;
-    case ACB_ADAPTER_TYPE_C: {
-            u_int32_t ccb_post_stamp, arc_cdb_size, cdb_phyaddr_hi32;
+       case ACB_ADAPTER_TYPE_C: {
+                       u_int32_t ccb_post_stamp, arc_cdb_size, cdb_phyaddr_hi32;
 
-            arc_cdb_size = (srb->arc_cdb_size > 0x300) ? 0x300 : srb->arc_cdb_size;
-            ccb_post_stamp = (cdb_phyaddr_low | ((arc_cdb_size-1) >> 6) | 1);
+                       arc_cdb_size = (srb->arc_cdb_size > 0x300) ? 0x300 : srb->arc_cdb_size;
+                       ccb_post_stamp = (cdb_phyaddr_low | ((arc_cdb_size-1) >> 6) | 1);
                        cdb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high;
-            if(cdb_phyaddr_hi32)
-            {
-                           CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_high, cdb_phyaddr_hi32);
-                           CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp);
-            }
-            else
-            {
-                           CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp);
-            }
-        }
-        break;
+                       if(cdb_phyaddr_hi32)
+                       {
+                               CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_high, cdb_phyaddr_hi32);
+                               CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp);
+                       }
+                       else
+                       {
+                               CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp);
+                       }
+               }
+               break;
        case ACB_ADAPTER_TYPE_D: {
                        struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
                        u_int16_t index_stripped;
@@ -1072,6 +1135,15 @@ static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandContr
                        ARCMSR_LOCK_RELEASE(&acb->postDone_lock);
                }
                break;
+       case ACB_ADAPTER_TYPE_E: {
+                       u_int32_t ccb_post_stamp, arc_cdb_size;
+
+                       arc_cdb_size = (srb->arc_cdb_size > 0x300) ? 0x300 : srb->arc_cdb_size;
+                       ccb_post_stamp = (srb->smid | ((arc_cdb_size-1) >> 6));
+                       CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_queueport_high, 0);
+                       CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_queueport_low, ccb_post_stamp);
+               }
+               break;
        }
 }
 /*
@@ -1103,10 +1175,16 @@ static struct QBUFFER *arcmsr_get_iop_rqbuffer( struct AdapterControlBlock *acb)
                break;
        case ACB_ADAPTER_TYPE_D: {
                        struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
-       
+
                        qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_rbuffer;
                }
                break;
+       case ACB_ADAPTER_TYPE_E: {
+                       struct HBE_MessageUnit *phbcmu = (struct HBE_MessageUnit *)acb->pmu;
+
+                       qbuffer = (struct QBUFFER *)&phbcmu->message_rbuffer;
+               }
+               break;
        }
        return(qbuffer);
 }
@@ -1139,10 +1217,16 @@ static struct QBUFFER *arcmsr_get_iop_wqbuffer( struct AdapterControlBlock *acb)
                break;
        case ACB_ADAPTER_TYPE_D: {
                        struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
-       
+
                        qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_wbuffer;
                }
                break;
+       case ACB_ADAPTER_TYPE_E: {
+                       struct HBE_MessageUnit *phbcmu = (struct HBE_MessageUnit *)acb->pmu;
+
+                       qbuffer = (struct QBUFFER *)&phbcmu->message_wbuffer;
+               }
+               break;
        }
        return(qbuffer);
 }
@@ -1159,8 +1243,9 @@ static void arcmsr_iop_message_read(struct AdapterControlBlock *acb)
                }
                break;
        case ACB_ADAPTER_TYPE_B: {
+                       struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
                        /* let IOP know data has been read */
-                       CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK);
+                       WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK);
                }
                break;
        case ACB_ADAPTER_TYPE_C: {
@@ -1173,6 +1258,12 @@ static void arcmsr_iop_message_read(struct AdapterControlBlock *acb)
                        CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ);
                }
                break;
+       case ACB_ADAPTER_TYPE_E: {
+                       /* let IOP know data has been read */
+                       acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK;
+                       CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+               }
+               break;
        }
 }
 /*
@@ -1191,11 +1282,12 @@ static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb)
                }
                break;
        case ACB_ADAPTER_TYPE_B: {
+                       struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
                        /*
                        ** push inbound doorbell tell iop, driver data write ok
                        ** and wait reply on next hwinterrupt for next Qbuffer post
                        */
-                       CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_WRITE_OK);
+                       WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_WRITE_OK);
                }
                break;
        case ACB_ADAPTER_TYPE_C: {
@@ -1208,12 +1300,21 @@ static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb)
                break;
        case ACB_ADAPTER_TYPE_D: {
                        /*
-                       ** push inbound doorbell tell iop, driver data write ok 
+                       ** push inbound doorbell tell iop, driver data write ok
                        ** and wait reply on next hwinterrupt for next Qbuffer post
                        */
                        CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_IN_READY);
                }
                break;
+       case ACB_ADAPTER_TYPE_E: {
+                       /*
+                       ** push inbound doorbell tell iop, driver data write ok
+                       ** and wait reply on next hwinterrupt for next Qbuffer post
+                       */
+                       acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_WRITE_OK;
+                       CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+               }
+               break;
        }
 }
 /*
@@ -1224,9 +1325,9 @@ static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb)
 {
        acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
        CHIP_REG_WRITE32(HBA_MessageUnit,
-       0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
+               0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
        if(!arcmsr_hba_wait_msgint_ready(acb)) {
-               kprintf("arcmsr%d: wait 'stop adapter background rebuild' timeout \n"
+               kprintf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n"
                        , acb->pci_unit);
        }
 }
@@ -1236,11 +1337,11 @@ static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb)
 */
 static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb)
 {
+       struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
        acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
-       CHIP_REG_WRITE32(HBB_DOORBELL,
-       0, drv2iop_doorbell, ARCMSR_MESSAGE_STOP_BGRB);
+       WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_STOP_BGRB);
        if(!arcmsr_hbb_wait_msgint_ready(acb)) {
-               kprintf( "arcmsr%d: wait 'stop adapter background rebuild' timeout \n"
+               kprintf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n"
                        , acb->pci_unit);
        }
 }
@@ -1254,7 +1355,7 @@ static void arcmsr_stop_hbc_bgrb(struct AdapterControlBlock *acb)
        CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
        CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
        if(!arcmsr_hbc_wait_msgint_ready(acb)) {
-               kprintf("arcmsr%d: wait 'stop adapter background rebuild' timeout \n", acb->pci_unit);
+               kprintf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit);
        }
 }
 /*
@@ -1273,6 +1374,20 @@ static void arcmsr_stop_hbd_bgrb(struct AdapterControlBlock *acb)
 ************************************************************************
 ************************************************************************
 */
+static void arcmsr_stop_hbe_bgrb(struct AdapterControlBlock *acb)
+{
+       acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
+       CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
+       acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+       CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+       if(!arcmsr_hbe_wait_msgint_ready(acb)) {
+               kprintf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit);
+       }
+}
+/*
+************************************************************************
+************************************************************************
+*/
 static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
 {
        switch (acb->adapter_type) {
@@ -1292,6 +1407,10 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
                        arcmsr_stop_hbd_bgrb(acb);
                }
                break;
+       case ACB_ADAPTER_TYPE_E: {
+                       arcmsr_stop_hbe_bgrb(acb);
+               }
+               break;
        }
 }
 /*
@@ -1316,7 +1435,7 @@ static void arcmsr_poll(struct cam_sim *psim)
 **************************************************************************
 */
 static u_int32_t arcmsr_Read_iop_rqbuffer_data_D(struct AdapterControlBlock *acb,
-    struct QBUFFER *prbuffer) {
+       struct QBUFFER *prbuffer) {
 
        u_int8_t *pQbuffer;
        u_int8_t *buf1 = NULL;
@@ -1361,13 +1480,13 @@ static u_int32_t arcmsr_Read_iop_rqbuffer_data_D(struct AdapterControlBlock *acb
 **************************************************************************
 */
 static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb,
-    struct QBUFFER *prbuffer) {
+       struct QBUFFER *prbuffer) {
 
        u_int8_t *pQbuffer;
        u_int8_t *iop_data;
        u_int32_t iop_len;
 
-       if(acb->adapter_type & (ACB_ADAPTER_TYPE_C | ACB_ADAPTER_TYPE_D)) {
+       if(acb->adapter_type >= ACB_ADAPTER_TYPE_B) {
                return(arcmsr_Read_iop_rqbuffer_data_D(acb, prbuffer));
        }
        iop_data = (u_int8_t *)prbuffer->data;
@@ -1393,12 +1512,12 @@ static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb)
 {
        struct QBUFFER *prbuffer;
        int my_empty_len;
-       
+
        /*check this iop data if overflow my rqbuffer*/
        ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
        prbuffer = arcmsr_get_iop_rqbuffer(acb);
        my_empty_len = (acb->rqbuf_lastindex - acb->rqbuf_firstindex - 1) &
-           (ARCMSR_MAX_QBUFFER-1);
+               (ARCMSR_MAX_QBUFFER-1);
        if(my_empty_len >= prbuffer->data_len) {
                if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
                        acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
@@ -1418,7 +1537,7 @@ static void arcmsr_Write_data_2iop_wqbuffer_D(struct AdapterControlBlock *acb)
        u_int8_t *buf1 = NULL;
        u_int32_t *iop_data, *buf2 = NULL;
        u_int32_t allxfer_len = 0, data_len;
-       
+
        if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) {
                buf1 = kmalloc(128, M_DEVBUF, M_NOWAIT | M_ZERO);
                buf2 = (u_int32_t *)buf1;
@@ -1428,7 +1547,7 @@ static void arcmsr_Write_data_2iop_wqbuffer_D(struct AdapterControlBlock *acb)
                acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ);
                pwbuffer = arcmsr_get_iop_wqbuffer(acb);
                iop_data = (u_int32_t *)pwbuffer->data;
-               while((acb->wqbuf_firstindex != acb->wqbuf_lastindex) 
+               while((acb->wqbuf_firstindex != acb->wqbuf_lastindex)
                        && (allxfer_len < 124)) {
                        pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex];
                        *buf1 = *pQbuffer;
@@ -1462,7 +1581,7 @@ static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb)
        u_int8_t *iop_data;
        int32_t allxfer_len=0;
 
-       if(acb->adapter_type & (ACB_ADAPTER_TYPE_C | ACB_ADAPTER_TYPE_D)) {
+       if(acb->adapter_type >= ACB_ADAPTER_TYPE_B) {
                arcmsr_Write_data_2iop_wqbuffer_D(acb);
                return;
        }
@@ -1470,7 +1589,7 @@ static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb)
                acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ);
                pwbuffer = arcmsr_get_iop_wqbuffer(acb);
                iop_data = (u_int8_t *)pwbuffer->data;
-               while((acb->wqbuf_firstindex != acb->wqbuf_lastindex) 
+               while((acb->wqbuf_firstindex != acb->wqbuf_lastindex)
                        && (allxfer_len < 124)) {
                        pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex];
                        *iop_data = *pQbuffer;
@@ -1514,8 +1633,8 @@ static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb)
 /*
        if (ccb->ccb_h.status != CAM_REQ_CMP)
                kprintf("arcmsr_rescanLun_cb: Rescan Target=%x, lun=%x,"
-                   "failure status=%x\n", ccb->ccb_h.target_id,
-                   ccb->ccb_h.target_lun, ccb->ccb_h.status);
+                       "failure status=%x\n", ccb->ccb_h.target_id,
+                       ccb->ccb_h.target_lun, ccb->ccb_h.status);
        else
                kprintf("arcmsr_rescanLun_cb: Rescan lun successfully!\n");
 */
@@ -1529,8 +1648,8 @@ static void       arcmsr_rescan_lun(struct AdapterControlBlock *acb, int target, int l
        union ccb           *ccb;
 
        if ((ccb = (union ccb *)xpt_alloc_ccb()) == NULL)
-               return;
-       if (xpt_create_path(&path, NULL, cam_sim_path(acb->psim), target, lun) != CAM_REQ_CMP)
+               return;
+       if (xpt_create_path(&path, xpt_periph, cam_sim_path(acb->psim), target, lun) != CAM_REQ_CMP)
        {
                xpt_free_ccb(ccb);
                return;
@@ -1558,13 +1677,13 @@ static void arcmsr_abort_dr_ccbs(struct AdapterControlBlock *acb, int target, in
                srb = acb->psrb_pool[i];
                if (srb->srb_state == ARCMSR_SRB_START)
                {
-               if((target == srb->pccb->ccb_h.target_id) && (lun == srb->pccb->ccb_h.target_lun))
-            {
-                       srb->srb_state = ARCMSR_SRB_ABORTED;
+                       if((target == srb->pccb->ccb_h.target_id) && (lun == srb->pccb->ccb_h.target_lun))
+                       {
+                               srb->srb_state = ARCMSR_SRB_ABORTED;
                                srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
-                       arcmsr_srb_complete(srb, 1);
+                               arcmsr_srb_complete(srb, 1);
                                kprintf("arcmsr%d: abort scsi id %d lun %d srb=%p \n", acb->pci_unit, target, lun, srb);
-               }
+                       }
                }
        }
        /* enable outbound Post Queue, outbound doorbell Interrupt */
@@ -1577,87 +1696,95 @@ static void arcmsr_abort_dr_ccbs(struct AdapterControlBlock *acb, int target, in
 static void arcmsr_dr_handle(struct AdapterControlBlock *acb) {
        u_int32_t       devicemap;
        u_int32_t       target, lun;
-    u_int32_t  deviceMapCurrent[4]={0};
-    u_int8_t   *pDevMap;
+       u_int32_t       deviceMapCurrent[4]={0};
+       u_int8_t        *pDevMap;
 
        switch (acb->adapter_type) {
        case ACB_ADAPTER_TYPE_A:
-                       devicemap = offsetof(struct HBA_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
-                       for (target = 0; target < 4; target++) 
-                       {
-               deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0],  devicemap);
-               devicemap += 4;
-                       }
-                       break;
+               devicemap = offsetof(struct HBA_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
+               for (target = 0; target < 4; target++)
+               {
+                       deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0],  devicemap);
+                       devicemap += 4;
+               }
+               break;
 
        case ACB_ADAPTER_TYPE_B:
-                       devicemap = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
-                       for (target = 0; target < 4; target++) 
-                       {
-               deviceMapCurrent[target]=bus_space_read_4(acb->btag[1], acb->bhandle[1],  devicemap);
-               devicemap += 4;
-                       }
-                       break;
+               devicemap = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
+               for (target = 0; target < 4; target++)
+               {
+                       deviceMapCurrent[target]=bus_space_read_4(acb->btag[1], acb->bhandle[1],  devicemap);
+                       devicemap += 4;
+               }
+               break;
 
        case ACB_ADAPTER_TYPE_C:
-                       devicemap = offsetof(struct HBC_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
-                       for (target = 0; target < 4; target++) 
-                       {
-               deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0],  devicemap);
-               devicemap += 4;
-                       }
-                       break;
+               devicemap = offsetof(struct HBC_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
+               for (target = 0; target < 4; target++)
+               {
+                       deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0],  devicemap);
+                       devicemap += 4;
+               }
+               break;
        case ACB_ADAPTER_TYPE_D:
-                       devicemap = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
-                       for (target = 0; target < 4; target++) 
-                       {
-               deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0],  devicemap);
-               devicemap += 4;
-                       }
-                       break;
-       }
-
-               if(acb->acb_flags & ACB_F_BUS_HANG_ON)
+               devicemap = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
+               for (target = 0; target < 4; target++)
                {
-                       acb->acb_flags &= ~ACB_F_BUS_HANG_ON;
+                       deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0],  devicemap);
+                       devicemap += 4;
                }
-               /*
-               ** adapter posted CONFIG message
-               ** copy the new map, note if there are differences with the current map
-               */
-               pDevMap = (u_int8_t     *)&deviceMapCurrent[0];
-               for (target = 0; target < ARCMSR_MAX_TARGETID - 1; target++) 
+               break;
+       case ACB_ADAPTER_TYPE_E:
+               devicemap = offsetof(struct HBE_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
+               for (target = 0; target < 4; target++)
                {
-                       if (*pDevMap != acb->device_map[target])
+                       deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0],  devicemap);
+                       devicemap += 4;
+               }
+               break;
+       }
+
+       if(acb->acb_flags & ACB_F_BUS_HANG_ON)
+       {
+               acb->acb_flags &= ~ACB_F_BUS_HANG_ON;
+       }
+       /*
+       ** adapter posted CONFIG message
+       ** copy the new map, note if there are differences with the current map
+       */
+       pDevMap = (u_int8_t *)&deviceMapCurrent[0];
+       for (target = 0; target < ARCMSR_MAX_TARGETID - 1; target++)
+       {
+               if (*pDevMap != acb->device_map[target])
+               {
+                       u_int8_t difference, bit_check;
+
+                       difference = *pDevMap ^ acb->device_map[target];
+                       for(lun=0; lun < ARCMSR_MAX_TARGETLUN; lun++)
                        {
-                u_int8_t difference, bit_check;
-
-                difference = *pDevMap ^ acb->device_map[target];
-                for(lun=0; lun < ARCMSR_MAX_TARGETLUN; lun++)
-                {
-                    bit_check = (1 << lun);                                            /*check bit from 0....31*/
-                    if(difference & bit_check)
-                    {
-                        if(acb->device_map[target] & bit_check)
-                        {/* unit departed */
-                                                       kprintf("arcmsr_dr_handle: Target=%x, lun=%x, GONE!!!\n",target,lun);
-                                                       arcmsr_abort_dr_ccbs(acb, target, lun);
-                               arcmsr_rescan_lun(acb, target, lun);
+                               bit_check = (1 << lun);         /*check bit from 0....31*/
+                               if(difference & bit_check)
+                               {
+                                       if(acb->device_map[target] & bit_check)
+                                       {/* unit departed */
+                                               kprintf("arcmsr_dr_handle: Target=%x, lun=%x, GONE!!!\n",target,lun);
+                                               arcmsr_abort_dr_ccbs(acb, target, lun);
+                                               arcmsr_rescan_lun(acb, target, lun);
                                                acb->devstate[target][lun] = ARECA_RAID_GONE;
-                        }
-                        else
-                        {/* unit arrived */
-                                                       kprintf("arcmsr_dr_handle: Target=%x, lun=%x, Plug-IN!!!\n",target,lun);
-                               arcmsr_rescan_lun(acb, target, lun);
+                                       }
+                                       else
+                                       {/* unit arrived */
+                                               kprintf("arcmsr_dr_handle: Target=%x, lun=%x, Plug-IN!!!\n",target,lun);
+                                               arcmsr_rescan_lun(acb, target, lun);
                                                acb->devstate[target][lun] = ARECA_RAID_GOOD;
-                        }
-                    }
-                }
-/*                             kprintf("arcmsr_dr_handle: acb->device_map[%x]=0x%x, deviceMapCurrent[%x]=%x\n",target,acb->device_map[target],target,*pDevMap); */
-                               acb->device_map[target] = *pDevMap;
+                                       }
+                               }
                        }
-                       pDevMap++;
+/*                     kprintf("arcmsr_dr_handle: acb->device_map[%x]=0x%x, deviceMapCurrent[%x]=%x\n",target,acb->device_map[target],target,*pDevMap); */
+                       acb->device_map[target] = *pDevMap;
                }
+               pDevMap++;
+       }
 }
 /*
 **************************************************************************
@@ -1677,9 +1804,10 @@ static void arcmsr_hba_message_isr(struct AdapterControlBlock *acb) {
 */
 static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) {
        u_int32_t outbound_message;
+       struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
 
        /* clear interrupts */
-       CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);
+       WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);
        outbound_message = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0]);
        if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
                arcmsr_dr_handle( acb );
@@ -1712,6 +1840,18 @@ static void arcmsr_hbd_message_isr(struct AdapterControlBlock *acb) {
 **************************************************************************
 **************************************************************************
 */
+static void arcmsr_hbe_message_isr(struct AdapterControlBlock *acb) {
+       u_int32_t outbound_message;
+
+       CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0);
+       outbound_message = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[0]);
+       if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
+               arcmsr_dr_handle( acb );
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
 static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb)
 {
        u_int32_t doorbell_status;
@@ -1766,11 +1906,11 @@ static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb)
 static void arcmsr_hbd_doorbell_isr(struct AdapterControlBlock *acb)
 {
        u_int32_t doorbell_status;
-       
+
        /*
        *******************************************************************
        **  Maybe here we need to check wrqbuffer_lock is lock or not
-       **  DOORBELL: din! don! 
+       **  DOORBELL: din! don!
        **  check if there are any mail need to pack from firmware
        *******************************************************************
        */
@@ -1796,6 +1936,35 @@ static void arcmsr_hbd_doorbell_isr(struct AdapterControlBlock *acb)
 **************************************************************************
 **************************************************************************
 */
+static void arcmsr_hbe_doorbell_isr(struct AdapterControlBlock *acb)
+{
+       u_int32_t doorbell_status, in_doorbell;
+
+       /*
+       *******************************************************************
+       **  Maybe here we need to check wrqbuffer_lock is lock or not
+       **  DOORBELL: din! don!
+       **  check if there are any mail need to pack from firmware
+       *******************************************************************
+       */
+       in_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell);
+       CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /* clear doorbell interrupt */
+       doorbell_status = in_doorbell ^ acb->in_doorbell;
+       if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_WRITE_OK) {
+               arcmsr_iop2drv_data_wrote_handle(acb);
+       }
+       if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_READ_OK) {
+               arcmsr_iop2drv_data_read_handle(acb);
+       }
+       if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) {
+               arcmsr_hbe_message_isr(acb);    /* messenger of "driver to iop commands" */
+       }
+       acb->in_doorbell = in_doorbell;
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
 static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb)
 {
        u_int32_t flag_srb;
@@ -1808,10 +1977,10 @@ static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb)
        */
        bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap,
                BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
-       while((flag_srb = CHIP_REG_READ32(HBA_MessageUnit, 
+       while((flag_srb = CHIP_REG_READ32(HBA_MessageUnit,
                0, outbound_queueport)) != 0xFFFFFFFF) {
                /* check if command done with no error*/
-        error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0) ? TRUE : FALSE;
+       error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0) ? TRUE : FALSE;
                arcmsr_drain_donequeue(acb, flag_srb, error);
        }       /*drain reply FIFO*/
 }
@@ -1840,7 +2009,7 @@ static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb)
                index %= ARCMSR_MAX_HBB_POSTQUEUE;     /*if last index number set it to 0 */
                phbbmu->doneq_index = index;
                /* check if command done with no error*/
-        error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
+       error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
                arcmsr_drain_donequeue(acb, flag_srb, error);
        }       /*drain reply FIFO*/
 }
@@ -1861,19 +2030,21 @@ static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb)
        bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
        do {
                flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low);
+               if (flag_srb == 0xFFFFFFFF)
+                       break;
                /* check if command done with no error*/
-               error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE;
+               error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE;
                arcmsr_drain_donequeue(acb, flag_srb, error);
-               throttling++;
+               throttling++;
                if(throttling == ARCMSR_HBC_ISR_THROTTLING_LEVEL) {
                        CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING);
                        throttling = 0;
-               }
+               }
        } while(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR);
 }
 /*
 **********************************************************************
-** 
+**
 **********************************************************************
 */
 static uint16_t arcmsr_get_doneq_index(struct HBD_MessageUnit0 *phbdmu)
@@ -1913,9 +2084,9 @@ static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb)
        *****************************************************************************
        */
        if((CHIP_REG_READ32(HBD_MessageUnit, 0, outboundlist_interrupt_cause) &
-           ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT) == 0)
-           return;
-       bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 
+               ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT) == 0)
+               return;
+       bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap,
                BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
        outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow;
        doneq_index = phbdmu->doneq_index;
@@ -1931,6 +2102,34 @@ static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb)
        CHIP_REG_READ32(HBD_MessageUnit, 0, outboundlist_interrupt_cause); /*Dummy ioread32 to force pci flush */
 }
 /*
+**************************************************************************
+**************************************************************************
+*/
+static void arcmsr_hbe_postqueue_isr(struct AdapterControlBlock *acb)
+{
+       u_int16_t error;
+       uint32_t doneq_index;
+       uint16_t cmdSMID;
+
+       /*
+       *****************************************************************************
+       **               areca cdb command done
+       *****************************************************************************
+       */
+       bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+       doneq_index = acb->doneq_index;
+       while ((CHIP_REG_READ32(HBE_MessageUnit, 0, reply_post_producer_index) & 0xFFFF) != doneq_index) {
+               cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID;
+               error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
+               arcmsr_drain_donequeue(acb, (u_int32_t)cmdSMID, error);
+               doneq_index++;
+               if (doneq_index >= acb->completionQ_entry)
+                       doneq_index = 0;
+       }
+       acb->doneq_index = doneq_index;
+       CHIP_REG_WRITE32(HBE_MessageUnit, 0, reply_post_consumer_index, doneq_index);
+}
+/*
 **********************************************************************
 **********************************************************************
 */
@@ -1967,19 +2166,20 @@ static void arcmsr_handle_hba_isr( struct AdapterControlBlock *acb)
 static void arcmsr_handle_hbb_isr( struct AdapterControlBlock *acb)
 {
        u_int32_t outbound_doorbell;
+       struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
        /*
        *********************************************
        **   check outbound intstatus
        *********************************************
        */
-       outbound_doorbell = CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & acb->outbound_int_enable;
+       outbound_doorbell = READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & acb->outbound_int_enable;
        if(!outbound_doorbell) {
                /*it must be share irq*/
                return;
        }
-       CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ~outbound_doorbell); /* clear doorbell interrupt */
-       CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell);
-       CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
+       WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ~outbound_doorbell); /* clear doorbell interrupt */
+       READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell);
+       WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
        /* MU ioctl transfer doorbell interrupts*/
        if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) {
                arcmsr_iop2drv_data_wrote_handle(acb);
@@ -2036,7 +2236,7 @@ static void arcmsr_handle_hbd_isr( struct AdapterControlBlock *acb)
        u_int32_t intmask_org;
        /*
        *********************************************
-       **   check outbound intstatus 
+       **   check outbound intstatus
        *********************************************
        */
        host_interrupt_status = CHIP_REG_READ32(HBD_MessageUnit, 0, host_int_status) & acb->outbound_int_enable;
@@ -2060,6 +2260,37 @@ static void arcmsr_handle_hbd_isr( struct AdapterControlBlock *acb)
 //     CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable);
 }
 /*
+**********************************************************************
+**********************************************************************
+*/
+static void arcmsr_handle_hbe_isr( struct AdapterControlBlock *acb)
+{
+       u_int32_t host_interrupt_status;
+       /*
+       *********************************************
+       **   check outbound intstatus
+       *********************************************
+       */
+       host_interrupt_status = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_status) &
+               (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR |
+               ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR);
+       if(!host_interrupt_status) {
+               /*it must be share irq*/
+               return;
+       }
+       do {
+               /* MU doorbell interrupts*/
+               if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR) {
+                       arcmsr_hbe_doorbell_isr(acb);
+               }
+               /* MU post queue interrupts*/
+               if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR) {
+                       arcmsr_hbe_postqueue_isr(acb);
+               }
+               host_interrupt_status = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_status);
+       } while (host_interrupt_status & (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR));
+}
+/*
 ******************************************************************************
 ******************************************************************************
 */
@@ -2078,6 +2309,9 @@ static void arcmsr_interrupt(struct AdapterControlBlock *acb)
        case ACB_ADAPTER_TYPE_D:
                arcmsr_handle_hbd_isr(acb);
                break;
+       case ACB_ADAPTER_TYPE_E:
+               arcmsr_handle_hbe_isr(acb);
+               break;
        default:
                kprintf("arcmsr%d: interrupt service,"
                " unknown adapter type =%d\n", acb->pci_unit, acb->adapter_type);
@@ -2092,9 +2326,7 @@ static void arcmsr_intr_handler(void *arg)
 {
        struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg;
 
-       ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
        arcmsr_interrupt(acb);
-       ARCMSR_LOCK_RELEASE(&acb->isr_lock);
 }
 /*
 ******************************************************************************
@@ -2105,20 +2337,28 @@ static void     arcmsr_polling_devmap(void *arg)
        struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg;
        switch (acb->adapter_type) {
        case ACB_ADAPTER_TYPE_A:
-                       CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
+               CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
                break;
 
-       case ACB_ADAPTER_TYPE_B:
-                       CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG);
+       case ACB_ADAPTER_TYPE_B: {
+                       struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
+                       WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG);
+               }
                break;
 
        case ACB_ADAPTER_TYPE_C:
-                       CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
-                       CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
+               CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
+               CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
+               break;
+
+       case ACB_ADAPTER_TYPE_D:
+               CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
                break;
 
-       case ACB_ADAPTER_TYPE_D:
-                       CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
+       case ACB_ADAPTER_TYPE_E:
+               CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
+               acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+               CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
                break;
        }
 
@@ -2165,10 +2405,10 @@ static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t
        switch(ioctl_cmd) {
        case ARCMSR_MESSAGE_READ_RQBUFFER: {
                        u_int8_t *pQbuffer;
-                       u_int8_t *ptmpQbuffer = pcmdmessagefld->messagedatabuffer;                      
+                       u_int8_t *ptmpQbuffer = pcmdmessagefld->messagedatabuffer;
                        u_int32_t allxfer_len=0;
 
-                       while((acb->rqbuf_firstindex != acb->rqbuf_lastindex) 
+                       while((acb->rqbuf_firstindex != acb->rqbuf_lastindex)
                                && (allxfer_len < 1031)) {
                                /*copy READ QBUFFER to srb*/
                                pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex];
@@ -2206,7 +2446,7 @@ static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t
                                pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR;
                        } else {
                                my_empty_len = (wqbuf_firstindex - wqbuf_lastindex - 1) &
-                                   (ARCMSR_MAX_QBUFFER - 1);
+                                       (ARCMSR_MAX_QBUFFER - 1);
                                if(my_empty_len >= user_len) {
                                        while(user_len > 0) {
                                                /*copy srb data to wqbuffer*/
@@ -2253,7 +2493,7 @@ static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t
 
                        if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
                                acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
-                arcmsr_iop_message_read(acb);
+                               arcmsr_iop_message_read(acb);
                                /*signature, let IOP know data has been readed */
                        }
                        acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ);
@@ -2269,7 +2509,7 @@ static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t
 
                        if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
                                acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
-                arcmsr_iop_message_read(acb);
+                               arcmsr_iop_message_read(acb);
                                /*signature, let IOP know data has been readed */
                        }
                        acb->acb_flags  |= (ACB_F_MESSAGE_WQBUFFER_CLEARED
@@ -2427,7 +2667,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *p
                        if (wqbuf_lastindex != wqbuf_firstindex) {
                                arcmsr_Write_data_2iop_wqbuffer(acb);
                                /* has error report sensedata */
-                           if(pccb->csio.sense_len) {
+                               if(pccb->csio.sense_len) {
                                ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70);
                                /* Valid,ErrorCode */
                                ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05;
@@ -2611,7 +2851,9 @@ static void arcmsr_execute_srb(void *arg, bus_dma_segment_t *dm_segs, int nseg,
        }
        if((pccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
                if(nseg != 0) {
+                       ARCMSR_LOCK_ACQUIRE(&acb->io_lock);
                        bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap);
+                       ARCMSR_LOCK_RELEASE(&acb->io_lock);
                }
                arcmsr_srb_complete(srb, 0);
                return;
@@ -2719,10 +2961,10 @@ static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb,
                char *buffer = pccb->csio.data_ptr;
 
                inqdata[0] = T_PROCESSOR;       /* Periph Qualifier & Periph Dev Type */
-               inqdata[1] = 0;                         /* rem media bit & Dev Type Modifier */
-               inqdata[2] = 0;                         /* ISO, ECMA, & ANSI versions */
+               inqdata[1] = 0;                 /* rem media bit & Dev Type Modifier */
+               inqdata[2] = 0;                 /* ISO, ECMA, & ANSI versions */
                inqdata[3] = 0;
-               inqdata[4] = 31;                        /* length of additional data */
+               inqdata[4] = 31;                /* length of additional data */
                inqdata[5] = 0;
                inqdata[6] = 0;
                inqdata[7] = 0;
@@ -2775,9 +3017,9 @@ static void arcmsr_action(struct cam_sim *psim, union ccb *pccb)
                                xpt_done(pccb);
                                return;
                        }
-                       pccb->ccb_h.arcmsr_ccbsrb_ptr=srb;
-                       pccb->ccb_h.arcmsr_ccbacb_ptr=acb;
-                       srb->pccb=pccb;
+                       pccb->ccb_h.arcmsr_ccbsrb_ptr = srb;
+                       pccb->ccb_h.arcmsr_ccbacb_ptr = acb;
+                       srb->pccb = pccb;
                        if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
                                if(!(pccb->ccb_h.flags & CAM_SCATTER_VALID)) {
                                        /* Single buffer */
@@ -2786,11 +3028,13 @@ static void arcmsr_action(struct cam_sim *psim, union ccb *pccb)
                                                u_int32_t error;
 
                                                crit_enter();
+                                               ARCMSR_LOCK_ACQUIRE(&acb->io_lock);
                                                error = bus_dmamap_load(acb->dm_segs_dmat
                                                        , srb->dm_segs_dmamap
                                                        , pccb->csio.data_ptr
                                                        , pccb->csio.dxfer_len
                                                        , arcmsr_execute_srb, srb, /*flags*/0);
+                                               ARCMSR_LOCK_RELEASE(&acb->io_lock);
                                                if(error == EINPROGRESS) {
                                                        xpt_freeze_simq(acb->psim, 1);
                                                        pccb->ccb_h.status |= CAM_RELEASE_SIMQ;
@@ -2852,6 +3096,7 @@ static void arcmsr_action(struct cam_sim *psim, union ccb *pccb)
                        else
                                cpi->base_transfer_speed = 300000;
                        if((acb->vendor_device_id == PCIDevVenIDARC1880) ||
+                          (acb->vendor_device_id == PCIDevVenIDARC1884) ||
                           (acb->vendor_device_id == PCIDevVenIDARC1680) ||
                           (acb->vendor_device_id == PCIDevVenIDARC1214))
                        {
@@ -2900,7 +3145,7 @@ static void arcmsr_action(struct cam_sim *psim, union ccb *pccb)
                }
        case XPT_RESET_BUS:
        case XPT_RESET_DEV: {
-                       u_int32_t     i;
+                       u_int32_t       i;
 
                        arcmsr_bus_reset(acb);
                        for (i=0; i < 500; i++) {
@@ -2935,6 +3180,7 @@ static void arcmsr_action(struct cam_sim *psim, union ccb *pccb)
                                cts->protocol = PROTO_SCSI;
 
                                if((acb->vendor_device_id == PCIDevVenIDARC1880) ||
+                                  (acb->vendor_device_id == PCIDevVenIDARC1884) ||
                                   (acb->vendor_device_id == PCIDevVenIDARC1680) ||
                                   (acb->vendor_device_id == PCIDevVenIDARC1214))
                                {
@@ -2943,12 +3189,11 @@ static void arcmsr_action(struct cam_sim *psim, union ccb *pccb)
                                        cts->transport = XPORT_SAS;
                                        sas = &cts->xport_specific.sas;
                                        sas->valid = CTS_SAS_VALID_SPEED;
-                                       if (acb->sub_device_id == ARECA_SUB_DEV_ID_1883)
+                                       if (acb->adapter_bus_speed == ACB_BUS_SPEED_12G)
                                                sas->bitrate = 1200000;
-                                       else if((acb->vendor_device_id == PCIDevVenIDARC1880) ||
-                                          (acb->vendor_device_id == PCIDevVenIDARC1214))
+                                       else if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G)
                                                sas->bitrate = 600000;
-                                       else if(acb->vendor_device_id == PCIDevVenIDARC1680)
+                                       else if(acb->adapter_bus_speed == ACB_BUS_SPEED_3G)
                                                sas->bitrate = 300000;
                                }
                                else
@@ -2958,7 +3203,10 @@ static void arcmsr_action(struct cam_sim *psim, union ccb *pccb)
                                        cts->transport = XPORT_SPI;
                                        spi = &cts->xport_specific.spi;
                                        spi->flags = CTS_SPI_FLAGS_DISC_ENB;
-                                       spi->sync_period = 2;
+                                       if (acb->adapter_bus_speed == ACB_BUS_SPEED_6G)
+                                               spi->sync_period = 1;
+                                       else
+                                               spi->sync_period = 2;
                                        spi->sync_offset = 32;
                                        spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
                                        spi->valid = CTS_SPI_VALID_DISC
@@ -3000,7 +3248,7 @@ static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb)
        acb->acb_flags |= ACB_F_MSG_START_BGRB;
        CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB);
        if(!arcmsr_hba_wait_msgint_ready(acb)) {
-               kprintf("arcmsr%d: wait 'start adapter background rebuild' timeout \n", acb->pci_unit);
+               kprintf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit);
        }
 }
 /*
@@ -3009,10 +3257,11 @@ static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb)
 */
 static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb)
 {
+       struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
        acb->acb_flags |= ACB_F_MSG_START_BGRB;
-       CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell,  ARCMSR_MESSAGE_START_BGRB);
+       WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_START_BGRB);
        if(!arcmsr_hbb_wait_msgint_ready(acb)) {
-               kprintf( "arcmsr%d: wait 'start adapter background rebuild' timeout \n", acb->pci_unit);
+               kprintf( "arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit);
        }
 }
 /*
@@ -3025,7 +3274,7 @@ static void arcmsr_start_hbc_bgrb(struct AdapterControlBlock *acb)
        CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB);
        CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
        if(!arcmsr_hbc_wait_msgint_ready(acb)) {
-               kprintf("arcmsr%d: wait 'start adapter background rebuild' timeout \n", acb->pci_unit);
+               kprintf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit);
        }
 }
 /*
@@ -3044,6 +3293,20 @@ static void arcmsr_start_hbd_bgrb(struct AdapterControlBlock *acb)
 **********************************************************************
 **********************************************************************
 */
+static void arcmsr_start_hbe_bgrb(struct AdapterControlBlock *acb)
+{
+       acb->acb_flags |= ACB_F_MSG_START_BGRB;
+       CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB);
+       acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+       CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+       if(!arcmsr_hbe_wait_msgint_ready(acb)) {
+               kprintf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit);
+       }
+}
+/*
+**********************************************************************
+**********************************************************************
+*/
 static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb)
 {
        switch (acb->adapter_type) {
@@ -3059,6 +3322,9 @@ static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb)
        case ACB_ADAPTER_TYPE_D:
                arcmsr_start_hbd_bgrb(acb);
                break;
+       case ACB_ADAPTER_TYPE_E:
+               arcmsr_start_hbe_bgrb(acb);
+               break;
        }
 }
 /*
@@ -3078,7 +3344,7 @@ polling_ccb_retry:
        CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);   /*clear interrupt*/
        bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
        while(1) {
-               if((flag_srb = CHIP_REG_READ32(HBA_MessageUnit, 
+               if((flag_srb = CHIP_REG_READ32(HBA_MessageUnit,
                        0, outbound_queueport)) == 0xFFFFFFFF) {
                        if(poll_srb_done) {
                                break;/*chip FIFO no ccb for completion already*/
@@ -3093,7 +3359,7 @@ polling_ccb_retry:
                /* check if command done with no error*/
                srb = (struct CommandControlBlock *)
                        (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
-        error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
+               error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
                poll_srb_done = (srb == poll_srb) ? 1:0;
                if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
                        if(srb->srb_state == ARCMSR_SRB_ABORTED) {
@@ -3130,8 +3396,7 @@ static void arcmsr_polling_hbb_srbdone(struct AdapterControlBlock *acb, struct C
 
 polling_ccb_retry:
        poll_count++;
-       CHIP_REG_WRITE32(HBB_DOORBELL,
-       0, iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */
+       WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */
        bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
        while(1) {
                index = phbbmu->doneq_index;
@@ -3140,7 +3405,7 @@ polling_ccb_retry:
                                break;/*chip FIFO no ccb for completion already*/
                        } else {
                                UDELAY(25000);
-                           if ((poll_count > 100) && (poll_srb != NULL)) {
+                               if ((poll_count > 100) && (poll_srb != NULL)) {
                                        break;
                                }
                                goto polling_ccb_retry;
@@ -3153,7 +3418,7 @@ polling_ccb_retry:
                /* check if command done with no error*/
                srb = (struct CommandControlBlock *)
                        (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
-        error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
+               error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
                poll_srb_done = (srb == poll_srb) ? 1:0;
                if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
                        if(srb->srb_state == ARCMSR_SRB_ABORTED) {
@@ -3195,19 +3460,19 @@ polling_ccb_retry:
                                break;/*chip FIFO no ccb for completion already*/
                        } else {
                                UDELAY(25000);
-                           if ((poll_count > 100) && (poll_srb != NULL)) {
+                               if ((poll_count > 100) && (poll_srb != NULL)) {
                                        break;
                                }
-                           if (acb->srboutstandingcount == 0) {
+                               if (acb->srboutstandingcount == 0) {
                                    break;
-                           }
+                               }
                                goto polling_ccb_retry;
                        }
                }
                flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low);
                /* check if command done with no error*/
                srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/
-        error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE;
+               error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE;
                if (poll_srb != NULL)
                        poll_srb_done = (srb == poll_srb) ? 1:0;
                if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
@@ -3227,7 +3492,7 @@ polling_ccb_retry:
 }
 /*
 **********************************************************************
-** 
+**
 **********************************************************************
 */
 static void arcmsr_polling_hbd_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
@@ -3237,7 +3502,7 @@ static void arcmsr_polling_hbd_srbdone(struct AdapterControlBlock *acb, struct C
        u_int32_t flag_srb, poll_srb_done=0, poll_count=0;
        u_int32_t outbound_write_pointer;
        u_int16_t       error, doneq_index;
-       
+
 polling_ccb_retry:
        poll_count++;
        bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
@@ -3249,12 +3514,12 @@ polling_ccb_retry:
                                break;/*chip FIFO no ccb for completion already*/
                        } else {
                                UDELAY(25000);
-                           if ((poll_count > 100) && (poll_srb != NULL)) {
+                               if ((poll_count > 100) && (poll_srb != NULL)) {
+                                       break;
+                               }
+                               if (acb->srboutstandingcount == 0) {
                                        break;
                                }
-                           if (acb->srboutstandingcount == 0) {
-                                   break;
-                           }
                                goto polling_ccb_retry;
                        }
                }
@@ -3262,7 +3527,7 @@ polling_ccb_retry:
                flag_srb = phbdmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow;
                /* check if command done with no error*/
                srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/
-        error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
+               error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
                CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_read_pointer, doneq_index);
                if (poll_srb != NULL)
                        poll_srb_done = (srb == poll_srb) ? 1:0;
@@ -3283,6 +3548,61 @@ polling_ccb_retry:
 }
 /*
 **********************************************************************
+**
+**********************************************************************
+*/
+static void arcmsr_polling_hbe_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
+{
+       struct CommandControlBlock *srb;
+       u_int32_t poll_srb_done=0, poll_count=0, doneq_index;
+       u_int16_t       error, cmdSMID;
+
+polling_ccb_retry:
+       poll_count++;
+       bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+       while(1) {
+               doneq_index = acb->doneq_index;
+               if((CHIP_REG_READ32(HBE_MessageUnit, 0, reply_post_producer_index) & 0xFFFF) == doneq_index) {
+                       if(poll_srb_done) {
+                               break;/*chip FIFO no ccb for completion already*/
+                       } else {
+                               UDELAY(25000);
+                           if ((poll_count > 100) && (poll_srb != NULL)) {
+                                       break;
+                               }
+                           if (acb->srboutstandingcount == 0) {
+                                   break;
+                           }
+                               goto polling_ccb_retry;
+                       }
+               }
+               cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID;
+               doneq_index++;
+               if (doneq_index >= acb->completionQ_entry)
+                       doneq_index = 0;
+               acb->doneq_index = doneq_index;
+               srb = acb->psrb_pool[cmdSMID];
+               error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
+               if (poll_srb != NULL)
+                       poll_srb_done = (srb == poll_srb) ? 1:0;
+               if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
+                       if(srb->srb_state == ARCMSR_SRB_ABORTED) {
+                               kprintf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n"
+                                               , acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
+                               srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
+                               arcmsr_srb_complete(srb, 1);
+                               continue;
+                       }
+                       kprintf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n"
+                                       , acb->pci_unit, srb, acb->srboutstandingcount);
+                       continue;
+               }
+               arcmsr_report_srb_state(acb, srb, error);
+       }       /*drain reply FIFO*/
+       CHIP_REG_WRITE32(HBE_MessageUnit, 0, reply_post_producer_index, doneq_index);
+}
+/*
+**********************************************************************
 **********************************************************************
 */
 static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
@@ -3304,6 +3624,10 @@ static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct Comma
                        arcmsr_polling_hbd_srbdone(acb, poll_srb);
                }
                break;
+       case ACB_ADAPTER_TYPE_E: {
+                       arcmsr_polling_hbe_srbdone(acb, poll_srb);
+               }
+               break;
        }
 }
 /*
@@ -3326,25 +3650,24 @@ static void arcmsr_get_hba_config(struct AdapterControlBlock *acb)
        }
        i = 0;
        while(i < 8) {
-               *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 
+               *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i);
                /* 8 bytes firm_model, 15, 60-67*/
                acb_firm_model++;
                i++;
        }
        i=0;
        while(i < 16) {
-               *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i);  
+               *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i);
                /* 16 bytes firm_version, 17, 68-83*/
                acb_firm_version++;
                i++;
        }
        i=0;
        while(i < 16) {
-               *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i);  
+               *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i);
                acb_device_map++;
                i++;
        }
-       kprintf("Areca RAID adapter%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION);
        kprintf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version);
        acb->firm_request_len = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[1]);   /*firm_request_len, 1, 04-07*/
        acb->firm_numbers_queue = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/
@@ -3362,6 +3685,7 @@ static void arcmsr_get_hba_config(struct AdapterControlBlock *acb)
 */
 static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb)
 {
+       struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
        char *acb_firm_model = acb->firm_model;
        char *acb_firm_version = acb->firm_version;
        char *acb_device_map = acb->device_map;
@@ -3370,7 +3694,7 @@ static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb)
        size_t iop_device_map = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
        int i;
 
-       CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG);
+       WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG);
        if(!arcmsr_hbb_wait_msgint_ready(acb)) {
                kprintf( "arcmsr%d: wait" "'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
        }
@@ -3390,11 +3714,10 @@ static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb)
        }
        i = 0;
        while(i < 16) {
-               *acb_device_map = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_device_map+i);  
+               *acb_device_map = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_device_map+i);
                acb_device_map++;
                i++;
        }
-       kprintf("Areca RAID adapter%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION);
        kprintf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version);
        acb->firm_request_len = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1]);   /*firm_request_len, 1, 04-07*/
        acb->firm_numbers_queue = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/
@@ -3427,25 +3750,24 @@ static void arcmsr_get_hbc_config(struct AdapterControlBlock *acb)
        }
        i = 0;
        while(i < 8) {
-               *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 
+               *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i);
                /* 8 bytes firm_model, 15, 60-67*/
                acb_firm_model++;
                i++;
        }
        i = 0;
        while(i < 16) {
-               *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i);  
+               *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i);
                /* 16 bytes firm_version, 17, 68-83*/
                acb_firm_version++;
                i++;
        }
        i = 0;
        while(i < 16) {
-               *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i);  
+               *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i);
                acb_device_map++;
                i++;
        }
-       kprintf("Areca RAID adapter%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION);
        kprintf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version);
        acb->firm_request_len   = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[1]);     /*firm_request_len,   1, 04-07*/
        acb->firm_numbers_queue = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[2]);     /*firm_numbers_queue, 2, 08-11*/
@@ -3470,7 +3792,7 @@ static void arcmsr_get_hbd_config(struct AdapterControlBlock *acb)
        size_t iop_firm_version = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/
        size_t iop_device_map = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
        int i;
-       
+
        if(CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE)
                CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR);
        CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
@@ -3479,30 +3801,29 @@ static void arcmsr_get_hbd_config(struct AdapterControlBlock *acb)
        }
        i = 0;
        while(i < 8) {
-               *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 
+               *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i);
                /* 8 bytes firm_model, 15, 60-67*/
                acb_firm_model++;
                i++;
        }
        i = 0;
        while(i < 16) {
-               *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i);  
+               *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i);
                /* 16 bytes firm_version, 17, 68-83*/
                acb_firm_version++;
                i++;
        }
        i = 0;
        while(i < 16) {
-               *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i);  
+               *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i);
                acb_device_map++;
                i++;
        }
-       kprintf("Areca RAID adapter%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION);
        kprintf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version);
-       acb->firm_request_len   = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[2]);     /*firm_request_len,   1, 04-07*/
-       acb->firm_numbers_queue = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[3]);     /*firm_numbers_queue, 2, 08-11*/
-       acb->firm_sdram_size    = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[4]);     /*firm_sdram_size,    3, 12-15*/
-       acb->firm_ide_channels  = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[5]);     /*firm_ide_channels,  4, 16-19*/
+       acb->firm_request_len   = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[1]);     /*firm_request_len,   1, 04-07*/
+       acb->firm_numbers_queue = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[2]);     /*firm_numbers_queue, 2, 08-11*/
+       acb->firm_sdram_size    = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[3]);     /*firm_sdram_size,    3, 12-15*/
+       acb->firm_ide_channels  = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[4]);     /*firm_ide_channels,  4, 16-19*/
        acb->firm_cfg_version   = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);       /*firm_cfg_version,  25,          */
        if(acb->firm_numbers_queue > ARCMSR_MAX_HBD_POSTQUEUE)
                acb->maxOutstanding = ARCMSR_MAX_HBD_POSTQUEUE - 1;
@@ -3513,6 +3834,58 @@ static void arcmsr_get_hbd_config(struct AdapterControlBlock *acb)
 **********************************************************************
 **********************************************************************
 */
+static void arcmsr_get_hbe_config(struct AdapterControlBlock *acb)
+{
+       char *acb_firm_model = acb->firm_model;
+       char *acb_firm_version = acb->firm_version;
+       char *acb_device_map = acb->device_map;
+       size_t iop_firm_model = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);   /*firm_model,15,60-67*/
+       size_t iop_firm_version = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/
+       size_t iop_device_map = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
+       int i;
+
+       CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
+       acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+       CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+       if(!arcmsr_hbe_wait_msgint_ready(acb)) {
+               kprintf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
+       }
+
+       i = 0;
+       while(i < 8) {
+               *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i);
+               /* 8 bytes firm_model, 15, 60-67*/
+               acb_firm_model++;
+               i++;
+       }
+       i = 0;
+       while(i < 16) {
+               *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i);
+               /* 16 bytes firm_version, 17, 68-83*/
+               acb_firm_version++;
+               i++;
+       }
+       i = 0;
+       while(i < 16) {
+               *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i);
+               acb_device_map++;
+               i++;
+       }
+       kprintf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version);
+       acb->firm_request_len   = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[1]);     /*firm_request_len,   1, 04-07*/
+       acb->firm_numbers_queue = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[2]);     /*firm_numbers_queue, 2, 08-11*/
+       acb->firm_sdram_size    = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[3]);     /*firm_sdram_size,    3, 12-15*/
+       acb->firm_ide_channels  = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[4]);     /*firm_ide_channels,  4, 16-19*/
+       acb->firm_cfg_version   = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);       /*firm_cfg_version,  25,          */
+       if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD)
+               acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1;
+       else
+               acb->maxOutstanding = acb->firm_numbers_queue - 1;
+}
+/*
+**********************************************************************
+**********************************************************************
+*/
 static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
 {
        switch (acb->adapter_type) {
@@ -3532,6 +3905,10 @@ static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
                        arcmsr_get_hbd_config(acb);
                }
                break;
+       case ACB_ADAPTER_TYPE_E: {
+                       arcmsr_get_hbe_config(acb);
+               }
+               break;
        }
 }
 /*
@@ -3556,7 +3933,8 @@ static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb)
                }
                break;
        case ACB_ADAPTER_TYPE_B: {
-                       while ((CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & ARCMSR_MESSAGE_FIRMWARE_OK) == 0)
+                       struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
+                       while ((READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & ARCMSR_MESSAGE_FIRMWARE_OK) == 0)
                        {
                                if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */
                                {
@@ -3565,7 +3943,7 @@ static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb)
                                }
                                UDELAY(15000); /* wait 15 milli-seconds */
                        }
-                       CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
+                       WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
                }
                break;
        case ACB_ADAPTER_TYPE_C: {
@@ -3592,6 +3970,18 @@ static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb)
                        }
                }
                break;
+       case ACB_ADAPTER_TYPE_E: {
+                       while ((CHIP_REG_READ32(HBE_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBEMU_MESSAGE_FIRMWARE_OK) == 0)
+                       {
+                               if (timeout++ > 4000) /* (4000*15)/1000 = 60 sec */
+                               {
+                                       kprintf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit);
+                                       return;
+                               }
+                               UDELAY(15000); /* wait 15 milli-seconds */
+                       }
+               }
+               break;
        }
 }
 /*
@@ -3608,12 +3998,12 @@ static void arcmsr_clear_doorbell_queue_buffer( struct AdapterControlBlock *acb)
                        outbound_doorbell = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell);
                        CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, outbound_doorbell);     /*clear doorbell interrupt */
                        CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
-
                }
                break;
        case ACB_ADAPTER_TYPE_B: {
-                       CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt and message state*/
-                       CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK);
+                       struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
+                       WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN);/*clear interrupt and message state*/
+                       WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK);
                        /* let IOP know data has been read */
                }
                break;
@@ -3631,7 +4021,14 @@ static void arcmsr_clear_doorbell_queue_buffer( struct AdapterControlBlock *acb)
                        outbound_doorbell = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell);
                        CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, outbound_doorbell);     /*clear doorbell interrupt */
                        CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ);
-
+               }
+               break;
+       case ACB_ADAPTER_TYPE_E: {
+                       /* empty doorbell Qbuffer if door bell ringed */
+                       acb->in_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell);
+                       CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0);       /*clear doorbell interrupt */
+                       acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK;
+                       CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
                }
                break;
        }
@@ -3680,24 +4077,24 @@ static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb)
                        phbbmu = (struct HBB_MessageUnit *)acb->pmu;
                        phbbmu->postq_index = 0;
                        phbbmu->doneq_index = 0;
-                       CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_SET_POST_WINDOW);
+                       WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_SET_POST_WINDOW);
                        if(!arcmsr_hbb_wait_msgint_ready(acb)) {
                                kprintf( "arcmsr%d: 'set window of post command Q' timeout\n", acb->pci_unit);
                                return FALSE;
                        }
                        post_queue_phyaddr = srb_phyaddr + ARCMSR_SRBS_POOL_SIZE
-                       + offsetof(struct HBB_MessageUnit, post_qbuffer);
+                                                               + offsetof(struct HBB_MessageUnit, post_qbuffer);
                        CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */
                        CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1], srb_phyaddr_hi32); /* normal should be zero */
                        CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ size (256+8)*4 */
                        CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3], post_queue_phyaddr+1056); /* doneQ size (256+8)*4 */
                        CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4], 1056); /* srb maxQ size must be --> [(256+8)*4] */
-                       CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_SET_CONFIG);
+                       WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_SET_CONFIG);
                        if(!arcmsr_hbb_wait_msgint_ready(acb)) {
                                kprintf( "arcmsr%d: 'set command Q window' timeout \n", acb->pci_unit);
                                return FALSE;
                        }
-                       CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_START_DRIVER_MODE);
+                       WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_START_DRIVER_MODE);
                        if(!arcmsr_hbb_wait_msgint_ready(acb)) {
                                kprintf( "arcmsr%d: 'start diver mode' timeout \n", acb->pci_unit);
                                return FALSE;
@@ -3720,13 +4117,13 @@ static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb)
        case ACB_ADAPTER_TYPE_D: {
                        u_int32_t post_queue_phyaddr, done_queue_phyaddr;
                        struct HBD_MessageUnit0 *phbdmu;
-       
+
                        phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
                        phbdmu->postq_index = 0;
                        phbdmu->doneq_index = 0x40FF;
-                       post_queue_phyaddr = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE 
+                       post_queue_phyaddr = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE
                                                                + offsetof(struct HBD_MessageUnit0, post_qbuffer);
-                       done_queue_phyaddr = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE 
+                       done_queue_phyaddr = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE
                                                                + offsetof(struct HBD_MessageUnit0, done_qbuffer);
                        CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */
                        CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32);
@@ -3740,6 +4137,27 @@ static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb)
                        }
                }
                break;
+       case ACB_ADAPTER_TYPE_E: {
+                       u_int32_t cdb_phyaddr_lo32;
+                       cdb_phyaddr_lo32 = srb_phyaddr_lo32 + offsetof(struct CommandControlBlock, arcmsr_cdb);
+                       CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG);
+                       CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[1], ARCMSR_SIGNATURE_1884);
+                       CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[2], cdb_phyaddr_lo32);
+                       CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[3], srb_phyaddr_hi32);
+                       CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[4], SRB_SIZE);
+                       cdb_phyaddr_lo32 = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE;
+                       CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[5], cdb_phyaddr_lo32);
+                       CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[6], srb_phyaddr_hi32);
+                       CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[7], COMPLETION_Q_POOL_SIZE);
+                       CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
+                       acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+                       CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+                       if(!arcmsr_hbe_wait_msgint_ready(acb)) {
+                               kprintf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit);
+                               return FALSE;
+                       }
+               }
+               break;
        }
        return (TRUE);
 }
@@ -3749,20 +4167,14 @@ static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb)
 */
 static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb)
 {
-       switch (acb->adapter_type)
+       if (acb->adapter_type == ACB_ADAPTER_TYPE_B)
        {
-       case ACB_ADAPTER_TYPE_A:
-       case ACB_ADAPTER_TYPE_C:
-       case ACB_ADAPTER_TYPE_D:
-               break;
-       case ACB_ADAPTER_TYPE_B: {
-                       CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell,ARCMSR_MESSAGE_ACTIVE_EOI_MODE);
-                       if(!arcmsr_hbb_wait_msgint_ready(acb)) {
-                               kprintf( "arcmsr%d: 'iop enable eoi mode' timeout \n", acb->pci_unit);
-                               return;
-                       }
+               struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
+               WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_ACTIVE_EOI_MODE);
+               if(!arcmsr_hbb_wait_msgint_ready(acb)) {
+                       kprintf( "arcmsr%d: 'iop enable eoi mode' timeout \n", acb->pci_unit);
+                       return;
                }
-               break;
        }
 }
 /*
@@ -3798,7 +4210,7 @@ static void arcmsr_map_free_srb(void *arg, bus_dma_segment_t *segs, int nseg, in
        u_int32_t i;
        unsigned long srb_phyaddr = (unsigned long)segs->ds_addr;
 
-       acb->srb_phyaddr.phyaddr = srb_phyaddr; 
+       acb->srb_phyaddr.phyaddr = srb_phyaddr;
        srb_tmp = (struct CommandControlBlock *)acb->uncacheptr;
        for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) {
                if(bus_dmamap_create(acb->dm_segs_dmat,
@@ -3808,7 +4220,8 @@ static void arcmsr_map_free_srb(void *arg, bus_dma_segment_t *segs, int nseg, in
                        " srb dmamap bus_dmamap_create error\n", acb->pci_unit);
                        return;
                }
-               if((acb->adapter_type == ACB_ADAPTER_TYPE_C) || (acb->adapter_type == ACB_ADAPTER_TYPE_D))
+               if((acb->adapter_type == ACB_ADAPTER_TYPE_C) || (acb->adapter_type == ACB_ADAPTER_TYPE_D)
+                        || (acb->adapter_type == ACB_ADAPTER_TYPE_E))
                {
                        srb_tmp->cdb_phyaddr_low = srb_phyaddr;
                        srb_tmp->cdb_phyaddr_high = (u_int32_t)((srb_phyaddr >> 16) >> 16);
@@ -3816,10 +4229,12 @@ static void arcmsr_map_free_srb(void *arg, bus_dma_segment_t *segs, int nseg, in
                else
                        srb_tmp->cdb_phyaddr_low = srb_phyaddr >> 5;
                srb_tmp->acb = acb;
+               srb_tmp->smid = i << 16;
                acb->srbworkingQ[i] = acb->psrb_pool[i] = srb_tmp;
                srb_phyaddr = srb_phyaddr + SRB_SIZE;
                srb_tmp = (struct CommandControlBlock *)((unsigned long)srb_tmp + SRB_SIZE);
        }
+       acb->pCompletionQ = (pCompletion_Q)srb_tmp;
        acb->vir2phy_offset = (unsigned long)srb_tmp - (unsigned long)srb_phyaddr;
 }
 /*
@@ -3848,6 +4263,8 @@ static void arcmsr_mutex_init(struct AdapterControlBlock *acb)
        ARCMSR_LOCK_INIT(&acb->srb_lock, "arcmsr srb lock");
        ARCMSR_LOCK_INIT(&acb->postDone_lock, "arcmsr postQ lock");
        ARCMSR_LOCK_INIT(&acb->qbuffer_lock, "arcmsr RW buffer lock");
+       ARCMSR_LOCK_INIT(&acb->io_lock, "arcmsr io lock");
+       ARCMSR_LOCK_INIT(&acb->sim_lock, "arcmsr sim lock");
 }
 /*
 ************************************************************************
@@ -3855,6 +4272,8 @@ static void arcmsr_mutex_init(struct AdapterControlBlock *acb)
 */
 static void arcmsr_mutex_destroy(struct AdapterControlBlock *acb)
 {
+       ARCMSR_LOCK_DESTROY(&acb->sim_lock);
+       ARCMSR_LOCK_DESTROY(&acb->io_lock);
        ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock);
        ARCMSR_LOCK_DESTROY(&acb->postDone_lock);
        ARCMSR_LOCK_DESTROY(&acb->srb_lock);
@@ -3880,13 +4299,21 @@ static u_int32_t arcmsr_initialize(device_t dev)
        case PCIDevVenIDARC1213:
        case PCIDevVenIDARC1223: {
                        acb->adapter_type = ACB_ADAPTER_TYPE_C;
-                       if (acb->sub_device_id == ARECA_SUB_DEV_ID_1883)
+                       if ((acb->sub_device_id == ARECA_SUB_DEV_ID_1883) ||
+                           (acb->sub_device_id == ARECA_SUB_DEV_ID_1216) ||
+                           (acb->sub_device_id == ARECA_SUB_DEV_ID_1226))
                                acb->adapter_bus_speed = ACB_BUS_SPEED_12G;
                        else
                                acb->adapter_bus_speed = ACB_BUS_SPEED_6G;
                        max_coherent_size = ARCMSR_SRBS_POOL_SIZE;
                }
                break;
+       case PCIDevVenIDARC1884:
+               acb->adapter_type = ACB_ADAPTER_TYPE_E;
+               acb->adapter_bus_speed = ACB_BUS_SPEED_12G;
+               max_coherent_size = ARCMSR_SRBS_POOL_SIZE + COMPLETION_Q_POOL_SIZE;
+               acb->completionQ_entry = COMPLETION_Q_POOL_SIZE / sizeof(struct deliver_completeQ);
+               break;
        case PCIDevVenIDARC1214: {
                        acb->adapter_type = ACB_ADAPTER_TYPE_D;
                        acb->adapter_bus_speed = ACB_BUS_SPEED_6G;
@@ -3900,6 +4327,12 @@ static u_int32_t arcmsr_initialize(device_t dev)
                        max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBB_MessageUnit));
                }
                break;
+       case PCIDevVenIDARC1203: {
+                       acb->adapter_type = ACB_ADAPTER_TYPE_B;
+                       acb->adapter_bus_speed = ACB_BUS_SPEED_6G;
+                       max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBB_MessageUnit));
+               }
+               break;
        case PCIDevVenIDARC1110:
        case PCIDevVenIDARC1120:
        case PCIDevVenIDARC1130:
@@ -3931,34 +4364,34 @@ static u_int32_t arcmsr_initialize(device_t dev)
                }
        }
        if(bus_dma_tag_create(  /*PCI parent*/          bus_get_dma_tag(dev),
-                               /*alignemnt*/   1,
-                               /*boundary*/    0,
-                               /*lowaddr*/     BUS_SPACE_MAXADDR,
-                               /*highaddr*/    BUS_SPACE_MAXADDR,
-                               /*filter*/      NULL,
-                               /*filterarg*/   NULL,
-                               /*maxsize*/     BUS_SPACE_MAXSIZE_32BIT,
-                               /*nsegments*/   BUS_SPACE_UNRESTRICTED,
-                               /*maxsegsz*/    BUS_SPACE_MAXSIZE_32BIT,
-                               /*flags*/       0,
-                                               &acb->parent_dmat) != 0)
+                               /*alignemnt*/           1,
+                               /*boundary*/            0,
+                               /*lowaddr*/             BUS_SPACE_MAXADDR,
+                               /*highaddr*/            BUS_SPACE_MAXADDR,
+                               /*filter*/              NULL,
+                               /*filterarg*/           NULL,
+                               /*maxsize*/             BUS_SPACE_MAXSIZE_32BIT,
+                               /*nsegments*/           BUS_SPACE_UNRESTRICTED,
+                               /*maxsegsz*/            BUS_SPACE_MAXSIZE_32BIT,
+                               /*flags*/               0,
+                                                       &acb->parent_dmat) != 0)
        {
                kprintf("arcmsr%d: parent_dmat bus_dma_tag_create failure!\n", device_get_unit(dev));
                return ENOMEM;
        }
        /* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */
-       if(bus_dma_tag_create(  /*parent_dmat*/ acb->parent_dmat,
-                               /*alignment*/   1,
-                               /*boundary*/    0,
-                               /*lowaddr*/     BUS_SPACE_MAXADDR,
-                               /*highaddr*/    BUS_SPACE_MAXADDR,
-                               /*filter*/      NULL,
-                               /*filterarg*/   NULL,
-                               /*maxsize*/     ARCMSR_MAX_SG_ENTRIES * PAGE_SIZE * ARCMSR_MAX_FREESRB_NUM,
-                               /*nsegments*/   ARCMSR_MAX_SG_ENTRIES,
-                               /*maxsegsz*/    BUS_SPACE_MAXSIZE_32BIT,
-                               /*flags*/       0,
-                                               &acb->dm_segs_dmat) != 0)
+       if(bus_dma_tag_create(  /*parent_dmat*/         acb->parent_dmat,
+                               /*alignment*/           1,
+                               /*boundary*/            0,
+                               /*lowaddr*/             BUS_SPACE_MAXADDR,
+                               /*highaddr*/            BUS_SPACE_MAXADDR,
+                               /*filter*/              NULL,
+                               /*filterarg*/           NULL,
+                               /*maxsize*/             ARCMSR_MAX_SG_ENTRIES * PAGE_SIZE * ARCMSR_MAX_FREESRB_NUM,
+                               /*nsegments*/           ARCMSR_MAX_SG_ENTRIES,
+                               /*maxsegsz*/            BUS_SPACE_MAXSIZE_32BIT,
+                               /*flags*/               0,
+                                                       &acb->dm_segs_dmat) != 0)
        {
                bus_dma_tag_destroy(acb->parent_dmat);
                kprintf("arcmsr%d: dm_segs_dmat bus_dma_tag_create failure!\n", device_get_unit(dev));
@@ -3966,18 +4399,18 @@ static u_int32_t arcmsr_initialize(device_t dev)
        }
 
        /* DMA tag for our srb structures.... Allocate the freesrb memory */
-       if(bus_dma_tag_create(  /*parent_dmat*/ acb->parent_dmat,
-                               /*alignment*/   0x20,
-                               /*boundary*/    0,
-                               /*lowaddr*/     BUS_SPACE_MAXADDR_32BIT,
-                               /*highaddr*/    BUS_SPACE_MAXADDR,
-                               /*filter*/      NULL,
-                               /*filterarg*/   NULL,
-                               /*maxsize*/     max_coherent_size,
-                               /*nsegments*/   1,
-                               /*maxsegsz*/    BUS_SPACE_MAXSIZE_32BIT,
-                               /*flags*/       0,
-                                               &acb->srb_dmat) != 0)
+       if(bus_dma_tag_create(  /*parent_dmat*/         acb->parent_dmat,
+                               /*alignment*/           0x20,
+                               /*boundary*/            0,
+                               /*lowaddr*/             BUS_SPACE_MAXADDR_32BIT,
+                               /*highaddr*/            BUS_SPACE_MAXADDR,
+                               /*filter*/              NULL,
+                               /*filterarg*/           NULL,
+                               /*maxsize*/             max_coherent_size,
+                               /*nsegments*/           1,
+                               /*maxsegsz*/            BUS_SPACE_MAXSIZE_32BIT,
+                               /*flags*/               0,
+                                                       &acb->srb_dmat) != 0)
        {
                bus_dma_tag_destroy(acb->dm_segs_dmat);
                bus_dma_tag_destroy(acb->parent_dmat);
@@ -4008,123 +4441,170 @@ static u_int32_t arcmsr_initialize(device_t dev)
        pci_write_config(dev, PCIR_COMMAND, pci_command, 2);
        switch(acb->adapter_type) {
        case ACB_ADAPTER_TYPE_A: {
-                       u_int32_t rid0 = PCIR_BAR(0);
-                       vm_offset_t     mem_base0;
+               u_int32_t rid0 = PCIR_BAR(0);
+               vm_offset_t     mem_base0;
 
-                       acb->sys_res_arcmsr[0] = bus_alloc_resource(dev,SYS_RES_MEMORY, &rid0, 0ul, ~0ul, 0x1000, RF_ACTIVE);
-                       if(acb->sys_res_arcmsr[0] == NULL) {
+               acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid0, RF_ACTIVE);
+               if(acb->sys_res_arcmsr[0] == NULL) {
+                       arcmsr_free_resource(acb);
+                       kprintf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
+                       return ENOMEM;
+               }
+               if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
+                       arcmsr_free_resource(acb);
+                       kprintf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
+                       return ENXIO;
+               }
+               mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
+               if(mem_base0 == 0) {
+                       arcmsr_free_resource(acb);
+                       kprintf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
+                       return ENXIO;
+               }
+               acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
+               acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
+               acb->pmu = (struct MessageUnit_UNION *)mem_base0;
+               acb->rid[0] = rid0;
+               }
+               break;
+       case ACB_ADAPTER_TYPE_B: {
+               struct HBB_MessageUnit *phbbmu;
+               struct CommandControlBlock *freesrb;
+               u_int32_t rid[]={ PCIR_BAR(0), PCIR_BAR(2) };
+               vm_offset_t     mem_base[]={0,0};
+               u_long  size;
+               if (vendor_dev_id == PCIDevVenIDARC1203)
+                       size = sizeof(struct HBB_DOORBELL_1203);
+               else
+                       size = sizeof(struct HBB_DOORBELL);
+               for(i=0; i < 2; i++) {
+                       acb->sys_res_arcmsr[i] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid[i], RF_ACTIVE);
+                       if(acb->sys_res_arcmsr[i] == NULL) {
                                arcmsr_free_resource(acb);
-                               kprintf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
+                               kprintf("arcmsr%d: bus_alloc_resource %d failure!\n", device_get_unit(dev), i);
                                return ENOMEM;
                        }
-                       if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
+                       if(rman_get_start(acb->sys_res_arcmsr[i]) <= 0) {
                                arcmsr_free_resource(acb);
-                               kprintf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
+                               kprintf("arcmsr%d: rman_get_start %d failure!\n", device_get_unit(dev), i);
                                return ENXIO;
                        }
-                       mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
-                       if(mem_base0 == 0) {
+                       mem_base[i] = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[i]);
+                       if(mem_base[i] == 0) {
                                arcmsr_free_resource(acb);
-                               kprintf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
+                               kprintf("arcmsr%d: rman_get_virtual %d failure!\n", device_get_unit(dev), i);
                                return ENXIO;
                        }
-                       acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
-                       acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
-                       acb->pmu = (struct MessageUnit_UNION *)mem_base0;
+                       acb->btag[i] = rman_get_bustag(acb->sys_res_arcmsr[i]);
+                       acb->bhandle[i] = rman_get_bushandle(acb->sys_res_arcmsr[i]);
+               }
+               freesrb = (struct CommandControlBlock *)acb->uncacheptr;
+               acb->pmu = (struct MessageUnit_UNION *)((unsigned long)freesrb+ARCMSR_SRBS_POOL_SIZE);
+               phbbmu = (struct HBB_MessageUnit *)acb->pmu;
+               phbbmu->hbb_doorbell = (struct HBB_DOORBELL *)mem_base[0];
+               phbbmu->hbb_rwbuffer = (struct HBB_RWBUFFER *)mem_base[1];
+               if (vendor_dev_id == PCIDevVenIDARC1203) {
+                       phbbmu->drv2iop_doorbell = offsetof(struct HBB_DOORBELL_1203, drv2iop_doorbell);
+                       phbbmu->drv2iop_doorbell_mask = offsetof(struct HBB_DOORBELL_1203, drv2iop_doorbell_mask);
+                       phbbmu->iop2drv_doorbell = offsetof(struct HBB_DOORBELL_1203, iop2drv_doorbell);
+                       phbbmu->iop2drv_doorbell_mask = offsetof(struct HBB_DOORBELL_1203, iop2drv_doorbell_mask);
+               } else {
+                       phbbmu->drv2iop_doorbell = offsetof(struct HBB_DOORBELL, drv2iop_doorbell);
+                       phbbmu->drv2iop_doorbell_mask = offsetof(struct HBB_DOORBELL, drv2iop_doorbell_mask);
+                       phbbmu->iop2drv_doorbell = offsetof(struct HBB_DOORBELL, iop2drv_doorbell);
+                       phbbmu->iop2drv_doorbell_mask = offsetof(struct HBB_DOORBELL, iop2drv_doorbell_mask);
                }
-               break;
-       case ACB_ADAPTER_TYPE_B: {
-                       struct HBB_MessageUnit *phbbmu;
-                       struct CommandControlBlock *freesrb;
-                       u_int32_t rid[]={ PCIR_BAR(0), PCIR_BAR(2) };
-                       vm_offset_t     mem_base[]={0,0};
-                       for(i=0; i < 2; i++) {
-                               if(i == 0) {
-                                       acb->sys_res_arcmsr[i] = bus_alloc_resource(dev,SYS_RES_MEMORY, &rid[i],
-                                                                                       0ul, ~0ul, sizeof(struct HBB_DOORBELL), RF_ACTIVE);
-                               } else {
-                                       acb->sys_res_arcmsr[i] = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid[i],
-                                                                                       0ul, ~0ul, sizeof(struct HBB_RWBUFFER), RF_ACTIVE);
-                               }
-                               if(acb->sys_res_arcmsr[i] == NULL) {
-                                       arcmsr_free_resource(acb);
-                                       kprintf("arcmsr%d: bus_alloc_resource %d failure!\n", device_get_unit(dev), i);
-                                       return ENOMEM;
-                               }
-                               if(rman_get_start(acb->sys_res_arcmsr[i]) <= 0) {
-                                       arcmsr_free_resource(acb);
-                                       kprintf("arcmsr%d: rman_get_start %d failure!\n", device_get_unit(dev), i);
-                                       return ENXIO;
-                               }
-                               mem_base[i] = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[i]);
-                               if(mem_base[i] == 0) {
-                                       arcmsr_free_resource(acb);
-                                       kprintf("arcmsr%d: rman_get_virtual %d failure!\n", device_get_unit(dev), i);
-                                       return ENXIO;
-                               }
-                               acb->btag[i] = rman_get_bustag(acb->sys_res_arcmsr[i]);
-                               acb->bhandle[i] = rman_get_bushandle(acb->sys_res_arcmsr[i]);
-                       }
-                       freesrb = (struct CommandControlBlock *)acb->uncacheptr;
-                       acb->pmu = (struct MessageUnit_UNION *)((unsigned long)freesrb+ARCMSR_SRBS_POOL_SIZE);
-                       phbbmu = (struct HBB_MessageUnit *)acb->pmu;
-                       phbbmu->hbb_doorbell = (struct HBB_DOORBELL *)mem_base[0];
-                       phbbmu->hbb_rwbuffer = (struct HBB_RWBUFFER *)mem_base[1];
+               acb->rid[0] = rid[0];
+               acb->rid[1] = rid[1];
                }
                break;
        case ACB_ADAPTER_TYPE_C: {
-                       u_int32_t rid0 = PCIR_BAR(1);
-                       vm_offset_t     mem_base0;
+               u_int32_t rid0 = PCIR_BAR(1);
+               vm_offset_t     mem_base0;
 
-                       acb->sys_res_arcmsr[0] = bus_alloc_resource(dev,SYS_RES_MEMORY, &rid0, 0ul, ~0ul, sizeof(struct HBC_MessageUnit), RF_ACTIVE);
-                       if(acb->sys_res_arcmsr[0] == NULL) {
-                               arcmsr_free_resource(acb);
-                               kprintf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
-                               return ENOMEM;
-                       }
-                       if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
-                               arcmsr_free_resource(acb);
-                               kprintf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
-                               return ENXIO;
-                       }
-                       mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
-                       if(mem_base0 == 0) {
-                               arcmsr_free_resource(acb);
-                               kprintf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
-                               return ENXIO;
-                       }
-                       acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
-                       acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
-                       acb->pmu = (struct MessageUnit_UNION *)mem_base0;
+               acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid0, RF_ACTIVE);
+               if(acb->sys_res_arcmsr[0] == NULL) {
+                       arcmsr_free_resource(acb);
+                       kprintf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
+                       return ENOMEM;
+               }
+               if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
+                       arcmsr_free_resource(acb);
+                       kprintf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
+                       return ENXIO;
+               }
+               mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
+               if(mem_base0 == 0) {
+                       arcmsr_free_resource(acb);
+                       kprintf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
+                       return ENXIO;
+               }
+               acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
+               acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
+               acb->pmu = (struct MessageUnit_UNION *)mem_base0;
+               acb->rid[0] = rid0;
                }
                break;
        case ACB_ADAPTER_TYPE_D: {
-                       struct HBD_MessageUnit0 *phbdmu;
-                       u_int32_t rid0 = PCIR_BAR(0);
-                       vm_offset_t     mem_base0;
-
-                       acb->sys_res_arcmsr[0] = bus_alloc_resource(dev,SYS_RES_MEMORY, &rid0, 0ul, ~0ul, sizeof(struct HBD_MessageUnit), RF_ACTIVE);
-                       if(acb->sys_res_arcmsr[0] == NULL) {
-                               arcmsr_free_resource(acb);
-                               kprintf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
-                               return ENOMEM;
-                       }
-                       if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
-                               arcmsr_free_resource(acb);
-                               kprintf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
-                               return ENXIO;
-                       }
-                       mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
-                       if(mem_base0 == 0) {
-                               arcmsr_free_resource(acb);
-                               kprintf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
-                               return ENXIO;
-                       }
-                       acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
-                       acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
-                       acb->pmu = (struct MessageUnit_UNION *)((unsigned long)acb->uncacheptr+ARCMSR_SRBS_POOL_SIZE);
-                       phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
-                       phbdmu->phbdmu = (struct HBD_MessageUnit *)mem_base0;
+               struct HBD_MessageUnit0 *phbdmu;
+               u_int32_t rid0 = PCIR_BAR(0);
+               vm_offset_t     mem_base0;
+
+               acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid0, RF_ACTIVE);
+               if(acb->sys_res_arcmsr[0] == NULL) {
+                       arcmsr_free_resource(acb);
+                       kprintf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
+                       return ENOMEM;
+               }
+               if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
+                       arcmsr_free_resource(acb);
+                       kprintf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
+                       return ENXIO;
+               }
+               mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
+               if(mem_base0 == 0) {
+                       arcmsr_free_resource(acb);
+                       kprintf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
+                       return ENXIO;
+               }
+               acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
+               acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
+               acb->pmu = (struct MessageUnit_UNION *)((unsigned long)acb->uncacheptr+ARCMSR_SRBS_POOL_SIZE);
+               phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
+               phbdmu->phbdmu = (struct HBD_MessageUnit *)mem_base0;
+               acb->rid[0] = rid0;
+               }
+               break;
+       case ACB_ADAPTER_TYPE_E: {
+               u_int32_t rid0 = PCIR_BAR(1);
+               vm_offset_t     mem_base0;
+
+               acb->sys_res_arcmsr[0] = bus_alloc_resource(dev,SYS_RES_MEMORY, &rid0, 0ul, ~0ul, sizeof(struct HBE_MessageUnit), RF_ACTIVE);
+               if(acb->sys_res_arcmsr[0] == NULL) {
+                       arcmsr_free_resource(acb);
+                       kprintf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
+                       return ENOMEM;
+               }
+               if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
+                       arcmsr_free_resource(acb);
+                       kprintf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
+                       return ENXIO;
+               }
+               mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
+               if(mem_base0 == 0) {
+                       arcmsr_free_resource(acb);
+                       kprintf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
+                       return ENXIO;
+               }
+               acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
+               acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
+               acb->pmu = (struct MessageUnit_UNION *)mem_base0;
+               acb->doneq_index = 0;
+               acb->in_doorbell = 0;
+               acb->out_doorbell = 0;
+               acb->rid[0] = rid0;
+               CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /*clear interrupt*/
+               CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, ARCMSR_HBEMU_DOORBELL_SYNC); /* synchronize doorbell to 0 */
                }
                break;
        }
@@ -4148,6 +4628,40 @@ static u_int32_t arcmsr_initialize(device_t dev)
        arcmsr_iop_init(acb);
        return(0);
 }
+
+/*
+************************************************************************
+************************************************************************
+*/
+static void arcmsr_teardown_intr(device_t dev, struct AdapterControlBlock *acb)
+{
+       int i;
+
+       if (acb->acb_flags & ACB_F_MSIX_ENABLED) {
+               for (i = 0; i < acb->msix_vectors; i++) {
+                       if (acb->ih[i])
+                               bus_teardown_intr(dev, acb->irqres[i], acb->ih[i]);
+               //      if (acb->irqres[i] != NULL)
+               //              bus_release_resource(dev, SYS_RES_IRQ,
+               //                  acb->irq_id[i], acb->irqres[i]);
+
+                       acb->ih[i] = NULL;
+               }
+               pci_release_msi(dev);
+       } else {
+               if ((acb->ih[0] != NULL) && (acb->irqres[0] != NULL))
+                       bus_teardown_intr(dev, acb->irqres[0], acb->ih[0]);
+               if (acb->irqres[0] != NULL)
+                       bus_release_resource(dev, SYS_RES_IRQ,
+                           acb->irq_id[0], acb->irqres[0]);
+               if (acb->irq_type == PCI_INTR_TYPE_MSI)
+                       pci_release_msi(dev);
+               acb->ih[0] = NULL;
+               acb->irqres[0] = NULL;
+               acb->irq_type = 0;
+       }
+
+}
 /*
 ************************************************************************
 ************************************************************************
@@ -4156,10 +4670,9 @@ static int arcmsr_attach(device_t dev)
 {
        struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev);
        u_int32_t unit=device_get_unit(dev);
-       struct ccb_setasync csa;
+       union ccb *ccb;
        struct cam_devq *devq;  /* Device Queue to use for this SIM */
        struct resource *irqres;
-       int     rid;
        u_int irq_flags;
 
        if(acb == NULL) {
@@ -4171,23 +4684,21 @@ static int arcmsr_attach(device_t dev)
        acb->pci_unit = unit;
        if(arcmsr_initialize(dev)) {
                kprintf("arcmsr%d: initialize failure!\n", unit);
-               arcmsr_mutex_destroy(acb);
-               return ENXIO;
+               goto initialize_failed;
        }
        /* After setting up the adapter, map our interrupt */
-       rid=0;
-       acb->irq_type = pci_alloc_1intr(dev, arcmsr_msi_enable, &rid,
-           &irq_flags);
-       irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1,
-           irq_flags);
-       if(irqres == NULL ||
-               bus_setup_intr(dev, irqres, INTR_MPSAFE, arcmsr_intr_handler, acb, &acb->ih, NULL)) {
-               arcmsr_free_resource(acb);
-               arcmsr_mutex_destroy(acb);
-               kprintf("arcmsr%d: unable to register interrupt handler!\n", unit);
-               return ENXIO;
-       }
-       acb->irqres = irqres;
+       acb->irq_id[0] = 0;
+       acb->irq_type = pci_alloc_1intr(dev, arcmsr_msi_enable, &acb->irq_id[0], &irq_flags);
+       irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &acb->irq_id[0], irq_flags);
+       if(irqres == NULL ) {
+               kprintf("arcmsr%d: unable to alloc interrupt resource!\n", unit);
+               goto alloc_intr_failed;
+       }
+       if(bus_setup_intr(dev, irqres, INTR_MPSAFE, arcmsr_intr_handler, acb, &acb->ih[0], NULL)) {
+               kprintf("arcmsr%d: unable to setup interrupt handler!\n", unit);
+               goto setup_intr_failed;
+       }
+       acb->irqres[0] = irqres;
        /*
         * Now let the CAM generic SCSI layer find the SCSI devices on
         * the bus *  start queue to reset to the idle loop. *
@@ -4196,65 +4707,66 @@ static int arcmsr_attach(device_t dev)
        */
        devq = cam_simq_alloc(acb->maxOutstanding);
        if(devq == NULL) {
-           arcmsr_free_resource(acb);
-               bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres);
-               if (acb->irq_type == PCI_INTR_TYPE_MSI)
-                       pci_release_msi(dev);
-               arcmsr_mutex_destroy(acb);
                kprintf("arcmsr%d: cam_simq_alloc failure!\n", unit);
-               return ENXIO;
+               goto simq_alloc_failed;
        }
        acb->psim = cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, &acb->isr_lock, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq);
        cam_simq_release(devq);
        if(acb->psim == NULL) {
-               arcmsr_free_resource(acb);
-               bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres);
-               if (acb->irq_type == PCI_INTR_TYPE_MSI)
-                       pci_release_msi(dev);
-               arcmsr_mutex_destroy(acb);
                kprintf("arcmsr%d: cam_sim_alloc failure!\n", unit);
-               return ENXIO;
+               goto sim_alloc_failed;
        }
        ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
        if(xpt_bus_register(acb->psim, 0) != CAM_SUCCESS) {
-               arcmsr_free_resource(acb);
-               bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres);
-               if (acb->irq_type == PCI_INTR_TYPE_MSI)
-                       pci_release_msi(dev);
-               cam_sim_free(acb->psim);
-               arcmsr_mutex_destroy(acb);
                kprintf("arcmsr%d: xpt_bus_register failure!\n", unit);
-               return ENXIO;
+               goto xpt_bus_failed;
        }
-       if(xpt_create_path(&acb->ppath, /* periph */ NULL, cam_sim_path(acb->psim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
-               arcmsr_free_resource(acb);
-               bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres);
-               if (acb->irq_type == PCI_INTR_TYPE_MSI)
-                       pci_release_msi(dev);
-               xpt_bus_deregister(cam_sim_path(acb->psim));
-               cam_sim_free(acb->psim);
-               arcmsr_mutex_destroy(acb);
+       if ((ccb = xpt_alloc_ccb()) == NULL) {
+               kprintf("arcmsr%d: xpt_alloc_ccb failure!\n", unit);
+               goto xpt_ccb_failed;
+       }
+       if(xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(acb->psim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
                kprintf("arcmsr%d: xpt_create_path failure!\n", unit);
-               return ENXIO;
+               goto xpt_path_failed;
        }
        /*
        ****************************************************
        */
-       xpt_setup_ccb(&csa.ccb_h, acb->ppath, /*priority*/5);
-       csa.ccb_h.func_code = XPT_SASYNC_CB;
-       csa.event_enable = AC_FOUND_DEVICE|AC_LOST_DEVICE;
-       csa.callback = arcmsr_async;
-       csa.callback_arg = acb->psim;
-       xpt_action((union ccb *)&csa);
+       xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, /*priority*/5);
+       ccb->ccb_h.func_code = XPT_SCAN_BUS;
+       ccb->ccb_h.cbfcnp = arcmsr_rescanLun_cb;
+       ccb->crcn.flags = CAM_FLAG_NONE;
+       xpt_action(ccb);
        ARCMSR_LOCK_RELEASE(&acb->isr_lock);
+
        /* Create the control device.  */
        acb->ioctl_dev = make_dev(&arcmsr_ops, unit, UID_ROOT, GID_WHEEL /* GID_OPERATOR */, S_IRUSR | S_IWUSR, "arcmsr%d", unit);
-
        acb->ioctl_dev->si_drv1 = acb;
        (void)make_dev_alias(acb->ioctl_dev, "arc%d", unit);
        arcmsr_callout_init(&acb->devmap_callout);
        callout_reset(&acb->devmap_callout, 60 * hz, arcmsr_polling_devmap, acb);
        return (0);
+
+xpt_path_failed:
+        xpt_free_ccb(ccb);
+xpt_ccb_failed:
+       xpt_bus_deregister(cam_sim_path(acb->psim));
+xpt_bus_failed:
+       ARCMSR_LOCK_RELEASE(&acb->isr_lock);
+       cam_sim_free(acb->psim);
+sim_alloc_failed:
+       cam_simq_release(devq);
+simq_alloc_failed:
+       arcmsr_teardown_intr(dev, acb);
+setup_intr_failed:
+       arcmsr_free_resource(acb);
+       bus_release_resource(dev, SYS_RES_IRQ, acb->irq_id[0], irqres);
+alloc_intr_failed:
+       if (acb->irq_type == PCI_INTR_TYPE_MSI)
+               pci_release_msi(dev);
+initialize_failed:
+       arcmsr_mutex_destroy(acb);
+       return ENXIO;
 }
 
 /*
@@ -4306,13 +4818,21 @@ static int arcmsr_probe(device_t dev)
        case PCIDevVenIDARC1882:
        case PCIDevVenIDARC1213:
        case PCIDevVenIDARC1223:
-               if (sub_device_id == ARECA_SUB_DEV_ID_1883)
+               if ((sub_device_id == ARECA_SUB_DEV_ID_1883) ||
+                   (sub_device_id == ARECA_SUB_DEV_ID_1216) ||
+                   (sub_device_id == ARECA_SUB_DEV_ID_1226))
                        type = "SAS 12G";
                else
                        type = "SAS 6G";
                arcmsr_msi_enable = 0;
                break;
+       case PCIDevVenIDARC1884:
+               type = "SAS 12G";
+               arcmsr_msi_enable = 0;
+               break;
        case PCIDevVenIDARC1214:
+               arcmsr_msi_enable = 0;
+       case PCIDevVenIDARC1203:
                type = "SATA 6G";
                break;
        default:
@@ -4322,8 +4842,8 @@ static int arcmsr_probe(device_t dev)
        }
        if(type == x_type)
                return(ENXIO);
-       ksprintf(buf, "Areca %s Host Adapter RAID Controller%s",
-               type, raid6 ? " (RAID6 capable)" : "");
+       ksprintf(buf, "Areca %s Host Adapter RAID Controller %s\n%s\n",
+               type, raid6 ? "(RAID6 capable)" : "", ARCMSR_DRIVER_VERSION);
        device_set_desc_copy(dev, buf);
        return (BUS_PROBE_DEFAULT);
 }
@@ -4378,18 +4898,13 @@ static int arcmsr_detach(device_t dev)
        int i;
 
        callout_stop(&acb->devmap_callout);
-       bus_teardown_intr(dev, acb->irqres, acb->ih);
+       arcmsr_teardown_intr(dev, acb);
        arcmsr_shutdown(dev);
        arcmsr_free_resource(acb);
-       for(i=0; i<2 && (acb->sys_res_arcmsr[i]!=NULL); i++) {
-               bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(i), acb->sys_res_arcmsr[i]);
+       for(i=0; (i < 2) && (acb->sys_res_arcmsr[i]!=NULL); i++) {
+               bus_release_resource(dev, SYS_RES_MEMORY, acb->rid[i], acb->sys_res_arcmsr[i]);
        }
-       bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres);
-       if (acb->irq_type == PCI_INTR_TYPE_MSI)
-               pci_release_msi(dev);
        ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
-       xpt_async(AC_LOST_DEVICE, acb->ppath, NULL);
-       xpt_free_path(acb->ppath);
        xpt_bus_deregister(cam_sim_path(acb->psim));
        cam_sim_free(acb->psim);
        ARCMSR_LOCK_RELEASE(&acb->isr_lock);
index 45edfff..bac8299 100644 (file)
@@ -34,9 +34,7 @@
 **************************************************************************
 * $FreeBSD: head/sys/dev/arcmsr/arcmsr.h 259565 2013-12-18 19:25:40Z delphij $
 */
-
 #include <sys/ioccom.h>
-
 #define ARCMSR_SCSI_INITIATOR_ID       255
 #define ARCMSR_DEV_SECTOR_SIZE         512
 #define ARCMSR_MAX_XFER_SECTORS                4096
@@ -53,7 +51,8 @@
 #define ARCMSR_RELEASE_SIMQ_LEVEL      230
 #define ARCMSR_MAX_HBB_POSTQUEUE       264     /* (ARCMSR_MAX_OUTSTANDING_CMD+8) */
 #define ARCMSR_MAX_HBD_POSTQUEUE       256
-#define        ARCMSR_TIMEOUT_DELAY            60      /* in sec */
+#define ARCMSR_TIMEOUT_DELAY           60      /* in sec */
+#define ARCMSR_NUM_MSIX_VECTORS                4
 /*
 *********************************************************************
 */
@@ -92,6 +91,7 @@ typedef struct lock           arcmsr_lock_t;
 #define PCI_DEVICE_ID_ARECA_1170        0x1170 /* Device ID    */
 #define PCI_DEVICE_ID_ARECA_1200        0x1200 /* Device ID    */
 #define PCI_DEVICE_ID_ARECA_1201        0x1201 /* Device ID    */
+#define PCI_DEVICE_ID_ARECA_1203        0x1203 /* Device ID    */
 #define PCI_DEVICE_ID_ARECA_1210        0x1210 /* Device ID    */
 #define PCI_DEVICE_ID_ARECA_1212        0x1212 /* Device ID    */
 #define PCI_DEVICE_ID_ARECA_1214        0x1214 /* Device ID    */
@@ -108,14 +108,18 @@ typedef struct lock               arcmsr_lock_t;
 #define PCI_DEVICE_ID_ARECA_1680        0x1680 /* Device ID    */
 #define PCI_DEVICE_ID_ARECA_1681        0x1681 /* Device ID    */
 #define PCI_DEVICE_ID_ARECA_1880        0x1880 /* Device ID    */
+#define PCI_DEVICE_ID_ARECA_1884        0x1884 /* Device ID    */
 
 #define ARECA_SUB_DEV_ID_1880  0x1880 /* Subsystem Device ID   */
 #define ARECA_SUB_DEV_ID_1882  0x1882 /* Subsystem Device ID   */
 #define ARECA_SUB_DEV_ID_1883  0x1883 /* Subsystem Device ID   */
+#define ARECA_SUB_DEV_ID_1884  0x1884 /* Subsystem Device ID   */
 #define ARECA_SUB_DEV_ID_1212  0x1212 /* Subsystem Device ID   */
 #define ARECA_SUB_DEV_ID_1213  0x1213 /* Subsystem Device ID   */
+#define ARECA_SUB_DEV_ID_1216  0x1216 /* Subsystem Device ID   */
 #define ARECA_SUB_DEV_ID_1222  0x1222 /* Subsystem Device ID   */
 #define ARECA_SUB_DEV_ID_1223  0x1223 /* Subsystem Device ID   */
+#define ARECA_SUB_DEV_ID_1226  0x1226 /* Subsystem Device ID   */
 
 #define PCIDevVenIDARC1110              0x111017D3 /* Vendor Device ID */
 #define PCIDevVenIDARC1120              0x112017D3 /* Vendor Device ID */
@@ -124,6 +128,7 @@ typedef struct lock         arcmsr_lock_t;
 #define PCIDevVenIDARC1170              0x117017D3 /* Vendor Device ID */
 #define PCIDevVenIDARC1200              0x120017D3 /* Vendor Device ID */
 #define PCIDevVenIDARC1201              0x120117D3 /* Vendor Device ID */
+#define PCIDevVenIDARC1203              0x120317D3 /* Vendor Device ID */
 #define PCIDevVenIDARC1210              0x121017D3 /* Vendor Device ID */
 #define PCIDevVenIDARC1212              0x121217D3 /* Vendor Device ID */
 #define PCIDevVenIDARC1213              0x121317D3 /* Vendor Device ID */
@@ -143,6 +148,7 @@ typedef struct lock         arcmsr_lock_t;
 #define PCIDevVenIDARC1681              0x168117D3 /* Vendor Device ID */
 #define PCIDevVenIDARC1880              0x188017D3 /* Vendor Device ID */
 #define PCIDevVenIDARC1882              0x188217D3 /* Vendor Device ID */
+#define PCIDevVenIDARC1884              0x188417D3 /* Vendor Device ID */
 
 #ifndef PCIR_BARS
        #define PCIR_BARS       0x10
@@ -181,6 +187,8 @@ typedef struct lock         arcmsr_lock_t;
 */
 #define CHIP_REG_READ32(s, b, r)       bus_space_read_4(acb->btag[b], acb->bhandle[b], offsetof(struct s, r))
 #define CHIP_REG_WRITE32(s, b, r, d)   bus_space_write_4(acb->btag[b], acb->bhandle[b], offsetof(struct s, r), d)
+#define READ_CHIP_REG32(b, r)          bus_space_read_4(acb->btag[b], acb->bhandle[b], r)
+#define WRITE_CHIP_REG32(b, r, d)      bus_space_write_4(acb->btag[b], acb->bhandle[b], r, d)
 /*
 **********************************************************************************
 **    IOCTL CONTROL Mail Box
@@ -294,6 +302,11 @@ struct CMD_MESSAGE_FIELD {
 #define ARCMSR_IOP2DRV_DOORBELL                 0x00020408    /* window of "instruction flags" from iop to driver */
 #define ARCMSR_IOP2DRV_DOORBELL_MASK            0x0002040C
 
+#define ARCMSR_IOP2DRV_DOORBELL_1203            0x00021870    /* window of "instruction flags" from iop to driver */
+#define ARCMSR_IOP2DRV_DOORBELL_MASK_1203       0x00021874
+#define ARCMSR_DRV2IOP_DOORBELL_1203            0x00021878    /* window of "instruction flags" from driver to iop */
+#define ARCMSR_DRV2IOP_DOORBELL_MASK_1203       0x0002187C
+
 /* ARECA FLAG LANGUAGE */
 #define ARCMSR_IOP2DRV_DATA_WRITE_OK            0x00000001        /* ioctl transfer */
 #define ARCMSR_IOP2DRV_DATA_READ_OK             0x00000002        /* ioctl transfer */
@@ -444,6 +457,26 @@ struct CMD_MESSAGE_FIELD {
 
 /*ARCMSR_HBAMU_MESSAGE_FIRMWARE_OK*/
 #define ARCMSR_HBDMU_MESSAGE_FIRMWARE_OK               0x80000000
+/* 
+*******************************************************************************
+**                SPEC. for Areca HBE adapter
+*******************************************************************************
+*/
+#define ARCMSR_SIGNATURE_1884                          0x188417D3
+#define ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR             0x00000001
+#define ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR            0x00000008
+#define ARCMSR_HBEMU_ALL_INTMASKENABLE                 0x00000009 /* disable all ISR */
+
+#define ARCMSR_HBEMU_DRV2IOP_DATA_WRITE_OK             0x00000002
+#define ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK              0x00000004
+#define ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE          0x00000008 /* inbound message 0 ready */
+#define ARCMSR_HBEMU_IOP2DRV_DATA_WRITE_OK             0x00000002
+#define ARCMSR_HBEMU_IOP2DRV_DATA_READ_OK              0x00000004
+#define ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE          0x00000008 /* outbound message 0 ready */
+#define ARCMSR_HBEMU_MESSAGE_FIRMWARE_OK               0x80000000 /* ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK */
+/* ARC-1884 doorbell sync */
+#define ARCMSR_HBEMU_DOORBELL_SYNC                     0x100
+#define ARCMSR_ARC188X_RESET_ADAPTER                   0x00000004
 /*
 *********************************************************************
 ** Message Unit structure
@@ -479,6 +512,14 @@ struct HBA_MessageUnit
 ** 
 *********************************************************************
 */
+struct HBB_DOORBELL_1203
+{
+       u_int8_t        doorbell_reserved[ARCMSR_IOP2DRV_DOORBELL_1203]; /*reserved */
+       u_int32_t       iop2drv_doorbell;          /*offset 0x00021870:00,01,02,03: window of "instruction flags" from iop to driver */
+       u_int32_t       iop2drv_doorbell_mask;     /*                  04,05,06,07: doorbell mask */
+       u_int32_t       drv2iop_doorbell;          /*                  08,09,10,11: window of "instruction flags" from driver to iop */
+       u_int32_t       drv2iop_doorbell_mask;     /*                  12,13,14,15: doorbell mask */
+};
 struct HBB_DOORBELL
 {
        u_int8_t        doorbell_reserved[ARCMSR_DRV2IOP_DOORBELL]; /*reserved */
@@ -513,6 +554,10 @@ struct HBB_MessageUnit
        int32_t                 doneq_index;                                                               /* done queue index */
        struct HBB_DOORBELL    *hbb_doorbell;
        struct HBB_RWBUFFER    *hbb_rwbuffer;
+       bus_size_t              drv2iop_doorbell;          /* window of "instruction flags" from driver to iop */
+       bus_size_t              drv2iop_doorbell_mask;     /* doorbell mask */
+       bus_size_t              iop2drv_doorbell;          /* window of "instruction flags" from iop to driver */
+       bus_size_t              iop2drv_doorbell_mask;     /* doorbell mask */
 };
 
 /*
@@ -659,6 +704,92 @@ struct HBD_MessageUnit0 {
        uint16_t doneq_index;
        struct HBD_MessageUnit  *phbdmu;
 };
+/*
+*********************************************************************
+** 
+*********************************************************************
+*/
+struct HBE_MessageUnit {
+       u_int32_t       iobound_doorbell;                           /*0000 0003*/
+       u_int32_t       write_sequence_3xxx;                        /*0004 0007*/
+       u_int32_t       host_diagnostic_3xxx;                       /*0008 000B*/
+       u_int32_t       posted_outbound_doorbell;                   /*000C 000F*/
+       u_int32_t       master_error_attribute;                     /*0010 0013*/
+       u_int32_t       master_error_address_low;                   /*0014 0017*/
+       u_int32_t       master_error_address_high;                  /*0018 001B*/
+       u_int32_t       hcb_size;                                   /*001C 001F*/
+       u_int32_t       inbound_doorbell;                           /*0020 0023*/
+       u_int32_t       diagnostic_rw_data;                         /*0024 0027*/
+       u_int32_t       diagnostic_rw_address_low;                  /*0028 002B*/
+       u_int32_t       diagnostic_rw_address_high;                 /*002C 002F*/
+       u_int32_t       host_int_status;                            /*0030 0033 host interrupt status*/
+       u_int32_t       host_int_mask;                              /*0034 0037 host interrupt mask*/
+       u_int32_t       dcr_data;                                   /*0038 003B*/
+       u_int32_t       dcr_address;                                /*003C 003F*/
+       u_int32_t       inbound_queueport;                          /*0040 0043 port32 host inbound queue port*/
+       u_int32_t       outbound_queueport;                         /*0044 0047 port32 host outbound queue port*/
+       u_int32_t       hcb_pci_address_low;                        /*0048 004B*/
+       u_int32_t       hcb_pci_address_high;                       /*004C 004F*/
+       u_int32_t       iop_int_status;                             /*0050 0053*/
+       u_int32_t       iop_int_mask;                               /*0054 0057*/
+       u_int32_t       iop_inbound_queue_port;                     /*0058 005B*/
+       u_int32_t       iop_outbound_queue_port;                    /*005C 005F*/
+       u_int32_t       inbound_free_list_index;                    /*0060 0063*/
+       u_int32_t       inbound_post_list_index;                    /*0064 0067*/
+       u_int32_t       outbound_free_list_index;                   /*0068 006B*/
+       u_int32_t       outbound_post_list_index;                   /*006C 006F*/
+       u_int32_t       inbound_doorbell_clear;                     /*0070 0073*/
+       u_int32_t       i2o_message_unit_control;                   /*0074 0077*/
+       u_int32_t       last_used_message_source_address_low;       /*0078 007B*/
+       u_int32_t       last_used_message_source_address_high;      /*007C 007F*/
+       u_int32_t       pull_mode_data_byte_count[4];               /*0080 008F*/
+       u_int32_t       message_dest_address_index;                 /*0090 0093*/
+       u_int32_t       done_queue_not_empty_int_counter_timer;     /*0094 0097*/
+       u_int32_t       utility_A_int_counter_timer;                /*0098 009B*/
+       u_int32_t       outbound_doorbell;                          /*009C 009F*/
+       u_int32_t       outbound_doorbell_clear;                    /*00A0 00A3*/
+       u_int32_t       message_source_address_index;               /*00A4 00A7*/
+       u_int32_t       message_done_queue_index;                   /*00A8 00AB*/
+       u_int32_t       reserved0;                                  /*00AC 00AF*/
+       u_int32_t       inbound_msgaddr0;                           /*00B0 00B3 scratchpad0*/
+       u_int32_t       inbound_msgaddr1;                           /*00B4 00B7 scratchpad1*/
+       u_int32_t       outbound_msgaddr0;                          /*00B8 00BB scratchpad2*/
+       u_int32_t       outbound_msgaddr1;                          /*00BC 00BF scratchpad3*/
+       u_int32_t       inbound_queueport_low;                      /*00C0 00C3 port64 host inbound queue port low*/
+       u_int32_t       inbound_queueport_high;                     /*00C4 00C7 port64 host inbound queue port high*/
+       u_int32_t       outbound_queueport_low;                     /*00C8 00CB port64 host outbound queue port low*/
+       u_int32_t       outbound_queueport_high;                    /*00CC 00CF port64 host outbound queue port high*/
+       u_int32_t       iop_inbound_queue_port_low;                 /*00D0 00D3*/
+       u_int32_t       iop_inbound_queue_port_high;                /*00D4 00D7*/
+       u_int32_t       iop_outbound_queue_port_low;                /*00D8 00DB*/
+       u_int32_t       iop_outbound_queue_port_high;               /*00DC 00DF*/
+       u_int32_t       message_dest_queue_port_low;                /*00E0 00E3*/
+       u_int32_t       message_dest_queue_port_high;               /*00E4 00E7*/
+       u_int32_t       last_used_message_dest_address_low;         /*00E8 00EB*/
+       u_int32_t       last_used_message_dest_address_high;        /*00EC 00EF*/
+       u_int32_t       message_done_queue_base_address_low;        /*00F0 00F3*/
+       u_int32_t       message_done_queue_base_address_high;       /*00F4 00F7*/
+       u_int32_t       host_diagnostic;                            /*00F8 00FB*/
+       u_int32_t       write_sequence;                             /*00FC 00FF*/
+       u_int32_t       reserved1[46];                              /*0100 01B7*/
+       u_int32_t       reply_post_producer_index;                  /*01B8 01BB*/
+       u_int32_t       reply_post_consumer_index;                  /*01BC 01BF*/
+       u_int32_t       reserved2[1936];                            /*01C0 1FFF*/
+       u_int32_t       message_wbuffer[32];                        /*2000 207F*/
+       u_int32_t       reserved3[32];                              /*2080 20FF*/
+       u_int32_t       message_rbuffer[32];                        /*2100 217F*/
+       u_int32_t       reserved4[32];                              /*2180 21FF*/
+       u_int32_t       msgcode_rwbuffer[256];                      /*2200 23FF*/
+};
+
+typedef struct deliver_completeQ {
+       u_int16_t       cmdFlag;
+       u_int16_t       cmdSMID;
+       u_int16_t       cmdLMID;        // reserved (0)
+       u_int16_t       cmdFlag2;       // reserved (0)
+} DeliverQ, CompletionQ, *pDeliver_Q, *pCompletion_Q;
+
+#define        COMPLETION_Q_POOL_SIZE  (sizeof(struct deliver_completeQ) * 512 + 128)
 
 /*
 *********************************************************************
@@ -672,6 +803,7 @@ struct MessageUnit_UNION
                struct HBB_MessageUnit          hbbmu;
                struct HBC_MessageUnit          hbcmu;
                struct HBD_MessageUnit0         hbdmu;
+               struct HBE_MessageUnit          hbemu;
        } muu;
 };
 /* 
@@ -1061,6 +1193,7 @@ struct CommandControlBlock {
        u_int16_t               srb_state;              /* 538-539 */
        u_int32_t               cdb_phyaddr_high;       /* 540-543 */
        struct  callout         ccb_callout;
+       u_int32_t               smid;
     /*  ==========================================================  */
 };
 /*     srb_flags */
@@ -1093,10 +1226,11 @@ struct CommandControlBlock {
 **                 Adapter Control Block
 *********************************************************************
 */
-#define ACB_ADAPTER_TYPE_A     0x00000001      /* hba I IOP */
-#define ACB_ADAPTER_TYPE_B     0x00000002      /* hbb M IOP */
-#define ACB_ADAPTER_TYPE_C     0x00000004      /* hbc L IOP */
-#define ACB_ADAPTER_TYPE_D     0x00000008      /* hbd M IOP */
+#define ACB_ADAPTER_TYPE_A     0x00000000      /* hba I IOP */
+#define ACB_ADAPTER_TYPE_B     0x00000001      /* hbb M IOP */
+#define ACB_ADAPTER_TYPE_C     0x00000002      /* hbc L IOP */
+#define ACB_ADAPTER_TYPE_D     0x00000003      /* hbd M IOP */
+#define ACB_ADAPTER_TYPE_E     0x00000004      /* hbd L IOP */
 
 struct AdapterControlBlock {
        u_int32_t               adapter_type;           /* adapter A,B..... */
@@ -1112,8 +1246,9 @@ struct AdapterControlBlock {
        int                     pci_unit;
        
        struct resource         *sys_res_arcmsr[2];
-       struct resource         *irqres;
-       void                    *ih;                    /* interrupt handle */
+       struct resource         *irqres[ARCMSR_NUM_MSIX_VECTORS];
+       void                    *ih[ARCMSR_NUM_MSIX_VECTORS]; /* interrupt handle */
+       int                     irq_id[ARCMSR_NUM_MSIX_VECTORS];
        int                     irq_type;
        
        /* Hooks into the CAM XPT */
@@ -1156,6 +1291,8 @@ struct AdapterControlBlock {
        arcmsr_lock_t           srb_lock;
        arcmsr_lock_t           postDone_lock;
        arcmsr_lock_t           qbuffer_lock;
+       arcmsr_lock_t           io_lock;
+       arcmsr_lock_t           sim_lock;
        
        u_int8_t                devstate[ARCMSR_MAX_TARGETID][ARCMSR_MAX_TARGETLUN]; /* id0 ..... id15,lun0...lun7 */
        u_int32_t               num_resets;
@@ -1175,6 +1312,13 @@ struct AdapterControlBlock {
        u_int32_t               adapter_bus_speed;
        u_int32_t               maxOutstanding;
        u_int16_t               sub_device_id;
+       u_int32_t               doneq_index;
+       u_int32_t               in_doorbell;
+       u_int32_t               out_doorbell;
+       u_int32_t               completionQ_entry;
+       pCompletion_Q           pCompletionQ;
+       int                     msix_vectors;
+       int                     rid[2];
 };/* HW_DEVICE_EXTENSION */
 /* acb_flags */
 #define ACB_F_SCSISTOPADAPTER           0x0001
@@ -1190,6 +1334,7 @@ struct AdapterControlBlock {
 #define ACB_F_CAM_DEV_QFRZN             0x0400
 #define ACB_F_BUS_HANG_ON               0x0800         /* need hardware reset bus */
 #define ACB_F_SRB_FUNCTION_POWER        0x1000
+#define ACB_F_MSIX_ENABLED             0x2000
 /* devstate */
 #define ARECA_RAID_GONE                0x55
 #define ARECA_RAID_GOOD                0xaa