diff options
author | delphij <delphij@FreeBSD.org> | 2017-07-17 06:28:34 +0000 |
---|---|---|
committer | delphij <delphij@FreeBSD.org> | 2017-07-17 06:28:34 +0000 |
commit | cb9c6059b4d3cfa58d8c5c0da642c9f0e4271c62 (patch) | |
tree | 353db8218babc9dba02ac76bbae64751c4b01321 | |
parent | a9ad15f3911f8b27134fa4315021904ca81a7e04 (diff) | |
download | FreeBSD-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.4 | 4 | ||||
-rw-r--r-- | sys/dev/arcmsr/arcmsr.c | 899 | ||||
-rw-r--r-- | sys/dev/arcmsr/arcmsr.h | 134 |
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 |