1f1c579b1SScott Long /* 246a7789eSMatt Jacob ***************************************************************************************** 3f1c579b1SScott Long ** O.S : FreeBSD 4f1c579b1SScott Long ** FILE NAME : arcmsr.c 5d74001adSXin LI ** BY : Erich Chen, Ching Huang 6f1c579b1SScott Long ** Description: SCSI RAID Device Driver for 7d74001adSXin 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 ** 13d74001adSXin 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 41*22f2616bSXin LI ** 1.00.00.00 03/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 43*22f2616bSXin LI ** 1.20.00.03 04/19/2005 Erich Chen add SATA 24 Ports adapter type support 44ad6d6297SScott Long ** clean unused function 45*22f2616bSXin LI ** 1.20.00.12 09/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 50*22f2616bSXin LI ** 1.20.00.13 08/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 60d74001adSXin LI ** 1.20.00.17 07/15/2010 Ching Huang Added support ARC1880 61d74001adSXin LI ** report CAM_DEV_NOT_THERE instead of CAM_SEL_TIMEOUT when device failed, 62d74001adSXin LI ** prevent cam_periph_error removing all LUN devices of one Target id 63d74001adSXin LI ** for any one LUN device failed 64231c8b71SXin LI ** 1.20.00.18 10/14/2010 Ching Huang Fixed "inquiry data fails comparion at DV1 step" 65231c8b71SXin LI ** 10/25/2010 Ching Huang Fixed bad range input in bus_alloc_resource for ADAPTER_TYPE_B 66231c8b71SXin LI ** 1.20.00.19 11/11/2010 Ching Huang Fixed arcmsr driver prevent arcsas support for Areca SAS HBA ARC13x0 67*22f2616bSXin LI ** 1.20.00.20 12/08/2010 Ching Huang Avoid calling atomic_set_int function 68*22f2616bSXin LI ** 1.20.00.21 02/08/2011 Ching Huang Implement I/O request timeout 69*22f2616bSXin LI ** 02/14/2011 Ching Huang Modified pktRequestCount 70*22f2616bSXin LI ** 1.20.00.21 03/03/2011 Ching Huang if a command timeout, then wait its ccb back before free it 71f1c579b1SScott Long ****************************************************************************************** 72ad6d6297SScott Long * $FreeBSD$ 73f1c579b1SScott Long */ 74*22f2616bSXin LI #if 0 75*22f2616bSXin LI #define ARCMSR_DEBUG1 1 76*22f2616bSXin LI #endif 77f1c579b1SScott Long #include <sys/param.h> 78f1c579b1SScott Long #include <sys/systm.h> 79f1c579b1SScott Long #include <sys/malloc.h> 80f1c579b1SScott Long #include <sys/kernel.h> 81f1c579b1SScott Long #include <sys/bus.h> 82f1c579b1SScott Long #include <sys/queue.h> 83f1c579b1SScott Long #include <sys/stat.h> 84f1c579b1SScott Long #include <sys/devicestat.h> 85f1c579b1SScott Long #include <sys/kthread.h> 86f1c579b1SScott Long #include <sys/module.h> 87f1c579b1SScott Long #include <sys/proc.h> 88f1c579b1SScott Long #include <sys/lock.h> 89f1c579b1SScott Long #include <sys/sysctl.h> 90f1c579b1SScott Long #include <sys/poll.h> 91f1c579b1SScott Long #include <sys/ioccom.h> 92f1c579b1SScott Long #include <vm/vm.h> 93f1c579b1SScott Long #include <vm/vm_param.h> 94f1c579b1SScott Long #include <vm/pmap.h> 95f1c579b1SScott Long 96f1c579b1SScott Long #include <isa/rtc.h> 97f1c579b1SScott Long 98f1c579b1SScott Long #include <machine/bus.h> 99f1c579b1SScott Long #include <machine/resource.h> 100f1c579b1SScott Long #include <machine/atomic.h> 101f1c579b1SScott Long #include <sys/conf.h> 102f1c579b1SScott Long #include <sys/rman.h> 103f1c579b1SScott Long 104f1c579b1SScott Long #include <cam/cam.h> 105f1c579b1SScott Long #include <cam/cam_ccb.h> 106f1c579b1SScott Long #include <cam/cam_sim.h> 107d74001adSXin LI #include <cam/cam_periph.h> 108d74001adSXin LI #include <cam/cam_xpt_periph.h> 109f1c579b1SScott Long #include <cam/cam_xpt_sim.h> 110f1c579b1SScott Long #include <cam/cam_debug.h> 111f1c579b1SScott Long #include <cam/scsi/scsi_all.h> 112f1c579b1SScott Long #include <cam/scsi/scsi_message.h> 113f1c579b1SScott Long /* 114f1c579b1SScott Long ************************************************************************** 115f1c579b1SScott Long ************************************************************************** 116f1c579b1SScott Long */ 117f1c579b1SScott Long #if __FreeBSD_version >= 500005 118f1c579b1SScott Long #include <sys/selinfo.h> 119f1c579b1SScott Long #include <sys/mutex.h> 120ad6d6297SScott Long #include <sys/endian.h> 121f1c579b1SScott Long #include <dev/pci/pcivar.h> 122f1c579b1SScott Long #include <dev/pci/pcireg.h> 123579ec1a5SScott Long #define ARCMSR_LOCK_INIT(l, s) mtx_init(l, s, NULL, MTX_DEF) 1245878cbecSScott Long #define ARCMSR_LOCK_DESTROY(l) mtx_destroy(l) 125f1c579b1SScott Long #define ARCMSR_LOCK_ACQUIRE(l) mtx_lock(l) 126f1c579b1SScott Long #define ARCMSR_LOCK_RELEASE(l) mtx_unlock(l) 127ad6d6297SScott Long #define ARCMSR_LOCK_TRY(l) mtx_trylock(l) 128ad6d6297SScott Long #define arcmsr_htole32(x) htole32(x) 129f1c579b1SScott Long typedef struct mtx arcmsr_lock_t; 130f1c579b1SScott Long #else 131f1c579b1SScott Long #include <sys/select.h> 132f1c579b1SScott Long #include <pci/pcivar.h> 133f1c579b1SScott Long #include <pci/pcireg.h> 134f1c579b1SScott Long #define ARCMSR_LOCK_INIT(l, s) simple_lock_init(l) 1355878cbecSScott Long #define ARCMSR_LOCK_DESTROY(l) 136f1c579b1SScott Long #define ARCMSR_LOCK_ACQUIRE(l) simple_lock(l) 137f1c579b1SScott Long #define ARCMSR_LOCK_RELEASE(l) simple_unlock(l) 138ad6d6297SScott Long #define ARCMSR_LOCK_TRY(l) simple_lock_try(l) 139ad6d6297SScott Long #define arcmsr_htole32(x) (x) 140f1c579b1SScott Long typedef struct simplelock arcmsr_lock_t; 141f1c579b1SScott Long #endif 14244f05562SScott Long 14344f05562SScott Long #if !defined(CAM_NEW_TRAN_CODE) && __FreeBSD_version >= 700025 14444f05562SScott Long #define CAM_NEW_TRAN_CODE 1 14544f05562SScott Long #endif 14644f05562SScott Long 147*22f2616bSXin LI #if __FreeBSD_version > 500000 148*22f2616bSXin LI #define arcmsr_callout_init(a) callout_init(a, /*mpsafe*/1); 149*22f2616bSXin LI #else 150*22f2616bSXin LI #define arcmsr_callout_init(a) callout_init(a); 151*22f2616bSXin LI #endif 152*22f2616bSXin LI 153*22f2616bSXin LI #define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.21 2010-03-03" 154f1c579b1SScott Long #include <dev/arcmsr/arcmsr.h> 155*22f2616bSXin LI #define SRB_SIZE ((sizeof(struct CommandControlBlock)+0x1f) & 0xffe0) 156*22f2616bSXin LI #define ARCMSR_SRBS_POOL_SIZE (SRB_SIZE * ARCMSR_MAX_FREESRB_NUM) 157f1c579b1SScott Long /* 158f1c579b1SScott Long ************************************************************************** 159f1c579b1SScott Long ************************************************************************** 160f1c579b1SScott Long */ 16144f05562SScott Long #define CHIP_REG_READ32(s, b, r) bus_space_read_4(acb->btag[b], acb->bhandle[b], offsetof(struct s, r)) 16244f05562SScott Long #define CHIP_REG_WRITE32(s, b, r, d) bus_space_write_4(acb->btag[b], acb->bhandle[b], offsetof(struct s, r), d) 163f1c579b1SScott Long /* 164f1c579b1SScott Long ************************************************************************** 165f1c579b1SScott Long ************************************************************************** 166f1c579b1SScott Long */ 167*22f2616bSXin LI static void arcmsr_free_srb(struct CommandControlBlock *srb); 168ad6d6297SScott Long static struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb); 169ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb); 170f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev); 171f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev); 172f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev); 173ad6d6297SScott Long static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg); 174ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb); 175f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev); 17644f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb); 177ad6d6297SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb); 178ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb); 179ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb); 180ad6d6297SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); 181ad6d6297SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb); 182ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb); 183ad6d6297SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb); 18444f05562SScott Long static void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb); 185ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb); 186ad6d6297SScott Long static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag); 187ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb); 188ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb); 189ad6d6297SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t * dm_segs, u_int32_t nseg); 190ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb); 191ad6d6297SScott Long static int arcmsr_resume(device_t dev); 192ad6d6297SScott Long static int arcmsr_suspend(device_t dev); 193d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb); 194d74001adSXin LI static void arcmsr_polling_devmap(void* arg); 195*22f2616bSXin LI static void arcmsr_srb_timeout(void* arg); 196*22f2616bSXin LI #ifdef ARCMSR_DEBUG1 197*22f2616bSXin LI static void arcmsr_dump_data(struct AdapterControlBlock *acb); 198*22f2616bSXin LI #endif 199f1c579b1SScott Long /* 200f1c579b1SScott Long ************************************************************************** 201ad6d6297SScott Long ************************************************************************** 202ad6d6297SScott Long */ 203ad6d6297SScott Long static void UDELAY(u_int32_t us) { DELAY(us); } 204ad6d6297SScott Long /* 205ad6d6297SScott Long ************************************************************************** 206f1c579b1SScott Long ************************************************************************** 207f1c579b1SScott Long */ 208231c8b71SXin LI static bus_dmamap_callback_t arcmsr_map_free_srb; 209231c8b71SXin LI static bus_dmamap_callback_t arcmsr_execute_srb; 210f1c579b1SScott Long /* 211f1c579b1SScott Long ************************************************************************** 212f1c579b1SScott Long ************************************************************************** 213f1c579b1SScott Long */ 214f1c579b1SScott Long static d_open_t arcmsr_open; 215f1c579b1SScott Long static d_close_t arcmsr_close; 216f1c579b1SScott Long static d_ioctl_t arcmsr_ioctl; 217f1c579b1SScott Long 218f1c579b1SScott Long static device_method_t arcmsr_methods[]={ 219f1c579b1SScott Long DEVMETHOD(device_probe, arcmsr_probe), 220f1c579b1SScott Long DEVMETHOD(device_attach, arcmsr_attach), 221f1c579b1SScott Long DEVMETHOD(device_detach, arcmsr_detach), 222f1c579b1SScott Long DEVMETHOD(device_shutdown, arcmsr_shutdown), 223ad6d6297SScott Long DEVMETHOD(device_suspend, arcmsr_suspend), 224ad6d6297SScott Long DEVMETHOD(device_resume, arcmsr_resume), 225ad6d6297SScott Long DEVMETHOD(bus_print_child, bus_generic_print_child), 226ad6d6297SScott Long DEVMETHOD(bus_driver_added, bus_generic_driver_added), 227f1c579b1SScott Long { 0, 0 } 228f1c579b1SScott Long }; 229f1c579b1SScott Long 230f1c579b1SScott Long static driver_t arcmsr_driver={ 231ad6d6297SScott Long "arcmsr", arcmsr_methods, sizeof(struct AdapterControlBlock) 232f1c579b1SScott Long }; 233f1c579b1SScott Long 234f1c579b1SScott Long static devclass_t arcmsr_devclass; 235f1c579b1SScott Long DRIVER_MODULE(arcmsr, pci, arcmsr_driver, arcmsr_devclass, 0, 0); 236d3cf342dSScott Long MODULE_DEPEND(arcmsr, pci, 1, 1, 1); 237d3cf342dSScott Long MODULE_DEPEND(arcmsr, cam, 1, 1, 1); 238ad6d6297SScott Long #ifndef BUS_DMA_COHERENT 239ad6d6297SScott Long #define BUS_DMA_COHERENT 0x04 /* hint: map memory in a coherent way */ 240ad6d6297SScott Long #endif 241ad6d6297SScott Long #if __FreeBSD_version >= 501000 242f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw={ 243*22f2616bSXin LI #if __FreeBSD_version >= 503000 244f1c579b1SScott Long .d_version = D_VERSION, 245ad6d6297SScott Long #endif 246*22f2616bSXin LI #if (__FreeBSD_version>=503000 && __FreeBSD_version<600034) 247f1c579b1SScott Long .d_flags = D_NEEDGIANT, 248*22f2616bSXin LI #endif 249f1c579b1SScott Long .d_open = arcmsr_open, /* open */ 250f1c579b1SScott Long .d_close = arcmsr_close, /* close */ 251f1c579b1SScott Long .d_ioctl = arcmsr_ioctl, /* ioctl */ 252f1c579b1SScott Long .d_name = "arcmsr", /* name */ 253f1c579b1SScott Long }; 254f1c579b1SScott Long #else 255f1c579b1SScott Long #define ARCMSR_CDEV_MAJOR 180 256f1c579b1SScott Long 257f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw = { 258f1c579b1SScott Long arcmsr_open, /* open */ 259f1c579b1SScott Long arcmsr_close, /* close */ 260f1c579b1SScott Long noread, /* read */ 261f1c579b1SScott Long nowrite, /* write */ 262f1c579b1SScott Long arcmsr_ioctl, /* ioctl */ 263f1c579b1SScott Long nopoll, /* poll */ 264f1c579b1SScott Long nommap, /* mmap */ 265f1c579b1SScott Long nostrategy, /* strategy */ 266f1c579b1SScott Long "arcmsr", /* name */ 267f1c579b1SScott Long ARCMSR_CDEV_MAJOR, /* major */ 268f1c579b1SScott Long nodump, /* dump */ 269f1c579b1SScott Long nopsize, /* psize */ 270f1c579b1SScott Long 0 /* flags */ 271f1c579b1SScott Long }; 272f1c579b1SScott Long #endif 273d74001adSXin LI /* 274d74001adSXin LI ************************************************************************** 275d74001adSXin LI ************************************************************************** 276d74001adSXin LI */ 277f1c579b1SScott Long #if __FreeBSD_version < 500005 278f1c579b1SScott Long static int arcmsr_open(dev_t dev, int flags, int fmt, struct proc *proc) 279f1c579b1SScott Long #else 280f1c579b1SScott Long #if __FreeBSD_version < 503000 281f1c579b1SScott Long static int arcmsr_open(dev_t dev, int flags, int fmt, struct thread *proc) 282f1c579b1SScott Long #else 28300b4e54aSWarner Losh static int arcmsr_open(struct cdev *dev, int flags, int fmt, struct thread *proc) 284f1c579b1SScott Long #endif 285f1c579b1SScott Long #endif 286f1c579b1SScott Long { 287f1c579b1SScott Long #if __FreeBSD_version < 503000 288ad6d6297SScott Long struct AdapterControlBlock *acb=dev->si_drv1; 289f1c579b1SScott Long #else 2906bfa9a2dSEd Schouten int unit = dev2unit(dev); 291ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 292f1c579b1SScott Long #endif 293ad6d6297SScott Long if(acb==NULL) { 294f1c579b1SScott Long return ENXIO; 295f1c579b1SScott Long } 296f1c579b1SScott Long return 0; 297f1c579b1SScott Long } 298f1c579b1SScott Long /* 299f1c579b1SScott Long ************************************************************************** 300f1c579b1SScott Long ************************************************************************** 301f1c579b1SScott Long */ 302f1c579b1SScott Long #if __FreeBSD_version < 500005 303f1c579b1SScott Long static int arcmsr_close(dev_t dev, int flags, int fmt, struct proc *proc) 304f1c579b1SScott Long #else 305f1c579b1SScott Long #if __FreeBSD_version < 503000 306f1c579b1SScott Long static int arcmsr_close(dev_t dev, int flags, int fmt, struct thread *proc) 307f1c579b1SScott Long #else 30800b4e54aSWarner Losh static int arcmsr_close(struct cdev *dev, int flags, int fmt, struct thread *proc) 309f1c579b1SScott Long #endif 310f1c579b1SScott Long #endif 311f1c579b1SScott Long { 312f1c579b1SScott Long #if __FreeBSD_version < 503000 313ad6d6297SScott Long struct AdapterControlBlock *acb=dev->si_drv1; 314f1c579b1SScott Long #else 3156bfa9a2dSEd Schouten int unit = dev2unit(dev); 316ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 317f1c579b1SScott Long #endif 318ad6d6297SScott Long if(acb==NULL) { 319f1c579b1SScott Long return ENXIO; 320f1c579b1SScott Long } 321f1c579b1SScott Long return 0; 322f1c579b1SScott Long } 323f1c579b1SScott Long /* 324f1c579b1SScott Long ************************************************************************** 325f1c579b1SScott Long ************************************************************************** 326f1c579b1SScott Long */ 327f1c579b1SScott Long #if __FreeBSD_version < 500005 328f1c579b1SScott Long static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct proc *proc) 329f1c579b1SScott Long #else 330f1c579b1SScott Long #if __FreeBSD_version < 503000 331f1c579b1SScott Long static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc) 332f1c579b1SScott Long #else 33300b4e54aSWarner Losh static int arcmsr_ioctl(struct cdev *dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc) 334f1c579b1SScott Long #endif 335f1c579b1SScott Long #endif 336f1c579b1SScott Long { 337f1c579b1SScott Long #if __FreeBSD_version < 503000 338ad6d6297SScott Long struct AdapterControlBlock *acb=dev->si_drv1; 339f1c579b1SScott Long #else 3406bfa9a2dSEd Schouten int unit = dev2unit(dev); 341ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 342f1c579b1SScott Long #endif 343f1c579b1SScott Long 344ad6d6297SScott Long if(acb==NULL) { 345f1c579b1SScott Long return ENXIO; 346f1c579b1SScott Long } 347ad6d6297SScott Long return(arcmsr_iop_ioctlcmd(acb, ioctl_cmd, arg)); 348f1c579b1SScott Long } 349f1c579b1SScott Long /* 35044f05562SScott Long ********************************************************************** 35144f05562SScott Long ********************************************************************** 35244f05562SScott Long */ 35344f05562SScott Long static u_int32_t arcmsr_disable_allintr( struct AdapterControlBlock *acb) 35444f05562SScott Long { 35544f05562SScott Long u_int32_t intmask_org=0; 35644f05562SScott Long 35744f05562SScott Long switch (acb->adapter_type) { 35844f05562SScott Long case ACB_ADAPTER_TYPE_A: { 35944f05562SScott Long /* disable all outbound interrupt */ 360d74001adSXin LI intmask_org=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intmask); /* disable outbound message0 int */ 361d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); 36244f05562SScott Long } 36344f05562SScott Long break; 36444f05562SScott Long case ACB_ADAPTER_TYPE_B: { 36544f05562SScott Long /* disable all outbound interrupt */ 36644f05562SScott Long intmask_org=CHIP_REG_READ32(HBB_DOORBELL, 36744f05562SScott Long 0, iop2drv_doorbell_mask) & (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); /* disable outbound message0 int */ 368d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell_mask, 0); /* disable all interrupt */ 369d74001adSXin LI } 370d74001adSXin LI break; 371d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 372d74001adSXin LI /* disable all outbound interrupt */ 373d74001adSXin LI intmask_org=CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_mask) ; /* disable outbound message0 int */ 374d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org|ARCMSR_HBCMU_ALL_INTMASKENABLE); 37544f05562SScott Long } 37644f05562SScott Long break; 37744f05562SScott Long } 37844f05562SScott Long return(intmask_org); 37944f05562SScott Long } 38044f05562SScott Long /* 38144f05562SScott Long ********************************************************************** 38244f05562SScott Long ********************************************************************** 38344f05562SScott Long */ 38444f05562SScott Long static void arcmsr_enable_allintr( struct AdapterControlBlock *acb, u_int32_t intmask_org) 38544f05562SScott Long { 38644f05562SScott Long u_int32_t mask; 38744f05562SScott Long 38844f05562SScott Long switch (acb->adapter_type) { 38944f05562SScott Long case ACB_ADAPTER_TYPE_A: { 39044f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 391d74001adSXin LI mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE); 39244f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org & mask); 39344f05562SScott Long acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; 39444f05562SScott Long } 39544f05562SScott Long break; 39644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 397d74001adSXin LI /* enable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */ 398d74001adSXin LI mask=(ARCMSR_IOP2DRV_DATA_WRITE_OK|ARCMSR_IOP2DRV_DATA_READ_OK|ARCMSR_IOP2DRV_CDB_DONE|ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); 399d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell_mask, intmask_org | mask); /*1=interrupt enable, 0=interrupt disable*/ 40044f05562SScott Long acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f; 40144f05562SScott Long } 40244f05562SScott Long break; 403d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 404d74001adSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 405d74001adSXin LI mask=~(ARCMSR_HBCMU_UTILITY_A_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK); 406d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org & mask); 407d74001adSXin LI acb->outbound_int_enable= ~(intmask_org & mask) & 0x0000000f; 408d74001adSXin LI } 409d74001adSXin LI break; 41044f05562SScott Long } 41144f05562SScott Long return; 41244f05562SScott Long } 41344f05562SScott Long /* 41444f05562SScott Long ********************************************************************** 41544f05562SScott Long ********************************************************************** 41644f05562SScott Long */ 41744f05562SScott Long static u_int8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) 41844f05562SScott Long { 41944f05562SScott Long u_int32_t Index; 42044f05562SScott Long u_int8_t Retries=0x00; 42144f05562SScott Long 42244f05562SScott Long do { 42344f05562SScott Long for(Index=0; Index < 100; Index++) { 424d74001adSXin LI if(CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { 425d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/ 42644f05562SScott Long return TRUE; 42744f05562SScott Long } 42844f05562SScott Long UDELAY(10000); 42944f05562SScott Long }/*max 1 seconds*/ 43044f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 43144f05562SScott Long return FALSE; 43244f05562SScott Long } 43344f05562SScott Long /* 43444f05562SScott Long ********************************************************************** 43544f05562SScott Long ********************************************************************** 43644f05562SScott Long */ 43744f05562SScott Long static u_int8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) 43844f05562SScott Long { 43944f05562SScott Long u_int32_t Index; 44044f05562SScott Long u_int8_t Retries=0x00; 44144f05562SScott Long 44244f05562SScott Long do { 44344f05562SScott Long for(Index=0; Index < 100; Index++) { 444d74001adSXin LI if(CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { 445d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/ 446d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 447d74001adSXin LI return TRUE; 448d74001adSXin LI } 449d74001adSXin LI UDELAY(10000); 450d74001adSXin LI }/*max 1 seconds*/ 451d74001adSXin LI }while(Retries++ < 20);/*max 20 sec*/ 452d74001adSXin LI return FALSE; 453d74001adSXin LI } 454d74001adSXin LI /* 455d74001adSXin LI ********************************************************************** 456d74001adSXin LI ********************************************************************** 457d74001adSXin LI */ 458d74001adSXin LI static u_int8_t arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock *acb) 459d74001adSXin LI { 460d74001adSXin LI u_int32_t Index; 461d74001adSXin LI u_int8_t Retries=0x00; 462d74001adSXin LI 463d74001adSXin LI do { 464d74001adSXin LI for(Index=0; Index < 100; Index++) { 465d74001adSXin LI if(CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { 466d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);/*clear interrupt*/ 46744f05562SScott Long return TRUE; 46844f05562SScott Long } 46944f05562SScott Long UDELAY(10000); 47044f05562SScott Long }/*max 1 seconds*/ 47144f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 47244f05562SScott Long return FALSE; 47344f05562SScott Long } 47444f05562SScott Long /* 47544f05562SScott Long ************************************************************************ 47644f05562SScott Long ************************************************************************ 47744f05562SScott Long */ 47844f05562SScott Long static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) 47944f05562SScott Long { 48044f05562SScott Long int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */ 48144f05562SScott Long 482d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 48344f05562SScott Long do { 48444f05562SScott Long if(arcmsr_hba_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 */ 49644f05562SScott Long static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) 49744f05562SScott Long { 49844f05562SScott Long int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */ 49944f05562SScott Long 50044f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 50144f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_FLUSH_CACHE); 50244f05562SScott Long do { 50344f05562SScott Long if(arcmsr_hbb_wait_msgint_ready(acb)) { 50444f05562SScott Long break; 50544f05562SScott Long } else { 50644f05562SScott Long retry_count--; 50744f05562SScott Long } 50844f05562SScott Long }while(retry_count!=0); 50944f05562SScott Long return; 51044f05562SScott Long } 51144f05562SScott Long /* 51244f05562SScott Long ************************************************************************ 51344f05562SScott Long ************************************************************************ 51444f05562SScott Long */ 515d74001adSXin LI static void arcmsr_flush_hbc_cache(struct AdapterControlBlock *acb) 516d74001adSXin LI { 517d74001adSXin LI int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */ 518d74001adSXin LI 519d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 520d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 521d74001adSXin LI do { 522d74001adSXin LI if(arcmsr_hbc_wait_msgint_ready(acb)) { 523d74001adSXin LI break; 524d74001adSXin LI } else { 525d74001adSXin LI retry_count--; 526d74001adSXin LI } 527d74001adSXin LI }while(retry_count!=0); 528d74001adSXin LI return; 529d74001adSXin LI } 530d74001adSXin LI /* 531d74001adSXin LI ************************************************************************ 532d74001adSXin LI ************************************************************************ 533d74001adSXin LI */ 53444f05562SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) 53544f05562SScott Long { 53644f05562SScott Long switch (acb->adapter_type) { 53744f05562SScott Long case ACB_ADAPTER_TYPE_A: { 53844f05562SScott Long arcmsr_flush_hba_cache(acb); 53944f05562SScott Long } 54044f05562SScott Long break; 54144f05562SScott Long case ACB_ADAPTER_TYPE_B: { 54244f05562SScott Long arcmsr_flush_hbb_cache(acb); 54344f05562SScott Long } 54444f05562SScott Long break; 545d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 546d74001adSXin LI arcmsr_flush_hbc_cache(acb); 547d74001adSXin LI } 548d74001adSXin LI break; 54944f05562SScott Long } 55044f05562SScott Long return; 55144f05562SScott Long } 55244f05562SScott Long /* 553ad6d6297SScott Long ******************************************************************************* 554ad6d6297SScott Long ******************************************************************************* 555f1c579b1SScott Long */ 556ad6d6297SScott Long static int arcmsr_suspend(device_t dev) 557f1c579b1SScott Long { 558ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 559f1c579b1SScott Long 560ad6d6297SScott Long /* flush controller */ 561ad6d6297SScott Long arcmsr_iop_parking(acb); 562d74001adSXin LI /* disable all outbound interrupt */ 563d74001adSXin LI arcmsr_disable_allintr(acb); 564ad6d6297SScott Long return(0); 565ad6d6297SScott Long } 566ad6d6297SScott Long /* 567ad6d6297SScott Long ******************************************************************************* 568ad6d6297SScott Long ******************************************************************************* 569ad6d6297SScott Long */ 570ad6d6297SScott Long static int arcmsr_resume(device_t dev) 571ad6d6297SScott Long { 572ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 573f1c579b1SScott Long 574ad6d6297SScott Long arcmsr_iop_init(acb); 575ad6d6297SScott Long return(0); 576f1c579b1SScott Long } 577f1c579b1SScott Long /* 578f1c579b1SScott Long ********************************************************************************* 579f1c579b1SScott Long ********************************************************************************* 580f1c579b1SScott Long */ 581ad6d6297SScott Long static void arcmsr_async(void *cb_arg, u_int32_t code, struct cam_path *path, void *arg) 582f1c579b1SScott Long { 583ad6d6297SScott Long struct AdapterControlBlock *acb; 584ad6d6297SScott Long u_int8_t target_id, target_lun; 585f1c579b1SScott Long struct cam_sim * sim; 586f1c579b1SScott Long 587f1c579b1SScott Long sim=(struct cam_sim *) cb_arg; 588ad6d6297SScott Long acb =(struct AdapterControlBlock *) cam_sim_softc(sim); 589ad6d6297SScott Long switch (code) { 590f1c579b1SScott Long case AC_LOST_DEVICE: 591f1c579b1SScott Long target_id=xpt_path_target_id(path); 592f1c579b1SScott Long target_lun=xpt_path_lun_id(path); 593d74001adSXin LI if((target_id > ARCMSR_MAX_TARGETID) || (target_lun > ARCMSR_MAX_TARGETLUN)) { 594f1c579b1SScott Long break; 595f1c579b1SScott Long } 596d74001adSXin LI printf("%s:scsi id=%d lun=%d device lost \n", device_get_name(acb->pci_dev), target_id, target_lun); 597f1c579b1SScott Long break; 598f1c579b1SScott Long default: 599f1c579b1SScott Long break; 600f1c579b1SScott Long } 601f1c579b1SScott Long } 602f1c579b1SScott Long /* 603f1c579b1SScott Long ********************************************************************** 604f1c579b1SScott Long ********************************************************************** 605f1c579b1SScott Long */ 606ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb) 607f1c579b1SScott Long { 608ad6d6297SScott Long union ccb * pccb=srb->pccb; 609f1c579b1SScott Long 610ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 611ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 612ad6d6297SScott Long if(&pccb->csio.sense_data) { 613ad6d6297SScott Long memset(&pccb->csio.sense_data, 0, sizeof(pccb->csio.sense_data)); 614ad6d6297SScott Long memcpy(&pccb->csio.sense_data, srb->arcmsr_cdb.SenseData, 615ad6d6297SScott Long get_min(sizeof(struct SENSE_DATA), sizeof(pccb->csio.sense_data))); 616ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); /* Valid,ErrorCode */ 617f1c579b1SScott Long pccb->ccb_h.status |= CAM_AUTOSNS_VALID; 618f1c579b1SScott Long } 619f1c579b1SScott Long return; 620f1c579b1SScott Long } 621f1c579b1SScott Long /* 622f1c579b1SScott Long ********************************************************************* 62344f05562SScott Long ********************************************************************* 62444f05562SScott Long */ 62544f05562SScott Long static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) 62644f05562SScott Long { 62744f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 62844f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 629d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 63044f05562SScott Long } 63144f05562SScott Long return; 63244f05562SScott Long } 63344f05562SScott Long /* 63444f05562SScott Long ********************************************************************* 63544f05562SScott Long ********************************************************************* 63644f05562SScott Long */ 63744f05562SScott Long static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) 63844f05562SScott Long { 63944f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_ABORT_CMD); 64044f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 641d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 642d74001adSXin LI } 643d74001adSXin LI return; 644d74001adSXin LI } 645d74001adSXin LI /* 646d74001adSXin LI ********************************************************************* 647d74001adSXin LI ********************************************************************* 648d74001adSXin LI */ 649d74001adSXin LI static void arcmsr_abort_hbc_allcmd(struct AdapterControlBlock *acb) 650d74001adSXin LI { 651d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 652d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 653d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 654d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 65544f05562SScott Long } 65644f05562SScott Long return; 65744f05562SScott Long } 65844f05562SScott Long /* 65944f05562SScott Long ********************************************************************* 660f1c579b1SScott Long ********************************************************************* 661f1c579b1SScott Long */ 662ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) 663f1c579b1SScott Long { 66444f05562SScott Long switch (acb->adapter_type) { 66544f05562SScott Long case ACB_ADAPTER_TYPE_A: { 66644f05562SScott Long arcmsr_abort_hba_allcmd(acb); 66744f05562SScott Long } 66844f05562SScott Long break; 66944f05562SScott Long case ACB_ADAPTER_TYPE_B: { 67044f05562SScott Long arcmsr_abort_hbb_allcmd(acb); 67144f05562SScott Long } 67244f05562SScott Long break; 673d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 674d74001adSXin LI arcmsr_abort_hbc_allcmd(acb); 675d74001adSXin LI } 676d74001adSXin LI break; 67744f05562SScott Long } 67844f05562SScott Long return; 67944f05562SScott Long } 68044f05562SScott Long /* 681231c8b71SXin LI ********************************************************************** 682231c8b71SXin LI ********************************************************************** 683231c8b71SXin LI */ 684231c8b71SXin LI static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag) 685231c8b71SXin LI { 686231c8b71SXin LI struct AdapterControlBlock *acb=srb->acb; 687231c8b71SXin LI union ccb * pccb=srb->pccb; 688231c8b71SXin LI 689*22f2616bSXin LI if(srb->srb_flags & SRB_FLAG_TIMER_START) 690*22f2616bSXin LI callout_stop(&srb->ccb_callout); 691231c8b71SXin LI if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 692231c8b71SXin LI bus_dmasync_op_t op; 693231c8b71SXin LI 694231c8b71SXin LI if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 695231c8b71SXin LI op = BUS_DMASYNC_POSTREAD; 696231c8b71SXin LI } else { 697231c8b71SXin LI op = BUS_DMASYNC_POSTWRITE; 698231c8b71SXin LI } 699231c8b71SXin LI bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 700231c8b71SXin LI bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 701231c8b71SXin LI } 702231c8b71SXin LI if(stand_flag==1) { 703231c8b71SXin LI atomic_subtract_int(&acb->srboutstandingcount, 1); 704231c8b71SXin LI if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) && ( 705231c8b71SXin LI acb->srboutstandingcount < ARCMSR_RELEASE_SIMQ_LEVEL)) { 706231c8b71SXin LI acb->acb_flags &= ~ACB_F_CAM_DEV_QFRZN; 707231c8b71SXin LI pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 708231c8b71SXin LI } 709231c8b71SXin LI } 710*22f2616bSXin LI if(srb->srb_state != ARCMSR_SRB_TIMEOUT) 711*22f2616bSXin LI arcmsr_free_srb(srb); 712*22f2616bSXin LI #ifdef ARCMSR_DEBUG1 713*22f2616bSXin LI acb->pktReturnCount++; 714*22f2616bSXin LI #endif 715231c8b71SXin LI xpt_done(pccb); 716231c8b71SXin LI return; 717231c8b71SXin LI } 718231c8b71SXin LI /* 71944f05562SScott Long ************************************************************************** 72044f05562SScott Long ************************************************************************** 72144f05562SScott Long */ 722d74001adSXin LI static void arcmsr_report_srb_state(struct AdapterControlBlock *acb, struct CommandControlBlock *srb, u_int16_t error) 72344f05562SScott Long { 72444f05562SScott Long int target, lun; 72544f05562SScott Long 72644f05562SScott Long target=srb->pccb->ccb_h.target_id; 72744f05562SScott Long lun=srb->pccb->ccb_h.target_lun; 728d74001adSXin LI if(error == FALSE) { 72944f05562SScott Long if(acb->devstate[target][lun]==ARECA_RAID_GONE) { 73044f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GOOD; 73144f05562SScott Long } 73244f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_CMP; 73344f05562SScott Long arcmsr_srb_complete(srb, 1); 73444f05562SScott Long } else { 73544f05562SScott Long switch(srb->arcmsr_cdb.DeviceStatus) { 73644f05562SScott Long case ARCMSR_DEV_SELECT_TIMEOUT: { 73744f05562SScott Long if(acb->devstate[target][lun]==ARECA_RAID_GOOD) { 738d74001adSXin LI printf( "arcmsr%d: Target=%x, Lun=%x, selection timeout, raid volume was lost\n", acb->pci_unit, target, lun); 739ad6d6297SScott Long } 74044f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GONE; 741d74001adSXin LI srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 74244f05562SScott Long arcmsr_srb_complete(srb, 1); 74344f05562SScott Long } 74444f05562SScott Long break; 74544f05562SScott Long case ARCMSR_DEV_ABORTED: 74644f05562SScott Long case ARCMSR_DEV_INIT_FAIL: { 74744f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GONE; 74844f05562SScott Long srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 74944f05562SScott Long arcmsr_srb_complete(srb, 1); 75044f05562SScott Long } 75144f05562SScott Long break; 75244f05562SScott Long case SCSISTAT_CHECK_CONDITION: { 75344f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GOOD; 75444f05562SScott Long arcmsr_report_sense_info(srb); 75544f05562SScott Long arcmsr_srb_complete(srb, 1); 75644f05562SScott Long } 75744f05562SScott Long break; 75844f05562SScott Long default: 759d74001adSXin LI printf("arcmsr%d: scsi id=%d lun=%d isr got command error done,but got unknow DeviceStatus=0x%x \n" 760d74001adSXin LI , acb->pci_unit, target, lun ,srb->arcmsr_cdb.DeviceStatus); 76144f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GONE; 76244f05562SScott Long srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY; 76344f05562SScott Long /*unknow error or crc error just for retry*/ 76444f05562SScott Long arcmsr_srb_complete(srb, 1); 76544f05562SScott Long break; 76644f05562SScott Long } 76744f05562SScott Long } 76844f05562SScott Long return; 76944f05562SScott Long } 77044f05562SScott Long /* 77144f05562SScott Long ************************************************************************** 77244f05562SScott Long ************************************************************************** 77344f05562SScott Long */ 774d74001adSXin LI static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t flag_srb, u_int16_t error) 77544f05562SScott Long { 77644f05562SScott Long struct CommandControlBlock *srb; 77744f05562SScott Long 77844f05562SScott Long /* check if command done with no error*/ 779d74001adSXin LI switch (acb->adapter_type) { 780d74001adSXin LI case ACB_ADAPTER_TYPE_C: 781*22f2616bSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/ 782d74001adSXin LI break; 783d74001adSXin LI case ACB_ADAPTER_TYPE_A: 784d74001adSXin LI case ACB_ADAPTER_TYPE_B: 785d74001adSXin LI default: 786d74001adSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 787d74001adSXin LI break; 788d74001adSXin LI } 789*22f2616bSXin LI if((srb->acb!=acb) || (srb->srb_state!=ARCMSR_SRB_START)) { 790*22f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_TIMEOUT) { 791*22f2616bSXin LI arcmsr_free_srb(srb); 792*22f2616bSXin LI printf("arcmsr%d: srb='%p' return srb has been timeouted\n", acb->pci_unit, srb); 79344f05562SScott Long return; 79444f05562SScott Long } 795*22f2616bSXin LI printf("arcmsr%d: return srb has been completed\n" 796*22f2616bSXin LI "srb='%p' srb_state=0x%x outstanding srb count=%d \n", 797*22f2616bSXin LI acb->pci_unit, srb, srb->srb_state, acb->srboutstandingcount); 79844f05562SScott Long return; 79944f05562SScott Long } 800d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 80144f05562SScott Long return; 80244f05562SScott Long } 80344f05562SScott Long /* 804*22f2616bSXin LI ************************************************************************** 805*22f2616bSXin LI ************************************************************************** 806*22f2616bSXin LI */ 807*22f2616bSXin LI static void arcmsr_srb_timeout(void* arg) 808*22f2616bSXin LI { 809*22f2616bSXin LI struct CommandControlBlock *srb = (struct CommandControlBlock *)arg; 810*22f2616bSXin LI struct AdapterControlBlock *acb; 811*22f2616bSXin LI int target, lun; 812*22f2616bSXin LI u_int8_t cmd; 813*22f2616bSXin LI 814*22f2616bSXin LI target=srb->pccb->ccb_h.target_id; 815*22f2616bSXin LI lun=srb->pccb->ccb_h.target_lun; 816*22f2616bSXin LI acb = srb->acb; 817*22f2616bSXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 818*22f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) 819*22f2616bSXin LI { 820*22f2616bSXin LI cmd = srb->pccb->csio.cdb_io.cdb_bytes[0]; 821*22f2616bSXin LI srb->srb_state = ARCMSR_SRB_TIMEOUT; 822*22f2616bSXin LI srb->pccb->ccb_h.status |= CAM_CMD_TIMEOUT; 823*22f2616bSXin LI arcmsr_srb_complete(srb, 1); 824*22f2616bSXin LI printf("arcmsr%d: scsi id %d lun %d cmd=0x%x srb='%p' ccb command time out!\n", 825*22f2616bSXin LI acb->pci_unit, target, lun, cmd, srb); 826*22f2616bSXin LI } 827*22f2616bSXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 828*22f2616bSXin LI #ifdef ARCMSR_DEBUG1 829*22f2616bSXin LI arcmsr_dump_data(acb); 830*22f2616bSXin LI #endif 831*22f2616bSXin LI } 832*22f2616bSXin LI 833*22f2616bSXin LI /* 83444f05562SScott Long ********************************************************************** 83544f05562SScott Long ********************************************************************** 83644f05562SScott Long */ 83744f05562SScott Long static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) 83844f05562SScott Long { 83944f05562SScott Long int i=0; 84044f05562SScott Long u_int32_t flag_srb; 841d74001adSXin LI u_int16_t error; 84244f05562SScott Long 84344f05562SScott Long switch (acb->adapter_type) { 84444f05562SScott Long case ACB_ADAPTER_TYPE_A: { 84544f05562SScott Long u_int32_t outbound_intstatus; 84644f05562SScott Long 84744f05562SScott Long /*clear and abort all outbound posted Q*/ 848d74001adSXin LI outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 849d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/ 850d74001adSXin LI while(((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_queueport)) != 0xFFFFFFFF) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { 851d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 852d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 85344f05562SScott Long } 85444f05562SScott Long } 85544f05562SScott Long break; 85644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 85744f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 85844f05562SScott Long 85944f05562SScott Long /*clear all outbound posted Q*/ 860d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 86144f05562SScott Long for(i=0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) { 86244f05562SScott Long if((flag_srb=phbbmu->done_qbuffer[i])!=0) { 86344f05562SScott Long phbbmu->done_qbuffer[i]=0; 864d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 865d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 86644f05562SScott Long } 86744f05562SScott Long phbbmu->post_qbuffer[i]=0; 86844f05562SScott Long }/*drain reply FIFO*/ 86944f05562SScott Long phbbmu->doneq_index=0; 87044f05562SScott Long phbbmu->postq_index=0; 87144f05562SScott Long } 87244f05562SScott Long break; 873d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 874d74001adSXin LI 875d74001adSXin LI while((CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { 876d74001adSXin LI flag_srb=CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 877d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; 878d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 879d74001adSXin LI } 880d74001adSXin LI } 881d74001adSXin LI break; 88244f05562SScott Long } 883f1c579b1SScott Long return; 884f1c579b1SScott Long } 885f1c579b1SScott Long /* 886f1c579b1SScott Long **************************************************************************** 887f1c579b1SScott Long **************************************************************************** 888f1c579b1SScott Long */ 889ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb) 890f1c579b1SScott Long { 891ad6d6297SScott Long struct CommandControlBlock *srb; 89244f05562SScott Long u_int32_t intmask_org; 893ad6d6297SScott Long u_int32_t i=0; 894f1c579b1SScott Long 89544f05562SScott Long if(acb->srboutstandingcount>0) { 89644f05562SScott Long /* disable all outbound interrupt */ 89744f05562SScott Long intmask_org=arcmsr_disable_allintr(acb); 89844f05562SScott Long /*clear and abort all outbound posted Q*/ 89944f05562SScott Long arcmsr_done4abort_postqueue(acb); 900f1c579b1SScott Long /* talk to iop 331 outstanding command aborted*/ 901ad6d6297SScott Long arcmsr_abort_allcmd(acb); 902ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 903ad6d6297SScott Long srb=acb->psrb_pool[i]; 904*22f2616bSXin LI if(srb->srb_state==ARCMSR_SRB_START) { 905*22f2616bSXin LI srb->srb_state=ARCMSR_SRB_ABORTED; 906ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 907ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 908*22f2616bSXin LI printf("arcmsr%d: scsi id=%d lun=%d srb='%p' aborted\n" 909*22f2616bSXin LI , acb->pci_unit, srb->pccb->ccb_h.target_id 910*22f2616bSXin LI , srb->pccb->ccb_h.target_lun, srb); 911f1c579b1SScott Long } 912f1c579b1SScott Long } 913f1c579b1SScott Long /* enable all outbound interrupt */ 91444f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 915f1c579b1SScott Long } 916*22f2616bSXin LI acb->srboutstandingcount=0; 917ad6d6297SScott Long acb->workingsrb_doneindex=0; 918ad6d6297SScott Long acb->workingsrb_startindex=0; 919*22f2616bSXin LI #ifdef ARCMSR_DEBUG1 920*22f2616bSXin LI acb->pktRequestCount = 0; 921*22f2616bSXin LI acb->pktReturnCount = 0; 922*22f2616bSXin LI #endif 923f1c579b1SScott Long return; 924f1c579b1SScott Long } 925f1c579b1SScott Long /* 926f1c579b1SScott Long ********************************************************************** 927f1c579b1SScott Long ********************************************************************** 928f1c579b1SScott Long */ 92944f05562SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, 93044f05562SScott Long bus_dma_segment_t *dm_segs, u_int32_t nseg) 931f1c579b1SScott Long { 932ad6d6297SScott Long struct ARCMSR_CDB * arcmsr_cdb= &srb->arcmsr_cdb; 933ad6d6297SScott Long u_int8_t * psge=(u_int8_t *)&arcmsr_cdb->u; 934ad6d6297SScott Long u_int32_t address_lo, address_hi; 935ad6d6297SScott Long union ccb * pccb=srb->pccb; 936f1c579b1SScott Long struct ccb_scsiio * pcsio= &pccb->csio; 937ad6d6297SScott Long u_int32_t arccdbsize=0x30; 938f1c579b1SScott Long 939ad6d6297SScott Long memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB)); 940ad6d6297SScott Long arcmsr_cdb->Bus=0; 941ad6d6297SScott Long arcmsr_cdb->TargetID=pccb->ccb_h.target_id; 942ad6d6297SScott Long arcmsr_cdb->LUN=pccb->ccb_h.target_lun; 943ad6d6297SScott Long arcmsr_cdb->Function=1; 944ad6d6297SScott Long arcmsr_cdb->CdbLength=(u_int8_t)pcsio->cdb_len; 94544f05562SScott Long arcmsr_cdb->Context=0; 946ad6d6297SScott Long bcopy(pcsio->cdb_io.cdb_bytes, arcmsr_cdb->Cdb, pcsio->cdb_len); 947ad6d6297SScott Long if(nseg != 0) { 948ad6d6297SScott Long struct AdapterControlBlock *acb=srb->acb; 949f1c579b1SScott Long bus_dmasync_op_t op; 950ad6d6297SScott Long u_int32_t length, i, cdb_sgcount=0; 951f1c579b1SScott Long 952ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 953ad6d6297SScott Long op=BUS_DMASYNC_PREREAD; 954ad6d6297SScott Long } else { 955ad6d6297SScott Long op=BUS_DMASYNC_PREWRITE; 956ad6d6297SScott Long arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_WRITE; 957ad6d6297SScott Long srb->srb_flags|=SRB_FLAG_WRITE; 958ad6d6297SScott Long } 959ad6d6297SScott Long bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 960ad6d6297SScott Long for(i=0;i<nseg;i++) { 961f1c579b1SScott Long /* Get the physical address of the current data pointer */ 962ad6d6297SScott Long length=arcmsr_htole32(dm_segs[i].ds_len); 963ad6d6297SScott Long address_lo=arcmsr_htole32(dma_addr_lo32(dm_segs[i].ds_addr)); 964ad6d6297SScott Long address_hi=arcmsr_htole32(dma_addr_hi32(dm_segs[i].ds_addr)); 965ad6d6297SScott Long if(address_hi==0) { 966ad6d6297SScott Long struct SG32ENTRY * pdma_sg=(struct SG32ENTRY *)psge; 967f1c579b1SScott Long pdma_sg->address=address_lo; 968f1c579b1SScott Long pdma_sg->length=length; 969ad6d6297SScott Long psge += sizeof(struct SG32ENTRY); 970ad6d6297SScott Long arccdbsize += sizeof(struct SG32ENTRY); 971ad6d6297SScott Long } else { 972ad6d6297SScott Long u_int32_t sg64s_size=0, tmplength=length; 973f1c579b1SScott Long 974ad6d6297SScott Long while(1) { 975ad6d6297SScott Long u_int64_t span4G, length0; 976ad6d6297SScott Long struct SG64ENTRY * pdma_sg=(struct SG64ENTRY *)psge; 977f1c579b1SScott Long 978ad6d6297SScott Long span4G=(u_int64_t)address_lo + tmplength; 979f1c579b1SScott Long pdma_sg->addresshigh=address_hi; 980f1c579b1SScott Long pdma_sg->address=address_lo; 981ad6d6297SScott Long if(span4G > 0x100000000) { 982f1c579b1SScott Long /*see if cross 4G boundary*/ 983f1c579b1SScott Long length0=0x100000000-address_lo; 984ad6d6297SScott Long pdma_sg->length=(u_int32_t)length0|IS_SG64_ADDR; 985f1c579b1SScott Long address_hi=address_hi+1; 986f1c579b1SScott Long address_lo=0; 987ad6d6297SScott Long tmplength=tmplength-(u_int32_t)length0; 988ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 989ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 990f1c579b1SScott Long cdb_sgcount++; 991ad6d6297SScott Long } else { 992f1c579b1SScott Long pdma_sg->length=tmplength|IS_SG64_ADDR; 993ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 994ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 995f1c579b1SScott Long break; 996f1c579b1SScott Long } 997f1c579b1SScott Long } 998f1c579b1SScott Long arccdbsize += sg64s_size; 999f1c579b1SScott Long } 1000f1c579b1SScott Long cdb_sgcount++; 1001f1c579b1SScott Long } 1002ad6d6297SScott Long arcmsr_cdb->sgcount=(u_int8_t)cdb_sgcount; 1003ad6d6297SScott Long arcmsr_cdb->DataLength=pcsio->dxfer_len; 1004ad6d6297SScott Long if( arccdbsize > 256) { 1005ad6d6297SScott Long arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_SGL_BSIZE; 1006f1c579b1SScott Long } 1007d74001adSXin LI } else { 1008d74001adSXin LI arcmsr_cdb->DataLength = 0; 1009f1c579b1SScott Long } 1010d74001adSXin LI srb->arc_cdb_size=arccdbsize; 1011f1c579b1SScott Long return; 1012f1c579b1SScott Long } 1013f1c579b1SScott Long /* 1014f1c579b1SScott Long ************************************************************************** 1015f1c579b1SScott Long ************************************************************************** 1016f1c579b1SScott Long */ 1017ad6d6297SScott Long static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandControlBlock *srb) 1018f1c579b1SScott Long { 1019ad6d6297SScott Long u_int32_t cdb_shifted_phyaddr=(u_int32_t) srb->cdb_shifted_phyaddr; 1020ad6d6297SScott Long struct ARCMSR_CDB * arcmsr_cdb=(struct ARCMSR_CDB *)&srb->arcmsr_cdb; 1021f1c579b1SScott Long 1022d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, (srb->srb_flags & SRB_FLAG_WRITE) ? BUS_DMASYNC_POSTWRITE:BUS_DMASYNC_POSTREAD); 1023ad6d6297SScott Long atomic_add_int(&acb->srboutstandingcount, 1); 1024*22f2616bSXin LI srb->srb_state=ARCMSR_SRB_START; 1025d74001adSXin LI 102644f05562SScott Long switch (acb->adapter_type) { 102744f05562SScott Long case ACB_ADAPTER_TYPE_A: { 1028ad6d6297SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 1029d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE); 1030ad6d6297SScott Long } else { 1031d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_shifted_phyaddr); 103244f05562SScott Long } 103344f05562SScott Long } 103444f05562SScott Long break; 103544f05562SScott Long case ACB_ADAPTER_TYPE_B: { 103644f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 103744f05562SScott Long int ending_index, index; 103844f05562SScott Long 103944f05562SScott Long index=phbbmu->postq_index; 104044f05562SScott Long ending_index=((index+1)%ARCMSR_MAX_HBB_POSTQUEUE); 104144f05562SScott Long phbbmu->post_qbuffer[ending_index]=0; 104244f05562SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 1043d74001adSXin LI phbbmu->post_qbuffer[index]= cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE; 104444f05562SScott Long } else { 1045d74001adSXin LI phbbmu->post_qbuffer[index]= cdb_shifted_phyaddr; 104644f05562SScott Long } 104744f05562SScott Long index++; 104844f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 104944f05562SScott Long phbbmu->postq_index=index; 1050d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED); 1051d74001adSXin LI } 1052d74001adSXin LI break; 1053d74001adSXin LI case ACB_ADAPTER_TYPE_C: 1054d74001adSXin LI { 1055d74001adSXin LI u_int32_t ccb_post_stamp, arc_cdb_size, cdb_phyaddr_hi32; 1056d74001adSXin LI 1057d74001adSXin LI arc_cdb_size=(srb->arc_cdb_size>0x300)?0x300:srb->arc_cdb_size; 1058d74001adSXin LI ccb_post_stamp=(cdb_shifted_phyaddr | ((arc_cdb_size-1) >> 6) | 1); 1059d74001adSXin LI cdb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high; 1060d74001adSXin LI if(cdb_phyaddr_hi32) 1061d74001adSXin LI { 1062d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_high, cdb_phyaddr_hi32); 1063d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp); 1064d74001adSXin LI } 1065d74001adSXin LI else 1066d74001adSXin LI { 1067d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp); 1068d74001adSXin LI } 106944f05562SScott Long } 107044f05562SScott Long break; 1071f1c579b1SScott Long } 1072f1c579b1SScott Long return; 1073f1c579b1SScott Long } 1074f1c579b1SScott Long /* 107544f05562SScott Long ************************************************************************ 107644f05562SScott Long ************************************************************************ 107744f05562SScott Long */ 107844f05562SScott Long static struct QBUFFER * arcmsr_get_iop_rqbuffer( struct AdapterControlBlock *acb) 107944f05562SScott Long { 108044f05562SScott Long struct QBUFFER *qbuffer=NULL; 108144f05562SScott Long 108244f05562SScott Long switch (acb->adapter_type) { 108344f05562SScott Long case ACB_ADAPTER_TYPE_A: { 108444f05562SScott Long struct HBA_MessageUnit *phbamu=(struct HBA_MessageUnit *)acb->pmu; 108544f05562SScott Long 108644f05562SScott Long qbuffer=(struct QBUFFER *)&phbamu->message_rbuffer; 108744f05562SScott Long } 108844f05562SScott Long break; 108944f05562SScott Long case ACB_ADAPTER_TYPE_B: { 109044f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 109144f05562SScott Long 109244f05562SScott Long qbuffer=(struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_rbuffer; 109344f05562SScott Long } 109444f05562SScott Long break; 1095d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1096d74001adSXin LI struct HBC_MessageUnit *phbcmu=(struct HBC_MessageUnit *)acb->pmu; 1097d74001adSXin LI 1098d74001adSXin LI qbuffer=(struct QBUFFER *)&phbcmu->message_rbuffer; 1099d74001adSXin LI } 1100d74001adSXin LI break; 110144f05562SScott Long } 110244f05562SScott Long return(qbuffer); 110344f05562SScott Long } 110444f05562SScott Long /* 110544f05562SScott Long ************************************************************************ 110644f05562SScott Long ************************************************************************ 110744f05562SScott Long */ 110844f05562SScott Long static struct QBUFFER * arcmsr_get_iop_wqbuffer( struct AdapterControlBlock *acb) 110944f05562SScott Long { 111044f05562SScott Long struct QBUFFER *qbuffer=NULL; 111144f05562SScott Long 111244f05562SScott Long switch (acb->adapter_type) { 111344f05562SScott Long case ACB_ADAPTER_TYPE_A: { 111444f05562SScott Long struct HBA_MessageUnit *phbamu=(struct HBA_MessageUnit *)acb->pmu; 111544f05562SScott Long 111644f05562SScott Long qbuffer=(struct QBUFFER *)&phbamu->message_wbuffer; 111744f05562SScott Long } 111844f05562SScott Long break; 111944f05562SScott Long case ACB_ADAPTER_TYPE_B: { 112044f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 112144f05562SScott Long 112244f05562SScott Long qbuffer=(struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_wbuffer; 112344f05562SScott Long } 112444f05562SScott Long break; 1125d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1126d74001adSXin LI struct HBC_MessageUnit *phbcmu=(struct HBC_MessageUnit *)acb->pmu; 1127d74001adSXin LI 1128d74001adSXin LI qbuffer=(struct QBUFFER *)&phbcmu->message_wbuffer; 1129d74001adSXin LI } 1130d74001adSXin LI break; 113144f05562SScott Long } 113244f05562SScott Long return(qbuffer); 113344f05562SScott Long } 113444f05562SScott Long /* 113544f05562SScott Long ************************************************************************** 113644f05562SScott Long ************************************************************************** 113744f05562SScott Long */ 113844f05562SScott Long static void arcmsr_iop_message_read(struct AdapterControlBlock *acb) 113944f05562SScott Long { 114044f05562SScott Long switch (acb->adapter_type) { 114144f05562SScott Long case ACB_ADAPTER_TYPE_A: { 114244f05562SScott Long /* let IOP know data has been read */ 1143d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 114444f05562SScott Long } 114544f05562SScott Long break; 114644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 114744f05562SScott Long /* let IOP know data has been read */ 1148d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 114944f05562SScott Long } 115044f05562SScott Long break; 1151d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1152d74001adSXin LI /* let IOP know data has been read */ 1153d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK); 1154d74001adSXin LI } 115544f05562SScott Long } 115644f05562SScott Long return; 115744f05562SScott Long } 115844f05562SScott Long /* 115944f05562SScott Long ************************************************************************** 116044f05562SScott Long ************************************************************************** 116144f05562SScott Long */ 116244f05562SScott Long static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) 116344f05562SScott Long { 116444f05562SScott Long switch (acb->adapter_type) { 116544f05562SScott Long case ACB_ADAPTER_TYPE_A: { 116644f05562SScott Long /* 116744f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 116844f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 116944f05562SScott Long */ 1170d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK); 117144f05562SScott Long } 117244f05562SScott Long break; 117344f05562SScott Long case ACB_ADAPTER_TYPE_B: { 117444f05562SScott Long /* 117544f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 117644f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 117744f05562SScott Long */ 1178d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_WRITE_OK); 1179d74001adSXin LI } 1180d74001adSXin LI break; 1181d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1182d74001adSXin LI /* 1183d74001adSXin LI ** push inbound doorbell tell iop, driver data write ok 1184d74001adSXin LI ** and wait reply on next hwinterrupt for next Qbuffer post 1185d74001adSXin LI */ 1186d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK); 118744f05562SScott Long } 118844f05562SScott Long break; 118944f05562SScott Long } 119044f05562SScott Long } 119144f05562SScott Long /* 1192f1c579b1SScott Long ********************************************************************** 1193f1c579b1SScott Long ********************************************************************** 1194f1c579b1SScott Long */ 119544f05562SScott Long static void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb) 1196f1c579b1SScott Long { 1197ad6d6297SScott Long u_int8_t *pQbuffer; 119844f05562SScott Long struct QBUFFER *pwbuffer; 119944f05562SScott Long u_int8_t * iop_data; 120044f05562SScott Long int32_t allxfer_len=0; 1201f1c579b1SScott Long 120244f05562SScott Long pwbuffer=arcmsr_get_iop_wqbuffer(acb); 120344f05562SScott Long iop_data=(u_int8_t *)pwbuffer->data; 120444f05562SScott Long if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) { 120544f05562SScott Long acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 120644f05562SScott Long while((acb->wqbuf_firstindex!=acb->wqbuf_lastindex) 120744f05562SScott Long && (allxfer_len<124)) { 1208ad6d6297SScott Long pQbuffer=&acb->wqbuffer[acb->wqbuf_firstindex]; 1209f1c579b1SScott Long memcpy(iop_data, pQbuffer, 1); 1210ad6d6297SScott Long acb->wqbuf_firstindex++; 121144f05562SScott Long acb->wqbuf_firstindex %=ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */ 1212f1c579b1SScott Long iop_data++; 1213f1c579b1SScott Long allxfer_len++; 1214f1c579b1SScott Long } 1215f1c579b1SScott Long pwbuffer->data_len=allxfer_len; 1216f1c579b1SScott Long /* 1217f1c579b1SScott Long ** push inbound doorbell and wait reply at hwinterrupt routine for next Qbuffer post 1218f1c579b1SScott Long */ 121944f05562SScott Long arcmsr_iop_message_wrote(acb); 1220ad6d6297SScott Long } 1221f1c579b1SScott Long return; 1222f1c579b1SScott Long } 1223f1c579b1SScott Long /* 1224f1c579b1SScott Long ************************************************************************ 1225f1c579b1SScott Long ************************************************************************ 1226f1c579b1SScott Long */ 122744f05562SScott Long static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb) 1228f1c579b1SScott Long { 1229ad6d6297SScott Long acb->acb_flags &=~ACB_F_MSG_START_BGRB; 123044f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 123144f05562SScott Long 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 123244f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 1233d74001adSXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n" 1234ad6d6297SScott Long , acb->pci_unit); 1235ad6d6297SScott Long } 1236f1c579b1SScott Long return; 1237f1c579b1SScott Long } 1238f1c579b1SScott Long /* 1239f1c579b1SScott Long ************************************************************************ 1240f1c579b1SScott Long ************************************************************************ 1241f1c579b1SScott Long */ 124244f05562SScott Long static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb) 124344f05562SScott Long { 124444f05562SScott Long acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 124544f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 124644f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_STOP_BGRB); 124744f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 1248d74001adSXin LI printf( "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" 124944f05562SScott Long , acb->pci_unit); 125044f05562SScott Long } 125144f05562SScott Long return; 125244f05562SScott Long } 125344f05562SScott Long /* 125444f05562SScott Long ************************************************************************ 125544f05562SScott Long ************************************************************************ 125644f05562SScott Long */ 1257d74001adSXin LI static void arcmsr_stop_hbc_bgrb(struct AdapterControlBlock *acb) 1258d74001adSXin LI { 1259d74001adSXin LI acb->acb_flags &=~ACB_F_MSG_START_BGRB; 1260d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 1261d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 1262d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 1263d74001adSXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit); 1264d74001adSXin LI } 1265d74001adSXin LI return; 1266d74001adSXin LI } 1267d74001adSXin LI /* 1268d74001adSXin LI ************************************************************************ 1269d74001adSXin LI ************************************************************************ 1270d74001adSXin LI */ 127144f05562SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) 127244f05562SScott Long { 127344f05562SScott Long switch (acb->adapter_type) { 127444f05562SScott Long case ACB_ADAPTER_TYPE_A: { 127544f05562SScott Long arcmsr_stop_hba_bgrb(acb); 127644f05562SScott Long } 127744f05562SScott Long break; 127844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 127944f05562SScott Long arcmsr_stop_hbb_bgrb(acb); 128044f05562SScott Long } 128144f05562SScott Long break; 1282d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1283d74001adSXin LI arcmsr_stop_hbc_bgrb(acb); 1284d74001adSXin LI } 1285d74001adSXin LI break; 128644f05562SScott Long } 128744f05562SScott Long return; 128844f05562SScott Long } 128944f05562SScott Long /* 129044f05562SScott Long ************************************************************************ 129144f05562SScott Long ************************************************************************ 129244f05562SScott Long */ 1293ad6d6297SScott Long static void arcmsr_poll(struct cam_sim * psim) 1294f1c579b1SScott Long { 1295579ec1a5SScott Long struct AdapterControlBlock *acb; 1296579ec1a5SScott Long 1297579ec1a5SScott Long acb = (struct AdapterControlBlock *)cam_sim_softc(psim); 1298579ec1a5SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 1299579ec1a5SScott Long arcmsr_interrupt(acb); 1300579ec1a5SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1301f1c579b1SScott Long return; 1302f1c579b1SScott Long } 1303f1c579b1SScott Long /* 130444f05562SScott Long ************************************************************************** 130544f05562SScott Long ************************************************************************** 13065878cbecSScott Long */ 130744f05562SScott Long static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) 1308f1c579b1SScott Long { 130944f05562SScott Long struct QBUFFER *prbuffer; 1310ad6d6297SScott Long u_int8_t *pQbuffer; 131144f05562SScott Long u_int8_t *iop_data; 131244f05562SScott Long int my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; 1313ad6d6297SScott Long 1314f1c579b1SScott Long /*check this iop data if overflow my rqbuffer*/ 1315ad6d6297SScott Long rqbuf_lastindex=acb->rqbuf_lastindex; 1316ad6d6297SScott Long rqbuf_firstindex=acb->rqbuf_firstindex; 131744f05562SScott Long prbuffer=arcmsr_get_iop_rqbuffer(acb); 131844f05562SScott Long iop_data=(u_int8_t *)prbuffer->data; 1319f1c579b1SScott Long iop_len=prbuffer->data_len; 1320f1c579b1SScott Long my_empty_len=(rqbuf_firstindex-rqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1); 1321ad6d6297SScott Long if(my_empty_len>=iop_len) { 1322ad6d6297SScott Long while(iop_len > 0) { 132344f05562SScott Long pQbuffer=&acb->rqbuffer[rqbuf_lastindex]; 1324f1c579b1SScott Long memcpy(pQbuffer, iop_data, 1); 132544f05562SScott Long rqbuf_lastindex++; 132644f05562SScott Long rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;/*if last index number set it to 0 */ 1327f1c579b1SScott Long iop_data++; 1328f1c579b1SScott Long iop_len--; 1329f1c579b1SScott Long } 133044f05562SScott Long acb->rqbuf_lastindex=rqbuf_lastindex; 133144f05562SScott Long arcmsr_iop_message_read(acb); 133244f05562SScott Long /*signature, let IOP know data has been read */ 1333ad6d6297SScott Long } else { 1334ad6d6297SScott Long acb->acb_flags|=ACB_F_IOPDATA_OVERFLOW; 1335f1c579b1SScott Long } 133644f05562SScott Long return; 1337f1c579b1SScott Long } 1338f1c579b1SScott Long /* 133944f05562SScott Long ************************************************************************** 134044f05562SScott Long ************************************************************************** 134144f05562SScott Long */ 134244f05562SScott Long static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) 134344f05562SScott Long { 134444f05562SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READ; 134544f05562SScott Long /* 134644f05562SScott Long ***************************************************************** 134744f05562SScott Long ** check if there are any mail packages from user space program 134844f05562SScott Long ** in my post bag, now is the time to send them into Areca's firmware 134944f05562SScott Long ***************************************************************** 1350f1c579b1SScott Long */ 1351ad6d6297SScott Long if(acb->wqbuf_firstindex!=acb->wqbuf_lastindex) { 1352ad6d6297SScott Long u_int8_t *pQbuffer; 135344f05562SScott Long struct QBUFFER *pwbuffer; 135444f05562SScott Long u_int8_t *iop_data; 135544f05562SScott Long int allxfer_len=0; 1356f1c579b1SScott Long 135744f05562SScott Long acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 135844f05562SScott Long pwbuffer=arcmsr_get_iop_wqbuffer(acb); 135944f05562SScott Long iop_data=(u_int8_t *)pwbuffer->data; 136044f05562SScott Long while((acb->wqbuf_firstindex!=acb->wqbuf_lastindex) 136144f05562SScott Long && (allxfer_len<124)) { 1362ad6d6297SScott Long pQbuffer=&acb->wqbuffer[acb->wqbuf_firstindex]; 1363f1c579b1SScott Long memcpy(iop_data, pQbuffer, 1); 1364ad6d6297SScott Long acb->wqbuf_firstindex++; 136544f05562SScott Long acb->wqbuf_firstindex %=ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */ 1366f1c579b1SScott Long iop_data++; 1367f1c579b1SScott Long allxfer_len++; 1368f1c579b1SScott Long } 1369f1c579b1SScott Long pwbuffer->data_len=allxfer_len; 1370f1c579b1SScott Long /* 1371ad6d6297SScott Long ** push inbound doorbell tell iop driver data write ok 1372ad6d6297SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 1373f1c579b1SScott Long */ 137444f05562SScott Long arcmsr_iop_message_wrote(acb); 1375f1c579b1SScott Long } 1376ad6d6297SScott Long if(acb->wqbuf_firstindex==acb->wqbuf_lastindex) { 1377ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; 1378f1c579b1SScott Long } 137944f05562SScott Long return; 1380f1c579b1SScott Long } 1381d74001adSXin LI 1382d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb) 1383d74001adSXin LI { 1384d74001adSXin LI /* 1385d74001adSXin LI if (ccb->ccb_h.status != CAM_REQ_CMP) 1386d74001adSXin 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); 1387d74001adSXin LI else 1388d74001adSXin LI printf("arcmsr_rescanLun_cb: Rescan lun successfully!\n"); 1389d74001adSXin LI */ 1390d74001adSXin LI xpt_free_path(ccb->ccb_h.path); 1391d74001adSXin LI xpt_free_ccb(ccb); 1392d74001adSXin LI } 1393d74001adSXin LI 1394d74001adSXin LI static void arcmsr_rescan_lun(struct AdapterControlBlock *acb, int target, int lun) 1395d74001adSXin LI { 1396d74001adSXin LI struct cam_path *path; 1397d74001adSXin LI union ccb *ccb; 1398d74001adSXin LI 1399d74001adSXin LI if ((ccb = (union ccb *)xpt_alloc_ccb_nowait()) == NULL) 1400d74001adSXin LI return; 1401d74001adSXin LI if (xpt_create_path(&path, xpt_periph, cam_sim_path(acb->psim), target, lun) != CAM_REQ_CMP) 1402d74001adSXin LI { 1403d74001adSXin LI xpt_free_ccb(ccb); 1404d74001adSXin LI return; 1405d74001adSXin LI } 1406d74001adSXin LI /* printf("arcmsr_rescan_lun: Rescan Target=%x, Lun=%x\n", target, lun); */ 1407d74001adSXin LI bzero(ccb, sizeof(union ccb)); 1408d74001adSXin LI xpt_setup_ccb(&ccb->ccb_h, path, 5); 1409d74001adSXin LI ccb->ccb_h.func_code = XPT_SCAN_LUN; 1410d74001adSXin LI ccb->ccb_h.cbfcnp = arcmsr_rescanLun_cb; 1411d74001adSXin LI ccb->crcn.flags = CAM_FLAG_NONE; 1412d74001adSXin LI xpt_action(ccb); 1413d74001adSXin LI return; 1414d74001adSXin LI } 1415d74001adSXin LI 1416d74001adSXin LI 1417d74001adSXin LI static void arcmsr_abort_dr_ccbs(struct AdapterControlBlock *acb, int target, int lun) 1418d74001adSXin LI { 1419d74001adSXin LI struct CommandControlBlock *srb; 1420d74001adSXin LI u_int32_t intmask_org; 1421d74001adSXin LI int i; 1422d74001adSXin LI 1423d74001adSXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 1424d74001adSXin LI /* disable all outbound interrupts */ 1425d74001adSXin LI intmask_org = arcmsr_disable_allintr(acb); 1426d74001adSXin LI for (i = 0; i < ARCMSR_MAX_FREESRB_NUM; i++) 1427d74001adSXin LI { 1428d74001adSXin LI srb = acb->psrb_pool[i]; 1429*22f2616bSXin LI if (srb->srb_state == ARCMSR_SRB_START) 1430d74001adSXin LI { 1431d74001adSXin LI if((target == srb->pccb->ccb_h.target_id) && (lun == srb->pccb->ccb_h.target_lun)) 1432d74001adSXin LI { 1433*22f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 1434d74001adSXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 1435d74001adSXin LI arcmsr_srb_complete(srb, 1); 1436*22f2616bSXin LI printf("arcmsr%d: abort scsi id %d lun %d srb=%p \n", acb->pci_unit, target, lun, srb); 1437d74001adSXin LI } 1438d74001adSXin LI } 1439d74001adSXin LI } 1440d74001adSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 1441d74001adSXin LI arcmsr_enable_allintr(acb, intmask_org); 1442d74001adSXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1443d74001adSXin LI } 1444d74001adSXin LI 1445d74001adSXin LI 1446d74001adSXin LI /* 1447d74001adSXin LI ************************************************************************** 1448d74001adSXin LI ************************************************************************** 1449d74001adSXin LI */ 1450d74001adSXin LI static void arcmsr_dr_handle(struct AdapterControlBlock *acb) { 1451d74001adSXin LI u_int32_t devicemap; 1452d74001adSXin LI u_int32_t target, lun; 1453d74001adSXin LI u_int32_t deviceMapCurrent[4]={0}; 1454d74001adSXin LI u_int8_t *pDevMap; 1455d74001adSXin LI 1456d74001adSXin LI switch (acb->adapter_type) { 1457d74001adSXin LI case ACB_ADAPTER_TYPE_A: 1458d74001adSXin LI devicemap = offsetof(struct HBA_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1459d74001adSXin LI for (target= 0; target < 4; target++) 1460d74001adSXin LI { 1461d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1462d74001adSXin LI devicemap += 4; 1463d74001adSXin LI } 1464d74001adSXin LI break; 1465d74001adSXin LI 1466d74001adSXin LI case ACB_ADAPTER_TYPE_B: 1467d74001adSXin LI devicemap = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1468d74001adSXin LI for (target= 0; target < 4; target++) 1469d74001adSXin LI { 1470d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[1], acb->bhandle[1], devicemap); 1471d74001adSXin LI devicemap += 4; 1472d74001adSXin LI } 1473d74001adSXin LI break; 1474d74001adSXin LI 1475d74001adSXin LI case ACB_ADAPTER_TYPE_C: 1476d74001adSXin LI devicemap = offsetof(struct HBC_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1477d74001adSXin LI for (target= 0; target < 4; target++) 1478d74001adSXin LI { 1479d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1480d74001adSXin LI devicemap += 4; 1481d74001adSXin LI } 1482d74001adSXin LI break; 1483d74001adSXin LI } 1484d74001adSXin LI if(acb->acb_flags & ACB_F_BUS_HANG_ON) 1485d74001adSXin LI { 1486d74001adSXin LI acb->acb_flags &= ~ACB_F_BUS_HANG_ON; 1487d74001adSXin LI } 1488d74001adSXin LI /* 1489d74001adSXin LI ** adapter posted CONFIG message 1490d74001adSXin LI ** copy the new map, note if there are differences with the current map 1491d74001adSXin LI */ 1492d74001adSXin LI pDevMap = (u_int8_t *)&deviceMapCurrent[0]; 1493d74001adSXin LI for (target= 0; target < ARCMSR_MAX_TARGETID - 1; target++) 1494d74001adSXin LI { 1495d74001adSXin LI if (*pDevMap != acb->device_map[target]) 1496d74001adSXin LI { 1497d74001adSXin LI u_int8_t difference, bit_check; 1498d74001adSXin LI 1499d74001adSXin LI difference= *pDevMap ^ acb->device_map[target]; 1500d74001adSXin LI for(lun=0; lun < ARCMSR_MAX_TARGETLUN; lun++) 1501d74001adSXin LI { 1502d74001adSXin LI bit_check=(1 << lun); /*check bit from 0....31*/ 1503d74001adSXin LI if(difference & bit_check) 1504d74001adSXin LI { 1505d74001adSXin LI if(acb->device_map[target] & bit_check) 1506d74001adSXin LI {/* unit departed */ 1507d74001adSXin LI printf("arcmsr_dr_handle: Target=%x, lun=%x, GONE!!!\n",target,lun); 1508d74001adSXin LI arcmsr_abort_dr_ccbs(acb, target, lun); 1509d74001adSXin LI arcmsr_rescan_lun(acb, target, lun); 1510d74001adSXin LI acb->devstate[target][lun] = ARECA_RAID_GONE; 1511d74001adSXin LI } 1512d74001adSXin LI else 1513d74001adSXin LI {/* unit arrived */ 1514*22f2616bSXin LI printf("arcmsr_dr_handle: Target=%x, lun=%x, Plug-IN!!!\n",target,lun); 1515d74001adSXin LI arcmsr_rescan_lun(acb, target, lun); 1516d74001adSXin LI acb->devstate[target][lun] = ARECA_RAID_GOOD; 1517d74001adSXin LI } 1518d74001adSXin LI } 1519d74001adSXin LI } 1520d74001adSXin LI /* printf("arcmsr_dr_handle: acb->device_map[%x]=0x%x, deviceMapCurrent[%x]=%x\n",target,acb->device_map[target],target,*pDevMap); */ 1521d74001adSXin LI acb->device_map[target]= *pDevMap; 1522d74001adSXin LI } 1523d74001adSXin LI pDevMap++; 1524d74001adSXin LI } 1525d74001adSXin LI } 1526d74001adSXin LI /* 1527d74001adSXin LI ************************************************************************** 1528d74001adSXin LI ************************************************************************** 1529d74001adSXin LI */ 1530d74001adSXin LI static void arcmsr_hba_message_isr(struct AdapterControlBlock *acb) { 1531d74001adSXin LI u_int32_t outbound_message; 1532d74001adSXin LI 1533d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT); 1534d74001adSXin LI outbound_message = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[0]); 1535d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1536d74001adSXin LI arcmsr_dr_handle( acb ); 1537d74001adSXin LI } 1538d74001adSXin LI /* 1539d74001adSXin LI ************************************************************************** 1540d74001adSXin LI ************************************************************************** 1541d74001adSXin LI */ 1542d74001adSXin LI static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) { 1543d74001adSXin LI u_int32_t outbound_message; 1544d74001adSXin LI 1545d74001adSXin LI /* clear interrupts */ 1546d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN); 1547d74001adSXin LI outbound_message = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0]); 1548d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1549d74001adSXin LI arcmsr_dr_handle( acb ); 1550d74001adSXin LI } 1551d74001adSXin LI /* 1552d74001adSXin LI ************************************************************************** 1553d74001adSXin LI ************************************************************************** 1554d74001adSXin LI */ 1555d74001adSXin LI static void arcmsr_hbc_message_isr(struct AdapterControlBlock *acb) { 1556d74001adSXin LI u_int32_t outbound_message; 1557d74001adSXin LI 1558d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR); 1559d74001adSXin LI outbound_message = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[0]); 1560d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1561d74001adSXin LI arcmsr_dr_handle( acb ); 1562d74001adSXin LI } 156344f05562SScott Long /* 156444f05562SScott Long ************************************************************************** 156544f05562SScott Long ************************************************************************** 156644f05562SScott Long */ 156744f05562SScott Long static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) 156844f05562SScott Long { 156944f05562SScott Long u_int32_t outbound_doorbell; 157044f05562SScott Long 157144f05562SScott Long /* 157244f05562SScott Long ******************************************************************* 157344f05562SScott Long ** Maybe here we need to check wrqbuffer_lock is lock or not 157444f05562SScott Long ** DOORBELL: din! don! 157544f05562SScott Long ** check if there are any mail need to pack from firmware 157644f05562SScott Long ******************************************************************* 157744f05562SScott Long */ 157844f05562SScott Long outbound_doorbell=CHIP_REG_READ32(HBA_MessageUnit, 157944f05562SScott Long 0, outbound_doorbell); 158044f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 158144f05562SScott Long 0, outbound_doorbell, outbound_doorbell); /* clear doorbell interrupt */ 158244f05562SScott Long if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { 158344f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 1584ad6d6297SScott Long } 158544f05562SScott Long if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { 158644f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 158744f05562SScott Long } 158844f05562SScott Long return; 158944f05562SScott Long } 159044f05562SScott Long /* 159144f05562SScott Long ************************************************************************** 159244f05562SScott Long ************************************************************************** 159344f05562SScott Long */ 1594d74001adSXin LI static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb) 1595d74001adSXin LI { 1596d74001adSXin LI u_int32_t outbound_doorbell; 1597d74001adSXin LI 1598d74001adSXin LI /* 1599d74001adSXin LI ******************************************************************* 1600d74001adSXin LI ** Maybe here we need to check wrqbuffer_lock is lock or not 1601d74001adSXin LI ** DOORBELL: din! don! 1602d74001adSXin LI ** check if there are any mail need to pack from firmware 1603d74001adSXin LI ******************************************************************* 1604d74001adSXin LI */ 1605d74001adSXin LI outbound_doorbell=CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); 1606d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell); /* clear doorbell interrupt */ 1607d74001adSXin LI if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) { 1608d74001adSXin LI arcmsr_iop2drv_data_wrote_handle(acb); 1609d74001adSXin LI } 1610d74001adSXin LI if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) { 1611d74001adSXin LI arcmsr_iop2drv_data_read_handle(acb); 1612d74001adSXin LI } 1613d74001adSXin LI if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { 1614d74001adSXin LI arcmsr_hbc_message_isr(acb); /* messenger of "driver to iop commands" */ 1615d74001adSXin LI } 1616d74001adSXin LI return; 1617d74001adSXin LI } 1618d74001adSXin LI /* 1619d74001adSXin LI ************************************************************************** 1620d74001adSXin LI ************************************************************************** 1621d74001adSXin LI */ 162244f05562SScott Long static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb) 162344f05562SScott Long { 162444f05562SScott Long u_int32_t flag_srb; 1625d74001adSXin LI u_int16_t error; 162644f05562SScott Long 1627f1c579b1SScott Long /* 1628f1c579b1SScott Long ***************************************************************************** 1629f1c579b1SScott Long ** areca cdb command done 1630f1c579b1SScott Long ***************************************************************************** 1631f1c579b1SScott Long */ 163244f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 163344f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 163444f05562SScott Long while((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 163544f05562SScott Long 0, outbound_queueport)) != 0xFFFFFFFF) { 1636f1c579b1SScott Long /* check if command done with no error*/ 1637d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 1638d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 163944f05562SScott Long } /*drain reply FIFO*/ 164044f05562SScott Long return; 1641f1c579b1SScott Long } 164244f05562SScott Long /* 164344f05562SScott Long ************************************************************************** 164444f05562SScott Long ************************************************************************** 164544f05562SScott Long */ 164644f05562SScott Long static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) 164744f05562SScott Long { 164844f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 164944f05562SScott Long u_int32_t flag_srb; 165044f05562SScott Long int index; 1651d74001adSXin LI u_int16_t error; 165244f05562SScott Long 165344f05562SScott Long /* 165444f05562SScott Long ***************************************************************************** 165544f05562SScott Long ** areca cdb command done 165644f05562SScott Long ***************************************************************************** 165744f05562SScott Long */ 165844f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 165944f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 166044f05562SScott Long index=phbbmu->doneq_index; 166144f05562SScott Long while((flag_srb=phbbmu->done_qbuffer[index]) != 0) { 166244f05562SScott Long phbbmu->done_qbuffer[index]=0; 166344f05562SScott Long index++; 166444f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 166544f05562SScott Long phbbmu->doneq_index=index; 166644f05562SScott Long /* check if command done with no error*/ 1667d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 1668d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 1669d74001adSXin LI } /*drain reply FIFO*/ 1670d74001adSXin LI return; 1671d74001adSXin LI } 1672d74001adSXin LI /* 1673d74001adSXin LI ************************************************************************** 1674d74001adSXin LI ************************************************************************** 1675d74001adSXin LI */ 1676d74001adSXin LI static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb) 1677d74001adSXin LI { 1678d74001adSXin LI u_int32_t flag_srb,throttling=0; 1679d74001adSXin LI u_int16_t error; 1680d74001adSXin LI 1681d74001adSXin LI /* 1682d74001adSXin LI ***************************************************************************** 1683d74001adSXin LI ** areca cdb command done 1684d74001adSXin LI ***************************************************************************** 1685d74001adSXin LI */ 1686d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 1687d74001adSXin LI 1688d74001adSXin LI while(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) { 1689d74001adSXin LI 1690d74001adSXin LI flag_srb=CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 1691d74001adSXin LI /* check if command done with no error*/ 1692d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; 1693d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 1694d74001adSXin LI if(throttling==ARCMSR_HBC_ISR_THROTTLING_LEVEL) { 1695d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING); 1696d74001adSXin LI break; 1697d74001adSXin LI } 1698d74001adSXin LI throttling++; 169944f05562SScott Long } /*drain reply FIFO*/ 170044f05562SScott Long return; 1701f1c579b1SScott Long } 170244f05562SScott Long /* 170344f05562SScott Long ********************************************************************** 170444f05562SScott Long ********************************************************************** 170544f05562SScott Long */ 170644f05562SScott Long static void arcmsr_handle_hba_isr( struct AdapterControlBlock *acb) 170744f05562SScott Long { 170844f05562SScott Long u_int32_t outbound_intstatus; 170944f05562SScott Long /* 171044f05562SScott Long ********************************************* 171144f05562SScott Long ** check outbound intstatus 171244f05562SScott Long ********************************************* 171344f05562SScott Long */ 1714d74001adSXin LI outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 171544f05562SScott Long if(!outbound_intstatus) { 171644f05562SScott Long /*it must be share irq*/ 171744f05562SScott Long return; 1718f1c579b1SScott Long } 1719d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/ 172044f05562SScott Long /* MU doorbell interrupts*/ 172144f05562SScott Long if(outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) { 172244f05562SScott Long arcmsr_hba_doorbell_isr(acb); 1723f1c579b1SScott Long } 172444f05562SScott Long /* MU post queue interrupts*/ 172544f05562SScott Long if(outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { 172644f05562SScott Long arcmsr_hba_postqueue_isr(acb); 172744f05562SScott Long } 1728d74001adSXin LI if(outbound_intstatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { 1729d74001adSXin LI arcmsr_hba_message_isr(acb); 1730d74001adSXin LI } 173144f05562SScott Long return; 173244f05562SScott Long } 173344f05562SScott Long /* 173444f05562SScott Long ********************************************************************** 173544f05562SScott Long ********************************************************************** 173644f05562SScott Long */ 173744f05562SScott Long static void arcmsr_handle_hbb_isr( struct AdapterControlBlock *acb) 173844f05562SScott Long { 173944f05562SScott Long u_int32_t outbound_doorbell; 174044f05562SScott Long /* 174144f05562SScott Long ********************************************* 174244f05562SScott Long ** check outbound intstatus 174344f05562SScott Long ********************************************* 174444f05562SScott Long */ 174544f05562SScott Long outbound_doorbell=CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & acb->outbound_int_enable; 174644f05562SScott Long if(!outbound_doorbell) { 174744f05562SScott Long /*it must be share irq*/ 174844f05562SScott Long return; 174944f05562SScott Long } 175044f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ~outbound_doorbell); /* clear doorbell interrupt */ 175144f05562SScott Long CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell); 175244f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 175344f05562SScott Long /* MU ioctl transfer doorbell interrupts*/ 175444f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { 175544f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 175644f05562SScott Long } 175744f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) { 175844f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 175944f05562SScott Long } 176044f05562SScott Long /* MU post queue interrupts*/ 176144f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) { 176244f05562SScott Long arcmsr_hbb_postqueue_isr(acb); 176344f05562SScott Long } 1764d74001adSXin LI if(outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { 1765d74001adSXin LI arcmsr_hbb_message_isr(acb); 1766d74001adSXin LI } 1767d74001adSXin LI return; 1768d74001adSXin LI } 1769d74001adSXin LI /* 1770d74001adSXin LI ********************************************************************** 1771d74001adSXin LI ********************************************************************** 1772d74001adSXin LI */ 1773d74001adSXin LI static void arcmsr_handle_hbc_isr( struct AdapterControlBlock *acb) 1774d74001adSXin LI { 1775d74001adSXin LI u_int32_t host_interrupt_status; 1776d74001adSXin LI /* 1777d74001adSXin LI ********************************************* 1778d74001adSXin LI ** check outbound intstatus 1779d74001adSXin LI ********************************************* 1780d74001adSXin LI */ 1781d74001adSXin LI host_interrupt_status=CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status); 1782d74001adSXin LI if(!host_interrupt_status) { 1783d74001adSXin LI /*it must be share irq*/ 1784d74001adSXin LI return; 1785d74001adSXin LI } 1786d74001adSXin LI /* MU doorbell interrupts*/ 1787d74001adSXin LI if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) { 1788d74001adSXin LI arcmsr_hbc_doorbell_isr(acb); 1789d74001adSXin LI } 1790d74001adSXin LI /* MU post queue interrupts*/ 1791d74001adSXin LI if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) { 1792d74001adSXin LI arcmsr_hbc_postqueue_isr(acb); 1793d74001adSXin LI } 179444f05562SScott Long return; 179544f05562SScott Long } 179644f05562SScott Long /* 179744f05562SScott Long ****************************************************************************** 179844f05562SScott Long ****************************************************************************** 179944f05562SScott Long */ 180044f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb) 180144f05562SScott Long { 180244f05562SScott Long switch (acb->adapter_type) { 180344f05562SScott Long case ACB_ADAPTER_TYPE_A: 180444f05562SScott Long arcmsr_handle_hba_isr(acb); 1805f1c579b1SScott Long break; 180644f05562SScott Long case ACB_ADAPTER_TYPE_B: 180744f05562SScott Long arcmsr_handle_hbb_isr(acb); 1808f1c579b1SScott Long break; 1809d74001adSXin LI case ACB_ADAPTER_TYPE_C: 1810d74001adSXin LI arcmsr_handle_hbc_isr(acb); 1811d74001adSXin LI break; 1812f1c579b1SScott Long default: 181344f05562SScott Long printf("arcmsr%d: interrupt service," 181444f05562SScott Long " unknow adapter type =%d\n", acb->pci_unit, acb->adapter_type); 1815f1c579b1SScott Long break; 1816f1c579b1SScott Long } 1817f1c579b1SScott Long return; 1818f1c579b1SScott Long } 1819f1c579b1SScott Long /* 1820d74001adSXin LI ********************************************************************** 1821d74001adSXin LI ********************************************************************** 1822d74001adSXin LI */ 1823d74001adSXin LI static void arcmsr_intr_handler(void *arg) 1824d74001adSXin LI { 1825d74001adSXin LI struct AdapterControlBlock *acb=(struct AdapterControlBlock *)arg; 1826d74001adSXin LI 1827d74001adSXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 1828d74001adSXin LI arcmsr_interrupt(acb); 1829d74001adSXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1830d74001adSXin LI } 1831d74001adSXin LI /* 1832d74001adSXin LI ****************************************************************************** 1833d74001adSXin LI ****************************************************************************** 1834d74001adSXin LI */ 1835d74001adSXin LI static void arcmsr_polling_devmap(void* arg) 1836d74001adSXin LI { 1837d74001adSXin LI struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg; 1838d74001adSXin LI switch (acb->adapter_type) { 1839d74001adSXin LI case ACB_ADAPTER_TYPE_A: 1840d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 1841d74001adSXin LI break; 1842d74001adSXin LI 1843d74001adSXin LI case ACB_ADAPTER_TYPE_B: 1844d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG); 1845d74001adSXin LI break; 1846d74001adSXin LI 1847d74001adSXin LI case ACB_ADAPTER_TYPE_C: 1848d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 1849d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 1850d74001adSXin LI break; 1851d74001adSXin LI } 1852d74001adSXin LI 1853d74001adSXin LI if((acb->acb_flags & ACB_F_SCSISTOPADAPTER) == 0) 1854d74001adSXin LI { 1855d74001adSXin LI callout_reset(&acb->devmap_callout, 5 * hz, arcmsr_polling_devmap, acb); /* polling per 5 seconds */ 1856d74001adSXin LI } 1857d74001adSXin LI } 1858d74001adSXin LI 1859d74001adSXin LI /* 1860ad6d6297SScott Long ******************************************************************************* 1861ad6d6297SScott Long ** 1862ad6d6297SScott Long ******************************************************************************* 1863ad6d6297SScott Long */ 1864ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb) 1865ad6d6297SScott Long { 1866d74001adSXin LI u_int32_t intmask_org; 1867d74001adSXin LI 1868ad6d6297SScott Long if(acb!=NULL) { 1869ad6d6297SScott Long /* stop adapter background rebuild */ 1870ad6d6297SScott Long if(acb->acb_flags & ACB_F_MSG_START_BGRB) { 1871d74001adSXin LI intmask_org = arcmsr_disable_allintr(acb); 1872ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 1873ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 1874d74001adSXin LI arcmsr_enable_allintr(acb, intmask_org); 1875ad6d6297SScott Long } 1876ad6d6297SScott Long } 1877ad6d6297SScott Long } 1878ad6d6297SScott Long /* 1879f1c579b1SScott Long *********************************************************************** 1880f1c579b1SScott Long ** 1881f1c579b1SScott Long ************************************************************************ 1882f1c579b1SScott Long */ 1883ad6d6297SScott Long u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg) 1884f1c579b1SScott Long { 1885ad6d6297SScott Long struct CMD_MESSAGE_FIELD * pcmdmessagefld; 1886ad6d6297SScott Long u_int32_t retvalue=EINVAL; 1887f1c579b1SScott Long 1888ad6d6297SScott Long pcmdmessagefld=(struct CMD_MESSAGE_FIELD *) arg; 1889ad6d6297SScott Long if(memcmp(pcmdmessagefld->cmdmessage.Signature, "ARCMSR", 6)!=0) { 1890ad6d6297SScott Long return retvalue; 1891f1c579b1SScott Long } 1892ad6d6297SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 1893ad6d6297SScott Long switch(ioctl_cmd) { 1894ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 1895ad6d6297SScott Long u_int8_t * pQbuffer; 1896ad6d6297SScott Long u_int8_t * ptmpQbuffer=pcmdmessagefld->messagedatabuffer; 1897ad6d6297SScott Long u_int32_t allxfer_len=0; 1898f1c579b1SScott Long 189944f05562SScott Long while((acb->rqbuf_firstindex!=acb->rqbuf_lastindex) 190044f05562SScott Long && (allxfer_len<1031)) { 1901f1c579b1SScott Long /*copy READ QBUFFER to srb*/ 1902ad6d6297SScott Long pQbuffer= &acb->rqbuffer[acb->rqbuf_firstindex]; 1903f1c579b1SScott Long memcpy(ptmpQbuffer, pQbuffer, 1); 1904ad6d6297SScott Long acb->rqbuf_firstindex++; 1905ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 1906ad6d6297SScott Long /*if last index number set it to 0 */ 1907f1c579b1SScott Long ptmpQbuffer++; 1908f1c579b1SScott Long allxfer_len++; 1909f1c579b1SScott Long } 1910ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 191144f05562SScott Long struct QBUFFER * prbuffer; 191244f05562SScott Long u_int8_t * iop_data; 1913ad6d6297SScott Long u_int32_t iop_len; 1914f1c579b1SScott Long 1915ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 191644f05562SScott Long prbuffer=arcmsr_get_iop_rqbuffer(acb); 191744f05562SScott Long iop_data=(u_int8_t *)prbuffer->data; 1918ad6d6297SScott Long iop_len=(u_int32_t)prbuffer->data_len; 1919f1c579b1SScott Long /*this iop data does no chance to make me overflow again here, so just do it*/ 1920ad6d6297SScott Long while(iop_len>0) { 1921ad6d6297SScott Long pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex]; 1922f1c579b1SScott Long memcpy(pQbuffer, iop_data, 1); 1923ad6d6297SScott Long acb->rqbuf_lastindex++; 1924ad6d6297SScott Long acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 1925ad6d6297SScott Long /*if last index number set it to 0 */ 1926f1c579b1SScott Long iop_data++; 1927f1c579b1SScott Long iop_len--; 1928f1c579b1SScott Long } 192944f05562SScott Long arcmsr_iop_message_read(acb); 193044f05562SScott Long /*signature, let IOP know data has been readed */ 1931f1c579b1SScott Long } 1932ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length=allxfer_len; 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_WRITE_WQBUFFER: { 1938ad6d6297SScott Long u_int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 1939ad6d6297SScott Long u_int8_t * pQbuffer; 1940ad6d6297SScott Long u_int8_t * ptmpuserbuffer=pcmdmessagefld->messagedatabuffer; 1941f1c579b1SScott Long 1942ad6d6297SScott Long user_len=pcmdmessagefld->cmdmessage.Length; 1943f1c579b1SScott Long /*check if data xfer length of this request will overflow my array qbuffer */ 1944ad6d6297SScott Long wqbuf_lastindex=acb->wqbuf_lastindex; 1945ad6d6297SScott Long wqbuf_firstindex=acb->wqbuf_firstindex; 1946ad6d6297SScott Long if(wqbuf_lastindex!=wqbuf_firstindex) { 194744f05562SScott Long arcmsr_post_ioctldata2iop(acb); 1948ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; 1949ad6d6297SScott Long } else { 1950f1c579b1SScott Long my_empty_len=(wqbuf_firstindex-wqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1); 1951ad6d6297SScott Long if(my_empty_len>=user_len) { 1952ad6d6297SScott Long while(user_len>0) { 1953f1c579b1SScott Long /*copy srb data to wqbuffer*/ 1954ad6d6297SScott Long pQbuffer= &acb->wqbuffer[acb->wqbuf_lastindex]; 1955f1c579b1SScott Long memcpy(pQbuffer, ptmpuserbuffer, 1); 1956ad6d6297SScott Long acb->wqbuf_lastindex++; 1957ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 1958ad6d6297SScott Long /*if last index number set it to 0 */ 1959f1c579b1SScott Long ptmpuserbuffer++; 1960f1c579b1SScott Long user_len--; 1961f1c579b1SScott Long } 1962f1c579b1SScott Long /*post fist Qbuffer*/ 1963ad6d6297SScott Long if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 1964ad6d6297SScott Long acb->acb_flags &=~ACB_F_MESSAGE_WQBUFFER_CLEARED; 196544f05562SScott Long arcmsr_post_ioctldata2iop(acb); 1966f1c579b1SScott Long } 1967ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1968ad6d6297SScott Long } else { 1969ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; 1970f1c579b1SScott Long } 1971f1c579b1SScott Long } 1972ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1973f1c579b1SScott Long } 1974f1c579b1SScott Long break; 1975ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 1976ad6d6297SScott Long u_int8_t * pQbuffer=acb->rqbuffer; 1977ad6d6297SScott Long 1978ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1979ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 198044f05562SScott Long arcmsr_iop_message_read(acb); 198144f05562SScott Long /*signature, let IOP know data has been readed */ 1982f1c579b1SScott Long } 1983ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 1984ad6d6297SScott Long acb->rqbuf_firstindex=0; 1985ad6d6297SScott Long acb->rqbuf_lastindex=0; 1986f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 1987ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1988ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1989f1c579b1SScott Long } 1990f1c579b1SScott Long break; 1991ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: 1992f1c579b1SScott Long { 1993ad6d6297SScott Long u_int8_t * pQbuffer=acb->wqbuffer; 1994f1c579b1SScott Long 1995ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1996ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 199744f05562SScott Long arcmsr_iop_message_read(acb); 199844f05562SScott Long /*signature, let IOP know data has been readed */ 1999f1c579b1SScott Long } 200044f05562SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ); 2001ad6d6297SScott Long acb->wqbuf_firstindex=0; 2002ad6d6297SScott Long acb->wqbuf_lastindex=0; 2003f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2004ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 2005ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 2006f1c579b1SScott Long } 2007f1c579b1SScott Long break; 2008ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 2009ad6d6297SScott Long u_int8_t * pQbuffer; 2010f1c579b1SScott Long 2011ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2012ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 201344f05562SScott Long arcmsr_iop_message_read(acb); 201444f05562SScott Long /*signature, let IOP know data has been readed */ 2015f1c579b1SScott Long } 2016ad6d6297SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED 2017ad6d6297SScott Long |ACB_F_MESSAGE_RQBUFFER_CLEARED 201844f05562SScott Long |ACB_F_MESSAGE_WQBUFFER_READ); 2019ad6d6297SScott Long acb->rqbuf_firstindex=0; 2020ad6d6297SScott Long acb->rqbuf_lastindex=0; 2021ad6d6297SScott Long acb->wqbuf_firstindex=0; 2022ad6d6297SScott Long acb->wqbuf_lastindex=0; 2023ad6d6297SScott Long pQbuffer=acb->rqbuffer; 2024ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 2025ad6d6297SScott Long pQbuffer=acb->wqbuffer; 2026ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 2027ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 2028ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 2029f1c579b1SScott Long } 2030f1c579b1SScott Long break; 2031ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 2032ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_3F; 2033ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 2034f1c579b1SScott Long } 2035f1c579b1SScott Long break; 2036ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 2037ad6d6297SScott Long u_int8_t * hello_string="Hello! I am ARCMSR"; 2038ad6d6297SScott Long u_int8_t * puserbuffer=(u_int8_t *)pcmdmessagefld->messagedatabuffer; 2039f1c579b1SScott Long 2040ad6d6297SScott Long if(memcpy(puserbuffer, hello_string, (int16_t)strlen(hello_string))) { 2041ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; 2042ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2043f1c579b1SScott Long return ENOIOCTL; 2044f1c579b1SScott Long } 2045ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 2046ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 2047ad6d6297SScott Long } 2048ad6d6297SScott Long break; 2049ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: { 2050ad6d6297SScott Long arcmsr_iop_parking(acb); 2051ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 2052ad6d6297SScott Long } 2053ad6d6297SScott Long break; 2054ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: { 2055ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2056ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 2057f1c579b1SScott Long } 2058f1c579b1SScott Long break; 2059f1c579b1SScott Long } 2060ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2061ad6d6297SScott Long return retvalue; 2062f1c579b1SScott Long } 2063f1c579b1SScott Long /* 2064f1c579b1SScott Long ************************************************************************** 2065f1c579b1SScott Long ************************************************************************** 2066f1c579b1SScott Long */ 2067*22f2616bSXin LI static void arcmsr_free_srb(struct CommandControlBlock *srb) 2068*22f2616bSXin LI { 2069*22f2616bSXin LI struct AdapterControlBlock *acb; 2070*22f2616bSXin LI int mutex; 2071*22f2616bSXin LI 2072*22f2616bSXin LI acb = srb->acb; 2073*22f2616bSXin LI mutex = mtx_owned(&acb->qbuffer_lock); 2074*22f2616bSXin LI if( mutex == 0 ) 2075*22f2616bSXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2076*22f2616bSXin LI srb->srb_state=ARCMSR_SRB_DONE; 2077*22f2616bSXin LI srb->srb_flags=0; 2078*22f2616bSXin LI acb->srbworkingQ[acb->workingsrb_doneindex]=srb; 2079*22f2616bSXin LI acb->workingsrb_doneindex++; 2080*22f2616bSXin LI acb->workingsrb_doneindex %= ARCMSR_MAX_FREESRB_NUM; 2081*22f2616bSXin LI if( mutex == 0 ) 2082*22f2616bSXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2083*22f2616bSXin LI } 2084*22f2616bSXin LI /* 2085*22f2616bSXin LI ************************************************************************** 2086*22f2616bSXin LI ************************************************************************** 2087*22f2616bSXin LI */ 2088ad6d6297SScott Long struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb) 2089f1c579b1SScott Long { 2090ad6d6297SScott Long struct CommandControlBlock *srb=NULL; 2091ad6d6297SScott Long u_int32_t workingsrb_startindex, workingsrb_doneindex; 2092f1c579b1SScott Long 2093579ec1a5SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2094ad6d6297SScott Long workingsrb_doneindex=acb->workingsrb_doneindex; 2095ad6d6297SScott Long workingsrb_startindex=acb->workingsrb_startindex; 2096ad6d6297SScott Long srb=acb->srbworkingQ[workingsrb_startindex]; 2097ad6d6297SScott Long workingsrb_startindex++; 2098ad6d6297SScott Long workingsrb_startindex %= ARCMSR_MAX_FREESRB_NUM; 2099ad6d6297SScott Long if(workingsrb_doneindex!=workingsrb_startindex) { 2100ad6d6297SScott Long acb->workingsrb_startindex=workingsrb_startindex; 2101ad6d6297SScott Long } else { 2102ad6d6297SScott Long srb=NULL; 2103ad6d6297SScott Long } 2104579ec1a5SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2105ad6d6297SScott Long return(srb); 2106ad6d6297SScott Long } 2107ad6d6297SScott Long /* 2108ad6d6297SScott Long ************************************************************************** 2109ad6d6297SScott Long ************************************************************************** 2110ad6d6297SScott Long */ 2111ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb) 2112ad6d6297SScott Long { 2113ad6d6297SScott Long struct CMD_MESSAGE_FIELD * pcmdmessagefld; 2114ad6d6297SScott Long int retvalue = 0, transfer_len = 0; 2115ad6d6297SScott Long char *buffer; 211644f05562SScott Long u_int32_t controlcode = (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[5] << 24 | 211744f05562SScott Long (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[6] << 16 | 211844f05562SScott Long (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[7] << 8 | 211944f05562SScott Long (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[8]; 2120ad6d6297SScott Long /* 4 bytes: Areca io control code */ 2121ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) { 2122ad6d6297SScott Long buffer = pccb->csio.data_ptr; 2123ad6d6297SScott Long transfer_len = pccb->csio.dxfer_len; 2124ad6d6297SScott Long } else { 2125ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2126ad6d6297SScott Long goto message_out; 2127ad6d6297SScott Long } 2128ad6d6297SScott Long if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) { 2129ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2130ad6d6297SScott Long goto message_out; 2131ad6d6297SScott Long } 2132ad6d6297SScott Long pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer; 2133ad6d6297SScott Long switch(controlcode) { 2134ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 2135ad6d6297SScott Long u_int8_t *pQbuffer; 2136ad6d6297SScott Long u_int8_t *ptmpQbuffer=pcmdmessagefld->messagedatabuffer; 2137ad6d6297SScott Long int32_t allxfer_len = 0; 2138f1c579b1SScott Long 2139ad6d6297SScott Long while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) 2140ad6d6297SScott Long && (allxfer_len < 1031)) { 2141ad6d6297SScott Long pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; 2142ad6d6297SScott Long memcpy(ptmpQbuffer, pQbuffer, 1); 2143ad6d6297SScott Long acb->rqbuf_firstindex++; 2144ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 2145ad6d6297SScott Long ptmpQbuffer++; 2146ad6d6297SScott Long allxfer_len++; 2147f1c579b1SScott Long } 2148ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 214944f05562SScott Long struct QBUFFER *prbuffer; 215044f05562SScott Long u_int8_t *iop_data; 2151ad6d6297SScott Long int32_t iop_len; 2152ad6d6297SScott Long 2153ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 215444f05562SScott Long prbuffer=arcmsr_get_iop_rqbuffer(acb); 215544f05562SScott Long iop_data = (u_int8_t *)prbuffer->data; 2156ad6d6297SScott Long iop_len =(u_int32_t)prbuffer->data_len; 2157ad6d6297SScott Long while (iop_len > 0) { 2158ad6d6297SScott Long pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex]; 2159ad6d6297SScott Long memcpy(pQbuffer, iop_data, 1); 2160ad6d6297SScott Long acb->rqbuf_lastindex++; 2161ad6d6297SScott Long acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 2162ad6d6297SScott Long iop_data++; 2163ad6d6297SScott Long iop_len--; 2164f1c579b1SScott Long } 216544f05562SScott Long arcmsr_iop_message_read(acb); 2166ad6d6297SScott Long } 2167ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length = allxfer_len; 2168ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2169ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 2170ad6d6297SScott Long } 2171ad6d6297SScott Long break; 2172ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 2173ad6d6297SScott Long int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 2174ad6d6297SScott Long u_int8_t *pQbuffer; 2175ad6d6297SScott Long u_int8_t *ptmpuserbuffer=pcmdmessagefld->messagedatabuffer; 2176ad6d6297SScott Long 2177ad6d6297SScott Long user_len = pcmdmessagefld->cmdmessage.Length; 2178ad6d6297SScott Long wqbuf_lastindex = acb->wqbuf_lastindex; 2179ad6d6297SScott Long wqbuf_firstindex = acb->wqbuf_firstindex; 2180ad6d6297SScott Long if (wqbuf_lastindex != wqbuf_firstindex) { 218144f05562SScott Long arcmsr_post_ioctldata2iop(acb); 2182ad6d6297SScott Long /* has error report sensedata */ 2183ad6d6297SScott Long if(&pccb->csio.sense_data) { 2184ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 2185ad6d6297SScott Long /* Valid,ErrorCode */ 2186ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 2187ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 2188ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 2189ad6d6297SScott Long /* AdditionalSenseLength */ 2190ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 2191ad6d6297SScott Long /* AdditionalSenseCode */ 2192ad6d6297SScott Long } 2193ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2194ad6d6297SScott Long } else { 2195ad6d6297SScott Long my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) 2196ad6d6297SScott Long &(ARCMSR_MAX_QBUFFER - 1); 2197ad6d6297SScott Long if (my_empty_len >= user_len) { 2198ad6d6297SScott Long while (user_len > 0) { 2199ad6d6297SScott Long pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; 2200ad6d6297SScott Long memcpy(pQbuffer, ptmpuserbuffer, 1); 2201ad6d6297SScott Long acb->wqbuf_lastindex++; 2202ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 2203ad6d6297SScott Long ptmpuserbuffer++; 2204ad6d6297SScott Long user_len--; 2205ad6d6297SScott Long } 2206ad6d6297SScott Long if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 2207ad6d6297SScott Long acb->acb_flags &= 2208ad6d6297SScott Long ~ACB_F_MESSAGE_WQBUFFER_CLEARED; 220944f05562SScott Long arcmsr_post_ioctldata2iop(acb); 2210ad6d6297SScott Long } 2211ad6d6297SScott Long } else { 2212ad6d6297SScott Long /* has error report sensedata */ 2213ad6d6297SScott Long if(&pccb->csio.sense_data) { 2214ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 2215ad6d6297SScott Long /* Valid,ErrorCode */ 2216ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 2217ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 2218ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 2219ad6d6297SScott Long /* AdditionalSenseLength */ 2220ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 2221ad6d6297SScott Long /* AdditionalSenseCode */ 2222ad6d6297SScott Long } 2223ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2224ad6d6297SScott Long } 2225ad6d6297SScott Long } 2226ad6d6297SScott Long } 2227ad6d6297SScott Long break; 2228ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 2229ad6d6297SScott Long u_int8_t *pQbuffer = acb->rqbuffer; 2230ad6d6297SScott Long 2231ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2232ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 223344f05562SScott Long arcmsr_iop_message_read(acb); 2234ad6d6297SScott Long } 2235ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 2236ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2237ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2238ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2239ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 2240ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 2241ad6d6297SScott Long } 2242ad6d6297SScott Long break; 2243ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { 2244ad6d6297SScott Long u_int8_t *pQbuffer = acb->wqbuffer; 2245ad6d6297SScott Long 2246ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2247ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 224844f05562SScott Long arcmsr_iop_message_read(acb); 2249ad6d6297SScott Long } 2250ad6d6297SScott Long acb->acb_flags |= 2251ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED | 225244f05562SScott Long ACB_F_MESSAGE_WQBUFFER_READ); 2253ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2254ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2255ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2256ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 2257ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 2258ad6d6297SScott Long } 2259ad6d6297SScott Long break; 2260ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 2261ad6d6297SScott Long u_int8_t *pQbuffer; 2262ad6d6297SScott Long 2263ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2264ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 226544f05562SScott Long arcmsr_iop_message_read(acb); 2266ad6d6297SScott Long } 2267ad6d6297SScott Long acb->acb_flags |= 2268ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED 2269ad6d6297SScott Long | ACB_F_MESSAGE_RQBUFFER_CLEARED 227044f05562SScott Long | ACB_F_MESSAGE_WQBUFFER_READ); 2271ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2272ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2273ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2274ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2275ad6d6297SScott Long pQbuffer = acb->rqbuffer; 2276ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 2277ad6d6297SScott Long pQbuffer = acb->wqbuffer; 2278ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 2279ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2280ad6d6297SScott Long } 2281ad6d6297SScott Long break; 2282ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 2283ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; 2284ad6d6297SScott Long } 2285ad6d6297SScott Long break; 2286ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 2287ad6d6297SScott Long int8_t * hello_string = "Hello! I am ARCMSR"; 2288ad6d6297SScott Long 2289ad6d6297SScott Long memcpy(pcmdmessagefld->messagedatabuffer, hello_string 2290ad6d6297SScott Long , (int16_t)strlen(hello_string)); 2291ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2292ad6d6297SScott Long } 2293ad6d6297SScott Long break; 2294ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: 2295ad6d6297SScott Long arcmsr_iop_parking(acb); 2296ad6d6297SScott Long break; 2297ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: 2298ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2299ad6d6297SScott Long break; 2300ad6d6297SScott Long default: 2301ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2302ad6d6297SScott Long } 2303ad6d6297SScott Long message_out: 2304ad6d6297SScott Long return retvalue; 2305f1c579b1SScott Long } 2306f1c579b1SScott Long /* 2307f1c579b1SScott Long ********************************************************************* 2308f1c579b1SScott Long ********************************************************************* 2309f1c579b1SScott Long */ 2310231c8b71SXin LI static void arcmsr_execute_srb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 2311f1c579b1SScott Long { 2312ad6d6297SScott Long struct CommandControlBlock *srb=(struct CommandControlBlock *)arg; 2313ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)srb->acb; 2314f1c579b1SScott Long union ccb * pccb; 2315ad6d6297SScott Long int target, lun; 2316f1c579b1SScott Long 2317ad6d6297SScott Long pccb=srb->pccb; 2318ad6d6297SScott Long target=pccb->ccb_h.target_id; 2319ad6d6297SScott Long lun=pccb->ccb_h.target_lun; 2320*22f2616bSXin LI #ifdef ARCMSR_DEBUG1 2321*22f2616bSXin LI acb->pktRequestCount++; 2322*22f2616bSXin LI #endif 2323ad6d6297SScott Long if(error != 0) { 2324ad6d6297SScott Long if(error != EFBIG) { 232544f05562SScott Long printf("arcmsr%d: unexpected error %x" 232644f05562SScott Long " returned from 'bus_dmamap_load' \n" 2327ad6d6297SScott Long , acb->pci_unit, error); 2328f1c579b1SScott Long } 2329ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { 233015735becSScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 2331f1c579b1SScott Long } 2332ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2333f1c579b1SScott Long return; 2334f1c579b1SScott Long } 2335ad6d6297SScott Long if(nseg > ARCMSR_MAX_SG_ENTRIES) { 2336ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 2337ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2338ad6d6297SScott Long return; 2339f1c579b1SScott Long } 2340ad6d6297SScott Long if(acb->acb_flags & ACB_F_BUS_RESET) { 2341ad6d6297SScott Long printf("arcmsr%d: bus reset and return busy \n", acb->pci_unit); 2342ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_BUS_RESET; 2343ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2344ad6d6297SScott Long return; 2345ad6d6297SScott Long } 2346ad6d6297SScott Long if(acb->devstate[target][lun]==ARECA_RAID_GONE) { 2347*22f2616bSXin LI u_int8_t block_cmd, cmd; 2348ad6d6297SScott Long 2349*22f2616bSXin LI cmd = pccb->csio.cdb_io.cdb_bytes[0]; 2350*22f2616bSXin LI block_cmd= cmd & 0x0f; 2351ad6d6297SScott Long if(block_cmd==0x08 || block_cmd==0x0a) { 2352ad6d6297SScott Long printf("arcmsr%d:block 'read/write' command " 2353*22f2616bSXin LI "with gone raid volume Cmd=0x%2x, TargetId=%d, Lun=%d \n" 2354*22f2616bSXin LI , acb->pci_unit, cmd, target, lun); 2355ad6d6297SScott Long pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 2356ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2357ad6d6297SScott Long return; 2358ad6d6297SScott Long } 2359ad6d6297SScott Long } 2360ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { 2361ad6d6297SScott Long if(nseg != 0) { 2362ad6d6297SScott Long bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 2363ad6d6297SScott Long } 2364ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2365f1c579b1SScott Long return; 2366f1c579b1SScott Long } 2367ad6d6297SScott Long if(acb->srboutstandingcount >= ARCMSR_MAX_OUTSTANDING_CMD) { 236815735becSScott Long xpt_freeze_simq(acb->psim, 1); 236915735becSScott Long pccb->ccb_h.status = CAM_REQUEUE_REQ; 2370dc3a205bSScott Long acb->acb_flags |= ACB_F_CAM_DEV_QFRZN; 2371ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2372ad6d6297SScott Long return; 2373f1c579b1SScott Long } 237415735becSScott Long pccb->ccb_h.status |= CAM_SIM_QUEUED; 2375ad6d6297SScott Long arcmsr_build_srb(srb, dm_segs, nseg); 2376ad6d6297SScott Long arcmsr_post_srb(acb, srb); 2377*22f2616bSXin LI if (pccb->ccb_h.timeout != CAM_TIME_INFINITY) 2378*22f2616bSXin LI { 2379*22f2616bSXin LI arcmsr_callout_init(&srb->ccb_callout); 2380*22f2616bSXin LI callout_reset(&srb->ccb_callout, (pccb->ccb_h.timeout * hz ) / 1000, arcmsr_srb_timeout, srb); 2381*22f2616bSXin LI srb->srb_flags |= SRB_FLAG_TIMER_START; 2382*22f2616bSXin LI } 2383f1c579b1SScott Long return; 2384f1c579b1SScott Long } 2385f1c579b1SScott Long /* 2386f1c579b1SScott Long ***************************************************************************************** 2387f1c579b1SScott Long ***************************************************************************************** 2388f1c579b1SScott Long */ 2389ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb) 2390f1c579b1SScott Long { 2391ad6d6297SScott Long struct CommandControlBlock *srb; 2392ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *) abortccb->ccb_h.arcmsr_ccbacb_ptr; 239344f05562SScott Long u_int32_t intmask_org; 2394ad6d6297SScott Long int i=0; 2395f1c579b1SScott Long 2396ad6d6297SScott Long acb->num_aborts++; 2397f1c579b1SScott Long /* 2398ad6d6297SScott Long *************************************************************************** 2399f1c579b1SScott Long ** It is the upper layer do abort command this lock just prior to calling us. 2400f1c579b1SScott Long ** First determine if we currently own this command. 2401f1c579b1SScott Long ** Start by searching the device queue. If not found 2402f1c579b1SScott Long ** at all, and the system wanted us to just abort the 2403f1c579b1SScott Long ** command return success. 2404ad6d6297SScott Long *************************************************************************** 2405f1c579b1SScott Long */ 2406ad6d6297SScott Long if(acb->srboutstandingcount!=0) { 2407*22f2616bSXin LI /* disable all outbound interrupt */ 2408*22f2616bSXin LI intmask_org=arcmsr_disable_allintr(acb); 2409ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 2410ad6d6297SScott Long srb=acb->psrb_pool[i]; 2411*22f2616bSXin LI if(srb->srb_state==ARCMSR_SRB_START) { 2412ad6d6297SScott Long if(srb->pccb==abortccb) { 2413*22f2616bSXin LI srb->srb_state=ARCMSR_SRB_ABORTED; 2414ad6d6297SScott Long printf("arcmsr%d:scsi id=%d lun=%d abort srb '%p'" 2415ad6d6297SScott Long "outstanding command \n" 2416ad6d6297SScott Long , acb->pci_unit, abortccb->ccb_h.target_id 2417ad6d6297SScott Long , abortccb->ccb_h.target_lun, srb); 2418ad6d6297SScott Long arcmsr_polling_srbdone(acb, srb); 241944f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 242044f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 2421ad6d6297SScott Long return (TRUE); 2422f1c579b1SScott Long } 2423*22f2616bSXin LI } 2424*22f2616bSXin LI } 2425*22f2616bSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 2426*22f2616bSXin LI arcmsr_enable_allintr(acb, intmask_org); 2427*22f2616bSXin LI } 2428*22f2616bSXin LI return(FALSE); 2429*22f2616bSXin LI } 2430f1c579b1SScott Long /* 2431f1c579b1SScott Long **************************************************************************** 2432f1c579b1SScott Long **************************************************************************** 2433f1c579b1SScott Long */ 2434ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb) 2435f1c579b1SScott Long { 2436ad6d6297SScott Long int retry=0; 2437f1c579b1SScott Long 2438ad6d6297SScott Long acb->num_resets++; 2439ad6d6297SScott Long acb->acb_flags |=ACB_F_BUS_RESET; 2440ad6d6297SScott Long while(acb->srboutstandingcount!=0 && retry < 400) { 244144f05562SScott Long arcmsr_interrupt(acb); 2442ad6d6297SScott Long UDELAY(25000); 2443ad6d6297SScott Long retry++; 2444ad6d6297SScott Long } 2445ad6d6297SScott Long arcmsr_iop_reset(acb); 2446ad6d6297SScott Long acb->acb_flags &= ~ACB_F_BUS_RESET; 2447f1c579b1SScott Long return; 2448f1c579b1SScott Long } 2449f1c579b1SScott Long /* 2450ad6d6297SScott Long ************************************************************************** 2451ad6d6297SScott Long ************************************************************************** 2452ad6d6297SScott Long */ 2453ad6d6297SScott Long static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, 2454ad6d6297SScott Long union ccb * pccb) 2455ad6d6297SScott Long { 2456ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2457ad6d6297SScott Long switch (pccb->csio.cdb_io.cdb_bytes[0]) { 2458ad6d6297SScott Long case INQUIRY: { 2459ad6d6297SScott Long unsigned char inqdata[36]; 2460c2ede4b3SMartin Blapp char *buffer=pccb->csio.data_ptr; 2461ad6d6297SScott Long 2462ad6d6297SScott Long if (pccb->ccb_h.target_lun) { 2463ad6d6297SScott Long pccb->ccb_h.status |= CAM_SEL_TIMEOUT; 2464ad6d6297SScott Long xpt_done(pccb); 2465ad6d6297SScott Long return; 2466ad6d6297SScott Long } 2467231c8b71SXin LI inqdata[0] = T_PROCESSOR; /* Periph Qualifier & Periph Dev Type */ 2468231c8b71SXin LI inqdata[1] = 0; /* rem media bit & Dev Type Modifier */ 2469231c8b71SXin LI inqdata[2] = 0; /* ISO, ECMA, & ANSI versions */ 2470231c8b71SXin LI inqdata[3] = 0; 2471231c8b71SXin LI inqdata[4] = 31; /* length of additional data */ 2472231c8b71SXin LI inqdata[5] = 0; 2473231c8b71SXin LI inqdata[6] = 0; 2474231c8b71SXin LI inqdata[7] = 0; 2475231c8b71SXin LI strncpy(&inqdata[8], "Areca ", 8); /* Vendor Identification */ 2476231c8b71SXin LI strncpy(&inqdata[16], "RAID controller ", 16); /* Product Identification */ 2477ad6d6297SScott Long strncpy(&inqdata[32], "R001", 4); /* Product Revision */ 2478ad6d6297SScott Long memcpy(buffer, inqdata, sizeof(inqdata)); 2479ad6d6297SScott Long xpt_done(pccb); 2480ad6d6297SScott Long } 2481ad6d6297SScott Long break; 2482ad6d6297SScott Long case WRITE_BUFFER: 2483ad6d6297SScott Long case READ_BUFFER: { 2484ad6d6297SScott Long if (arcmsr_iop_message_xfer(acb, pccb)) { 2485ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 2486ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 2487ad6d6297SScott Long } 2488ad6d6297SScott Long xpt_done(pccb); 2489ad6d6297SScott Long } 2490ad6d6297SScott Long break; 2491ad6d6297SScott Long default: 2492ad6d6297SScott Long xpt_done(pccb); 2493ad6d6297SScott Long } 2494ad6d6297SScott Long } 2495ad6d6297SScott Long /* 2496f1c579b1SScott Long ********************************************************************* 2497f1c579b1SScott Long ********************************************************************* 2498f1c579b1SScott Long */ 2499ad6d6297SScott Long static void arcmsr_action(struct cam_sim * psim, union ccb * pccb) 2500f1c579b1SScott Long { 2501ad6d6297SScott Long struct AdapterControlBlock * acb; 2502f1c579b1SScott Long 2503ad6d6297SScott Long acb=(struct AdapterControlBlock *) cam_sim_softc(psim); 2504ad6d6297SScott Long if(acb==NULL) { 2505ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2506f1c579b1SScott Long xpt_done(pccb); 2507f1c579b1SScott Long return; 2508f1c579b1SScott Long } 2509ad6d6297SScott Long switch (pccb->ccb_h.func_code) { 2510ad6d6297SScott Long case XPT_SCSI_IO: { 2511ad6d6297SScott Long struct CommandControlBlock *srb; 2512ad6d6297SScott Long int target=pccb->ccb_h.target_id; 2513f1c579b1SScott Long 2514ad6d6297SScott Long if(target == 16) { 2515ad6d6297SScott Long /* virtual device for iop message transfer */ 2516ad6d6297SScott Long arcmsr_handle_virtual_command(acb, pccb); 2517ad6d6297SScott Long return; 2518ad6d6297SScott Long } 2519ad6d6297SScott Long if((srb=arcmsr_get_freesrb(acb)) == NULL) { 2520ad6d6297SScott Long pccb->ccb_h.status |= CAM_RESRC_UNAVAIL; 2521f1c579b1SScott Long xpt_done(pccb); 2522f1c579b1SScott Long return; 2523f1c579b1SScott Long } 2524ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbsrb_ptr=srb; 2525ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbacb_ptr=acb; 2526ad6d6297SScott Long srb->pccb=pccb; 2527ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 2528ad6d6297SScott Long if(!(pccb->ccb_h.flags & CAM_SCATTER_VALID)) { 2529ad6d6297SScott Long /* Single buffer */ 2530ad6d6297SScott Long if(!(pccb->ccb_h.flags & CAM_DATA_PHYS)) { 2531ad6d6297SScott Long /* Buffer is virtual */ 2532ad6d6297SScott Long u_int32_t error, s; 2533f1c579b1SScott Long 2534f1c579b1SScott Long s=splsoftvm(); 2535ad6d6297SScott Long error = bus_dmamap_load(acb->dm_segs_dmat 2536ad6d6297SScott Long , srb->dm_segs_dmamap 2537ad6d6297SScott Long , pccb->csio.data_ptr 2538ad6d6297SScott Long , pccb->csio.dxfer_len 2539231c8b71SXin LI , arcmsr_execute_srb, srb, /*flags*/0); 2540ad6d6297SScott Long if(error == EINPROGRESS) { 2541ad6d6297SScott Long xpt_freeze_simq(acb->psim, 1); 2542f1c579b1SScott Long pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 2543f1c579b1SScott Long } 2544f1c579b1SScott Long splx(s); 2545231c8b71SXin LI } 2546231c8b71SXin LI else { /* Buffer is physical */ 2547add5afdcSXin LI #ifdef PAE 2548add5afdcSXin LI panic("arcmsr: CAM_DATA_PHYS not supported"); 2549add5afdcSXin LI #else 2550231c8b71SXin LI struct bus_dma_segment seg; 2551231c8b71SXin LI 2552231c8b71SXin LI seg.ds_addr = (bus_addr_t)pccb->csio.data_ptr; 2553231c8b71SXin LI seg.ds_len = pccb->csio.dxfer_len; 2554231c8b71SXin LI arcmsr_execute_srb(srb, &seg, 1, 0); 2555add5afdcSXin LI #endif 2556f1c579b1SScott Long } 2557ad6d6297SScott Long } else { 2558ad6d6297SScott Long /* Scatter/gather list */ 2559f1c579b1SScott Long struct bus_dma_segment *segs; 2560f1c579b1SScott Long 2561ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0 2562ad6d6297SScott Long || (pccb->ccb_h.flags & CAM_DATA_PHYS) != 0) { 2563ad6d6297SScott Long pccb->ccb_h.status |= CAM_PROVIDE_FAIL; 2564f1c579b1SScott Long xpt_done(pccb); 2565ad6d6297SScott Long free(srb, M_DEVBUF); 2566f1c579b1SScott Long return; 2567f1c579b1SScott Long } 2568f1c579b1SScott Long segs=(struct bus_dma_segment *)pccb->csio.data_ptr; 2569231c8b71SXin LI arcmsr_execute_srb(srb, segs, pccb->csio.sglist_cnt, 0); 2570f1c579b1SScott Long } 2571ad6d6297SScott Long } else { 2572231c8b71SXin LI arcmsr_execute_srb(srb, NULL, 0, 0); 2573f1c579b1SScott Long } 2574f1c579b1SScott Long break; 2575f1c579b1SScott Long } 2576ad6d6297SScott Long case XPT_TARGET_IO: { 2577ad6d6297SScott Long /* target mode not yet support vendor specific commands. */ 2578ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2579f1c579b1SScott Long xpt_done(pccb); 2580f1c579b1SScott Long break; 2581f1c579b1SScott Long } 2582ad6d6297SScott Long case XPT_PATH_INQ: { 2583f1c579b1SScott Long struct ccb_pathinq *cpi= &pccb->cpi; 2584f1c579b1SScott Long 2585f1c579b1SScott Long cpi->version_num=1; 2586f1c579b1SScott Long cpi->hba_inquiry=PI_SDTR_ABLE | PI_TAG_ABLE; 2587f1c579b1SScott Long cpi->target_sprt=0; 2588f1c579b1SScott Long cpi->hba_misc=0; 2589f1c579b1SScott Long cpi->hba_eng_cnt=0; 2590ad6d6297SScott Long cpi->max_target=ARCMSR_MAX_TARGETID; /* 0-16 */ 2591ad6d6297SScott Long cpi->max_lun=ARCMSR_MAX_TARGETLUN; /* 0-7 */ 2592ad6d6297SScott Long cpi->initiator_id=ARCMSR_SCSI_INITIATOR_ID; /* 255 */ 2593f1c579b1SScott Long cpi->bus_id=cam_sim_bus(psim); 2594f1c579b1SScott Long strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 2595f1c579b1SScott Long strncpy(cpi->hba_vid, "ARCMSR", HBA_IDLEN); 2596f1c579b1SScott Long strncpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN); 2597f1c579b1SScott Long cpi->unit_number=cam_sim_unit(psim); 259844f05562SScott Long #ifdef CAM_NEW_TRAN_CODE 2599fa9ed865SMatt Jacob cpi->transport = XPORT_SPI; 2600fa9ed865SMatt Jacob cpi->transport_version = 2; 2601fa9ed865SMatt Jacob cpi->protocol = PROTO_SCSI; 2602fa9ed865SMatt Jacob cpi->protocol_version = SCSI_REV_2; 260344f05562SScott Long #endif 2604ad6d6297SScott Long cpi->ccb_h.status |= CAM_REQ_CMP; 2605f1c579b1SScott Long xpt_done(pccb); 2606f1c579b1SScott Long break; 2607f1c579b1SScott Long } 2608ad6d6297SScott Long case XPT_ABORT: { 2609f1c579b1SScott Long union ccb *pabort_ccb; 2610f1c579b1SScott Long 2611f1c579b1SScott Long pabort_ccb=pccb->cab.abort_ccb; 2612ad6d6297SScott Long switch (pabort_ccb->ccb_h.func_code) { 2613f1c579b1SScott Long case XPT_ACCEPT_TARGET_IO: 2614f1c579b1SScott Long case XPT_IMMED_NOTIFY: 2615f1c579b1SScott Long case XPT_CONT_TARGET_IO: 2616ad6d6297SScott Long if(arcmsr_seek_cmd2abort(pabort_ccb)==TRUE) { 2617ad6d6297SScott Long pabort_ccb->ccb_h.status |= CAM_REQ_ABORTED; 2618f1c579b1SScott Long xpt_done(pabort_ccb); 2619ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2620ad6d6297SScott Long } else { 2621f1c579b1SScott Long xpt_print_path(pabort_ccb->ccb_h.path); 2622f1c579b1SScott Long printf("Not found\n"); 2623ad6d6297SScott Long pccb->ccb_h.status |= CAM_PATH_INVALID; 2624f1c579b1SScott Long } 2625f1c579b1SScott Long break; 2626f1c579b1SScott Long case XPT_SCSI_IO: 2627ad6d6297SScott Long pccb->ccb_h.status |= CAM_UA_ABORT; 2628f1c579b1SScott Long break; 2629f1c579b1SScott Long default: 2630ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2631f1c579b1SScott Long break; 2632f1c579b1SScott Long } 2633f1c579b1SScott Long xpt_done(pccb); 2634f1c579b1SScott Long break; 2635f1c579b1SScott Long } 2636f1c579b1SScott Long case XPT_RESET_BUS: 2637ad6d6297SScott Long case XPT_RESET_DEV: { 2638ad6d6297SScott Long u_int32_t i; 2639f1c579b1SScott Long 2640ad6d6297SScott Long arcmsr_bus_reset(acb); 2641ad6d6297SScott Long for (i=0; i < 500; i++) { 2642f1c579b1SScott Long DELAY(1000); 2643f1c579b1SScott Long } 2644ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2645f1c579b1SScott Long xpt_done(pccb); 2646f1c579b1SScott Long break; 2647f1c579b1SScott Long } 2648ad6d6297SScott Long case XPT_TERM_IO: { 2649ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2650f1c579b1SScott Long xpt_done(pccb); 2651f1c579b1SScott Long break; 2652f1c579b1SScott Long } 2653ad6d6297SScott Long case XPT_GET_TRAN_SETTINGS: { 2654ad6d6297SScott Long struct ccb_trans_settings *cts; 2655ad6d6297SScott Long 2656ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 2657ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 2658ad6d6297SScott Long xpt_done(pccb); 2659ad6d6297SScott Long break; 2660ad6d6297SScott Long } 2661ad6d6297SScott Long cts= &pccb->cts; 266244f05562SScott Long #ifdef CAM_NEW_TRAN_CODE 266344f05562SScott Long { 266444f05562SScott Long struct ccb_trans_settings_scsi *scsi; 266544f05562SScott Long struct ccb_trans_settings_spi *spi; 266644f05562SScott Long 2667ad6d6297SScott Long scsi = &cts->proto_specific.scsi; 2668ad6d6297SScott Long spi = &cts->xport_specific.spi; 2669fa9ed865SMatt Jacob cts->protocol = PROTO_SCSI; 2670fa9ed865SMatt Jacob cts->protocol_version = SCSI_REV_2; 2671fa9ed865SMatt Jacob cts->transport = XPORT_SPI; 2672fa9ed865SMatt Jacob cts->transport_version = 2; 2673fa9ed865SMatt Jacob spi->flags = CTS_SPI_FLAGS_DISC_ENB; 2674fa9ed865SMatt Jacob spi->sync_period=3; 2675fa9ed865SMatt Jacob spi->sync_offset=32; 2676fa9ed865SMatt Jacob spi->bus_width=MSG_EXT_WDTR_BUS_16_BIT; 2677fa9ed865SMatt Jacob scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 26789d98ff4dSScott Long spi->valid = CTS_SPI_VALID_DISC 26799d98ff4dSScott Long | CTS_SPI_VALID_SYNC_RATE 2680fa9ed865SMatt Jacob | CTS_SPI_VALID_SYNC_OFFSET 2681fa9ed865SMatt Jacob | CTS_SPI_VALID_BUS_WIDTH; 2682fa9ed865SMatt Jacob scsi->valid = CTS_SCSI_VALID_TQ; 268344f05562SScott Long } 268444f05562SScott Long #else 268544f05562SScott Long { 268644f05562SScott Long cts->flags=(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB); 268744f05562SScott Long cts->sync_period=3; 268844f05562SScott Long cts->sync_offset=32; 268944f05562SScott Long cts->bus_width=MSG_EXT_WDTR_BUS_16_BIT; 269044f05562SScott Long cts->valid=CCB_TRANS_SYNC_RATE_VALID | 269144f05562SScott Long CCB_TRANS_SYNC_OFFSET_VALID | 269244f05562SScott Long CCB_TRANS_BUS_WIDTH_VALID | 269344f05562SScott Long CCB_TRANS_DISC_VALID | 269444f05562SScott Long CCB_TRANS_TQ_VALID; 269544f05562SScott Long } 269644f05562SScott Long #endif 2697ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2698ad6d6297SScott Long xpt_done(pccb); 2699ad6d6297SScott Long break; 2700ad6d6297SScott Long } 2701ad6d6297SScott Long case XPT_SET_TRAN_SETTINGS: { 2702ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 2703ad6d6297SScott Long xpt_done(pccb); 2704ad6d6297SScott Long break; 2705ad6d6297SScott Long } 2706ad6d6297SScott Long case XPT_CALC_GEOMETRY: { 2707ad6d6297SScott Long struct ccb_calc_geometry *ccg; 2708ad6d6297SScott Long u_int32_t size_mb; 2709ad6d6297SScott Long u_int32_t secs_per_cylinder; 2710ad6d6297SScott Long 2711ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 2712ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 2713ad6d6297SScott Long xpt_done(pccb); 2714ad6d6297SScott Long break; 2715ad6d6297SScott Long } 2716f1c579b1SScott Long ccg= &pccb->ccg; 2717ad6d6297SScott Long if (ccg->block_size == 0) { 2718ad6d6297SScott Long pccb->ccb_h.status = CAM_REQ_INVALID; 2719ad6d6297SScott Long xpt_done(pccb); 2720ad6d6297SScott Long break; 2721ad6d6297SScott Long } 2722ad6d6297SScott Long if(((1024L * 1024L)/ccg->block_size) < 0) { 2723ad6d6297SScott Long pccb->ccb_h.status = CAM_REQ_INVALID; 2724ad6d6297SScott Long xpt_done(pccb); 2725ad6d6297SScott Long break; 2726ad6d6297SScott Long } 2727f1c579b1SScott Long size_mb=ccg->volume_size/((1024L * 1024L)/ccg->block_size); 2728ad6d6297SScott Long if(size_mb > 1024 ) { 2729f1c579b1SScott Long ccg->heads=255; 2730f1c579b1SScott Long ccg->secs_per_track=63; 2731ad6d6297SScott Long } else { 2732f1c579b1SScott Long ccg->heads=64; 2733f1c579b1SScott Long ccg->secs_per_track=32; 2734f1c579b1SScott Long } 2735f1c579b1SScott Long secs_per_cylinder=ccg->heads * ccg->secs_per_track; 2736f1c579b1SScott Long ccg->cylinders=ccg->volume_size / secs_per_cylinder; 2737ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2738f1c579b1SScott Long xpt_done(pccb); 2739f1c579b1SScott Long break; 2740f1c579b1SScott Long } 2741f1c579b1SScott Long default: 2742ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2743f1c579b1SScott Long xpt_done(pccb); 2744f1c579b1SScott Long break; 2745f1c579b1SScott Long } 2746f1c579b1SScott Long return; 2747f1c579b1SScott Long } 2748f1c579b1SScott Long /* 2749f1c579b1SScott Long ********************************************************************** 2750f1c579b1SScott Long ********************************************************************** 2751f1c579b1SScott Long */ 275244f05562SScott Long static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) 2753f1c579b1SScott Long { 2754ad6d6297SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 275544f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 275644f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 2757ad6d6297SScott Long printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 2758ad6d6297SScott Long } 2759f1c579b1SScott Long return; 2760f1c579b1SScott Long } 2761f1c579b1SScott Long /* 2762f1c579b1SScott Long ********************************************************************** 2763f1c579b1SScott Long ********************************************************************** 2764f1c579b1SScott Long */ 276544f05562SScott Long static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb) 276644f05562SScott Long { 276744f05562SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 2768d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_START_BGRB); 276944f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 277044f05562SScott Long printf( "arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 277144f05562SScott Long } 277244f05562SScott Long return; 277344f05562SScott Long } 277444f05562SScott Long /* 277544f05562SScott Long ********************************************************************** 277644f05562SScott Long ********************************************************************** 277744f05562SScott Long */ 2778d74001adSXin LI static void arcmsr_start_hbc_bgrb(struct AdapterControlBlock *acb) 2779d74001adSXin LI { 2780d74001adSXin LI acb->acb_flags |= ACB_F_MSG_START_BGRB; 2781d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 2782d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 2783d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 2784d74001adSXin LI printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 2785d74001adSXin LI } 2786d74001adSXin LI return; 2787d74001adSXin LI } 2788d74001adSXin LI /* 2789d74001adSXin LI ********************************************************************** 2790d74001adSXin LI ********************************************************************** 2791d74001adSXin LI */ 279244f05562SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) 279344f05562SScott Long { 279444f05562SScott Long switch (acb->adapter_type) { 279544f05562SScott Long case ACB_ADAPTER_TYPE_A: 279644f05562SScott Long arcmsr_start_hba_bgrb(acb); 279744f05562SScott Long break; 279844f05562SScott Long case ACB_ADAPTER_TYPE_B: 279944f05562SScott Long arcmsr_start_hbb_bgrb(acb); 280044f05562SScott Long break; 2801d74001adSXin LI case ACB_ADAPTER_TYPE_C: 2802d74001adSXin LI arcmsr_start_hbc_bgrb(acb); 2803d74001adSXin LI break; 280444f05562SScott Long } 280544f05562SScott Long return; 280644f05562SScott Long } 280744f05562SScott Long /* 280844f05562SScott Long ********************************************************************** 280944f05562SScott Long ** 281044f05562SScott Long ********************************************************************** 281144f05562SScott Long */ 281244f05562SScott Long static void arcmsr_polling_hba_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 2813f1c579b1SScott Long { 2814ad6d6297SScott Long struct CommandControlBlock *srb; 281544f05562SScott Long u_int32_t flag_srb, outbound_intstatus, poll_srb_done=0, poll_count=0; 2816d74001adSXin LI u_int16_t error; 2817f1c579b1SScott Long 281844f05562SScott Long polling_ccb_retry: 2819ad6d6297SScott Long poll_count++; 2820d74001adSXin LI outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 2821d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus); /*clear interrupt*/ 282244f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 2823ad6d6297SScott Long while(1) { 282444f05562SScott Long if((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 282544f05562SScott Long 0, outbound_queueport))==0xFFFFFFFF) { 2826ad6d6297SScott Long if(poll_srb_done) { 2827ad6d6297SScott Long break;/*chip FIFO no ccb for completion already*/ 2828ad6d6297SScott Long } else { 2829ad6d6297SScott Long UDELAY(25000); 2830d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 2831ad6d6297SScott Long break; 2832f1c579b1SScott Long } 283344f05562SScott Long goto polling_ccb_retry; 2834f1c579b1SScott Long } 2835ad6d6297SScott Long } 2836ad6d6297SScott Long /* check if command done with no error*/ 283744f05562SScott Long srb=(struct CommandControlBlock *) 283844f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 2839d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 284044f05562SScott Long poll_srb_done = (srb==poll_srb) ? 1:0; 2841*22f2616bSXin LI if((srb->acb!=acb) || (srb->srb_state!=ARCMSR_SRB_START)) { 2842*22f2616bSXin LI if(srb->srb_state==ARCMSR_SRB_ABORTED) { 2843ad6d6297SScott Long printf("arcmsr%d: scsi id=%d lun=%d srb='%p'" 2844ad6d6297SScott Long "poll command abort successfully \n" 2845ad6d6297SScott Long , acb->pci_unit 2846ad6d6297SScott Long , srb->pccb->ccb_h.target_id 2847ad6d6297SScott Long , srb->pccb->ccb_h.target_lun, srb); 2848ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 2849ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 2850ad6d6297SScott Long continue; 2851ad6d6297SScott Long } 2852ad6d6297SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 2853ad6d6297SScott Long "srboutstandingcount=%d \n" 2854ad6d6297SScott Long , acb->pci_unit 2855ad6d6297SScott Long , srb, acb->srboutstandingcount); 2856ad6d6297SScott Long continue; 2857ad6d6297SScott Long } 2858d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 2859ad6d6297SScott Long } /*drain reply FIFO*/ 2860f1c579b1SScott Long return; 2861f1c579b1SScott Long } 2862f1c579b1SScott Long /* 2863f1c579b1SScott Long ********************************************************************** 286444f05562SScott Long ** 2865ad6d6297SScott Long ********************************************************************** 2866ad6d6297SScott Long */ 286744f05562SScott Long static void arcmsr_polling_hbb_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 286844f05562SScott Long { 286944f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 287044f05562SScott Long struct CommandControlBlock *srb; 287144f05562SScott Long u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 287244f05562SScott Long int index; 2873d74001adSXin LI u_int16_t error; 287444f05562SScott Long 287544f05562SScott Long polling_ccb_retry: 287644f05562SScott Long poll_count++; 287744f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 287844f05562SScott Long 0, iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 287944f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 288044f05562SScott Long while(1) { 288144f05562SScott Long index=phbbmu->doneq_index; 288244f05562SScott Long if((flag_srb=phbbmu->done_qbuffer[index]) == 0) { 288344f05562SScott Long if(poll_srb_done) { 288444f05562SScott Long break;/*chip FIFO no ccb for completion already*/ 288544f05562SScott Long } else { 288644f05562SScott Long UDELAY(25000); 2887d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 288844f05562SScott Long break; 288944f05562SScott Long } 289044f05562SScott Long goto polling_ccb_retry; 289144f05562SScott Long } 289244f05562SScott Long } 289344f05562SScott Long phbbmu->done_qbuffer[index]=0; 289444f05562SScott Long index++; 289544f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 289644f05562SScott Long phbbmu->doneq_index=index; 289744f05562SScott Long /* check if command done with no error*/ 289844f05562SScott Long srb=(struct CommandControlBlock *) 289944f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 2900d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 290144f05562SScott Long poll_srb_done = (srb==poll_srb) ? 1:0; 2902*22f2616bSXin LI if((srb->acb!=acb) || (srb->srb_state!=ARCMSR_SRB_START)) { 2903*22f2616bSXin LI if(srb->srb_state==ARCMSR_SRB_ABORTED) { 290444f05562SScott Long printf("arcmsr%d: scsi id=%d lun=%d srb='%p'" 290544f05562SScott Long "poll command abort successfully \n" 290644f05562SScott Long , acb->pci_unit 290744f05562SScott Long , srb->pccb->ccb_h.target_id 290844f05562SScott Long , srb->pccb->ccb_h.target_lun, srb); 290944f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 291044f05562SScott Long arcmsr_srb_complete(srb, 1); 291144f05562SScott Long continue; 291244f05562SScott Long } 291344f05562SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 291444f05562SScott Long "srboutstandingcount=%d \n" 291544f05562SScott Long , acb->pci_unit 291644f05562SScott Long , srb, acb->srboutstandingcount); 291744f05562SScott Long continue; 291844f05562SScott Long } 2919d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 2920d74001adSXin LI } /*drain reply FIFO*/ 2921d74001adSXin LI return; 2922d74001adSXin LI } 2923d74001adSXin LI /* 2924d74001adSXin LI ********************************************************************** 2925d74001adSXin LI ** 2926d74001adSXin LI ********************************************************************** 2927d74001adSXin LI */ 2928d74001adSXin LI static void arcmsr_polling_hbc_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 2929d74001adSXin LI { 2930d74001adSXin LI struct CommandControlBlock *srb; 2931d74001adSXin LI u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 2932d74001adSXin LI u_int16_t error; 2933d74001adSXin LI 2934d74001adSXin LI polling_ccb_retry: 2935d74001adSXin LI poll_count++; 2936d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 2937d74001adSXin LI while(1) { 2938d74001adSXin LI if(!(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR)) { 2939d74001adSXin LI if(poll_srb_done) { 2940d74001adSXin LI break;/*chip FIFO no ccb for completion already*/ 2941d74001adSXin LI } else { 2942d74001adSXin LI UDELAY(25000); 2943d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 2944d74001adSXin LI break; 2945d74001adSXin LI } 2946d74001adSXin LI if (acb->srboutstandingcount == 0) { 2947d74001adSXin LI break; 2948d74001adSXin LI } 2949d74001adSXin LI goto polling_ccb_retry; 2950d74001adSXin LI } 2951d74001adSXin LI } 2952d74001adSXin LI flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 2953d74001adSXin LI /* check if command done with no error*/ 2954*22f2616bSXin LI srb=(struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/ 2955d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; 2956d74001adSXin LI if (poll_srb != NULL) 2957d74001adSXin LI poll_srb_done = (srb==poll_srb) ? 1:0; 2958*22f2616bSXin LI if((srb->acb!=acb) || (srb->srb_state!=ARCMSR_SRB_START)) { 2959*22f2616bSXin LI if(srb->srb_state==ARCMSR_SRB_ABORTED) { 2960d74001adSXin LI printf("arcmsr%d: scsi id=%d lun=%d srb='%p'poll command abort successfully \n" 2961d74001adSXin LI , acb->pci_unit, srb->pccb->ccb_h.target_id, srb->pccb->ccb_h.target_lun, srb); 2962d74001adSXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 2963d74001adSXin LI arcmsr_srb_complete(srb, 1); 2964d74001adSXin LI continue; 2965d74001adSXin LI } 2966d74001adSXin LI printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n" 2967d74001adSXin LI , acb->pci_unit, srb, acb->srboutstandingcount); 2968d74001adSXin LI continue; 2969d74001adSXin LI } 2970d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 297144f05562SScott Long } /*drain reply FIFO*/ 297244f05562SScott Long return; 297344f05562SScott Long } 297444f05562SScott Long /* 297544f05562SScott Long ********************************************************************** 297644f05562SScott Long ********************************************************************** 297744f05562SScott Long */ 297844f05562SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 297944f05562SScott Long { 298044f05562SScott Long switch (acb->adapter_type) { 298144f05562SScott Long case ACB_ADAPTER_TYPE_A: { 298244f05562SScott Long arcmsr_polling_hba_srbdone(acb, poll_srb); 298344f05562SScott Long } 298444f05562SScott Long break; 298544f05562SScott Long case ACB_ADAPTER_TYPE_B: { 298644f05562SScott Long arcmsr_polling_hbb_srbdone(acb, poll_srb); 298744f05562SScott Long } 298844f05562SScott Long break; 2989d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 2990d74001adSXin LI arcmsr_polling_hbc_srbdone(acb, poll_srb); 2991d74001adSXin LI } 2992d74001adSXin LI break; 299344f05562SScott Long } 299444f05562SScott Long } 299544f05562SScott Long /* 299644f05562SScott Long ********************************************************************** 299744f05562SScott Long ********************************************************************** 299844f05562SScott Long */ 299944f05562SScott Long static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) 3000ad6d6297SScott Long { 3001ad6d6297SScott Long char *acb_firm_model=acb->firm_model; 3002ad6d6297SScott Long char *acb_firm_version=acb->firm_version; 3003d74001adSXin LI char *acb_device_map = acb->device_map; 3004d74001adSXin LI size_t iop_firm_model=offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3005d74001adSXin LI size_t iop_firm_version=offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3006d74001adSXin LI size_t iop_device_map = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 3007ad6d6297SScott Long int i; 3008ad6d6297SScott Long 300944f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 301044f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 3011d74001adSXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 3012ad6d6297SScott Long } 3013ad6d6297SScott Long i=0; 3014ad6d6297SScott Long while(i<8) { 301544f05562SScott Long *acb_firm_model=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 3016ad6d6297SScott Long /* 8 bytes firm_model, 15, 60-67*/ 3017ad6d6297SScott Long acb_firm_model++; 3018ad6d6297SScott Long i++; 3019ad6d6297SScott Long } 3020ad6d6297SScott Long i=0; 3021ad6d6297SScott Long while(i<16) { 302244f05562SScott Long *acb_firm_version=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 3023ad6d6297SScott Long /* 16 bytes firm_version, 17, 68-83*/ 3024ad6d6297SScott Long acb_firm_version++; 3025ad6d6297SScott Long i++; 3026ad6d6297SScott Long } 3027d74001adSXin LI i=0; 3028d74001adSXin LI while(i<16) { 3029d74001adSXin LI *acb_device_map=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 3030d74001adSXin LI acb_device_map++; 3031d74001adSXin LI i++; 3032d74001adSXin LI } 3033ad6d6297SScott Long printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION); 3034ad6d6297SScott Long printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version); 3035d74001adSXin LI acb->firm_request_len=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3036d74001adSXin LI acb->firm_numbers_queue=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3037d74001adSXin LI acb->firm_sdram_size=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3038d74001adSXin LI acb->firm_ide_channels=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3039d74001adSXin LI acb->firm_cfg_version=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3040ad6d6297SScott Long return; 3041ad6d6297SScott Long } 3042ad6d6297SScott Long /* 3043ad6d6297SScott Long ********************************************************************** 304444f05562SScott Long ********************************************************************** 304544f05562SScott Long */ 304644f05562SScott Long static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) 304744f05562SScott Long { 304844f05562SScott Long char *acb_firm_model=acb->firm_model; 304944f05562SScott Long char *acb_firm_version=acb->firm_version; 3050d74001adSXin LI char *acb_device_map = acb->device_map; 3051d74001adSXin LI size_t iop_firm_model=offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3052d74001adSXin LI size_t iop_firm_version=offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3053d74001adSXin LI size_t iop_device_map = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 305444f05562SScott Long int i; 305544f05562SScott Long 3056d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG); 305744f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 3058d74001adSXin LI printf( "arcmsr%d: wait" "'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 305944f05562SScott Long } 306044f05562SScott Long i=0; 306144f05562SScott Long while(i<8) { 306244f05562SScott Long *acb_firm_model=bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_model+i); 306344f05562SScott Long /* 8 bytes firm_model, 15, 60-67*/ 306444f05562SScott Long acb_firm_model++; 306544f05562SScott Long i++; 306644f05562SScott Long } 306744f05562SScott Long i=0; 306844f05562SScott Long while(i<16) { 306944f05562SScott Long *acb_firm_version=bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_version+i); 307044f05562SScott Long /* 16 bytes firm_version, 17, 68-83*/ 307144f05562SScott Long acb_firm_version++; 307244f05562SScott Long i++; 307344f05562SScott Long } 3074d74001adSXin LI i=0; 3075d74001adSXin LI while(i<16) { 3076d74001adSXin LI *acb_device_map=bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_device_map+i); 3077d74001adSXin LI acb_device_map++; 3078d74001adSXin LI i++; 3079d74001adSXin LI } 308044f05562SScott Long printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION); 308144f05562SScott Long printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version); 3082d74001adSXin LI acb->firm_request_len=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3083d74001adSXin LI acb->firm_numbers_queue=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3084d74001adSXin LI acb->firm_sdram_size=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3085d74001adSXin LI acb->firm_ide_channels=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3086d74001adSXin LI acb->firm_cfg_version=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3087d74001adSXin LI return; 3088d74001adSXin LI } 3089d74001adSXin LI /* 3090d74001adSXin LI ********************************************************************** 3091d74001adSXin LI ********************************************************************** 3092d74001adSXin LI */ 3093d74001adSXin LI static void arcmsr_get_hbc_config(struct AdapterControlBlock *acb) 3094d74001adSXin LI { 3095d74001adSXin LI char *acb_firm_model=acb->firm_model; 3096d74001adSXin LI char *acb_firm_version=acb->firm_version; 3097d74001adSXin LI char *acb_device_map = acb->device_map; 3098d74001adSXin LI size_t iop_firm_model=offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3099d74001adSXin LI size_t iop_firm_version=offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3100d74001adSXin LI size_t iop_device_map = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 3101d74001adSXin LI int i; 3102d74001adSXin LI 3103d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 3104d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 3105d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 3106d74001adSXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 3107d74001adSXin LI } 3108d74001adSXin LI i=0; 3109d74001adSXin LI while(i<8) { 3110d74001adSXin LI *acb_firm_model=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 3111d74001adSXin LI /* 8 bytes firm_model, 15, 60-67*/ 3112d74001adSXin LI acb_firm_model++; 3113d74001adSXin LI i++; 3114d74001adSXin LI } 3115d74001adSXin LI i=0; 3116d74001adSXin LI while(i<16) { 3117d74001adSXin LI *acb_firm_version=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 3118d74001adSXin LI /* 16 bytes firm_version, 17, 68-83*/ 3119d74001adSXin LI acb_firm_version++; 3120d74001adSXin LI i++; 3121d74001adSXin LI } 3122d74001adSXin LI i=0; 3123d74001adSXin LI while(i<16) { 3124d74001adSXin LI *acb_device_map=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 3125d74001adSXin LI acb_device_map++; 3126d74001adSXin LI i++; 3127d74001adSXin LI } 3128d74001adSXin LI printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION); 3129d74001adSXin LI printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version); 3130d74001adSXin LI acb->firm_request_len =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3131d74001adSXin LI acb->firm_numbers_queue =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3132d74001adSXin LI acb->firm_sdram_size =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3133d74001adSXin LI acb->firm_ide_channels =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3134d74001adSXin LI acb->firm_cfg_version =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 313544f05562SScott Long return; 313644f05562SScott Long } 313744f05562SScott Long /* 313844f05562SScott Long ********************************************************************** 313944f05562SScott Long ********************************************************************** 314044f05562SScott Long */ 314144f05562SScott Long static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) 314244f05562SScott Long { 314344f05562SScott Long switch (acb->adapter_type) { 314444f05562SScott Long case ACB_ADAPTER_TYPE_A: { 314544f05562SScott Long arcmsr_get_hba_config(acb); 314644f05562SScott Long } 314744f05562SScott Long break; 314844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 314944f05562SScott Long arcmsr_get_hbb_config(acb); 315044f05562SScott Long } 315144f05562SScott Long break; 3152d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3153d74001adSXin LI arcmsr_get_hbc_config(acb); 3154d74001adSXin LI } 3155d74001adSXin LI break; 315644f05562SScott Long } 315744f05562SScott Long return; 315844f05562SScott Long } 315944f05562SScott Long /* 316044f05562SScott Long ********************************************************************** 316144f05562SScott Long ********************************************************************** 316244f05562SScott Long */ 316344f05562SScott Long static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb) 316444f05562SScott Long { 316544f05562SScott Long int timeout=0; 316644f05562SScott Long 316744f05562SScott Long switch (acb->adapter_type) { 316844f05562SScott Long case ACB_ADAPTER_TYPE_A: { 3169d74001adSXin LI while ((CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) 317044f05562SScott Long { 317144f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 317244f05562SScott Long { 3173d74001adSXin LI printf( "arcmsr%d:timed out waiting for firmware \n", acb->pci_unit); 317444f05562SScott Long return; 317544f05562SScott Long } 317644f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 317744f05562SScott Long } 317844f05562SScott Long } 317944f05562SScott Long break; 318044f05562SScott Long case ACB_ADAPTER_TYPE_B: { 3181d74001adSXin LI while ((CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & ARCMSR_MESSAGE_FIRMWARE_OK) == 0) 318244f05562SScott Long { 318344f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 318444f05562SScott Long { 3185d74001adSXin LI printf( "arcmsr%d: timed out waiting for firmware \n", acb->pci_unit); 318644f05562SScott Long return; 318744f05562SScott Long } 318844f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 318944f05562SScott Long } 3190d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 3191d74001adSXin LI } 3192d74001adSXin LI break; 3193d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3194d74001adSXin LI while ((CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0) 3195d74001adSXin LI { 3196d74001adSXin LI if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 3197d74001adSXin LI { 3198d74001adSXin LI printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit); 3199d74001adSXin LI return; 3200d74001adSXin LI } 3201d74001adSXin LI UDELAY(15000); /* wait 15 milli-seconds */ 3202d74001adSXin LI } 320344f05562SScott Long } 320444f05562SScott Long break; 320544f05562SScott Long } 320644f05562SScott Long return; 320744f05562SScott Long } 320844f05562SScott Long /* 320944f05562SScott Long ********************************************************************** 321044f05562SScott Long ********************************************************************** 321144f05562SScott Long */ 321244f05562SScott Long static void arcmsr_clear_doorbell_queue_buffer( struct AdapterControlBlock *acb) 321344f05562SScott Long { 3214d74001adSXin LI u_int32_t outbound_doorbell; 3215d74001adSXin LI 321644f05562SScott Long switch (acb->adapter_type) { 321744f05562SScott Long case ACB_ADAPTER_TYPE_A: { 321844f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 3219d74001adSXin LI outbound_doorbell = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell); 3220d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, outbound_doorbell); /*clear doorbell interrupt */ 3221d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 3222d74001adSXin LI 322344f05562SScott Long } 322444f05562SScott Long break; 322544f05562SScott Long case ACB_ADAPTER_TYPE_B: { 3226d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt and message state*/ 3227d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 322844f05562SScott Long /* let IOP know data has been read */ 322944f05562SScott Long } 323044f05562SScott Long break; 3231d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3232d74001adSXin LI /* empty doorbell Qbuffer if door bell ringed */ 3233d74001adSXin LI outbound_doorbell = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); 3234d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell); /*clear doorbell interrupt */ 3235d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK); 3236d74001adSXin LI 3237d74001adSXin LI } 3238d74001adSXin LI break; 323944f05562SScott Long } 324044f05562SScott Long return; 324144f05562SScott Long } 324244f05562SScott Long /* 324344f05562SScott Long ************************************************************************ 324444f05562SScott Long ************************************************************************ 324544f05562SScott Long */ 324644f05562SScott Long static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb) 324744f05562SScott Long { 324844f05562SScott Long unsigned long srb_phyaddr; 324944f05562SScott Long u_int32_t srb_phyaddr_hi32; 325044f05562SScott Long 325144f05562SScott Long /* 325244f05562SScott Long ******************************************************************** 325344f05562SScott Long ** here we need to tell iop 331 our freesrb.HighPart 325444f05562SScott Long ** if freesrb.HighPart is not zero 325544f05562SScott Long ******************************************************************** 325644f05562SScott Long */ 3257d74001adSXin LI srb_phyaddr= (unsigned long) acb->srb_phyaddr.phyaddr; 3258d74001adSXin LI // srb_phyaddr_hi32=(u_int32_t) ((srb_phyaddr>>16)>>16); 3259d74001adSXin LI srb_phyaddr_hi32=acb->srb_phyaddr.B.phyadd_high; 326044f05562SScott Long switch (acb->adapter_type) { 326144f05562SScott Long case ACB_ADAPTER_TYPE_A: { 326244f05562SScott Long if(srb_phyaddr_hi32!=0) { 3263d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 3264d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 3265d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 326644f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 3267d74001adSXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 326844f05562SScott Long return FALSE; 326944f05562SScott Long } 327044f05562SScott Long } 327144f05562SScott Long } 327244f05562SScott Long break; 327344f05562SScott Long /* 327444f05562SScott Long *********************************************************************** 327544f05562SScott Long ** if adapter type B, set window of "post command Q" 327644f05562SScott Long *********************************************************************** 327744f05562SScott Long */ 327844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 327944f05562SScott Long u_int32_t post_queue_phyaddr; 328044f05562SScott Long struct HBB_MessageUnit *phbbmu; 328144f05562SScott Long 328244f05562SScott Long phbbmu=(struct HBB_MessageUnit *)acb->pmu; 328344f05562SScott Long phbbmu->postq_index=0; 328444f05562SScott Long phbbmu->doneq_index=0; 3285d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_SET_POST_WINDOW); 328644f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 3287d74001adSXin LI printf( "arcmsr%d: 'set window of post command Q' timeout\n", acb->pci_unit); 328844f05562SScott Long return FALSE; 328944f05562SScott Long } 3290*22f2616bSXin LI post_queue_phyaddr = srb_phyaddr + ARCMSR_SRBS_POOL_SIZE 329144f05562SScott Long + offsetof(struct HBB_MessageUnit, post_qbuffer); 3292d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */ 3293d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1], srb_phyaddr_hi32); /* normal should be zero */ 3294d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ size (256+8)*4 */ 3295d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3], post_queue_phyaddr+1056); /* doneQ size (256+8)*4 */ 3296d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4], 1056); /* srb maxQ size must be --> [(256+8)*4] */ 3297d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_SET_CONFIG); 329844f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 329944f05562SScott Long printf( "arcmsr%d: 'set command Q window' timeout \n", acb->pci_unit); 330044f05562SScott Long return FALSE; 330144f05562SScott Long } 3302d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_START_DRIVER_MODE); 330344f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 330444f05562SScott Long printf( "arcmsr%d: 'start diver mode' timeout \n", acb->pci_unit); 330544f05562SScott Long return FALSE; 330644f05562SScott Long } 330744f05562SScott Long } 330844f05562SScott Long break; 3309d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3310d74001adSXin LI if(srb_phyaddr_hi32!=0) { 3311d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 3312d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 3313d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 3314d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 3315d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 3316d74001adSXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 3317d74001adSXin LI return FALSE; 3318d74001adSXin LI } 3319d74001adSXin LI } 3320d74001adSXin LI } 3321d74001adSXin LI break; 332244f05562SScott Long } 332344f05562SScott Long return TRUE; 332444f05562SScott Long } 332544f05562SScott Long /* 332644f05562SScott Long ************************************************************************ 332744f05562SScott Long ************************************************************************ 332844f05562SScott Long */ 332944f05562SScott Long static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb) 333044f05562SScott Long { 333144f05562SScott Long switch (acb->adapter_type) 333244f05562SScott Long { 333344f05562SScott Long case ACB_ADAPTER_TYPE_A: 3334d74001adSXin LI case ACB_ADAPTER_TYPE_C: 3335d74001adSXin LI break; 333644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 3337d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell,ARCMSR_MESSAGE_ACTIVE_EOI_MODE); 333844f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 3339d74001adSXin LI printf( "arcmsr%d: 'iop enable eoi mode' timeout \n", acb->pci_unit); 3340d74001adSXin LI 334144f05562SScott Long return; 334244f05562SScott Long } 334344f05562SScott Long } 334444f05562SScott Long break; 334544f05562SScott Long } 334644f05562SScott Long return; 334744f05562SScott Long } 334844f05562SScott Long /* 334944f05562SScott Long ********************************************************************** 3350ad6d6297SScott Long ********************************************************************** 3351ad6d6297SScott Long */ 3352ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb) 3353ad6d6297SScott Long { 335444f05562SScott Long u_int32_t intmask_org; 3355ad6d6297SScott Long 335644f05562SScott Long /* disable all outbound interrupt */ 335744f05562SScott Long intmask_org=arcmsr_disable_allintr(acb); 335844f05562SScott Long arcmsr_wait_firmware_ready(acb); 335944f05562SScott Long arcmsr_iop_confirm(acb); 3360ad6d6297SScott Long arcmsr_get_firmware_spec(acb); 336144f05562SScott Long /*start background rebuild*/ 3362ad6d6297SScott Long arcmsr_start_adapter_bgrb(acb); 336344f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 336444f05562SScott Long arcmsr_clear_doorbell_queue_buffer(acb); 336544f05562SScott Long arcmsr_enable_eoi_mode(acb); 336644f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 336744f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 3368ad6d6297SScott Long acb->acb_flags |=ACB_F_IOP_INITED; 3369ad6d6297SScott Long return; 3370ad6d6297SScott Long } 3371ad6d6297SScott Long /* 3372ad6d6297SScott Long ********************************************************************** 3373f1c579b1SScott Long ********************************************************************** 3374f1c579b1SScott Long */ 3375231c8b71SXin LI static void arcmsr_map_free_srb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 3376f1c579b1SScott Long { 3377ad6d6297SScott Long struct AdapterControlBlock *acb=arg; 3378ad6d6297SScott Long struct CommandControlBlock *srb_tmp; 3379ad6d6297SScott Long u_int8_t * dma_memptr; 338044f05562SScott Long u_int32_t i; 3381ad6d6297SScott Long unsigned long srb_phyaddr=(unsigned long)segs->ds_addr; 3382f1c579b1SScott Long 3383ad6d6297SScott Long dma_memptr=acb->uncacheptr; 3384d74001adSXin LI acb->srb_phyaddr.phyaddr=srb_phyaddr; 3385ad6d6297SScott Long srb_tmp=(struct CommandControlBlock *)dma_memptr; 3386ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 338744f05562SScott Long if(bus_dmamap_create(acb->dm_segs_dmat, 338844f05562SScott Long /*flags*/0, &srb_tmp->dm_segs_dmamap)!=0) { 3389ad6d6297SScott Long acb->acb_flags |= ACB_F_MAPFREESRB_FAILD; 339044f05562SScott Long printf("arcmsr%d:" 339144f05562SScott Long " srb dmamap bus_dmamap_create error\n", acb->pci_unit); 3392ad6d6297SScott Long return; 3393ad6d6297SScott Long } 3394d74001adSXin LI srb_tmp->cdb_shifted_phyaddr=(acb->adapter_type==ACB_ADAPTER_TYPE_C)?srb_phyaddr:(srb_phyaddr >> 5); 3395ad6d6297SScott Long srb_tmp->acb=acb; 3396ad6d6297SScott Long acb->srbworkingQ[i]=acb->psrb_pool[i]=srb_tmp; 3397*22f2616bSXin LI srb_phyaddr=srb_phyaddr+SRB_SIZE; 3398*22f2616bSXin LI srb_tmp = (struct CommandControlBlock *)((unsigned long)srb_tmp+SRB_SIZE); 3399ad6d6297SScott Long } 3400ad6d6297SScott Long acb->vir2phy_offset=(unsigned long)srb_tmp-(unsigned long)srb_phyaddr; 3401f1c579b1SScott Long return; 3402f1c579b1SScott Long } 3403f1c579b1SScott Long /* 3404f1c579b1SScott Long ************************************************************************ 3405f1c579b1SScott Long ** 3406f1c579b1SScott Long ** 3407f1c579b1SScott Long ************************************************************************ 3408f1c579b1SScott Long */ 3409ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb) 3410f1c579b1SScott Long { 3411f1c579b1SScott Long /* remove the control device */ 3412ad6d6297SScott Long if(acb->ioctl_dev != NULL) { 3413ad6d6297SScott Long destroy_dev(acb->ioctl_dev); 3414f1c579b1SScott Long } 3415ad6d6297SScott Long bus_dmamap_unload(acb->srb_dmat, acb->srb_dmamap); 3416ad6d6297SScott Long bus_dmamap_destroy(acb->srb_dmat, acb->srb_dmamap); 3417ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 3418ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 3419ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 3420f1c579b1SScott Long return; 3421f1c579b1SScott Long } 3422f1c579b1SScott Long /* 3423f1c579b1SScott Long ************************************************************************ 3424f1c579b1SScott Long ************************************************************************ 3425f1c579b1SScott Long */ 3426ad6d6297SScott Long static u_int32_t arcmsr_initialize(device_t dev) 3427f1c579b1SScott Long { 3428ad6d6297SScott Long struct AdapterControlBlock *acb=device_get_softc(dev); 3429ad6d6297SScott Long u_int16_t pci_command; 343044f05562SScott Long int i, j,max_coherent_size; 3431f1c579b1SScott Long 343244f05562SScott Long switch (pci_get_devid(dev)) { 3433d74001adSXin LI case PCIDevVenIDARC1880: { 3434d74001adSXin LI acb->adapter_type=ACB_ADAPTER_TYPE_C; 3435d74001adSXin LI max_coherent_size=ARCMSR_SRBS_POOL_SIZE; 3436d74001adSXin LI } 3437d74001adSXin LI break; 3438231c8b71SXin LI case PCIDevVenIDARC1200: 343944f05562SScott Long case PCIDevVenIDARC1201: { 344044f05562SScott Long acb->adapter_type=ACB_ADAPTER_TYPE_B; 3441d74001adSXin LI max_coherent_size=ARCMSR_SRBS_POOL_SIZE+(sizeof(struct HBB_MessageUnit)); 344244f05562SScott Long } 344344f05562SScott Long break; 344444f05562SScott Long case PCIDevVenIDARC1110: 344544f05562SScott Long case PCIDevVenIDARC1120: 344644f05562SScott Long case PCIDevVenIDARC1130: 344744f05562SScott Long case PCIDevVenIDARC1160: 344844f05562SScott Long case PCIDevVenIDARC1170: 344944f05562SScott Long case PCIDevVenIDARC1210: 345044f05562SScott Long case PCIDevVenIDARC1220: 345144f05562SScott Long case PCIDevVenIDARC1230: 3452231c8b71SXin LI case PCIDevVenIDARC1231: 345344f05562SScott Long case PCIDevVenIDARC1260: 3454231c8b71SXin LI case PCIDevVenIDARC1261: 345544f05562SScott Long case PCIDevVenIDARC1270: 345644f05562SScott Long case PCIDevVenIDARC1280: 3457d74001adSXin LI case PCIDevVenIDARC1212: 3458d74001adSXin LI case PCIDevVenIDARC1222: 345944f05562SScott Long case PCIDevVenIDARC1380: 346044f05562SScott Long case PCIDevVenIDARC1381: 346144f05562SScott Long case PCIDevVenIDARC1680: 346244f05562SScott Long case PCIDevVenIDARC1681: { 346344f05562SScott Long acb->adapter_type=ACB_ADAPTER_TYPE_A; 346444f05562SScott Long max_coherent_size=ARCMSR_SRBS_POOL_SIZE; 346544f05562SScott Long } 346644f05562SScott Long break; 346744f05562SScott Long default: { 346844f05562SScott Long printf("arcmsr%d:" 346944f05562SScott Long " unknown RAID adapter type \n", device_get_unit(dev)); 347044f05562SScott Long return ENOMEM; 347144f05562SScott Long } 347244f05562SScott Long } 3473f1c579b1SScott Long if(bus_dma_tag_create( /*parent*/ NULL, 3474f1c579b1SScott Long /*alignemnt*/ 1, 3475f1c579b1SScott Long /*boundary*/ 0, 3476701d9f1fSScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 3477f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 3478f1c579b1SScott Long /*filter*/ NULL, 3479f1c579b1SScott Long /*filterarg*/ NULL, 3480f1c579b1SScott Long /*maxsize*/ BUS_SPACE_MAXSIZE_32BIT, 3481f1c579b1SScott Long /*nsegments*/ BUS_SPACE_UNRESTRICTED, 3482f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 3483f1c579b1SScott Long /*flags*/ 0, 3484*22f2616bSXin LI #if __FreeBSD_version >= 501102 3485f1c579b1SScott Long /*lockfunc*/ NULL, 3486f1c579b1SScott Long /*lockarg*/ NULL, 3487f1c579b1SScott Long #endif 3488231c8b71SXin LI &acb->parent_dmat) != 0) 3489f1c579b1SScott Long { 349044f05562SScott Long printf("arcmsr%d: parent_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 3491f1c579b1SScott Long return ENOMEM; 3492f1c579b1SScott Long } 3493231c8b71SXin LI 3494f1c579b1SScott Long /* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */ 3495ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 3496f1c579b1SScott Long /*alignment*/ 1, 3497f1c579b1SScott Long /*boundary*/ 0, 3498*22f2616bSXin LI #ifdef PAE 3499*22f2616bSXin LI /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 3500*22f2616bSXin LI #else 3501f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 3502*22f2616bSXin LI #endif 3503f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 3504f1c579b1SScott Long /*filter*/ NULL, 3505f1c579b1SScott Long /*filterarg*/ NULL, 3506231c8b71SXin LI /*maxsize*/ ARCMSR_MAX_SG_ENTRIES * PAGE_SIZE * ARCMSR_MAX_FREESRB_NUM, 3507f1c579b1SScott Long /*nsegments*/ ARCMSR_MAX_SG_ENTRIES, 3508f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 3509ad6d6297SScott Long /*flags*/ 0, 3510*22f2616bSXin LI #if __FreeBSD_version >= 501102 3511f1c579b1SScott Long /*lockfunc*/ busdma_lock_mutex, 35125878cbecSScott Long /*lockarg*/ &acb->qbuffer_lock, 3513f1c579b1SScott Long #endif 3514231c8b71SXin LI &acb->dm_segs_dmat) != 0) 3515f1c579b1SScott Long { 3516ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 351744f05562SScott Long printf("arcmsr%d: dm_segs_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 3518f1c579b1SScott Long return ENOMEM; 3519f1c579b1SScott Long } 3520231c8b71SXin LI 3521ad6d6297SScott Long /* DMA tag for our srb structures.... Allocate the freesrb memory */ 3522ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 352344f05562SScott Long /*alignment*/ 0x20, 3524f1c579b1SScott Long /*boundary*/ 0, 3525f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 3526f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 3527f1c579b1SScott Long /*filter*/ NULL, 3528f1c579b1SScott Long /*filterarg*/ NULL, 352944f05562SScott Long /*maxsize*/ max_coherent_size, 3530f1c579b1SScott Long /*nsegments*/ 1, 3531f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 3532701d9f1fSScott Long /*flags*/ 0, 3533*22f2616bSXin LI #if __FreeBSD_version >= 501102 3534f1c579b1SScott Long /*lockfunc*/ NULL, 3535f1c579b1SScott Long /*lockarg*/ NULL, 3536f1c579b1SScott Long #endif 3537231c8b71SXin LI &acb->srb_dmat) != 0) 3538f1c579b1SScott Long { 3539ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 3540ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 354144f05562SScott Long printf("arcmsr%d: srb_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 3542f1c579b1SScott Long return ENXIO; 3543f1c579b1SScott Long } 3544f1c579b1SScott Long /* Allocation for our srbs */ 3545d74001adSXin LI if(bus_dmamem_alloc(acb->srb_dmat, (void **)&acb->uncacheptr, BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &acb->srb_dmamap) != 0) { 3546ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 3547ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 3548ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 354944f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamem_alloc failure!\n", device_get_unit(dev)); 3550f1c579b1SScott Long return ENXIO; 3551f1c579b1SScott Long } 3552f1c579b1SScott Long /* And permanently map them */ 3553231c8b71SXin LI if(bus_dmamap_load(acb->srb_dmat, acb->srb_dmamap, acb->uncacheptr, max_coherent_size, arcmsr_map_free_srb, acb, /*flags*/0)) { 3554ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 3555ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 3556ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 355744f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamap_load failure!\n", device_get_unit(dev)); 3558f1c579b1SScott Long return ENXIO; 3559f1c579b1SScott Long } 3560f1c579b1SScott Long pci_command=pci_read_config(dev, PCIR_COMMAND, 2); 3561f1c579b1SScott Long pci_command |= PCIM_CMD_BUSMASTEREN; 3562f1c579b1SScott Long pci_command |= PCIM_CMD_PERRESPEN; 3563f1c579b1SScott Long pci_command |= PCIM_CMD_MWRICEN; 3564f1c579b1SScott Long /* Enable Busmaster/Mem */ 3565f1c579b1SScott Long pci_command |= PCIM_CMD_MEMEN; 3566f1c579b1SScott Long pci_write_config(dev, PCIR_COMMAND, pci_command, 2); 356744f05562SScott Long switch(acb->adapter_type) { 356844f05562SScott Long case ACB_ADAPTER_TYPE_A: { 356944f05562SScott Long u_int32_t rid0=PCIR_BAR(0); 357044f05562SScott Long vm_offset_t mem_base0; 357144f05562SScott Long 3572d74001adSXin LI acb->sys_res_arcmsr[0]=bus_alloc_resource(dev,SYS_RES_MEMORY, &rid0, 0ul, ~0ul, 0x1000, RF_ACTIVE); 357344f05562SScott Long if(acb->sys_res_arcmsr[0] == NULL) { 3574ad6d6297SScott Long arcmsr_free_resource(acb); 3575d74001adSXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 3576f1c579b1SScott Long return ENOMEM; 3577f1c579b1SScott Long } 357844f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 3579ad6d6297SScott Long arcmsr_free_resource(acb); 3580d74001adSXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 3581f1c579b1SScott Long return ENXIO; 3582f1c579b1SScott Long } 358344f05562SScott Long mem_base0=(vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 358444f05562SScott Long if(mem_base0==0) { 3585ad6d6297SScott Long arcmsr_free_resource(acb); 3586d74001adSXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 3587f1c579b1SScott Long return ENXIO; 3588f1c579b1SScott Long } 358944f05562SScott Long acb->btag[0]=rman_get_bustag(acb->sys_res_arcmsr[0]); 359044f05562SScott Long acb->bhandle[0]=rman_get_bushandle(acb->sys_res_arcmsr[0]); 359144f05562SScott Long acb->pmu=(struct MessageUnit_UNION *)mem_base0; 359244f05562SScott Long } 359344f05562SScott Long break; 359444f05562SScott Long case ACB_ADAPTER_TYPE_B: { 359544f05562SScott Long struct HBB_MessageUnit *phbbmu; 359644f05562SScott Long struct CommandControlBlock *freesrb; 359744f05562SScott Long u_int32_t rid[]={ PCIR_BAR(0), PCIR_BAR(2) }; 359844f05562SScott Long vm_offset_t mem_base[]={0,0}; 359944f05562SScott Long for(i=0; i<2; i++) { 360044f05562SScott Long if(i==0) { 3601d74001adSXin LI acb->sys_res_arcmsr[i]=bus_alloc_resource(dev,SYS_RES_MEMORY, &rid[i], 3602231c8b71SXin LI 0ul, ~0ul, sizeof(struct HBB_DOORBELL), RF_ACTIVE); 360344f05562SScott Long } else { 3604d74001adSXin LI acb->sys_res_arcmsr[i]=bus_alloc_resource(dev, SYS_RES_MEMORY, &rid[i], 3605231c8b71SXin LI 0ul, ~0ul, sizeof(struct HBB_RWBUFFER), RF_ACTIVE); 360644f05562SScott Long } 360744f05562SScott Long if(acb->sys_res_arcmsr[i] == NULL) { 360844f05562SScott Long arcmsr_free_resource(acb); 3609d74001adSXin LI printf("arcmsr%d: bus_alloc_resource %d failure!\n", device_get_unit(dev), i); 361044f05562SScott Long return ENOMEM; 361144f05562SScott Long } 361244f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[i]) <= 0) { 361344f05562SScott Long arcmsr_free_resource(acb); 3614d74001adSXin LI printf("arcmsr%d: rman_get_start %d failure!\n", device_get_unit(dev), i); 361544f05562SScott Long return ENXIO; 361644f05562SScott Long } 361744f05562SScott Long mem_base[i]=(vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[i]); 361844f05562SScott Long if(mem_base[i]==0) { 361944f05562SScott Long arcmsr_free_resource(acb); 3620d74001adSXin LI printf("arcmsr%d: rman_get_virtual %d failure!\n", device_get_unit(dev), i); 362144f05562SScott Long return ENXIO; 362244f05562SScott Long } 362344f05562SScott Long acb->btag[i]=rman_get_bustag(acb->sys_res_arcmsr[i]); 362444f05562SScott Long acb->bhandle[i]=rman_get_bushandle(acb->sys_res_arcmsr[i]); 362544f05562SScott Long } 362644f05562SScott Long freesrb=(struct CommandControlBlock *)acb->uncacheptr; 3627*22f2616bSXin LI // acb->pmu=(struct MessageUnit_UNION *)&freesrb[ARCMSR_MAX_FREESRB_NUM]; 3628*22f2616bSXin LI acb->pmu=(struct MessageUnit_UNION *)((unsigned long)freesrb+ARCMSR_SRBS_POOL_SIZE); 362944f05562SScott Long phbbmu=(struct HBB_MessageUnit *)acb->pmu; 363044f05562SScott Long phbbmu->hbb_doorbell=(struct HBB_DOORBELL *)mem_base[0]; 363144f05562SScott Long phbbmu->hbb_rwbuffer=(struct HBB_RWBUFFER *)mem_base[1]; 363244f05562SScott Long } 363344f05562SScott Long break; 3634d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3635d74001adSXin LI u_int32_t rid0=PCIR_BAR(1); 3636d74001adSXin LI vm_offset_t mem_base0; 3637d74001adSXin LI 3638d74001adSXin LI acb->sys_res_arcmsr[0]=bus_alloc_resource(dev,SYS_RES_MEMORY, &rid0, 0ul, ~0ul, sizeof(struct HBC_MessageUnit), RF_ACTIVE); 3639d74001adSXin LI if(acb->sys_res_arcmsr[0] == NULL) { 3640d74001adSXin LI arcmsr_free_resource(acb); 3641d74001adSXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 3642d74001adSXin LI return ENOMEM; 3643d74001adSXin LI } 3644d74001adSXin LI if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 3645d74001adSXin LI arcmsr_free_resource(acb); 3646d74001adSXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 3647d74001adSXin LI return ENXIO; 3648d74001adSXin LI } 3649d74001adSXin LI mem_base0=(vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 3650d74001adSXin LI if(mem_base0==0) { 3651d74001adSXin LI arcmsr_free_resource(acb); 3652d74001adSXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 3653d74001adSXin LI return ENXIO; 3654d74001adSXin LI } 3655d74001adSXin LI acb->btag[0]=rman_get_bustag(acb->sys_res_arcmsr[0]); 3656d74001adSXin LI acb->bhandle[0]=rman_get_bushandle(acb->sys_res_arcmsr[0]); 3657d74001adSXin LI acb->pmu=(struct MessageUnit_UNION *)mem_base0; 3658d74001adSXin LI } 3659d74001adSXin LI break; 366044f05562SScott Long } 3661ad6d6297SScott Long if(acb->acb_flags & ACB_F_MAPFREESRB_FAILD) { 3662ad6d6297SScott Long arcmsr_free_resource(acb); 366344f05562SScott Long printf("arcmsr%d: map free srb failure!\n", device_get_unit(dev)); 3664f1c579b1SScott Long return ENXIO; 3665f1c579b1SScott Long } 3666d74001adSXin LI acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_RQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ); 3667ad6d6297SScott Long acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; 3668ad6d6297SScott Long /* 3669ad6d6297SScott Long ******************************************************************** 3670ad6d6297SScott Long ** init raid volume state 3671ad6d6297SScott Long ******************************************************************** 3672ad6d6297SScott Long */ 3673ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_TARGETID;i++) { 3674ad6d6297SScott Long for(j=0;j<ARCMSR_MAX_TARGETLUN;j++) { 367544f05562SScott Long acb->devstate[i][j]=ARECA_RAID_GONE; 3676ad6d6297SScott Long } 3677ad6d6297SScott Long } 3678ad6d6297SScott Long arcmsr_iop_init(acb); 3679f1c579b1SScott Long return(0); 3680f1c579b1SScott Long } 3681f1c579b1SScott Long /* 3682f1c579b1SScott Long ************************************************************************ 3683f1c579b1SScott Long ************************************************************************ 3684f1c579b1SScott Long */ 3685f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev) 3686f1c579b1SScott Long { 3687ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 3688ad6d6297SScott Long u_int32_t unit=device_get_unit(dev); 3689f1c579b1SScott Long struct ccb_setasync csa; 3690f1c579b1SScott Long struct cam_devq *devq; /* Device Queue to use for this SIM */ 3691f1c579b1SScott Long struct resource *irqres; 3692f1c579b1SScott Long int rid; 3693f1c579b1SScott Long 3694ad6d6297SScott Long if(acb == NULL) { 3695ad6d6297SScott Long printf("arcmsr%d: cannot allocate softc\n", unit); 3696ad6d6297SScott Long return (ENOMEM); 3697ad6d6297SScott Long } 36985878cbecSScott Long ARCMSR_LOCK_INIT(&acb->qbuffer_lock, "arcmsr Q buffer lock"); 3699ad6d6297SScott Long if(arcmsr_initialize(dev)) { 3700ad6d6297SScott Long printf("arcmsr%d: initialize failure!\n", unit); 37015878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3702f1c579b1SScott Long return ENXIO; 3703f1c579b1SScott Long } 3704f1c579b1SScott Long /* After setting up the adapter, map our interrupt */ 3705f1c579b1SScott Long rid=0; 3706ad6d6297SScott Long irqres=bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE); 3707ad6d6297SScott Long if(irqres == NULL || 370844f05562SScott Long #if __FreeBSD_version >= 700025 3709d74001adSXin LI bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, NULL, arcmsr_intr_handler, acb, &acb->ih)) { 371044f05562SScott Long #else 3711d74001adSXin LI bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, arcmsr_intr_handler, acb, &acb->ih)) { 371244f05562SScott Long #endif 3713ad6d6297SScott Long arcmsr_free_resource(acb); 37145878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3715f1c579b1SScott Long printf("arcmsr%d: unable to register interrupt handler!\n", unit); 3716f1c579b1SScott Long return ENXIO; 3717f1c579b1SScott Long } 3718ad6d6297SScott Long acb->irqres=irqres; 3719ad6d6297SScott Long acb->pci_dev=dev; 3720ad6d6297SScott Long acb->pci_unit=unit; 3721f1c579b1SScott Long /* 3722f1c579b1SScott Long * Now let the CAM generic SCSI layer find the SCSI devices on 3723f1c579b1SScott Long * the bus * start queue to reset to the idle loop. * 3724f1c579b1SScott Long * Create device queue of SIM(s) * (MAX_START_JOB - 1) : 3725f1c579b1SScott Long * max_sim_transactions 3726f1c579b1SScott Long */ 3727f1c579b1SScott Long devq=cam_simq_alloc(ARCMSR_MAX_START_JOB); 3728ad6d6297SScott Long if(devq == NULL) { 3729ad6d6297SScott Long arcmsr_free_resource(acb); 3730ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 37315878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3732ad6d6297SScott Long printf("arcmsr%d: cam_simq_alloc failure!\n", unit); 3733f1c579b1SScott Long return ENXIO; 3734f1c579b1SScott Long } 373544f05562SScott Long #if __FreeBSD_version >= 700025 3736d74001adSXin LI acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, &acb->qbuffer_lock, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq); 373744f05562SScott Long #else 3738d74001adSXin LI acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq); 373944f05562SScott Long #endif 3740ad6d6297SScott Long if(acb->psim == NULL) { 3741ad6d6297SScott Long arcmsr_free_resource(acb); 3742ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 3743f1c579b1SScott Long cam_simq_free(devq); 37445878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3745ad6d6297SScott Long printf("arcmsr%d: cam_sim_alloc failure!\n", unit); 3746f1c579b1SScott Long return ENXIO; 3747f1c579b1SScott Long } 37485878cbecSScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 3749f40b4cabSScott Long #if __FreeBSD_version >= 700044 3750b50569b7SScott Long if(xpt_bus_register(acb->psim, dev, 0) != CAM_SUCCESS) { 375144f05562SScott Long #else 375244f05562SScott Long if(xpt_bus_register(acb->psim, 0) != CAM_SUCCESS) { 375344f05562SScott Long #endif 3754ad6d6297SScott Long arcmsr_free_resource(acb); 3755ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 3756ad6d6297SScott Long cam_sim_free(acb->psim, /*free_devq*/TRUE); 37575878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3758ad6d6297SScott Long printf("arcmsr%d: xpt_bus_register failure!\n", unit); 3759f1c579b1SScott Long return ENXIO; 3760f1c579b1SScott Long } 3761d74001adSXin LI if(xpt_create_path(&acb->ppath, /* periph */ NULL, cam_sim_path(acb->psim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 3762ad6d6297SScott Long arcmsr_free_resource(acb); 3763ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 3764ad6d6297SScott Long xpt_bus_deregister(cam_sim_path(acb->psim)); 3765ad6d6297SScott Long cam_sim_free(acb->psim, /* free_simq */ TRUE); 37665878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3767ad6d6297SScott Long printf("arcmsr%d: xpt_create_path failure!\n", unit); 3768f1c579b1SScott Long return ENXIO; 3769f1c579b1SScott Long } 3770f1c579b1SScott Long /* 3771f1c579b1SScott Long **************************************************** 3772f1c579b1SScott Long */ 3773ad6d6297SScott Long xpt_setup_ccb(&csa.ccb_h, acb->ppath, /*priority*/5); 3774f1c579b1SScott Long csa.ccb_h.func_code=XPT_SASYNC_CB; 3775f1c579b1SScott Long csa.event_enable=AC_FOUND_DEVICE|AC_LOST_DEVICE; 3776f1c579b1SScott Long csa.callback=arcmsr_async; 3777ad6d6297SScott Long csa.callback_arg=acb->psim; 3778f1c579b1SScott Long xpt_action((union ccb *)&csa); 37795878cbecSScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 3780f1c579b1SScott Long /* Create the control device. */ 3781d74001adSXin LI acb->ioctl_dev=make_dev(&arcmsr_cdevsw, unit, UID_ROOT, GID_WHEEL /* GID_OPERATOR */, S_IRUSR | S_IWUSR, "arcmsr%d", unit); 3782d74001adSXin LI 3783f1c579b1SScott Long #if __FreeBSD_version < 503000 3784ad6d6297SScott Long acb->ioctl_dev->si_drv1=acb; 3785f1c579b1SScott Long #endif 3786f1c579b1SScott Long #if __FreeBSD_version > 500005 3787ad6d6297SScott Long (void)make_dev_alias(acb->ioctl_dev, "arc%d", unit); 3788f1c579b1SScott Long #endif 3789*22f2616bSXin LI arcmsr_callout_init(&acb->devmap_callout); 3790d74001adSXin LI callout_reset(&acb->devmap_callout, 60 * hz, arcmsr_polling_devmap, acb); 3791f1c579b1SScott Long return 0; 3792f1c579b1SScott Long } 3793*22f2616bSXin LI 3794f1c579b1SScott Long /* 3795f1c579b1SScott Long ************************************************************************ 3796f1c579b1SScott Long ************************************************************************ 3797f1c579b1SScott Long */ 3798f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev) 3799f1c579b1SScott Long { 3800ad6d6297SScott Long u_int32_t id; 3801ad6d6297SScott Long static char buf[256]; 3802231c8b71SXin LI char x_type[]={"X-TYPE"}; 3803ad6d6297SScott Long char *type; 3804ad6d6297SScott Long int raid6 = 1; 3805ad6d6297SScott Long 3806ad6d6297SScott Long if (pci_get_vendor(dev) != PCI_VENDOR_ID_ARECA) { 3807ad6d6297SScott Long return (ENXIO); 3808ad6d6297SScott Long } 3809ad6d6297SScott Long switch(id=pci_get_devid(dev)) { 3810f1c579b1SScott Long case PCIDevVenIDARC1110: 3811231c8b71SXin LI case PCIDevVenIDARC1200: 381244f05562SScott Long case PCIDevVenIDARC1201: 3813231c8b71SXin LI case PCIDevVenIDARC1210: 3814ad6d6297SScott Long raid6 = 0; 3815ad6d6297SScott Long /*FALLTHRU*/ 3816ad6d6297SScott Long case PCIDevVenIDARC1120: 3817ad6d6297SScott Long case PCIDevVenIDARC1130: 3818ad6d6297SScott Long case PCIDevVenIDARC1160: 3819ad6d6297SScott Long case PCIDevVenIDARC1170: 3820f1c579b1SScott Long case PCIDevVenIDARC1220: 3821f1c579b1SScott Long case PCIDevVenIDARC1230: 3822231c8b71SXin LI case PCIDevVenIDARC1231: 3823f1c579b1SScott Long case PCIDevVenIDARC1260: 3824231c8b71SXin LI case PCIDevVenIDARC1261: 3825ad6d6297SScott Long case PCIDevVenIDARC1270: 3826ad6d6297SScott Long case PCIDevVenIDARC1280: 3827ad6d6297SScott Long type = "SATA"; 3828ad6d6297SScott Long break; 3829d74001adSXin LI case PCIDevVenIDARC1212: 3830d74001adSXin LI case PCIDevVenIDARC1222: 3831ad6d6297SScott Long case PCIDevVenIDARC1380: 3832ad6d6297SScott Long case PCIDevVenIDARC1381: 3833ad6d6297SScott Long case PCIDevVenIDARC1680: 3834ad6d6297SScott Long case PCIDevVenIDARC1681: 3835d74001adSXin LI type = "SAS 3G"; 3836d74001adSXin LI break; 3837d74001adSXin LI case PCIDevVenIDARC1880: 3838d74001adSXin LI type = "SAS 6G"; 3839ad6d6297SScott Long break; 3840ad6d6297SScott Long default: 3841231c8b71SXin LI type = x_type; 3842ad6d6297SScott Long break; 3843f1c579b1SScott Long } 3844231c8b71SXin LI if(type == x_type) 3845231c8b71SXin LI return(ENXIO); 3846ad6d6297SScott Long sprintf(buf, "Areca %s Host Adapter RAID Controller %s\n", type, raid6 ? "(RAID6 capable)" : ""); 3847ad6d6297SScott Long device_set_desc_copy(dev, buf); 3848ad6d6297SScott Long return 0; 3849f1c579b1SScott Long } 3850f1c579b1SScott Long /* 3851f1c579b1SScott Long ************************************************************************ 3852f1c579b1SScott Long ************************************************************************ 3853f1c579b1SScott Long */ 3854f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev) 3855f1c579b1SScott Long { 385644f05562SScott Long u_int32_t i; 3857ad6d6297SScott Long u_int32_t intmask_org; 3858ad6d6297SScott Long struct CommandControlBlock *srb; 3859ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 3860f1c579b1SScott Long 3861f1c579b1SScott Long /* stop adapter background rebuild */ 38625878cbecSScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 386344f05562SScott Long /* disable all outbound interrupt */ 386444f05562SScott Long intmask_org=arcmsr_disable_allintr(acb); 3865ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 3866ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 3867f1c579b1SScott Long /* abort all outstanding command */ 3868ad6d6297SScott Long acb->acb_flags |= ACB_F_SCSISTOPADAPTER; 3869ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOP_INITED; 3870ad6d6297SScott Long if(acb->srboutstandingcount!=0) { 387144f05562SScott Long /*clear and abort all outbound posted Q*/ 387244f05562SScott Long arcmsr_done4abort_postqueue(acb); 387344f05562SScott Long /* talk to iop 331 outstanding command aborted*/ 3874ad6d6297SScott Long arcmsr_abort_allcmd(acb); 3875ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 3876ad6d6297SScott Long srb=acb->psrb_pool[i]; 3877*22f2616bSXin LI if(srb->srb_state==ARCMSR_SRB_START) { 3878*22f2616bSXin LI srb->srb_state=ARCMSR_SRB_ABORTED; 3879ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 3880ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 3881f1c579b1SScott Long } 3882f1c579b1SScott Long } 3883f1c579b1SScott Long } 3884*22f2616bSXin LI acb->srboutstandingcount=0; 3885ad6d6297SScott Long acb->workingsrb_doneindex=0; 3886ad6d6297SScott Long acb->workingsrb_startindex=0; 3887*22f2616bSXin LI #ifdef ARCMSR_DEBUG1 3888*22f2616bSXin LI acb->pktRequestCount = 0; 3889*22f2616bSXin LI acb->pktReturnCount = 0; 3890*22f2616bSXin LI #endif 38915878cbecSScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 3892f2aa0e9fSWarner Losh return (0); 3893f1c579b1SScott Long } 3894f1c579b1SScott Long /* 3895f1c579b1SScott Long ************************************************************************ 3896f1c579b1SScott Long ************************************************************************ 3897f1c579b1SScott Long */ 3898f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev) 3899f1c579b1SScott Long { 3900ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 390144f05562SScott Long int i; 3902f1c579b1SScott Long 3903d74001adSXin LI callout_stop(&acb->devmap_callout); 39045878cbecSScott Long bus_teardown_intr(dev, acb->irqres, acb->ih); 3905f1c579b1SScott Long arcmsr_shutdown(dev); 3906ad6d6297SScott Long arcmsr_free_resource(acb); 390744f05562SScott Long for(i=0; (acb->sys_res_arcmsr[i]!=NULL) && (i<2); i++) { 390844f05562SScott Long bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(i), acb->sys_res_arcmsr[i]); 390944f05562SScott Long } 3910ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 39115878cbecSScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 3912ad6d6297SScott Long xpt_async(AC_LOST_DEVICE, acb->ppath, NULL); 3913ad6d6297SScott Long xpt_free_path(acb->ppath); 3914ad6d6297SScott Long xpt_bus_deregister(cam_sim_path(acb->psim)); 3915ad6d6297SScott Long cam_sim_free(acb->psim, TRUE); 39165878cbecSScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 39175878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3918f1c579b1SScott Long return (0); 3919f1c579b1SScott Long } 3920f1c579b1SScott Long 3921*22f2616bSXin LI #ifdef ARCMSR_DEBUG1 3922*22f2616bSXin LI static void arcmsr_dump_data(struct AdapterControlBlock *acb) 3923*22f2616bSXin LI { 3924*22f2616bSXin LI if((acb->pktRequestCount - acb->pktReturnCount) == 0) 3925*22f2616bSXin LI return; 3926*22f2616bSXin LI printf("Command Request Count =0x%x\n",acb->pktRequestCount); 3927*22f2616bSXin LI printf("Command Return Count =0x%x\n",acb->pktReturnCount); 3928*22f2616bSXin LI printf("Command (Req-Rtn) Count =0x%x\n",(acb->pktRequestCount - acb->pktReturnCount)); 3929*22f2616bSXin LI printf("Queued Command Count =0x%x\n",acb->srboutstandingcount); 3930*22f2616bSXin LI } 3931*22f2616bSXin LI #endif 3932f1c579b1SScott Long 3933