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 88*6964b77eS黃清隆 ** 1.50.00.03 05/04/2021 Ching Huang Fixed doorbell status arrived late on ARC-1886 89*6964b77eS黃清隆 ** 1.50.00.04 12/08/2021 Ching Huang Fixed boot up hung under ARC-1886 with no volume created 90f1c579b1SScott Long ****************************************************************************************** 91f1c579b1SScott Long */ 924b7ec270SMarius Strobl 934b7ec270SMarius Strobl #include <sys/cdefs.h> 944b7ec270SMarius Strobl __FBSDID("$FreeBSD$"); 954b7ec270SMarius Strobl 9622f2616bSXin LI #if 0 9722f2616bSXin LI #define ARCMSR_DEBUG1 1 9822f2616bSXin LI #endif 99f1c579b1SScott Long #include <sys/param.h> 100f1c579b1SScott Long #include <sys/systm.h> 101f1c579b1SScott Long #include <sys/malloc.h> 102f1c579b1SScott Long #include <sys/kernel.h> 103f1c579b1SScott Long #include <sys/bus.h> 104f1c579b1SScott Long #include <sys/queue.h> 105f1c579b1SScott Long #include <sys/stat.h> 106f1c579b1SScott Long #include <sys/devicestat.h> 107f1c579b1SScott Long #include <sys/kthread.h> 108f1c579b1SScott Long #include <sys/module.h> 109f1c579b1SScott Long #include <sys/proc.h> 110f1c579b1SScott Long #include <sys/lock.h> 111f1c579b1SScott Long #include <sys/sysctl.h> 112f1c579b1SScott Long #include <sys/poll.h> 113f1c579b1SScott Long #include <sys/ioccom.h> 114f1c579b1SScott Long #include <vm/vm.h> 115f1c579b1SScott Long #include <vm/vm_param.h> 116f1c579b1SScott Long #include <vm/pmap.h> 117f1c579b1SScott Long 118f1c579b1SScott Long #include <isa/rtc.h> 119f1c579b1SScott Long 120f1c579b1SScott Long #include <machine/bus.h> 121f1c579b1SScott Long #include <machine/resource.h> 122f1c579b1SScott Long #include <machine/atomic.h> 123f1c579b1SScott Long #include <sys/conf.h> 124f1c579b1SScott Long #include <sys/rman.h> 125f1c579b1SScott Long 126f1c579b1SScott Long #include <cam/cam.h> 127f1c579b1SScott Long #include <cam/cam_ccb.h> 128f1c579b1SScott Long #include <cam/cam_sim.h> 129d74001adSXin LI #include <cam/cam_periph.h> 130d74001adSXin LI #include <cam/cam_xpt_periph.h> 131f1c579b1SScott Long #include <cam/cam_xpt_sim.h> 132f1c579b1SScott Long #include <cam/cam_debug.h> 133f1c579b1SScott Long #include <cam/scsi/scsi_all.h> 134f1c579b1SScott Long #include <cam/scsi/scsi_message.h> 135f1c579b1SScott Long /* 136f1c579b1SScott Long ************************************************************************** 137f1c579b1SScott Long ************************************************************************** 138f1c579b1SScott Long */ 139f1c579b1SScott Long #include <sys/selinfo.h> 140f1c579b1SScott Long #include <sys/mutex.h> 141ad6d6297SScott Long #include <sys/endian.h> 142f1c579b1SScott Long #include <dev/pci/pcivar.h> 143f1c579b1SScott Long #include <dev/pci/pcireg.h> 14444f05562SScott Long 14522f2616bSXin LI #define arcmsr_callout_init(a) callout_init(a, /*mpsafe*/1); 14622f2616bSXin LI 147*6964b77eS黃清隆 #define ARCMSR_DRIVER_VERSION "arcmsr version 1.50.00.04 2021-12-08" 148f1c579b1SScott Long #include <dev/arcmsr/arcmsr.h> 149f1c579b1SScott Long /* 150f1c579b1SScott Long ************************************************************************** 151f1c579b1SScott Long ************************************************************************** 152f1c579b1SScott Long */ 15322f2616bSXin LI static void arcmsr_free_srb(struct CommandControlBlock *srb); 154ad6d6297SScott Long static struct CommandControlBlock *arcmsr_get_freesrb(struct AdapterControlBlock *acb); 155ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb *abortccb); 156f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev); 157f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev); 158f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev); 159ad6d6297SScott Long static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg); 160ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb); 161f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev); 16244f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb); 163ad6d6297SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb); 164ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb); 165ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb); 166ad6d6297SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); 167ad6d6297SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb); 168ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb); 169ad6d6297SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb); 17035689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, struct QBUFFER *prbuffer); 1717a7bc959SXin LI static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb); 172ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb); 173ad6d6297SScott Long static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag); 174ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb); 175ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb); 176ad6d6297SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t *dm_segs, u_int32_t nseg); 177ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *pccb); 178ad6d6297SScott Long static int arcmsr_resume(device_t dev); 179ad6d6297SScott Long static int arcmsr_suspend(device_t dev); 180d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb); 181d74001adSXin LI static void arcmsr_polling_devmap(void *arg); 18222f2616bSXin LI static void arcmsr_srb_timeout(void *arg); 1837a7bc959SXin LI static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb); 184a1103e04SXin LI static void arcmsr_hbe_postqueue_isr(struct AdapterControlBlock *acb); 185fa42a0bfSXin LI static void arcmsr_hbf_postqueue_isr(struct AdapterControlBlock *acb); 186fc5ef1caSXin LI static void arcmsr_teardown_intr(device_t dev, struct AdapterControlBlock *acb); 18722f2616bSXin LI #ifdef ARCMSR_DEBUG1 18822f2616bSXin LI static void arcmsr_dump_data(struct AdapterControlBlock *acb); 18922f2616bSXin LI #endif 190f1c579b1SScott Long /* 191f1c579b1SScott Long ************************************************************************** 192ad6d6297SScott Long ************************************************************************** 193ad6d6297SScott Long */ 194ad6d6297SScott Long static void UDELAY(u_int32_t us) { DELAY(us); } 195ad6d6297SScott Long /* 196ad6d6297SScott Long ************************************************************************** 197f1c579b1SScott Long ************************************************************************** 198f1c579b1SScott Long */ 199231c8b71SXin LI static bus_dmamap_callback_t arcmsr_map_free_srb; 200231c8b71SXin LI static bus_dmamap_callback_t arcmsr_execute_srb; 201f1c579b1SScott Long /* 202f1c579b1SScott Long ************************************************************************** 203f1c579b1SScott Long ************************************************************************** 204f1c579b1SScott Long */ 205f1c579b1SScott Long static d_open_t arcmsr_open; 206f1c579b1SScott Long static d_close_t arcmsr_close; 207f1c579b1SScott Long static d_ioctl_t arcmsr_ioctl; 208f1c579b1SScott Long 209f1c579b1SScott Long static device_method_t arcmsr_methods[]={ 210f1c579b1SScott Long DEVMETHOD(device_probe, arcmsr_probe), 211f1c579b1SScott Long DEVMETHOD(device_attach, arcmsr_attach), 212f1c579b1SScott Long DEVMETHOD(device_detach, arcmsr_detach), 213f1c579b1SScott Long DEVMETHOD(device_shutdown, arcmsr_shutdown), 214ad6d6297SScott Long DEVMETHOD(device_suspend, arcmsr_suspend), 215ad6d6297SScott Long DEVMETHOD(device_resume, arcmsr_resume), 2164b7ec270SMarius Strobl DEVMETHOD_END 217f1c579b1SScott Long }; 218f1c579b1SScott Long 219f1c579b1SScott Long static driver_t arcmsr_driver={ 220ad6d6297SScott Long "arcmsr", arcmsr_methods, sizeof(struct AdapterControlBlock) 221f1c579b1SScott Long }; 222f1c579b1SScott Long 223f1c579b1SScott Long static devclass_t arcmsr_devclass; 224f1c579b1SScott Long DRIVER_MODULE(arcmsr, pci, arcmsr_driver, arcmsr_devclass, 0, 0); 225d3cf342dSScott Long MODULE_DEPEND(arcmsr, pci, 1, 1, 1); 226d3cf342dSScott Long MODULE_DEPEND(arcmsr, cam, 1, 1, 1); 227ad6d6297SScott Long #ifndef BUS_DMA_COHERENT 228ad6d6297SScott Long #define BUS_DMA_COHERENT 0x04 /* hint: map memory in a coherent way */ 229ad6d6297SScott Long #endif 230f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw={ 231f1c579b1SScott Long .d_version = D_VERSION, 232f1c579b1SScott Long .d_open = arcmsr_open, /* open */ 233f1c579b1SScott Long .d_close = arcmsr_close, /* close */ 234f1c579b1SScott Long .d_ioctl = arcmsr_ioctl, /* ioctl */ 235f1c579b1SScott Long .d_name = "arcmsr", /* name */ 236f1c579b1SScott Long }; 237d74001adSXin LI /* 238d74001adSXin LI ************************************************************************** 239d74001adSXin LI ************************************************************************** 240d74001adSXin LI */ 24100b4e54aSWarner Losh static int arcmsr_open(struct cdev *dev, int flags, int fmt, struct thread *proc) 242f1c579b1SScott Long { 2436bfa9a2dSEd Schouten int unit = dev2unit(dev); 244ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 2459ea5bef2SWarner Losh 246ad6d6297SScott Long if (acb == NULL) { 247f1c579b1SScott Long return ENXIO; 248f1c579b1SScott Long } 249dac36688SXin LI return (0); 250f1c579b1SScott Long } 251f1c579b1SScott Long /* 252f1c579b1SScott Long ************************************************************************** 253f1c579b1SScott Long ************************************************************************** 254f1c579b1SScott Long */ 25500b4e54aSWarner Losh static int arcmsr_close(struct cdev *dev, int flags, int fmt, struct thread *proc) 256f1c579b1SScott Long { 2576bfa9a2dSEd Schouten int unit = dev2unit(dev); 258ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 2599ea5bef2SWarner Losh 260ad6d6297SScott Long if (acb == NULL) { 261f1c579b1SScott Long return ENXIO; 262f1c579b1SScott Long } 263f1c579b1SScott Long return 0; 264f1c579b1SScott Long } 265f1c579b1SScott Long /* 266f1c579b1SScott Long ************************************************************************** 267f1c579b1SScott Long ************************************************************************** 268f1c579b1SScott Long */ 26900b4e54aSWarner Losh static int arcmsr_ioctl(struct cdev *dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc) 270f1c579b1SScott Long { 2716bfa9a2dSEd Schouten int unit = dev2unit(dev); 272ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 273f1c579b1SScott Long 274ad6d6297SScott Long if (acb == NULL) { 275f1c579b1SScott Long return ENXIO; 276f1c579b1SScott Long } 277ad6d6297SScott Long return (arcmsr_iop_ioctlcmd(acb, ioctl_cmd, arg)); 278f1c579b1SScott Long } 279f1c579b1SScott Long /* 28044f05562SScott Long ********************************************************************** 28144f05562SScott Long ********************************************************************** 28244f05562SScott Long */ 28344f05562SScott Long static u_int32_t arcmsr_disable_allintr( struct AdapterControlBlock *acb) 28444f05562SScott Long { 28544f05562SScott Long u_int32_t intmask_org = 0; 28644f05562SScott Long 28744f05562SScott Long switch (acb->adapter_type) { 28844f05562SScott Long case ACB_ADAPTER_TYPE_A: { 28944f05562SScott Long /* disable all outbound interrupt */ 290d74001adSXin LI intmask_org = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intmask); /* disable outbound message0 int */ 291d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); 29244f05562SScott Long } 29344f05562SScott Long break; 29444f05562SScott Long case ACB_ADAPTER_TYPE_B: { 295b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 29644f05562SScott Long /* disable all outbound interrupt */ 297b23a1998SXin LI intmask_org = READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask) 298b23a1998SXin LI & (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); /* disable outbound message0 int */ 299b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask, 0); /* disable all interrupt */ 300d74001adSXin LI } 301d74001adSXin LI break; 302d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 303d74001adSXin LI /* disable all outbound interrupt */ 304d74001adSXin LI intmask_org = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_mask); /* disable outbound message0 int */ 305d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org|ARCMSR_HBCMU_ALL_INTMASKENABLE); 30644f05562SScott Long } 30744f05562SScott Long break; 3087a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 3097a7bc959SXin LI /* disable all outbound interrupt */ 3107a7bc959SXin LI intmask_org = CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable); /* disable outbound message0 int */ 3117a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, ARCMSR_HBDMU_ALL_INT_DISABLE); 3127a7bc959SXin LI } 3137a7bc959SXin LI break; 314fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 315fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 316a1103e04SXin LI /* disable all outbound interrupt */ 317fa42a0bfSXin LI intmask_org = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_mask); /* disable outbound message0 int */ 318a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_mask, intmask_org | ARCMSR_HBEMU_ALL_INTMASKENABLE); 319a1103e04SXin LI } 320a1103e04SXin LI break; 32144f05562SScott Long } 32244f05562SScott Long return (intmask_org); 32344f05562SScott Long } 32444f05562SScott Long /* 32544f05562SScott Long ********************************************************************** 32644f05562SScott Long ********************************************************************** 32744f05562SScott Long */ 32844f05562SScott Long static void arcmsr_enable_allintr( struct AdapterControlBlock *acb, u_int32_t intmask_org) 32944f05562SScott Long { 33044f05562SScott Long u_int32_t mask; 33144f05562SScott Long 33244f05562SScott Long switch (acb->adapter_type) { 33344f05562SScott Long case ACB_ADAPTER_TYPE_A: { 33444f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 335d74001adSXin LI mask = ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE); 33644f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org & mask); 33744f05562SScott Long acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; 33844f05562SScott Long } 33944f05562SScott Long break; 34044f05562SScott Long case ACB_ADAPTER_TYPE_B: { 341b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 342d74001adSXin LI /* enable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */ 343d74001adSXin LI mask = (ARCMSR_IOP2DRV_DATA_WRITE_OK|ARCMSR_IOP2DRV_DATA_READ_OK|ARCMSR_IOP2DRV_CDB_DONE|ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); 344b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask, intmask_org | mask); /*1=interrupt enable, 0=interrupt disable*/ 34544f05562SScott Long acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f; 34644f05562SScott Long } 34744f05562SScott Long break; 348d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 349d74001adSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 350d74001adSXin LI mask = ~(ARCMSR_HBCMU_UTILITY_A_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK); 351d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org & mask); 352d74001adSXin LI acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f; 353d74001adSXin LI } 354d74001adSXin LI break; 3557a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 3567a7bc959SXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 3577a7bc959SXin LI mask = ARCMSR_HBDMU_ALL_INT_ENABLE; 3587a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, intmask_org | mask); 3597a7bc959SXin LI CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable); 3607a7bc959SXin LI acb->outbound_int_enable = mask; 3617a7bc959SXin LI } 3627a7bc959SXin LI break; 363fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 364fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 365a1103e04SXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 366a1103e04SXin LI mask = ~(ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR | ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR); 367a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_mask, intmask_org & mask); 368a1103e04SXin LI acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f; 369a1103e04SXin LI } 370a1103e04SXin LI break; 37144f05562SScott Long } 37244f05562SScott Long } 37344f05562SScott Long /* 37444f05562SScott Long ********************************************************************** 37544f05562SScott Long ********************************************************************** 37644f05562SScott Long */ 37744f05562SScott Long static u_int8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) 37844f05562SScott Long { 37944f05562SScott Long u_int32_t Index; 38044f05562SScott Long u_int8_t Retries = 0x00; 38144f05562SScott Long 38244f05562SScott Long do { 38344f05562SScott Long for(Index=0; Index < 100; Index++) { 384d74001adSXin LI if(CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { 385d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/ 38644f05562SScott Long return TRUE; 38744f05562SScott Long } 38844f05562SScott Long UDELAY(10000); 38944f05562SScott Long }/*max 1 seconds*/ 39044f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 391dac36688SXin LI return (FALSE); 39244f05562SScott Long } 39344f05562SScott Long /* 39444f05562SScott Long ********************************************************************** 39544f05562SScott Long ********************************************************************** 39644f05562SScott Long */ 39744f05562SScott Long static u_int8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) 39844f05562SScott Long { 39944f05562SScott Long u_int32_t Index; 40044f05562SScott Long u_int8_t Retries = 0x00; 401b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 40244f05562SScott Long 40344f05562SScott Long do { 40444f05562SScott Long for(Index=0; Index < 100; Index++) { 405b23a1998SXin LI if(READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { 406b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/ 407b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 408d74001adSXin LI return TRUE; 409d74001adSXin LI } 410d74001adSXin LI UDELAY(10000); 411d74001adSXin LI }/*max 1 seconds*/ 412d74001adSXin LI }while(Retries++ < 20);/*max 20 sec*/ 413dac36688SXin LI return (FALSE); 414d74001adSXin LI } 415d74001adSXin LI /* 416d74001adSXin LI ********************************************************************** 417d74001adSXin LI ********************************************************************** 418d74001adSXin LI */ 419d74001adSXin LI static u_int8_t arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock *acb) 420d74001adSXin LI { 421d74001adSXin LI u_int32_t Index; 422d74001adSXin LI u_int8_t Retries = 0x00; 423d74001adSXin LI 424d74001adSXin LI do { 425d74001adSXin LI for(Index=0; Index < 100; Index++) { 426d74001adSXin LI if(CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { 427d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);/*clear interrupt*/ 42844f05562SScott Long return TRUE; 42944f05562SScott Long } 43044f05562SScott Long UDELAY(10000); 43144f05562SScott Long }/*max 1 seconds*/ 43244f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 433dac36688SXin LI return (FALSE); 43444f05562SScott Long } 43544f05562SScott Long /* 4367a7bc959SXin LI ********************************************************************** 4377a7bc959SXin LI ********************************************************************** 4387a7bc959SXin LI */ 4397a7bc959SXin LI static u_int8_t arcmsr_hbd_wait_msgint_ready(struct AdapterControlBlock *acb) 4407a7bc959SXin LI { 4417a7bc959SXin LI u_int32_t Index; 4427a7bc959SXin LI u_int8_t Retries = 0x00; 4437a7bc959SXin LI 4447a7bc959SXin LI do { 4457a7bc959SXin LI for(Index=0; Index < 100; Index++) { 4467a7bc959SXin LI if(CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) { 4477a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR);/*clear interrupt*/ 4487a7bc959SXin LI return TRUE; 4497a7bc959SXin LI } 4507a7bc959SXin LI UDELAY(10000); 4517a7bc959SXin LI }/*max 1 seconds*/ 4527a7bc959SXin LI }while(Retries++ < 20);/*max 20 sec*/ 4537a7bc959SXin LI return (FALSE); 4547a7bc959SXin LI } 4557a7bc959SXin LI /* 456a1103e04SXin LI ********************************************************************** 457a1103e04SXin LI ********************************************************************** 458a1103e04SXin LI */ 459a1103e04SXin LI static u_int8_t arcmsr_hbe_wait_msgint_ready(struct AdapterControlBlock *acb) 460a1103e04SXin LI { 461a1103e04SXin LI u_int32_t Index, read_doorbell; 462a1103e04SXin LI u_int8_t Retries = 0x00; 463a1103e04SXin LI 464a1103e04SXin LI do { 465a1103e04SXin LI for(Index=0; Index < 100; Index++) { 466a1103e04SXin LI read_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell); 467a1103e04SXin LI if((read_doorbell ^ acb->in_doorbell) & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) { 468a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0);/*clear interrupt*/ 469a1103e04SXin LI acb->in_doorbell = read_doorbell; 470a1103e04SXin LI return TRUE; 471a1103e04SXin LI } 472a1103e04SXin LI UDELAY(10000); 473a1103e04SXin LI }/*max 1 seconds*/ 474a1103e04SXin LI }while(Retries++ < 20);/*max 20 sec*/ 475a1103e04SXin LI return (FALSE); 476a1103e04SXin LI } 477a1103e04SXin LI /* 47844f05562SScott Long ************************************************************************ 47944f05562SScott Long ************************************************************************ 48044f05562SScott Long */ 48144f05562SScott Long static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) 48244f05562SScott Long { 48344f05562SScott Long int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ 48444f05562SScott Long 485d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 48644f05562SScott Long do { 48744f05562SScott Long if(arcmsr_hba_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 */ 49844f05562SScott Long static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) 49944f05562SScott Long { 50044f05562SScott Long int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ 501b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 50244f05562SScott Long 503b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_FLUSH_CACHE); 50444f05562SScott Long do { 50544f05562SScott Long if(arcmsr_hbb_wait_msgint_ready(acb)) { 50644f05562SScott Long break; 50744f05562SScott Long } else { 50844f05562SScott Long retry_count--; 50944f05562SScott Long } 51044f05562SScott Long }while(retry_count != 0); 51144f05562SScott Long } 51244f05562SScott Long /* 51344f05562SScott Long ************************************************************************ 51444f05562SScott Long ************************************************************************ 51544f05562SScott Long */ 516d74001adSXin LI static void arcmsr_flush_hbc_cache(struct AdapterControlBlock *acb) 517d74001adSXin LI { 518d74001adSXin LI int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ 519d74001adSXin LI 520d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 521d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 522d74001adSXin LI do { 523d74001adSXin LI if(arcmsr_hbc_wait_msgint_ready(acb)) { 524d74001adSXin LI break; 525d74001adSXin LI } else { 526d74001adSXin LI retry_count--; 527d74001adSXin LI } 528d74001adSXin LI }while(retry_count != 0); 529d74001adSXin LI } 530d74001adSXin LI /* 531d74001adSXin LI ************************************************************************ 532d74001adSXin LI ************************************************************************ 533d74001adSXin LI */ 5347a7bc959SXin LI static void arcmsr_flush_hbd_cache(struct AdapterControlBlock *acb) 5357a7bc959SXin LI { 5367a7bc959SXin LI int retry_count = 30; /* enlarge wait flush adapter cache time: 10 minute */ 5377a7bc959SXin LI 5387a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 5397a7bc959SXin LI do { 5407a7bc959SXin LI if(arcmsr_hbd_wait_msgint_ready(acb)) { 5417a7bc959SXin LI break; 5427a7bc959SXin LI } else { 5437a7bc959SXin LI retry_count--; 5447a7bc959SXin LI } 5457a7bc959SXin LI }while(retry_count != 0); 5467a7bc959SXin LI } 5477a7bc959SXin LI /* 5487a7bc959SXin LI ************************************************************************ 5497a7bc959SXin LI ************************************************************************ 5507a7bc959SXin LI */ 551a1103e04SXin LI static void arcmsr_flush_hbe_cache(struct AdapterControlBlock *acb) 552a1103e04SXin LI { 553a1103e04SXin LI int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ 554a1103e04SXin LI 555a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 556a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 557a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 558a1103e04SXin LI do { 559a1103e04SXin LI if(arcmsr_hbe_wait_msgint_ready(acb)) { 560a1103e04SXin LI break; 561a1103e04SXin LI } else { 562a1103e04SXin LI retry_count--; 563a1103e04SXin LI } 564a1103e04SXin LI }while(retry_count != 0); 565a1103e04SXin LI } 566a1103e04SXin LI /* 567a1103e04SXin LI ************************************************************************ 568a1103e04SXin LI ************************************************************************ 569a1103e04SXin LI */ 57044f05562SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) 57144f05562SScott Long { 57244f05562SScott Long switch (acb->adapter_type) { 57344f05562SScott Long case ACB_ADAPTER_TYPE_A: { 57444f05562SScott Long arcmsr_flush_hba_cache(acb); 57544f05562SScott Long } 57644f05562SScott Long break; 57744f05562SScott Long case ACB_ADAPTER_TYPE_B: { 57844f05562SScott Long arcmsr_flush_hbb_cache(acb); 57944f05562SScott Long } 58044f05562SScott Long break; 581d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 582d74001adSXin LI arcmsr_flush_hbc_cache(acb); 583d74001adSXin LI } 584d74001adSXin LI break; 5857a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 5867a7bc959SXin LI arcmsr_flush_hbd_cache(acb); 5877a7bc959SXin LI } 5887a7bc959SXin LI break; 589fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 590fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 591a1103e04SXin LI arcmsr_flush_hbe_cache(acb); 592a1103e04SXin LI } 593a1103e04SXin LI break; 59444f05562SScott Long } 59544f05562SScott Long } 59644f05562SScott Long /* 597ad6d6297SScott Long ******************************************************************************* 598ad6d6297SScott Long ******************************************************************************* 599f1c579b1SScott Long */ 600ad6d6297SScott Long static int arcmsr_suspend(device_t dev) 601f1c579b1SScott Long { 602ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 603f1c579b1SScott Long 604ad6d6297SScott Long /* flush controller */ 605ad6d6297SScott Long arcmsr_iop_parking(acb); 606d74001adSXin LI /* disable all outbound interrupt */ 607d74001adSXin LI arcmsr_disable_allintr(acb); 608ad6d6297SScott Long return(0); 609ad6d6297SScott Long } 610ad6d6297SScott Long /* 611ad6d6297SScott Long ******************************************************************************* 612ad6d6297SScott Long ******************************************************************************* 613ad6d6297SScott Long */ 614ad6d6297SScott Long static int arcmsr_resume(device_t dev) 615ad6d6297SScott Long { 616ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 617f1c579b1SScott Long 618ad6d6297SScott Long arcmsr_iop_init(acb); 619ad6d6297SScott Long return(0); 620f1c579b1SScott Long } 621f1c579b1SScott Long /* 622f1c579b1SScott Long ********************************************************************************* 623f1c579b1SScott Long ********************************************************************************* 624f1c579b1SScott Long */ 625ad6d6297SScott Long static void arcmsr_async(void *cb_arg, u_int32_t code, struct cam_path *path, void *arg) 626f1c579b1SScott Long { 627ad6d6297SScott Long u_int8_t target_id, target_lun; 628f1c579b1SScott Long 629ad6d6297SScott Long switch (code) { 630f1c579b1SScott Long case AC_LOST_DEVICE: 631f1c579b1SScott Long target_id = xpt_path_target_id(path); 632f1c579b1SScott Long target_lun = xpt_path_lun_id(path); 633d74001adSXin LI if((target_id > ARCMSR_MAX_TARGETID) || (target_lun > ARCMSR_MAX_TARGETLUN)) { 634f1c579b1SScott Long break; 635f1c579b1SScott Long } 636f1c579b1SScott Long break; 637f1c579b1SScott Long default: 638f1c579b1SScott Long break; 639f1c579b1SScott Long } 640f1c579b1SScott Long } 641f1c579b1SScott Long /* 642f1c579b1SScott Long ********************************************************************** 643f1c579b1SScott Long ********************************************************************** 644f1c579b1SScott Long */ 645ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb) 646f1c579b1SScott Long { 647ad6d6297SScott Long union ccb *pccb = srb->pccb; 648f1c579b1SScott Long 649ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 650ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 651dac36688SXin LI if(pccb->csio.sense_len) { 652ad6d6297SScott Long memset(&pccb->csio.sense_data, 0, sizeof(pccb->csio.sense_data)); 653ad6d6297SScott Long memcpy(&pccb->csio.sense_data, srb->arcmsr_cdb.SenseData, 654ad6d6297SScott Long get_min(sizeof(struct SENSE_DATA), sizeof(pccb->csio.sense_data))); 655ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); /* Valid,ErrorCode */ 656f1c579b1SScott Long pccb->ccb_h.status |= CAM_AUTOSNS_VALID; 657f1c579b1SScott Long } 658f1c579b1SScott Long } 659f1c579b1SScott Long /* 660f1c579b1SScott Long ********************************************************************* 66144f05562SScott Long ********************************************************************* 66244f05562SScott Long */ 66344f05562SScott Long static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) 66444f05562SScott Long { 66544f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 66644f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 667d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 66844f05562SScott Long } 66944f05562SScott Long } 67044f05562SScott Long /* 67144f05562SScott Long ********************************************************************* 67244f05562SScott Long ********************************************************************* 67344f05562SScott Long */ 67444f05562SScott Long static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) 67544f05562SScott Long { 676b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 677b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_ABORT_CMD); 67844f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 679d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 680d74001adSXin LI } 681d74001adSXin LI } 682d74001adSXin LI /* 683d74001adSXin LI ********************************************************************* 684d74001adSXin LI ********************************************************************* 685d74001adSXin LI */ 686d74001adSXin LI static void arcmsr_abort_hbc_allcmd(struct AdapterControlBlock *acb) 687d74001adSXin LI { 688d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 689d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 690d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 691d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 69244f05562SScott Long } 69344f05562SScott Long } 69444f05562SScott Long /* 69544f05562SScott Long ********************************************************************* 696f1c579b1SScott Long ********************************************************************* 697f1c579b1SScott Long */ 6987a7bc959SXin LI static void arcmsr_abort_hbd_allcmd(struct AdapterControlBlock *acb) 6997a7bc959SXin LI { 7007a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 7017a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 7027a7bc959SXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 7037a7bc959SXin LI } 7047a7bc959SXin LI } 7057a7bc959SXin LI /* 7067a7bc959SXin LI ********************************************************************* 7077a7bc959SXin LI ********************************************************************* 7087a7bc959SXin LI */ 709a1103e04SXin LI static void arcmsr_abort_hbe_allcmd(struct AdapterControlBlock *acb) 710a1103e04SXin LI { 711a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 712a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 713a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 714a1103e04SXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) { 715a1103e04SXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 716a1103e04SXin LI } 717a1103e04SXin LI } 718a1103e04SXin LI /* 719a1103e04SXin LI ********************************************************************* 720a1103e04SXin LI ********************************************************************* 721a1103e04SXin LI */ 722ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) 723f1c579b1SScott Long { 72444f05562SScott Long switch (acb->adapter_type) { 72544f05562SScott Long case ACB_ADAPTER_TYPE_A: { 72644f05562SScott Long arcmsr_abort_hba_allcmd(acb); 72744f05562SScott Long } 72844f05562SScott Long break; 72944f05562SScott Long case ACB_ADAPTER_TYPE_B: { 73044f05562SScott Long arcmsr_abort_hbb_allcmd(acb); 73144f05562SScott Long } 73244f05562SScott Long break; 733d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 734d74001adSXin LI arcmsr_abort_hbc_allcmd(acb); 735d74001adSXin LI } 736d74001adSXin LI break; 7377a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 7387a7bc959SXin LI arcmsr_abort_hbd_allcmd(acb); 7397a7bc959SXin LI } 7407a7bc959SXin LI break; 741fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 742fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 743a1103e04SXin LI arcmsr_abort_hbe_allcmd(acb); 744a1103e04SXin LI } 745a1103e04SXin LI break; 74644f05562SScott Long } 74744f05562SScott Long } 74844f05562SScott Long /* 749231c8b71SXin LI ********************************************************************** 750231c8b71SXin LI ********************************************************************** 751231c8b71SXin LI */ 752231c8b71SXin LI static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag) 753231c8b71SXin LI { 754231c8b71SXin LI struct AdapterControlBlock *acb = srb->acb; 755231c8b71SXin LI union ccb *pccb = srb->pccb; 756231c8b71SXin LI 75722f2616bSXin LI if(srb->srb_flags & SRB_FLAG_TIMER_START) 75822f2616bSXin LI callout_stop(&srb->ccb_callout); 759231c8b71SXin LI if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 760231c8b71SXin LI bus_dmasync_op_t op; 761231c8b71SXin LI 762231c8b71SXin LI if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 763231c8b71SXin LI op = BUS_DMASYNC_POSTREAD; 764231c8b71SXin LI } else { 765231c8b71SXin LI op = BUS_DMASYNC_POSTWRITE; 766231c8b71SXin LI } 767231c8b71SXin LI bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 768231c8b71SXin LI bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 769231c8b71SXin LI } 770231c8b71SXin LI if(stand_flag == 1) { 771231c8b71SXin LI atomic_subtract_int(&acb->srboutstandingcount, 1); 772231c8b71SXin LI if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) && ( 773abfdbca9SXin LI acb->srboutstandingcount < (acb->maxOutstanding -10))) { 774231c8b71SXin LI acb->acb_flags &= ~ACB_F_CAM_DEV_QFRZN; 775231c8b71SXin LI pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 776231c8b71SXin LI } 777231c8b71SXin LI } 77822f2616bSXin LI if(srb->srb_state != ARCMSR_SRB_TIMEOUT) 77922f2616bSXin LI arcmsr_free_srb(srb); 78022f2616bSXin LI acb->pktReturnCount++; 781231c8b71SXin LI xpt_done(pccb); 782231c8b71SXin LI } 783231c8b71SXin LI /* 78444f05562SScott Long ************************************************************************** 78544f05562SScott Long ************************************************************************** 78644f05562SScott Long */ 787d74001adSXin LI static void arcmsr_report_srb_state(struct AdapterControlBlock *acb, struct CommandControlBlock *srb, u_int16_t error) 78844f05562SScott Long { 78944f05562SScott Long int target, lun; 79044f05562SScott Long 79144f05562SScott Long target = srb->pccb->ccb_h.target_id; 79244f05562SScott Long lun = srb->pccb->ccb_h.target_lun; 793d74001adSXin LI if(error == FALSE) { 79444f05562SScott Long if(acb->devstate[target][lun] == ARECA_RAID_GONE) { 79544f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GOOD; 79644f05562SScott Long } 79744f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_CMP; 79844f05562SScott Long arcmsr_srb_complete(srb, 1); 79944f05562SScott Long } else { 80044f05562SScott Long switch(srb->arcmsr_cdb.DeviceStatus) { 80144f05562SScott Long case ARCMSR_DEV_SELECT_TIMEOUT: { 80244f05562SScott Long if(acb->devstate[target][lun] == ARECA_RAID_GOOD) { 803d74001adSXin LI printf( "arcmsr%d: Target=%x, Lun=%x, selection timeout, raid volume was lost\n", acb->pci_unit, target, lun); 804ad6d6297SScott Long } 80544f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GONE; 806d74001adSXin LI srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 80744f05562SScott Long arcmsr_srb_complete(srb, 1); 80844f05562SScott Long } 80944f05562SScott Long break; 81044f05562SScott Long case ARCMSR_DEV_ABORTED: 81144f05562SScott Long case ARCMSR_DEV_INIT_FAIL: { 81244f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GONE; 81344f05562SScott Long srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 81444f05562SScott Long arcmsr_srb_complete(srb, 1); 81544f05562SScott Long } 81644f05562SScott Long break; 81744f05562SScott Long case SCSISTAT_CHECK_CONDITION: { 81844f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GOOD; 81944f05562SScott Long arcmsr_report_sense_info(srb); 82044f05562SScott Long arcmsr_srb_complete(srb, 1); 82144f05562SScott Long } 82244f05562SScott Long break; 82344f05562SScott Long default: 82410d66948SKevin Lo printf("arcmsr%d: scsi id=%d lun=%d isr got command error done,but got unknown DeviceStatus=0x%x \n" 825d74001adSXin LI , acb->pci_unit, target, lun ,srb->arcmsr_cdb.DeviceStatus); 82644f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GONE; 82744f05562SScott Long srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY; 82810d66948SKevin Lo /*unknown error or crc error just for retry*/ 82944f05562SScott Long arcmsr_srb_complete(srb, 1); 83044f05562SScott Long break; 83144f05562SScott Long } 83244f05562SScott Long } 83344f05562SScott Long } 83444f05562SScott Long /* 83544f05562SScott Long ************************************************************************** 83644f05562SScott Long ************************************************************************** 83744f05562SScott Long */ 838d74001adSXin LI static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t flag_srb, u_int16_t error) 83944f05562SScott Long { 84044f05562SScott Long struct CommandControlBlock *srb; 84144f05562SScott Long 84244f05562SScott Long /* check if command done with no error*/ 843d74001adSXin LI switch (acb->adapter_type) { 844fc5ef1caSXin LI case ACB_ADAPTER_TYPE_A: 845fc5ef1caSXin LI case ACB_ADAPTER_TYPE_B: 846fc5ef1caSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 847fc5ef1caSXin LI break; 848d74001adSXin LI case ACB_ADAPTER_TYPE_C: 8497a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 85022f2616bSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0)); /*frame must be 32 bytes aligned*/ 851d74001adSXin LI break; 852a1103e04SXin LI case ACB_ADAPTER_TYPE_E: 853fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 854a1103e04SXin LI srb = acb->psrb_pool[flag_srb]; 855a1103e04SXin LI break; 856d74001adSXin LI default: 857d74001adSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 858d74001adSXin LI break; 859d74001adSXin LI } 86022f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 86122f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_TIMEOUT) { 86222f2616bSXin LI arcmsr_free_srb(srb); 86322f2616bSXin LI printf("arcmsr%d: srb='%p' return srb has been timeouted\n", acb->pci_unit, srb); 86444f05562SScott Long return; 86544f05562SScott Long } 86622f2616bSXin LI printf("arcmsr%d: return srb has been completed\n" 86722f2616bSXin LI "srb='%p' srb_state=0x%x outstanding srb count=%d \n", 86822f2616bSXin LI acb->pci_unit, srb, srb->srb_state, acb->srboutstandingcount); 86944f05562SScott Long return; 87044f05562SScott Long } 871d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 87244f05562SScott Long } 87344f05562SScott Long /* 87422f2616bSXin LI ************************************************************************** 87522f2616bSXin LI ************************************************************************** 87622f2616bSXin LI */ 87722f2616bSXin LI static void arcmsr_srb_timeout(void *arg) 87822f2616bSXin LI { 87922f2616bSXin LI struct CommandControlBlock *srb = (struct CommandControlBlock *)arg; 88022f2616bSXin LI struct AdapterControlBlock *acb; 88122f2616bSXin LI int target, lun; 88222f2616bSXin LI u_int8_t cmd; 88322f2616bSXin LI 88422f2616bSXin LI target = srb->pccb->ccb_h.target_id; 88522f2616bSXin LI lun = srb->pccb->ccb_h.target_lun; 88622f2616bSXin LI acb = srb->acb; 8877a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 88822f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) 88922f2616bSXin LI { 8904aa947cbSWarner Losh cmd = scsiio_cdb_ptr(&srb->pccb->csio)[0]; 89122f2616bSXin LI srb->srb_state = ARCMSR_SRB_TIMEOUT; 89222f2616bSXin LI srb->pccb->ccb_h.status |= CAM_CMD_TIMEOUT; 89322f2616bSXin LI arcmsr_srb_complete(srb, 1); 89422f2616bSXin LI printf("arcmsr%d: scsi id %d lun %d cmd=0x%x srb='%p' ccb command time out!\n", 89522f2616bSXin LI acb->pci_unit, target, lun, cmd, srb); 89622f2616bSXin LI } 8977a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 89822f2616bSXin LI #ifdef ARCMSR_DEBUG1 89922f2616bSXin LI arcmsr_dump_data(acb); 90022f2616bSXin LI #endif 90122f2616bSXin LI } 90222f2616bSXin LI 90322f2616bSXin LI /* 90444f05562SScott Long ********************************************************************** 90544f05562SScott Long ********************************************************************** 90644f05562SScott Long */ 90744f05562SScott Long static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) 90844f05562SScott Long { 90944f05562SScott Long int i=0; 91044f05562SScott Long u_int32_t flag_srb; 911d74001adSXin LI u_int16_t error; 91244f05562SScott Long 91344f05562SScott Long switch (acb->adapter_type) { 91444f05562SScott Long case ACB_ADAPTER_TYPE_A: { 91544f05562SScott Long u_int32_t outbound_intstatus; 91644f05562SScott Long 91744f05562SScott Long /*clear and abort all outbound posted Q*/ 918d74001adSXin LI outbound_intstatus = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 919d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/ 920d74001adSXin LI while(((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_queueport)) != 0xFFFFFFFF) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { 921d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 922d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 92344f05562SScott Long } 92444f05562SScott Long } 92544f05562SScott Long break; 92644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 92744f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 92844f05562SScott Long 92944f05562SScott Long /*clear all outbound posted Q*/ 930b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 93144f05562SScott Long for(i=0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) { 93244f05562SScott Long if((flag_srb = phbbmu->done_qbuffer[i]) != 0) { 93344f05562SScott Long phbbmu->done_qbuffer[i] = 0; 934d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 935d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 93644f05562SScott Long } 93744f05562SScott Long phbbmu->post_qbuffer[i] = 0; 93844f05562SScott Long }/*drain reply FIFO*/ 93944f05562SScott Long phbbmu->doneq_index = 0; 94044f05562SScott Long phbbmu->postq_index = 0; 94144f05562SScott Long } 94244f05562SScott Long break; 943d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 944d74001adSXin LI while((CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { 945d74001adSXin LI flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 946d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 947d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 948d74001adSXin LI } 949d74001adSXin LI } 950d74001adSXin LI break; 951fa42a0bfSXin LI case ACB_ADAPTER_TYPE_D: 9527a7bc959SXin LI arcmsr_hbd_postqueue_isr(acb); 9537a7bc959SXin LI break; 954fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 955a1103e04SXin LI arcmsr_hbe_postqueue_isr(acb); 956fa42a0bfSXin LI break; 957fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 958fa42a0bfSXin LI arcmsr_hbf_postqueue_isr(acb); 959a1103e04SXin LI break; 96044f05562SScott Long } 961f1c579b1SScott Long } 962f1c579b1SScott Long /* 963f1c579b1SScott Long **************************************************************************** 964f1c579b1SScott Long **************************************************************************** 965f1c579b1SScott Long */ 966ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb) 967f1c579b1SScott Long { 968ad6d6297SScott Long struct CommandControlBlock *srb; 96944f05562SScott Long u_int32_t intmask_org; 970ad6d6297SScott Long u_int32_t i=0; 971f1c579b1SScott Long 97244f05562SScott Long if(acb->srboutstandingcount>0) { 97344f05562SScott Long /* disable all outbound interrupt */ 97444f05562SScott Long intmask_org = arcmsr_disable_allintr(acb); 97544f05562SScott Long /*clear and abort all outbound posted Q*/ 97644f05562SScott Long arcmsr_done4abort_postqueue(acb); 977f1c579b1SScott Long /* talk to iop 331 outstanding command aborted*/ 978ad6d6297SScott Long arcmsr_abort_allcmd(acb); 979ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 980ad6d6297SScott Long srb = acb->psrb_pool[i]; 98122f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) { 98222f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 983ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 984ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 985123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p' aborted\n" 98622f2616bSXin LI , acb->pci_unit, srb->pccb->ccb_h.target_id 987123055f0SNathan Whitehorn , (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 988f1c579b1SScott Long } 989f1c579b1SScott Long } 990f1c579b1SScott Long /* enable all outbound interrupt */ 99144f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 992f1c579b1SScott Long } 99322f2616bSXin LI acb->srboutstandingcount = 0; 994ad6d6297SScott Long acb->workingsrb_doneindex = 0; 995ad6d6297SScott Long acb->workingsrb_startindex = 0; 99622f2616bSXin LI acb->pktRequestCount = 0; 99722f2616bSXin LI acb->pktReturnCount = 0; 998f1c579b1SScott Long } 999f1c579b1SScott Long /* 1000f1c579b1SScott Long ********************************************************************** 1001f1c579b1SScott Long ********************************************************************** 1002f1c579b1SScott Long */ 100344f05562SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, 100444f05562SScott Long bus_dma_segment_t *dm_segs, u_int32_t nseg) 1005f1c579b1SScott Long { 1006ad6d6297SScott Long struct ARCMSR_CDB *arcmsr_cdb = &srb->arcmsr_cdb; 1007ad6d6297SScott Long u_int8_t *psge = (u_int8_t *)&arcmsr_cdb->u; 1008ad6d6297SScott Long u_int32_t address_lo, address_hi; 1009ad6d6297SScott Long union ccb *pccb = srb->pccb; 1010f1c579b1SScott Long struct ccb_scsiio *pcsio = &pccb->csio; 1011ad6d6297SScott Long u_int32_t arccdbsize = 0x30; 1012f1c579b1SScott Long 1013ad6d6297SScott Long memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB)); 1014ad6d6297SScott Long arcmsr_cdb->Bus = 0; 1015ad6d6297SScott Long arcmsr_cdb->TargetID = pccb->ccb_h.target_id; 1016ad6d6297SScott Long arcmsr_cdb->LUN = pccb->ccb_h.target_lun; 1017ad6d6297SScott Long arcmsr_cdb->Function = 1; 1018ad6d6297SScott Long arcmsr_cdb->CdbLength = (u_int8_t)pcsio->cdb_len; 10194aa947cbSWarner Losh bcopy(scsiio_cdb_ptr(pcsio), arcmsr_cdb->Cdb, pcsio->cdb_len); 1020ad6d6297SScott Long if(nseg != 0) { 1021ad6d6297SScott Long struct AdapterControlBlock *acb = srb->acb; 1022f1c579b1SScott Long bus_dmasync_op_t op; 1023ad6d6297SScott Long u_int32_t length, i, cdb_sgcount = 0; 1024f1c579b1SScott Long 1025ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 1026ad6d6297SScott Long op = BUS_DMASYNC_PREREAD; 1027ad6d6297SScott Long } else { 1028ad6d6297SScott Long op = BUS_DMASYNC_PREWRITE; 1029ad6d6297SScott Long arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE; 1030ad6d6297SScott Long srb->srb_flags |= SRB_FLAG_WRITE; 1031ad6d6297SScott Long } 1032ad6d6297SScott Long bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 1033ad6d6297SScott Long for(i=0; i < nseg; i++) { 1034f1c579b1SScott Long /* Get the physical address of the current data pointer */ 1035ad6d6297SScott Long length = arcmsr_htole32(dm_segs[i].ds_len); 1036ad6d6297SScott Long address_lo = arcmsr_htole32(dma_addr_lo32(dm_segs[i].ds_addr)); 1037ad6d6297SScott Long address_hi = arcmsr_htole32(dma_addr_hi32(dm_segs[i].ds_addr)); 1038ad6d6297SScott Long if(address_hi == 0) { 1039ad6d6297SScott Long struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge; 1040f1c579b1SScott Long pdma_sg->address = address_lo; 1041f1c579b1SScott Long pdma_sg->length = length; 1042ad6d6297SScott Long psge += sizeof(struct SG32ENTRY); 1043ad6d6297SScott Long arccdbsize += sizeof(struct SG32ENTRY); 1044ad6d6297SScott Long } else { 1045ad6d6297SScott Long u_int32_t sg64s_size = 0, tmplength = length; 1046f1c579b1SScott Long 1047ad6d6297SScott Long while(1) { 1048ad6d6297SScott Long u_int64_t span4G, length0; 1049ad6d6297SScott Long struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge; 1050f1c579b1SScott Long 1051ad6d6297SScott Long span4G = (u_int64_t)address_lo + tmplength; 1052f1c579b1SScott Long pdma_sg->addresshigh = address_hi; 1053f1c579b1SScott Long pdma_sg->address = address_lo; 1054ad6d6297SScott Long if(span4G > 0x100000000) { 1055f1c579b1SScott Long /*see if cross 4G boundary*/ 1056f1c579b1SScott Long length0 = 0x100000000-address_lo; 1057ad6d6297SScott Long pdma_sg->length = (u_int32_t)length0 | IS_SG64_ADDR; 1058f1c579b1SScott Long address_hi = address_hi+1; 1059f1c579b1SScott Long address_lo = 0; 1060ad6d6297SScott Long tmplength = tmplength - (u_int32_t)length0; 1061ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 1062ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 1063f1c579b1SScott Long cdb_sgcount++; 1064ad6d6297SScott Long } else { 1065f1c579b1SScott Long pdma_sg->length = tmplength | IS_SG64_ADDR; 1066ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 1067ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 1068f1c579b1SScott Long break; 1069f1c579b1SScott Long } 1070f1c579b1SScott Long } 1071f1c579b1SScott Long arccdbsize += sg64s_size; 1072f1c579b1SScott Long } 1073f1c579b1SScott Long cdb_sgcount++; 1074f1c579b1SScott Long } 1075ad6d6297SScott Long arcmsr_cdb->sgcount = (u_int8_t)cdb_sgcount; 1076ad6d6297SScott Long arcmsr_cdb->DataLength = pcsio->dxfer_len; 1077ad6d6297SScott Long if( arccdbsize > 256) { 1078ad6d6297SScott Long arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE; 1079f1c579b1SScott Long } 1080d74001adSXin LI } else { 1081d74001adSXin LI arcmsr_cdb->DataLength = 0; 1082f1c579b1SScott Long } 1083d74001adSXin LI srb->arc_cdb_size = arccdbsize; 10847a7bc959SXin LI arcmsr_cdb->msgPages = (arccdbsize/256) + ((arccdbsize % 256) ? 1 : 0); 1085f1c579b1SScott Long } 1086f1c579b1SScott Long /* 1087f1c579b1SScott Long ************************************************************************** 1088f1c579b1SScott Long ************************************************************************** 1089f1c579b1SScott Long */ 1090ad6d6297SScott Long static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandControlBlock *srb) 1091f1c579b1SScott Long { 10927a7bc959SXin LI u_int32_t cdb_phyaddr_low = (u_int32_t) srb->cdb_phyaddr_low; 1093ad6d6297SScott Long struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&srb->arcmsr_cdb; 1094f1c579b1SScott Long 1095d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, (srb->srb_flags & SRB_FLAG_WRITE) ? BUS_DMASYNC_POSTWRITE:BUS_DMASYNC_POSTREAD); 1096ad6d6297SScott Long atomic_add_int(&acb->srboutstandingcount, 1); 109722f2616bSXin LI srb->srb_state = ARCMSR_SRB_START; 1098d74001adSXin LI 109944f05562SScott Long switch (acb->adapter_type) { 110044f05562SScott Long case ACB_ADAPTER_TYPE_A: { 1101ad6d6297SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 11027a7bc959SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_phyaddr_low|ARCMSR_SRBPOST_FLAG_SGL_BSIZE); 1103ad6d6297SScott Long } else { 11047a7bc959SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_phyaddr_low); 110544f05562SScott Long } 110644f05562SScott Long } 110744f05562SScott Long break; 110844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 110944f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 111044f05562SScott Long int ending_index, index; 111144f05562SScott Long 111244f05562SScott Long index = phbbmu->postq_index; 111344f05562SScott Long ending_index = ((index+1) % ARCMSR_MAX_HBB_POSTQUEUE); 111444f05562SScott Long phbbmu->post_qbuffer[ending_index] = 0; 111544f05562SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 11167a7bc959SXin LI phbbmu->post_qbuffer[index] = cdb_phyaddr_low | ARCMSR_SRBPOST_FLAG_SGL_BSIZE; 111744f05562SScott Long } else { 11187a7bc959SXin LI phbbmu->post_qbuffer[index] = cdb_phyaddr_low; 111944f05562SScott Long } 112044f05562SScott Long index++; 112144f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 112244f05562SScott Long phbbmu->postq_index = index; 1123b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED); 1124d74001adSXin LI } 1125d74001adSXin LI break; 11267a7bc959SXin LI case ACB_ADAPTER_TYPE_C: { 1127d74001adSXin LI u_int32_t ccb_post_stamp, arc_cdb_size, cdb_phyaddr_hi32; 1128d74001adSXin LI 1129d74001adSXin LI arc_cdb_size = (srb->arc_cdb_size > 0x300) ? 0x300 : srb->arc_cdb_size; 11307a7bc959SXin LI ccb_post_stamp = (cdb_phyaddr_low | ((arc_cdb_size-1) >> 6) | 1); 1131d74001adSXin LI cdb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high; 1132d74001adSXin LI if(cdb_phyaddr_hi32) 1133d74001adSXin LI { 1134d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_high, cdb_phyaddr_hi32); 1135d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp); 1136d74001adSXin LI } 1137d74001adSXin LI else 1138d74001adSXin LI { 1139d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp); 1140d74001adSXin LI } 114144f05562SScott Long } 114244f05562SScott Long break; 11437a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 11447a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 11457a7bc959SXin LI u_int16_t index_stripped; 11467a7bc959SXin LI u_int16_t postq_index; 11477a7bc959SXin LI struct InBound_SRB *pinbound_srb; 11487a7bc959SXin LI 11497a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->postDone_lock); 11507a7bc959SXin LI postq_index = phbdmu->postq_index; 11517a7bc959SXin LI pinbound_srb = (struct InBound_SRB *)&phbdmu->post_qbuffer[postq_index & 0xFF]; 11527a7bc959SXin LI pinbound_srb->addressHigh = srb->cdb_phyaddr_high; 11537a7bc959SXin LI pinbound_srb->addressLow = srb->cdb_phyaddr_low; 11547a7bc959SXin LI pinbound_srb->length = srb->arc_cdb_size >> 2; 11557a7bc959SXin LI arcmsr_cdb->Context = srb->cdb_phyaddr_low; 11567a7bc959SXin LI if (postq_index & 0x4000) { 11577a7bc959SXin LI index_stripped = postq_index & 0xFF; 11587a7bc959SXin LI index_stripped += 1; 11597a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 11607a7bc959SXin LI phbdmu->postq_index = index_stripped ? (index_stripped | 0x4000) : index_stripped; 11617a7bc959SXin LI } else { 11627a7bc959SXin LI index_stripped = postq_index; 11637a7bc959SXin LI index_stripped += 1; 11647a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 11657a7bc959SXin LI phbdmu->postq_index = index_stripped ? index_stripped : (index_stripped | 0x4000); 11667a7bc959SXin LI } 11677a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inboundlist_write_pointer, postq_index); 11687a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->postDone_lock); 11697a7bc959SXin LI } 11707a7bc959SXin LI break; 1171a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 1172a1103e04SXin LI u_int32_t ccb_post_stamp, arc_cdb_size; 1173a1103e04SXin LI 1174a1103e04SXin LI arc_cdb_size = (srb->arc_cdb_size > 0x300) ? 0x300 : srb->arc_cdb_size; 1175a1103e04SXin LI ccb_post_stamp = (srb->smid | ((arc_cdb_size-1) >> 6)); 1176a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_queueport_high, 0); 1177a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_queueport_low, ccb_post_stamp); 1178a1103e04SXin LI } 1179a1103e04SXin LI break; 1180fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 1181fa42a0bfSXin LI u_int32_t ccb_post_stamp, arc_cdb_size; 1182fa42a0bfSXin LI 1183fa42a0bfSXin LI if (srb->arc_cdb_size <= 0x300) 1184fa42a0bfSXin LI arc_cdb_size = (srb->arc_cdb_size - 1) >> 6 | 1; 1185438b5532SXin LI else { 1186438b5532SXin LI arc_cdb_size = ((srb->arc_cdb_size + 0xff) >> 8) + 2; 1187438b5532SXin LI if (arc_cdb_size > 0xF) 1188438b5532SXin LI arc_cdb_size = 0xF; 1189438b5532SXin LI arc_cdb_size = (arc_cdb_size << 1) | 1; 1190438b5532SXin LI } 1191fa42a0bfSXin LI ccb_post_stamp = (srb->smid | arc_cdb_size); 1192fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_queueport_high, 0); 1193fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_queueport_low, ccb_post_stamp); 1194fa42a0bfSXin LI } 1195fa42a0bfSXin LI break; 1196f1c579b1SScott Long } 1197f1c579b1SScott Long } 1198f1c579b1SScott Long /* 119944f05562SScott Long ************************************************************************ 120044f05562SScott Long ************************************************************************ 120144f05562SScott Long */ 120244f05562SScott Long static struct QBUFFER *arcmsr_get_iop_rqbuffer( struct AdapterControlBlock *acb) 120344f05562SScott Long { 120444f05562SScott Long struct QBUFFER *qbuffer=NULL; 120544f05562SScott Long 120644f05562SScott Long switch (acb->adapter_type) { 120744f05562SScott Long case ACB_ADAPTER_TYPE_A: { 120844f05562SScott Long struct HBA_MessageUnit *phbamu = (struct HBA_MessageUnit *)acb->pmu; 120944f05562SScott Long 121044f05562SScott Long qbuffer = (struct QBUFFER *)&phbamu->message_rbuffer; 121144f05562SScott Long } 121244f05562SScott Long break; 121344f05562SScott Long case ACB_ADAPTER_TYPE_B: { 121444f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 121544f05562SScott Long 121644f05562SScott Long qbuffer = (struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_rbuffer; 121744f05562SScott Long } 121844f05562SScott Long break; 1219d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1220d74001adSXin LI struct HBC_MessageUnit *phbcmu = (struct HBC_MessageUnit *)acb->pmu; 1221d74001adSXin LI 1222d74001adSXin LI qbuffer = (struct QBUFFER *)&phbcmu->message_rbuffer; 1223d74001adSXin LI } 1224d74001adSXin LI break; 12257a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 12267a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 12277a7bc959SXin LI 12287a7bc959SXin LI qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_rbuffer; 12297a7bc959SXin LI } 12307a7bc959SXin LI break; 1231a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 1232a1103e04SXin LI struct HBE_MessageUnit *phbcmu = (struct HBE_MessageUnit *)acb->pmu; 1233a1103e04SXin LI 1234a1103e04SXin LI qbuffer = (struct QBUFFER *)&phbcmu->message_rbuffer; 1235a1103e04SXin LI } 1236a1103e04SXin LI break; 1237fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 1238fa42a0bfSXin LI qbuffer = (struct QBUFFER *)acb->message_rbuffer; 1239fa42a0bfSXin LI break; 124044f05562SScott Long } 124144f05562SScott Long return(qbuffer); 124244f05562SScott Long } 124344f05562SScott Long /* 124444f05562SScott Long ************************************************************************ 124544f05562SScott Long ************************************************************************ 124644f05562SScott Long */ 124744f05562SScott Long static struct QBUFFER *arcmsr_get_iop_wqbuffer( struct AdapterControlBlock *acb) 124844f05562SScott Long { 124944f05562SScott Long struct QBUFFER *qbuffer = NULL; 125044f05562SScott Long 125144f05562SScott Long switch (acb->adapter_type) { 125244f05562SScott Long case ACB_ADAPTER_TYPE_A: { 125344f05562SScott Long struct HBA_MessageUnit *phbamu = (struct HBA_MessageUnit *)acb->pmu; 125444f05562SScott Long 125544f05562SScott Long qbuffer = (struct QBUFFER *)&phbamu->message_wbuffer; 125644f05562SScott Long } 125744f05562SScott Long break; 125844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 125944f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 126044f05562SScott Long 126144f05562SScott Long qbuffer = (struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_wbuffer; 126244f05562SScott Long } 126344f05562SScott Long break; 1264d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1265d74001adSXin LI struct HBC_MessageUnit *phbcmu = (struct HBC_MessageUnit *)acb->pmu; 1266d74001adSXin LI 1267d74001adSXin LI qbuffer = (struct QBUFFER *)&phbcmu->message_wbuffer; 1268d74001adSXin LI } 1269d74001adSXin LI break; 12707a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 12717a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 12727a7bc959SXin LI 12737a7bc959SXin LI qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_wbuffer; 12747a7bc959SXin LI } 12757a7bc959SXin LI break; 1276a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 1277a1103e04SXin LI struct HBE_MessageUnit *phbcmu = (struct HBE_MessageUnit *)acb->pmu; 1278a1103e04SXin LI 1279a1103e04SXin LI qbuffer = (struct QBUFFER *)&phbcmu->message_wbuffer; 1280a1103e04SXin LI } 1281a1103e04SXin LI break; 1282fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 1283fa42a0bfSXin LI qbuffer = (struct QBUFFER *)acb->message_wbuffer; 1284fa42a0bfSXin LI break; 128544f05562SScott Long } 128644f05562SScott Long return(qbuffer); 128744f05562SScott Long } 128844f05562SScott Long /* 128944f05562SScott Long ************************************************************************** 129044f05562SScott Long ************************************************************************** 129144f05562SScott Long */ 129244f05562SScott Long static void arcmsr_iop_message_read(struct AdapterControlBlock *acb) 129344f05562SScott Long { 129444f05562SScott Long switch (acb->adapter_type) { 129544f05562SScott Long case ACB_ADAPTER_TYPE_A: { 129644f05562SScott Long /* let IOP know data has been read */ 1297d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 129844f05562SScott Long } 129944f05562SScott Long break; 130044f05562SScott Long case ACB_ADAPTER_TYPE_B: { 1301b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 130244f05562SScott Long /* let IOP know data has been read */ 1303b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 130444f05562SScott Long } 130544f05562SScott Long break; 1306d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1307d74001adSXin LI /* let IOP know data has been read */ 1308d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK); 1309d74001adSXin LI } 13107a7bc959SXin LI break; 13117a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 13127a7bc959SXin LI /* let IOP know data has been read */ 13137a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ); 13147a7bc959SXin LI } 13157a7bc959SXin LI break; 1316fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 1317fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 1318a1103e04SXin LI /* let IOP know data has been read */ 1319a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK; 1320a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 1321a1103e04SXin LI } 1322a1103e04SXin LI break; 132344f05562SScott Long } 132444f05562SScott Long } 132544f05562SScott Long /* 132644f05562SScott Long ************************************************************************** 132744f05562SScott Long ************************************************************************** 132844f05562SScott Long */ 132944f05562SScott Long static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) 133044f05562SScott Long { 133144f05562SScott Long switch (acb->adapter_type) { 133244f05562SScott Long case ACB_ADAPTER_TYPE_A: { 133344f05562SScott Long /* 133444f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 133544f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 133644f05562SScott Long */ 1337d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK); 133844f05562SScott Long } 133944f05562SScott Long break; 134044f05562SScott Long case ACB_ADAPTER_TYPE_B: { 1341b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 134244f05562SScott Long /* 134344f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 134444f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 134544f05562SScott Long */ 1346b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_WRITE_OK); 1347d74001adSXin LI } 1348d74001adSXin LI break; 1349d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1350d74001adSXin LI /* 1351d74001adSXin LI ** push inbound doorbell tell iop, driver data write ok 1352d74001adSXin LI ** and wait reply on next hwinterrupt for next Qbuffer post 1353d74001adSXin LI */ 1354d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK); 135544f05562SScott Long } 135644f05562SScott Long break; 13577a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 135844f05562SScott Long /* 13597a7bc959SXin LI ** push inbound doorbell tell iop, driver data write ok 13607a7bc959SXin LI ** and wait reply on next hwinterrupt for next Qbuffer post 1361f1c579b1SScott Long */ 13627a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_IN_READY); 1363f1c579b1SScott Long } 13647a7bc959SXin LI break; 1365fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 1366fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 1367a1103e04SXin LI /* 1368a1103e04SXin LI ** push inbound doorbell tell iop, driver data write ok 1369a1103e04SXin LI ** and wait reply on next hwinterrupt for next Qbuffer post 1370a1103e04SXin LI */ 1371a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_WRITE_OK; 1372a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 1373a1103e04SXin LI } 1374a1103e04SXin LI break; 1375ad6d6297SScott Long } 1376f1c579b1SScott Long } 1377f1c579b1SScott Long /* 1378f1c579b1SScott Long ************************************************************************ 1379f1c579b1SScott Long ************************************************************************ 1380f1c579b1SScott Long */ 138144f05562SScott Long static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb) 1382f1c579b1SScott Long { 1383ad6d6297SScott Long acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 138444f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 138544f05562SScott Long 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 138644f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 1387d74001adSXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n" 1388ad6d6297SScott Long , acb->pci_unit); 1389ad6d6297SScott Long } 1390f1c579b1SScott Long } 1391f1c579b1SScott Long /* 1392f1c579b1SScott Long ************************************************************************ 1393f1c579b1SScott Long ************************************************************************ 1394f1c579b1SScott Long */ 139544f05562SScott Long static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb) 139644f05562SScott Long { 1397b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 139844f05562SScott Long acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 1399b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_STOP_BGRB); 140044f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 1401d74001adSXin LI printf( "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" 140244f05562SScott Long , acb->pci_unit); 140344f05562SScott Long } 140444f05562SScott Long } 140544f05562SScott Long /* 140644f05562SScott Long ************************************************************************ 140744f05562SScott Long ************************************************************************ 140844f05562SScott Long */ 1409d74001adSXin LI static void arcmsr_stop_hbc_bgrb(struct AdapterControlBlock *acb) 1410d74001adSXin LI { 1411d74001adSXin LI acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 1412d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 1413d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 1414d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 1415d74001adSXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit); 1416d74001adSXin LI } 1417d74001adSXin LI } 1418d74001adSXin LI /* 1419d74001adSXin LI ************************************************************************ 1420d74001adSXin LI ************************************************************************ 1421d74001adSXin LI */ 14227a7bc959SXin LI static void arcmsr_stop_hbd_bgrb(struct AdapterControlBlock *acb) 14237a7bc959SXin LI { 14247a7bc959SXin LI acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 14257a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 14267a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 14277a7bc959SXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit); 14287a7bc959SXin LI } 14297a7bc959SXin LI } 14307a7bc959SXin LI /* 14317a7bc959SXin LI ************************************************************************ 14327a7bc959SXin LI ************************************************************************ 14337a7bc959SXin LI */ 1434a1103e04SXin LI static void arcmsr_stop_hbe_bgrb(struct AdapterControlBlock *acb) 1435a1103e04SXin LI { 1436a1103e04SXin LI acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 1437a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 1438a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 1439a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 1440a1103e04SXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) { 1441a1103e04SXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit); 1442a1103e04SXin LI } 1443a1103e04SXin LI } 1444a1103e04SXin LI /* 1445a1103e04SXin LI ************************************************************************ 1446a1103e04SXin LI ************************************************************************ 1447a1103e04SXin LI */ 144844f05562SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) 144944f05562SScott Long { 145044f05562SScott Long switch (acb->adapter_type) { 145144f05562SScott Long case ACB_ADAPTER_TYPE_A: { 145244f05562SScott Long arcmsr_stop_hba_bgrb(acb); 145344f05562SScott Long } 145444f05562SScott Long break; 145544f05562SScott Long case ACB_ADAPTER_TYPE_B: { 145644f05562SScott Long arcmsr_stop_hbb_bgrb(acb); 145744f05562SScott Long } 145844f05562SScott Long break; 1459d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1460d74001adSXin LI arcmsr_stop_hbc_bgrb(acb); 1461d74001adSXin LI } 1462d74001adSXin LI break; 14637a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 14647a7bc959SXin LI arcmsr_stop_hbd_bgrb(acb); 14657a7bc959SXin LI } 14667a7bc959SXin LI break; 1467fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 1468fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 1469a1103e04SXin LI arcmsr_stop_hbe_bgrb(acb); 1470a1103e04SXin LI } 1471a1103e04SXin LI break; 147244f05562SScott Long } 147344f05562SScott Long } 147444f05562SScott Long /* 147544f05562SScott Long ************************************************************************ 147644f05562SScott Long ************************************************************************ 147744f05562SScott Long */ 1478ad6d6297SScott Long static void arcmsr_poll(struct cam_sim *psim) 1479f1c579b1SScott Long { 1480579ec1a5SScott Long struct AdapterControlBlock *acb; 14814e32649fSXin LI int mutex; 1482579ec1a5SScott Long 1483579ec1a5SScott Long acb = (struct AdapterControlBlock *)cam_sim_softc(psim); 14847a7bc959SXin LI mutex = mtx_owned(&acb->isr_lock); 14854e32649fSXin LI if( mutex == 0 ) 14867a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 1487579ec1a5SScott Long arcmsr_interrupt(acb); 14884e32649fSXin LI if( mutex == 0 ) 14897a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 14907a7bc959SXin LI } 14917a7bc959SXin LI /* 14927a7bc959SXin LI ************************************************************************** 14937a7bc959SXin LI ************************************************************************** 14947a7bc959SXin LI */ 149535689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data_D(struct AdapterControlBlock *acb, 149635689395SXin LI struct QBUFFER *prbuffer) { 149735689395SXin LI u_int8_t *pQbuffer; 14984d24901aSPedro F. Giffuni u_int8_t *buf1 = NULL; 14994d24901aSPedro F. Giffuni u_int32_t *iop_data, *buf2 = NULL; 150035689395SXin LI u_int32_t iop_len, data_len; 150135689395SXin LI 150235689395SXin LI iop_data = (u_int32_t *)prbuffer->data; 150335689395SXin LI iop_len = (u_int32_t)prbuffer->data_len; 150435689395SXin LI if ( iop_len > 0 ) 150535689395SXin LI { 150635689395SXin LI buf1 = malloc(128, M_DEVBUF, M_NOWAIT | M_ZERO); 150735689395SXin LI buf2 = (u_int32_t *)buf1; 150835689395SXin LI if( buf1 == NULL) 150935689395SXin LI return (0); 151035689395SXin LI data_len = iop_len; 151135689395SXin LI while(data_len >= 4) 151235689395SXin LI { 151335689395SXin LI *buf2++ = *iop_data++; 151435689395SXin LI data_len -= 4; 151535689395SXin LI } 151635689395SXin LI if(data_len) 151735689395SXin LI *buf2 = *iop_data; 151835689395SXin LI buf2 = (u_int32_t *)buf1; 151935689395SXin LI } 152035689395SXin LI while (iop_len > 0) { 152135689395SXin LI pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex]; 152235689395SXin LI *pQbuffer = *buf1; 152335689395SXin LI acb->rqbuf_lastindex++; 152435689395SXin LI /* if last, index number set it to 0 */ 152535689395SXin LI acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 152635689395SXin LI buf1++; 152735689395SXin LI iop_len--; 152835689395SXin LI } 152935689395SXin LI if(buf2) 153035689395SXin LI free( (u_int8_t *)buf2, M_DEVBUF); 153135689395SXin LI /* let IOP know data has been read */ 153235689395SXin LI arcmsr_iop_message_read(acb); 153335689395SXin LI return (1); 153435689395SXin LI } 153535689395SXin LI /* 153635689395SXin LI ************************************************************************** 153735689395SXin LI ************************************************************************** 153835689395SXin LI */ 153935689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, 15407a7bc959SXin LI struct QBUFFER *prbuffer) { 15417a7bc959SXin LI u_int8_t *pQbuffer; 15427a7bc959SXin LI u_int8_t *iop_data; 15437a7bc959SXin LI u_int32_t iop_len; 15447a7bc959SXin LI 1545fc5ef1caSXin LI if(acb->adapter_type >= ACB_ADAPTER_TYPE_B) { 154635689395SXin LI return(arcmsr_Read_iop_rqbuffer_data_D(acb, prbuffer)); 154735689395SXin LI } 15487a7bc959SXin LI iop_data = (u_int8_t *)prbuffer->data; 15497a7bc959SXin LI iop_len = (u_int32_t)prbuffer->data_len; 15507a7bc959SXin LI while (iop_len > 0) { 15517a7bc959SXin LI pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex]; 15527a7bc959SXin LI *pQbuffer = *iop_data; 15537a7bc959SXin LI acb->rqbuf_lastindex++; 15547a7bc959SXin LI /* if last, index number set it to 0 */ 15557a7bc959SXin LI acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 15567a7bc959SXin LI iop_data++; 15577a7bc959SXin LI iop_len--; 15587a7bc959SXin LI } 15597a7bc959SXin LI /* let IOP know data has been read */ 15607a7bc959SXin LI arcmsr_iop_message_read(acb); 156135689395SXin LI return (1); 1562f1c579b1SScott Long } 1563f1c579b1SScott Long /* 156444f05562SScott Long ************************************************************************** 156544f05562SScott Long ************************************************************************** 15665878cbecSScott Long */ 156744f05562SScott Long static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) 1568f1c579b1SScott Long { 156944f05562SScott Long struct QBUFFER *prbuffer; 15707a7bc959SXin LI int my_empty_len; 1571ad6d6297SScott Long 1572f1c579b1SScott Long /*check this iop data if overflow my rqbuffer*/ 15737a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 157444f05562SScott Long prbuffer = arcmsr_get_iop_rqbuffer(acb); 15757a7bc959SXin LI my_empty_len = (acb->rqbuf_lastindex - acb->rqbuf_firstindex - 1) & 15767a7bc959SXin LI (ARCMSR_MAX_QBUFFER-1); 15777a7bc959SXin LI if(my_empty_len >= prbuffer->data_len) { 157835689395SXin LI if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) 157935689395SXin LI acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 1580ad6d6297SScott Long } else { 1581ad6d6297SScott Long acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 1582f1c579b1SScott Long } 15837a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 15847a7bc959SXin LI } 15857a7bc959SXin LI /* 15867a7bc959SXin LI ********************************************************************** 15877a7bc959SXin LI ********************************************************************** 15887a7bc959SXin LI */ 158935689395SXin LI static void arcmsr_Write_data_2iop_wqbuffer_D(struct AdapterControlBlock *acb) 159035689395SXin LI { 159135689395SXin LI u_int8_t *pQbuffer; 159235689395SXin LI struct QBUFFER *pwbuffer; 15934d24901aSPedro F. Giffuni u_int8_t *buf1 = NULL; 15944d24901aSPedro F. Giffuni u_int32_t *iop_data, *buf2 = NULL; 159535689395SXin LI u_int32_t allxfer_len = 0, data_len; 159635689395SXin LI 159735689395SXin LI if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) { 159835689395SXin LI buf1 = malloc(128, M_DEVBUF, M_NOWAIT | M_ZERO); 159935689395SXin LI buf2 = (u_int32_t *)buf1; 160035689395SXin LI if( buf1 == NULL) 160135689395SXin LI return; 160235689395SXin LI 160335689395SXin LI acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 160435689395SXin LI pwbuffer = arcmsr_get_iop_wqbuffer(acb); 160535689395SXin LI iop_data = (u_int32_t *)pwbuffer->data; 160635689395SXin LI while((acb->wqbuf_firstindex != acb->wqbuf_lastindex) 160735689395SXin LI && (allxfer_len < 124)) { 160835689395SXin LI pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex]; 160935689395SXin LI *buf1 = *pQbuffer; 161035689395SXin LI acb->wqbuf_firstindex++; 161135689395SXin LI acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 161235689395SXin LI buf1++; 161335689395SXin LI allxfer_len++; 161435689395SXin LI } 161535689395SXin LI pwbuffer->data_len = allxfer_len; 161635689395SXin LI data_len = allxfer_len; 161735689395SXin LI buf1 = (u_int8_t *)buf2; 161835689395SXin LI while(data_len >= 4) 161935689395SXin LI { 162035689395SXin LI *iop_data++ = *buf2++; 162135689395SXin LI data_len -= 4; 162235689395SXin LI } 162335689395SXin LI if(data_len) 162435689395SXin LI *iop_data = *buf2; 162535689395SXin LI free( buf1, M_DEVBUF); 162635689395SXin LI arcmsr_iop_message_wrote(acb); 162735689395SXin LI } 162835689395SXin LI } 162935689395SXin LI /* 163035689395SXin LI ********************************************************************** 163135689395SXin LI ********************************************************************** 163235689395SXin LI */ 16337a7bc959SXin LI static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb) 16347a7bc959SXin LI { 16357a7bc959SXin LI u_int8_t *pQbuffer; 16367a7bc959SXin LI struct QBUFFER *pwbuffer; 16377a7bc959SXin LI u_int8_t *iop_data; 16387a7bc959SXin LI int32_t allxfer_len=0; 16397a7bc959SXin LI 1640fc5ef1caSXin LI if(acb->adapter_type >= ACB_ADAPTER_TYPE_B) { 164135689395SXin LI arcmsr_Write_data_2iop_wqbuffer_D(acb); 164235689395SXin LI return; 164335689395SXin LI } 16447a7bc959SXin LI if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) { 16457a7bc959SXin LI acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 16467a7bc959SXin LI pwbuffer = arcmsr_get_iop_wqbuffer(acb); 16477a7bc959SXin LI iop_data = (u_int8_t *)pwbuffer->data; 16487a7bc959SXin LI while((acb->wqbuf_firstindex != acb->wqbuf_lastindex) 16497a7bc959SXin LI && (allxfer_len < 124)) { 16507a7bc959SXin LI pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex]; 16517a7bc959SXin LI *iop_data = *pQbuffer; 16527a7bc959SXin LI acb->wqbuf_firstindex++; 16537a7bc959SXin LI acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 16547a7bc959SXin LI iop_data++; 16557a7bc959SXin LI allxfer_len++; 16567a7bc959SXin LI } 16577a7bc959SXin LI pwbuffer->data_len = allxfer_len; 16587a7bc959SXin LI arcmsr_iop_message_wrote(acb); 16597a7bc959SXin LI } 1660f1c579b1SScott Long } 1661f1c579b1SScott Long /* 166244f05562SScott Long ************************************************************************** 166344f05562SScott Long ************************************************************************** 166444f05562SScott Long */ 166544f05562SScott Long static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) 166644f05562SScott Long { 16677a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 166844f05562SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READ; 166944f05562SScott Long /* 167044f05562SScott Long ***************************************************************** 167144f05562SScott Long ** check if there are any mail packages from user space program 167244f05562SScott Long ** in my post bag, now is the time to send them into Areca's firmware 167344f05562SScott Long ***************************************************************** 1674f1c579b1SScott Long */ 1675ad6d6297SScott Long if(acb->wqbuf_firstindex != acb->wqbuf_lastindex) { 16767a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 1677f1c579b1SScott Long } 1678ad6d6297SScott Long if(acb->wqbuf_firstindex == acb->wqbuf_lastindex) { 1679ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; 1680f1c579b1SScott Long } 16817a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1682f1c579b1SScott Long } 16837a7bc959SXin LI /* 16847a7bc959SXin LI ************************************************************************** 16857a7bc959SXin LI ************************************************************************** 16867a7bc959SXin LI */ 1687d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb) 1688d74001adSXin LI { 1689d74001adSXin LI /* 1690d74001adSXin LI if (ccb->ccb_h.status != CAM_REQ_CMP) 16917a7bc959SXin LI printf("arcmsr_rescanLun_cb: Rescan Target=%x, lun=%x," 16927a7bc959SXin LI "failure status=%x\n", ccb->ccb_h.target_id, 16937a7bc959SXin LI ccb->ccb_h.target_lun, ccb->ccb_h.status); 1694d74001adSXin LI else 1695d74001adSXin LI printf("arcmsr_rescanLun_cb: Rescan lun successfully!\n"); 1696d74001adSXin LI */ 1697d74001adSXin LI xpt_free_path(ccb->ccb_h.path); 1698d74001adSXin LI xpt_free_ccb(ccb); 1699d74001adSXin LI } 1700d74001adSXin LI 1701d74001adSXin LI static void arcmsr_rescan_lun(struct AdapterControlBlock *acb, int target, int lun) 1702d74001adSXin LI { 1703d74001adSXin LI struct cam_path *path; 1704d74001adSXin LI union ccb *ccb; 1705d74001adSXin LI 1706d74001adSXin LI if ((ccb = (union ccb *)xpt_alloc_ccb_nowait()) == NULL) 1707d74001adSXin LI return; 1708abfdbca9SXin LI if (xpt_create_path(&path, NULL, cam_sim_path(acb->psim), target, lun) != CAM_REQ_CMP) 1709d74001adSXin LI { 1710d74001adSXin LI xpt_free_ccb(ccb); 1711d74001adSXin LI return; 1712d74001adSXin LI } 1713d74001adSXin LI /* printf("arcmsr_rescan_lun: Rescan Target=%x, Lun=%x\n", target, lun); */ 1714d74001adSXin LI xpt_setup_ccb(&ccb->ccb_h, path, 5); 1715d74001adSXin LI ccb->ccb_h.func_code = XPT_SCAN_LUN; 1716d74001adSXin LI ccb->ccb_h.cbfcnp = arcmsr_rescanLun_cb; 1717d74001adSXin LI ccb->crcn.flags = CAM_FLAG_NONE; 1718d74001adSXin LI xpt_action(ccb); 1719d74001adSXin LI } 1720d74001adSXin LI 1721d74001adSXin LI static void arcmsr_abort_dr_ccbs(struct AdapterControlBlock *acb, int target, int lun) 1722d74001adSXin LI { 1723d74001adSXin LI struct CommandControlBlock *srb; 1724d74001adSXin LI u_int32_t intmask_org; 1725d74001adSXin LI int i; 1726d74001adSXin LI 1727d74001adSXin LI /* disable all outbound interrupts */ 1728d74001adSXin LI intmask_org = arcmsr_disable_allintr(acb); 1729d74001adSXin LI for (i = 0; i < ARCMSR_MAX_FREESRB_NUM; i++) 1730d74001adSXin LI { 1731d74001adSXin LI srb = acb->psrb_pool[i]; 173222f2616bSXin LI if (srb->srb_state == ARCMSR_SRB_START) 1733d74001adSXin LI { 1734d74001adSXin LI if((target == srb->pccb->ccb_h.target_id) && (lun == srb->pccb->ccb_h.target_lun)) 1735d74001adSXin LI { 173622f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 1737d74001adSXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 1738d74001adSXin LI arcmsr_srb_complete(srb, 1); 173922f2616bSXin LI printf("arcmsr%d: abort scsi id %d lun %d srb=%p \n", acb->pci_unit, target, lun, srb); 1740d74001adSXin LI } 1741d74001adSXin LI } 1742d74001adSXin LI } 1743d74001adSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 1744d74001adSXin LI arcmsr_enable_allintr(acb, intmask_org); 1745d74001adSXin LI } 1746d74001adSXin LI /* 1747d74001adSXin LI ************************************************************************** 1748d74001adSXin LI ************************************************************************** 1749d74001adSXin LI */ 1750d74001adSXin LI static void arcmsr_dr_handle(struct AdapterControlBlock *acb) { 1751d74001adSXin LI u_int32_t devicemap; 1752d74001adSXin LI u_int32_t target, lun; 1753d74001adSXin LI u_int32_t deviceMapCurrent[4]={0}; 1754d74001adSXin LI u_int8_t *pDevMap; 1755d74001adSXin LI 1756d74001adSXin LI switch (acb->adapter_type) { 1757d74001adSXin LI case ACB_ADAPTER_TYPE_A: 1758d74001adSXin LI devicemap = offsetof(struct HBA_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1759d74001adSXin LI for (target = 0; target < 4; target++) 1760d74001adSXin LI { 1761d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1762d74001adSXin LI devicemap += 4; 1763d74001adSXin LI } 1764d74001adSXin LI break; 1765d74001adSXin LI 1766d74001adSXin LI case ACB_ADAPTER_TYPE_B: 1767d74001adSXin LI devicemap = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1768d74001adSXin LI for (target = 0; target < 4; target++) 1769d74001adSXin LI { 1770d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[1], acb->bhandle[1], devicemap); 1771d74001adSXin LI devicemap += 4; 1772d74001adSXin LI } 1773d74001adSXin LI break; 1774d74001adSXin LI 1775d74001adSXin LI case ACB_ADAPTER_TYPE_C: 1776d74001adSXin LI devicemap = offsetof(struct HBC_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1777d74001adSXin LI for (target = 0; target < 4; target++) 1778d74001adSXin LI { 1779d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1780d74001adSXin LI devicemap += 4; 1781d74001adSXin LI } 1782d74001adSXin LI break; 17837a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 17847a7bc959SXin LI devicemap = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 17857a7bc959SXin LI for (target = 0; target < 4; target++) 17867a7bc959SXin LI { 17877a7bc959SXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 17887a7bc959SXin LI devicemap += 4; 17897a7bc959SXin LI } 17907a7bc959SXin LI break; 1791a1103e04SXin LI case ACB_ADAPTER_TYPE_E: 1792a1103e04SXin LI devicemap = offsetof(struct HBE_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1793a1103e04SXin LI for (target = 0; target < 4; target++) 1794a1103e04SXin LI { 1795a1103e04SXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1796a1103e04SXin LI devicemap += 4; 1797a1103e04SXin LI } 1798a1103e04SXin LI break; 1799fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 1800fa42a0bfSXin LI devicemap = ARCMSR_FW_DEVMAP_OFFSET; 1801fa42a0bfSXin LI for (target = 0; target < 4; target++) 1802fa42a0bfSXin LI { 1803fa42a0bfSXin LI deviceMapCurrent[target] = acb->msgcode_rwbuffer[devicemap]; 1804fa42a0bfSXin LI devicemap += 1; 1805fa42a0bfSXin LI } 1806fa42a0bfSXin LI break; 1807d74001adSXin LI } 1808dac36688SXin LI 1809d74001adSXin LI if(acb->acb_flags & ACB_F_BUS_HANG_ON) 1810d74001adSXin LI { 1811d74001adSXin LI acb->acb_flags &= ~ACB_F_BUS_HANG_ON; 1812d74001adSXin LI } 1813d74001adSXin LI /* 1814d74001adSXin LI ** adapter posted CONFIG message 1815d74001adSXin LI ** copy the new map, note if there are differences with the current map 1816d74001adSXin LI */ 1817d74001adSXin LI pDevMap = (u_int8_t *)&deviceMapCurrent[0]; 1818d74001adSXin LI for (target = 0; target < ARCMSR_MAX_TARGETID - 1; target++) 1819d74001adSXin LI { 1820d74001adSXin LI if (*pDevMap != acb->device_map[target]) 1821d74001adSXin LI { 1822d74001adSXin LI u_int8_t difference, bit_check; 1823d74001adSXin LI 1824d74001adSXin LI difference = *pDevMap ^ acb->device_map[target]; 1825d74001adSXin LI for(lun=0; lun < ARCMSR_MAX_TARGETLUN; lun++) 1826d74001adSXin LI { 1827d74001adSXin LI bit_check = (1 << lun); /*check bit from 0....31*/ 1828d74001adSXin LI if(difference & bit_check) 1829d74001adSXin LI { 1830d74001adSXin LI if(acb->device_map[target] & bit_check) 1831d74001adSXin LI {/* unit departed */ 1832d74001adSXin LI printf("arcmsr_dr_handle: Target=%x, lun=%x, GONE!!!\n",target,lun); 1833d74001adSXin LI arcmsr_abort_dr_ccbs(acb, target, lun); 1834d74001adSXin LI arcmsr_rescan_lun(acb, target, lun); 1835d74001adSXin LI acb->devstate[target][lun] = ARECA_RAID_GONE; 1836d74001adSXin LI } 1837d74001adSXin LI else 1838d74001adSXin LI {/* unit arrived */ 183922f2616bSXin LI printf("arcmsr_dr_handle: Target=%x, lun=%x, Plug-IN!!!\n",target,lun); 1840d74001adSXin LI arcmsr_rescan_lun(acb, target, lun); 1841d74001adSXin LI acb->devstate[target][lun] = ARECA_RAID_GOOD; 1842d74001adSXin LI } 1843d74001adSXin LI } 1844d74001adSXin LI } 1845d74001adSXin LI /* printf("arcmsr_dr_handle: acb->device_map[%x]=0x%x, deviceMapCurrent[%x]=%x\n",target,acb->device_map[target],target,*pDevMap); */ 1846d74001adSXin LI acb->device_map[target] = *pDevMap; 1847d74001adSXin LI } 1848d74001adSXin LI pDevMap++; 1849d74001adSXin LI } 1850d74001adSXin LI } 1851d74001adSXin LI /* 1852d74001adSXin LI ************************************************************************** 1853d74001adSXin LI ************************************************************************** 1854d74001adSXin LI */ 1855d74001adSXin LI static void arcmsr_hba_message_isr(struct AdapterControlBlock *acb) { 1856d74001adSXin LI u_int32_t outbound_message; 1857d74001adSXin LI 1858d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT); 1859d74001adSXin LI outbound_message = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[0]); 1860d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1861d74001adSXin LI arcmsr_dr_handle( acb ); 1862d74001adSXin LI } 1863d74001adSXin LI /* 1864d74001adSXin LI ************************************************************************** 1865d74001adSXin LI ************************************************************************** 1866d74001adSXin LI */ 1867d74001adSXin LI static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) { 1868d74001adSXin LI u_int32_t outbound_message; 1869b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 1870d74001adSXin LI 1871d74001adSXin LI /* clear interrupts */ 1872b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN); 1873d74001adSXin LI outbound_message = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0]); 1874d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1875d74001adSXin LI arcmsr_dr_handle( acb ); 1876d74001adSXin LI } 1877d74001adSXin LI /* 1878d74001adSXin LI ************************************************************************** 1879d74001adSXin LI ************************************************************************** 1880d74001adSXin LI */ 1881d74001adSXin LI static void arcmsr_hbc_message_isr(struct AdapterControlBlock *acb) { 1882d74001adSXin LI u_int32_t outbound_message; 1883d74001adSXin LI 1884d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR); 1885d74001adSXin LI outbound_message = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[0]); 1886d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1887d74001adSXin LI arcmsr_dr_handle( acb ); 1888d74001adSXin LI } 188944f05562SScott Long /* 189044f05562SScott Long ************************************************************************** 189144f05562SScott Long ************************************************************************** 189244f05562SScott Long */ 18937a7bc959SXin LI static void arcmsr_hbd_message_isr(struct AdapterControlBlock *acb) { 18947a7bc959SXin LI u_int32_t outbound_message; 18957a7bc959SXin LI 18967a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR); 18977a7bc959SXin LI outbound_message = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[0]); 18987a7bc959SXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 18997a7bc959SXin LI arcmsr_dr_handle( acb ); 19007a7bc959SXin LI } 19017a7bc959SXin LI /* 19027a7bc959SXin LI ************************************************************************** 19037a7bc959SXin LI ************************************************************************** 19047a7bc959SXin LI */ 1905a1103e04SXin LI static void arcmsr_hbe_message_isr(struct AdapterControlBlock *acb) { 1906a1103e04SXin LI u_int32_t outbound_message; 1907a1103e04SXin LI 1908a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); 19095842073aSXin LI if (acb->adapter_type == ACB_ADAPTER_TYPE_E) 1910a1103e04SXin LI outbound_message = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[0]); 19115842073aSXin LI else 19125842073aSXin LI outbound_message = acb->msgcode_rwbuffer[0]; 1913a1103e04SXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1914a1103e04SXin LI arcmsr_dr_handle( acb ); 1915a1103e04SXin LI } 1916a1103e04SXin LI /* 1917a1103e04SXin LI ************************************************************************** 1918a1103e04SXin LI ************************************************************************** 1919a1103e04SXin LI */ 192044f05562SScott Long static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) 192144f05562SScott Long { 1922224a78aeSXin LI u_int32_t doorbell_status; 192344f05562SScott Long 192444f05562SScott Long /* 192544f05562SScott Long ******************************************************************* 192644f05562SScott Long ** Maybe here we need to check wrqbuffer_lock is lock or not 192744f05562SScott Long ** DOORBELL: din! don! 192844f05562SScott Long ** check if there are any mail need to pack from firmware 192944f05562SScott Long ******************************************************************* 193044f05562SScott Long */ 1931224a78aeSXin LI doorbell_status = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell); 1932224a78aeSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */ 1933224a78aeSXin LI if(doorbell_status & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { 193444f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 1935ad6d6297SScott Long } 1936224a78aeSXin LI if(doorbell_status & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { 193744f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 193844f05562SScott Long } 193944f05562SScott Long } 194044f05562SScott Long /* 194144f05562SScott Long ************************************************************************** 194244f05562SScott Long ************************************************************************** 194344f05562SScott Long */ 1944d74001adSXin LI static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb) 1945d74001adSXin LI { 1946224a78aeSXin LI u_int32_t doorbell_status; 1947d74001adSXin LI 1948d74001adSXin LI /* 1949d74001adSXin LI ******************************************************************* 1950d74001adSXin LI ** Maybe here we need to check wrqbuffer_lock is lock or not 1951d74001adSXin LI ** DOORBELL: din! don! 1952d74001adSXin LI ** check if there are any mail need to pack from firmware 1953d74001adSXin LI ******************************************************************* 1954d74001adSXin LI */ 1955224a78aeSXin LI doorbell_status = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); 1956224a78aeSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, doorbell_status); /* clear doorbell interrupt */ 1957224a78aeSXin LI if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) { 1958d74001adSXin LI arcmsr_iop2drv_data_wrote_handle(acb); 1959d74001adSXin LI } 1960224a78aeSXin LI if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) { 1961d74001adSXin LI arcmsr_iop2drv_data_read_handle(acb); 1962d74001adSXin LI } 1963224a78aeSXin LI if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { 1964d74001adSXin LI arcmsr_hbc_message_isr(acb); /* messenger of "driver to iop commands" */ 1965d74001adSXin LI } 1966d74001adSXin LI } 1967d74001adSXin LI /* 1968d74001adSXin LI ************************************************************************** 1969d74001adSXin LI ************************************************************************** 1970d74001adSXin LI */ 19717a7bc959SXin LI static void arcmsr_hbd_doorbell_isr(struct AdapterControlBlock *acb) 19727a7bc959SXin LI { 1973224a78aeSXin LI u_int32_t doorbell_status; 19747a7bc959SXin LI 19757a7bc959SXin LI /* 19767a7bc959SXin LI ******************************************************************* 19777a7bc959SXin LI ** Maybe here we need to check wrqbuffer_lock is lock or not 19787a7bc959SXin LI ** DOORBELL: din! don! 19797a7bc959SXin LI ** check if there are any mail need to pack from firmware 19807a7bc959SXin LI ******************************************************************* 19817a7bc959SXin LI */ 1982224a78aeSXin LI doorbell_status = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE; 1983224a78aeSXin LI if(doorbell_status) 1984224a78aeSXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */ 1985224a78aeSXin LI while( doorbell_status & ARCMSR_HBDMU_F0_DOORBELL_CAUSE ) { 1986224a78aeSXin LI if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_DATA_WRITE_OK) { 19877a7bc959SXin LI arcmsr_iop2drv_data_wrote_handle(acb); 19887a7bc959SXin LI } 1989224a78aeSXin LI if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_DATA_READ_OK) { 19907a7bc959SXin LI arcmsr_iop2drv_data_read_handle(acb); 19917a7bc959SXin LI } 1992224a78aeSXin LI if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) { 19937a7bc959SXin LI arcmsr_hbd_message_isr(acb); /* messenger of "driver to iop commands" */ 19947a7bc959SXin LI } 1995224a78aeSXin LI doorbell_status = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE; 1996224a78aeSXin LI if(doorbell_status) 1997224a78aeSXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */ 19987a7bc959SXin LI } 19997a7bc959SXin LI } 20007a7bc959SXin LI /* 20017a7bc959SXin LI ************************************************************************** 20027a7bc959SXin LI ************************************************************************** 20037a7bc959SXin LI */ 2004a1103e04SXin LI static void arcmsr_hbe_doorbell_isr(struct AdapterControlBlock *acb) 2005a1103e04SXin LI { 2006a1103e04SXin LI u_int32_t doorbell_status, in_doorbell; 2007a1103e04SXin LI 2008a1103e04SXin LI /* 2009a1103e04SXin LI ******************************************************************* 2010a1103e04SXin LI ** Maybe here we need to check wrqbuffer_lock is lock or not 2011a1103e04SXin LI ** DOORBELL: din! don! 2012a1103e04SXin LI ** check if there are any mail need to pack from firmware 2013a1103e04SXin LI ******************************************************************* 2014a1103e04SXin LI */ 2015a1103e04SXin LI in_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell); 2016a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /* clear doorbell interrupt */ 2017a1103e04SXin LI doorbell_status = in_doorbell ^ acb->in_doorbell; 2018a1103e04SXin LI if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_WRITE_OK) { 2019a1103e04SXin LI arcmsr_iop2drv_data_wrote_handle(acb); 2020a1103e04SXin LI } 2021a1103e04SXin LI if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_READ_OK) { 2022a1103e04SXin LI arcmsr_iop2drv_data_read_handle(acb); 2023a1103e04SXin LI } 2024a1103e04SXin LI if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) { 2025a1103e04SXin LI arcmsr_hbe_message_isr(acb); /* messenger of "driver to iop commands" */ 2026a1103e04SXin LI } 2027a1103e04SXin LI acb->in_doorbell = in_doorbell; 2028a1103e04SXin LI } 2029a1103e04SXin LI /* 2030a1103e04SXin LI ************************************************************************** 2031a1103e04SXin LI ************************************************************************** 2032a1103e04SXin LI */ 2033*6964b77eS黃清隆 static void arcmsr_hbf_doorbell_isr(struct AdapterControlBlock *acb) 2034*6964b77eS黃清隆 { 2035*6964b77eS黃清隆 u_int32_t doorbell_status, in_doorbell; 2036*6964b77eS黃清隆 2037*6964b77eS黃清隆 /* 2038*6964b77eS黃清隆 ******************************************************************* 2039*6964b77eS黃清隆 ** Maybe here we need to check wrqbuffer_lock is lock or not 2040*6964b77eS黃清隆 ** DOORBELL: din! don! 2041*6964b77eS黃清隆 ** check if there are any mail need to pack from firmware 2042*6964b77eS黃清隆 ******************************************************************* 2043*6964b77eS黃清隆 */ 2044*6964b77eS黃清隆 while(1) { 2045*6964b77eS黃清隆 in_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell); 2046*6964b77eS黃清隆 if ((in_doorbell != 0) && (in_doorbell != 0xFFFFFFFF)) 2047*6964b77eS黃清隆 break; 2048*6964b77eS黃清隆 } 2049*6964b77eS黃清隆 CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /* clear doorbell interrupt */ 2050*6964b77eS黃清隆 doorbell_status = in_doorbell ^ acb->in_doorbell; 2051*6964b77eS黃清隆 if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_WRITE_OK) { 2052*6964b77eS黃清隆 arcmsr_iop2drv_data_wrote_handle(acb); 2053*6964b77eS黃清隆 } 2054*6964b77eS黃清隆 if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_READ_OK) { 2055*6964b77eS黃清隆 arcmsr_iop2drv_data_read_handle(acb); 2056*6964b77eS黃清隆 } 2057*6964b77eS黃清隆 if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) { 2058*6964b77eS黃清隆 arcmsr_hbe_message_isr(acb); /* messenger of "driver to iop commands" */ 2059*6964b77eS黃清隆 } 2060*6964b77eS黃清隆 acb->in_doorbell = in_doorbell; 2061*6964b77eS黃清隆 } 2062*6964b77eS黃清隆 /* 2063*6964b77eS黃清隆 ************************************************************************** 2064*6964b77eS黃清隆 ************************************************************************** 2065*6964b77eS黃清隆 */ 206644f05562SScott Long static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb) 206744f05562SScott Long { 206844f05562SScott Long u_int32_t flag_srb; 2069d74001adSXin LI u_int16_t error; 207044f05562SScott Long 2071f1c579b1SScott Long /* 2072f1c579b1SScott Long ***************************************************************************** 2073f1c579b1SScott Long ** areca cdb command done 2074f1c579b1SScott Long ***************************************************************************** 2075f1c579b1SScott Long */ 207644f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 207744f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 207844f05562SScott Long while((flag_srb = CHIP_REG_READ32(HBA_MessageUnit, 207944f05562SScott Long 0, outbound_queueport)) != 0xFFFFFFFF) { 2080f1c579b1SScott Long /* check if command done with no error*/ 2081d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0) ? TRUE : FALSE; 2082d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 208344f05562SScott Long } /*drain reply FIFO*/ 2084f1c579b1SScott Long } 208544f05562SScott Long /* 208644f05562SScott Long ************************************************************************** 208744f05562SScott Long ************************************************************************** 208844f05562SScott Long */ 208944f05562SScott Long static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) 209044f05562SScott Long { 209144f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 209244f05562SScott Long u_int32_t flag_srb; 209344f05562SScott Long int index; 2094d74001adSXin LI u_int16_t error; 209544f05562SScott Long 209644f05562SScott Long /* 209744f05562SScott Long ***************************************************************************** 209844f05562SScott Long ** areca cdb command done 209944f05562SScott Long ***************************************************************************** 210044f05562SScott Long */ 210144f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 210244f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 210344f05562SScott Long index = phbbmu->doneq_index; 210444f05562SScott Long while((flag_srb = phbbmu->done_qbuffer[index]) != 0) { 210544f05562SScott Long phbbmu->done_qbuffer[index] = 0; 210644f05562SScott Long index++; 210744f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 210844f05562SScott Long phbbmu->doneq_index = index; 210944f05562SScott Long /* check if command done with no error*/ 2110d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 2111d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 2112d74001adSXin LI } /*drain reply FIFO*/ 2113d74001adSXin LI } 2114d74001adSXin LI /* 2115d74001adSXin LI ************************************************************************** 2116d74001adSXin LI ************************************************************************** 2117d74001adSXin LI */ 2118d74001adSXin LI static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb) 2119d74001adSXin LI { 2120d74001adSXin LI u_int32_t flag_srb,throttling = 0; 2121d74001adSXin LI u_int16_t error; 2122d74001adSXin LI 2123d74001adSXin LI /* 2124d74001adSXin LI ***************************************************************************** 2125d74001adSXin LI ** areca cdb command done 2126d74001adSXin LI ***************************************************************************** 2127d74001adSXin LI */ 2128d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2129224a78aeSXin LI do { 2130d74001adSXin LI flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 2131b23a1998SXin LI if (flag_srb == 0xFFFFFFFF) 2132b23a1998SXin LI break; 2133d74001adSXin LI /* check if command done with no error*/ 2134d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; 2135d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 2136abfdbca9SXin LI throttling++; 2137d74001adSXin LI if(throttling == ARCMSR_HBC_ISR_THROTTLING_LEVEL) { 2138d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING); 2139abfdbca9SXin LI throttling = 0; 2140d74001adSXin LI } 2141224a78aeSXin LI } while(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR); 2142f1c579b1SScott Long } 214344f05562SScott Long /* 214444f05562SScott Long ********************************************************************** 21457a7bc959SXin LI ** 21467a7bc959SXin LI ********************************************************************** 21477a7bc959SXin LI */ 21487a7bc959SXin LI static uint16_t arcmsr_get_doneq_index(struct HBD_MessageUnit0 *phbdmu) 21497a7bc959SXin LI { 21507a7bc959SXin LI uint16_t doneq_index, index_stripped; 21517a7bc959SXin LI 21527a7bc959SXin LI doneq_index = phbdmu->doneq_index; 21537a7bc959SXin LI if (doneq_index & 0x4000) { 21547a7bc959SXin LI index_stripped = doneq_index & 0xFF; 21557a7bc959SXin LI index_stripped += 1; 21567a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 21577a7bc959SXin LI phbdmu->doneq_index = index_stripped ? 21587a7bc959SXin LI (index_stripped | 0x4000) : index_stripped; 21597a7bc959SXin LI } else { 21607a7bc959SXin LI index_stripped = doneq_index; 21617a7bc959SXin LI index_stripped += 1; 21627a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 21637a7bc959SXin LI phbdmu->doneq_index = index_stripped ? 21647a7bc959SXin LI index_stripped : (index_stripped | 0x4000); 21657a7bc959SXin LI } 21667a7bc959SXin LI return (phbdmu->doneq_index); 21677a7bc959SXin LI } 21687a7bc959SXin LI /* 21697a7bc959SXin LI ************************************************************************** 21707a7bc959SXin LI ************************************************************************** 21717a7bc959SXin LI */ 21727a7bc959SXin LI static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb) 21737a7bc959SXin LI { 21747a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 21757a7bc959SXin LI u_int32_t outbound_write_pointer; 21767a7bc959SXin LI u_int32_t addressLow; 21777a7bc959SXin LI uint16_t doneq_index; 21787a7bc959SXin LI u_int16_t error; 21797a7bc959SXin LI /* 21807a7bc959SXin LI ***************************************************************************** 21817a7bc959SXin LI ** areca cdb command done 21827a7bc959SXin LI ***************************************************************************** 21837a7bc959SXin LI */ 21847a7bc959SXin LI if((CHIP_REG_READ32(HBD_MessageUnit, 0, outboundlist_interrupt_cause) & 21857a7bc959SXin LI ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT) == 0) 21867a7bc959SXin LI return; 21877a7bc959SXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 21887a7bc959SXin LI BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 21897a7bc959SXin LI outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow; 21907a7bc959SXin LI doneq_index = phbdmu->doneq_index; 21917a7bc959SXin LI while ((doneq_index & 0xFF) != (outbound_write_pointer & 0xFF)) { 21927a7bc959SXin LI doneq_index = arcmsr_get_doneq_index(phbdmu); 21937a7bc959SXin LI addressLow = phbdmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow; 21947a7bc959SXin LI error = (addressLow & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 21957a7bc959SXin LI arcmsr_drain_donequeue(acb, addressLow, error); /*Check if command done with no error */ 21967a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_read_pointer, doneq_index); 21977a7bc959SXin LI outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow; 21987a7bc959SXin LI } 21997a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_interrupt_cause, ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT_CLEAR); 22007a7bc959SXin LI CHIP_REG_READ32(HBD_MessageUnit, 0, outboundlist_interrupt_cause); /*Dummy ioread32 to force pci flush */ 22017a7bc959SXin LI } 22027a7bc959SXin LI /* 2203a1103e04SXin LI ************************************************************************** 2204a1103e04SXin LI ************************************************************************** 2205a1103e04SXin LI */ 2206a1103e04SXin LI static void arcmsr_hbe_postqueue_isr(struct AdapterControlBlock *acb) 2207a1103e04SXin LI { 2208a1103e04SXin LI u_int16_t error; 2209a1103e04SXin LI uint32_t doneq_index; 2210a1103e04SXin LI uint16_t cmdSMID; 2211a1103e04SXin LI 2212a1103e04SXin LI /* 2213a1103e04SXin LI ***************************************************************************** 2214a1103e04SXin LI ** areca cdb command done 2215a1103e04SXin LI ***************************************************************************** 2216a1103e04SXin LI */ 2217a1103e04SXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2218a1103e04SXin LI doneq_index = acb->doneq_index; 2219a1103e04SXin LI while ((CHIP_REG_READ32(HBE_MessageUnit, 0, reply_post_producer_index) & 0xFFFF) != doneq_index) { 2220a1103e04SXin LI cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID; 2221a1103e04SXin LI error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 2222a1103e04SXin LI arcmsr_drain_donequeue(acb, (u_int32_t)cmdSMID, error); 2223a1103e04SXin LI doneq_index++; 2224a1103e04SXin LI if (doneq_index >= acb->completionQ_entry) 2225a1103e04SXin LI doneq_index = 0; 2226a1103e04SXin LI } 2227a1103e04SXin LI acb->doneq_index = doneq_index; 2228a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, reply_post_consumer_index, doneq_index); 2229a1103e04SXin LI } 2230fa42a0bfSXin LI 2231fa42a0bfSXin LI static void arcmsr_hbf_postqueue_isr(struct AdapterControlBlock *acb) 2232fa42a0bfSXin LI { 2233fa42a0bfSXin LI uint16_t error; 2234fa42a0bfSXin LI uint32_t doneq_index; 2235fa42a0bfSXin LI uint16_t cmdSMID; 2236fa42a0bfSXin LI 2237fa42a0bfSXin LI /* 2238fa42a0bfSXin LI ***************************************************************************** 2239fa42a0bfSXin LI ** areca cdb command done 2240fa42a0bfSXin LI ***************************************************************************** 2241fa42a0bfSXin LI */ 2242fa42a0bfSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2243fa42a0bfSXin LI doneq_index = acb->doneq_index; 2244fa42a0bfSXin LI while (1) { 2245fa42a0bfSXin LI cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID; 2246fa42a0bfSXin LI if (cmdSMID == 0xffff) 2247fa42a0bfSXin LI break; 2248fa42a0bfSXin LI error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 2249fa42a0bfSXin LI arcmsr_drain_donequeue(acb, (u_int32_t)cmdSMID, error); 2250fa42a0bfSXin LI acb->pCompletionQ[doneq_index].cmdSMID = 0xffff; 2251fa42a0bfSXin LI doneq_index++; 2252fa42a0bfSXin LI if (doneq_index >= acb->completionQ_entry) 2253fa42a0bfSXin LI doneq_index = 0; 2254fa42a0bfSXin LI } 2255fa42a0bfSXin LI acb->doneq_index = doneq_index; 2256fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, reply_post_consumer_index, doneq_index); 2257fa42a0bfSXin LI } 2258fa42a0bfSXin LI 2259a1103e04SXin LI /* 22607a7bc959SXin LI ********************************************************************** 226144f05562SScott Long ********************************************************************** 226244f05562SScott Long */ 226344f05562SScott Long static void arcmsr_handle_hba_isr( struct AdapterControlBlock *acb) 226444f05562SScott Long { 2265dac36688SXin LI u_int32_t outbound_intStatus; 226644f05562SScott Long /* 226744f05562SScott Long ********************************************* 226844f05562SScott Long ** check outbound intstatus 226944f05562SScott Long ********************************************* 227044f05562SScott Long */ 2271dac36688SXin LI outbound_intStatus = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 2272dac36688SXin LI if(!outbound_intStatus) { 227344f05562SScott Long /*it must be share irq*/ 227444f05562SScott Long return; 2275f1c579b1SScott Long } 2276dac36688SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intStatus); /*clear interrupt*/ 227744f05562SScott Long /* MU doorbell interrupts*/ 2278dac36688SXin LI if(outbound_intStatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) { 227944f05562SScott Long arcmsr_hba_doorbell_isr(acb); 2280f1c579b1SScott Long } 228144f05562SScott Long /* MU post queue interrupts*/ 2282dac36688SXin LI if(outbound_intStatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { 228344f05562SScott Long arcmsr_hba_postqueue_isr(acb); 228444f05562SScott Long } 2285dac36688SXin LI if(outbound_intStatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { 2286d74001adSXin LI arcmsr_hba_message_isr(acb); 2287d74001adSXin LI } 228844f05562SScott Long } 228944f05562SScott Long /* 229044f05562SScott Long ********************************************************************** 229144f05562SScott Long ********************************************************************** 229244f05562SScott Long */ 229344f05562SScott Long static void arcmsr_handle_hbb_isr( struct AdapterControlBlock *acb) 229444f05562SScott Long { 229544f05562SScott Long u_int32_t outbound_doorbell; 2296b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 229744f05562SScott Long /* 229844f05562SScott Long ********************************************* 229944f05562SScott Long ** check outbound intstatus 230044f05562SScott Long ********************************************* 230144f05562SScott Long */ 2302b23a1998SXin LI outbound_doorbell = READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & acb->outbound_int_enable; 230344f05562SScott Long if(!outbound_doorbell) { 230444f05562SScott Long /*it must be share irq*/ 230544f05562SScott Long return; 230644f05562SScott Long } 2307b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ~outbound_doorbell); /* clear doorbell interrupt */ 2308b23a1998SXin LI READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell); 2309b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 231044f05562SScott Long /* MU ioctl transfer doorbell interrupts*/ 231144f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { 231244f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 231344f05562SScott Long } 231444f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) { 231544f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 231644f05562SScott Long } 231744f05562SScott Long /* MU post queue interrupts*/ 231844f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) { 231944f05562SScott Long arcmsr_hbb_postqueue_isr(acb); 232044f05562SScott Long } 2321d74001adSXin LI if(outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { 2322d74001adSXin LI arcmsr_hbb_message_isr(acb); 2323d74001adSXin LI } 2324d74001adSXin LI } 2325d74001adSXin LI /* 2326d74001adSXin LI ********************************************************************** 2327d74001adSXin LI ********************************************************************** 2328d74001adSXin LI */ 2329d74001adSXin LI static void arcmsr_handle_hbc_isr( struct AdapterControlBlock *acb) 2330d74001adSXin LI { 2331d74001adSXin LI u_int32_t host_interrupt_status; 2332d74001adSXin LI /* 2333d74001adSXin LI ********************************************* 2334d74001adSXin LI ** check outbound intstatus 2335d74001adSXin LI ********************************************* 2336d74001adSXin LI */ 2337224a78aeSXin LI host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & 2338224a78aeSXin LI (ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR | 2339224a78aeSXin LI ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR); 2340d74001adSXin LI if(!host_interrupt_status) { 2341d74001adSXin LI /*it must be share irq*/ 2342d74001adSXin LI return; 2343d74001adSXin LI } 2344224a78aeSXin LI do { 2345d74001adSXin LI /* MU doorbell interrupts*/ 2346d74001adSXin LI if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) { 2347d74001adSXin LI arcmsr_hbc_doorbell_isr(acb); 2348d74001adSXin LI } 2349d74001adSXin LI /* MU post queue interrupts*/ 2350d74001adSXin LI if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) { 2351d74001adSXin LI arcmsr_hbc_postqueue_isr(acb); 2352d74001adSXin LI } 2353224a78aeSXin LI host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status); 2354224a78aeSXin LI } while (host_interrupt_status & (ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR)); 235544f05562SScott Long } 235644f05562SScott Long /* 23577a7bc959SXin LI ********************************************************************** 23587a7bc959SXin LI ********************************************************************** 23597a7bc959SXin LI */ 23607a7bc959SXin LI static void arcmsr_handle_hbd_isr( struct AdapterControlBlock *acb) 23617a7bc959SXin LI { 23627a7bc959SXin LI u_int32_t host_interrupt_status; 23637a7bc959SXin LI u_int32_t intmask_org; 23647a7bc959SXin LI /* 23657a7bc959SXin LI ********************************************* 23667a7bc959SXin LI ** check outbound intstatus 23677a7bc959SXin LI ********************************************* 23687a7bc959SXin LI */ 23697a7bc959SXin LI host_interrupt_status = CHIP_REG_READ32(HBD_MessageUnit, 0, host_int_status) & acb->outbound_int_enable; 23707a7bc959SXin LI if(!(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_INT)) { 23717a7bc959SXin LI /*it must be share irq*/ 23727a7bc959SXin LI return; 23737a7bc959SXin LI } 23747a7bc959SXin LI /* disable outbound interrupt */ 23757a7bc959SXin LI intmask_org = CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable) ; /* disable outbound message0 int */ 23767a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, ARCMSR_HBDMU_ALL_INT_DISABLE); 23777a7bc959SXin LI /* MU doorbell interrupts*/ 23787a7bc959SXin LI if(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_DOORBELL_INT) { 23797a7bc959SXin LI arcmsr_hbd_doorbell_isr(acb); 23807a7bc959SXin LI } 23817a7bc959SXin LI /* MU post queue interrupts*/ 23827a7bc959SXin LI if(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_POSTQUEUE_INT) { 23837a7bc959SXin LI arcmsr_hbd_postqueue_isr(acb); 23847a7bc959SXin LI } 23857a7bc959SXin LI /* enable all outbound interrupt */ 23867a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, intmask_org | ARCMSR_HBDMU_ALL_INT_ENABLE); 23877a7bc959SXin LI // CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable); 23887a7bc959SXin LI } 23897a7bc959SXin LI /* 2390a1103e04SXin LI ********************************************************************** 2391a1103e04SXin LI ********************************************************************** 2392a1103e04SXin LI */ 2393a1103e04SXin LI static void arcmsr_handle_hbe_isr( struct AdapterControlBlock *acb) 2394a1103e04SXin LI { 2395a1103e04SXin LI u_int32_t host_interrupt_status; 2396a1103e04SXin LI /* 2397a1103e04SXin LI ********************************************* 2398a1103e04SXin LI ** check outbound intstatus 2399a1103e04SXin LI ********************************************* 2400a1103e04SXin LI */ 2401a1103e04SXin LI host_interrupt_status = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_status) & 2402a1103e04SXin LI (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR | 2403a1103e04SXin LI ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR); 2404a1103e04SXin LI if(!host_interrupt_status) { 2405a1103e04SXin LI /*it must be share irq*/ 2406a1103e04SXin LI return; 2407a1103e04SXin LI } 2408a1103e04SXin LI do { 2409a1103e04SXin LI /* MU doorbell interrupts*/ 2410a1103e04SXin LI if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR) { 2411a1103e04SXin LI arcmsr_hbe_doorbell_isr(acb); 2412a1103e04SXin LI } 2413a1103e04SXin LI /* MU post queue interrupts*/ 2414a1103e04SXin LI if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR) { 2415a1103e04SXin LI arcmsr_hbe_postqueue_isr(acb); 2416a1103e04SXin LI } 2417a1103e04SXin LI host_interrupt_status = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_status); 2418a1103e04SXin LI } while (host_interrupt_status & (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR)); 2419a1103e04SXin LI } 2420fa42a0bfSXin LI 2421fa42a0bfSXin LI static void arcmsr_handle_hbf_isr( struct AdapterControlBlock *acb) 2422fa42a0bfSXin LI { 2423fa42a0bfSXin LI u_int32_t host_interrupt_status; 2424fa42a0bfSXin LI /* 2425fa42a0bfSXin LI ********************************************* 2426fa42a0bfSXin LI ** check outbound intstatus 2427fa42a0bfSXin LI ********************************************* 2428fa42a0bfSXin LI */ 2429fa42a0bfSXin LI host_interrupt_status = CHIP_REG_READ32(HBF_MessageUnit, 0, host_int_status) & 2430fa42a0bfSXin LI (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR | 2431fa42a0bfSXin LI ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR); 2432fa42a0bfSXin LI if(!host_interrupt_status) { 2433fa42a0bfSXin LI /*it must be share irq*/ 2434fa42a0bfSXin LI return; 2435fa42a0bfSXin LI } 2436fa42a0bfSXin LI do { 2437fa42a0bfSXin LI /* MU doorbell interrupts*/ 2438fa42a0bfSXin LI if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR) { 2439*6964b77eS黃清隆 arcmsr_hbf_doorbell_isr(acb); 2440fa42a0bfSXin LI } 2441fa42a0bfSXin LI /* MU post queue interrupts*/ 2442fa42a0bfSXin LI if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR) { 2443fa42a0bfSXin LI arcmsr_hbf_postqueue_isr(acb); 2444fa42a0bfSXin LI } 2445fa42a0bfSXin LI host_interrupt_status = CHIP_REG_READ32(HBF_MessageUnit, 0, host_int_status); 2446fa42a0bfSXin LI } while (host_interrupt_status & (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR)); 2447fa42a0bfSXin LI } 2448a1103e04SXin LI /* 244944f05562SScott Long ****************************************************************************** 245044f05562SScott Long ****************************************************************************** 245144f05562SScott Long */ 245244f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb) 245344f05562SScott Long { 245444f05562SScott Long switch (acb->adapter_type) { 245544f05562SScott Long case ACB_ADAPTER_TYPE_A: 245644f05562SScott Long arcmsr_handle_hba_isr(acb); 2457f1c579b1SScott Long break; 245844f05562SScott Long case ACB_ADAPTER_TYPE_B: 245944f05562SScott Long arcmsr_handle_hbb_isr(acb); 2460f1c579b1SScott Long break; 2461d74001adSXin LI case ACB_ADAPTER_TYPE_C: 2462d74001adSXin LI arcmsr_handle_hbc_isr(acb); 2463d74001adSXin LI break; 24647a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 24657a7bc959SXin LI arcmsr_handle_hbd_isr(acb); 24667a7bc959SXin LI break; 2467a1103e04SXin LI case ACB_ADAPTER_TYPE_E: 2468a1103e04SXin LI arcmsr_handle_hbe_isr(acb); 2469a1103e04SXin LI break; 2470fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 2471fa42a0bfSXin LI arcmsr_handle_hbf_isr(acb); 2472fa42a0bfSXin LI break; 2473f1c579b1SScott Long default: 247444f05562SScott Long printf("arcmsr%d: interrupt service," 247510d66948SKevin Lo " unknown adapter type =%d\n", acb->pci_unit, acb->adapter_type); 2476f1c579b1SScott Long break; 2477f1c579b1SScott Long } 2478f1c579b1SScott Long } 2479f1c579b1SScott Long /* 2480d74001adSXin LI ********************************************************************** 2481d74001adSXin LI ********************************************************************** 2482d74001adSXin LI */ 2483d74001adSXin LI static void arcmsr_intr_handler(void *arg) 2484d74001adSXin LI { 2485d74001adSXin LI struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg; 2486d74001adSXin LI 24877a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 2488d74001adSXin LI arcmsr_interrupt(acb); 24897a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 2490d74001adSXin LI } 2491d74001adSXin LI /* 2492d74001adSXin LI ****************************************************************************** 2493d74001adSXin LI ****************************************************************************** 2494d74001adSXin LI */ 2495d74001adSXin LI static void arcmsr_polling_devmap(void *arg) 2496d74001adSXin LI { 2497d74001adSXin LI struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg; 2498d74001adSXin LI switch (acb->adapter_type) { 2499d74001adSXin LI case ACB_ADAPTER_TYPE_A: 2500dac36688SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 2501d74001adSXin LI break; 2502d74001adSXin LI 2503b23a1998SXin LI case ACB_ADAPTER_TYPE_B: { 2504b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 2505b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG); 2506b23a1998SXin LI } 2507d74001adSXin LI break; 2508d74001adSXin LI 2509d74001adSXin LI case ACB_ADAPTER_TYPE_C: 2510d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 2511d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 2512d74001adSXin LI break; 25137a7bc959SXin LI 25147a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 25157a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 25167a7bc959SXin LI break; 2517a1103e04SXin LI 2518a1103e04SXin LI case ACB_ADAPTER_TYPE_E: 2519a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 2520a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 2521a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 2522a1103e04SXin LI break; 2523d74001adSXin LI 2524fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 2525fa42a0bfSXin LI u_int32_t outMsg1 = CHIP_REG_READ32(HBF_MessageUnit, 0, outbound_msgaddr1); 2526fa42a0bfSXin LI if (!(outMsg1 & ARCMSR_HBFMU_MESSAGE_FIRMWARE_OK) || 2527fa42a0bfSXin LI (outMsg1 & ARCMSR_HBFMU_MESSAGE_NO_VOLUME_CHANGE)) 2528fa42a0bfSXin LI goto nxt6s; 2529fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 2530fa42a0bfSXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 2531fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 2532fa42a0bfSXin LI break; 2533fa42a0bfSXin LI } 2534fa42a0bfSXin LI } 2535fa42a0bfSXin LI nxt6s: 2536d74001adSXin LI if((acb->acb_flags & ACB_F_SCSISTOPADAPTER) == 0) 2537d74001adSXin LI { 2538d74001adSXin LI callout_reset(&acb->devmap_callout, 5 * hz, arcmsr_polling_devmap, acb); /* polling per 5 seconds */ 2539d74001adSXin LI } 2540d74001adSXin LI } 2541d74001adSXin LI 2542d74001adSXin LI /* 2543ad6d6297SScott Long ******************************************************************************* 2544ad6d6297SScott Long ** 2545ad6d6297SScott Long ******************************************************************************* 2546ad6d6297SScott Long */ 2547ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb) 2548ad6d6297SScott Long { 2549d74001adSXin LI u_int32_t intmask_org; 2550d74001adSXin LI 2551ad6d6297SScott Long if(acb != NULL) { 2552ad6d6297SScott Long /* stop adapter background rebuild */ 2553ad6d6297SScott Long if(acb->acb_flags & ACB_F_MSG_START_BGRB) { 2554d74001adSXin LI intmask_org = arcmsr_disable_allintr(acb); 2555ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 2556ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2557d74001adSXin LI arcmsr_enable_allintr(acb, intmask_org); 2558ad6d6297SScott Long } 2559ad6d6297SScott Long } 2560ad6d6297SScott Long } 2561ad6d6297SScott Long /* 2562f1c579b1SScott Long *********************************************************************** 2563f1c579b1SScott Long ** 2564f1c579b1SScott Long ************************************************************************ 2565f1c579b1SScott Long */ 2566fc5ef1caSXin LI static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg) 2567f1c579b1SScott Long { 2568ad6d6297SScott Long struct CMD_MESSAGE_FIELD *pcmdmessagefld; 2569ad6d6297SScott Long u_int32_t retvalue = EINVAL; 2570f1c579b1SScott Long 2571ad6d6297SScott Long pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) arg; 2572ad6d6297SScott Long if(memcmp(pcmdmessagefld->cmdmessage.Signature, "ARCMSR", 6)!=0) { 2573ad6d6297SScott Long return retvalue; 2574f1c579b1SScott Long } 2575ad6d6297SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2576ad6d6297SScott Long switch(ioctl_cmd) { 2577ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 2578ad6d6297SScott Long u_int8_t *pQbuffer; 2579ad6d6297SScott Long u_int8_t *ptmpQbuffer = pcmdmessagefld->messagedatabuffer; 2580ad6d6297SScott Long u_int32_t allxfer_len=0; 2581f1c579b1SScott Long 258244f05562SScott Long while((acb->rqbuf_firstindex != acb->rqbuf_lastindex) 258344f05562SScott Long && (allxfer_len < 1031)) { 2584f1c579b1SScott Long /*copy READ QBUFFER to srb*/ 2585ad6d6297SScott Long pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; 25867a7bc959SXin LI *ptmpQbuffer = *pQbuffer; 2587ad6d6297SScott Long acb->rqbuf_firstindex++; 2588ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 2589ad6d6297SScott Long /*if last index number set it to 0 */ 2590f1c579b1SScott Long ptmpQbuffer++; 2591f1c579b1SScott Long allxfer_len++; 2592f1c579b1SScott Long } 2593ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 259444f05562SScott Long struct QBUFFER *prbuffer; 2595f1c579b1SScott Long 2596ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 259744f05562SScott Long prbuffer = arcmsr_get_iop_rqbuffer(acb); 259835689395SXin LI if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) 259935689395SXin LI acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 2600f1c579b1SScott Long } 2601ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length = allxfer_len; 2602ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2603ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2604f1c579b1SScott Long } 2605f1c579b1SScott Long break; 2606ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 2607ad6d6297SScott Long u_int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 2608ad6d6297SScott Long u_int8_t *pQbuffer; 2609ad6d6297SScott Long u_int8_t *ptmpuserbuffer = pcmdmessagefld->messagedatabuffer; 2610f1c579b1SScott Long 2611ad6d6297SScott Long user_len = pcmdmessagefld->cmdmessage.Length; 2612f1c579b1SScott Long /*check if data xfer length of this request will overflow my array qbuffer */ 2613ad6d6297SScott Long wqbuf_lastindex = acb->wqbuf_lastindex; 2614ad6d6297SScott Long wqbuf_firstindex = acb->wqbuf_firstindex; 2615ad6d6297SScott Long if(wqbuf_lastindex != wqbuf_firstindex) { 26167a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2617ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR; 2618ad6d6297SScott Long } else { 26197a7bc959SXin LI my_empty_len = (wqbuf_firstindex - wqbuf_lastindex - 1) & 26207a7bc959SXin LI (ARCMSR_MAX_QBUFFER - 1); 2621ad6d6297SScott Long if(my_empty_len >= user_len) { 2622ad6d6297SScott Long while(user_len > 0) { 2623f1c579b1SScott Long /*copy srb data to wqbuffer*/ 2624ad6d6297SScott Long pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; 26257a7bc959SXin LI *pQbuffer = *ptmpuserbuffer; 2626ad6d6297SScott Long acb->wqbuf_lastindex++; 2627ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 2628ad6d6297SScott Long /*if last index number set it to 0 */ 2629f1c579b1SScott Long ptmpuserbuffer++; 2630f1c579b1SScott Long user_len--; 2631f1c579b1SScott Long } 2632f1c579b1SScott Long /*post fist Qbuffer*/ 2633ad6d6297SScott Long if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 2634ad6d6297SScott Long acb->acb_flags &= ~ACB_F_MESSAGE_WQBUFFER_CLEARED; 26357a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2636f1c579b1SScott Long } 2637ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2638ad6d6297SScott Long } else { 2639ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR; 2640f1c579b1SScott Long } 2641f1c579b1SScott Long } 2642ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2643f1c579b1SScott Long } 2644f1c579b1SScott Long break; 2645ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 2646ad6d6297SScott Long u_int8_t *pQbuffer = acb->rqbuffer; 2647ad6d6297SScott Long 2648ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2649ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 265044f05562SScott Long arcmsr_iop_message_read(acb); 265144f05562SScott Long /*signature, let IOP know data has been readed */ 2652f1c579b1SScott Long } 2653ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 2654ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2655ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2656f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2657ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2658ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2659f1c579b1SScott Long } 2660f1c579b1SScott Long break; 2661ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: 2662f1c579b1SScott Long { 2663ad6d6297SScott Long u_int8_t *pQbuffer = acb->wqbuffer; 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 } 267044f05562SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ); 2671ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2672ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2673f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2674ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2675ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2676f1c579b1SScott Long } 2677f1c579b1SScott Long break; 2678ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 2679ad6d6297SScott Long u_int8_t *pQbuffer; 2680f1c579b1SScott Long 2681ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2682ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 268344f05562SScott Long arcmsr_iop_message_read(acb); 268444f05562SScott Long /*signature, let IOP know data has been readed */ 2685f1c579b1SScott Long } 2686ad6d6297SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED 2687ad6d6297SScott Long |ACB_F_MESSAGE_RQBUFFER_CLEARED 268844f05562SScott Long |ACB_F_MESSAGE_WQBUFFER_READ); 2689ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2690ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2691ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2692ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2693ad6d6297SScott Long pQbuffer = acb->rqbuffer; 2694ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 2695ad6d6297SScott Long pQbuffer = acb->wqbuffer; 2696ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 2697ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2698ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2699f1c579b1SScott Long } 2700f1c579b1SScott Long break; 2701ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 2702ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; 2703ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2704f1c579b1SScott Long } 2705f1c579b1SScott Long break; 2706ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 2707ad6d6297SScott Long u_int8_t *hello_string = "Hello! I am ARCMSR"; 2708ad6d6297SScott Long u_int8_t *puserbuffer = (u_int8_t *)pcmdmessagefld->messagedatabuffer; 2709f1c579b1SScott Long 2710ad6d6297SScott Long if(memcpy(puserbuffer, hello_string, (int16_t)strlen(hello_string))) { 2711ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR; 2712ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2713f1c579b1SScott Long return ENOIOCTL; 2714f1c579b1SScott Long } 2715ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2716ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2717ad6d6297SScott Long } 2718ad6d6297SScott Long break; 2719ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: { 2720ad6d6297SScott Long arcmsr_iop_parking(acb); 2721ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2722ad6d6297SScott Long } 2723ad6d6297SScott Long break; 2724ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: { 2725ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2726ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2727f1c579b1SScott Long } 2728f1c579b1SScott Long break; 2729f1c579b1SScott Long } 2730ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2731dac36688SXin LI return (retvalue); 2732f1c579b1SScott Long } 2733f1c579b1SScott Long /* 2734f1c579b1SScott Long ************************************************************************** 2735f1c579b1SScott Long ************************************************************************** 2736f1c579b1SScott Long */ 273722f2616bSXin LI static void arcmsr_free_srb(struct CommandControlBlock *srb) 273822f2616bSXin LI { 273922f2616bSXin LI struct AdapterControlBlock *acb; 274022f2616bSXin LI 274122f2616bSXin LI acb = srb->acb; 27427a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->srb_lock); 274322f2616bSXin LI srb->srb_state = ARCMSR_SRB_DONE; 274422f2616bSXin LI srb->srb_flags = 0; 274522f2616bSXin LI acb->srbworkingQ[acb->workingsrb_doneindex] = srb; 274622f2616bSXin LI acb->workingsrb_doneindex++; 274722f2616bSXin LI acb->workingsrb_doneindex %= ARCMSR_MAX_FREESRB_NUM; 27487a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->srb_lock); 274922f2616bSXin LI } 275022f2616bSXin LI /* 275122f2616bSXin LI ************************************************************************** 275222f2616bSXin LI ************************************************************************** 275322f2616bSXin LI */ 2754fc5ef1caSXin LI static struct CommandControlBlock *arcmsr_get_freesrb(struct AdapterControlBlock *acb) 2755f1c579b1SScott Long { 2756ad6d6297SScott Long struct CommandControlBlock *srb = NULL; 2757ad6d6297SScott Long u_int32_t workingsrb_startindex, workingsrb_doneindex; 2758f1c579b1SScott Long 27597a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->srb_lock); 2760ad6d6297SScott Long workingsrb_doneindex = acb->workingsrb_doneindex; 2761ad6d6297SScott Long workingsrb_startindex = acb->workingsrb_startindex; 2762ad6d6297SScott Long srb = acb->srbworkingQ[workingsrb_startindex]; 2763ad6d6297SScott Long workingsrb_startindex++; 2764ad6d6297SScott Long workingsrb_startindex %= ARCMSR_MAX_FREESRB_NUM; 2765ad6d6297SScott Long if(workingsrb_doneindex != workingsrb_startindex) { 2766ad6d6297SScott Long acb->workingsrb_startindex = workingsrb_startindex; 2767ad6d6297SScott Long } else { 2768ad6d6297SScott Long srb = NULL; 2769ad6d6297SScott Long } 27707a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->srb_lock); 2771ad6d6297SScott Long return(srb); 2772ad6d6297SScott Long } 2773ad6d6297SScott Long /* 2774ad6d6297SScott Long ************************************************************************** 2775ad6d6297SScott Long ************************************************************************** 2776ad6d6297SScott Long */ 2777ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *pccb) 2778ad6d6297SScott Long { 2779ad6d6297SScott Long struct CMD_MESSAGE_FIELD *pcmdmessagefld; 2780ad6d6297SScott Long int retvalue = 0, transfer_len = 0; 2781ad6d6297SScott Long char *buffer; 27824aa947cbSWarner Losh uint8_t *ptr = scsiio_cdb_ptr(&pccb->csio); 27834aa947cbSWarner Losh u_int32_t controlcode = (u_int32_t ) ptr[5] << 24 | 27844aa947cbSWarner Losh (u_int32_t ) ptr[6] << 16 | 27854aa947cbSWarner Losh (u_int32_t ) ptr[7] << 8 | 27864aa947cbSWarner Losh (u_int32_t ) ptr[8]; 2787ad6d6297SScott Long /* 4 bytes: Areca io control code */ 2788dd0b4fb6SKonstantin Belousov if ((pccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) { 2789ad6d6297SScott Long buffer = pccb->csio.data_ptr; 2790ad6d6297SScott Long transfer_len = pccb->csio.dxfer_len; 2791ad6d6297SScott Long } else { 2792ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2793ad6d6297SScott Long goto message_out; 2794ad6d6297SScott Long } 2795ad6d6297SScott Long if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) { 2796ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2797ad6d6297SScott Long goto message_out; 2798ad6d6297SScott Long } 2799ad6d6297SScott Long pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer; 2800ad6d6297SScott Long switch(controlcode) { 2801ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 2802ad6d6297SScott Long u_int8_t *pQbuffer; 2803ad6d6297SScott Long u_int8_t *ptmpQbuffer = pcmdmessagefld->messagedatabuffer; 2804ad6d6297SScott Long int32_t allxfer_len = 0; 2805f1c579b1SScott Long 28067a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2807ad6d6297SScott Long while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) 2808ad6d6297SScott Long && (allxfer_len < 1031)) { 2809ad6d6297SScott Long pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; 28107a7bc959SXin LI *ptmpQbuffer = *pQbuffer; 2811ad6d6297SScott Long acb->rqbuf_firstindex++; 2812ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 2813ad6d6297SScott Long ptmpQbuffer++; 2814ad6d6297SScott Long allxfer_len++; 2815f1c579b1SScott Long } 2816ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 281744f05562SScott Long struct QBUFFER *prbuffer; 2818ad6d6297SScott Long 2819ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 282044f05562SScott Long prbuffer = arcmsr_get_iop_rqbuffer(acb); 282135689395SXin LI if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) 282235689395SXin LI acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 2823ad6d6297SScott Long } 2824ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length = allxfer_len; 2825ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2826ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 28277a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2828ad6d6297SScott Long } 2829ad6d6297SScott Long break; 2830ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 2831ad6d6297SScott Long int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 2832ad6d6297SScott Long u_int8_t *pQbuffer; 2833ad6d6297SScott Long u_int8_t *ptmpuserbuffer = pcmdmessagefld->messagedatabuffer; 2834ad6d6297SScott Long 2835ad6d6297SScott Long user_len = pcmdmessagefld->cmdmessage.Length; 28367a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2837ad6d6297SScott Long wqbuf_lastindex = acb->wqbuf_lastindex; 2838ad6d6297SScott Long wqbuf_firstindex = acb->wqbuf_firstindex; 2839ad6d6297SScott Long if (wqbuf_lastindex != wqbuf_firstindex) { 28407a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2841ad6d6297SScott Long /* has error report sensedata */ 2842dac36688SXin LI if(pccb->csio.sense_len) { 2843ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 2844ad6d6297SScott Long /* Valid,ErrorCode */ 2845ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 2846ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 2847ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 2848ad6d6297SScott Long /* AdditionalSenseLength */ 2849ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 2850ad6d6297SScott Long /* AdditionalSenseCode */ 2851ad6d6297SScott Long } 2852ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2853ad6d6297SScott Long } else { 2854ad6d6297SScott Long my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) 2855ad6d6297SScott Long &(ARCMSR_MAX_QBUFFER - 1); 2856ad6d6297SScott Long if (my_empty_len >= user_len) { 2857ad6d6297SScott Long while (user_len > 0) { 2858ad6d6297SScott Long pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; 28597a7bc959SXin LI *pQbuffer = *ptmpuserbuffer; 2860ad6d6297SScott Long acb->wqbuf_lastindex++; 2861ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 2862ad6d6297SScott Long ptmpuserbuffer++; 2863ad6d6297SScott Long user_len--; 2864ad6d6297SScott Long } 2865ad6d6297SScott Long if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 2866ad6d6297SScott Long acb->acb_flags &= 2867ad6d6297SScott Long ~ACB_F_MESSAGE_WQBUFFER_CLEARED; 28687a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2869ad6d6297SScott Long } 2870ad6d6297SScott Long } else { 2871ad6d6297SScott Long /* has error report sensedata */ 2872dac36688SXin LI if(pccb->csio.sense_len) { 2873ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 2874ad6d6297SScott Long /* Valid,ErrorCode */ 2875ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 2876ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 2877ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 2878ad6d6297SScott Long /* AdditionalSenseLength */ 2879ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 2880ad6d6297SScott Long /* AdditionalSenseCode */ 2881ad6d6297SScott Long } 2882ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2883ad6d6297SScott Long } 2884ad6d6297SScott Long } 28857a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2886ad6d6297SScott Long } 2887ad6d6297SScott Long break; 2888ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 2889ad6d6297SScott Long u_int8_t *pQbuffer = acb->rqbuffer; 2890ad6d6297SScott Long 28917a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2892ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2893ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 289444f05562SScott Long arcmsr_iop_message_read(acb); 2895ad6d6297SScott Long } 2896ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 2897ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2898ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2899ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2900ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 2901ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 29027a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2903ad6d6297SScott Long } 2904ad6d6297SScott Long break; 2905ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { 2906ad6d6297SScott Long u_int8_t *pQbuffer = acb->wqbuffer; 2907ad6d6297SScott Long 29087a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2909ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2910ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 291144f05562SScott Long arcmsr_iop_message_read(acb); 2912ad6d6297SScott Long } 2913ad6d6297SScott Long acb->acb_flags |= 2914ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED | 291544f05562SScott Long ACB_F_MESSAGE_WQBUFFER_READ); 2916ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2917ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2918ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2919ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 2920ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 29217a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2922ad6d6297SScott Long } 2923ad6d6297SScott Long break; 2924ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 2925ad6d6297SScott Long u_int8_t *pQbuffer; 2926ad6d6297SScott Long 29277a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2928ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2929ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 293044f05562SScott Long arcmsr_iop_message_read(acb); 2931ad6d6297SScott Long } 2932ad6d6297SScott Long acb->acb_flags |= 2933ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED 2934ad6d6297SScott Long | ACB_F_MESSAGE_RQBUFFER_CLEARED 293544f05562SScott Long | ACB_F_MESSAGE_WQBUFFER_READ); 2936ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2937ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2938ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2939ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2940ad6d6297SScott Long pQbuffer = acb->rqbuffer; 2941ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 2942ad6d6297SScott Long pQbuffer = acb->wqbuffer; 2943ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 2944ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 29457a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2946ad6d6297SScott Long } 2947ad6d6297SScott Long break; 2948ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 2949ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; 2950ad6d6297SScott Long } 2951ad6d6297SScott Long break; 2952ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 2953ad6d6297SScott Long int8_t *hello_string = "Hello! I am ARCMSR"; 2954ad6d6297SScott Long 2955ad6d6297SScott Long memcpy(pcmdmessagefld->messagedatabuffer, hello_string 2956ad6d6297SScott Long , (int16_t)strlen(hello_string)); 2957ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2958ad6d6297SScott Long } 2959ad6d6297SScott Long break; 2960ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: 2961ad6d6297SScott Long arcmsr_iop_parking(acb); 2962ad6d6297SScott Long break; 2963ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: 2964ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2965ad6d6297SScott Long break; 2966ad6d6297SScott Long default: 2967ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2968ad6d6297SScott Long } 2969ad6d6297SScott Long message_out: 2970dac36688SXin LI return (retvalue); 2971f1c579b1SScott Long } 2972f1c579b1SScott Long /* 2973f1c579b1SScott Long ********************************************************************* 2974f1c579b1SScott Long ********************************************************************* 2975f1c579b1SScott Long */ 2976231c8b71SXin LI static void arcmsr_execute_srb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 2977f1c579b1SScott Long { 2978ad6d6297SScott Long struct CommandControlBlock *srb = (struct CommandControlBlock *)arg; 2979ad6d6297SScott Long struct AdapterControlBlock *acb = (struct AdapterControlBlock *)srb->acb; 2980f1c579b1SScott Long union ccb *pccb; 2981ad6d6297SScott Long int target, lun; 2982f1c579b1SScott Long 2983ad6d6297SScott Long pccb = srb->pccb; 2984ad6d6297SScott Long target = pccb->ccb_h.target_id; 2985ad6d6297SScott Long lun = pccb->ccb_h.target_lun; 298622f2616bSXin LI acb->pktRequestCount++; 2987ad6d6297SScott Long if(error != 0) { 2988ad6d6297SScott Long if(error != EFBIG) { 298944f05562SScott Long printf("arcmsr%d: unexpected error %x" 299044f05562SScott Long " returned from 'bus_dmamap_load' \n" 2991ad6d6297SScott Long , acb->pci_unit, error); 2992f1c579b1SScott Long } 2993ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { 299415735becSScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 2995f1c579b1SScott Long } 2996ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2997f1c579b1SScott Long return; 2998f1c579b1SScott Long } 2999ad6d6297SScott Long if(nseg > ARCMSR_MAX_SG_ENTRIES) { 3000ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 3001ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 3002ad6d6297SScott Long return; 3003f1c579b1SScott Long } 3004ad6d6297SScott Long if(acb->acb_flags & ACB_F_BUS_RESET) { 3005ad6d6297SScott Long printf("arcmsr%d: bus reset and return busy \n", acb->pci_unit); 3006ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_BUS_RESET; 3007ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 3008ad6d6297SScott Long return; 3009ad6d6297SScott Long } 3010ad6d6297SScott Long if(acb->devstate[target][lun] == ARECA_RAID_GONE) { 301122f2616bSXin LI u_int8_t block_cmd, cmd; 3012ad6d6297SScott Long 30134aa947cbSWarner Losh cmd = scsiio_cdb_ptr(&pccb->csio)[0]; 301422f2616bSXin LI block_cmd = cmd & 0x0f; 3015ad6d6297SScott Long if(block_cmd == 0x08 || block_cmd == 0x0a) { 3016ad6d6297SScott Long printf("arcmsr%d:block 'read/write' command " 301722f2616bSXin LI "with gone raid volume Cmd=0x%2x, TargetId=%d, Lun=%d \n" 301822f2616bSXin LI , acb->pci_unit, cmd, target, lun); 3019ad6d6297SScott Long pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 3020ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 3021ad6d6297SScott Long return; 3022ad6d6297SScott Long } 3023ad6d6297SScott Long } 3024ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { 3025ad6d6297SScott Long if(nseg != 0) { 3026ad6d6297SScott Long bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 3027ad6d6297SScott Long } 3028ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 3029f1c579b1SScott Long return; 3030f1c579b1SScott Long } 3031abfdbca9SXin LI if(acb->srboutstandingcount >= acb->maxOutstanding) { 30327a7bc959SXin LI if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) == 0) 30337a7bc959SXin LI { 303415735becSScott Long xpt_freeze_simq(acb->psim, 1); 3035dc3a205bSScott Long acb->acb_flags |= ACB_F_CAM_DEV_QFRZN; 30367a7bc959SXin LI } 30377a7bc959SXin LI pccb->ccb_h.status &= ~CAM_SIM_QUEUED; 30387a7bc959SXin LI pccb->ccb_h.status |= CAM_REQUEUE_REQ; 3039ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 3040ad6d6297SScott Long return; 3041f1c579b1SScott Long } 304215735becSScott Long pccb->ccb_h.status |= CAM_SIM_QUEUED; 3043ad6d6297SScott Long arcmsr_build_srb(srb, dm_segs, nseg); 3044ad6d6297SScott Long arcmsr_post_srb(acb, srb); 304522f2616bSXin LI if (pccb->ccb_h.timeout != CAM_TIME_INFINITY) 304622f2616bSXin LI { 304722f2616bSXin LI arcmsr_callout_init(&srb->ccb_callout); 304885c9dd9dSSteven Hartland callout_reset_sbt(&srb->ccb_callout, SBT_1MS * 304985c9dd9dSSteven Hartland (pccb->ccb_h.timeout + (ARCMSR_TIMEOUT_DELAY * 1000)), 0, 305085c9dd9dSSteven Hartland arcmsr_srb_timeout, srb, 0); 305122f2616bSXin LI srb->srb_flags |= SRB_FLAG_TIMER_START; 305222f2616bSXin LI } 3053f1c579b1SScott Long } 3054f1c579b1SScott Long /* 3055f1c579b1SScott Long ***************************************************************************************** 3056f1c579b1SScott Long ***************************************************************************************** 3057f1c579b1SScott Long */ 3058ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb *abortccb) 3059f1c579b1SScott Long { 3060ad6d6297SScott Long struct CommandControlBlock *srb; 3061ad6d6297SScott Long struct AdapterControlBlock *acb = (struct AdapterControlBlock *) abortccb->ccb_h.arcmsr_ccbacb_ptr; 306244f05562SScott Long u_int32_t intmask_org; 3063ad6d6297SScott Long int i = 0; 3064f1c579b1SScott Long 3065ad6d6297SScott Long acb->num_aborts++; 3066f1c579b1SScott Long /* 3067ad6d6297SScott Long *************************************************************************** 3068f1c579b1SScott Long ** It is the upper layer do abort command this lock just prior to calling us. 3069f1c579b1SScott Long ** First determine if we currently own this command. 3070f1c579b1SScott Long ** Start by searching the device queue. If not found 3071f1c579b1SScott Long ** at all, and the system wanted us to just abort the 3072f1c579b1SScott Long ** command return success. 3073ad6d6297SScott Long *************************************************************************** 3074f1c579b1SScott Long */ 3075ad6d6297SScott Long if(acb->srboutstandingcount != 0) { 307622f2616bSXin LI /* disable all outbound interrupt */ 307722f2616bSXin LI intmask_org = arcmsr_disable_allintr(acb); 3078ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 3079ad6d6297SScott Long srb = acb->psrb_pool[i]; 308022f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) { 3081ad6d6297SScott Long if(srb->pccb == abortccb) { 308222f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 3083123055f0SNathan Whitehorn printf("arcmsr%d:scsi id=%d lun=%jx abort srb '%p'" 3084ad6d6297SScott Long "outstanding command \n" 3085ad6d6297SScott Long , acb->pci_unit, abortccb->ccb_h.target_id 3086123055f0SNathan Whitehorn , (uintmax_t)abortccb->ccb_h.target_lun, srb); 3087ad6d6297SScott Long arcmsr_polling_srbdone(acb, srb); 308844f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 308944f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 3090ad6d6297SScott Long return (TRUE); 3091f1c579b1SScott Long } 309222f2616bSXin LI } 309322f2616bSXin LI } 309422f2616bSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 309522f2616bSXin LI arcmsr_enable_allintr(acb, intmask_org); 309622f2616bSXin LI } 309722f2616bSXin LI return(FALSE); 309822f2616bSXin LI } 3099f1c579b1SScott Long /* 3100f1c579b1SScott Long **************************************************************************** 3101f1c579b1SScott Long **************************************************************************** 3102f1c579b1SScott Long */ 3103ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb) 3104f1c579b1SScott Long { 3105ad6d6297SScott Long int retry = 0; 3106f1c579b1SScott Long 3107ad6d6297SScott Long acb->num_resets++; 3108ad6d6297SScott Long acb->acb_flags |= ACB_F_BUS_RESET; 3109ad6d6297SScott Long while(acb->srboutstandingcount != 0 && retry < 400) { 311044f05562SScott Long arcmsr_interrupt(acb); 3111ad6d6297SScott Long UDELAY(25000); 3112ad6d6297SScott Long retry++; 3113ad6d6297SScott Long } 3114ad6d6297SScott Long arcmsr_iop_reset(acb); 3115ad6d6297SScott Long acb->acb_flags &= ~ACB_F_BUS_RESET; 3116f1c579b1SScott Long } 3117f1c579b1SScott Long /* 3118ad6d6297SScott Long ************************************************************************** 3119ad6d6297SScott Long ************************************************************************** 3120ad6d6297SScott Long */ 3121ad6d6297SScott Long static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, 3122ad6d6297SScott Long union ccb *pccb) 3123ad6d6297SScott Long { 3124ad6d6297SScott Long if (pccb->ccb_h.target_lun) { 312561ba2ac6SJim Harris pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 3126ad6d6297SScott Long xpt_done(pccb); 3127ad6d6297SScott Long return; 3128ad6d6297SScott Long } 31297a7bc959SXin LI pccb->ccb_h.status |= CAM_REQ_CMP; 31304aa947cbSWarner Losh switch (scsiio_cdb_ptr(&pccb->csio)[0]) { 31317a7bc959SXin LI case INQUIRY: { 31327a7bc959SXin LI unsigned char inqdata[36]; 31337a7bc959SXin LI char *buffer = pccb->csio.data_ptr; 31347a7bc959SXin LI 3135231c8b71SXin LI inqdata[0] = T_PROCESSOR; /* Periph Qualifier & Periph Dev Type */ 3136231c8b71SXin LI inqdata[1] = 0; /* rem media bit & Dev Type Modifier */ 3137231c8b71SXin LI inqdata[2] = 0; /* ISO, ECMA, & ANSI versions */ 3138231c8b71SXin LI inqdata[3] = 0; 3139231c8b71SXin LI inqdata[4] = 31; /* length of additional data */ 3140231c8b71SXin LI inqdata[5] = 0; 3141231c8b71SXin LI inqdata[6] = 0; 3142231c8b71SXin LI inqdata[7] = 0; 3143231c8b71SXin LI strncpy(&inqdata[8], "Areca ", 8); /* Vendor Identification */ 3144231c8b71SXin LI strncpy(&inqdata[16], "RAID controller ", 16); /* Product Identification */ 3145ad6d6297SScott Long strncpy(&inqdata[32], "R001", 4); /* Product Revision */ 3146ad6d6297SScott Long memcpy(buffer, inqdata, sizeof(inqdata)); 3147ad6d6297SScott Long xpt_done(pccb); 3148ad6d6297SScott Long } 3149ad6d6297SScott Long break; 3150ad6d6297SScott Long case WRITE_BUFFER: 3151ad6d6297SScott Long case READ_BUFFER: { 3152ad6d6297SScott Long if (arcmsr_iop_message_xfer(acb, pccb)) { 3153ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 3154ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 3155ad6d6297SScott Long } 3156ad6d6297SScott Long xpt_done(pccb); 3157ad6d6297SScott Long } 3158ad6d6297SScott Long break; 3159ad6d6297SScott Long default: 3160ad6d6297SScott Long xpt_done(pccb); 3161ad6d6297SScott Long } 3162ad6d6297SScott Long } 3163ad6d6297SScott Long /* 3164f1c579b1SScott Long ********************************************************************* 3165f1c579b1SScott Long ********************************************************************* 3166f1c579b1SScott Long */ 3167ad6d6297SScott Long static void arcmsr_action(struct cam_sim *psim, union ccb *pccb) 3168f1c579b1SScott Long { 3169ad6d6297SScott Long struct AdapterControlBlock *acb; 3170f1c579b1SScott Long 3171ad6d6297SScott Long acb = (struct AdapterControlBlock *) cam_sim_softc(psim); 3172ad6d6297SScott Long if(acb == NULL) { 3173ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 3174f1c579b1SScott Long xpt_done(pccb); 3175f1c579b1SScott Long return; 3176f1c579b1SScott Long } 3177ad6d6297SScott Long switch (pccb->ccb_h.func_code) { 3178ad6d6297SScott Long case XPT_SCSI_IO: { 3179ad6d6297SScott Long struct CommandControlBlock *srb; 3180ad6d6297SScott Long int target = pccb->ccb_h.target_id; 3181dd0b4fb6SKonstantin Belousov int error; 3182f1c579b1SScott Long 31834aa947cbSWarner Losh if (pccb->ccb_h.flags & CAM_CDB_PHYS) { 31844aa947cbSWarner Losh pccb->ccb_h.status = CAM_REQ_INVALID; 31854aa947cbSWarner Losh xpt_done(pccb); 31864aa947cbSWarner Losh return; 31874aa947cbSWarner Losh } 31884aa947cbSWarner Losh 3189ad6d6297SScott Long if(target == 16) { 3190ad6d6297SScott Long /* virtual device for iop message transfer */ 3191ad6d6297SScott Long arcmsr_handle_virtual_command(acb, pccb); 3192ad6d6297SScott Long return; 3193ad6d6297SScott Long } 3194ad6d6297SScott Long if((srb = arcmsr_get_freesrb(acb)) == NULL) { 3195ad6d6297SScott Long pccb->ccb_h.status |= CAM_RESRC_UNAVAIL; 3196f1c579b1SScott Long xpt_done(pccb); 3197f1c579b1SScott Long return; 3198f1c579b1SScott Long } 3199ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbsrb_ptr = srb; 3200ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbacb_ptr = acb; 3201ad6d6297SScott Long srb->pccb = pccb; 3202dd0b4fb6SKonstantin Belousov error = bus_dmamap_load_ccb(acb->dm_segs_dmat 3203ad6d6297SScott Long , srb->dm_segs_dmamap 3204dd0b4fb6SKonstantin Belousov , pccb 3205231c8b71SXin LI , arcmsr_execute_srb, srb, /*flags*/0); 3206ad6d6297SScott Long if(error == EINPROGRESS) { 3207ad6d6297SScott Long xpt_freeze_simq(acb->psim, 1); 3208f1c579b1SScott Long pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 3209f1c579b1SScott Long } 3210f1c579b1SScott Long break; 3211f1c579b1SScott Long } 3212ad6d6297SScott Long case XPT_PATH_INQ: { 3213f1c579b1SScott Long struct ccb_pathinq *cpi = &pccb->cpi; 3214f1c579b1SScott Long 3215f1c579b1SScott Long cpi->version_num = 1; 3216f1c579b1SScott Long cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE; 3217f1c579b1SScott Long cpi->target_sprt = 0; 3218f1c579b1SScott Long cpi->hba_misc = 0; 3219f1c579b1SScott Long cpi->hba_eng_cnt = 0; 3220ad6d6297SScott Long cpi->max_target = ARCMSR_MAX_TARGETID; /* 0-16 */ 3221ad6d6297SScott Long cpi->max_lun = ARCMSR_MAX_TARGETLUN; /* 0-7 */ 3222ad6d6297SScott Long cpi->initiator_id = ARCMSR_SCSI_INITIATOR_ID; /* 255 */ 3223f1c579b1SScott Long cpi->bus_id = cam_sim_bus(psim); 32244195c7deSAlan Somers strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 32254195c7deSAlan Somers strlcpy(cpi->hba_vid, "ARCMSR", HBA_IDLEN); 32264195c7deSAlan Somers strlcpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN); 3227f1c579b1SScott Long cpi->unit_number = cam_sim_unit(psim); 3228224a78aeSXin LI if(acb->adapter_bus_speed == ACB_BUS_SPEED_12G) 3229224a78aeSXin LI cpi->base_transfer_speed = 1200000; 3230224a78aeSXin LI else if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G) 3231dac36688SXin LI cpi->base_transfer_speed = 600000; 3232dac36688SXin LI else 3233dac36688SXin LI cpi->base_transfer_speed = 300000; 3234dac36688SXin LI if((acb->vendor_device_id == PCIDevVenIDARC1880) || 3235a1103e04SXin LI (acb->vendor_device_id == PCIDevVenIDARC1884) || 32367a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1680) || 32377a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1214)) 3238dac36688SXin LI { 3239dac36688SXin LI cpi->transport = XPORT_SAS; 3240dac36688SXin LI cpi->transport_version = 0; 3241dac36688SXin LI cpi->protocol_version = SCSI_REV_SPC2; 3242dac36688SXin LI } 3243dac36688SXin LI else 3244dac36688SXin LI { 3245fa9ed865SMatt Jacob cpi->transport = XPORT_SPI; 3246fa9ed865SMatt Jacob cpi->transport_version = 2; 3247fa9ed865SMatt Jacob cpi->protocol_version = SCSI_REV_2; 3248dac36688SXin LI } 3249dac36688SXin LI cpi->protocol = PROTO_SCSI; 3250ad6d6297SScott Long cpi->ccb_h.status |= CAM_REQ_CMP; 3251f1c579b1SScott Long xpt_done(pccb); 3252f1c579b1SScott Long break; 3253f1c579b1SScott Long } 3254ad6d6297SScott Long case XPT_ABORT: { 3255f1c579b1SScott Long union ccb *pabort_ccb; 3256f1c579b1SScott Long 3257f1c579b1SScott Long pabort_ccb = pccb->cab.abort_ccb; 3258ad6d6297SScott Long switch (pabort_ccb->ccb_h.func_code) { 3259f1c579b1SScott Long case XPT_ACCEPT_TARGET_IO: 3260f1c579b1SScott Long case XPT_CONT_TARGET_IO: 3261ad6d6297SScott Long if(arcmsr_seek_cmd2abort(pabort_ccb)==TRUE) { 3262ad6d6297SScott Long pabort_ccb->ccb_h.status |= CAM_REQ_ABORTED; 3263f1c579b1SScott Long xpt_done(pabort_ccb); 3264ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 3265ad6d6297SScott Long } else { 3266f1c579b1SScott Long xpt_print_path(pabort_ccb->ccb_h.path); 3267f1c579b1SScott Long printf("Not found\n"); 3268ad6d6297SScott Long pccb->ccb_h.status |= CAM_PATH_INVALID; 3269f1c579b1SScott Long } 3270f1c579b1SScott Long break; 3271f1c579b1SScott Long case XPT_SCSI_IO: 3272ad6d6297SScott Long pccb->ccb_h.status |= CAM_UA_ABORT; 3273f1c579b1SScott Long break; 3274f1c579b1SScott Long default: 3275ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 3276f1c579b1SScott Long break; 3277f1c579b1SScott Long } 3278f1c579b1SScott Long xpt_done(pccb); 3279f1c579b1SScott Long break; 3280f1c579b1SScott Long } 3281f1c579b1SScott Long case XPT_RESET_BUS: 3282ad6d6297SScott Long case XPT_RESET_DEV: { 3283ad6d6297SScott Long u_int32_t i; 3284f1c579b1SScott Long 3285ad6d6297SScott Long arcmsr_bus_reset(acb); 3286ad6d6297SScott Long for (i=0; i < 500; i++) { 3287f1c579b1SScott Long DELAY(1000); 3288f1c579b1SScott Long } 3289ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 3290f1c579b1SScott Long xpt_done(pccb); 3291f1c579b1SScott Long break; 3292f1c579b1SScott Long } 3293ad6d6297SScott Long case XPT_TERM_IO: { 3294ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 3295f1c579b1SScott Long xpt_done(pccb); 3296f1c579b1SScott Long break; 3297f1c579b1SScott Long } 3298ad6d6297SScott Long case XPT_GET_TRAN_SETTINGS: { 3299ad6d6297SScott Long struct ccb_trans_settings *cts; 3300ad6d6297SScott Long 3301ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 3302ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 3303ad6d6297SScott Long xpt_done(pccb); 3304ad6d6297SScott Long break; 3305ad6d6297SScott Long } 3306ad6d6297SScott Long cts = &pccb->cts; 330744f05562SScott Long { 330844f05562SScott Long struct ccb_trans_settings_scsi *scsi; 330944f05562SScott Long struct ccb_trans_settings_spi *spi; 3310dac36688SXin LI struct ccb_trans_settings_sas *sas; 331144f05562SScott Long 3312ad6d6297SScott Long scsi = &cts->proto_specific.scsi; 3313dac36688SXin LI scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 3314dac36688SXin LI scsi->valid = CTS_SCSI_VALID_TQ; 3315fa9ed865SMatt Jacob cts->protocol = PROTO_SCSI; 3316dac36688SXin LI 3317dac36688SXin LI if((acb->vendor_device_id == PCIDevVenIDARC1880) || 3318a1103e04SXin LI (acb->vendor_device_id == PCIDevVenIDARC1884) || 33197a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1680) || 33207a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1214)) 3321dac36688SXin LI { 3322dac36688SXin LI cts->protocol_version = SCSI_REV_SPC2; 3323dac36688SXin LI cts->transport_version = 0; 3324dac36688SXin LI cts->transport = XPORT_SAS; 3325dac36688SXin LI sas = &cts->xport_specific.sas; 3326dac36688SXin LI sas->valid = CTS_SAS_VALID_SPEED; 3327b23a1998SXin LI if (acb->adapter_bus_speed == ACB_BUS_SPEED_12G) 3328224a78aeSXin LI sas->bitrate = 1200000; 3329b23a1998SXin LI else if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G) 3330dac36688SXin LI sas->bitrate = 600000; 3331b23a1998SXin LI else if(acb->adapter_bus_speed == ACB_BUS_SPEED_3G) 3332dac36688SXin LI sas->bitrate = 300000; 3333dac36688SXin LI } 3334dac36688SXin LI else 3335dac36688SXin LI { 3336fa9ed865SMatt Jacob cts->protocol_version = SCSI_REV_2; 3337fa9ed865SMatt Jacob cts->transport_version = 2; 3338dac36688SXin LI cts->transport = XPORT_SPI; 3339dac36688SXin LI spi = &cts->xport_specific.spi; 3340fa9ed865SMatt Jacob spi->flags = CTS_SPI_FLAGS_DISC_ENB; 3341b23a1998SXin LI if (acb->adapter_bus_speed == ACB_BUS_SPEED_6G) 3342b23a1998SXin LI spi->sync_period = 1; 3343b23a1998SXin LI else 3344dac36688SXin LI spi->sync_period = 2; 3345fa9ed865SMatt Jacob spi->sync_offset = 32; 3346fa9ed865SMatt Jacob spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 33479d98ff4dSScott Long spi->valid = CTS_SPI_VALID_DISC 33489d98ff4dSScott Long | CTS_SPI_VALID_SYNC_RATE 3349fa9ed865SMatt Jacob | CTS_SPI_VALID_SYNC_OFFSET 3350fa9ed865SMatt Jacob | CTS_SPI_VALID_BUS_WIDTH; 3351dac36688SXin LI } 335244f05562SScott Long } 3353ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 3354ad6d6297SScott Long xpt_done(pccb); 3355ad6d6297SScott Long break; 3356ad6d6297SScott Long } 3357ad6d6297SScott Long case XPT_SET_TRAN_SETTINGS: { 3358ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 3359ad6d6297SScott Long xpt_done(pccb); 3360ad6d6297SScott Long break; 3361ad6d6297SScott Long } 3362f3b080e6SMarius Strobl case XPT_CALC_GEOMETRY: 3363ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 3364ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 3365ad6d6297SScott Long xpt_done(pccb); 3366ad6d6297SScott Long break; 3367ad6d6297SScott Long } 3368f3b080e6SMarius Strobl cam_calc_geometry(&pccb->ccg, 1); 3369f1c579b1SScott Long xpt_done(pccb); 3370f1c579b1SScott Long break; 3371f1c579b1SScott Long default: 3372ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 3373f1c579b1SScott Long xpt_done(pccb); 3374f1c579b1SScott Long break; 3375f1c579b1SScott Long } 3376f1c579b1SScott Long } 3377f1c579b1SScott Long /* 3378f1c579b1SScott Long ********************************************************************** 3379f1c579b1SScott Long ********************************************************************** 3380f1c579b1SScott Long */ 338144f05562SScott Long static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) 3382f1c579b1SScott Long { 3383ad6d6297SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 338444f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 338544f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 3386ad6d6297SScott Long printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 3387ad6d6297SScott Long } 3388f1c579b1SScott Long } 3389f1c579b1SScott Long /* 3390f1c579b1SScott Long ********************************************************************** 3391f1c579b1SScott Long ********************************************************************** 3392f1c579b1SScott Long */ 339344f05562SScott Long static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb) 339444f05562SScott Long { 3395b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 339644f05562SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 3397b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_START_BGRB); 339844f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 339944f05562SScott Long printf( "arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 340044f05562SScott Long } 340144f05562SScott Long } 340244f05562SScott Long /* 340344f05562SScott Long ********************************************************************** 340444f05562SScott Long ********************************************************************** 340544f05562SScott Long */ 3406d74001adSXin LI static void arcmsr_start_hbc_bgrb(struct AdapterControlBlock *acb) 3407d74001adSXin LI { 3408d74001adSXin LI acb->acb_flags |= ACB_F_MSG_START_BGRB; 3409d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 3410d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 3411d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 3412d74001adSXin LI printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 3413d74001adSXin LI } 3414d74001adSXin LI } 3415d74001adSXin LI /* 3416d74001adSXin LI ********************************************************************** 3417d74001adSXin LI ********************************************************************** 3418d74001adSXin LI */ 34197a7bc959SXin LI static void arcmsr_start_hbd_bgrb(struct AdapterControlBlock *acb) 34207a7bc959SXin LI { 34217a7bc959SXin LI acb->acb_flags |= ACB_F_MSG_START_BGRB; 34227a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 34237a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 34247a7bc959SXin LI printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 34257a7bc959SXin LI } 34267a7bc959SXin LI } 34277a7bc959SXin LI /* 34287a7bc959SXin LI ********************************************************************** 34297a7bc959SXin LI ********************************************************************** 34307a7bc959SXin LI */ 3431a1103e04SXin LI static void arcmsr_start_hbe_bgrb(struct AdapterControlBlock *acb) 3432a1103e04SXin LI { 3433a1103e04SXin LI acb->acb_flags |= ACB_F_MSG_START_BGRB; 3434a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 3435a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 3436a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 3437a1103e04SXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) { 3438a1103e04SXin LI printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 3439a1103e04SXin LI } 3440a1103e04SXin LI } 3441a1103e04SXin LI /* 3442a1103e04SXin LI ********************************************************************** 3443a1103e04SXin LI ********************************************************************** 3444a1103e04SXin LI */ 344544f05562SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) 344644f05562SScott Long { 344744f05562SScott Long switch (acb->adapter_type) { 344844f05562SScott Long case ACB_ADAPTER_TYPE_A: 344944f05562SScott Long arcmsr_start_hba_bgrb(acb); 345044f05562SScott Long break; 345144f05562SScott Long case ACB_ADAPTER_TYPE_B: 345244f05562SScott Long arcmsr_start_hbb_bgrb(acb); 345344f05562SScott Long break; 3454d74001adSXin LI case ACB_ADAPTER_TYPE_C: 3455d74001adSXin LI arcmsr_start_hbc_bgrb(acb); 3456d74001adSXin LI break; 34577a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 34587a7bc959SXin LI arcmsr_start_hbd_bgrb(acb); 34597a7bc959SXin LI break; 3460a1103e04SXin LI case ACB_ADAPTER_TYPE_E: 3461fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 3462a1103e04SXin LI arcmsr_start_hbe_bgrb(acb); 3463a1103e04SXin LI break; 346444f05562SScott Long } 346544f05562SScott Long } 346644f05562SScott Long /* 346744f05562SScott Long ********************************************************************** 346844f05562SScott Long ** 346944f05562SScott Long ********************************************************************** 347044f05562SScott Long */ 347144f05562SScott Long static void arcmsr_polling_hba_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 3472f1c579b1SScott Long { 3473ad6d6297SScott Long struct CommandControlBlock *srb; 347444f05562SScott Long u_int32_t flag_srb, outbound_intstatus, poll_srb_done=0, poll_count=0; 3475d74001adSXin LI u_int16_t error; 3476f1c579b1SScott Long 347744f05562SScott Long polling_ccb_retry: 3478ad6d6297SScott Long poll_count++; 3479d74001adSXin LI outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 3480d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus); /*clear interrupt*/ 348144f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 3482ad6d6297SScott Long while(1) { 348344f05562SScott Long if((flag_srb = CHIP_REG_READ32(HBA_MessageUnit, 348444f05562SScott Long 0, outbound_queueport)) == 0xFFFFFFFF) { 3485ad6d6297SScott Long if(poll_srb_done) { 3486ad6d6297SScott Long break;/*chip FIFO no ccb for completion already*/ 3487ad6d6297SScott Long } else { 3488ad6d6297SScott Long UDELAY(25000); 3489d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 3490ad6d6297SScott Long break; 3491f1c579b1SScott Long } 349244f05562SScott Long goto polling_ccb_retry; 3493f1c579b1SScott Long } 3494ad6d6297SScott Long } 3495ad6d6297SScott Long /* check if command done with no error*/ 349644f05562SScott Long srb = (struct CommandControlBlock *) 349744f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 3498d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 349944f05562SScott Long poll_srb_done = (srb == poll_srb) ? 1:0; 350022f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 350122f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3502123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'" 3503ad6d6297SScott Long "poll command abort successfully \n" 3504ad6d6297SScott Long , acb->pci_unit 3505ad6d6297SScott Long , srb->pccb->ccb_h.target_id 3506123055f0SNathan Whitehorn , (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 3507ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 3508ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 3509ad6d6297SScott Long continue; 3510ad6d6297SScott Long } 3511ad6d6297SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 3512ad6d6297SScott Long "srboutstandingcount=%d \n" 3513ad6d6297SScott Long , acb->pci_unit 3514ad6d6297SScott Long , srb, acb->srboutstandingcount); 3515ad6d6297SScott Long continue; 3516ad6d6297SScott Long } 3517d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 3518ad6d6297SScott Long } /*drain reply FIFO*/ 3519f1c579b1SScott Long } 3520f1c579b1SScott Long /* 3521f1c579b1SScott Long ********************************************************************** 352244f05562SScott Long ** 3523ad6d6297SScott Long ********************************************************************** 3524ad6d6297SScott Long */ 352544f05562SScott Long static void arcmsr_polling_hbb_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 352644f05562SScott Long { 352744f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 352844f05562SScott Long struct CommandControlBlock *srb; 352944f05562SScott Long u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 353044f05562SScott Long int index; 3531d74001adSXin LI u_int16_t error; 353244f05562SScott Long 353344f05562SScott Long polling_ccb_retry: 353444f05562SScott Long poll_count++; 3535b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 353644f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 353744f05562SScott Long while(1) { 353844f05562SScott Long index = phbbmu->doneq_index; 353944f05562SScott Long if((flag_srb = phbbmu->done_qbuffer[index]) == 0) { 354044f05562SScott Long if(poll_srb_done) { 354144f05562SScott Long break;/*chip FIFO no ccb for completion already*/ 354244f05562SScott Long } else { 354344f05562SScott Long UDELAY(25000); 3544d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 354544f05562SScott Long break; 354644f05562SScott Long } 354744f05562SScott Long goto polling_ccb_retry; 354844f05562SScott Long } 354944f05562SScott Long } 355044f05562SScott Long phbbmu->done_qbuffer[index] = 0; 355144f05562SScott Long index++; 355244f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 355344f05562SScott Long phbbmu->doneq_index = index; 355444f05562SScott Long /* check if command done with no error*/ 355544f05562SScott Long srb = (struct CommandControlBlock *) 355644f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 3557d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 355844f05562SScott Long poll_srb_done = (srb == poll_srb) ? 1:0; 355922f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 356022f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3561123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'" 356244f05562SScott Long "poll command abort successfully \n" 356344f05562SScott Long , acb->pci_unit 356444f05562SScott Long , srb->pccb->ccb_h.target_id 3565123055f0SNathan Whitehorn , (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 356644f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 356744f05562SScott Long arcmsr_srb_complete(srb, 1); 356844f05562SScott Long continue; 356944f05562SScott Long } 357044f05562SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 357144f05562SScott Long "srboutstandingcount=%d \n" 357244f05562SScott Long , acb->pci_unit 357344f05562SScott Long , srb, acb->srboutstandingcount); 357444f05562SScott Long continue; 357544f05562SScott Long } 3576d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 3577d74001adSXin LI } /*drain reply FIFO*/ 3578d74001adSXin LI } 3579d74001adSXin LI /* 3580d74001adSXin LI ********************************************************************** 3581d74001adSXin LI ** 3582d74001adSXin LI ********************************************************************** 3583d74001adSXin LI */ 3584d74001adSXin LI static void arcmsr_polling_hbc_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 3585d74001adSXin LI { 3586d74001adSXin LI struct CommandControlBlock *srb; 3587d74001adSXin LI u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 3588d74001adSXin LI u_int16_t error; 3589d74001adSXin LI 3590d74001adSXin LI polling_ccb_retry: 3591d74001adSXin LI poll_count++; 3592d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 3593d74001adSXin LI while(1) { 3594d74001adSXin LI if(!(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR)) { 3595d74001adSXin LI if(poll_srb_done) { 3596d74001adSXin LI break;/*chip FIFO no ccb for completion already*/ 3597d74001adSXin LI } else { 3598d74001adSXin LI UDELAY(25000); 3599d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 3600d74001adSXin LI break; 3601d74001adSXin LI } 3602d74001adSXin LI if (acb->srboutstandingcount == 0) { 3603d74001adSXin LI break; 3604d74001adSXin LI } 3605d74001adSXin LI goto polling_ccb_retry; 3606d74001adSXin LI } 3607d74001adSXin LI } 3608d74001adSXin LI flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 3609d74001adSXin LI /* check if command done with no error*/ 361022f2616bSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/ 3611d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; 3612d74001adSXin LI if (poll_srb != NULL) 3613d74001adSXin LI poll_srb_done = (srb == poll_srb) ? 1:0; 361422f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 361522f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3616123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n" 3617123055f0SNathan Whitehorn , acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 3618d74001adSXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 3619d74001adSXin LI arcmsr_srb_complete(srb, 1); 3620d74001adSXin LI continue; 3621d74001adSXin LI } 3622d74001adSXin LI printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n" 3623d74001adSXin LI , acb->pci_unit, srb, acb->srboutstandingcount); 3624d74001adSXin LI continue; 3625d74001adSXin LI } 3626d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 362744f05562SScott Long } /*drain reply FIFO*/ 362844f05562SScott Long } 362944f05562SScott Long /* 363044f05562SScott Long ********************************************************************** 36317a7bc959SXin LI ** 36327a7bc959SXin LI ********************************************************************** 36337a7bc959SXin LI */ 36347a7bc959SXin LI static void arcmsr_polling_hbd_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 36357a7bc959SXin LI { 36367a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 36377a7bc959SXin LI struct CommandControlBlock *srb; 36387a7bc959SXin LI u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 36397a7bc959SXin LI u_int32_t outbound_write_pointer; 36407a7bc959SXin LI u_int16_t error, doneq_index; 36417a7bc959SXin LI 36427a7bc959SXin LI polling_ccb_retry: 36437a7bc959SXin LI poll_count++; 36447a7bc959SXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 36457a7bc959SXin LI while(1) { 36467a7bc959SXin LI outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow; 36477a7bc959SXin LI doneq_index = phbdmu->doneq_index; 36487a7bc959SXin LI if ((outbound_write_pointer & 0xFF) == (doneq_index & 0xFF)) { 36497a7bc959SXin LI if(poll_srb_done) { 36507a7bc959SXin LI break;/*chip FIFO no ccb for completion already*/ 36517a7bc959SXin LI } else { 36527a7bc959SXin LI UDELAY(25000); 36537a7bc959SXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 36547a7bc959SXin LI break; 36557a7bc959SXin LI } 36567a7bc959SXin LI if (acb->srboutstandingcount == 0) { 36577a7bc959SXin LI break; 36587a7bc959SXin LI } 36597a7bc959SXin LI goto polling_ccb_retry; 36607a7bc959SXin LI } 36617a7bc959SXin LI } 36627a7bc959SXin LI doneq_index = arcmsr_get_doneq_index(phbdmu); 36637a7bc959SXin LI flag_srb = phbdmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow; 36647a7bc959SXin LI /* check if command done with no error*/ 36657a7bc959SXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/ 36667a7bc959SXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 36677a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_read_pointer, doneq_index); 36687a7bc959SXin LI if (poll_srb != NULL) 36697a7bc959SXin LI poll_srb_done = (srb == poll_srb) ? 1:0; 36707a7bc959SXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 36717a7bc959SXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3672123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n" 3673123055f0SNathan Whitehorn , acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 36747a7bc959SXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 36757a7bc959SXin LI arcmsr_srb_complete(srb, 1); 36767a7bc959SXin LI continue; 36777a7bc959SXin LI } 36787a7bc959SXin LI printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n" 36797a7bc959SXin LI , acb->pci_unit, srb, acb->srboutstandingcount); 36807a7bc959SXin LI continue; 36817a7bc959SXin LI } 36827a7bc959SXin LI arcmsr_report_srb_state(acb, srb, error); 36837a7bc959SXin LI } /*drain reply FIFO*/ 36847a7bc959SXin LI } 36857a7bc959SXin LI /* 36867a7bc959SXin LI ********************************************************************** 3687a1103e04SXin LI ** 3688a1103e04SXin LI ********************************************************************** 3689a1103e04SXin LI */ 3690a1103e04SXin LI static void arcmsr_polling_hbe_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 3691a1103e04SXin LI { 3692a1103e04SXin LI struct CommandControlBlock *srb; 3693a1103e04SXin LI u_int32_t poll_srb_done=0, poll_count=0, doneq_index; 3694a1103e04SXin LI u_int16_t error, cmdSMID; 3695a1103e04SXin LI 3696a1103e04SXin LI polling_ccb_retry: 3697a1103e04SXin LI poll_count++; 3698a1103e04SXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 3699a1103e04SXin LI while(1) { 3700a1103e04SXin LI doneq_index = acb->doneq_index; 3701a1103e04SXin LI if((CHIP_REG_READ32(HBE_MessageUnit, 0, reply_post_producer_index) & 0xFFFF) == doneq_index) { 3702a1103e04SXin LI if(poll_srb_done) { 3703a1103e04SXin LI break;/*chip FIFO no ccb for completion already*/ 3704a1103e04SXin LI } else { 3705a1103e04SXin LI UDELAY(25000); 3706a1103e04SXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 3707a1103e04SXin LI break; 3708a1103e04SXin LI } 3709a1103e04SXin LI if (acb->srboutstandingcount == 0) { 3710a1103e04SXin LI break; 3711a1103e04SXin LI } 3712a1103e04SXin LI goto polling_ccb_retry; 3713a1103e04SXin LI } 3714a1103e04SXin LI } 3715a1103e04SXin LI cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID; 3716a1103e04SXin LI doneq_index++; 3717a1103e04SXin LI if (doneq_index >= acb->completionQ_entry) 3718a1103e04SXin LI doneq_index = 0; 3719a1103e04SXin LI acb->doneq_index = doneq_index; 3720a1103e04SXin LI srb = acb->psrb_pool[cmdSMID]; 3721a1103e04SXin LI error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 3722a1103e04SXin LI if (poll_srb != NULL) 3723a1103e04SXin LI poll_srb_done = (srb == poll_srb) ? 1:0; 3724a1103e04SXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 3725a1103e04SXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3726a1103e04SXin LI printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n" 3727a1103e04SXin LI , acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 3728a1103e04SXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 3729a1103e04SXin LI arcmsr_srb_complete(srb, 1); 3730a1103e04SXin LI continue; 3731a1103e04SXin LI } 3732a1103e04SXin LI printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n" 3733a1103e04SXin LI , acb->pci_unit, srb, acb->srboutstandingcount); 3734a1103e04SXin LI continue; 3735a1103e04SXin LI } 3736a1103e04SXin LI arcmsr_report_srb_state(acb, srb, error); 3737a1103e04SXin LI } /*drain reply FIFO*/ 3738a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, reply_post_producer_index, doneq_index); 3739a1103e04SXin LI } 3740a1103e04SXin LI /* 3741a1103e04SXin LI ********************************************************************** 374244f05562SScott Long ********************************************************************** 374344f05562SScott Long */ 374444f05562SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 374544f05562SScott Long { 374644f05562SScott Long switch (acb->adapter_type) { 3747fa42a0bfSXin LI case ACB_ADAPTER_TYPE_A: 374844f05562SScott Long arcmsr_polling_hba_srbdone(acb, poll_srb); 374944f05562SScott Long break; 3750fa42a0bfSXin LI case ACB_ADAPTER_TYPE_B: 375144f05562SScott Long arcmsr_polling_hbb_srbdone(acb, poll_srb); 375244f05562SScott Long break; 3753fa42a0bfSXin LI case ACB_ADAPTER_TYPE_C: 3754d74001adSXin LI arcmsr_polling_hbc_srbdone(acb, poll_srb); 3755d74001adSXin LI break; 3756fa42a0bfSXin LI case ACB_ADAPTER_TYPE_D: 37577a7bc959SXin LI arcmsr_polling_hbd_srbdone(acb, poll_srb); 37587a7bc959SXin LI break; 3759fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 3760fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 3761a1103e04SXin LI arcmsr_polling_hbe_srbdone(acb, poll_srb); 3762a1103e04SXin LI break; 376344f05562SScott Long } 376444f05562SScott Long } 376544f05562SScott Long /* 376644f05562SScott Long ********************************************************************** 376744f05562SScott Long ********************************************************************** 376844f05562SScott Long */ 376944f05562SScott Long static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) 3770ad6d6297SScott Long { 3771ad6d6297SScott Long char *acb_firm_model = acb->firm_model; 3772ad6d6297SScott Long char *acb_firm_version = acb->firm_version; 3773d74001adSXin LI char *acb_device_map = acb->device_map; 3774d74001adSXin LI size_t iop_firm_model = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3775d74001adSXin LI size_t iop_firm_version = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3776d74001adSXin LI size_t iop_device_map = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 3777ad6d6297SScott Long int i; 3778ad6d6297SScott Long 377944f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 378044f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 3781d74001adSXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 3782ad6d6297SScott Long } 3783ad6d6297SScott Long i = 0; 3784ad6d6297SScott Long while(i < 8) { 378544f05562SScott Long *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 3786ad6d6297SScott Long /* 8 bytes firm_model, 15, 60-67*/ 3787ad6d6297SScott Long acb_firm_model++; 3788ad6d6297SScott Long i++; 3789ad6d6297SScott Long } 3790ad6d6297SScott Long i=0; 3791ad6d6297SScott Long while(i < 16) { 379244f05562SScott Long *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 3793ad6d6297SScott Long /* 16 bytes firm_version, 17, 68-83*/ 3794ad6d6297SScott Long acb_firm_version++; 3795ad6d6297SScott Long i++; 3796ad6d6297SScott Long } 3797d74001adSXin LI i=0; 3798d74001adSXin LI while(i < 16) { 3799d74001adSXin LI *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 3800d74001adSXin LI acb_device_map++; 3801d74001adSXin LI i++; 3802d74001adSXin LI } 38031e7d660aSXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 3804d74001adSXin LI acb->firm_request_len = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3805d74001adSXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3806d74001adSXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3807d74001adSXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3808d74001adSXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3809abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD) 3810abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1; 3811abfdbca9SXin LI else 3812abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 3813ad6d6297SScott Long } 3814ad6d6297SScott Long /* 3815ad6d6297SScott Long ********************************************************************** 381644f05562SScott Long ********************************************************************** 381744f05562SScott Long */ 381844f05562SScott Long static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) 381944f05562SScott Long { 3820b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 382144f05562SScott Long char *acb_firm_model = acb->firm_model; 382244f05562SScott Long char *acb_firm_version = acb->firm_version; 3823d74001adSXin LI char *acb_device_map = acb->device_map; 3824d74001adSXin LI size_t iop_firm_model = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3825d74001adSXin LI size_t iop_firm_version = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3826d74001adSXin LI size_t iop_device_map = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 382744f05562SScott Long int i; 382844f05562SScott Long 3829b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG); 383044f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 3831d74001adSXin LI printf( "arcmsr%d: wait" "'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 383244f05562SScott Long } 383344f05562SScott Long i = 0; 383444f05562SScott Long while(i < 8) { 383544f05562SScott Long *acb_firm_model = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_model+i); 383644f05562SScott Long /* 8 bytes firm_model, 15, 60-67*/ 383744f05562SScott Long acb_firm_model++; 383844f05562SScott Long i++; 383944f05562SScott Long } 384044f05562SScott Long i = 0; 384144f05562SScott Long while(i < 16) { 384244f05562SScott Long *acb_firm_version = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_version+i); 384344f05562SScott Long /* 16 bytes firm_version, 17, 68-83*/ 384444f05562SScott Long acb_firm_version++; 384544f05562SScott Long i++; 384644f05562SScott Long } 3847d74001adSXin LI i = 0; 3848d74001adSXin LI while(i < 16) { 3849d74001adSXin LI *acb_device_map = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_device_map+i); 3850d74001adSXin LI acb_device_map++; 3851d74001adSXin LI i++; 3852d74001adSXin LI } 38531e7d660aSXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 3854d74001adSXin LI acb->firm_request_len = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3855d74001adSXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3856d74001adSXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3857d74001adSXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3858d74001adSXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3859abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_HBB_POSTQUEUE) 3860abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_HBB_POSTQUEUE - 1; 3861abfdbca9SXin LI else 3862abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 3863d74001adSXin LI } 3864d74001adSXin LI /* 3865d74001adSXin LI ********************************************************************** 3866d74001adSXin LI ********************************************************************** 3867d74001adSXin LI */ 3868d74001adSXin LI static void arcmsr_get_hbc_config(struct AdapterControlBlock *acb) 3869d74001adSXin LI { 3870d74001adSXin LI char *acb_firm_model = acb->firm_model; 3871d74001adSXin LI char *acb_firm_version = acb->firm_version; 3872d74001adSXin LI char *acb_device_map = acb->device_map; 3873d74001adSXin LI size_t iop_firm_model = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3874d74001adSXin LI size_t iop_firm_version = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3875d74001adSXin LI size_t iop_device_map = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 3876d74001adSXin LI int i; 3877d74001adSXin LI 3878d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 3879d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 3880d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 3881d74001adSXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 3882d74001adSXin LI } 3883d74001adSXin LI i = 0; 3884d74001adSXin LI while(i < 8) { 3885d74001adSXin LI *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 3886d74001adSXin LI /* 8 bytes firm_model, 15, 60-67*/ 3887d74001adSXin LI acb_firm_model++; 3888d74001adSXin LI i++; 3889d74001adSXin LI } 3890d74001adSXin LI i = 0; 3891d74001adSXin LI while(i < 16) { 3892d74001adSXin LI *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 3893d74001adSXin LI /* 16 bytes firm_version, 17, 68-83*/ 3894d74001adSXin LI acb_firm_version++; 3895d74001adSXin LI i++; 3896d74001adSXin LI } 3897d74001adSXin LI i = 0; 3898d74001adSXin LI while(i < 16) { 3899d74001adSXin LI *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 3900d74001adSXin LI acb_device_map++; 3901d74001adSXin LI i++; 3902d74001adSXin LI } 39031e7d660aSXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 3904d74001adSXin LI acb->firm_request_len = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3905d74001adSXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3906d74001adSXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3907d74001adSXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3908d74001adSXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3909abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD) 3910abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1; 3911abfdbca9SXin LI else 3912abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 391344f05562SScott Long } 391444f05562SScott Long /* 391544f05562SScott Long ********************************************************************** 391644f05562SScott Long ********************************************************************** 391744f05562SScott Long */ 39187a7bc959SXin LI static void arcmsr_get_hbd_config(struct AdapterControlBlock *acb) 39197a7bc959SXin LI { 39207a7bc959SXin LI char *acb_firm_model = acb->firm_model; 39217a7bc959SXin LI char *acb_firm_version = acb->firm_version; 39227a7bc959SXin LI char *acb_device_map = acb->device_map; 39237a7bc959SXin LI size_t iop_firm_model = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 39247a7bc959SXin LI size_t iop_firm_version = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 39257a7bc959SXin LI size_t iop_device_map = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 39267a7bc959SXin LI int i; 39277a7bc959SXin LI 39287a7bc959SXin LI if(CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) 39297a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR); 39307a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 39317a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 39327a7bc959SXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 39337a7bc959SXin LI } 39347a7bc959SXin LI i = 0; 39357a7bc959SXin LI while(i < 8) { 39367a7bc959SXin LI *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 39377a7bc959SXin LI /* 8 bytes firm_model, 15, 60-67*/ 39387a7bc959SXin LI acb_firm_model++; 39397a7bc959SXin LI i++; 39407a7bc959SXin LI } 39417a7bc959SXin LI i = 0; 39427a7bc959SXin LI while(i < 16) { 39437a7bc959SXin LI *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 39447a7bc959SXin LI /* 16 bytes firm_version, 17, 68-83*/ 39457a7bc959SXin LI acb_firm_version++; 39467a7bc959SXin LI i++; 39477a7bc959SXin LI } 39487a7bc959SXin LI i = 0; 39497a7bc959SXin LI while(i < 16) { 39507a7bc959SXin LI *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 39517a7bc959SXin LI acb_device_map++; 39527a7bc959SXin LI i++; 39537a7bc959SXin LI } 39541e7d660aSXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 3955b23a1998SXin LI acb->firm_request_len = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3956b23a1998SXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3957b23a1998SXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3958b23a1998SXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 39597a7bc959SXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3960abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_HBD_POSTQUEUE) 3961abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_HBD_POSTQUEUE - 1; 3962abfdbca9SXin LI else 3963abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 39647a7bc959SXin LI } 39657a7bc959SXin LI /* 39667a7bc959SXin LI ********************************************************************** 39677a7bc959SXin LI ********************************************************************** 39687a7bc959SXin LI */ 3969a1103e04SXin LI static void arcmsr_get_hbe_config(struct AdapterControlBlock *acb) 3970a1103e04SXin LI { 3971a1103e04SXin LI char *acb_firm_model = acb->firm_model; 3972a1103e04SXin LI char *acb_firm_version = acb->firm_version; 3973a1103e04SXin LI char *acb_device_map = acb->device_map; 3974a1103e04SXin LI size_t iop_firm_model = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3975a1103e04SXin LI size_t iop_firm_version = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3976a1103e04SXin LI size_t iop_device_map = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 3977a1103e04SXin LI int i; 3978a1103e04SXin LI 3979a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 3980a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 3981a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 3982a1103e04SXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) { 3983a1103e04SXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 3984a1103e04SXin LI } 3985a1103e04SXin LI 3986a1103e04SXin LI i = 0; 3987a1103e04SXin LI while(i < 8) { 3988a1103e04SXin LI *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 3989a1103e04SXin LI /* 8 bytes firm_model, 15, 60-67*/ 3990a1103e04SXin LI acb_firm_model++; 3991a1103e04SXin LI i++; 3992a1103e04SXin LI } 3993a1103e04SXin LI i = 0; 3994a1103e04SXin LI while(i < 16) { 3995a1103e04SXin LI *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 3996a1103e04SXin LI /* 16 bytes firm_version, 17, 68-83*/ 3997a1103e04SXin LI acb_firm_version++; 3998a1103e04SXin LI i++; 3999a1103e04SXin LI } 4000a1103e04SXin LI i = 0; 4001a1103e04SXin LI while(i < 16) { 4002a1103e04SXin LI *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 4003a1103e04SXin LI acb_device_map++; 4004a1103e04SXin LI i++; 4005a1103e04SXin LI } 4006a1103e04SXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 4007a1103e04SXin LI acb->firm_request_len = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 4008a1103e04SXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 4009a1103e04SXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 4010a1103e04SXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 4011a1103e04SXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 4012a1103e04SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD) 4013a1103e04SXin LI acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1; 4014a1103e04SXin LI else 4015a1103e04SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 4016a1103e04SXin LI } 4017a1103e04SXin LI /* 4018a1103e04SXin LI ********************************************************************** 4019a1103e04SXin LI ********************************************************************** 4020a1103e04SXin LI */ 4021fa42a0bfSXin LI static void arcmsr_get_hbf_config(struct AdapterControlBlock *acb) 4022fa42a0bfSXin LI { 4023fa42a0bfSXin LI u_int32_t *acb_firm_model = (u_int32_t *)acb->firm_model; 4024fa42a0bfSXin LI u_int32_t *acb_firm_version = (u_int32_t *)acb->firm_version; 4025fa42a0bfSXin LI u_int32_t *acb_device_map = (u_int32_t *)acb->device_map; 4026fa42a0bfSXin LI size_t iop_firm_model = ARCMSR_FW_MODEL_OFFSET; /*firm_model,15,60-67*/ 4027fa42a0bfSXin LI size_t iop_firm_version = ARCMSR_FW_VERS_OFFSET; /*firm_version,17,68-83*/ 4028fa42a0bfSXin LI size_t iop_device_map = ARCMSR_FW_DEVMAP_OFFSET; 4029fa42a0bfSXin LI int i; 4030fa42a0bfSXin LI 4031fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 4032fa42a0bfSXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 4033fa42a0bfSXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 4034fa42a0bfSXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) 4035fa42a0bfSXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 4036fa42a0bfSXin LI 4037fa42a0bfSXin LI i = 0; 4038fa42a0bfSXin LI while(i < 2) { 4039fa42a0bfSXin LI *acb_firm_model = acb->msgcode_rwbuffer[iop_firm_model]; 4040fa42a0bfSXin LI /* 8 bytes firm_model, 15, 60-67*/ 4041fa42a0bfSXin LI acb_firm_model++; 4042fa42a0bfSXin LI iop_firm_model++; 4043fa42a0bfSXin LI i++; 4044fa42a0bfSXin LI } 4045fa42a0bfSXin LI i = 0; 4046fa42a0bfSXin LI while(i < 4) { 4047fa42a0bfSXin LI *acb_firm_version = acb->msgcode_rwbuffer[iop_firm_version]; 4048fa42a0bfSXin LI /* 16 bytes firm_version, 17, 68-83*/ 4049fa42a0bfSXin LI acb_firm_version++; 4050fa42a0bfSXin LI iop_firm_version++; 4051fa42a0bfSXin LI i++; 4052fa42a0bfSXin LI } 4053fa42a0bfSXin LI i = 0; 4054fa42a0bfSXin LI while(i < 4) { 4055fa42a0bfSXin LI *acb_device_map = acb->msgcode_rwbuffer[iop_device_map]; 4056fa42a0bfSXin LI acb_device_map++; 4057fa42a0bfSXin LI iop_device_map++; 4058fa42a0bfSXin LI i++; 4059fa42a0bfSXin LI } 4060fa42a0bfSXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 4061fa42a0bfSXin LI acb->firm_request_len = acb->msgcode_rwbuffer[1]; /*firm_request_len, 1, 04-07*/ 4062fa42a0bfSXin LI acb->firm_numbers_queue = acb->msgcode_rwbuffer[2]; /*firm_numbers_queue, 2, 08-11*/ 4063fa42a0bfSXin LI acb->firm_sdram_size = acb->msgcode_rwbuffer[3]; /*firm_sdram_size, 3, 12-15*/ 4064fa42a0bfSXin LI acb->firm_ide_channels = acb->msgcode_rwbuffer[4]; /*firm_ide_channels, 4, 16-19*/ 4065fa42a0bfSXin LI acb->firm_cfg_version = acb->msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]; /*firm_cfg_version, 25*/ 4066fa42a0bfSXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD) 4067fa42a0bfSXin LI acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1; 4068fa42a0bfSXin LI else 4069fa42a0bfSXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 4070fa42a0bfSXin LI } 4071fa42a0bfSXin LI /* 4072fa42a0bfSXin LI ********************************************************************** 4073fa42a0bfSXin LI ********************************************************************** 4074fa42a0bfSXin LI */ 407544f05562SScott Long static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) 407644f05562SScott Long { 407744f05562SScott Long switch (acb->adapter_type) { 4078fa42a0bfSXin LI case ACB_ADAPTER_TYPE_A: 407944f05562SScott Long arcmsr_get_hba_config(acb); 408044f05562SScott Long break; 4081fa42a0bfSXin LI case ACB_ADAPTER_TYPE_B: 408244f05562SScott Long arcmsr_get_hbb_config(acb); 408344f05562SScott Long break; 4084fa42a0bfSXin LI case ACB_ADAPTER_TYPE_C: 4085d74001adSXin LI arcmsr_get_hbc_config(acb); 4086d74001adSXin LI break; 4087fa42a0bfSXin LI case ACB_ADAPTER_TYPE_D: 40887a7bc959SXin LI arcmsr_get_hbd_config(acb); 40897a7bc959SXin LI break; 4090fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 4091a1103e04SXin LI arcmsr_get_hbe_config(acb); 4092fa42a0bfSXin LI break; 4093fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 4094fa42a0bfSXin LI arcmsr_get_hbf_config(acb); 4095a1103e04SXin LI break; 409644f05562SScott Long } 409744f05562SScott Long } 409844f05562SScott Long /* 409944f05562SScott Long ********************************************************************** 410044f05562SScott Long ********************************************************************** 410144f05562SScott Long */ 410244f05562SScott Long static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb) 410344f05562SScott Long { 410444f05562SScott Long int timeout=0; 410544f05562SScott Long 410644f05562SScott Long switch (acb->adapter_type) { 410744f05562SScott Long case ACB_ADAPTER_TYPE_A: { 4108d74001adSXin LI while ((CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) 410944f05562SScott Long { 411044f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 411144f05562SScott Long { 4112d74001adSXin LI printf( "arcmsr%d:timed out waiting for firmware \n", acb->pci_unit); 411344f05562SScott Long return; 411444f05562SScott Long } 411544f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 411644f05562SScott Long } 411744f05562SScott Long } 411844f05562SScott Long break; 411944f05562SScott Long case ACB_ADAPTER_TYPE_B: { 4120b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 4121b23a1998SXin LI while ((READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & ARCMSR_MESSAGE_FIRMWARE_OK) == 0) 412244f05562SScott Long { 412344f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 412444f05562SScott Long { 4125d74001adSXin LI printf( "arcmsr%d: timed out waiting for firmware \n", acb->pci_unit); 412644f05562SScott Long return; 412744f05562SScott Long } 412844f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 412944f05562SScott Long } 4130b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 4131d74001adSXin LI } 4132d74001adSXin LI break; 4133d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 4134d74001adSXin LI while ((CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0) 4135d74001adSXin LI { 4136d74001adSXin LI if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 4137d74001adSXin LI { 4138d74001adSXin LI printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit); 4139d74001adSXin LI return; 4140d74001adSXin LI } 4141d74001adSXin LI UDELAY(15000); /* wait 15 milli-seconds */ 4142d74001adSXin LI } 414344f05562SScott Long } 414444f05562SScott Long break; 41457a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 41467a7bc959SXin LI while ((CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBDMU_MESSAGE_FIRMWARE_OK) == 0) 41477a7bc959SXin LI { 41487a7bc959SXin LI if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 41497a7bc959SXin LI { 41507a7bc959SXin LI printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit); 41517a7bc959SXin LI return; 41527a7bc959SXin LI } 41537a7bc959SXin LI UDELAY(15000); /* wait 15 milli-seconds */ 41547a7bc959SXin LI } 41557a7bc959SXin LI } 41567a7bc959SXin LI break; 4157fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 4158fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 4159a1103e04SXin LI while ((CHIP_REG_READ32(HBE_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBEMU_MESSAGE_FIRMWARE_OK) == 0) 4160a1103e04SXin LI { 4161a1103e04SXin LI if (timeout++ > 4000) /* (4000*15)/1000 = 60 sec */ 4162a1103e04SXin LI { 4163a1103e04SXin LI printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit); 4164a1103e04SXin LI return; 4165a1103e04SXin LI } 4166a1103e04SXin LI UDELAY(15000); /* wait 15 milli-seconds */ 4167a1103e04SXin LI } 4168a1103e04SXin LI } 4169a1103e04SXin LI break; 417044f05562SScott Long } 417144f05562SScott Long } 417244f05562SScott Long /* 417344f05562SScott Long ********************************************************************** 417444f05562SScott Long ********************************************************************** 417544f05562SScott Long */ 417644f05562SScott Long static void arcmsr_clear_doorbell_queue_buffer( struct AdapterControlBlock *acb) 417744f05562SScott Long { 4178d74001adSXin LI u_int32_t outbound_doorbell; 4179d74001adSXin LI 418044f05562SScott Long switch (acb->adapter_type) { 418144f05562SScott Long case ACB_ADAPTER_TYPE_A: { 418244f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 4183d74001adSXin LI outbound_doorbell = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell); 4184d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, outbound_doorbell); /*clear doorbell interrupt */ 4185d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 418644f05562SScott Long } 418744f05562SScott Long break; 418844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 4189b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 4190fc5ef1caSXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN);/*clear interrupt and message state*/ 4191b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 419244f05562SScott Long /* let IOP know data has been read */ 419344f05562SScott Long } 419444f05562SScott Long break; 4195d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 4196d74001adSXin LI /* empty doorbell Qbuffer if door bell ringed */ 4197d74001adSXin LI outbound_doorbell = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); 4198d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell); /*clear doorbell interrupt */ 4199d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK); 42007a7bc959SXin LI CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell_clear); /* Dummy read to force pci flush */ 42017a7bc959SXin LI CHIP_REG_READ32(HBC_MessageUnit, 0, inbound_doorbell); /* Dummy read to force pci flush */ 42027a7bc959SXin LI } 42037a7bc959SXin LI break; 42047a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 42057a7bc959SXin LI /* empty doorbell Qbuffer if door bell ringed */ 42067a7bc959SXin LI outbound_doorbell = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell); 42077a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, outbound_doorbell); /*clear doorbell interrupt */ 42087a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ); 4209d74001adSXin LI } 4210d74001adSXin LI break; 4211fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 4212fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 4213a1103e04SXin LI /* empty doorbell Qbuffer if door bell ringed */ 4214a1103e04SXin LI acb->in_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell); 4215a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /*clear doorbell interrupt */ 4216a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK; 4217a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 4218a1103e04SXin LI } 4219a1103e04SXin LI break; 422044f05562SScott Long } 422144f05562SScott Long } 422244f05562SScott Long /* 422344f05562SScott Long ************************************************************************ 422444f05562SScott Long ************************************************************************ 422544f05562SScott Long */ 422644f05562SScott Long static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb) 422744f05562SScott Long { 422844f05562SScott Long unsigned long srb_phyaddr; 422944f05562SScott Long u_int32_t srb_phyaddr_hi32; 42307a7bc959SXin LI u_int32_t srb_phyaddr_lo32; 423144f05562SScott Long 423244f05562SScott Long /* 423344f05562SScott Long ******************************************************************** 423444f05562SScott Long ** here we need to tell iop 331 our freesrb.HighPart 423544f05562SScott Long ** if freesrb.HighPart is not zero 423644f05562SScott Long ******************************************************************** 423744f05562SScott Long */ 4238d74001adSXin LI srb_phyaddr = (unsigned long) acb->srb_phyaddr.phyaddr; 4239d74001adSXin LI srb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high; 42407a7bc959SXin LI srb_phyaddr_lo32 = acb->srb_phyaddr.B.phyadd_low; 424144f05562SScott Long switch (acb->adapter_type) { 424244f05562SScott Long case ACB_ADAPTER_TYPE_A: { 424344f05562SScott Long if(srb_phyaddr_hi32 != 0) { 4244d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 4245d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 4246d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 424744f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 4248d74001adSXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 424944f05562SScott Long return FALSE; 425044f05562SScott Long } 425144f05562SScott Long } 425244f05562SScott Long } 425344f05562SScott Long break; 425444f05562SScott Long /* 425544f05562SScott Long *********************************************************************** 425644f05562SScott Long ** if adapter type B, set window of "post command Q" 425744f05562SScott Long *********************************************************************** 425844f05562SScott Long */ 425944f05562SScott Long case ACB_ADAPTER_TYPE_B: { 426044f05562SScott Long u_int32_t post_queue_phyaddr; 426144f05562SScott Long struct HBB_MessageUnit *phbbmu; 426244f05562SScott Long 426344f05562SScott Long phbbmu = (struct HBB_MessageUnit *)acb->pmu; 426444f05562SScott Long phbbmu->postq_index = 0; 426544f05562SScott Long phbbmu->doneq_index = 0; 4266b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_SET_POST_WINDOW); 426744f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 4268d74001adSXin LI printf( "arcmsr%d: 'set window of post command Q' timeout\n", acb->pci_unit); 426944f05562SScott Long return FALSE; 427044f05562SScott Long } 427122f2616bSXin LI post_queue_phyaddr = srb_phyaddr + ARCMSR_SRBS_POOL_SIZE 427244f05562SScott Long + offsetof(struct HBB_MessageUnit, post_qbuffer); 4273d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */ 4274d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1], srb_phyaddr_hi32); /* normal should be zero */ 4275d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ size (256+8)*4 */ 4276d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3], post_queue_phyaddr+1056); /* doneQ size (256+8)*4 */ 4277d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4], 1056); /* srb maxQ size must be --> [(256+8)*4] */ 4278b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_SET_CONFIG); 427944f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 428044f05562SScott Long printf( "arcmsr%d: 'set command Q window' timeout \n", acb->pci_unit); 428144f05562SScott Long return FALSE; 428244f05562SScott Long } 4283b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_START_DRIVER_MODE); 428444f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 428544f05562SScott Long printf( "arcmsr%d: 'start diver mode' timeout \n", acb->pci_unit); 428644f05562SScott Long return FALSE; 428744f05562SScott Long } 428844f05562SScott Long } 428944f05562SScott Long break; 4290d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 4291d74001adSXin LI if(srb_phyaddr_hi32 != 0) { 4292d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 4293d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 4294d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 4295d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 4296d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 4297d74001adSXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 4298d74001adSXin LI return FALSE; 4299d74001adSXin LI } 4300d74001adSXin LI } 4301d74001adSXin LI } 4302d74001adSXin LI break; 43037a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 43047a7bc959SXin LI u_int32_t post_queue_phyaddr, done_queue_phyaddr; 43057a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu; 43067a7bc959SXin LI 43077a7bc959SXin LI phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 43087a7bc959SXin LI phbdmu->postq_index = 0; 43097a7bc959SXin LI phbdmu->doneq_index = 0x40FF; 43107a7bc959SXin LI post_queue_phyaddr = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE 43117a7bc959SXin LI + offsetof(struct HBD_MessageUnit0, post_qbuffer); 43127a7bc959SXin LI done_queue_phyaddr = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE 43137a7bc959SXin LI + offsetof(struct HBD_MessageUnit0, done_qbuffer); 43147a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */ 43157a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 43167a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ base */ 43177a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[3], done_queue_phyaddr); /* doneQ base */ 43187a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[4], 0x100); 43197a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 43207a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 43217a7bc959SXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 43227a7bc959SXin LI return FALSE; 43237a7bc959SXin LI } 43247a7bc959SXin LI } 43257a7bc959SXin LI break; 4326a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 4327a1103e04SXin LI u_int32_t cdb_phyaddr_lo32; 4328a1103e04SXin LI cdb_phyaddr_lo32 = srb_phyaddr_lo32 + offsetof(struct CommandControlBlock, arcmsr_cdb); 4329a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 4330a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[1], ARCMSR_SIGNATURE_1884); 4331a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[2], cdb_phyaddr_lo32); 4332a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[3], srb_phyaddr_hi32); 4333a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[4], SRB_SIZE); 4334a1103e04SXin LI cdb_phyaddr_lo32 = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE; 4335a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[5], cdb_phyaddr_lo32); 4336a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[6], srb_phyaddr_hi32); 4337a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[7], COMPLETION_Q_POOL_SIZE); 4338a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 4339a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 4340a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 4341a1103e04SXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) { 4342a1103e04SXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 4343a1103e04SXin LI return FALSE; 4344a1103e04SXin LI } 4345a1103e04SXin LI } 4346a1103e04SXin LI break; 4347fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 4348fa42a0bfSXin LI u_int32_t cdb_phyaddr_lo32; 4349fa42a0bfSXin LI cdb_phyaddr_lo32 = srb_phyaddr_lo32 + offsetof(struct CommandControlBlock, arcmsr_cdb); 4350fa42a0bfSXin LI acb->msgcode_rwbuffer[0] = ARCMSR_SIGNATURE_SET_CONFIG; 4351fa42a0bfSXin LI acb->msgcode_rwbuffer[1] = ARCMSR_SIGNATURE_1886; 4352fa42a0bfSXin LI acb->msgcode_rwbuffer[2] = cdb_phyaddr_lo32; 4353fa42a0bfSXin LI acb->msgcode_rwbuffer[3] = srb_phyaddr_hi32; 4354fa42a0bfSXin LI acb->msgcode_rwbuffer[4] = SRB_SIZE; 4355fa42a0bfSXin LI cdb_phyaddr_lo32 = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE; 4356fa42a0bfSXin LI acb->msgcode_rwbuffer[5] = cdb_phyaddr_lo32; 4357fa42a0bfSXin LI acb->msgcode_rwbuffer[6] = srb_phyaddr_hi32; 4358fa42a0bfSXin LI acb->msgcode_rwbuffer[7] = COMPLETION_Q_POOL_SIZE; 4359fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 4360fa42a0bfSXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 4361fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 4362fa42a0bfSXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) { 4363fa42a0bfSXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 4364fa42a0bfSXin LI return FALSE; 4365fa42a0bfSXin LI } 4366fa42a0bfSXin LI } 4367fa42a0bfSXin LI break; 436844f05562SScott Long } 4369dac36688SXin LI return (TRUE); 437044f05562SScott Long } 437144f05562SScott Long /* 437244f05562SScott Long ************************************************************************ 437344f05562SScott Long ************************************************************************ 437444f05562SScott Long */ 437544f05562SScott Long static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb) 437644f05562SScott Long { 4377a1103e04SXin LI if (acb->adapter_type == ACB_ADAPTER_TYPE_B) 437844f05562SScott Long { 4379b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 4380b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_ACTIVE_EOI_MODE); 438144f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 4382d74001adSXin LI printf( "arcmsr%d: 'iop enable eoi mode' timeout \n", acb->pci_unit); 438344f05562SScott Long return; 438444f05562SScott Long } 438544f05562SScott Long } 438644f05562SScott Long } 438744f05562SScott Long /* 438844f05562SScott Long ********************************************************************** 4389ad6d6297SScott Long ********************************************************************** 4390ad6d6297SScott Long */ 4391ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb) 4392ad6d6297SScott Long { 439344f05562SScott Long u_int32_t intmask_org; 4394ad6d6297SScott Long 439544f05562SScott Long /* disable all outbound interrupt */ 439644f05562SScott Long intmask_org = arcmsr_disable_allintr(acb); 439744f05562SScott Long arcmsr_wait_firmware_ready(acb); 439844f05562SScott Long arcmsr_iop_confirm(acb); 4399ad6d6297SScott Long arcmsr_get_firmware_spec(acb); 440044f05562SScott Long /*start background rebuild*/ 4401ad6d6297SScott Long arcmsr_start_adapter_bgrb(acb); 440244f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 440344f05562SScott Long arcmsr_clear_doorbell_queue_buffer(acb); 440444f05562SScott Long arcmsr_enable_eoi_mode(acb); 440544f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 440644f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 4407ad6d6297SScott Long acb->acb_flags |= ACB_F_IOP_INITED; 4408ad6d6297SScott Long } 4409ad6d6297SScott Long /* 4410ad6d6297SScott Long ********************************************************************** 4411f1c579b1SScott Long ********************************************************************** 4412f1c579b1SScott Long */ 4413231c8b71SXin LI static void arcmsr_map_free_srb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 4414f1c579b1SScott Long { 4415ad6d6297SScott Long struct AdapterControlBlock *acb = arg; 4416ad6d6297SScott Long struct CommandControlBlock *srb_tmp; 441744f05562SScott Long u_int32_t i; 4418ad6d6297SScott Long unsigned long srb_phyaddr = (unsigned long)segs->ds_addr; 4419f1c579b1SScott Long 4420d74001adSXin LI acb->srb_phyaddr.phyaddr = srb_phyaddr; 44217a7bc959SXin LI srb_tmp = (struct CommandControlBlock *)acb->uncacheptr; 4422ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 442344f05562SScott Long if(bus_dmamap_create(acb->dm_segs_dmat, 442444f05562SScott Long /*flags*/0, &srb_tmp->dm_segs_dmamap) != 0) { 4425ad6d6297SScott Long acb->acb_flags |= ACB_F_MAPFREESRB_FAILD; 442644f05562SScott Long printf("arcmsr%d:" 442744f05562SScott Long " srb dmamap bus_dmamap_create error\n", acb->pci_unit); 4428ad6d6297SScott Long return; 4429ad6d6297SScott Long } 4430a1103e04SXin LI if((acb->adapter_type == ACB_ADAPTER_TYPE_C) || (acb->adapter_type == ACB_ADAPTER_TYPE_D) 4431fa42a0bfSXin LI || (acb->adapter_type == ACB_ADAPTER_TYPE_E) || (acb->adapter_type == ACB_ADAPTER_TYPE_F)) 44327a7bc959SXin LI { 44337a7bc959SXin LI srb_tmp->cdb_phyaddr_low = srb_phyaddr; 44347a7bc959SXin LI srb_tmp->cdb_phyaddr_high = (u_int32_t)((srb_phyaddr >> 16) >> 16); 44357a7bc959SXin LI } 44367a7bc959SXin LI else 44377a7bc959SXin LI srb_tmp->cdb_phyaddr_low = srb_phyaddr >> 5; 4438ad6d6297SScott Long srb_tmp->acb = acb; 4439a1103e04SXin LI srb_tmp->smid = i << 16; 4440ad6d6297SScott Long acb->srbworkingQ[i] = acb->psrb_pool[i] = srb_tmp; 444122f2616bSXin LI srb_phyaddr = srb_phyaddr + SRB_SIZE; 444222f2616bSXin LI srb_tmp = (struct CommandControlBlock *)((unsigned long)srb_tmp + SRB_SIZE); 4443ad6d6297SScott Long } 4444fc5ef1caSXin LI if (acb->adapter_type == ACB_ADAPTER_TYPE_E) 4445a1103e04SXin LI acb->pCompletionQ = (pCompletion_Q)srb_tmp; 4446fa42a0bfSXin LI else if (acb->adapter_type == ACB_ADAPTER_TYPE_F) { 4447fa42a0bfSXin LI acb->pCompletionQ = (pCompletion_Q)srb_tmp; 4448fa42a0bfSXin LI acb->completeQ_phys = srb_phyaddr; 4449fa42a0bfSXin LI memset(acb->pCompletionQ, 0xff, COMPLETION_Q_POOL_SIZE); 4450fa42a0bfSXin LI acb->message_wbuffer = (u_int32_t *)((unsigned long)acb->pCompletionQ + COMPLETION_Q_POOL_SIZE); 4451fa42a0bfSXin LI acb->message_rbuffer = (u_int32_t *)((unsigned long)acb->message_wbuffer + 0x100); 4452fa42a0bfSXin LI acb->msgcode_rwbuffer = (u_int32_t *)((unsigned long)acb->message_wbuffer + 0x200); 4453fa42a0bfSXin LI memset((void *)acb->message_wbuffer, 0, MESG_RW_BUFFER_SIZE); 4454fa42a0bfSXin LI } 4455ad6d6297SScott Long acb->vir2phy_offset = (unsigned long)srb_tmp - (unsigned long)srb_phyaddr; 4456f1c579b1SScott Long } 4457f1c579b1SScott Long /* 4458f1c579b1SScott Long ************************************************************************ 4459f1c579b1SScott Long ************************************************************************ 4460f1c579b1SScott Long */ 4461ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb) 4462f1c579b1SScott Long { 4463f1c579b1SScott Long /* remove the control device */ 4464ad6d6297SScott Long if(acb->ioctl_dev != NULL) { 4465ad6d6297SScott Long destroy_dev(acb->ioctl_dev); 4466f1c579b1SScott Long } 4467ad6d6297SScott Long bus_dmamap_unload(acb->srb_dmat, acb->srb_dmamap); 4468ad6d6297SScott Long bus_dmamap_destroy(acb->srb_dmat, acb->srb_dmamap); 4469ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 4470ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 4471ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 4472f1c579b1SScott Long } 4473f1c579b1SScott Long /* 4474f1c579b1SScott Long ************************************************************************ 4475f1c579b1SScott Long ************************************************************************ 4476f1c579b1SScott Long */ 44777a7bc959SXin LI static void arcmsr_mutex_init(struct AdapterControlBlock *acb) 44787a7bc959SXin LI { 44797a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->isr_lock, "arcmsr isr lock"); 44807a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->srb_lock, "arcmsr srb lock"); 44817a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->postDone_lock, "arcmsr postQ lock"); 44827a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->qbuffer_lock, "arcmsr RW buffer lock"); 44837a7bc959SXin LI } 44847a7bc959SXin LI /* 44857a7bc959SXin LI ************************************************************************ 44867a7bc959SXin LI ************************************************************************ 44877a7bc959SXin LI */ 44887a7bc959SXin LI static void arcmsr_mutex_destroy(struct AdapterControlBlock *acb) 44897a7bc959SXin LI { 44907a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 44917a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->postDone_lock); 44927a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->srb_lock); 44937a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->isr_lock); 44947a7bc959SXin LI } 44957a7bc959SXin LI /* 44967a7bc959SXin LI ************************************************************************ 44977a7bc959SXin LI ************************************************************************ 44987a7bc959SXin LI */ 4499ad6d6297SScott Long static u_int32_t arcmsr_initialize(device_t dev) 4500f1c579b1SScott Long { 4501ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 4502ad6d6297SScott Long u_int16_t pci_command; 450344f05562SScott Long int i, j,max_coherent_size; 4504dac36688SXin LI u_int32_t vendor_dev_id; 4505f1c579b1SScott Long 4506dac36688SXin LI vendor_dev_id = pci_get_devid(dev); 4507dac36688SXin LI acb->vendor_device_id = vendor_dev_id; 4508224a78aeSXin LI acb->sub_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2); 4509dac36688SXin LI switch (vendor_dev_id) { 4510dac36688SXin LI case PCIDevVenIDARC1880: 4511dac36688SXin LI case PCIDevVenIDARC1882: 4512dac36688SXin LI case PCIDevVenIDARC1213: 4513dac36688SXin LI case PCIDevVenIDARC1223: { 4514d74001adSXin LI acb->adapter_type = ACB_ADAPTER_TYPE_C; 4515fc5ef1caSXin LI if ((acb->sub_device_id == ARECA_SUB_DEV_ID_1883) || 4516fc5ef1caSXin LI (acb->sub_device_id == ARECA_SUB_DEV_ID_1216) || 4517fc5ef1caSXin LI (acb->sub_device_id == ARECA_SUB_DEV_ID_1226)) 4518224a78aeSXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_12G; 4519224a78aeSXin LI else 4520dac36688SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_6G; 4521d74001adSXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE; 4522d74001adSXin LI } 4523d74001adSXin LI break; 4524a1103e04SXin LI case PCIDevVenIDARC1884: 4525a1103e04SXin LI acb->adapter_type = ACB_ADAPTER_TYPE_E; 4526a1103e04SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_12G; 4527a1103e04SXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + COMPLETION_Q_POOL_SIZE; 4528a1103e04SXin LI acb->completionQ_entry = COMPLETION_Q_POOL_SIZE / sizeof(struct deliver_completeQ); 4529a1103e04SXin LI break; 4530fa42a0bfSXin LI case PCIDevVenIDARC1886_: 4531fa42a0bfSXin LI case PCIDevVenIDARC1886: 4532fa42a0bfSXin LI acb->adapter_type = ACB_ADAPTER_TYPE_F; 4533fa42a0bfSXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_12G; 4534fa42a0bfSXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + COMPLETION_Q_POOL_SIZE + MESG_RW_BUFFER_SIZE; 4535fa42a0bfSXin LI acb->completionQ_entry = COMPLETION_Q_POOL_SIZE / sizeof(struct deliver_completeQ); 4536fa42a0bfSXin LI break; 45377a7bc959SXin LI case PCIDevVenIDARC1214: { 45387a7bc959SXin LI acb->adapter_type = ACB_ADAPTER_TYPE_D; 45397a7bc959SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_6G; 45407a7bc959SXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBD_MessageUnit0)); 45417a7bc959SXin LI } 45427a7bc959SXin LI break; 4543231c8b71SXin LI case PCIDevVenIDARC1200: 454444f05562SScott Long case PCIDevVenIDARC1201: { 454544f05562SScott Long acb->adapter_type = ACB_ADAPTER_TYPE_B; 4546dac36688SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_3G; 4547d74001adSXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBB_MessageUnit)); 454844f05562SScott Long } 454944f05562SScott Long break; 4550b23a1998SXin LI case PCIDevVenIDARC1203: { 4551b23a1998SXin LI acb->adapter_type = ACB_ADAPTER_TYPE_B; 4552b23a1998SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_6G; 4553b23a1998SXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBB_MessageUnit)); 4554b23a1998SXin LI } 4555b23a1998SXin LI break; 455644f05562SScott Long case PCIDevVenIDARC1110: 455744f05562SScott Long case PCIDevVenIDARC1120: 455844f05562SScott Long case PCIDevVenIDARC1130: 455944f05562SScott Long case PCIDevVenIDARC1160: 456044f05562SScott Long case PCIDevVenIDARC1170: 456144f05562SScott Long case PCIDevVenIDARC1210: 456244f05562SScott Long case PCIDevVenIDARC1220: 456344f05562SScott Long case PCIDevVenIDARC1230: 4564231c8b71SXin LI case PCIDevVenIDARC1231: 456544f05562SScott Long case PCIDevVenIDARC1260: 4566231c8b71SXin LI case PCIDevVenIDARC1261: 456744f05562SScott Long case PCIDevVenIDARC1270: 456844f05562SScott Long case PCIDevVenIDARC1280: 4569d74001adSXin LI case PCIDevVenIDARC1212: 4570d74001adSXin LI case PCIDevVenIDARC1222: 457144f05562SScott Long case PCIDevVenIDARC1380: 457244f05562SScott Long case PCIDevVenIDARC1381: 457344f05562SScott Long case PCIDevVenIDARC1680: 457444f05562SScott Long case PCIDevVenIDARC1681: { 457544f05562SScott Long acb->adapter_type = ACB_ADAPTER_TYPE_A; 4576dac36688SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_3G; 457744f05562SScott Long max_coherent_size = ARCMSR_SRBS_POOL_SIZE; 457844f05562SScott Long } 457944f05562SScott Long break; 458044f05562SScott Long default: { 458144f05562SScott Long printf("arcmsr%d:" 458244f05562SScott Long " unknown RAID adapter type \n", device_get_unit(dev)); 458344f05562SScott Long return ENOMEM; 458444f05562SScott Long } 458544f05562SScott Long } 4586b6f97155SScott Long if(bus_dma_tag_create( /*PCI parent*/ bus_get_dma_tag(dev), 4587f1c579b1SScott Long /*alignemnt*/ 1, 4588f1c579b1SScott Long /*boundary*/ 0, 4589701d9f1fSScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 4590f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 4591f1c579b1SScott Long /*filter*/ NULL, 4592f1c579b1SScott Long /*filterarg*/ NULL, 4593f1c579b1SScott Long /*maxsize*/ BUS_SPACE_MAXSIZE_32BIT, 4594f1c579b1SScott Long /*nsegments*/ BUS_SPACE_UNRESTRICTED, 4595f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 4596f1c579b1SScott Long /*flags*/ 0, 4597f1c579b1SScott Long /*lockfunc*/ NULL, 4598f1c579b1SScott Long /*lockarg*/ NULL, 4599231c8b71SXin LI &acb->parent_dmat) != 0) 4600f1c579b1SScott Long { 460144f05562SScott Long printf("arcmsr%d: parent_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 4602f1c579b1SScott Long return ENOMEM; 4603f1c579b1SScott Long } 4604231c8b71SXin LI 4605f1c579b1SScott Long /* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */ 4606ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 4607f1c579b1SScott Long /*alignment*/ 1, 4608f1c579b1SScott Long /*boundary*/ 0, 460922f2616bSXin LI #ifdef PAE 461022f2616bSXin LI /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 461122f2616bSXin LI #else 4612f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 461322f2616bSXin LI #endif 4614f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 4615f1c579b1SScott Long /*filter*/ NULL, 4616f1c579b1SScott Long /*filterarg*/ NULL, 4617231c8b71SXin LI /*maxsize*/ ARCMSR_MAX_SG_ENTRIES * PAGE_SIZE * ARCMSR_MAX_FREESRB_NUM, 4618f1c579b1SScott Long /*nsegments*/ ARCMSR_MAX_SG_ENTRIES, 4619f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 4620ad6d6297SScott Long /*flags*/ 0, 4621f1c579b1SScott Long /*lockfunc*/ busdma_lock_mutex, 46227a7bc959SXin LI /*lockarg*/ &acb->isr_lock, 4623231c8b71SXin LI &acb->dm_segs_dmat) != 0) 4624f1c579b1SScott Long { 4625ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 462644f05562SScott Long printf("arcmsr%d: dm_segs_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 4627f1c579b1SScott Long return ENOMEM; 4628f1c579b1SScott Long } 4629231c8b71SXin LI 4630ad6d6297SScott Long /* DMA tag for our srb structures.... Allocate the freesrb memory */ 4631ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 463244f05562SScott Long /*alignment*/ 0x20, 4633f1c579b1SScott Long /*boundary*/ 0, 4634f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 4635f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 4636f1c579b1SScott Long /*filter*/ NULL, 4637f1c579b1SScott Long /*filterarg*/ NULL, 463844f05562SScott Long /*maxsize*/ max_coherent_size, 4639f1c579b1SScott Long /*nsegments*/ 1, 4640f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 4641701d9f1fSScott Long /*flags*/ 0, 4642f1c579b1SScott Long /*lockfunc*/ NULL, 4643f1c579b1SScott Long /*lockarg*/ NULL, 4644231c8b71SXin LI &acb->srb_dmat) != 0) 4645f1c579b1SScott Long { 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_dma_tag_create failure!\n", device_get_unit(dev)); 4649f1c579b1SScott Long return ENXIO; 4650f1c579b1SScott Long } 4651f1c579b1SScott Long /* Allocation for our srbs */ 4652d74001adSXin LI if(bus_dmamem_alloc(acb->srb_dmat, (void **)&acb->uncacheptr, BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &acb->srb_dmamap) != 0) { 4653ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 4654ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 4655ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 465644f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamem_alloc failure!\n", device_get_unit(dev)); 4657f1c579b1SScott Long return ENXIO; 4658f1c579b1SScott Long } 4659f1c579b1SScott Long /* And permanently map them */ 4660231c8b71SXin LI if(bus_dmamap_load(acb->srb_dmat, acb->srb_dmamap, acb->uncacheptr, max_coherent_size, arcmsr_map_free_srb, acb, /*flags*/0)) { 4661ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 4662ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 4663ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 466444f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamap_load failure!\n", device_get_unit(dev)); 4665f1c579b1SScott Long return ENXIO; 4666f1c579b1SScott Long } 4667f1c579b1SScott Long pci_command = pci_read_config(dev, PCIR_COMMAND, 2); 4668f1c579b1SScott Long pci_command |= PCIM_CMD_BUSMASTEREN; 4669f1c579b1SScott Long pci_command |= PCIM_CMD_PERRESPEN; 4670f1c579b1SScott Long pci_command |= PCIM_CMD_MWRICEN; 4671c68534f1SScott Long /* Enable Busmaster */ 4672f1c579b1SScott Long pci_write_config(dev, PCIR_COMMAND, pci_command, 2); 467344f05562SScott Long switch(acb->adapter_type) { 467444f05562SScott Long case ACB_ADAPTER_TYPE_A: { 467544f05562SScott Long u_int32_t rid0 = PCIR_BAR(0); 467644f05562SScott Long vm_offset_t mem_base0; 467744f05562SScott Long 4678eff83876SJustin Hibbits acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid0, RF_ACTIVE); 467944f05562SScott Long if(acb->sys_res_arcmsr[0] == NULL) { 4680ad6d6297SScott Long arcmsr_free_resource(acb); 4681d74001adSXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 4682f1c579b1SScott Long return ENOMEM; 4683f1c579b1SScott Long } 468444f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 4685ad6d6297SScott Long arcmsr_free_resource(acb); 4686d74001adSXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 4687f1c579b1SScott Long return ENXIO; 4688f1c579b1SScott Long } 468944f05562SScott Long mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 469044f05562SScott Long if(mem_base0 == 0) { 4691ad6d6297SScott Long arcmsr_free_resource(acb); 4692d74001adSXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 4693f1c579b1SScott Long return ENXIO; 4694f1c579b1SScott Long } 469544f05562SScott Long acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 469644f05562SScott Long acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 469744f05562SScott Long acb->pmu = (struct MessageUnit_UNION *)mem_base0; 4698fc5ef1caSXin LI acb->rid[0] = rid0; 469944f05562SScott Long } 470044f05562SScott Long break; 470144f05562SScott Long case ACB_ADAPTER_TYPE_B: { 470244f05562SScott Long struct HBB_MessageUnit *phbbmu; 470344f05562SScott Long struct CommandControlBlock *freesrb; 470444f05562SScott Long u_int32_t rid[]={ PCIR_BAR(0), PCIR_BAR(2) }; 470544f05562SScott Long vm_offset_t mem_base[]={0,0}; 470644f05562SScott Long for(i=0; i < 2; i++) { 4707fc5ef1caSXin LI acb->sys_res_arcmsr[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid[i], RF_ACTIVE); 470844f05562SScott Long if(acb->sys_res_arcmsr[i] == NULL) { 470944f05562SScott Long arcmsr_free_resource(acb); 4710d74001adSXin LI printf("arcmsr%d: bus_alloc_resource %d failure!\n", device_get_unit(dev), i); 471144f05562SScott Long return ENOMEM; 471244f05562SScott Long } 471344f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[i]) <= 0) { 471444f05562SScott Long arcmsr_free_resource(acb); 4715d74001adSXin LI printf("arcmsr%d: rman_get_start %d failure!\n", device_get_unit(dev), i); 471644f05562SScott Long return ENXIO; 471744f05562SScott Long } 471844f05562SScott Long mem_base[i] = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[i]); 471944f05562SScott Long if(mem_base[i] == 0) { 472044f05562SScott Long arcmsr_free_resource(acb); 4721d74001adSXin LI printf("arcmsr%d: rman_get_virtual %d failure!\n", device_get_unit(dev), i); 472244f05562SScott Long return ENXIO; 472344f05562SScott Long } 472444f05562SScott Long acb->btag[i] = rman_get_bustag(acb->sys_res_arcmsr[i]); 472544f05562SScott Long acb->bhandle[i] = rman_get_bushandle(acb->sys_res_arcmsr[i]); 472644f05562SScott Long } 472744f05562SScott Long freesrb = (struct CommandControlBlock *)acb->uncacheptr; 472822f2616bSXin LI acb->pmu = (struct MessageUnit_UNION *)((unsigned long)freesrb+ARCMSR_SRBS_POOL_SIZE); 472944f05562SScott Long phbbmu = (struct HBB_MessageUnit *)acb->pmu; 473044f05562SScott Long phbbmu->hbb_doorbell = (struct HBB_DOORBELL *)mem_base[0]; 473144f05562SScott Long phbbmu->hbb_rwbuffer = (struct HBB_RWBUFFER *)mem_base[1]; 4732b23a1998SXin LI if (vendor_dev_id == PCIDevVenIDARC1203) { 4733b23a1998SXin LI phbbmu->drv2iop_doorbell = offsetof(struct HBB_DOORBELL_1203, drv2iop_doorbell); 4734b23a1998SXin LI phbbmu->drv2iop_doorbell_mask = offsetof(struct HBB_DOORBELL_1203, drv2iop_doorbell_mask); 4735b23a1998SXin LI phbbmu->iop2drv_doorbell = offsetof(struct HBB_DOORBELL_1203, iop2drv_doorbell); 4736b23a1998SXin LI phbbmu->iop2drv_doorbell_mask = offsetof(struct HBB_DOORBELL_1203, iop2drv_doorbell_mask); 4737b23a1998SXin LI } else { 4738b23a1998SXin LI phbbmu->drv2iop_doorbell = offsetof(struct HBB_DOORBELL, drv2iop_doorbell); 4739b23a1998SXin LI phbbmu->drv2iop_doorbell_mask = offsetof(struct HBB_DOORBELL, drv2iop_doorbell_mask); 4740b23a1998SXin LI phbbmu->iop2drv_doorbell = offsetof(struct HBB_DOORBELL, iop2drv_doorbell); 4741b23a1998SXin LI phbbmu->iop2drv_doorbell_mask = offsetof(struct HBB_DOORBELL, iop2drv_doorbell_mask); 4742b23a1998SXin LI } 4743fc5ef1caSXin LI acb->rid[0] = rid[0]; 4744fc5ef1caSXin LI acb->rid[1] = rid[1]; 474544f05562SScott Long } 474644f05562SScott Long break; 4747d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 4748d74001adSXin LI u_int32_t rid0 = PCIR_BAR(1); 4749d74001adSXin LI vm_offset_t mem_base0; 4750d74001adSXin LI 4751eff83876SJustin Hibbits acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid0, RF_ACTIVE); 4752d74001adSXin LI if(acb->sys_res_arcmsr[0] == NULL) { 4753d74001adSXin LI arcmsr_free_resource(acb); 4754d74001adSXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 4755d74001adSXin LI return ENOMEM; 4756d74001adSXin LI } 4757d74001adSXin LI if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 4758d74001adSXin LI arcmsr_free_resource(acb); 4759d74001adSXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 4760d74001adSXin LI return ENXIO; 4761d74001adSXin LI } 4762d74001adSXin LI mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 4763d74001adSXin LI if(mem_base0 == 0) { 4764d74001adSXin LI arcmsr_free_resource(acb); 4765d74001adSXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 4766d74001adSXin LI return ENXIO; 4767d74001adSXin LI } 4768d74001adSXin LI acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 4769d74001adSXin LI acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 4770d74001adSXin LI acb->pmu = (struct MessageUnit_UNION *)mem_base0; 4771fc5ef1caSXin LI acb->rid[0] = rid0; 4772d74001adSXin LI } 4773d74001adSXin LI break; 47747a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 47757a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu; 47767a7bc959SXin LI u_int32_t rid0 = PCIR_BAR(0); 47777a7bc959SXin LI vm_offset_t mem_base0; 47787a7bc959SXin LI 4779eff83876SJustin Hibbits acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid0, RF_ACTIVE); 47807a7bc959SXin LI if(acb->sys_res_arcmsr[0] == NULL) { 47817a7bc959SXin LI arcmsr_free_resource(acb); 47827a7bc959SXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 47837a7bc959SXin LI return ENOMEM; 47847a7bc959SXin LI } 47857a7bc959SXin LI if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 47867a7bc959SXin LI arcmsr_free_resource(acb); 47877a7bc959SXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 47887a7bc959SXin LI return ENXIO; 47897a7bc959SXin LI } 47907a7bc959SXin LI mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 47917a7bc959SXin LI if(mem_base0 == 0) { 47927a7bc959SXin LI arcmsr_free_resource(acb); 47937a7bc959SXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 47947a7bc959SXin LI return ENXIO; 47957a7bc959SXin LI } 47967a7bc959SXin LI acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 47977a7bc959SXin LI acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 47987a7bc959SXin LI acb->pmu = (struct MessageUnit_UNION *)((unsigned long)acb->uncacheptr+ARCMSR_SRBS_POOL_SIZE); 47997a7bc959SXin LI phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 48007a7bc959SXin LI phbdmu->phbdmu = (struct HBD_MessageUnit *)mem_base0; 4801fc5ef1caSXin LI acb->rid[0] = rid0; 4802a1103e04SXin LI } 4803a1103e04SXin LI break; 4804a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 4805a1103e04SXin LI u_int32_t rid0 = PCIR_BAR(1); 4806a1103e04SXin LI vm_offset_t mem_base0; 4807a1103e04SXin LI 4808fc5ef1caSXin LI acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid0, RF_ACTIVE); 4809a1103e04SXin LI if(acb->sys_res_arcmsr[0] == NULL) { 4810a1103e04SXin LI arcmsr_free_resource(acb); 4811a1103e04SXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 4812a1103e04SXin LI return ENOMEM; 4813a1103e04SXin LI } 4814a1103e04SXin LI if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 4815a1103e04SXin LI arcmsr_free_resource(acb); 4816a1103e04SXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 4817a1103e04SXin LI return ENXIO; 4818a1103e04SXin LI } 4819a1103e04SXin LI mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 4820a1103e04SXin LI if(mem_base0 == 0) { 4821a1103e04SXin LI arcmsr_free_resource(acb); 4822a1103e04SXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 4823a1103e04SXin LI return ENXIO; 4824a1103e04SXin LI } 4825a1103e04SXin LI acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 4826a1103e04SXin LI acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 4827a1103e04SXin LI acb->pmu = (struct MessageUnit_UNION *)mem_base0; 4828a1103e04SXin LI acb->doneq_index = 0; 4829a1103e04SXin LI acb->in_doorbell = 0; 4830a1103e04SXin LI acb->out_doorbell = 0; 4831fc5ef1caSXin LI acb->rid[0] = rid0; 4832a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /*clear interrupt*/ 4833a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, ARCMSR_HBEMU_DOORBELL_SYNC); /* synchronize doorbell to 0 */ 48347a7bc959SXin LI } 48357a7bc959SXin LI break; 4836fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 4837fa42a0bfSXin LI u_int32_t rid0 = PCIR_BAR(0); 4838fa42a0bfSXin LI vm_offset_t mem_base0; 4839fa42a0bfSXin LI unsigned long host_buffer_dma; 4840fa42a0bfSXin LI 4841fa42a0bfSXin LI acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid0, RF_ACTIVE); 4842fa42a0bfSXin LI if(acb->sys_res_arcmsr[0] == NULL) { 4843fa42a0bfSXin LI arcmsr_free_resource(acb); 4844fa42a0bfSXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 4845fa42a0bfSXin LI return ENOMEM; 4846fa42a0bfSXin LI } 4847fa42a0bfSXin LI if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 4848fa42a0bfSXin LI arcmsr_free_resource(acb); 4849fa42a0bfSXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 4850fa42a0bfSXin LI return ENXIO; 4851fa42a0bfSXin LI } 4852fa42a0bfSXin LI mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 4853fa42a0bfSXin LI if(mem_base0 == 0) { 4854fa42a0bfSXin LI arcmsr_free_resource(acb); 4855fa42a0bfSXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 4856fa42a0bfSXin LI return ENXIO; 4857fa42a0bfSXin LI } 4858fa42a0bfSXin LI acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 4859fa42a0bfSXin LI acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 4860fa42a0bfSXin LI acb->pmu = (struct MessageUnit_UNION *)mem_base0; 4861fa42a0bfSXin LI acb->doneq_index = 0; 4862fa42a0bfSXin LI acb->in_doorbell = 0; 4863fa42a0bfSXin LI acb->out_doorbell = 0; 4864fa42a0bfSXin LI acb->rid[0] = rid0; 4865fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, host_int_status, 0); /*clear interrupt*/ 4866fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, iobound_doorbell, ARCMSR_HBEMU_DOORBELL_SYNC); /* synchronize doorbell to 0 */ 4867*6964b77eS黃清隆 arcmsr_wait_firmware_ready(acb); 4868fa42a0bfSXin LI host_buffer_dma = acb->completeQ_phys + COMPLETION_Q_POOL_SIZE; 4869fa42a0bfSXin 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 */ 4870fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_msgaddr1, (u_int32_t)((host_buffer_dma >> 16) >> 16));/* host buffer high addr */ 4871fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, iobound_doorbell, ARCMSR_HBFMU_DOORBELL_SYNC1); /* set host buffer physical address */ 4872fa42a0bfSXin LI } 4873fa42a0bfSXin LI break; 487444f05562SScott Long } 4875ad6d6297SScott Long if(acb->acb_flags & ACB_F_MAPFREESRB_FAILD) { 4876ad6d6297SScott Long arcmsr_free_resource(acb); 487744f05562SScott Long printf("arcmsr%d: map free srb failure!\n", device_get_unit(dev)); 4878f1c579b1SScott Long return ENXIO; 4879f1c579b1SScott Long } 4880d74001adSXin LI acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_RQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ); 4881ad6d6297SScott Long acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; 4882ad6d6297SScott Long /* 4883ad6d6297SScott Long ******************************************************************** 4884ad6d6297SScott Long ** init raid volume state 4885ad6d6297SScott Long ******************************************************************** 4886ad6d6297SScott Long */ 4887ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_TARGETID; i++) { 4888ad6d6297SScott Long for(j=0; j < ARCMSR_MAX_TARGETLUN; j++) { 488944f05562SScott Long acb->devstate[i][j] = ARECA_RAID_GONE; 4890ad6d6297SScott Long } 4891ad6d6297SScott Long } 4892ad6d6297SScott Long arcmsr_iop_init(acb); 4893f1c579b1SScott Long return(0); 4894f1c579b1SScott Long } 4895a1103e04SXin LI 4896a1103e04SXin LI static int arcmsr_setup_msix(struct AdapterControlBlock *acb) 4897a1103e04SXin LI { 4898a1103e04SXin LI int i; 4899a1103e04SXin LI 4900a1103e04SXin LI for (i = 0; i < acb->msix_vectors; i++) { 4901fc5ef1caSXin LI acb->irq_id[i] = 1 + i; 4902a1103e04SXin LI acb->irqres[i] = bus_alloc_resource_any(acb->pci_dev, 4903a1103e04SXin LI SYS_RES_IRQ, &acb->irq_id[i], RF_ACTIVE); 4904a1103e04SXin LI if (acb->irqres[i] == NULL) { 4905a1103e04SXin LI printf("arcmsr: Can't allocate MSI-X resource\n"); 4906a1103e04SXin LI goto irq_alloc_failed; 4907a1103e04SXin LI } 4908a1103e04SXin LI if (bus_setup_intr(acb->pci_dev, acb->irqres[i], 4909a1103e04SXin LI INTR_MPSAFE | INTR_TYPE_CAM, NULL, arcmsr_intr_handler, 4910a1103e04SXin LI acb, &acb->ih[i])) { 4911a1103e04SXin LI printf("arcmsr: Cannot set up MSI-X interrupt handler\n"); 4912a1103e04SXin LI goto irq_alloc_failed; 4913a1103e04SXin LI } 4914a1103e04SXin LI } 4915a1103e04SXin LI printf("arcmsr: MSI-X INT enabled\n"); 4916a1103e04SXin LI acb->acb_flags |= ACB_F_MSIX_ENABLED; 4917a1103e04SXin LI return TRUE; 4918a1103e04SXin LI 4919a1103e04SXin LI irq_alloc_failed: 4920a1103e04SXin LI arcmsr_teardown_intr(acb->pci_dev, acb); 4921a1103e04SXin LI return FALSE; 4922a1103e04SXin LI } 4923a1103e04SXin LI 4924f1c579b1SScott Long /* 4925f1c579b1SScott Long ************************************************************************ 4926f1c579b1SScott Long ************************************************************************ 4927f1c579b1SScott Long */ 4928f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev) 4929f1c579b1SScott Long { 4930ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 4931ad6d6297SScott Long u_int32_t unit=device_get_unit(dev); 4932f1c579b1SScott Long struct ccb_setasync csa; 4933f1c579b1SScott Long struct cam_devq *devq; /* Device Queue to use for this SIM */ 4934f1c579b1SScott Long struct resource *irqres; 4935f1c579b1SScott Long 4936ad6d6297SScott Long if(acb == NULL) { 4937ad6d6297SScott Long printf("arcmsr%d: cannot allocate softc\n", unit); 4938ad6d6297SScott Long return (ENOMEM); 4939ad6d6297SScott Long } 49407a7bc959SXin LI arcmsr_mutex_init(acb); 49411e7d660aSXin LI acb->pci_dev = dev; 49421e7d660aSXin LI acb->pci_unit = unit; 4943ad6d6297SScott Long if(arcmsr_initialize(dev)) { 4944ad6d6297SScott Long printf("arcmsr%d: initialize failure!\n", unit); 4945a1103e04SXin LI goto initialize_failed; 4946f1c579b1SScott Long } 4947f1c579b1SScott Long /* After setting up the adapter, map our interrupt */ 4948a1103e04SXin LI acb->msix_vectors = ARCMSR_NUM_MSIX_VECTORS; 4949a1103e04SXin LI if (pci_alloc_msix(dev, &acb->msix_vectors) == 0) { 4950a1103e04SXin LI if (arcmsr_setup_msix(acb) == TRUE) 4951a1103e04SXin LI goto irqx; 4952a1103e04SXin LI } 4953fc5ef1caSXin LI acb->irq_id[0] = 0; 4954a1103e04SXin LI irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &acb->irq_id[0], RF_SHAREABLE | RF_ACTIVE); 4955ad6d6297SScott Long if(irqres == NULL || 4956a1103e04SXin LI bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, NULL, arcmsr_intr_handler, acb, &acb->ih[0])) { 4957f1c579b1SScott Long printf("arcmsr%d: unable to register interrupt handler!\n", unit); 4958a1103e04SXin LI goto setup_intr_failed; 4959f1c579b1SScott Long } 4960a1103e04SXin LI acb->irqres[0] = irqres; 4961a1103e04SXin LI irqx: 4962f1c579b1SScott Long /* 4963f1c579b1SScott Long * Now let the CAM generic SCSI layer find the SCSI devices on 4964f1c579b1SScott Long * the bus * start queue to reset to the idle loop. * 4965f1c579b1SScott Long * Create device queue of SIM(s) * (MAX_START_JOB - 1) : 4966f1c579b1SScott Long * max_sim_transactions 4967f1c579b1SScott Long */ 4968224a78aeSXin LI devq = cam_simq_alloc(acb->maxOutstanding); 4969ad6d6297SScott Long if(devq == NULL) { 4970ad6d6297SScott Long printf("arcmsr%d: cam_simq_alloc failure!\n", unit); 4971a1103e04SXin LI goto simq_alloc_failed; 4972f1c579b1SScott Long } 49737a7bc959SXin LI acb->psim = cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, &acb->isr_lock, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq); 4974ad6d6297SScott Long if(acb->psim == NULL) { 4975ad6d6297SScott Long printf("arcmsr%d: cam_sim_alloc failure!\n", unit); 4976a1103e04SXin LI goto sim_alloc_failed; 4977f1c579b1SScott Long } 49787a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 4979b50569b7SScott Long if(xpt_bus_register(acb->psim, dev, 0) != CAM_SUCCESS) { 4980ad6d6297SScott Long printf("arcmsr%d: xpt_bus_register failure!\n", unit); 4981a1103e04SXin LI goto xpt_bus_failed; 4982f1c579b1SScott Long } 4983d74001adSXin LI if(xpt_create_path(&acb->ppath, /* periph */ NULL, cam_sim_path(acb->psim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 4984ad6d6297SScott Long printf("arcmsr%d: xpt_create_path failure!\n", unit); 4985a1103e04SXin LI goto xpt_path_failed; 4986f1c579b1SScott Long } 4987f1c579b1SScott Long /* 4988f1c579b1SScott Long **************************************************** 4989f1c579b1SScott Long */ 499045f57ce1SEdward Tomasz Napierala memset(&csa, 0, sizeof(csa)); 4991ad6d6297SScott Long xpt_setup_ccb(&csa.ccb_h, acb->ppath, /*priority*/5); 4992f1c579b1SScott Long csa.ccb_h.func_code = XPT_SASYNC_CB; 4993f1c579b1SScott Long csa.event_enable = AC_FOUND_DEVICE|AC_LOST_DEVICE; 4994f1c579b1SScott Long csa.callback = arcmsr_async; 4995ad6d6297SScott Long csa.callback_arg = acb->psim; 4996f1c579b1SScott Long xpt_action((union ccb *)&csa); 49977a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 4998f1c579b1SScott Long /* Create the control device. */ 4999d74001adSXin LI acb->ioctl_dev = make_dev(&arcmsr_cdevsw, unit, UID_ROOT, GID_WHEEL /* GID_OPERATOR */, S_IRUSR | S_IWUSR, "arcmsr%d", unit); 5000d74001adSXin LI 5001ad6d6297SScott Long (void)make_dev_alias(acb->ioctl_dev, "arc%d", unit); 500222f2616bSXin LI arcmsr_callout_init(&acb->devmap_callout); 5003d74001adSXin LI callout_reset(&acb->devmap_callout, 60 * hz, arcmsr_polling_devmap, acb); 5004dac36688SXin LI return (0); 5005a1103e04SXin LI xpt_path_failed: 5006a1103e04SXin LI xpt_bus_deregister(cam_sim_path(acb->psim)); 5007a1103e04SXin LI xpt_bus_failed: 5008a1103e04SXin LI cam_sim_free(acb->psim, /* free_simq */ TRUE); 5009a1103e04SXin LI sim_alloc_failed: 5010a1103e04SXin LI cam_simq_free(devq); 5011a1103e04SXin LI simq_alloc_failed: 5012a1103e04SXin LI arcmsr_teardown_intr(dev, acb); 5013a1103e04SXin LI setup_intr_failed: 5014a1103e04SXin LI arcmsr_free_resource(acb); 5015a1103e04SXin LI initialize_failed: 5016a1103e04SXin LI arcmsr_mutex_destroy(acb); 5017a1103e04SXin LI return ENXIO; 5018f1c579b1SScott Long } 501922f2616bSXin LI 5020f1c579b1SScott Long /* 5021f1c579b1SScott Long ************************************************************************ 5022f1c579b1SScott Long ************************************************************************ 5023f1c579b1SScott Long */ 5024f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev) 5025f1c579b1SScott Long { 5026ad6d6297SScott Long u_int32_t id; 5027224a78aeSXin LI u_int16_t sub_device_id; 5028ad6d6297SScott Long static char buf[256]; 50291e7d660aSXin LI char x_type[]={"unknown"}; 5030ad6d6297SScott Long char *type; 5031ad6d6297SScott Long int raid6 = 1; 5032ad6d6297SScott Long 5033ad6d6297SScott Long if (pci_get_vendor(dev) != PCI_VENDOR_ID_ARECA) { 5034ad6d6297SScott Long return (ENXIO); 5035ad6d6297SScott Long } 5036224a78aeSXin LI sub_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2); 5037ad6d6297SScott Long switch(id = pci_get_devid(dev)) { 5038f1c579b1SScott Long case PCIDevVenIDARC1110: 5039231c8b71SXin LI case PCIDevVenIDARC1200: 504044f05562SScott Long case PCIDevVenIDARC1201: 5041231c8b71SXin LI case PCIDevVenIDARC1210: 5042ad6d6297SScott Long raid6 = 0; 5043ad6d6297SScott Long /*FALLTHRU*/ 5044ad6d6297SScott Long case PCIDevVenIDARC1120: 5045ad6d6297SScott Long case PCIDevVenIDARC1130: 5046ad6d6297SScott Long case PCIDevVenIDARC1160: 5047ad6d6297SScott Long case PCIDevVenIDARC1170: 5048f1c579b1SScott Long case PCIDevVenIDARC1220: 5049f1c579b1SScott Long case PCIDevVenIDARC1230: 5050231c8b71SXin LI case PCIDevVenIDARC1231: 5051f1c579b1SScott Long case PCIDevVenIDARC1260: 5052231c8b71SXin LI case PCIDevVenIDARC1261: 5053ad6d6297SScott Long case PCIDevVenIDARC1270: 5054ad6d6297SScott Long case PCIDevVenIDARC1280: 50557a7bc959SXin LI type = "SATA 3G"; 5056ad6d6297SScott Long break; 5057d74001adSXin LI case PCIDevVenIDARC1212: 5058d74001adSXin LI case PCIDevVenIDARC1222: 5059ad6d6297SScott Long case PCIDevVenIDARC1380: 5060ad6d6297SScott Long case PCIDevVenIDARC1381: 5061ad6d6297SScott Long case PCIDevVenIDARC1680: 5062ad6d6297SScott Long case PCIDevVenIDARC1681: 5063d74001adSXin LI type = "SAS 3G"; 5064d74001adSXin LI break; 5065d74001adSXin LI case PCIDevVenIDARC1880: 5066dac36688SXin LI case PCIDevVenIDARC1882: 5067dac36688SXin LI case PCIDevVenIDARC1213: 5068dac36688SXin LI case PCIDevVenIDARC1223: 5069fc5ef1caSXin LI if ((sub_device_id == ARECA_SUB_DEV_ID_1883) || 5070fc5ef1caSXin LI (sub_device_id == ARECA_SUB_DEV_ID_1216) || 5071fc5ef1caSXin LI (sub_device_id == ARECA_SUB_DEV_ID_1226)) 5072224a78aeSXin LI type = "SAS 12G"; 5073224a78aeSXin LI else 5074d74001adSXin LI type = "SAS 6G"; 5075ad6d6297SScott Long break; 5076a1103e04SXin LI case PCIDevVenIDARC1884: 5077a1103e04SXin LI type = "SAS 12G"; 5078a1103e04SXin LI break; 5079fa42a0bfSXin LI case PCIDevVenIDARC1886_: 5080fa42a0bfSXin LI case PCIDevVenIDARC1886: 5081fa42a0bfSXin LI type = "NVME,SAS-12G,SATA-6G"; 5082fa42a0bfSXin LI break; 50837a7bc959SXin LI case PCIDevVenIDARC1214: 5084b23a1998SXin LI case PCIDevVenIDARC1203: 50857a7bc959SXin LI type = "SATA 6G"; 50867a7bc959SXin LI break; 5087ad6d6297SScott Long default: 5088231c8b71SXin LI type = x_type; 50891e7d660aSXin LI raid6 = 0; 5090ad6d6297SScott Long break; 5091f1c579b1SScott Long } 5092231c8b71SXin LI if(type == x_type) 5093231c8b71SXin LI return(ENXIO); 50941e7d660aSXin LI sprintf(buf, "Areca %s Host Adapter RAID Controller %s\n%s\n", 50951e7d660aSXin LI type, raid6 ? "(RAID6 capable)" : "", ARCMSR_DRIVER_VERSION); 5096ad6d6297SScott Long device_set_desc_copy(dev, buf); 509703389298SXin LI return (BUS_PROBE_DEFAULT); 5098f1c579b1SScott Long } 5099f1c579b1SScott Long /* 5100f1c579b1SScott Long ************************************************************************ 5101f1c579b1SScott Long ************************************************************************ 5102f1c579b1SScott Long */ 5103f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev) 5104f1c579b1SScott Long { 510544f05562SScott Long u_int32_t i; 5106ad6d6297SScott Long struct CommandControlBlock *srb; 5107ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 5108f1c579b1SScott Long 5109f1c579b1SScott Long /* stop adapter background rebuild */ 51107a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 511144f05562SScott Long /* disable all outbound interrupt */ 5112bca8e8c0SScott Long arcmsr_disable_allintr(acb); 5113ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 5114ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 5115f1c579b1SScott Long /* abort all outstanding command */ 5116ad6d6297SScott Long acb->acb_flags |= ACB_F_SCSISTOPADAPTER; 5117ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOP_INITED; 5118ad6d6297SScott Long if(acb->srboutstandingcount != 0) { 511944f05562SScott Long /*clear and abort all outbound posted Q*/ 512044f05562SScott Long arcmsr_done4abort_postqueue(acb); 512144f05562SScott Long /* talk to iop 331 outstanding command aborted*/ 5122ad6d6297SScott Long arcmsr_abort_allcmd(acb); 5123ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 5124ad6d6297SScott Long srb = acb->psrb_pool[i]; 512522f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) { 512622f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 5127ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 5128ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 5129f1c579b1SScott Long } 5130f1c579b1SScott Long } 5131f1c579b1SScott Long } 513222f2616bSXin LI acb->srboutstandingcount = 0; 5133ad6d6297SScott Long acb->workingsrb_doneindex = 0; 5134ad6d6297SScott Long acb->workingsrb_startindex = 0; 513522f2616bSXin LI acb->pktRequestCount = 0; 513622f2616bSXin LI acb->pktReturnCount = 0; 51377a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 5138f2aa0e9fSWarner Losh return (0); 5139f1c579b1SScott Long } 5140f1c579b1SScott Long /* 5141f1c579b1SScott Long ************************************************************************ 5142f1c579b1SScott Long ************************************************************************ 5143f1c579b1SScott Long */ 5144fc5ef1caSXin LI static void arcmsr_teardown_intr(device_t dev, struct AdapterControlBlock *acb) 5145a1103e04SXin LI { 5146a1103e04SXin LI int i; 5147a1103e04SXin LI 5148a1103e04SXin LI if (acb->acb_flags & ACB_F_MSIX_ENABLED) { 5149a1103e04SXin LI for (i = 0; i < acb->msix_vectors; i++) { 5150a1103e04SXin LI if (acb->ih[i]) 5151a1103e04SXin LI bus_teardown_intr(dev, acb->irqres[i], acb->ih[i]); 5152a1103e04SXin LI if (acb->irqres[i] != NULL) 5153a1103e04SXin LI bus_release_resource(dev, SYS_RES_IRQ, 5154a1103e04SXin LI acb->irq_id[i], acb->irqres[i]); 5155a1103e04SXin LI 5156a1103e04SXin LI acb->ih[i] = NULL; 5157a1103e04SXin LI } 5158a1103e04SXin LI pci_release_msi(dev); 5159a1103e04SXin LI } else { 5160a1103e04SXin LI if (acb->ih[0]) 5161a1103e04SXin LI bus_teardown_intr(dev, acb->irqres[0], acb->ih[0]); 5162a1103e04SXin LI if (acb->irqres[0] != NULL) 5163a1103e04SXin LI bus_release_resource(dev, SYS_RES_IRQ, 5164a1103e04SXin LI acb->irq_id[0], acb->irqres[0]); 5165a1103e04SXin LI acb->ih[0] = NULL; 5166a1103e04SXin LI } 5167a1103e04SXin LI 5168a1103e04SXin LI } 5169a1103e04SXin LI /* 5170a1103e04SXin LI ************************************************************************ 5171a1103e04SXin LI ************************************************************************ 5172a1103e04SXin LI */ 5173f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev) 5174f1c579b1SScott Long { 5175ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 517644f05562SScott Long int i; 5177f1c579b1SScott Long 5178d74001adSXin LI callout_stop(&acb->devmap_callout); 5179a1103e04SXin LI arcmsr_teardown_intr(dev, acb); 5180f1c579b1SScott Long arcmsr_shutdown(dev); 5181ad6d6297SScott Long arcmsr_free_resource(acb); 518244f05562SScott Long for(i=0; (acb->sys_res_arcmsr[i]!=NULL) && (i<2); i++) { 5183fc5ef1caSXin LI bus_release_resource(dev, SYS_RES_MEMORY, acb->rid[i], acb->sys_res_arcmsr[i]); 518444f05562SScott Long } 51857a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 5186ad6d6297SScott Long xpt_async(AC_LOST_DEVICE, acb->ppath, NULL); 5187ad6d6297SScott Long xpt_free_path(acb->ppath); 5188ad6d6297SScott Long xpt_bus_deregister(cam_sim_path(acb->psim)); 5189ad6d6297SScott Long cam_sim_free(acb->psim, TRUE); 51907a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 51917a7bc959SXin LI arcmsr_mutex_destroy(acb); 5192f1c579b1SScott Long return (0); 5193f1c579b1SScott Long } 5194f1c579b1SScott Long 519522f2616bSXin LI #ifdef ARCMSR_DEBUG1 519622f2616bSXin LI static void arcmsr_dump_data(struct AdapterControlBlock *acb) 519722f2616bSXin LI { 519822f2616bSXin LI if((acb->pktRequestCount - acb->pktReturnCount) == 0) 519922f2616bSXin LI return; 520022f2616bSXin LI printf("Command Request Count =0x%x\n",acb->pktRequestCount); 520122f2616bSXin LI printf("Command Return Count =0x%x\n",acb->pktReturnCount); 520222f2616bSXin LI printf("Command (Req-Rtn) Count =0x%x\n",(acb->pktRequestCount - acb->pktReturnCount)); 520322f2616bSXin LI printf("Queued Command Count =0x%x\n",acb->srboutstandingcount); 520422f2616bSXin LI } 520522f2616bSXin LI #endif 5206