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 75*abfdbca9SXin LI ** 1.20.00.26 12/14/2012 Ching Huang Added support ARC1214,1224,1264,1284 76*abfdbca9SXin LI ** 1.20.00.27 05/06/2013 Ching Huang Fixed out standing cmd full on ARC-12x4 77f1c579b1SScott Long ****************************************************************************************** 78f1c579b1SScott Long */ 794b7ec270SMarius Strobl 804b7ec270SMarius Strobl #include <sys/cdefs.h> 814b7ec270SMarius Strobl __FBSDID("$FreeBSD$"); 824b7ec270SMarius Strobl 8322f2616bSXin LI #if 0 8422f2616bSXin LI #define ARCMSR_DEBUG1 1 8522f2616bSXin LI #endif 86f1c579b1SScott Long #include <sys/param.h> 87f1c579b1SScott Long #include <sys/systm.h> 88f1c579b1SScott Long #include <sys/malloc.h> 89f1c579b1SScott Long #include <sys/kernel.h> 90f1c579b1SScott Long #include <sys/bus.h> 91f1c579b1SScott Long #include <sys/queue.h> 92f1c579b1SScott Long #include <sys/stat.h> 93f1c579b1SScott Long #include <sys/devicestat.h> 94f1c579b1SScott Long #include <sys/kthread.h> 95f1c579b1SScott Long #include <sys/module.h> 96f1c579b1SScott Long #include <sys/proc.h> 97f1c579b1SScott Long #include <sys/lock.h> 98f1c579b1SScott Long #include <sys/sysctl.h> 99f1c579b1SScott Long #include <sys/poll.h> 100f1c579b1SScott Long #include <sys/ioccom.h> 101f1c579b1SScott Long #include <vm/vm.h> 102f1c579b1SScott Long #include <vm/vm_param.h> 103f1c579b1SScott Long #include <vm/pmap.h> 104f1c579b1SScott Long 105f1c579b1SScott Long #include <isa/rtc.h> 106f1c579b1SScott Long 107f1c579b1SScott Long #include <machine/bus.h> 108f1c579b1SScott Long #include <machine/resource.h> 109f1c579b1SScott Long #include <machine/atomic.h> 110f1c579b1SScott Long #include <sys/conf.h> 111f1c579b1SScott Long #include <sys/rman.h> 112f1c579b1SScott Long 113f1c579b1SScott Long #include <cam/cam.h> 114f1c579b1SScott Long #include <cam/cam_ccb.h> 115f1c579b1SScott Long #include <cam/cam_sim.h> 116d74001adSXin LI #include <cam/cam_periph.h> 117d74001adSXin LI #include <cam/cam_xpt_periph.h> 118f1c579b1SScott Long #include <cam/cam_xpt_sim.h> 119f1c579b1SScott Long #include <cam/cam_debug.h> 120f1c579b1SScott Long #include <cam/scsi/scsi_all.h> 121f1c579b1SScott Long #include <cam/scsi/scsi_message.h> 122f1c579b1SScott Long /* 123f1c579b1SScott Long ************************************************************************** 124f1c579b1SScott Long ************************************************************************** 125f1c579b1SScott Long */ 126f1c579b1SScott Long #if __FreeBSD_version >= 500005 127f1c579b1SScott Long #include <sys/selinfo.h> 128f1c579b1SScott Long #include <sys/mutex.h> 129ad6d6297SScott Long #include <sys/endian.h> 130f1c579b1SScott Long #include <dev/pci/pcivar.h> 131f1c579b1SScott Long #include <dev/pci/pcireg.h> 132f1c579b1SScott Long #else 133f1c579b1SScott Long #include <sys/select.h> 134f1c579b1SScott Long #include <pci/pcivar.h> 135f1c579b1SScott Long #include <pci/pcireg.h> 136f1c579b1SScott Long #endif 13744f05562SScott Long 13844f05562SScott Long #if !defined(CAM_NEW_TRAN_CODE) && __FreeBSD_version >= 700025 13944f05562SScott Long #define CAM_NEW_TRAN_CODE 1 14044f05562SScott Long #endif 14144f05562SScott Long 14222f2616bSXin LI #if __FreeBSD_version > 500000 14322f2616bSXin LI #define arcmsr_callout_init(a) callout_init(a, /*mpsafe*/1); 14422f2616bSXin LI #else 14522f2616bSXin LI #define arcmsr_callout_init(a) callout_init(a); 14622f2616bSXin LI #endif 14722f2616bSXin LI 148*abfdbca9SXin LI #define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.27 2013-05-06" 149f1c579b1SScott Long #include <dev/arcmsr/arcmsr.h> 150f1c579b1SScott Long /* 151f1c579b1SScott Long ************************************************************************** 152f1c579b1SScott Long ************************************************************************** 153f1c579b1SScott Long */ 15422f2616bSXin LI static void arcmsr_free_srb(struct CommandControlBlock *srb); 155ad6d6297SScott Long static struct CommandControlBlock *arcmsr_get_freesrb(struct AdapterControlBlock *acb); 156ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb *abortccb); 157f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev); 158f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev); 159f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev); 160ad6d6297SScott Long static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg); 161ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb); 162f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev); 16344f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb); 164ad6d6297SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb); 165ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb); 166ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb); 167ad6d6297SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); 168ad6d6297SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb); 169ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb); 170ad6d6297SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb); 17135689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, struct QBUFFER *prbuffer); 1727a7bc959SXin LI static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb); 173ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb); 174ad6d6297SScott Long static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag); 175ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb); 176ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb); 177ad6d6297SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t *dm_segs, u_int32_t nseg); 178ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *pccb); 179ad6d6297SScott Long static int arcmsr_resume(device_t dev); 180ad6d6297SScott Long static int arcmsr_suspend(device_t dev); 181d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb); 182d74001adSXin LI static void arcmsr_polling_devmap(void *arg); 18322f2616bSXin LI static void arcmsr_srb_timeout(void *arg); 1847a7bc959SXin LI static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb); 18522f2616bSXin LI #ifdef ARCMSR_DEBUG1 18622f2616bSXin LI static void arcmsr_dump_data(struct AdapterControlBlock *acb); 18722f2616bSXin LI #endif 188f1c579b1SScott Long /* 189f1c579b1SScott Long ************************************************************************** 190ad6d6297SScott Long ************************************************************************** 191ad6d6297SScott Long */ 192ad6d6297SScott Long static void UDELAY(u_int32_t us) { DELAY(us); } 193ad6d6297SScott Long /* 194ad6d6297SScott Long ************************************************************************** 195f1c579b1SScott Long ************************************************************************** 196f1c579b1SScott Long */ 197231c8b71SXin LI static bus_dmamap_callback_t arcmsr_map_free_srb; 198231c8b71SXin LI static bus_dmamap_callback_t arcmsr_execute_srb; 199f1c579b1SScott Long /* 200f1c579b1SScott Long ************************************************************************** 201f1c579b1SScott Long ************************************************************************** 202f1c579b1SScott Long */ 203f1c579b1SScott Long static d_open_t arcmsr_open; 204f1c579b1SScott Long static d_close_t arcmsr_close; 205f1c579b1SScott Long static d_ioctl_t arcmsr_ioctl; 206f1c579b1SScott Long 207f1c579b1SScott Long static device_method_t arcmsr_methods[]={ 208f1c579b1SScott Long DEVMETHOD(device_probe, arcmsr_probe), 209f1c579b1SScott Long DEVMETHOD(device_attach, arcmsr_attach), 210f1c579b1SScott Long DEVMETHOD(device_detach, arcmsr_detach), 211f1c579b1SScott Long DEVMETHOD(device_shutdown, arcmsr_shutdown), 212ad6d6297SScott Long DEVMETHOD(device_suspend, arcmsr_suspend), 213ad6d6297SScott Long DEVMETHOD(device_resume, arcmsr_resume), 2144b7ec270SMarius Strobl 21535689395SXin LI #if __FreeBSD_version >= 803000 2164b7ec270SMarius Strobl DEVMETHOD_END 21735689395SXin LI #else 21835689395SXin LI { 0, 0 } 21935689395SXin LI #endif 220f1c579b1SScott Long }; 221f1c579b1SScott Long 222f1c579b1SScott Long static driver_t arcmsr_driver={ 223ad6d6297SScott Long "arcmsr", arcmsr_methods, sizeof(struct AdapterControlBlock) 224f1c579b1SScott Long }; 225f1c579b1SScott Long 226f1c579b1SScott Long static devclass_t arcmsr_devclass; 227f1c579b1SScott Long DRIVER_MODULE(arcmsr, pci, arcmsr_driver, arcmsr_devclass, 0, 0); 228d3cf342dSScott Long MODULE_DEPEND(arcmsr, pci, 1, 1, 1); 229d3cf342dSScott Long MODULE_DEPEND(arcmsr, cam, 1, 1, 1); 230ad6d6297SScott Long #ifndef BUS_DMA_COHERENT 231ad6d6297SScott Long #define BUS_DMA_COHERENT 0x04 /* hint: map memory in a coherent way */ 232ad6d6297SScott Long #endif 233ad6d6297SScott Long #if __FreeBSD_version >= 501000 234f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw={ 23522f2616bSXin LI #if __FreeBSD_version >= 503000 236f1c579b1SScott Long .d_version = D_VERSION, 237ad6d6297SScott Long #endif 23822f2616bSXin LI #if (__FreeBSD_version>=503000 && __FreeBSD_version<600034) 239f1c579b1SScott Long .d_flags = D_NEEDGIANT, 24022f2616bSXin LI #endif 241f1c579b1SScott Long .d_open = arcmsr_open, /* open */ 242f1c579b1SScott Long .d_close = arcmsr_close, /* close */ 243f1c579b1SScott Long .d_ioctl = arcmsr_ioctl, /* ioctl */ 244f1c579b1SScott Long .d_name = "arcmsr", /* name */ 245f1c579b1SScott Long }; 246f1c579b1SScott Long #else 247f1c579b1SScott Long #define ARCMSR_CDEV_MAJOR 180 248f1c579b1SScott Long 249f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw = { 250f1c579b1SScott Long arcmsr_open, /* open */ 251f1c579b1SScott Long arcmsr_close, /* close */ 252f1c579b1SScott Long noread, /* read */ 253f1c579b1SScott Long nowrite, /* write */ 254f1c579b1SScott Long arcmsr_ioctl, /* ioctl */ 255f1c579b1SScott Long nopoll, /* poll */ 256f1c579b1SScott Long nommap, /* mmap */ 257f1c579b1SScott Long nostrategy, /* strategy */ 258f1c579b1SScott Long "arcmsr", /* name */ 259f1c579b1SScott Long ARCMSR_CDEV_MAJOR, /* major */ 260f1c579b1SScott Long nodump, /* dump */ 261f1c579b1SScott Long nopsize, /* psize */ 262f1c579b1SScott Long 0 /* flags */ 263f1c579b1SScott Long }; 264f1c579b1SScott Long #endif 265d74001adSXin LI /* 266d74001adSXin LI ************************************************************************** 267d74001adSXin LI ************************************************************************** 268d74001adSXin LI */ 269f1c579b1SScott Long #if __FreeBSD_version < 500005 270f1c579b1SScott Long static int arcmsr_open(dev_t dev, int flags, int fmt, struct proc *proc) 271f1c579b1SScott Long #else 272f1c579b1SScott Long #if __FreeBSD_version < 503000 273f1c579b1SScott Long static int arcmsr_open(dev_t dev, int flags, int fmt, struct thread *proc) 274f1c579b1SScott Long #else 27500b4e54aSWarner Losh static int arcmsr_open(struct cdev *dev, int flags, int fmt, struct thread *proc) 276f1c579b1SScott Long #endif 277f1c579b1SScott Long #endif 278f1c579b1SScott Long { 279f1c579b1SScott Long #if __FreeBSD_version < 503000 280ad6d6297SScott Long struct AdapterControlBlock *acb = dev->si_drv1; 281f1c579b1SScott Long #else 2826bfa9a2dSEd Schouten int unit = dev2unit(dev); 283ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 284f1c579b1SScott Long #endif 285ad6d6297SScott Long if(acb == NULL) { 286f1c579b1SScott Long return ENXIO; 287f1c579b1SScott Long } 288dac36688SXin LI return (0); 289f1c579b1SScott Long } 290f1c579b1SScott Long /* 291f1c579b1SScott Long ************************************************************************** 292f1c579b1SScott Long ************************************************************************** 293f1c579b1SScott Long */ 294f1c579b1SScott Long #if __FreeBSD_version < 500005 295f1c579b1SScott Long static int arcmsr_close(dev_t dev, int flags, int fmt, struct proc *proc) 296f1c579b1SScott Long #else 297f1c579b1SScott Long #if __FreeBSD_version < 503000 298f1c579b1SScott Long static int arcmsr_close(dev_t dev, int flags, int fmt, struct thread *proc) 299f1c579b1SScott Long #else 30000b4e54aSWarner Losh static int arcmsr_close(struct cdev *dev, int flags, int fmt, struct thread *proc) 301f1c579b1SScott Long #endif 302f1c579b1SScott Long #endif 303f1c579b1SScott Long { 304f1c579b1SScott Long #if __FreeBSD_version < 503000 305ad6d6297SScott Long struct AdapterControlBlock *acb = dev->si_drv1; 306f1c579b1SScott Long #else 3076bfa9a2dSEd Schouten int unit = dev2unit(dev); 308ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 309f1c579b1SScott Long #endif 310ad6d6297SScott Long if(acb == NULL) { 311f1c579b1SScott Long return ENXIO; 312f1c579b1SScott Long } 313f1c579b1SScott Long return 0; 314f1c579b1SScott Long } 315f1c579b1SScott Long /* 316f1c579b1SScott Long ************************************************************************** 317f1c579b1SScott Long ************************************************************************** 318f1c579b1SScott Long */ 319f1c579b1SScott Long #if __FreeBSD_version < 500005 320f1c579b1SScott Long static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct proc *proc) 321f1c579b1SScott Long #else 322f1c579b1SScott Long #if __FreeBSD_version < 503000 323f1c579b1SScott Long static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc) 324f1c579b1SScott Long #else 32500b4e54aSWarner Losh static int arcmsr_ioctl(struct cdev *dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc) 326f1c579b1SScott Long #endif 327f1c579b1SScott Long #endif 328f1c579b1SScott Long { 329f1c579b1SScott Long #if __FreeBSD_version < 503000 330ad6d6297SScott Long struct AdapterControlBlock *acb = dev->si_drv1; 331f1c579b1SScott Long #else 3326bfa9a2dSEd Schouten int unit = dev2unit(dev); 333ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 334f1c579b1SScott Long #endif 335f1c579b1SScott Long 336ad6d6297SScott Long if(acb == NULL) { 337f1c579b1SScott Long return ENXIO; 338f1c579b1SScott Long } 339ad6d6297SScott Long return (arcmsr_iop_ioctlcmd(acb, ioctl_cmd, arg)); 340f1c579b1SScott Long } 341f1c579b1SScott Long /* 34244f05562SScott Long ********************************************************************** 34344f05562SScott Long ********************************************************************** 34444f05562SScott Long */ 34544f05562SScott Long static u_int32_t arcmsr_disable_allintr( struct AdapterControlBlock *acb) 34644f05562SScott Long { 34744f05562SScott Long u_int32_t intmask_org = 0; 34844f05562SScott Long 34944f05562SScott Long switch (acb->adapter_type) { 35044f05562SScott Long case ACB_ADAPTER_TYPE_A: { 35144f05562SScott Long /* disable all outbound interrupt */ 352d74001adSXin LI intmask_org = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intmask); /* disable outbound message0 int */ 353d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); 35444f05562SScott Long } 35544f05562SScott Long break; 35644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 35744f05562SScott Long /* disable all outbound interrupt */ 35844f05562SScott Long intmask_org = CHIP_REG_READ32(HBB_DOORBELL, 35944f05562SScott Long 0, iop2drv_doorbell_mask) & (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); /* disable outbound message0 int */ 360d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell_mask, 0); /* disable all interrupt */ 361d74001adSXin LI } 362d74001adSXin LI break; 363d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 364d74001adSXin LI /* disable all outbound interrupt */ 365d74001adSXin LI intmask_org = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_mask) ; /* disable outbound message0 int */ 366d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org|ARCMSR_HBCMU_ALL_INTMASKENABLE); 36744f05562SScott Long } 36844f05562SScott Long break; 3697a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 3707a7bc959SXin LI /* disable all outbound interrupt */ 3717a7bc959SXin LI intmask_org = CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable) ; /* disable outbound message0 int */ 3727a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, ARCMSR_HBDMU_ALL_INT_DISABLE); 3737a7bc959SXin LI } 3747a7bc959SXin LI break; 37544f05562SScott Long } 37644f05562SScott Long return (intmask_org); 37744f05562SScott Long } 37844f05562SScott Long /* 37944f05562SScott Long ********************************************************************** 38044f05562SScott Long ********************************************************************** 38144f05562SScott Long */ 38244f05562SScott Long static void arcmsr_enable_allintr( struct AdapterControlBlock *acb, u_int32_t intmask_org) 38344f05562SScott Long { 38444f05562SScott Long u_int32_t mask; 38544f05562SScott Long 38644f05562SScott Long switch (acb->adapter_type) { 38744f05562SScott Long case ACB_ADAPTER_TYPE_A: { 38844f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 389d74001adSXin LI mask = ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE); 39044f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org & mask); 39144f05562SScott Long acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; 39244f05562SScott Long } 39344f05562SScott Long break; 39444f05562SScott Long case ACB_ADAPTER_TYPE_B: { 395d74001adSXin LI /* enable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */ 396d74001adSXin LI mask = (ARCMSR_IOP2DRV_DATA_WRITE_OK|ARCMSR_IOP2DRV_DATA_READ_OK|ARCMSR_IOP2DRV_CDB_DONE|ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); 397d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell_mask, intmask_org | mask); /*1=interrupt enable, 0=interrupt disable*/ 39844f05562SScott Long acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f; 39944f05562SScott Long } 40044f05562SScott Long break; 401d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 402d74001adSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 403d74001adSXin LI mask = ~(ARCMSR_HBCMU_UTILITY_A_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK); 404d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org & mask); 405d74001adSXin LI acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f; 406d74001adSXin LI } 407d74001adSXin LI break; 4087a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 4097a7bc959SXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 4107a7bc959SXin LI mask = ARCMSR_HBDMU_ALL_INT_ENABLE; 4117a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, intmask_org | mask); 4127a7bc959SXin LI CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable); 4137a7bc959SXin LI acb->outbound_int_enable = mask; 4147a7bc959SXin LI } 4157a7bc959SXin LI break; 41644f05562SScott Long } 41744f05562SScott Long } 41844f05562SScott Long /* 41944f05562SScott Long ********************************************************************** 42044f05562SScott Long ********************************************************************** 42144f05562SScott Long */ 42244f05562SScott Long static u_int8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) 42344f05562SScott Long { 42444f05562SScott Long u_int32_t Index; 42544f05562SScott Long u_int8_t Retries = 0x00; 42644f05562SScott Long 42744f05562SScott Long do { 42844f05562SScott Long for(Index=0; Index < 100; Index++) { 429d74001adSXin LI if(CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { 430d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/ 43144f05562SScott Long return TRUE; 43244f05562SScott Long } 43344f05562SScott Long UDELAY(10000); 43444f05562SScott Long }/*max 1 seconds*/ 43544f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 436dac36688SXin LI return (FALSE); 43744f05562SScott Long } 43844f05562SScott Long /* 43944f05562SScott Long ********************************************************************** 44044f05562SScott Long ********************************************************************** 44144f05562SScott Long */ 44244f05562SScott Long static u_int8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) 44344f05562SScott Long { 44444f05562SScott Long u_int32_t Index; 44544f05562SScott Long u_int8_t Retries = 0x00; 44644f05562SScott Long 44744f05562SScott Long do { 44844f05562SScott Long for(Index=0; Index < 100; Index++) { 449d74001adSXin LI if(CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { 450d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/ 451d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 452d74001adSXin LI return TRUE; 453d74001adSXin LI } 454d74001adSXin LI UDELAY(10000); 455d74001adSXin LI }/*max 1 seconds*/ 456d74001adSXin LI }while(Retries++ < 20);/*max 20 sec*/ 457dac36688SXin LI return (FALSE); 458d74001adSXin LI } 459d74001adSXin LI /* 460d74001adSXin LI ********************************************************************** 461d74001adSXin LI ********************************************************************** 462d74001adSXin LI */ 463d74001adSXin LI static u_int8_t arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock *acb) 464d74001adSXin LI { 465d74001adSXin LI u_int32_t Index; 466d74001adSXin LI u_int8_t Retries = 0x00; 467d74001adSXin LI 468d74001adSXin LI do { 469d74001adSXin LI for(Index=0; Index < 100; Index++) { 470d74001adSXin LI if(CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { 471d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);/*clear interrupt*/ 47244f05562SScott Long return TRUE; 47344f05562SScott Long } 47444f05562SScott Long UDELAY(10000); 47544f05562SScott Long }/*max 1 seconds*/ 47644f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 477dac36688SXin LI return (FALSE); 47844f05562SScott Long } 47944f05562SScott Long /* 4807a7bc959SXin LI ********************************************************************** 4817a7bc959SXin LI ********************************************************************** 4827a7bc959SXin LI */ 4837a7bc959SXin LI static u_int8_t arcmsr_hbd_wait_msgint_ready(struct AdapterControlBlock *acb) 4847a7bc959SXin LI { 4857a7bc959SXin LI u_int32_t Index; 4867a7bc959SXin LI u_int8_t Retries = 0x00; 4877a7bc959SXin LI 4887a7bc959SXin LI do { 4897a7bc959SXin LI for(Index=0; Index < 100; Index++) { 4907a7bc959SXin LI if(CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) { 4917a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR);/*clear interrupt*/ 4927a7bc959SXin LI return TRUE; 4937a7bc959SXin LI } 4947a7bc959SXin LI UDELAY(10000); 4957a7bc959SXin LI }/*max 1 seconds*/ 4967a7bc959SXin LI }while(Retries++ < 20);/*max 20 sec*/ 4977a7bc959SXin LI return (FALSE); 4987a7bc959SXin LI } 4997a7bc959SXin LI /* 50044f05562SScott Long ************************************************************************ 50144f05562SScott Long ************************************************************************ 50244f05562SScott Long */ 50344f05562SScott Long static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) 50444f05562SScott Long { 50544f05562SScott Long int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ 50644f05562SScott Long 507d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 50844f05562SScott Long do { 50944f05562SScott Long if(arcmsr_hba_wait_msgint_ready(acb)) { 51044f05562SScott Long break; 51144f05562SScott Long } else { 51244f05562SScott Long retry_count--; 51344f05562SScott Long } 51444f05562SScott Long }while(retry_count != 0); 51544f05562SScott Long } 51644f05562SScott Long /* 51744f05562SScott Long ************************************************************************ 51844f05562SScott Long ************************************************************************ 51944f05562SScott Long */ 52044f05562SScott Long static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) 52144f05562SScott Long { 52244f05562SScott Long int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ 52344f05562SScott Long 52444f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 52544f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_FLUSH_CACHE); 52644f05562SScott Long do { 52744f05562SScott Long if(arcmsr_hbb_wait_msgint_ready(acb)) { 52844f05562SScott Long break; 52944f05562SScott Long } else { 53044f05562SScott Long retry_count--; 53144f05562SScott Long } 53244f05562SScott Long }while(retry_count != 0); 53344f05562SScott Long } 53444f05562SScott Long /* 53544f05562SScott Long ************************************************************************ 53644f05562SScott Long ************************************************************************ 53744f05562SScott Long */ 538d74001adSXin LI static void arcmsr_flush_hbc_cache(struct AdapterControlBlock *acb) 539d74001adSXin LI { 540d74001adSXin LI int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ 541d74001adSXin LI 542d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 543d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 544d74001adSXin LI do { 545d74001adSXin LI if(arcmsr_hbc_wait_msgint_ready(acb)) { 546d74001adSXin LI break; 547d74001adSXin LI } else { 548d74001adSXin LI retry_count--; 549d74001adSXin LI } 550d74001adSXin LI }while(retry_count != 0); 551d74001adSXin LI } 552d74001adSXin LI /* 553d74001adSXin LI ************************************************************************ 554d74001adSXin LI ************************************************************************ 555d74001adSXin LI */ 5567a7bc959SXin LI static void arcmsr_flush_hbd_cache(struct AdapterControlBlock *acb) 5577a7bc959SXin LI { 5587a7bc959SXin LI int retry_count = 30; /* enlarge wait flush adapter cache time: 10 minute */ 5597a7bc959SXin LI 5607a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 5617a7bc959SXin LI do { 5627a7bc959SXin LI if(arcmsr_hbd_wait_msgint_ready(acb)) { 5637a7bc959SXin LI break; 5647a7bc959SXin LI } else { 5657a7bc959SXin LI retry_count--; 5667a7bc959SXin LI } 5677a7bc959SXin LI }while(retry_count != 0); 5687a7bc959SXin LI } 5697a7bc959SXin LI /* 5707a7bc959SXin LI ************************************************************************ 5717a7bc959SXin LI ************************************************************************ 5727a7bc959SXin LI */ 57344f05562SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) 57444f05562SScott Long { 57544f05562SScott Long switch (acb->adapter_type) { 57644f05562SScott Long case ACB_ADAPTER_TYPE_A: { 57744f05562SScott Long arcmsr_flush_hba_cache(acb); 57844f05562SScott Long } 57944f05562SScott Long break; 58044f05562SScott Long case ACB_ADAPTER_TYPE_B: { 58144f05562SScott Long arcmsr_flush_hbb_cache(acb); 58244f05562SScott Long } 58344f05562SScott Long break; 584d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 585d74001adSXin LI arcmsr_flush_hbc_cache(acb); 586d74001adSXin LI } 587d74001adSXin LI break; 5887a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 5897a7bc959SXin LI arcmsr_flush_hbd_cache(acb); 5907a7bc959SXin LI } 5917a7bc959SXin LI break; 59244f05562SScott Long } 59344f05562SScott Long } 59444f05562SScott Long /* 595ad6d6297SScott Long ******************************************************************************* 596ad6d6297SScott Long ******************************************************************************* 597f1c579b1SScott Long */ 598ad6d6297SScott Long static int arcmsr_suspend(device_t dev) 599f1c579b1SScott Long { 600ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 601f1c579b1SScott Long 602ad6d6297SScott Long /* flush controller */ 603ad6d6297SScott Long arcmsr_iop_parking(acb); 604d74001adSXin LI /* disable all outbound interrupt */ 605d74001adSXin LI arcmsr_disable_allintr(acb); 606ad6d6297SScott Long return(0); 607ad6d6297SScott Long } 608ad6d6297SScott Long /* 609ad6d6297SScott Long ******************************************************************************* 610ad6d6297SScott Long ******************************************************************************* 611ad6d6297SScott Long */ 612ad6d6297SScott Long static int arcmsr_resume(device_t dev) 613ad6d6297SScott Long { 614ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 615f1c579b1SScott Long 616ad6d6297SScott Long arcmsr_iop_init(acb); 617ad6d6297SScott Long return(0); 618f1c579b1SScott Long } 619f1c579b1SScott Long /* 620f1c579b1SScott Long ********************************************************************************* 621f1c579b1SScott Long ********************************************************************************* 622f1c579b1SScott Long */ 623ad6d6297SScott Long static void arcmsr_async(void *cb_arg, u_int32_t code, struct cam_path *path, void *arg) 624f1c579b1SScott Long { 625ad6d6297SScott Long struct AdapterControlBlock *acb; 626ad6d6297SScott Long u_int8_t target_id, target_lun; 627f1c579b1SScott Long struct cam_sim *sim; 628f1c579b1SScott Long 629f1c579b1SScott Long sim = (struct cam_sim *) cb_arg; 630ad6d6297SScott Long acb =(struct AdapterControlBlock *) cam_sim_softc(sim); 631ad6d6297SScott Long switch (code) { 632f1c579b1SScott Long case AC_LOST_DEVICE: 633f1c579b1SScott Long target_id = xpt_path_target_id(path); 634f1c579b1SScott Long target_lun = xpt_path_lun_id(path); 635d74001adSXin LI if((target_id > ARCMSR_MAX_TARGETID) || (target_lun > ARCMSR_MAX_TARGETLUN)) { 636f1c579b1SScott Long break; 637f1c579b1SScott Long } 638dac36688SXin LI // printf("%s:scsi id=%d lun=%d device lost \n", device_get_name(acb->pci_dev), target_id, target_lun); 639f1c579b1SScott Long break; 640f1c579b1SScott Long default: 641f1c579b1SScott Long break; 642f1c579b1SScott Long } 643f1c579b1SScott Long } 644f1c579b1SScott Long /* 645f1c579b1SScott Long ********************************************************************** 646f1c579b1SScott Long ********************************************************************** 647f1c579b1SScott Long */ 648ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb) 649f1c579b1SScott Long { 650ad6d6297SScott Long union ccb *pccb = srb->pccb; 651f1c579b1SScott Long 652ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 653ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 654dac36688SXin LI if(pccb->csio.sense_len) { 655ad6d6297SScott Long memset(&pccb->csio.sense_data, 0, sizeof(pccb->csio.sense_data)); 656ad6d6297SScott Long memcpy(&pccb->csio.sense_data, srb->arcmsr_cdb.SenseData, 657ad6d6297SScott Long get_min(sizeof(struct SENSE_DATA), sizeof(pccb->csio.sense_data))); 658ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); /* Valid,ErrorCode */ 659f1c579b1SScott Long pccb->ccb_h.status |= CAM_AUTOSNS_VALID; 660f1c579b1SScott Long } 661f1c579b1SScott Long } 662f1c579b1SScott Long /* 663f1c579b1SScott Long ********************************************************************* 66444f05562SScott Long ********************************************************************* 66544f05562SScott Long */ 66644f05562SScott Long static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) 66744f05562SScott Long { 66844f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 66944f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 670d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 67144f05562SScott Long } 67244f05562SScott Long } 67344f05562SScott Long /* 67444f05562SScott Long ********************************************************************* 67544f05562SScott Long ********************************************************************* 67644f05562SScott Long */ 67744f05562SScott Long static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) 67844f05562SScott Long { 67944f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_ABORT_CMD); 68044f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 681d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 682d74001adSXin LI } 683d74001adSXin LI } 684d74001adSXin LI /* 685d74001adSXin LI ********************************************************************* 686d74001adSXin LI ********************************************************************* 687d74001adSXin LI */ 688d74001adSXin LI static void arcmsr_abort_hbc_allcmd(struct AdapterControlBlock *acb) 689d74001adSXin LI { 690d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 691d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 692d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 693d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 69444f05562SScott Long } 69544f05562SScott Long } 69644f05562SScott Long /* 69744f05562SScott Long ********************************************************************* 698f1c579b1SScott Long ********************************************************************* 699f1c579b1SScott Long */ 7007a7bc959SXin LI static void arcmsr_abort_hbd_allcmd(struct AdapterControlBlock *acb) 7017a7bc959SXin LI { 7027a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 7037a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 7047a7bc959SXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 7057a7bc959SXin LI } 7067a7bc959SXin LI } 7077a7bc959SXin LI /* 7087a7bc959SXin LI ********************************************************************* 7097a7bc959SXin LI ********************************************************************* 7107a7bc959SXin LI */ 711ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) 712f1c579b1SScott Long { 71344f05562SScott Long switch (acb->adapter_type) { 71444f05562SScott Long case ACB_ADAPTER_TYPE_A: { 71544f05562SScott Long arcmsr_abort_hba_allcmd(acb); 71644f05562SScott Long } 71744f05562SScott Long break; 71844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 71944f05562SScott Long arcmsr_abort_hbb_allcmd(acb); 72044f05562SScott Long } 72144f05562SScott Long break; 722d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 723d74001adSXin LI arcmsr_abort_hbc_allcmd(acb); 724d74001adSXin LI } 725d74001adSXin LI break; 7267a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 7277a7bc959SXin LI arcmsr_abort_hbd_allcmd(acb); 7287a7bc959SXin LI } 7297a7bc959SXin LI break; 73044f05562SScott Long } 73144f05562SScott Long } 73244f05562SScott Long /* 733231c8b71SXin LI ********************************************************************** 734231c8b71SXin LI ********************************************************************** 735231c8b71SXin LI */ 736231c8b71SXin LI static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag) 737231c8b71SXin LI { 738231c8b71SXin LI struct AdapterControlBlock *acb = srb->acb; 739231c8b71SXin LI union ccb *pccb = srb->pccb; 740231c8b71SXin LI 74122f2616bSXin LI if(srb->srb_flags & SRB_FLAG_TIMER_START) 74222f2616bSXin LI callout_stop(&srb->ccb_callout); 743231c8b71SXin LI if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 744231c8b71SXin LI bus_dmasync_op_t op; 745231c8b71SXin LI 746231c8b71SXin LI if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 747231c8b71SXin LI op = BUS_DMASYNC_POSTREAD; 748231c8b71SXin LI } else { 749231c8b71SXin LI op = BUS_DMASYNC_POSTWRITE; 750231c8b71SXin LI } 751231c8b71SXin LI bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 752231c8b71SXin LI bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 753231c8b71SXin LI } 754231c8b71SXin LI if(stand_flag == 1) { 755231c8b71SXin LI atomic_subtract_int(&acb->srboutstandingcount, 1); 756231c8b71SXin LI if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) && ( 757*abfdbca9SXin LI acb->srboutstandingcount < (acb->maxOutstanding -10))) { 758231c8b71SXin LI acb->acb_flags &= ~ACB_F_CAM_DEV_QFRZN; 759231c8b71SXin LI pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 760231c8b71SXin LI } 761231c8b71SXin LI } 76222f2616bSXin LI if(srb->srb_state != ARCMSR_SRB_TIMEOUT) 76322f2616bSXin LI arcmsr_free_srb(srb); 76422f2616bSXin LI acb->pktReturnCount++; 765231c8b71SXin LI xpt_done(pccb); 766231c8b71SXin LI } 767231c8b71SXin LI /* 76844f05562SScott Long ************************************************************************** 76944f05562SScott Long ************************************************************************** 77044f05562SScott Long */ 771d74001adSXin LI static void arcmsr_report_srb_state(struct AdapterControlBlock *acb, struct CommandControlBlock *srb, u_int16_t error) 77244f05562SScott Long { 77344f05562SScott Long int target, lun; 77444f05562SScott Long 77544f05562SScott Long target = srb->pccb->ccb_h.target_id; 77644f05562SScott Long lun = srb->pccb->ccb_h.target_lun; 777d74001adSXin LI if(error == FALSE) { 77844f05562SScott Long if(acb->devstate[target][lun] == ARECA_RAID_GONE) { 77944f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GOOD; 78044f05562SScott Long } 78144f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_CMP; 78244f05562SScott Long arcmsr_srb_complete(srb, 1); 78344f05562SScott Long } else { 78444f05562SScott Long switch(srb->arcmsr_cdb.DeviceStatus) { 78544f05562SScott Long case ARCMSR_DEV_SELECT_TIMEOUT: { 78644f05562SScott Long if(acb->devstate[target][lun] == ARECA_RAID_GOOD) { 787d74001adSXin LI printf( "arcmsr%d: Target=%x, Lun=%x, selection timeout, raid volume was lost\n", acb->pci_unit, target, lun); 788ad6d6297SScott Long } 78944f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GONE; 790d74001adSXin LI srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 79144f05562SScott Long arcmsr_srb_complete(srb, 1); 79244f05562SScott Long } 79344f05562SScott Long break; 79444f05562SScott Long case ARCMSR_DEV_ABORTED: 79544f05562SScott Long case ARCMSR_DEV_INIT_FAIL: { 79644f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GONE; 79744f05562SScott Long srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 79844f05562SScott Long arcmsr_srb_complete(srb, 1); 79944f05562SScott Long } 80044f05562SScott Long break; 80144f05562SScott Long case SCSISTAT_CHECK_CONDITION: { 80244f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GOOD; 80344f05562SScott Long arcmsr_report_sense_info(srb); 80444f05562SScott Long arcmsr_srb_complete(srb, 1); 80544f05562SScott Long } 80644f05562SScott Long break; 80744f05562SScott Long default: 80810d66948SKevin Lo printf("arcmsr%d: scsi id=%d lun=%d isr got command error done,but got unknown DeviceStatus=0x%x \n" 809d74001adSXin LI , acb->pci_unit, target, lun ,srb->arcmsr_cdb.DeviceStatus); 81044f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GONE; 81144f05562SScott Long srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY; 81210d66948SKevin Lo /*unknown error or crc error just for retry*/ 81344f05562SScott Long arcmsr_srb_complete(srb, 1); 81444f05562SScott Long break; 81544f05562SScott Long } 81644f05562SScott Long } 81744f05562SScott Long } 81844f05562SScott Long /* 81944f05562SScott Long ************************************************************************** 82044f05562SScott Long ************************************************************************** 82144f05562SScott Long */ 822d74001adSXin LI static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t flag_srb, u_int16_t error) 82344f05562SScott Long { 82444f05562SScott Long struct CommandControlBlock *srb; 82544f05562SScott Long 82644f05562SScott Long /* check if command done with no error*/ 827d74001adSXin LI switch (acb->adapter_type) { 828d74001adSXin LI case ACB_ADAPTER_TYPE_C: 8297a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 83022f2616bSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0)); /*frame must be 32 bytes aligned*/ 831d74001adSXin LI break; 832d74001adSXin LI case ACB_ADAPTER_TYPE_A: 833d74001adSXin LI case ACB_ADAPTER_TYPE_B: 834d74001adSXin LI default: 835d74001adSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 836d74001adSXin LI break; 837d74001adSXin LI } 83822f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 83922f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_TIMEOUT) { 84022f2616bSXin LI arcmsr_free_srb(srb); 84122f2616bSXin LI printf("arcmsr%d: srb='%p' return srb has been timeouted\n", acb->pci_unit, srb); 84244f05562SScott Long return; 84344f05562SScott Long } 84422f2616bSXin LI printf("arcmsr%d: return srb has been completed\n" 84522f2616bSXin LI "srb='%p' srb_state=0x%x outstanding srb count=%d \n", 84622f2616bSXin LI acb->pci_unit, srb, srb->srb_state, acb->srboutstandingcount); 84744f05562SScott Long return; 84844f05562SScott Long } 849d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 85044f05562SScott Long } 85144f05562SScott Long /* 85222f2616bSXin LI ************************************************************************** 85322f2616bSXin LI ************************************************************************** 85422f2616bSXin LI */ 85522f2616bSXin LI static void arcmsr_srb_timeout(void *arg) 85622f2616bSXin LI { 85722f2616bSXin LI struct CommandControlBlock *srb = (struct CommandControlBlock *)arg; 85822f2616bSXin LI struct AdapterControlBlock *acb; 85922f2616bSXin LI int target, lun; 86022f2616bSXin LI u_int8_t cmd; 86122f2616bSXin LI 86222f2616bSXin LI target = srb->pccb->ccb_h.target_id; 86322f2616bSXin LI lun = srb->pccb->ccb_h.target_lun; 86422f2616bSXin LI acb = srb->acb; 8657a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 86622f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) 86722f2616bSXin LI { 86822f2616bSXin LI cmd = srb->pccb->csio.cdb_io.cdb_bytes[0]; 86922f2616bSXin LI srb->srb_state = ARCMSR_SRB_TIMEOUT; 87022f2616bSXin LI srb->pccb->ccb_h.status |= CAM_CMD_TIMEOUT; 87122f2616bSXin LI arcmsr_srb_complete(srb, 1); 87222f2616bSXin LI printf("arcmsr%d: scsi id %d lun %d cmd=0x%x srb='%p' ccb command time out!\n", 87322f2616bSXin LI acb->pci_unit, target, lun, cmd, srb); 87422f2616bSXin LI } 8757a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 87622f2616bSXin LI #ifdef ARCMSR_DEBUG1 87722f2616bSXin LI arcmsr_dump_data(acb); 87822f2616bSXin LI #endif 87922f2616bSXin LI } 88022f2616bSXin LI 88122f2616bSXin LI /* 88244f05562SScott Long ********************************************************************** 88344f05562SScott Long ********************************************************************** 88444f05562SScott Long */ 88544f05562SScott Long static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) 88644f05562SScott Long { 88744f05562SScott Long int i=0; 88844f05562SScott Long u_int32_t flag_srb; 889d74001adSXin LI u_int16_t error; 89044f05562SScott Long 89144f05562SScott Long switch (acb->adapter_type) { 89244f05562SScott Long case ACB_ADAPTER_TYPE_A: { 89344f05562SScott Long u_int32_t outbound_intstatus; 89444f05562SScott Long 89544f05562SScott Long /*clear and abort all outbound posted Q*/ 896d74001adSXin LI outbound_intstatus = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 897d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/ 898d74001adSXin LI while(((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_queueport)) != 0xFFFFFFFF) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { 899d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 900d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 90144f05562SScott Long } 90244f05562SScott Long } 90344f05562SScott Long break; 90444f05562SScott Long case ACB_ADAPTER_TYPE_B: { 90544f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 90644f05562SScott Long 90744f05562SScott Long /*clear all outbound posted Q*/ 908d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 90944f05562SScott Long for(i=0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) { 91044f05562SScott Long if((flag_srb = phbbmu->done_qbuffer[i]) != 0) { 91144f05562SScott Long phbbmu->done_qbuffer[i] = 0; 912d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 913d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 91444f05562SScott Long } 91544f05562SScott Long phbbmu->post_qbuffer[i] = 0; 91644f05562SScott Long }/*drain reply FIFO*/ 91744f05562SScott Long phbbmu->doneq_index = 0; 91844f05562SScott Long phbbmu->postq_index = 0; 91944f05562SScott Long } 92044f05562SScott Long break; 921d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 922d74001adSXin LI 923d74001adSXin LI while((CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { 924d74001adSXin LI flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 925d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 926d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 927d74001adSXin LI } 928d74001adSXin LI } 929d74001adSXin LI break; 9307a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 9317a7bc959SXin LI arcmsr_hbd_postqueue_isr(acb); 9327a7bc959SXin LI } 9337a7bc959SXin LI break; 93444f05562SScott Long } 935f1c579b1SScott Long } 936f1c579b1SScott Long /* 937f1c579b1SScott Long **************************************************************************** 938f1c579b1SScott Long **************************************************************************** 939f1c579b1SScott Long */ 940ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb) 941f1c579b1SScott Long { 942ad6d6297SScott Long struct CommandControlBlock *srb; 94344f05562SScott Long u_int32_t intmask_org; 944ad6d6297SScott Long u_int32_t i=0; 945f1c579b1SScott Long 94644f05562SScott Long if(acb->srboutstandingcount>0) { 94744f05562SScott Long /* disable all outbound interrupt */ 94844f05562SScott Long intmask_org = arcmsr_disable_allintr(acb); 94944f05562SScott Long /*clear and abort all outbound posted Q*/ 95044f05562SScott Long arcmsr_done4abort_postqueue(acb); 951f1c579b1SScott Long /* talk to iop 331 outstanding command aborted*/ 952ad6d6297SScott Long arcmsr_abort_allcmd(acb); 953ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 954ad6d6297SScott Long srb = acb->psrb_pool[i]; 95522f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) { 95622f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 957ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 958ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 95922f2616bSXin LI printf("arcmsr%d: scsi id=%d lun=%d srb='%p' aborted\n" 96022f2616bSXin LI , acb->pci_unit, srb->pccb->ccb_h.target_id 96122f2616bSXin LI , srb->pccb->ccb_h.target_lun, srb); 962f1c579b1SScott Long } 963f1c579b1SScott Long } 964f1c579b1SScott Long /* enable all outbound interrupt */ 96544f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 966f1c579b1SScott Long } 96722f2616bSXin LI acb->srboutstandingcount = 0; 968ad6d6297SScott Long acb->workingsrb_doneindex = 0; 969ad6d6297SScott Long acb->workingsrb_startindex = 0; 97022f2616bSXin LI acb->pktRequestCount = 0; 97122f2616bSXin LI acb->pktReturnCount = 0; 972f1c579b1SScott Long } 973f1c579b1SScott Long /* 974f1c579b1SScott Long ********************************************************************** 975f1c579b1SScott Long ********************************************************************** 976f1c579b1SScott Long */ 97744f05562SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, 97844f05562SScott Long bus_dma_segment_t *dm_segs, u_int32_t nseg) 979f1c579b1SScott Long { 980ad6d6297SScott Long struct ARCMSR_CDB *arcmsr_cdb = &srb->arcmsr_cdb; 981ad6d6297SScott Long u_int8_t *psge = (u_int8_t *)&arcmsr_cdb->u; 982ad6d6297SScott Long u_int32_t address_lo, address_hi; 983ad6d6297SScott Long union ccb *pccb = srb->pccb; 984f1c579b1SScott Long struct ccb_scsiio *pcsio = &pccb->csio; 985ad6d6297SScott Long u_int32_t arccdbsize = 0x30; 986f1c579b1SScott Long 987ad6d6297SScott Long memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB)); 988ad6d6297SScott Long arcmsr_cdb->Bus = 0; 989ad6d6297SScott Long arcmsr_cdb->TargetID = pccb->ccb_h.target_id; 990ad6d6297SScott Long arcmsr_cdb->LUN = pccb->ccb_h.target_lun; 991ad6d6297SScott Long arcmsr_cdb->Function = 1; 992ad6d6297SScott Long arcmsr_cdb->CdbLength = (u_int8_t)pcsio->cdb_len; 993ad6d6297SScott Long bcopy(pcsio->cdb_io.cdb_bytes, arcmsr_cdb->Cdb, pcsio->cdb_len); 994ad6d6297SScott Long if(nseg != 0) { 995ad6d6297SScott Long struct AdapterControlBlock *acb = srb->acb; 996f1c579b1SScott Long bus_dmasync_op_t op; 997ad6d6297SScott Long u_int32_t length, i, cdb_sgcount = 0; 998f1c579b1SScott Long 999ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 1000ad6d6297SScott Long op = BUS_DMASYNC_PREREAD; 1001ad6d6297SScott Long } else { 1002ad6d6297SScott Long op = BUS_DMASYNC_PREWRITE; 1003ad6d6297SScott Long arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE; 1004ad6d6297SScott Long srb->srb_flags |= SRB_FLAG_WRITE; 1005ad6d6297SScott Long } 1006ad6d6297SScott Long bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 1007ad6d6297SScott Long for(i=0; i < nseg; i++) { 1008f1c579b1SScott Long /* Get the physical address of the current data pointer */ 1009ad6d6297SScott Long length = arcmsr_htole32(dm_segs[i].ds_len); 1010ad6d6297SScott Long address_lo = arcmsr_htole32(dma_addr_lo32(dm_segs[i].ds_addr)); 1011ad6d6297SScott Long address_hi = arcmsr_htole32(dma_addr_hi32(dm_segs[i].ds_addr)); 1012ad6d6297SScott Long if(address_hi == 0) { 1013ad6d6297SScott Long struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge; 1014f1c579b1SScott Long pdma_sg->address = address_lo; 1015f1c579b1SScott Long pdma_sg->length = length; 1016ad6d6297SScott Long psge += sizeof(struct SG32ENTRY); 1017ad6d6297SScott Long arccdbsize += sizeof(struct SG32ENTRY); 1018ad6d6297SScott Long } else { 1019ad6d6297SScott Long u_int32_t sg64s_size = 0, tmplength = length; 1020f1c579b1SScott Long 1021ad6d6297SScott Long while(1) { 1022ad6d6297SScott Long u_int64_t span4G, length0; 1023ad6d6297SScott Long struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge; 1024f1c579b1SScott Long 1025ad6d6297SScott Long span4G = (u_int64_t)address_lo + tmplength; 1026f1c579b1SScott Long pdma_sg->addresshigh = address_hi; 1027f1c579b1SScott Long pdma_sg->address = address_lo; 1028ad6d6297SScott Long if(span4G > 0x100000000) { 1029f1c579b1SScott Long /*see if cross 4G boundary*/ 1030f1c579b1SScott Long length0 = 0x100000000-address_lo; 1031ad6d6297SScott Long pdma_sg->length = (u_int32_t)length0 | IS_SG64_ADDR; 1032f1c579b1SScott Long address_hi = address_hi+1; 1033f1c579b1SScott Long address_lo = 0; 1034ad6d6297SScott Long tmplength = tmplength - (u_int32_t)length0; 1035ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 1036ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 1037f1c579b1SScott Long cdb_sgcount++; 1038ad6d6297SScott Long } else { 1039f1c579b1SScott Long pdma_sg->length = tmplength | IS_SG64_ADDR; 1040ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 1041ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 1042f1c579b1SScott Long break; 1043f1c579b1SScott Long } 1044f1c579b1SScott Long } 1045f1c579b1SScott Long arccdbsize += sg64s_size; 1046f1c579b1SScott Long } 1047f1c579b1SScott Long cdb_sgcount++; 1048f1c579b1SScott Long } 1049ad6d6297SScott Long arcmsr_cdb->sgcount = (u_int8_t)cdb_sgcount; 1050ad6d6297SScott Long arcmsr_cdb->DataLength = pcsio->dxfer_len; 1051ad6d6297SScott Long if( arccdbsize > 256) { 1052ad6d6297SScott Long arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE; 1053f1c579b1SScott Long } 1054d74001adSXin LI } else { 1055d74001adSXin LI arcmsr_cdb->DataLength = 0; 1056f1c579b1SScott Long } 1057d74001adSXin LI srb->arc_cdb_size = arccdbsize; 10587a7bc959SXin LI arcmsr_cdb->msgPages = (arccdbsize/256) + ((arccdbsize % 256) ? 1 : 0); 1059f1c579b1SScott Long } 1060f1c579b1SScott Long /* 1061f1c579b1SScott Long ************************************************************************** 1062f1c579b1SScott Long ************************************************************************** 1063f1c579b1SScott Long */ 1064ad6d6297SScott Long static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandControlBlock *srb) 1065f1c579b1SScott Long { 10667a7bc959SXin LI u_int32_t cdb_phyaddr_low = (u_int32_t) srb->cdb_phyaddr_low; 1067ad6d6297SScott Long struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&srb->arcmsr_cdb; 1068f1c579b1SScott Long 1069d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, (srb->srb_flags & SRB_FLAG_WRITE) ? BUS_DMASYNC_POSTWRITE:BUS_DMASYNC_POSTREAD); 1070ad6d6297SScott Long atomic_add_int(&acb->srboutstandingcount, 1); 107122f2616bSXin LI srb->srb_state = ARCMSR_SRB_START; 1072d74001adSXin LI 107344f05562SScott Long switch (acb->adapter_type) { 107444f05562SScott Long case ACB_ADAPTER_TYPE_A: { 1075ad6d6297SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 10767a7bc959SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_phyaddr_low|ARCMSR_SRBPOST_FLAG_SGL_BSIZE); 1077ad6d6297SScott Long } else { 10787a7bc959SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_phyaddr_low); 107944f05562SScott Long } 108044f05562SScott Long } 108144f05562SScott Long break; 108244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 108344f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 108444f05562SScott Long int ending_index, index; 108544f05562SScott Long 108644f05562SScott Long index = phbbmu->postq_index; 108744f05562SScott Long ending_index = ((index+1) % ARCMSR_MAX_HBB_POSTQUEUE); 108844f05562SScott Long phbbmu->post_qbuffer[ending_index] = 0; 108944f05562SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 10907a7bc959SXin LI phbbmu->post_qbuffer[index] = cdb_phyaddr_low | ARCMSR_SRBPOST_FLAG_SGL_BSIZE; 109144f05562SScott Long } else { 10927a7bc959SXin LI phbbmu->post_qbuffer[index] = cdb_phyaddr_low; 109344f05562SScott Long } 109444f05562SScott Long index++; 109544f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 109644f05562SScott Long phbbmu->postq_index = index; 1097d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED); 1098d74001adSXin LI } 1099d74001adSXin LI break; 11007a7bc959SXin LI case ACB_ADAPTER_TYPE_C: { 1101d74001adSXin LI u_int32_t ccb_post_stamp, arc_cdb_size, cdb_phyaddr_hi32; 1102d74001adSXin LI 1103d74001adSXin LI arc_cdb_size = (srb->arc_cdb_size > 0x300) ? 0x300 : srb->arc_cdb_size; 11047a7bc959SXin LI ccb_post_stamp = (cdb_phyaddr_low | ((arc_cdb_size-1) >> 6) | 1); 1105d74001adSXin LI cdb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high; 1106d74001adSXin LI if(cdb_phyaddr_hi32) 1107d74001adSXin LI { 1108d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_high, cdb_phyaddr_hi32); 1109d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp); 1110d74001adSXin LI } 1111d74001adSXin LI else 1112d74001adSXin LI { 1113d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp); 1114d74001adSXin LI } 111544f05562SScott Long } 111644f05562SScott Long break; 11177a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 11187a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 11197a7bc959SXin LI u_int16_t index_stripped; 11207a7bc959SXin LI u_int16_t postq_index; 11217a7bc959SXin LI struct InBound_SRB *pinbound_srb; 11227a7bc959SXin LI 11237a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->postDone_lock); 11247a7bc959SXin LI postq_index = phbdmu->postq_index; 11257a7bc959SXin LI pinbound_srb = (struct InBound_SRB *)&phbdmu->post_qbuffer[postq_index & 0xFF]; 11267a7bc959SXin LI pinbound_srb->addressHigh = srb->cdb_phyaddr_high; 11277a7bc959SXin LI pinbound_srb->addressLow = srb->cdb_phyaddr_low; 11287a7bc959SXin LI pinbound_srb->length = srb->arc_cdb_size >> 2; 11297a7bc959SXin LI arcmsr_cdb->Context = srb->cdb_phyaddr_low; 11307a7bc959SXin LI if (postq_index & 0x4000) { 11317a7bc959SXin LI index_stripped = postq_index & 0xFF; 11327a7bc959SXin LI index_stripped += 1; 11337a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 11347a7bc959SXin LI phbdmu->postq_index = index_stripped ? (index_stripped | 0x4000) : index_stripped; 11357a7bc959SXin LI } else { 11367a7bc959SXin LI index_stripped = postq_index; 11377a7bc959SXin LI index_stripped += 1; 11387a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 11397a7bc959SXin LI phbdmu->postq_index = index_stripped ? index_stripped : (index_stripped | 0x4000); 11407a7bc959SXin LI } 11417a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inboundlist_write_pointer, postq_index); 11427a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->postDone_lock); 11437a7bc959SXin LI } 11447a7bc959SXin LI break; 1145f1c579b1SScott Long } 1146f1c579b1SScott Long } 1147f1c579b1SScott Long /* 114844f05562SScott Long ************************************************************************ 114944f05562SScott Long ************************************************************************ 115044f05562SScott Long */ 115144f05562SScott Long static struct QBUFFER *arcmsr_get_iop_rqbuffer( struct AdapterControlBlock *acb) 115244f05562SScott Long { 115344f05562SScott Long struct QBUFFER *qbuffer=NULL; 115444f05562SScott Long 115544f05562SScott Long switch (acb->adapter_type) { 115644f05562SScott Long case ACB_ADAPTER_TYPE_A: { 115744f05562SScott Long struct HBA_MessageUnit *phbamu = (struct HBA_MessageUnit *)acb->pmu; 115844f05562SScott Long 115944f05562SScott Long qbuffer = (struct QBUFFER *)&phbamu->message_rbuffer; 116044f05562SScott Long } 116144f05562SScott Long break; 116244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 116344f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 116444f05562SScott Long 116544f05562SScott Long qbuffer = (struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_rbuffer; 116644f05562SScott Long } 116744f05562SScott Long break; 1168d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1169d74001adSXin LI struct HBC_MessageUnit *phbcmu = (struct HBC_MessageUnit *)acb->pmu; 1170d74001adSXin LI 1171d74001adSXin LI qbuffer = (struct QBUFFER *)&phbcmu->message_rbuffer; 1172d74001adSXin LI } 1173d74001adSXin LI break; 11747a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 11757a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 11767a7bc959SXin LI 11777a7bc959SXin LI qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_rbuffer; 11787a7bc959SXin LI } 11797a7bc959SXin LI break; 118044f05562SScott Long } 118144f05562SScott Long return(qbuffer); 118244f05562SScott Long } 118344f05562SScott Long /* 118444f05562SScott Long ************************************************************************ 118544f05562SScott Long ************************************************************************ 118644f05562SScott Long */ 118744f05562SScott Long static struct QBUFFER *arcmsr_get_iop_wqbuffer( struct AdapterControlBlock *acb) 118844f05562SScott Long { 118944f05562SScott Long struct QBUFFER *qbuffer = NULL; 119044f05562SScott Long 119144f05562SScott Long switch (acb->adapter_type) { 119244f05562SScott Long case ACB_ADAPTER_TYPE_A: { 119344f05562SScott Long struct HBA_MessageUnit *phbamu = (struct HBA_MessageUnit *)acb->pmu; 119444f05562SScott Long 119544f05562SScott Long qbuffer = (struct QBUFFER *)&phbamu->message_wbuffer; 119644f05562SScott Long } 119744f05562SScott Long break; 119844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 119944f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 120044f05562SScott Long 120144f05562SScott Long qbuffer = (struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_wbuffer; 120244f05562SScott Long } 120344f05562SScott Long break; 1204d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1205d74001adSXin LI struct HBC_MessageUnit *phbcmu = (struct HBC_MessageUnit *)acb->pmu; 1206d74001adSXin LI 1207d74001adSXin LI qbuffer = (struct QBUFFER *)&phbcmu->message_wbuffer; 1208d74001adSXin LI } 1209d74001adSXin LI break; 12107a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 12117a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 12127a7bc959SXin LI 12137a7bc959SXin LI qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_wbuffer; 12147a7bc959SXin LI } 12157a7bc959SXin LI break; 121644f05562SScott Long } 121744f05562SScott Long return(qbuffer); 121844f05562SScott Long } 121944f05562SScott Long /* 122044f05562SScott Long ************************************************************************** 122144f05562SScott Long ************************************************************************** 122244f05562SScott Long */ 122344f05562SScott Long static void arcmsr_iop_message_read(struct AdapterControlBlock *acb) 122444f05562SScott Long { 122544f05562SScott Long switch (acb->adapter_type) { 122644f05562SScott Long case ACB_ADAPTER_TYPE_A: { 122744f05562SScott Long /* let IOP know data has been read */ 1228d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 122944f05562SScott Long } 123044f05562SScott Long break; 123144f05562SScott Long case ACB_ADAPTER_TYPE_B: { 123244f05562SScott Long /* let IOP know data has been read */ 1233d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 123444f05562SScott Long } 123544f05562SScott Long break; 1236d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1237d74001adSXin LI /* let IOP know data has been read */ 1238d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK); 1239d74001adSXin LI } 12407a7bc959SXin LI break; 12417a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 12427a7bc959SXin LI /* let IOP know data has been read */ 12437a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ); 12447a7bc959SXin LI } 12457a7bc959SXin LI break; 124644f05562SScott Long } 124744f05562SScott Long } 124844f05562SScott Long /* 124944f05562SScott Long ************************************************************************** 125044f05562SScott Long ************************************************************************** 125144f05562SScott Long */ 125244f05562SScott Long static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) 125344f05562SScott Long { 125444f05562SScott Long switch (acb->adapter_type) { 125544f05562SScott Long case ACB_ADAPTER_TYPE_A: { 125644f05562SScott Long /* 125744f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 125844f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 125944f05562SScott Long */ 1260d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK); 126144f05562SScott Long } 126244f05562SScott Long break; 126344f05562SScott Long case ACB_ADAPTER_TYPE_B: { 126444f05562SScott Long /* 126544f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 126644f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 126744f05562SScott Long */ 1268d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_WRITE_OK); 1269d74001adSXin LI } 1270d74001adSXin LI break; 1271d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1272d74001adSXin LI /* 1273d74001adSXin LI ** push inbound doorbell tell iop, driver data write ok 1274d74001adSXin LI ** and wait reply on next hwinterrupt for next Qbuffer post 1275d74001adSXin LI */ 1276d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK); 127744f05562SScott Long } 127844f05562SScott Long break; 12797a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 128044f05562SScott Long /* 12817a7bc959SXin LI ** push inbound doorbell tell iop, driver data write ok 12827a7bc959SXin LI ** and wait reply on next hwinterrupt for next Qbuffer post 1283f1c579b1SScott Long */ 12847a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_IN_READY); 1285f1c579b1SScott Long } 12867a7bc959SXin LI break; 1287ad6d6297SScott Long } 1288f1c579b1SScott Long } 1289f1c579b1SScott Long /* 1290f1c579b1SScott Long ************************************************************************ 1291f1c579b1SScott Long ************************************************************************ 1292f1c579b1SScott Long */ 129344f05562SScott Long static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb) 1294f1c579b1SScott Long { 1295ad6d6297SScott Long acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 129644f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 129744f05562SScott Long 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 129844f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 1299d74001adSXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n" 1300ad6d6297SScott Long , acb->pci_unit); 1301ad6d6297SScott Long } 1302f1c579b1SScott Long } 1303f1c579b1SScott Long /* 1304f1c579b1SScott Long ************************************************************************ 1305f1c579b1SScott Long ************************************************************************ 1306f1c579b1SScott Long */ 130744f05562SScott Long static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb) 130844f05562SScott Long { 130944f05562SScott Long acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 131044f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 131144f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_STOP_BGRB); 131244f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 1313d74001adSXin LI printf( "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" 131444f05562SScott Long , acb->pci_unit); 131544f05562SScott Long } 131644f05562SScott Long } 131744f05562SScott Long /* 131844f05562SScott Long ************************************************************************ 131944f05562SScott Long ************************************************************************ 132044f05562SScott Long */ 1321d74001adSXin LI static void arcmsr_stop_hbc_bgrb(struct AdapterControlBlock *acb) 1322d74001adSXin LI { 1323d74001adSXin LI acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 1324d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 1325d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 1326d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 1327d74001adSXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit); 1328d74001adSXin LI } 1329d74001adSXin LI } 1330d74001adSXin LI /* 1331d74001adSXin LI ************************************************************************ 1332d74001adSXin LI ************************************************************************ 1333d74001adSXin LI */ 13347a7bc959SXin LI static void arcmsr_stop_hbd_bgrb(struct AdapterControlBlock *acb) 13357a7bc959SXin LI { 13367a7bc959SXin LI acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 13377a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 13387a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 13397a7bc959SXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit); 13407a7bc959SXin LI } 13417a7bc959SXin LI } 13427a7bc959SXin LI /* 13437a7bc959SXin LI ************************************************************************ 13447a7bc959SXin LI ************************************************************************ 13457a7bc959SXin LI */ 134644f05562SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) 134744f05562SScott Long { 134844f05562SScott Long switch (acb->adapter_type) { 134944f05562SScott Long case ACB_ADAPTER_TYPE_A: { 135044f05562SScott Long arcmsr_stop_hba_bgrb(acb); 135144f05562SScott Long } 135244f05562SScott Long break; 135344f05562SScott Long case ACB_ADAPTER_TYPE_B: { 135444f05562SScott Long arcmsr_stop_hbb_bgrb(acb); 135544f05562SScott Long } 135644f05562SScott Long break; 1357d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1358d74001adSXin LI arcmsr_stop_hbc_bgrb(acb); 1359d74001adSXin LI } 1360d74001adSXin LI break; 13617a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 13627a7bc959SXin LI arcmsr_stop_hbd_bgrb(acb); 13637a7bc959SXin LI } 13647a7bc959SXin LI break; 136544f05562SScott Long } 136644f05562SScott Long } 136744f05562SScott Long /* 136844f05562SScott Long ************************************************************************ 136944f05562SScott Long ************************************************************************ 137044f05562SScott Long */ 1371ad6d6297SScott Long static void arcmsr_poll(struct cam_sim *psim) 1372f1c579b1SScott Long { 1373579ec1a5SScott Long struct AdapterControlBlock *acb; 13744e32649fSXin LI int mutex; 1375579ec1a5SScott Long 1376579ec1a5SScott Long acb = (struct AdapterControlBlock *)cam_sim_softc(psim); 13777a7bc959SXin LI mutex = mtx_owned(&acb->isr_lock); 13784e32649fSXin LI if( mutex == 0 ) 13797a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 1380579ec1a5SScott Long arcmsr_interrupt(acb); 13814e32649fSXin LI if( mutex == 0 ) 13827a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 13837a7bc959SXin LI } 13847a7bc959SXin LI /* 13857a7bc959SXin LI ************************************************************************** 13867a7bc959SXin LI ************************************************************************** 13877a7bc959SXin LI */ 138835689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data_D(struct AdapterControlBlock *acb, 138935689395SXin LI struct QBUFFER *prbuffer) { 139035689395SXin LI 139135689395SXin LI u_int8_t *pQbuffer; 139235689395SXin LI u_int8_t *buf1 = 0; 139335689395SXin LI u_int32_t *iop_data, *buf2 = 0; 139435689395SXin LI u_int32_t iop_len, data_len; 139535689395SXin LI 139635689395SXin LI iop_data = (u_int32_t *)prbuffer->data; 139735689395SXin LI iop_len = (u_int32_t)prbuffer->data_len; 139835689395SXin LI if ( iop_len > 0 ) 139935689395SXin LI { 140035689395SXin LI buf1 = malloc(128, M_DEVBUF, M_NOWAIT | M_ZERO); 140135689395SXin LI buf2 = (u_int32_t *)buf1; 140235689395SXin LI if( buf1 == NULL) 140335689395SXin LI return (0); 140435689395SXin LI data_len = iop_len; 140535689395SXin LI while(data_len >= 4) 140635689395SXin LI { 140735689395SXin LI *buf2++ = *iop_data++; 140835689395SXin LI data_len -= 4; 140935689395SXin LI } 141035689395SXin LI if(data_len) 141135689395SXin LI *buf2 = *iop_data; 141235689395SXin LI buf2 = (u_int32_t *)buf1; 141335689395SXin LI } 141435689395SXin LI while (iop_len > 0) { 141535689395SXin LI pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex]; 141635689395SXin LI *pQbuffer = *buf1; 141735689395SXin LI acb->rqbuf_lastindex++; 141835689395SXin LI /* if last, index number set it to 0 */ 141935689395SXin LI acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 142035689395SXin LI buf1++; 142135689395SXin LI iop_len--; 142235689395SXin LI } 142335689395SXin LI if(buf2) 142435689395SXin LI free( (u_int8_t *)buf2, M_DEVBUF); 142535689395SXin LI /* let IOP know data has been read */ 142635689395SXin LI arcmsr_iop_message_read(acb); 142735689395SXin LI return (1); 142835689395SXin LI } 142935689395SXin LI /* 143035689395SXin LI ************************************************************************** 143135689395SXin LI ************************************************************************** 143235689395SXin LI */ 143335689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, 14347a7bc959SXin LI struct QBUFFER *prbuffer) { 14357a7bc959SXin LI 14367a7bc959SXin LI u_int8_t *pQbuffer; 14377a7bc959SXin LI u_int8_t *iop_data; 14387a7bc959SXin LI u_int32_t iop_len; 14397a7bc959SXin LI 144035689395SXin LI if(acb->adapter_type == ACB_ADAPTER_TYPE_D) { 144135689395SXin LI return(arcmsr_Read_iop_rqbuffer_data_D(acb, prbuffer)); 144235689395SXin LI } 14437a7bc959SXin LI iop_data = (u_int8_t *)prbuffer->data; 14447a7bc959SXin LI iop_len = (u_int32_t)prbuffer->data_len; 14457a7bc959SXin LI while (iop_len > 0) { 14467a7bc959SXin LI pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex]; 14477a7bc959SXin LI *pQbuffer = *iop_data; 14487a7bc959SXin LI acb->rqbuf_lastindex++; 14497a7bc959SXin LI /* if last, index number set it to 0 */ 14507a7bc959SXin LI acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 14517a7bc959SXin LI iop_data++; 14527a7bc959SXin LI iop_len--; 14537a7bc959SXin LI } 14547a7bc959SXin LI /* let IOP know data has been read */ 14557a7bc959SXin LI arcmsr_iop_message_read(acb); 145635689395SXin LI return (1); 1457f1c579b1SScott Long } 1458f1c579b1SScott Long /* 145944f05562SScott Long ************************************************************************** 146044f05562SScott Long ************************************************************************** 14615878cbecSScott Long */ 146244f05562SScott Long static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) 1463f1c579b1SScott Long { 146444f05562SScott Long struct QBUFFER *prbuffer; 14657a7bc959SXin LI int my_empty_len; 1466ad6d6297SScott Long 1467f1c579b1SScott Long /*check this iop data if overflow my rqbuffer*/ 14687a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 146944f05562SScott Long prbuffer = arcmsr_get_iop_rqbuffer(acb); 14707a7bc959SXin LI my_empty_len = (acb->rqbuf_lastindex - acb->rqbuf_firstindex - 1) & 14717a7bc959SXin LI (ARCMSR_MAX_QBUFFER-1); 14727a7bc959SXin LI if(my_empty_len >= prbuffer->data_len) { 147335689395SXin LI if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) 147435689395SXin LI acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 1475ad6d6297SScott Long } else { 1476ad6d6297SScott Long acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 1477f1c579b1SScott Long } 14787a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 14797a7bc959SXin LI } 14807a7bc959SXin LI /* 14817a7bc959SXin LI ********************************************************************** 14827a7bc959SXin LI ********************************************************************** 14837a7bc959SXin LI */ 148435689395SXin LI static void arcmsr_Write_data_2iop_wqbuffer_D(struct AdapterControlBlock *acb) 148535689395SXin LI { 148635689395SXin LI u_int8_t *pQbuffer; 148735689395SXin LI struct QBUFFER *pwbuffer; 148835689395SXin LI u_int8_t *buf1 = 0; 148935689395SXin LI u_int32_t *iop_data, *buf2 = 0; 149035689395SXin LI u_int32_t allxfer_len = 0, data_len; 149135689395SXin LI 149235689395SXin LI if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) { 149335689395SXin LI buf1 = malloc(128, M_DEVBUF, M_NOWAIT | M_ZERO); 149435689395SXin LI buf2 = (u_int32_t *)buf1; 149535689395SXin LI if( buf1 == NULL) 149635689395SXin LI return; 149735689395SXin LI 149835689395SXin LI acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 149935689395SXin LI pwbuffer = arcmsr_get_iop_wqbuffer(acb); 150035689395SXin LI iop_data = (u_int32_t *)pwbuffer->data; 150135689395SXin LI while((acb->wqbuf_firstindex != acb->wqbuf_lastindex) 150235689395SXin LI && (allxfer_len < 124)) { 150335689395SXin LI pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex]; 150435689395SXin LI *buf1 = *pQbuffer; 150535689395SXin LI acb->wqbuf_firstindex++; 150635689395SXin LI acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 150735689395SXin LI buf1++; 150835689395SXin LI allxfer_len++; 150935689395SXin LI } 151035689395SXin LI pwbuffer->data_len = allxfer_len; 151135689395SXin LI data_len = allxfer_len; 151235689395SXin LI buf1 = (u_int8_t *)buf2; 151335689395SXin LI while(data_len >= 4) 151435689395SXin LI { 151535689395SXin LI *iop_data++ = *buf2++; 151635689395SXin LI data_len -= 4; 151735689395SXin LI } 151835689395SXin LI if(data_len) 151935689395SXin LI *iop_data = *buf2; 152035689395SXin LI free( buf1, M_DEVBUF); 152135689395SXin LI arcmsr_iop_message_wrote(acb); 152235689395SXin LI } 152335689395SXin LI } 152435689395SXin LI /* 152535689395SXin LI ********************************************************************** 152635689395SXin LI ********************************************************************** 152735689395SXin LI */ 15287a7bc959SXin LI static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb) 15297a7bc959SXin LI { 15307a7bc959SXin LI u_int8_t *pQbuffer; 15317a7bc959SXin LI struct QBUFFER *pwbuffer; 15327a7bc959SXin LI u_int8_t *iop_data; 15337a7bc959SXin LI int32_t allxfer_len=0; 15347a7bc959SXin LI 153535689395SXin LI if(acb->adapter_type == ACB_ADAPTER_TYPE_D) { 153635689395SXin LI arcmsr_Write_data_2iop_wqbuffer_D(acb); 153735689395SXin LI return; 153835689395SXin LI } 15397a7bc959SXin LI if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) { 15407a7bc959SXin LI acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 15417a7bc959SXin LI pwbuffer = arcmsr_get_iop_wqbuffer(acb); 15427a7bc959SXin LI iop_data = (u_int8_t *)pwbuffer->data; 15437a7bc959SXin LI while((acb->wqbuf_firstindex != acb->wqbuf_lastindex) 15447a7bc959SXin LI && (allxfer_len < 124)) { 15457a7bc959SXin LI pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex]; 15467a7bc959SXin LI *iop_data = *pQbuffer; 15477a7bc959SXin LI acb->wqbuf_firstindex++; 15487a7bc959SXin LI acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 15497a7bc959SXin LI iop_data++; 15507a7bc959SXin LI allxfer_len++; 15517a7bc959SXin LI } 15527a7bc959SXin LI pwbuffer->data_len = allxfer_len; 15537a7bc959SXin LI arcmsr_iop_message_wrote(acb); 15547a7bc959SXin LI } 1555f1c579b1SScott Long } 1556f1c579b1SScott Long /* 155744f05562SScott Long ************************************************************************** 155844f05562SScott Long ************************************************************************** 155944f05562SScott Long */ 156044f05562SScott Long static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) 156144f05562SScott Long { 15627a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 156344f05562SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READ; 156444f05562SScott Long /* 156544f05562SScott Long ***************************************************************** 156644f05562SScott Long ** check if there are any mail packages from user space program 156744f05562SScott Long ** in my post bag, now is the time to send them into Areca's firmware 156844f05562SScott Long ***************************************************************** 1569f1c579b1SScott Long */ 1570ad6d6297SScott Long if(acb->wqbuf_firstindex != acb->wqbuf_lastindex) { 15717a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 1572f1c579b1SScott Long } 1573ad6d6297SScott Long if(acb->wqbuf_firstindex == acb->wqbuf_lastindex) { 1574ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; 1575f1c579b1SScott Long } 15767a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1577f1c579b1SScott Long } 15787a7bc959SXin LI /* 15797a7bc959SXin LI ************************************************************************** 15807a7bc959SXin LI ************************************************************************** 15817a7bc959SXin LI */ 1582d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb) 1583d74001adSXin LI { 1584d74001adSXin LI /* 1585d74001adSXin LI if (ccb->ccb_h.status != CAM_REQ_CMP) 15867a7bc959SXin LI printf("arcmsr_rescanLun_cb: Rescan Target=%x, lun=%x," 15877a7bc959SXin LI "failure status=%x\n", ccb->ccb_h.target_id, 15887a7bc959SXin LI ccb->ccb_h.target_lun, ccb->ccb_h.status); 1589d74001adSXin LI else 1590d74001adSXin LI printf("arcmsr_rescanLun_cb: Rescan lun successfully!\n"); 1591d74001adSXin LI */ 1592d74001adSXin LI xpt_free_path(ccb->ccb_h.path); 1593d74001adSXin LI xpt_free_ccb(ccb); 1594d74001adSXin LI } 1595d74001adSXin LI 1596d74001adSXin LI static void arcmsr_rescan_lun(struct AdapterControlBlock *acb, int target, int lun) 1597d74001adSXin LI { 1598d74001adSXin LI struct cam_path *path; 1599d74001adSXin LI union ccb *ccb; 1600d74001adSXin LI 1601d74001adSXin LI if ((ccb = (union ccb *)xpt_alloc_ccb_nowait()) == NULL) 1602d74001adSXin LI return; 1603*abfdbca9SXin LI if (xpt_create_path(&path, NULL, cam_sim_path(acb->psim), target, lun) != CAM_REQ_CMP) 1604d74001adSXin LI { 1605d74001adSXin LI xpt_free_ccb(ccb); 1606d74001adSXin LI return; 1607d74001adSXin LI } 1608d74001adSXin LI /* printf("arcmsr_rescan_lun: Rescan Target=%x, Lun=%x\n", target, lun); */ 1609d74001adSXin LI bzero(ccb, sizeof(union ccb)); 1610d74001adSXin LI xpt_setup_ccb(&ccb->ccb_h, path, 5); 1611d74001adSXin LI ccb->ccb_h.func_code = XPT_SCAN_LUN; 1612d74001adSXin LI ccb->ccb_h.cbfcnp = arcmsr_rescanLun_cb; 1613d74001adSXin LI ccb->crcn.flags = CAM_FLAG_NONE; 1614d74001adSXin LI xpt_action(ccb); 1615d74001adSXin LI } 1616d74001adSXin LI 1617d74001adSXin LI 1618d74001adSXin LI static void arcmsr_abort_dr_ccbs(struct AdapterControlBlock *acb, int target, int lun) 1619d74001adSXin LI { 1620d74001adSXin LI struct CommandControlBlock *srb; 1621d74001adSXin LI u_int32_t intmask_org; 1622d74001adSXin LI int i; 1623d74001adSXin LI 16247a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 1625d74001adSXin LI /* disable all outbound interrupts */ 1626d74001adSXin LI intmask_org = arcmsr_disable_allintr(acb); 1627d74001adSXin LI for (i = 0; i < ARCMSR_MAX_FREESRB_NUM; i++) 1628d74001adSXin LI { 1629d74001adSXin LI srb = acb->psrb_pool[i]; 163022f2616bSXin LI if (srb->srb_state == ARCMSR_SRB_START) 1631d74001adSXin LI { 1632d74001adSXin LI if((target == srb->pccb->ccb_h.target_id) && (lun == srb->pccb->ccb_h.target_lun)) 1633d74001adSXin LI { 163422f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 1635d74001adSXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 1636d74001adSXin LI arcmsr_srb_complete(srb, 1); 163722f2616bSXin LI printf("arcmsr%d: abort scsi id %d lun %d srb=%p \n", acb->pci_unit, target, lun, srb); 1638d74001adSXin LI } 1639d74001adSXin LI } 1640d74001adSXin LI } 1641d74001adSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 1642d74001adSXin LI arcmsr_enable_allintr(acb, intmask_org); 16437a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 1644d74001adSXin LI } 1645d74001adSXin LI /* 1646d74001adSXin LI ************************************************************************** 1647d74001adSXin LI ************************************************************************** 1648d74001adSXin LI */ 1649d74001adSXin LI static void arcmsr_dr_handle(struct AdapterControlBlock *acb) { 1650d74001adSXin LI u_int32_t devicemap; 1651d74001adSXin LI u_int32_t target, lun; 1652d74001adSXin LI u_int32_t deviceMapCurrent[4]={0}; 1653d74001adSXin LI u_int8_t *pDevMap; 1654d74001adSXin LI 1655d74001adSXin LI switch (acb->adapter_type) { 1656d74001adSXin LI case ACB_ADAPTER_TYPE_A: 1657d74001adSXin LI devicemap = offsetof(struct HBA_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1658d74001adSXin LI for (target = 0; target < 4; target++) 1659d74001adSXin LI { 1660d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1661d74001adSXin LI devicemap += 4; 1662d74001adSXin LI } 1663d74001adSXin LI break; 1664d74001adSXin LI 1665d74001adSXin LI case ACB_ADAPTER_TYPE_B: 1666d74001adSXin LI devicemap = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1667d74001adSXin LI for (target = 0; target < 4; target++) 1668d74001adSXin LI { 1669d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[1], acb->bhandle[1], devicemap); 1670d74001adSXin LI devicemap += 4; 1671d74001adSXin LI } 1672d74001adSXin LI break; 1673d74001adSXin LI 1674d74001adSXin LI case ACB_ADAPTER_TYPE_C: 1675d74001adSXin LI devicemap = offsetof(struct HBC_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1676d74001adSXin LI for (target = 0; target < 4; target++) 1677d74001adSXin LI { 1678d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1679d74001adSXin LI devicemap += 4; 1680d74001adSXin LI } 1681d74001adSXin LI break; 16827a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 16837a7bc959SXin LI devicemap = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 16847a7bc959SXin LI for (target = 0; target < 4; target++) 16857a7bc959SXin LI { 16867a7bc959SXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 16877a7bc959SXin LI devicemap += 4; 16887a7bc959SXin LI } 16897a7bc959SXin LI break; 1690d74001adSXin LI } 1691dac36688SXin LI 1692d74001adSXin LI if(acb->acb_flags & ACB_F_BUS_HANG_ON) 1693d74001adSXin LI { 1694d74001adSXin LI acb->acb_flags &= ~ACB_F_BUS_HANG_ON; 1695d74001adSXin LI } 1696d74001adSXin LI /* 1697d74001adSXin LI ** adapter posted CONFIG message 1698d74001adSXin LI ** copy the new map, note if there are differences with the current map 1699d74001adSXin LI */ 1700d74001adSXin LI pDevMap = (u_int8_t *)&deviceMapCurrent[0]; 1701d74001adSXin LI for (target = 0; target < ARCMSR_MAX_TARGETID - 1; target++) 1702d74001adSXin LI { 1703d74001adSXin LI if (*pDevMap != acb->device_map[target]) 1704d74001adSXin LI { 1705d74001adSXin LI u_int8_t difference, bit_check; 1706d74001adSXin LI 1707d74001adSXin LI difference = *pDevMap ^ acb->device_map[target]; 1708d74001adSXin LI for(lun=0; lun < ARCMSR_MAX_TARGETLUN; lun++) 1709d74001adSXin LI { 1710d74001adSXin LI bit_check = (1 << lun); /*check bit from 0....31*/ 1711d74001adSXin LI if(difference & bit_check) 1712d74001adSXin LI { 1713d74001adSXin LI if(acb->device_map[target] & bit_check) 1714d74001adSXin LI {/* unit departed */ 1715d74001adSXin LI printf("arcmsr_dr_handle: Target=%x, lun=%x, GONE!!!\n",target,lun); 1716d74001adSXin LI arcmsr_abort_dr_ccbs(acb, target, lun); 1717d74001adSXin LI arcmsr_rescan_lun(acb, target, lun); 1718d74001adSXin LI acb->devstate[target][lun] = ARECA_RAID_GONE; 1719d74001adSXin LI } 1720d74001adSXin LI else 1721d74001adSXin LI {/* unit arrived */ 172222f2616bSXin LI printf("arcmsr_dr_handle: Target=%x, lun=%x, Plug-IN!!!\n",target,lun); 1723d74001adSXin LI arcmsr_rescan_lun(acb, target, lun); 1724d74001adSXin LI acb->devstate[target][lun] = ARECA_RAID_GOOD; 1725d74001adSXin LI } 1726d74001adSXin LI } 1727d74001adSXin LI } 1728d74001adSXin LI /* printf("arcmsr_dr_handle: acb->device_map[%x]=0x%x, deviceMapCurrent[%x]=%x\n",target,acb->device_map[target],target,*pDevMap); */ 1729d74001adSXin LI acb->device_map[target] = *pDevMap; 1730d74001adSXin LI } 1731d74001adSXin LI pDevMap++; 1732d74001adSXin LI } 1733d74001adSXin LI } 1734d74001adSXin LI /* 1735d74001adSXin LI ************************************************************************** 1736d74001adSXin LI ************************************************************************** 1737d74001adSXin LI */ 1738d74001adSXin LI static void arcmsr_hba_message_isr(struct AdapterControlBlock *acb) { 1739d74001adSXin LI u_int32_t outbound_message; 1740d74001adSXin LI 1741d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT); 1742d74001adSXin LI outbound_message = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[0]); 1743d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1744d74001adSXin LI arcmsr_dr_handle( acb ); 1745d74001adSXin LI } 1746d74001adSXin LI /* 1747d74001adSXin LI ************************************************************************** 1748d74001adSXin LI ************************************************************************** 1749d74001adSXin LI */ 1750d74001adSXin LI static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) { 1751d74001adSXin LI u_int32_t outbound_message; 1752d74001adSXin LI 1753d74001adSXin LI /* clear interrupts */ 1754d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN); 1755d74001adSXin LI outbound_message = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0]); 1756d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1757d74001adSXin LI arcmsr_dr_handle( acb ); 1758d74001adSXin LI } 1759d74001adSXin LI /* 1760d74001adSXin LI ************************************************************************** 1761d74001adSXin LI ************************************************************************** 1762d74001adSXin LI */ 1763d74001adSXin LI static void arcmsr_hbc_message_isr(struct AdapterControlBlock *acb) { 1764d74001adSXin LI u_int32_t outbound_message; 1765d74001adSXin LI 1766d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR); 1767d74001adSXin LI outbound_message = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[0]); 1768d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1769d74001adSXin LI arcmsr_dr_handle( acb ); 1770d74001adSXin LI } 177144f05562SScott Long /* 177244f05562SScott Long ************************************************************************** 177344f05562SScott Long ************************************************************************** 177444f05562SScott Long */ 17757a7bc959SXin LI static void arcmsr_hbd_message_isr(struct AdapterControlBlock *acb) { 17767a7bc959SXin LI u_int32_t outbound_message; 17777a7bc959SXin LI 17787a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR); 17797a7bc959SXin LI outbound_message = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[0]); 17807a7bc959SXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 17817a7bc959SXin LI arcmsr_dr_handle( acb ); 17827a7bc959SXin LI } 17837a7bc959SXin LI /* 17847a7bc959SXin LI ************************************************************************** 17857a7bc959SXin LI ************************************************************************** 17867a7bc959SXin LI */ 178744f05562SScott Long static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) 178844f05562SScott Long { 178944f05562SScott Long u_int32_t outbound_doorbell; 179044f05562SScott Long 179144f05562SScott Long /* 179244f05562SScott Long ******************************************************************* 179344f05562SScott Long ** Maybe here we need to check wrqbuffer_lock is lock or not 179444f05562SScott Long ** DOORBELL: din! don! 179544f05562SScott Long ** check if there are any mail need to pack from firmware 179644f05562SScott Long ******************************************************************* 179744f05562SScott Long */ 179844f05562SScott Long outbound_doorbell = CHIP_REG_READ32(HBA_MessageUnit, 179944f05562SScott Long 0, outbound_doorbell); 180044f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 180144f05562SScott Long 0, outbound_doorbell, outbound_doorbell); /* clear doorbell interrupt */ 180244f05562SScott Long if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { 180344f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 1804ad6d6297SScott Long } 180544f05562SScott Long if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { 180644f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 180744f05562SScott Long } 180844f05562SScott Long } 180944f05562SScott Long /* 181044f05562SScott Long ************************************************************************** 181144f05562SScott Long ************************************************************************** 181244f05562SScott Long */ 1813d74001adSXin LI static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb) 1814d74001adSXin LI { 1815d74001adSXin LI u_int32_t outbound_doorbell; 1816d74001adSXin LI 1817d74001adSXin LI /* 1818d74001adSXin LI ******************************************************************* 1819d74001adSXin LI ** Maybe here we need to check wrqbuffer_lock is lock or not 1820d74001adSXin LI ** DOORBELL: din! don! 1821d74001adSXin LI ** check if there are any mail need to pack from firmware 1822d74001adSXin LI ******************************************************************* 1823d74001adSXin LI */ 1824d74001adSXin LI outbound_doorbell = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); 1825d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell); /* clear doorbell interrupt */ 1826d74001adSXin LI if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) { 1827d74001adSXin LI arcmsr_iop2drv_data_wrote_handle(acb); 1828d74001adSXin LI } 1829d74001adSXin LI if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) { 1830d74001adSXin LI arcmsr_iop2drv_data_read_handle(acb); 1831d74001adSXin LI } 1832d74001adSXin LI if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { 1833d74001adSXin LI arcmsr_hbc_message_isr(acb); /* messenger of "driver to iop commands" */ 1834d74001adSXin LI } 1835d74001adSXin LI } 1836d74001adSXin LI /* 1837d74001adSXin LI ************************************************************************** 1838d74001adSXin LI ************************************************************************** 1839d74001adSXin LI */ 18407a7bc959SXin LI static void arcmsr_hbd_doorbell_isr(struct AdapterControlBlock *acb) 18417a7bc959SXin LI { 18427a7bc959SXin LI u_int32_t outbound_Doorbell; 18437a7bc959SXin LI 18447a7bc959SXin LI /* 18457a7bc959SXin LI ******************************************************************* 18467a7bc959SXin LI ** Maybe here we need to check wrqbuffer_lock is lock or not 18477a7bc959SXin LI ** DOORBELL: din! don! 18487a7bc959SXin LI ** check if there are any mail need to pack from firmware 18497a7bc959SXin LI ******************************************************************* 18507a7bc959SXin LI */ 18517a7bc959SXin LI outbound_Doorbell = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE; 18527a7bc959SXin LI if(outbound_Doorbell) 18537a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, outbound_Doorbell); /* clear doorbell interrupt */ 18547a7bc959SXin LI while( outbound_Doorbell & ARCMSR_HBDMU_F0_DOORBELL_CAUSE ) { 18557a7bc959SXin LI if(outbound_Doorbell & ARCMSR_HBDMU_IOP2DRV_DATA_WRITE_OK) { 18567a7bc959SXin LI arcmsr_iop2drv_data_wrote_handle(acb); 18577a7bc959SXin LI } 18587a7bc959SXin LI if(outbound_Doorbell & ARCMSR_HBDMU_IOP2DRV_DATA_READ_OK) { 18597a7bc959SXin LI arcmsr_iop2drv_data_read_handle(acb); 18607a7bc959SXin LI } 18617a7bc959SXin LI if(outbound_Doorbell & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) { 18627a7bc959SXin LI arcmsr_hbd_message_isr(acb); /* messenger of "driver to iop commands" */ 18637a7bc959SXin LI } 18647a7bc959SXin LI outbound_Doorbell = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE; 18657a7bc959SXin LI if(outbound_Doorbell) 18667a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, outbound_Doorbell); /* clear doorbell interrupt */ 18677a7bc959SXin LI } 18687a7bc959SXin LI } 18697a7bc959SXin LI /* 18707a7bc959SXin LI ************************************************************************** 18717a7bc959SXin LI ************************************************************************** 18727a7bc959SXin LI */ 187344f05562SScott Long static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb) 187444f05562SScott Long { 187544f05562SScott Long u_int32_t flag_srb; 1876d74001adSXin LI u_int16_t error; 187744f05562SScott Long 1878f1c579b1SScott Long /* 1879f1c579b1SScott Long ***************************************************************************** 1880f1c579b1SScott Long ** areca cdb command done 1881f1c579b1SScott Long ***************************************************************************** 1882f1c579b1SScott Long */ 188344f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 188444f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 188544f05562SScott Long while((flag_srb = CHIP_REG_READ32(HBA_MessageUnit, 188644f05562SScott Long 0, outbound_queueport)) != 0xFFFFFFFF) { 1887f1c579b1SScott Long /* check if command done with no error*/ 1888d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0) ? TRUE : FALSE; 1889d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 189044f05562SScott Long } /*drain reply FIFO*/ 1891f1c579b1SScott Long } 189244f05562SScott Long /* 189344f05562SScott Long ************************************************************************** 189444f05562SScott Long ************************************************************************** 189544f05562SScott Long */ 189644f05562SScott Long static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) 189744f05562SScott Long { 189844f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 189944f05562SScott Long u_int32_t flag_srb; 190044f05562SScott Long int index; 1901d74001adSXin LI u_int16_t error; 190244f05562SScott Long 190344f05562SScott Long /* 190444f05562SScott Long ***************************************************************************** 190544f05562SScott Long ** areca cdb command done 190644f05562SScott Long ***************************************************************************** 190744f05562SScott Long */ 190844f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 190944f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 191044f05562SScott Long index = phbbmu->doneq_index; 191144f05562SScott Long while((flag_srb = phbbmu->done_qbuffer[index]) != 0) { 191244f05562SScott Long phbbmu->done_qbuffer[index] = 0; 191344f05562SScott Long index++; 191444f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 191544f05562SScott Long phbbmu->doneq_index = index; 191644f05562SScott Long /* check if command done with no error*/ 1917d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 1918d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 1919d74001adSXin LI } /*drain reply FIFO*/ 1920d74001adSXin LI } 1921d74001adSXin LI /* 1922d74001adSXin LI ************************************************************************** 1923d74001adSXin LI ************************************************************************** 1924d74001adSXin LI */ 1925d74001adSXin LI static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb) 1926d74001adSXin LI { 1927d74001adSXin LI u_int32_t flag_srb,throttling = 0; 1928d74001adSXin LI u_int16_t error; 1929d74001adSXin LI 1930d74001adSXin LI /* 1931d74001adSXin LI ***************************************************************************** 1932d74001adSXin LI ** areca cdb command done 1933d74001adSXin LI ***************************************************************************** 1934d74001adSXin LI */ 1935d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 1936d74001adSXin LI 1937d74001adSXin LI while(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) { 1938d74001adSXin LI 1939d74001adSXin LI flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 1940d74001adSXin LI /* check if command done with no error*/ 1941d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; 1942d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 1943*abfdbca9SXin LI throttling++; 1944d74001adSXin LI if(throttling == ARCMSR_HBC_ISR_THROTTLING_LEVEL) { 1945d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING); 1946*abfdbca9SXin LI throttling = 0; 1947d74001adSXin LI } 194844f05562SScott Long } /*drain reply FIFO*/ 1949f1c579b1SScott Long } 195044f05562SScott Long /* 195144f05562SScott Long ********************************************************************** 19527a7bc959SXin LI ** 19537a7bc959SXin LI ********************************************************************** 19547a7bc959SXin LI */ 19557a7bc959SXin LI static uint16_t arcmsr_get_doneq_index(struct HBD_MessageUnit0 *phbdmu) 19567a7bc959SXin LI { 19577a7bc959SXin LI uint16_t doneq_index, index_stripped; 19587a7bc959SXin LI 19597a7bc959SXin LI doneq_index = phbdmu->doneq_index; 19607a7bc959SXin LI if (doneq_index & 0x4000) { 19617a7bc959SXin LI index_stripped = doneq_index & 0xFF; 19627a7bc959SXin LI index_stripped += 1; 19637a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 19647a7bc959SXin LI phbdmu->doneq_index = index_stripped ? 19657a7bc959SXin LI (index_stripped | 0x4000) : index_stripped; 19667a7bc959SXin LI } else { 19677a7bc959SXin LI index_stripped = doneq_index; 19687a7bc959SXin LI index_stripped += 1; 19697a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 19707a7bc959SXin LI phbdmu->doneq_index = index_stripped ? 19717a7bc959SXin LI index_stripped : (index_stripped | 0x4000); 19727a7bc959SXin LI } 19737a7bc959SXin LI return (phbdmu->doneq_index); 19747a7bc959SXin LI } 19757a7bc959SXin LI /* 19767a7bc959SXin LI ************************************************************************** 19777a7bc959SXin LI ************************************************************************** 19787a7bc959SXin LI */ 19797a7bc959SXin LI static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb) 19807a7bc959SXin LI { 19817a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 19827a7bc959SXin LI u_int32_t outbound_write_pointer; 19837a7bc959SXin LI u_int32_t addressLow; 19847a7bc959SXin LI uint16_t doneq_index; 19857a7bc959SXin LI u_int16_t error; 19867a7bc959SXin LI /* 19877a7bc959SXin LI ***************************************************************************** 19887a7bc959SXin LI ** areca cdb command done 19897a7bc959SXin LI ***************************************************************************** 19907a7bc959SXin LI */ 19917a7bc959SXin LI if((CHIP_REG_READ32(HBD_MessageUnit, 0, outboundlist_interrupt_cause) & 19927a7bc959SXin LI ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT) == 0) 19937a7bc959SXin LI return; 19947a7bc959SXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 19957a7bc959SXin LI BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 19967a7bc959SXin LI outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow; 19977a7bc959SXin LI doneq_index = phbdmu->doneq_index; 19987a7bc959SXin LI while ((doneq_index & 0xFF) != (outbound_write_pointer & 0xFF)) { 19997a7bc959SXin LI doneq_index = arcmsr_get_doneq_index(phbdmu); 20007a7bc959SXin LI addressLow = phbdmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow; 20017a7bc959SXin LI error = (addressLow & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 20027a7bc959SXin LI arcmsr_drain_donequeue(acb, addressLow, error); /*Check if command done with no error */ 20037a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_read_pointer, doneq_index); 20047a7bc959SXin LI outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow; 20057a7bc959SXin LI } 20067a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_interrupt_cause, ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT_CLEAR); 20077a7bc959SXin LI CHIP_REG_READ32(HBD_MessageUnit, 0, outboundlist_interrupt_cause); /*Dummy ioread32 to force pci flush */ 20087a7bc959SXin LI } 20097a7bc959SXin LI /* 20107a7bc959SXin LI ********************************************************************** 201144f05562SScott Long ********************************************************************** 201244f05562SScott Long */ 201344f05562SScott Long static void arcmsr_handle_hba_isr( struct AdapterControlBlock *acb) 201444f05562SScott Long { 2015dac36688SXin LI u_int32_t outbound_intStatus; 201644f05562SScott Long /* 201744f05562SScott Long ********************************************* 201844f05562SScott Long ** check outbound intstatus 201944f05562SScott Long ********************************************* 202044f05562SScott Long */ 2021dac36688SXin LI outbound_intStatus = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 2022dac36688SXin LI if(!outbound_intStatus) { 202344f05562SScott Long /*it must be share irq*/ 202444f05562SScott Long return; 2025f1c579b1SScott Long } 2026dac36688SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intStatus); /*clear interrupt*/ 202744f05562SScott Long /* MU doorbell interrupts*/ 2028dac36688SXin LI if(outbound_intStatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) { 202944f05562SScott Long arcmsr_hba_doorbell_isr(acb); 2030f1c579b1SScott Long } 203144f05562SScott Long /* MU post queue interrupts*/ 2032dac36688SXin LI if(outbound_intStatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { 203344f05562SScott Long arcmsr_hba_postqueue_isr(acb); 203444f05562SScott Long } 2035dac36688SXin LI if(outbound_intStatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { 2036d74001adSXin LI arcmsr_hba_message_isr(acb); 2037d74001adSXin LI } 203844f05562SScott Long } 203944f05562SScott Long /* 204044f05562SScott Long ********************************************************************** 204144f05562SScott Long ********************************************************************** 204244f05562SScott Long */ 204344f05562SScott Long static void arcmsr_handle_hbb_isr( struct AdapterControlBlock *acb) 204444f05562SScott Long { 204544f05562SScott Long u_int32_t outbound_doorbell; 204644f05562SScott Long /* 204744f05562SScott Long ********************************************* 204844f05562SScott Long ** check outbound intstatus 204944f05562SScott Long ********************************************* 205044f05562SScott Long */ 205144f05562SScott Long outbound_doorbell = CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & acb->outbound_int_enable; 205244f05562SScott Long if(!outbound_doorbell) { 205344f05562SScott Long /*it must be share irq*/ 205444f05562SScott Long return; 205544f05562SScott Long } 205644f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ~outbound_doorbell); /* clear doorbell interrupt */ 205744f05562SScott Long CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell); 205844f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 205944f05562SScott Long /* MU ioctl transfer doorbell interrupts*/ 206044f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { 206144f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 206244f05562SScott Long } 206344f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) { 206444f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 206544f05562SScott Long } 206644f05562SScott Long /* MU post queue interrupts*/ 206744f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) { 206844f05562SScott Long arcmsr_hbb_postqueue_isr(acb); 206944f05562SScott Long } 2070d74001adSXin LI if(outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { 2071d74001adSXin LI arcmsr_hbb_message_isr(acb); 2072d74001adSXin LI } 2073d74001adSXin LI } 2074d74001adSXin LI /* 2075d74001adSXin LI ********************************************************************** 2076d74001adSXin LI ********************************************************************** 2077d74001adSXin LI */ 2078d74001adSXin LI static void arcmsr_handle_hbc_isr( struct AdapterControlBlock *acb) 2079d74001adSXin LI { 2080d74001adSXin LI u_int32_t host_interrupt_status; 2081d74001adSXin LI /* 2082d74001adSXin LI ********************************************* 2083d74001adSXin LI ** check outbound intstatus 2084d74001adSXin LI ********************************************* 2085d74001adSXin LI */ 2086d74001adSXin LI host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status); 2087d74001adSXin LI if(!host_interrupt_status) { 2088d74001adSXin LI /*it must be share irq*/ 2089d74001adSXin LI return; 2090d74001adSXin LI } 2091d74001adSXin LI /* MU doorbell interrupts*/ 2092d74001adSXin LI if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) { 2093d74001adSXin LI arcmsr_hbc_doorbell_isr(acb); 2094d74001adSXin LI } 2095d74001adSXin LI /* MU post queue interrupts*/ 2096d74001adSXin LI if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) { 2097d74001adSXin LI arcmsr_hbc_postqueue_isr(acb); 2098d74001adSXin LI } 209944f05562SScott Long } 210044f05562SScott Long /* 21017a7bc959SXin LI ********************************************************************** 21027a7bc959SXin LI ********************************************************************** 21037a7bc959SXin LI */ 21047a7bc959SXin LI static void arcmsr_handle_hbd_isr( struct AdapterControlBlock *acb) 21057a7bc959SXin LI { 21067a7bc959SXin LI u_int32_t host_interrupt_status; 21077a7bc959SXin LI u_int32_t intmask_org; 21087a7bc959SXin LI /* 21097a7bc959SXin LI ********************************************* 21107a7bc959SXin LI ** check outbound intstatus 21117a7bc959SXin LI ********************************************* 21127a7bc959SXin LI */ 21137a7bc959SXin LI host_interrupt_status = CHIP_REG_READ32(HBD_MessageUnit, 0, host_int_status) & acb->outbound_int_enable; 21147a7bc959SXin LI if(!(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_INT)) { 21157a7bc959SXin LI /*it must be share irq*/ 21167a7bc959SXin LI return; 21177a7bc959SXin LI } 21187a7bc959SXin LI /* disable outbound interrupt */ 21197a7bc959SXin LI intmask_org = CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable) ; /* disable outbound message0 int */ 21207a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, ARCMSR_HBDMU_ALL_INT_DISABLE); 21217a7bc959SXin LI /* MU doorbell interrupts*/ 21227a7bc959SXin LI if(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_DOORBELL_INT) { 21237a7bc959SXin LI arcmsr_hbd_doorbell_isr(acb); 21247a7bc959SXin LI } 21257a7bc959SXin LI /* MU post queue interrupts*/ 21267a7bc959SXin LI if(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_POSTQUEUE_INT) { 21277a7bc959SXin LI arcmsr_hbd_postqueue_isr(acb); 21287a7bc959SXin LI } 21297a7bc959SXin LI /* enable all outbound interrupt */ 21307a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, intmask_org | ARCMSR_HBDMU_ALL_INT_ENABLE); 21317a7bc959SXin LI // CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable); 21327a7bc959SXin LI } 21337a7bc959SXin LI /* 213444f05562SScott Long ****************************************************************************** 213544f05562SScott Long ****************************************************************************** 213644f05562SScott Long */ 213744f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb) 213844f05562SScott Long { 213944f05562SScott Long switch (acb->adapter_type) { 214044f05562SScott Long case ACB_ADAPTER_TYPE_A: 214144f05562SScott Long arcmsr_handle_hba_isr(acb); 2142f1c579b1SScott Long break; 214344f05562SScott Long case ACB_ADAPTER_TYPE_B: 214444f05562SScott Long arcmsr_handle_hbb_isr(acb); 2145f1c579b1SScott Long break; 2146d74001adSXin LI case ACB_ADAPTER_TYPE_C: 2147d74001adSXin LI arcmsr_handle_hbc_isr(acb); 2148d74001adSXin LI break; 21497a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 21507a7bc959SXin LI arcmsr_handle_hbd_isr(acb); 21517a7bc959SXin LI break; 2152f1c579b1SScott Long default: 215344f05562SScott Long printf("arcmsr%d: interrupt service," 215410d66948SKevin Lo " unknown adapter type =%d\n", acb->pci_unit, acb->adapter_type); 2155f1c579b1SScott Long break; 2156f1c579b1SScott Long } 2157f1c579b1SScott Long } 2158f1c579b1SScott Long /* 2159d74001adSXin LI ********************************************************************** 2160d74001adSXin LI ********************************************************************** 2161d74001adSXin LI */ 2162d74001adSXin LI static void arcmsr_intr_handler(void *arg) 2163d74001adSXin LI { 2164d74001adSXin LI struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg; 2165d74001adSXin LI 21667a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 2167d74001adSXin LI arcmsr_interrupt(acb); 21687a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 2169d74001adSXin LI } 2170d74001adSXin LI /* 2171d74001adSXin LI ****************************************************************************** 2172d74001adSXin LI ****************************************************************************** 2173d74001adSXin LI */ 2174d74001adSXin LI static void arcmsr_polling_devmap(void *arg) 2175d74001adSXin LI { 2176d74001adSXin LI struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg; 2177d74001adSXin LI switch (acb->adapter_type) { 2178d74001adSXin LI case ACB_ADAPTER_TYPE_A: 2179dac36688SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 2180d74001adSXin LI break; 2181d74001adSXin LI 2182d74001adSXin LI case ACB_ADAPTER_TYPE_B: 2183d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG); 2184d74001adSXin LI break; 2185d74001adSXin LI 2186d74001adSXin LI case ACB_ADAPTER_TYPE_C: 2187d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 2188d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 2189d74001adSXin LI break; 21907a7bc959SXin LI 21917a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 21927a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 21937a7bc959SXin LI break; 2194d74001adSXin LI } 2195d74001adSXin LI 2196d74001adSXin LI if((acb->acb_flags & ACB_F_SCSISTOPADAPTER) == 0) 2197d74001adSXin LI { 2198d74001adSXin LI callout_reset(&acb->devmap_callout, 5 * hz, arcmsr_polling_devmap, acb); /* polling per 5 seconds */ 2199d74001adSXin LI } 2200d74001adSXin LI } 2201d74001adSXin LI 2202d74001adSXin LI /* 2203ad6d6297SScott Long ******************************************************************************* 2204ad6d6297SScott Long ** 2205ad6d6297SScott Long ******************************************************************************* 2206ad6d6297SScott Long */ 2207ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb) 2208ad6d6297SScott Long { 2209d74001adSXin LI u_int32_t intmask_org; 2210d74001adSXin LI 2211ad6d6297SScott Long if(acb != NULL) { 2212ad6d6297SScott Long /* stop adapter background rebuild */ 2213ad6d6297SScott Long if(acb->acb_flags & ACB_F_MSG_START_BGRB) { 2214d74001adSXin LI intmask_org = arcmsr_disable_allintr(acb); 2215ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 2216ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2217d74001adSXin LI arcmsr_enable_allintr(acb, intmask_org); 2218ad6d6297SScott Long } 2219ad6d6297SScott Long } 2220ad6d6297SScott Long } 2221ad6d6297SScott Long /* 2222f1c579b1SScott Long *********************************************************************** 2223f1c579b1SScott Long ** 2224f1c579b1SScott Long ************************************************************************ 2225f1c579b1SScott Long */ 2226ad6d6297SScott Long u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg) 2227f1c579b1SScott Long { 2228ad6d6297SScott Long struct CMD_MESSAGE_FIELD *pcmdmessagefld; 2229ad6d6297SScott Long u_int32_t retvalue = EINVAL; 2230f1c579b1SScott Long 2231ad6d6297SScott Long pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) arg; 2232ad6d6297SScott Long if(memcmp(pcmdmessagefld->cmdmessage.Signature, "ARCMSR", 6)!=0) { 2233ad6d6297SScott Long return retvalue; 2234f1c579b1SScott Long } 2235ad6d6297SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2236ad6d6297SScott Long switch(ioctl_cmd) { 2237ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 2238ad6d6297SScott Long u_int8_t *pQbuffer; 2239ad6d6297SScott Long u_int8_t *ptmpQbuffer = pcmdmessagefld->messagedatabuffer; 2240ad6d6297SScott Long u_int32_t allxfer_len=0; 2241f1c579b1SScott Long 224244f05562SScott Long while((acb->rqbuf_firstindex != acb->rqbuf_lastindex) 224344f05562SScott Long && (allxfer_len < 1031)) { 2244f1c579b1SScott Long /*copy READ QBUFFER to srb*/ 2245ad6d6297SScott Long pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; 22467a7bc959SXin LI *ptmpQbuffer = *pQbuffer; 2247ad6d6297SScott Long acb->rqbuf_firstindex++; 2248ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 2249ad6d6297SScott Long /*if last index number set it to 0 */ 2250f1c579b1SScott Long ptmpQbuffer++; 2251f1c579b1SScott Long allxfer_len++; 2252f1c579b1SScott Long } 2253ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 225444f05562SScott Long struct QBUFFER *prbuffer; 2255f1c579b1SScott Long 2256ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 225744f05562SScott Long prbuffer = arcmsr_get_iop_rqbuffer(acb); 225835689395SXin LI if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) 225935689395SXin LI acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 2260f1c579b1SScott Long } 2261ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length = allxfer_len; 2262ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2263ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2264f1c579b1SScott Long } 2265f1c579b1SScott Long break; 2266ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 2267ad6d6297SScott Long u_int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 2268ad6d6297SScott Long u_int8_t *pQbuffer; 2269ad6d6297SScott Long u_int8_t *ptmpuserbuffer = pcmdmessagefld->messagedatabuffer; 2270f1c579b1SScott Long 2271ad6d6297SScott Long user_len = pcmdmessagefld->cmdmessage.Length; 2272f1c579b1SScott Long /*check if data xfer length of this request will overflow my array qbuffer */ 2273ad6d6297SScott Long wqbuf_lastindex = acb->wqbuf_lastindex; 2274ad6d6297SScott Long wqbuf_firstindex = acb->wqbuf_firstindex; 2275ad6d6297SScott Long if(wqbuf_lastindex != wqbuf_firstindex) { 22767a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2277ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR; 2278ad6d6297SScott Long } else { 22797a7bc959SXin LI my_empty_len = (wqbuf_firstindex - wqbuf_lastindex - 1) & 22807a7bc959SXin LI (ARCMSR_MAX_QBUFFER - 1); 2281ad6d6297SScott Long if(my_empty_len >= user_len) { 2282ad6d6297SScott Long while(user_len > 0) { 2283f1c579b1SScott Long /*copy srb data to wqbuffer*/ 2284ad6d6297SScott Long pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; 22857a7bc959SXin LI *pQbuffer = *ptmpuserbuffer; 2286ad6d6297SScott Long acb->wqbuf_lastindex++; 2287ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 2288ad6d6297SScott Long /*if last index number set it to 0 */ 2289f1c579b1SScott Long ptmpuserbuffer++; 2290f1c579b1SScott Long user_len--; 2291f1c579b1SScott Long } 2292f1c579b1SScott Long /*post fist Qbuffer*/ 2293ad6d6297SScott Long if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 2294ad6d6297SScott Long acb->acb_flags &= ~ACB_F_MESSAGE_WQBUFFER_CLEARED; 22957a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2296f1c579b1SScott Long } 2297ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2298ad6d6297SScott Long } else { 2299ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR; 2300f1c579b1SScott Long } 2301f1c579b1SScott Long } 2302ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2303f1c579b1SScott Long } 2304f1c579b1SScott Long break; 2305ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 2306ad6d6297SScott Long u_int8_t *pQbuffer = acb->rqbuffer; 2307ad6d6297SScott Long 2308ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2309ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 231044f05562SScott Long arcmsr_iop_message_read(acb); 231144f05562SScott Long /*signature, let IOP know data has been readed */ 2312f1c579b1SScott Long } 2313ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 2314ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2315ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2316f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2317ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2318ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2319f1c579b1SScott Long } 2320f1c579b1SScott Long break; 2321ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: 2322f1c579b1SScott Long { 2323ad6d6297SScott Long u_int8_t *pQbuffer = acb->wqbuffer; 2324f1c579b1SScott Long 2325ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2326ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 232744f05562SScott Long arcmsr_iop_message_read(acb); 232844f05562SScott Long /*signature, let IOP know data has been readed */ 2329f1c579b1SScott Long } 233044f05562SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ); 2331ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2332ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2333f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2334ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2335ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2336f1c579b1SScott Long } 2337f1c579b1SScott Long break; 2338ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 2339ad6d6297SScott Long u_int8_t *pQbuffer; 2340f1c579b1SScott Long 2341ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2342ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 234344f05562SScott Long arcmsr_iop_message_read(acb); 234444f05562SScott Long /*signature, let IOP know data has been readed */ 2345f1c579b1SScott Long } 2346ad6d6297SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED 2347ad6d6297SScott Long |ACB_F_MESSAGE_RQBUFFER_CLEARED 234844f05562SScott Long |ACB_F_MESSAGE_WQBUFFER_READ); 2349ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2350ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2351ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2352ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2353ad6d6297SScott Long pQbuffer = acb->rqbuffer; 2354ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 2355ad6d6297SScott Long pQbuffer = acb->wqbuffer; 2356ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 2357ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2358ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2359f1c579b1SScott Long } 2360f1c579b1SScott Long break; 2361ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 2362ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; 2363ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2364f1c579b1SScott Long } 2365f1c579b1SScott Long break; 2366ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 2367ad6d6297SScott Long u_int8_t *hello_string = "Hello! I am ARCMSR"; 2368ad6d6297SScott Long u_int8_t *puserbuffer = (u_int8_t *)pcmdmessagefld->messagedatabuffer; 2369f1c579b1SScott Long 2370ad6d6297SScott Long if(memcpy(puserbuffer, hello_string, (int16_t)strlen(hello_string))) { 2371ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR; 2372ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2373f1c579b1SScott Long return ENOIOCTL; 2374f1c579b1SScott Long } 2375ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2376ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2377ad6d6297SScott Long } 2378ad6d6297SScott Long break; 2379ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: { 2380ad6d6297SScott Long arcmsr_iop_parking(acb); 2381ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2382ad6d6297SScott Long } 2383ad6d6297SScott Long break; 2384ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: { 2385ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2386ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2387f1c579b1SScott Long } 2388f1c579b1SScott Long break; 2389f1c579b1SScott Long } 2390ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2391dac36688SXin LI return (retvalue); 2392f1c579b1SScott Long } 2393f1c579b1SScott Long /* 2394f1c579b1SScott Long ************************************************************************** 2395f1c579b1SScott Long ************************************************************************** 2396f1c579b1SScott Long */ 239722f2616bSXin LI static void arcmsr_free_srb(struct CommandControlBlock *srb) 239822f2616bSXin LI { 239922f2616bSXin LI struct AdapterControlBlock *acb; 240022f2616bSXin LI 240122f2616bSXin LI acb = srb->acb; 24027a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->srb_lock); 240322f2616bSXin LI srb->srb_state = ARCMSR_SRB_DONE; 240422f2616bSXin LI srb->srb_flags = 0; 240522f2616bSXin LI acb->srbworkingQ[acb->workingsrb_doneindex] = srb; 240622f2616bSXin LI acb->workingsrb_doneindex++; 240722f2616bSXin LI acb->workingsrb_doneindex %= ARCMSR_MAX_FREESRB_NUM; 24087a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->srb_lock); 240922f2616bSXin LI } 241022f2616bSXin LI /* 241122f2616bSXin LI ************************************************************************** 241222f2616bSXin LI ************************************************************************** 241322f2616bSXin LI */ 2414ad6d6297SScott Long struct CommandControlBlock *arcmsr_get_freesrb(struct AdapterControlBlock *acb) 2415f1c579b1SScott Long { 2416ad6d6297SScott Long struct CommandControlBlock *srb = NULL; 2417ad6d6297SScott Long u_int32_t workingsrb_startindex, workingsrb_doneindex; 2418f1c579b1SScott Long 24197a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->srb_lock); 2420ad6d6297SScott Long workingsrb_doneindex = acb->workingsrb_doneindex; 2421ad6d6297SScott Long workingsrb_startindex = acb->workingsrb_startindex; 2422ad6d6297SScott Long srb = acb->srbworkingQ[workingsrb_startindex]; 2423ad6d6297SScott Long workingsrb_startindex++; 2424ad6d6297SScott Long workingsrb_startindex %= ARCMSR_MAX_FREESRB_NUM; 2425ad6d6297SScott Long if(workingsrb_doneindex != workingsrb_startindex) { 2426ad6d6297SScott Long acb->workingsrb_startindex = workingsrb_startindex; 2427ad6d6297SScott Long } else { 2428ad6d6297SScott Long srb = NULL; 2429ad6d6297SScott Long } 24307a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->srb_lock); 2431ad6d6297SScott Long return(srb); 2432ad6d6297SScott Long } 2433ad6d6297SScott Long /* 2434ad6d6297SScott Long ************************************************************************** 2435ad6d6297SScott Long ************************************************************************** 2436ad6d6297SScott Long */ 2437ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *pccb) 2438ad6d6297SScott Long { 2439ad6d6297SScott Long struct CMD_MESSAGE_FIELD *pcmdmessagefld; 2440ad6d6297SScott Long int retvalue = 0, transfer_len = 0; 2441ad6d6297SScott Long char *buffer; 244244f05562SScott Long u_int32_t controlcode = (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[5] << 24 | 244344f05562SScott Long (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[6] << 16 | 244444f05562SScott Long (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[7] << 8 | 244544f05562SScott Long (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[8]; 2446ad6d6297SScott Long /* 4 bytes: Areca io control code */ 2447dd0b4fb6SKonstantin Belousov if ((pccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) { 2448ad6d6297SScott Long buffer = pccb->csio.data_ptr; 2449ad6d6297SScott Long transfer_len = pccb->csio.dxfer_len; 2450ad6d6297SScott Long } else { 2451ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2452ad6d6297SScott Long goto message_out; 2453ad6d6297SScott Long } 2454ad6d6297SScott Long if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) { 2455ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2456ad6d6297SScott Long goto message_out; 2457ad6d6297SScott Long } 2458ad6d6297SScott Long pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer; 2459ad6d6297SScott Long switch(controlcode) { 2460ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 2461ad6d6297SScott Long u_int8_t *pQbuffer; 2462ad6d6297SScott Long u_int8_t *ptmpQbuffer = pcmdmessagefld->messagedatabuffer; 2463ad6d6297SScott Long int32_t allxfer_len = 0; 2464f1c579b1SScott Long 24657a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2466ad6d6297SScott Long while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) 2467ad6d6297SScott Long && (allxfer_len < 1031)) { 2468ad6d6297SScott Long pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; 24697a7bc959SXin LI *ptmpQbuffer = *pQbuffer; 2470ad6d6297SScott Long acb->rqbuf_firstindex++; 2471ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 2472ad6d6297SScott Long ptmpQbuffer++; 2473ad6d6297SScott Long allxfer_len++; 2474f1c579b1SScott Long } 2475ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 247644f05562SScott Long struct QBUFFER *prbuffer; 2477ad6d6297SScott Long 2478ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 247944f05562SScott Long prbuffer = arcmsr_get_iop_rqbuffer(acb); 248035689395SXin LI if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) 248135689395SXin LI acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 2482ad6d6297SScott Long } 2483ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length = allxfer_len; 2484ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2485ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 24867a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2487ad6d6297SScott Long } 2488ad6d6297SScott Long break; 2489ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 2490ad6d6297SScott Long int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 2491ad6d6297SScott Long u_int8_t *pQbuffer; 2492ad6d6297SScott Long u_int8_t *ptmpuserbuffer = pcmdmessagefld->messagedatabuffer; 2493ad6d6297SScott Long 2494ad6d6297SScott Long user_len = pcmdmessagefld->cmdmessage.Length; 24957a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2496ad6d6297SScott Long wqbuf_lastindex = acb->wqbuf_lastindex; 2497ad6d6297SScott Long wqbuf_firstindex = acb->wqbuf_firstindex; 2498ad6d6297SScott Long if (wqbuf_lastindex != wqbuf_firstindex) { 24997a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2500ad6d6297SScott Long /* has error report sensedata */ 2501dac36688SXin LI if(pccb->csio.sense_len) { 2502ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 2503ad6d6297SScott Long /* Valid,ErrorCode */ 2504ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 2505ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 2506ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 2507ad6d6297SScott Long /* AdditionalSenseLength */ 2508ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 2509ad6d6297SScott Long /* AdditionalSenseCode */ 2510ad6d6297SScott Long } 2511ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2512ad6d6297SScott Long } else { 2513ad6d6297SScott Long my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) 2514ad6d6297SScott Long &(ARCMSR_MAX_QBUFFER - 1); 2515ad6d6297SScott Long if (my_empty_len >= user_len) { 2516ad6d6297SScott Long while (user_len > 0) { 2517ad6d6297SScott Long pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; 25187a7bc959SXin LI *pQbuffer = *ptmpuserbuffer; 2519ad6d6297SScott Long acb->wqbuf_lastindex++; 2520ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 2521ad6d6297SScott Long ptmpuserbuffer++; 2522ad6d6297SScott Long user_len--; 2523ad6d6297SScott Long } 2524ad6d6297SScott Long if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 2525ad6d6297SScott Long acb->acb_flags &= 2526ad6d6297SScott Long ~ACB_F_MESSAGE_WQBUFFER_CLEARED; 25277a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2528ad6d6297SScott Long } 2529ad6d6297SScott Long } else { 2530ad6d6297SScott Long /* has error report sensedata */ 2531dac36688SXin LI if(pccb->csio.sense_len) { 2532ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 2533ad6d6297SScott Long /* Valid,ErrorCode */ 2534ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 2535ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 2536ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 2537ad6d6297SScott Long /* AdditionalSenseLength */ 2538ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 2539ad6d6297SScott Long /* AdditionalSenseCode */ 2540ad6d6297SScott Long } 2541ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2542ad6d6297SScott Long } 2543ad6d6297SScott Long } 25447a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2545ad6d6297SScott Long } 2546ad6d6297SScott Long break; 2547ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 2548ad6d6297SScott Long u_int8_t *pQbuffer = acb->rqbuffer; 2549ad6d6297SScott Long 25507a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2551ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2552ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 255344f05562SScott Long arcmsr_iop_message_read(acb); 2554ad6d6297SScott Long } 2555ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 2556ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2557ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2558ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2559ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 2560ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 25617a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2562ad6d6297SScott Long } 2563ad6d6297SScott Long break; 2564ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { 2565ad6d6297SScott Long u_int8_t *pQbuffer = acb->wqbuffer; 2566ad6d6297SScott Long 25677a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2568ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2569ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 257044f05562SScott Long arcmsr_iop_message_read(acb); 2571ad6d6297SScott Long } 2572ad6d6297SScott Long acb->acb_flags |= 2573ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED | 257444f05562SScott Long ACB_F_MESSAGE_WQBUFFER_READ); 2575ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2576ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2577ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2578ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 2579ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 25807a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2581ad6d6297SScott Long } 2582ad6d6297SScott Long break; 2583ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 2584ad6d6297SScott Long u_int8_t *pQbuffer; 2585ad6d6297SScott Long 25867a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2587ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2588ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 258944f05562SScott Long arcmsr_iop_message_read(acb); 2590ad6d6297SScott Long } 2591ad6d6297SScott Long acb->acb_flags |= 2592ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED 2593ad6d6297SScott Long | ACB_F_MESSAGE_RQBUFFER_CLEARED 259444f05562SScott Long | ACB_F_MESSAGE_WQBUFFER_READ); 2595ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2596ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2597ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2598ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2599ad6d6297SScott Long pQbuffer = acb->rqbuffer; 2600ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 2601ad6d6297SScott Long pQbuffer = acb->wqbuffer; 2602ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 2603ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 26047a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2605ad6d6297SScott Long } 2606ad6d6297SScott Long break; 2607ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 2608ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; 2609ad6d6297SScott Long } 2610ad6d6297SScott Long break; 2611ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 2612ad6d6297SScott Long int8_t *hello_string = "Hello! I am ARCMSR"; 2613ad6d6297SScott Long 2614ad6d6297SScott Long memcpy(pcmdmessagefld->messagedatabuffer, hello_string 2615ad6d6297SScott Long , (int16_t)strlen(hello_string)); 2616ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2617ad6d6297SScott Long } 2618ad6d6297SScott Long break; 2619ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: 2620ad6d6297SScott Long arcmsr_iop_parking(acb); 2621ad6d6297SScott Long break; 2622ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: 2623ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2624ad6d6297SScott Long break; 2625ad6d6297SScott Long default: 2626ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2627ad6d6297SScott Long } 2628ad6d6297SScott Long message_out: 2629dac36688SXin LI return (retvalue); 2630f1c579b1SScott Long } 2631f1c579b1SScott Long /* 2632f1c579b1SScott Long ********************************************************************* 2633f1c579b1SScott Long ********************************************************************* 2634f1c579b1SScott Long */ 2635231c8b71SXin LI static void arcmsr_execute_srb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 2636f1c579b1SScott Long { 2637ad6d6297SScott Long struct CommandControlBlock *srb = (struct CommandControlBlock *)arg; 2638ad6d6297SScott Long struct AdapterControlBlock *acb = (struct AdapterControlBlock *)srb->acb; 2639f1c579b1SScott Long union ccb *pccb; 2640ad6d6297SScott Long int target, lun; 2641f1c579b1SScott Long 2642ad6d6297SScott Long pccb = srb->pccb; 2643ad6d6297SScott Long target = pccb->ccb_h.target_id; 2644ad6d6297SScott Long lun = pccb->ccb_h.target_lun; 264522f2616bSXin LI acb->pktRequestCount++; 2646ad6d6297SScott Long if(error != 0) { 2647ad6d6297SScott Long if(error != EFBIG) { 264844f05562SScott Long printf("arcmsr%d: unexpected error %x" 264944f05562SScott Long " returned from 'bus_dmamap_load' \n" 2650ad6d6297SScott Long , acb->pci_unit, error); 2651f1c579b1SScott Long } 2652ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { 265315735becSScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 2654f1c579b1SScott Long } 2655ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2656f1c579b1SScott Long return; 2657f1c579b1SScott Long } 2658ad6d6297SScott Long if(nseg > ARCMSR_MAX_SG_ENTRIES) { 2659ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 2660ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2661ad6d6297SScott Long return; 2662f1c579b1SScott Long } 2663ad6d6297SScott Long if(acb->acb_flags & ACB_F_BUS_RESET) { 2664ad6d6297SScott Long printf("arcmsr%d: bus reset and return busy \n", acb->pci_unit); 2665ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_BUS_RESET; 2666ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2667ad6d6297SScott Long return; 2668ad6d6297SScott Long } 2669ad6d6297SScott Long if(acb->devstate[target][lun] == ARECA_RAID_GONE) { 267022f2616bSXin LI u_int8_t block_cmd, cmd; 2671ad6d6297SScott Long 267222f2616bSXin LI cmd = pccb->csio.cdb_io.cdb_bytes[0]; 267322f2616bSXin LI block_cmd = cmd & 0x0f; 2674ad6d6297SScott Long if(block_cmd == 0x08 || block_cmd == 0x0a) { 2675ad6d6297SScott Long printf("arcmsr%d:block 'read/write' command " 267622f2616bSXin LI "with gone raid volume Cmd=0x%2x, TargetId=%d, Lun=%d \n" 267722f2616bSXin LI , acb->pci_unit, cmd, target, lun); 2678ad6d6297SScott Long pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 2679ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2680ad6d6297SScott Long return; 2681ad6d6297SScott Long } 2682ad6d6297SScott Long } 2683ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { 2684ad6d6297SScott Long if(nseg != 0) { 2685ad6d6297SScott Long bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 2686ad6d6297SScott Long } 2687ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2688f1c579b1SScott Long return; 2689f1c579b1SScott Long } 2690*abfdbca9SXin LI if(acb->srboutstandingcount >= acb->maxOutstanding) { 26917a7bc959SXin LI if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) == 0) 26927a7bc959SXin LI { 269315735becSScott Long xpt_freeze_simq(acb->psim, 1); 2694dc3a205bSScott Long acb->acb_flags |= ACB_F_CAM_DEV_QFRZN; 26957a7bc959SXin LI } 26967a7bc959SXin LI pccb->ccb_h.status &= ~CAM_SIM_QUEUED; 26977a7bc959SXin LI pccb->ccb_h.status |= CAM_REQUEUE_REQ; 2698ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2699ad6d6297SScott Long return; 2700f1c579b1SScott Long } 270115735becSScott Long pccb->ccb_h.status |= CAM_SIM_QUEUED; 2702ad6d6297SScott Long arcmsr_build_srb(srb, dm_segs, nseg); 2703ad6d6297SScott Long arcmsr_post_srb(acb, srb); 270422f2616bSXin LI if (pccb->ccb_h.timeout != CAM_TIME_INFINITY) 270522f2616bSXin LI { 270622f2616bSXin LI arcmsr_callout_init(&srb->ccb_callout); 2707dac36688SXin LI callout_reset(&srb->ccb_callout, ((pccb->ccb_h.timeout + (ARCMSR_TIMEOUT_DELAY * 1000)) * hz) / 1000, arcmsr_srb_timeout, srb); 270822f2616bSXin LI srb->srb_flags |= SRB_FLAG_TIMER_START; 270922f2616bSXin LI } 2710f1c579b1SScott Long } 2711f1c579b1SScott Long /* 2712f1c579b1SScott Long ***************************************************************************************** 2713f1c579b1SScott Long ***************************************************************************************** 2714f1c579b1SScott Long */ 2715ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb *abortccb) 2716f1c579b1SScott Long { 2717ad6d6297SScott Long struct CommandControlBlock *srb; 2718ad6d6297SScott Long struct AdapterControlBlock *acb = (struct AdapterControlBlock *) abortccb->ccb_h.arcmsr_ccbacb_ptr; 271944f05562SScott Long u_int32_t intmask_org; 2720ad6d6297SScott Long int i = 0; 2721f1c579b1SScott Long 2722ad6d6297SScott Long acb->num_aborts++; 2723f1c579b1SScott Long /* 2724ad6d6297SScott Long *************************************************************************** 2725f1c579b1SScott Long ** It is the upper layer do abort command this lock just prior to calling us. 2726f1c579b1SScott Long ** First determine if we currently own this command. 2727f1c579b1SScott Long ** Start by searching the device queue. If not found 2728f1c579b1SScott Long ** at all, and the system wanted us to just abort the 2729f1c579b1SScott Long ** command return success. 2730ad6d6297SScott Long *************************************************************************** 2731f1c579b1SScott Long */ 2732ad6d6297SScott Long if(acb->srboutstandingcount != 0) { 273322f2616bSXin LI /* disable all outbound interrupt */ 273422f2616bSXin LI intmask_org = arcmsr_disable_allintr(acb); 2735ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 2736ad6d6297SScott Long srb = acb->psrb_pool[i]; 273722f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) { 2738ad6d6297SScott Long if(srb->pccb == abortccb) { 273922f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 2740ad6d6297SScott Long printf("arcmsr%d:scsi id=%d lun=%d abort srb '%p'" 2741ad6d6297SScott Long "outstanding command \n" 2742ad6d6297SScott Long , acb->pci_unit, abortccb->ccb_h.target_id 2743ad6d6297SScott Long , abortccb->ccb_h.target_lun, srb); 2744ad6d6297SScott Long arcmsr_polling_srbdone(acb, srb); 274544f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 274644f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 2747ad6d6297SScott Long return (TRUE); 2748f1c579b1SScott Long } 274922f2616bSXin LI } 275022f2616bSXin LI } 275122f2616bSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 275222f2616bSXin LI arcmsr_enable_allintr(acb, intmask_org); 275322f2616bSXin LI } 275422f2616bSXin LI return(FALSE); 275522f2616bSXin LI } 2756f1c579b1SScott Long /* 2757f1c579b1SScott Long **************************************************************************** 2758f1c579b1SScott Long **************************************************************************** 2759f1c579b1SScott Long */ 2760ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb) 2761f1c579b1SScott Long { 2762ad6d6297SScott Long int retry = 0; 2763f1c579b1SScott Long 2764ad6d6297SScott Long acb->num_resets++; 2765ad6d6297SScott Long acb->acb_flags |= ACB_F_BUS_RESET; 2766ad6d6297SScott Long while(acb->srboutstandingcount != 0 && retry < 400) { 276744f05562SScott Long arcmsr_interrupt(acb); 2768ad6d6297SScott Long UDELAY(25000); 2769ad6d6297SScott Long retry++; 2770ad6d6297SScott Long } 2771ad6d6297SScott Long arcmsr_iop_reset(acb); 2772ad6d6297SScott Long acb->acb_flags &= ~ACB_F_BUS_RESET; 2773f1c579b1SScott Long } 2774f1c579b1SScott Long /* 2775ad6d6297SScott Long ************************************************************************** 2776ad6d6297SScott Long ************************************************************************** 2777ad6d6297SScott Long */ 2778ad6d6297SScott Long static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, 2779ad6d6297SScott Long union ccb *pccb) 2780ad6d6297SScott Long { 2781ad6d6297SScott Long if (pccb->ccb_h.target_lun) { 278261ba2ac6SJim Harris pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 2783ad6d6297SScott Long xpt_done(pccb); 2784ad6d6297SScott Long return; 2785ad6d6297SScott Long } 27867a7bc959SXin LI pccb->ccb_h.status |= CAM_REQ_CMP; 27877a7bc959SXin LI switch (pccb->csio.cdb_io.cdb_bytes[0]) { 27887a7bc959SXin LI case INQUIRY: { 27897a7bc959SXin LI unsigned char inqdata[36]; 27907a7bc959SXin LI char *buffer = pccb->csio.data_ptr; 27917a7bc959SXin LI 2792231c8b71SXin LI inqdata[0] = T_PROCESSOR; /* Periph Qualifier & Periph Dev Type */ 2793231c8b71SXin LI inqdata[1] = 0; /* rem media bit & Dev Type Modifier */ 2794231c8b71SXin LI inqdata[2] = 0; /* ISO, ECMA, & ANSI versions */ 2795231c8b71SXin LI inqdata[3] = 0; 2796231c8b71SXin LI inqdata[4] = 31; /* length of additional data */ 2797231c8b71SXin LI inqdata[5] = 0; 2798231c8b71SXin LI inqdata[6] = 0; 2799231c8b71SXin LI inqdata[7] = 0; 2800231c8b71SXin LI strncpy(&inqdata[8], "Areca ", 8); /* Vendor Identification */ 2801231c8b71SXin LI strncpy(&inqdata[16], "RAID controller ", 16); /* Product Identification */ 2802ad6d6297SScott Long strncpy(&inqdata[32], "R001", 4); /* Product Revision */ 2803ad6d6297SScott Long memcpy(buffer, inqdata, sizeof(inqdata)); 2804ad6d6297SScott Long xpt_done(pccb); 2805ad6d6297SScott Long } 2806ad6d6297SScott Long break; 2807ad6d6297SScott Long case WRITE_BUFFER: 2808ad6d6297SScott Long case READ_BUFFER: { 2809ad6d6297SScott Long if (arcmsr_iop_message_xfer(acb, pccb)) { 2810ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 2811ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 2812ad6d6297SScott Long } 2813ad6d6297SScott Long xpt_done(pccb); 2814ad6d6297SScott Long } 2815ad6d6297SScott Long break; 2816ad6d6297SScott Long default: 2817ad6d6297SScott Long xpt_done(pccb); 2818ad6d6297SScott Long } 2819ad6d6297SScott Long } 2820ad6d6297SScott Long /* 2821f1c579b1SScott Long ********************************************************************* 2822f1c579b1SScott Long ********************************************************************* 2823f1c579b1SScott Long */ 2824ad6d6297SScott Long static void arcmsr_action(struct cam_sim *psim, union ccb *pccb) 2825f1c579b1SScott Long { 2826ad6d6297SScott Long struct AdapterControlBlock *acb; 2827f1c579b1SScott Long 2828ad6d6297SScott Long acb = (struct AdapterControlBlock *) cam_sim_softc(psim); 2829ad6d6297SScott Long if(acb == NULL) { 2830ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2831f1c579b1SScott Long xpt_done(pccb); 2832f1c579b1SScott Long return; 2833f1c579b1SScott Long } 2834ad6d6297SScott Long switch (pccb->ccb_h.func_code) { 2835ad6d6297SScott Long case XPT_SCSI_IO: { 2836ad6d6297SScott Long struct CommandControlBlock *srb; 2837ad6d6297SScott Long int target = pccb->ccb_h.target_id; 2838dd0b4fb6SKonstantin Belousov int error; 2839f1c579b1SScott Long 2840ad6d6297SScott Long if(target == 16) { 2841ad6d6297SScott Long /* virtual device for iop message transfer */ 2842ad6d6297SScott Long arcmsr_handle_virtual_command(acb, pccb); 2843ad6d6297SScott Long return; 2844ad6d6297SScott Long } 2845ad6d6297SScott Long if((srb = arcmsr_get_freesrb(acb)) == NULL) { 2846ad6d6297SScott Long pccb->ccb_h.status |= CAM_RESRC_UNAVAIL; 2847f1c579b1SScott Long xpt_done(pccb); 2848f1c579b1SScott Long return; 2849f1c579b1SScott Long } 2850ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbsrb_ptr = srb; 2851ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbacb_ptr = acb; 2852ad6d6297SScott Long srb->pccb = pccb; 2853dd0b4fb6SKonstantin Belousov error = bus_dmamap_load_ccb(acb->dm_segs_dmat 2854ad6d6297SScott Long , srb->dm_segs_dmamap 2855dd0b4fb6SKonstantin Belousov , pccb 2856231c8b71SXin LI , arcmsr_execute_srb, srb, /*flags*/0); 2857ad6d6297SScott Long if(error == EINPROGRESS) { 2858ad6d6297SScott Long xpt_freeze_simq(acb->psim, 1); 2859f1c579b1SScott Long pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 2860f1c579b1SScott Long } 2861f1c579b1SScott Long break; 2862f1c579b1SScott Long } 2863ad6d6297SScott Long case XPT_TARGET_IO: { 2864ad6d6297SScott Long /* target mode not yet support vendor specific commands. */ 2865ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2866f1c579b1SScott Long xpt_done(pccb); 2867f1c579b1SScott Long break; 2868f1c579b1SScott Long } 2869ad6d6297SScott Long case XPT_PATH_INQ: { 2870f1c579b1SScott Long struct ccb_pathinq *cpi = &pccb->cpi; 2871f1c579b1SScott Long 2872f1c579b1SScott Long cpi->version_num = 1; 2873f1c579b1SScott Long cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE; 2874f1c579b1SScott Long cpi->target_sprt = 0; 2875f1c579b1SScott Long cpi->hba_misc = 0; 2876f1c579b1SScott Long cpi->hba_eng_cnt = 0; 2877ad6d6297SScott Long cpi->max_target = ARCMSR_MAX_TARGETID; /* 0-16 */ 2878ad6d6297SScott Long cpi->max_lun = ARCMSR_MAX_TARGETLUN; /* 0-7 */ 2879ad6d6297SScott Long cpi->initiator_id = ARCMSR_SCSI_INITIATOR_ID; /* 255 */ 2880f1c579b1SScott Long cpi->bus_id = cam_sim_bus(psim); 2881f1c579b1SScott Long strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 2882f1c579b1SScott Long strncpy(cpi->hba_vid, "ARCMSR", HBA_IDLEN); 2883f1c579b1SScott Long strncpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN); 2884f1c579b1SScott Long cpi->unit_number = cam_sim_unit(psim); 288544f05562SScott Long #ifdef CAM_NEW_TRAN_CODE 2886dac36688SXin LI if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G) 2887dac36688SXin LI cpi->base_transfer_speed = 600000; 2888dac36688SXin LI else 2889dac36688SXin LI cpi->base_transfer_speed = 300000; 2890dac36688SXin LI if((acb->vendor_device_id == PCIDevVenIDARC1880) || 28917a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1680) || 28927a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1214)) 2893dac36688SXin LI { 2894dac36688SXin LI cpi->transport = XPORT_SAS; 2895dac36688SXin LI cpi->transport_version = 0; 2896dac36688SXin LI cpi->protocol_version = SCSI_REV_SPC2; 2897dac36688SXin LI } 2898dac36688SXin LI else 2899dac36688SXin LI { 2900fa9ed865SMatt Jacob cpi->transport = XPORT_SPI; 2901fa9ed865SMatt Jacob cpi->transport_version = 2; 2902fa9ed865SMatt Jacob cpi->protocol_version = SCSI_REV_2; 2903dac36688SXin LI } 2904dac36688SXin LI cpi->protocol = PROTO_SCSI; 290544f05562SScott Long #endif 2906ad6d6297SScott Long cpi->ccb_h.status |= CAM_REQ_CMP; 2907f1c579b1SScott Long xpt_done(pccb); 2908f1c579b1SScott Long break; 2909f1c579b1SScott Long } 2910ad6d6297SScott Long case XPT_ABORT: { 2911f1c579b1SScott Long union ccb *pabort_ccb; 2912f1c579b1SScott Long 2913f1c579b1SScott Long pabort_ccb = pccb->cab.abort_ccb; 2914ad6d6297SScott Long switch (pabort_ccb->ccb_h.func_code) { 2915f1c579b1SScott Long case XPT_ACCEPT_TARGET_IO: 2916f1c579b1SScott Long case XPT_IMMED_NOTIFY: 2917f1c579b1SScott Long case XPT_CONT_TARGET_IO: 2918ad6d6297SScott Long if(arcmsr_seek_cmd2abort(pabort_ccb)==TRUE) { 2919ad6d6297SScott Long pabort_ccb->ccb_h.status |= CAM_REQ_ABORTED; 2920f1c579b1SScott Long xpt_done(pabort_ccb); 2921ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2922ad6d6297SScott Long } else { 2923f1c579b1SScott Long xpt_print_path(pabort_ccb->ccb_h.path); 2924f1c579b1SScott Long printf("Not found\n"); 2925ad6d6297SScott Long pccb->ccb_h.status |= CAM_PATH_INVALID; 2926f1c579b1SScott Long } 2927f1c579b1SScott Long break; 2928f1c579b1SScott Long case XPT_SCSI_IO: 2929ad6d6297SScott Long pccb->ccb_h.status |= CAM_UA_ABORT; 2930f1c579b1SScott Long break; 2931f1c579b1SScott Long default: 2932ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2933f1c579b1SScott Long break; 2934f1c579b1SScott Long } 2935f1c579b1SScott Long xpt_done(pccb); 2936f1c579b1SScott Long break; 2937f1c579b1SScott Long } 2938f1c579b1SScott Long case XPT_RESET_BUS: 2939ad6d6297SScott Long case XPT_RESET_DEV: { 2940ad6d6297SScott Long u_int32_t i; 2941f1c579b1SScott Long 2942ad6d6297SScott Long arcmsr_bus_reset(acb); 2943ad6d6297SScott Long for (i=0; i < 500; i++) { 2944f1c579b1SScott Long DELAY(1000); 2945f1c579b1SScott Long } 2946ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2947f1c579b1SScott Long xpt_done(pccb); 2948f1c579b1SScott Long break; 2949f1c579b1SScott Long } 2950ad6d6297SScott Long case XPT_TERM_IO: { 2951ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2952f1c579b1SScott Long xpt_done(pccb); 2953f1c579b1SScott Long break; 2954f1c579b1SScott Long } 2955ad6d6297SScott Long case XPT_GET_TRAN_SETTINGS: { 2956ad6d6297SScott Long struct ccb_trans_settings *cts; 2957ad6d6297SScott Long 2958ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 2959ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 2960ad6d6297SScott Long xpt_done(pccb); 2961ad6d6297SScott Long break; 2962ad6d6297SScott Long } 2963ad6d6297SScott Long cts = &pccb->cts; 296444f05562SScott Long #ifdef CAM_NEW_TRAN_CODE 296544f05562SScott Long { 296644f05562SScott Long struct ccb_trans_settings_scsi *scsi; 296744f05562SScott Long struct ccb_trans_settings_spi *spi; 2968dac36688SXin LI struct ccb_trans_settings_sas *sas; 296944f05562SScott Long 2970ad6d6297SScott Long scsi = &cts->proto_specific.scsi; 2971dac36688SXin LI scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 2972dac36688SXin LI scsi->valid = CTS_SCSI_VALID_TQ; 2973fa9ed865SMatt Jacob cts->protocol = PROTO_SCSI; 2974dac36688SXin LI 2975dac36688SXin LI if((acb->vendor_device_id == PCIDevVenIDARC1880) || 29767a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1680) || 29777a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1214)) 2978dac36688SXin LI { 2979dac36688SXin LI cts->protocol_version = SCSI_REV_SPC2; 2980dac36688SXin LI cts->transport_version = 0; 2981dac36688SXin LI cts->transport = XPORT_SAS; 2982dac36688SXin LI sas = &cts->xport_specific.sas; 2983dac36688SXin LI sas->valid = CTS_SAS_VALID_SPEED; 29847a7bc959SXin LI if((acb->vendor_device_id == PCIDevVenIDARC1880) || 29857a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1214)) 2986dac36688SXin LI sas->bitrate = 600000; 2987dac36688SXin LI else if(acb->vendor_device_id == PCIDevVenIDARC1680) 2988dac36688SXin LI sas->bitrate = 300000; 2989dac36688SXin LI } 2990dac36688SXin LI else 2991dac36688SXin LI { 2992fa9ed865SMatt Jacob cts->protocol_version = SCSI_REV_2; 2993fa9ed865SMatt Jacob cts->transport_version = 2; 2994dac36688SXin LI cts->transport = XPORT_SPI; 2995dac36688SXin LI spi = &cts->xport_specific.spi; 2996fa9ed865SMatt Jacob spi->flags = CTS_SPI_FLAGS_DISC_ENB; 2997dac36688SXin LI spi->sync_period = 2; 2998fa9ed865SMatt Jacob spi->sync_offset = 32; 2999fa9ed865SMatt Jacob spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 30009d98ff4dSScott Long spi->valid = CTS_SPI_VALID_DISC 30019d98ff4dSScott Long | CTS_SPI_VALID_SYNC_RATE 3002fa9ed865SMatt Jacob | CTS_SPI_VALID_SYNC_OFFSET 3003fa9ed865SMatt Jacob | CTS_SPI_VALID_BUS_WIDTH; 3004dac36688SXin LI } 300544f05562SScott Long } 300644f05562SScott Long #else 300744f05562SScott Long { 300844f05562SScott Long cts->flags = (CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB); 3009dac36688SXin LI cts->sync_period = 2; 301044f05562SScott Long cts->sync_offset = 32; 301144f05562SScott Long cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 301244f05562SScott Long cts->valid = CCB_TRANS_SYNC_RATE_VALID | 301344f05562SScott Long CCB_TRANS_SYNC_OFFSET_VALID | 301444f05562SScott Long CCB_TRANS_BUS_WIDTH_VALID | 301544f05562SScott Long CCB_TRANS_DISC_VALID | 301644f05562SScott Long CCB_TRANS_TQ_VALID; 301744f05562SScott Long } 301844f05562SScott Long #endif 3019ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 3020ad6d6297SScott Long xpt_done(pccb); 3021ad6d6297SScott Long break; 3022ad6d6297SScott Long } 3023ad6d6297SScott Long case XPT_SET_TRAN_SETTINGS: { 3024ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 3025ad6d6297SScott Long xpt_done(pccb); 3026ad6d6297SScott Long break; 3027ad6d6297SScott Long } 3028f3b080e6SMarius Strobl case XPT_CALC_GEOMETRY: 3029ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 3030ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 3031ad6d6297SScott Long xpt_done(pccb); 3032ad6d6297SScott Long break; 3033ad6d6297SScott Long } 3034f3b080e6SMarius Strobl #if __FreeBSD_version >= 500000 3035f3b080e6SMarius Strobl cam_calc_geometry(&pccb->ccg, 1); 3036f3b080e6SMarius Strobl #else 3037f3b080e6SMarius Strobl { 3038f3b080e6SMarius Strobl struct ccb_calc_geometry *ccg; 3039f3b080e6SMarius Strobl u_int32_t size_mb; 3040f3b080e6SMarius Strobl u_int32_t secs_per_cylinder; 3041f3b080e6SMarius Strobl 3042f1c579b1SScott Long ccg = &pccb->ccg; 3043ad6d6297SScott Long if (ccg->block_size == 0) { 3044ad6d6297SScott Long pccb->ccb_h.status = CAM_REQ_INVALID; 3045ad6d6297SScott Long xpt_done(pccb); 3046ad6d6297SScott Long break; 3047ad6d6297SScott Long } 3048ad6d6297SScott Long if(((1024L * 1024L)/ccg->block_size) < 0) { 3049ad6d6297SScott Long pccb->ccb_h.status = CAM_REQ_INVALID; 3050ad6d6297SScott Long xpt_done(pccb); 3051ad6d6297SScott Long break; 3052ad6d6297SScott Long } 3053f1c579b1SScott Long size_mb = ccg->volume_size/((1024L * 1024L)/ccg->block_size); 3054ad6d6297SScott Long if(size_mb > 1024 ) { 3055f1c579b1SScott Long ccg->heads = 255; 3056f1c579b1SScott Long ccg->secs_per_track = 63; 3057ad6d6297SScott Long } else { 3058f1c579b1SScott Long ccg->heads = 64; 3059f1c579b1SScott Long ccg->secs_per_track = 32; 3060f1c579b1SScott Long } 3061f1c579b1SScott Long secs_per_cylinder = ccg->heads * ccg->secs_per_track; 3062f1c579b1SScott Long ccg->cylinders = ccg->volume_size / secs_per_cylinder; 3063ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 3064f3b080e6SMarius Strobl } 3065f3b080e6SMarius Strobl #endif 3066f1c579b1SScott Long xpt_done(pccb); 3067f1c579b1SScott Long break; 3068f1c579b1SScott Long default: 3069ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 3070f1c579b1SScott Long xpt_done(pccb); 3071f1c579b1SScott Long break; 3072f1c579b1SScott Long } 3073f1c579b1SScott Long } 3074f1c579b1SScott Long /* 3075f1c579b1SScott Long ********************************************************************** 3076f1c579b1SScott Long ********************************************************************** 3077f1c579b1SScott Long */ 307844f05562SScott Long static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) 3079f1c579b1SScott Long { 3080ad6d6297SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 308144f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 308244f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 3083ad6d6297SScott Long printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 3084ad6d6297SScott Long } 3085f1c579b1SScott Long } 3086f1c579b1SScott Long /* 3087f1c579b1SScott Long ********************************************************************** 3088f1c579b1SScott Long ********************************************************************** 3089f1c579b1SScott Long */ 309044f05562SScott Long static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb) 309144f05562SScott Long { 309244f05562SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 3093d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_START_BGRB); 309444f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 309544f05562SScott Long printf( "arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 309644f05562SScott Long } 309744f05562SScott Long } 309844f05562SScott Long /* 309944f05562SScott Long ********************************************************************** 310044f05562SScott Long ********************************************************************** 310144f05562SScott Long */ 3102d74001adSXin LI static void arcmsr_start_hbc_bgrb(struct AdapterControlBlock *acb) 3103d74001adSXin LI { 3104d74001adSXin LI acb->acb_flags |= ACB_F_MSG_START_BGRB; 3105d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 3106d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 3107d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 3108d74001adSXin LI printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 3109d74001adSXin LI } 3110d74001adSXin LI } 3111d74001adSXin LI /* 3112d74001adSXin LI ********************************************************************** 3113d74001adSXin LI ********************************************************************** 3114d74001adSXin LI */ 31157a7bc959SXin LI static void arcmsr_start_hbd_bgrb(struct AdapterControlBlock *acb) 31167a7bc959SXin LI { 31177a7bc959SXin LI acb->acb_flags |= ACB_F_MSG_START_BGRB; 31187a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 31197a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 31207a7bc959SXin LI printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 31217a7bc959SXin LI } 31227a7bc959SXin LI } 31237a7bc959SXin LI /* 31247a7bc959SXin LI ********************************************************************** 31257a7bc959SXin LI ********************************************************************** 31267a7bc959SXin LI */ 312744f05562SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) 312844f05562SScott Long { 312944f05562SScott Long switch (acb->adapter_type) { 313044f05562SScott Long case ACB_ADAPTER_TYPE_A: 313144f05562SScott Long arcmsr_start_hba_bgrb(acb); 313244f05562SScott Long break; 313344f05562SScott Long case ACB_ADAPTER_TYPE_B: 313444f05562SScott Long arcmsr_start_hbb_bgrb(acb); 313544f05562SScott Long break; 3136d74001adSXin LI case ACB_ADAPTER_TYPE_C: 3137d74001adSXin LI arcmsr_start_hbc_bgrb(acb); 3138d74001adSXin LI break; 31397a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 31407a7bc959SXin LI arcmsr_start_hbd_bgrb(acb); 31417a7bc959SXin LI break; 314244f05562SScott Long } 314344f05562SScott Long } 314444f05562SScott Long /* 314544f05562SScott Long ********************************************************************** 314644f05562SScott Long ** 314744f05562SScott Long ********************************************************************** 314844f05562SScott Long */ 314944f05562SScott Long static void arcmsr_polling_hba_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 3150f1c579b1SScott Long { 3151ad6d6297SScott Long struct CommandControlBlock *srb; 315244f05562SScott Long u_int32_t flag_srb, outbound_intstatus, poll_srb_done=0, poll_count=0; 3153d74001adSXin LI u_int16_t error; 3154f1c579b1SScott Long 315544f05562SScott Long polling_ccb_retry: 3156ad6d6297SScott Long poll_count++; 3157d74001adSXin LI outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 3158d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus); /*clear interrupt*/ 315944f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 3160ad6d6297SScott Long while(1) { 316144f05562SScott Long if((flag_srb = CHIP_REG_READ32(HBA_MessageUnit, 316244f05562SScott Long 0, outbound_queueport)) == 0xFFFFFFFF) { 3163ad6d6297SScott Long if(poll_srb_done) { 3164ad6d6297SScott Long break;/*chip FIFO no ccb for completion already*/ 3165ad6d6297SScott Long } else { 3166ad6d6297SScott Long UDELAY(25000); 3167d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 3168ad6d6297SScott Long break; 3169f1c579b1SScott Long } 317044f05562SScott Long goto polling_ccb_retry; 3171f1c579b1SScott Long } 3172ad6d6297SScott Long } 3173ad6d6297SScott Long /* check if command done with no error*/ 317444f05562SScott Long srb = (struct CommandControlBlock *) 317544f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 3176d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 317744f05562SScott Long poll_srb_done = (srb == poll_srb) ? 1:0; 317822f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 317922f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3180ad6d6297SScott Long printf("arcmsr%d: scsi id=%d lun=%d srb='%p'" 3181ad6d6297SScott Long "poll command abort successfully \n" 3182ad6d6297SScott Long , acb->pci_unit 3183ad6d6297SScott Long , srb->pccb->ccb_h.target_id 3184ad6d6297SScott Long , srb->pccb->ccb_h.target_lun, srb); 3185ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 3186ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 3187ad6d6297SScott Long continue; 3188ad6d6297SScott Long } 3189ad6d6297SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 3190ad6d6297SScott Long "srboutstandingcount=%d \n" 3191ad6d6297SScott Long , acb->pci_unit 3192ad6d6297SScott Long , srb, acb->srboutstandingcount); 3193ad6d6297SScott Long continue; 3194ad6d6297SScott Long } 3195d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 3196ad6d6297SScott Long } /*drain reply FIFO*/ 3197f1c579b1SScott Long } 3198f1c579b1SScott Long /* 3199f1c579b1SScott Long ********************************************************************** 320044f05562SScott Long ** 3201ad6d6297SScott Long ********************************************************************** 3202ad6d6297SScott Long */ 320344f05562SScott Long static void arcmsr_polling_hbb_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 320444f05562SScott Long { 320544f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 320644f05562SScott Long struct CommandControlBlock *srb; 320744f05562SScott Long u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 320844f05562SScott Long int index; 3209d74001adSXin LI u_int16_t error; 321044f05562SScott Long 321144f05562SScott Long polling_ccb_retry: 321244f05562SScott Long poll_count++; 321344f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 321444f05562SScott Long 0, iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 321544f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 321644f05562SScott Long while(1) { 321744f05562SScott Long index = phbbmu->doneq_index; 321844f05562SScott Long if((flag_srb = phbbmu->done_qbuffer[index]) == 0) { 321944f05562SScott Long if(poll_srb_done) { 322044f05562SScott Long break;/*chip FIFO no ccb for completion already*/ 322144f05562SScott Long } else { 322244f05562SScott Long UDELAY(25000); 3223d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 322444f05562SScott Long break; 322544f05562SScott Long } 322644f05562SScott Long goto polling_ccb_retry; 322744f05562SScott Long } 322844f05562SScott Long } 322944f05562SScott Long phbbmu->done_qbuffer[index] = 0; 323044f05562SScott Long index++; 323144f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 323244f05562SScott Long phbbmu->doneq_index = index; 323344f05562SScott Long /* check if command done with no error*/ 323444f05562SScott Long srb = (struct CommandControlBlock *) 323544f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 3236d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 323744f05562SScott Long poll_srb_done = (srb == poll_srb) ? 1:0; 323822f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 323922f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 324044f05562SScott Long printf("arcmsr%d: scsi id=%d lun=%d srb='%p'" 324144f05562SScott Long "poll command abort successfully \n" 324244f05562SScott Long , acb->pci_unit 324344f05562SScott Long , srb->pccb->ccb_h.target_id 324444f05562SScott Long , srb->pccb->ccb_h.target_lun, srb); 324544f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 324644f05562SScott Long arcmsr_srb_complete(srb, 1); 324744f05562SScott Long continue; 324844f05562SScott Long } 324944f05562SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 325044f05562SScott Long "srboutstandingcount=%d \n" 325144f05562SScott Long , acb->pci_unit 325244f05562SScott Long , srb, acb->srboutstandingcount); 325344f05562SScott Long continue; 325444f05562SScott Long } 3255d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 3256d74001adSXin LI } /*drain reply FIFO*/ 3257d74001adSXin LI } 3258d74001adSXin LI /* 3259d74001adSXin LI ********************************************************************** 3260d74001adSXin LI ** 3261d74001adSXin LI ********************************************************************** 3262d74001adSXin LI */ 3263d74001adSXin LI static void arcmsr_polling_hbc_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 3264d74001adSXin LI { 3265d74001adSXin LI struct CommandControlBlock *srb; 3266d74001adSXin LI u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 3267d74001adSXin LI u_int16_t error; 3268d74001adSXin LI 3269d74001adSXin LI polling_ccb_retry: 3270d74001adSXin LI poll_count++; 3271d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 3272d74001adSXin LI while(1) { 3273d74001adSXin LI if(!(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR)) { 3274d74001adSXin LI if(poll_srb_done) { 3275d74001adSXin LI break;/*chip FIFO no ccb for completion already*/ 3276d74001adSXin LI } else { 3277d74001adSXin LI UDELAY(25000); 3278d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 3279d74001adSXin LI break; 3280d74001adSXin LI } 3281d74001adSXin LI if (acb->srboutstandingcount == 0) { 3282d74001adSXin LI break; 3283d74001adSXin LI } 3284d74001adSXin LI goto polling_ccb_retry; 3285d74001adSXin LI } 3286d74001adSXin LI } 3287d74001adSXin LI flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 3288d74001adSXin LI /* check if command done with no error*/ 328922f2616bSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/ 3290d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; 3291d74001adSXin LI if (poll_srb != NULL) 3292d74001adSXin LI poll_srb_done = (srb == poll_srb) ? 1:0; 329322f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 329422f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3295d74001adSXin LI printf("arcmsr%d: scsi id=%d lun=%d srb='%p'poll command abort successfully \n" 3296d74001adSXin LI , acb->pci_unit, srb->pccb->ccb_h.target_id, srb->pccb->ccb_h.target_lun, srb); 3297d74001adSXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 3298d74001adSXin LI arcmsr_srb_complete(srb, 1); 3299d74001adSXin LI continue; 3300d74001adSXin LI } 3301d74001adSXin LI printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n" 3302d74001adSXin LI , acb->pci_unit, srb, acb->srboutstandingcount); 3303d74001adSXin LI continue; 3304d74001adSXin LI } 3305d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 330644f05562SScott Long } /*drain reply FIFO*/ 330744f05562SScott Long } 330844f05562SScott Long /* 330944f05562SScott Long ********************************************************************** 33107a7bc959SXin LI ** 33117a7bc959SXin LI ********************************************************************** 33127a7bc959SXin LI */ 33137a7bc959SXin LI static void arcmsr_polling_hbd_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 33147a7bc959SXin LI { 33157a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 33167a7bc959SXin LI struct CommandControlBlock *srb; 33177a7bc959SXin LI u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 33187a7bc959SXin LI u_int32_t outbound_write_pointer; 33197a7bc959SXin LI u_int16_t error, doneq_index; 33207a7bc959SXin LI 33217a7bc959SXin LI polling_ccb_retry: 33227a7bc959SXin LI poll_count++; 33237a7bc959SXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 33247a7bc959SXin LI while(1) { 33257a7bc959SXin LI outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow; 33267a7bc959SXin LI doneq_index = phbdmu->doneq_index; 33277a7bc959SXin LI if ((outbound_write_pointer & 0xFF) == (doneq_index & 0xFF)) { 33287a7bc959SXin LI if(poll_srb_done) { 33297a7bc959SXin LI break;/*chip FIFO no ccb for completion already*/ 33307a7bc959SXin LI } else { 33317a7bc959SXin LI UDELAY(25000); 33327a7bc959SXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 33337a7bc959SXin LI break; 33347a7bc959SXin LI } 33357a7bc959SXin LI if (acb->srboutstandingcount == 0) { 33367a7bc959SXin LI break; 33377a7bc959SXin LI } 33387a7bc959SXin LI goto polling_ccb_retry; 33397a7bc959SXin LI } 33407a7bc959SXin LI } 33417a7bc959SXin LI doneq_index = arcmsr_get_doneq_index(phbdmu); 33427a7bc959SXin LI flag_srb = phbdmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow; 33437a7bc959SXin LI /* check if command done with no error*/ 33447a7bc959SXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/ 33457a7bc959SXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 33467a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_read_pointer, doneq_index); 33477a7bc959SXin LI if (poll_srb != NULL) 33487a7bc959SXin LI poll_srb_done = (srb == poll_srb) ? 1:0; 33497a7bc959SXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 33507a7bc959SXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 33517a7bc959SXin LI printf("arcmsr%d: scsi id=%d lun=%d srb='%p'poll command abort successfully \n" 33527a7bc959SXin LI , acb->pci_unit, srb->pccb->ccb_h.target_id, srb->pccb->ccb_h.target_lun, srb); 33537a7bc959SXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 33547a7bc959SXin LI arcmsr_srb_complete(srb, 1); 33557a7bc959SXin LI continue; 33567a7bc959SXin LI } 33577a7bc959SXin LI printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n" 33587a7bc959SXin LI , acb->pci_unit, srb, acb->srboutstandingcount); 33597a7bc959SXin LI continue; 33607a7bc959SXin LI } 33617a7bc959SXin LI arcmsr_report_srb_state(acb, srb, error); 33627a7bc959SXin LI } /*drain reply FIFO*/ 33637a7bc959SXin LI } 33647a7bc959SXin LI /* 33657a7bc959SXin LI ********************************************************************** 336644f05562SScott Long ********************************************************************** 336744f05562SScott Long */ 336844f05562SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 336944f05562SScott Long { 337044f05562SScott Long switch (acb->adapter_type) { 337144f05562SScott Long case ACB_ADAPTER_TYPE_A: { 337244f05562SScott Long arcmsr_polling_hba_srbdone(acb, poll_srb); 337344f05562SScott Long } 337444f05562SScott Long break; 337544f05562SScott Long case ACB_ADAPTER_TYPE_B: { 337644f05562SScott Long arcmsr_polling_hbb_srbdone(acb, poll_srb); 337744f05562SScott Long } 337844f05562SScott Long break; 3379d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3380d74001adSXin LI arcmsr_polling_hbc_srbdone(acb, poll_srb); 3381d74001adSXin LI } 3382d74001adSXin LI break; 33837a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 33847a7bc959SXin LI arcmsr_polling_hbd_srbdone(acb, poll_srb); 33857a7bc959SXin LI } 33867a7bc959SXin LI break; 338744f05562SScott Long } 338844f05562SScott Long } 338944f05562SScott Long /* 339044f05562SScott Long ********************************************************************** 339144f05562SScott Long ********************************************************************** 339244f05562SScott Long */ 339344f05562SScott Long static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) 3394ad6d6297SScott Long { 3395ad6d6297SScott Long char *acb_firm_model = acb->firm_model; 3396ad6d6297SScott Long char *acb_firm_version = acb->firm_version; 3397d74001adSXin LI char *acb_device_map = acb->device_map; 3398d74001adSXin LI size_t iop_firm_model = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3399d74001adSXin LI size_t iop_firm_version = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3400d74001adSXin LI size_t iop_device_map = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 3401ad6d6297SScott Long int i; 3402ad6d6297SScott Long 340344f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 340444f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 3405d74001adSXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 3406ad6d6297SScott Long } 3407ad6d6297SScott Long i = 0; 3408ad6d6297SScott Long while(i < 8) { 340944f05562SScott Long *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 3410ad6d6297SScott Long /* 8 bytes firm_model, 15, 60-67*/ 3411ad6d6297SScott Long acb_firm_model++; 3412ad6d6297SScott Long i++; 3413ad6d6297SScott Long } 3414ad6d6297SScott Long i=0; 3415ad6d6297SScott Long while(i < 16) { 341644f05562SScott Long *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 3417ad6d6297SScott Long /* 16 bytes firm_version, 17, 68-83*/ 3418ad6d6297SScott Long acb_firm_version++; 3419ad6d6297SScott Long i++; 3420ad6d6297SScott Long } 3421d74001adSXin LI i=0; 3422d74001adSXin LI while(i < 16) { 3423d74001adSXin LI *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 3424d74001adSXin LI acb_device_map++; 3425d74001adSXin LI i++; 3426d74001adSXin LI } 3427ad6d6297SScott Long printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION); 3428ad6d6297SScott Long printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version); 3429d74001adSXin LI acb->firm_request_len = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3430d74001adSXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3431d74001adSXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3432d74001adSXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3433d74001adSXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3434*abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD) 3435*abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1; 3436*abfdbca9SXin LI else 3437*abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 3438ad6d6297SScott Long } 3439ad6d6297SScott Long /* 3440ad6d6297SScott Long ********************************************************************** 344144f05562SScott Long ********************************************************************** 344244f05562SScott Long */ 344344f05562SScott Long static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) 344444f05562SScott Long { 344544f05562SScott Long char *acb_firm_model = acb->firm_model; 344644f05562SScott Long char *acb_firm_version = acb->firm_version; 3447d74001adSXin LI char *acb_device_map = acb->device_map; 3448d74001adSXin LI size_t iop_firm_model = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3449d74001adSXin LI size_t iop_firm_version = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3450d74001adSXin LI size_t iop_device_map = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 345144f05562SScott Long int i; 345244f05562SScott Long 3453d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG); 345444f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 3455d74001adSXin LI printf( "arcmsr%d: wait" "'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 345644f05562SScott Long } 345744f05562SScott Long i = 0; 345844f05562SScott Long while(i < 8) { 345944f05562SScott Long *acb_firm_model = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_model+i); 346044f05562SScott Long /* 8 bytes firm_model, 15, 60-67*/ 346144f05562SScott Long acb_firm_model++; 346244f05562SScott Long i++; 346344f05562SScott Long } 346444f05562SScott Long i = 0; 346544f05562SScott Long while(i < 16) { 346644f05562SScott Long *acb_firm_version = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_version+i); 346744f05562SScott Long /* 16 bytes firm_version, 17, 68-83*/ 346844f05562SScott Long acb_firm_version++; 346944f05562SScott Long i++; 347044f05562SScott Long } 3471d74001adSXin LI i = 0; 3472d74001adSXin LI while(i < 16) { 3473d74001adSXin LI *acb_device_map = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_device_map+i); 3474d74001adSXin LI acb_device_map++; 3475d74001adSXin LI i++; 3476d74001adSXin LI } 347744f05562SScott Long printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION); 347844f05562SScott Long printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version); 3479d74001adSXin LI acb->firm_request_len = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3480d74001adSXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3481d74001adSXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3482d74001adSXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3483d74001adSXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3484*abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_HBB_POSTQUEUE) 3485*abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_HBB_POSTQUEUE - 1; 3486*abfdbca9SXin LI else 3487*abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 3488d74001adSXin LI } 3489d74001adSXin LI /* 3490d74001adSXin LI ********************************************************************** 3491d74001adSXin LI ********************************************************************** 3492d74001adSXin LI */ 3493d74001adSXin LI static void arcmsr_get_hbc_config(struct AdapterControlBlock *acb) 3494d74001adSXin LI { 3495d74001adSXin LI char *acb_firm_model = acb->firm_model; 3496d74001adSXin LI char *acb_firm_version = acb->firm_version; 3497d74001adSXin LI char *acb_device_map = acb->device_map; 3498d74001adSXin LI size_t iop_firm_model = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3499d74001adSXin LI size_t iop_firm_version = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3500d74001adSXin LI size_t iop_device_map = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 3501d74001adSXin LI int i; 3502d74001adSXin LI 3503d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 3504d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 3505d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 3506d74001adSXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 3507d74001adSXin LI } 3508d74001adSXin LI i = 0; 3509d74001adSXin LI while(i < 8) { 3510d74001adSXin LI *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 3511d74001adSXin LI /* 8 bytes firm_model, 15, 60-67*/ 3512d74001adSXin LI acb_firm_model++; 3513d74001adSXin LI i++; 3514d74001adSXin LI } 3515d74001adSXin LI i = 0; 3516d74001adSXin LI while(i < 16) { 3517d74001adSXin LI *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 3518d74001adSXin LI /* 16 bytes firm_version, 17, 68-83*/ 3519d74001adSXin LI acb_firm_version++; 3520d74001adSXin LI i++; 3521d74001adSXin LI } 3522d74001adSXin LI i = 0; 3523d74001adSXin LI while(i < 16) { 3524d74001adSXin LI *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 3525d74001adSXin LI acb_device_map++; 3526d74001adSXin LI i++; 3527d74001adSXin LI } 3528d74001adSXin LI printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION); 3529d74001adSXin LI printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version); 3530d74001adSXin LI acb->firm_request_len = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3531d74001adSXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3532d74001adSXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3533d74001adSXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3534d74001adSXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3535*abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD) 3536*abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1; 3537*abfdbca9SXin LI else 3538*abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 353944f05562SScott Long } 354044f05562SScott Long /* 354144f05562SScott Long ********************************************************************** 354244f05562SScott Long ********************************************************************** 354344f05562SScott Long */ 35447a7bc959SXin LI static void arcmsr_get_hbd_config(struct AdapterControlBlock *acb) 35457a7bc959SXin LI { 35467a7bc959SXin LI char *acb_firm_model = acb->firm_model; 35477a7bc959SXin LI char *acb_firm_version = acb->firm_version; 35487a7bc959SXin LI char *acb_device_map = acb->device_map; 35497a7bc959SXin LI size_t iop_firm_model = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 35507a7bc959SXin LI size_t iop_firm_version = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 35517a7bc959SXin LI size_t iop_device_map = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 35527a7bc959SXin LI int i; 35537a7bc959SXin LI 35547a7bc959SXin LI if(CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) 35557a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR); 35567a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 35577a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 35587a7bc959SXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 35597a7bc959SXin LI } 35607a7bc959SXin LI i = 0; 35617a7bc959SXin LI while(i < 8) { 35627a7bc959SXin LI *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 35637a7bc959SXin LI /* 8 bytes firm_model, 15, 60-67*/ 35647a7bc959SXin LI acb_firm_model++; 35657a7bc959SXin LI i++; 35667a7bc959SXin LI } 35677a7bc959SXin LI i = 0; 35687a7bc959SXin LI while(i < 16) { 35697a7bc959SXin LI *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 35707a7bc959SXin LI /* 16 bytes firm_version, 17, 68-83*/ 35717a7bc959SXin LI acb_firm_version++; 35727a7bc959SXin LI i++; 35737a7bc959SXin LI } 35747a7bc959SXin LI i = 0; 35757a7bc959SXin LI while(i < 16) { 35767a7bc959SXin LI *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 35777a7bc959SXin LI acb_device_map++; 35787a7bc959SXin LI i++; 35797a7bc959SXin LI } 35807a7bc959SXin LI printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION); 35817a7bc959SXin LI printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version); 35827a7bc959SXin LI acb->firm_request_len = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_request_len, 1, 04-07*/ 35837a7bc959SXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_numbers_queue, 2, 08-11*/ 35847a7bc959SXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_sdram_size, 3, 12-15*/ 35857a7bc959SXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[5]); /*firm_ide_channels, 4, 16-19*/ 35867a7bc959SXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3587*abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_HBD_POSTQUEUE) 3588*abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_HBD_POSTQUEUE - 1; 3589*abfdbca9SXin LI else 3590*abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 35917a7bc959SXin LI } 35927a7bc959SXin LI /* 35937a7bc959SXin LI ********************************************************************** 35947a7bc959SXin LI ********************************************************************** 35957a7bc959SXin LI */ 359644f05562SScott Long static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) 359744f05562SScott Long { 359844f05562SScott Long switch (acb->adapter_type) { 359944f05562SScott Long case ACB_ADAPTER_TYPE_A: { 360044f05562SScott Long arcmsr_get_hba_config(acb); 360144f05562SScott Long } 360244f05562SScott Long break; 360344f05562SScott Long case ACB_ADAPTER_TYPE_B: { 360444f05562SScott Long arcmsr_get_hbb_config(acb); 360544f05562SScott Long } 360644f05562SScott Long break; 3607d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3608d74001adSXin LI arcmsr_get_hbc_config(acb); 3609d74001adSXin LI } 3610d74001adSXin LI break; 36117a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 36127a7bc959SXin LI arcmsr_get_hbd_config(acb); 36137a7bc959SXin LI } 36147a7bc959SXin LI break; 361544f05562SScott Long } 361644f05562SScott Long } 361744f05562SScott Long /* 361844f05562SScott Long ********************************************************************** 361944f05562SScott Long ********************************************************************** 362044f05562SScott Long */ 362144f05562SScott Long static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb) 362244f05562SScott Long { 362344f05562SScott Long int timeout=0; 362444f05562SScott Long 362544f05562SScott Long switch (acb->adapter_type) { 362644f05562SScott Long case ACB_ADAPTER_TYPE_A: { 3627d74001adSXin LI while ((CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) 362844f05562SScott Long { 362944f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 363044f05562SScott Long { 3631d74001adSXin LI printf( "arcmsr%d:timed out waiting for firmware \n", acb->pci_unit); 363244f05562SScott Long return; 363344f05562SScott Long } 363444f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 363544f05562SScott Long } 363644f05562SScott Long } 363744f05562SScott Long break; 363844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 3639d74001adSXin LI while ((CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & ARCMSR_MESSAGE_FIRMWARE_OK) == 0) 364044f05562SScott Long { 364144f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 364244f05562SScott Long { 3643d74001adSXin LI printf( "arcmsr%d: timed out waiting for firmware \n", acb->pci_unit); 364444f05562SScott Long return; 364544f05562SScott Long } 364644f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 364744f05562SScott Long } 3648d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 3649d74001adSXin LI } 3650d74001adSXin LI break; 3651d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3652d74001adSXin LI while ((CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0) 3653d74001adSXin LI { 3654d74001adSXin LI if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 3655d74001adSXin LI { 3656d74001adSXin LI printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit); 3657d74001adSXin LI return; 3658d74001adSXin LI } 3659d74001adSXin LI UDELAY(15000); /* wait 15 milli-seconds */ 3660d74001adSXin LI } 366144f05562SScott Long } 366244f05562SScott Long break; 36637a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 36647a7bc959SXin LI while ((CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBDMU_MESSAGE_FIRMWARE_OK) == 0) 36657a7bc959SXin LI { 36667a7bc959SXin LI if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 36677a7bc959SXin LI { 36687a7bc959SXin LI printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit); 36697a7bc959SXin LI return; 36707a7bc959SXin LI } 36717a7bc959SXin LI UDELAY(15000); /* wait 15 milli-seconds */ 36727a7bc959SXin LI } 36737a7bc959SXin LI } 36747a7bc959SXin LI break; 367544f05562SScott Long } 367644f05562SScott Long } 367744f05562SScott Long /* 367844f05562SScott Long ********************************************************************** 367944f05562SScott Long ********************************************************************** 368044f05562SScott Long */ 368144f05562SScott Long static void arcmsr_clear_doorbell_queue_buffer( struct AdapterControlBlock *acb) 368244f05562SScott Long { 3683d74001adSXin LI u_int32_t outbound_doorbell; 3684d74001adSXin LI 368544f05562SScott Long switch (acb->adapter_type) { 368644f05562SScott Long case ACB_ADAPTER_TYPE_A: { 368744f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 3688d74001adSXin LI outbound_doorbell = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell); 3689d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, outbound_doorbell); /*clear doorbell interrupt */ 3690d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 3691d74001adSXin LI 369244f05562SScott Long } 369344f05562SScott Long break; 369444f05562SScott Long case ACB_ADAPTER_TYPE_B: { 3695d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt and message state*/ 3696d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 369744f05562SScott Long /* let IOP know data has been read */ 369844f05562SScott Long } 369944f05562SScott Long break; 3700d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3701d74001adSXin LI /* empty doorbell Qbuffer if door bell ringed */ 3702d74001adSXin LI outbound_doorbell = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); 3703d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell); /*clear doorbell interrupt */ 3704d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK); 37057a7bc959SXin LI CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell_clear); /* Dummy read to force pci flush */ 37067a7bc959SXin LI CHIP_REG_READ32(HBC_MessageUnit, 0, inbound_doorbell); /* Dummy read to force pci flush */ 37077a7bc959SXin LI } 37087a7bc959SXin LI break; 37097a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 37107a7bc959SXin LI /* empty doorbell Qbuffer if door bell ringed */ 37117a7bc959SXin LI outbound_doorbell = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell); 37127a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, outbound_doorbell); /*clear doorbell interrupt */ 37137a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ); 3714d74001adSXin LI 3715d74001adSXin LI } 3716d74001adSXin LI break; 371744f05562SScott Long } 371844f05562SScott Long } 371944f05562SScott Long /* 372044f05562SScott Long ************************************************************************ 372144f05562SScott Long ************************************************************************ 372244f05562SScott Long */ 372344f05562SScott Long static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb) 372444f05562SScott Long { 372544f05562SScott Long unsigned long srb_phyaddr; 372644f05562SScott Long u_int32_t srb_phyaddr_hi32; 37277a7bc959SXin LI u_int32_t srb_phyaddr_lo32; 372844f05562SScott Long 372944f05562SScott Long /* 373044f05562SScott Long ******************************************************************** 373144f05562SScott Long ** here we need to tell iop 331 our freesrb.HighPart 373244f05562SScott Long ** if freesrb.HighPart is not zero 373344f05562SScott Long ******************************************************************** 373444f05562SScott Long */ 3735d74001adSXin LI srb_phyaddr = (unsigned long) acb->srb_phyaddr.phyaddr; 3736d74001adSXin LI srb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high; 37377a7bc959SXin LI srb_phyaddr_lo32 = acb->srb_phyaddr.B.phyadd_low; 373844f05562SScott Long switch (acb->adapter_type) { 373944f05562SScott Long case ACB_ADAPTER_TYPE_A: { 374044f05562SScott Long if(srb_phyaddr_hi32 != 0) { 3741d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 3742d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 3743d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 374444f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 3745d74001adSXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 374644f05562SScott Long return FALSE; 374744f05562SScott Long } 374844f05562SScott Long } 374944f05562SScott Long } 375044f05562SScott Long break; 375144f05562SScott Long /* 375244f05562SScott Long *********************************************************************** 375344f05562SScott Long ** if adapter type B, set window of "post command Q" 375444f05562SScott Long *********************************************************************** 375544f05562SScott Long */ 375644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 375744f05562SScott Long u_int32_t post_queue_phyaddr; 375844f05562SScott Long struct HBB_MessageUnit *phbbmu; 375944f05562SScott Long 376044f05562SScott Long phbbmu = (struct HBB_MessageUnit *)acb->pmu; 376144f05562SScott Long phbbmu->postq_index = 0; 376244f05562SScott Long phbbmu->doneq_index = 0; 3763d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_SET_POST_WINDOW); 376444f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 3765d74001adSXin LI printf( "arcmsr%d: 'set window of post command Q' timeout\n", acb->pci_unit); 376644f05562SScott Long return FALSE; 376744f05562SScott Long } 376822f2616bSXin LI post_queue_phyaddr = srb_phyaddr + ARCMSR_SRBS_POOL_SIZE 376944f05562SScott Long + offsetof(struct HBB_MessageUnit, post_qbuffer); 3770d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */ 3771d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1], srb_phyaddr_hi32); /* normal should be zero */ 3772d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ size (256+8)*4 */ 3773d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3], post_queue_phyaddr+1056); /* doneQ size (256+8)*4 */ 3774d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4], 1056); /* srb maxQ size must be --> [(256+8)*4] */ 3775d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_SET_CONFIG); 377644f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 377744f05562SScott Long printf( "arcmsr%d: 'set command Q window' timeout \n", acb->pci_unit); 377844f05562SScott Long return FALSE; 377944f05562SScott Long } 3780d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_START_DRIVER_MODE); 378144f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 378244f05562SScott Long printf( "arcmsr%d: 'start diver mode' timeout \n", acb->pci_unit); 378344f05562SScott Long return FALSE; 378444f05562SScott Long } 378544f05562SScott Long } 378644f05562SScott Long break; 3787d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3788d74001adSXin LI if(srb_phyaddr_hi32 != 0) { 3789d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 3790d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 3791d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 3792d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 3793d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 3794d74001adSXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 3795d74001adSXin LI return FALSE; 3796d74001adSXin LI } 3797d74001adSXin LI } 3798d74001adSXin LI } 3799d74001adSXin LI break; 38007a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 38017a7bc959SXin LI u_int32_t post_queue_phyaddr, done_queue_phyaddr; 38027a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu; 38037a7bc959SXin LI 38047a7bc959SXin LI phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 38057a7bc959SXin LI phbdmu->postq_index = 0; 38067a7bc959SXin LI phbdmu->doneq_index = 0x40FF; 38077a7bc959SXin LI post_queue_phyaddr = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE 38087a7bc959SXin LI + offsetof(struct HBD_MessageUnit0, post_qbuffer); 38097a7bc959SXin LI done_queue_phyaddr = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE 38107a7bc959SXin LI + offsetof(struct HBD_MessageUnit0, done_qbuffer); 38117a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */ 38127a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 38137a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ base */ 38147a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[3], done_queue_phyaddr); /* doneQ base */ 38157a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[4], 0x100); 38167a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 38177a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 38187a7bc959SXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 38197a7bc959SXin LI return FALSE; 38207a7bc959SXin LI } 38217a7bc959SXin LI } 38227a7bc959SXin LI break; 382344f05562SScott Long } 3824dac36688SXin LI return (TRUE); 382544f05562SScott Long } 382644f05562SScott Long /* 382744f05562SScott Long ************************************************************************ 382844f05562SScott Long ************************************************************************ 382944f05562SScott Long */ 383044f05562SScott Long static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb) 383144f05562SScott Long { 383244f05562SScott Long switch (acb->adapter_type) 383344f05562SScott Long { 383444f05562SScott Long case ACB_ADAPTER_TYPE_A: 3835d74001adSXin LI case ACB_ADAPTER_TYPE_C: 38367a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 3837d74001adSXin LI break; 383844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 3839d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell,ARCMSR_MESSAGE_ACTIVE_EOI_MODE); 384044f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 3841d74001adSXin LI printf( "arcmsr%d: 'iop enable eoi mode' timeout \n", acb->pci_unit); 384244f05562SScott Long return; 384344f05562SScott Long } 384444f05562SScott Long } 384544f05562SScott Long break; 384644f05562SScott Long } 384744f05562SScott Long } 384844f05562SScott Long /* 384944f05562SScott Long ********************************************************************** 3850ad6d6297SScott Long ********************************************************************** 3851ad6d6297SScott Long */ 3852ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb) 3853ad6d6297SScott Long { 385444f05562SScott Long u_int32_t intmask_org; 3855ad6d6297SScott Long 385644f05562SScott Long /* disable all outbound interrupt */ 385744f05562SScott Long intmask_org = arcmsr_disable_allintr(acb); 385844f05562SScott Long arcmsr_wait_firmware_ready(acb); 385944f05562SScott Long arcmsr_iop_confirm(acb); 3860ad6d6297SScott Long arcmsr_get_firmware_spec(acb); 386144f05562SScott Long /*start background rebuild*/ 3862ad6d6297SScott Long arcmsr_start_adapter_bgrb(acb); 386344f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 386444f05562SScott Long arcmsr_clear_doorbell_queue_buffer(acb); 386544f05562SScott Long arcmsr_enable_eoi_mode(acb); 386644f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 386744f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 3868ad6d6297SScott Long acb->acb_flags |= ACB_F_IOP_INITED; 3869ad6d6297SScott Long } 3870ad6d6297SScott Long /* 3871ad6d6297SScott Long ********************************************************************** 3872f1c579b1SScott Long ********************************************************************** 3873f1c579b1SScott Long */ 3874231c8b71SXin LI static void arcmsr_map_free_srb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 3875f1c579b1SScott Long { 3876ad6d6297SScott Long struct AdapterControlBlock *acb = arg; 3877ad6d6297SScott Long struct CommandControlBlock *srb_tmp; 387844f05562SScott Long u_int32_t i; 3879ad6d6297SScott Long unsigned long srb_phyaddr = (unsigned long)segs->ds_addr; 3880f1c579b1SScott Long 3881d74001adSXin LI acb->srb_phyaddr.phyaddr = srb_phyaddr; 38827a7bc959SXin LI srb_tmp = (struct CommandControlBlock *)acb->uncacheptr; 3883ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 388444f05562SScott Long if(bus_dmamap_create(acb->dm_segs_dmat, 388544f05562SScott Long /*flags*/0, &srb_tmp->dm_segs_dmamap) != 0) { 3886ad6d6297SScott Long acb->acb_flags |= ACB_F_MAPFREESRB_FAILD; 388744f05562SScott Long printf("arcmsr%d:" 388844f05562SScott Long " srb dmamap bus_dmamap_create error\n", acb->pci_unit); 3889ad6d6297SScott Long return; 3890ad6d6297SScott Long } 38917a7bc959SXin LI if((acb->adapter_type == ACB_ADAPTER_TYPE_C) || (acb->adapter_type == ACB_ADAPTER_TYPE_D)) 38927a7bc959SXin LI { 38937a7bc959SXin LI srb_tmp->cdb_phyaddr_low = srb_phyaddr; 38947a7bc959SXin LI srb_tmp->cdb_phyaddr_high = (u_int32_t)((srb_phyaddr >> 16) >> 16); 38957a7bc959SXin LI } 38967a7bc959SXin LI else 38977a7bc959SXin LI srb_tmp->cdb_phyaddr_low = srb_phyaddr >> 5; 3898ad6d6297SScott Long srb_tmp->acb = acb; 3899ad6d6297SScott Long acb->srbworkingQ[i] = acb->psrb_pool[i] = srb_tmp; 390022f2616bSXin LI srb_phyaddr = srb_phyaddr + SRB_SIZE; 390122f2616bSXin LI srb_tmp = (struct CommandControlBlock *)((unsigned long)srb_tmp + SRB_SIZE); 3902ad6d6297SScott Long } 3903ad6d6297SScott Long acb->vir2phy_offset = (unsigned long)srb_tmp - (unsigned long)srb_phyaddr; 3904f1c579b1SScott Long } 3905f1c579b1SScott Long /* 3906f1c579b1SScott Long ************************************************************************ 3907f1c579b1SScott Long ************************************************************************ 3908f1c579b1SScott Long */ 3909ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb) 3910f1c579b1SScott Long { 3911f1c579b1SScott Long /* remove the control device */ 3912ad6d6297SScott Long if(acb->ioctl_dev != NULL) { 3913ad6d6297SScott Long destroy_dev(acb->ioctl_dev); 3914f1c579b1SScott Long } 3915ad6d6297SScott Long bus_dmamap_unload(acb->srb_dmat, acb->srb_dmamap); 3916ad6d6297SScott Long bus_dmamap_destroy(acb->srb_dmat, acb->srb_dmamap); 3917ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 3918ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 3919ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 3920f1c579b1SScott Long } 3921f1c579b1SScott Long /* 3922f1c579b1SScott Long ************************************************************************ 3923f1c579b1SScott Long ************************************************************************ 3924f1c579b1SScott Long */ 39257a7bc959SXin LI static void arcmsr_mutex_init(struct AdapterControlBlock *acb) 39267a7bc959SXin LI { 39277a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->isr_lock, "arcmsr isr lock"); 39287a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->srb_lock, "arcmsr srb lock"); 39297a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->postDone_lock, "arcmsr postQ lock"); 39307a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->qbuffer_lock, "arcmsr RW buffer lock"); 39317a7bc959SXin LI } 39327a7bc959SXin LI /* 39337a7bc959SXin LI ************************************************************************ 39347a7bc959SXin LI ************************************************************************ 39357a7bc959SXin LI */ 39367a7bc959SXin LI static void arcmsr_mutex_destroy(struct AdapterControlBlock *acb) 39377a7bc959SXin LI { 39387a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 39397a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->postDone_lock); 39407a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->srb_lock); 39417a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->isr_lock); 39427a7bc959SXin LI } 39437a7bc959SXin LI /* 39447a7bc959SXin LI ************************************************************************ 39457a7bc959SXin LI ************************************************************************ 39467a7bc959SXin LI */ 3947ad6d6297SScott Long static u_int32_t arcmsr_initialize(device_t dev) 3948f1c579b1SScott Long { 3949ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 3950ad6d6297SScott Long u_int16_t pci_command; 395144f05562SScott Long int i, j,max_coherent_size; 3952dac36688SXin LI u_int32_t vendor_dev_id; 3953f1c579b1SScott Long 3954dac36688SXin LI vendor_dev_id = pci_get_devid(dev); 3955dac36688SXin LI acb->vendor_device_id = vendor_dev_id; 3956dac36688SXin LI switch (vendor_dev_id) { 3957dac36688SXin LI case PCIDevVenIDARC1880: 3958dac36688SXin LI case PCIDevVenIDARC1882: 3959dac36688SXin LI case PCIDevVenIDARC1213: 3960dac36688SXin LI case PCIDevVenIDARC1223: { 3961d74001adSXin LI acb->adapter_type = ACB_ADAPTER_TYPE_C; 3962dac36688SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_6G; 3963d74001adSXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE; 3964d74001adSXin LI } 3965d74001adSXin LI break; 39667a7bc959SXin LI case PCIDevVenIDARC1214: { 39677a7bc959SXin LI acb->adapter_type = ACB_ADAPTER_TYPE_D; 39687a7bc959SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_6G; 39697a7bc959SXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBD_MessageUnit0)); 39707a7bc959SXin LI } 39717a7bc959SXin LI break; 3972231c8b71SXin LI case PCIDevVenIDARC1200: 397344f05562SScott Long case PCIDevVenIDARC1201: { 397444f05562SScott Long acb->adapter_type = ACB_ADAPTER_TYPE_B; 3975dac36688SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_3G; 3976d74001adSXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBB_MessageUnit)); 397744f05562SScott Long } 397844f05562SScott Long break; 397944f05562SScott Long case PCIDevVenIDARC1110: 398044f05562SScott Long case PCIDevVenIDARC1120: 398144f05562SScott Long case PCIDevVenIDARC1130: 398244f05562SScott Long case PCIDevVenIDARC1160: 398344f05562SScott Long case PCIDevVenIDARC1170: 398444f05562SScott Long case PCIDevVenIDARC1210: 398544f05562SScott Long case PCIDevVenIDARC1220: 398644f05562SScott Long case PCIDevVenIDARC1230: 3987231c8b71SXin LI case PCIDevVenIDARC1231: 398844f05562SScott Long case PCIDevVenIDARC1260: 3989231c8b71SXin LI case PCIDevVenIDARC1261: 399044f05562SScott Long case PCIDevVenIDARC1270: 399144f05562SScott Long case PCIDevVenIDARC1280: 3992d74001adSXin LI case PCIDevVenIDARC1212: 3993d74001adSXin LI case PCIDevVenIDARC1222: 399444f05562SScott Long case PCIDevVenIDARC1380: 399544f05562SScott Long case PCIDevVenIDARC1381: 399644f05562SScott Long case PCIDevVenIDARC1680: 399744f05562SScott Long case PCIDevVenIDARC1681: { 399844f05562SScott Long acb->adapter_type = ACB_ADAPTER_TYPE_A; 3999dac36688SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_3G; 400044f05562SScott Long max_coherent_size = ARCMSR_SRBS_POOL_SIZE; 400144f05562SScott Long } 400244f05562SScott Long break; 400344f05562SScott Long default: { 400444f05562SScott Long printf("arcmsr%d:" 400544f05562SScott Long " unknown RAID adapter type \n", device_get_unit(dev)); 400644f05562SScott Long return ENOMEM; 400744f05562SScott Long } 400844f05562SScott Long } 40097a7bc959SXin LI #if __FreeBSD_version >= 700000 4010b6f97155SScott Long if(bus_dma_tag_create( /*PCI parent*/ bus_get_dma_tag(dev), 40117a7bc959SXin LI #else 40127a7bc959SXin LI if(bus_dma_tag_create( /*PCI parent*/ NULL, 40137a7bc959SXin LI #endif 4014f1c579b1SScott Long /*alignemnt*/ 1, 4015f1c579b1SScott Long /*boundary*/ 0, 4016701d9f1fSScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 4017f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 4018f1c579b1SScott Long /*filter*/ NULL, 4019f1c579b1SScott Long /*filterarg*/ NULL, 4020f1c579b1SScott Long /*maxsize*/ BUS_SPACE_MAXSIZE_32BIT, 4021f1c579b1SScott Long /*nsegments*/ BUS_SPACE_UNRESTRICTED, 4022f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 4023f1c579b1SScott Long /*flags*/ 0, 402422f2616bSXin LI #if __FreeBSD_version >= 501102 4025f1c579b1SScott Long /*lockfunc*/ NULL, 4026f1c579b1SScott Long /*lockarg*/ NULL, 4027f1c579b1SScott Long #endif 4028231c8b71SXin LI &acb->parent_dmat) != 0) 4029f1c579b1SScott Long { 403044f05562SScott Long printf("arcmsr%d: parent_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 4031f1c579b1SScott Long return ENOMEM; 4032f1c579b1SScott Long } 4033231c8b71SXin LI 4034f1c579b1SScott Long /* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */ 4035ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 4036f1c579b1SScott Long /*alignment*/ 1, 4037f1c579b1SScott Long /*boundary*/ 0, 403822f2616bSXin LI #ifdef PAE 403922f2616bSXin LI /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 404022f2616bSXin LI #else 4041f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 404222f2616bSXin LI #endif 4043f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 4044f1c579b1SScott Long /*filter*/ NULL, 4045f1c579b1SScott Long /*filterarg*/ NULL, 4046231c8b71SXin LI /*maxsize*/ ARCMSR_MAX_SG_ENTRIES * PAGE_SIZE * ARCMSR_MAX_FREESRB_NUM, 4047f1c579b1SScott Long /*nsegments*/ ARCMSR_MAX_SG_ENTRIES, 4048f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 4049ad6d6297SScott Long /*flags*/ 0, 405022f2616bSXin LI #if __FreeBSD_version >= 501102 4051f1c579b1SScott Long /*lockfunc*/ busdma_lock_mutex, 40527a7bc959SXin LI /*lockarg*/ &acb->isr_lock, 4053f1c579b1SScott Long #endif 4054231c8b71SXin LI &acb->dm_segs_dmat) != 0) 4055f1c579b1SScott Long { 4056ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 405744f05562SScott Long printf("arcmsr%d: dm_segs_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 4058f1c579b1SScott Long return ENOMEM; 4059f1c579b1SScott Long } 4060231c8b71SXin LI 4061ad6d6297SScott Long /* DMA tag for our srb structures.... Allocate the freesrb memory */ 4062ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 406344f05562SScott Long /*alignment*/ 0x20, 4064f1c579b1SScott Long /*boundary*/ 0, 4065f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 4066f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 4067f1c579b1SScott Long /*filter*/ NULL, 4068f1c579b1SScott Long /*filterarg*/ NULL, 406944f05562SScott Long /*maxsize*/ max_coherent_size, 4070f1c579b1SScott Long /*nsegments*/ 1, 4071f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 4072701d9f1fSScott Long /*flags*/ 0, 407322f2616bSXin LI #if __FreeBSD_version >= 501102 4074f1c579b1SScott Long /*lockfunc*/ NULL, 4075f1c579b1SScott Long /*lockarg*/ NULL, 4076f1c579b1SScott Long #endif 4077231c8b71SXin LI &acb->srb_dmat) != 0) 4078f1c579b1SScott Long { 4079ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 4080ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 408144f05562SScott Long printf("arcmsr%d: srb_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 4082f1c579b1SScott Long return ENXIO; 4083f1c579b1SScott Long } 4084f1c579b1SScott Long /* Allocation for our srbs */ 4085d74001adSXin LI if(bus_dmamem_alloc(acb->srb_dmat, (void **)&acb->uncacheptr, BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &acb->srb_dmamap) != 0) { 4086ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 4087ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 4088ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 408944f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamem_alloc failure!\n", device_get_unit(dev)); 4090f1c579b1SScott Long return ENXIO; 4091f1c579b1SScott Long } 4092f1c579b1SScott Long /* And permanently map them */ 4093231c8b71SXin LI if(bus_dmamap_load(acb->srb_dmat, acb->srb_dmamap, acb->uncacheptr, max_coherent_size, arcmsr_map_free_srb, acb, /*flags*/0)) { 4094ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 4095ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 4096ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 409744f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamap_load failure!\n", device_get_unit(dev)); 4098f1c579b1SScott Long return ENXIO; 4099f1c579b1SScott Long } 4100f1c579b1SScott Long pci_command = pci_read_config(dev, PCIR_COMMAND, 2); 4101f1c579b1SScott Long pci_command |= PCIM_CMD_BUSMASTEREN; 4102f1c579b1SScott Long pci_command |= PCIM_CMD_PERRESPEN; 4103f1c579b1SScott Long pci_command |= PCIM_CMD_MWRICEN; 4104f1c579b1SScott Long /* Enable Busmaster/Mem */ 4105f1c579b1SScott Long pci_command |= PCIM_CMD_MEMEN; 4106f1c579b1SScott Long pci_write_config(dev, PCIR_COMMAND, pci_command, 2); 410744f05562SScott Long switch(acb->adapter_type) { 410844f05562SScott Long case ACB_ADAPTER_TYPE_A: { 410944f05562SScott Long u_int32_t rid0 = PCIR_BAR(0); 411044f05562SScott Long vm_offset_t mem_base0; 411144f05562SScott Long 4112d74001adSXin LI acb->sys_res_arcmsr[0] = bus_alloc_resource(dev,SYS_RES_MEMORY, &rid0, 0ul, ~0ul, 0x1000, RF_ACTIVE); 411344f05562SScott Long if(acb->sys_res_arcmsr[0] == NULL) { 4114ad6d6297SScott Long arcmsr_free_resource(acb); 4115d74001adSXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 4116f1c579b1SScott Long return ENOMEM; 4117f1c579b1SScott Long } 411844f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 4119ad6d6297SScott Long arcmsr_free_resource(acb); 4120d74001adSXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 4121f1c579b1SScott Long return ENXIO; 4122f1c579b1SScott Long } 412344f05562SScott Long mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 412444f05562SScott Long if(mem_base0 == 0) { 4125ad6d6297SScott Long arcmsr_free_resource(acb); 4126d74001adSXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 4127f1c579b1SScott Long return ENXIO; 4128f1c579b1SScott Long } 412944f05562SScott Long acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 413044f05562SScott Long acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 413144f05562SScott Long acb->pmu = (struct MessageUnit_UNION *)mem_base0; 413244f05562SScott Long } 413344f05562SScott Long break; 413444f05562SScott Long case ACB_ADAPTER_TYPE_B: { 413544f05562SScott Long struct HBB_MessageUnit *phbbmu; 413644f05562SScott Long struct CommandControlBlock *freesrb; 413744f05562SScott Long u_int32_t rid[]={ PCIR_BAR(0), PCIR_BAR(2) }; 413844f05562SScott Long vm_offset_t mem_base[]={0,0}; 413944f05562SScott Long for(i=0; i < 2; i++) { 414044f05562SScott Long if(i == 0) { 4141d74001adSXin LI acb->sys_res_arcmsr[i] = bus_alloc_resource(dev,SYS_RES_MEMORY, &rid[i], 4142231c8b71SXin LI 0ul, ~0ul, sizeof(struct HBB_DOORBELL), RF_ACTIVE); 414344f05562SScott Long } else { 4144d74001adSXin LI acb->sys_res_arcmsr[i] = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid[i], 4145231c8b71SXin LI 0ul, ~0ul, sizeof(struct HBB_RWBUFFER), RF_ACTIVE); 414644f05562SScott Long } 414744f05562SScott Long if(acb->sys_res_arcmsr[i] == NULL) { 414844f05562SScott Long arcmsr_free_resource(acb); 4149d74001adSXin LI printf("arcmsr%d: bus_alloc_resource %d failure!\n", device_get_unit(dev), i); 415044f05562SScott Long return ENOMEM; 415144f05562SScott Long } 415244f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[i]) <= 0) { 415344f05562SScott Long arcmsr_free_resource(acb); 4154d74001adSXin LI printf("arcmsr%d: rman_get_start %d failure!\n", device_get_unit(dev), i); 415544f05562SScott Long return ENXIO; 415644f05562SScott Long } 415744f05562SScott Long mem_base[i] = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[i]); 415844f05562SScott Long if(mem_base[i] == 0) { 415944f05562SScott Long arcmsr_free_resource(acb); 4160d74001adSXin LI printf("arcmsr%d: rman_get_virtual %d failure!\n", device_get_unit(dev), i); 416144f05562SScott Long return ENXIO; 416244f05562SScott Long } 416344f05562SScott Long acb->btag[i] = rman_get_bustag(acb->sys_res_arcmsr[i]); 416444f05562SScott Long acb->bhandle[i] = rman_get_bushandle(acb->sys_res_arcmsr[i]); 416544f05562SScott Long } 416644f05562SScott Long freesrb = (struct CommandControlBlock *)acb->uncacheptr; 416722f2616bSXin LI acb->pmu = (struct MessageUnit_UNION *)((unsigned long)freesrb+ARCMSR_SRBS_POOL_SIZE); 416844f05562SScott Long phbbmu = (struct HBB_MessageUnit *)acb->pmu; 416944f05562SScott Long phbbmu->hbb_doorbell = (struct HBB_DOORBELL *)mem_base[0]; 417044f05562SScott Long phbbmu->hbb_rwbuffer = (struct HBB_RWBUFFER *)mem_base[1]; 417144f05562SScott Long } 417244f05562SScott Long break; 4173d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 4174d74001adSXin LI u_int32_t rid0 = PCIR_BAR(1); 4175d74001adSXin LI vm_offset_t mem_base0; 4176d74001adSXin LI 4177d74001adSXin LI acb->sys_res_arcmsr[0] = bus_alloc_resource(dev,SYS_RES_MEMORY, &rid0, 0ul, ~0ul, sizeof(struct HBC_MessageUnit), RF_ACTIVE); 4178d74001adSXin LI if(acb->sys_res_arcmsr[0] == NULL) { 4179d74001adSXin LI arcmsr_free_resource(acb); 4180d74001adSXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 4181d74001adSXin LI return ENOMEM; 4182d74001adSXin LI } 4183d74001adSXin LI if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 4184d74001adSXin LI arcmsr_free_resource(acb); 4185d74001adSXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 4186d74001adSXin LI return ENXIO; 4187d74001adSXin LI } 4188d74001adSXin LI mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 4189d74001adSXin LI if(mem_base0 == 0) { 4190d74001adSXin LI arcmsr_free_resource(acb); 4191d74001adSXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 4192d74001adSXin LI return ENXIO; 4193d74001adSXin LI } 4194d74001adSXin LI acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 4195d74001adSXin LI acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 4196d74001adSXin LI acb->pmu = (struct MessageUnit_UNION *)mem_base0; 4197d74001adSXin LI } 4198d74001adSXin LI break; 41997a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 42007a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu; 42017a7bc959SXin LI u_int32_t rid0 = PCIR_BAR(0); 42027a7bc959SXin LI vm_offset_t mem_base0; 42037a7bc959SXin LI 42047a7bc959SXin LI acb->sys_res_arcmsr[0] = bus_alloc_resource(dev,SYS_RES_MEMORY, &rid0, 0ul, ~0ul, sizeof(struct HBD_MessageUnit), RF_ACTIVE); 42057a7bc959SXin LI if(acb->sys_res_arcmsr[0] == NULL) { 42067a7bc959SXin LI arcmsr_free_resource(acb); 42077a7bc959SXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 42087a7bc959SXin LI return ENOMEM; 42097a7bc959SXin LI } 42107a7bc959SXin LI if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 42117a7bc959SXin LI arcmsr_free_resource(acb); 42127a7bc959SXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 42137a7bc959SXin LI return ENXIO; 42147a7bc959SXin LI } 42157a7bc959SXin LI mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 42167a7bc959SXin LI if(mem_base0 == 0) { 42177a7bc959SXin LI arcmsr_free_resource(acb); 42187a7bc959SXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 42197a7bc959SXin LI return ENXIO; 42207a7bc959SXin LI } 42217a7bc959SXin LI acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 42227a7bc959SXin LI acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 42237a7bc959SXin LI acb->pmu = (struct MessageUnit_UNION *)((unsigned long)acb->uncacheptr+ARCMSR_SRBS_POOL_SIZE); 42247a7bc959SXin LI phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 42257a7bc959SXin LI phbdmu->phbdmu = (struct HBD_MessageUnit *)mem_base0; 42267a7bc959SXin LI } 42277a7bc959SXin LI break; 422844f05562SScott Long } 4229ad6d6297SScott Long if(acb->acb_flags & ACB_F_MAPFREESRB_FAILD) { 4230ad6d6297SScott Long arcmsr_free_resource(acb); 423144f05562SScott Long printf("arcmsr%d: map free srb failure!\n", device_get_unit(dev)); 4232f1c579b1SScott Long return ENXIO; 4233f1c579b1SScott Long } 4234d74001adSXin LI acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_RQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ); 4235ad6d6297SScott Long acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; 4236ad6d6297SScott Long /* 4237ad6d6297SScott Long ******************************************************************** 4238ad6d6297SScott Long ** init raid volume state 4239ad6d6297SScott Long ******************************************************************** 4240ad6d6297SScott Long */ 4241ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_TARGETID; i++) { 4242ad6d6297SScott Long for(j=0; j < ARCMSR_MAX_TARGETLUN; j++) { 424344f05562SScott Long acb->devstate[i][j] = ARECA_RAID_GONE; 4244ad6d6297SScott Long } 4245ad6d6297SScott Long } 4246ad6d6297SScott Long arcmsr_iop_init(acb); 4247f1c579b1SScott Long return(0); 4248f1c579b1SScott Long } 4249f1c579b1SScott Long /* 4250f1c579b1SScott Long ************************************************************************ 4251f1c579b1SScott Long ************************************************************************ 4252f1c579b1SScott Long */ 4253f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev) 4254f1c579b1SScott Long { 4255ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 4256ad6d6297SScott Long u_int32_t unit=device_get_unit(dev); 4257f1c579b1SScott Long struct ccb_setasync csa; 4258f1c579b1SScott Long struct cam_devq *devq; /* Device Queue to use for this SIM */ 4259f1c579b1SScott Long struct resource *irqres; 4260f1c579b1SScott Long int rid; 4261f1c579b1SScott Long 4262ad6d6297SScott Long if(acb == NULL) { 4263ad6d6297SScott Long printf("arcmsr%d: cannot allocate softc\n", unit); 4264ad6d6297SScott Long return (ENOMEM); 4265ad6d6297SScott Long } 42667a7bc959SXin LI arcmsr_mutex_init(acb); 4267ad6d6297SScott Long if(arcmsr_initialize(dev)) { 4268ad6d6297SScott Long printf("arcmsr%d: initialize failure!\n", unit); 42697a7bc959SXin LI arcmsr_mutex_destroy(acb); 4270f1c579b1SScott Long return ENXIO; 4271f1c579b1SScott Long } 4272f1c579b1SScott Long /* After setting up the adapter, map our interrupt */ 4273f1c579b1SScott Long rid = 0; 4274ad6d6297SScott Long irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE); 4275ad6d6297SScott Long if(irqres == NULL || 427644f05562SScott Long #if __FreeBSD_version >= 700025 4277d74001adSXin LI bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, NULL, arcmsr_intr_handler, acb, &acb->ih)) { 427844f05562SScott Long #else 4279d74001adSXin LI bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, arcmsr_intr_handler, acb, &acb->ih)) { 428044f05562SScott Long #endif 4281ad6d6297SScott Long arcmsr_free_resource(acb); 42827a7bc959SXin LI arcmsr_mutex_destroy(acb); 4283f1c579b1SScott Long printf("arcmsr%d: unable to register interrupt handler!\n", unit); 4284f1c579b1SScott Long return ENXIO; 4285f1c579b1SScott Long } 4286ad6d6297SScott Long acb->irqres = irqres; 4287ad6d6297SScott Long acb->pci_dev = dev; 4288ad6d6297SScott Long acb->pci_unit = unit; 4289f1c579b1SScott Long /* 4290f1c579b1SScott Long * Now let the CAM generic SCSI layer find the SCSI devices on 4291f1c579b1SScott Long * the bus * start queue to reset to the idle loop. * 4292f1c579b1SScott Long * Create device queue of SIM(s) * (MAX_START_JOB - 1) : 4293f1c579b1SScott Long * max_sim_transactions 4294f1c579b1SScott Long */ 4295f1c579b1SScott Long devq = cam_simq_alloc(ARCMSR_MAX_START_JOB); 4296ad6d6297SScott Long if(devq == NULL) { 4297ad6d6297SScott Long arcmsr_free_resource(acb); 4298ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 42997a7bc959SXin LI arcmsr_mutex_destroy(acb); 4300ad6d6297SScott Long printf("arcmsr%d: cam_simq_alloc failure!\n", unit); 4301f1c579b1SScott Long return ENXIO; 4302f1c579b1SScott Long } 430344f05562SScott Long #if __FreeBSD_version >= 700025 43047a7bc959SXin LI acb->psim = cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, &acb->isr_lock, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq); 430544f05562SScott Long #else 4306d74001adSXin LI acb->psim = cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq); 430744f05562SScott Long #endif 4308ad6d6297SScott Long if(acb->psim == NULL) { 4309ad6d6297SScott Long arcmsr_free_resource(acb); 4310ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 4311f1c579b1SScott Long cam_simq_free(devq); 43127a7bc959SXin LI arcmsr_mutex_destroy(acb); 4313ad6d6297SScott Long printf("arcmsr%d: cam_sim_alloc failure!\n", unit); 4314f1c579b1SScott Long return ENXIO; 4315f1c579b1SScott Long } 43167a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 4317f40b4cabSScott Long #if __FreeBSD_version >= 700044 4318b50569b7SScott Long if(xpt_bus_register(acb->psim, dev, 0) != CAM_SUCCESS) { 431944f05562SScott Long #else 432044f05562SScott Long if(xpt_bus_register(acb->psim, 0) != CAM_SUCCESS) { 432144f05562SScott Long #endif 4322ad6d6297SScott Long arcmsr_free_resource(acb); 4323ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 4324ad6d6297SScott Long cam_sim_free(acb->psim, /*free_devq*/TRUE); 43257a7bc959SXin LI arcmsr_mutex_destroy(acb); 4326ad6d6297SScott Long printf("arcmsr%d: xpt_bus_register failure!\n", unit); 4327f1c579b1SScott Long return ENXIO; 4328f1c579b1SScott Long } 4329d74001adSXin LI if(xpt_create_path(&acb->ppath, /* periph */ NULL, cam_sim_path(acb->psim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 4330ad6d6297SScott Long arcmsr_free_resource(acb); 4331ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 4332ad6d6297SScott Long xpt_bus_deregister(cam_sim_path(acb->psim)); 4333ad6d6297SScott Long cam_sim_free(acb->psim, /* free_simq */ TRUE); 43347a7bc959SXin LI arcmsr_mutex_destroy(acb); 4335ad6d6297SScott Long printf("arcmsr%d: xpt_create_path failure!\n", unit); 4336f1c579b1SScott Long return ENXIO; 4337f1c579b1SScott Long } 4338f1c579b1SScott Long /* 4339f1c579b1SScott Long **************************************************** 4340f1c579b1SScott Long */ 4341ad6d6297SScott Long xpt_setup_ccb(&csa.ccb_h, acb->ppath, /*priority*/5); 4342f1c579b1SScott Long csa.ccb_h.func_code = XPT_SASYNC_CB; 4343f1c579b1SScott Long csa.event_enable = AC_FOUND_DEVICE|AC_LOST_DEVICE; 4344f1c579b1SScott Long csa.callback = arcmsr_async; 4345ad6d6297SScott Long csa.callback_arg = acb->psim; 4346f1c579b1SScott Long xpt_action((union ccb *)&csa); 43477a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 4348f1c579b1SScott Long /* Create the control device. */ 4349d74001adSXin LI acb->ioctl_dev = make_dev(&arcmsr_cdevsw, unit, UID_ROOT, GID_WHEEL /* GID_OPERATOR */, S_IRUSR | S_IWUSR, "arcmsr%d", unit); 4350d74001adSXin LI 4351f1c579b1SScott Long #if __FreeBSD_version < 503000 4352ad6d6297SScott Long acb->ioctl_dev->si_drv1 = acb; 4353f1c579b1SScott Long #endif 4354f1c579b1SScott Long #if __FreeBSD_version > 500005 4355ad6d6297SScott Long (void)make_dev_alias(acb->ioctl_dev, "arc%d", unit); 4356f1c579b1SScott Long #endif 435722f2616bSXin LI arcmsr_callout_init(&acb->devmap_callout); 4358d74001adSXin LI callout_reset(&acb->devmap_callout, 60 * hz, arcmsr_polling_devmap, acb); 4359dac36688SXin LI return (0); 4360f1c579b1SScott Long } 436122f2616bSXin LI 4362f1c579b1SScott Long /* 4363f1c579b1SScott Long ************************************************************************ 4364f1c579b1SScott Long ************************************************************************ 4365f1c579b1SScott Long */ 4366f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev) 4367f1c579b1SScott Long { 4368ad6d6297SScott Long u_int32_t id; 4369ad6d6297SScott Long static char buf[256]; 4370231c8b71SXin LI char x_type[]={"X-TYPE"}; 4371ad6d6297SScott Long char *type; 4372ad6d6297SScott Long int raid6 = 1; 4373ad6d6297SScott Long 4374ad6d6297SScott Long if (pci_get_vendor(dev) != PCI_VENDOR_ID_ARECA) { 4375ad6d6297SScott Long return (ENXIO); 4376ad6d6297SScott Long } 4377ad6d6297SScott Long switch(id = pci_get_devid(dev)) { 4378f1c579b1SScott Long case PCIDevVenIDARC1110: 4379231c8b71SXin LI case PCIDevVenIDARC1200: 438044f05562SScott Long case PCIDevVenIDARC1201: 4381231c8b71SXin LI case PCIDevVenIDARC1210: 4382ad6d6297SScott Long raid6 = 0; 4383ad6d6297SScott Long /*FALLTHRU*/ 4384ad6d6297SScott Long case PCIDevVenIDARC1120: 4385ad6d6297SScott Long case PCIDevVenIDARC1130: 4386ad6d6297SScott Long case PCIDevVenIDARC1160: 4387ad6d6297SScott Long case PCIDevVenIDARC1170: 4388f1c579b1SScott Long case PCIDevVenIDARC1220: 4389f1c579b1SScott Long case PCIDevVenIDARC1230: 4390231c8b71SXin LI case PCIDevVenIDARC1231: 4391f1c579b1SScott Long case PCIDevVenIDARC1260: 4392231c8b71SXin LI case PCIDevVenIDARC1261: 4393ad6d6297SScott Long case PCIDevVenIDARC1270: 4394ad6d6297SScott Long case PCIDevVenIDARC1280: 43957a7bc959SXin LI type = "SATA 3G"; 4396ad6d6297SScott Long break; 4397d74001adSXin LI case PCIDevVenIDARC1212: 4398d74001adSXin LI case PCIDevVenIDARC1222: 4399ad6d6297SScott Long case PCIDevVenIDARC1380: 4400ad6d6297SScott Long case PCIDevVenIDARC1381: 4401ad6d6297SScott Long case PCIDevVenIDARC1680: 4402ad6d6297SScott Long case PCIDevVenIDARC1681: 4403d74001adSXin LI type = "SAS 3G"; 4404d74001adSXin LI break; 4405d74001adSXin LI case PCIDevVenIDARC1880: 4406dac36688SXin LI case PCIDevVenIDARC1882: 4407dac36688SXin LI case PCIDevVenIDARC1213: 4408dac36688SXin LI case PCIDevVenIDARC1223: 4409d74001adSXin LI type = "SAS 6G"; 4410ad6d6297SScott Long break; 44117a7bc959SXin LI case PCIDevVenIDARC1214: 44127a7bc959SXin LI type = "SATA 6G"; 44137a7bc959SXin LI break; 4414ad6d6297SScott Long default: 4415231c8b71SXin LI type = x_type; 4416ad6d6297SScott Long break; 4417f1c579b1SScott Long } 4418231c8b71SXin LI if(type == x_type) 4419231c8b71SXin LI return(ENXIO); 4420ad6d6297SScott Long sprintf(buf, "Areca %s Host Adapter RAID Controller %s\n", type, raid6 ? "(RAID6 capable)" : ""); 4421ad6d6297SScott Long device_set_desc_copy(dev, buf); 442203389298SXin LI return (BUS_PROBE_DEFAULT); 4423f1c579b1SScott Long } 4424f1c579b1SScott Long /* 4425f1c579b1SScott Long ************************************************************************ 4426f1c579b1SScott Long ************************************************************************ 4427f1c579b1SScott Long */ 4428f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev) 4429f1c579b1SScott Long { 443044f05562SScott Long u_int32_t i; 4431ad6d6297SScott Long u_int32_t intmask_org; 4432ad6d6297SScott Long struct CommandControlBlock *srb; 4433ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 4434f1c579b1SScott Long 4435f1c579b1SScott Long /* stop adapter background rebuild */ 44367a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 443744f05562SScott Long /* disable all outbound interrupt */ 443844f05562SScott Long intmask_org = arcmsr_disable_allintr(acb); 4439ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 4440ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 4441f1c579b1SScott Long /* abort all outstanding command */ 4442ad6d6297SScott Long acb->acb_flags |= ACB_F_SCSISTOPADAPTER; 4443ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOP_INITED; 4444ad6d6297SScott Long if(acb->srboutstandingcount != 0) { 444544f05562SScott Long /*clear and abort all outbound posted Q*/ 444644f05562SScott Long arcmsr_done4abort_postqueue(acb); 444744f05562SScott Long /* talk to iop 331 outstanding command aborted*/ 4448ad6d6297SScott Long arcmsr_abort_allcmd(acb); 4449ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 4450ad6d6297SScott Long srb = acb->psrb_pool[i]; 445122f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) { 445222f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 4453ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 4454ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 4455f1c579b1SScott Long } 4456f1c579b1SScott Long } 4457f1c579b1SScott Long } 445822f2616bSXin LI acb->srboutstandingcount = 0; 4459ad6d6297SScott Long acb->workingsrb_doneindex = 0; 4460ad6d6297SScott Long acb->workingsrb_startindex = 0; 446122f2616bSXin LI acb->pktRequestCount = 0; 446222f2616bSXin LI acb->pktReturnCount = 0; 44637a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 4464f2aa0e9fSWarner Losh return (0); 4465f1c579b1SScott Long } 4466f1c579b1SScott Long /* 4467f1c579b1SScott Long ************************************************************************ 4468f1c579b1SScott Long ************************************************************************ 4469f1c579b1SScott Long */ 4470f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev) 4471f1c579b1SScott Long { 4472ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 447344f05562SScott Long int i; 4474f1c579b1SScott Long 4475d74001adSXin LI callout_stop(&acb->devmap_callout); 44765878cbecSScott Long bus_teardown_intr(dev, acb->irqres, acb->ih); 4477f1c579b1SScott Long arcmsr_shutdown(dev); 4478ad6d6297SScott Long arcmsr_free_resource(acb); 447944f05562SScott Long for(i=0; (acb->sys_res_arcmsr[i]!=NULL) && (i<2); i++) { 448044f05562SScott Long bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(i), acb->sys_res_arcmsr[i]); 448144f05562SScott Long } 4482ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 44837a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 4484ad6d6297SScott Long xpt_async(AC_LOST_DEVICE, acb->ppath, NULL); 4485ad6d6297SScott Long xpt_free_path(acb->ppath); 4486ad6d6297SScott Long xpt_bus_deregister(cam_sim_path(acb->psim)); 4487ad6d6297SScott Long cam_sim_free(acb->psim, TRUE); 44887a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 44897a7bc959SXin LI arcmsr_mutex_destroy(acb); 4490f1c579b1SScott Long return (0); 4491f1c579b1SScott Long } 4492f1c579b1SScott Long 449322f2616bSXin LI #ifdef ARCMSR_DEBUG1 449422f2616bSXin LI static void arcmsr_dump_data(struct AdapterControlBlock *acb) 449522f2616bSXin LI { 449622f2616bSXin LI if((acb->pktRequestCount - acb->pktReturnCount) == 0) 449722f2616bSXin LI return; 449822f2616bSXin LI printf("Command Request Count =0x%x\n",acb->pktRequestCount); 449922f2616bSXin LI printf("Command Return Count =0x%x\n",acb->pktReturnCount); 450022f2616bSXin LI printf("Command (Req-Rtn) Count =0x%x\n",(acb->pktRequestCount - acb->pktReturnCount)); 450122f2616bSXin LI printf("Queued Command Count =0x%x\n",acb->srboutstandingcount); 450222f2616bSXin LI } 450322f2616bSXin LI #endif 4504f1c579b1SScott Long 4505