svn commit: r210358 - head/sys/dev/arcmsr

Xin LI delphij at FreeBSD.org
Wed Jul 21 18:50:24 UTC 2010


Author: delphij
Date: Wed Jul 21 18:50:24 2010
New Revision: 210358
URL: http://svn.freebsd.org/changeset/base/210358

Log:
  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]
  MFC after:	2 weeks

Modified:
  head/sys/dev/arcmsr/arcmsr.c
  head/sys/dev/arcmsr/arcmsr.h

Modified: head/sys/dev/arcmsr/arcmsr.c
==============================================================================
--- head/sys/dev/arcmsr/arcmsr.c	Wed Jul 21 18:47:52 2010	(r210357)
+++ head/sys/dev/arcmsr/arcmsr.c	Wed Jul 21 18:50:24 2010	(r210358)
@@ -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 ***


More information about the svn-src-all mailing list