1f1c579b1SScott Long /* 246a7789eSMatt Jacob ***************************************************************************************** 3f1c579b1SScott Long ** O.S : FreeBSD 4f1c579b1SScott Long ** FILE NAME : arcmsr.c 5*d74001adSXin LI ** BY : Erich Chen, Ching Huang 6f1c579b1SScott Long ** Description: SCSI RAID Device Driver for 7*d74001adSXin LI ** ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX/ARC188x) 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 ** 13*d74001adSXin LI ** Copyright (c) 2004-2010 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 58641182baSXin LI ** 1.20.00.16 10/10/2009 Erich Chen Bug fix for RAID adapter type ARC120x 59641182baSXin LI ** bus_dmamem_alloc() with BUS_DMA_ZERO 60*d74001adSXin LI ** 1.20.00.17 07/15/2010 Ching Huang Added support ARC1880 61*d74001adSXin LI ** report CAM_DEV_NOT_THERE instead of CAM_SEL_TIMEOUT when device failed, 62*d74001adSXin LI ** prevent cam_periph_error removing all LUN devices of one Target id 63*d74001adSXin LI ** for any one LUN device failed 64f1c579b1SScott Long ****************************************************************************************** 65ad6d6297SScott Long * $FreeBSD$ 66f1c579b1SScott Long */ 67f1c579b1SScott Long #include <sys/param.h> 68f1c579b1SScott Long #include <sys/systm.h> 69f1c579b1SScott Long #include <sys/malloc.h> 70f1c579b1SScott Long #include <sys/kernel.h> 71f1c579b1SScott Long #include <sys/bus.h> 72f1c579b1SScott Long #include <sys/queue.h> 73f1c579b1SScott Long #include <sys/stat.h> 74f1c579b1SScott Long #include <sys/devicestat.h> 75f1c579b1SScott Long #include <sys/kthread.h> 76f1c579b1SScott Long #include <sys/module.h> 77f1c579b1SScott Long #include <sys/proc.h> 78f1c579b1SScott Long #include <sys/lock.h> 79f1c579b1SScott Long #include <sys/sysctl.h> 80f1c579b1SScott Long #include <sys/poll.h> 81f1c579b1SScott Long #include <sys/ioccom.h> 82f1c579b1SScott Long #include <vm/vm.h> 83f1c579b1SScott Long #include <vm/vm_param.h> 84f1c579b1SScott Long #include <vm/pmap.h> 85f1c579b1SScott Long 86f1c579b1SScott Long #include <isa/rtc.h> 87f1c579b1SScott Long 88f1c579b1SScott Long #include <machine/bus.h> 89f1c579b1SScott Long #include <machine/resource.h> 90f1c579b1SScott Long #include <machine/atomic.h> 91f1c579b1SScott Long #include <sys/conf.h> 92f1c579b1SScott Long #include <sys/rman.h> 93f1c579b1SScott Long 94f1c579b1SScott Long #include <cam/cam.h> 95f1c579b1SScott Long #include <cam/cam_ccb.h> 96f1c579b1SScott Long #include <cam/cam_sim.h> 97*d74001adSXin LI #include <cam/cam_periph.h> 98*d74001adSXin LI #include <cam/cam_xpt_periph.h> 99f1c579b1SScott Long #include <cam/cam_xpt_sim.h> 100f1c579b1SScott Long #include <cam/cam_debug.h> 101f1c579b1SScott Long #include <cam/scsi/scsi_all.h> 102f1c579b1SScott Long #include <cam/scsi/scsi_message.h> 103f1c579b1SScott Long /* 104f1c579b1SScott Long ************************************************************************** 105f1c579b1SScott Long ************************************************************************** 106f1c579b1SScott Long */ 107f1c579b1SScott Long #if __FreeBSD_version >= 500005 108f1c579b1SScott Long #include <sys/selinfo.h> 109f1c579b1SScott Long #include <sys/mutex.h> 110ad6d6297SScott Long #include <sys/endian.h> 111f1c579b1SScott Long #include <dev/pci/pcivar.h> 112f1c579b1SScott Long #include <dev/pci/pcireg.h> 113579ec1a5SScott Long #define ARCMSR_LOCK_INIT(l, s) mtx_init(l, s, NULL, MTX_DEF) 1145878cbecSScott Long #define ARCMSR_LOCK_DESTROY(l) mtx_destroy(l) 115f1c579b1SScott Long #define ARCMSR_LOCK_ACQUIRE(l) mtx_lock(l) 116f1c579b1SScott Long #define ARCMSR_LOCK_RELEASE(l) mtx_unlock(l) 117ad6d6297SScott Long #define ARCMSR_LOCK_TRY(l) mtx_trylock(l) 118ad6d6297SScott Long #define arcmsr_htole32(x) htole32(x) 119f1c579b1SScott Long typedef struct mtx arcmsr_lock_t; 120f1c579b1SScott Long #else 121f1c579b1SScott Long #include <sys/select.h> 122f1c579b1SScott Long #include <pci/pcivar.h> 123f1c579b1SScott Long #include <pci/pcireg.h> 124f1c579b1SScott Long #define ARCMSR_LOCK_INIT(l, s) simple_lock_init(l) 1255878cbecSScott Long #define ARCMSR_LOCK_DESTROY(l) 126f1c579b1SScott Long #define ARCMSR_LOCK_ACQUIRE(l) simple_lock(l) 127f1c579b1SScott Long #define ARCMSR_LOCK_RELEASE(l) simple_unlock(l) 128ad6d6297SScott Long #define ARCMSR_LOCK_TRY(l) simple_lock_try(l) 129ad6d6297SScott Long #define arcmsr_htole32(x) (x) 130f1c579b1SScott Long typedef struct simplelock arcmsr_lock_t; 131f1c579b1SScott Long #endif 13244f05562SScott Long 13344f05562SScott Long #if !defined(CAM_NEW_TRAN_CODE) && __FreeBSD_version >= 700025 13444f05562SScott Long #define CAM_NEW_TRAN_CODE 1 13544f05562SScott Long #endif 13644f05562SScott Long 137f1c579b1SScott Long #include <dev/arcmsr/arcmsr.h> 13844f05562SScott Long #define ARCMSR_SRBS_POOL_SIZE ((sizeof(struct CommandControlBlock) * ARCMSR_MAX_FREESRB_NUM)) 139f1c579b1SScott Long /* 140f1c579b1SScott Long ************************************************************************** 141f1c579b1SScott Long ************************************************************************** 142f1c579b1SScott Long */ 14344f05562SScott Long #define CHIP_REG_READ32(s, b, r) bus_space_read_4(acb->btag[b], acb->bhandle[b], offsetof(struct s, r)) 14444f05562SScott Long #define CHIP_REG_WRITE32(s, b, r, d) bus_space_write_4(acb->btag[b], acb->bhandle[b], offsetof(struct s, r), d) 145f1c579b1SScott Long /* 146f1c579b1SScott Long ************************************************************************** 147f1c579b1SScott Long ************************************************************************** 148f1c579b1SScott Long */ 149ad6d6297SScott Long static struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb); 150ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb); 151f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev); 152f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev); 153f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev); 154ad6d6297SScott Long static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg); 155ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb); 156f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev); 15744f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb); 158ad6d6297SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb); 159ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb); 160ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb); 161ad6d6297SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); 162ad6d6297SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb); 163ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb); 164ad6d6297SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb); 16544f05562SScott Long static void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb); 166ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb); 167ad6d6297SScott Long static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag); 168ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb); 169ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb); 170ad6d6297SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t * dm_segs, u_int32_t nseg); 171ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb); 172ad6d6297SScott Long static int arcmsr_resume(device_t dev); 173ad6d6297SScott Long static int arcmsr_suspend(device_t dev); 174*d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb); 175*d74001adSXin LI static void arcmsr_polling_devmap(void* arg); 176f1c579b1SScott Long /* 177f1c579b1SScott Long ************************************************************************** 178ad6d6297SScott Long ************************************************************************** 179ad6d6297SScott Long */ 180ad6d6297SScott Long static void UDELAY(u_int32_t us) { DELAY(us); } 181ad6d6297SScott Long /* 182ad6d6297SScott Long ************************************************************************** 183f1c579b1SScott Long ************************************************************************** 184f1c579b1SScott Long */ 185f1c579b1SScott Long static bus_dmamap_callback_t arcmsr_map_freesrb; 186f1c579b1SScott Long static bus_dmamap_callback_t arcmsr_executesrb; 187f1c579b1SScott Long /* 188f1c579b1SScott Long ************************************************************************** 189f1c579b1SScott Long ************************************************************************** 190f1c579b1SScott Long */ 191f1c579b1SScott Long static d_open_t arcmsr_open; 192f1c579b1SScott Long static d_close_t arcmsr_close; 193f1c579b1SScott Long static d_ioctl_t arcmsr_ioctl; 194f1c579b1SScott Long 195f1c579b1SScott Long static device_method_t arcmsr_methods[]={ 196f1c579b1SScott Long DEVMETHOD(device_probe, arcmsr_probe), 197f1c579b1SScott Long DEVMETHOD(device_attach, arcmsr_attach), 198f1c579b1SScott Long DEVMETHOD(device_detach, arcmsr_detach), 199f1c579b1SScott Long DEVMETHOD(device_shutdown, arcmsr_shutdown), 200ad6d6297SScott Long DEVMETHOD(device_suspend, arcmsr_suspend), 201ad6d6297SScott Long DEVMETHOD(device_resume, arcmsr_resume), 202ad6d6297SScott Long DEVMETHOD(bus_print_child, bus_generic_print_child), 203ad6d6297SScott Long DEVMETHOD(bus_driver_added, bus_generic_driver_added), 204f1c579b1SScott Long { 0, 0 } 205f1c579b1SScott Long }; 206f1c579b1SScott Long 207f1c579b1SScott Long static driver_t arcmsr_driver={ 208ad6d6297SScott Long "arcmsr", arcmsr_methods, sizeof(struct AdapterControlBlock) 209f1c579b1SScott Long }; 210f1c579b1SScott Long 211f1c579b1SScott Long static devclass_t arcmsr_devclass; 212f1c579b1SScott Long DRIVER_MODULE(arcmsr, pci, arcmsr_driver, arcmsr_devclass, 0, 0); 213d3cf342dSScott Long MODULE_DEPEND(arcmsr, pci, 1, 1, 1); 214d3cf342dSScott Long MODULE_DEPEND(arcmsr, cam, 1, 1, 1); 215ad6d6297SScott Long #ifndef BUS_DMA_COHERENT 216ad6d6297SScott Long #define BUS_DMA_COHERENT 0x04 /* hint: map memory in a coherent way */ 217ad6d6297SScott Long #endif 218ad6d6297SScott Long #if __FreeBSD_version >= 501000 219ad6d6297SScott Long #ifndef D_NEEDGIANT 220ad6d6297SScott Long #define D_NEEDGIANT 0x00400000 /* driver want Giant */ 221ad6d6297SScott Long #endif 222ad6d6297SScott Long #ifndef D_VERSION 223ad6d6297SScott Long #define D_VERSION 0x20011966 224ad6d6297SScott Long #endif 225f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw={ 226ad6d6297SScott Long #if __FreeBSD_version > 502010 227f1c579b1SScott Long .d_version = D_VERSION, 228ad6d6297SScott Long #endif 229f1c579b1SScott Long .d_flags = D_NEEDGIANT, 230f1c579b1SScott Long .d_open = arcmsr_open, /* open */ 231f1c579b1SScott Long .d_close = arcmsr_close, /* close */ 232f1c579b1SScott Long .d_ioctl = arcmsr_ioctl, /* ioctl */ 233f1c579b1SScott Long .d_name = "arcmsr", /* name */ 234f1c579b1SScott Long }; 235f1c579b1SScott Long #else 236f1c579b1SScott Long #define ARCMSR_CDEV_MAJOR 180 237f1c579b1SScott Long 238f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw = { 239f1c579b1SScott Long arcmsr_open, /* open */ 240f1c579b1SScott Long arcmsr_close, /* close */ 241f1c579b1SScott Long noread, /* read */ 242f1c579b1SScott Long nowrite, /* write */ 243f1c579b1SScott Long arcmsr_ioctl, /* ioctl */ 244f1c579b1SScott Long nopoll, /* poll */ 245f1c579b1SScott Long nommap, /* mmap */ 246f1c579b1SScott Long nostrategy, /* strategy */ 247f1c579b1SScott Long "arcmsr", /* name */ 248f1c579b1SScott Long ARCMSR_CDEV_MAJOR, /* major */ 249f1c579b1SScott Long nodump, /* dump */ 250f1c579b1SScott Long nopsize, /* psize */ 251f1c579b1SScott Long 0 /* flags */ 252f1c579b1SScott Long }; 253f1c579b1SScott Long #endif 254*d74001adSXin LI /* 255*d74001adSXin LI ************************************************************************** 256*d74001adSXin LI ************************************************************************** 257*d74001adSXin LI */ 258f1c579b1SScott Long #if __FreeBSD_version < 500005 259f1c579b1SScott Long static int arcmsr_open(dev_t dev, int flags, int fmt, struct proc *proc) 260f1c579b1SScott Long #else 261f1c579b1SScott Long #if __FreeBSD_version < 503000 262f1c579b1SScott Long static int arcmsr_open(dev_t dev, int flags, int fmt, struct thread *proc) 263f1c579b1SScott Long #else 26400b4e54aSWarner Losh static int arcmsr_open(struct cdev *dev, int flags, int fmt, struct thread *proc) 265f1c579b1SScott Long #endif 266f1c579b1SScott Long #endif 267f1c579b1SScott Long { 268f1c579b1SScott Long #if __FreeBSD_version < 503000 269ad6d6297SScott Long struct AdapterControlBlock *acb=dev->si_drv1; 270f1c579b1SScott Long #else 2716bfa9a2dSEd Schouten int unit = dev2unit(dev); 272ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 273f1c579b1SScott Long #endif 274ad6d6297SScott Long if(acb==NULL) { 275f1c579b1SScott Long return ENXIO; 276f1c579b1SScott Long } 277f1c579b1SScott Long return 0; 278f1c579b1SScott Long } 279f1c579b1SScott Long /* 280f1c579b1SScott Long ************************************************************************** 281f1c579b1SScott Long ************************************************************************** 282f1c579b1SScott Long */ 283f1c579b1SScott Long #if __FreeBSD_version < 500005 284f1c579b1SScott Long static int arcmsr_close(dev_t dev, int flags, int fmt, struct proc *proc) 285f1c579b1SScott Long #else 286f1c579b1SScott Long #if __FreeBSD_version < 503000 287f1c579b1SScott Long static int arcmsr_close(dev_t dev, int flags, int fmt, struct thread *proc) 288f1c579b1SScott Long #else 28900b4e54aSWarner Losh static int arcmsr_close(struct cdev *dev, int flags, int fmt, struct thread *proc) 290f1c579b1SScott Long #endif 291f1c579b1SScott Long #endif 292f1c579b1SScott Long { 293f1c579b1SScott Long #if __FreeBSD_version < 503000 294ad6d6297SScott Long struct AdapterControlBlock *acb=dev->si_drv1; 295f1c579b1SScott Long #else 2966bfa9a2dSEd Schouten int unit = dev2unit(dev); 297ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 298f1c579b1SScott Long #endif 299ad6d6297SScott Long if(acb==NULL) { 300f1c579b1SScott Long return ENXIO; 301f1c579b1SScott Long } 302f1c579b1SScott Long return 0; 303f1c579b1SScott Long } 304f1c579b1SScott Long /* 305f1c579b1SScott Long ************************************************************************** 306f1c579b1SScott Long ************************************************************************** 307f1c579b1SScott Long */ 308f1c579b1SScott Long #if __FreeBSD_version < 500005 309f1c579b1SScott Long static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct proc *proc) 310f1c579b1SScott Long #else 311f1c579b1SScott Long #if __FreeBSD_version < 503000 312f1c579b1SScott Long static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc) 313f1c579b1SScott Long #else 31400b4e54aSWarner Losh static int arcmsr_ioctl(struct cdev *dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc) 315f1c579b1SScott Long #endif 316f1c579b1SScott Long #endif 317f1c579b1SScott Long { 318f1c579b1SScott Long #if __FreeBSD_version < 503000 319ad6d6297SScott Long struct AdapterControlBlock *acb=dev->si_drv1; 320f1c579b1SScott Long #else 3216bfa9a2dSEd Schouten int unit = dev2unit(dev); 322ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 323f1c579b1SScott Long #endif 324f1c579b1SScott Long 325ad6d6297SScott Long if(acb==NULL) { 326f1c579b1SScott Long return ENXIO; 327f1c579b1SScott Long } 328ad6d6297SScott Long return(arcmsr_iop_ioctlcmd(acb, ioctl_cmd, arg)); 329f1c579b1SScott Long } 330f1c579b1SScott Long /* 33144f05562SScott Long ********************************************************************** 33244f05562SScott Long ********************************************************************** 33344f05562SScott Long */ 33444f05562SScott Long static u_int32_t arcmsr_disable_allintr( struct AdapterControlBlock *acb) 33544f05562SScott Long { 33644f05562SScott Long u_int32_t intmask_org=0; 33744f05562SScott Long 33844f05562SScott Long switch (acb->adapter_type) { 33944f05562SScott Long case ACB_ADAPTER_TYPE_A: { 34044f05562SScott Long /* disable all outbound interrupt */ 341*d74001adSXin LI intmask_org=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intmask); /* disable outbound message0 int */ 342*d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); 34344f05562SScott Long } 34444f05562SScott Long break; 34544f05562SScott Long case ACB_ADAPTER_TYPE_B: { 34644f05562SScott Long /* disable all outbound interrupt */ 34744f05562SScott Long intmask_org=CHIP_REG_READ32(HBB_DOORBELL, 34844f05562SScott Long 0, iop2drv_doorbell_mask) & (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); /* disable outbound message0 int */ 349*d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell_mask, 0); /* disable all interrupt */ 350*d74001adSXin LI } 351*d74001adSXin LI break; 352*d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 353*d74001adSXin LI /* disable all outbound interrupt */ 354*d74001adSXin LI intmask_org=CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_mask) ; /* disable outbound message0 int */ 355*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org|ARCMSR_HBCMU_ALL_INTMASKENABLE); 35644f05562SScott Long } 35744f05562SScott Long break; 35844f05562SScott Long } 35944f05562SScott Long return(intmask_org); 36044f05562SScott Long } 36144f05562SScott Long /* 36244f05562SScott Long ********************************************************************** 36344f05562SScott Long ********************************************************************** 36444f05562SScott Long */ 36544f05562SScott Long static void arcmsr_enable_allintr( struct AdapterControlBlock *acb, u_int32_t intmask_org) 36644f05562SScott Long { 36744f05562SScott Long u_int32_t mask; 36844f05562SScott Long 36944f05562SScott Long switch (acb->adapter_type) { 37044f05562SScott Long case ACB_ADAPTER_TYPE_A: { 37144f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 372*d74001adSXin LI mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE); 37344f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org & mask); 37444f05562SScott Long acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; 37544f05562SScott Long } 37644f05562SScott Long break; 37744f05562SScott Long case ACB_ADAPTER_TYPE_B: { 378*d74001adSXin LI /* enable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */ 379*d74001adSXin LI mask=(ARCMSR_IOP2DRV_DATA_WRITE_OK|ARCMSR_IOP2DRV_DATA_READ_OK|ARCMSR_IOP2DRV_CDB_DONE|ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); 380*d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell_mask, intmask_org | mask); /*1=interrupt enable, 0=interrupt disable*/ 38144f05562SScott Long acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f; 38244f05562SScott Long } 38344f05562SScott Long break; 384*d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 385*d74001adSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 386*d74001adSXin LI mask=~(ARCMSR_HBCMU_UTILITY_A_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK); 387*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org & mask); 388*d74001adSXin LI acb->outbound_int_enable= ~(intmask_org & mask) & 0x0000000f; 389*d74001adSXin LI } 390*d74001adSXin LI break; 39144f05562SScott Long } 39244f05562SScott Long return; 39344f05562SScott Long } 39444f05562SScott Long /* 39544f05562SScott Long ********************************************************************** 39644f05562SScott Long ********************************************************************** 39744f05562SScott Long */ 39844f05562SScott Long static u_int8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) 39944f05562SScott Long { 40044f05562SScott Long u_int32_t Index; 40144f05562SScott Long u_int8_t Retries=0x00; 40244f05562SScott Long 40344f05562SScott Long do { 40444f05562SScott Long for(Index=0; Index < 100; Index++) { 405*d74001adSXin LI if(CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { 406*d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/ 40744f05562SScott Long return TRUE; 40844f05562SScott Long } 40944f05562SScott Long UDELAY(10000); 41044f05562SScott Long }/*max 1 seconds*/ 41144f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 41244f05562SScott Long return FALSE; 41344f05562SScott Long } 41444f05562SScott Long /* 41544f05562SScott Long ********************************************************************** 41644f05562SScott Long ********************************************************************** 41744f05562SScott Long */ 41844f05562SScott Long static u_int8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) 41944f05562SScott Long { 42044f05562SScott Long u_int32_t Index; 42144f05562SScott Long u_int8_t Retries=0x00; 42244f05562SScott Long 42344f05562SScott Long do { 42444f05562SScott Long for(Index=0; Index < 100; Index++) { 425*d74001adSXin LI if(CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { 426*d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/ 427*d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 428*d74001adSXin LI return TRUE; 429*d74001adSXin LI } 430*d74001adSXin LI UDELAY(10000); 431*d74001adSXin LI }/*max 1 seconds*/ 432*d74001adSXin LI }while(Retries++ < 20);/*max 20 sec*/ 433*d74001adSXin LI return FALSE; 434*d74001adSXin LI } 435*d74001adSXin LI /* 436*d74001adSXin LI ********************************************************************** 437*d74001adSXin LI ********************************************************************** 438*d74001adSXin LI */ 439*d74001adSXin LI static u_int8_t arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock *acb) 440*d74001adSXin LI { 441*d74001adSXin LI u_int32_t Index; 442*d74001adSXin LI u_int8_t Retries=0x00; 443*d74001adSXin LI 444*d74001adSXin LI do { 445*d74001adSXin LI for(Index=0; Index < 100; Index++) { 446*d74001adSXin LI if(CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { 447*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);/*clear interrupt*/ 44844f05562SScott Long return TRUE; 44944f05562SScott Long } 45044f05562SScott Long UDELAY(10000); 45144f05562SScott Long }/*max 1 seconds*/ 45244f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 45344f05562SScott Long return FALSE; 45444f05562SScott Long } 45544f05562SScott Long /* 45644f05562SScott Long ************************************************************************ 45744f05562SScott Long ************************************************************************ 45844f05562SScott Long */ 45944f05562SScott Long static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) 46044f05562SScott Long { 46144f05562SScott Long int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */ 46244f05562SScott Long 463*d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 46444f05562SScott Long do { 46544f05562SScott Long if(arcmsr_hba_wait_msgint_ready(acb)) { 46644f05562SScott Long break; 46744f05562SScott Long } else { 46844f05562SScott Long retry_count--; 46944f05562SScott Long } 47044f05562SScott Long }while(retry_count!=0); 47144f05562SScott Long return; 47244f05562SScott Long } 47344f05562SScott Long /* 47444f05562SScott Long ************************************************************************ 47544f05562SScott Long ************************************************************************ 47644f05562SScott Long */ 47744f05562SScott Long static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) 47844f05562SScott Long { 47944f05562SScott Long int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */ 48044f05562SScott Long 48144f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 48244f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_FLUSH_CACHE); 48344f05562SScott Long do { 48444f05562SScott Long if(arcmsr_hbb_wait_msgint_ready(acb)) { 48544f05562SScott Long break; 48644f05562SScott Long } else { 48744f05562SScott Long retry_count--; 48844f05562SScott Long } 48944f05562SScott Long }while(retry_count!=0); 49044f05562SScott Long return; 49144f05562SScott Long } 49244f05562SScott Long /* 49344f05562SScott Long ************************************************************************ 49444f05562SScott Long ************************************************************************ 49544f05562SScott Long */ 496*d74001adSXin LI static void arcmsr_flush_hbc_cache(struct AdapterControlBlock *acb) 497*d74001adSXin LI { 498*d74001adSXin LI int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */ 499*d74001adSXin LI 500*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 501*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 502*d74001adSXin LI do { 503*d74001adSXin LI if(arcmsr_hbc_wait_msgint_ready(acb)) { 504*d74001adSXin LI break; 505*d74001adSXin LI } else { 506*d74001adSXin LI retry_count--; 507*d74001adSXin LI } 508*d74001adSXin LI }while(retry_count!=0); 509*d74001adSXin LI return; 510*d74001adSXin LI } 511*d74001adSXin LI /* 512*d74001adSXin LI ************************************************************************ 513*d74001adSXin LI ************************************************************************ 514*d74001adSXin LI */ 51544f05562SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) 51644f05562SScott Long { 51744f05562SScott Long switch (acb->adapter_type) { 51844f05562SScott Long case ACB_ADAPTER_TYPE_A: { 51944f05562SScott Long arcmsr_flush_hba_cache(acb); 52044f05562SScott Long } 52144f05562SScott Long break; 52244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 52344f05562SScott Long arcmsr_flush_hbb_cache(acb); 52444f05562SScott Long } 52544f05562SScott Long break; 526*d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 527*d74001adSXin LI arcmsr_flush_hbc_cache(acb); 528*d74001adSXin LI } 529*d74001adSXin LI break; 53044f05562SScott Long } 53144f05562SScott Long return; 53244f05562SScott Long } 53344f05562SScott Long /* 534ad6d6297SScott Long ******************************************************************************* 535ad6d6297SScott Long ******************************************************************************* 536f1c579b1SScott Long */ 537ad6d6297SScott Long static int arcmsr_suspend(device_t dev) 538f1c579b1SScott Long { 539ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 540f1c579b1SScott Long 541ad6d6297SScott Long /* flush controller */ 542ad6d6297SScott Long arcmsr_iop_parking(acb); 543*d74001adSXin LI /* disable all outbound interrupt */ 544*d74001adSXin LI arcmsr_disable_allintr(acb); 545ad6d6297SScott Long return(0); 546ad6d6297SScott Long } 547ad6d6297SScott Long /* 548ad6d6297SScott Long ******************************************************************************* 549ad6d6297SScott Long ******************************************************************************* 550ad6d6297SScott Long */ 551ad6d6297SScott Long static int arcmsr_resume(device_t dev) 552ad6d6297SScott Long { 553ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 554f1c579b1SScott Long 555ad6d6297SScott Long arcmsr_iop_init(acb); 556ad6d6297SScott Long return(0); 557f1c579b1SScott Long } 558f1c579b1SScott Long /* 559f1c579b1SScott Long ********************************************************************************* 560f1c579b1SScott Long ********************************************************************************* 561f1c579b1SScott Long */ 562ad6d6297SScott Long static void arcmsr_async(void *cb_arg, u_int32_t code, struct cam_path *path, void *arg) 563f1c579b1SScott Long { 564ad6d6297SScott Long struct AdapterControlBlock *acb; 565ad6d6297SScott Long u_int8_t target_id, target_lun; 566f1c579b1SScott Long struct cam_sim * sim; 567f1c579b1SScott Long 568f1c579b1SScott Long sim=(struct cam_sim *) cb_arg; 569ad6d6297SScott Long acb =(struct AdapterControlBlock *) cam_sim_softc(sim); 570ad6d6297SScott Long switch (code) { 571f1c579b1SScott Long case AC_LOST_DEVICE: 572f1c579b1SScott Long target_id=xpt_path_target_id(path); 573f1c579b1SScott Long target_lun=xpt_path_lun_id(path); 574*d74001adSXin LI if((target_id > ARCMSR_MAX_TARGETID) || (target_lun > ARCMSR_MAX_TARGETLUN)) { 575f1c579b1SScott Long break; 576f1c579b1SScott Long } 577*d74001adSXin LI printf("%s:scsi id=%d lun=%d device lost \n", device_get_name(acb->pci_dev), target_id, target_lun); 578f1c579b1SScott Long break; 579f1c579b1SScott Long default: 580f1c579b1SScott Long break; 581f1c579b1SScott Long } 582f1c579b1SScott Long } 583f1c579b1SScott Long /* 584f1c579b1SScott Long ********************************************************************** 585f1c579b1SScott Long ********************************************************************** 586f1c579b1SScott Long */ 587ad6d6297SScott Long static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag) 588f1c579b1SScott Long { 589ad6d6297SScott Long struct AdapterControlBlock *acb=srb->acb; 590ad6d6297SScott Long union ccb * pccb=srb->pccb; 591f1c579b1SScott Long 592ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 593f1c579b1SScott Long bus_dmasync_op_t op; 594f1c579b1SScott Long 595ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 596f1c579b1SScott Long op = BUS_DMASYNC_POSTREAD; 597ad6d6297SScott Long } else { 598f1c579b1SScott Long op = BUS_DMASYNC_POSTWRITE; 599f1c579b1SScott Long } 600ad6d6297SScott Long bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 601ad6d6297SScott Long bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 602f1c579b1SScott Long } 603ad6d6297SScott Long if(stand_flag==1) { 604ad6d6297SScott Long atomic_subtract_int(&acb->srboutstandingcount, 1); 605dc3a205bSScott Long if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) && ( 606dc3a205bSScott Long acb->srboutstandingcount < ARCMSR_RELEASE_SIMQ_LEVEL)) { 607dc3a205bSScott Long acb->acb_flags &= ~ACB_F_CAM_DEV_QFRZN; 608dc3a205bSScott Long pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 609dc3a205bSScott Long } 610ad6d6297SScott Long } 611ad6d6297SScott Long srb->startdone=ARCMSR_SRB_DONE; 612ad6d6297SScott Long srb->srb_flags=0; 613ad6d6297SScott Long acb->srbworkingQ[acb->workingsrb_doneindex]=srb; 614ad6d6297SScott Long acb->workingsrb_doneindex++; 615ad6d6297SScott Long acb->workingsrb_doneindex %= ARCMSR_MAX_FREESRB_NUM; 616f1c579b1SScott Long xpt_done(pccb); 617f1c579b1SScott Long return; 618f1c579b1SScott Long } 619f1c579b1SScott Long /* 620f1c579b1SScott Long ********************************************************************** 621f1c579b1SScott Long ********************************************************************** 622f1c579b1SScott Long */ 623ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb) 624f1c579b1SScott Long { 625ad6d6297SScott Long union ccb * pccb=srb->pccb; 626f1c579b1SScott Long 627ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 628ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 629ad6d6297SScott Long if(&pccb->csio.sense_data) { 630ad6d6297SScott Long memset(&pccb->csio.sense_data, 0, sizeof(pccb->csio.sense_data)); 631ad6d6297SScott Long memcpy(&pccb->csio.sense_data, srb->arcmsr_cdb.SenseData, 632ad6d6297SScott Long get_min(sizeof(struct SENSE_DATA), sizeof(pccb->csio.sense_data))); 633ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); /* Valid,ErrorCode */ 634f1c579b1SScott Long pccb->ccb_h.status |= CAM_AUTOSNS_VALID; 635f1c579b1SScott Long } 636f1c579b1SScott Long return; 637f1c579b1SScott Long } 638f1c579b1SScott Long /* 639f1c579b1SScott Long ********************************************************************* 64044f05562SScott Long ********************************************************************* 64144f05562SScott Long */ 64244f05562SScott Long static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) 64344f05562SScott Long { 64444f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 64544f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 646*d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 64744f05562SScott Long } 64844f05562SScott Long return; 64944f05562SScott Long } 65044f05562SScott Long /* 65144f05562SScott Long ********************************************************************* 65244f05562SScott Long ********************************************************************* 65344f05562SScott Long */ 65444f05562SScott Long static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) 65544f05562SScott Long { 65644f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_ABORT_CMD); 65744f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 658*d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 659*d74001adSXin LI } 660*d74001adSXin LI return; 661*d74001adSXin LI } 662*d74001adSXin LI /* 663*d74001adSXin LI ********************************************************************* 664*d74001adSXin LI ********************************************************************* 665*d74001adSXin LI */ 666*d74001adSXin LI static void arcmsr_abort_hbc_allcmd(struct AdapterControlBlock *acb) 667*d74001adSXin LI { 668*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 669*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 670*d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 671*d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 67244f05562SScott Long } 67344f05562SScott Long return; 67444f05562SScott Long } 67544f05562SScott Long /* 67644f05562SScott Long ********************************************************************* 677f1c579b1SScott Long ********************************************************************* 678f1c579b1SScott Long */ 679ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) 680f1c579b1SScott Long { 68144f05562SScott Long switch (acb->adapter_type) { 68244f05562SScott Long case ACB_ADAPTER_TYPE_A: { 68344f05562SScott Long arcmsr_abort_hba_allcmd(acb); 68444f05562SScott Long } 68544f05562SScott Long break; 68644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 68744f05562SScott Long arcmsr_abort_hbb_allcmd(acb); 68844f05562SScott Long } 68944f05562SScott Long break; 690*d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 691*d74001adSXin LI arcmsr_abort_hbc_allcmd(acb); 692*d74001adSXin LI } 693*d74001adSXin LI break; 69444f05562SScott Long } 69544f05562SScott Long return; 69644f05562SScott Long } 69744f05562SScott Long /* 69844f05562SScott Long ************************************************************************** 69944f05562SScott Long ************************************************************************** 70044f05562SScott Long */ 701*d74001adSXin LI static void arcmsr_report_srb_state(struct AdapterControlBlock *acb, struct CommandControlBlock *srb, u_int16_t error) 70244f05562SScott Long { 70344f05562SScott Long int target, lun; 70444f05562SScott Long 70544f05562SScott Long target=srb->pccb->ccb_h.target_id; 70644f05562SScott Long lun=srb->pccb->ccb_h.target_lun; 707*d74001adSXin LI if(error == FALSE) { 70844f05562SScott Long if(acb->devstate[target][lun]==ARECA_RAID_GONE) { 70944f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GOOD; 71044f05562SScott Long } 71144f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_CMP; 71244f05562SScott Long arcmsr_srb_complete(srb, 1); 71344f05562SScott Long } else { 71444f05562SScott Long switch(srb->arcmsr_cdb.DeviceStatus) { 71544f05562SScott Long case ARCMSR_DEV_SELECT_TIMEOUT: { 71644f05562SScott Long if(acb->devstate[target][lun]==ARECA_RAID_GOOD) { 717*d74001adSXin LI printf( "arcmsr%d: Target=%x, Lun=%x, selection timeout, raid volume was lost\n", acb->pci_unit, target, lun); 718ad6d6297SScott Long } 71944f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GONE; 720*d74001adSXin LI srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 72144f05562SScott Long arcmsr_srb_complete(srb, 1); 72244f05562SScott Long } 72344f05562SScott Long break; 72444f05562SScott Long case ARCMSR_DEV_ABORTED: 72544f05562SScott Long case ARCMSR_DEV_INIT_FAIL: { 72644f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GONE; 72744f05562SScott Long srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 72844f05562SScott Long arcmsr_srb_complete(srb, 1); 72944f05562SScott Long } 73044f05562SScott Long break; 73144f05562SScott Long case SCSISTAT_CHECK_CONDITION: { 73244f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GOOD; 73344f05562SScott Long arcmsr_report_sense_info(srb); 73444f05562SScott Long arcmsr_srb_complete(srb, 1); 73544f05562SScott Long } 73644f05562SScott Long break; 73744f05562SScott Long default: 738*d74001adSXin LI printf("arcmsr%d: scsi id=%d lun=%d isr got command error done,but got unknow DeviceStatus=0x%x \n" 739*d74001adSXin LI , acb->pci_unit, target, lun ,srb->arcmsr_cdb.DeviceStatus); 74044f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GONE; 74144f05562SScott Long srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY; 74244f05562SScott Long /*unknow error or crc error just for retry*/ 74344f05562SScott Long arcmsr_srb_complete(srb, 1); 74444f05562SScott Long break; 74544f05562SScott Long } 74644f05562SScott Long } 74744f05562SScott Long return; 74844f05562SScott Long } 74944f05562SScott Long /* 75044f05562SScott Long ************************************************************************** 75144f05562SScott Long ************************************************************************** 75244f05562SScott Long */ 753*d74001adSXin LI static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t flag_srb, u_int16_t error) 75444f05562SScott Long { 75544f05562SScott Long struct CommandControlBlock *srb; 75644f05562SScott Long 75744f05562SScott Long /* check if command done with no error*/ 758*d74001adSXin LI switch (acb->adapter_type) { 759*d74001adSXin LI case ACB_ADAPTER_TYPE_C: 760*d74001adSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFF0));/*frame must be 32 bytes aligned*/ 761*d74001adSXin LI break; 762*d74001adSXin LI case ACB_ADAPTER_TYPE_A: 763*d74001adSXin LI case ACB_ADAPTER_TYPE_B: 764*d74001adSXin LI default: 765*d74001adSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 766*d74001adSXin LI break; 767*d74001adSXin LI } 76844f05562SScott Long if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) { 76944f05562SScott Long if(srb->startdone==ARCMSR_SRB_ABORTED) { 770*d74001adSXin LI printf("arcmsr%d: srb='%p' isr got aborted command \n", acb->pci_unit, srb); 77144f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 77244f05562SScott Long arcmsr_srb_complete(srb, 1); 77344f05562SScott Long return; 77444f05562SScott Long } 77544f05562SScott Long printf("arcmsr%d: isr get an illegal srb command done" 776*d74001adSXin LI "acb='%p' srb='%p' srbacb='%p' startdone=0x%xsrboutstandingcount=%d \n", 777*d74001adSXin LI acb->pci_unit, acb, srb, srb->acb,srb->startdone, acb->srboutstandingcount); 77844f05562SScott Long return; 77944f05562SScott Long } 780*d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 78144f05562SScott Long return; 78244f05562SScott Long } 78344f05562SScott Long /* 78444f05562SScott Long ********************************************************************** 78544f05562SScott Long ********************************************************************** 78644f05562SScott Long */ 78744f05562SScott Long static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) 78844f05562SScott Long { 78944f05562SScott Long int i=0; 79044f05562SScott Long u_int32_t flag_srb; 791*d74001adSXin LI u_int16_t error; 79244f05562SScott Long 79344f05562SScott Long switch (acb->adapter_type) { 79444f05562SScott Long case ACB_ADAPTER_TYPE_A: { 79544f05562SScott Long u_int32_t outbound_intstatus; 79644f05562SScott Long 79744f05562SScott Long /*clear and abort all outbound posted Q*/ 798*d74001adSXin LI outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 799*d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/ 800*d74001adSXin LI while(((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_queueport)) != 0xFFFFFFFF) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { 801*d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 802*d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 80344f05562SScott Long } 80444f05562SScott Long } 80544f05562SScott Long break; 80644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 80744f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 80844f05562SScott Long 80944f05562SScott Long /*clear all outbound posted Q*/ 810*d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 81144f05562SScott Long for(i=0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) { 81244f05562SScott Long if((flag_srb=phbbmu->done_qbuffer[i])!=0) { 81344f05562SScott Long phbbmu->done_qbuffer[i]=0; 814*d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 815*d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 81644f05562SScott Long } 81744f05562SScott Long phbbmu->post_qbuffer[i]=0; 81844f05562SScott Long }/*drain reply FIFO*/ 81944f05562SScott Long phbbmu->doneq_index=0; 82044f05562SScott Long phbbmu->postq_index=0; 82144f05562SScott Long } 82244f05562SScott Long break; 823*d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 824*d74001adSXin LI 825*d74001adSXin LI while((CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { 826*d74001adSXin LI flag_srb=CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 827*d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; 828*d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 829*d74001adSXin LI } 830*d74001adSXin LI } 831*d74001adSXin LI break; 83244f05562SScott Long } 833f1c579b1SScott Long return; 834f1c579b1SScott Long } 835f1c579b1SScott Long /* 836f1c579b1SScott Long **************************************************************************** 837f1c579b1SScott Long **************************************************************************** 838f1c579b1SScott Long */ 839ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb) 840f1c579b1SScott Long { 841ad6d6297SScott Long struct CommandControlBlock *srb; 84244f05562SScott Long u_int32_t intmask_org; 843ad6d6297SScott Long u_int32_t i=0; 844f1c579b1SScott Long 84544f05562SScott Long if(acb->srboutstandingcount>0) { 84644f05562SScott Long /* disable all outbound interrupt */ 84744f05562SScott Long intmask_org=arcmsr_disable_allintr(acb); 84844f05562SScott Long /*clear and abort all outbound posted Q*/ 84944f05562SScott Long arcmsr_done4abort_postqueue(acb); 850f1c579b1SScott Long /* talk to iop 331 outstanding command aborted*/ 851ad6d6297SScott Long arcmsr_abort_allcmd(acb); 852ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 853ad6d6297SScott Long srb=acb->psrb_pool[i]; 854ad6d6297SScott Long if(srb->startdone==ARCMSR_SRB_START) { 855ad6d6297SScott Long srb->startdone=ARCMSR_SRB_ABORTED; 856ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 857ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 858f1c579b1SScott Long } 859f1c579b1SScott Long } 860f1c579b1SScott Long /* enable all outbound interrupt */ 86144f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 862f1c579b1SScott Long } 863ad6d6297SScott Long atomic_set_int(&acb->srboutstandingcount, 0); 864ad6d6297SScott Long acb->workingsrb_doneindex=0; 865ad6d6297SScott Long acb->workingsrb_startindex=0; 866f1c579b1SScott Long return; 867f1c579b1SScott Long } 868f1c579b1SScott Long /* 869f1c579b1SScott Long ********************************************************************** 870f1c579b1SScott Long ********************************************************************** 871f1c579b1SScott Long */ 87244f05562SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, 87344f05562SScott Long bus_dma_segment_t *dm_segs, u_int32_t nseg) 874f1c579b1SScott Long { 875ad6d6297SScott Long struct ARCMSR_CDB * arcmsr_cdb= &srb->arcmsr_cdb; 876ad6d6297SScott Long u_int8_t * psge=(u_int8_t *)&arcmsr_cdb->u; 877ad6d6297SScott Long u_int32_t address_lo, address_hi; 878ad6d6297SScott Long union ccb * pccb=srb->pccb; 879f1c579b1SScott Long struct ccb_scsiio * pcsio= &pccb->csio; 880ad6d6297SScott Long u_int32_t arccdbsize=0x30; 881f1c579b1SScott Long 882ad6d6297SScott Long memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB)); 883ad6d6297SScott Long arcmsr_cdb->Bus=0; 884ad6d6297SScott Long arcmsr_cdb->TargetID=pccb->ccb_h.target_id; 885ad6d6297SScott Long arcmsr_cdb->LUN=pccb->ccb_h.target_lun; 886ad6d6297SScott Long arcmsr_cdb->Function=1; 887ad6d6297SScott Long arcmsr_cdb->CdbLength=(u_int8_t)pcsio->cdb_len; 88844f05562SScott Long arcmsr_cdb->Context=0; 889ad6d6297SScott Long bcopy(pcsio->cdb_io.cdb_bytes, arcmsr_cdb->Cdb, pcsio->cdb_len); 890ad6d6297SScott Long if(nseg != 0) { 891ad6d6297SScott Long struct AdapterControlBlock *acb=srb->acb; 892f1c579b1SScott Long bus_dmasync_op_t op; 893ad6d6297SScott Long u_int32_t length, i, cdb_sgcount=0; 894f1c579b1SScott Long 895ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 896ad6d6297SScott Long op=BUS_DMASYNC_PREREAD; 897ad6d6297SScott Long } else { 898ad6d6297SScott Long op=BUS_DMASYNC_PREWRITE; 899ad6d6297SScott Long arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_WRITE; 900ad6d6297SScott Long srb->srb_flags|=SRB_FLAG_WRITE; 901ad6d6297SScott Long } 902ad6d6297SScott Long bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 903ad6d6297SScott Long for(i=0;i<nseg;i++) { 904f1c579b1SScott Long /* Get the physical address of the current data pointer */ 905ad6d6297SScott Long length=arcmsr_htole32(dm_segs[i].ds_len); 906ad6d6297SScott Long address_lo=arcmsr_htole32(dma_addr_lo32(dm_segs[i].ds_addr)); 907ad6d6297SScott Long address_hi=arcmsr_htole32(dma_addr_hi32(dm_segs[i].ds_addr)); 908ad6d6297SScott Long if(address_hi==0) { 909ad6d6297SScott Long struct SG32ENTRY * pdma_sg=(struct SG32ENTRY *)psge; 910f1c579b1SScott Long pdma_sg->address=address_lo; 911f1c579b1SScott Long pdma_sg->length=length; 912ad6d6297SScott Long psge += sizeof(struct SG32ENTRY); 913ad6d6297SScott Long arccdbsize += sizeof(struct SG32ENTRY); 914ad6d6297SScott Long } else { 915ad6d6297SScott Long u_int32_t sg64s_size=0, tmplength=length; 916f1c579b1SScott Long 917ad6d6297SScott Long while(1) { 918ad6d6297SScott Long u_int64_t span4G, length0; 919ad6d6297SScott Long struct SG64ENTRY * pdma_sg=(struct SG64ENTRY *)psge; 920f1c579b1SScott Long 921ad6d6297SScott Long span4G=(u_int64_t)address_lo + tmplength; 922f1c579b1SScott Long pdma_sg->addresshigh=address_hi; 923f1c579b1SScott Long pdma_sg->address=address_lo; 924ad6d6297SScott Long if(span4G > 0x100000000) { 925f1c579b1SScott Long /*see if cross 4G boundary*/ 926f1c579b1SScott Long length0=0x100000000-address_lo; 927ad6d6297SScott Long pdma_sg->length=(u_int32_t)length0|IS_SG64_ADDR; 928f1c579b1SScott Long address_hi=address_hi+1; 929f1c579b1SScott Long address_lo=0; 930ad6d6297SScott Long tmplength=tmplength-(u_int32_t)length0; 931ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 932ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 933f1c579b1SScott Long cdb_sgcount++; 934ad6d6297SScott Long } else { 935f1c579b1SScott Long pdma_sg->length=tmplength|IS_SG64_ADDR; 936ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 937ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 938f1c579b1SScott Long break; 939f1c579b1SScott Long } 940f1c579b1SScott Long } 941f1c579b1SScott Long arccdbsize += sg64s_size; 942f1c579b1SScott Long } 943f1c579b1SScott Long cdb_sgcount++; 944f1c579b1SScott Long } 945ad6d6297SScott Long arcmsr_cdb->sgcount=(u_int8_t)cdb_sgcount; 946ad6d6297SScott Long arcmsr_cdb->DataLength=pcsio->dxfer_len; 947ad6d6297SScott Long if( arccdbsize > 256) { 948ad6d6297SScott Long arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_SGL_BSIZE; 949f1c579b1SScott Long } 950*d74001adSXin LI } else { 951*d74001adSXin LI arcmsr_cdb->DataLength = 0; 952f1c579b1SScott Long } 953*d74001adSXin LI srb->arc_cdb_size=arccdbsize; 954f1c579b1SScott Long return; 955f1c579b1SScott Long } 956f1c579b1SScott Long /* 957f1c579b1SScott Long ************************************************************************** 958f1c579b1SScott Long ************************************************************************** 959f1c579b1SScott Long */ 960ad6d6297SScott Long static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandControlBlock *srb) 961f1c579b1SScott Long { 962ad6d6297SScott Long u_int32_t cdb_shifted_phyaddr=(u_int32_t) srb->cdb_shifted_phyaddr; 963ad6d6297SScott Long struct ARCMSR_CDB * arcmsr_cdb=(struct ARCMSR_CDB *)&srb->arcmsr_cdb; 964f1c579b1SScott Long 965*d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, (srb->srb_flags & SRB_FLAG_WRITE) ? BUS_DMASYNC_POSTWRITE:BUS_DMASYNC_POSTREAD); 966ad6d6297SScott Long atomic_add_int(&acb->srboutstandingcount, 1); 967ad6d6297SScott Long srb->startdone=ARCMSR_SRB_START; 968*d74001adSXin LI 96944f05562SScott Long switch (acb->adapter_type) { 97044f05562SScott Long case ACB_ADAPTER_TYPE_A: { 971ad6d6297SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 972*d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE); 973ad6d6297SScott Long } else { 974*d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_shifted_phyaddr); 97544f05562SScott Long } 97644f05562SScott Long } 97744f05562SScott Long break; 97844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 97944f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 98044f05562SScott Long int ending_index, index; 98144f05562SScott Long 98244f05562SScott Long index=phbbmu->postq_index; 98344f05562SScott Long ending_index=((index+1)%ARCMSR_MAX_HBB_POSTQUEUE); 98444f05562SScott Long phbbmu->post_qbuffer[ending_index]=0; 98544f05562SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 986*d74001adSXin LI phbbmu->post_qbuffer[index]= cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE; 98744f05562SScott Long } else { 988*d74001adSXin LI phbbmu->post_qbuffer[index]= cdb_shifted_phyaddr; 98944f05562SScott Long } 99044f05562SScott Long index++; 99144f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 99244f05562SScott Long phbbmu->postq_index=index; 993*d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED); 994*d74001adSXin LI } 995*d74001adSXin LI break; 996*d74001adSXin LI case ACB_ADAPTER_TYPE_C: 997*d74001adSXin LI { 998*d74001adSXin LI u_int32_t ccb_post_stamp, arc_cdb_size, cdb_phyaddr_hi32; 999*d74001adSXin LI 1000*d74001adSXin LI arc_cdb_size=(srb->arc_cdb_size>0x300)?0x300:srb->arc_cdb_size; 1001*d74001adSXin LI ccb_post_stamp=(cdb_shifted_phyaddr | ((arc_cdb_size-1) >> 6) | 1); 1002*d74001adSXin LI cdb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high; 1003*d74001adSXin LI if(cdb_phyaddr_hi32) 1004*d74001adSXin LI { 1005*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_high, cdb_phyaddr_hi32); 1006*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp); 1007*d74001adSXin LI } 1008*d74001adSXin LI else 1009*d74001adSXin LI { 1010*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp); 1011*d74001adSXin LI } 101244f05562SScott Long } 101344f05562SScott Long break; 1014f1c579b1SScott Long } 1015f1c579b1SScott Long return; 1016f1c579b1SScott Long } 1017f1c579b1SScott Long /* 101844f05562SScott Long ************************************************************************ 101944f05562SScott Long ************************************************************************ 102044f05562SScott Long */ 102144f05562SScott Long static struct QBUFFER * arcmsr_get_iop_rqbuffer( struct AdapterControlBlock *acb) 102244f05562SScott Long { 102344f05562SScott Long struct QBUFFER *qbuffer=NULL; 102444f05562SScott Long 102544f05562SScott Long switch (acb->adapter_type) { 102644f05562SScott Long case ACB_ADAPTER_TYPE_A: { 102744f05562SScott Long struct HBA_MessageUnit *phbamu=(struct HBA_MessageUnit *)acb->pmu; 102844f05562SScott Long 102944f05562SScott Long qbuffer=(struct QBUFFER *)&phbamu->message_rbuffer; 103044f05562SScott Long } 103144f05562SScott Long break; 103244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 103344f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 103444f05562SScott Long 103544f05562SScott Long qbuffer=(struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_rbuffer; 103644f05562SScott Long } 103744f05562SScott Long break; 1038*d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1039*d74001adSXin LI struct HBC_MessageUnit *phbcmu=(struct HBC_MessageUnit *)acb->pmu; 1040*d74001adSXin LI 1041*d74001adSXin LI qbuffer=(struct QBUFFER *)&phbcmu->message_rbuffer; 1042*d74001adSXin LI } 1043*d74001adSXin LI break; 104444f05562SScott Long } 104544f05562SScott Long return(qbuffer); 104644f05562SScott Long } 104744f05562SScott Long /* 104844f05562SScott Long ************************************************************************ 104944f05562SScott Long ************************************************************************ 105044f05562SScott Long */ 105144f05562SScott Long static struct QBUFFER * arcmsr_get_iop_wqbuffer( struct AdapterControlBlock *acb) 105244f05562SScott Long { 105344f05562SScott Long struct QBUFFER *qbuffer=NULL; 105444f05562SScott Long 105544f05562SScott Long switch (acb->adapter_type) { 105644f05562SScott Long case ACB_ADAPTER_TYPE_A: { 105744f05562SScott Long struct HBA_MessageUnit *phbamu=(struct HBA_MessageUnit *)acb->pmu; 105844f05562SScott Long 105944f05562SScott Long qbuffer=(struct QBUFFER *)&phbamu->message_wbuffer; 106044f05562SScott Long } 106144f05562SScott Long break; 106244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 106344f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 106444f05562SScott Long 106544f05562SScott Long qbuffer=(struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_wbuffer; 106644f05562SScott Long } 106744f05562SScott Long break; 1068*d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1069*d74001adSXin LI struct HBC_MessageUnit *phbcmu=(struct HBC_MessageUnit *)acb->pmu; 1070*d74001adSXin LI 1071*d74001adSXin LI qbuffer=(struct QBUFFER *)&phbcmu->message_wbuffer; 1072*d74001adSXin LI } 1073*d74001adSXin LI break; 107444f05562SScott Long } 107544f05562SScott Long return(qbuffer); 107644f05562SScott Long } 107744f05562SScott Long /* 107844f05562SScott Long ************************************************************************** 107944f05562SScott Long ************************************************************************** 108044f05562SScott Long */ 108144f05562SScott Long static void arcmsr_iop_message_read(struct AdapterControlBlock *acb) 108244f05562SScott Long { 108344f05562SScott Long switch (acb->adapter_type) { 108444f05562SScott Long case ACB_ADAPTER_TYPE_A: { 108544f05562SScott Long /* let IOP know data has been read */ 1086*d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 108744f05562SScott Long } 108844f05562SScott Long break; 108944f05562SScott Long case ACB_ADAPTER_TYPE_B: { 109044f05562SScott Long /* let IOP know data has been read */ 1091*d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 109244f05562SScott Long } 109344f05562SScott Long break; 1094*d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1095*d74001adSXin LI /* let IOP know data has been read */ 1096*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK); 1097*d74001adSXin LI } 109844f05562SScott Long } 109944f05562SScott Long return; 110044f05562SScott Long } 110144f05562SScott Long /* 110244f05562SScott Long ************************************************************************** 110344f05562SScott Long ************************************************************************** 110444f05562SScott Long */ 110544f05562SScott Long static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) 110644f05562SScott Long { 110744f05562SScott Long switch (acb->adapter_type) { 110844f05562SScott Long case ACB_ADAPTER_TYPE_A: { 110944f05562SScott Long /* 111044f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 111144f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 111244f05562SScott Long */ 1113*d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK); 111444f05562SScott Long } 111544f05562SScott Long break; 111644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 111744f05562SScott Long /* 111844f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 111944f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 112044f05562SScott Long */ 1121*d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_WRITE_OK); 1122*d74001adSXin LI } 1123*d74001adSXin LI break; 1124*d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1125*d74001adSXin LI /* 1126*d74001adSXin LI ** push inbound doorbell tell iop, driver data write ok 1127*d74001adSXin LI ** and wait reply on next hwinterrupt for next Qbuffer post 1128*d74001adSXin LI */ 1129*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK); 113044f05562SScott Long } 113144f05562SScott Long break; 113244f05562SScott Long } 113344f05562SScott Long } 113444f05562SScott Long /* 1135f1c579b1SScott Long ********************************************************************** 1136f1c579b1SScott Long ********************************************************************** 1137f1c579b1SScott Long */ 113844f05562SScott Long static void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb) 1139f1c579b1SScott Long { 1140ad6d6297SScott Long u_int8_t *pQbuffer; 114144f05562SScott Long struct QBUFFER *pwbuffer; 114244f05562SScott Long u_int8_t * iop_data; 114344f05562SScott Long int32_t allxfer_len=0; 1144f1c579b1SScott Long 114544f05562SScott Long pwbuffer=arcmsr_get_iop_wqbuffer(acb); 114644f05562SScott Long iop_data=(u_int8_t *)pwbuffer->data; 114744f05562SScott Long if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) { 114844f05562SScott Long acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 114944f05562SScott Long while((acb->wqbuf_firstindex!=acb->wqbuf_lastindex) 115044f05562SScott Long && (allxfer_len<124)) { 1151ad6d6297SScott Long pQbuffer=&acb->wqbuffer[acb->wqbuf_firstindex]; 1152f1c579b1SScott Long memcpy(iop_data, pQbuffer, 1); 1153ad6d6297SScott Long acb->wqbuf_firstindex++; 115444f05562SScott Long acb->wqbuf_firstindex %=ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */ 1155f1c579b1SScott Long iop_data++; 1156f1c579b1SScott Long allxfer_len++; 1157f1c579b1SScott Long } 1158f1c579b1SScott Long pwbuffer->data_len=allxfer_len; 1159f1c579b1SScott Long /* 1160f1c579b1SScott Long ** push inbound doorbell and wait reply at hwinterrupt routine for next Qbuffer post 1161f1c579b1SScott Long */ 116244f05562SScott Long arcmsr_iop_message_wrote(acb); 1163ad6d6297SScott Long } 1164f1c579b1SScott Long return; 1165f1c579b1SScott Long } 1166f1c579b1SScott Long /* 1167f1c579b1SScott Long ************************************************************************ 1168f1c579b1SScott Long ************************************************************************ 1169f1c579b1SScott Long */ 117044f05562SScott Long static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb) 1171f1c579b1SScott Long { 1172ad6d6297SScott Long acb->acb_flags &=~ACB_F_MSG_START_BGRB; 117344f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 117444f05562SScott Long 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 117544f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 1176*d74001adSXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n" 1177ad6d6297SScott Long , acb->pci_unit); 1178ad6d6297SScott Long } 1179f1c579b1SScott Long return; 1180f1c579b1SScott Long } 1181f1c579b1SScott Long /* 1182f1c579b1SScott Long ************************************************************************ 1183f1c579b1SScott Long ************************************************************************ 1184f1c579b1SScott Long */ 118544f05562SScott Long static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb) 118644f05562SScott Long { 118744f05562SScott Long acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 118844f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 118944f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_STOP_BGRB); 119044f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 1191*d74001adSXin LI printf( "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" 119244f05562SScott Long , acb->pci_unit); 119344f05562SScott Long } 119444f05562SScott Long return; 119544f05562SScott Long } 119644f05562SScott Long /* 119744f05562SScott Long ************************************************************************ 119844f05562SScott Long ************************************************************************ 119944f05562SScott Long */ 1200*d74001adSXin LI static void arcmsr_stop_hbc_bgrb(struct AdapterControlBlock *acb) 1201*d74001adSXin LI { 1202*d74001adSXin LI acb->acb_flags &=~ACB_F_MSG_START_BGRB; 1203*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 1204*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 1205*d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 1206*d74001adSXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit); 1207*d74001adSXin LI } 1208*d74001adSXin LI return; 1209*d74001adSXin LI } 1210*d74001adSXin LI /* 1211*d74001adSXin LI ************************************************************************ 1212*d74001adSXin LI ************************************************************************ 1213*d74001adSXin LI */ 121444f05562SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) 121544f05562SScott Long { 121644f05562SScott Long switch (acb->adapter_type) { 121744f05562SScott Long case ACB_ADAPTER_TYPE_A: { 121844f05562SScott Long arcmsr_stop_hba_bgrb(acb); 121944f05562SScott Long } 122044f05562SScott Long break; 122144f05562SScott Long case ACB_ADAPTER_TYPE_B: { 122244f05562SScott Long arcmsr_stop_hbb_bgrb(acb); 122344f05562SScott Long } 122444f05562SScott Long break; 1225*d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1226*d74001adSXin LI arcmsr_stop_hbc_bgrb(acb); 1227*d74001adSXin LI } 1228*d74001adSXin LI break; 122944f05562SScott Long } 123044f05562SScott Long return; 123144f05562SScott Long } 123244f05562SScott Long /* 123344f05562SScott Long ************************************************************************ 123444f05562SScott Long ************************************************************************ 123544f05562SScott Long */ 1236ad6d6297SScott Long static void arcmsr_poll(struct cam_sim * psim) 1237f1c579b1SScott Long { 1238579ec1a5SScott Long struct AdapterControlBlock *acb; 1239579ec1a5SScott Long 1240579ec1a5SScott Long acb = (struct AdapterControlBlock *)cam_sim_softc(psim); 1241579ec1a5SScott Long #if __FreeBSD_version < 700025 1242579ec1a5SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 1243579ec1a5SScott Long #endif 1244579ec1a5SScott Long arcmsr_interrupt(acb); 1245579ec1a5SScott Long #if __FreeBSD_version < 700025 1246579ec1a5SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1247579ec1a5SScott Long #endif 1248f1c579b1SScott Long return; 1249f1c579b1SScott Long } 1250f1c579b1SScott Long /* 125144f05562SScott Long ************************************************************************** 125244f05562SScott Long ************************************************************************** 12535878cbecSScott Long */ 125444f05562SScott Long static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) 1255f1c579b1SScott Long { 125644f05562SScott Long struct QBUFFER *prbuffer; 1257ad6d6297SScott Long u_int8_t *pQbuffer; 125844f05562SScott Long u_int8_t *iop_data; 125944f05562SScott Long int my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; 1260ad6d6297SScott Long 1261f1c579b1SScott Long /*check this iop data if overflow my rqbuffer*/ 1262ad6d6297SScott Long rqbuf_lastindex=acb->rqbuf_lastindex; 1263ad6d6297SScott Long rqbuf_firstindex=acb->rqbuf_firstindex; 126444f05562SScott Long prbuffer=arcmsr_get_iop_rqbuffer(acb); 126544f05562SScott Long iop_data=(u_int8_t *)prbuffer->data; 1266f1c579b1SScott Long iop_len=prbuffer->data_len; 1267f1c579b1SScott Long my_empty_len=(rqbuf_firstindex-rqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1); 1268ad6d6297SScott Long if(my_empty_len>=iop_len) { 1269ad6d6297SScott Long while(iop_len > 0) { 127044f05562SScott Long pQbuffer=&acb->rqbuffer[rqbuf_lastindex]; 1271f1c579b1SScott Long memcpy(pQbuffer, iop_data, 1); 127244f05562SScott Long rqbuf_lastindex++; 127344f05562SScott Long rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;/*if last index number set it to 0 */ 1274f1c579b1SScott Long iop_data++; 1275f1c579b1SScott Long iop_len--; 1276f1c579b1SScott Long } 127744f05562SScott Long acb->rqbuf_lastindex=rqbuf_lastindex; 127844f05562SScott Long arcmsr_iop_message_read(acb); 127944f05562SScott Long /*signature, let IOP know data has been read */ 1280ad6d6297SScott Long } else { 1281ad6d6297SScott Long acb->acb_flags|=ACB_F_IOPDATA_OVERFLOW; 1282f1c579b1SScott Long } 128344f05562SScott Long return; 1284f1c579b1SScott Long } 1285f1c579b1SScott Long /* 128644f05562SScott Long ************************************************************************** 128744f05562SScott Long ************************************************************************** 128844f05562SScott Long */ 128944f05562SScott Long static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) 129044f05562SScott Long { 129144f05562SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READ; 129244f05562SScott Long /* 129344f05562SScott Long ***************************************************************** 129444f05562SScott Long ** check if there are any mail packages from user space program 129544f05562SScott Long ** in my post bag, now is the time to send them into Areca's firmware 129644f05562SScott Long ***************************************************************** 1297f1c579b1SScott Long */ 1298ad6d6297SScott Long if(acb->wqbuf_firstindex!=acb->wqbuf_lastindex) { 1299ad6d6297SScott Long u_int8_t *pQbuffer; 130044f05562SScott Long struct QBUFFER *pwbuffer; 130144f05562SScott Long u_int8_t *iop_data; 130244f05562SScott Long int allxfer_len=0; 1303f1c579b1SScott Long 130444f05562SScott Long acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 130544f05562SScott Long pwbuffer=arcmsr_get_iop_wqbuffer(acb); 130644f05562SScott Long iop_data=(u_int8_t *)pwbuffer->data; 130744f05562SScott Long while((acb->wqbuf_firstindex!=acb->wqbuf_lastindex) 130844f05562SScott Long && (allxfer_len<124)) { 1309ad6d6297SScott Long pQbuffer=&acb->wqbuffer[acb->wqbuf_firstindex]; 1310f1c579b1SScott Long memcpy(iop_data, pQbuffer, 1); 1311ad6d6297SScott Long acb->wqbuf_firstindex++; 131244f05562SScott Long acb->wqbuf_firstindex %=ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */ 1313f1c579b1SScott Long iop_data++; 1314f1c579b1SScott Long allxfer_len++; 1315f1c579b1SScott Long } 1316f1c579b1SScott Long pwbuffer->data_len=allxfer_len; 1317f1c579b1SScott Long /* 1318ad6d6297SScott Long ** push inbound doorbell tell iop driver data write ok 1319ad6d6297SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 1320f1c579b1SScott Long */ 132144f05562SScott Long arcmsr_iop_message_wrote(acb); 1322f1c579b1SScott Long } 1323ad6d6297SScott Long if(acb->wqbuf_firstindex==acb->wqbuf_lastindex) { 1324ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; 1325f1c579b1SScott Long } 132644f05562SScott Long return; 1327f1c579b1SScott Long } 1328*d74001adSXin LI 1329*d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb) 1330*d74001adSXin LI { 1331*d74001adSXin LI /* 1332*d74001adSXin LI if (ccb->ccb_h.status != CAM_REQ_CMP) 1333*d74001adSXin LI printf("arcmsr_rescanLun_cb: Rescan Target=%x, lun=%x, failure status=%x\n",ccb->ccb_h.target_id,ccb->ccb_h.target_lun,ccb->ccb_h.status); 1334*d74001adSXin LI else 1335*d74001adSXin LI printf("arcmsr_rescanLun_cb: Rescan lun successfully!\n"); 1336*d74001adSXin LI */ 1337*d74001adSXin LI xpt_free_path(ccb->ccb_h.path); 1338*d74001adSXin LI xpt_free_ccb(ccb); 1339*d74001adSXin LI } 1340*d74001adSXin LI 1341*d74001adSXin LI static void arcmsr_rescan_lun(struct AdapterControlBlock *acb, int target, int lun) 1342*d74001adSXin LI { 1343*d74001adSXin LI struct cam_path *path; 1344*d74001adSXin LI union ccb *ccb; 1345*d74001adSXin LI 1346*d74001adSXin LI if ((ccb = (union ccb *)xpt_alloc_ccb_nowait()) == NULL) 1347*d74001adSXin LI return; 1348*d74001adSXin LI if (xpt_create_path(&path, xpt_periph, cam_sim_path(acb->psim), target, lun) != CAM_REQ_CMP) 1349*d74001adSXin LI { 1350*d74001adSXin LI xpt_free_ccb(ccb); 1351*d74001adSXin LI return; 1352*d74001adSXin LI } 1353*d74001adSXin LI /* printf("arcmsr_rescan_lun: Rescan Target=%x, Lun=%x\n", target, lun); */ 1354*d74001adSXin LI bzero(ccb, sizeof(union ccb)); 1355*d74001adSXin LI xpt_setup_ccb(&ccb->ccb_h, path, 5); 1356*d74001adSXin LI ccb->ccb_h.func_code = XPT_SCAN_LUN; 1357*d74001adSXin LI ccb->ccb_h.cbfcnp = arcmsr_rescanLun_cb; 1358*d74001adSXin LI ccb->crcn.flags = CAM_FLAG_NONE; 1359*d74001adSXin LI xpt_action(ccb); 1360*d74001adSXin LI return; 1361*d74001adSXin LI } 1362*d74001adSXin LI 1363*d74001adSXin LI 1364*d74001adSXin LI static void arcmsr_abort_dr_ccbs(struct AdapterControlBlock *acb, int target, int lun) 1365*d74001adSXin LI { 1366*d74001adSXin LI struct CommandControlBlock *srb; 1367*d74001adSXin LI u_int32_t intmask_org; 1368*d74001adSXin LI int i; 1369*d74001adSXin LI 1370*d74001adSXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 1371*d74001adSXin LI /* disable all outbound interrupts */ 1372*d74001adSXin LI intmask_org = arcmsr_disable_allintr(acb); 1373*d74001adSXin LI for (i = 0; i < ARCMSR_MAX_FREESRB_NUM; i++) 1374*d74001adSXin LI { 1375*d74001adSXin LI srb = acb->psrb_pool[i]; 1376*d74001adSXin LI if (srb->startdone == ARCMSR_SRB_START) 1377*d74001adSXin LI { 1378*d74001adSXin LI if((target == srb->pccb->ccb_h.target_id) && (lun == srb->pccb->ccb_h.target_lun)) 1379*d74001adSXin LI { 1380*d74001adSXin LI srb->startdone = ARCMSR_SRB_ABORTED; 1381*d74001adSXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 1382*d74001adSXin LI arcmsr_srb_complete(srb, 1); 1383*d74001adSXin LI } 1384*d74001adSXin LI } 1385*d74001adSXin LI } 1386*d74001adSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 1387*d74001adSXin LI arcmsr_enable_allintr(acb, intmask_org); 1388*d74001adSXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1389*d74001adSXin LI } 1390*d74001adSXin LI 1391*d74001adSXin LI 1392*d74001adSXin LI /* 1393*d74001adSXin LI ************************************************************************** 1394*d74001adSXin LI ************************************************************************** 1395*d74001adSXin LI */ 1396*d74001adSXin LI static void arcmsr_dr_handle(struct AdapterControlBlock *acb) { 1397*d74001adSXin LI u_int32_t devicemap; 1398*d74001adSXin LI u_int32_t target, lun; 1399*d74001adSXin LI u_int32_t deviceMapCurrent[4]={0}; 1400*d74001adSXin LI u_int8_t *pDevMap; 1401*d74001adSXin LI 1402*d74001adSXin LI switch (acb->adapter_type) { 1403*d74001adSXin LI case ACB_ADAPTER_TYPE_A: 1404*d74001adSXin LI devicemap = offsetof(struct HBA_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1405*d74001adSXin LI for (target= 0; target < 4; target++) 1406*d74001adSXin LI { 1407*d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1408*d74001adSXin LI devicemap += 4; 1409*d74001adSXin LI } 1410*d74001adSXin LI break; 1411*d74001adSXin LI 1412*d74001adSXin LI case ACB_ADAPTER_TYPE_B: 1413*d74001adSXin LI devicemap = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1414*d74001adSXin LI for (target= 0; target < 4; target++) 1415*d74001adSXin LI { 1416*d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[1], acb->bhandle[1], devicemap); 1417*d74001adSXin LI devicemap += 4; 1418*d74001adSXin LI } 1419*d74001adSXin LI break; 1420*d74001adSXin LI 1421*d74001adSXin LI case ACB_ADAPTER_TYPE_C: 1422*d74001adSXin LI devicemap = offsetof(struct HBC_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1423*d74001adSXin LI for (target= 0; target < 4; target++) 1424*d74001adSXin LI { 1425*d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1426*d74001adSXin LI devicemap += 4; 1427*d74001adSXin LI } 1428*d74001adSXin LI break; 1429*d74001adSXin LI } 1430*d74001adSXin LI if(acb->acb_flags & ACB_F_BUS_HANG_ON) 1431*d74001adSXin LI { 1432*d74001adSXin LI acb->acb_flags &= ~ACB_F_BUS_HANG_ON; 1433*d74001adSXin LI } 1434*d74001adSXin LI /* 1435*d74001adSXin LI ** adapter posted CONFIG message 1436*d74001adSXin LI ** copy the new map, note if there are differences with the current map 1437*d74001adSXin LI */ 1438*d74001adSXin LI pDevMap = (u_int8_t *)&deviceMapCurrent[0]; 1439*d74001adSXin LI for (target= 0; target < ARCMSR_MAX_TARGETID - 1; target++) 1440*d74001adSXin LI { 1441*d74001adSXin LI if (*pDevMap != acb->device_map[target]) 1442*d74001adSXin LI { 1443*d74001adSXin LI u_int8_t difference, bit_check; 1444*d74001adSXin LI 1445*d74001adSXin LI difference= *pDevMap ^ acb->device_map[target]; 1446*d74001adSXin LI for(lun=0; lun < ARCMSR_MAX_TARGETLUN; lun++) 1447*d74001adSXin LI { 1448*d74001adSXin LI bit_check=(1 << lun); /*check bit from 0....31*/ 1449*d74001adSXin LI if(difference & bit_check) 1450*d74001adSXin LI { 1451*d74001adSXin LI if(acb->device_map[target] & bit_check) 1452*d74001adSXin LI {/* unit departed */ 1453*d74001adSXin LI printf("arcmsr_dr_handle: Target=%x, lun=%x, GONE!!!\n",target,lun); 1454*d74001adSXin LI arcmsr_abort_dr_ccbs(acb, target, lun); 1455*d74001adSXin LI arcmsr_rescan_lun(acb, target, lun); 1456*d74001adSXin LI acb->devstate[target][lun] = ARECA_RAID_GONE; 1457*d74001adSXin LI } 1458*d74001adSXin LI else 1459*d74001adSXin LI {/* unit arrived */ 1460*d74001adSXin LI printf("arcmsr_dr_handle: Target=%x, lun=%x, ARRIVING!!!\n",target,lun); 1461*d74001adSXin LI arcmsr_rescan_lun(acb, target, lun); 1462*d74001adSXin LI acb->devstate[target][lun] = ARECA_RAID_GOOD; 1463*d74001adSXin LI } 1464*d74001adSXin LI } 1465*d74001adSXin LI } 1466*d74001adSXin LI /* printf("arcmsr_dr_handle: acb->device_map[%x]=0x%x, deviceMapCurrent[%x]=%x\n",target,acb->device_map[target],target,*pDevMap); */ 1467*d74001adSXin LI acb->device_map[target]= *pDevMap; 1468*d74001adSXin LI } 1469*d74001adSXin LI pDevMap++; 1470*d74001adSXin LI } 1471*d74001adSXin LI } 1472*d74001adSXin LI /* 1473*d74001adSXin LI ************************************************************************** 1474*d74001adSXin LI ************************************************************************** 1475*d74001adSXin LI */ 1476*d74001adSXin LI static void arcmsr_hba_message_isr(struct AdapterControlBlock *acb) { 1477*d74001adSXin LI u_int32_t outbound_message; 1478*d74001adSXin LI 1479*d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT); 1480*d74001adSXin LI outbound_message = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[0]); 1481*d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1482*d74001adSXin LI arcmsr_dr_handle( acb ); 1483*d74001adSXin LI } 1484*d74001adSXin LI /* 1485*d74001adSXin LI ************************************************************************** 1486*d74001adSXin LI ************************************************************************** 1487*d74001adSXin LI */ 1488*d74001adSXin LI static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) { 1489*d74001adSXin LI u_int32_t outbound_message; 1490*d74001adSXin LI 1491*d74001adSXin LI /* clear interrupts */ 1492*d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN); 1493*d74001adSXin LI outbound_message = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0]); 1494*d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1495*d74001adSXin LI arcmsr_dr_handle( acb ); 1496*d74001adSXin LI } 1497*d74001adSXin LI /* 1498*d74001adSXin LI ************************************************************************** 1499*d74001adSXin LI ************************************************************************** 1500*d74001adSXin LI */ 1501*d74001adSXin LI static void arcmsr_hbc_message_isr(struct AdapterControlBlock *acb) { 1502*d74001adSXin LI u_int32_t outbound_message; 1503*d74001adSXin LI 1504*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR); 1505*d74001adSXin LI outbound_message = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[0]); 1506*d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1507*d74001adSXin LI arcmsr_dr_handle( acb ); 1508*d74001adSXin LI } 150944f05562SScott Long /* 151044f05562SScott Long ************************************************************************** 151144f05562SScott Long ************************************************************************** 151244f05562SScott Long */ 151344f05562SScott Long static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) 151444f05562SScott Long { 151544f05562SScott Long u_int32_t outbound_doorbell; 151644f05562SScott Long 151744f05562SScott Long /* 151844f05562SScott Long ******************************************************************* 151944f05562SScott Long ** Maybe here we need to check wrqbuffer_lock is lock or not 152044f05562SScott Long ** DOORBELL: din! don! 152144f05562SScott Long ** check if there are any mail need to pack from firmware 152244f05562SScott Long ******************************************************************* 152344f05562SScott Long */ 152444f05562SScott Long outbound_doorbell=CHIP_REG_READ32(HBA_MessageUnit, 152544f05562SScott Long 0, outbound_doorbell); 152644f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 152744f05562SScott Long 0, outbound_doorbell, outbound_doorbell); /* clear doorbell interrupt */ 152844f05562SScott Long if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { 152944f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 1530ad6d6297SScott Long } 153144f05562SScott Long if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { 153244f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 153344f05562SScott Long } 153444f05562SScott Long return; 153544f05562SScott Long } 153644f05562SScott Long /* 153744f05562SScott Long ************************************************************************** 153844f05562SScott Long ************************************************************************** 153944f05562SScott Long */ 1540*d74001adSXin LI static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb) 1541*d74001adSXin LI { 1542*d74001adSXin LI u_int32_t outbound_doorbell; 1543*d74001adSXin LI 1544*d74001adSXin LI /* 1545*d74001adSXin LI ******************************************************************* 1546*d74001adSXin LI ** Maybe here we need to check wrqbuffer_lock is lock or not 1547*d74001adSXin LI ** DOORBELL: din! don! 1548*d74001adSXin LI ** check if there are any mail need to pack from firmware 1549*d74001adSXin LI ******************************************************************* 1550*d74001adSXin LI */ 1551*d74001adSXin LI outbound_doorbell=CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); 1552*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell); /* clear doorbell interrupt */ 1553*d74001adSXin LI if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) { 1554*d74001adSXin LI arcmsr_iop2drv_data_wrote_handle(acb); 1555*d74001adSXin LI } 1556*d74001adSXin LI if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) { 1557*d74001adSXin LI arcmsr_iop2drv_data_read_handle(acb); 1558*d74001adSXin LI } 1559*d74001adSXin LI if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { 1560*d74001adSXin LI arcmsr_hbc_message_isr(acb); /* messenger of "driver to iop commands" */ 1561*d74001adSXin LI } 1562*d74001adSXin LI return; 1563*d74001adSXin LI } 1564*d74001adSXin LI /* 1565*d74001adSXin LI ************************************************************************** 1566*d74001adSXin LI ************************************************************************** 1567*d74001adSXin LI */ 156844f05562SScott Long static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb) 156944f05562SScott Long { 157044f05562SScott Long u_int32_t flag_srb; 1571*d74001adSXin LI u_int16_t error; 157244f05562SScott Long 1573f1c579b1SScott Long /* 1574f1c579b1SScott Long ***************************************************************************** 1575f1c579b1SScott Long ** areca cdb command done 1576f1c579b1SScott Long ***************************************************************************** 1577f1c579b1SScott Long */ 157844f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 157944f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 158044f05562SScott Long while((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 158144f05562SScott Long 0, outbound_queueport)) != 0xFFFFFFFF) { 1582f1c579b1SScott Long /* check if command done with no error*/ 1583*d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 1584*d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 158544f05562SScott Long } /*drain reply FIFO*/ 158644f05562SScott Long return; 1587f1c579b1SScott Long } 158844f05562SScott Long /* 158944f05562SScott Long ************************************************************************** 159044f05562SScott Long ************************************************************************** 159144f05562SScott Long */ 159244f05562SScott Long static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) 159344f05562SScott Long { 159444f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 159544f05562SScott Long u_int32_t flag_srb; 159644f05562SScott Long int index; 1597*d74001adSXin LI u_int16_t error; 159844f05562SScott Long 159944f05562SScott Long /* 160044f05562SScott Long ***************************************************************************** 160144f05562SScott Long ** areca cdb command done 160244f05562SScott Long ***************************************************************************** 160344f05562SScott Long */ 160444f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 160544f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 160644f05562SScott Long index=phbbmu->doneq_index; 160744f05562SScott Long while((flag_srb=phbbmu->done_qbuffer[index]) != 0) { 160844f05562SScott Long phbbmu->done_qbuffer[index]=0; 160944f05562SScott Long index++; 161044f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 161144f05562SScott Long phbbmu->doneq_index=index; 161244f05562SScott Long /* check if command done with no error*/ 1613*d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 1614*d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 1615*d74001adSXin LI } /*drain reply FIFO*/ 1616*d74001adSXin LI return; 1617*d74001adSXin LI } 1618*d74001adSXin LI /* 1619*d74001adSXin LI ************************************************************************** 1620*d74001adSXin LI ************************************************************************** 1621*d74001adSXin LI */ 1622*d74001adSXin LI static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb) 1623*d74001adSXin LI { 1624*d74001adSXin LI u_int32_t flag_srb,throttling=0; 1625*d74001adSXin LI u_int16_t error; 1626*d74001adSXin LI 1627*d74001adSXin LI /* 1628*d74001adSXin LI ***************************************************************************** 1629*d74001adSXin LI ** areca cdb command done 1630*d74001adSXin LI ***************************************************************************** 1631*d74001adSXin LI */ 1632*d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 1633*d74001adSXin LI 1634*d74001adSXin LI while(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) { 1635*d74001adSXin LI 1636*d74001adSXin LI flag_srb=CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 1637*d74001adSXin LI /* check if command done with no error*/ 1638*d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; 1639*d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 1640*d74001adSXin LI if(throttling==ARCMSR_HBC_ISR_THROTTLING_LEVEL) { 1641*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING); 1642*d74001adSXin LI break; 1643*d74001adSXin LI } 1644*d74001adSXin LI throttling++; 164544f05562SScott Long } /*drain reply FIFO*/ 164644f05562SScott Long return; 1647f1c579b1SScott Long } 164844f05562SScott Long /* 164944f05562SScott Long ********************************************************************** 165044f05562SScott Long ********************************************************************** 165144f05562SScott Long */ 165244f05562SScott Long static void arcmsr_handle_hba_isr( struct AdapterControlBlock *acb) 165344f05562SScott Long { 165444f05562SScott Long u_int32_t outbound_intstatus; 165544f05562SScott Long /* 165644f05562SScott Long ********************************************* 165744f05562SScott Long ** check outbound intstatus 165844f05562SScott Long ********************************************* 165944f05562SScott Long */ 1660*d74001adSXin LI outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 166144f05562SScott Long if(!outbound_intstatus) { 166244f05562SScott Long /*it must be share irq*/ 166344f05562SScott Long return; 1664f1c579b1SScott Long } 1665*d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/ 166644f05562SScott Long /* MU doorbell interrupts*/ 166744f05562SScott Long if(outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) { 166844f05562SScott Long arcmsr_hba_doorbell_isr(acb); 1669f1c579b1SScott Long } 167044f05562SScott Long /* MU post queue interrupts*/ 167144f05562SScott Long if(outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { 167244f05562SScott Long arcmsr_hba_postqueue_isr(acb); 167344f05562SScott Long } 1674*d74001adSXin LI if(outbound_intstatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { 1675*d74001adSXin LI arcmsr_hba_message_isr(acb); 1676*d74001adSXin LI } 167744f05562SScott Long return; 167844f05562SScott Long } 167944f05562SScott Long /* 168044f05562SScott Long ********************************************************************** 168144f05562SScott Long ********************************************************************** 168244f05562SScott Long */ 168344f05562SScott Long static void arcmsr_handle_hbb_isr( struct AdapterControlBlock *acb) 168444f05562SScott Long { 168544f05562SScott Long u_int32_t outbound_doorbell; 168644f05562SScott Long /* 168744f05562SScott Long ********************************************* 168844f05562SScott Long ** check outbound intstatus 168944f05562SScott Long ********************************************* 169044f05562SScott Long */ 169144f05562SScott Long outbound_doorbell=CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & acb->outbound_int_enable; 169244f05562SScott Long if(!outbound_doorbell) { 169344f05562SScott Long /*it must be share irq*/ 169444f05562SScott Long return; 169544f05562SScott Long } 169644f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ~outbound_doorbell); /* clear doorbell interrupt */ 169744f05562SScott Long CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell); 169844f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 169944f05562SScott Long /* MU ioctl transfer doorbell interrupts*/ 170044f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { 170144f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 170244f05562SScott Long } 170344f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) { 170444f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 170544f05562SScott Long } 170644f05562SScott Long /* MU post queue interrupts*/ 170744f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) { 170844f05562SScott Long arcmsr_hbb_postqueue_isr(acb); 170944f05562SScott Long } 1710*d74001adSXin LI if(outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { 1711*d74001adSXin LI arcmsr_hbb_message_isr(acb); 1712*d74001adSXin LI } 1713*d74001adSXin LI return; 1714*d74001adSXin LI } 1715*d74001adSXin LI /* 1716*d74001adSXin LI ********************************************************************** 1717*d74001adSXin LI ********************************************************************** 1718*d74001adSXin LI */ 1719*d74001adSXin LI static void arcmsr_handle_hbc_isr( struct AdapterControlBlock *acb) 1720*d74001adSXin LI { 1721*d74001adSXin LI u_int32_t host_interrupt_status; 1722*d74001adSXin LI /* 1723*d74001adSXin LI ********************************************* 1724*d74001adSXin LI ** check outbound intstatus 1725*d74001adSXin LI ********************************************* 1726*d74001adSXin LI */ 1727*d74001adSXin LI host_interrupt_status=CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status); 1728*d74001adSXin LI if(!host_interrupt_status) { 1729*d74001adSXin LI /*it must be share irq*/ 1730*d74001adSXin LI return; 1731*d74001adSXin LI } 1732*d74001adSXin LI /* MU doorbell interrupts*/ 1733*d74001adSXin LI if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) { 1734*d74001adSXin LI arcmsr_hbc_doorbell_isr(acb); 1735*d74001adSXin LI } 1736*d74001adSXin LI /* MU post queue interrupts*/ 1737*d74001adSXin LI if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) { 1738*d74001adSXin LI arcmsr_hbc_postqueue_isr(acb); 1739*d74001adSXin LI } 174044f05562SScott Long return; 174144f05562SScott Long } 174244f05562SScott Long /* 174344f05562SScott Long ****************************************************************************** 174444f05562SScott Long ****************************************************************************** 174544f05562SScott Long */ 174644f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb) 174744f05562SScott Long { 174844f05562SScott Long switch (acb->adapter_type) { 174944f05562SScott Long case ACB_ADAPTER_TYPE_A: 175044f05562SScott Long arcmsr_handle_hba_isr(acb); 1751f1c579b1SScott Long break; 175244f05562SScott Long case ACB_ADAPTER_TYPE_B: 175344f05562SScott Long arcmsr_handle_hbb_isr(acb); 1754f1c579b1SScott Long break; 1755*d74001adSXin LI case ACB_ADAPTER_TYPE_C: 1756*d74001adSXin LI arcmsr_handle_hbc_isr(acb); 1757*d74001adSXin LI break; 1758f1c579b1SScott Long default: 175944f05562SScott Long printf("arcmsr%d: interrupt service," 176044f05562SScott Long " unknow adapter type =%d\n", acb->pci_unit, acb->adapter_type); 1761f1c579b1SScott Long break; 1762f1c579b1SScott Long } 1763f1c579b1SScott Long return; 1764f1c579b1SScott Long } 1765f1c579b1SScott Long /* 1766*d74001adSXin LI ********************************************************************** 1767*d74001adSXin LI ********************************************************************** 1768*d74001adSXin LI */ 1769*d74001adSXin LI static void arcmsr_intr_handler(void *arg) 1770*d74001adSXin LI { 1771*d74001adSXin LI struct AdapterControlBlock *acb=(struct AdapterControlBlock *)arg; 1772*d74001adSXin LI 1773*d74001adSXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 1774*d74001adSXin LI arcmsr_interrupt(acb); 1775*d74001adSXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1776*d74001adSXin LI } 1777*d74001adSXin LI /* 1778*d74001adSXin LI ****************************************************************************** 1779*d74001adSXin LI ****************************************************************************** 1780*d74001adSXin LI */ 1781*d74001adSXin LI static void arcmsr_polling_devmap(void* arg) 1782*d74001adSXin LI { 1783*d74001adSXin LI struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg; 1784*d74001adSXin LI switch (acb->adapter_type) { 1785*d74001adSXin LI case ACB_ADAPTER_TYPE_A: 1786*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 1787*d74001adSXin LI break; 1788*d74001adSXin LI 1789*d74001adSXin LI case ACB_ADAPTER_TYPE_B: 1790*d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG); 1791*d74001adSXin LI break; 1792*d74001adSXin LI 1793*d74001adSXin LI case ACB_ADAPTER_TYPE_C: 1794*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 1795*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 1796*d74001adSXin LI break; 1797*d74001adSXin LI } 1798*d74001adSXin LI 1799*d74001adSXin LI if((acb->acb_flags & ACB_F_SCSISTOPADAPTER) == 0) 1800*d74001adSXin LI { 1801*d74001adSXin LI callout_reset(&acb->devmap_callout, 5 * hz, arcmsr_polling_devmap, acb); /* polling per 5 seconds */ 1802*d74001adSXin LI } 1803*d74001adSXin LI } 1804*d74001adSXin LI 1805*d74001adSXin LI /* 1806ad6d6297SScott Long ******************************************************************************* 1807ad6d6297SScott Long ** 1808ad6d6297SScott Long ******************************************************************************* 1809ad6d6297SScott Long */ 1810ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb) 1811ad6d6297SScott Long { 1812*d74001adSXin LI u_int32_t intmask_org; 1813*d74001adSXin LI 1814ad6d6297SScott Long if(acb!=NULL) { 1815ad6d6297SScott Long /* stop adapter background rebuild */ 1816ad6d6297SScott Long if(acb->acb_flags & ACB_F_MSG_START_BGRB) { 1817*d74001adSXin LI intmask_org = arcmsr_disable_allintr(acb); 1818ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 1819ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 1820*d74001adSXin LI arcmsr_enable_allintr(acb, intmask_org); 1821ad6d6297SScott Long } 1822ad6d6297SScott Long } 1823ad6d6297SScott Long } 1824ad6d6297SScott Long /* 1825f1c579b1SScott Long *********************************************************************** 1826f1c579b1SScott Long ** 1827f1c579b1SScott Long ************************************************************************ 1828f1c579b1SScott Long */ 1829ad6d6297SScott Long u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg) 1830f1c579b1SScott Long { 1831ad6d6297SScott Long struct CMD_MESSAGE_FIELD * pcmdmessagefld; 1832ad6d6297SScott Long u_int32_t retvalue=EINVAL; 1833f1c579b1SScott Long 1834ad6d6297SScott Long pcmdmessagefld=(struct CMD_MESSAGE_FIELD *) arg; 1835ad6d6297SScott Long if(memcmp(pcmdmessagefld->cmdmessage.Signature, "ARCMSR", 6)!=0) { 1836ad6d6297SScott Long return retvalue; 1837f1c579b1SScott Long } 1838ad6d6297SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 1839ad6d6297SScott Long switch(ioctl_cmd) { 1840ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 1841ad6d6297SScott Long u_int8_t * pQbuffer; 1842ad6d6297SScott Long u_int8_t * ptmpQbuffer=pcmdmessagefld->messagedatabuffer; 1843ad6d6297SScott Long u_int32_t allxfer_len=0; 1844f1c579b1SScott Long 184544f05562SScott Long while((acb->rqbuf_firstindex!=acb->rqbuf_lastindex) 184644f05562SScott Long && (allxfer_len<1031)) { 1847f1c579b1SScott Long /*copy READ QBUFFER to srb*/ 1848ad6d6297SScott Long pQbuffer= &acb->rqbuffer[acb->rqbuf_firstindex]; 1849f1c579b1SScott Long memcpy(ptmpQbuffer, pQbuffer, 1); 1850ad6d6297SScott Long acb->rqbuf_firstindex++; 1851ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 1852ad6d6297SScott Long /*if last index number set it to 0 */ 1853f1c579b1SScott Long ptmpQbuffer++; 1854f1c579b1SScott Long allxfer_len++; 1855f1c579b1SScott Long } 1856ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 185744f05562SScott Long struct QBUFFER * prbuffer; 185844f05562SScott Long u_int8_t * iop_data; 1859ad6d6297SScott Long u_int32_t iop_len; 1860f1c579b1SScott Long 1861ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 186244f05562SScott Long prbuffer=arcmsr_get_iop_rqbuffer(acb); 186344f05562SScott Long iop_data=(u_int8_t *)prbuffer->data; 1864ad6d6297SScott Long iop_len=(u_int32_t)prbuffer->data_len; 1865f1c579b1SScott Long /*this iop data does no chance to make me overflow again here, so just do it*/ 1866ad6d6297SScott Long while(iop_len>0) { 1867ad6d6297SScott Long pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex]; 1868f1c579b1SScott Long memcpy(pQbuffer, iop_data, 1); 1869ad6d6297SScott Long acb->rqbuf_lastindex++; 1870ad6d6297SScott Long acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 1871ad6d6297SScott Long /*if last index number set it to 0 */ 1872f1c579b1SScott Long iop_data++; 1873f1c579b1SScott Long iop_len--; 1874f1c579b1SScott Long } 187544f05562SScott Long arcmsr_iop_message_read(acb); 187644f05562SScott Long /*signature, let IOP know data has been readed */ 1877f1c579b1SScott Long } 1878ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length=allxfer_len; 1879ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1880ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1881f1c579b1SScott Long } 1882f1c579b1SScott Long break; 1883ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 1884ad6d6297SScott Long u_int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 1885ad6d6297SScott Long u_int8_t * pQbuffer; 1886ad6d6297SScott Long u_int8_t * ptmpuserbuffer=pcmdmessagefld->messagedatabuffer; 1887f1c579b1SScott Long 1888ad6d6297SScott Long user_len=pcmdmessagefld->cmdmessage.Length; 1889f1c579b1SScott Long /*check if data xfer length of this request will overflow my array qbuffer */ 1890ad6d6297SScott Long wqbuf_lastindex=acb->wqbuf_lastindex; 1891ad6d6297SScott Long wqbuf_firstindex=acb->wqbuf_firstindex; 1892ad6d6297SScott Long if(wqbuf_lastindex!=wqbuf_firstindex) { 189344f05562SScott Long arcmsr_post_ioctldata2iop(acb); 1894ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; 1895ad6d6297SScott Long } else { 1896f1c579b1SScott Long my_empty_len=(wqbuf_firstindex-wqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1); 1897ad6d6297SScott Long if(my_empty_len>=user_len) { 1898ad6d6297SScott Long while(user_len>0) { 1899f1c579b1SScott Long /*copy srb data to wqbuffer*/ 1900ad6d6297SScott Long pQbuffer= &acb->wqbuffer[acb->wqbuf_lastindex]; 1901f1c579b1SScott Long memcpy(pQbuffer, ptmpuserbuffer, 1); 1902ad6d6297SScott Long acb->wqbuf_lastindex++; 1903ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 1904ad6d6297SScott Long /*if last index number set it to 0 */ 1905f1c579b1SScott Long ptmpuserbuffer++; 1906f1c579b1SScott Long user_len--; 1907f1c579b1SScott Long } 1908f1c579b1SScott Long /*post fist Qbuffer*/ 1909ad6d6297SScott Long if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 1910ad6d6297SScott Long acb->acb_flags &=~ACB_F_MESSAGE_WQBUFFER_CLEARED; 191144f05562SScott Long arcmsr_post_ioctldata2iop(acb); 1912f1c579b1SScott Long } 1913ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1914ad6d6297SScott Long } else { 1915ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; 1916f1c579b1SScott Long } 1917f1c579b1SScott Long } 1918ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1919f1c579b1SScott Long } 1920f1c579b1SScott Long break; 1921ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 1922ad6d6297SScott Long u_int8_t * pQbuffer=acb->rqbuffer; 1923ad6d6297SScott Long 1924ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1925ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 192644f05562SScott Long arcmsr_iop_message_read(acb); 192744f05562SScott Long /*signature, let IOP know data has been readed */ 1928f1c579b1SScott Long } 1929ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 1930ad6d6297SScott Long acb->rqbuf_firstindex=0; 1931ad6d6297SScott Long acb->rqbuf_lastindex=0; 1932f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 1933ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1934ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1935f1c579b1SScott Long } 1936f1c579b1SScott Long break; 1937ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: 1938f1c579b1SScott Long { 1939ad6d6297SScott Long u_int8_t * pQbuffer=acb->wqbuffer; 1940f1c579b1SScott Long 1941ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1942ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 194344f05562SScott Long arcmsr_iop_message_read(acb); 194444f05562SScott Long /*signature, let IOP know data has been readed */ 1945f1c579b1SScott Long } 194644f05562SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ); 1947ad6d6297SScott Long acb->wqbuf_firstindex=0; 1948ad6d6297SScott Long acb->wqbuf_lastindex=0; 1949f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 1950ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1951ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1952f1c579b1SScott Long } 1953f1c579b1SScott Long break; 1954ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 1955ad6d6297SScott Long u_int8_t * pQbuffer; 1956f1c579b1SScott Long 1957ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1958ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 195944f05562SScott Long arcmsr_iop_message_read(acb); 196044f05562SScott Long /*signature, let IOP know data has been readed */ 1961f1c579b1SScott Long } 1962ad6d6297SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED 1963ad6d6297SScott Long |ACB_F_MESSAGE_RQBUFFER_CLEARED 196444f05562SScott Long |ACB_F_MESSAGE_WQBUFFER_READ); 1965ad6d6297SScott Long acb->rqbuf_firstindex=0; 1966ad6d6297SScott Long acb->rqbuf_lastindex=0; 1967ad6d6297SScott Long acb->wqbuf_firstindex=0; 1968ad6d6297SScott Long acb->wqbuf_lastindex=0; 1969ad6d6297SScott Long pQbuffer=acb->rqbuffer; 1970ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 1971ad6d6297SScott Long pQbuffer=acb->wqbuffer; 1972ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 1973ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1974ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1975f1c579b1SScott Long } 1976f1c579b1SScott Long break; 1977ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 1978ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_3F; 1979ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1980f1c579b1SScott Long } 1981f1c579b1SScott Long break; 1982ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 1983ad6d6297SScott Long u_int8_t * hello_string="Hello! I am ARCMSR"; 1984ad6d6297SScott Long u_int8_t * puserbuffer=(u_int8_t *)pcmdmessagefld->messagedatabuffer; 1985f1c579b1SScott Long 1986ad6d6297SScott Long if(memcpy(puserbuffer, hello_string, (int16_t)strlen(hello_string))) { 1987ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; 1988ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1989f1c579b1SScott Long return ENOIOCTL; 1990f1c579b1SScott Long } 1991ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1992ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1993ad6d6297SScott Long } 1994ad6d6297SScott Long break; 1995ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: { 1996ad6d6297SScott Long arcmsr_iop_parking(acb); 1997ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1998ad6d6297SScott Long } 1999ad6d6297SScott Long break; 2000ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: { 2001ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2002ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 2003f1c579b1SScott Long } 2004f1c579b1SScott Long break; 2005f1c579b1SScott Long } 2006ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2007ad6d6297SScott Long return retvalue; 2008f1c579b1SScott Long } 2009f1c579b1SScott Long /* 2010f1c579b1SScott Long ************************************************************************** 2011f1c579b1SScott Long ************************************************************************** 2012f1c579b1SScott Long */ 2013ad6d6297SScott Long struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb) 2014f1c579b1SScott Long { 2015ad6d6297SScott Long struct CommandControlBlock *srb=NULL; 2016ad6d6297SScott Long u_int32_t workingsrb_startindex, workingsrb_doneindex; 2017f1c579b1SScott Long 2018579ec1a5SScott Long #if __FreeBSD_version < 700025 2019579ec1a5SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2020579ec1a5SScott Long #endif 2021ad6d6297SScott Long workingsrb_doneindex=acb->workingsrb_doneindex; 2022ad6d6297SScott Long workingsrb_startindex=acb->workingsrb_startindex; 2023ad6d6297SScott Long srb=acb->srbworkingQ[workingsrb_startindex]; 2024ad6d6297SScott Long workingsrb_startindex++; 2025ad6d6297SScott Long workingsrb_startindex %= ARCMSR_MAX_FREESRB_NUM; 2026ad6d6297SScott Long if(workingsrb_doneindex!=workingsrb_startindex) { 2027ad6d6297SScott Long acb->workingsrb_startindex=workingsrb_startindex; 2028ad6d6297SScott Long } else { 2029ad6d6297SScott Long srb=NULL; 2030ad6d6297SScott Long } 2031579ec1a5SScott Long #if __FreeBSD_version < 700025 2032579ec1a5SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2033579ec1a5SScott Long #endif 2034ad6d6297SScott Long return(srb); 2035ad6d6297SScott Long } 2036ad6d6297SScott Long /* 2037ad6d6297SScott Long ************************************************************************** 2038ad6d6297SScott Long ************************************************************************** 2039ad6d6297SScott Long */ 2040ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb) 2041ad6d6297SScott Long { 2042ad6d6297SScott Long struct CMD_MESSAGE_FIELD * pcmdmessagefld; 2043ad6d6297SScott Long int retvalue = 0, transfer_len = 0; 2044ad6d6297SScott Long char *buffer; 204544f05562SScott Long u_int32_t controlcode = (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[5] << 24 | 204644f05562SScott Long (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[6] << 16 | 204744f05562SScott Long (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[7] << 8 | 204844f05562SScott Long (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[8]; 2049ad6d6297SScott Long /* 4 bytes: Areca io control code */ 2050ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) { 2051ad6d6297SScott Long buffer = pccb->csio.data_ptr; 2052ad6d6297SScott Long transfer_len = pccb->csio.dxfer_len; 2053ad6d6297SScott Long } else { 2054ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2055ad6d6297SScott Long goto message_out; 2056ad6d6297SScott Long } 2057ad6d6297SScott Long if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) { 2058ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2059ad6d6297SScott Long goto message_out; 2060ad6d6297SScott Long } 2061ad6d6297SScott Long pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer; 2062ad6d6297SScott Long switch(controlcode) { 2063ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 2064ad6d6297SScott Long u_int8_t *pQbuffer; 2065ad6d6297SScott Long u_int8_t *ptmpQbuffer=pcmdmessagefld->messagedatabuffer; 2066ad6d6297SScott Long int32_t allxfer_len = 0; 2067f1c579b1SScott Long 2068ad6d6297SScott Long while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) 2069ad6d6297SScott Long && (allxfer_len < 1031)) { 2070ad6d6297SScott Long pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; 2071ad6d6297SScott Long memcpy(ptmpQbuffer, pQbuffer, 1); 2072ad6d6297SScott Long acb->rqbuf_firstindex++; 2073ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 2074ad6d6297SScott Long ptmpQbuffer++; 2075ad6d6297SScott Long allxfer_len++; 2076f1c579b1SScott Long } 2077ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 207844f05562SScott Long struct QBUFFER *prbuffer; 207944f05562SScott Long u_int8_t *iop_data; 2080ad6d6297SScott Long int32_t iop_len; 2081ad6d6297SScott Long 2082ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 208344f05562SScott Long prbuffer=arcmsr_get_iop_rqbuffer(acb); 208444f05562SScott Long iop_data = (u_int8_t *)prbuffer->data; 2085ad6d6297SScott Long iop_len =(u_int32_t)prbuffer->data_len; 2086ad6d6297SScott Long while (iop_len > 0) { 2087ad6d6297SScott Long pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex]; 2088ad6d6297SScott Long memcpy(pQbuffer, iop_data, 1); 2089ad6d6297SScott Long acb->rqbuf_lastindex++; 2090ad6d6297SScott Long acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 2091ad6d6297SScott Long iop_data++; 2092ad6d6297SScott Long iop_len--; 2093f1c579b1SScott Long } 209444f05562SScott Long arcmsr_iop_message_read(acb); 2095ad6d6297SScott Long } 2096ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length = allxfer_len; 2097ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2098ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 2099ad6d6297SScott Long } 2100ad6d6297SScott Long break; 2101ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 2102ad6d6297SScott Long int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 2103ad6d6297SScott Long u_int8_t *pQbuffer; 2104ad6d6297SScott Long u_int8_t *ptmpuserbuffer=pcmdmessagefld->messagedatabuffer; 2105ad6d6297SScott Long 2106ad6d6297SScott Long user_len = pcmdmessagefld->cmdmessage.Length; 2107ad6d6297SScott Long wqbuf_lastindex = acb->wqbuf_lastindex; 2108ad6d6297SScott Long wqbuf_firstindex = acb->wqbuf_firstindex; 2109ad6d6297SScott Long if (wqbuf_lastindex != wqbuf_firstindex) { 211044f05562SScott Long arcmsr_post_ioctldata2iop(acb); 2111ad6d6297SScott Long /* has error report sensedata */ 2112ad6d6297SScott Long if(&pccb->csio.sense_data) { 2113ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 2114ad6d6297SScott Long /* Valid,ErrorCode */ 2115ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 2116ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 2117ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 2118ad6d6297SScott Long /* AdditionalSenseLength */ 2119ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 2120ad6d6297SScott Long /* AdditionalSenseCode */ 2121ad6d6297SScott Long } 2122ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2123ad6d6297SScott Long } else { 2124ad6d6297SScott Long my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) 2125ad6d6297SScott Long &(ARCMSR_MAX_QBUFFER - 1); 2126ad6d6297SScott Long if (my_empty_len >= user_len) { 2127ad6d6297SScott Long while (user_len > 0) { 2128ad6d6297SScott Long pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; 2129ad6d6297SScott Long memcpy(pQbuffer, ptmpuserbuffer, 1); 2130ad6d6297SScott Long acb->wqbuf_lastindex++; 2131ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 2132ad6d6297SScott Long ptmpuserbuffer++; 2133ad6d6297SScott Long user_len--; 2134ad6d6297SScott Long } 2135ad6d6297SScott Long if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 2136ad6d6297SScott Long acb->acb_flags &= 2137ad6d6297SScott Long ~ACB_F_MESSAGE_WQBUFFER_CLEARED; 213844f05562SScott Long arcmsr_post_ioctldata2iop(acb); 2139ad6d6297SScott Long } 2140ad6d6297SScott Long } else { 2141ad6d6297SScott Long /* has error report sensedata */ 2142ad6d6297SScott Long if(&pccb->csio.sense_data) { 2143ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 2144ad6d6297SScott Long /* Valid,ErrorCode */ 2145ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 2146ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 2147ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 2148ad6d6297SScott Long /* AdditionalSenseLength */ 2149ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 2150ad6d6297SScott Long /* AdditionalSenseCode */ 2151ad6d6297SScott Long } 2152ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2153ad6d6297SScott Long } 2154ad6d6297SScott Long } 2155ad6d6297SScott Long } 2156ad6d6297SScott Long break; 2157ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 2158ad6d6297SScott Long u_int8_t *pQbuffer = acb->rqbuffer; 2159ad6d6297SScott Long 2160ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2161ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 216244f05562SScott Long arcmsr_iop_message_read(acb); 2163ad6d6297SScott Long } 2164ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 2165ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2166ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2167ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2168ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 2169ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 2170ad6d6297SScott Long } 2171ad6d6297SScott Long break; 2172ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { 2173ad6d6297SScott Long u_int8_t *pQbuffer = acb->wqbuffer; 2174ad6d6297SScott Long 2175ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2176ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 217744f05562SScott Long arcmsr_iop_message_read(acb); 2178ad6d6297SScott Long } 2179ad6d6297SScott Long acb->acb_flags |= 2180ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED | 218144f05562SScott Long ACB_F_MESSAGE_WQBUFFER_READ); 2182ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2183ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2184ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2185ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 2186ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 2187ad6d6297SScott Long } 2188ad6d6297SScott Long break; 2189ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 2190ad6d6297SScott Long u_int8_t *pQbuffer; 2191ad6d6297SScott Long 2192ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2193ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 219444f05562SScott Long arcmsr_iop_message_read(acb); 2195ad6d6297SScott Long } 2196ad6d6297SScott Long acb->acb_flags |= 2197ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED 2198ad6d6297SScott Long | ACB_F_MESSAGE_RQBUFFER_CLEARED 219944f05562SScott Long | ACB_F_MESSAGE_WQBUFFER_READ); 2200ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2201ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2202ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2203ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2204ad6d6297SScott Long pQbuffer = acb->rqbuffer; 2205ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 2206ad6d6297SScott Long pQbuffer = acb->wqbuffer; 2207ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 2208ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2209ad6d6297SScott Long } 2210ad6d6297SScott Long break; 2211ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 2212ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; 2213ad6d6297SScott Long } 2214ad6d6297SScott Long break; 2215ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 2216ad6d6297SScott Long int8_t * hello_string = "Hello! I am ARCMSR"; 2217ad6d6297SScott Long 2218ad6d6297SScott Long memcpy(pcmdmessagefld->messagedatabuffer, hello_string 2219ad6d6297SScott Long , (int16_t)strlen(hello_string)); 2220ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2221ad6d6297SScott Long } 2222ad6d6297SScott Long break; 2223ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: 2224ad6d6297SScott Long arcmsr_iop_parking(acb); 2225ad6d6297SScott Long break; 2226ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: 2227ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2228ad6d6297SScott Long break; 2229ad6d6297SScott Long default: 2230ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2231ad6d6297SScott Long } 2232ad6d6297SScott Long message_out: 2233ad6d6297SScott Long return retvalue; 2234f1c579b1SScott Long } 2235f1c579b1SScott Long /* 2236f1c579b1SScott Long ********************************************************************* 2237f1c579b1SScott Long ********************************************************************* 2238f1c579b1SScott Long */ 2239ad6d6297SScott Long static void arcmsr_executesrb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 2240f1c579b1SScott Long { 2241ad6d6297SScott Long struct CommandControlBlock *srb=(struct CommandControlBlock *)arg; 2242ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)srb->acb; 2243f1c579b1SScott Long union ccb * pccb; 2244ad6d6297SScott Long int target, lun; 2245f1c579b1SScott Long 2246ad6d6297SScott Long pccb=srb->pccb; 2247ad6d6297SScott Long target=pccb->ccb_h.target_id; 2248ad6d6297SScott Long lun=pccb->ccb_h.target_lun; 2249ad6d6297SScott Long if(error != 0) { 2250ad6d6297SScott Long if(error != EFBIG) { 225144f05562SScott Long printf("arcmsr%d: unexpected error %x" 225244f05562SScott Long " returned from 'bus_dmamap_load' \n" 2253ad6d6297SScott Long , acb->pci_unit, error); 2254f1c579b1SScott Long } 2255ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { 225615735becSScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 2257f1c579b1SScott Long } 2258ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2259f1c579b1SScott Long return; 2260f1c579b1SScott Long } 2261ad6d6297SScott Long if(nseg > ARCMSR_MAX_SG_ENTRIES) { 2262ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 2263ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2264ad6d6297SScott Long return; 2265f1c579b1SScott Long } 2266ad6d6297SScott Long if(acb->acb_flags & ACB_F_BUS_RESET) { 2267ad6d6297SScott Long printf("arcmsr%d: bus reset and return busy \n", acb->pci_unit); 2268ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_BUS_RESET; 2269ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2270ad6d6297SScott Long return; 2271ad6d6297SScott Long } 2272ad6d6297SScott Long if(acb->devstate[target][lun]==ARECA_RAID_GONE) { 2273ad6d6297SScott Long u_int8_t block_cmd; 2274ad6d6297SScott Long 2275ad6d6297SScott Long block_cmd=pccb->csio.cdb_io.cdb_bytes[0] & 0x0f; 2276ad6d6297SScott Long if(block_cmd==0x08 || block_cmd==0x0a) { 2277ad6d6297SScott Long printf("arcmsr%d:block 'read/write' command " 2278ad6d6297SScott Long "with gone raid volume Cmd=%2x, TargetId=%d, Lun=%d \n" 2279ad6d6297SScott Long , acb->pci_unit, block_cmd, target, lun); 2280ad6d6297SScott Long pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 2281ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2282ad6d6297SScott Long return; 2283ad6d6297SScott Long } 2284ad6d6297SScott Long } 2285ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { 2286ad6d6297SScott Long if(nseg != 0) { 2287ad6d6297SScott Long bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 2288ad6d6297SScott Long } 2289ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2290f1c579b1SScott Long return; 2291f1c579b1SScott Long } 2292ad6d6297SScott Long if(acb->srboutstandingcount >= ARCMSR_MAX_OUTSTANDING_CMD) { 229315735becSScott Long xpt_freeze_simq(acb->psim, 1); 229415735becSScott Long pccb->ccb_h.status = CAM_REQUEUE_REQ; 2295dc3a205bSScott Long acb->acb_flags |= ACB_F_CAM_DEV_QFRZN; 2296ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2297ad6d6297SScott Long return; 2298f1c579b1SScott Long } 229915735becSScott Long pccb->ccb_h.status |= CAM_SIM_QUEUED; 2300ad6d6297SScott Long arcmsr_build_srb(srb, dm_segs, nseg); 2301*d74001adSXin LI /* if (pccb->ccb_h.timeout != CAM_TIME_INFINITY) 2302*d74001adSXin LI callout_reset(&srb->ccb_callout, (pccb->ccb_h.timeout * hz) / 1000, arcmsr_srb_timeout, srb); 2303*d74001adSXin LI */ 2304ad6d6297SScott Long arcmsr_post_srb(acb, srb); 2305f1c579b1SScott Long return; 2306f1c579b1SScott Long } 2307f1c579b1SScott Long /* 2308f1c579b1SScott Long ***************************************************************************************** 2309f1c579b1SScott Long ***************************************************************************************** 2310f1c579b1SScott Long */ 2311ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb) 2312f1c579b1SScott Long { 2313ad6d6297SScott Long struct CommandControlBlock *srb; 2314ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *) abortccb->ccb_h.arcmsr_ccbacb_ptr; 231544f05562SScott Long u_int32_t intmask_org; 2316ad6d6297SScott Long int i=0; 2317f1c579b1SScott Long 2318ad6d6297SScott Long acb->num_aborts++; 2319f1c579b1SScott Long /* 2320ad6d6297SScott Long *************************************************************************** 2321f1c579b1SScott Long ** It is the upper layer do abort command this lock just prior to calling us. 2322f1c579b1SScott Long ** First determine if we currently own this command. 2323f1c579b1SScott Long ** Start by searching the device queue. If not found 2324f1c579b1SScott Long ** at all, and the system wanted us to just abort the 2325f1c579b1SScott Long ** command return success. 2326ad6d6297SScott Long *************************************************************************** 2327f1c579b1SScott Long */ 2328ad6d6297SScott Long if(acb->srboutstandingcount!=0) { 2329ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 2330ad6d6297SScott Long srb=acb->psrb_pool[i]; 2331ad6d6297SScott Long if(srb->startdone==ARCMSR_SRB_START) { 2332ad6d6297SScott Long if(srb->pccb==abortccb) { 2333ad6d6297SScott Long srb->startdone=ARCMSR_SRB_ABORTED; 2334ad6d6297SScott Long printf("arcmsr%d:scsi id=%d lun=%d abort srb '%p'" 2335ad6d6297SScott Long "outstanding command \n" 2336ad6d6297SScott Long , acb->pci_unit, abortccb->ccb_h.target_id 2337ad6d6297SScott Long , abortccb->ccb_h.target_lun, srb); 2338ad6d6297SScott Long goto abort_outstanding_cmd; 2339f1c579b1SScott Long } 2340f1c579b1SScott Long } 2341f1c579b1SScott Long } 2342f1c579b1SScott Long } 2343f1c579b1SScott Long return(FALSE); 2344ad6d6297SScott Long abort_outstanding_cmd: 2345ad6d6297SScott Long /* disable all outbound interrupt */ 234644f05562SScott Long intmask_org=arcmsr_disable_allintr(acb); 2347ad6d6297SScott Long arcmsr_polling_srbdone(acb, srb); 234844f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 234944f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 2350ad6d6297SScott Long return (TRUE); 2351f1c579b1SScott Long } 2352f1c579b1SScott Long /* 2353f1c579b1SScott Long **************************************************************************** 2354f1c579b1SScott Long **************************************************************************** 2355f1c579b1SScott Long */ 2356ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb) 2357f1c579b1SScott Long { 2358ad6d6297SScott Long int retry=0; 2359f1c579b1SScott Long 2360ad6d6297SScott Long acb->num_resets++; 2361ad6d6297SScott Long acb->acb_flags |=ACB_F_BUS_RESET; 2362ad6d6297SScott Long while(acb->srboutstandingcount!=0 && retry < 400) { 236344f05562SScott Long arcmsr_interrupt(acb); 2364ad6d6297SScott Long UDELAY(25000); 2365ad6d6297SScott Long retry++; 2366ad6d6297SScott Long } 2367ad6d6297SScott Long arcmsr_iop_reset(acb); 2368ad6d6297SScott Long acb->acb_flags &= ~ACB_F_BUS_RESET; 2369f1c579b1SScott Long return; 2370f1c579b1SScott Long } 2371f1c579b1SScott Long /* 2372ad6d6297SScott Long ************************************************************************** 2373ad6d6297SScott Long ************************************************************************** 2374ad6d6297SScott Long */ 2375ad6d6297SScott Long static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, 2376ad6d6297SScott Long union ccb * pccb) 2377ad6d6297SScott Long { 2378ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2379ad6d6297SScott Long switch (pccb->csio.cdb_io.cdb_bytes[0]) { 2380ad6d6297SScott Long case INQUIRY: { 2381ad6d6297SScott Long unsigned char inqdata[36]; 2382c2ede4b3SMartin Blapp char *buffer=pccb->csio.data_ptr; 2383ad6d6297SScott Long 2384ad6d6297SScott Long if (pccb->ccb_h.target_lun) { 2385ad6d6297SScott Long pccb->ccb_h.status |= CAM_SEL_TIMEOUT; 2386ad6d6297SScott Long xpt_done(pccb); 2387ad6d6297SScott Long return; 2388ad6d6297SScott Long } 2389ad6d6297SScott Long inqdata[0] = T_PROCESSOR; 2390ad6d6297SScott Long /* Periph Qualifier & Periph Dev Type */ 2391ad6d6297SScott Long inqdata[1] = 0; 2392ad6d6297SScott Long /* rem media bit & Dev Type Modifier */ 2393ad6d6297SScott Long inqdata[2] = 0; 2394ad6d6297SScott Long /* ISO, ECMA, & ANSI versions */ 2395ad6d6297SScott Long inqdata[4] = 31; 2396ad6d6297SScott Long /* length of additional data */ 2397ad6d6297SScott Long strncpy(&inqdata[8], "Areca ", 8); 2398ad6d6297SScott Long /* Vendor Identification */ 2399ad6d6297SScott Long strncpy(&inqdata[16], "RAID controller ", 16); 2400ad6d6297SScott Long /* Product Identification */ 2401ad6d6297SScott Long strncpy(&inqdata[32], "R001", 4); /* Product Revision */ 2402ad6d6297SScott Long memcpy(buffer, inqdata, sizeof(inqdata)); 2403ad6d6297SScott Long xpt_done(pccb); 2404ad6d6297SScott Long } 2405ad6d6297SScott Long break; 2406ad6d6297SScott Long case WRITE_BUFFER: 2407ad6d6297SScott Long case READ_BUFFER: { 2408ad6d6297SScott Long if (arcmsr_iop_message_xfer(acb, pccb)) { 2409ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 2410ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 2411ad6d6297SScott Long } 2412ad6d6297SScott Long xpt_done(pccb); 2413ad6d6297SScott Long } 2414ad6d6297SScott Long break; 2415ad6d6297SScott Long default: 2416ad6d6297SScott Long xpt_done(pccb); 2417ad6d6297SScott Long } 2418ad6d6297SScott Long } 2419ad6d6297SScott Long /* 2420f1c579b1SScott Long ********************************************************************* 2421f1c579b1SScott Long ********************************************************************* 2422f1c579b1SScott Long */ 2423ad6d6297SScott Long static void arcmsr_action(struct cam_sim * psim, union ccb * pccb) 2424f1c579b1SScott Long { 2425ad6d6297SScott Long struct AdapterControlBlock * acb; 2426f1c579b1SScott Long 2427ad6d6297SScott Long acb=(struct AdapterControlBlock *) cam_sim_softc(psim); 2428ad6d6297SScott Long if(acb==NULL) { 2429ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2430f1c579b1SScott Long xpt_done(pccb); 2431f1c579b1SScott Long return; 2432f1c579b1SScott Long } 2433ad6d6297SScott Long switch (pccb->ccb_h.func_code) { 2434ad6d6297SScott Long case XPT_SCSI_IO: { 2435ad6d6297SScott Long struct CommandControlBlock *srb; 2436ad6d6297SScott Long int target=pccb->ccb_h.target_id; 2437f1c579b1SScott Long 2438ad6d6297SScott Long if(target == 16) { 2439ad6d6297SScott Long /* virtual device for iop message transfer */ 2440ad6d6297SScott Long arcmsr_handle_virtual_command(acb, pccb); 2441ad6d6297SScott Long return; 2442ad6d6297SScott Long } 2443ad6d6297SScott Long if((srb=arcmsr_get_freesrb(acb)) == NULL) { 2444ad6d6297SScott Long pccb->ccb_h.status |= CAM_RESRC_UNAVAIL; 2445f1c579b1SScott Long xpt_done(pccb); 2446f1c579b1SScott Long return; 2447f1c579b1SScott Long } 2448ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbsrb_ptr=srb; 2449ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbacb_ptr=acb; 2450ad6d6297SScott Long srb->pccb=pccb; 2451ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 2452ad6d6297SScott Long if(!(pccb->ccb_h.flags & CAM_SCATTER_VALID)) { 2453ad6d6297SScott Long /* Single buffer */ 2454ad6d6297SScott Long if(!(pccb->ccb_h.flags & CAM_DATA_PHYS)) { 2455ad6d6297SScott Long /* Buffer is virtual */ 2456ad6d6297SScott Long u_int32_t error, s; 2457f1c579b1SScott Long 2458f1c579b1SScott Long s=splsoftvm(); 2459ad6d6297SScott Long error = bus_dmamap_load(acb->dm_segs_dmat 2460ad6d6297SScott Long , srb->dm_segs_dmamap 2461ad6d6297SScott Long , pccb->csio.data_ptr 2462ad6d6297SScott Long , pccb->csio.dxfer_len 2463ad6d6297SScott Long , arcmsr_executesrb, srb, /*flags*/0); 2464ad6d6297SScott Long if(error == EINPROGRESS) { 2465ad6d6297SScott Long xpt_freeze_simq(acb->psim, 1); 2466f1c579b1SScott Long pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 2467f1c579b1SScott Long } 2468f1c579b1SScott Long splx(s); 2469ad6d6297SScott Long } else { 2470ad6d6297SScott Long /* Buffer is physical */ 24711c7e9358SScott Long panic("arcmsr: CAM_DATA_PHYS not supported"); 2472f1c579b1SScott Long } 2473ad6d6297SScott Long } else { 2474ad6d6297SScott Long /* Scatter/gather list */ 2475f1c579b1SScott Long struct bus_dma_segment *segs; 2476f1c579b1SScott Long 2477ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0 2478ad6d6297SScott Long || (pccb->ccb_h.flags & CAM_DATA_PHYS) != 0) { 2479ad6d6297SScott Long pccb->ccb_h.status |= CAM_PROVIDE_FAIL; 2480f1c579b1SScott Long xpt_done(pccb); 2481ad6d6297SScott Long free(srb, M_DEVBUF); 2482f1c579b1SScott Long return; 2483f1c579b1SScott Long } 2484f1c579b1SScott Long segs=(struct bus_dma_segment *)pccb->csio.data_ptr; 2485ad6d6297SScott Long arcmsr_executesrb(srb, segs, pccb->csio.sglist_cnt, 0); 2486f1c579b1SScott Long } 2487ad6d6297SScott Long } else { 2488ad6d6297SScott Long arcmsr_executesrb(srb, NULL, 0, 0); 2489f1c579b1SScott Long } 2490f1c579b1SScott Long break; 2491f1c579b1SScott Long } 2492ad6d6297SScott Long case XPT_TARGET_IO: { 2493ad6d6297SScott Long /* target mode not yet support vendor specific commands. */ 2494ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2495f1c579b1SScott Long xpt_done(pccb); 2496f1c579b1SScott Long break; 2497f1c579b1SScott Long } 2498ad6d6297SScott Long case XPT_PATH_INQ: { 2499f1c579b1SScott Long struct ccb_pathinq *cpi= &pccb->cpi; 2500f1c579b1SScott Long 2501f1c579b1SScott Long cpi->version_num=1; 2502f1c579b1SScott Long cpi->hba_inquiry=PI_SDTR_ABLE | PI_TAG_ABLE; 2503f1c579b1SScott Long cpi->target_sprt=0; 2504f1c579b1SScott Long cpi->hba_misc=0; 2505f1c579b1SScott Long cpi->hba_eng_cnt=0; 2506ad6d6297SScott Long cpi->max_target=ARCMSR_MAX_TARGETID; /* 0-16 */ 2507ad6d6297SScott Long cpi->max_lun=ARCMSR_MAX_TARGETLUN; /* 0-7 */ 2508ad6d6297SScott Long cpi->initiator_id=ARCMSR_SCSI_INITIATOR_ID; /* 255 */ 2509f1c579b1SScott Long cpi->bus_id=cam_sim_bus(psim); 2510f1c579b1SScott Long strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 2511f1c579b1SScott Long strncpy(cpi->hba_vid, "ARCMSR", HBA_IDLEN); 2512f1c579b1SScott Long strncpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN); 2513f1c579b1SScott Long cpi->unit_number=cam_sim_unit(psim); 251444f05562SScott Long #ifdef CAM_NEW_TRAN_CODE 2515fa9ed865SMatt Jacob cpi->transport = XPORT_SPI; 2516fa9ed865SMatt Jacob cpi->transport_version = 2; 2517fa9ed865SMatt Jacob cpi->protocol = PROTO_SCSI; 2518fa9ed865SMatt Jacob cpi->protocol_version = SCSI_REV_2; 251944f05562SScott Long #endif 2520ad6d6297SScott Long cpi->ccb_h.status |= CAM_REQ_CMP; 2521f1c579b1SScott Long xpt_done(pccb); 2522f1c579b1SScott Long break; 2523f1c579b1SScott Long } 2524ad6d6297SScott Long case XPT_ABORT: { 2525f1c579b1SScott Long union ccb *pabort_ccb; 2526f1c579b1SScott Long 2527f1c579b1SScott Long pabort_ccb=pccb->cab.abort_ccb; 2528ad6d6297SScott Long switch (pabort_ccb->ccb_h.func_code) { 2529f1c579b1SScott Long case XPT_ACCEPT_TARGET_IO: 2530f1c579b1SScott Long case XPT_IMMED_NOTIFY: 2531f1c579b1SScott Long case XPT_CONT_TARGET_IO: 2532ad6d6297SScott Long if(arcmsr_seek_cmd2abort(pabort_ccb)==TRUE) { 2533ad6d6297SScott Long pabort_ccb->ccb_h.status |= CAM_REQ_ABORTED; 2534f1c579b1SScott Long xpt_done(pabort_ccb); 2535ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2536ad6d6297SScott Long } else { 2537f1c579b1SScott Long xpt_print_path(pabort_ccb->ccb_h.path); 2538f1c579b1SScott Long printf("Not found\n"); 2539ad6d6297SScott Long pccb->ccb_h.status |= CAM_PATH_INVALID; 2540f1c579b1SScott Long } 2541f1c579b1SScott Long break; 2542f1c579b1SScott Long case XPT_SCSI_IO: 2543ad6d6297SScott Long pccb->ccb_h.status |= CAM_UA_ABORT; 2544f1c579b1SScott Long break; 2545f1c579b1SScott Long default: 2546ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2547f1c579b1SScott Long break; 2548f1c579b1SScott Long } 2549f1c579b1SScott Long xpt_done(pccb); 2550f1c579b1SScott Long break; 2551f1c579b1SScott Long } 2552f1c579b1SScott Long case XPT_RESET_BUS: 2553ad6d6297SScott Long case XPT_RESET_DEV: { 2554ad6d6297SScott Long u_int32_t i; 2555f1c579b1SScott Long 2556ad6d6297SScott Long arcmsr_bus_reset(acb); 2557ad6d6297SScott Long for (i=0; i < 500; i++) { 2558f1c579b1SScott Long DELAY(1000); 2559f1c579b1SScott Long } 2560ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2561f1c579b1SScott Long xpt_done(pccb); 2562f1c579b1SScott Long break; 2563f1c579b1SScott Long } 2564ad6d6297SScott Long case XPT_TERM_IO: { 2565ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2566f1c579b1SScott Long xpt_done(pccb); 2567f1c579b1SScott Long break; 2568f1c579b1SScott Long } 2569ad6d6297SScott Long case XPT_GET_TRAN_SETTINGS: { 2570ad6d6297SScott Long struct ccb_trans_settings *cts; 2571ad6d6297SScott Long 2572ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 2573ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 2574ad6d6297SScott Long xpt_done(pccb); 2575ad6d6297SScott Long break; 2576ad6d6297SScott Long } 2577ad6d6297SScott Long cts= &pccb->cts; 257844f05562SScott Long #ifdef CAM_NEW_TRAN_CODE 257944f05562SScott Long { 258044f05562SScott Long struct ccb_trans_settings_scsi *scsi; 258144f05562SScott Long struct ccb_trans_settings_spi *spi; 258244f05562SScott Long 2583ad6d6297SScott Long scsi = &cts->proto_specific.scsi; 2584ad6d6297SScott Long spi = &cts->xport_specific.spi; 2585fa9ed865SMatt Jacob cts->protocol = PROTO_SCSI; 2586fa9ed865SMatt Jacob cts->protocol_version = SCSI_REV_2; 2587fa9ed865SMatt Jacob cts->transport = XPORT_SPI; 2588fa9ed865SMatt Jacob cts->transport_version = 2; 2589fa9ed865SMatt Jacob spi->flags = CTS_SPI_FLAGS_DISC_ENB; 2590fa9ed865SMatt Jacob spi->sync_period=3; 2591fa9ed865SMatt Jacob spi->sync_offset=32; 2592fa9ed865SMatt Jacob spi->bus_width=MSG_EXT_WDTR_BUS_16_BIT; 2593fa9ed865SMatt Jacob scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 25949d98ff4dSScott Long spi->valid = CTS_SPI_VALID_DISC 25959d98ff4dSScott Long | CTS_SPI_VALID_SYNC_RATE 2596fa9ed865SMatt Jacob | CTS_SPI_VALID_SYNC_OFFSET 2597fa9ed865SMatt Jacob | CTS_SPI_VALID_BUS_WIDTH; 2598fa9ed865SMatt Jacob scsi->valid = CTS_SCSI_VALID_TQ; 259944f05562SScott Long } 260044f05562SScott Long #else 260144f05562SScott Long { 260244f05562SScott Long cts->flags=(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB); 260344f05562SScott Long cts->sync_period=3; 260444f05562SScott Long cts->sync_offset=32; 260544f05562SScott Long cts->bus_width=MSG_EXT_WDTR_BUS_16_BIT; 260644f05562SScott Long cts->valid=CCB_TRANS_SYNC_RATE_VALID | 260744f05562SScott Long CCB_TRANS_SYNC_OFFSET_VALID | 260844f05562SScott Long CCB_TRANS_BUS_WIDTH_VALID | 260944f05562SScott Long CCB_TRANS_DISC_VALID | 261044f05562SScott Long CCB_TRANS_TQ_VALID; 261144f05562SScott Long } 261244f05562SScott Long #endif 2613ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2614ad6d6297SScott Long xpt_done(pccb); 2615ad6d6297SScott Long break; 2616ad6d6297SScott Long } 2617ad6d6297SScott Long case XPT_SET_TRAN_SETTINGS: { 2618ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 2619ad6d6297SScott Long xpt_done(pccb); 2620ad6d6297SScott Long break; 2621ad6d6297SScott Long } 2622ad6d6297SScott Long case XPT_CALC_GEOMETRY: { 2623ad6d6297SScott Long struct ccb_calc_geometry *ccg; 2624ad6d6297SScott Long u_int32_t size_mb; 2625ad6d6297SScott Long u_int32_t secs_per_cylinder; 2626ad6d6297SScott Long 2627ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 2628ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 2629ad6d6297SScott Long xpt_done(pccb); 2630ad6d6297SScott Long break; 2631ad6d6297SScott Long } 2632f1c579b1SScott Long ccg= &pccb->ccg; 2633ad6d6297SScott Long if (ccg->block_size == 0) { 2634ad6d6297SScott Long pccb->ccb_h.status = CAM_REQ_INVALID; 2635ad6d6297SScott Long xpt_done(pccb); 2636ad6d6297SScott Long break; 2637ad6d6297SScott Long } 2638ad6d6297SScott Long if(((1024L * 1024L)/ccg->block_size) < 0) { 2639ad6d6297SScott Long pccb->ccb_h.status = CAM_REQ_INVALID; 2640ad6d6297SScott Long xpt_done(pccb); 2641ad6d6297SScott Long break; 2642ad6d6297SScott Long } 2643f1c579b1SScott Long size_mb=ccg->volume_size/((1024L * 1024L)/ccg->block_size); 2644ad6d6297SScott Long if(size_mb > 1024 ) { 2645f1c579b1SScott Long ccg->heads=255; 2646f1c579b1SScott Long ccg->secs_per_track=63; 2647ad6d6297SScott Long } else { 2648f1c579b1SScott Long ccg->heads=64; 2649f1c579b1SScott Long ccg->secs_per_track=32; 2650f1c579b1SScott Long } 2651f1c579b1SScott Long secs_per_cylinder=ccg->heads * ccg->secs_per_track; 2652f1c579b1SScott Long ccg->cylinders=ccg->volume_size / secs_per_cylinder; 2653ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2654f1c579b1SScott Long xpt_done(pccb); 2655f1c579b1SScott Long break; 2656f1c579b1SScott Long } 2657f1c579b1SScott Long default: 2658ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2659f1c579b1SScott Long xpt_done(pccb); 2660f1c579b1SScott Long break; 2661f1c579b1SScott Long } 2662f1c579b1SScott Long return; 2663f1c579b1SScott Long } 2664f1c579b1SScott Long /* 2665f1c579b1SScott Long ********************************************************************** 2666f1c579b1SScott Long ********************************************************************** 2667f1c579b1SScott Long */ 266844f05562SScott Long static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) 2669f1c579b1SScott Long { 2670ad6d6297SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 267144f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 267244f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 2673ad6d6297SScott Long printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 2674ad6d6297SScott Long } 2675f1c579b1SScott Long return; 2676f1c579b1SScott Long } 2677f1c579b1SScott Long /* 2678f1c579b1SScott Long ********************************************************************** 2679f1c579b1SScott Long ********************************************************************** 2680f1c579b1SScott Long */ 268144f05562SScott Long static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb) 268244f05562SScott Long { 268344f05562SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 2684*d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_START_BGRB); 268544f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 268644f05562SScott Long printf( "arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 268744f05562SScott Long } 268844f05562SScott Long return; 268944f05562SScott Long } 269044f05562SScott Long /* 269144f05562SScott Long ********************************************************************** 269244f05562SScott Long ********************************************************************** 269344f05562SScott Long */ 2694*d74001adSXin LI static void arcmsr_start_hbc_bgrb(struct AdapterControlBlock *acb) 2695*d74001adSXin LI { 2696*d74001adSXin LI acb->acb_flags |= ACB_F_MSG_START_BGRB; 2697*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 2698*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 2699*d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 2700*d74001adSXin LI printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 2701*d74001adSXin LI } 2702*d74001adSXin LI return; 2703*d74001adSXin LI } 2704*d74001adSXin LI /* 2705*d74001adSXin LI ********************************************************************** 2706*d74001adSXin LI ********************************************************************** 2707*d74001adSXin LI */ 270844f05562SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) 270944f05562SScott Long { 271044f05562SScott Long switch (acb->adapter_type) { 271144f05562SScott Long case ACB_ADAPTER_TYPE_A: 271244f05562SScott Long arcmsr_start_hba_bgrb(acb); 271344f05562SScott Long break; 271444f05562SScott Long case ACB_ADAPTER_TYPE_B: 271544f05562SScott Long arcmsr_start_hbb_bgrb(acb); 271644f05562SScott Long break; 2717*d74001adSXin LI case ACB_ADAPTER_TYPE_C: 2718*d74001adSXin LI arcmsr_start_hbc_bgrb(acb); 2719*d74001adSXin LI break; 272044f05562SScott Long } 272144f05562SScott Long return; 272244f05562SScott Long } 272344f05562SScott Long /* 272444f05562SScott Long ********************************************************************** 272544f05562SScott Long ** 272644f05562SScott Long ********************************************************************** 272744f05562SScott Long */ 272844f05562SScott Long static void arcmsr_polling_hba_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 2729f1c579b1SScott Long { 2730ad6d6297SScott Long struct CommandControlBlock *srb; 273144f05562SScott Long u_int32_t flag_srb, outbound_intstatus, poll_srb_done=0, poll_count=0; 2732*d74001adSXin LI u_int16_t error; 2733f1c579b1SScott Long 273444f05562SScott Long polling_ccb_retry: 2735ad6d6297SScott Long poll_count++; 2736*d74001adSXin LI outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 2737*d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus); /*clear interrupt*/ 273844f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 2739ad6d6297SScott Long while(1) { 274044f05562SScott Long if((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 274144f05562SScott Long 0, outbound_queueport))==0xFFFFFFFF) { 2742ad6d6297SScott Long if(poll_srb_done) { 2743ad6d6297SScott Long break;/*chip FIFO no ccb for completion already*/ 2744ad6d6297SScott Long } else { 2745ad6d6297SScott Long UDELAY(25000); 2746*d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 2747ad6d6297SScott Long break; 2748f1c579b1SScott Long } 274944f05562SScott Long goto polling_ccb_retry; 2750f1c579b1SScott Long } 2751ad6d6297SScott Long } 2752ad6d6297SScott Long /* check if command done with no error*/ 275344f05562SScott Long srb=(struct CommandControlBlock *) 275444f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 2755*d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 275644f05562SScott Long poll_srb_done = (srb==poll_srb) ? 1:0; 2757ad6d6297SScott Long if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) { 275844f05562SScott Long if(srb->startdone==ARCMSR_SRB_ABORTED) { 2759ad6d6297SScott Long printf("arcmsr%d: scsi id=%d lun=%d srb='%p'" 2760ad6d6297SScott Long "poll command abort successfully \n" 2761ad6d6297SScott Long , acb->pci_unit 2762ad6d6297SScott Long , srb->pccb->ccb_h.target_id 2763ad6d6297SScott Long , srb->pccb->ccb_h.target_lun, srb); 2764ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 2765ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 2766ad6d6297SScott Long continue; 2767ad6d6297SScott Long } 2768ad6d6297SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 2769ad6d6297SScott Long "srboutstandingcount=%d \n" 2770ad6d6297SScott Long , acb->pci_unit 2771ad6d6297SScott Long , srb, acb->srboutstandingcount); 2772ad6d6297SScott Long continue; 2773ad6d6297SScott Long } 2774*d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 2775ad6d6297SScott Long } /*drain reply FIFO*/ 2776f1c579b1SScott Long return; 2777f1c579b1SScott Long } 2778f1c579b1SScott Long /* 2779f1c579b1SScott Long ********************************************************************** 278044f05562SScott Long ** 2781ad6d6297SScott Long ********************************************************************** 2782ad6d6297SScott Long */ 278344f05562SScott Long static void arcmsr_polling_hbb_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 278444f05562SScott Long { 278544f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 278644f05562SScott Long struct CommandControlBlock *srb; 278744f05562SScott Long u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 278844f05562SScott Long int index; 2789*d74001adSXin LI u_int16_t error; 279044f05562SScott Long 279144f05562SScott Long polling_ccb_retry: 279244f05562SScott Long poll_count++; 279344f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 279444f05562SScott Long 0, iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 279544f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 279644f05562SScott Long while(1) { 279744f05562SScott Long index=phbbmu->doneq_index; 279844f05562SScott Long if((flag_srb=phbbmu->done_qbuffer[index]) == 0) { 279944f05562SScott Long if(poll_srb_done) { 280044f05562SScott Long break;/*chip FIFO no ccb for completion already*/ 280144f05562SScott Long } else { 280244f05562SScott Long UDELAY(25000); 2803*d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 280444f05562SScott Long break; 280544f05562SScott Long } 280644f05562SScott Long goto polling_ccb_retry; 280744f05562SScott Long } 280844f05562SScott Long } 280944f05562SScott Long phbbmu->done_qbuffer[index]=0; 281044f05562SScott Long index++; 281144f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 281244f05562SScott Long phbbmu->doneq_index=index; 281344f05562SScott Long /* check if command done with no error*/ 281444f05562SScott Long srb=(struct CommandControlBlock *) 281544f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 2816*d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 281744f05562SScott Long poll_srb_done = (srb==poll_srb) ? 1:0; 281844f05562SScott Long if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) { 281944f05562SScott Long if(srb->startdone==ARCMSR_SRB_ABORTED) { 282044f05562SScott Long printf("arcmsr%d: scsi id=%d lun=%d srb='%p'" 282144f05562SScott Long "poll command abort successfully \n" 282244f05562SScott Long , acb->pci_unit 282344f05562SScott Long , srb->pccb->ccb_h.target_id 282444f05562SScott Long , srb->pccb->ccb_h.target_lun, srb); 282544f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 282644f05562SScott Long arcmsr_srb_complete(srb, 1); 282744f05562SScott Long continue; 282844f05562SScott Long } 282944f05562SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 283044f05562SScott Long "srboutstandingcount=%d \n" 283144f05562SScott Long , acb->pci_unit 283244f05562SScott Long , srb, acb->srboutstandingcount); 283344f05562SScott Long continue; 283444f05562SScott Long } 2835*d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 2836*d74001adSXin LI } /*drain reply FIFO*/ 2837*d74001adSXin LI return; 2838*d74001adSXin LI } 2839*d74001adSXin LI /* 2840*d74001adSXin LI ********************************************************************** 2841*d74001adSXin LI ** 2842*d74001adSXin LI ********************************************************************** 2843*d74001adSXin LI */ 2844*d74001adSXin LI static void arcmsr_polling_hbc_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 2845*d74001adSXin LI { 2846*d74001adSXin LI struct CommandControlBlock *srb; 2847*d74001adSXin LI u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 2848*d74001adSXin LI u_int16_t error; 2849*d74001adSXin LI 2850*d74001adSXin LI polling_ccb_retry: 2851*d74001adSXin LI poll_count++; 2852*d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 2853*d74001adSXin LI while(1) { 2854*d74001adSXin LI if(!(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR)) { 2855*d74001adSXin LI if(poll_srb_done) { 2856*d74001adSXin LI break;/*chip FIFO no ccb for completion already*/ 2857*d74001adSXin LI } else { 2858*d74001adSXin LI UDELAY(25000); 2859*d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 2860*d74001adSXin LI break; 2861*d74001adSXin LI } 2862*d74001adSXin LI if (acb->srboutstandingcount == 0) { 2863*d74001adSXin LI break; 2864*d74001adSXin LI } 2865*d74001adSXin LI goto polling_ccb_retry; 2866*d74001adSXin LI } 2867*d74001adSXin LI } 2868*d74001adSXin LI flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 2869*d74001adSXin LI /* check if command done with no error*/ 2870*d74001adSXin LI srb=(struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFF0));/*frame must be 32 bytes aligned*/ 2871*d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; 2872*d74001adSXin LI if (poll_srb != NULL) 2873*d74001adSXin LI poll_srb_done = (srb==poll_srb) ? 1:0; 2874*d74001adSXin LI if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) { 2875*d74001adSXin LI if(srb->startdone==ARCMSR_SRB_ABORTED) { 2876*d74001adSXin LI printf("arcmsr%d: scsi id=%d lun=%d srb='%p'poll command abort successfully \n" 2877*d74001adSXin LI , acb->pci_unit, srb->pccb->ccb_h.target_id, srb->pccb->ccb_h.target_lun, srb); 2878*d74001adSXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 2879*d74001adSXin LI arcmsr_srb_complete(srb, 1); 2880*d74001adSXin LI continue; 2881*d74001adSXin LI } 2882*d74001adSXin LI printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n" 2883*d74001adSXin LI , acb->pci_unit, srb, acb->srboutstandingcount); 2884*d74001adSXin LI continue; 2885*d74001adSXin LI } 2886*d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 288744f05562SScott Long } /*drain reply FIFO*/ 288844f05562SScott Long return; 288944f05562SScott Long } 289044f05562SScott Long /* 289144f05562SScott Long ********************************************************************** 289244f05562SScott Long ********************************************************************** 289344f05562SScott Long */ 289444f05562SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 289544f05562SScott Long { 289644f05562SScott Long switch (acb->adapter_type) { 289744f05562SScott Long case ACB_ADAPTER_TYPE_A: { 289844f05562SScott Long arcmsr_polling_hba_srbdone(acb, poll_srb); 289944f05562SScott Long } 290044f05562SScott Long break; 290144f05562SScott Long case ACB_ADAPTER_TYPE_B: { 290244f05562SScott Long arcmsr_polling_hbb_srbdone(acb, poll_srb); 290344f05562SScott Long } 290444f05562SScott Long break; 2905*d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 2906*d74001adSXin LI arcmsr_polling_hbc_srbdone(acb, poll_srb); 2907*d74001adSXin LI } 2908*d74001adSXin LI break; 290944f05562SScott Long } 291044f05562SScott Long } 291144f05562SScott Long /* 291244f05562SScott Long ********************************************************************** 291344f05562SScott Long ********************************************************************** 291444f05562SScott Long */ 291544f05562SScott Long static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) 2916ad6d6297SScott Long { 2917ad6d6297SScott Long char *acb_firm_model=acb->firm_model; 2918ad6d6297SScott Long char *acb_firm_version=acb->firm_version; 2919*d74001adSXin LI char *acb_device_map = acb->device_map; 2920*d74001adSXin LI size_t iop_firm_model=offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 2921*d74001adSXin LI size_t iop_firm_version=offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 2922*d74001adSXin LI size_t iop_device_map = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 2923ad6d6297SScott Long int i; 2924ad6d6297SScott Long 292544f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 292644f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 2927*d74001adSXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 2928ad6d6297SScott Long } 2929ad6d6297SScott Long i=0; 2930ad6d6297SScott Long while(i<8) { 293144f05562SScott Long *acb_firm_model=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 2932ad6d6297SScott Long /* 8 bytes firm_model, 15, 60-67*/ 2933ad6d6297SScott Long acb_firm_model++; 2934ad6d6297SScott Long i++; 2935ad6d6297SScott Long } 2936ad6d6297SScott Long i=0; 2937ad6d6297SScott Long while(i<16) { 293844f05562SScott Long *acb_firm_version=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 2939ad6d6297SScott Long /* 16 bytes firm_version, 17, 68-83*/ 2940ad6d6297SScott Long acb_firm_version++; 2941ad6d6297SScott Long i++; 2942ad6d6297SScott Long } 2943*d74001adSXin LI i=0; 2944*d74001adSXin LI while(i<16) { 2945*d74001adSXin LI *acb_device_map=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 2946*d74001adSXin LI acb_device_map++; 2947*d74001adSXin LI i++; 2948*d74001adSXin LI } 2949ad6d6297SScott Long printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION); 2950ad6d6297SScott Long printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version); 2951*d74001adSXin LI acb->firm_request_len=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 2952*d74001adSXin LI acb->firm_numbers_queue=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 2953*d74001adSXin LI acb->firm_sdram_size=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 2954*d74001adSXin LI acb->firm_ide_channels=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 2955*d74001adSXin LI acb->firm_cfg_version=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 2956ad6d6297SScott Long return; 2957ad6d6297SScott Long } 2958ad6d6297SScott Long /* 2959ad6d6297SScott Long ********************************************************************** 296044f05562SScott Long ********************************************************************** 296144f05562SScott Long */ 296244f05562SScott Long static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) 296344f05562SScott Long { 296444f05562SScott Long char *acb_firm_model=acb->firm_model; 296544f05562SScott Long char *acb_firm_version=acb->firm_version; 2966*d74001adSXin LI char *acb_device_map = acb->device_map; 2967*d74001adSXin LI size_t iop_firm_model=offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 2968*d74001adSXin LI size_t iop_firm_version=offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 2969*d74001adSXin LI size_t iop_device_map = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 297044f05562SScott Long int i; 297144f05562SScott Long 2972*d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG); 297344f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 2974*d74001adSXin LI printf( "arcmsr%d: wait" "'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 297544f05562SScott Long } 297644f05562SScott Long i=0; 297744f05562SScott Long while(i<8) { 297844f05562SScott Long *acb_firm_model=bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_model+i); 297944f05562SScott Long /* 8 bytes firm_model, 15, 60-67*/ 298044f05562SScott Long acb_firm_model++; 298144f05562SScott Long i++; 298244f05562SScott Long } 298344f05562SScott Long i=0; 298444f05562SScott Long while(i<16) { 298544f05562SScott Long *acb_firm_version=bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_version+i); 298644f05562SScott Long /* 16 bytes firm_version, 17, 68-83*/ 298744f05562SScott Long acb_firm_version++; 298844f05562SScott Long i++; 298944f05562SScott Long } 2990*d74001adSXin LI i=0; 2991*d74001adSXin LI while(i<16) { 2992*d74001adSXin LI *acb_device_map=bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_device_map+i); 2993*d74001adSXin LI acb_device_map++; 2994*d74001adSXin LI i++; 2995*d74001adSXin LI } 299644f05562SScott Long printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION); 299744f05562SScott Long printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version); 2998*d74001adSXin LI acb->firm_request_len=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 2999*d74001adSXin LI acb->firm_numbers_queue=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3000*d74001adSXin LI acb->firm_sdram_size=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3001*d74001adSXin LI acb->firm_ide_channels=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3002*d74001adSXin LI acb->firm_cfg_version=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3003*d74001adSXin LI return; 3004*d74001adSXin LI } 3005*d74001adSXin LI /* 3006*d74001adSXin LI ********************************************************************** 3007*d74001adSXin LI ********************************************************************** 3008*d74001adSXin LI */ 3009*d74001adSXin LI static void arcmsr_get_hbc_config(struct AdapterControlBlock *acb) 3010*d74001adSXin LI { 3011*d74001adSXin LI char *acb_firm_model=acb->firm_model; 3012*d74001adSXin LI char *acb_firm_version=acb->firm_version; 3013*d74001adSXin LI char *acb_device_map = acb->device_map; 3014*d74001adSXin LI size_t iop_firm_model=offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3015*d74001adSXin LI size_t iop_firm_version=offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3016*d74001adSXin LI size_t iop_device_map = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 3017*d74001adSXin LI int i; 3018*d74001adSXin LI 3019*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 3020*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 3021*d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 3022*d74001adSXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 3023*d74001adSXin LI } 3024*d74001adSXin LI i=0; 3025*d74001adSXin LI while(i<8) { 3026*d74001adSXin LI *acb_firm_model=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 3027*d74001adSXin LI /* 8 bytes firm_model, 15, 60-67*/ 3028*d74001adSXin LI acb_firm_model++; 3029*d74001adSXin LI i++; 3030*d74001adSXin LI } 3031*d74001adSXin LI i=0; 3032*d74001adSXin LI while(i<16) { 3033*d74001adSXin LI *acb_firm_version=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 3034*d74001adSXin LI /* 16 bytes firm_version, 17, 68-83*/ 3035*d74001adSXin LI acb_firm_version++; 3036*d74001adSXin LI i++; 3037*d74001adSXin LI } 3038*d74001adSXin LI i=0; 3039*d74001adSXin LI while(i<16) { 3040*d74001adSXin LI *acb_device_map=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 3041*d74001adSXin LI acb_device_map++; 3042*d74001adSXin LI i++; 3043*d74001adSXin LI } 3044*d74001adSXin LI printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION); 3045*d74001adSXin LI printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version); 3046*d74001adSXin LI acb->firm_request_len =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3047*d74001adSXin LI acb->firm_numbers_queue =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3048*d74001adSXin LI acb->firm_sdram_size =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3049*d74001adSXin LI acb->firm_ide_channels =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3050*d74001adSXin LI acb->firm_cfg_version =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 305144f05562SScott Long return; 305244f05562SScott Long } 305344f05562SScott Long /* 305444f05562SScott Long ********************************************************************** 305544f05562SScott Long ********************************************************************** 305644f05562SScott Long */ 305744f05562SScott Long static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) 305844f05562SScott Long { 305944f05562SScott Long switch (acb->adapter_type) { 306044f05562SScott Long case ACB_ADAPTER_TYPE_A: { 306144f05562SScott Long arcmsr_get_hba_config(acb); 306244f05562SScott Long } 306344f05562SScott Long break; 306444f05562SScott Long case ACB_ADAPTER_TYPE_B: { 306544f05562SScott Long arcmsr_get_hbb_config(acb); 306644f05562SScott Long } 306744f05562SScott Long break; 3068*d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3069*d74001adSXin LI arcmsr_get_hbc_config(acb); 3070*d74001adSXin LI } 3071*d74001adSXin LI break; 307244f05562SScott Long } 307344f05562SScott Long return; 307444f05562SScott Long } 307544f05562SScott Long /* 307644f05562SScott Long ********************************************************************** 307744f05562SScott Long ********************************************************************** 307844f05562SScott Long */ 307944f05562SScott Long static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb) 308044f05562SScott Long { 308144f05562SScott Long int timeout=0; 308244f05562SScott Long 308344f05562SScott Long switch (acb->adapter_type) { 308444f05562SScott Long case ACB_ADAPTER_TYPE_A: { 3085*d74001adSXin LI while ((CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) 308644f05562SScott Long { 308744f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 308844f05562SScott Long { 3089*d74001adSXin LI printf( "arcmsr%d:timed out waiting for firmware \n", acb->pci_unit); 309044f05562SScott Long return; 309144f05562SScott Long } 309244f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 309344f05562SScott Long } 309444f05562SScott Long } 309544f05562SScott Long break; 309644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 3097*d74001adSXin LI while ((CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & ARCMSR_MESSAGE_FIRMWARE_OK) == 0) 309844f05562SScott Long { 309944f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 310044f05562SScott Long { 3101*d74001adSXin LI printf( "arcmsr%d: timed out waiting for firmware \n", acb->pci_unit); 310244f05562SScott Long return; 310344f05562SScott Long } 310444f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 310544f05562SScott Long } 3106*d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 3107*d74001adSXin LI } 3108*d74001adSXin LI break; 3109*d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3110*d74001adSXin LI while ((CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0) 3111*d74001adSXin LI { 3112*d74001adSXin LI if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 3113*d74001adSXin LI { 3114*d74001adSXin LI printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit); 3115*d74001adSXin LI return; 3116*d74001adSXin LI } 3117*d74001adSXin LI UDELAY(15000); /* wait 15 milli-seconds */ 3118*d74001adSXin LI } 311944f05562SScott Long } 312044f05562SScott Long break; 312144f05562SScott Long } 312244f05562SScott Long return; 312344f05562SScott Long } 312444f05562SScott Long /* 312544f05562SScott Long ********************************************************************** 312644f05562SScott Long ********************************************************************** 312744f05562SScott Long */ 312844f05562SScott Long static void arcmsr_clear_doorbell_queue_buffer( struct AdapterControlBlock *acb) 312944f05562SScott Long { 3130*d74001adSXin LI u_int32_t outbound_doorbell; 3131*d74001adSXin LI 313244f05562SScott Long switch (acb->adapter_type) { 313344f05562SScott Long case ACB_ADAPTER_TYPE_A: { 313444f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 3135*d74001adSXin LI outbound_doorbell = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell); 3136*d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, outbound_doorbell); /*clear doorbell interrupt */ 3137*d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 3138*d74001adSXin LI 313944f05562SScott Long } 314044f05562SScott Long break; 314144f05562SScott Long case ACB_ADAPTER_TYPE_B: { 3142*d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt and message state*/ 3143*d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 314444f05562SScott Long /* let IOP know data has been read */ 314544f05562SScott Long } 314644f05562SScott Long break; 3147*d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3148*d74001adSXin LI /* empty doorbell Qbuffer if door bell ringed */ 3149*d74001adSXin LI outbound_doorbell = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); 3150*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell); /*clear doorbell interrupt */ 3151*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK); 3152*d74001adSXin LI 3153*d74001adSXin LI } 3154*d74001adSXin LI break; 315544f05562SScott Long } 315644f05562SScott Long return; 315744f05562SScott Long } 315844f05562SScott Long /* 315944f05562SScott Long ************************************************************************ 316044f05562SScott Long ************************************************************************ 316144f05562SScott Long */ 316244f05562SScott Long static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb) 316344f05562SScott Long { 316444f05562SScott Long unsigned long srb_phyaddr; 316544f05562SScott Long u_int32_t srb_phyaddr_hi32; 316644f05562SScott Long 316744f05562SScott Long /* 316844f05562SScott Long ******************************************************************** 316944f05562SScott Long ** here we need to tell iop 331 our freesrb.HighPart 317044f05562SScott Long ** if freesrb.HighPart is not zero 317144f05562SScott Long ******************************************************************** 317244f05562SScott Long */ 3173*d74001adSXin LI srb_phyaddr= (unsigned long) acb->srb_phyaddr.phyaddr; 3174*d74001adSXin LI // srb_phyaddr_hi32=(u_int32_t) ((srb_phyaddr>>16)>>16); 3175*d74001adSXin LI srb_phyaddr_hi32=acb->srb_phyaddr.B.phyadd_high; 317644f05562SScott Long switch (acb->adapter_type) { 317744f05562SScott Long case ACB_ADAPTER_TYPE_A: { 317844f05562SScott Long if(srb_phyaddr_hi32!=0) { 3179*d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 3180*d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 3181*d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 318244f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 3183*d74001adSXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 318444f05562SScott Long return FALSE; 318544f05562SScott Long } 318644f05562SScott Long } 318744f05562SScott Long } 318844f05562SScott Long break; 318944f05562SScott Long /* 319044f05562SScott Long *********************************************************************** 319144f05562SScott Long ** if adapter type B, set window of "post command Q" 319244f05562SScott Long *********************************************************************** 319344f05562SScott Long */ 319444f05562SScott Long case ACB_ADAPTER_TYPE_B: { 319544f05562SScott Long u_int32_t post_queue_phyaddr; 319644f05562SScott Long struct HBB_MessageUnit *phbbmu; 319744f05562SScott Long 319844f05562SScott Long phbbmu=(struct HBB_MessageUnit *)acb->pmu; 319944f05562SScott Long phbbmu->postq_index=0; 320044f05562SScott Long phbbmu->doneq_index=0; 3201*d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_SET_POST_WINDOW); 320244f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 3203*d74001adSXin LI printf( "arcmsr%d: 'set window of post command Q' timeout\n", acb->pci_unit); 320444f05562SScott Long return FALSE; 320544f05562SScott Long } 3206*d74001adSXin LI post_queue_phyaddr = srb_phyaddr + ARCMSR_MAX_FREESRB_NUM*sizeof(struct CommandControlBlock) 320744f05562SScott Long + offsetof(struct HBB_MessageUnit, post_qbuffer); 3208*d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */ 3209*d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1], srb_phyaddr_hi32); /* normal should be zero */ 3210*d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ size (256+8)*4 */ 3211*d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3], post_queue_phyaddr+1056); /* doneQ size (256+8)*4 */ 3212*d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4], 1056); /* srb maxQ size must be --> [(256+8)*4] */ 3213*d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_SET_CONFIG); 321444f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 321544f05562SScott Long printf( "arcmsr%d: 'set command Q window' timeout \n", acb->pci_unit); 321644f05562SScott Long return FALSE; 321744f05562SScott Long } 3218*d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_START_DRIVER_MODE); 321944f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 322044f05562SScott Long printf( "arcmsr%d: 'start diver mode' timeout \n", acb->pci_unit); 322144f05562SScott Long return FALSE; 322244f05562SScott Long } 322344f05562SScott Long } 322444f05562SScott Long break; 3225*d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3226*d74001adSXin LI if(srb_phyaddr_hi32!=0) { 3227*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 3228*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 3229*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 3230*d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 3231*d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 3232*d74001adSXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 3233*d74001adSXin LI return FALSE; 3234*d74001adSXin LI } 3235*d74001adSXin LI } 3236*d74001adSXin LI } 3237*d74001adSXin LI break; 323844f05562SScott Long } 323944f05562SScott Long return TRUE; 324044f05562SScott Long } 324144f05562SScott Long /* 324244f05562SScott Long ************************************************************************ 324344f05562SScott Long ************************************************************************ 324444f05562SScott Long */ 324544f05562SScott Long static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb) 324644f05562SScott Long { 324744f05562SScott Long switch (acb->adapter_type) 324844f05562SScott Long { 324944f05562SScott Long case ACB_ADAPTER_TYPE_A: 3250*d74001adSXin LI case ACB_ADAPTER_TYPE_C: 3251*d74001adSXin LI break; 325244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 3253*d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell,ARCMSR_MESSAGE_ACTIVE_EOI_MODE); 325444f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 3255*d74001adSXin LI printf( "arcmsr%d: 'iop enable eoi mode' timeout \n", acb->pci_unit); 3256*d74001adSXin LI 325744f05562SScott Long return; 325844f05562SScott Long } 325944f05562SScott Long } 326044f05562SScott Long break; 326144f05562SScott Long } 326244f05562SScott Long return; 326344f05562SScott Long } 326444f05562SScott Long /* 326544f05562SScott Long ********************************************************************** 3266ad6d6297SScott Long ********************************************************************** 3267ad6d6297SScott Long */ 3268ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb) 3269ad6d6297SScott Long { 327044f05562SScott Long u_int32_t intmask_org; 3271ad6d6297SScott Long 327244f05562SScott Long /* disable all outbound interrupt */ 327344f05562SScott Long intmask_org=arcmsr_disable_allintr(acb); 327444f05562SScott Long arcmsr_wait_firmware_ready(acb); 327544f05562SScott Long arcmsr_iop_confirm(acb); 3276ad6d6297SScott Long arcmsr_get_firmware_spec(acb); 327744f05562SScott Long /*start background rebuild*/ 3278ad6d6297SScott Long arcmsr_start_adapter_bgrb(acb); 327944f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 328044f05562SScott Long arcmsr_clear_doorbell_queue_buffer(acb); 328144f05562SScott Long arcmsr_enable_eoi_mode(acb); 328244f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 328344f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 3284ad6d6297SScott Long acb->acb_flags |=ACB_F_IOP_INITED; 3285ad6d6297SScott Long return; 3286ad6d6297SScott Long } 3287ad6d6297SScott Long /* 3288ad6d6297SScott Long ********************************************************************** 3289f1c579b1SScott Long ********************************************************************** 3290f1c579b1SScott Long */ 3291f1c579b1SScott Long static void arcmsr_map_freesrb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 3292f1c579b1SScott Long { 3293ad6d6297SScott Long struct AdapterControlBlock *acb=arg; 3294ad6d6297SScott Long struct CommandControlBlock *srb_tmp; 3295ad6d6297SScott Long u_int8_t * dma_memptr; 329644f05562SScott Long u_int32_t i; 3297ad6d6297SScott Long unsigned long srb_phyaddr=(unsigned long)segs->ds_addr; 3298f1c579b1SScott Long 3299ad6d6297SScott Long dma_memptr=acb->uncacheptr; 3300*d74001adSXin LI acb->srb_phyaddr.phyaddr=srb_phyaddr; 3301ad6d6297SScott Long srb_tmp=(struct CommandControlBlock *)dma_memptr; 3302ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 330344f05562SScott Long if(bus_dmamap_create(acb->dm_segs_dmat, 330444f05562SScott Long /*flags*/0, &srb_tmp->dm_segs_dmamap)!=0) { 3305ad6d6297SScott Long acb->acb_flags |= ACB_F_MAPFREESRB_FAILD; 330644f05562SScott Long printf("arcmsr%d:" 330744f05562SScott Long " srb dmamap bus_dmamap_create error\n", acb->pci_unit); 3308ad6d6297SScott Long return; 3309ad6d6297SScott Long } 3310*d74001adSXin LI srb_tmp->cdb_shifted_phyaddr=(acb->adapter_type==ACB_ADAPTER_TYPE_C)?srb_phyaddr:(srb_phyaddr >> 5); 3311ad6d6297SScott Long srb_tmp->acb=acb; 3312ad6d6297SScott Long acb->srbworkingQ[i]=acb->psrb_pool[i]=srb_tmp; 3313ad6d6297SScott Long srb_phyaddr=srb_phyaddr+sizeof(struct CommandControlBlock); 3314ad6d6297SScott Long srb_tmp++; 3315ad6d6297SScott Long } 3316ad6d6297SScott Long acb->vir2phy_offset=(unsigned long)srb_tmp-(unsigned long)srb_phyaddr; 3317f1c579b1SScott Long return; 3318f1c579b1SScott Long } 3319f1c579b1SScott Long /* 3320f1c579b1SScott Long ************************************************************************ 3321f1c579b1SScott Long ** 3322f1c579b1SScott Long ** 3323f1c579b1SScott Long ************************************************************************ 3324f1c579b1SScott Long */ 3325ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb) 3326f1c579b1SScott Long { 3327f1c579b1SScott Long /* remove the control device */ 3328ad6d6297SScott Long if(acb->ioctl_dev != NULL) { 3329ad6d6297SScott Long destroy_dev(acb->ioctl_dev); 3330f1c579b1SScott Long } 3331ad6d6297SScott Long bus_dmamap_unload(acb->srb_dmat, acb->srb_dmamap); 3332ad6d6297SScott Long bus_dmamap_destroy(acb->srb_dmat, acb->srb_dmamap); 3333ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 3334ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 3335ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 3336f1c579b1SScott Long return; 3337f1c579b1SScott Long } 3338f1c579b1SScott Long /* 3339f1c579b1SScott Long ************************************************************************ 3340f1c579b1SScott Long ************************************************************************ 3341f1c579b1SScott Long */ 3342ad6d6297SScott Long static u_int32_t arcmsr_initialize(device_t dev) 3343f1c579b1SScott Long { 3344ad6d6297SScott Long struct AdapterControlBlock *acb=device_get_softc(dev); 3345ad6d6297SScott Long u_int16_t pci_command; 334644f05562SScott Long int i, j,max_coherent_size; 3347f1c579b1SScott Long 334844f05562SScott Long switch (pci_get_devid(dev)) { 3349*d74001adSXin LI case PCIDevVenIDARC1880: { 3350*d74001adSXin LI acb->adapter_type=ACB_ADAPTER_TYPE_C; 3351*d74001adSXin LI max_coherent_size=ARCMSR_SRBS_POOL_SIZE; 3352*d74001adSXin LI } 3353*d74001adSXin LI break; 335444f05562SScott Long case PCIDevVenIDARC1201: { 335544f05562SScott Long acb->adapter_type=ACB_ADAPTER_TYPE_B; 3356*d74001adSXin LI max_coherent_size=ARCMSR_SRBS_POOL_SIZE+(sizeof(struct HBB_MessageUnit)); 335744f05562SScott Long } 335844f05562SScott Long break; 335944f05562SScott Long case PCIDevVenIDARC1110: 336044f05562SScott Long case PCIDevVenIDARC1120: 336144f05562SScott Long case PCIDevVenIDARC1130: 336244f05562SScott Long case PCIDevVenIDARC1160: 336344f05562SScott Long case PCIDevVenIDARC1170: 336444f05562SScott Long case PCIDevVenIDARC1210: 336544f05562SScott Long case PCIDevVenIDARC1220: 336644f05562SScott Long case PCIDevVenIDARC1230: 336744f05562SScott Long case PCIDevVenIDARC1260: 336844f05562SScott Long case PCIDevVenIDARC1270: 336944f05562SScott Long case PCIDevVenIDARC1280: 3370*d74001adSXin LI case PCIDevVenIDARC1212: 3371*d74001adSXin LI case PCIDevVenIDARC1222: 337244f05562SScott Long case PCIDevVenIDARC1380: 337344f05562SScott Long case PCIDevVenIDARC1381: 337444f05562SScott Long case PCIDevVenIDARC1680: 337544f05562SScott Long case PCIDevVenIDARC1681: { 337644f05562SScott Long acb->adapter_type=ACB_ADAPTER_TYPE_A; 337744f05562SScott Long max_coherent_size=ARCMSR_SRBS_POOL_SIZE; 337844f05562SScott Long } 337944f05562SScott Long break; 338044f05562SScott Long default: { 338144f05562SScott Long printf("arcmsr%d:" 338244f05562SScott Long " unknown RAID adapter type \n", device_get_unit(dev)); 338344f05562SScott Long return ENOMEM; 338444f05562SScott Long } 338544f05562SScott Long } 3386f1c579b1SScott Long #if __FreeBSD_version >= 502010 3387f1c579b1SScott Long if(bus_dma_tag_create( /*parent*/ NULL, 3388f1c579b1SScott Long /*alignemnt*/ 1, 3389f1c579b1SScott Long /*boundary*/ 0, 3390701d9f1fSScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 3391f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 3392f1c579b1SScott Long /*filter*/ NULL, 3393f1c579b1SScott Long /*filterarg*/ NULL, 3394f1c579b1SScott Long /*maxsize*/ BUS_SPACE_MAXSIZE_32BIT, 3395f1c579b1SScott Long /*nsegments*/ BUS_SPACE_UNRESTRICTED, 3396f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 3397f1c579b1SScott Long /*flags*/ 0, 3398f1c579b1SScott Long /*lockfunc*/ NULL, 3399f1c579b1SScott Long /*lockarg*/ NULL, 3400ad6d6297SScott Long &acb->parent_dmat) != 0) 3401f1c579b1SScott Long #else 3402f1c579b1SScott Long if(bus_dma_tag_create( /*parent*/ NULL, 3403f1c579b1SScott Long /*alignemnt*/ 1, 3404f1c579b1SScott Long /*boundary*/ 0, 3405701d9f1fSScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 3406f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 3407f1c579b1SScott Long /*filter*/ NULL, 3408f1c579b1SScott Long /*filterarg*/ NULL, 3409f1c579b1SScott Long /*maxsize*/ BUS_SPACE_MAXSIZE_32BIT, 3410f1c579b1SScott Long /*nsegments*/ BUS_SPACE_UNRESTRICTED, 3411f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 3412f1c579b1SScott Long /*flags*/ 0, 3413ad6d6297SScott Long &acb->parent_dmat) != 0) 3414f1c579b1SScott Long #endif 3415f1c579b1SScott Long { 341644f05562SScott Long printf("arcmsr%d: parent_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 3417f1c579b1SScott Long return ENOMEM; 3418f1c579b1SScott Long } 3419f1c579b1SScott Long /* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */ 3420f1c579b1SScott Long #if __FreeBSD_version >= 502010 3421ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 3422f1c579b1SScott Long /*alignment*/ 1, 3423f1c579b1SScott Long /*boundary*/ 0, 3424f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 3425f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 3426f1c579b1SScott Long /*filter*/ NULL, 3427f1c579b1SScott Long /*filterarg*/ NULL, 3428f1c579b1SScott Long /*maxsize*/ MAXBSIZE, 3429f1c579b1SScott Long /*nsegments*/ ARCMSR_MAX_SG_ENTRIES, 3430f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 3431ad6d6297SScott Long /*flags*/ 0, 3432f1c579b1SScott Long /*lockfunc*/ busdma_lock_mutex, 3433579ec1a5SScott Long #if __FreeBSD_version >= 700025 34345878cbecSScott Long /*lockarg*/ &acb->qbuffer_lock, 3435579ec1a5SScott Long #else 3436579ec1a5SScott Long /*lockarg*/ &Giant, 3437579ec1a5SScott Long #endif 3438ad6d6297SScott Long &acb->dm_segs_dmat) != 0) 3439f1c579b1SScott Long #else 3440ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 3441f1c579b1SScott Long /*alignment*/ 1, 3442f1c579b1SScott Long /*boundary*/ 0, 3443f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 3444f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 3445f1c579b1SScott Long /*filter*/ NULL, 3446f1c579b1SScott Long /*filterarg*/ NULL, 3447f1c579b1SScott Long /*maxsize*/ MAXBSIZE, 3448f1c579b1SScott Long /*nsegments*/ ARCMSR_MAX_SG_ENTRIES, 3449f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 3450ad6d6297SScott Long /*flags*/ 0, 3451ad6d6297SScott Long &acb->dm_segs_dmat) != 0) 3452f1c579b1SScott Long #endif 3453f1c579b1SScott Long { 3454ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 345544f05562SScott Long printf("arcmsr%d: dm_segs_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 3456f1c579b1SScott Long return ENOMEM; 3457f1c579b1SScott Long } 3458ad6d6297SScott Long /* DMA tag for our srb structures.... Allocate the freesrb memory */ 3459f1c579b1SScott Long #if __FreeBSD_version >= 502010 3460ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 346144f05562SScott Long /*alignment*/ 0x20, 3462f1c579b1SScott Long /*boundary*/ 0, 3463f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 3464f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 3465f1c579b1SScott Long /*filter*/ NULL, 3466f1c579b1SScott Long /*filterarg*/ NULL, 346744f05562SScott Long /*maxsize*/ max_coherent_size, 3468f1c579b1SScott Long /*nsegments*/ 1, 3469f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 3470701d9f1fSScott Long /*flags*/ 0, 3471f1c579b1SScott Long /*lockfunc*/ NULL, 3472f1c579b1SScott Long /*lockarg*/ NULL, 3473ad6d6297SScott Long &acb->srb_dmat) != 0) 3474f1c579b1SScott Long #else 3475ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 347644f05562SScott Long /*alignment*/ 0x20, 3477f1c579b1SScott Long /*boundary*/ 0, 3478f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 3479f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 3480f1c579b1SScott Long /*filter*/ NULL, 3481f1c579b1SScott Long /*filterarg*/ NULL, 348244f05562SScott Long /*maxsize*/ max_coherent_size, 3483f1c579b1SScott Long /*nsegments*/ 1, 3484f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 3485701d9f1fSScott Long /*flags*/ 0, 3486ad6d6297SScott Long &acb->srb_dmat) != 0) 3487f1c579b1SScott Long #endif 3488f1c579b1SScott Long { 3489ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 3490ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 349144f05562SScott Long printf("arcmsr%d: srb_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 3492f1c579b1SScott Long return ENXIO; 3493f1c579b1SScott Long } 3494f1c579b1SScott Long /* Allocation for our srbs */ 3495*d74001adSXin LI if(bus_dmamem_alloc(acb->srb_dmat, (void **)&acb->uncacheptr, BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &acb->srb_dmamap) != 0) { 3496ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 3497ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 3498ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 349944f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamem_alloc failure!\n", device_get_unit(dev)); 3500f1c579b1SScott Long return ENXIO; 3501f1c579b1SScott Long } 3502f1c579b1SScott Long /* And permanently map them */ 3503*d74001adSXin LI if(bus_dmamap_load(acb->srb_dmat, acb->srb_dmamap, acb->uncacheptr, max_coherent_size, arcmsr_map_freesrb, acb, /*flags*/0)) { 3504ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 3505ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 3506ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 350744f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamap_load failure!\n", device_get_unit(dev)); 3508f1c579b1SScott Long return ENXIO; 3509f1c579b1SScott Long } 3510f1c579b1SScott Long pci_command=pci_read_config(dev, PCIR_COMMAND, 2); 3511f1c579b1SScott Long pci_command |= PCIM_CMD_BUSMASTEREN; 3512f1c579b1SScott Long pci_command |= PCIM_CMD_PERRESPEN; 3513f1c579b1SScott Long pci_command |= PCIM_CMD_MWRICEN; 3514f1c579b1SScott Long /* Enable Busmaster/Mem */ 3515f1c579b1SScott Long pci_command |= PCIM_CMD_MEMEN; 3516f1c579b1SScott Long pci_write_config(dev, PCIR_COMMAND, pci_command, 2); 351744f05562SScott Long switch(acb->adapter_type) { 351844f05562SScott Long case ACB_ADAPTER_TYPE_A: { 351944f05562SScott Long u_int32_t rid0=PCIR_BAR(0); 352044f05562SScott Long vm_offset_t mem_base0; 352144f05562SScott Long 3522*d74001adSXin LI acb->sys_res_arcmsr[0]=bus_alloc_resource(dev,SYS_RES_MEMORY, &rid0, 0ul, ~0ul, 0x1000, RF_ACTIVE); 352344f05562SScott Long if(acb->sys_res_arcmsr[0] == NULL) { 3524ad6d6297SScott Long arcmsr_free_resource(acb); 3525*d74001adSXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 3526f1c579b1SScott Long return ENOMEM; 3527f1c579b1SScott Long } 352844f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 3529ad6d6297SScott Long arcmsr_free_resource(acb); 3530*d74001adSXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 3531f1c579b1SScott Long return ENXIO; 3532f1c579b1SScott Long } 353344f05562SScott Long mem_base0=(vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 353444f05562SScott Long if(mem_base0==0) { 3535ad6d6297SScott Long arcmsr_free_resource(acb); 3536*d74001adSXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 3537f1c579b1SScott Long return ENXIO; 3538f1c579b1SScott Long } 353944f05562SScott Long acb->btag[0]=rman_get_bustag(acb->sys_res_arcmsr[0]); 354044f05562SScott Long acb->bhandle[0]=rman_get_bushandle(acb->sys_res_arcmsr[0]); 354144f05562SScott Long acb->pmu=(struct MessageUnit_UNION *)mem_base0; 354244f05562SScott Long } 354344f05562SScott Long break; 354444f05562SScott Long case ACB_ADAPTER_TYPE_B: { 354544f05562SScott Long struct HBB_MessageUnit *phbbmu; 354644f05562SScott Long struct CommandControlBlock *freesrb; 354744f05562SScott Long u_int32_t rid[]={ PCIR_BAR(0), PCIR_BAR(2) }; 354844f05562SScott Long vm_offset_t mem_base[]={0,0}; 354944f05562SScott Long for(i=0; i<2; i++) { 355044f05562SScott Long if(i==0) { 3551*d74001adSXin LI acb->sys_res_arcmsr[i]=bus_alloc_resource(dev,SYS_RES_MEMORY, &rid[i], 3552*d74001adSXin LI 0x20400, 0x20400+sizeof(struct HBB_DOORBELL), sizeof(struct HBB_DOORBELL), RF_ACTIVE); 355344f05562SScott Long } else { 3554*d74001adSXin LI acb->sys_res_arcmsr[i]=bus_alloc_resource(dev, SYS_RES_MEMORY, &rid[i], 3555*d74001adSXin LI 0x0fa00, 0x0fa00+sizeof(struct HBB_RWBUFFER), sizeof(struct HBB_RWBUFFER), RF_ACTIVE); 355644f05562SScott Long } 355744f05562SScott Long if(acb->sys_res_arcmsr[i] == NULL) { 355844f05562SScott Long arcmsr_free_resource(acb); 3559*d74001adSXin LI printf("arcmsr%d: bus_alloc_resource %d failure!\n", device_get_unit(dev), i); 356044f05562SScott Long return ENOMEM; 356144f05562SScott Long } 356244f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[i]) <= 0) { 356344f05562SScott Long arcmsr_free_resource(acb); 3564*d74001adSXin LI printf("arcmsr%d: rman_get_start %d failure!\n", device_get_unit(dev), i); 356544f05562SScott Long return ENXIO; 356644f05562SScott Long } 356744f05562SScott Long mem_base[i]=(vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[i]); 356844f05562SScott Long if(mem_base[i]==0) { 356944f05562SScott Long arcmsr_free_resource(acb); 3570*d74001adSXin LI printf("arcmsr%d: rman_get_virtual %d failure!\n", device_get_unit(dev), i); 357144f05562SScott Long return ENXIO; 357244f05562SScott Long } 357344f05562SScott Long acb->btag[i]=rman_get_bustag(acb->sys_res_arcmsr[i]); 357444f05562SScott Long acb->bhandle[i]=rman_get_bushandle(acb->sys_res_arcmsr[i]); 357544f05562SScott Long } 357644f05562SScott Long freesrb=(struct CommandControlBlock *)acb->uncacheptr; 357744f05562SScott Long acb->pmu=(struct MessageUnit_UNION *)&freesrb[ARCMSR_MAX_FREESRB_NUM]; 357844f05562SScott Long phbbmu=(struct HBB_MessageUnit *)acb->pmu; 357944f05562SScott Long phbbmu->hbb_doorbell=(struct HBB_DOORBELL *)mem_base[0]; 358044f05562SScott Long phbbmu->hbb_rwbuffer=(struct HBB_RWBUFFER *)mem_base[1]; 358144f05562SScott Long } 358244f05562SScott Long break; 3583*d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3584*d74001adSXin LI u_int32_t rid0=PCIR_BAR(1); 3585*d74001adSXin LI vm_offset_t mem_base0; 3586*d74001adSXin LI 3587*d74001adSXin LI acb->sys_res_arcmsr[0]=bus_alloc_resource(dev,SYS_RES_MEMORY, &rid0, 0ul, ~0ul, sizeof(struct HBC_MessageUnit), RF_ACTIVE); 3588*d74001adSXin LI if(acb->sys_res_arcmsr[0] == NULL) { 3589*d74001adSXin LI arcmsr_free_resource(acb); 3590*d74001adSXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 3591*d74001adSXin LI return ENOMEM; 3592*d74001adSXin LI } 3593*d74001adSXin LI if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 3594*d74001adSXin LI arcmsr_free_resource(acb); 3595*d74001adSXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 3596*d74001adSXin LI return ENXIO; 3597*d74001adSXin LI } 3598*d74001adSXin LI mem_base0=(vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 3599*d74001adSXin LI if(mem_base0==0) { 3600*d74001adSXin LI arcmsr_free_resource(acb); 3601*d74001adSXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 3602*d74001adSXin LI return ENXIO; 3603*d74001adSXin LI } 3604*d74001adSXin LI acb->btag[0]=rman_get_bustag(acb->sys_res_arcmsr[0]); 3605*d74001adSXin LI acb->bhandle[0]=rman_get_bushandle(acb->sys_res_arcmsr[0]); 3606*d74001adSXin LI acb->pmu=(struct MessageUnit_UNION *)mem_base0; 3607*d74001adSXin LI } 3608*d74001adSXin LI break; 360944f05562SScott Long } 3610ad6d6297SScott Long if(acb->acb_flags & ACB_F_MAPFREESRB_FAILD) { 3611ad6d6297SScott Long arcmsr_free_resource(acb); 361244f05562SScott Long printf("arcmsr%d: map free srb failure!\n", device_get_unit(dev)); 3613f1c579b1SScott Long return ENXIO; 3614f1c579b1SScott Long } 3615*d74001adSXin LI acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_RQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ); 3616ad6d6297SScott Long acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; 3617ad6d6297SScott Long /* 3618ad6d6297SScott Long ******************************************************************** 3619ad6d6297SScott Long ** init raid volume state 3620ad6d6297SScott Long ******************************************************************** 3621ad6d6297SScott Long */ 3622ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_TARGETID;i++) { 3623ad6d6297SScott Long for(j=0;j<ARCMSR_MAX_TARGETLUN;j++) { 362444f05562SScott Long acb->devstate[i][j]=ARECA_RAID_GONE; 3625ad6d6297SScott Long } 3626ad6d6297SScott Long } 3627ad6d6297SScott Long arcmsr_iop_init(acb); 3628f1c579b1SScott Long return(0); 3629f1c579b1SScott Long } 3630f1c579b1SScott Long /* 3631f1c579b1SScott Long ************************************************************************ 3632f1c579b1SScott Long ************************************************************************ 3633f1c579b1SScott Long */ 3634f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev) 3635f1c579b1SScott Long { 3636ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 3637ad6d6297SScott Long u_int32_t unit=device_get_unit(dev); 3638f1c579b1SScott Long struct ccb_setasync csa; 3639f1c579b1SScott Long struct cam_devq *devq; /* Device Queue to use for this SIM */ 3640f1c579b1SScott Long struct resource *irqres; 3641f1c579b1SScott Long int rid; 3642f1c579b1SScott Long 3643ad6d6297SScott Long if(acb == NULL) { 3644ad6d6297SScott Long printf("arcmsr%d: cannot allocate softc\n", unit); 3645ad6d6297SScott Long return (ENOMEM); 3646ad6d6297SScott Long } 36475878cbecSScott Long ARCMSR_LOCK_INIT(&acb->qbuffer_lock, "arcmsr Q buffer lock"); 3648ad6d6297SScott Long if(arcmsr_initialize(dev)) { 3649ad6d6297SScott Long printf("arcmsr%d: initialize failure!\n", unit); 36505878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3651f1c579b1SScott Long return ENXIO; 3652f1c579b1SScott Long } 3653f1c579b1SScott Long /* After setting up the adapter, map our interrupt */ 3654f1c579b1SScott Long rid=0; 3655ad6d6297SScott Long irqres=bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE); 3656ad6d6297SScott Long if(irqres == NULL || 365744f05562SScott Long #if __FreeBSD_version >= 700025 3658*d74001adSXin LI bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, NULL, arcmsr_intr_handler, acb, &acb->ih)) { 365944f05562SScott Long #else 3660*d74001adSXin LI bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, arcmsr_intr_handler, acb, &acb->ih)) { 366144f05562SScott Long #endif 3662ad6d6297SScott Long arcmsr_free_resource(acb); 36635878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3664f1c579b1SScott Long printf("arcmsr%d: unable to register interrupt handler!\n", unit); 3665f1c579b1SScott Long return ENXIO; 3666f1c579b1SScott Long } 3667ad6d6297SScott Long acb->irqres=irqres; 3668ad6d6297SScott Long acb->pci_dev=dev; 3669ad6d6297SScott Long acb->pci_unit=unit; 3670f1c579b1SScott Long /* 3671f1c579b1SScott Long * Now let the CAM generic SCSI layer find the SCSI devices on 3672f1c579b1SScott Long * the bus * start queue to reset to the idle loop. * 3673f1c579b1SScott Long * Create device queue of SIM(s) * (MAX_START_JOB - 1) : 3674f1c579b1SScott Long * max_sim_transactions 3675f1c579b1SScott Long */ 3676f1c579b1SScott Long devq=cam_simq_alloc(ARCMSR_MAX_START_JOB); 3677ad6d6297SScott Long if(devq == NULL) { 3678ad6d6297SScott Long arcmsr_free_resource(acb); 3679ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 36805878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3681ad6d6297SScott Long printf("arcmsr%d: cam_simq_alloc failure!\n", unit); 3682f1c579b1SScott Long return ENXIO; 3683f1c579b1SScott Long } 368444f05562SScott Long #if __FreeBSD_version >= 700025 3685*d74001adSXin LI acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, &acb->qbuffer_lock, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq); 368644f05562SScott Long #else 3687*d74001adSXin LI acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq); 368844f05562SScott Long #endif 3689ad6d6297SScott Long if(acb->psim == NULL) { 3690ad6d6297SScott Long arcmsr_free_resource(acb); 3691ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 3692f1c579b1SScott Long cam_simq_free(devq); 36935878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3694ad6d6297SScott Long printf("arcmsr%d: cam_sim_alloc failure!\n", unit); 3695f1c579b1SScott Long return ENXIO; 3696f1c579b1SScott Long } 36975878cbecSScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 3698f40b4cabSScott Long #if __FreeBSD_version >= 700044 3699b50569b7SScott Long if(xpt_bus_register(acb->psim, dev, 0) != CAM_SUCCESS) { 370044f05562SScott Long #else 370144f05562SScott Long if(xpt_bus_register(acb->psim, 0) != CAM_SUCCESS) { 370244f05562SScott Long #endif 3703ad6d6297SScott Long arcmsr_free_resource(acb); 3704ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 3705ad6d6297SScott Long cam_sim_free(acb->psim, /*free_devq*/TRUE); 37065878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3707ad6d6297SScott Long printf("arcmsr%d: xpt_bus_register failure!\n", unit); 3708f1c579b1SScott Long return ENXIO; 3709f1c579b1SScott Long } 3710*d74001adSXin LI if(xpt_create_path(&acb->ppath, /* periph */ NULL, cam_sim_path(acb->psim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 3711ad6d6297SScott Long arcmsr_free_resource(acb); 3712ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 3713ad6d6297SScott Long xpt_bus_deregister(cam_sim_path(acb->psim)); 3714ad6d6297SScott Long cam_sim_free(acb->psim, /* free_simq */ TRUE); 37155878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3716ad6d6297SScott Long printf("arcmsr%d: xpt_create_path failure!\n", unit); 3717f1c579b1SScott Long return ENXIO; 3718f1c579b1SScott Long } 3719f1c579b1SScott Long /* 3720f1c579b1SScott Long **************************************************** 3721f1c579b1SScott Long */ 3722ad6d6297SScott Long xpt_setup_ccb(&csa.ccb_h, acb->ppath, /*priority*/5); 3723f1c579b1SScott Long csa.ccb_h.func_code=XPT_SASYNC_CB; 3724f1c579b1SScott Long csa.event_enable=AC_FOUND_DEVICE|AC_LOST_DEVICE; 3725f1c579b1SScott Long csa.callback=arcmsr_async; 3726ad6d6297SScott Long csa.callback_arg=acb->psim; 3727f1c579b1SScott Long xpt_action((union ccb *)&csa); 37285878cbecSScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 3729f1c579b1SScott Long /* Create the control device. */ 3730*d74001adSXin LI acb->ioctl_dev=make_dev(&arcmsr_cdevsw, unit, UID_ROOT, GID_WHEEL /* GID_OPERATOR */, S_IRUSR | S_IWUSR, "arcmsr%d", unit); 3731*d74001adSXin LI 3732f1c579b1SScott Long #if __FreeBSD_version < 503000 3733ad6d6297SScott Long acb->ioctl_dev->si_drv1=acb; 3734f1c579b1SScott Long #endif 3735f1c579b1SScott Long #if __FreeBSD_version > 500005 3736ad6d6297SScott Long (void)make_dev_alias(acb->ioctl_dev, "arc%d", unit); 3737f1c579b1SScott Long #endif 3738*d74001adSXin LI #if __FreeBSD_version > 500000 3739*d74001adSXin LI callout_init(&acb->devmap_callout, /*mpsafe*/1); 3740*d74001adSXin LI #else 3741*d74001adSXin LI callout_init(&acb->devmap_callout); 3742*d74001adSXin LI #endif 3743*d74001adSXin LI callout_reset(&acb->devmap_callout, 60 * hz, arcmsr_polling_devmap, acb); 3744f1c579b1SScott Long return 0; 3745f1c579b1SScott Long } 3746f1c579b1SScott Long /* 3747f1c579b1SScott Long ************************************************************************ 3748f1c579b1SScott Long ************************************************************************ 3749f1c579b1SScott Long */ 3750f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev) 3751f1c579b1SScott Long { 3752ad6d6297SScott Long u_int32_t id; 3753ad6d6297SScott Long static char buf[256]; 3754ad6d6297SScott Long char *type; 3755ad6d6297SScott Long int raid6 = 1; 3756ad6d6297SScott Long 3757ad6d6297SScott Long if (pci_get_vendor(dev) != PCI_VENDOR_ID_ARECA) { 3758ad6d6297SScott Long return (ENXIO); 3759ad6d6297SScott Long } 3760ad6d6297SScott Long switch(id=pci_get_devid(dev)) { 3761f1c579b1SScott Long case PCIDevVenIDARC1110: 3762f1c579b1SScott Long case PCIDevVenIDARC1210: 376344f05562SScott Long case PCIDevVenIDARC1201: 3764ad6d6297SScott Long raid6 = 0; 3765ad6d6297SScott Long /*FALLTHRU*/ 3766ad6d6297SScott Long case PCIDevVenIDARC1120: 3767ad6d6297SScott Long case PCIDevVenIDARC1130: 3768ad6d6297SScott Long case PCIDevVenIDARC1160: 3769ad6d6297SScott Long case PCIDevVenIDARC1170: 3770f1c579b1SScott Long case PCIDevVenIDARC1220: 3771f1c579b1SScott Long case PCIDevVenIDARC1230: 3772f1c579b1SScott Long case PCIDevVenIDARC1260: 3773ad6d6297SScott Long case PCIDevVenIDARC1270: 3774ad6d6297SScott Long case PCIDevVenIDARC1280: 3775ad6d6297SScott Long type = "SATA"; 3776ad6d6297SScott Long break; 3777*d74001adSXin LI case PCIDevVenIDARC1212: 3778*d74001adSXin LI case PCIDevVenIDARC1222: 3779ad6d6297SScott Long case PCIDevVenIDARC1380: 3780ad6d6297SScott Long case PCIDevVenIDARC1381: 3781ad6d6297SScott Long case PCIDevVenIDARC1680: 3782ad6d6297SScott Long case PCIDevVenIDARC1681: 3783*d74001adSXin LI type = "SAS 3G"; 3784*d74001adSXin LI break; 3785*d74001adSXin LI case PCIDevVenIDARC1880: 3786*d74001adSXin LI type = "SAS 6G"; 3787ad6d6297SScott Long break; 3788ad6d6297SScott Long default: 3789ad6d6297SScott Long type = "X-TYPE"; 3790ad6d6297SScott Long break; 3791f1c579b1SScott Long } 3792ad6d6297SScott Long sprintf(buf, "Areca %s Host Adapter RAID Controller %s\n", type, raid6 ? "(RAID6 capable)" : ""); 3793ad6d6297SScott Long device_set_desc_copy(dev, buf); 3794ad6d6297SScott Long return 0; 3795f1c579b1SScott Long } 3796f1c579b1SScott Long /* 3797f1c579b1SScott Long ************************************************************************ 3798f1c579b1SScott Long ************************************************************************ 3799f1c579b1SScott Long */ 3800f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev) 3801f1c579b1SScott Long { 380244f05562SScott Long u_int32_t i; 3803ad6d6297SScott Long u_int32_t intmask_org; 3804ad6d6297SScott Long struct CommandControlBlock *srb; 3805ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 3806f1c579b1SScott Long 3807f1c579b1SScott Long /* stop adapter background rebuild */ 38085878cbecSScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 380944f05562SScott Long /* disable all outbound interrupt */ 381044f05562SScott Long intmask_org=arcmsr_disable_allintr(acb); 3811ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 3812ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 3813f1c579b1SScott Long /* abort all outstanding command */ 3814ad6d6297SScott Long acb->acb_flags |= ACB_F_SCSISTOPADAPTER; 3815ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOP_INITED; 3816ad6d6297SScott Long if(acb->srboutstandingcount!=0) { 381744f05562SScott Long /*clear and abort all outbound posted Q*/ 381844f05562SScott Long arcmsr_done4abort_postqueue(acb); 381944f05562SScott Long /* talk to iop 331 outstanding command aborted*/ 3820ad6d6297SScott Long arcmsr_abort_allcmd(acb); 3821ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 3822ad6d6297SScott Long srb=acb->psrb_pool[i]; 3823ad6d6297SScott Long if(srb->startdone==ARCMSR_SRB_START) { 3824ad6d6297SScott Long srb->startdone=ARCMSR_SRB_ABORTED; 3825ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 3826ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 3827f1c579b1SScott Long } 3828f1c579b1SScott Long } 3829f1c579b1SScott Long } 3830ad6d6297SScott Long atomic_set_int(&acb->srboutstandingcount, 0); 3831ad6d6297SScott Long acb->workingsrb_doneindex=0; 3832ad6d6297SScott Long acb->workingsrb_startindex=0; 38335878cbecSScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 3834f2aa0e9fSWarner Losh return (0); 3835f1c579b1SScott Long } 3836f1c579b1SScott Long /* 3837f1c579b1SScott Long ************************************************************************ 3838f1c579b1SScott Long ************************************************************************ 3839f1c579b1SScott Long */ 3840f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev) 3841f1c579b1SScott Long { 3842ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 384344f05562SScott Long int i; 3844f1c579b1SScott Long 3845*d74001adSXin LI callout_stop(&acb->devmap_callout); 38465878cbecSScott Long bus_teardown_intr(dev, acb->irqres, acb->ih); 3847f1c579b1SScott Long arcmsr_shutdown(dev); 3848ad6d6297SScott Long arcmsr_free_resource(acb); 384944f05562SScott Long for(i=0; (acb->sys_res_arcmsr[i]!=NULL) && (i<2); i++) { 385044f05562SScott Long bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(i), acb->sys_res_arcmsr[i]); 385144f05562SScott Long } 3852ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 38535878cbecSScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 3854ad6d6297SScott Long xpt_async(AC_LOST_DEVICE, acb->ppath, NULL); 3855ad6d6297SScott Long xpt_free_path(acb->ppath); 3856ad6d6297SScott Long xpt_bus_deregister(cam_sim_path(acb->psim)); 3857ad6d6297SScott Long cam_sim_free(acb->psim, TRUE); 38585878cbecSScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 38595878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3860f1c579b1SScott Long return (0); 3861f1c579b1SScott Long } 3862f1c579b1SScott Long 3863f1c579b1SScott Long 3864