Author: delphij
Date: Wed Aug  4 01:36:48 2010
New Revision: 210836
URL: http://svn.freebsd.org/changeset/base/210836

Log:
  MFC r210358:
  
  Apply vendor version 1.20.00.17.
  
  This version adds support for ARC1880; additionally this version fixed
  an issue where all devices on a SAS port gets offlined when any device
  failed on the port [1].
  
  Many thanks to Areca for continuing to support FreeBSD.
  
  PR:           kern/148502 [1]
  Submitted by: Ching-Lung Huang <ching2048 areca com tw>
  Obtained from:        Areca
  Tested by:    Rich Ercolani <rercola acm jhu edu> [1]

Modified:
  stable/8/sys/dev/arcmsr/arcmsr.c
  stable/8/sys/dev/arcmsr/arcmsr.h
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)

Modified: stable/8/sys/dev/arcmsr/arcmsr.c
==============================================================================
--- stable/8/sys/dev/arcmsr/arcmsr.c    Wed Aug  4 01:34:35 2010        
(r210835)
+++ stable/8/sys/dev/arcmsr/arcmsr.c    Wed Aug  4 01:36:48 2010        
(r210836)
@@ -2,15 +2,15 @@
 
*****************************************************************************************
 **        O.S   : FreeBSD
 **   FILE NAME  : arcmsr.c
-**        BY    : Erich Chen   
+**        BY    : Erich Chen, Ching Huang
 **   Description: SCSI RAID Device Driver for 
-**                ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX) SATA/SAS RAID HOST 
Adapter
+**                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]
 
******************************************************************************************
 ************************************************************************
 **
-** Copyright (c) 2004-2006 ARECA Co. Ltd.
+** Copyright (c) 2004-2010 ARECA Co. Ltd.
 **        Erich Chen, Taipei Taiwan All rights reserved.
 **
 ** Redistribution and use in source and binary forms, with or without
@@ -57,6 +57,10 @@
 **     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
 
******************************************************************************************
 * $FreeBSD$
 */
@@ -90,6 +94,8 @@
 #include <cam/cam.h>
 #include <cam/cam_ccb.h>
 #include <cam/cam_sim.h>
+#include <cam/cam_periph.h>
+#include <cam/cam_xpt_periph.h>
 #include <cam/cam_xpt_sim.h>
 #include <cam/cam_debug.h>
 #include <cam/scsi/scsi_all.h>
@@ -165,6 +171,8 @@ static void arcmsr_build_srb(struct Comm
 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);
 /*
 **************************************************************************
 **************************************************************************
@@ -191,7 +199,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),
        { 0, 0 }
@@ -215,7 +222,7 @@ MODULE_DEPEND(arcmsr, cam, 1, 1, 1);
        #ifndef D_VERSION
                #define D_VERSION       0x20011966
        #endif
-       static struct cdevsw arcmsr_cdevsw={
+static struct cdevsw arcmsr_cdevsw={
        #if __FreeBSD_version > 502010
                .d_version = D_VERSION, 
        #endif
@@ -228,7 +235,7 @@ MODULE_DEPEND(arcmsr, cam, 1, 1, 1);
 #else
        #define ARCMSR_CDEV_MAJOR       180
        
-       static struct cdevsw arcmsr_cdevsw = {
+static struct cdevsw arcmsr_cdevsw = {
                arcmsr_open,                    /* open     */
                arcmsr_close,                   /* close    */
                noread,                         /* read     */
@@ -244,7 +251,10 @@ MODULE_DEPEND(arcmsr, cam, 1, 1, 1);
                0                               /* flags    */
        };
 #endif
-
+/*
+**************************************************************************
+**************************************************************************
+*/
 #if __FreeBSD_version < 500005
        static int arcmsr_open(dev_t dev, int flags, int fmt, struct proc *proc)
 #else
@@ -328,18 +338,21 @@ static u_int32_t arcmsr_disable_allintr(
        switch (acb->adapter_type) {
        case ACB_ADAPTER_TYPE_A: {
                        /* disable all outbound interrupt */
-                       intmask_org=CHIP_REG_READ32(HBA_MessageUnit, 
-                       0, 
outbound_intmask)|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE; /* disable 
outbound message0 int */
-                       CHIP_REG_WRITE32(HBA_MessageUnit, 
-                       0, outbound_intmask, 
intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE);
+                       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, 
                        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 
*/
+                       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 */
+                       CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, 
intmask_org|ARCMSR_HBCMU_ALL_INTMASKENABLE);
                }
                break;
        }
@@ -356,19 +369,25 @@ static void arcmsr_enable_allintr( struc
        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);
+                       
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: {
-                       /* disable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */
-                       
mask=(ARCMSR_IOP2DRV_DATA_WRITE_OK|ARCMSR_IOP2DRV_DATA_READ_OK|ARCMSR_IOP2DRV_CDB_DONE);
-                       CHIP_REG_WRITE32(HBB_DOORBELL, 
-                       0, iop2drv_doorbell_mask, intmask_org | mask); 
/*1=interrupt enable, 0=interrupt disable*/
+                       /* enable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */
+                       
mask=(ARCMSR_IOP2DRV_DATA_WRITE_OK|ARCMSR_IOP2DRV_DATA_READ_OK|ARCMSR_IOP2DRV_CDB_DONE|ARCMSR_IOP2DRV_MESSAGE_CMD_DONE);
+                       CHIP_REG_WRITE32(HBB_DOORBELL, 0, 
iop2drv_doorbell_mask, intmask_org | mask); /*1=interrupt enable, 0=interrupt 
disable*/
                        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);
+                       CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, 
intmask_org & mask);
+                       acb->outbound_int_enable= ~(intmask_org & mask) & 
0x0000000f;
+               }
+               break;
        }
        return;
 }
@@ -383,10 +402,8 @@ static u_int8_t arcmsr_hba_wait_msgint_r
        
        do {
                for(Index=0; Index < 100; Index++) {
-                       if(CHIP_REG_READ32(HBA_MessageUnit, 
-                               0, outbound_intstatus) & 
ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
-                               CHIP_REG_WRITE32(HBA_MessageUnit, 
-                               0, outbound_intstatus, 
ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/
+                       if(CHIP_REG_READ32(HBA_MessageUnit, 0, 
outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
+                               CHIP_REG_WRITE32(HBA_MessageUnit, 0, 
outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/
                                return TRUE;
                        }
                        UDELAY(10000);
@@ -405,12 +422,29 @@ static u_int8_t arcmsr_hbb_wait_msgint_r
        
        do {
                for(Index=0; Index < 100; Index++) {
-                       if(CHIP_REG_READ32(HBB_DOORBELL, 
-                               0, iop2drv_doorbell) & 
ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
-                               CHIP_REG_WRITE32(HBB_DOORBELL, 
-                               0, iop2drv_doorbell, 
ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/
-                               CHIP_REG_WRITE32(HBB_DOORBELL, 
-                               0, drv2iop_doorbell, 
ARCMSR_DRV2IOP_END_OF_INTERRUPT);
+                       if(CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & 
ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
+                               CHIP_REG_WRITE32(HBB_DOORBELL, 0, 
iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/
+                               CHIP_REG_WRITE32(HBB_DOORBELL, 0, 
drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
+                               return TRUE;
+                       }
+                       UDELAY(10000);
+               }/*max 1 seconds*/
+       }while(Retries++ < 20);/*max 20 sec*/
+       return FALSE;
+}
+/*
+**********************************************************************
+**********************************************************************
+*/
+static u_int8_t arcmsr_hbc_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(HBC_MessageUnit, 0, 
outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) {
+                               CHIP_REG_WRITE32(HBC_MessageUnit, 0, 
outbound_doorbell_clear, 
ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);/*clear interrupt*/
                                return TRUE;
                        }
                        UDELAY(10000);
@@ -426,8 +460,7 @@ static void arcmsr_flush_hba_cache(struc
 {
        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);
+       CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, 
ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
        do {
                if(arcmsr_hba_wait_msgint_ready(acb)) {
                        break;
@@ -460,6 +493,25 @@ static void arcmsr_flush_hbb_cache(struc
 ************************************************************************
 ************************************************************************
 */
+static void arcmsr_flush_hbc_cache(struct AdapterControlBlock *acb)
+{
+       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);
+       do {
+               if(arcmsr_hbc_wait_msgint_ready(acb)) {
+                       break;
+               } else {
+                       retry_count--;
+               }
+       }while(retry_count!=0);
+       return;
+}
+/*
+************************************************************************
+************************************************************************
+*/
 static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
 {
        switch (acb->adapter_type) {
@@ -471,6 +523,10 @@ static void arcmsr_flush_adapter_cache(s
                        arcmsr_flush_hbb_cache(acb);
                }
                break;
+       case ACB_ADAPTER_TYPE_C: {
+                       arcmsr_flush_hbc_cache(acb);
+               }
+               break;
        }
        return;
 }
@@ -482,10 +538,10 @@ static int arcmsr_suspend(device_t dev)
 {
        struct AdapterControlBlock      *acb = device_get_softc(dev);
        
-       /* disable all outbound interrupt */
-       arcmsr_disable_allintr(acb);
        /* flush controller */
        arcmsr_iop_parking(acb);
+       /* disable all outbound interrupt */
+       arcmsr_disable_allintr(acb);
        return(0);
 }
 /*
@@ -515,12 +571,10 @@ static void arcmsr_async(void *cb_arg, u
        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)) {
+               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);
+               printf("%s:scsi id=%d lun=%d device lost \n", 
device_get_name(acb->pci_dev), target_id, target_lun);
                break;
        default:
                break;
@@ -589,8 +643,7 @@ static void arcmsr_abort_hba_allcmd(stru
 {
        CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, 
ARCMSR_INBOUND_MESG0_ABORT_CMD);
        if(!arcmsr_hba_wait_msgint_ready(acb)) {
-               printf("arcmsr%d: wait 'abort all outstanding command' timeout 
\n"
-                       , acb->pci_unit);
+               printf("arcmsr%d: wait 'abort all outstanding command' timeout 
\n", acb->pci_unit);
        }
        return;
 }
@@ -602,8 +655,20 @@ static void arcmsr_abort_hbb_allcmd(stru
 {
        CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, 
ARCMSR_MESSAGE_ABORT_CMD);
        if(!arcmsr_hbb_wait_msgint_ready(acb)) {
-               printf("arcmsr%d: wait 'abort all outstanding command' timeout 
\n"
-                       , acb->pci_unit);
+               printf("arcmsr%d: wait 'abort all outstanding command' timeout 
\n", acb->pci_unit);
+       }
+       return;
+}
+/*
+*********************************************************************
+*********************************************************************
+*/
+static void arcmsr_abort_hbc_allcmd(struct AdapterControlBlock *acb)
+{
+       CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, 
ARCMSR_INBOUND_MESG0_ABORT_CMD);
+       CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, 
ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
+       if(!arcmsr_hbc_wait_msgint_ready(acb)) {
+               printf("arcmsr%d: wait 'abort all outstanding command' timeout 
\n", acb->pci_unit);
        }
        return;
 }
@@ -622,6 +687,10 @@ static void arcmsr_abort_allcmd(struct A
                        arcmsr_abort_hbb_allcmd(acb);
                }
                break;
+       case ACB_ADAPTER_TYPE_C: {
+                       arcmsr_abort_hbc_allcmd(acb);
+               }
+               break;
        }
        return;
 }
@@ -629,14 +698,13 @@ static void arcmsr_abort_allcmd(struct A
 **************************************************************************
 **************************************************************************
 */
-static void arcmsr_report_srb_state(struct AdapterControlBlock *acb, 
-       struct CommandControlBlock *srb, u_int32_t flag_srb)
+static void arcmsr_report_srb_state(struct AdapterControlBlock *acb, struct 
CommandControlBlock *srb, u_int16_t error)
 {
        int target, lun;
        
        target=srb->pccb->ccb_h.target_id;
        lun=srb->pccb->ccb_h.target_lun;
-       if((flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR)==0) {
+       if(error == FALSE) {
                if(acb->devstate[target][lun]==ARECA_RAID_GONE) {
                        acb->devstate[target][lun]=ARECA_RAID_GOOD;
                }
@@ -646,12 +714,10 @@ static void arcmsr_report_srb_state(stru
                switch(srb->arcmsr_cdb.DeviceStatus) {
                case ARCMSR_DEV_SELECT_TIMEOUT: {
                                if(acb->devstate[target][lun]==ARECA_RAID_GOOD) 
{
-                                       printf( "arcmsr%d: select timeout"
-                                               ", raid volume was kicked out 
\n"
-                                               , acb->pci_unit);
+                                       printf( "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;
-                               srb->pccb->ccb_h.status |= CAM_SEL_TIMEOUT;
+                               srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
                                arcmsr_srb_complete(srb, 1);
                        }
                        break;
@@ -669,11 +735,8 @@ static void arcmsr_report_srb_state(stru
                        }
                        break;
                default:
-                       printf("arcmsr%d: scsi id=%d lun=%d"
-                               "isr get command error done,"
-                               "but got unknow DeviceStatus=0x%x \n"
-                               , acb->pci_unit, target, lun 
-                               ,srb->arcmsr_cdb.DeviceStatus);
+                       printf("arcmsr%d: scsi id=%d lun=%d isr got command 
error done,but got unknow DeviceStatus=0x%x \n"
+                                       , acb->pci_unit, target, lun 
,srb->arcmsr_cdb.DeviceStatus);
                        acb->devstate[target][lun]=ARECA_RAID_GONE;
                        srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY;
                        /*unknow error or crc error just for retry*/
@@ -687,29 +750,34 @@ static void arcmsr_report_srb_state(stru
 **************************************************************************
 **************************************************************************
 */
-static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t 
flag_srb)
+static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t 
flag_srb, u_int16_t error)
 {
        struct CommandControlBlock *srb;
        
        /* check if command done with no error*/
-       srb=(struct CommandControlBlock *)
-               (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes 
aligned*/
+       switch (acb->adapter_type) {
+       case ACB_ADAPTER_TYPE_C:
+               srb = (struct CommandControlBlock 
*)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFF0));/*frame must be 32 bytes 
aligned*/
+               break;
+       case ACB_ADAPTER_TYPE_A:
+       case ACB_ADAPTER_TYPE_B:
+       default:
+               srb = (struct CommandControlBlock 
*)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
+               break;
+       }
        if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) {
                if(srb->startdone==ARCMSR_SRB_ABORTED) {
-                       printf("arcmsr%d: srb='%p' isr got aborted command \n"
-                               , acb->pci_unit, srb);
+                       printf("arcmsr%d: srb='%p' isr got aborted command \n", 
acb->pci_unit, srb);
                        srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
                        arcmsr_srb_complete(srb, 1);
                        return;
                }
                printf("arcmsr%d: isr get an illegal srb command done"
-                       "acb='%p' srb='%p' srbacb='%p' startdone=0x%x"
-                       "srboutstandingcount=%d \n",
-                       acb->pci_unit, acb, srb, srb->acb,
-                       srb->startdone, acb->srboutstandingcount);
+                       "acb='%p' srb='%p' srbacb='%p' 
startdone=0x%xsrboutstandingcount=%d \n",
+                       acb->pci_unit, acb, srb, srb->acb,srb->startdone, 
acb->srboutstandingcount);
                return;
        }
-       arcmsr_report_srb_state(acb, srb, flag_srb);
+       arcmsr_report_srb_state(acb, srb, error);
        return;
 }
 /*
@@ -720,20 +788,18 @@ static void arcmsr_done4abort_postqueue(
 {
        int i=0;
        u_int32_t flag_srb;
+       u_int16_t error;
        
        switch (acb->adapter_type) {
        case ACB_ADAPTER_TYPE_A: {
                        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;
-                       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)) {
-                               arcmsr_drain_donequeue(acb, flag_srb);
+                       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;
+                               arcmsr_drain_donequeue(acb, flag_srb, error);
                        }
                }
                break;
@@ -741,13 +807,12 @@ static void arcmsr_done4abort_postqueue(
                        struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit 
*)acb->pmu;
        
                        /*clear all outbound posted Q*/
-                       CHIP_REG_WRITE32(HBB_DOORBELL, 
-                       0, iop2drv_doorbell, 
-                       ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell 
interrupt */
+                       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;
-                                       arcmsr_drain_donequeue(acb, flag_srb);
+                       error=(flag_srb & 
ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
+                                       arcmsr_drain_donequeue(acb, flag_srb, 
error);
                                }
                                phbbmu->post_qbuffer[i]=0;
                        }/*drain reply FIFO*/
@@ -755,6 +820,15 @@ static void arcmsr_done4abort_postqueue(
                        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;
+                               arcmsr_drain_donequeue(acb, flag_srb, error);
+                       }
+               }
+               break;
        }
        return;
 }
@@ -873,7 +947,10 @@ static void arcmsr_build_srb(struct Comm
                if( arccdbsize > 256) {
                        arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_SGL_BSIZE;
                }
+       } else {
+               arcmsr_cdb->DataLength = 0;
        }
+    srb->arc_cdb_size=arccdbsize;
        return;
 }
 /*
@@ -885,19 +962,16 @@ static void arcmsr_post_srb(struct Adapt
        u_int32_t cdb_shifted_phyaddr=(u_int32_t) srb->cdb_shifted_phyaddr;
        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);
+       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->startdone=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_shifted_phyaddr|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_shifted_phyaddr);
                        }
                }
                break;
@@ -909,17 +983,32 @@ static void arcmsr_post_srb(struct Adapt
                        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_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE;
                        } else {
-                               phbbmu->post_qbuffer[index]=
-                                       cdb_shifted_phyaddr;
+                               phbbmu->post_qbuffer[index]= 
cdb_shifted_phyaddr;
                        }
                        index++;
                        index %= ARCMSR_MAX_HBB_POSTQUEUE;     /*if last index 
number set it to 0 */
                        phbbmu->postq_index=index;
-                       CHIP_REG_WRITE32(HBB_DOORBELL, 
-                       0, drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED);
+                       CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, 
ARCMSR_DRV2IOP_CDB_POSTED);
+               }
+               break;
+    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);
+                       cdb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high;
+            if(cdb_phyaddr_hi32)
+            {
+                           
CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_high, cdb_phyaddr_hi32);
+                           
CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp);
+            }
+            else
+            {
+                           
CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp);
+            }
                }
                break;
        }
@@ -946,6 +1035,12 @@ static struct QBUFFER * arcmsr_get_iop_r
                        qbuffer=(struct QBUFFER 
*)&phbbmu->hbb_rwbuffer->message_rbuffer;
                }
                break;
+       case ACB_ADAPTER_TYPE_C: {
+                       struct HBC_MessageUnit *phbcmu=(struct HBC_MessageUnit 
*)acb->pmu;
+       
+                       qbuffer=(struct QBUFFER *)&phbcmu->message_rbuffer;
+               }
+               break;
        }
        return(qbuffer);
 }
@@ -970,6 +1065,12 @@ static struct QBUFFER * arcmsr_get_iop_w
                        qbuffer=(struct QBUFFER 
*)&phbbmu->hbb_rwbuffer->message_wbuffer;
                }
                break;
+       case ACB_ADAPTER_TYPE_C: {
+                       struct HBC_MessageUnit *phbcmu=(struct HBC_MessageUnit 
*)acb->pmu;
+       
+                       qbuffer=(struct QBUFFER *)&phbcmu->message_wbuffer;
+               }
+               break;
        }
        return(qbuffer);
 }
@@ -982,16 +1083,18 @@ static void arcmsr_iop_message_read(stru
        switch (acb->adapter_type) {
        case ACB_ADAPTER_TYPE_A: {
                        /* let IOP know data has been read */
-                       CHIP_REG_WRITE32(HBA_MessageUnit, 
-                       0, inbound_doorbell, 
ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
+                       CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, 
ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
                }
                break;
        case ACB_ADAPTER_TYPE_B: {
                        /* let IOP know data has been read */
-                       CHIP_REG_WRITE32(HBB_DOORBELL, 
-                       0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK);
+                       CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, 
ARCMSR_DRV2IOP_DATA_READ_OK);
                }
                break;
+       case ACB_ADAPTER_TYPE_C: {
+                       /* let IOP know data has been read */
+                       CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, 
ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK);
+               }
        }
        return;
 }
@@ -1007,8 +1110,7 @@ static void arcmsr_iop_message_wrote(str
                        ** push inbound doorbell tell iop, driver data write ok 
                        ** and wait reply on next hwinterrupt for next Qbuffer 
post
                        */
-                       CHIP_REG_WRITE32(HBA_MessageUnit, 
-                       0, inbound_doorbell, 
ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK);
+                       CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, 
ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK);
                }
                break;
        case ACB_ADAPTER_TYPE_B: {
@@ -1016,8 +1118,15 @@ static void arcmsr_iop_message_wrote(str
                        ** push inbound doorbell tell iop, driver data write ok 
                        ** and wait reply on next hwinterrupt for next Qbuffer 
post
                        */
-                       CHIP_REG_WRITE32(HBB_DOORBELL, 
-                       0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_WRITE_OK);
+                       CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, 
ARCMSR_DRV2IOP_DATA_WRITE_OK);
+               }
+               break;
+       case ACB_ADAPTER_TYPE_C: {
+                       /*
+                       ** push inbound doorbell tell iop, driver data write ok 
+                       ** and wait reply on next hwinterrupt for next Qbuffer 
post
+                       */
+                       CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, 
ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK);
                }
                break;
        }
@@ -1064,7 +1173,7 @@ static void arcmsr_stop_hba_bgrb(struct 
        CHIP_REG_WRITE32(HBA_MessageUnit, 
        0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
        if(!arcmsr_hba_wait_msgint_ready(acb)) {
-               printf("arcmsr%d: wait 'stop adapter rebulid' timeout \n"
+               printf("arcmsr%d: wait 'stop adapter background rebulid' 
timeout \n"
                        , acb->pci_unit);
        }
        return;
@@ -1079,7 +1188,7 @@ static void arcmsr_stop_hbb_bgrb(struct 
        CHIP_REG_WRITE32(HBB_DOORBELL, 
        0, drv2iop_doorbell, ARCMSR_MESSAGE_STOP_BGRB);
        if(!arcmsr_hbb_wait_msgint_ready(acb)) {
-               printf( "arcmsr%d: wait 'stop adapter rebulid' timeout \n"
+               printf( "arcmsr%d: wait 'stop adapter background rebulid' 
timeout \n"
                        , acb->pci_unit);
        }
        return;
@@ -1088,6 +1197,20 @@ static void arcmsr_stop_hbb_bgrb(struct 
 ************************************************************************
 ************************************************************************
 */
+static void arcmsr_stop_hbc_bgrb(struct AdapterControlBlock *acb)
+{
+       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)) {
+               printf("arcmsr%d: wait 'stop adapter background rebulid' 
timeout \n", acb->pci_unit);
+       }
+       return;
+}
+/*
+************************************************************************
+************************************************************************
+*/
 static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
 {
        switch (acb->adapter_type) {
@@ -1099,6 +1222,10 @@ static void arcmsr_stop_adapter_bgrb(str
                        arcmsr_stop_hbb_bgrb(acb);
                }
                break;
+       case ACB_ADAPTER_TYPE_C: {
+                       arcmsr_stop_hbc_bgrb(acb);
+               }
+               break;
        }
        return;
 }
@@ -1121,18 +1248,6 @@ static void arcmsr_poll(struct cam_sim *
        return;
 }
 /*
-**********************************************************************
-**********************************************************************
-*/
-static void arcmsr_intr_handler(void *arg)
-{
-       struct AdapterControlBlock *acb=(struct AdapterControlBlock *)arg;
-       
-       ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
-       arcmsr_interrupt(acb);
-       ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
-}
-/*
 **************************************************************************
 **************************************************************************
 */
@@ -1210,6 +1325,187 @@ static void arcmsr_iop2drv_data_read_han
        }
        return;
 }
+
+static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb)
+{
+/*
+       if (ccb->ccb_h.status != CAM_REQ_CMP)
+               printf("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
+               printf("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;
+
+       if ((ccb = (union ccb *)xpt_alloc_ccb_nowait()) == NULL)
+               return;
+       if (xpt_create_path(&path, xpt_periph, cam_sim_path(acb->psim), target, 
lun) != CAM_REQ_CMP)
+       {
+               xpt_free_ccb(ccb);
+               return;
+       }
+/*     printf("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);
+       return;
+}
+
+
+static void arcmsr_abort_dr_ccbs(struct AdapterControlBlock *acb, int target, 
int lun)
+{
+       struct CommandControlBlock *srb;
+       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++)
+       {
+               srb = acb->psrb_pool[i];
+               if (srb->startdone == ARCMSR_SRB_START)
+               {
+               if((target == srb->pccb->ccb_h.target_id) && (lun == 
srb->pccb->ccb_h.target_lun))
+            {
+                       srb->startdone = ARCMSR_SRB_ABORTED;
+                               srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
+                       arcmsr_srb_complete(srb, 1);
+                       }
+               }
+       }
+       /* enable outbound Post Queue, outbound doorbell Interrupt */
+       arcmsr_enable_allintr(acb, intmask_org);
+       ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
+}
+
+
+/*
+**************************************************************************
+**************************************************************************
+*/
+static void arcmsr_dr_handle(struct AdapterControlBlock *acb) {
+       u_int32_t       devicemap;
+       u_int32_t       target, lun;
+    u_int32_t  deviceMapCurrent[4]={0};
+    u_int8_t   *pDevMap;
+
+       switch (acb->adapter_type) {
+       case ACB_ADAPTER_TYPE_A:
+                       devicemap = offsetof(struct HBA_MessageUnit, 
msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
+                       for (target= 0; target < 4; target++) 
+                       {
+               deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], 
acb->bhandle[0],  devicemap);
+               devicemap += 4;
+                       }
+                       break;
+
+       case ACB_ADAPTER_TYPE_B:
+                       devicemap = offsetof(struct HBB_RWBUFFER, 
msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
+                       for (target= 0; target < 4; target++) 
+                       {
+               deviceMapCurrent[target]=bus_space_read_4(acb->btag[1], 
acb->bhandle[1],  devicemap);
+               devicemap += 4;
+                       }
+                       break;
+
+       case ACB_ADAPTER_TYPE_C:
+                       devicemap = offsetof(struct HBC_MessageUnit, 
msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
+                       for (target= 0; target < 4; target++) 
+                       {
+               deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], 
acb->bhandle[0],  devicemap);
+               devicemap += 4;
+                       }
+                       break;
+       }
+               if(acb->acb_flags & ACB_F_BUS_HANG_ON)
+               {
+                       acb->acb_flags &= ~ACB_F_BUS_HANG_ON;
+               }
+               /* 
+               ** adapter posted CONFIG message 
+               ** copy the new map, note if there are differences with the 
current map
+               */
+               pDevMap = (u_int8_t     *)&deviceMapCurrent[0];
+               for (target= 0; target < ARCMSR_MAX_TARGETID - 1; target++) 
+               {
+                       if (*pDevMap != acb->device_map[target])
+                       {
+                u_int8_t difference, bit_check;
+
+                difference= *pDevMap ^ acb->device_map[target];
+                for(lun=0; lun < ARCMSR_MAX_TARGETLUN; lun++)
+                {
+                    bit_check=(1 << lun);                                      
        /*check bit from 0....31*/
+                    if(difference & bit_check)
+                    {
+                        if(acb->device_map[target] & bit_check)
+                        {/* unit departed */
+                                                       
printf("arcmsr_dr_handle: Target=%x, lun=%x, GONE!!!\n",target,lun);
+                                                       
arcmsr_abort_dr_ccbs(acb, target, lun);
+                               arcmsr_rescan_lun(acb, target, lun);
+                                               acb->devstate[target][lun] = 
ARECA_RAID_GONE;
+                        }
+                        else
+                        {/* unit arrived */
+                                                       
printf("arcmsr_dr_handle: Target=%x, lun=%x, ARRIVING!!!\n",target,lun);
+                               arcmsr_rescan_lun(acb, target, lun);
+                                               acb->devstate[target][lun] = 
ARECA_RAID_GOOD;
+                        }
+                    }
+                }
+/*                             printf("arcmsr_dr_handle: 
acb->device_map[%x]=0x%x, 
deviceMapCurrent[%x]=%x\n",target,acb->device_map[target],target,*pDevMap); */
+                               acb->device_map[target]= *pDevMap;
+                       }
+                       pDevMap++;
+               }
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
+static void arcmsr_hba_message_isr(struct AdapterControlBlock *acb) {
+       u_int32_t outbound_message;
+
+       CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, 
ARCMSR_MU_OUTBOUND_MESSAGE0_INT);
+       outbound_message = CHIP_REG_READ32(HBA_MessageUnit, 0, 
msgcode_rwbuffer[0]);
+       if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
+               arcmsr_dr_handle( acb );
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
+static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) {
+       u_int32_t outbound_message;
+
+       /* clear interrupts */
+       CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, 
ARCMSR_MESSAGE_INT_CLEAR_PATTERN);
+       outbound_message = CHIP_REG_READ32(HBB_RWBUFFER, 1, 
msgcode_rwbuffer[0]);
+       if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
+               arcmsr_dr_handle( acb );
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
+static void arcmsr_hbc_message_isr(struct AdapterControlBlock *acb) {
+       u_int32_t outbound_message;
+
+       CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, 
ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);
+       outbound_message = CHIP_REG_READ32(HBC_MessageUnit, 0, 
msgcode_rwbuffer[0]);
+       if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
+               arcmsr_dr_handle( acb );
+}
 /*
 **************************************************************************
 **************************************************************************
@@ -1241,9 +1537,38 @@ static void arcmsr_hba_doorbell_isr(stru
 **************************************************************************
 **************************************************************************
 */
+static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb)
+{
+       u_int32_t outbound_doorbell;
+       
+       /*
+       *******************************************************************
+       **  Maybe here we need to check wrqbuffer_lock is lock or not
+       **  DOORBELL: din! don! 
+       **  check if there are any mail need to pack from firmware
+       *******************************************************************
+       */
+       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) {
+               arcmsr_iop2drv_data_wrote_handle(acb);
+       }
+       if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) {
+               arcmsr_iop2drv_data_read_handle(acb);
+       }
+       if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) {
+               arcmsr_hbc_message_isr(acb);    /* messenger of "driver to iop 
commands" */
+       }
+       return;
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
 static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb)
 {
        u_int32_t flag_srb;
+       u_int16_t error;
        
        /*
        
*****************************************************************************
@@ -1255,7 +1580,8 @@ static void arcmsr_hba_postqueue_isr(str
        while((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 
                0, outbound_queueport)) != 0xFFFFFFFF) {
                /* check if command done with no error*/
-               arcmsr_drain_donequeue(acb, flag_srb);
+        error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
+               arcmsr_drain_donequeue(acb, flag_srb, error);
        }       /*drain reply FIFO*/
        return;
 }
@@ -1268,6 +1594,7 @@ static void arcmsr_hbb_postqueue_isr(str
        struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu;
        u_int32_t flag_srb;
        int index;
+       u_int16_t error;
        
        /*
        
*****************************************************************************
@@ -1283,7 +1610,38 @@ static void arcmsr_hbb_postqueue_isr(str
                index %= ARCMSR_MAX_HBB_POSTQUEUE;     /*if last index number 
set it to 0 */
                phbbmu->doneq_index=index;
                /* check if command done with no error*/
-               arcmsr_drain_donequeue(acb, flag_srb);
+        error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
+               arcmsr_drain_donequeue(acb, flag_srb, error);
+       }       /*drain reply FIFO*/
+       return;
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
+static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb)
+{
+       u_int32_t flag_srb,throttling=0;
+       u_int16_t error;
+       
+       /*
+       
*****************************************************************************
+       **               areca cdb command done
+       
*****************************************************************************
+       */
+       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);
+               /* check if command done with no error*/
+        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*/
        return;
 }
@@ -1299,14 +1657,12 @@ static void arcmsr_handle_hba_isr( struc
        **   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);
@@ -1315,6 +1671,9 @@ static void arcmsr_handle_hba_isr( struc
        if(outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) {
                arcmsr_hba_postqueue_isr(acb);
        }
+       if(outbound_intstatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
+               arcmsr_hba_message_isr(acb);
+       }
        return;
 }
 /*
@@ -1348,6 +1707,36 @@ static void arcmsr_handle_hbb_isr( struc
        if(outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) {

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to