1f1c579b1SScott Long /* 246a7789eSMatt Jacob ***************************************************************************************** 3f1c579b1SScott Long ** O.S : FreeBSD 4f1c579b1SScott Long ** FILE NAME : arcmsr.c 5f1c579b1SScott Long ** BY : Erich Chen 6f1c579b1SScott Long ** Description: SCSI RAID Device Driver for 7ad6d6297SScott Long ** ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX) SATA/SAS RAID HOST Adapter 8ad6d6297SScott Long ** ARCMSR RAID Host adapter 9ad6d6297SScott Long ** [RAID controller:INTEL 331(PCI-X) 341(PCI-EXPRESS) chip set] 10f1c579b1SScott Long ****************************************************************************************** 11f1c579b1SScott Long ************************************************************************ 12f1c579b1SScott Long ** 13f1c579b1SScott Long ** Copyright (c) 2004-2006 ARECA Co. Ltd. 14f1c579b1SScott Long ** Erich Chen, Taipei Taiwan All rights reserved. 15f1c579b1SScott Long ** 16f1c579b1SScott Long ** Redistribution and use in source and binary forms, with or without 17f1c579b1SScott Long ** modification, are permitted provided that the following conditions 18f1c579b1SScott Long ** are met: 19f1c579b1SScott Long ** 1. Redistributions of source code must retain the above copyright 20f1c579b1SScott Long ** notice, this list of conditions and the following disclaimer. 21f1c579b1SScott Long ** 2. Redistributions in binary form must reproduce the above copyright 22f1c579b1SScott Long ** notice, this list of conditions and the following disclaimer in the 23f1c579b1SScott Long ** documentation and/or other materials provided with the distribution. 24f1c579b1SScott Long ** 3. The name of the author may not be used to endorse or promote products 25f1c579b1SScott Long ** derived from this software without specific prior written permission. 26f1c579b1SScott Long ** 27f1c579b1SScott Long ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 28f1c579b1SScott Long ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 29f1c579b1SScott Long ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 30f1c579b1SScott Long ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 31f1c579b1SScott Long ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT 32f1c579b1SScott Long ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33f1c579b1SScott Long ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY 34f1c579b1SScott Long ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35f1c579b1SScott Long **(INCLUDING NEGLIGENCE OR OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF 36f1c579b1SScott Long ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37f1c579b1SScott Long ************************************************************************** 38f1c579b1SScott Long ** History 39f1c579b1SScott Long ** 40f1c579b1SScott Long ** REV# DATE NAME DESCRIPTION 41f1c579b1SScott Long ** 1.00.00.00 3/31/2004 Erich Chen First release 42f1c579b1SScott Long ** 1.20.00.02 11/29/2004 Erich Chen bug fix with arcmsr_bus_reset when PHY error 43ad6d6297SScott Long ** 1.20.00.03 4/19/2005 Erich Chen add SATA 24 Ports adapter type support 44ad6d6297SScott Long ** clean unused function 45ad6d6297SScott Long ** 1.20.00.12 9/12/2005 Erich Chen bug fix with abort command handling, 46ad6d6297SScott Long ** firmware version check 47ad6d6297SScott Long ** and firmware update notify for hardware bug fix 48ad6d6297SScott Long ** handling if none zero high part physical address 49ad6d6297SScott Long ** of srb resource 50ad6d6297SScott Long ** 1.20.00.13 8/18/2006 Erich Chen remove pending srb and report busy 51ad6d6297SScott Long ** add iop message xfer 52ad6d6297SScott Long ** with scsi pass-through command 53ad6d6297SScott Long ** add new device id of sas raid adapters 54ad6d6297SScott Long ** code fit for SPARC64 & PPC 55f48f00a1SScott Long ** 1.20.00.14 02/05/2007 Erich Chen bug fix for incorrect ccb_h.status report 56f48f00a1SScott Long ** and cause g_vfs_done() read write error 5744f05562SScott Long ** 1.20.00.15 10/10/2007 Erich Chen support new RAID adapter type ARC120x 58f1c579b1SScott Long ****************************************************************************************** 59ad6d6297SScott Long * $FreeBSD$ 60f1c579b1SScott Long */ 61f1c579b1SScott Long #include <sys/param.h> 62f1c579b1SScott Long #include <sys/systm.h> 63f1c579b1SScott Long #include <sys/malloc.h> 64f1c579b1SScott Long #include <sys/kernel.h> 65f1c579b1SScott Long #include <sys/bus.h> 66f1c579b1SScott Long #include <sys/queue.h> 67f1c579b1SScott Long #include <sys/stat.h> 68f1c579b1SScott Long #include <sys/devicestat.h> 69f1c579b1SScott Long #include <sys/kthread.h> 70f1c579b1SScott Long #include <sys/module.h> 71f1c579b1SScott Long #include <sys/proc.h> 72f1c579b1SScott Long #include <sys/lock.h> 73f1c579b1SScott Long #include <sys/sysctl.h> 74f1c579b1SScott Long #include <sys/poll.h> 75f1c579b1SScott Long #include <sys/ioccom.h> 76f1c579b1SScott Long #include <vm/vm.h> 77f1c579b1SScott Long #include <vm/vm_param.h> 78f1c579b1SScott Long #include <vm/pmap.h> 79f1c579b1SScott Long 80f1c579b1SScott Long #include <isa/rtc.h> 81f1c579b1SScott Long 82f1c579b1SScott Long #include <machine/bus.h> 83f1c579b1SScott Long #include <machine/resource.h> 84f1c579b1SScott Long #include <machine/atomic.h> 85f1c579b1SScott Long #include <sys/conf.h> 86f1c579b1SScott Long #include <sys/rman.h> 87f1c579b1SScott Long 88f1c579b1SScott Long #include <cam/cam.h> 89f1c579b1SScott Long #include <cam/cam_ccb.h> 90f1c579b1SScott Long #include <cam/cam_sim.h> 91f1c579b1SScott Long #include <cam/cam_xpt_sim.h> 92f1c579b1SScott Long #include <cam/cam_debug.h> 93f1c579b1SScott Long #include <cam/scsi/scsi_all.h> 94f1c579b1SScott Long #include <cam/scsi/scsi_message.h> 95f1c579b1SScott Long /* 96f1c579b1SScott Long ************************************************************************** 97f1c579b1SScott Long ************************************************************************** 98f1c579b1SScott Long */ 99f1c579b1SScott Long #if __FreeBSD_version >= 500005 100f1c579b1SScott Long #include <sys/selinfo.h> 101f1c579b1SScott Long #include <sys/mutex.h> 102ad6d6297SScott Long #include <sys/endian.h> 103f1c579b1SScott Long #include <dev/pci/pcivar.h> 104f1c579b1SScott Long #include <dev/pci/pcireg.h> 105579ec1a5SScott Long #define ARCMSR_LOCK_INIT(l, s) mtx_init(l, s, NULL, MTX_DEF) 1065878cbecSScott Long #define ARCMSR_LOCK_DESTROY(l) mtx_destroy(l) 107f1c579b1SScott Long #define ARCMSR_LOCK_ACQUIRE(l) mtx_lock(l) 108f1c579b1SScott Long #define ARCMSR_LOCK_RELEASE(l) mtx_unlock(l) 109ad6d6297SScott Long #define ARCMSR_LOCK_TRY(l) mtx_trylock(l) 110ad6d6297SScott Long #define arcmsr_htole32(x) htole32(x) 111f1c579b1SScott Long typedef struct mtx arcmsr_lock_t; 112f1c579b1SScott Long #else 113f1c579b1SScott Long #include <sys/select.h> 114f1c579b1SScott Long #include <pci/pcivar.h> 115f1c579b1SScott Long #include <pci/pcireg.h> 116f1c579b1SScott Long #define ARCMSR_LOCK_INIT(l, s) simple_lock_init(l) 1175878cbecSScott Long #define ARCMSR_LOCK_DESTROY(l) 118f1c579b1SScott Long #define ARCMSR_LOCK_ACQUIRE(l) simple_lock(l) 119f1c579b1SScott Long #define ARCMSR_LOCK_RELEASE(l) simple_unlock(l) 120ad6d6297SScott Long #define ARCMSR_LOCK_TRY(l) simple_lock_try(l) 121ad6d6297SScott Long #define arcmsr_htole32(x) (x) 122f1c579b1SScott Long typedef struct simplelock arcmsr_lock_t; 123f1c579b1SScott Long #endif 12444f05562SScott Long 12544f05562SScott Long #if !defined(CAM_NEW_TRAN_CODE) && __FreeBSD_version >= 700025 12644f05562SScott Long #define CAM_NEW_TRAN_CODE 1 12744f05562SScott Long #endif 12844f05562SScott Long 129f1c579b1SScott Long #include <dev/arcmsr/arcmsr.h> 13044f05562SScott Long #define ARCMSR_SRBS_POOL_SIZE ((sizeof(struct CommandControlBlock) * ARCMSR_MAX_FREESRB_NUM)) 131f1c579b1SScott Long /* 132f1c579b1SScott Long ************************************************************************** 133f1c579b1SScott Long ************************************************************************** 134f1c579b1SScott Long */ 13544f05562SScott Long #define CHIP_REG_READ32(s, b, r) bus_space_read_4(acb->btag[b], acb->bhandle[b], offsetof(struct s, r)) 13644f05562SScott Long #define CHIP_REG_WRITE32(s, b, r, d) bus_space_write_4(acb->btag[b], acb->bhandle[b], offsetof(struct s, r), d) 137f1c579b1SScott Long /* 138f1c579b1SScott Long ************************************************************************** 139f1c579b1SScott Long ************************************************************************** 140f1c579b1SScott Long */ 141ad6d6297SScott Long static struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb); 142ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb); 143f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev); 144f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev); 145f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev); 146ad6d6297SScott Long static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg); 147ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb); 148f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev); 14944f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb); 150ad6d6297SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb); 151ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb); 152ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb); 153ad6d6297SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); 154ad6d6297SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb); 155ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb); 156ad6d6297SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb); 15744f05562SScott Long static void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb); 158ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb); 159ad6d6297SScott Long static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag); 160ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb); 161ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb); 162ad6d6297SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t * dm_segs, u_int32_t nseg); 163ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb); 164ad6d6297SScott Long static int arcmsr_resume(device_t dev); 165ad6d6297SScott Long static int arcmsr_suspend(device_t dev); 166f1c579b1SScott Long /* 167f1c579b1SScott Long ************************************************************************** 168ad6d6297SScott Long ************************************************************************** 169ad6d6297SScott Long */ 170ad6d6297SScott Long static void UDELAY(u_int32_t us) { DELAY(us); } 171ad6d6297SScott Long /* 172ad6d6297SScott Long ************************************************************************** 173f1c579b1SScott Long ************************************************************************** 174f1c579b1SScott Long */ 175f1c579b1SScott Long static bus_dmamap_callback_t arcmsr_map_freesrb; 176f1c579b1SScott Long static bus_dmamap_callback_t arcmsr_executesrb; 177f1c579b1SScott Long /* 178f1c579b1SScott Long ************************************************************************** 179f1c579b1SScott Long ************************************************************************** 180f1c579b1SScott Long */ 181f1c579b1SScott Long static d_open_t arcmsr_open; 182f1c579b1SScott Long static d_close_t arcmsr_close; 183f1c579b1SScott Long static d_ioctl_t arcmsr_ioctl; 184f1c579b1SScott Long 185f1c579b1SScott Long static device_method_t arcmsr_methods[]={ 186f1c579b1SScott Long DEVMETHOD(device_probe, arcmsr_probe), 187f1c579b1SScott Long DEVMETHOD(device_attach, arcmsr_attach), 188f1c579b1SScott Long DEVMETHOD(device_detach, arcmsr_detach), 189f1c579b1SScott Long DEVMETHOD(device_shutdown, arcmsr_shutdown), 190ad6d6297SScott Long DEVMETHOD(device_suspend, arcmsr_suspend), 191ad6d6297SScott Long DEVMETHOD(device_resume, arcmsr_resume), 192ad6d6297SScott Long 193ad6d6297SScott Long DEVMETHOD(bus_print_child, bus_generic_print_child), 194ad6d6297SScott Long DEVMETHOD(bus_driver_added, bus_generic_driver_added), 195f1c579b1SScott Long { 0, 0 } 196f1c579b1SScott Long }; 197f1c579b1SScott Long 198f1c579b1SScott Long static driver_t arcmsr_driver={ 199ad6d6297SScott Long "arcmsr", arcmsr_methods, sizeof(struct AdapterControlBlock) 200f1c579b1SScott Long }; 201f1c579b1SScott Long 202f1c579b1SScott Long static devclass_t arcmsr_devclass; 203f1c579b1SScott Long DRIVER_MODULE(arcmsr, pci, arcmsr_driver, arcmsr_devclass, 0, 0); 204d3cf342dSScott Long MODULE_DEPEND(arcmsr, pci, 1, 1, 1); 205d3cf342dSScott Long MODULE_DEPEND(arcmsr, cam, 1, 1, 1); 206ad6d6297SScott Long #ifndef BUS_DMA_COHERENT 207ad6d6297SScott Long #define BUS_DMA_COHERENT 0x04 /* hint: map memory in a coherent way */ 208ad6d6297SScott Long #endif 209ad6d6297SScott Long #if __FreeBSD_version >= 501000 210ad6d6297SScott Long #ifndef D_NEEDGIANT 211ad6d6297SScott Long #define D_NEEDGIANT 0x00400000 /* driver want Giant */ 212ad6d6297SScott Long #endif 213ad6d6297SScott Long #ifndef D_VERSION 214ad6d6297SScott Long #define D_VERSION 0x20011966 215ad6d6297SScott Long #endif 216f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw={ 217ad6d6297SScott Long #if __FreeBSD_version > 502010 218f1c579b1SScott Long .d_version = D_VERSION, 219ad6d6297SScott Long #endif 220f1c579b1SScott Long .d_flags = D_NEEDGIANT, 221f1c579b1SScott Long .d_open = arcmsr_open, /* open */ 222f1c579b1SScott Long .d_close = arcmsr_close, /* close */ 223f1c579b1SScott Long .d_ioctl = arcmsr_ioctl, /* ioctl */ 224f1c579b1SScott Long .d_name = "arcmsr", /* name */ 225f1c579b1SScott Long }; 226f1c579b1SScott Long #else 227f1c579b1SScott Long #define ARCMSR_CDEV_MAJOR 180 228f1c579b1SScott Long 229f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw = { 230f1c579b1SScott Long arcmsr_open, /* open */ 231f1c579b1SScott Long arcmsr_close, /* close */ 232f1c579b1SScott Long noread, /* read */ 233f1c579b1SScott Long nowrite, /* write */ 234f1c579b1SScott Long arcmsr_ioctl, /* ioctl */ 235f1c579b1SScott Long nopoll, /* poll */ 236f1c579b1SScott Long nommap, /* mmap */ 237f1c579b1SScott Long nostrategy, /* strategy */ 238f1c579b1SScott Long "arcmsr", /* name */ 239f1c579b1SScott Long ARCMSR_CDEV_MAJOR, /* major */ 240f1c579b1SScott Long nodump, /* dump */ 241f1c579b1SScott Long nopsize, /* psize */ 242f1c579b1SScott Long 0 /* flags */ 243f1c579b1SScott Long }; 244f1c579b1SScott Long #endif 245f1c579b1SScott Long 246f1c579b1SScott Long #if __FreeBSD_version < 500005 247f1c579b1SScott Long static int arcmsr_open(dev_t dev, int flags, int fmt, struct proc *proc) 248f1c579b1SScott Long #else 249f1c579b1SScott Long #if __FreeBSD_version < 503000 250f1c579b1SScott Long static int arcmsr_open(dev_t dev, int flags, int fmt, struct thread *proc) 251f1c579b1SScott Long #else 252f1c579b1SScott Long static int arcmsr_open(struct cdev *dev, int flags, int fmt, d_thread_t *proc) 253f1c579b1SScott Long #endif 254f1c579b1SScott Long #endif 255f1c579b1SScott Long { 256f1c579b1SScott Long #if __FreeBSD_version < 503000 257ad6d6297SScott Long struct AdapterControlBlock *acb=dev->si_drv1; 258f1c579b1SScott Long #else 2596bfa9a2dSEd Schouten int unit = dev2unit(dev); 260ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 261f1c579b1SScott Long #endif 262ad6d6297SScott Long if(acb==NULL) { 263f1c579b1SScott Long return ENXIO; 264f1c579b1SScott Long } 265f1c579b1SScott Long return 0; 266f1c579b1SScott Long } 267f1c579b1SScott Long /* 268f1c579b1SScott Long ************************************************************************** 269f1c579b1SScott Long ************************************************************************** 270f1c579b1SScott Long */ 271f1c579b1SScott Long #if __FreeBSD_version < 500005 272f1c579b1SScott Long static int arcmsr_close(dev_t dev, int flags, int fmt, struct proc *proc) 273f1c579b1SScott Long #else 274f1c579b1SScott Long #if __FreeBSD_version < 503000 275f1c579b1SScott Long static int arcmsr_close(dev_t dev, int flags, int fmt, struct thread *proc) 276f1c579b1SScott Long #else 277f1c579b1SScott Long static int arcmsr_close(struct cdev *dev, int flags, int fmt, d_thread_t *proc) 278f1c579b1SScott Long #endif 279f1c579b1SScott Long #endif 280f1c579b1SScott Long { 281f1c579b1SScott Long #if __FreeBSD_version < 503000 282ad6d6297SScott Long struct AdapterControlBlock *acb=dev->si_drv1; 283f1c579b1SScott Long #else 2846bfa9a2dSEd Schouten int unit = dev2unit(dev); 285ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 286f1c579b1SScott Long #endif 287ad6d6297SScott Long if(acb==NULL) { 288f1c579b1SScott Long return ENXIO; 289f1c579b1SScott Long } 290f1c579b1SScott Long return 0; 291f1c579b1SScott Long } 292f1c579b1SScott Long /* 293f1c579b1SScott Long ************************************************************************** 294f1c579b1SScott Long ************************************************************************** 295f1c579b1SScott Long */ 296f1c579b1SScott Long #if __FreeBSD_version < 500005 297f1c579b1SScott Long static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct proc *proc) 298f1c579b1SScott Long #else 299f1c579b1SScott Long #if __FreeBSD_version < 503000 300f1c579b1SScott Long static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc) 301f1c579b1SScott Long #else 302f1c579b1SScott Long static int arcmsr_ioctl(struct cdev *dev, u_long ioctl_cmd, caddr_t arg, int flags, d_thread_t *proc) 303f1c579b1SScott Long #endif 304f1c579b1SScott Long #endif 305f1c579b1SScott Long { 306f1c579b1SScott Long #if __FreeBSD_version < 503000 307ad6d6297SScott Long struct AdapterControlBlock *acb=dev->si_drv1; 308f1c579b1SScott Long #else 3096bfa9a2dSEd Schouten int unit = dev2unit(dev); 310ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 311f1c579b1SScott Long #endif 312f1c579b1SScott Long 313ad6d6297SScott Long if(acb==NULL) { 314f1c579b1SScott Long return ENXIO; 315f1c579b1SScott Long } 316ad6d6297SScott Long return(arcmsr_iop_ioctlcmd(acb, ioctl_cmd, arg)); 317f1c579b1SScott Long } 318f1c579b1SScott Long /* 31944f05562SScott Long ********************************************************************** 32044f05562SScott Long ********************************************************************** 32144f05562SScott Long */ 32244f05562SScott Long static u_int32_t arcmsr_disable_allintr( struct AdapterControlBlock *acb) 32344f05562SScott Long { 32444f05562SScott Long u_int32_t intmask_org=0; 32544f05562SScott Long 32644f05562SScott Long switch (acb->adapter_type) { 32744f05562SScott Long case ACB_ADAPTER_TYPE_A: { 32844f05562SScott Long /* disable all outbound interrupt */ 32944f05562SScott Long intmask_org=CHIP_REG_READ32(HBA_MessageUnit, 33044f05562SScott Long 0, outbound_intmask)|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE; /* disable outbound message0 int */ 33144f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 33244f05562SScott Long 0, outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); 33344f05562SScott Long } 33444f05562SScott Long break; 33544f05562SScott Long case ACB_ADAPTER_TYPE_B: { 33644f05562SScott Long /* disable all outbound interrupt */ 33744f05562SScott Long intmask_org=CHIP_REG_READ32(HBB_DOORBELL, 33844f05562SScott Long 0, iop2drv_doorbell_mask) & (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); /* disable outbound message0 int */ 33944f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 34044f05562SScott Long 0, iop2drv_doorbell_mask, 0); /* disable all interrupt */ 34144f05562SScott Long } 34244f05562SScott Long break; 34344f05562SScott Long } 34444f05562SScott Long return(intmask_org); 34544f05562SScott Long } 34644f05562SScott Long /* 34744f05562SScott Long ********************************************************************** 34844f05562SScott Long ********************************************************************** 34944f05562SScott Long */ 35044f05562SScott Long static void arcmsr_enable_allintr( struct AdapterControlBlock *acb, u_int32_t intmask_org) 35144f05562SScott Long { 35244f05562SScott Long u_int32_t mask; 35344f05562SScott Long 35444f05562SScott Long switch (acb->adapter_type) { 35544f05562SScott Long case ACB_ADAPTER_TYPE_A: { 35644f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 35744f05562SScott Long mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); 35844f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org & mask); 35944f05562SScott Long acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; 36044f05562SScott Long } 36144f05562SScott Long break; 36244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 36344f05562SScott Long /* disable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */ 36444f05562SScott Long mask=(ARCMSR_IOP2DRV_DATA_WRITE_OK|ARCMSR_IOP2DRV_DATA_READ_OK|ARCMSR_IOP2DRV_CDB_DONE); 36544f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 36644f05562SScott Long 0, iop2drv_doorbell_mask, intmask_org | mask); /*1=interrupt enable, 0=interrupt disable*/ 36744f05562SScott Long acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f; 36844f05562SScott Long } 36944f05562SScott Long break; 37044f05562SScott Long } 37144f05562SScott Long return; 37244f05562SScott Long } 37344f05562SScott Long /* 37444f05562SScott Long ********************************************************************** 37544f05562SScott Long ********************************************************************** 37644f05562SScott Long */ 37744f05562SScott Long static u_int8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) 37844f05562SScott Long { 37944f05562SScott Long u_int32_t Index; 38044f05562SScott Long u_int8_t Retries=0x00; 38144f05562SScott Long 38244f05562SScott Long do { 38344f05562SScott Long for(Index=0; Index < 100; Index++) { 38444f05562SScott Long if(CHIP_REG_READ32(HBA_MessageUnit, 38544f05562SScott Long 0, outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { 38644f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 38744f05562SScott Long 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/ 38844f05562SScott Long return TRUE; 38944f05562SScott Long } 39044f05562SScott Long UDELAY(10000); 39144f05562SScott Long }/*max 1 seconds*/ 39244f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 39344f05562SScott Long return FALSE; 39444f05562SScott Long } 39544f05562SScott Long /* 39644f05562SScott Long ********************************************************************** 39744f05562SScott Long ********************************************************************** 39844f05562SScott Long */ 39944f05562SScott Long static u_int8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) 40044f05562SScott Long { 40144f05562SScott Long u_int32_t Index; 40244f05562SScott Long u_int8_t Retries=0x00; 40344f05562SScott Long 40444f05562SScott Long do { 40544f05562SScott Long for(Index=0; Index < 100; Index++) { 40644f05562SScott Long if(CHIP_REG_READ32(HBB_DOORBELL, 40744f05562SScott Long 0, iop2drv_doorbell) & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { 40844f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 40944f05562SScott Long 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/ 41044f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 41144f05562SScott Long 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 41244f05562SScott Long return TRUE; 41344f05562SScott Long } 41444f05562SScott Long UDELAY(10000); 41544f05562SScott Long }/*max 1 seconds*/ 41644f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 41744f05562SScott Long return FALSE; 41844f05562SScott Long } 41944f05562SScott Long /* 42044f05562SScott Long ************************************************************************ 42144f05562SScott Long ************************************************************************ 42244f05562SScott Long */ 42344f05562SScott Long static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) 42444f05562SScott Long { 42544f05562SScott Long int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */ 42644f05562SScott Long 42744f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 42844f05562SScott Long 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 42944f05562SScott Long do { 43044f05562SScott Long if(arcmsr_hba_wait_msgint_ready(acb)) { 43144f05562SScott Long break; 43244f05562SScott Long } else { 43344f05562SScott Long retry_count--; 43444f05562SScott Long } 43544f05562SScott Long }while(retry_count!=0); 43644f05562SScott Long return; 43744f05562SScott Long } 43844f05562SScott Long /* 43944f05562SScott Long ************************************************************************ 44044f05562SScott Long ************************************************************************ 44144f05562SScott Long */ 44244f05562SScott Long static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) 44344f05562SScott Long { 44444f05562SScott Long int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */ 44544f05562SScott Long 44644f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 44744f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_FLUSH_CACHE); 44844f05562SScott Long do { 44944f05562SScott Long if(arcmsr_hbb_wait_msgint_ready(acb)) { 45044f05562SScott Long break; 45144f05562SScott Long } else { 45244f05562SScott Long retry_count--; 45344f05562SScott Long } 45444f05562SScott Long }while(retry_count!=0); 45544f05562SScott Long return; 45644f05562SScott Long } 45744f05562SScott Long /* 45844f05562SScott Long ************************************************************************ 45944f05562SScott Long ************************************************************************ 46044f05562SScott Long */ 46144f05562SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) 46244f05562SScott Long { 46344f05562SScott Long switch (acb->adapter_type) { 46444f05562SScott Long case ACB_ADAPTER_TYPE_A: { 46544f05562SScott Long arcmsr_flush_hba_cache(acb); 46644f05562SScott Long } 46744f05562SScott Long break; 46844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 46944f05562SScott Long arcmsr_flush_hbb_cache(acb); 47044f05562SScott Long } 47144f05562SScott Long break; 47244f05562SScott Long } 47344f05562SScott Long return; 47444f05562SScott Long } 47544f05562SScott Long /* 476ad6d6297SScott Long ******************************************************************************* 477ad6d6297SScott Long ******************************************************************************* 478f1c579b1SScott Long */ 479ad6d6297SScott Long static int arcmsr_suspend(device_t dev) 480f1c579b1SScott Long { 481ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 482f1c579b1SScott Long 483ad6d6297SScott Long /* disable all outbound interrupt */ 48444f05562SScott Long arcmsr_disable_allintr(acb); 485ad6d6297SScott Long /* flush controller */ 486ad6d6297SScott Long arcmsr_iop_parking(acb); 487ad6d6297SScott Long return(0); 488ad6d6297SScott Long } 489ad6d6297SScott Long /* 490ad6d6297SScott Long ******************************************************************************* 491ad6d6297SScott Long ******************************************************************************* 492ad6d6297SScott Long */ 493ad6d6297SScott Long static int arcmsr_resume(device_t dev) 494ad6d6297SScott Long { 495ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 496f1c579b1SScott Long 497ad6d6297SScott Long arcmsr_iop_init(acb); 498ad6d6297SScott Long return(0); 499f1c579b1SScott Long } 500f1c579b1SScott Long /* 501f1c579b1SScott Long ********************************************************************************* 502f1c579b1SScott Long ********************************************************************************* 503f1c579b1SScott Long */ 504ad6d6297SScott Long static void arcmsr_async(void *cb_arg, u_int32_t code, struct cam_path *path, void *arg) 505f1c579b1SScott Long { 506ad6d6297SScott Long struct AdapterControlBlock *acb; 507ad6d6297SScott Long u_int8_t target_id, target_lun; 508f1c579b1SScott Long struct cam_sim * sim; 509f1c579b1SScott Long 510f1c579b1SScott Long sim=(struct cam_sim *) cb_arg; 511ad6d6297SScott Long acb =(struct AdapterControlBlock *) cam_sim_softc(sim); 512ad6d6297SScott Long switch (code) { 513f1c579b1SScott Long case AC_LOST_DEVICE: 514f1c579b1SScott Long target_id=xpt_path_target_id(path); 515f1c579b1SScott Long target_lun=xpt_path_lun_id(path); 51644f05562SScott Long if((target_id > ARCMSR_MAX_TARGETID) 51744f05562SScott Long || (target_lun > ARCMSR_MAX_TARGETLUN)) { 518f1c579b1SScott Long break; 519f1c579b1SScott Long } 520ad6d6297SScott Long printf("%s:scsi id%d lun%d device lost \n" 521ad6d6297SScott Long , device_get_name(acb->pci_dev), target_id, target_lun); 522f1c579b1SScott Long break; 523f1c579b1SScott Long default: 524f1c579b1SScott Long break; 525f1c579b1SScott Long } 526f1c579b1SScott Long } 527f1c579b1SScott Long /* 528f1c579b1SScott Long ********************************************************************** 529f1c579b1SScott Long ********************************************************************** 530f1c579b1SScott Long */ 531ad6d6297SScott Long static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag) 532f1c579b1SScott Long { 533ad6d6297SScott Long struct AdapterControlBlock *acb=srb->acb; 534ad6d6297SScott Long union ccb * pccb=srb->pccb; 535f1c579b1SScott Long 536ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 537f1c579b1SScott Long bus_dmasync_op_t op; 538f1c579b1SScott Long 539ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 540f1c579b1SScott Long op = BUS_DMASYNC_POSTREAD; 541ad6d6297SScott Long } else { 542f1c579b1SScott Long op = BUS_DMASYNC_POSTWRITE; 543f1c579b1SScott Long } 544ad6d6297SScott Long bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 545ad6d6297SScott Long bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 546f1c579b1SScott Long } 547ad6d6297SScott Long if(stand_flag==1) { 548ad6d6297SScott Long atomic_subtract_int(&acb->srboutstandingcount, 1); 549dc3a205bSScott Long if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) && ( 550dc3a205bSScott Long acb->srboutstandingcount < ARCMSR_RELEASE_SIMQ_LEVEL)) { 551dc3a205bSScott Long acb->acb_flags &= ~ACB_F_CAM_DEV_QFRZN; 552dc3a205bSScott Long pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 553dc3a205bSScott Long } 554ad6d6297SScott Long } 555ad6d6297SScott Long srb->startdone=ARCMSR_SRB_DONE; 556ad6d6297SScott Long srb->srb_flags=0; 557ad6d6297SScott Long acb->srbworkingQ[acb->workingsrb_doneindex]=srb; 558ad6d6297SScott Long acb->workingsrb_doneindex++; 559ad6d6297SScott Long acb->workingsrb_doneindex %= ARCMSR_MAX_FREESRB_NUM; 560f1c579b1SScott Long xpt_done(pccb); 561f1c579b1SScott Long return; 562f1c579b1SScott Long } 563f1c579b1SScott Long /* 564f1c579b1SScott Long ********************************************************************** 565f1c579b1SScott Long ********************************************************************** 566f1c579b1SScott Long */ 567ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb) 568f1c579b1SScott Long { 569ad6d6297SScott Long union ccb * pccb=srb->pccb; 570f1c579b1SScott Long 571ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 572ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 573ad6d6297SScott Long if(&pccb->csio.sense_data) { 574ad6d6297SScott Long memset(&pccb->csio.sense_data, 0, sizeof(pccb->csio.sense_data)); 575ad6d6297SScott Long memcpy(&pccb->csio.sense_data, srb->arcmsr_cdb.SenseData, 576ad6d6297SScott Long get_min(sizeof(struct SENSE_DATA), sizeof(pccb->csio.sense_data))); 577ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); /* Valid,ErrorCode */ 578f1c579b1SScott Long pccb->ccb_h.status |= CAM_AUTOSNS_VALID; 579f1c579b1SScott Long } 580f1c579b1SScott Long return; 581f1c579b1SScott Long } 582f1c579b1SScott Long /* 583f1c579b1SScott Long ********************************************************************* 58444f05562SScott Long ********************************************************************* 58544f05562SScott Long */ 58644f05562SScott Long static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) 58744f05562SScott Long { 58844f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 58944f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 59044f05562SScott Long printf("arcmsr%d: wait 'abort all outstanding command' timeout \n" 59144f05562SScott Long , acb->pci_unit); 59244f05562SScott Long } 59344f05562SScott Long return; 59444f05562SScott Long } 59544f05562SScott Long /* 59644f05562SScott Long ********************************************************************* 59744f05562SScott Long ********************************************************************* 59844f05562SScott Long */ 59944f05562SScott Long static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) 60044f05562SScott Long { 60144f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_ABORT_CMD); 60244f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 60344f05562SScott Long printf("arcmsr%d: wait 'abort all outstanding command' timeout \n" 60444f05562SScott Long , acb->pci_unit); 60544f05562SScott Long } 60644f05562SScott Long return; 60744f05562SScott Long } 60844f05562SScott Long /* 60944f05562SScott Long ********************************************************************* 610f1c579b1SScott Long ********************************************************************* 611f1c579b1SScott Long */ 612ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) 613f1c579b1SScott Long { 61444f05562SScott Long switch (acb->adapter_type) { 61544f05562SScott Long case ACB_ADAPTER_TYPE_A: { 61644f05562SScott Long arcmsr_abort_hba_allcmd(acb); 61744f05562SScott Long } 61844f05562SScott Long break; 61944f05562SScott Long case ACB_ADAPTER_TYPE_B: { 62044f05562SScott Long arcmsr_abort_hbb_allcmd(acb); 62144f05562SScott Long } 62244f05562SScott Long break; 62344f05562SScott Long } 62444f05562SScott Long return; 62544f05562SScott Long } 62644f05562SScott Long /* 62744f05562SScott Long ************************************************************************** 62844f05562SScott Long ************************************************************************** 62944f05562SScott Long */ 63044f05562SScott Long static void arcmsr_report_srb_state(struct AdapterControlBlock *acb, 63144f05562SScott Long struct CommandControlBlock *srb, u_int32_t flag_srb) 63244f05562SScott Long { 63344f05562SScott Long int target, lun; 63444f05562SScott Long 63544f05562SScott Long target=srb->pccb->ccb_h.target_id; 63644f05562SScott Long lun=srb->pccb->ccb_h.target_lun; 63744f05562SScott Long if((flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR)==0) { 63844f05562SScott Long if(acb->devstate[target][lun]==ARECA_RAID_GONE) { 63944f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GOOD; 64044f05562SScott Long } 64144f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_CMP; 64244f05562SScott Long arcmsr_srb_complete(srb, 1); 64344f05562SScott Long } else { 64444f05562SScott Long switch(srb->arcmsr_cdb.DeviceStatus) { 64544f05562SScott Long case ARCMSR_DEV_SELECT_TIMEOUT: { 64644f05562SScott Long if(acb->devstate[target][lun]==ARECA_RAID_GOOD) { 64744f05562SScott Long printf( "arcmsr%d: select timeout" 64844f05562SScott Long ", raid volume was kicked out \n" 649ad6d6297SScott Long , acb->pci_unit); 650ad6d6297SScott Long } 65144f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GONE; 65244f05562SScott Long srb->pccb->ccb_h.status |= CAM_SEL_TIMEOUT; 65344f05562SScott Long arcmsr_srb_complete(srb, 1); 65444f05562SScott Long } 65544f05562SScott Long break; 65644f05562SScott Long case ARCMSR_DEV_ABORTED: 65744f05562SScott Long case ARCMSR_DEV_INIT_FAIL: { 65844f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GONE; 65944f05562SScott Long srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 66044f05562SScott Long arcmsr_srb_complete(srb, 1); 66144f05562SScott Long } 66244f05562SScott Long break; 66344f05562SScott Long case SCSISTAT_CHECK_CONDITION: { 66444f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GOOD; 66544f05562SScott Long arcmsr_report_sense_info(srb); 66644f05562SScott Long arcmsr_srb_complete(srb, 1); 66744f05562SScott Long } 66844f05562SScott Long break; 66944f05562SScott Long default: 67044f05562SScott Long printf("arcmsr%d: scsi id=%d lun=%d" 67144f05562SScott Long "isr get command error done," 67244f05562SScott Long "but got unknow DeviceStatus=0x%x \n" 67344f05562SScott Long , acb->pci_unit, target, lun 67444f05562SScott Long ,srb->arcmsr_cdb.DeviceStatus); 67544f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GONE; 67644f05562SScott Long srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY; 67744f05562SScott Long /*unknow error or crc error just for retry*/ 67844f05562SScott Long arcmsr_srb_complete(srb, 1); 67944f05562SScott Long break; 68044f05562SScott Long } 68144f05562SScott Long } 68244f05562SScott Long return; 68344f05562SScott Long } 68444f05562SScott Long /* 68544f05562SScott Long ************************************************************************** 68644f05562SScott Long ************************************************************************** 68744f05562SScott Long */ 68844f05562SScott Long static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t flag_srb) 68944f05562SScott Long { 69044f05562SScott Long struct CommandControlBlock *srb; 69144f05562SScott Long 69244f05562SScott Long /* check if command done with no error*/ 69344f05562SScott Long srb=(struct CommandControlBlock *) 69444f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 69544f05562SScott Long if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) { 69644f05562SScott Long if(srb->startdone==ARCMSR_SRB_ABORTED) { 69744f05562SScott Long printf("arcmsr%d: srb='%p' isr got aborted command \n" 69844f05562SScott Long , acb->pci_unit, srb); 69944f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 70044f05562SScott Long arcmsr_srb_complete(srb, 1); 70144f05562SScott Long return; 70244f05562SScott Long } 70344f05562SScott Long printf("arcmsr%d: isr get an illegal srb command done" 70444f05562SScott Long "acb='%p' srb='%p' srbacb='%p' startdone=0x%x" 70544f05562SScott Long "srboutstandingcount=%d \n", 70644f05562SScott Long acb->pci_unit, acb, srb, srb->acb, 70744f05562SScott Long srb->startdone, acb->srboutstandingcount); 70844f05562SScott Long return; 70944f05562SScott Long } 71044f05562SScott Long arcmsr_report_srb_state(acb, srb, flag_srb); 71144f05562SScott Long return; 71244f05562SScott Long } 71344f05562SScott Long /* 71444f05562SScott Long ********************************************************************** 71544f05562SScott Long ********************************************************************** 71644f05562SScott Long */ 71744f05562SScott Long static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) 71844f05562SScott Long { 71944f05562SScott Long int i=0; 72044f05562SScott Long u_int32_t flag_srb; 72144f05562SScott Long 72244f05562SScott Long switch (acb->adapter_type) { 72344f05562SScott Long case ACB_ADAPTER_TYPE_A: { 72444f05562SScott Long u_int32_t outbound_intstatus; 72544f05562SScott Long 72644f05562SScott Long /*clear and abort all outbound posted Q*/ 72744f05562SScott Long outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 72844f05562SScott Long 0, outbound_intstatus) & acb->outbound_int_enable; 72944f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 73044f05562SScott Long 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/ 73144f05562SScott Long while(((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 73244f05562SScott Long 0, outbound_queueport)) != 0xFFFFFFFF) 73344f05562SScott Long && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { 73444f05562SScott Long arcmsr_drain_donequeue(acb, flag_srb); 73544f05562SScott Long } 73644f05562SScott Long } 73744f05562SScott Long break; 73844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 73944f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 74044f05562SScott Long 74144f05562SScott Long /*clear all outbound posted Q*/ 74244f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 74344f05562SScott Long 0, iop2drv_doorbell, 74444f05562SScott Long ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 74544f05562SScott Long for(i=0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) { 74644f05562SScott Long if((flag_srb=phbbmu->done_qbuffer[i])!=0) { 74744f05562SScott Long phbbmu->done_qbuffer[i]=0; 74844f05562SScott Long arcmsr_drain_donequeue(acb, flag_srb); 74944f05562SScott Long } 75044f05562SScott Long phbbmu->post_qbuffer[i]=0; 75144f05562SScott Long }/*drain reply FIFO*/ 75244f05562SScott Long phbbmu->doneq_index=0; 75344f05562SScott Long phbbmu->postq_index=0; 75444f05562SScott Long } 75544f05562SScott Long break; 75644f05562SScott Long } 757f1c579b1SScott Long return; 758f1c579b1SScott Long } 759f1c579b1SScott Long /* 760f1c579b1SScott Long **************************************************************************** 761f1c579b1SScott Long **************************************************************************** 762f1c579b1SScott Long */ 763ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb) 764f1c579b1SScott Long { 765ad6d6297SScott Long struct CommandControlBlock *srb; 76644f05562SScott Long u_int32_t intmask_org; 767ad6d6297SScott Long u_int32_t i=0; 768f1c579b1SScott Long 76944f05562SScott Long if(acb->srboutstandingcount>0) { 77044f05562SScott Long /* disable all outbound interrupt */ 77144f05562SScott Long intmask_org=arcmsr_disable_allintr(acb); 77244f05562SScott Long /*clear and abort all outbound posted Q*/ 77344f05562SScott Long arcmsr_done4abort_postqueue(acb); 774f1c579b1SScott Long /* talk to iop 331 outstanding command aborted*/ 775ad6d6297SScott Long arcmsr_abort_allcmd(acb); 776ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 777ad6d6297SScott Long srb=acb->psrb_pool[i]; 778ad6d6297SScott Long if(srb->startdone==ARCMSR_SRB_START) { 779ad6d6297SScott Long srb->startdone=ARCMSR_SRB_ABORTED; 780ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 781ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 782f1c579b1SScott Long } 783f1c579b1SScott Long } 784f1c579b1SScott Long /* enable all outbound interrupt */ 78544f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 786f1c579b1SScott Long } 787ad6d6297SScott Long atomic_set_int(&acb->srboutstandingcount, 0); 788ad6d6297SScott Long acb->workingsrb_doneindex=0; 789ad6d6297SScott Long acb->workingsrb_startindex=0; 790f1c579b1SScott Long return; 791f1c579b1SScott Long } 792f1c579b1SScott Long /* 793f1c579b1SScott Long ********************************************************************** 794f1c579b1SScott Long ********************************************************************** 795f1c579b1SScott Long */ 79644f05562SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, 79744f05562SScott Long bus_dma_segment_t *dm_segs, u_int32_t nseg) 798f1c579b1SScott Long { 799ad6d6297SScott Long struct ARCMSR_CDB * arcmsr_cdb= &srb->arcmsr_cdb; 800ad6d6297SScott Long u_int8_t * psge=(u_int8_t *)&arcmsr_cdb->u; 801ad6d6297SScott Long u_int32_t address_lo, address_hi; 802ad6d6297SScott Long union ccb * pccb=srb->pccb; 803f1c579b1SScott Long struct ccb_scsiio * pcsio= &pccb->csio; 804ad6d6297SScott Long u_int32_t arccdbsize=0x30; 805f1c579b1SScott Long 806ad6d6297SScott Long memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB)); 807ad6d6297SScott Long arcmsr_cdb->Bus=0; 808ad6d6297SScott Long arcmsr_cdb->TargetID=pccb->ccb_h.target_id; 809ad6d6297SScott Long arcmsr_cdb->LUN=pccb->ccb_h.target_lun; 810ad6d6297SScott Long arcmsr_cdb->Function=1; 811ad6d6297SScott Long arcmsr_cdb->CdbLength=(u_int8_t)pcsio->cdb_len; 81244f05562SScott Long arcmsr_cdb->Context=0; 813ad6d6297SScott Long bcopy(pcsio->cdb_io.cdb_bytes, arcmsr_cdb->Cdb, pcsio->cdb_len); 814ad6d6297SScott Long if(nseg != 0) { 815ad6d6297SScott Long struct AdapterControlBlock *acb=srb->acb; 816f1c579b1SScott Long bus_dmasync_op_t op; 817ad6d6297SScott Long u_int32_t length, i, cdb_sgcount=0; 818f1c579b1SScott Long 819ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 820ad6d6297SScott Long op=BUS_DMASYNC_PREREAD; 821ad6d6297SScott Long } else { 822ad6d6297SScott Long op=BUS_DMASYNC_PREWRITE; 823ad6d6297SScott Long arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_WRITE; 824ad6d6297SScott Long srb->srb_flags|=SRB_FLAG_WRITE; 825ad6d6297SScott Long } 826ad6d6297SScott Long bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 827ad6d6297SScott Long for(i=0;i<nseg;i++) { 828f1c579b1SScott Long /* Get the physical address of the current data pointer */ 829ad6d6297SScott Long length=arcmsr_htole32(dm_segs[i].ds_len); 830ad6d6297SScott Long address_lo=arcmsr_htole32(dma_addr_lo32(dm_segs[i].ds_addr)); 831ad6d6297SScott Long address_hi=arcmsr_htole32(dma_addr_hi32(dm_segs[i].ds_addr)); 832ad6d6297SScott Long if(address_hi==0) { 833ad6d6297SScott Long struct SG32ENTRY * pdma_sg=(struct SG32ENTRY *)psge; 834f1c579b1SScott Long pdma_sg->address=address_lo; 835f1c579b1SScott Long pdma_sg->length=length; 836ad6d6297SScott Long psge += sizeof(struct SG32ENTRY); 837ad6d6297SScott Long arccdbsize += sizeof(struct SG32ENTRY); 838ad6d6297SScott Long } else { 839ad6d6297SScott Long u_int32_t sg64s_size=0, tmplength=length; 840f1c579b1SScott Long 841ad6d6297SScott Long while(1) { 842ad6d6297SScott Long u_int64_t span4G, length0; 843ad6d6297SScott Long struct SG64ENTRY * pdma_sg=(struct SG64ENTRY *)psge; 844f1c579b1SScott Long 845ad6d6297SScott Long span4G=(u_int64_t)address_lo + tmplength; 846f1c579b1SScott Long pdma_sg->addresshigh=address_hi; 847f1c579b1SScott Long pdma_sg->address=address_lo; 848ad6d6297SScott Long if(span4G > 0x100000000) { 849f1c579b1SScott Long /*see if cross 4G boundary*/ 850f1c579b1SScott Long length0=0x100000000-address_lo; 851ad6d6297SScott Long pdma_sg->length=(u_int32_t)length0|IS_SG64_ADDR; 852f1c579b1SScott Long address_hi=address_hi+1; 853f1c579b1SScott Long address_lo=0; 854ad6d6297SScott Long tmplength=tmplength-(u_int32_t)length0; 855ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 856ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 857f1c579b1SScott Long cdb_sgcount++; 858ad6d6297SScott Long } else { 859f1c579b1SScott Long pdma_sg->length=tmplength|IS_SG64_ADDR; 860ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 861ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 862f1c579b1SScott Long break; 863f1c579b1SScott Long } 864f1c579b1SScott Long } 865f1c579b1SScott Long arccdbsize += sg64s_size; 866f1c579b1SScott Long } 867f1c579b1SScott Long cdb_sgcount++; 868f1c579b1SScott Long } 869ad6d6297SScott Long arcmsr_cdb->sgcount=(u_int8_t)cdb_sgcount; 870ad6d6297SScott Long arcmsr_cdb->DataLength=pcsio->dxfer_len; 871ad6d6297SScott Long if( arccdbsize > 256) { 872ad6d6297SScott Long arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_SGL_BSIZE; 873f1c579b1SScott Long } 874f1c579b1SScott Long } 875f1c579b1SScott Long return; 876f1c579b1SScott Long } 877f1c579b1SScott Long /* 878f1c579b1SScott Long ************************************************************************** 879f1c579b1SScott Long ************************************************************************** 880f1c579b1SScott Long */ 881ad6d6297SScott Long static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandControlBlock *srb) 882f1c579b1SScott Long { 883ad6d6297SScott Long u_int32_t cdb_shifted_phyaddr=(u_int32_t) srb->cdb_shifted_phyaddr; 884ad6d6297SScott Long struct ARCMSR_CDB * arcmsr_cdb=(struct ARCMSR_CDB *)&srb->arcmsr_cdb; 885f1c579b1SScott Long 886ad6d6297SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 887ad6d6297SScott Long (srb->srb_flags & SRB_FLAG_WRITE) ? BUS_DMASYNC_POSTWRITE:BUS_DMASYNC_POSTREAD); 888ad6d6297SScott Long atomic_add_int(&acb->srboutstandingcount, 1); 889ad6d6297SScott Long srb->startdone=ARCMSR_SRB_START; 89044f05562SScott Long switch (acb->adapter_type) { 89144f05562SScott Long case ACB_ADAPTER_TYPE_A: { 892ad6d6297SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 89344f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 89444f05562SScott Long 0, inbound_queueport, 89544f05562SScott Long cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE); 896ad6d6297SScott Long } else { 89744f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 89844f05562SScott Long 0, inbound_queueport, cdb_shifted_phyaddr); 89944f05562SScott Long } 90044f05562SScott Long } 90144f05562SScott Long break; 90244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 90344f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 90444f05562SScott Long int ending_index, index; 90544f05562SScott Long 90644f05562SScott Long index=phbbmu->postq_index; 90744f05562SScott Long ending_index=((index+1)%ARCMSR_MAX_HBB_POSTQUEUE); 90844f05562SScott Long phbbmu->post_qbuffer[ending_index]=0; 90944f05562SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 91044f05562SScott Long phbbmu->post_qbuffer[index]= 91144f05562SScott Long cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE; 91244f05562SScott Long } else { 91344f05562SScott Long phbbmu->post_qbuffer[index]= 91444f05562SScott Long cdb_shifted_phyaddr; 91544f05562SScott Long } 91644f05562SScott Long index++; 91744f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 91844f05562SScott Long phbbmu->postq_index=index; 91944f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 92044f05562SScott Long 0, drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED); 92144f05562SScott Long } 92244f05562SScott Long break; 923f1c579b1SScott Long } 924f1c579b1SScott Long return; 925f1c579b1SScott Long } 926f1c579b1SScott Long /* 92744f05562SScott Long ************************************************************************ 92844f05562SScott Long ************************************************************************ 92944f05562SScott Long */ 93044f05562SScott Long static struct QBUFFER * arcmsr_get_iop_rqbuffer( struct AdapterControlBlock *acb) 93144f05562SScott Long { 93244f05562SScott Long struct QBUFFER *qbuffer=NULL; 93344f05562SScott Long 93444f05562SScott Long switch (acb->adapter_type) { 93544f05562SScott Long case ACB_ADAPTER_TYPE_A: { 93644f05562SScott Long struct HBA_MessageUnit *phbamu=(struct HBA_MessageUnit *)acb->pmu; 93744f05562SScott Long 93844f05562SScott Long qbuffer=(struct QBUFFER *)&phbamu->message_rbuffer; 93944f05562SScott Long } 94044f05562SScott Long break; 94144f05562SScott Long case ACB_ADAPTER_TYPE_B: { 94244f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 94344f05562SScott Long 94444f05562SScott Long qbuffer=(struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_rbuffer; 94544f05562SScott Long } 94644f05562SScott Long break; 94744f05562SScott Long } 94844f05562SScott Long return(qbuffer); 94944f05562SScott Long } 95044f05562SScott Long /* 95144f05562SScott Long ************************************************************************ 95244f05562SScott Long ************************************************************************ 95344f05562SScott Long */ 95444f05562SScott Long static struct QBUFFER * arcmsr_get_iop_wqbuffer( struct AdapterControlBlock *acb) 95544f05562SScott Long { 95644f05562SScott Long struct QBUFFER *qbuffer=NULL; 95744f05562SScott Long 95844f05562SScott Long switch (acb->adapter_type) { 95944f05562SScott Long case ACB_ADAPTER_TYPE_A: { 96044f05562SScott Long struct HBA_MessageUnit *phbamu=(struct HBA_MessageUnit *)acb->pmu; 96144f05562SScott Long 96244f05562SScott Long qbuffer=(struct QBUFFER *)&phbamu->message_wbuffer; 96344f05562SScott Long } 96444f05562SScott Long break; 96544f05562SScott Long case ACB_ADAPTER_TYPE_B: { 96644f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 96744f05562SScott Long 96844f05562SScott Long qbuffer=(struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_wbuffer; 96944f05562SScott Long } 97044f05562SScott Long break; 97144f05562SScott Long } 97244f05562SScott Long return(qbuffer); 97344f05562SScott Long } 97444f05562SScott Long /* 97544f05562SScott Long ************************************************************************** 97644f05562SScott Long ************************************************************************** 97744f05562SScott Long */ 97844f05562SScott Long static void arcmsr_iop_message_read(struct AdapterControlBlock *acb) 97944f05562SScott Long { 98044f05562SScott Long switch (acb->adapter_type) { 98144f05562SScott Long case ACB_ADAPTER_TYPE_A: { 98244f05562SScott Long /* let IOP know data has been read */ 98344f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 98444f05562SScott Long 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 98544f05562SScott Long } 98644f05562SScott Long break; 98744f05562SScott Long case ACB_ADAPTER_TYPE_B: { 98844f05562SScott Long /* let IOP know data has been read */ 98944f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 99044f05562SScott Long 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 99144f05562SScott Long } 99244f05562SScott Long break; 99344f05562SScott Long } 99444f05562SScott Long return; 99544f05562SScott Long } 99644f05562SScott Long /* 99744f05562SScott Long ************************************************************************** 99844f05562SScott Long ************************************************************************** 99944f05562SScott Long */ 100044f05562SScott Long static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) 100144f05562SScott Long { 100244f05562SScott Long switch (acb->adapter_type) { 100344f05562SScott Long case ACB_ADAPTER_TYPE_A: { 100444f05562SScott Long /* 100544f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 100644f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 100744f05562SScott Long */ 100844f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 100944f05562SScott Long 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK); 101044f05562SScott Long } 101144f05562SScott Long break; 101244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 101344f05562SScott Long /* 101444f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 101544f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 101644f05562SScott Long */ 101744f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 101844f05562SScott Long 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_WRITE_OK); 101944f05562SScott Long } 102044f05562SScott Long break; 102144f05562SScott Long } 102244f05562SScott Long } 102344f05562SScott Long /* 1024f1c579b1SScott Long ********************************************************************** 1025f1c579b1SScott Long ********************************************************************** 1026f1c579b1SScott Long */ 102744f05562SScott Long static void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb) 1028f1c579b1SScott Long { 1029ad6d6297SScott Long u_int8_t *pQbuffer; 103044f05562SScott Long struct QBUFFER *pwbuffer; 103144f05562SScott Long u_int8_t * iop_data; 103244f05562SScott Long int32_t allxfer_len=0; 1033f1c579b1SScott Long 103444f05562SScott Long pwbuffer=arcmsr_get_iop_wqbuffer(acb); 103544f05562SScott Long iop_data=(u_int8_t *)pwbuffer->data; 103644f05562SScott Long if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) { 103744f05562SScott Long acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 103844f05562SScott Long while((acb->wqbuf_firstindex!=acb->wqbuf_lastindex) 103944f05562SScott Long && (allxfer_len<124)) { 1040ad6d6297SScott Long pQbuffer=&acb->wqbuffer[acb->wqbuf_firstindex]; 1041f1c579b1SScott Long memcpy(iop_data, pQbuffer, 1); 1042ad6d6297SScott Long acb->wqbuf_firstindex++; 104344f05562SScott Long acb->wqbuf_firstindex %=ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */ 1044f1c579b1SScott Long iop_data++; 1045f1c579b1SScott Long allxfer_len++; 1046f1c579b1SScott Long } 1047f1c579b1SScott Long pwbuffer->data_len=allxfer_len; 1048f1c579b1SScott Long /* 1049f1c579b1SScott Long ** push inbound doorbell and wait reply at hwinterrupt routine for next Qbuffer post 1050f1c579b1SScott Long */ 105144f05562SScott Long arcmsr_iop_message_wrote(acb); 1052ad6d6297SScott Long } 1053f1c579b1SScott Long return; 1054f1c579b1SScott Long } 1055f1c579b1SScott Long /* 1056f1c579b1SScott Long ************************************************************************ 1057f1c579b1SScott Long ************************************************************************ 1058f1c579b1SScott Long */ 105944f05562SScott Long static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb) 1060f1c579b1SScott Long { 1061ad6d6297SScott Long acb->acb_flags &=~ACB_F_MSG_START_BGRB; 106244f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 106344f05562SScott Long 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 106444f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 1065ad6d6297SScott Long printf("arcmsr%d: wait 'stop adapter rebulid' timeout \n" 1066ad6d6297SScott Long , acb->pci_unit); 1067ad6d6297SScott Long } 1068f1c579b1SScott Long return; 1069f1c579b1SScott Long } 1070f1c579b1SScott Long /* 1071f1c579b1SScott Long ************************************************************************ 1072f1c579b1SScott Long ************************************************************************ 1073f1c579b1SScott Long */ 107444f05562SScott Long static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb) 107544f05562SScott Long { 107644f05562SScott Long acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 107744f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 107844f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_STOP_BGRB); 107944f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 108044f05562SScott Long printf( "arcmsr%d: wait 'stop adapter rebulid' timeout \n" 108144f05562SScott Long , acb->pci_unit); 108244f05562SScott Long } 108344f05562SScott Long return; 108444f05562SScott Long } 108544f05562SScott Long /* 108644f05562SScott Long ************************************************************************ 108744f05562SScott Long ************************************************************************ 108844f05562SScott Long */ 108944f05562SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) 109044f05562SScott Long { 109144f05562SScott Long switch (acb->adapter_type) { 109244f05562SScott Long case ACB_ADAPTER_TYPE_A: { 109344f05562SScott Long arcmsr_stop_hba_bgrb(acb); 109444f05562SScott Long } 109544f05562SScott Long break; 109644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 109744f05562SScott Long arcmsr_stop_hbb_bgrb(acb); 109844f05562SScott Long } 109944f05562SScott Long break; 110044f05562SScott Long } 110144f05562SScott Long return; 110244f05562SScott Long } 110344f05562SScott Long /* 110444f05562SScott Long ************************************************************************ 110544f05562SScott Long ************************************************************************ 110644f05562SScott Long */ 1107ad6d6297SScott Long static void arcmsr_poll(struct cam_sim * psim) 1108f1c579b1SScott Long { 1109579ec1a5SScott Long struct AdapterControlBlock *acb; 1110579ec1a5SScott Long 1111579ec1a5SScott Long acb = (struct AdapterControlBlock *)cam_sim_softc(psim); 1112579ec1a5SScott Long #if __FreeBSD_version < 700025 1113579ec1a5SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 1114579ec1a5SScott Long #endif 1115579ec1a5SScott Long arcmsr_interrupt(acb); 1116579ec1a5SScott Long #if __FreeBSD_version < 700025 1117579ec1a5SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1118579ec1a5SScott Long #endif 1119f1c579b1SScott Long return; 1120f1c579b1SScott Long } 1121f1c579b1SScott Long /* 1122f1c579b1SScott Long ********************************************************************** 1123f1c579b1SScott Long ********************************************************************** 1124f1c579b1SScott Long */ 11255878cbecSScott Long static void arcmsr_intr_handler(void *arg) 11265878cbecSScott Long { 11275878cbecSScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)arg; 11285878cbecSScott Long 11295878cbecSScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 11305878cbecSScott Long arcmsr_interrupt(acb); 11315878cbecSScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 11325878cbecSScott Long } 11335878cbecSScott Long /* 113444f05562SScott Long ************************************************************************** 113544f05562SScott Long ************************************************************************** 11365878cbecSScott Long */ 113744f05562SScott Long static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) 1138f1c579b1SScott Long { 113944f05562SScott Long struct QBUFFER *prbuffer; 1140ad6d6297SScott Long u_int8_t *pQbuffer; 114144f05562SScott Long u_int8_t *iop_data; 114244f05562SScott Long int my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; 1143ad6d6297SScott Long 1144f1c579b1SScott Long /*check this iop data if overflow my rqbuffer*/ 1145ad6d6297SScott Long rqbuf_lastindex=acb->rqbuf_lastindex; 1146ad6d6297SScott Long rqbuf_firstindex=acb->rqbuf_firstindex; 114744f05562SScott Long prbuffer=arcmsr_get_iop_rqbuffer(acb); 114844f05562SScott Long iop_data=(u_int8_t *)prbuffer->data; 1149f1c579b1SScott Long iop_len=prbuffer->data_len; 1150f1c579b1SScott Long my_empty_len=(rqbuf_firstindex-rqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1); 1151ad6d6297SScott Long if(my_empty_len>=iop_len) { 1152ad6d6297SScott Long while(iop_len > 0) { 115344f05562SScott Long pQbuffer=&acb->rqbuffer[rqbuf_lastindex]; 1154f1c579b1SScott Long memcpy(pQbuffer, iop_data, 1); 115544f05562SScott Long rqbuf_lastindex++; 115644f05562SScott Long rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;/*if last index number set it to 0 */ 1157f1c579b1SScott Long iop_data++; 1158f1c579b1SScott Long iop_len--; 1159f1c579b1SScott Long } 116044f05562SScott Long acb->rqbuf_lastindex=rqbuf_lastindex; 116144f05562SScott Long arcmsr_iop_message_read(acb); 116244f05562SScott Long /*signature, let IOP know data has been read */ 1163ad6d6297SScott Long } else { 1164ad6d6297SScott Long acb->acb_flags|=ACB_F_IOPDATA_OVERFLOW; 1165f1c579b1SScott Long } 116644f05562SScott Long return; 1167f1c579b1SScott Long } 1168f1c579b1SScott Long /* 116944f05562SScott Long ************************************************************************** 117044f05562SScott Long ************************************************************************** 117144f05562SScott Long */ 117244f05562SScott Long static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) 117344f05562SScott Long { 117444f05562SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READ; 117544f05562SScott Long /* 117644f05562SScott Long ***************************************************************** 117744f05562SScott Long ** check if there are any mail packages from user space program 117844f05562SScott Long ** in my post bag, now is the time to send them into Areca's firmware 117944f05562SScott Long ***************************************************************** 1180f1c579b1SScott Long */ 1181ad6d6297SScott Long if(acb->wqbuf_firstindex!=acb->wqbuf_lastindex) { 1182ad6d6297SScott Long u_int8_t *pQbuffer; 118344f05562SScott Long struct QBUFFER *pwbuffer; 118444f05562SScott Long u_int8_t *iop_data; 118544f05562SScott Long int allxfer_len=0; 1186f1c579b1SScott Long 118744f05562SScott Long acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 118844f05562SScott Long pwbuffer=arcmsr_get_iop_wqbuffer(acb); 118944f05562SScott Long iop_data=(u_int8_t *)pwbuffer->data; 119044f05562SScott Long while((acb->wqbuf_firstindex!=acb->wqbuf_lastindex) 119144f05562SScott Long && (allxfer_len<124)) { 1192ad6d6297SScott Long pQbuffer=&acb->wqbuffer[acb->wqbuf_firstindex]; 1193f1c579b1SScott Long memcpy(iop_data, pQbuffer, 1); 1194ad6d6297SScott Long acb->wqbuf_firstindex++; 119544f05562SScott Long acb->wqbuf_firstindex %=ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */ 1196f1c579b1SScott Long iop_data++; 1197f1c579b1SScott Long allxfer_len++; 1198f1c579b1SScott Long } 1199f1c579b1SScott Long pwbuffer->data_len=allxfer_len; 1200f1c579b1SScott Long /* 1201ad6d6297SScott Long ** push inbound doorbell tell iop driver data write ok 1202ad6d6297SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 1203f1c579b1SScott Long */ 120444f05562SScott Long arcmsr_iop_message_wrote(acb); 1205f1c579b1SScott Long } 1206ad6d6297SScott Long if(acb->wqbuf_firstindex==acb->wqbuf_lastindex) { 1207ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; 1208f1c579b1SScott Long } 120944f05562SScott Long return; 1210f1c579b1SScott Long } 121144f05562SScott Long /* 121244f05562SScott Long ************************************************************************** 121344f05562SScott Long ************************************************************************** 121444f05562SScott Long */ 121544f05562SScott Long static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) 121644f05562SScott Long { 121744f05562SScott Long u_int32_t outbound_doorbell; 121844f05562SScott Long 121944f05562SScott Long /* 122044f05562SScott Long ******************************************************************* 122144f05562SScott Long ** Maybe here we need to check wrqbuffer_lock is lock or not 122244f05562SScott Long ** DOORBELL: din! don! 122344f05562SScott Long ** check if there are any mail need to pack from firmware 122444f05562SScott Long ******************************************************************* 122544f05562SScott Long */ 122644f05562SScott Long outbound_doorbell=CHIP_REG_READ32(HBA_MessageUnit, 122744f05562SScott Long 0, outbound_doorbell); 122844f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 122944f05562SScott Long 0, outbound_doorbell, outbound_doorbell); /* clear doorbell interrupt */ 123044f05562SScott Long if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { 123144f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 1232ad6d6297SScott Long } 123344f05562SScott Long if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { 123444f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 123544f05562SScott Long } 123644f05562SScott Long return; 123744f05562SScott Long } 123844f05562SScott Long /* 123944f05562SScott Long ************************************************************************** 124044f05562SScott Long ************************************************************************** 124144f05562SScott Long */ 124244f05562SScott Long static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb) 124344f05562SScott Long { 124444f05562SScott Long u_int32_t flag_srb; 124544f05562SScott Long 1246f1c579b1SScott Long /* 1247f1c579b1SScott Long ***************************************************************************** 1248f1c579b1SScott Long ** areca cdb command done 1249f1c579b1SScott Long ***************************************************************************** 1250f1c579b1SScott Long */ 125144f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 125244f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 125344f05562SScott Long while((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 125444f05562SScott Long 0, outbound_queueport)) != 0xFFFFFFFF) { 1255f1c579b1SScott Long /* check if command done with no error*/ 125644f05562SScott Long arcmsr_drain_donequeue(acb, flag_srb); 125744f05562SScott Long } /*drain reply FIFO*/ 125844f05562SScott Long return; 1259f1c579b1SScott Long } 126044f05562SScott Long /* 126144f05562SScott Long ************************************************************************** 126244f05562SScott Long ************************************************************************** 126344f05562SScott Long */ 126444f05562SScott Long static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) 126544f05562SScott Long { 126644f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 126744f05562SScott Long u_int32_t flag_srb; 126844f05562SScott Long int index; 126944f05562SScott Long 127044f05562SScott Long /* 127144f05562SScott Long ***************************************************************************** 127244f05562SScott Long ** areca cdb command done 127344f05562SScott Long ***************************************************************************** 127444f05562SScott Long */ 127544f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 127644f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 127744f05562SScott Long index=phbbmu->doneq_index; 127844f05562SScott Long while((flag_srb=phbbmu->done_qbuffer[index]) != 0) { 127944f05562SScott Long phbbmu->done_qbuffer[index]=0; 128044f05562SScott Long index++; 128144f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 128244f05562SScott Long phbbmu->doneq_index=index; 128344f05562SScott Long /* check if command done with no error*/ 128444f05562SScott Long arcmsr_drain_donequeue(acb, flag_srb); 128544f05562SScott Long } /*drain reply FIFO*/ 128644f05562SScott Long return; 1287f1c579b1SScott Long } 128844f05562SScott Long /* 128944f05562SScott Long ********************************************************************** 129044f05562SScott Long ********************************************************************** 129144f05562SScott Long */ 129244f05562SScott Long static void arcmsr_handle_hba_isr( struct AdapterControlBlock *acb) 129344f05562SScott Long { 129444f05562SScott Long u_int32_t outbound_intstatus; 129544f05562SScott Long /* 129644f05562SScott Long ********************************************* 129744f05562SScott Long ** check outbound intstatus 129844f05562SScott Long ********************************************* 129944f05562SScott Long */ 130044f05562SScott Long outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 130144f05562SScott Long 0, outbound_intstatus) & acb->outbound_int_enable; 130244f05562SScott Long if(!outbound_intstatus) { 130344f05562SScott Long /*it must be share irq*/ 130444f05562SScott Long return; 1305f1c579b1SScott Long } 130644f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 130744f05562SScott Long 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/ 130844f05562SScott Long /* MU doorbell interrupts*/ 130944f05562SScott Long if(outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) { 131044f05562SScott Long arcmsr_hba_doorbell_isr(acb); 1311f1c579b1SScott Long } 131244f05562SScott Long /* MU post queue interrupts*/ 131344f05562SScott Long if(outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { 131444f05562SScott Long arcmsr_hba_postqueue_isr(acb); 131544f05562SScott Long } 131644f05562SScott Long return; 131744f05562SScott Long } 131844f05562SScott Long /* 131944f05562SScott Long ********************************************************************** 132044f05562SScott Long ********************************************************************** 132144f05562SScott Long */ 132244f05562SScott Long static void arcmsr_handle_hbb_isr( struct AdapterControlBlock *acb) 132344f05562SScott Long { 132444f05562SScott Long u_int32_t outbound_doorbell; 132544f05562SScott Long /* 132644f05562SScott Long ********************************************* 132744f05562SScott Long ** check outbound intstatus 132844f05562SScott Long ********************************************* 132944f05562SScott Long */ 133044f05562SScott Long outbound_doorbell=CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & acb->outbound_int_enable; 133144f05562SScott Long if(!outbound_doorbell) { 133244f05562SScott Long /*it must be share irq*/ 133344f05562SScott Long return; 133444f05562SScott Long } 133544f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ~outbound_doorbell); /* clear doorbell interrupt */ 133644f05562SScott Long CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell); 133744f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 133844f05562SScott Long /* MU ioctl transfer doorbell interrupts*/ 133944f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { 134044f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 134144f05562SScott Long } 134244f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) { 134344f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 134444f05562SScott Long } 134544f05562SScott Long /* MU post queue interrupts*/ 134644f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) { 134744f05562SScott Long arcmsr_hbb_postqueue_isr(acb); 134844f05562SScott Long } 134944f05562SScott Long return; 135044f05562SScott Long } 135144f05562SScott Long /* 135244f05562SScott Long ****************************************************************************** 135344f05562SScott Long ****************************************************************************** 135444f05562SScott Long */ 135544f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb) 135644f05562SScott Long { 135744f05562SScott Long switch (acb->adapter_type) { 135844f05562SScott Long case ACB_ADAPTER_TYPE_A: 135944f05562SScott Long arcmsr_handle_hba_isr(acb); 1360f1c579b1SScott Long break; 136144f05562SScott Long case ACB_ADAPTER_TYPE_B: 136244f05562SScott Long arcmsr_handle_hbb_isr(acb); 1363f1c579b1SScott Long break; 1364f1c579b1SScott Long default: 136544f05562SScott Long printf("arcmsr%d: interrupt service," 136644f05562SScott Long " unknow adapter type =%d\n", acb->pci_unit, acb->adapter_type); 1367f1c579b1SScott Long break; 1368f1c579b1SScott Long } 1369f1c579b1SScott Long return; 1370f1c579b1SScott Long } 1371f1c579b1SScott Long /* 1372ad6d6297SScott Long ******************************************************************************* 1373ad6d6297SScott Long ** 1374ad6d6297SScott Long ******************************************************************************* 1375ad6d6297SScott Long */ 1376ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb) 1377ad6d6297SScott Long { 1378ad6d6297SScott Long if(acb!=NULL) { 1379ad6d6297SScott Long /* stop adapter background rebuild */ 1380ad6d6297SScott Long if(acb->acb_flags & ACB_F_MSG_START_BGRB) { 1381ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 1382ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 1383ad6d6297SScott Long } 1384ad6d6297SScott Long } 1385ad6d6297SScott Long } 1386ad6d6297SScott Long /* 1387f1c579b1SScott Long *********************************************************************** 1388f1c579b1SScott Long ** 1389f1c579b1SScott Long ************************************************************************ 1390f1c579b1SScott Long */ 1391ad6d6297SScott Long u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg) 1392f1c579b1SScott Long { 1393ad6d6297SScott Long struct CMD_MESSAGE_FIELD * pcmdmessagefld; 1394ad6d6297SScott Long u_int32_t retvalue=EINVAL; 1395f1c579b1SScott Long 1396ad6d6297SScott Long pcmdmessagefld=(struct CMD_MESSAGE_FIELD *) arg; 1397ad6d6297SScott Long if(memcmp(pcmdmessagefld->cmdmessage.Signature, "ARCMSR", 6)!=0) { 1398ad6d6297SScott Long return retvalue; 1399f1c579b1SScott Long } 1400ad6d6297SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 1401ad6d6297SScott Long switch(ioctl_cmd) { 1402ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 1403ad6d6297SScott Long u_int8_t * pQbuffer; 1404ad6d6297SScott Long u_int8_t * ptmpQbuffer=pcmdmessagefld->messagedatabuffer; 1405ad6d6297SScott Long u_int32_t allxfer_len=0; 1406f1c579b1SScott Long 140744f05562SScott Long while((acb->rqbuf_firstindex!=acb->rqbuf_lastindex) 140844f05562SScott Long && (allxfer_len<1031)) { 1409f1c579b1SScott Long /*copy READ QBUFFER to srb*/ 1410ad6d6297SScott Long pQbuffer= &acb->rqbuffer[acb->rqbuf_firstindex]; 1411f1c579b1SScott Long memcpy(ptmpQbuffer, pQbuffer, 1); 1412ad6d6297SScott Long acb->rqbuf_firstindex++; 1413ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 1414ad6d6297SScott Long /*if last index number set it to 0 */ 1415f1c579b1SScott Long ptmpQbuffer++; 1416f1c579b1SScott Long allxfer_len++; 1417f1c579b1SScott Long } 1418ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 141944f05562SScott Long struct QBUFFER * prbuffer; 142044f05562SScott Long u_int8_t * iop_data; 1421ad6d6297SScott Long u_int32_t iop_len; 1422f1c579b1SScott Long 1423ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 142444f05562SScott Long prbuffer=arcmsr_get_iop_rqbuffer(acb); 142544f05562SScott Long iop_data=(u_int8_t *)prbuffer->data; 1426ad6d6297SScott Long iop_len=(u_int32_t)prbuffer->data_len; 1427f1c579b1SScott Long /*this iop data does no chance to make me overflow again here, so just do it*/ 1428ad6d6297SScott Long while(iop_len>0) { 1429ad6d6297SScott Long pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex]; 1430f1c579b1SScott Long memcpy(pQbuffer, iop_data, 1); 1431ad6d6297SScott Long acb->rqbuf_lastindex++; 1432ad6d6297SScott Long acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 1433ad6d6297SScott Long /*if last index number set it to 0 */ 1434f1c579b1SScott Long iop_data++; 1435f1c579b1SScott Long iop_len--; 1436f1c579b1SScott Long } 143744f05562SScott Long arcmsr_iop_message_read(acb); 143844f05562SScott Long /*signature, let IOP know data has been readed */ 1439f1c579b1SScott Long } 1440ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length=allxfer_len; 1441ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1442ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1443f1c579b1SScott Long } 1444f1c579b1SScott Long break; 1445ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 1446ad6d6297SScott Long u_int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 1447ad6d6297SScott Long u_int8_t * pQbuffer; 1448ad6d6297SScott Long u_int8_t * ptmpuserbuffer=pcmdmessagefld->messagedatabuffer; 1449f1c579b1SScott Long 1450ad6d6297SScott Long user_len=pcmdmessagefld->cmdmessage.Length; 1451f1c579b1SScott Long /*check if data xfer length of this request will overflow my array qbuffer */ 1452ad6d6297SScott Long wqbuf_lastindex=acb->wqbuf_lastindex; 1453ad6d6297SScott Long wqbuf_firstindex=acb->wqbuf_firstindex; 1454ad6d6297SScott Long if(wqbuf_lastindex!=wqbuf_firstindex) { 145544f05562SScott Long arcmsr_post_ioctldata2iop(acb); 1456ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; 1457ad6d6297SScott Long } else { 1458f1c579b1SScott Long my_empty_len=(wqbuf_firstindex-wqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1); 1459ad6d6297SScott Long if(my_empty_len>=user_len) { 1460ad6d6297SScott Long while(user_len>0) { 1461f1c579b1SScott Long /*copy srb data to wqbuffer*/ 1462ad6d6297SScott Long pQbuffer= &acb->wqbuffer[acb->wqbuf_lastindex]; 1463f1c579b1SScott Long memcpy(pQbuffer, ptmpuserbuffer, 1); 1464ad6d6297SScott Long acb->wqbuf_lastindex++; 1465ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 1466ad6d6297SScott Long /*if last index number set it to 0 */ 1467f1c579b1SScott Long ptmpuserbuffer++; 1468f1c579b1SScott Long user_len--; 1469f1c579b1SScott Long } 1470f1c579b1SScott Long /*post fist Qbuffer*/ 1471ad6d6297SScott Long if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 1472ad6d6297SScott Long acb->acb_flags &=~ACB_F_MESSAGE_WQBUFFER_CLEARED; 147344f05562SScott Long arcmsr_post_ioctldata2iop(acb); 1474f1c579b1SScott Long } 1475ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1476ad6d6297SScott Long } else { 1477ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; 1478f1c579b1SScott Long } 1479f1c579b1SScott Long } 1480ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1481f1c579b1SScott Long } 1482f1c579b1SScott Long break; 1483ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 1484ad6d6297SScott Long u_int8_t * pQbuffer=acb->rqbuffer; 1485ad6d6297SScott Long 1486ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1487ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 148844f05562SScott Long arcmsr_iop_message_read(acb); 148944f05562SScott Long /*signature, let IOP know data has been readed */ 1490f1c579b1SScott Long } 1491ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 1492ad6d6297SScott Long acb->rqbuf_firstindex=0; 1493ad6d6297SScott Long acb->rqbuf_lastindex=0; 1494f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 1495ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1496ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1497f1c579b1SScott Long } 1498f1c579b1SScott Long break; 1499ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: 1500f1c579b1SScott Long { 1501ad6d6297SScott Long u_int8_t * pQbuffer=acb->wqbuffer; 1502f1c579b1SScott Long 1503ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1504ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 150544f05562SScott Long arcmsr_iop_message_read(acb); 150644f05562SScott Long /*signature, let IOP know data has been readed */ 1507f1c579b1SScott Long } 150844f05562SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ); 1509ad6d6297SScott Long acb->wqbuf_firstindex=0; 1510ad6d6297SScott Long acb->wqbuf_lastindex=0; 1511f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 1512ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1513ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1514f1c579b1SScott Long } 1515f1c579b1SScott Long break; 1516ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 1517ad6d6297SScott Long u_int8_t * pQbuffer; 1518f1c579b1SScott Long 1519ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1520ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 152144f05562SScott Long arcmsr_iop_message_read(acb); 152244f05562SScott Long /*signature, let IOP know data has been readed */ 1523f1c579b1SScott Long } 1524ad6d6297SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED 1525ad6d6297SScott Long |ACB_F_MESSAGE_RQBUFFER_CLEARED 152644f05562SScott Long |ACB_F_MESSAGE_WQBUFFER_READ); 1527ad6d6297SScott Long acb->rqbuf_firstindex=0; 1528ad6d6297SScott Long acb->rqbuf_lastindex=0; 1529ad6d6297SScott Long acb->wqbuf_firstindex=0; 1530ad6d6297SScott Long acb->wqbuf_lastindex=0; 1531ad6d6297SScott Long pQbuffer=acb->rqbuffer; 1532ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 1533ad6d6297SScott Long pQbuffer=acb->wqbuffer; 1534ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 1535ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1536ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1537f1c579b1SScott Long } 1538f1c579b1SScott Long break; 1539ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 1540ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_3F; 1541ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1542f1c579b1SScott Long } 1543f1c579b1SScott Long break; 1544ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 1545ad6d6297SScott Long u_int8_t * hello_string="Hello! I am ARCMSR"; 1546ad6d6297SScott Long u_int8_t * puserbuffer=(u_int8_t *)pcmdmessagefld->messagedatabuffer; 1547f1c579b1SScott Long 1548ad6d6297SScott Long if(memcpy(puserbuffer, hello_string, (int16_t)strlen(hello_string))) { 1549ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; 1550ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1551f1c579b1SScott Long return ENOIOCTL; 1552f1c579b1SScott Long } 1553ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1554ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1555ad6d6297SScott Long } 1556ad6d6297SScott Long break; 1557ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: { 1558ad6d6297SScott Long arcmsr_iop_parking(acb); 1559ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1560ad6d6297SScott Long } 1561ad6d6297SScott Long break; 1562ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: { 1563ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 1564ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1565f1c579b1SScott Long } 1566f1c579b1SScott Long break; 1567f1c579b1SScott Long } 1568ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1569ad6d6297SScott Long return retvalue; 1570f1c579b1SScott Long } 1571f1c579b1SScott Long /* 1572f1c579b1SScott Long ************************************************************************** 1573f1c579b1SScott Long ************************************************************************** 1574f1c579b1SScott Long */ 1575ad6d6297SScott Long struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb) 1576f1c579b1SScott Long { 1577ad6d6297SScott Long struct CommandControlBlock *srb=NULL; 1578ad6d6297SScott Long u_int32_t workingsrb_startindex, workingsrb_doneindex; 1579f1c579b1SScott Long 1580579ec1a5SScott Long #if __FreeBSD_version < 700025 1581579ec1a5SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 1582579ec1a5SScott Long #endif 1583ad6d6297SScott Long workingsrb_doneindex=acb->workingsrb_doneindex; 1584ad6d6297SScott Long workingsrb_startindex=acb->workingsrb_startindex; 1585ad6d6297SScott Long srb=acb->srbworkingQ[workingsrb_startindex]; 1586ad6d6297SScott Long workingsrb_startindex++; 1587ad6d6297SScott Long workingsrb_startindex %= ARCMSR_MAX_FREESRB_NUM; 1588ad6d6297SScott Long if(workingsrb_doneindex!=workingsrb_startindex) { 1589ad6d6297SScott Long acb->workingsrb_startindex=workingsrb_startindex; 1590ad6d6297SScott Long } else { 1591ad6d6297SScott Long srb=NULL; 1592ad6d6297SScott Long } 1593579ec1a5SScott Long #if __FreeBSD_version < 700025 1594579ec1a5SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1595579ec1a5SScott Long #endif 1596ad6d6297SScott Long return(srb); 1597ad6d6297SScott Long } 1598ad6d6297SScott Long /* 1599ad6d6297SScott Long ************************************************************************** 1600ad6d6297SScott Long ************************************************************************** 1601ad6d6297SScott Long */ 1602ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb) 1603ad6d6297SScott Long { 1604ad6d6297SScott Long struct CMD_MESSAGE_FIELD * pcmdmessagefld; 1605ad6d6297SScott Long int retvalue = 0, transfer_len = 0; 1606ad6d6297SScott Long char *buffer; 160744f05562SScott Long u_int32_t controlcode = (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[5] << 24 | 160844f05562SScott Long (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[6] << 16 | 160944f05562SScott Long (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[7] << 8 | 161044f05562SScott Long (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[8]; 1611ad6d6297SScott Long /* 4 bytes: Areca io control code */ 1612ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) { 1613ad6d6297SScott Long buffer = pccb->csio.data_ptr; 1614ad6d6297SScott Long transfer_len = pccb->csio.dxfer_len; 1615ad6d6297SScott Long } else { 1616ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 1617ad6d6297SScott Long goto message_out; 1618ad6d6297SScott Long } 1619ad6d6297SScott Long if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) { 1620ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 1621ad6d6297SScott Long goto message_out; 1622ad6d6297SScott Long } 1623ad6d6297SScott Long pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer; 1624ad6d6297SScott Long switch(controlcode) { 1625ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 1626ad6d6297SScott Long u_int8_t *pQbuffer; 1627ad6d6297SScott Long u_int8_t *ptmpQbuffer=pcmdmessagefld->messagedatabuffer; 1628ad6d6297SScott Long int32_t allxfer_len = 0; 1629f1c579b1SScott Long 1630ad6d6297SScott Long while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) 1631ad6d6297SScott Long && (allxfer_len < 1031)) { 1632ad6d6297SScott Long pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; 1633ad6d6297SScott Long memcpy(ptmpQbuffer, pQbuffer, 1); 1634ad6d6297SScott Long acb->rqbuf_firstindex++; 1635ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 1636ad6d6297SScott Long ptmpQbuffer++; 1637ad6d6297SScott Long allxfer_len++; 1638f1c579b1SScott Long } 1639ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 164044f05562SScott Long struct QBUFFER *prbuffer; 164144f05562SScott Long u_int8_t *iop_data; 1642ad6d6297SScott Long int32_t iop_len; 1643ad6d6297SScott Long 1644ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 164544f05562SScott Long prbuffer=arcmsr_get_iop_rqbuffer(acb); 164644f05562SScott Long iop_data = (u_int8_t *)prbuffer->data; 1647ad6d6297SScott Long iop_len =(u_int32_t)prbuffer->data_len; 1648ad6d6297SScott Long while (iop_len > 0) { 1649ad6d6297SScott Long pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex]; 1650ad6d6297SScott Long memcpy(pQbuffer, iop_data, 1); 1651ad6d6297SScott Long acb->rqbuf_lastindex++; 1652ad6d6297SScott Long acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 1653ad6d6297SScott Long iop_data++; 1654ad6d6297SScott Long iop_len--; 1655f1c579b1SScott Long } 165644f05562SScott Long arcmsr_iop_message_read(acb); 1657ad6d6297SScott Long } 1658ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length = allxfer_len; 1659ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 1660ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1661ad6d6297SScott Long } 1662ad6d6297SScott Long break; 1663ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 1664ad6d6297SScott Long int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 1665ad6d6297SScott Long u_int8_t *pQbuffer; 1666ad6d6297SScott Long u_int8_t *ptmpuserbuffer=pcmdmessagefld->messagedatabuffer; 1667ad6d6297SScott Long 1668ad6d6297SScott Long user_len = pcmdmessagefld->cmdmessage.Length; 1669ad6d6297SScott Long wqbuf_lastindex = acb->wqbuf_lastindex; 1670ad6d6297SScott Long wqbuf_firstindex = acb->wqbuf_firstindex; 1671ad6d6297SScott Long if (wqbuf_lastindex != wqbuf_firstindex) { 167244f05562SScott Long arcmsr_post_ioctldata2iop(acb); 1673ad6d6297SScott Long /* has error report sensedata */ 1674ad6d6297SScott Long if(&pccb->csio.sense_data) { 1675ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 1676ad6d6297SScott Long /* Valid,ErrorCode */ 1677ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 1678ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 1679ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 1680ad6d6297SScott Long /* AdditionalSenseLength */ 1681ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 1682ad6d6297SScott Long /* AdditionalSenseCode */ 1683ad6d6297SScott Long } 1684ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 1685ad6d6297SScott Long } else { 1686ad6d6297SScott Long my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) 1687ad6d6297SScott Long &(ARCMSR_MAX_QBUFFER - 1); 1688ad6d6297SScott Long if (my_empty_len >= user_len) { 1689ad6d6297SScott Long while (user_len > 0) { 1690ad6d6297SScott Long pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; 1691ad6d6297SScott Long memcpy(pQbuffer, ptmpuserbuffer, 1); 1692ad6d6297SScott Long acb->wqbuf_lastindex++; 1693ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 1694ad6d6297SScott Long ptmpuserbuffer++; 1695ad6d6297SScott Long user_len--; 1696ad6d6297SScott Long } 1697ad6d6297SScott Long if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 1698ad6d6297SScott Long acb->acb_flags &= 1699ad6d6297SScott Long ~ACB_F_MESSAGE_WQBUFFER_CLEARED; 170044f05562SScott Long arcmsr_post_ioctldata2iop(acb); 1701ad6d6297SScott Long } 1702ad6d6297SScott Long } else { 1703ad6d6297SScott Long /* has error report sensedata */ 1704ad6d6297SScott Long if(&pccb->csio.sense_data) { 1705ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 1706ad6d6297SScott Long /* Valid,ErrorCode */ 1707ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 1708ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 1709ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 1710ad6d6297SScott Long /* AdditionalSenseLength */ 1711ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 1712ad6d6297SScott Long /* AdditionalSenseCode */ 1713ad6d6297SScott Long } 1714ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 1715ad6d6297SScott Long } 1716ad6d6297SScott Long } 1717ad6d6297SScott Long } 1718ad6d6297SScott Long break; 1719ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 1720ad6d6297SScott Long u_int8_t *pQbuffer = acb->rqbuffer; 1721ad6d6297SScott Long 1722ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1723ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 172444f05562SScott Long arcmsr_iop_message_read(acb); 1725ad6d6297SScott Long } 1726ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 1727ad6d6297SScott Long acb->rqbuf_firstindex = 0; 1728ad6d6297SScott Long acb->rqbuf_lastindex = 0; 1729ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 1730ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 1731ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 1732ad6d6297SScott Long } 1733ad6d6297SScott Long break; 1734ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { 1735ad6d6297SScott Long u_int8_t *pQbuffer = acb->wqbuffer; 1736ad6d6297SScott Long 1737ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1738ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 173944f05562SScott Long arcmsr_iop_message_read(acb); 1740ad6d6297SScott Long } 1741ad6d6297SScott Long acb->acb_flags |= 1742ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED | 174344f05562SScott Long ACB_F_MESSAGE_WQBUFFER_READ); 1744ad6d6297SScott Long acb->wqbuf_firstindex = 0; 1745ad6d6297SScott Long acb->wqbuf_lastindex = 0; 1746ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 1747ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 1748ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 1749ad6d6297SScott Long } 1750ad6d6297SScott Long break; 1751ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 1752ad6d6297SScott Long u_int8_t *pQbuffer; 1753ad6d6297SScott Long 1754ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1755ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 175644f05562SScott Long arcmsr_iop_message_read(acb); 1757ad6d6297SScott Long } 1758ad6d6297SScott Long acb->acb_flags |= 1759ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED 1760ad6d6297SScott Long | ACB_F_MESSAGE_RQBUFFER_CLEARED 176144f05562SScott Long | ACB_F_MESSAGE_WQBUFFER_READ); 1762ad6d6297SScott Long acb->rqbuf_firstindex = 0; 1763ad6d6297SScott Long acb->rqbuf_lastindex = 0; 1764ad6d6297SScott Long acb->wqbuf_firstindex = 0; 1765ad6d6297SScott Long acb->wqbuf_lastindex = 0; 1766ad6d6297SScott Long pQbuffer = acb->rqbuffer; 1767ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 1768ad6d6297SScott Long pQbuffer = acb->wqbuffer; 1769ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 1770ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 1771ad6d6297SScott Long } 1772ad6d6297SScott Long break; 1773ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 1774ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; 1775ad6d6297SScott Long } 1776ad6d6297SScott Long break; 1777ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 1778ad6d6297SScott Long int8_t * hello_string = "Hello! I am ARCMSR"; 1779ad6d6297SScott Long 1780ad6d6297SScott Long memcpy(pcmdmessagefld->messagedatabuffer, hello_string 1781ad6d6297SScott Long , (int16_t)strlen(hello_string)); 1782ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 1783ad6d6297SScott Long } 1784ad6d6297SScott Long break; 1785ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: 1786ad6d6297SScott Long arcmsr_iop_parking(acb); 1787ad6d6297SScott Long break; 1788ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: 1789ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 1790ad6d6297SScott Long break; 1791ad6d6297SScott Long default: 1792ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 1793ad6d6297SScott Long } 1794ad6d6297SScott Long message_out: 1795ad6d6297SScott Long return retvalue; 1796f1c579b1SScott Long } 1797f1c579b1SScott Long /* 1798f1c579b1SScott Long ********************************************************************* 1799f1c579b1SScott Long ********************************************************************* 1800f1c579b1SScott Long */ 1801ad6d6297SScott Long static void arcmsr_executesrb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 1802f1c579b1SScott Long { 1803ad6d6297SScott Long struct CommandControlBlock *srb=(struct CommandControlBlock *)arg; 1804ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)srb->acb; 1805f1c579b1SScott Long union ccb * pccb; 1806ad6d6297SScott Long int target, lun; 1807f1c579b1SScott Long 1808ad6d6297SScott Long pccb=srb->pccb; 1809ad6d6297SScott Long target=pccb->ccb_h.target_id; 1810ad6d6297SScott Long lun=pccb->ccb_h.target_lun; 1811ad6d6297SScott Long if(error != 0) { 1812ad6d6297SScott Long if(error != EFBIG) { 181344f05562SScott Long printf("arcmsr%d: unexpected error %x" 181444f05562SScott Long " returned from 'bus_dmamap_load' \n" 1815ad6d6297SScott Long , acb->pci_unit, error); 1816f1c579b1SScott Long } 1817ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { 181815735becSScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 1819f1c579b1SScott Long } 1820ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 1821f1c579b1SScott Long return; 1822f1c579b1SScott Long } 1823ad6d6297SScott Long if(nseg > ARCMSR_MAX_SG_ENTRIES) { 1824ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 1825ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 1826ad6d6297SScott Long return; 1827f1c579b1SScott Long } 1828ad6d6297SScott Long if(acb->acb_flags & ACB_F_BUS_RESET) { 1829ad6d6297SScott Long printf("arcmsr%d: bus reset and return busy \n", acb->pci_unit); 1830ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_BUS_RESET; 1831ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 1832ad6d6297SScott Long return; 1833ad6d6297SScott Long } 1834ad6d6297SScott Long if(acb->devstate[target][lun]==ARECA_RAID_GONE) { 1835ad6d6297SScott Long u_int8_t block_cmd; 1836ad6d6297SScott Long 1837ad6d6297SScott Long block_cmd=pccb->csio.cdb_io.cdb_bytes[0] & 0x0f; 1838ad6d6297SScott Long if(block_cmd==0x08 || block_cmd==0x0a) { 1839ad6d6297SScott Long printf("arcmsr%d:block 'read/write' command" 1840ad6d6297SScott Long "with gone raid volume Cmd=%2x, TargetId=%d, Lun=%d \n" 1841ad6d6297SScott Long , acb->pci_unit, block_cmd, target, lun); 1842ad6d6297SScott Long pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 1843ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 1844ad6d6297SScott Long return; 1845ad6d6297SScott Long } 1846ad6d6297SScott Long } 1847ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { 1848ad6d6297SScott Long if(nseg != 0) { 1849ad6d6297SScott Long bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 1850ad6d6297SScott Long } 1851ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 1852f1c579b1SScott Long return; 1853f1c579b1SScott Long } 1854ad6d6297SScott Long if(acb->srboutstandingcount >= ARCMSR_MAX_OUTSTANDING_CMD) { 185515735becSScott Long xpt_freeze_simq(acb->psim, 1); 185615735becSScott Long pccb->ccb_h.status = CAM_REQUEUE_REQ; 1857dc3a205bSScott Long acb->acb_flags |= ACB_F_CAM_DEV_QFRZN; 1858ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 1859ad6d6297SScott Long return; 1860f1c579b1SScott Long } 186115735becSScott Long pccb->ccb_h.status |= CAM_SIM_QUEUED; 1862ad6d6297SScott Long arcmsr_build_srb(srb, dm_segs, nseg); 1863ad6d6297SScott Long arcmsr_post_srb(acb, srb); 1864f1c579b1SScott Long return; 1865f1c579b1SScott Long } 1866f1c579b1SScott Long /* 1867f1c579b1SScott Long ***************************************************************************************** 1868f1c579b1SScott Long ***************************************************************************************** 1869f1c579b1SScott Long */ 1870ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb) 1871f1c579b1SScott Long { 1872ad6d6297SScott Long struct CommandControlBlock *srb; 1873ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *) abortccb->ccb_h.arcmsr_ccbacb_ptr; 187444f05562SScott Long u_int32_t intmask_org; 1875ad6d6297SScott Long int i=0; 1876f1c579b1SScott Long 1877ad6d6297SScott Long acb->num_aborts++; 1878f1c579b1SScott Long /* 1879ad6d6297SScott Long *************************************************************************** 1880f1c579b1SScott Long ** It is the upper layer do abort command this lock just prior to calling us. 1881f1c579b1SScott Long ** First determine if we currently own this command. 1882f1c579b1SScott Long ** Start by searching the device queue. If not found 1883f1c579b1SScott Long ** at all, and the system wanted us to just abort the 1884f1c579b1SScott Long ** command return success. 1885ad6d6297SScott Long *************************************************************************** 1886f1c579b1SScott Long */ 1887ad6d6297SScott Long if(acb->srboutstandingcount!=0) { 1888ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 1889ad6d6297SScott Long srb=acb->psrb_pool[i]; 1890ad6d6297SScott Long if(srb->startdone==ARCMSR_SRB_START) { 1891ad6d6297SScott Long if(srb->pccb==abortccb) { 1892ad6d6297SScott Long srb->startdone=ARCMSR_SRB_ABORTED; 1893ad6d6297SScott Long printf("arcmsr%d:scsi id=%d lun=%d abort srb '%p'" 1894ad6d6297SScott Long "outstanding command \n" 1895ad6d6297SScott Long , acb->pci_unit, abortccb->ccb_h.target_id 1896ad6d6297SScott Long , abortccb->ccb_h.target_lun, srb); 1897ad6d6297SScott Long goto abort_outstanding_cmd; 1898f1c579b1SScott Long } 1899f1c579b1SScott Long } 1900f1c579b1SScott Long } 1901f1c579b1SScott Long } 1902f1c579b1SScott Long return(FALSE); 1903ad6d6297SScott Long abort_outstanding_cmd: 1904ad6d6297SScott Long /* disable all outbound interrupt */ 190544f05562SScott Long intmask_org=arcmsr_disable_allintr(acb); 1906ad6d6297SScott Long arcmsr_polling_srbdone(acb, srb); 190744f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 190844f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 1909ad6d6297SScott Long return (TRUE); 1910f1c579b1SScott Long } 1911f1c579b1SScott Long /* 1912f1c579b1SScott Long **************************************************************************** 1913f1c579b1SScott Long **************************************************************************** 1914f1c579b1SScott Long */ 1915ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb) 1916f1c579b1SScott Long { 1917ad6d6297SScott Long int retry=0; 1918f1c579b1SScott Long 1919ad6d6297SScott Long acb->num_resets++; 1920ad6d6297SScott Long acb->acb_flags |=ACB_F_BUS_RESET; 1921ad6d6297SScott Long while(acb->srboutstandingcount!=0 && retry < 400) { 192244f05562SScott Long arcmsr_interrupt(acb); 1923ad6d6297SScott Long UDELAY(25000); 1924ad6d6297SScott Long retry++; 1925ad6d6297SScott Long } 1926ad6d6297SScott Long arcmsr_iop_reset(acb); 1927ad6d6297SScott Long acb->acb_flags &= ~ACB_F_BUS_RESET; 1928f1c579b1SScott Long return; 1929f1c579b1SScott Long } 1930f1c579b1SScott Long /* 1931ad6d6297SScott Long ************************************************************************** 1932ad6d6297SScott Long ************************************************************************** 1933ad6d6297SScott Long */ 1934ad6d6297SScott Long static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, 1935ad6d6297SScott Long union ccb * pccb) 1936ad6d6297SScott Long { 1937ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 1938ad6d6297SScott Long switch (pccb->csio.cdb_io.cdb_bytes[0]) { 1939ad6d6297SScott Long case INQUIRY: { 1940ad6d6297SScott Long unsigned char inqdata[36]; 1941ad6d6297SScott Long char *buffer=pccb->csio.data_ptr;; 1942ad6d6297SScott Long 1943ad6d6297SScott Long if (pccb->ccb_h.target_lun) { 1944ad6d6297SScott Long pccb->ccb_h.status |= CAM_SEL_TIMEOUT; 1945ad6d6297SScott Long xpt_done(pccb); 1946ad6d6297SScott Long return; 1947ad6d6297SScott Long } 1948ad6d6297SScott Long inqdata[0] = T_PROCESSOR; 1949ad6d6297SScott Long /* Periph Qualifier & Periph Dev Type */ 1950ad6d6297SScott Long inqdata[1] = 0; 1951ad6d6297SScott Long /* rem media bit & Dev Type Modifier */ 1952ad6d6297SScott Long inqdata[2] = 0; 1953ad6d6297SScott Long /* ISO, ECMA, & ANSI versions */ 1954ad6d6297SScott Long inqdata[4] = 31; 1955ad6d6297SScott Long /* length of additional data */ 1956ad6d6297SScott Long strncpy(&inqdata[8], "Areca ", 8); 1957ad6d6297SScott Long /* Vendor Identification */ 1958ad6d6297SScott Long strncpy(&inqdata[16], "RAID controller ", 16); 1959ad6d6297SScott Long /* Product Identification */ 1960ad6d6297SScott Long strncpy(&inqdata[32], "R001", 4); /* Product Revision */ 1961ad6d6297SScott Long memcpy(buffer, inqdata, sizeof(inqdata)); 1962ad6d6297SScott Long xpt_done(pccb); 1963ad6d6297SScott Long } 1964ad6d6297SScott Long break; 1965ad6d6297SScott Long case WRITE_BUFFER: 1966ad6d6297SScott Long case READ_BUFFER: { 1967ad6d6297SScott Long if (arcmsr_iop_message_xfer(acb, pccb)) { 1968ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 1969ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 1970ad6d6297SScott Long } 1971ad6d6297SScott Long xpt_done(pccb); 1972ad6d6297SScott Long } 1973ad6d6297SScott Long break; 1974ad6d6297SScott Long default: 1975ad6d6297SScott Long xpt_done(pccb); 1976ad6d6297SScott Long } 1977ad6d6297SScott Long } 1978ad6d6297SScott Long /* 1979f1c579b1SScott Long ********************************************************************* 1980f1c579b1SScott Long ********************************************************************* 1981f1c579b1SScott Long */ 1982ad6d6297SScott Long static void arcmsr_action(struct cam_sim * psim, union ccb * pccb) 1983f1c579b1SScott Long { 1984ad6d6297SScott Long struct AdapterControlBlock * acb; 1985f1c579b1SScott Long 1986ad6d6297SScott Long acb=(struct AdapterControlBlock *) cam_sim_softc(psim); 1987ad6d6297SScott Long if(acb==NULL) { 1988ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 1989f1c579b1SScott Long xpt_done(pccb); 1990f1c579b1SScott Long return; 1991f1c579b1SScott Long } 1992ad6d6297SScott Long switch (pccb->ccb_h.func_code) { 1993ad6d6297SScott Long case XPT_SCSI_IO: { 1994ad6d6297SScott Long struct CommandControlBlock *srb; 1995ad6d6297SScott Long int target=pccb->ccb_h.target_id; 1996f1c579b1SScott Long 1997ad6d6297SScott Long if(target == 16) { 1998ad6d6297SScott Long /* virtual device for iop message transfer */ 1999ad6d6297SScott Long arcmsr_handle_virtual_command(acb, pccb); 2000ad6d6297SScott Long return; 2001ad6d6297SScott Long } 2002ad6d6297SScott Long if((srb=arcmsr_get_freesrb(acb)) == NULL) { 2003ad6d6297SScott Long pccb->ccb_h.status |= CAM_RESRC_UNAVAIL; 2004f1c579b1SScott Long xpt_done(pccb); 2005f1c579b1SScott Long return; 2006f1c579b1SScott Long } 2007ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbsrb_ptr=srb; 2008ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbacb_ptr=acb; 2009ad6d6297SScott Long srb->pccb=pccb; 2010ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 2011ad6d6297SScott Long if(!(pccb->ccb_h.flags & CAM_SCATTER_VALID)) { 2012ad6d6297SScott Long /* Single buffer */ 2013ad6d6297SScott Long if(!(pccb->ccb_h.flags & CAM_DATA_PHYS)) { 2014ad6d6297SScott Long /* Buffer is virtual */ 2015ad6d6297SScott Long u_int32_t error, s; 2016f1c579b1SScott Long 2017f1c579b1SScott Long s=splsoftvm(); 2018ad6d6297SScott Long error = bus_dmamap_load(acb->dm_segs_dmat 2019ad6d6297SScott Long , srb->dm_segs_dmamap 2020ad6d6297SScott Long , pccb->csio.data_ptr 2021ad6d6297SScott Long , pccb->csio.dxfer_len 2022ad6d6297SScott Long , arcmsr_executesrb, srb, /*flags*/0); 2023ad6d6297SScott Long if(error == EINPROGRESS) { 2024ad6d6297SScott Long xpt_freeze_simq(acb->psim, 1); 2025f1c579b1SScott Long pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 2026f1c579b1SScott Long } 2027f1c579b1SScott Long splx(s); 2028ad6d6297SScott Long } else { 2029ad6d6297SScott Long /* Buffer is physical */ 20301c7e9358SScott Long panic("arcmsr: CAM_DATA_PHYS not supported"); 2031f1c579b1SScott Long } 2032ad6d6297SScott Long } else { 2033ad6d6297SScott Long /* Scatter/gather list */ 2034f1c579b1SScott Long struct bus_dma_segment *segs; 2035f1c579b1SScott Long 2036ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0 2037ad6d6297SScott Long || (pccb->ccb_h.flags & CAM_DATA_PHYS) != 0) { 2038ad6d6297SScott Long pccb->ccb_h.status |= CAM_PROVIDE_FAIL; 2039f1c579b1SScott Long xpt_done(pccb); 2040ad6d6297SScott Long free(srb, M_DEVBUF); 2041f1c579b1SScott Long return; 2042f1c579b1SScott Long } 2043f1c579b1SScott Long segs=(struct bus_dma_segment *)pccb->csio.data_ptr; 2044ad6d6297SScott Long arcmsr_executesrb(srb, segs, pccb->csio.sglist_cnt, 0); 2045f1c579b1SScott Long } 2046ad6d6297SScott Long } else { 2047ad6d6297SScott Long arcmsr_executesrb(srb, NULL, 0, 0); 2048f1c579b1SScott Long } 2049f1c579b1SScott Long break; 2050f1c579b1SScott Long } 2051ad6d6297SScott Long case XPT_TARGET_IO: { 2052ad6d6297SScott Long /* target mode not yet support vendor specific commands. */ 2053ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2054f1c579b1SScott Long xpt_done(pccb); 2055f1c579b1SScott Long break; 2056f1c579b1SScott Long } 2057ad6d6297SScott Long case XPT_PATH_INQ: { 2058f1c579b1SScott Long struct ccb_pathinq *cpi= &pccb->cpi; 2059f1c579b1SScott Long 2060f1c579b1SScott Long cpi->version_num=1; 2061f1c579b1SScott Long cpi->hba_inquiry=PI_SDTR_ABLE | PI_TAG_ABLE; 2062f1c579b1SScott Long cpi->target_sprt=0; 2063f1c579b1SScott Long cpi->hba_misc=0; 2064f1c579b1SScott Long cpi->hba_eng_cnt=0; 2065ad6d6297SScott Long cpi->max_target=ARCMSR_MAX_TARGETID; /* 0-16 */ 2066ad6d6297SScott Long cpi->max_lun=ARCMSR_MAX_TARGETLUN; /* 0-7 */ 2067ad6d6297SScott Long cpi->initiator_id=ARCMSR_SCSI_INITIATOR_ID; /* 255 */ 2068f1c579b1SScott Long cpi->bus_id=cam_sim_bus(psim); 2069f1c579b1SScott Long strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 2070f1c579b1SScott Long strncpy(cpi->hba_vid, "ARCMSR", HBA_IDLEN); 2071f1c579b1SScott Long strncpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN); 2072f1c579b1SScott Long cpi->unit_number=cam_sim_unit(psim); 207344f05562SScott Long #ifdef CAM_NEW_TRAN_CODE 2074fa9ed865SMatt Jacob cpi->transport = XPORT_SPI; 2075fa9ed865SMatt Jacob cpi->transport_version = 2; 2076fa9ed865SMatt Jacob cpi->protocol = PROTO_SCSI; 2077fa9ed865SMatt Jacob cpi->protocol_version = SCSI_REV_2; 207844f05562SScott Long #endif 2079ad6d6297SScott Long cpi->ccb_h.status |= CAM_REQ_CMP; 2080f1c579b1SScott Long xpt_done(pccb); 2081f1c579b1SScott Long break; 2082f1c579b1SScott Long } 2083ad6d6297SScott Long case XPT_ABORT: { 2084f1c579b1SScott Long union ccb *pabort_ccb; 2085f1c579b1SScott Long 2086f1c579b1SScott Long pabort_ccb=pccb->cab.abort_ccb; 2087ad6d6297SScott Long switch (pabort_ccb->ccb_h.func_code) { 2088f1c579b1SScott Long case XPT_ACCEPT_TARGET_IO: 2089f1c579b1SScott Long case XPT_IMMED_NOTIFY: 2090f1c579b1SScott Long case XPT_CONT_TARGET_IO: 2091ad6d6297SScott Long if(arcmsr_seek_cmd2abort(pabort_ccb)==TRUE) { 2092ad6d6297SScott Long pabort_ccb->ccb_h.status |= CAM_REQ_ABORTED; 2093f1c579b1SScott Long xpt_done(pabort_ccb); 2094ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2095ad6d6297SScott Long } else { 2096f1c579b1SScott Long xpt_print_path(pabort_ccb->ccb_h.path); 2097f1c579b1SScott Long printf("Not found\n"); 2098ad6d6297SScott Long pccb->ccb_h.status |= CAM_PATH_INVALID; 2099f1c579b1SScott Long } 2100f1c579b1SScott Long break; 2101f1c579b1SScott Long case XPT_SCSI_IO: 2102ad6d6297SScott Long pccb->ccb_h.status |= CAM_UA_ABORT; 2103f1c579b1SScott Long break; 2104f1c579b1SScott Long default: 2105ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2106f1c579b1SScott Long break; 2107f1c579b1SScott Long } 2108f1c579b1SScott Long xpt_done(pccb); 2109f1c579b1SScott Long break; 2110f1c579b1SScott Long } 2111f1c579b1SScott Long case XPT_RESET_BUS: 2112ad6d6297SScott Long case XPT_RESET_DEV: { 2113ad6d6297SScott Long u_int32_t i; 2114f1c579b1SScott Long 2115ad6d6297SScott Long arcmsr_bus_reset(acb); 2116ad6d6297SScott Long for (i=0; i < 500; i++) { 2117f1c579b1SScott Long DELAY(1000); 2118f1c579b1SScott Long } 2119ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2120f1c579b1SScott Long xpt_done(pccb); 2121f1c579b1SScott Long break; 2122f1c579b1SScott Long } 2123ad6d6297SScott Long case XPT_TERM_IO: { 2124ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2125f1c579b1SScott Long xpt_done(pccb); 2126f1c579b1SScott Long break; 2127f1c579b1SScott Long } 2128ad6d6297SScott Long case XPT_GET_TRAN_SETTINGS: { 2129ad6d6297SScott Long struct ccb_trans_settings *cts; 2130ad6d6297SScott Long 2131ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 2132ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 2133ad6d6297SScott Long xpt_done(pccb); 2134ad6d6297SScott Long break; 2135ad6d6297SScott Long } 2136ad6d6297SScott Long cts= &pccb->cts; 213744f05562SScott Long #ifdef CAM_NEW_TRAN_CODE 213844f05562SScott Long { 213944f05562SScott Long struct ccb_trans_settings_scsi *scsi; 214044f05562SScott Long struct ccb_trans_settings_spi *spi; 214144f05562SScott Long 2142ad6d6297SScott Long scsi = &cts->proto_specific.scsi; 2143ad6d6297SScott Long spi = &cts->xport_specific.spi; 2144fa9ed865SMatt Jacob cts->protocol = PROTO_SCSI; 2145fa9ed865SMatt Jacob cts->protocol_version = SCSI_REV_2; 2146fa9ed865SMatt Jacob cts->transport = XPORT_SPI; 2147fa9ed865SMatt Jacob cts->transport_version = 2; 2148fa9ed865SMatt Jacob spi->flags = CTS_SPI_FLAGS_DISC_ENB; 2149fa9ed865SMatt Jacob spi->sync_period=3; 2150fa9ed865SMatt Jacob spi->sync_offset=32; 2151fa9ed865SMatt Jacob spi->bus_width=MSG_EXT_WDTR_BUS_16_BIT; 2152fa9ed865SMatt Jacob scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 2153fa9ed865SMatt Jacob spi->valid = CTS_SPI_VALID_SYNC_RATE 2154fa9ed865SMatt Jacob | CTS_SPI_VALID_SYNC_OFFSET 2155fa9ed865SMatt Jacob | CTS_SPI_VALID_BUS_WIDTH; 2156fa9ed865SMatt Jacob scsi->valid = CTS_SCSI_VALID_TQ; 215744f05562SScott Long } 215844f05562SScott Long #else 215944f05562SScott Long { 216044f05562SScott Long cts->flags=(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB); 216144f05562SScott Long cts->sync_period=3; 216244f05562SScott Long cts->sync_offset=32; 216344f05562SScott Long cts->bus_width=MSG_EXT_WDTR_BUS_16_BIT; 216444f05562SScott Long cts->valid=CCB_TRANS_SYNC_RATE_VALID | 216544f05562SScott Long CCB_TRANS_SYNC_OFFSET_VALID | 216644f05562SScott Long CCB_TRANS_BUS_WIDTH_VALID | 216744f05562SScott Long CCB_TRANS_DISC_VALID | 216844f05562SScott Long CCB_TRANS_TQ_VALID; 216944f05562SScott Long } 217044f05562SScott Long #endif 2171ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2172ad6d6297SScott Long xpt_done(pccb); 2173ad6d6297SScott Long break; 2174ad6d6297SScott Long } 2175ad6d6297SScott Long case XPT_SET_TRAN_SETTINGS: { 2176ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 2177ad6d6297SScott Long xpt_done(pccb); 2178ad6d6297SScott Long break; 2179ad6d6297SScott Long } 2180ad6d6297SScott Long case XPT_CALC_GEOMETRY: { 2181ad6d6297SScott Long struct ccb_calc_geometry *ccg; 2182ad6d6297SScott Long u_int32_t size_mb; 2183ad6d6297SScott Long u_int32_t secs_per_cylinder; 2184ad6d6297SScott Long 2185ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 2186ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 2187ad6d6297SScott Long xpt_done(pccb); 2188ad6d6297SScott Long break; 2189ad6d6297SScott Long } 2190f1c579b1SScott Long ccg= &pccb->ccg; 2191ad6d6297SScott Long if (ccg->block_size == 0) { 2192ad6d6297SScott Long pccb->ccb_h.status = CAM_REQ_INVALID; 2193ad6d6297SScott Long xpt_done(pccb); 2194ad6d6297SScott Long break; 2195ad6d6297SScott Long } 2196ad6d6297SScott Long if(((1024L * 1024L)/ccg->block_size) < 0) { 2197ad6d6297SScott Long pccb->ccb_h.status = CAM_REQ_INVALID; 2198ad6d6297SScott Long xpt_done(pccb); 2199ad6d6297SScott Long break; 2200ad6d6297SScott Long } 2201f1c579b1SScott Long size_mb=ccg->volume_size/((1024L * 1024L)/ccg->block_size); 2202ad6d6297SScott Long if(size_mb > 1024 ) { 2203f1c579b1SScott Long ccg->heads=255; 2204f1c579b1SScott Long ccg->secs_per_track=63; 2205ad6d6297SScott Long } else { 2206f1c579b1SScott Long ccg->heads=64; 2207f1c579b1SScott Long ccg->secs_per_track=32; 2208f1c579b1SScott Long } 2209f1c579b1SScott Long secs_per_cylinder=ccg->heads * ccg->secs_per_track; 2210f1c579b1SScott Long ccg->cylinders=ccg->volume_size / secs_per_cylinder; 2211ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2212f1c579b1SScott Long xpt_done(pccb); 2213f1c579b1SScott Long break; 2214f1c579b1SScott Long } 2215f1c579b1SScott Long default: 2216ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2217f1c579b1SScott Long xpt_done(pccb); 2218f1c579b1SScott Long break; 2219f1c579b1SScott Long } 2220f1c579b1SScott Long return; 2221f1c579b1SScott Long } 2222f1c579b1SScott Long /* 2223f1c579b1SScott Long ********************************************************************** 2224f1c579b1SScott Long ********************************************************************** 2225f1c579b1SScott Long */ 222644f05562SScott Long static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) 2227f1c579b1SScott Long { 2228ad6d6297SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 222944f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 223044f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 2231ad6d6297SScott Long printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 2232ad6d6297SScott Long } 2233f1c579b1SScott Long return; 2234f1c579b1SScott Long } 2235f1c579b1SScott Long /* 2236f1c579b1SScott Long ********************************************************************** 2237f1c579b1SScott Long ********************************************************************** 2238f1c579b1SScott Long */ 223944f05562SScott Long static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb) 224044f05562SScott Long { 224144f05562SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 224244f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 224344f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_START_BGRB); 224444f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 224544f05562SScott Long printf( "arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 224644f05562SScott Long } 224744f05562SScott Long return; 224844f05562SScott Long } 224944f05562SScott Long /* 225044f05562SScott Long ********************************************************************** 225144f05562SScott Long ********************************************************************** 225244f05562SScott Long */ 225344f05562SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) 225444f05562SScott Long { 225544f05562SScott Long switch (acb->adapter_type) { 225644f05562SScott Long case ACB_ADAPTER_TYPE_A: 225744f05562SScott Long arcmsr_start_hba_bgrb(acb); 225844f05562SScott Long break; 225944f05562SScott Long case ACB_ADAPTER_TYPE_B: 226044f05562SScott Long arcmsr_start_hbb_bgrb(acb); 226144f05562SScott Long break; 226244f05562SScott Long } 226344f05562SScott Long return; 226444f05562SScott Long } 226544f05562SScott Long /* 226644f05562SScott Long ********************************************************************** 226744f05562SScott Long ** 226844f05562SScott Long ********************************************************************** 226944f05562SScott Long */ 227044f05562SScott Long static void arcmsr_polling_hba_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 2271f1c579b1SScott Long { 2272ad6d6297SScott Long struct CommandControlBlock *srb; 227344f05562SScott Long u_int32_t flag_srb, outbound_intstatus, poll_srb_done=0, poll_count=0; 2274f1c579b1SScott Long 227544f05562SScott Long polling_ccb_retry: 2276ad6d6297SScott Long poll_count++; 227744f05562SScott Long outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 227844f05562SScott Long 0, outbound_intstatus) & acb->outbound_int_enable; 227944f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 228044f05562SScott Long 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/ 228144f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 2282ad6d6297SScott Long while(1) { 228344f05562SScott Long if((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 228444f05562SScott Long 0, outbound_queueport))==0xFFFFFFFF) { 2285ad6d6297SScott Long if(poll_srb_done) { 2286ad6d6297SScott Long break;/*chip FIFO no ccb for completion already*/ 2287ad6d6297SScott Long } else { 2288ad6d6297SScott Long UDELAY(25000); 2289ad6d6297SScott Long if(poll_count > 100) { 2290ad6d6297SScott Long break; 2291f1c579b1SScott Long } 229244f05562SScott Long goto polling_ccb_retry; 2293f1c579b1SScott Long } 2294ad6d6297SScott Long } 2295ad6d6297SScott Long /* check ifcommand done with no error*/ 229644f05562SScott Long srb=(struct CommandControlBlock *) 229744f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 229844f05562SScott Long poll_srb_done = (srb==poll_srb) ? 1:0; 2299ad6d6297SScott Long if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) { 230044f05562SScott Long if(srb->startdone==ARCMSR_SRB_ABORTED) { 2301ad6d6297SScott Long printf("arcmsr%d: scsi id=%d lun=%d srb='%p'" 2302ad6d6297SScott Long "poll command abort successfully \n" 2303ad6d6297SScott Long , acb->pci_unit 2304ad6d6297SScott Long , srb->pccb->ccb_h.target_id 2305ad6d6297SScott Long , srb->pccb->ccb_h.target_lun, srb); 2306ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 2307ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 2308ad6d6297SScott Long continue; 2309ad6d6297SScott Long } 2310ad6d6297SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 2311ad6d6297SScott Long "srboutstandingcount=%d \n" 2312ad6d6297SScott Long , acb->pci_unit 2313ad6d6297SScott Long , srb, acb->srboutstandingcount); 2314ad6d6297SScott Long continue; 2315ad6d6297SScott Long } 231644f05562SScott Long arcmsr_report_srb_state(acb, srb, flag_srb); 2317ad6d6297SScott Long } /*drain reply FIFO*/ 2318f1c579b1SScott Long return; 2319f1c579b1SScott Long } 2320f1c579b1SScott Long /* 2321f1c579b1SScott Long ********************************************************************** 232244f05562SScott Long ** 2323ad6d6297SScott Long ********************************************************************** 2324ad6d6297SScott Long */ 232544f05562SScott Long static void arcmsr_polling_hbb_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 232644f05562SScott Long { 232744f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 232844f05562SScott Long struct CommandControlBlock *srb; 232944f05562SScott Long u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 233044f05562SScott Long int index; 233144f05562SScott Long 233244f05562SScott Long polling_ccb_retry: 233344f05562SScott Long poll_count++; 233444f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 233544f05562SScott Long 0, iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 233644f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 233744f05562SScott Long while(1) { 233844f05562SScott Long index=phbbmu->doneq_index; 233944f05562SScott Long if((flag_srb=phbbmu->done_qbuffer[index]) == 0) { 234044f05562SScott Long if(poll_srb_done) { 234144f05562SScott Long break;/*chip FIFO no ccb for completion already*/ 234244f05562SScott Long } else { 234344f05562SScott Long UDELAY(25000); 234444f05562SScott Long if(poll_count > 100) { 234544f05562SScott Long break; 234644f05562SScott Long } 234744f05562SScott Long goto polling_ccb_retry; 234844f05562SScott Long } 234944f05562SScott Long } 235044f05562SScott Long phbbmu->done_qbuffer[index]=0; 235144f05562SScott Long index++; 235244f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 235344f05562SScott Long phbbmu->doneq_index=index; 235444f05562SScott Long /* check if command done with no error*/ 235544f05562SScott Long srb=(struct CommandControlBlock *) 235644f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 235744f05562SScott Long poll_srb_done = (srb==poll_srb) ? 1:0; 235844f05562SScott Long if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) { 235944f05562SScott Long if(srb->startdone==ARCMSR_SRB_ABORTED) { 236044f05562SScott Long printf("arcmsr%d: scsi id=%d lun=%d srb='%p'" 236144f05562SScott Long "poll command abort successfully \n" 236244f05562SScott Long , acb->pci_unit 236344f05562SScott Long , srb->pccb->ccb_h.target_id 236444f05562SScott Long , srb->pccb->ccb_h.target_lun, srb); 236544f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 236644f05562SScott Long arcmsr_srb_complete(srb, 1); 236744f05562SScott Long continue; 236844f05562SScott Long } 236944f05562SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 237044f05562SScott Long "srboutstandingcount=%d \n" 237144f05562SScott Long , acb->pci_unit 237244f05562SScott Long , srb, acb->srboutstandingcount); 237344f05562SScott Long continue; 237444f05562SScott Long } 237544f05562SScott Long arcmsr_report_srb_state(acb, srb, flag_srb); 237644f05562SScott Long } /*drain reply FIFO*/ 237744f05562SScott Long return; 237844f05562SScott Long } 237944f05562SScott Long /* 238044f05562SScott Long ********************************************************************** 238144f05562SScott Long ********************************************************************** 238244f05562SScott Long */ 238344f05562SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 238444f05562SScott Long { 238544f05562SScott Long switch (acb->adapter_type) { 238644f05562SScott Long case ACB_ADAPTER_TYPE_A: { 238744f05562SScott Long arcmsr_polling_hba_srbdone(acb, poll_srb); 238844f05562SScott Long } 238944f05562SScott Long break; 239044f05562SScott Long case ACB_ADAPTER_TYPE_B: { 239144f05562SScott Long arcmsr_polling_hbb_srbdone(acb, poll_srb); 239244f05562SScott Long } 239344f05562SScott Long break; 239444f05562SScott Long } 239544f05562SScott Long } 239644f05562SScott Long /* 239744f05562SScott Long ********************************************************************** 239844f05562SScott Long ********************************************************************** 239944f05562SScott Long */ 240044f05562SScott Long static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) 2401ad6d6297SScott Long { 2402ad6d6297SScott Long char *acb_firm_model=acb->firm_model; 2403ad6d6297SScott Long char *acb_firm_version=acb->firm_version; 240444f05562SScott Long size_t iop_firm_model=offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[15]); /*firm_model,15,60-67*/ 240544f05562SScott Long size_t iop_firm_version=offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[17]); /*firm_version,17,68-83*/ 2406ad6d6297SScott Long int i; 2407ad6d6297SScott Long 240844f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 240944f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 2410ad6d6297SScott Long printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n" 2411ad6d6297SScott Long , acb->pci_unit); 2412ad6d6297SScott Long } 2413ad6d6297SScott Long i=0; 2414ad6d6297SScott Long while(i<8) { 241544f05562SScott Long *acb_firm_model=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 2416ad6d6297SScott Long /* 8 bytes firm_model, 15, 60-67*/ 2417ad6d6297SScott Long acb_firm_model++; 2418ad6d6297SScott Long i++; 2419ad6d6297SScott Long } 2420ad6d6297SScott Long i=0; 2421ad6d6297SScott Long while(i<16) { 242244f05562SScott Long *acb_firm_version=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 2423ad6d6297SScott Long /* 16 bytes firm_version, 17, 68-83*/ 2424ad6d6297SScott Long acb_firm_version++; 2425ad6d6297SScott Long i++; 2426ad6d6297SScott Long } 2427ad6d6297SScott Long printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION); 2428ad6d6297SScott Long printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version); 242944f05562SScott Long acb->firm_request_len=CHIP_REG_READ32(HBA_MessageUnit, 243044f05562SScott Long 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 243144f05562SScott Long acb->firm_numbers_queue=CHIP_REG_READ32(HBA_MessageUnit, 243244f05562SScott Long 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 243344f05562SScott Long acb->firm_sdram_size=CHIP_REG_READ32(HBA_MessageUnit, 243444f05562SScott Long 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 243544f05562SScott Long acb->firm_ide_channels=CHIP_REG_READ32(HBA_MessageUnit, 243644f05562SScott Long 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 2437ad6d6297SScott Long return; 2438ad6d6297SScott Long } 2439ad6d6297SScott Long /* 2440ad6d6297SScott Long ********************************************************************** 244144f05562SScott Long ********************************************************************** 244244f05562SScott Long */ 244344f05562SScott Long static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) 244444f05562SScott Long { 244544f05562SScott Long char *acb_firm_model=acb->firm_model; 244644f05562SScott Long char *acb_firm_version=acb->firm_version; 244744f05562SScott Long size_t iop_firm_model=offsetof(struct HBB_RWBUFFER, 244844f05562SScott Long msgcode_rwbuffer[15]); /*firm_model,15,60-67*/ 244944f05562SScott Long size_t iop_firm_version=offsetof(struct HBB_RWBUFFER, 245044f05562SScott Long msgcode_rwbuffer[17]); /*firm_version,17,68-83*/ 245144f05562SScott Long int i; 245244f05562SScott Long 245344f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 245444f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG); 245544f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 245644f05562SScott Long printf( "arcmsr%d: wait" 245744f05562SScott Long "'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 245844f05562SScott Long } 245944f05562SScott Long i=0; 246044f05562SScott Long while(i<8) { 246144f05562SScott Long *acb_firm_model=bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_model+i); 246244f05562SScott Long /* 8 bytes firm_model, 15, 60-67*/ 246344f05562SScott Long acb_firm_model++; 246444f05562SScott Long i++; 246544f05562SScott Long } 246644f05562SScott Long i=0; 246744f05562SScott Long while(i<16) { 246844f05562SScott Long *acb_firm_version=bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_version+i); 246944f05562SScott Long /* 16 bytes firm_version, 17, 68-83*/ 247044f05562SScott Long acb_firm_version++; 247144f05562SScott Long i++; 247244f05562SScott Long } 247344f05562SScott Long printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION); 247444f05562SScott Long printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version); 247544f05562SScott Long acb->firm_request_len=CHIP_REG_READ32(HBB_RWBUFFER, 247644f05562SScott Long 1, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 247744f05562SScott Long acb->firm_numbers_queue=CHIP_REG_READ32(HBB_RWBUFFER, 247844f05562SScott Long 1, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 247944f05562SScott Long acb->firm_sdram_size=CHIP_REG_READ32(HBB_RWBUFFER, 248044f05562SScott Long 1, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 248144f05562SScott Long acb->firm_ide_channels=CHIP_REG_READ32(HBB_RWBUFFER, 248244f05562SScott Long 1, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 248344f05562SScott Long return; 248444f05562SScott Long } 248544f05562SScott Long /* 248644f05562SScott Long ********************************************************************** 248744f05562SScott Long ********************************************************************** 248844f05562SScott Long */ 248944f05562SScott Long static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) 249044f05562SScott Long { 249144f05562SScott Long switch (acb->adapter_type) { 249244f05562SScott Long case ACB_ADAPTER_TYPE_A: { 249344f05562SScott Long arcmsr_get_hba_config(acb); 249444f05562SScott Long } 249544f05562SScott Long break; 249644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 249744f05562SScott Long arcmsr_get_hbb_config(acb); 249844f05562SScott Long } 249944f05562SScott Long break; 250044f05562SScott Long } 250144f05562SScott Long return; 250244f05562SScott Long } 250344f05562SScott Long /* 250444f05562SScott Long ********************************************************************** 250544f05562SScott Long ********************************************************************** 250644f05562SScott Long */ 250744f05562SScott Long static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb) 250844f05562SScott Long { 250944f05562SScott Long int timeout=0; 251044f05562SScott Long 251144f05562SScott Long switch (acb->adapter_type) { 251244f05562SScott Long case ACB_ADAPTER_TYPE_A: { 251344f05562SScott Long while ((CHIP_REG_READ32(HBA_MessageUnit, 251444f05562SScott Long 0, outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) 251544f05562SScott Long { 251644f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 251744f05562SScott Long { 251844f05562SScott Long printf( "arcmsr%d:" 251944f05562SScott Long "timed out waiting for firmware \n", acb->pci_unit); 252044f05562SScott Long return; 252144f05562SScott Long } 252244f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 252344f05562SScott Long } 252444f05562SScott Long } 252544f05562SScott Long break; 252644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 252744f05562SScott Long while ((CHIP_REG_READ32(HBB_DOORBELL, 252844f05562SScott Long 0, iop2drv_doorbell) & ARCMSR_MESSAGE_FIRMWARE_OK) == 0) 252944f05562SScott Long { 253044f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 253144f05562SScott Long { 253244f05562SScott Long printf( "arcmsr%d:" 253344f05562SScott Long " timed out waiting for firmware \n", acb->pci_unit); 253444f05562SScott Long return; 253544f05562SScott Long } 253644f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 253744f05562SScott Long } 253844f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 253944f05562SScott Long 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 254044f05562SScott Long } 254144f05562SScott Long break; 254244f05562SScott Long } 254344f05562SScott Long return; 254444f05562SScott Long } 254544f05562SScott Long /* 254644f05562SScott Long ********************************************************************** 254744f05562SScott Long ********************************************************************** 254844f05562SScott Long */ 254944f05562SScott Long static void arcmsr_clear_doorbell_queue_buffer( struct AdapterControlBlock *acb) 255044f05562SScott Long { 255144f05562SScott Long switch (acb->adapter_type) { 255244f05562SScott Long case ACB_ADAPTER_TYPE_A: { 255344f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 255444f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 255544f05562SScott Long 0, outbound_doorbell, 255644f05562SScott Long CHIP_REG_READ32(HBA_MessageUnit, 255744f05562SScott Long 0, outbound_doorbell));/*clear doorbell interrupt */ 255844f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 255944f05562SScott Long 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 256044f05562SScott Long } 256144f05562SScott Long break; 256244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 256344f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 256444f05562SScott Long 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt and message state*/ 256544f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 256644f05562SScott Long 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 256744f05562SScott Long /* let IOP know data has been read */ 256844f05562SScott Long } 256944f05562SScott Long break; 257044f05562SScott Long } 257144f05562SScott Long return; 257244f05562SScott Long } 257344f05562SScott Long /* 257444f05562SScott Long ************************************************************************ 257544f05562SScott Long ************************************************************************ 257644f05562SScott Long */ 257744f05562SScott Long static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb) 257844f05562SScott Long { 257944f05562SScott Long unsigned long srb_phyaddr; 258044f05562SScott Long u_int32_t srb_phyaddr_hi32; 258144f05562SScott Long 258244f05562SScott Long /* 258344f05562SScott Long ******************************************************************** 258444f05562SScott Long ** here we need to tell iop 331 our freesrb.HighPart 258544f05562SScott Long ** if freesrb.HighPart is not zero 258644f05562SScott Long ******************************************************************** 258744f05562SScott Long */ 258844f05562SScott Long srb_phyaddr= (unsigned long) acb->srb_phyaddr; 258944f05562SScott Long srb_phyaddr_hi32=(u_int32_t) ((srb_phyaddr>>16)>>16); 259044f05562SScott Long switch (acb->adapter_type) { 259144f05562SScott Long case ACB_ADAPTER_TYPE_A: { 259244f05562SScott Long if(srb_phyaddr_hi32!=0) { 259344f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 259444f05562SScott Long 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 259544f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 259644f05562SScott Long 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 259744f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 259844f05562SScott Long 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 259944f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 260044f05562SScott Long printf( "arcmsr%d:" 260144f05562SScott Long " 'set srb high part physical address' timeout \n", acb->pci_unit); 260244f05562SScott Long return FALSE; 260344f05562SScott Long } 260444f05562SScott Long } 260544f05562SScott Long } 260644f05562SScott Long break; 260744f05562SScott Long /* 260844f05562SScott Long *********************************************************************** 260944f05562SScott Long ** if adapter type B, set window of "post command Q" 261044f05562SScott Long *********************************************************************** 261144f05562SScott Long */ 261244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 261344f05562SScott Long u_int32_t post_queue_phyaddr; 261444f05562SScott Long struct HBB_MessageUnit *phbbmu; 261544f05562SScott Long 261644f05562SScott Long phbbmu=(struct HBB_MessageUnit *)acb->pmu; 261744f05562SScott Long phbbmu->postq_index=0; 261844f05562SScott Long phbbmu->doneq_index=0; 261944f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 262044f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_SET_POST_WINDOW); 262144f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 262244f05562SScott Long printf( "arcmsr%d:" 262344f05562SScott Long " 'set window of post command Q' timeout\n", acb->pci_unit); 262444f05562SScott Long return FALSE; 262544f05562SScott Long } 262644f05562SScott Long post_queue_phyaddr = srb_phyaddr 262744f05562SScott Long + ARCMSR_MAX_FREESRB_NUM*sizeof(struct CommandControlBlock) 262844f05562SScott Long + offsetof(struct HBB_MessageUnit, post_qbuffer); 262944f05562SScott Long CHIP_REG_WRITE32(HBB_RWBUFFER, 263044f05562SScott Long 1, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */ 263144f05562SScott Long CHIP_REG_WRITE32(HBB_RWBUFFER, 263244f05562SScott Long 1, msgcode_rwbuffer[1], srb_phyaddr_hi32); /* normal should be zero */ 263344f05562SScott Long CHIP_REG_WRITE32(HBB_RWBUFFER, 263444f05562SScott Long 1, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ size (256+8)*4 */ 263544f05562SScott Long CHIP_REG_WRITE32(HBB_RWBUFFER, 263644f05562SScott Long 1, msgcode_rwbuffer[3], post_queue_phyaddr+1056); /* doneQ size (256+8)*4 */ 263744f05562SScott Long CHIP_REG_WRITE32(HBB_RWBUFFER, 263844f05562SScott Long 1, msgcode_rwbuffer[4], 1056); /* srb maxQ size must be --> [(256+8)*4] */ 263944f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 264044f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_SET_CONFIG); 264144f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 264244f05562SScott Long printf( "arcmsr%d: 'set command Q window' timeout \n", acb->pci_unit); 264344f05562SScott Long return FALSE; 264444f05562SScott Long } 264544f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 264644f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_START_DRIVER_MODE); 264744f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 264844f05562SScott Long printf( "arcmsr%d: 'start diver mode' timeout \n", acb->pci_unit); 264944f05562SScott Long return FALSE; 265044f05562SScott Long } 265144f05562SScott Long } 265244f05562SScott Long break; 265344f05562SScott Long } 265444f05562SScott Long return TRUE; 265544f05562SScott Long } 265644f05562SScott Long /* 265744f05562SScott Long ************************************************************************ 265844f05562SScott Long ************************************************************************ 265944f05562SScott Long */ 266044f05562SScott Long static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb) 266144f05562SScott Long { 266244f05562SScott Long switch (acb->adapter_type) 266344f05562SScott Long { 266444f05562SScott Long case ACB_ADAPTER_TYPE_A: 266544f05562SScott Long return; 266644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 266744f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 266844f05562SScott Long 0, drv2iop_doorbell,ARCMSR_MESSAGE_ACTIVE_EOI_MODE); 266944f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 267044f05562SScott Long printf( "arcmsr%d:" 267144f05562SScott Long " 'iop enable eoi mode' timeout \n", acb->pci_unit); 267244f05562SScott Long return; 267344f05562SScott Long } 267444f05562SScott Long } 267544f05562SScott Long break; 267644f05562SScott Long } 267744f05562SScott Long return; 267844f05562SScott Long } 267944f05562SScott Long /* 268044f05562SScott Long ********************************************************************** 2681ad6d6297SScott Long ********************************************************************** 2682ad6d6297SScott Long */ 2683ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb) 2684ad6d6297SScott Long { 268544f05562SScott Long u_int32_t intmask_org; 2686ad6d6297SScott Long 268744f05562SScott Long /* disable all outbound interrupt */ 268844f05562SScott Long intmask_org=arcmsr_disable_allintr(acb); 268944f05562SScott Long arcmsr_wait_firmware_ready(acb); 269044f05562SScott Long arcmsr_iop_confirm(acb); 2691ad6d6297SScott Long arcmsr_get_firmware_spec(acb); 269244f05562SScott Long /*start background rebuild*/ 2693ad6d6297SScott Long arcmsr_start_adapter_bgrb(acb); 269444f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 269544f05562SScott Long arcmsr_clear_doorbell_queue_buffer(acb); 269644f05562SScott Long arcmsr_enable_eoi_mode(acb); 269744f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 269844f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 2699ad6d6297SScott Long acb->acb_flags |=ACB_F_IOP_INITED; 2700ad6d6297SScott Long return; 2701ad6d6297SScott Long } 2702ad6d6297SScott Long /* 2703ad6d6297SScott Long ********************************************************************** 2704f1c579b1SScott Long ********************************************************************** 2705f1c579b1SScott Long */ 2706f1c579b1SScott Long static void arcmsr_map_freesrb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 2707f1c579b1SScott Long { 2708ad6d6297SScott Long struct AdapterControlBlock *acb=arg; 2709ad6d6297SScott Long struct CommandControlBlock *srb_tmp; 2710ad6d6297SScott Long u_int8_t * dma_memptr; 271144f05562SScott Long u_int32_t i; 2712ad6d6297SScott Long unsigned long srb_phyaddr=(unsigned long)segs->ds_addr; 2713f1c579b1SScott Long 2714ad6d6297SScott Long dma_memptr=acb->uncacheptr; 271544f05562SScott Long acb->srb_phyaddr=srb_phyaddr; 2716ad6d6297SScott Long srb_tmp=(struct CommandControlBlock *)dma_memptr; 2717ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 271844f05562SScott Long if(bus_dmamap_create(acb->dm_segs_dmat, 271944f05562SScott Long /*flags*/0, &srb_tmp->dm_segs_dmamap)!=0) { 2720ad6d6297SScott Long acb->acb_flags |= ACB_F_MAPFREESRB_FAILD; 272144f05562SScott Long printf("arcmsr%d:" 272244f05562SScott Long " srb dmamap bus_dmamap_create error\n", acb->pci_unit); 2723ad6d6297SScott Long return; 2724ad6d6297SScott Long } 2725ad6d6297SScott Long srb_tmp->cdb_shifted_phyaddr=srb_phyaddr >> 5; 2726ad6d6297SScott Long srb_tmp->acb=acb; 2727ad6d6297SScott Long acb->srbworkingQ[i]=acb->psrb_pool[i]=srb_tmp; 2728ad6d6297SScott Long srb_phyaddr=srb_phyaddr+sizeof(struct CommandControlBlock); 2729ad6d6297SScott Long srb_tmp++; 2730ad6d6297SScott Long } 2731ad6d6297SScott Long acb->vir2phy_offset=(unsigned long)srb_tmp-(unsigned long)srb_phyaddr; 2732f1c579b1SScott Long return; 2733f1c579b1SScott Long } 2734f1c579b1SScott Long /* 2735f1c579b1SScott Long ************************************************************************ 2736f1c579b1SScott Long ** 2737f1c579b1SScott Long ** 2738f1c579b1SScott Long ************************************************************************ 2739f1c579b1SScott Long */ 2740ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb) 2741f1c579b1SScott Long { 2742f1c579b1SScott Long /* remove the control device */ 2743ad6d6297SScott Long if(acb->ioctl_dev != NULL) { 2744ad6d6297SScott Long destroy_dev(acb->ioctl_dev); 2745f1c579b1SScott Long } 2746ad6d6297SScott Long bus_dmamap_unload(acb->srb_dmat, acb->srb_dmamap); 2747ad6d6297SScott Long bus_dmamap_destroy(acb->srb_dmat, acb->srb_dmamap); 2748ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 2749ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 2750ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 2751f1c579b1SScott Long return; 2752f1c579b1SScott Long } 2753f1c579b1SScott Long /* 2754f1c579b1SScott Long ************************************************************************ 2755f1c579b1SScott Long ************************************************************************ 2756f1c579b1SScott Long */ 2757ad6d6297SScott Long static u_int32_t arcmsr_initialize(device_t dev) 2758f1c579b1SScott Long { 2759ad6d6297SScott Long struct AdapterControlBlock *acb=device_get_softc(dev); 2760ad6d6297SScott Long u_int16_t pci_command; 276144f05562SScott Long int i, j,max_coherent_size; 2762f1c579b1SScott Long 276344f05562SScott Long switch (pci_get_devid(dev)) { 276444f05562SScott Long case PCIDevVenIDARC1201: { 276544f05562SScott Long acb->adapter_type=ACB_ADAPTER_TYPE_B; 276644f05562SScott Long max_coherent_size=ARCMSR_SRBS_POOL_SIZE 276744f05562SScott Long +(sizeof(struct HBB_MessageUnit)); 276844f05562SScott Long } 276944f05562SScott Long break; 277044f05562SScott Long case PCIDevVenIDARC1110: 277144f05562SScott Long case PCIDevVenIDARC1120: 277244f05562SScott Long case PCIDevVenIDARC1130: 277344f05562SScott Long case PCIDevVenIDARC1160: 277444f05562SScott Long case PCIDevVenIDARC1170: 277544f05562SScott Long case PCIDevVenIDARC1210: 277644f05562SScott Long case PCIDevVenIDARC1220: 277744f05562SScott Long case PCIDevVenIDARC1230: 277844f05562SScott Long case PCIDevVenIDARC1260: 277944f05562SScott Long case PCIDevVenIDARC1270: 278044f05562SScott Long case PCIDevVenIDARC1280: 278144f05562SScott Long case PCIDevVenIDARC1380: 278244f05562SScott Long case PCIDevVenIDARC1381: 278344f05562SScott Long case PCIDevVenIDARC1680: 278444f05562SScott Long case PCIDevVenIDARC1681: { 278544f05562SScott Long acb->adapter_type=ACB_ADAPTER_TYPE_A; 278644f05562SScott Long max_coherent_size=ARCMSR_SRBS_POOL_SIZE; 278744f05562SScott Long } 278844f05562SScott Long break; 278944f05562SScott Long default: { 279044f05562SScott Long printf("arcmsr%d:" 279144f05562SScott Long " unknown RAID adapter type \n", device_get_unit(dev)); 279244f05562SScott Long return ENOMEM; 279344f05562SScott Long } 279444f05562SScott Long } 2795f1c579b1SScott Long #if __FreeBSD_version >= 502010 2796f1c579b1SScott Long if(bus_dma_tag_create( /*parent*/ NULL, 2797f1c579b1SScott Long /*alignemnt*/ 1, 2798f1c579b1SScott Long /*boundary*/ 0, 2799701d9f1fSScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 2800f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 2801f1c579b1SScott Long /*filter*/ NULL, 2802f1c579b1SScott Long /*filterarg*/ NULL, 2803f1c579b1SScott Long /*maxsize*/ BUS_SPACE_MAXSIZE_32BIT, 2804f1c579b1SScott Long /*nsegments*/ BUS_SPACE_UNRESTRICTED, 2805f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 2806f1c579b1SScott Long /*flags*/ 0, 2807f1c579b1SScott Long /*lockfunc*/ NULL, 2808f1c579b1SScott Long /*lockarg*/ NULL, 2809ad6d6297SScott Long &acb->parent_dmat) != 0) 2810f1c579b1SScott Long #else 2811f1c579b1SScott Long if(bus_dma_tag_create( /*parent*/ NULL, 2812f1c579b1SScott Long /*alignemnt*/ 1, 2813f1c579b1SScott Long /*boundary*/ 0, 2814701d9f1fSScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 2815f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 2816f1c579b1SScott Long /*filter*/ NULL, 2817f1c579b1SScott Long /*filterarg*/ NULL, 2818f1c579b1SScott Long /*maxsize*/ BUS_SPACE_MAXSIZE_32BIT, 2819f1c579b1SScott Long /*nsegments*/ BUS_SPACE_UNRESTRICTED, 2820f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 2821f1c579b1SScott Long /*flags*/ 0, 2822ad6d6297SScott Long &acb->parent_dmat) != 0) 2823f1c579b1SScott Long #endif 2824f1c579b1SScott Long { 282544f05562SScott Long printf("arcmsr%d: parent_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 2826f1c579b1SScott Long return ENOMEM; 2827f1c579b1SScott Long } 2828f1c579b1SScott Long /* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */ 2829f1c579b1SScott Long #if __FreeBSD_version >= 502010 2830ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 2831f1c579b1SScott Long /*alignment*/ 1, 2832f1c579b1SScott Long /*boundary*/ 0, 2833f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 2834f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 2835f1c579b1SScott Long /*filter*/ NULL, 2836f1c579b1SScott Long /*filterarg*/ NULL, 2837f1c579b1SScott Long /*maxsize*/ MAXBSIZE, 2838f1c579b1SScott Long /*nsegments*/ ARCMSR_MAX_SG_ENTRIES, 2839f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 2840ad6d6297SScott Long /*flags*/ 0, 2841f1c579b1SScott Long /*lockfunc*/ busdma_lock_mutex, 2842579ec1a5SScott Long #if __FreeBSD_version >= 700025 28435878cbecSScott Long /*lockarg*/ &acb->qbuffer_lock, 2844579ec1a5SScott Long #else 2845579ec1a5SScott Long /*lockarg*/ &Giant, 2846579ec1a5SScott Long #endif 2847ad6d6297SScott Long &acb->dm_segs_dmat) != 0) 2848f1c579b1SScott Long #else 2849ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 2850f1c579b1SScott Long /*alignment*/ 1, 2851f1c579b1SScott Long /*boundary*/ 0, 2852f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 2853f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 2854f1c579b1SScott Long /*filter*/ NULL, 2855f1c579b1SScott Long /*filterarg*/ NULL, 2856f1c579b1SScott Long /*maxsize*/ MAXBSIZE, 2857f1c579b1SScott Long /*nsegments*/ ARCMSR_MAX_SG_ENTRIES, 2858f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 2859ad6d6297SScott Long /*flags*/ 0, 2860ad6d6297SScott Long &acb->dm_segs_dmat) != 0) 2861f1c579b1SScott Long #endif 2862f1c579b1SScott Long { 2863ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 286444f05562SScott Long printf("arcmsr%d: dm_segs_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 2865f1c579b1SScott Long return ENOMEM; 2866f1c579b1SScott Long } 2867ad6d6297SScott Long /* DMA tag for our srb structures.... Allocate the freesrb memory */ 2868f1c579b1SScott Long #if __FreeBSD_version >= 502010 2869ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 287044f05562SScott Long /*alignment*/ 0x20, 2871f1c579b1SScott Long /*boundary*/ 0, 2872f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 2873f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 2874f1c579b1SScott Long /*filter*/ NULL, 2875f1c579b1SScott Long /*filterarg*/ NULL, 287644f05562SScott Long /*maxsize*/ max_coherent_size, 2877f1c579b1SScott Long /*nsegments*/ 1, 2878f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 2879701d9f1fSScott Long /*flags*/ 0, 2880f1c579b1SScott Long /*lockfunc*/ NULL, 2881f1c579b1SScott Long /*lockarg*/ NULL, 2882ad6d6297SScott Long &acb->srb_dmat) != 0) 2883f1c579b1SScott Long #else 2884ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 288544f05562SScott Long /*alignment*/ 0x20, 2886f1c579b1SScott Long /*boundary*/ 0, 2887f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 2888f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 2889f1c579b1SScott Long /*filter*/ NULL, 2890f1c579b1SScott Long /*filterarg*/ NULL, 289144f05562SScott Long /*maxsize*/ max_coherent_size, 2892f1c579b1SScott Long /*nsegments*/ 1, 2893f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 2894701d9f1fSScott Long /*flags*/ 0, 2895ad6d6297SScott Long &acb->srb_dmat) != 0) 2896f1c579b1SScott Long #endif 2897f1c579b1SScott Long { 2898ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 2899ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 290044f05562SScott Long printf("arcmsr%d: srb_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 2901f1c579b1SScott Long return ENXIO; 2902f1c579b1SScott Long } 2903f1c579b1SScott Long /* Allocation for our srbs */ 2904ad6d6297SScott Long if(bus_dmamem_alloc(acb->srb_dmat, (void **)&acb->uncacheptr 2905ad6d6297SScott Long , BUS_DMA_WAITOK | BUS_DMA_COHERENT, &acb->srb_dmamap) != 0) { 2906ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 2907ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 2908ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 290944f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamem_alloc failure!\n", device_get_unit(dev)); 2910f1c579b1SScott Long return ENXIO; 2911f1c579b1SScott Long } 2912f1c579b1SScott Long /* And permanently map them */ 2913ad6d6297SScott Long if(bus_dmamap_load(acb->srb_dmat, acb->srb_dmamap, acb->uncacheptr 291444f05562SScott Long , max_coherent_size, arcmsr_map_freesrb, acb, /*flags*/0)) { 2915ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 2916ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 2917ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 291844f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamap_load failure!\n", device_get_unit(dev)); 2919f1c579b1SScott Long return ENXIO; 2920f1c579b1SScott Long } 2921f1c579b1SScott Long pci_command=pci_read_config(dev, PCIR_COMMAND, 2); 2922f1c579b1SScott Long pci_command |= PCIM_CMD_BUSMASTEREN; 2923f1c579b1SScott Long pci_command |= PCIM_CMD_PERRESPEN; 2924f1c579b1SScott Long pci_command |= PCIM_CMD_MWRICEN; 2925f1c579b1SScott Long /* Enable Busmaster/Mem */ 2926f1c579b1SScott Long pci_command |= PCIM_CMD_MEMEN; 2927f1c579b1SScott Long pci_write_config(dev, PCIR_COMMAND, pci_command, 2); 292844f05562SScott Long switch(acb->adapter_type) { 292944f05562SScott Long case ACB_ADAPTER_TYPE_A: { 293044f05562SScott Long u_int32_t rid0=PCIR_BAR(0); 293144f05562SScott Long vm_offset_t mem_base0; 293244f05562SScott Long 293344f05562SScott Long acb->sys_res_arcmsr[0]=bus_alloc_resource(dev, 293444f05562SScott Long SYS_RES_MEMORY, &rid0, 0ul, ~0ul, 0x1000, RF_ACTIVE); 293544f05562SScott Long if(acb->sys_res_arcmsr[0] == NULL) { 2936ad6d6297SScott Long arcmsr_free_resource(acb); 293744f05562SScott Long printf("arcmsr%d:" 293844f05562SScott Long " bus_alloc_resource failure!\n", device_get_unit(dev)); 2939f1c579b1SScott Long return ENOMEM; 2940f1c579b1SScott Long } 294144f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 2942ad6d6297SScott Long arcmsr_free_resource(acb); 294344f05562SScott Long printf("arcmsr%d:" 294444f05562SScott Long " rman_get_start failure!\n", device_get_unit(dev)); 2945f1c579b1SScott Long return ENXIO; 2946f1c579b1SScott Long } 294744f05562SScott Long mem_base0=(vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 294844f05562SScott Long if(mem_base0==0) { 2949ad6d6297SScott Long arcmsr_free_resource(acb); 295044f05562SScott Long printf("arcmsr%d:" 295144f05562SScott Long " rman_get_virtual failure!\n", device_get_unit(dev)); 2952f1c579b1SScott Long return ENXIO; 2953f1c579b1SScott Long } 295444f05562SScott Long acb->btag[0]=rman_get_bustag(acb->sys_res_arcmsr[0]); 295544f05562SScott Long acb->bhandle[0]=rman_get_bushandle(acb->sys_res_arcmsr[0]); 295644f05562SScott Long acb->pmu=(struct MessageUnit_UNION *)mem_base0; 295744f05562SScott Long } 295844f05562SScott Long break; 295944f05562SScott Long case ACB_ADAPTER_TYPE_B: { 296044f05562SScott Long struct HBB_MessageUnit *phbbmu; 296144f05562SScott Long struct CommandControlBlock *freesrb; 296244f05562SScott Long u_int32_t rid[]={ PCIR_BAR(0), PCIR_BAR(2) }; 296344f05562SScott Long vm_offset_t mem_base[]={0,0}; 296444f05562SScott Long for(i=0; i<2; i++) { 296544f05562SScott Long if(i==0) { 296644f05562SScott Long acb->sys_res_arcmsr[i]=bus_alloc_resource(dev, 296744f05562SScott Long SYS_RES_MEMORY, &rid[i], 296844f05562SScott Long 0x20400, 0x20400+sizeof(struct HBB_DOORBELL), 296944f05562SScott Long sizeof(struct HBB_DOORBELL), RF_ACTIVE); 297044f05562SScott Long } else { 297144f05562SScott Long acb->sys_res_arcmsr[i]=bus_alloc_resource(dev, 297244f05562SScott Long SYS_RES_MEMORY, &rid[i], 297344f05562SScott Long 0x0fa00, 0x0fa00+sizeof(struct HBB_RWBUFFER), 297444f05562SScott Long sizeof(struct HBB_RWBUFFER), RF_ACTIVE); 297544f05562SScott Long } 297644f05562SScott Long if(acb->sys_res_arcmsr[i] == NULL) { 297744f05562SScott Long arcmsr_free_resource(acb); 297844f05562SScott Long printf("arcmsr%d:" 297944f05562SScott Long " bus_alloc_resource %d failure!\n", device_get_unit(dev), i); 298044f05562SScott Long return ENOMEM; 298144f05562SScott Long } 298244f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[i]) <= 0) { 298344f05562SScott Long arcmsr_free_resource(acb); 298444f05562SScott Long printf("arcmsr%d:" 298544f05562SScott Long " rman_get_start %d failure!\n", device_get_unit(dev), i); 298644f05562SScott Long return ENXIO; 298744f05562SScott Long } 298844f05562SScott Long mem_base[i]=(vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[i]); 298944f05562SScott Long if(mem_base[i]==0) { 299044f05562SScott Long arcmsr_free_resource(acb); 299144f05562SScott Long printf("arcmsr%d:" 299244f05562SScott Long " rman_get_virtual %d failure!\n", device_get_unit(dev), i); 299344f05562SScott Long return ENXIO; 299444f05562SScott Long } 299544f05562SScott Long acb->btag[i]=rman_get_bustag(acb->sys_res_arcmsr[i]); 299644f05562SScott Long acb->bhandle[i]=rman_get_bushandle(acb->sys_res_arcmsr[i]); 299744f05562SScott Long } 299844f05562SScott Long freesrb=(struct CommandControlBlock *)acb->uncacheptr; 299944f05562SScott Long acb->pmu=(struct MessageUnit_UNION *)&freesrb[ARCMSR_MAX_FREESRB_NUM]; 300044f05562SScott Long phbbmu=(struct HBB_MessageUnit *)acb->pmu; 300144f05562SScott Long phbbmu->hbb_doorbell=(struct HBB_DOORBELL *)mem_base[0]; 300244f05562SScott Long phbbmu->hbb_rwbuffer=(struct HBB_RWBUFFER *)mem_base[1]; 300344f05562SScott Long } 300444f05562SScott Long break; 300544f05562SScott Long } 3006ad6d6297SScott Long if(acb->acb_flags & ACB_F_MAPFREESRB_FAILD) { 3007ad6d6297SScott Long arcmsr_free_resource(acb); 300844f05562SScott Long printf("arcmsr%d: map free srb failure!\n", device_get_unit(dev)); 3009f1c579b1SScott Long return ENXIO; 3010f1c579b1SScott Long } 3011ad6d6297SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED 3012ad6d6297SScott Long |ACB_F_MESSAGE_RQBUFFER_CLEARED 301344f05562SScott Long |ACB_F_MESSAGE_WQBUFFER_READ); 3014ad6d6297SScott Long acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; 3015ad6d6297SScott Long /* 3016ad6d6297SScott Long ******************************************************************** 3017ad6d6297SScott Long ** init raid volume state 3018ad6d6297SScott Long ******************************************************************** 3019ad6d6297SScott Long */ 3020ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_TARGETID;i++) { 3021ad6d6297SScott Long for(j=0;j<ARCMSR_MAX_TARGETLUN;j++) { 302244f05562SScott Long acb->devstate[i][j]=ARECA_RAID_GONE; 3023ad6d6297SScott Long } 3024ad6d6297SScott Long } 3025ad6d6297SScott Long arcmsr_iop_init(acb); 3026f1c579b1SScott Long return(0); 3027f1c579b1SScott Long } 3028f1c579b1SScott Long /* 3029f1c579b1SScott Long ************************************************************************ 3030f1c579b1SScott Long ************************************************************************ 3031f1c579b1SScott Long */ 3032f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev) 3033f1c579b1SScott Long { 3034ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 3035ad6d6297SScott Long u_int32_t unit=device_get_unit(dev); 3036f1c579b1SScott Long struct ccb_setasync csa; 3037f1c579b1SScott Long struct cam_devq *devq; /* Device Queue to use for this SIM */ 3038f1c579b1SScott Long struct resource *irqres; 3039f1c579b1SScott Long int rid; 3040f1c579b1SScott Long 3041ad6d6297SScott Long if(acb == NULL) { 3042ad6d6297SScott Long printf("arcmsr%d: cannot allocate softc\n", unit); 3043ad6d6297SScott Long return (ENOMEM); 3044ad6d6297SScott Long } 30455878cbecSScott Long ARCMSR_LOCK_INIT(&acb->qbuffer_lock, "arcmsr Q buffer lock"); 3046ad6d6297SScott Long if(arcmsr_initialize(dev)) { 3047ad6d6297SScott Long printf("arcmsr%d: initialize failure!\n", unit); 30485878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3049f1c579b1SScott Long return ENXIO; 3050f1c579b1SScott Long } 3051f1c579b1SScott Long /* After setting up the adapter, map our interrupt */ 3052f1c579b1SScott Long rid=0; 3053ad6d6297SScott Long irqres=bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE); 3054ad6d6297SScott Long if(irqres == NULL || 305544f05562SScott Long #if __FreeBSD_version >= 700025 3056ad6d6297SScott Long bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE 30575878cbecSScott Long , NULL, arcmsr_intr_handler, acb, &acb->ih)) { 305844f05562SScott Long #else 305944f05562SScott Long bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE 306044f05562SScott Long , arcmsr_intr_handler, acb, &acb->ih)) { 306144f05562SScott Long #endif 3062ad6d6297SScott Long arcmsr_free_resource(acb); 30635878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3064f1c579b1SScott Long printf("arcmsr%d: unable to register interrupt handler!\n", unit); 3065f1c579b1SScott Long return ENXIO; 3066f1c579b1SScott Long } 3067ad6d6297SScott Long acb->irqres=irqres; 3068ad6d6297SScott Long acb->pci_dev=dev; 3069ad6d6297SScott Long acb->pci_unit=unit; 3070f1c579b1SScott Long /* 3071f1c579b1SScott Long * Now let the CAM generic SCSI layer find the SCSI devices on 3072f1c579b1SScott Long * the bus * start queue to reset to the idle loop. * 3073f1c579b1SScott Long * Create device queue of SIM(s) * (MAX_START_JOB - 1) : 3074f1c579b1SScott Long * max_sim_transactions 3075f1c579b1SScott Long */ 3076f1c579b1SScott Long devq=cam_simq_alloc(ARCMSR_MAX_START_JOB); 3077ad6d6297SScott Long if(devq == NULL) { 3078ad6d6297SScott Long arcmsr_free_resource(acb); 3079ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 30805878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3081ad6d6297SScott Long printf("arcmsr%d: cam_simq_alloc failure!\n", unit); 3082f1c579b1SScott Long return ENXIO; 3083f1c579b1SScott Long } 308444f05562SScott Long #if __FreeBSD_version >= 700025 30852b83592fSScott Long acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll, 30865878cbecSScott Long "arcmsr", acb, unit, &acb->qbuffer_lock, 1, 30872b83592fSScott Long ARCMSR_MAX_OUTSTANDING_CMD, devq); 308844f05562SScott Long #else 308944f05562SScott Long acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll, 309044f05562SScott Long "arcmsr", acb, unit, 1, 309144f05562SScott Long ARCMSR_MAX_OUTSTANDING_CMD, devq); 309244f05562SScott Long #endif 3093ad6d6297SScott Long if(acb->psim == NULL) { 3094ad6d6297SScott Long arcmsr_free_resource(acb); 3095ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 3096f1c579b1SScott Long cam_simq_free(devq); 30975878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3098ad6d6297SScott Long printf("arcmsr%d: cam_sim_alloc failure!\n", unit); 3099f1c579b1SScott Long return ENXIO; 3100f1c579b1SScott Long } 31015878cbecSScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 3102f40b4cabSScott Long #if __FreeBSD_version >= 700044 3103b50569b7SScott Long if(xpt_bus_register(acb->psim, dev, 0) != CAM_SUCCESS) { 310444f05562SScott Long #else 310544f05562SScott Long if(xpt_bus_register(acb->psim, 0) != CAM_SUCCESS) { 310644f05562SScott Long #endif 3107ad6d6297SScott Long arcmsr_free_resource(acb); 3108ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 3109ad6d6297SScott Long cam_sim_free(acb->psim, /*free_devq*/TRUE); 31105878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3111ad6d6297SScott Long printf("arcmsr%d: xpt_bus_register failure!\n", unit); 3112f1c579b1SScott Long return ENXIO; 3113f1c579b1SScott Long } 3114ad6d6297SScott Long if(xpt_create_path(&acb->ppath, /* periph */ NULL 3115ad6d6297SScott Long , cam_sim_path(acb->psim) 3116ad6d6297SScott Long , CAM_TARGET_WILDCARD 3117ad6d6297SScott Long , CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 3118ad6d6297SScott Long arcmsr_free_resource(acb); 3119ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 3120ad6d6297SScott Long xpt_bus_deregister(cam_sim_path(acb->psim)); 3121ad6d6297SScott Long cam_sim_free(acb->psim, /* free_simq */ TRUE); 31225878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3123ad6d6297SScott Long printf("arcmsr%d: xpt_create_path failure!\n", unit); 3124f1c579b1SScott Long return ENXIO; 3125f1c579b1SScott Long } 3126f1c579b1SScott Long /* 3127f1c579b1SScott Long **************************************************** 3128f1c579b1SScott Long */ 3129ad6d6297SScott Long xpt_setup_ccb(&csa.ccb_h, acb->ppath, /*priority*/5); 3130f1c579b1SScott Long csa.ccb_h.func_code=XPT_SASYNC_CB; 3131f1c579b1SScott Long csa.event_enable=AC_FOUND_DEVICE|AC_LOST_DEVICE; 3132f1c579b1SScott Long csa.callback=arcmsr_async; 3133ad6d6297SScott Long csa.callback_arg=acb->psim; 3134f1c579b1SScott Long xpt_action((union ccb *)&csa); 31355878cbecSScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 3136f1c579b1SScott Long /* Create the control device. */ 3137ad6d6297SScott Long acb->ioctl_dev=make_dev(&arcmsr_cdevsw 3138ad6d6297SScott Long , unit 3139ad6d6297SScott Long , UID_ROOT 3140ad6d6297SScott Long , GID_WHEEL /* GID_OPERATOR */ 3141ad6d6297SScott Long , S_IRUSR | S_IWUSR 3142ad6d6297SScott Long , "arcmsr%d", unit); 3143f1c579b1SScott Long #if __FreeBSD_version < 503000 3144ad6d6297SScott Long acb->ioctl_dev->si_drv1=acb; 3145f1c579b1SScott Long #endif 3146f1c579b1SScott Long #if __FreeBSD_version > 500005 3147ad6d6297SScott Long (void)make_dev_alias(acb->ioctl_dev, "arc%d", unit); 3148f1c579b1SScott Long #endif 3149f1c579b1SScott Long return 0; 3150f1c579b1SScott Long } 3151f1c579b1SScott Long /* 3152f1c579b1SScott Long ************************************************************************ 3153f1c579b1SScott Long ************************************************************************ 3154f1c579b1SScott Long */ 3155f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev) 3156f1c579b1SScott Long { 3157ad6d6297SScott Long u_int32_t id; 3158ad6d6297SScott Long static char buf[256]; 3159ad6d6297SScott Long char *type; 3160ad6d6297SScott Long int raid6 = 1; 3161ad6d6297SScott Long 3162ad6d6297SScott Long if (pci_get_vendor(dev) != PCI_VENDOR_ID_ARECA) { 3163ad6d6297SScott Long return (ENXIO); 3164ad6d6297SScott Long } 3165ad6d6297SScott Long switch(id=pci_get_devid(dev)) { 3166f1c579b1SScott Long case PCIDevVenIDARC1110: 3167f1c579b1SScott Long case PCIDevVenIDARC1210: 316844f05562SScott Long case PCIDevVenIDARC1201: 3169ad6d6297SScott Long raid6 = 0; 3170ad6d6297SScott Long /*FALLTHRU*/ 3171ad6d6297SScott Long case PCIDevVenIDARC1120: 3172ad6d6297SScott Long case PCIDevVenIDARC1130: 3173ad6d6297SScott Long case PCIDevVenIDARC1160: 3174ad6d6297SScott Long case PCIDevVenIDARC1170: 3175f1c579b1SScott Long case PCIDevVenIDARC1220: 3176f1c579b1SScott Long case PCIDevVenIDARC1230: 3177f1c579b1SScott Long case PCIDevVenIDARC1260: 3178ad6d6297SScott Long case PCIDevVenIDARC1270: 3179ad6d6297SScott Long case PCIDevVenIDARC1280: 3180ad6d6297SScott Long type = "SATA"; 3181ad6d6297SScott Long break; 3182ad6d6297SScott Long case PCIDevVenIDARC1380: 3183ad6d6297SScott Long case PCIDevVenIDARC1381: 3184ad6d6297SScott Long case PCIDevVenIDARC1680: 3185ad6d6297SScott Long case PCIDevVenIDARC1681: 3186ad6d6297SScott Long type = "SAS"; 3187ad6d6297SScott Long break; 3188ad6d6297SScott Long default: 3189ad6d6297SScott Long type = "X-TYPE"; 3190ad6d6297SScott Long break; 3191f1c579b1SScott Long } 3192ad6d6297SScott Long sprintf(buf, "Areca %s Host Adapter RAID Controller %s\n", type, raid6 ? "(RAID6 capable)" : ""); 3193ad6d6297SScott Long device_set_desc_copy(dev, buf); 3194ad6d6297SScott Long return 0; 3195f1c579b1SScott Long } 3196f1c579b1SScott Long /* 3197f1c579b1SScott Long ************************************************************************ 3198f1c579b1SScott Long ************************************************************************ 3199f1c579b1SScott Long */ 3200f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev) 3201f1c579b1SScott Long { 320244f05562SScott Long u_int32_t i; 3203ad6d6297SScott Long u_int32_t intmask_org; 3204ad6d6297SScott Long struct CommandControlBlock *srb; 3205ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 3206f1c579b1SScott Long 3207f1c579b1SScott Long /* stop adapter background rebuild */ 32085878cbecSScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 320944f05562SScott Long /* disable all outbound interrupt */ 321044f05562SScott Long intmask_org=arcmsr_disable_allintr(acb); 3211ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 3212ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 3213f1c579b1SScott Long /* abort all outstanding command */ 3214ad6d6297SScott Long acb->acb_flags |= ACB_F_SCSISTOPADAPTER; 3215ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOP_INITED; 3216ad6d6297SScott Long if(acb->srboutstandingcount!=0) { 321744f05562SScott Long /*clear and abort all outbound posted Q*/ 321844f05562SScott Long arcmsr_done4abort_postqueue(acb); 321944f05562SScott Long /* talk to iop 331 outstanding command aborted*/ 3220ad6d6297SScott Long arcmsr_abort_allcmd(acb); 3221ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 3222ad6d6297SScott Long srb=acb->psrb_pool[i]; 3223ad6d6297SScott Long if(srb->startdone==ARCMSR_SRB_START) { 3224ad6d6297SScott Long srb->startdone=ARCMSR_SRB_ABORTED; 3225ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 3226ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 3227f1c579b1SScott Long } 3228f1c579b1SScott Long } 3229f1c579b1SScott Long } 3230ad6d6297SScott Long atomic_set_int(&acb->srboutstandingcount, 0); 3231ad6d6297SScott Long acb->workingsrb_doneindex=0; 3232ad6d6297SScott Long acb->workingsrb_startindex=0; 32335878cbecSScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 3234f2aa0e9fSWarner Losh return (0); 3235f1c579b1SScott Long } 3236f1c579b1SScott Long /* 3237f1c579b1SScott Long ************************************************************************ 3238f1c579b1SScott Long ************************************************************************ 3239f1c579b1SScott Long */ 3240f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev) 3241f1c579b1SScott Long { 3242ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 324344f05562SScott Long int i; 3244f1c579b1SScott Long 32455878cbecSScott Long bus_teardown_intr(dev, acb->irqres, acb->ih); 3246f1c579b1SScott Long arcmsr_shutdown(dev); 3247ad6d6297SScott Long arcmsr_free_resource(acb); 324844f05562SScott Long for(i=0; (acb->sys_res_arcmsr[i]!=NULL) && (i<2); i++) { 324944f05562SScott Long bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(i), acb->sys_res_arcmsr[i]); 325044f05562SScott Long } 3251ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 32525878cbecSScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 3253ad6d6297SScott Long xpt_async(AC_LOST_DEVICE, acb->ppath, NULL); 3254ad6d6297SScott Long xpt_free_path(acb->ppath); 3255ad6d6297SScott Long xpt_bus_deregister(cam_sim_path(acb->psim)); 3256ad6d6297SScott Long cam_sim_free(acb->psim, TRUE); 32575878cbecSScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 32585878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3259f1c579b1SScott Long return (0); 3260f1c579b1SScott Long } 3261f1c579b1SScott Long 3262f1c579b1SScott Long 3263