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 88f1c579b1SScott Long ****************************************************************************************** 89f1c579b1SScott Long */ 904b7ec270SMarius Strobl 914b7ec270SMarius Strobl #include <sys/cdefs.h> 924b7ec270SMarius Strobl __FBSDID("$FreeBSD$"); 934b7ec270SMarius Strobl 9422f2616bSXin LI #if 0 9522f2616bSXin LI #define ARCMSR_DEBUG1 1 9622f2616bSXin LI #endif 97f1c579b1SScott Long #include <sys/param.h> 98f1c579b1SScott Long #include <sys/systm.h> 99f1c579b1SScott Long #include <sys/malloc.h> 100f1c579b1SScott Long #include <sys/kernel.h> 101f1c579b1SScott Long #include <sys/bus.h> 102f1c579b1SScott Long #include <sys/queue.h> 103f1c579b1SScott Long #include <sys/stat.h> 104f1c579b1SScott Long #include <sys/devicestat.h> 105f1c579b1SScott Long #include <sys/kthread.h> 106f1c579b1SScott Long #include <sys/module.h> 107f1c579b1SScott Long #include <sys/proc.h> 108f1c579b1SScott Long #include <sys/lock.h> 109f1c579b1SScott Long #include <sys/sysctl.h> 110f1c579b1SScott Long #include <sys/poll.h> 111f1c579b1SScott Long #include <sys/ioccom.h> 112f1c579b1SScott Long #include <vm/vm.h> 113f1c579b1SScott Long #include <vm/vm_param.h> 114f1c579b1SScott Long #include <vm/pmap.h> 115f1c579b1SScott Long 116f1c579b1SScott Long #include <isa/rtc.h> 117f1c579b1SScott Long 118f1c579b1SScott Long #include <machine/bus.h> 119f1c579b1SScott Long #include <machine/resource.h> 120f1c579b1SScott Long #include <machine/atomic.h> 121f1c579b1SScott Long #include <sys/conf.h> 122f1c579b1SScott Long #include <sys/rman.h> 123f1c579b1SScott Long 124f1c579b1SScott Long #include <cam/cam.h> 125f1c579b1SScott Long #include <cam/cam_ccb.h> 126f1c579b1SScott Long #include <cam/cam_sim.h> 127d74001adSXin LI #include <cam/cam_periph.h> 128d74001adSXin LI #include <cam/cam_xpt_periph.h> 129f1c579b1SScott Long #include <cam/cam_xpt_sim.h> 130f1c579b1SScott Long #include <cam/cam_debug.h> 131f1c579b1SScott Long #include <cam/scsi/scsi_all.h> 132f1c579b1SScott Long #include <cam/scsi/scsi_message.h> 133f1c579b1SScott Long /* 134f1c579b1SScott Long ************************************************************************** 135f1c579b1SScott Long ************************************************************************** 136f1c579b1SScott Long */ 137f1c579b1SScott Long #include <sys/selinfo.h> 138f1c579b1SScott Long #include <sys/mutex.h> 139ad6d6297SScott Long #include <sys/endian.h> 140f1c579b1SScott Long #include <dev/pci/pcivar.h> 141f1c579b1SScott Long #include <dev/pci/pcireg.h> 14244f05562SScott Long 14322f2616bSXin LI #define arcmsr_callout_init(a) callout_init(a, /*mpsafe*/1); 14422f2616bSXin LI 145438b5532SXin LI #define ARCMSR_DRIVER_VERSION "arcmsr version 1.50.00.02 2021-04-16" 146f1c579b1SScott Long #include <dev/arcmsr/arcmsr.h> 147f1c579b1SScott Long /* 148f1c579b1SScott Long ************************************************************************** 149f1c579b1SScott Long ************************************************************************** 150f1c579b1SScott Long */ 15122f2616bSXin LI static void arcmsr_free_srb(struct CommandControlBlock *srb); 152ad6d6297SScott Long static struct CommandControlBlock *arcmsr_get_freesrb(struct AdapterControlBlock *acb); 153ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb *abortccb); 154f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev); 155f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev); 156f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev); 157ad6d6297SScott Long static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg); 158ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb); 159f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev); 16044f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb); 161ad6d6297SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb); 162ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb); 163ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb); 164ad6d6297SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); 165ad6d6297SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb); 166ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb); 167ad6d6297SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb); 16835689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, struct QBUFFER *prbuffer); 1697a7bc959SXin LI static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb); 170ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb); 171ad6d6297SScott Long static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag); 172ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb); 173ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb); 174ad6d6297SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t *dm_segs, u_int32_t nseg); 175ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *pccb); 176ad6d6297SScott Long static int arcmsr_resume(device_t dev); 177ad6d6297SScott Long static int arcmsr_suspend(device_t dev); 178d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb); 179d74001adSXin LI static void arcmsr_polling_devmap(void *arg); 18022f2616bSXin LI static void arcmsr_srb_timeout(void *arg); 1817a7bc959SXin LI static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb); 182a1103e04SXin LI static void arcmsr_hbe_postqueue_isr(struct AdapterControlBlock *acb); 183fa42a0bfSXin LI static void arcmsr_hbf_postqueue_isr(struct AdapterControlBlock *acb); 184fc5ef1caSXin LI static void arcmsr_teardown_intr(device_t dev, struct AdapterControlBlock *acb); 18522f2616bSXin LI #ifdef ARCMSR_DEBUG1 18622f2616bSXin LI static void arcmsr_dump_data(struct AdapterControlBlock *acb); 18722f2616bSXin LI #endif 188f1c579b1SScott Long /* 189f1c579b1SScott Long ************************************************************************** 190ad6d6297SScott Long ************************************************************************** 191ad6d6297SScott Long */ 192ad6d6297SScott Long static void UDELAY(u_int32_t us) { DELAY(us); } 193ad6d6297SScott Long /* 194ad6d6297SScott Long ************************************************************************** 195f1c579b1SScott Long ************************************************************************** 196f1c579b1SScott Long */ 197231c8b71SXin LI static bus_dmamap_callback_t arcmsr_map_free_srb; 198231c8b71SXin LI static bus_dmamap_callback_t arcmsr_execute_srb; 199f1c579b1SScott Long /* 200f1c579b1SScott Long ************************************************************************** 201f1c579b1SScott Long ************************************************************************** 202f1c579b1SScott Long */ 203f1c579b1SScott Long static d_open_t arcmsr_open; 204f1c579b1SScott Long static d_close_t arcmsr_close; 205f1c579b1SScott Long static d_ioctl_t arcmsr_ioctl; 206f1c579b1SScott Long 207f1c579b1SScott Long static device_method_t arcmsr_methods[]={ 208f1c579b1SScott Long DEVMETHOD(device_probe, arcmsr_probe), 209f1c579b1SScott Long DEVMETHOD(device_attach, arcmsr_attach), 210f1c579b1SScott Long DEVMETHOD(device_detach, arcmsr_detach), 211f1c579b1SScott Long DEVMETHOD(device_shutdown, arcmsr_shutdown), 212ad6d6297SScott Long DEVMETHOD(device_suspend, arcmsr_suspend), 213ad6d6297SScott Long DEVMETHOD(device_resume, arcmsr_resume), 2144b7ec270SMarius Strobl DEVMETHOD_END 215f1c579b1SScott Long }; 216f1c579b1SScott Long 217f1c579b1SScott Long static driver_t arcmsr_driver={ 218ad6d6297SScott Long "arcmsr", arcmsr_methods, sizeof(struct AdapterControlBlock) 219f1c579b1SScott Long }; 220f1c579b1SScott Long 221f1c579b1SScott Long static devclass_t arcmsr_devclass; 222f1c579b1SScott Long DRIVER_MODULE(arcmsr, pci, arcmsr_driver, arcmsr_devclass, 0, 0); 223d3cf342dSScott Long MODULE_DEPEND(arcmsr, pci, 1, 1, 1); 224d3cf342dSScott Long MODULE_DEPEND(arcmsr, cam, 1, 1, 1); 225ad6d6297SScott Long #ifndef BUS_DMA_COHERENT 226ad6d6297SScott Long #define BUS_DMA_COHERENT 0x04 /* hint: map memory in a coherent way */ 227ad6d6297SScott Long #endif 228f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw={ 229f1c579b1SScott Long .d_version = D_VERSION, 230f1c579b1SScott Long .d_open = arcmsr_open, /* open */ 231f1c579b1SScott Long .d_close = arcmsr_close, /* close */ 232f1c579b1SScott Long .d_ioctl = arcmsr_ioctl, /* ioctl */ 233f1c579b1SScott Long .d_name = "arcmsr", /* name */ 234f1c579b1SScott Long }; 235d74001adSXin LI /* 236d74001adSXin LI ************************************************************************** 237d74001adSXin LI ************************************************************************** 238d74001adSXin LI */ 23900b4e54aSWarner Losh static int arcmsr_open(struct cdev *dev, int flags, int fmt, struct thread *proc) 240f1c579b1SScott Long { 2416bfa9a2dSEd Schouten int unit = dev2unit(dev); 242ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 2439ea5bef2SWarner Losh 244ad6d6297SScott Long if (acb == NULL) { 245f1c579b1SScott Long return ENXIO; 246f1c579b1SScott Long } 247dac36688SXin LI return (0); 248f1c579b1SScott Long } 249f1c579b1SScott Long /* 250f1c579b1SScott Long ************************************************************************** 251f1c579b1SScott Long ************************************************************************** 252f1c579b1SScott Long */ 25300b4e54aSWarner Losh static int arcmsr_close(struct cdev *dev, int flags, int fmt, struct thread *proc) 254f1c579b1SScott Long { 2556bfa9a2dSEd Schouten int unit = dev2unit(dev); 256ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 2579ea5bef2SWarner Losh 258ad6d6297SScott Long if (acb == NULL) { 259f1c579b1SScott Long return ENXIO; 260f1c579b1SScott Long } 261f1c579b1SScott Long return 0; 262f1c579b1SScott Long } 263f1c579b1SScott Long /* 264f1c579b1SScott Long ************************************************************************** 265f1c579b1SScott Long ************************************************************************** 266f1c579b1SScott Long */ 26700b4e54aSWarner Losh static int arcmsr_ioctl(struct cdev *dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc) 268f1c579b1SScott Long { 2696bfa9a2dSEd Schouten int unit = dev2unit(dev); 270ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 271f1c579b1SScott Long 272ad6d6297SScott Long if (acb == NULL) { 273f1c579b1SScott Long return ENXIO; 274f1c579b1SScott Long } 275ad6d6297SScott Long return (arcmsr_iop_ioctlcmd(acb, ioctl_cmd, arg)); 276f1c579b1SScott Long } 277f1c579b1SScott Long /* 27844f05562SScott Long ********************************************************************** 27944f05562SScott Long ********************************************************************** 28044f05562SScott Long */ 28144f05562SScott Long static u_int32_t arcmsr_disable_allintr( struct AdapterControlBlock *acb) 28244f05562SScott Long { 28344f05562SScott Long u_int32_t intmask_org = 0; 28444f05562SScott Long 28544f05562SScott Long switch (acb->adapter_type) { 28644f05562SScott Long case ACB_ADAPTER_TYPE_A: { 28744f05562SScott Long /* disable all outbound interrupt */ 288d74001adSXin LI intmask_org = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intmask); /* disable outbound message0 int */ 289d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); 29044f05562SScott Long } 29144f05562SScott Long break; 29244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 293b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 29444f05562SScott Long /* disable all outbound interrupt */ 295b23a1998SXin LI intmask_org = READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask) 296b23a1998SXin LI & (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); /* disable outbound message0 int */ 297b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask, 0); /* disable all interrupt */ 298d74001adSXin LI } 299d74001adSXin LI break; 300d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 301d74001adSXin LI /* disable all outbound interrupt */ 302d74001adSXin LI intmask_org = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_mask); /* disable outbound message0 int */ 303d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org|ARCMSR_HBCMU_ALL_INTMASKENABLE); 30444f05562SScott Long } 30544f05562SScott Long break; 3067a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 3077a7bc959SXin LI /* disable all outbound interrupt */ 3087a7bc959SXin LI intmask_org = CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable); /* disable outbound message0 int */ 3097a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, ARCMSR_HBDMU_ALL_INT_DISABLE); 3107a7bc959SXin LI } 3117a7bc959SXin LI break; 312fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 313fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 314a1103e04SXin LI /* disable all outbound interrupt */ 315fa42a0bfSXin LI intmask_org = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_mask); /* disable outbound message0 int */ 316a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_mask, intmask_org | ARCMSR_HBEMU_ALL_INTMASKENABLE); 317a1103e04SXin LI } 318a1103e04SXin LI break; 31944f05562SScott Long } 32044f05562SScott Long return (intmask_org); 32144f05562SScott Long } 32244f05562SScott Long /* 32344f05562SScott Long ********************************************************************** 32444f05562SScott Long ********************************************************************** 32544f05562SScott Long */ 32644f05562SScott Long static void arcmsr_enable_allintr( struct AdapterControlBlock *acb, u_int32_t intmask_org) 32744f05562SScott Long { 32844f05562SScott Long u_int32_t mask; 32944f05562SScott Long 33044f05562SScott Long switch (acb->adapter_type) { 33144f05562SScott Long case ACB_ADAPTER_TYPE_A: { 33244f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 333d74001adSXin LI mask = ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE); 33444f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org & mask); 33544f05562SScott Long acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; 33644f05562SScott Long } 33744f05562SScott Long break; 33844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 339b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 340d74001adSXin LI /* enable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */ 341d74001adSXin LI mask = (ARCMSR_IOP2DRV_DATA_WRITE_OK|ARCMSR_IOP2DRV_DATA_READ_OK|ARCMSR_IOP2DRV_CDB_DONE|ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); 342b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask, intmask_org | mask); /*1=interrupt enable, 0=interrupt disable*/ 34344f05562SScott Long acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f; 34444f05562SScott Long } 34544f05562SScott Long break; 346d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 347d74001adSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 348d74001adSXin LI mask = ~(ARCMSR_HBCMU_UTILITY_A_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK); 349d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org & mask); 350d74001adSXin LI acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f; 351d74001adSXin LI } 352d74001adSXin LI break; 3537a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 3547a7bc959SXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 3557a7bc959SXin LI mask = ARCMSR_HBDMU_ALL_INT_ENABLE; 3567a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, intmask_org | mask); 3577a7bc959SXin LI CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable); 3587a7bc959SXin LI acb->outbound_int_enable = mask; 3597a7bc959SXin LI } 3607a7bc959SXin LI break; 361fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 362fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 363a1103e04SXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 364a1103e04SXin LI mask = ~(ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR | ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR); 365a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_mask, intmask_org & mask); 366a1103e04SXin LI acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f; 367a1103e04SXin LI } 368a1103e04SXin LI break; 36944f05562SScott Long } 37044f05562SScott Long } 37144f05562SScott Long /* 37244f05562SScott Long ********************************************************************** 37344f05562SScott Long ********************************************************************** 37444f05562SScott Long */ 37544f05562SScott Long static u_int8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) 37644f05562SScott Long { 37744f05562SScott Long u_int32_t Index; 37844f05562SScott Long u_int8_t Retries = 0x00; 37944f05562SScott Long 38044f05562SScott Long do { 38144f05562SScott Long for(Index=0; Index < 100; Index++) { 382d74001adSXin LI if(CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { 383d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/ 38444f05562SScott Long return TRUE; 38544f05562SScott Long } 38644f05562SScott Long UDELAY(10000); 38744f05562SScott Long }/*max 1 seconds*/ 38844f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 389dac36688SXin LI return (FALSE); 39044f05562SScott Long } 39144f05562SScott Long /* 39244f05562SScott Long ********************************************************************** 39344f05562SScott Long ********************************************************************** 39444f05562SScott Long */ 39544f05562SScott Long static u_int8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) 39644f05562SScott Long { 39744f05562SScott Long u_int32_t Index; 39844f05562SScott Long u_int8_t Retries = 0x00; 399b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 40044f05562SScott Long 40144f05562SScott Long do { 40244f05562SScott Long for(Index=0; Index < 100; Index++) { 403b23a1998SXin LI if(READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { 404b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/ 405b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 406d74001adSXin LI return TRUE; 407d74001adSXin LI } 408d74001adSXin LI UDELAY(10000); 409d74001adSXin LI }/*max 1 seconds*/ 410d74001adSXin LI }while(Retries++ < 20);/*max 20 sec*/ 411dac36688SXin LI return (FALSE); 412d74001adSXin LI } 413d74001adSXin LI /* 414d74001adSXin LI ********************************************************************** 415d74001adSXin LI ********************************************************************** 416d74001adSXin LI */ 417d74001adSXin LI static u_int8_t arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock *acb) 418d74001adSXin LI { 419d74001adSXin LI u_int32_t Index; 420d74001adSXin LI u_int8_t Retries = 0x00; 421d74001adSXin LI 422d74001adSXin LI do { 423d74001adSXin LI for(Index=0; Index < 100; Index++) { 424d74001adSXin LI if(CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { 425d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);/*clear interrupt*/ 42644f05562SScott Long return TRUE; 42744f05562SScott Long } 42844f05562SScott Long UDELAY(10000); 42944f05562SScott Long }/*max 1 seconds*/ 43044f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 431dac36688SXin LI return (FALSE); 43244f05562SScott Long } 43344f05562SScott Long /* 4347a7bc959SXin LI ********************************************************************** 4357a7bc959SXin LI ********************************************************************** 4367a7bc959SXin LI */ 4377a7bc959SXin LI static u_int8_t arcmsr_hbd_wait_msgint_ready(struct AdapterControlBlock *acb) 4387a7bc959SXin LI { 4397a7bc959SXin LI u_int32_t Index; 4407a7bc959SXin LI u_int8_t Retries = 0x00; 4417a7bc959SXin LI 4427a7bc959SXin LI do { 4437a7bc959SXin LI for(Index=0; Index < 100; Index++) { 4447a7bc959SXin LI if(CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) { 4457a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR);/*clear interrupt*/ 4467a7bc959SXin LI return TRUE; 4477a7bc959SXin LI } 4487a7bc959SXin LI UDELAY(10000); 4497a7bc959SXin LI }/*max 1 seconds*/ 4507a7bc959SXin LI }while(Retries++ < 20);/*max 20 sec*/ 4517a7bc959SXin LI return (FALSE); 4527a7bc959SXin LI } 4537a7bc959SXin LI /* 454a1103e04SXin LI ********************************************************************** 455a1103e04SXin LI ********************************************************************** 456a1103e04SXin LI */ 457a1103e04SXin LI static u_int8_t arcmsr_hbe_wait_msgint_ready(struct AdapterControlBlock *acb) 458a1103e04SXin LI { 459a1103e04SXin LI u_int32_t Index, read_doorbell; 460a1103e04SXin LI u_int8_t Retries = 0x00; 461a1103e04SXin LI 462a1103e04SXin LI do { 463a1103e04SXin LI for(Index=0; Index < 100; Index++) { 464a1103e04SXin LI read_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell); 465a1103e04SXin LI if((read_doorbell ^ acb->in_doorbell) & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) { 466a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0);/*clear interrupt*/ 467a1103e04SXin LI acb->in_doorbell = read_doorbell; 468a1103e04SXin LI return TRUE; 469a1103e04SXin LI } 470a1103e04SXin LI UDELAY(10000); 471a1103e04SXin LI }/*max 1 seconds*/ 472a1103e04SXin LI }while(Retries++ < 20);/*max 20 sec*/ 473a1103e04SXin LI return (FALSE); 474a1103e04SXin LI } 475a1103e04SXin LI /* 47644f05562SScott Long ************************************************************************ 47744f05562SScott Long ************************************************************************ 47844f05562SScott Long */ 47944f05562SScott Long static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) 48044f05562SScott Long { 48144f05562SScott Long int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ 48244f05562SScott Long 483d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 48444f05562SScott Long do { 48544f05562SScott Long if(arcmsr_hba_wait_msgint_ready(acb)) { 48644f05562SScott Long break; 48744f05562SScott Long } else { 48844f05562SScott Long retry_count--; 48944f05562SScott Long } 49044f05562SScott Long }while(retry_count != 0); 49144f05562SScott Long } 49244f05562SScott Long /* 49344f05562SScott Long ************************************************************************ 49444f05562SScott Long ************************************************************************ 49544f05562SScott Long */ 49644f05562SScott Long static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) 49744f05562SScott Long { 49844f05562SScott Long int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ 499b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 50044f05562SScott Long 501b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_FLUSH_CACHE); 50244f05562SScott Long do { 50344f05562SScott Long if(arcmsr_hbb_wait_msgint_ready(acb)) { 50444f05562SScott Long break; 50544f05562SScott Long } else { 50644f05562SScott Long retry_count--; 50744f05562SScott Long } 50844f05562SScott Long }while(retry_count != 0); 50944f05562SScott Long } 51044f05562SScott Long /* 51144f05562SScott Long ************************************************************************ 51244f05562SScott Long ************************************************************************ 51344f05562SScott Long */ 514d74001adSXin LI static void arcmsr_flush_hbc_cache(struct AdapterControlBlock *acb) 515d74001adSXin LI { 516d74001adSXin LI int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ 517d74001adSXin LI 518d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 519d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 520d74001adSXin LI do { 521d74001adSXin LI if(arcmsr_hbc_wait_msgint_ready(acb)) { 522d74001adSXin LI break; 523d74001adSXin LI } else { 524d74001adSXin LI retry_count--; 525d74001adSXin LI } 526d74001adSXin LI }while(retry_count != 0); 527d74001adSXin LI } 528d74001adSXin LI /* 529d74001adSXin LI ************************************************************************ 530d74001adSXin LI ************************************************************************ 531d74001adSXin LI */ 5327a7bc959SXin LI static void arcmsr_flush_hbd_cache(struct AdapterControlBlock *acb) 5337a7bc959SXin LI { 5347a7bc959SXin LI int retry_count = 30; /* enlarge wait flush adapter cache time: 10 minute */ 5357a7bc959SXin LI 5367a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 5377a7bc959SXin LI do { 5387a7bc959SXin LI if(arcmsr_hbd_wait_msgint_ready(acb)) { 5397a7bc959SXin LI break; 5407a7bc959SXin LI } else { 5417a7bc959SXin LI retry_count--; 5427a7bc959SXin LI } 5437a7bc959SXin LI }while(retry_count != 0); 5447a7bc959SXin LI } 5457a7bc959SXin LI /* 5467a7bc959SXin LI ************************************************************************ 5477a7bc959SXin LI ************************************************************************ 5487a7bc959SXin LI */ 549a1103e04SXin LI static void arcmsr_flush_hbe_cache(struct AdapterControlBlock *acb) 550a1103e04SXin LI { 551a1103e04SXin LI int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ 552a1103e04SXin LI 553a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 554a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 555a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 556a1103e04SXin LI do { 557a1103e04SXin LI if(arcmsr_hbe_wait_msgint_ready(acb)) { 558a1103e04SXin LI break; 559a1103e04SXin LI } else { 560a1103e04SXin LI retry_count--; 561a1103e04SXin LI } 562a1103e04SXin LI }while(retry_count != 0); 563a1103e04SXin LI } 564a1103e04SXin LI /* 565a1103e04SXin LI ************************************************************************ 566a1103e04SXin LI ************************************************************************ 567a1103e04SXin LI */ 56844f05562SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) 56944f05562SScott Long { 57044f05562SScott Long switch (acb->adapter_type) { 57144f05562SScott Long case ACB_ADAPTER_TYPE_A: { 57244f05562SScott Long arcmsr_flush_hba_cache(acb); 57344f05562SScott Long } 57444f05562SScott Long break; 57544f05562SScott Long case ACB_ADAPTER_TYPE_B: { 57644f05562SScott Long arcmsr_flush_hbb_cache(acb); 57744f05562SScott Long } 57844f05562SScott Long break; 579d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 580d74001adSXin LI arcmsr_flush_hbc_cache(acb); 581d74001adSXin LI } 582d74001adSXin LI break; 5837a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 5847a7bc959SXin LI arcmsr_flush_hbd_cache(acb); 5857a7bc959SXin LI } 5867a7bc959SXin LI break; 587fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 588fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 589a1103e04SXin LI arcmsr_flush_hbe_cache(acb); 590a1103e04SXin LI } 591a1103e04SXin LI break; 59244f05562SScott Long } 59344f05562SScott Long } 59444f05562SScott Long /* 595ad6d6297SScott Long ******************************************************************************* 596ad6d6297SScott Long ******************************************************************************* 597f1c579b1SScott Long */ 598ad6d6297SScott Long static int arcmsr_suspend(device_t dev) 599f1c579b1SScott Long { 600ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 601f1c579b1SScott Long 602ad6d6297SScott Long /* flush controller */ 603ad6d6297SScott Long arcmsr_iop_parking(acb); 604d74001adSXin LI /* disable all outbound interrupt */ 605d74001adSXin LI arcmsr_disable_allintr(acb); 606ad6d6297SScott Long return(0); 607ad6d6297SScott Long } 608ad6d6297SScott Long /* 609ad6d6297SScott Long ******************************************************************************* 610ad6d6297SScott Long ******************************************************************************* 611ad6d6297SScott Long */ 612ad6d6297SScott Long static int arcmsr_resume(device_t dev) 613ad6d6297SScott Long { 614ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 615f1c579b1SScott Long 616ad6d6297SScott Long arcmsr_iop_init(acb); 617ad6d6297SScott Long return(0); 618f1c579b1SScott Long } 619f1c579b1SScott Long /* 620f1c579b1SScott Long ********************************************************************************* 621f1c579b1SScott Long ********************************************************************************* 622f1c579b1SScott Long */ 623ad6d6297SScott Long static void arcmsr_async(void *cb_arg, u_int32_t code, struct cam_path *path, void *arg) 624f1c579b1SScott Long { 625ad6d6297SScott Long u_int8_t target_id, target_lun; 626f1c579b1SScott Long 627ad6d6297SScott Long switch (code) { 628f1c579b1SScott Long case AC_LOST_DEVICE: 629f1c579b1SScott Long target_id = xpt_path_target_id(path); 630f1c579b1SScott Long target_lun = xpt_path_lun_id(path); 631d74001adSXin LI if((target_id > ARCMSR_MAX_TARGETID) || (target_lun > ARCMSR_MAX_TARGETLUN)) { 632f1c579b1SScott Long break; 633f1c579b1SScott Long } 634f1c579b1SScott Long break; 635f1c579b1SScott Long default: 636f1c579b1SScott Long break; 637f1c579b1SScott Long } 638f1c579b1SScott Long } 639f1c579b1SScott Long /* 640f1c579b1SScott Long ********************************************************************** 641f1c579b1SScott Long ********************************************************************** 642f1c579b1SScott Long */ 643ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb) 644f1c579b1SScott Long { 645ad6d6297SScott Long union ccb *pccb = srb->pccb; 646f1c579b1SScott Long 647ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 648ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 649dac36688SXin LI if(pccb->csio.sense_len) { 650ad6d6297SScott Long memset(&pccb->csio.sense_data, 0, sizeof(pccb->csio.sense_data)); 651ad6d6297SScott Long memcpy(&pccb->csio.sense_data, srb->arcmsr_cdb.SenseData, 652ad6d6297SScott Long get_min(sizeof(struct SENSE_DATA), sizeof(pccb->csio.sense_data))); 653ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); /* Valid,ErrorCode */ 654f1c579b1SScott Long pccb->ccb_h.status |= CAM_AUTOSNS_VALID; 655f1c579b1SScott Long } 656f1c579b1SScott Long } 657f1c579b1SScott Long /* 658f1c579b1SScott Long ********************************************************************* 65944f05562SScott Long ********************************************************************* 66044f05562SScott Long */ 66144f05562SScott Long static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) 66244f05562SScott Long { 66344f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 66444f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 665d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 66644f05562SScott Long } 66744f05562SScott Long } 66844f05562SScott Long /* 66944f05562SScott Long ********************************************************************* 67044f05562SScott Long ********************************************************************* 67144f05562SScott Long */ 67244f05562SScott Long static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) 67344f05562SScott Long { 674b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 675b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_ABORT_CMD); 67644f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 677d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 678d74001adSXin LI } 679d74001adSXin LI } 680d74001adSXin LI /* 681d74001adSXin LI ********************************************************************* 682d74001adSXin LI ********************************************************************* 683d74001adSXin LI */ 684d74001adSXin LI static void arcmsr_abort_hbc_allcmd(struct AdapterControlBlock *acb) 685d74001adSXin LI { 686d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 687d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 688d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 689d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 69044f05562SScott Long } 69144f05562SScott Long } 69244f05562SScott Long /* 69344f05562SScott Long ********************************************************************* 694f1c579b1SScott Long ********************************************************************* 695f1c579b1SScott Long */ 6967a7bc959SXin LI static void arcmsr_abort_hbd_allcmd(struct AdapterControlBlock *acb) 6977a7bc959SXin LI { 6987a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 6997a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 7007a7bc959SXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 7017a7bc959SXin LI } 7027a7bc959SXin LI } 7037a7bc959SXin LI /* 7047a7bc959SXin LI ********************************************************************* 7057a7bc959SXin LI ********************************************************************* 7067a7bc959SXin LI */ 707a1103e04SXin LI static void arcmsr_abort_hbe_allcmd(struct AdapterControlBlock *acb) 708a1103e04SXin LI { 709a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 710a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 711a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 712a1103e04SXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) { 713a1103e04SXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 714a1103e04SXin LI } 715a1103e04SXin LI } 716a1103e04SXin LI /* 717a1103e04SXin LI ********************************************************************* 718a1103e04SXin LI ********************************************************************* 719a1103e04SXin LI */ 720ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) 721f1c579b1SScott Long { 72244f05562SScott Long switch (acb->adapter_type) { 72344f05562SScott Long case ACB_ADAPTER_TYPE_A: { 72444f05562SScott Long arcmsr_abort_hba_allcmd(acb); 72544f05562SScott Long } 72644f05562SScott Long break; 72744f05562SScott Long case ACB_ADAPTER_TYPE_B: { 72844f05562SScott Long arcmsr_abort_hbb_allcmd(acb); 72944f05562SScott Long } 73044f05562SScott Long break; 731d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 732d74001adSXin LI arcmsr_abort_hbc_allcmd(acb); 733d74001adSXin LI } 734d74001adSXin LI break; 7357a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 7367a7bc959SXin LI arcmsr_abort_hbd_allcmd(acb); 7377a7bc959SXin LI } 7387a7bc959SXin LI break; 739fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 740fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 741a1103e04SXin LI arcmsr_abort_hbe_allcmd(acb); 742a1103e04SXin LI } 743a1103e04SXin LI break; 74444f05562SScott Long } 74544f05562SScott Long } 74644f05562SScott Long /* 747231c8b71SXin LI ********************************************************************** 748231c8b71SXin LI ********************************************************************** 749231c8b71SXin LI */ 750231c8b71SXin LI static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag) 751231c8b71SXin LI { 752231c8b71SXin LI struct AdapterControlBlock *acb = srb->acb; 753231c8b71SXin LI union ccb *pccb = srb->pccb; 754231c8b71SXin LI 75522f2616bSXin LI if(srb->srb_flags & SRB_FLAG_TIMER_START) 75622f2616bSXin LI callout_stop(&srb->ccb_callout); 757231c8b71SXin LI if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 758231c8b71SXin LI bus_dmasync_op_t op; 759231c8b71SXin LI 760231c8b71SXin LI if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 761231c8b71SXin LI op = BUS_DMASYNC_POSTREAD; 762231c8b71SXin LI } else { 763231c8b71SXin LI op = BUS_DMASYNC_POSTWRITE; 764231c8b71SXin LI } 765231c8b71SXin LI bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 766231c8b71SXin LI bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 767231c8b71SXin LI } 768231c8b71SXin LI if(stand_flag == 1) { 769231c8b71SXin LI atomic_subtract_int(&acb->srboutstandingcount, 1); 770231c8b71SXin LI if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) && ( 771abfdbca9SXin LI acb->srboutstandingcount < (acb->maxOutstanding -10))) { 772231c8b71SXin LI acb->acb_flags &= ~ACB_F_CAM_DEV_QFRZN; 773231c8b71SXin LI pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 774231c8b71SXin LI } 775231c8b71SXin LI } 77622f2616bSXin LI if(srb->srb_state != ARCMSR_SRB_TIMEOUT) 77722f2616bSXin LI arcmsr_free_srb(srb); 77822f2616bSXin LI acb->pktReturnCount++; 779231c8b71SXin LI xpt_done(pccb); 780231c8b71SXin LI } 781231c8b71SXin LI /* 78244f05562SScott Long ************************************************************************** 78344f05562SScott Long ************************************************************************** 78444f05562SScott Long */ 785d74001adSXin LI static void arcmsr_report_srb_state(struct AdapterControlBlock *acb, struct CommandControlBlock *srb, u_int16_t error) 78644f05562SScott Long { 78744f05562SScott Long int target, lun; 78844f05562SScott Long 78944f05562SScott Long target = srb->pccb->ccb_h.target_id; 79044f05562SScott Long lun = srb->pccb->ccb_h.target_lun; 791d74001adSXin LI if(error == FALSE) { 79244f05562SScott Long if(acb->devstate[target][lun] == ARECA_RAID_GONE) { 79344f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GOOD; 79444f05562SScott Long } 79544f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_CMP; 79644f05562SScott Long arcmsr_srb_complete(srb, 1); 79744f05562SScott Long } else { 79844f05562SScott Long switch(srb->arcmsr_cdb.DeviceStatus) { 79944f05562SScott Long case ARCMSR_DEV_SELECT_TIMEOUT: { 80044f05562SScott Long if(acb->devstate[target][lun] == ARECA_RAID_GOOD) { 801d74001adSXin LI printf( "arcmsr%d: Target=%x, Lun=%x, selection timeout, raid volume was lost\n", acb->pci_unit, target, lun); 802ad6d6297SScott Long } 80344f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GONE; 804d74001adSXin LI srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 80544f05562SScott Long arcmsr_srb_complete(srb, 1); 80644f05562SScott Long } 80744f05562SScott Long break; 80844f05562SScott Long case ARCMSR_DEV_ABORTED: 80944f05562SScott Long case ARCMSR_DEV_INIT_FAIL: { 81044f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GONE; 81144f05562SScott Long srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 81244f05562SScott Long arcmsr_srb_complete(srb, 1); 81344f05562SScott Long } 81444f05562SScott Long break; 81544f05562SScott Long case SCSISTAT_CHECK_CONDITION: { 81644f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GOOD; 81744f05562SScott Long arcmsr_report_sense_info(srb); 81844f05562SScott Long arcmsr_srb_complete(srb, 1); 81944f05562SScott Long } 82044f05562SScott Long break; 82144f05562SScott Long default: 82210d66948SKevin Lo printf("arcmsr%d: scsi id=%d lun=%d isr got command error done,but got unknown DeviceStatus=0x%x \n" 823d74001adSXin LI , acb->pci_unit, target, lun ,srb->arcmsr_cdb.DeviceStatus); 82444f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GONE; 82544f05562SScott Long srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY; 82610d66948SKevin Lo /*unknown error or crc error just for retry*/ 82744f05562SScott Long arcmsr_srb_complete(srb, 1); 82844f05562SScott Long break; 82944f05562SScott Long } 83044f05562SScott Long } 83144f05562SScott Long } 83244f05562SScott Long /* 83344f05562SScott Long ************************************************************************** 83444f05562SScott Long ************************************************************************** 83544f05562SScott Long */ 836d74001adSXin LI static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t flag_srb, u_int16_t error) 83744f05562SScott Long { 83844f05562SScott Long struct CommandControlBlock *srb; 83944f05562SScott Long 84044f05562SScott Long /* check if command done with no error*/ 841d74001adSXin LI switch (acb->adapter_type) { 842fc5ef1caSXin LI case ACB_ADAPTER_TYPE_A: 843fc5ef1caSXin LI case ACB_ADAPTER_TYPE_B: 844fc5ef1caSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 845fc5ef1caSXin LI break; 846d74001adSXin LI case ACB_ADAPTER_TYPE_C: 8477a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 84822f2616bSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0)); /*frame must be 32 bytes aligned*/ 849d74001adSXin LI break; 850a1103e04SXin LI case ACB_ADAPTER_TYPE_E: 851fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 852a1103e04SXin LI srb = acb->psrb_pool[flag_srb]; 853a1103e04SXin LI break; 854d74001adSXin LI default: 855d74001adSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 856d74001adSXin LI break; 857d74001adSXin LI } 85822f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 85922f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_TIMEOUT) { 86022f2616bSXin LI arcmsr_free_srb(srb); 86122f2616bSXin LI printf("arcmsr%d: srb='%p' return srb has been timeouted\n", acb->pci_unit, srb); 86244f05562SScott Long return; 86344f05562SScott Long } 86422f2616bSXin LI printf("arcmsr%d: return srb has been completed\n" 86522f2616bSXin LI "srb='%p' srb_state=0x%x outstanding srb count=%d \n", 86622f2616bSXin LI acb->pci_unit, srb, srb->srb_state, acb->srboutstandingcount); 86744f05562SScott Long return; 86844f05562SScott Long } 869d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 87044f05562SScott Long } 87144f05562SScott Long /* 87222f2616bSXin LI ************************************************************************** 87322f2616bSXin LI ************************************************************************** 87422f2616bSXin LI */ 87522f2616bSXin LI static void arcmsr_srb_timeout(void *arg) 87622f2616bSXin LI { 87722f2616bSXin LI struct CommandControlBlock *srb = (struct CommandControlBlock *)arg; 87822f2616bSXin LI struct AdapterControlBlock *acb; 87922f2616bSXin LI int target, lun; 88022f2616bSXin LI u_int8_t cmd; 88122f2616bSXin LI 88222f2616bSXin LI target = srb->pccb->ccb_h.target_id; 88322f2616bSXin LI lun = srb->pccb->ccb_h.target_lun; 88422f2616bSXin LI acb = srb->acb; 8857a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 88622f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) 88722f2616bSXin LI { 8884aa947cbSWarner Losh cmd = scsiio_cdb_ptr(&srb->pccb->csio)[0]; 88922f2616bSXin LI srb->srb_state = ARCMSR_SRB_TIMEOUT; 89022f2616bSXin LI srb->pccb->ccb_h.status |= CAM_CMD_TIMEOUT; 89122f2616bSXin LI arcmsr_srb_complete(srb, 1); 89222f2616bSXin LI printf("arcmsr%d: scsi id %d lun %d cmd=0x%x srb='%p' ccb command time out!\n", 89322f2616bSXin LI acb->pci_unit, target, lun, cmd, srb); 89422f2616bSXin LI } 8957a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 89622f2616bSXin LI #ifdef ARCMSR_DEBUG1 89722f2616bSXin LI arcmsr_dump_data(acb); 89822f2616bSXin LI #endif 89922f2616bSXin LI } 90022f2616bSXin LI 90122f2616bSXin LI /* 90244f05562SScott Long ********************************************************************** 90344f05562SScott Long ********************************************************************** 90444f05562SScott Long */ 90544f05562SScott Long static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) 90644f05562SScott Long { 90744f05562SScott Long int i=0; 90844f05562SScott Long u_int32_t flag_srb; 909d74001adSXin LI u_int16_t error; 91044f05562SScott Long 91144f05562SScott Long switch (acb->adapter_type) { 91244f05562SScott Long case ACB_ADAPTER_TYPE_A: { 91344f05562SScott Long u_int32_t outbound_intstatus; 91444f05562SScott Long 91544f05562SScott Long /*clear and abort all outbound posted Q*/ 916d74001adSXin LI outbound_intstatus = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 917d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/ 918d74001adSXin LI while(((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_queueport)) != 0xFFFFFFFF) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { 919d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 920d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 92144f05562SScott Long } 92244f05562SScott Long } 92344f05562SScott Long break; 92444f05562SScott Long case ACB_ADAPTER_TYPE_B: { 92544f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 92644f05562SScott Long 92744f05562SScott Long /*clear all outbound posted Q*/ 928b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 92944f05562SScott Long for(i=0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) { 93044f05562SScott Long if((flag_srb = phbbmu->done_qbuffer[i]) != 0) { 93144f05562SScott Long phbbmu->done_qbuffer[i] = 0; 932d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 933d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 93444f05562SScott Long } 93544f05562SScott Long phbbmu->post_qbuffer[i] = 0; 93644f05562SScott Long }/*drain reply FIFO*/ 93744f05562SScott Long phbbmu->doneq_index = 0; 93844f05562SScott Long phbbmu->postq_index = 0; 93944f05562SScott Long } 94044f05562SScott Long break; 941d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 942d74001adSXin LI while((CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { 943d74001adSXin LI flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 944d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 945d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 946d74001adSXin LI } 947d74001adSXin LI } 948d74001adSXin LI break; 949fa42a0bfSXin LI case ACB_ADAPTER_TYPE_D: 9507a7bc959SXin LI arcmsr_hbd_postqueue_isr(acb); 9517a7bc959SXin LI break; 952fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 953a1103e04SXin LI arcmsr_hbe_postqueue_isr(acb); 954fa42a0bfSXin LI break; 955fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 956fa42a0bfSXin LI arcmsr_hbf_postqueue_isr(acb); 957a1103e04SXin LI break; 95844f05562SScott Long } 959f1c579b1SScott Long } 960f1c579b1SScott Long /* 961f1c579b1SScott Long **************************************************************************** 962f1c579b1SScott Long **************************************************************************** 963f1c579b1SScott Long */ 964ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb) 965f1c579b1SScott Long { 966ad6d6297SScott Long struct CommandControlBlock *srb; 96744f05562SScott Long u_int32_t intmask_org; 968ad6d6297SScott Long u_int32_t i=0; 969f1c579b1SScott Long 97044f05562SScott Long if(acb->srboutstandingcount>0) { 97144f05562SScott Long /* disable all outbound interrupt */ 97244f05562SScott Long intmask_org = arcmsr_disable_allintr(acb); 97344f05562SScott Long /*clear and abort all outbound posted Q*/ 97444f05562SScott Long arcmsr_done4abort_postqueue(acb); 975f1c579b1SScott Long /* talk to iop 331 outstanding command aborted*/ 976ad6d6297SScott Long arcmsr_abort_allcmd(acb); 977ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 978ad6d6297SScott Long srb = acb->psrb_pool[i]; 97922f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) { 98022f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 981ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 982ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 983123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p' aborted\n" 98422f2616bSXin LI , acb->pci_unit, srb->pccb->ccb_h.target_id 985123055f0SNathan Whitehorn , (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 986f1c579b1SScott Long } 987f1c579b1SScott Long } 988f1c579b1SScott Long /* enable all outbound interrupt */ 98944f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 990f1c579b1SScott Long } 99122f2616bSXin LI acb->srboutstandingcount = 0; 992ad6d6297SScott Long acb->workingsrb_doneindex = 0; 993ad6d6297SScott Long acb->workingsrb_startindex = 0; 99422f2616bSXin LI acb->pktRequestCount = 0; 99522f2616bSXin LI acb->pktReturnCount = 0; 996f1c579b1SScott Long } 997f1c579b1SScott Long /* 998f1c579b1SScott Long ********************************************************************** 999f1c579b1SScott Long ********************************************************************** 1000f1c579b1SScott Long */ 100144f05562SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, 100244f05562SScott Long bus_dma_segment_t *dm_segs, u_int32_t nseg) 1003f1c579b1SScott Long { 1004ad6d6297SScott Long struct ARCMSR_CDB *arcmsr_cdb = &srb->arcmsr_cdb; 1005ad6d6297SScott Long u_int8_t *psge = (u_int8_t *)&arcmsr_cdb->u; 1006ad6d6297SScott Long u_int32_t address_lo, address_hi; 1007ad6d6297SScott Long union ccb *pccb = srb->pccb; 1008f1c579b1SScott Long struct ccb_scsiio *pcsio = &pccb->csio; 1009ad6d6297SScott Long u_int32_t arccdbsize = 0x30; 1010f1c579b1SScott Long 1011ad6d6297SScott Long memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB)); 1012ad6d6297SScott Long arcmsr_cdb->Bus = 0; 1013ad6d6297SScott Long arcmsr_cdb->TargetID = pccb->ccb_h.target_id; 1014ad6d6297SScott Long arcmsr_cdb->LUN = pccb->ccb_h.target_lun; 1015ad6d6297SScott Long arcmsr_cdb->Function = 1; 1016ad6d6297SScott Long arcmsr_cdb->CdbLength = (u_int8_t)pcsio->cdb_len; 10174aa947cbSWarner Losh bcopy(scsiio_cdb_ptr(pcsio), arcmsr_cdb->Cdb, pcsio->cdb_len); 1018ad6d6297SScott Long if(nseg != 0) { 1019ad6d6297SScott Long struct AdapterControlBlock *acb = srb->acb; 1020f1c579b1SScott Long bus_dmasync_op_t op; 1021ad6d6297SScott Long u_int32_t length, i, cdb_sgcount = 0; 1022f1c579b1SScott Long 1023ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 1024ad6d6297SScott Long op = BUS_DMASYNC_PREREAD; 1025ad6d6297SScott Long } else { 1026ad6d6297SScott Long op = BUS_DMASYNC_PREWRITE; 1027ad6d6297SScott Long arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE; 1028ad6d6297SScott Long srb->srb_flags |= SRB_FLAG_WRITE; 1029ad6d6297SScott Long } 1030ad6d6297SScott Long bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 1031ad6d6297SScott Long for(i=0; i < nseg; i++) { 1032f1c579b1SScott Long /* Get the physical address of the current data pointer */ 1033ad6d6297SScott Long length = arcmsr_htole32(dm_segs[i].ds_len); 1034ad6d6297SScott Long address_lo = arcmsr_htole32(dma_addr_lo32(dm_segs[i].ds_addr)); 1035ad6d6297SScott Long address_hi = arcmsr_htole32(dma_addr_hi32(dm_segs[i].ds_addr)); 1036ad6d6297SScott Long if(address_hi == 0) { 1037ad6d6297SScott Long struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge; 1038f1c579b1SScott Long pdma_sg->address = address_lo; 1039f1c579b1SScott Long pdma_sg->length = length; 1040ad6d6297SScott Long psge += sizeof(struct SG32ENTRY); 1041ad6d6297SScott Long arccdbsize += sizeof(struct SG32ENTRY); 1042ad6d6297SScott Long } else { 1043ad6d6297SScott Long u_int32_t sg64s_size = 0, tmplength = length; 1044f1c579b1SScott Long 1045ad6d6297SScott Long while(1) { 1046ad6d6297SScott Long u_int64_t span4G, length0; 1047ad6d6297SScott Long struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge; 1048f1c579b1SScott Long 1049ad6d6297SScott Long span4G = (u_int64_t)address_lo + tmplength; 1050f1c579b1SScott Long pdma_sg->addresshigh = address_hi; 1051f1c579b1SScott Long pdma_sg->address = address_lo; 1052ad6d6297SScott Long if(span4G > 0x100000000) { 1053f1c579b1SScott Long /*see if cross 4G boundary*/ 1054f1c579b1SScott Long length0 = 0x100000000-address_lo; 1055ad6d6297SScott Long pdma_sg->length = (u_int32_t)length0 | IS_SG64_ADDR; 1056f1c579b1SScott Long address_hi = address_hi+1; 1057f1c579b1SScott Long address_lo = 0; 1058ad6d6297SScott Long tmplength = tmplength - (u_int32_t)length0; 1059ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 1060ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 1061f1c579b1SScott Long cdb_sgcount++; 1062ad6d6297SScott Long } else { 1063f1c579b1SScott Long pdma_sg->length = tmplength | IS_SG64_ADDR; 1064ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 1065ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 1066f1c579b1SScott Long break; 1067f1c579b1SScott Long } 1068f1c579b1SScott Long } 1069f1c579b1SScott Long arccdbsize += sg64s_size; 1070f1c579b1SScott Long } 1071f1c579b1SScott Long cdb_sgcount++; 1072f1c579b1SScott Long } 1073ad6d6297SScott Long arcmsr_cdb->sgcount = (u_int8_t)cdb_sgcount; 1074ad6d6297SScott Long arcmsr_cdb->DataLength = pcsio->dxfer_len; 1075ad6d6297SScott Long if( arccdbsize > 256) { 1076ad6d6297SScott Long arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE; 1077f1c579b1SScott Long } 1078d74001adSXin LI } else { 1079d74001adSXin LI arcmsr_cdb->DataLength = 0; 1080f1c579b1SScott Long } 1081d74001adSXin LI srb->arc_cdb_size = arccdbsize; 10827a7bc959SXin LI arcmsr_cdb->msgPages = (arccdbsize/256) + ((arccdbsize % 256) ? 1 : 0); 1083f1c579b1SScott Long } 1084f1c579b1SScott Long /* 1085f1c579b1SScott Long ************************************************************************** 1086f1c579b1SScott Long ************************************************************************** 1087f1c579b1SScott Long */ 1088ad6d6297SScott Long static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandControlBlock *srb) 1089f1c579b1SScott Long { 10907a7bc959SXin LI u_int32_t cdb_phyaddr_low = (u_int32_t) srb->cdb_phyaddr_low; 1091ad6d6297SScott Long struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&srb->arcmsr_cdb; 1092f1c579b1SScott Long 1093d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, (srb->srb_flags & SRB_FLAG_WRITE) ? BUS_DMASYNC_POSTWRITE:BUS_DMASYNC_POSTREAD); 1094ad6d6297SScott Long atomic_add_int(&acb->srboutstandingcount, 1); 109522f2616bSXin LI srb->srb_state = ARCMSR_SRB_START; 1096d74001adSXin LI 109744f05562SScott Long switch (acb->adapter_type) { 109844f05562SScott Long case ACB_ADAPTER_TYPE_A: { 1099ad6d6297SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 11007a7bc959SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_phyaddr_low|ARCMSR_SRBPOST_FLAG_SGL_BSIZE); 1101ad6d6297SScott Long } else { 11027a7bc959SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_phyaddr_low); 110344f05562SScott Long } 110444f05562SScott Long } 110544f05562SScott Long break; 110644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 110744f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 110844f05562SScott Long int ending_index, index; 110944f05562SScott Long 111044f05562SScott Long index = phbbmu->postq_index; 111144f05562SScott Long ending_index = ((index+1) % ARCMSR_MAX_HBB_POSTQUEUE); 111244f05562SScott Long phbbmu->post_qbuffer[ending_index] = 0; 111344f05562SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 11147a7bc959SXin LI phbbmu->post_qbuffer[index] = cdb_phyaddr_low | ARCMSR_SRBPOST_FLAG_SGL_BSIZE; 111544f05562SScott Long } else { 11167a7bc959SXin LI phbbmu->post_qbuffer[index] = cdb_phyaddr_low; 111744f05562SScott Long } 111844f05562SScott Long index++; 111944f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 112044f05562SScott Long phbbmu->postq_index = index; 1121b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED); 1122d74001adSXin LI } 1123d74001adSXin LI break; 11247a7bc959SXin LI case ACB_ADAPTER_TYPE_C: { 1125d74001adSXin LI u_int32_t ccb_post_stamp, arc_cdb_size, cdb_phyaddr_hi32; 1126d74001adSXin LI 1127d74001adSXin LI arc_cdb_size = (srb->arc_cdb_size > 0x300) ? 0x300 : srb->arc_cdb_size; 11287a7bc959SXin LI ccb_post_stamp = (cdb_phyaddr_low | ((arc_cdb_size-1) >> 6) | 1); 1129d74001adSXin LI cdb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high; 1130d74001adSXin LI if(cdb_phyaddr_hi32) 1131d74001adSXin LI { 1132d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_high, cdb_phyaddr_hi32); 1133d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp); 1134d74001adSXin LI } 1135d74001adSXin LI else 1136d74001adSXin LI { 1137d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp); 1138d74001adSXin LI } 113944f05562SScott Long } 114044f05562SScott Long break; 11417a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 11427a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 11437a7bc959SXin LI u_int16_t index_stripped; 11447a7bc959SXin LI u_int16_t postq_index; 11457a7bc959SXin LI struct InBound_SRB *pinbound_srb; 11467a7bc959SXin LI 11477a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->postDone_lock); 11487a7bc959SXin LI postq_index = phbdmu->postq_index; 11497a7bc959SXin LI pinbound_srb = (struct InBound_SRB *)&phbdmu->post_qbuffer[postq_index & 0xFF]; 11507a7bc959SXin LI pinbound_srb->addressHigh = srb->cdb_phyaddr_high; 11517a7bc959SXin LI pinbound_srb->addressLow = srb->cdb_phyaddr_low; 11527a7bc959SXin LI pinbound_srb->length = srb->arc_cdb_size >> 2; 11537a7bc959SXin LI arcmsr_cdb->Context = srb->cdb_phyaddr_low; 11547a7bc959SXin LI if (postq_index & 0x4000) { 11557a7bc959SXin LI index_stripped = postq_index & 0xFF; 11567a7bc959SXin LI index_stripped += 1; 11577a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 11587a7bc959SXin LI phbdmu->postq_index = index_stripped ? (index_stripped | 0x4000) : index_stripped; 11597a7bc959SXin LI } else { 11607a7bc959SXin LI index_stripped = postq_index; 11617a7bc959SXin LI index_stripped += 1; 11627a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 11637a7bc959SXin LI phbdmu->postq_index = index_stripped ? index_stripped : (index_stripped | 0x4000); 11647a7bc959SXin LI } 11657a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inboundlist_write_pointer, postq_index); 11667a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->postDone_lock); 11677a7bc959SXin LI } 11687a7bc959SXin LI break; 1169a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 1170a1103e04SXin LI u_int32_t ccb_post_stamp, arc_cdb_size; 1171a1103e04SXin LI 1172a1103e04SXin LI arc_cdb_size = (srb->arc_cdb_size > 0x300) ? 0x300 : srb->arc_cdb_size; 1173a1103e04SXin LI ccb_post_stamp = (srb->smid | ((arc_cdb_size-1) >> 6)); 1174a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_queueport_high, 0); 1175a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_queueport_low, ccb_post_stamp); 1176a1103e04SXin LI } 1177a1103e04SXin LI break; 1178fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 1179fa42a0bfSXin LI u_int32_t ccb_post_stamp, arc_cdb_size; 1180fa42a0bfSXin LI 1181fa42a0bfSXin LI if (srb->arc_cdb_size <= 0x300) 1182fa42a0bfSXin LI arc_cdb_size = (srb->arc_cdb_size - 1) >> 6 | 1; 1183438b5532SXin LI else { 1184438b5532SXin LI arc_cdb_size = ((srb->arc_cdb_size + 0xff) >> 8) + 2; 1185438b5532SXin LI if (arc_cdb_size > 0xF) 1186438b5532SXin LI arc_cdb_size = 0xF; 1187438b5532SXin LI arc_cdb_size = (arc_cdb_size << 1) | 1; 1188438b5532SXin LI } 1189fa42a0bfSXin LI ccb_post_stamp = (srb->smid | arc_cdb_size); 1190fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_queueport_high, 0); 1191fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_queueport_low, ccb_post_stamp); 1192fa42a0bfSXin LI } 1193fa42a0bfSXin LI break; 1194f1c579b1SScott Long } 1195f1c579b1SScott Long } 1196f1c579b1SScott Long /* 119744f05562SScott Long ************************************************************************ 119844f05562SScott Long ************************************************************************ 119944f05562SScott Long */ 120044f05562SScott Long static struct QBUFFER *arcmsr_get_iop_rqbuffer( struct AdapterControlBlock *acb) 120144f05562SScott Long { 120244f05562SScott Long struct QBUFFER *qbuffer=NULL; 120344f05562SScott Long 120444f05562SScott Long switch (acb->adapter_type) { 120544f05562SScott Long case ACB_ADAPTER_TYPE_A: { 120644f05562SScott Long struct HBA_MessageUnit *phbamu = (struct HBA_MessageUnit *)acb->pmu; 120744f05562SScott Long 120844f05562SScott Long qbuffer = (struct QBUFFER *)&phbamu->message_rbuffer; 120944f05562SScott Long } 121044f05562SScott Long break; 121144f05562SScott Long case ACB_ADAPTER_TYPE_B: { 121244f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 121344f05562SScott Long 121444f05562SScott Long qbuffer = (struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_rbuffer; 121544f05562SScott Long } 121644f05562SScott Long break; 1217d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1218d74001adSXin LI struct HBC_MessageUnit *phbcmu = (struct HBC_MessageUnit *)acb->pmu; 1219d74001adSXin LI 1220d74001adSXin LI qbuffer = (struct QBUFFER *)&phbcmu->message_rbuffer; 1221d74001adSXin LI } 1222d74001adSXin LI break; 12237a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 12247a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 12257a7bc959SXin LI 12267a7bc959SXin LI qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_rbuffer; 12277a7bc959SXin LI } 12287a7bc959SXin LI break; 1229a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 1230a1103e04SXin LI struct HBE_MessageUnit *phbcmu = (struct HBE_MessageUnit *)acb->pmu; 1231a1103e04SXin LI 1232a1103e04SXin LI qbuffer = (struct QBUFFER *)&phbcmu->message_rbuffer; 1233a1103e04SXin LI } 1234a1103e04SXin LI break; 1235fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 1236fa42a0bfSXin LI qbuffer = (struct QBUFFER *)acb->message_rbuffer; 1237fa42a0bfSXin LI break; 123844f05562SScott Long } 123944f05562SScott Long return(qbuffer); 124044f05562SScott Long } 124144f05562SScott Long /* 124244f05562SScott Long ************************************************************************ 124344f05562SScott Long ************************************************************************ 124444f05562SScott Long */ 124544f05562SScott Long static struct QBUFFER *arcmsr_get_iop_wqbuffer( struct AdapterControlBlock *acb) 124644f05562SScott Long { 124744f05562SScott Long struct QBUFFER *qbuffer = NULL; 124844f05562SScott Long 124944f05562SScott Long switch (acb->adapter_type) { 125044f05562SScott Long case ACB_ADAPTER_TYPE_A: { 125144f05562SScott Long struct HBA_MessageUnit *phbamu = (struct HBA_MessageUnit *)acb->pmu; 125244f05562SScott Long 125344f05562SScott Long qbuffer = (struct QBUFFER *)&phbamu->message_wbuffer; 125444f05562SScott Long } 125544f05562SScott Long break; 125644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 125744f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 125844f05562SScott Long 125944f05562SScott Long qbuffer = (struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_wbuffer; 126044f05562SScott Long } 126144f05562SScott Long break; 1262d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1263d74001adSXin LI struct HBC_MessageUnit *phbcmu = (struct HBC_MessageUnit *)acb->pmu; 1264d74001adSXin LI 1265d74001adSXin LI qbuffer = (struct QBUFFER *)&phbcmu->message_wbuffer; 1266d74001adSXin LI } 1267d74001adSXin LI break; 12687a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 12697a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 12707a7bc959SXin LI 12717a7bc959SXin LI qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_wbuffer; 12727a7bc959SXin LI } 12737a7bc959SXin LI break; 1274a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 1275a1103e04SXin LI struct HBE_MessageUnit *phbcmu = (struct HBE_MessageUnit *)acb->pmu; 1276a1103e04SXin LI 1277a1103e04SXin LI qbuffer = (struct QBUFFER *)&phbcmu->message_wbuffer; 1278a1103e04SXin LI } 1279a1103e04SXin LI break; 1280fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 1281fa42a0bfSXin LI qbuffer = (struct QBUFFER *)acb->message_wbuffer; 1282fa42a0bfSXin LI break; 128344f05562SScott Long } 128444f05562SScott Long return(qbuffer); 128544f05562SScott Long } 128644f05562SScott Long /* 128744f05562SScott Long ************************************************************************** 128844f05562SScott Long ************************************************************************** 128944f05562SScott Long */ 129044f05562SScott Long static void arcmsr_iop_message_read(struct AdapterControlBlock *acb) 129144f05562SScott Long { 129244f05562SScott Long switch (acb->adapter_type) { 129344f05562SScott Long case ACB_ADAPTER_TYPE_A: { 129444f05562SScott Long /* let IOP know data has been read */ 1295d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 129644f05562SScott Long } 129744f05562SScott Long break; 129844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 1299b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 130044f05562SScott Long /* let IOP know data has been read */ 1301b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 130244f05562SScott Long } 130344f05562SScott Long break; 1304d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1305d74001adSXin LI /* let IOP know data has been read */ 1306d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK); 1307d74001adSXin LI } 13087a7bc959SXin LI break; 13097a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 13107a7bc959SXin LI /* let IOP know data has been read */ 13117a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ); 13127a7bc959SXin LI } 13137a7bc959SXin LI break; 1314fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 1315fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 1316a1103e04SXin LI /* let IOP know data has been read */ 1317a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK; 1318a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 1319a1103e04SXin LI } 1320a1103e04SXin LI break; 132144f05562SScott Long } 132244f05562SScott Long } 132344f05562SScott Long /* 132444f05562SScott Long ************************************************************************** 132544f05562SScott Long ************************************************************************** 132644f05562SScott Long */ 132744f05562SScott Long static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) 132844f05562SScott Long { 132944f05562SScott Long switch (acb->adapter_type) { 133044f05562SScott Long case ACB_ADAPTER_TYPE_A: { 133144f05562SScott Long /* 133244f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 133344f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 133444f05562SScott Long */ 1335d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK); 133644f05562SScott Long } 133744f05562SScott Long break; 133844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 1339b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 134044f05562SScott Long /* 134144f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 134244f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 134344f05562SScott Long */ 1344b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_WRITE_OK); 1345d74001adSXin LI } 1346d74001adSXin LI break; 1347d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1348d74001adSXin LI /* 1349d74001adSXin LI ** push inbound doorbell tell iop, driver data write ok 1350d74001adSXin LI ** and wait reply on next hwinterrupt for next Qbuffer post 1351d74001adSXin LI */ 1352d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK); 135344f05562SScott Long } 135444f05562SScott Long break; 13557a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 135644f05562SScott Long /* 13577a7bc959SXin LI ** push inbound doorbell tell iop, driver data write ok 13587a7bc959SXin LI ** and wait reply on next hwinterrupt for next Qbuffer post 1359f1c579b1SScott Long */ 13607a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_IN_READY); 1361f1c579b1SScott Long } 13627a7bc959SXin LI break; 1363fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 1364fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 1365a1103e04SXin LI /* 1366a1103e04SXin LI ** push inbound doorbell tell iop, driver data write ok 1367a1103e04SXin LI ** and wait reply on next hwinterrupt for next Qbuffer post 1368a1103e04SXin LI */ 1369a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_WRITE_OK; 1370a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 1371a1103e04SXin LI } 1372a1103e04SXin LI break; 1373ad6d6297SScott Long } 1374f1c579b1SScott Long } 1375f1c579b1SScott Long /* 1376f1c579b1SScott Long ************************************************************************ 1377f1c579b1SScott Long ************************************************************************ 1378f1c579b1SScott Long */ 137944f05562SScott Long static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb) 1380f1c579b1SScott Long { 1381ad6d6297SScott Long acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 138244f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 138344f05562SScott Long 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 138444f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 1385d74001adSXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n" 1386ad6d6297SScott Long , acb->pci_unit); 1387ad6d6297SScott Long } 1388f1c579b1SScott Long } 1389f1c579b1SScott Long /* 1390f1c579b1SScott Long ************************************************************************ 1391f1c579b1SScott Long ************************************************************************ 1392f1c579b1SScott Long */ 139344f05562SScott Long static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb) 139444f05562SScott Long { 1395b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 139644f05562SScott Long acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 1397b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_STOP_BGRB); 139844f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 1399d74001adSXin LI printf( "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" 140044f05562SScott Long , acb->pci_unit); 140144f05562SScott Long } 140244f05562SScott Long } 140344f05562SScott Long /* 140444f05562SScott Long ************************************************************************ 140544f05562SScott Long ************************************************************************ 140644f05562SScott Long */ 1407d74001adSXin LI static void arcmsr_stop_hbc_bgrb(struct AdapterControlBlock *acb) 1408d74001adSXin LI { 1409d74001adSXin LI acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 1410d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 1411d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 1412d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 1413d74001adSXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit); 1414d74001adSXin LI } 1415d74001adSXin LI } 1416d74001adSXin LI /* 1417d74001adSXin LI ************************************************************************ 1418d74001adSXin LI ************************************************************************ 1419d74001adSXin LI */ 14207a7bc959SXin LI static void arcmsr_stop_hbd_bgrb(struct AdapterControlBlock *acb) 14217a7bc959SXin LI { 14227a7bc959SXin LI acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 14237a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 14247a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 14257a7bc959SXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit); 14267a7bc959SXin LI } 14277a7bc959SXin LI } 14287a7bc959SXin LI /* 14297a7bc959SXin LI ************************************************************************ 14307a7bc959SXin LI ************************************************************************ 14317a7bc959SXin LI */ 1432a1103e04SXin LI static void arcmsr_stop_hbe_bgrb(struct AdapterControlBlock *acb) 1433a1103e04SXin LI { 1434a1103e04SXin LI acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 1435a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 1436a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 1437a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 1438a1103e04SXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) { 1439a1103e04SXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit); 1440a1103e04SXin LI } 1441a1103e04SXin LI } 1442a1103e04SXin LI /* 1443a1103e04SXin LI ************************************************************************ 1444a1103e04SXin LI ************************************************************************ 1445a1103e04SXin LI */ 144644f05562SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) 144744f05562SScott Long { 144844f05562SScott Long switch (acb->adapter_type) { 144944f05562SScott Long case ACB_ADAPTER_TYPE_A: { 145044f05562SScott Long arcmsr_stop_hba_bgrb(acb); 145144f05562SScott Long } 145244f05562SScott Long break; 145344f05562SScott Long case ACB_ADAPTER_TYPE_B: { 145444f05562SScott Long arcmsr_stop_hbb_bgrb(acb); 145544f05562SScott Long } 145644f05562SScott Long break; 1457d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1458d74001adSXin LI arcmsr_stop_hbc_bgrb(acb); 1459d74001adSXin LI } 1460d74001adSXin LI break; 14617a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 14627a7bc959SXin LI arcmsr_stop_hbd_bgrb(acb); 14637a7bc959SXin LI } 14647a7bc959SXin LI break; 1465fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 1466fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 1467a1103e04SXin LI arcmsr_stop_hbe_bgrb(acb); 1468a1103e04SXin LI } 1469a1103e04SXin LI break; 147044f05562SScott Long } 147144f05562SScott Long } 147244f05562SScott Long /* 147344f05562SScott Long ************************************************************************ 147444f05562SScott Long ************************************************************************ 147544f05562SScott Long */ 1476ad6d6297SScott Long static void arcmsr_poll(struct cam_sim *psim) 1477f1c579b1SScott Long { 1478579ec1a5SScott Long struct AdapterControlBlock *acb; 14794e32649fSXin LI int mutex; 1480579ec1a5SScott Long 1481579ec1a5SScott Long acb = (struct AdapterControlBlock *)cam_sim_softc(psim); 14827a7bc959SXin LI mutex = mtx_owned(&acb->isr_lock); 14834e32649fSXin LI if( mutex == 0 ) 14847a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 1485579ec1a5SScott Long arcmsr_interrupt(acb); 14864e32649fSXin LI if( mutex == 0 ) 14877a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 14887a7bc959SXin LI } 14897a7bc959SXin LI /* 14907a7bc959SXin LI ************************************************************************** 14917a7bc959SXin LI ************************************************************************** 14927a7bc959SXin LI */ 149335689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data_D(struct AdapterControlBlock *acb, 149435689395SXin LI struct QBUFFER *prbuffer) { 149535689395SXin LI u_int8_t *pQbuffer; 14964d24901aSPedro F. Giffuni u_int8_t *buf1 = NULL; 14974d24901aSPedro F. Giffuni u_int32_t *iop_data, *buf2 = NULL; 149835689395SXin LI u_int32_t iop_len, data_len; 149935689395SXin LI 150035689395SXin LI iop_data = (u_int32_t *)prbuffer->data; 150135689395SXin LI iop_len = (u_int32_t)prbuffer->data_len; 150235689395SXin LI if ( iop_len > 0 ) 150335689395SXin LI { 150435689395SXin LI buf1 = malloc(128, M_DEVBUF, M_NOWAIT | M_ZERO); 150535689395SXin LI buf2 = (u_int32_t *)buf1; 150635689395SXin LI if( buf1 == NULL) 150735689395SXin LI return (0); 150835689395SXin LI data_len = iop_len; 150935689395SXin LI while(data_len >= 4) 151035689395SXin LI { 151135689395SXin LI *buf2++ = *iop_data++; 151235689395SXin LI data_len -= 4; 151335689395SXin LI } 151435689395SXin LI if(data_len) 151535689395SXin LI *buf2 = *iop_data; 151635689395SXin LI buf2 = (u_int32_t *)buf1; 151735689395SXin LI } 151835689395SXin LI while (iop_len > 0) { 151935689395SXin LI pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex]; 152035689395SXin LI *pQbuffer = *buf1; 152135689395SXin LI acb->rqbuf_lastindex++; 152235689395SXin LI /* if last, index number set it to 0 */ 152335689395SXin LI acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 152435689395SXin LI buf1++; 152535689395SXin LI iop_len--; 152635689395SXin LI } 152735689395SXin LI if(buf2) 152835689395SXin LI free( (u_int8_t *)buf2, M_DEVBUF); 152935689395SXin LI /* let IOP know data has been read */ 153035689395SXin LI arcmsr_iop_message_read(acb); 153135689395SXin LI return (1); 153235689395SXin LI } 153335689395SXin LI /* 153435689395SXin LI ************************************************************************** 153535689395SXin LI ************************************************************************** 153635689395SXin LI */ 153735689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, 15387a7bc959SXin LI struct QBUFFER *prbuffer) { 15397a7bc959SXin LI u_int8_t *pQbuffer; 15407a7bc959SXin LI u_int8_t *iop_data; 15417a7bc959SXin LI u_int32_t iop_len; 15427a7bc959SXin LI 1543fc5ef1caSXin LI if(acb->adapter_type >= ACB_ADAPTER_TYPE_B) { 154435689395SXin LI return(arcmsr_Read_iop_rqbuffer_data_D(acb, prbuffer)); 154535689395SXin LI } 15467a7bc959SXin LI iop_data = (u_int8_t *)prbuffer->data; 15477a7bc959SXin LI iop_len = (u_int32_t)prbuffer->data_len; 15487a7bc959SXin LI while (iop_len > 0) { 15497a7bc959SXin LI pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex]; 15507a7bc959SXin LI *pQbuffer = *iop_data; 15517a7bc959SXin LI acb->rqbuf_lastindex++; 15527a7bc959SXin LI /* if last, index number set it to 0 */ 15537a7bc959SXin LI acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 15547a7bc959SXin LI iop_data++; 15557a7bc959SXin LI iop_len--; 15567a7bc959SXin LI } 15577a7bc959SXin LI /* let IOP know data has been read */ 15587a7bc959SXin LI arcmsr_iop_message_read(acb); 155935689395SXin LI return (1); 1560f1c579b1SScott Long } 1561f1c579b1SScott Long /* 156244f05562SScott Long ************************************************************************** 156344f05562SScott Long ************************************************************************** 15645878cbecSScott Long */ 156544f05562SScott Long static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) 1566f1c579b1SScott Long { 156744f05562SScott Long struct QBUFFER *prbuffer; 15687a7bc959SXin LI int my_empty_len; 1569ad6d6297SScott Long 1570f1c579b1SScott Long /*check this iop data if overflow my rqbuffer*/ 15717a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 157244f05562SScott Long prbuffer = arcmsr_get_iop_rqbuffer(acb); 15737a7bc959SXin LI my_empty_len = (acb->rqbuf_lastindex - acb->rqbuf_firstindex - 1) & 15747a7bc959SXin LI (ARCMSR_MAX_QBUFFER-1); 15757a7bc959SXin LI if(my_empty_len >= prbuffer->data_len) { 157635689395SXin LI if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) 157735689395SXin LI acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 1578ad6d6297SScott Long } else { 1579ad6d6297SScott Long acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 1580f1c579b1SScott Long } 15817a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 15827a7bc959SXin LI } 15837a7bc959SXin LI /* 15847a7bc959SXin LI ********************************************************************** 15857a7bc959SXin LI ********************************************************************** 15867a7bc959SXin LI */ 158735689395SXin LI static void arcmsr_Write_data_2iop_wqbuffer_D(struct AdapterControlBlock *acb) 158835689395SXin LI { 158935689395SXin LI u_int8_t *pQbuffer; 159035689395SXin LI struct QBUFFER *pwbuffer; 15914d24901aSPedro F. Giffuni u_int8_t *buf1 = NULL; 15924d24901aSPedro F. Giffuni u_int32_t *iop_data, *buf2 = NULL; 159335689395SXin LI u_int32_t allxfer_len = 0, data_len; 159435689395SXin LI 159535689395SXin LI if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) { 159635689395SXin LI buf1 = malloc(128, M_DEVBUF, M_NOWAIT | M_ZERO); 159735689395SXin LI buf2 = (u_int32_t *)buf1; 159835689395SXin LI if( buf1 == NULL) 159935689395SXin LI return; 160035689395SXin LI 160135689395SXin LI acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 160235689395SXin LI pwbuffer = arcmsr_get_iop_wqbuffer(acb); 160335689395SXin LI iop_data = (u_int32_t *)pwbuffer->data; 160435689395SXin LI while((acb->wqbuf_firstindex != acb->wqbuf_lastindex) 160535689395SXin LI && (allxfer_len < 124)) { 160635689395SXin LI pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex]; 160735689395SXin LI *buf1 = *pQbuffer; 160835689395SXin LI acb->wqbuf_firstindex++; 160935689395SXin LI acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 161035689395SXin LI buf1++; 161135689395SXin LI allxfer_len++; 161235689395SXin LI } 161335689395SXin LI pwbuffer->data_len = allxfer_len; 161435689395SXin LI data_len = allxfer_len; 161535689395SXin LI buf1 = (u_int8_t *)buf2; 161635689395SXin LI while(data_len >= 4) 161735689395SXin LI { 161835689395SXin LI *iop_data++ = *buf2++; 161935689395SXin LI data_len -= 4; 162035689395SXin LI } 162135689395SXin LI if(data_len) 162235689395SXin LI *iop_data = *buf2; 162335689395SXin LI free( buf1, M_DEVBUF); 162435689395SXin LI arcmsr_iop_message_wrote(acb); 162535689395SXin LI } 162635689395SXin LI } 162735689395SXin LI /* 162835689395SXin LI ********************************************************************** 162935689395SXin LI ********************************************************************** 163035689395SXin LI */ 16317a7bc959SXin LI static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb) 16327a7bc959SXin LI { 16337a7bc959SXin LI u_int8_t *pQbuffer; 16347a7bc959SXin LI struct QBUFFER *pwbuffer; 16357a7bc959SXin LI u_int8_t *iop_data; 16367a7bc959SXin LI int32_t allxfer_len=0; 16377a7bc959SXin LI 1638fc5ef1caSXin LI if(acb->adapter_type >= ACB_ADAPTER_TYPE_B) { 163935689395SXin LI arcmsr_Write_data_2iop_wqbuffer_D(acb); 164035689395SXin LI return; 164135689395SXin LI } 16427a7bc959SXin LI if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) { 16437a7bc959SXin LI acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 16447a7bc959SXin LI pwbuffer = arcmsr_get_iop_wqbuffer(acb); 16457a7bc959SXin LI iop_data = (u_int8_t *)pwbuffer->data; 16467a7bc959SXin LI while((acb->wqbuf_firstindex != acb->wqbuf_lastindex) 16477a7bc959SXin LI && (allxfer_len < 124)) { 16487a7bc959SXin LI pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex]; 16497a7bc959SXin LI *iop_data = *pQbuffer; 16507a7bc959SXin LI acb->wqbuf_firstindex++; 16517a7bc959SXin LI acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 16527a7bc959SXin LI iop_data++; 16537a7bc959SXin LI allxfer_len++; 16547a7bc959SXin LI } 16557a7bc959SXin LI pwbuffer->data_len = allxfer_len; 16567a7bc959SXin LI arcmsr_iop_message_wrote(acb); 16577a7bc959SXin LI } 1658f1c579b1SScott Long } 1659f1c579b1SScott Long /* 166044f05562SScott Long ************************************************************************** 166144f05562SScott Long ************************************************************************** 166244f05562SScott Long */ 166344f05562SScott Long static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) 166444f05562SScott Long { 16657a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 166644f05562SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READ; 166744f05562SScott Long /* 166844f05562SScott Long ***************************************************************** 166944f05562SScott Long ** check if there are any mail packages from user space program 167044f05562SScott Long ** in my post bag, now is the time to send them into Areca's firmware 167144f05562SScott Long ***************************************************************** 1672f1c579b1SScott Long */ 1673ad6d6297SScott Long if(acb->wqbuf_firstindex != acb->wqbuf_lastindex) { 16747a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 1675f1c579b1SScott Long } 1676ad6d6297SScott Long if(acb->wqbuf_firstindex == acb->wqbuf_lastindex) { 1677ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; 1678f1c579b1SScott Long } 16797a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1680f1c579b1SScott Long } 16817a7bc959SXin LI /* 16827a7bc959SXin LI ************************************************************************** 16837a7bc959SXin LI ************************************************************************** 16847a7bc959SXin LI */ 1685d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb) 1686d74001adSXin LI { 1687d74001adSXin LI /* 1688d74001adSXin LI if (ccb->ccb_h.status != CAM_REQ_CMP) 16897a7bc959SXin LI printf("arcmsr_rescanLun_cb: Rescan Target=%x, lun=%x," 16907a7bc959SXin LI "failure status=%x\n", ccb->ccb_h.target_id, 16917a7bc959SXin LI ccb->ccb_h.target_lun, ccb->ccb_h.status); 1692d74001adSXin LI else 1693d74001adSXin LI printf("arcmsr_rescanLun_cb: Rescan lun successfully!\n"); 1694d74001adSXin LI */ 1695d74001adSXin LI xpt_free_path(ccb->ccb_h.path); 1696d74001adSXin LI xpt_free_ccb(ccb); 1697d74001adSXin LI } 1698d74001adSXin LI 1699d74001adSXin LI static void arcmsr_rescan_lun(struct AdapterControlBlock *acb, int target, int lun) 1700d74001adSXin LI { 1701d74001adSXin LI struct cam_path *path; 1702d74001adSXin LI union ccb *ccb; 1703d74001adSXin LI 1704d74001adSXin LI if ((ccb = (union ccb *)xpt_alloc_ccb_nowait()) == NULL) 1705d74001adSXin LI return; 1706abfdbca9SXin LI if (xpt_create_path(&path, NULL, cam_sim_path(acb->psim), target, lun) != CAM_REQ_CMP) 1707d74001adSXin LI { 1708d74001adSXin LI xpt_free_ccb(ccb); 1709d74001adSXin LI return; 1710d74001adSXin LI } 1711d74001adSXin LI /* printf("arcmsr_rescan_lun: Rescan Target=%x, Lun=%x\n", target, lun); */ 1712d74001adSXin LI xpt_setup_ccb(&ccb->ccb_h, path, 5); 1713d74001adSXin LI ccb->ccb_h.func_code = XPT_SCAN_LUN; 1714d74001adSXin LI ccb->ccb_h.cbfcnp = arcmsr_rescanLun_cb; 1715d74001adSXin LI ccb->crcn.flags = CAM_FLAG_NONE; 1716d74001adSXin LI xpt_action(ccb); 1717d74001adSXin LI } 1718d74001adSXin LI 1719d74001adSXin LI static void arcmsr_abort_dr_ccbs(struct AdapterControlBlock *acb, int target, int lun) 1720d74001adSXin LI { 1721d74001adSXin LI struct CommandControlBlock *srb; 1722d74001adSXin LI u_int32_t intmask_org; 1723d74001adSXin LI int i; 1724d74001adSXin LI 1725d74001adSXin LI /* disable all outbound interrupts */ 1726d74001adSXin LI intmask_org = arcmsr_disable_allintr(acb); 1727d74001adSXin LI for (i = 0; i < ARCMSR_MAX_FREESRB_NUM; i++) 1728d74001adSXin LI { 1729d74001adSXin LI srb = acb->psrb_pool[i]; 173022f2616bSXin LI if (srb->srb_state == ARCMSR_SRB_START) 1731d74001adSXin LI { 1732d74001adSXin LI if((target == srb->pccb->ccb_h.target_id) && (lun == srb->pccb->ccb_h.target_lun)) 1733d74001adSXin LI { 173422f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 1735d74001adSXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 1736d74001adSXin LI arcmsr_srb_complete(srb, 1); 173722f2616bSXin LI printf("arcmsr%d: abort scsi id %d lun %d srb=%p \n", acb->pci_unit, target, lun, srb); 1738d74001adSXin LI } 1739d74001adSXin LI } 1740d74001adSXin LI } 1741d74001adSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 1742d74001adSXin LI arcmsr_enable_allintr(acb, intmask_org); 1743d74001adSXin LI } 1744d74001adSXin LI /* 1745d74001adSXin LI ************************************************************************** 1746d74001adSXin LI ************************************************************************** 1747d74001adSXin LI */ 1748d74001adSXin LI static void arcmsr_dr_handle(struct AdapterControlBlock *acb) { 1749d74001adSXin LI u_int32_t devicemap; 1750d74001adSXin LI u_int32_t target, lun; 1751d74001adSXin LI u_int32_t deviceMapCurrent[4]={0}; 1752d74001adSXin LI u_int8_t *pDevMap; 1753d74001adSXin LI 1754d74001adSXin LI switch (acb->adapter_type) { 1755d74001adSXin LI case ACB_ADAPTER_TYPE_A: 1756d74001adSXin LI devicemap = offsetof(struct HBA_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1757d74001adSXin LI for (target = 0; target < 4; target++) 1758d74001adSXin LI { 1759d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1760d74001adSXin LI devicemap += 4; 1761d74001adSXin LI } 1762d74001adSXin LI break; 1763d74001adSXin LI 1764d74001adSXin LI case ACB_ADAPTER_TYPE_B: 1765d74001adSXin LI devicemap = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1766d74001adSXin LI for (target = 0; target < 4; target++) 1767d74001adSXin LI { 1768d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[1], acb->bhandle[1], devicemap); 1769d74001adSXin LI devicemap += 4; 1770d74001adSXin LI } 1771d74001adSXin LI break; 1772d74001adSXin LI 1773d74001adSXin LI case ACB_ADAPTER_TYPE_C: 1774d74001adSXin LI devicemap = offsetof(struct HBC_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1775d74001adSXin LI for (target = 0; target < 4; target++) 1776d74001adSXin LI { 1777d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1778d74001adSXin LI devicemap += 4; 1779d74001adSXin LI } 1780d74001adSXin LI break; 17817a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 17827a7bc959SXin LI devicemap = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 17837a7bc959SXin LI for (target = 0; target < 4; target++) 17847a7bc959SXin LI { 17857a7bc959SXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 17867a7bc959SXin LI devicemap += 4; 17877a7bc959SXin LI } 17887a7bc959SXin LI break; 1789a1103e04SXin LI case ACB_ADAPTER_TYPE_E: 1790a1103e04SXin LI devicemap = offsetof(struct HBE_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1791a1103e04SXin LI for (target = 0; target < 4; target++) 1792a1103e04SXin LI { 1793a1103e04SXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1794a1103e04SXin LI devicemap += 4; 1795a1103e04SXin LI } 1796a1103e04SXin LI break; 1797fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 1798fa42a0bfSXin LI devicemap = ARCMSR_FW_DEVMAP_OFFSET; 1799fa42a0bfSXin LI for (target = 0; target < 4; target++) 1800fa42a0bfSXin LI { 1801fa42a0bfSXin LI deviceMapCurrent[target] = acb->msgcode_rwbuffer[devicemap]; 1802fa42a0bfSXin LI devicemap += 1; 1803fa42a0bfSXin LI } 1804fa42a0bfSXin LI break; 1805d74001adSXin LI } 1806dac36688SXin LI 1807d74001adSXin LI if(acb->acb_flags & ACB_F_BUS_HANG_ON) 1808d74001adSXin LI { 1809d74001adSXin LI acb->acb_flags &= ~ACB_F_BUS_HANG_ON; 1810d74001adSXin LI } 1811d74001adSXin LI /* 1812d74001adSXin LI ** adapter posted CONFIG message 1813d74001adSXin LI ** copy the new map, note if there are differences with the current map 1814d74001adSXin LI */ 1815d74001adSXin LI pDevMap = (u_int8_t *)&deviceMapCurrent[0]; 1816d74001adSXin LI for (target = 0; target < ARCMSR_MAX_TARGETID - 1; target++) 1817d74001adSXin LI { 1818d74001adSXin LI if (*pDevMap != acb->device_map[target]) 1819d74001adSXin LI { 1820d74001adSXin LI u_int8_t difference, bit_check; 1821d74001adSXin LI 1822d74001adSXin LI difference = *pDevMap ^ acb->device_map[target]; 1823d74001adSXin LI for(lun=0; lun < ARCMSR_MAX_TARGETLUN; lun++) 1824d74001adSXin LI { 1825d74001adSXin LI bit_check = (1 << lun); /*check bit from 0....31*/ 1826d74001adSXin LI if(difference & bit_check) 1827d74001adSXin LI { 1828d74001adSXin LI if(acb->device_map[target] & bit_check) 1829d74001adSXin LI {/* unit departed */ 1830d74001adSXin LI printf("arcmsr_dr_handle: Target=%x, lun=%x, GONE!!!\n",target,lun); 1831d74001adSXin LI arcmsr_abort_dr_ccbs(acb, target, lun); 1832d74001adSXin LI arcmsr_rescan_lun(acb, target, lun); 1833d74001adSXin LI acb->devstate[target][lun] = ARECA_RAID_GONE; 1834d74001adSXin LI } 1835d74001adSXin LI else 1836d74001adSXin LI {/* unit arrived */ 183722f2616bSXin LI printf("arcmsr_dr_handle: Target=%x, lun=%x, Plug-IN!!!\n",target,lun); 1838d74001adSXin LI arcmsr_rescan_lun(acb, target, lun); 1839d74001adSXin LI acb->devstate[target][lun] = ARECA_RAID_GOOD; 1840d74001adSXin LI } 1841d74001adSXin LI } 1842d74001adSXin LI } 1843d74001adSXin LI /* printf("arcmsr_dr_handle: acb->device_map[%x]=0x%x, deviceMapCurrent[%x]=%x\n",target,acb->device_map[target],target,*pDevMap); */ 1844d74001adSXin LI acb->device_map[target] = *pDevMap; 1845d74001adSXin LI } 1846d74001adSXin LI pDevMap++; 1847d74001adSXin LI } 1848d74001adSXin LI } 1849d74001adSXin LI /* 1850d74001adSXin LI ************************************************************************** 1851d74001adSXin LI ************************************************************************** 1852d74001adSXin LI */ 1853d74001adSXin LI static void arcmsr_hba_message_isr(struct AdapterControlBlock *acb) { 1854d74001adSXin LI u_int32_t outbound_message; 1855d74001adSXin LI 1856d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT); 1857d74001adSXin LI outbound_message = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[0]); 1858d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1859d74001adSXin LI arcmsr_dr_handle( acb ); 1860d74001adSXin LI } 1861d74001adSXin LI /* 1862d74001adSXin LI ************************************************************************** 1863d74001adSXin LI ************************************************************************** 1864d74001adSXin LI */ 1865d74001adSXin LI static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) { 1866d74001adSXin LI u_int32_t outbound_message; 1867b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 1868d74001adSXin LI 1869d74001adSXin LI /* clear interrupts */ 1870b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN); 1871d74001adSXin LI outbound_message = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0]); 1872d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1873d74001adSXin LI arcmsr_dr_handle( acb ); 1874d74001adSXin LI } 1875d74001adSXin LI /* 1876d74001adSXin LI ************************************************************************** 1877d74001adSXin LI ************************************************************************** 1878d74001adSXin LI */ 1879d74001adSXin LI static void arcmsr_hbc_message_isr(struct AdapterControlBlock *acb) { 1880d74001adSXin LI u_int32_t outbound_message; 1881d74001adSXin LI 1882d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR); 1883d74001adSXin LI outbound_message = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[0]); 1884d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1885d74001adSXin LI arcmsr_dr_handle( acb ); 1886d74001adSXin LI } 188744f05562SScott Long /* 188844f05562SScott Long ************************************************************************** 188944f05562SScott Long ************************************************************************** 189044f05562SScott Long */ 18917a7bc959SXin LI static void arcmsr_hbd_message_isr(struct AdapterControlBlock *acb) { 18927a7bc959SXin LI u_int32_t outbound_message; 18937a7bc959SXin LI 18947a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR); 18957a7bc959SXin LI outbound_message = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[0]); 18967a7bc959SXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 18977a7bc959SXin LI arcmsr_dr_handle( acb ); 18987a7bc959SXin LI } 18997a7bc959SXin LI /* 19007a7bc959SXin LI ************************************************************************** 19017a7bc959SXin LI ************************************************************************** 19027a7bc959SXin LI */ 1903a1103e04SXin LI static void arcmsr_hbe_message_isr(struct AdapterControlBlock *acb) { 1904a1103e04SXin LI u_int32_t outbound_message; 1905a1103e04SXin LI 1906a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); 19075842073aSXin LI if (acb->adapter_type == ACB_ADAPTER_TYPE_E) 1908a1103e04SXin LI outbound_message = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[0]); 19095842073aSXin LI else 19105842073aSXin LI outbound_message = acb->msgcode_rwbuffer[0]; 1911a1103e04SXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1912a1103e04SXin LI arcmsr_dr_handle( acb ); 1913a1103e04SXin LI } 1914a1103e04SXin LI /* 1915a1103e04SXin LI ************************************************************************** 1916a1103e04SXin LI ************************************************************************** 1917a1103e04SXin LI */ 191844f05562SScott Long static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) 191944f05562SScott Long { 1920224a78aeSXin LI u_int32_t doorbell_status; 192144f05562SScott Long 192244f05562SScott Long /* 192344f05562SScott Long ******************************************************************* 192444f05562SScott Long ** Maybe here we need to check wrqbuffer_lock is lock or not 192544f05562SScott Long ** DOORBELL: din! don! 192644f05562SScott Long ** check if there are any mail need to pack from firmware 192744f05562SScott Long ******************************************************************* 192844f05562SScott Long */ 1929224a78aeSXin LI doorbell_status = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell); 1930224a78aeSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */ 1931224a78aeSXin LI if(doorbell_status & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { 193244f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 1933ad6d6297SScott Long } 1934224a78aeSXin LI if(doorbell_status & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { 193544f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 193644f05562SScott Long } 193744f05562SScott Long } 193844f05562SScott Long /* 193944f05562SScott Long ************************************************************************** 194044f05562SScott Long ************************************************************************** 194144f05562SScott Long */ 1942d74001adSXin LI static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb) 1943d74001adSXin LI { 1944224a78aeSXin LI u_int32_t doorbell_status; 1945d74001adSXin LI 1946d74001adSXin LI /* 1947d74001adSXin LI ******************************************************************* 1948d74001adSXin LI ** Maybe here we need to check wrqbuffer_lock is lock or not 1949d74001adSXin LI ** DOORBELL: din! don! 1950d74001adSXin LI ** check if there are any mail need to pack from firmware 1951d74001adSXin LI ******************************************************************* 1952d74001adSXin LI */ 1953224a78aeSXin LI doorbell_status = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); 1954224a78aeSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, doorbell_status); /* clear doorbell interrupt */ 1955224a78aeSXin LI if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) { 1956d74001adSXin LI arcmsr_iop2drv_data_wrote_handle(acb); 1957d74001adSXin LI } 1958224a78aeSXin LI if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) { 1959d74001adSXin LI arcmsr_iop2drv_data_read_handle(acb); 1960d74001adSXin LI } 1961224a78aeSXin LI if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { 1962d74001adSXin LI arcmsr_hbc_message_isr(acb); /* messenger of "driver to iop commands" */ 1963d74001adSXin LI } 1964d74001adSXin LI } 1965d74001adSXin LI /* 1966d74001adSXin LI ************************************************************************** 1967d74001adSXin LI ************************************************************************** 1968d74001adSXin LI */ 19697a7bc959SXin LI static void arcmsr_hbd_doorbell_isr(struct AdapterControlBlock *acb) 19707a7bc959SXin LI { 1971224a78aeSXin LI u_int32_t doorbell_status; 19727a7bc959SXin LI 19737a7bc959SXin LI /* 19747a7bc959SXin LI ******************************************************************* 19757a7bc959SXin LI ** Maybe here we need to check wrqbuffer_lock is lock or not 19767a7bc959SXin LI ** DOORBELL: din! don! 19777a7bc959SXin LI ** check if there are any mail need to pack from firmware 19787a7bc959SXin LI ******************************************************************* 19797a7bc959SXin LI */ 1980224a78aeSXin LI doorbell_status = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE; 1981224a78aeSXin LI if(doorbell_status) 1982224a78aeSXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */ 1983224a78aeSXin LI while( doorbell_status & ARCMSR_HBDMU_F0_DOORBELL_CAUSE ) { 1984224a78aeSXin LI if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_DATA_WRITE_OK) { 19857a7bc959SXin LI arcmsr_iop2drv_data_wrote_handle(acb); 19867a7bc959SXin LI } 1987224a78aeSXin LI if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_DATA_READ_OK) { 19887a7bc959SXin LI arcmsr_iop2drv_data_read_handle(acb); 19897a7bc959SXin LI } 1990224a78aeSXin LI if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) { 19917a7bc959SXin LI arcmsr_hbd_message_isr(acb); /* messenger of "driver to iop commands" */ 19927a7bc959SXin LI } 1993224a78aeSXin LI doorbell_status = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE; 1994224a78aeSXin LI if(doorbell_status) 1995224a78aeSXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */ 19967a7bc959SXin LI } 19977a7bc959SXin LI } 19987a7bc959SXin LI /* 19997a7bc959SXin LI ************************************************************************** 20007a7bc959SXin LI ************************************************************************** 20017a7bc959SXin LI */ 2002a1103e04SXin LI static void arcmsr_hbe_doorbell_isr(struct AdapterControlBlock *acb) 2003a1103e04SXin LI { 2004a1103e04SXin LI u_int32_t doorbell_status, in_doorbell; 2005a1103e04SXin LI 2006a1103e04SXin LI /* 2007a1103e04SXin LI ******************************************************************* 2008a1103e04SXin LI ** Maybe here we need to check wrqbuffer_lock is lock or not 2009a1103e04SXin LI ** DOORBELL: din! don! 2010a1103e04SXin LI ** check if there are any mail need to pack from firmware 2011a1103e04SXin LI ******************************************************************* 2012a1103e04SXin LI */ 2013a1103e04SXin LI in_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell); 2014a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /* clear doorbell interrupt */ 2015a1103e04SXin LI doorbell_status = in_doorbell ^ acb->in_doorbell; 2016a1103e04SXin LI if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_WRITE_OK) { 2017a1103e04SXin LI arcmsr_iop2drv_data_wrote_handle(acb); 2018a1103e04SXin LI } 2019a1103e04SXin LI if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_READ_OK) { 2020a1103e04SXin LI arcmsr_iop2drv_data_read_handle(acb); 2021a1103e04SXin LI } 2022a1103e04SXin LI if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) { 2023a1103e04SXin LI arcmsr_hbe_message_isr(acb); /* messenger of "driver to iop commands" */ 2024a1103e04SXin LI } 2025a1103e04SXin LI acb->in_doorbell = in_doorbell; 2026a1103e04SXin LI } 2027a1103e04SXin LI /* 2028a1103e04SXin LI ************************************************************************** 2029a1103e04SXin LI ************************************************************************** 2030a1103e04SXin LI */ 203144f05562SScott Long static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb) 203244f05562SScott Long { 203344f05562SScott Long u_int32_t flag_srb; 2034d74001adSXin LI u_int16_t error; 203544f05562SScott Long 2036f1c579b1SScott Long /* 2037f1c579b1SScott Long ***************************************************************************** 2038f1c579b1SScott Long ** areca cdb command done 2039f1c579b1SScott Long ***************************************************************************** 2040f1c579b1SScott Long */ 204144f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 204244f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 204344f05562SScott Long while((flag_srb = CHIP_REG_READ32(HBA_MessageUnit, 204444f05562SScott Long 0, outbound_queueport)) != 0xFFFFFFFF) { 2045f1c579b1SScott Long /* check if command done with no error*/ 2046d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0) ? TRUE : FALSE; 2047d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 204844f05562SScott Long } /*drain reply FIFO*/ 2049f1c579b1SScott Long } 205044f05562SScott Long /* 205144f05562SScott Long ************************************************************************** 205244f05562SScott Long ************************************************************************** 205344f05562SScott Long */ 205444f05562SScott Long static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) 205544f05562SScott Long { 205644f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 205744f05562SScott Long u_int32_t flag_srb; 205844f05562SScott Long int index; 2059d74001adSXin LI u_int16_t error; 206044f05562SScott Long 206144f05562SScott Long /* 206244f05562SScott Long ***************************************************************************** 206344f05562SScott Long ** areca cdb command done 206444f05562SScott Long ***************************************************************************** 206544f05562SScott Long */ 206644f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 206744f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 206844f05562SScott Long index = phbbmu->doneq_index; 206944f05562SScott Long while((flag_srb = phbbmu->done_qbuffer[index]) != 0) { 207044f05562SScott Long phbbmu->done_qbuffer[index] = 0; 207144f05562SScott Long index++; 207244f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 207344f05562SScott Long phbbmu->doneq_index = index; 207444f05562SScott Long /* check if command done with no error*/ 2075d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 2076d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 2077d74001adSXin LI } /*drain reply FIFO*/ 2078d74001adSXin LI } 2079d74001adSXin LI /* 2080d74001adSXin LI ************************************************************************** 2081d74001adSXin LI ************************************************************************** 2082d74001adSXin LI */ 2083d74001adSXin LI static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb) 2084d74001adSXin LI { 2085d74001adSXin LI u_int32_t flag_srb,throttling = 0; 2086d74001adSXin LI u_int16_t error; 2087d74001adSXin LI 2088d74001adSXin LI /* 2089d74001adSXin LI ***************************************************************************** 2090d74001adSXin LI ** areca cdb command done 2091d74001adSXin LI ***************************************************************************** 2092d74001adSXin LI */ 2093d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2094224a78aeSXin LI do { 2095d74001adSXin LI flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 2096b23a1998SXin LI if (flag_srb == 0xFFFFFFFF) 2097b23a1998SXin LI break; 2098d74001adSXin LI /* check if command done with no error*/ 2099d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; 2100d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 2101abfdbca9SXin LI throttling++; 2102d74001adSXin LI if(throttling == ARCMSR_HBC_ISR_THROTTLING_LEVEL) { 2103d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING); 2104abfdbca9SXin LI throttling = 0; 2105d74001adSXin LI } 2106224a78aeSXin LI } while(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR); 2107f1c579b1SScott Long } 210844f05562SScott Long /* 210944f05562SScott Long ********************************************************************** 21107a7bc959SXin LI ** 21117a7bc959SXin LI ********************************************************************** 21127a7bc959SXin LI */ 21137a7bc959SXin LI static uint16_t arcmsr_get_doneq_index(struct HBD_MessageUnit0 *phbdmu) 21147a7bc959SXin LI { 21157a7bc959SXin LI uint16_t doneq_index, index_stripped; 21167a7bc959SXin LI 21177a7bc959SXin LI doneq_index = phbdmu->doneq_index; 21187a7bc959SXin LI if (doneq_index & 0x4000) { 21197a7bc959SXin LI index_stripped = doneq_index & 0xFF; 21207a7bc959SXin LI index_stripped += 1; 21217a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 21227a7bc959SXin LI phbdmu->doneq_index = index_stripped ? 21237a7bc959SXin LI (index_stripped | 0x4000) : index_stripped; 21247a7bc959SXin LI } else { 21257a7bc959SXin LI index_stripped = doneq_index; 21267a7bc959SXin LI index_stripped += 1; 21277a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 21287a7bc959SXin LI phbdmu->doneq_index = index_stripped ? 21297a7bc959SXin LI index_stripped : (index_stripped | 0x4000); 21307a7bc959SXin LI } 21317a7bc959SXin LI return (phbdmu->doneq_index); 21327a7bc959SXin LI } 21337a7bc959SXin LI /* 21347a7bc959SXin LI ************************************************************************** 21357a7bc959SXin LI ************************************************************************** 21367a7bc959SXin LI */ 21377a7bc959SXin LI static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb) 21387a7bc959SXin LI { 21397a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 21407a7bc959SXin LI u_int32_t outbound_write_pointer; 21417a7bc959SXin LI u_int32_t addressLow; 21427a7bc959SXin LI uint16_t doneq_index; 21437a7bc959SXin LI u_int16_t error; 21447a7bc959SXin LI /* 21457a7bc959SXin LI ***************************************************************************** 21467a7bc959SXin LI ** areca cdb command done 21477a7bc959SXin LI ***************************************************************************** 21487a7bc959SXin LI */ 21497a7bc959SXin LI if((CHIP_REG_READ32(HBD_MessageUnit, 0, outboundlist_interrupt_cause) & 21507a7bc959SXin LI ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT) == 0) 21517a7bc959SXin LI return; 21527a7bc959SXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 21537a7bc959SXin LI BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 21547a7bc959SXin LI outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow; 21557a7bc959SXin LI doneq_index = phbdmu->doneq_index; 21567a7bc959SXin LI while ((doneq_index & 0xFF) != (outbound_write_pointer & 0xFF)) { 21577a7bc959SXin LI doneq_index = arcmsr_get_doneq_index(phbdmu); 21587a7bc959SXin LI addressLow = phbdmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow; 21597a7bc959SXin LI error = (addressLow & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 21607a7bc959SXin LI arcmsr_drain_donequeue(acb, addressLow, error); /*Check if command done with no error */ 21617a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_read_pointer, doneq_index); 21627a7bc959SXin LI outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow; 21637a7bc959SXin LI } 21647a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_interrupt_cause, ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT_CLEAR); 21657a7bc959SXin LI CHIP_REG_READ32(HBD_MessageUnit, 0, outboundlist_interrupt_cause); /*Dummy ioread32 to force pci flush */ 21667a7bc959SXin LI } 21677a7bc959SXin LI /* 2168a1103e04SXin LI ************************************************************************** 2169a1103e04SXin LI ************************************************************************** 2170a1103e04SXin LI */ 2171a1103e04SXin LI static void arcmsr_hbe_postqueue_isr(struct AdapterControlBlock *acb) 2172a1103e04SXin LI { 2173a1103e04SXin LI u_int16_t error; 2174a1103e04SXin LI uint32_t doneq_index; 2175a1103e04SXin LI uint16_t cmdSMID; 2176a1103e04SXin LI 2177a1103e04SXin LI /* 2178a1103e04SXin LI ***************************************************************************** 2179a1103e04SXin LI ** areca cdb command done 2180a1103e04SXin LI ***************************************************************************** 2181a1103e04SXin LI */ 2182a1103e04SXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2183a1103e04SXin LI doneq_index = acb->doneq_index; 2184a1103e04SXin LI while ((CHIP_REG_READ32(HBE_MessageUnit, 0, reply_post_producer_index) & 0xFFFF) != doneq_index) { 2185a1103e04SXin LI cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID; 2186a1103e04SXin LI error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 2187a1103e04SXin LI arcmsr_drain_donequeue(acb, (u_int32_t)cmdSMID, error); 2188a1103e04SXin LI doneq_index++; 2189a1103e04SXin LI if (doneq_index >= acb->completionQ_entry) 2190a1103e04SXin LI doneq_index = 0; 2191a1103e04SXin LI } 2192a1103e04SXin LI acb->doneq_index = doneq_index; 2193a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, reply_post_consumer_index, doneq_index); 2194a1103e04SXin LI } 2195fa42a0bfSXin LI 2196fa42a0bfSXin LI static void arcmsr_hbf_postqueue_isr(struct AdapterControlBlock *acb) 2197fa42a0bfSXin LI { 2198fa42a0bfSXin LI uint16_t error; 2199fa42a0bfSXin LI uint32_t doneq_index; 2200fa42a0bfSXin LI uint16_t cmdSMID; 2201fa42a0bfSXin LI 2202fa42a0bfSXin LI /* 2203fa42a0bfSXin LI ***************************************************************************** 2204fa42a0bfSXin LI ** areca cdb command done 2205fa42a0bfSXin LI ***************************************************************************** 2206fa42a0bfSXin LI */ 2207fa42a0bfSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2208fa42a0bfSXin LI doneq_index = acb->doneq_index; 2209fa42a0bfSXin LI while (1) { 2210fa42a0bfSXin LI cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID; 2211fa42a0bfSXin LI if (cmdSMID == 0xffff) 2212fa42a0bfSXin LI break; 2213fa42a0bfSXin LI error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 2214fa42a0bfSXin LI arcmsr_drain_donequeue(acb, (u_int32_t)cmdSMID, error); 2215fa42a0bfSXin LI acb->pCompletionQ[doneq_index].cmdSMID = 0xffff; 2216fa42a0bfSXin LI doneq_index++; 2217fa42a0bfSXin LI if (doneq_index >= acb->completionQ_entry) 2218fa42a0bfSXin LI doneq_index = 0; 2219fa42a0bfSXin LI } 2220fa42a0bfSXin LI acb->doneq_index = doneq_index; 2221fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, reply_post_consumer_index, doneq_index); 2222fa42a0bfSXin LI } 2223fa42a0bfSXin LI 2224a1103e04SXin LI /* 22257a7bc959SXin LI ********************************************************************** 222644f05562SScott Long ********************************************************************** 222744f05562SScott Long */ 222844f05562SScott Long static void arcmsr_handle_hba_isr( struct AdapterControlBlock *acb) 222944f05562SScott Long { 2230dac36688SXin LI u_int32_t outbound_intStatus; 223144f05562SScott Long /* 223244f05562SScott Long ********************************************* 223344f05562SScott Long ** check outbound intstatus 223444f05562SScott Long ********************************************* 223544f05562SScott Long */ 2236dac36688SXin LI outbound_intStatus = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 2237dac36688SXin LI if(!outbound_intStatus) { 223844f05562SScott Long /*it must be share irq*/ 223944f05562SScott Long return; 2240f1c579b1SScott Long } 2241dac36688SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intStatus); /*clear interrupt*/ 224244f05562SScott Long /* MU doorbell interrupts*/ 2243dac36688SXin LI if(outbound_intStatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) { 224444f05562SScott Long arcmsr_hba_doorbell_isr(acb); 2245f1c579b1SScott Long } 224644f05562SScott Long /* MU post queue interrupts*/ 2247dac36688SXin LI if(outbound_intStatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { 224844f05562SScott Long arcmsr_hba_postqueue_isr(acb); 224944f05562SScott Long } 2250dac36688SXin LI if(outbound_intStatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { 2251d74001adSXin LI arcmsr_hba_message_isr(acb); 2252d74001adSXin LI } 225344f05562SScott Long } 225444f05562SScott Long /* 225544f05562SScott Long ********************************************************************** 225644f05562SScott Long ********************************************************************** 225744f05562SScott Long */ 225844f05562SScott Long static void arcmsr_handle_hbb_isr( struct AdapterControlBlock *acb) 225944f05562SScott Long { 226044f05562SScott Long u_int32_t outbound_doorbell; 2261b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 226244f05562SScott Long /* 226344f05562SScott Long ********************************************* 226444f05562SScott Long ** check outbound intstatus 226544f05562SScott Long ********************************************* 226644f05562SScott Long */ 2267b23a1998SXin LI outbound_doorbell = READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & acb->outbound_int_enable; 226844f05562SScott Long if(!outbound_doorbell) { 226944f05562SScott Long /*it must be share irq*/ 227044f05562SScott Long return; 227144f05562SScott Long } 2272b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ~outbound_doorbell); /* clear doorbell interrupt */ 2273b23a1998SXin LI READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell); 2274b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 227544f05562SScott Long /* MU ioctl transfer doorbell interrupts*/ 227644f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { 227744f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 227844f05562SScott Long } 227944f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) { 228044f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 228144f05562SScott Long } 228244f05562SScott Long /* MU post queue interrupts*/ 228344f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) { 228444f05562SScott Long arcmsr_hbb_postqueue_isr(acb); 228544f05562SScott Long } 2286d74001adSXin LI if(outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { 2287d74001adSXin LI arcmsr_hbb_message_isr(acb); 2288d74001adSXin LI } 2289d74001adSXin LI } 2290d74001adSXin LI /* 2291d74001adSXin LI ********************************************************************** 2292d74001adSXin LI ********************************************************************** 2293d74001adSXin LI */ 2294d74001adSXin LI static void arcmsr_handle_hbc_isr( struct AdapterControlBlock *acb) 2295d74001adSXin LI { 2296d74001adSXin LI u_int32_t host_interrupt_status; 2297d74001adSXin LI /* 2298d74001adSXin LI ********************************************* 2299d74001adSXin LI ** check outbound intstatus 2300d74001adSXin LI ********************************************* 2301d74001adSXin LI */ 2302224a78aeSXin LI host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & 2303224a78aeSXin LI (ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR | 2304224a78aeSXin LI ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR); 2305d74001adSXin LI if(!host_interrupt_status) { 2306d74001adSXin LI /*it must be share irq*/ 2307d74001adSXin LI return; 2308d74001adSXin LI } 2309224a78aeSXin LI do { 2310d74001adSXin LI /* MU doorbell interrupts*/ 2311d74001adSXin LI if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) { 2312d74001adSXin LI arcmsr_hbc_doorbell_isr(acb); 2313d74001adSXin LI } 2314d74001adSXin LI /* MU post queue interrupts*/ 2315d74001adSXin LI if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) { 2316d74001adSXin LI arcmsr_hbc_postqueue_isr(acb); 2317d74001adSXin LI } 2318224a78aeSXin LI host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status); 2319224a78aeSXin LI } while (host_interrupt_status & (ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR)); 232044f05562SScott Long } 232144f05562SScott Long /* 23227a7bc959SXin LI ********************************************************************** 23237a7bc959SXin LI ********************************************************************** 23247a7bc959SXin LI */ 23257a7bc959SXin LI static void arcmsr_handle_hbd_isr( struct AdapterControlBlock *acb) 23267a7bc959SXin LI { 23277a7bc959SXin LI u_int32_t host_interrupt_status; 23287a7bc959SXin LI u_int32_t intmask_org; 23297a7bc959SXin LI /* 23307a7bc959SXin LI ********************************************* 23317a7bc959SXin LI ** check outbound intstatus 23327a7bc959SXin LI ********************************************* 23337a7bc959SXin LI */ 23347a7bc959SXin LI host_interrupt_status = CHIP_REG_READ32(HBD_MessageUnit, 0, host_int_status) & acb->outbound_int_enable; 23357a7bc959SXin LI if(!(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_INT)) { 23367a7bc959SXin LI /*it must be share irq*/ 23377a7bc959SXin LI return; 23387a7bc959SXin LI } 23397a7bc959SXin LI /* disable outbound interrupt */ 23407a7bc959SXin LI intmask_org = CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable) ; /* disable outbound message0 int */ 23417a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, ARCMSR_HBDMU_ALL_INT_DISABLE); 23427a7bc959SXin LI /* MU doorbell interrupts*/ 23437a7bc959SXin LI if(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_DOORBELL_INT) { 23447a7bc959SXin LI arcmsr_hbd_doorbell_isr(acb); 23457a7bc959SXin LI } 23467a7bc959SXin LI /* MU post queue interrupts*/ 23477a7bc959SXin LI if(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_POSTQUEUE_INT) { 23487a7bc959SXin LI arcmsr_hbd_postqueue_isr(acb); 23497a7bc959SXin LI } 23507a7bc959SXin LI /* enable all outbound interrupt */ 23517a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, intmask_org | ARCMSR_HBDMU_ALL_INT_ENABLE); 23527a7bc959SXin LI // CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable); 23537a7bc959SXin LI } 23547a7bc959SXin LI /* 2355a1103e04SXin LI ********************************************************************** 2356a1103e04SXin LI ********************************************************************** 2357a1103e04SXin LI */ 2358a1103e04SXin LI static void arcmsr_handle_hbe_isr( struct AdapterControlBlock *acb) 2359a1103e04SXin LI { 2360a1103e04SXin LI u_int32_t host_interrupt_status; 2361a1103e04SXin LI /* 2362a1103e04SXin LI ********************************************* 2363a1103e04SXin LI ** check outbound intstatus 2364a1103e04SXin LI ********************************************* 2365a1103e04SXin LI */ 2366a1103e04SXin LI host_interrupt_status = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_status) & 2367a1103e04SXin LI (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR | 2368a1103e04SXin LI ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR); 2369a1103e04SXin LI if(!host_interrupt_status) { 2370a1103e04SXin LI /*it must be share irq*/ 2371a1103e04SXin LI return; 2372a1103e04SXin LI } 2373a1103e04SXin LI do { 2374a1103e04SXin LI /* MU doorbell interrupts*/ 2375a1103e04SXin LI if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR) { 2376a1103e04SXin LI arcmsr_hbe_doorbell_isr(acb); 2377a1103e04SXin LI } 2378a1103e04SXin LI /* MU post queue interrupts*/ 2379a1103e04SXin LI if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR) { 2380a1103e04SXin LI arcmsr_hbe_postqueue_isr(acb); 2381a1103e04SXin LI } 2382a1103e04SXin LI host_interrupt_status = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_status); 2383a1103e04SXin LI } while (host_interrupt_status & (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR)); 2384a1103e04SXin LI } 2385fa42a0bfSXin LI 2386fa42a0bfSXin LI static void arcmsr_handle_hbf_isr( struct AdapterControlBlock *acb) 2387fa42a0bfSXin LI { 2388fa42a0bfSXin LI u_int32_t host_interrupt_status; 2389fa42a0bfSXin LI /* 2390fa42a0bfSXin LI ********************************************* 2391fa42a0bfSXin LI ** check outbound intstatus 2392fa42a0bfSXin LI ********************************************* 2393fa42a0bfSXin LI */ 2394fa42a0bfSXin LI host_interrupt_status = CHIP_REG_READ32(HBF_MessageUnit, 0, host_int_status) & 2395fa42a0bfSXin LI (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR | 2396fa42a0bfSXin LI ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR); 2397fa42a0bfSXin LI if(!host_interrupt_status) { 2398fa42a0bfSXin LI /*it must be share irq*/ 2399fa42a0bfSXin LI return; 2400fa42a0bfSXin LI } 2401fa42a0bfSXin LI do { 2402fa42a0bfSXin LI /* MU doorbell interrupts*/ 2403fa42a0bfSXin LI if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR) { 2404fa42a0bfSXin LI arcmsr_hbe_doorbell_isr(acb); 2405fa42a0bfSXin LI } 2406fa42a0bfSXin LI /* MU post queue interrupts*/ 2407fa42a0bfSXin LI if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR) { 2408fa42a0bfSXin LI arcmsr_hbf_postqueue_isr(acb); 2409fa42a0bfSXin LI } 2410fa42a0bfSXin LI host_interrupt_status = CHIP_REG_READ32(HBF_MessageUnit, 0, host_int_status); 2411fa42a0bfSXin LI } while (host_interrupt_status & (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR)); 2412fa42a0bfSXin LI } 2413a1103e04SXin LI /* 241444f05562SScott Long ****************************************************************************** 241544f05562SScott Long ****************************************************************************** 241644f05562SScott Long */ 241744f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb) 241844f05562SScott Long { 241944f05562SScott Long switch (acb->adapter_type) { 242044f05562SScott Long case ACB_ADAPTER_TYPE_A: 242144f05562SScott Long arcmsr_handle_hba_isr(acb); 2422f1c579b1SScott Long break; 242344f05562SScott Long case ACB_ADAPTER_TYPE_B: 242444f05562SScott Long arcmsr_handle_hbb_isr(acb); 2425f1c579b1SScott Long break; 2426d74001adSXin LI case ACB_ADAPTER_TYPE_C: 2427d74001adSXin LI arcmsr_handle_hbc_isr(acb); 2428d74001adSXin LI break; 24297a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 24307a7bc959SXin LI arcmsr_handle_hbd_isr(acb); 24317a7bc959SXin LI break; 2432a1103e04SXin LI case ACB_ADAPTER_TYPE_E: 2433a1103e04SXin LI arcmsr_handle_hbe_isr(acb); 2434a1103e04SXin LI break; 2435fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 2436fa42a0bfSXin LI arcmsr_handle_hbf_isr(acb); 2437fa42a0bfSXin LI break; 2438f1c579b1SScott Long default: 243944f05562SScott Long printf("arcmsr%d: interrupt service," 244010d66948SKevin Lo " unknown adapter type =%d\n", acb->pci_unit, acb->adapter_type); 2441f1c579b1SScott Long break; 2442f1c579b1SScott Long } 2443f1c579b1SScott Long } 2444f1c579b1SScott Long /* 2445d74001adSXin LI ********************************************************************** 2446d74001adSXin LI ********************************************************************** 2447d74001adSXin LI */ 2448d74001adSXin LI static void arcmsr_intr_handler(void *arg) 2449d74001adSXin LI { 2450d74001adSXin LI struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg; 2451d74001adSXin LI 24527a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 2453d74001adSXin LI arcmsr_interrupt(acb); 24547a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 2455d74001adSXin LI } 2456d74001adSXin LI /* 2457d74001adSXin LI ****************************************************************************** 2458d74001adSXin LI ****************************************************************************** 2459d74001adSXin LI */ 2460d74001adSXin LI static void arcmsr_polling_devmap(void *arg) 2461d74001adSXin LI { 2462d74001adSXin LI struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg; 2463d74001adSXin LI switch (acb->adapter_type) { 2464d74001adSXin LI case ACB_ADAPTER_TYPE_A: 2465dac36688SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 2466d74001adSXin LI break; 2467d74001adSXin LI 2468b23a1998SXin LI case ACB_ADAPTER_TYPE_B: { 2469b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 2470b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG); 2471b23a1998SXin LI } 2472d74001adSXin LI break; 2473d74001adSXin LI 2474d74001adSXin LI case ACB_ADAPTER_TYPE_C: 2475d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 2476d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 2477d74001adSXin LI break; 24787a7bc959SXin LI 24797a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 24807a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 24817a7bc959SXin LI break; 2482a1103e04SXin LI 2483a1103e04SXin LI case ACB_ADAPTER_TYPE_E: 2484a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 2485a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 2486a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 2487a1103e04SXin LI break; 2488d74001adSXin LI 2489fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 2490fa42a0bfSXin LI u_int32_t outMsg1 = CHIP_REG_READ32(HBF_MessageUnit, 0, outbound_msgaddr1); 2491fa42a0bfSXin LI if (!(outMsg1 & ARCMSR_HBFMU_MESSAGE_FIRMWARE_OK) || 2492fa42a0bfSXin LI (outMsg1 & ARCMSR_HBFMU_MESSAGE_NO_VOLUME_CHANGE)) 2493fa42a0bfSXin LI goto nxt6s; 2494fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 2495fa42a0bfSXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 2496fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 2497fa42a0bfSXin LI break; 2498fa42a0bfSXin LI } 2499fa42a0bfSXin LI } 2500fa42a0bfSXin LI nxt6s: 2501d74001adSXin LI if((acb->acb_flags & ACB_F_SCSISTOPADAPTER) == 0) 2502d74001adSXin LI { 2503d74001adSXin LI callout_reset(&acb->devmap_callout, 5 * hz, arcmsr_polling_devmap, acb); /* polling per 5 seconds */ 2504d74001adSXin LI } 2505d74001adSXin LI } 2506d74001adSXin LI 2507d74001adSXin LI /* 2508ad6d6297SScott Long ******************************************************************************* 2509ad6d6297SScott Long ** 2510ad6d6297SScott Long ******************************************************************************* 2511ad6d6297SScott Long */ 2512ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb) 2513ad6d6297SScott Long { 2514d74001adSXin LI u_int32_t intmask_org; 2515d74001adSXin LI 2516ad6d6297SScott Long if(acb != NULL) { 2517ad6d6297SScott Long /* stop adapter background rebuild */ 2518ad6d6297SScott Long if(acb->acb_flags & ACB_F_MSG_START_BGRB) { 2519d74001adSXin LI intmask_org = arcmsr_disable_allintr(acb); 2520ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 2521ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2522d74001adSXin LI arcmsr_enable_allintr(acb, intmask_org); 2523ad6d6297SScott Long } 2524ad6d6297SScott Long } 2525ad6d6297SScott Long } 2526ad6d6297SScott Long /* 2527f1c579b1SScott Long *********************************************************************** 2528f1c579b1SScott Long ** 2529f1c579b1SScott Long ************************************************************************ 2530f1c579b1SScott Long */ 2531fc5ef1caSXin LI static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg) 2532f1c579b1SScott Long { 2533ad6d6297SScott Long struct CMD_MESSAGE_FIELD *pcmdmessagefld; 2534ad6d6297SScott Long u_int32_t retvalue = EINVAL; 2535f1c579b1SScott Long 2536ad6d6297SScott Long pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) arg; 2537ad6d6297SScott Long if(memcmp(pcmdmessagefld->cmdmessage.Signature, "ARCMSR", 6)!=0) { 2538ad6d6297SScott Long return retvalue; 2539f1c579b1SScott Long } 2540ad6d6297SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2541ad6d6297SScott Long switch(ioctl_cmd) { 2542ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 2543ad6d6297SScott Long u_int8_t *pQbuffer; 2544ad6d6297SScott Long u_int8_t *ptmpQbuffer = pcmdmessagefld->messagedatabuffer; 2545ad6d6297SScott Long u_int32_t allxfer_len=0; 2546f1c579b1SScott Long 254744f05562SScott Long while((acb->rqbuf_firstindex != acb->rqbuf_lastindex) 254844f05562SScott Long && (allxfer_len < 1031)) { 2549f1c579b1SScott Long /*copy READ QBUFFER to srb*/ 2550ad6d6297SScott Long pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; 25517a7bc959SXin LI *ptmpQbuffer = *pQbuffer; 2552ad6d6297SScott Long acb->rqbuf_firstindex++; 2553ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 2554ad6d6297SScott Long /*if last index number set it to 0 */ 2555f1c579b1SScott Long ptmpQbuffer++; 2556f1c579b1SScott Long allxfer_len++; 2557f1c579b1SScott Long } 2558ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 255944f05562SScott Long struct QBUFFER *prbuffer; 2560f1c579b1SScott Long 2561ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 256244f05562SScott Long prbuffer = arcmsr_get_iop_rqbuffer(acb); 256335689395SXin LI if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) 256435689395SXin LI acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 2565f1c579b1SScott Long } 2566ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length = allxfer_len; 2567ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2568ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2569f1c579b1SScott Long } 2570f1c579b1SScott Long break; 2571ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 2572ad6d6297SScott Long u_int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 2573ad6d6297SScott Long u_int8_t *pQbuffer; 2574ad6d6297SScott Long u_int8_t *ptmpuserbuffer = pcmdmessagefld->messagedatabuffer; 2575f1c579b1SScott Long 2576ad6d6297SScott Long user_len = pcmdmessagefld->cmdmessage.Length; 2577f1c579b1SScott Long /*check if data xfer length of this request will overflow my array qbuffer */ 2578ad6d6297SScott Long wqbuf_lastindex = acb->wqbuf_lastindex; 2579ad6d6297SScott Long wqbuf_firstindex = acb->wqbuf_firstindex; 2580ad6d6297SScott Long if(wqbuf_lastindex != wqbuf_firstindex) { 25817a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2582ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR; 2583ad6d6297SScott Long } else { 25847a7bc959SXin LI my_empty_len = (wqbuf_firstindex - wqbuf_lastindex - 1) & 25857a7bc959SXin LI (ARCMSR_MAX_QBUFFER - 1); 2586ad6d6297SScott Long if(my_empty_len >= user_len) { 2587ad6d6297SScott Long while(user_len > 0) { 2588f1c579b1SScott Long /*copy srb data to wqbuffer*/ 2589ad6d6297SScott Long pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; 25907a7bc959SXin LI *pQbuffer = *ptmpuserbuffer; 2591ad6d6297SScott Long acb->wqbuf_lastindex++; 2592ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 2593ad6d6297SScott Long /*if last index number set it to 0 */ 2594f1c579b1SScott Long ptmpuserbuffer++; 2595f1c579b1SScott Long user_len--; 2596f1c579b1SScott Long } 2597f1c579b1SScott Long /*post fist Qbuffer*/ 2598ad6d6297SScott Long if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 2599ad6d6297SScott Long acb->acb_flags &= ~ACB_F_MESSAGE_WQBUFFER_CLEARED; 26007a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2601f1c579b1SScott Long } 2602ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2603ad6d6297SScott Long } else { 2604ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR; 2605f1c579b1SScott Long } 2606f1c579b1SScott Long } 2607ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2608f1c579b1SScott Long } 2609f1c579b1SScott Long break; 2610ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 2611ad6d6297SScott Long u_int8_t *pQbuffer = acb->rqbuffer; 2612ad6d6297SScott Long 2613ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2614ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 261544f05562SScott Long arcmsr_iop_message_read(acb); 261644f05562SScott Long /*signature, let IOP know data has been readed */ 2617f1c579b1SScott Long } 2618ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 2619ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2620ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2621f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2622ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2623ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2624f1c579b1SScott Long } 2625f1c579b1SScott Long break; 2626ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: 2627f1c579b1SScott Long { 2628ad6d6297SScott Long u_int8_t *pQbuffer = acb->wqbuffer; 2629f1c579b1SScott Long 2630ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2631ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 263244f05562SScott Long arcmsr_iop_message_read(acb); 263344f05562SScott Long /*signature, let IOP know data has been readed */ 2634f1c579b1SScott Long } 263544f05562SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ); 2636ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2637ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2638f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2639ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2640ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2641f1c579b1SScott Long } 2642f1c579b1SScott Long break; 2643ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 2644ad6d6297SScott Long u_int8_t *pQbuffer; 2645f1c579b1SScott Long 2646ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2647ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 264844f05562SScott Long arcmsr_iop_message_read(acb); 264944f05562SScott Long /*signature, let IOP know data has been readed */ 2650f1c579b1SScott Long } 2651ad6d6297SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED 2652ad6d6297SScott Long |ACB_F_MESSAGE_RQBUFFER_CLEARED 265344f05562SScott Long |ACB_F_MESSAGE_WQBUFFER_READ); 2654ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2655ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2656ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2657ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2658ad6d6297SScott Long pQbuffer = acb->rqbuffer; 2659ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 2660ad6d6297SScott Long pQbuffer = acb->wqbuffer; 2661ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 2662ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2663ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2664f1c579b1SScott Long } 2665f1c579b1SScott Long break; 2666ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 2667ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; 2668ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2669f1c579b1SScott Long } 2670f1c579b1SScott Long break; 2671ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 2672ad6d6297SScott Long u_int8_t *hello_string = "Hello! I am ARCMSR"; 2673ad6d6297SScott Long u_int8_t *puserbuffer = (u_int8_t *)pcmdmessagefld->messagedatabuffer; 2674f1c579b1SScott Long 2675ad6d6297SScott Long if(memcpy(puserbuffer, hello_string, (int16_t)strlen(hello_string))) { 2676ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR; 2677ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2678f1c579b1SScott Long return ENOIOCTL; 2679f1c579b1SScott Long } 2680ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2681ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2682ad6d6297SScott Long } 2683ad6d6297SScott Long break; 2684ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: { 2685ad6d6297SScott Long arcmsr_iop_parking(acb); 2686ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2687ad6d6297SScott Long } 2688ad6d6297SScott Long break; 2689ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: { 2690ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2691ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2692f1c579b1SScott Long } 2693f1c579b1SScott Long break; 2694f1c579b1SScott Long } 2695ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2696dac36688SXin LI return (retvalue); 2697f1c579b1SScott Long } 2698f1c579b1SScott Long /* 2699f1c579b1SScott Long ************************************************************************** 2700f1c579b1SScott Long ************************************************************************** 2701f1c579b1SScott Long */ 270222f2616bSXin LI static void arcmsr_free_srb(struct CommandControlBlock *srb) 270322f2616bSXin LI { 270422f2616bSXin LI struct AdapterControlBlock *acb; 270522f2616bSXin LI 270622f2616bSXin LI acb = srb->acb; 27077a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->srb_lock); 270822f2616bSXin LI srb->srb_state = ARCMSR_SRB_DONE; 270922f2616bSXin LI srb->srb_flags = 0; 271022f2616bSXin LI acb->srbworkingQ[acb->workingsrb_doneindex] = srb; 271122f2616bSXin LI acb->workingsrb_doneindex++; 271222f2616bSXin LI acb->workingsrb_doneindex %= ARCMSR_MAX_FREESRB_NUM; 27137a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->srb_lock); 271422f2616bSXin LI } 271522f2616bSXin LI /* 271622f2616bSXin LI ************************************************************************** 271722f2616bSXin LI ************************************************************************** 271822f2616bSXin LI */ 2719fc5ef1caSXin LI static struct CommandControlBlock *arcmsr_get_freesrb(struct AdapterControlBlock *acb) 2720f1c579b1SScott Long { 2721ad6d6297SScott Long struct CommandControlBlock *srb = NULL; 2722ad6d6297SScott Long u_int32_t workingsrb_startindex, workingsrb_doneindex; 2723f1c579b1SScott Long 27247a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->srb_lock); 2725ad6d6297SScott Long workingsrb_doneindex = acb->workingsrb_doneindex; 2726ad6d6297SScott Long workingsrb_startindex = acb->workingsrb_startindex; 2727ad6d6297SScott Long srb = acb->srbworkingQ[workingsrb_startindex]; 2728ad6d6297SScott Long workingsrb_startindex++; 2729ad6d6297SScott Long workingsrb_startindex %= ARCMSR_MAX_FREESRB_NUM; 2730ad6d6297SScott Long if(workingsrb_doneindex != workingsrb_startindex) { 2731ad6d6297SScott Long acb->workingsrb_startindex = workingsrb_startindex; 2732ad6d6297SScott Long } else { 2733ad6d6297SScott Long srb = NULL; 2734ad6d6297SScott Long } 27357a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->srb_lock); 2736ad6d6297SScott Long return(srb); 2737ad6d6297SScott Long } 2738ad6d6297SScott Long /* 2739ad6d6297SScott Long ************************************************************************** 2740ad6d6297SScott Long ************************************************************************** 2741ad6d6297SScott Long */ 2742ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *pccb) 2743ad6d6297SScott Long { 2744ad6d6297SScott Long struct CMD_MESSAGE_FIELD *pcmdmessagefld; 2745ad6d6297SScott Long int retvalue = 0, transfer_len = 0; 2746ad6d6297SScott Long char *buffer; 27474aa947cbSWarner Losh uint8_t *ptr = scsiio_cdb_ptr(&pccb->csio); 27484aa947cbSWarner Losh u_int32_t controlcode = (u_int32_t ) ptr[5] << 24 | 27494aa947cbSWarner Losh (u_int32_t ) ptr[6] << 16 | 27504aa947cbSWarner Losh (u_int32_t ) ptr[7] << 8 | 27514aa947cbSWarner Losh (u_int32_t ) ptr[8]; 2752ad6d6297SScott Long /* 4 bytes: Areca io control code */ 2753dd0b4fb6SKonstantin Belousov if ((pccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) { 2754ad6d6297SScott Long buffer = pccb->csio.data_ptr; 2755ad6d6297SScott Long transfer_len = pccb->csio.dxfer_len; 2756ad6d6297SScott Long } else { 2757ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2758ad6d6297SScott Long goto message_out; 2759ad6d6297SScott Long } 2760ad6d6297SScott Long if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) { 2761ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2762ad6d6297SScott Long goto message_out; 2763ad6d6297SScott Long } 2764ad6d6297SScott Long pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer; 2765ad6d6297SScott Long switch(controlcode) { 2766ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 2767ad6d6297SScott Long u_int8_t *pQbuffer; 2768ad6d6297SScott Long u_int8_t *ptmpQbuffer = pcmdmessagefld->messagedatabuffer; 2769ad6d6297SScott Long int32_t allxfer_len = 0; 2770f1c579b1SScott Long 27717a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2772ad6d6297SScott Long while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) 2773ad6d6297SScott Long && (allxfer_len < 1031)) { 2774ad6d6297SScott Long pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; 27757a7bc959SXin LI *ptmpQbuffer = *pQbuffer; 2776ad6d6297SScott Long acb->rqbuf_firstindex++; 2777ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 2778ad6d6297SScott Long ptmpQbuffer++; 2779ad6d6297SScott Long allxfer_len++; 2780f1c579b1SScott Long } 2781ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 278244f05562SScott Long struct QBUFFER *prbuffer; 2783ad6d6297SScott Long 2784ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 278544f05562SScott Long prbuffer = arcmsr_get_iop_rqbuffer(acb); 278635689395SXin LI if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) 278735689395SXin LI acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 2788ad6d6297SScott Long } 2789ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length = allxfer_len; 2790ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2791ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 27927a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2793ad6d6297SScott Long } 2794ad6d6297SScott Long break; 2795ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 2796ad6d6297SScott Long int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 2797ad6d6297SScott Long u_int8_t *pQbuffer; 2798ad6d6297SScott Long u_int8_t *ptmpuserbuffer = pcmdmessagefld->messagedatabuffer; 2799ad6d6297SScott Long 2800ad6d6297SScott Long user_len = pcmdmessagefld->cmdmessage.Length; 28017a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2802ad6d6297SScott Long wqbuf_lastindex = acb->wqbuf_lastindex; 2803ad6d6297SScott Long wqbuf_firstindex = acb->wqbuf_firstindex; 2804ad6d6297SScott Long if (wqbuf_lastindex != wqbuf_firstindex) { 28057a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2806ad6d6297SScott Long /* has error report sensedata */ 2807dac36688SXin LI if(pccb->csio.sense_len) { 2808ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 2809ad6d6297SScott Long /* Valid,ErrorCode */ 2810ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 2811ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 2812ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 2813ad6d6297SScott Long /* AdditionalSenseLength */ 2814ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 2815ad6d6297SScott Long /* AdditionalSenseCode */ 2816ad6d6297SScott Long } 2817ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2818ad6d6297SScott Long } else { 2819ad6d6297SScott Long my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) 2820ad6d6297SScott Long &(ARCMSR_MAX_QBUFFER - 1); 2821ad6d6297SScott Long if (my_empty_len >= user_len) { 2822ad6d6297SScott Long while (user_len > 0) { 2823ad6d6297SScott Long pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; 28247a7bc959SXin LI *pQbuffer = *ptmpuserbuffer; 2825ad6d6297SScott Long acb->wqbuf_lastindex++; 2826ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 2827ad6d6297SScott Long ptmpuserbuffer++; 2828ad6d6297SScott Long user_len--; 2829ad6d6297SScott Long } 2830ad6d6297SScott Long if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 2831ad6d6297SScott Long acb->acb_flags &= 2832ad6d6297SScott Long ~ACB_F_MESSAGE_WQBUFFER_CLEARED; 28337a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2834ad6d6297SScott Long } 2835ad6d6297SScott Long } else { 2836ad6d6297SScott Long /* has error report sensedata */ 2837dac36688SXin LI if(pccb->csio.sense_len) { 2838ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 2839ad6d6297SScott Long /* Valid,ErrorCode */ 2840ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 2841ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 2842ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 2843ad6d6297SScott Long /* AdditionalSenseLength */ 2844ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 2845ad6d6297SScott Long /* AdditionalSenseCode */ 2846ad6d6297SScott Long } 2847ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2848ad6d6297SScott Long } 2849ad6d6297SScott Long } 28507a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2851ad6d6297SScott Long } 2852ad6d6297SScott Long break; 2853ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 2854ad6d6297SScott Long u_int8_t *pQbuffer = acb->rqbuffer; 2855ad6d6297SScott Long 28567a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2857ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2858ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 285944f05562SScott Long arcmsr_iop_message_read(acb); 2860ad6d6297SScott Long } 2861ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 2862ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2863ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2864ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2865ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 2866ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 28677a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2868ad6d6297SScott Long } 2869ad6d6297SScott Long break; 2870ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { 2871ad6d6297SScott Long u_int8_t *pQbuffer = acb->wqbuffer; 2872ad6d6297SScott Long 28737a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2874ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2875ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 287644f05562SScott Long arcmsr_iop_message_read(acb); 2877ad6d6297SScott Long } 2878ad6d6297SScott Long acb->acb_flags |= 2879ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED | 288044f05562SScott Long ACB_F_MESSAGE_WQBUFFER_READ); 2881ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2882ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2883ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2884ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 2885ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 28867a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2887ad6d6297SScott Long } 2888ad6d6297SScott Long break; 2889ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 2890ad6d6297SScott Long u_int8_t *pQbuffer; 2891ad6d6297SScott Long 28927a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2893ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2894ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 289544f05562SScott Long arcmsr_iop_message_read(acb); 2896ad6d6297SScott Long } 2897ad6d6297SScott Long acb->acb_flags |= 2898ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED 2899ad6d6297SScott Long | ACB_F_MESSAGE_RQBUFFER_CLEARED 290044f05562SScott Long | ACB_F_MESSAGE_WQBUFFER_READ); 2901ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2902ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2903ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2904ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2905ad6d6297SScott Long pQbuffer = acb->rqbuffer; 2906ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 2907ad6d6297SScott Long pQbuffer = acb->wqbuffer; 2908ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 2909ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 29107a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2911ad6d6297SScott Long } 2912ad6d6297SScott Long break; 2913ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 2914ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; 2915ad6d6297SScott Long } 2916ad6d6297SScott Long break; 2917ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 2918ad6d6297SScott Long int8_t *hello_string = "Hello! I am ARCMSR"; 2919ad6d6297SScott Long 2920ad6d6297SScott Long memcpy(pcmdmessagefld->messagedatabuffer, hello_string 2921ad6d6297SScott Long , (int16_t)strlen(hello_string)); 2922ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2923ad6d6297SScott Long } 2924ad6d6297SScott Long break; 2925ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: 2926ad6d6297SScott Long arcmsr_iop_parking(acb); 2927ad6d6297SScott Long break; 2928ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: 2929ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2930ad6d6297SScott Long break; 2931ad6d6297SScott Long default: 2932ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2933ad6d6297SScott Long } 2934ad6d6297SScott Long message_out: 2935dac36688SXin LI return (retvalue); 2936f1c579b1SScott Long } 2937f1c579b1SScott Long /* 2938f1c579b1SScott Long ********************************************************************* 2939f1c579b1SScott Long ********************************************************************* 2940f1c579b1SScott Long */ 2941231c8b71SXin LI static void arcmsr_execute_srb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 2942f1c579b1SScott Long { 2943ad6d6297SScott Long struct CommandControlBlock *srb = (struct CommandControlBlock *)arg; 2944ad6d6297SScott Long struct AdapterControlBlock *acb = (struct AdapterControlBlock *)srb->acb; 2945f1c579b1SScott Long union ccb *pccb; 2946ad6d6297SScott Long int target, lun; 2947f1c579b1SScott Long 2948ad6d6297SScott Long pccb = srb->pccb; 2949ad6d6297SScott Long target = pccb->ccb_h.target_id; 2950ad6d6297SScott Long lun = pccb->ccb_h.target_lun; 295122f2616bSXin LI acb->pktRequestCount++; 2952ad6d6297SScott Long if(error != 0) { 2953ad6d6297SScott Long if(error != EFBIG) { 295444f05562SScott Long printf("arcmsr%d: unexpected error %x" 295544f05562SScott Long " returned from 'bus_dmamap_load' \n" 2956ad6d6297SScott Long , acb->pci_unit, error); 2957f1c579b1SScott Long } 2958ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { 295915735becSScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 2960f1c579b1SScott Long } 2961ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2962f1c579b1SScott Long return; 2963f1c579b1SScott Long } 2964ad6d6297SScott Long if(nseg > ARCMSR_MAX_SG_ENTRIES) { 2965ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 2966ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2967ad6d6297SScott Long return; 2968f1c579b1SScott Long } 2969ad6d6297SScott Long if(acb->acb_flags & ACB_F_BUS_RESET) { 2970ad6d6297SScott Long printf("arcmsr%d: bus reset and return busy \n", acb->pci_unit); 2971ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_BUS_RESET; 2972ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2973ad6d6297SScott Long return; 2974ad6d6297SScott Long } 2975ad6d6297SScott Long if(acb->devstate[target][lun] == ARECA_RAID_GONE) { 297622f2616bSXin LI u_int8_t block_cmd, cmd; 2977ad6d6297SScott Long 29784aa947cbSWarner Losh cmd = scsiio_cdb_ptr(&pccb->csio)[0]; 297922f2616bSXin LI block_cmd = cmd & 0x0f; 2980ad6d6297SScott Long if(block_cmd == 0x08 || block_cmd == 0x0a) { 2981ad6d6297SScott Long printf("arcmsr%d:block 'read/write' command " 298222f2616bSXin LI "with gone raid volume Cmd=0x%2x, TargetId=%d, Lun=%d \n" 298322f2616bSXin LI , acb->pci_unit, cmd, target, lun); 2984ad6d6297SScott Long pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 2985ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2986ad6d6297SScott Long return; 2987ad6d6297SScott Long } 2988ad6d6297SScott Long } 2989ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { 2990ad6d6297SScott Long if(nseg != 0) { 2991ad6d6297SScott Long bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 2992ad6d6297SScott Long } 2993ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2994f1c579b1SScott Long return; 2995f1c579b1SScott Long } 2996abfdbca9SXin LI if(acb->srboutstandingcount >= acb->maxOutstanding) { 29977a7bc959SXin LI if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) == 0) 29987a7bc959SXin LI { 299915735becSScott Long xpt_freeze_simq(acb->psim, 1); 3000dc3a205bSScott Long acb->acb_flags |= ACB_F_CAM_DEV_QFRZN; 30017a7bc959SXin LI } 30027a7bc959SXin LI pccb->ccb_h.status &= ~CAM_SIM_QUEUED; 30037a7bc959SXin LI pccb->ccb_h.status |= CAM_REQUEUE_REQ; 3004ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 3005ad6d6297SScott Long return; 3006f1c579b1SScott Long } 300715735becSScott Long pccb->ccb_h.status |= CAM_SIM_QUEUED; 3008ad6d6297SScott Long arcmsr_build_srb(srb, dm_segs, nseg); 3009ad6d6297SScott Long arcmsr_post_srb(acb, srb); 301022f2616bSXin LI if (pccb->ccb_h.timeout != CAM_TIME_INFINITY) 301122f2616bSXin LI { 301222f2616bSXin LI arcmsr_callout_init(&srb->ccb_callout); 301385c9dd9dSSteven Hartland callout_reset_sbt(&srb->ccb_callout, SBT_1MS * 301485c9dd9dSSteven Hartland (pccb->ccb_h.timeout + (ARCMSR_TIMEOUT_DELAY * 1000)), 0, 301585c9dd9dSSteven Hartland arcmsr_srb_timeout, srb, 0); 301622f2616bSXin LI srb->srb_flags |= SRB_FLAG_TIMER_START; 301722f2616bSXin LI } 3018f1c579b1SScott Long } 3019f1c579b1SScott Long /* 3020f1c579b1SScott Long ***************************************************************************************** 3021f1c579b1SScott Long ***************************************************************************************** 3022f1c579b1SScott Long */ 3023ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb *abortccb) 3024f1c579b1SScott Long { 3025ad6d6297SScott Long struct CommandControlBlock *srb; 3026ad6d6297SScott Long struct AdapterControlBlock *acb = (struct AdapterControlBlock *) abortccb->ccb_h.arcmsr_ccbacb_ptr; 302744f05562SScott Long u_int32_t intmask_org; 3028ad6d6297SScott Long int i = 0; 3029f1c579b1SScott Long 3030ad6d6297SScott Long acb->num_aborts++; 3031f1c579b1SScott Long /* 3032ad6d6297SScott Long *************************************************************************** 3033f1c579b1SScott Long ** It is the upper layer do abort command this lock just prior to calling us. 3034f1c579b1SScott Long ** First determine if we currently own this command. 3035f1c579b1SScott Long ** Start by searching the device queue. If not found 3036f1c579b1SScott Long ** at all, and the system wanted us to just abort the 3037f1c579b1SScott Long ** command return success. 3038ad6d6297SScott Long *************************************************************************** 3039f1c579b1SScott Long */ 3040ad6d6297SScott Long if(acb->srboutstandingcount != 0) { 304122f2616bSXin LI /* disable all outbound interrupt */ 304222f2616bSXin LI intmask_org = arcmsr_disable_allintr(acb); 3043ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 3044ad6d6297SScott Long srb = acb->psrb_pool[i]; 304522f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) { 3046ad6d6297SScott Long if(srb->pccb == abortccb) { 304722f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 3048123055f0SNathan Whitehorn printf("arcmsr%d:scsi id=%d lun=%jx abort srb '%p'" 3049ad6d6297SScott Long "outstanding command \n" 3050ad6d6297SScott Long , acb->pci_unit, abortccb->ccb_h.target_id 3051123055f0SNathan Whitehorn , (uintmax_t)abortccb->ccb_h.target_lun, srb); 3052ad6d6297SScott Long arcmsr_polling_srbdone(acb, srb); 305344f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 305444f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 3055ad6d6297SScott Long return (TRUE); 3056f1c579b1SScott Long } 305722f2616bSXin LI } 305822f2616bSXin LI } 305922f2616bSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 306022f2616bSXin LI arcmsr_enable_allintr(acb, intmask_org); 306122f2616bSXin LI } 306222f2616bSXin LI return(FALSE); 306322f2616bSXin LI } 3064f1c579b1SScott Long /* 3065f1c579b1SScott Long **************************************************************************** 3066f1c579b1SScott Long **************************************************************************** 3067f1c579b1SScott Long */ 3068ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb) 3069f1c579b1SScott Long { 3070ad6d6297SScott Long int retry = 0; 3071f1c579b1SScott Long 3072ad6d6297SScott Long acb->num_resets++; 3073ad6d6297SScott Long acb->acb_flags |= ACB_F_BUS_RESET; 3074ad6d6297SScott Long while(acb->srboutstandingcount != 0 && retry < 400) { 307544f05562SScott Long arcmsr_interrupt(acb); 3076ad6d6297SScott Long UDELAY(25000); 3077ad6d6297SScott Long retry++; 3078ad6d6297SScott Long } 3079ad6d6297SScott Long arcmsr_iop_reset(acb); 3080ad6d6297SScott Long acb->acb_flags &= ~ACB_F_BUS_RESET; 3081f1c579b1SScott Long } 3082f1c579b1SScott Long /* 3083ad6d6297SScott Long ************************************************************************** 3084ad6d6297SScott Long ************************************************************************** 3085ad6d6297SScott Long */ 3086ad6d6297SScott Long static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, 3087ad6d6297SScott Long union ccb *pccb) 3088ad6d6297SScott Long { 3089ad6d6297SScott Long if (pccb->ccb_h.target_lun) { 309061ba2ac6SJim Harris pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 3091ad6d6297SScott Long xpt_done(pccb); 3092ad6d6297SScott Long return; 3093ad6d6297SScott Long } 30947a7bc959SXin LI pccb->ccb_h.status |= CAM_REQ_CMP; 30954aa947cbSWarner Losh switch (scsiio_cdb_ptr(&pccb->csio)[0]) { 30967a7bc959SXin LI case INQUIRY: { 30977a7bc959SXin LI unsigned char inqdata[36]; 30987a7bc959SXin LI char *buffer = pccb->csio.data_ptr; 30997a7bc959SXin LI 3100231c8b71SXin LI inqdata[0] = T_PROCESSOR; /* Periph Qualifier & Periph Dev Type */ 3101231c8b71SXin LI inqdata[1] = 0; /* rem media bit & Dev Type Modifier */ 3102231c8b71SXin LI inqdata[2] = 0; /* ISO, ECMA, & ANSI versions */ 3103231c8b71SXin LI inqdata[3] = 0; 3104231c8b71SXin LI inqdata[4] = 31; /* length of additional data */ 3105231c8b71SXin LI inqdata[5] = 0; 3106231c8b71SXin LI inqdata[6] = 0; 3107231c8b71SXin LI inqdata[7] = 0; 3108231c8b71SXin LI strncpy(&inqdata[8], "Areca ", 8); /* Vendor Identification */ 3109231c8b71SXin LI strncpy(&inqdata[16], "RAID controller ", 16); /* Product Identification */ 3110ad6d6297SScott Long strncpy(&inqdata[32], "R001", 4); /* Product Revision */ 3111ad6d6297SScott Long memcpy(buffer, inqdata, sizeof(inqdata)); 3112ad6d6297SScott Long xpt_done(pccb); 3113ad6d6297SScott Long } 3114ad6d6297SScott Long break; 3115ad6d6297SScott Long case WRITE_BUFFER: 3116ad6d6297SScott Long case READ_BUFFER: { 3117ad6d6297SScott Long if (arcmsr_iop_message_xfer(acb, pccb)) { 3118ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 3119ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 3120ad6d6297SScott Long } 3121ad6d6297SScott Long xpt_done(pccb); 3122ad6d6297SScott Long } 3123ad6d6297SScott Long break; 3124ad6d6297SScott Long default: 3125ad6d6297SScott Long xpt_done(pccb); 3126ad6d6297SScott Long } 3127ad6d6297SScott Long } 3128ad6d6297SScott Long /* 3129f1c579b1SScott Long ********************************************************************* 3130f1c579b1SScott Long ********************************************************************* 3131f1c579b1SScott Long */ 3132ad6d6297SScott Long static void arcmsr_action(struct cam_sim *psim, union ccb *pccb) 3133f1c579b1SScott Long { 3134ad6d6297SScott Long struct AdapterControlBlock *acb; 3135f1c579b1SScott Long 3136ad6d6297SScott Long acb = (struct AdapterControlBlock *) cam_sim_softc(psim); 3137ad6d6297SScott Long if(acb == NULL) { 3138ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 3139f1c579b1SScott Long xpt_done(pccb); 3140f1c579b1SScott Long return; 3141f1c579b1SScott Long } 3142ad6d6297SScott Long switch (pccb->ccb_h.func_code) { 3143ad6d6297SScott Long case XPT_SCSI_IO: { 3144ad6d6297SScott Long struct CommandControlBlock *srb; 3145ad6d6297SScott Long int target = pccb->ccb_h.target_id; 3146dd0b4fb6SKonstantin Belousov int error; 3147f1c579b1SScott Long 31484aa947cbSWarner Losh if (pccb->ccb_h.flags & CAM_CDB_PHYS) { 31494aa947cbSWarner Losh pccb->ccb_h.status = CAM_REQ_INVALID; 31504aa947cbSWarner Losh xpt_done(pccb); 31514aa947cbSWarner Losh return; 31524aa947cbSWarner Losh } 31534aa947cbSWarner Losh 3154ad6d6297SScott Long if(target == 16) { 3155ad6d6297SScott Long /* virtual device for iop message transfer */ 3156ad6d6297SScott Long arcmsr_handle_virtual_command(acb, pccb); 3157ad6d6297SScott Long return; 3158ad6d6297SScott Long } 3159ad6d6297SScott Long if((srb = arcmsr_get_freesrb(acb)) == NULL) { 3160ad6d6297SScott Long pccb->ccb_h.status |= CAM_RESRC_UNAVAIL; 3161f1c579b1SScott Long xpt_done(pccb); 3162f1c579b1SScott Long return; 3163f1c579b1SScott Long } 3164ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbsrb_ptr = srb; 3165ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbacb_ptr = acb; 3166ad6d6297SScott Long srb->pccb = pccb; 3167dd0b4fb6SKonstantin Belousov error = bus_dmamap_load_ccb(acb->dm_segs_dmat 3168ad6d6297SScott Long , srb->dm_segs_dmamap 3169dd0b4fb6SKonstantin Belousov , pccb 3170231c8b71SXin LI , arcmsr_execute_srb, srb, /*flags*/0); 3171ad6d6297SScott Long if(error == EINPROGRESS) { 3172ad6d6297SScott Long xpt_freeze_simq(acb->psim, 1); 3173f1c579b1SScott Long pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 3174f1c579b1SScott Long } 3175f1c579b1SScott Long break; 3176f1c579b1SScott Long } 3177ad6d6297SScott Long case XPT_PATH_INQ: { 3178f1c579b1SScott Long struct ccb_pathinq *cpi = &pccb->cpi; 3179f1c579b1SScott Long 3180f1c579b1SScott Long cpi->version_num = 1; 3181f1c579b1SScott Long cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE; 3182f1c579b1SScott Long cpi->target_sprt = 0; 3183f1c579b1SScott Long cpi->hba_misc = 0; 3184f1c579b1SScott Long cpi->hba_eng_cnt = 0; 3185ad6d6297SScott Long cpi->max_target = ARCMSR_MAX_TARGETID; /* 0-16 */ 3186ad6d6297SScott Long cpi->max_lun = ARCMSR_MAX_TARGETLUN; /* 0-7 */ 3187ad6d6297SScott Long cpi->initiator_id = ARCMSR_SCSI_INITIATOR_ID; /* 255 */ 3188f1c579b1SScott Long cpi->bus_id = cam_sim_bus(psim); 31894195c7deSAlan Somers strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 31904195c7deSAlan Somers strlcpy(cpi->hba_vid, "ARCMSR", HBA_IDLEN); 31914195c7deSAlan Somers strlcpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN); 3192f1c579b1SScott Long cpi->unit_number = cam_sim_unit(psim); 3193224a78aeSXin LI if(acb->adapter_bus_speed == ACB_BUS_SPEED_12G) 3194224a78aeSXin LI cpi->base_transfer_speed = 1200000; 3195224a78aeSXin LI else if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G) 3196dac36688SXin LI cpi->base_transfer_speed = 600000; 3197dac36688SXin LI else 3198dac36688SXin LI cpi->base_transfer_speed = 300000; 3199dac36688SXin LI if((acb->vendor_device_id == PCIDevVenIDARC1880) || 3200a1103e04SXin LI (acb->vendor_device_id == PCIDevVenIDARC1884) || 32017a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1680) || 32027a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1214)) 3203dac36688SXin LI { 3204dac36688SXin LI cpi->transport = XPORT_SAS; 3205dac36688SXin LI cpi->transport_version = 0; 3206dac36688SXin LI cpi->protocol_version = SCSI_REV_SPC2; 3207dac36688SXin LI } 3208dac36688SXin LI else 3209dac36688SXin LI { 3210fa9ed865SMatt Jacob cpi->transport = XPORT_SPI; 3211fa9ed865SMatt Jacob cpi->transport_version = 2; 3212fa9ed865SMatt Jacob cpi->protocol_version = SCSI_REV_2; 3213dac36688SXin LI } 3214dac36688SXin LI cpi->protocol = PROTO_SCSI; 3215ad6d6297SScott Long cpi->ccb_h.status |= CAM_REQ_CMP; 3216f1c579b1SScott Long xpt_done(pccb); 3217f1c579b1SScott Long break; 3218f1c579b1SScott Long } 3219ad6d6297SScott Long case XPT_ABORT: { 3220f1c579b1SScott Long union ccb *pabort_ccb; 3221f1c579b1SScott Long 3222f1c579b1SScott Long pabort_ccb = pccb->cab.abort_ccb; 3223ad6d6297SScott Long switch (pabort_ccb->ccb_h.func_code) { 3224f1c579b1SScott Long case XPT_ACCEPT_TARGET_IO: 3225f1c579b1SScott Long case XPT_CONT_TARGET_IO: 3226ad6d6297SScott Long if(arcmsr_seek_cmd2abort(pabort_ccb)==TRUE) { 3227ad6d6297SScott Long pabort_ccb->ccb_h.status |= CAM_REQ_ABORTED; 3228f1c579b1SScott Long xpt_done(pabort_ccb); 3229ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 3230ad6d6297SScott Long } else { 3231f1c579b1SScott Long xpt_print_path(pabort_ccb->ccb_h.path); 3232f1c579b1SScott Long printf("Not found\n"); 3233ad6d6297SScott Long pccb->ccb_h.status |= CAM_PATH_INVALID; 3234f1c579b1SScott Long } 3235f1c579b1SScott Long break; 3236f1c579b1SScott Long case XPT_SCSI_IO: 3237ad6d6297SScott Long pccb->ccb_h.status |= CAM_UA_ABORT; 3238f1c579b1SScott Long break; 3239f1c579b1SScott Long default: 3240ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 3241f1c579b1SScott Long break; 3242f1c579b1SScott Long } 3243f1c579b1SScott Long xpt_done(pccb); 3244f1c579b1SScott Long break; 3245f1c579b1SScott Long } 3246f1c579b1SScott Long case XPT_RESET_BUS: 3247ad6d6297SScott Long case XPT_RESET_DEV: { 3248ad6d6297SScott Long u_int32_t i; 3249f1c579b1SScott Long 3250ad6d6297SScott Long arcmsr_bus_reset(acb); 3251ad6d6297SScott Long for (i=0; i < 500; i++) { 3252f1c579b1SScott Long DELAY(1000); 3253f1c579b1SScott Long } 3254ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 3255f1c579b1SScott Long xpt_done(pccb); 3256f1c579b1SScott Long break; 3257f1c579b1SScott Long } 3258ad6d6297SScott Long case XPT_TERM_IO: { 3259ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 3260f1c579b1SScott Long xpt_done(pccb); 3261f1c579b1SScott Long break; 3262f1c579b1SScott Long } 3263ad6d6297SScott Long case XPT_GET_TRAN_SETTINGS: { 3264ad6d6297SScott Long struct ccb_trans_settings *cts; 3265ad6d6297SScott Long 3266ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 3267ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 3268ad6d6297SScott Long xpt_done(pccb); 3269ad6d6297SScott Long break; 3270ad6d6297SScott Long } 3271ad6d6297SScott Long cts = &pccb->cts; 327244f05562SScott Long { 327344f05562SScott Long struct ccb_trans_settings_scsi *scsi; 327444f05562SScott Long struct ccb_trans_settings_spi *spi; 3275dac36688SXin LI struct ccb_trans_settings_sas *sas; 327644f05562SScott Long 3277ad6d6297SScott Long scsi = &cts->proto_specific.scsi; 3278dac36688SXin LI scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 3279dac36688SXin LI scsi->valid = CTS_SCSI_VALID_TQ; 3280fa9ed865SMatt Jacob cts->protocol = PROTO_SCSI; 3281dac36688SXin LI 3282dac36688SXin LI if((acb->vendor_device_id == PCIDevVenIDARC1880) || 3283a1103e04SXin LI (acb->vendor_device_id == PCIDevVenIDARC1884) || 32847a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1680) || 32857a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1214)) 3286dac36688SXin LI { 3287dac36688SXin LI cts->protocol_version = SCSI_REV_SPC2; 3288dac36688SXin LI cts->transport_version = 0; 3289dac36688SXin LI cts->transport = XPORT_SAS; 3290dac36688SXin LI sas = &cts->xport_specific.sas; 3291dac36688SXin LI sas->valid = CTS_SAS_VALID_SPEED; 3292b23a1998SXin LI if (acb->adapter_bus_speed == ACB_BUS_SPEED_12G) 3293224a78aeSXin LI sas->bitrate = 1200000; 3294b23a1998SXin LI else if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G) 3295dac36688SXin LI sas->bitrate = 600000; 3296b23a1998SXin LI else if(acb->adapter_bus_speed == ACB_BUS_SPEED_3G) 3297dac36688SXin LI sas->bitrate = 300000; 3298dac36688SXin LI } 3299dac36688SXin LI else 3300dac36688SXin LI { 3301fa9ed865SMatt Jacob cts->protocol_version = SCSI_REV_2; 3302fa9ed865SMatt Jacob cts->transport_version = 2; 3303dac36688SXin LI cts->transport = XPORT_SPI; 3304dac36688SXin LI spi = &cts->xport_specific.spi; 3305fa9ed865SMatt Jacob spi->flags = CTS_SPI_FLAGS_DISC_ENB; 3306b23a1998SXin LI if (acb->adapter_bus_speed == ACB_BUS_SPEED_6G) 3307b23a1998SXin LI spi->sync_period = 1; 3308b23a1998SXin LI else 3309dac36688SXin LI spi->sync_period = 2; 3310fa9ed865SMatt Jacob spi->sync_offset = 32; 3311fa9ed865SMatt Jacob spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 33129d98ff4dSScott Long spi->valid = CTS_SPI_VALID_DISC 33139d98ff4dSScott Long | CTS_SPI_VALID_SYNC_RATE 3314fa9ed865SMatt Jacob | CTS_SPI_VALID_SYNC_OFFSET 3315fa9ed865SMatt Jacob | CTS_SPI_VALID_BUS_WIDTH; 3316dac36688SXin LI } 331744f05562SScott Long } 3318ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 3319ad6d6297SScott Long xpt_done(pccb); 3320ad6d6297SScott Long break; 3321ad6d6297SScott Long } 3322ad6d6297SScott Long case XPT_SET_TRAN_SETTINGS: { 3323ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 3324ad6d6297SScott Long xpt_done(pccb); 3325ad6d6297SScott Long break; 3326ad6d6297SScott Long } 3327f3b080e6SMarius Strobl case XPT_CALC_GEOMETRY: 3328ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 3329ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 3330ad6d6297SScott Long xpt_done(pccb); 3331ad6d6297SScott Long break; 3332ad6d6297SScott Long } 3333f3b080e6SMarius Strobl cam_calc_geometry(&pccb->ccg, 1); 3334f1c579b1SScott Long xpt_done(pccb); 3335f1c579b1SScott Long break; 3336f1c579b1SScott Long default: 3337ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 3338f1c579b1SScott Long xpt_done(pccb); 3339f1c579b1SScott Long break; 3340f1c579b1SScott Long } 3341f1c579b1SScott Long } 3342f1c579b1SScott Long /* 3343f1c579b1SScott Long ********************************************************************** 3344f1c579b1SScott Long ********************************************************************** 3345f1c579b1SScott Long */ 334644f05562SScott Long static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) 3347f1c579b1SScott Long { 3348ad6d6297SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 334944f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 335044f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 3351ad6d6297SScott Long printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 3352ad6d6297SScott Long } 3353f1c579b1SScott Long } 3354f1c579b1SScott Long /* 3355f1c579b1SScott Long ********************************************************************** 3356f1c579b1SScott Long ********************************************************************** 3357f1c579b1SScott Long */ 335844f05562SScott Long static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb) 335944f05562SScott Long { 3360b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 336144f05562SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 3362b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_START_BGRB); 336344f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 336444f05562SScott Long printf( "arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 336544f05562SScott Long } 336644f05562SScott Long } 336744f05562SScott Long /* 336844f05562SScott Long ********************************************************************** 336944f05562SScott Long ********************************************************************** 337044f05562SScott Long */ 3371d74001adSXin LI static void arcmsr_start_hbc_bgrb(struct AdapterControlBlock *acb) 3372d74001adSXin LI { 3373d74001adSXin LI acb->acb_flags |= ACB_F_MSG_START_BGRB; 3374d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 3375d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 3376d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 3377d74001adSXin LI printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 3378d74001adSXin LI } 3379d74001adSXin LI } 3380d74001adSXin LI /* 3381d74001adSXin LI ********************************************************************** 3382d74001adSXin LI ********************************************************************** 3383d74001adSXin LI */ 33847a7bc959SXin LI static void arcmsr_start_hbd_bgrb(struct AdapterControlBlock *acb) 33857a7bc959SXin LI { 33867a7bc959SXin LI acb->acb_flags |= ACB_F_MSG_START_BGRB; 33877a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 33887a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 33897a7bc959SXin LI printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 33907a7bc959SXin LI } 33917a7bc959SXin LI } 33927a7bc959SXin LI /* 33937a7bc959SXin LI ********************************************************************** 33947a7bc959SXin LI ********************************************************************** 33957a7bc959SXin LI */ 3396a1103e04SXin LI static void arcmsr_start_hbe_bgrb(struct AdapterControlBlock *acb) 3397a1103e04SXin LI { 3398a1103e04SXin LI acb->acb_flags |= ACB_F_MSG_START_BGRB; 3399a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 3400a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 3401a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 3402a1103e04SXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) { 3403a1103e04SXin LI printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 3404a1103e04SXin LI } 3405a1103e04SXin LI } 3406a1103e04SXin LI /* 3407a1103e04SXin LI ********************************************************************** 3408a1103e04SXin LI ********************************************************************** 3409a1103e04SXin LI */ 341044f05562SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) 341144f05562SScott Long { 341244f05562SScott Long switch (acb->adapter_type) { 341344f05562SScott Long case ACB_ADAPTER_TYPE_A: 341444f05562SScott Long arcmsr_start_hba_bgrb(acb); 341544f05562SScott Long break; 341644f05562SScott Long case ACB_ADAPTER_TYPE_B: 341744f05562SScott Long arcmsr_start_hbb_bgrb(acb); 341844f05562SScott Long break; 3419d74001adSXin LI case ACB_ADAPTER_TYPE_C: 3420d74001adSXin LI arcmsr_start_hbc_bgrb(acb); 3421d74001adSXin LI break; 34227a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 34237a7bc959SXin LI arcmsr_start_hbd_bgrb(acb); 34247a7bc959SXin LI break; 3425a1103e04SXin LI case ACB_ADAPTER_TYPE_E: 3426fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 3427a1103e04SXin LI arcmsr_start_hbe_bgrb(acb); 3428a1103e04SXin LI break; 342944f05562SScott Long } 343044f05562SScott Long } 343144f05562SScott Long /* 343244f05562SScott Long ********************************************************************** 343344f05562SScott Long ** 343444f05562SScott Long ********************************************************************** 343544f05562SScott Long */ 343644f05562SScott Long static void arcmsr_polling_hba_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 3437f1c579b1SScott Long { 3438ad6d6297SScott Long struct CommandControlBlock *srb; 343944f05562SScott Long u_int32_t flag_srb, outbound_intstatus, poll_srb_done=0, poll_count=0; 3440d74001adSXin LI u_int16_t error; 3441f1c579b1SScott Long 344244f05562SScott Long polling_ccb_retry: 3443ad6d6297SScott Long poll_count++; 3444d74001adSXin LI outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 3445d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus); /*clear interrupt*/ 344644f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 3447ad6d6297SScott Long while(1) { 344844f05562SScott Long if((flag_srb = CHIP_REG_READ32(HBA_MessageUnit, 344944f05562SScott Long 0, outbound_queueport)) == 0xFFFFFFFF) { 3450ad6d6297SScott Long if(poll_srb_done) { 3451ad6d6297SScott Long break;/*chip FIFO no ccb for completion already*/ 3452ad6d6297SScott Long } else { 3453ad6d6297SScott Long UDELAY(25000); 3454d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 3455ad6d6297SScott Long break; 3456f1c579b1SScott Long } 345744f05562SScott Long goto polling_ccb_retry; 3458f1c579b1SScott Long } 3459ad6d6297SScott Long } 3460ad6d6297SScott Long /* check if command done with no error*/ 346144f05562SScott Long srb = (struct CommandControlBlock *) 346244f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 3463d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 346444f05562SScott Long poll_srb_done = (srb == poll_srb) ? 1:0; 346522f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 346622f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3467123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'" 3468ad6d6297SScott Long "poll command abort successfully \n" 3469ad6d6297SScott Long , acb->pci_unit 3470ad6d6297SScott Long , srb->pccb->ccb_h.target_id 3471123055f0SNathan Whitehorn , (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 3472ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 3473ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 3474ad6d6297SScott Long continue; 3475ad6d6297SScott Long } 3476ad6d6297SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 3477ad6d6297SScott Long "srboutstandingcount=%d \n" 3478ad6d6297SScott Long , acb->pci_unit 3479ad6d6297SScott Long , srb, acb->srboutstandingcount); 3480ad6d6297SScott Long continue; 3481ad6d6297SScott Long } 3482d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 3483ad6d6297SScott Long } /*drain reply FIFO*/ 3484f1c579b1SScott Long } 3485f1c579b1SScott Long /* 3486f1c579b1SScott Long ********************************************************************** 348744f05562SScott Long ** 3488ad6d6297SScott Long ********************************************************************** 3489ad6d6297SScott Long */ 349044f05562SScott Long static void arcmsr_polling_hbb_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 349144f05562SScott Long { 349244f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 349344f05562SScott Long struct CommandControlBlock *srb; 349444f05562SScott Long u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 349544f05562SScott Long int index; 3496d74001adSXin LI u_int16_t error; 349744f05562SScott Long 349844f05562SScott Long polling_ccb_retry: 349944f05562SScott Long poll_count++; 3500b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 350144f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 350244f05562SScott Long while(1) { 350344f05562SScott Long index = phbbmu->doneq_index; 350444f05562SScott Long if((flag_srb = phbbmu->done_qbuffer[index]) == 0) { 350544f05562SScott Long if(poll_srb_done) { 350644f05562SScott Long break;/*chip FIFO no ccb for completion already*/ 350744f05562SScott Long } else { 350844f05562SScott Long UDELAY(25000); 3509d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 351044f05562SScott Long break; 351144f05562SScott Long } 351244f05562SScott Long goto polling_ccb_retry; 351344f05562SScott Long } 351444f05562SScott Long } 351544f05562SScott Long phbbmu->done_qbuffer[index] = 0; 351644f05562SScott Long index++; 351744f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 351844f05562SScott Long phbbmu->doneq_index = index; 351944f05562SScott Long /* check if command done with no error*/ 352044f05562SScott Long srb = (struct CommandControlBlock *) 352144f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 3522d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 352344f05562SScott Long poll_srb_done = (srb == poll_srb) ? 1:0; 352422f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 352522f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3526123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'" 352744f05562SScott Long "poll command abort successfully \n" 352844f05562SScott Long , acb->pci_unit 352944f05562SScott Long , srb->pccb->ccb_h.target_id 3530123055f0SNathan Whitehorn , (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 353144f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 353244f05562SScott Long arcmsr_srb_complete(srb, 1); 353344f05562SScott Long continue; 353444f05562SScott Long } 353544f05562SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 353644f05562SScott Long "srboutstandingcount=%d \n" 353744f05562SScott Long , acb->pci_unit 353844f05562SScott Long , srb, acb->srboutstandingcount); 353944f05562SScott Long continue; 354044f05562SScott Long } 3541d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 3542d74001adSXin LI } /*drain reply FIFO*/ 3543d74001adSXin LI } 3544d74001adSXin LI /* 3545d74001adSXin LI ********************************************************************** 3546d74001adSXin LI ** 3547d74001adSXin LI ********************************************************************** 3548d74001adSXin LI */ 3549d74001adSXin LI static void arcmsr_polling_hbc_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 3550d74001adSXin LI { 3551d74001adSXin LI struct CommandControlBlock *srb; 3552d74001adSXin LI u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 3553d74001adSXin LI u_int16_t error; 3554d74001adSXin LI 3555d74001adSXin LI polling_ccb_retry: 3556d74001adSXin LI poll_count++; 3557d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 3558d74001adSXin LI while(1) { 3559d74001adSXin LI if(!(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR)) { 3560d74001adSXin LI if(poll_srb_done) { 3561d74001adSXin LI break;/*chip FIFO no ccb for completion already*/ 3562d74001adSXin LI } else { 3563d74001adSXin LI UDELAY(25000); 3564d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 3565d74001adSXin LI break; 3566d74001adSXin LI } 3567d74001adSXin LI if (acb->srboutstandingcount == 0) { 3568d74001adSXin LI break; 3569d74001adSXin LI } 3570d74001adSXin LI goto polling_ccb_retry; 3571d74001adSXin LI } 3572d74001adSXin LI } 3573d74001adSXin LI flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 3574d74001adSXin LI /* check if command done with no error*/ 357522f2616bSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/ 3576d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; 3577d74001adSXin LI if (poll_srb != NULL) 3578d74001adSXin LI poll_srb_done = (srb == poll_srb) ? 1:0; 357922f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 358022f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3581123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n" 3582123055f0SNathan Whitehorn , acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 3583d74001adSXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 3584d74001adSXin LI arcmsr_srb_complete(srb, 1); 3585d74001adSXin LI continue; 3586d74001adSXin LI } 3587d74001adSXin LI printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n" 3588d74001adSXin LI , acb->pci_unit, srb, acb->srboutstandingcount); 3589d74001adSXin LI continue; 3590d74001adSXin LI } 3591d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 359244f05562SScott Long } /*drain reply FIFO*/ 359344f05562SScott Long } 359444f05562SScott Long /* 359544f05562SScott Long ********************************************************************** 35967a7bc959SXin LI ** 35977a7bc959SXin LI ********************************************************************** 35987a7bc959SXin LI */ 35997a7bc959SXin LI static void arcmsr_polling_hbd_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 36007a7bc959SXin LI { 36017a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 36027a7bc959SXin LI struct CommandControlBlock *srb; 36037a7bc959SXin LI u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 36047a7bc959SXin LI u_int32_t outbound_write_pointer; 36057a7bc959SXin LI u_int16_t error, doneq_index; 36067a7bc959SXin LI 36077a7bc959SXin LI polling_ccb_retry: 36087a7bc959SXin LI poll_count++; 36097a7bc959SXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 36107a7bc959SXin LI while(1) { 36117a7bc959SXin LI outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow; 36127a7bc959SXin LI doneq_index = phbdmu->doneq_index; 36137a7bc959SXin LI if ((outbound_write_pointer & 0xFF) == (doneq_index & 0xFF)) { 36147a7bc959SXin LI if(poll_srb_done) { 36157a7bc959SXin LI break;/*chip FIFO no ccb for completion already*/ 36167a7bc959SXin LI } else { 36177a7bc959SXin LI UDELAY(25000); 36187a7bc959SXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 36197a7bc959SXin LI break; 36207a7bc959SXin LI } 36217a7bc959SXin LI if (acb->srboutstandingcount == 0) { 36227a7bc959SXin LI break; 36237a7bc959SXin LI } 36247a7bc959SXin LI goto polling_ccb_retry; 36257a7bc959SXin LI } 36267a7bc959SXin LI } 36277a7bc959SXin LI doneq_index = arcmsr_get_doneq_index(phbdmu); 36287a7bc959SXin LI flag_srb = phbdmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow; 36297a7bc959SXin LI /* check if command done with no error*/ 36307a7bc959SXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/ 36317a7bc959SXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 36327a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_read_pointer, doneq_index); 36337a7bc959SXin LI if (poll_srb != NULL) 36347a7bc959SXin LI poll_srb_done = (srb == poll_srb) ? 1:0; 36357a7bc959SXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 36367a7bc959SXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3637123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n" 3638123055f0SNathan Whitehorn , acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 36397a7bc959SXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 36407a7bc959SXin LI arcmsr_srb_complete(srb, 1); 36417a7bc959SXin LI continue; 36427a7bc959SXin LI } 36437a7bc959SXin LI printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n" 36447a7bc959SXin LI , acb->pci_unit, srb, acb->srboutstandingcount); 36457a7bc959SXin LI continue; 36467a7bc959SXin LI } 36477a7bc959SXin LI arcmsr_report_srb_state(acb, srb, error); 36487a7bc959SXin LI } /*drain reply FIFO*/ 36497a7bc959SXin LI } 36507a7bc959SXin LI /* 36517a7bc959SXin LI ********************************************************************** 3652a1103e04SXin LI ** 3653a1103e04SXin LI ********************************************************************** 3654a1103e04SXin LI */ 3655a1103e04SXin LI static void arcmsr_polling_hbe_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 3656a1103e04SXin LI { 3657a1103e04SXin LI struct CommandControlBlock *srb; 3658a1103e04SXin LI u_int32_t poll_srb_done=0, poll_count=0, doneq_index; 3659a1103e04SXin LI u_int16_t error, cmdSMID; 3660a1103e04SXin LI 3661a1103e04SXin LI polling_ccb_retry: 3662a1103e04SXin LI poll_count++; 3663a1103e04SXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 3664a1103e04SXin LI while(1) { 3665a1103e04SXin LI doneq_index = acb->doneq_index; 3666a1103e04SXin LI if((CHIP_REG_READ32(HBE_MessageUnit, 0, reply_post_producer_index) & 0xFFFF) == doneq_index) { 3667a1103e04SXin LI if(poll_srb_done) { 3668a1103e04SXin LI break;/*chip FIFO no ccb for completion already*/ 3669a1103e04SXin LI } else { 3670a1103e04SXin LI UDELAY(25000); 3671a1103e04SXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 3672a1103e04SXin LI break; 3673a1103e04SXin LI } 3674a1103e04SXin LI if (acb->srboutstandingcount == 0) { 3675a1103e04SXin LI break; 3676a1103e04SXin LI } 3677a1103e04SXin LI goto polling_ccb_retry; 3678a1103e04SXin LI } 3679a1103e04SXin LI } 3680a1103e04SXin LI cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID; 3681a1103e04SXin LI doneq_index++; 3682a1103e04SXin LI if (doneq_index >= acb->completionQ_entry) 3683a1103e04SXin LI doneq_index = 0; 3684a1103e04SXin LI acb->doneq_index = doneq_index; 3685a1103e04SXin LI srb = acb->psrb_pool[cmdSMID]; 3686a1103e04SXin LI error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 3687a1103e04SXin LI if (poll_srb != NULL) 3688a1103e04SXin LI poll_srb_done = (srb == poll_srb) ? 1:0; 3689a1103e04SXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 3690a1103e04SXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3691a1103e04SXin LI printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n" 3692a1103e04SXin LI , acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 3693a1103e04SXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 3694a1103e04SXin LI arcmsr_srb_complete(srb, 1); 3695a1103e04SXin LI continue; 3696a1103e04SXin LI } 3697a1103e04SXin LI printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n" 3698a1103e04SXin LI , acb->pci_unit, srb, acb->srboutstandingcount); 3699a1103e04SXin LI continue; 3700a1103e04SXin LI } 3701a1103e04SXin LI arcmsr_report_srb_state(acb, srb, error); 3702a1103e04SXin LI } /*drain reply FIFO*/ 3703a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, reply_post_producer_index, doneq_index); 3704a1103e04SXin LI } 3705a1103e04SXin LI /* 3706a1103e04SXin LI ********************************************************************** 370744f05562SScott Long ********************************************************************** 370844f05562SScott Long */ 370944f05562SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 371044f05562SScott Long { 371144f05562SScott Long switch (acb->adapter_type) { 3712fa42a0bfSXin LI case ACB_ADAPTER_TYPE_A: 371344f05562SScott Long arcmsr_polling_hba_srbdone(acb, poll_srb); 371444f05562SScott Long break; 3715fa42a0bfSXin LI case ACB_ADAPTER_TYPE_B: 371644f05562SScott Long arcmsr_polling_hbb_srbdone(acb, poll_srb); 371744f05562SScott Long break; 3718fa42a0bfSXin LI case ACB_ADAPTER_TYPE_C: 3719d74001adSXin LI arcmsr_polling_hbc_srbdone(acb, poll_srb); 3720d74001adSXin LI break; 3721fa42a0bfSXin LI case ACB_ADAPTER_TYPE_D: 37227a7bc959SXin LI arcmsr_polling_hbd_srbdone(acb, poll_srb); 37237a7bc959SXin LI break; 3724fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 3725fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 3726a1103e04SXin LI arcmsr_polling_hbe_srbdone(acb, poll_srb); 3727a1103e04SXin LI break; 372844f05562SScott Long } 372944f05562SScott Long } 373044f05562SScott Long /* 373144f05562SScott Long ********************************************************************** 373244f05562SScott Long ********************************************************************** 373344f05562SScott Long */ 373444f05562SScott Long static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) 3735ad6d6297SScott Long { 3736ad6d6297SScott Long char *acb_firm_model = acb->firm_model; 3737ad6d6297SScott Long char *acb_firm_version = acb->firm_version; 3738d74001adSXin LI char *acb_device_map = acb->device_map; 3739d74001adSXin LI size_t iop_firm_model = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3740d74001adSXin LI size_t iop_firm_version = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3741d74001adSXin LI size_t iop_device_map = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 3742ad6d6297SScott Long int i; 3743ad6d6297SScott Long 374444f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 374544f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 3746d74001adSXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 3747ad6d6297SScott Long } 3748ad6d6297SScott Long i = 0; 3749ad6d6297SScott Long while(i < 8) { 375044f05562SScott Long *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 3751ad6d6297SScott Long /* 8 bytes firm_model, 15, 60-67*/ 3752ad6d6297SScott Long acb_firm_model++; 3753ad6d6297SScott Long i++; 3754ad6d6297SScott Long } 3755ad6d6297SScott Long i=0; 3756ad6d6297SScott Long while(i < 16) { 375744f05562SScott Long *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 3758ad6d6297SScott Long /* 16 bytes firm_version, 17, 68-83*/ 3759ad6d6297SScott Long acb_firm_version++; 3760ad6d6297SScott Long i++; 3761ad6d6297SScott Long } 3762d74001adSXin LI i=0; 3763d74001adSXin LI while(i < 16) { 3764d74001adSXin LI *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 3765d74001adSXin LI acb_device_map++; 3766d74001adSXin LI i++; 3767d74001adSXin LI } 37681e7d660aSXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 3769d74001adSXin LI acb->firm_request_len = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3770d74001adSXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3771d74001adSXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3772d74001adSXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3773d74001adSXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3774abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD) 3775abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1; 3776abfdbca9SXin LI else 3777abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 3778ad6d6297SScott Long } 3779ad6d6297SScott Long /* 3780ad6d6297SScott Long ********************************************************************** 378144f05562SScott Long ********************************************************************** 378244f05562SScott Long */ 378344f05562SScott Long static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) 378444f05562SScott Long { 3785b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 378644f05562SScott Long char *acb_firm_model = acb->firm_model; 378744f05562SScott Long char *acb_firm_version = acb->firm_version; 3788d74001adSXin LI char *acb_device_map = acb->device_map; 3789d74001adSXin LI size_t iop_firm_model = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3790d74001adSXin LI size_t iop_firm_version = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3791d74001adSXin LI size_t iop_device_map = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 379244f05562SScott Long int i; 379344f05562SScott Long 3794b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG); 379544f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 3796d74001adSXin LI printf( "arcmsr%d: wait" "'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 379744f05562SScott Long } 379844f05562SScott Long i = 0; 379944f05562SScott Long while(i < 8) { 380044f05562SScott Long *acb_firm_model = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_model+i); 380144f05562SScott Long /* 8 bytes firm_model, 15, 60-67*/ 380244f05562SScott Long acb_firm_model++; 380344f05562SScott Long i++; 380444f05562SScott Long } 380544f05562SScott Long i = 0; 380644f05562SScott Long while(i < 16) { 380744f05562SScott Long *acb_firm_version = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_version+i); 380844f05562SScott Long /* 16 bytes firm_version, 17, 68-83*/ 380944f05562SScott Long acb_firm_version++; 381044f05562SScott Long i++; 381144f05562SScott Long } 3812d74001adSXin LI i = 0; 3813d74001adSXin LI while(i < 16) { 3814d74001adSXin LI *acb_device_map = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_device_map+i); 3815d74001adSXin LI acb_device_map++; 3816d74001adSXin LI i++; 3817d74001adSXin LI } 38181e7d660aSXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 3819d74001adSXin LI acb->firm_request_len = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3820d74001adSXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3821d74001adSXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3822d74001adSXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3823d74001adSXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3824abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_HBB_POSTQUEUE) 3825abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_HBB_POSTQUEUE - 1; 3826abfdbca9SXin LI else 3827abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 3828d74001adSXin LI } 3829d74001adSXin LI /* 3830d74001adSXin LI ********************************************************************** 3831d74001adSXin LI ********************************************************************** 3832d74001adSXin LI */ 3833d74001adSXin LI static void arcmsr_get_hbc_config(struct AdapterControlBlock *acb) 3834d74001adSXin LI { 3835d74001adSXin LI char *acb_firm_model = acb->firm_model; 3836d74001adSXin LI char *acb_firm_version = acb->firm_version; 3837d74001adSXin LI char *acb_device_map = acb->device_map; 3838d74001adSXin LI size_t iop_firm_model = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3839d74001adSXin LI size_t iop_firm_version = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3840d74001adSXin LI size_t iop_device_map = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 3841d74001adSXin LI int i; 3842d74001adSXin LI 3843d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 3844d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 3845d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 3846d74001adSXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 3847d74001adSXin LI } 3848d74001adSXin LI i = 0; 3849d74001adSXin LI while(i < 8) { 3850d74001adSXin LI *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 3851d74001adSXin LI /* 8 bytes firm_model, 15, 60-67*/ 3852d74001adSXin LI acb_firm_model++; 3853d74001adSXin LI i++; 3854d74001adSXin LI } 3855d74001adSXin LI i = 0; 3856d74001adSXin LI while(i < 16) { 3857d74001adSXin LI *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 3858d74001adSXin LI /* 16 bytes firm_version, 17, 68-83*/ 3859d74001adSXin LI acb_firm_version++; 3860d74001adSXin LI i++; 3861d74001adSXin LI } 3862d74001adSXin LI i = 0; 3863d74001adSXin LI while(i < 16) { 3864d74001adSXin LI *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 3865d74001adSXin LI acb_device_map++; 3866d74001adSXin LI i++; 3867d74001adSXin LI } 38681e7d660aSXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 3869d74001adSXin LI acb->firm_request_len = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3870d74001adSXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3871d74001adSXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3872d74001adSXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3873d74001adSXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3874abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD) 3875abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1; 3876abfdbca9SXin LI else 3877abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 387844f05562SScott Long } 387944f05562SScott Long /* 388044f05562SScott Long ********************************************************************** 388144f05562SScott Long ********************************************************************** 388244f05562SScott Long */ 38837a7bc959SXin LI static void arcmsr_get_hbd_config(struct AdapterControlBlock *acb) 38847a7bc959SXin LI { 38857a7bc959SXin LI char *acb_firm_model = acb->firm_model; 38867a7bc959SXin LI char *acb_firm_version = acb->firm_version; 38877a7bc959SXin LI char *acb_device_map = acb->device_map; 38887a7bc959SXin LI size_t iop_firm_model = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 38897a7bc959SXin LI size_t iop_firm_version = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 38907a7bc959SXin LI size_t iop_device_map = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 38917a7bc959SXin LI int i; 38927a7bc959SXin LI 38937a7bc959SXin LI if(CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) 38947a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR); 38957a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 38967a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 38977a7bc959SXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 38987a7bc959SXin LI } 38997a7bc959SXin LI i = 0; 39007a7bc959SXin LI while(i < 8) { 39017a7bc959SXin LI *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 39027a7bc959SXin LI /* 8 bytes firm_model, 15, 60-67*/ 39037a7bc959SXin LI acb_firm_model++; 39047a7bc959SXin LI i++; 39057a7bc959SXin LI } 39067a7bc959SXin LI i = 0; 39077a7bc959SXin LI while(i < 16) { 39087a7bc959SXin LI *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 39097a7bc959SXin LI /* 16 bytes firm_version, 17, 68-83*/ 39107a7bc959SXin LI acb_firm_version++; 39117a7bc959SXin LI i++; 39127a7bc959SXin LI } 39137a7bc959SXin LI i = 0; 39147a7bc959SXin LI while(i < 16) { 39157a7bc959SXin LI *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 39167a7bc959SXin LI acb_device_map++; 39177a7bc959SXin LI i++; 39187a7bc959SXin LI } 39191e7d660aSXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 3920b23a1998SXin LI acb->firm_request_len = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3921b23a1998SXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3922b23a1998SXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3923b23a1998SXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 39247a7bc959SXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3925abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_HBD_POSTQUEUE) 3926abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_HBD_POSTQUEUE - 1; 3927abfdbca9SXin LI else 3928abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 39297a7bc959SXin LI } 39307a7bc959SXin LI /* 39317a7bc959SXin LI ********************************************************************** 39327a7bc959SXin LI ********************************************************************** 39337a7bc959SXin LI */ 3934a1103e04SXin LI static void arcmsr_get_hbe_config(struct AdapterControlBlock *acb) 3935a1103e04SXin LI { 3936a1103e04SXin LI char *acb_firm_model = acb->firm_model; 3937a1103e04SXin LI char *acb_firm_version = acb->firm_version; 3938a1103e04SXin LI char *acb_device_map = acb->device_map; 3939a1103e04SXin LI size_t iop_firm_model = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3940a1103e04SXin LI size_t iop_firm_version = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3941a1103e04SXin LI size_t iop_device_map = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 3942a1103e04SXin LI int i; 3943a1103e04SXin LI 3944a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 3945a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 3946a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 3947a1103e04SXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) { 3948a1103e04SXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 3949a1103e04SXin LI } 3950a1103e04SXin LI 3951a1103e04SXin LI i = 0; 3952a1103e04SXin LI while(i < 8) { 3953a1103e04SXin LI *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 3954a1103e04SXin LI /* 8 bytes firm_model, 15, 60-67*/ 3955a1103e04SXin LI acb_firm_model++; 3956a1103e04SXin LI i++; 3957a1103e04SXin LI } 3958a1103e04SXin LI i = 0; 3959a1103e04SXin LI while(i < 16) { 3960a1103e04SXin LI *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 3961a1103e04SXin LI /* 16 bytes firm_version, 17, 68-83*/ 3962a1103e04SXin LI acb_firm_version++; 3963a1103e04SXin LI i++; 3964a1103e04SXin LI } 3965a1103e04SXin LI i = 0; 3966a1103e04SXin LI while(i < 16) { 3967a1103e04SXin LI *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 3968a1103e04SXin LI acb_device_map++; 3969a1103e04SXin LI i++; 3970a1103e04SXin LI } 3971a1103e04SXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 3972a1103e04SXin LI acb->firm_request_len = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3973a1103e04SXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3974a1103e04SXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3975a1103e04SXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3976a1103e04SXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3977a1103e04SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD) 3978a1103e04SXin LI acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1; 3979a1103e04SXin LI else 3980a1103e04SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 3981a1103e04SXin LI } 3982a1103e04SXin LI /* 3983a1103e04SXin LI ********************************************************************** 3984a1103e04SXin LI ********************************************************************** 3985a1103e04SXin LI */ 3986fa42a0bfSXin LI static void arcmsr_get_hbf_config(struct AdapterControlBlock *acb) 3987fa42a0bfSXin LI { 3988fa42a0bfSXin LI u_int32_t *acb_firm_model = (u_int32_t *)acb->firm_model; 3989fa42a0bfSXin LI u_int32_t *acb_firm_version = (u_int32_t *)acb->firm_version; 3990fa42a0bfSXin LI u_int32_t *acb_device_map = (u_int32_t *)acb->device_map; 3991fa42a0bfSXin LI size_t iop_firm_model = ARCMSR_FW_MODEL_OFFSET; /*firm_model,15,60-67*/ 3992fa42a0bfSXin LI size_t iop_firm_version = ARCMSR_FW_VERS_OFFSET; /*firm_version,17,68-83*/ 3993fa42a0bfSXin LI size_t iop_device_map = ARCMSR_FW_DEVMAP_OFFSET; 3994fa42a0bfSXin LI int i; 3995fa42a0bfSXin LI 3996fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 3997fa42a0bfSXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 3998fa42a0bfSXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 3999fa42a0bfSXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) 4000fa42a0bfSXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 4001fa42a0bfSXin LI 4002fa42a0bfSXin LI i = 0; 4003fa42a0bfSXin LI while(i < 2) { 4004fa42a0bfSXin LI *acb_firm_model = acb->msgcode_rwbuffer[iop_firm_model]; 4005fa42a0bfSXin LI /* 8 bytes firm_model, 15, 60-67*/ 4006fa42a0bfSXin LI acb_firm_model++; 4007fa42a0bfSXin LI iop_firm_model++; 4008fa42a0bfSXin LI i++; 4009fa42a0bfSXin LI } 4010fa42a0bfSXin LI i = 0; 4011fa42a0bfSXin LI while(i < 4) { 4012fa42a0bfSXin LI *acb_firm_version = acb->msgcode_rwbuffer[iop_firm_version]; 4013fa42a0bfSXin LI /* 16 bytes firm_version, 17, 68-83*/ 4014fa42a0bfSXin LI acb_firm_version++; 4015fa42a0bfSXin LI iop_firm_version++; 4016fa42a0bfSXin LI i++; 4017fa42a0bfSXin LI } 4018fa42a0bfSXin LI i = 0; 4019fa42a0bfSXin LI while(i < 4) { 4020fa42a0bfSXin LI *acb_device_map = acb->msgcode_rwbuffer[iop_device_map]; 4021fa42a0bfSXin LI acb_device_map++; 4022fa42a0bfSXin LI iop_device_map++; 4023fa42a0bfSXin LI i++; 4024fa42a0bfSXin LI } 4025fa42a0bfSXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 4026fa42a0bfSXin LI acb->firm_request_len = acb->msgcode_rwbuffer[1]; /*firm_request_len, 1, 04-07*/ 4027fa42a0bfSXin LI acb->firm_numbers_queue = acb->msgcode_rwbuffer[2]; /*firm_numbers_queue, 2, 08-11*/ 4028fa42a0bfSXin LI acb->firm_sdram_size = acb->msgcode_rwbuffer[3]; /*firm_sdram_size, 3, 12-15*/ 4029fa42a0bfSXin LI acb->firm_ide_channels = acb->msgcode_rwbuffer[4]; /*firm_ide_channels, 4, 16-19*/ 4030fa42a0bfSXin LI acb->firm_cfg_version = acb->msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]; /*firm_cfg_version, 25*/ 4031fa42a0bfSXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD) 4032fa42a0bfSXin LI acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1; 4033fa42a0bfSXin LI else 4034fa42a0bfSXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 4035fa42a0bfSXin LI } 4036fa42a0bfSXin LI /* 4037fa42a0bfSXin LI ********************************************************************** 4038fa42a0bfSXin LI ********************************************************************** 4039fa42a0bfSXin LI */ 404044f05562SScott Long static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) 404144f05562SScott Long { 404244f05562SScott Long switch (acb->adapter_type) { 4043fa42a0bfSXin LI case ACB_ADAPTER_TYPE_A: 404444f05562SScott Long arcmsr_get_hba_config(acb); 404544f05562SScott Long break; 4046fa42a0bfSXin LI case ACB_ADAPTER_TYPE_B: 404744f05562SScott Long arcmsr_get_hbb_config(acb); 404844f05562SScott Long break; 4049fa42a0bfSXin LI case ACB_ADAPTER_TYPE_C: 4050d74001adSXin LI arcmsr_get_hbc_config(acb); 4051d74001adSXin LI break; 4052fa42a0bfSXin LI case ACB_ADAPTER_TYPE_D: 40537a7bc959SXin LI arcmsr_get_hbd_config(acb); 40547a7bc959SXin LI break; 4055fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 4056a1103e04SXin LI arcmsr_get_hbe_config(acb); 4057fa42a0bfSXin LI break; 4058fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: 4059fa42a0bfSXin LI arcmsr_get_hbf_config(acb); 4060a1103e04SXin LI break; 406144f05562SScott Long } 406244f05562SScott Long } 406344f05562SScott Long /* 406444f05562SScott Long ********************************************************************** 406544f05562SScott Long ********************************************************************** 406644f05562SScott Long */ 406744f05562SScott Long static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb) 406844f05562SScott Long { 406944f05562SScott Long int timeout=0; 407044f05562SScott Long 407144f05562SScott Long switch (acb->adapter_type) { 407244f05562SScott Long case ACB_ADAPTER_TYPE_A: { 4073d74001adSXin LI while ((CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) 407444f05562SScott Long { 407544f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 407644f05562SScott Long { 4077d74001adSXin LI printf( "arcmsr%d:timed out waiting for firmware \n", acb->pci_unit); 407844f05562SScott Long return; 407944f05562SScott Long } 408044f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 408144f05562SScott Long } 408244f05562SScott Long } 408344f05562SScott Long break; 408444f05562SScott Long case ACB_ADAPTER_TYPE_B: { 4085b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 4086b23a1998SXin LI while ((READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & ARCMSR_MESSAGE_FIRMWARE_OK) == 0) 408744f05562SScott Long { 408844f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 408944f05562SScott Long { 4090d74001adSXin LI printf( "arcmsr%d: timed out waiting for firmware \n", acb->pci_unit); 409144f05562SScott Long return; 409244f05562SScott Long } 409344f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 409444f05562SScott Long } 4095b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 4096d74001adSXin LI } 4097d74001adSXin LI break; 4098d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 4099d74001adSXin LI while ((CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0) 4100d74001adSXin LI { 4101d74001adSXin LI if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 4102d74001adSXin LI { 4103d74001adSXin LI printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit); 4104d74001adSXin LI return; 4105d74001adSXin LI } 4106d74001adSXin LI UDELAY(15000); /* wait 15 milli-seconds */ 4107d74001adSXin LI } 410844f05562SScott Long } 410944f05562SScott Long break; 41107a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 41117a7bc959SXin LI while ((CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBDMU_MESSAGE_FIRMWARE_OK) == 0) 41127a7bc959SXin LI { 41137a7bc959SXin LI if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 41147a7bc959SXin LI { 41157a7bc959SXin LI printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit); 41167a7bc959SXin LI return; 41177a7bc959SXin LI } 41187a7bc959SXin LI UDELAY(15000); /* wait 15 milli-seconds */ 41197a7bc959SXin LI } 41207a7bc959SXin LI } 41217a7bc959SXin LI break; 4122fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 4123fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 4124a1103e04SXin LI while ((CHIP_REG_READ32(HBE_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBEMU_MESSAGE_FIRMWARE_OK) == 0) 4125a1103e04SXin LI { 4126a1103e04SXin LI if (timeout++ > 4000) /* (4000*15)/1000 = 60 sec */ 4127a1103e04SXin LI { 4128a1103e04SXin LI printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit); 4129a1103e04SXin LI return; 4130a1103e04SXin LI } 4131a1103e04SXin LI UDELAY(15000); /* wait 15 milli-seconds */ 4132a1103e04SXin LI } 4133a1103e04SXin LI } 4134a1103e04SXin LI break; 413544f05562SScott Long } 413644f05562SScott Long } 413744f05562SScott Long /* 413844f05562SScott Long ********************************************************************** 413944f05562SScott Long ********************************************************************** 414044f05562SScott Long */ 414144f05562SScott Long static void arcmsr_clear_doorbell_queue_buffer( struct AdapterControlBlock *acb) 414244f05562SScott Long { 4143d74001adSXin LI u_int32_t outbound_doorbell; 4144d74001adSXin LI 414544f05562SScott Long switch (acb->adapter_type) { 414644f05562SScott Long case ACB_ADAPTER_TYPE_A: { 414744f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 4148d74001adSXin LI outbound_doorbell = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell); 4149d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, outbound_doorbell); /*clear doorbell interrupt */ 4150d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 415144f05562SScott Long } 415244f05562SScott Long break; 415344f05562SScott Long case ACB_ADAPTER_TYPE_B: { 4154b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 4155fc5ef1caSXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN);/*clear interrupt and message state*/ 4156b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 415744f05562SScott Long /* let IOP know data has been read */ 415844f05562SScott Long } 415944f05562SScott Long break; 4160d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 4161d74001adSXin LI /* empty doorbell Qbuffer if door bell ringed */ 4162d74001adSXin LI outbound_doorbell = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); 4163d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell); /*clear doorbell interrupt */ 4164d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK); 41657a7bc959SXin LI CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell_clear); /* Dummy read to force pci flush */ 41667a7bc959SXin LI CHIP_REG_READ32(HBC_MessageUnit, 0, inbound_doorbell); /* Dummy read to force pci flush */ 41677a7bc959SXin LI } 41687a7bc959SXin LI break; 41697a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 41707a7bc959SXin LI /* empty doorbell Qbuffer if door bell ringed */ 41717a7bc959SXin LI outbound_doorbell = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell); 41727a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, outbound_doorbell); /*clear doorbell interrupt */ 41737a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ); 4174d74001adSXin LI } 4175d74001adSXin LI break; 4176fa42a0bfSXin LI case ACB_ADAPTER_TYPE_E: 4177fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 4178a1103e04SXin LI /* empty doorbell Qbuffer if door bell ringed */ 4179a1103e04SXin LI acb->in_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell); 4180a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /*clear doorbell interrupt */ 4181a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK; 4182a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 4183a1103e04SXin LI } 4184a1103e04SXin LI break; 418544f05562SScott Long } 418644f05562SScott Long } 418744f05562SScott Long /* 418844f05562SScott Long ************************************************************************ 418944f05562SScott Long ************************************************************************ 419044f05562SScott Long */ 419144f05562SScott Long static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb) 419244f05562SScott Long { 419344f05562SScott Long unsigned long srb_phyaddr; 419444f05562SScott Long u_int32_t srb_phyaddr_hi32; 41957a7bc959SXin LI u_int32_t srb_phyaddr_lo32; 419644f05562SScott Long 419744f05562SScott Long /* 419844f05562SScott Long ******************************************************************** 419944f05562SScott Long ** here we need to tell iop 331 our freesrb.HighPart 420044f05562SScott Long ** if freesrb.HighPart is not zero 420144f05562SScott Long ******************************************************************** 420244f05562SScott Long */ 4203d74001adSXin LI srb_phyaddr = (unsigned long) acb->srb_phyaddr.phyaddr; 4204d74001adSXin LI srb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high; 42057a7bc959SXin LI srb_phyaddr_lo32 = acb->srb_phyaddr.B.phyadd_low; 420644f05562SScott Long switch (acb->adapter_type) { 420744f05562SScott Long case ACB_ADAPTER_TYPE_A: { 420844f05562SScott Long if(srb_phyaddr_hi32 != 0) { 4209d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 4210d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 4211d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 421244f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 4213d74001adSXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 421444f05562SScott Long return FALSE; 421544f05562SScott Long } 421644f05562SScott Long } 421744f05562SScott Long } 421844f05562SScott Long break; 421944f05562SScott Long /* 422044f05562SScott Long *********************************************************************** 422144f05562SScott Long ** if adapter type B, set window of "post command Q" 422244f05562SScott Long *********************************************************************** 422344f05562SScott Long */ 422444f05562SScott Long case ACB_ADAPTER_TYPE_B: { 422544f05562SScott Long u_int32_t post_queue_phyaddr; 422644f05562SScott Long struct HBB_MessageUnit *phbbmu; 422744f05562SScott Long 422844f05562SScott Long phbbmu = (struct HBB_MessageUnit *)acb->pmu; 422944f05562SScott Long phbbmu->postq_index = 0; 423044f05562SScott Long phbbmu->doneq_index = 0; 4231b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_SET_POST_WINDOW); 423244f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 4233d74001adSXin LI printf( "arcmsr%d: 'set window of post command Q' timeout\n", acb->pci_unit); 423444f05562SScott Long return FALSE; 423544f05562SScott Long } 423622f2616bSXin LI post_queue_phyaddr = srb_phyaddr + ARCMSR_SRBS_POOL_SIZE 423744f05562SScott Long + offsetof(struct HBB_MessageUnit, post_qbuffer); 4238d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */ 4239d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1], srb_phyaddr_hi32); /* normal should be zero */ 4240d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ size (256+8)*4 */ 4241d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3], post_queue_phyaddr+1056); /* doneQ size (256+8)*4 */ 4242d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4], 1056); /* srb maxQ size must be --> [(256+8)*4] */ 4243b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_SET_CONFIG); 424444f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 424544f05562SScott Long printf( "arcmsr%d: 'set command Q window' timeout \n", acb->pci_unit); 424644f05562SScott Long return FALSE; 424744f05562SScott Long } 4248b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_START_DRIVER_MODE); 424944f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 425044f05562SScott Long printf( "arcmsr%d: 'start diver mode' timeout \n", acb->pci_unit); 425144f05562SScott Long return FALSE; 425244f05562SScott Long } 425344f05562SScott Long } 425444f05562SScott Long break; 4255d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 4256d74001adSXin LI if(srb_phyaddr_hi32 != 0) { 4257d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 4258d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 4259d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 4260d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 4261d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 4262d74001adSXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 4263d74001adSXin LI return FALSE; 4264d74001adSXin LI } 4265d74001adSXin LI } 4266d74001adSXin LI } 4267d74001adSXin LI break; 42687a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 42697a7bc959SXin LI u_int32_t post_queue_phyaddr, done_queue_phyaddr; 42707a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu; 42717a7bc959SXin LI 42727a7bc959SXin LI phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 42737a7bc959SXin LI phbdmu->postq_index = 0; 42747a7bc959SXin LI phbdmu->doneq_index = 0x40FF; 42757a7bc959SXin LI post_queue_phyaddr = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE 42767a7bc959SXin LI + offsetof(struct HBD_MessageUnit0, post_qbuffer); 42777a7bc959SXin LI done_queue_phyaddr = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE 42787a7bc959SXin LI + offsetof(struct HBD_MessageUnit0, done_qbuffer); 42797a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */ 42807a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 42817a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ base */ 42827a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[3], done_queue_phyaddr); /* doneQ base */ 42837a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[4], 0x100); 42847a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 42857a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 42867a7bc959SXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 42877a7bc959SXin LI return FALSE; 42887a7bc959SXin LI } 42897a7bc959SXin LI } 42907a7bc959SXin LI break; 4291a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 4292a1103e04SXin LI u_int32_t cdb_phyaddr_lo32; 4293a1103e04SXin LI cdb_phyaddr_lo32 = srb_phyaddr_lo32 + offsetof(struct CommandControlBlock, arcmsr_cdb); 4294a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 4295a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[1], ARCMSR_SIGNATURE_1884); 4296a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[2], cdb_phyaddr_lo32); 4297a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[3], srb_phyaddr_hi32); 4298a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[4], SRB_SIZE); 4299a1103e04SXin LI cdb_phyaddr_lo32 = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE; 4300a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[5], cdb_phyaddr_lo32); 4301a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[6], srb_phyaddr_hi32); 4302a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[7], COMPLETION_Q_POOL_SIZE); 4303a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 4304a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 4305a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 4306a1103e04SXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) { 4307a1103e04SXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 4308a1103e04SXin LI return FALSE; 4309a1103e04SXin LI } 4310a1103e04SXin LI } 4311a1103e04SXin LI break; 4312fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 4313fa42a0bfSXin LI u_int32_t cdb_phyaddr_lo32; 4314fa42a0bfSXin LI cdb_phyaddr_lo32 = srb_phyaddr_lo32 + offsetof(struct CommandControlBlock, arcmsr_cdb); 4315fa42a0bfSXin LI acb->msgcode_rwbuffer[0] = ARCMSR_SIGNATURE_SET_CONFIG; 4316fa42a0bfSXin LI acb->msgcode_rwbuffer[1] = ARCMSR_SIGNATURE_1886; 4317fa42a0bfSXin LI acb->msgcode_rwbuffer[2] = cdb_phyaddr_lo32; 4318fa42a0bfSXin LI acb->msgcode_rwbuffer[3] = srb_phyaddr_hi32; 4319fa42a0bfSXin LI acb->msgcode_rwbuffer[4] = SRB_SIZE; 4320fa42a0bfSXin LI cdb_phyaddr_lo32 = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE; 4321fa42a0bfSXin LI acb->msgcode_rwbuffer[5] = cdb_phyaddr_lo32; 4322fa42a0bfSXin LI acb->msgcode_rwbuffer[6] = srb_phyaddr_hi32; 4323fa42a0bfSXin LI acb->msgcode_rwbuffer[7] = COMPLETION_Q_POOL_SIZE; 4324fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 4325fa42a0bfSXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 4326fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 4327fa42a0bfSXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) { 4328fa42a0bfSXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 4329fa42a0bfSXin LI return FALSE; 4330fa42a0bfSXin LI } 4331fa42a0bfSXin LI } 4332fa42a0bfSXin LI break; 433344f05562SScott Long } 4334dac36688SXin LI return (TRUE); 433544f05562SScott Long } 433644f05562SScott Long /* 433744f05562SScott Long ************************************************************************ 433844f05562SScott Long ************************************************************************ 433944f05562SScott Long */ 434044f05562SScott Long static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb) 434144f05562SScott Long { 4342a1103e04SXin LI if (acb->adapter_type == ACB_ADAPTER_TYPE_B) 434344f05562SScott Long { 4344b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 4345b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_ACTIVE_EOI_MODE); 434644f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 4347d74001adSXin LI printf( "arcmsr%d: 'iop enable eoi mode' timeout \n", acb->pci_unit); 434844f05562SScott Long return; 434944f05562SScott Long } 435044f05562SScott Long } 435144f05562SScott Long } 435244f05562SScott Long /* 435344f05562SScott Long ********************************************************************** 4354ad6d6297SScott Long ********************************************************************** 4355ad6d6297SScott Long */ 4356ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb) 4357ad6d6297SScott Long { 435844f05562SScott Long u_int32_t intmask_org; 4359ad6d6297SScott Long 436044f05562SScott Long /* disable all outbound interrupt */ 436144f05562SScott Long intmask_org = arcmsr_disable_allintr(acb); 436244f05562SScott Long arcmsr_wait_firmware_ready(acb); 436344f05562SScott Long arcmsr_iop_confirm(acb); 4364ad6d6297SScott Long arcmsr_get_firmware_spec(acb); 436544f05562SScott Long /*start background rebuild*/ 4366ad6d6297SScott Long arcmsr_start_adapter_bgrb(acb); 436744f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 436844f05562SScott Long arcmsr_clear_doorbell_queue_buffer(acb); 436944f05562SScott Long arcmsr_enable_eoi_mode(acb); 437044f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 437144f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 4372ad6d6297SScott Long acb->acb_flags |= ACB_F_IOP_INITED; 4373ad6d6297SScott Long } 4374ad6d6297SScott Long /* 4375ad6d6297SScott Long ********************************************************************** 4376f1c579b1SScott Long ********************************************************************** 4377f1c579b1SScott Long */ 4378231c8b71SXin LI static void arcmsr_map_free_srb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 4379f1c579b1SScott Long { 4380ad6d6297SScott Long struct AdapterControlBlock *acb = arg; 4381ad6d6297SScott Long struct CommandControlBlock *srb_tmp; 438244f05562SScott Long u_int32_t i; 4383ad6d6297SScott Long unsigned long srb_phyaddr = (unsigned long)segs->ds_addr; 4384f1c579b1SScott Long 4385d74001adSXin LI acb->srb_phyaddr.phyaddr = srb_phyaddr; 43867a7bc959SXin LI srb_tmp = (struct CommandControlBlock *)acb->uncacheptr; 4387ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 438844f05562SScott Long if(bus_dmamap_create(acb->dm_segs_dmat, 438944f05562SScott Long /*flags*/0, &srb_tmp->dm_segs_dmamap) != 0) { 4390ad6d6297SScott Long acb->acb_flags |= ACB_F_MAPFREESRB_FAILD; 439144f05562SScott Long printf("arcmsr%d:" 439244f05562SScott Long " srb dmamap bus_dmamap_create error\n", acb->pci_unit); 4393ad6d6297SScott Long return; 4394ad6d6297SScott Long } 4395a1103e04SXin LI if((acb->adapter_type == ACB_ADAPTER_TYPE_C) || (acb->adapter_type == ACB_ADAPTER_TYPE_D) 4396fa42a0bfSXin LI || (acb->adapter_type == ACB_ADAPTER_TYPE_E) || (acb->adapter_type == ACB_ADAPTER_TYPE_F)) 43977a7bc959SXin LI { 43987a7bc959SXin LI srb_tmp->cdb_phyaddr_low = srb_phyaddr; 43997a7bc959SXin LI srb_tmp->cdb_phyaddr_high = (u_int32_t)((srb_phyaddr >> 16) >> 16); 44007a7bc959SXin LI } 44017a7bc959SXin LI else 44027a7bc959SXin LI srb_tmp->cdb_phyaddr_low = srb_phyaddr >> 5; 4403ad6d6297SScott Long srb_tmp->acb = acb; 4404a1103e04SXin LI srb_tmp->smid = i << 16; 4405ad6d6297SScott Long acb->srbworkingQ[i] = acb->psrb_pool[i] = srb_tmp; 440622f2616bSXin LI srb_phyaddr = srb_phyaddr + SRB_SIZE; 440722f2616bSXin LI srb_tmp = (struct CommandControlBlock *)((unsigned long)srb_tmp + SRB_SIZE); 4408ad6d6297SScott Long } 4409fc5ef1caSXin LI if (acb->adapter_type == ACB_ADAPTER_TYPE_E) 4410a1103e04SXin LI acb->pCompletionQ = (pCompletion_Q)srb_tmp; 4411fa42a0bfSXin LI else if (acb->adapter_type == ACB_ADAPTER_TYPE_F) { 4412fa42a0bfSXin LI acb->pCompletionQ = (pCompletion_Q)srb_tmp; 4413fa42a0bfSXin LI acb->completeQ_phys = srb_phyaddr; 4414fa42a0bfSXin LI memset(acb->pCompletionQ, 0xff, COMPLETION_Q_POOL_SIZE); 4415fa42a0bfSXin LI acb->message_wbuffer = (u_int32_t *)((unsigned long)acb->pCompletionQ + COMPLETION_Q_POOL_SIZE); 4416fa42a0bfSXin LI acb->message_rbuffer = (u_int32_t *)((unsigned long)acb->message_wbuffer + 0x100); 4417fa42a0bfSXin LI acb->msgcode_rwbuffer = (u_int32_t *)((unsigned long)acb->message_wbuffer + 0x200); 4418fa42a0bfSXin LI memset((void *)acb->message_wbuffer, 0, MESG_RW_BUFFER_SIZE); 4419fa42a0bfSXin LI } 4420ad6d6297SScott Long acb->vir2phy_offset = (unsigned long)srb_tmp - (unsigned long)srb_phyaddr; 4421f1c579b1SScott Long } 4422f1c579b1SScott Long /* 4423f1c579b1SScott Long ************************************************************************ 4424f1c579b1SScott Long ************************************************************************ 4425f1c579b1SScott Long */ 4426ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb) 4427f1c579b1SScott Long { 4428f1c579b1SScott Long /* remove the control device */ 4429ad6d6297SScott Long if(acb->ioctl_dev != NULL) { 4430ad6d6297SScott Long destroy_dev(acb->ioctl_dev); 4431f1c579b1SScott Long } 4432ad6d6297SScott Long bus_dmamap_unload(acb->srb_dmat, acb->srb_dmamap); 4433ad6d6297SScott Long bus_dmamap_destroy(acb->srb_dmat, acb->srb_dmamap); 4434ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 4435ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 4436ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 4437f1c579b1SScott Long } 4438f1c579b1SScott Long /* 4439f1c579b1SScott Long ************************************************************************ 4440f1c579b1SScott Long ************************************************************************ 4441f1c579b1SScott Long */ 44427a7bc959SXin LI static void arcmsr_mutex_init(struct AdapterControlBlock *acb) 44437a7bc959SXin LI { 44447a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->isr_lock, "arcmsr isr lock"); 44457a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->srb_lock, "arcmsr srb lock"); 44467a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->postDone_lock, "arcmsr postQ lock"); 44477a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->qbuffer_lock, "arcmsr RW buffer lock"); 44487a7bc959SXin LI } 44497a7bc959SXin LI /* 44507a7bc959SXin LI ************************************************************************ 44517a7bc959SXin LI ************************************************************************ 44527a7bc959SXin LI */ 44537a7bc959SXin LI static void arcmsr_mutex_destroy(struct AdapterControlBlock *acb) 44547a7bc959SXin LI { 44557a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 44567a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->postDone_lock); 44577a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->srb_lock); 44587a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->isr_lock); 44597a7bc959SXin LI } 44607a7bc959SXin LI /* 44617a7bc959SXin LI ************************************************************************ 44627a7bc959SXin LI ************************************************************************ 44637a7bc959SXin LI */ 4464ad6d6297SScott Long static u_int32_t arcmsr_initialize(device_t dev) 4465f1c579b1SScott Long { 4466ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 4467ad6d6297SScott Long u_int16_t pci_command; 446844f05562SScott Long int i, j,max_coherent_size; 4469dac36688SXin LI u_int32_t vendor_dev_id; 4470f1c579b1SScott Long 4471dac36688SXin LI vendor_dev_id = pci_get_devid(dev); 4472dac36688SXin LI acb->vendor_device_id = vendor_dev_id; 4473224a78aeSXin LI acb->sub_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2); 4474dac36688SXin LI switch (vendor_dev_id) { 4475dac36688SXin LI case PCIDevVenIDARC1880: 4476dac36688SXin LI case PCIDevVenIDARC1882: 4477dac36688SXin LI case PCIDevVenIDARC1213: 4478dac36688SXin LI case PCIDevVenIDARC1223: { 4479d74001adSXin LI acb->adapter_type = ACB_ADAPTER_TYPE_C; 4480fc5ef1caSXin LI if ((acb->sub_device_id == ARECA_SUB_DEV_ID_1883) || 4481fc5ef1caSXin LI (acb->sub_device_id == ARECA_SUB_DEV_ID_1216) || 4482fc5ef1caSXin LI (acb->sub_device_id == ARECA_SUB_DEV_ID_1226)) 4483224a78aeSXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_12G; 4484224a78aeSXin LI else 4485dac36688SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_6G; 4486d74001adSXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE; 4487d74001adSXin LI } 4488d74001adSXin LI break; 4489a1103e04SXin LI case PCIDevVenIDARC1884: 4490a1103e04SXin LI acb->adapter_type = ACB_ADAPTER_TYPE_E; 4491a1103e04SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_12G; 4492a1103e04SXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + COMPLETION_Q_POOL_SIZE; 4493a1103e04SXin LI acb->completionQ_entry = COMPLETION_Q_POOL_SIZE / sizeof(struct deliver_completeQ); 4494a1103e04SXin LI break; 4495fa42a0bfSXin LI case PCIDevVenIDARC1886_: 4496fa42a0bfSXin LI case PCIDevVenIDARC1886: 4497fa42a0bfSXin LI acb->adapter_type = ACB_ADAPTER_TYPE_F; 4498fa42a0bfSXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_12G; 4499fa42a0bfSXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + COMPLETION_Q_POOL_SIZE + MESG_RW_BUFFER_SIZE; 4500fa42a0bfSXin LI acb->completionQ_entry = COMPLETION_Q_POOL_SIZE / sizeof(struct deliver_completeQ); 4501fa42a0bfSXin LI break; 45027a7bc959SXin LI case PCIDevVenIDARC1214: { 45037a7bc959SXin LI acb->adapter_type = ACB_ADAPTER_TYPE_D; 45047a7bc959SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_6G; 45057a7bc959SXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBD_MessageUnit0)); 45067a7bc959SXin LI } 45077a7bc959SXin LI break; 4508231c8b71SXin LI case PCIDevVenIDARC1200: 450944f05562SScott Long case PCIDevVenIDARC1201: { 451044f05562SScott Long acb->adapter_type = ACB_ADAPTER_TYPE_B; 4511dac36688SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_3G; 4512d74001adSXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBB_MessageUnit)); 451344f05562SScott Long } 451444f05562SScott Long break; 4515b23a1998SXin LI case PCIDevVenIDARC1203: { 4516b23a1998SXin LI acb->adapter_type = ACB_ADAPTER_TYPE_B; 4517b23a1998SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_6G; 4518b23a1998SXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBB_MessageUnit)); 4519b23a1998SXin LI } 4520b23a1998SXin LI break; 452144f05562SScott Long case PCIDevVenIDARC1110: 452244f05562SScott Long case PCIDevVenIDARC1120: 452344f05562SScott Long case PCIDevVenIDARC1130: 452444f05562SScott Long case PCIDevVenIDARC1160: 452544f05562SScott Long case PCIDevVenIDARC1170: 452644f05562SScott Long case PCIDevVenIDARC1210: 452744f05562SScott Long case PCIDevVenIDARC1220: 452844f05562SScott Long case PCIDevVenIDARC1230: 4529231c8b71SXin LI case PCIDevVenIDARC1231: 453044f05562SScott Long case PCIDevVenIDARC1260: 4531231c8b71SXin LI case PCIDevVenIDARC1261: 453244f05562SScott Long case PCIDevVenIDARC1270: 453344f05562SScott Long case PCIDevVenIDARC1280: 4534d74001adSXin LI case PCIDevVenIDARC1212: 4535d74001adSXin LI case PCIDevVenIDARC1222: 453644f05562SScott Long case PCIDevVenIDARC1380: 453744f05562SScott Long case PCIDevVenIDARC1381: 453844f05562SScott Long case PCIDevVenIDARC1680: 453944f05562SScott Long case PCIDevVenIDARC1681: { 454044f05562SScott Long acb->adapter_type = ACB_ADAPTER_TYPE_A; 4541dac36688SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_3G; 454244f05562SScott Long max_coherent_size = ARCMSR_SRBS_POOL_SIZE; 454344f05562SScott Long } 454444f05562SScott Long break; 454544f05562SScott Long default: { 454644f05562SScott Long printf("arcmsr%d:" 454744f05562SScott Long " unknown RAID adapter type \n", device_get_unit(dev)); 454844f05562SScott Long return ENOMEM; 454944f05562SScott Long } 455044f05562SScott Long } 4551b6f97155SScott Long if(bus_dma_tag_create( /*PCI parent*/ bus_get_dma_tag(dev), 4552f1c579b1SScott Long /*alignemnt*/ 1, 4553f1c579b1SScott Long /*boundary*/ 0, 4554701d9f1fSScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 4555f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 4556f1c579b1SScott Long /*filter*/ NULL, 4557f1c579b1SScott Long /*filterarg*/ NULL, 4558f1c579b1SScott Long /*maxsize*/ BUS_SPACE_MAXSIZE_32BIT, 4559f1c579b1SScott Long /*nsegments*/ BUS_SPACE_UNRESTRICTED, 4560f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 4561f1c579b1SScott Long /*flags*/ 0, 4562f1c579b1SScott Long /*lockfunc*/ NULL, 4563f1c579b1SScott Long /*lockarg*/ NULL, 4564231c8b71SXin LI &acb->parent_dmat) != 0) 4565f1c579b1SScott Long { 456644f05562SScott Long printf("arcmsr%d: parent_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 4567f1c579b1SScott Long return ENOMEM; 4568f1c579b1SScott Long } 4569231c8b71SXin LI 4570f1c579b1SScott Long /* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */ 4571ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 4572f1c579b1SScott Long /*alignment*/ 1, 4573f1c579b1SScott Long /*boundary*/ 0, 457422f2616bSXin LI #ifdef PAE 457522f2616bSXin LI /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 457622f2616bSXin LI #else 4577f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 457822f2616bSXin LI #endif 4579f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 4580f1c579b1SScott Long /*filter*/ NULL, 4581f1c579b1SScott Long /*filterarg*/ NULL, 4582231c8b71SXin LI /*maxsize*/ ARCMSR_MAX_SG_ENTRIES * PAGE_SIZE * ARCMSR_MAX_FREESRB_NUM, 4583f1c579b1SScott Long /*nsegments*/ ARCMSR_MAX_SG_ENTRIES, 4584f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 4585ad6d6297SScott Long /*flags*/ 0, 4586f1c579b1SScott Long /*lockfunc*/ busdma_lock_mutex, 45877a7bc959SXin LI /*lockarg*/ &acb->isr_lock, 4588231c8b71SXin LI &acb->dm_segs_dmat) != 0) 4589f1c579b1SScott Long { 4590ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 459144f05562SScott Long printf("arcmsr%d: dm_segs_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 4592f1c579b1SScott Long return ENOMEM; 4593f1c579b1SScott Long } 4594231c8b71SXin LI 4595ad6d6297SScott Long /* DMA tag for our srb structures.... Allocate the freesrb memory */ 4596ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 459744f05562SScott Long /*alignment*/ 0x20, 4598f1c579b1SScott Long /*boundary*/ 0, 4599f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 4600f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 4601f1c579b1SScott Long /*filter*/ NULL, 4602f1c579b1SScott Long /*filterarg*/ NULL, 460344f05562SScott Long /*maxsize*/ max_coherent_size, 4604f1c579b1SScott Long /*nsegments*/ 1, 4605f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 4606701d9f1fSScott Long /*flags*/ 0, 4607f1c579b1SScott Long /*lockfunc*/ NULL, 4608f1c579b1SScott Long /*lockarg*/ NULL, 4609231c8b71SXin LI &acb->srb_dmat) != 0) 4610f1c579b1SScott Long { 4611ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 4612ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 461344f05562SScott Long printf("arcmsr%d: srb_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 4614f1c579b1SScott Long return ENXIO; 4615f1c579b1SScott Long } 4616f1c579b1SScott Long /* Allocation for our srbs */ 4617d74001adSXin LI if(bus_dmamem_alloc(acb->srb_dmat, (void **)&acb->uncacheptr, BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &acb->srb_dmamap) != 0) { 4618ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 4619ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 4620ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 462144f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamem_alloc failure!\n", device_get_unit(dev)); 4622f1c579b1SScott Long return ENXIO; 4623f1c579b1SScott Long } 4624f1c579b1SScott Long /* And permanently map them */ 4625231c8b71SXin LI if(bus_dmamap_load(acb->srb_dmat, acb->srb_dmamap, acb->uncacheptr, max_coherent_size, arcmsr_map_free_srb, acb, /*flags*/0)) { 4626ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 4627ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 4628ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 462944f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamap_load failure!\n", device_get_unit(dev)); 4630f1c579b1SScott Long return ENXIO; 4631f1c579b1SScott Long } 4632f1c579b1SScott Long pci_command = pci_read_config(dev, PCIR_COMMAND, 2); 4633f1c579b1SScott Long pci_command |= PCIM_CMD_BUSMASTEREN; 4634f1c579b1SScott Long pci_command |= PCIM_CMD_PERRESPEN; 4635f1c579b1SScott Long pci_command |= PCIM_CMD_MWRICEN; 4636c68534f1SScott Long /* Enable Busmaster */ 4637f1c579b1SScott Long pci_write_config(dev, PCIR_COMMAND, pci_command, 2); 463844f05562SScott Long switch(acb->adapter_type) { 463944f05562SScott Long case ACB_ADAPTER_TYPE_A: { 464044f05562SScott Long u_int32_t rid0 = PCIR_BAR(0); 464144f05562SScott Long vm_offset_t mem_base0; 464244f05562SScott Long 4643eff83876SJustin Hibbits acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid0, RF_ACTIVE); 464444f05562SScott Long if(acb->sys_res_arcmsr[0] == NULL) { 4645ad6d6297SScott Long arcmsr_free_resource(acb); 4646d74001adSXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 4647f1c579b1SScott Long return ENOMEM; 4648f1c579b1SScott Long } 464944f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 4650ad6d6297SScott Long arcmsr_free_resource(acb); 4651d74001adSXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 4652f1c579b1SScott Long return ENXIO; 4653f1c579b1SScott Long } 465444f05562SScott Long mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 465544f05562SScott Long if(mem_base0 == 0) { 4656ad6d6297SScott Long arcmsr_free_resource(acb); 4657d74001adSXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 4658f1c579b1SScott Long return ENXIO; 4659f1c579b1SScott Long } 466044f05562SScott Long acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 466144f05562SScott Long acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 466244f05562SScott Long acb->pmu = (struct MessageUnit_UNION *)mem_base0; 4663fc5ef1caSXin LI acb->rid[0] = rid0; 466444f05562SScott Long } 466544f05562SScott Long break; 466644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 466744f05562SScott Long struct HBB_MessageUnit *phbbmu; 466844f05562SScott Long struct CommandControlBlock *freesrb; 466944f05562SScott Long u_int32_t rid[]={ PCIR_BAR(0), PCIR_BAR(2) }; 467044f05562SScott Long vm_offset_t mem_base[]={0,0}; 467144f05562SScott Long for(i=0; i < 2; i++) { 4672fc5ef1caSXin LI acb->sys_res_arcmsr[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid[i], RF_ACTIVE); 467344f05562SScott Long if(acb->sys_res_arcmsr[i] == NULL) { 467444f05562SScott Long arcmsr_free_resource(acb); 4675d74001adSXin LI printf("arcmsr%d: bus_alloc_resource %d failure!\n", device_get_unit(dev), i); 467644f05562SScott Long return ENOMEM; 467744f05562SScott Long } 467844f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[i]) <= 0) { 467944f05562SScott Long arcmsr_free_resource(acb); 4680d74001adSXin LI printf("arcmsr%d: rman_get_start %d failure!\n", device_get_unit(dev), i); 468144f05562SScott Long return ENXIO; 468244f05562SScott Long } 468344f05562SScott Long mem_base[i] = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[i]); 468444f05562SScott Long if(mem_base[i] == 0) { 468544f05562SScott Long arcmsr_free_resource(acb); 4686d74001adSXin LI printf("arcmsr%d: rman_get_virtual %d failure!\n", device_get_unit(dev), i); 468744f05562SScott Long return ENXIO; 468844f05562SScott Long } 468944f05562SScott Long acb->btag[i] = rman_get_bustag(acb->sys_res_arcmsr[i]); 469044f05562SScott Long acb->bhandle[i] = rman_get_bushandle(acb->sys_res_arcmsr[i]); 469144f05562SScott Long } 469244f05562SScott Long freesrb = (struct CommandControlBlock *)acb->uncacheptr; 469322f2616bSXin LI acb->pmu = (struct MessageUnit_UNION *)((unsigned long)freesrb+ARCMSR_SRBS_POOL_SIZE); 469444f05562SScott Long phbbmu = (struct HBB_MessageUnit *)acb->pmu; 469544f05562SScott Long phbbmu->hbb_doorbell = (struct HBB_DOORBELL *)mem_base[0]; 469644f05562SScott Long phbbmu->hbb_rwbuffer = (struct HBB_RWBUFFER *)mem_base[1]; 4697b23a1998SXin LI if (vendor_dev_id == PCIDevVenIDARC1203) { 4698b23a1998SXin LI phbbmu->drv2iop_doorbell = offsetof(struct HBB_DOORBELL_1203, drv2iop_doorbell); 4699b23a1998SXin LI phbbmu->drv2iop_doorbell_mask = offsetof(struct HBB_DOORBELL_1203, drv2iop_doorbell_mask); 4700b23a1998SXin LI phbbmu->iop2drv_doorbell = offsetof(struct HBB_DOORBELL_1203, iop2drv_doorbell); 4701b23a1998SXin LI phbbmu->iop2drv_doorbell_mask = offsetof(struct HBB_DOORBELL_1203, iop2drv_doorbell_mask); 4702b23a1998SXin LI } else { 4703b23a1998SXin LI phbbmu->drv2iop_doorbell = offsetof(struct HBB_DOORBELL, drv2iop_doorbell); 4704b23a1998SXin LI phbbmu->drv2iop_doorbell_mask = offsetof(struct HBB_DOORBELL, drv2iop_doorbell_mask); 4705b23a1998SXin LI phbbmu->iop2drv_doorbell = offsetof(struct HBB_DOORBELL, iop2drv_doorbell); 4706b23a1998SXin LI phbbmu->iop2drv_doorbell_mask = offsetof(struct HBB_DOORBELL, iop2drv_doorbell_mask); 4707b23a1998SXin LI } 4708fc5ef1caSXin LI acb->rid[0] = rid[0]; 4709fc5ef1caSXin LI acb->rid[1] = rid[1]; 471044f05562SScott Long } 471144f05562SScott Long break; 4712d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 4713d74001adSXin LI u_int32_t rid0 = PCIR_BAR(1); 4714d74001adSXin LI vm_offset_t mem_base0; 4715d74001adSXin LI 4716eff83876SJustin Hibbits acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid0, RF_ACTIVE); 4717d74001adSXin LI if(acb->sys_res_arcmsr[0] == NULL) { 4718d74001adSXin LI arcmsr_free_resource(acb); 4719d74001adSXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 4720d74001adSXin LI return ENOMEM; 4721d74001adSXin LI } 4722d74001adSXin LI if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 4723d74001adSXin LI arcmsr_free_resource(acb); 4724d74001adSXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 4725d74001adSXin LI return ENXIO; 4726d74001adSXin LI } 4727d74001adSXin LI mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 4728d74001adSXin LI if(mem_base0 == 0) { 4729d74001adSXin LI arcmsr_free_resource(acb); 4730d74001adSXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 4731d74001adSXin LI return ENXIO; 4732d74001adSXin LI } 4733d74001adSXin LI acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 4734d74001adSXin LI acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 4735d74001adSXin LI acb->pmu = (struct MessageUnit_UNION *)mem_base0; 4736fc5ef1caSXin LI acb->rid[0] = rid0; 4737d74001adSXin LI } 4738d74001adSXin LI break; 47397a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 47407a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu; 47417a7bc959SXin LI u_int32_t rid0 = PCIR_BAR(0); 47427a7bc959SXin LI vm_offset_t mem_base0; 47437a7bc959SXin LI 4744eff83876SJustin Hibbits acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid0, RF_ACTIVE); 47457a7bc959SXin LI if(acb->sys_res_arcmsr[0] == NULL) { 47467a7bc959SXin LI arcmsr_free_resource(acb); 47477a7bc959SXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 47487a7bc959SXin LI return ENOMEM; 47497a7bc959SXin LI } 47507a7bc959SXin LI if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 47517a7bc959SXin LI arcmsr_free_resource(acb); 47527a7bc959SXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 47537a7bc959SXin LI return ENXIO; 47547a7bc959SXin LI } 47557a7bc959SXin LI mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 47567a7bc959SXin LI if(mem_base0 == 0) { 47577a7bc959SXin LI arcmsr_free_resource(acb); 47587a7bc959SXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 47597a7bc959SXin LI return ENXIO; 47607a7bc959SXin LI } 47617a7bc959SXin LI acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 47627a7bc959SXin LI acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 47637a7bc959SXin LI acb->pmu = (struct MessageUnit_UNION *)((unsigned long)acb->uncacheptr+ARCMSR_SRBS_POOL_SIZE); 47647a7bc959SXin LI phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 47657a7bc959SXin LI phbdmu->phbdmu = (struct HBD_MessageUnit *)mem_base0; 4766fc5ef1caSXin LI acb->rid[0] = rid0; 4767a1103e04SXin LI } 4768a1103e04SXin LI break; 4769a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 4770a1103e04SXin LI u_int32_t rid0 = PCIR_BAR(1); 4771a1103e04SXin LI vm_offset_t mem_base0; 4772a1103e04SXin LI 4773fc5ef1caSXin LI acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid0, RF_ACTIVE); 4774a1103e04SXin LI if(acb->sys_res_arcmsr[0] == NULL) { 4775a1103e04SXin LI arcmsr_free_resource(acb); 4776a1103e04SXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 4777a1103e04SXin LI return ENOMEM; 4778a1103e04SXin LI } 4779a1103e04SXin LI if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 4780a1103e04SXin LI arcmsr_free_resource(acb); 4781a1103e04SXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 4782a1103e04SXin LI return ENXIO; 4783a1103e04SXin LI } 4784a1103e04SXin LI mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 4785a1103e04SXin LI if(mem_base0 == 0) { 4786a1103e04SXin LI arcmsr_free_resource(acb); 4787a1103e04SXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 4788a1103e04SXin LI return ENXIO; 4789a1103e04SXin LI } 4790a1103e04SXin LI acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 4791a1103e04SXin LI acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 4792a1103e04SXin LI acb->pmu = (struct MessageUnit_UNION *)mem_base0; 4793a1103e04SXin LI acb->doneq_index = 0; 4794a1103e04SXin LI acb->in_doorbell = 0; 4795a1103e04SXin LI acb->out_doorbell = 0; 4796fc5ef1caSXin LI acb->rid[0] = rid0; 4797a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /*clear interrupt*/ 4798a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, ARCMSR_HBEMU_DOORBELL_SYNC); /* synchronize doorbell to 0 */ 47997a7bc959SXin LI } 48007a7bc959SXin LI break; 4801fa42a0bfSXin LI case ACB_ADAPTER_TYPE_F: { 4802fa42a0bfSXin LI u_int32_t rid0 = PCIR_BAR(0); 4803fa42a0bfSXin LI vm_offset_t mem_base0; 4804fa42a0bfSXin LI unsigned long host_buffer_dma; 4805fa42a0bfSXin LI 4806fa42a0bfSXin LI acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid0, RF_ACTIVE); 4807fa42a0bfSXin LI if(acb->sys_res_arcmsr[0] == NULL) { 4808fa42a0bfSXin LI arcmsr_free_resource(acb); 4809fa42a0bfSXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 4810fa42a0bfSXin LI return ENOMEM; 4811fa42a0bfSXin LI } 4812fa42a0bfSXin LI if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 4813fa42a0bfSXin LI arcmsr_free_resource(acb); 4814fa42a0bfSXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 4815fa42a0bfSXin LI return ENXIO; 4816fa42a0bfSXin LI } 4817fa42a0bfSXin LI mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 4818fa42a0bfSXin LI if(mem_base0 == 0) { 4819fa42a0bfSXin LI arcmsr_free_resource(acb); 4820fa42a0bfSXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 4821fa42a0bfSXin LI return ENXIO; 4822fa42a0bfSXin LI } 4823fa42a0bfSXin LI acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 4824fa42a0bfSXin LI acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 4825fa42a0bfSXin LI acb->pmu = (struct MessageUnit_UNION *)mem_base0; 4826fa42a0bfSXin LI acb->doneq_index = 0; 4827fa42a0bfSXin LI acb->in_doorbell = 0; 4828fa42a0bfSXin LI acb->out_doorbell = 0; 4829fa42a0bfSXin LI acb->rid[0] = rid0; 4830fa42a0bfSXin LI arcmsr_wait_firmware_ready(acb); 4831fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, host_int_status, 0); /*clear interrupt*/ 4832fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, iobound_doorbell, ARCMSR_HBEMU_DOORBELL_SYNC); /* synchronize doorbell to 0 */ 4833fa42a0bfSXin LI host_buffer_dma = acb->completeQ_phys + COMPLETION_Q_POOL_SIZE; 4834fa42a0bfSXin 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 */ 4835fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_msgaddr1, (u_int32_t)((host_buffer_dma >> 16) >> 16));/* host buffer high addr */ 4836fa42a0bfSXin LI CHIP_REG_WRITE32(HBF_MessageUnit, 0, iobound_doorbell, ARCMSR_HBFMU_DOORBELL_SYNC1); /* set host buffer physical address */ 4837fa42a0bfSXin LI } 4838fa42a0bfSXin LI break; 483944f05562SScott Long } 4840ad6d6297SScott Long if(acb->acb_flags & ACB_F_MAPFREESRB_FAILD) { 4841ad6d6297SScott Long arcmsr_free_resource(acb); 484244f05562SScott Long printf("arcmsr%d: map free srb failure!\n", device_get_unit(dev)); 4843f1c579b1SScott Long return ENXIO; 4844f1c579b1SScott Long } 4845d74001adSXin LI acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_RQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ); 4846ad6d6297SScott Long acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; 4847ad6d6297SScott Long /* 4848ad6d6297SScott Long ******************************************************************** 4849ad6d6297SScott Long ** init raid volume state 4850ad6d6297SScott Long ******************************************************************** 4851ad6d6297SScott Long */ 4852ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_TARGETID; i++) { 4853ad6d6297SScott Long for(j=0; j < ARCMSR_MAX_TARGETLUN; j++) { 485444f05562SScott Long acb->devstate[i][j] = ARECA_RAID_GONE; 4855ad6d6297SScott Long } 4856ad6d6297SScott Long } 4857ad6d6297SScott Long arcmsr_iop_init(acb); 4858f1c579b1SScott Long return(0); 4859f1c579b1SScott Long } 4860a1103e04SXin LI 4861a1103e04SXin LI static int arcmsr_setup_msix(struct AdapterControlBlock *acb) 4862a1103e04SXin LI { 4863a1103e04SXin LI int i; 4864a1103e04SXin LI 4865a1103e04SXin LI for (i = 0; i < acb->msix_vectors; i++) { 4866fc5ef1caSXin LI acb->irq_id[i] = 1 + i; 4867a1103e04SXin LI acb->irqres[i] = bus_alloc_resource_any(acb->pci_dev, 4868a1103e04SXin LI SYS_RES_IRQ, &acb->irq_id[i], RF_ACTIVE); 4869a1103e04SXin LI if (acb->irqres[i] == NULL) { 4870a1103e04SXin LI printf("arcmsr: Can't allocate MSI-X resource\n"); 4871a1103e04SXin LI goto irq_alloc_failed; 4872a1103e04SXin LI } 4873a1103e04SXin LI if (bus_setup_intr(acb->pci_dev, acb->irqres[i], 4874a1103e04SXin LI INTR_MPSAFE | INTR_TYPE_CAM, NULL, arcmsr_intr_handler, 4875a1103e04SXin LI acb, &acb->ih[i])) { 4876a1103e04SXin LI printf("arcmsr: Cannot set up MSI-X interrupt handler\n"); 4877a1103e04SXin LI goto irq_alloc_failed; 4878a1103e04SXin LI } 4879a1103e04SXin LI } 4880a1103e04SXin LI printf("arcmsr: MSI-X INT enabled\n"); 4881a1103e04SXin LI acb->acb_flags |= ACB_F_MSIX_ENABLED; 4882a1103e04SXin LI return TRUE; 4883a1103e04SXin LI 4884a1103e04SXin LI irq_alloc_failed: 4885a1103e04SXin LI arcmsr_teardown_intr(acb->pci_dev, acb); 4886a1103e04SXin LI return FALSE; 4887a1103e04SXin LI } 4888a1103e04SXin LI 4889f1c579b1SScott Long /* 4890f1c579b1SScott Long ************************************************************************ 4891f1c579b1SScott Long ************************************************************************ 4892f1c579b1SScott Long */ 4893f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev) 4894f1c579b1SScott Long { 4895ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 4896ad6d6297SScott Long u_int32_t unit=device_get_unit(dev); 4897f1c579b1SScott Long struct ccb_setasync csa; 4898f1c579b1SScott Long struct cam_devq *devq; /* Device Queue to use for this SIM */ 4899f1c579b1SScott Long struct resource *irqres; 4900f1c579b1SScott Long 4901ad6d6297SScott Long if(acb == NULL) { 4902ad6d6297SScott Long printf("arcmsr%d: cannot allocate softc\n", unit); 4903ad6d6297SScott Long return (ENOMEM); 4904ad6d6297SScott Long } 49057a7bc959SXin LI arcmsr_mutex_init(acb); 49061e7d660aSXin LI acb->pci_dev = dev; 49071e7d660aSXin LI acb->pci_unit = unit; 4908ad6d6297SScott Long if(arcmsr_initialize(dev)) { 4909ad6d6297SScott Long printf("arcmsr%d: initialize failure!\n", unit); 4910a1103e04SXin LI goto initialize_failed; 4911f1c579b1SScott Long } 4912f1c579b1SScott Long /* After setting up the adapter, map our interrupt */ 4913a1103e04SXin LI acb->msix_vectors = ARCMSR_NUM_MSIX_VECTORS; 4914a1103e04SXin LI if (pci_alloc_msix(dev, &acb->msix_vectors) == 0) { 4915a1103e04SXin LI if (arcmsr_setup_msix(acb) == TRUE) 4916a1103e04SXin LI goto irqx; 4917a1103e04SXin LI } 4918fc5ef1caSXin LI acb->irq_id[0] = 0; 4919a1103e04SXin LI irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &acb->irq_id[0], RF_SHAREABLE | RF_ACTIVE); 4920ad6d6297SScott Long if(irqres == NULL || 4921a1103e04SXin LI bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, NULL, arcmsr_intr_handler, acb, &acb->ih[0])) { 4922f1c579b1SScott Long printf("arcmsr%d: unable to register interrupt handler!\n", unit); 4923a1103e04SXin LI goto setup_intr_failed; 4924f1c579b1SScott Long } 4925a1103e04SXin LI acb->irqres[0] = irqres; 4926a1103e04SXin LI irqx: 4927f1c579b1SScott Long /* 4928f1c579b1SScott Long * Now let the CAM generic SCSI layer find the SCSI devices on 4929f1c579b1SScott Long * the bus * start queue to reset to the idle loop. * 4930f1c579b1SScott Long * Create device queue of SIM(s) * (MAX_START_JOB - 1) : 4931f1c579b1SScott Long * max_sim_transactions 4932f1c579b1SScott Long */ 4933224a78aeSXin LI devq = cam_simq_alloc(acb->maxOutstanding); 4934ad6d6297SScott Long if(devq == NULL) { 4935ad6d6297SScott Long printf("arcmsr%d: cam_simq_alloc failure!\n", unit); 4936a1103e04SXin LI goto simq_alloc_failed; 4937f1c579b1SScott Long } 49387a7bc959SXin LI acb->psim = cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, &acb->isr_lock, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq); 4939ad6d6297SScott Long if(acb->psim == NULL) { 4940ad6d6297SScott Long printf("arcmsr%d: cam_sim_alloc failure!\n", unit); 4941a1103e04SXin LI goto sim_alloc_failed; 4942f1c579b1SScott Long } 49437a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 4944b50569b7SScott Long if(xpt_bus_register(acb->psim, dev, 0) != CAM_SUCCESS) { 4945ad6d6297SScott Long printf("arcmsr%d: xpt_bus_register failure!\n", unit); 4946a1103e04SXin LI goto xpt_bus_failed; 4947f1c579b1SScott Long } 4948d74001adSXin LI if(xpt_create_path(&acb->ppath, /* periph */ NULL, cam_sim_path(acb->psim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 4949ad6d6297SScott Long printf("arcmsr%d: xpt_create_path failure!\n", unit); 4950a1103e04SXin LI goto xpt_path_failed; 4951f1c579b1SScott Long } 4952f1c579b1SScott Long /* 4953f1c579b1SScott Long **************************************************** 4954f1c579b1SScott Long */ 495545f57ce1SEdward Tomasz Napierala memset(&csa, 0, sizeof(csa)); 4956ad6d6297SScott Long xpt_setup_ccb(&csa.ccb_h, acb->ppath, /*priority*/5); 4957f1c579b1SScott Long csa.ccb_h.func_code = XPT_SASYNC_CB; 4958f1c579b1SScott Long csa.event_enable = AC_FOUND_DEVICE|AC_LOST_DEVICE; 4959f1c579b1SScott Long csa.callback = arcmsr_async; 4960ad6d6297SScott Long csa.callback_arg = acb->psim; 4961f1c579b1SScott Long xpt_action((union ccb *)&csa); 49627a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 4963f1c579b1SScott Long /* Create the control device. */ 4964d74001adSXin LI acb->ioctl_dev = make_dev(&arcmsr_cdevsw, unit, UID_ROOT, GID_WHEEL /* GID_OPERATOR */, S_IRUSR | S_IWUSR, "arcmsr%d", unit); 4965d74001adSXin LI 4966ad6d6297SScott Long (void)make_dev_alias(acb->ioctl_dev, "arc%d", unit); 496722f2616bSXin LI arcmsr_callout_init(&acb->devmap_callout); 4968d74001adSXin LI callout_reset(&acb->devmap_callout, 60 * hz, arcmsr_polling_devmap, acb); 4969dac36688SXin LI return (0); 4970a1103e04SXin LI xpt_path_failed: 4971a1103e04SXin LI xpt_bus_deregister(cam_sim_path(acb->psim)); 4972a1103e04SXin LI xpt_bus_failed: 4973a1103e04SXin LI cam_sim_free(acb->psim, /* free_simq */ TRUE); 4974a1103e04SXin LI sim_alloc_failed: 4975a1103e04SXin LI cam_simq_free(devq); 4976a1103e04SXin LI simq_alloc_failed: 4977a1103e04SXin LI arcmsr_teardown_intr(dev, acb); 4978a1103e04SXin LI setup_intr_failed: 4979a1103e04SXin LI arcmsr_free_resource(acb); 4980a1103e04SXin LI initialize_failed: 4981a1103e04SXin LI arcmsr_mutex_destroy(acb); 4982a1103e04SXin LI return ENXIO; 4983f1c579b1SScott Long } 498422f2616bSXin LI 4985f1c579b1SScott Long /* 4986f1c579b1SScott Long ************************************************************************ 4987f1c579b1SScott Long ************************************************************************ 4988f1c579b1SScott Long */ 4989f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev) 4990f1c579b1SScott Long { 4991ad6d6297SScott Long u_int32_t id; 4992224a78aeSXin LI u_int16_t sub_device_id; 4993ad6d6297SScott Long static char buf[256]; 49941e7d660aSXin LI char x_type[]={"unknown"}; 4995ad6d6297SScott Long char *type; 4996ad6d6297SScott Long int raid6 = 1; 4997ad6d6297SScott Long 4998ad6d6297SScott Long if (pci_get_vendor(dev) != PCI_VENDOR_ID_ARECA) { 4999ad6d6297SScott Long return (ENXIO); 5000ad6d6297SScott Long } 5001224a78aeSXin LI sub_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2); 5002ad6d6297SScott Long switch(id = pci_get_devid(dev)) { 5003f1c579b1SScott Long case PCIDevVenIDARC1110: 5004231c8b71SXin LI case PCIDevVenIDARC1200: 500544f05562SScott Long case PCIDevVenIDARC1201: 5006231c8b71SXin LI case PCIDevVenIDARC1210: 5007ad6d6297SScott Long raid6 = 0; 5008ad6d6297SScott Long /*FALLTHRU*/ 5009ad6d6297SScott Long case PCIDevVenIDARC1120: 5010ad6d6297SScott Long case PCIDevVenIDARC1130: 5011ad6d6297SScott Long case PCIDevVenIDARC1160: 5012ad6d6297SScott Long case PCIDevVenIDARC1170: 5013f1c579b1SScott Long case PCIDevVenIDARC1220: 5014f1c579b1SScott Long case PCIDevVenIDARC1230: 5015231c8b71SXin LI case PCIDevVenIDARC1231: 5016f1c579b1SScott Long case PCIDevVenIDARC1260: 5017231c8b71SXin LI case PCIDevVenIDARC1261: 5018ad6d6297SScott Long case PCIDevVenIDARC1270: 5019ad6d6297SScott Long case PCIDevVenIDARC1280: 50207a7bc959SXin LI type = "SATA 3G"; 5021ad6d6297SScott Long break; 5022d74001adSXin LI case PCIDevVenIDARC1212: 5023d74001adSXin LI case PCIDevVenIDARC1222: 5024ad6d6297SScott Long case PCIDevVenIDARC1380: 5025ad6d6297SScott Long case PCIDevVenIDARC1381: 5026ad6d6297SScott Long case PCIDevVenIDARC1680: 5027ad6d6297SScott Long case PCIDevVenIDARC1681: 5028d74001adSXin LI type = "SAS 3G"; 5029d74001adSXin LI break; 5030d74001adSXin LI case PCIDevVenIDARC1880: 5031dac36688SXin LI case PCIDevVenIDARC1882: 5032dac36688SXin LI case PCIDevVenIDARC1213: 5033dac36688SXin LI case PCIDevVenIDARC1223: 5034fc5ef1caSXin LI if ((sub_device_id == ARECA_SUB_DEV_ID_1883) || 5035fc5ef1caSXin LI (sub_device_id == ARECA_SUB_DEV_ID_1216) || 5036fc5ef1caSXin LI (sub_device_id == ARECA_SUB_DEV_ID_1226)) 5037224a78aeSXin LI type = "SAS 12G"; 5038224a78aeSXin LI else 5039d74001adSXin LI type = "SAS 6G"; 5040ad6d6297SScott Long break; 5041a1103e04SXin LI case PCIDevVenIDARC1884: 5042a1103e04SXin LI type = "SAS 12G"; 5043a1103e04SXin LI break; 5044fa42a0bfSXin LI case PCIDevVenIDARC1886_: 5045fa42a0bfSXin LI case PCIDevVenIDARC1886: 5046fa42a0bfSXin LI type = "NVME,SAS-12G,SATA-6G"; 5047fa42a0bfSXin LI break; 50487a7bc959SXin LI case PCIDevVenIDARC1214: 5049b23a1998SXin LI case PCIDevVenIDARC1203: 50507a7bc959SXin LI type = "SATA 6G"; 50517a7bc959SXin LI break; 5052ad6d6297SScott Long default: 5053231c8b71SXin LI type = x_type; 50541e7d660aSXin LI raid6 = 0; 5055ad6d6297SScott Long break; 5056f1c579b1SScott Long } 5057231c8b71SXin LI if(type == x_type) 5058231c8b71SXin LI return(ENXIO); 50591e7d660aSXin LI sprintf(buf, "Areca %s Host Adapter RAID Controller %s\n%s\n", 50601e7d660aSXin LI type, raid6 ? "(RAID6 capable)" : "", ARCMSR_DRIVER_VERSION); 5061ad6d6297SScott Long device_set_desc_copy(dev, buf); 506203389298SXin LI return (BUS_PROBE_DEFAULT); 5063f1c579b1SScott Long } 5064f1c579b1SScott Long /* 5065f1c579b1SScott Long ************************************************************************ 5066f1c579b1SScott Long ************************************************************************ 5067f1c579b1SScott Long */ 5068f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev) 5069f1c579b1SScott Long { 507044f05562SScott Long u_int32_t i; 5071ad6d6297SScott Long struct CommandControlBlock *srb; 5072ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 5073f1c579b1SScott Long 5074f1c579b1SScott Long /* stop adapter background rebuild */ 50757a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 507644f05562SScott Long /* disable all outbound interrupt */ 5077*bca8e8c0SScott Long arcmsr_disable_allintr(acb); 5078ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 5079ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 5080f1c579b1SScott Long /* abort all outstanding command */ 5081ad6d6297SScott Long acb->acb_flags |= ACB_F_SCSISTOPADAPTER; 5082ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOP_INITED; 5083ad6d6297SScott Long if(acb->srboutstandingcount != 0) { 508444f05562SScott Long /*clear and abort all outbound posted Q*/ 508544f05562SScott Long arcmsr_done4abort_postqueue(acb); 508644f05562SScott Long /* talk to iop 331 outstanding command aborted*/ 5087ad6d6297SScott Long arcmsr_abort_allcmd(acb); 5088ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 5089ad6d6297SScott Long srb = acb->psrb_pool[i]; 509022f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) { 509122f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 5092ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 5093ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 5094f1c579b1SScott Long } 5095f1c579b1SScott Long } 5096f1c579b1SScott Long } 509722f2616bSXin LI acb->srboutstandingcount = 0; 5098ad6d6297SScott Long acb->workingsrb_doneindex = 0; 5099ad6d6297SScott Long acb->workingsrb_startindex = 0; 510022f2616bSXin LI acb->pktRequestCount = 0; 510122f2616bSXin LI acb->pktReturnCount = 0; 51027a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 5103f2aa0e9fSWarner Losh return (0); 5104f1c579b1SScott Long } 5105f1c579b1SScott Long /* 5106f1c579b1SScott Long ************************************************************************ 5107f1c579b1SScott Long ************************************************************************ 5108f1c579b1SScott Long */ 5109fc5ef1caSXin LI static void arcmsr_teardown_intr(device_t dev, struct AdapterControlBlock *acb) 5110a1103e04SXin LI { 5111a1103e04SXin LI int i; 5112a1103e04SXin LI 5113a1103e04SXin LI if (acb->acb_flags & ACB_F_MSIX_ENABLED) { 5114a1103e04SXin LI for (i = 0; i < acb->msix_vectors; i++) { 5115a1103e04SXin LI if (acb->ih[i]) 5116a1103e04SXin LI bus_teardown_intr(dev, acb->irqres[i], acb->ih[i]); 5117a1103e04SXin LI if (acb->irqres[i] != NULL) 5118a1103e04SXin LI bus_release_resource(dev, SYS_RES_IRQ, 5119a1103e04SXin LI acb->irq_id[i], acb->irqres[i]); 5120a1103e04SXin LI 5121a1103e04SXin LI acb->ih[i] = NULL; 5122a1103e04SXin LI } 5123a1103e04SXin LI pci_release_msi(dev); 5124a1103e04SXin LI } else { 5125a1103e04SXin LI if (acb->ih[0]) 5126a1103e04SXin LI bus_teardown_intr(dev, acb->irqres[0], acb->ih[0]); 5127a1103e04SXin LI if (acb->irqres[0] != NULL) 5128a1103e04SXin LI bus_release_resource(dev, SYS_RES_IRQ, 5129a1103e04SXin LI acb->irq_id[0], acb->irqres[0]); 5130a1103e04SXin LI acb->ih[0] = NULL; 5131a1103e04SXin LI } 5132a1103e04SXin LI 5133a1103e04SXin LI } 5134a1103e04SXin LI /* 5135a1103e04SXin LI ************************************************************************ 5136a1103e04SXin LI ************************************************************************ 5137a1103e04SXin LI */ 5138f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev) 5139f1c579b1SScott Long { 5140ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 514144f05562SScott Long int i; 5142f1c579b1SScott Long 5143d74001adSXin LI callout_stop(&acb->devmap_callout); 5144a1103e04SXin LI arcmsr_teardown_intr(dev, acb); 5145f1c579b1SScott Long arcmsr_shutdown(dev); 5146ad6d6297SScott Long arcmsr_free_resource(acb); 514744f05562SScott Long for(i=0; (acb->sys_res_arcmsr[i]!=NULL) && (i<2); i++) { 5148fc5ef1caSXin LI bus_release_resource(dev, SYS_RES_MEMORY, acb->rid[i], acb->sys_res_arcmsr[i]); 514944f05562SScott Long } 51507a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 5151ad6d6297SScott Long xpt_async(AC_LOST_DEVICE, acb->ppath, NULL); 5152ad6d6297SScott Long xpt_free_path(acb->ppath); 5153ad6d6297SScott Long xpt_bus_deregister(cam_sim_path(acb->psim)); 5154ad6d6297SScott Long cam_sim_free(acb->psim, TRUE); 51557a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 51567a7bc959SXin LI arcmsr_mutex_destroy(acb); 5157f1c579b1SScott Long return (0); 5158f1c579b1SScott Long } 5159f1c579b1SScott Long 516022f2616bSXin LI #ifdef ARCMSR_DEBUG1 516122f2616bSXin LI static void arcmsr_dump_data(struct AdapterControlBlock *acb) 516222f2616bSXin LI { 516322f2616bSXin LI if((acb->pktRequestCount - acb->pktReturnCount) == 0) 516422f2616bSXin LI return; 516522f2616bSXin LI printf("Command Request Count =0x%x\n",acb->pktRequestCount); 516622f2616bSXin LI printf("Command Return Count =0x%x\n",acb->pktReturnCount); 516722f2616bSXin LI printf("Command (Req-Rtn) Count =0x%x\n",(acb->pktRequestCount - acb->pktReturnCount)); 516822f2616bSXin LI printf("Queued Command Count =0x%x\n",acb->srboutstandingcount); 516922f2616bSXin LI } 517022f2616bSXin LI #endif 5171