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 ** 1235689395SXin LI ** Copyright (C) 2002 - 2012, Areca Technology Corporation All rights reserved. 13f1c579b1SScott Long ** 14f1c579b1SScott Long ** Redistribution and use in source and binary forms, with or without 15f1c579b1SScott Long ** modification, are permitted provided that the following conditions 16f1c579b1SScott Long ** are met: 17f1c579b1SScott Long ** 1. Redistributions of source code must retain the above copyright 18f1c579b1SScott Long ** notice, this list of conditions and the following disclaimer. 19f1c579b1SScott Long ** 2. Redistributions in binary form must reproduce the above copyright 20f1c579b1SScott Long ** notice, this list of conditions and the following disclaimer in the 21f1c579b1SScott Long ** documentation and/or other materials provided with the distribution. 22f1c579b1SScott Long ** 3. The name of the author may not be used to endorse or promote products 23f1c579b1SScott Long ** derived from this software without specific prior written permission. 24f1c579b1SScott Long ** 25f1c579b1SScott Long ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 26f1c579b1SScott Long ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 27f1c579b1SScott Long ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28f1c579b1SScott Long ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 29f1c579b1SScott Long ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT 30f1c579b1SScott Long ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31f1c579b1SScott Long ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY 32f1c579b1SScott Long ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33f1c579b1SScott Long **(INCLUDING NEGLIGENCE OR OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF 34f1c579b1SScott Long ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3535689395SXin LI ******************************************************************************** 36f1c579b1SScott Long ** History 37f1c579b1SScott Long ** 38f1c579b1SScott Long ** REV# DATE NAME DESCRIPTION 3922f2616bSXin LI ** 1.00.00.00 03/31/2004 Erich Chen First release 40f1c579b1SScott Long ** 1.20.00.02 11/29/2004 Erich Chen bug fix with arcmsr_bus_reset when PHY error 4122f2616bSXin LI ** 1.20.00.03 04/19/2005 Erich Chen add SATA 24 Ports adapter type support 42ad6d6297SScott Long ** clean unused function 4322f2616bSXin LI ** 1.20.00.12 09/12/2005 Erich Chen bug fix with abort command handling, 44ad6d6297SScott Long ** firmware version check 45ad6d6297SScott Long ** and firmware update notify for hardware bug fix 46ad6d6297SScott Long ** handling if none zero high part physical address 47ad6d6297SScott Long ** of srb resource 4822f2616bSXin LI ** 1.20.00.13 08/18/2006 Erich Chen remove pending srb and report busy 49ad6d6297SScott Long ** add iop message xfer 50ad6d6297SScott Long ** with scsi pass-through command 51ad6d6297SScott Long ** add new device id of sas raid adapters 52ad6d6297SScott Long ** code fit for SPARC64 & PPC 53f48f00a1SScott Long ** 1.20.00.14 02/05/2007 Erich Chen bug fix for incorrect ccb_h.status report 54f48f00a1SScott Long ** and cause g_vfs_done() read write error 5544f05562SScott Long ** 1.20.00.15 10/10/2007 Erich Chen support new RAID adapter type ARC120x 56641182baSXin LI ** 1.20.00.16 10/10/2009 Erich Chen Bug fix for RAID adapter type ARC120x 57641182baSXin LI ** bus_dmamem_alloc() with BUS_DMA_ZERO 58d74001adSXin LI ** 1.20.00.17 07/15/2010 Ching Huang Added support ARC1880 59d74001adSXin LI ** report CAM_DEV_NOT_THERE instead of CAM_SEL_TIMEOUT when device failed, 60d74001adSXin LI ** prevent cam_periph_error removing all LUN devices of one Target id 61d74001adSXin LI ** for any one LUN device failed 62231c8b71SXin LI ** 1.20.00.18 10/14/2010 Ching Huang Fixed "inquiry data fails comparion at DV1 step" 63231c8b71SXin LI ** 10/25/2010 Ching Huang Fixed bad range input in bus_alloc_resource for ADAPTER_TYPE_B 64231c8b71SXin LI ** 1.20.00.19 11/11/2010 Ching Huang Fixed arcmsr driver prevent arcsas support for Areca SAS HBA ARC13x0 6522f2616bSXin LI ** 1.20.00.20 12/08/2010 Ching Huang Avoid calling atomic_set_int function 6622f2616bSXin LI ** 1.20.00.21 02/08/2011 Ching Huang Implement I/O request timeout 6722f2616bSXin LI ** 02/14/2011 Ching Huang Modified pktRequestCount 6822f2616bSXin LI ** 1.20.00.21 03/03/2011 Ching Huang if a command timeout, then wait its ccb back before free it 694e32649fSXin LI ** 1.20.00.22 07/04/2011 Ching Huang Fixed multiple MTX panic 70dac36688SXin LI ** 1.20.00.23 10/28/2011 Ching Huang Added TIMEOUT_DELAY in case of too many HDDs need to start 71dac36688SXin LI ** 1.20.00.23 11/08/2011 Ching Huang Added report device transfer speed 72dac36688SXin LI ** 1.20.00.23 01/30/2012 Ching Huang Fixed Request requeued and Retrying command 73dac36688SXin LI ** 1.20.00.24 06/11/2012 Ching Huang Fixed return sense data condition 74dac36688SXin LI ** 1.20.00.25 08/17/2012 Ching Huang Fixed hotplug device no function on type A adapter 75abfdbca9SXin LI ** 1.20.00.26 12/14/2012 Ching Huang Added support ARC1214,1224,1264,1284 76abfdbca9SXin LI ** 1.20.00.27 05/06/2013 Ching Huang Fixed out standing cmd full on ARC-12x4 771e7d660aSXin LI ** 1.20.00.28 09/13/2013 Ching Huang Removed recursive mutex in arcmsr_abort_dr_ccbs 78224a78aeSXin LI ** 1.20.00.29 12/18/2013 Ching Huang Change simq allocation number, support ARC1883 79b23a1998SXin LI ** 1.30.00.00 11/30/2015 Ching Huang Added support ARC1203 80a1103e04SXin LI ** 1.40.00.00 07/11/2017 Ching Huang Added support ARC1884 81*fc5ef1caSXin LI ** 1.40.00.01 10/30/2017 Ching Huang Fixed release memory resource 82f1c579b1SScott Long ****************************************************************************************** 83f1c579b1SScott Long */ 844b7ec270SMarius Strobl 854b7ec270SMarius Strobl #include <sys/cdefs.h> 864b7ec270SMarius Strobl __FBSDID("$FreeBSD$"); 874b7ec270SMarius Strobl 8822f2616bSXin LI #if 0 8922f2616bSXin LI #define ARCMSR_DEBUG1 1 9022f2616bSXin LI #endif 91f1c579b1SScott Long #include <sys/param.h> 92f1c579b1SScott Long #include <sys/systm.h> 93f1c579b1SScott Long #include <sys/malloc.h> 94f1c579b1SScott Long #include <sys/kernel.h> 95f1c579b1SScott Long #include <sys/bus.h> 96f1c579b1SScott Long #include <sys/queue.h> 97f1c579b1SScott Long #include <sys/stat.h> 98f1c579b1SScott Long #include <sys/devicestat.h> 99f1c579b1SScott Long #include <sys/kthread.h> 100f1c579b1SScott Long #include <sys/module.h> 101f1c579b1SScott Long #include <sys/proc.h> 102f1c579b1SScott Long #include <sys/lock.h> 103f1c579b1SScott Long #include <sys/sysctl.h> 104f1c579b1SScott Long #include <sys/poll.h> 105f1c579b1SScott Long #include <sys/ioccom.h> 106f1c579b1SScott Long #include <vm/vm.h> 107f1c579b1SScott Long #include <vm/vm_param.h> 108f1c579b1SScott Long #include <vm/pmap.h> 109f1c579b1SScott Long 110f1c579b1SScott Long #include <isa/rtc.h> 111f1c579b1SScott Long 112f1c579b1SScott Long #include <machine/bus.h> 113f1c579b1SScott Long #include <machine/resource.h> 114f1c579b1SScott Long #include <machine/atomic.h> 115f1c579b1SScott Long #include <sys/conf.h> 116f1c579b1SScott Long #include <sys/rman.h> 117f1c579b1SScott Long 118f1c579b1SScott Long #include <cam/cam.h> 119f1c579b1SScott Long #include <cam/cam_ccb.h> 120f1c579b1SScott Long #include <cam/cam_sim.h> 121d74001adSXin LI #include <cam/cam_periph.h> 122d74001adSXin LI #include <cam/cam_xpt_periph.h> 123f1c579b1SScott Long #include <cam/cam_xpt_sim.h> 124f1c579b1SScott Long #include <cam/cam_debug.h> 125f1c579b1SScott Long #include <cam/scsi/scsi_all.h> 126f1c579b1SScott Long #include <cam/scsi/scsi_message.h> 127f1c579b1SScott Long /* 128f1c579b1SScott Long ************************************************************************** 129f1c579b1SScott Long ************************************************************************** 130f1c579b1SScott Long */ 131f1c579b1SScott Long #if __FreeBSD_version >= 500005 132f1c579b1SScott Long #include <sys/selinfo.h> 133f1c579b1SScott Long #include <sys/mutex.h> 134ad6d6297SScott Long #include <sys/endian.h> 135f1c579b1SScott Long #include <dev/pci/pcivar.h> 136f1c579b1SScott Long #include <dev/pci/pcireg.h> 137f1c579b1SScott Long #else 138f1c579b1SScott Long #include <sys/select.h> 139f1c579b1SScott Long #include <pci/pcivar.h> 140f1c579b1SScott Long #include <pci/pcireg.h> 141f1c579b1SScott Long #endif 14244f05562SScott Long 14344f05562SScott Long #if !defined(CAM_NEW_TRAN_CODE) && __FreeBSD_version >= 700025 14444f05562SScott Long #define CAM_NEW_TRAN_CODE 1 14544f05562SScott Long #endif 14644f05562SScott Long 14722f2616bSXin LI #if __FreeBSD_version > 500000 14822f2616bSXin LI #define arcmsr_callout_init(a) callout_init(a, /*mpsafe*/1); 14922f2616bSXin LI #else 15022f2616bSXin LI #define arcmsr_callout_init(a) callout_init(a); 15122f2616bSXin LI #endif 15222f2616bSXin LI 153*fc5ef1caSXin LI #define ARCMSR_DRIVER_VERSION "arcmsr version 1.40.00.01 2017-10-30" 154f1c579b1SScott Long #include <dev/arcmsr/arcmsr.h> 155f1c579b1SScott Long /* 156f1c579b1SScott Long ************************************************************************** 157f1c579b1SScott Long ************************************************************************** 158f1c579b1SScott Long */ 15922f2616bSXin LI static void arcmsr_free_srb(struct CommandControlBlock *srb); 160ad6d6297SScott Long static struct CommandControlBlock *arcmsr_get_freesrb(struct AdapterControlBlock *acb); 161ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb *abortccb); 162f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev); 163f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev); 164f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev); 165ad6d6297SScott Long static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg); 166ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb); 167f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev); 16844f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb); 169ad6d6297SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb); 170ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb); 171ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb); 172ad6d6297SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); 173ad6d6297SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb); 174ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb); 175ad6d6297SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb); 17635689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, struct QBUFFER *prbuffer); 1777a7bc959SXin LI static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb); 178ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb); 179ad6d6297SScott Long static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag); 180ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb); 181ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb); 182ad6d6297SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t *dm_segs, u_int32_t nseg); 183ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *pccb); 184ad6d6297SScott Long static int arcmsr_resume(device_t dev); 185ad6d6297SScott Long static int arcmsr_suspend(device_t dev); 186d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb); 187d74001adSXin LI static void arcmsr_polling_devmap(void *arg); 18822f2616bSXin LI static void arcmsr_srb_timeout(void *arg); 1897a7bc959SXin LI static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb); 190a1103e04SXin LI static void arcmsr_hbe_postqueue_isr(struct AdapterControlBlock *acb); 191*fc5ef1caSXin LI static void arcmsr_teardown_intr(device_t dev, struct AdapterControlBlock *acb); 19222f2616bSXin LI #ifdef ARCMSR_DEBUG1 19322f2616bSXin LI static void arcmsr_dump_data(struct AdapterControlBlock *acb); 19422f2616bSXin LI #endif 195f1c579b1SScott Long /* 196f1c579b1SScott Long ************************************************************************** 197ad6d6297SScott Long ************************************************************************** 198ad6d6297SScott Long */ 199ad6d6297SScott Long static void UDELAY(u_int32_t us) { DELAY(us); } 200ad6d6297SScott Long /* 201ad6d6297SScott Long ************************************************************************** 202f1c579b1SScott Long ************************************************************************** 203f1c579b1SScott Long */ 204231c8b71SXin LI static bus_dmamap_callback_t arcmsr_map_free_srb; 205231c8b71SXin LI static bus_dmamap_callback_t arcmsr_execute_srb; 206f1c579b1SScott Long /* 207f1c579b1SScott Long ************************************************************************** 208f1c579b1SScott Long ************************************************************************** 209f1c579b1SScott Long */ 210f1c579b1SScott Long static d_open_t arcmsr_open; 211f1c579b1SScott Long static d_close_t arcmsr_close; 212f1c579b1SScott Long static d_ioctl_t arcmsr_ioctl; 213f1c579b1SScott Long 214f1c579b1SScott Long static device_method_t arcmsr_methods[]={ 215f1c579b1SScott Long DEVMETHOD(device_probe, arcmsr_probe), 216f1c579b1SScott Long DEVMETHOD(device_attach, arcmsr_attach), 217f1c579b1SScott Long DEVMETHOD(device_detach, arcmsr_detach), 218f1c579b1SScott Long DEVMETHOD(device_shutdown, arcmsr_shutdown), 219ad6d6297SScott Long DEVMETHOD(device_suspend, arcmsr_suspend), 220ad6d6297SScott Long DEVMETHOD(device_resume, arcmsr_resume), 2214b7ec270SMarius Strobl 22235689395SXin LI #if __FreeBSD_version >= 803000 2234b7ec270SMarius Strobl DEVMETHOD_END 22435689395SXin LI #else 22535689395SXin LI { 0, 0 } 22635689395SXin LI #endif 227f1c579b1SScott Long }; 228f1c579b1SScott Long 229f1c579b1SScott Long static driver_t arcmsr_driver={ 230ad6d6297SScott Long "arcmsr", arcmsr_methods, sizeof(struct AdapterControlBlock) 231f1c579b1SScott Long }; 232f1c579b1SScott Long 233f1c579b1SScott Long static devclass_t arcmsr_devclass; 234f1c579b1SScott Long DRIVER_MODULE(arcmsr, pci, arcmsr_driver, arcmsr_devclass, 0, 0); 235d3cf342dSScott Long MODULE_DEPEND(arcmsr, pci, 1, 1, 1); 236d3cf342dSScott Long MODULE_DEPEND(arcmsr, cam, 1, 1, 1); 237ad6d6297SScott Long #ifndef BUS_DMA_COHERENT 238ad6d6297SScott Long #define BUS_DMA_COHERENT 0x04 /* hint: map memory in a coherent way */ 239ad6d6297SScott Long #endif 240ad6d6297SScott Long #if __FreeBSD_version >= 501000 241f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw={ 24222f2616bSXin LI #if __FreeBSD_version >= 503000 243f1c579b1SScott Long .d_version = D_VERSION, 244ad6d6297SScott Long #endif 24522f2616bSXin LI #if (__FreeBSD_version>=503000 && __FreeBSD_version<600034) 246f1c579b1SScott Long .d_flags = D_NEEDGIANT, 24722f2616bSXin LI #endif 248f1c579b1SScott Long .d_open = arcmsr_open, /* open */ 249f1c579b1SScott Long .d_close = arcmsr_close, /* close */ 250f1c579b1SScott Long .d_ioctl = arcmsr_ioctl, /* ioctl */ 251f1c579b1SScott Long .d_name = "arcmsr", /* name */ 252f1c579b1SScott Long }; 253f1c579b1SScott Long #else 254f1c579b1SScott Long #define ARCMSR_CDEV_MAJOR 180 255f1c579b1SScott Long 256f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw = { 257f1c579b1SScott Long arcmsr_open, /* open */ 258f1c579b1SScott Long arcmsr_close, /* close */ 259f1c579b1SScott Long noread, /* read */ 260f1c579b1SScott Long nowrite, /* write */ 261f1c579b1SScott Long arcmsr_ioctl, /* ioctl */ 262f1c579b1SScott Long nopoll, /* poll */ 263f1c579b1SScott Long nommap, /* mmap */ 264f1c579b1SScott Long nostrategy, /* strategy */ 265f1c579b1SScott Long "arcmsr", /* name */ 266f1c579b1SScott Long ARCMSR_CDEV_MAJOR, /* major */ 267f1c579b1SScott Long nodump, /* dump */ 268f1c579b1SScott Long nopsize, /* psize */ 269f1c579b1SScott Long 0 /* flags */ 270f1c579b1SScott Long }; 271f1c579b1SScott Long #endif 272d74001adSXin LI /* 273d74001adSXin LI ************************************************************************** 274d74001adSXin LI ************************************************************************** 275d74001adSXin LI */ 276f1c579b1SScott Long #if __FreeBSD_version < 500005 277f1c579b1SScott Long static int arcmsr_open(dev_t dev, int flags, int fmt, struct proc *proc) 278f1c579b1SScott Long #else 279f1c579b1SScott Long #if __FreeBSD_version < 503000 280f1c579b1SScott Long static int arcmsr_open(dev_t dev, int flags, int fmt, struct thread *proc) 281f1c579b1SScott Long #else 28200b4e54aSWarner Losh static int arcmsr_open(struct cdev *dev, int flags, int fmt, struct thread *proc) 283f1c579b1SScott Long #endif 284f1c579b1SScott Long #endif 285f1c579b1SScott Long { 286f1c579b1SScott Long #if __FreeBSD_version < 503000 287ad6d6297SScott Long struct AdapterControlBlock *acb = dev->si_drv1; 288f1c579b1SScott Long #else 2896bfa9a2dSEd Schouten int unit = dev2unit(dev); 290ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 291f1c579b1SScott Long #endif 292ad6d6297SScott Long if(acb == NULL) { 293f1c579b1SScott Long return ENXIO; 294f1c579b1SScott Long } 295dac36688SXin LI return (0); 296f1c579b1SScott Long } 297f1c579b1SScott Long /* 298f1c579b1SScott Long ************************************************************************** 299f1c579b1SScott Long ************************************************************************** 300f1c579b1SScott Long */ 301f1c579b1SScott Long #if __FreeBSD_version < 500005 302f1c579b1SScott Long static int arcmsr_close(dev_t dev, int flags, int fmt, struct proc *proc) 303f1c579b1SScott Long #else 304f1c579b1SScott Long #if __FreeBSD_version < 503000 305f1c579b1SScott Long static int arcmsr_close(dev_t dev, int flags, int fmt, struct thread *proc) 306f1c579b1SScott Long #else 30700b4e54aSWarner Losh static int arcmsr_close(struct cdev *dev, int flags, int fmt, struct thread *proc) 308f1c579b1SScott Long #endif 309f1c579b1SScott Long #endif 310f1c579b1SScott Long { 311f1c579b1SScott Long #if __FreeBSD_version < 503000 312ad6d6297SScott Long struct AdapterControlBlock *acb = dev->si_drv1; 313f1c579b1SScott Long #else 3146bfa9a2dSEd Schouten int unit = dev2unit(dev); 315ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 316f1c579b1SScott Long #endif 317ad6d6297SScott Long if(acb == NULL) { 318f1c579b1SScott Long return ENXIO; 319f1c579b1SScott Long } 320f1c579b1SScott Long return 0; 321f1c579b1SScott Long } 322f1c579b1SScott Long /* 323f1c579b1SScott Long ************************************************************************** 324f1c579b1SScott Long ************************************************************************** 325f1c579b1SScott Long */ 326f1c579b1SScott Long #if __FreeBSD_version < 500005 327f1c579b1SScott Long static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct proc *proc) 328f1c579b1SScott Long #else 329f1c579b1SScott Long #if __FreeBSD_version < 503000 330f1c579b1SScott Long static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc) 331f1c579b1SScott Long #else 33200b4e54aSWarner Losh static int arcmsr_ioctl(struct cdev *dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc) 333f1c579b1SScott Long #endif 334f1c579b1SScott Long #endif 335f1c579b1SScott Long { 336f1c579b1SScott Long #if __FreeBSD_version < 503000 337ad6d6297SScott Long struct AdapterControlBlock *acb = dev->si_drv1; 338f1c579b1SScott Long #else 3396bfa9a2dSEd Schouten int unit = dev2unit(dev); 340ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 341f1c579b1SScott Long #endif 342f1c579b1SScott Long 343ad6d6297SScott Long if(acb == NULL) { 344f1c579b1SScott Long return ENXIO; 345f1c579b1SScott Long } 346ad6d6297SScott Long return (arcmsr_iop_ioctlcmd(acb, ioctl_cmd, arg)); 347f1c579b1SScott Long } 348f1c579b1SScott Long /* 34944f05562SScott Long ********************************************************************** 35044f05562SScott Long ********************************************************************** 35144f05562SScott Long */ 35244f05562SScott Long static u_int32_t arcmsr_disable_allintr( struct AdapterControlBlock *acb) 35344f05562SScott Long { 35444f05562SScott Long u_int32_t intmask_org = 0; 35544f05562SScott Long 35644f05562SScott Long switch (acb->adapter_type) { 35744f05562SScott Long case ACB_ADAPTER_TYPE_A: { 35844f05562SScott Long /* disable all outbound interrupt */ 359d74001adSXin LI intmask_org = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intmask); /* disable outbound message0 int */ 360d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); 36144f05562SScott Long } 36244f05562SScott Long break; 36344f05562SScott Long case ACB_ADAPTER_TYPE_B: { 364b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 36544f05562SScott Long /* disable all outbound interrupt */ 366b23a1998SXin LI intmask_org = READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask) 367b23a1998SXin LI & (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); /* disable outbound message0 int */ 368b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask, 0); /* disable all interrupt */ 369d74001adSXin LI } 370d74001adSXin LI break; 371d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 372d74001adSXin LI /* disable all outbound interrupt */ 373d74001adSXin LI intmask_org = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_mask) ; /* disable outbound message0 int */ 374d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org|ARCMSR_HBCMU_ALL_INTMASKENABLE); 37544f05562SScott Long } 37644f05562SScott Long break; 3777a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 3787a7bc959SXin LI /* disable all outbound interrupt */ 3797a7bc959SXin LI intmask_org = CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable) ; /* disable outbound message0 int */ 3807a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, ARCMSR_HBDMU_ALL_INT_DISABLE); 3817a7bc959SXin LI } 3827a7bc959SXin LI break; 383a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 384a1103e04SXin LI /* disable all outbound interrupt */ 385a1103e04SXin LI intmask_org = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_mask) ; /* disable outbound message0 int */ 386a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_mask, intmask_org | ARCMSR_HBEMU_ALL_INTMASKENABLE); 387a1103e04SXin LI } 388a1103e04SXin LI break; 38944f05562SScott Long } 39044f05562SScott Long return (intmask_org); 39144f05562SScott Long } 39244f05562SScott Long /* 39344f05562SScott Long ********************************************************************** 39444f05562SScott Long ********************************************************************** 39544f05562SScott Long */ 39644f05562SScott Long static void arcmsr_enable_allintr( struct AdapterControlBlock *acb, u_int32_t intmask_org) 39744f05562SScott Long { 39844f05562SScott Long u_int32_t mask; 39944f05562SScott Long 40044f05562SScott Long switch (acb->adapter_type) { 40144f05562SScott Long case ACB_ADAPTER_TYPE_A: { 40244f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 403d74001adSXin LI mask = ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE); 40444f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org & mask); 40544f05562SScott Long acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; 40644f05562SScott Long } 40744f05562SScott Long break; 40844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 409b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 410d74001adSXin LI /* enable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */ 411d74001adSXin LI mask = (ARCMSR_IOP2DRV_DATA_WRITE_OK|ARCMSR_IOP2DRV_DATA_READ_OK|ARCMSR_IOP2DRV_CDB_DONE|ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); 412b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask, intmask_org | mask); /*1=interrupt enable, 0=interrupt disable*/ 41344f05562SScott Long acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f; 41444f05562SScott Long } 41544f05562SScott Long break; 416d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 417d74001adSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 418d74001adSXin LI mask = ~(ARCMSR_HBCMU_UTILITY_A_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK); 419d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org & mask); 420d74001adSXin LI acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f; 421d74001adSXin LI } 422d74001adSXin LI break; 4237a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 4247a7bc959SXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 4257a7bc959SXin LI mask = ARCMSR_HBDMU_ALL_INT_ENABLE; 4267a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, intmask_org | mask); 4277a7bc959SXin LI CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable); 4287a7bc959SXin LI acb->outbound_int_enable = mask; 4297a7bc959SXin LI } 4307a7bc959SXin LI break; 431a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 432a1103e04SXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 433a1103e04SXin LI mask = ~(ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR | ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR); 434a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_mask, intmask_org & mask); 435a1103e04SXin LI acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f; 436a1103e04SXin LI } 437a1103e04SXin LI break; 43844f05562SScott Long } 43944f05562SScott Long } 44044f05562SScott Long /* 44144f05562SScott Long ********************************************************************** 44244f05562SScott Long ********************************************************************** 44344f05562SScott Long */ 44444f05562SScott Long static u_int8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) 44544f05562SScott Long { 44644f05562SScott Long u_int32_t Index; 44744f05562SScott Long u_int8_t Retries = 0x00; 44844f05562SScott Long 44944f05562SScott Long do { 45044f05562SScott Long for(Index=0; Index < 100; Index++) { 451d74001adSXin LI if(CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { 452d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/ 45344f05562SScott Long return TRUE; 45444f05562SScott Long } 45544f05562SScott Long UDELAY(10000); 45644f05562SScott Long }/*max 1 seconds*/ 45744f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 458dac36688SXin LI return (FALSE); 45944f05562SScott Long } 46044f05562SScott Long /* 46144f05562SScott Long ********************************************************************** 46244f05562SScott Long ********************************************************************** 46344f05562SScott Long */ 46444f05562SScott Long static u_int8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) 46544f05562SScott Long { 46644f05562SScott Long u_int32_t Index; 46744f05562SScott Long u_int8_t Retries = 0x00; 468b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 46944f05562SScott Long 47044f05562SScott Long do { 47144f05562SScott Long for(Index=0; Index < 100; Index++) { 472b23a1998SXin LI if(READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { 473b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/ 474b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 475d74001adSXin LI return TRUE; 476d74001adSXin LI } 477d74001adSXin LI UDELAY(10000); 478d74001adSXin LI }/*max 1 seconds*/ 479d74001adSXin LI }while(Retries++ < 20);/*max 20 sec*/ 480dac36688SXin LI return (FALSE); 481d74001adSXin LI } 482d74001adSXin LI /* 483d74001adSXin LI ********************************************************************** 484d74001adSXin LI ********************************************************************** 485d74001adSXin LI */ 486d74001adSXin LI static u_int8_t arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock *acb) 487d74001adSXin LI { 488d74001adSXin LI u_int32_t Index; 489d74001adSXin LI u_int8_t Retries = 0x00; 490d74001adSXin LI 491d74001adSXin LI do { 492d74001adSXin LI for(Index=0; Index < 100; Index++) { 493d74001adSXin LI if(CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { 494d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);/*clear interrupt*/ 49544f05562SScott Long return TRUE; 49644f05562SScott Long } 49744f05562SScott Long UDELAY(10000); 49844f05562SScott Long }/*max 1 seconds*/ 49944f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 500dac36688SXin LI return (FALSE); 50144f05562SScott Long } 50244f05562SScott Long /* 5037a7bc959SXin LI ********************************************************************** 5047a7bc959SXin LI ********************************************************************** 5057a7bc959SXin LI */ 5067a7bc959SXin LI static u_int8_t arcmsr_hbd_wait_msgint_ready(struct AdapterControlBlock *acb) 5077a7bc959SXin LI { 5087a7bc959SXin LI u_int32_t Index; 5097a7bc959SXin LI u_int8_t Retries = 0x00; 5107a7bc959SXin LI 5117a7bc959SXin LI do { 5127a7bc959SXin LI for(Index=0; Index < 100; Index++) { 5137a7bc959SXin LI if(CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) { 5147a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR);/*clear interrupt*/ 5157a7bc959SXin LI return TRUE; 5167a7bc959SXin LI } 5177a7bc959SXin LI UDELAY(10000); 5187a7bc959SXin LI }/*max 1 seconds*/ 5197a7bc959SXin LI }while(Retries++ < 20);/*max 20 sec*/ 5207a7bc959SXin LI return (FALSE); 5217a7bc959SXin LI } 5227a7bc959SXin LI /* 523a1103e04SXin LI ********************************************************************** 524a1103e04SXin LI ********************************************************************** 525a1103e04SXin LI */ 526a1103e04SXin LI static u_int8_t arcmsr_hbe_wait_msgint_ready(struct AdapterControlBlock *acb) 527a1103e04SXin LI { 528a1103e04SXin LI u_int32_t Index, read_doorbell; 529a1103e04SXin LI u_int8_t Retries = 0x00; 530a1103e04SXin LI 531a1103e04SXin LI do { 532a1103e04SXin LI for(Index=0; Index < 100; Index++) { 533a1103e04SXin LI read_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell); 534a1103e04SXin LI if((read_doorbell ^ acb->in_doorbell) & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) { 535a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0);/*clear interrupt*/ 536a1103e04SXin LI acb->in_doorbell = read_doorbell; 537a1103e04SXin LI return TRUE; 538a1103e04SXin LI } 539a1103e04SXin LI UDELAY(10000); 540a1103e04SXin LI }/*max 1 seconds*/ 541a1103e04SXin LI }while(Retries++ < 20);/*max 20 sec*/ 542a1103e04SXin LI return (FALSE); 543a1103e04SXin LI } 544a1103e04SXin LI /* 54544f05562SScott Long ************************************************************************ 54644f05562SScott Long ************************************************************************ 54744f05562SScott Long */ 54844f05562SScott Long static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) 54944f05562SScott Long { 55044f05562SScott Long int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ 55144f05562SScott Long 552d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 55344f05562SScott Long do { 55444f05562SScott Long if(arcmsr_hba_wait_msgint_ready(acb)) { 55544f05562SScott Long break; 55644f05562SScott Long } else { 55744f05562SScott Long retry_count--; 55844f05562SScott Long } 55944f05562SScott Long }while(retry_count != 0); 56044f05562SScott Long } 56144f05562SScott Long /* 56244f05562SScott Long ************************************************************************ 56344f05562SScott Long ************************************************************************ 56444f05562SScott Long */ 56544f05562SScott Long static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) 56644f05562SScott Long { 56744f05562SScott Long int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ 568b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 56944f05562SScott Long 570b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_FLUSH_CACHE); 57144f05562SScott Long do { 57244f05562SScott Long if(arcmsr_hbb_wait_msgint_ready(acb)) { 57344f05562SScott Long break; 57444f05562SScott Long } else { 57544f05562SScott Long retry_count--; 57644f05562SScott Long } 57744f05562SScott Long }while(retry_count != 0); 57844f05562SScott Long } 57944f05562SScott Long /* 58044f05562SScott Long ************************************************************************ 58144f05562SScott Long ************************************************************************ 58244f05562SScott Long */ 583d74001adSXin LI static void arcmsr_flush_hbc_cache(struct AdapterControlBlock *acb) 584d74001adSXin LI { 585d74001adSXin LI int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ 586d74001adSXin LI 587d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 588d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 589d74001adSXin LI do { 590d74001adSXin LI if(arcmsr_hbc_wait_msgint_ready(acb)) { 591d74001adSXin LI break; 592d74001adSXin LI } else { 593d74001adSXin LI retry_count--; 594d74001adSXin LI } 595d74001adSXin LI }while(retry_count != 0); 596d74001adSXin LI } 597d74001adSXin LI /* 598d74001adSXin LI ************************************************************************ 599d74001adSXin LI ************************************************************************ 600d74001adSXin LI */ 6017a7bc959SXin LI static void arcmsr_flush_hbd_cache(struct AdapterControlBlock *acb) 6027a7bc959SXin LI { 6037a7bc959SXin LI int retry_count = 30; /* enlarge wait flush adapter cache time: 10 minute */ 6047a7bc959SXin LI 6057a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 6067a7bc959SXin LI do { 6077a7bc959SXin LI if(arcmsr_hbd_wait_msgint_ready(acb)) { 6087a7bc959SXin LI break; 6097a7bc959SXin LI } else { 6107a7bc959SXin LI retry_count--; 6117a7bc959SXin LI } 6127a7bc959SXin LI }while(retry_count != 0); 6137a7bc959SXin LI } 6147a7bc959SXin LI /* 6157a7bc959SXin LI ************************************************************************ 6167a7bc959SXin LI ************************************************************************ 6177a7bc959SXin LI */ 618a1103e04SXin LI static void arcmsr_flush_hbe_cache(struct AdapterControlBlock *acb) 619a1103e04SXin LI { 620a1103e04SXin LI int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ 621a1103e04SXin LI 622a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 623a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 624a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 625a1103e04SXin LI do { 626a1103e04SXin LI if(arcmsr_hbe_wait_msgint_ready(acb)) { 627a1103e04SXin LI break; 628a1103e04SXin LI } else { 629a1103e04SXin LI retry_count--; 630a1103e04SXin LI } 631a1103e04SXin LI }while(retry_count != 0); 632a1103e04SXin LI } 633a1103e04SXin LI /* 634a1103e04SXin LI ************************************************************************ 635a1103e04SXin LI ************************************************************************ 636a1103e04SXin LI */ 63744f05562SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) 63844f05562SScott Long { 63944f05562SScott Long switch (acb->adapter_type) { 64044f05562SScott Long case ACB_ADAPTER_TYPE_A: { 64144f05562SScott Long arcmsr_flush_hba_cache(acb); 64244f05562SScott Long } 64344f05562SScott Long break; 64444f05562SScott Long case ACB_ADAPTER_TYPE_B: { 64544f05562SScott Long arcmsr_flush_hbb_cache(acb); 64644f05562SScott Long } 64744f05562SScott Long break; 648d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 649d74001adSXin LI arcmsr_flush_hbc_cache(acb); 650d74001adSXin LI } 651d74001adSXin LI break; 6527a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 6537a7bc959SXin LI arcmsr_flush_hbd_cache(acb); 6547a7bc959SXin LI } 6557a7bc959SXin LI break; 656a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 657a1103e04SXin LI arcmsr_flush_hbe_cache(acb); 658a1103e04SXin LI } 659a1103e04SXin LI break; 66044f05562SScott Long } 66144f05562SScott Long } 66244f05562SScott Long /* 663ad6d6297SScott Long ******************************************************************************* 664ad6d6297SScott Long ******************************************************************************* 665f1c579b1SScott Long */ 666ad6d6297SScott Long static int arcmsr_suspend(device_t dev) 667f1c579b1SScott Long { 668ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 669f1c579b1SScott Long 670ad6d6297SScott Long /* flush controller */ 671ad6d6297SScott Long arcmsr_iop_parking(acb); 672d74001adSXin LI /* disable all outbound interrupt */ 673d74001adSXin LI arcmsr_disable_allintr(acb); 674ad6d6297SScott Long return(0); 675ad6d6297SScott Long } 676ad6d6297SScott Long /* 677ad6d6297SScott Long ******************************************************************************* 678ad6d6297SScott Long ******************************************************************************* 679ad6d6297SScott Long */ 680ad6d6297SScott Long static int arcmsr_resume(device_t dev) 681ad6d6297SScott Long { 682ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 683f1c579b1SScott Long 684ad6d6297SScott Long arcmsr_iop_init(acb); 685ad6d6297SScott Long return(0); 686f1c579b1SScott Long } 687f1c579b1SScott Long /* 688f1c579b1SScott Long ********************************************************************************* 689f1c579b1SScott Long ********************************************************************************* 690f1c579b1SScott Long */ 691ad6d6297SScott Long static void arcmsr_async(void *cb_arg, u_int32_t code, struct cam_path *path, void *arg) 692f1c579b1SScott Long { 693ad6d6297SScott Long struct AdapterControlBlock *acb; 694ad6d6297SScott Long u_int8_t target_id, target_lun; 695f1c579b1SScott Long struct cam_sim *sim; 696f1c579b1SScott Long 697f1c579b1SScott Long sim = (struct cam_sim *) cb_arg; 698ad6d6297SScott Long acb =(struct AdapterControlBlock *) cam_sim_softc(sim); 699ad6d6297SScott Long switch (code) { 700f1c579b1SScott Long case AC_LOST_DEVICE: 701f1c579b1SScott Long target_id = xpt_path_target_id(path); 702f1c579b1SScott Long target_lun = xpt_path_lun_id(path); 703d74001adSXin LI if((target_id > ARCMSR_MAX_TARGETID) || (target_lun > ARCMSR_MAX_TARGETLUN)) { 704f1c579b1SScott Long break; 705f1c579b1SScott Long } 706dac36688SXin LI // printf("%s:scsi id=%d lun=%d device lost \n", device_get_name(acb->pci_dev), target_id, target_lun); 707f1c579b1SScott Long break; 708f1c579b1SScott Long default: 709f1c579b1SScott Long break; 710f1c579b1SScott Long } 711f1c579b1SScott Long } 712f1c579b1SScott Long /* 713f1c579b1SScott Long ********************************************************************** 714f1c579b1SScott Long ********************************************************************** 715f1c579b1SScott Long */ 716ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb) 717f1c579b1SScott Long { 718ad6d6297SScott Long union ccb *pccb = srb->pccb; 719f1c579b1SScott Long 720ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 721ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 722dac36688SXin LI if(pccb->csio.sense_len) { 723ad6d6297SScott Long memset(&pccb->csio.sense_data, 0, sizeof(pccb->csio.sense_data)); 724ad6d6297SScott Long memcpy(&pccb->csio.sense_data, srb->arcmsr_cdb.SenseData, 725ad6d6297SScott Long get_min(sizeof(struct SENSE_DATA), sizeof(pccb->csio.sense_data))); 726ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); /* Valid,ErrorCode */ 727f1c579b1SScott Long pccb->ccb_h.status |= CAM_AUTOSNS_VALID; 728f1c579b1SScott Long } 729f1c579b1SScott Long } 730f1c579b1SScott Long /* 731f1c579b1SScott Long ********************************************************************* 73244f05562SScott Long ********************************************************************* 73344f05562SScott Long */ 73444f05562SScott Long static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) 73544f05562SScott Long { 73644f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 73744f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 738d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 73944f05562SScott Long } 74044f05562SScott Long } 74144f05562SScott Long /* 74244f05562SScott Long ********************************************************************* 74344f05562SScott Long ********************************************************************* 74444f05562SScott Long */ 74544f05562SScott Long static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) 74644f05562SScott Long { 747b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 748b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_ABORT_CMD); 74944f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 750d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 751d74001adSXin LI } 752d74001adSXin LI } 753d74001adSXin LI /* 754d74001adSXin LI ********************************************************************* 755d74001adSXin LI ********************************************************************* 756d74001adSXin LI */ 757d74001adSXin LI static void arcmsr_abort_hbc_allcmd(struct AdapterControlBlock *acb) 758d74001adSXin LI { 759d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 760d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 761d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 762d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 76344f05562SScott Long } 76444f05562SScott Long } 76544f05562SScott Long /* 76644f05562SScott Long ********************************************************************* 767f1c579b1SScott Long ********************************************************************* 768f1c579b1SScott Long */ 7697a7bc959SXin LI static void arcmsr_abort_hbd_allcmd(struct AdapterControlBlock *acb) 7707a7bc959SXin LI { 7717a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 7727a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 7737a7bc959SXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 7747a7bc959SXin LI } 7757a7bc959SXin LI } 7767a7bc959SXin LI /* 7777a7bc959SXin LI ********************************************************************* 7787a7bc959SXin LI ********************************************************************* 7797a7bc959SXin LI */ 780a1103e04SXin LI static void arcmsr_abort_hbe_allcmd(struct AdapterControlBlock *acb) 781a1103e04SXin LI { 782a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 783a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 784a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 785a1103e04SXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) { 786a1103e04SXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 787a1103e04SXin LI } 788a1103e04SXin LI } 789a1103e04SXin LI /* 790a1103e04SXin LI ********************************************************************* 791a1103e04SXin LI ********************************************************************* 792a1103e04SXin LI */ 793ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) 794f1c579b1SScott Long { 79544f05562SScott Long switch (acb->adapter_type) { 79644f05562SScott Long case ACB_ADAPTER_TYPE_A: { 79744f05562SScott Long arcmsr_abort_hba_allcmd(acb); 79844f05562SScott Long } 79944f05562SScott Long break; 80044f05562SScott Long case ACB_ADAPTER_TYPE_B: { 80144f05562SScott Long arcmsr_abort_hbb_allcmd(acb); 80244f05562SScott Long } 80344f05562SScott Long break; 804d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 805d74001adSXin LI arcmsr_abort_hbc_allcmd(acb); 806d74001adSXin LI } 807d74001adSXin LI break; 8087a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 8097a7bc959SXin LI arcmsr_abort_hbd_allcmd(acb); 8107a7bc959SXin LI } 8117a7bc959SXin LI break; 812a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 813a1103e04SXin LI arcmsr_abort_hbe_allcmd(acb); 814a1103e04SXin LI } 815a1103e04SXin LI break; 81644f05562SScott Long } 81744f05562SScott Long } 81844f05562SScott Long /* 819231c8b71SXin LI ********************************************************************** 820231c8b71SXin LI ********************************************************************** 821231c8b71SXin LI */ 822231c8b71SXin LI static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag) 823231c8b71SXin LI { 824231c8b71SXin LI struct AdapterControlBlock *acb = srb->acb; 825231c8b71SXin LI union ccb *pccb = srb->pccb; 826231c8b71SXin LI 82722f2616bSXin LI if(srb->srb_flags & SRB_FLAG_TIMER_START) 82822f2616bSXin LI callout_stop(&srb->ccb_callout); 829231c8b71SXin LI if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 830231c8b71SXin LI bus_dmasync_op_t op; 831231c8b71SXin LI 832231c8b71SXin LI if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 833231c8b71SXin LI op = BUS_DMASYNC_POSTREAD; 834231c8b71SXin LI } else { 835231c8b71SXin LI op = BUS_DMASYNC_POSTWRITE; 836231c8b71SXin LI } 837231c8b71SXin LI bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 838231c8b71SXin LI bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 839231c8b71SXin LI } 840231c8b71SXin LI if(stand_flag == 1) { 841231c8b71SXin LI atomic_subtract_int(&acb->srboutstandingcount, 1); 842231c8b71SXin LI if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) && ( 843abfdbca9SXin LI acb->srboutstandingcount < (acb->maxOutstanding -10))) { 844231c8b71SXin LI acb->acb_flags &= ~ACB_F_CAM_DEV_QFRZN; 845231c8b71SXin LI pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 846231c8b71SXin LI } 847231c8b71SXin LI } 84822f2616bSXin LI if(srb->srb_state != ARCMSR_SRB_TIMEOUT) 84922f2616bSXin LI arcmsr_free_srb(srb); 85022f2616bSXin LI acb->pktReturnCount++; 851231c8b71SXin LI xpt_done(pccb); 852231c8b71SXin LI } 853231c8b71SXin LI /* 85444f05562SScott Long ************************************************************************** 85544f05562SScott Long ************************************************************************** 85644f05562SScott Long */ 857d74001adSXin LI static void arcmsr_report_srb_state(struct AdapterControlBlock *acb, struct CommandControlBlock *srb, u_int16_t error) 85844f05562SScott Long { 85944f05562SScott Long int target, lun; 86044f05562SScott Long 86144f05562SScott Long target = srb->pccb->ccb_h.target_id; 86244f05562SScott Long lun = srb->pccb->ccb_h.target_lun; 863d74001adSXin LI if(error == FALSE) { 86444f05562SScott Long if(acb->devstate[target][lun] == ARECA_RAID_GONE) { 86544f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GOOD; 86644f05562SScott Long } 86744f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_CMP; 86844f05562SScott Long arcmsr_srb_complete(srb, 1); 86944f05562SScott Long } else { 87044f05562SScott Long switch(srb->arcmsr_cdb.DeviceStatus) { 87144f05562SScott Long case ARCMSR_DEV_SELECT_TIMEOUT: { 87244f05562SScott Long if(acb->devstate[target][lun] == ARECA_RAID_GOOD) { 873d74001adSXin LI printf( "arcmsr%d: Target=%x, Lun=%x, selection timeout, raid volume was lost\n", acb->pci_unit, target, lun); 874ad6d6297SScott Long } 87544f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GONE; 876d74001adSXin LI srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 87744f05562SScott Long arcmsr_srb_complete(srb, 1); 87844f05562SScott Long } 87944f05562SScott Long break; 88044f05562SScott Long case ARCMSR_DEV_ABORTED: 88144f05562SScott Long case ARCMSR_DEV_INIT_FAIL: { 88244f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GONE; 88344f05562SScott Long srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 88444f05562SScott Long arcmsr_srb_complete(srb, 1); 88544f05562SScott Long } 88644f05562SScott Long break; 88744f05562SScott Long case SCSISTAT_CHECK_CONDITION: { 88844f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GOOD; 88944f05562SScott Long arcmsr_report_sense_info(srb); 89044f05562SScott Long arcmsr_srb_complete(srb, 1); 89144f05562SScott Long } 89244f05562SScott Long break; 89344f05562SScott Long default: 89410d66948SKevin Lo printf("arcmsr%d: scsi id=%d lun=%d isr got command error done,but got unknown DeviceStatus=0x%x \n" 895d74001adSXin LI , acb->pci_unit, target, lun ,srb->arcmsr_cdb.DeviceStatus); 89644f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GONE; 89744f05562SScott Long srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY; 89810d66948SKevin Lo /*unknown error or crc error just for retry*/ 89944f05562SScott Long arcmsr_srb_complete(srb, 1); 90044f05562SScott Long break; 90144f05562SScott Long } 90244f05562SScott Long } 90344f05562SScott Long } 90444f05562SScott Long /* 90544f05562SScott Long ************************************************************************** 90644f05562SScott Long ************************************************************************** 90744f05562SScott Long */ 908d74001adSXin LI static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t flag_srb, u_int16_t error) 90944f05562SScott Long { 91044f05562SScott Long struct CommandControlBlock *srb; 91144f05562SScott Long 91244f05562SScott Long /* check if command done with no error*/ 913d74001adSXin LI switch (acb->adapter_type) { 914*fc5ef1caSXin LI case ACB_ADAPTER_TYPE_A: 915*fc5ef1caSXin LI case ACB_ADAPTER_TYPE_B: 916*fc5ef1caSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 917*fc5ef1caSXin LI break; 918d74001adSXin LI case ACB_ADAPTER_TYPE_C: 9197a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 92022f2616bSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0)); /*frame must be 32 bytes aligned*/ 921d74001adSXin LI break; 922a1103e04SXin LI case ACB_ADAPTER_TYPE_E: 923a1103e04SXin LI srb = acb->psrb_pool[flag_srb]; 924a1103e04SXin LI break; 925d74001adSXin LI default: 926d74001adSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 927d74001adSXin LI break; 928d74001adSXin LI } 92922f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 93022f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_TIMEOUT) { 93122f2616bSXin LI arcmsr_free_srb(srb); 93222f2616bSXin LI printf("arcmsr%d: srb='%p' return srb has been timeouted\n", acb->pci_unit, srb); 93344f05562SScott Long return; 93444f05562SScott Long } 93522f2616bSXin LI printf("arcmsr%d: return srb has been completed\n" 93622f2616bSXin LI "srb='%p' srb_state=0x%x outstanding srb count=%d \n", 93722f2616bSXin LI acb->pci_unit, srb, srb->srb_state, acb->srboutstandingcount); 93844f05562SScott Long return; 93944f05562SScott Long } 940d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 94144f05562SScott Long } 94244f05562SScott Long /* 94322f2616bSXin LI ************************************************************************** 94422f2616bSXin LI ************************************************************************** 94522f2616bSXin LI */ 94622f2616bSXin LI static void arcmsr_srb_timeout(void *arg) 94722f2616bSXin LI { 94822f2616bSXin LI struct CommandControlBlock *srb = (struct CommandControlBlock *)arg; 94922f2616bSXin LI struct AdapterControlBlock *acb; 95022f2616bSXin LI int target, lun; 95122f2616bSXin LI u_int8_t cmd; 95222f2616bSXin LI 95322f2616bSXin LI target = srb->pccb->ccb_h.target_id; 95422f2616bSXin LI lun = srb->pccb->ccb_h.target_lun; 95522f2616bSXin LI acb = srb->acb; 9567a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 95722f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) 95822f2616bSXin LI { 9594aa947cbSWarner Losh cmd = scsiio_cdb_ptr(&srb->pccb->csio)[0]; 96022f2616bSXin LI srb->srb_state = ARCMSR_SRB_TIMEOUT; 96122f2616bSXin LI srb->pccb->ccb_h.status |= CAM_CMD_TIMEOUT; 96222f2616bSXin LI arcmsr_srb_complete(srb, 1); 96322f2616bSXin LI printf("arcmsr%d: scsi id %d lun %d cmd=0x%x srb='%p' ccb command time out!\n", 96422f2616bSXin LI acb->pci_unit, target, lun, cmd, srb); 96522f2616bSXin LI } 9667a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 96722f2616bSXin LI #ifdef ARCMSR_DEBUG1 96822f2616bSXin LI arcmsr_dump_data(acb); 96922f2616bSXin LI #endif 97022f2616bSXin LI } 97122f2616bSXin LI 97222f2616bSXin LI /* 97344f05562SScott Long ********************************************************************** 97444f05562SScott Long ********************************************************************** 97544f05562SScott Long */ 97644f05562SScott Long static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) 97744f05562SScott Long { 97844f05562SScott Long int i=0; 97944f05562SScott Long u_int32_t flag_srb; 980d74001adSXin LI u_int16_t error; 98144f05562SScott Long 98244f05562SScott Long switch (acb->adapter_type) { 98344f05562SScott Long case ACB_ADAPTER_TYPE_A: { 98444f05562SScott Long u_int32_t outbound_intstatus; 98544f05562SScott Long 98644f05562SScott Long /*clear and abort all outbound posted Q*/ 987d74001adSXin LI outbound_intstatus = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 988d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/ 989d74001adSXin LI while(((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_queueport)) != 0xFFFFFFFF) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { 990d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 991d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 99244f05562SScott Long } 99344f05562SScott Long } 99444f05562SScott Long break; 99544f05562SScott Long case ACB_ADAPTER_TYPE_B: { 99644f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 99744f05562SScott Long 99844f05562SScott Long /*clear all outbound posted Q*/ 999b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 100044f05562SScott Long for(i=0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) { 100144f05562SScott Long if((flag_srb = phbbmu->done_qbuffer[i]) != 0) { 100244f05562SScott Long phbbmu->done_qbuffer[i] = 0; 1003d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 1004d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 100544f05562SScott Long } 100644f05562SScott Long phbbmu->post_qbuffer[i] = 0; 100744f05562SScott Long }/*drain reply FIFO*/ 100844f05562SScott Long phbbmu->doneq_index = 0; 100944f05562SScott Long phbbmu->postq_index = 0; 101044f05562SScott Long } 101144f05562SScott Long break; 1012d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1013d74001adSXin LI 1014d74001adSXin LI while((CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { 1015d74001adSXin LI flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 1016d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 1017d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 1018d74001adSXin LI } 1019d74001adSXin LI } 1020d74001adSXin LI break; 10217a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 10227a7bc959SXin LI arcmsr_hbd_postqueue_isr(acb); 10237a7bc959SXin LI } 10247a7bc959SXin LI break; 1025a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 1026a1103e04SXin LI arcmsr_hbe_postqueue_isr(acb); 1027a1103e04SXin LI } 1028a1103e04SXin LI break; 102944f05562SScott Long } 1030f1c579b1SScott Long } 1031f1c579b1SScott Long /* 1032f1c579b1SScott Long **************************************************************************** 1033f1c579b1SScott Long **************************************************************************** 1034f1c579b1SScott Long */ 1035ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb) 1036f1c579b1SScott Long { 1037ad6d6297SScott Long struct CommandControlBlock *srb; 103844f05562SScott Long u_int32_t intmask_org; 1039ad6d6297SScott Long u_int32_t i=0; 1040f1c579b1SScott Long 104144f05562SScott Long if(acb->srboutstandingcount>0) { 104244f05562SScott Long /* disable all outbound interrupt */ 104344f05562SScott Long intmask_org = arcmsr_disable_allintr(acb); 104444f05562SScott Long /*clear and abort all outbound posted Q*/ 104544f05562SScott Long arcmsr_done4abort_postqueue(acb); 1046f1c579b1SScott Long /* talk to iop 331 outstanding command aborted*/ 1047ad6d6297SScott Long arcmsr_abort_allcmd(acb); 1048ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 1049ad6d6297SScott Long srb = acb->psrb_pool[i]; 105022f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) { 105122f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 1052ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 1053ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 1054123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p' aborted\n" 105522f2616bSXin LI , acb->pci_unit, srb->pccb->ccb_h.target_id 1056123055f0SNathan Whitehorn , (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 1057f1c579b1SScott Long } 1058f1c579b1SScott Long } 1059f1c579b1SScott Long /* enable all outbound interrupt */ 106044f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 1061f1c579b1SScott Long } 106222f2616bSXin LI acb->srboutstandingcount = 0; 1063ad6d6297SScott Long acb->workingsrb_doneindex = 0; 1064ad6d6297SScott Long acb->workingsrb_startindex = 0; 106522f2616bSXin LI acb->pktRequestCount = 0; 106622f2616bSXin LI acb->pktReturnCount = 0; 1067f1c579b1SScott Long } 1068f1c579b1SScott Long /* 1069f1c579b1SScott Long ********************************************************************** 1070f1c579b1SScott Long ********************************************************************** 1071f1c579b1SScott Long */ 107244f05562SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, 107344f05562SScott Long bus_dma_segment_t *dm_segs, u_int32_t nseg) 1074f1c579b1SScott Long { 1075ad6d6297SScott Long struct ARCMSR_CDB *arcmsr_cdb = &srb->arcmsr_cdb; 1076ad6d6297SScott Long u_int8_t *psge = (u_int8_t *)&arcmsr_cdb->u; 1077ad6d6297SScott Long u_int32_t address_lo, address_hi; 1078ad6d6297SScott Long union ccb *pccb = srb->pccb; 1079f1c579b1SScott Long struct ccb_scsiio *pcsio = &pccb->csio; 1080ad6d6297SScott Long u_int32_t arccdbsize = 0x30; 1081f1c579b1SScott Long 1082ad6d6297SScott Long memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB)); 1083ad6d6297SScott Long arcmsr_cdb->Bus = 0; 1084ad6d6297SScott Long arcmsr_cdb->TargetID = pccb->ccb_h.target_id; 1085ad6d6297SScott Long arcmsr_cdb->LUN = pccb->ccb_h.target_lun; 1086ad6d6297SScott Long arcmsr_cdb->Function = 1; 1087ad6d6297SScott Long arcmsr_cdb->CdbLength = (u_int8_t)pcsio->cdb_len; 10884aa947cbSWarner Losh bcopy(scsiio_cdb_ptr(pcsio), arcmsr_cdb->Cdb, pcsio->cdb_len); 1089ad6d6297SScott Long if(nseg != 0) { 1090ad6d6297SScott Long struct AdapterControlBlock *acb = srb->acb; 1091f1c579b1SScott Long bus_dmasync_op_t op; 1092ad6d6297SScott Long u_int32_t length, i, cdb_sgcount = 0; 1093f1c579b1SScott Long 1094ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 1095ad6d6297SScott Long op = BUS_DMASYNC_PREREAD; 1096ad6d6297SScott Long } else { 1097ad6d6297SScott Long op = BUS_DMASYNC_PREWRITE; 1098ad6d6297SScott Long arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE; 1099ad6d6297SScott Long srb->srb_flags |= SRB_FLAG_WRITE; 1100ad6d6297SScott Long } 1101ad6d6297SScott Long bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 1102ad6d6297SScott Long for(i=0; i < nseg; i++) { 1103f1c579b1SScott Long /* Get the physical address of the current data pointer */ 1104ad6d6297SScott Long length = arcmsr_htole32(dm_segs[i].ds_len); 1105ad6d6297SScott Long address_lo = arcmsr_htole32(dma_addr_lo32(dm_segs[i].ds_addr)); 1106ad6d6297SScott Long address_hi = arcmsr_htole32(dma_addr_hi32(dm_segs[i].ds_addr)); 1107ad6d6297SScott Long if(address_hi == 0) { 1108ad6d6297SScott Long struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge; 1109f1c579b1SScott Long pdma_sg->address = address_lo; 1110f1c579b1SScott Long pdma_sg->length = length; 1111ad6d6297SScott Long psge += sizeof(struct SG32ENTRY); 1112ad6d6297SScott Long arccdbsize += sizeof(struct SG32ENTRY); 1113ad6d6297SScott Long } else { 1114ad6d6297SScott Long u_int32_t sg64s_size = 0, tmplength = length; 1115f1c579b1SScott Long 1116ad6d6297SScott Long while(1) { 1117ad6d6297SScott Long u_int64_t span4G, length0; 1118ad6d6297SScott Long struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge; 1119f1c579b1SScott Long 1120ad6d6297SScott Long span4G = (u_int64_t)address_lo + tmplength; 1121f1c579b1SScott Long pdma_sg->addresshigh = address_hi; 1122f1c579b1SScott Long pdma_sg->address = address_lo; 1123ad6d6297SScott Long if(span4G > 0x100000000) { 1124f1c579b1SScott Long /*see if cross 4G boundary*/ 1125f1c579b1SScott Long length0 = 0x100000000-address_lo; 1126ad6d6297SScott Long pdma_sg->length = (u_int32_t)length0 | IS_SG64_ADDR; 1127f1c579b1SScott Long address_hi = address_hi+1; 1128f1c579b1SScott Long address_lo = 0; 1129ad6d6297SScott Long tmplength = tmplength - (u_int32_t)length0; 1130ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 1131ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 1132f1c579b1SScott Long cdb_sgcount++; 1133ad6d6297SScott Long } else { 1134f1c579b1SScott Long pdma_sg->length = tmplength | IS_SG64_ADDR; 1135ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 1136ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 1137f1c579b1SScott Long break; 1138f1c579b1SScott Long } 1139f1c579b1SScott Long } 1140f1c579b1SScott Long arccdbsize += sg64s_size; 1141f1c579b1SScott Long } 1142f1c579b1SScott Long cdb_sgcount++; 1143f1c579b1SScott Long } 1144ad6d6297SScott Long arcmsr_cdb->sgcount = (u_int8_t)cdb_sgcount; 1145ad6d6297SScott Long arcmsr_cdb->DataLength = pcsio->dxfer_len; 1146ad6d6297SScott Long if( arccdbsize > 256) { 1147ad6d6297SScott Long arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE; 1148f1c579b1SScott Long } 1149d74001adSXin LI } else { 1150d74001adSXin LI arcmsr_cdb->DataLength = 0; 1151f1c579b1SScott Long } 1152d74001adSXin LI srb->arc_cdb_size = arccdbsize; 11537a7bc959SXin LI arcmsr_cdb->msgPages = (arccdbsize/256) + ((arccdbsize % 256) ? 1 : 0); 1154f1c579b1SScott Long } 1155f1c579b1SScott Long /* 1156f1c579b1SScott Long ************************************************************************** 1157f1c579b1SScott Long ************************************************************************** 1158f1c579b1SScott Long */ 1159ad6d6297SScott Long static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandControlBlock *srb) 1160f1c579b1SScott Long { 11617a7bc959SXin LI u_int32_t cdb_phyaddr_low = (u_int32_t) srb->cdb_phyaddr_low; 1162ad6d6297SScott Long struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&srb->arcmsr_cdb; 1163f1c579b1SScott Long 1164d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, (srb->srb_flags & SRB_FLAG_WRITE) ? BUS_DMASYNC_POSTWRITE:BUS_DMASYNC_POSTREAD); 1165ad6d6297SScott Long atomic_add_int(&acb->srboutstandingcount, 1); 116622f2616bSXin LI srb->srb_state = ARCMSR_SRB_START; 1167d74001adSXin LI 116844f05562SScott Long switch (acb->adapter_type) { 116944f05562SScott Long case ACB_ADAPTER_TYPE_A: { 1170ad6d6297SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 11717a7bc959SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_phyaddr_low|ARCMSR_SRBPOST_FLAG_SGL_BSIZE); 1172ad6d6297SScott Long } else { 11737a7bc959SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_phyaddr_low); 117444f05562SScott Long } 117544f05562SScott Long } 117644f05562SScott Long break; 117744f05562SScott Long case ACB_ADAPTER_TYPE_B: { 117844f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 117944f05562SScott Long int ending_index, index; 118044f05562SScott Long 118144f05562SScott Long index = phbbmu->postq_index; 118244f05562SScott Long ending_index = ((index+1) % ARCMSR_MAX_HBB_POSTQUEUE); 118344f05562SScott Long phbbmu->post_qbuffer[ending_index] = 0; 118444f05562SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 11857a7bc959SXin LI phbbmu->post_qbuffer[index] = cdb_phyaddr_low | ARCMSR_SRBPOST_FLAG_SGL_BSIZE; 118644f05562SScott Long } else { 11877a7bc959SXin LI phbbmu->post_qbuffer[index] = cdb_phyaddr_low; 118844f05562SScott Long } 118944f05562SScott Long index++; 119044f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 119144f05562SScott Long phbbmu->postq_index = index; 1192b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED); 1193d74001adSXin LI } 1194d74001adSXin LI break; 11957a7bc959SXin LI case ACB_ADAPTER_TYPE_C: { 1196d74001adSXin LI u_int32_t ccb_post_stamp, arc_cdb_size, cdb_phyaddr_hi32; 1197d74001adSXin LI 1198d74001adSXin LI arc_cdb_size = (srb->arc_cdb_size > 0x300) ? 0x300 : srb->arc_cdb_size; 11997a7bc959SXin LI ccb_post_stamp = (cdb_phyaddr_low | ((arc_cdb_size-1) >> 6) | 1); 1200d74001adSXin LI cdb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high; 1201d74001adSXin LI if(cdb_phyaddr_hi32) 1202d74001adSXin LI { 1203d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_high, cdb_phyaddr_hi32); 1204d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp); 1205d74001adSXin LI } 1206d74001adSXin LI else 1207d74001adSXin LI { 1208d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp); 1209d74001adSXin LI } 121044f05562SScott Long } 121144f05562SScott Long break; 12127a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 12137a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 12147a7bc959SXin LI u_int16_t index_stripped; 12157a7bc959SXin LI u_int16_t postq_index; 12167a7bc959SXin LI struct InBound_SRB *pinbound_srb; 12177a7bc959SXin LI 12187a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->postDone_lock); 12197a7bc959SXin LI postq_index = phbdmu->postq_index; 12207a7bc959SXin LI pinbound_srb = (struct InBound_SRB *)&phbdmu->post_qbuffer[postq_index & 0xFF]; 12217a7bc959SXin LI pinbound_srb->addressHigh = srb->cdb_phyaddr_high; 12227a7bc959SXin LI pinbound_srb->addressLow = srb->cdb_phyaddr_low; 12237a7bc959SXin LI pinbound_srb->length = srb->arc_cdb_size >> 2; 12247a7bc959SXin LI arcmsr_cdb->Context = srb->cdb_phyaddr_low; 12257a7bc959SXin LI if (postq_index & 0x4000) { 12267a7bc959SXin LI index_stripped = postq_index & 0xFF; 12277a7bc959SXin LI index_stripped += 1; 12287a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 12297a7bc959SXin LI phbdmu->postq_index = index_stripped ? (index_stripped | 0x4000) : index_stripped; 12307a7bc959SXin LI } else { 12317a7bc959SXin LI index_stripped = postq_index; 12327a7bc959SXin LI index_stripped += 1; 12337a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 12347a7bc959SXin LI phbdmu->postq_index = index_stripped ? index_stripped : (index_stripped | 0x4000); 12357a7bc959SXin LI } 12367a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inboundlist_write_pointer, postq_index); 12377a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->postDone_lock); 12387a7bc959SXin LI } 12397a7bc959SXin LI break; 1240a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 1241a1103e04SXin LI u_int32_t ccb_post_stamp, arc_cdb_size; 1242a1103e04SXin LI 1243a1103e04SXin LI arc_cdb_size = (srb->arc_cdb_size > 0x300) ? 0x300 : srb->arc_cdb_size; 1244a1103e04SXin LI ccb_post_stamp = (srb->smid | ((arc_cdb_size-1) >> 6)); 1245a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_queueport_high, 0); 1246a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_queueport_low, ccb_post_stamp); 1247a1103e04SXin LI } 1248a1103e04SXin LI break; 1249f1c579b1SScott Long } 1250f1c579b1SScott Long } 1251f1c579b1SScott Long /* 125244f05562SScott Long ************************************************************************ 125344f05562SScott Long ************************************************************************ 125444f05562SScott Long */ 125544f05562SScott Long static struct QBUFFER *arcmsr_get_iop_rqbuffer( struct AdapterControlBlock *acb) 125644f05562SScott Long { 125744f05562SScott Long struct QBUFFER *qbuffer=NULL; 125844f05562SScott Long 125944f05562SScott Long switch (acb->adapter_type) { 126044f05562SScott Long case ACB_ADAPTER_TYPE_A: { 126144f05562SScott Long struct HBA_MessageUnit *phbamu = (struct HBA_MessageUnit *)acb->pmu; 126244f05562SScott Long 126344f05562SScott Long qbuffer = (struct QBUFFER *)&phbamu->message_rbuffer; 126444f05562SScott Long } 126544f05562SScott Long break; 126644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 126744f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 126844f05562SScott Long 126944f05562SScott Long qbuffer = (struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_rbuffer; 127044f05562SScott Long } 127144f05562SScott Long break; 1272d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1273d74001adSXin LI struct HBC_MessageUnit *phbcmu = (struct HBC_MessageUnit *)acb->pmu; 1274d74001adSXin LI 1275d74001adSXin LI qbuffer = (struct QBUFFER *)&phbcmu->message_rbuffer; 1276d74001adSXin LI } 1277d74001adSXin LI break; 12787a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 12797a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 12807a7bc959SXin LI 12817a7bc959SXin LI qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_rbuffer; 12827a7bc959SXin LI } 12837a7bc959SXin LI break; 1284a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 1285a1103e04SXin LI struct HBE_MessageUnit *phbcmu = (struct HBE_MessageUnit *)acb->pmu; 1286a1103e04SXin LI 1287a1103e04SXin LI qbuffer = (struct QBUFFER *)&phbcmu->message_rbuffer; 1288a1103e04SXin LI } 1289a1103e04SXin LI break; 129044f05562SScott Long } 129144f05562SScott Long return(qbuffer); 129244f05562SScott Long } 129344f05562SScott Long /* 129444f05562SScott Long ************************************************************************ 129544f05562SScott Long ************************************************************************ 129644f05562SScott Long */ 129744f05562SScott Long static struct QBUFFER *arcmsr_get_iop_wqbuffer( struct AdapterControlBlock *acb) 129844f05562SScott Long { 129944f05562SScott Long struct QBUFFER *qbuffer = NULL; 130044f05562SScott Long 130144f05562SScott Long switch (acb->adapter_type) { 130244f05562SScott Long case ACB_ADAPTER_TYPE_A: { 130344f05562SScott Long struct HBA_MessageUnit *phbamu = (struct HBA_MessageUnit *)acb->pmu; 130444f05562SScott Long 130544f05562SScott Long qbuffer = (struct QBUFFER *)&phbamu->message_wbuffer; 130644f05562SScott Long } 130744f05562SScott Long break; 130844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 130944f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 131044f05562SScott Long 131144f05562SScott Long qbuffer = (struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_wbuffer; 131244f05562SScott Long } 131344f05562SScott Long break; 1314d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1315d74001adSXin LI struct HBC_MessageUnit *phbcmu = (struct HBC_MessageUnit *)acb->pmu; 1316d74001adSXin LI 1317d74001adSXin LI qbuffer = (struct QBUFFER *)&phbcmu->message_wbuffer; 1318d74001adSXin LI } 1319d74001adSXin LI break; 13207a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 13217a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 13227a7bc959SXin LI 13237a7bc959SXin LI qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_wbuffer; 13247a7bc959SXin LI } 13257a7bc959SXin LI break; 1326a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 1327a1103e04SXin LI struct HBE_MessageUnit *phbcmu = (struct HBE_MessageUnit *)acb->pmu; 1328a1103e04SXin LI 1329a1103e04SXin LI qbuffer = (struct QBUFFER *)&phbcmu->message_wbuffer; 1330a1103e04SXin LI } 1331a1103e04SXin LI break; 133244f05562SScott Long } 133344f05562SScott Long return(qbuffer); 133444f05562SScott Long } 133544f05562SScott Long /* 133644f05562SScott Long ************************************************************************** 133744f05562SScott Long ************************************************************************** 133844f05562SScott Long */ 133944f05562SScott Long static void arcmsr_iop_message_read(struct AdapterControlBlock *acb) 134044f05562SScott Long { 134144f05562SScott Long switch (acb->adapter_type) { 134244f05562SScott Long case ACB_ADAPTER_TYPE_A: { 134344f05562SScott Long /* let IOP know data has been read */ 1344d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 134544f05562SScott Long } 134644f05562SScott Long break; 134744f05562SScott Long case ACB_ADAPTER_TYPE_B: { 1348b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 134944f05562SScott Long /* let IOP know data has been read */ 1350b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 135144f05562SScott Long } 135244f05562SScott Long break; 1353d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1354d74001adSXin LI /* let IOP know data has been read */ 1355d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK); 1356d74001adSXin LI } 13577a7bc959SXin LI break; 13587a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 13597a7bc959SXin LI /* let IOP know data has been read */ 13607a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ); 13617a7bc959SXin LI } 13627a7bc959SXin LI break; 1363a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 1364a1103e04SXin LI /* let IOP know data has been read */ 1365a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK; 1366a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 1367a1103e04SXin LI } 1368a1103e04SXin LI break; 136944f05562SScott Long } 137044f05562SScott Long } 137144f05562SScott Long /* 137244f05562SScott Long ************************************************************************** 137344f05562SScott Long ************************************************************************** 137444f05562SScott Long */ 137544f05562SScott Long static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) 137644f05562SScott Long { 137744f05562SScott Long switch (acb->adapter_type) { 137844f05562SScott Long case ACB_ADAPTER_TYPE_A: { 137944f05562SScott Long /* 138044f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 138144f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 138244f05562SScott Long */ 1383d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK); 138444f05562SScott Long } 138544f05562SScott Long break; 138644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 1387b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 138844f05562SScott Long /* 138944f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 139044f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 139144f05562SScott Long */ 1392b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_WRITE_OK); 1393d74001adSXin LI } 1394d74001adSXin LI break; 1395d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1396d74001adSXin LI /* 1397d74001adSXin LI ** push inbound doorbell tell iop, driver data write ok 1398d74001adSXin LI ** and wait reply on next hwinterrupt for next Qbuffer post 1399d74001adSXin LI */ 1400d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK); 140144f05562SScott Long } 140244f05562SScott Long break; 14037a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 140444f05562SScott Long /* 14057a7bc959SXin LI ** push inbound doorbell tell iop, driver data write ok 14067a7bc959SXin LI ** and wait reply on next hwinterrupt for next Qbuffer post 1407f1c579b1SScott Long */ 14087a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_IN_READY); 1409f1c579b1SScott Long } 14107a7bc959SXin LI break; 1411a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 1412a1103e04SXin LI /* 1413a1103e04SXin LI ** push inbound doorbell tell iop, driver data write ok 1414a1103e04SXin LI ** and wait reply on next hwinterrupt for next Qbuffer post 1415a1103e04SXin LI */ 1416a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_WRITE_OK; 1417a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 1418a1103e04SXin LI } 1419a1103e04SXin LI break; 1420ad6d6297SScott Long } 1421f1c579b1SScott Long } 1422f1c579b1SScott Long /* 1423f1c579b1SScott Long ************************************************************************ 1424f1c579b1SScott Long ************************************************************************ 1425f1c579b1SScott Long */ 142644f05562SScott Long static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb) 1427f1c579b1SScott Long { 1428ad6d6297SScott Long acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 142944f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 143044f05562SScott Long 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 143144f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 1432d74001adSXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n" 1433ad6d6297SScott Long , acb->pci_unit); 1434ad6d6297SScott Long } 1435f1c579b1SScott Long } 1436f1c579b1SScott Long /* 1437f1c579b1SScott Long ************************************************************************ 1438f1c579b1SScott Long ************************************************************************ 1439f1c579b1SScott Long */ 144044f05562SScott Long static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb) 144144f05562SScott Long { 1442b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 144344f05562SScott Long acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 1444b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_STOP_BGRB); 144544f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 1446d74001adSXin LI printf( "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" 144744f05562SScott Long , acb->pci_unit); 144844f05562SScott Long } 144944f05562SScott Long } 145044f05562SScott Long /* 145144f05562SScott Long ************************************************************************ 145244f05562SScott Long ************************************************************************ 145344f05562SScott Long */ 1454d74001adSXin LI static void arcmsr_stop_hbc_bgrb(struct AdapterControlBlock *acb) 1455d74001adSXin LI { 1456d74001adSXin LI acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 1457d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 1458d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 1459d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 1460d74001adSXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit); 1461d74001adSXin LI } 1462d74001adSXin LI } 1463d74001adSXin LI /* 1464d74001adSXin LI ************************************************************************ 1465d74001adSXin LI ************************************************************************ 1466d74001adSXin LI */ 14677a7bc959SXin LI static void arcmsr_stop_hbd_bgrb(struct AdapterControlBlock *acb) 14687a7bc959SXin LI { 14697a7bc959SXin LI acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 14707a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 14717a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 14727a7bc959SXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit); 14737a7bc959SXin LI } 14747a7bc959SXin LI } 14757a7bc959SXin LI /* 14767a7bc959SXin LI ************************************************************************ 14777a7bc959SXin LI ************************************************************************ 14787a7bc959SXin LI */ 1479a1103e04SXin LI static void arcmsr_stop_hbe_bgrb(struct AdapterControlBlock *acb) 1480a1103e04SXin LI { 1481a1103e04SXin LI acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 1482a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 1483a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 1484a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 1485a1103e04SXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) { 1486a1103e04SXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit); 1487a1103e04SXin LI } 1488a1103e04SXin LI } 1489a1103e04SXin LI /* 1490a1103e04SXin LI ************************************************************************ 1491a1103e04SXin LI ************************************************************************ 1492a1103e04SXin LI */ 149344f05562SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) 149444f05562SScott Long { 149544f05562SScott Long switch (acb->adapter_type) { 149644f05562SScott Long case ACB_ADAPTER_TYPE_A: { 149744f05562SScott Long arcmsr_stop_hba_bgrb(acb); 149844f05562SScott Long } 149944f05562SScott Long break; 150044f05562SScott Long case ACB_ADAPTER_TYPE_B: { 150144f05562SScott Long arcmsr_stop_hbb_bgrb(acb); 150244f05562SScott Long } 150344f05562SScott Long break; 1504d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1505d74001adSXin LI arcmsr_stop_hbc_bgrb(acb); 1506d74001adSXin LI } 1507d74001adSXin LI break; 15087a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 15097a7bc959SXin LI arcmsr_stop_hbd_bgrb(acb); 15107a7bc959SXin LI } 15117a7bc959SXin LI break; 1512a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 1513a1103e04SXin LI arcmsr_stop_hbe_bgrb(acb); 1514a1103e04SXin LI } 1515a1103e04SXin LI break; 151644f05562SScott Long } 151744f05562SScott Long } 151844f05562SScott Long /* 151944f05562SScott Long ************************************************************************ 152044f05562SScott Long ************************************************************************ 152144f05562SScott Long */ 1522ad6d6297SScott Long static void arcmsr_poll(struct cam_sim *psim) 1523f1c579b1SScott Long { 1524579ec1a5SScott Long struct AdapterControlBlock *acb; 15254e32649fSXin LI int mutex; 1526579ec1a5SScott Long 1527579ec1a5SScott Long acb = (struct AdapterControlBlock *)cam_sim_softc(psim); 15287a7bc959SXin LI mutex = mtx_owned(&acb->isr_lock); 15294e32649fSXin LI if( mutex == 0 ) 15307a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 1531579ec1a5SScott Long arcmsr_interrupt(acb); 15324e32649fSXin LI if( mutex == 0 ) 15337a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 15347a7bc959SXin LI } 15357a7bc959SXin LI /* 15367a7bc959SXin LI ************************************************************************** 15377a7bc959SXin LI ************************************************************************** 15387a7bc959SXin LI */ 153935689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data_D(struct AdapterControlBlock *acb, 154035689395SXin LI struct QBUFFER *prbuffer) { 154135689395SXin LI 154235689395SXin LI u_int8_t *pQbuffer; 15434d24901aSPedro F. Giffuni u_int8_t *buf1 = NULL; 15444d24901aSPedro F. Giffuni u_int32_t *iop_data, *buf2 = NULL; 154535689395SXin LI u_int32_t iop_len, data_len; 154635689395SXin LI 154735689395SXin LI iop_data = (u_int32_t *)prbuffer->data; 154835689395SXin LI iop_len = (u_int32_t)prbuffer->data_len; 154935689395SXin LI if ( iop_len > 0 ) 155035689395SXin LI { 155135689395SXin LI buf1 = malloc(128, M_DEVBUF, M_NOWAIT | M_ZERO); 155235689395SXin LI buf2 = (u_int32_t *)buf1; 155335689395SXin LI if( buf1 == NULL) 155435689395SXin LI return (0); 155535689395SXin LI data_len = iop_len; 155635689395SXin LI while(data_len >= 4) 155735689395SXin LI { 155835689395SXin LI *buf2++ = *iop_data++; 155935689395SXin LI data_len -= 4; 156035689395SXin LI } 156135689395SXin LI if(data_len) 156235689395SXin LI *buf2 = *iop_data; 156335689395SXin LI buf2 = (u_int32_t *)buf1; 156435689395SXin LI } 156535689395SXin LI while (iop_len > 0) { 156635689395SXin LI pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex]; 156735689395SXin LI *pQbuffer = *buf1; 156835689395SXin LI acb->rqbuf_lastindex++; 156935689395SXin LI /* if last, index number set it to 0 */ 157035689395SXin LI acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 157135689395SXin LI buf1++; 157235689395SXin LI iop_len--; 157335689395SXin LI } 157435689395SXin LI if(buf2) 157535689395SXin LI free( (u_int8_t *)buf2, M_DEVBUF); 157635689395SXin LI /* let IOP know data has been read */ 157735689395SXin LI arcmsr_iop_message_read(acb); 157835689395SXin LI return (1); 157935689395SXin LI } 158035689395SXin LI /* 158135689395SXin LI ************************************************************************** 158235689395SXin LI ************************************************************************** 158335689395SXin LI */ 158435689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, 15857a7bc959SXin LI struct QBUFFER *prbuffer) { 15867a7bc959SXin LI 15877a7bc959SXin LI u_int8_t *pQbuffer; 15887a7bc959SXin LI u_int8_t *iop_data; 15897a7bc959SXin LI u_int32_t iop_len; 15907a7bc959SXin LI 1591*fc5ef1caSXin LI if(acb->adapter_type >= ACB_ADAPTER_TYPE_B) { 159235689395SXin LI return(arcmsr_Read_iop_rqbuffer_data_D(acb, prbuffer)); 159335689395SXin LI } 15947a7bc959SXin LI iop_data = (u_int8_t *)prbuffer->data; 15957a7bc959SXin LI iop_len = (u_int32_t)prbuffer->data_len; 15967a7bc959SXin LI while (iop_len > 0) { 15977a7bc959SXin LI pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex]; 15987a7bc959SXin LI *pQbuffer = *iop_data; 15997a7bc959SXin LI acb->rqbuf_lastindex++; 16007a7bc959SXin LI /* if last, index number set it to 0 */ 16017a7bc959SXin LI acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 16027a7bc959SXin LI iop_data++; 16037a7bc959SXin LI iop_len--; 16047a7bc959SXin LI } 16057a7bc959SXin LI /* let IOP know data has been read */ 16067a7bc959SXin LI arcmsr_iop_message_read(acb); 160735689395SXin LI return (1); 1608f1c579b1SScott Long } 1609f1c579b1SScott Long /* 161044f05562SScott Long ************************************************************************** 161144f05562SScott Long ************************************************************************** 16125878cbecSScott Long */ 161344f05562SScott Long static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) 1614f1c579b1SScott Long { 161544f05562SScott Long struct QBUFFER *prbuffer; 16167a7bc959SXin LI int my_empty_len; 1617ad6d6297SScott Long 1618f1c579b1SScott Long /*check this iop data if overflow my rqbuffer*/ 16197a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 162044f05562SScott Long prbuffer = arcmsr_get_iop_rqbuffer(acb); 16217a7bc959SXin LI my_empty_len = (acb->rqbuf_lastindex - acb->rqbuf_firstindex - 1) & 16227a7bc959SXin LI (ARCMSR_MAX_QBUFFER-1); 16237a7bc959SXin LI if(my_empty_len >= prbuffer->data_len) { 162435689395SXin LI if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) 162535689395SXin LI acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 1626ad6d6297SScott Long } else { 1627ad6d6297SScott Long acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 1628f1c579b1SScott Long } 16297a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 16307a7bc959SXin LI } 16317a7bc959SXin LI /* 16327a7bc959SXin LI ********************************************************************** 16337a7bc959SXin LI ********************************************************************** 16347a7bc959SXin LI */ 163535689395SXin LI static void arcmsr_Write_data_2iop_wqbuffer_D(struct AdapterControlBlock *acb) 163635689395SXin LI { 163735689395SXin LI u_int8_t *pQbuffer; 163835689395SXin LI struct QBUFFER *pwbuffer; 16394d24901aSPedro F. Giffuni u_int8_t *buf1 = NULL; 16404d24901aSPedro F. Giffuni u_int32_t *iop_data, *buf2 = NULL; 164135689395SXin LI u_int32_t allxfer_len = 0, data_len; 164235689395SXin LI 164335689395SXin LI if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) { 164435689395SXin LI buf1 = malloc(128, M_DEVBUF, M_NOWAIT | M_ZERO); 164535689395SXin LI buf2 = (u_int32_t *)buf1; 164635689395SXin LI if( buf1 == NULL) 164735689395SXin LI return; 164835689395SXin LI 164935689395SXin LI acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 165035689395SXin LI pwbuffer = arcmsr_get_iop_wqbuffer(acb); 165135689395SXin LI iop_data = (u_int32_t *)pwbuffer->data; 165235689395SXin LI while((acb->wqbuf_firstindex != acb->wqbuf_lastindex) 165335689395SXin LI && (allxfer_len < 124)) { 165435689395SXin LI pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex]; 165535689395SXin LI *buf1 = *pQbuffer; 165635689395SXin LI acb->wqbuf_firstindex++; 165735689395SXin LI acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 165835689395SXin LI buf1++; 165935689395SXin LI allxfer_len++; 166035689395SXin LI } 166135689395SXin LI pwbuffer->data_len = allxfer_len; 166235689395SXin LI data_len = allxfer_len; 166335689395SXin LI buf1 = (u_int8_t *)buf2; 166435689395SXin LI while(data_len >= 4) 166535689395SXin LI { 166635689395SXin LI *iop_data++ = *buf2++; 166735689395SXin LI data_len -= 4; 166835689395SXin LI } 166935689395SXin LI if(data_len) 167035689395SXin LI *iop_data = *buf2; 167135689395SXin LI free( buf1, M_DEVBUF); 167235689395SXin LI arcmsr_iop_message_wrote(acb); 167335689395SXin LI } 167435689395SXin LI } 167535689395SXin LI /* 167635689395SXin LI ********************************************************************** 167735689395SXin LI ********************************************************************** 167835689395SXin LI */ 16797a7bc959SXin LI static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb) 16807a7bc959SXin LI { 16817a7bc959SXin LI u_int8_t *pQbuffer; 16827a7bc959SXin LI struct QBUFFER *pwbuffer; 16837a7bc959SXin LI u_int8_t *iop_data; 16847a7bc959SXin LI int32_t allxfer_len=0; 16857a7bc959SXin LI 1686*fc5ef1caSXin LI if(acb->adapter_type >= ACB_ADAPTER_TYPE_B) { 168735689395SXin LI arcmsr_Write_data_2iop_wqbuffer_D(acb); 168835689395SXin LI return; 168935689395SXin LI } 16907a7bc959SXin LI if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) { 16917a7bc959SXin LI acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 16927a7bc959SXin LI pwbuffer = arcmsr_get_iop_wqbuffer(acb); 16937a7bc959SXin LI iop_data = (u_int8_t *)pwbuffer->data; 16947a7bc959SXin LI while((acb->wqbuf_firstindex != acb->wqbuf_lastindex) 16957a7bc959SXin LI && (allxfer_len < 124)) { 16967a7bc959SXin LI pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex]; 16977a7bc959SXin LI *iop_data = *pQbuffer; 16987a7bc959SXin LI acb->wqbuf_firstindex++; 16997a7bc959SXin LI acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 17007a7bc959SXin LI iop_data++; 17017a7bc959SXin LI allxfer_len++; 17027a7bc959SXin LI } 17037a7bc959SXin LI pwbuffer->data_len = allxfer_len; 17047a7bc959SXin LI arcmsr_iop_message_wrote(acb); 17057a7bc959SXin LI } 1706f1c579b1SScott Long } 1707f1c579b1SScott Long /* 170844f05562SScott Long ************************************************************************** 170944f05562SScott Long ************************************************************************** 171044f05562SScott Long */ 171144f05562SScott Long static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) 171244f05562SScott Long { 17137a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 171444f05562SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READ; 171544f05562SScott Long /* 171644f05562SScott Long ***************************************************************** 171744f05562SScott Long ** check if there are any mail packages from user space program 171844f05562SScott Long ** in my post bag, now is the time to send them into Areca's firmware 171944f05562SScott Long ***************************************************************** 1720f1c579b1SScott Long */ 1721ad6d6297SScott Long if(acb->wqbuf_firstindex != acb->wqbuf_lastindex) { 17227a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 1723f1c579b1SScott Long } 1724ad6d6297SScott Long if(acb->wqbuf_firstindex == acb->wqbuf_lastindex) { 1725ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; 1726f1c579b1SScott Long } 17277a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1728f1c579b1SScott Long } 17297a7bc959SXin LI /* 17307a7bc959SXin LI ************************************************************************** 17317a7bc959SXin LI ************************************************************************** 17327a7bc959SXin LI */ 1733d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb) 1734d74001adSXin LI { 1735d74001adSXin LI /* 1736d74001adSXin LI if (ccb->ccb_h.status != CAM_REQ_CMP) 17377a7bc959SXin LI printf("arcmsr_rescanLun_cb: Rescan Target=%x, lun=%x," 17387a7bc959SXin LI "failure status=%x\n", ccb->ccb_h.target_id, 17397a7bc959SXin LI ccb->ccb_h.target_lun, ccb->ccb_h.status); 1740d74001adSXin LI else 1741d74001adSXin LI printf("arcmsr_rescanLun_cb: Rescan lun successfully!\n"); 1742d74001adSXin LI */ 1743d74001adSXin LI xpt_free_path(ccb->ccb_h.path); 1744d74001adSXin LI xpt_free_ccb(ccb); 1745d74001adSXin LI } 1746d74001adSXin LI 1747d74001adSXin LI static void arcmsr_rescan_lun(struct AdapterControlBlock *acb, int target, int lun) 1748d74001adSXin LI { 1749d74001adSXin LI struct cam_path *path; 1750d74001adSXin LI union ccb *ccb; 1751d74001adSXin LI 1752d74001adSXin LI if ((ccb = (union ccb *)xpt_alloc_ccb_nowait()) == NULL) 1753d74001adSXin LI return; 1754abfdbca9SXin LI if (xpt_create_path(&path, NULL, cam_sim_path(acb->psim), target, lun) != CAM_REQ_CMP) 1755d74001adSXin LI { 1756d74001adSXin LI xpt_free_ccb(ccb); 1757d74001adSXin LI return; 1758d74001adSXin LI } 1759d74001adSXin LI /* printf("arcmsr_rescan_lun: Rescan Target=%x, Lun=%x\n", target, lun); */ 1760d74001adSXin LI bzero(ccb, sizeof(union ccb)); 1761d74001adSXin LI xpt_setup_ccb(&ccb->ccb_h, path, 5); 1762d74001adSXin LI ccb->ccb_h.func_code = XPT_SCAN_LUN; 1763d74001adSXin LI ccb->ccb_h.cbfcnp = arcmsr_rescanLun_cb; 1764d74001adSXin LI ccb->crcn.flags = CAM_FLAG_NONE; 1765d74001adSXin LI xpt_action(ccb); 1766d74001adSXin LI } 1767d74001adSXin LI 1768d74001adSXin LI 1769d74001adSXin LI static void arcmsr_abort_dr_ccbs(struct AdapterControlBlock *acb, int target, int lun) 1770d74001adSXin LI { 1771d74001adSXin LI struct CommandControlBlock *srb; 1772d74001adSXin LI u_int32_t intmask_org; 1773d74001adSXin LI int i; 1774d74001adSXin LI 1775d74001adSXin LI /* disable all outbound interrupts */ 1776d74001adSXin LI intmask_org = arcmsr_disable_allintr(acb); 1777d74001adSXin LI for (i = 0; i < ARCMSR_MAX_FREESRB_NUM; i++) 1778d74001adSXin LI { 1779d74001adSXin LI srb = acb->psrb_pool[i]; 178022f2616bSXin LI if (srb->srb_state == ARCMSR_SRB_START) 1781d74001adSXin LI { 1782d74001adSXin LI if((target == srb->pccb->ccb_h.target_id) && (lun == srb->pccb->ccb_h.target_lun)) 1783d74001adSXin LI { 178422f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 1785d74001adSXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 1786d74001adSXin LI arcmsr_srb_complete(srb, 1); 178722f2616bSXin LI printf("arcmsr%d: abort scsi id %d lun %d srb=%p \n", acb->pci_unit, target, lun, srb); 1788d74001adSXin LI } 1789d74001adSXin LI } 1790d74001adSXin LI } 1791d74001adSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 1792d74001adSXin LI arcmsr_enable_allintr(acb, intmask_org); 1793d74001adSXin LI } 1794d74001adSXin LI /* 1795d74001adSXin LI ************************************************************************** 1796d74001adSXin LI ************************************************************************** 1797d74001adSXin LI */ 1798d74001adSXin LI static void arcmsr_dr_handle(struct AdapterControlBlock *acb) { 1799d74001adSXin LI u_int32_t devicemap; 1800d74001adSXin LI u_int32_t target, lun; 1801d74001adSXin LI u_int32_t deviceMapCurrent[4]={0}; 1802d74001adSXin LI u_int8_t *pDevMap; 1803d74001adSXin LI 1804d74001adSXin LI switch (acb->adapter_type) { 1805d74001adSXin LI case ACB_ADAPTER_TYPE_A: 1806d74001adSXin LI devicemap = offsetof(struct HBA_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1807d74001adSXin LI for (target = 0; target < 4; target++) 1808d74001adSXin LI { 1809d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1810d74001adSXin LI devicemap += 4; 1811d74001adSXin LI } 1812d74001adSXin LI break; 1813d74001adSXin LI 1814d74001adSXin LI case ACB_ADAPTER_TYPE_B: 1815d74001adSXin LI devicemap = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1816d74001adSXin LI for (target = 0; target < 4; target++) 1817d74001adSXin LI { 1818d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[1], acb->bhandle[1], devicemap); 1819d74001adSXin LI devicemap += 4; 1820d74001adSXin LI } 1821d74001adSXin LI break; 1822d74001adSXin LI 1823d74001adSXin LI case ACB_ADAPTER_TYPE_C: 1824d74001adSXin LI devicemap = offsetof(struct HBC_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1825d74001adSXin LI for (target = 0; target < 4; target++) 1826d74001adSXin LI { 1827d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1828d74001adSXin LI devicemap += 4; 1829d74001adSXin LI } 1830d74001adSXin LI break; 18317a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 18327a7bc959SXin LI devicemap = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 18337a7bc959SXin LI for (target = 0; target < 4; target++) 18347a7bc959SXin LI { 18357a7bc959SXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 18367a7bc959SXin LI devicemap += 4; 18377a7bc959SXin LI } 18387a7bc959SXin LI break; 1839a1103e04SXin LI case ACB_ADAPTER_TYPE_E: 1840a1103e04SXin LI devicemap = offsetof(struct HBE_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1841a1103e04SXin LI for (target = 0; target < 4; target++) 1842a1103e04SXin LI { 1843a1103e04SXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1844a1103e04SXin LI devicemap += 4; 1845a1103e04SXin LI } 1846a1103e04SXin LI break; 1847d74001adSXin LI } 1848dac36688SXin LI 1849d74001adSXin LI if(acb->acb_flags & ACB_F_BUS_HANG_ON) 1850d74001adSXin LI { 1851d74001adSXin LI acb->acb_flags &= ~ACB_F_BUS_HANG_ON; 1852d74001adSXin LI } 1853d74001adSXin LI /* 1854d74001adSXin LI ** adapter posted CONFIG message 1855d74001adSXin LI ** copy the new map, note if there are differences with the current map 1856d74001adSXin LI */ 1857d74001adSXin LI pDevMap = (u_int8_t *)&deviceMapCurrent[0]; 1858d74001adSXin LI for (target = 0; target < ARCMSR_MAX_TARGETID - 1; target++) 1859d74001adSXin LI { 1860d74001adSXin LI if (*pDevMap != acb->device_map[target]) 1861d74001adSXin LI { 1862d74001adSXin LI u_int8_t difference, bit_check; 1863d74001adSXin LI 1864d74001adSXin LI difference = *pDevMap ^ acb->device_map[target]; 1865d74001adSXin LI for(lun=0; lun < ARCMSR_MAX_TARGETLUN; lun++) 1866d74001adSXin LI { 1867d74001adSXin LI bit_check = (1 << lun); /*check bit from 0....31*/ 1868d74001adSXin LI if(difference & bit_check) 1869d74001adSXin LI { 1870d74001adSXin LI if(acb->device_map[target] & bit_check) 1871d74001adSXin LI {/* unit departed */ 1872d74001adSXin LI printf("arcmsr_dr_handle: Target=%x, lun=%x, GONE!!!\n",target,lun); 1873d74001adSXin LI arcmsr_abort_dr_ccbs(acb, target, lun); 1874d74001adSXin LI arcmsr_rescan_lun(acb, target, lun); 1875d74001adSXin LI acb->devstate[target][lun] = ARECA_RAID_GONE; 1876d74001adSXin LI } 1877d74001adSXin LI else 1878d74001adSXin LI {/* unit arrived */ 187922f2616bSXin LI printf("arcmsr_dr_handle: Target=%x, lun=%x, Plug-IN!!!\n",target,lun); 1880d74001adSXin LI arcmsr_rescan_lun(acb, target, lun); 1881d74001adSXin LI acb->devstate[target][lun] = ARECA_RAID_GOOD; 1882d74001adSXin LI } 1883d74001adSXin LI } 1884d74001adSXin LI } 1885d74001adSXin LI /* printf("arcmsr_dr_handle: acb->device_map[%x]=0x%x, deviceMapCurrent[%x]=%x\n",target,acb->device_map[target],target,*pDevMap); */ 1886d74001adSXin LI acb->device_map[target] = *pDevMap; 1887d74001adSXin LI } 1888d74001adSXin LI pDevMap++; 1889d74001adSXin LI } 1890d74001adSXin LI } 1891d74001adSXin LI /* 1892d74001adSXin LI ************************************************************************** 1893d74001adSXin LI ************************************************************************** 1894d74001adSXin LI */ 1895d74001adSXin LI static void arcmsr_hba_message_isr(struct AdapterControlBlock *acb) { 1896d74001adSXin LI u_int32_t outbound_message; 1897d74001adSXin LI 1898d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT); 1899d74001adSXin LI outbound_message = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[0]); 1900d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1901d74001adSXin LI arcmsr_dr_handle( acb ); 1902d74001adSXin LI } 1903d74001adSXin LI /* 1904d74001adSXin LI ************************************************************************** 1905d74001adSXin LI ************************************************************************** 1906d74001adSXin LI */ 1907d74001adSXin LI static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) { 1908d74001adSXin LI u_int32_t outbound_message; 1909b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 1910d74001adSXin LI 1911d74001adSXin LI /* clear interrupts */ 1912b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN); 1913d74001adSXin LI outbound_message = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0]); 1914d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1915d74001adSXin LI arcmsr_dr_handle( acb ); 1916d74001adSXin LI } 1917d74001adSXin LI /* 1918d74001adSXin LI ************************************************************************** 1919d74001adSXin LI ************************************************************************** 1920d74001adSXin LI */ 1921d74001adSXin LI static void arcmsr_hbc_message_isr(struct AdapterControlBlock *acb) { 1922d74001adSXin LI u_int32_t outbound_message; 1923d74001adSXin LI 1924d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR); 1925d74001adSXin LI outbound_message = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[0]); 1926d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1927d74001adSXin LI arcmsr_dr_handle( acb ); 1928d74001adSXin LI } 192944f05562SScott Long /* 193044f05562SScott Long ************************************************************************** 193144f05562SScott Long ************************************************************************** 193244f05562SScott Long */ 19337a7bc959SXin LI static void arcmsr_hbd_message_isr(struct AdapterControlBlock *acb) { 19347a7bc959SXin LI u_int32_t outbound_message; 19357a7bc959SXin LI 19367a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR); 19377a7bc959SXin LI outbound_message = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[0]); 19387a7bc959SXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 19397a7bc959SXin LI arcmsr_dr_handle( acb ); 19407a7bc959SXin LI } 19417a7bc959SXin LI /* 19427a7bc959SXin LI ************************************************************************** 19437a7bc959SXin LI ************************************************************************** 19447a7bc959SXin LI */ 1945a1103e04SXin LI static void arcmsr_hbe_message_isr(struct AdapterControlBlock *acb) { 1946a1103e04SXin LI u_int32_t outbound_message; 1947a1103e04SXin LI 1948a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); 1949a1103e04SXin LI outbound_message = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[0]); 1950a1103e04SXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1951a1103e04SXin LI arcmsr_dr_handle( acb ); 1952a1103e04SXin LI } 1953a1103e04SXin LI /* 1954a1103e04SXin LI ************************************************************************** 1955a1103e04SXin LI ************************************************************************** 1956a1103e04SXin LI */ 195744f05562SScott Long static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) 195844f05562SScott Long { 1959224a78aeSXin LI u_int32_t doorbell_status; 196044f05562SScott Long 196144f05562SScott Long /* 196244f05562SScott Long ******************************************************************* 196344f05562SScott Long ** Maybe here we need to check wrqbuffer_lock is lock or not 196444f05562SScott Long ** DOORBELL: din! don! 196544f05562SScott Long ** check if there are any mail need to pack from firmware 196644f05562SScott Long ******************************************************************* 196744f05562SScott Long */ 1968224a78aeSXin LI doorbell_status = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell); 1969224a78aeSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */ 1970224a78aeSXin LI if(doorbell_status & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { 197144f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 1972ad6d6297SScott Long } 1973224a78aeSXin LI if(doorbell_status & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { 197444f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 197544f05562SScott Long } 197644f05562SScott Long } 197744f05562SScott Long /* 197844f05562SScott Long ************************************************************************** 197944f05562SScott Long ************************************************************************** 198044f05562SScott Long */ 1981d74001adSXin LI static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb) 1982d74001adSXin LI { 1983224a78aeSXin LI u_int32_t doorbell_status; 1984d74001adSXin LI 1985d74001adSXin LI /* 1986d74001adSXin LI ******************************************************************* 1987d74001adSXin LI ** Maybe here we need to check wrqbuffer_lock is lock or not 1988d74001adSXin LI ** DOORBELL: din! don! 1989d74001adSXin LI ** check if there are any mail need to pack from firmware 1990d74001adSXin LI ******************************************************************* 1991d74001adSXin LI */ 1992224a78aeSXin LI doorbell_status = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); 1993224a78aeSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, doorbell_status); /* clear doorbell interrupt */ 1994224a78aeSXin LI if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) { 1995d74001adSXin LI arcmsr_iop2drv_data_wrote_handle(acb); 1996d74001adSXin LI } 1997224a78aeSXin LI if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) { 1998d74001adSXin LI arcmsr_iop2drv_data_read_handle(acb); 1999d74001adSXin LI } 2000224a78aeSXin LI if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { 2001d74001adSXin LI arcmsr_hbc_message_isr(acb); /* messenger of "driver to iop commands" */ 2002d74001adSXin LI } 2003d74001adSXin LI } 2004d74001adSXin LI /* 2005d74001adSXin LI ************************************************************************** 2006d74001adSXin LI ************************************************************************** 2007d74001adSXin LI */ 20087a7bc959SXin LI static void arcmsr_hbd_doorbell_isr(struct AdapterControlBlock *acb) 20097a7bc959SXin LI { 2010224a78aeSXin LI u_int32_t doorbell_status; 20117a7bc959SXin LI 20127a7bc959SXin LI /* 20137a7bc959SXin LI ******************************************************************* 20147a7bc959SXin LI ** Maybe here we need to check wrqbuffer_lock is lock or not 20157a7bc959SXin LI ** DOORBELL: din! don! 20167a7bc959SXin LI ** check if there are any mail need to pack from firmware 20177a7bc959SXin LI ******************************************************************* 20187a7bc959SXin LI */ 2019224a78aeSXin LI doorbell_status = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE; 2020224a78aeSXin LI if(doorbell_status) 2021224a78aeSXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */ 2022224a78aeSXin LI while( doorbell_status & ARCMSR_HBDMU_F0_DOORBELL_CAUSE ) { 2023224a78aeSXin LI if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_DATA_WRITE_OK) { 20247a7bc959SXin LI arcmsr_iop2drv_data_wrote_handle(acb); 20257a7bc959SXin LI } 2026224a78aeSXin LI if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_DATA_READ_OK) { 20277a7bc959SXin LI arcmsr_iop2drv_data_read_handle(acb); 20287a7bc959SXin LI } 2029224a78aeSXin LI if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) { 20307a7bc959SXin LI arcmsr_hbd_message_isr(acb); /* messenger of "driver to iop commands" */ 20317a7bc959SXin LI } 2032224a78aeSXin LI doorbell_status = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE; 2033224a78aeSXin LI if(doorbell_status) 2034224a78aeSXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */ 20357a7bc959SXin LI } 20367a7bc959SXin LI } 20377a7bc959SXin LI /* 20387a7bc959SXin LI ************************************************************************** 20397a7bc959SXin LI ************************************************************************** 20407a7bc959SXin LI */ 2041a1103e04SXin LI static void arcmsr_hbe_doorbell_isr(struct AdapterControlBlock *acb) 2042a1103e04SXin LI { 2043a1103e04SXin LI u_int32_t doorbell_status, in_doorbell; 2044a1103e04SXin LI 2045a1103e04SXin LI /* 2046a1103e04SXin LI ******************************************************************* 2047a1103e04SXin LI ** Maybe here we need to check wrqbuffer_lock is lock or not 2048a1103e04SXin LI ** DOORBELL: din! don! 2049a1103e04SXin LI ** check if there are any mail need to pack from firmware 2050a1103e04SXin LI ******************************************************************* 2051a1103e04SXin LI */ 2052a1103e04SXin LI in_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell); 2053a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /* clear doorbell interrupt */ 2054a1103e04SXin LI doorbell_status = in_doorbell ^ acb->in_doorbell; 2055a1103e04SXin LI if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_WRITE_OK) { 2056a1103e04SXin LI arcmsr_iop2drv_data_wrote_handle(acb); 2057a1103e04SXin LI } 2058a1103e04SXin LI if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_READ_OK) { 2059a1103e04SXin LI arcmsr_iop2drv_data_read_handle(acb); 2060a1103e04SXin LI } 2061a1103e04SXin LI if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) { 2062a1103e04SXin LI arcmsr_hbe_message_isr(acb); /* messenger of "driver to iop commands" */ 2063a1103e04SXin LI } 2064a1103e04SXin LI acb->in_doorbell = in_doorbell; 2065a1103e04SXin LI } 2066a1103e04SXin LI /* 2067a1103e04SXin LI ************************************************************************** 2068a1103e04SXin LI ************************************************************************** 2069a1103e04SXin LI */ 207044f05562SScott Long static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb) 207144f05562SScott Long { 207244f05562SScott Long u_int32_t flag_srb; 2073d74001adSXin LI u_int16_t error; 207444f05562SScott Long 2075f1c579b1SScott Long /* 2076f1c579b1SScott Long ***************************************************************************** 2077f1c579b1SScott Long ** areca cdb command done 2078f1c579b1SScott Long ***************************************************************************** 2079f1c579b1SScott Long */ 208044f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 208144f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 208244f05562SScott Long while((flag_srb = CHIP_REG_READ32(HBA_MessageUnit, 208344f05562SScott Long 0, outbound_queueport)) != 0xFFFFFFFF) { 2084f1c579b1SScott Long /* check if command done with no error*/ 2085d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0) ? TRUE : FALSE; 2086d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 208744f05562SScott Long } /*drain reply FIFO*/ 2088f1c579b1SScott Long } 208944f05562SScott Long /* 209044f05562SScott Long ************************************************************************** 209144f05562SScott Long ************************************************************************** 209244f05562SScott Long */ 209344f05562SScott Long static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) 209444f05562SScott Long { 209544f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 209644f05562SScott Long u_int32_t flag_srb; 209744f05562SScott Long int index; 2098d74001adSXin LI u_int16_t error; 209944f05562SScott Long 210044f05562SScott Long /* 210144f05562SScott Long ***************************************************************************** 210244f05562SScott Long ** areca cdb command done 210344f05562SScott Long ***************************************************************************** 210444f05562SScott Long */ 210544f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 210644f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 210744f05562SScott Long index = phbbmu->doneq_index; 210844f05562SScott Long while((flag_srb = phbbmu->done_qbuffer[index]) != 0) { 210944f05562SScott Long phbbmu->done_qbuffer[index] = 0; 211044f05562SScott Long index++; 211144f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 211244f05562SScott Long phbbmu->doneq_index = index; 211344f05562SScott Long /* check if command done with no error*/ 2114d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 2115d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 2116d74001adSXin LI } /*drain reply FIFO*/ 2117d74001adSXin LI } 2118d74001adSXin LI /* 2119d74001adSXin LI ************************************************************************** 2120d74001adSXin LI ************************************************************************** 2121d74001adSXin LI */ 2122d74001adSXin LI static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb) 2123d74001adSXin LI { 2124d74001adSXin LI u_int32_t flag_srb,throttling = 0; 2125d74001adSXin LI u_int16_t error; 2126d74001adSXin LI 2127d74001adSXin LI /* 2128d74001adSXin LI ***************************************************************************** 2129d74001adSXin LI ** areca cdb command done 2130d74001adSXin LI ***************************************************************************** 2131d74001adSXin LI */ 2132d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 2133224a78aeSXin LI do { 2134d74001adSXin LI flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 2135b23a1998SXin LI if (flag_srb == 0xFFFFFFFF) 2136b23a1998SXin LI break; 2137d74001adSXin LI /* check if command done with no error*/ 2138d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; 2139d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 2140abfdbca9SXin LI throttling++; 2141d74001adSXin LI if(throttling == ARCMSR_HBC_ISR_THROTTLING_LEVEL) { 2142d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING); 2143abfdbca9SXin LI throttling = 0; 2144d74001adSXin LI } 2145224a78aeSXin LI } while(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR); 2146f1c579b1SScott Long } 214744f05562SScott Long /* 214844f05562SScott Long ********************************************************************** 21497a7bc959SXin LI ** 21507a7bc959SXin LI ********************************************************************** 21517a7bc959SXin LI */ 21527a7bc959SXin LI static uint16_t arcmsr_get_doneq_index(struct HBD_MessageUnit0 *phbdmu) 21537a7bc959SXin LI { 21547a7bc959SXin LI uint16_t doneq_index, index_stripped; 21557a7bc959SXin LI 21567a7bc959SXin LI doneq_index = phbdmu->doneq_index; 21577a7bc959SXin LI if (doneq_index & 0x4000) { 21587a7bc959SXin LI index_stripped = doneq_index & 0xFF; 21597a7bc959SXin LI index_stripped += 1; 21607a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 21617a7bc959SXin LI phbdmu->doneq_index = index_stripped ? 21627a7bc959SXin LI (index_stripped | 0x4000) : index_stripped; 21637a7bc959SXin LI } else { 21647a7bc959SXin LI index_stripped = doneq_index; 21657a7bc959SXin LI index_stripped += 1; 21667a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 21677a7bc959SXin LI phbdmu->doneq_index = index_stripped ? 21687a7bc959SXin LI index_stripped : (index_stripped | 0x4000); 21697a7bc959SXin LI } 21707a7bc959SXin LI return (phbdmu->doneq_index); 21717a7bc959SXin LI } 21727a7bc959SXin LI /* 21737a7bc959SXin LI ************************************************************************** 21747a7bc959SXin LI ************************************************************************** 21757a7bc959SXin LI */ 21767a7bc959SXin LI static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb) 21777a7bc959SXin LI { 21787a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 21797a7bc959SXin LI u_int32_t outbound_write_pointer; 21807a7bc959SXin LI u_int32_t addressLow; 21817a7bc959SXin LI uint16_t doneq_index; 21827a7bc959SXin LI u_int16_t error; 21837a7bc959SXin LI /* 21847a7bc959SXin LI ***************************************************************************** 21857a7bc959SXin LI ** areca cdb command done 21867a7bc959SXin LI ***************************************************************************** 21877a7bc959SXin LI */ 21887a7bc959SXin LI if((CHIP_REG_READ32(HBD_MessageUnit, 0, outboundlist_interrupt_cause) & 21897a7bc959SXin LI ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT) == 0) 21907a7bc959SXin LI return; 21917a7bc959SXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 21927a7bc959SXin LI BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 21937a7bc959SXin LI outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow; 21947a7bc959SXin LI doneq_index = phbdmu->doneq_index; 21957a7bc959SXin LI while ((doneq_index & 0xFF) != (outbound_write_pointer & 0xFF)) { 21967a7bc959SXin LI doneq_index = arcmsr_get_doneq_index(phbdmu); 21977a7bc959SXin LI addressLow = phbdmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow; 21987a7bc959SXin LI error = (addressLow & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 21997a7bc959SXin LI arcmsr_drain_donequeue(acb, addressLow, error); /*Check if command done with no error */ 22007a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_read_pointer, doneq_index); 22017a7bc959SXin LI outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow; 22027a7bc959SXin LI } 22037a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_interrupt_cause, ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT_CLEAR); 22047a7bc959SXin LI CHIP_REG_READ32(HBD_MessageUnit, 0, outboundlist_interrupt_cause); /*Dummy ioread32 to force pci flush */ 22057a7bc959SXin LI } 22067a7bc959SXin LI /* 2207a1103e04SXin LI ************************************************************************** 2208a1103e04SXin LI ************************************************************************** 2209a1103e04SXin LI */ 2210a1103e04SXin LI static void arcmsr_hbe_postqueue_isr(struct AdapterControlBlock *acb) 2211a1103e04SXin LI { 2212a1103e04SXin LI u_int16_t error; 2213a1103e04SXin LI uint32_t doneq_index; 2214a1103e04SXin LI uint16_t cmdSMID; 2215a1103e04SXin LI 2216a1103e04SXin LI /* 2217a1103e04SXin LI ***************************************************************************** 2218a1103e04SXin LI ** areca cdb command done 2219a1103e04SXin LI ***************************************************************************** 2220a1103e04SXin LI */ 2221a1103e04SXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2222a1103e04SXin LI doneq_index = acb->doneq_index; 2223a1103e04SXin LI while ((CHIP_REG_READ32(HBE_MessageUnit, 0, reply_post_producer_index) & 0xFFFF) != doneq_index) { 2224a1103e04SXin LI cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID; 2225a1103e04SXin LI error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 2226a1103e04SXin LI arcmsr_drain_donequeue(acb, (u_int32_t)cmdSMID, error); 2227a1103e04SXin LI doneq_index++; 2228a1103e04SXin LI if (doneq_index >= acb->completionQ_entry) 2229a1103e04SXin LI doneq_index = 0; 2230a1103e04SXin LI } 2231a1103e04SXin LI acb->doneq_index = doneq_index; 2232a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, reply_post_consumer_index, doneq_index); 2233a1103e04SXin LI } 2234a1103e04SXin LI /* 22357a7bc959SXin LI ********************************************************************** 223644f05562SScott Long ********************************************************************** 223744f05562SScott Long */ 223844f05562SScott Long static void arcmsr_handle_hba_isr( struct AdapterControlBlock *acb) 223944f05562SScott Long { 2240dac36688SXin LI u_int32_t outbound_intStatus; 224144f05562SScott Long /* 224244f05562SScott Long ********************************************* 224344f05562SScott Long ** check outbound intstatus 224444f05562SScott Long ********************************************* 224544f05562SScott Long */ 2246dac36688SXin LI outbound_intStatus = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 2247dac36688SXin LI if(!outbound_intStatus) { 224844f05562SScott Long /*it must be share irq*/ 224944f05562SScott Long return; 2250f1c579b1SScott Long } 2251dac36688SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intStatus); /*clear interrupt*/ 225244f05562SScott Long /* MU doorbell interrupts*/ 2253dac36688SXin LI if(outbound_intStatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) { 225444f05562SScott Long arcmsr_hba_doorbell_isr(acb); 2255f1c579b1SScott Long } 225644f05562SScott Long /* MU post queue interrupts*/ 2257dac36688SXin LI if(outbound_intStatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { 225844f05562SScott Long arcmsr_hba_postqueue_isr(acb); 225944f05562SScott Long } 2260dac36688SXin LI if(outbound_intStatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { 2261d74001adSXin LI arcmsr_hba_message_isr(acb); 2262d74001adSXin LI } 226344f05562SScott Long } 226444f05562SScott Long /* 226544f05562SScott Long ********************************************************************** 226644f05562SScott Long ********************************************************************** 226744f05562SScott Long */ 226844f05562SScott Long static void arcmsr_handle_hbb_isr( struct AdapterControlBlock *acb) 226944f05562SScott Long { 227044f05562SScott Long u_int32_t outbound_doorbell; 2271b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 227244f05562SScott Long /* 227344f05562SScott Long ********************************************* 227444f05562SScott Long ** check outbound intstatus 227544f05562SScott Long ********************************************* 227644f05562SScott Long */ 2277b23a1998SXin LI outbound_doorbell = READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & acb->outbound_int_enable; 227844f05562SScott Long if(!outbound_doorbell) { 227944f05562SScott Long /*it must be share irq*/ 228044f05562SScott Long return; 228144f05562SScott Long } 2282b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ~outbound_doorbell); /* clear doorbell interrupt */ 2283b23a1998SXin LI READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell); 2284b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 228544f05562SScott Long /* MU ioctl transfer doorbell interrupts*/ 228644f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { 228744f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 228844f05562SScott Long } 228944f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) { 229044f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 229144f05562SScott Long } 229244f05562SScott Long /* MU post queue interrupts*/ 229344f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) { 229444f05562SScott Long arcmsr_hbb_postqueue_isr(acb); 229544f05562SScott Long } 2296d74001adSXin LI if(outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { 2297d74001adSXin LI arcmsr_hbb_message_isr(acb); 2298d74001adSXin LI } 2299d74001adSXin LI } 2300d74001adSXin LI /* 2301d74001adSXin LI ********************************************************************** 2302d74001adSXin LI ********************************************************************** 2303d74001adSXin LI */ 2304d74001adSXin LI static void arcmsr_handle_hbc_isr( struct AdapterControlBlock *acb) 2305d74001adSXin LI { 2306d74001adSXin LI u_int32_t host_interrupt_status; 2307d74001adSXin LI /* 2308d74001adSXin LI ********************************************* 2309d74001adSXin LI ** check outbound intstatus 2310d74001adSXin LI ********************************************* 2311d74001adSXin LI */ 2312224a78aeSXin LI host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & 2313224a78aeSXin LI (ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR | 2314224a78aeSXin LI ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR); 2315d74001adSXin LI if(!host_interrupt_status) { 2316d74001adSXin LI /*it must be share irq*/ 2317d74001adSXin LI return; 2318d74001adSXin LI } 2319224a78aeSXin LI do { 2320d74001adSXin LI /* MU doorbell interrupts*/ 2321d74001adSXin LI if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) { 2322d74001adSXin LI arcmsr_hbc_doorbell_isr(acb); 2323d74001adSXin LI } 2324d74001adSXin LI /* MU post queue interrupts*/ 2325d74001adSXin LI if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) { 2326d74001adSXin LI arcmsr_hbc_postqueue_isr(acb); 2327d74001adSXin LI } 2328224a78aeSXin LI host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status); 2329224a78aeSXin LI } while (host_interrupt_status & (ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR)); 233044f05562SScott Long } 233144f05562SScott Long /* 23327a7bc959SXin LI ********************************************************************** 23337a7bc959SXin LI ********************************************************************** 23347a7bc959SXin LI */ 23357a7bc959SXin LI static void arcmsr_handle_hbd_isr( struct AdapterControlBlock *acb) 23367a7bc959SXin LI { 23377a7bc959SXin LI u_int32_t host_interrupt_status; 23387a7bc959SXin LI u_int32_t intmask_org; 23397a7bc959SXin LI /* 23407a7bc959SXin LI ********************************************* 23417a7bc959SXin LI ** check outbound intstatus 23427a7bc959SXin LI ********************************************* 23437a7bc959SXin LI */ 23447a7bc959SXin LI host_interrupt_status = CHIP_REG_READ32(HBD_MessageUnit, 0, host_int_status) & acb->outbound_int_enable; 23457a7bc959SXin LI if(!(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_INT)) { 23467a7bc959SXin LI /*it must be share irq*/ 23477a7bc959SXin LI return; 23487a7bc959SXin LI } 23497a7bc959SXin LI /* disable outbound interrupt */ 23507a7bc959SXin LI intmask_org = CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable) ; /* disable outbound message0 int */ 23517a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, ARCMSR_HBDMU_ALL_INT_DISABLE); 23527a7bc959SXin LI /* MU doorbell interrupts*/ 23537a7bc959SXin LI if(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_DOORBELL_INT) { 23547a7bc959SXin LI arcmsr_hbd_doorbell_isr(acb); 23557a7bc959SXin LI } 23567a7bc959SXin LI /* MU post queue interrupts*/ 23577a7bc959SXin LI if(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_POSTQUEUE_INT) { 23587a7bc959SXin LI arcmsr_hbd_postqueue_isr(acb); 23597a7bc959SXin LI } 23607a7bc959SXin LI /* enable all outbound interrupt */ 23617a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, intmask_org | ARCMSR_HBDMU_ALL_INT_ENABLE); 23627a7bc959SXin LI // CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable); 23637a7bc959SXin LI } 23647a7bc959SXin LI /* 2365a1103e04SXin LI ********************************************************************** 2366a1103e04SXin LI ********************************************************************** 2367a1103e04SXin LI */ 2368a1103e04SXin LI static void arcmsr_handle_hbe_isr( struct AdapterControlBlock *acb) 2369a1103e04SXin LI { 2370a1103e04SXin LI u_int32_t host_interrupt_status; 2371a1103e04SXin LI /* 2372a1103e04SXin LI ********************************************* 2373a1103e04SXin LI ** check outbound intstatus 2374a1103e04SXin LI ********************************************* 2375a1103e04SXin LI */ 2376a1103e04SXin LI host_interrupt_status = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_status) & 2377a1103e04SXin LI (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR | 2378a1103e04SXin LI ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR); 2379a1103e04SXin LI if(!host_interrupt_status) { 2380a1103e04SXin LI /*it must be share irq*/ 2381a1103e04SXin LI return; 2382a1103e04SXin LI } 2383a1103e04SXin LI do { 2384a1103e04SXin LI /* MU doorbell interrupts*/ 2385a1103e04SXin LI if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR) { 2386a1103e04SXin LI arcmsr_hbe_doorbell_isr(acb); 2387a1103e04SXin LI } 2388a1103e04SXin LI /* MU post queue interrupts*/ 2389a1103e04SXin LI if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR) { 2390a1103e04SXin LI arcmsr_hbe_postqueue_isr(acb); 2391a1103e04SXin LI } 2392a1103e04SXin LI host_interrupt_status = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_status); 2393a1103e04SXin LI } while (host_interrupt_status & (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR)); 2394a1103e04SXin LI } 2395a1103e04SXin LI /* 239644f05562SScott Long ****************************************************************************** 239744f05562SScott Long ****************************************************************************** 239844f05562SScott Long */ 239944f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb) 240044f05562SScott Long { 240144f05562SScott Long switch (acb->adapter_type) { 240244f05562SScott Long case ACB_ADAPTER_TYPE_A: 240344f05562SScott Long arcmsr_handle_hba_isr(acb); 2404f1c579b1SScott Long break; 240544f05562SScott Long case ACB_ADAPTER_TYPE_B: 240644f05562SScott Long arcmsr_handle_hbb_isr(acb); 2407f1c579b1SScott Long break; 2408d74001adSXin LI case ACB_ADAPTER_TYPE_C: 2409d74001adSXin LI arcmsr_handle_hbc_isr(acb); 2410d74001adSXin LI break; 24117a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 24127a7bc959SXin LI arcmsr_handle_hbd_isr(acb); 24137a7bc959SXin LI break; 2414a1103e04SXin LI case ACB_ADAPTER_TYPE_E: 2415a1103e04SXin LI arcmsr_handle_hbe_isr(acb); 2416a1103e04SXin LI break; 2417f1c579b1SScott Long default: 241844f05562SScott Long printf("arcmsr%d: interrupt service," 241910d66948SKevin Lo " unknown adapter type =%d\n", acb->pci_unit, acb->adapter_type); 2420f1c579b1SScott Long break; 2421f1c579b1SScott Long } 2422f1c579b1SScott Long } 2423f1c579b1SScott Long /* 2424d74001adSXin LI ********************************************************************** 2425d74001adSXin LI ********************************************************************** 2426d74001adSXin LI */ 2427d74001adSXin LI static void arcmsr_intr_handler(void *arg) 2428d74001adSXin LI { 2429d74001adSXin LI struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg; 2430d74001adSXin LI 24317a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 2432d74001adSXin LI arcmsr_interrupt(acb); 24337a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 2434d74001adSXin LI } 2435d74001adSXin LI /* 2436d74001adSXin LI ****************************************************************************** 2437d74001adSXin LI ****************************************************************************** 2438d74001adSXin LI */ 2439d74001adSXin LI static void arcmsr_polling_devmap(void *arg) 2440d74001adSXin LI { 2441d74001adSXin LI struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg; 2442d74001adSXin LI switch (acb->adapter_type) { 2443d74001adSXin LI case ACB_ADAPTER_TYPE_A: 2444dac36688SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 2445d74001adSXin LI break; 2446d74001adSXin LI 2447b23a1998SXin LI case ACB_ADAPTER_TYPE_B: { 2448b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 2449b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG); 2450b23a1998SXin LI } 2451d74001adSXin LI break; 2452d74001adSXin LI 2453d74001adSXin LI case ACB_ADAPTER_TYPE_C: 2454d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 2455d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 2456d74001adSXin LI break; 24577a7bc959SXin LI 24587a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 24597a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 24607a7bc959SXin LI break; 2461a1103e04SXin LI 2462a1103e04SXin LI case ACB_ADAPTER_TYPE_E: 2463a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 2464a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 2465a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 2466a1103e04SXin LI break; 2467d74001adSXin LI } 2468d74001adSXin LI 2469d74001adSXin LI if((acb->acb_flags & ACB_F_SCSISTOPADAPTER) == 0) 2470d74001adSXin LI { 2471d74001adSXin LI callout_reset(&acb->devmap_callout, 5 * hz, arcmsr_polling_devmap, acb); /* polling per 5 seconds */ 2472d74001adSXin LI } 2473d74001adSXin LI } 2474d74001adSXin LI 2475d74001adSXin LI /* 2476ad6d6297SScott Long ******************************************************************************* 2477ad6d6297SScott Long ** 2478ad6d6297SScott Long ******************************************************************************* 2479ad6d6297SScott Long */ 2480ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb) 2481ad6d6297SScott Long { 2482d74001adSXin LI u_int32_t intmask_org; 2483d74001adSXin LI 2484ad6d6297SScott Long if(acb != NULL) { 2485ad6d6297SScott Long /* stop adapter background rebuild */ 2486ad6d6297SScott Long if(acb->acb_flags & ACB_F_MSG_START_BGRB) { 2487d74001adSXin LI intmask_org = arcmsr_disable_allintr(acb); 2488ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 2489ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2490d74001adSXin LI arcmsr_enable_allintr(acb, intmask_org); 2491ad6d6297SScott Long } 2492ad6d6297SScott Long } 2493ad6d6297SScott Long } 2494ad6d6297SScott Long /* 2495f1c579b1SScott Long *********************************************************************** 2496f1c579b1SScott Long ** 2497f1c579b1SScott Long ************************************************************************ 2498f1c579b1SScott Long */ 2499*fc5ef1caSXin LI static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg) 2500f1c579b1SScott Long { 2501ad6d6297SScott Long struct CMD_MESSAGE_FIELD *pcmdmessagefld; 2502ad6d6297SScott Long u_int32_t retvalue = EINVAL; 2503f1c579b1SScott Long 2504ad6d6297SScott Long pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) arg; 2505ad6d6297SScott Long if(memcmp(pcmdmessagefld->cmdmessage.Signature, "ARCMSR", 6)!=0) { 2506ad6d6297SScott Long return retvalue; 2507f1c579b1SScott Long } 2508ad6d6297SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2509ad6d6297SScott Long switch(ioctl_cmd) { 2510ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 2511ad6d6297SScott Long u_int8_t *pQbuffer; 2512ad6d6297SScott Long u_int8_t *ptmpQbuffer = pcmdmessagefld->messagedatabuffer; 2513ad6d6297SScott Long u_int32_t allxfer_len=0; 2514f1c579b1SScott Long 251544f05562SScott Long while((acb->rqbuf_firstindex != acb->rqbuf_lastindex) 251644f05562SScott Long && (allxfer_len < 1031)) { 2517f1c579b1SScott Long /*copy READ QBUFFER to srb*/ 2518ad6d6297SScott Long pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; 25197a7bc959SXin LI *ptmpQbuffer = *pQbuffer; 2520ad6d6297SScott Long acb->rqbuf_firstindex++; 2521ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 2522ad6d6297SScott Long /*if last index number set it to 0 */ 2523f1c579b1SScott Long ptmpQbuffer++; 2524f1c579b1SScott Long allxfer_len++; 2525f1c579b1SScott Long } 2526ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 252744f05562SScott Long struct QBUFFER *prbuffer; 2528f1c579b1SScott Long 2529ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 253044f05562SScott Long prbuffer = arcmsr_get_iop_rqbuffer(acb); 253135689395SXin LI if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) 253235689395SXin LI acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 2533f1c579b1SScott Long } 2534ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length = allxfer_len; 2535ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2536ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2537f1c579b1SScott Long } 2538f1c579b1SScott Long break; 2539ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 2540ad6d6297SScott Long u_int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 2541ad6d6297SScott Long u_int8_t *pQbuffer; 2542ad6d6297SScott Long u_int8_t *ptmpuserbuffer = pcmdmessagefld->messagedatabuffer; 2543f1c579b1SScott Long 2544ad6d6297SScott Long user_len = pcmdmessagefld->cmdmessage.Length; 2545f1c579b1SScott Long /*check if data xfer length of this request will overflow my array qbuffer */ 2546ad6d6297SScott Long wqbuf_lastindex = acb->wqbuf_lastindex; 2547ad6d6297SScott Long wqbuf_firstindex = acb->wqbuf_firstindex; 2548ad6d6297SScott Long if(wqbuf_lastindex != wqbuf_firstindex) { 25497a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2550ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR; 2551ad6d6297SScott Long } else { 25527a7bc959SXin LI my_empty_len = (wqbuf_firstindex - wqbuf_lastindex - 1) & 25537a7bc959SXin LI (ARCMSR_MAX_QBUFFER - 1); 2554ad6d6297SScott Long if(my_empty_len >= user_len) { 2555ad6d6297SScott Long while(user_len > 0) { 2556f1c579b1SScott Long /*copy srb data to wqbuffer*/ 2557ad6d6297SScott Long pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; 25587a7bc959SXin LI *pQbuffer = *ptmpuserbuffer; 2559ad6d6297SScott Long acb->wqbuf_lastindex++; 2560ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 2561ad6d6297SScott Long /*if last index number set it to 0 */ 2562f1c579b1SScott Long ptmpuserbuffer++; 2563f1c579b1SScott Long user_len--; 2564f1c579b1SScott Long } 2565f1c579b1SScott Long /*post fist Qbuffer*/ 2566ad6d6297SScott Long if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 2567ad6d6297SScott Long acb->acb_flags &= ~ACB_F_MESSAGE_WQBUFFER_CLEARED; 25687a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2569f1c579b1SScott Long } 2570ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2571ad6d6297SScott Long } else { 2572ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR; 2573f1c579b1SScott Long } 2574f1c579b1SScott Long } 2575ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2576f1c579b1SScott Long } 2577f1c579b1SScott Long break; 2578ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 2579ad6d6297SScott Long u_int8_t *pQbuffer = acb->rqbuffer; 2580ad6d6297SScott Long 2581ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2582ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 258344f05562SScott Long arcmsr_iop_message_read(acb); 258444f05562SScott Long /*signature, let IOP know data has been readed */ 2585f1c579b1SScott Long } 2586ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 2587ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2588ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2589f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2590ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2591ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2592f1c579b1SScott Long } 2593f1c579b1SScott Long break; 2594ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: 2595f1c579b1SScott Long { 2596ad6d6297SScott Long u_int8_t *pQbuffer = acb->wqbuffer; 2597f1c579b1SScott Long 2598ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2599ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 260044f05562SScott Long arcmsr_iop_message_read(acb); 260144f05562SScott Long /*signature, let IOP know data has been readed */ 2602f1c579b1SScott Long } 260344f05562SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ); 2604ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2605ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2606f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2607ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2608ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2609f1c579b1SScott Long } 2610f1c579b1SScott Long break; 2611ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 2612ad6d6297SScott Long u_int8_t *pQbuffer; 2613f1c579b1SScott Long 2614ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2615ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 261644f05562SScott Long arcmsr_iop_message_read(acb); 261744f05562SScott Long /*signature, let IOP know data has been readed */ 2618f1c579b1SScott Long } 2619ad6d6297SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED 2620ad6d6297SScott Long |ACB_F_MESSAGE_RQBUFFER_CLEARED 262144f05562SScott Long |ACB_F_MESSAGE_WQBUFFER_READ); 2622ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2623ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2624ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2625ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2626ad6d6297SScott Long pQbuffer = acb->rqbuffer; 2627ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 2628ad6d6297SScott Long pQbuffer = acb->wqbuffer; 2629ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 2630ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2631ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2632f1c579b1SScott Long } 2633f1c579b1SScott Long break; 2634ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 2635ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; 2636ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2637f1c579b1SScott Long } 2638f1c579b1SScott Long break; 2639ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 2640ad6d6297SScott Long u_int8_t *hello_string = "Hello! I am ARCMSR"; 2641ad6d6297SScott Long u_int8_t *puserbuffer = (u_int8_t *)pcmdmessagefld->messagedatabuffer; 2642f1c579b1SScott Long 2643ad6d6297SScott Long if(memcpy(puserbuffer, hello_string, (int16_t)strlen(hello_string))) { 2644ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR; 2645ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2646f1c579b1SScott Long return ENOIOCTL; 2647f1c579b1SScott Long } 2648ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2649ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2650ad6d6297SScott Long } 2651ad6d6297SScott Long break; 2652ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: { 2653ad6d6297SScott Long arcmsr_iop_parking(acb); 2654ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2655ad6d6297SScott Long } 2656ad6d6297SScott Long break; 2657ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: { 2658ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2659ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2660f1c579b1SScott Long } 2661f1c579b1SScott Long break; 2662f1c579b1SScott Long } 2663ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2664dac36688SXin LI return (retvalue); 2665f1c579b1SScott Long } 2666f1c579b1SScott Long /* 2667f1c579b1SScott Long ************************************************************************** 2668f1c579b1SScott Long ************************************************************************** 2669f1c579b1SScott Long */ 267022f2616bSXin LI static void arcmsr_free_srb(struct CommandControlBlock *srb) 267122f2616bSXin LI { 267222f2616bSXin LI struct AdapterControlBlock *acb; 267322f2616bSXin LI 267422f2616bSXin LI acb = srb->acb; 26757a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->srb_lock); 267622f2616bSXin LI srb->srb_state = ARCMSR_SRB_DONE; 267722f2616bSXin LI srb->srb_flags = 0; 267822f2616bSXin LI acb->srbworkingQ[acb->workingsrb_doneindex] = srb; 267922f2616bSXin LI acb->workingsrb_doneindex++; 268022f2616bSXin LI acb->workingsrb_doneindex %= ARCMSR_MAX_FREESRB_NUM; 26817a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->srb_lock); 268222f2616bSXin LI } 268322f2616bSXin LI /* 268422f2616bSXin LI ************************************************************************** 268522f2616bSXin LI ************************************************************************** 268622f2616bSXin LI */ 2687*fc5ef1caSXin LI static struct CommandControlBlock *arcmsr_get_freesrb(struct AdapterControlBlock *acb) 2688f1c579b1SScott Long { 2689ad6d6297SScott Long struct CommandControlBlock *srb = NULL; 2690ad6d6297SScott Long u_int32_t workingsrb_startindex, workingsrb_doneindex; 2691f1c579b1SScott Long 26927a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->srb_lock); 2693ad6d6297SScott Long workingsrb_doneindex = acb->workingsrb_doneindex; 2694ad6d6297SScott Long workingsrb_startindex = acb->workingsrb_startindex; 2695ad6d6297SScott Long srb = acb->srbworkingQ[workingsrb_startindex]; 2696ad6d6297SScott Long workingsrb_startindex++; 2697ad6d6297SScott Long workingsrb_startindex %= ARCMSR_MAX_FREESRB_NUM; 2698ad6d6297SScott Long if(workingsrb_doneindex != workingsrb_startindex) { 2699ad6d6297SScott Long acb->workingsrb_startindex = workingsrb_startindex; 2700ad6d6297SScott Long } else { 2701ad6d6297SScott Long srb = NULL; 2702ad6d6297SScott Long } 27037a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->srb_lock); 2704ad6d6297SScott Long return(srb); 2705ad6d6297SScott Long } 2706ad6d6297SScott Long /* 2707ad6d6297SScott Long ************************************************************************** 2708ad6d6297SScott Long ************************************************************************** 2709ad6d6297SScott Long */ 2710ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *pccb) 2711ad6d6297SScott Long { 2712ad6d6297SScott Long struct CMD_MESSAGE_FIELD *pcmdmessagefld; 2713ad6d6297SScott Long int retvalue = 0, transfer_len = 0; 2714ad6d6297SScott Long char *buffer; 27154aa947cbSWarner Losh uint8_t *ptr = scsiio_cdb_ptr(&pccb->csio); 27164aa947cbSWarner Losh u_int32_t controlcode = (u_int32_t ) ptr[5] << 24 | 27174aa947cbSWarner Losh (u_int32_t ) ptr[6] << 16 | 27184aa947cbSWarner Losh (u_int32_t ) ptr[7] << 8 | 27194aa947cbSWarner Losh (u_int32_t ) ptr[8]; 2720ad6d6297SScott Long /* 4 bytes: Areca io control code */ 2721dd0b4fb6SKonstantin Belousov if ((pccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) { 2722ad6d6297SScott Long buffer = pccb->csio.data_ptr; 2723ad6d6297SScott Long transfer_len = pccb->csio.dxfer_len; 2724ad6d6297SScott Long } else { 2725ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2726ad6d6297SScott Long goto message_out; 2727ad6d6297SScott Long } 2728ad6d6297SScott Long if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) { 2729ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2730ad6d6297SScott Long goto message_out; 2731ad6d6297SScott Long } 2732ad6d6297SScott Long pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer; 2733ad6d6297SScott Long switch(controlcode) { 2734ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 2735ad6d6297SScott Long u_int8_t *pQbuffer; 2736ad6d6297SScott Long u_int8_t *ptmpQbuffer = pcmdmessagefld->messagedatabuffer; 2737ad6d6297SScott Long int32_t allxfer_len = 0; 2738f1c579b1SScott Long 27397a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2740ad6d6297SScott Long while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) 2741ad6d6297SScott Long && (allxfer_len < 1031)) { 2742ad6d6297SScott Long pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; 27437a7bc959SXin LI *ptmpQbuffer = *pQbuffer; 2744ad6d6297SScott Long acb->rqbuf_firstindex++; 2745ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 2746ad6d6297SScott Long ptmpQbuffer++; 2747ad6d6297SScott Long allxfer_len++; 2748f1c579b1SScott Long } 2749ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 275044f05562SScott Long struct QBUFFER *prbuffer; 2751ad6d6297SScott Long 2752ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 275344f05562SScott Long prbuffer = arcmsr_get_iop_rqbuffer(acb); 275435689395SXin LI if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) 275535689395SXin LI acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 2756ad6d6297SScott Long } 2757ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length = allxfer_len; 2758ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2759ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 27607a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2761ad6d6297SScott Long } 2762ad6d6297SScott Long break; 2763ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 2764ad6d6297SScott Long int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 2765ad6d6297SScott Long u_int8_t *pQbuffer; 2766ad6d6297SScott Long u_int8_t *ptmpuserbuffer = pcmdmessagefld->messagedatabuffer; 2767ad6d6297SScott Long 2768ad6d6297SScott Long user_len = pcmdmessagefld->cmdmessage.Length; 27697a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2770ad6d6297SScott Long wqbuf_lastindex = acb->wqbuf_lastindex; 2771ad6d6297SScott Long wqbuf_firstindex = acb->wqbuf_firstindex; 2772ad6d6297SScott Long if (wqbuf_lastindex != wqbuf_firstindex) { 27737a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2774ad6d6297SScott Long /* has error report sensedata */ 2775dac36688SXin LI if(pccb->csio.sense_len) { 2776ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 2777ad6d6297SScott Long /* Valid,ErrorCode */ 2778ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 2779ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 2780ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 2781ad6d6297SScott Long /* AdditionalSenseLength */ 2782ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 2783ad6d6297SScott Long /* AdditionalSenseCode */ 2784ad6d6297SScott Long } 2785ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2786ad6d6297SScott Long } else { 2787ad6d6297SScott Long my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) 2788ad6d6297SScott Long &(ARCMSR_MAX_QBUFFER - 1); 2789ad6d6297SScott Long if (my_empty_len >= user_len) { 2790ad6d6297SScott Long while (user_len > 0) { 2791ad6d6297SScott Long pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; 27927a7bc959SXin LI *pQbuffer = *ptmpuserbuffer; 2793ad6d6297SScott Long acb->wqbuf_lastindex++; 2794ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 2795ad6d6297SScott Long ptmpuserbuffer++; 2796ad6d6297SScott Long user_len--; 2797ad6d6297SScott Long } 2798ad6d6297SScott Long if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 2799ad6d6297SScott Long acb->acb_flags &= 2800ad6d6297SScott Long ~ACB_F_MESSAGE_WQBUFFER_CLEARED; 28017a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2802ad6d6297SScott Long } 2803ad6d6297SScott Long } else { 2804ad6d6297SScott Long /* has error report sensedata */ 2805dac36688SXin LI if(pccb->csio.sense_len) { 2806ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 2807ad6d6297SScott Long /* Valid,ErrorCode */ 2808ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 2809ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 2810ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 2811ad6d6297SScott Long /* AdditionalSenseLength */ 2812ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 2813ad6d6297SScott Long /* AdditionalSenseCode */ 2814ad6d6297SScott Long } 2815ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2816ad6d6297SScott Long } 2817ad6d6297SScott Long } 28187a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2819ad6d6297SScott Long } 2820ad6d6297SScott Long break; 2821ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 2822ad6d6297SScott Long u_int8_t *pQbuffer = acb->rqbuffer; 2823ad6d6297SScott Long 28247a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2825ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2826ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 282744f05562SScott Long arcmsr_iop_message_read(acb); 2828ad6d6297SScott Long } 2829ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 2830ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2831ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2832ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2833ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 2834ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 28357a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2836ad6d6297SScott Long } 2837ad6d6297SScott Long break; 2838ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { 2839ad6d6297SScott Long u_int8_t *pQbuffer = acb->wqbuffer; 2840ad6d6297SScott Long 28417a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2842ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2843ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 284444f05562SScott Long arcmsr_iop_message_read(acb); 2845ad6d6297SScott Long } 2846ad6d6297SScott Long acb->acb_flags |= 2847ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED | 284844f05562SScott Long ACB_F_MESSAGE_WQBUFFER_READ); 2849ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2850ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2851ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2852ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 2853ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 28547a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2855ad6d6297SScott Long } 2856ad6d6297SScott Long break; 2857ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 2858ad6d6297SScott Long u_int8_t *pQbuffer; 2859ad6d6297SScott Long 28607a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2861ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2862ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 286344f05562SScott Long arcmsr_iop_message_read(acb); 2864ad6d6297SScott Long } 2865ad6d6297SScott Long acb->acb_flags |= 2866ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED 2867ad6d6297SScott Long | ACB_F_MESSAGE_RQBUFFER_CLEARED 286844f05562SScott Long | ACB_F_MESSAGE_WQBUFFER_READ); 2869ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2870ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2871ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2872ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2873ad6d6297SScott Long pQbuffer = acb->rqbuffer; 2874ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 2875ad6d6297SScott Long pQbuffer = acb->wqbuffer; 2876ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 2877ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 28787a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2879ad6d6297SScott Long } 2880ad6d6297SScott Long break; 2881ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 2882ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; 2883ad6d6297SScott Long } 2884ad6d6297SScott Long break; 2885ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 2886ad6d6297SScott Long int8_t *hello_string = "Hello! I am ARCMSR"; 2887ad6d6297SScott Long 2888ad6d6297SScott Long memcpy(pcmdmessagefld->messagedatabuffer, hello_string 2889ad6d6297SScott Long , (int16_t)strlen(hello_string)); 2890ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2891ad6d6297SScott Long } 2892ad6d6297SScott Long break; 2893ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: 2894ad6d6297SScott Long arcmsr_iop_parking(acb); 2895ad6d6297SScott Long break; 2896ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: 2897ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2898ad6d6297SScott Long break; 2899ad6d6297SScott Long default: 2900ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2901ad6d6297SScott Long } 2902ad6d6297SScott Long message_out: 2903dac36688SXin LI return (retvalue); 2904f1c579b1SScott Long } 2905f1c579b1SScott Long /* 2906f1c579b1SScott Long ********************************************************************* 2907f1c579b1SScott Long ********************************************************************* 2908f1c579b1SScott Long */ 2909231c8b71SXin LI static void arcmsr_execute_srb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 2910f1c579b1SScott Long { 2911ad6d6297SScott Long struct CommandControlBlock *srb = (struct CommandControlBlock *)arg; 2912ad6d6297SScott Long struct AdapterControlBlock *acb = (struct AdapterControlBlock *)srb->acb; 2913f1c579b1SScott Long union ccb *pccb; 2914ad6d6297SScott Long int target, lun; 2915f1c579b1SScott Long 2916ad6d6297SScott Long pccb = srb->pccb; 2917ad6d6297SScott Long target = pccb->ccb_h.target_id; 2918ad6d6297SScott Long lun = pccb->ccb_h.target_lun; 291922f2616bSXin LI acb->pktRequestCount++; 2920ad6d6297SScott Long if(error != 0) { 2921ad6d6297SScott Long if(error != EFBIG) { 292244f05562SScott Long printf("arcmsr%d: unexpected error %x" 292344f05562SScott Long " returned from 'bus_dmamap_load' \n" 2924ad6d6297SScott Long , acb->pci_unit, error); 2925f1c579b1SScott Long } 2926ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { 292715735becSScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 2928f1c579b1SScott Long } 2929ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2930f1c579b1SScott Long return; 2931f1c579b1SScott Long } 2932ad6d6297SScott Long if(nseg > ARCMSR_MAX_SG_ENTRIES) { 2933ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 2934ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2935ad6d6297SScott Long return; 2936f1c579b1SScott Long } 2937ad6d6297SScott Long if(acb->acb_flags & ACB_F_BUS_RESET) { 2938ad6d6297SScott Long printf("arcmsr%d: bus reset and return busy \n", acb->pci_unit); 2939ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_BUS_RESET; 2940ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2941ad6d6297SScott Long return; 2942ad6d6297SScott Long } 2943ad6d6297SScott Long if(acb->devstate[target][lun] == ARECA_RAID_GONE) { 294422f2616bSXin LI u_int8_t block_cmd, cmd; 2945ad6d6297SScott Long 29464aa947cbSWarner Losh cmd = scsiio_cdb_ptr(&pccb->csio)[0]; 294722f2616bSXin LI block_cmd = cmd & 0x0f; 2948ad6d6297SScott Long if(block_cmd == 0x08 || block_cmd == 0x0a) { 2949ad6d6297SScott Long printf("arcmsr%d:block 'read/write' command " 295022f2616bSXin LI "with gone raid volume Cmd=0x%2x, TargetId=%d, Lun=%d \n" 295122f2616bSXin LI , acb->pci_unit, cmd, target, lun); 2952ad6d6297SScott Long pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 2953ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2954ad6d6297SScott Long return; 2955ad6d6297SScott Long } 2956ad6d6297SScott Long } 2957ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { 2958ad6d6297SScott Long if(nseg != 0) { 2959ad6d6297SScott Long bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 2960ad6d6297SScott Long } 2961ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2962f1c579b1SScott Long return; 2963f1c579b1SScott Long } 2964abfdbca9SXin LI if(acb->srboutstandingcount >= acb->maxOutstanding) { 29657a7bc959SXin LI if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) == 0) 29667a7bc959SXin LI { 296715735becSScott Long xpt_freeze_simq(acb->psim, 1); 2968dc3a205bSScott Long acb->acb_flags |= ACB_F_CAM_DEV_QFRZN; 29697a7bc959SXin LI } 29707a7bc959SXin LI pccb->ccb_h.status &= ~CAM_SIM_QUEUED; 29717a7bc959SXin LI pccb->ccb_h.status |= CAM_REQUEUE_REQ; 2972ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2973ad6d6297SScott Long return; 2974f1c579b1SScott Long } 297515735becSScott Long pccb->ccb_h.status |= CAM_SIM_QUEUED; 2976ad6d6297SScott Long arcmsr_build_srb(srb, dm_segs, nseg); 2977ad6d6297SScott Long arcmsr_post_srb(acb, srb); 297822f2616bSXin LI if (pccb->ccb_h.timeout != CAM_TIME_INFINITY) 297922f2616bSXin LI { 298022f2616bSXin LI arcmsr_callout_init(&srb->ccb_callout); 298185c9dd9dSSteven Hartland callout_reset_sbt(&srb->ccb_callout, SBT_1MS * 298285c9dd9dSSteven Hartland (pccb->ccb_h.timeout + (ARCMSR_TIMEOUT_DELAY * 1000)), 0, 298385c9dd9dSSteven Hartland arcmsr_srb_timeout, srb, 0); 298422f2616bSXin LI srb->srb_flags |= SRB_FLAG_TIMER_START; 298522f2616bSXin LI } 2986f1c579b1SScott Long } 2987f1c579b1SScott Long /* 2988f1c579b1SScott Long ***************************************************************************************** 2989f1c579b1SScott Long ***************************************************************************************** 2990f1c579b1SScott Long */ 2991ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb *abortccb) 2992f1c579b1SScott Long { 2993ad6d6297SScott Long struct CommandControlBlock *srb; 2994ad6d6297SScott Long struct AdapterControlBlock *acb = (struct AdapterControlBlock *) abortccb->ccb_h.arcmsr_ccbacb_ptr; 299544f05562SScott Long u_int32_t intmask_org; 2996ad6d6297SScott Long int i = 0; 2997f1c579b1SScott Long 2998ad6d6297SScott Long acb->num_aborts++; 2999f1c579b1SScott Long /* 3000ad6d6297SScott Long *************************************************************************** 3001f1c579b1SScott Long ** It is the upper layer do abort command this lock just prior to calling us. 3002f1c579b1SScott Long ** First determine if we currently own this command. 3003f1c579b1SScott Long ** Start by searching the device queue. If not found 3004f1c579b1SScott Long ** at all, and the system wanted us to just abort the 3005f1c579b1SScott Long ** command return success. 3006ad6d6297SScott Long *************************************************************************** 3007f1c579b1SScott Long */ 3008ad6d6297SScott Long if(acb->srboutstandingcount != 0) { 300922f2616bSXin LI /* disable all outbound interrupt */ 301022f2616bSXin LI intmask_org = arcmsr_disable_allintr(acb); 3011ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 3012ad6d6297SScott Long srb = acb->psrb_pool[i]; 301322f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) { 3014ad6d6297SScott Long if(srb->pccb == abortccb) { 301522f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 3016123055f0SNathan Whitehorn printf("arcmsr%d:scsi id=%d lun=%jx abort srb '%p'" 3017ad6d6297SScott Long "outstanding command \n" 3018ad6d6297SScott Long , acb->pci_unit, abortccb->ccb_h.target_id 3019123055f0SNathan Whitehorn , (uintmax_t)abortccb->ccb_h.target_lun, srb); 3020ad6d6297SScott Long arcmsr_polling_srbdone(acb, srb); 302144f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 302244f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 3023ad6d6297SScott Long return (TRUE); 3024f1c579b1SScott Long } 302522f2616bSXin LI } 302622f2616bSXin LI } 302722f2616bSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 302822f2616bSXin LI arcmsr_enable_allintr(acb, intmask_org); 302922f2616bSXin LI } 303022f2616bSXin LI return(FALSE); 303122f2616bSXin LI } 3032f1c579b1SScott Long /* 3033f1c579b1SScott Long **************************************************************************** 3034f1c579b1SScott Long **************************************************************************** 3035f1c579b1SScott Long */ 3036ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb) 3037f1c579b1SScott Long { 3038ad6d6297SScott Long int retry = 0; 3039f1c579b1SScott Long 3040ad6d6297SScott Long acb->num_resets++; 3041ad6d6297SScott Long acb->acb_flags |= ACB_F_BUS_RESET; 3042ad6d6297SScott Long while(acb->srboutstandingcount != 0 && retry < 400) { 304344f05562SScott Long arcmsr_interrupt(acb); 3044ad6d6297SScott Long UDELAY(25000); 3045ad6d6297SScott Long retry++; 3046ad6d6297SScott Long } 3047ad6d6297SScott Long arcmsr_iop_reset(acb); 3048ad6d6297SScott Long acb->acb_flags &= ~ACB_F_BUS_RESET; 3049f1c579b1SScott Long } 3050f1c579b1SScott Long /* 3051ad6d6297SScott Long ************************************************************************** 3052ad6d6297SScott Long ************************************************************************** 3053ad6d6297SScott Long */ 3054ad6d6297SScott Long static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, 3055ad6d6297SScott Long union ccb *pccb) 3056ad6d6297SScott Long { 3057ad6d6297SScott Long if (pccb->ccb_h.target_lun) { 305861ba2ac6SJim Harris pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 3059ad6d6297SScott Long xpt_done(pccb); 3060ad6d6297SScott Long return; 3061ad6d6297SScott Long } 30627a7bc959SXin LI pccb->ccb_h.status |= CAM_REQ_CMP; 30634aa947cbSWarner Losh switch (scsiio_cdb_ptr(&pccb->csio)[0]) { 30647a7bc959SXin LI case INQUIRY: { 30657a7bc959SXin LI unsigned char inqdata[36]; 30667a7bc959SXin LI char *buffer = pccb->csio.data_ptr; 30677a7bc959SXin LI 3068231c8b71SXin LI inqdata[0] = T_PROCESSOR; /* Periph Qualifier & Periph Dev Type */ 3069231c8b71SXin LI inqdata[1] = 0; /* rem media bit & Dev Type Modifier */ 3070231c8b71SXin LI inqdata[2] = 0; /* ISO, ECMA, & ANSI versions */ 3071231c8b71SXin LI inqdata[3] = 0; 3072231c8b71SXin LI inqdata[4] = 31; /* length of additional data */ 3073231c8b71SXin LI inqdata[5] = 0; 3074231c8b71SXin LI inqdata[6] = 0; 3075231c8b71SXin LI inqdata[7] = 0; 3076231c8b71SXin LI strncpy(&inqdata[8], "Areca ", 8); /* Vendor Identification */ 3077231c8b71SXin LI strncpy(&inqdata[16], "RAID controller ", 16); /* Product Identification */ 3078ad6d6297SScott Long strncpy(&inqdata[32], "R001", 4); /* Product Revision */ 3079ad6d6297SScott Long memcpy(buffer, inqdata, sizeof(inqdata)); 3080ad6d6297SScott Long xpt_done(pccb); 3081ad6d6297SScott Long } 3082ad6d6297SScott Long break; 3083ad6d6297SScott Long case WRITE_BUFFER: 3084ad6d6297SScott Long case READ_BUFFER: { 3085ad6d6297SScott Long if (arcmsr_iop_message_xfer(acb, pccb)) { 3086ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 3087ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 3088ad6d6297SScott Long } 3089ad6d6297SScott Long xpt_done(pccb); 3090ad6d6297SScott Long } 3091ad6d6297SScott Long break; 3092ad6d6297SScott Long default: 3093ad6d6297SScott Long xpt_done(pccb); 3094ad6d6297SScott Long } 3095ad6d6297SScott Long } 3096ad6d6297SScott Long /* 3097f1c579b1SScott Long ********************************************************************* 3098f1c579b1SScott Long ********************************************************************* 3099f1c579b1SScott Long */ 3100ad6d6297SScott Long static void arcmsr_action(struct cam_sim *psim, union ccb *pccb) 3101f1c579b1SScott Long { 3102ad6d6297SScott Long struct AdapterControlBlock *acb; 3103f1c579b1SScott Long 3104ad6d6297SScott Long acb = (struct AdapterControlBlock *) cam_sim_softc(psim); 3105ad6d6297SScott Long if(acb == NULL) { 3106ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 3107f1c579b1SScott Long xpt_done(pccb); 3108f1c579b1SScott Long return; 3109f1c579b1SScott Long } 3110ad6d6297SScott Long switch (pccb->ccb_h.func_code) { 3111ad6d6297SScott Long case XPT_SCSI_IO: { 3112ad6d6297SScott Long struct CommandControlBlock *srb; 3113ad6d6297SScott Long int target = pccb->ccb_h.target_id; 3114dd0b4fb6SKonstantin Belousov int error; 3115f1c579b1SScott Long 31164aa947cbSWarner Losh if (pccb->ccb_h.flags & CAM_CDB_PHYS) { 31174aa947cbSWarner Losh pccb->ccb_h.status = CAM_REQ_INVALID; 31184aa947cbSWarner Losh xpt_done(pccb); 31194aa947cbSWarner Losh return; 31204aa947cbSWarner Losh } 31214aa947cbSWarner Losh 3122ad6d6297SScott Long if(target == 16) { 3123ad6d6297SScott Long /* virtual device for iop message transfer */ 3124ad6d6297SScott Long arcmsr_handle_virtual_command(acb, pccb); 3125ad6d6297SScott Long return; 3126ad6d6297SScott Long } 3127ad6d6297SScott Long if((srb = arcmsr_get_freesrb(acb)) == NULL) { 3128ad6d6297SScott Long pccb->ccb_h.status |= CAM_RESRC_UNAVAIL; 3129f1c579b1SScott Long xpt_done(pccb); 3130f1c579b1SScott Long return; 3131f1c579b1SScott Long } 3132ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbsrb_ptr = srb; 3133ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbacb_ptr = acb; 3134ad6d6297SScott Long srb->pccb = pccb; 3135dd0b4fb6SKonstantin Belousov error = bus_dmamap_load_ccb(acb->dm_segs_dmat 3136ad6d6297SScott Long , srb->dm_segs_dmamap 3137dd0b4fb6SKonstantin Belousov , pccb 3138231c8b71SXin LI , arcmsr_execute_srb, srb, /*flags*/0); 3139ad6d6297SScott Long if(error == EINPROGRESS) { 3140ad6d6297SScott Long xpt_freeze_simq(acb->psim, 1); 3141f1c579b1SScott Long pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 3142f1c579b1SScott Long } 3143f1c579b1SScott Long break; 3144f1c579b1SScott Long } 3145ad6d6297SScott Long case XPT_PATH_INQ: { 3146f1c579b1SScott Long struct ccb_pathinq *cpi = &pccb->cpi; 3147f1c579b1SScott Long 3148f1c579b1SScott Long cpi->version_num = 1; 3149f1c579b1SScott Long cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE; 3150f1c579b1SScott Long cpi->target_sprt = 0; 3151f1c579b1SScott Long cpi->hba_misc = 0; 3152f1c579b1SScott Long cpi->hba_eng_cnt = 0; 3153ad6d6297SScott Long cpi->max_target = ARCMSR_MAX_TARGETID; /* 0-16 */ 3154ad6d6297SScott Long cpi->max_lun = ARCMSR_MAX_TARGETLUN; /* 0-7 */ 3155ad6d6297SScott Long cpi->initiator_id = ARCMSR_SCSI_INITIATOR_ID; /* 255 */ 3156f1c579b1SScott Long cpi->bus_id = cam_sim_bus(psim); 31574195c7deSAlan Somers strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 31584195c7deSAlan Somers strlcpy(cpi->hba_vid, "ARCMSR", HBA_IDLEN); 31594195c7deSAlan Somers strlcpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN); 3160f1c579b1SScott Long cpi->unit_number = cam_sim_unit(psim); 316144f05562SScott Long #ifdef CAM_NEW_TRAN_CODE 3162224a78aeSXin LI if(acb->adapter_bus_speed == ACB_BUS_SPEED_12G) 3163224a78aeSXin LI cpi->base_transfer_speed = 1200000; 3164224a78aeSXin LI else if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G) 3165dac36688SXin LI cpi->base_transfer_speed = 600000; 3166dac36688SXin LI else 3167dac36688SXin LI cpi->base_transfer_speed = 300000; 3168dac36688SXin LI if((acb->vendor_device_id == PCIDevVenIDARC1880) || 3169a1103e04SXin LI (acb->vendor_device_id == PCIDevVenIDARC1884) || 31707a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1680) || 31717a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1214)) 3172dac36688SXin LI { 3173dac36688SXin LI cpi->transport = XPORT_SAS; 3174dac36688SXin LI cpi->transport_version = 0; 3175dac36688SXin LI cpi->protocol_version = SCSI_REV_SPC2; 3176dac36688SXin LI } 3177dac36688SXin LI else 3178dac36688SXin LI { 3179fa9ed865SMatt Jacob cpi->transport = XPORT_SPI; 3180fa9ed865SMatt Jacob cpi->transport_version = 2; 3181fa9ed865SMatt Jacob cpi->protocol_version = SCSI_REV_2; 3182dac36688SXin LI } 3183dac36688SXin LI cpi->protocol = PROTO_SCSI; 318444f05562SScott Long #endif 3185ad6d6297SScott Long cpi->ccb_h.status |= CAM_REQ_CMP; 3186f1c579b1SScott Long xpt_done(pccb); 3187f1c579b1SScott Long break; 3188f1c579b1SScott Long } 3189ad6d6297SScott Long case XPT_ABORT: { 3190f1c579b1SScott Long union ccb *pabort_ccb; 3191f1c579b1SScott Long 3192f1c579b1SScott Long pabort_ccb = pccb->cab.abort_ccb; 3193ad6d6297SScott Long switch (pabort_ccb->ccb_h.func_code) { 3194f1c579b1SScott Long case XPT_ACCEPT_TARGET_IO: 3195f1c579b1SScott Long case XPT_CONT_TARGET_IO: 3196ad6d6297SScott Long if(arcmsr_seek_cmd2abort(pabort_ccb)==TRUE) { 3197ad6d6297SScott Long pabort_ccb->ccb_h.status |= CAM_REQ_ABORTED; 3198f1c579b1SScott Long xpt_done(pabort_ccb); 3199ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 3200ad6d6297SScott Long } else { 3201f1c579b1SScott Long xpt_print_path(pabort_ccb->ccb_h.path); 3202f1c579b1SScott Long printf("Not found\n"); 3203ad6d6297SScott Long pccb->ccb_h.status |= CAM_PATH_INVALID; 3204f1c579b1SScott Long } 3205f1c579b1SScott Long break; 3206f1c579b1SScott Long case XPT_SCSI_IO: 3207ad6d6297SScott Long pccb->ccb_h.status |= CAM_UA_ABORT; 3208f1c579b1SScott Long break; 3209f1c579b1SScott Long default: 3210ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 3211f1c579b1SScott Long break; 3212f1c579b1SScott Long } 3213f1c579b1SScott Long xpt_done(pccb); 3214f1c579b1SScott Long break; 3215f1c579b1SScott Long } 3216f1c579b1SScott Long case XPT_RESET_BUS: 3217ad6d6297SScott Long case XPT_RESET_DEV: { 3218ad6d6297SScott Long u_int32_t i; 3219f1c579b1SScott Long 3220ad6d6297SScott Long arcmsr_bus_reset(acb); 3221ad6d6297SScott Long for (i=0; i < 500; i++) { 3222f1c579b1SScott Long DELAY(1000); 3223f1c579b1SScott Long } 3224ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 3225f1c579b1SScott Long xpt_done(pccb); 3226f1c579b1SScott Long break; 3227f1c579b1SScott Long } 3228ad6d6297SScott Long case XPT_TERM_IO: { 3229ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 3230f1c579b1SScott Long xpt_done(pccb); 3231f1c579b1SScott Long break; 3232f1c579b1SScott Long } 3233ad6d6297SScott Long case XPT_GET_TRAN_SETTINGS: { 3234ad6d6297SScott Long struct ccb_trans_settings *cts; 3235ad6d6297SScott Long 3236ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 3237ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 3238ad6d6297SScott Long xpt_done(pccb); 3239ad6d6297SScott Long break; 3240ad6d6297SScott Long } 3241ad6d6297SScott Long cts = &pccb->cts; 324244f05562SScott Long #ifdef CAM_NEW_TRAN_CODE 324344f05562SScott Long { 324444f05562SScott Long struct ccb_trans_settings_scsi *scsi; 324544f05562SScott Long struct ccb_trans_settings_spi *spi; 3246dac36688SXin LI struct ccb_trans_settings_sas *sas; 324744f05562SScott Long 3248ad6d6297SScott Long scsi = &cts->proto_specific.scsi; 3249dac36688SXin LI scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 3250dac36688SXin LI scsi->valid = CTS_SCSI_VALID_TQ; 3251fa9ed865SMatt Jacob cts->protocol = PROTO_SCSI; 3252dac36688SXin LI 3253dac36688SXin LI if((acb->vendor_device_id == PCIDevVenIDARC1880) || 3254a1103e04SXin LI (acb->vendor_device_id == PCIDevVenIDARC1884) || 32557a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1680) || 32567a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1214)) 3257dac36688SXin LI { 3258dac36688SXin LI cts->protocol_version = SCSI_REV_SPC2; 3259dac36688SXin LI cts->transport_version = 0; 3260dac36688SXin LI cts->transport = XPORT_SAS; 3261dac36688SXin LI sas = &cts->xport_specific.sas; 3262dac36688SXin LI sas->valid = CTS_SAS_VALID_SPEED; 3263b23a1998SXin LI if (acb->adapter_bus_speed == ACB_BUS_SPEED_12G) 3264224a78aeSXin LI sas->bitrate = 1200000; 3265b23a1998SXin LI else if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G) 3266dac36688SXin LI sas->bitrate = 600000; 3267b23a1998SXin LI else if(acb->adapter_bus_speed == ACB_BUS_SPEED_3G) 3268dac36688SXin LI sas->bitrate = 300000; 3269dac36688SXin LI } 3270dac36688SXin LI else 3271dac36688SXin LI { 3272fa9ed865SMatt Jacob cts->protocol_version = SCSI_REV_2; 3273fa9ed865SMatt Jacob cts->transport_version = 2; 3274dac36688SXin LI cts->transport = XPORT_SPI; 3275dac36688SXin LI spi = &cts->xport_specific.spi; 3276fa9ed865SMatt Jacob spi->flags = CTS_SPI_FLAGS_DISC_ENB; 3277b23a1998SXin LI if (acb->adapter_bus_speed == ACB_BUS_SPEED_6G) 3278b23a1998SXin LI spi->sync_period = 1; 3279b23a1998SXin LI else 3280dac36688SXin LI spi->sync_period = 2; 3281fa9ed865SMatt Jacob spi->sync_offset = 32; 3282fa9ed865SMatt Jacob spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 32839d98ff4dSScott Long spi->valid = CTS_SPI_VALID_DISC 32849d98ff4dSScott Long | CTS_SPI_VALID_SYNC_RATE 3285fa9ed865SMatt Jacob | CTS_SPI_VALID_SYNC_OFFSET 3286fa9ed865SMatt Jacob | CTS_SPI_VALID_BUS_WIDTH; 3287dac36688SXin LI } 328844f05562SScott Long } 328944f05562SScott Long #else 329044f05562SScott Long { 329144f05562SScott Long cts->flags = (CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB); 3292b23a1998SXin LI if (acb->adapter_bus_speed == ACB_BUS_SPEED_6G) 3293b23a1998SXin LI cts->sync_period = 1; 3294b23a1998SXin LI else 3295dac36688SXin LI cts->sync_period = 2; 329644f05562SScott Long cts->sync_offset = 32; 329744f05562SScott Long cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 329844f05562SScott Long cts->valid = CCB_TRANS_SYNC_RATE_VALID | 329944f05562SScott Long CCB_TRANS_SYNC_OFFSET_VALID | 330044f05562SScott Long CCB_TRANS_BUS_WIDTH_VALID | 330144f05562SScott Long CCB_TRANS_DISC_VALID | 330244f05562SScott Long CCB_TRANS_TQ_VALID; 330344f05562SScott Long } 330444f05562SScott Long #endif 3305ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 3306ad6d6297SScott Long xpt_done(pccb); 3307ad6d6297SScott Long break; 3308ad6d6297SScott Long } 3309ad6d6297SScott Long case XPT_SET_TRAN_SETTINGS: { 3310ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 3311ad6d6297SScott Long xpt_done(pccb); 3312ad6d6297SScott Long break; 3313ad6d6297SScott Long } 3314f3b080e6SMarius Strobl case XPT_CALC_GEOMETRY: 3315ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 3316ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 3317ad6d6297SScott Long xpt_done(pccb); 3318ad6d6297SScott Long break; 3319ad6d6297SScott Long } 3320f3b080e6SMarius Strobl #if __FreeBSD_version >= 500000 3321f3b080e6SMarius Strobl cam_calc_geometry(&pccb->ccg, 1); 3322f3b080e6SMarius Strobl #else 3323f3b080e6SMarius Strobl { 3324f3b080e6SMarius Strobl struct ccb_calc_geometry *ccg; 3325f3b080e6SMarius Strobl u_int32_t size_mb; 3326f3b080e6SMarius Strobl u_int32_t secs_per_cylinder; 3327f3b080e6SMarius Strobl 3328f1c579b1SScott Long ccg = &pccb->ccg; 3329ad6d6297SScott Long if (ccg->block_size == 0) { 3330ad6d6297SScott Long pccb->ccb_h.status = CAM_REQ_INVALID; 3331ad6d6297SScott Long xpt_done(pccb); 3332ad6d6297SScott Long break; 3333ad6d6297SScott Long } 3334ad6d6297SScott Long if(((1024L * 1024L)/ccg->block_size) < 0) { 3335ad6d6297SScott Long pccb->ccb_h.status = CAM_REQ_INVALID; 3336ad6d6297SScott Long xpt_done(pccb); 3337ad6d6297SScott Long break; 3338ad6d6297SScott Long } 3339f1c579b1SScott Long size_mb = ccg->volume_size/((1024L * 1024L)/ccg->block_size); 3340ad6d6297SScott Long if(size_mb > 1024 ) { 3341f1c579b1SScott Long ccg->heads = 255; 3342f1c579b1SScott Long ccg->secs_per_track = 63; 3343ad6d6297SScott Long } else { 3344f1c579b1SScott Long ccg->heads = 64; 3345f1c579b1SScott Long ccg->secs_per_track = 32; 3346f1c579b1SScott Long } 3347f1c579b1SScott Long secs_per_cylinder = ccg->heads * ccg->secs_per_track; 3348f1c579b1SScott Long ccg->cylinders = ccg->volume_size / secs_per_cylinder; 3349ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 3350f3b080e6SMarius Strobl } 3351f3b080e6SMarius Strobl #endif 3352f1c579b1SScott Long xpt_done(pccb); 3353f1c579b1SScott Long break; 3354f1c579b1SScott Long default: 3355ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 3356f1c579b1SScott Long xpt_done(pccb); 3357f1c579b1SScott Long break; 3358f1c579b1SScott Long } 3359f1c579b1SScott Long } 3360f1c579b1SScott Long /* 3361f1c579b1SScott Long ********************************************************************** 3362f1c579b1SScott Long ********************************************************************** 3363f1c579b1SScott Long */ 336444f05562SScott Long static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) 3365f1c579b1SScott Long { 3366ad6d6297SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 336744f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 336844f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 3369ad6d6297SScott Long printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 3370ad6d6297SScott Long } 3371f1c579b1SScott Long } 3372f1c579b1SScott Long /* 3373f1c579b1SScott Long ********************************************************************** 3374f1c579b1SScott Long ********************************************************************** 3375f1c579b1SScott Long */ 337644f05562SScott Long static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb) 337744f05562SScott Long { 3378b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 337944f05562SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 3380b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_START_BGRB); 338144f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 338244f05562SScott Long printf( "arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 338344f05562SScott Long } 338444f05562SScott Long } 338544f05562SScott Long /* 338644f05562SScott Long ********************************************************************** 338744f05562SScott Long ********************************************************************** 338844f05562SScott Long */ 3389d74001adSXin LI static void arcmsr_start_hbc_bgrb(struct AdapterControlBlock *acb) 3390d74001adSXin LI { 3391d74001adSXin LI acb->acb_flags |= ACB_F_MSG_START_BGRB; 3392d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 3393d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 3394d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 3395d74001adSXin LI printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 3396d74001adSXin LI } 3397d74001adSXin LI } 3398d74001adSXin LI /* 3399d74001adSXin LI ********************************************************************** 3400d74001adSXin LI ********************************************************************** 3401d74001adSXin LI */ 34027a7bc959SXin LI static void arcmsr_start_hbd_bgrb(struct AdapterControlBlock *acb) 34037a7bc959SXin LI { 34047a7bc959SXin LI acb->acb_flags |= ACB_F_MSG_START_BGRB; 34057a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 34067a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 34077a7bc959SXin LI printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 34087a7bc959SXin LI } 34097a7bc959SXin LI } 34107a7bc959SXin LI /* 34117a7bc959SXin LI ********************************************************************** 34127a7bc959SXin LI ********************************************************************** 34137a7bc959SXin LI */ 3414a1103e04SXin LI static void arcmsr_start_hbe_bgrb(struct AdapterControlBlock *acb) 3415a1103e04SXin LI { 3416a1103e04SXin LI acb->acb_flags |= ACB_F_MSG_START_BGRB; 3417a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 3418a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 3419a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 3420a1103e04SXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) { 3421a1103e04SXin LI printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 3422a1103e04SXin LI } 3423a1103e04SXin LI } 3424a1103e04SXin LI /* 3425a1103e04SXin LI ********************************************************************** 3426a1103e04SXin LI ********************************************************************** 3427a1103e04SXin LI */ 342844f05562SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) 342944f05562SScott Long { 343044f05562SScott Long switch (acb->adapter_type) { 343144f05562SScott Long case ACB_ADAPTER_TYPE_A: 343244f05562SScott Long arcmsr_start_hba_bgrb(acb); 343344f05562SScott Long break; 343444f05562SScott Long case ACB_ADAPTER_TYPE_B: 343544f05562SScott Long arcmsr_start_hbb_bgrb(acb); 343644f05562SScott Long break; 3437d74001adSXin LI case ACB_ADAPTER_TYPE_C: 3438d74001adSXin LI arcmsr_start_hbc_bgrb(acb); 3439d74001adSXin LI break; 34407a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 34417a7bc959SXin LI arcmsr_start_hbd_bgrb(acb); 34427a7bc959SXin LI break; 3443a1103e04SXin LI case ACB_ADAPTER_TYPE_E: 3444a1103e04SXin LI arcmsr_start_hbe_bgrb(acb); 3445a1103e04SXin LI break; 344644f05562SScott Long } 344744f05562SScott Long } 344844f05562SScott Long /* 344944f05562SScott Long ********************************************************************** 345044f05562SScott Long ** 345144f05562SScott Long ********************************************************************** 345244f05562SScott Long */ 345344f05562SScott Long static void arcmsr_polling_hba_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 3454f1c579b1SScott Long { 3455ad6d6297SScott Long struct CommandControlBlock *srb; 345644f05562SScott Long u_int32_t flag_srb, outbound_intstatus, poll_srb_done=0, poll_count=0; 3457d74001adSXin LI u_int16_t error; 3458f1c579b1SScott Long 345944f05562SScott Long polling_ccb_retry: 3460ad6d6297SScott Long poll_count++; 3461d74001adSXin LI outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 3462d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus); /*clear interrupt*/ 346344f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 3464ad6d6297SScott Long while(1) { 346544f05562SScott Long if((flag_srb = CHIP_REG_READ32(HBA_MessageUnit, 346644f05562SScott Long 0, outbound_queueport)) == 0xFFFFFFFF) { 3467ad6d6297SScott Long if(poll_srb_done) { 3468ad6d6297SScott Long break;/*chip FIFO no ccb for completion already*/ 3469ad6d6297SScott Long } else { 3470ad6d6297SScott Long UDELAY(25000); 3471d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 3472ad6d6297SScott Long break; 3473f1c579b1SScott Long } 347444f05562SScott Long goto polling_ccb_retry; 3475f1c579b1SScott Long } 3476ad6d6297SScott Long } 3477ad6d6297SScott Long /* check if command done with no error*/ 347844f05562SScott Long srb = (struct CommandControlBlock *) 347944f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 3480d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 348144f05562SScott Long poll_srb_done = (srb == poll_srb) ? 1:0; 348222f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 348322f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3484123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'" 3485ad6d6297SScott Long "poll command abort successfully \n" 3486ad6d6297SScott Long , acb->pci_unit 3487ad6d6297SScott Long , srb->pccb->ccb_h.target_id 3488123055f0SNathan Whitehorn , (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 3489ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 3490ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 3491ad6d6297SScott Long continue; 3492ad6d6297SScott Long } 3493ad6d6297SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 3494ad6d6297SScott Long "srboutstandingcount=%d \n" 3495ad6d6297SScott Long , acb->pci_unit 3496ad6d6297SScott Long , srb, acb->srboutstandingcount); 3497ad6d6297SScott Long continue; 3498ad6d6297SScott Long } 3499d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 3500ad6d6297SScott Long } /*drain reply FIFO*/ 3501f1c579b1SScott Long } 3502f1c579b1SScott Long /* 3503f1c579b1SScott Long ********************************************************************** 350444f05562SScott Long ** 3505ad6d6297SScott Long ********************************************************************** 3506ad6d6297SScott Long */ 350744f05562SScott Long static void arcmsr_polling_hbb_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 350844f05562SScott Long { 350944f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 351044f05562SScott Long struct CommandControlBlock *srb; 351144f05562SScott Long u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 351244f05562SScott Long int index; 3513d74001adSXin LI u_int16_t error; 351444f05562SScott Long 351544f05562SScott Long polling_ccb_retry: 351644f05562SScott Long poll_count++; 3517b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 351844f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 351944f05562SScott Long while(1) { 352044f05562SScott Long index = phbbmu->doneq_index; 352144f05562SScott Long if((flag_srb = phbbmu->done_qbuffer[index]) == 0) { 352244f05562SScott Long if(poll_srb_done) { 352344f05562SScott Long break;/*chip FIFO no ccb for completion already*/ 352444f05562SScott Long } else { 352544f05562SScott Long UDELAY(25000); 3526d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 352744f05562SScott Long break; 352844f05562SScott Long } 352944f05562SScott Long goto polling_ccb_retry; 353044f05562SScott Long } 353144f05562SScott Long } 353244f05562SScott Long phbbmu->done_qbuffer[index] = 0; 353344f05562SScott Long index++; 353444f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 353544f05562SScott Long phbbmu->doneq_index = index; 353644f05562SScott Long /* check if command done with no error*/ 353744f05562SScott Long srb = (struct CommandControlBlock *) 353844f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 3539d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 354044f05562SScott Long poll_srb_done = (srb == poll_srb) ? 1:0; 354122f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 354222f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3543123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'" 354444f05562SScott Long "poll command abort successfully \n" 354544f05562SScott Long , acb->pci_unit 354644f05562SScott Long , srb->pccb->ccb_h.target_id 3547123055f0SNathan Whitehorn , (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 354844f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 354944f05562SScott Long arcmsr_srb_complete(srb, 1); 355044f05562SScott Long continue; 355144f05562SScott Long } 355244f05562SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 355344f05562SScott Long "srboutstandingcount=%d \n" 355444f05562SScott Long , acb->pci_unit 355544f05562SScott Long , srb, acb->srboutstandingcount); 355644f05562SScott Long continue; 355744f05562SScott Long } 3558d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 3559d74001adSXin LI } /*drain reply FIFO*/ 3560d74001adSXin LI } 3561d74001adSXin LI /* 3562d74001adSXin LI ********************************************************************** 3563d74001adSXin LI ** 3564d74001adSXin LI ********************************************************************** 3565d74001adSXin LI */ 3566d74001adSXin LI static void arcmsr_polling_hbc_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 3567d74001adSXin LI { 3568d74001adSXin LI struct CommandControlBlock *srb; 3569d74001adSXin LI u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 3570d74001adSXin LI u_int16_t error; 3571d74001adSXin LI 3572d74001adSXin LI polling_ccb_retry: 3573d74001adSXin LI poll_count++; 3574d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 3575d74001adSXin LI while(1) { 3576d74001adSXin LI if(!(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR)) { 3577d74001adSXin LI if(poll_srb_done) { 3578d74001adSXin LI break;/*chip FIFO no ccb for completion already*/ 3579d74001adSXin LI } else { 3580d74001adSXin LI UDELAY(25000); 3581d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 3582d74001adSXin LI break; 3583d74001adSXin LI } 3584d74001adSXin LI if (acb->srboutstandingcount == 0) { 3585d74001adSXin LI break; 3586d74001adSXin LI } 3587d74001adSXin LI goto polling_ccb_retry; 3588d74001adSXin LI } 3589d74001adSXin LI } 3590d74001adSXin LI flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 3591d74001adSXin LI /* check if command done with no error*/ 359222f2616bSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/ 3593d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; 3594d74001adSXin LI if (poll_srb != NULL) 3595d74001adSXin LI poll_srb_done = (srb == poll_srb) ? 1:0; 359622f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 359722f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3598123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n" 3599123055f0SNathan Whitehorn , acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 3600d74001adSXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 3601d74001adSXin LI arcmsr_srb_complete(srb, 1); 3602d74001adSXin LI continue; 3603d74001adSXin LI } 3604d74001adSXin LI printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n" 3605d74001adSXin LI , acb->pci_unit, srb, acb->srboutstandingcount); 3606d74001adSXin LI continue; 3607d74001adSXin LI } 3608d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 360944f05562SScott Long } /*drain reply FIFO*/ 361044f05562SScott Long } 361144f05562SScott Long /* 361244f05562SScott Long ********************************************************************** 36137a7bc959SXin LI ** 36147a7bc959SXin LI ********************************************************************** 36157a7bc959SXin LI */ 36167a7bc959SXin LI static void arcmsr_polling_hbd_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 36177a7bc959SXin LI { 36187a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 36197a7bc959SXin LI struct CommandControlBlock *srb; 36207a7bc959SXin LI u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 36217a7bc959SXin LI u_int32_t outbound_write_pointer; 36227a7bc959SXin LI u_int16_t error, doneq_index; 36237a7bc959SXin LI 36247a7bc959SXin LI polling_ccb_retry: 36257a7bc959SXin LI poll_count++; 36267a7bc959SXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 36277a7bc959SXin LI while(1) { 36287a7bc959SXin LI outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow; 36297a7bc959SXin LI doneq_index = phbdmu->doneq_index; 36307a7bc959SXin LI if ((outbound_write_pointer & 0xFF) == (doneq_index & 0xFF)) { 36317a7bc959SXin LI if(poll_srb_done) { 36327a7bc959SXin LI break;/*chip FIFO no ccb for completion already*/ 36337a7bc959SXin LI } else { 36347a7bc959SXin LI UDELAY(25000); 36357a7bc959SXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 36367a7bc959SXin LI break; 36377a7bc959SXin LI } 36387a7bc959SXin LI if (acb->srboutstandingcount == 0) { 36397a7bc959SXin LI break; 36407a7bc959SXin LI } 36417a7bc959SXin LI goto polling_ccb_retry; 36427a7bc959SXin LI } 36437a7bc959SXin LI } 36447a7bc959SXin LI doneq_index = arcmsr_get_doneq_index(phbdmu); 36457a7bc959SXin LI flag_srb = phbdmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow; 36467a7bc959SXin LI /* check if command done with no error*/ 36477a7bc959SXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/ 36487a7bc959SXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 36497a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_read_pointer, doneq_index); 36507a7bc959SXin LI if (poll_srb != NULL) 36517a7bc959SXin LI poll_srb_done = (srb == poll_srb) ? 1:0; 36527a7bc959SXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 36537a7bc959SXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3654123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n" 3655123055f0SNathan Whitehorn , acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 36567a7bc959SXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 36577a7bc959SXin LI arcmsr_srb_complete(srb, 1); 36587a7bc959SXin LI continue; 36597a7bc959SXin LI } 36607a7bc959SXin LI printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n" 36617a7bc959SXin LI , acb->pci_unit, srb, acb->srboutstandingcount); 36627a7bc959SXin LI continue; 36637a7bc959SXin LI } 36647a7bc959SXin LI arcmsr_report_srb_state(acb, srb, error); 36657a7bc959SXin LI } /*drain reply FIFO*/ 36667a7bc959SXin LI } 36677a7bc959SXin LI /* 36687a7bc959SXin LI ********************************************************************** 3669a1103e04SXin LI ** 3670a1103e04SXin LI ********************************************************************** 3671a1103e04SXin LI */ 3672a1103e04SXin LI static void arcmsr_polling_hbe_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 3673a1103e04SXin LI { 3674a1103e04SXin LI struct CommandControlBlock *srb; 3675a1103e04SXin LI u_int32_t poll_srb_done=0, poll_count=0, doneq_index; 3676a1103e04SXin LI u_int16_t error, cmdSMID; 3677a1103e04SXin LI 3678a1103e04SXin LI polling_ccb_retry: 3679a1103e04SXin LI poll_count++; 3680a1103e04SXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 3681a1103e04SXin LI while(1) { 3682a1103e04SXin LI doneq_index = acb->doneq_index; 3683a1103e04SXin LI if((CHIP_REG_READ32(HBE_MessageUnit, 0, reply_post_producer_index) & 0xFFFF) == doneq_index) { 3684a1103e04SXin LI if(poll_srb_done) { 3685a1103e04SXin LI break;/*chip FIFO no ccb for completion already*/ 3686a1103e04SXin LI } else { 3687a1103e04SXin LI UDELAY(25000); 3688a1103e04SXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 3689a1103e04SXin LI break; 3690a1103e04SXin LI } 3691a1103e04SXin LI if (acb->srboutstandingcount == 0) { 3692a1103e04SXin LI break; 3693a1103e04SXin LI } 3694a1103e04SXin LI goto polling_ccb_retry; 3695a1103e04SXin LI } 3696a1103e04SXin LI } 3697a1103e04SXin LI cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID; 3698a1103e04SXin LI doneq_index++; 3699a1103e04SXin LI if (doneq_index >= acb->completionQ_entry) 3700a1103e04SXin LI doneq_index = 0; 3701a1103e04SXin LI acb->doneq_index = doneq_index; 3702a1103e04SXin LI srb = acb->psrb_pool[cmdSMID]; 3703a1103e04SXin LI error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 3704a1103e04SXin LI if (poll_srb != NULL) 3705a1103e04SXin LI poll_srb_done = (srb == poll_srb) ? 1:0; 3706a1103e04SXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 3707a1103e04SXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3708a1103e04SXin LI printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n" 3709a1103e04SXin LI , acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 3710a1103e04SXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 3711a1103e04SXin LI arcmsr_srb_complete(srb, 1); 3712a1103e04SXin LI continue; 3713a1103e04SXin LI } 3714a1103e04SXin LI printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n" 3715a1103e04SXin LI , acb->pci_unit, srb, acb->srboutstandingcount); 3716a1103e04SXin LI continue; 3717a1103e04SXin LI } 3718a1103e04SXin LI arcmsr_report_srb_state(acb, srb, error); 3719a1103e04SXin LI } /*drain reply FIFO*/ 3720a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, reply_post_producer_index, doneq_index); 3721a1103e04SXin LI } 3722a1103e04SXin LI /* 3723a1103e04SXin LI ********************************************************************** 372444f05562SScott Long ********************************************************************** 372544f05562SScott Long */ 372644f05562SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 372744f05562SScott Long { 372844f05562SScott Long switch (acb->adapter_type) { 372944f05562SScott Long case ACB_ADAPTER_TYPE_A: { 373044f05562SScott Long arcmsr_polling_hba_srbdone(acb, poll_srb); 373144f05562SScott Long } 373244f05562SScott Long break; 373344f05562SScott Long case ACB_ADAPTER_TYPE_B: { 373444f05562SScott Long arcmsr_polling_hbb_srbdone(acb, poll_srb); 373544f05562SScott Long } 373644f05562SScott Long break; 3737d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3738d74001adSXin LI arcmsr_polling_hbc_srbdone(acb, poll_srb); 3739d74001adSXin LI } 3740d74001adSXin LI break; 37417a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 37427a7bc959SXin LI arcmsr_polling_hbd_srbdone(acb, poll_srb); 37437a7bc959SXin LI } 37447a7bc959SXin LI break; 3745a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 3746a1103e04SXin LI arcmsr_polling_hbe_srbdone(acb, poll_srb); 3747a1103e04SXin LI } 3748a1103e04SXin LI break; 374944f05562SScott Long } 375044f05562SScott Long } 375144f05562SScott Long /* 375244f05562SScott Long ********************************************************************** 375344f05562SScott Long ********************************************************************** 375444f05562SScott Long */ 375544f05562SScott Long static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) 3756ad6d6297SScott Long { 3757ad6d6297SScott Long char *acb_firm_model = acb->firm_model; 3758ad6d6297SScott Long char *acb_firm_version = acb->firm_version; 3759d74001adSXin LI char *acb_device_map = acb->device_map; 3760d74001adSXin LI size_t iop_firm_model = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3761d74001adSXin LI size_t iop_firm_version = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3762d74001adSXin LI size_t iop_device_map = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 3763ad6d6297SScott Long int i; 3764ad6d6297SScott Long 376544f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 376644f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 3767d74001adSXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 3768ad6d6297SScott Long } 3769ad6d6297SScott Long i = 0; 3770ad6d6297SScott Long while(i < 8) { 377144f05562SScott Long *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 3772ad6d6297SScott Long /* 8 bytes firm_model, 15, 60-67*/ 3773ad6d6297SScott Long acb_firm_model++; 3774ad6d6297SScott Long i++; 3775ad6d6297SScott Long } 3776ad6d6297SScott Long i=0; 3777ad6d6297SScott Long while(i < 16) { 377844f05562SScott Long *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 3779ad6d6297SScott Long /* 16 bytes firm_version, 17, 68-83*/ 3780ad6d6297SScott Long acb_firm_version++; 3781ad6d6297SScott Long i++; 3782ad6d6297SScott Long } 3783d74001adSXin LI i=0; 3784d74001adSXin LI while(i < 16) { 3785d74001adSXin LI *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 3786d74001adSXin LI acb_device_map++; 3787d74001adSXin LI i++; 3788d74001adSXin LI } 37891e7d660aSXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 3790d74001adSXin LI acb->firm_request_len = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3791d74001adSXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3792d74001adSXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3793d74001adSXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3794d74001adSXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3795abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD) 3796abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1; 3797abfdbca9SXin LI else 3798abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 3799ad6d6297SScott Long } 3800ad6d6297SScott Long /* 3801ad6d6297SScott Long ********************************************************************** 380244f05562SScott Long ********************************************************************** 380344f05562SScott Long */ 380444f05562SScott Long static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) 380544f05562SScott Long { 3806b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 380744f05562SScott Long char *acb_firm_model = acb->firm_model; 380844f05562SScott Long char *acb_firm_version = acb->firm_version; 3809d74001adSXin LI char *acb_device_map = acb->device_map; 3810d74001adSXin LI size_t iop_firm_model = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3811d74001adSXin LI size_t iop_firm_version = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3812d74001adSXin LI size_t iop_device_map = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 381344f05562SScott Long int i; 381444f05562SScott Long 3815b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG); 381644f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 3817d74001adSXin LI printf( "arcmsr%d: wait" "'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 381844f05562SScott Long } 381944f05562SScott Long i = 0; 382044f05562SScott Long while(i < 8) { 382144f05562SScott Long *acb_firm_model = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_model+i); 382244f05562SScott Long /* 8 bytes firm_model, 15, 60-67*/ 382344f05562SScott Long acb_firm_model++; 382444f05562SScott Long i++; 382544f05562SScott Long } 382644f05562SScott Long i = 0; 382744f05562SScott Long while(i < 16) { 382844f05562SScott Long *acb_firm_version = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_version+i); 382944f05562SScott Long /* 16 bytes firm_version, 17, 68-83*/ 383044f05562SScott Long acb_firm_version++; 383144f05562SScott Long i++; 383244f05562SScott Long } 3833d74001adSXin LI i = 0; 3834d74001adSXin LI while(i < 16) { 3835d74001adSXin LI *acb_device_map = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_device_map+i); 3836d74001adSXin LI acb_device_map++; 3837d74001adSXin LI i++; 3838d74001adSXin LI } 38391e7d660aSXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 3840d74001adSXin LI acb->firm_request_len = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3841d74001adSXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3842d74001adSXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3843d74001adSXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3844d74001adSXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3845abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_HBB_POSTQUEUE) 3846abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_HBB_POSTQUEUE - 1; 3847abfdbca9SXin LI else 3848abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 3849d74001adSXin LI } 3850d74001adSXin LI /* 3851d74001adSXin LI ********************************************************************** 3852d74001adSXin LI ********************************************************************** 3853d74001adSXin LI */ 3854d74001adSXin LI static void arcmsr_get_hbc_config(struct AdapterControlBlock *acb) 3855d74001adSXin LI { 3856d74001adSXin LI char *acb_firm_model = acb->firm_model; 3857d74001adSXin LI char *acb_firm_version = acb->firm_version; 3858d74001adSXin LI char *acb_device_map = acb->device_map; 3859d74001adSXin LI size_t iop_firm_model = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3860d74001adSXin LI size_t iop_firm_version = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3861d74001adSXin LI size_t iop_device_map = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 3862d74001adSXin LI int i; 3863d74001adSXin LI 3864d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 3865d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 3866d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 3867d74001adSXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 3868d74001adSXin LI } 3869d74001adSXin LI i = 0; 3870d74001adSXin LI while(i < 8) { 3871d74001adSXin LI *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 3872d74001adSXin LI /* 8 bytes firm_model, 15, 60-67*/ 3873d74001adSXin LI acb_firm_model++; 3874d74001adSXin LI i++; 3875d74001adSXin LI } 3876d74001adSXin LI i = 0; 3877d74001adSXin LI while(i < 16) { 3878d74001adSXin LI *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 3879d74001adSXin LI /* 16 bytes firm_version, 17, 68-83*/ 3880d74001adSXin LI acb_firm_version++; 3881d74001adSXin LI i++; 3882d74001adSXin LI } 3883d74001adSXin LI i = 0; 3884d74001adSXin LI while(i < 16) { 3885d74001adSXin LI *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 3886d74001adSXin LI acb_device_map++; 3887d74001adSXin LI i++; 3888d74001adSXin LI } 38891e7d660aSXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 3890d74001adSXin LI acb->firm_request_len = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3891d74001adSXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3892d74001adSXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3893d74001adSXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3894d74001adSXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3895abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD) 3896abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1; 3897abfdbca9SXin LI else 3898abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 389944f05562SScott Long } 390044f05562SScott Long /* 390144f05562SScott Long ********************************************************************** 390244f05562SScott Long ********************************************************************** 390344f05562SScott Long */ 39047a7bc959SXin LI static void arcmsr_get_hbd_config(struct AdapterControlBlock *acb) 39057a7bc959SXin LI { 39067a7bc959SXin LI char *acb_firm_model = acb->firm_model; 39077a7bc959SXin LI char *acb_firm_version = acb->firm_version; 39087a7bc959SXin LI char *acb_device_map = acb->device_map; 39097a7bc959SXin LI size_t iop_firm_model = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 39107a7bc959SXin LI size_t iop_firm_version = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 39117a7bc959SXin LI size_t iop_device_map = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 39127a7bc959SXin LI int i; 39137a7bc959SXin LI 39147a7bc959SXin LI if(CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) 39157a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR); 39167a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 39177a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 39187a7bc959SXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 39197a7bc959SXin LI } 39207a7bc959SXin LI i = 0; 39217a7bc959SXin LI while(i < 8) { 39227a7bc959SXin LI *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 39237a7bc959SXin LI /* 8 bytes firm_model, 15, 60-67*/ 39247a7bc959SXin LI acb_firm_model++; 39257a7bc959SXin LI i++; 39267a7bc959SXin LI } 39277a7bc959SXin LI i = 0; 39287a7bc959SXin LI while(i < 16) { 39297a7bc959SXin LI *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 39307a7bc959SXin LI /* 16 bytes firm_version, 17, 68-83*/ 39317a7bc959SXin LI acb_firm_version++; 39327a7bc959SXin LI i++; 39337a7bc959SXin LI } 39347a7bc959SXin LI i = 0; 39357a7bc959SXin LI while(i < 16) { 39367a7bc959SXin LI *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 39377a7bc959SXin LI acb_device_map++; 39387a7bc959SXin LI i++; 39397a7bc959SXin LI } 39401e7d660aSXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 3941b23a1998SXin LI acb->firm_request_len = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3942b23a1998SXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3943b23a1998SXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3944b23a1998SXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 39457a7bc959SXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3946abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_HBD_POSTQUEUE) 3947abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_HBD_POSTQUEUE - 1; 3948abfdbca9SXin LI else 3949abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 39507a7bc959SXin LI } 39517a7bc959SXin LI /* 39527a7bc959SXin LI ********************************************************************** 39537a7bc959SXin LI ********************************************************************** 39547a7bc959SXin LI */ 3955a1103e04SXin LI static void arcmsr_get_hbe_config(struct AdapterControlBlock *acb) 3956a1103e04SXin LI { 3957a1103e04SXin LI char *acb_firm_model = acb->firm_model; 3958a1103e04SXin LI char *acb_firm_version = acb->firm_version; 3959a1103e04SXin LI char *acb_device_map = acb->device_map; 3960a1103e04SXin LI size_t iop_firm_model = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3961a1103e04SXin LI size_t iop_firm_version = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3962a1103e04SXin LI size_t iop_device_map = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 3963a1103e04SXin LI int i; 3964a1103e04SXin LI 3965a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 3966a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 3967a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 3968a1103e04SXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) { 3969a1103e04SXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 3970a1103e04SXin LI } 3971a1103e04SXin LI 3972a1103e04SXin LI i = 0; 3973a1103e04SXin LI while(i < 8) { 3974a1103e04SXin LI *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 3975a1103e04SXin LI /* 8 bytes firm_model, 15, 60-67*/ 3976a1103e04SXin LI acb_firm_model++; 3977a1103e04SXin LI i++; 3978a1103e04SXin LI } 3979a1103e04SXin LI i = 0; 3980a1103e04SXin LI while(i < 16) { 3981a1103e04SXin LI *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 3982a1103e04SXin LI /* 16 bytes firm_version, 17, 68-83*/ 3983a1103e04SXin LI acb_firm_version++; 3984a1103e04SXin LI i++; 3985a1103e04SXin LI } 3986a1103e04SXin LI i = 0; 3987a1103e04SXin LI while(i < 16) { 3988a1103e04SXin LI *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 3989a1103e04SXin LI acb_device_map++; 3990a1103e04SXin LI i++; 3991a1103e04SXin LI } 3992a1103e04SXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 3993a1103e04SXin LI acb->firm_request_len = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3994a1103e04SXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3995a1103e04SXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3996a1103e04SXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3997a1103e04SXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3998a1103e04SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD) 3999a1103e04SXin LI acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1; 4000a1103e04SXin LI else 4001a1103e04SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 4002a1103e04SXin LI } 4003a1103e04SXin LI /* 4004a1103e04SXin LI ********************************************************************** 4005a1103e04SXin LI ********************************************************************** 4006a1103e04SXin LI */ 400744f05562SScott Long static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) 400844f05562SScott Long { 400944f05562SScott Long switch (acb->adapter_type) { 401044f05562SScott Long case ACB_ADAPTER_TYPE_A: { 401144f05562SScott Long arcmsr_get_hba_config(acb); 401244f05562SScott Long } 401344f05562SScott Long break; 401444f05562SScott Long case ACB_ADAPTER_TYPE_B: { 401544f05562SScott Long arcmsr_get_hbb_config(acb); 401644f05562SScott Long } 401744f05562SScott Long break; 4018d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 4019d74001adSXin LI arcmsr_get_hbc_config(acb); 4020d74001adSXin LI } 4021d74001adSXin LI break; 40227a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 40237a7bc959SXin LI arcmsr_get_hbd_config(acb); 40247a7bc959SXin LI } 40257a7bc959SXin LI break; 4026a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 4027a1103e04SXin LI arcmsr_get_hbe_config(acb); 4028a1103e04SXin LI } 4029a1103e04SXin LI break; 403044f05562SScott Long } 403144f05562SScott Long } 403244f05562SScott Long /* 403344f05562SScott Long ********************************************************************** 403444f05562SScott Long ********************************************************************** 403544f05562SScott Long */ 403644f05562SScott Long static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb) 403744f05562SScott Long { 403844f05562SScott Long int timeout=0; 403944f05562SScott Long 404044f05562SScott Long switch (acb->adapter_type) { 404144f05562SScott Long case ACB_ADAPTER_TYPE_A: { 4042d74001adSXin LI while ((CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) 404344f05562SScott Long { 404444f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 404544f05562SScott Long { 4046d74001adSXin LI printf( "arcmsr%d:timed out waiting for firmware \n", acb->pci_unit); 404744f05562SScott Long return; 404844f05562SScott Long } 404944f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 405044f05562SScott Long } 405144f05562SScott Long } 405244f05562SScott Long break; 405344f05562SScott Long case ACB_ADAPTER_TYPE_B: { 4054b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 4055b23a1998SXin LI while ((READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & ARCMSR_MESSAGE_FIRMWARE_OK) == 0) 405644f05562SScott Long { 405744f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 405844f05562SScott Long { 4059d74001adSXin LI printf( "arcmsr%d: timed out waiting for firmware \n", acb->pci_unit); 406044f05562SScott Long return; 406144f05562SScott Long } 406244f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 406344f05562SScott Long } 4064b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 4065d74001adSXin LI } 4066d74001adSXin LI break; 4067d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 4068d74001adSXin LI while ((CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0) 4069d74001adSXin LI { 4070d74001adSXin LI if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 4071d74001adSXin LI { 4072d74001adSXin LI printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit); 4073d74001adSXin LI return; 4074d74001adSXin LI } 4075d74001adSXin LI UDELAY(15000); /* wait 15 milli-seconds */ 4076d74001adSXin LI } 407744f05562SScott Long } 407844f05562SScott Long break; 40797a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 40807a7bc959SXin LI while ((CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBDMU_MESSAGE_FIRMWARE_OK) == 0) 40817a7bc959SXin LI { 40827a7bc959SXin LI if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 40837a7bc959SXin LI { 40847a7bc959SXin LI printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit); 40857a7bc959SXin LI return; 40867a7bc959SXin LI } 40877a7bc959SXin LI UDELAY(15000); /* wait 15 milli-seconds */ 40887a7bc959SXin LI } 40897a7bc959SXin LI } 40907a7bc959SXin LI break; 4091a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 4092a1103e04SXin LI while ((CHIP_REG_READ32(HBE_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBEMU_MESSAGE_FIRMWARE_OK) == 0) 4093a1103e04SXin LI { 4094a1103e04SXin LI if (timeout++ > 4000) /* (4000*15)/1000 = 60 sec */ 4095a1103e04SXin LI { 4096a1103e04SXin LI printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit); 4097a1103e04SXin LI return; 4098a1103e04SXin LI } 4099a1103e04SXin LI UDELAY(15000); /* wait 15 milli-seconds */ 4100a1103e04SXin LI } 4101a1103e04SXin LI } 4102a1103e04SXin LI break; 410344f05562SScott Long } 410444f05562SScott Long } 410544f05562SScott Long /* 410644f05562SScott Long ********************************************************************** 410744f05562SScott Long ********************************************************************** 410844f05562SScott Long */ 410944f05562SScott Long static void arcmsr_clear_doorbell_queue_buffer( struct AdapterControlBlock *acb) 411044f05562SScott Long { 4111d74001adSXin LI u_int32_t outbound_doorbell; 4112d74001adSXin LI 411344f05562SScott Long switch (acb->adapter_type) { 411444f05562SScott Long case ACB_ADAPTER_TYPE_A: { 411544f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 4116d74001adSXin LI outbound_doorbell = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell); 4117d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, outbound_doorbell); /*clear doorbell interrupt */ 4118d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 411944f05562SScott Long } 412044f05562SScott Long break; 412144f05562SScott Long case ACB_ADAPTER_TYPE_B: { 4122b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 4123*fc5ef1caSXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN);/*clear interrupt and message state*/ 4124b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 412544f05562SScott Long /* let IOP know data has been read */ 412644f05562SScott Long } 412744f05562SScott Long break; 4128d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 4129d74001adSXin LI /* empty doorbell Qbuffer if door bell ringed */ 4130d74001adSXin LI outbound_doorbell = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); 4131d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell); /*clear doorbell interrupt */ 4132d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK); 41337a7bc959SXin LI CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell_clear); /* Dummy read to force pci flush */ 41347a7bc959SXin LI CHIP_REG_READ32(HBC_MessageUnit, 0, inbound_doorbell); /* Dummy read to force pci flush */ 41357a7bc959SXin LI } 41367a7bc959SXin LI break; 41377a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 41387a7bc959SXin LI /* empty doorbell Qbuffer if door bell ringed */ 41397a7bc959SXin LI outbound_doorbell = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell); 41407a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, outbound_doorbell); /*clear doorbell interrupt */ 41417a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ); 4142d74001adSXin LI } 4143d74001adSXin LI break; 4144a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 4145a1103e04SXin LI /* empty doorbell Qbuffer if door bell ringed */ 4146a1103e04SXin LI acb->in_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell); 4147a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /*clear doorbell interrupt */ 4148a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK; 4149a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 4150a1103e04SXin LI } 4151a1103e04SXin LI break; 415244f05562SScott Long } 415344f05562SScott Long } 415444f05562SScott Long /* 415544f05562SScott Long ************************************************************************ 415644f05562SScott Long ************************************************************************ 415744f05562SScott Long */ 415844f05562SScott Long static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb) 415944f05562SScott Long { 416044f05562SScott Long unsigned long srb_phyaddr; 416144f05562SScott Long u_int32_t srb_phyaddr_hi32; 41627a7bc959SXin LI u_int32_t srb_phyaddr_lo32; 416344f05562SScott Long 416444f05562SScott Long /* 416544f05562SScott Long ******************************************************************** 416644f05562SScott Long ** here we need to tell iop 331 our freesrb.HighPart 416744f05562SScott Long ** if freesrb.HighPart is not zero 416844f05562SScott Long ******************************************************************** 416944f05562SScott Long */ 4170d74001adSXin LI srb_phyaddr = (unsigned long) acb->srb_phyaddr.phyaddr; 4171d74001adSXin LI srb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high; 41727a7bc959SXin LI srb_phyaddr_lo32 = acb->srb_phyaddr.B.phyadd_low; 417344f05562SScott Long switch (acb->adapter_type) { 417444f05562SScott Long case ACB_ADAPTER_TYPE_A: { 417544f05562SScott Long if(srb_phyaddr_hi32 != 0) { 4176d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 4177d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 4178d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 417944f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 4180d74001adSXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 418144f05562SScott Long return FALSE; 418244f05562SScott Long } 418344f05562SScott Long } 418444f05562SScott Long } 418544f05562SScott Long break; 418644f05562SScott Long /* 418744f05562SScott Long *********************************************************************** 418844f05562SScott Long ** if adapter type B, set window of "post command Q" 418944f05562SScott Long *********************************************************************** 419044f05562SScott Long */ 419144f05562SScott Long case ACB_ADAPTER_TYPE_B: { 419244f05562SScott Long u_int32_t post_queue_phyaddr; 419344f05562SScott Long struct HBB_MessageUnit *phbbmu; 419444f05562SScott Long 419544f05562SScott Long phbbmu = (struct HBB_MessageUnit *)acb->pmu; 419644f05562SScott Long phbbmu->postq_index = 0; 419744f05562SScott Long phbbmu->doneq_index = 0; 4198b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_SET_POST_WINDOW); 419944f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 4200d74001adSXin LI printf( "arcmsr%d: 'set window of post command Q' timeout\n", acb->pci_unit); 420144f05562SScott Long return FALSE; 420244f05562SScott Long } 420322f2616bSXin LI post_queue_phyaddr = srb_phyaddr + ARCMSR_SRBS_POOL_SIZE 420444f05562SScott Long + offsetof(struct HBB_MessageUnit, post_qbuffer); 4205d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */ 4206d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1], srb_phyaddr_hi32); /* normal should be zero */ 4207d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ size (256+8)*4 */ 4208d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3], post_queue_phyaddr+1056); /* doneQ size (256+8)*4 */ 4209d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4], 1056); /* srb maxQ size must be --> [(256+8)*4] */ 4210b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_SET_CONFIG); 421144f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 421244f05562SScott Long printf( "arcmsr%d: 'set command Q window' timeout \n", acb->pci_unit); 421344f05562SScott Long return FALSE; 421444f05562SScott Long } 4215b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_START_DRIVER_MODE); 421644f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 421744f05562SScott Long printf( "arcmsr%d: 'start diver mode' timeout \n", acb->pci_unit); 421844f05562SScott Long return FALSE; 421944f05562SScott Long } 422044f05562SScott Long } 422144f05562SScott Long break; 4222d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 4223d74001adSXin LI if(srb_phyaddr_hi32 != 0) { 4224d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 4225d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 4226d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 4227d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 4228d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 4229d74001adSXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 4230d74001adSXin LI return FALSE; 4231d74001adSXin LI } 4232d74001adSXin LI } 4233d74001adSXin LI } 4234d74001adSXin LI break; 42357a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 42367a7bc959SXin LI u_int32_t post_queue_phyaddr, done_queue_phyaddr; 42377a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu; 42387a7bc959SXin LI 42397a7bc959SXin LI phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 42407a7bc959SXin LI phbdmu->postq_index = 0; 42417a7bc959SXin LI phbdmu->doneq_index = 0x40FF; 42427a7bc959SXin LI post_queue_phyaddr = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE 42437a7bc959SXin LI + offsetof(struct HBD_MessageUnit0, post_qbuffer); 42447a7bc959SXin LI done_queue_phyaddr = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE 42457a7bc959SXin LI + offsetof(struct HBD_MessageUnit0, done_qbuffer); 42467a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */ 42477a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 42487a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ base */ 42497a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[3], done_queue_phyaddr); /* doneQ base */ 42507a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[4], 0x100); 42517a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 42527a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 42537a7bc959SXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 42547a7bc959SXin LI return FALSE; 42557a7bc959SXin LI } 42567a7bc959SXin LI } 42577a7bc959SXin LI break; 4258a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 4259a1103e04SXin LI u_int32_t cdb_phyaddr_lo32; 4260a1103e04SXin LI cdb_phyaddr_lo32 = srb_phyaddr_lo32 + offsetof(struct CommandControlBlock, arcmsr_cdb); 4261a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 4262a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[1], ARCMSR_SIGNATURE_1884); 4263a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[2], cdb_phyaddr_lo32); 4264a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[3], srb_phyaddr_hi32); 4265a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[4], SRB_SIZE); 4266a1103e04SXin LI cdb_phyaddr_lo32 = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE; 4267a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[5], cdb_phyaddr_lo32); 4268a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[6], srb_phyaddr_hi32); 4269a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[7], COMPLETION_Q_POOL_SIZE); 4270a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 4271a1103e04SXin LI acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE; 4272a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell); 4273a1103e04SXin LI if(!arcmsr_hbe_wait_msgint_ready(acb)) { 4274a1103e04SXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 4275a1103e04SXin LI return FALSE; 4276a1103e04SXin LI } 4277a1103e04SXin LI } 4278a1103e04SXin LI break; 427944f05562SScott Long } 4280dac36688SXin LI return (TRUE); 428144f05562SScott Long } 428244f05562SScott Long /* 428344f05562SScott Long ************************************************************************ 428444f05562SScott Long ************************************************************************ 428544f05562SScott Long */ 428644f05562SScott Long static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb) 428744f05562SScott Long { 4288a1103e04SXin LI if (acb->adapter_type == ACB_ADAPTER_TYPE_B) 428944f05562SScott Long { 4290b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 4291b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_ACTIVE_EOI_MODE); 429244f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 4293d74001adSXin LI printf( "arcmsr%d: 'iop enable eoi mode' timeout \n", acb->pci_unit); 429444f05562SScott Long return; 429544f05562SScott Long } 429644f05562SScott Long } 429744f05562SScott Long } 429844f05562SScott Long /* 429944f05562SScott Long ********************************************************************** 4300ad6d6297SScott Long ********************************************************************** 4301ad6d6297SScott Long */ 4302ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb) 4303ad6d6297SScott Long { 430444f05562SScott Long u_int32_t intmask_org; 4305ad6d6297SScott Long 430644f05562SScott Long /* disable all outbound interrupt */ 430744f05562SScott Long intmask_org = arcmsr_disable_allintr(acb); 430844f05562SScott Long arcmsr_wait_firmware_ready(acb); 430944f05562SScott Long arcmsr_iop_confirm(acb); 4310ad6d6297SScott Long arcmsr_get_firmware_spec(acb); 431144f05562SScott Long /*start background rebuild*/ 4312ad6d6297SScott Long arcmsr_start_adapter_bgrb(acb); 431344f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 431444f05562SScott Long arcmsr_clear_doorbell_queue_buffer(acb); 431544f05562SScott Long arcmsr_enable_eoi_mode(acb); 431644f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 431744f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 4318ad6d6297SScott Long acb->acb_flags |= ACB_F_IOP_INITED; 4319ad6d6297SScott Long } 4320ad6d6297SScott Long /* 4321ad6d6297SScott Long ********************************************************************** 4322f1c579b1SScott Long ********************************************************************** 4323f1c579b1SScott Long */ 4324231c8b71SXin LI static void arcmsr_map_free_srb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 4325f1c579b1SScott Long { 4326ad6d6297SScott Long struct AdapterControlBlock *acb = arg; 4327ad6d6297SScott Long struct CommandControlBlock *srb_tmp; 432844f05562SScott Long u_int32_t i; 4329ad6d6297SScott Long unsigned long srb_phyaddr = (unsigned long)segs->ds_addr; 4330f1c579b1SScott Long 4331d74001adSXin LI acb->srb_phyaddr.phyaddr = srb_phyaddr; 43327a7bc959SXin LI srb_tmp = (struct CommandControlBlock *)acb->uncacheptr; 4333ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 433444f05562SScott Long if(bus_dmamap_create(acb->dm_segs_dmat, 433544f05562SScott Long /*flags*/0, &srb_tmp->dm_segs_dmamap) != 0) { 4336ad6d6297SScott Long acb->acb_flags |= ACB_F_MAPFREESRB_FAILD; 433744f05562SScott Long printf("arcmsr%d:" 433844f05562SScott Long " srb dmamap bus_dmamap_create error\n", acb->pci_unit); 4339ad6d6297SScott Long return; 4340ad6d6297SScott Long } 4341a1103e04SXin LI if((acb->adapter_type == ACB_ADAPTER_TYPE_C) || (acb->adapter_type == ACB_ADAPTER_TYPE_D) 4342a1103e04SXin LI || (acb->adapter_type == ACB_ADAPTER_TYPE_E)) 43437a7bc959SXin LI { 43447a7bc959SXin LI srb_tmp->cdb_phyaddr_low = srb_phyaddr; 43457a7bc959SXin LI srb_tmp->cdb_phyaddr_high = (u_int32_t)((srb_phyaddr >> 16) >> 16); 43467a7bc959SXin LI } 43477a7bc959SXin LI else 43487a7bc959SXin LI srb_tmp->cdb_phyaddr_low = srb_phyaddr >> 5; 4349ad6d6297SScott Long srb_tmp->acb = acb; 4350a1103e04SXin LI srb_tmp->smid = i << 16; 4351ad6d6297SScott Long acb->srbworkingQ[i] = acb->psrb_pool[i] = srb_tmp; 435222f2616bSXin LI srb_phyaddr = srb_phyaddr + SRB_SIZE; 435322f2616bSXin LI srb_tmp = (struct CommandControlBlock *)((unsigned long)srb_tmp + SRB_SIZE); 4354ad6d6297SScott Long } 4355*fc5ef1caSXin LI if (acb->adapter_type == ACB_ADAPTER_TYPE_E) 4356a1103e04SXin LI acb->pCompletionQ = (pCompletion_Q)srb_tmp; 4357ad6d6297SScott Long acb->vir2phy_offset = (unsigned long)srb_tmp - (unsigned long)srb_phyaddr; 4358f1c579b1SScott Long } 4359f1c579b1SScott Long /* 4360f1c579b1SScott Long ************************************************************************ 4361f1c579b1SScott Long ************************************************************************ 4362f1c579b1SScott Long */ 4363ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb) 4364f1c579b1SScott Long { 4365f1c579b1SScott Long /* remove the control device */ 4366ad6d6297SScott Long if(acb->ioctl_dev != NULL) { 4367ad6d6297SScott Long destroy_dev(acb->ioctl_dev); 4368f1c579b1SScott Long } 4369ad6d6297SScott Long bus_dmamap_unload(acb->srb_dmat, acb->srb_dmamap); 4370ad6d6297SScott Long bus_dmamap_destroy(acb->srb_dmat, acb->srb_dmamap); 4371ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 4372ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 4373ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 4374f1c579b1SScott Long } 4375f1c579b1SScott Long /* 4376f1c579b1SScott Long ************************************************************************ 4377f1c579b1SScott Long ************************************************************************ 4378f1c579b1SScott Long */ 43797a7bc959SXin LI static void arcmsr_mutex_init(struct AdapterControlBlock *acb) 43807a7bc959SXin LI { 43817a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->isr_lock, "arcmsr isr lock"); 43827a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->srb_lock, "arcmsr srb lock"); 43837a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->postDone_lock, "arcmsr postQ lock"); 43847a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->qbuffer_lock, "arcmsr RW buffer lock"); 43857a7bc959SXin LI } 43867a7bc959SXin LI /* 43877a7bc959SXin LI ************************************************************************ 43887a7bc959SXin LI ************************************************************************ 43897a7bc959SXin LI */ 43907a7bc959SXin LI static void arcmsr_mutex_destroy(struct AdapterControlBlock *acb) 43917a7bc959SXin LI { 43927a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 43937a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->postDone_lock); 43947a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->srb_lock); 43957a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->isr_lock); 43967a7bc959SXin LI } 43977a7bc959SXin LI /* 43987a7bc959SXin LI ************************************************************************ 43997a7bc959SXin LI ************************************************************************ 44007a7bc959SXin LI */ 4401ad6d6297SScott Long static u_int32_t arcmsr_initialize(device_t dev) 4402f1c579b1SScott Long { 4403ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 4404ad6d6297SScott Long u_int16_t pci_command; 440544f05562SScott Long int i, j,max_coherent_size; 4406dac36688SXin LI u_int32_t vendor_dev_id; 4407f1c579b1SScott Long 4408dac36688SXin LI vendor_dev_id = pci_get_devid(dev); 4409dac36688SXin LI acb->vendor_device_id = vendor_dev_id; 4410224a78aeSXin LI acb->sub_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2); 4411dac36688SXin LI switch (vendor_dev_id) { 4412dac36688SXin LI case PCIDevVenIDARC1880: 4413dac36688SXin LI case PCIDevVenIDARC1882: 4414dac36688SXin LI case PCIDevVenIDARC1213: 4415dac36688SXin LI case PCIDevVenIDARC1223: { 4416d74001adSXin LI acb->adapter_type = ACB_ADAPTER_TYPE_C; 4417*fc5ef1caSXin LI if ((acb->sub_device_id == ARECA_SUB_DEV_ID_1883) || 4418*fc5ef1caSXin LI (acb->sub_device_id == ARECA_SUB_DEV_ID_1216) || 4419*fc5ef1caSXin LI (acb->sub_device_id == ARECA_SUB_DEV_ID_1226)) 4420224a78aeSXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_12G; 4421224a78aeSXin LI else 4422dac36688SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_6G; 4423d74001adSXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE; 4424d74001adSXin LI } 4425d74001adSXin LI break; 4426a1103e04SXin LI case PCIDevVenIDARC1884: 4427a1103e04SXin LI acb->adapter_type = ACB_ADAPTER_TYPE_E; 4428a1103e04SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_12G; 4429a1103e04SXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + COMPLETION_Q_POOL_SIZE; 4430a1103e04SXin LI acb->completionQ_entry = COMPLETION_Q_POOL_SIZE / sizeof(struct deliver_completeQ); 4431a1103e04SXin LI break; 44327a7bc959SXin LI case PCIDevVenIDARC1214: { 44337a7bc959SXin LI acb->adapter_type = ACB_ADAPTER_TYPE_D; 44347a7bc959SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_6G; 44357a7bc959SXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBD_MessageUnit0)); 44367a7bc959SXin LI } 44377a7bc959SXin LI break; 4438231c8b71SXin LI case PCIDevVenIDARC1200: 443944f05562SScott Long case PCIDevVenIDARC1201: { 444044f05562SScott Long acb->adapter_type = ACB_ADAPTER_TYPE_B; 4441dac36688SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_3G; 4442d74001adSXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBB_MessageUnit)); 444344f05562SScott Long } 444444f05562SScott Long break; 4445b23a1998SXin LI case PCIDevVenIDARC1203: { 4446b23a1998SXin LI acb->adapter_type = ACB_ADAPTER_TYPE_B; 4447b23a1998SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_6G; 4448b23a1998SXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBB_MessageUnit)); 4449b23a1998SXin LI } 4450b23a1998SXin LI break; 445144f05562SScott Long case PCIDevVenIDARC1110: 445244f05562SScott Long case PCIDevVenIDARC1120: 445344f05562SScott Long case PCIDevVenIDARC1130: 445444f05562SScott Long case PCIDevVenIDARC1160: 445544f05562SScott Long case PCIDevVenIDARC1170: 445644f05562SScott Long case PCIDevVenIDARC1210: 445744f05562SScott Long case PCIDevVenIDARC1220: 445844f05562SScott Long case PCIDevVenIDARC1230: 4459231c8b71SXin LI case PCIDevVenIDARC1231: 446044f05562SScott Long case PCIDevVenIDARC1260: 4461231c8b71SXin LI case PCIDevVenIDARC1261: 446244f05562SScott Long case PCIDevVenIDARC1270: 446344f05562SScott Long case PCIDevVenIDARC1280: 4464d74001adSXin LI case PCIDevVenIDARC1212: 4465d74001adSXin LI case PCIDevVenIDARC1222: 446644f05562SScott Long case PCIDevVenIDARC1380: 446744f05562SScott Long case PCIDevVenIDARC1381: 446844f05562SScott Long case PCIDevVenIDARC1680: 446944f05562SScott Long case PCIDevVenIDARC1681: { 447044f05562SScott Long acb->adapter_type = ACB_ADAPTER_TYPE_A; 4471dac36688SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_3G; 447244f05562SScott Long max_coherent_size = ARCMSR_SRBS_POOL_SIZE; 447344f05562SScott Long } 447444f05562SScott Long break; 447544f05562SScott Long default: { 447644f05562SScott Long printf("arcmsr%d:" 447744f05562SScott Long " unknown RAID adapter type \n", device_get_unit(dev)); 447844f05562SScott Long return ENOMEM; 447944f05562SScott Long } 448044f05562SScott Long } 44817a7bc959SXin LI #if __FreeBSD_version >= 700000 4482b6f97155SScott Long if(bus_dma_tag_create( /*PCI parent*/ bus_get_dma_tag(dev), 44837a7bc959SXin LI #else 44847a7bc959SXin LI if(bus_dma_tag_create( /*PCI parent*/ NULL, 44857a7bc959SXin LI #endif 4486f1c579b1SScott Long /*alignemnt*/ 1, 4487f1c579b1SScott Long /*boundary*/ 0, 4488701d9f1fSScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 4489f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 4490f1c579b1SScott Long /*filter*/ NULL, 4491f1c579b1SScott Long /*filterarg*/ NULL, 4492f1c579b1SScott Long /*maxsize*/ BUS_SPACE_MAXSIZE_32BIT, 4493f1c579b1SScott Long /*nsegments*/ BUS_SPACE_UNRESTRICTED, 4494f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 4495f1c579b1SScott Long /*flags*/ 0, 449622f2616bSXin LI #if __FreeBSD_version >= 501102 4497f1c579b1SScott Long /*lockfunc*/ NULL, 4498f1c579b1SScott Long /*lockarg*/ NULL, 4499f1c579b1SScott Long #endif 4500231c8b71SXin LI &acb->parent_dmat) != 0) 4501f1c579b1SScott Long { 450244f05562SScott Long printf("arcmsr%d: parent_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 4503f1c579b1SScott Long return ENOMEM; 4504f1c579b1SScott Long } 4505231c8b71SXin LI 4506f1c579b1SScott Long /* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */ 4507ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 4508f1c579b1SScott Long /*alignment*/ 1, 4509f1c579b1SScott Long /*boundary*/ 0, 451022f2616bSXin LI #ifdef PAE 451122f2616bSXin LI /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 451222f2616bSXin LI #else 4513f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 451422f2616bSXin LI #endif 4515f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 4516f1c579b1SScott Long /*filter*/ NULL, 4517f1c579b1SScott Long /*filterarg*/ NULL, 4518231c8b71SXin LI /*maxsize*/ ARCMSR_MAX_SG_ENTRIES * PAGE_SIZE * ARCMSR_MAX_FREESRB_NUM, 4519f1c579b1SScott Long /*nsegments*/ ARCMSR_MAX_SG_ENTRIES, 4520f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 4521ad6d6297SScott Long /*flags*/ 0, 452222f2616bSXin LI #if __FreeBSD_version >= 501102 4523f1c579b1SScott Long /*lockfunc*/ busdma_lock_mutex, 45247a7bc959SXin LI /*lockarg*/ &acb->isr_lock, 4525f1c579b1SScott Long #endif 4526231c8b71SXin LI &acb->dm_segs_dmat) != 0) 4527f1c579b1SScott Long { 4528ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 452944f05562SScott Long printf("arcmsr%d: dm_segs_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 4530f1c579b1SScott Long return ENOMEM; 4531f1c579b1SScott Long } 4532231c8b71SXin LI 4533ad6d6297SScott Long /* DMA tag for our srb structures.... Allocate the freesrb memory */ 4534ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 453544f05562SScott Long /*alignment*/ 0x20, 4536f1c579b1SScott Long /*boundary*/ 0, 4537f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 4538f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 4539f1c579b1SScott Long /*filter*/ NULL, 4540f1c579b1SScott Long /*filterarg*/ NULL, 454144f05562SScott Long /*maxsize*/ max_coherent_size, 4542f1c579b1SScott Long /*nsegments*/ 1, 4543f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 4544701d9f1fSScott Long /*flags*/ 0, 454522f2616bSXin LI #if __FreeBSD_version >= 501102 4546f1c579b1SScott Long /*lockfunc*/ NULL, 4547f1c579b1SScott Long /*lockarg*/ NULL, 4548f1c579b1SScott Long #endif 4549231c8b71SXin LI &acb->srb_dmat) != 0) 4550f1c579b1SScott Long { 4551ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 4552ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 455344f05562SScott Long printf("arcmsr%d: srb_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 4554f1c579b1SScott Long return ENXIO; 4555f1c579b1SScott Long } 4556f1c579b1SScott Long /* Allocation for our srbs */ 4557d74001adSXin LI if(bus_dmamem_alloc(acb->srb_dmat, (void **)&acb->uncacheptr, BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &acb->srb_dmamap) != 0) { 4558ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 4559ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 4560ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 456144f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamem_alloc failure!\n", device_get_unit(dev)); 4562f1c579b1SScott Long return ENXIO; 4563f1c579b1SScott Long } 4564f1c579b1SScott Long /* And permanently map them */ 4565231c8b71SXin LI if(bus_dmamap_load(acb->srb_dmat, acb->srb_dmamap, acb->uncacheptr, max_coherent_size, arcmsr_map_free_srb, acb, /*flags*/0)) { 4566ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 4567ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 4568ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 456944f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamap_load failure!\n", device_get_unit(dev)); 4570f1c579b1SScott Long return ENXIO; 4571f1c579b1SScott Long } 4572f1c579b1SScott Long pci_command = pci_read_config(dev, PCIR_COMMAND, 2); 4573f1c579b1SScott Long pci_command |= PCIM_CMD_BUSMASTEREN; 4574f1c579b1SScott Long pci_command |= PCIM_CMD_PERRESPEN; 4575f1c579b1SScott Long pci_command |= PCIM_CMD_MWRICEN; 4576c68534f1SScott Long /* Enable Busmaster */ 4577f1c579b1SScott Long pci_write_config(dev, PCIR_COMMAND, pci_command, 2); 457844f05562SScott Long switch(acb->adapter_type) { 457944f05562SScott Long case ACB_ADAPTER_TYPE_A: { 458044f05562SScott Long u_int32_t rid0 = PCIR_BAR(0); 458144f05562SScott Long vm_offset_t mem_base0; 458244f05562SScott Long 4583eff83876SJustin Hibbits acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid0, RF_ACTIVE); 458444f05562SScott Long if(acb->sys_res_arcmsr[0] == NULL) { 4585ad6d6297SScott Long arcmsr_free_resource(acb); 4586d74001adSXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 4587f1c579b1SScott Long return ENOMEM; 4588f1c579b1SScott Long } 458944f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 4590ad6d6297SScott Long arcmsr_free_resource(acb); 4591d74001adSXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 4592f1c579b1SScott Long return ENXIO; 4593f1c579b1SScott Long } 459444f05562SScott Long mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 459544f05562SScott Long if(mem_base0 == 0) { 4596ad6d6297SScott Long arcmsr_free_resource(acb); 4597d74001adSXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 4598f1c579b1SScott Long return ENXIO; 4599f1c579b1SScott Long } 460044f05562SScott Long acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 460144f05562SScott Long acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 460244f05562SScott Long acb->pmu = (struct MessageUnit_UNION *)mem_base0; 4603*fc5ef1caSXin LI acb->rid[0] = rid0; 460444f05562SScott Long } 460544f05562SScott Long break; 460644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 460744f05562SScott Long struct HBB_MessageUnit *phbbmu; 460844f05562SScott Long struct CommandControlBlock *freesrb; 460944f05562SScott Long u_int32_t rid[]={ PCIR_BAR(0), PCIR_BAR(2) }; 461044f05562SScott Long vm_offset_t mem_base[]={0,0}; 461144f05562SScott Long for(i=0; i < 2; i++) { 4612*fc5ef1caSXin LI acb->sys_res_arcmsr[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid[i], RF_ACTIVE); 461344f05562SScott Long if(acb->sys_res_arcmsr[i] == NULL) { 461444f05562SScott Long arcmsr_free_resource(acb); 4615d74001adSXin LI printf("arcmsr%d: bus_alloc_resource %d failure!\n", device_get_unit(dev), i); 461644f05562SScott Long return ENOMEM; 461744f05562SScott Long } 461844f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[i]) <= 0) { 461944f05562SScott Long arcmsr_free_resource(acb); 4620d74001adSXin LI printf("arcmsr%d: rman_get_start %d failure!\n", device_get_unit(dev), i); 462144f05562SScott Long return ENXIO; 462244f05562SScott Long } 462344f05562SScott Long mem_base[i] = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[i]); 462444f05562SScott Long if(mem_base[i] == 0) { 462544f05562SScott Long arcmsr_free_resource(acb); 4626d74001adSXin LI printf("arcmsr%d: rman_get_virtual %d failure!\n", device_get_unit(dev), i); 462744f05562SScott Long return ENXIO; 462844f05562SScott Long } 462944f05562SScott Long acb->btag[i] = rman_get_bustag(acb->sys_res_arcmsr[i]); 463044f05562SScott Long acb->bhandle[i] = rman_get_bushandle(acb->sys_res_arcmsr[i]); 463144f05562SScott Long } 463244f05562SScott Long freesrb = (struct CommandControlBlock *)acb->uncacheptr; 463322f2616bSXin LI acb->pmu = (struct MessageUnit_UNION *)((unsigned long)freesrb+ARCMSR_SRBS_POOL_SIZE); 463444f05562SScott Long phbbmu = (struct HBB_MessageUnit *)acb->pmu; 463544f05562SScott Long phbbmu->hbb_doorbell = (struct HBB_DOORBELL *)mem_base[0]; 463644f05562SScott Long phbbmu->hbb_rwbuffer = (struct HBB_RWBUFFER *)mem_base[1]; 4637b23a1998SXin LI if (vendor_dev_id == PCIDevVenIDARC1203) { 4638b23a1998SXin LI phbbmu->drv2iop_doorbell = offsetof(struct HBB_DOORBELL_1203, drv2iop_doorbell); 4639b23a1998SXin LI phbbmu->drv2iop_doorbell_mask = offsetof(struct HBB_DOORBELL_1203, drv2iop_doorbell_mask); 4640b23a1998SXin LI phbbmu->iop2drv_doorbell = offsetof(struct HBB_DOORBELL_1203, iop2drv_doorbell); 4641b23a1998SXin LI phbbmu->iop2drv_doorbell_mask = offsetof(struct HBB_DOORBELL_1203, iop2drv_doorbell_mask); 4642b23a1998SXin LI } else { 4643b23a1998SXin LI phbbmu->drv2iop_doorbell = offsetof(struct HBB_DOORBELL, drv2iop_doorbell); 4644b23a1998SXin LI phbbmu->drv2iop_doorbell_mask = offsetof(struct HBB_DOORBELL, drv2iop_doorbell_mask); 4645b23a1998SXin LI phbbmu->iop2drv_doorbell = offsetof(struct HBB_DOORBELL, iop2drv_doorbell); 4646b23a1998SXin LI phbbmu->iop2drv_doorbell_mask = offsetof(struct HBB_DOORBELL, iop2drv_doorbell_mask); 4647b23a1998SXin LI } 4648*fc5ef1caSXin LI acb->rid[0] = rid[0]; 4649*fc5ef1caSXin LI acb->rid[1] = rid[1]; 465044f05562SScott Long } 465144f05562SScott Long break; 4652d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 4653d74001adSXin LI u_int32_t rid0 = PCIR_BAR(1); 4654d74001adSXin LI vm_offset_t mem_base0; 4655d74001adSXin LI 4656eff83876SJustin Hibbits acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid0, RF_ACTIVE); 4657d74001adSXin LI if(acb->sys_res_arcmsr[0] == NULL) { 4658d74001adSXin LI arcmsr_free_resource(acb); 4659d74001adSXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 4660d74001adSXin LI return ENOMEM; 4661d74001adSXin LI } 4662d74001adSXin LI if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 4663d74001adSXin LI arcmsr_free_resource(acb); 4664d74001adSXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 4665d74001adSXin LI return ENXIO; 4666d74001adSXin LI } 4667d74001adSXin LI mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 4668d74001adSXin LI if(mem_base0 == 0) { 4669d74001adSXin LI arcmsr_free_resource(acb); 4670d74001adSXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 4671d74001adSXin LI return ENXIO; 4672d74001adSXin LI } 4673d74001adSXin LI acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 4674d74001adSXin LI acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 4675d74001adSXin LI acb->pmu = (struct MessageUnit_UNION *)mem_base0; 4676*fc5ef1caSXin LI acb->rid[0] = rid0; 4677d74001adSXin LI } 4678d74001adSXin LI break; 46797a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 46807a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu; 46817a7bc959SXin LI u_int32_t rid0 = PCIR_BAR(0); 46827a7bc959SXin LI vm_offset_t mem_base0; 46837a7bc959SXin LI 4684eff83876SJustin Hibbits acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid0, RF_ACTIVE); 46857a7bc959SXin LI if(acb->sys_res_arcmsr[0] == NULL) { 46867a7bc959SXin LI arcmsr_free_resource(acb); 46877a7bc959SXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 46887a7bc959SXin LI return ENOMEM; 46897a7bc959SXin LI } 46907a7bc959SXin LI if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 46917a7bc959SXin LI arcmsr_free_resource(acb); 46927a7bc959SXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 46937a7bc959SXin LI return ENXIO; 46947a7bc959SXin LI } 46957a7bc959SXin LI mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 46967a7bc959SXin LI if(mem_base0 == 0) { 46977a7bc959SXin LI arcmsr_free_resource(acb); 46987a7bc959SXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 46997a7bc959SXin LI return ENXIO; 47007a7bc959SXin LI } 47017a7bc959SXin LI acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 47027a7bc959SXin LI acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 47037a7bc959SXin LI acb->pmu = (struct MessageUnit_UNION *)((unsigned long)acb->uncacheptr+ARCMSR_SRBS_POOL_SIZE); 47047a7bc959SXin LI phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 47057a7bc959SXin LI phbdmu->phbdmu = (struct HBD_MessageUnit *)mem_base0; 4706*fc5ef1caSXin LI acb->rid[0] = rid0; 4707a1103e04SXin LI } 4708a1103e04SXin LI break; 4709a1103e04SXin LI case ACB_ADAPTER_TYPE_E: { 4710a1103e04SXin LI u_int32_t rid0 = PCIR_BAR(1); 4711a1103e04SXin LI vm_offset_t mem_base0; 4712a1103e04SXin LI 4713*fc5ef1caSXin LI acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid0, RF_ACTIVE); 4714a1103e04SXin LI if(acb->sys_res_arcmsr[0] == NULL) { 4715a1103e04SXin LI arcmsr_free_resource(acb); 4716a1103e04SXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 4717a1103e04SXin LI return ENOMEM; 4718a1103e04SXin LI } 4719a1103e04SXin LI if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 4720a1103e04SXin LI arcmsr_free_resource(acb); 4721a1103e04SXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 4722a1103e04SXin LI return ENXIO; 4723a1103e04SXin LI } 4724a1103e04SXin LI mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 4725a1103e04SXin LI if(mem_base0 == 0) { 4726a1103e04SXin LI arcmsr_free_resource(acb); 4727a1103e04SXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 4728a1103e04SXin LI return ENXIO; 4729a1103e04SXin LI } 4730a1103e04SXin LI acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 4731a1103e04SXin LI acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 4732a1103e04SXin LI acb->pmu = (struct MessageUnit_UNION *)mem_base0; 4733a1103e04SXin LI acb->doneq_index = 0; 4734a1103e04SXin LI acb->in_doorbell = 0; 4735a1103e04SXin LI acb->out_doorbell = 0; 4736*fc5ef1caSXin LI acb->rid[0] = rid0; 4737a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /*clear interrupt*/ 4738a1103e04SXin LI CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, ARCMSR_HBEMU_DOORBELL_SYNC); /* synchronize doorbell to 0 */ 47397a7bc959SXin LI } 47407a7bc959SXin LI break; 474144f05562SScott Long } 4742ad6d6297SScott Long if(acb->acb_flags & ACB_F_MAPFREESRB_FAILD) { 4743ad6d6297SScott Long arcmsr_free_resource(acb); 474444f05562SScott Long printf("arcmsr%d: map free srb failure!\n", device_get_unit(dev)); 4745f1c579b1SScott Long return ENXIO; 4746f1c579b1SScott Long } 4747d74001adSXin LI acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_RQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ); 4748ad6d6297SScott Long acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; 4749ad6d6297SScott Long /* 4750ad6d6297SScott Long ******************************************************************** 4751ad6d6297SScott Long ** init raid volume state 4752ad6d6297SScott Long ******************************************************************** 4753ad6d6297SScott Long */ 4754ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_TARGETID; i++) { 4755ad6d6297SScott Long for(j=0; j < ARCMSR_MAX_TARGETLUN; j++) { 475644f05562SScott Long acb->devstate[i][j] = ARECA_RAID_GONE; 4757ad6d6297SScott Long } 4758ad6d6297SScott Long } 4759ad6d6297SScott Long arcmsr_iop_init(acb); 4760f1c579b1SScott Long return(0); 4761f1c579b1SScott Long } 4762a1103e04SXin LI 4763a1103e04SXin LI static int arcmsr_setup_msix(struct AdapterControlBlock *acb) 4764a1103e04SXin LI { 4765a1103e04SXin LI int i; 4766a1103e04SXin LI 4767a1103e04SXin LI for (i = 0; i < acb->msix_vectors; i++) { 4768*fc5ef1caSXin LI acb->irq_id[i] = 1 + i; 4769a1103e04SXin LI acb->irqres[i] = bus_alloc_resource_any(acb->pci_dev, 4770a1103e04SXin LI SYS_RES_IRQ, &acb->irq_id[i], RF_ACTIVE); 4771a1103e04SXin LI if (acb->irqres[i] == NULL) { 4772a1103e04SXin LI printf("arcmsr: Can't allocate MSI-X resource\n"); 4773a1103e04SXin LI goto irq_alloc_failed; 4774a1103e04SXin LI } 4775a1103e04SXin LI if (bus_setup_intr(acb->pci_dev, acb->irqres[i], 4776a1103e04SXin LI INTR_MPSAFE | INTR_TYPE_CAM, NULL, arcmsr_intr_handler, 4777a1103e04SXin LI acb, &acb->ih[i])) { 4778a1103e04SXin LI printf("arcmsr: Cannot set up MSI-X interrupt handler\n"); 4779a1103e04SXin LI goto irq_alloc_failed; 4780a1103e04SXin LI } 4781a1103e04SXin LI } 4782a1103e04SXin LI printf("arcmsr: MSI-X INT enabled\n"); 4783a1103e04SXin LI acb->acb_flags |= ACB_F_MSIX_ENABLED; 4784a1103e04SXin LI return TRUE; 4785a1103e04SXin LI 4786a1103e04SXin LI irq_alloc_failed: 4787a1103e04SXin LI arcmsr_teardown_intr(acb->pci_dev, acb); 4788a1103e04SXin LI return FALSE; 4789a1103e04SXin LI } 4790a1103e04SXin LI 4791f1c579b1SScott Long /* 4792f1c579b1SScott Long ************************************************************************ 4793f1c579b1SScott Long ************************************************************************ 4794f1c579b1SScott Long */ 4795f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev) 4796f1c579b1SScott Long { 4797ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 4798ad6d6297SScott Long u_int32_t unit=device_get_unit(dev); 4799f1c579b1SScott Long struct ccb_setasync csa; 4800f1c579b1SScott Long struct cam_devq *devq; /* Device Queue to use for this SIM */ 4801f1c579b1SScott Long struct resource *irqres; 4802f1c579b1SScott Long 4803ad6d6297SScott Long if(acb == NULL) { 4804ad6d6297SScott Long printf("arcmsr%d: cannot allocate softc\n", unit); 4805ad6d6297SScott Long return (ENOMEM); 4806ad6d6297SScott Long } 48077a7bc959SXin LI arcmsr_mutex_init(acb); 48081e7d660aSXin LI acb->pci_dev = dev; 48091e7d660aSXin LI acb->pci_unit = unit; 4810ad6d6297SScott Long if(arcmsr_initialize(dev)) { 4811ad6d6297SScott Long printf("arcmsr%d: initialize failure!\n", unit); 4812a1103e04SXin LI goto initialize_failed; 4813f1c579b1SScott Long } 4814f1c579b1SScott Long /* After setting up the adapter, map our interrupt */ 4815a1103e04SXin LI acb->msix_vectors = ARCMSR_NUM_MSIX_VECTORS; 4816a1103e04SXin LI if (pci_alloc_msix(dev, &acb->msix_vectors) == 0) { 4817a1103e04SXin LI if (arcmsr_setup_msix(acb) == TRUE) 4818a1103e04SXin LI goto irqx; 4819a1103e04SXin LI } 4820*fc5ef1caSXin LI acb->irq_id[0] = 0; 4821a1103e04SXin LI irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &acb->irq_id[0], RF_SHAREABLE | RF_ACTIVE); 4822ad6d6297SScott Long if(irqres == NULL || 482344f05562SScott Long #if __FreeBSD_version >= 700025 4824a1103e04SXin LI bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, NULL, arcmsr_intr_handler, acb, &acb->ih[0])) { 482544f05562SScott Long #else 4826a1103e04SXin LI bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, arcmsr_intr_handler, acb, &acb->ih[0])) { 482744f05562SScott Long #endif 4828f1c579b1SScott Long printf("arcmsr%d: unable to register interrupt handler!\n", unit); 4829a1103e04SXin LI goto setup_intr_failed; 4830f1c579b1SScott Long } 4831a1103e04SXin LI acb->irqres[0] = irqres; 4832a1103e04SXin LI irqx: 4833f1c579b1SScott Long /* 4834f1c579b1SScott Long * Now let the CAM generic SCSI layer find the SCSI devices on 4835f1c579b1SScott Long * the bus * start queue to reset to the idle loop. * 4836f1c579b1SScott Long * Create device queue of SIM(s) * (MAX_START_JOB - 1) : 4837f1c579b1SScott Long * max_sim_transactions 4838f1c579b1SScott Long */ 4839224a78aeSXin LI devq = cam_simq_alloc(acb->maxOutstanding); 4840ad6d6297SScott Long if(devq == NULL) { 4841ad6d6297SScott Long printf("arcmsr%d: cam_simq_alloc failure!\n", unit); 4842a1103e04SXin LI goto simq_alloc_failed; 4843f1c579b1SScott Long } 484444f05562SScott Long #if __FreeBSD_version >= 700025 48457a7bc959SXin LI acb->psim = cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, &acb->isr_lock, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq); 484644f05562SScott Long #else 4847d74001adSXin LI acb->psim = cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq); 484844f05562SScott Long #endif 4849ad6d6297SScott Long if(acb->psim == NULL) { 4850ad6d6297SScott Long printf("arcmsr%d: cam_sim_alloc failure!\n", unit); 4851a1103e04SXin LI goto sim_alloc_failed; 4852f1c579b1SScott Long } 48537a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 4854f40b4cabSScott Long #if __FreeBSD_version >= 700044 4855b50569b7SScott Long if(xpt_bus_register(acb->psim, dev, 0) != CAM_SUCCESS) { 485644f05562SScott Long #else 485744f05562SScott Long if(xpt_bus_register(acb->psim, 0) != CAM_SUCCESS) { 485844f05562SScott Long #endif 4859ad6d6297SScott Long printf("arcmsr%d: xpt_bus_register failure!\n", unit); 4860a1103e04SXin LI goto xpt_bus_failed; 4861f1c579b1SScott Long } 4862d74001adSXin LI if(xpt_create_path(&acb->ppath, /* periph */ NULL, cam_sim_path(acb->psim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 4863ad6d6297SScott Long printf("arcmsr%d: xpt_create_path failure!\n", unit); 4864a1103e04SXin LI goto xpt_path_failed; 4865f1c579b1SScott Long } 4866f1c579b1SScott Long /* 4867f1c579b1SScott Long **************************************************** 4868f1c579b1SScott Long */ 4869ad6d6297SScott Long xpt_setup_ccb(&csa.ccb_h, acb->ppath, /*priority*/5); 4870f1c579b1SScott Long csa.ccb_h.func_code = XPT_SASYNC_CB; 4871f1c579b1SScott Long csa.event_enable = AC_FOUND_DEVICE|AC_LOST_DEVICE; 4872f1c579b1SScott Long csa.callback = arcmsr_async; 4873ad6d6297SScott Long csa.callback_arg = acb->psim; 4874f1c579b1SScott Long xpt_action((union ccb *)&csa); 48757a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 4876f1c579b1SScott Long /* Create the control device. */ 4877d74001adSXin LI acb->ioctl_dev = make_dev(&arcmsr_cdevsw, unit, UID_ROOT, GID_WHEEL /* GID_OPERATOR */, S_IRUSR | S_IWUSR, "arcmsr%d", unit); 4878d74001adSXin LI 4879f1c579b1SScott Long #if __FreeBSD_version < 503000 4880ad6d6297SScott Long acb->ioctl_dev->si_drv1 = acb; 4881f1c579b1SScott Long #endif 4882f1c579b1SScott Long #if __FreeBSD_version > 500005 4883ad6d6297SScott Long (void)make_dev_alias(acb->ioctl_dev, "arc%d", unit); 4884f1c579b1SScott Long #endif 488522f2616bSXin LI arcmsr_callout_init(&acb->devmap_callout); 4886d74001adSXin LI callout_reset(&acb->devmap_callout, 60 * hz, arcmsr_polling_devmap, acb); 4887dac36688SXin LI return (0); 4888a1103e04SXin LI xpt_path_failed: 4889a1103e04SXin LI xpt_bus_deregister(cam_sim_path(acb->psim)); 4890a1103e04SXin LI xpt_bus_failed: 4891a1103e04SXin LI cam_sim_free(acb->psim, /* free_simq */ TRUE); 4892a1103e04SXin LI sim_alloc_failed: 4893a1103e04SXin LI cam_simq_free(devq); 4894a1103e04SXin LI simq_alloc_failed: 4895a1103e04SXin LI arcmsr_teardown_intr(dev, acb); 4896a1103e04SXin LI setup_intr_failed: 4897a1103e04SXin LI arcmsr_free_resource(acb); 4898a1103e04SXin LI initialize_failed: 4899a1103e04SXin LI arcmsr_mutex_destroy(acb); 4900a1103e04SXin LI return ENXIO; 4901f1c579b1SScott Long } 490222f2616bSXin LI 4903f1c579b1SScott Long /* 4904f1c579b1SScott Long ************************************************************************ 4905f1c579b1SScott Long ************************************************************************ 4906f1c579b1SScott Long */ 4907f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev) 4908f1c579b1SScott Long { 4909ad6d6297SScott Long u_int32_t id; 4910224a78aeSXin LI u_int16_t sub_device_id; 4911ad6d6297SScott Long static char buf[256]; 49121e7d660aSXin LI char x_type[]={"unknown"}; 4913ad6d6297SScott Long char *type; 4914ad6d6297SScott Long int raid6 = 1; 4915ad6d6297SScott Long 4916ad6d6297SScott Long if (pci_get_vendor(dev) != PCI_VENDOR_ID_ARECA) { 4917ad6d6297SScott Long return (ENXIO); 4918ad6d6297SScott Long } 4919224a78aeSXin LI sub_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2); 4920ad6d6297SScott Long switch(id = pci_get_devid(dev)) { 4921f1c579b1SScott Long case PCIDevVenIDARC1110: 4922231c8b71SXin LI case PCIDevVenIDARC1200: 492344f05562SScott Long case PCIDevVenIDARC1201: 4924231c8b71SXin LI case PCIDevVenIDARC1210: 4925ad6d6297SScott Long raid6 = 0; 4926ad6d6297SScott Long /*FALLTHRU*/ 4927ad6d6297SScott Long case PCIDevVenIDARC1120: 4928ad6d6297SScott Long case PCIDevVenIDARC1130: 4929ad6d6297SScott Long case PCIDevVenIDARC1160: 4930ad6d6297SScott Long case PCIDevVenIDARC1170: 4931f1c579b1SScott Long case PCIDevVenIDARC1220: 4932f1c579b1SScott Long case PCIDevVenIDARC1230: 4933231c8b71SXin LI case PCIDevVenIDARC1231: 4934f1c579b1SScott Long case PCIDevVenIDARC1260: 4935231c8b71SXin LI case PCIDevVenIDARC1261: 4936ad6d6297SScott Long case PCIDevVenIDARC1270: 4937ad6d6297SScott Long case PCIDevVenIDARC1280: 49387a7bc959SXin LI type = "SATA 3G"; 4939ad6d6297SScott Long break; 4940d74001adSXin LI case PCIDevVenIDARC1212: 4941d74001adSXin LI case PCIDevVenIDARC1222: 4942ad6d6297SScott Long case PCIDevVenIDARC1380: 4943ad6d6297SScott Long case PCIDevVenIDARC1381: 4944ad6d6297SScott Long case PCIDevVenIDARC1680: 4945ad6d6297SScott Long case PCIDevVenIDARC1681: 4946d74001adSXin LI type = "SAS 3G"; 4947d74001adSXin LI break; 4948d74001adSXin LI case PCIDevVenIDARC1880: 4949dac36688SXin LI case PCIDevVenIDARC1882: 4950dac36688SXin LI case PCIDevVenIDARC1213: 4951dac36688SXin LI case PCIDevVenIDARC1223: 4952*fc5ef1caSXin LI if ((sub_device_id == ARECA_SUB_DEV_ID_1883) || 4953*fc5ef1caSXin LI (sub_device_id == ARECA_SUB_DEV_ID_1216) || 4954*fc5ef1caSXin LI (sub_device_id == ARECA_SUB_DEV_ID_1226)) 4955224a78aeSXin LI type = "SAS 12G"; 4956224a78aeSXin LI else 4957d74001adSXin LI type = "SAS 6G"; 4958ad6d6297SScott Long break; 4959a1103e04SXin LI case PCIDevVenIDARC1884: 4960a1103e04SXin LI type = "SAS 12G"; 4961a1103e04SXin LI break; 49627a7bc959SXin LI case PCIDevVenIDARC1214: 4963b23a1998SXin LI case PCIDevVenIDARC1203: 49647a7bc959SXin LI type = "SATA 6G"; 49657a7bc959SXin LI break; 4966ad6d6297SScott Long default: 4967231c8b71SXin LI type = x_type; 49681e7d660aSXin LI raid6 = 0; 4969ad6d6297SScott Long break; 4970f1c579b1SScott Long } 4971231c8b71SXin LI if(type == x_type) 4972231c8b71SXin LI return(ENXIO); 49731e7d660aSXin LI sprintf(buf, "Areca %s Host Adapter RAID Controller %s\n%s\n", 49741e7d660aSXin LI type, raid6 ? "(RAID6 capable)" : "", ARCMSR_DRIVER_VERSION); 4975ad6d6297SScott Long device_set_desc_copy(dev, buf); 497603389298SXin LI return (BUS_PROBE_DEFAULT); 4977f1c579b1SScott Long } 4978f1c579b1SScott Long /* 4979f1c579b1SScott Long ************************************************************************ 4980f1c579b1SScott Long ************************************************************************ 4981f1c579b1SScott Long */ 4982f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev) 4983f1c579b1SScott Long { 498444f05562SScott Long u_int32_t i; 4985ad6d6297SScott Long u_int32_t intmask_org; 4986ad6d6297SScott Long struct CommandControlBlock *srb; 4987ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 4988f1c579b1SScott Long 4989f1c579b1SScott Long /* stop adapter background rebuild */ 49907a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 499144f05562SScott Long /* disable all outbound interrupt */ 499244f05562SScott Long intmask_org = arcmsr_disable_allintr(acb); 4993ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 4994ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 4995f1c579b1SScott Long /* abort all outstanding command */ 4996ad6d6297SScott Long acb->acb_flags |= ACB_F_SCSISTOPADAPTER; 4997ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOP_INITED; 4998ad6d6297SScott Long if(acb->srboutstandingcount != 0) { 499944f05562SScott Long /*clear and abort all outbound posted Q*/ 500044f05562SScott Long arcmsr_done4abort_postqueue(acb); 500144f05562SScott Long /* talk to iop 331 outstanding command aborted*/ 5002ad6d6297SScott Long arcmsr_abort_allcmd(acb); 5003ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 5004ad6d6297SScott Long srb = acb->psrb_pool[i]; 500522f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) { 500622f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 5007ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 5008ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 5009f1c579b1SScott Long } 5010f1c579b1SScott Long } 5011f1c579b1SScott Long } 501222f2616bSXin LI acb->srboutstandingcount = 0; 5013ad6d6297SScott Long acb->workingsrb_doneindex = 0; 5014ad6d6297SScott Long acb->workingsrb_startindex = 0; 501522f2616bSXin LI acb->pktRequestCount = 0; 501622f2616bSXin LI acb->pktReturnCount = 0; 50177a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 5018f2aa0e9fSWarner Losh return (0); 5019f1c579b1SScott Long } 5020f1c579b1SScott Long /* 5021f1c579b1SScott Long ************************************************************************ 5022f1c579b1SScott Long ************************************************************************ 5023f1c579b1SScott Long */ 5024*fc5ef1caSXin LI static void arcmsr_teardown_intr(device_t dev, struct AdapterControlBlock *acb) 5025a1103e04SXin LI { 5026a1103e04SXin LI int i; 5027a1103e04SXin LI 5028a1103e04SXin LI if (acb->acb_flags & ACB_F_MSIX_ENABLED) { 5029a1103e04SXin LI for (i = 0; i < acb->msix_vectors; i++) { 5030a1103e04SXin LI if (acb->ih[i]) 5031a1103e04SXin LI bus_teardown_intr(dev, acb->irqres[i], acb->ih[i]); 5032a1103e04SXin LI if (acb->irqres[i] != NULL) 5033a1103e04SXin LI bus_release_resource(dev, SYS_RES_IRQ, 5034a1103e04SXin LI acb->irq_id[i], acb->irqres[i]); 5035a1103e04SXin LI 5036a1103e04SXin LI acb->ih[i] = NULL; 5037a1103e04SXin LI } 5038a1103e04SXin LI pci_release_msi(dev); 5039a1103e04SXin LI } else { 5040a1103e04SXin LI if (acb->ih[0]) 5041a1103e04SXin LI bus_teardown_intr(dev, acb->irqres[0], acb->ih[0]); 5042a1103e04SXin LI if (acb->irqres[0] != NULL) 5043a1103e04SXin LI bus_release_resource(dev, SYS_RES_IRQ, 5044a1103e04SXin LI acb->irq_id[0], acb->irqres[0]); 5045a1103e04SXin LI acb->ih[0] = NULL; 5046a1103e04SXin LI } 5047a1103e04SXin LI 5048a1103e04SXin LI } 5049a1103e04SXin LI /* 5050a1103e04SXin LI ************************************************************************ 5051a1103e04SXin LI ************************************************************************ 5052a1103e04SXin LI */ 5053f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev) 5054f1c579b1SScott Long { 5055ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 505644f05562SScott Long int i; 5057f1c579b1SScott Long 5058d74001adSXin LI callout_stop(&acb->devmap_callout); 5059a1103e04SXin LI arcmsr_teardown_intr(dev, acb); 5060f1c579b1SScott Long arcmsr_shutdown(dev); 5061ad6d6297SScott Long arcmsr_free_resource(acb); 506244f05562SScott Long for(i=0; (acb->sys_res_arcmsr[i]!=NULL) && (i<2); i++) { 5063*fc5ef1caSXin LI bus_release_resource(dev, SYS_RES_MEMORY, acb->rid[i], acb->sys_res_arcmsr[i]); 506444f05562SScott Long } 50657a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 5066ad6d6297SScott Long xpt_async(AC_LOST_DEVICE, acb->ppath, NULL); 5067ad6d6297SScott Long xpt_free_path(acb->ppath); 5068ad6d6297SScott Long xpt_bus_deregister(cam_sim_path(acb->psim)); 5069ad6d6297SScott Long cam_sim_free(acb->psim, TRUE); 50707a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 50717a7bc959SXin LI arcmsr_mutex_destroy(acb); 5072f1c579b1SScott Long return (0); 5073f1c579b1SScott Long } 5074f1c579b1SScott Long 507522f2616bSXin LI #ifdef ARCMSR_DEBUG1 507622f2616bSXin LI static void arcmsr_dump_data(struct AdapterControlBlock *acb) 507722f2616bSXin LI { 507822f2616bSXin LI if((acb->pktRequestCount - acb->pktReturnCount) == 0) 507922f2616bSXin LI return; 508022f2616bSXin LI printf("Command Request Count =0x%x\n",acb->pktRequestCount); 508122f2616bSXin LI printf("Command Return Count =0x%x\n",acb->pktReturnCount); 508222f2616bSXin LI printf("Command (Req-Rtn) Count =0x%x\n",(acb->pktRequestCount - acb->pktReturnCount)); 508322f2616bSXin LI printf("Queued Command Count =0x%x\n",acb->srboutstandingcount); 508422f2616bSXin LI } 508522f2616bSXin LI #endif 5086