arcmsr(4): Sync with FreeBSD (1.20.00.25 -> 1.20.00.29).
authorSascha Wildner <saw@online.de>
Tue, 25 Feb 2014 09:27:13 +0000 (10:27 +0100)
committerSascha Wildner <saw@online.de>
Tue, 25 Feb 2014 09:28:08 +0000 (10:28 +0100)
Adds support for ARC1214, ARC1224, ARC1264, ARC1284, and ARC1883, mainly.

Unfortunately, lots of style fixes, whitespace adjustment, etc. are mixed up
in it too, so it's a rather large commit.

Also, this upgrade has so far only been tested with my ARC-1210.

share/man/man4/arcmsr.4
sys/dev/raid/arcmsr/arcmsr.c
sys/dev/raid/arcmsr/arcmsr.h

index 8935339..8037326 100644 (file)
@@ -22,9 +22,9 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.\" $FreeBSD: src/share/man/man4/arcmsr.4,v 1.8 2012/09/04 05:15:54 delphij Exp $
+.\" $FreeBSD: head/share/man/man4/arcmsr.4 259564 2013-12-18 19:23:05Z delphij $
 .\"
-.Dd September 25, 2012
+.Dd February 25, 2014
 .Dt ARCMSR 4
 .Os
 .Sh NAME
@@ -106,12 +106,16 @@ ARC-1212
 .It
 ARC-1213
 .It
+ARC-1214
+.It
 ARC-1220
 .It
 ARC-1222
 .It
 ARC-1223
 .It
+ARC-1224
+.It
 ARC-1230
 .It
 ARC-1231
@@ -120,10 +124,14 @@ ARC-1260
 .It
 ARC-1261
 .It
+ARC-1264
+.It
 ARC-1270
 .It
 ARC-1280
 .It
+ARC-1284
+.It
 ARC-1210ML
 .It
 ARC-1220ML
@@ -159,6 +167,8 @@ ARC-1880ix
 ARC-1880ixl
 .It
 ARC-1882
+.It
+ARC-1883
 .El
 .Sh FILES
 .Bl -tag -width ".Pa /dev/arcmsr?" -compact
index f08380d..99d72b3 100644 (file)
@@ -1,17 +1,15 @@
 /*
-*****************************************************************************************
-**        O.S   : FreeBSD
+********************************************************************************
+**        O   : FreeBSD
 **   FILE NAME  : arcmsr.c
 **        BY    : Erich Chen, Ching Huang
 **   Description: SCSI RAID Device Driver for
-**                ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX/ARC188x) SATA/SAS RAID HOST Adapter
-**                ARCMSR RAID Host adapter
-**                [RAID controller:INTEL 331(PCI-X) 341(PCI-EXPRESS) chip set]
-******************************************************************************************
-************************************************************************
+**                ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX/ARC188x)
+**                SATA/SAS RAID HOST Adapter
+********************************************************************************
+********************************************************************************
 **
-** Copyright (c) 2004-2010 ARECA Co. Ltd.
-**        Erich Chen, Taipei Taiwan All rights reserved.
+** Copyright (C) 2002 - 2012, Areca Technology Corporation All rights reserved.
 **
 ** Redistribution and use in source and binary forms, with or without
 ** modification, are permitted provided that the following conditions
 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 **(INCLUDING NEGLIGENCE OR OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF
 ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-**************************************************************************
+********************************************************************************
 ** History
 **
-**        REV#         DATE             NAME             DESCRIPTION
-**     1.00.00.00   03/31/2004      Erich Chen           First release
-**     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
-**                                                       and firmware update notify for hardware bug fix
-**                                                       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
-**                                                       with scsi pass-through command
-**                                                       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
-**     1.20.00.16   10/10/2009      Erich Chen           Bug fix for RAID adapter type ARC120x
-**                                                       bus_dmamem_alloc() with BUS_DMA_ZERO
-**     1.20.00.17   07/15/2010      Ching Huang          Added support ARC1880
-**                                                       report CAM_DEV_NOT_THERE instead of CAM_SEL_TIMEOUT when device failed,
-**                                                       prevent cam_periph_error removing all LUN devices of one Target id
-**                                                       for any one LUN device failed
-**     1.20.00.18   10/14/2010      Ching Huang          Fixed "inquiry data fails comparion at DV1 step"
-**                  10/25/2010      Ching Huang          Fixed bad range input in bus_alloc_resource for ADAPTER_TYPE_B
-**     1.20.00.19   11/11/2010      Ching Huang          Fixed arcmsr driver prevent arcsas support for Areca SAS HBA ARC13x0
-**     1.20.00.20   12/08/2010      Ching Huang          Avoid calling atomic_set_int function
-**     1.20.00.21   02/08/2011      Ching Huang          Implement I/O request timeout
-**                  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   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
+**    REV#         DATE         NAME        DESCRIPTION
+** 1.00.00.00   03/31/2004  Erich Chen      First release
+** 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 
+**                                          and firmware update notify for hardware bug fix
+**                                          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 
+**                                          with scsi pass-through command
+**                                          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
+** 1.20.00.16   10/10/2009  Erich Chen      Bug fix for RAID adapter type ARC120x
+**                                          bus_dmamem_alloc() with BUS_DMA_ZERO
+** 1.20.00.17   07/15/2010  Ching Huang     Added support ARC1880
+**                                          report CAM_DEV_NOT_THERE instead of CAM_SEL_TIMEOUT when device failed,
+**                                          prevent cam_periph_error removing all LUN devices of one Target id
+**                                          for any one LUN device failed
+** 1.20.00.18   10/14/2010  Ching Huang     Fixed "inquiry data fails comparion at DV1 step"
+**              10/25/2010  Ching Huang     Fixed bad range input in bus_alloc_resource for ADAPTER_TYPE_B
+** 1.20.00.19   11/11/2010  Ching Huang     Fixed arcmsr driver prevent arcsas support for Areca SAS HBA ARC13x0
+** 1.20.00.20   12/08/2010  Ching Huang     Avoid calling atomic_set_int function
+** 1.20.00.21   02/08/2011  Ching Huang     Implement I/O request timeout
+**              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   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.26   12/14/2012  Ching Huang     Added support ARC1214,1224,1264,1284
+** 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
 ******************************************************************************************
-* $FreeBSD: src/sys/dev/arcmsr/arcmsr.c,v 1.43 2012/09/04 05:15:54 delphij Exp $
+* $FreeBSD: head/sys/dev/arcmsr/arcmsr.c 259565 2013-12-18 19:25:40Z delphij $
 */
 #if 0
 #define ARCMSR_DEBUG1                  1
 #include <sys/endian.h>
 #include <bus/pci/pcivar.h>
 #include <bus/pci/pcireg.h>
-#define ARCMSR_LOCK_INIT(l, s) lockinit(l, s, 0, LK_CANRECURSE)
-#define ARCMSR_LOCK_DESTROY(l) lockuninit(l)
-#define ARCMSR_LOCK_ACQUIRE(l) lockmgr(l, LK_EXCLUSIVE)
-#define ARCMSR_LOCK_RELEASE(l) lockmgr(l, LK_RELEASE)
-#define ARCMSR_LOCK_TRY(l)     lockmgr(&l, LK_EXCLUSIVE|LK_NOWAIT);
-#define arcmsr_htole32(x)      htole32(x)
-typedef struct lock            arcmsr_lock_t;
 
 #define arcmsr_callout_init(a) callout_init_mp(a);
 
-#define ARCMSR_DRIVER_VERSION                  "Driver Version 1.20.00.25 2012-08-17"
+#define ARCMSR_DRIVER_VERSION  "arcmsr version 1.20.00.29 2013-12-18"
 #include <dev/raid/arcmsr/arcmsr.h>
-#define        SRB_SIZE                                                ((sizeof(struct CommandControlBlock)+0x1f) & 0xffe0)
-#define ARCMSR_SRBS_POOL_SIZE           (SRB_SIZE * ARCMSR_MAX_FREESRB_NUM)
-/*
-**************************************************************************
-**************************************************************************
-*/
-#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)
 /*
 **************************************************************************
 **************************************************************************
 */
 static void arcmsr_free_srb(struct CommandControlBlock *srb);
-static struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb);
-static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb);
+static struct CommandControlBlock *arcmsr_get_freesrb(struct AdapterControlBlock *acb);
+static u_int8_t arcmsr_seek_cmd2abort(union ccb *abortccb);
 static int arcmsr_probe(device_t dev);
 static int arcmsr_attach(device_t dev);
 static int arcmsr_detach(device_t dev);
@@ -160,18 +147,20 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb);
 static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb);
 static void arcmsr_iop_init(struct AdapterControlBlock *acb);
 static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb);
-static void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb);
+static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, struct QBUFFER *prbuffer);
+static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb);
 static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb);
 static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag);
 static void arcmsr_iop_reset(struct AdapterControlBlock *acb);
 static void arcmsr_report_sense_info(struct CommandControlBlock *srb);
-static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t * dm_segs, u_int32_t nseg);
-static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb);
+static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t *dm_segs, u_int32_t nseg);
+static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *pccb);
 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);
 #ifdef ARCMSR_DEBUG1
 static void arcmsr_dump_data(struct AdapterControlBlock *acb);
 #endif
@@ -201,8 +190,6 @@ 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
 };
 
@@ -239,9 +226,9 @@ static int
 arcmsr_open(struct dev_open_args *ap)
 {
        cdev_t dev = ap->a_head.a_dev;
-       struct AdapterControlBlock *acb=dev->si_drv1;
+       struct AdapterControlBlock *acb = dev->si_drv1;
 
-       if(acb==NULL) {
+       if(acb == NULL) {
                return ENXIO;
        }
        return (0);
@@ -256,9 +243,9 @@ static int
 arcmsr_close(struct dev_close_args *ap)
 {
        cdev_t dev = ap->a_head.a_dev;
-       struct AdapterControlBlock *acb=dev->si_drv1;
+       struct AdapterControlBlock *acb = dev->si_drv1;
 
-       if(acb==NULL) {
+       if(acb == NULL) {
                return ENXIO;
        }
        return 0;
@@ -275,9 +262,9 @@ arcmsr_ioctl(struct dev_ioctl_args *ap)
        cdev_t dev = ap->a_head.a_dev;
        u_long ioctl_cmd = ap->a_cmd;
        caddr_t arg = ap->a_data;
-       struct AdapterControlBlock *acb=dev->si_drv1;
+       struct AdapterControlBlock *acb = dev->si_drv1;
 
-       if(acb==NULL) {
+       if(acb == NULL) {
                return ENXIO;
        }
        return (arcmsr_iop_ioctlcmd(acb, ioctl_cmd, arg));
@@ -289,28 +276,34 @@ arcmsr_ioctl(struct dev_ioctl_args *ap)
 */
 static u_int32_t arcmsr_disable_allintr( struct AdapterControlBlock *acb)
 {
-       u_int32_t intmask_org=0;
+       u_int32_t intmask_org = 0;
 
        switch (acb->adapter_type) {
        case ACB_ADAPTER_TYPE_A: {
                        /* disable all outbound interrupt */
-                       intmask_org=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intmask); /* disable outbound message0 int */
+                       intmask_org = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intmask); /* disable outbound message0 int */
                        CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE);
                }
                break;
        case ACB_ADAPTER_TYPE_B: {
                        /* disable all outbound interrupt */
-                       intmask_org=CHIP_REG_READ32(HBB_DOORBELL,
+                       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 */
                }
                break;
        case ACB_ADAPTER_TYPE_C: {
                        /* disable all outbound interrupt */
-                       intmask_org=CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_mask)  ; /* disable outbound message0 int */
+                       intmask_org = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_mask)        ; /* disable outbound message0 int */
                        CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org|ARCMSR_HBCMU_ALL_INTMASKENABLE);
                }
                break;
+       case ACB_ADAPTER_TYPE_D: {
+                       /* disable all outbound interrupt */
+                       intmask_org = CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable)    ; /* disable outbound message0 int */
+                       CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, ARCMSR_HBDMU_ALL_INT_DISABLE);
+               }
+               break;
        }
        return (intmask_org);
 }
@@ -325,23 +318,31 @@ static void arcmsr_enable_allintr( struct AdapterControlBlock *acb, u_int32_t in
        switch (acb->adapter_type) {
        case ACB_ADAPTER_TYPE_A: {
                        /* enable outbound Post Queue, outbound doorbell Interrupt */
-                       mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE);
+                       mask = ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE);
                        CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org & mask);
                        acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff;
                }
                break;
        case ACB_ADAPTER_TYPE_B: {
                        /* 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);
+                       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*/
                        acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f;
                }
                break;
        case ACB_ADAPTER_TYPE_C: {
                        /* enable outbound Post Queue, outbound doorbell Interrupt */
-                       mask=~(ARCMSR_HBCMU_UTILITY_A_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK);
+                       mask = ~(ARCMSR_HBCMU_UTILITY_A_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK);
                        CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org & mask);
-                       acb->outbound_int_enable= ~(intmask_org & mask) & 0x0000000f;
+                       acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f;
+               }
+               break;
+       case ACB_ADAPTER_TYPE_D: {
+                       /* enable outbound Post Queue, outbound doorbell Interrupt */
+                       mask = ARCMSR_HBDMU_ALL_INT_ENABLE;
+                       CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, intmask_org | mask);
+                       CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable);
+                       acb->outbound_int_enable = mask;
                }
                break;
        }
@@ -353,7 +354,7 @@ static void arcmsr_enable_allintr( struct AdapterControlBlock *acb, u_int32_t in
 static u_int8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb)
 {
        u_int32_t Index;
-       u_int8_t Retries=0x00;
+       u_int8_t Retries = 0x00;
 
        do {
                for(Index=0; Index < 100; Index++) {
@@ -373,7 +374,7 @@ static u_int8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb)
 static u_int8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb)
 {
        u_int32_t Index;
-       u_int8_t Retries=0x00;
+       u_int8_t Retries = 0x00;
 
        do {
                for(Index=0; Index < 100; Index++) {
@@ -394,7 +395,7 @@ static u_int8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb)
 static u_int8_t arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock *acb)
 {
        u_int32_t Index;
-       u_int8_t Retries=0x00;
+       u_int8_t Retries = 0x00;
 
        do {
                for(Index=0; Index < 100; Index++) {
@@ -408,12 +409,32 @@ static u_int8_t arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock *acb)
        return (FALSE);
 }
 /*
+**********************************************************************
+**********************************************************************
+*/
+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) {
+                               CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR);/*clear interrupt*/
+                               return TRUE;
+                       }
+                       UDELAY(10000);
+               }/*max 1 seconds*/
+       }while(Retries++ < 20);/*max 20 sec*/
+       return (FALSE);
+}
+/*
 ************************************************************************
 ************************************************************************
 */
 static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb)
 {
-       int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */
+       int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */
 
        CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
        do {
@@ -422,7 +443,7 @@ static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb)
                } else {
                        retry_count--;
                }
-       }while(retry_count!=0);
+       }while(retry_count != 0);
 }
 /*
 ************************************************************************
@@ -430,7 +451,7 @@ 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 */
+       int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */
 
        CHIP_REG_WRITE32(HBB_DOORBELL,
        0, drv2iop_doorbell, ARCMSR_MESSAGE_FLUSH_CACHE);
@@ -440,7 +461,7 @@ static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb)
                } else {
                        retry_count--;
                }
-       }while(retry_count!=0);
+       }while(retry_count != 0);
 }
 /*
 ************************************************************************
@@ -448,7 +469,7 @@ static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb)
 */
 static void arcmsr_flush_hbc_cache(struct AdapterControlBlock *acb)
 {
-       int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */
+       int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */
 
        CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
        CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
@@ -458,7 +479,24 @@ static void arcmsr_flush_hbc_cache(struct AdapterControlBlock *acb)
                } else {
                        retry_count--;
                }
-       }while(retry_count!=0);
+       }while(retry_count != 0);
+}
+/*
+************************************************************************
+************************************************************************
+*/
+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)) {
+                       break;
+               } else {
+                       retry_count--;
+               }
+       }while(retry_count != 0);
 }
 /*
 ************************************************************************
@@ -479,6 +517,10 @@ static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
                        arcmsr_flush_hbc_cache(acb);
                }
                break;
+       case ACB_ADAPTER_TYPE_D: {
+                       arcmsr_flush_hbd_cache(acb);
+               }
+               break;
        }
 }
 /*
@@ -512,44 +554,24 @@ static int arcmsr_resume(device_t dev)
 */
 static void arcmsr_async(void *cb_arg, u_int32_t code, struct cam_path *path, void *arg)
 {
-}
-/*
-**********************************************************************
-**********************************************************************
-*/
-static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag)
-{
-       struct AdapterControlBlock *acb=srb->acb;
-       union ccb * pccb=srb->pccb;
-
-       if(srb->srb_flags & SRB_FLAG_TIMER_START)
-               callout_stop(&srb->ccb_callout);
-       if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
-               bus_dmasync_op_t op;
-
-               if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
-                       op = BUS_DMASYNC_POSTREAD;
-               } else {
-                       op = BUS_DMASYNC_POSTWRITE;
-               }
-               bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op);
-               bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap);
-       }
-       if(stand_flag==1) {
-               atomic_subtract_int(&acb->srboutstandingcount, 1);
-               if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) && (
-               acb->srboutstandingcount < ARCMSR_RELEASE_SIMQ_LEVEL)) {
-                       acb->acb_flags &= ~ACB_F_CAM_DEV_QFRZN;
-                       pccb->ccb_h.status |= CAM_RELEASE_SIMQ;
+       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;
        }
-       if(srb->srb_state != ARCMSR_SRB_TIMEOUT)
-               arcmsr_free_srb(srb);
-#ifdef ARCMSR_DEBUG1
-       acb->pktReturnCount++;
-#endif
-       xpt_done(pccb);
-       return;
 }
 /*
 **********************************************************************
@@ -557,7 +579,7 @@ static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag)
 */
 static void arcmsr_report_sense_info(struct CommandControlBlock *srb)
 {
-       union ccb * pccb=srb->pccb;
+       union ccb *pccb = srb->pccb;
 
        pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
        pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
@@ -607,6 +629,17 @@ static void arcmsr_abort_hbc_allcmd(struct AdapterControlBlock *acb)
 *********************************************************************
 *********************************************************************
 */
+static void arcmsr_abort_hbd_allcmd(struct AdapterControlBlock *acb)
+{
+       CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD);
+       if(!arcmsr_hbd_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) {
@@ -622,7 +655,46 @@ static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb)
                        arcmsr_abort_hbc_allcmd(acb);
                }
                break;
+       case ACB_ADAPTER_TYPE_D: {
+                       arcmsr_abort_hbd_allcmd(acb);
+               }
+               break;
+       }
+}
+/*
+**********************************************************************
+**********************************************************************
+*/
+static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag)
+{
+       struct AdapterControlBlock *acb = srb->acb;
+       union ccb *pccb = srb->pccb;
+
+       if(srb->srb_flags & SRB_FLAG_TIMER_START)
+               callout_stop(&srb->ccb_callout);
+       if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
+               bus_dmasync_op_t op;
+
+               if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
+                       op = BUS_DMASYNC_POSTREAD;
+               } else {
+                       op = BUS_DMASYNC_POSTWRITE;
+               }
+               bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op);
+               bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap);
        }
+       if(stand_flag == 1) {
+               atomic_subtract_int(&acb->srboutstandingcount, 1);
+               if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) && (
+               acb->srboutstandingcount < (acb->maxOutstanding -10))) {
+                       acb->acb_flags &= ~ACB_F_CAM_DEV_QFRZN;
+                       pccb->ccb_h.status |= CAM_RELEASE_SIMQ;
+               }
+       }
+       if(srb->srb_state != ARCMSR_SRB_TIMEOUT)
+               arcmsr_free_srb(srb);
+       acb->pktReturnCount++;
+       xpt_done(pccb);
 }
 /*
 **************************************************************************
@@ -632,42 +704,42 @@ static void arcmsr_report_srb_state(struct AdapterControlBlock *acb, struct Comm
 {
        int target, lun;
 
-       target=srb->pccb->ccb_h.target_id;
-       lun=srb->pccb->ccb_h.target_lun;
+       target = srb->pccb->ccb_h.target_id;
+       lun = srb->pccb->ccb_h.target_lun;
        if(error == FALSE) {
-               if(acb->devstate[target][lun]==ARECA_RAID_GONE) {
-                       acb->devstate[target][lun]=ARECA_RAID_GOOD;
+               if(acb->devstate[target][lun] == ARECA_RAID_GONE) {
+                       acb->devstate[target][lun] = ARECA_RAID_GOOD;
                }
                srb->pccb->ccb_h.status |= CAM_REQ_CMP;
                arcmsr_srb_complete(srb, 1);
        } else {
                switch(srb->arcmsr_cdb.DeviceStatus) {
                case ARCMSR_DEV_SELECT_TIMEOUT: {
-                               if(acb->devstate[target][lun]==ARECA_RAID_GOOD) {
+                               if(acb->devstate[target][lun] == ARECA_RAID_GOOD) {
                                        kprintf( "arcmsr%d: Target=%x, Lun=%x, selection timeout, raid volume was lost\n", acb->pci_unit, target, lun);
                                }
-                               acb->devstate[target][lun]=ARECA_RAID_GONE;
+                               acb->devstate[target][lun] = ARECA_RAID_GONE;
                                srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
                                arcmsr_srb_complete(srb, 1);
                        }
                        break;
                case ARCMSR_DEV_ABORTED:
                case ARCMSR_DEV_INIT_FAIL: {
-                               acb->devstate[target][lun]=ARECA_RAID_GONE;
+                               acb->devstate[target][lun] = ARECA_RAID_GONE;
                                srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
                                arcmsr_srb_complete(srb, 1);
                        }
                        break;
                case SCSISTAT_CHECK_CONDITION: {
-                               acb->devstate[target][lun]=ARECA_RAID_GOOD;
+                               acb->devstate[target][lun] = ARECA_RAID_GOOD;
                                arcmsr_report_sense_info(srb);
                                arcmsr_srb_complete(srb, 1);
                        }
                        break;
                default:
-                       kprintf("arcmsr%d: scsi id=%d lun=%d isr got command error done, but got unknown DeviceStatus=0x%x\n"
+                       kprintf("arcmsr%d: scsi id=%d lun=%d isr got command error done,but got unknown DeviceStatus=0x%x \n"
                                        , acb->pci_unit, target, lun ,srb->arcmsr_cdb.DeviceStatus);
-                       acb->devstate[target][lun]=ARECA_RAID_GONE;
+                       acb->devstate[target][lun] = ARECA_RAID_GONE;
                        srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY;
                        /*unknown error or crc error just for retry*/
                        arcmsr_srb_complete(srb, 1);
@@ -686,7 +758,8 @@ static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t fl
        /* check if command done with no error*/
        switch (acb->adapter_type) {
        case ACB_ADAPTER_TYPE_C:
-               srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/
+       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_A:
        case ACB_ADAPTER_TYPE_B:
@@ -694,7 +767,7 @@ static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t fl
                srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
                break;
        }
-       if((srb->acb!=acb) || (srb->srb_state!=ARCMSR_SRB_START)) {
+       if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
                if(srb->srb_state == ARCMSR_SRB_TIMEOUT) {
                        arcmsr_free_srb(srb);
                        kprintf("arcmsr%d: srb='%p' return srb has been timeouted\n", acb->pci_unit, srb);
@@ -711,17 +784,17 @@ static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t fl
 **************************************************************************
 **************************************************************************
 */
-static void    arcmsr_srb_timeout(voidarg)
+static void    arcmsr_srb_timeout(void *arg)
 {
        struct CommandControlBlock *srb = (struct CommandControlBlock *)arg;
        struct AdapterControlBlock *acb;
        int target, lun;
        u_int8_t cmd;
 
-       target=srb->pccb->ccb_h.target_id;
-       lun=srb->pccb->ccb_h.target_lun;
+       target = srb->pccb->ccb_h.target_id;
+       lun = srb->pccb->ccb_h.target_lun;
        acb = srb->acb;
-       ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
+       ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
        if(srb->srb_state == ARCMSR_SRB_START)
        {
                cmd = srb->pccb->csio.cdb_io.cdb_bytes[0];
@@ -731,7 +804,7 @@ static void arcmsr_srb_timeout(void* arg)
                kprintf("arcmsr%d: scsi id %d lun %d cmd=0x%x srb='%p' ccb command time out!\n",
                                 acb->pci_unit, target, lun, cmd, srb);
        }
-       ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
+       ARCMSR_LOCK_RELEASE(&acb->isr_lock);
 #ifdef ARCMSR_DEBUG1
        arcmsr_dump_data(acb);
 #endif
@@ -752,10 +825,10 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
                        u_int32_t outbound_intstatus;
 
                        /*clear and abort all outbound posted Q*/
-                       outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable;
+                       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);
                        }
                }
@@ -766,26 +839,30 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
                        /*clear all outbound posted Q*/
                        CHIP_REG_WRITE32(HBB_DOORBELL, 0, 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;
+                               if((flag_srb = phbbmu->done_qbuffer[i]) != 0) {
+                                       phbbmu->done_qbuffer[i] = 0;
+                       error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
                                        arcmsr_drain_donequeue(acb, flag_srb, error);
                                }
-                               phbbmu->post_qbuffer[i]=0;
+                               phbbmu->post_qbuffer[i] = 0;
                        }/*drain reply FIFO*/
-                       phbbmu->doneq_index=0;
-                       phbbmu->postq_index=0;
+                       phbbmu->doneq_index = 0;
+                       phbbmu->postq_index = 0;
                }
                break;
        case ACB_ADAPTER_TYPE_C: {
 
                        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;
+                               flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low);
+                error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
                                arcmsr_drain_donequeue(acb, flag_srb, error);
                        }
                }
                break;
+       case ACB_ADAPTER_TYPE_D: {
+                       arcmsr_hbd_postqueue_isr(acb);
+               }
+               break;
        }
 }
 /*
@@ -800,32 +877,30 @@ static void arcmsr_iop_reset(struct AdapterControlBlock *acb)
 
        if(acb->srboutstandingcount>0) {
                /* disable all outbound interrupt */
-               intmask_org=arcmsr_disable_allintr(acb);
+               intmask_org = arcmsr_disable_allintr(acb);
                /*clear and abort all outbound posted Q*/
                arcmsr_done4abort_postqueue(acb);
                /* talk to iop 331 outstanding command aborted*/
                arcmsr_abort_allcmd(acb);
-               for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) {
-                       srb=acb->psrb_pool[i];
-                       if(srb->srb_state==ARCMSR_SRB_START) {
-                               srb->srb_state=ARCMSR_SRB_ABORTED;
+               for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) {
+                       srb = acb->psrb_pool[i];
+                       if(srb->srb_state == ARCMSR_SRB_START) {
+                               srb->srb_state = ARCMSR_SRB_ABORTED;
                                srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
                                arcmsr_srb_complete(srb, 1);
-                               kprintf("arcmsr%d: scsi id=%d lun=%d srb='%p' aborted\n"
+                               kprintf("arcmsr%d: scsi id=%d lun=%jx srb='%p' aborted\n"
                                                , acb->pci_unit, srb->pccb->ccb_h.target_id
-                                               , srb->pccb->ccb_h.target_lun, srb);
+                                               , (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
                        }
                }
                /* enable all outbound interrupt */
                arcmsr_enable_allintr(acb, intmask_org);
        }
-       acb->srboutstandingcount=0;
-       acb->workingsrb_doneindex=0;
-       acb->workingsrb_startindex=0;
-#ifdef ARCMSR_DEBUG1
+       acb->srboutstandingcount = 0;
+       acb->workingsrb_doneindex = 0;
+       acb->workingsrb_startindex = 0;
        acb->pktRequestCount = 0;
        acb->pktReturnCount = 0;
-#endif
 }
 /*
 **********************************************************************
@@ -834,67 +909,66 @@ static void arcmsr_iop_reset(struct AdapterControlBlock *acb)
 static void arcmsr_build_srb(struct CommandControlBlock *srb,
                bus_dma_segment_t *dm_segs, u_int32_t nseg)
 {
-       struct ARCMSR_CDB * arcmsr_cdb= &srb->arcmsr_cdb;
-       u_int8_t * psge=(u_int8_t *)&arcmsr_cdb->u;
+       struct ARCMSR_CDB *arcmsr_cdb = &srb->arcmsr_cdb;
+       u_int8_t *psge = (u_int8_t *)&arcmsr_cdb->u;
        u_int32_t address_lo, address_hi;
-       union ccb * pccb=srb->pccb;
-       struct ccb_scsiio * pcsio= &pccb->csio;
-       u_int32_t arccdbsize=0x30;
+       union ccb *pccb = srb->pccb;
+       struct ccb_scsiio *pcsio = &pccb->csio;
+       u_int32_t arccdbsize = 0x30;
 
        memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB));
-       arcmsr_cdb->Bus=0;
-       arcmsr_cdb->TargetID=pccb->ccb_h.target_id;
-       arcmsr_cdb->LUN=pccb->ccb_h.target_lun;
-       arcmsr_cdb->Function=1;
-       arcmsr_cdb->CdbLength=(u_int8_t)pcsio->cdb_len;
-       arcmsr_cdb->Context=0;
+       arcmsr_cdb->Bus = 0;
+       arcmsr_cdb->TargetID = pccb->ccb_h.target_id;
+       arcmsr_cdb->LUN = pccb->ccb_h.target_lun;
+       arcmsr_cdb->Function = 1;
+       arcmsr_cdb->CdbLength = (u_int8_t)pcsio->cdb_len;
        bcopy(pcsio->cdb_io.cdb_bytes, arcmsr_cdb->Cdb, pcsio->cdb_len);
        if(nseg != 0) {
-               struct AdapterControlBlock *acb=srb->acb;
+               struct AdapterControlBlock *acb = srb->acb;
                bus_dmasync_op_t op;
-               u_int32_t length, i, cdb_sgcount=0;
+               u_int32_t length, i, cdb_sgcount = 0;
 
                if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
-                       op=BUS_DMASYNC_PREREAD;
+                       op = BUS_DMASYNC_PREREAD;
                } else {
-                       op=BUS_DMASYNC_PREWRITE;
-                       arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_WRITE;
-                       srb->srb_flags|=SRB_FLAG_WRITE;
+                       op = BUS_DMASYNC_PREWRITE;
+                       arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE;
+                       srb->srb_flags |= SRB_FLAG_WRITE;
                }
                bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op);
-               for(i=0;i<nseg;i++) {
+               for(i=0; i < nseg; i++) {
                        /* Get the physical address of the current data pointer */
-                       length=arcmsr_htole32(dm_segs[i].ds_len);
-                       address_lo=arcmsr_htole32(dma_addr_lo32(dm_segs[i].ds_addr));
-                       address_hi=arcmsr_htole32(dma_addr_hi32(dm_segs[i].ds_addr));
-                       if(address_hi==0) {
-                               struct SG32ENTRY * pdma_sg=(struct SG32ENTRY *)psge;
-                               pdma_sg->address=address_lo;
-                               pdma_sg->length=length;
+                       length = arcmsr_htole32(dm_segs[i].ds_len);
+                       address_lo = arcmsr_htole32(dma_addr_lo32(dm_segs[i].ds_addr));
+                       address_hi = arcmsr_htole32(dma_addr_hi32(dm_segs[i].ds_addr));
+                       if(address_hi == 0) {
+                               struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge;
+                               pdma_sg->address = address_lo;
+                               pdma_sg->length = length;
                                psge += sizeof(struct SG32ENTRY);
                                arccdbsize += sizeof(struct SG32ENTRY);
                        } else {
-                               u_int32_t sg64s_size=0, tmplength=length;
+                               u_int32_t sg64s_size = 0, tmplength = length;
 
                                while(1) {
                                        u_int64_t span4G, length0;
-                                       struct SG64ENTRY * pdma_sg=(struct SG64ENTRY *)psge;
+                                       struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge;
 
-                                       span4G=(u_int64_t)address_lo + tmplength;
-                                       pdma_sg->addresshigh=address_hi;
-                                       pdma_sg->address=address_lo;
+                                       span4G = (u_int64_t)address_lo + tmplength;
+                                       pdma_sg->addresshigh = address_hi;
+                                       pdma_sg->address = address_lo;
                                        if(span4G > 0x100000000) {
                                                /*see if cross 4G boundary*/
-                                               length0=0x100000000-address_lo;
-                                               pdma_sg->length=(u_int32_t)length0|IS_SG64_ADDR;
-                                               address_hi=address_hi+1;
-                                               address_lo=0;
-                                               tmplength=tmplength-(u_int32_t)length0;
+                                               length0 = 0x100000000-address_lo;
+                                               pdma_sg->length = (u_int32_t)length0 | IS_SG64_ADDR;
+                                               address_hi = address_hi+1;
+                                               address_lo = 0;
+                                               tmplength = tmplength - (u_int32_t)length0;
                                                sg64s_size += sizeof(struct SG64ENTRY);
                                                psge += sizeof(struct SG64ENTRY);
                                                cdb_sgcount++;
                                        } else {
-                                               pdma_sg->length=tmplength|IS_SG64_ADDR;
+                                               pdma_sg->length = tmplength | IS_SG64_ADDR;
                                                sg64s_size += sizeof(struct SG64ENTRY);
                                                psge += sizeof(struct SG64ENTRY);
                                                break;
@@ -904,15 +978,16 @@ static void arcmsr_build_srb(struct CommandControlBlock *srb,
                        }
                        cdb_sgcount++;
                }
-               arcmsr_cdb->sgcount=(u_int8_t)cdb_sgcount;
-               arcmsr_cdb->DataLength=pcsio->dxfer_len;
+               arcmsr_cdb->sgcount = (u_int8_t)cdb_sgcount;
+               arcmsr_cdb->DataLength = pcsio->dxfer_len;
                if( arccdbsize > 256) {
-                       arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_SGL_BSIZE;
+                       arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE;
                }
        } else {
                arcmsr_cdb->DataLength = 0;
        }
-       srb->arc_cdb_size=arccdbsize;
+    srb->arc_cdb_size = arccdbsize;
+    arcmsr_cdb->msgPages = (arccdbsize/256) + ((arccdbsize % 256) ? 1 : 0);
 }
 /*
 **************************************************************************
@@ -920,46 +995,45 @@ static void arcmsr_build_srb(struct CommandControlBlock *srb,
 */
 static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandControlBlock *srb)
 {
-       u_int32_t cdb_shifted_phyaddr=(u_int32_t) srb->cdb_shifted_phyaddr;
-       struct ARCMSR_CDB * arcmsr_cdb=(struct ARCMSR_CDB *)&srb->arcmsr_cdb;
+       u_int32_t cdb_phyaddr_low = (u_int32_t) srb->cdb_phyaddr_low;
+       struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&srb->arcmsr_cdb;
 
        bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, (srb->srb_flags & SRB_FLAG_WRITE) ? BUS_DMASYNC_POSTWRITE:BUS_DMASYNC_POSTREAD);
        atomic_add_int(&acb->srboutstandingcount, 1);
-       srb->srb_state=ARCMSR_SRB_START;
+       srb->srb_state = ARCMSR_SRB_START;
 
        switch (acb->adapter_type) {
        case ACB_ADAPTER_TYPE_A: {
                        if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) {
-                               CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE);
+                               CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_phyaddr_low|ARCMSR_SRBPOST_FLAG_SGL_BSIZE);
                        } else {
-                               CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_shifted_phyaddr);
+                               CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_phyaddr_low);
                        }
                }
                break;
        case ACB_ADAPTER_TYPE_B: {
-                       struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu;
+                       struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
                        int ending_index, index;
 
-                       index=phbbmu->postq_index;
-                       ending_index=((index+1)%ARCMSR_MAX_HBB_POSTQUEUE);
-                       phbbmu->post_qbuffer[ending_index]=0;
+                       index = phbbmu->postq_index;
+                       ending_index = ((index+1) % ARCMSR_MAX_HBB_POSTQUEUE);
+                       phbbmu->post_qbuffer[ending_index] = 0;
                        if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) {
-                               phbbmu->post_qbuffer[index]= cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE;
+                               phbbmu->post_qbuffer[index] = cdb_phyaddr_low | ARCMSR_SRBPOST_FLAG_SGL_BSIZE;
                        } else {
-                               phbbmu->post_qbuffer[index]= cdb_shifted_phyaddr;
+                               phbbmu->post_qbuffer[index] = cdb_phyaddr_low;
                        }
                        index++;
                        index %= ARCMSR_MAX_HBB_POSTQUEUE;     /*if last index number set it to 0 */
-                       phbbmu->postq_index=index;
+                       phbbmu->postq_index = index;
                        CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED);
                }
                break;
-    case ACB_ADAPTER_TYPE_C:
-        {
+    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_shifted_phyaddr | ((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)
             {
@@ -972,33 +1046,67 @@ static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandContr
             }
         }
         break;
+       case ACB_ADAPTER_TYPE_D: {
+                       struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
+                       u_int16_t index_stripped;
+                       u_int16_t postq_index;
+                       struct InBound_SRB *pinbound_srb;
+
+                       ARCMSR_LOCK_ACQUIRE(&acb->postDone_lock);
+                       postq_index = phbdmu->postq_index;
+                       pinbound_srb = (struct InBound_SRB *)&phbdmu->post_qbuffer[postq_index & 0xFF];
+                       pinbound_srb->addressHigh = srb->cdb_phyaddr_high;
+                       pinbound_srb->addressLow = srb->cdb_phyaddr_low;
+                       pinbound_srb->length = srb->arc_cdb_size >> 2;
+                       arcmsr_cdb->Context = srb->cdb_phyaddr_low;
+                       if (postq_index & 0x4000) {
+                               index_stripped = postq_index & 0xFF;
+                               index_stripped += 1;
+                               index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
+                               phbdmu->postq_index = index_stripped ? (index_stripped | 0x4000) : index_stripped;
+                       } else {
+                               index_stripped = postq_index;
+                               index_stripped += 1;
+                               index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
+                               phbdmu->postq_index = index_stripped ? index_stripped : (index_stripped | 0x4000);
+                       }
+                       CHIP_REG_WRITE32(HBD_MessageUnit, 0, inboundlist_write_pointer, postq_index);
+                       ARCMSR_LOCK_RELEASE(&acb->postDone_lock);
+               }
+               break;
        }
 }
 /*
 ************************************************************************
 ************************************************************************
 */
-static struct QBUFFER * arcmsr_get_iop_rqbuffer( struct AdapterControlBlock *acb)
+static struct QBUFFER *arcmsr_get_iop_rqbuffer( struct AdapterControlBlock *acb)
 {
        struct QBUFFER *qbuffer=NULL;
 
        switch (acb->adapter_type) {
        case ACB_ADAPTER_TYPE_A: {
-                       struct HBA_MessageUnit *phbamu=(struct HBA_MessageUnit *)acb->pmu;
+                       struct HBA_MessageUnit *phbamu = (struct HBA_MessageUnit *)acb->pmu;
 
-                       qbuffer=(struct QBUFFER *)&phbamu->message_rbuffer;
+                       qbuffer = (struct QBUFFER *)&phbamu->message_rbuffer;
                }
                break;
        case ACB_ADAPTER_TYPE_B: {
-                       struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu;
+                       struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
 
-                       qbuffer=(struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_rbuffer;
+                       qbuffer = (struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_rbuffer;
                }
                break;
        case ACB_ADAPTER_TYPE_C: {
-                       struct HBC_MessageUnit *phbcmu=(struct HBC_MessageUnit *)acb->pmu;
+                       struct HBC_MessageUnit *phbcmu = (struct HBC_MessageUnit *)acb->pmu;
 
-                       qbuffer=(struct QBUFFER *)&phbcmu->message_rbuffer;
+                       qbuffer = (struct QBUFFER *)&phbcmu->message_rbuffer;
+               }
+               break;
+       case ACB_ADAPTER_TYPE_D: {
+                       struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
+       
+                       qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_rbuffer;
                }
                break;
        }
@@ -1008,27 +1116,33 @@ static struct QBUFFER * arcmsr_get_iop_rqbuffer( struct AdapterControlBlock *acb
 ************************************************************************
 ************************************************************************
 */
-static struct QBUFFER * arcmsr_get_iop_wqbuffer( struct AdapterControlBlock *acb)
+static struct QBUFFER *arcmsr_get_iop_wqbuffer( struct AdapterControlBlock *acb)
 {
-       struct QBUFFER *qbuffer=NULL;
+       struct QBUFFER *qbuffer = NULL;
 
        switch (acb->adapter_type) {
        case ACB_ADAPTER_TYPE_A: {
-                       struct HBA_MessageUnit *phbamu=(struct HBA_MessageUnit *)acb->pmu;
+                       struct HBA_MessageUnit *phbamu = (struct HBA_MessageUnit *)acb->pmu;
 
-                       qbuffer=(struct QBUFFER *)&phbamu->message_wbuffer;
+                       qbuffer = (struct QBUFFER *)&phbamu->message_wbuffer;
                }
                break;
        case ACB_ADAPTER_TYPE_B: {
-                       struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu;
+                       struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
 
-                       qbuffer=(struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_wbuffer;
+                       qbuffer = (struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_wbuffer;
                }
                break;
        case ACB_ADAPTER_TYPE_C: {
-                       struct HBC_MessageUnit *phbcmu=(struct HBC_MessageUnit *)acb->pmu;
+                       struct HBC_MessageUnit *phbcmu = (struct HBC_MessageUnit *)acb->pmu;
 
-                       qbuffer=(struct QBUFFER *)&phbcmu->message_wbuffer;
+                       qbuffer = (struct QBUFFER *)&phbcmu->message_wbuffer;
+               }
+               break;
+       case ACB_ADAPTER_TYPE_D: {
+                       struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
+       
+                       qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_wbuffer;
                }
                break;
        }
@@ -1055,6 +1169,12 @@ static void arcmsr_iop_message_read(struct AdapterControlBlock *acb)
                        /* let IOP know data has been read */
                        CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK);
                }
+               break;
+       case ACB_ADAPTER_TYPE_D: {
+                       /* let IOP know data has been read */
+                       CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ);
+               }
+               break;
        }
 }
 /*
@@ -1088,37 +1208,14 @@ static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb)
                        CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK);
                }
                break;
-       }
-}
-/*
-**********************************************************************
-**********************************************************************
-*/
-static void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb)
-{
-       u_int8_t *pQbuffer;
-       struct QBUFFER *pwbuffer;
-       u_int8_t * iop_data;
-       int32_t allxfer_len=0;
-
-       pwbuffer=arcmsr_get_iop_wqbuffer(acb);
-       iop_data=(u_int8_t *)pwbuffer->data;
-       if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) {
-               acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ);
-               while((acb->wqbuf_firstindex!=acb->wqbuf_lastindex)
-                       && (allxfer_len<124)) {
-                       pQbuffer=&acb->wqbuffer[acb->wqbuf_firstindex];
-                       memcpy(iop_data, pQbuffer, 1);
-                       acb->wqbuf_firstindex++;
-                       acb->wqbuf_firstindex %=ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */
-                       iop_data++;
-                       allxfer_len++;
+       case ACB_ADAPTER_TYPE_D: {
+                       /*
+                       ** 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);
                }
-               pwbuffer->data_len=allxfer_len;
-               /*
-               ** push inbound doorbell and wait reply at hwinterrupt routine for next Qbuffer post
-               */
-               arcmsr_iop_message_wrote(acb);
+               break;
        }
 }
 /*
@@ -1127,14 +1224,13 @@ static void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb)
 */
 static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb)
 {
-       acb->acb_flags &=~ACB_F_MSG_START_BGRB;
+       acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
        CHIP_REG_WRITE32(HBA_MessageUnit,
        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"
                        , acb->pci_unit);
        }
-       return;
 }
 /*
 ************************************************************************
@@ -1156,7 +1252,7 @@ static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb)
 */
 static void arcmsr_stop_hbc_bgrb(struct AdapterControlBlock *acb)
 {
-       acb->acb_flags &=~ACB_F_MSG_START_BGRB;
+       acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
        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)) {
@@ -1167,6 +1263,18 @@ static void arcmsr_stop_hbc_bgrb(struct AdapterControlBlock *acb)
 ************************************************************************
 ************************************************************************
 */
+static void arcmsr_stop_hbd_bgrb(struct AdapterControlBlock *acb)
+{
+       acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
+       CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
+       if(!arcmsr_hbd_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) {
@@ -1182,24 +1290,102 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
                        arcmsr_stop_hbc_bgrb(acb);
                }
                break;
+       case ACB_ADAPTER_TYPE_D: {
+                       arcmsr_stop_hbd_bgrb(acb);
+               }
+               break;
        }
 }
 /*
 ************************************************************************
 ************************************************************************
 */
-static void arcmsr_poll(struct cam_sim * psim)
+static void arcmsr_poll(struct cam_sim *psim)
 {
        struct AdapterControlBlock *acb;
        int     mutex;
 
        acb = (struct AdapterControlBlock *)cam_sim_softc(psim);
-       mutex = lockstatus(&acb->qbuffer_lock, curthread);
+       mutex = lockstatus(&acb->isr_lock, curthread);
        if( mutex == 0 )
-               ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
+               ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
        arcmsr_interrupt(acb);
        if( mutex == 0 )
-               ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
+               ARCMSR_LOCK_RELEASE(&acb->isr_lock);
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
+static u_int32_t arcmsr_Read_iop_rqbuffer_data_D(struct AdapterControlBlock *acb,
+    struct QBUFFER *prbuffer) {
+
+       u_int8_t *pQbuffer;
+       u_int8_t *buf1 = 0;
+       u_int32_t *iop_data, *buf2 = 0;
+       u_int32_t iop_len, data_len;
+
+       iop_data = (u_int32_t *)prbuffer->data;
+       iop_len = (u_int32_t)prbuffer->data_len;
+       if ( iop_len > 0 )
+       {
+               buf1 = kmalloc(128, M_DEVBUF, M_NOWAIT | M_ZERO);
+               buf2 = (u_int32_t *)buf1;
+               if( buf1 == NULL)
+                       return (0);
+               data_len = iop_len;
+               while(data_len >= 4)
+               {
+                       *buf2++ = *iop_data++;
+                       data_len -= 4;
+               }
+               if(data_len)
+                       *buf2 = *iop_data;
+               buf2 = (u_int32_t *)buf1;
+       }
+       while (iop_len > 0) {
+               pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex];
+               *pQbuffer = *buf1;
+               acb->rqbuf_lastindex++;
+               /* if last, index number set it to 0 */
+               acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
+               buf1++;
+               iop_len--;
+       }
+       if(buf2)
+               kfree( (u_int8_t *)buf2, M_DEVBUF);
+       /* let IOP know data has been read */
+       arcmsr_iop_message_read(acb);
+       return (1);
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
+static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb,
+    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)) {
+               return(arcmsr_Read_iop_rqbuffer_data_D(acb, prbuffer));
+       }
+       iop_data = (u_int8_t *)prbuffer->data;
+       iop_len = (u_int32_t)prbuffer->data_len;
+       while (iop_len > 0) {
+               pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex];
+               *pQbuffer = *iop_data;
+               acb->rqbuf_lastindex++;
+               /* if last, index number set it to 0 */
+               acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
+               iop_data++;
+               iop_len--;
+       }
+       /* let IOP know data has been read */
+       arcmsr_iop_message_read(acb);
+       return (1);
 }
 /*
 **************************************************************************
@@ -1208,31 +1394,95 @@ static void arcmsr_poll(struct cam_sim * psim)
 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);
+       if(my_empty_len >= prbuffer->data_len) {
+               if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
+                       acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
+       } else {
+               acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
+       }
+       ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
+}
+/*
+**********************************************************************
+**********************************************************************
+*/
+static void arcmsr_Write_data_2iop_wqbuffer_D(struct AdapterControlBlock *acb)
+{
        u_int8_t *pQbuffer;
+       struct QBUFFER *pwbuffer;
+       u_int8_t *buf1 = 0;
+       u_int32_t *iop_data, *buf2 = 0;
+       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;
+               if( buf1 == NULL)
+                       return;
+
+               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) 
+                       && (allxfer_len < 124)) {
+                       pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex];
+                       *buf1 = *pQbuffer;
+                       acb->wqbuf_firstindex++;
+                       acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
+                       buf1++;
+                       allxfer_len++;
+               }
+               pwbuffer->data_len = allxfer_len;
+               data_len = allxfer_len;
+               buf1 = (u_int8_t *)buf2;
+               while(data_len >= 4)
+               {
+                       *iop_data++ = *buf2++;
+                       data_len -= 4;
+               }
+               if(data_len)
+                       *iop_data = *buf2;
+               kfree( buf1, M_DEVBUF);
+               arcmsr_iop_message_wrote(acb);
+       }
+}
+/*
+**********************************************************************
+**********************************************************************
+*/
+static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb)
+{
+       u_int8_t *pQbuffer;
+       struct QBUFFER *pwbuffer;
        u_int8_t *iop_data;
-       int my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex;
+       int32_t allxfer_len=0;
 
-       /*check this iop data if overflow my rqbuffer*/
-       rqbuf_lastindex=acb->rqbuf_lastindex;
-       rqbuf_firstindex=acb->rqbuf_firstindex;
-       prbuffer=arcmsr_get_iop_rqbuffer(acb);
-       iop_data=(u_int8_t *)prbuffer->data;
-       iop_len=prbuffer->data_len;
-       my_empty_len=(rqbuf_firstindex-rqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1);
-       if(my_empty_len>=iop_len) {
-               while(iop_len > 0) {
-                       pQbuffer=&acb->rqbuffer[rqbuf_lastindex];
-                       memcpy(pQbuffer, iop_data, 1);
-                       rqbuf_lastindex++;
-                       rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;/*if last index number set it to 0 */
+       if(acb->adapter_type & (ACB_ADAPTER_TYPE_C | ACB_ADAPTER_TYPE_D)) {
+               arcmsr_Write_data_2iop_wqbuffer_D(acb);
+               return;
+       }
+       if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) {
+               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) 
+                       && (allxfer_len < 124)) {
+                       pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex];
+                       *iop_data = *pQbuffer;
+                       acb->wqbuf_firstindex++;
+                       acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
                        iop_data++;
-                       iop_len--;
+                       allxfer_len++;
                }
-               acb->rqbuf_lastindex=rqbuf_lastindex;
-               arcmsr_iop_message_read(acb);
-               /*signature, let IOP know data has been read */
-       } else {
-               acb->acb_flags|=ACB_F_IOPDATA_OVERFLOW;
+               pwbuffer->data_len = allxfer_len;
+               arcmsr_iop_message_wrote(acb);
        }
 }
 /*
@@ -1241,6 +1491,7 @@ static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb)
 */
 static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb)
 {
+       ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
        acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READ;
        /*
        *****************************************************************
@@ -1248,61 +1499,51 @@ static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb)
        **   in my post bag, now is the time to send them into Areca's firmware
        *****************************************************************
        */
-       if(acb->wqbuf_firstindex!=acb->wqbuf_lastindex) {
-               u_int8_t *pQbuffer;
-               struct QBUFFER *pwbuffer;
-               u_int8_t *iop_data;
-               int allxfer_len=0;
-
-               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)
-                       && (allxfer_len<124)) {
-                       pQbuffer=&acb->wqbuffer[acb->wqbuf_firstindex];
-                       memcpy(iop_data, pQbuffer, 1);
-                       acb->wqbuf_firstindex++;
-                       acb->wqbuf_firstindex %=ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */
-                       iop_data++;
-                       allxfer_len++;
-               }
-               pwbuffer->data_len=allxfer_len;
-               /*
-               ** push inbound doorbell tell iop driver data write ok
-               ** and wait reply on next hwinterrupt for next Qbuffer post
-               */
-               arcmsr_iop_message_wrote(acb);
+       if(acb->wqbuf_firstindex != acb->wqbuf_lastindex) {
+               arcmsr_Write_data_2iop_wqbuffer(acb);
        }
-       if(acb->wqbuf_firstindex==acb->wqbuf_lastindex) {
+       if(acb->wqbuf_firstindex == acb->wqbuf_lastindex) {
                acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED;
        }
+       ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
 }
-
+/*
+**************************************************************************
+**************************************************************************
+*/
 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);
+               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);
        else
                kprintf("arcmsr_rescanLun_cb: Rescan lun successfully!\n");
 */
        xpt_free_path(ccb->ccb_h.path);
+       xpt_free_ccb(ccb);
 }
 
 static void    arcmsr_rescan_lun(struct AdapterControlBlock *acb, int target, int lun)
 {
        struct cam_path     *path;
-       union ccb            ccb;
+       union ccb           *ccb;
 
-       if (xpt_create_path(&path, xpt_periph, cam_sim_path(acb->psim), target, lun) != CAM_REQ_CMP)
+       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)
+       {
+               xpt_free_ccb(ccb);
                return;
+       }
 /*     kprintf("arcmsr_rescan_lun: Rescan Target=%x, Lun=%x\n", target, lun); */
-       bzero(&ccb, sizeof(union ccb));
-       xpt_setup_ccb(&ccb.ccb_h, path, 5);
-       ccb.ccb_h.func_code = XPT_SCAN_LUN;
-       ccb.ccb_h.cbfcnp = arcmsr_rescanLun_cb;
-       ccb.crcn.flags = CAM_FLAG_NONE;
-       xpt_action(&ccb);
+       bzero(ccb, sizeof(union ccb));
+       xpt_setup_ccb(&ccb->ccb_h, path, 5);
+       ccb->ccb_h.func_code = XPT_SCAN_LUN;
+       ccb->ccb_h.cbfcnp = arcmsr_rescanLun_cb;
+       ccb->crcn.flags = CAM_FLAG_NONE;
+       xpt_action(ccb);
 }
 
 
@@ -1312,7 +1553,6 @@ static void arcmsr_abort_dr_ccbs(struct AdapterControlBlock *acb, int target, in
        u_int32_t intmask_org;
        int i;
 
-       ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
        /* disable all outbound interrupts */
        intmask_org = arcmsr_disable_allintr(acb);
        for (i = 0; i < ARCMSR_MAX_FREESRB_NUM; i++)
@@ -1331,10 +1571,7 @@ static void arcmsr_abort_dr_ccbs(struct AdapterControlBlock *acb, int target, in
        }
        /* enable outbound Post Queue, outbound doorbell Interrupt */
        arcmsr_enable_allintr(acb, intmask_org);
-       ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
 }
-
-
 /*
 **************************************************************************
 **************************************************************************
@@ -1348,7 +1585,7 @@ static void arcmsr_dr_handle(struct AdapterControlBlock *acb) {
        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++)
+                       for (target = 0; target < 4; target++) 
                        {
                deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0],  devicemap);
                devicemap += 4;
@@ -1357,7 +1594,7 @@ static void arcmsr_dr_handle(struct AdapterControlBlock *acb) {
 
        case ACB_ADAPTER_TYPE_B:
                        devicemap = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
-                       for (target= 0; target < 4; target++)
+                       for (target = 0; target < 4; target++) 
                        {
                deviceMapCurrent[target]=bus_space_read_4(acb->btag[1], acb->bhandle[1],  devicemap);
                devicemap += 4;
@@ -1366,12 +1603,20 @@ static void arcmsr_dr_handle(struct AdapterControlBlock *acb) {
 
        case ACB_ADAPTER_TYPE_C:
                        devicemap = offsetof(struct HBC_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
-                       for (target= 0; target < 4; target++)
+                       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)
@@ -1383,16 +1628,16 @@ static void arcmsr_dr_handle(struct AdapterControlBlock *acb) {
                ** 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++)
+               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];
+                difference = *pDevMap ^ acb->device_map[target];
                 for(lun=0; lun < ARCMSR_MAX_TARGETLUN; lun++)
                 {
-                    bit_check=(1 << lun);                                              /*check bit from 0....31*/
+                    bit_check = (1 << lun);                                            /*check bit from 0....31*/
                     if(difference & bit_check)
                     {
                         if(acb->device_map[target] & bit_check)
@@ -1411,7 +1656,7 @@ static void arcmsr_dr_handle(struct AdapterControlBlock *acb) {
                     }
                 }
 /*                             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;
+                               acb->device_map[target] = *pDevMap;
                        }
                        pDevMap++;
                }
@@ -1457,9 +1702,21 @@ static void arcmsr_hbc_message_isr(struct AdapterControlBlock *acb) {
 **************************************************************************
 **************************************************************************
 */
+static void arcmsr_hbd_message_isr(struct AdapterControlBlock *acb) {
+       u_int32_t outbound_message;
+
+       CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR);
+       outbound_message = CHIP_REG_READ32(HBD_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 outbound_doorbell;
+       u_int32_t doorbell_status;
 
        /*
        *******************************************************************
@@ -1468,14 +1725,12 @@ static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb)
        **  check if there are any mail need to pack from firmware
        *******************************************************************
        */
-       outbound_doorbell=CHIP_REG_READ32(HBA_MessageUnit,
-       0, outbound_doorbell);
-       CHIP_REG_WRITE32(HBA_MessageUnit,
-       0, outbound_doorbell, outbound_doorbell); /* clear doorbell interrupt */
-       if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) {
+       doorbell_status = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell);
+       CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */
+       if(doorbell_status & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) {
                arcmsr_iop2drv_data_wrote_handle(acb);
        }
-       if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) {
+       if(doorbell_status & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) {
                arcmsr_iop2drv_data_read_handle(acb);
        }
 }
@@ -1485,7 +1740,7 @@ static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb)
 */
 static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb)
 {
-       u_int32_t outbound_doorbell;
+       u_int32_t doorbell_status;
 
        /*
        *******************************************************************
@@ -1494,15 +1749,15 @@ static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb)
        **  check if there are any mail need to pack from firmware
        *******************************************************************
        */
-       outbound_doorbell=CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell);
-       CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell); /* clear doorbell interrupt */
-       if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) {
+       doorbell_status = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell);
+       CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, doorbell_status); /* clear doorbell interrupt */
+       if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) {
                arcmsr_iop2drv_data_wrote_handle(acb);
        }
-       if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) {
+       if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) {
                arcmsr_iop2drv_data_read_handle(acb);
        }
-       if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) {
+       if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) {
                arcmsr_hbc_message_isr(acb);    /* messenger of "driver to iop commands" */
        }
 }
@@ -1510,6 +1765,39 @@ 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! 
+       **  check if there are any mail need to pack from firmware
+       *******************************************************************
+       */
+       doorbell_status = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE;
+       if(doorbell_status)
+               CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */
+       while( doorbell_status & ARCMSR_HBDMU_F0_DOORBELL_CAUSE ) {
+               if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_DATA_WRITE_OK) {
+                       arcmsr_iop2drv_data_wrote_handle(acb);
+               }
+               if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_DATA_READ_OK) {
+                       arcmsr_iop2drv_data_read_handle(acb);
+               }
+               if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) {
+                       arcmsr_hbd_message_isr(acb);    /* messenger of "driver to iop commands" */
+               }
+               doorbell_status = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE;
+               if(doorbell_status)
+                       CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */
+       }
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
 static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb)
 {
        u_int32_t flag_srb;
@@ -1522,10 +1810,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*/
 }
@@ -1535,7 +1823,7 @@ static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb)
 */
 static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb)
 {
-       struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu;
+       struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
        u_int32_t flag_srb;
        int index;
        u_int16_t error;
@@ -1547,14 +1835,14 @@ static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb)
        */
        bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap,
                BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
-       index=phbbmu->doneq_index;
-       while((flag_srb=phbbmu->done_qbuffer[index]) != 0) {
-               phbbmu->done_qbuffer[index]=0;
+       index = phbbmu->doneq_index;
+       while((flag_srb = phbbmu->done_qbuffer[index]) != 0) {
+               phbbmu->done_qbuffer[index] = 0;
                index++;
                index %= ARCMSR_MAX_HBB_POSTQUEUE;     /*if last index number set it to 0 */
-               phbbmu->doneq_index=index;
+               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*/
 }
@@ -1564,7 +1852,7 @@ static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb)
 */
 static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb)
 {
-       u_int32_t flag_srb,throttling=0;
+       u_int32_t flag_srb,throttling = 0;
        u_int16_t error;
 
        /*
@@ -1573,19 +1861,76 @@ static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb)
        *****************************************************************************
        */
        bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
-
-       while(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) {
-
-               flag_srb=CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low);
+       do {
+               flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low);
                /* 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);
-        if(throttling==ARCMSR_HBC_ISR_THROTTLING_LEVEL) {
-            CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING);
-            break;
-        }
-        throttling++;
-       }       /*drain reply FIFO*/
+               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)
+{
+       uint16_t doneq_index, index_stripped;
+
+       doneq_index = phbdmu->doneq_index;
+       if (doneq_index & 0x4000) {
+               index_stripped = doneq_index & 0xFF;
+               index_stripped += 1;
+               index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
+               phbdmu->doneq_index = index_stripped ?
+                   (index_stripped | 0x4000) : index_stripped;
+       } else {
+               index_stripped = doneq_index;
+               index_stripped += 1;
+               index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
+               phbdmu->doneq_index = index_stripped ?
+                   index_stripped : (index_stripped | 0x4000);
+       }
+       return (phbdmu->doneq_index);
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
+static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb)
+{
+       struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
+       u_int32_t outbound_write_pointer;
+       u_int32_t addressLow;
+       uint16_t doneq_index;
+       u_int16_t error;
+       /*
+       *****************************************************************************
+       **               areca cdb command done
+       *****************************************************************************
+       */
+       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, 
+               BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+       outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow;
+       doneq_index = phbdmu->doneq_index;
+       while ((doneq_index & 0xFF) != (outbound_write_pointer & 0xFF)) {
+               doneq_index = arcmsr_get_doneq_index(phbdmu);
+               addressLow = phbdmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow;
+               error = (addressLow & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
+               arcmsr_drain_donequeue(acb, addressLow, error); /*Check if command done with no error */
+               CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_read_pointer, doneq_index);
+               outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow;
+       }
+       CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_interrupt_cause, ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT_CLEAR);
+       CHIP_REG_READ32(HBD_MessageUnit, 0, outboundlist_interrupt_cause); /*Dummy ioread32 to force pci flush */
 }
 /*
 **********************************************************************
@@ -1599,12 +1944,12 @@ static void arcmsr_handle_hba_isr( struct AdapterControlBlock *acb)
        **   check outbound intstatus
        *********************************************
        */
-       outbound_intStatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable;
+       outbound_intStatus = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable;
        if(!outbound_intStatus) {
                /*it must be share irq*/
                return;
        }
-       CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intStatus);/*clear interrupt*/
+       CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intStatus); /*clear interrupt*/
        /* MU doorbell interrupts*/
        if(outbound_intStatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) {
                arcmsr_hba_doorbell_isr(acb);
@@ -1629,7 +1974,7 @@ static void arcmsr_handle_hbb_isr( struct AdapterControlBlock *acb)
        **   check outbound intstatus
        *********************************************
        */
-       outbound_doorbell=CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & acb->outbound_int_enable;
+       outbound_doorbell = CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & acb->outbound_int_enable;
        if(!outbound_doorbell) {
                /*it must be share irq*/
                return;
@@ -1664,19 +2009,57 @@ static void arcmsr_handle_hbc_isr( struct AdapterControlBlock *acb)
        **   check outbound intstatus
        *********************************************
        */
-       host_interrupt_status=CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status);
+       host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) &
+               (ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR |
+               ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR);
        if(!host_interrupt_status) {
                /*it must be share irq*/
                return;
        }
+       do {
+               /* MU doorbell interrupts*/
+               if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) {
+                       arcmsr_hbc_doorbell_isr(acb);
+               }
+               /* MU post queue interrupts*/
+               if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) {
+                       arcmsr_hbc_postqueue_isr(acb);
+               }
+               host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status);
+       } while (host_interrupt_status & (ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR));
+}
+/*
+**********************************************************************
+**********************************************************************
+*/
+static void arcmsr_handle_hbd_isr( struct AdapterControlBlock *acb)
+{
+       u_int32_t host_interrupt_status;
+       u_int32_t intmask_org;
+       /*
+       *********************************************
+       **   check outbound intstatus 
+       *********************************************
+       */
+       host_interrupt_status = CHIP_REG_READ32(HBD_MessageUnit, 0, host_int_status) & acb->outbound_int_enable;
+       if(!(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_INT)) {
+               /*it must be share irq*/
+               return;
+       }
+       /* disable outbound interrupt */
+       intmask_org = CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable)    ; /* disable outbound message0 int */
+       CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, ARCMSR_HBDMU_ALL_INT_DISABLE);
        /* MU doorbell interrupts*/
-       if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) {
-               arcmsr_hbc_doorbell_isr(acb);
+       if(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_DOORBELL_INT) {
+               arcmsr_hbd_doorbell_isr(acb);
        }
        /* MU post queue interrupts*/
-       if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) {
-               arcmsr_hbc_postqueue_isr(acb);
+       if(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_POSTQUEUE_INT) {
+               arcmsr_hbd_postqueue_isr(acb);
        }
+       /* enable all outbound interrupt */
+       CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, intmask_org | ARCMSR_HBDMU_ALL_INT_ENABLE);
+//     CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable);
 }
 /*
 ******************************************************************************
@@ -1694,6 +2077,9 @@ static void arcmsr_interrupt(struct AdapterControlBlock *acb)
        case ACB_ADAPTER_TYPE_C:
                arcmsr_handle_hbc_isr(acb);
                break;
+       case ACB_ADAPTER_TYPE_D:
+               arcmsr_handle_hbd_isr(acb);
+               break;
        default:
                kprintf("arcmsr%d: interrupt service,"
                " unknown adapter type =%d\n", acb->pci_unit, acb->adapter_type);
@@ -1706,17 +2092,17 @@ static void arcmsr_interrupt(struct AdapterControlBlock *acb)
 */
 static void arcmsr_intr_handler(void *arg)
 {
-       struct AdapterControlBlock *acb=(struct AdapterControlBlock *)arg;
+       struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg;
 
-       ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
+       ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
        arcmsr_interrupt(acb);
-       ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
+       ARCMSR_LOCK_RELEASE(&acb->isr_lock);
 }
 /*
 ******************************************************************************
 ******************************************************************************
 */
-static void    arcmsr_polling_devmap(voidarg)
+static void    arcmsr_polling_devmap(void *arg)
 {
        struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg;
        switch (acb->adapter_type) {
@@ -1732,6 +2118,10 @@ static void      arcmsr_polling_devmap(void* arg)
                        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;
        }
 
        if((acb->acb_flags & ACB_F_SCSISTOPADAPTER) == 0)
@@ -1749,7 +2139,7 @@ static void arcmsr_iop_parking(struct AdapterControlBlock *acb)
 {
        u_int32_t intmask_org;
 
-       if(acb!=NULL) {
+       if(acb != NULL) {
                /* stop adapter background rebuild */
                if(acb->acb_flags & ACB_F_MSG_START_BGRB) {
                        intmask_org = arcmsr_disable_allintr(acb);
@@ -1766,25 +2156,25 @@ static void arcmsr_iop_parking(struct AdapterControlBlock *acb)
 */
 u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg)
 {
-       struct CMD_MESSAGE_FIELD * pcmdmessagefld;
-       u_int32_t retvalue=EINVAL;
+       struct CMD_MESSAGE_FIELD *pcmdmessagefld;
+       u_int32_t retvalue = EINVAL;
 
-       pcmdmessagefld=(struct CMD_MESSAGE_FIELD *) arg;
+       pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) arg;
        if(memcmp(pcmdmessagefld->cmdmessage.Signature, "ARCMSR", 6)!=0) {
                return retvalue;
        }
        ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
        switch(ioctl_cmd) {
        case ARCMSR_MESSAGE_READ_RQBUFFER: {
-                       u_int8_t * pQbuffer;
-                       u_int8_t * ptmpQbuffer=pcmdmessagefld->messagedatabuffer;
+                       u_int8_t *pQbuffer;
+                       u_int8_t *ptmpQbuffer = pcmdmessagefld->messagedatabuffer;                      
                        u_int32_t allxfer_len=0;
 
-                       while((acb->rqbuf_firstindex!=acb->rqbuf_lastindex)
-                               && (allxfer_len<1031)) {
+                       while((acb->rqbuf_firstindex != acb->rqbuf_lastindex) 
+                               && (allxfer_len < 1031)) {
                                /*copy READ QBUFFER to srb*/
-                               pQbuffer= &acb->rqbuffer[acb->rqbuf_firstindex];
-                               memcpy(ptmpQbuffer, pQbuffer, 1);
+                               pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex];
+                               *ptmpQbuffer = *pQbuffer;
                                acb->rqbuf_firstindex++;
                                acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
                                /*if last index number set it to 0 */
@@ -1792,51 +2182,38 @@ u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_c
                                allxfer_len++;
                        }
                        if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
-                               struct QBUFFER * prbuffer;
-                               u_int8_t * iop_data;
-                               u_int32_t iop_len;
+                               struct QBUFFER *prbuffer;
 
                                acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
-                               prbuffer=arcmsr_get_iop_rqbuffer(acb);
-                               iop_data=(u_int8_t *)prbuffer->data;
-                               iop_len=(u_int32_t)prbuffer->data_len;
-                               /*this iop data does no chance to make me overflow again here, so just do it*/
-                               while(iop_len>0) {
-                                       pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex];
-                                       memcpy(pQbuffer, iop_data, 1);
-                                       acb->rqbuf_lastindex++;
-                                       acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
-                                       /*if last index number set it to 0 */
-                                       iop_data++;
-                                       iop_len--;
-                               }
-                               arcmsr_iop_message_read(acb);
-                               /*signature, let IOP know data has been readed */
+                               prbuffer = arcmsr_get_iop_rqbuffer(acb);
+                               if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
+                                       acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
                        }
-                       pcmdmessagefld->cmdmessage.Length=allxfer_len;
-                       pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK;
-                       retvalue=ARCMSR_MESSAGE_SUCCESS;
+                       pcmdmessagefld->cmdmessage.Length = allxfer_len;
+                       pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
+                       retvalue = ARCMSR_MESSAGE_SUCCESS;
                }
                break;
        case ARCMSR_MESSAGE_WRITE_WQBUFFER: {
                        u_int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
-                       u_int8_t * pQbuffer;
-                       u_int8_t * ptmpuserbuffer=pcmdmessagefld->messagedatabuffer;
+                       u_int8_t *pQbuffer;
+                       u_int8_t *ptmpuserbuffer = pcmdmessagefld->messagedatabuffer;
 
-                       user_len=pcmdmessagefld->cmdmessage.Length;
+                       user_len = pcmdmessagefld->cmdmessage.Length;
                        /*check if data xfer length of this request will overflow my array qbuffer */
-                       wqbuf_lastindex=acb->wqbuf_lastindex;
-                       wqbuf_firstindex=acb->wqbuf_firstindex;
-                       if(wqbuf_lastindex!=wqbuf_firstindex) {
-                               arcmsr_post_ioctldata2iop(acb);
-                               pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR;
+                       wqbuf_lastindex = acb->wqbuf_lastindex;
+                       wqbuf_firstindex = acb->wqbuf_firstindex;
+                       if(wqbuf_lastindex != wqbuf_firstindex) {
+                               arcmsr_Write_data_2iop_wqbuffer(acb);
+                               pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR;
                        } else {
-                               my_empty_len=(wqbuf_firstindex-wqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1);
-                               if(my_empty_len>=user_len) {
-                                       while(user_len>0) {
+                               my_empty_len = (wqbuf_firstindex - wqbuf_lastindex - 1) &
+                                   (ARCMSR_MAX_QBUFFER - 1);
+                               if(my_empty_len >= user_len) {
+                                       while(user_len > 0) {
                                                /*copy srb data to wqbuffer*/
-                                               pQbuffer= &acb->wqbuffer[acb->wqbuf_lastindex];
-                                               memcpy(pQbuffer, ptmpuserbuffer, 1);
+                                               pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex];
+                                               *pQbuffer = *ptmpuserbuffer;
                                                acb->wqbuf_lastindex++;
                                                acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
                                                /*if last index number set it to 0 */
@@ -1845,19 +2222,19 @@ u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_c
                                        }
                                        /*post fist Qbuffer*/
                                        if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) {
-                                               acb->acb_flags &=~ACB_F_MESSAGE_WQBUFFER_CLEARED;
-                                               arcmsr_post_ioctldata2iop(acb);
+                                               acb->acb_flags &= ~ACB_F_MESSAGE_WQBUFFER_CLEARED;
+                                               arcmsr_Write_data_2iop_wqbuffer(acb);
                                        }
-                                       pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK;
+                                       pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
                                } else {
-                                       pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR;
+                                       pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR;
                                }
                        }
-                       retvalue=ARCMSR_MESSAGE_SUCCESS;
+                       retvalue = ARCMSR_MESSAGE_SUCCESS;
                }
                break;
        case ARCMSR_MESSAGE_CLEAR_RQBUFFER: {
-                       u_int8_t * pQbuffer=acb->rqbuffer;
+                       u_int8_t *pQbuffer = acb->rqbuffer;
 
                        if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
                                acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
@@ -1865,16 +2242,16 @@ u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_c
                                /*signature, let IOP know data has been readed */
                        }
                        acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED;
-                       acb->rqbuf_firstindex=0;
-                       acb->rqbuf_lastindex=0;
+                       acb->rqbuf_firstindex = 0;
+                       acb->rqbuf_lastindex = 0;
                        memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
-                       pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK;
-                       retvalue=ARCMSR_MESSAGE_SUCCESS;
+                       pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
+                       retvalue = ARCMSR_MESSAGE_SUCCESS;
                }
                break;
        case ARCMSR_MESSAGE_CLEAR_WQBUFFER:
                {
-                       u_int8_t * pQbuffer=acb->wqbuffer;
+                       u_int8_t *pQbuffer = acb->wqbuffer;
 
                        if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
                                acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
@@ -1882,15 +2259,15 @@ u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_c
                                /*signature, let IOP know data has been readed */
                        }
                        acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ);
-                       acb->wqbuf_firstindex=0;
-                       acb->wqbuf_lastindex=0;
+                       acb->wqbuf_firstindex = 0;
+                       acb->wqbuf_lastindex = 0;
                        memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
-                       pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK;
-                       retvalue=ARCMSR_MESSAGE_SUCCESS;
+                       pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
+                       retvalue = ARCMSR_MESSAGE_SUCCESS;
                }
                break;
        case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: {
-                       u_int8_t * pQbuffer;
+                       u_int8_t *pQbuffer;
 
                        if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
                                acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
@@ -1900,44 +2277,44 @@ u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_c
                        acb->acb_flags  |= (ACB_F_MESSAGE_WQBUFFER_CLEARED
                                        |ACB_F_MESSAGE_RQBUFFER_CLEARED
                                        |ACB_F_MESSAGE_WQBUFFER_READ);
-                       acb->rqbuf_firstindex=0;
-                       acb->rqbuf_lastindex=0;
-                       acb->wqbuf_firstindex=0;
-                       acb->wqbuf_lastindex=0;
-                       pQbuffer=acb->rqbuffer;
+                       acb->rqbuf_firstindex = 0;
+                       acb->rqbuf_lastindex = 0;
+                       acb->wqbuf_firstindex = 0;
+                       acb->wqbuf_lastindex = 0;
+                       pQbuffer = acb->rqbuffer;
                        memset(pQbuffer, 0, sizeof(struct QBUFFER));
-                       pQbuffer=acb->wqbuffer;
+                       pQbuffer = acb->wqbuffer;
                        memset(pQbuffer, 0, sizeof(struct QBUFFER));
-                       pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK;
-                       retvalue=ARCMSR_MESSAGE_SUCCESS;
+                       pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
+                       retvalue = ARCMSR_MESSAGE_SUCCESS;
                }
                break;
        case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: {
-                       pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_3F;
-                       retvalue=ARCMSR_MESSAGE_SUCCESS;
+                       pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F;
+                       retvalue = ARCMSR_MESSAGE_SUCCESS;
                }
                break;
        case ARCMSR_MESSAGE_SAY_HELLO: {
-                       u_int8_t * hello_string="Hello! I am ARCMSR";
-                       u_int8_t * puserbuffer=(u_int8_t *)pcmdmessagefld->messagedatabuffer;
+                       u_int8_t *hello_string = "Hello! I am ARCMSR";
+                       u_int8_t *puserbuffer = (u_int8_t *)pcmdmessagefld->messagedatabuffer;
 
                        if(memcpy(puserbuffer, hello_string, (int16_t)strlen(hello_string))) {
-                               pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR;
+                               pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR;
                                ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
                                return ENOIOCTL;
                        }
-                       pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK;
-                       retvalue=ARCMSR_MESSAGE_SUCCESS;
+                       pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
+                       retvalue = ARCMSR_MESSAGE_SUCCESS;
                }
                break;
        case ARCMSR_MESSAGE_SAY_GOODBYE: {
                        arcmsr_iop_parking(acb);
-                       retvalue=ARCMSR_MESSAGE_SUCCESS;
+                       retvalue = ARCMSR_MESSAGE_SUCCESS;
                }
                break;
        case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: {
                        arcmsr_flush_adapter_cache(acb);
-                       retvalue=ARCMSR_MESSAGE_SUCCESS;
+                       retvalue = ARCMSR_MESSAGE_SUCCESS;
                }
                break;
        }
@@ -1951,54 +2328,46 @@ u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_c
 static void arcmsr_free_srb(struct CommandControlBlock *srb)
 {
        struct AdapterControlBlock      *acb;
-       int     mutex;
 
        acb = srb->acb;
-       mutex = lockstatus(&acb->qbuffer_lock, curthread);
-       if( mutex == 0 )
-               ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
-       srb->srb_state=ARCMSR_SRB_DONE;
-       srb->srb_flags=0;
-       acb->srbworkingQ[acb->workingsrb_doneindex]=srb;
+       ARCMSR_LOCK_ACQUIRE(&acb->srb_lock);
+       srb->srb_state = ARCMSR_SRB_DONE;
+       srb->srb_flags = 0;
+       acb->srbworkingQ[acb->workingsrb_doneindex] = srb;
        acb->workingsrb_doneindex++;
        acb->workingsrb_doneindex %= ARCMSR_MAX_FREESRB_NUM;
-       if( mutex == 0 )
-               ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
+       ARCMSR_LOCK_RELEASE(&acb->srb_lock);
 }
 /*
 **************************************************************************
 **************************************************************************
 */
-struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb)
+struct CommandControlBlock *arcmsr_get_freesrb(struct AdapterControlBlock *acb)
 {
-       struct CommandControlBlock *srb=NULL;
+       struct CommandControlBlock *srb = NULL;
        u_int32_t workingsrb_startindex, workingsrb_doneindex;
-       int     mutex;
 
-       mutex = lockstatus(&acb->qbuffer_lock, curthread);
-       if( mutex == 0 )
-               ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
-       workingsrb_doneindex=acb->workingsrb_doneindex;
-       workingsrb_startindex=acb->workingsrb_startindex;
-       srb=acb->srbworkingQ[workingsrb_startindex];
+       ARCMSR_LOCK_ACQUIRE(&acb->srb_lock);
+       workingsrb_doneindex = acb->workingsrb_doneindex;
+       workingsrb_startindex = acb->workingsrb_startindex;
+       srb = acb->srbworkingQ[workingsrb_startindex];
        workingsrb_startindex++;
        workingsrb_startindex %= ARCMSR_MAX_FREESRB_NUM;
-       if(workingsrb_doneindex!=workingsrb_startindex) {
-               acb->workingsrb_startindex=workingsrb_startindex;
+       if(workingsrb_doneindex != workingsrb_startindex) {
+               acb->workingsrb_startindex = workingsrb_startindex;
        } else {
-               srb=NULL;
+               srb = NULL;
        }
-       if( mutex == 0 )
-               ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
+       ARCMSR_LOCK_RELEASE(&acb->srb_lock);
        return(srb);
 }
 /*
 **************************************************************************
 **************************************************************************
 */
-static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb)
+static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *pccb)
 {
-       struct CMD_MESSAGE_FIELD * pcmdmessagefld;
+       struct CMD_MESSAGE_FIELD *pcmdmessagefld;
        int retvalue = 0, transfer_len = 0;
        char *buffer;
        u_int32_t controlcode = (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[5] << 24 |
@@ -2021,13 +2390,14 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *
        switch(controlcode) {
        case ARCMSR_MESSAGE_READ_RQBUFFER: {
                        u_int8_t *pQbuffer;
-                       u_int8_t *ptmpQbuffer=pcmdmessagefld->messagedatabuffer;
+                       u_int8_t *ptmpQbuffer = pcmdmessagefld->messagedatabuffer;
                        int32_t allxfer_len = 0;
 
+                       ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
                        while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex)
                                && (allxfer_len < 1031)) {
                                pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex];
-                               memcpy(ptmpQbuffer, pQbuffer, 1);
+                               *ptmpQbuffer = *pQbuffer;
                                acb->rqbuf_firstindex++;
                                acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
                                ptmpQbuffer++;
@@ -2035,38 +2405,29 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *
                        }
                        if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
                                struct QBUFFER  *prbuffer;
-                               u_int8_t  *iop_data;
-                               int32_t iop_len;
 
                                acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
-                               prbuffer=arcmsr_get_iop_rqbuffer(acb);
-                               iop_data = (u_int8_t *)prbuffer->data;
-                               iop_len =(u_int32_t)prbuffer->data_len;
-                               while (iop_len > 0) {
-                               pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex];
-                                       memcpy(pQbuffer, iop_data, 1);
-                                       acb->rqbuf_lastindex++;
-                                       acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
-                                       iop_data++;
-                                       iop_len--;
-                               }
-                               arcmsr_iop_message_read(acb);
+                               prbuffer = arcmsr_get_iop_rqbuffer(acb);
+                               if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
+                                       acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
                        }
                        pcmdmessagefld->cmdmessage.Length = allxfer_len;
                        pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
-                       retvalue=ARCMSR_MESSAGE_SUCCESS;
+                       retvalue = ARCMSR_MESSAGE_SUCCESS;
+                       ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
                }
                break;
        case ARCMSR_MESSAGE_WRITE_WQBUFFER: {
                        int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
                        u_int8_t *pQbuffer;
-                       u_int8_t *ptmpuserbuffer=pcmdmessagefld->messagedatabuffer;
+                       u_int8_t *ptmpuserbuffer = pcmdmessagefld->messagedatabuffer;
 
                        user_len = pcmdmessagefld->cmdmessage.Length;
+                       ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
                        wqbuf_lastindex = acb->wqbuf_lastindex;
                        wqbuf_firstindex = acb->wqbuf_firstindex;
                        if (wqbuf_lastindex != wqbuf_firstindex) {
-                               arcmsr_post_ioctldata2iop(acb);
+                               arcmsr_Write_data_2iop_wqbuffer(acb);
                                /* has error report sensedata */
                            if(pccb->csio.sense_len) {
                                ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70);
@@ -2085,7 +2446,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *
                                if (my_empty_len >= user_len) {
                                        while (user_len > 0) {
                                                pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex];
-                                               memcpy(pQbuffer, ptmpuserbuffer, 1);
+                                               *pQbuffer = *ptmpuserbuffer;
                                                acb->wqbuf_lastindex++;
                                                acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
                                                ptmpuserbuffer++;
@@ -2093,8 +2454,8 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *
                                        }
                                        if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) {
                                                acb->acb_flags &=
-                                               ~ACB_F_MESSAGE_WQBUFFER_CLEARED;
-                                               arcmsr_post_ioctldata2iop(acb);
+                                                   ~ACB_F_MESSAGE_WQBUFFER_CLEARED;
+                                               arcmsr_Write_data_2iop_wqbuffer(acb);
                                        }
                                } else {
                                        /* has error report sensedata */
@@ -2111,11 +2472,13 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *
                                        retvalue = ARCMSR_MESSAGE_FAIL;
                                }
                        }
+                       ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
                }
                break;
        case ARCMSR_MESSAGE_CLEAR_RQBUFFER: {
                        u_int8_t *pQbuffer = acb->rqbuffer;
 
+                       ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
                        if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
                                acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
                                arcmsr_iop_message_read(acb);
@@ -2125,12 +2488,14 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *
                        acb->rqbuf_lastindex = 0;
                        memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
                        pcmdmessagefld->cmdmessage.ReturnCode =
-                       ARCMSR_MESSAGE_RETURNCODE_OK;
+                           ARCMSR_MESSAGE_RETURNCODE_OK;
+                       ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
                }
                break;
        case ARCMSR_MESSAGE_CLEAR_WQBUFFER: {
                        u_int8_t *pQbuffer = acb->wqbuffer;
 
+                       ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
                        if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
                                acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
                                arcmsr_iop_message_read(acb);
@@ -2143,11 +2508,13 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *
                        memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
                        pcmdmessagefld->cmdmessage.ReturnCode =
                                ARCMSR_MESSAGE_RETURNCODE_OK;
+                       ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
                }
                break;
        case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: {
                        u_int8_t *pQbuffer;
 
+                       ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
                        if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
                                acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
                                arcmsr_iop_message_read(acb);
@@ -2165,6 +2532,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *
                        pQbuffer = acb->wqbuffer;
                        memset(pQbuffer, 0, sizeof (struct QBUFFER));
                        pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
+                       ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
                }
                break;
        case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: {
@@ -2172,7 +2540,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *
                }
                break;
        case ARCMSR_MESSAGE_SAY_HELLO: {
-                       int8_t * hello_string = "Hello! I am ARCMSR";
+                       int8_t *hello_string = "Hello! I am ARCMSR";
 
                        memcpy(pcmdmessagefld->messagedatabuffer, hello_string
                                , (int16_t)strlen(hello_string));
@@ -2197,17 +2565,15 @@ message_out:
 */
 static void arcmsr_execute_srb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
 {
-       struct CommandControlBlock *srb=(struct CommandControlBlock *)arg;
-       struct AdapterControlBlock *acb=(struct AdapterControlBlock *)srb->acb;
-       union ccb * pccb;
+       struct CommandControlBlock *srb = (struct CommandControlBlock *)arg;
+       struct AdapterControlBlock *acb = (struct AdapterControlBlock *)srb->acb;
+       union ccb *pccb;
        int target, lun;
 
-       pccb=srb->pccb;
-       target=pccb->ccb_h.target_id;
-       lun=pccb->ccb_h.target_lun;
-#ifdef ARCMSR_DEBUG1
+       pccb = srb->pccb;
+       target = pccb->ccb_h.target_id;
+       lun = pccb->ccb_h.target_lun;
        acb->pktRequestCount++;
-#endif
        if(error != 0) {
                if(error != EFBIG) {
                        kprintf("arcmsr%d: unexpected error %x"
@@ -2231,12 +2597,12 @@ static void arcmsr_execute_srb(void *arg, bus_dma_segment_t *dm_segs, int nseg,
                arcmsr_srb_complete(srb, 0);
                return;
        }
-       if(acb->devstate[target][lun]==ARECA_RAID_GONE) {
+       if(acb->devstate[target][lun] == ARECA_RAID_GONE) {
                u_int8_t block_cmd, cmd;
 
                cmd = pccb->csio.cdb_io.cdb_bytes[0];
-               block_cmd= cmd & 0x0f;
-               if(block_cmd==0x08 || block_cmd==0x0a) {
+               block_cmd = cmd & 0x0f;
+               if(block_cmd == 0x08 || block_cmd == 0x0a) {
                        kprintf("arcmsr%d:block 'read/write' command "
                                "with gone raid volume Cmd=0x%2x, TargetId=%d, Lun=%d \n"
                                , acb->pci_unit, cmd, target, lun);
@@ -2252,10 +2618,14 @@ static void arcmsr_execute_srb(void *arg, bus_dma_segment_t *dm_segs, int nseg,
                arcmsr_srb_complete(srb, 0);
                return;
        }
-       if(acb->srboutstandingcount > ARCMSR_MAX_OUTSTANDING_CMD) {
-               xpt_freeze_simq(acb->psim, 1);
-               pccb->ccb_h.status = CAM_REQUEUE_REQ;
-               acb->acb_flags |= ACB_F_CAM_DEV_QFRZN;
+       if(acb->srboutstandingcount >= acb->maxOutstanding) {
+               if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) == 0)
+               {
+                       xpt_freeze_simq(acb->psim, 1);
+                       acb->acb_flags |= ACB_F_CAM_DEV_QFRZN;
+               }
+               pccb->ccb_h.status &= ~CAM_SIM_QUEUED;
+               pccb->ccb_h.status |= CAM_REQUEUE_REQ;
                arcmsr_srb_complete(srb, 0);
                return;
        }
@@ -2273,12 +2643,12 @@ static void arcmsr_execute_srb(void *arg, bus_dma_segment_t *dm_segs, int nseg,
 *****************************************************************************************
 *****************************************************************************************
 */
-static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb)
+static u_int8_t arcmsr_seek_cmd2abort(union ccb *abortccb)
 {
        struct CommandControlBlock *srb;
-       struct AdapterControlBlock *acb=(struct AdapterControlBlock *) abortccb->ccb_h.arcmsr_ccbacb_ptr;
+       struct AdapterControlBlock *acb = (struct AdapterControlBlock *) abortccb->ccb_h.arcmsr_ccbacb_ptr;
        u_int32_t intmask_org;
-       int i=0;
+       int i = 0;
 
        acb->num_aborts++;
        /*
@@ -2290,18 +2660,18 @@ static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb)
        ** command return success.
        ***************************************************************************
        */
-       if(acb->srboutstandingcount!=0) {
+       if(acb->srboutstandingcount != 0) {
                /* disable all outbound interrupt */
-               intmask_org=arcmsr_disable_allintr(acb);
-               for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) {
-                       srb=acb->psrb_pool[i];
-                       if(srb->srb_state==ARCMSR_SRB_START) {
-                               if(srb->pccb==abortccb) {
-                                       srb->srb_state=ARCMSR_SRB_ABORTED;
-                                       kprintf("arcmsr%d:scsi id=%d lun=%d abort srb '%p'"
+               intmask_org = arcmsr_disable_allintr(acb);
+               for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) {
+                       srb = acb->psrb_pool[i];
+                       if(srb->srb_state == ARCMSR_SRB_START) {
+                               if(srb->pccb == abortccb) {
+                                       srb->srb_state = ARCMSR_SRB_ABORTED;
+                                       kprintf("arcmsr%d:scsi id=%d lun=%jx abort srb '%p'"
                                                "outstanding command \n"
                                                , acb->pci_unit, abortccb->ccb_h.target_id
-                                               , abortccb->ccb_h.target_lun, srb);
+                                               , (uintmax_t)abortccb->ccb_h.target_lun, srb);
                                        arcmsr_polling_srbdone(acb, srb);
                                        /* enable outbound Post Queue, outbound doorbell Interrupt */
                                        arcmsr_enable_allintr(acb, intmask_org);
@@ -2320,11 +2690,11 @@ static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb)
 */
 static void arcmsr_bus_reset(struct AdapterControlBlock *acb)
 {
-       int retry=0;
+       int retry = 0;
 
        acb->num_resets++;
-       acb->acb_flags |=ACB_F_BUS_RESET;
-       while(acb->srboutstandingcount!=0 && retry < 400) {
+       acb->acb_flags |= ACB_F_BUS_RESET;
+       while(acb->srboutstandingcount != 0 && retry < 400) {
                arcmsr_interrupt(acb);
                UDELAY(25000);
                retry++;
@@ -2337,19 +2707,19 @@ static void arcmsr_bus_reset(struct AdapterControlBlock *acb)
 **************************************************************************
 */
 static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb,
-               union ccb * pccb)
+               union ccb *pccb)
 {
+       if (pccb->ccb_h.target_lun) {
+               pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
+               xpt_done(pccb);
+               return;
+       }
        pccb->ccb_h.status |= CAM_REQ_CMP;
        switch (pccb->csio.cdb_io.cdb_bytes[0]) {
        case INQUIRY: {
                unsigned char inqdata[36];
-               char *buffer=pccb->csio.data_ptr;
+               char *buffer = pccb->csio.data_ptr;
 
-               if (pccb->ccb_h.target_lun) {
-                       pccb->ccb_h.status |= CAM_SEL_TIMEOUT;
-                       xpt_done(pccb);
-                       return;
-               }
                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 */
@@ -2382,12 +2752,12 @@ static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb,
 *********************************************************************
 *********************************************************************
 */
-static void arcmsr_action(struct cam_sim * psim, union ccb * pccb)
+static void arcmsr_action(struct cam_sim *psim, union ccb *pccb)
 {
-       struct AdapterControlBlock *  acb;
+       struct AdapterControlBlock *acb;
 
-       acb=(struct AdapterControlBlock *) cam_sim_softc(psim);
-       if(acb==NULL) {
+       acb = (struct AdapterControlBlock *) cam_sim_softc(psim);
+       if(acb == NULL) {
                pccb->ccb_h.status |= CAM_REQ_INVALID;
                xpt_done(pccb);
                return;
@@ -2395,14 +2765,14 @@ static void arcmsr_action(struct cam_sim * psim, union ccb * pccb)
        switch (pccb->ccb_h.func_code) {
        case XPT_SCSI_IO: {
                        struct CommandControlBlock *srb;
-                       int target=pccb->ccb_h.target_id;
+                       int target = pccb->ccb_h.target_id;
 
                        if(target == 16) {
                                /* virtual device for iop message transfer */
                                arcmsr_handle_virtual_command(acb, pccb);
                                return;
                        }
-                       if((srb=arcmsr_get_freesrb(acb)) == NULL) {
+                       if((srb = arcmsr_get_freesrb(acb)) == NULL) {
                                pccb->ccb_h.status |= CAM_RESRC_UNAVAIL;
                                xpt_done(pccb);
                                return;
@@ -2462,27 +2832,30 @@ static void arcmsr_action(struct cam_sim * psim, union ccb * pccb)
                        break;
                }
        case XPT_PATH_INQ: {
-                       struct ccb_pathinq *cpi= &pccb->cpi;
-
-                       cpi->version_num=1;
-                       cpi->hba_inquiry=PI_SDTR_ABLE | PI_TAG_ABLE;
-                       cpi->target_sprt=0;
-                       cpi->hba_misc=0;
-                       cpi->hba_eng_cnt=0;
-                       cpi->max_target=ARCMSR_MAX_TARGETID;        /* 0-16 */
-                       cpi->max_lun=ARCMSR_MAX_TARGETLUN;          /* 0-7 */
-                       cpi->initiator_id=ARCMSR_SCSI_INITIATOR_ID; /* 255 */
-                       cpi->bus_id=cam_sim_bus(psim);
+                       struct ccb_pathinq *cpi = &pccb->cpi;
+
+                       cpi->version_num = 1;
+                       cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE;
+                       cpi->target_sprt = 0;
+                       cpi->hba_misc = 0;
+                       cpi->hba_eng_cnt = 0;
+                       cpi->max_target = ARCMSR_MAX_TARGETID;        /* 0-16 */
+                       cpi->max_lun = ARCMSR_MAX_TARGETLUN;        /* 0-7 */
+                       cpi->initiator_id = ARCMSR_SCSI_INITIATOR_ID; /* 255 */
+                       cpi->bus_id = cam_sim_bus(psim);
                        strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
                        strncpy(cpi->hba_vid, "ARCMSR", HBA_IDLEN);
                        strncpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN);
-                       cpi->unit_number=cam_sim_unit(psim);
-                       if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G)
+                       cpi->unit_number = cam_sim_unit(psim);
+                       if(acb->adapter_bus_speed == ACB_BUS_SPEED_12G)
+                               cpi->base_transfer_speed = 1200000;
+                       else if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G)
                                cpi->base_transfer_speed = 600000;
                        else
                                cpi->base_transfer_speed = 300000;
                        if((acb->vendor_device_id == PCIDevVenIDARC1880) ||
-                          (acb->vendor_device_id == PCIDevVenIDARC1680))
+                          (acb->vendor_device_id == PCIDevVenIDARC1680) ||
+                          (acb->vendor_device_id == PCIDevVenIDARC1214))
                        {
                                cpi->transport = XPORT_SAS;
                                cpi->transport_version = 0;
@@ -2502,7 +2875,7 @@ static void arcmsr_action(struct cam_sim * psim, union ccb * pccb)
        case XPT_ABORT: {
                        union ccb *pabort_ccb;
 
-                       pabort_ccb=pccb->cab.abort_ccb;
+                       pabort_ccb = pccb->cab.abort_ccb;
                        switch (pabort_ccb->ccb_h.func_code) {
                        case XPT_ACCEPT_TARGET_IO:
                        case XPT_IMMED_NOTIFY:
@@ -2552,7 +2925,7 @@ static void arcmsr_action(struct cam_sim * psim, union ccb * pccb)
                                xpt_done(pccb);
                                break;
                        }
-                       cts= &pccb->cts;
+                       cts = &pccb->cts;
                        {
                                struct ccb_trans_settings_scsi *scsi;
                                struct ccb_trans_settings_spi *spi;
@@ -2564,14 +2937,18 @@ 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 == PCIDevVenIDARC1680))
+                                  (acb->vendor_device_id == PCIDevVenIDARC1680) ||
+                                  (acb->vendor_device_id == PCIDevVenIDARC1214))
                                {
                                        cts->protocol_version = SCSI_REV_SPC2;
                                        cts->transport_version = 0;
                                        cts->transport = XPORT_SAS;
                                        sas = &cts->xport_specific.sas;
                                        sas->valid = CTS_SAS_VALID_SPEED;
-                                       if(acb->vendor_device_id == PCIDevVenIDARC1880)
+                                       if (acb->sub_device_id == ARECA_SUB_DEV_ID_1883)
+                                               sas->bitrate = 1200000;
+                                       else if((acb->vendor_device_id == PCIDevVenIDARC1880) ||
+                                          (acb->vendor_device_id == PCIDevVenIDARC1214))
                                                sas->bitrate = 600000;
                                        else if(acb->vendor_device_id == PCIDevVenIDARC1680)
                                                sas->bitrate = 300000;
@@ -2583,9 +2960,9 @@ 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;
-                                       spi->sync_offset=32;
-                                       spi->bus_width=MSG_EXT_WDTR_BUS_16_BIT;
+                                       spi->sync_period = 2;
+                                       spi->sync_offset = 32;
+                                       spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
                                        spi->valid = CTS_SPI_VALID_DISC
                                                | CTS_SPI_VALID_SYNC_RATE
                                                | CTS_SPI_VALID_SYNC_OFFSET
@@ -2657,6 +3034,18 @@ static void arcmsr_start_hbc_bgrb(struct AdapterControlBlock *acb)
 **********************************************************************
 **********************************************************************
 */
+static void arcmsr_start_hbd_bgrb(struct AdapterControlBlock *acb)
+{
+       acb->acb_flags |= ACB_F_MSG_START_BGRB;
+       CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB);
+       if(!arcmsr_hbd_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) {
@@ -2669,6 +3058,9 @@ static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb)
        case ACB_ADAPTER_TYPE_C:
                arcmsr_start_hbc_bgrb(acb);
                break;
+       case ACB_ADAPTER_TYPE_D:
+               arcmsr_start_hbd_bgrb(acb);
+               break;
        }
 }
 /*
@@ -2688,8 +3080,8 @@ 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,
-                       0, outbound_queueport))==0xFFFFFFFF) {
+               if((flag_srb = CHIP_REG_READ32(HBA_MessageUnit, 
+                       0, outbound_queueport)) == 0xFFFFFFFF) {
                        if(poll_srb_done) {
                                break;/*chip FIFO no ccb for completion already*/
                        } else {
@@ -2701,17 +3093,17 @@ polling_ccb_retry:
                        }
                }
                /* check if command done with no error*/
-               srb=(struct CommandControlBlock *)
+               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;
-               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=%d srb='%p'"
+        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) {
+                               kprintf("arcmsr%d: scsi id=%d lun=%jx srb='%p'"
                                        "poll command abort successfully \n"
                                        , acb->pci_unit
                                        , srb->pccb->ccb_h.target_id
-                                       , srb->pccb->ccb_h.target_lun, srb);
+                                       , (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
                                srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
                                arcmsr_srb_complete(srb, 1);
                                continue;
@@ -2732,7 +3124,7 @@ polling_ccb_retry:
 */
 static void arcmsr_polling_hbb_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
 {
-       struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu;
+       struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
        struct CommandControlBlock *srb;
        u_int32_t flag_srb, poll_srb_done=0, poll_count=0;
        int index;
@@ -2744,8 +3136,8 @@ polling_ccb_retry:
        0, 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;
-               if((flag_srb=phbbmu->done_qbuffer[index]) == 0) {
+               index = phbbmu->doneq_index;
+               if((flag_srb = phbbmu->done_qbuffer[index]) == 0) {
                        if(poll_srb_done) {
                                break;/*chip FIFO no ccb for completion already*/
                        } else {
@@ -2756,22 +3148,22 @@ polling_ccb_retry:
                                goto polling_ccb_retry;
                        }
                }
-               phbbmu->done_qbuffer[index]=0;
+               phbbmu->done_qbuffer[index] = 0;
                index++;
                index %= ARCMSR_MAX_HBB_POSTQUEUE;     /*if last index number set it to 0 */
-               phbbmu->doneq_index=index;
+               phbbmu->doneq_index = index;
                /* check if command done with no error*/
-               srb=(struct CommandControlBlock *)
+               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;
-               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=%d srb='%p'"
+        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) {
+                               kprintf("arcmsr%d: scsi id=%d lun=%jx srb='%p'"
                                        "poll command abort successfully \n"
                                        , acb->pci_unit
                                        , srb->pccb->ccb_h.target_id
-                                       , srb->pccb->ccb_h.target_lun, srb);
+                                       , (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
                                srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
                                arcmsr_srb_complete(srb, 1);
                                continue;
@@ -2816,14 +3208,70 @@ 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;
+               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;
+               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*/
+}
+/*
+**********************************************************************
+** 
+**********************************************************************
+*/
+static void arcmsr_polling_hbd_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
+{
+       struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
+       struct CommandControlBlock *srb;
+       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);
+       while(1) {
+               outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow;
+               doneq_index = phbdmu->doneq_index;
+               if ((outbound_write_pointer & 0xFF) == (doneq_index & 0xFF)) {
+                       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;
+                       }
+               }
+               doneq_index = arcmsr_get_doneq_index(phbdmu);
+               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;
+               CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_read_pointer, doneq_index);
                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=%d srb='%p'poll command abort successfully \n"
-                                               , acb->pci_unit, srb->pccb->ccb_h.target_id, srb->pccb->ccb_h.target_lun, srb);
+                       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;
@@ -2854,6 +3302,10 @@ static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct Comma
                        arcmsr_polling_hbc_srbdone(acb, poll_srb);
                }
                break;
+       case ACB_ADAPTER_TYPE_D: {
+                       arcmsr_polling_hbd_srbdone(acb, poll_srb);
+               }
+               break;
        }
 }
 /*
@@ -2862,11 +3314,11 @@ static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct Comma
 */
 static void arcmsr_get_hba_config(struct AdapterControlBlock *acb)
 {
-       char *acb_firm_model=acb->firm_model;
-       char *acb_firm_version=acb->firm_version;
+       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 HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);        /*firm_model,15,60-67*/
-       size_t iop_firm_version=offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]);       /*firm_version,17,68-83*/
+       size_t iop_firm_model = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);      /*firm_model,15,60-67*/
+       size_t iop_firm_version = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]);     /*firm_version,17,68-83*/
        size_t iop_device_map = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
        int i;
 
@@ -2874,33 +3326,37 @@ static void arcmsr_get_hba_config(struct AdapterControlBlock *acb)
        if(!arcmsr_hba_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);
+       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);
+       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);
+       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 \n", acb->pci_unit, ARCMSR_DRIVER_VERSION);
-       kprintf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, 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*/
-       acb->firm_sdram_size=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[3]);    /*firm_sdram_size, 3, 12-15*/
-       acb->firm_ide_channels=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[4]);  /*firm_ide_channels, 4, 16-19*/
-       acb->firm_cfg_version=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);   /*firm_cfg_version,  25,          */
+       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*/
+       acb->firm_sdram_size = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[3]);    /*firm_sdram_size, 3, 12-15*/
+       acb->firm_ide_channels = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[4]);  /*firm_ide_channels, 4, 16-19*/
+       acb->firm_cfg_version = CHIP_REG_READ32(HBA_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;
 }
 /*
 **********************************************************************
@@ -2908,11 +3364,11 @@ static void arcmsr_get_hba_config(struct AdapterControlBlock *acb)
 */
 static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb)
 {
-       char *acb_firm_model=acb->firm_model;
-       char *acb_firm_version=acb->firm_version;
+       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 HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);  /*firm_model,15,60-67*/
-       size_t iop_firm_version=offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/
+       size_t iop_firm_model = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);        /*firm_model,15,60-67*/
+       size_t iop_firm_version = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]);       /*firm_version,17,68-83*/
        size_t iop_device_map = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
        int i;
 
@@ -2920,33 +3376,37 @@ static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb)
        if(!arcmsr_hbb_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[1], acb->bhandle[1], iop_firm_model+i);
+       i = 0;
+       while(i < 8) {
+               *acb_firm_model = bus_space_read_1(acb->btag[1], acb->bhandle[1], 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[1], acb->bhandle[1], iop_firm_version+i);
+       i = 0;
+       while(i < 16) {
+               *acb_firm_version = bus_space_read_1(acb->btag[1], acb->bhandle[1], 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[1], acb->bhandle[1], iop_device_map+i);
+       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++;
                i++;
        }
-       kprintf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION);
-       kprintf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, 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*/
-       acb->firm_sdram_size=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3]);    /*firm_sdram_size, 3, 12-15*/
-       acb->firm_ide_channels=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4]);  /*firm_ide_channels, 4, 16-19*/
-       acb->firm_cfg_version=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);      /*firm_cfg_version,  25,          */
+       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*/
+       acb->firm_sdram_size = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3]);    /*firm_sdram_size, 3, 12-15*/
+       acb->firm_ide_channels = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4]);  /*firm_ide_channels, 4, 16-19*/
+       acb->firm_cfg_version = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);    /*firm_cfg_version,  25,          */
+       if(acb->firm_numbers_queue > ARCMSR_MAX_HBB_POSTQUEUE)
+               acb->maxOutstanding = ARCMSR_MAX_HBB_POSTQUEUE - 1;
+       else
+               acb->maxOutstanding = acb->firm_numbers_queue - 1;
 }
 /*
 **********************************************************************
@@ -2954,11 +3414,11 @@ static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb)
 */
 static void arcmsr_get_hbc_config(struct AdapterControlBlock *acb)
 {
-       char *acb_firm_model=acb->firm_model;
-       char *acb_firm_version=acb->firm_version;
+       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 HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);   /*firm_model,15,60-67*/
-       size_t iop_firm_version=offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/
+       size_t iop_firm_model = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);   /*firm_model,15,60-67*/
+       size_t iop_firm_version = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/
        size_t iop_device_map = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
        int i;
 
@@ -2967,33 +3427,89 @@ static void arcmsr_get_hbc_config(struct AdapterControlBlock *acb)
        if(!arcmsr_hbc_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);
+       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);
+       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);
+       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 \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*/
+       acb->firm_sdram_size    = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[3]);     /*firm_sdram_size,    3, 12-15*/
+       acb->firm_ide_channels  = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[4]);     /*firm_ide_channels,  4, 16-19*/
+       acb->firm_cfg_version   = CHIP_REG_READ32(HBC_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_hbd_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 HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);   /*firm_model,15,60-67*/
+       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);
+       if(!arcmsr_hbd_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 \n", acb->pci_unit, ARCMSR_DRIVER_VERSION);
-       kprintf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, 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*/
-       acb->firm_sdram_size    =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[3]);      /*firm_sdram_size,    3, 12-15*/
-       acb->firm_ide_channels  =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[4]);      /*firm_ide_channels,  4, 16-19*/
-       acb->firm_cfg_version   =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);        /*firm_cfg_version,  25,          */
+       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_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;
+       else
+               acb->maxOutstanding = acb->firm_numbers_queue - 1;
 }
 /*
 **********************************************************************
@@ -3014,6 +3530,10 @@ static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
                        arcmsr_get_hbc_config(acb);
                }
                break;
+       case ACB_ADAPTER_TYPE_D: {
+                       arcmsr_get_hbd_config(acb);
+               }
+               break;
        }
 }
 /*
@@ -3062,6 +3582,18 @@ static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb)
                        }
                }
                break;
+       case ACB_ADAPTER_TYPE_D: {
+                       while ((CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBDMU_MESSAGE_FIRMWARE_OK) == 0)
+                       {
+                               if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */
+                               {
+                                       kprintf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit);
+                                       return;
+                               }
+                               UDELAY(15000); /* wait 15 milli-seconds */
+                       }
+               }
+               break;
        }
 }
 /*
@@ -3092,6 +3624,15 @@ static void arcmsr_clear_doorbell_queue_buffer( struct AdapterControlBlock *acb)
                        outbound_doorbell = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell);
                        CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell);       /*clear doorbell interrupt */
                        CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK);
+                       CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell_clear); /* Dummy read to force pci flush */
+                       CHIP_REG_READ32(HBC_MessageUnit, 0, inbound_doorbell); /* Dummy read to force pci flush */
+               }
+               break;
+       case ACB_ADAPTER_TYPE_D: {
+                       /* empty doorbell Qbuffer if door bell ringed */
+                       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;
@@ -3105,6 +3646,7 @@ static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb)
 {
        unsigned long srb_phyaddr;
        u_int32_t srb_phyaddr_hi32;
+       u_int32_t srb_phyaddr_lo32;
 
        /*
        ********************************************************************
@@ -3112,12 +3654,12 @@ static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb)
        ** if freesrb.HighPart is not zero
        ********************************************************************
        */
-       srb_phyaddr= (unsigned long) acb->srb_phyaddr.phyaddr;
-//     srb_phyaddr_hi32=(u_int32_t) ((srb_phyaddr>>16)>>16);
-       srb_phyaddr_hi32=acb->srb_phyaddr.B.phyadd_high;
+       srb_phyaddr = (unsigned long) acb->srb_phyaddr.phyaddr;
+       srb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high;
+       srb_phyaddr_lo32 = acb->srb_phyaddr.B.phyadd_low;
        switch (acb->adapter_type) {
        case ACB_ADAPTER_TYPE_A: {
-                       if(srb_phyaddr_hi32!=0) {
+                       if(srb_phyaddr_hi32 != 0) {
                                CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG);
                                CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32);
                                CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
@@ -3137,9 +3679,9 @@ static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb)
                        u_int32_t post_queue_phyaddr;
                        struct HBB_MessageUnit *phbbmu;
 
-                       phbbmu=(struct HBB_MessageUnit *)acb->pmu;
-                       phbbmu->postq_index=0;
-                       phbbmu->doneq_index=0;
+                       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);
                        if(!arcmsr_hbb_wait_msgint_ready(acb)) {
                                kprintf( "arcmsr%d: 'set window of post command Q' timeout\n", acb->pci_unit);
@@ -3165,7 +3707,7 @@ static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb)
                }
                break;
        case ACB_ADAPTER_TYPE_C: {
-                       if(srb_phyaddr_hi32!=0) {
+                       if(srb_phyaddr_hi32 != 0) {
                                CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG);
                                CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32);
                                CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
@@ -3177,6 +3719,29 @@ static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb)
                        }
                }
                break;
+       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 
+                                                               + offsetof(struct HBD_MessageUnit0, post_qbuffer);
+                       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);
+                       CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ base */
+                       CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[3], done_queue_phyaddr); /* doneQ base */
+                       CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[4], 0x100);
+                       CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
+                       if(!arcmsr_hbd_wait_msgint_ready(acb)) {
+                               kprintf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit);
+                               return FALSE;
+                       }
+               }
+               break;
        }
        return (TRUE);
 }
@@ -3190,12 +3755,12 @@ static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb)
        {
        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;
                        }
                }
@@ -3211,7 +3776,7 @@ static void arcmsr_iop_init(struct AdapterControlBlock *acb)
        u_int32_t intmask_org;
 
        /* disable all outbound interrupt */
-       intmask_org=arcmsr_disable_allintr(acb);
+       intmask_org = arcmsr_disable_allintr(acb);
        arcmsr_wait_firmware_ready(acb);
        arcmsr_iop_confirm(acb);
        arcmsr_get_firmware_spec(acb);
@@ -3222,7 +3787,7 @@ static void arcmsr_iop_init(struct AdapterControlBlock *acb)
        arcmsr_enable_eoi_mode(acb);
        /* enable outbound Post Queue, outbound doorbell Interrupt */
        arcmsr_enable_allintr(acb, intmask_org);
-       acb->acb_flags |=ACB_F_IOP_INITED;
+       acb->acb_flags |= ACB_F_IOP_INITED;
 }
 /*
 **********************************************************************
@@ -3230,35 +3795,37 @@ static void arcmsr_iop_init(struct AdapterControlBlock *acb)
 */
 static void arcmsr_map_free_srb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
 {
-       struct AdapterControlBlock *acb=arg;
+       struct AdapterControlBlock *acb = arg;
        struct CommandControlBlock *srb_tmp;
-       u_int8_t * dma_memptr;
        u_int32_t i;
-       unsigned long srb_phyaddr=(unsigned long)segs->ds_addr;
+       unsigned long srb_phyaddr = (unsigned long)segs->ds_addr;
 
-       dma_memptr=acb->uncacheptr;
-       acb->srb_phyaddr.phyaddr=srb_phyaddr;
-       srb_tmp=(struct CommandControlBlock *)dma_memptr;
-       for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) {
+       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,
-                        /*flags*/0, &srb_tmp->dm_segs_dmamap)!=0) {
+                        /*flags*/0, &srb_tmp->dm_segs_dmamap) != 0) {
                        acb->acb_flags |= ACB_F_MAPFREESRB_FAILD;
                        kprintf("arcmsr%d:"
                        " srb dmamap bus_dmamap_create error\n", acb->pci_unit);
                        return;
                }
-               srb_tmp->cdb_shifted_phyaddr=(acb->adapter_type==ACB_ADAPTER_TYPE_C)?srb_phyaddr:(srb_phyaddr >> 5);
-               srb_tmp->acb=acb;
-               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);
+               if((acb->adapter_type == ACB_ADAPTER_TYPE_C) || (acb->adapter_type == ACB_ADAPTER_TYPE_D))
+               {
+                       srb_tmp->cdb_phyaddr_low = srb_phyaddr;
+                       srb_tmp->cdb_phyaddr_high = (u_int32_t)((srb_phyaddr >> 16) >> 16);
+               }
+               else
+                       srb_tmp->cdb_phyaddr_low = srb_phyaddr >> 5;
+               srb_tmp->acb = acb;
+               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->vir2phy_offset=(unsigned long)srb_tmp-srb_phyaddr;
+       acb->vir2phy_offset = (unsigned long)srb_tmp - (unsigned long)srb_phyaddr;
 }
 /*
 ************************************************************************
-**
-**
 ************************************************************************
 */
 static void arcmsr_free_resource(struct AdapterControlBlock *acb)
@@ -3277,30 +3844,62 @@ static void arcmsr_free_resource(struct AdapterControlBlock *acb)
 ************************************************************************
 ************************************************************************
 */
+static void arcmsr_mutex_init(struct AdapterControlBlock *acb)
+{
+       ARCMSR_LOCK_INIT(&acb->isr_lock, "arcmsr isr lock");
+       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");
+}
+/*
+************************************************************************
+************************************************************************
+*/
+static void arcmsr_mutex_destroy(struct AdapterControlBlock *acb)
+{
+       ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock);
+       ARCMSR_LOCK_DESTROY(&acb->postDone_lock);
+       ARCMSR_LOCK_DESTROY(&acb->srb_lock);
+       ARCMSR_LOCK_DESTROY(&acb->isr_lock);
+}
+/*
+************************************************************************
+************************************************************************
+*/
 static u_int32_t arcmsr_initialize(device_t dev)
 {
-       struct AdapterControlBlock *acb=device_get_softc(dev);
+       struct AdapterControlBlock *acb = device_get_softc(dev);
        u_int16_t pci_command;
        int i, j,max_coherent_size;
        u_int32_t vendor_dev_id;
 
        vendor_dev_id = pci_get_devid(dev);
        acb->vendor_device_id = vendor_dev_id;
+       acb->sub_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2);
        switch (vendor_dev_id) {
        case PCIDevVenIDARC1880:
        case PCIDevVenIDARC1882:
        case PCIDevVenIDARC1213:
        case PCIDevVenIDARC1223: {
-                       acb->adapter_type=ACB_ADAPTER_TYPE_C;
+                       acb->adapter_type = ACB_ADAPTER_TYPE_C;
+                       if (acb->sub_device_id == ARECA_SUB_DEV_ID_1883)
+                               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 PCIDevVenIDARC1214: {
+                       acb->adapter_type = ACB_ADAPTER_TYPE_D;
                        acb->adapter_bus_speed = ACB_BUS_SPEED_6G;
-                       max_coherent_size=ARCMSR_SRBS_POOL_SIZE;
+                       max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBD_MessageUnit0));
                }
                break;
        case PCIDevVenIDARC1200:
        case PCIDevVenIDARC1201: {
-                       acb->adapter_type=ACB_ADAPTER_TYPE_B;
+                       acb->adapter_type = ACB_ADAPTER_TYPE_B;
                        acb->adapter_bus_speed = ACB_BUS_SPEED_3G;
-                       max_coherent_size=ARCMSR_SRBS_POOL_SIZE+(sizeof(struct HBB_MessageUnit));
+                       max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBB_MessageUnit));
                }
                break;
        case PCIDevVenIDARC1110:
@@ -3322,9 +3921,9 @@ static u_int32_t arcmsr_initialize(device_t dev)
        case PCIDevVenIDARC1381:
        case PCIDevVenIDARC1680:
        case PCIDevVenIDARC1681: {
-                       acb->adapter_type=ACB_ADAPTER_TYPE_A;
+                       acb->adapter_type = ACB_ADAPTER_TYPE_A;
                        acb->adapter_bus_speed = ACB_BUS_SPEED_3G;
-                       max_coherent_size=ARCMSR_SRBS_POOL_SIZE;
+                       max_coherent_size = ARCMSR_SRBS_POOL_SIZE;
                }
                break;
        default: {
@@ -3333,7 +3932,7 @@ static u_int32_t arcmsr_initialize(device_t dev)
                        return ENOMEM;
                }
        }
-       if(bus_dma_tag_create(  /*parent*/      NULL,
+       if(bus_dma_tag_create(  /*PCI parent*/          bus_get_dma_tag(dev),
                                /*alignemnt*/   1,
                                /*boundary*/    0,
                                /*lowaddr*/     BUS_SPACE_MAXADDR,
@@ -3367,6 +3966,7 @@ static u_int32_t arcmsr_initialize(device_t dev)
                kprintf("arcmsr%d: dm_segs_dmat bus_dma_tag_create failure!\n", device_get_unit(dev));
                return ENOMEM;
        }
+
        /* DMA tag for our srb structures.... Allocate the freesrb memory */
        if(bus_dma_tag_create(  /*parent_dmat*/ acb->parent_dmat,
                                /*alignment*/   0x20,
@@ -3402,19 +4002,18 @@ static u_int32_t arcmsr_initialize(device_t dev)
                kprintf("arcmsr%d: srb_dmat bus_dmamap_load failure!\n", device_get_unit(dev));
                return ENXIO;
        }
-       pci_command=pci_read_config(dev, PCIR_COMMAND, 2);
+       pci_command = pci_read_config(dev, PCIR_COMMAND, 2);
        pci_command |= PCIM_CMD_BUSMASTEREN;
        pci_command |= PCIM_CMD_PERRESPEN;
        pci_command |= PCIM_CMD_MWRICEN;
-       /* Enable Busmaster/Mem */
-       pci_command |= PCIM_CMD_MEMEN;
+       /* Enable Busmaster */
        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);
+                       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);
+                       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) {
                                arcmsr_free_resource(acb);
                                kprintf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
@@ -3425,15 +4024,15 @@ static u_int32_t arcmsr_initialize(device_t dev)
                                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) {
+                       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->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;
                }
                break;
        case ACB_ADAPTER_TYPE_B: {
@@ -3441,12 +4040,12 @@ static u_int32_t arcmsr_initialize(device_t dev)
                        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],
+                       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],
+                                       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) {
@@ -3459,28 +4058,54 @@ static u_int32_t arcmsr_initialize(device_t dev)
                                        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) {
+                               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]);
+                               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 *)&freesrb[ARCMSR_MAX_FREESRB_NUM];
-                       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];
+                       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];
                }
                break;
        case ACB_ADAPTER_TYPE_C: {
-                       u_int32_t rid0=PCIR_BAR(1);
+                       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;
+               }
+               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 HBC_MessageUnit), RF_ACTIVE);
+                       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));
@@ -3491,15 +4116,17 @@ static u_int32_t arcmsr_initialize(device_t dev)
                                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) {
+                       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->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;
                }
                break;
        }
@@ -3515,9 +4142,9 @@ static u_int32_t arcmsr_initialize(device_t dev)
        ** init raid volume state
        ********************************************************************
        */
-       for(i=0;i<ARCMSR_MAX_TARGETID;i++) {
-               for(j=0;j<ARCMSR_MAX_TARGETLUN;j++) {
-                       acb->devstate[i][j]=ARECA_RAID_GONE;
+       for(i=0; i < ARCMSR_MAX_TARGETID; i++) {
+               for(j=0; j < ARCMSR_MAX_TARGETLUN; j++) {
+                       acb->devstate[i][j] = ARECA_RAID_GONE;
                }
        }
        arcmsr_iop_init(acb);
@@ -3541,63 +4168,63 @@ static int arcmsr_attach(device_t dev)
                kprintf("arcmsr%d: cannot allocate softc\n", unit);
                return (ENOMEM);
        }
-       ARCMSR_LOCK_INIT(&acb->qbuffer_lock, "arcmsr Q buffer lock");
+       arcmsr_mutex_init(acb);
+       acb->pci_dev = dev;
+       acb->pci_unit = unit;
        if(arcmsr_initialize(dev)) {
                kprintf("arcmsr%d: initialize failure!\n", unit);
-               ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock);
+               arcmsr_mutex_destroy(acb);
                return ENXIO;
        }
        /* 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,
+       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_LOCK_DESTROY(&acb->qbuffer_lock);
+               arcmsr_mutex_destroy(acb);
                kprintf("arcmsr%d: unable to register interrupt handler!\n", unit);
                return ENXIO;
        }
-       acb->irqres=irqres;
-       acb->pci_dev=dev;
-       acb->pci_unit=unit;
+       acb->irqres = irqres;
        /*
         * Now let the CAM generic SCSI layer find the SCSI devices on
         * the bus *  start queue to reset to the idle loop. *
         * Create device queue of SIM(s) *  (MAX_START_JOB - 1) :
         * max_sim_transactions
        */
-       devq=cam_simq_alloc(ARCMSR_MAX_START_JOB);
+       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_LOCK_DESTROY(&acb->qbuffer_lock);
+               arcmsr_mutex_destroy(acb);
                kprintf("arcmsr%d: cam_simq_alloc failure!\n", unit);
                return ENXIO;
        }
-       acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, &acb->qbuffer_lock, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq);
+       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_LOCK_DESTROY(&acb->qbuffer_lock);
+               arcmsr_mutex_destroy(acb);
                kprintf("arcmsr%d: cam_sim_alloc failure!\n", unit);
                return ENXIO;
        }
-       ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
+       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_LOCK_DESTROY(&acb->qbuffer_lock);
+               arcmsr_mutex_destroy(acb);
                kprintf("arcmsr%d: xpt_bus_register failure!\n", unit);
                return ENXIO;
        }
@@ -3608,7 +4235,7 @@ static int arcmsr_attach(device_t dev)
                        pci_release_msi(dev);
                xpt_bus_deregister(cam_sim_path(acb->psim));
                cam_sim_free(acb->psim);
-               ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock);
+               arcmsr_mutex_destroy(acb);
                kprintf("arcmsr%d: xpt_create_path failure!\n", unit);
                return ENXIO;
        }
@@ -3616,16 +4243,16 @@ static int arcmsr_attach(device_t dev)
        ****************************************************
        */
        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;
+       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);
-       ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
+       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 = make_dev(&arcmsr_ops, unit, UID_ROOT, GID_WHEEL /* GID_OPERATOR */, S_IRUSR | S_IWUSR, "arcmsr%d", unit);
 
-       acb->ioctl_dev->si_drv1=acb;
+       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);
@@ -3639,15 +4266,17 @@ static int arcmsr_attach(device_t dev)
 static int arcmsr_probe(device_t dev)
 {
        u_int32_t id;
+       u_int16_t sub_device_id;
        static char buf[256];
-       char x_type[]={"X-TYPE"};
+       char x_type[]={"unknown"};
        char *type;
        int raid6 = 1;
 
        if (pci_get_vendor(dev) != PCI_VENDOR_ID_ARECA) {
                return (ENXIO);
        }
-       switch(id=pci_get_devid(dev)) {
+       sub_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2);
+       switch(id = pci_get_devid(dev)) {
        case PCIDevVenIDARC1110:
        case PCIDevVenIDARC1200:
        case PCIDevVenIDARC1201:
@@ -3665,7 +4294,7 @@ static int arcmsr_probe(device_t dev)
        case PCIDevVenIDARC1261:
        case PCIDevVenIDARC1270:
        case PCIDevVenIDARC1280:
-               type = "SATA";
+               type = "SATA 3G";
                break;
        case PCIDevVenIDARC1212:
        case PCIDevVenIDARC1222:
@@ -3679,16 +4308,24 @@ static int arcmsr_probe(device_t dev)
        case PCIDevVenIDARC1882:
        case PCIDevVenIDARC1213:
        case PCIDevVenIDARC1223:
-               type = "SAS 6G";
+               if (sub_device_id == ARECA_SUB_DEV_ID_1883)
+                       type = "SAS 12G";
+               else
+                       type = "SAS 6G";
                arcmsr_msi_enable = 0;
                break;
+       case PCIDevVenIDARC1214:
+               type = "SATA 6G";
+               break;
        default:
                type = x_type;
+               raid6 = 0;
                break;
        }
        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",
+               type, raid6 ? " (RAID6 capable)" : "");
        device_set_desc_copy(dev, buf);
        return (BUS_PROBE_DEFAULT);
 }
@@ -3703,7 +4340,7 @@ static int arcmsr_shutdown(device_t dev)
        struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev);
 
        /* stop adapter background rebuild */
-       ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
+       ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
        /* disable all outbound interrupt */
        arcmsr_disable_allintr(acb);
        arcmsr_stop_adapter_bgrb(acb);
@@ -3711,28 +4348,26 @@ static int arcmsr_shutdown(device_t dev)
        /* abort all outstanding command */
        acb->acb_flags |= ACB_F_SCSISTOPADAPTER;
        acb->acb_flags &= ~ACB_F_IOP_INITED;
-       if(acb->srboutstandingcount!=0) {
+       if(acb->srboutstandingcount != 0) {
                /*clear and abort all outbound posted Q*/
                arcmsr_done4abort_postqueue(acb);
                /* talk to iop 331 outstanding command aborted*/
                arcmsr_abort_allcmd(acb);
-               for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) {
-                       srb=acb->psrb_pool[i];
-                       if(srb->srb_state==ARCMSR_SRB_START) {
-                               srb->srb_state=ARCMSR_SRB_ABORTED;
+               for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) {
+                       srb = acb->psrb_pool[i];
+                       if(srb->srb_state == ARCMSR_SRB_START) {
+                               srb->srb_state = ARCMSR_SRB_ABORTED;
                                srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
                                arcmsr_srb_complete(srb, 1);
                        }
                }
        }
-       acb->srboutstandingcount=0;
-       acb->workingsrb_doneindex=0;
-       acb->workingsrb_startindex=0;
-#ifdef ARCMSR_DEBUG1
+       acb->srboutstandingcount = 0;
+       acb->workingsrb_doneindex = 0;
+       acb->workingsrb_startindex = 0;
        acb->pktRequestCount = 0;
        acb->pktReturnCount = 0;
-#endif
-       ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
+       ARCMSR_LOCK_RELEASE(&acb->isr_lock);
        return (0);
 }
 /*
@@ -3754,13 +4389,13 @@ static int arcmsr_detach(device_t dev)
        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->qbuffer_lock);
+       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->qbuffer_lock);
-       ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock);
+       ARCMSR_LOCK_RELEASE(&acb->isr_lock);
+       arcmsr_mutex_destroy(acb);
        return (0);
 }
 
@@ -3769,9 +4404,9 @@ static void arcmsr_dump_data(struct AdapterControlBlock *acb)
 {
        if((acb->pktRequestCount - acb->pktReturnCount) == 0)
                return;
-       printf("Command Request Count   =0x%x\n",acb->pktRequestCount);
-       printf("Command Return Count    =0x%x\n",acb->pktReturnCount);
-       printf("Command (Req-Rtn) Count =0x%x\n",(acb->pktRequestCount - acb->pktReturnCount));
-       printf("Queued Command Count    =0x%x\n",acb->srboutstandingcount);
+       kprintf("Command Request Count   =0x%x\n",acb->pktRequestCount);
+       kprintf("Command Return Count    =0x%x\n",acb->pktReturnCount);
+       kprintf("Command (Req-Rtn) Count =0x%x\n",(acb->pktRequestCount - acb->pktReturnCount));
+       kprintf("Queued Command Count    =0x%x\n",acb->srboutstandingcount);
 }
 #endif
index ed91264..45edfff 100644 (file)
@@ -1,17 +1,14 @@
 /*
-***********************************************************************************************
-**        O.S   : FreeBSD
+********************************************************************************
+**        O   : FreeBSD
 **   FILE NAME  : arcmsr.h
 **        BY    : Erich Chen, Ching Huang
-**   Description: SCSI RAID Device Driver for
-**                ARECA SATA/SAS RAID HOST Adapter
-**                [RAID controller:INTEL 331(PCI-X) 341(PCI-EXPRESS) chip set]
-***********************************************************************************************
-************************************************************************
-** Copyright (C) 2002 - 2010, Areca Technology Corporation All rights reserved.
-**
-**     Web site: www.areca.com.tw
-**       E-mail: erich@areca.com.tw; ching2048@areca.com.tw
+**   Description: SCSI RAID Device Driver for 
+**                ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX/ARC188x)
+**                SATA/SAS RAID HOST Adapter
+********************************************************************************
+********************************************************************************
+** Copyright (C) 2002 - 2012, Areca Technology Corporation All rights reserved.
 **
 ** Redistribution and use in source and binary forms,with or without
 ** modification,are permitted provided that the following conditions
 **(INCLUDING NEGLIGENCE OR OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF
 ** THIS SOFTWARE,EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 **************************************************************************
-* $FreeBSD: src/sys/dev/arcmsr/arcmsr.h,v 1.10 2012/09/04 05:15:54 delphij Exp $
+* $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
-#define ARCMSR_MAX_TARGETID                                                    17 /*16 max target id + 1*/
-#define ARCMSR_MAX_TARGETLUN                                                    8 /*8*/
-#define ARCMSR_MAX_CHIPTYPE_NUM                                                 4
-#define ARCMSR_MAX_OUTSTANDING_CMD                                            256
-#define ARCMSR_MAX_START_JOB                                                  257
-#define ARCMSR_MAX_CMD_PERLUN                          ARCMSR_MAX_OUTSTANDING_CMD
-#define ARCMSR_MAX_FREESRB_NUM                         384
-#define ARCMSR_MAX_QBUFFER                                                   4096 /* ioctl QBUFFER */
-#define ARCMSR_MAX_SG_ENTRIES                                                  38 /* max 38*/
-#define ARCMSR_MAX_ADAPTER                                                      4
-#define ARCMSR_RELEASE_SIMQ_LEVEL                                             230
-#define ARCMSR_MAX_HBB_POSTQUEUE                                              264 /* (ARCMSR_MAX_OUTSTANDING_CMD+8) */
-#define        ARCMSR_TIMEOUT_DELAY                            60 /* in sec */
+#define ARCMSR_SCSI_INITIATOR_ID       255
+#define ARCMSR_DEV_SECTOR_SIZE         512
+#define ARCMSR_MAX_XFER_SECTORS                4096
+#define ARCMSR_MAX_TARGETID            17      /*16 max target id + 1*/
+#define ARCMSR_MAX_TARGETLUN           8       /*8*/
+#define ARCMSR_MAX_CHIPTYPE_NUM                4
+#define ARCMSR_MAX_OUTSTANDING_CMD     256
+#define ARCMSR_MAX_START_JOB           256
+#define ARCMSR_MAX_CMD_PERLUN          ARCMSR_MAX_OUTSTANDING_CMD
+#define ARCMSR_MAX_FREESRB_NUM         384
+#define ARCMSR_MAX_QBUFFER             4096    /* ioctl QBUFFER */
+#define ARCMSR_MAX_SG_ENTRIES          38      /* max 38*/
+#define ARCMSR_MAX_ADAPTER             4
+#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 */
 /*
 *********************************************************************
 */
 #ifndef offsetof
        #define offsetof(type, member)  ((size_t)(&((type *)0)->member))
 #endif
+
+#define ARCMSR_LOCK_INIT(l, s) lockinit(l, s, 0, LK_CANRECURSE)
+#define ARCMSR_LOCK_DESTROY(l) lockuninit(l)
+#define ARCMSR_LOCK_ACQUIRE(l) lockmgr(l, LK_EXCLUSIVE)
+#define ARCMSR_LOCK_RELEASE(l) lockmgr(l, LK_RELEASE)
+#define ARCMSR_LOCK_TRY(l)     lockmgr(&l, LK_EXCLUSIVE|LK_NOWAIT)
+#define arcmsr_htole32(x)      htole32(x)
+typedef struct lock            arcmsr_lock_t;
+
 /*
 **********************************************************************************
 **
 **********************************************************************************
 */
-#define PCI_VENDOR_ID_ARECA                                                0x17D3 /* Vendor ID */
-#define PCI_DEVICE_ID_ARECA_1110                                           0x1110 /* Device ID */
-#define PCI_DEVICE_ID_ARECA_1120                                           0x1120 /* Device ID */
-#define PCI_DEVICE_ID_ARECA_1130                                           0x1130 /* Device ID */
-#define PCI_DEVICE_ID_ARECA_1160                                           0x1160 /* Device ID */
-#define PCI_DEVICE_ID_ARECA_1170                                           0x1170 /* Device ID */
+#define PCI_VENDOR_ID_ARECA            0x17D3 /* Vendor ID     */
+#define PCI_DEVICE_ID_ARECA_1110        0x1110 /* Device ID    */
+#define PCI_DEVICE_ID_ARECA_1120        0x1120 /* Device ID    */
+#define PCI_DEVICE_ID_ARECA_1130        0x1130 /* Device ID    */
+#define PCI_DEVICE_ID_ARECA_1160        0x1160 /* Device ID    */
+#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_1210                                           0x1210 /* 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_1220                                           0x1220 /* Device ID */
+#define PCI_DEVICE_ID_ARECA_1214        0x1214 /* Device ID    */
+#define PCI_DEVICE_ID_ARECA_1220        0x1220 /* Device ID    */
 #define PCI_DEVICE_ID_ARECA_1222        0x1222 /* Device ID    */
-#define PCI_DEVICE_ID_ARECA_1230                                           0x1230 /* Device ID */
+#define PCI_DEVICE_ID_ARECA_1230        0x1230 /* Device ID    */
 #define PCI_DEVICE_ID_ARECA_1231        0x1231 /* Device ID    */
-#define PCI_DEVICE_ID_ARECA_1260                                           0x1260 /* Device ID */
+#define PCI_DEVICE_ID_ARECA_1260        0x1260 /* Device ID    */
 #define PCI_DEVICE_ID_ARECA_1261        0x1261 /* Device ID    */
-#define PCI_DEVICE_ID_ARECA_1270                                           0x1270 /* Device ID */
-#define PCI_DEVICE_ID_ARECA_1280                                           0x1280 /* Device ID */
-#define PCI_DEVICE_ID_ARECA_1380                                           0x1380 /* Device ID */
-#define PCI_DEVICE_ID_ARECA_1381                                           0x1381 /* Device ID */
-#define PCI_DEVICE_ID_ARECA_1680                                           0x1680 /* Device ID */
-#define PCI_DEVICE_ID_ARECA_1681                                           0x1681 /* Device ID */
+#define PCI_DEVICE_ID_ARECA_1270        0x1270 /* Device ID    */
+#define PCI_DEVICE_ID_ARECA_1280        0x1280 /* Device ID    */
+#define PCI_DEVICE_ID_ARECA_1380        0x1380 /* Device ID    */
+#define PCI_DEVICE_ID_ARECA_1381        0x1381 /* Device ID    */
+#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 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_1212  0x1212 /* Subsystem Device ID   */
 #define ARECA_SUB_DEV_ID_1213  0x1213 /* Subsystem Device ID   */
 #define ARECA_SUB_DEV_ID_1222  0x1222 /* Subsystem Device ID   */
 #define PCIDevVenIDARC1210              0x121017D3 /* Vendor Device ID */
 #define PCIDevVenIDARC1212              0x121217D3 /* Vendor Device ID */
 #define PCIDevVenIDARC1213              0x121317D3 /* Vendor Device ID */
+#define PCIDevVenIDARC1214              0x121417D3 /* Vendor Device ID */
 #define PCIDevVenIDARC1220              0x122017D3 /* Vendor Device ID */
 #define PCIDevVenIDARC1222              0x122217D3 /* Vendor Device ID */
 #define PCIDevVenIDARC1223              0x122317D3 /* Vendor Device ID */
        #define PCIR_BAR(x)     (PCIR_BARS + (x) * 4)
 #endif
 
-#define PCI_BASE_ADDR0                                               0x10
-#define PCI_BASE_ADDR1                                               0x14
-#define PCI_BASE_ADDR2                                               0x18
-#define PCI_BASE_ADDR3                                               0x1C
-#define PCI_BASE_ADDR4                                               0x20
-#define PCI_BASE_ADDR5                                               0x24
+#define PCI_BASE_ADDR0                  0x10
+#define PCI_BASE_ADDR1                  0x14
+#define PCI_BASE_ADDR2                  0x18
+#define PCI_BASE_ADDR3                  0x1C
+#define PCI_BASE_ADDR4                  0x20
+#define PCI_BASE_ADDR5                  0x24
 /*
 **********************************************************************************
 **
 **********************************************************************************
 */
-#define ARCMSR_SCSICMD_IOCTL                                         0x77
-#define ARCMSR_CDEVSW_IOCTL                                          0x88
-#define ARCMSR_MESSAGE_FAIL                                          0x0001
-#define        ARCMSR_MESSAGE_SUCCESS                                       0x0000
+#define ARCMSR_SCSICMD_IOCTL            0x77
+#define ARCMSR_CDEVSW_IOCTL             0x88
+#define ARCMSR_MESSAGE_FAIL             0x0001
+#define        ARCMSR_MESSAGE_SUCCESS          0x0000
 /*
 **********************************************************************************
 **
 **********************************************************************************
 */
-#define arcmsr_ccbsrb_ptr                                                                      spriv_ptr0
-#define arcmsr_ccbacb_ptr                                                                      spriv_ptr1
-#define dma_addr_hi32(addr)                                                                    (u_int32_t) ((addr>>16)>>16)
-#define dma_addr_lo32(addr)                                                                    (u_int32_t) (addr & 0xffffffff)
-#define get_min(x,y)            ((x) < (y) ? (x) : (y))
-#define get_max(x,y)            ((x) < (y) ? (y) : (x))
+#define arcmsr_ccbsrb_ptr      spriv_ptr0
+#define arcmsr_ccbacb_ptr      spriv_ptr1
+#define dma_addr_hi32(addr)    (u_int32_t) ((addr>>16)>>16)
+#define dma_addr_lo32(addr)    (u_int32_t) (addr & 0xffffffff)
+#define get_min(x,y)           ((x) < (y) ? (x) : (y))
+#define get_max(x,y)           ((x) < (y) ? (y) : (x))
+/*
+**************************************************************************
+**************************************************************************
+*/
+#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)
 /*
 **********************************************************************************
-**
+**    IOCTL CONTROL Mail Box
 **********************************************************************************
 */
 struct CMD_MESSAGE {
@@ -187,17 +203,17 @@ struct CMD_MESSAGE_FIELD {
 /************************************************************************/
 /************************************************************************/
 
-#define ARCMSR_IOP_ERROR_ILLEGALPCI                    0x0001
-#define ARCMSR_IOP_ERROR_VENDORID                      0x0002
-#define ARCMSR_IOP_ERROR_DEVICEID                      0x0002
-#define ARCMSR_IOP_ERROR_ILLEGALCDB            0x0003
-#define ARCMSR_IOP_ERROR_UNKNOW_CDBERR         0x0004
-#define ARCMSR_SYS_ERROR_MEMORY_ALLOCATE       0x0005
-#define ARCMSR_SYS_ERROR_MEMORY_CROSS4G        0x0006
-#define ARCMSR_SYS_ERROR_MEMORY_LACK           0x0007
-#define ARCMSR_SYS_ERROR_MEMORY_RANGE           0x0008
-#define ARCMSR_SYS_ERROR_DEVICE_BASE            0x0009
-#define ARCMSR_SYS_ERROR_PORT_VALIDATE          0x000A
+#define ARCMSR_IOP_ERROR_ILLEGALPCI            0x0001
+#define ARCMSR_IOP_ERROR_VENDORID              0x0002
+#define ARCMSR_IOP_ERROR_DEVICEID              0x0002
+#define ARCMSR_IOP_ERROR_ILLEGALCDB            0x0003
+#define ARCMSR_IOP_ERROR_UNKNOW_CDBERR         0x0004
+#define ARCMSR_SYS_ERROR_MEMORY_ALLOCATE       0x0005
+#define ARCMSR_SYS_ERROR_MEMORY_CROSS4G                0x0006
+#define ARCMSR_SYS_ERROR_MEMORY_LACK           0x0007
+#define ARCMSR_SYS_ERROR_MEMORY_RANGE          0x0008
+#define ARCMSR_SYS_ERROR_DEVICE_BASE           0x0009
+#define ARCMSR_SYS_ERROR_PORT_VALIDATE         0x000A
 
 /*DeviceType*/
 #define ARECA_SATA_RAID                        0x90000000
@@ -214,7 +230,7 @@ struct CMD_MESSAGE_FIELD {
 #define FUNCTION_FLUSH_ADAPTER_CACHE                   0x0809
 /*
 ************************************************************************
-**        IOCTL CONTROL CODE
+**      IOCTL CONTROL CODE
 ************************************************************************
 */
 /* ARECA IO CONTROL CODE*/
@@ -224,16 +240,50 @@ struct CMD_MESSAGE_FIELD {
 #define ARCMSR_MESSAGE_CLEAR_WQBUFFER                  _IOWR('F', FUNCTION_CLEAR_WQBUFFER, struct CMD_MESSAGE_FIELD)
 #define ARCMSR_MESSAGE_CLEAR_ALLQBUFFER                _IOWR('F', FUNCTION_CLEAR_ALLQBUFFER, struct CMD_MESSAGE_FIELD)
 #define ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F           _IOWR('F', FUNCTION_REQUEST_RETURNCODE_3F, struct CMD_MESSAGE_FIELD)
-#define ARCMSR_MESSAGE_SAY_HELLO                       _IOWR('F', FUNCTION_SAY_HELLO, struct CMD_MESSAGE_FIELD)
+#define ARCMSR_MESSAGE_SAY_HELLO                       _IOWR('F', FUNCTION_SAY_HELLO, struct CMD_MESSAGE_FIELD) 
 #define ARCMSR_MESSAGE_SAY_GOODBYE              _IOWR('F', FUNCTION_SAY_GOODBYE, struct CMD_MESSAGE_FIELD)
 #define ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE      _IOWR('F', FUNCTION_FLUSH_ADAPTER_CACHE, struct CMD_MESSAGE_FIELD)
 
 /* ARECA IOCTL ReturnCode */
-#define ARCMSR_MESSAGE_RETURNCODE_OK              0x00000001
-#define ARCMSR_MESSAGE_RETURNCODE_ERROR           0x00000006
-#define ARCMSR_MESSAGE_RETURNCODE_3F              0x0000003F
-#define ARCMSR_IOCTL_RETURNCODE_BUS_HANG_ON            0x00000088
-/*
+#define ARCMSR_MESSAGE_RETURNCODE_OK           0x00000001
+#define ARCMSR_MESSAGE_RETURNCODE_ERROR                0x00000006
+#define ARCMSR_MESSAGE_RETURNCODE_3F           0x0000003F
+#define ARCMSR_IOCTL_RETURNCODE_BUS_HANG_ON    0x00000088
+/* 
+************************************************************************
+**                SPEC. for Areca HBA adapter
+************************************************************************
+*/
+/* signature of set and get firmware config */
+#define ARCMSR_SIGNATURE_GET_CONFIG            0x87974060
+#define ARCMSR_SIGNATURE_SET_CONFIG            0x87974063
+/* message code of inbound message register */
+#define ARCMSR_INBOUND_MESG0_NOP               0x00000000
+#define ARCMSR_INBOUND_MESG0_GET_CONFIG                0x00000001
+#define ARCMSR_INBOUND_MESG0_SET_CONFIG                0x00000002
+#define ARCMSR_INBOUND_MESG0_ABORT_CMD         0x00000003
+#define ARCMSR_INBOUND_MESG0_STOP_BGRB         0x00000004
+#define ARCMSR_INBOUND_MESG0_FLUSH_CACHE       0x00000005
+#define ARCMSR_INBOUND_MESG0_START_BGRB                0x00000006
+#define ARCMSR_INBOUND_MESG0_CHK331PENDING     0x00000007
+#define ARCMSR_INBOUND_MESG0_SYNC_TIMER                0x00000008
+/* doorbell interrupt generator */
+#define ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK    0x00000001
+#define ARCMSR_INBOUND_DRIVER_DATA_READ_OK     0x00000002
+#define ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK   0x00000001
+#define ARCMSR_OUTBOUND_IOP331_DATA_READ_OK    0x00000002
+/* srb areca cdb flag */
+#define ARCMSR_SRBPOST_FLAG_SGL_BSIZE          0x80000000
+#define ARCMSR_SRBPOST_FLAG_IAM_BIOS           0x40000000
+#define ARCMSR_SRBREPLY_FLAG_IAM_BIOS          0x40000000
+#define ARCMSR_SRBREPLY_FLAG_ERROR             0x10000000
+#define ARCMSR_SRBREPLY_FLAG_ERROR_MODE0        0x10000000
+#define ARCMSR_SRBREPLY_FLAG_ERROR_MODE1       0x00000001
+/* outbound firmware ok */
+#define ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK      0x80000000
+
+#define ARCMSR_ARC1680_BUS_RESET               0x00000003
+/* 
 ************************************************************************
 **                SPEC. for Areca HBB adapter
 ************************************************************************
@@ -250,20 +300,20 @@ struct CMD_MESSAGE_FIELD {
 #define ARCMSR_IOP2DRV_CDB_DONE                 0x00000004
 #define ARCMSR_IOP2DRV_MESSAGE_CMD_DONE         0x00000008
 
-#define ARCMSR_DOORBELL_HANDLE_INT                     0x0000000F
+#define ARCMSR_DOORBELL_HANDLE_INT             0x0000000F
 #define ARCMSR_DOORBELL_INT_CLEAR_PATTERN       0xFF00FFF0
 #define ARCMSR_MESSAGE_INT_CLEAR_PATTERN        0xFF00FFF7
 
-#define ARCMSR_MESSAGE_GET_CONFIG                              0x00010008      /* (ARCMSR_INBOUND_MESG0_GET_CONFIG<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */
-#define ARCMSR_MESSAGE_SET_CONFIG                              0x00020008      /* (ARCMSR_INBOUND_MESG0_SET_CONFIG<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */
-#define ARCMSR_MESSAGE_ABORT_CMD                               0x00030008      /* (ARCMSR_INBOUND_MESG0_ABORT_CMD<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */
-#define ARCMSR_MESSAGE_STOP_BGRB                               0x00040008      /* (ARCMSR_INBOUND_MESG0_STOP_BGRB<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */
+#define ARCMSR_MESSAGE_GET_CONFIG              0x00010008      /* (ARCMSR_INBOUND_MESG0_GET_CONFIG<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */
+#define ARCMSR_MESSAGE_SET_CONFIG              0x00020008      /* (ARCMSR_INBOUND_MESG0_SET_CONFIG<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */
+#define ARCMSR_MESSAGE_ABORT_CMD               0x00030008      /* (ARCMSR_INBOUND_MESG0_ABORT_CMD<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */
+#define ARCMSR_MESSAGE_STOP_BGRB               0x00040008      /* (ARCMSR_INBOUND_MESG0_STOP_BGRB<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */
 #define ARCMSR_MESSAGE_FLUSH_CACHE              0x00050008     /* (ARCMSR_INBOUND_MESG0_FLUSH_CACHE<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */
-#define ARCMSR_MESSAGE_START_BGRB                              0x00060008      /* (ARCMSR_INBOUND_MESG0_START_BGRB<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */
-#define ARCMSR_MESSAGE_START_DRIVER_MODE               0x000E0008
-#define ARCMSR_MESSAGE_SET_POST_WINDOW             0x000F0008
-#define ARCMSR_MESSAGE_ACTIVE_EOI_MODE             0x00100008
-#define ARCMSR_MESSAGE_FIRMWARE_OK                             0x80000000      /* ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK */
+#define ARCMSR_MESSAGE_START_BGRB              0x00060008      /* (ARCMSR_INBOUND_MESG0_START_BGRB<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */
+#define ARCMSR_MESSAGE_START_DRIVER_MODE       0x000E0008      
+#define ARCMSR_MESSAGE_SET_POST_WINDOW         0x000F0008      
+#define ARCMSR_MESSAGE_ACTIVE_EOI_MODE         0x00100008
+#define ARCMSR_MESSAGE_FIRMWARE_OK             0x80000000      /* ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK */
 
 #define ARCMSR_DRV2IOP_DATA_WRITE_OK            0x00000001     /* ioctl transfer */
 #define ARCMSR_DRV2IOP_DATA_READ_OK             0x00000002     /* ioctl transfer */
@@ -272,14 +322,14 @@ struct CMD_MESSAGE_FIELD {
 #define ARCMSR_DRV2IOP_END_OF_INTERRUPT         0x00000010  /*  */
 
 /* data tunnel buffer between user space program and its firmware */
-#define ARCMSR_MSGCODE_RWBUFFER                                        0x0000fa00    /* iop msgcode_rwbuffer for message command */
-#define ARCMSR_IOCTL_WBUFFER                                   0x0000fe00    /* user space data to iop 128bytes */
-#define ARCMSR_IOCTL_RBUFFER                                   0x0000ff00    /* iop data to user space 128bytes */
-#define ARCMSR_HBB_BASE0_OFFSET                                        0x00000010
-#define ARCMSR_HBB_BASE1_OFFSET                                        0x00000018
-#define ARCMSR_HBB_BASE0_LEN                                   0x00021000
-#define ARCMSR_HBB_BASE1_LEN                                   0x00010000
-/*
+#define ARCMSR_MSGCODE_RWBUFFER                        0x0000fa00    /* iop msgcode_rwbuffer for message command */
+#define ARCMSR_IOCTL_WBUFFER                   0x0000fe00    /* user space data to iop 128bytes */
+#define ARCMSR_IOCTL_RBUFFER                   0x0000ff00    /* iop data to user space 128bytes */
+#define ARCMSR_HBB_BASE0_OFFSET                        0x00000010
+#define ARCMSR_HBB_BASE1_OFFSET                        0x00000018
+#define ARCMSR_HBB_BASE0_LEN                   0x00021000
+#define ARCMSR_HBB_BASE1_LEN                   0x00010000
+/* 
 ************************************************************************
 **                SPEC. for Areca HBC adapter
 ************************************************************************
@@ -294,7 +344,7 @@ struct CMD_MESSAGE_FIELD {
 /* Host Interrupt Status */
 #define ARCMSR_HBCMU_UTILITY_A_ISR                      0x00000001
         /*
-        ** Set when the Utility_A Interrupt bit is set in the Outbound Doorbell Register.
+        ** Set when the Utility_A Interrupt bit is set in the Outbound Doorbell Register. 
         ** It clears by writing a 1 to the Utility_A bit in the Outbound Doorbell Clear Register or through automatic clearing (if enabled).
         */
 #define ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR              0x00000004
@@ -326,14 +376,310 @@ struct CMD_MESSAGE_FIELD {
 #define ARCMSR_HBCMU_IOP2DRV_DATA_READ_DOORBELL_CLEAR           0x00000004/*outbound DATA READ isr door bell clear*/
 #define ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE                   0x00000008/*outbound message 0 ready*/
 #define ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR    0x00000008/*outbound message cmd isr door bell clear*/
-#define ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK                               0x80000000/*ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK*/
+#define ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK                       0x80000000/*ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK*/
+#define ARCMSR_HBCMU_RESET_ADAPTER                             0x00000024
+#define ARCMSR_HBCMU_DiagWrite_ENABLE                          0x00000080
+
+/* 
+************************************************************************
+**                SPEC. for Areca HBD adapter
+************************************************************************
+*/
+#define ARCMSR_HBDMU_CHIP_ID                           0x00004
+#define ARCMSR_HBDMU_CPU_MEMORY_CONFIGURATION          0x00008
+#define ARCMSR_HBDMU_I2_HOST_INTERRUPT_MASK            0x00034
+#define ARCMSR_HBDMU_MAIN_INTERRUPT_STATUS             0x00200
+#define ARCMSR_HBDMU_PCIE_F0_INTERRUPT_ENABLE          0x0020C
+#define ARCMSR_HBDMU_INBOUND_MESSAGE0                  0x00400
+#define ARCMSR_HBDMU_INBOUND_MESSAGE1                  0x00404
+#define ARCMSR_HBDMU_OUTBOUND_MESSAGE0                 0x00420
+#define ARCMSR_HBDMU_OUTBOUND_MESSAGE1                 0x00424
+#define ARCMSR_HBDMU_INBOUND_DOORBELL                  0x00460
+#define ARCMSR_HBDMU_OUTBOUND_DOORBELL                 0x00480
+#define ARCMSR_HBDMU_OUTBOUND_DOORBELL_ENABLE          0x00484
+#define ARCMSR_HBDMU_INBOUND_LIST_BASE_LOW             0x01000
+#define ARCMSR_HBDMU_INBOUND_LIST_BASE_HIGH            0x01004
+#define ARCMSR_HBDMU_INBOUND_LIST_WRITE_POINTER                0x01018
+#define ARCMSR_HBDMU_OUTBOUND_LIST_BASE_LOW            0x01060
+#define ARCMSR_HBDMU_OUTBOUND_LIST_BASE_HIGH           0x01064
+#define ARCMSR_HBDMU_OUTBOUND_LIST_COPY_POINTER                0x0106C
+#define ARCMSR_HBDMU_OUTBOUND_LIST_READ_POINTER                0x01070
+#define ARCMSR_HBDMU_OUTBOUND_INTERRUPT_CAUSE          0x01088
+#define ARCMSR_HBDMU_OUTBOUND_INTERRUPT_ENABLE         0x0108C
+
+#define ARCMSR_HBDMU_MESSAGE_WBUFFER                   0x02000
+#define ARCMSR_HBDMU_MESSAGE_RBUFFER                   0x02100
+#define ARCMSR_HBDMU_MESSAGE_RWBUFFER                  0x02200
+
+#define ARCMSR_HBDMU_ISR_THROTTLING_LEVEL              16
+#define ARCMSR_HBDMU_ISR_MAX_DONE_QUEUE                        20
+
+/* Host Interrupt Mask */
+#define ARCMSR_HBDMU_ALL_INT_ENABLE                    0x00001010      /* enable all ISR */
+#define ARCMSR_HBDMU_ALL_INT_DISABLE                   0x00000000      /* disable all ISR */
+
+/* Host Interrupt Status */
+#define ARCMSR_HBDMU_OUTBOUND_INT                      0x00001010
+#define ARCMSR_HBDMU_OUTBOUND_DOORBELL_INT             0x00001000
+#define ARCMSR_HBDMU_OUTBOUND_POSTQUEUE_INT            0x00000010
+
+/* DoorBell*/
+#define ARCMSR_HBDMU_DRV2IOP_DATA_IN_READY             0x00000001
+#define ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ             0x00000002
+
+#define ARCMSR_HBDMU_IOP2DRV_DATA_WRITE_OK             0x00000001
+#define ARCMSR_HBDMU_IOP2DRV_DATA_READ_OK              0x00000002
+
+/*outbound message 0 ready*/
+#define ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE          0x02000000
+
+#define ARCMSR_HBDMU_F0_DOORBELL_CAUSE                 0x02000003
+
+/*outbound message cmd isr door bell clear*/
+#define ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR    0x02000000
+
+/*outbound list */
+#define ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT           0x00000001
+#define ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT_CLEAR     0x00000001
+
+/*ARCMSR_HBAMU_MESSAGE_FIRMWARE_OK*/
+#define ARCMSR_HBDMU_MESSAGE_FIRMWARE_OK               0x80000000
+/*
+*********************************************************************
+** Message Unit structure
+*********************************************************************
+*/
+struct HBA_MessageUnit
+{
+       u_int32_t       resrved0[4];            /*0000 000F*/
+       u_int32_t       inbound_msgaddr0;       /*0010 0013*/
+       u_int32_t       inbound_msgaddr1;       /*0014 0017*/
+       u_int32_t       outbound_msgaddr0;      /*0018 001B*/
+       u_int32_t       outbound_msgaddr1;      /*001C 001F*/
+       u_int32_t       inbound_doorbell;       /*0020 0023*/
+       u_int32_t       inbound_intstatus;      /*0024 0027*/
+       u_int32_t       inbound_intmask;        /*0028 002B*/
+       u_int32_t       outbound_doorbell;      /*002C 002F*/
+       u_int32_t       outbound_intstatus;     /*0030 0033*/
+       u_int32_t       outbound_intmask;       /*0034 0037*/
+       u_int32_t       reserved1[2];           /*0038 003F*/
+       u_int32_t       inbound_queueport;      /*0040 0043*/
+       u_int32_t       outbound_queueport;     /*0044 0047*/
+       u_int32_t       reserved2[2];           /*0048 004F*/
+       u_int32_t       reserved3[492];         /*0050 07FF ......local_buffer 492*/
+       u_int32_t       reserved4[128];         /*0800 09FF                    128*/
+       u_int32_t       msgcode_rwbuffer[256];  /*0a00 0DFF                    256*/
+       u_int32_t       message_wbuffer[32];    /*0E00 0E7F                     32*/
+       u_int32_t       reserved5[32];          /*0E80 0EFF                     32*/
+       u_int32_t       message_rbuffer[32];    /*0F00 0F7F                     32*/
+       u_int32_t       reserved6[32];          /*0F80 0FFF                     32*/
+};
+/*
+*********************************************************************
+** 
+*********************************************************************
+*/
+struct HBB_DOORBELL
+{
+       u_int8_t        doorbell_reserved[ARCMSR_DRV2IOP_DOORBELL]; /*reserved */
+       u_int32_t       drv2iop_doorbell;          /*offset 0x00020400:00,01,02,03: window of "instruction flags" from driver to iop */
+       u_int32_t       drv2iop_doorbell_mask;     /*                  04,05,06,07: doorbell mask */
+       u_int32_t       iop2drv_doorbell;          /*                  08,09,10,11: window of "instruction flags" from iop to driver */
+       u_int32_t       iop2drv_doorbell_mask;     /*                  12,13,14,15: doorbell mask */
+};
+/*
+*********************************************************************
+** 
+*********************************************************************
+*/
+struct HBB_RWBUFFER
+{
+       u_int8_t        message_reserved0[ARCMSR_MSGCODE_RWBUFFER];   /*reserved */
+       u_int32_t       msgcode_rwbuffer[256];      /*offset 0x0000fa00:   0,   1,   2,   3,...,1023: message code read write 1024bytes */
+       u_int32_t       message_wbuffer[32];        /*offset 0x0000fe00:1024,1025,1026,1027,...,1151: user space data to iop 128bytes */
+       u_int32_t       message_reserved1[32];      /*                  1152,1153,1154,1155,...,1279: message reserved*/
+       u_int32_t       message_rbuffer[32];        /*offset 0x0000ff00:1280,1281,1282,1283,...,1407: iop data to user space 128bytes */ 
+};
+/*
+*********************************************************************
+** 
+*********************************************************************
+*/
+struct HBB_MessageUnit
+{
+       u_int32_t               post_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE];       /* post queue buffer for iop */
+       u_int32_t               done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE];       /* done queue buffer for iop */
+       int32_t                 postq_index;                                  /* post queue index */
+       int32_t                 doneq_index;                                                               /* done queue index */
+       struct HBB_DOORBELL    *hbb_doorbell;
+       struct HBB_RWBUFFER    *hbb_rwbuffer;
+};
 
 /*
+*********************************************************************
+** 
+*********************************************************************
+*/
+struct HBC_MessageUnit {
+       u_int32_t       message_unit_status;                        /*0000 0003*/
+       u_int32_t       slave_error_attribute;                      /*0004 0007*/
+       u_int32_t       slave_error_address;                        /*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 size of the PCIe window used for HCB_Mode accesses*/
+       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 inbound free list producer consumer index*/
+       u_int32_t       inbound_post_list_index;                    /*0064 0067 inbound post list producer consumer index*/
+       u_int32_t       outbound_free_list_index;                   /*0068 006B outbound free list producer consumer index*/
+       u_int32_t       outbound_post_list_index;                   /*006C 006F outbound post list producer consumer index*/
+       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 pull mode data byte count0..count7*/
+       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 message accelerator source address consumer producer index*/
+       u_int32_t       message_done_queue_index;                   /*00A8 00AB message accelerator completion queue consumer producer index*/
+       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 message accelerator destination queue port low*/
+       u_int32_t       message_dest_queue_port_high;               /*00E4 00E7 message accelerator destination queue port high*/
+       u_int32_t       last_used_message_dest_address_low;         /*00E8 00EB last used message accelerator destination address low*/
+       u_int32_t       last_used_message_dest_address_high;        /*00EC 00EF last used message accelerator destination address high*/
+       u_int32_t       message_done_queue_base_address_low;        /*00F0 00F3 message accelerator completion queue base address low*/
+       u_int32_t       message_done_queue_base_address_high;       /*00F4 00F7 message accelerator completion queue base address high*/
+       u_int32_t       host_diagnostic;                            /*00F8 00FB*/
+       u_int32_t       write_sequence;                             /*00FC 00FF*/
+       u_int32_t       reserved1[34];                              /*0100 0187*/
+       u_int32_t       reserved2[1950];                            /*0188 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*/
+};
+/*
+*********************************************************************
+** 
+*********************************************************************
+*/
+struct InBound_SRB {
+       uint32_t addressLow; //pointer to SRB block
+       uint32_t addressHigh;
+       uint32_t length; // in DWORDs
+       uint32_t reserved0;
+};
+
+struct OutBound_SRB {
+       uint32_t addressLow; //pointer to SRB block
+       uint32_t addressHigh;
+};
+
+struct HBD_MessageUnit {
+       uint32_t reserved0;
+       uint32_t chip_id;                       //0x0004
+       uint32_t cpu_mem_config;                //0x0008
+       uint32_t reserved1[10];                 //0x000C
+       uint32_t i2o_host_interrupt_mask;       //0x0034
+       uint32_t reserved2[114];                //0x0038
+       uint32_t host_int_status;               //0x0200
+       uint32_t host_int_enable;               //0x0204
+       uint32_t reserved3[1];                  //0x0208
+       uint32_t pcief0_int_enable;             //0x020C
+       uint32_t reserved4[124];                //0x0210
+       uint32_t inbound_msgaddr0;              //0x0400
+       uint32_t inbound_msgaddr1;              //0x0404
+       uint32_t reserved5[6];                  //0x0408
+       uint32_t outbound_msgaddr0;             //0x0420
+       uint32_t outbound_msgaddr1;             //0x0424
+       uint32_t reserved6[14];                 //0x0428
+       uint32_t inbound_doorbell;              //0x0460
+       uint32_t reserved7[7];                  //0x0464
+       uint32_t outbound_doorbell;             //0x0480
+       uint32_t outbound_doorbell_enable;      //0x0484
+       uint32_t reserved8[734];                //0x0488
+       uint32_t inboundlist_base_low;          //0x1000
+       uint32_t inboundlist_base_high;         //0x1004
+       uint32_t reserved9[4];                  //0x1008
+       uint32_t inboundlist_write_pointer;     //0x1018
+       uint32_t inboundlist_read_pointer;      //0x101C
+       uint32_t reserved10[16];                //0x1020
+       uint32_t outboundlist_base_low;         //0x1060
+       uint32_t outboundlist_base_high;        //0x1064
+       uint32_t reserved11;                    //0x1068
+       uint32_t outboundlist_copy_pointer;     //0x106C
+       uint32_t outboundlist_read_pointer;     //0x1070 0x1072
+       uint32_t reserved12[5];                 //0x1074
+       uint32_t outboundlist_interrupt_cause;  //0x1088
+       uint32_t outboundlist_interrupt_enable; //0x108C
+       uint32_t reserved13[988];               //0x1090
+       uint32_t message_wbuffer[32];           //0x2000
+       uint32_t reserved14[32];                //0x2080
+       uint32_t message_rbuffer[32];           //0x2100
+       uint32_t reserved15[32];                //0x2180
+       uint32_t msgcode_rwbuffer[256];         //0x2200
+};
+
+struct HBD_MessageUnit0 {
+       struct InBound_SRB post_qbuffer[ARCMSR_MAX_HBD_POSTQUEUE];
+       struct OutBound_SRB done_qbuffer[ARCMSR_MAX_HBD_POSTQUEUE+1];
+       uint16_t postq_index;
+       uint16_t doneq_index;
+       struct HBD_MessageUnit  *phbdmu;
+};
+
+/*
+*********************************************************************
+** 
+*********************************************************************
+*/
+struct MessageUnit_UNION
+{
+       union   {
+               struct HBA_MessageUnit          hbamu;
+               struct HBB_MessageUnit          hbbmu;
+               struct HBC_MessageUnit          hbcmu;
+               struct HBD_MessageUnit0         hbdmu;
+       } muu;
+};
+/* 
 *************************************************************
-**   structure for holding DMA address data
+**   structure for holding DMA address data 
 *************************************************************
 */
-#define IS_SG64_ADDR                0x01000000 /* bit24 */
+#define IS_SG64_ADDR   0x01000000 /* bit24 */
 /*
 ************************************************************************************************
 **                            ARECA FIRMWARE SPEC
@@ -342,10 +688,10 @@ struct CMD_MESSAGE_FIELD {
 **             (All In/Out is in IOP331's view)
 **             1. Message 0 --> InitThread message and retrun code
 **             2. Doorbell is used for RS-232 emulation
-**                             inDoorBell :    bit0 -- data in ready            (DRIVER DATA WRITE OK)
-**                                                             bit1 -- data out has been read   (DRIVER DATA READ OK)
-**                             outDooeBell:    bit0 -- data out ready           (IOP331 DATA WRITE OK)
-**                                                             bit1 -- data in has been read    (IOP331 DATA READ OK)
+**                     inDoorBell :    bit0 -- data in ready            (DRIVER DATA WRITE OK)
+**                                     bit1 -- data out has been read   (DRIVER DATA READ OK)
+**                     outDooeBell:    bit0 -- data out ready           (IOP331 DATA WRITE OK)
+**                                     bit1 -- data in has been read    (IOP331 DATA READ OK)
 **             3. Index Memory Usage
 **                     offset 0xf00 : for RS232 out (request buffer)
 **                     offset 0xe00 : for RS232 in  (scratch buffer)
@@ -357,74 +703,74 @@ struct CMD_MESSAGE_FIELD {
 **                             Byte 4--127 : Max 124 bytes of data
 **             5. PostQ
 **             All SCSI Command must be sent through postQ:
-**             (inbound queue port)    Request frame must be 32 bytes aligned
-**            #   bit27--bit31 => flag for post ccb
-**                       #   bit0--bit26 => real address (bit27--bit31) of post arcmsr_cdb
-**                                                                                                     bit31 : 0 : 256 bytes frame
-**                                                                                                                     1 : 512 bytes frame
-**                                                                                                     bit30 : 0 : normal request
-**                                                                                                                     1 : BIOS request
-**                                                  bit29 : reserved
-**                                                  bit28 : reserved
-**                                                  bit27 : reserved
+**             (inbound queue port)    Request frame must be 32 bytes aligned 
+**                     #   bit27--bit31 => flag for post ccb 
+**                     #   bit0--bit26 => real address (bit27--bit31) of post arcmsr_cdb  
+**                                     bit31 : 0 : 256 bytes frame
+**                                             1 : 512 bytes frame
+**                                     bit30 : 0 : normal request
+**                                             1 : BIOS request
+**                                      bit29 : reserved
+**                                      bit28 : reserved
+**                                      bit27 : reserved
 **  -------------------------------------------------------------------------------
-**             (outbount queue port)   Request reply
-**            #   bit27--bit31 => flag for reply
-**                       #   bit0--bit26 => real address (bit27--bit31) of reply arcmsr_cdb
-**                                                                                                     bit31 : must be 0 (for this type of reply)
-**                                                                                                     bit30 : reserved for BIOS handshake
-**                                                                                                     bit29 : reserved
-**                                                                                                     bit28 : 0 : no error, ignore AdapStatus/DevStatus/SenseData
-**                                                                                                                     1 : Error, error code in AdapStatus/DevStatus/SenseData
-**                                                                                                     bit27 : reserved
+**             (outbount queue port)   Request reply                          
+**                     #   bit27--bit31 => flag for reply
+**                     #   bit0--bit26 => real address (bit27--bit31) of reply arcmsr_cdb 
+**                     bit31 : must be 0 (for this type of reply)
+**                     bit30 : reserved for BIOS handshake
+**                     bit29 : reserved
+**                     bit28 : 0 : no error, ignore AdapStatus/DevStatus/SenseData
+**                             1 : Error, error code in AdapStatus/DevStatus/SenseData
+**                     bit27 : reserved
 **             6. BIOS request
 **                     All BIOS request is the same with request from PostQ
 **                     Except :
 **                             Request frame is sent from configuration space
-**                                                             offset: 0x78 : Request Frame (bit30 == 1)
-**                                                             offset: 0x18 : writeonly to generate IRQ to IOP331
+**                                     offset: 0x78 : Request Frame (bit30 == 1)
+**                                     offset: 0x18 : writeonly to generate IRQ to IOP331
 **                             Completion of request:
-**                                                   (bit30 == 0, bit28==err flag)
+**                                     (bit30 == 0, bit28==err flag)
 **             7. Definition of SGL entry (structure)
 **             8. Message1 Out - Diag Status Code (????)
 **             9. Message0 message code :
 **                     0x00 : NOP
 **                     0x01 : Get Config ->offset 0xa00 :for outbound message code msgcode_rwbuffer (IOP331 send to driver)
-**                                                                                             Signature             0x87974060(4)
-**                                                                                             Request len           0x00000200(4)
-**                                                                                             numbers of queue      0x00000100(4)
-**                                                                                             SDRAM Size            0x00000100(4)-->256 MB
-**                                                                                             IDE Channels          0x00000008(4)
-**                                                                                             vendor                40 bytes char
-**                                                                                             model                  8 bytes char
-**                                                                                             FirmVer               16 bytes char
-**                                                                                             Device Map            16 bytes char
-**
+**                                     Signature             0x87974060(4)
+**                                     Request len           0x00000200(4)
+**                                     numbers of queue      0x00000100(4)
+**                                     SDRAM Size            0x00000100(4)-->256 MB
+**                                     IDE Channels          0x00000008(4)
+**                                     vendor                40 bytes char
+**                                     model                  8 bytes char
+**                                     FirmVer               16 bytes char
+**                                     Device Map            16 bytes char
+**     
 **                                     FirmwareVersion DWORD <== Added for checking of new firmware capability
 **                     0x02 : Set Config ->offset 0xa00 : for inbound message code msgcode_rwbuffer (driver send to IOP331)
-**                                                                                             Signature             0x87974063(4)
-**                                                                                             UPPER32 of Request Frame  (4)-->Driver Only
+**                                     Signature             0x87974063(4)
+**                                     UPPER32 of Request Frame  (4)-->Driver Only
 **                     0x03 : Reset (Abort all queued Command)
 **                     0x04 : Stop Background Activity
 **                     0x05 : Flush Cache
 **                     0x06 : Start Background Activity (re-start if background is halted)
 **                     0x07 : Check If Host Command Pending (Novell May Need This Function)
 **                     0x08 : Set controller time ->offset 0xa00 : for inbound message code msgcode_rwbuffer (driver to IOP331)
-**                                                                                     byte 0 : 0xaa <-- signature
-**                                                                                     byte 1 : 0x55 <-- signature
-**                                                                                     byte 2 : year (04)
-**                                                                                     byte 3 : month (1..12)
-**                                                                                     byte 4 : date (1..31)
-**                                                                                     byte 5 : hour (0..23)
-**                                                                                     byte 6 : minute (0..59)
-**                                                                                     byte 7 : second (0..59)
+**                                     byte 0 : 0xaa <-- signature
+**                                     byte 1 : 0x55 <-- signature
+**                                     byte 2 : year (04)
+**                                     byte 3 : month (1..12)
+**                                     byte 4 : date (1..31)
+**                                     byte 5 : hour (0..23)
+**                                     byte 6 : minute (0..59)
+**                                     byte 7 : second (0..59)
 **      *********************************************************************************
 **      Porting Of LSI2108/2116 Based PCIE SAS/6G host raid adapter
 **      ==> Difference from IOP348
 **      <1> Message Register 0,1 (the same usage) Init Thread message and retrun code
 **           Inbound Message 0  (inbound_msgaddr0) : at offset 0xB0 (Scratchpad0) for inbound message code msgcode_rwbuffer (driver send to IOP)
-**           Inbound Message 1  (inbound_msgaddr1) : at offset 0xB4 (Scratchpad1) Out.... Diag Status Code
-**           Outbound Message 0 (outbound_msgaddr0): at offset 0xB8 (Scratchpad3) Out.... Diag Status Code
+**           Inbound Message 1  (inbound_msgaddr1) : at offset 0xB4 (Scratchpad1) Out.... Diag Status Code 
+**           Outbound Message 0 (outbound_msgaddr0): at offset 0xB8 (Scratchpad3) Out.... Diag Status Code 
 **           Outbound Message 1 (outbound_msgaddr1): at offset 0xBC (Scratchpad2) for outbound message code msgcode_rwbuffer (IOP send to driver)
 **           <A> use doorbell to generate interrupt
 **
@@ -433,36 +779,36 @@ struct CMD_MESSAGE_FIELD {
 **
 **                     a. Message1: Out - Diag Status Code (????)
 **
-**                     b. Message0: message code
+**                     b. Message0: message code 
 **                                 0x00 : NOP
 **                                 0x01 : Get Config ->offset 0xB8 :for outbound message code msgcode_rwbuffer (IOP send to driver)
-**                                                                                                     Signature             0x87974060(4)
-**                                                                                                     Request len           0x00000200(4)
-**                                                                                                     numbers of queue      0x00000100(4)
-**                                                                                                     SDRAM Size            0x00000100(4)-->256 MB
-**                                                                                                     IDE Channels          0x00000008(4)
-**                                                                                                     vendor                40 bytes char
-**                                                                                                     model                  8 bytes char
-**                                                                                                     FirmVer               16 bytes char
-**                                                                             Device Map            16 bytes char
-**                                                             cfgVersion    ULONG <== Added for checking of new firmware capability
+**                                                     Signature             0x87974060(4)
+**                                                     Request len           0x00000200(4)
+**                                                     numbers of queue      0x00000100(4)
+**                                                     SDRAM Size            0x00000100(4)-->256 MB
+**                                                     IDE Channels          0x00000008(4)
+**                                                     vendor                40 bytes char
+**                                                     model                  8 bytes char
+**                                                     FirmVer               16 bytes char
+**                                         Device Map            16 bytes char
+**                                         cfgVersion    ULONG <== Added for checking of new firmware capability
 **                                 0x02 : Set Config ->offset 0xB0 :for inbound message code msgcode_rwbuffer (driver send to IOP)
-**                                                                                                     Signature             0x87974063(4)
-**                                                                                                     UPPER32 of Request Frame  (4)-->Driver Only
+**                                                     Signature             0x87974063(4)
+**                                                     UPPER32 of Request Frame  (4)-->Driver Only
 **                                 0x03 : Reset (Abort all queued Command)
 **                                 0x04 : Stop Background Activity
 **                                 0x05 : Flush Cache
 **                                 0x06 : Start Background Activity (re-start if background is halted)
 **                                 0x07 : Check If Host Command Pending (Novell May Need This Function)
 **                                 0x08 : Set controller time ->offset 0xB0 : for inbound message code msgcode_rwbuffer (driver to IOP)
-**                                                                                             byte 0 : 0xaa <-- signature
-**                                                                             byte 1 : 0x55 <-- signature
-**                                                                                             byte 2 : year (04)
-**                                                                                             byte 3 : month (1..12)
-**                                                                                             byte 4 : date (1..31)
-**                                                                                             byte 5 : hour (0..23)
-**                                                                                             byte 6 : minute (0..59)
-**                                                                                             byte 7 : second (0..59)
+**                                                     byte 0 : 0xaa <-- signature
+**                                                     byte 1 : 0x55 <-- signature
+**                                                     byte 2 : year (04)
+**                                                     byte 3 : month (1..12)
+**                                                     byte 4 : date (1..31)
+**                                                     byte 5 : hour (0..23)
+**                                                     byte 6 : minute (0..59)
+**                                                     byte 7 : second (0..59)
 **
 **      <2> Doorbell Register is used for RS-232 emulation
 **           <A> different clear register
@@ -527,13 +873,13 @@ struct CMD_MESSAGE_FIELD {
 **                      111: <= 0x0300 (reserved)
 **                  -----------------------------
 **                  if len > 0x300 the len always set as 0x300
-**                  -----------------------------
+**                  -----------------------------   
 **                  post addr = addr | ((len-1) >> 6) | 1
 **                  -----------------------------
-**                  page length in command buffer still required,
+**                  page length in command buffer still required, 
 **
-**                  if page length > 3,
-**                     firmware will assume more request data need to be retrieved
+**                  if page length > 3, 
+**                     firmware will assume more request data need to be retrieved 
 **
 **              <D> Outbound Posting
 **                  bit0:0 , no error, 1 with error, refer to status buffer
@@ -542,42 +888,12 @@ struct CMD_MESSAGE_FIELD {
 **                  bit3:0 , reserved (will be 0)
 **                  bit63-4: Completed command address
 **
-**              <E> BIOS support, no special support is required.
+**              <E> BIOS support, no special support is required. 
 **                  LSI2108 support I/O register
 **                  All driver functionality is supported through I/O address
 **
-**           For further spec, refer to
-**       \spec\lsi\2108 for Areca\2108\LSISAS2108_PG_NoEncryption.pdf : Chapter 8 (8-11/8-28)
-**       \spec\lsi\2108 for Areca\2108\SAS2108_RM_20.pdf              : for configuration space
 ************************************************************************************************
 */
-/* signature of set and get firmware config */
-#define ARCMSR_SIGNATURE_GET_CONFIG                   0x87974060
-#define ARCMSR_SIGNATURE_SET_CONFIG                   0x87974063
-/* message code of inbound message register */
-#define ARCMSR_INBOUND_MESG0_NOP                      0x00000000
-#define ARCMSR_INBOUND_MESG0_GET_CONFIG               0x00000001
-#define ARCMSR_INBOUND_MESG0_SET_CONFIG               0x00000002
-#define ARCMSR_INBOUND_MESG0_ABORT_CMD                0x00000003
-#define ARCMSR_INBOUND_MESG0_STOP_BGRB                0x00000004
-#define ARCMSR_INBOUND_MESG0_FLUSH_CACHE              0x00000005
-#define ARCMSR_INBOUND_MESG0_START_BGRB               0x00000006
-#define ARCMSR_INBOUND_MESG0_CHK331PENDING            0x00000007
-#define ARCMSR_INBOUND_MESG0_SYNC_TIMER               0x00000008
-/* doorbell interrupt generator */
-#define ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK           0x00000001
-#define ARCMSR_INBOUND_DRIVER_DATA_READ_OK            0x00000002
-#define ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK          0x00000001
-#define ARCMSR_OUTBOUND_IOP331_DATA_READ_OK           0x00000002
-/* srb areca cdb flag */
-#define ARCMSR_SRBPOST_FLAG_SGL_BSIZE                 0x80000000
-#define ARCMSR_SRBPOST_FLAG_IAM_BIOS                  0x40000000
-#define ARCMSR_SRBREPLY_FLAG_IAM_BIOS                 0x40000000
-#define ARCMSR_SRBREPLY_FLAG_ERROR                    0x10000000
-#define ARCMSR_SRBREPLY_FLAG_ERROR_MODE0               0x10000000
-#define ARCMSR_SRBREPLY_FLAG_ERROR_MODE1                       0x00000001
-/* outbound firmware ok */
-#define ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK             0x80000000
 /*
 **********************************
 **
@@ -585,21 +901,21 @@ struct CMD_MESSAGE_FIELD {
 */
 /* size 8 bytes */
 /* 32bit Scatter-Gather list */
-struct SG32ENTRY {                             /* length bit 24 == 0                      */
-    u_int32_t                                          length;    /* high 8 bit == flag,low 24 bit == length */
-    u_int32_t                                          address;
+struct SG32ENTRY {                 /* length bit 24 == 0 */
+       u_int32_t       length;    /* high 8 bit == flag,low 24 bit == length */
+       u_int32_t       address;
 };
 /* size 12 bytes */
 /* 64bit Scatter-Gather list */
-struct SG64ENTRY {                             /* length bit 24 == 1                      */
-       u_int32_t                                       length;    /* high 8 bit == flag,low 24 bit == length */
-       u_int32_t                                       address;
-       u_int32_t                                       addresshigh;
+struct SG64ENTRY {                 /* length bit 24 == 1 */
+       u_int32_t       length;    /* high 8 bit == flag,low 24 bit == length */
+       u_int32_t       address; 
+       u_int32_t       addresshigh;
 };
 struct SGENTRY_UNION {
        union {
-               struct SG32ENTRY            sg32entry;   /* 30h   Scatter gather address  */
-               struct SG64ENTRY            sg64entry;   /* 30h                           */
+               struct SG32ENTRY        sg32entry;   /* 30h   Scatter gather address  */
+               struct SG64ENTRY        sg64entry;   /* 30h */
        }u;
 };
 /*
@@ -609,9 +925,16 @@ struct SGENTRY_UNION {
 */
 struct QBUFFER {
        u_int32_t     data_len;
-    u_int8_t      data[124];
+       u_int8_t      data[124];
 };
 /*
+**********************************
+*/
+typedef struct PHYS_ADDR64 {
+       u_int32_t       phyadd_low;
+       u_int32_t       phyadd_high;
+}PHYSADDR64;
+/*
 ************************************************************************************************
 **      FIRMWARE INFO
 ************************************************************************************************
@@ -622,23 +945,23 @@ struct QBUFFER {
 #define        ARCMSR_FW_CFGVER_OFFSET         25
 
 struct FIRMWARE_INFO {
-       u_int32_t      signature;                /*0,00-03*/
-       u_int32_t      request_len;              /*1,04-07*/
-       u_int32_t      numbers_queue;            /*2,08-11*/
-       u_int32_t      sdram_size;               /*3,12-15*/
-       u_int32_t      ide_channels;             /*4,16-19*/
-       char           vendor[40];               /*5,20-59*/
-       char           model[8];                 /*15,60-67*/
-       char           firmware_ver[16];         /*17,68-83*/
-       char           device_map[16];           /*21,84-99*/
-    u_int32_t      cfgVersion;          /*25,100-103 Added for checking of new firmware capability*/
-    char           cfgSerial[16];       /*26,104-119*/
-    u_int32_t      cfgPicStatus;        /*30,120-123*/
+       u_int32_t      signature;           /*0,00-03*/
+       u_int32_t      request_len;         /*1,04-07*/
+       u_int32_t      numbers_queue;       /*2,08-11*/
+       u_int32_t      sdram_size;          /*3,12-15*/
+       u_int32_t      ide_channels;        /*4,16-19*/
+       char           vendor[40];          /*5,20-59*/
+       char           model[8];            /*15,60-67*/
+       char           firmware_ver[16];    /*17,68-83*/
+       char           device_map[16];      /*21,84-99*/
+       u_int32_t      cfgVersion;          /*25,100-103 Added for checking of new firmware capability*/
+       char           cfgSerial[16];       /*26,104-119*/
+       u_int32_t      cfgPicStatus;        /*30,120-123*/
 };
 /*   (A) For cfgVersion in FIRMWARE_INFO
 **        if low BYTE (byte#0) >= 3 (version 3)
 **        then byte#1 report the capability of the firmware can xfer in a single request
-**
+**        
 **        byte#1
 **        0         256K
 **        1         512K
@@ -668,33 +991,43 @@ struct FIRMWARE_INFO {
 ************************************************************************************************
 */
 struct ARCMSR_CDB {
-       u_int8_t                                                Bus;              /* 00h   should be 0            */
-       u_int8_t                                                TargetID;         /* 01h   should be 0--15        */
-       u_int8_t                                                LUN;              /* 02h   should be 0--7         */
-       u_int8_t                                                Function;         /* 03h   should be 1            */
-
-       u_int8_t                                                CdbLength;        /* 04h   not used now           */
-       u_int8_t                                                sgcount;          /* 05h                          */
-       u_int8_t                                                Flags;            /* 06h                          */
-#define ARCMSR_CDB_FLAG_SGL_BSIZE          0x01   /* bit 0: 0(256) / 1(512) bytes         */
-#define ARCMSR_CDB_FLAG_BIOS               0x02   /* bit 1: 0(from driver) / 1(from BIOS) */
-#define ARCMSR_CDB_FLAG_WRITE              0x04          /* bit 2: 0(Data in) / 1(Data out)      */
-#define ARCMSR_CDB_FLAG_SIMPLEQ            0x00          /* bit 4/3 ,00 : simple Q,01 : head of Q,10 : ordered Q */
-#define ARCMSR_CDB_FLAG_HEADQ              0x08
-#define ARCMSR_CDB_FLAG_ORDEREDQ           0x10
+       u_int8_t        Bus;              /* 00h   should be 0            */
+       u_int8_t        TargetID;         /* 01h   should be 0--15        */
+       u_int8_t        LUN;              /* 02h   should be 0--7         */
+       u_int8_t        Function;         /* 03h   should be 1            */
+       
+       u_int8_t        CdbLength;        /* 04h   not used now           */
+       u_int8_t        sgcount;          /* 05h                          */
+       u_int8_t        Flags;            /* 06h                          */
        u_int8_t        msgPages;         /* 07h                          */
-
-       u_int32_t                                               Context;          /* 08h   Address of this request */
-       u_int32_t                                               DataLength;       /* 0ch   not used now            */
-
-       u_int8_t                                                Cdb[16];          /* 10h   SCSI CDB                */
+       
+       u_int32_t       Context;          /* 08h   Address of this request */
+       u_int32_t       DataLength;       /* 0ch   not used now           */
+       
+       u_int8_t        Cdb[16];          /* 10h   SCSI CDB               */
        /*
        ********************************************************
-       **Device Status : the same from SCSI bus if error occur
+       ** Device Status : the same from SCSI bus if error occur 
        ** SCSI bus status codes.
        ********************************************************
        */
-       u_int8_t                                                DeviceStatus;     /* 20h   if error                */
+       u_int8_t        DeviceStatus;     /* 20h   if error                */
+       
+       u_int8_t        SenseData[15];    /* 21h   output                  */        
+       
+       union {
+               struct SG32ENTRY        sg32entry[ARCMSR_MAX_SG_ENTRIES];        /* 30h   Scatter gather address  */
+               struct SG64ENTRY        sg64entry[ARCMSR_MAX_SG_ENTRIES];        /* 30h                           */
+       } u;
+};
+/* CDB flag */
+#define ARCMSR_CDB_FLAG_SGL_BSIZE              0x01    /* bit 0: 0(256) / 1(512) bytes         */
+#define ARCMSR_CDB_FLAG_BIOS                   0x02    /* bit 1: 0(from driver) / 1(from BIOS) */
+#define ARCMSR_CDB_FLAG_WRITE                  0x04    /* bit 2: 0(Data in) / 1(Data out)      */
+#define ARCMSR_CDB_FLAG_SIMPLEQ                        0x00    /* bit 4/3 ,00 : simple Q,01 : head of Q,10 : ordered Q */
+#define ARCMSR_CDB_FLAG_HEADQ                  0x08
+#define ARCMSR_CDB_FLAG_ORDEREDQ               0x10
+/* scsi status */
 #define SCSISTAT_GOOD                                  0x00
 #define SCSISTAT_CHECK_CONDITION                       0x02
 #define SCSISTAT_CONDITION_MET                         0x04
@@ -704,17 +1037,10 @@ struct ARCMSR_CDB {
 #define SCSISTAT_RESERVATION_CONFLICT                  0x18
 #define SCSISTAT_COMMAND_TERMINATED                    0x22
 #define SCSISTAT_QUEUE_FULL                            0x28
-#define ARCMSR_DEV_SELECT_TIMEOUT               0xF0
-#define ARCMSR_DEV_ABORTED                      0xF1
-#define ARCMSR_DEV_INIT_FAIL                    0xF2
-
-       u_int8_t                                                SenseData[15];    /* 21h   output                  */
-
-       union {
-               struct SG32ENTRY                sg32entry[ARCMSR_MAX_SG_ENTRIES];        /* 30h   Scatter gather address  */
-               struct SG64ENTRY                sg64entry[ARCMSR_MAX_SG_ENTRIES];        /* 30h                           */
-       } u;
-};
+/* DeviceStatus */
+#define ARCMSR_DEV_SELECT_TIMEOUT              0xF0
+#define ARCMSR_DEV_ABORTED                     0xF1
+#define ARCMSR_DEV_INIT_FAIL                   0xF2
 /*
 *********************************************************************
 **                   Command Control Block (SrbExtension)
@@ -724,351 +1050,196 @@ struct ARCMSR_CDB {
 *********************************************************************
 */
 struct CommandControlBlock {
-       struct ARCMSR_CDB                       arcmsr_cdb;                             /* 0  -503 (size of CDB=504): arcmsr messenger scsi command descriptor size 504 bytes */
-       u_int32_t                                       cdb_shifted_phyaddr;     /* 504-507 */
-       u_int32_t                                       arc_cdb_size;                   /* 508-511 */
+       struct ARCMSR_CDB       arcmsr_cdb;             /* 0  -503 (size of CDB=504): arcmsr messenger scsi command descriptor size 504 bytes */
+       u_int32_t               cdb_phyaddr_low;        /* 504-507 */
+       u_int32_t               arc_cdb_size;           /* 508-511 */
        /*  ======================512+32 bytes============================  */
-       union ccb                                       *pccb;                                  /* 512-515 516-519 pointer of freebsd scsi command */
-       struct AdapterControlBlock      *acb;                                   /* 520-523 524-527 */
-               bus_dmamap_t                            dm_segs_dmamap;          /* 528-531 532-535 */
-               u_int16_t                               srb_flags;               /* 536-537 */
-       u_int16_t                                       srb_state;                /* 538-539 */
-       struct  callout                         ccb_callout;
+       union ccb               *pccb;                  /* 512-515 516-519 pointer of freebsd scsi command */
+       struct AdapterControlBlock      *acb;           /* 520-523 524-527 */
+       bus_dmamap_t            dm_segs_dmamap;         /* 528-531 532-535 */
+       u_int16_t               srb_flags;              /* 536-537 */
+       u_int16_t               srb_state;              /* 538-539 */
+       u_int32_t               cdb_phyaddr_high;       /* 540-543 */
+       struct  callout         ccb_callout;
     /*  ==========================================================  */
 };
 /*     srb_flags */
-#define                SRB_FLAG_READ                           0x0000
-#define                SRB_FLAG_WRITE                          0x0001
-#define                SRB_FLAG_ERROR                          0x0002
-#define                SRB_FLAG_FLUSHCACHE                     0x0004
+#define                SRB_FLAG_READ                   0x0000
+#define                SRB_FLAG_WRITE                  0x0001
+#define                SRB_FLAG_ERROR                  0x0002
+#define                SRB_FLAG_FLUSHCACHE             0x0004
 #define                SRB_FLAG_MASTER_ABORTED         0x0008
-#define                SRB_FLAG_DMAVALID                       0x0010
+#define                SRB_FLAG_DMAVALID               0x0010
 #define                SRB_FLAG_DMACONSISTENT          0x0020
-#define                SRB_FLAG_DMAWRITE                       0x0040
-#define                SRB_FLAG_PKTBIND                        0x0080
+#define                SRB_FLAG_DMAWRITE               0x0040
+#define                SRB_FLAG_PKTBIND                0x0080
 #define                SRB_FLAG_TIMER_START            0x0080
 /*     srb_state */
-#define                ARCMSR_SRB_DONE                         0x0000
-#define                ARCMSR_SRB_UNBUILD                      0x0000
-#define                ARCMSR_SRB_TIMEOUT                      0x1111
-#define                ARCMSR_SRB_RETRY                        0x2222
-#define                ARCMSR_SRB_START                        0x55AA
-#define                ARCMSR_SRB_PENDING                      0xAA55
-#define                ARCMSR_SRB_RESET                        0xA5A5
-#define                ARCMSR_SRB_ABORTED                      0x5A5A
-#define                ARCMSR_SRB_ILLEGAL                      0xFFFF
+#define                ARCMSR_SRB_DONE                 0x0000
+#define                ARCMSR_SRB_UNBUILD              0x0000
+#define                ARCMSR_SRB_TIMEOUT              0x1111
+#define                ARCMSR_SRB_RETRY                0x2222
+#define                ARCMSR_SRB_START                0x55AA
+#define                ARCMSR_SRB_PENDING              0xAA55
+#define                ARCMSR_SRB_RESET                0xA5A5
+#define                ARCMSR_SRB_ABORTED              0x5A5A
+#define                ARCMSR_SRB_ILLEGAL              0xFFFF
+
+#define                SRB_SIZE        ((sizeof(struct CommandControlBlock)+0x1f) & 0xffe0)
+#define        ARCMSR_SRBS_POOL_SIZE   (SRB_SIZE * ARCMSR_MAX_FREESRB_NUM)
+
 /*
 *********************************************************************
 **                 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 A IOP */
+#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 */
 
 struct AdapterControlBlock {
-       u_int32_t                                       adapter_type;               /* adapter A,B..... */
-
-       bus_space_tag_t                                 btag[2];
-       bus_space_handle_t                              bhandle[2];
-       bus_dma_tag_t                                   parent_dmat;
-       bus_dma_tag_t                                   dm_segs_dmat;                         /* dmat for buffer I/O */
-       bus_dma_tag_t                                   srb_dmat;                             /* dmat for freesrb */
-       bus_dmamap_t                                    srb_dmamap;
-       device_t                                        pci_dev;
-       struct cdev                                     *ioctl_dev;
-       int                                             pci_unit;
-
-       struct resource                         *sys_res_arcmsr[2];
-       struct resource                         *irqres;
-       void                                            *ih;                         /* interrupt handle */
-       int                                             irq_type;
-
+       u_int32_t               adapter_type;           /* adapter A,B..... */
+       
+       bus_space_tag_t         btag[2];
+       bus_space_handle_t      bhandle[2];
+       bus_dma_tag_t           parent_dmat;
+       bus_dma_tag_t           dm_segs_dmat;           /* dmat for buffer I/O */  
+       bus_dma_tag_t           srb_dmat;               /* dmat for freesrb */
+       bus_dmamap_t            srb_dmamap;
+       device_t                pci_dev;
+       struct cdev             *ioctl_dev;
+       int                     pci_unit;
+       
+       struct resource         *sys_res_arcmsr[2];
+       struct resource         *irqres;
+       void                    *ih;                    /* interrupt handle */
+       int                     irq_type;
+       
        /* Hooks into the CAM XPT */
-       struct                                          cam_sim *psim;
-       struct                                          cam_path *ppath;
-       u_int8_t                                        *uncacheptr;
-       unsigned long                                   vir2phy_offset;
+       struct                  cam_sim *psim;
+       struct                  cam_path *ppath;
+       u_int8_t                *uncacheptr;
+       unsigned long           vir2phy_offset;
        union   {
-               unsigned long                   phyaddr;
+               unsigned long   phyaddr;
                struct {
-                               u_int32_t               phyadd_low;
-                               u_int32_t               phyadd_high;
+                       u_int32_t       phyadd_low;
+                       u_int32_t       phyadd_high;
                }B;
-       }                                                       srb_phyaddr;
+       }srb_phyaddr;
 //     unsigned long                           srb_phyaddr;
        /* Offset is used in making arc cdb physical to virtual calculations */
-       u_int32_t                                       outbound_int_enable;
-
-       struct MessageUnit_UNION        *pmu;                        /* message unit ATU inbound base address0 */
-
-       u_int8_t                                        adapter_index;                         /*  */
-       u_int8_t                                        irq;
-       u_int16_t                                       acb_flags;                             /*  */
-
+       u_int32_t               outbound_int_enable;
+       
+       struct MessageUnit_UNION        *pmu;           /* message unit ATU inbound base address0 */
+       
+       u_int8_t                adapter_index;
+       u_int8_t                irq;
+       u_int16_t               acb_flags;
+       
        struct CommandControlBlock *psrb_pool[ARCMSR_MAX_FREESRB_NUM];     /* serial srb pointer array */
        struct CommandControlBlock *srbworkingQ[ARCMSR_MAX_FREESRB_NUM];   /* working srb pointer array */
-       int32_t                                         workingsrb_doneindex;                  /* done srb array index */
-       int32_t                                         workingsrb_startindex;                 /* start srb array index  */
-       int32_t                                         srboutstandingcount;
-
-       u_int8_t                                        rqbuffer[ARCMSR_MAX_QBUFFER];          /* data collection buffer for read from 80331 */
-       u_int32_t                                       rqbuf_firstindex;                      /* first of read buffer  */
-       u_int32_t                                       rqbuf_lastindex;                       /* last of read buffer   */
-
-       u_int8_t                                        wqbuffer[ARCMSR_MAX_QBUFFER];          /* data collection buffer for write to 80331  */
-       u_int32_t                                       wqbuf_firstindex;                      /* first of write buffer */
-       u_int32_t                                       wqbuf_lastindex;                       /* last of write buffer  */
-
-       arcmsr_lock_t                                   workingQ_done_lock;
-       arcmsr_lock_t                                   workingQ_start_lock;
-       arcmsr_lock_t                                   qbuffer_lock;
-
-       u_int8_t                                        devstate[ARCMSR_MAX_TARGETID][ARCMSR_MAX_TARGETLUN]; /* id0 ..... id15,lun0...lun7 */
-       u_int32_t                                       num_resets;
-       u_int32_t                                       num_aborts;
-       u_int32_t                                       firm_request_len;                      /*1,04-07*/
-       u_int32_t                                       firm_numbers_queue;                    /*2,08-11*/
-       u_int32_t                                       firm_sdram_size;                       /*3,12-15*/
-       u_int32_t                                       firm_ide_channels;                     /*4,16-19*/
-       u_int32_t                                       firm_cfg_version;
-       char                                            firm_model[12];                        /*15,60-67*/
-       char                                            firm_version[20];                      /*17,68-83*/
-       char                                            device_map[20];                         /*21,84-99 */
-       struct  callout                         devmap_callout;
-#ifdef ARCMSR_DEBUG1
-       u_int32_t                                       pktRequestCount;
-       u_int32_t                                       pktReturnCount;
-#endif
-       u_int32_t                                       vendor_device_id;
-       u_int32_t                                       adapter_bus_speed;
+       int32_t                 workingsrb_doneindex;           /* done srb array index */
+       int32_t                 workingsrb_startindex;          /* start srb array index  */
+       int32_t                 srboutstandingcount;
+       
+       u_int8_t                rqbuffer[ARCMSR_MAX_QBUFFER];   /* data collection buffer for read from 80331 */
+       u_int32_t               rqbuf_firstindex;               /* first of read buffer  */
+       u_int32_t               rqbuf_lastindex;                /* last of read buffer   */
+       
+       u_int8_t                wqbuffer[ARCMSR_MAX_QBUFFER];   /* data collection buffer for write to 80331  */
+       u_int32_t               wqbuf_firstindex;               /* first of write buffer */
+       u_int32_t               wqbuf_lastindex;                /* last of write buffer  */
+       
+       arcmsr_lock_t           isr_lock;
+       arcmsr_lock_t           srb_lock;
+       arcmsr_lock_t           postDone_lock;
+       arcmsr_lock_t           qbuffer_lock;
+       
+       u_int8_t                devstate[ARCMSR_MAX_TARGETID][ARCMSR_MAX_TARGETLUN]; /* id0 ..... id15,lun0...lun7 */
+       u_int32_t               num_resets;
+       u_int32_t               num_aborts;
+       u_int32_t               firm_request_len;       /*1,04-07*/
+       u_int32_t               firm_numbers_queue;     /*2,08-11*/
+       u_int32_t               firm_sdram_size;        /*3,12-15*/
+       u_int32_t               firm_ide_channels;      /*4,16-19*/
+       u_int32_t               firm_cfg_version;
+       char                    firm_model[12];         /*15,60-67*/
+       char                    firm_version[20];       /*17,68-83*/
+       char                    device_map[20];         /*21,84-99 */
+       struct  callout         devmap_callout;
+       u_int32_t               pktRequestCount;
+       u_int32_t               pktReturnCount;
+       u_int32_t               vendor_device_id;
+       u_int32_t               adapter_bus_speed;
+       u_int32_t               maxOutstanding;
+       u_int16_t               sub_device_id;
 };/* HW_DEVICE_EXTENSION */
 /* acb_flags */
 #define ACB_F_SCSISTOPADAPTER           0x0001
-#define ACB_F_MSG_STOP_BGRB             0x0002              /* stop RAID background rebuild */
-#define ACB_F_MSG_START_BGRB            0x0004              /* stop RAID background rebuild */
-#define ACB_F_IOPDATA_OVERFLOW          0x0008              /* iop ioctl data rqbuffer overflow */
-#define ACB_F_MESSAGE_WQBUFFER_CLEARED  0x0010              /* ioctl clear wqbuffer */
-#define ACB_F_MESSAGE_RQBUFFER_CLEARED  0x0020              /* ioctl clear rqbuffer */
+#define ACB_F_MSG_STOP_BGRB             0x0002         /* stop RAID background rebuild */
+#define ACB_F_MSG_START_BGRB            0x0004         /* stop RAID background rebuild */
+#define ACB_F_IOPDATA_OVERFLOW          0x0008         /* iop ioctl data rqbuffer overflow */
+#define ACB_F_MESSAGE_WQBUFFER_CLEARED  0x0010         /* ioctl clear wqbuffer */
+#define ACB_F_MESSAGE_RQBUFFER_CLEARED  0x0020         /* ioctl clear rqbuffer */
 #define ACB_F_MESSAGE_WQBUFFER_READ     0x0040
 #define ACB_F_BUS_RESET                 0x0080
-#define ACB_F_IOP_INITED                0x0100              /* iop init */
-#define ACB_F_MAPFREESRB_FAILD             0x0200              /* arcmsr_map_freesrb faild */
+#define ACB_F_IOP_INITED                0x0100         /* iop init */
+#define ACB_F_MAPFREESRB_FAILD         0x0200          /* arcmsr_map_freesrb faild */
 #define ACB_F_CAM_DEV_QFRZN             0x0400
-#define ACB_F_BUS_HANG_ON               0x0800              /* need hardware reset bus */
+#define ACB_F_BUS_HANG_ON               0x0800         /* need hardware reset bus */
 #define ACB_F_SRB_FUNCTION_POWER        0x1000
 /* devstate */
-#define ARECA_RAID_GONE                        0x55
-#define ARECA_RAID_GOOD                        0xaa
+#define ARECA_RAID_GONE                0x55
+#define ARECA_RAID_GOOD                0xaa
 /* adapter_bus_speed */
 #define        ACB_BUS_SPEED_3G        0
 #define        ACB_BUS_SPEED_6G        1
 #define        ACB_BUS_SPEED_12G       2
-/*
-*********************************************************************
-** Message Unit structure
-*********************************************************************
-*/
-struct HBA_MessageUnit
-{
-       u_int32_t                               resrved0[4];            /*0000 000F*/
-       u_int32_t                               inbound_msgaddr0;           /*0010 0013*/
-       u_int32_t                               inbound_msgaddr1;           /*0014 0017*/
-       u_int32_t                               outbound_msgaddr0;          /*0018 001B*/
-       u_int32_t                               outbound_msgaddr1;          /*001C 001F*/
-       u_int32_t                               inbound_doorbell;           /*0020 0023*/
-       u_int32_t                               inbound_intstatus;          /*0024 0027*/
-       u_int32_t                               inbound_intmask;            /*0028 002B*/
-       u_int32_t                               outbound_doorbell;          /*002C 002F*/
-       u_int32_t                               outbound_intstatus;         /*0030 0033*/
-       u_int32_t                               outbound_intmask;           /*0034 0037*/
-       u_int32_t                               reserved1[2];           /*0038 003F*/
-       u_int32_t                               inbound_queueport;          /*0040 0043*/
-       u_int32_t                               outbound_queueport;     /*0044 0047*/
-       u_int32_t                               reserved2[2];           /*0048 004F*/
-       u_int32_t                               reserved3[492];         /*0050 07FF ......local_buffer 492*/
-       u_int32_t                               reserved4[128];         /*0800 09FF                    128*/
-       u_int32_t                               msgcode_rwbuffer[256];  /*0a00 0DFF                    256*/
-       u_int32_t                               message_wbuffer[32];    /*0E00 0E7F                     32*/
-       u_int32_t                               reserved5[32];          /*0E80 0EFF                     32*/
-       u_int32_t                   &n