summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2017-07-17 06:28:34 +0000
committerdelphij <delphij@FreeBSD.org>2017-07-17 06:28:34 +0000
commitcb9c6059b4d3cfa58d8c5c0da642c9f0e4271c62 (patch)
tree353db8218babc9dba02ac76bbae64751c4b01321
parenta9ad15f3911f8b27134fa4315021904ca81a7e04 (diff)
downloadFreeBSD-src-cb9c6059b4d3cfa58d8c5c0da642c9f0e4271c62.zip
FreeBSD-src-cb9c6059b4d3cfa58d8c5c0da642c9f0e4271c62.tar.gz
MFC r320986:
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>
-rw-r--r--share/man/man4/arcmsr.44
-rw-r--r--sys/dev/arcmsr/arcmsr.c899
-rw-r--r--sys/dev/arcmsr/arcmsr.h134
3 files changed, 842 insertions, 195 deletions
diff --git a/share/man/man4/arcmsr.4 b/share/man/man4/arcmsr.4
index 5fd9453..ec15aee 100644
--- a/share/man/man4/arcmsr.4
+++ b/share/man/man4/arcmsr.4
@@ -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
diff --git a/sys/dev/arcmsr/arcmsr.c b/sys/dev/arcmsr/arcmsr.c
index df4ba50..6b976b9 100644
--- a/sys/dev/arcmsr/arcmsr.c
+++ b/sys/dev/arcmsr/arcmsr.c
@@ -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 *periph, union ccb *ccb);
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 AdapterControlBlock *acb)
CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, ARCMSR_HBDMU_ALL_INT_DISABLE);
}
break;
+ case ACB_ADAPTER_TYPE_E: {
+ /* disable all outbound interrupt */
+ intmask_org = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_mask) ; /* disable outbound message0 int */
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_mask, intmask_org | ARCMSR_HBEMU_ALL_INTMASKENABLE);
+ }
+ break;
}
return (intmask_org);
}
@@ -418,6 +427,13 @@ static void arcmsr_enable_allintr( struct AdapterControlBlock *acb, u_int32_t in
acb->outbound_int_enable = mask;
}
break;
+ case ACB_ADAPTER_TYPE_E: {
+ /* enable outbound Post Queue, outbound doorbell Interrupt */
+ mask = ~(ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR | ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR);
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_mask, intmask_org & mask);
+ acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f;
+ }
+ break;
}
}
/*
@@ -503,6 +519,28 @@ static u_int8_t arcmsr_hbd_wait_msgint_ready(struct AdapterControlBlock *acb)
return (FALSE);
}
/*
+**********************************************************************
+**********************************************************************
+*/
+static u_int8_t arcmsr_hbe_wait_msgint_ready(struct AdapterControlBlock *acb)
+{
+ u_int32_t Index, read_doorbell;
+ u_int8_t Retries = 0x00;
+
+ do {
+ for(Index=0; Index < 100; Index++) {
+ read_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell);
+ if((read_doorbell ^ acb->in_doorbell) & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) {
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0);/*clear interrupt*/
+ acb->in_doorbell = read_doorbell;
+ return TRUE;
+ }
+ UDELAY(10000);
+ }/*max 1 seconds*/
+ }while(Retries++ < 20);/*max 20 sec*/
+ return (FALSE);
+}
+/*
************************************************************************
************************************************************************
*/
@@ -576,6 +614,25 @@ static void arcmsr_flush_hbd_cache(struct AdapterControlBlock *acb)
************************************************************************
************************************************************************
*/
+static void arcmsr_flush_hbe_cache(struct AdapterControlBlock *acb)
+{
+ int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */
+
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
+ acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+ do {
+ if(arcmsr_hbe_wait_msgint_ready(acb)) {
+ break;
+ } else {
+ retry_count--;
+ }
+ }while(retry_count != 0);
+}
+/*
+************************************************************************
+************************************************************************
+*/
static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
{
switch (acb->adapter_type) {
@@ -595,6 +652,10 @@ static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
arcmsr_flush_hbd_cache(acb);
}
break;
+ case ACB_ADAPTER_TYPE_E: {
+ arcmsr_flush_hbe_cache(acb);
+ }
+ break;
}
}
/*
@@ -715,6 +776,19 @@ static void arcmsr_abort_hbd_allcmd(struct AdapterControlBlock *acb)
*********************************************************************
*********************************************************************
*/
+static void arcmsr_abort_hbe_allcmd(struct AdapterControlBlock *acb)
+{
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD);
+ acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+ if(!arcmsr_hbe_wait_msgint_ready(acb)) {
+ 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 AdapterControlBlock *acb)
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 AdapterControlBlock *acb, u_int32_t fl
case ACB_ADAPTER_TYPE_D:
srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0)); /*frame must be 32 bytes aligned*/
break;
+ case ACB_ADAPTER_TYPE_E:
+ srb = acb->psrb_pool[flag_srb];
+ break;
case ACB_ADAPTER_TYPE_A:
case ACB_ADAPTER_TYPE_B:
default:
@@ -938,6 +1019,10 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
arcmsr_hbd_postqueue_isr(acb);
}
break;
+ case ACB_ADAPTER_TYPE_E: {
+ arcmsr_hbe_postqueue_isr(acb);
+ }
+ break;
}
}
/*
@@ -963,9 +1048,9 @@ static void arcmsr_iop_reset(struct AdapterControlBlock *acb)
srb->srb_state = ARCMSR_SRB_ABORTED;
srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
arcmsr_srb_complete(srb, 1);
- printf("arcmsr%d: scsi id=%d lun=%d srb='%p' aborted\n"
+ printf("arcmsr%d: scsi id=%d lun=%jx srb='%p' aborted\n"
, acb->pci_unit, srb->pccb->ccb_h.target_id
- , srb->pccb->ccb_h.target_lun, srb);
+ , (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
}
}
/* enable all outbound interrupt */
@@ -1149,6 +1234,15 @@ static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandContr
ARCMSR_LOCK_RELEASE(&acb->postDone_lock);
}
break;
+ case ACB_ADAPTER_TYPE_E: {
+ u_int32_t ccb_post_stamp, arc_cdb_size;
+
+ arc_cdb_size = (srb->arc_cdb_size > 0x300) ? 0x300 : srb->arc_cdb_size;
+ ccb_post_stamp = (srb->smid | ((arc_cdb_size-1) >> 6));
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_queueport_high, 0);
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_queueport_low, ccb_post_stamp);
+ }
+ break;
}
}
/*
@@ -1184,6 +1278,12 @@ static struct QBUFFER *arcmsr_get_iop_rqbuffer( struct AdapterControlBlock *acb)
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 AdapterControlBlock *acb)
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 AdapterControlBlock *acb)
CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ);
}
break;
+ case ACB_ADAPTER_TYPE_E: {
+ /* let IOP know data has been read */
+ acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK;
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+ }
+ break;
}
}
/*
@@ -1293,6 +1405,15 @@ static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb)
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 AdapterControlBlock *acb)
************************************************************************
************************************************************************
*/
+static void arcmsr_stop_hbe_bgrb(struct AdapterControlBlock *acb)
+{
+ acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
+ acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+ if(!arcmsr_hbe_wait_msgint_ready(acb)) {
+ 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 AdapterControlBlock *acb)
arcmsr_stop_hbd_bgrb(acb);
}
break;
+ case ACB_ADAPTER_TYPE_E: {
+ arcmsr_stop_hbe_bgrb(acb);
+ }
+ break;
}
}
/*
@@ -1398,8 +1537,8 @@ static u_int32_t arcmsr_Read_iop_rqbuffer_data_D(struct AdapterControlBlock *acb
struct QBUFFER *prbuffer) {
u_int8_t *pQbuffer;
- u_int8_t *buf1 = 0;
- u_int32_t *iop_data, *buf2 = 0;
+ u_int8_t *buf1 = NULL;
+ u_int32_t *iop_data, *buf2 = NULL;
u_int32_t iop_len, data_len;
iop_data = (u_int32_t *)prbuffer->data;
@@ -1446,7 +1585,8 @@ static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb,
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;
@@ -1494,8 +1634,8 @@ static void arcmsr_Write_data_2iop_wqbuffer_D(struct AdapterControlBlock *acb)
{
u_int8_t *pQbuffer;
struct QBUFFER *pwbuffer;
- u_int8_t *buf1 = 0;
- u_int32_t *iop_data, *buf2 = 0;
+ u_int8_t *buf1 = NULL;
+ u_int32_t *iop_data, *buf2 = NULL;
u_int32_t allxfer_len = 0, data_len;
if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) {
@@ -1541,7 +1681,8 @@ static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb)
u_int8_t *iop_data;
int32_t allxfer_len=0;
- if(acb->adapter_type & (ACB_ADAPTER_TYPE_C | ACB_ADAPTER_TYPE_D)) {
+ if((acb->adapter_type == ACB_ADAPTER_TYPE_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 AdapterControlBlock *acb) {
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 AdapterControlBlock *acb) {
**************************************************************************
**************************************************************************
*/
+static void arcmsr_hbe_message_isr(struct AdapterControlBlock *acb) {
+ u_int32_t outbound_message;
+
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0);
+ outbound_message = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[0]);
+ if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
+ arcmsr_dr_handle( acb );
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb)
{
u_int32_t doorbell_status;
@@ -1876,6 +2037,35 @@ static void arcmsr_hbd_doorbell_isr(struct AdapterControlBlock *acb)
**************************************************************************
**************************************************************************
*/
+static void arcmsr_hbe_doorbell_isr(struct AdapterControlBlock *acb)
+{
+ u_int32_t doorbell_status, in_doorbell;
+
+ /*
+ *******************************************************************
+ ** Maybe here we need to check wrqbuffer_lock is lock or not
+ ** DOORBELL: din! don!
+ ** check if there are any mail need to pack from firmware
+ *******************************************************************
+ */
+ in_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell);
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /* clear doorbell interrupt */
+ doorbell_status = in_doorbell ^ acb->in_doorbell;
+ if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_WRITE_OK) {
+ arcmsr_iop2drv_data_wrote_handle(acb);
+ }
+ if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_READ_OK) {
+ arcmsr_iop2drv_data_read_handle(acb);
+ }
+ if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) {
+ arcmsr_hbe_message_isr(acb); /* messenger of "driver to iop commands" */
+ }
+ acb->in_doorbell = in_doorbell;
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb)
{
u_int32_t flag_srb;
@@ -2013,6 +2203,34 @@ static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb)
CHIP_REG_READ32(HBD_MessageUnit, 0, outboundlist_interrupt_cause); /*Dummy ioread32 to force pci flush */
}
/*
+**************************************************************************
+**************************************************************************
+*/
+static void arcmsr_hbe_postqueue_isr(struct AdapterControlBlock *acb)
+{
+ u_int16_t error;
+ uint32_t doneq_index;
+ uint16_t cmdSMID;
+
+ /*
+ *****************************************************************************
+ ** areca cdb command done
+ *****************************************************************************
+ */
+ bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+ doneq_index = acb->doneq_index;
+ while ((CHIP_REG_READ32(HBE_MessageUnit, 0, reply_post_producer_index) & 0xFFFF) != doneq_index) {
+ cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID;
+ error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
+ arcmsr_drain_donequeue(acb, (u_int32_t)cmdSMID, error);
+ doneq_index++;
+ if (doneq_index >= acb->completionQ_entry)
+ doneq_index = 0;
+ }
+ acb->doneq_index = doneq_index;
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, reply_post_consumer_index, doneq_index);
+}
+/*
**********************************************************************
**********************************************************************
*/
@@ -2143,6 +2361,37 @@ static void arcmsr_handle_hbd_isr( struct AdapterControlBlock *acb)
// CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable);
}
/*
+**********************************************************************
+**********************************************************************
+*/
+static void arcmsr_handle_hbe_isr( struct AdapterControlBlock *acb)
+{
+ u_int32_t host_interrupt_status;
+ /*
+ *********************************************
+ ** check outbound intstatus
+ *********************************************
+ */
+ host_interrupt_status = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_status) &
+ (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR |
+ ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR);
+ if(!host_interrupt_status) {
+ /*it must be share irq*/
+ return;
+ }
+ do {
+ /* MU doorbell interrupts*/
+ if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR) {
+ arcmsr_hbe_doorbell_isr(acb);
+ }
+ /* MU post queue interrupts*/
+ if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR) {
+ arcmsr_hbe_postqueue_isr(acb);
+ }
+ host_interrupt_status = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_status);
+ } while (host_interrupt_status & (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR));
+}
+/*
******************************************************************************
******************************************************************************
*/
@@ -2161,6 +2410,9 @@ static void arcmsr_interrupt(struct AdapterControlBlock *acb)
case ACB_ADAPTER_TYPE_D:
arcmsr_handle_hbd_isr(acb);
break;
+ case ACB_ADAPTER_TYPE_E:
+ arcmsr_handle_hbe_isr(acb);
+ break;
default:
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)
@@ -2754,10 +3012,10 @@ static u_int8_t arcmsr_seek_cmd2abort(union ccb *abortccb)
if(srb->srb_state == ARCMSR_SRB_START) {
if(srb->pccb == abortccb) {
srb->srb_state = ARCMSR_SRB_ABORTED;
- printf("arcmsr%d:scsi id=%d lun=%d abort srb '%p'"
+ printf("arcmsr%d:scsi id=%d lun=%jx abort srb '%p'"
"outstanding command \n"
, acb->pci_unit, abortccb->ccb_h.target_id
- , abortccb->ccb_h.target_lun, srb);
+ , (uintmax_t)abortccb->ccb_h.target_lun, srb);
arcmsr_polling_srbdone(acb, srb);
/* enable outbound Post Queue, outbound doorbell Interrupt */
arcmsr_enable_allintr(acb, intmask_org);
@@ -2883,12 +3141,6 @@ static void arcmsr_action(struct cam_sim *psim, union ccb *pccb)
}
break;
}
- case XPT_TARGET_IO: {
- /* target mode not yet support vendor specific commands. */
- pccb->ccb_h.status |= CAM_REQ_CMP;
- xpt_done(pccb);
- break;
- }
case XPT_PATH_INQ: {
struct ccb_pathinq *cpi = &pccb->cpi;
@@ -2913,6 +3165,7 @@ static void arcmsr_action(struct cam_sim *psim, union ccb *pccb)
else
cpi->base_transfer_speed = 300000;
if((acb->vendor_device_id == PCIDevVenIDARC1880) ||
+ (acb->vendor_device_id == PCIDevVenIDARC1884) ||
(acb->vendor_device_id == PCIDevVenIDARC1680) ||
(acb->vendor_device_id == PCIDevVenIDARC1214))
{
@@ -2938,7 +3191,6 @@ static void arcmsr_action(struct cam_sim *psim, union ccb *pccb)
pabort_ccb = pccb->cab.abort_ccb;
switch (pabort_ccb->ccb_h.func_code) {
case XPT_ACCEPT_TARGET_IO:
- case XPT_IMMED_NOTIFY:
case XPT_CONT_TARGET_IO:
if(arcmsr_seek_cmd2abort(pabort_ccb)==TRUE) {
pabort_ccb->ccb_h.status |= CAM_REQ_ABORTED;
@@ -2998,6 +3250,7 @@ static void arcmsr_action(struct cam_sim *psim, union ccb *pccb)
cts->protocol = PROTO_SCSI;
if((acb->vendor_device_id == PCIDevVenIDARC1880) ||
+ (acb->vendor_device_id == PCIDevVenIDARC1884) ||
(acb->vendor_device_id == PCIDevVenIDARC1680) ||
(acb->vendor_device_id == PCIDevVenIDARC1214))
{
@@ -3157,6 +3410,20 @@ static void arcmsr_start_hbd_bgrb(struct AdapterControlBlock *acb)
**********************************************************************
**********************************************************************
*/
+static void arcmsr_start_hbe_bgrb(struct AdapterControlBlock *acb)
+{
+ acb->acb_flags |= ACB_F_MSG_START_BGRB;
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB);
+ acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+ if(!arcmsr_hbe_wait_msgint_ready(acb)) {
+ 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) {
@@ -3172,6 +3439,9 @@ static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb)
case ACB_ADAPTER_TYPE_D:
arcmsr_start_hbd_bgrb(acb);
break;
+ case ACB_ADAPTER_TYPE_E:
+ arcmsr_start_hbe_bgrb(acb);
+ break;
}
}
/*
@@ -3210,11 +3480,11 @@ polling_ccb_retry:
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=%d srb='%p'"
+ printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'"
"poll command abort successfully \n"
, acb->pci_unit
, srb->pccb->ccb_h.target_id
- , srb->pccb->ccb_h.target_lun, srb);
+ , (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
arcmsr_srb_complete(srb, 1);
continue;
@@ -3269,11 +3539,11 @@ polling_ccb_retry:
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=%d srb='%p'"
+ printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'"
"poll command abort successfully \n"
, acb->pci_unit
, srb->pccb->ccb_h.target_id
- , srb->pccb->ccb_h.target_lun, srb);
+ , (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
arcmsr_srb_complete(srb, 1);
continue;
@@ -3324,8 +3594,8 @@ polling_ccb_retry:
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=%d srb='%p'poll command abort successfully \n"
- , acb->pci_unit, srb->pccb->ccb_h.target_id, srb->pccb->ccb_h.target_lun, srb);
+ 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;
@@ -3380,8 +3650,8 @@ polling_ccb_retry:
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=%d srb='%p'poll command abort successfully \n"
- , acb->pci_unit, srb->pccb->ccb_h.target_id, srb->pccb->ccb_h.target_lun, srb);
+ 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;
@@ -3395,6 +3665,61 @@ polling_ccb_retry:
}
/*
**********************************************************************
+**
+**********************************************************************
+*/
+static void arcmsr_polling_hbe_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
+{
+ struct CommandControlBlock *srb;
+ u_int32_t poll_srb_done=0, poll_count=0, doneq_index;
+ u_int16_t error, cmdSMID;
+
+polling_ccb_retry:
+ poll_count++;
+ bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+ while(1) {
+ doneq_index = acb->doneq_index;
+ if((CHIP_REG_READ32(HBE_MessageUnit, 0, reply_post_producer_index) & 0xFFFF) == doneq_index) {
+ if(poll_srb_done) {
+ break;/*chip FIFO no ccb for completion already*/
+ } else {
+ UDELAY(25000);
+ if ((poll_count > 100) && (poll_srb != NULL)) {
+ break;
+ }
+ if (acb->srboutstandingcount == 0) {
+ break;
+ }
+ goto polling_ccb_retry;
+ }
+ }
+ cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID;
+ doneq_index++;
+ if (doneq_index >= acb->completionQ_entry)
+ doneq_index = 0;
+ acb->doneq_index = doneq_index;
+ srb = acb->psrb_pool[cmdSMID];
+ error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
+ if (poll_srb != NULL)
+ poll_srb_done = (srb == poll_srb) ? 1:0;
+ if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
+ if(srb->srb_state == ARCMSR_SRB_ABORTED) {
+ 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)
@@ -3416,6 +3741,10 @@ static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct Comma
arcmsr_polling_hbd_srbdone(acb, poll_srb);
}
break;
+ case ACB_ADAPTER_TYPE_E: {
+ arcmsr_polling_hbe_srbdone(acb, poll_srb);
+ }
+ break;
}
}
/*
@@ -3622,6 +3951,58 @@ static void arcmsr_get_hbd_config(struct AdapterControlBlock *acb)
**********************************************************************
**********************************************************************
*/
+static void arcmsr_get_hbe_config(struct AdapterControlBlock *acb)
+{
+ char *acb_firm_model = acb->firm_model;
+ char *acb_firm_version = acb->firm_version;
+ char *acb_device_map = acb->device_map;
+ size_t iop_firm_model = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/
+ size_t iop_firm_version = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/
+ size_t iop_device_map = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
+ int i;
+
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
+ acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+ if(!arcmsr_hbe_wait_msgint_ready(acb)) {
+ 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) {
@@ -3641,6 +4022,10 @@ static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
arcmsr_get_hbd_config(acb);
}
break;
+ case ACB_ADAPTER_TYPE_E: {
+ arcmsr_get_hbe_config(acb);
+ }
+ break;
}
}
/*
@@ -3702,6 +4087,18 @@ static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb)
}
}
break;
+ case ACB_ADAPTER_TYPE_E: {
+ while ((CHIP_REG_READ32(HBE_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBEMU_MESSAGE_FIRMWARE_OK) == 0)
+ {
+ if (timeout++ > 4000) /* (4000*15)/1000 = 60 sec */
+ {
+ printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit);
+ return;
+ }
+ UDELAY(15000); /* wait 15 milli-seconds */
+ }
+ }
+ break;
}
}
/*
@@ -3745,6 +4142,14 @@ static void arcmsr_clear_doorbell_queue_buffer( struct AdapterControlBlock *acb)
}
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;
}
}
/*
@@ -3851,6 +4256,27 @@ static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb)
}
}
break;
+ case ACB_ADAPTER_TYPE_E: {
+ u_int32_t cdb_phyaddr_lo32;
+ cdb_phyaddr_lo32 = srb_phyaddr_lo32 + offsetof(struct CommandControlBlock, arcmsr_cdb);
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG);
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[1], ARCMSR_SIGNATURE_1884);
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[2], cdb_phyaddr_lo32);
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[3], srb_phyaddr_hi32);
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[4], SRB_SIZE);
+ cdb_phyaddr_lo32 = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE;
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[5], cdb_phyaddr_lo32);
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[6], srb_phyaddr_hi32);
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[7], COMPLETION_Q_POOL_SIZE);
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
+ acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
+ if(!arcmsr_hbe_wait_msgint_ready(acb)) {
+ printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit);
+ return FALSE;
+ }
+ }
+ break;
}
return (TRUE);
}
@@ -3860,21 +4286,14 @@ static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb)
*/
static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb)
{
- switch (acb->adapter_type)
+ if (acb->adapter_type == ACB_ADAPTER_TYPE_B)
{
- case ACB_ADAPTER_TYPE_A:
- case ACB_ADAPTER_TYPE_C:
- case ACB_ADAPTER_TYPE_D:
- break;
- case ACB_ADAPTER_TYPE_B: {
- 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;
}
}
/*
@@ -3920,7 +4339,8 @@ static void arcmsr_map_free_srb(void *arg, bus_dma_segment_t *segs, int nseg, in
" srb dmamap bus_dmamap_create error\n", acb->pci_unit);
return;
}
- if((acb->adapter_type == ACB_ADAPTER_TYPE_C) || (acb->adapter_type == ACB_ADAPTER_TYPE_D))
+ if((acb->adapter_type == ACB_ADAPTER_TYPE_C) || (acb->adapter_type == ACB_ADAPTER_TYPE_D)
+ || (acb->adapter_type == ACB_ADAPTER_TYPE_E))
{
srb_tmp->cdb_phyaddr_low = srb_phyaddr;
srb_tmp->cdb_phyaddr_high = (u_int32_t)((srb_phyaddr >> 16) >> 16);
@@ -3928,10 +4348,12 @@ static void arcmsr_map_free_srb(void *arg, bus_dma_segment_t *segs, int nseg, in
else
srb_tmp->cdb_phyaddr_low = srb_phyaddr >> 5;
srb_tmp->acb = acb;
+ srb_tmp->smid = i << 16;
acb->srbworkingQ[i] = acb->psrb_pool[i] = srb_tmp;
srb_phyaddr = srb_phyaddr + SRB_SIZE;
srb_tmp = (struct CommandControlBlock *)((unsigned long)srb_tmp + SRB_SIZE);
}
+ acb->pCompletionQ = (pCompletion_Q)srb_tmp;
acb->vir2phy_offset = (unsigned long)srb_tmp - (unsigned long)srb_phyaddr;
}
/*
@@ -3999,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;
@@ -4147,139 +4575,175 @@ 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_D: {
- struct HBD_MessageUnit0 *phbdmu;
- u_int32_t rid0 = PCIR_BAR(0);
- vm_offset_t mem_base0;
+ 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 *)((unsigned long)acb->uncacheptr+ARCMSR_SRBS_POOL_SIZE);
- phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
- phbdmu->phbdmu = (struct HBD_MessageUnit *)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;
+ }
+ break;
+ case ACB_ADAPTER_TYPE_D: {
+ struct HBD_MessageUnit0 *phbdmu;
+ u_int32_t rid0 = PCIR_BAR(0);
+ vm_offset_t mem_base0;
+
+ acb->sys_res_arcmsr[0] = bus_alloc_resource_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 *)((unsigned long)acb->uncacheptr+ARCMSR_SRBS_POOL_SIZE);
+ phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
+ phbdmu->phbdmu = (struct HBD_MessageUnit *)mem_base0;
+ acb->rid = 0;
+ }
+ break;
+ case ACB_ADAPTER_TYPE_E: {
+ u_int32_t rid0 = PCIR_BAR(1);
+ vm_offset_t mem_base0;
+
+ acb->sys_res_arcmsr[0] = bus_alloc_resource(dev,SYS_RES_MEMORY, &rid0, 0ul, ~0ul, sizeof(struct HBE_MessageUnit), RF_ACTIVE);
+ if(acb->sys_res_arcmsr[0] == NULL) {
+ arcmsr_free_resource(acb);
+ 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->doneq_index = 0;
+ acb->in_doorbell = 0;
+ acb->out_doorbell = 0;
+ acb->rid = 1;
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /*clear interrupt*/
+ CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, ARCMSR_HBEMU_DOORBELL_SYNC); /* synchronize doorbell to 0 */
}
break;
}
@@ -4303,6 +4767,35 @@ static u_int32_t arcmsr_initialize(device_t dev)
arcmsr_iop_init(acb);
return(0);
}
+
+static int arcmsr_setup_msix(struct AdapterControlBlock *acb)
+{
+ int i;
+
+ for (i = 0; i < acb->msix_vectors; i++) {
+ acb->irq_id[i] = acb->rid + i;
+ acb->irqres[i] = bus_alloc_resource_any(acb->pci_dev,
+ SYS_RES_IRQ, &acb->irq_id[i], RF_ACTIVE);
+ if (acb->irqres[i] == NULL) {
+ printf("arcmsr: Can't allocate MSI-X resource\n");
+ goto irq_alloc_failed;
+ }
+ if (bus_setup_intr(acb->pci_dev, acb->irqres[i],
+ INTR_MPSAFE | INTR_TYPE_CAM, NULL, arcmsr_intr_handler,
+ acb, &acb->ih[i])) {
+ printf("arcmsr: Cannot set up MSI-X interrupt handler\n");
+ goto irq_alloc_failed;
+ }
+ }
+ printf("arcmsr: MSI-X INT enabled\n");
+ acb->acb_flags |= ACB_F_MSIX_ENABLED;
+ return TRUE;
+
+irq_alloc_failed:
+ arcmsr_teardown_intr(acb->pci_dev, acb);
+ return FALSE;
+}
+
/*
************************************************************************
************************************************************************
@@ -4314,7 +4807,6 @@ static int arcmsr_attach(device_t dev)
struct ccb_setasync csa;
struct cam_devq *devq; /* Device Queue to use for this SIM */
struct resource *irqres;
- int rid;
if(acb == NULL) {
printf("arcmsr%d: cannot allocate softc\n", unit);
@@ -4325,24 +4817,27 @@ static int arcmsr_attach(device_t dev)
acb->pci_unit = unit;
if(arcmsr_initialize(dev)) {
printf("arcmsr%d: initialize failure!\n", unit);
- arcmsr_mutex_destroy(acb);
- return ENXIO;
+ goto initialize_failed;
}
/* After setting up the adapter, map our interrupt */
- rid = 0;
- irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE);
+ acb->msix_vectors = ARCMSR_NUM_MSIX_VECTORS;
+ if (pci_alloc_msix(dev, &acb->msix_vectors) == 0) {
+ if (arcmsr_setup_msix(acb) == TRUE)
+ goto irqx;
+ }
+ acb->irq_id[0] = acb->rid;
+ irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &acb->irq_id[0], RF_SHAREABLE | RF_ACTIVE);
if(irqres == NULL ||
#if __FreeBSD_version >= 700025
- bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, NULL, arcmsr_intr_handler, acb, &acb->ih)) {
+ bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, NULL, arcmsr_intr_handler, acb, &acb->ih[0])) {
#else
- bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, arcmsr_intr_handler, acb, &acb->ih)) {
+ bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, arcmsr_intr_handler, acb, &acb->ih[0])) {
#endif
- arcmsr_free_resource(acb);
- arcmsr_mutex_destroy(acb);
printf("arcmsr%d: unable to register interrupt handler!\n", unit);
- return ENXIO;
+ goto setup_intr_failed;
}
- acb->irqres = irqres;
+ acb->irqres[0] = irqres;
+irqx:
/*
* Now let the CAM generic SCSI layer find the SCSI devices on
* the bus * start queue to reset to the idle loop. *
@@ -4351,11 +4846,8 @@ static int arcmsr_attach(device_t dev)
*/
devq = cam_simq_alloc(acb->maxOutstanding);
if(devq == NULL) {
- arcmsr_free_resource(acb);
- bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres);
- arcmsr_mutex_destroy(acb);
printf("arcmsr%d: cam_simq_alloc failure!\n", unit);
- return ENXIO;
+ goto simq_alloc_failed;
}
#if __FreeBSD_version >= 700025
acb->psim = cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, &acb->isr_lock, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq);
@@ -4363,12 +4855,8 @@ static int arcmsr_attach(device_t dev)
acb->psim = cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq);
#endif
if(acb->psim == NULL) {
- arcmsr_free_resource(acb);
- bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres);
- cam_simq_free(devq);
- arcmsr_mutex_destroy(acb);
printf("arcmsr%d: cam_sim_alloc failure!\n", unit);
- return ENXIO;
+ goto sim_alloc_failed;
}
ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
#if __FreeBSD_version >= 700044
@@ -4376,21 +4864,12 @@ static int arcmsr_attach(device_t dev)
#else
if(xpt_bus_register(acb->psim, 0) != CAM_SUCCESS) {
#endif
- arcmsr_free_resource(acb);
- bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres);
- cam_sim_free(acb->psim, /*free_devq*/TRUE);
- arcmsr_mutex_destroy(acb);
printf("arcmsr%d: xpt_bus_register failure!\n", unit);
- return ENXIO;
+ goto xpt_bus_failed;
}
if(xpt_create_path(&acb->ppath, /* periph */ NULL, cam_sim_path(acb->psim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
- arcmsr_free_resource(acb);
- bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres);
- xpt_bus_deregister(cam_sim_path(acb->psim));
- cam_sim_free(acb->psim, /* free_simq */ TRUE);
- arcmsr_mutex_destroy(acb);
printf("arcmsr%d: xpt_create_path failure!\n", unit);
- return ENXIO;
+ goto xpt_path_failed;
}
/*
****************************************************
@@ -4414,6 +4893,19 @@ static int arcmsr_attach(device_t dev)
arcmsr_callout_init(&acb->devmap_callout);
callout_reset(&acb->devmap_callout, 60 * hz, arcmsr_polling_devmap, acb);
return (0);
+xpt_path_failed:
+ xpt_bus_deregister(cam_sim_path(acb->psim));
+xpt_bus_failed:
+ cam_sim_free(acb->psim, /* free_simq */ TRUE);
+sim_alloc_failed:
+ cam_simq_free(devq);
+simq_alloc_failed:
+ arcmsr_teardown_intr(dev, acb);
+setup_intr_failed:
+ arcmsr_free_resource(acb);
+initialize_failed:
+ arcmsr_mutex_destroy(acb);
+ return ENXIO;
}
/*
@@ -4470,6 +4962,9 @@ static int arcmsr_probe(device_t dev)
else
type = "SAS 6G";
break;
+ case PCIDevVenIDARC1884:
+ type = "SAS 12G";
+ break;
case PCIDevVenIDARC1214:
case PCIDevVenIDARC1203:
type = "SATA 6G";
@@ -4532,19 +5027,47 @@ static int arcmsr_shutdown(device_t dev)
************************************************************************
************************************************************************
*/
+void arcmsr_teardown_intr(device_t dev, struct AdapterControlBlock *acb)
+{
+ int i;
+
+ if (acb->acb_flags & ACB_F_MSIX_ENABLED) {
+ for (i = 0; i < acb->msix_vectors; i++) {
+ if (acb->ih[i])
+ bus_teardown_intr(dev, acb->irqres[i], acb->ih[i]);
+ if (acb->irqres[i] != NULL)
+ bus_release_resource(dev, SYS_RES_IRQ,
+ acb->irq_id[i], acb->irqres[i]);
+
+ acb->ih[i] = NULL;
+ }
+ pci_release_msi(dev);
+ } else {
+ if (acb->ih[0])
+ bus_teardown_intr(dev, acb->irqres[0], acb->ih[0]);
+ if (acb->irqres[0] != NULL)
+ bus_release_resource(dev, SYS_RES_IRQ,
+ acb->irq_id[0], acb->irqres[0]);
+ acb->ih[0] = NULL;
+ }
+
+}
+/*
+************************************************************************
+************************************************************************
+*/
static int arcmsr_detach(device_t dev)
{
struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev);
int i;
callout_stop(&acb->devmap_callout);
- bus_teardown_intr(dev, acb->irqres, acb->ih);
+ arcmsr_teardown_intr(dev, acb);
arcmsr_shutdown(dev);
arcmsr_free_resource(acb);
for(i=0; (acb->sys_res_arcmsr[i]!=NULL) && (i<2); i++) {
bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(i), acb->sys_res_arcmsr[i]);
}
- bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres);
ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
xpt_async(AC_LOST_DEVICE, acb->ppath, NULL);
xpt_free_path(acb->ppath);
diff --git a/sys/dev/arcmsr/arcmsr.h b/sys/dev/arcmsr/arcmsr.h
index aa613ad..03dd0b0 100644
--- a/sys/dev/arcmsr/arcmsr.h
+++ b/sys/dev/arcmsr/arcmsr.h
@@ -51,6 +51,7 @@
#define ARCMSR_MAX_HBB_POSTQUEUE 264 /* (ARCMSR_MAX_OUTSTANDING_CMD+8) */
#define ARCMSR_MAX_HBD_POSTQUEUE 256
#define ARCMSR_TIMEOUT_DELAY 60 /* in sec */
+#define ARCMSR_NUM_MSIX_VECTORS 4
/*
*********************************************************************
*/
@@ -116,10 +117,12 @@
#define PCI_DEVICE_ID_ARECA_1680 0x1680 /* Device ID */
#define PCI_DEVICE_ID_ARECA_1681 0x1681 /* Device ID */
#define PCI_DEVICE_ID_ARECA_1880 0x1880 /* Device ID */
+#define PCI_DEVICE_ID_ARECA_1884 0x1884 /* Device ID */
#define ARECA_SUB_DEV_ID_1880 0x1880 /* Subsystem Device ID */
#define ARECA_SUB_DEV_ID_1882 0x1882 /* Subsystem Device ID */
#define ARECA_SUB_DEV_ID_1883 0x1883 /* Subsystem Device ID */
+#define ARECA_SUB_DEV_ID_1884 0x1884 /* Subsystem Device ID */
#define ARECA_SUB_DEV_ID_1212 0x1212 /* Subsystem Device ID */
#define ARECA_SUB_DEV_ID_1213 0x1213 /* Subsystem Device ID */
#define ARECA_SUB_DEV_ID_1222 0x1222 /* Subsystem Device ID */
@@ -152,6 +155,7 @@
#define PCIDevVenIDARC1681 0x168117D3 /* Vendor Device ID */
#define PCIDevVenIDARC1880 0x188017D3 /* Vendor Device ID */
#define PCIDevVenIDARC1882 0x188217D3 /* Vendor Device ID */
+#define PCIDevVenIDARC1884 0x188417D3 /* Vendor Device ID */
#ifndef PCIR_BARS
#define PCIR_BARS 0x10
@@ -460,6 +464,26 @@ struct CMD_MESSAGE_FIELD {
/*ARCMSR_HBAMU_MESSAGE_FIRMWARE_OK*/
#define ARCMSR_HBDMU_MESSAGE_FIRMWARE_OK 0x80000000
+/*
+*******************************************************************************
+** SPEC. for Areca HBE adapter
+*******************************************************************************
+*/
+#define ARCMSR_SIGNATURE_1884 0x188417D3
+#define ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR 0x00000001
+#define ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR 0x00000008
+#define ARCMSR_HBEMU_ALL_INTMASKENABLE 0x00000009 /* disable all ISR */
+
+#define ARCMSR_HBEMU_DRV2IOP_DATA_WRITE_OK 0x00000002
+#define ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK 0x00000004
+#define ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE 0x00000008 /* inbound message 0 ready */
+#define ARCMSR_HBEMU_IOP2DRV_DATA_WRITE_OK 0x00000002
+#define ARCMSR_HBEMU_IOP2DRV_DATA_READ_OK 0x00000004
+#define ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE 0x00000008 /* outbound message 0 ready */
+#define ARCMSR_HBEMU_MESSAGE_FIRMWARE_OK 0x80000000 /* ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK */
+/* ARC-1884 doorbell sync */
+#define ARCMSR_HBEMU_DOORBELL_SYNC 0x100
+#define ARCMSR_ARC188X_RESET_ADAPTER 0x00000004
/*
*********************************************************************
** Message Unit structure
@@ -687,6 +711,92 @@ struct HBD_MessageUnit0 {
uint16_t doneq_index;
struct HBD_MessageUnit *phbdmu;
};
+/*
+*********************************************************************
+**
+*********************************************************************
+*/
+struct HBE_MessageUnit {
+ u_int32_t iobound_doorbell; /*0000 0003*/
+ u_int32_t write_sequence_3xxx; /*0004 0007*/
+ u_int32_t host_diagnostic_3xxx; /*0008 000B*/
+ u_int32_t posted_outbound_doorbell; /*000C 000F*/
+ u_int32_t master_error_attribute; /*0010 0013*/
+ u_int32_t master_error_address_low; /*0014 0017*/
+ u_int32_t master_error_address_high; /*0018 001B*/
+ u_int32_t hcb_size; /*001C 001F*/
+ u_int32_t inbound_doorbell; /*0020 0023*/
+ u_int32_t diagnostic_rw_data; /*0024 0027*/
+ u_int32_t diagnostic_rw_address_low; /*0028 002B*/
+ u_int32_t diagnostic_rw_address_high; /*002C 002F*/
+ u_int32_t host_int_status; /*0030 0033 host interrupt status*/
+ u_int32_t host_int_mask; /*0034 0037 host interrupt mask*/
+ u_int32_t dcr_data; /*0038 003B*/
+ u_int32_t dcr_address; /*003C 003F*/
+ u_int32_t inbound_queueport; /*0040 0043 port32 host inbound queue port*/
+ u_int32_t outbound_queueport; /*0044 0047 port32 host outbound queue port*/
+ u_int32_t hcb_pci_address_low; /*0048 004B*/
+ u_int32_t hcb_pci_address_high; /*004C 004F*/
+ u_int32_t iop_int_status; /*0050 0053*/
+ u_int32_t iop_int_mask; /*0054 0057*/
+ u_int32_t iop_inbound_queue_port; /*0058 005B*/
+ u_int32_t iop_outbound_queue_port; /*005C 005F*/
+ u_int32_t inbound_free_list_index; /*0060 0063*/
+ u_int32_t inbound_post_list_index; /*0064 0067*/
+ u_int32_t outbound_free_list_index; /*0068 006B*/
+ u_int32_t outbound_post_list_index; /*006C 006F*/
+ u_int32_t inbound_doorbell_clear; /*0070 0073*/
+ u_int32_t i2o_message_unit_control; /*0074 0077*/
+ u_int32_t last_used_message_source_address_low; /*0078 007B*/
+ u_int32_t last_used_message_source_address_high; /*007C 007F*/
+ u_int32_t pull_mode_data_byte_count[4]; /*0080 008F*/
+ u_int32_t message_dest_address_index; /*0090 0093*/
+ u_int32_t done_queue_not_empty_int_counter_timer; /*0094 0097*/
+ u_int32_t utility_A_int_counter_timer; /*0098 009B*/
+ u_int32_t outbound_doorbell; /*009C 009F*/
+ u_int32_t outbound_doorbell_clear; /*00A0 00A3*/
+ u_int32_t message_source_address_index; /*00A4 00A7*/
+ u_int32_t message_done_queue_index; /*00A8 00AB*/
+ u_int32_t reserved0; /*00AC 00AF*/
+ u_int32_t inbound_msgaddr0; /*00B0 00B3 scratchpad0*/
+ u_int32_t inbound_msgaddr1; /*00B4 00B7 scratchpad1*/
+ u_int32_t outbound_msgaddr0; /*00B8 00BB scratchpad2*/
+ u_int32_t outbound_msgaddr1; /*00BC 00BF scratchpad3*/
+ u_int32_t inbound_queueport_low; /*00C0 00C3 port64 host inbound queue port low*/
+ u_int32_t inbound_queueport_high; /*00C4 00C7 port64 host inbound queue port high*/
+ u_int32_t outbound_queueport_low; /*00C8 00CB port64 host outbound queue port low*/
+ u_int32_t outbound_queueport_high; /*00CC 00CF port64 host outbound queue port high*/
+ u_int32_t iop_inbound_queue_port_low; /*00D0 00D3*/
+ u_int32_t iop_inbound_queue_port_high; /*00D4 00D7*/
+ u_int32_t iop_outbound_queue_port_low; /*00D8 00DB*/
+ u_int32_t iop_outbound_queue_port_high; /*00DC 00DF*/
+ u_int32_t message_dest_queue_port_low; /*00E0 00E3*/
+ u_int32_t message_dest_queue_port_high; /*00E4 00E7*/
+ u_int32_t last_used_message_dest_address_low; /*00E8 00EB*/
+ u_int32_t last_used_message_dest_address_high; /*00EC 00EF*/
+ u_int32_t message_done_queue_base_address_low; /*00F0 00F3*/
+ u_int32_t message_done_queue_base_address_high; /*00F4 00F7*/
+ u_int32_t host_diagnostic; /*00F8 00FB*/
+ u_int32_t write_sequence; /*00FC 00FF*/
+ u_int32_t reserved1[46]; /*0100 01B7*/
+ u_int32_t reply_post_producer_index; /*01B8 01BB*/
+ u_int32_t reply_post_consumer_index; /*01BC 01BF*/
+ u_int32_t reserved2[1936]; /*01C0 1FFF*/
+ u_int32_t message_wbuffer[32]; /*2000 207F*/
+ u_int32_t reserved3[32]; /*2080 20FF*/
+ u_int32_t message_rbuffer[32]; /*2100 217F*/
+ u_int32_t reserved4[32]; /*2180 21FF*/
+ u_int32_t msgcode_rwbuffer[256]; /*2200 23FF*/
+};
+
+typedef struct deliver_completeQ {
+ u_int16_t cmdFlag;
+ u_int16_t cmdSMID;
+ u_int16_t cmdLMID; // reserved (0)
+ u_int16_t cmdFlag2; // reserved (0)
+} DeliverQ, CompletionQ, *pDeliver_Q, *pCompletion_Q;
+
+#define COMPLETION_Q_POOL_SIZE (sizeof(struct deliver_completeQ) * 512 + 128)
/*
*********************************************************************
@@ -700,6 +810,7 @@ struct MessageUnit_UNION
struct HBB_MessageUnit hbbmu;
struct HBC_MessageUnit hbcmu;
struct HBD_MessageUnit0 hbdmu;
+ struct HBE_MessageUnit hbemu;
} muu;
};
/*
@@ -1089,6 +1200,7 @@ struct CommandControlBlock {
u_int16_t srb_state; /* 538-539 */
u_int32_t cdb_phyaddr_high; /* 540-543 */
struct callout ccb_callout;
+ u_int32_t smid;
/* ========================================================== */
};
/* srb_flags */
@@ -1121,10 +1233,11 @@ struct CommandControlBlock {
** Adapter Control Block
*********************************************************************
*/
-#define ACB_ADAPTER_TYPE_A 0x00000001 /* hba I IOP */
-#define ACB_ADAPTER_TYPE_B 0x00000002 /* hbb M IOP */
-#define ACB_ADAPTER_TYPE_C 0x00000004 /* hbc L IOP */
-#define ACB_ADAPTER_TYPE_D 0x00000008 /* hbd M IOP */
+#define ACB_ADAPTER_TYPE_A 0x00000000 /* hba I IOP */
+#define ACB_ADAPTER_TYPE_B 0x00000001 /* hbb M IOP */
+#define ACB_ADAPTER_TYPE_C 0x00000002 /* hbc L IOP */
+#define ACB_ADAPTER_TYPE_D 0x00000003 /* hbd M IOP */
+#define ACB_ADAPTER_TYPE_E 0x00000004 /* hbd L IOP */
struct AdapterControlBlock {
u_int32_t adapter_type; /* adapter A,B..... */
@@ -1144,8 +1257,9 @@ struct AdapterControlBlock {
int pci_unit;
struct resource *sys_res_arcmsr[2];
- struct resource *irqres;
- void *ih; /* interrupt handle */
+ struct resource *irqres[ARCMSR_NUM_MSIX_VECTORS];
+ void *ih[ARCMSR_NUM_MSIX_VECTORS]; /* interrupt handle */
+ int irq_id[ARCMSR_NUM_MSIX_VECTORS];
/* Hooks into the CAM XPT */
struct cam_sim *psim;
@@ -1206,6 +1320,13 @@ struct AdapterControlBlock {
u_int32_t adapter_bus_speed;
u_int32_t maxOutstanding;
u_int16_t sub_device_id;
+ u_int32_t doneq_index;
+ u_int32_t in_doorbell;
+ u_int32_t out_doorbell;
+ u_int32_t completionQ_entry;
+ pCompletion_Q pCompletionQ;
+ int msix_vectors;
+ int rid;
};/* HW_DEVICE_EXTENSION */
/* acb_flags */
#define ACB_F_SCSISTOPADAPTER 0x0001
@@ -1221,6 +1342,7 @@ struct AdapterControlBlock {
#define ACB_F_CAM_DEV_QFRZN 0x0400
#define ACB_F_BUS_HANG_ON 0x0800 /* need hardware reset bus */
#define ACB_F_SRB_FUNCTION_POWER 0x1000
+#define ACB_F_MSIX_ENABLED 0x2000
/* devstate */
#define ARECA_RAID_GONE 0x55
#define ARECA_RAID_GOOD 0xaa
OpenPOWER on IntegriCloud