summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2010-07-21 18:50:24 +0000
committerdelphij <delphij@FreeBSD.org>2010-07-21 18:50:24 +0000
commit9f0f49f9528dd9a8e493d68f20aa752708a73f2c (patch)
treedb6ecb7bff66cb0f9030c44a5c7c3fa6375ecfcb /sys/dev
parent7ee117f1d70c1044ced4673197a63e5918787e22 (diff)
downloadFreeBSD-src-9f0f49f9528dd9a8e493d68f20aa752708a73f2c.zip
FreeBSD-src-9f0f49f9528dd9a8e493d68f20aa752708a73f2c.tar.gz
Apply vendor version 1.20.00.17.
This version adds support for ARC1880; additionally this version fixed an issue where all devices on a SAS port gets offlined when any device failed on the port [1]. Many thanks to Areca for continuing to support FreeBSD. PR: kern/148502 [1] Submitted by: Ching-Lung Huang <ching2048 areca com tw> Obtained from: Areca Tested by: Rich Ercolani <rercola acm jhu edu> [1] MFC after: 2 weeks
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/arcmsr/arcmsr.c1132
-rw-r--r--sys/dev/arcmsr/arcmsr.h614
2 files changed, 1339 insertions, 407 deletions
diff --git a/sys/dev/arcmsr/arcmsr.c b/sys/dev/arcmsr/arcmsr.c
index 93466eb..418fd11 100644
--- a/sys/dev/arcmsr/arcmsr.c
+++ b/sys/dev/arcmsr/arcmsr.c
@@ -2,15 +2,15 @@
*****************************************************************************************
** O.S : FreeBSD
** FILE NAME : arcmsr.c
-** BY : Erich Chen
+** BY : Erich Chen, Ching Huang
** Description: SCSI RAID Device Driver for
-** ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX) SATA/SAS RAID HOST Adapter
+** ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX/ARC188x) SATA/SAS RAID HOST Adapter
** ARCMSR RAID Host adapter
** [RAID controller:INTEL 331(PCI-X) 341(PCI-EXPRESS) chip set]
******************************************************************************************
************************************************************************
**
-** Copyright (c) 2004-2006 ARECA Co. Ltd.
+** Copyright (c) 2004-2010 ARECA Co. Ltd.
** Erich Chen, Taipei Taiwan All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
@@ -57,6 +57,10 @@
** 1.20.00.15 10/10/2007 Erich Chen support new RAID adapter type ARC120x
** 1.20.00.16 10/10/2009 Erich Chen Bug fix for RAID adapter type ARC120x
** bus_dmamem_alloc() with BUS_DMA_ZERO
+** 1.20.00.17 07/15/2010 Ching Huang Added support ARC1880
+** report CAM_DEV_NOT_THERE instead of CAM_SEL_TIMEOUT when device failed,
+** prevent cam_periph_error removing all LUN devices of one Target id
+** for any one LUN device failed
******************************************************************************************
* $FreeBSD$
*/
@@ -90,6 +94,8 @@
#include <cam/cam.h>
#include <cam/cam_ccb.h>
#include <cam/cam_sim.h>
+#include <cam/cam_periph.h>
+#include <cam/cam_xpt_periph.h>
#include <cam/cam_xpt_sim.h>
#include <cam/cam_debug.h>
#include <cam/scsi/scsi_all.h>
@@ -165,6 +171,8 @@ static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t
static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb);
static int arcmsr_resume(device_t dev);
static int arcmsr_suspend(device_t dev);
+static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb);
+static void arcmsr_polling_devmap(void* arg);
/*
**************************************************************************
**************************************************************************
@@ -191,7 +199,6 @@ static device_method_t arcmsr_methods[]={
DEVMETHOD(device_shutdown, arcmsr_shutdown),
DEVMETHOD(device_suspend, arcmsr_suspend),
DEVMETHOD(device_resume, arcmsr_resume),
-
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_driver_added, bus_generic_driver_added),
{ 0, 0 }
@@ -215,7 +222,7 @@ MODULE_DEPEND(arcmsr, cam, 1, 1, 1);
#ifndef D_VERSION
#define D_VERSION 0x20011966
#endif
- static struct cdevsw arcmsr_cdevsw={
+static struct cdevsw arcmsr_cdevsw={
#if __FreeBSD_version > 502010
.d_version = D_VERSION,
#endif
@@ -228,7 +235,7 @@ MODULE_DEPEND(arcmsr, cam, 1, 1, 1);
#else
#define ARCMSR_CDEV_MAJOR 180
- static struct cdevsw arcmsr_cdevsw = {
+static struct cdevsw arcmsr_cdevsw = {
arcmsr_open, /* open */
arcmsr_close, /* close */
noread, /* read */
@@ -244,7 +251,10 @@ MODULE_DEPEND(arcmsr, cam, 1, 1, 1);
0 /* flags */
};
#endif
-
+/*
+**************************************************************************
+**************************************************************************
+*/
#if __FreeBSD_version < 500005
static int arcmsr_open(dev_t dev, int flags, int fmt, struct proc *proc)
#else
@@ -328,18 +338,21 @@ static u_int32_t arcmsr_disable_allintr( struct AdapterControlBlock *acb)
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
/* disable all outbound interrupt */
- intmask_org=CHIP_REG_READ32(HBA_MessageUnit,
- 0, outbound_intmask)|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE; /* disable outbound message0 int */
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE);
+ intmask_org=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intmask); /* disable outbound message0 int */
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE);
}
break;
case ACB_ADAPTER_TYPE_B: {
/* disable all outbound interrupt */
intmask_org=CHIP_REG_READ32(HBB_DOORBELL,
0, iop2drv_doorbell_mask) & (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); /* disable outbound message0 int */
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, iop2drv_doorbell_mask, 0); /* disable all interrupt */
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell_mask, 0); /* disable all interrupt */
+ }
+ break;
+ case ACB_ADAPTER_TYPE_C: {
+ /* disable all outbound interrupt */
+ intmask_org=CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_mask) ; /* disable outbound message0 int */
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org|ARCMSR_HBCMU_ALL_INTMASKENABLE);
}
break;
}
@@ -356,19 +369,25 @@ static void arcmsr_enable_allintr( struct AdapterControlBlock *acb, u_int32_t in
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
/* enable outbound Post Queue, outbound doorbell Interrupt */
- mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE);
+ mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE);
CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org & mask);
acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff;
}
break;
case ACB_ADAPTER_TYPE_B: {
- /* disable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */
- mask=(ARCMSR_IOP2DRV_DATA_WRITE_OK|ARCMSR_IOP2DRV_DATA_READ_OK|ARCMSR_IOP2DRV_CDB_DONE);
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, iop2drv_doorbell_mask, intmask_org | mask); /*1=interrupt enable, 0=interrupt disable*/
+ /* enable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */
+ mask=(ARCMSR_IOP2DRV_DATA_WRITE_OK|ARCMSR_IOP2DRV_DATA_READ_OK|ARCMSR_IOP2DRV_CDB_DONE|ARCMSR_IOP2DRV_MESSAGE_CMD_DONE);
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell_mask, intmask_org | mask); /*1=interrupt enable, 0=interrupt disable*/
acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f;
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ /* enable outbound Post Queue, outbound doorbell Interrupt */
+ mask=~(ARCMSR_HBCMU_UTILITY_A_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK);
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org & mask);
+ acb->outbound_int_enable= ~(intmask_org & mask) & 0x0000000f;
+ }
+ break;
}
return;
}
@@ -383,10 +402,8 @@ static u_int8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb)
do {
for(Index=0; Index < 100; Index++) {
- if(CHIP_REG_READ32(HBA_MessageUnit,
- 0, outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/
+ if(CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/
return TRUE;
}
UDELAY(10000);
@@ -405,12 +422,29 @@ static u_int8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb)
do {
for(Index=0; Index < 100; Index++) {
- if(CHIP_REG_READ32(HBB_DOORBELL,
- 0, iop2drv_doorbell) & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
+ if(CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
+ return TRUE;
+ }
+ UDELAY(10000);
+ }/*max 1 seconds*/
+ }while(Retries++ < 20);/*max 20 sec*/
+ return FALSE;
+}
+/*
+**********************************************************************
+**********************************************************************
+*/
+static u_int8_t arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock *acb)
+{
+ u_int32_t Index;
+ u_int8_t Retries=0x00;
+
+ do {
+ for(Index=0; Index < 100; Index++) {
+ if(CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) {
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);/*clear interrupt*/
return TRUE;
}
UDELAY(10000);
@@ -426,8 +460,7 @@ static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb)
{
int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
do {
if(arcmsr_hba_wait_msgint_ready(acb)) {
break;
@@ -460,6 +493,25 @@ static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb)
************************************************************************
************************************************************************
*/
+static void arcmsr_flush_hbc_cache(struct AdapterControlBlock *acb)
+{
+ int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */
+
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
+ do {
+ if(arcmsr_hbc_wait_msgint_ready(acb)) {
+ break;
+ } else {
+ retry_count--;
+ }
+ }while(retry_count!=0);
+ return;
+}
+/*
+************************************************************************
+************************************************************************
+*/
static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
{
switch (acb->adapter_type) {
@@ -471,6 +523,10 @@ static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
arcmsr_flush_hbb_cache(acb);
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ arcmsr_flush_hbc_cache(acb);
+ }
+ break;
}
return;
}
@@ -482,10 +538,10 @@ static int arcmsr_suspend(device_t dev)
{
struct AdapterControlBlock *acb = device_get_softc(dev);
- /* disable all outbound interrupt */
- arcmsr_disable_allintr(acb);
/* flush controller */
arcmsr_iop_parking(acb);
+ /* disable all outbound interrupt */
+ arcmsr_disable_allintr(acb);
return(0);
}
/*
@@ -515,12 +571,10 @@ static void arcmsr_async(void *cb_arg, u_int32_t code, struct cam_path *path, vo
case AC_LOST_DEVICE:
target_id=xpt_path_target_id(path);
target_lun=xpt_path_lun_id(path);
- if((target_id > ARCMSR_MAX_TARGETID)
- || (target_lun > ARCMSR_MAX_TARGETLUN)) {
+ if((target_id > ARCMSR_MAX_TARGETID) || (target_lun > ARCMSR_MAX_TARGETLUN)) {
break;
}
- printf("%s:scsi id%d lun%d device lost \n"
- , device_get_name(acb->pci_dev), target_id, target_lun);
+ printf("%s:scsi id=%d lun=%d device lost \n", device_get_name(acb->pci_dev), target_id, target_lun);
break;
default:
break;
@@ -589,8 +643,7 @@ static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb)
{
CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD);
if(!arcmsr_hba_wait_msgint_ready(acb)) {
- printf("arcmsr%d: wait 'abort all outstanding command' timeout \n"
- , acb->pci_unit);
+ printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
}
return;
}
@@ -602,8 +655,20 @@ static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb)
{
CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_ABORT_CMD);
if(!arcmsr_hbb_wait_msgint_ready(acb)) {
- printf("arcmsr%d: wait 'abort all outstanding command' timeout \n"
- , acb->pci_unit);
+ printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
+ }
+ return;
+}
+/*
+*********************************************************************
+*********************************************************************
+*/
+static void arcmsr_abort_hbc_allcmd(struct AdapterControlBlock *acb)
+{
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD);
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
+ if(!arcmsr_hbc_wait_msgint_ready(acb)) {
+ printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
}
return;
}
@@ -622,6 +687,10 @@ static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb)
arcmsr_abort_hbb_allcmd(acb);
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ arcmsr_abort_hbc_allcmd(acb);
+ }
+ break;
}
return;
}
@@ -629,14 +698,13 @@ static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb)
**************************************************************************
**************************************************************************
*/
-static void arcmsr_report_srb_state(struct AdapterControlBlock *acb,
- struct CommandControlBlock *srb, u_int32_t flag_srb)
+static void arcmsr_report_srb_state(struct AdapterControlBlock *acb, struct CommandControlBlock *srb, u_int16_t error)
{
int target, lun;
target=srb->pccb->ccb_h.target_id;
lun=srb->pccb->ccb_h.target_lun;
- if((flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR)==0) {
+ if(error == FALSE) {
if(acb->devstate[target][lun]==ARECA_RAID_GONE) {
acb->devstate[target][lun]=ARECA_RAID_GOOD;
}
@@ -646,12 +714,10 @@ static void arcmsr_report_srb_state(struct AdapterControlBlock *acb,
switch(srb->arcmsr_cdb.DeviceStatus) {
case ARCMSR_DEV_SELECT_TIMEOUT: {
if(acb->devstate[target][lun]==ARECA_RAID_GOOD) {
- printf( "arcmsr%d: select timeout"
- ", raid volume was kicked out \n"
- , acb->pci_unit);
+ printf( "arcmsr%d: Target=%x, Lun=%x, selection timeout, raid volume was lost\n", acb->pci_unit, target, lun);
}
acb->devstate[target][lun]=ARECA_RAID_GONE;
- srb->pccb->ccb_h.status |= CAM_SEL_TIMEOUT;
+ srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
arcmsr_srb_complete(srb, 1);
}
break;
@@ -669,11 +735,8 @@ static void arcmsr_report_srb_state(struct AdapterControlBlock *acb,
}
break;
default:
- printf("arcmsr%d: scsi id=%d lun=%d"
- "isr get command error done,"
- "but got unknow DeviceStatus=0x%x \n"
- , acb->pci_unit, target, lun
- ,srb->arcmsr_cdb.DeviceStatus);
+ printf("arcmsr%d: scsi id=%d lun=%d isr got command error done,but got unknow DeviceStatus=0x%x \n"
+ , acb->pci_unit, target, lun ,srb->arcmsr_cdb.DeviceStatus);
acb->devstate[target][lun]=ARECA_RAID_GONE;
srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY;
/*unknow error or crc error just for retry*/
@@ -687,29 +750,34 @@ static void arcmsr_report_srb_state(struct AdapterControlBlock *acb,
**************************************************************************
**************************************************************************
*/
-static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t flag_srb)
+static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t flag_srb, u_int16_t error)
{
struct CommandControlBlock *srb;
/* check if command done with no error*/
- srb=(struct CommandControlBlock *)
- (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
+ switch (acb->adapter_type) {
+ case ACB_ADAPTER_TYPE_C:
+ srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFF0));/*frame must be 32 bytes aligned*/
+ break;
+ case ACB_ADAPTER_TYPE_A:
+ case ACB_ADAPTER_TYPE_B:
+ default:
+ srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
+ break;
+ }
if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) {
if(srb->startdone==ARCMSR_SRB_ABORTED) {
- printf("arcmsr%d: srb='%p' isr got aborted command \n"
- , acb->pci_unit, srb);
+ printf("arcmsr%d: srb='%p' isr got aborted command \n", acb->pci_unit, srb);
srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
arcmsr_srb_complete(srb, 1);
return;
}
printf("arcmsr%d: isr get an illegal srb command done"
- "acb='%p' srb='%p' srbacb='%p' startdone=0x%x"
- "srboutstandingcount=%d \n",
- acb->pci_unit, acb, srb, srb->acb,
- srb->startdone, acb->srboutstandingcount);
+ "acb='%p' srb='%p' srbacb='%p' startdone=0x%xsrboutstandingcount=%d \n",
+ acb->pci_unit, acb, srb, srb->acb,srb->startdone, acb->srboutstandingcount);
return;
}
- arcmsr_report_srb_state(acb, srb, flag_srb);
+ arcmsr_report_srb_state(acb, srb, error);
return;
}
/*
@@ -720,20 +788,18 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
{
int i=0;
u_int32_t flag_srb;
+ u_int16_t error;
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
u_int32_t outbound_intstatus;
/*clear and abort all outbound posted Q*/
- outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit,
- 0, outbound_intstatus) & acb->outbound_int_enable;
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/
- while(((flag_srb=CHIP_REG_READ32(HBA_MessageUnit,
- 0, outbound_queueport)) != 0xFFFFFFFF)
- && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) {
- arcmsr_drain_donequeue(acb, flag_srb);
+ outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable;
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/
+ while(((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_queueport)) != 0xFFFFFFFF) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) {
+ error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
+ arcmsr_drain_donequeue(acb, flag_srb, error);
}
}
break;
@@ -741,13 +807,12 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu;
/*clear all outbound posted Q*/
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, iop2drv_doorbell,
- ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */
for(i=0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) {
if((flag_srb=phbbmu->done_qbuffer[i])!=0) {
phbbmu->done_qbuffer[i]=0;
- arcmsr_drain_donequeue(acb, flag_srb);
+ error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
+ arcmsr_drain_donequeue(acb, flag_srb, error);
}
phbbmu->post_qbuffer[i]=0;
}/*drain reply FIFO*/
@@ -755,6 +820,15 @@ static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
phbbmu->postq_index=0;
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+
+ while((CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) {
+ flag_srb=CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low);
+ error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE;
+ arcmsr_drain_donequeue(acb, flag_srb, error);
+ }
+ }
+ break;
}
return;
}
@@ -873,7 +947,10 @@ static void arcmsr_build_srb(struct CommandControlBlock *srb,
if( arccdbsize > 256) {
arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_SGL_BSIZE;
}
+ } else {
+ arcmsr_cdb->DataLength = 0;
}
+ srb->arc_cdb_size=arccdbsize;
return;
}
/*
@@ -885,19 +962,16 @@ static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandContr
u_int32_t cdb_shifted_phyaddr=(u_int32_t) srb->cdb_shifted_phyaddr;
struct ARCMSR_CDB * arcmsr_cdb=(struct ARCMSR_CDB *)&srb->arcmsr_cdb;
- bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap,
- (srb->srb_flags & SRB_FLAG_WRITE) ? BUS_DMASYNC_POSTWRITE:BUS_DMASYNC_POSTREAD);
+ bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, (srb->srb_flags & SRB_FLAG_WRITE) ? BUS_DMASYNC_POSTWRITE:BUS_DMASYNC_POSTREAD);
atomic_add_int(&acb->srboutstandingcount, 1);
srb->startdone=ARCMSR_SRB_START;
+
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) {
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, inbound_queueport,
- cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE);
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE);
} else {
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, inbound_queueport, cdb_shifted_phyaddr);
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_shifted_phyaddr);
}
}
break;
@@ -909,17 +983,32 @@ static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandContr
ending_index=((index+1)%ARCMSR_MAX_HBB_POSTQUEUE);
phbbmu->post_qbuffer[ending_index]=0;
if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) {
- phbbmu->post_qbuffer[index]=
- cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE;
+ phbbmu->post_qbuffer[index]= cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE;
} else {
- phbbmu->post_qbuffer[index]=
- cdb_shifted_phyaddr;
+ phbbmu->post_qbuffer[index]= cdb_shifted_phyaddr;
}
index++;
index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */
phbbmu->postq_index=index;
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED);
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED);
+ }
+ break;
+ case ACB_ADAPTER_TYPE_C:
+ {
+ u_int32_t ccb_post_stamp, arc_cdb_size, cdb_phyaddr_hi32;
+
+ arc_cdb_size=(srb->arc_cdb_size>0x300)?0x300:srb->arc_cdb_size;
+ ccb_post_stamp=(cdb_shifted_phyaddr | ((arc_cdb_size-1) >> 6) | 1);
+ cdb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high;
+ if(cdb_phyaddr_hi32)
+ {
+ CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_high, cdb_phyaddr_hi32);
+ CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp);
+ }
+ else
+ {
+ CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp);
+ }
}
break;
}
@@ -946,6 +1035,12 @@ static struct QBUFFER * arcmsr_get_iop_rqbuffer( struct AdapterControlBlock *acb
qbuffer=(struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_rbuffer;
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ struct HBC_MessageUnit *phbcmu=(struct HBC_MessageUnit *)acb->pmu;
+
+ qbuffer=(struct QBUFFER *)&phbcmu->message_rbuffer;
+ }
+ break;
}
return(qbuffer);
}
@@ -970,6 +1065,12 @@ static struct QBUFFER * arcmsr_get_iop_wqbuffer( struct AdapterControlBlock *acb
qbuffer=(struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_wbuffer;
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ struct HBC_MessageUnit *phbcmu=(struct HBC_MessageUnit *)acb->pmu;
+
+ qbuffer=(struct QBUFFER *)&phbcmu->message_wbuffer;
+ }
+ break;
}
return(qbuffer);
}
@@ -982,16 +1083,18 @@ static void arcmsr_iop_message_read(struct AdapterControlBlock *acb)
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
/* let IOP know data has been read */
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
}
break;
case ACB_ADAPTER_TYPE_B: {
/* let IOP know data has been read */
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK);
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK);
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ /* let IOP know data has been read */
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK);
+ }
}
return;
}
@@ -1007,8 +1110,7 @@ static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb)
** push inbound doorbell tell iop, driver data write ok
** and wait reply on next hwinterrupt for next Qbuffer post
*/
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK);
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK);
}
break;
case ACB_ADAPTER_TYPE_B: {
@@ -1016,8 +1118,15 @@ static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb)
** push inbound doorbell tell iop, driver data write ok
** and wait reply on next hwinterrupt for next Qbuffer post
*/
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_WRITE_OK);
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_WRITE_OK);
+ }
+ break;
+ case ACB_ADAPTER_TYPE_C: {
+ /*
+ ** push inbound doorbell tell iop, driver data write ok
+ ** and wait reply on next hwinterrupt for next Qbuffer post
+ */
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK);
}
break;
}
@@ -1064,7 +1173,7 @@ static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb)
CHIP_REG_WRITE32(HBA_MessageUnit,
0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
if(!arcmsr_hba_wait_msgint_ready(acb)) {
- printf("arcmsr%d: wait 'stop adapter rebulid' timeout \n"
+ printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n"
, acb->pci_unit);
}
return;
@@ -1079,7 +1188,7 @@ static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb)
CHIP_REG_WRITE32(HBB_DOORBELL,
0, drv2iop_doorbell, ARCMSR_MESSAGE_STOP_BGRB);
if(!arcmsr_hbb_wait_msgint_ready(acb)) {
- printf( "arcmsr%d: wait 'stop adapter rebulid' timeout \n"
+ printf( "arcmsr%d: wait 'stop adapter background rebulid' timeout \n"
, acb->pci_unit);
}
return;
@@ -1088,6 +1197,20 @@ static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb)
************************************************************************
************************************************************************
*/
+static void arcmsr_stop_hbc_bgrb(struct AdapterControlBlock *acb)
+{
+ acb->acb_flags &=~ACB_F_MSG_START_BGRB;
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
+ if(!arcmsr_hbc_wait_msgint_ready(acb)) {
+ printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit);
+ }
+ return;
+}
+/*
+************************************************************************
+************************************************************************
+*/
static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
{
switch (acb->adapter_type) {
@@ -1099,6 +1222,10 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
arcmsr_stop_hbb_bgrb(acb);
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ arcmsr_stop_hbc_bgrb(acb);
+ }
+ break;
}
return;
}
@@ -1121,18 +1248,6 @@ static void arcmsr_poll(struct cam_sim * psim)
return;
}
/*
-**********************************************************************
-**********************************************************************
-*/
-static void arcmsr_intr_handler(void *arg)
-{
- struct AdapterControlBlock *acb=(struct AdapterControlBlock *)arg;
-
- ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
- arcmsr_interrupt(acb);
- ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
-}
-/*
**************************************************************************
**************************************************************************
*/
@@ -1210,6 +1325,187 @@ static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb)
}
return;
}
+
+static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb)
+{
+/*
+ if (ccb->ccb_h.status != CAM_REQ_CMP)
+ printf("arcmsr_rescanLun_cb: Rescan Target=%x, lun=%x, failure status=%x\n",ccb->ccb_h.target_id,ccb->ccb_h.target_lun,ccb->ccb_h.status);
+ else
+ printf("arcmsr_rescanLun_cb: Rescan lun successfully!\n");
+*/
+ xpt_free_path(ccb->ccb_h.path);
+ xpt_free_ccb(ccb);
+}
+
+static void arcmsr_rescan_lun(struct AdapterControlBlock *acb, int target, int lun)
+{
+ struct cam_path *path;
+ union ccb *ccb;
+
+ if ((ccb = (union ccb *)xpt_alloc_ccb_nowait()) == NULL)
+ return;
+ if (xpt_create_path(&path, xpt_periph, cam_sim_path(acb->psim), target, lun) != CAM_REQ_CMP)
+ {
+ xpt_free_ccb(ccb);
+ return;
+ }
+/* printf("arcmsr_rescan_lun: Rescan Target=%x, Lun=%x\n", target, lun); */
+ bzero(ccb, sizeof(union ccb));
+ xpt_setup_ccb(&ccb->ccb_h, path, 5);
+ ccb->ccb_h.func_code = XPT_SCAN_LUN;
+ ccb->ccb_h.cbfcnp = arcmsr_rescanLun_cb;
+ ccb->crcn.flags = CAM_FLAG_NONE;
+ xpt_action(ccb);
+ return;
+}
+
+
+static void arcmsr_abort_dr_ccbs(struct AdapterControlBlock *acb, int target, int lun)
+{
+ struct CommandControlBlock *srb;
+ u_int32_t intmask_org;
+ int i;
+
+ ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
+ /* disable all outbound interrupts */
+ intmask_org = arcmsr_disable_allintr(acb);
+ for (i = 0; i < ARCMSR_MAX_FREESRB_NUM; i++)
+ {
+ srb = acb->psrb_pool[i];
+ if (srb->startdone == ARCMSR_SRB_START)
+ {
+ if((target == srb->pccb->ccb_h.target_id) && (lun == srb->pccb->ccb_h.target_lun))
+ {
+ srb->startdone = ARCMSR_SRB_ABORTED;
+ srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
+ arcmsr_srb_complete(srb, 1);
+ }
+ }
+ }
+ /* enable outbound Post Queue, outbound doorbell Interrupt */
+ arcmsr_enable_allintr(acb, intmask_org);
+ ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
+}
+
+
+/*
+**************************************************************************
+**************************************************************************
+*/
+static void arcmsr_dr_handle(struct AdapterControlBlock *acb) {
+ u_int32_t devicemap;
+ u_int32_t target, lun;
+ u_int32_t deviceMapCurrent[4]={0};
+ u_int8_t *pDevMap;
+
+ switch (acb->adapter_type) {
+ case ACB_ADAPTER_TYPE_A:
+ devicemap = offsetof(struct HBA_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
+ for (target= 0; target < 4; target++)
+ {
+ deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap);
+ devicemap += 4;
+ }
+ break;
+
+ case ACB_ADAPTER_TYPE_B:
+ devicemap = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
+ for (target= 0; target < 4; target++)
+ {
+ deviceMapCurrent[target]=bus_space_read_4(acb->btag[1], acb->bhandle[1], devicemap);
+ devicemap += 4;
+ }
+ break;
+
+ case ACB_ADAPTER_TYPE_C:
+ devicemap = offsetof(struct HBC_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
+ for (target= 0; target < 4; target++)
+ {
+ deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap);
+ devicemap += 4;
+ }
+ break;
+ }
+ if(acb->acb_flags & ACB_F_BUS_HANG_ON)
+ {
+ acb->acb_flags &= ~ACB_F_BUS_HANG_ON;
+ }
+ /*
+ ** adapter posted CONFIG message
+ ** copy the new map, note if there are differences with the current map
+ */
+ pDevMap = (u_int8_t *)&deviceMapCurrent[0];
+ for (target= 0; target < ARCMSR_MAX_TARGETID - 1; target++)
+ {
+ if (*pDevMap != acb->device_map[target])
+ {
+ u_int8_t difference, bit_check;
+
+ difference= *pDevMap ^ acb->device_map[target];
+ for(lun=0; lun < ARCMSR_MAX_TARGETLUN; lun++)
+ {
+ bit_check=(1 << lun); /*check bit from 0....31*/
+ if(difference & bit_check)
+ {
+ if(acb->device_map[target] & bit_check)
+ {/* unit departed */
+ printf("arcmsr_dr_handle: Target=%x, lun=%x, GONE!!!\n",target,lun);
+ arcmsr_abort_dr_ccbs(acb, target, lun);
+ arcmsr_rescan_lun(acb, target, lun);
+ acb->devstate[target][lun] = ARECA_RAID_GONE;
+ }
+ else
+ {/* unit arrived */
+ printf("arcmsr_dr_handle: Target=%x, lun=%x, ARRIVING!!!\n",target,lun);
+ arcmsr_rescan_lun(acb, target, lun);
+ acb->devstate[target][lun] = ARECA_RAID_GOOD;
+ }
+ }
+ }
+/* printf("arcmsr_dr_handle: acb->device_map[%x]=0x%x, deviceMapCurrent[%x]=%x\n",target,acb->device_map[target],target,*pDevMap); */
+ acb->device_map[target]= *pDevMap;
+ }
+ pDevMap++;
+ }
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
+static void arcmsr_hba_message_isr(struct AdapterControlBlock *acb) {
+ u_int32_t outbound_message;
+
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);
+ outbound_message = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[0]);
+ if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
+ arcmsr_dr_handle( acb );
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
+static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) {
+ u_int32_t outbound_message;
+
+ /* clear interrupts */
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);
+ outbound_message = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0]);
+ if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
+ arcmsr_dr_handle( acb );
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
+static void arcmsr_hbc_message_isr(struct AdapterControlBlock *acb) {
+ u_int32_t outbound_message;
+
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);
+ outbound_message = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[0]);
+ if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
+ arcmsr_dr_handle( acb );
+}
/*
**************************************************************************
**************************************************************************
@@ -1241,9 +1537,38 @@ static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb)
**************************************************************************
**************************************************************************
*/
+static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb)
+{
+ u_int32_t outbound_doorbell;
+
+ /*
+ *******************************************************************
+ ** Maybe here we need to check wrqbuffer_lock is lock or not
+ ** DOORBELL: din! don!
+ ** check if there are any mail need to pack from firmware
+ *******************************************************************
+ */
+ outbound_doorbell=CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell);
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell); /* clear doorbell interrupt */
+ if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) {
+ arcmsr_iop2drv_data_wrote_handle(acb);
+ }
+ if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) {
+ arcmsr_iop2drv_data_read_handle(acb);
+ }
+ if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) {
+ arcmsr_hbc_message_isr(acb); /* messenger of "driver to iop commands" */
+ }
+ return;
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb)
{
u_int32_t flag_srb;
+ u_int16_t error;
/*
*****************************************************************************
@@ -1255,7 +1580,8 @@ static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb)
while((flag_srb=CHIP_REG_READ32(HBA_MessageUnit,
0, outbound_queueport)) != 0xFFFFFFFF) {
/* check if command done with no error*/
- arcmsr_drain_donequeue(acb, flag_srb);
+ error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
+ arcmsr_drain_donequeue(acb, flag_srb, error);
} /*drain reply FIFO*/
return;
}
@@ -1268,6 +1594,7 @@ static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb)
struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu;
u_int32_t flag_srb;
int index;
+ u_int16_t error;
/*
*****************************************************************************
@@ -1283,7 +1610,38 @@ static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb)
index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */
phbbmu->doneq_index=index;
/* check if command done with no error*/
- arcmsr_drain_donequeue(acb, flag_srb);
+ error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
+ arcmsr_drain_donequeue(acb, flag_srb, error);
+ } /*drain reply FIFO*/
+ return;
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
+static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb)
+{
+ u_int32_t flag_srb,throttling=0;
+ u_int16_t error;
+
+ /*
+ *****************************************************************************
+ ** areca cdb command done
+ *****************************************************************************
+ */
+ bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+
+ while(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) {
+
+ flag_srb=CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low);
+ /* check if command done with no error*/
+ error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE;
+ arcmsr_drain_donequeue(acb, flag_srb, error);
+ if(throttling==ARCMSR_HBC_ISR_THROTTLING_LEVEL) {
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING);
+ break;
+ }
+ throttling++;
} /*drain reply FIFO*/
return;
}
@@ -1299,14 +1657,12 @@ static void arcmsr_handle_hba_isr( struct AdapterControlBlock *acb)
** check outbound intstatus
*********************************************
*/
- outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit,
- 0, outbound_intstatus) & acb->outbound_int_enable;
+ outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable;
if(!outbound_intstatus) {
/*it must be share irq*/
return;
}
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/
/* MU doorbell interrupts*/
if(outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) {
arcmsr_hba_doorbell_isr(acb);
@@ -1315,6 +1671,9 @@ static void arcmsr_handle_hba_isr( struct AdapterControlBlock *acb)
if(outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) {
arcmsr_hba_postqueue_isr(acb);
}
+ if(outbound_intstatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
+ arcmsr_hba_message_isr(acb);
+ }
return;
}
/*
@@ -1348,6 +1707,36 @@ static void arcmsr_handle_hbb_isr( struct AdapterControlBlock *acb)
if(outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) {
arcmsr_hbb_postqueue_isr(acb);
}
+ if(outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
+ arcmsr_hbb_message_isr(acb);
+ }
+ return;
+}
+/*
+**********************************************************************
+**********************************************************************
+*/
+static void arcmsr_handle_hbc_isr( struct AdapterControlBlock *acb)
+{
+ u_int32_t host_interrupt_status;
+ /*
+ *********************************************
+ ** check outbound intstatus
+ *********************************************
+ */
+ host_interrupt_status=CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status);
+ if(!host_interrupt_status) {
+ /*it must be share irq*/
+ return;
+ }
+ /* MU doorbell interrupts*/
+ if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) {
+ arcmsr_hbc_doorbell_isr(acb);
+ }
+ /* MU post queue interrupts*/
+ if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) {
+ arcmsr_hbc_postqueue_isr(acb);
+ }
return;
}
/*
@@ -1363,6 +1752,9 @@ static void arcmsr_interrupt(struct AdapterControlBlock *acb)
case ACB_ADAPTER_TYPE_B:
arcmsr_handle_hbb_isr(acb);
break;
+ case ACB_ADAPTER_TYPE_C:
+ arcmsr_handle_hbc_isr(acb);
+ break;
default:
printf("arcmsr%d: interrupt service,"
" unknow adapter type =%d\n", acb->pci_unit, acb->adapter_type);
@@ -1371,17 +1763,61 @@ static void arcmsr_interrupt(struct AdapterControlBlock *acb)
return;
}
/*
+**********************************************************************
+**********************************************************************
+*/
+static void arcmsr_intr_handler(void *arg)
+{
+ struct AdapterControlBlock *acb=(struct AdapterControlBlock *)arg;
+
+ ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
+ arcmsr_interrupt(acb);
+ ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
+}
+/*
+******************************************************************************
+******************************************************************************
+*/
+static void arcmsr_polling_devmap(void* arg)
+{
+ struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg;
+ switch (acb->adapter_type) {
+ case ACB_ADAPTER_TYPE_A:
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
+ break;
+
+ case ACB_ADAPTER_TYPE_B:
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG);
+ break;
+
+ case ACB_ADAPTER_TYPE_C:
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
+ break;
+ }
+
+ if((acb->acb_flags & ACB_F_SCSISTOPADAPTER) == 0)
+ {
+ callout_reset(&acb->devmap_callout, 5 * hz, arcmsr_polling_devmap, acb); /* polling per 5 seconds */
+ }
+}
+
+/*
*******************************************************************************
**
*******************************************************************************
*/
static void arcmsr_iop_parking(struct AdapterControlBlock *acb)
{
+ u_int32_t intmask_org;
+
if(acb!=NULL) {
/* stop adapter background rebuild */
if(acb->acb_flags & ACB_F_MSG_START_BGRB) {
+ intmask_org = arcmsr_disable_allintr(acb);
arcmsr_stop_adapter_bgrb(acb);
arcmsr_flush_adapter_cache(acb);
+ arcmsr_enable_allintr(acb, intmask_org);
}
}
}
@@ -1838,7 +2274,7 @@ static void arcmsr_executesrb(void *arg, bus_dma_segment_t *dm_segs, int nseg, i
block_cmd=pccb->csio.cdb_io.cdb_bytes[0] & 0x0f;
if(block_cmd==0x08 || block_cmd==0x0a) {
- printf("arcmsr%d:block 'read/write' command"
+ printf("arcmsr%d:block 'read/write' command "
"with gone raid volume Cmd=%2x, TargetId=%d, Lun=%d \n"
, acb->pci_unit, block_cmd, target, lun);
pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
@@ -1862,6 +2298,9 @@ static void arcmsr_executesrb(void *arg, bus_dma_segment_t *dm_segs, int nseg, i
}
pccb->ccb_h.status |= CAM_SIM_QUEUED;
arcmsr_build_srb(srb, dm_segs, nseg);
+/* if (pccb->ccb_h.timeout != CAM_TIME_INFINITY)
+ callout_reset(&srb->ccb_callout, (pccb->ccb_h.timeout * hz) / 1000, arcmsr_srb_timeout, srb);
+*/
arcmsr_post_srb(acb, srb);
return;
}
@@ -2242,8 +2681,7 @@ static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb)
static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb)
{
acb->acb_flags |= ACB_F_MSG_START_BGRB;
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, drv2iop_doorbell, ARCMSR_MESSAGE_START_BGRB);
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_START_BGRB);
if(!arcmsr_hbb_wait_msgint_ready(acb)) {
printf( "arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit);
}
@@ -2253,6 +2691,20 @@ static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb)
**********************************************************************
**********************************************************************
*/
+static void arcmsr_start_hbc_bgrb(struct AdapterControlBlock *acb)
+{
+ acb->acb_flags |= ACB_F_MSG_START_BGRB;
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB);
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
+ if(!arcmsr_hbc_wait_msgint_ready(acb)) {
+ printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit);
+ }
+ return;
+}
+/*
+**********************************************************************
+**********************************************************************
+*/
static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb)
{
switch (acb->adapter_type) {
@@ -2262,6 +2714,9 @@ static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb)
case ACB_ADAPTER_TYPE_B:
arcmsr_start_hbb_bgrb(acb);
break;
+ case ACB_ADAPTER_TYPE_C:
+ arcmsr_start_hbc_bgrb(acb);
+ break;
}
return;
}
@@ -2274,13 +2729,12 @@ static void arcmsr_polling_hba_srbdone(struct AdapterControlBlock *acb, struct C
{
struct CommandControlBlock *srb;
u_int32_t flag_srb, outbound_intstatus, poll_srb_done=0, poll_count=0;
+ u_int16_t error;
polling_ccb_retry:
poll_count++;
- outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit,
- 0, outbound_intstatus) & acb->outbound_int_enable;
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/
+ outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable;
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus); /*clear interrupt*/
bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
while(1) {
if((flag_srb=CHIP_REG_READ32(HBA_MessageUnit,
@@ -2289,15 +2743,16 @@ polling_ccb_retry:
break;/*chip FIFO no ccb for completion already*/
} else {
UDELAY(25000);
- if(poll_count > 100) {
+ if ((poll_count > 100) && (poll_srb != NULL)) {
break;
}
goto polling_ccb_retry;
}
}
- /* check ifcommand done with no error*/
+ /* check if command done with no error*/
srb=(struct CommandControlBlock *)
(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
+ error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
poll_srb_done = (srb==poll_srb) ? 1:0;
if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) {
if(srb->startdone==ARCMSR_SRB_ABORTED) {
@@ -2316,7 +2771,7 @@ polling_ccb_retry:
, srb, acb->srboutstandingcount);
continue;
}
- arcmsr_report_srb_state(acb, srb, flag_srb);
+ arcmsr_report_srb_state(acb, srb, error);
} /*drain reply FIFO*/
return;
}
@@ -2331,6 +2786,7 @@ static void arcmsr_polling_hbb_srbdone(struct AdapterControlBlock *acb, struct C
struct CommandControlBlock *srb;
u_int32_t flag_srb, poll_srb_done=0, poll_count=0;
int index;
+ u_int16_t error;
polling_ccb_retry:
poll_count++;
@@ -2344,7 +2800,7 @@ polling_ccb_retry:
break;/*chip FIFO no ccb for completion already*/
} else {
UDELAY(25000);
- if(poll_count > 100) {
+ if ((poll_count > 100) && (poll_srb != NULL)) {
break;
}
goto polling_ccb_retry;
@@ -2357,6 +2813,7 @@ polling_ccb_retry:
/* check if command done with no error*/
srb=(struct CommandControlBlock *)
(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
+ error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
poll_srb_done = (srb==poll_srb) ? 1:0;
if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) {
if(srb->startdone==ARCMSR_SRB_ABORTED) {
@@ -2375,7 +2832,58 @@ polling_ccb_retry:
, srb, acb->srboutstandingcount);
continue;
}
- arcmsr_report_srb_state(acb, srb, flag_srb);
+ arcmsr_report_srb_state(acb, srb, error);
+ } /*drain reply FIFO*/
+ return;
+}
+/*
+**********************************************************************
+**
+**********************************************************************
+*/
+static void arcmsr_polling_hbc_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
+{
+ struct CommandControlBlock *srb;
+ u_int32_t flag_srb, poll_srb_done=0, poll_count=0;
+ u_int16_t error;
+
+polling_ccb_retry:
+ poll_count++;
+ bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+ while(1) {
+ if(!(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR)) {
+ 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;
+ }
+ }
+ flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low);
+ /* check if command done with no error*/
+ srb=(struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFF0));/*frame must be 32 bytes aligned*/
+ error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE;
+ if (poll_srb != NULL)
+ poll_srb_done = (srb==poll_srb) ? 1:0;
+ if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) {
+ if(srb->startdone==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);
+ 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*/
return;
}
@@ -2394,6 +2902,10 @@ static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct Comma
arcmsr_polling_hbb_srbdone(acb, poll_srb);
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ arcmsr_polling_hbc_srbdone(acb, poll_srb);
+ }
+ break;
}
}
/*
@@ -2404,14 +2916,15 @@ static void arcmsr_get_hba_config(struct AdapterControlBlock *acb)
{
char *acb_firm_model=acb->firm_model;
char *acb_firm_version=acb->firm_version;
- size_t iop_firm_model=offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[15]); /*firm_model,15,60-67*/
- size_t iop_firm_version=offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[17]); /*firm_version,17,68-83*/
+ char *acb_device_map = acb->device_map;
+ size_t iop_firm_model=offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/
+ size_t iop_firm_version=offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/
+ size_t iop_device_map = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
int i;
CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
if(!arcmsr_hba_wait_msgint_ready(acb)) {
- printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n"
- , acb->pci_unit);
+ printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
}
i=0;
while(i<8) {
@@ -2427,16 +2940,19 @@ static void arcmsr_get_hba_config(struct AdapterControlBlock *acb)
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 \n", acb->pci_unit, ARCMSR_DRIVER_VERSION);
printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version);
- acb->firm_request_len=CHIP_REG_READ32(HBA_MessageUnit,
- 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/
- acb->firm_numbers_queue=CHIP_REG_READ32(HBA_MessageUnit,
- 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/
- acb->firm_sdram_size=CHIP_REG_READ32(HBA_MessageUnit,
- 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/
- acb->firm_ide_channels=CHIP_REG_READ32(HBA_MessageUnit,
- 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/
+ acb->firm_request_len=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/
+ acb->firm_numbers_queue=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/
+ acb->firm_sdram_size=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/
+ acb->firm_ide_channels=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/
+ acb->firm_cfg_version=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */
return;
}
/*
@@ -2447,17 +2963,15 @@ static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb)
{
char *acb_firm_model=acb->firm_model;
char *acb_firm_version=acb->firm_version;
- size_t iop_firm_model=offsetof(struct HBB_RWBUFFER,
- msgcode_rwbuffer[15]); /*firm_model,15,60-67*/
- size_t iop_firm_version=offsetof(struct HBB_RWBUFFER,
- msgcode_rwbuffer[17]); /*firm_version,17,68-83*/
+ char *acb_device_map = acb->device_map;
+ size_t iop_firm_model=offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/
+ size_t iop_firm_version=offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/
+ size_t iop_device_map = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
int i;
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG);
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG);
if(!arcmsr_hbb_wait_msgint_ready(acb)) {
- printf( "arcmsr%d: wait"
- "'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
+ printf( "arcmsr%d: wait" "'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
}
i=0;
while(i<8) {
@@ -2473,16 +2987,67 @@ static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb)
acb_firm_version++;
i++;
}
+ i=0;
+ while(i<16) {
+ *acb_device_map=bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_device_map+i);
+ acb_device_map++;
+ i++;
+ }
+ printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION);
+ printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version);
+ acb->firm_request_len=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/
+ acb->firm_numbers_queue=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/
+ acb->firm_sdram_size=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/
+ acb->firm_ide_channels=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/
+ acb->firm_cfg_version=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */
+ return;
+}
+/*
+**********************************************************************
+**********************************************************************
+*/
+static void arcmsr_get_hbc_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 HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/
+ size_t iop_firm_version=offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/
+ size_t iop_device_map = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
+ int i;
+
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
+ if(!arcmsr_hbc_wait_msgint_ready(acb)) {
+ printf("arcmsr%d: wait '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 \n", acb->pci_unit, ARCMSR_DRIVER_VERSION);
printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version);
- acb->firm_request_len=CHIP_REG_READ32(HBB_RWBUFFER,
- 1, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/
- acb->firm_numbers_queue=CHIP_REG_READ32(HBB_RWBUFFER,
- 1, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/
- acb->firm_sdram_size=CHIP_REG_READ32(HBB_RWBUFFER,
- 1, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/
- acb->firm_ide_channels=CHIP_REG_READ32(HBB_RWBUFFER,
- 1, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/
+ acb->firm_request_len =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/
+ acb->firm_numbers_queue =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/
+ acb->firm_sdram_size =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/
+ acb->firm_ide_channels =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/
+ acb->firm_cfg_version =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */
return;
}
/*
@@ -2500,6 +3065,10 @@ static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
arcmsr_get_hbb_config(acb);
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ arcmsr_get_hbc_config(acb);
+ }
+ break;
}
return;
}
@@ -2513,13 +3082,11 @@ static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb)
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
- while ((CHIP_REG_READ32(HBA_MessageUnit,
- 0, outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0)
+ while ((CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0)
{
if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */
{
- printf( "arcmsr%d:"
- "timed out waiting for firmware \n", acb->pci_unit);
+ printf( "arcmsr%d:timed out waiting for firmware \n", acb->pci_unit);
return;
}
UDELAY(15000); /* wait 15 milli-seconds */
@@ -2527,19 +3094,28 @@ static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb)
}
break;
case ACB_ADAPTER_TYPE_B: {
- while ((CHIP_REG_READ32(HBB_DOORBELL,
- 0, iop2drv_doorbell) & ARCMSR_MESSAGE_FIRMWARE_OK) == 0)
+ while ((CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & ARCMSR_MESSAGE_FIRMWARE_OK) == 0)
{
if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */
{
- printf( "arcmsr%d:"
- " timed out waiting for firmware \n", acb->pci_unit);
+ printf( "arcmsr%d: timed out waiting for firmware \n", acb->pci_unit);
+ return;
+ }
+ UDELAY(15000); /* wait 15 milli-seconds */
+ }
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
+ }
+ break;
+ case ACB_ADAPTER_TYPE_C: {
+ while ((CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0)
+ {
+ if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */
+ {
+ printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit);
return;
}
UDELAY(15000); /* wait 15 milli-seconds */
}
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
}
break;
}
@@ -2551,25 +3127,31 @@ static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb)
*/
static void arcmsr_clear_doorbell_queue_buffer( struct AdapterControlBlock *acb)
{
+ u_int32_t outbound_doorbell;
+
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
/* empty doorbell Qbuffer if door bell ringed */
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, outbound_doorbell,
- CHIP_REG_READ32(HBA_MessageUnit,
- 0, outbound_doorbell));/*clear doorbell interrupt */
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
+ outbound_doorbell = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell);
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, outbound_doorbell); /*clear doorbell interrupt */
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
+
}
break;
case ACB_ADAPTER_TYPE_B: {
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt and message state*/
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK);
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt and message state*/
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK);
/* let IOP know data has been read */
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ /* empty doorbell Qbuffer if door bell ringed */
+ outbound_doorbell = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell);
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell); /*clear doorbell interrupt */
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK);
+
+ }
+ break;
}
return;
}
@@ -2588,20 +3170,17 @@ static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb)
** if freesrb.HighPart is not zero
********************************************************************
*/
- srb_phyaddr= (unsigned long) acb->srb_phyaddr;
- srb_phyaddr_hi32=(u_int32_t) ((srb_phyaddr>>16)>>16);
+ srb_phyaddr= (unsigned long) acb->srb_phyaddr.phyaddr;
+// srb_phyaddr_hi32=(u_int32_t) ((srb_phyaddr>>16)>>16);
+ srb_phyaddr_hi32=acb->srb_phyaddr.B.phyadd_high;
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
if(srb_phyaddr_hi32!=0) {
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG);
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, msgcode_rwbuffer[1], srb_phyaddr_hi32);
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG);
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32);
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
if(!arcmsr_hba_wait_msgint_ready(acb)) {
- printf( "arcmsr%d:"
- " 'set srb high part physical address' timeout \n", acb->pci_unit);
+ printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit);
return FALSE;
}
}
@@ -2619,40 +3198,43 @@ static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb)
phbbmu=(struct HBB_MessageUnit *)acb->pmu;
phbbmu->postq_index=0;
phbbmu->doneq_index=0;
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, drv2iop_doorbell, ARCMSR_MESSAGE_SET_POST_WINDOW);
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_SET_POST_WINDOW);
if(!arcmsr_hbb_wait_msgint_ready(acb)) {
- printf( "arcmsr%d:"
- " 'set window of post command Q' timeout\n", acb->pci_unit);
+ printf( "arcmsr%d: 'set window of post command Q' timeout\n", acb->pci_unit);
return FALSE;
}
- post_queue_phyaddr = srb_phyaddr
- + ARCMSR_MAX_FREESRB_NUM*sizeof(struct CommandControlBlock)
+ post_queue_phyaddr = srb_phyaddr + ARCMSR_MAX_FREESRB_NUM*sizeof(struct CommandControlBlock)
+ offsetof(struct HBB_MessageUnit, post_qbuffer);
- CHIP_REG_WRITE32(HBB_RWBUFFER,
- 1, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */
- CHIP_REG_WRITE32(HBB_RWBUFFER,
- 1, msgcode_rwbuffer[1], srb_phyaddr_hi32); /* normal should be zero */
- CHIP_REG_WRITE32(HBB_RWBUFFER,
- 1, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ size (256+8)*4 */
- CHIP_REG_WRITE32(HBB_RWBUFFER,
- 1, msgcode_rwbuffer[3], post_queue_phyaddr+1056); /* doneQ size (256+8)*4 */
- CHIP_REG_WRITE32(HBB_RWBUFFER,
- 1, msgcode_rwbuffer[4], 1056); /* srb maxQ size must be --> [(256+8)*4] */
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, drv2iop_doorbell, ARCMSR_MESSAGE_SET_CONFIG);
+ CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */
+ CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1], srb_phyaddr_hi32); /* normal should be zero */
+ CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ size (256+8)*4 */
+ CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3], post_queue_phyaddr+1056); /* doneQ size (256+8)*4 */
+ CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4], 1056); /* srb maxQ size must be --> [(256+8)*4] */
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_SET_CONFIG);
if(!arcmsr_hbb_wait_msgint_ready(acb)) {
printf( "arcmsr%d: 'set command Q window' timeout \n", acb->pci_unit);
return FALSE;
}
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, drv2iop_doorbell, ARCMSR_MESSAGE_START_DRIVER_MODE);
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_START_DRIVER_MODE);
if(!arcmsr_hbb_wait_msgint_ready(acb)) {
printf( "arcmsr%d: 'start diver mode' timeout \n", acb->pci_unit);
return FALSE;
}
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ if(srb_phyaddr_hi32!=0) {
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG);
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32);
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
+ if(!arcmsr_hbc_wait_msgint_ready(acb)) {
+ printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit);
+ return FALSE;
+ }
+ }
+ }
+ break;
}
return TRUE;
}
@@ -2665,13 +3247,13 @@ static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb)
switch (acb->adapter_type)
{
case ACB_ADAPTER_TYPE_A:
- return;
+ case ACB_ADAPTER_TYPE_C:
+ break;
case ACB_ADAPTER_TYPE_B: {
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, drv2iop_doorbell,ARCMSR_MESSAGE_ACTIVE_EOI_MODE);
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, 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);
+ printf( "arcmsr%d: 'iop enable eoi mode' timeout \n", acb->pci_unit);
+
return;
}
}
@@ -2715,7 +3297,7 @@ static void arcmsr_map_freesrb(void *arg, bus_dma_segment_t *segs, int nseg, int
unsigned long srb_phyaddr=(unsigned long)segs->ds_addr;
dma_memptr=acb->uncacheptr;
- acb->srb_phyaddr=srb_phyaddr;
+ acb->srb_phyaddr.phyaddr=srb_phyaddr;
srb_tmp=(struct CommandControlBlock *)dma_memptr;
for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) {
if(bus_dmamap_create(acb->dm_segs_dmat,
@@ -2725,7 +3307,7 @@ static void arcmsr_map_freesrb(void *arg, bus_dma_segment_t *segs, int nseg, int
" srb dmamap bus_dmamap_create error\n", acb->pci_unit);
return;
}
- srb_tmp->cdb_shifted_phyaddr=srb_phyaddr >> 5;
+ srb_tmp->cdb_shifted_phyaddr=(acb->adapter_type==ACB_ADAPTER_TYPE_C)?srb_phyaddr:(srb_phyaddr >> 5);
srb_tmp->acb=acb;
acb->srbworkingQ[i]=acb->psrb_pool[i]=srb_tmp;
srb_phyaddr=srb_phyaddr+sizeof(struct CommandControlBlock);
@@ -2764,10 +3346,14 @@ static u_int32_t arcmsr_initialize(device_t dev)
int i, j,max_coherent_size;
switch (pci_get_devid(dev)) {
+ case PCIDevVenIDARC1880: {
+ acb->adapter_type=ACB_ADAPTER_TYPE_C;
+ max_coherent_size=ARCMSR_SRBS_POOL_SIZE;
+ }
+ break;
case PCIDevVenIDARC1201: {
acb->adapter_type=ACB_ADAPTER_TYPE_B;
- max_coherent_size=ARCMSR_SRBS_POOL_SIZE
- +(sizeof(struct HBB_MessageUnit));
+ max_coherent_size=ARCMSR_SRBS_POOL_SIZE+(sizeof(struct HBB_MessageUnit));
}
break;
case PCIDevVenIDARC1110:
@@ -2781,6 +3367,8 @@ static u_int32_t arcmsr_initialize(device_t dev)
case PCIDevVenIDARC1260:
case PCIDevVenIDARC1270:
case PCIDevVenIDARC1280:
+ case PCIDevVenIDARC1212:
+ case PCIDevVenIDARC1222:
case PCIDevVenIDARC1380:
case PCIDevVenIDARC1381:
case PCIDevVenIDARC1680:
@@ -2842,11 +3430,11 @@ static u_int32_t arcmsr_initialize(device_t dev)
/*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT,
/*flags*/ 0,
/*lockfunc*/ busdma_lock_mutex,
-#if __FreeBSD_version >= 700025
+ #if __FreeBSD_version >= 700025
/*lockarg*/ &acb->qbuffer_lock,
-#else
+ #else
/*lockarg*/ &Giant,
-#endif
+ #endif
&acb->dm_segs_dmat) != 0)
#else
if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat,
@@ -2904,8 +3492,7 @@ static u_int32_t arcmsr_initialize(device_t dev)
return ENXIO;
}
/* Allocation for our srbs */
- if(bus_dmamem_alloc(acb->srb_dmat, (void **)&acb->uncacheptr
- , BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &acb->srb_dmamap) != 0) {
+ if(bus_dmamem_alloc(acb->srb_dmat, (void **)&acb->uncacheptr, BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &acb->srb_dmamap) != 0) {
bus_dma_tag_destroy(acb->srb_dmat);
bus_dma_tag_destroy(acb->dm_segs_dmat);
bus_dma_tag_destroy(acb->parent_dmat);
@@ -2913,8 +3500,7 @@ static u_int32_t arcmsr_initialize(device_t dev)
return ENXIO;
}
/* And permanently map them */
- if(bus_dmamap_load(acb->srb_dmat, acb->srb_dmamap, acb->uncacheptr
- , max_coherent_size, arcmsr_map_freesrb, acb, /*flags*/0)) {
+ if(bus_dmamap_load(acb->srb_dmat, acb->srb_dmamap, acb->uncacheptr, max_coherent_size, arcmsr_map_freesrb, acb, /*flags*/0)) {
bus_dma_tag_destroy(acb->srb_dmat);
bus_dma_tag_destroy(acb->dm_segs_dmat);
bus_dma_tag_destroy(acb->parent_dmat);
@@ -2933,25 +3519,21 @@ static u_int32_t arcmsr_initialize(device_t dev)
u_int32_t rid0=PCIR_BAR(0);
vm_offset_t mem_base0;
- acb->sys_res_arcmsr[0]=bus_alloc_resource(dev,
- SYS_RES_MEMORY, &rid0, 0ul, ~0ul, 0x1000, RF_ACTIVE);
+ acb->sys_res_arcmsr[0]=bus_alloc_resource(dev,SYS_RES_MEMORY, &rid0, 0ul, ~0ul, 0x1000, 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));
+ 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));
+ 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));
+ 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]);
@@ -2966,33 +3548,26 @@ static u_int32_t arcmsr_initialize(device_t dev)
vm_offset_t mem_base[]={0,0};
for(i=0; i<2; i++) {
if(i==0) {
- acb->sys_res_arcmsr[i]=bus_alloc_resource(dev,
- SYS_RES_MEMORY, &rid[i],
- 0x20400, 0x20400+sizeof(struct HBB_DOORBELL),
- sizeof(struct HBB_DOORBELL), RF_ACTIVE);
+ acb->sys_res_arcmsr[i]=bus_alloc_resource(dev,SYS_RES_MEMORY, &rid[i],
+ 0x20400, 0x20400+sizeof(struct HBB_DOORBELL), sizeof(struct HBB_DOORBELL), RF_ACTIVE);
} else {
- acb->sys_res_arcmsr[i]=bus_alloc_resource(dev,
- SYS_RES_MEMORY, &rid[i],
- 0x0fa00, 0x0fa00+sizeof(struct HBB_RWBUFFER),
- sizeof(struct HBB_RWBUFFER), RF_ACTIVE);
+ acb->sys_res_arcmsr[i]=bus_alloc_resource(dev, SYS_RES_MEMORY, &rid[i],
+ 0x0fa00, 0x0fa00+sizeof(struct HBB_RWBUFFER), sizeof(struct HBB_RWBUFFER), 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);
+ 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);
+ 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);
+ 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]);
@@ -3005,15 +3580,39 @@ static u_int32_t arcmsr_initialize(device_t dev)
phbbmu->hbb_rwbuffer=(struct HBB_RWBUFFER *)mem_base[1];
}
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(dev,SYS_RES_MEMORY, &rid0, 0ul, ~0ul, sizeof(struct HBC_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;
+ }
+ break;
}
if(acb->acb_flags & ACB_F_MAPFREESRB_FAILD) {
arcmsr_free_resource(acb);
printf("arcmsr%d: map free srb failure!\n", device_get_unit(dev));
return ENXIO;
}
- acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED
- |ACB_F_MESSAGE_RQBUFFER_CLEARED
- |ACB_F_MESSAGE_WQBUFFER_READ);
+ acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_RQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ);
acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER;
/*
********************************************************************
@@ -3056,11 +3655,9 @@ static int arcmsr_attach(device_t dev)
irqres=bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1, 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)) {
#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)) {
#endif
arcmsr_free_resource(acb);
ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock);
@@ -3085,13 +3682,9 @@ static int arcmsr_attach(device_t dev)
return ENXIO;
}
#if __FreeBSD_version >= 700025
- acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll,
- "arcmsr", acb, unit, &acb->qbuffer_lock, 1,
- ARCMSR_MAX_OUTSTANDING_CMD, devq);
+ acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, &acb->qbuffer_lock, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq);
#else
- acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll,
- "arcmsr", acb, unit, 1,
- ARCMSR_MAX_OUTSTANDING_CMD, devq);
+ 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);
@@ -3114,10 +3707,7 @@ static int arcmsr_attach(device_t dev)
printf("arcmsr%d: xpt_bus_register failure!\n", unit);
return ENXIO;
}
- if(xpt_create_path(&acb->ppath, /* periph */ NULL
- , cam_sim_path(acb->psim)
- , CAM_TARGET_WILDCARD
- , CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
+ 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));
@@ -3137,18 +3727,20 @@ static int arcmsr_attach(device_t dev)
xpt_action((union ccb *)&csa);
ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
/* Create the control device. */
- acb->ioctl_dev=make_dev(&arcmsr_cdevsw
- , unit
- , UID_ROOT
- , GID_WHEEL /* GID_OPERATOR */
- , S_IRUSR | S_IWUSR
- , "arcmsr%d", unit);
+ acb->ioctl_dev=make_dev(&arcmsr_cdevsw, unit, UID_ROOT, GID_WHEEL /* GID_OPERATOR */, S_IRUSR | S_IWUSR, "arcmsr%d", unit);
+
#if __FreeBSD_version < 503000
acb->ioctl_dev->si_drv1=acb;
#endif
#if __FreeBSD_version > 500005
(void)make_dev_alias(acb->ioctl_dev, "arc%d", unit);
#endif
+#if __FreeBSD_version > 500000
+ callout_init(&acb->devmap_callout, /*mpsafe*/1);
+#else
+ callout_init(&acb->devmap_callout);
+#endif
+ callout_reset(&acb->devmap_callout, 60 * hz, arcmsr_polling_devmap, acb);
return 0;
}
/*
@@ -3182,11 +3774,16 @@ static int arcmsr_probe(device_t dev)
case PCIDevVenIDARC1280:
type = "SATA";
break;
+ case PCIDevVenIDARC1212:
+ case PCIDevVenIDARC1222:
case PCIDevVenIDARC1380:
case PCIDevVenIDARC1381:
case PCIDevVenIDARC1680:
case PCIDevVenIDARC1681:
- type = "SAS";
+ type = "SAS 3G";
+ break;
+ case PCIDevVenIDARC1880:
+ type = "SAS 6G";
break;
default:
type = "X-TYPE";
@@ -3245,6 +3842,7 @@ 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_shutdown(dev);
arcmsr_free_resource(acb);
diff --git a/sys/dev/arcmsr/arcmsr.h b/sys/dev/arcmsr/arcmsr.h
index 7d8e24b..2e78f39 100644
--- a/sys/dev/arcmsr/arcmsr.h
+++ b/sys/dev/arcmsr/arcmsr.h
@@ -2,16 +2,16 @@
***********************************************************************************************
** O.S : FreeBSD
** FILE NAME : arcmsr.h
-** BY : Erich Chen
+** BY : Erich Chen, Ching Huang
** Description: SCSI RAID Device Driver for
-** ARECA SATA RAID HOST Adapter
+** ARECA SATA/SAS RAID HOST Adapter
** [RAID controller:INTEL 331(PCI-X) 341(PCI-EXPRESS) chip set]
***********************************************************************************************
************************************************************************
-** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved.
+** Copyright (C) 2002 - 2010, Areca Technology Corporation All rights reserved.
**
** Web site: www.areca.com.tw
-** E-mail: erich@areca.com.tw
+** E-mail: erich@areca.com.tw; ching2048@areca.com.tw
**
** Redistribution and use in source and binary forms,with or without
** modification,are permitted provided that the following conditions
@@ -37,11 +37,11 @@
**************************************************************************
* $FreeBSD$
*/
-#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.16 2009-10-10"
+#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.17 2010-07-15"
#define ARCMSR_SCSI_INITIATOR_ID 255
#define ARCMSR_DEV_SECTOR_SIZE 512
#define ARCMSR_MAX_XFER_SECTORS 4096
-#define ARCMSR_MAX_TARGETID 16 /*16 max target id + 1*/
+#define ARCMSR_MAX_TARGETID 17 /*16 max target id + 1*/
#define ARCMSR_MAX_TARGETLUN 8 /*8*/
#define ARCMSR_MAX_CHIPTYPE_NUM 4
#define ARCMSR_MAX_OUTSTANDING_CMD 256
@@ -86,11 +86,14 @@
#define PCI_DEVICE_ID_ARECA_1260 0x1260 /* Device ID */
#define PCI_DEVICE_ID_ARECA_1270 0x1270 /* Device ID */
#define PCI_DEVICE_ID_ARECA_1280 0x1280 /* Device ID */
+#define PCI_DEVICE_ID_ARECA_1212 0x1212 /* Device ID */
+#define PCI_DEVICE_ID_ARECA_1222 0x1222 /* Device ID */
#define PCI_DEVICE_ID_ARECA_1380 0x1380 /* Device ID */
#define PCI_DEVICE_ID_ARECA_1381 0x1381 /* Device ID */
#define PCI_DEVICE_ID_ARECA_1680 0x1680 /* Device ID */
#define PCI_DEVICE_ID_ARECA_1681 0x1681 /* Device ID */
#define PCI_DEVICE_ID_ARECA_1201 0x1201 /* Device ID */
+#define PCI_DEVICE_ID_ARECA_1880 0x1880 /* Device ID */
#define PCIDevVenIDARC1110 0x111017D3 /* Vendor Device ID */
#define PCIDevVenIDARC1120 0x112017D3 /* Vendor Device ID */
@@ -103,11 +106,14 @@
#define PCIDevVenIDARC1260 0x126017D3 /* Vendor Device ID */
#define PCIDevVenIDARC1270 0x127017D3 /* Vendor Device ID */
#define PCIDevVenIDARC1280 0x128017D3 /* Vendor Device ID */
+#define PCIDevVenIDARC1212 0x121217D3 /* Vendor Device ID */
+#define PCIDevVenIDARC1222 0x122217D3 /* Vendor Device ID */
#define PCIDevVenIDARC1380 0x138017D3 /* Vendor Device ID */
#define PCIDevVenIDARC1381 0x138117D3 /* Vendor Device ID */
#define PCIDevVenIDARC1680 0x168017D3 /* Vendor Device ID */
#define PCIDevVenIDARC1681 0x168117D3 /* Vendor Device ID */
#define PCIDevVenIDARC1201 0x120117D3 /* Vendor Device ID */
+#define PCIDevVenIDARC1880 0x188017D3 /* Vendor Device ID */
#ifndef PCIR_BARS
#define PCIR_BARS 0x10
@@ -145,6 +151,23 @@
**
**********************************************************************************
*/
+struct CMD_MESSAGE {
+ u_int32_t HeaderLength;
+ u_int8_t Signature[8];
+ u_int32_t Timeout;
+ u_int32_t ControlCode;
+ u_int32_t ReturnCode;
+ u_int32_t Length;
+};
+
+struct CMD_MESSAGE_FIELD {
+ struct CMD_MESSAGE cmdmessage; /* ioctl header */
+ u_int8_t messagedatabuffer[1032]; /* areca gui program does not accept more than 1031 byte */
+};
+
+/************************************************************************/
+/************************************************************************/
+
#define ARCMSR_IOP_ERROR_ILLEGALPCI 0x0001
#define ARCMSR_IOP_ERROR_VENDORID 0x0002
#define ARCMSR_IOP_ERROR_DEVICEID 0x0002
@@ -156,8 +179,10 @@
#define ARCMSR_SYS_ERROR_MEMORY_RANGE 0x0008
#define ARCMSR_SYS_ERROR_DEVICE_BASE 0x0009
#define ARCMSR_SYS_ERROR_PORT_VALIDATE 0x000A
+
/*DeviceType*/
#define ARECA_SATA_RAID 0x90000000
+
/*FunctionCode*/
#define FUNCTION_READ_RQBUFFER 0x0801
#define FUNCTION_WRITE_WQBUFFER 0x0802
@@ -173,19 +198,6 @@
** IOCTL CONTROL CODE
************************************************************************
*/
-struct CMD_MESSAGE {
- u_int32_t HeaderLength;
- u_int8_t Signature[8];
- u_int32_t Timeout;
- u_int32_t ControlCode;
- u_int32_t ReturnCode;
- u_int32_t Length;
-};
-
-struct CMD_MESSAGE_FIELD {
- struct CMD_MESSAGE cmdmessage; /* ioctl header */
- u_int8_t messagedatabuffer[1032]; /* areca gui program does not accept more than 1031 byte */
-};
/* ARECA IO CONTROL CODE*/
#define ARCMSR_MESSAGE_READ_RQBUFFER _IOWR('F', FUNCTION_READ_RQBUFFER, struct CMD_MESSAGE_FIELD)
#define ARCMSR_MESSAGE_WRITE_WQBUFFER _IOWR('F', FUNCTION_WRITE_WQBUFFER, struct CMD_MESSAGE_FIELD)
@@ -196,10 +208,12 @@ struct CMD_MESSAGE_FIELD {
#define ARCMSR_MESSAGE_SAY_HELLO _IOWR('F', FUNCTION_SAY_HELLO, struct CMD_MESSAGE_FIELD)
#define ARCMSR_MESSAGE_SAY_GOODBYE _IOWR('F', FUNCTION_SAY_GOODBYE, struct CMD_MESSAGE_FIELD)
#define ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE _IOWR('F', FUNCTION_FLUSH_ADAPTER_CACHE, struct CMD_MESSAGE_FIELD)
+
/* ARECA IOCTL ReturnCode */
#define ARCMSR_MESSAGE_RETURNCODE_OK 0x00000001
#define ARCMSR_MESSAGE_RETURNCODE_ERROR 0x00000006
#define ARCMSR_MESSAGE_RETURNCODE_3F 0x0000003F
+#define ARCMSR_IOCTL_RETURNCODE_BUS_HANG_ON 0x00000088
/*
************************************************************************
** SPEC. for Areca HBB adapter
@@ -210,8 +224,8 @@ struct CMD_MESSAGE_FIELD {
#define ARCMSR_DRV2IOP_DOORBELL_MASK 0x00020404
#define ARCMSR_IOP2DRV_DOORBELL 0x00020408 /* window of "instruction flags" from iop to driver */
#define ARCMSR_IOP2DRV_DOORBELL_MASK 0x0002040C
-/* ARECA FLAG LANGUAGE */
+/* ARECA FLAG LANGUAGE */
#define ARCMSR_IOP2DRV_DATA_WRITE_OK 0x00000001 /* ioctl transfer */
#define ARCMSR_IOP2DRV_DATA_READ_OK 0x00000002 /* ioctl transfer */
#define ARCMSR_IOP2DRV_CDB_DONE 0x00000004
@@ -247,6 +261,55 @@ struct CMD_MESSAGE_FIELD {
#define ARCMSR_HBB_BASE0_LEN 0x00021000
#define ARCMSR_HBB_BASE1_LEN 0x00010000
/*
+************************************************************************
+** SPEC. for Areca HBC adapter
+************************************************************************
+*/
+#define ARCMSR_HBC_ISR_THROTTLING_LEVEL 12
+#define ARCMSR_HBC_ISR_MAX_DONE_QUEUE 20
+/* Host Interrupt Mask */
+#define ARCMSR_HBCMU_UTILITY_A_ISR_MASK 0x00000001 /* When clear, the Utility_A interrupt routes to the host.*/
+#define ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK 0x00000004 /* When clear, the General Outbound Doorbell interrupt routes to the host.*/
+#define ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK 0x00000008 /* When clear, the Outbound Post List FIFO Not Empty interrupt routes to the host.*/
+#define ARCMSR_HBCMU_ALL_INTMASKENABLE 0x0000000D /* disable all ISR */
+/* Host Interrupt Status */
+#define ARCMSR_HBCMU_UTILITY_A_ISR 0x00000001
+ /*
+ ** Set when the Utility_A Interrupt bit is set in the Outbound Doorbell Register.
+ ** It clears by writing a 1 to the Utility_A bit in the Outbound Doorbell Clear Register or through automatic clearing (if enabled).
+ */
+#define ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR 0x00000004
+ /*
+ ** Set if Outbound Doorbell register bits 30:1 have a non-zero
+ ** value. This bit clears only when Outbound Doorbell bits
+ ** 30:1 are ALL clear. Only a write to the Outbound Doorbell
+ ** Clear register clears bits in the Outbound Doorbell register.
+ */
+#define ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR 0x00000008
+ /*
+ ** Set whenever the Outbound Post List Producer/Consumer
+ ** Register (FIFO) is not empty. It clears when the Outbound
+ ** Post List FIFO is empty.
+ */
+#define ARCMSR_HBCMU_SAS_ALL_INT 0x00000010
+ /*
+ ** This bit indicates a SAS interrupt from a source external to
+ ** the PCIe core. This bit is not maskable.
+ */
+/* DoorBell*/
+#define ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK 0x00000002/**/
+#define ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK 0x00000004/**/
+#define ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE 0x00000008/*inbound message 0 ready*/
+#define ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING 0x00000010/*more than 12 request completed in a time*/
+#define ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK 0x00000002/**/
+#define ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_DOORBELL_CLEAR 0x00000002/*outbound DATA WRITE isr door bell clear*/
+#define ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK 0x00000004/**/
+#define ARCMSR_HBCMU_IOP2DRV_DATA_READ_DOORBELL_CLEAR 0x00000004/*outbound DATA READ isr door bell clear*/
+#define ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE 0x00000008/*outbound message 0 ready*/
+#define ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR 0x00000008/*outbound message cmd isr door bell clear*/
+#define ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK 0x80000000/*ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK*/
+
+/*
*************************************************************
** structure for holding DMA address data
*************************************************************
@@ -336,6 +399,137 @@ struct CMD_MESSAGE_FIELD {
** byte 5 : hour (0..23)
** byte 6 : minute (0..59)
** byte 7 : second (0..59)
+** *********************************************************************************
+** Porting Of LSI2108/2116 Based PCIE SAS/6G host raid adapter
+** ==> Difference from IOP348
+** <1> Message Register 0,1 (the same usage) Init Thread message and retrun code
+** Inbound Message 0 (inbound_msgaddr0) : at offset 0xB0 (Scratchpad0) for inbound message code msgcode_rwbuffer (driver send to IOP)
+** Inbound Message 1 (inbound_msgaddr1) : at offset 0xB4 (Scratchpad1) Out.... Diag Status Code
+** Outbound Message 0 (outbound_msgaddr0): at offset 0xB8 (Scratchpad3) Out.... Diag Status Code
+** Outbound Message 1 (outbound_msgaddr1): at offset 0xBC (Scratchpad2) for outbound message code msgcode_rwbuffer (IOP send to driver)
+** <A> use doorbell to generate interrupt
+**
+** inbound doorbell: bit3 -- inbound message 0 ready (driver to iop)
+** outbound doorbell: bit3 -- outbound message 0 ready (iop to driver)
+**
+** a. Message1: Out - Diag Status Code (????)
+**
+** b. Message0: message code
+** 0x00 : NOP
+** 0x01 : Get Config ->offset 0xB8 :for outbound message code msgcode_rwbuffer (IOP send to driver)
+** Signature 0x87974060(4)
+** Request len 0x00000200(4)
+** numbers of queue 0x00000100(4)
+** SDRAM Size 0x00000100(4)-->256 MB
+** IDE Channels 0x00000008(4)
+** vendor 40 bytes char
+** model 8 bytes char
+** FirmVer 16 bytes char
+** Device Map 16 bytes char
+** cfgVersion ULONG <== Added for checking of new firmware capability
+** 0x02 : Set Config ->offset 0xB0 :for inbound message code msgcode_rwbuffer (driver send to IOP)
+** Signature 0x87974063(4)
+** UPPER32 of Request Frame (4)-->Driver Only
+** 0x03 : Reset (Abort all queued Command)
+** 0x04 : Stop Background Activity
+** 0x05 : Flush Cache
+** 0x06 : Start Background Activity (re-start if background is halted)
+** 0x07 : Check If Host Command Pending (Novell May Need This Function)
+** 0x08 : Set controller time ->offset 0xB0 : for inbound message code msgcode_rwbuffer (driver to IOP)
+** byte 0 : 0xaa <-- signature
+** byte 1 : 0x55 <-- signature
+** byte 2 : year (04)
+** byte 3 : month (1..12)
+** byte 4 : date (1..31)
+** byte 5 : hour (0..23)
+** byte 6 : minute (0..59)
+** byte 7 : second (0..59)
+**
+** <2> Doorbell Register is used for RS-232 emulation
+** <A> different clear register
+** <B> different bit0 definition (bit0 is reserved)
+**
+** inbound doorbell : at offset 0x20
+** inbound doorbell clear : at offset 0x70
+**
+** inbound doorbell : bit0 -- reserved
+** bit1 -- data in ready (DRIVER DATA WRITE OK)
+** bit2 -- data out has been read (DRIVER DATA READ OK)
+** bit3 -- inbound message 0 ready
+** bit4 -- more than 12 request completed in a time
+**
+** outbound doorbell : at offset 0x9C
+** outbound doorbell clear : at offset 0xA0
+**
+** outbound doorbell : bit0 -- reserved
+** bit1 -- data out ready (IOP DATA WRITE OK)
+** bit2 -- data in has been read (IOP DATA READ OK)
+** bit3 -- outbound message 0 ready
+**
+** <3> Index Memory Usage (Buffer Area)
+** COMPORT_IN at 0x2000: message_wbuffer -- 128 bytes (to be sent to ROC) : for RS232 in (scratch buffer)
+** COMPORT_OUT at 0x2100: message_rbuffer -- 128 bytes (to be sent to host): for RS232 out (request buffer)
+** BIOS_CFG_AREA at 0x2200: msgcode_rwbuffer -- 1024 bytes for outbound message code msgcode_rwbuffer (IOP send to driver)
+** BIOS_CFG_AREA at 0x2200: msgcode_rwbuffer -- 1024 bytes for inbound message code msgcode_rwbuffer (driver send to IOP)
+**
+** <4> PostQ (Command Post Address)
+** All SCSI Command must be sent through postQ:
+** inbound queue port32 at offset 0x40 , 0x41, 0x42, 0x43
+** inbound queue port64 at offset 0xC0 (lower)/0xC4 (upper)
+** outbound queue port32 at offset 0x44
+** outbound queue port64 at offset 0xC8 (lower)/0xCC (upper)
+** <A> For 32bit queue, access low part is enough to send/receive request
+** i.e. write 0x40/0xC0, ROC will get the request with high part == 0, the
+** same for outbound queue port
+** <B> For 64bit queue, if 64bit instruction is supported, use 64bit instruction
+** to post inbound request in a single instruction, and use 64bit instruction
+** to retrieve outbound request in a single instruction.
+** If in 32bit environment, when sending inbound queue, write high part first
+** then write low part. For receiving outbound request, read high part first
+** then low part, to check queue empty, ONLY check high part to be 0xFFFFFFFF.
+** If high part is 0xFFFFFFFF, DO NOT read low part, this may corrupt the
+** consistency of the FIFO. Another way to check empty is to check status flag
+** at 0x30 bit3.
+** <C> Post Address IS NOT shifted (must be 16 bytes aligned)
+** For BIOS, 16bytes aligned is OK
+** For Driver, 32bytes alignment is recommended.
+** POST Command bit0 to bit3 is defined differently
+** ----------------------------
+** bit0:1 for PULL mode (must be 1)
+** ----------------------------
+** bit3/2/1: for arcmsr cdb size (arccdbsize)
+** 000: <= 0x0080 (128)
+** 001: <= 0x0100 (256)
+** 010: <= 0x0180 (384)
+** 011: <= 0x0200 (512)
+** 100: <= 0x0280 (640)
+** 101: <= 0x0300 (768)
+** 110: <= 0x0300 (reserved)
+** 111: <= 0x0300 (reserved)
+** -----------------------------
+** if len > 0x300 the len always set as 0x300
+** -----------------------------
+** post addr = addr | ((len-1) >> 6) | 1
+** -----------------------------
+** page length in command buffer still required,
+**
+** if page length > 3,
+** firmware will assume more request data need to be retrieved
+**
+** <D> Outbound Posting
+** bit0:0 , no error, 1 with error, refer to status buffer
+** bit1:0 , reserved (will be 0)
+** bit2:0 , reserved (will be 0)
+** bit3:0 , reserved (will be 0)
+** bit63-4: Completed command address
+**
+** <E> BIOS support, no special support is required.
+** LSI2108 support I/O register
+** All driver functionality is supported through I/O address
+**
+** For further spec, refer to
+** \spec\lsi\2108 for Areca\2108\LSISAS2108_PG_NoEncryption.pdf : Chapter 8 (8-11/8-28)
+** \spec\lsi\2108 for Areca\2108\SAS2108_RM_20.pdf : for configuration space
************************************************************************************************
*/
/* signature of set and get firmware config */
@@ -361,6 +555,8 @@ struct CMD_MESSAGE_FIELD {
#define ARCMSR_SRBPOST_FLAG_IAM_BIOS 0x40000000
#define ARCMSR_SRBREPLY_FLAG_IAM_BIOS 0x40000000
#define ARCMSR_SRBREPLY_FLAG_ERROR 0x10000000
+#define ARCMSR_SRBREPLY_FLAG_ERROR_MODE0 0x10000000
+#define ARCMSR_SRBREPLY_FLAG_ERROR_MODE1 0x00000001
/* outbound firmware ok */
#define ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK 0x80000000
/*
@@ -369,11 +565,13 @@ struct CMD_MESSAGE_FIELD {
**********************************
*/
/* size 8 bytes */
+/* 32bit Scatter-Gather list */
struct SG32ENTRY { /* length bit 24 == 0 */
u_int32_t length; /* high 8 bit == flag,low 24 bit == length */
u_int32_t address;
};
/* size 12 bytes */
+/* 64bit Scatter-Gather list */
struct SG64ENTRY { /* length bit 24 == 1 */
u_int32_t length; /* high 8 bit == flag,low 24 bit == length */
u_int32_t address;
@@ -399,6 +597,11 @@ struct QBUFFER {
** FIRMWARE INFO
************************************************************************************************
*/
+#define ARCMSR_FW_MODEL_OFFSET 15
+#define ARCMSR_FW_VERS_OFFSET 17
+#define ARCMSR_FW_DEVMAP_OFFSET 21
+#define ARCMSR_FW_CFGVER_OFFSET 25
+
struct FIRMWARE_INFO {
u_int32_t signature; /*0,00-03*/
u_int32_t request_len; /*1,04-07*/
@@ -409,7 +612,37 @@ struct FIRMWARE_INFO {
char model[8]; /*15,60-67*/
char firmware_ver[16]; /*17,68-83*/
char device_map[16]; /*21,84-99*/
+ u_int32_t cfgVersion; /*25,100-103 Added for checking of new firmware capability*/
+ char cfgSerial[16]; /*26,104-119*/
+ u_int32_t cfgPicStatus; /*30,120-123*/
};
+/* (A) For cfgVersion in FIRMWARE_INFO
+** if low BYTE (byte#0) >= 3 (version 3)
+** then byte#1 report the capability of the firmware can xfer in a single request
+**
+** byte#1
+** 0 256K
+** 1 512K
+** 2 1M
+** 3 2M
+** 4 4M
+** 5 8M
+** 6 16M
+** (B) Byte offset 7 (Reserved1) of CDB is changed to msgPages
+** Driver support new xfer method need to set this field to indicate
+** large CDB block in 0x100 unit (we use 0x100 byte as one page)
+** e.g. If the length of CDB including MSG header and SGL is 0x1508
+** driver need to set the msgPages to 0x16
+** (C) REQ_LEN_512BYTE must be used also to indicate SRB length
+** e.g. CDB len msgPages REQ_LEN_512BYTE flag
+** <= 0x100 1 0
+** <= 0x200 2 1
+** <= 0x300 3 1
+** <= 0x400 4 1
+** .
+** .
+*/
+
/*
************************************************************************************************
** size 0x1F8 (504)
@@ -430,7 +663,7 @@ struct ARCMSR_CDB {
#define ARCMSR_CDB_FLAG_SIMPLEQ 0x00 /* bit 4/3 ,00 : simple Q,01 : head of Q,10 : ordered Q */
#define ARCMSR_CDB_FLAG_HEADQ 0x08
#define ARCMSR_CDB_FLAG_ORDEREDQ 0x10
- u_int8_t Reserved1; /* 07h */
+ u_int8_t msgPages; /* 07h */
u_int32_t Context; /* 08h Address of this request */
u_int32_t DataLength; /* 0ch not used now */
@@ -472,58 +705,61 @@ struct ARCMSR_CDB {
*********************************************************************
*/
struct CommandControlBlock {
- struct ARCMSR_CDB arcmsr_cdb;
- /* 0-503 (size of CDB=504): arcmsr messenger scsi command descriptor size 504 bytes */
+ struct ARCMSR_CDB arcmsr_cdb; /* 0 -503 (size of CDB=504): arcmsr messenger scsi command descriptor size 504 bytes */
u_int32_t cdb_shifted_phyaddr; /* 504-507 */
- u_int32_t reserved1; /* 508-511*/
+ u_int32_t arc_cdb_size; /* 508-511 */
/* ======================512+32 bytes============================ */
#if defined(__x86_64__) || defined(__amd64__) || defined(__ia64__) || defined(__sparc64__) || defined(__powerpc__)
- union ccb * pccb; /* 512-515 516-519 pointer of freebsd scsi command */
- struct AdapterControlBlock * acb; /* 520-523 524-527 */
+ union ccb *pccb; /* 512-515 516-519 pointer of freebsd scsi command */
+ struct AdapterControlBlock *acb; /* 520-523 524-527 */
bus_dmamap_t dm_segs_dmamap; /* 528-531 532-535 */
u_int16_t srb_flags; /* 536-537 */
- #define SRB_FLAG_READ 0x0000
- #define SRB_FLAG_WRITE 0x0001
- #define SRB_FLAG_ERROR 0x0002
- #define SRB_FLAG_FLUSHCACHE 0x0004
- #define SRB_FLAG_MASTER_ABORTED 0x0008
u_int16_t startdone; /* 538-539 */
- #define ARCMSR_SRB_DONE 0x0000
- #define ARCMSR_SRB_START 0x55AA
- #define ARCMSR_SRB_ABORTED 0xAA55
- #define ARCMSR_SRB_ILLEGAL 0xFFFF
u_int32_t reserved2; /* 540-543 */
#else
- union ccb * pccb; /* 512-515 pointer of freebsd scsi command */
- struct AdapterControlBlock * acb; /* 516-519 */
+ union ccb *pccb; /* 512-515 pointer of freebsd scsi command */
+ struct AdapterControlBlock *acb; /* 516-519 */
bus_dmamap_t dm_segs_dmamap; /* 520-523 */
u_int16_t srb_flags; /* 524-525 */
- #define SRB_FLAG_READ 0x0000
- #define SRB_FLAG_WRITE 0x0001
- #define SRB_FLAG_ERROR 0x0002
- #define SRB_FLAG_FLUSHCACHE 0x0004
- #define SRB_FLAG_MASTER_ABORTED 0x0008
u_int16_t startdone; /* 526-527 */
- #define ARCMSR_SRB_DONE 0x0000
- #define ARCMSR_SRB_START 0x55AA
- #define ARCMSR_SRB_ABORTED 0xAA55
- #define ARCMSR_SRB_ILLEGAL 0xFFFF
u_int32_t reserved2[4]; /* 528-531 532-535 536-539 540-543 */
#endif
/* ========================================================== */
+/* struct callout ccb_callout; */
};
+/* srb_flags */
+#define SRB_FLAG_READ 0x0000
+#define SRB_FLAG_WRITE 0x0001
+#define SRB_FLAG_ERROR 0x0002
+#define SRB_FLAG_FLUSHCACHE 0x0004
+#define SRB_FLAG_MASTER_ABORTED 0x0008
+#define SRB_FLAG_DMAVALID 0x0010
+#define SRB_FLAG_DMACONSISTENT 0x0020
+#define SRB_FLAG_DMAWRITE 0x0040
+#define SRB_FLAG_PKTBIND 0x0080
+/* startdone */
+#define ARCMSR_SRB_DONE 0x0000
+#define ARCMSR_SRB_UNBUILD 0x0000
+#define ARCMSR_SRB_TIMEOUT 0x1111
+#define ARCMSR_SRB_RETRY 0x2222
+#define ARCMSR_SRB_START 0x55AA
+#define ARCMSR_SRB_PENDING 0xAA55
+#define ARCMSR_SRB_RESET 0xA5A5
+#define ARCMSR_SRB_ABORTED 0x5A5A
+#define ARCMSR_SRB_ILLEGAL 0xFFFF
/*
*********************************************************************
** Adapter Control Block
*********************************************************************
*/
-struct AdapterControlBlock {
- u_int32_t adapter_type; /* adapter A,B..... */
#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 P IOP */
+#define ACB_ADAPTER_TYPE_C 0x00000004 /* hbc L IOP */
#define ACB_ADAPTER_TYPE_D 0x00000008 /* hbd A IOP */
+struct AdapterControlBlock {
+ u_int32_t adapter_type; /* adapter A,B..... */
+
bus_space_tag_t btag[2];
bus_space_handle_t bhandle[2];
bus_dma_tag_t parent_dmat;
@@ -547,7 +783,14 @@ struct AdapterControlBlock {
struct cam_path *ppath;
u_int8_t * uncacheptr;
unsigned long vir2phy_offset;
- unsigned long srb_phyaddr;
+ union {
+ unsigned long phyaddr;
+ struct {
+ u_int32_t phyadd_low;
+ u_int32_t phyadd_high;
+ }B;
+ } srb_phyaddr;
+// unsigned long srb_phyaddr;
/* Offset is used in making arc cdb physical to virtual calculations */
u_int32_t outbound_int_enable;
@@ -556,17 +799,6 @@ struct AdapterControlBlock {
u_int8_t adapter_index; /* */
u_int8_t irq;
u_int16_t acb_flags; /* */
-#define ACB_F_SCSISTOPADAPTER 0x0001
-#define ACB_F_MSG_STOP_BGRB 0x0002 /* stop RAID background rebuild */
-#define ACB_F_MSG_START_BGRB 0x0004 /* stop RAID background rebuild */
-#define ACB_F_IOPDATA_OVERFLOW 0x0008 /* iop ioctl data rqbuffer overflow */
-#define ACB_F_MESSAGE_WQBUFFER_CLEARED 0x0010 /* ioctl clear wqbuffer */
-#define ACB_F_MESSAGE_RQBUFFER_CLEARED 0x0020 /* ioctl clear rqbuffer */
-#define ACB_F_MESSAGE_WQBUFFER_READ 0x0040
-#define ACB_F_BUS_RESET 0x0080
-#define ACB_F_IOP_INITED 0x0100 /* iop init */
-#define ACB_F_MAPFREESRB_FAILD 0x0200 /* arcmsr_map_freesrb faild */
-#define ACB_F_CAM_DEV_QFRZN 0x0400
struct CommandControlBlock * psrb_pool[ARCMSR_MAX_FREESRB_NUM]; /* serial srb pointer array */
struct CommandControlBlock * srbworkingQ[ARCMSR_MAX_FREESRB_NUM]; /* working srb pointer array */
@@ -587,17 +819,196 @@ struct AdapterControlBlock {
arcmsr_lock_t qbuffer_lock;
u_int8_t devstate[ARCMSR_MAX_TARGETID][ARCMSR_MAX_TARGETLUN]; /* id0 ..... id15,lun0...lun7 */
-#define ARECA_RAID_GONE 0x55
-#define ARECA_RAID_GOOD 0xaa
u_int32_t num_resets;
u_int32_t num_aborts;
u_int32_t firm_request_len; /*1,04-07*/
u_int32_t firm_numbers_queue; /*2,08-11*/
u_int32_t firm_sdram_size; /*3,12-15*/
u_int32_t firm_ide_channels; /*4,16-19*/
+ u_int32_t firm_cfg_version;
char firm_model[12]; /*15,60-67*/
char firm_version[20]; /*17,68-83*/
+ char device_map[20]; /*21,84-99 */
+ struct callout devmap_callout;
};/* HW_DEVICE_EXTENSION */
+/* acb_flags */
+#define ACB_F_SCSISTOPADAPTER 0x0001
+#define ACB_F_MSG_STOP_BGRB 0x0002 /* stop RAID background rebuild */
+#define ACB_F_MSG_START_BGRB 0x0004 /* stop RAID background rebuild */
+#define ACB_F_IOPDATA_OVERFLOW 0x0008 /* iop ioctl data rqbuffer overflow */
+#define ACB_F_MESSAGE_WQBUFFER_CLEARED 0x0010 /* ioctl clear wqbuffer */
+#define ACB_F_MESSAGE_RQBUFFER_CLEARED 0x0020 /* ioctl clear rqbuffer */
+#define ACB_F_MESSAGE_WQBUFFER_READ 0x0040
+#define ACB_F_BUS_RESET 0x0080
+#define ACB_F_IOP_INITED 0x0100 /* iop init */
+#define ACB_F_MAPFREESRB_FAILD 0x0200 /* arcmsr_map_freesrb faild */
+#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
+/* devstate */
+#define ARECA_RAID_GONE 0x55
+#define ARECA_RAID_GOOD 0xaa
+/*
+*********************************************************************
+** Message Unit structure
+*********************************************************************
+*/
+struct HBA_MessageUnit
+{
+ u_int32_t resrved0[4]; /*0000 000F*/
+ u_int32_t inbound_msgaddr0; /*0010 0013*/
+ u_int32_t inbound_msgaddr1; /*0014 0017*/
+ u_int32_t outbound_msgaddr0; /*0018 001B*/
+ u_int32_t outbound_msgaddr1; /*001C 001F*/
+ u_int32_t inbound_doorbell; /*0020 0023*/
+ u_int32_t inbound_intstatus; /*0024 0027*/
+ u_int32_t inbound_intmask; /*0028 002B*/
+ u_int32_t outbound_doorbell; /*002C 002F*/
+ u_int32_t outbound_intstatus; /*0030 0033*/
+ u_int32_t outbound_intmask; /*0034 0037*/
+ u_int32_t reserved1[2]; /*0038 003F*/
+ u_int32_t inbound_queueport; /*0040 0043*/
+ u_int32_t outbound_queueport; /*0044 0047*/
+ u_int32_t reserved2[2]; /*0048 004F*/
+ u_int32_t reserved3[492]; /*0050 07FF ......local_buffer 492*/
+ u_int32_t reserved4[128]; /*0800 09FF 128*/
+ u_int32_t msgcode_rwbuffer[256]; /*0a00 0DFF 256*/
+ u_int32_t message_wbuffer[32]; /*0E00 0E7F 32*/
+ u_int32_t reserved5[32]; /*0E80 0EFF 32*/
+ u_int32_t message_rbuffer[32]; /*0F00 0F7F 32*/
+ u_int32_t reserved6[32]; /*0F80 0FFF 32*/
+};
+/*
+*********************************************************************
+**
+*********************************************************************
+*/
+struct HBB_DOORBELL
+{
+ u_int8_t doorbell_reserved[132096]; /*reserved */
+ u_int32_t drv2iop_doorbell; /*offset 0x00020400:00,01,02,03: window of "instruction flags" from driver to iop */
+ u_int32_t drv2iop_doorbell_mask; /* 04,05,06,07: doorbell mask */
+ u_int32_t iop2drv_doorbell; /* 08,09,10,11: window of "instruction flags" from iop to driver */
+ u_int32_t iop2drv_doorbell_mask; /* 12,13,14,15: doorbell mask */
+};
+/*
+*********************************************************************
+**
+*********************************************************************
+*/
+struct HBB_RWBUFFER
+{
+ u_int8_t message_reserved0[64000]; /*reserved */
+ u_int32_t msgcode_rwbuffer[256]; /*offset 0x0000fa00: 0, 1, 2, 3,...,1023: message code read write 1024bytes */
+ u_int32_t message_wbuffer[32]; /*offset 0x0000fe00:1024,1025,1026,1027,...,1151: user space data to iop 128bytes */
+ u_int32_t message_reserved1[32]; /* 1152,1153,1154,1155,...,1279: message reserved*/
+ u_int32_t message_rbuffer[32]; /*offset 0x0000ff00:1280,1281,1282,1283,...,1407: iop data to user space 128bytes */
+};
+/*
+*********************************************************************
+**
+*********************************************************************
+*/
+struct HBB_MessageUnit
+{
+ u_int32_t post_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE]; /* post queue buffer for iop */
+ u_int32_t done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE]; /* done queue buffer for iop */
+ int32_t postq_index; /* post queue index */
+ int32_t doneq_index; /* done queue index */
+ struct HBB_DOORBELL *hbb_doorbell;
+ struct HBB_RWBUFFER *hbb_rwbuffer;
+};
+
+/*
+*********************************************************************
+**
+*********************************************************************
+*/
+struct HBC_MessageUnit {
+ u_int32_t message_unit_status; /*0000 0003*/
+ u_int32_t slave_error_attribute; /*0004 0007*/
+ u_int32_t slave_error_address; /*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 size of the PCIe window used for HCB_Mode accesses*/
+ 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 inbound free list producer consumer index*/
+ u_int32_t inbound_post_list_index; /*0064 0067 inbound post list producer consumer index*/
+ u_int32_t outbound_free_list_index; /*0068 006B outbound free list producer consumer index*/
+ u_int32_t outbound_post_list_index; /*006C 006F outbound post list producer consumer index*/
+ 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 pull mode data byte count0..count7*/
+ 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 message accelerator source address consumer producer index*/
+ u_int32_t message_done_queue_index; /*00A8 00AB message accelerator completion queue consumer producer index*/
+ 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 message accelerator destination queue port low*/
+ u_int32_t message_dest_queue_port_high; /*00E4 00E7 message accelerator destination queue port high*/
+ u_int32_t last_used_message_dest_address_low; /*00E8 00EB last used message accelerator destination address low*/
+ u_int32_t last_used_message_dest_address_high; /*00EC 00EF last used message accelerator destination address high*/
+ u_int32_t message_done_queue_base_address_low; /*00F0 00F3 message accelerator completion queue base address low*/
+ u_int32_t message_done_queue_base_address_high; /*00F4 00F7 message accelerator completion queue base address high*/
+ u_int32_t host_diagnostic; /*00F8 00FB*/
+ u_int32_t write_sequence; /*00FC 00FF*/
+ u_int32_t reserved1[34]; /*0100 0187*/
+ u_int32_t reserved2[1950]; /*0188 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*/
+};
+
+/*
+*********************************************************************
+**
+*********************************************************************
+*/
+struct MessageUnit_UNION
+{
+ union {
+ struct HBA_MessageUnit hbamu;
+ struct HBB_MessageUnit hbbmu;
+ struct HBC_MessageUnit hbcmu;
+ } muu;
+};
+
/*
*************************************************************
*************************************************************
@@ -3874,83 +4285,6 @@ struct SENSE_DATA {
** 0FFCH ] 1004 Index Registers
*******************************************************************************
*/
-struct HBA_MessageUnit
-{
- u_int32_t resrved0[4]; /*0000 000F*/
- u_int32_t inbound_msgaddr0; /*0010 0013*/
- u_int32_t inbound_msgaddr1; /*0014 0017*/
- u_int32_t outbound_msgaddr0; /*0018 001B*/
- u_int32_t outbound_msgaddr1; /*001C 001F*/
- u_int32_t inbound_doorbell; /*0020 0023*/
- u_int32_t inbound_intstatus; /*0024 0027*/
- u_int32_t inbound_intmask; /*0028 002B*/
- u_int32_t outbound_doorbell; /*002C 002F*/
- u_int32_t outbound_intstatus; /*0030 0033*/
- u_int32_t outbound_intmask; /*0034 0037*/
- u_int32_t reserved1[2]; /*0038 003F*/
- u_int32_t inbound_queueport; /*0040 0043*/
- u_int32_t outbound_queueport; /*0044 0047*/
- u_int32_t reserved2[2]; /*0048 004F*/
- u_int32_t reserved3[492]; /*0050 07FF ......local_buffer 492*/
- u_int32_t reserved4[128]; /*0800 09FF 128*/
- u_int32_t msgcode_rwbuffer[256]; /*0a00 0DFF 256*/
- u_int32_t message_wbuffer[32]; /*0E00 0E7F 32*/
- u_int32_t reserved5[32]; /*0E80 0EFF 32*/
- u_int32_t message_rbuffer[32]; /*0F00 0F7F 32*/
- u_int32_t reserved6[32]; /*0F80 0FFF 32*/
-};
-/*
-*********************************************************************
-**
-*********************************************************************
-*/
-struct HBB_DOORBELL
-{
- u_int8_t doorbell_reserved[132096]; /*reserved */
- u_int32_t drv2iop_doorbell; /*offset 0x00020400:00,01,02,03: window of "instruction flags" from driver to iop */
- u_int32_t drv2iop_doorbell_mask; /* 04,05,06,07: doorbell mask */
- u_int32_t iop2drv_doorbell; /* 08,09,10,11: window of "instruction flags" from iop to driver */
- u_int32_t iop2drv_doorbell_mask; /* 12,13,14,15: doorbell mask */
-};
-/*
-*********************************************************************
-**
-*********************************************************************
-*/
-struct HBB_RWBUFFER
-{
- u_int8_t message_reserved0[64000]; /*reserved */
- u_int32_t msgcode_rwbuffer[256]; /*offset 0x0000fa00: 0, 1, 2, 3,...,1023: message code read write 1024bytes */
- u_int32_t message_wbuffer[32]; /*offset 0x0000fe00:1024,1025,1026,1027,...,1151: user space data to iop 128bytes */
- u_int32_t message_reserved1[32]; /* 1152,1153,1154,1155,...,1279: message reserved*/
- u_int32_t message_rbuffer[32]; /*offset 0x0000ff00:1280,1281,1282,1283,...,1407: iop data to user space 128bytes */
-};
-/*
-*********************************************************************
-**
-*********************************************************************
-*/
-struct HBB_MessageUnit
-{
- u_int32_t post_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE]; /* post queue buffer for iop */
- u_int32_t done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE]; /* done queue buffer for iop */
- int32_t postq_index; /* post queue index */
- int32_t doneq_index; /* done queue index */
- struct HBB_DOORBELL *hbb_doorbell;
- struct HBB_RWBUFFER *hbb_rwbuffer;
-};
-/*
-*********************************************************************
-**
-*********************************************************************
-*/
-struct MessageUnit_UNION
-{
- union {
- struct HBA_MessageUnit hbamu;
- struct HBB_MessageUnit hbbmu;
- } muu;
-};
/*
*****************************************************************************
** Theory of MU Operation
OpenPOWER on IntegriCloud