diff options
Diffstat (limited to 'sys/dev/arcmsr/arcmsr.c')
-rw-r--r-- | sys/dev/arcmsr/arcmsr.c | 3490 |
1 files changed, 1574 insertions, 1916 deletions
diff --git a/sys/dev/arcmsr/arcmsr.c b/sys/dev/arcmsr/arcmsr.c index 4da0343..7d8d807 100644 --- a/sys/dev/arcmsr/arcmsr.c +++ b/sys/dev/arcmsr/arcmsr.c @@ -4,47 +4,56 @@ ** FILE NAME : arcmsr.c ** BY : Erich Chen ** Description: SCSI RAID Device Driver for -** ARECA (ARC1110/1120/1160/1210/1220/1260) SATA RAID HOST Adapter -** ARCMSR RAID Host adapter[RAID controller:INTEL 331(PCI-X) 341(PCI-EXPRESS) chip set] +** ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX) SATA/SAS RAID HOST Adapter +** ARCMSR RAID Host adapter +** [RAID controller:INTEL 331(PCI-X) 341(PCI-EXPRESS) chip set] ****************************************************************************************** ************************************************************************ ** -** Copyright (c) 2004-2006 ARECA Co. Ltd.
-** Erich Chen, Taipei Taiwan All rights reserved.
+** Copyright (c) 2004-2006 ARECA Co. Ltd. +** Erich Chen, Taipei Taiwan All rights reserved. ** -** Redistribution and use in source and binary forms,with or without -** modification,are permitted provided that the following conditions +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions ** are met: ** 1. Redistributions of source code must retain the above copyright -** notice,this list of conditions and the following disclaimer. +** notice, this list of conditions and the following disclaimer. ** 2. Redistributions in binary form must reproduce the above copyright -** notice,this list of conditions and the following disclaimer in the +** notice, this list of conditions and the following disclaimer in the ** documentation and/or other materials provided with the distribution. ** 3. The name of the author may not be used to endorse or promote products ** derived from this software without specific prior written permission. ** ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -** IMPLIED WARRANTIES,INCLUDING,BUT NOT LIMITED TO,THE IMPLIED WARRANTIES +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,INDIRECT, -** INCIDENTAL,SPECIAL,EXEMPLARY,OR CONSEQUENTIAL DAMAGES(INCLUDING,BUT -** NOT LIMITED TO,PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA,OR PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY,WHETHER IN CONTRACT,STRICT LIABILITY,OR TORT +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT **(INCLUDING NEGLIGENCE OR OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF -** THIS SOFTWARE,EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ************************************************************************** ** History ** ** REV# DATE NAME DESCRIPTION ** 1.00.00.00 3/31/2004 Erich Chen First release ** 1.20.00.02 11/29/2004 Erich Chen bug fix with arcmsr_bus_reset when PHY error +** 1.20.00.03 4/19/2005 Erich Chen add SATA 24 Ports adapter type support +** clean unused function +** 1.20.00.12 9/12/2005 Erich Chen bug fix with abort command handling, +** firmware version check +** and firmware update notify for hardware bug fix +** handling if none zero high part physical address +** of srb resource +** 1.20.00.13 8/18/2006 Erich Chen remove pending srb and report busy +** add iop message xfer +** with scsi pass-through command +** add new device id of sas raid adapters +** code fit for SPARC64 & PPC ****************************************************************************************** -** $FreeBSD$ -*/ -#define ARCMSR_DEBUG0 0 -/* -********************************** +* $FreeBSD$ */ #include <sys/param.h> #include <sys/systm.h> @@ -80,104 +89,84 @@ #include <cam/cam_debug.h> #include <cam/scsi/scsi_all.h> #include <cam/scsi/scsi_message.h> -/* +/* ************************************************************************** -** Define the OS version specific locks ************************************************************************** */ #if __FreeBSD_version >= 500005 #include <sys/selinfo.h> - #include <sys/mutex.h> + #include <sys/mutex.h> + #include <sys/endian.h> #include <dev/pci/pcivar.h> #include <dev/pci/pcireg.h> - #define ARCMSR_LOCK_INIT(l, s) mtx_init(l, s,NULL, MTX_DEF|MTX_RECURSE) - #define ARCMSR_LOCK_ACQUIRE(l) mtx_lock(l) - #define ARCMSR_LOCK_RELEASE(l) mtx_unlock(l) - typedef struct mtx arcmsr_lock_t; + #define ARCMSR_LOCK_INIT(l, s) mtx_init(l, s, NULL, MTX_DEF|MTX_RECURSE) + #define ARCMSR_LOCK_ACQUIRE(l) mtx_lock(l) + #define ARCMSR_LOCK_RELEASE(l) mtx_unlock(l) + #define ARCMSR_LOCK_TRY(l) mtx_trylock(l) + #define arcmsr_htole32(x) htole32(x) + typedef struct mtx arcmsr_lock_t; #else #include <sys/select.h> #include <pci/pcivar.h> #include <pci/pcireg.h> - #define ARCMSR_LOCK_INIT(l, s) simple_lock_init(l) - #define ARCMSR_LOCK_ACQUIRE(l) simple_lock(l) - #define ARCMSR_LOCK_RELEASE(l) simple_unlock(l) - typedef struct simplelock arcmsr_lock_t; + #define ARCMSR_LOCK_INIT(l, s) simple_lock_init(l) + #define ARCMSR_LOCK_ACQUIRE(l) simple_lock(l) + #define ARCMSR_LOCK_RELEASE(l) simple_unlock(l) + #define ARCMSR_LOCK_TRY(l) simple_lock_try(l) + #define arcmsr_htole32(x) (x) + typedef struct simplelock arcmsr_lock_t; #endif #include <dev/arcmsr/arcmsr.h> +#define ARCMSR_SRBS_POOL_SIZE ((sizeof(struct CommandControlBlock) * ARCMSR_MAX_FREESRB_NUM)+0x20) /* ************************************************************************** -** __FreeBSD_version 502010 ************************************************************************** */ -static VOID arcmsr_interrupt(VOID *arg); -static LONG arcmsr_probe(device_t dev); -static LONG arcmsr_attach(device_t dev); -static LONG arcmsr_detach(device_t dev); -static VOID arcmsr_shutdown(device_t dev); -#if 0 -ULONG arcmsr_make_timespec(ULONG year,ULONG mon,ULONG day,ULONG hour,ULONG min,ULONG sec); -ULONG arcmsr_getcmos_time(VOID); -#endif -LONG arcmsr_queue_dpc(PACB pACB,DPCFUN dpcfun,VOID *arg); -LONG arcmsr_iop_ioctlcmd(PACB pACB,ULONG ioctl_cmd,caddr_t arg); -BOOLEAN arcmsr_seek_cmd2abort(union ccb * pabortccb); -BOOLEAN arcmsr_wait_msgint_ready(PACB pACB); -PSRB arcmsr_get_freesrb(PACB pACB); -VOID arcmsr_free_resource(PACB pACB); -VOID arcmsr_bus_reset(PACB pACB); -VOID arcmsr_stop_adapter_bgrb(PACB pACB); -VOID arcmsr_start_adapter_bgrb(PACB pACB); -VOID arcmsr_iop_init(PACB pACB); -VOID arcmsr_do_dpcQ(PACB pACB); -VOID arcmsr_flush_adapter_cache(PACB pACB); -VOID arcmsr_do_thread_works(VOID *arg); -VOID arcmsr_queue_wait2go_srb(PACB pACB,PSRB pSRB); -VOID arcmsr_post_wait2go_srb(PACB pACB); -VOID arcmsr_post_Qbuffer(PACB pACB); -VOID arcmsr_abort_allcmd(PACB pACB); -VOID arcmsr_srb_complete(PSRB pSRB); -VOID arcmsr_iop_reset(PACB pACB); -VOID arcmsr_report_SenseInfoBuffer(PSRB pSRB); -VOID arcmsr_build_srb(PSRB pSRB, bus_dma_segment_t *dm_segs, LONG nseg); +#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) /* -***************************************************************************************** -** Character device switch table -**struct cdevsw { -** d_open_t *d_open; -** d_close_t *d_close; -** d_read_t *d_read; -** d_write_t *d_write; -** d_ioctl_t *d_ioctl; -** d_poll_t *d_poll; -** d_mmap_t *d_mmap; -** d_strategy_t *d_strategy; -** const char *d_name; "" base device name, e.g. 'vn' -** int d_maj; -** d_dump_t *d_dump; -** d_psize_t *d_psize; -** u_int d_flags; -** int d_bmaj; -** d_kqfilter_t *d_kqfilter; "" additions below are not binary compatible with 4.2 and below -**}; -****************************************************************************************** +************************************************************************** +************************************************************************** */ +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_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); +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_abort_allcmd(struct AdapterControlBlock *acb); +static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag); +static void arcmsr_iop_reset(struct AdapterControlBlock *acb); +static void arcmsr_report_sense_info(struct CommandControlBlock *srb); +static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t * dm_segs, u_int32_t nseg); +static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb); +static int arcmsr_resume(device_t dev); +static int arcmsr_suspend(device_t dev); /* ************************************************************************** -** Insert a delay in micro-seconds and milli-seconds. -** static void MDELAY(LONG ms) { while (ms--) UDELAY(1000); } ************************************************************************** */ -static VOID UDELAY(LONG us) { DELAY(us); } +static void UDELAY(u_int32_t us) { DELAY(us); } /* ************************************************************************** -** ************************************************************************** */ static bus_dmamap_callback_t arcmsr_map_freesrb; static bus_dmamap_callback_t arcmsr_executesrb; /* ************************************************************************** -** ************************************************************************** */ static d_open_t arcmsr_open; @@ -188,75 +177,80 @@ static device_method_t arcmsr_methods[]={ DEVMETHOD(device_probe, arcmsr_probe), DEVMETHOD(device_attach, arcmsr_attach), DEVMETHOD(device_detach, arcmsr_detach), - DEVMETHOD(device_shutdown, arcmsr_shutdown), - { 0,0 } + 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 _ACB) + "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); -MODULE_DEPEND(arcmsr, cam, 1, 1, 1); - -#if __FreeBSD_version >= 502010 +DRIVER_MODULE(arcmsr, pci, arcmsr_driver, arcmsr_devclass, 0, 0); +#ifndef BUS_DMA_COHERENT + #define BUS_DMA_COHERENT 0x04 /* hint: map memory in a coherent way */ +#endif +#if __FreeBSD_version >= 501000 + #ifndef D_NEEDGIANT + #define D_NEEDGIANT 0x00400000 /* driver want Giant */ + #endif + #ifndef D_VERSION + #define D_VERSION 0x20011966 + #endif static struct cdevsw arcmsr_cdevsw={ - .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, - .d_open = arcmsr_open, /* open */ - .d_close = arcmsr_close, /* close */ - .d_ioctl = arcmsr_ioctl, /* ioctl */ - .d_name = "arcmsr", /* name */ + #if __FreeBSD_version > 502010 + .d_version = D_VERSION, + #endif + .d_flags = D_NEEDGIANT, + .d_open = arcmsr_open, /* open */ + .d_close = arcmsr_close, /* close */ + .d_ioctl = arcmsr_ioctl, /* ioctl */ + .d_name = "arcmsr", /* name */ }; #else #define ARCMSR_CDEV_MAJOR 180 static struct cdevsw arcmsr_cdevsw = { - arcmsr_open, /* open */ - arcmsr_close, /* close */ - noread, /* read */ - nowrite, /* write */ - arcmsr_ioctl, /* ioctl */ - nopoll, /* poll */ - nommap, /* mmap */ - nostrategy, /* strategy */ - "arcmsr", /* name */ - ARCMSR_CDEV_MAJOR, /* major */ - nodump, /* dump */ - nopsize, /* psize */ - 0 /* flags */ + arcmsr_open, /* open */ + arcmsr_close, /* close */ + noread, /* read */ + nowrite, /* write */ + arcmsr_ioctl, /* ioctl */ + nopoll, /* poll */ + nommap, /* mmap */ + nostrategy, /* strategy */ + "arcmsr", /* name */ + ARCMSR_CDEV_MAJOR, /* major */ + nodump, /* dump */ + nopsize, /* psize */ + 0 /* flags */ }; #endif #if __FreeBSD_version < 500005 - static int arcmsr_open(dev_t dev, int flags, int fmt, struct proc *proc) + 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) + 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) + static int arcmsr_open(struct cdev *dev, int flags, int fmt, d_thread_t *proc) #endif #endif { #if __FreeBSD_version < 503000 - PACB pACB=dev->si_drv1; - #else + struct AdapterControlBlock *acb=dev->si_drv1; + #else int unit = minor(dev); - PACB pACB = devclass_get_softc(arcmsr_devclass, unit); - #endif - - if(pACB==NULL) - { + struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); + #endif + if(acb==NULL) { return ENXIO; } - /* Check to make sure the device isn't already open */ - if (pACB->acb_flags & ACB_F_IOCTL_OPEN) - { - return EBUSY; - } - pACB->acb_flags |= ACB_F_IOCTL_OPEN; return 0; } /* @@ -264,400 +258,189 @@ 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) + 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) + 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) + static int arcmsr_close(struct cdev *dev, int flags, int fmt, d_thread_t *proc) #endif #endif { #if __FreeBSD_version < 503000 - PACB pACB=dev->si_drv1; - #else + struct AdapterControlBlock *acb=dev->si_drv1; + #else int unit = minor(dev); - PACB pACB = devclass_get_softc(arcmsr_devclass, unit); - #endif - - if(pACB==NULL) - { + struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); + #endif + if(acb==NULL) { return ENXIO; } - pACB->acb_flags &= ~ACB_F_IOCTL_OPEN; return 0; } /* ************************************************************************** -**ENOENT -**ENOIOCTL -**ENOMEM -**EINVAL ************************************************************************** */ #if __FreeBSD_version < 500005 - static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct proc *proc) + 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) + 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) + 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 - PACB pACB=dev->si_drv1; - #else + struct AdapterControlBlock *acb=dev->si_drv1; + #else int unit = minor(dev); - PACB pACB = devclass_get_softc(arcmsr_devclass, unit); - #endif - - if(pACB==NULL) - { - return ENXIO; - } - return(arcmsr_iop_ioctlcmd(pACB,ioctl_cmd,arg)); -} -/* -************************************************************************** -************************************************************************** -*/ -LONG arcmsr_queue_dpc(PACB pACB,DPCFUN dpcfun,VOID *arg) -{ - ULONG s; - UCHAR index_pointer; - - #if ARCMSR_DEBUG0 - printf("arcmsr_queue_dpc................. \n"); - #endif - - s=splcam(); - index_pointer=(pACB->dpcQ_tail + 1) % ARCMSR_MAX_DPC; - if(index_pointer==pACB->dpcQ_head) - { - splx(s); - printf("DPC Queue full!\n"); - return -1; - } - pACB->dpcQ[pACB->dpcQ_tail].dpcfun=dpcfun; - pACB->dpcQ[pACB->dpcQ_tail].arg=arg; - pACB->dpcQ_tail=index_pointer; - /* - ********************************************************* - ********************************************************* - */ - wakeup(pACB->kthread_proc); - - splx(s); - return 0; -} -/* -************************************************************************** -** arcmsr_do_dpcQ -** execute dpc routine by kernel thread -*************************************************************************** -*/ -VOID arcmsr_do_dpcQ(PACB pACB) -{ - #if ARCMSR_DEBUG0 - printf("arcmsr_do_dpcQ................. \n"); + struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); #endif - /* - ****************************************** - ****************************************** - */ - while (pACB->dpcQ_head!=pACB->dpcQ_tail) - { - ULONG s; - DPC dpc; - /* got a "dpc routine" */ - s=splcam(); - dpc=pACB->dpcQ[pACB->dpcQ_head]; - pACB->dpcQ_head++; - pACB->dpcQ_head %=ARCMSR_MAX_DPC; - splx(s); - /* execute this "dpc routine" */ - dpc.dpcfun(dpc.arg); + if(acb==NULL) { + return ENXIO; } - return; + return(arcmsr_iop_ioctlcmd(acb, ioctl_cmd, arg)); } -#if 0 /* -********************************************************************** -** <second> bit 05,04,03,02,01,00: 0 - 59 -** <minute> bit 11,10,09,08,07,06: 0 - 59 -** <month> bit 15,14,13,12: 1 - 12 -** <hour> bit 21,20,19,18,17,16: 0 - 59 -** <day> bit 26,25,24,23,22: 1 - 31 -** <year> bit 31,30,29,28,27: 0=2000,31=2031 -********************************************************************** +******************************************************************************* +******************************************************************************* */ -ULONG arcmsr_make_timespec(ULONG year,ULONG mon,ULONG day,ULONG hour,ULONG min,ULONG sec) +static int arcmsr_suspend(device_t dev) { - return((year<<27)|(day<<22)|(hour<<16)|(mon<<12)|(min<<6)|(sec)); + 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)); + /* flush controller */ + arcmsr_iop_parking(acb); + return(0); } /* -******************************************************************** -******************************************************************** +******************************************************************************* +******************************************************************************* */ -ULONG arcmsr_getcmos_time(VOID) +static int arcmsr_resume(device_t dev) { - ULONG year,mon,day,hour,min,sec; + struct AdapterControlBlock *acb = device_get_softc(dev); - #if ARCMSR_DEBUG0 - printf("arcmsr_getcmos_time \n"); - #endif - sec=bcd2bin(rtcin(RTC_SEC)); - min=bcd2bin(rtcin(RTC_MIN)); - hour=bcd2bin(rtcin(RTC_HRS)); - day=bcd2bin(rtcin(RTC_DAY)); - mon=bcd2bin(rtcin(RTC_MONTH)); - year=bcd2bin(rtcin(RTC_YEAR)); - if((year +=1900) < 1970) - year +=100; - return arcmsr_make_timespec(year,mon,day,hour,min,sec); + arcmsr_iop_init(acb); + return(0); } -#endif /* ********************************************************************************* -** Asynchronous notification handler. ********************************************************************************* */ -static VOID arcmsr_async(VOID *cb_arg, ULONG code, struct cam_path *path, VOID *arg) +static void arcmsr_async(void *cb_arg, u_int32_t code, struct cam_path *path, void *arg) { - PACB pACB; - UCHAR target_id,target_lun; - struct cam_sim *sim; - ULONG s; - #if ARCMSR_DEBUG0 - printf("arcmsr_async.......................................... \n"); - #endif - s=splcam(); + struct AdapterControlBlock *acb; + u_int8_t target_id, target_lun; + struct cam_sim * sim; sim=(struct cam_sim *) cb_arg; - pACB =(PACB) cam_sim_softc(sim); - switch (code) - { + 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)) - { + target_lun=xpt_path_lun_id(path); + if((target_id > ARCMSR_MAX_TARGETID) || (target_lun > ARCMSR_MAX_TARGETLUN)) { break; } - printf("%s:scsi id%d lun%d device lost \n",device_get_name(pACB->pci_dev),target_id,target_lun); + printf("%s:scsi id%d lun%d device lost \n" + , device_get_name(acb->pci_dev), target_id, target_lun); break; default: break; } - splx(s); -} -/* -************************************************************************** -* arcmsr_do_thread_works -* execute programs schedule by kernel thread -* execute programs schedule by kernel thread -* :do background rebuilding -* -* tsleep(void *ident,int priority,const char *wmesg,int timo) -* tsleep() -* General sleep call. Suspends the current process until a wakeup is -* performed on the specified identifier. The process will then be made -* runnable with the specified priority. Sleeps at most timo/hz seconds -* (0 means no timeout). If pri includes PCATCH flag, signals are checked -* before and after sleeping, else signals are not checked. Returns 0 if -* awakened, EWOULDBLOCK if the timeout expires. If PCATCH is set and a -* signal needs to be delivered, ERESTART is returned if the current system -* call should be restarted if possible, and EINTR is returned if the system -* call should be interrupted by the signal (return EINTR). -* -* await(int priority, int timo) -* await() - wait for async condition to occur. The process blocks until -* wakeup() is called on the most recent asleep() address. If wakeup is called -* priority to await(), await() winds up being a NOP. -* -* If await() is called more then once (without an intervening asleep() call), -* await() is still effectively a NOP but it calls mi_switch() to give other -* processes some cpu before returning. The process is left runnable. -* -* <<<<<<<< EXPERIMENTAL, UNTESTED >>>>>>>>>> -* asleep(void *ident, int priority, const char *wmesg, int timo) -* asleep() - async sleep call. Place process on wait queue and return -* immediately without blocking. The process stays runnable until await() -* is called. If ident is NULL, remove process from wait queue if it is still -* on one. -* -* Only the most recent sleep condition is effective when making successive -* calls to asleep() or when calling tsleep(). -* -* The timeout, if any, is not initiated until await() is called. The sleep -* priority, signal, and timeout is specified in the asleep() call but may be -* overriden in the await() call. -* -* <<<<<<<< EXPERIMENTAL, UNTESTED >>>>>>>>>> -* :do background rebuilding -*************************************************************************** -*/ -VOID arcmsr_do_thread_works(VOID *arg) -{ - PACB pACB=(PACB) arg; - ARCMSR_LOCK_INIT(&pACB->arcmsr_kthread_lock, "arcmsr kthread lock"); - - #if ARCMSR_DEBUG0 - printf("arcmsr_do_thread_works................. \n"); - #endif - - ARCMSR_LOCK_ACQUIRE(&pACB->arcmsr_kthread_lock); - while(1) - { - tsleep((caddr_t)pACB->kthread_proc, PRIBIO | PWAIT, "arcmsr", hz/4);/*.25 sec*/ - /* - ** if do_dpcQ_semaphore is signal - ** do following works - */ - arcmsr_do_dpcQ(pACB); /*see if there were some dpc routine need to execute*/ - if(pACB->acb_flags & ACB_F_STOP_THREAD) - { - ARCMSR_LOCK_RELEASE(&pACB->arcmsr_kthread_lock); - break; - } - } - kthread_exit(0); - return; } /* ************************************************************************ -** -** ************************************************************************ */ -VOID arcmsr_flush_adapter_cache(PACB pACB) +static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) { - #if ARCMSR_DEBUG0 - printf("arcmsr_flush_adapter_cache..............\n"); - #endif - CHIP_REG_WRITE32(&pACB->pmu->inbound_msgaddr0,ARCMSR_INBOUND_MESG0_FLUSH_CACHE); + 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; } /* ********************************************************************** -** -** -** ********************************************************************** */ -BOOLEAN arcmsr_wait_msgint_ready(PACB pACB) +static u_int8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *acb) { - ULONG Index; - UCHAR Retries=0x00; - do - { - for(Index=0; Index < 500000; Index++) - { - if(CHIP_REG_READ32(&pACB->pmu->outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) - { - CHIP_REG_WRITE32(&pACB->pmu->outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/ - return TRUE; + 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(10); - }/*max 5 seconds*/ - }while(Retries++ < 24);/*max 2 minutes*/ - return FALSE; + UDELAY(10000); + }/*max 1 seconds*/ + }while(Retries++ < 20);/*max 20 sec*/ + return 0xff; } /* ********************************************************************** -** -** Q back this SRB into ACB ArraySRB -** ********************************************************************** */ -VOID arcmsr_srb_complete(PSRB pSRB) +static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag) { - ULONG s; - PACB pACB=pSRB->pACB; - union ccb *pccb=pSRB->pccb; - - #if ARCMSR_DEBUG0 - printf("arcmsr_srb_complete: pSRB=%p srb_doneindex=%x srb_startindex=%x\n",pSRB,pACB->srb_doneindex,pACB->srb_startindex); - #endif + struct AdapterControlBlock *acb=srb->acb; + union ccb * pccb=srb->pccb; - if ((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) - { + 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) - { + if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { op = BUS_DMASYNC_POSTREAD; - } - else - { + } else { op = BUS_DMASYNC_POSTWRITE; } - bus_dmamap_sync(pACB->buffer_dmat, pSRB->dmamap, op); - bus_dmamap_unload(pACB->buffer_dmat, pSRB->dmamap); - } - s=splcam(); - atomic_subtract_int(&pACB->srboutstandingcount,1); - pSRB->startdone=ARCMSR_SRB_DONE; - pSRB->srb_flags=0; - pACB->psrbringQ[pACB->srb_doneindex]=pSRB; - pACB->srb_doneindex++; - pACB->srb_doneindex %= ARCMSR_MAX_FREESRB_NUM; - splx(s); - xpt_done(pccb); + bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); + bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); + } + ARCMSR_LOCK_ACQUIRE(&acb->workingQ_done_lock); + if(stand_flag==1) { + atomic_subtract_int(&acb->srboutstandingcount, 1); + } + srb->startdone=ARCMSR_SRB_DONE; + srb->srb_flags=0; + acb->srbworkingQ[acb->workingsrb_doneindex]=srb; + acb->workingsrb_doneindex++; + acb->workingsrb_doneindex %= ARCMSR_MAX_FREESRB_NUM; + ARCMSR_LOCK_RELEASE(&acb->workingQ_done_lock); + xpt_done(pccb); return; } /* ********************************************************************** -** if scsi error do auto request sense ********************************************************************** */ -VOID arcmsr_report_SenseInfoBuffer(PSRB pSRB) -{ - union ccb *pccb=pSRB->pccb; - PSENSE_DATA psenseBuffer=(PSENSE_DATA)&pccb->csio.sense_data; - #if ARCMSR_DEBUG0 - printf("arcmsr_report_SenseInfoBuffer...........\n"); - #endif - - pccb->ccb_h.status|=CAM_REQ_CMP; - if(psenseBuffer) - { - memset(psenseBuffer, 0, sizeof(pccb->csio.sense_data)); - memcpy(psenseBuffer,pSRB->arcmsr_cdb.SenseData,get_min(sizeof(struct _SENSE_DATA),sizeof(pccb->csio.sense_data))); - psenseBuffer->ErrorCode=0x70; - psenseBuffer->Valid=1; - pccb->ccb_h.status|=CAM_AUTOSNS_VALID; - } - return; -} -/* -********************************************************************* -** to insert pSRB into tail of pACB wait exec srbQ -********************************************************************* -*/ -VOID arcmsr_queue_wait2go_srb(PACB pACB,PSRB pSRB) +static void arcmsr_report_sense_info(struct CommandControlBlock *srb) { - ULONG s; - LONG i=0; - #if ARCMSR_DEBUG0 - printf("arcmsr_qtail_wait2go_srb:......................................... \n"); - #endif - - s=splcam(); - while(1) - { - if(pACB->psrbwait2go[i]==NULL) - { - pACB->psrbwait2go[i]=pSRB; - atomic_add_int(&pACB->srbwait2gocount,1); - splx(s); - return; - } - i++; - i%=ARCMSR_MAX_OUTSTANDING_CMD; + 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) { + memset(&pccb->csio.sense_data, 0, sizeof(pccb->csio.sense_data)); + memcpy(&pccb->csio.sense_data, srb->arcmsr_cdb.SenseData, + get_min(sizeof(struct SENSE_DATA), sizeof(pccb->csio.sense_data))); + ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); /* Valid,ErrorCode */ + pccb->ccb_h.status |= CAM_AUTOSNS_VALID; } return; } @@ -666,164 +449,126 @@ VOID arcmsr_queue_wait2go_srb(PACB pACB,PSRB pSRB) ** ********************************************************************* */ -VOID arcmsr_abort_allcmd(PACB pACB) +static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) { - CHIP_REG_WRITE32(&pACB->pmu->inbound_msgaddr0,ARCMSR_INBOUND_MESG0_ABORT_CMD); + 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); + } return; } - /* **************************************************************************** -** Routine Description: Reset 80331 iop. -** Arguments: -** Return Value: Nothing. **************************************************************************** */ -VOID arcmsr_iop_reset(PACB pACB) +static void arcmsr_iop_reset(struct AdapterControlBlock *acb) { - PSRB pSRB,pfreesrb; - ULONG intmask_org,mask; - LONG i=0; + struct CommandControlBlock *srb; + u_int32_t intmask_org, mask; + u_int32_t i=0; - #if ARCMSR_DEBUG0 - printf("arcmsr_iop_reset: reset iop controller......................................\n"); - #endif - if(pACB->srboutstandingcount!=0) + if(acb->srboutstandingcount!=0) { - /* Q back all outstanding srb into wait exec psrb Q*/ - #if ARCMSR_DEBUG0 - printf("arcmsr_iop_reset: srboutstandingcount=%d ...\n",pACB->srboutstandingcount); - #endif - /* disable all outbound interrupt */ - intmask_org=CHIP_REG_READ32(&pACB->pmu->outbound_intmask); - CHIP_REG_WRITE32(&pACB->pmu->outbound_intmask,intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); - /* talk to iop 331 outstanding command aborted*/ - arcmsr_abort_allcmd(pACB); - if(arcmsr_wait_msgint_ready(pACB)!=TRUE) - { - printf("arcmsr_iop_reset: wait 'abort all outstanding command' timeout.................in \n"); - } + /* 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;i<ARCMSR_MAX_OUTSTANDING_CMD;i++) - { - CHIP_REG_READ32(&pACB->pmu->outbound_queueport); + for(i=0;i<ARCMSR_MAX_OUTSTANDING_CMD;i++) { + CHIP_REG_READ32(outbound_queueport); } - pfreesrb=pACB->pfreesrb; - for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) - { - pSRB=&pfreesrb[i]; - if(pSRB->startdone==ARCMSR_SRB_START) - { - pSRB->startdone=ARCMSR_SRB_ABORTED; - pSRB->pccb->ccb_h.status=CAM_REQ_ABORTED; - arcmsr_srb_complete(pSRB); + for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { + srb=acb->psrb_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); } } /* enable all outbound interrupt */ - mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE); - CHIP_REG_WRITE32(&pACB->pmu->outbound_intmask,intmask_org & mask); - atomic_set_int(&pACB->srboutstandingcount,0); + 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 */ } - i=0; - while(pACB->srbwait2gocount > 0) - { - pSRB=pACB->psrbwait2go[i]; - if(pSRB!=NULL) - { - #if ARCMSR_DEBUG0 - printf("arcmsr_iop_reset:abort command... srbwait2gocount=%d ...\n",pACB->srbwait2gocount); - #endif - pACB->psrbwait2go[i]=NULL; - pSRB->startdone=ARCMSR_SRB_ABORTED; - pSRB->pccb->ccb_h.status=CAM_REQ_ABORTED; - arcmsr_srb_complete(pSRB); - atomic_subtract_int(&pACB->srbwait2gocount,1); - } - i++; - i%=ARCMSR_MAX_OUTSTANDING_CMD; - } + atomic_set_int(&acb->srboutstandingcount, 0); + acb->workingsrb_doneindex=0; + acb->workingsrb_startindex=0; return; } /* ********************************************************************** -** -** PAGE_SIZE=4096 or 8192,PAGE_SHIFT=12 ********************************************************************** */ -VOID arcmsr_build_srb(PSRB pSRB, bus_dma_segment_t *dm_segs, LONG nseg) +static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t *dm_segs, u_int32_t nseg) { - PARCMSR_CDB pARCMSR_CDB=&pSRB->arcmsr_cdb; - PCHAR psge=(PCHAR)&pARCMSR_CDB->u; - ULONG address_lo,address_hi; - union ccb *pccb=pSRB->pccb; - struct ccb_scsiio *pcsio=&pccb->csio; - LONG arccdbsize=0x30; - - #if ARCMSR_DEBUG0 - printf("arcmsr_build_srb........................... \n"); - #endif - memset(pARCMSR_CDB,0,sizeof(struct _ARCMSR_CDB)); - pARCMSR_CDB->Bus=0; - pARCMSR_CDB->TargetID=pccb->ccb_h.target_id; - pARCMSR_CDB->LUN=pccb->ccb_h.target_lun; - pARCMSR_CDB->Function=1; - pARCMSR_CDB->CdbLength=(UCHAR)pcsio->cdb_len; - pARCMSR_CDB->Context=(CPT2INT)pARCMSR_CDB; - bcopy(pcsio->cdb_io.cdb_bytes, pARCMSR_CDB->Cdb, pcsio->cdb_len); - if(nseg != 0) - { - PACB pACB=pSRB->pACB; - bus_dmasync_op_t op; - LONG length,i,cdb_sgcount=0; - - /* map stor port SG list to our iop SG List.*/ - for(i=0;i<nseg;i++) - { + struct ARCMSR_CDB * arcmsr_cdb= &srb->arcmsr_cdb; + u_int8_t * psge=(u_int8_t *)&arcmsr_cdb->u; + u_int32_t address_lo, address_hi; + 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; + 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 { + op=BUS_DMASYNC_PREWRITE; + arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_WRITE; + srb->srb_flags|=SRB_FLAG_WRITE; + } + bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); + for(i=0;i<nseg;i++) { /* Get the physical address of the current data pointer */ - length=(ULONG) dm_segs[i].ds_len; - address_lo=dma_addr_lo32(dm_segs[i].ds_addr); - address_hi=dma_addr_hi32(dm_segs[i].ds_addr); - if(address_hi==0) - { - PSG32ENTRY pdma_sg=(PSG32ENTRY)psge; + length=arcmsr_htole32(dm_segs[i].ds_len); + address_lo=arcmsr_htole32(dma_addr_lo32(dm_segs[i].ds_addr)); + address_hi=arcmsr_htole32(dma_addr_hi32(dm_segs[i].ds_addr)); + if(address_hi==0) { + struct SG32ENTRY * pdma_sg=(struct SG32ENTRY *)psge; pdma_sg->address=address_lo; pdma_sg->length=length; - psge += sizeof(SG32ENTRY); - arccdbsize += sizeof(SG32ENTRY); - } - else - { - LONG sg64s_size=0,tmplength=length; + psge += sizeof(struct SG32ENTRY); + arccdbsize += sizeof(struct SG32ENTRY); + } else { + u_int32_t sg64s_size=0, tmplength=length; - #if ARCMSR_DEBUG0 - printf("arcmsr_build_srb: !!!!!!!!!!!......address_hi=%x.... \n",address_hi); - #endif - while(1) - { - LONG64 span4G,length0; - PSG64ENTRY pdma_sg=(PSG64ENTRY)psge; + while(1) { + u_int64_t span4G, length0; + struct SG64ENTRY * pdma_sg=(struct SG64ENTRY *)psge; - span4G=(LONG64)address_lo + tmplength; + span4G=(u_int64_t)address_lo + tmplength; pdma_sg->addresshigh=address_hi; pdma_sg->address=address_lo; - if(span4G > 0x100000000) - { + if(span4G > 0x100000000) { /*see if cross 4G boundary*/ length0=0x100000000-address_lo; - pdma_sg->length=(ULONG)length0|IS_SG64_ADDR; + pdma_sg->length=(u_int32_t)length0|IS_SG64_ADDR; address_hi=address_hi+1; address_lo=0; - tmplength=tmplength-(LONG)length0; - sg64s_size += sizeof(SG64ENTRY); - psge += sizeof(SG64ENTRY); + tmplength=tmplength-(u_int32_t)length0; + sg64s_size += sizeof(struct SG64ENTRY); + psge += sizeof(struct SG64ENTRY); cdb_sgcount++; - } - else - { - pdma_sg->length=tmplength|IS_SG64_ADDR; - sg64s_size += sizeof(SG64ENTRY); - psge += sizeof(SG64ENTRY); + } else { + pdma_sg->length=tmplength|IS_SG64_ADDR; + sg64s_size += sizeof(struct SG64ENTRY); + psge += sizeof(struct SG64ENTRY); break; } } @@ -831,1157 +576,1020 @@ VOID arcmsr_build_srb(PSRB pSRB, bus_dma_segment_t *dm_segs, LONG nseg) } cdb_sgcount++; } - pARCMSR_CDB->sgcount=(UCHAR)cdb_sgcount; - pARCMSR_CDB->DataLength=pcsio->dxfer_len; - if( arccdbsize > 256) - { - pARCMSR_CDB->Flags|=ARCMSR_CDB_FLAG_SGL_BSIZE; + arcmsr_cdb->sgcount=(u_int8_t)cdb_sgcount; + arcmsr_cdb->DataLength=pcsio->dxfer_len; + if( arccdbsize > 256) { + arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_SGL_BSIZE; } - if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) - { - op=BUS_DMASYNC_PREREAD; - } - else - { - op=BUS_DMASYNC_PREWRITE; - pARCMSR_CDB->Flags|=ARCMSR_CDB_FLAG_WRITE; - pSRB->srb_flags|=SRB_FLAG_WRITE; - } - bus_dmamap_sync(pACB->buffer_dmat, pSRB->dmamap, op); } - #if ARCMSR_DEBUG0 - printf("arcmsr_build_srb: pSRB=%p cmd=%x xferlength=%d arccdbsize=%d sgcount=%d\n",pSRB,pcsio->cdb_io.cdb_bytes[0],pARCMSR_CDB->DataLength,arccdbsize,pARCMSR_CDB->sgcount); - #endif return; } /* ************************************************************************** -** -** arcmsr_post_srb - Send a protocol specific ARC send postcard to a AIOC . -** handle: Handle of registered ARC protocol driver -** adapter_id: AIOC unique identifier(integer) -** pPOSTCARD_SEND: Pointer to ARC send postcard -** -** This routine posts a ARC send postcard to the request post FIFO of a -** specific ARC adapter. -** ************************************************************************** */ -static VOID arcmsr_post_srb(PACB pACB,PSRB pSRB) +static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandControlBlock *srb) { - ULONG cdb_shifted_phyaddr=(ULONG) pSRB->cdb_shifted_phyaddr; - PARCMSR_CDB pARCMSR_CDB=(PARCMSR_CDB)&pSRB->arcmsr_cdb; - - #if ARCMSR_DEBUG0 - printf("arcmsr_post_srb: pSRB=%p cdb_shifted_phyaddr=%x\n",pSRB,cdb_shifted_phyaddr); - #endif - atomic_add_int(&pACB->srboutstandingcount,1); - pSRB->startdone=ARCMSR_SRB_START; - if(pARCMSR_CDB->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) - { - CHIP_REG_WRITE32(&pACB->pmu->inbound_queueport,cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE); - } - else - { - CHIP_REG_WRITE32(&pACB->pmu->inbound_queueport,cdb_shifted_phyaddr); + 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); } return; } /* -************************************************************************** -** -** -************************************************************************** -*/ -VOID arcmsr_post_wait2go_srb(PACB pACB) -{ - ULONG s; - PSRB pSRB; - LONG i=0; - #if ARCMSR_DEBUG0 - printf("arcmsr_post_wait2go_srb:srbwait2gocount=%d srboutstandingcount=%d\n",pACB->srbwait2gocount,pACB->srboutstandingcount); - #endif - s=splcam(); - while((pACB->srbwait2gocount > 0) && (pACB->srboutstandingcount < ARCMSR_MAX_OUTSTANDING_CMD)) - { - pSRB=pACB->psrbwait2go[i]; - if(pSRB!=NULL) - { - pACB->psrbwait2go[i]=NULL; - arcmsr_post_srb(pACB,pSRB); - atomic_subtract_int(&pACB->srbwait2gocount,1); - } - i++; - i%=ARCMSR_MAX_OUTSTANDING_CMD; - } - splx(s); - return; -} -/* ********************************************************************** -** Function: arcmsr_post_Qbuffer -** Output: ********************************************************************** */ -VOID arcmsr_post_Qbuffer(PACB pACB) +static void arcmsr_post_Qbuffer(struct AdapterControlBlock *acb) { - ULONG s; - PUCHAR pQbuffer; - PQBUFFER pwbuffer=(PQBUFFER)&pACB->pmu->ioctl_wbuffer; - PUCHAR iop_data=(PUCHAR)pwbuffer->data; - LONG allxfer_len=0; - - s=splcam(); - while((pACB->wqbuf_firstindex!=pACB->wqbuf_lastindex) && (allxfer_len<124)) - { - pQbuffer=&pACB->wqbuffer[pACB->wqbuf_firstindex]; - memcpy(iop_data,pQbuffer,1); - pACB->wqbuf_firstindex++; - pACB->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 and wait reply at hwinterrupt routine for next Qbuffer post - */ - CHIP_REG_WRITE32(&pACB->pmu->inbound_doorbell,ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK); - splx(s); + 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]; + 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 and wait reply at hwinterrupt routine for next Qbuffer post + */ + CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK); + } return; } /* ************************************************************************ -** -** ************************************************************************ */ -VOID arcmsr_stop_adapter_bgrb(PACB pACB) +static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) { - #if ARCMSR_DEBUG0 - printf("arcmsr_stop_adapter_bgrb..............\n"); - #endif - pACB->acb_flags |= ACB_F_MSG_STOP_BGRB; - pACB->acb_flags &= ~ACB_F_MSG_START_BGRB; - CHIP_REG_WRITE32(&pACB->pmu->inbound_msgaddr0,ARCMSR_INBOUND_MESG0_STOP_BGRB); + acb->acb_flags &= ~ACB_F_MSG_START_BGRB; + CHIP_REG_WRITE32(inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); + if(arcmsr_wait_msgint_ready(acb)) { + printf("arcmsr%d: wait 'stop adapter rebulid' timeout \n" + , acb->pci_unit); + } return; } /* ************************************************************************ -** -** ************************************************************************ */ -static VOID arcmsr_poll(struct cam_sim * psim) +static void arcmsr_poll(struct cam_sim * psim) { arcmsr_interrupt(cam_sim_softc(psim)); return; } /* ********************************************************************** -** Function: arcmsr_interrupt -** Output: VOID -** CAM Status field values -**typedef enum { -** CAM_REQ_INPROG, CCB request is in progress -** CAM_REQ_CMP, CCB request completed without error -** CAM_REQ_ABORTED, CCB request aborted by the host -** CAM_UA_ABORT, Unable to abort CCB request -** CAM_REQ_CMP_ERR, CCB request completed with an error -** CAM_BUSY, CAM subsytem is busy -** CAM_REQ_INVALID, CCB request was invalid -** CAM_PATH_INVALID, Supplied Path ID is invalid -** CAM_DEV_NOT_THERE, SCSI Device Not Installed/there -** CAM_UA_TERMIO, Unable to terminate I/O CCB request -** CAM_SEL_TIMEOUT, Target Selection Timeout -** CAM_CMD_TIMEOUT, Command timeout -** CAM_SCSI_STATUS_ERROR, SCSI error, look at error code in CCB -** CAM_MSG_REJECT_REC, Message Reject Received -** CAM_SCSI_BUS_RESET, SCSI Bus Reset Sent/Received -** CAM_UNCOR_PARITY, Uncorrectable parity error occurred -** CAM_AUTOSENSE_FAIL=0x10, Autosense: request sense cmd fail -** CAM_NO_HBA, No HBA Detected error -** CAM_DATA_RUN_ERR, Data Overrun error -** CAM_UNEXP_BUSFREE, Unexpected Bus Free -** CAM_SEQUENCE_FAIL, Target Bus Phase Sequence Failure -** CAM_CCB_LEN_ERR, CCB length supplied is inadequate -** CAM_PROVIDE_FAIL, Unable to provide requested capability -** CAM_BDR_SENT, A SCSI BDR msg was sent to target -** CAM_REQ_TERMIO, CCB request terminated by the host -** CAM_UNREC_HBA_ERROR, Unrecoverable Host Bus Adapter Error -** CAM_REQ_TOO_BIG, The request was too large for this host -** CAM_REQUEUE_REQ, -** * This request should be requeued to preserve -** * transaction ordering. This typically occurs -** * when the SIM recognizes an error that should -** * freeze the queue and must place additional -** * requests for the target at the sim level -** * back into the XPT queue. -** -** CAM_IDE=0x33, Initiator Detected Error -** CAM_RESRC_UNAVAIL, Resource Unavailable -** CAM_UNACKED_EVENT, Unacknowledged Event by Host -** CAM_MESSAGE_RECV, Message Received in Host Target Mode -** CAM_INVALID_CDB, Invalid CDB received in Host Target Mode -** CAM_LUN_INVALID, Lun supplied is invalid -** CAM_TID_INVALID, Target ID supplied is invalid -** CAM_FUNC_NOTAVAIL, The requested function is not available -** CAM_NO_NEXUS, Nexus is not established -** CAM_IID_INVALID, The initiator ID is invalid -** CAM_CDB_RECVD, The SCSI CDB has been received -** CAM_LUN_ALRDY_ENA, The LUN is already eanbeld for target mode -** CAM_SCSI_BUSY, SCSI Bus Busy -** -** CAM_DEV_QFRZN=0x40, The DEV queue is frozen w/this err -** -** Autosense data valid for target -** CAM_AUTOSNS_VALID=0x80, -** CAM_RELEASE_SIMQ=0x100, SIM ready to take more commands -** CAM_SIM_QUEUED =0x200, SIM has this command in it's queue -** -** CAM_STATUS_MASK=0x3F, Mask bits for just the status # -** -** Target Specific Adjunct Status -** CAM_SENT_SENSE=0x40000000 sent sense with status -**} cam_status; ********************************************************************** */ -static VOID arcmsr_interrupt(VOID *arg) +static void arcmsr_interrupt(void *arg) { - PACB pACB=(PACB)arg; - PSRB pSRB; - ULONG flagpsrb,outbound_intstatus,outbound_doorbell; + struct AdapterControlBlock *acb=(struct AdapterControlBlock *)arg; + struct CommandControlBlock *srb; + u_int32_t flag_srb, outbound_intstatus, outbound_doorbell; - #if ARCMSR_DEBUG0 - printf("arcmsr_interrupt..............\n"); - #endif /* ********************************************* - ** check outbound intstatus À˹µL¶l®t«öªù¹a + ** check outbound intstatus ********************************************* */ - outbound_intstatus=CHIP_REG_READ32(&pACB->pmu->outbound_intstatus) & pACB->outbound_int_enable; - CHIP_REG_WRITE32(&pACB->pmu->outbound_intstatus, outbound_intstatus);/*clear interrupt*/ - if(outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) - { - #if ARCMSR_DEBUG0 - printf("arcmsr_interrupt:..........ARCMSR_MU_OUTBOUND_DOORBELL_INT\n"); - #endif + outbound_intstatus=CHIP_REG_READ32(outbound_intstatus) & acb->outbound_int_enable; + CHIP_REG_WRITE32(outbound_intstatus, outbound_intstatus);/*clear interrupt*/ + if(outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) { /* ********************************************* - ** DOORBELL ¥m¾´! ¬O§_¦³¶l¥ónñ¦¬ + ** DOORBELL ********************************************* */ - outbound_doorbell=CHIP_REG_READ32(&pACB->pmu->outbound_doorbell); - CHIP_REG_WRITE32(&pACB->pmu->outbound_doorbell,outbound_doorbell);/*clear interrupt */ - if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) - { - PQBUFFER prbuffer=(PQBUFFER)&pACB->pmu->ioctl_rbuffer; - PUCHAR iop_data=(PUCHAR)prbuffer->data; - PUCHAR pQbuffer; - LONG my_empty_len,iop_len,rqbuf_firstindex,rqbuf_lastindex; - ULONG s; - /*check this iop data if overflow my rqbuffer*/ - s=splcam(); - rqbuf_lastindex=pACB->rqbuf_lastindex; - rqbuf_firstindex=pACB->rqbuf_firstindex; + 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=&pACB->rqbuffer[pACB->rqbuf_lastindex]; - memcpy(pQbuffer,iop_data,1); - pACB->rqbuf_lastindex++; - pACB->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;/*if last index number set it to 0 */ + 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(&pACB->pmu->inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);/*signature, let IOP331 know data has been readed */ - } - else - { - pACB->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 */ + } else { + acb->acb_flags|=ACB_F_IOPDATA_OVERFLOW; } - splx(s); } - if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) - { - ULONG s; + if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { + acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED; /* ********************************************* - ** ¬Ý¬Ý¬O§_ÁÙ¦³¶l¥ón¶¶¹D±H¥X ********************************************* */ - s=splcam(); - if(pACB->wqbuf_firstindex!=pACB->wqbuf_lastindex) - { - PUCHAR pQbuffer; - PQBUFFER pwbuffer=(PQBUFFER)&pACB->pmu->ioctl_wbuffer; - PUCHAR iop_data=(PUCHAR)pwbuffer->data; - LONG allxfer_len=0; - - while((pACB->wqbuf_firstindex!=pACB->wqbuf_lastindex) && (allxfer_len<124)) - { - pQbuffer=&pACB->wqbuffer[pACB->wqbuf_firstindex]; - memcpy(iop_data,pQbuffer,1); - pACB->wqbuf_firstindex++; - pACB->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */ + 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 + ** push inbound doorbell tell iop driver data write ok + ** and wait reply on next hwinterrupt for next Qbuffer post */ - CHIP_REG_WRITE32(&pACB->pmu->inbound_doorbell,ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK); + CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK); } - else - { - pACB->acb_flags |= ACB_F_IOCTL_WQBUFFER_CLEARED; + if(acb->wqbuf_firstindex==acb->wqbuf_lastindex) { + acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; } - splx(s); } } - if(outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) - { + if(outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { + int target, lun; /* ***************************************************************************** ** areca cdb command done ***************************************************************************** */ - while(1) - { - if((flagpsrb=CHIP_REG_READ32(&pACB->pmu->outbound_queueport)) == 0xFFFFFFFF) - { + 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*/ - pSRB=(PSRB)(CINT2P)(pACB->vir2phy_offset+(flagpsrb << 5));/*frame must be 32 bytes aligned*/ - if((pSRB->pACB!=pACB) || (pSRB->startdone!=ARCMSR_SRB_START)) - { - if(pSRB->startdone==ARCMSR_SRB_ABORTED) - { - pSRB->pccb->ccb_h.status=CAM_REQ_ABORTED; - arcmsr_srb_complete(pSRB); - break; + 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_interrupt:got an illegal srb command done ...pACB=%p pSRB=%p srboutstandingcount=%d .....\n",pACB,pSRB,pACB->srboutstandingcount); - break; + 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; } - if((flagpsrb & ARCMSR_SRBREPLY_FLAG_ERROR)==0) - { - pSRB->pccb->ccb_h.status=CAM_REQ_CMP; - arcmsr_srb_complete(pSRB); - } - else - { - switch(pSRB->arcmsr_cdb.DeviceStatus) - { - case ARCMSR_DEV_SELECT_TIMEOUT: - { - #if ARCMSR_DEBUG0 - printf("pSRB=%p ......ARCMSR_DEV_SELECT_TIMEOUT\n",pSRB); - #endif - pSRB->pccb->ccb_h.status=CAM_SEL_TIMEOUT; - arcmsr_srb_complete(pSRB); + 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: - { - #if ARCMSR_DEBUG0 - printf("pSRB=%p ......ARCMSR_DEV_ABORTED\n",pSRB); - #endif - pSRB->pccb->ccb_h.status=CAM_DEV_NOT_THERE; - arcmsr_srb_complete(pSRB); - } - break; - case ARCMSR_DEV_INIT_FAIL: - { - #if ARCMSR_DEBUG0 - printf("pSRB=%p .....ARCMSR_DEV_INIT_FAIL\n",pSRB); - #endif - pSRB->pccb->ccb_h.status=CAM_DEV_NOT_THERE; - arcmsr_srb_complete(pSRB); + 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: - { - #if ARCMSR_DEBUG0 - printf("pSRB=%p .....SCSISTAT_CHECK_CONDITION\n",pSRB); - #endif - arcmsr_report_SenseInfoBuffer(pSRB); - arcmsr_srb_complete(pSRB); + case SCSISTAT_CHECK_CONDITION: { + acb->devstate[target][lun]=ARECA_RAID_GOOD; + arcmsr_report_sense_info(srb); + arcmsr_srb_complete(srb, 1); } break; default: - /* error occur Q all error srb to errorsrbpending Q*/ - printf("arcmsr_interrupt:command error done ......but got unknow DeviceStatus=%x....\n",pSRB->arcmsr_cdb.DeviceStatus); - pSRB->pccb->ccb_h.status=CAM_UNCOR_PARITY;/*unknow error or crc error just for retry*/ - arcmsr_srb_complete(pSRB); + 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*/ } - if(pACB->srbwait2gocount != 0) - { - arcmsr_post_wait2go_srb(pACB);/*try to post all pending srb*/ - } - return; + return; } /* -*********************************************************************** +******************************************************************************* ** -**int copyin __P((const void *udaddr, void *kaddr, size_t len)); -**int copyout __P((const void *kaddr, void *udaddr, size_t len)); +******************************************************************************* +*/ +static void arcmsr_iop_parking(struct AdapterControlBlock *acb) +{ + if(acb!=NULL) { + /* stop adapter background rebuild */ + if(acb->acb_flags & ACB_F_MSG_START_BGRB) { + arcmsr_stop_adapter_bgrb(acb); + arcmsr_flush_adapter_cache(acb); + } + } +} +/* +*********************************************************************** ** -**ENOENT "" No such file or directory "" -**ENOIOCTL "" ioctl not handled by this layer "" -**ENOMEM "" Cannot allocate memory "" -**EINVAL "" Invalid argument "" ************************************************************************ */ -LONG arcmsr_iop_ioctlcmd(PACB pACB,ULONG ioctl_cmd,caddr_t arg) +u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg) { - PCMD_IO_CONTROL pccbioctl=(PCMD_IO_CONTROL) arg; - - #if ARCMSR_DEBUG0 - printf("arcmsr_iop_ioctlcmd................. \n"); - #endif + struct CMD_MESSAGE_FIELD * pcmdmessagefld; + u_int32_t retvalue=EINVAL; - if(memcmp(pccbioctl->Signature,"ARCMSR",6)!=0) - { - return EINVAL; + pcmdmessagefld=(struct CMD_MESSAGE_FIELD *) arg; + if(memcmp(pcmdmessagefld->cmdmessage.Signature, "ARCMSR", 6)!=0) { + return retvalue; } - switch(ioctl_cmd) - { - case ARCMSR_IOCTL_READ_RQBUFFER: - { - ULONG s; - PCMD_IOCTL_FIELD pccbioctlfld=(PCMD_IOCTL_FIELD)arg; - PUCHAR pQbuffer,ptmpQbuffer=pccbioctlfld->ioctldatabuffer; - LONG allxfer_len=0; - - s=splcam(); - while((pACB->rqbuf_firstindex!=pACB->rqbuf_lastindex) && (allxfer_len<1031)) - { + ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); + switch(ioctl_cmd) { + case ARCMSR_MESSAGE_READ_RQBUFFER: { + 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)) { /*copy READ QBUFFER to srb*/ - pQbuffer=&pACB->rqbuffer[pACB->rqbuf_firstindex]; - memcpy(ptmpQbuffer,pQbuffer,1); - pACB->rqbuf_firstindex++; - pACB->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */ + pQbuffer= &acb->rqbuffer[acb->rqbuf_firstindex]; + memcpy(ptmpQbuffer, pQbuffer, 1); + acb->rqbuf_firstindex++; + acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; + /*if last index number set it to 0 */ ptmpQbuffer++; allxfer_len++; } - if(pACB->acb_flags & ACB_F_IOPDATA_OVERFLOW) - { - PQBUFFER prbuffer=(PQBUFFER)&pACB->pmu->ioctl_rbuffer; - PUCHAR pQbuffer; - PUCHAR iop_data=(PUCHAR)prbuffer->data; - LONG iop_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; + u_int32_t iop_len; - pACB->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; - iop_len=(LONG)prbuffer->data_len; + acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; + 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) - { - pQbuffer=&pACB->rqbuffer[pACB->rqbuf_lastindex]; - memcpy(pQbuffer,iop_data,1); - pACB->rqbuf_lastindex++; - pACB->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;/*if last index number set it to 0 */ + 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(&pACB->pmu->inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);/*signature, let IOP331 know data has been readed */ + CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); + /*signature, let IOP331 know data has been readed */ } - pccbioctl->Length=allxfer_len; - pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_OK; - splx(s); - return ARC_IOCTL_SUCCESS; + pcmdmessagefld->cmdmessage.Length=allxfer_len; + pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; + retvalue=ARCMSR_MESSAGE_SUCCESS; } break; - case ARCMSR_IOCTL_WRITE_WQBUFFER: - { - ULONG s; - PCMD_IOCTL_FIELD pccbioctlfld=(PCMD_IOCTL_FIELD)arg; - LONG my_empty_len,user_len,wqbuf_firstindex,wqbuf_lastindex; - PUCHAR pQbuffer,ptmpuserbuffer=pccbioctlfld->ioctldatabuffer; - - s=splcam(); - user_len=pccbioctl->Length; - - /*check if data xfer length of this request will overflow my array qbuffer */ - wqbuf_lastindex=pACB->wqbuf_lastindex; - wqbuf_firstindex=pACB->wqbuf_firstindex; - my_empty_len=(wqbuf_firstindex-wqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1); - if(my_empty_len>=user_len) - { - while(user_len>0) - { - /*copy srb data to wqbuffer*/ - pQbuffer=&pACB->wqbuffer[pACB->wqbuf_lastindex]; - memcpy(pQbuffer,ptmpuserbuffer,1); - pACB->wqbuf_lastindex++; - pACB->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER;/*if last index number set it to 0 */ - ptmpuserbuffer++; - user_len--; - } - /*post fist Qbuffer*/ - if(pACB->acb_flags & ACB_F_IOCTL_WQBUFFER_CLEARED) - { - pACB->acb_flags &=~ACB_F_IOCTL_WQBUFFER_CLEARED; - arcmsr_post_Qbuffer(pACB); + 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); + pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; + } else { + my_empty_len=(wqbuf_firstindex-wqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1); + if(my_empty_len>=user_len) { + while(user_len>0) { + /*copy srb data to wqbuffer*/ + pQbuffer= &acb->wqbuffer[acb->wqbuf_lastindex]; + memcpy(pQbuffer, ptmpuserbuffer, 1); + acb->wqbuf_lastindex++; + acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; + /*if last index number set it to 0 */ + 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); + } + pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; + } else { + pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; } - pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_OK; - } - else - { - pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_ERROR; } - splx(s); - return ARC_IOCTL_SUCCESS; + retvalue=ARCMSR_MESSAGE_SUCCESS; } break; - case ARCMSR_IOCTL_CLEAR_RQBUFFER: - { - ULONG s; - PUCHAR pQbuffer=pACB->rqbuffer; - s=splcam(); - if(pACB->acb_flags & ACB_F_IOPDATA_OVERFLOW) - { - pACB->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; - CHIP_REG_WRITE32(&pACB->pmu->inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);/*signature, let IOP331 know data has been readed */ + 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 */ } - pACB->acb_flags |= ACB_F_IOCTL_RQBUFFER_CLEARED; - pACB->rqbuf_firstindex=0; - pACB->rqbuf_lastindex=0; - memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); - pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_OK; - splx(s); - return ARC_IOCTL_SUCCESS; + acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; + acb->rqbuf_firstindex=0; + acb->rqbuf_lastindex=0; + memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); + pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; + retvalue=ARCMSR_MESSAGE_SUCCESS; } break; - case ARCMSR_IOCTL_CLEAR_WQBUFFER: + case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { - ULONG s; - PUCHAR pQbuffer=pACB->wqbuffer; + u_int8_t * pQbuffer=acb->wqbuffer; - s=splcam(); - if(pACB->acb_flags & ACB_F_IOPDATA_OVERFLOW) - { - pACB->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; - CHIP_REG_WRITE32(&pACB->pmu->inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);/*signature, let IOP331 know data has been readed */ + 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 */ } - pACB->acb_flags |= ACB_F_IOCTL_WQBUFFER_CLEARED; - pACB->wqbuf_firstindex=0; - pACB->wqbuf_lastindex=0; - memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); - pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_OK; - splx(s); - return ARC_IOCTL_SUCCESS; + acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READED); + acb->wqbuf_firstindex=0; + acb->wqbuf_lastindex=0; + memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); + pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; + retvalue=ARCMSR_MESSAGE_SUCCESS; } break; - case ARCMSR_IOCTL_CLEAR_ALLQBUFFER: - { - ULONG s; - PUCHAR pQbuffer; + case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { + u_int8_t * pQbuffer; - s=splcam(); - if(pACB->acb_flags & ACB_F_IOPDATA_OVERFLOW) - { - pACB->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; - CHIP_REG_WRITE32(&pACB->pmu->inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);/*signature, let IOP331 know data has been readed */ + 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 */ } - pACB->acb_flags |= (ACB_F_IOCTL_WQBUFFER_CLEARED|ACB_F_IOCTL_RQBUFFER_CLEARED); - pACB->rqbuf_firstindex=0; - pACB->rqbuf_lastindex=0; - pACB->wqbuf_firstindex=0; - pACB->wqbuf_lastindex=0; - pQbuffer=pACB->rqbuffer; - memset(pQbuffer, 0, sizeof(struct _QBUFFER)); - pQbuffer=pACB->wqbuffer; - memset(pQbuffer, 0, sizeof(struct _QBUFFER)); - pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_OK; - splx(s); - return ARC_IOCTL_SUCCESS; + acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED + |ACB_F_MESSAGE_RQBUFFER_CLEARED + |ACB_F_MESSAGE_WQBUFFER_READED); + acb->rqbuf_firstindex=0; + acb->rqbuf_lastindex=0; + acb->wqbuf_firstindex=0; + acb->wqbuf_lastindex=0; + pQbuffer=acb->rqbuffer; + memset(pQbuffer, 0, sizeof(struct QBUFFER)); + pQbuffer=acb->wqbuffer; + memset(pQbuffer, 0, sizeof(struct QBUFFER)); + pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; + retvalue=ARCMSR_MESSAGE_SUCCESS; } break; - case ARCMSR_IOCTL_RETURN_CODE_3F: - { - pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_3F; - return ARC_IOCTL_SUCCESS; + case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { + pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_3F; + retvalue=ARCMSR_MESSAGE_SUCCESS; } break; - case ARCMSR_IOCTL_SAY_HELLO: - { - PCMD_IOCTL_FIELD pccbioctlfld=(PCMD_IOCTL_FIELD)arg; - PCHAR hello_string="Hello! I am ARCMSR"; - PCHAR puserbuffer=(PUCHAR)pccbioctlfld->ioctldatabuffer; + 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,(SHORT)strlen(hello_string))) - { - pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_ERROR; - return ENOIOCTL; + if(memcpy(puserbuffer, hello_string, (int16_t)strlen(hello_string))) { + pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; + ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); + return ENOIOCTL; } - pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_OK; - return ARC_IOCTL_SUCCESS; + pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; + retvalue=ARCMSR_MESSAGE_SUCCESS; + } + break; + case ARCMSR_MESSAGE_SAY_GOODBYE: { + arcmsr_iop_parking(acb); + retvalue=ARCMSR_MESSAGE_SUCCESS; + } + break; + case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: { + arcmsr_flush_adapter_cache(acb); + retvalue=ARCMSR_MESSAGE_SUCCESS; } break; } - return EINVAL; + ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); + return retvalue; } /* ************************************************************************** -** ************************************************************************** */ -PSRB arcmsr_get_freesrb(PACB pACB) +struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb) { - PSRB pSRB=NULL; - ULONG s; - LONG srb_startindex,srb_doneindex; - - #if ARCMSR_DEBUG0 - printf("arcmsr_get_freesrb: srb_startindex=%d srb_doneindex=%d\n",pACB->srb_startindex,pACB->srb_doneindex); - #endif - - s=splcam(); - srb_doneindex=pACB->srb_doneindex; - srb_startindex=pACB->srb_startindex; - pSRB=pACB->psrbringQ[srb_startindex]; - srb_startindex++; - srb_startindex %= ARCMSR_MAX_FREESRB_NUM; - if(srb_doneindex!=srb_startindex) - { - pACB->srb_startindex=srb_startindex; - } - else - { - pSRB=NULL; + struct CommandControlBlock *srb=NULL; + u_int32_t workingsrb_startindex, workingsrb_doneindex; + + ARCMSR_LOCK_ACQUIRE(&acb->workingQ_start_lock); + workingsrb_doneindex=acb->workingsrb_doneindex; + workingsrb_startindex=acb->workingsrb_startindex; + srb=acb->srbworkingQ[workingsrb_startindex]; + workingsrb_startindex++; + workingsrb_startindex %= ARCMSR_MAX_FREESRB_NUM; + if(workingsrb_doneindex!=workingsrb_startindex) { + acb->workingsrb_startindex=workingsrb_startindex; + } else { + srb=NULL; } - splx(s); - return(pSRB); + ARCMSR_LOCK_RELEASE(&acb->workingQ_start_lock); + return(srb); +} +/* +************************************************************************** +************************************************************************** +*/ +static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb) +{ + 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]; + /* 4 bytes: Areca io control code */ + if((pccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) { + buffer = pccb->csio.data_ptr; + transfer_len = pccb->csio.dxfer_len; + } else { + retvalue = ARCMSR_MESSAGE_FAIL; + goto message_out; + } + if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) { + retvalue = ARCMSR_MESSAGE_FAIL; + goto message_out; + } + pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer; + switch(controlcode) { + case ARCMSR_MESSAGE_READ_RQBUFFER: { + u_int8_t *pQbuffer; + u_int8_t *ptmpQbuffer=pcmdmessagefld->messagedatabuffer; + int32_t allxfer_len = 0; + + while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) + && (allxfer_len < 1031)) { + pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; + memcpy(ptmpQbuffer, pQbuffer, 1); + acb->rqbuf_firstindex++; + acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; + ptmpQbuffer++; + 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; + int32_t iop_len; + + acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; + iop_len =(u_int32_t)prbuffer->data_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; + iop_data++; + iop_len--; + } + CHIP_REG_WRITE32(inbound_doorbell, + ARCMSR_INBOUND_DRIVER_DATA_READ_OK); + } + pcmdmessagefld->cmdmessage.Length = allxfer_len; + pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; + retvalue=ARCMSR_MESSAGE_SUCCESS; + } + break; + case ARCMSR_MESSAGE_WRITE_WQBUFFER: { + 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); + /* has error report sensedata */ + if(&pccb->csio.sense_data) { + ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); + /* Valid,ErrorCode */ + ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; + /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ + ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; + /* AdditionalSenseLength */ + ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; + /* AdditionalSenseCode */ + } + retvalue = ARCMSR_MESSAGE_FAIL; + } else { + my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) + &(ARCMSR_MAX_QBUFFER - 1); + if (my_empty_len >= user_len) { + while (user_len > 0) { + pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; + memcpy(pQbuffer, ptmpuserbuffer, 1); + acb->wqbuf_lastindex++; + acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; + ptmpuserbuffer++; + user_len--; + } + if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { + acb->acb_flags &= + ~ACB_F_MESSAGE_WQBUFFER_CLEARED; + arcmsr_post_Qbuffer(acb); + } + } else { + /* has error report sensedata */ + if(&pccb->csio.sense_data) { + ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); + /* Valid,ErrorCode */ + ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; + /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ + ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; + /* AdditionalSenseLength */ + ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; + /* AdditionalSenseCode */ + } + retvalue = ARCMSR_MESSAGE_FAIL; + } + } + } + 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); + } + acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; + acb->rqbuf_firstindex = 0; + acb->rqbuf_lastindex = 0; + memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); + pcmdmessagefld->cmdmessage.ReturnCode = + ARCMSR_MESSAGE_RETURNCODE_OK; + } + break; + case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { + u_int8_t *pQbuffer = acb->wqbuffer; + + 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); + } + acb->acb_flags |= + (ACB_F_MESSAGE_WQBUFFER_CLEARED | + ACB_F_MESSAGE_WQBUFFER_READED); + acb->wqbuf_firstindex = 0; + acb->wqbuf_lastindex = 0; + memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); + pcmdmessagefld->cmdmessage.ReturnCode = + ARCMSR_MESSAGE_RETURNCODE_OK; + } + break; + case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { + u_int8_t *pQbuffer; + + 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); + } + acb->acb_flags |= + (ACB_F_MESSAGE_WQBUFFER_CLEARED + | ACB_F_MESSAGE_RQBUFFER_CLEARED + | ACB_F_MESSAGE_WQBUFFER_READED); + acb->rqbuf_firstindex = 0; + acb->rqbuf_lastindex = 0; + acb->wqbuf_firstindex = 0; + acb->wqbuf_lastindex = 0; + pQbuffer = acb->rqbuffer; + memset(pQbuffer, 0, sizeof (struct QBUFFER)); + pQbuffer = acb->wqbuffer; + memset(pQbuffer, 0, sizeof (struct QBUFFER)); + pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; + } + break; + case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { + pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; + } + break; + case ARCMSR_MESSAGE_SAY_HELLO: { + int8_t * hello_string = "Hello! I am ARCMSR"; + + memcpy(pcmdmessagefld->messagedatabuffer, hello_string + , (int16_t)strlen(hello_string)); + pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; + } + break; + case ARCMSR_MESSAGE_SAY_GOODBYE: + arcmsr_iop_parking(acb); + break; + case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: + arcmsr_flush_adapter_cache(acb); + break; + default: + retvalue = ARCMSR_MESSAGE_FAIL; + } +message_out: + return retvalue; } /* ********************************************************************* -** -** -** ********************************************************************* */ -static VOID arcmsr_executesrb(VOID *arg,bus_dma_segment_t *dm_segs,LONG nseg,LONG error) +static void arcmsr_executesrb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) { - PSRB pSRB=(PSRB)arg; - PACB pACB; - union ccb *pccb; - - #if ARCMSR_DEBUG0 - printf("arcmsr_executesrb........................................ \n" ); - #endif - - pccb=pSRB->pccb; - pACB=(PACB)pSRB->pACB; - if(error != 0) - { - if(error != EFBIG) - { - printf("arcmsr_executesrb:%d Unexepected error %x returned from " "bus_dmamap_load\n",pACB->pci_unit,error); + struct CommandControlBlock *srb=(struct CommandControlBlock *)arg; + 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" + , acb->pci_unit, error); } - if(pccb->ccb_h.status == CAM_REQ_INPROG) - { - xpt_freeze_devq(pccb->ccb_h.path,/*count*/1); - pccb->ccb_h.status=CAM_REQ_TOO_BIG|CAM_DEV_QFRZN; + if((pccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { + xpt_freeze_devq(pccb->ccb_h.path, /*count*/1); + pccb->ccb_h.status |= (CAM_REQ_TOO_BIG|CAM_DEV_QFRZN); } - xpt_done(pccb); + arcmsr_srb_complete(srb, 0); return; } - arcmsr_build_srb(pSRB,dm_segs,nseg); - if((pccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) - { - if(nseg != 0) - { - bus_dmamap_unload(pACB->buffer_dmat,pSRB->dmamap); + if(nseg > ARCMSR_MAX_SG_ENTRIES) { + pccb->ccb_h.status |= CAM_REQ_TOO_BIG; + arcmsr_srb_complete(srb, 0); + return; + } + 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); + return; + } + if(acb->devstate[target][lun]==ARECA_RAID_GONE) { + u_int8_t block_cmd; + + block_cmd=pccb->csio.cdb_io.cdb_bytes[0] & 0x0f; + if(block_cmd==0x08 || block_cmd==0x0a) { + printf("arcmsr%d:block 'read/write' command" + "with gone raid volume Cmd=%2x, TargetId=%d, Lun=%d \n" + , acb->pci_unit, block_cmd, target, lun); + pccb->ccb_h.status |= CAM_DEV_NOT_THERE; + arcmsr_srb_complete(srb, 0); + return; } - xpt_done(pccb); + } + if((pccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { + if(nseg != 0) { + bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); + } + arcmsr_srb_complete(srb, 0); return; } pccb->ccb_h.status |= CAM_SIM_QUEUED; - if(pACB->srboutstandingcount < ARCMSR_MAX_OUTSTANDING_CMD) - { - /* - ****************************************************************** - ** and we can make sure there were no pending srb in this duration - ****************************************************************** - */ - arcmsr_post_srb(pACB,pSRB); - } - else - { - /* - ****************************************************************** - ** Q of srbwaitexec will be post out when any outstanding command complete - ****************************************************************** - */ - arcmsr_queue_wait2go_srb(pACB,pSRB); + if(acb->srboutstandingcount >= ARCMSR_MAX_OUTSTANDING_CMD) { + pccb->ccb_h.status |= CAM_SCSI_BUSY; + arcmsr_srb_complete(srb, 0); + return; } + arcmsr_build_srb(srb, dm_segs, nseg); + arcmsr_post_srb(acb, srb); return; } /* ***************************************************************************************** -** ***************************************************************************************** */ -BOOLEAN arcmsr_seek_cmd2abort(union ccb * pabortccb) +static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb) { - PSRB pSRB,pfreesrb; - PACB pACB=(PACB) pabortccb->ccb_h.arcmsr_ccbacb_ptr; - ULONG s,intmask_org,mask; - LONG i=0; + struct CommandControlBlock *srb; + struct AdapterControlBlock *acb=(struct AdapterControlBlock *) abortccb->ccb_h.arcmsr_ccbacb_ptr; + u_int32_t intmask_org, mask; + int i=0; - #if ARCMSR_DEBUG0 - printf("arcmsr_seek_cmd2abort.................. \n"); - #endif - - s=splcam(); - /* + acb->num_aborts++; + /* + *************************************************************************** ** It is the upper layer do abort command this lock just prior to calling us. ** First determine if we currently own this command. ** Start by searching the device queue. If not found - ** at all,and the system wanted us to just abort the + ** at all, and the system wanted us to just abort the ** command return success. + *************************************************************************** */ - if(pACB->srboutstandingcount!=0) - { - /* Q back all outstanding srb into wait exec psrb Q*/ - pfreesrb=pACB->pfreesrb; - for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) - { - pSRB=&pfreesrb[i]; - if(pSRB->startdone==ARCMSR_SRB_START) - { - if(pSRB->pccb==pabortccb) - { - /* disable all outbound interrupt */ - intmask_org=CHIP_REG_READ32(&pACB->pmu->outbound_intmask); - CHIP_REG_WRITE32(&pACB->pmu->outbound_intmask,intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); - /* talk to iop 331 outstanding command aborted*/ - arcmsr_abort_allcmd(pACB); - if(arcmsr_wait_msgint_ready(pACB)!=TRUE) - { - printf("arcmsr_seek_cmd2abort: wait 'abort all outstanding command' timeout.................in \n"); - } - /*clear all outbound posted Q*/ - for(i=0;i<ARCMSR_MAX_OUTSTANDING_CMD;i++) - { - CHIP_REG_READ32(&pACB->pmu->outbound_queueport); - } - pfreesrb=pACB->pfreesrb; - for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) - { - pSRB=&pfreesrb[i]; - if(pSRB->startdone==ARCMSR_SRB_START) - { - pSRB->startdone=ARCMSR_SRB_ABORTED; - pSRB->pccb->ccb_h.status=CAM_REQ_ABORTED; - arcmsr_srb_complete(pSRB); - } - } - /* enable all outbound interrupt */ - mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE); - CHIP_REG_WRITE32(&pACB->pmu->outbound_intmask,intmask_org & mask); - splx(s); - return(TRUE); - } - } - } - } - /* - ** seek this command at our command list - ** if command found then remove,abort it and free this SRB - */ - if(pACB->srbwait2gocount!=0) - { - for(i=0;i<ARCMSR_MAX_OUTSTANDING_CMD;i++) - { - pSRB=pACB->psrbwait2go[i]; - if(pSRB!=NULL) - { - if(pSRB->pccb==pabortccb) - { - pACB->psrbwait2go[i]=NULL; - pSRB->startdone=ARCMSR_SRB_ABORTED; - pSRB->pccb->ccb_h.status=CAM_REQ_ABORTED; - arcmsr_srb_complete(pSRB); - atomic_subtract_int(&pACB->srbwait2gocount,1); - splx(s); - return(TRUE); + if(acb->srboutstandingcount!=0) { + for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { + srb=acb->psrb_pool[i]; + if(srb->startdone==ARCMSR_SRB_START) { + if(srb->pccb==abortccb) { + srb->startdone=ARCMSR_SRB_ABORTED; + printf("arcmsr%d:scsi id=%d lun=%d abort srb '%p'" + "outstanding command \n" + , acb->pci_unit, abortccb->ccb_h.target_id + , abortccb->ccb_h.target_lun, srb); + goto abort_outstanding_cmd; } } } } - splx(s); - return (FALSE); + 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); + 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); + return (TRUE); } /* **************************************************************************** -** **************************************************************************** */ -VOID arcmsr_bus_reset(PACB pACB) +static void arcmsr_bus_reset(struct AdapterControlBlock *acb) { - #if ARCMSR_DEBUG0 - printf("arcmsr_bus_reset.......................... \n"); - #endif - - arcmsr_iop_reset(pACB); - return; + int retry=0; + + acb->num_resets++; + acb->acb_flags |=ACB_F_BUS_RESET; + while(acb->srboutstandingcount!=0 && retry < 400) { + arcmsr_interrupt((void *)acb); + UDELAY(25000); + retry++; + } + arcmsr_iop_reset(acb); + acb->acb_flags &= ~ACB_F_BUS_RESET; + return; } /* +************************************************************************** +************************************************************************** +*/ +static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, + union ccb * pccb) +{ + pccb->ccb_h.status |= CAM_REQ_CMP; + switch (pccb->csio.cdb_io.cdb_bytes[0]) { + case INQUIRY: { + unsigned char inqdata[36]; + char *buffer=pccb->csio.data_ptr;; + + if (pccb->ccb_h.target_lun) { + pccb->ccb_h.status |= CAM_SEL_TIMEOUT; + xpt_done(pccb); + return; + } + inqdata[0] = T_PROCESSOR; + /* Periph Qualifier & Periph Dev Type */ + inqdata[1] = 0; + /* rem media bit & Dev Type Modifier */ + inqdata[2] = 0; + /* ISO, ECMA, & ANSI versions */ + inqdata[4] = 31; + /* length of additional data */ + strncpy(&inqdata[8], "Areca ", 8); + /* Vendor Identification */ + strncpy(&inqdata[16], "RAID controller ", 16); + /* Product Identification */ + strncpy(&inqdata[32], "R001", 4); /* Product Revision */ + memcpy(buffer, inqdata, sizeof(inqdata)); + xpt_done(pccb); + } + break; + case WRITE_BUFFER: + case READ_BUFFER: { + if (arcmsr_iop_message_xfer(acb, pccb)) { + pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; + pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; + } + xpt_done(pccb); + } + break; + default: + xpt_done(pccb); + } +} +/* ********************************************************************* -** -** CAM Status field values -**typedef enum { -** CAM_REQ_INPROG, CCB request is in progress -** CAM_REQ_CMP, CCB request completed without error -** CAM_REQ_ABORTED, CCB request aborted by the host -** CAM_UA_ABORT, Unable to abort CCB request -** CAM_REQ_CMP_ERR, CCB request completed with an error -** CAM_BUSY, CAM subsytem is busy -** CAM_REQ_INVALID, CCB request was invalid -** CAM_PATH_INVALID, Supplied Path ID is invalid -** CAM_DEV_NOT_THERE, SCSI Device Not Installed/there -** CAM_UA_TERMIO, Unable to terminate I/O CCB request -** CAM_SEL_TIMEOUT, Target Selection Timeout -** CAM_CMD_TIMEOUT, Command timeout -** CAM_SCSI_STATUS_ERROR, SCSI error, look at error code in CCB -** CAM_MSG_REJECT_REC, Message Reject Received -** CAM_SCSI_BUS_RESET, SCSI Bus Reset Sent/Received -** CAM_UNCOR_PARITY, Uncorrectable parity error occurred -** CAM_AUTOSENSE_FAIL=0x10, Autosense: request sense cmd fail -** CAM_NO_HBA, No HBA Detected error -** CAM_DATA_RUN_ERR, Data Overrun error -** CAM_UNEXP_BUSFREE, Unexpected Bus Free -** CAM_SEQUENCE_FAIL, Target Bus Phase Sequence Failure -** CAM_CCB_LEN_ERR, CCB length supplied is inadequate -** CAM_PROVIDE_FAIL, Unable to provide requested capability -** CAM_BDR_SENT, A SCSI BDR msg was sent to target -** CAM_REQ_TERMIO, CCB request terminated by the host -** CAM_UNREC_HBA_ERROR, Unrecoverable Host Bus Adapter Error -** CAM_REQ_TOO_BIG, The request was too large for this host -** CAM_REQUEUE_REQ, -** * This request should be requeued to preserve -** * transaction ordering. This typically occurs -** * when the SIM recognizes an error that should -** * freeze the queue and must place additional -** * requests for the target at the sim level -** * back into the XPT queue. -** -** CAM_IDE=0x33, Initiator Detected Error -** CAM_RESRC_UNAVAIL, Resource Unavailable -** CAM_UNACKED_EVENT, Unacknowledged Event by Host -** CAM_MESSAGE_RECV, Message Received in Host Target Mode -** CAM_INVALID_CDB, Invalid CDB received in Host Target Mode -** CAM_LUN_INVALID, Lun supplied is invalid -** CAM_TID_INVALID, Target ID supplied is invalid -** CAM_FUNC_NOTAVAIL, The requested function is not available -** CAM_NO_NEXUS, Nexus is not established -** CAM_IID_INVALID, The initiator ID is invalid -** CAM_CDB_RECVD, The SCSI CDB has been received -** CAM_LUN_ALRDY_ENA, The LUN is already eanbeld for target mode -** CAM_SCSI_BUSY, SCSI Bus Busy -** -** CAM_DEV_QFRZN=0x40, The DEV queue is frozen w/this err -** -** Autosense data valid for target -** CAM_AUTOSNS_VALID=0x80, -** CAM_RELEASE_SIMQ=0x100, SIM ready to take more commands -** CAM_SIM_QUEUED =0x200, SIM has this command in it's queue -** -** CAM_STATUS_MASK=0x3F, Mask bits for just the status # -** -** Target Specific Adjunct Status -** CAM_SENT_SENSE=0x40000000 sent sense with status -**} cam_status; -** -**union ccb { -** struct ccb_hdr ccb_h; For convenience -** struct ccb_scsiio csio; -** struct ccb_getdev cgd; -** struct ccb_getdevlist cgdl; -** struct ccb_pathinq cpi; -** struct ccb_relsim crs; -** struct ccb_setasync csa; -** struct ccb_setdev csd; -** struct ccb_pathstats cpis; -** struct ccb_getdevstats cgds; -** struct ccb_dev_match cdm; -** struct ccb_trans_settings cts; -** struct ccb_calc_geometry ccg; -** struct ccb_abort cab; -** struct ccb_resetbus crb; -** struct ccb_resetdev crd; -** struct ccb_termio tio; -** struct ccb_accept_tio atio; -** struct ccb_scsiio ctio; -** struct ccb_en_lun cel; -** struct ccb_immed_notify cin; -** struct ccb_notify_ack cna; -** struct ccb_eng_inq cei; -** struct ccb_eng_exec cee; -** struct ccb_rescan crcn; -** struct ccb_debug cdbg; -** } -** -**struct ccb_hdr { -** cam_pinfo pinfo; "" Info for priority scheduling -** camq_entry xpt_links; "" For chaining in the XPT layer -** camq_entry sim_links; "" For chaining in the SIM layer -** camq_entry periph_links; "" For chaining in the type driver -** u_int32_t retry_count; -** void (*cbfcnp)(struct cam_periph *, union ccb *);"" Callback on completion function -** xpt_opcode func_code; "" XPT function code -** u_int32_t status; "" Status returned by CAM subsystem -** struct cam_path *path; "" Compiled path for this ccb -** path_id_t path_id; "" Path ID for the request -** target_id_t target_id; "" Target device ID -** lun_id_t target_lun; "" Target LUN number -** u_int32_t flags; -** ccb_ppriv_area periph_priv; -** ccb_spriv_area sim_priv; -** u_int32_t timeout; "" Timeout value -** struct callout_handle timeout_ch; "" Callout handle used for timeouts -**}; -** -**typedef union { -** u_int8_t *cdb_ptr; "" Pointer to the CDB bytes to send -** u_int8_t cdb_bytes[IOCDBLEN]; "" Area for the CDB send -**} cdb_t; -** -** SCSI I/O Request CCB used for the XPT_SCSI_IO and XPT_CONT_TARGET_IO -** function codes. -** -**struct ccb_scsiio { -** struct ccb_hdr ccb_h; -** union ccb *next_ccb; "" Ptr for next CCB for action -** u_int8_t *req_map; "" Ptr to mapping info -** u_int8_t *data_ptr; "" Ptr to the data buf/SG list -** u_int32_t dxfer_len; "" Data transfer length -** struct scsi_sense_data sense_data; "" Autosense storage -** u_int8_t sense_len; "" Number of bytes to autosense -** u_int8_t cdb_len; "" Number of bytes for the CDB -** u_int16_t sglist_cnt; "" Number of SG list entries -** u_int8_t scsi_status; "" Returned SCSI status -** u_int8_t sense_resid; "" Autosense resid length: 2's comp -** u_int32_t resid; "" Transfer residual length: 2's comp -** cdb_t cdb_io; "" Union for CDB bytes/pointer -** u_int8_t *msg_ptr; "" Pointer to the message buffer -** u_int16_t msg_len; "" Number of bytes for the Message -** u_int8_t tag_action; "" What to do for tag queueing -**#define CAM_TAG_ACTION_NONE 0x00 "" The tag action should be either the define below (to send a non-tagged transaction) or one of the defined scsi tag messages from scsi_message.h. -** u_int tag_id; "" tag id from initator (target mode) -** u_int init_id; "" initiator id of who selected -**} ********************************************************************* */ -static VOID arcmsr_action(struct cam_sim * psim,union ccb * pccb) +static void arcmsr_action(struct cam_sim * psim, union ccb * pccb) { - PACB pACB; - - #if ARCMSR_DEBUG0 - printf("arcmsr_action ..................................\n" ); - #endif + struct AdapterControlBlock * acb; - pACB=(PACB) cam_sim_softc(psim); - if(pACB==NULL) - { - pccb->ccb_h.status=CAM_REQ_INVALID; + acb=(struct AdapterControlBlock *) cam_sim_softc(psim); + if(acb==NULL) { + pccb->ccb_h.status |= CAM_REQ_INVALID; xpt_done(pccb); return; } - switch (pccb->ccb_h.func_code) - { - case XPT_SCSI_IO: - { - PSRB pSRB; - #if ARCMSR_DEBUG0 - printf("arcmsr_action: XPT_SCSI_IO......................\n" ); - #endif - - if((pSRB=arcmsr_get_freesrb(pACB)) == NULL) - { - pccb->ccb_h.status=CAM_RESRC_UNAVAIL; + switch (pccb->ccb_h.func_code) { + 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) { + pccb->ccb_h.status |= CAM_RESRC_UNAVAIL; xpt_done(pccb); return; } - pccb->ccb_h.arcmsr_ccbsrb_ptr=pSRB; - pccb->ccb_h.arcmsr_ccbacb_ptr=pACB; - pSRB->pccb=pccb; - if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) - { - if((pccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) - { - if((pccb->ccb_h.flags & CAM_DATA_PHYS) == 0) - { - LONG error,s; + 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) { + if(!(pccb->ccb_h.flags & CAM_SCATTER_VALID)) { + /* Single buffer */ + if(!(pccb->ccb_h.flags & CAM_DATA_PHYS)) { + /* Buffer is virtual */ + u_int32_t error, s; s=splsoftvm(); - error = bus_dmamap_load(pACB->buffer_dmat,pSRB->dmamap,pccb->csio.data_ptr,pccb->csio.dxfer_len,arcmsr_executesrb,pSRB,/*flags*/0); - if(error == EINPROGRESS) - { - xpt_freeze_simq(pACB->psim,1); + error = bus_dmamap_load(acb->dm_segs_dmat + , srb->dm_segs_dmamap + , pccb->csio.data_ptr + , pccb->csio.dxfer_len + , arcmsr_executesrb, srb, /*flags*/0); + if(error == EINPROGRESS) { + xpt_freeze_simq(acb->psim, 1); pccb->ccb_h.status |= CAM_RELEASE_SIMQ; } splx(s); - } - else - { + } else { + /* Buffer is physical */ panic("arcmsr: CAM_DATA_PHYS not supported"); } - } - else - { + } 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; + 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; xpt_done(pccb); - free(pSRB,M_DEVBUF); + free(srb, M_DEVBUF); return; } segs=(struct bus_dma_segment *)pccb->csio.data_ptr; - arcmsr_executesrb(pSRB,segs,pccb->csio.sglist_cnt,0); + arcmsr_executesrb(srb, segs, pccb->csio.sglist_cnt, 0); } - } - else - { - arcmsr_executesrb(pSRB,NULL,0,0); + } else { + arcmsr_executesrb(srb, NULL, 0, 0); } break; } - case XPT_TARGET_IO: - { - #if ARCMSR_DEBUG0 - printf("arcmsr_action: XPT_TARGET_IO\n" ); - #endif - /* - ** target mode not yet support vendor specific commands. - */ - pccb->ccb_h.status=CAM_REQ_CMP; + case XPT_TARGET_IO: { + /* target mode not yet support vendor specific commands. */ + pccb->ccb_h.status |= CAM_REQ_CMP; xpt_done(pccb); break; } - case XPT_PATH_INQ: - { - struct ccb_pathinq *cpi=&pccb->cpi; + case XPT_PATH_INQ: { + struct ccb_pathinq *cpi= &pccb->cpi; - #if ARCMSR_DEBUG0 - printf("arcmsr_action: XPT_PATH_INQ\n" ); - #endif cpi->version_num=1; cpi->hba_inquiry=PI_SDTR_ABLE | PI_TAG_ABLE; cpi->target_sprt=0; cpi->hba_misc=0; cpi->hba_eng_cnt=0; - cpi->max_target=ARCMSR_MAX_TARGETID; - cpi->max_lun=ARCMSR_MAX_TARGETLUN; /* 7 or 0 */ - cpi->initiator_id=ARCMSR_SCSI_INITIATOR_ID; + cpi->max_target=ARCMSR_MAX_TARGETID; /* 0-16 */ + cpi->max_lun=ARCMSR_MAX_TARGETLUN; /* 0-7 */ + cpi->initiator_id=ARCMSR_SCSI_INITIATOR_ID; /* 255 */ cpi->bus_id=cam_sim_bus(psim); - strncpy(cpi->sim_vid,"FreeBSD",SIM_IDLEN); - strncpy(cpi->hba_vid,"ARCMSR",HBA_IDLEN); - strncpy(cpi->dev_name,cam_sim_name(psim),DEV_IDLEN); + strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); + strncpy(cpi->hba_vid, "ARCMSR", HBA_IDLEN); + strncpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN); cpi->unit_number=cam_sim_unit(psim); - cpi->ccb_h.status=CAM_REQ_CMP; cpi->transport = XPORT_SPI; cpi->transport_version = 2; cpi->protocol = PROTO_SCSI; cpi->protocol_version = SCSI_REV_2; + cpi->ccb_h.status |= CAM_REQ_CMP; xpt_done(pccb); break; } - case XPT_ABORT: - { + case XPT_ABORT: { union ccb *pabort_ccb; - #if ARCMSR_DEBUG0 - printf("arcmsr_action: XPT_ABORT\n" ); - #endif pabort_ccb=pccb->cab.abort_ccb; - switch (pabort_ccb->ccb_h.func_code) - { + switch (pabort_ccb->ccb_h.func_code) { case XPT_ACCEPT_TARGET_IO: case XPT_IMMED_NOTIFY: case XPT_CONT_TARGET_IO: - if(arcmsr_seek_cmd2abort(pabort_ccb)==TRUE) - { - pabort_ccb->ccb_h.status=CAM_REQ_ABORTED; + if(arcmsr_seek_cmd2abort(pabort_ccb)==TRUE) { + pabort_ccb->ccb_h.status |= CAM_REQ_ABORTED; xpt_done(pabort_ccb); - pccb->ccb_h.status=CAM_REQ_CMP; - } - else - { + pccb->ccb_h.status |= CAM_REQ_CMP; + } else { xpt_print_path(pabort_ccb->ccb_h.path); printf("Not found\n"); - pccb->ccb_h.status=CAM_PATH_INVALID; + pccb->ccb_h.status |= CAM_PATH_INVALID; } break; case XPT_SCSI_IO: - pccb->ccb_h.status=CAM_UA_ABORT; + pccb->ccb_h.status |= CAM_UA_ABORT; break; default: - pccb->ccb_h.status=CAM_REQ_INVALID; + pccb->ccb_h.status |= CAM_REQ_INVALID; break; } xpt_done(pccb); break; } case XPT_RESET_BUS: - case XPT_RESET_DEV: - { - LONG i; + case XPT_RESET_DEV: { + u_int32_t i; - #if ARCMSR_DEBUG0 - printf("arcmsr_action: XPT_RESET_BUS\n" ); - #endif - arcmsr_bus_reset(pACB); - for (i=0; i < 500; i++) - { + arcmsr_bus_reset(acb); + for (i=0; i < 500; i++) { DELAY(1000); } - pccb->ccb_h.status=CAM_REQ_CMP; + pccb->ccb_h.status |= CAM_REQ_CMP; xpt_done(pccb); break; } - case XPT_TERM_IO: - { - #if ARCMSR_DEBUG0 - printf("arcmsr_action: XPT_TERM_IO\n" ); - #endif - pccb->ccb_h.status=CAM_REQ_INVALID; + case XPT_TERM_IO: { + pccb->ccb_h.status |= CAM_REQ_INVALID; xpt_done(pccb); break; } - case XPT_GET_TRAN_SETTINGS: - { - struct ccb_trans_settings *cts = &pccb->cts; - ULONG s; - struct ccb_trans_settings_scsi *scsi = - &cts->proto_specific.scsi; - struct ccb_trans_settings_spi *spi = - &cts->xport_specific.spi; + 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; - - - #if ARCMSR_DEBUG0 - printf("arcmsr_action: XPT_GET_TRAN_SETTINGS\n" ); - #endif - - s=splcam(); spi->flags = CTS_SPI_FLAGS_DISC_ENB; spi->sync_period=3; spi->sync_offset=32; @@ -1991,52 +1599,53 @@ static VOID arcmsr_action(struct cam_sim * psim,union ccb * pccb) | CTS_SPI_VALID_SYNC_OFFSET | CTS_SPI_VALID_BUS_WIDTH; scsi->valid = CTS_SCSI_VALID_TQ; - splx(s); - pccb->ccb_h.status=CAM_REQ_CMP; + + pccb->ccb_h.status |= CAM_REQ_CMP; xpt_done(pccb); break; } - case XPT_SET_TRAN_SETTINGS: - { - #if ARCMSR_DEBUG0 - printf("arcmsr_action: XPT_SET_TRAN_SETTINGS\n" ); - #endif - pccb->ccb_h.status = CAM_FUNC_NOTAVAIL; - xpt_done(pccb); + case XPT_SET_TRAN_SETTINGS: { + pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; + xpt_done(pccb); break; } - case XPT_CALC_GEOMETRY: - { + case XPT_CALC_GEOMETRY: { struct ccb_calc_geometry *ccg; - ULONG size_mb; - ULONG secs_per_cylinder; + u_int32_t size_mb; + u_int32_t secs_per_cylinder; - #if ARCMSR_DEBUG0 - printf("arcmsr_action: XPT_CALC_GEOMETRY\n" ); - #endif - ccg=&pccb->ccg; + if(pccb->ccb_h.target_id == 16) { + pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; + xpt_done(pccb); + break; + } + ccg= &pccb->ccg; + if (ccg->block_size == 0) { + pccb->ccb_h.status = CAM_REQ_INVALID; + xpt_done(pccb); + break; + } + if(((1024L * 1024L)/ccg->block_size) < 0) { + pccb->ccb_h.status = CAM_REQ_INVALID; + xpt_done(pccb); + break; + } size_mb=ccg->volume_size/((1024L * 1024L)/ccg->block_size); - if(size_mb > 1024 ) - { + if(size_mb > 1024 ) { ccg->heads=255; ccg->secs_per_track=63; - } - else - { + } else { ccg->heads=64; ccg->secs_per_track=32; } secs_per_cylinder=ccg->heads * ccg->secs_per_track; ccg->cylinders=ccg->volume_size / secs_per_cylinder; - pccb->ccb_h.status=CAM_REQ_CMP; + pccb->ccb_h.status |= CAM_REQ_CMP; xpt_done(pccb); break; } default: - #if ARCMSR_DEBUG0 - printf("arcmsr_action: invalid XPT function CAM_REQ_INVALID\n" ); - #endif - pccb->ccb_h.status=CAM_REQ_INVALID; + pccb->ccb_h.status |= CAM_REQ_INVALID; xpt_done(pccb); break; } @@ -2044,115 +1653,233 @@ static VOID arcmsr_action(struct cam_sim * psim,union ccb * pccb) } /* ********************************************************************** -** -** start background rebuild -** ********************************************************************** */ -VOID arcmsr_start_adapter_bgrb(PACB pACB) +static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) { - #if ARCMSR_DEBUG0 - printf("arcmsr_start_adapter_bgrb.................................. \n"); - #endif - pACB->acb_flags |= ACB_F_MSG_START_BGRB; - pACB->acb_flags &= ~ACB_F_MSG_STOP_BGRB; - CHIP_REG_WRITE32(&pACB->pmu->inbound_msgaddr0,ARCMSR_INBOUND_MESG0_START_BGRB); + acb->acb_flags |= ACB_F_MSG_START_BGRB; + CHIP_REG_WRITE32(inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); + if(arcmsr_wait_msgint_ready(acb)) { + printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); + } return; } /* ********************************************************************** -** -** start background rebuild -** ********************************************************************** */ -VOID arcmsr_iop_init(PACB pACB) +static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) { - ULONG intmask_org,mask,outbound_doorbell,firmware_state=0; - - #if ARCMSR_DEBUG0 - printf("arcmsr_iop_init.................................. \n"); - #endif - do
- {
- firmware_state=CHIP_REG_READ32(&pACB->pmu->outbound_msgaddr1);
- }while((firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK)==0); - /* disable all outbound interrupt */ - intmask_org=CHIP_REG_READ32(&pACB->pmu->outbound_intmask); - CHIP_REG_WRITE32(&pACB->pmu->outbound_intmask,intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); - /*start background rebuild*/ - arcmsr_start_adapter_bgrb(pACB); - if(arcmsr_wait_msgint_ready(pACB)!=TRUE) - { - printf("arcmsr_HwInitialize: wait 'start adapter background rebuild' timeout................. \n"); + struct CommandControlBlock *srb; + uint32_t flag_srb, outbound_intstatus, poll_srb_done=0, poll_count=0; + int id, lun; + +polling_srb_retry: + poll_count++; + outbound_intstatus=CHIP_REG_READ32(outbound_intstatus) & acb->outbound_int_enable; + CHIP_REG_WRITE32(outbound_intstatus, outbound_intstatus);/*clear interrupt*/ + while(1) { + if((flag_srb=CHIP_REG_READ32(outbound_queueport))==0xFFFFFFFF) { + if(poll_srb_done) { + break;/*chip FIFO no ccb for completion already*/ + } else { + UDELAY(25000); + if(poll_count > 100) { + break; + } + goto polling_srb_retry; + } + } + /* check ifcommand 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) && (srb==poll_srb)) { + 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); + poll_srb_done=1; + continue; + } + printf("arcmsr%d: polling get an illegal srb command done srb='%p'" + "srboutstandingcount=%d \n" + , acb->pci_unit + , 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; + } + } + } /*drain reply FIFO*/ + return; +} +/* +********************************************************************** +** get firmware miscellaneous data +********************************************************************** +*/ +static void arcmsr_get_firmware_spec(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*/ + int i; + + CHIP_REG_WRITE32(inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); + if(arcmsr_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); + /* 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); + /* 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*/ + 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; + arcmsr_get_firmware_spec(acb); + arcmsr_start_adapter_bgrb(acb); /* clear Qbuffer if door bell ringed */ - outbound_doorbell=CHIP_REG_READ32(&pACB->pmu->outbound_doorbell); - if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) - { - CHIP_REG_WRITE32(&pACB->pmu->outbound_doorbell,outbound_doorbell);/*clear interrupt */ - CHIP_REG_WRITE32(&pACB->pmu->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|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE); - CHIP_REG_WRITE32(&pACB->pmu->outbound_intmask,intmask_org & mask); - pACB->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; - pACB->acb_flags |=ACB_F_IOP_INITED; + 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; + acb->acb_flags |=ACB_F_IOP_INITED; return; } /* ********************************************************************** -** -** map freesrb -** ********************************************************************** */ static void arcmsr_map_freesrb(void *arg, bus_dma_segment_t *segs, int nseg, int error) { - PACB pACB=arg; - PSRB psrb_tmp,pfreesrb; - ULONG cdb_phyaddr; - LONG i; - - pfreesrb=(PSRB)pACB->uncacheptr;
- cdb_phyaddr=segs->ds_addr; /* We suppose bus_addr_t high part always 0 here*/
- if(((CPT2INT)pACB->uncacheptr & 0x1F)!=0)
- {
- pfreesrb=pfreesrb+(0x20-((CPT2INT)pfreesrb & 0x1F));
- cdb_phyaddr=cdb_phyaddr+(0x20-((CPT2INT)cdb_phyaddr & 0x1F));
+ struct AdapterControlBlock *acb=arg; + struct CommandControlBlock *srb_tmp; + u_int8_t * dma_memptr; + u_int32_t i, srb_phyaddr_hi32; + 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)); + } + srb_tmp=(struct CommandControlBlock *)dma_memptr; + for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { + /*srb address must 32 (0x20) boundary*/ + if(((unsigned long)srb_tmp & 0x1F)==0) { + 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: 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 { + 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); + return; + } + 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 ******************************************************************** */ - for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) - { - psrb_tmp=&pfreesrb[i]; - if(((CPT2INT)psrb_tmp & 0x1F)==0) /*srb address must 32 (0x20) boundary*/ - { - if(bus_dmamap_create(pACB->buffer_dmat, /*flags*/0, &psrb_tmp->dmamap)!=0) - { - pACB->acb_flags |= ACB_F_MAPFREESRB_FAILD; - printf(" arcmsr_map_freesrb: (pSRB->dmamap) bus_dmamap_create ..............error\n"); - return; - } - psrb_tmp->cdb_shifted_phyaddr=cdb_phyaddr >> 5; - psrb_tmp->pACB=pACB; - pACB->psrbringQ[i]=psrb_tmp; - cdb_phyaddr=cdb_phyaddr+sizeof(struct _SRB); - } - else - { - pACB->acb_flags |= ACB_F_MAPFREESRB_FAILD; - printf(" arcmsr_map_freesrb:pfreesrb=%p i=%d this srb cross 32 bytes boundary ignored ......psrb_tmp=%p \n",pfreesrb,i,psrb_tmp); - return; + 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); } } - pACB->pfreesrb=pfreesrb; - pACB->vir2phy_offset=(CPT2INT)psrb_tmp-(cdb_phyaddr-sizeof(struct _SRB)); - return; + return; } /* ************************************************************************ @@ -2160,255 +1887,240 @@ static void arcmsr_map_freesrb(void *arg, bus_dma_segment_t *segs, int nseg, int ** ************************************************************************ */ -VOID arcmsr_free_resource(PACB pACB) +static void arcmsr_free_resource(struct AdapterControlBlock *acb) { /* remove the control device */ - if (pACB->ioctl_dev != NULL) - { - destroy_dev(pACB->ioctl_dev); + if(acb->ioctl_dev != NULL) { + destroy_dev(acb->ioctl_dev); } - bus_dmamap_unload(pACB->srb_dmat, pACB->srb_dmamap); - bus_dmamap_destroy(pACB->srb_dmat, pACB->srb_dmamap); - bus_dma_tag_destroy(pACB->srb_dmat); - bus_dma_tag_destroy(pACB->buffer_dmat); - bus_dma_tag_destroy(pACB->parent_dmat); + bus_dmamap_unload(acb->srb_dmat, acb->srb_dmamap); + bus_dmamap_destroy(acb->srb_dmat, acb->srb_dmamap); + bus_dma_tag_destroy(acb->srb_dmat); + bus_dma_tag_destroy(acb->dm_segs_dmat); + bus_dma_tag_destroy(acb->parent_dmat); return; } /* ************************************************************************ -** PCI config header registers for all devices -** -** #define PCIR_COMMAND 0x04 -** #define PCIM_CMD_PORTEN 0x0001 -** #define PCIM_CMD_MEMEN 0x0002 -** #define PCIM_CMD_BUSMASTEREN 0x0004 -** #define PCIM_CMD_MWRICEN 0x0010 -** #define PCIM_CMD_PERRESPEN 0x0040 -** -** Function : arcmsr_initialize -** Purpose : initialize the internal structures for a given SCSI host -** Inputs : host - pointer to this host adapter's structure -** Preconditions : when this function is called,the chip_type -** field of the pACB structure MUST have been set. -** -** 10h Base Address register #0 -** 14h Base Address register #1 -** 18h Base Address register #2 -** 1Ch Base Address register #3 -** 20h Base Address register #4 -** 24h Base Address register #5 ************************************************************************ */ -static LONG arcmsr_initialize(device_t dev) +static u_int32_t arcmsr_initialize(device_t dev) { - PACB pACB=device_get_softc(dev); - LONG rid=PCI_BASE_ADDR0; + struct AdapterControlBlock *acb=device_get_softc(dev); + u_int32_t intmask_org, rid=PCIR_BAR(0); vm_offset_t mem_base; - USHORT pci_command; + u_int16_t pci_command; + int i, j; - #if ARCMSR_DEBUG0 - printf("arcmsr_initialize..............................\n"); - #endif #if __FreeBSD_version >= 502010 - if (bus_dma_tag_create( /*parent*/NULL, - /*alignemnt*/1, - /*boundary*/0, - /*lowaddr*/BUS_SPACE_MAXADDR, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, - /*filterarg*/NULL, - /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, - /*nsegments*/BUS_SPACE_UNRESTRICTED, - /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, - /*flags*/0, - /*lockfunc*/NULL, - /*lockarg*/NULL, - &pACB->parent_dmat) != 0) + if(bus_dma_tag_create( /*parent*/ NULL, + /*alignemnt*/ 1, + /*boundary*/ 0, + /*lowaddr*/ BUS_SPACE_MAXADDR, + /*highaddr*/ BUS_SPACE_MAXADDR, + /*filter*/ NULL, + /*filterarg*/ NULL, + /*maxsize*/ BUS_SPACE_MAXSIZE_32BIT, + /*nsegments*/ BUS_SPACE_UNRESTRICTED, + /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, + /*flags*/ 0, + /*lockfunc*/ NULL, + /*lockarg*/ NULL, + &acb->parent_dmat) != 0) #else - if (bus_dma_tag_create( /*parent*/NULL, - /*alignemnt*/1, - /*boundary*/0, - /*lowaddr*/BUS_SPACE_MAXADDR, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, - /*filterarg*/NULL, - /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, - /*nsegments*/BUS_SPACE_UNRESTRICTED, - /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, - /*flags*/0, - &pACB->parent_dmat) != 0) + if(bus_dma_tag_create( /*parent*/ NULL, + /*alignemnt*/ 1, + /*boundary*/ 0, + /*lowaddr*/ BUS_SPACE_MAXADDR, + /*highaddr*/ BUS_SPACE_MAXADDR, + /*filter*/ NULL, + /*filterarg*/ NULL, + /*maxsize*/ BUS_SPACE_MAXSIZE_32BIT, + /*nsegments*/ BUS_SPACE_UNRESTRICTED, + /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, + /*flags*/ 0, + &acb->parent_dmat) != 0) #endif { - printf("arcmsr_initialize: bus_dma_tag_create .......................failure!\n"); + printf("arcmsr%d: parent_dmat bus_dma_tag_create failure!\n", acb->pci_unit); return ENOMEM; } - /* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */ + /* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */ #if __FreeBSD_version >= 502010 - if(bus_dma_tag_create( /*parent_dmat*/pACB->parent_dmat, - /*alignment*/1, - /*boundary*/0, - /*lowaddr*/BUS_SPACE_MAXADDR, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, - /*filterarg*/NULL, - /*maxsize*/MAXBSIZE, - /*nsegments*/ARCMSR_MAX_SG_ENTRIES, - /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, - /*flags*/BUS_DMA_ALLOCNOW, - /*lockfunc*/busdma_lock_mutex, - /*lockarg*/&Giant, - &pACB->buffer_dmat) != 0) + if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, + /*alignment*/ 1, + /*boundary*/ 0, + /*lowaddr*/ BUS_SPACE_MAXADDR, + /*highaddr*/ BUS_SPACE_MAXADDR, + /*filter*/ NULL, + /*filterarg*/ NULL, + /*maxsize*/ MAXBSIZE, + /*nsegments*/ ARCMSR_MAX_SG_ENTRIES, + /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, + /*flags*/ 0, + /*lockfunc*/ busdma_lock_mutex, + /*lockarg*/ &Giant, + &acb->dm_segs_dmat) != 0) #else - if(bus_dma_tag_create( /*parent_dmat*/pACB->parent_dmat, - /*alignment*/1, - /*boundary*/0, - /*lowaddr*/BUS_SPACE_MAXADDR, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, - /*filterarg*/NULL, - /*maxsize*/MAXBSIZE, - /*nsegments*/ARCMSR_MAX_SG_ENTRIES, - /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, - /*flags*/BUS_DMA_ALLOCNOW, - &pACB->buffer_dmat) != 0) + if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, + /*alignment*/ 1, + /*boundary*/ 0, + /*lowaddr*/ BUS_SPACE_MAXADDR, + /*highaddr*/ BUS_SPACE_MAXADDR, + /*filter*/ NULL, + /*filterarg*/ NULL, + /*maxsize*/ MAXBSIZE, + /*nsegments*/ ARCMSR_MAX_SG_ENTRIES, + /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, + /*flags*/ 0, + &acb->dm_segs_dmat) != 0) #endif { - bus_dma_tag_destroy(pACB->parent_dmat); - printf("arcmsr_initialize: bus_dma_tag_create ............................failure!\n"); + bus_dma_tag_destroy(acb->parent_dmat); + printf("arcmsr%d: dm_segs_dmat bus_dma_tag_create failure!\n", acb->pci_unit); return ENOMEM; - } - /* DMA tag for our srb structures.... Allocate the pfreesrb memory */ + } + /* DMA tag for our srb structures.... Allocate the freesrb memory */ #if __FreeBSD_version >= 502010 - if (bus_dma_tag_create( /*parent_dmat*/pACB->parent_dmat, - /*alignment*/1, - /*boundary*/0, - /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, - /*filterarg*/NULL, - /*maxsize*/((sizeof(struct _SRB) * ARCMSR_MAX_FREESRB_NUM)+0x20), - /*nsegments*/1, - /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, - /*flags*/0, - /*lockfunc*/NULL, - /*lockarg*/NULL, - &pACB->srb_dmat) != 0) + if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, + /*alignment*/ 1, + /*boundary*/ 0, + /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, + /*highaddr*/ BUS_SPACE_MAXADDR, + /*filter*/ NULL, + /*filterarg*/ NULL, + /*maxsize*/ ARCMSR_SRBS_POOL_SIZE, + /*nsegments*/ 1, + /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, + /*flags*/ 0, + /*lockfunc*/ NULL, + /*lockarg*/ NULL, + &acb->srb_dmat) != 0) #else - if (bus_dma_tag_create( /*parent_dmat*/pACB->parent_dmat, - /*alignment*/1, - /*boundary*/0, - /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, - /*highaddr*/BUS_SPACE_MAXADDR, - /*filter*/NULL, - /*filterarg*/NULL, - /*maxsize*/((sizeof(struct _SRB) * ARCMSR_MAX_FREESRB_NUM)+0x20), - /*nsegments*/1, - /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, - /*flags*/0, - &pACB->srb_dmat) != 0) + if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, + /*alignment*/ 1, + /*boundary*/ 0, + /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, + /*highaddr*/ BUS_SPACE_MAXADDR, + /*filter*/ NULL, + /*filterarg*/ NULL, + /*maxsize*/ ARCMSR_SRBS_POOL_SIZE, + /*nsegments*/ 1, + /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, + /*flags*/ 0, + &acb->srb_dmat) != 0) #endif { - bus_dma_tag_destroy(pACB->buffer_dmat); - bus_dma_tag_destroy(pACB->parent_dmat); - printf("arcmsr_initialize: pACB->srb_dmat bus_dma_tag_create .....................failure!\n"); + 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); return ENXIO; - } + } /* Allocation for our srbs */ - if (bus_dmamem_alloc(pACB->srb_dmat, (void **)&pACB->uncacheptr, BUS_DMA_WAITOK | BUS_DMA_COHERENT, &pACB->srb_dmamap) != 0) - { - bus_dma_tag_destroy(pACB->srb_dmat); - bus_dma_tag_destroy(pACB->buffer_dmat); - bus_dma_tag_destroy(pACB->parent_dmat); - printf("arcmsr_initialize: pACB->srb_dmat bus_dma_tag_create ...............failure!\n"); + if(bus_dmamem_alloc(acb->srb_dmat, (void **)&acb->uncacheptr + , BUS_DMA_WAITOK | BUS_DMA_COHERENT, &acb->srb_dmamap) != 0) { + bus_dma_tag_destroy(acb->srb_dmat); + bus_dma_tag_destroy(acb->dm_segs_dmat); + bus_dma_tag_destroy(acb->parent_dmat); + printf("arcmsr%d: srb_dmat bus_dmamem_alloc failure!\n", acb->pci_unit); return ENXIO; } /* And permanently map them */ - if(bus_dmamap_load(pACB->srb_dmat, pACB->srb_dmamap,pACB->uncacheptr,(sizeof(struct _SRB) * ARCMSR_MAX_FREESRB_NUM)+0x20,arcmsr_map_freesrb, pACB, /*flags*/0)) - { - bus_dma_tag_destroy(pACB->srb_dmat); - bus_dma_tag_destroy(pACB->buffer_dmat); - bus_dma_tag_destroy(pACB->parent_dmat); - printf("arcmsr_initialize: bus_dmamap_load................... failure!\n"); + if(bus_dmamap_load(acb->srb_dmat, acb->srb_dmamap, acb->uncacheptr + , ARCMSR_SRBS_POOL_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); return ENXIO; } - pci_command=pci_read_config(dev,PCIR_COMMAND,2); + pci_command=pci_read_config(dev, PCIR_COMMAND, 2); pci_command |= PCIM_CMD_BUSMASTEREN; pci_command |= PCIM_CMD_PERRESPEN; pci_command |= PCIM_CMD_MWRICEN; /* Enable Busmaster/Mem */ pci_command |= PCIM_CMD_MEMEN; - pci_write_config(dev,PCIR_COMMAND,pci_command,2); - pACB->sys_res_arcmsr=bus_alloc_resource(dev,SYS_RES_MEMORY,&rid,0,~0,0x1000,RF_ACTIVE); - if(pACB->sys_res_arcmsr == NULL) - { - arcmsr_free_resource(pACB); - printf("arcmsr_initialize: bus_alloc_resource .....................failure!\n"); + 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(pACB->sys_res_arcmsr) <= 0) - { - arcmsr_free_resource(pACB); - printf("arcmsr_initialize: rman_get_start ...........................failure!\n"); - return ENXIO; + 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(pACB->sys_res_arcmsr); - if(mem_base==0) - { - arcmsr_free_resource(pACB); - printf("arcmsr_initialize: rman_get_virtual ..........................failure!\n"); + 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; } - if(pACB->acb_flags & ACB_F_MAPFREESRB_FAILD) - { - arcmsr_free_resource(pACB); - printf("arcmsr_initialize: arman_get_virtual ..........................failure!\n"); + if(acb->acb_flags & ACB_F_MAPFREESRB_FAILD) { + arcmsr_free_resource(acb); + printf("arcmsr%d: map free srb failure!\n", acb->pci_unit); return ENXIO; } - pACB->btag=rman_get_bustag(pACB->sys_res_arcmsr); - pACB->bhandle=rman_get_bushandle(pACB->sys_res_arcmsr); - pACB->pmu=(PMU)mem_base; - pACB->acb_flags |= (ACB_F_IOCTL_WQBUFFER_CLEARED|ACB_F_IOCTL_RQBUFFER_CLEARED); - pACB->acb_flags &= ~ACB_F_SCSISTOPADAPTER; - arcmsr_iop_init(pACB); - return(0); + 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->acb_flags &= ~ACB_F_SCSISTOPADAPTER; + /* + ******************************************************************** + ** init raid volume state + ******************************************************************** + */ + for(i=0;i<ARCMSR_MAX_TARGETID;i++) { + for(j=0;j<ARCMSR_MAX_TARGETLUN;j++) { + acb->devstate[i][j]=ARECA_RAID_GOOD; + } + } + /* 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); } /* ************************************************************************ -** -** attach and init a host adapter -** ************************************************************************ */ -static LONG arcmsr_attach(device_t dev) +static u_int32_t arcmsr_attach(device_t dev) { - PACB pACB=device_get_softc(dev); - LONG unit=device_get_unit(dev); + struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); + u_int32_t unit=device_get_unit(dev); struct ccb_setasync csa; struct cam_devq *devq; /* Device Queue to use for this SIM */ struct resource *irqres; int rid; - #if ARCMSR_DEBUG0 - printf("arcmsr_attach .............................\n" ); - #endif - - if(arcmsr_initialize(dev)) - { - printf("arcmsr_attach: arcmsr_initialize failure!\n"); + if(acb == NULL) { + printf("arcmsr%d: cannot allocate softc\n", unit); + return (ENOMEM); + } + bzero(acb, sizeof(struct AdapterControlBlock)); + if(arcmsr_initialize(dev)) { + printf("arcmsr%d: initialize failure!\n", unit); return ENXIO; } - /* After setting up the adapter,map our interrupt */ + /* After setting up the adapter, map our interrupt */ rid=0; - irqres=bus_alloc_resource(dev,SYS_RES_IRQ,&rid,0,~0,1,RF_SHAREABLE | RF_ACTIVE); - if(irqres == NULL || bus_setup_intr(dev,irqres,INTR_TYPE_CAM,arcmsr_interrupt,pACB,&pACB->ih)) - { - arcmsr_free_resource(pACB); - printf("arcmsr%d: unable to register interrupt handler!\n",unit); + irqres=bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE); + if(irqres == NULL || + bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE + , arcmsr_interrupt, acb, &acb->ih)) { + arcmsr_free_resource(acb); + printf("arcmsr%d: unable to register interrupt handler!\n", unit); return ENXIO; } - pACB->irqres=irqres; - pACB->pci_dev=dev; - pACB->pci_unit=unit; + acb->irqres=irqres; + acb->pci_dev=dev; + acb->pci_unit=unit; /* * Now let the CAM generic SCSI layer find the SCSI devices on * the bus * start queue to reset to the idle loop. * @@ -2416,229 +2128,175 @@ static LONG arcmsr_attach(device_t dev) * max_sim_transactions */ devq=cam_simq_alloc(ARCMSR_MAX_START_JOB); - if(devq == NULL) - { - arcmsr_free_resource(pACB); - bus_release_resource(dev, SYS_RES_IRQ, 0, pACB->irqres); - printf("arcmsr_attach: cam_simq_alloc failure!\n"); + if(devq == NULL) { + arcmsr_free_resource(acb); + bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); + printf("arcmsr%d: cam_simq_alloc failure!\n", unit); return ENXIO; } - pACB->psim=cam_sim_alloc(arcmsr_action,arcmsr_poll,"arcmsr",pACB,pACB->pci_unit,1,ARCMSR_MAX_OUTSTANDING_CMD,devq); - if(pACB->psim == NULL) - { - arcmsr_free_resource(pACB); - bus_release_resource(dev, SYS_RES_IRQ, 0, pACB->irqres); + acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll + , "arcmsr", acb, unit, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq); + if(acb->psim == NULL) { + arcmsr_free_resource(acb); + bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); cam_simq_free(devq); - printf("arcmsr_attach: cam_sim_alloc ..................failure!\n"); + printf("arcmsr%d: cam_sim_alloc failure!\n", unit); return ENXIO; } - if(xpt_bus_register(pACB->psim,0) != CAM_SUCCESS) - { - arcmsr_free_resource(pACB); - bus_release_resource(dev, SYS_RES_IRQ, 0, pACB->irqres); - cam_sim_free(pACB->psim,/*free_devq*/TRUE); - printf("arcmsr_attach: xpt_bus_register .......................failure!\n"); + if(xpt_bus_register(acb->psim, 0) != CAM_SUCCESS) { + arcmsr_free_resource(acb); + bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); + cam_sim_free(acb->psim, /*free_devq*/TRUE); + printf("arcmsr%d: xpt_bus_register failure!\n", unit); return ENXIO; } - if(xpt_create_path(&pACB->ppath,/* periph */ NULL,cam_sim_path(pACB->psim),CAM_TARGET_WILDCARD,CAM_LUN_WILDCARD) != CAM_REQ_CMP) - { - arcmsr_free_resource(pACB); - bus_release_resource(dev, SYS_RES_IRQ, 0, pACB->irqres); - xpt_bus_deregister(cam_sim_path(pACB->psim)); - cam_sim_free(pACB->psim,/* free_simq */ TRUE); - printf("arcmsr_attach: xpt_create_path .....................failure!\n"); + if(xpt_create_path(&acb->ppath, /* periph */ NULL + , cam_sim_path(acb->psim) + , CAM_TARGET_WILDCARD + , CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + arcmsr_free_resource(acb); + bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); + xpt_bus_deregister(cam_sim_path(acb->psim)); + cam_sim_free(acb->psim, /* free_simq */ TRUE); + printf("arcmsr%d: xpt_create_path failure!\n", unit); return ENXIO; } - /* + ARCMSR_LOCK_INIT(&acb->workingQ_done_lock, "arcmsr done working Q lock"); + ARCMSR_LOCK_INIT(&acb->workingQ_start_lock, "arcmsr start working Q lock"); + ARCMSR_LOCK_INIT(&acb->qbuffer_lock, "arcmsr Q buffer lock"); + /* **************************************************** */ - xpt_setup_ccb(&csa.ccb_h,pACB->ppath,/*priority*/5); + xpt_setup_ccb(&csa.ccb_h, acb->ppath, /*priority*/5); csa.ccb_h.func_code=XPT_SASYNC_CB; csa.event_enable=AC_FOUND_DEVICE|AC_LOST_DEVICE; csa.callback=arcmsr_async; - csa.callback_arg=pACB->psim; + csa.callback_arg=acb->psim; xpt_action((union ccb *)&csa); - /* Create the control device. */ - pACB->ioctl_dev=make_dev(&arcmsr_cdevsw, unit, UID_ROOT, GID_WHEEL /* GID_OPERATOR */, S_IRUSR | S_IWUSR, "arcmsr%d", unit); + /* Create the control device. */ + acb->ioctl_dev=make_dev(&arcmsr_cdevsw + , unit + , UID_ROOT + , GID_WHEEL /* GID_OPERATOR */ + , S_IRUSR | S_IWUSR + , "arcmsr%d", unit); #if __FreeBSD_version < 503000 - pACB->ioctl_dev->si_drv1=pACB; + acb->ioctl_dev->si_drv1=acb; #endif #if __FreeBSD_version > 500005 - (void)make_dev_alias(pACB->ioctl_dev, "arc%d", unit); -#endif - -#if 0 - #if __FreeBSD_version > 500005 - if(kthread_create(arcmsr_do_thread_works, pACB, &pACB->kthread_proc,0,"arcmsr%d: kthread",pACB->pci_unit)) - { - device_printf(pACB->pci_dev,"cannot create kernel thread for this host adapetr\n"); - xpt_bus_deregister(cam_sim_path(pACB->psim)); - cam_sim_free(pACB->psim,/* free_simq */ TRUE); - panic("arcmsr plunge kernel thread fail"); - } - #else - if(kthread_create(arcmsr_do_thread_works, pACB, &pACB->kthread_proc,"arcmsr%d: kthread", pACB->pci_unit)) - { - device_printf(pACB->pci_dev,"cannot create kernel thread for this host adapetr\n"); - xpt_bus_deregister(cam_sim_path(pACB->psim)); - cam_sim_free(pACB->psim,/* free_simq */ TRUE); - panic("arcmsr plunge kernel thread fail"); - } - #endif + (void)make_dev_alias(acb->ioctl_dev, "arc%d", unit); #endif - return 0; + return 0; } /* ************************************************************************ -** -** -** ************************************************************************ */ -static LONG arcmsr_probe(device_t dev) +static u_int32_t arcmsr_probe(device_t dev) { - ULONG id; - #if ARCMSR_DEBUG0 - printf("arcmsr_probe................. \n"); - #endif - switch(id=pci_get_devid(dev)) - { + u_int32_t id; + 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: - device_set_desc(dev,"ARECA ARC1110 PCI-X 4 PORTS SATA RAID CONTROLLER \n" ARCMSR_DRIVER_VERSION ); - return 0; - case PCIDevVenIDARC1120: - device_set_desc(dev,"ARECA ARC1120 PCI-X 8 PORTS SATA RAID CONTROLLER (RAID6-ENGINE Inside) \n" ARCMSR_DRIVER_VERSION); - return 0; - case PCIDevVenIDARC1130: - device_set_desc(dev,"ARECA ARC1130 PCI-X 12 PORTS SATA RAID CONTROLLER (RAID6-ENGINE Inside) \n" ARCMSR_DRIVER_VERSION); - return 0; - case PCIDevVenIDARC1160: - device_set_desc(dev,"ARECA ARC1160 PCI-X 16 PORTS SATA RAID CONTROLLER (RAID6-ENGINE Inside) \n" ARCMSR_DRIVER_VERSION); - return 0; - case PCIDevVenIDARC1210: - device_set_desc(dev,"ARECA ARC1210 PCI-EXPRESS 4 PORTS SATA RAID CONTROLLER \n" ARCMSR_DRIVER_VERSION); - return 0; - case PCIDevVenIDARC1220: - device_set_desc(dev,"ARECA ARC1220 PCI-EXPRESS 8 PORTS SATA RAID CONTROLLER (RAID6-ENGINE Inside) \n" ARCMSR_DRIVER_VERSION); - return 0; - case PCIDevVenIDARC1230: - device_set_desc(dev,"ARECA ARC1230 PCI-EXPRESS 12 PORTS SATA RAID CONTROLLER (RAID6-ENGINE Inside) \n" ARCMSR_DRIVER_VERSION); - return 0; - case PCIDevVenIDARC1260: - device_set_desc(dev,"ARECA ARC1260 PCI-EXPRESS 16 PORTS SATA RAID CONTROLLER (RAID6-ENGINE Inside) \n" ARCMSR_DRIVER_VERSION); - return 0; - } - return ENXIO; + case PCIDevVenIDARC1210: + raid6 = 0; + /*FALLTHRU*/ + case PCIDevVenIDARC1120: + case PCIDevVenIDARC1130: + case PCIDevVenIDARC1160: + case PCIDevVenIDARC1170: + case PCIDevVenIDARC1220: + case PCIDevVenIDARC1230: + case PCIDevVenIDARC1260: + case PCIDevVenIDARC1270: + case PCIDevVenIDARC1280: + type = "SATA"; + break; + case PCIDevVenIDARC1380: + case PCIDevVenIDARC1381: + case PCIDevVenIDARC1680: + case PCIDevVenIDARC1681: + type = "SAS"; + break; + default: + type = "X-TYPE"; + break; + } + sprintf(buf, "Areca %s Host Adapter RAID Controller %s\n", type, raid6 ? "(RAID6 capable)" : ""); + device_set_desc_copy(dev, buf); + return 0; } /* ************************************************************************ -** -** -** ************************************************************************ */ -static VOID arcmsr_shutdown(device_t dev) +static void arcmsr_shutdown(device_t dev) { - LONG i,abort_cmd_cnt=0; - ULONG s,intmask_org; - PSRB pSRB; - PACB pACB=device_get_softc(dev); + u_int32_t i, poll_count=0; + u_int32_t intmask_org; + struct CommandControlBlock *srb; + struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); - #if ARCMSR_DEBUG0 - printf("arcmsr_shutdown................. \n"); - #endif - s=splcam(); - /* disable all outbound interrupt */ - intmask_org=CHIP_REG_READ32(&pACB->pmu->outbound_intmask); - CHIP_REG_WRITE32(&pACB->pmu->outbound_intmask,(intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE)); /* stop adapter background rebuild */ - arcmsr_stop_adapter_bgrb(pACB); - if(arcmsr_wait_msgint_ready(pACB)!=TRUE) - { - printf("arcmsr_pcidev_disattach: wait 'stop adapter rebuild' timeout.... \n"); - } - arcmsr_flush_adapter_cache(pACB); - if(arcmsr_wait_msgint_ready(pACB)!=TRUE) - { - printf("arcmsr_pcidev_disattach: wait 'flush adapter cache' timeout.... \n"); - } + 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 */ - pACB->acb_flags |= ACB_F_SCSISTOPADAPTER; - pACB->acb_flags &= ~ACB_F_IOP_INITED; - if(pACB->srboutstandingcount!=0) - { - PSRB pfreesrb; - #if ARCMSR_DEBUG0 - printf("arcmsr_pcidev_disattach: .....pACB->srboutstandingcount!=0 \n"); - #endif - /* Q back all outstanding srb into wait exec psrb Q*/ - pfreesrb=pACB->pfreesrb; - for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) - { - pSRB=&pfreesrb[i]; - if(pSRB->startdone==ARCMSR_SRB_START) - { - pSRB->srb_flags|=SRB_FLAG_MASTER_ABORTED; - pSRB->pccb->ccb_h.status=CAM_REQ_ABORTED; - abort_cmd_cnt++; - } + 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(abort_cmd_cnt!=0) - { - #if ARCMSR_DEBUG0 - printf("arcmsr_pcidev_disattach: .....abort_cmd_cnt!=0 \n"); - #endif - arcmsr_abort_allcmd(pACB); - if(arcmsr_wait_msgint_ready(pACB)!=TRUE) - { - printf("arcmsr_pcidev_disattach: wait 'abort all outstanding command' timeout.................in \n"); + if(acb->srboutstandingcount!=0) { + arcmsr_abort_allcmd(acb); + /*clear all outbound posted Q*/ + for(i=0;i<ARCMSR_MAX_OUTSTANDING_CMD;i++) { + CHIP_REG_READ32(outbound_queueport); } - } - atomic_set_int(&pACB->srboutstandingcount,0); - } - if(pACB->srbwait2gocount!=0) - { /*remove first wait2go srb and abort it*/ - for(i=0;i<ARCMSR_MAX_OUTSTANDING_CMD;i++) - { - pSRB=pACB->psrbwait2go[i]; - if(pSRB!=NULL) - { - pACB->psrbwait2go[i]=NULL; - atomic_subtract_int(&pACB->srbwait2gocount,1); - pSRB->pccb->ccb_h.status=CAM_REQ_ABORTED; - arcmsr_srb_complete(pSRB); + for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { + srb=acb->psrb_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); + } } } } - splx(s); -#if 0 - pACB->acb_flags |= ACB_F_STOP_THREAD; - wakeup(pACB->kthread_proc);/* signal to kernel thread do_dpcQ: "stop thread" */ -#endif - return; + atomic_set_int(&acb->srboutstandingcount, 0); + acb->workingsrb_doneindex=0; + acb->workingsrb_startindex=0; + return; } /* ************************************************************************ -** -** -** ************************************************************************ */ -static LONG arcmsr_detach(device_t dev) +static u_int32_t arcmsr_detach(device_t dev) { - PACB pACB=device_get_softc(dev); + struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); arcmsr_shutdown(dev); - arcmsr_free_resource(pACB); - bus_release_resource(dev, SYS_RES_MEMORY, PCI_BASE_ADDR0, pACB->sys_res_arcmsr); - bus_teardown_intr(dev, pACB->irqres, pACB->ih); - bus_release_resource(dev, SYS_RES_IRQ, 0, pACB->irqres); - xpt_async(AC_LOST_DEVICE, pACB->ppath, NULL); - xpt_free_path(pACB->ppath); - xpt_bus_deregister(cam_sim_path(pACB->psim)); - cam_sim_free(pACB->psim, TRUE); + arcmsr_free_resource(acb); + bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0), acb->sys_res_arcmsr); + bus_teardown_intr(dev, acb->irqres, acb->ih); + bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); + xpt_async(AC_LOST_DEVICE, acb->ppath, NULL); + xpt_free_path(acb->ppath); + xpt_bus_deregister(cam_sim_path(acb->psim)); + cam_sim_free(acb->psim, TRUE); return (0); } - |