diff options
author | delphij <delphij@FreeBSD.org> | 2010-07-21 18:50:24 +0000 |
---|---|---|
committer | delphij <delphij@FreeBSD.org> | 2010-07-21 18:50:24 +0000 |
commit | 9f0f49f9528dd9a8e493d68f20aa752708a73f2c (patch) | |
tree | db6ecb7bff66cb0f9030c44a5c7c3fa6375ecfcb | |
parent | 7ee117f1d70c1044ced4673197a63e5918787e22 (diff) | |
download | FreeBSD-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
-rw-r--r-- | sys/dev/arcmsr/arcmsr.c | 1132 | ||||
-rw-r--r-- | sys/dev/arcmsr/arcmsr.h | 614 |
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 |