From 44f05562dea4da444d4c2deb26452fc2e3fd6793 Mon Sep 17 00:00:00 2001 From: Scott Long Date: Sat, 8 Dec 2007 20:48:26 +0000 Subject: [PATCH] Support new ARC120x family of controllers. Many thanks for Areca's continued support of FreeBSD. Submitted by: Erich Chen @ Areca --- sys/dev/arcmsr/arcmsr.c | 2021 ++++++++++++++++++++++++++++----------- sys/dev/arcmsr/arcmsr.h | 239 +++-- 2 files changed, 1639 insertions(+), 621 deletions(-) diff --git a/sys/dev/arcmsr/arcmsr.c b/sys/dev/arcmsr/arcmsr.c index 6383cb863782..ed7be1bccfb1 100644 --- a/sys/dev/arcmsr/arcmsr.c +++ b/sys/dev/arcmsr/arcmsr.c @@ -54,7 +54,7 @@ ** code fit for SPARC64 & PPC ** 1.20.00.14 02/05/2007 Erich Chen bug fix for incorrect ccb_h.status report ** and cause g_vfs_done() read write error - +** 1.20.00.15 10/10/2007 Erich Chen support new RAID adapter type ARC120x ****************************************************************************************** * $FreeBSD$ */ @@ -121,28 +121,32 @@ #define arcmsr_htole32(x) (x) typedef struct simplelock arcmsr_lock_t; #endif + +#if !defined(CAM_NEW_TRAN_CODE) && __FreeBSD_version >= 700025 +#define CAM_NEW_TRAN_CODE 1 +#endif + #include -#define ARCMSR_SRBS_POOL_SIZE ((sizeof(struct CommandControlBlock) * ARCMSR_MAX_FREESRB_NUM)+0x20) +#define ARCMSR_SRBS_POOL_SIZE ((sizeof(struct CommandControlBlock) * ARCMSR_MAX_FREESRB_NUM)) /* ************************************************************************** ************************************************************************** */ -#define CHIP_REG_READ32(r) bus_space_read_4(acb->btag, acb->bhandle, offsetof(struct MessageUnit,r)) -#define CHIP_REG_WRITE32(r,d) bus_space_write_4(acb->btag, acb->bhandle, offsetof(struct MessageUnit,r), d) +#define CHIP_REG_READ32(s, b, r) bus_space_read_4(acb->btag[b], acb->bhandle[b], offsetof(struct s, r)) +#define CHIP_REG_WRITE32(s, b, r, d) bus_space_write_4(acb->btag[b], acb->bhandle[b], offsetof(struct s, r), d) /* ************************************************************************** ************************************************************************** */ static struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb); static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb); -static u_int8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *acb); static u_int32_t arcmsr_probe(device_t dev); static u_int32_t arcmsr_attach(device_t dev); static u_int32_t arcmsr_detach(device_t dev); static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg); static void arcmsr_iop_parking(struct AdapterControlBlock *acb); static void arcmsr_shutdown(device_t dev); -static void arcmsr_interrupt(void *arg); +static void arcmsr_interrupt(struct AdapterControlBlock *acb); static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb); static void arcmsr_free_resource(struct AdapterControlBlock *acb); static void arcmsr_bus_reset(struct AdapterControlBlock *acb); @@ -150,7 +154,7 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb); static void arcmsr_iop_init(struct AdapterControlBlock *acb); static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb); -static void arcmsr_post_Qbuffer(struct AdapterControlBlock *acb); +static void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb); static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb); static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag); static void arcmsr_iop_reset(struct AdapterControlBlock *acb); @@ -185,16 +189,16 @@ 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 } }; - + static driver_t arcmsr_driver={ "arcmsr", arcmsr_methods, sizeof(struct AdapterControlBlock) }; - + static devclass_t arcmsr_devclass; DRIVER_MODULE(arcmsr, pci, arcmsr_driver, arcmsr_devclass, 0, 0); MODULE_DEPEND(arcmsr, pci, 1, 1, 1); @@ -221,7 +225,7 @@ MODULE_DEPEND(arcmsr, cam, 1, 1, 1); }; #else #define ARCMSR_CDEV_MAJOR 180 - + static struct cdevsw arcmsr_cdevsw = { arcmsr_open, /* open */ arcmsr_close, /* close */ @@ -242,15 +246,15 @@ MODULE_DEPEND(arcmsr, cam, 1, 1, 1); #if __FreeBSD_version < 500005 static int arcmsr_open(dev_t dev, int flags, int fmt, struct proc *proc) #else - #if __FreeBSD_version < 503000 - static int arcmsr_open(dev_t dev, int flags, int fmt, struct thread *proc) - #else - static int arcmsr_open(struct cdev *dev, int flags, int fmt, d_thread_t *proc) - #endif + #if __FreeBSD_version < 503000 + static int arcmsr_open(dev_t dev, int flags, int fmt, struct thread *proc) + #else + static int arcmsr_open(struct cdev *dev, int flags, int fmt, d_thread_t *proc) + #endif #endif { #if __FreeBSD_version < 503000 - struct AdapterControlBlock *acb=dev->si_drv1; + struct AdapterControlBlock *acb=dev->si_drv1; #else int unit = minor(dev); struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); @@ -267,11 +271,11 @@ MODULE_DEPEND(arcmsr, cam, 1, 1, 1); #if __FreeBSD_version < 500005 static int arcmsr_close(dev_t dev, int flags, int fmt, struct proc *proc) #else - #if __FreeBSD_version < 503000 - static int arcmsr_close(dev_t dev, int flags, int fmt, struct thread *proc) - #else - static int arcmsr_close(struct cdev *dev, int flags, int fmt, d_thread_t *proc) - #endif + #if __FreeBSD_version < 503000 + static int arcmsr_close(dev_t dev, int flags, int fmt, struct thread *proc) + #else + static int arcmsr_close(struct cdev *dev, int flags, int fmt, d_thread_t *proc) + #endif #endif { #if __FreeBSD_version < 503000 @@ -292,11 +296,11 @@ MODULE_DEPEND(arcmsr, cam, 1, 1, 1); #if __FreeBSD_version < 500005 static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct proc *proc) #else - #if __FreeBSD_version < 503000 - static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc) - #else - static int arcmsr_ioctl(struct cdev *dev, u_long ioctl_cmd, caddr_t arg, int flags, d_thread_t *proc) - #endif + #if __FreeBSD_version < 503000 + static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc) + #else + static int arcmsr_ioctl(struct cdev *dev, u_long ioctl_cmd, caddr_t arg, int flags, d_thread_t *proc) + #endif #endif { #if __FreeBSD_version < 503000 @@ -305,24 +309,179 @@ MODULE_DEPEND(arcmsr, cam, 1, 1, 1); int unit = minor(dev); struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); #endif - + if(acb==NULL) { return ENXIO; } return(arcmsr_iop_ioctlcmd(acb, ioctl_cmd, arg)); } /* +********************************************************************** +********************************************************************** +*/ +static u_int32_t arcmsr_disable_allintr( struct AdapterControlBlock *acb) +{ + u_int32_t intmask_org=0; + + 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); + } + 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 */ + } + break; + } + return(intmask_org); +} +/* +********************************************************************** +********************************************************************** +*/ +static void arcmsr_enable_allintr( struct AdapterControlBlock *acb, u_int32_t intmask_org) +{ + u_int32_t mask; + + 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); + 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*/ + acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f; + } + break; + } + return; +} +/* +********************************************************************** +********************************************************************** +*/ +static u_int8_t arcmsr_hba_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(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); + }/*max 1 seconds*/ + }while(Retries++ < 20);/*max 20 sec*/ + return FALSE; +} +/* +********************************************************************** +********************************************************************** +*/ +static u_int8_t arcmsr_hbb_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(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 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); + do { + if(arcmsr_hba_wait_msgint_ready(acb)) { + break; + } else { + retry_count--; + } + }while(retry_count!=0); + return; +} +/* +************************************************************************ +************************************************************************ +*/ +static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) +{ + int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */ + + CHIP_REG_WRITE32(HBB_DOORBELL, + 0, drv2iop_doorbell, ARCMSR_MESSAGE_FLUSH_CACHE); + do { + if(arcmsr_hbb_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) { + case ACB_ADAPTER_TYPE_A: { + arcmsr_flush_hba_cache(acb); + } + break; + case ACB_ADAPTER_TYPE_B: { + arcmsr_flush_hbb_cache(acb); + } + break; + } + return; +} +/* ******************************************************************************* ******************************************************************************* */ static int arcmsr_suspend(device_t dev) { struct AdapterControlBlock *acb = device_get_softc(dev); - u_int32_t intmask_org; - + /* disable all outbound interrupt */ - intmask_org=CHIP_REG_READ32(outbound_intmask); - CHIP_REG_WRITE32(outbound_intmask, (intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE)); + arcmsr_disable_allintr(acb); /* flush controller */ arcmsr_iop_parking(acb); return(0); @@ -334,7 +493,7 @@ static int arcmsr_suspend(device_t dev) static int arcmsr_resume(device_t dev) { struct AdapterControlBlock *acb = device_get_softc(dev); - + arcmsr_iop_init(acb); return(0); } @@ -347,14 +506,15 @@ static void arcmsr_async(void *cb_arg, u_int32_t code, struct cam_path *path, vo struct AdapterControlBlock *acb; u_int8_t target_id, target_lun; struct cam_sim * sim; - + sim=(struct cam_sim *) cb_arg; acb =(struct AdapterControlBlock *) cam_sim_softc(sim); switch (code) { 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" @@ -365,41 +525,6 @@ static void arcmsr_async(void *cb_arg, u_int32_t code, struct cam_path *path, vo } } /* -************************************************************************ -************************************************************************ -*/ -static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) -{ - CHIP_REG_WRITE32(inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); - if(arcmsr_wait_msgint_ready(acb)) { - printf("arcmsr%d: wait 'flush adapter cache' timeout \n" - , acb->pci_unit); - } - return; -} -/* -********************************************************************** -********************************************************************** -*/ -static u_int8_t arcmsr_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(outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { - /*clear interrupt*/ - CHIP_REG_WRITE32(outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT); - return 0x00; - } - /* one us delay */ - UDELAY(10000); - }/*max 1 seconds*/ - }while(Retries++ < 20);/*max 20 sec*/ - return 0xff; -} -/* ********************************************************************** ********************************************************************** */ @@ -407,10 +532,10 @@ static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag) { struct AdapterControlBlock *acb=srb->acb; union ccb * pccb=srb->pccb; - + if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { bus_dmasync_op_t op; - + if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { op = BUS_DMASYNC_POSTREAD; } else { @@ -442,7 +567,7 @@ static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag) static void arcmsr_report_sense_info(struct CommandControlBlock *srb) { union ccb * pccb=srb->pccb; - + pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; if(&pccb->csio.sense_data) { @@ -456,15 +581,178 @@ static void arcmsr_report_sense_info(struct CommandControlBlock *srb) } /* ********************************************************************* -** +********************************************************************* +*/ +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); + } + return; +} +/* +********************************************************************* +********************************************************************* +*/ +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); + } + return; +} +/* +********************************************************************* ********************************************************************* */ static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) { - CHIP_REG_WRITE32(inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); - if(arcmsr_wait_msgint_ready(acb)) { - printf("arcmsr%d: wait 'abort all outstanding command' timeout \n" - , acb->pci_unit); + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + arcmsr_abort_hba_allcmd(acb); + } + break; + case ACB_ADAPTER_TYPE_B: { + arcmsr_abort_hbb_allcmd(acb); + } + break; + } + return; +} +/* +************************************************************************** +************************************************************************** +*/ +static void arcmsr_report_srb_state(struct AdapterControlBlock *acb, + struct CommandControlBlock *srb, u_int32_t flag_srb) +{ + 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(acb->devstate[target][lun]==ARECA_RAID_GONE) { + acb->devstate[target][lun]=ARECA_RAID_GOOD; + } + srb->pccb->ccb_h.status |= CAM_REQ_CMP; + arcmsr_srb_complete(srb, 1); + } else { + 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); + } + acb->devstate[target][lun]=ARECA_RAID_GONE; + srb->pccb->ccb_h.status |= CAM_SEL_TIMEOUT; + arcmsr_srb_complete(srb, 1); + } + break; + case ARCMSR_DEV_ABORTED: + case ARCMSR_DEV_INIT_FAIL: { + acb->devstate[target][lun]=ARECA_RAID_GONE; + srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; + arcmsr_srb_complete(srb, 1); + } + break; + case SCSISTAT_CHECK_CONDITION: { + acb->devstate[target][lun]=ARECA_RAID_GOOD; + arcmsr_report_sense_info(srb); + arcmsr_srb_complete(srb, 1); + } + 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); + acb->devstate[target][lun]=ARECA_RAID_GONE; + srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY; + /*unknow error or crc error just for retry*/ + arcmsr_srb_complete(srb, 1); + break; + } + } + return; +} +/* +************************************************************************** +************************************************************************** +*/ +static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t flag_srb) +{ + 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*/ + 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); + 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); + return; + } + arcmsr_report_srb_state(acb, srb, flag_srb); + return; +} +/* +********************************************************************** +********************************************************************** +*/ +static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) +{ + int i=0; + u_int32_t flag_srb; + + 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); + } + } + break; + case ACB_ADAPTER_TYPE_B: { + 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 */ + 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); + } + phbbmu->post_qbuffer[i]=0; + }/*drain reply FIFO*/ + phbbmu->doneq_index=0; + phbbmu->postq_index=0; + } + break; } return; } @@ -475,22 +763,16 @@ static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) static void arcmsr_iop_reset(struct AdapterControlBlock *acb) { struct CommandControlBlock *srb; - u_int32_t intmask_org, mask; + u_int32_t intmask_org; u_int32_t i=0; - - if(acb->srboutstandingcount!=0) - { + + if(acb->srboutstandingcount>0) { + /* disable all outbound interrupt */ + intmask_org=arcmsr_disable_allintr(acb); + /*clear and abort all outbound posted Q*/ + arcmsr_done4abort_postqueue(acb); /* talk to iop 331 outstanding command aborted*/ arcmsr_abort_allcmd(acb); - UDELAY(3000*1000);/*wait for 3 sec for all command aborted*/ - /* disable all outbound interrupt */ - intmask_org=CHIP_REG_READ32(outbound_intmask); - CHIP_REG_WRITE32(outbound_intmask - , intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); - /*clear all outbound posted Q*/ - for(i=0;ipsrb_pool[i]; if(srb->startdone==ARCMSR_SRB_START) { @@ -500,10 +782,7 @@ static void arcmsr_iop_reset(struct AdapterControlBlock *acb) } } /* enable all outbound interrupt */ - mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE - |ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); - CHIP_REG_WRITE32(outbound_intmask, intmask_org & mask); - /* post abort all outstanding command message to RAID controller */ + arcmsr_enable_allintr(acb, intmask_org); } atomic_set_int(&acb->srboutstandingcount, 0); acb->workingsrb_doneindex=0; @@ -514,7 +793,8 @@ static void arcmsr_iop_reset(struct AdapterControlBlock *acb) ********************************************************************** ********************************************************************** */ -static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t *dm_segs, u_int32_t nseg) +static void arcmsr_build_srb(struct CommandControlBlock *srb, + bus_dma_segment_t *dm_segs, u_int32_t nseg) { struct ARCMSR_CDB * arcmsr_cdb= &srb->arcmsr_cdb; u_int8_t * psge=(u_int8_t *)&arcmsr_cdb->u; @@ -522,20 +802,20 @@ static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t union ccb * pccb=srb->pccb; struct ccb_scsiio * pcsio= &pccb->csio; u_int32_t arccdbsize=0x30; - + memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB)); arcmsr_cdb->Bus=0; arcmsr_cdb->TargetID=pccb->ccb_h.target_id; arcmsr_cdb->LUN=pccb->ccb_h.target_lun; arcmsr_cdb->Function=1; arcmsr_cdb->CdbLength=(u_int8_t)pcsio->cdb_len; - arcmsr_cdb->Context=(unsigned long)arcmsr_cdb; + arcmsr_cdb->Context=0; bcopy(pcsio->cdb_io.cdb_bytes, arcmsr_cdb->Cdb, pcsio->cdb_len); if(nseg != 0) { struct AdapterControlBlock *acb=srb->acb; bus_dmasync_op_t op; u_int32_t length, i, cdb_sgcount=0; - + if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { op=BUS_DMASYNC_PREREAD; } else { @@ -557,11 +837,11 @@ static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t arccdbsize += sizeof(struct SG32ENTRY); } else { u_int32_t sg64s_size=0, tmplength=length; - + while(1) { u_int64_t span4G, length0; struct SG64ENTRY * pdma_sg=(struct SG64ENTRY *)psge; - + span4G=(u_int64_t)address_lo + tmplength; pdma_sg->addresshigh=address_hi; pdma_sg->address=address_lo; @@ -576,7 +856,7 @@ static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t psge += sizeof(struct SG64ENTRY); cdb_sgcount++; } else { - pdma_sg->length=tmplength|IS_SG64_ADDR; + pdma_sg->length=tmplength|IS_SG64_ADDR; sg64s_size += sizeof(struct SG64ENTRY); psge += sizeof(struct SG64ENTRY); break; @@ -592,7 +872,7 @@ static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_SGL_BSIZE; } } - return; + return; } /* ************************************************************************** @@ -602,37 +882,167 @@ 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); atomic_add_int(&acb->srboutstandingcount, 1); srb->startdone=ARCMSR_SRB_START; - if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { - CHIP_REG_WRITE32(inbound_queueport, cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE); - } else { - CHIP_REG_WRITE32(inbound_queueport, cdb_shifted_phyaddr); + 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); + } else { + CHIP_REG_WRITE32(HBA_MessageUnit, + 0, inbound_queueport, cdb_shifted_phyaddr); + } + } + break; + case ACB_ADAPTER_TYPE_B: { + struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; + int ending_index, index; + + ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); + index=phbbmu->postq_index; + 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; + } else { + 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); + ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); + } + break; } return; } /* +************************************************************************ +************************************************************************ +*/ +static struct QBUFFER * arcmsr_get_iop_rqbuffer( struct AdapterControlBlock *acb) +{ + struct QBUFFER *qbuffer=NULL; + + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + struct HBA_MessageUnit *phbamu=(struct HBA_MessageUnit *)acb->pmu; + + qbuffer=(struct QBUFFER *)&phbamu->message_rbuffer; + } + break; + case ACB_ADAPTER_TYPE_B: { + struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; + + qbuffer=(struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_rbuffer; + } + break; + } + return(qbuffer); +} +/* +************************************************************************ +************************************************************************ +*/ +static struct QBUFFER * arcmsr_get_iop_wqbuffer( struct AdapterControlBlock *acb) +{ + struct QBUFFER *qbuffer=NULL; + + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + struct HBA_MessageUnit *phbamu=(struct HBA_MessageUnit *)acb->pmu; + + qbuffer=(struct QBUFFER *)&phbamu->message_wbuffer; + } + break; + case ACB_ADAPTER_TYPE_B: { + struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; + + qbuffer=(struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_wbuffer; + } + break; + } + return(qbuffer); +} +/* +************************************************************************** +************************************************************************** +*/ +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); + } + 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); + } + break; + } + return; +} +/* +************************************************************************** +************************************************************************** +*/ +static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) +{ + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + /* + ** 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); + } + break; + case ACB_ADAPTER_TYPE_B: { + /* + ** 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); + } + break; + } +} +/* ********************************************************************** ********************************************************************** */ -static void arcmsr_post_Qbuffer(struct AdapterControlBlock *acb) +static void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb) { - u_int8_t * pQbuffer; - struct QBUFFER * pwbuffer=(struct QBUFFER *)&acb->pmu->message_wbuffer; - u_int8_t * iop_data=(u_int8_t *)pwbuffer->data; - u_int32_t allxfer_len=0; - - if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READED) { - acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); - while((acb->wqbuf_firstindex!=acb->wqbuf_lastindex) && (allxfer_len<124)) { - pQbuffer= &acb->wqbuffer[acb->wqbuf_firstindex]; + u_int8_t *pQbuffer; + struct QBUFFER *pwbuffer; + u_int8_t * iop_data; + int32_t allxfer_len=0; + + pwbuffer=arcmsr_get_iop_wqbuffer(acb); + iop_data=(u_int8_t *)pwbuffer->data; + if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) { + acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); + while((acb->wqbuf_firstindex!=acb->wqbuf_lastindex) + && (allxfer_len<124)) { + pQbuffer=&acb->wqbuffer[acb->wqbuf_firstindex]; memcpy(iop_data, pQbuffer, 1); acb->wqbuf_firstindex++; - acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; - /*if last index number set it to 0 */ + acb->wqbuf_firstindex %=ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */ iop_data++; allxfer_len++; } @@ -640,7 +1050,7 @@ static void arcmsr_post_Qbuffer(struct AdapterControlBlock *acb) /* ** push inbound doorbell and wait reply at hwinterrupt routine for next Qbuffer post */ - CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK); + arcmsr_iop_message_wrote(acb); } return; } @@ -648,11 +1058,12 @@ static void arcmsr_post_Qbuffer(struct AdapterControlBlock *acb) ************************************************************************ ************************************************************************ */ -static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) +static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb) { - acb->acb_flags &= ~ACB_F_MSG_START_BGRB; - CHIP_REG_WRITE32(inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); - if(arcmsr_wait_msgint_ready(acb)) { + acb->acb_flags &=~ACB_F_MSG_START_BGRB; + 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" , acb->pci_unit); } @@ -662,9 +1073,42 @@ static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) ************************************************************************ ************************************************************************ */ +static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb) +{ + acb->acb_flags &= ~ACB_F_MSG_START_BGRB; + 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" + , acb->pci_unit); + } + return; +} +/* +************************************************************************ +************************************************************************ +*/ +static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) +{ + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + arcmsr_stop_hba_bgrb(acb); + } + break; + case ACB_ADAPTER_TYPE_B: { + arcmsr_stop_hbb_bgrb(acb); + } + break; + } + return; +} +/* +************************************************************************ +************************************************************************ +*/ static void arcmsr_poll(struct cam_sim * psim) { - arcmsr_interrupt(cam_sim_softc(psim)); + arcmsr_interrupt((struct AdapterControlBlock *)cam_sim_softc(psim)); return; } /* @@ -674,172 +1118,248 @@ static void arcmsr_poll(struct cam_sim * psim) 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_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) +{ + struct QBUFFER *prbuffer; + u_int8_t *pQbuffer; + u_int8_t *iop_data; + int my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; + + /*check this iop data if overflow my rqbuffer*/ + rqbuf_lastindex=acb->rqbuf_lastindex; + rqbuf_firstindex=acb->rqbuf_firstindex; + prbuffer=arcmsr_get_iop_rqbuffer(acb); + iop_data=(u_int8_t *)prbuffer->data; + iop_len=prbuffer->data_len; + my_empty_len=(rqbuf_firstindex-rqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1); + if(my_empty_len>=iop_len) { + while(iop_len > 0) { + pQbuffer=&acb->rqbuffer[rqbuf_lastindex]; + memcpy(pQbuffer, iop_data, 1); + rqbuf_lastindex++; + rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;/*if last index number set it to 0 */ + iop_data++; + iop_len--; + } + acb->rqbuf_lastindex=rqbuf_lastindex; + arcmsr_iop_message_read(acb); + /*signature, let IOP know data has been read */ + } else { + acb->acb_flags|=ACB_F_IOPDATA_OVERFLOW; + } + return; +} +/* +************************************************************************** +************************************************************************** +*/ +static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) +{ + acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READ; + /* + ***************************************************************** + ** check if there are any mail packages from user space program + ** in my post bag, now is the time to send them into Areca's firmware + ***************************************************************** + */ + if(acb->wqbuf_firstindex!=acb->wqbuf_lastindex) { + u_int8_t *pQbuffer; + struct QBUFFER *pwbuffer; + u_int8_t *iop_data; + int allxfer_len=0; + + acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); + pwbuffer=arcmsr_get_iop_wqbuffer(acb); + iop_data=(u_int8_t *)pwbuffer->data; + while((acb->wqbuf_firstindex!=acb->wqbuf_lastindex) + && (allxfer_len<124)) { + pQbuffer=&acb->wqbuffer[acb->wqbuf_firstindex]; + memcpy(iop_data, pQbuffer, 1); + acb->wqbuf_firstindex++; + acb->wqbuf_firstindex %=ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */ + iop_data++; + allxfer_len++; + } + pwbuffer->data_len=allxfer_len; + /* + ** push inbound doorbell tell iop driver data write ok + ** and wait reply on next hwinterrupt for next Qbuffer post + */ + arcmsr_iop_message_wrote(acb); + } + if(acb->wqbuf_firstindex==acb->wqbuf_lastindex) { + acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; + } + return; +} +/* +************************************************************************** +************************************************************************** +*/ +static void arcmsr_hba_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(HBA_MessageUnit, + 0, outbound_doorbell); + CHIP_REG_WRITE32(HBA_MessageUnit, + 0, outbound_doorbell, outbound_doorbell); /* clear doorbell interrupt */ + if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { + arcmsr_iop2drv_data_wrote_handle(acb); + } + if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { + arcmsr_iop2drv_data_read_handle(acb); + } + return; +} +/* +************************************************************************** +************************************************************************** +*/ +static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb) +{ + u_int32_t flag_srb; + + /* + ***************************************************************************** + ** areca cdb command done + ***************************************************************************** + */ + bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); + 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); + } /*drain reply FIFO*/ + return; +} +/* +************************************************************************** +************************************************************************** +*/ +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; + + /* + ***************************************************************************** + ** areca cdb command done + ***************************************************************************** + */ + bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); + index=phbbmu->doneq_index; + while((flag_srb=phbbmu->done_qbuffer[index]) != 0) { + phbbmu->done_qbuffer[index]=0; + index++; + 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); + } /*drain reply FIFO*/ + return; +} +/* ********************************************************************** ********************************************************************** */ -static void arcmsr_interrupt(void *arg) +static void arcmsr_handle_hba_isr( struct AdapterControlBlock *acb) { - struct AdapterControlBlock *acb=(struct AdapterControlBlock *)arg; - struct CommandControlBlock *srb; - u_int32_t flag_srb, outbound_intstatus, outbound_doorbell; - + u_int32_t outbound_intstatus; /* ********************************************* ** check outbound intstatus ********************************************* */ - outbound_intstatus=CHIP_REG_READ32(outbound_intstatus) & acb->outbound_int_enable; - CHIP_REG_WRITE32(outbound_intstatus, outbound_intstatus);/*clear interrupt*/ + 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*/ + /* MU doorbell interrupts*/ if(outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) { - /* - ********************************************* - ** DOORBELL - ********************************************* - */ - outbound_doorbell=CHIP_REG_READ32(outbound_doorbell); - CHIP_REG_WRITE32(outbound_doorbell, outbound_doorbell);/*clear interrupt */ - if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { - struct QBUFFER * prbuffer=(struct QBUFFER *)&acb->pmu->message_rbuffer; - u_int8_t * iop_data=(u_int8_t *)prbuffer->data; - u_int8_t * pQbuffer; - u_int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; - - /*check this iop data if overflow my rqbuffer*/ - rqbuf_lastindex=acb->rqbuf_lastindex; - rqbuf_firstindex=acb->rqbuf_firstindex; - iop_len=prbuffer->data_len; - my_empty_len=(rqbuf_firstindex-rqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1); - if(my_empty_len>=iop_len) { - while(iop_len > 0) { - pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex]; - memcpy(pQbuffer, iop_data, 1); - acb->rqbuf_lastindex++; - acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; - /*if last index number set it to 0 */ - iop_data++; - iop_len--; - } - CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); - /*signature, let IOP331 know data has been readed */ - } else { - acb->acb_flags|=ACB_F_IOPDATA_OVERFLOW; - } - } - if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { - acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED; - /* - ********************************************* - ********************************************* - */ - if(acb->wqbuf_firstindex!=acb->wqbuf_lastindex) { - u_int8_t * pQbuffer; - struct QBUFFER * pwbuffer=(struct QBUFFER *)&acb->pmu->message_wbuffer; - u_int8_t * iop_data=(u_int8_t *)pwbuffer->data; - u_int32_t allxfer_len=0; - - acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); - while((acb->wqbuf_firstindex!=acb->wqbuf_lastindex) && (allxfer_len<124)) { - pQbuffer= &acb->wqbuffer[acb->wqbuf_firstindex]; - memcpy(iop_data, pQbuffer, 1); - acb->wqbuf_firstindex++; - acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; - /*if last index number set it to 0 */ - iop_data++; - allxfer_len++; - } - pwbuffer->data_len=allxfer_len; - /* - ** push inbound doorbell tell iop driver data write ok - ** and wait reply on next hwinterrupt for next Qbuffer post - */ - CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK); - } - if(acb->wqbuf_firstindex==acb->wqbuf_lastindex) { - acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; - } - } + arcmsr_hba_doorbell_isr(acb); } + /* MU post queue interrupts*/ if(outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { - int target, lun; - /* - ***************************************************************************** - ** areca cdb command done - ***************************************************************************** - */ - bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); - while(1) { - if((flag_srb=CHIP_REG_READ32(outbound_queueport)) == 0xFFFFFFFF) { - break;/*chip FIFO no srb for completion already*/ - } - /* check if command done with no error*/ - srb=(struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5)); - /*frame must be 32 bytes aligned*/ - 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); - srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; - arcmsr_srb_complete(srb, 1); - continue; - } - 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); - continue; - } - target=srb->pccb->ccb_h.target_id; - lun=srb->pccb->ccb_h.target_lun; - if((flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR)==0) { - if(acb->devstate[target][lun]==ARECA_RAID_GONE) { - acb->devstate[target][lun]=ARECA_RAID_GOOD; - } - srb->pccb->ccb_h.status |= CAM_REQ_CMP; - arcmsr_srb_complete(srb, 1); - } else { - switch(srb->arcmsr_cdb.DeviceStatus) { - case ARCMSR_DEV_SELECT_TIMEOUT: { - acb->devstate[target][lun]=ARECA_RAID_GONE; - srb->pccb->ccb_h.status |= CAM_SEL_TIMEOUT; - arcmsr_srb_complete(srb, 1); - } - break; - case ARCMSR_DEV_ABORTED: - case ARCMSR_DEV_INIT_FAIL: { - acb->devstate[target][lun]=ARECA_RAID_GONE; - srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; - arcmsr_srb_complete(srb, 1); - } - break; - case SCSISTAT_CHECK_CONDITION: { - acb->devstate[target][lun]=ARECA_RAID_GOOD; - arcmsr_report_sense_info(srb); - arcmsr_srb_complete(srb, 1); - } - 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); - acb->devstate[target][lun]=ARECA_RAID_GONE; - srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY; - /*unknow error or crc error just for retry*/ - arcmsr_srb_complete(srb, 1); - break; - } - } - } /*drain reply FIFO*/ + arcmsr_hba_postqueue_isr(acb); } - return; + return; +} +/* +********************************************************************** +********************************************************************** +*/ +static void arcmsr_handle_hbb_isr( struct AdapterControlBlock *acb) +{ + u_int32_t outbound_doorbell; + /* + ********************************************* + ** check outbound intstatus + ********************************************* + */ + outbound_doorbell=CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & acb->outbound_int_enable; + if(!outbound_doorbell) { + /*it must be share irq*/ + return; + } + CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ~outbound_doorbell); /* clear doorbell interrupt */ + CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell); + CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); + /* MU ioctl transfer doorbell interrupts*/ + if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { + arcmsr_iop2drv_data_wrote_handle(acb); + } + if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) { + arcmsr_iop2drv_data_read_handle(acb); + } + /* MU post queue interrupts*/ + if(outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) { + arcmsr_hbb_postqueue_isr(acb); + } + return; +} +/* +****************************************************************************** +****************************************************************************** +*/ +static void arcmsr_interrupt(struct AdapterControlBlock *acb) +{ + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: + arcmsr_handle_hba_isr(acb); + break; + case ACB_ADAPTER_TYPE_B: + arcmsr_handle_hbb_isr(acb); + break; + default: + printf("arcmsr%d: interrupt service," + " unknow adapter type =%d\n", acb->pci_unit, acb->adapter_type); + break; + } + return; } /* ******************************************************************************* @@ -865,7 +1385,7 @@ u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_c { struct CMD_MESSAGE_FIELD * pcmdmessagefld; u_int32_t retvalue=EINVAL; - + pcmdmessagefld=(struct CMD_MESSAGE_FIELD *) arg; if(memcmp(pcmdmessagefld->cmdmessage.Signature, "ARCMSR", 6)!=0) { return retvalue; @@ -876,8 +1396,9 @@ u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_c u_int8_t * pQbuffer; u_int8_t * ptmpQbuffer=pcmdmessagefld->messagedatabuffer; u_int32_t allxfer_len=0; - - while((acb->rqbuf_firstindex!=acb->rqbuf_lastindex) && (allxfer_len<1031)) { + + while((acb->rqbuf_firstindex!=acb->rqbuf_lastindex) + && (allxfer_len<1031)) { /*copy READ QBUFFER to srb*/ pQbuffer= &acb->rqbuffer[acb->rqbuf_firstindex]; memcpy(ptmpQbuffer, pQbuffer, 1); @@ -888,11 +1409,13 @@ u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_c allxfer_len++; } if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { - struct QBUFFER * prbuffer=(struct QBUFFER *)&acb->pmu->message_rbuffer; - u_int8_t * iop_data=(u_int8_t *)prbuffer->data; + struct QBUFFER * prbuffer; + u_int8_t * iop_data; u_int32_t iop_len; - + acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; + prbuffer=arcmsr_get_iop_rqbuffer(acb); + iop_data=(u_int8_t *)prbuffer->data; iop_len=(u_int32_t)prbuffer->data_len; /*this iop data does no chance to make me overflow again here, so just do it*/ while(iop_len>0) { @@ -904,25 +1427,25 @@ u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_c iop_data++; iop_len--; } - CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); - /*signature, let IOP331 know data has been readed */ + arcmsr_iop_message_read(acb); + /*signature, let IOP know data has been readed */ } pcmdmessagefld->cmdmessage.Length=allxfer_len; pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; retvalue=ARCMSR_MESSAGE_SUCCESS; - } + } break; case ARCMSR_MESSAGE_WRITE_WQBUFFER: { u_int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; u_int8_t * pQbuffer; u_int8_t * ptmpuserbuffer=pcmdmessagefld->messagedatabuffer; - + user_len=pcmdmessagefld->cmdmessage.Length; /*check if data xfer length of this request will overflow my array qbuffer */ wqbuf_lastindex=acb->wqbuf_lastindex; wqbuf_firstindex=acb->wqbuf_firstindex; if(wqbuf_lastindex!=wqbuf_firstindex) { - arcmsr_post_Qbuffer(acb); + arcmsr_post_ioctldata2iop(acb); pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; } else { my_empty_len=(wqbuf_firstindex-wqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1); @@ -934,13 +1457,13 @@ u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_c acb->wqbuf_lastindex++; acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */ - ptmpuserbuffer++; + ptmpuserbuffer++; user_len--; } /*post fist Qbuffer*/ if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { acb->acb_flags &=~ACB_F_MESSAGE_WQBUFFER_CLEARED; - arcmsr_post_Qbuffer(acb); + arcmsr_post_ioctldata2iop(acb); } pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; } else { @@ -952,11 +1475,11 @@ u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_c break; case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { u_int8_t * pQbuffer=acb->rqbuffer; - + if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; - CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); - /*signature, let IOP331 know data has been readed */ + arcmsr_iop_message_read(acb); + /*signature, let IOP know data has been readed */ } acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; acb->rqbuf_firstindex=0; @@ -972,10 +1495,10 @@ u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_c if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; - CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); - /*signature, let IOP331 know data has been readed */ + arcmsr_iop_message_read(acb); + /*signature, let IOP know data has been readed */ } - acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READED); + acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ); acb->wqbuf_firstindex=0; acb->wqbuf_lastindex=0; memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); @@ -988,12 +1511,12 @@ u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_c if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; - CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); - /*signature, let IOP331 know data has been readed */ + arcmsr_iop_message_read(acb); + /*signature, let IOP know data has been readed */ } acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED |ACB_F_MESSAGE_RQBUFFER_CLEARED - |ACB_F_MESSAGE_WQBUFFER_READED); + |ACB_F_MESSAGE_WQBUFFER_READ); acb->rqbuf_firstindex=0; acb->rqbuf_lastindex=0; acb->wqbuf_firstindex=0; @@ -1014,7 +1537,7 @@ u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_c case ARCMSR_MESSAGE_SAY_HELLO: { u_int8_t * hello_string="Hello! I am ARCMSR"; u_int8_t * puserbuffer=(u_int8_t *)pcmdmessagefld->messagedatabuffer; - + if(memcpy(puserbuffer, hello_string, (int16_t)strlen(hello_string))) { pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); @@ -1029,7 +1552,7 @@ u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_c retvalue=ARCMSR_MESSAGE_SUCCESS; } break; - case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: { + case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: { arcmsr_flush_adapter_cache(acb); retvalue=ARCMSR_MESSAGE_SUCCESS; } @@ -1046,7 +1569,7 @@ struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb) { struct CommandControlBlock *srb=NULL; u_int32_t workingsrb_startindex, workingsrb_doneindex; - + workingsrb_doneindex=acb->workingsrb_doneindex; workingsrb_startindex=acb->workingsrb_startindex; srb=acb->srbworkingQ[workingsrb_startindex]; @@ -1068,10 +1591,10 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * struct CMD_MESSAGE_FIELD * pcmdmessagefld; int retvalue = 0, transfer_len = 0; char *buffer; - uint32_t controlcode = (uint32_t ) pccb->csio.cdb_io.cdb_bytes[5] << 24 | - (uint32_t ) pccb->csio.cdb_io.cdb_bytes[6] << 16 | - (uint32_t ) pccb->csio.cdb_io.cdb_bytes[7] << 8 | - (uint32_t ) pccb->csio.cdb_io.cdb_bytes[8]; + u_int32_t controlcode = (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[5] << 24 | + (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[6] << 16 | + (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[7] << 8 | + (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[8]; /* 4 bytes: Areca io control code */ if((pccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) { buffer = pccb->csio.data_ptr; @@ -1101,11 +1624,13 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * allxfer_len++; } if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { - struct QBUFFER *prbuffer = (struct QBUFFER *) &acb->pmu->message_rbuffer; - u_int8_t *iop_data = (u_int8_t *)prbuffer->data; + struct QBUFFER *prbuffer; + u_int8_t *iop_data; int32_t iop_len; acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; + prbuffer=arcmsr_get_iop_rqbuffer(acb); + iop_data = (u_int8_t *)prbuffer->data; iop_len =(u_int32_t)prbuffer->data_len; while (iop_len > 0) { pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex]; @@ -1115,8 +1640,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * iop_data++; iop_len--; } - CHIP_REG_WRITE32(inbound_doorbell, - ARCMSR_INBOUND_DRIVER_DATA_READ_OK); + arcmsr_iop_message_read(acb); } pcmdmessagefld->cmdmessage.Length = allxfer_len; pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; @@ -1127,12 +1651,12 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; u_int8_t *pQbuffer; u_int8_t *ptmpuserbuffer=pcmdmessagefld->messagedatabuffer; - + user_len = pcmdmessagefld->cmdmessage.Length; wqbuf_lastindex = acb->wqbuf_lastindex; wqbuf_firstindex = acb->wqbuf_firstindex; if (wqbuf_lastindex != wqbuf_firstindex) { - arcmsr_post_Qbuffer(acb); + arcmsr_post_ioctldata2iop(acb); /* has error report sensedata */ if(&pccb->csio.sense_data) { ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); @@ -1160,7 +1684,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { acb->acb_flags &= ~ACB_F_MESSAGE_WQBUFFER_CLEARED; - arcmsr_post_Qbuffer(acb); + arcmsr_post_ioctldata2iop(acb); } } else { /* has error report sensedata */ @@ -1184,8 +1708,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; - CHIP_REG_WRITE32(inbound_doorbell - , ARCMSR_INBOUND_DRIVER_DATA_READ_OK); + arcmsr_iop_message_read(acb); } acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; acb->rqbuf_firstindex = 0; @@ -1200,12 +1723,11 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; - CHIP_REG_WRITE32(inbound_doorbell - , ARCMSR_INBOUND_DRIVER_DATA_READ_OK); + arcmsr_iop_message_read(acb); } acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | - ACB_F_MESSAGE_WQBUFFER_READED); + ACB_F_MESSAGE_WQBUFFER_READ); acb->wqbuf_firstindex = 0; acb->wqbuf_lastindex = 0; memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); @@ -1218,13 +1740,12 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; - CHIP_REG_WRITE32(inbound_doorbell - , ARCMSR_INBOUND_DRIVER_DATA_READ_OK); + arcmsr_iop_message_read(acb); } acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | ACB_F_MESSAGE_RQBUFFER_CLEARED - | ACB_F_MESSAGE_WQBUFFER_READED); + | ACB_F_MESSAGE_WQBUFFER_READ); acb->rqbuf_firstindex = 0; acb->rqbuf_lastindex = 0; acb->wqbuf_firstindex = 0; @@ -1270,13 +1791,14 @@ static void arcmsr_executesrb(void *arg, bus_dma_segment_t *dm_segs, int nseg, i struct AdapterControlBlock *acb=(struct AdapterControlBlock *)srb->acb; union ccb * pccb; int target, lun; - + pccb=srb->pccb; target=pccb->ccb_h.target_id; lun=pccb->ccb_h.target_lun; if(error != 0) { if(error != EFBIG) { - printf("arcmsr%d: unexpected error %x returned from 'bus_dmamap_load' \n" + printf("arcmsr%d: unexpected error %x" + " returned from 'bus_dmamap_load' \n" , acb->pci_unit, error); } if((pccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { @@ -1290,7 +1812,7 @@ static void arcmsr_executesrb(void *arg, bus_dma_segment_t *dm_segs, int nseg, i arcmsr_srb_complete(srb, 0); return; } - if(acb->acb_flags & ACB_F_BUS_RESET) { + if(acb->acb_flags & ACB_F_BUS_RESET) { printf("arcmsr%d: bus reset and return busy \n", acb->pci_unit); pccb->ccb_h.status |= CAM_SCSI_BUS_RESET; arcmsr_srb_complete(srb, 0); @@ -1336,9 +1858,9 @@ static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb) { struct CommandControlBlock *srb; struct AdapterControlBlock *acb=(struct AdapterControlBlock *) abortccb->ccb_h.arcmsr_ccbacb_ptr; - u_int32_t intmask_org, mask; + u_int32_t intmask_org; int i=0; - + acb->num_aborts++; /* *************************************************************************** @@ -1366,15 +1888,11 @@ static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb) } return(FALSE); abort_outstanding_cmd: - /* do not talk to iop 331 abort command */ - UDELAY(3000*1000);/*wait for 3 sec for all command done*/ /* disable all outbound interrupt */ - intmask_org=CHIP_REG_READ32(outbound_intmask); - CHIP_REG_WRITE32(outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); + intmask_org=arcmsr_disable_allintr(acb); arcmsr_polling_srbdone(acb, srb); - /* enable all outbound interrupt */ - mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); - CHIP_REG_WRITE32(outbound_intmask, intmask_org & mask); + /* enable outbound Post Queue, outbound doorbell Interrupt */ + arcmsr_enable_allintr(acb, intmask_org); return (TRUE); } /* @@ -1384,11 +1902,11 @@ static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb) static void arcmsr_bus_reset(struct AdapterControlBlock *acb) { int retry=0; - + acb->num_resets++; acb->acb_flags |=ACB_F_BUS_RESET; while(acb->srboutstandingcount!=0 && retry < 400) { - arcmsr_interrupt((void *)acb); + arcmsr_interrupt(acb); UDELAY(25000); retry++; } @@ -1451,7 +1969,7 @@ static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, static void arcmsr_action(struct cam_sim * psim, union ccb * pccb) { struct AdapterControlBlock * acb; - + acb=(struct AdapterControlBlock *) cam_sim_softc(psim); if(acb==NULL) { pccb->ccb_h.status |= CAM_REQ_INVALID; @@ -1462,18 +1980,18 @@ static void arcmsr_action(struct cam_sim * psim, union ccb * pccb) case XPT_SCSI_IO: { struct CommandControlBlock *srb; int target=pccb->ccb_h.target_id; - + if(target == 16) { /* virtual device for iop message transfer */ arcmsr_handle_virtual_command(acb, pccb); return; } - if((srb=arcmsr_get_freesrb(acb)) == NULL) { + if((srb=arcmsr_get_freesrb(acb)) == NULL) { pccb->ccb_h.status |= CAM_RESRC_UNAVAIL; xpt_done(pccb); return; } - pccb->ccb_h.arcmsr_ccbsrb_ptr=srb; + pccb->ccb_h.arcmsr_ccbsrb_ptr=srb; pccb->ccb_h.arcmsr_ccbacb_ptr=acb; srb->pccb=pccb; if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { @@ -1482,7 +2000,7 @@ static void arcmsr_action(struct cam_sim * psim, union ccb * pccb) if(!(pccb->ccb_h.flags & CAM_DATA_PHYS)) { /* Buffer is virtual */ u_int32_t error, s; - + s=splsoftvm(); error = bus_dmamap_load(acb->dm_segs_dmat , srb->dm_segs_dmamap @@ -1501,7 +2019,7 @@ static void arcmsr_action(struct cam_sim * psim, union ccb * pccb) } else { /* Scatter/gather list */ struct bus_dma_segment *segs; - + if((pccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0 || (pccb->ccb_h.flags & CAM_DATA_PHYS) != 0) { pccb->ccb_h.status |= CAM_PROVIDE_FAIL; @@ -1539,17 +2057,19 @@ static void arcmsr_action(struct cam_sim * psim, union ccb * pccb) strncpy(cpi->hba_vid, "ARCMSR", HBA_IDLEN); strncpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN); cpi->unit_number=cam_sim_unit(psim); + #ifdef CAM_NEW_TRAN_CODE cpi->transport = XPORT_SPI; cpi->transport_version = 2; cpi->protocol = PROTO_SCSI; cpi->protocol_version = SCSI_REV_2; + #endif cpi->ccb_h.status |= CAM_REQ_CMP; xpt_done(pccb); break; } case XPT_ABORT: { union ccb *pabort_ccb; - + pabort_ccb=pccb->cab.abort_ccb; switch (pabort_ccb->ccb_h.func_code) { case XPT_ACCEPT_TARGET_IO: @@ -1578,7 +2098,7 @@ static void arcmsr_action(struct cam_sim * psim, union ccb * pccb) case XPT_RESET_BUS: case XPT_RESET_DEV: { u_int32_t i; - + arcmsr_bus_reset(acb); for (i=0; i < 500; i++) { DELAY(1000); @@ -1594,33 +2114,47 @@ static void arcmsr_action(struct cam_sim * psim, union ccb * pccb) } case XPT_GET_TRAN_SETTINGS: { struct ccb_trans_settings *cts; - struct ccb_trans_settings_scsi *scsi; - struct ccb_trans_settings_spi *spi; - + if(pccb->ccb_h.target_id == 16) { pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; xpt_done(pccb); break; } - cts= &pccb->cts; - scsi = &cts->proto_specific.scsi; - spi = &cts->xport_specific.spi; - - cts->protocol = PROTO_SCSI; - cts->protocol_version = SCSI_REV_2; - cts->transport = XPORT_SPI; - cts->transport_version = 2; - spi->flags = CTS_SPI_FLAGS_DISC_ENB; - spi->sync_period=3; - spi->sync_offset=32; - spi->bus_width=MSG_EXT_WDTR_BUS_16_BIT; - scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; - spi->valid = CTS_SPI_VALID_SYNC_RATE - | CTS_SPI_VALID_SYNC_OFFSET - | CTS_SPI_VALID_BUS_WIDTH; - scsi->valid = CTS_SCSI_VALID_TQ; - + #ifdef CAM_NEW_TRAN_CODE + { + struct ccb_trans_settings_scsi *scsi; + struct ccb_trans_settings_spi *spi; + + scsi = &cts->proto_specific.scsi; + spi = &cts->xport_specific.spi; + cts->protocol = PROTO_SCSI; + cts->protocol_version = SCSI_REV_2; + cts->transport = XPORT_SPI; + cts->transport_version = 2; + spi->flags = CTS_SPI_FLAGS_DISC_ENB; + spi->sync_period=3; + spi->sync_offset=32; + spi->bus_width=MSG_EXT_WDTR_BUS_16_BIT; + scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; + spi->valid = CTS_SPI_VALID_SYNC_RATE + | CTS_SPI_VALID_SYNC_OFFSET + | CTS_SPI_VALID_BUS_WIDTH; + scsi->valid = CTS_SCSI_VALID_TQ; + } + #else + { + cts->flags=(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB); + cts->sync_period=3; + cts->sync_offset=32; + cts->bus_width=MSG_EXT_WDTR_BUS_16_BIT; + cts->valid=CCB_TRANS_SYNC_RATE_VALID | + CCB_TRANS_SYNC_OFFSET_VALID | + CCB_TRANS_BUS_WIDTH_VALID | + CCB_TRANS_DISC_VALID | + CCB_TRANS_TQ_VALID; + } + #endif pccb->ccb_h.status |= CAM_REQ_CMP; xpt_done(pccb); break; @@ -1634,13 +2168,13 @@ static void arcmsr_action(struct cam_sim * psim, union ccb * pccb) struct ccb_calc_geometry *ccg; u_int32_t size_mb; u_int32_t secs_per_cylinder; - + if(pccb->ccb_h.target_id == 16) { pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; xpt_done(pccb); break; } - ccg= &pccb->ccg; + ccg= &pccb->ccg; if (ccg->block_size == 0) { pccb->ccb_h.status = CAM_REQ_INVALID; xpt_done(pccb); @@ -1676,11 +2210,11 @@ static void arcmsr_action(struct cam_sim * psim, union ccb * pccb) ********************************************************************** ********************************************************************** */ -static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) +static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) { acb->acb_flags |= ACB_F_MSG_START_BGRB; - CHIP_REG_WRITE32(inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); - if(arcmsr_wait_msgint_ready(acb)) { + CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); + if(!arcmsr_hba_wait_msgint_ready(acb)) { printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); } return; @@ -1689,18 +2223,52 @@ static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) ********************************************************************** ********************************************************************** */ -static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) +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); + if(!arcmsr_hbb_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) { + case ACB_ADAPTER_TYPE_A: + arcmsr_start_hba_bgrb(acb); + break; + case ACB_ADAPTER_TYPE_B: + arcmsr_start_hbb_bgrb(acb); + break; + } + return; +} +/* +********************************************************************** +** +********************************************************************** +*/ +static void arcmsr_polling_hba_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) { struct CommandControlBlock *srb; - uint32_t flag_srb, outbound_intstatus, poll_srb_done=0, poll_count=0; - int id, lun; - -polling_srb_retry: + u_int32_t flag_srb, outbound_intstatus, poll_srb_done=0, poll_count=0; + +polling_ccb_retry: poll_count++; - outbound_intstatus=CHIP_REG_READ32(outbound_intstatus) & acb->outbound_int_enable; - CHIP_REG_WRITE32(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(outbound_queueport))==0xFFFFFFFF) { + if((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, + 0, outbound_queueport))==0xFFFFFFFF) { if(poll_srb_done) { break;/*chip FIFO no ccb for completion already*/ } else { @@ -1708,14 +2276,15 @@ static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct Comma if(poll_count > 100) { break; } - goto polling_srb_retry; + goto polling_ccb_retry; } } /* check ifcommand done with no error*/ - srb=(struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5)); - /*frame must be 32 bytes aligned*/ + srb=(struct CommandControlBlock *) + (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ + poll_srb_done = (srb==poll_srb) ? 1:0; if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) { - if((srb->startdone==ARCMSR_SRB_ABORTED) && (srb==poll_srb)) { + if(srb->startdone==ARCMSR_SRB_ABORTED) { printf("arcmsr%d: scsi id=%d lun=%d srb='%p'" "poll command abort successfully \n" , acb->pci_unit @@ -1723,7 +2292,6 @@ static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct Comma , srb->pccb->ccb_h.target_lun, srb); srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; arcmsr_srb_complete(srb, 1); - poll_srb_done=1; continue; } printf("arcmsr%d: polling get an illegal srb command done srb='%p'" @@ -1732,115 +2300,389 @@ static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct Comma , srb, acb->srboutstandingcount); continue; } - id=srb->pccb->ccb_h.target_id; - lun=srb->pccb->ccb_h.target_lun; - if((flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR)==0) { - if(acb->devstate[id][lun]==ARECA_RAID_GONE) { - acb->devstate[id][lun]=ARECA_RAID_GOOD; - } - srb->pccb->ccb_h.status |= CAM_REQ_CMP; - arcmsr_srb_complete(srb, 1); - } else { - switch(srb->arcmsr_cdb.DeviceStatus) { - case ARCMSR_DEV_SELECT_TIMEOUT: { - acb->devstate[id][lun]=ARECA_RAID_GONE; - srb->pccb->ccb_h.status |= CAM_SEL_TIMEOUT; - arcmsr_srb_complete(srb, 1); - } - break; - case ARCMSR_DEV_ABORTED: - case ARCMSR_DEV_INIT_FAIL: { - acb->devstate[id][lun]=ARECA_RAID_GONE; - srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; - arcmsr_srb_complete(srb, 1); - } - break; - case SCSISTAT_CHECK_CONDITION: { - acb->devstate[id][lun]=ARECA_RAID_GOOD; - arcmsr_report_sense_info(srb); - arcmsr_srb_complete(srb, 1); - } - break; - default: - printf("arcmsr%d: scsi id=%d lun=%d" - "polling and getting command error done" - ", but got unknow DeviceStatus=0x%x \n" - , acb->pci_unit, id, lun, srb->arcmsr_cdb.DeviceStatus); - acb->devstate[id][lun]=ARECA_RAID_GONE; - srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY; - /*unknow error or crc error just for retry*/ - arcmsr_srb_complete(srb, 1); - break; - } - } + arcmsr_report_srb_state(acb, srb, flag_srb); } /*drain reply FIFO*/ return; } /* ********************************************************************** -** get firmware miscellaneous data +** ********************************************************************** */ -static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) +static void arcmsr_polling_hbb_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) +{ + struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; + struct CommandControlBlock *srb; + u_int32_t flag_srb, poll_srb_done=0, poll_count=0; + int index; + +polling_ccb_retry: + poll_count++; + CHIP_REG_WRITE32(HBB_DOORBELL, + 0, iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ + bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); + while(1) { + index=phbbmu->doneq_index; + if((flag_srb=phbbmu->done_qbuffer[index]) == 0) { + if(poll_srb_done) { + break;/*chip FIFO no ccb for completion already*/ + } else { + UDELAY(25000); + if(poll_count > 100) { + break; + } + goto polling_ccb_retry; + } + } + phbbmu->done_qbuffer[index]=0; + index++; + index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ + phbbmu->doneq_index=index; + /* check if command done with no error*/ + srb=(struct CommandControlBlock *) + (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ + 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, flag_srb); + } /*drain reply FIFO*/ + return; +} +/* +********************************************************************** +********************************************************************** +*/ +static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) +{ + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + arcmsr_polling_hba_srbdone(acb, poll_srb); + } + break; + case ACB_ADAPTER_TYPE_B: { + arcmsr_polling_hbb_srbdone(acb, poll_srb); + } + break; + } +} +/* +********************************************************************** +********************************************************************** +*/ +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 MessageUnit,message_rwbuffer[15]); /*firm_model,15,60-67*/ - size_t iop_firm_version=offsetof(struct MessageUnit,message_rwbuffer[17]); /*firm_version,17,68-83*/ + 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*/ int i; - - CHIP_REG_WRITE32(inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); - if(arcmsr_wait_msgint_ready(acb)) { + + 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); } i=0; while(i<8) { - *acb_firm_model=bus_space_read_1(acb->btag, acb->bhandle, iop_firm_model+i); + *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, acb->bhandle, iop_firm_version+i); + *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++; } 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(message_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ - acb->firm_numbers_queue=CHIP_REG_READ32(message_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ - acb->firm_sdram_size=CHIP_REG_READ32(message_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ - acb->firm_ide_channels=CHIP_REG_READ32(message_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*/ + return; +} +/* +********************************************************************** +********************************************************************** +*/ +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*/ + int i; + + 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); + } + i=0; + while(i<8) { + *acb_firm_model=bus_space_read_1(acb->btag[1], acb->bhandle[1], 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[1], acb->bhandle[1], iop_firm_version+i); + /* 16 bytes firm_version, 17, 68-83*/ + acb_firm_version++; + 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*/ + return; +} +/* +********************************************************************** +********************************************************************** +*/ +static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) +{ + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + arcmsr_get_hba_config(acb); + } + break; + case ACB_ADAPTER_TYPE_B: { + arcmsr_get_hbb_config(acb); + } + break; + } + return; +} +/* +********************************************************************** +********************************************************************** +*/ +static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb) +{ + int timeout=0; + + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + 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); + return; + } + UDELAY(15000); /* wait 15 milli-seconds */ + } + } + break; + case ACB_ADAPTER_TYPE_B: { + 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); + return; + } + UDELAY(15000); /* wait 15 milli-seconds */ + } + CHIP_REG_WRITE32(HBB_DOORBELL, + 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); + } + break; + } + return; +} +/* +********************************************************************** +********************************************************************** +*/ +static void arcmsr_clear_doorbell_queue_buffer( struct AdapterControlBlock *acb) +{ + 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); + } + 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); + /* let IOP know data has been read */ + } + break; + } + return; +} +/* +************************************************************************ +************************************************************************ +*/ +static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb) +{ + unsigned long srb_phyaddr; + u_int32_t srb_phyaddr_hi32; + + /* + ******************************************************************** + ** here we need to tell iop 331 our freesrb.HighPart + ** if freesrb.HighPart is not zero + ******************************************************************** + */ + srb_phyaddr= (unsigned long) acb->srb_phyaddr; + srb_phyaddr_hi32=(u_int32_t) ((srb_phyaddr>>16)>>16); + 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); + if(!arcmsr_hba_wait_msgint_ready(acb)) { + printf( "arcmsr%d:" + " 'set srb high part physical address' timeout \n", acb->pci_unit); + return FALSE; + } + } + } + break; + /* + *********************************************************************** + ** if adapter type B, set window of "post command Q" + *********************************************************************** + */ + case ACB_ADAPTER_TYPE_B: { + u_int32_t post_queue_phyaddr; + struct HBB_MessageUnit *phbbmu; + + 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); + if(!arcmsr_hbb_wait_msgint_ready(acb)) { + 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) + + 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); + 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); + if(!arcmsr_hbb_wait_msgint_ready(acb)) { + printf( "arcmsr%d: 'start diver mode' timeout \n", acb->pci_unit); + return FALSE; + } + } + break; + } + return TRUE; +} +/* +************************************************************************ +************************************************************************ +*/ +static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb) +{ + switch (acb->adapter_type) + { + case ACB_ADAPTER_TYPE_A: + return; + case ACB_ADAPTER_TYPE_B: { + 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); + return; + } + } + break; + } return; } /* ********************************************************************** -** start background rebulid ********************************************************************** */ static void arcmsr_iop_init(struct AdapterControlBlock *acb) { - u_int32_t intmask_org, mask, outbound_doorbell, firmware_state=0; - - do { - firmware_state=CHIP_REG_READ32(outbound_msgaddr1); - } while((firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK)==0); - intmask_org=CHIP_REG_READ32(outbound_intmask)|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE; - CHIP_REG_WRITE32(outbound_intmask, intmask_org); - intmask_org=CHIP_REG_READ32(outbound_intmask)|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE; + u_int32_t intmask_org; + + /* disable all outbound interrupt */ + intmask_org=arcmsr_disable_allintr(acb); + arcmsr_wait_firmware_ready(acb); + arcmsr_iop_confirm(acb); arcmsr_get_firmware_spec(acb); + /*start background rebuild*/ arcmsr_start_adapter_bgrb(acb); - /* clear Qbuffer if door bell ringed */ - outbound_doorbell=CHIP_REG_READ32(outbound_doorbell); - CHIP_REG_WRITE32(outbound_doorbell, outbound_doorbell);/*clear interrupt */ - CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); - /* enable outbound Post Queue, outbound message0, outbell doorbell Interrupt */ - mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); - CHIP_REG_WRITE32(outbound_intmask, intmask_org & mask); - acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; + /* empty doorbell Qbuffer if door bell ringed */ + arcmsr_clear_doorbell_queue_buffer(acb); + arcmsr_enable_eoi_mode(acb); + /* enable outbound Post Queue, outbound doorbell Interrupt */ + arcmsr_enable_allintr(acb, intmask_org); acb->acb_flags |=ACB_F_IOP_INITED; return; } @@ -1853,53 +2695,27 @@ static void arcmsr_map_freesrb(void *arg, bus_dma_segment_t *segs, int nseg, int struct AdapterControlBlock *acb=arg; struct CommandControlBlock *srb_tmp; u_int8_t * dma_memptr; - u_int32_t i, srb_phyaddr_hi32; + u_int32_t i; unsigned long srb_phyaddr=(unsigned long)segs->ds_addr; - + dma_memptr=acb->uncacheptr; - srb_phyaddr=segs->ds_addr; /* We suppose bus_addr_t high part always 0 here*/ - if(((unsigned long)dma_memptr & 0x1F)!=0) { - dma_memptr=dma_memptr+(0x20-((unsigned long)dma_memptr & 0x1F)); - srb_phyaddr=srb_phyaddr+(0x20-((unsigned long)srb_phyaddr & 0x1F)); - } + acb->srb_phyaddr=srb_phyaddr; srb_tmp=(struct CommandControlBlock *)dma_memptr; for(i=0;idm_segs_dmat, /*flags*/0, &srb_tmp->dm_segs_dmamap)!=0) { - acb->acb_flags |= ACB_F_MAPFREESRB_FAILD; - printf("arcmsr%d: srb dmamap bus_dmamap_create error\n", acb->pci_unit); - return; - } - srb_tmp->cdb_shifted_phyaddr=srb_phyaddr >> 5; - srb_tmp->acb=acb; - acb->srbworkingQ[i]=acb->psrb_pool[i]=srb_tmp; - srb_phyaddr=srb_phyaddr+sizeof(struct CommandControlBlock); - } else { + if(bus_dmamap_create(acb->dm_segs_dmat, + /*flags*/0, &srb_tmp->dm_segs_dmamap)!=0) { acb->acb_flags |= ACB_F_MAPFREESRB_FAILD; - printf("arcmsr%d: dma_memptr=%p i=%d" - "this srb cross 32 bytes boundary ignored srb_tmp=%p \n" - , acb->pci_unit, dma_memptr, i, srb_tmp); + printf("arcmsr%d:" + " srb dmamap bus_dmamap_create error\n", acb->pci_unit); return; } + srb_tmp->cdb_shifted_phyaddr=srb_phyaddr >> 5; + srb_tmp->acb=acb; + acb->srbworkingQ[i]=acb->psrb_pool[i]=srb_tmp; + srb_phyaddr=srb_phyaddr+sizeof(struct CommandControlBlock); srb_tmp++; } acb->vir2phy_offset=(unsigned long)srb_tmp-(unsigned long)srb_phyaddr; - /* - ******************************************************************** - ** here we need to tell iop 331 our freesrb.HighPart - ** if freesrb.HighPart is not zero - ******************************************************************** - */ - srb_phyaddr_hi32=(uint32_t) ((srb_phyaddr>>16)>>16); - if(srb_phyaddr_hi32!=0) { - CHIP_REG_WRITE32(message_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); - CHIP_REG_WRITE32(message_rwbuffer[1], srb_phyaddr_hi32); - CHIP_REG_WRITE32(inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); - if(arcmsr_wait_msgint_ready(acb)) { - printf("arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); - } - } return; } /* @@ -1928,11 +2744,41 @@ static void arcmsr_free_resource(struct AdapterControlBlock *acb) static u_int32_t arcmsr_initialize(device_t dev) { struct AdapterControlBlock *acb=device_get_softc(dev); - u_int32_t intmask_org, rid=PCIR_BAR(0); - vm_offset_t mem_base; u_int16_t pci_command; - int i, j; - + int i, j,max_coherent_size; + + switch (pci_get_devid(dev)) { + case PCIDevVenIDARC1201: { + acb->adapter_type=ACB_ADAPTER_TYPE_B; + max_coherent_size=ARCMSR_SRBS_POOL_SIZE + +(sizeof(struct HBB_MessageUnit)); + } + break; + case PCIDevVenIDARC1110: + case PCIDevVenIDARC1120: + case PCIDevVenIDARC1130: + case PCIDevVenIDARC1160: + case PCIDevVenIDARC1170: + case PCIDevVenIDARC1210: + case PCIDevVenIDARC1220: + case PCIDevVenIDARC1230: + case PCIDevVenIDARC1260: + case PCIDevVenIDARC1270: + case PCIDevVenIDARC1280: + case PCIDevVenIDARC1380: + case PCIDevVenIDARC1381: + case PCIDevVenIDARC1680: + case PCIDevVenIDARC1681: { + acb->adapter_type=ACB_ADAPTER_TYPE_A; + max_coherent_size=ARCMSR_SRBS_POOL_SIZE; + } + break; + default: { + printf("arcmsr%d:" + " unknown RAID adapter type \n", device_get_unit(dev)); + return ENOMEM; + } + } #if __FreeBSD_version >= 502010 if(bus_dma_tag_create( /*parent*/ NULL, /*alignemnt*/ 1, @@ -1963,7 +2809,7 @@ static u_int32_t arcmsr_initialize(device_t dev) &acb->parent_dmat) != 0) #endif { - printf("arcmsr%d: parent_dmat bus_dma_tag_create failure!\n", acb->pci_unit); + printf("arcmsr%d: parent_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); return ENOMEM; } /* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */ @@ -1998,19 +2844,19 @@ static u_int32_t arcmsr_initialize(device_t dev) #endif { bus_dma_tag_destroy(acb->parent_dmat); - printf("arcmsr%d: dm_segs_dmat bus_dma_tag_create failure!\n", acb->pci_unit); + printf("arcmsr%d: dm_segs_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); return ENOMEM; } /* DMA tag for our srb structures.... Allocate the freesrb memory */ #if __FreeBSD_version >= 502010 if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, - /*alignment*/ 1, + /*alignment*/ 0x20, /*boundary*/ 0, /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, /*highaddr*/ BUS_SPACE_MAXADDR, /*filter*/ NULL, /*filterarg*/ NULL, - /*maxsize*/ ARCMSR_SRBS_POOL_SIZE, + /*maxsize*/ max_coherent_size, /*nsegments*/ 1, /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, /*flags*/ 0, @@ -2019,13 +2865,13 @@ static u_int32_t arcmsr_initialize(device_t dev) &acb->srb_dmat) != 0) #else if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, - /*alignment*/ 1, + /*alignment*/ 0x20, /*boundary*/ 0, /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, /*highaddr*/ BUS_SPACE_MAXADDR, /*filter*/ NULL, /*filterarg*/ NULL, - /*maxsize*/ ARCMSR_SRBS_POOL_SIZE, + /*maxsize*/ max_coherent_size, /*nsegments*/ 1, /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, /*flags*/ 0, @@ -2034,7 +2880,7 @@ static u_int32_t arcmsr_initialize(device_t dev) { bus_dma_tag_destroy(acb->dm_segs_dmat); bus_dma_tag_destroy(acb->parent_dmat); - printf("arcmsr%d: srb_dmat bus_dma_tag_create failure!\n", acb->pci_unit); + printf("arcmsr%d: srb_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); return ENXIO; } /* Allocation for our srbs */ @@ -2043,16 +2889,16 @@ static u_int32_t arcmsr_initialize(device_t dev) bus_dma_tag_destroy(acb->srb_dmat); bus_dma_tag_destroy(acb->dm_segs_dmat); bus_dma_tag_destroy(acb->parent_dmat); - printf("arcmsr%d: srb_dmat bus_dmamem_alloc failure!\n", acb->pci_unit); + printf("arcmsr%d: srb_dmat bus_dmamem_alloc failure!\n", device_get_unit(dev)); return ENXIO; } /* And permanently map them */ if(bus_dmamap_load(acb->srb_dmat, acb->srb_dmamap, acb->uncacheptr - , ARCMSR_SRBS_POOL_SIZE, arcmsr_map_freesrb, acb, /*flags*/0)) { + , 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); - printf("arcmsr%d: srb_dmat bus_dmamap_load failure!\n", acb->pci_unit); + printf("arcmsr%d: srb_dmat bus_dmamap_load failure!\n", device_get_unit(dev)); return ENXIO; } pci_command=pci_read_config(dev, PCIR_COMMAND, 2); @@ -2062,34 +2908,92 @@ static u_int32_t arcmsr_initialize(device_t dev) /* Enable Busmaster/Mem */ pci_command |= PCIM_CMD_MEMEN; pci_write_config(dev, PCIR_COMMAND, pci_command, 2); - acb->sys_res_arcmsr=bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0ul, ~0ul, 0x1000, RF_ACTIVE); - if(acb->sys_res_arcmsr == NULL) { - arcmsr_free_resource(acb); - printf("arcmsr%d: bus_alloc_resource failure!\n", acb->pci_unit); - return ENOMEM; - } - if(rman_get_start(acb->sys_res_arcmsr) <= 0) { - arcmsr_free_resource(acb); - printf("arcmsr%d: rman_get_start failure!\n", acb->pci_unit); - return ENXIO; - } - mem_base=(vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr); - if(mem_base==0) { - arcmsr_free_resource(acb); - printf("arcmsr%d: rman_get_virtual failure!\n", acb->pci_unit); - return ENXIO; + switch(acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + 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); + 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; + case ACB_ADAPTER_TYPE_B: { + struct HBB_MessageUnit *phbbmu; + struct CommandControlBlock *freesrb; + u_int32_t rid[]={ PCIR_BAR(0), PCIR_BAR(2) }; + vm_offset_t mem_base[]={0,0}; + 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); + } 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); + } + if(acb->sys_res_arcmsr[i] == NULL) { + arcmsr_free_resource(acb); + printf("arcmsr%d:" + " bus_alloc_resource %d failure!\n", device_get_unit(dev), i); + return ENOMEM; + } + if(rman_get_start(acb->sys_res_arcmsr[i]) <= 0) { + arcmsr_free_resource(acb); + printf("arcmsr%d:" + " rman_get_start %d failure!\n", device_get_unit(dev), i); + return ENXIO; + } + mem_base[i]=(vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[i]); + if(mem_base[i]==0) { + arcmsr_free_resource(acb); + printf("arcmsr%d:" + " rman_get_virtual %d failure!\n", device_get_unit(dev), i); + return ENXIO; + } + acb->btag[i]=rman_get_bustag(acb->sys_res_arcmsr[i]); + acb->bhandle[i]=rman_get_bushandle(acb->sys_res_arcmsr[i]); + } + freesrb=(struct CommandControlBlock *)acb->uncacheptr; + acb->pmu=(struct MessageUnit_UNION *)&freesrb[ARCMSR_MAX_FREESRB_NUM]; + phbbmu=(struct HBB_MessageUnit *)acb->pmu; + phbbmu->hbb_doorbell=(struct HBB_DOORBELL *)mem_base[0]; + phbbmu->hbb_rwbuffer=(struct HBB_RWBUFFER *)mem_base[1]; + } + break; } if(acb->acb_flags & ACB_F_MAPFREESRB_FAILD) { arcmsr_free_resource(acb); - printf("arcmsr%d: map free srb failure!\n", acb->pci_unit); + printf("arcmsr%d: map free srb failure!\n", device_get_unit(dev)); return ENXIO; } - acb->btag=rman_get_bustag(acb->sys_res_arcmsr); - acb->bhandle=rman_get_bushandle(acb->sys_res_arcmsr); - acb->pmu=(struct MessageUnit *)mem_base; acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED |ACB_F_MESSAGE_RQBUFFER_CLEARED - |ACB_F_MESSAGE_WQBUFFER_READED); + |ACB_F_MESSAGE_WQBUFFER_READ); acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; /* ******************************************************************** @@ -2098,12 +3002,9 @@ static u_int32_t arcmsr_initialize(device_t dev) */ for(i=0;idevstate[i][j]=ARECA_RAID_GOOD; + acb->devstate[i][j]=ARECA_RAID_GONE; } } - /* disable iop all outbound interrupt */ - intmask_org=CHIP_REG_READ32(outbound_intmask); - CHIP_REG_WRITE32(outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); arcmsr_iop_init(acb); return(0); } @@ -2119,7 +3020,7 @@ static u_int32_t arcmsr_attach(device_t dev) struct cam_devq *devq; /* Device Queue to use for this SIM */ struct resource *irqres; int rid; - + if(acb == NULL) { printf("arcmsr%d: cannot allocate softc\n", unit); return (ENOMEM); @@ -2134,8 +3035,13 @@ static u_int32_t arcmsr_attach(device_t dev) rid=0; 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)) { + , 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)) { +#endif arcmsr_free_resource(acb); ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); printf("arcmsr%d: unable to register interrupt handler!\n", unit); @@ -2158,9 +3064,15 @@ static u_int32_t arcmsr_attach(device_t dev) printf("arcmsr%d: cam_simq_alloc failure!\n", unit); 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); +#else + acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll, + "arcmsr", acb, unit, 1, + ARCMSR_MAX_OUTSTANDING_CMD, devq); +#endif if(acb->psim == NULL) { arcmsr_free_resource(acb); bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); @@ -2170,7 +3082,11 @@ static u_int32_t arcmsr_attach(device_t dev) return ENXIO; } ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); +#if __FreeBSD_version >= 700099 if(xpt_bus_register(acb->psim, dev, 0) != CAM_SUCCESS) { +#else + if(xpt_bus_register(acb->psim, 0) != CAM_SUCCESS) { +#endif arcmsr_free_resource(acb); bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); cam_sim_free(acb->psim, /*free_devq*/TRUE); @@ -2178,7 +3094,7 @@ static u_int32_t arcmsr_attach(device_t dev) printf("arcmsr%d: xpt_bus_register failure!\n", unit); return ENXIO; } - if(xpt_create_path(&acb->ppath, /* periph */ NULL + if(xpt_create_path(&acb->ppath, /* periph */ NULL , cam_sim_path(acb->psim) , CAM_TARGET_WILDCARD , CAM_LUN_WILDCARD) != CAM_REQ_CMP) { @@ -2225,13 +3141,14 @@ static u_int32_t arcmsr_probe(device_t dev) static char buf[256]; char *type; int raid6 = 1; - + if (pci_get_vendor(dev) != PCI_VENDOR_ID_ARECA) { return (ENXIO); } switch(id=pci_get_devid(dev)) { case PCIDevVenIDARC1110: case PCIDevVenIDARC1210: + case PCIDevVenIDARC1201: raid6 = 0; /*FALLTHRU*/ case PCIDevVenIDARC1120: @@ -2265,40 +3182,31 @@ static u_int32_t arcmsr_probe(device_t dev) */ static void arcmsr_shutdown(device_t dev) { - u_int32_t i, poll_count=0; + u_int32_t i; u_int32_t intmask_org; struct CommandControlBlock *srb; struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); - + /* stop adapter background rebuild */ ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); + /* disable all outbound interrupt */ + intmask_org=arcmsr_disable_allintr(acb); arcmsr_stop_adapter_bgrb(acb); arcmsr_flush_adapter_cache(acb); - /* disable all outbound interrupt */ - intmask_org=CHIP_REG_READ32(outbound_intmask); - CHIP_REG_WRITE32(outbound_intmask, (intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE)); /* abort all outstanding command */ acb->acb_flags |= ACB_F_SCSISTOPADAPTER; acb->acb_flags &= ~ACB_F_IOP_INITED; if(acb->srboutstandingcount!=0) { - while((acb->srboutstandingcount!=0) && (poll_count < 256)) { - arcmsr_interrupt((void *)acb); - UDELAY(25000); - poll_count++; - } - if(acb->srboutstandingcount!=0) { - arcmsr_abort_allcmd(acb); - /*clear all outbound posted Q*/ - for(i=0;ipsrb_pool[i]; - if(srb->startdone==ARCMSR_SRB_START) { - srb->startdone=ARCMSR_SRB_ABORTED; - srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; - arcmsr_srb_complete(srb, 1); - } + /*clear and abort all outbound posted Q*/ + arcmsr_done4abort_postqueue(acb); + /* talk to iop 331 outstanding command aborted*/ + arcmsr_abort_allcmd(acb); + for(i=0;ipsrb_pool[i]; + if(srb->startdone==ARCMSR_SRB_START) { + srb->startdone=ARCMSR_SRB_ABORTED; + srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; + arcmsr_srb_complete(srb, 1); } } } @@ -2315,11 +3223,14 @@ static void arcmsr_shutdown(device_t dev) static u_int32_t arcmsr_detach(device_t dev) { struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); - + int i; + bus_teardown_intr(dev, acb->irqres, acb->ih); arcmsr_shutdown(dev); arcmsr_free_resource(acb); - bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0), acb->sys_res_arcmsr); + for(i=0; (acb->sys_res_arcmsr[i]!=NULL) && (i<2); i++) { + bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(i), acb->sys_res_arcmsr[i]); + } bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); xpt_async(AC_LOST_DEVICE, acb->ppath, NULL); diff --git a/sys/dev/arcmsr/arcmsr.h b/sys/dev/arcmsr/arcmsr.h index 8060707d8b58..0b573816a184 100644 --- a/sys/dev/arcmsr/arcmsr.h +++ b/sys/dev/arcmsr/arcmsr.h @@ -37,7 +37,7 @@ ************************************************************************** * $FreeBSD$ */ -#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.14 2007-2-05" +#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2007-10-07" #define ARCMSR_SCSI_INITIATOR_ID 255 #define ARCMSR_DEV_SECTOR_SIZE 512 #define ARCMSR_MAX_XFER_SECTORS 4096 @@ -52,17 +52,18 @@ #define ARCMSR_MAX_SG_ENTRIES 38 /* max 38*/ #define ARCMSR_MAX_ADAPTER 4 #define ARCMSR_RELEASE_SIMQ_LEVEL 230 +#define ARCMSR_MAX_HBB_POSTQUEUE 264 /* (ARCMSR_MAX_OUTSTANDING_CMD+8) */ /* ********************************************************************* */ #ifndef TRUE - #define TRUE 1 + #define TRUE 1 #endif #ifndef FALSE - #define FALSE 0 + #define FALSE 0 #endif #ifndef INTR_ENTROPY - # define INTR_ENTROPY 0 + # define INTR_ENTROPY 0 #endif #ifndef offsetof @@ -89,6 +90,7 @@ #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 PCIDevVenIDARC1110 0x111017D3 /* Vendor Device ID */ #define PCIDevVenIDARC1120 0x112017D3 /* Vendor Device ID */ @@ -105,6 +107,7 @@ #define PCIDevVenIDARC1381 0x138117D3 /* Vendor Device ID */ #define PCIDevVenIDARC1680 0x168017D3 /* Vendor Device ID */ #define PCIDevVenIDARC1681 0x168117D3 /* Vendor Device ID */ +#define PCIDevVenIDARC1201 0x120117D3 /* Vendor Device ID */ #ifndef PCIR_BARS #define PCIR_BARS 0x10 @@ -198,6 +201,52 @@ struct CMD_MESSAGE_FIELD { #define ARCMSR_MESSAGE_RETURNCODE_ERROR 0x00000006 #define ARCMSR_MESSAGE_RETURNCODE_3F 0x0000003F /* +************************************************************************ +** SPEC. for Areca HBB adapter +************************************************************************ +*/ +/* ARECA HBB COMMAND for its FIRMWARE */ +#define ARCMSR_DRV2IOP_DOORBELL 0x00020400 /* window of "instruction flags" from driver to iop */ +#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 */ + +#define ARCMSR_IOP2DRV_DATA_WRITE_OK 0x00000001 /* ioctl transfer */ +#define ARCMSR_IOP2DRV_DATA_READ_OK 0x00000002 /* ioctl transfer */ +#define ARCMSR_IOP2DRV_CDB_DONE 0x00000004 +#define ARCMSR_IOP2DRV_MESSAGE_CMD_DONE 0x00000008 + +#define ARCMSR_DOORBELL_HANDLE_INT 0x0000000F +#define ARCMSR_DOORBELL_INT_CLEAR_PATTERN 0xFF00FFF0 +#define ARCMSR_MESSAGE_INT_CLEAR_PATTERN 0xFF00FFF7 + +#define ARCMSR_MESSAGE_GET_CONFIG 0x00010008 /* (ARCMSR_INBOUND_MESG0_GET_CONFIG<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ +#define ARCMSR_MESSAGE_SET_CONFIG 0x00020008 /* (ARCMSR_INBOUND_MESG0_SET_CONFIG<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ +#define ARCMSR_MESSAGE_ABORT_CMD 0x00030008 /* (ARCMSR_INBOUND_MESG0_ABORT_CMD<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ +#define ARCMSR_MESSAGE_STOP_BGRB 0x00040008 /* (ARCMSR_INBOUND_MESG0_STOP_BGRB<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ +#define ARCMSR_MESSAGE_FLUSH_CACHE 0x00050008 /* (ARCMSR_INBOUND_MESG0_FLUSH_CACHE<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ +#define ARCMSR_MESSAGE_START_BGRB 0x00060008 /* (ARCMSR_INBOUND_MESG0_START_BGRB<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ +#define ARCMSR_MESSAGE_START_DRIVER_MODE 0x000E0008 +#define ARCMSR_MESSAGE_SET_POST_WINDOW 0x000F0008 +#define ARCMSR_MESSAGE_ACTIVE_EOI_MODE 0x00100008 +#define ARCMSR_MESSAGE_FIRMWARE_OK 0x80000000 /* ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK */ + +#define ARCMSR_DRV2IOP_DATA_WRITE_OK 0x00000001 /* ioctl transfer */ +#define ARCMSR_DRV2IOP_DATA_READ_OK 0x00000002 /* ioctl transfer */ +#define ARCMSR_DRV2IOP_CDB_POSTED 0x00000004 +#define ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED 0x00000008 +#define ARCMSR_DRV2IOP_END_OF_INTERRUPT 0x00000010 /* */ + +/* data tunnel buffer between user space program and its firmware */ +#define ARCMSR_MSGCODE_RWBUFFER 0x0000fa00 /* iop msgcode_rwbuffer for message command */ +#define ARCMSR_IOCTL_WBUFFER 0x0000fe00 /* user space data to iop 128bytes */ +#define ARCMSR_IOCTL_RBUFFER 0x0000ff00 /* iop data to user space 128bytes */ +#define ARCMSR_HBB_BASE0_OFFSET 0x00000010 +#define ARCMSR_HBB_BASE1_OFFSET 0x00000018 +#define ARCMSR_HBB_BASE0_LEN 0x00021000 +#define ARCMSR_HBB_BASE1_LEN 0x00010000 +/* ************************************************************* ** structure for holding DMA address data ************************************************************* @@ -218,8 +267,8 @@ struct CMD_MESSAGE_FIELD { ** 3. Index Memory Usage ** offset 0xf00 : for RS232 out (request buffer) ** offset 0xe00 : for RS232 in (scratch buffer) -** offset 0xa00 : for inbound message code message_rwbuffer (driver send to IOP331) -** offset 0xa00 : for outbound message code message_rwbuffer (IOP331 send to driver) +** offset 0xa00 : for inbound message code msgcode_rwbuffer (driver send to IOP331) +** offset 0xa00 : for outbound message code msgcode_rwbuffer (IOP331 send to driver) ** 4. RS-232 emulation ** Currently 128 byte buffer is used ** 1st u_int32_t : Data length (1--124) @@ -258,7 +307,7 @@ struct CMD_MESSAGE_FIELD { ** 8. Message1 Out - Diag Status Code (????) ** 9. Message0 message code : ** 0x00 : NOP -** 0x01 : Get Config ->offset 0xa00 :for outbound message code message_rwbuffer (IOP331 send to driver) +** 0x01 : Get Config ->offset 0xa00 :for outbound message code msgcode_rwbuffer (IOP331 send to driver) ** Signature 0x87974060(4) ** Request len 0x00000200(4) ** numbers of queue 0x00000100(4) @@ -267,10 +316,10 @@ struct CMD_MESSAGE_FIELD { ** vendor 40 bytes char ** model 8 bytes char ** FirmVer 16 bytes char -** Device Map 16 bytes char -** -** FirmwareVersion DWORD <== Added for checking of new firmware capability -** 0x02 : Set Config ->offset 0xa00 : for inbound message code message_rwbuffer (driver send to IOP331) +** Device Map 16 bytes char +** +** FirmwareVersion DWORD <== Added for checking of new firmware capability +** 0x02 : Set Config ->offset 0xa00 : for inbound message code msgcode_rwbuffer (driver send to IOP331) ** Signature 0x87974063(4) ** UPPER32 of Request Frame (4)-->Driver Only ** 0x03 : Reset (Abort all queued Command) @@ -278,15 +327,15 @@ struct CMD_MESSAGE_FIELD { ** 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 0xa00 : for inbound message code message_rwbuffer (driver to IOP331) -** 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) +** 0x08 : Set controller time ->offset 0xa00 : for inbound message code msgcode_rwbuffer (driver to IOP331) +** 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) ************************************************************************************************ */ /* signature of set and get firmware config */ @@ -371,7 +420,7 @@ struct ARCMSR_CDB { u_int8_t TargetID; /* 01h should be 0--15 */ u_int8_t LUN; /* 02h should be 0--7 */ u_int8_t Function; /* 03h should be 1 */ - + u_int8_t CdbLength; /* 04h not used now */ u_int8_t sgcount; /* 05h */ u_int8_t Flags; /* 06h */ @@ -382,10 +431,10 @@ struct ARCMSR_CDB { #define ARCMSR_CDB_FLAG_HEADQ 0x08 #define ARCMSR_CDB_FLAG_ORDEREDQ 0x10 u_int8_t Reserved1; /* 07h */ - + u_int32_t Context; /* 08h Address of this request */ u_int32_t DataLength; /* 0ch not used now */ - + u_int8_t Cdb[16]; /* 10h SCSI CDB */ /* ******************************************************** @@ -406,12 +455,12 @@ struct ARCMSR_CDB { #define ARCMSR_DEV_SELECT_TIMEOUT 0xF0 #define ARCMSR_DEV_ABORTED 0xF1 #define ARCMSR_DEV_INIT_FAIL 0xF2 - + u_int8_t SenseData[15]; /* 21h output */ - + union { - struct SG32ENTRY sg32entry[ARCMSR_MAX_SG_ENTRIES]; /* 30h Scatter gather address */ - struct SG64ENTRY sg64entry[ARCMSR_MAX_SG_ENTRIES]; /* 30h */ + struct SG32ENTRY sg32entry[ARCMSR_MAX_SG_ENTRIES]; /* 30h Scatter gather address */ + struct SG64ENTRY sg64entry[ARCMSR_MAX_SG_ENTRIES]; /* 30h */ } u; }; /* @@ -423,42 +472,42 @@ struct ARCMSR_CDB { ********************************************************************* */ struct CommandControlBlock { - struct ARCMSR_CDB arcmsr_cdb; + 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 reserved1; /* 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 */ 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 + #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 + #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 */ 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 + #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 + #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 /* ========================================================== */ @@ -469,8 +518,14 @@ struct CommandControlBlock { ********************************************************************* */ struct AdapterControlBlock { - bus_space_tag_t btag; - bus_space_handle_t bhandle; + 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_D 0x00000008 /* hbd A IOP */ + + bus_space_tag_t btag[2]; + bus_space_handle_t bhandle[2]; bus_dma_tag_t parent_dmat; bus_dma_tag_t dm_segs_dmat; /* dmat for buffer I/O */ bus_dma_tag_t srb_dmat; /* dmat for freesrb */ @@ -482,21 +537,22 @@ struct AdapterControlBlock { struct cdev * ioctl_dev; #endif int pci_unit; - - struct resource * sys_res_arcmsr; + + struct resource * sys_res_arcmsr[2]; struct resource * irqres; void * ih; /* interrupt handle */ - + /* Hooks into the CAM XPT */ struct cam_sim *psim; struct cam_path *ppath; u_int8_t * uncacheptr; unsigned long vir2phy_offset; + unsigned long srb_phyaddr; /* Offset is used in making arc cdb physical to virtual calculations */ u_int32_t outbound_int_enable; - - struct MessageUnit * pmu; /* message unit ATU inbound base address0 */ - + + struct MessageUnit_UNION * pmu; /* message unit ATU inbound base address0 */ + u_int8_t adapter_index; /* */ u_int8_t irq; u_int16_t acb_flags; /* */ @@ -506,30 +562,30 @@ struct AdapterControlBlock { #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_READED 0x0040 +#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_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 */ int32_t workingsrb_doneindex; /* done srb array index */ int32_t workingsrb_startindex; /* start srb array index */ int32_t srboutstandingcount; - + u_int8_t rqbuffer[ARCMSR_MAX_QBUFFER]; /* data collection buffer for read from 80331 */ u_int32_t rqbuf_firstindex; /* first of read buffer */ u_int32_t rqbuf_lastindex; /* last of read buffer */ - + u_int8_t wqbuffer[ARCMSR_MAX_QBUFFER]; /* data collection buffer for write to 80331 */ u_int32_t wqbuf_firstindex; /* first of write buffer */ u_int32_t wqbuf_lastindex; /* last of write buffer */ - + arcmsr_lock_t workingQ_done_lock; arcmsr_lock_t workingQ_start_lock; 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 @@ -1071,8 +1127,7 @@ struct SENSE_DATA { ** and transaction forwarding of the following VGA transactions from the primary bus ** to the secondary bus: ** frame buffer memory addresses 000A0000h:000BFFFFh, -** VGA I/O addresses 3B0:3BBh and 3C0h:3DFh, where AD[31:16]=¡§0000h¡ -** ¨ and AD[15:10] are either not decoded (i.e., don't cares), +** VGA I/O addresses 3B0:3BBh and 3C0h:3DFh, where AD[31:16]=¡§0000h?** ?and AD[15:10] are either not decoded (i.e., don't cares), ** or must be ¡§000000b¡¨ ** depending upon the state of the VGA Alias Filter Enable bit. (bit(4) of this register) ** I/O and Memory Enable bits must be set in the Command register @@ -3819,7 +3874,7 @@ struct SENSE_DATA { ** 0FFCH ] 1004 Index Registers ******************************************************************************* */ -struct MessageUnit +struct HBA_MessageUnit { u_int32_t resrved0[4]; /*0000 000F*/ u_int32_t inbound_msgaddr0; /*0010 0013*/ @@ -3838,13 +3893,65 @@ struct MessageUnit 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 message_rwbuffer[256]; /*0a00 0DFF 256*/ + 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 *****************************************************************************