svn commit: r210836 - stable/8/sys/dev/arcmsr
Xin LI
delphij at FreeBSD.org
Wed Aug 4 01:36:49 UTC 2010
Author: delphij
Date: Wed Aug 4 01:36:48 2010
New Revision: 210836
URL: http://svn.freebsd.org/changeset/base/210836
Log:
MFC r210358:
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]
Modified:
stable/8/sys/dev/arcmsr/arcmsr.c
stable/8/sys/dev/arcmsr/arcmsr.h
Directory Properties:
stable/8/sys/ (props changed)
stable/8/sys/amd64/include/xen/ (props changed)
stable/8/sys/cddl/contrib/opensolaris/ (props changed)
stable/8/sys/contrib/dev/acpica/ (props changed)
stable/8/sys/contrib/pf/ (props changed)
stable/8/sys/dev/xen/xenpci/ (props changed)
Modified: stable/8/sys/dev/arcmsr/arcmsr.c
==============================================================================
--- stable/8/sys/dev/arcmsr/arcmsr.c Wed Aug 4 01:34:35 2010 (r210835)
+++ stable/8/sys/dev/arcmsr/arcmsr.c Wed Aug 4 01:36:48 2010 (r210836)
@@ -2,15 +2,15 @@
*****************************************************************************************
** O.S : FreeBSD
** FILE NAME : arcmsr.c
-** BY : Erich Chen
+** BY : Erich Chen, Ching Huang
** Description: SCSI RAID Device Driver for
-** ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX) SATA/SAS RAID HOST Adapter
+** ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX/ARC188x) SATA/SAS RAID HOST Adapter
** ARCMSR RAID Host adapter
** [RAID controller:INTEL 331(PCI-X) 341(PCI-EXPRESS) chip set]
******************************************************************************************
************************************************************************
**
-** Copyright (c) 2004-2006 ARECA Co. Ltd.
+** Copyright (c) 2004-2010 ARECA Co. Ltd.
** Erich Chen, Taipei Taiwan All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
@@ -57,6 +57,10 @@
** 1.20.00.15 10/10/2007 Erich Chen support new RAID adapter type ARC120x
** 1.20.00.16 10/10/2009 Erich Chen Bug fix for RAID adapter type ARC120x
** bus_dmamem_alloc() with BUS_DMA_ZERO
+** 1.20.00.17 07/15/2010 Ching Huang Added support ARC1880
+** report CAM_DEV_NOT_THERE instead of CAM_SEL_TIMEOUT when device failed,
+** prevent cam_periph_error removing all LUN devices of one Target id
+** for any one LUN device failed
******************************************************************************************
* $FreeBSD$
*/
@@ -90,6 +94,8 @@
#include <cam/cam.h>
#include <cam/cam_ccb.h>
#include <cam/cam_sim.h>
+#include <cam/cam_periph.h>
+#include <cam/cam_xpt_periph.h>
#include <cam/cam_xpt_sim.h>
#include <cam/cam_debug.h>
#include <cam/scsi/scsi_all.h>
@@ -165,6 +171,8 @@ static void arcmsr_build_srb(struct Comm
static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb);
static int arcmsr_resume(device_t dev);
static int arcmsr_suspend(device_t dev);
+static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb);
+static void arcmsr_polling_devmap(void* arg);
/*
**************************************************************************
**************************************************************************
@@ -191,7 +199,6 @@ static device_method_t arcmsr_methods[]=
DEVMETHOD(device_shutdown, arcmsr_shutdown),
DEVMETHOD(device_suspend, arcmsr_suspend),
DEVMETHOD(device_resume, arcmsr_resume),
-
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_driver_added, bus_generic_driver_added),
{ 0, 0 }
@@ -215,7 +222,7 @@ MODULE_DEPEND(arcmsr, cam, 1, 1, 1);
#ifndef D_VERSION
#define D_VERSION 0x20011966
#endif
- static struct cdevsw arcmsr_cdevsw={
+static struct cdevsw arcmsr_cdevsw={
#if __FreeBSD_version > 502010
.d_version = D_VERSION,
#endif
@@ -228,7 +235,7 @@ MODULE_DEPEND(arcmsr, cam, 1, 1, 1);
#else
#define ARCMSR_CDEV_MAJOR 180
- static struct cdevsw arcmsr_cdevsw = {
+static struct cdevsw arcmsr_cdevsw = {
arcmsr_open, /* open */
arcmsr_close, /* close */
noread, /* read */
@@ -244,7 +251,10 @@ MODULE_DEPEND(arcmsr, cam, 1, 1, 1);
0 /* flags */
};
#endif
-
+/*
+**************************************************************************
+**************************************************************************
+*/
#if __FreeBSD_version < 500005
static int arcmsr_open(dev_t dev, int flags, int fmt, struct proc *proc)
#else
@@ -328,18 +338,21 @@ static u_int32_t arcmsr_disable_allintr(
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
/* disable all outbound interrupt */
- intmask_org=CHIP_REG_READ32(HBA_MessageUnit,
- 0, outbound_intmask)|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE; /* disable outbound message0 int */
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE);
+ intmask_org=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intmask); /* disable outbound message0 int */
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE);
}
break;
case ACB_ADAPTER_TYPE_B: {
/* disable all outbound interrupt */
intmask_org=CHIP_REG_READ32(HBB_DOORBELL,
0, iop2drv_doorbell_mask) & (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); /* disable outbound message0 int */
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, iop2drv_doorbell_mask, 0); /* disable all interrupt */
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell_mask, 0); /* disable all interrupt */
+ }
+ break;
+ case ACB_ADAPTER_TYPE_C: {
+ /* disable all outbound interrupt */
+ intmask_org=CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_mask) ; /* disable outbound message0 int */
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org|ARCMSR_HBCMU_ALL_INTMASKENABLE);
}
break;
}
@@ -356,19 +369,25 @@ static void arcmsr_enable_allintr( struc
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
/* enable outbound Post Queue, outbound doorbell Interrupt */
- mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE);
+ mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE);
CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org & mask);
acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff;
}
break;
case ACB_ADAPTER_TYPE_B: {
- /* disable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */
- mask=(ARCMSR_IOP2DRV_DATA_WRITE_OK|ARCMSR_IOP2DRV_DATA_READ_OK|ARCMSR_IOP2DRV_CDB_DONE);
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, iop2drv_doorbell_mask, intmask_org | mask); /*1=interrupt enable, 0=interrupt disable*/
+ /* enable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */
+ mask=(ARCMSR_IOP2DRV_DATA_WRITE_OK|ARCMSR_IOP2DRV_DATA_READ_OK|ARCMSR_IOP2DRV_CDB_DONE|ARCMSR_IOP2DRV_MESSAGE_CMD_DONE);
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell_mask, intmask_org | mask); /*1=interrupt enable, 0=interrupt disable*/
acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f;
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ /* enable outbound Post Queue, outbound doorbell Interrupt */
+ mask=~(ARCMSR_HBCMU_UTILITY_A_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK);
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org & mask);
+ acb->outbound_int_enable= ~(intmask_org & mask) & 0x0000000f;
+ }
+ break;
}
return;
}
@@ -383,10 +402,8 @@ static u_int8_t arcmsr_hba_wait_msgint_r
do {
for(Index=0; Index < 100; Index++) {
- if(CHIP_REG_READ32(HBA_MessageUnit,
- 0, outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/
+ if(CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/
return TRUE;
}
UDELAY(10000);
@@ -405,12 +422,29 @@ static u_int8_t arcmsr_hbb_wait_msgint_r
do {
for(Index=0; Index < 100; Index++) {
- if(CHIP_REG_READ32(HBB_DOORBELL,
- 0, iop2drv_doorbell) & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
+ if(CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
+ return TRUE;
+ }
+ UDELAY(10000);
+ }/*max 1 seconds*/
+ }while(Retries++ < 20);/*max 20 sec*/
+ return FALSE;
+}
+/*
+**********************************************************************
+**********************************************************************
+*/
+static u_int8_t arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock *acb)
+{
+ u_int32_t Index;
+ u_int8_t Retries=0x00;
+
+ do {
+ for(Index=0; Index < 100; Index++) {
+ if(CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) {
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);/*clear interrupt*/
return TRUE;
}
UDELAY(10000);
@@ -426,8 +460,7 @@ static void arcmsr_flush_hba_cache(struc
{
int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
do {
if(arcmsr_hba_wait_msgint_ready(acb)) {
break;
@@ -460,6 +493,25 @@ static void arcmsr_flush_hbb_cache(struc
************************************************************************
************************************************************************
*/
+static void arcmsr_flush_hbc_cache(struct AdapterControlBlock *acb)
+{
+ int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */
+
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
+ do {
+ if(arcmsr_hbc_wait_msgint_ready(acb)) {
+ break;
+ } else {
+ retry_count--;
+ }
+ }while(retry_count!=0);
+ return;
+}
+/*
+************************************************************************
+************************************************************************
+*/
static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
{
switch (acb->adapter_type) {
@@ -471,6 +523,10 @@ static void arcmsr_flush_adapter_cache(s
arcmsr_flush_hbb_cache(acb);
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ arcmsr_flush_hbc_cache(acb);
+ }
+ break;
}
return;
}
@@ -482,10 +538,10 @@ static int arcmsr_suspend(device_t dev)
{
struct AdapterControlBlock *acb = device_get_softc(dev);
- /* disable all outbound interrupt */
- arcmsr_disable_allintr(acb);
/* flush controller */
arcmsr_iop_parking(acb);
+ /* disable all outbound interrupt */
+ arcmsr_disable_allintr(acb);
return(0);
}
/*
@@ -515,12 +571,10 @@ static void arcmsr_async(void *cb_arg, u
case AC_LOST_DEVICE:
target_id=xpt_path_target_id(path);
target_lun=xpt_path_lun_id(path);
- if((target_id > ARCMSR_MAX_TARGETID)
- || (target_lun > ARCMSR_MAX_TARGETLUN)) {
+ if((target_id > ARCMSR_MAX_TARGETID) || (target_lun > ARCMSR_MAX_TARGETLUN)) {
break;
}
- printf("%s:scsi id%d lun%d device lost \n"
- , device_get_name(acb->pci_dev), target_id, target_lun);
+ printf("%s:scsi id=%d lun=%d device lost \n", device_get_name(acb->pci_dev), target_id, target_lun);
break;
default:
break;
@@ -589,8 +643,7 @@ static void arcmsr_abort_hba_allcmd(stru
{
CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD);
if(!arcmsr_hba_wait_msgint_ready(acb)) {
- printf("arcmsr%d: wait 'abort all outstanding command' timeout \n"
- , acb->pci_unit);
+ printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
}
return;
}
@@ -602,8 +655,20 @@ static void arcmsr_abort_hbb_allcmd(stru
{
CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_ABORT_CMD);
if(!arcmsr_hbb_wait_msgint_ready(acb)) {
- printf("arcmsr%d: wait 'abort all outstanding command' timeout \n"
- , acb->pci_unit);
+ printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
+ }
+ return;
+}
+/*
+*********************************************************************
+*********************************************************************
+*/
+static void arcmsr_abort_hbc_allcmd(struct AdapterControlBlock *acb)
+{
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD);
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
+ if(!arcmsr_hbc_wait_msgint_ready(acb)) {
+ printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
}
return;
}
@@ -622,6 +687,10 @@ static void arcmsr_abort_allcmd(struct A
arcmsr_abort_hbb_allcmd(acb);
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ arcmsr_abort_hbc_allcmd(acb);
+ }
+ break;
}
return;
}
@@ -629,14 +698,13 @@ static void arcmsr_abort_allcmd(struct A
**************************************************************************
**************************************************************************
*/
-static void arcmsr_report_srb_state(struct AdapterControlBlock *acb,
- struct CommandControlBlock *srb, u_int32_t flag_srb)
+static void arcmsr_report_srb_state(struct AdapterControlBlock *acb, struct CommandControlBlock *srb, u_int16_t error)
{
int target, lun;
target=srb->pccb->ccb_h.target_id;
lun=srb->pccb->ccb_h.target_lun;
- if((flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR)==0) {
+ if(error == FALSE) {
if(acb->devstate[target][lun]==ARECA_RAID_GONE) {
acb->devstate[target][lun]=ARECA_RAID_GOOD;
}
@@ -646,12 +714,10 @@ static void arcmsr_report_srb_state(stru
switch(srb->arcmsr_cdb.DeviceStatus) {
case ARCMSR_DEV_SELECT_TIMEOUT: {
if(acb->devstate[target][lun]==ARECA_RAID_GOOD) {
- printf( "arcmsr%d: select timeout"
- ", raid volume was kicked out \n"
- , acb->pci_unit);
+ printf( "arcmsr%d: Target=%x, Lun=%x, selection timeout, raid volume was lost\n", acb->pci_unit, target, lun);
}
acb->devstate[target][lun]=ARECA_RAID_GONE;
- srb->pccb->ccb_h.status |= CAM_SEL_TIMEOUT;
+ srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
arcmsr_srb_complete(srb, 1);
}
break;
@@ -669,11 +735,8 @@ static void arcmsr_report_srb_state(stru
}
break;
default:
- printf("arcmsr%d: scsi id=%d lun=%d"
- "isr get command error done,"
- "but got unknow DeviceStatus=0x%x \n"
- , acb->pci_unit, target, lun
- ,srb->arcmsr_cdb.DeviceStatus);
+ printf("arcmsr%d: scsi id=%d lun=%d isr got command error done,but got unknow DeviceStatus=0x%x \n"
+ , acb->pci_unit, target, lun ,srb->arcmsr_cdb.DeviceStatus);
acb->devstate[target][lun]=ARECA_RAID_GONE;
srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY;
/*unknow error or crc error just for retry*/
@@ -687,29 +750,34 @@ static void arcmsr_report_srb_state(stru
**************************************************************************
**************************************************************************
*/
-static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t flag_srb)
+static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t flag_srb, u_int16_t error)
{
struct CommandControlBlock *srb;
/* check if command done with no error*/
- srb=(struct CommandControlBlock *)
- (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
+ switch (acb->adapter_type) {
+ case ACB_ADAPTER_TYPE_C:
+ srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFF0));/*frame must be 32 bytes aligned*/
+ break;
+ case ACB_ADAPTER_TYPE_A:
+ case ACB_ADAPTER_TYPE_B:
+ default:
+ srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
+ break;
+ }
if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) {
if(srb->startdone==ARCMSR_SRB_ABORTED) {
- printf("arcmsr%d: srb='%p' isr got aborted command \n"
- , acb->pci_unit, srb);
+ printf("arcmsr%d: srb='%p' isr got aborted command \n", acb->pci_unit, srb);
srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
arcmsr_srb_complete(srb, 1);
return;
}
printf("arcmsr%d: isr get an illegal srb command done"
- "acb='%p' srb='%p' srbacb='%p' startdone=0x%x"
- "srboutstandingcount=%d \n",
- acb->pci_unit, acb, srb, srb->acb,
- srb->startdone, acb->srboutstandingcount);
+ "acb='%p' srb='%p' srbacb='%p' startdone=0x%xsrboutstandingcount=%d \n",
+ acb->pci_unit, acb, srb, srb->acb,srb->startdone, acb->srboutstandingcount);
return;
}
- arcmsr_report_srb_state(acb, srb, flag_srb);
+ arcmsr_report_srb_state(acb, srb, error);
return;
}
/*
@@ -720,20 +788,18 @@ static void arcmsr_done4abort_postqueue(
{
int i=0;
u_int32_t flag_srb;
+ u_int16_t error;
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
u_int32_t outbound_intstatus;
/*clear and abort all outbound posted Q*/
- outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit,
- 0, outbound_intstatus) & acb->outbound_int_enable;
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/
- while(((flag_srb=CHIP_REG_READ32(HBA_MessageUnit,
- 0, outbound_queueport)) != 0xFFFFFFFF)
- && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) {
- arcmsr_drain_donequeue(acb, flag_srb);
+ outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable;
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/
+ while(((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_queueport)) != 0xFFFFFFFF) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) {
+ error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
+ arcmsr_drain_donequeue(acb, flag_srb, error);
}
}
break;
@@ -741,13 +807,12 @@ static void arcmsr_done4abort_postqueue(
struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu;
/*clear all outbound posted Q*/
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, iop2drv_doorbell,
- ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */
for(i=0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) {
if((flag_srb=phbbmu->done_qbuffer[i])!=0) {
phbbmu->done_qbuffer[i]=0;
- arcmsr_drain_donequeue(acb, flag_srb);
+ error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
+ arcmsr_drain_donequeue(acb, flag_srb, error);
}
phbbmu->post_qbuffer[i]=0;
}/*drain reply FIFO*/
@@ -755,6 +820,15 @@ static void arcmsr_done4abort_postqueue(
phbbmu->postq_index=0;
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+
+ while((CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) {
+ flag_srb=CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low);
+ error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE;
+ arcmsr_drain_donequeue(acb, flag_srb, error);
+ }
+ }
+ break;
}
return;
}
@@ -873,7 +947,10 @@ static void arcmsr_build_srb(struct Comm
if( arccdbsize > 256) {
arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_SGL_BSIZE;
}
+ } else {
+ arcmsr_cdb->DataLength = 0;
}
+ srb->arc_cdb_size=arccdbsize;
return;
}
/*
@@ -885,19 +962,16 @@ static void arcmsr_post_srb(struct Adapt
u_int32_t cdb_shifted_phyaddr=(u_int32_t) srb->cdb_shifted_phyaddr;
struct ARCMSR_CDB * arcmsr_cdb=(struct ARCMSR_CDB *)&srb->arcmsr_cdb;
- bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap,
- (srb->srb_flags & SRB_FLAG_WRITE) ? BUS_DMASYNC_POSTWRITE:BUS_DMASYNC_POSTREAD);
+ bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, (srb->srb_flags & SRB_FLAG_WRITE) ? BUS_DMASYNC_POSTWRITE:BUS_DMASYNC_POSTREAD);
atomic_add_int(&acb->srboutstandingcount, 1);
srb->startdone=ARCMSR_SRB_START;
+
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) {
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, inbound_queueport,
- cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE);
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE);
} else {
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, inbound_queueport, cdb_shifted_phyaddr);
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_shifted_phyaddr);
}
}
break;
@@ -909,17 +983,32 @@ static void arcmsr_post_srb(struct Adapt
ending_index=((index+1)%ARCMSR_MAX_HBB_POSTQUEUE);
phbbmu->post_qbuffer[ending_index]=0;
if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) {
- phbbmu->post_qbuffer[index]=
- cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE;
+ phbbmu->post_qbuffer[index]= cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE;
} else {
- phbbmu->post_qbuffer[index]=
- cdb_shifted_phyaddr;
+ phbbmu->post_qbuffer[index]= cdb_shifted_phyaddr;
}
index++;
index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */
phbbmu->postq_index=index;
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED);
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED);
+ }
+ break;
+ case ACB_ADAPTER_TYPE_C:
+ {
+ u_int32_t ccb_post_stamp, arc_cdb_size, cdb_phyaddr_hi32;
+
+ arc_cdb_size=(srb->arc_cdb_size>0x300)?0x300:srb->arc_cdb_size;
+ ccb_post_stamp=(cdb_shifted_phyaddr | ((arc_cdb_size-1) >> 6) | 1);
+ cdb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high;
+ if(cdb_phyaddr_hi32)
+ {
+ CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_high, cdb_phyaddr_hi32);
+ CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp);
+ }
+ else
+ {
+ CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp);
+ }
}
break;
}
@@ -946,6 +1035,12 @@ static struct QBUFFER * arcmsr_get_iop_r
qbuffer=(struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_rbuffer;
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ struct HBC_MessageUnit *phbcmu=(struct HBC_MessageUnit *)acb->pmu;
+
+ qbuffer=(struct QBUFFER *)&phbcmu->message_rbuffer;
+ }
+ break;
}
return(qbuffer);
}
@@ -970,6 +1065,12 @@ static struct QBUFFER * arcmsr_get_iop_w
qbuffer=(struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_wbuffer;
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ struct HBC_MessageUnit *phbcmu=(struct HBC_MessageUnit *)acb->pmu;
+
+ qbuffer=(struct QBUFFER *)&phbcmu->message_wbuffer;
+ }
+ break;
}
return(qbuffer);
}
@@ -982,16 +1083,18 @@ static void arcmsr_iop_message_read(stru
switch (acb->adapter_type) {
case ACB_ADAPTER_TYPE_A: {
/* let IOP know data has been read */
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
}
break;
case ACB_ADAPTER_TYPE_B: {
/* let IOP know data has been read */
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK);
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK);
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ /* let IOP know data has been read */
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK);
+ }
}
return;
}
@@ -1007,8 +1110,7 @@ static void arcmsr_iop_message_wrote(str
** push inbound doorbell tell iop, driver data write ok
** and wait reply on next hwinterrupt for next Qbuffer post
*/
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK);
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK);
}
break;
case ACB_ADAPTER_TYPE_B: {
@@ -1016,8 +1118,15 @@ static void arcmsr_iop_message_wrote(str
** push inbound doorbell tell iop, driver data write ok
** and wait reply on next hwinterrupt for next Qbuffer post
*/
- CHIP_REG_WRITE32(HBB_DOORBELL,
- 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_WRITE_OK);
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_WRITE_OK);
+ }
+ break;
+ case ACB_ADAPTER_TYPE_C: {
+ /*
+ ** push inbound doorbell tell iop, driver data write ok
+ ** and wait reply on next hwinterrupt for next Qbuffer post
+ */
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK);
}
break;
}
@@ -1064,7 +1173,7 @@ static void arcmsr_stop_hba_bgrb(struct
CHIP_REG_WRITE32(HBA_MessageUnit,
0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
if(!arcmsr_hba_wait_msgint_ready(acb)) {
- printf("arcmsr%d: wait 'stop adapter rebulid' timeout \n"
+ printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n"
, acb->pci_unit);
}
return;
@@ -1079,7 +1188,7 @@ static void arcmsr_stop_hbb_bgrb(struct
CHIP_REG_WRITE32(HBB_DOORBELL,
0, drv2iop_doorbell, ARCMSR_MESSAGE_STOP_BGRB);
if(!arcmsr_hbb_wait_msgint_ready(acb)) {
- printf( "arcmsr%d: wait 'stop adapter rebulid' timeout \n"
+ printf( "arcmsr%d: wait 'stop adapter background rebulid' timeout \n"
, acb->pci_unit);
}
return;
@@ -1088,6 +1197,20 @@ static void arcmsr_stop_hbb_bgrb(struct
************************************************************************
************************************************************************
*/
+static void arcmsr_stop_hbc_bgrb(struct AdapterControlBlock *acb)
+{
+ acb->acb_flags &=~ACB_F_MSG_START_BGRB;
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
+ if(!arcmsr_hbc_wait_msgint_ready(acb)) {
+ printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit);
+ }
+ return;
+}
+/*
+************************************************************************
+************************************************************************
+*/
static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
{
switch (acb->adapter_type) {
@@ -1099,6 +1222,10 @@ static void arcmsr_stop_adapter_bgrb(str
arcmsr_stop_hbb_bgrb(acb);
}
break;
+ case ACB_ADAPTER_TYPE_C: {
+ arcmsr_stop_hbc_bgrb(acb);
+ }
+ break;
}
return;
}
@@ -1121,18 +1248,6 @@ static void arcmsr_poll(struct cam_sim *
return;
}
/*
-**********************************************************************
-**********************************************************************
-*/
-static void arcmsr_intr_handler(void *arg)
-{
- struct AdapterControlBlock *acb=(struct AdapterControlBlock *)arg;
-
- ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
- arcmsr_interrupt(acb);
- ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
-}
-/*
**************************************************************************
**************************************************************************
*/
@@ -1210,6 +1325,187 @@ static void arcmsr_iop2drv_data_read_han
}
return;
}
+
+static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb)
+{
+/*
+ if (ccb->ccb_h.status != CAM_REQ_CMP)
+ printf("arcmsr_rescanLun_cb: Rescan Target=%x, lun=%x, failure status=%x\n",ccb->ccb_h.target_id,ccb->ccb_h.target_lun,ccb->ccb_h.status);
+ else
+ printf("arcmsr_rescanLun_cb: Rescan lun successfully!\n");
+*/
+ xpt_free_path(ccb->ccb_h.path);
+ xpt_free_ccb(ccb);
+}
+
+static void arcmsr_rescan_lun(struct AdapterControlBlock *acb, int target, int lun)
+{
+ struct cam_path *path;
+ union ccb *ccb;
+
+ if ((ccb = (union ccb *)xpt_alloc_ccb_nowait()) == NULL)
+ return;
+ if (xpt_create_path(&path, xpt_periph, cam_sim_path(acb->psim), target, lun) != CAM_REQ_CMP)
+ {
+ xpt_free_ccb(ccb);
+ return;
+ }
+/* printf("arcmsr_rescan_lun: Rescan Target=%x, Lun=%x\n", target, lun); */
+ bzero(ccb, sizeof(union ccb));
+ xpt_setup_ccb(&ccb->ccb_h, path, 5);
+ ccb->ccb_h.func_code = XPT_SCAN_LUN;
+ ccb->ccb_h.cbfcnp = arcmsr_rescanLun_cb;
+ ccb->crcn.flags = CAM_FLAG_NONE;
+ xpt_action(ccb);
+ return;
+}
+
+
+static void arcmsr_abort_dr_ccbs(struct AdapterControlBlock *acb, int target, int lun)
+{
+ struct CommandControlBlock *srb;
+ u_int32_t intmask_org;
+ int i;
+
+ ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
+ /* disable all outbound interrupts */
+ intmask_org = arcmsr_disable_allintr(acb);
+ for (i = 0; i < ARCMSR_MAX_FREESRB_NUM; i++)
+ {
+ srb = acb->psrb_pool[i];
+ if (srb->startdone == ARCMSR_SRB_START)
+ {
+ if((target == srb->pccb->ccb_h.target_id) && (lun == srb->pccb->ccb_h.target_lun))
+ {
+ srb->startdone = ARCMSR_SRB_ABORTED;
+ srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
+ arcmsr_srb_complete(srb, 1);
+ }
+ }
+ }
+ /* enable outbound Post Queue, outbound doorbell Interrupt */
+ arcmsr_enable_allintr(acb, intmask_org);
+ ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
+}
+
+
+/*
+**************************************************************************
+**************************************************************************
+*/
+static void arcmsr_dr_handle(struct AdapterControlBlock *acb) {
+ u_int32_t devicemap;
+ u_int32_t target, lun;
+ u_int32_t deviceMapCurrent[4]={0};
+ u_int8_t *pDevMap;
+
+ switch (acb->adapter_type) {
+ case ACB_ADAPTER_TYPE_A:
+ devicemap = offsetof(struct HBA_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
+ for (target= 0; target < 4; target++)
+ {
+ deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap);
+ devicemap += 4;
+ }
+ break;
+
+ case ACB_ADAPTER_TYPE_B:
+ devicemap = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
+ for (target= 0; target < 4; target++)
+ {
+ deviceMapCurrent[target]=bus_space_read_4(acb->btag[1], acb->bhandle[1], devicemap);
+ devicemap += 4;
+ }
+ break;
+
+ case ACB_ADAPTER_TYPE_C:
+ devicemap = offsetof(struct HBC_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
+ for (target= 0; target < 4; target++)
+ {
+ deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap);
+ devicemap += 4;
+ }
+ break;
+ }
+ if(acb->acb_flags & ACB_F_BUS_HANG_ON)
+ {
+ acb->acb_flags &= ~ACB_F_BUS_HANG_ON;
+ }
+ /*
+ ** adapter posted CONFIG message
+ ** copy the new map, note if there are differences with the current map
+ */
+ pDevMap = (u_int8_t *)&deviceMapCurrent[0];
+ for (target= 0; target < ARCMSR_MAX_TARGETID - 1; target++)
+ {
+ if (*pDevMap != acb->device_map[target])
+ {
+ u_int8_t difference, bit_check;
+
+ difference= *pDevMap ^ acb->device_map[target];
+ for(lun=0; lun < ARCMSR_MAX_TARGETLUN; lun++)
+ {
+ bit_check=(1 << lun); /*check bit from 0....31*/
+ if(difference & bit_check)
+ {
+ if(acb->device_map[target] & bit_check)
+ {/* unit departed */
+ printf("arcmsr_dr_handle: Target=%x, lun=%x, GONE!!!\n",target,lun);
+ arcmsr_abort_dr_ccbs(acb, target, lun);
+ arcmsr_rescan_lun(acb, target, lun);
+ acb->devstate[target][lun] = ARECA_RAID_GONE;
+ }
+ else
+ {/* unit arrived */
+ printf("arcmsr_dr_handle: Target=%x, lun=%x, ARRIVING!!!\n",target,lun);
+ arcmsr_rescan_lun(acb, target, lun);
+ acb->devstate[target][lun] = ARECA_RAID_GOOD;
+ }
+ }
+ }
+/* printf("arcmsr_dr_handle: acb->device_map[%x]=0x%x, deviceMapCurrent[%x]=%x\n",target,acb->device_map[target],target,*pDevMap); */
+ acb->device_map[target]= *pDevMap;
+ }
+ pDevMap++;
+ }
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
+static void arcmsr_hba_message_isr(struct AdapterControlBlock *acb) {
+ u_int32_t outbound_message;
+
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);
+ outbound_message = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[0]);
+ if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
+ arcmsr_dr_handle( acb );
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
+static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) {
+ u_int32_t outbound_message;
+
+ /* clear interrupts */
+ CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);
+ outbound_message = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0]);
+ if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
+ arcmsr_dr_handle( acb );
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
+static void arcmsr_hbc_message_isr(struct AdapterControlBlock *acb) {
+ u_int32_t outbound_message;
+
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);
+ outbound_message = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[0]);
+ if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
+ arcmsr_dr_handle( acb );
+}
/*
**************************************************************************
**************************************************************************
@@ -1241,9 +1537,38 @@ static void arcmsr_hba_doorbell_isr(stru
**************************************************************************
**************************************************************************
*/
+static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb)
+{
+ u_int32_t outbound_doorbell;
+
+ /*
+ *******************************************************************
+ ** Maybe here we need to check wrqbuffer_lock is lock or not
+ ** DOORBELL: din! don!
+ ** check if there are any mail need to pack from firmware
+ *******************************************************************
+ */
+ outbound_doorbell=CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell);
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell); /* clear doorbell interrupt */
+ if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) {
+ arcmsr_iop2drv_data_wrote_handle(acb);
+ }
+ if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) {
+ arcmsr_iop2drv_data_read_handle(acb);
+ }
+ if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) {
+ arcmsr_hbc_message_isr(acb); /* messenger of "driver to iop commands" */
+ }
+ return;
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb)
{
u_int32_t flag_srb;
+ u_int16_t error;
/*
*****************************************************************************
@@ -1255,7 +1580,8 @@ static void arcmsr_hba_postqueue_isr(str
while((flag_srb=CHIP_REG_READ32(HBA_MessageUnit,
0, outbound_queueport)) != 0xFFFFFFFF) {
/* check if command done with no error*/
- arcmsr_drain_donequeue(acb, flag_srb);
+ error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
+ arcmsr_drain_donequeue(acb, flag_srb, error);
} /*drain reply FIFO*/
return;
}
@@ -1268,6 +1594,7 @@ static void arcmsr_hbb_postqueue_isr(str
struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu;
u_int32_t flag_srb;
int index;
+ u_int16_t error;
/*
*****************************************************************************
@@ -1283,7 +1610,38 @@ static void arcmsr_hbb_postqueue_isr(str
index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */
phbbmu->doneq_index=index;
/* check if command done with no error*/
- arcmsr_drain_donequeue(acb, flag_srb);
+ error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
+ arcmsr_drain_donequeue(acb, flag_srb, error);
+ } /*drain reply FIFO*/
+ return;
+}
+/*
+**************************************************************************
+**************************************************************************
+*/
+static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb)
+{
+ u_int32_t flag_srb,throttling=0;
+ u_int16_t error;
+
+ /*
+ *****************************************************************************
+ ** areca cdb command done
+ *****************************************************************************
+ */
+ bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+
+ while(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) {
+
+ flag_srb=CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low);
+ /* check if command done with no error*/
+ error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE;
+ arcmsr_drain_donequeue(acb, flag_srb, error);
+ if(throttling==ARCMSR_HBC_ISR_THROTTLING_LEVEL) {
+ CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING);
+ break;
+ }
+ throttling++;
} /*drain reply FIFO*/
return;
}
@@ -1299,14 +1657,12 @@ static void arcmsr_handle_hba_isr( struc
** check outbound intstatus
*********************************************
*/
- outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit,
- 0, outbound_intstatus) & acb->outbound_int_enable;
+ outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable;
if(!outbound_intstatus) {
/*it must be share irq*/
return;
}
- CHIP_REG_WRITE32(HBA_MessageUnit,
- 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/
+ CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/
/* MU doorbell interrupts*/
if(outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) {
arcmsr_hba_doorbell_isr(acb);
@@ -1315,6 +1671,9 @@ static void arcmsr_handle_hba_isr( struc
if(outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) {
arcmsr_hba_postqueue_isr(acb);
}
+ if(outbound_intstatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
+ arcmsr_hba_message_isr(acb);
+ }
return;
}
/*
@@ -1348,6 +1707,36 @@ static void arcmsr_handle_hbb_isr( struc
if(outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) {
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-stable-8
mailing list