svn commit: r320986 - in head: share/man/man4 sys/dev/arcmsr

Xin LI delphij at FreeBSD.org
Fri Jul 14 14:53:15 UTC 2017


Author: delphij
Date: Fri Jul 14 14:53:13 2017
New Revision: 320986
URL: https://svnweb.freebsd.org/changeset/base/320986

Log:
  Update arcmsr(4) to 1.40.00.00 in order to add support of
  ARC-1884 SATA RAID controllers.
  
  Many thanks to Areca for continuing to support FreeBSD.
  
  Submitted by:	黃清隆 <ching2048 areca com tw>
  MFC after:	3 days

Modified:
  head/share/man/man4/arcmsr.4
  head/sys/dev/arcmsr/arcmsr.c
  head/sys/dev/arcmsr/arcmsr.h

Modified: head/share/man/man4/arcmsr.4
==============================================================================
--- head/share/man/man4/arcmsr.4	Fri Jul 14 14:52:44 2017	(r320985)
+++ head/share/man/man4/arcmsr.4	Fri Jul 14 14:53:13 2017	(r320986)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd December 4, 2015
+.Dd July 14, 2017
 .Dt ARCMSR 4
 .Os
 .Sh NAME
@@ -147,6 +147,8 @@ ARC-1880
 ARC-1882
 .It
 ARC-1883
+.It
+ARC-1884
 .El
 .Sh FILES
 .Bl -tag -width ".Pa /dev/arcmsr?" -compact

Modified: head/sys/dev/arcmsr/arcmsr.c
==============================================================================
--- head/sys/dev/arcmsr/arcmsr.c	Fri Jul 14 14:52:44 2017	(r320985)
+++ head/sys/dev/arcmsr/arcmsr.c	Fri Jul 14 14:53:13 2017	(r320986)
@@ -77,6 +77,7 @@
 ** 1.20.00.28   09/13/2013  Ching Huang     Removed recursive mutex in arcmsr_abort_dr_ccbs
 ** 1.20.00.29   12/18/2013  Ching Huang     Change simq allocation number, support ARC1883
 ** 1.30.00.00   11/30/2015  Ching Huang     Added support ARC1203
+** 1.40.00.00   07/11/2017  Ching Huang     Added support ARC1884
 ******************************************************************************************
 */
 
@@ -148,7 +149,7 @@ __FBSDID("$FreeBSD$");
 #define arcmsr_callout_init(a)	callout_init(a);
 #endif
 
-#define ARCMSR_DRIVER_VERSION	"arcmsr version 1.30.00.00 2015-11-30"
+#define ARCMSR_DRIVER_VERSION	"arcmsr version 1.40.00.00 2017-07-11"
 #include <dev/arcmsr/arcmsr.h>
 /*
 **************************************************************************
@@ -185,6 +186,8 @@ static void arcmsr_rescanLun_cb(struct cam_periph *per
 static void arcmsr_polling_devmap(void *arg);
 static void arcmsr_srb_timeout(void *arg);
 static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb);
+static void arcmsr_hbe_postqueue_isr(struct AdapterControlBlock *acb);
+void arcmsr_teardown_intr(device_t dev, struct AdapterControlBlock *acb);
 #ifdef ARCMSR_DEBUG1
 static void arcmsr_dump_data(struct AdapterControlBlock *acb);
 #endif
@@ -376,6 +379,12 @@ static u_int32_t arcmsr_disable_allintr( struct Adapte
 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, ARCMSR_HBDMU_ALL_INT_DISABLE);
 		}
 		break;
+	case ACB_ADAPTER_TYPE_E: {
+			/* disable all outbound interrupt */
+			intmask_org = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_mask)	; /* disable outbound message0 int */
+			CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_mask, intmask_org | ARCMSR_HBEMU_ALL_INTMASKENABLE);
+		}
+		break;
 	}
 	return (intmask_org);
 }
@@ -418,6 +427,13 @@ static void arcmsr_enable_allintr( struct AdapterContr
 			acb->outbound_int_enable = mask;
 		}
 		break;
+	case ACB_ADAPTER_TYPE_E: {
+			/* enable outbound Post Queue, outbound doorbell Interrupt */
+			mask = ~(ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR | ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR);
+			CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_mask, intmask_org & mask);
+			acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f;
+		}
+		break;
 	}
 }
 /*
@@ -503,6 +519,28 @@ static u_int8_t arcmsr_hbd_wait_msgint_ready(struct Ad
 	return (FALSE);
 }
 /*
+**********************************************************************
+**********************************************************************
+*/
+static u_int8_t arcmsr_hbe_wait_msgint_ready(struct AdapterControlBlock *acb)
+{
+	u_int32_t Index, read_doorbell;
+	u_int8_t Retries = 0x00;
+	
+	do {
+		for(Index=0; Index < 100; Index++) {
+			read_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell);
+			if((read_doorbell ^ acb->in_doorbell) & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) {
+				CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0);/*clear interrupt*/
+				acb->in_doorbell = read_doorbell;
+				return TRUE;
+			}
+			UDELAY(10000);
+		}/*max 1 seconds*/
+	}while(Retries++ < 20);/*max 20 sec*/
+	return (FALSE);
+}
+/*
 ************************************************************************
 ************************************************************************
 */
@@ -576,6 +614,25 @@ static void arcmsr_flush_hbd_cache(struct AdapterContr
 ************************************************************************
 ************************************************************************
 */
+static void arcmsr_flush_hbe_cache(struct AdapterControlBlock *acb)
+{
+	int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */
+	
+	CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
+	acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+	CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+	do {
+		if(arcmsr_hbe_wait_msgint_ready(acb)) {
+			break;
+		} else {
+			retry_count--;
+		}
+	}while(retry_count != 0);
+}
+/*
+************************************************************************
+************************************************************************
+*/
 static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
 {
 	switch (acb->adapter_type) {
@@ -595,6 +652,10 @@ static void arcmsr_flush_adapter_cache(struct AdapterC
 			arcmsr_flush_hbd_cache(acb);
 		}
 		break;
+	case ACB_ADAPTER_TYPE_E: {
+			arcmsr_flush_hbe_cache(acb);
+		}
+		break;
 	}
 }
 /*
@@ -715,6 +776,19 @@ static void arcmsr_abort_hbd_allcmd(struct AdapterCont
 *********************************************************************
 *********************************************************************
 */
+static void arcmsr_abort_hbe_allcmd(struct AdapterControlBlock *acb)
+{
+	CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD);
+	acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+	CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+	if(!arcmsr_hbe_wait_msgint_ready(acb)) {
+		printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
+	}
+}
+/*
+*********************************************************************
+*********************************************************************
+*/
 static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb)
 {
 	switch (acb->adapter_type) {
@@ -734,6 +808,10 @@ static void arcmsr_abort_allcmd(struct AdapterControlB
 			arcmsr_abort_hbd_allcmd(acb);
 		}
 		break;
+	case ACB_ADAPTER_TYPE_E: {
+			arcmsr_abort_hbe_allcmd(acb);
+		}
+		break;
 	}
 }
 /*
@@ -836,6 +914,9 @@ static void arcmsr_drain_donequeue(struct AdapterContr
 	case ACB_ADAPTER_TYPE_D:
 		srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0)); /*frame must be 32 bytes aligned*/
 		break;
+	case ACB_ADAPTER_TYPE_E:
+		srb = acb->psrb_pool[flag_srb];
+		break;
 	case ACB_ADAPTER_TYPE_A:
 	case ACB_ADAPTER_TYPE_B:
 	default:
@@ -938,6 +1019,10 @@ static void arcmsr_done4abort_postqueue(struct Adapter
 			arcmsr_hbd_postqueue_isr(acb);
 		}
 		break;
+	case ACB_ADAPTER_TYPE_E: {
+			arcmsr_hbe_postqueue_isr(acb);
+		}
+		break;
 	}
 }
 /*
@@ -1149,6 +1234,15 @@ static void arcmsr_post_srb(struct AdapterControlBlock
 			ARCMSR_LOCK_RELEASE(&acb->postDone_lock);
 		}
 		break;
+	case ACB_ADAPTER_TYPE_E: {
+			u_int32_t ccb_post_stamp, arc_cdb_size;
+
+			arc_cdb_size = (srb->arc_cdb_size > 0x300) ? 0x300 : srb->arc_cdb_size;
+			ccb_post_stamp = (srb->smid | ((arc_cdb_size-1) >> 6));
+			CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_queueport_high, 0);
+			CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_queueport_low, ccb_post_stamp);
+        	}
+		break;
 	}
 }
 /*
@@ -1184,6 +1278,12 @@ static struct QBUFFER *arcmsr_get_iop_rqbuffer( struct
 			qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_rbuffer;
 		}
 		break;
+	case ACB_ADAPTER_TYPE_E: {
+			struct HBE_MessageUnit *phbcmu = (struct HBE_MessageUnit *)acb->pmu;
+	
+			qbuffer = (struct QBUFFER *)&phbcmu->message_rbuffer;
+		}
+		break;
 	}
 	return(qbuffer);
 }
@@ -1220,6 +1320,12 @@ static struct QBUFFER *arcmsr_get_iop_wqbuffer( struct
 			qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_wbuffer;
 		}
 		break;
+	case ACB_ADAPTER_TYPE_E: {
+			struct HBE_MessageUnit *phbcmu = (struct HBE_MessageUnit *)acb->pmu;
+	
+			qbuffer = (struct QBUFFER *)&phbcmu->message_wbuffer;
+		}
+		break;
 	}
 	return(qbuffer);
 }
@@ -1251,6 +1357,12 @@ static void arcmsr_iop_message_read(struct AdapterCont
 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ);
 		}
 		break;
+	case ACB_ADAPTER_TYPE_E: {
+			/* let IOP know data has been read */
+			acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK;
+			CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+		}
+		break;
 	}
 }
 /*
@@ -1293,6 +1405,15 @@ static void arcmsr_iop_message_wrote(struct AdapterCon
 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_IN_READY);
 		}
 		break;
+	case ACB_ADAPTER_TYPE_E: {
+			/*
+			** push inbound doorbell tell iop, driver data write ok 
+			** and wait reply on next hwinterrupt for next Qbuffer post
+			*/
+			acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_WRITE_OK;
+			CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+		}
+		break;
 	}
 }
 /*
@@ -1352,6 +1473,20 @@ static void arcmsr_stop_hbd_bgrb(struct AdapterControl
 ************************************************************************
 ************************************************************************
 */
+static void arcmsr_stop_hbe_bgrb(struct AdapterControlBlock *acb)
+{
+	acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
+	CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
+	acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+	CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+	if(!arcmsr_hbe_wait_msgint_ready(acb)) {
+		printf("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) {
@@ -1371,6 +1506,10 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterCon
 			arcmsr_stop_hbd_bgrb(acb);
 		}
 		break;
+	case ACB_ADAPTER_TYPE_E: {
+			arcmsr_stop_hbe_bgrb(acb);
+		}
+		break;
 	}
 }
 /*
@@ -1446,7 +1585,8 @@ static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct 
 	u_int8_t *iop_data;
 	u_int32_t iop_len;
 
-	if(acb->adapter_type & (ACB_ADAPTER_TYPE_C | ACB_ADAPTER_TYPE_D)) {
+	if((acb->adapter_type == ACB_ADAPTER_TYPE_C) || (acb->adapter_type == ACB_ADAPTER_TYPE_D) ||
+		(acb->adapter_type == ACB_ADAPTER_TYPE_E)) {
 		return(arcmsr_Read_iop_rqbuffer_data_D(acb, prbuffer));
 	}
 	iop_data = (u_int8_t *)prbuffer->data;
@@ -1541,7 +1681,8 @@ static void arcmsr_Write_data_2iop_wqbuffer(struct Ada
 	u_int8_t *iop_data;
 	int32_t allxfer_len=0;
 
-	if(acb->adapter_type & (ACB_ADAPTER_TYPE_C | ACB_ADAPTER_TYPE_D)) {
+	if((acb->adapter_type == ACB_ADAPTER_TYPE_C) || (acb->adapter_type == ACB_ADAPTER_TYPE_D) ||
+		(acb->adapter_type == ACB_ADAPTER_TYPE_E)) {
 		arcmsr_Write_data_2iop_wqbuffer_D(acb);
 		return;
 	}
@@ -1694,6 +1835,14 @@ static void arcmsr_dr_handle(struct AdapterControlBloc
 			devicemap += 4;
 		}
 		break;
+	case ACB_ADAPTER_TYPE_E:
+		devicemap = offsetof(struct HBE_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)
@@ -1792,6 +1941,18 @@ static void arcmsr_hbd_message_isr(struct AdapterContr
 **************************************************************************
 **************************************************************************
 */
+static void arcmsr_hbe_message_isr(struct AdapterControlBlock *acb) {
+	u_int32_t outbound_message;
+
+	CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0);
+	outbound_message = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[0]);
+	if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
+		arcmsr_dr_handle( acb );
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
 static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb)
 {
 	u_int32_t doorbell_status;
@@ -1876,6 +2037,35 @@ static void arcmsr_hbd_doorbell_isr(struct AdapterCont
 **************************************************************************
 **************************************************************************
 */
+static void arcmsr_hbe_doorbell_isr(struct AdapterControlBlock *acb)
+{
+	u_int32_t doorbell_status, in_doorbell;
+	
+	/*
+	*******************************************************************
+	**  Maybe here we need to check wrqbuffer_lock is lock or not
+	**  DOORBELL: din! don! 
+	**  check if there are any mail need to pack from firmware
+	*******************************************************************
+	*/
+	in_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell);
+	CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /* clear doorbell interrupt */
+	doorbell_status = in_doorbell ^ acb->in_doorbell;
+	if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_WRITE_OK) {
+		arcmsr_iop2drv_data_wrote_handle(acb);
+	}
+	if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_READ_OK) {
+		arcmsr_iop2drv_data_read_handle(acb);
+	}
+	if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) {
+		arcmsr_hbe_message_isr(acb);    /* messenger of "driver to iop commands" */
+	}
+	acb->in_doorbell = in_doorbell;
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
 static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb)
 {
 	u_int32_t flag_srb;
@@ -2013,6 +2203,34 @@ static void arcmsr_hbd_postqueue_isr(struct AdapterCon
 	CHIP_REG_READ32(HBD_MessageUnit, 0, outboundlist_interrupt_cause); /*Dummy ioread32 to force pci flush */
 }
 /*
+**************************************************************************
+**************************************************************************
+*/
+static void arcmsr_hbe_postqueue_isr(struct AdapterControlBlock *acb)
+{
+	u_int16_t error;
+	uint32_t doneq_index;
+	uint16_t cmdSMID;
+	
+	/*
+	*****************************************************************************
+	**               areca cdb command done
+	*****************************************************************************
+	*/
+	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+	doneq_index = acb->doneq_index;
+	while ((CHIP_REG_READ32(HBE_MessageUnit, 0, reply_post_producer_index) & 0xFFFF) != doneq_index) {
+		cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID;
+		error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
+		arcmsr_drain_donequeue(acb, (u_int32_t)cmdSMID, error);
+		doneq_index++;
+		if (doneq_index >= acb->completionQ_entry)
+			doneq_index = 0;
+	}
+	acb->doneq_index = doneq_index;
+	CHIP_REG_WRITE32(HBE_MessageUnit, 0, reply_post_consumer_index, doneq_index);
+}
+/*
 **********************************************************************
 **********************************************************************
 */
@@ -2143,6 +2361,37 @@ static void arcmsr_handle_hbd_isr( struct AdapterContr
 //	CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable);
 }
 /*
+**********************************************************************
+**********************************************************************
+*/
+static void arcmsr_handle_hbe_isr( struct AdapterControlBlock *acb)
+{
+	u_int32_t host_interrupt_status;
+	/*
+	*********************************************
+	**   check outbound intstatus 
+	*********************************************
+	*/
+	host_interrupt_status = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_status) &
+		(ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR |
+		ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR);
+	if(!host_interrupt_status) {
+		/*it must be share irq*/
+		return;
+	}
+	do {
+		/* MU doorbell interrupts*/
+		if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR) {
+			arcmsr_hbe_doorbell_isr(acb);
+		}
+		/* MU post queue interrupts*/
+		if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR) {
+			arcmsr_hbe_postqueue_isr(acb);
+		}
+		host_interrupt_status = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_status);
+	} while (host_interrupt_status & (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR));
+}
+/*
 ******************************************************************************
 ******************************************************************************
 */
@@ -2161,6 +2410,9 @@ static void arcmsr_interrupt(struct AdapterControlBloc
 	case ACB_ADAPTER_TYPE_D:
 		arcmsr_handle_hbd_isr(acb);
 		break;
+	case ACB_ADAPTER_TYPE_E:
+		arcmsr_handle_hbe_isr(acb);
+		break;
 	default:
 		printf("arcmsr%d: interrupt service,"
 		" unknown adapter type =%d\n", acb->pci_unit, acb->adapter_type);
@@ -2205,6 +2457,12 @@ static void	arcmsr_polling_devmap(void *arg)
 	case ACB_ADAPTER_TYPE_D:
 		CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
 		break;
+
+    	case ACB_ADAPTER_TYPE_E:
+		CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
+		acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+		CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+	    	break;
 	}
 
 	if((acb->acb_flags & ACB_F_SCSISTOPADAPTER) == 0)
@@ -2907,6 +3165,7 @@ static void arcmsr_action(struct cam_sim *psim, union 
 			else
 				cpi->base_transfer_speed = 300000;
 			if((acb->vendor_device_id == PCIDevVenIDARC1880) ||
+			   (acb->vendor_device_id == PCIDevVenIDARC1884) ||
 			   (acb->vendor_device_id == PCIDevVenIDARC1680) ||
 			   (acb->vendor_device_id == PCIDevVenIDARC1214))
 			{
@@ -2991,6 +3250,7 @@ static void arcmsr_action(struct cam_sim *psim, union 
 				cts->protocol = PROTO_SCSI;
 
 				if((acb->vendor_device_id == PCIDevVenIDARC1880) ||
+				   (acb->vendor_device_id == PCIDevVenIDARC1884) ||
 				   (acb->vendor_device_id == PCIDevVenIDARC1680) ||
 				   (acb->vendor_device_id == PCIDevVenIDARC1214))
 				{
@@ -3150,6 +3410,20 @@ static void arcmsr_start_hbd_bgrb(struct AdapterContro
 **********************************************************************
 **********************************************************************
 */
+static void arcmsr_start_hbe_bgrb(struct AdapterControlBlock *acb)
+{
+	acb->acb_flags |= ACB_F_MSG_START_BGRB;
+	CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB);
+	acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+	CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+	if(!arcmsr_hbe_wait_msgint_ready(acb)) {
+		printf("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) {
@@ -3165,6 +3439,9 @@ static void arcmsr_start_adapter_bgrb(struct AdapterCo
 	case ACB_ADAPTER_TYPE_D:
 		arcmsr_start_hbd_bgrb(acb);
 		break;
+	case ACB_ADAPTER_TYPE_E:
+		arcmsr_start_hbe_bgrb(acb);
+		break;
 	}
 }
 /*
@@ -3388,8 +3665,63 @@ polling_ccb_retry:
 }
 /*
 **********************************************************************
+** 
 **********************************************************************
 */
+static void arcmsr_polling_hbe_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
+{
+	struct CommandControlBlock *srb;
+	u_int32_t poll_srb_done=0, poll_count=0, doneq_index;
+	u_int16_t	error, cmdSMID;
+	
+polling_ccb_retry:
+	poll_count++;
+	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+	while(1) {
+		doneq_index = acb->doneq_index;
+		if((CHIP_REG_READ32(HBE_MessageUnit, 0, reply_post_producer_index) & 0xFFFF) == doneq_index) {
+			if(poll_srb_done) {
+				break;/*chip FIFO no ccb for completion already*/
+			} else {
+				UDELAY(25000);
+			    if ((poll_count > 100) && (poll_srb != NULL)) {
+					break;
+				}
+			    if (acb->srboutstandingcount == 0) {
+				    break;
+			    }
+				goto polling_ccb_retry;
+			}
+		}
+		cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID;
+		doneq_index++;
+		if (doneq_index >= acb->completionQ_entry)
+			doneq_index = 0;
+		acb->doneq_index = doneq_index;
+		srb = acb->psrb_pool[cmdSMID];
+		error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
+		if (poll_srb != NULL)
+			poll_srb_done = (srb == poll_srb) ? 1:0;
+		if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
+			if(srb->srb_state == ARCMSR_SRB_ABORTED) {
+				printf("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;
+			}
+			printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n"
+					, acb->pci_unit, srb, acb->srboutstandingcount);
+			continue;
+		}
+		arcmsr_report_srb_state(acb, srb, error);
+	}	/*drain reply FIFO*/
+	CHIP_REG_WRITE32(HBE_MessageUnit, 0, reply_post_producer_index, doneq_index);
+}
+/*
+**********************************************************************
+**********************************************************************
+*/
 static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
 {
 	switch (acb->adapter_type) {
@@ -3409,6 +3741,10 @@ static void arcmsr_polling_srbdone(struct AdapterContr
 			arcmsr_polling_hbd_srbdone(acb, poll_srb);
 		}
 		break;
+	case ACB_ADAPTER_TYPE_E: {
+			arcmsr_polling_hbe_srbdone(acb, poll_srb);
+		}
+		break;
 	}
 }
 /*
@@ -3615,6 +3951,58 @@ static void arcmsr_get_hbd_config(struct AdapterContro
 **********************************************************************
 **********************************************************************
 */
+static void arcmsr_get_hbe_config(struct AdapterControlBlock *acb)
+{
+	char *acb_firm_model = acb->firm_model;
+	char *acb_firm_version = acb->firm_version;
+	char *acb_device_map = acb->device_map;
+	size_t iop_firm_model = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);   /*firm_model,15,60-67*/
+	size_t iop_firm_version = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/
+	size_t iop_device_map = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
+	int i;
+	
+	CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
+	acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+	CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+	if(!arcmsr_hbe_wait_msgint_ready(acb)) {
+		printf("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++;
+	}
+	printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version);
+	acb->firm_request_len	= CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[1]);	/*firm_request_len,   1, 04-07*/
+	acb->firm_numbers_queue	= CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[2]);	/*firm_numbers_queue, 2, 08-11*/
+	acb->firm_sdram_size	= CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[3]);	/*firm_sdram_size,    3, 12-15*/
+	acb->firm_ide_channels	= CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[4]);	/*firm_ide_channels,  4, 16-19*/
+	acb->firm_cfg_version	= CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);	/*firm_cfg_version,  25, 	  */
+	if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD)
+		acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1;
+	else
+		acb->maxOutstanding = acb->firm_numbers_queue - 1;
+}
+/*
+**********************************************************************
+**********************************************************************
+*/
 static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
 {
 	switch (acb->adapter_type) {
@@ -3634,6 +4022,10 @@ static void arcmsr_get_firmware_spec(struct AdapterCon
 			arcmsr_get_hbd_config(acb);
 		}
 		break;
+	case ACB_ADAPTER_TYPE_E: {
+			arcmsr_get_hbe_config(acb);
+		}
+		break;
 	}
 }
 /*
@@ -3695,6 +4087,18 @@ static void arcmsr_wait_firmware_ready( struct Adapter
 			}
 		}
 		break;
+	case ACB_ADAPTER_TYPE_E: {
+			while ((CHIP_REG_READ32(HBE_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBEMU_MESSAGE_FIRMWARE_OK) == 0)
+			{
+				if (timeout++ > 4000) /* (4000*15)/1000 = 60 sec */
+				{
+					printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit);
+					return;
+				}
+				UDELAY(15000); /* wait 15 milli-seconds */
+			}
+		}
+		break;
 	}
 }
 /*
@@ -3738,6 +4142,14 @@ static void arcmsr_clear_doorbell_queue_buffer( struct
 			
 		}
 		break;
+	case ACB_ADAPTER_TYPE_E: {
+			/* empty doorbell Qbuffer if door bell ringed */
+			acb->in_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell);
+			CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0);	/*clear doorbell interrupt */
+			acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK;
+			CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+		}
+		break;
 	}
 }
 /*
@@ -3844,6 +4256,27 @@ static u_int32_t arcmsr_iop_confirm(struct AdapterCont
 			}
 		}
 		break;
+	case ACB_ADAPTER_TYPE_E: {
+			u_int32_t cdb_phyaddr_lo32;
+			cdb_phyaddr_lo32 = srb_phyaddr_lo32 + offsetof(struct CommandControlBlock, arcmsr_cdb);
+			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG);
+			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[1], ARCMSR_SIGNATURE_1884);
+			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[2], cdb_phyaddr_lo32);
+			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[3], srb_phyaddr_hi32);
+			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[4], SRB_SIZE);
+			cdb_phyaddr_lo32 = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE;
+			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[5], cdb_phyaddr_lo32);
+			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[6], srb_phyaddr_hi32);
+			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[7], COMPLETION_Q_POOL_SIZE);
+			CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
+			acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+			CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+			if(!arcmsr_hbe_wait_msgint_ready(acb)) {
+				printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit);
+				return FALSE;
+			}
+		}
+		break;
 	}
 	return (TRUE);
 }
@@ -3853,21 +4286,14 @@ static u_int32_t arcmsr_iop_confirm(struct AdapterCont
 */
 static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb)
 {
-	switch (acb->adapter_type)
+	if (acb->adapter_type == ACB_ADAPTER_TYPE_B)
 	{
-	case ACB_ADAPTER_TYPE_A:
-	case ACB_ADAPTER_TYPE_C:
-	case ACB_ADAPTER_TYPE_D:
-		break;
-	case ACB_ADAPTER_TYPE_B: {
-			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
-			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_ACTIVE_EOI_MODE);
-			if(!arcmsr_hbb_wait_msgint_ready(acb)) {
-				printf( "arcmsr%d: 'iop enable eoi mode' timeout \n", acb->pci_unit);
-				return;
-			}
+		struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
+		WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_ACTIVE_EOI_MODE);
+		if(!arcmsr_hbb_wait_msgint_ready(acb)) {
+			printf( "arcmsr%d: 'iop enable eoi mode' timeout \n", acb->pci_unit);
+			return;
 		}
-		break;
 	}
 }
 /*
@@ -3913,7 +4339,8 @@ static void arcmsr_map_free_srb(void *arg, bus_dma_seg
 			" srb dmamap bus_dmamap_create error\n", acb->pci_unit);
 			return;
 		}
-		if((acb->adapter_type == ACB_ADAPTER_TYPE_C) || (acb->adapter_type == ACB_ADAPTER_TYPE_D))
+		if((acb->adapter_type == ACB_ADAPTER_TYPE_C) || (acb->adapter_type == ACB_ADAPTER_TYPE_D)
+			 || (acb->adapter_type == ACB_ADAPTER_TYPE_E))
 		{
 			srb_tmp->cdb_phyaddr_low = srb_phyaddr;
 			srb_tmp->cdb_phyaddr_high = (u_int32_t)((srb_phyaddr >> 16) >> 16);
@@ -3921,10 +4348,12 @@ static void arcmsr_map_free_srb(void *arg, bus_dma_seg
 		else
 			srb_tmp->cdb_phyaddr_low = srb_phyaddr >> 5;
 		srb_tmp->acb = acb;
+		srb_tmp->smid = i << 16;
 		acb->srbworkingQ[i] = acb->psrb_pool[i] = srb_tmp;
 		srb_phyaddr = srb_phyaddr + SRB_SIZE;
 		srb_tmp = (struct CommandControlBlock *)((unsigned long)srb_tmp + SRB_SIZE);
 	}
+	acb->pCompletionQ = (pCompletion_Q)srb_tmp;
 	acb->vir2phy_offset = (unsigned long)srb_tmp - (unsigned long)srb_phyaddr;
 }
 /*
@@ -3992,6 +4421,12 @@ static u_int32_t arcmsr_initialize(device_t dev)
 			max_coherent_size = ARCMSR_SRBS_POOL_SIZE;
 		}
 		break;
+	case PCIDevVenIDARC1884:
+		acb->adapter_type = ACB_ADAPTER_TYPE_E;
+		acb->adapter_bus_speed = ACB_BUS_SPEED_12G;
+		max_coherent_size = ARCMSR_SRBS_POOL_SIZE + COMPLETION_Q_POOL_SIZE;
+		acb->completionQ_entry = COMPLETION_Q_POOL_SIZE / sizeof(struct deliver_completeQ);
+		break;
 	case PCIDevVenIDARC1214: {
 			acb->adapter_type = ACB_ADAPTER_TYPE_D;
 			acb->adapter_bus_speed = ACB_BUS_SPEED_6G;
@@ -4140,141 +4575,177 @@ static u_int32_t arcmsr_initialize(device_t dev)
 	pci_write_config(dev, PCIR_COMMAND, pci_command, 2);
 	switch(acb->adapter_type) {
 	case ACB_ADAPTER_TYPE_A: {
-			u_int32_t rid0 = PCIR_BAR(0);
-			vm_offset_t	mem_base0;
+		u_int32_t rid0 = PCIR_BAR(0);
+		vm_offset_t	mem_base0;
 
-			acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid0, RF_ACTIVE);
-			if(acb->sys_res_arcmsr[0] == NULL) {
-				arcmsr_free_resource(acb);
-				printf("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);
-				printf("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);
-				printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
-				return ENXIO;
-			}
-			acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
-			acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
-			acb->pmu = (struct MessageUnit_UNION *)mem_base0;
+		acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid0, RF_ACTIVE);
+		if(acb->sys_res_arcmsr[0] == NULL) {
+			arcmsr_free_resource(acb);
+			printf("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);
+			printf("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);
+			printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
+			return ENXIO;
+		}
+		acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
+		acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
+		acb->pmu = (struct MessageUnit_UNION *)mem_base0;
+		acb->rid = 0;
+		}
 		break;
 	case ACB_ADAPTER_TYPE_B: {
-			struct HBB_MessageUnit *phbbmu;
-			struct CommandControlBlock *freesrb;
-			u_int32_t rid[]={ PCIR_BAR(0), PCIR_BAR(2) };
-			vm_offset_t	mem_base[]={0,0};
-			u_long	size;
-			if (vendor_dev_id == PCIDevVenIDARC1203)
-				size = sizeof(struct HBB_DOORBELL_1203);
-			else
-				size = sizeof(struct HBB_DOORBELL);
-			for(i=0; i < 2; i++) {
-				if(i == 0) {
-					acb->sys_res_arcmsr[i] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid[i],
-											RF_ACTIVE);
-				} else {
-					acb->sys_res_arcmsr[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid[i],
-											RF_ACTIVE);
-				}
-				if(acb->sys_res_arcmsr[i] == NULL) {
-					arcmsr_free_resource(acb);
-					printf("arcmsr%d: bus_alloc_resource %d failure!\n", device_get_unit(dev), i);
-					return ENOMEM;
-				}
-				if(rman_get_start(acb->sys_res_arcmsr[i]) <= 0) {
-					arcmsr_free_resource(acb);
-					printf("arcmsr%d: rman_get_start %d failure!\n", device_get_unit(dev), i);
-					return ENXIO;
-				}
-				mem_base[i] = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[i]);
-				if(mem_base[i] == 0) {
-					arcmsr_free_resource(acb);
-					printf("arcmsr%d: rman_get_virtual %d failure!\n", device_get_unit(dev), i);
-					return ENXIO;
-				}
-				acb->btag[i] = rman_get_bustag(acb->sys_res_arcmsr[i]);
-				acb->bhandle[i] = rman_get_bushandle(acb->sys_res_arcmsr[i]);
-			}
-			freesrb = (struct CommandControlBlock *)acb->uncacheptr;
-			acb->pmu = (struct MessageUnit_UNION *)((unsigned long)freesrb+ARCMSR_SRBS_POOL_SIZE);
-			phbbmu = (struct HBB_MessageUnit *)acb->pmu;
-			phbbmu->hbb_doorbell = (struct HBB_DOORBELL *)mem_base[0];
-			phbbmu->hbb_rwbuffer = (struct HBB_RWBUFFER *)mem_base[1];
-			if (vendor_dev_id == PCIDevVenIDARC1203) {
-				phbbmu->drv2iop_doorbell = offsetof(struct HBB_DOORBELL_1203, drv2iop_doorbell);
-				phbbmu->drv2iop_doorbell_mask = offsetof(struct HBB_DOORBELL_1203, drv2iop_doorbell_mask);
-				phbbmu->iop2drv_doorbell = offsetof(struct HBB_DOORBELL_1203, iop2drv_doorbell);
-				phbbmu->iop2drv_doorbell_mask = offsetof(struct HBB_DOORBELL_1203, iop2drv_doorbell_mask);
+		struct HBB_MessageUnit *phbbmu;
+		struct CommandControlBlock *freesrb;
+		u_int32_t rid[]={ PCIR_BAR(0), PCIR_BAR(2) };
+		vm_offset_t	mem_base[]={0,0};
+		u_long	size;
+		if (vendor_dev_id == PCIDevVenIDARC1203)
+			size = sizeof(struct HBB_DOORBELL_1203);
+		else
+			size = sizeof(struct HBB_DOORBELL);
+		for(i=0; i < 2; i++) {
+			if(i == 0) {
+				acb->sys_res_arcmsr[i] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid[i],
+										RF_ACTIVE);
 			} else {
-				phbbmu->drv2iop_doorbell = offsetof(struct HBB_DOORBELL, drv2iop_doorbell);
-				phbbmu->drv2iop_doorbell_mask = offsetof(struct HBB_DOORBELL, drv2iop_doorbell_mask);
-				phbbmu->iop2drv_doorbell = offsetof(struct HBB_DOORBELL, iop2drv_doorbell);
-				phbbmu->iop2drv_doorbell_mask = offsetof(struct HBB_DOORBELL, iop2drv_doorbell_mask);
+				acb->sys_res_arcmsr[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid[i],
+										RF_ACTIVE);
 			}
-		}
-		break;
-	case ACB_ADAPTER_TYPE_C: {
-			u_int32_t rid0 = PCIR_BAR(1);
-			vm_offset_t	mem_base0;
-
-			acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid0, RF_ACTIVE);
-			if(acb->sys_res_arcmsr[0] == NULL) {
+			if(acb->sys_res_arcmsr[i] == NULL) {
 				arcmsr_free_resource(acb);
-				printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
+				printf("arcmsr%d: bus_alloc_resource %d failure!\n", device_get_unit(dev), i);
 				return ENOMEM;
 			}
-			if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
+			if(rman_get_start(acb->sys_res_arcmsr[i]) <= 0) {
 				arcmsr_free_resource(acb);
-				printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
+				printf("arcmsr%d: rman_get_start %d failure!\n", device_get_unit(dev), i);
 				return ENXIO;
 			}
-			mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
-			if(mem_base0 == 0) {
+			mem_base[i] = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[i]);
+			if(mem_base[i] == 0) {
 				arcmsr_free_resource(acb);
-				printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
+				printf("arcmsr%d: rman_get_virtual %d failure!\n", device_get_unit(dev), i);
 				return ENXIO;
 			}
-			acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
-			acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
-			acb->pmu = (struct MessageUnit_UNION *)mem_base0;
+			acb->btag[i] = rman_get_bustag(acb->sys_res_arcmsr[i]);
+			acb->bhandle[i] = rman_get_bushandle(acb->sys_res_arcmsr[i]);
 		}
+		freesrb = (struct CommandControlBlock *)acb->uncacheptr;
+		acb->pmu = (struct MessageUnit_UNION *)((unsigned long)freesrb+ARCMSR_SRBS_POOL_SIZE);
+		phbbmu = (struct HBB_MessageUnit *)acb->pmu;
+		phbbmu->hbb_doorbell = (struct HBB_DOORBELL *)mem_base[0];
+		phbbmu->hbb_rwbuffer = (struct HBB_RWBUFFER *)mem_base[1];
+		if (vendor_dev_id == PCIDevVenIDARC1203) {
+			phbbmu->drv2iop_doorbell = offsetof(struct HBB_DOORBELL_1203, drv2iop_doorbell);
+			phbbmu->drv2iop_doorbell_mask = offsetof(struct HBB_DOORBELL_1203, drv2iop_doorbell_mask);
+			phbbmu->iop2drv_doorbell = offsetof(struct HBB_DOORBELL_1203, iop2drv_doorbell);
+			phbbmu->iop2drv_doorbell_mask = offsetof(struct HBB_DOORBELL_1203, iop2drv_doorbell_mask);
+		} else {
+			phbbmu->drv2iop_doorbell = offsetof(struct HBB_DOORBELL, drv2iop_doorbell);
+			phbbmu->drv2iop_doorbell_mask = offsetof(struct HBB_DOORBELL, drv2iop_doorbell_mask);
+			phbbmu->iop2drv_doorbell = offsetof(struct HBB_DOORBELL, iop2drv_doorbell);
+			phbbmu->iop2drv_doorbell_mask = offsetof(struct HBB_DOORBELL, iop2drv_doorbell_mask);
+		}
+		acb->rid = 0;
+		}
 		break;
+	case ACB_ADAPTER_TYPE_C: {
+		u_int32_t rid0 = PCIR_BAR(1);
+		vm_offset_t	mem_base0;
+
+		acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid0, RF_ACTIVE);
+		if(acb->sys_res_arcmsr[0] == NULL) {
+			arcmsr_free_resource(acb);
+			printf("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);
+			printf("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);
+			printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
+			return ENXIO;
+		}
+		acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
+		acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
+		acb->pmu = (struct MessageUnit_UNION *)mem_base0;
+		acb->rid = 1;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-head mailing list