1f1c579b1SScott Long /* 235689395SXin LI ******************************************************************************** 335689395SXin LI ** OS : FreeBSD 4f1c579b1SScott Long ** FILE NAME : arcmsr.c 5d74001adSXin LI ** BY : Erich Chen, Ching Huang 6f1c579b1SScott Long ** Description: SCSI RAID Device Driver for 735689395SXin LI ** ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX/ARC188x) 835689395SXin LI ** SATA/SAS RAID HOST Adapter 935689395SXin LI ******************************************************************************** 1035689395SXin LI ******************************************************************************** 11f1c579b1SScott Long ** 12718cf2ccSPedro F. Giffuni ** SPDX-License-Identifier: BSD-3-Clause 13718cf2ccSPedro F. Giffuni ** 1435689395SXin LI ** Copyright (C) 2002 - 2012, Areca Technology Corporation 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. 3735689395SXin LI ******************************************************************************** 38f1c579b1SScott Long ** History 39f1c579b1SScott Long ** 40f1c579b1SScott Long ** REV# DATE NAME DESCRIPTION 4122f2616bSXin 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 4322f2616bSXin LI ** 1.20.00.03 04/19/2005 Erich Chen add SATA 24 Ports adapter type support 44ad6d6297SScott Long ** clean unused function 4522f2616bSXin 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 5022f2616bSXin 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 6722f2616bSXin LI ** 1.20.00.20 12/08/2010 Ching Huang Avoid calling atomic_set_int function 6822f2616bSXin LI ** 1.20.00.21 02/08/2011 Ching Huang Implement I/O request timeout 6922f2616bSXin LI ** 02/14/2011 Ching Huang Modified pktRequestCount 7022f2616bSXin LI ** 1.20.00.21 03/03/2011 Ching Huang if a command timeout, then wait its ccb back before free it 714e32649fSXin LI ** 1.20.00.22 07/04/2011 Ching Huang Fixed multiple MTX panic 72dac36688SXin LI ** 1.20.00.23 10/28/2011 Ching Huang Added TIMEOUT_DELAY in case of too many HDDs need to start 73dac36688SXin LI ** 1.20.00.23 11/08/2011 Ching Huang Added report device transfer speed 74dac36688SXin LI ** 1.20.00.23 01/30/2012 Ching Huang Fixed Request requeued and Retrying command 75dac36688SXin LI ** 1.20.00.24 06/11/2012 Ching Huang Fixed return sense data condition 76dac36688SXin LI ** 1.20.00.25 08/17/2012 Ching Huang Fixed hotplug device no function on type A adapter 77abfdbca9SXin LI ** 1.20.00.26 12/14/2012 Ching Huang Added support ARC1214,1224,1264,1284 78abfdbca9SXin LI ** 1.20.00.27 05/06/2013 Ching Huang Fixed out standing cmd full on ARC-12x4 791e7d660aSXin LI ** 1.20.00.28 09/13/2013 Ching Huang Removed recursive mutex in arcmsr_abort_dr_ccbs 80224a78aeSXin LI ** 1.20.00.29 12/18/2013 Ching Huang Change simq allocation number, support ARC1883 81b23a1998SXin LI ** 1.30.00.00 11/30/2015 Ching Huang Added support ARC1203 82a1103e04SXin LI ** 1.40.00.00 07/11/2017 Ching Huang Added support ARC1884 83fc5ef1caSXin LI ** 1.40.00.01 10/30/2017 Ching Huang Fixed release memory resource 84fa42a0bfSXin LI ** 1.50.00.00 09/30/2020 Ching Huang Added support ARC-1886, NVMe/SAS/SATA controller 855842073aSXin LI ** 1.50.00.01 02/26/2021 Ching Huang Fixed no action of hot plugging device on type_F adapter 86438b5532SXin LI ** 1.50.00.02 04/16/2021 Ching Huang Fixed scsi command timeout on ARC-1886 when 87438b5532SXin LI ** scatter-gather count large than some number 886964b77eS黃清隆 ** 1.50.00.03 05/04/2021 Ching Huang Fixed doorbell status arrived late on ARC-1886 896964b77eS黃清隆 ** 1.50.00.04 12/08/2021 Ching Huang Fixed boot up hung under ARC-1886 with no volume created 90285d85f4S黃清隆 ** 1.50.00.05 03/23/2023 Ching Huang Fixed reading buffer empty length error 91f1c579b1SScott Long ****************************************************************************************** 92f1c579b1SScott Long */ 934b7ec270SMarius Strobl 944b7ec270SMarius Strobl #include <sys/cdefs.h> 9522f2616bSXin LI #if 0 9622f2616bSXin LI #define ARCMSR_DEBUG1 1 9722f2616bSXin LI #endif 98f1c579b1SScott Long #include <sys/param.h> 99f1c579b1SScott Long #include <sys/systm.h> 100f1c579b1SScott Long #include <sys/malloc.h> 101f1c579b1SScott Long #include <sys/kernel.h> 102f1c579b1SScott Long #include <sys/bus.h> 103f1c579b1SScott Long #include <sys/queue.h> 104f1c579b1SScott Long #include <sys/stat.h> 105f1c579b1SScott Long #include <sys/devicestat.h> 106f1c579b1SScott Long #include <sys/kthread.h> 107f1c579b1SScott Long #include <sys/module.h> 108f1c579b1SScott Long #include <sys/proc.h> 109f1c579b1SScott Long #include <sys/lock.h> 110f1c579b1SScott Long #include <sys/sysctl.h> 111f1c579b1SScott Long #include <sys/poll.h> 112f1c579b1SScott Long #include <sys/ioccom.h> 113f1c579b1SScott Long #include <vm/vm.h> 114f1c579b1SScott Long #include <vm/vm_param.h> 115f1c579b1SScott Long #include <vm/pmap.h> 116f1c579b1SScott Long 117f1c579b1SScott Long #include <isa/rtc.h> 118f1c579b1SScott Long 119f1c579b1SScott Long #include <machine/bus.h> 120f1c579b1SScott Long #include <machine/resource.h> 121f1c579b1SScott Long #include <machine/atomic.h> 122f1c579b1SScott Long #include <sys/conf.h> 123f1c579b1SScott Long #include <sys/rman.h> 124f1c579b1SScott Long 125f1c579b1SScott Long #include <cam/cam.h> 126f1c579b1SScott Long #include <cam/cam_ccb.h> 127f1c579b1SScott Long #include <cam/cam_sim.h> 128d74001adSXin LI #include <cam/cam_periph.h> 129d74001adSXin LI #include <cam/cam_xpt_periph.h> 130f1c579b1SScott Long #include <cam/cam_xpt_sim.h> 131f1c579b1SScott Long #include <cam/cam_debug.h> 132f1c579b1SScott Long #include <cam/scsi/scsi_all.h> 133f1c579b1SScott Long #include <cam/scsi/scsi_message.h> 134f1c579b1SScott Long /* 135f1c579b1SScott Long ************************************************************************** 136f1c579b1SScott Long ************************************************************************** 137f1c579b1SScott Long */ 138f1c579b1SScott Long #include <sys/selinfo.h> 139f1c579b1SScott Long #include <sys/mutex.h> 140ad6d6297SScott Long #include <sys/endian.h> 141f1c579b1SScott Long #include <dev/pci/pcivar.h> 142f1c579b1SScott Long #include <dev/pci/pcireg.h> 14344f05562SScott Long 14422f2616bSXin LI #define arcmsr_callout_init(a) callout_init(a, /*mpsafe*/1); 14522f2616bSXin LI 146285d85f4S黃清隆 #define ARCMSR_DRIVER_VERSION "arcmsr version 1.50.00.05 2023-03-23" 147f1c579b1SScott Long #include <dev/arcmsr/arcmsr.h> 148f1c579b1SScott Long /* 149f1c579b1SScott Long ************************************************************************** 150f1c579b1SScott Long ************************************************************************** 151f1c579b1SScott Long */ 15222f2616bSXin LI static void arcmsr_free_srb(struct CommandControlBlock *srb); 153ad6d6297SScott Long static struct CommandControlBlock *arcmsr_get_freesrb(struct AdapterControlBlock *acb); 154ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb *abortccb); 155f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev); 156f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev); 157f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev); 158ad6d6297SScott Long static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg); 159ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb); 160f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev); 16144f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb); 162ad6d6297SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb); 163ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb); 164ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb); 165ad6d6297SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); 166ad6d6297SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb); 167ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb); 168ad6d6297SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb); 16935689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, struct QBUFFER *prbuffer); 1707a7bc959SXin LI static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb); 171ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb); 172ad6d6297SScott Long static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag); 173ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb); 174ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb); 175ad6d6297SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t *dm_segs, u_int32_t nseg); 176ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *pccb); 177ad6d6297SScott Long static int arcmsr_resume(device_t dev); 178ad6d6297SScott Long static int arcmsr_suspend(device_t dev); 179d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb); 180d74001adSXin LI static void arcmsr_polling_devmap(void *arg); 18122f2616bSXin LI static void arcmsr_srb_timeout(void *arg); 1827a7bc959SXin LI static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb); 183a1103e04SXin LI static void arcmsr_hbe_postqueue_isr(struct AdapterControlBlock *acb); 184fa42a0bfSXin LI static void arcmsr_hbf_postqueue_isr(struct AdapterControlBlock *acb); 185fc5ef1caSXin LI static void arcmsr_teardown_intr(device_t dev, struct AdapterControlBlock *acb); 18622f2616bSXin LI #ifdef ARCMSR_DEBUG1 18722f2616bSXin LI static void arcmsr_dump_data(struct AdapterControlBlock *acb); 18822f2616bSXin LI #endif 189f1c579b1SScott Long /* 190f1c579b1SScott Long ************************************************************************** 191ad6d6297SScott Long ************************************************************************** 192ad6d6297SScott Long */ 193ad6d6297SScott Long static void UDELAY(u_int32_t us) { DELAY(us); } 194ad6d6297SScott Long /* 195ad6d6297SScott Long ************************************************************************** 196f1c579b1SScott Long ************************************************************************** 197f1c579b1SScott Long */ 198231c8b71SXin LI static bus_dmamap_callback_t arcmsr_map_free_srb; 199231c8b71SXin LI static bus_dmamap_callback_t arcmsr_execute_srb; 200f1c579b1SScott Long /* 201f1c579b1SScott Long ************************************************************************** 202f1c579b1SScott Long ************************************************************************** 203f1c579b1SScott Long */ 204f1c579b1SScott Long static d_open_t arcmsr_open; 205f1c579b1SScott Long static d_close_t arcmsr_close; 206f1c579b1SScott Long static d_ioctl_t arcmsr_ioctl; 207f1c579b1SScott Long 208f1c579b1SScott Long static device_method_t arcmsr_methods[]={ 209f1c579b1SScott Long DEVMETHOD(device_probe, arcmsr_probe), 210f1c579b1SScott Long DEVMETHOD(device_attach, arcmsr_attach), 211f1c579b1SScott Long DEVMETHOD(device_detach, arcmsr_detach), 212f1c579b1SScott Long DEVMETHOD(device_shutdown, arcmsr_shutdown), 213ad6d6297SScott Long DEVMETHOD(device_suspend, arcmsr_suspend), 214ad6d6297SScott Long DEVMETHOD(device_resume, arcmsr_resume), 2154b7ec270SMarius Strobl DEVMETHOD_END 216f1c579b1SScott Long }; 217f1c579b1SScott Long 218f1c579b1SScott Long static driver_t arcmsr_driver={ 219ad6d6297SScott Long "arcmsr", arcmsr_methods, sizeof(struct AdapterControlBlock) 220f1c579b1SScott Long }; 221f1c579b1SScott Long 2220d6d8bacSJohn Baldwin DRIVER_MODULE(arcmsr, pci, arcmsr_driver, 0, 0); 223d3cf342dSScott Long MODULE_DEPEND(arcmsr, pci, 1, 1, 1); 224d3cf342dSScott Long MODULE_DEPEND(arcmsr, cam, 1, 1, 1); 225ad6d6297SScott Long #ifndef BUS_DMA_COHERENT 226ad6d6297SScott Long #define BUS_DMA_COHERENT 0x04 /* hint: map memory in a coherent way */ 227ad6d6297SScott Long #endif 228f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw={ 229f1c579b1SScott Long .d_version = D_VERSION, 230f1c579b1SScott Long .d_open = arcmsr_open, /* open */ 231f1c579b1SScott Long .d_close = arcmsr_close, /* close */ 232f1c579b1SScott Long .d_ioctl = arcmsr_ioctl, /* ioctl */ 233f1c579b1SScott Long .d_name = "arcmsr", /* name */ 234f1c579b1SScott Long }; 235d74001adSXin LI /* 236d74001adSXin LI ************************************************************************** 237d74001adSXin LI ************************************************************************** 238d74001adSXin LI */ 23900b4e54aSWarner Losh static int arcmsr_open(struct cdev *dev, int flags, int fmt, struct thread *proc) 240f1c579b1SScott Long { 241dac36688SXin LI return (0); 242f1c579b1SScott Long } 243f1c579b1SScott Long /* 244f1c579b1SScott Long ************************************************************************** 245f1c579b1SScott Long ************************************************************************** 246f1c579b1SScott Long */ 24700b4e54aSWarner Losh static int arcmsr_close(struct cdev *dev, int flags, int fmt, struct thread *proc) 248f1c579b1SScott Long { 249f1c579b1SScott Long return 0; 250f1c579b1SScott Long } 251f1c579b1SScott Long /* 252f1c579b1SScott Long ************************************************************************** 253f1c579b1SScott Long ************************************************************************** 254f1c579b1SScott Long */ 25500b4e54aSWarner Losh static int arcmsr_ioctl(struct cdev *dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc) 256f1c579b1SScott Long { 257a9e5e04eSJohn Baldwin struct AdapterControlBlock *acb = dev->si_drv1; 258f1c579b1SScott Long 259ad6d6297SScott Long return (arcmsr_iop_ioctlcmd(acb, ioctl_cmd, arg)); 260f1c579b1SScott Long } 261f1c579b1SScott Long /* 26244f05562SScott Long ********************************************************************** 26344f05562SScott Long ********************************************************************** 26444f05562SScott Long */ 26544f05562SScott Long static u_int32_t arcmsr_disable_allintr( struct AdapterControlBlock *acb) 26644f05562SScott Long { 26744f05562SScott Long u_int32_t intmask_org = 0; 26844f05562SScott Long 26944f05562SScott Long switch (acb->adapter_type) { 27044f05562SScott Long case ACB_ADAPTER_TYPE_A: { 27144f05562SScott Long /* disable all outbound interrupt */ 272d74001adSXin LI intmask_org = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intmask); /* disable outbound message0 int */ 273d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); 27444f05562SScott Long } 27544f05562SScott Long break; 27644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 277b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 27844f05562SScott Long /* disable all outbound interrupt */ 279b23a1998SXin LI intmask_org = READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask) 280b23a1998SXin LI & (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); /* disable outbound message0 int */ 281b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask, 0); /* disable all interrupt */ 282d74001adSXin LI } 283d74001adSXin LI break; 284d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 285d74001adSXin LI /* disable all outbound interrupt */ 286d74001adSXin LI intmask_org = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_mask); /* disable outbound message0 int */ 287d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org|ARCMSR_HBCMU_ALL_INTMASKENABLE); 28844f05562SScott Long } 28944f05562SScott Long break; 2907a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 2917a7bc959SXin LI /* disable all outbound interrupt */ 2927a7bc959SXin LI intmask_org = CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable); /* disable outbound message0 int */ 2937a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, ARCMSR_HBDMU_ALL_INT_DISABLE); 2947a7bc959SXin LI } 2957a7bc959SXin LI break; 296fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 297fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 298a1103e04SXin LI /* disable all outbound interrupt */ 299fa42a0bfSXin LI intmask_org = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_mask); /* disable outbound message0 int */ 300a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_mask, intmask_org | ARCMSR_HBEMU_ALL_INTMASKENABLE); 301a1103e04SXin LI } 302a1103e04SXin LI break; 30344f05562SScott Long } 30444f05562SScott Long return (intmask_org); 30544f05562SScott Long } 30644f05562SScott Long /* 30744f05562SScott Long ********************************************************************** 30844f05562SScott Long ********************************************************************** 30944f05562SScott Long */ 31044f05562SScott Long static void arcmsr_enable_allintr( struct AdapterControlBlock *acb, u_int32_t intmask_org) 31144f05562SScott Long { 31244f05562SScott Long u_int32_t mask; 31344f05562SScott Long 31444f05562SScott Long switch (acb->adapter_type) { 31544f05562SScott Long case ACB_ADAPTER_TYPE_A: { 31644f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 317d74001adSXin LI mask = ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE); 31844f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org & mask); 31944f05562SScott Long acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; 32044f05562SScott Long } 32144f05562SScott Long break; 32244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 323b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 324d74001adSXin LI /* enable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */ 325d74001adSXin LI mask = (ARCMSR_IOP2DRV_DATA_WRITE_OK|ARCMSR_IOP2DRV_DATA_READ_OK|ARCMSR_IOP2DRV_CDB_DONE|ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); 326b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask, intmask_org | mask); /*1=interrupt enable, 0=interrupt disable*/ 32744f05562SScott Long acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f; 32844f05562SScott Long } 32944f05562SScott Long break; 330d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 331d74001adSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 332d74001adSXin LI mask = ~(ARCMSR_HBCMU_UTILITY_A_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK); 333d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org & mask); 334d74001adSXin LI acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f; 335d74001adSXin LI } 336d74001adSXin LI break; 3377a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 3387a7bc959SXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 3397a7bc959SXin LI mask = ARCMSR_HBDMU_ALL_INT_ENABLE; 3407a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, intmask_org | mask); 3417a7bc959SXin LI CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable); 3427a7bc959SXin LI acb->outbound_int_enable = mask; 3437a7bc959SXin LI } 3447a7bc959SXin LI break; 345fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 346fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 347a1103e04SXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 348a1103e04SXin LI mask = ~(ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR | ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR); 349a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_mask, intmask_org & mask); 350a1103e04SXin LI acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f; 351a1103e04SXin LI } 352a1103e04SXin LI break; 35344f05562SScott Long } 35444f05562SScott Long } 35544f05562SScott Long /* 35644f05562SScott Long ********************************************************************** 35744f05562SScott Long ********************************************************************** 35844f05562SScott Long */ 35944f05562SScott Long static u_int8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) 36044f05562SScott Long { 36144f05562SScott Long u_int32_t Index; 36244f05562SScott Long u_int8_t Retries = 0x00; 36344f05562SScott Long 36444f05562SScott Long do { 36544f05562SScott Long for(Index=0; Index < 100; Index++) { 366d74001adSXin LI if(CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { 367d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/ 36844f05562SScott Long return TRUE; 36944f05562SScott Long } 37044f05562SScott Long UDELAY(10000); 37144f05562SScott Long }/*max 1 seconds*/ 37244f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 373dac36688SXin LI return (FALSE); 37444f05562SScott Long } 37544f05562SScott Long /* 37644f05562SScott Long ********************************************************************** 37744f05562SScott Long ********************************************************************** 37844f05562SScott Long */ 37944f05562SScott Long static u_int8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) 38044f05562SScott Long { 38144f05562SScott Long u_int32_t Index; 38244f05562SScott Long u_int8_t Retries = 0x00; 383b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 38444f05562SScott Long 38544f05562SScott Long do { 38644f05562SScott Long for(Index=0; Index < 100; Index++) { 387b23a1998SXin LI if(READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { 388b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/ 389b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 390d74001adSXin LI return TRUE; 391d74001adSXin LI } 392d74001adSXin LI UDELAY(10000); 393d74001adSXin LI }/*max 1 seconds*/ 394d74001adSXin LI }while(Retries++ < 20);/*max 20 sec*/ 395dac36688SXin LI return (FALSE); 396d74001adSXin LI } 397d74001adSXin LI /* 398d74001adSXin LI ********************************************************************** 399d74001adSXin LI ********************************************************************** 400d74001adSXin LI */ 401d74001adSXin LI static u_int8_t arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock *acb) 402d74001adSXin LI { 403d74001adSXin LI u_int32_t Index; 404d74001adSXin LI u_int8_t Retries = 0x00; 405d74001adSXin LI 406d74001adSXin LI do { 407d74001adSXin LI for(Index=0; Index < 100; Index++) { 408d74001adSXin LI if(CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { 409d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);/*clear interrupt*/ 41044f05562SScott Long return TRUE; 41144f05562SScott Long } 41244f05562SScott Long UDELAY(10000); 41344f05562SScott Long }/*max 1 seconds*/ 41444f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 415dac36688SXin LI return (FALSE); 41644f05562SScott Long } 41744f05562SScott Long /* 4187a7bc959SXin LI ********************************************************************** 4197a7bc959SXin LI ********************************************************************** 4207a7bc959SXin LI */ 4217a7bc959SXin LI static u_int8_t arcmsr_hbd_wait_msgint_ready(struct AdapterControlBlock *acb) 4227a7bc959SXin LI { 4237a7bc959SXin LI u_int32_t Index; 4247a7bc959SXin LI u_int8_t Retries = 0x00; 4257a7bc959SXin LI 4267a7bc959SXin LI do { 4277a7bc959SXin LI for(Index=0; Index < 100; Index++) { 4287a7bc959SXin LI if(CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) { 4297a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR);/*clear interrupt*/ 4307a7bc959SXin LI return TRUE; 4317a7bc959SXin LI } 4327a7bc959SXin LI UDELAY(10000); 4337a7bc959SXin LI }/*max 1 seconds*/ 4347a7bc959SXin LI }while(Retries++ < 20);/*max 20 sec*/ 4357a7bc959SXin LI return (FALSE); 4367a7bc959SXin LI } 4377a7bc959SXin LI /* 438a1103e04SXin LI ********************************************************************** 439a1103e04SXin LI ********************************************************************** 440a1103e04SXin LI */ 441a1103e04SXin LI static u_int8_t arcmsr_hbe_wait_msgint_ready(struct AdapterControlBlock *acb) 442a1103e04SXin LI { 443a1103e04SXin LI u_int32_t Index, read_doorbell; 444a1103e04SXin LI u_int8_t Retries = 0x00; 445a1103e04SXin LI 446a1103e04SXin LI do { 447a1103e04SXin LI for(Index=0; Index < 100; Index++) { 448a1103e04SXin LI read_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell); 449a1103e04SXin LI if((read_doorbell ^ acb->in_doorbell) & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) { 450a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0);/*clear interrupt*/ 451a1103e04SXin LI acb->in_doorbell = read_doorbell; 452a1103e04SXin LI return TRUE; 453a1103e04SXin LI } 454a1103e04SXin LI UDELAY(10000); 455a1103e04SXin LI }/*max 1 seconds*/ 456a1103e04SXin LI }while(Retries++ < 20);/*max 20 sec*/ 457a1103e04SXin LI return (FALSE); 458a1103e04SXin LI } 459a1103e04SXin LI /* 46044f05562SScott Long ************************************************************************ 46144f05562SScott Long ************************************************************************ 46244f05562SScott Long */ 46344f05562SScott Long static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) 46444f05562SScott Long { 46544f05562SScott Long int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ 46644f05562SScott Long 467d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 46844f05562SScott Long do { 46944f05562SScott Long if(arcmsr_hba_wait_msgint_ready(acb)) { 47044f05562SScott Long break; 47144f05562SScott Long } else { 47244f05562SScott Long retry_count--; 47344f05562SScott Long } 47444f05562SScott Long }while(retry_count != 0); 47544f05562SScott Long } 47644f05562SScott Long /* 47744f05562SScott Long ************************************************************************ 47844f05562SScott Long ************************************************************************ 47944f05562SScott Long */ 48044f05562SScott Long static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) 48144f05562SScott Long { 48244f05562SScott Long int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ 483b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 48444f05562SScott Long 485b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_FLUSH_CACHE); 48644f05562SScott Long do { 48744f05562SScott Long if(arcmsr_hbb_wait_msgint_ready(acb)) { 48844f05562SScott Long break; 48944f05562SScott Long } else { 49044f05562SScott Long retry_count--; 49144f05562SScott Long } 49244f05562SScott Long }while(retry_count != 0); 49344f05562SScott Long } 49444f05562SScott Long /* 49544f05562SScott Long ************************************************************************ 49644f05562SScott Long ************************************************************************ 49744f05562SScott Long */ 498d74001adSXin LI static void arcmsr_flush_hbc_cache(struct AdapterControlBlock *acb) 499d74001adSXin LI { 500d74001adSXin LI int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ 501d74001adSXin LI 502d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 503d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 504d74001adSXin LI do { 505d74001adSXin LI if(arcmsr_hbc_wait_msgint_ready(acb)) { 506d74001adSXin LI break; 507d74001adSXin LI } else { 508d74001adSXin LI retry_count--; 509d74001adSXin LI } 510d74001adSXin LI }while(retry_count != 0); 511d74001adSXin LI } 512d74001adSXin LI /* 513d74001adSXin LI ************************************************************************ 514d74001adSXin LI ************************************************************************ 515d74001adSXin LI */ 5167a7bc959SXin LI static void arcmsr_flush_hbd_cache(struct AdapterControlBlock *acb) 5177a7bc959SXin LI { 5187a7bc959SXin LI int retry_count = 30; /* enlarge wait flush adapter cache time: 10 minute */ 5197a7bc959SXin LI 5207a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 5217a7bc959SXin LI do { 5227a7bc959SXin LI if(arcmsr_hbd_wait_msgint_ready(acb)) { 5237a7bc959SXin LI break; 5247a7bc959SXin LI } else { 5257a7bc959SXin LI retry_count--; 5267a7bc959SXin LI } 5277a7bc959SXin LI }while(retry_count != 0); 5287a7bc959SXin LI } 5297a7bc959SXin LI /* 5307a7bc959SXin LI ************************************************************************ 5317a7bc959SXin LI ************************************************************************ 5327a7bc959SXin LI */ 533a1103e04SXin LI static void arcmsr_flush_hbe_cache(struct AdapterControlBlock *acb) 534a1103e04SXin LI { 535a1103e04SXin LI int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ 536a1103e04SXin LI 537a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 538a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 539a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 540a1103e04SXin LI do { 541a1103e04SXin LI if(arcmsr_hbe_wait_msgint_ready(acb)) { 542a1103e04SXin LI break; 543a1103e04SXin LI } else { 544a1103e04SXin LI retry_count--; 545a1103e04SXin LI } 546a1103e04SXin LI }while(retry_count != 0); 547a1103e04SXin LI } 548a1103e04SXin LI /* 549a1103e04SXin LI ************************************************************************ 550a1103e04SXin LI ************************************************************************ 551a1103e04SXin LI */ 55244f05562SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) 55344f05562SScott Long { 55444f05562SScott Long switch (acb->adapter_type) { 55544f05562SScott Long case ACB_ADAPTER_TYPE_A: { 55644f05562SScott Long arcmsr_flush_hba_cache(acb); 55744f05562SScott Long } 55844f05562SScott Long break; 55944f05562SScott Long case ACB_ADAPTER_TYPE_B: { 56044f05562SScott Long arcmsr_flush_hbb_cache(acb); 56144f05562SScott Long } 56244f05562SScott Long break; 563d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 564d74001adSXin LI arcmsr_flush_hbc_cache(acb); 565d74001adSXin LI } 566d74001adSXin LI break; 5677a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 5687a7bc959SXin LI arcmsr_flush_hbd_cache(acb); 5697a7bc959SXin LI } 5707a7bc959SXin LI break; 571fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 572fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 573a1103e04SXin LI arcmsr_flush_hbe_cache(acb); 574a1103e04SXin LI } 575a1103e04SXin LI break; 57644f05562SScott Long } 57744f05562SScott Long } 57844f05562SScott Long /* 579ad6d6297SScott Long ******************************************************************************* 580ad6d6297SScott Long ******************************************************************************* 581f1c579b1SScott Long */ 582ad6d6297SScott Long static int arcmsr_suspend(device_t dev) 583f1c579b1SScott Long { 584ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 585f1c579b1SScott Long 586ad6d6297SScott Long /* flush controller */ 587ad6d6297SScott Long arcmsr_iop_parking(acb); 588d74001adSXin LI /* disable all outbound interrupt */ 589d74001adSXin LI arcmsr_disable_allintr(acb); 590ad6d6297SScott Long return(0); 591ad6d6297SScott Long } 592ad6d6297SScott Long /* 593ad6d6297SScott Long ******************************************************************************* 594ad6d6297SScott Long ******************************************************************************* 595ad6d6297SScott Long */ 596ad6d6297SScott Long static int arcmsr_resume(device_t dev) 597ad6d6297SScott Long { 598ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 599f1c579b1SScott Long 600ad6d6297SScott Long arcmsr_iop_init(acb); 601ad6d6297SScott Long return(0); 602f1c579b1SScott Long } 603f1c579b1SScott Long /* 604f1c579b1SScott Long ********************************************************************************* 605f1c579b1SScott Long ********************************************************************************* 606f1c579b1SScott Long */ 607ad6d6297SScott Long static void arcmsr_async(void *cb_arg, u_int32_t code, struct cam_path *path, void *arg) 608f1c579b1SScott Long { 609ad6d6297SScott Long u_int8_t target_id, target_lun; 610f1c579b1SScott Long 611ad6d6297SScott Long switch (code) { 612f1c579b1SScott Long case AC_LOST_DEVICE: 613f1c579b1SScott Long target_id = xpt_path_target_id(path); 614f1c579b1SScott Long target_lun = xpt_path_lun_id(path); 615d74001adSXin LI if((target_id > ARCMSR_MAX_TARGETID) || (target_lun > ARCMSR_MAX_TARGETLUN)) { 616f1c579b1SScott Long break; 617f1c579b1SScott Long } 618f1c579b1SScott Long break; 619f1c579b1SScott Long default: 620f1c579b1SScott Long break; 621f1c579b1SScott Long } 622f1c579b1SScott Long } 623f1c579b1SScott Long /* 624f1c579b1SScott Long ********************************************************************** 625f1c579b1SScott Long ********************************************************************** 626f1c579b1SScott Long */ 627ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb) 628f1c579b1SScott Long { 629ad6d6297SScott Long union ccb *pccb = srb->pccb; 630f1c579b1SScott Long 631ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 632ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 633dac36688SXin LI if(pccb->csio.sense_len) { 634ad6d6297SScott Long memset(&pccb->csio.sense_data, 0, sizeof(pccb->csio.sense_data)); 635ad6d6297SScott Long memcpy(&pccb->csio.sense_data, srb->arcmsr_cdb.SenseData, 636ad6d6297SScott Long get_min(sizeof(struct SENSE_DATA), sizeof(pccb->csio.sense_data))); 637ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); /* Valid,ErrorCode */ 638f1c579b1SScott Long pccb->ccb_h.status |= CAM_AUTOSNS_VALID; 639f1c579b1SScott Long } 640f1c579b1SScott Long } 641f1c579b1SScott Long /* 642f1c579b1SScott Long ********************************************************************* 64344f05562SScott Long ********************************************************************* 64444f05562SScott Long */ 64544f05562SScott Long static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) 64644f05562SScott Long { 64744f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 64844f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 649d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 65044f05562SScott Long } 65144f05562SScott Long } 65244f05562SScott Long /* 65344f05562SScott Long ********************************************************************* 65444f05562SScott Long ********************************************************************* 65544f05562SScott Long */ 65644f05562SScott Long static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) 65744f05562SScott Long { 658b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 659b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_ABORT_CMD); 66044f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 661d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 662d74001adSXin LI } 663d74001adSXin LI } 664d74001adSXin LI /* 665d74001adSXin LI ********************************************************************* 666d74001adSXin LI ********************************************************************* 667d74001adSXin LI */ 668d74001adSXin LI static void arcmsr_abort_hbc_allcmd(struct AdapterControlBlock *acb) 669d74001adSXin LI { 670d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 671d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 672d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 673d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 67444f05562SScott Long } 67544f05562SScott Long } 67644f05562SScott Long /* 67744f05562SScott Long ********************************************************************* 678f1c579b1SScott Long ********************************************************************* 679f1c579b1SScott Long */ 6807a7bc959SXin LI static void arcmsr_abort_hbd_allcmd(struct AdapterControlBlock *acb) 6817a7bc959SXin LI { 6827a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 6837a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 6847a7bc959SXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 6857a7bc959SXin LI } 6867a7bc959SXin LI } 6877a7bc959SXin LI /* 6887a7bc959SXin LI ********************************************************************* 6897a7bc959SXin LI ********************************************************************* 6907a7bc959SXin LI */ 691a1103e04SXin LI static void arcmsr_abort_hbe_allcmd(struct AdapterControlBlock *acb) 692a1103e04SXin LI { 693a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 694a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 695a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 696a1103e04SXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) { 697a1103e04SXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 698a1103e04SXin LI } 699a1103e04SXin LI } 700a1103e04SXin LI /* 701a1103e04SXin LI ********************************************************************* 702a1103e04SXin LI ********************************************************************* 703a1103e04SXin LI */ 704ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) 705f1c579b1SScott Long { 70644f05562SScott Long switch (acb->adapter_type) { 70744f05562SScott Long case ACB_ADAPTER_TYPE_A: { 70844f05562SScott Long arcmsr_abort_hba_allcmd(acb); 70944f05562SScott Long } 71044f05562SScott Long break; 71144f05562SScott Long case ACB_ADAPTER_TYPE_B: { 71244f05562SScott Long arcmsr_abort_hbb_allcmd(acb); 71344f05562SScott Long } 71444f05562SScott Long break; 715d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 716d74001adSXin LI arcmsr_abort_hbc_allcmd(acb); 717d74001adSXin LI } 718d74001adSXin LI break; 7197a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 7207a7bc959SXin LI arcmsr_abort_hbd_allcmd(acb); 7217a7bc959SXin LI } 7227a7bc959SXin LI break; 723fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 724fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 725a1103e04SXin LI arcmsr_abort_hbe_allcmd(acb); 726a1103e04SXin LI } 727a1103e04SXin LI break; 72844f05562SScott Long } 72944f05562SScott Long } 73044f05562SScott Long /* 731231c8b71SXin LI ********************************************************************** 732231c8b71SXin LI ********************************************************************** 733231c8b71SXin LI */ 734231c8b71SXin LI static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag) 735231c8b71SXin LI { 736231c8b71SXin LI struct AdapterControlBlock *acb = srb->acb; 737231c8b71SXin LI union ccb *pccb = srb->pccb; 738231c8b71SXin LI 73922f2616bSXin LI if(srb->srb_flags & SRB_FLAG_TIMER_START) 74022f2616bSXin LI callout_stop(&srb->ccb_callout); 741231c8b71SXin LI if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 742231c8b71SXin LI bus_dmasync_op_t op; 743231c8b71SXin LI 744231c8b71SXin LI if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 745231c8b71SXin LI op = BUS_DMASYNC_POSTREAD; 746231c8b71SXin LI } else { 747231c8b71SXin LI op = BUS_DMASYNC_POSTWRITE; 748231c8b71SXin LI } 749231c8b71SXin LI bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 750231c8b71SXin LI bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 751231c8b71SXin LI } 752231c8b71SXin LI if(stand_flag == 1) { 753231c8b71SXin LI atomic_subtract_int(&acb->srboutstandingcount, 1); 754231c8b71SXin LI if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) && ( 755abfdbca9SXin LI acb->srboutstandingcount < (acb->maxOutstanding -10))) { 756231c8b71SXin LI acb->acb_flags &= ~ACB_F_CAM_DEV_QFRZN; 757231c8b71SXin LI pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 758231c8b71SXin LI } 759231c8b71SXin LI } 76022f2616bSXin LI if(srb->srb_state != ARCMSR_SRB_TIMEOUT) 76122f2616bSXin LI arcmsr_free_srb(srb); 76222f2616bSXin LI acb->pktReturnCount++; 763231c8b71SXin LI xpt_done(pccb); 764231c8b71SXin LI } 765231c8b71SXin LI /* 76644f05562SScott Long ************************************************************************** 76744f05562SScott Long ************************************************************************** 76844f05562SScott Long */ 769d74001adSXin LI static void arcmsr_report_srb_state(struct AdapterControlBlock *acb, struct CommandControlBlock *srb, u_int16_t error) 77044f05562SScott Long { 77144f05562SScott Long int target, lun; 77244f05562SScott Long 77344f05562SScott Long target = srb->pccb->ccb_h.target_id; 77444f05562SScott Long lun = srb->pccb->ccb_h.target_lun; 775d74001adSXin LI if(error == FALSE) { 77644f05562SScott Long if(acb->devstate[target][lun] == ARECA_RAID_GONE) { 77744f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GOOD; 77844f05562SScott Long } 77944f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_CMP; 78044f05562SScott Long arcmsr_srb_complete(srb, 1); 78144f05562SScott Long } else { 78244f05562SScott Long switch(srb->arcmsr_cdb.DeviceStatus) { 78344f05562SScott Long case ARCMSR_DEV_SELECT_TIMEOUT: { 78444f05562SScott Long if(acb->devstate[target][lun] == ARECA_RAID_GOOD) { 785d74001adSXin LI printf( "arcmsr%d: Target=%x, Lun=%x, selection timeout, raid volume was lost\n", acb->pci_unit, target, lun); 786ad6d6297SScott Long } 78744f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GONE; 788d74001adSXin LI srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 78944f05562SScott Long arcmsr_srb_complete(srb, 1); 79044f05562SScott Long } 79144f05562SScott Long break; 79244f05562SScott Long case ARCMSR_DEV_ABORTED: 79344f05562SScott Long case ARCMSR_DEV_INIT_FAIL: { 79444f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GONE; 79544f05562SScott Long srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 79644f05562SScott Long arcmsr_srb_complete(srb, 1); 79744f05562SScott Long } 79844f05562SScott Long break; 79944f05562SScott Long case SCSISTAT_CHECK_CONDITION: { 80044f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GOOD; 80144f05562SScott Long arcmsr_report_sense_info(srb); 80244f05562SScott Long arcmsr_srb_complete(srb, 1); 80344f05562SScott Long } 80444f05562SScott Long break; 80544f05562SScott Long default: 80610d66948SKevin Lo printf("arcmsr%d: scsi id=%d lun=%d isr got command error done,but got unknown DeviceStatus=0x%x \n" 807d74001adSXin LI , acb->pci_unit, target, lun ,srb->arcmsr_cdb.DeviceStatus); 80844f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GONE; 80944f05562SScott Long srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY; 81010d66948SKevin Lo /*unknown error or crc error just for retry*/ 81144f05562SScott Long arcmsr_srb_complete(srb, 1); 81244f05562SScott Long break; 81344f05562SScott Long } 81444f05562SScott Long } 81544f05562SScott Long } 81644f05562SScott Long /* 81744f05562SScott Long ************************************************************************** 81844f05562SScott Long ************************************************************************** 81944f05562SScott Long */ 820d74001adSXin LI static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t flag_srb, u_int16_t error) 82144f05562SScott Long { 82244f05562SScott Long struct CommandControlBlock *srb; 82344f05562SScott Long 82444f05562SScott Long /* check if command done with no error*/ 825d74001adSXin LI switch (acb->adapter_type) { 826fc5ef1caSXin LI case ACB_ADAPTER_TYPE_A: 827fc5ef1caSXin LI case ACB_ADAPTER_TYPE_B: 828fc5ef1caSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 829fc5ef1caSXin LI break; 830d74001adSXin LI case ACB_ADAPTER_TYPE_C: 8317a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 83222f2616bSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0)); /*frame must be 32 bytes aligned*/ 833d74001adSXin LI break; 834a1103e04SXin LI case ACB_ADAPTER_TYPE_E: 835fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 836a1103e04SXin LI srb = acb->psrb_pool[flag_srb]; 837a1103e04SXin LI break; 838d74001adSXin LI default: 839d74001adSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 840d74001adSXin LI break; 841d74001adSXin LI } 84222f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 84322f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_TIMEOUT) { 84422f2616bSXin LI arcmsr_free_srb(srb); 84522f2616bSXin LI printf("arcmsr%d: srb='%p' return srb has been timeouted\n", acb->pci_unit, srb); 84644f05562SScott Long return; 84744f05562SScott Long } 84822f2616bSXin LI printf("arcmsr%d: return srb has been completed\n" 84922f2616bSXin LI "srb='%p' srb_state=0x%x outstanding srb count=%d \n", 85022f2616bSXin LI acb->pci_unit, srb, srb->srb_state, acb->srboutstandingcount); 85144f05562SScott Long return; 85244f05562SScott Long } 853d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 85444f05562SScott Long } 85544f05562SScott Long /* 85622f2616bSXin LI ************************************************************************** 85722f2616bSXin LI ************************************************************************** 85822f2616bSXin LI */ 85922f2616bSXin LI static void arcmsr_srb_timeout(void *arg) 86022f2616bSXin LI { 86122f2616bSXin LI struct CommandControlBlock *srb = (struct CommandControlBlock *)arg; 86222f2616bSXin LI struct AdapterControlBlock *acb; 86322f2616bSXin LI int target, lun; 86422f2616bSXin LI u_int8_t cmd; 86522f2616bSXin LI 86622f2616bSXin LI target = srb->pccb->ccb_h.target_id; 86722f2616bSXin LI lun = srb->pccb->ccb_h.target_lun; 86822f2616bSXin LI acb = srb->acb; 8697a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 87022f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) 87122f2616bSXin LI { 8724aa947cbSWarner Losh cmd = scsiio_cdb_ptr(&srb->pccb->csio)[0]; 87322f2616bSXin LI srb->srb_state = ARCMSR_SRB_TIMEOUT; 87422f2616bSXin LI srb->pccb->ccb_h.status |= CAM_CMD_TIMEOUT; 87522f2616bSXin LI arcmsr_srb_complete(srb, 1); 87622f2616bSXin LI printf("arcmsr%d: scsi id %d lun %d cmd=0x%x srb='%p' ccb command time out!\n", 87722f2616bSXin LI acb->pci_unit, target, lun, cmd, srb); 87822f2616bSXin LI } 8797a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 88022f2616bSXin LI #ifdef ARCMSR_DEBUG1 88122f2616bSXin LI arcmsr_dump_data(acb); 88222f2616bSXin LI #endif 88322f2616bSXin LI } 88422f2616bSXin LI 88522f2616bSXin LI /* 88644f05562SScott Long ********************************************************************** 88744f05562SScott Long ********************************************************************** 88844f05562SScott Long */ 88944f05562SScott Long static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) 89044f05562SScott Long { 89144f05562SScott Long int i=0; 89244f05562SScott Long u_int32_t flag_srb; 893d74001adSXin LI u_int16_t error; 89444f05562SScott Long 89544f05562SScott Long switch (acb->adapter_type) { 89644f05562SScott Long case ACB_ADAPTER_TYPE_A: { 89744f05562SScott Long u_int32_t outbound_intstatus; 89844f05562SScott Long 89944f05562SScott Long /*clear and abort all outbound posted Q*/ 900d74001adSXin LI outbound_intstatus = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 901d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/ 902d74001adSXin LI while(((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_queueport)) != 0xFFFFFFFF) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { 903d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 904d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 90544f05562SScott Long } 90644f05562SScott Long } 90744f05562SScott Long break; 90844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 90944f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 91044f05562SScott Long 91144f05562SScott Long /*clear all outbound posted Q*/ 912b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 91344f05562SScott Long for(i=0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) { 91444f05562SScott Long if((flag_srb = phbbmu->done_qbuffer[i]) != 0) { 91544f05562SScott Long phbbmu->done_qbuffer[i] = 0; 916d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 917d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 91844f05562SScott Long } 91944f05562SScott Long phbbmu->post_qbuffer[i] = 0; 92044f05562SScott Long }/*drain reply FIFO*/ 92144f05562SScott Long phbbmu->doneq_index = 0; 92244f05562SScott Long phbbmu->postq_index = 0; 92344f05562SScott Long } 92444f05562SScott Long break; 925d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 926d74001adSXin LI while((CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { 927d74001adSXin LI flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 928d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 929d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 930d74001adSXin LI } 931d74001adSXin LI } 932d74001adSXin LI break; 933fa42a0bfSXin LI case ACB_ADAPTER_TYPE_D: 9347a7bc959SXin LI arcmsr_hbd_postqueue_isr(acb); 9357a7bc959SXin LI break; 936fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 937a1103e04SXin LI arcmsr_hbe_postqueue_isr(acb); 938fa42a0bfSXin LI break; 939fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 940fa42a0bfSXin LI arcmsr_hbf_postqueue_isr(acb); 941a1103e04SXin LI break; 94244f05562SScott Long } 943f1c579b1SScott Long } 944f1c579b1SScott Long /* 945f1c579b1SScott Long **************************************************************************** 946f1c579b1SScott Long **************************************************************************** 947f1c579b1SScott Long */ 948ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb) 949f1c579b1SScott Long { 950ad6d6297SScott Long struct CommandControlBlock *srb; 95144f05562SScott Long u_int32_t intmask_org; 952ad6d6297SScott Long u_int32_t i=0; 953f1c579b1SScott Long 95444f05562SScott Long if(acb->srboutstandingcount>0) { 95544f05562SScott Long /* disable all outbound interrupt */ 95644f05562SScott Long intmask_org = arcmsr_disable_allintr(acb); 95744f05562SScott Long /*clear and abort all outbound posted Q*/ 95844f05562SScott Long arcmsr_done4abort_postqueue(acb); 959f1c579b1SScott Long /* talk to iop 331 outstanding command aborted*/ 960ad6d6297SScott Long arcmsr_abort_allcmd(acb); 961ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 962ad6d6297SScott Long srb = acb->psrb_pool[i]; 96322f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) { 96422f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 965ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 966ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 967123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p' aborted\n" 96822f2616bSXin LI , acb->pci_unit, srb->pccb->ccb_h.target_id 969123055f0SNathan Whitehorn , (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 970f1c579b1SScott Long } 971f1c579b1SScott Long } 972f1c579b1SScott Long /* enable all outbound interrupt */ 97344f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 974f1c579b1SScott Long } 97522f2616bSXin LI acb->srboutstandingcount = 0; 976ad6d6297SScott Long acb->workingsrb_doneindex = 0; 977ad6d6297SScott Long acb->workingsrb_startindex = 0; 97822f2616bSXin LI acb->pktRequestCount = 0; 97922f2616bSXin LI acb->pktReturnCount = 0; 980f1c579b1SScott Long } 981f1c579b1SScott Long /* 982f1c579b1SScott Long ********************************************************************** 983f1c579b1SScott Long ********************************************************************** 984f1c579b1SScott Long */ 98544f05562SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, 98644f05562SScott Long bus_dma_segment_t *dm_segs, u_int32_t nseg) 987f1c579b1SScott Long { 988ad6d6297SScott Long struct ARCMSR_CDB *arcmsr_cdb = &srb->arcmsr_cdb; 989ad6d6297SScott Long u_int8_t *psge = (u_int8_t *)&arcmsr_cdb->u; 990ad6d6297SScott Long u_int32_t address_lo, address_hi; 991ad6d6297SScott Long union ccb *pccb = srb->pccb; 992f1c579b1SScott Long struct ccb_scsiio *pcsio = &pccb->csio; 993ad6d6297SScott Long u_int32_t arccdbsize = 0x30; 994f1c579b1SScott Long 995ad6d6297SScott Long memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB)); 996ad6d6297SScott Long arcmsr_cdb->Bus = 0; 997ad6d6297SScott Long arcmsr_cdb->TargetID = pccb->ccb_h.target_id; 998ad6d6297SScott Long arcmsr_cdb->LUN = pccb->ccb_h.target_lun; 999ad6d6297SScott Long arcmsr_cdb->Function = 1; 1000ad6d6297SScott Long arcmsr_cdb->CdbLength = (u_int8_t)pcsio->cdb_len; 10014aa947cbSWarner Losh bcopy(scsiio_cdb_ptr(pcsio), arcmsr_cdb->Cdb, pcsio->cdb_len); 1002ad6d6297SScott Long if(nseg != 0) { 1003ad6d6297SScott Long struct AdapterControlBlock *acb = srb->acb; 1004f1c579b1SScott Long bus_dmasync_op_t op; 1005ad6d6297SScott Long u_int32_t length, i, cdb_sgcount = 0; 1006f1c579b1SScott Long 1007ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 1008ad6d6297SScott Long op = BUS_DMASYNC_PREREAD; 1009ad6d6297SScott Long } else { 1010ad6d6297SScott Long op = BUS_DMASYNC_PREWRITE; 1011ad6d6297SScott Long arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE; 1012ad6d6297SScott Long srb->srb_flags |= SRB_FLAG_WRITE; 1013ad6d6297SScott Long } 1014ad6d6297SScott Long bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 1015ad6d6297SScott Long for(i=0; i < nseg; i++) { 1016f1c579b1SScott Long /* Get the physical address of the current data pointer */ 1017ad6d6297SScott Long length = arcmsr_htole32(dm_segs[i].ds_len); 1018ad6d6297SScott Long address_lo = arcmsr_htole32(dma_addr_lo32(dm_segs[i].ds_addr)); 1019ad6d6297SScott Long address_hi = arcmsr_htole32(dma_addr_hi32(dm_segs[i].ds_addr)); 1020ad6d6297SScott Long if(address_hi == 0) { 1021ad6d6297SScott Long struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge; 1022f1c579b1SScott Long pdma_sg->address = address_lo; 1023f1c579b1SScott Long pdma_sg->length = length; 1024ad6d6297SScott Long psge += sizeof(struct SG32ENTRY); 1025ad6d6297SScott Long arccdbsize += sizeof(struct SG32ENTRY); 1026ad6d6297SScott Long } else { 1027ad6d6297SScott Long u_int32_t sg64s_size = 0, tmplength = length; 1028f1c579b1SScott Long 1029ad6d6297SScott Long while(1) { 1030ad6d6297SScott Long u_int64_t span4G, length0; 1031ad6d6297SScott Long struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge; 1032f1c579b1SScott Long 1033ad6d6297SScott Long span4G = (u_int64_t)address_lo + tmplength; 1034f1c579b1SScott Long pdma_sg->addresshigh = address_hi; 1035f1c579b1SScott Long pdma_sg->address = address_lo; 1036ad6d6297SScott Long if(span4G > 0x100000000) { 1037f1c579b1SScott Long /*see if cross 4G boundary*/ 1038f1c579b1SScott Long length0 = 0x100000000-address_lo; 1039ad6d6297SScott Long pdma_sg->length = (u_int32_t)length0 | IS_SG64_ADDR; 1040f1c579b1SScott Long address_hi = address_hi+1; 1041f1c579b1SScott Long address_lo = 0; 1042ad6d6297SScott Long tmplength = tmplength - (u_int32_t)length0; 1043ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 1044ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 1045f1c579b1SScott Long cdb_sgcount++; 1046ad6d6297SScott Long } else { 1047f1c579b1SScott Long pdma_sg->length = tmplength | IS_SG64_ADDR; 1048ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 1049ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 1050f1c579b1SScott Long break; 1051f1c579b1SScott Long } 1052f1c579b1SScott Long } 1053f1c579b1SScott Long arccdbsize += sg64s_size; 1054f1c579b1SScott Long } 1055f1c579b1SScott Long cdb_sgcount++; 1056f1c579b1SScott Long } 1057ad6d6297SScott Long arcmsr_cdb->sgcount = (u_int8_t)cdb_sgcount; 1058ad6d6297SScott Long arcmsr_cdb->DataLength = pcsio->dxfer_len; 1059ad6d6297SScott Long if( arccdbsize > 256) { 1060ad6d6297SScott Long arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE; 1061f1c579b1SScott Long } 1062d74001adSXin LI } else { 1063d74001adSXin LI arcmsr_cdb->DataLength = 0; 1064f1c579b1SScott Long } 1065d74001adSXin LI srb->arc_cdb_size = arccdbsize; 10667a7bc959SXin LI arcmsr_cdb->msgPages = (arccdbsize/256) + ((arccdbsize % 256) ? 1 : 0); 1067f1c579b1SScott Long } 1068f1c579b1SScott Long /* 1069f1c579b1SScott Long ************************************************************************** 1070f1c579b1SScott Long ************************************************************************** 1071f1c579b1SScott Long */ 1072ad6d6297SScott Long static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandControlBlock *srb) 1073f1c579b1SScott Long { 10747a7bc959SXin LI u_int32_t cdb_phyaddr_low = (u_int32_t) srb->cdb_phyaddr_low; 1075ad6d6297SScott Long struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&srb->arcmsr_cdb; 1076f1c579b1SScott Long 1077d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, (srb->srb_flags & SRB_FLAG_WRITE) ? BUS_DMASYNC_POSTWRITE:BUS_DMASYNC_POSTREAD); 1078ad6d6297SScott Long atomic_add_int(&acb->srboutstandingcount, 1); 107922f2616bSXin LI srb->srb_state = ARCMSR_SRB_START; 1080d74001adSXin LI 108144f05562SScott Long switch (acb->adapter_type) { 108244f05562SScott Long case ACB_ADAPTER_TYPE_A: { 1083ad6d6297SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 10847a7bc959SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_phyaddr_low|ARCMSR_SRBPOST_FLAG_SGL_BSIZE); 1085ad6d6297SScott Long } else { 10867a7bc959SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_phyaddr_low); 108744f05562SScott Long } 108844f05562SScott Long } 108944f05562SScott Long break; 109044f05562SScott Long case ACB_ADAPTER_TYPE_B: { 109144f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 109244f05562SScott Long int ending_index, index; 109344f05562SScott Long 109444f05562SScott Long index = phbbmu->postq_index; 109544f05562SScott Long ending_index = ((index+1) % ARCMSR_MAX_HBB_POSTQUEUE); 109644f05562SScott Long phbbmu->post_qbuffer[ending_index] = 0; 109744f05562SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 10987a7bc959SXin LI phbbmu->post_qbuffer[index] = cdb_phyaddr_low | ARCMSR_SRBPOST_FLAG_SGL_BSIZE; 109944f05562SScott Long } else { 11007a7bc959SXin LI phbbmu->post_qbuffer[index] = cdb_phyaddr_low; 110144f05562SScott Long } 110244f05562SScott Long index++; 110344f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 110444f05562SScott Long phbbmu->postq_index = index; 1105b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED); 1106d74001adSXin LI } 1107d74001adSXin LI break; 11087a7bc959SXin LI case ACB_ADAPTER_TYPE_C: { 1109d74001adSXin LI u_int32_t ccb_post_stamp, arc_cdb_size, cdb_phyaddr_hi32; 1110d74001adSXin LI 1111d74001adSXin LI arc_cdb_size = (srb->arc_cdb_size > 0x300) ? 0x300 : srb->arc_cdb_size; 11127a7bc959SXin LI ccb_post_stamp = (cdb_phyaddr_low | ((arc_cdb_size-1) >> 6) | 1); 1113d74001adSXin LI cdb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high; 1114d74001adSXin LI if(cdb_phyaddr_hi32) 1115d74001adSXin LI { 1116d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_high, cdb_phyaddr_hi32); 1117d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp); 1118d74001adSXin LI } 1119d74001adSXin LI else 1120d74001adSXin LI { 1121d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp); 1122d74001adSXin LI } 112344f05562SScott Long } 112444f05562SScott Long break; 11257a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 11267a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 11277a7bc959SXin LI u_int16_t index_stripped; 11287a7bc959SXin LI u_int16_t postq_index; 11297a7bc959SXin LI struct InBound_SRB *pinbound_srb; 11307a7bc959SXin LI 11317a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->postDone_lock); 11327a7bc959SXin LI postq_index = phbdmu->postq_index; 11337a7bc959SXin LI pinbound_srb = (struct InBound_SRB *)&phbdmu->post_qbuffer[postq_index & 0xFF]; 11347a7bc959SXin LI pinbound_srb->addressHigh = srb->cdb_phyaddr_high; 11357a7bc959SXin LI pinbound_srb->addressLow = srb->cdb_phyaddr_low; 11367a7bc959SXin LI pinbound_srb->length = srb->arc_cdb_size >> 2; 11377a7bc959SXin LI arcmsr_cdb->Context = srb->cdb_phyaddr_low; 11387a7bc959SXin LI if (postq_index & 0x4000) { 11397a7bc959SXin LI index_stripped = postq_index & 0xFF; 11407a7bc959SXin LI index_stripped += 1; 11417a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 11427a7bc959SXin LI phbdmu->postq_index = index_stripped ? (index_stripped | 0x4000) : index_stripped; 11437a7bc959SXin LI } else { 11447a7bc959SXin LI index_stripped = postq_index; 11457a7bc959SXin LI index_stripped += 1; 11467a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 11477a7bc959SXin LI phbdmu->postq_index = index_stripped ? index_stripped : (index_stripped | 0x4000); 11487a7bc959SXin LI } 11497a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inboundlist_write_pointer, postq_index); 11507a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->postDone_lock); 11517a7bc959SXin LI } 11527a7bc959SXin LI break; 1153a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 1154a1103e04SXin LI u_int32_t ccb_post_stamp, arc_cdb_size; 1155a1103e04SXin LI 1156a1103e04SXin LI arc_cdb_size = (srb->arc_cdb_size > 0x300) ? 0x300 : srb->arc_cdb_size; 1157a1103e04SXin LI ccb_post_stamp = (srb->smid | ((arc_cdb_size-1) >> 6)); 1158a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_queueport_high, 0); 1159a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_queueport_low, ccb_post_stamp); 1160a1103e04SXin LI } 1161a1103e04SXin LI break; 1162fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 1163fa42a0bfSXin LI u_int32_t ccb_post_stamp, arc_cdb_size; 1164fa42a0bfSXin LI 1165fa42a0bfSXin LI if (srb->arc_cdb_size <= 0x300) 1166fa42a0bfSXin LI arc_cdb_size = (srb->arc_cdb_size - 1) >> 6 | 1; 1167438b5532SXin LI else { 1168438b5532SXin LI arc_cdb_size = ((srb->arc_cdb_size + 0xff) >> 8) + 2; 1169438b5532SXin LI if (arc_cdb_size > 0xF) 1170438b5532SXin LI arc_cdb_size = 0xF; 1171438b5532SXin LI arc_cdb_size = (arc_cdb_size << 1) | 1; 1172438b5532SXin LI } 1173fa42a0bfSXin LI ccb_post_stamp = (srb->smid | arc_cdb_size); 1174fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_queueport_high, 0); 1175fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_queueport_low, ccb_post_stamp); 1176fa42a0bfSXin LI } 1177fa42a0bfSXin LI break; 1178f1c579b1SScott Long } 1179f1c579b1SScott Long } 1180f1c579b1SScott Long /* 118144f05562SScott Long ************************************************************************ 118244f05562SScott Long ************************************************************************ 118344f05562SScott Long */ 118444f05562SScott Long static struct QBUFFER *arcmsr_get_iop_rqbuffer( struct AdapterControlBlock *acb) 118544f05562SScott Long { 118644f05562SScott Long struct QBUFFER *qbuffer=NULL; 118744f05562SScott Long 118844f05562SScott Long switch (acb->adapter_type) { 118944f05562SScott Long case ACB_ADAPTER_TYPE_A: { 119044f05562SScott Long struct HBA_MessageUnit *phbamu = (struct HBA_MessageUnit *)acb->pmu; 119144f05562SScott Long 119244f05562SScott Long qbuffer = (struct QBUFFER *)&phbamu->message_rbuffer; 119344f05562SScott Long } 119444f05562SScott Long break; 119544f05562SScott Long case ACB_ADAPTER_TYPE_B: { 119644f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 119744f05562SScott Long 119844f05562SScott Long qbuffer = (struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_rbuffer; 119944f05562SScott Long } 120044f05562SScott Long break; 1201d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1202d74001adSXin LI struct HBC_MessageUnit *phbcmu = (struct HBC_MessageUnit *)acb->pmu; 1203d74001adSXin LI 1204d74001adSXin LI qbuffer = (struct QBUFFER *)&phbcmu->message_rbuffer; 1205d74001adSXin LI } 1206d74001adSXin LI break; 12077a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 12087a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 12097a7bc959SXin LI 12107a7bc959SXin LI qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_rbuffer; 12117a7bc959SXin LI } 12127a7bc959SXin LI break; 1213a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 1214a1103e04SXin LI struct HBE_MessageUnit *phbcmu = (struct HBE_MessageUnit *)acb->pmu; 1215a1103e04SXin LI 1216a1103e04SXin LI qbuffer = (struct QBUFFER *)&phbcmu->message_rbuffer; 1217a1103e04SXin LI } 1218a1103e04SXin LI break; 1219fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 1220fa42a0bfSXin LI qbuffer = (struct QBUFFER *)acb->message_rbuffer; 1221fa42a0bfSXin LI break; 122244f05562SScott Long } 122344f05562SScott Long return(qbuffer); 122444f05562SScott Long } 122544f05562SScott Long /* 122644f05562SScott Long ************************************************************************ 122744f05562SScott Long ************************************************************************ 122844f05562SScott Long */ 122944f05562SScott Long static struct QBUFFER *arcmsr_get_iop_wqbuffer( struct AdapterControlBlock *acb) 123044f05562SScott Long { 123144f05562SScott Long struct QBUFFER *qbuffer = NULL; 123244f05562SScott Long 123344f05562SScott Long switch (acb->adapter_type) { 123444f05562SScott Long case ACB_ADAPTER_TYPE_A: { 123544f05562SScott Long struct HBA_MessageUnit *phbamu = (struct HBA_MessageUnit *)acb->pmu; 123644f05562SScott Long 123744f05562SScott Long qbuffer = (struct QBUFFER *)&phbamu->message_wbuffer; 123844f05562SScott Long } 123944f05562SScott Long break; 124044f05562SScott Long case ACB_ADAPTER_TYPE_B: { 124144f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 124244f05562SScott Long 124344f05562SScott Long qbuffer = (struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_wbuffer; 124444f05562SScott Long } 124544f05562SScott Long break; 1246d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1247d74001adSXin LI struct HBC_MessageUnit *phbcmu = (struct HBC_MessageUnit *)acb->pmu; 1248d74001adSXin LI 1249d74001adSXin LI qbuffer = (struct QBUFFER *)&phbcmu->message_wbuffer; 1250d74001adSXin LI } 1251d74001adSXin LI break; 12527a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 12537a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 12547a7bc959SXin LI 12557a7bc959SXin LI qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_wbuffer; 12567a7bc959SXin LI } 12577a7bc959SXin LI break; 1258a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 1259a1103e04SXin LI struct HBE_MessageUnit *phbcmu = (struct HBE_MessageUnit *)acb->pmu; 1260a1103e04SXin LI 1261a1103e04SXin LI qbuffer = (struct QBUFFER *)&phbcmu->message_wbuffer; 1262a1103e04SXin LI } 1263a1103e04SXin LI break; 1264fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 1265fa42a0bfSXin LI qbuffer = (struct QBUFFER *)acb->message_wbuffer; 1266fa42a0bfSXin LI break; 126744f05562SScott Long } 126844f05562SScott Long return(qbuffer); 126944f05562SScott Long } 127044f05562SScott Long /* 127144f05562SScott Long ************************************************************************** 127244f05562SScott Long ************************************************************************** 127344f05562SScott Long */ 127444f05562SScott Long static void arcmsr_iop_message_read(struct AdapterControlBlock *acb) 127544f05562SScott Long { 127644f05562SScott Long switch (acb->adapter_type) { 127744f05562SScott Long case ACB_ADAPTER_TYPE_A: { 127844f05562SScott Long /* let IOP know data has been read */ 1279d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 128044f05562SScott Long } 128144f05562SScott Long break; 128244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 1283b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 128444f05562SScott Long /* let IOP know data has been read */ 1285b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 128644f05562SScott Long } 128744f05562SScott Long break; 1288d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1289d74001adSXin LI /* let IOP know data has been read */ 1290d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK); 1291d74001adSXin LI } 12927a7bc959SXin LI break; 12937a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 12947a7bc959SXin LI /* let IOP know data has been read */ 12957a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ); 12967a7bc959SXin LI } 12977a7bc959SXin LI break; 1298fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 1299fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 1300a1103e04SXin LI /* let IOP know data has been read */ 1301a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK; 1302a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 1303a1103e04SXin LI } 1304a1103e04SXin LI break; 130544f05562SScott Long } 130644f05562SScott Long } 130744f05562SScott Long /* 130844f05562SScott Long ************************************************************************** 130944f05562SScott Long ************************************************************************** 131044f05562SScott Long */ 131144f05562SScott Long static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) 131244f05562SScott Long { 131344f05562SScott Long switch (acb->adapter_type) { 131444f05562SScott Long case ACB_ADAPTER_TYPE_A: { 131544f05562SScott Long /* 131644f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 131744f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 131844f05562SScott Long */ 1319d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK); 132044f05562SScott Long } 132144f05562SScott Long break; 132244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 1323b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 132444f05562SScott Long /* 132544f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 132644f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 132744f05562SScott Long */ 1328b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_WRITE_OK); 1329d74001adSXin LI } 1330d74001adSXin LI break; 1331d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1332d74001adSXin LI /* 1333d74001adSXin LI ** push inbound doorbell tell iop, driver data write ok 1334d74001adSXin LI ** and wait reply on next hwinterrupt for next Qbuffer post 1335d74001adSXin LI */ 1336d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK); 133744f05562SScott Long } 133844f05562SScott Long break; 13397a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 134044f05562SScott Long /* 13417a7bc959SXin LI ** push inbound doorbell tell iop, driver data write ok 13427a7bc959SXin LI ** and wait reply on next hwinterrupt for next Qbuffer post 1343f1c579b1SScott Long */ 13447a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_IN_READY); 1345f1c579b1SScott Long } 13467a7bc959SXin LI break; 1347fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 1348fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 1349a1103e04SXin LI /* 1350a1103e04SXin LI ** push inbound doorbell tell iop, driver data write ok 1351a1103e04SXin LI ** and wait reply on next hwinterrupt for next Qbuffer post 1352a1103e04SXin LI */ 1353a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_WRITE_OK; 1354a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 1355a1103e04SXin LI } 1356a1103e04SXin LI break; 1357ad6d6297SScott Long } 1358f1c579b1SScott Long } 1359f1c579b1SScott Long /* 1360f1c579b1SScott Long ************************************************************************ 1361f1c579b1SScott Long ************************************************************************ 1362f1c579b1SScott Long */ 136344f05562SScott Long static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb) 1364f1c579b1SScott Long { 1365ad6d6297SScott Long acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 136644f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 136744f05562SScott Long 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 136844f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 1369*2f7e72bdSMustafa Ateş Uzun printf("arcmsr%d: wait 'stop adapter background rebuild' timeout \n" 1370ad6d6297SScott Long , acb->pci_unit); 1371ad6d6297SScott Long } 1372f1c579b1SScott Long } 1373f1c579b1SScott Long /* 1374f1c579b1SScott Long ************************************************************************ 1375f1c579b1SScott Long ************************************************************************ 1376f1c579b1SScott Long */ 137744f05562SScott Long static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb) 137844f05562SScott Long { 1379b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 138044f05562SScott Long acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 1381b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_STOP_BGRB); 138244f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 1383*2f7e72bdSMustafa Ateş Uzun printf( "arcmsr%d: wait 'stop adapter background rebuild' timeout \n" 138444f05562SScott Long , acb->pci_unit); 138544f05562SScott Long } 138644f05562SScott Long } 138744f05562SScott Long /* 138844f05562SScott Long ************************************************************************ 138944f05562SScott Long ************************************************************************ 139044f05562SScott Long */ 1391d74001adSXin LI static void arcmsr_stop_hbc_bgrb(struct AdapterControlBlock *acb) 1392d74001adSXin LI { 1393d74001adSXin LI acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 1394d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 1395d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 1396d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 1397*2f7e72bdSMustafa Ateş Uzun printf("arcmsr%d: wait 'stop adapter background rebuild' timeout \n", acb->pci_unit); 1398d74001adSXin LI } 1399d74001adSXin LI } 1400d74001adSXin LI /* 1401d74001adSXin LI ************************************************************************ 1402d74001adSXin LI ************************************************************************ 1403d74001adSXin LI */ 14047a7bc959SXin LI static void arcmsr_stop_hbd_bgrb(struct AdapterControlBlock *acb) 14057a7bc959SXin LI { 14067a7bc959SXin LI acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 14077a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 14087a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 1409*2f7e72bdSMustafa Ateş Uzun printf("arcmsr%d: wait 'stop adapter background rebuild' timeout \n", acb->pci_unit); 14107a7bc959SXin LI } 14117a7bc959SXin LI } 14127a7bc959SXin LI /* 14137a7bc959SXin LI ************************************************************************ 14147a7bc959SXin LI ************************************************************************ 14157a7bc959SXin LI */ 1416a1103e04SXin LI static void arcmsr_stop_hbe_bgrb(struct AdapterControlBlock *acb) 1417a1103e04SXin LI { 1418a1103e04SXin LI acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 1419a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 1420a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 1421a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 1422a1103e04SXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) { 1423*2f7e72bdSMustafa Ateş Uzun printf("arcmsr%d: wait 'stop adapter background rebuild' timeout \n", acb->pci_unit); 1424a1103e04SXin LI } 1425a1103e04SXin LI } 1426a1103e04SXin LI /* 1427a1103e04SXin LI ************************************************************************ 1428a1103e04SXin LI ************************************************************************ 1429a1103e04SXin LI */ 143044f05562SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) 143144f05562SScott Long { 143244f05562SScott Long switch (acb->adapter_type) { 143344f05562SScott Long case ACB_ADAPTER_TYPE_A: { 143444f05562SScott Long arcmsr_stop_hba_bgrb(acb); 143544f05562SScott Long } 143644f05562SScott Long break; 143744f05562SScott Long case ACB_ADAPTER_TYPE_B: { 143844f05562SScott Long arcmsr_stop_hbb_bgrb(acb); 143944f05562SScott Long } 144044f05562SScott Long break; 1441d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1442d74001adSXin LI arcmsr_stop_hbc_bgrb(acb); 1443d74001adSXin LI } 1444d74001adSXin LI break; 14457a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 14467a7bc959SXin LI arcmsr_stop_hbd_bgrb(acb); 14477a7bc959SXin LI } 14487a7bc959SXin LI break; 1449fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 1450fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 1451a1103e04SXin LI arcmsr_stop_hbe_bgrb(acb); 1452a1103e04SXin LI } 1453a1103e04SXin LI break; 145444f05562SScott Long } 145544f05562SScott Long } 145644f05562SScott Long /* 145744f05562SScott Long ************************************************************************ 145844f05562SScott Long ************************************************************************ 145944f05562SScott Long */ 1460ad6d6297SScott Long static void arcmsr_poll(struct cam_sim *psim) 1461f1c579b1SScott Long { 1462579ec1a5SScott Long struct AdapterControlBlock *acb; 14634e32649fSXin LI int mutex; 1464579ec1a5SScott Long 1465579ec1a5SScott Long acb = (struct AdapterControlBlock *)cam_sim_softc(psim); 14667a7bc959SXin LI mutex = mtx_owned(&acb->isr_lock); 14674e32649fSXin LI if( mutex == 0 ) 14687a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 1469579ec1a5SScott Long arcmsr_interrupt(acb); 14704e32649fSXin LI if( mutex == 0 ) 14717a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 14727a7bc959SXin LI } 14737a7bc959SXin LI /* 14747a7bc959SXin LI ************************************************************************** 14757a7bc959SXin LI ************************************************************************** 14767a7bc959SXin LI */ 147735689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data_D(struct AdapterControlBlock *acb, 147835689395SXin LI struct QBUFFER *prbuffer) { 147935689395SXin LI u_int8_t *pQbuffer; 14804d24901aSPedro F. Giffuni u_int8_t *buf1 = NULL; 14814d24901aSPedro F. Giffuni u_int32_t *iop_data, *buf2 = NULL; 148235689395SXin LI u_int32_t iop_len, data_len; 148335689395SXin LI 148435689395SXin LI iop_data = (u_int32_t *)prbuffer->data; 148535689395SXin LI iop_len = (u_int32_t)prbuffer->data_len; 148635689395SXin LI if ( iop_len > 0 ) 148735689395SXin LI { 148835689395SXin LI buf1 = malloc(128, M_DEVBUF, M_NOWAIT | M_ZERO); 148935689395SXin LI buf2 = (u_int32_t *)buf1; 149035689395SXin LI if( buf1 == NULL) 149135689395SXin LI return (0); 149235689395SXin LI data_len = iop_len; 149335689395SXin LI while(data_len >= 4) 149435689395SXin LI { 149535689395SXin LI *buf2++ = *iop_data++; 149635689395SXin LI data_len -= 4; 149735689395SXin LI } 149835689395SXin LI if(data_len) 149935689395SXin LI *buf2 = *iop_data; 150035689395SXin LI buf2 = (u_int32_t *)buf1; 150135689395SXin LI } 150235689395SXin LI while (iop_len > 0) { 150335689395SXin LI pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex]; 150435689395SXin LI *pQbuffer = *buf1; 150535689395SXin LI acb->rqbuf_lastindex++; 150635689395SXin LI /* if last, index number set it to 0 */ 150735689395SXin LI acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 150835689395SXin LI buf1++; 150935689395SXin LI iop_len--; 151035689395SXin LI } 151135689395SXin LI if(buf2) 151235689395SXin LI free( (u_int8_t *)buf2, M_DEVBUF); 151335689395SXin LI /* let IOP know data has been read */ 151435689395SXin LI arcmsr_iop_message_read(acb); 151535689395SXin LI return (1); 151635689395SXin LI } 151735689395SXin LI /* 151835689395SXin LI ************************************************************************** 151935689395SXin LI ************************************************************************** 152035689395SXin LI */ 152135689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, 15227a7bc959SXin LI struct QBUFFER *prbuffer) { 15237a7bc959SXin LI u_int8_t *pQbuffer; 15247a7bc959SXin LI u_int8_t *iop_data; 15257a7bc959SXin LI u_int32_t iop_len; 15267a7bc959SXin LI 1527fc5ef1caSXin LI if(acb->adapter_type >= ACB_ADAPTER_TYPE_B) { 152835689395SXin LI return(arcmsr_Read_iop_rqbuffer_data_D(acb, prbuffer)); 152935689395SXin LI } 15307a7bc959SXin LI iop_data = (u_int8_t *)prbuffer->data; 15317a7bc959SXin LI iop_len = (u_int32_t)prbuffer->data_len; 15327a7bc959SXin LI while (iop_len > 0) { 15337a7bc959SXin LI pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex]; 15347a7bc959SXin LI *pQbuffer = *iop_data; 15357a7bc959SXin LI acb->rqbuf_lastindex++; 15367a7bc959SXin LI /* if last, index number set it to 0 */ 15377a7bc959SXin LI acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 15387a7bc959SXin LI iop_data++; 15397a7bc959SXin LI iop_len--; 15407a7bc959SXin LI } 15417a7bc959SXin LI /* let IOP know data has been read */ 15427a7bc959SXin LI arcmsr_iop_message_read(acb); 154335689395SXin LI return (1); 1544f1c579b1SScott Long } 1545f1c579b1SScott Long /* 154644f05562SScott Long ************************************************************************** 154744f05562SScott Long ************************************************************************** 15485878cbecSScott Long */ 154944f05562SScott Long static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) 1550f1c579b1SScott Long { 155144f05562SScott Long struct QBUFFER *prbuffer; 15527a7bc959SXin LI int my_empty_len; 1553ad6d6297SScott Long 1554f1c579b1SScott Long /*check this iop data if overflow my rqbuffer*/ 15557a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 155644f05562SScott Long prbuffer = arcmsr_get_iop_rqbuffer(acb); 1557285d85f4S黃清隆 if (acb->rqbuf_lastindex >= acb->rqbuf_firstindex) 1558285d85f4S黃清隆 my_empty_len = (ARCMSR_MAX_QBUFFER - 1) - (acb->rqbuf_lastindex - acb->rqbuf_firstindex); 1559285d85f4S黃清隆 else 1560285d85f4S黃清隆 my_empty_len = acb->rqbuf_firstindex - acb->rqbuf_lastindex - 1; 15617a7bc959SXin LI if(my_empty_len >= prbuffer->data_len) { 156235689395SXin LI if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) 156335689395SXin LI acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 1564ad6d6297SScott Long } else { 1565ad6d6297SScott Long acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 1566f1c579b1SScott Long } 15677a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 15687a7bc959SXin LI } 15697a7bc959SXin LI /* 15707a7bc959SXin LI ********************************************************************** 15717a7bc959SXin LI ********************************************************************** 15727a7bc959SXin LI */ 157335689395SXin LI static void arcmsr_Write_data_2iop_wqbuffer_D(struct AdapterControlBlock *acb) 157435689395SXin LI { 157535689395SXin LI u_int8_t *pQbuffer; 157635689395SXin LI struct QBUFFER *pwbuffer; 15774d24901aSPedro F. Giffuni u_int8_t *buf1 = NULL; 15784d24901aSPedro F. Giffuni u_int32_t *iop_data, *buf2 = NULL; 157935689395SXin LI u_int32_t allxfer_len = 0, data_len; 158035689395SXin LI 158135689395SXin LI if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) { 158235689395SXin LI buf1 = malloc(128, M_DEVBUF, M_NOWAIT | M_ZERO); 158335689395SXin LI buf2 = (u_int32_t *)buf1; 158435689395SXin LI if( buf1 == NULL) 158535689395SXin LI return; 158635689395SXin LI 158735689395SXin LI acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 158835689395SXin LI pwbuffer = arcmsr_get_iop_wqbuffer(acb); 158935689395SXin LI iop_data = (u_int32_t *)pwbuffer->data; 159035689395SXin LI while((acb->wqbuf_firstindex != acb->wqbuf_lastindex) 159135689395SXin LI && (allxfer_len < 124)) { 159235689395SXin LI pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex]; 159335689395SXin LI *buf1 = *pQbuffer; 159435689395SXin LI acb->wqbuf_firstindex++; 159535689395SXin LI acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 159635689395SXin LI buf1++; 159735689395SXin LI allxfer_len++; 159835689395SXin LI } 159935689395SXin LI pwbuffer->data_len = allxfer_len; 160035689395SXin LI data_len = allxfer_len; 160135689395SXin LI buf1 = (u_int8_t *)buf2; 160235689395SXin LI while(data_len >= 4) 160335689395SXin LI { 160435689395SXin LI *iop_data++ = *buf2++; 160535689395SXin LI data_len -= 4; 160635689395SXin LI } 160735689395SXin LI if(data_len) 160835689395SXin LI *iop_data = *buf2; 160935689395SXin LI free( buf1, M_DEVBUF); 161035689395SXin LI arcmsr_iop_message_wrote(acb); 161135689395SXin LI } 161235689395SXin LI } 161335689395SXin LI /* 161435689395SXin LI ********************************************************************** 161535689395SXin LI ********************************************************************** 161635689395SXin LI */ 16177a7bc959SXin LI static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb) 16187a7bc959SXin LI { 16197a7bc959SXin LI u_int8_t *pQbuffer; 16207a7bc959SXin LI struct QBUFFER *pwbuffer; 16217a7bc959SXin LI u_int8_t *iop_data; 16227a7bc959SXin LI int32_t allxfer_len=0; 16237a7bc959SXin LI 1624fc5ef1caSXin LI if(acb->adapter_type >= ACB_ADAPTER_TYPE_B) { 162535689395SXin LI arcmsr_Write_data_2iop_wqbuffer_D(acb); 162635689395SXin LI return; 162735689395SXin LI } 16287a7bc959SXin LI if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) { 16297a7bc959SXin LI acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 16307a7bc959SXin LI pwbuffer = arcmsr_get_iop_wqbuffer(acb); 16317a7bc959SXin LI iop_data = (u_int8_t *)pwbuffer->data; 16327a7bc959SXin LI while((acb->wqbuf_firstindex != acb->wqbuf_lastindex) 16337a7bc959SXin LI && (allxfer_len < 124)) { 16347a7bc959SXin LI pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex]; 16357a7bc959SXin LI *iop_data = *pQbuffer; 16367a7bc959SXin LI acb->wqbuf_firstindex++; 16377a7bc959SXin LI acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 16387a7bc959SXin LI iop_data++; 16397a7bc959SXin LI allxfer_len++; 16407a7bc959SXin LI } 16417a7bc959SXin LI pwbuffer->data_len = allxfer_len; 16427a7bc959SXin LI arcmsr_iop_message_wrote(acb); 16437a7bc959SXin LI } 1644f1c579b1SScott Long } 1645f1c579b1SScott Long /* 164644f05562SScott Long ************************************************************************** 164744f05562SScott Long ************************************************************************** 164844f05562SScott Long */ 164944f05562SScott Long static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) 165044f05562SScott Long { 16517a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 165244f05562SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READ; 165344f05562SScott Long /* 165444f05562SScott Long ***************************************************************** 165544f05562SScott Long ** check if there are any mail packages from user space program 165644f05562SScott Long ** in my post bag, now is the time to send them into Areca's firmware 165744f05562SScott Long ***************************************************************** 1658f1c579b1SScott Long */ 1659ad6d6297SScott Long if(acb->wqbuf_firstindex != acb->wqbuf_lastindex) { 16607a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 1661f1c579b1SScott Long } 1662ad6d6297SScott Long if(acb->wqbuf_firstindex == acb->wqbuf_lastindex) { 1663ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; 1664f1c579b1SScott Long } 16657a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1666f1c579b1SScott Long } 16677a7bc959SXin LI /* 16687a7bc959SXin LI ************************************************************************** 16697a7bc959SXin LI ************************************************************************** 16707a7bc959SXin LI */ 1671d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb) 1672d74001adSXin LI { 1673d74001adSXin LI /* 1674d74001adSXin LI if (ccb->ccb_h.status != CAM_REQ_CMP) 16757a7bc959SXin LI printf("arcmsr_rescanLun_cb: Rescan Target=%x, lun=%x," 16767a7bc959SXin LI "failure status=%x\n", ccb->ccb_h.target_id, 16777a7bc959SXin LI ccb->ccb_h.target_lun, ccb->ccb_h.status); 1678d74001adSXin LI else 1679d74001adSXin LI printf("arcmsr_rescanLun_cb: Rescan lun successfully!\n"); 1680d74001adSXin LI */ 1681d74001adSXin LI xpt_free_path(ccb->ccb_h.path); 1682d74001adSXin LI xpt_free_ccb(ccb); 1683d74001adSXin LI } 1684d74001adSXin LI 1685d74001adSXin LI static void arcmsr_rescan_lun(struct AdapterControlBlock *acb, int target, int lun) 1686d74001adSXin LI { 1687d74001adSXin LI struct cam_path *path; 1688d74001adSXin LI union ccb *ccb; 1689d74001adSXin LI 1690d74001adSXin LI if ((ccb = (union ccb *)xpt_alloc_ccb_nowait()) == NULL) 1691d74001adSXin LI return; 1692abfdbca9SXin LI if (xpt_create_path(&path, NULL, cam_sim_path(acb->psim), target, lun) != CAM_REQ_CMP) 1693d74001adSXin LI { 1694d74001adSXin LI xpt_free_ccb(ccb); 1695d74001adSXin LI return; 1696d74001adSXin LI } 1697d74001adSXin LI /* printf("arcmsr_rescan_lun: Rescan Target=%x, Lun=%x\n", target, lun); */ 1698d74001adSXin LI xpt_setup_ccb(&ccb->ccb_h, path, 5); 1699d74001adSXin LI ccb->ccb_h.func_code = XPT_SCAN_LUN; 1700d74001adSXin LI ccb->ccb_h.cbfcnp = arcmsr_rescanLun_cb; 1701d74001adSXin LI ccb->crcn.flags = CAM_FLAG_NONE; 1702d74001adSXin LI xpt_action(ccb); 1703d74001adSXin LI } 1704d74001adSXin LI 1705d74001adSXin LI static void arcmsr_abort_dr_ccbs(struct AdapterControlBlock *acb, int target, int lun) 1706d74001adSXin LI { 1707d74001adSXin LI struct CommandControlBlock *srb; 1708d74001adSXin LI u_int32_t intmask_org; 1709d74001adSXin LI int i; 1710d74001adSXin LI 1711d74001adSXin LI /* disable all outbound interrupts */ 1712d74001adSXin LI intmask_org = arcmsr_disable_allintr(acb); 1713d74001adSXin LI for (i = 0; i < ARCMSR_MAX_FREESRB_NUM; i++) 1714d74001adSXin LI { 1715d74001adSXin LI srb = acb->psrb_pool[i]; 171622f2616bSXin LI if (srb->srb_state == ARCMSR_SRB_START) 1717d74001adSXin LI { 1718d74001adSXin LI if((target == srb->pccb->ccb_h.target_id) && (lun == srb->pccb->ccb_h.target_lun)) 1719d74001adSXin LI { 172022f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 1721d74001adSXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 1722d74001adSXin LI arcmsr_srb_complete(srb, 1); 172322f2616bSXin LI printf("arcmsr%d: abort scsi id %d lun %d srb=%p \n", acb->pci_unit, target, lun, srb); 1724d74001adSXin LI } 1725d74001adSXin LI } 1726d74001adSXin LI } 1727d74001adSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 1728d74001adSXin LI arcmsr_enable_allintr(acb, intmask_org); 1729d74001adSXin LI } 1730d74001adSXin LI /* 1731d74001adSXin LI ************************************************************************** 1732d74001adSXin LI ************************************************************************** 1733d74001adSXin LI */ 1734d74001adSXin LI static void arcmsr_dr_handle(struct AdapterControlBlock *acb) { 1735d74001adSXin LI u_int32_t devicemap; 1736d74001adSXin LI u_int32_t target, lun; 1737d74001adSXin LI u_int32_t deviceMapCurrent[4]={0}; 1738d74001adSXin LI u_int8_t *pDevMap; 1739d74001adSXin LI 1740d74001adSXin LI switch (acb->adapter_type) { 1741d74001adSXin LI case ACB_ADAPTER_TYPE_A: 1742d74001adSXin LI devicemap = offsetof(struct HBA_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1743d74001adSXin LI for (target = 0; target < 4; target++) 1744d74001adSXin LI { 1745d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1746d74001adSXin LI devicemap += 4; 1747d74001adSXin LI } 1748d74001adSXin LI break; 1749d74001adSXin LI 1750d74001adSXin LI case ACB_ADAPTER_TYPE_B: 1751d74001adSXin LI devicemap = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1752d74001adSXin LI for (target = 0; target < 4; target++) 1753d74001adSXin LI { 1754d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[1], acb->bhandle[1], devicemap); 1755d74001adSXin LI devicemap += 4; 1756d74001adSXin LI } 1757d74001adSXin LI break; 1758d74001adSXin LI 1759d74001adSXin LI case ACB_ADAPTER_TYPE_C: 1760d74001adSXin LI devicemap = offsetof(struct HBC_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1761d74001adSXin LI for (target = 0; target < 4; target++) 1762d74001adSXin LI { 1763d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1764d74001adSXin LI devicemap += 4; 1765d74001adSXin LI } 1766d74001adSXin LI break; 17677a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 17687a7bc959SXin LI devicemap = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 17697a7bc959SXin LI for (target = 0; target < 4; target++) 17707a7bc959SXin LI { 17717a7bc959SXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 17727a7bc959SXin LI devicemap += 4; 17737a7bc959SXin LI } 17747a7bc959SXin LI break; 1775a1103e04SXin LI case ACB_ADAPTER_TYPE_E: 1776a1103e04SXin LI devicemap = offsetof(struct HBE_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1777a1103e04SXin LI for (target = 0; target < 4; target++) 1778a1103e04SXin LI { 1779a1103e04SXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1780a1103e04SXin LI devicemap += 4; 1781a1103e04SXin LI } 1782a1103e04SXin LI break; 1783fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 1784fa42a0bfSXin LI devicemap = ARCMSR_FW_DEVMAP_OFFSET; 1785fa42a0bfSXin LI for (target = 0; target < 4; target++) 1786fa42a0bfSXin LI { 1787fa42a0bfSXin LI deviceMapCurrent[target] = acb->msgcode_rwbuffer[devicemap]; 1788fa42a0bfSXin LI devicemap += 1; 1789fa42a0bfSXin LI } 1790fa42a0bfSXin LI break; 1791d74001adSXin LI } 1792dac36688SXin LI 1793d74001adSXin LI if(acb->acb_flags & ACB_F_BUS_HANG_ON) 1794d74001adSXin LI { 1795d74001adSXin LI acb->acb_flags &= ~ACB_F_BUS_HANG_ON; 1796d74001adSXin LI } 1797d74001adSXin LI /* 1798d74001adSXin LI ** adapter posted CONFIG message 1799d74001adSXin LI ** copy the new map, note if there are differences with the current map 1800d74001adSXin LI */ 1801d74001adSXin LI pDevMap = (u_int8_t *)&deviceMapCurrent[0]; 1802d74001adSXin LI for (target = 0; target < ARCMSR_MAX_TARGETID - 1; target++) 1803d74001adSXin LI { 1804d74001adSXin LI if (*pDevMap != acb->device_map[target]) 1805d74001adSXin LI { 1806d74001adSXin LI u_int8_t difference, bit_check; 1807d74001adSXin LI 1808d74001adSXin LI difference = *pDevMap ^ acb->device_map[target]; 1809d74001adSXin LI for(lun=0; lun < ARCMSR_MAX_TARGETLUN; lun++) 1810d74001adSXin LI { 1811d74001adSXin LI bit_check = (1 << lun); /*check bit from 0....31*/ 1812d74001adSXin LI if(difference & bit_check) 1813d74001adSXin LI { 1814d74001adSXin LI if(acb->device_map[target] & bit_check) 1815d74001adSXin LI {/* unit departed */ 1816d74001adSXin LI printf("arcmsr_dr_handle: Target=%x, lun=%x, GONE!!!\n",target,lun); 1817d74001adSXin LI arcmsr_abort_dr_ccbs(acb, target, lun); 1818d74001adSXin LI arcmsr_rescan_lun(acb, target, lun); 1819d74001adSXin LI acb->devstate[target][lun] = ARECA_RAID_GONE; 1820d74001adSXin LI } 1821d74001adSXin LI else 1822d74001adSXin LI {/* unit arrived */ 182322f2616bSXin LI printf("arcmsr_dr_handle: Target=%x, lun=%x, Plug-IN!!!\n",target,lun); 1824d74001adSXin LI arcmsr_rescan_lun(acb, target, lun); 1825d74001adSXin LI acb->devstate[target][lun] = ARECA_RAID_GOOD; 1826d74001adSXin LI } 1827d74001adSXin LI } 1828d74001adSXin LI } 1829d74001adSXin LI /* printf("arcmsr_dr_handle: acb->device_map[%x]=0x%x, deviceMapCurrent[%x]=%x\n",target,acb->device_map[target],target,*pDevMap); */ 1830d74001adSXin LI acb->device_map[target] = *pDevMap; 1831d74001adSXin LI } 1832d74001adSXin LI pDevMap++; 1833d74001adSXin LI } 1834d74001adSXin LI } 1835d74001adSXin LI /* 1836d74001adSXin LI ************************************************************************** 1837d74001adSXin LI ************************************************************************** 1838d74001adSXin LI */ 1839d74001adSXin LI static void arcmsr_hba_message_isr(struct AdapterControlBlock *acb) { 1840d74001adSXin LI u_int32_t outbound_message; 1841d74001adSXin LI 1842d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT); 1843d74001adSXin LI outbound_message = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[0]); 1844d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1845d74001adSXin LI arcmsr_dr_handle( acb ); 1846d74001adSXin LI } 1847d74001adSXin LI /* 1848d74001adSXin LI ************************************************************************** 1849d74001adSXin LI ************************************************************************** 1850d74001adSXin LI */ 1851d74001adSXin LI static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) { 1852d74001adSXin LI u_int32_t outbound_message; 1853b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 1854d74001adSXin LI 1855d74001adSXin LI /* clear interrupts */ 1856b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN); 1857d74001adSXin LI outbound_message = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0]); 1858d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1859d74001adSXin LI arcmsr_dr_handle( acb ); 1860d74001adSXin LI } 1861d74001adSXin LI /* 1862d74001adSXin LI ************************************************************************** 1863d74001adSXin LI ************************************************************************** 1864d74001adSXin LI */ 1865d74001adSXin LI static void arcmsr_hbc_message_isr(struct AdapterControlBlock *acb) { 1866d74001adSXin LI u_int32_t outbound_message; 1867d74001adSXin LI 1868d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR); 1869d74001adSXin LI outbound_message = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[0]); 1870d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1871d74001adSXin LI arcmsr_dr_handle( acb ); 1872d74001adSXin LI } 187344f05562SScott Long /* 187444f05562SScott Long ************************************************************************** 187544f05562SScott Long ************************************************************************** 187644f05562SScott Long */ 18777a7bc959SXin LI static void arcmsr_hbd_message_isr(struct AdapterControlBlock *acb) { 18787a7bc959SXin LI u_int32_t outbound_message; 18797a7bc959SXin LI 18807a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR); 18817a7bc959SXin LI outbound_message = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[0]); 18827a7bc959SXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 18837a7bc959SXin LI arcmsr_dr_handle( acb ); 18847a7bc959SXin LI } 18857a7bc959SXin LI /* 18867a7bc959SXin LI ************************************************************************** 18877a7bc959SXin LI ************************************************************************** 18887a7bc959SXin LI */ 1889a1103e04SXin LI static void arcmsr_hbe_message_isr(struct AdapterControlBlock *acb) { 1890a1103e04SXin LI u_int32_t outbound_message; 1891a1103e04SXin LI 1892a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); 18935842073aSXin LI if (acb->adapter_type == ACB_ADAPTER_TYPE_E) 1894a1103e04SXin LI outbound_message = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[0]); 18955842073aSXin LI else 18965842073aSXin LI outbound_message = acb->msgcode_rwbuffer[0]; 1897a1103e04SXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1898a1103e04SXin LI arcmsr_dr_handle( acb ); 1899a1103e04SXin LI } 1900a1103e04SXin LI /* 1901a1103e04SXin LI ************************************************************************** 1902a1103e04SXin LI ************************************************************************** 1903a1103e04SXin LI */ 190444f05562SScott Long static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) 190544f05562SScott Long { 1906224a78aeSXin LI u_int32_t doorbell_status; 190744f05562SScott Long 190844f05562SScott Long /* 190944f05562SScott Long ******************************************************************* 191044f05562SScott Long ** Maybe here we need to check wrqbuffer_lock is lock or not 191144f05562SScott Long ** DOORBELL: din! don! 191244f05562SScott Long ** check if there are any mail need to pack from firmware 191344f05562SScott Long ******************************************************************* 191444f05562SScott Long */ 1915224a78aeSXin LI doorbell_status = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell); 1916224a78aeSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */ 1917224a78aeSXin LI if(doorbell_status & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { 191844f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 1919ad6d6297SScott Long } 1920224a78aeSXin LI if(doorbell_status & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { 192144f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 192244f05562SScott Long } 192344f05562SScott Long } 192444f05562SScott Long /* 192544f05562SScott Long ************************************************************************** 192644f05562SScott Long ************************************************************************** 192744f05562SScott Long */ 1928d74001adSXin LI static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb) 1929d74001adSXin LI { 1930224a78aeSXin LI u_int32_t doorbell_status; 1931d74001adSXin LI 1932d74001adSXin LI /* 1933d74001adSXin LI ******************************************************************* 1934d74001adSXin LI ** Maybe here we need to check wrqbuffer_lock is lock or not 1935d74001adSXin LI ** DOORBELL: din! don! 1936d74001adSXin LI ** check if there are any mail need to pack from firmware 1937d74001adSXin LI ******************************************************************* 1938d74001adSXin LI */ 1939224a78aeSXin LI doorbell_status = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); 1940224a78aeSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, doorbell_status); /* clear doorbell interrupt */ 1941224a78aeSXin LI if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) { 1942d74001adSXin LI arcmsr_iop2drv_data_wrote_handle(acb); 1943d74001adSXin LI } 1944224a78aeSXin LI if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) { 1945d74001adSXin LI arcmsr_iop2drv_data_read_handle(acb); 1946d74001adSXin LI } 1947224a78aeSXin LI if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { 1948d74001adSXin LI arcmsr_hbc_message_isr(acb); /* messenger of "driver to iop commands" */ 1949d74001adSXin LI } 1950d74001adSXin LI } 1951d74001adSXin LI /* 1952d74001adSXin LI ************************************************************************** 1953d74001adSXin LI ************************************************************************** 1954d74001adSXin LI */ 19557a7bc959SXin LI static void arcmsr_hbd_doorbell_isr(struct AdapterControlBlock *acb) 19567a7bc959SXin LI { 1957224a78aeSXin LI u_int32_t doorbell_status; 19587a7bc959SXin LI 19597a7bc959SXin LI /* 19607a7bc959SXin LI ******************************************************************* 19617a7bc959SXin LI ** Maybe here we need to check wrqbuffer_lock is lock or not 19627a7bc959SXin LI ** DOORBELL: din! don! 19637a7bc959SXin LI ** check if there are any mail need to pack from firmware 19647a7bc959SXin LI ******************************************************************* 19657a7bc959SXin LI */ 1966224a78aeSXin LI doorbell_status = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE; 1967224a78aeSXin LI if(doorbell_status) 1968224a78aeSXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */ 1969224a78aeSXin LI while( doorbell_status & ARCMSR_HBDMU_F0_DOORBELL_CAUSE ) { 1970224a78aeSXin LI if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_DATA_WRITE_OK) { 19717a7bc959SXin LI arcmsr_iop2drv_data_wrote_handle(acb); 19727a7bc959SXin LI } 1973224a78aeSXin LI if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_DATA_READ_OK) { 19747a7bc959SXin LI arcmsr_iop2drv_data_read_handle(acb); 19757a7bc959SXin LI } 1976224a78aeSXin LI if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) { 19777a7bc959SXin LI arcmsr_hbd_message_isr(acb); /* messenger of "driver to iop commands" */ 19787a7bc959SXin LI } 1979224a78aeSXin LI doorbell_status = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE; 1980224a78aeSXin LI if(doorbell_status) 1981224a78aeSXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */ 19827a7bc959SXin LI } 19837a7bc959SXin LI } 19847a7bc959SXin LI /* 19857a7bc959SXin LI ************************************************************************** 19867a7bc959SXin LI ************************************************************************** 19877a7bc959SXin LI */ 1988a1103e04SXin LI static void arcmsr_hbe_doorbell_isr(struct AdapterControlBlock *acb) 1989a1103e04SXin LI { 1990a1103e04SXin LI u_int32_t doorbell_status, in_doorbell; 1991a1103e04SXin LI 1992a1103e04SXin LI /* 1993a1103e04SXin LI ******************************************************************* 1994a1103e04SXin LI ** Maybe here we need to check wrqbuffer_lock is lock or not 1995a1103e04SXin LI ** DOORBELL: din! don! 1996a1103e04SXin LI ** check if there are any mail need to pack from firmware 1997a1103e04SXin LI ******************************************************************* 1998a1103e04SXin LI */ 1999a1103e04SXin LI in_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell); 2000a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /* clear doorbell interrupt */ 2001a1103e04SXin LI doorbell_status = in_doorbell ^ acb->in_doorbell; 2002a1103e04SXin LI if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_WRITE_OK) { 2003a1103e04SXin LI arcmsr_iop2drv_data_wrote_handle(acb); 2004a1103e04SXin LI } 2005a1103e04SXin LI if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_READ_OK) { 2006a1103e04SXin LI arcmsr_iop2drv_data_read_handle(acb); 2007a1103e04SXin LI } 2008a1103e04SXin LI if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) { 2009a1103e04SXin LI arcmsr_hbe_message_isr(acb); /* messenger of "driver to iop commands" */ 2010a1103e04SXin LI } 2011a1103e04SXin LI acb->in_doorbell = in_doorbell; 2012a1103e04SXin LI } 2013a1103e04SXin LI /* 2014a1103e04SXin LI ************************************************************************** 2015a1103e04SXin LI ************************************************************************** 2016a1103e04SXin LI */ 20176964b77eS黃清隆 static void arcmsr_hbf_doorbell_isr(struct AdapterControlBlock *acb) 20186964b77eS黃清隆 { 20196964b77eS黃清隆 u_int32_t doorbell_status, in_doorbell; 20206964b77eS黃清隆 20216964b77eS黃清隆 /* 20226964b77eS黃清隆 ******************************************************************* 20236964b77eS黃清隆 ** Maybe here we need to check wrqbuffer_lock is lock or not 20246964b77eS黃清隆 ** DOORBELL: din! don! 20256964b77eS黃清隆 ** check if there are any mail need to pack from firmware 20266964b77eS黃清隆 ******************************************************************* 20276964b77eS黃清隆 */ 20286964b77eS黃清隆 while(1) { 20296964b77eS黃清隆 in_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell); 20306964b77eS黃清隆 if ((in_doorbell != 0) && (in_doorbell != 0xFFFFFFFF)) 20316964b77eS黃清隆 break; 20326964b77eS黃清隆 } 20336964b77eS黃清隆 CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /* clear doorbell interrupt */ 20346964b77eS黃清隆 doorbell_status = in_doorbell ^ acb->in_doorbell; 20356964b77eS黃清隆 if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_WRITE_OK) { 20366964b77eS黃清隆 arcmsr_iop2drv_data_wrote_handle(acb); 20376964b77eS黃清隆 } 20386964b77eS黃清隆 if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_READ_OK) { 20396964b77eS黃清隆 arcmsr_iop2drv_data_read_handle(acb); 20406964b77eS黃清隆 } 20416964b77eS黃清隆 if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) { 20426964b77eS黃清隆 arcmsr_hbe_message_isr(acb); /* messenger of "driver to iop commands" */ 20436964b77eS黃清隆 } 20446964b77eS黃清隆 acb->in_doorbell = in_doorbell; 20456964b77eS黃清隆 } 20466964b77eS黃清隆 /* 20476964b77eS黃清隆 ************************************************************************** 20486964b77eS黃清隆 ************************************************************************** 20496964b77eS黃清隆 */ 205044f05562SScott Long static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb) 205144f05562SScott Long { 205244f05562SScott Long u_int32_t flag_srb; 2053d74001adSXin LI u_int16_t error; 205444f05562SScott Long 2055f1c579b1SScott Long /* 2056f1c579b1SScott Long ***************************************************************************** 2057f1c579b1SScott Long ** areca cdb command done 2058f1c579b1SScott Long ***************************************************************************** 2059f1c579b1SScott Long */ 206044f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 206144f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 206244f05562SScott Long while((flag_srb = CHIP_REG_READ32(HBA_MessageUnit, 206344f05562SScott Long 0, outbound_queueport)) != 0xFFFFFFFF) { 2064f1c579b1SScott Long /* check if command done with no error*/ 2065d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0) ? TRUE : FALSE; 2066d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 206744f05562SScott Long } /*drain reply FIFO*/ 2068f1c579b1SScott Long } 206944f05562SScott Long /* 207044f05562SScott Long ************************************************************************** 207144f05562SScott Long ************************************************************************** 207244f05562SScott Long */ 207344f05562SScott Long static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) 207444f05562SScott Long { 207544f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 207644f05562SScott Long u_int32_t flag_srb; 207744f05562SScott Long int index; 2078d74001adSXin LI u_int16_t error; 207944f05562SScott Long 208044f05562SScott Long /* 208144f05562SScott Long ***************************************************************************** 208244f05562SScott Long ** areca cdb command done 208344f05562SScott Long ***************************************************************************** 208444f05562SScott Long */ 208544f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 208644f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 208744f05562SScott Long index = phbbmu->doneq_index; 208844f05562SScott Long while((flag_srb = phbbmu->done_qbuffer[index]) != 0) { 208944f05562SScott Long phbbmu->done_qbuffer[index] = 0; 209044f05562SScott Long index++; 209144f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 209244f05562SScott Long phbbmu->doneq_index = index; 209344f05562SScott Long /* check if command done with no error*/ 2094d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 2095d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 2096d74001adSXin LI } /*drain reply FIFO*/ 2097d74001adSXin LI } 2098d74001adSXin LI /* 2099d74001adSXin LI ************************************************************************** 2100d74001adSXin LI ************************************************************************** 2101d74001adSXin LI */ 2102d74001adSXin LI static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb) 2103d74001adSXin LI { 2104d74001adSXin LI u_int32_t flag_srb,throttling = 0; 2105d74001adSXin LI u_int16_t error; 2106d74001adSXin LI 2107d74001adSXin LI /* 2108d74001adSXin LI ***************************************************************************** 2109d74001adSXin LI ** areca cdb command done 2110d74001adSXin LI ***************************************************************************** 2111d74001adSXin LI */ 2112d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2113224a78aeSXin LI do { 2114d74001adSXin LI flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 2115b23a1998SXin LI if (flag_srb == 0xFFFFFFFF) 2116b23a1998SXin LI break; 2117d74001adSXin LI /* check if command done with no error*/ 2118d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; 2119d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 2120abfdbca9SXin LI throttling++; 2121d74001adSXin LI if(throttling == ARCMSR_HBC_ISR_THROTTLING_LEVEL) { 2122d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING); 2123abfdbca9SXin LI throttling = 0; 2124d74001adSXin LI } 2125224a78aeSXin LI } while(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR); 2126f1c579b1SScott Long } 212744f05562SScott Long /* 212844f05562SScott Long ********************************************************************** 21297a7bc959SXin LI ** 21307a7bc959SXin LI ********************************************************************** 21317a7bc959SXin LI */ 21327a7bc959SXin LI static uint16_t arcmsr_get_doneq_index(struct HBD_MessageUnit0 *phbdmu) 21337a7bc959SXin LI { 21347a7bc959SXin LI uint16_t doneq_index, index_stripped; 21357a7bc959SXin LI 21367a7bc959SXin LI doneq_index = phbdmu->doneq_index; 21377a7bc959SXin LI if (doneq_index & 0x4000) { 21387a7bc959SXin LI index_stripped = doneq_index & 0xFF; 21397a7bc959SXin LI index_stripped += 1; 21407a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 21417a7bc959SXin LI phbdmu->doneq_index = index_stripped ? 21427a7bc959SXin LI (index_stripped | 0x4000) : index_stripped; 21437a7bc959SXin LI } else { 21447a7bc959SXin LI index_stripped = doneq_index; 21457a7bc959SXin LI index_stripped += 1; 21467a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 21477a7bc959SXin LI phbdmu->doneq_index = index_stripped ? 21487a7bc959SXin LI index_stripped : (index_stripped | 0x4000); 21497a7bc959SXin LI } 21507a7bc959SXin LI return (phbdmu->doneq_index); 21517a7bc959SXin LI } 21527a7bc959SXin LI /* 21537a7bc959SXin LI ************************************************************************** 21547a7bc959SXin LI ************************************************************************** 21557a7bc959SXin LI */ 21567a7bc959SXin LI static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb) 21577a7bc959SXin LI { 21587a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 21597a7bc959SXin LI u_int32_t outbound_write_pointer; 21607a7bc959SXin LI u_int32_t addressLow; 21617a7bc959SXin LI uint16_t doneq_index; 21627a7bc959SXin LI u_int16_t error; 21637a7bc959SXin LI /* 21647a7bc959SXin LI ***************************************************************************** 21657a7bc959SXin LI ** areca cdb command done 21667a7bc959SXin LI ***************************************************************************** 21677a7bc959SXin LI */ 21687a7bc959SXin LI if((CHIP_REG_READ32(HBD_MessageUnit, 0, outboundlist_interrupt_cause) & 21697a7bc959SXin LI ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT) == 0) 21707a7bc959SXin LI return; 21717a7bc959SXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 21727a7bc959SXin LI BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 21737a7bc959SXin LI outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow; 21747a7bc959SXin LI doneq_index = phbdmu->doneq_index; 21757a7bc959SXin LI while ((doneq_index & 0xFF) != (outbound_write_pointer & 0xFF)) { 21767a7bc959SXin LI doneq_index = arcmsr_get_doneq_index(phbdmu); 21777a7bc959SXin LI addressLow = phbdmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow; 21787a7bc959SXin LI error = (addressLow & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 21797a7bc959SXin LI arcmsr_drain_donequeue(acb, addressLow, error); /*Check if command done with no error */ 21807a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_read_pointer, doneq_index); 21817a7bc959SXin LI outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow; 21827a7bc959SXin LI } 21837a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_interrupt_cause, ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT_CLEAR); 21847a7bc959SXin LI CHIP_REG_READ32(HBD_MessageUnit, 0, outboundlist_interrupt_cause); /*Dummy ioread32 to force pci flush */ 21857a7bc959SXin LI } 21867a7bc959SXin LI /* 2187a1103e04SXin LI ************************************************************************** 2188a1103e04SXin LI ************************************************************************** 2189a1103e04SXin LI */ 2190a1103e04SXin LI static void arcmsr_hbe_postqueue_isr(struct AdapterControlBlock *acb) 2191a1103e04SXin LI { 2192a1103e04SXin LI u_int16_t error; 2193a1103e04SXin LI uint32_t doneq_index; 2194a1103e04SXin LI uint16_t cmdSMID; 2195a1103e04SXin LI 2196a1103e04SXin LI /* 2197a1103e04SXin LI ***************************************************************************** 2198a1103e04SXin LI ** areca cdb command done 2199a1103e04SXin LI ***************************************************************************** 2200a1103e04SXin LI */ 2201a1103e04SXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2202a1103e04SXin LI doneq_index = acb->doneq_index; 2203a1103e04SXin LI while ((CHIP_REG_READ32(HBE_MessageUnit, 0, reply_post_producer_index) & 0xFFFF) != doneq_index) { 2204a1103e04SXin LI cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID; 2205a1103e04SXin LI error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 2206a1103e04SXin LI arcmsr_drain_donequeue(acb, (u_int32_t)cmdSMID, error); 2207a1103e04SXin LI doneq_index++; 2208a1103e04SXin LI if (doneq_index >= acb->completionQ_entry) 2209a1103e04SXin LI doneq_index = 0; 2210a1103e04SXin LI } 2211a1103e04SXin LI acb->doneq_index = doneq_index; 2212a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, reply_post_consumer_index, doneq_index); 2213a1103e04SXin LI } 2214fa42a0bfSXin LI 2215fa42a0bfSXin LI static void arcmsr_hbf_postqueue_isr(struct AdapterControlBlock *acb) 2216fa42a0bfSXin LI { 2217fa42a0bfSXin LI uint16_t error; 2218fa42a0bfSXin LI uint32_t doneq_index; 2219fa42a0bfSXin LI uint16_t cmdSMID; 2220fa42a0bfSXin LI 2221fa42a0bfSXin LI /* 2222fa42a0bfSXin LI ***************************************************************************** 2223fa42a0bfSXin LI ** areca cdb command done 2224fa42a0bfSXin LI ***************************************************************************** 2225fa42a0bfSXin LI */ 2226fa42a0bfSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2227fa42a0bfSXin LI doneq_index = acb->doneq_index; 2228fa42a0bfSXin LI while (1) { 2229fa42a0bfSXin LI cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID; 2230fa42a0bfSXin LI if (cmdSMID == 0xffff) 2231fa42a0bfSXin LI break; 2232fa42a0bfSXin LI error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 2233fa42a0bfSXin LI arcmsr_drain_donequeue(acb, (u_int32_t)cmdSMID, error); 2234fa42a0bfSXin LI acb->pCompletionQ[doneq_index].cmdSMID = 0xffff; 2235fa42a0bfSXin LI doneq_index++; 2236fa42a0bfSXin LI if (doneq_index >= acb->completionQ_entry) 2237fa42a0bfSXin LI doneq_index = 0; 2238fa42a0bfSXin LI } 2239fa42a0bfSXin LI acb->doneq_index = doneq_index; 2240fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, reply_post_consumer_index, doneq_index); 2241fa42a0bfSXin LI } 2242fa42a0bfSXin LI 2243a1103e04SXin LI /* 22447a7bc959SXin LI ********************************************************************** 224544f05562SScott Long ********************************************************************** 224644f05562SScott Long */ 224744f05562SScott Long static void arcmsr_handle_hba_isr( struct AdapterControlBlock *acb) 224844f05562SScott Long { 2249dac36688SXin LI u_int32_t outbound_intStatus; 225044f05562SScott Long /* 225144f05562SScott Long ********************************************* 225244f05562SScott Long ** check outbound intstatus 225344f05562SScott Long ********************************************* 225444f05562SScott Long */ 2255dac36688SXin LI outbound_intStatus = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 2256dac36688SXin LI if(!outbound_intStatus) { 225744f05562SScott Long /*it must be share irq*/ 225844f05562SScott Long return; 2259f1c579b1SScott Long } 2260dac36688SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intStatus); /*clear interrupt*/ 226144f05562SScott Long /* MU doorbell interrupts*/ 2262dac36688SXin LI if(outbound_intStatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) { 226344f05562SScott Long arcmsr_hba_doorbell_isr(acb); 2264f1c579b1SScott Long } 226544f05562SScott Long /* MU post queue interrupts*/ 2266dac36688SXin LI if(outbound_intStatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { 226744f05562SScott Long arcmsr_hba_postqueue_isr(acb); 226844f05562SScott Long } 2269dac36688SXin LI if(outbound_intStatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { 2270d74001adSXin LI arcmsr_hba_message_isr(acb); 2271d74001adSXin LI } 227244f05562SScott Long } 227344f05562SScott Long /* 227444f05562SScott Long ********************************************************************** 227544f05562SScott Long ********************************************************************** 227644f05562SScott Long */ 227744f05562SScott Long static void arcmsr_handle_hbb_isr( struct AdapterControlBlock *acb) 227844f05562SScott Long { 227944f05562SScott Long u_int32_t outbound_doorbell; 2280b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 228144f05562SScott Long /* 228244f05562SScott Long ********************************************* 228344f05562SScott Long ** check outbound intstatus 228444f05562SScott Long ********************************************* 228544f05562SScott Long */ 2286b23a1998SXin LI outbound_doorbell = READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & acb->outbound_int_enable; 228744f05562SScott Long if(!outbound_doorbell) { 228844f05562SScott Long /*it must be share irq*/ 228944f05562SScott Long return; 229044f05562SScott Long } 2291b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ~outbound_doorbell); /* clear doorbell interrupt */ 2292b23a1998SXin LI READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell); 2293b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 229444f05562SScott Long /* MU ioctl transfer doorbell interrupts*/ 229544f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { 229644f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 229744f05562SScott Long } 229844f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) { 229944f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 230044f05562SScott Long } 230144f05562SScott Long /* MU post queue interrupts*/ 230244f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) { 230344f05562SScott Long arcmsr_hbb_postqueue_isr(acb); 230444f05562SScott Long } 2305d74001adSXin LI if(outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { 2306d74001adSXin LI arcmsr_hbb_message_isr(acb); 2307d74001adSXin LI } 2308d74001adSXin LI } 2309d74001adSXin LI /* 2310d74001adSXin LI ********************************************************************** 2311d74001adSXin LI ********************************************************************** 2312d74001adSXin LI */ 2313d74001adSXin LI static void arcmsr_handle_hbc_isr( struct AdapterControlBlock *acb) 2314d74001adSXin LI { 2315d74001adSXin LI u_int32_t host_interrupt_status; 2316d74001adSXin LI /* 2317d74001adSXin LI ********************************************* 2318d74001adSXin LI ** check outbound intstatus 2319d74001adSXin LI ********************************************* 2320d74001adSXin LI */ 2321224a78aeSXin LI host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & 2322224a78aeSXin LI (ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR | 2323224a78aeSXin LI ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR); 2324d74001adSXin LI if(!host_interrupt_status) { 2325d74001adSXin LI /*it must be share irq*/ 2326d74001adSXin LI return; 2327d74001adSXin LI } 2328224a78aeSXin LI do { 2329d74001adSXin LI /* MU doorbell interrupts*/ 2330d74001adSXin LI if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) { 2331d74001adSXin LI arcmsr_hbc_doorbell_isr(acb); 2332d74001adSXin LI } 2333d74001adSXin LI /* MU post queue interrupts*/ 2334d74001adSXin LI if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) { 2335d74001adSXin LI arcmsr_hbc_postqueue_isr(acb); 2336d74001adSXin LI } 2337224a78aeSXin LI host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status); 2338224a78aeSXin LI } while (host_interrupt_status & (ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR)); 233944f05562SScott Long } 234044f05562SScott Long /* 23417a7bc959SXin LI ********************************************************************** 23427a7bc959SXin LI ********************************************************************** 23437a7bc959SXin LI */ 23447a7bc959SXin LI static void arcmsr_handle_hbd_isr( struct AdapterControlBlock *acb) 23457a7bc959SXin LI { 23467a7bc959SXin LI u_int32_t host_interrupt_status; 23477a7bc959SXin LI u_int32_t intmask_org; 23487a7bc959SXin LI /* 23497a7bc959SXin LI ********************************************* 23507a7bc959SXin LI ** check outbound intstatus 23517a7bc959SXin LI ********************************************* 23527a7bc959SXin LI */ 23537a7bc959SXin LI host_interrupt_status = CHIP_REG_READ32(HBD_MessageUnit, 0, host_int_status) & acb->outbound_int_enable; 23547a7bc959SXin LI if(!(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_INT)) { 23557a7bc959SXin LI /*it must be share irq*/ 23567a7bc959SXin LI return; 23577a7bc959SXin LI } 23587a7bc959SXin LI /* disable outbound interrupt */ 23597a7bc959SXin LI intmask_org = CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable) ; /* disable outbound message0 int */ 23607a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, ARCMSR_HBDMU_ALL_INT_DISABLE); 23617a7bc959SXin LI /* MU doorbell interrupts*/ 23627a7bc959SXin LI if(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_DOORBELL_INT) { 23637a7bc959SXin LI arcmsr_hbd_doorbell_isr(acb); 23647a7bc959SXin LI } 23657a7bc959SXin LI /* MU post queue interrupts*/ 23667a7bc959SXin LI if(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_POSTQUEUE_INT) { 23677a7bc959SXin LI arcmsr_hbd_postqueue_isr(acb); 23687a7bc959SXin LI } 23697a7bc959SXin LI /* enable all outbound interrupt */ 23707a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, intmask_org | ARCMSR_HBDMU_ALL_INT_ENABLE); 23717a7bc959SXin LI // CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable); 23727a7bc959SXin LI } 23737a7bc959SXin LI /* 2374a1103e04SXin LI ********************************************************************** 2375a1103e04SXin LI ********************************************************************** 2376a1103e04SXin LI */ 2377a1103e04SXin LI static void arcmsr_handle_hbe_isr( struct AdapterControlBlock *acb) 2378a1103e04SXin LI { 2379a1103e04SXin LI u_int32_t host_interrupt_status; 2380a1103e04SXin LI /* 2381a1103e04SXin LI ********************************************* 2382a1103e04SXin LI ** check outbound intstatus 2383a1103e04SXin LI ********************************************* 2384a1103e04SXin LI */ 2385a1103e04SXin LI host_interrupt_status = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_status) & 2386a1103e04SXin LI (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR | 2387a1103e04SXin LI ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR); 2388a1103e04SXin LI if(!host_interrupt_status) { 2389a1103e04SXin LI /*it must be share irq*/ 2390a1103e04SXin LI return; 2391a1103e04SXin LI } 2392a1103e04SXin LI do { 2393a1103e04SXin LI /* MU doorbell interrupts*/ 2394a1103e04SXin LI if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR) { 2395a1103e04SXin LI arcmsr_hbe_doorbell_isr(acb); 2396a1103e04SXin LI } 2397a1103e04SXin LI /* MU post queue interrupts*/ 2398a1103e04SXin LI if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR) { 2399a1103e04SXin LI arcmsr_hbe_postqueue_isr(acb); 2400a1103e04SXin LI } 2401a1103e04SXin LI host_interrupt_status = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_status); 2402a1103e04SXin LI } while (host_interrupt_status & (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR)); 2403a1103e04SXin LI } 2404fa42a0bfSXin LI 2405fa42a0bfSXin LI static void arcmsr_handle_hbf_isr( struct AdapterControlBlock *acb) 2406fa42a0bfSXin LI { 2407fa42a0bfSXin LI u_int32_t host_interrupt_status; 2408fa42a0bfSXin LI /* 2409fa42a0bfSXin LI ********************************************* 2410fa42a0bfSXin LI ** check outbound intstatus 2411fa42a0bfSXin LI ********************************************* 2412fa42a0bfSXin LI */ 2413fa42a0bfSXin LI host_interrupt_status = CHIP_REG_READ32(HBF_MessageUnit, 0, host_int_status) & 2414fa42a0bfSXin LI (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR | 2415fa42a0bfSXin LI ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR); 2416fa42a0bfSXin LI if(!host_interrupt_status) { 2417fa42a0bfSXin LI /*it must be share irq*/ 2418fa42a0bfSXin LI return; 2419fa42a0bfSXin LI } 2420fa42a0bfSXin LI do { 2421fa42a0bfSXin LI /* MU doorbell interrupts*/ 2422fa42a0bfSXin LI if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR) { 24236964b77eS黃清隆 arcmsr_hbf_doorbell_isr(acb); 2424fa42a0bfSXin LI } 2425fa42a0bfSXin LI /* MU post queue interrupts*/ 2426fa42a0bfSXin LI if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR) { 2427fa42a0bfSXin LI arcmsr_hbf_postqueue_isr(acb); 2428fa42a0bfSXin LI } 2429fa42a0bfSXin LI host_interrupt_status = CHIP_REG_READ32(HBF_MessageUnit, 0, host_int_status); 2430fa42a0bfSXin LI } while (host_interrupt_status & (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR)); 2431fa42a0bfSXin LI } 2432a1103e04SXin LI /* 243344f05562SScott Long ****************************************************************************** 243444f05562SScott Long ****************************************************************************** 243544f05562SScott Long */ 243644f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb) 243744f05562SScott Long { 243844f05562SScott Long switch (acb->adapter_type) { 243944f05562SScott Long case ACB_ADAPTER_TYPE_A: 244044f05562SScott Long arcmsr_handle_hba_isr(acb); 2441f1c579b1SScott Long break; 244244f05562SScott Long case ACB_ADAPTER_TYPE_B: 244344f05562SScott Long arcmsr_handle_hbb_isr(acb); 2444f1c579b1SScott Long break; 2445d74001adSXin LI case ACB_ADAPTER_TYPE_C: 2446d74001adSXin LI arcmsr_handle_hbc_isr(acb); 2447d74001adSXin LI break; 24487a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 24497a7bc959SXin LI arcmsr_handle_hbd_isr(acb); 24507a7bc959SXin LI break; 2451a1103e04SXin LI case ACB_ADAPTER_TYPE_E: 2452a1103e04SXin LI arcmsr_handle_hbe_isr(acb); 2453a1103e04SXin LI break; 2454fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 2455fa42a0bfSXin LI arcmsr_handle_hbf_isr(acb); 2456fa42a0bfSXin LI break; 2457f1c579b1SScott Long default: 245844f05562SScott Long printf("arcmsr%d: interrupt service," 245910d66948SKevin Lo " unknown adapter type =%d\n", acb->pci_unit, acb->adapter_type); 2460f1c579b1SScott Long break; 2461f1c579b1SScott Long } 2462f1c579b1SScott Long } 2463f1c579b1SScott Long /* 2464d74001adSXin LI ********************************************************************** 2465d74001adSXin LI ********************************************************************** 2466d74001adSXin LI */ 2467d74001adSXin LI static void arcmsr_intr_handler(void *arg) 2468d74001adSXin LI { 2469d74001adSXin LI struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg; 2470d74001adSXin LI 24717a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 2472d74001adSXin LI arcmsr_interrupt(acb); 24737a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 2474d74001adSXin LI } 2475d74001adSXin LI /* 2476d74001adSXin LI ****************************************************************************** 2477d74001adSXin LI ****************************************************************************** 2478d74001adSXin LI */ 2479d74001adSXin LI static void arcmsr_polling_devmap(void *arg) 2480d74001adSXin LI { 2481d74001adSXin LI struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg; 2482d74001adSXin LI switch (acb->adapter_type) { 2483d74001adSXin LI case ACB_ADAPTER_TYPE_A: 2484dac36688SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 2485d74001adSXin LI break; 2486d74001adSXin LI 2487b23a1998SXin LI case ACB_ADAPTER_TYPE_B: { 2488b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 2489b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG); 2490b23a1998SXin LI } 2491d74001adSXin LI break; 2492d74001adSXin LI 2493d74001adSXin LI case ACB_ADAPTER_TYPE_C: 2494d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 2495d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 2496d74001adSXin LI break; 24977a7bc959SXin LI 24987a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 24997a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 25007a7bc959SXin LI break; 2501a1103e04SXin LI 2502a1103e04SXin LI case ACB_ADAPTER_TYPE_E: 2503a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 2504a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 2505a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 2506a1103e04SXin LI break; 2507d74001adSXin LI 2508fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 2509fa42a0bfSXin LI u_int32_t outMsg1 = CHIP_REG_READ32(HBF_MessageUnit, 0, outbound_msgaddr1); 2510fa42a0bfSXin LI if (!(outMsg1 & ARCMSR_HBFMU_MESSAGE_FIRMWARE_OK) || 2511fa42a0bfSXin LI (outMsg1 & ARCMSR_HBFMU_MESSAGE_NO_VOLUME_CHANGE)) 2512fa42a0bfSXin LI goto nxt6s; 2513fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 2514fa42a0bfSXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 2515fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 2516fa42a0bfSXin LI break; 2517fa42a0bfSXin LI } 2518fa42a0bfSXin LI } 2519fa42a0bfSXin LI nxt6s: 2520d74001adSXin LI if((acb->acb_flags & ACB_F_SCSISTOPADAPTER) == 0) 2521d74001adSXin LI { 2522d74001adSXin LI callout_reset(&acb->devmap_callout, 5 * hz, arcmsr_polling_devmap, acb); /* polling per 5 seconds */ 2523d74001adSXin LI } 2524d74001adSXin LI } 2525d74001adSXin LI 2526d74001adSXin LI /* 2527ad6d6297SScott Long ******************************************************************************* 2528ad6d6297SScott Long ** 2529ad6d6297SScott Long ******************************************************************************* 2530ad6d6297SScott Long */ 2531ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb) 2532ad6d6297SScott Long { 2533d74001adSXin LI u_int32_t intmask_org; 2534d74001adSXin LI 2535ad6d6297SScott Long if(acb != NULL) { 2536ad6d6297SScott Long /* stop adapter background rebuild */ 2537ad6d6297SScott Long if(acb->acb_flags & ACB_F_MSG_START_BGRB) { 2538d74001adSXin LI intmask_org = arcmsr_disable_allintr(acb); 2539ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 2540ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2541d74001adSXin LI arcmsr_enable_allintr(acb, intmask_org); 2542ad6d6297SScott Long } 2543ad6d6297SScott Long } 2544ad6d6297SScott Long } 2545ad6d6297SScott Long /* 2546f1c579b1SScott Long *********************************************************************** 2547f1c579b1SScott Long ** 2548f1c579b1SScott Long ************************************************************************ 2549f1c579b1SScott Long */ 2550fc5ef1caSXin LI static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg) 2551f1c579b1SScott Long { 2552ad6d6297SScott Long struct CMD_MESSAGE_FIELD *pcmdmessagefld; 2553ad6d6297SScott Long u_int32_t retvalue = EINVAL; 2554f1c579b1SScott Long 2555ad6d6297SScott Long pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) arg; 2556ad6d6297SScott Long if(memcmp(pcmdmessagefld->cmdmessage.Signature, "ARCMSR", 6)!=0) { 2557ad6d6297SScott Long return retvalue; 2558f1c579b1SScott Long } 2559ad6d6297SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2560ad6d6297SScott Long switch(ioctl_cmd) { 2561ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 2562ad6d6297SScott Long u_int8_t *pQbuffer; 2563ad6d6297SScott Long u_int8_t *ptmpQbuffer = pcmdmessagefld->messagedatabuffer; 2564ad6d6297SScott Long u_int32_t allxfer_len=0; 2565f1c579b1SScott Long 256644f05562SScott Long while((acb->rqbuf_firstindex != acb->rqbuf_lastindex) 256744f05562SScott Long && (allxfer_len < 1031)) { 2568f1c579b1SScott Long /*copy READ QBUFFER to srb*/ 2569ad6d6297SScott Long pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; 25707a7bc959SXin LI *ptmpQbuffer = *pQbuffer; 2571ad6d6297SScott Long acb->rqbuf_firstindex++; 2572ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 2573ad6d6297SScott Long /*if last index number set it to 0 */ 2574f1c579b1SScott Long ptmpQbuffer++; 2575f1c579b1SScott Long allxfer_len++; 2576f1c579b1SScott Long } 2577ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 257844f05562SScott Long struct QBUFFER *prbuffer; 2579f1c579b1SScott Long 2580ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 258144f05562SScott Long prbuffer = arcmsr_get_iop_rqbuffer(acb); 258235689395SXin LI if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) 258335689395SXin LI acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 2584f1c579b1SScott Long } 2585ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length = allxfer_len; 2586ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2587ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2588f1c579b1SScott Long } 2589f1c579b1SScott Long break; 2590ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 2591ad6d6297SScott Long u_int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 2592ad6d6297SScott Long u_int8_t *pQbuffer; 2593ad6d6297SScott Long u_int8_t *ptmpuserbuffer = pcmdmessagefld->messagedatabuffer; 2594f1c579b1SScott Long 2595ad6d6297SScott Long user_len = pcmdmessagefld->cmdmessage.Length; 2596f1c579b1SScott Long /*check if data xfer length of this request will overflow my array qbuffer */ 2597ad6d6297SScott Long wqbuf_lastindex = acb->wqbuf_lastindex; 2598ad6d6297SScott Long wqbuf_firstindex = acb->wqbuf_firstindex; 2599ad6d6297SScott Long if(wqbuf_lastindex != wqbuf_firstindex) { 26007a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2601ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR; 2602ad6d6297SScott Long } else { 26037a7bc959SXin LI my_empty_len = (wqbuf_firstindex - wqbuf_lastindex - 1) & 26047a7bc959SXin LI (ARCMSR_MAX_QBUFFER - 1); 2605ad6d6297SScott Long if(my_empty_len >= user_len) { 2606ad6d6297SScott Long while(user_len > 0) { 2607f1c579b1SScott Long /*copy srb data to wqbuffer*/ 2608ad6d6297SScott Long pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; 26097a7bc959SXin LI *pQbuffer = *ptmpuserbuffer; 2610ad6d6297SScott Long acb->wqbuf_lastindex++; 2611ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 2612ad6d6297SScott Long /*if last index number set it to 0 */ 2613f1c579b1SScott Long ptmpuserbuffer++; 2614f1c579b1SScott Long user_len--; 2615f1c579b1SScott Long } 2616f1c579b1SScott Long /*post fist Qbuffer*/ 2617ad6d6297SScott Long if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 2618ad6d6297SScott Long acb->acb_flags &= ~ACB_F_MESSAGE_WQBUFFER_CLEARED; 26197a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2620f1c579b1SScott Long } 2621ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2622ad6d6297SScott Long } else { 2623ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR; 2624f1c579b1SScott Long } 2625f1c579b1SScott Long } 2626ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2627f1c579b1SScott Long } 2628f1c579b1SScott Long break; 2629ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 2630ad6d6297SScott Long u_int8_t *pQbuffer = acb->rqbuffer; 2631ad6d6297SScott Long 2632ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2633ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 263444f05562SScott Long arcmsr_iop_message_read(acb); 263544f05562SScott Long /*signature, let IOP know data has been readed */ 2636f1c579b1SScott Long } 2637ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 2638ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2639ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2640f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2641ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2642ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2643f1c579b1SScott Long } 2644f1c579b1SScott Long break; 2645ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: 2646f1c579b1SScott Long { 2647ad6d6297SScott Long u_int8_t *pQbuffer = acb->wqbuffer; 2648f1c579b1SScott Long 2649ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2650ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 265144f05562SScott Long arcmsr_iop_message_read(acb); 265244f05562SScott Long /*signature, let IOP know data has been readed */ 2653f1c579b1SScott Long } 265444f05562SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ); 2655ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2656ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2657f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2658ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2659ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2660f1c579b1SScott Long } 2661f1c579b1SScott Long break; 2662ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 2663ad6d6297SScott Long u_int8_t *pQbuffer; 2664f1c579b1SScott Long 2665ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2666ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 266744f05562SScott Long arcmsr_iop_message_read(acb); 266844f05562SScott Long /*signature, let IOP know data has been readed */ 2669f1c579b1SScott Long } 2670ad6d6297SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED 2671ad6d6297SScott Long |ACB_F_MESSAGE_RQBUFFER_CLEARED 267244f05562SScott Long |ACB_F_MESSAGE_WQBUFFER_READ); 2673ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2674ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2675ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2676ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2677ad6d6297SScott Long pQbuffer = acb->rqbuffer; 2678ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 2679ad6d6297SScott Long pQbuffer = acb->wqbuffer; 2680ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 2681ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2682ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2683f1c579b1SScott Long } 2684f1c579b1SScott Long break; 2685ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 2686ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; 2687ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2688f1c579b1SScott Long } 2689f1c579b1SScott Long break; 2690ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 2691ad6d6297SScott Long u_int8_t *hello_string = "Hello! I am ARCMSR"; 2692ad6d6297SScott Long u_int8_t *puserbuffer = (u_int8_t *)pcmdmessagefld->messagedatabuffer; 2693f1c579b1SScott Long 2694ad6d6297SScott Long if(memcpy(puserbuffer, hello_string, (int16_t)strlen(hello_string))) { 2695ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR; 2696ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2697f1c579b1SScott Long return ENOIOCTL; 2698f1c579b1SScott Long } 2699ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2700ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2701ad6d6297SScott Long } 2702ad6d6297SScott Long break; 2703ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: { 2704ad6d6297SScott Long arcmsr_iop_parking(acb); 2705ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2706ad6d6297SScott Long } 2707ad6d6297SScott Long break; 2708ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: { 2709ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2710ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2711f1c579b1SScott Long } 2712f1c579b1SScott Long break; 2713f1c579b1SScott Long } 2714ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2715dac36688SXin LI return (retvalue); 2716f1c579b1SScott Long } 2717f1c579b1SScott Long /* 2718f1c579b1SScott Long ************************************************************************** 2719f1c579b1SScott Long ************************************************************************** 2720f1c579b1SScott Long */ 272122f2616bSXin LI static void arcmsr_free_srb(struct CommandControlBlock *srb) 272222f2616bSXin LI { 272322f2616bSXin LI struct AdapterControlBlock *acb; 272422f2616bSXin LI 272522f2616bSXin LI acb = srb->acb; 27267a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->srb_lock); 272722f2616bSXin LI srb->srb_state = ARCMSR_SRB_DONE; 272822f2616bSXin LI srb->srb_flags = 0; 272922f2616bSXin LI acb->srbworkingQ[acb->workingsrb_doneindex] = srb; 273022f2616bSXin LI acb->workingsrb_doneindex++; 273122f2616bSXin LI acb->workingsrb_doneindex %= ARCMSR_MAX_FREESRB_NUM; 27327a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->srb_lock); 273322f2616bSXin LI } 273422f2616bSXin LI /* 273522f2616bSXin LI ************************************************************************** 273622f2616bSXin LI ************************************************************************** 273722f2616bSXin LI */ 2738fc5ef1caSXin LI static struct CommandControlBlock *arcmsr_get_freesrb(struct AdapterControlBlock *acb) 2739f1c579b1SScott Long { 2740ad6d6297SScott Long struct CommandControlBlock *srb = NULL; 2741ad6d6297SScott Long u_int32_t workingsrb_startindex, workingsrb_doneindex; 2742f1c579b1SScott Long 27437a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->srb_lock); 2744ad6d6297SScott Long workingsrb_doneindex = acb->workingsrb_doneindex; 2745ad6d6297SScott Long workingsrb_startindex = acb->workingsrb_startindex; 2746ad6d6297SScott Long srb = acb->srbworkingQ[workingsrb_startindex]; 2747ad6d6297SScott Long workingsrb_startindex++; 2748ad6d6297SScott Long workingsrb_startindex %= ARCMSR_MAX_FREESRB_NUM; 2749ad6d6297SScott Long if(workingsrb_doneindex != workingsrb_startindex) { 2750ad6d6297SScott Long acb->workingsrb_startindex = workingsrb_startindex; 2751ad6d6297SScott Long } else { 2752ad6d6297SScott Long srb = NULL; 2753ad6d6297SScott Long } 27547a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->srb_lock); 2755ad6d6297SScott Long return(srb); 2756ad6d6297SScott Long } 2757ad6d6297SScott Long /* 2758ad6d6297SScott Long ************************************************************************** 2759ad6d6297SScott Long ************************************************************************** 2760ad6d6297SScott Long */ 2761ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *pccb) 2762ad6d6297SScott Long { 2763ad6d6297SScott Long struct CMD_MESSAGE_FIELD *pcmdmessagefld; 2764ad6d6297SScott Long int retvalue = 0, transfer_len = 0; 2765ad6d6297SScott Long char *buffer; 27664aa947cbSWarner Losh uint8_t *ptr = scsiio_cdb_ptr(&pccb->csio); 27674aa947cbSWarner Losh u_int32_t controlcode = (u_int32_t ) ptr[5] << 24 | 27684aa947cbSWarner Losh (u_int32_t ) ptr[6] << 16 | 27694aa947cbSWarner Losh (u_int32_t ) ptr[7] << 8 | 27704aa947cbSWarner Losh (u_int32_t ) ptr[8]; 2771ad6d6297SScott Long /* 4 bytes: Areca io control code */ 2772dd0b4fb6SKonstantin Belousov if ((pccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) { 2773ad6d6297SScott Long buffer = pccb->csio.data_ptr; 2774ad6d6297SScott Long transfer_len = pccb->csio.dxfer_len; 2775ad6d6297SScott Long } else { 2776ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2777ad6d6297SScott Long goto message_out; 2778ad6d6297SScott Long } 2779ad6d6297SScott Long if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) { 2780ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2781ad6d6297SScott Long goto message_out; 2782ad6d6297SScott Long } 2783ad6d6297SScott Long pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer; 2784ad6d6297SScott Long switch(controlcode) { 2785ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 2786ad6d6297SScott Long u_int8_t *pQbuffer; 2787ad6d6297SScott Long u_int8_t *ptmpQbuffer = pcmdmessagefld->messagedatabuffer; 2788ad6d6297SScott Long int32_t allxfer_len = 0; 2789f1c579b1SScott Long 27907a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2791ad6d6297SScott Long while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) 2792ad6d6297SScott Long && (allxfer_len < 1031)) { 2793ad6d6297SScott Long pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; 27947a7bc959SXin LI *ptmpQbuffer = *pQbuffer; 2795ad6d6297SScott Long acb->rqbuf_firstindex++; 2796ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 2797ad6d6297SScott Long ptmpQbuffer++; 2798ad6d6297SScott Long allxfer_len++; 2799f1c579b1SScott Long } 2800ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 280144f05562SScott Long struct QBUFFER *prbuffer; 2802ad6d6297SScott Long 2803ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 280444f05562SScott Long prbuffer = arcmsr_get_iop_rqbuffer(acb); 280535689395SXin LI if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) 280635689395SXin LI acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 2807ad6d6297SScott Long } 2808ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length = allxfer_len; 2809ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2810ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 28117a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2812ad6d6297SScott Long } 2813ad6d6297SScott Long break; 2814ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 2815ad6d6297SScott Long int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 2816ad6d6297SScott Long u_int8_t *pQbuffer; 2817ad6d6297SScott Long u_int8_t *ptmpuserbuffer = pcmdmessagefld->messagedatabuffer; 2818ad6d6297SScott Long 2819ad6d6297SScott Long user_len = pcmdmessagefld->cmdmessage.Length; 28207a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2821ad6d6297SScott Long wqbuf_lastindex = acb->wqbuf_lastindex; 2822ad6d6297SScott Long wqbuf_firstindex = acb->wqbuf_firstindex; 2823ad6d6297SScott Long if (wqbuf_lastindex != wqbuf_firstindex) { 28247a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2825ad6d6297SScott Long /* has error report sensedata */ 2826dac36688SXin LI if(pccb->csio.sense_len) { 2827ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 2828ad6d6297SScott Long /* Valid,ErrorCode */ 2829ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 2830ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 2831ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 2832ad6d6297SScott Long /* AdditionalSenseLength */ 2833ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 2834ad6d6297SScott Long /* AdditionalSenseCode */ 2835ad6d6297SScott Long } 2836ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2837ad6d6297SScott Long } else { 2838ad6d6297SScott Long my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) 2839ad6d6297SScott Long &(ARCMSR_MAX_QBUFFER - 1); 2840ad6d6297SScott Long if (my_empty_len >= user_len) { 2841ad6d6297SScott Long while (user_len > 0) { 2842ad6d6297SScott Long pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; 28437a7bc959SXin LI *pQbuffer = *ptmpuserbuffer; 2844ad6d6297SScott Long acb->wqbuf_lastindex++; 2845ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 2846ad6d6297SScott Long ptmpuserbuffer++; 2847ad6d6297SScott Long user_len--; 2848ad6d6297SScott Long } 2849ad6d6297SScott Long if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 2850ad6d6297SScott Long acb->acb_flags &= 2851ad6d6297SScott Long ~ACB_F_MESSAGE_WQBUFFER_CLEARED; 28527a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2853ad6d6297SScott Long } 2854ad6d6297SScott Long } else { 2855ad6d6297SScott Long /* has error report sensedata */ 2856dac36688SXin LI if(pccb->csio.sense_len) { 2857ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 2858ad6d6297SScott Long /* Valid,ErrorCode */ 2859ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 2860ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 2861ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 2862ad6d6297SScott Long /* AdditionalSenseLength */ 2863ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 2864ad6d6297SScott Long /* AdditionalSenseCode */ 2865ad6d6297SScott Long } 2866ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2867ad6d6297SScott Long } 2868ad6d6297SScott Long } 28697a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2870ad6d6297SScott Long } 2871ad6d6297SScott Long break; 2872ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 2873ad6d6297SScott Long u_int8_t *pQbuffer = acb->rqbuffer; 2874ad6d6297SScott Long 28757a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2876ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2877ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 287844f05562SScott Long arcmsr_iop_message_read(acb); 2879ad6d6297SScott Long } 2880ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 2881ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2882ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2883ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2884ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 2885ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 28867a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2887ad6d6297SScott Long } 2888ad6d6297SScott Long break; 2889ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { 2890ad6d6297SScott Long u_int8_t *pQbuffer = acb->wqbuffer; 2891ad6d6297SScott Long 28927a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2893ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2894ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 289544f05562SScott Long arcmsr_iop_message_read(acb); 2896ad6d6297SScott Long } 2897ad6d6297SScott Long acb->acb_flags |= 2898ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED | 289944f05562SScott Long ACB_F_MESSAGE_WQBUFFER_READ); 2900ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2901ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2902ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2903ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 2904ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 29057a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2906ad6d6297SScott Long } 2907ad6d6297SScott Long break; 2908ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 2909ad6d6297SScott Long u_int8_t *pQbuffer; 2910ad6d6297SScott Long 29117a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2912ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2913ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 291444f05562SScott Long arcmsr_iop_message_read(acb); 2915ad6d6297SScott Long } 2916ad6d6297SScott Long acb->acb_flags |= 2917ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED 2918ad6d6297SScott Long | ACB_F_MESSAGE_RQBUFFER_CLEARED 291944f05562SScott Long | ACB_F_MESSAGE_WQBUFFER_READ); 2920ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2921ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2922ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2923ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2924ad6d6297SScott Long pQbuffer = acb->rqbuffer; 2925ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 2926ad6d6297SScott Long pQbuffer = acb->wqbuffer; 2927ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 2928ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 29297a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2930ad6d6297SScott Long } 2931ad6d6297SScott Long break; 2932ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 2933ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; 2934ad6d6297SScott Long } 2935ad6d6297SScott Long break; 2936ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 2937ad6d6297SScott Long int8_t *hello_string = "Hello! I am ARCMSR"; 2938ad6d6297SScott Long 2939ad6d6297SScott Long memcpy(pcmdmessagefld->messagedatabuffer, hello_string 2940ad6d6297SScott Long , (int16_t)strlen(hello_string)); 2941ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2942ad6d6297SScott Long } 2943ad6d6297SScott Long break; 2944ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: 2945ad6d6297SScott Long arcmsr_iop_parking(acb); 2946ad6d6297SScott Long break; 2947ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: 2948ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2949ad6d6297SScott Long break; 2950ad6d6297SScott Long default: 2951ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2952ad6d6297SScott Long } 2953ad6d6297SScott Long message_out: 2954dac36688SXin LI return (retvalue); 2955f1c579b1SScott Long } 2956f1c579b1SScott Long /* 2957f1c579b1SScott Long ********************************************************************* 2958f1c579b1SScott Long ********************************************************************* 2959f1c579b1SScott Long */ 2960231c8b71SXin LI static void arcmsr_execute_srb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 2961f1c579b1SScott Long { 2962ad6d6297SScott Long struct CommandControlBlock *srb = (struct CommandControlBlock *)arg; 2963ad6d6297SScott Long struct AdapterControlBlock *acb = (struct AdapterControlBlock *)srb->acb; 2964f1c579b1SScott Long union ccb *pccb; 2965ad6d6297SScott Long int target, lun; 2966f1c579b1SScott Long 2967ad6d6297SScott Long pccb = srb->pccb; 2968ad6d6297SScott Long target = pccb->ccb_h.target_id; 2969ad6d6297SScott Long lun = pccb->ccb_h.target_lun; 297022f2616bSXin LI acb->pktRequestCount++; 2971ad6d6297SScott Long if(error != 0) { 2972ad6d6297SScott Long if(error != EFBIG) { 297344f05562SScott Long printf("arcmsr%d: unexpected error %x" 297444f05562SScott Long " returned from 'bus_dmamap_load' \n" 2975ad6d6297SScott Long , acb->pci_unit, error); 2976f1c579b1SScott Long } 2977ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { 297815735becSScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 2979f1c579b1SScott Long } 2980ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2981f1c579b1SScott Long return; 2982f1c579b1SScott Long } 2983ad6d6297SScott Long if(nseg > ARCMSR_MAX_SG_ENTRIES) { 2984ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 2985ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2986ad6d6297SScott Long return; 2987f1c579b1SScott Long } 2988ad6d6297SScott Long if(acb->acb_flags & ACB_F_BUS_RESET) { 2989ad6d6297SScott Long printf("arcmsr%d: bus reset and return busy \n", acb->pci_unit); 2990ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_BUS_RESET; 2991ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2992ad6d6297SScott Long return; 2993ad6d6297SScott Long } 2994ad6d6297SScott Long if(acb->devstate[target][lun] == ARECA_RAID_GONE) { 299522f2616bSXin LI u_int8_t block_cmd, cmd; 2996ad6d6297SScott Long 29974aa947cbSWarner Losh cmd = scsiio_cdb_ptr(&pccb->csio)[0]; 299822f2616bSXin LI block_cmd = cmd & 0x0f; 2999ad6d6297SScott Long if(block_cmd == 0x08 || block_cmd == 0x0a) { 3000ad6d6297SScott Long printf("arcmsr%d:block 'read/write' command " 300122f2616bSXin LI "with gone raid volume Cmd=0x%2x, TargetId=%d, Lun=%d \n" 300222f2616bSXin LI , acb->pci_unit, cmd, target, lun); 3003ad6d6297SScott Long pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 3004ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 3005ad6d6297SScott Long return; 3006ad6d6297SScott Long } 3007ad6d6297SScott Long } 3008ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { 3009ad6d6297SScott Long if(nseg != 0) { 3010ad6d6297SScott Long bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 3011ad6d6297SScott Long } 3012ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 3013f1c579b1SScott Long return; 3014f1c579b1SScott Long } 3015abfdbca9SXin LI if(acb->srboutstandingcount >= acb->maxOutstanding) { 30167a7bc959SXin LI if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) == 0) 30177a7bc959SXin LI { 301815735becSScott Long xpt_freeze_simq(acb->psim, 1); 3019dc3a205bSScott Long acb->acb_flags |= ACB_F_CAM_DEV_QFRZN; 30207a7bc959SXin LI } 30217a7bc959SXin LI pccb->ccb_h.status &= ~CAM_SIM_QUEUED; 30227a7bc959SXin LI pccb->ccb_h.status |= CAM_REQUEUE_REQ; 3023ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 3024ad6d6297SScott Long return; 3025f1c579b1SScott Long } 302615735becSScott Long pccb->ccb_h.status |= CAM_SIM_QUEUED; 3027ad6d6297SScott Long arcmsr_build_srb(srb, dm_segs, nseg); 3028ad6d6297SScott Long arcmsr_post_srb(acb, srb); 302922f2616bSXin LI if (pccb->ccb_h.timeout != CAM_TIME_INFINITY) 303022f2616bSXin LI { 303122f2616bSXin LI arcmsr_callout_init(&srb->ccb_callout); 303285c9dd9dSSteven Hartland callout_reset_sbt(&srb->ccb_callout, SBT_1MS * 303385c9dd9dSSteven Hartland (pccb->ccb_h.timeout + (ARCMSR_TIMEOUT_DELAY * 1000)), 0, 303485c9dd9dSSteven Hartland arcmsr_srb_timeout, srb, 0); 303522f2616bSXin LI srb->srb_flags |= SRB_FLAG_TIMER_START; 303622f2616bSXin LI } 3037f1c579b1SScott Long } 3038f1c579b1SScott Long /* 3039f1c579b1SScott Long ***************************************************************************************** 3040f1c579b1SScott Long ***************************************************************************************** 3041f1c579b1SScott Long */ 3042ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb *abortccb) 3043f1c579b1SScott Long { 3044ad6d6297SScott Long struct CommandControlBlock *srb; 3045ad6d6297SScott Long struct AdapterControlBlock *acb = (struct AdapterControlBlock *) abortccb->ccb_h.arcmsr_ccbacb_ptr; 304644f05562SScott Long u_int32_t intmask_org; 3047ad6d6297SScott Long int i = 0; 3048f1c579b1SScott Long 3049ad6d6297SScott Long acb->num_aborts++; 3050f1c579b1SScott Long /* 3051ad6d6297SScott Long *************************************************************************** 3052f1c579b1SScott Long ** It is the upper layer do abort command this lock just prior to calling us. 3053f1c579b1SScott Long ** First determine if we currently own this command. 3054f1c579b1SScott Long ** Start by searching the device queue. If not found 3055f1c579b1SScott Long ** at all, and the system wanted us to just abort the 3056f1c579b1SScott Long ** command return success. 3057ad6d6297SScott Long *************************************************************************** 3058f1c579b1SScott Long */ 3059ad6d6297SScott Long if(acb->srboutstandingcount != 0) { 306022f2616bSXin LI /* disable all outbound interrupt */ 306122f2616bSXin LI intmask_org = arcmsr_disable_allintr(acb); 3062ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 3063ad6d6297SScott Long srb = acb->psrb_pool[i]; 306422f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) { 3065ad6d6297SScott Long if(srb->pccb == abortccb) { 306622f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 3067123055f0SNathan Whitehorn printf("arcmsr%d:scsi id=%d lun=%jx abort srb '%p'" 3068ad6d6297SScott Long "outstanding command \n" 3069ad6d6297SScott Long , acb->pci_unit, abortccb->ccb_h.target_id 3070123055f0SNathan Whitehorn , (uintmax_t)abortccb->ccb_h.target_lun, srb); 3071ad6d6297SScott Long arcmsr_polling_srbdone(acb, srb); 307244f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 307344f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 3074ad6d6297SScott Long return (TRUE); 3075f1c579b1SScott Long } 307622f2616bSXin LI } 307722f2616bSXin LI } 307822f2616bSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 307922f2616bSXin LI arcmsr_enable_allintr(acb, intmask_org); 308022f2616bSXin LI } 308122f2616bSXin LI return(FALSE); 308222f2616bSXin LI } 3083f1c579b1SScott Long /* 3084f1c579b1SScott Long **************************************************************************** 3085f1c579b1SScott Long **************************************************************************** 3086f1c579b1SScott Long */ 3087ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb) 3088f1c579b1SScott Long { 3089ad6d6297SScott Long int retry = 0; 3090f1c579b1SScott Long 3091ad6d6297SScott Long acb->num_resets++; 3092ad6d6297SScott Long acb->acb_flags |= ACB_F_BUS_RESET; 3093ad6d6297SScott Long while(acb->srboutstandingcount != 0 && retry < 400) { 309444f05562SScott Long arcmsr_interrupt(acb); 3095ad6d6297SScott Long UDELAY(25000); 3096ad6d6297SScott Long retry++; 3097ad6d6297SScott Long } 3098ad6d6297SScott Long arcmsr_iop_reset(acb); 3099ad6d6297SScott Long acb->acb_flags &= ~ACB_F_BUS_RESET; 3100f1c579b1SScott Long } 3101f1c579b1SScott Long /* 3102ad6d6297SScott Long ************************************************************************** 3103ad6d6297SScott Long ************************************************************************** 3104ad6d6297SScott Long */ 3105ad6d6297SScott Long static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, 3106ad6d6297SScott Long union ccb *pccb) 3107ad6d6297SScott Long { 3108ad6d6297SScott Long if (pccb->ccb_h.target_lun) { 310961ba2ac6SJim Harris pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 3110ad6d6297SScott Long xpt_done(pccb); 3111ad6d6297SScott Long return; 3112ad6d6297SScott Long } 31137a7bc959SXin LI pccb->ccb_h.status |= CAM_REQ_CMP; 31144aa947cbSWarner Losh switch (scsiio_cdb_ptr(&pccb->csio)[0]) { 31157a7bc959SXin LI case INQUIRY: { 31167a7bc959SXin LI unsigned char inqdata[36]; 31177a7bc959SXin LI char *buffer = pccb->csio.data_ptr; 31187a7bc959SXin LI 3119231c8b71SXin LI inqdata[0] = T_PROCESSOR; /* Periph Qualifier & Periph Dev Type */ 3120231c8b71SXin LI inqdata[1] = 0; /* rem media bit & Dev Type Modifier */ 3121231c8b71SXin LI inqdata[2] = 0; /* ISO, ECMA, & ANSI versions */ 3122231c8b71SXin LI inqdata[3] = 0; 3123231c8b71SXin LI inqdata[4] = 31; /* length of additional data */ 3124231c8b71SXin LI inqdata[5] = 0; 3125231c8b71SXin LI inqdata[6] = 0; 3126231c8b71SXin LI inqdata[7] = 0; 3127231c8b71SXin LI strncpy(&inqdata[8], "Areca ", 8); /* Vendor Identification */ 3128231c8b71SXin LI strncpy(&inqdata[16], "RAID controller ", 16); /* Product Identification */ 3129ad6d6297SScott Long strncpy(&inqdata[32], "R001", 4); /* Product Revision */ 3130ad6d6297SScott Long memcpy(buffer, inqdata, sizeof(inqdata)); 3131ad6d6297SScott Long xpt_done(pccb); 3132ad6d6297SScott Long } 3133ad6d6297SScott Long break; 3134ad6d6297SScott Long case WRITE_BUFFER: 3135ad6d6297SScott Long case READ_BUFFER: { 3136ad6d6297SScott Long if (arcmsr_iop_message_xfer(acb, pccb)) { 3137ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 3138ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 3139ad6d6297SScott Long } 3140ad6d6297SScott Long xpt_done(pccb); 3141ad6d6297SScott Long } 3142ad6d6297SScott Long break; 3143ad6d6297SScott Long default: 3144ad6d6297SScott Long xpt_done(pccb); 3145ad6d6297SScott Long } 3146ad6d6297SScott Long } 3147ad6d6297SScott Long /* 3148f1c579b1SScott Long ********************************************************************* 3149f1c579b1SScott Long ********************************************************************* 3150f1c579b1SScott Long */ 3151ad6d6297SScott Long static void arcmsr_action(struct cam_sim *psim, union ccb *pccb) 3152f1c579b1SScott Long { 3153ad6d6297SScott Long struct AdapterControlBlock *acb; 3154f1c579b1SScott Long 3155ad6d6297SScott Long acb = (struct AdapterControlBlock *) cam_sim_softc(psim); 3156ad6d6297SScott Long if(acb == NULL) { 3157ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 3158f1c579b1SScott Long xpt_done(pccb); 3159f1c579b1SScott Long return; 3160f1c579b1SScott Long } 3161ad6d6297SScott Long switch (pccb->ccb_h.func_code) { 3162ad6d6297SScott Long case XPT_SCSI_IO: { 3163ad6d6297SScott Long struct CommandControlBlock *srb; 3164ad6d6297SScott Long int target = pccb->ccb_h.target_id; 3165dd0b4fb6SKonstantin Belousov int error; 3166f1c579b1SScott Long 31674aa947cbSWarner Losh if (pccb->ccb_h.flags & CAM_CDB_PHYS) { 31684aa947cbSWarner Losh pccb->ccb_h.status = CAM_REQ_INVALID; 31694aa947cbSWarner Losh xpt_done(pccb); 31704aa947cbSWarner Losh return; 31714aa947cbSWarner Losh } 31724aa947cbSWarner Losh 3173ad6d6297SScott Long if(target == 16) { 3174ad6d6297SScott Long /* virtual device for iop message transfer */ 3175ad6d6297SScott Long arcmsr_handle_virtual_command(acb, pccb); 3176ad6d6297SScott Long return; 3177ad6d6297SScott Long } 3178ad6d6297SScott Long if((srb = arcmsr_get_freesrb(acb)) == NULL) { 3179ad6d6297SScott Long pccb->ccb_h.status |= CAM_RESRC_UNAVAIL; 3180f1c579b1SScott Long xpt_done(pccb); 3181f1c579b1SScott Long return; 3182f1c579b1SScott Long } 3183ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbsrb_ptr = srb; 3184ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbacb_ptr = acb; 3185ad6d6297SScott Long srb->pccb = pccb; 3186dd0b4fb6SKonstantin Belousov error = bus_dmamap_load_ccb(acb->dm_segs_dmat 3187ad6d6297SScott Long , srb->dm_segs_dmamap 3188dd0b4fb6SKonstantin Belousov , pccb 3189231c8b71SXin LI , arcmsr_execute_srb, srb, /*flags*/0); 3190ad6d6297SScott Long if(error == EINPROGRESS) { 3191ad6d6297SScott Long xpt_freeze_simq(acb->psim, 1); 3192f1c579b1SScott Long pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 3193f1c579b1SScott Long } 3194f1c579b1SScott Long break; 3195f1c579b1SScott Long } 3196ad6d6297SScott Long case XPT_PATH_INQ: { 3197f1c579b1SScott Long struct ccb_pathinq *cpi = &pccb->cpi; 3198f1c579b1SScott Long 3199f1c579b1SScott Long cpi->version_num = 1; 3200f1c579b1SScott Long cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE; 3201f1c579b1SScott Long cpi->target_sprt = 0; 3202f1c579b1SScott Long cpi->hba_misc = 0; 3203f1c579b1SScott Long cpi->hba_eng_cnt = 0; 3204ad6d6297SScott Long cpi->max_target = ARCMSR_MAX_TARGETID; /* 0-16 */ 3205ad6d6297SScott Long cpi->max_lun = ARCMSR_MAX_TARGETLUN; /* 0-7 */ 3206ad6d6297SScott Long cpi->initiator_id = ARCMSR_SCSI_INITIATOR_ID; /* 255 */ 3207f1c579b1SScott Long cpi->bus_id = cam_sim_bus(psim); 32084195c7deSAlan Somers strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 32094195c7deSAlan Somers strlcpy(cpi->hba_vid, "ARCMSR", HBA_IDLEN); 32104195c7deSAlan Somers strlcpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN); 3211f1c579b1SScott Long cpi->unit_number = cam_sim_unit(psim); 3212224a78aeSXin LI if(acb->adapter_bus_speed == ACB_BUS_SPEED_12G) 3213224a78aeSXin LI cpi->base_transfer_speed = 1200000; 3214224a78aeSXin LI else if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G) 3215dac36688SXin LI cpi->base_transfer_speed = 600000; 3216dac36688SXin LI else 3217dac36688SXin LI cpi->base_transfer_speed = 300000; 3218dac36688SXin LI if((acb->vendor_device_id == PCIDevVenIDARC1880) || 3219a1103e04SXin LI (acb->vendor_device_id == PCIDevVenIDARC1884) || 32207a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1680) || 32217a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1214)) 3222dac36688SXin LI { 3223dac36688SXin LI cpi->transport = XPORT_SAS; 3224dac36688SXin LI cpi->transport_version = 0; 3225dac36688SXin LI cpi->protocol_version = SCSI_REV_SPC2; 3226dac36688SXin LI } 3227dac36688SXin LI else 3228dac36688SXin LI { 3229fa9ed865SMatt Jacob cpi->transport = XPORT_SPI; 3230fa9ed865SMatt Jacob cpi->transport_version = 2; 3231fa9ed865SMatt Jacob cpi->protocol_version = SCSI_REV_2; 3232dac36688SXin LI } 3233dac36688SXin LI cpi->protocol = PROTO_SCSI; 3234ad6d6297SScott Long cpi->ccb_h.status |= CAM_REQ_CMP; 3235f1c579b1SScott Long xpt_done(pccb); 3236f1c579b1SScott Long break; 3237f1c579b1SScott Long } 3238ad6d6297SScott Long case XPT_ABORT: { 3239f1c579b1SScott Long union ccb *pabort_ccb; 3240f1c579b1SScott Long 3241f1c579b1SScott Long pabort_ccb = pccb->cab.abort_ccb; 3242ad6d6297SScott Long switch (pabort_ccb->ccb_h.func_code) { 3243f1c579b1SScott Long case XPT_ACCEPT_TARGET_IO: 3244f1c579b1SScott Long case XPT_CONT_TARGET_IO: 3245ad6d6297SScott Long if(arcmsr_seek_cmd2abort(pabort_ccb)==TRUE) { 3246ad6d6297SScott Long pabort_ccb->ccb_h.status |= CAM_REQ_ABORTED; 3247f1c579b1SScott Long xpt_done(pabort_ccb); 3248ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 3249ad6d6297SScott Long } else { 3250f1c579b1SScott Long xpt_print_path(pabort_ccb->ccb_h.path); 3251f1c579b1SScott Long printf("Not found\n"); 3252ad6d6297SScott Long pccb->ccb_h.status |= CAM_PATH_INVALID; 3253f1c579b1SScott Long } 3254f1c579b1SScott Long break; 3255f1c579b1SScott Long case XPT_SCSI_IO: 3256ad6d6297SScott Long pccb->ccb_h.status |= CAM_UA_ABORT; 3257f1c579b1SScott Long break; 3258f1c579b1SScott Long default: 3259ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 3260f1c579b1SScott Long break; 3261f1c579b1SScott Long } 3262f1c579b1SScott Long xpt_done(pccb); 3263f1c579b1SScott Long break; 3264f1c579b1SScott Long } 3265f1c579b1SScott Long case XPT_RESET_BUS: 3266ad6d6297SScott Long case XPT_RESET_DEV: { 3267ad6d6297SScott Long u_int32_t i; 3268f1c579b1SScott Long 3269ad6d6297SScott Long arcmsr_bus_reset(acb); 3270ad6d6297SScott Long for (i=0; i < 500; i++) { 3271f1c579b1SScott Long DELAY(1000); 3272f1c579b1SScott Long } 3273ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 3274f1c579b1SScott Long xpt_done(pccb); 3275f1c579b1SScott Long break; 3276f1c579b1SScott Long } 3277ad6d6297SScott Long case XPT_TERM_IO: { 3278ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 3279f1c579b1SScott Long xpt_done(pccb); 3280f1c579b1SScott Long break; 3281f1c579b1SScott Long } 3282ad6d6297SScott Long case XPT_GET_TRAN_SETTINGS: { 3283ad6d6297SScott Long struct ccb_trans_settings *cts; 3284ad6d6297SScott Long 3285ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 3286ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 3287ad6d6297SScott Long xpt_done(pccb); 3288ad6d6297SScott Long break; 3289ad6d6297SScott Long } 3290ad6d6297SScott Long cts = &pccb->cts; 329144f05562SScott Long { 329244f05562SScott Long struct ccb_trans_settings_scsi *scsi; 329344f05562SScott Long struct ccb_trans_settings_spi *spi; 3294dac36688SXin LI struct ccb_trans_settings_sas *sas; 329544f05562SScott Long 3296ad6d6297SScott Long scsi = &cts->proto_specific.scsi; 3297dac36688SXin LI scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 3298dac36688SXin LI scsi->valid = CTS_SCSI_VALID_TQ; 3299fa9ed865SMatt Jacob cts->protocol = PROTO_SCSI; 3300dac36688SXin LI 3301dac36688SXin LI if((acb->vendor_device_id == PCIDevVenIDARC1880) || 3302a1103e04SXin LI (acb->vendor_device_id == PCIDevVenIDARC1884) || 33037a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1680) || 33047a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1214)) 3305dac36688SXin LI { 3306dac36688SXin LI cts->protocol_version = SCSI_REV_SPC2; 3307dac36688SXin LI cts->transport_version = 0; 3308dac36688SXin LI cts->transport = XPORT_SAS; 3309dac36688SXin LI sas = &cts->xport_specific.sas; 3310dac36688SXin LI sas->valid = CTS_SAS_VALID_SPEED; 3311b23a1998SXin LI if (acb->adapter_bus_speed == ACB_BUS_SPEED_12G) 3312224a78aeSXin LI sas->bitrate = 1200000; 3313b23a1998SXin LI else if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G) 3314dac36688SXin LI sas->bitrate = 600000; 3315b23a1998SXin LI else if(acb->adapter_bus_speed == ACB_BUS_SPEED_3G) 3316dac36688SXin LI sas->bitrate = 300000; 3317dac36688SXin LI } 3318dac36688SXin LI else 3319dac36688SXin LI { 3320fa9ed865SMatt Jacob cts->protocol_version = SCSI_REV_2; 3321fa9ed865SMatt Jacob cts->transport_version = 2; 3322dac36688SXin LI cts->transport = XPORT_SPI; 3323dac36688SXin LI spi = &cts->xport_specific.spi; 3324fa9ed865SMatt Jacob spi->flags = CTS_SPI_FLAGS_DISC_ENB; 3325b23a1998SXin LI if (acb->adapter_bus_speed == ACB_BUS_SPEED_6G) 3326b23a1998SXin LI spi->sync_period = 1; 3327b23a1998SXin LI else 3328dac36688SXin LI spi->sync_period = 2; 3329fa9ed865SMatt Jacob spi->sync_offset = 32; 3330fa9ed865SMatt Jacob spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 33319d98ff4dSScott Long spi->valid = CTS_SPI_VALID_DISC 33329d98ff4dSScott Long | CTS_SPI_VALID_SYNC_RATE 3333fa9ed865SMatt Jacob | CTS_SPI_VALID_SYNC_OFFSET 3334fa9ed865SMatt Jacob | CTS_SPI_VALID_BUS_WIDTH; 3335dac36688SXin LI } 333644f05562SScott Long } 3337ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 3338ad6d6297SScott Long xpt_done(pccb); 3339ad6d6297SScott Long break; 3340ad6d6297SScott Long } 3341ad6d6297SScott Long case XPT_SET_TRAN_SETTINGS: { 3342ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 3343ad6d6297SScott Long xpt_done(pccb); 3344ad6d6297SScott Long break; 3345ad6d6297SScott Long } 3346f3b080e6SMarius Strobl case XPT_CALC_GEOMETRY: 3347ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 3348ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 3349ad6d6297SScott Long xpt_done(pccb); 3350ad6d6297SScott Long break; 3351ad6d6297SScott Long } 3352f3b080e6SMarius Strobl cam_calc_geometry(&pccb->ccg, 1); 3353f1c579b1SScott Long xpt_done(pccb); 3354f1c579b1SScott Long break; 3355f1c579b1SScott Long default: 3356ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 3357f1c579b1SScott Long xpt_done(pccb); 3358f1c579b1SScott Long break; 3359f1c579b1SScott Long } 3360f1c579b1SScott Long } 3361f1c579b1SScott Long /* 3362f1c579b1SScott Long ********************************************************************** 3363f1c579b1SScott Long ********************************************************************** 3364f1c579b1SScott Long */ 336544f05562SScott Long static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) 3366f1c579b1SScott Long { 3367ad6d6297SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 336844f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 336944f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 3370*2f7e72bdSMustafa Ateş Uzun printf("arcmsr%d: wait 'start adapter background rebuild' timeout \n", acb->pci_unit); 3371ad6d6297SScott Long } 3372f1c579b1SScott Long } 3373f1c579b1SScott Long /* 3374f1c579b1SScott Long ********************************************************************** 3375f1c579b1SScott Long ********************************************************************** 3376f1c579b1SScott Long */ 337744f05562SScott Long static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb) 337844f05562SScott Long { 3379b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 338044f05562SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 3381b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_START_BGRB); 338244f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 3383*2f7e72bdSMustafa Ateş Uzun printf( "arcmsr%d: wait 'start adapter background rebuild' timeout \n", acb->pci_unit); 338444f05562SScott Long } 338544f05562SScott Long } 338644f05562SScott Long /* 338744f05562SScott Long ********************************************************************** 338844f05562SScott Long ********************************************************************** 338944f05562SScott Long */ 3390d74001adSXin LI static void arcmsr_start_hbc_bgrb(struct AdapterControlBlock *acb) 3391d74001adSXin LI { 3392d74001adSXin LI acb->acb_flags |= ACB_F_MSG_START_BGRB; 3393d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 3394d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 3395d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 3396*2f7e72bdSMustafa Ateş Uzun printf("arcmsr%d: wait 'start adapter background rebuild' timeout \n", acb->pci_unit); 3397d74001adSXin LI } 3398d74001adSXin LI } 3399d74001adSXin LI /* 3400d74001adSXin LI ********************************************************************** 3401d74001adSXin LI ********************************************************************** 3402d74001adSXin LI */ 34037a7bc959SXin LI static void arcmsr_start_hbd_bgrb(struct AdapterControlBlock *acb) 34047a7bc959SXin LI { 34057a7bc959SXin LI acb->acb_flags |= ACB_F_MSG_START_BGRB; 34067a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 34077a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 3408*2f7e72bdSMustafa Ateş Uzun printf("arcmsr%d: wait 'start adapter background rebuild' timeout \n", acb->pci_unit); 34097a7bc959SXin LI } 34107a7bc959SXin LI } 34117a7bc959SXin LI /* 34127a7bc959SXin LI ********************************************************************** 34137a7bc959SXin LI ********************************************************************** 34147a7bc959SXin LI */ 3415a1103e04SXin LI static void arcmsr_start_hbe_bgrb(struct AdapterControlBlock *acb) 3416a1103e04SXin LI { 3417a1103e04SXin LI acb->acb_flags |= ACB_F_MSG_START_BGRB; 3418a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 3419a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 3420a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 3421a1103e04SXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) { 3422*2f7e72bdSMustafa Ateş Uzun printf("arcmsr%d: wait 'start adapter background rebuild' timeout \n", acb->pci_unit); 3423a1103e04SXin LI } 3424a1103e04SXin LI } 3425a1103e04SXin LI /* 3426a1103e04SXin LI ********************************************************************** 3427a1103e04SXin LI ********************************************************************** 3428a1103e04SXin LI */ 342944f05562SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) 343044f05562SScott Long { 343144f05562SScott Long switch (acb->adapter_type) { 343244f05562SScott Long case ACB_ADAPTER_TYPE_A: 343344f05562SScott Long arcmsr_start_hba_bgrb(acb); 343444f05562SScott Long break; 343544f05562SScott Long case ACB_ADAPTER_TYPE_B: 343644f05562SScott Long arcmsr_start_hbb_bgrb(acb); 343744f05562SScott Long break; 3438d74001adSXin LI case ACB_ADAPTER_TYPE_C: 3439d74001adSXin LI arcmsr_start_hbc_bgrb(acb); 3440d74001adSXin LI break; 34417a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 34427a7bc959SXin LI arcmsr_start_hbd_bgrb(acb); 34437a7bc959SXin LI break; 3444a1103e04SXin LI case ACB_ADAPTER_TYPE_E: 3445fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 3446a1103e04SXin LI arcmsr_start_hbe_bgrb(acb); 3447a1103e04SXin LI break; 344844f05562SScott Long } 344944f05562SScott Long } 345044f05562SScott Long /* 345144f05562SScott Long ********************************************************************** 345244f05562SScott Long ** 345344f05562SScott Long ********************************************************************** 345444f05562SScott Long */ 345544f05562SScott Long static void arcmsr_polling_hba_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 3456f1c579b1SScott Long { 3457ad6d6297SScott Long struct CommandControlBlock *srb; 345844f05562SScott Long u_int32_t flag_srb, outbound_intstatus, poll_srb_done=0, poll_count=0; 3459d74001adSXin LI u_int16_t error; 3460f1c579b1SScott Long 346144f05562SScott Long polling_ccb_retry: 3462ad6d6297SScott Long poll_count++; 3463d74001adSXin LI outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 3464d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus); /*clear interrupt*/ 346544f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 3466ad6d6297SScott Long while(1) { 346744f05562SScott Long if((flag_srb = CHIP_REG_READ32(HBA_MessageUnit, 346844f05562SScott Long 0, outbound_queueport)) == 0xFFFFFFFF) { 3469ad6d6297SScott Long if(poll_srb_done) { 3470ad6d6297SScott Long break;/*chip FIFO no ccb for completion already*/ 3471ad6d6297SScott Long } else { 3472ad6d6297SScott Long UDELAY(25000); 3473d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 3474ad6d6297SScott Long break; 3475f1c579b1SScott Long } 347644f05562SScott Long goto polling_ccb_retry; 3477f1c579b1SScott Long } 3478ad6d6297SScott Long } 3479ad6d6297SScott Long /* check if command done with no error*/ 348044f05562SScott Long srb = (struct CommandControlBlock *) 348144f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 3482d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 348344f05562SScott Long poll_srb_done = (srb == poll_srb) ? 1:0; 348422f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 348522f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3486123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'" 3487ad6d6297SScott Long "poll command abort successfully \n" 3488ad6d6297SScott Long , acb->pci_unit 3489ad6d6297SScott Long , srb->pccb->ccb_h.target_id 3490123055f0SNathan Whitehorn , (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 3491ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 3492ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 3493ad6d6297SScott Long continue; 3494ad6d6297SScott Long } 3495ad6d6297SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 3496ad6d6297SScott Long "srboutstandingcount=%d \n" 3497ad6d6297SScott Long , acb->pci_unit 3498ad6d6297SScott Long , srb, acb->srboutstandingcount); 3499ad6d6297SScott Long continue; 3500ad6d6297SScott Long } 3501d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 3502ad6d6297SScott Long } /*drain reply FIFO*/ 3503f1c579b1SScott Long } 3504f1c579b1SScott Long /* 3505f1c579b1SScott Long ********************************************************************** 350644f05562SScott Long ** 3507ad6d6297SScott Long ********************************************************************** 3508ad6d6297SScott Long */ 350944f05562SScott Long static void arcmsr_polling_hbb_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 351044f05562SScott Long { 351144f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 351244f05562SScott Long struct CommandControlBlock *srb; 351344f05562SScott Long u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 351444f05562SScott Long int index; 3515d74001adSXin LI u_int16_t error; 351644f05562SScott Long 351744f05562SScott Long polling_ccb_retry: 351844f05562SScott Long poll_count++; 3519b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 352044f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 352144f05562SScott Long while(1) { 352244f05562SScott Long index = phbbmu->doneq_index; 352344f05562SScott Long if((flag_srb = phbbmu->done_qbuffer[index]) == 0) { 352444f05562SScott Long if(poll_srb_done) { 352544f05562SScott Long break;/*chip FIFO no ccb for completion already*/ 352644f05562SScott Long } else { 352744f05562SScott Long UDELAY(25000); 3528d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 352944f05562SScott Long break; 353044f05562SScott Long } 353144f05562SScott Long goto polling_ccb_retry; 353244f05562SScott Long } 353344f05562SScott Long } 353444f05562SScott Long phbbmu->done_qbuffer[index] = 0; 353544f05562SScott Long index++; 353644f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 353744f05562SScott Long phbbmu->doneq_index = index; 353844f05562SScott Long /* check if command done with no error*/ 353944f05562SScott Long srb = (struct CommandControlBlock *) 354044f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 3541d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 354244f05562SScott Long poll_srb_done = (srb == poll_srb) ? 1:0; 354322f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 354422f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3545123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'" 354644f05562SScott Long "poll command abort successfully \n" 354744f05562SScott Long , acb->pci_unit 354844f05562SScott Long , srb->pccb->ccb_h.target_id 3549123055f0SNathan Whitehorn , (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 355044f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 355144f05562SScott Long arcmsr_srb_complete(srb, 1); 355244f05562SScott Long continue; 355344f05562SScott Long } 355444f05562SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 355544f05562SScott Long "srboutstandingcount=%d \n" 355644f05562SScott Long , acb->pci_unit 355744f05562SScott Long , srb, acb->srboutstandingcount); 355844f05562SScott Long continue; 355944f05562SScott Long } 3560d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 3561d74001adSXin LI } /*drain reply FIFO*/ 3562d74001adSXin LI } 3563d74001adSXin LI /* 3564d74001adSXin LI ********************************************************************** 3565d74001adSXin LI ** 3566d74001adSXin LI ********************************************************************** 3567d74001adSXin LI */ 3568d74001adSXin LI static void arcmsr_polling_hbc_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 3569d74001adSXin LI { 3570d74001adSXin LI struct CommandControlBlock *srb; 3571d74001adSXin LI u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 3572d74001adSXin LI u_int16_t error; 3573d74001adSXin LI 3574d74001adSXin LI polling_ccb_retry: 3575d74001adSXin LI poll_count++; 3576d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 3577d74001adSXin LI while(1) { 3578d74001adSXin LI if(!(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR)) { 3579d74001adSXin LI if(poll_srb_done) { 3580d74001adSXin LI break;/*chip FIFO no ccb for completion already*/ 3581d74001adSXin LI } else { 3582d74001adSXin LI UDELAY(25000); 3583d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 3584d74001adSXin LI break; 3585d74001adSXin LI } 3586d74001adSXin LI if (acb->srboutstandingcount == 0) { 3587d74001adSXin LI break; 3588d74001adSXin LI } 3589d74001adSXin LI goto polling_ccb_retry; 3590d74001adSXin LI } 3591d74001adSXin LI } 3592d74001adSXin LI flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 3593d74001adSXin LI /* check if command done with no error*/ 359422f2616bSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/ 3595d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; 3596d74001adSXin LI if (poll_srb != NULL) 3597d74001adSXin LI poll_srb_done = (srb == poll_srb) ? 1:0; 359822f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 359922f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3600123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n" 3601123055f0SNathan Whitehorn , acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 3602d74001adSXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 3603d74001adSXin LI arcmsr_srb_complete(srb, 1); 3604d74001adSXin LI continue; 3605d74001adSXin LI } 3606d74001adSXin LI printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n" 3607d74001adSXin LI , acb->pci_unit, srb, acb->srboutstandingcount); 3608d74001adSXin LI continue; 3609d74001adSXin LI } 3610d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 361144f05562SScott Long } /*drain reply FIFO*/ 361244f05562SScott Long } 361344f05562SScott Long /* 361444f05562SScott Long ********************************************************************** 36157a7bc959SXin LI ** 36167a7bc959SXin LI ********************************************************************** 36177a7bc959SXin LI */ 36187a7bc959SXin LI static void arcmsr_polling_hbd_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 36197a7bc959SXin LI { 36207a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 36217a7bc959SXin LI struct CommandControlBlock *srb; 36227a7bc959SXin LI u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 36237a7bc959SXin LI u_int32_t outbound_write_pointer; 36247a7bc959SXin LI u_int16_t error, doneq_index; 36257a7bc959SXin LI 36267a7bc959SXin LI polling_ccb_retry: 36277a7bc959SXin LI poll_count++; 36287a7bc959SXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 36297a7bc959SXin LI while(1) { 36307a7bc959SXin LI outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow; 36317a7bc959SXin LI doneq_index = phbdmu->doneq_index; 36327a7bc959SXin LI if ((outbound_write_pointer & 0xFF) == (doneq_index & 0xFF)) { 36337a7bc959SXin LI if(poll_srb_done) { 36347a7bc959SXin LI break;/*chip FIFO no ccb for completion already*/ 36357a7bc959SXin LI } else { 36367a7bc959SXin LI UDELAY(25000); 36377a7bc959SXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 36387a7bc959SXin LI break; 36397a7bc959SXin LI } 36407a7bc959SXin LI if (acb->srboutstandingcount == 0) { 36417a7bc959SXin LI break; 36427a7bc959SXin LI } 36437a7bc959SXin LI goto polling_ccb_retry; 36447a7bc959SXin LI } 36457a7bc959SXin LI } 36467a7bc959SXin LI doneq_index = arcmsr_get_doneq_index(phbdmu); 36477a7bc959SXin LI flag_srb = phbdmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow; 36487a7bc959SXin LI /* check if command done with no error*/ 36497a7bc959SXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/ 36507a7bc959SXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 36517a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_read_pointer, doneq_index); 36527a7bc959SXin LI if (poll_srb != NULL) 36537a7bc959SXin LI poll_srb_done = (srb == poll_srb) ? 1:0; 36547a7bc959SXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 36557a7bc959SXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3656123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n" 3657123055f0SNathan Whitehorn , acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 36587a7bc959SXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 36597a7bc959SXin LI arcmsr_srb_complete(srb, 1); 36607a7bc959SXin LI continue; 36617a7bc959SXin LI } 36627a7bc959SXin LI printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n" 36637a7bc959SXin LI , acb->pci_unit, srb, acb->srboutstandingcount); 36647a7bc959SXin LI continue; 36657a7bc959SXin LI } 36667a7bc959SXin LI arcmsr_report_srb_state(acb, srb, error); 36677a7bc959SXin LI } /*drain reply FIFO*/ 36687a7bc959SXin LI } 36697a7bc959SXin LI /* 36707a7bc959SXin LI ********************************************************************** 3671a1103e04SXin LI ** 3672a1103e04SXin LI ********************************************************************** 3673a1103e04SXin LI */ 3674a1103e04SXin LI static void arcmsr_polling_hbe_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 3675a1103e04SXin LI { 3676a1103e04SXin LI struct CommandControlBlock *srb; 3677a1103e04SXin LI u_int32_t poll_srb_done=0, poll_count=0, doneq_index; 3678a1103e04SXin LI u_int16_t error, cmdSMID; 3679a1103e04SXin LI 3680a1103e04SXin LI polling_ccb_retry: 3681a1103e04SXin LI poll_count++; 3682a1103e04SXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 3683a1103e04SXin LI while(1) { 3684a1103e04SXin LI doneq_index = acb->doneq_index; 3685a1103e04SXin LI if((CHIP_REG_READ32(HBE_MessageUnit, 0, reply_post_producer_index) & 0xFFFF) == doneq_index) { 3686a1103e04SXin LI if(poll_srb_done) { 3687a1103e04SXin LI break;/*chip FIFO no ccb for completion already*/ 3688a1103e04SXin LI } else { 3689a1103e04SXin LI UDELAY(25000); 3690a1103e04SXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 3691a1103e04SXin LI break; 3692a1103e04SXin LI } 3693a1103e04SXin LI if (acb->srboutstandingcount == 0) { 3694a1103e04SXin LI break; 3695a1103e04SXin LI } 3696a1103e04SXin LI goto polling_ccb_retry; 3697a1103e04SXin LI } 3698a1103e04SXin LI } 3699a1103e04SXin LI cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID; 3700a1103e04SXin LI doneq_index++; 3701a1103e04SXin LI if (doneq_index >= acb->completionQ_entry) 3702a1103e04SXin LI doneq_index = 0; 3703a1103e04SXin LI acb->doneq_index = doneq_index; 3704a1103e04SXin LI srb = acb->psrb_pool[cmdSMID]; 3705a1103e04SXin LI error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 3706a1103e04SXin LI if (poll_srb != NULL) 3707a1103e04SXin LI poll_srb_done = (srb == poll_srb) ? 1:0; 3708a1103e04SXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 3709a1103e04SXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3710a1103e04SXin LI printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n" 3711a1103e04SXin LI , acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 3712a1103e04SXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 3713a1103e04SXin LI arcmsr_srb_complete(srb, 1); 3714a1103e04SXin LI continue; 3715a1103e04SXin LI } 3716a1103e04SXin LI printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n" 3717a1103e04SXin LI , acb->pci_unit, srb, acb->srboutstandingcount); 3718a1103e04SXin LI continue; 3719a1103e04SXin LI } 3720a1103e04SXin LI arcmsr_report_srb_state(acb, srb, error); 3721a1103e04SXin LI } /*drain reply FIFO*/ 3722a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, reply_post_producer_index, doneq_index); 3723a1103e04SXin LI } 3724a1103e04SXin LI /* 3725a1103e04SXin LI ********************************************************************** 372644f05562SScott Long ********************************************************************** 372744f05562SScott Long */ 372844f05562SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 372944f05562SScott Long { 373044f05562SScott Long switch (acb->adapter_type) { 3731fa42a0bfSXin LI case ACB_ADAPTER_TYPE_A: 373244f05562SScott Long arcmsr_polling_hba_srbdone(acb, poll_srb); 373344f05562SScott Long break; 3734fa42a0bfSXin LI case ACB_ADAPTER_TYPE_B: 373544f05562SScott Long arcmsr_polling_hbb_srbdone(acb, poll_srb); 373644f05562SScott Long break; 3737fa42a0bfSXin LI case ACB_ADAPTER_TYPE_C: 3738d74001adSXin LI arcmsr_polling_hbc_srbdone(acb, poll_srb); 3739d74001adSXin LI break; 3740fa42a0bfSXin LI case ACB_ADAPTER_TYPE_D: 37417a7bc959SXin LI arcmsr_polling_hbd_srbdone(acb, poll_srb); 37427a7bc959SXin LI break; 3743fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 3744fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 3745a1103e04SXin LI arcmsr_polling_hbe_srbdone(acb, poll_srb); 3746a1103e04SXin LI break; 374744f05562SScott Long } 374844f05562SScott Long } 374944f05562SScott Long /* 375044f05562SScott Long ********************************************************************** 375144f05562SScott Long ********************************************************************** 375244f05562SScott Long */ 375344f05562SScott Long static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) 3754ad6d6297SScott Long { 3755ad6d6297SScott Long char *acb_firm_model = acb->firm_model; 3756ad6d6297SScott Long char *acb_firm_version = acb->firm_version; 3757d74001adSXin LI char *acb_device_map = acb->device_map; 3758d74001adSXin LI size_t iop_firm_model = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3759d74001adSXin LI size_t iop_firm_version = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3760d74001adSXin LI size_t iop_device_map = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 3761ad6d6297SScott Long int i; 3762ad6d6297SScott Long 376344f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 376444f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 3765d74001adSXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 3766ad6d6297SScott Long } 3767ad6d6297SScott Long i = 0; 3768ad6d6297SScott Long while(i < 8) { 376944f05562SScott Long *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 3770ad6d6297SScott Long /* 8 bytes firm_model, 15, 60-67*/ 3771ad6d6297SScott Long acb_firm_model++; 3772ad6d6297SScott Long i++; 3773ad6d6297SScott Long } 3774ad6d6297SScott Long i=0; 3775ad6d6297SScott Long while(i < 16) { 377644f05562SScott Long *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 3777ad6d6297SScott Long /* 16 bytes firm_version, 17, 68-83*/ 3778ad6d6297SScott Long acb_firm_version++; 3779ad6d6297SScott Long i++; 3780ad6d6297SScott Long } 3781d74001adSXin LI i=0; 3782d74001adSXin LI while(i < 16) { 3783d74001adSXin LI *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 3784d74001adSXin LI acb_device_map++; 3785d74001adSXin LI i++; 3786d74001adSXin LI } 37871e7d660aSXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 3788d74001adSXin LI acb->firm_request_len = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3789d74001adSXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3790d74001adSXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3791d74001adSXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3792d74001adSXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3793abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD) 3794abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1; 3795abfdbca9SXin LI else 3796abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 3797ad6d6297SScott Long } 3798ad6d6297SScott Long /* 3799ad6d6297SScott Long ********************************************************************** 380044f05562SScott Long ********************************************************************** 380144f05562SScott Long */ 380244f05562SScott Long static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) 380344f05562SScott Long { 3804b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 380544f05562SScott Long char *acb_firm_model = acb->firm_model; 380644f05562SScott Long char *acb_firm_version = acb->firm_version; 3807d74001adSXin LI char *acb_device_map = acb->device_map; 3808d74001adSXin LI size_t iop_firm_model = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3809d74001adSXin LI size_t iop_firm_version = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3810d74001adSXin LI size_t iop_device_map = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 381144f05562SScott Long int i; 381244f05562SScott Long 3813b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG); 381444f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 3815d74001adSXin LI printf( "arcmsr%d: wait" "'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 381644f05562SScott Long } 381744f05562SScott Long i = 0; 381844f05562SScott Long while(i < 8) { 381944f05562SScott Long *acb_firm_model = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_model+i); 382044f05562SScott Long /* 8 bytes firm_model, 15, 60-67*/ 382144f05562SScott Long acb_firm_model++; 382244f05562SScott Long i++; 382344f05562SScott Long } 382444f05562SScott Long i = 0; 382544f05562SScott Long while(i < 16) { 382644f05562SScott Long *acb_firm_version = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_version+i); 382744f05562SScott Long /* 16 bytes firm_version, 17, 68-83*/ 382844f05562SScott Long acb_firm_version++; 382944f05562SScott Long i++; 383044f05562SScott Long } 3831d74001adSXin LI i = 0; 3832d74001adSXin LI while(i < 16) { 3833d74001adSXin LI *acb_device_map = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_device_map+i); 3834d74001adSXin LI acb_device_map++; 3835d74001adSXin LI i++; 3836d74001adSXin LI } 38371e7d660aSXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 3838d74001adSXin LI acb->firm_request_len = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3839d74001adSXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3840d74001adSXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3841d74001adSXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3842d74001adSXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3843abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_HBB_POSTQUEUE) 3844abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_HBB_POSTQUEUE - 1; 3845abfdbca9SXin LI else 3846abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 3847d74001adSXin LI } 3848d74001adSXin LI /* 3849d74001adSXin LI ********************************************************************** 3850d74001adSXin LI ********************************************************************** 3851d74001adSXin LI */ 3852d74001adSXin LI static void arcmsr_get_hbc_config(struct AdapterControlBlock *acb) 3853d74001adSXin LI { 3854d74001adSXin LI char *acb_firm_model = acb->firm_model; 3855d74001adSXin LI char *acb_firm_version = acb->firm_version; 3856d74001adSXin LI char *acb_device_map = acb->device_map; 3857d74001adSXin LI size_t iop_firm_model = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3858d74001adSXin LI size_t iop_firm_version = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3859d74001adSXin LI size_t iop_device_map = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 3860d74001adSXin LI int i; 3861d74001adSXin LI 3862d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 3863d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 3864d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 3865d74001adSXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 3866d74001adSXin LI } 3867d74001adSXin LI i = 0; 3868d74001adSXin LI while(i < 8) { 3869d74001adSXin LI *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 3870d74001adSXin LI /* 8 bytes firm_model, 15, 60-67*/ 3871d74001adSXin LI acb_firm_model++; 3872d74001adSXin LI i++; 3873d74001adSXin LI } 3874d74001adSXin LI i = 0; 3875d74001adSXin LI while(i < 16) { 3876d74001adSXin LI *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 3877d74001adSXin LI /* 16 bytes firm_version, 17, 68-83*/ 3878d74001adSXin LI acb_firm_version++; 3879d74001adSXin LI i++; 3880d74001adSXin LI } 3881d74001adSXin LI i = 0; 3882d74001adSXin LI while(i < 16) { 3883d74001adSXin LI *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 3884d74001adSXin LI acb_device_map++; 3885d74001adSXin LI i++; 3886d74001adSXin LI } 38871e7d660aSXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 3888d74001adSXin LI acb->firm_request_len = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3889d74001adSXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3890d74001adSXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3891d74001adSXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3892d74001adSXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3893abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD) 3894abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1; 3895abfdbca9SXin LI else 3896abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 389744f05562SScott Long } 389844f05562SScott Long /* 389944f05562SScott Long ********************************************************************** 390044f05562SScott Long ********************************************************************** 390144f05562SScott Long */ 39027a7bc959SXin LI static void arcmsr_get_hbd_config(struct AdapterControlBlock *acb) 39037a7bc959SXin LI { 39047a7bc959SXin LI char *acb_firm_model = acb->firm_model; 39057a7bc959SXin LI char *acb_firm_version = acb->firm_version; 39067a7bc959SXin LI char *acb_device_map = acb->device_map; 39077a7bc959SXin LI size_t iop_firm_model = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 39087a7bc959SXin LI size_t iop_firm_version = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 39097a7bc959SXin LI size_t iop_device_map = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 39107a7bc959SXin LI int i; 39117a7bc959SXin LI 39127a7bc959SXin LI if(CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) 39137a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR); 39147a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 39157a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 39167a7bc959SXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 39177a7bc959SXin LI } 39187a7bc959SXin LI i = 0; 39197a7bc959SXin LI while(i < 8) { 39207a7bc959SXin LI *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 39217a7bc959SXin LI /* 8 bytes firm_model, 15, 60-67*/ 39227a7bc959SXin LI acb_firm_model++; 39237a7bc959SXin LI i++; 39247a7bc959SXin LI } 39257a7bc959SXin LI i = 0; 39267a7bc959SXin LI while(i < 16) { 39277a7bc959SXin LI *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 39287a7bc959SXin LI /* 16 bytes firm_version, 17, 68-83*/ 39297a7bc959SXin LI acb_firm_version++; 39307a7bc959SXin LI i++; 39317a7bc959SXin LI } 39327a7bc959SXin LI i = 0; 39337a7bc959SXin LI while(i < 16) { 39347a7bc959SXin LI *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 39357a7bc959SXin LI acb_device_map++; 39367a7bc959SXin LI i++; 39377a7bc959SXin LI } 39381e7d660aSXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 3939b23a1998SXin LI acb->firm_request_len = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3940b23a1998SXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3941b23a1998SXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3942b23a1998SXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 39437a7bc959SXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3944abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_HBD_POSTQUEUE) 3945abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_HBD_POSTQUEUE - 1; 3946abfdbca9SXin LI else 3947abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 39487a7bc959SXin LI } 39497a7bc959SXin LI /* 39507a7bc959SXin LI ********************************************************************** 39517a7bc959SXin LI ********************************************************************** 39527a7bc959SXin LI */ 3953a1103e04SXin LI static void arcmsr_get_hbe_config(struct AdapterControlBlock *acb) 3954a1103e04SXin LI { 3955a1103e04SXin LI char *acb_firm_model = acb->firm_model; 3956a1103e04SXin LI char *acb_firm_version = acb->firm_version; 3957a1103e04SXin LI char *acb_device_map = acb->device_map; 3958a1103e04SXin LI size_t iop_firm_model = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3959a1103e04SXin LI size_t iop_firm_version = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3960a1103e04SXin LI size_t iop_device_map = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 3961a1103e04SXin LI int i; 3962a1103e04SXin LI 3963a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 3964a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 3965a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 3966a1103e04SXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) { 3967a1103e04SXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 3968a1103e04SXin LI } 3969a1103e04SXin LI 3970a1103e04SXin LI i = 0; 3971a1103e04SXin LI while(i < 8) { 3972a1103e04SXin LI *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 3973a1103e04SXin LI /* 8 bytes firm_model, 15, 60-67*/ 3974a1103e04SXin LI acb_firm_model++; 3975a1103e04SXin LI i++; 3976a1103e04SXin LI } 3977a1103e04SXin LI i = 0; 3978a1103e04SXin LI while(i < 16) { 3979a1103e04SXin LI *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 3980a1103e04SXin LI /* 16 bytes firm_version, 17, 68-83*/ 3981a1103e04SXin LI acb_firm_version++; 3982a1103e04SXin LI i++; 3983a1103e04SXin LI } 3984a1103e04SXin LI i = 0; 3985a1103e04SXin LI while(i < 16) { 3986a1103e04SXin LI *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 3987a1103e04SXin LI acb_device_map++; 3988a1103e04SXin LI i++; 3989a1103e04SXin LI } 3990a1103e04SXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 3991a1103e04SXin LI acb->firm_request_len = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3992a1103e04SXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3993a1103e04SXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3994a1103e04SXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3995a1103e04SXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3996a1103e04SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD) 3997a1103e04SXin LI acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1; 3998a1103e04SXin LI else 3999a1103e04SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 4000a1103e04SXin LI } 4001a1103e04SXin LI /* 4002a1103e04SXin LI ********************************************************************** 4003a1103e04SXin LI ********************************************************************** 4004a1103e04SXin LI */ 4005fa42a0bfSXin LI static void arcmsr_get_hbf_config(struct AdapterControlBlock *acb) 4006fa42a0bfSXin LI { 4007fa42a0bfSXin LI u_int32_t *acb_firm_model = (u_int32_t *)acb->firm_model; 4008fa42a0bfSXin LI u_int32_t *acb_firm_version = (u_int32_t *)acb->firm_version; 4009fa42a0bfSXin LI u_int32_t *acb_device_map = (u_int32_t *)acb->device_map; 4010fa42a0bfSXin LI size_t iop_firm_model = ARCMSR_FW_MODEL_OFFSET; /*firm_model,15,60-67*/ 4011fa42a0bfSXin LI size_t iop_firm_version = ARCMSR_FW_VERS_OFFSET; /*firm_version,17,68-83*/ 4012fa42a0bfSXin LI size_t iop_device_map = ARCMSR_FW_DEVMAP_OFFSET; 4013fa42a0bfSXin LI int i; 4014fa42a0bfSXin LI 4015fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 4016fa42a0bfSXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 4017fa42a0bfSXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 4018fa42a0bfSXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) 4019fa42a0bfSXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 4020fa42a0bfSXin LI 4021fa42a0bfSXin LI i = 0; 4022fa42a0bfSXin LI while(i < 2) { 4023fa42a0bfSXin LI *acb_firm_model = acb->msgcode_rwbuffer[iop_firm_model]; 4024fa42a0bfSXin LI /* 8 bytes firm_model, 15, 60-67*/ 4025fa42a0bfSXin LI acb_firm_model++; 4026fa42a0bfSXin LI iop_firm_model++; 4027fa42a0bfSXin LI i++; 4028fa42a0bfSXin LI } 4029fa42a0bfSXin LI i = 0; 4030fa42a0bfSXin LI while(i < 4) { 4031fa42a0bfSXin LI *acb_firm_version = acb->msgcode_rwbuffer[iop_firm_version]; 4032fa42a0bfSXin LI /* 16 bytes firm_version, 17, 68-83*/ 4033fa42a0bfSXin LI acb_firm_version++; 4034fa42a0bfSXin LI iop_firm_version++; 4035fa42a0bfSXin LI i++; 4036fa42a0bfSXin LI } 4037fa42a0bfSXin LI i = 0; 4038fa42a0bfSXin LI while(i < 4) { 4039fa42a0bfSXin LI *acb_device_map = acb->msgcode_rwbuffer[iop_device_map]; 4040fa42a0bfSXin LI acb_device_map++; 4041fa42a0bfSXin LI iop_device_map++; 4042fa42a0bfSXin LI i++; 4043fa42a0bfSXin LI } 4044fa42a0bfSXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 4045fa42a0bfSXin LI acb->firm_request_len = acb->msgcode_rwbuffer[1]; /*firm_request_len, 1, 04-07*/ 4046fa42a0bfSXin LI acb->firm_numbers_queue = acb->msgcode_rwbuffer[2]; /*firm_numbers_queue, 2, 08-11*/ 4047fa42a0bfSXin LI acb->firm_sdram_size = acb->msgcode_rwbuffer[3]; /*firm_sdram_size, 3, 12-15*/ 4048fa42a0bfSXin LI acb->firm_ide_channels = acb->msgcode_rwbuffer[4]; /*firm_ide_channels, 4, 16-19*/ 4049fa42a0bfSXin LI acb->firm_cfg_version = acb->msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]; /*firm_cfg_version, 25*/ 4050fa42a0bfSXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD) 4051fa42a0bfSXin LI acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1; 4052fa42a0bfSXin LI else 4053fa42a0bfSXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 4054fa42a0bfSXin LI } 4055fa42a0bfSXin LI /* 4056fa42a0bfSXin LI ********************************************************************** 4057fa42a0bfSXin LI ********************************************************************** 4058fa42a0bfSXin LI */ 405944f05562SScott Long static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) 406044f05562SScott Long { 406144f05562SScott Long switch (acb->adapter_type) { 4062fa42a0bfSXin LI case ACB_ADAPTER_TYPE_A: 406344f05562SScott Long arcmsr_get_hba_config(acb); 406444f05562SScott Long break; 4065fa42a0bfSXin LI case ACB_ADAPTER_TYPE_B: 406644f05562SScott Long arcmsr_get_hbb_config(acb); 406744f05562SScott Long break; 4068fa42a0bfSXin LI case ACB_ADAPTER_TYPE_C: 4069d74001adSXin LI arcmsr_get_hbc_config(acb); 4070d74001adSXin LI break; 4071fa42a0bfSXin LI case ACB_ADAPTER_TYPE_D: 40727a7bc959SXin LI arcmsr_get_hbd_config(acb); 40737a7bc959SXin LI break; 4074fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 4075a1103e04SXin LI arcmsr_get_hbe_config(acb); 4076fa42a0bfSXin LI break; 4077fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 4078fa42a0bfSXin LI arcmsr_get_hbf_config(acb); 4079a1103e04SXin LI break; 408044f05562SScott Long } 408144f05562SScott Long } 408244f05562SScott Long /* 408344f05562SScott Long ********************************************************************** 408444f05562SScott Long ********************************************************************** 408544f05562SScott Long */ 408644f05562SScott Long static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb) 408744f05562SScott Long { 408844f05562SScott Long int timeout=0; 408944f05562SScott Long 409044f05562SScott Long switch (acb->adapter_type) { 409144f05562SScott Long case ACB_ADAPTER_TYPE_A: { 4092d74001adSXin LI while ((CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) 409344f05562SScott Long { 409444f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 409544f05562SScott Long { 4096d74001adSXin LI printf( "arcmsr%d:timed out waiting for firmware \n", acb->pci_unit); 409744f05562SScott Long return; 409844f05562SScott Long } 409944f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 410044f05562SScott Long } 410144f05562SScott Long } 410244f05562SScott Long break; 410344f05562SScott Long case ACB_ADAPTER_TYPE_B: { 4104b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 4105b23a1998SXin LI while ((READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & ARCMSR_MESSAGE_FIRMWARE_OK) == 0) 410644f05562SScott Long { 410744f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 410844f05562SScott Long { 4109d74001adSXin LI printf( "arcmsr%d: timed out waiting for firmware \n", acb->pci_unit); 411044f05562SScott Long return; 411144f05562SScott Long } 411244f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 411344f05562SScott Long } 4114b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 4115d74001adSXin LI } 4116d74001adSXin LI break; 4117d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 4118d74001adSXin LI while ((CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0) 4119d74001adSXin LI { 4120d74001adSXin LI if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 4121d74001adSXin LI { 4122d74001adSXin LI printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit); 4123d74001adSXin LI return; 4124d74001adSXin LI } 4125d74001adSXin LI UDELAY(15000); /* wait 15 milli-seconds */ 4126d74001adSXin LI } 412744f05562SScott Long } 412844f05562SScott Long break; 41297a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 41307a7bc959SXin LI while ((CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBDMU_MESSAGE_FIRMWARE_OK) == 0) 41317a7bc959SXin LI { 41327a7bc959SXin LI if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 41337a7bc959SXin LI { 41347a7bc959SXin LI printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit); 41357a7bc959SXin LI return; 41367a7bc959SXin LI } 41377a7bc959SXin LI UDELAY(15000); /* wait 15 milli-seconds */ 41387a7bc959SXin LI } 41397a7bc959SXin LI } 41407a7bc959SXin LI break; 4141fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 4142fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 4143a1103e04SXin LI while ((CHIP_REG_READ32(HBE_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBEMU_MESSAGE_FIRMWARE_OK) == 0) 4144a1103e04SXin LI { 4145a1103e04SXin LI if (timeout++ > 4000) /* (4000*15)/1000 = 60 sec */ 4146a1103e04SXin LI { 4147a1103e04SXin LI printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit); 4148a1103e04SXin LI return; 4149a1103e04SXin LI } 4150a1103e04SXin LI UDELAY(15000); /* wait 15 milli-seconds */ 4151a1103e04SXin LI } 4152a1103e04SXin LI } 4153a1103e04SXin LI break; 415444f05562SScott Long } 415544f05562SScott Long } 415644f05562SScott Long /* 415744f05562SScott Long ********************************************************************** 415844f05562SScott Long ********************************************************************** 415944f05562SScott Long */ 416044f05562SScott Long static void arcmsr_clear_doorbell_queue_buffer( struct AdapterControlBlock *acb) 416144f05562SScott Long { 4162d74001adSXin LI u_int32_t outbound_doorbell; 4163d74001adSXin LI 416444f05562SScott Long switch (acb->adapter_type) { 416544f05562SScott Long case ACB_ADAPTER_TYPE_A: { 416644f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 4167d74001adSXin LI outbound_doorbell = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell); 4168d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, outbound_doorbell); /*clear doorbell interrupt */ 4169d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 417044f05562SScott Long } 417144f05562SScott Long break; 417244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 4173b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 4174fc5ef1caSXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN);/*clear interrupt and message state*/ 4175b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 417644f05562SScott Long /* let IOP know data has been read */ 417744f05562SScott Long } 417844f05562SScott Long break; 4179d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 4180d74001adSXin LI /* empty doorbell Qbuffer if door bell ringed */ 4181d74001adSXin LI outbound_doorbell = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); 4182d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell); /*clear doorbell interrupt */ 4183d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK); 41847a7bc959SXin LI CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell_clear); /* Dummy read to force pci flush */ 41857a7bc959SXin LI CHIP_REG_READ32(HBC_MessageUnit, 0, inbound_doorbell); /* Dummy read to force pci flush */ 41867a7bc959SXin LI } 41877a7bc959SXin LI break; 41887a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 41897a7bc959SXin LI /* empty doorbell Qbuffer if door bell ringed */ 41907a7bc959SXin LI outbound_doorbell = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell); 41917a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, outbound_doorbell); /*clear doorbell interrupt */ 41927a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ); 4193d74001adSXin LI } 4194d74001adSXin LI break; 4195fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 4196fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 4197a1103e04SXin LI /* empty doorbell Qbuffer if door bell ringed */ 4198a1103e04SXin LI acb->in_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell); 4199a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /*clear doorbell interrupt */ 4200a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK; 4201a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 4202a1103e04SXin LI } 4203a1103e04SXin LI break; 420444f05562SScott Long } 420544f05562SScott Long } 420644f05562SScott Long /* 420744f05562SScott Long ************************************************************************ 420844f05562SScott Long ************************************************************************ 420944f05562SScott Long */ 421044f05562SScott Long static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb) 421144f05562SScott Long { 421244f05562SScott Long unsigned long srb_phyaddr; 421344f05562SScott Long u_int32_t srb_phyaddr_hi32; 42147a7bc959SXin LI u_int32_t srb_phyaddr_lo32; 421544f05562SScott Long 421644f05562SScott Long /* 421744f05562SScott Long ******************************************************************** 421844f05562SScott Long ** here we need to tell iop 331 our freesrb.HighPart 421944f05562SScott Long ** if freesrb.HighPart is not zero 422044f05562SScott Long ******************************************************************** 422144f05562SScott Long */ 4222d74001adSXin LI srb_phyaddr = (unsigned long) acb->srb_phyaddr.phyaddr; 4223d74001adSXin LI srb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high; 42247a7bc959SXin LI srb_phyaddr_lo32 = acb->srb_phyaddr.B.phyadd_low; 422544f05562SScott Long switch (acb->adapter_type) { 422644f05562SScott Long case ACB_ADAPTER_TYPE_A: { 422744f05562SScott Long if(srb_phyaddr_hi32 != 0) { 4228d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 4229d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 4230d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 423144f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 4232d74001adSXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 423344f05562SScott Long return FALSE; 423444f05562SScott Long } 423544f05562SScott Long } 423644f05562SScott Long } 423744f05562SScott Long break; 423844f05562SScott Long /* 423944f05562SScott Long *********************************************************************** 424044f05562SScott Long ** if adapter type B, set window of "post command Q" 424144f05562SScott Long *********************************************************************** 424244f05562SScott Long */ 424344f05562SScott Long case ACB_ADAPTER_TYPE_B: { 424444f05562SScott Long u_int32_t post_queue_phyaddr; 424544f05562SScott Long struct HBB_MessageUnit *phbbmu; 424644f05562SScott Long 424744f05562SScott Long phbbmu = (struct HBB_MessageUnit *)acb->pmu; 424844f05562SScott Long phbbmu->postq_index = 0; 424944f05562SScott Long phbbmu->doneq_index = 0; 4250b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_SET_POST_WINDOW); 425144f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 4252d74001adSXin LI printf( "arcmsr%d: 'set window of post command Q' timeout\n", acb->pci_unit); 425344f05562SScott Long return FALSE; 425444f05562SScott Long } 425522f2616bSXin LI post_queue_phyaddr = srb_phyaddr + ARCMSR_SRBS_POOL_SIZE 425644f05562SScott Long + offsetof(struct HBB_MessageUnit, post_qbuffer); 4257d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */ 4258d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1], srb_phyaddr_hi32); /* normal should be zero */ 4259d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ size (256+8)*4 */ 4260d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3], post_queue_phyaddr+1056); /* doneQ size (256+8)*4 */ 4261d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4], 1056); /* srb maxQ size must be --> [(256+8)*4] */ 4262b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_SET_CONFIG); 426344f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 426444f05562SScott Long printf( "arcmsr%d: 'set command Q window' timeout \n", acb->pci_unit); 426544f05562SScott Long return FALSE; 426644f05562SScott Long } 4267b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_START_DRIVER_MODE); 426844f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 426944f05562SScott Long printf( "arcmsr%d: 'start diver mode' timeout \n", acb->pci_unit); 427044f05562SScott Long return FALSE; 427144f05562SScott Long } 427244f05562SScott Long } 427344f05562SScott Long break; 4274d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 4275d74001adSXin LI if(srb_phyaddr_hi32 != 0) { 4276d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 4277d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 4278d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 4279d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 4280d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 4281d74001adSXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 4282d74001adSXin LI return FALSE; 4283d74001adSXin LI } 4284d74001adSXin LI } 4285d74001adSXin LI } 4286d74001adSXin LI break; 42877a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 42887a7bc959SXin LI u_int32_t post_queue_phyaddr, done_queue_phyaddr; 42897a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu; 42907a7bc959SXin LI 42917a7bc959SXin LI phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 42927a7bc959SXin LI phbdmu->postq_index = 0; 42937a7bc959SXin LI phbdmu->doneq_index = 0x40FF; 42947a7bc959SXin LI post_queue_phyaddr = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE 42957a7bc959SXin LI + offsetof(struct HBD_MessageUnit0, post_qbuffer); 42967a7bc959SXin LI done_queue_phyaddr = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE 42977a7bc959SXin LI + offsetof(struct HBD_MessageUnit0, done_qbuffer); 42987a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */ 42997a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 43007a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ base */ 43017a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[3], done_queue_phyaddr); /* doneQ base */ 43027a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[4], 0x100); 43037a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 43047a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 43057a7bc959SXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 43067a7bc959SXin LI return FALSE; 43077a7bc959SXin LI } 43087a7bc959SXin LI } 43097a7bc959SXin LI break; 4310a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 4311a1103e04SXin LI u_int32_t cdb_phyaddr_lo32; 4312a1103e04SXin LI cdb_phyaddr_lo32 = srb_phyaddr_lo32 + offsetof(struct CommandControlBlock, arcmsr_cdb); 4313a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 4314a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[1], ARCMSR_SIGNATURE_1884); 4315a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[2], cdb_phyaddr_lo32); 4316a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[3], srb_phyaddr_hi32); 4317a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[4], SRB_SIZE); 4318a1103e04SXin LI cdb_phyaddr_lo32 = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE; 4319a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[5], cdb_phyaddr_lo32); 4320a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[6], srb_phyaddr_hi32); 4321a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[7], COMPLETION_Q_POOL_SIZE); 4322a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 4323a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 4324a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 4325a1103e04SXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) { 4326a1103e04SXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 4327a1103e04SXin LI return FALSE; 4328a1103e04SXin LI } 4329a1103e04SXin LI } 4330a1103e04SXin LI break; 4331fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 4332fa42a0bfSXin LI u_int32_t cdb_phyaddr_lo32; 4333fa42a0bfSXin LI cdb_phyaddr_lo32 = srb_phyaddr_lo32 + offsetof(struct CommandControlBlock, arcmsr_cdb); 4334fa42a0bfSXin LI acb->msgcode_rwbuffer[0] = ARCMSR_SIGNATURE_SET_CONFIG; 4335fa42a0bfSXin LI acb->msgcode_rwbuffer[1] = ARCMSR_SIGNATURE_1886; 4336fa42a0bfSXin LI acb->msgcode_rwbuffer[2] = cdb_phyaddr_lo32; 4337fa42a0bfSXin LI acb->msgcode_rwbuffer[3] = srb_phyaddr_hi32; 4338fa42a0bfSXin LI acb->msgcode_rwbuffer[4] = SRB_SIZE; 4339fa42a0bfSXin LI cdb_phyaddr_lo32 = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE; 4340fa42a0bfSXin LI acb->msgcode_rwbuffer[5] = cdb_phyaddr_lo32; 4341fa42a0bfSXin LI acb->msgcode_rwbuffer[6] = srb_phyaddr_hi32; 4342fa42a0bfSXin LI acb->msgcode_rwbuffer[7] = COMPLETION_Q_POOL_SIZE; 4343fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 4344fa42a0bfSXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 4345fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 4346fa42a0bfSXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) { 4347fa42a0bfSXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 4348fa42a0bfSXin LI return FALSE; 4349fa42a0bfSXin LI } 4350fa42a0bfSXin LI } 4351fa42a0bfSXin LI break; 435244f05562SScott Long } 4353dac36688SXin LI return (TRUE); 435444f05562SScott Long } 435544f05562SScott Long /* 435644f05562SScott Long ************************************************************************ 435744f05562SScott Long ************************************************************************ 435844f05562SScott Long */ 435944f05562SScott Long static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb) 436044f05562SScott Long { 4361a1103e04SXin LI if (acb->adapter_type == ACB_ADAPTER_TYPE_B) 436244f05562SScott Long { 4363b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 4364b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_ACTIVE_EOI_MODE); 436544f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 4366d74001adSXin LI printf( "arcmsr%d: 'iop enable eoi mode' timeout \n", acb->pci_unit); 436744f05562SScott Long return; 436844f05562SScott Long } 436944f05562SScott Long } 437044f05562SScott Long } 437144f05562SScott Long /* 437244f05562SScott Long ********************************************************************** 4373ad6d6297SScott Long ********************************************************************** 4374ad6d6297SScott Long */ 4375ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb) 4376ad6d6297SScott Long { 437744f05562SScott Long u_int32_t intmask_org; 4378ad6d6297SScott Long 437944f05562SScott Long /* disable all outbound interrupt */ 438044f05562SScott Long intmask_org = arcmsr_disable_allintr(acb); 438144f05562SScott Long arcmsr_wait_firmware_ready(acb); 438244f05562SScott Long arcmsr_iop_confirm(acb); 4383ad6d6297SScott Long arcmsr_get_firmware_spec(acb); 438444f05562SScott Long /*start background rebuild*/ 4385ad6d6297SScott Long arcmsr_start_adapter_bgrb(acb); 438644f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 438744f05562SScott Long arcmsr_clear_doorbell_queue_buffer(acb); 438844f05562SScott Long arcmsr_enable_eoi_mode(acb); 438944f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 439044f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 4391ad6d6297SScott Long acb->acb_flags |= ACB_F_IOP_INITED; 4392ad6d6297SScott Long } 4393ad6d6297SScott Long /* 4394ad6d6297SScott Long ********************************************************************** 4395f1c579b1SScott Long ********************************************************************** 4396f1c579b1SScott Long */ 4397231c8b71SXin LI static void arcmsr_map_free_srb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 4398f1c579b1SScott Long { 4399ad6d6297SScott Long struct AdapterControlBlock *acb = arg; 4400ad6d6297SScott Long struct CommandControlBlock *srb_tmp; 440144f05562SScott Long u_int32_t i; 4402ad6d6297SScott Long unsigned long srb_phyaddr = (unsigned long)segs->ds_addr; 4403f1c579b1SScott Long 4404d74001adSXin LI acb->srb_phyaddr.phyaddr = srb_phyaddr; 44057a7bc959SXin LI srb_tmp = (struct CommandControlBlock *)acb->uncacheptr; 4406ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 440744f05562SScott Long if(bus_dmamap_create(acb->dm_segs_dmat, 440844f05562SScott Long /*flags*/0, &srb_tmp->dm_segs_dmamap) != 0) { 4409ad6d6297SScott Long acb->acb_flags |= ACB_F_MAPFREESRB_FAILD; 441044f05562SScott Long printf("arcmsr%d:" 441144f05562SScott Long " srb dmamap bus_dmamap_create error\n", acb->pci_unit); 4412ad6d6297SScott Long return; 4413ad6d6297SScott Long } 4414a1103e04SXin LI if((acb->adapter_type == ACB_ADAPTER_TYPE_C) || (acb->adapter_type == ACB_ADAPTER_TYPE_D) 4415fa42a0bfSXin LI || (acb->adapter_type == ACB_ADAPTER_TYPE_E) || (acb->adapter_type == ACB_ADAPTER_TYPE_F)) 44167a7bc959SXin LI { 44177a7bc959SXin LI srb_tmp->cdb_phyaddr_low = srb_phyaddr; 44187a7bc959SXin LI srb_tmp->cdb_phyaddr_high = (u_int32_t)((srb_phyaddr >> 16) >> 16); 44197a7bc959SXin LI } 44207a7bc959SXin LI else 44217a7bc959SXin LI srb_tmp->cdb_phyaddr_low = srb_phyaddr >> 5; 4422ad6d6297SScott Long srb_tmp->acb = acb; 4423a1103e04SXin LI srb_tmp->smid = i << 16; 4424ad6d6297SScott Long acb->srbworkingQ[i] = acb->psrb_pool[i] = srb_tmp; 442522f2616bSXin LI srb_phyaddr = srb_phyaddr + SRB_SIZE; 442622f2616bSXin LI srb_tmp = (struct CommandControlBlock *)((unsigned long)srb_tmp + SRB_SIZE); 4427ad6d6297SScott Long } 4428fc5ef1caSXin LI if (acb->adapter_type == ACB_ADAPTER_TYPE_E) 4429a1103e04SXin LI acb->pCompletionQ = (pCompletion_Q)srb_tmp; 4430fa42a0bfSXin LI else if (acb->adapter_type == ACB_ADAPTER_TYPE_F) { 4431fa42a0bfSXin LI acb->pCompletionQ = (pCompletion_Q)srb_tmp; 4432fa42a0bfSXin LI acb->completeQ_phys = srb_phyaddr; 4433fa42a0bfSXin LI memset(acb->pCompletionQ, 0xff, COMPLETION_Q_POOL_SIZE); 4434fa42a0bfSXin LI acb->message_wbuffer = (u_int32_t *)((unsigned long)acb->pCompletionQ + COMPLETION_Q_POOL_SIZE); 4435fa42a0bfSXin LI acb->message_rbuffer = (u_int32_t *)((unsigned long)acb->message_wbuffer + 0x100); 4436fa42a0bfSXin LI acb->msgcode_rwbuffer = (u_int32_t *)((unsigned long)acb->message_wbuffer + 0x200); 4437fa42a0bfSXin LI memset((void *)acb->message_wbuffer, 0, MESG_RW_BUFFER_SIZE); 4438fa42a0bfSXin LI } 4439ad6d6297SScott Long acb->vir2phy_offset = (unsigned long)srb_tmp - (unsigned long)srb_phyaddr; 4440f1c579b1SScott Long } 4441f1c579b1SScott Long /* 4442f1c579b1SScott Long ************************************************************************ 4443f1c579b1SScott Long ************************************************************************ 4444f1c579b1SScott Long */ 4445ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb) 4446f1c579b1SScott Long { 4447f1c579b1SScott Long /* remove the control device */ 4448ad6d6297SScott Long if(acb->ioctl_dev != NULL) { 4449ad6d6297SScott Long destroy_dev(acb->ioctl_dev); 4450f1c579b1SScott Long } 4451ad6d6297SScott Long bus_dmamap_unload(acb->srb_dmat, acb->srb_dmamap); 4452ad6d6297SScott Long bus_dmamap_destroy(acb->srb_dmat, acb->srb_dmamap); 4453ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 4454ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 4455ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 4456f1c579b1SScott Long } 4457f1c579b1SScott Long /* 4458f1c579b1SScott Long ************************************************************************ 4459f1c579b1SScott Long ************************************************************************ 4460f1c579b1SScott Long */ 44617a7bc959SXin LI static void arcmsr_mutex_init(struct AdapterControlBlock *acb) 44627a7bc959SXin LI { 44637a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->isr_lock, "arcmsr isr lock"); 44647a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->srb_lock, "arcmsr srb lock"); 44657a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->postDone_lock, "arcmsr postQ lock"); 44667a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->qbuffer_lock, "arcmsr RW buffer lock"); 44677a7bc959SXin LI } 44687a7bc959SXin LI /* 44697a7bc959SXin LI ************************************************************************ 44707a7bc959SXin LI ************************************************************************ 44717a7bc959SXin LI */ 44727a7bc959SXin LI static void arcmsr_mutex_destroy(struct AdapterControlBlock *acb) 44737a7bc959SXin LI { 44747a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 44757a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->postDone_lock); 44767a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->srb_lock); 44777a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->isr_lock); 44787a7bc959SXin LI } 44797a7bc959SXin LI /* 44807a7bc959SXin LI ************************************************************************ 44817a7bc959SXin LI ************************************************************************ 44827a7bc959SXin LI */ 4483ad6d6297SScott Long static u_int32_t arcmsr_initialize(device_t dev) 4484f1c579b1SScott Long { 4485ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 4486ad6d6297SScott Long u_int16_t pci_command; 448744f05562SScott Long int i, j,max_coherent_size; 4488dac36688SXin LI u_int32_t vendor_dev_id; 4489f1c579b1SScott Long 4490dac36688SXin LI vendor_dev_id = pci_get_devid(dev); 4491dac36688SXin LI acb->vendor_device_id = vendor_dev_id; 4492224a78aeSXin LI acb->sub_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2); 4493dac36688SXin LI switch (vendor_dev_id) { 4494dac36688SXin LI case PCIDevVenIDARC1880: 4495dac36688SXin LI case PCIDevVenIDARC1882: 4496dac36688SXin LI case PCIDevVenIDARC1213: 4497dac36688SXin LI case PCIDevVenIDARC1223: { 4498d74001adSXin LI acb->adapter_type = ACB_ADAPTER_TYPE_C; 4499fc5ef1caSXin LI if ((acb->sub_device_id == ARECA_SUB_DEV_ID_1883) || 4500fc5ef1caSXin LI (acb->sub_device_id == ARECA_SUB_DEV_ID_1216) || 4501fc5ef1caSXin LI (acb->sub_device_id == ARECA_SUB_DEV_ID_1226)) 4502224a78aeSXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_12G; 4503224a78aeSXin LI else 4504dac36688SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_6G; 4505d74001adSXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE; 4506d74001adSXin LI } 4507d74001adSXin LI break; 4508a1103e04SXin LI case PCIDevVenIDARC1884: 4509a1103e04SXin LI acb->adapter_type = ACB_ADAPTER_TYPE_E; 4510a1103e04SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_12G; 4511a1103e04SXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + COMPLETION_Q_POOL_SIZE; 4512a1103e04SXin LI acb->completionQ_entry = COMPLETION_Q_POOL_SIZE / sizeof(struct deliver_completeQ); 4513a1103e04SXin LI break; 4514fa42a0bfSXin LI case PCIDevVenIDARC1886_: 4515fa42a0bfSXin LI case PCIDevVenIDARC1886: 4516fa42a0bfSXin LI acb->adapter_type = ACB_ADAPTER_TYPE_F; 4517fa42a0bfSXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_12G; 4518fa42a0bfSXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + COMPLETION_Q_POOL_SIZE + MESG_RW_BUFFER_SIZE; 4519fa42a0bfSXin LI acb->completionQ_entry = COMPLETION_Q_POOL_SIZE / sizeof(struct deliver_completeQ); 4520fa42a0bfSXin LI break; 45217a7bc959SXin LI case PCIDevVenIDARC1214: { 45227a7bc959SXin LI acb->adapter_type = ACB_ADAPTER_TYPE_D; 45237a7bc959SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_6G; 45247a7bc959SXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBD_MessageUnit0)); 45257a7bc959SXin LI } 45267a7bc959SXin LI break; 4527231c8b71SXin LI case PCIDevVenIDARC1200: 452844f05562SScott Long case PCIDevVenIDARC1201: { 452944f05562SScott Long acb->adapter_type = ACB_ADAPTER_TYPE_B; 4530dac36688SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_3G; 4531d74001adSXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBB_MessageUnit)); 453244f05562SScott Long } 453344f05562SScott Long break; 4534b23a1998SXin LI case PCIDevVenIDARC1203: { 4535b23a1998SXin LI acb->adapter_type = ACB_ADAPTER_TYPE_B; 4536b23a1998SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_6G; 4537b23a1998SXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBB_MessageUnit)); 4538b23a1998SXin LI } 4539b23a1998SXin LI break; 454044f05562SScott Long case PCIDevVenIDARC1110: 454144f05562SScott Long case PCIDevVenIDARC1120: 454244f05562SScott Long case PCIDevVenIDARC1130: 454344f05562SScott Long case PCIDevVenIDARC1160: 454444f05562SScott Long case PCIDevVenIDARC1170: 454544f05562SScott Long case PCIDevVenIDARC1210: 454644f05562SScott Long case PCIDevVenIDARC1220: 454744f05562SScott Long case PCIDevVenIDARC1230: 4548231c8b71SXin LI case PCIDevVenIDARC1231: 454944f05562SScott Long case PCIDevVenIDARC1260: 4550231c8b71SXin LI case PCIDevVenIDARC1261: 455144f05562SScott Long case PCIDevVenIDARC1270: 455244f05562SScott Long case PCIDevVenIDARC1280: 4553d74001adSXin LI case PCIDevVenIDARC1212: 4554d74001adSXin LI case PCIDevVenIDARC1222: 455544f05562SScott Long case PCIDevVenIDARC1380: 455644f05562SScott Long case PCIDevVenIDARC1381: 455744f05562SScott Long case PCIDevVenIDARC1680: 455844f05562SScott Long case PCIDevVenIDARC1681: { 455944f05562SScott Long acb->adapter_type = ACB_ADAPTER_TYPE_A; 4560dac36688SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_3G; 456144f05562SScott Long max_coherent_size = ARCMSR_SRBS_POOL_SIZE; 456244f05562SScott Long } 456344f05562SScott Long break; 456444f05562SScott Long default: { 456544f05562SScott Long printf("arcmsr%d:" 456644f05562SScott Long " unknown RAID adapter type \n", device_get_unit(dev)); 456744f05562SScott Long return ENOMEM; 456844f05562SScott Long } 456944f05562SScott Long } 4570b6f97155SScott Long if(bus_dma_tag_create( /*PCI parent*/ bus_get_dma_tag(dev), 4571f1c579b1SScott Long /*alignemnt*/ 1, 4572f1c579b1SScott Long /*boundary*/ 0, 4573701d9f1fSScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 4574f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 4575f1c579b1SScott Long /*filter*/ NULL, 4576f1c579b1SScott Long /*filterarg*/ NULL, 4577f1c579b1SScott Long /*maxsize*/ BUS_SPACE_MAXSIZE_32BIT, 4578f1c579b1SScott Long /*nsegments*/ BUS_SPACE_UNRESTRICTED, 4579f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 4580f1c579b1SScott Long /*flags*/ 0, 4581f1c579b1SScott Long /*lockfunc*/ NULL, 4582f1c579b1SScott Long /*lockarg*/ NULL, 4583231c8b71SXin LI &acb->parent_dmat) != 0) 4584f1c579b1SScott Long { 458544f05562SScott Long printf("arcmsr%d: parent_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 4586f1c579b1SScott Long return ENOMEM; 4587f1c579b1SScott Long } 4588231c8b71SXin LI 4589f1c579b1SScott Long /* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */ 4590ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 4591f1c579b1SScott Long /*alignment*/ 1, 4592f1c579b1SScott Long /*boundary*/ 0, 459322f2616bSXin LI #ifdef PAE 459422f2616bSXin LI /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 459522f2616bSXin LI #else 4596f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 459722f2616bSXin LI #endif 4598f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 4599f1c579b1SScott Long /*filter*/ NULL, 4600f1c579b1SScott Long /*filterarg*/ NULL, 4601231c8b71SXin LI /*maxsize*/ ARCMSR_MAX_SG_ENTRIES * PAGE_SIZE * ARCMSR_MAX_FREESRB_NUM, 4602f1c579b1SScott Long /*nsegments*/ ARCMSR_MAX_SG_ENTRIES, 4603f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 4604ad6d6297SScott Long /*flags*/ 0, 4605f1c579b1SScott Long /*lockfunc*/ busdma_lock_mutex, 46067a7bc959SXin LI /*lockarg*/ &acb->isr_lock, 4607231c8b71SXin LI &acb->dm_segs_dmat) != 0) 4608f1c579b1SScott Long { 4609ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 461044f05562SScott Long printf("arcmsr%d: dm_segs_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 4611f1c579b1SScott Long return ENOMEM; 4612f1c579b1SScott Long } 4613231c8b71SXin LI 4614ad6d6297SScott Long /* DMA tag for our srb structures.... Allocate the freesrb memory */ 4615ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 461644f05562SScott Long /*alignment*/ 0x20, 4617f1c579b1SScott Long /*boundary*/ 0, 4618f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 4619f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 4620f1c579b1SScott Long /*filter*/ NULL, 4621f1c579b1SScott Long /*filterarg*/ NULL, 462244f05562SScott Long /*maxsize*/ max_coherent_size, 4623f1c579b1SScott Long /*nsegments*/ 1, 4624f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 4625701d9f1fSScott Long /*flags*/ 0, 4626f1c579b1SScott Long /*lockfunc*/ NULL, 4627f1c579b1SScott Long /*lockarg*/ NULL, 4628231c8b71SXin LI &acb->srb_dmat) != 0) 4629f1c579b1SScott Long { 4630ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 4631ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 463244f05562SScott Long printf("arcmsr%d: srb_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 4633f1c579b1SScott Long return ENXIO; 4634f1c579b1SScott Long } 4635f1c579b1SScott Long /* Allocation for our srbs */ 4636d74001adSXin LI if(bus_dmamem_alloc(acb->srb_dmat, (void **)&acb->uncacheptr, BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &acb->srb_dmamap) != 0) { 4637ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 4638ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 4639ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 464044f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamem_alloc failure!\n", device_get_unit(dev)); 4641f1c579b1SScott Long return ENXIO; 4642f1c579b1SScott Long } 4643f1c579b1SScott Long /* And permanently map them */ 4644231c8b71SXin LI if(bus_dmamap_load(acb->srb_dmat, acb->srb_dmamap, acb->uncacheptr, max_coherent_size, arcmsr_map_free_srb, acb, /*flags*/0)) { 4645ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 4646ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 4647ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 464844f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamap_load failure!\n", device_get_unit(dev)); 4649f1c579b1SScott Long return ENXIO; 4650f1c579b1SScott Long } 4651f1c579b1SScott Long pci_command = pci_read_config(dev, PCIR_COMMAND, 2); 4652f1c579b1SScott Long pci_command |= PCIM_CMD_BUSMASTEREN; 4653f1c579b1SScott Long pci_command |= PCIM_CMD_PERRESPEN; 4654f1c579b1SScott Long pci_command |= PCIM_CMD_MWRICEN; 4655c68534f1SScott Long /* Enable Busmaster */ 4656f1c579b1SScott Long pci_write_config(dev, PCIR_COMMAND, pci_command, 2); 465744f05562SScott Long switch(acb->adapter_type) { 465844f05562SScott Long case ACB_ADAPTER_TYPE_A: { 465944f05562SScott Long u_int32_t rid0 = PCIR_BAR(0); 466044f05562SScott Long vm_offset_t mem_base0; 466144f05562SScott Long 4662eff83876SJustin Hibbits acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid0, RF_ACTIVE); 466344f05562SScott Long if(acb->sys_res_arcmsr[0] == NULL) { 4664ad6d6297SScott Long arcmsr_free_resource(acb); 4665d74001adSXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 4666f1c579b1SScott Long return ENOMEM; 4667f1c579b1SScott Long } 466844f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 4669ad6d6297SScott Long arcmsr_free_resource(acb); 4670d74001adSXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 4671f1c579b1SScott Long return ENXIO; 4672f1c579b1SScott Long } 467344f05562SScott Long mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 467444f05562SScott Long if(mem_base0 == 0) { 4675ad6d6297SScott Long arcmsr_free_resource(acb); 4676d74001adSXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 4677f1c579b1SScott Long return ENXIO; 4678f1c579b1SScott Long } 467944f05562SScott Long acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 468044f05562SScott Long acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 468144f05562SScott Long acb->pmu = (struct MessageUnit_UNION *)mem_base0; 4682fc5ef1caSXin LI acb->rid[0] = rid0; 468344f05562SScott Long } 468444f05562SScott Long break; 468544f05562SScott Long case ACB_ADAPTER_TYPE_B: { 468644f05562SScott Long struct HBB_MessageUnit *phbbmu; 468744f05562SScott Long struct CommandControlBlock *freesrb; 468844f05562SScott Long u_int32_t rid[]={ PCIR_BAR(0), PCIR_BAR(2) }; 468944f05562SScott Long vm_offset_t mem_base[]={0,0}; 469044f05562SScott Long for(i=0; i < 2; i++) { 4691fc5ef1caSXin LI acb->sys_res_arcmsr[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid[i], RF_ACTIVE); 469244f05562SScott Long if(acb->sys_res_arcmsr[i] == NULL) { 469344f05562SScott Long arcmsr_free_resource(acb); 4694d74001adSXin LI printf("arcmsr%d: bus_alloc_resource %d failure!\n", device_get_unit(dev), i); 469544f05562SScott Long return ENOMEM; 469644f05562SScott Long } 469744f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[i]) <= 0) { 469844f05562SScott Long arcmsr_free_resource(acb); 4699d74001adSXin LI printf("arcmsr%d: rman_get_start %d failure!\n", device_get_unit(dev), i); 470044f05562SScott Long return ENXIO; 470144f05562SScott Long } 470244f05562SScott Long mem_base[i] = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[i]); 470344f05562SScott Long if(mem_base[i] == 0) { 470444f05562SScott Long arcmsr_free_resource(acb); 4705d74001adSXin LI printf("arcmsr%d: rman_get_virtual %d failure!\n", device_get_unit(dev), i); 470644f05562SScott Long return ENXIO; 470744f05562SScott Long } 470844f05562SScott Long acb->btag[i] = rman_get_bustag(acb->sys_res_arcmsr[i]); 470944f05562SScott Long acb->bhandle[i] = rman_get_bushandle(acb->sys_res_arcmsr[i]); 471044f05562SScott Long } 471144f05562SScott Long freesrb = (struct CommandControlBlock *)acb->uncacheptr; 471222f2616bSXin LI acb->pmu = (struct MessageUnit_UNION *)((unsigned long)freesrb+ARCMSR_SRBS_POOL_SIZE); 471344f05562SScott Long phbbmu = (struct HBB_MessageUnit *)acb->pmu; 471444f05562SScott Long phbbmu->hbb_doorbell = (struct HBB_DOORBELL *)mem_base[0]; 471544f05562SScott Long phbbmu->hbb_rwbuffer = (struct HBB_RWBUFFER *)mem_base[1]; 4716b23a1998SXin LI if (vendor_dev_id == PCIDevVenIDARC1203) { 4717b23a1998SXin LI phbbmu->drv2iop_doorbell = offsetof(struct HBB_DOORBELL_1203, drv2iop_doorbell); 4718b23a1998SXin LI phbbmu->drv2iop_doorbell_mask = offsetof(struct HBB_DOORBELL_1203, drv2iop_doorbell_mask); 4719b23a1998SXin LI phbbmu->iop2drv_doorbell = offsetof(struct HBB_DOORBELL_1203, iop2drv_doorbell); 4720b23a1998SXin LI phbbmu->iop2drv_doorbell_mask = offsetof(struct HBB_DOORBELL_1203, iop2drv_doorbell_mask); 4721b23a1998SXin LI } else { 4722b23a1998SXin LI phbbmu->drv2iop_doorbell = offsetof(struct HBB_DOORBELL, drv2iop_doorbell); 4723b23a1998SXin LI phbbmu->drv2iop_doorbell_mask = offsetof(struct HBB_DOORBELL, drv2iop_doorbell_mask); 4724b23a1998SXin LI phbbmu->iop2drv_doorbell = offsetof(struct HBB_DOORBELL, iop2drv_doorbell); 4725b23a1998SXin LI phbbmu->iop2drv_doorbell_mask = offsetof(struct HBB_DOORBELL, iop2drv_doorbell_mask); 4726b23a1998SXin LI } 4727fc5ef1caSXin LI acb->rid[0] = rid[0]; 4728fc5ef1caSXin LI acb->rid[1] = rid[1]; 472944f05562SScott Long } 473044f05562SScott Long break; 4731d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 4732d74001adSXin LI u_int32_t rid0 = PCIR_BAR(1); 4733d74001adSXin LI vm_offset_t mem_base0; 4734d74001adSXin LI 4735eff83876SJustin Hibbits acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid0, RF_ACTIVE); 4736d74001adSXin LI if(acb->sys_res_arcmsr[0] == NULL) { 4737d74001adSXin LI arcmsr_free_resource(acb); 4738d74001adSXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 4739d74001adSXin LI return ENOMEM; 4740d74001adSXin LI } 4741d74001adSXin LI if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 4742d74001adSXin LI arcmsr_free_resource(acb); 4743d74001adSXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 4744d74001adSXin LI return ENXIO; 4745d74001adSXin LI } 4746d74001adSXin LI mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 4747d74001adSXin LI if(mem_base0 == 0) { 4748d74001adSXin LI arcmsr_free_resource(acb); 4749d74001adSXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 4750d74001adSXin LI return ENXIO; 4751d74001adSXin LI } 4752d74001adSXin LI acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 4753d74001adSXin LI acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 4754d74001adSXin LI acb->pmu = (struct MessageUnit_UNION *)mem_base0; 4755fc5ef1caSXin LI acb->rid[0] = rid0; 4756d74001adSXin LI } 4757d74001adSXin LI break; 47587a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 47597a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu; 47607a7bc959SXin LI u_int32_t rid0 = PCIR_BAR(0); 47617a7bc959SXin LI vm_offset_t mem_base0; 47627a7bc959SXin LI 4763eff83876SJustin Hibbits acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid0, RF_ACTIVE); 47647a7bc959SXin LI if(acb->sys_res_arcmsr[0] == NULL) { 47657a7bc959SXin LI arcmsr_free_resource(acb); 47667a7bc959SXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 47677a7bc959SXin LI return ENOMEM; 47687a7bc959SXin LI } 47697a7bc959SXin LI if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 47707a7bc959SXin LI arcmsr_free_resource(acb); 47717a7bc959SXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 47727a7bc959SXin LI return ENXIO; 47737a7bc959SXin LI } 47747a7bc959SXin LI mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 47757a7bc959SXin LI if(mem_base0 == 0) { 47767a7bc959SXin LI arcmsr_free_resource(acb); 47777a7bc959SXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 47787a7bc959SXin LI return ENXIO; 47797a7bc959SXin LI } 47807a7bc959SXin LI acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 47817a7bc959SXin LI acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 47827a7bc959SXin LI acb->pmu = (struct MessageUnit_UNION *)((unsigned long)acb->uncacheptr+ARCMSR_SRBS_POOL_SIZE); 47837a7bc959SXin LI phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 47847a7bc959SXin LI phbdmu->phbdmu = (struct HBD_MessageUnit *)mem_base0; 4785fc5ef1caSXin LI acb->rid[0] = rid0; 4786a1103e04SXin LI } 4787a1103e04SXin LI break; 4788a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 4789a1103e04SXin LI u_int32_t rid0 = PCIR_BAR(1); 4790a1103e04SXin LI vm_offset_t mem_base0; 4791a1103e04SXin LI 4792fc5ef1caSXin LI acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid0, RF_ACTIVE); 4793a1103e04SXin LI if(acb->sys_res_arcmsr[0] == NULL) { 4794a1103e04SXin LI arcmsr_free_resource(acb); 4795a1103e04SXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 4796a1103e04SXin LI return ENOMEM; 4797a1103e04SXin LI } 4798a1103e04SXin LI if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 4799a1103e04SXin LI arcmsr_free_resource(acb); 4800a1103e04SXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 4801a1103e04SXin LI return ENXIO; 4802a1103e04SXin LI } 4803a1103e04SXin LI mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 4804a1103e04SXin LI if(mem_base0 == 0) { 4805a1103e04SXin LI arcmsr_free_resource(acb); 4806a1103e04SXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 4807a1103e04SXin LI return ENXIO; 4808a1103e04SXin LI } 4809a1103e04SXin LI acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 4810a1103e04SXin LI acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 4811a1103e04SXin LI acb->pmu = (struct MessageUnit_UNION *)mem_base0; 4812a1103e04SXin LI acb->doneq_index = 0; 4813a1103e04SXin LI acb->in_doorbell = 0; 4814a1103e04SXin LI acb->out_doorbell = 0; 4815fc5ef1caSXin LI acb->rid[0] = rid0; 4816a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /*clear interrupt*/ 4817a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, ARCMSR_HBEMU_DOORBELL_SYNC); /* synchronize doorbell to 0 */ 48187a7bc959SXin LI } 48197a7bc959SXin LI break; 4820fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 4821fa42a0bfSXin LI u_int32_t rid0 = PCIR_BAR(0); 4822fa42a0bfSXin LI vm_offset_t mem_base0; 4823fa42a0bfSXin LI unsigned long host_buffer_dma; 4824fa42a0bfSXin LI 4825fa42a0bfSXin LI acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid0, RF_ACTIVE); 4826fa42a0bfSXin LI if(acb->sys_res_arcmsr[0] == NULL) { 4827fa42a0bfSXin LI arcmsr_free_resource(acb); 4828fa42a0bfSXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 4829fa42a0bfSXin LI return ENOMEM; 4830fa42a0bfSXin LI } 4831fa42a0bfSXin LI if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 4832fa42a0bfSXin LI arcmsr_free_resource(acb); 4833fa42a0bfSXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 4834fa42a0bfSXin LI return ENXIO; 4835fa42a0bfSXin LI } 4836fa42a0bfSXin LI mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 4837fa42a0bfSXin LI if(mem_base0 == 0) { 4838fa42a0bfSXin LI arcmsr_free_resource(acb); 4839fa42a0bfSXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 4840fa42a0bfSXin LI return ENXIO; 4841fa42a0bfSXin LI } 4842fa42a0bfSXin LI acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 4843fa42a0bfSXin LI acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 4844fa42a0bfSXin LI acb->pmu = (struct MessageUnit_UNION *)mem_base0; 4845fa42a0bfSXin LI acb->doneq_index = 0; 4846fa42a0bfSXin LI acb->in_doorbell = 0; 4847fa42a0bfSXin LI acb->out_doorbell = 0; 4848fa42a0bfSXin LI acb->rid[0] = rid0; 4849fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, host_int_status, 0); /*clear interrupt*/ 4850fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, iobound_doorbell, ARCMSR_HBEMU_DOORBELL_SYNC); /* synchronize doorbell to 0 */ 48516964b77eS黃清隆 arcmsr_wait_firmware_ready(acb); 4852fa42a0bfSXin LI host_buffer_dma = acb->completeQ_phys + COMPLETION_Q_POOL_SIZE; 4853fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_msgaddr0, (u_int32_t)(host_buffer_dma | 1)); /* host buffer low addr, bit0:1 all buffer active */ 4854fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_msgaddr1, (u_int32_t)((host_buffer_dma >> 16) >> 16));/* host buffer high addr */ 4855fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, iobound_doorbell, ARCMSR_HBFMU_DOORBELL_SYNC1); /* set host buffer physical address */ 4856fa42a0bfSXin LI } 4857fa42a0bfSXin LI break; 485844f05562SScott Long } 4859ad6d6297SScott Long if(acb->acb_flags & ACB_F_MAPFREESRB_FAILD) { 4860ad6d6297SScott Long arcmsr_free_resource(acb); 486144f05562SScott Long printf("arcmsr%d: map free srb failure!\n", device_get_unit(dev)); 4862f1c579b1SScott Long return ENXIO; 4863f1c579b1SScott Long } 4864d74001adSXin LI acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_RQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ); 4865ad6d6297SScott Long acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; 4866ad6d6297SScott Long /* 4867ad6d6297SScott Long ******************************************************************** 4868ad6d6297SScott Long ** init raid volume state 4869ad6d6297SScott Long ******************************************************************** 4870ad6d6297SScott Long */ 4871ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_TARGETID; i++) { 4872ad6d6297SScott Long for(j=0; j < ARCMSR_MAX_TARGETLUN; j++) { 487344f05562SScott Long acb->devstate[i][j] = ARECA_RAID_GONE; 4874ad6d6297SScott Long } 4875ad6d6297SScott Long } 4876ad6d6297SScott Long arcmsr_iop_init(acb); 4877f1c579b1SScott Long return(0); 4878f1c579b1SScott Long } 4879a1103e04SXin LI 4880a1103e04SXin LI static int arcmsr_setup_msix(struct AdapterControlBlock *acb) 4881a1103e04SXin LI { 4882a1103e04SXin LI int i; 4883a1103e04SXin LI 4884a1103e04SXin LI for (i = 0; i < acb->msix_vectors; i++) { 4885fc5ef1caSXin LI acb->irq_id[i] = 1 + i; 4886a1103e04SXin LI acb->irqres[i] = bus_alloc_resource_any(acb->pci_dev, 4887a1103e04SXin LI SYS_RES_IRQ, &acb->irq_id[i], RF_ACTIVE); 4888a1103e04SXin LI if (acb->irqres[i] == NULL) { 4889a1103e04SXin LI printf("arcmsr: Can't allocate MSI-X resource\n"); 4890a1103e04SXin LI goto irq_alloc_failed; 4891a1103e04SXin LI } 4892a1103e04SXin LI if (bus_setup_intr(acb->pci_dev, acb->irqres[i], 4893a1103e04SXin LI INTR_MPSAFE | INTR_TYPE_CAM, NULL, arcmsr_intr_handler, 4894a1103e04SXin LI acb, &acb->ih[i])) { 4895a1103e04SXin LI printf("arcmsr: Cannot set up MSI-X interrupt handler\n"); 4896a1103e04SXin LI goto irq_alloc_failed; 4897a1103e04SXin LI } 4898a1103e04SXin LI } 4899a1103e04SXin LI printf("arcmsr: MSI-X INT enabled\n"); 4900a1103e04SXin LI acb->acb_flags |= ACB_F_MSIX_ENABLED; 4901a1103e04SXin LI return TRUE; 4902a1103e04SXin LI 4903a1103e04SXin LI irq_alloc_failed: 4904a1103e04SXin LI arcmsr_teardown_intr(acb->pci_dev, acb); 4905a1103e04SXin LI return FALSE; 4906a1103e04SXin LI } 4907a1103e04SXin LI 4908f1c579b1SScott Long /* 4909f1c579b1SScott Long ************************************************************************ 4910f1c579b1SScott Long ************************************************************************ 4911f1c579b1SScott Long */ 4912f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev) 4913f1c579b1SScott Long { 4914a9e5e04eSJohn Baldwin struct make_dev_args args; 4915ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 4916ad6d6297SScott Long u_int32_t unit=device_get_unit(dev); 4917f1c579b1SScott Long struct ccb_setasync csa; 4918f1c579b1SScott Long struct cam_devq *devq; /* Device Queue to use for this SIM */ 4919f1c579b1SScott Long struct resource *irqres; 4920f1c579b1SScott Long 4921ad6d6297SScott Long if(acb == NULL) { 4922ad6d6297SScott Long printf("arcmsr%d: cannot allocate softc\n", unit); 4923ad6d6297SScott Long return (ENOMEM); 4924ad6d6297SScott Long } 49257a7bc959SXin LI arcmsr_mutex_init(acb); 49261e7d660aSXin LI acb->pci_dev = dev; 49271e7d660aSXin LI acb->pci_unit = unit; 4928ad6d6297SScott Long if(arcmsr_initialize(dev)) { 4929ad6d6297SScott Long printf("arcmsr%d: initialize failure!\n", unit); 4930a1103e04SXin LI goto initialize_failed; 4931f1c579b1SScott Long } 4932f1c579b1SScott Long /* After setting up the adapter, map our interrupt */ 4933a1103e04SXin LI acb->msix_vectors = ARCMSR_NUM_MSIX_VECTORS; 4934a1103e04SXin LI if (pci_alloc_msix(dev, &acb->msix_vectors) == 0) { 4935a1103e04SXin LI if (arcmsr_setup_msix(acb) == TRUE) 4936a1103e04SXin LI goto irqx; 4937a1103e04SXin LI } 4938fc5ef1caSXin LI acb->irq_id[0] = 0; 4939a1103e04SXin LI irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &acb->irq_id[0], RF_SHAREABLE | RF_ACTIVE); 4940ad6d6297SScott Long if(irqres == NULL || 4941a1103e04SXin LI bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, NULL, arcmsr_intr_handler, acb, &acb->ih[0])) { 4942f1c579b1SScott Long printf("arcmsr%d: unable to register interrupt handler!\n", unit); 4943a1103e04SXin LI goto setup_intr_failed; 4944f1c579b1SScott Long } 4945a1103e04SXin LI acb->irqres[0] = irqres; 4946a1103e04SXin LI irqx: 4947f1c579b1SScott Long /* 4948f1c579b1SScott Long * Now let the CAM generic SCSI layer find the SCSI devices on 4949f1c579b1SScott Long * the bus * start queue to reset to the idle loop. * 4950f1c579b1SScott Long * Create device queue of SIM(s) * (MAX_START_JOB - 1) : 4951f1c579b1SScott Long * max_sim_transactions 4952f1c579b1SScott Long */ 4953224a78aeSXin LI devq = cam_simq_alloc(acb->maxOutstanding); 4954ad6d6297SScott Long if(devq == NULL) { 4955ad6d6297SScott Long printf("arcmsr%d: cam_simq_alloc failure!\n", unit); 4956a1103e04SXin LI goto simq_alloc_failed; 4957f1c579b1SScott Long } 49587a7bc959SXin LI acb->psim = cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, &acb->isr_lock, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq); 4959ad6d6297SScott Long if(acb->psim == NULL) { 4960ad6d6297SScott Long printf("arcmsr%d: cam_sim_alloc failure!\n", unit); 4961a1103e04SXin LI goto sim_alloc_failed; 4962f1c579b1SScott Long } 49637a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 4964b50569b7SScott Long if(xpt_bus_register(acb->psim, dev, 0) != CAM_SUCCESS) { 4965ad6d6297SScott Long printf("arcmsr%d: xpt_bus_register failure!\n", unit); 4966a1103e04SXin LI goto xpt_bus_failed; 4967f1c579b1SScott Long } 4968d74001adSXin LI if(xpt_create_path(&acb->ppath, /* periph */ NULL, cam_sim_path(acb->psim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 4969ad6d6297SScott Long printf("arcmsr%d: xpt_create_path failure!\n", unit); 4970a1103e04SXin LI goto xpt_path_failed; 4971f1c579b1SScott Long } 4972f1c579b1SScott Long /* 4973f1c579b1SScott Long **************************************************** 4974f1c579b1SScott Long */ 497545f57ce1SEdward Tomasz Napierala memset(&csa, 0, sizeof(csa)); 4976ad6d6297SScott Long xpt_setup_ccb(&csa.ccb_h, acb->ppath, /*priority*/5); 4977f1c579b1SScott Long csa.ccb_h.func_code = XPT_SASYNC_CB; 4978f1c579b1SScott Long csa.event_enable = AC_FOUND_DEVICE|AC_LOST_DEVICE; 4979f1c579b1SScott Long csa.callback = arcmsr_async; 4980ad6d6297SScott Long csa.callback_arg = acb->psim; 4981f1c579b1SScott Long xpt_action((union ccb *)&csa); 49827a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 4983f1c579b1SScott Long /* Create the control device. */ 4984a9e5e04eSJohn Baldwin make_dev_args_init(&args); 4985a9e5e04eSJohn Baldwin args.mda_devsw = &arcmsr_cdevsw; 4986a9e5e04eSJohn Baldwin args.mda_uid = UID_ROOT; 4987a9e5e04eSJohn Baldwin args.mda_gid = GID_WHEEL /* GID_OPERATOR */; 4988a9e5e04eSJohn Baldwin args.mda_mode = S_IRUSR | S_IWUSR; 4989a9e5e04eSJohn Baldwin args.mda_si_drv1 = acb; 4990a9e5e04eSJohn Baldwin (void)make_dev_s(&args, &acb->ioctl_dev, "arcmsr%d", unit); 4991d74001adSXin LI 4992ad6d6297SScott Long (void)make_dev_alias(acb->ioctl_dev, "arc%d", unit); 499322f2616bSXin LI arcmsr_callout_init(&acb->devmap_callout); 4994d74001adSXin LI callout_reset(&acb->devmap_callout, 60 * hz, arcmsr_polling_devmap, acb); 4995dac36688SXin LI return (0); 4996a1103e04SXin LI xpt_path_failed: 4997a1103e04SXin LI xpt_bus_deregister(cam_sim_path(acb->psim)); 4998a1103e04SXin LI xpt_bus_failed: 4999a1103e04SXin LI cam_sim_free(acb->psim, /* free_simq */ TRUE); 5000a1103e04SXin LI sim_alloc_failed: 5001a1103e04SXin LI cam_simq_free(devq); 5002a1103e04SXin LI simq_alloc_failed: 5003a1103e04SXin LI arcmsr_teardown_intr(dev, acb); 5004a1103e04SXin LI setup_intr_failed: 5005a1103e04SXin LI arcmsr_free_resource(acb); 5006a1103e04SXin LI initialize_failed: 5007a1103e04SXin LI arcmsr_mutex_destroy(acb); 5008a1103e04SXin LI return ENXIO; 5009f1c579b1SScott Long } 501022f2616bSXin LI 5011f1c579b1SScott Long /* 5012f1c579b1SScott Long ************************************************************************ 5013f1c579b1SScott Long ************************************************************************ 5014f1c579b1SScott Long */ 5015f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev) 5016f1c579b1SScott Long { 5017ad6d6297SScott Long u_int32_t id; 5018224a78aeSXin LI u_int16_t sub_device_id; 5019ad6d6297SScott Long static char buf[256]; 50201e7d660aSXin LI char x_type[]={"unknown"}; 5021ad6d6297SScott Long char *type; 5022ad6d6297SScott Long int raid6 = 1; 5023ad6d6297SScott Long 5024ad6d6297SScott Long if (pci_get_vendor(dev) != PCI_VENDOR_ID_ARECA) { 5025ad6d6297SScott Long return (ENXIO); 5026ad6d6297SScott Long } 5027224a78aeSXin LI sub_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2); 5028ad6d6297SScott Long switch(id = pci_get_devid(dev)) { 5029f1c579b1SScott Long case PCIDevVenIDARC1110: 5030231c8b71SXin LI case PCIDevVenIDARC1200: 503144f05562SScott Long case PCIDevVenIDARC1201: 5032231c8b71SXin LI case PCIDevVenIDARC1210: 5033ad6d6297SScott Long raid6 = 0; 5034ad6d6297SScott Long /*FALLTHRU*/ 5035ad6d6297SScott Long case PCIDevVenIDARC1120: 5036ad6d6297SScott Long case PCIDevVenIDARC1130: 5037ad6d6297SScott Long case PCIDevVenIDARC1160: 5038ad6d6297SScott Long case PCIDevVenIDARC1170: 5039f1c579b1SScott Long case PCIDevVenIDARC1220: 5040f1c579b1SScott Long case PCIDevVenIDARC1230: 5041231c8b71SXin LI case PCIDevVenIDARC1231: 5042f1c579b1SScott Long case PCIDevVenIDARC1260: 5043231c8b71SXin LI case PCIDevVenIDARC1261: 5044ad6d6297SScott Long case PCIDevVenIDARC1270: 5045ad6d6297SScott Long case PCIDevVenIDARC1280: 50467a7bc959SXin LI type = "SATA 3G"; 5047ad6d6297SScott Long break; 5048d74001adSXin LI case PCIDevVenIDARC1212: 5049d74001adSXin LI case PCIDevVenIDARC1222: 5050ad6d6297SScott Long case PCIDevVenIDARC1380: 5051ad6d6297SScott Long case PCIDevVenIDARC1381: 5052ad6d6297SScott Long case PCIDevVenIDARC1680: 5053ad6d6297SScott Long case PCIDevVenIDARC1681: 5054d74001adSXin LI type = "SAS 3G"; 5055d74001adSXin LI break; 5056d74001adSXin LI case PCIDevVenIDARC1880: 5057dac36688SXin LI case PCIDevVenIDARC1882: 5058dac36688SXin LI case PCIDevVenIDARC1213: 5059dac36688SXin LI case PCIDevVenIDARC1223: 5060fc5ef1caSXin LI if ((sub_device_id == ARECA_SUB_DEV_ID_1883) || 5061fc5ef1caSXin LI (sub_device_id == ARECA_SUB_DEV_ID_1216) || 5062fc5ef1caSXin LI (sub_device_id == ARECA_SUB_DEV_ID_1226)) 5063224a78aeSXin LI type = "SAS 12G"; 5064224a78aeSXin LI else 5065d74001adSXin LI type = "SAS 6G"; 5066ad6d6297SScott Long break; 5067a1103e04SXin LI case PCIDevVenIDARC1884: 5068a1103e04SXin LI type = "SAS 12G"; 5069a1103e04SXin LI break; 5070fa42a0bfSXin LI case PCIDevVenIDARC1886_: 5071fa42a0bfSXin LI case PCIDevVenIDARC1886: 5072fa42a0bfSXin LI type = "NVME,SAS-12G,SATA-6G"; 5073fa42a0bfSXin LI break; 50747a7bc959SXin LI case PCIDevVenIDARC1214: 5075b23a1998SXin LI case PCIDevVenIDARC1203: 50767a7bc959SXin LI type = "SATA 6G"; 50777a7bc959SXin LI break; 5078ad6d6297SScott Long default: 5079231c8b71SXin LI type = x_type; 50801e7d660aSXin LI raid6 = 0; 5081ad6d6297SScott Long break; 5082f1c579b1SScott Long } 5083231c8b71SXin LI if(type == x_type) 5084231c8b71SXin LI return(ENXIO); 50851e7d660aSXin LI sprintf(buf, "Areca %s Host Adapter RAID Controller %s\n%s\n", 50861e7d660aSXin LI type, raid6 ? "(RAID6 capable)" : "", ARCMSR_DRIVER_VERSION); 5087ad6d6297SScott Long device_set_desc_copy(dev, buf); 508803389298SXin LI return (BUS_PROBE_DEFAULT); 5089f1c579b1SScott Long } 5090f1c579b1SScott Long /* 5091f1c579b1SScott Long ************************************************************************ 5092f1c579b1SScott Long ************************************************************************ 5093f1c579b1SScott Long */ 5094f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev) 5095f1c579b1SScott Long { 509644f05562SScott Long u_int32_t i; 5097ad6d6297SScott Long struct CommandControlBlock *srb; 5098ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 5099f1c579b1SScott Long 5100f1c579b1SScott Long /* stop adapter background rebuild */ 51017a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 510244f05562SScott Long /* disable all outbound interrupt */ 5103bca8e8c0SScott Long arcmsr_disable_allintr(acb); 5104ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 5105ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 5106f1c579b1SScott Long /* abort all outstanding command */ 5107ad6d6297SScott Long acb->acb_flags |= ACB_F_SCSISTOPADAPTER; 5108ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOP_INITED; 5109ad6d6297SScott Long if(acb->srboutstandingcount != 0) { 511044f05562SScott Long /*clear and abort all outbound posted Q*/ 511144f05562SScott Long arcmsr_done4abort_postqueue(acb); 511244f05562SScott Long /* talk to iop 331 outstanding command aborted*/ 5113ad6d6297SScott Long arcmsr_abort_allcmd(acb); 5114ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 5115ad6d6297SScott Long srb = acb->psrb_pool[i]; 511622f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) { 511722f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 5118ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 5119ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 5120f1c579b1SScott Long } 5121f1c579b1SScott Long } 5122f1c579b1SScott Long } 512322f2616bSXin LI acb->srboutstandingcount = 0; 5124ad6d6297SScott Long acb->workingsrb_doneindex = 0; 5125ad6d6297SScott Long acb->workingsrb_startindex = 0; 512622f2616bSXin LI acb->pktRequestCount = 0; 512722f2616bSXin LI acb->pktReturnCount = 0; 51287a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 5129f2aa0e9fSWarner Losh return (0); 5130f1c579b1SScott Long } 5131f1c579b1SScott Long /* 5132f1c579b1SScott Long ************************************************************************ 5133f1c579b1SScott Long ************************************************************************ 5134f1c579b1SScott Long */ 5135fc5ef1caSXin LI static void arcmsr_teardown_intr(device_t dev, struct AdapterControlBlock *acb) 5136a1103e04SXin LI { 5137a1103e04SXin LI int i; 5138a1103e04SXin LI 5139a1103e04SXin LI if (acb->acb_flags & ACB_F_MSIX_ENABLED) { 5140a1103e04SXin LI for (i = 0; i < acb->msix_vectors; i++) { 5141a1103e04SXin LI if (acb->ih[i]) 5142a1103e04SXin LI bus_teardown_intr(dev, acb->irqres[i], acb->ih[i]); 5143a1103e04SXin LI if (acb->irqres[i] != NULL) 5144a1103e04SXin LI bus_release_resource(dev, SYS_RES_IRQ, 5145a1103e04SXin LI acb->irq_id[i], acb->irqres[i]); 5146a1103e04SXin LI 5147a1103e04SXin LI acb->ih[i] = NULL; 5148a1103e04SXin LI } 5149a1103e04SXin LI pci_release_msi(dev); 5150a1103e04SXin LI } else { 5151a1103e04SXin LI if (acb->ih[0]) 5152a1103e04SXin LI bus_teardown_intr(dev, acb->irqres[0], acb->ih[0]); 5153a1103e04SXin LI if (acb->irqres[0] != NULL) 5154a1103e04SXin LI bus_release_resource(dev, SYS_RES_IRQ, 5155a1103e04SXin LI acb->irq_id[0], acb->irqres[0]); 5156a1103e04SXin LI acb->ih[0] = NULL; 5157a1103e04SXin LI } 5158a1103e04SXin LI 5159a1103e04SXin LI } 5160a1103e04SXin LI /* 5161a1103e04SXin LI ************************************************************************ 5162a1103e04SXin LI ************************************************************************ 5163a1103e04SXin LI */ 5164f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev) 5165f1c579b1SScott Long { 5166ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 516744f05562SScott Long int i; 5168f1c579b1SScott Long 5169d74001adSXin LI callout_stop(&acb->devmap_callout); 5170a1103e04SXin LI arcmsr_teardown_intr(dev, acb); 5171f1c579b1SScott Long arcmsr_shutdown(dev); 5172ad6d6297SScott Long arcmsr_free_resource(acb); 517344f05562SScott Long for(i=0; (acb->sys_res_arcmsr[i]!=NULL) && (i<2); i++) { 5174fc5ef1caSXin LI bus_release_resource(dev, SYS_RES_MEMORY, acb->rid[i], acb->sys_res_arcmsr[i]); 517544f05562SScott Long } 51767a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 5177ad6d6297SScott Long xpt_async(AC_LOST_DEVICE, acb->ppath, NULL); 5178ad6d6297SScott Long xpt_free_path(acb->ppath); 5179ad6d6297SScott Long xpt_bus_deregister(cam_sim_path(acb->psim)); 5180ad6d6297SScott Long cam_sim_free(acb->psim, TRUE); 51817a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 51827a7bc959SXin LI arcmsr_mutex_destroy(acb); 5183f1c579b1SScott Long return (0); 5184f1c579b1SScott Long } 5185f1c579b1SScott Long 518622f2616bSXin LI #ifdef ARCMSR_DEBUG1 518722f2616bSXin LI static void arcmsr_dump_data(struct AdapterControlBlock *acb) 518822f2616bSXin LI { 518922f2616bSXin LI if((acb->pktRequestCount - acb->pktReturnCount) == 0) 519022f2616bSXin LI return; 519122f2616bSXin LI printf("Command Request Count =0x%x\n",acb->pktRequestCount); 519222f2616bSXin LI printf("Command Return Count =0x%x\n",acb->pktReturnCount); 519322f2616bSXin LI printf("Command (Req-Rtn) Count =0x%x\n",(acb->pktRequestCount - acb->pktReturnCount)); 519422f2616bSXin LI printf("Queued Command Count =0x%x\n",acb->srboutstandingcount); 519522f2616bSXin LI } 519622f2616bSXin LI #endif 5197