1f1c579b1SScott Long /* 246a7789eSMatt Jacob ***************************************************************************************** 3f1c579b1SScott Long ** O.S : FreeBSD 4f1c579b1SScott Long ** FILE NAME : arcmsr.c 5d74001adSXin LI ** BY : Erich Chen, Ching Huang 6f1c579b1SScott Long ** Description: SCSI RAID Device Driver for 7d74001adSXin LI ** ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX/ARC188x) SATA/SAS RAID HOST Adapter 8ad6d6297SScott Long ** ARCMSR RAID Host adapter 9ad6d6297SScott Long ** [RAID controller:INTEL 331(PCI-X) 341(PCI-EXPRESS) chip set] 10f1c579b1SScott Long ****************************************************************************************** 11f1c579b1SScott Long ************************************************************************ 12f1c579b1SScott Long ** 13d74001adSXin LI ** Copyright (c) 2004-2010 ARECA Co. Ltd. 14f1c579b1SScott Long ** Erich Chen, Taipei Taiwan All rights reserved. 15f1c579b1SScott Long ** 16f1c579b1SScott Long ** Redistribution and use in source and binary forms, with or without 17f1c579b1SScott Long ** modification, are permitted provided that the following conditions 18f1c579b1SScott Long ** are met: 19f1c579b1SScott Long ** 1. Redistributions of source code must retain the above copyright 20f1c579b1SScott Long ** notice, this list of conditions and the following disclaimer. 21f1c579b1SScott Long ** 2. Redistributions in binary form must reproduce the above copyright 22f1c579b1SScott Long ** notice, this list of conditions and the following disclaimer in the 23f1c579b1SScott Long ** documentation and/or other materials provided with the distribution. 24f1c579b1SScott Long ** 3. The name of the author may not be used to endorse or promote products 25f1c579b1SScott Long ** derived from this software without specific prior written permission. 26f1c579b1SScott Long ** 27f1c579b1SScott Long ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 28f1c579b1SScott Long ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 29f1c579b1SScott Long ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 30f1c579b1SScott Long ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 31f1c579b1SScott Long ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT 32f1c579b1SScott Long ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33f1c579b1SScott Long ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY 34f1c579b1SScott Long ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35f1c579b1SScott Long **(INCLUDING NEGLIGENCE OR OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF 36f1c579b1SScott Long ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 37f1c579b1SScott Long ************************************************************************** 38f1c579b1SScott Long ** History 39f1c579b1SScott Long ** 40f1c579b1SScott Long ** REV# DATE NAME DESCRIPTION 4122f2616bSXin LI ** 1.00.00.00 03/31/2004 Erich Chen First release 42f1c579b1SScott Long ** 1.20.00.02 11/29/2004 Erich Chen bug fix with arcmsr_bus_reset when PHY error 4322f2616bSXin LI ** 1.20.00.03 04/19/2005 Erich Chen add SATA 24 Ports adapter type support 44ad6d6297SScott Long ** clean unused function 4522f2616bSXin LI ** 1.20.00.12 09/12/2005 Erich Chen bug fix with abort command handling, 46ad6d6297SScott Long ** firmware version check 47ad6d6297SScott Long ** and firmware update notify for hardware bug fix 48ad6d6297SScott Long ** handling if none zero high part physical address 49ad6d6297SScott Long ** of srb resource 5022f2616bSXin LI ** 1.20.00.13 08/18/2006 Erich Chen remove pending srb and report busy 51ad6d6297SScott Long ** add iop message xfer 52ad6d6297SScott Long ** with scsi pass-through command 53ad6d6297SScott Long ** add new device id of sas raid adapters 54ad6d6297SScott Long ** code fit for SPARC64 & PPC 55f48f00a1SScott Long ** 1.20.00.14 02/05/2007 Erich Chen bug fix for incorrect ccb_h.status report 56f48f00a1SScott Long ** and cause g_vfs_done() read write error 5744f05562SScott Long ** 1.20.00.15 10/10/2007 Erich Chen support new RAID adapter type ARC120x 58641182baSXin LI ** 1.20.00.16 10/10/2009 Erich Chen Bug fix for RAID adapter type ARC120x 59641182baSXin LI ** bus_dmamem_alloc() with BUS_DMA_ZERO 60d74001adSXin LI ** 1.20.00.17 07/15/2010 Ching Huang Added support ARC1880 61d74001adSXin LI ** report CAM_DEV_NOT_THERE instead of CAM_SEL_TIMEOUT when device failed, 62d74001adSXin LI ** prevent cam_periph_error removing all LUN devices of one Target id 63d74001adSXin LI ** for any one LUN device failed 64231c8b71SXin LI ** 1.20.00.18 10/14/2010 Ching Huang Fixed "inquiry data fails comparion at DV1 step" 65231c8b71SXin LI ** 10/25/2010 Ching Huang Fixed bad range input in bus_alloc_resource for ADAPTER_TYPE_B 66231c8b71SXin LI ** 1.20.00.19 11/11/2010 Ching Huang Fixed arcmsr driver prevent arcsas support for Areca SAS HBA ARC13x0 6722f2616bSXin LI ** 1.20.00.20 12/08/2010 Ching Huang Avoid calling atomic_set_int function 6822f2616bSXin LI ** 1.20.00.21 02/08/2011 Ching Huang Implement I/O request timeout 6922f2616bSXin LI ** 02/14/2011 Ching Huang Modified pktRequestCount 7022f2616bSXin LI ** 1.20.00.21 03/03/2011 Ching Huang if a command timeout, then wait its ccb back before free it 714e32649fSXin LI ** 1.20.00.22 07/04/2011 Ching Huang Fixed multiple MTX panic 72dac36688SXin LI ** 1.20.00.23 10/28/2011 Ching Huang Added TIMEOUT_DELAY in case of too many HDDs need to start 73dac36688SXin LI ** 1.20.00.23 11/08/2011 Ching Huang Added report device transfer speed 74dac36688SXin LI ** 1.20.00.23 01/30/2012 Ching Huang Fixed Request requeued and Retrying command 75dac36688SXin LI ** 1.20.00.24 06/11/2012 Ching Huang Fixed return sense data condition 76dac36688SXin LI ** 1.20.00.25 08/17/2012 Ching Huang Fixed hotplug device no function on type A adapter 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> 132579ec1a5SScott Long #define ARCMSR_LOCK_INIT(l, s) mtx_init(l, s, NULL, MTX_DEF) 1335878cbecSScott Long #define ARCMSR_LOCK_DESTROY(l) mtx_destroy(l) 134f1c579b1SScott Long #define ARCMSR_LOCK_ACQUIRE(l) mtx_lock(l) 135f1c579b1SScott Long #define ARCMSR_LOCK_RELEASE(l) mtx_unlock(l) 136ad6d6297SScott Long #define ARCMSR_LOCK_TRY(l) mtx_trylock(l) 137ad6d6297SScott Long #define arcmsr_htole32(x) htole32(x) 138f1c579b1SScott Long typedef struct mtx arcmsr_lock_t; 139f1c579b1SScott Long #else 140f1c579b1SScott Long #include <sys/select.h> 141f1c579b1SScott Long #include <pci/pcivar.h> 142f1c579b1SScott Long #include <pci/pcireg.h> 143f1c579b1SScott Long #define ARCMSR_LOCK_INIT(l, s) simple_lock_init(l) 1445878cbecSScott Long #define ARCMSR_LOCK_DESTROY(l) 145f1c579b1SScott Long #define ARCMSR_LOCK_ACQUIRE(l) simple_lock(l) 146f1c579b1SScott Long #define ARCMSR_LOCK_RELEASE(l) simple_unlock(l) 147ad6d6297SScott Long #define ARCMSR_LOCK_TRY(l) simple_lock_try(l) 148ad6d6297SScott Long #define arcmsr_htole32(x) (x) 149f1c579b1SScott Long typedef struct simplelock arcmsr_lock_t; 150f1c579b1SScott Long #endif 15144f05562SScott Long 15244f05562SScott Long #if !defined(CAM_NEW_TRAN_CODE) && __FreeBSD_version >= 700025 15344f05562SScott Long #define CAM_NEW_TRAN_CODE 1 15444f05562SScott Long #endif 15544f05562SScott Long 15622f2616bSXin LI #if __FreeBSD_version > 500000 15722f2616bSXin LI #define arcmsr_callout_init(a) callout_init(a, /*mpsafe*/1); 15822f2616bSXin LI #else 15922f2616bSXin LI #define arcmsr_callout_init(a) callout_init(a); 16022f2616bSXin LI #endif 16122f2616bSXin LI 162dac36688SXin LI #define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.25 2012-08-17" 163f1c579b1SScott Long #include <dev/arcmsr/arcmsr.h> 16422f2616bSXin LI #define SRB_SIZE ((sizeof(struct CommandControlBlock)+0x1f) & 0xffe0) 16522f2616bSXin LI #define ARCMSR_SRBS_POOL_SIZE (SRB_SIZE * ARCMSR_MAX_FREESRB_NUM) 166f1c579b1SScott Long /* 167f1c579b1SScott Long ************************************************************************** 168f1c579b1SScott Long ************************************************************************** 169f1c579b1SScott Long */ 17044f05562SScott Long #define CHIP_REG_READ32(s, b, r) bus_space_read_4(acb->btag[b], acb->bhandle[b], offsetof(struct s, r)) 17144f05562SScott Long #define CHIP_REG_WRITE32(s, b, r, d) bus_space_write_4(acb->btag[b], acb->bhandle[b], offsetof(struct s, r), d) 172f1c579b1SScott Long /* 173f1c579b1SScott Long ************************************************************************** 174f1c579b1SScott Long ************************************************************************** 175f1c579b1SScott Long */ 17622f2616bSXin LI static void arcmsr_free_srb(struct CommandControlBlock *srb); 177ad6d6297SScott Long static struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb); 178ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb); 179f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev); 180f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev); 181f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev); 182ad6d6297SScott Long static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg); 183ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb); 184f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev); 18544f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb); 186ad6d6297SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb); 187ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb); 188ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb); 189ad6d6297SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); 190ad6d6297SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb); 191ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb); 192ad6d6297SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb); 19344f05562SScott Long static void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb); 194ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb); 195ad6d6297SScott Long static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag); 196ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb); 197ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb); 198ad6d6297SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t * dm_segs, u_int32_t nseg); 199ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb); 200ad6d6297SScott Long static int arcmsr_resume(device_t dev); 201ad6d6297SScott Long static int arcmsr_suspend(device_t dev); 202d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb); 203d74001adSXin LI static void arcmsr_polling_devmap(void* arg); 20422f2616bSXin LI static void arcmsr_srb_timeout(void* arg); 20522f2616bSXin LI #ifdef ARCMSR_DEBUG1 20622f2616bSXin LI static void arcmsr_dump_data(struct AdapterControlBlock *acb); 20722f2616bSXin LI #endif 208f1c579b1SScott Long /* 209f1c579b1SScott Long ************************************************************************** 210ad6d6297SScott Long ************************************************************************** 211ad6d6297SScott Long */ 212ad6d6297SScott Long static void UDELAY(u_int32_t us) { DELAY(us); } 213ad6d6297SScott Long /* 214ad6d6297SScott Long ************************************************************************** 215f1c579b1SScott Long ************************************************************************** 216f1c579b1SScott Long */ 217231c8b71SXin LI static bus_dmamap_callback_t arcmsr_map_free_srb; 218231c8b71SXin LI static bus_dmamap_callback_t arcmsr_execute_srb; 219f1c579b1SScott Long /* 220f1c579b1SScott Long ************************************************************************** 221f1c579b1SScott Long ************************************************************************** 222f1c579b1SScott Long */ 223f1c579b1SScott Long static d_open_t arcmsr_open; 224f1c579b1SScott Long static d_close_t arcmsr_close; 225f1c579b1SScott Long static d_ioctl_t arcmsr_ioctl; 226f1c579b1SScott Long 227f1c579b1SScott Long static device_method_t arcmsr_methods[]={ 228f1c579b1SScott Long DEVMETHOD(device_probe, arcmsr_probe), 229f1c579b1SScott Long DEVMETHOD(device_attach, arcmsr_attach), 230f1c579b1SScott Long DEVMETHOD(device_detach, arcmsr_detach), 231f1c579b1SScott Long DEVMETHOD(device_shutdown, arcmsr_shutdown), 232ad6d6297SScott Long DEVMETHOD(device_suspend, arcmsr_suspend), 233ad6d6297SScott Long DEVMETHOD(device_resume, arcmsr_resume), 2344b7ec270SMarius Strobl 2354b7ec270SMarius Strobl DEVMETHOD_END 236f1c579b1SScott Long }; 237f1c579b1SScott Long 238f1c579b1SScott Long static driver_t arcmsr_driver={ 239ad6d6297SScott Long "arcmsr", arcmsr_methods, sizeof(struct AdapterControlBlock) 240f1c579b1SScott Long }; 241f1c579b1SScott Long 242f1c579b1SScott Long static devclass_t arcmsr_devclass; 243f1c579b1SScott Long DRIVER_MODULE(arcmsr, pci, arcmsr_driver, arcmsr_devclass, 0, 0); 244d3cf342dSScott Long MODULE_DEPEND(arcmsr, pci, 1, 1, 1); 245d3cf342dSScott Long MODULE_DEPEND(arcmsr, cam, 1, 1, 1); 246ad6d6297SScott Long #ifndef BUS_DMA_COHERENT 247ad6d6297SScott Long #define BUS_DMA_COHERENT 0x04 /* hint: map memory in a coherent way */ 248ad6d6297SScott Long #endif 249ad6d6297SScott Long #if __FreeBSD_version >= 501000 250f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw={ 25122f2616bSXin LI #if __FreeBSD_version >= 503000 252f1c579b1SScott Long .d_version = D_VERSION, 253ad6d6297SScott Long #endif 25422f2616bSXin LI #if (__FreeBSD_version>=503000 && __FreeBSD_version<600034) 255f1c579b1SScott Long .d_flags = D_NEEDGIANT, 25622f2616bSXin LI #endif 257f1c579b1SScott Long .d_open = arcmsr_open, /* open */ 258f1c579b1SScott Long .d_close = arcmsr_close, /* close */ 259f1c579b1SScott Long .d_ioctl = arcmsr_ioctl, /* ioctl */ 260f1c579b1SScott Long .d_name = "arcmsr", /* name */ 261f1c579b1SScott Long }; 262f1c579b1SScott Long #else 263f1c579b1SScott Long #define ARCMSR_CDEV_MAJOR 180 264f1c579b1SScott Long 265f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw = { 266f1c579b1SScott Long arcmsr_open, /* open */ 267f1c579b1SScott Long arcmsr_close, /* close */ 268f1c579b1SScott Long noread, /* read */ 269f1c579b1SScott Long nowrite, /* write */ 270f1c579b1SScott Long arcmsr_ioctl, /* ioctl */ 271f1c579b1SScott Long nopoll, /* poll */ 272f1c579b1SScott Long nommap, /* mmap */ 273f1c579b1SScott Long nostrategy, /* strategy */ 274f1c579b1SScott Long "arcmsr", /* name */ 275f1c579b1SScott Long ARCMSR_CDEV_MAJOR, /* major */ 276f1c579b1SScott Long nodump, /* dump */ 277f1c579b1SScott Long nopsize, /* psize */ 278f1c579b1SScott Long 0 /* flags */ 279f1c579b1SScott Long }; 280f1c579b1SScott Long #endif 281d74001adSXin LI /* 282d74001adSXin LI ************************************************************************** 283d74001adSXin LI ************************************************************************** 284d74001adSXin LI */ 285f1c579b1SScott Long #if __FreeBSD_version < 500005 286f1c579b1SScott Long static int arcmsr_open(dev_t dev, int flags, int fmt, struct proc *proc) 287f1c579b1SScott Long #else 288f1c579b1SScott Long #if __FreeBSD_version < 503000 289f1c579b1SScott Long static int arcmsr_open(dev_t dev, int flags, int fmt, struct thread *proc) 290f1c579b1SScott Long #else 29100b4e54aSWarner Losh static int arcmsr_open(struct cdev *dev, int flags, int fmt, struct thread *proc) 292f1c579b1SScott Long #endif 293f1c579b1SScott Long #endif 294f1c579b1SScott Long { 295f1c579b1SScott Long #if __FreeBSD_version < 503000 296ad6d6297SScott Long struct AdapterControlBlock *acb=dev->si_drv1; 297f1c579b1SScott Long #else 2986bfa9a2dSEd Schouten int unit = dev2unit(dev); 299ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 300f1c579b1SScott Long #endif 301ad6d6297SScott Long if(acb==NULL) { 302f1c579b1SScott Long return ENXIO; 303f1c579b1SScott Long } 304dac36688SXin LI return (0); 305f1c579b1SScott Long } 306f1c579b1SScott Long /* 307f1c579b1SScott Long ************************************************************************** 308f1c579b1SScott Long ************************************************************************** 309f1c579b1SScott Long */ 310f1c579b1SScott Long #if __FreeBSD_version < 500005 311f1c579b1SScott Long static int arcmsr_close(dev_t dev, int flags, int fmt, struct proc *proc) 312f1c579b1SScott Long #else 313f1c579b1SScott Long #if __FreeBSD_version < 503000 314f1c579b1SScott Long static int arcmsr_close(dev_t dev, int flags, int fmt, struct thread *proc) 315f1c579b1SScott Long #else 31600b4e54aSWarner Losh static int arcmsr_close(struct cdev *dev, int flags, int fmt, struct thread *proc) 317f1c579b1SScott Long #endif 318f1c579b1SScott Long #endif 319f1c579b1SScott Long { 320f1c579b1SScott Long #if __FreeBSD_version < 503000 321ad6d6297SScott Long struct AdapterControlBlock *acb=dev->si_drv1; 322f1c579b1SScott Long #else 3236bfa9a2dSEd Schouten int unit = dev2unit(dev); 324ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 325f1c579b1SScott Long #endif 326ad6d6297SScott Long if(acb==NULL) { 327f1c579b1SScott Long return ENXIO; 328f1c579b1SScott Long } 329f1c579b1SScott Long return 0; 330f1c579b1SScott Long } 331f1c579b1SScott Long /* 332f1c579b1SScott Long ************************************************************************** 333f1c579b1SScott Long ************************************************************************** 334f1c579b1SScott Long */ 335f1c579b1SScott Long #if __FreeBSD_version < 500005 336f1c579b1SScott Long static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct proc *proc) 337f1c579b1SScott Long #else 338f1c579b1SScott Long #if __FreeBSD_version < 503000 339f1c579b1SScott Long static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc) 340f1c579b1SScott Long #else 34100b4e54aSWarner Losh static int arcmsr_ioctl(struct cdev *dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc) 342f1c579b1SScott Long #endif 343f1c579b1SScott Long #endif 344f1c579b1SScott Long { 345f1c579b1SScott Long #if __FreeBSD_version < 503000 346ad6d6297SScott Long struct AdapterControlBlock *acb=dev->si_drv1; 347f1c579b1SScott Long #else 3486bfa9a2dSEd Schouten int unit = dev2unit(dev); 349ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 350f1c579b1SScott Long #endif 351f1c579b1SScott Long 352ad6d6297SScott Long if(acb==NULL) { 353f1c579b1SScott Long return ENXIO; 354f1c579b1SScott Long } 355ad6d6297SScott Long return (arcmsr_iop_ioctlcmd(acb, ioctl_cmd, arg)); 356f1c579b1SScott Long } 357f1c579b1SScott Long /* 35844f05562SScott Long ********************************************************************** 35944f05562SScott Long ********************************************************************** 36044f05562SScott Long */ 36144f05562SScott Long static u_int32_t arcmsr_disable_allintr( struct AdapterControlBlock *acb) 36244f05562SScott Long { 36344f05562SScott Long u_int32_t intmask_org=0; 36444f05562SScott Long 36544f05562SScott Long switch (acb->adapter_type) { 36644f05562SScott Long case ACB_ADAPTER_TYPE_A: { 36744f05562SScott Long /* disable all outbound interrupt */ 368d74001adSXin LI intmask_org=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intmask); /* disable outbound message0 int */ 369d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); 37044f05562SScott Long } 37144f05562SScott Long break; 37244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 37344f05562SScott Long /* disable all outbound interrupt */ 37444f05562SScott Long intmask_org=CHIP_REG_READ32(HBB_DOORBELL, 37544f05562SScott Long 0, iop2drv_doorbell_mask) & (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); /* disable outbound message0 int */ 376d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell_mask, 0); /* disable all interrupt */ 377d74001adSXin LI } 378d74001adSXin LI break; 379d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 380d74001adSXin LI /* disable all outbound interrupt */ 381d74001adSXin LI intmask_org=CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_mask) ; /* disable outbound message0 int */ 382d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org|ARCMSR_HBCMU_ALL_INTMASKENABLE); 38344f05562SScott Long } 38444f05562SScott Long break; 38544f05562SScott Long } 38644f05562SScott Long return (intmask_org); 38744f05562SScott Long } 38844f05562SScott Long /* 38944f05562SScott Long ********************************************************************** 39044f05562SScott Long ********************************************************************** 39144f05562SScott Long */ 39244f05562SScott Long static void arcmsr_enable_allintr( struct AdapterControlBlock *acb, u_int32_t intmask_org) 39344f05562SScott Long { 39444f05562SScott Long u_int32_t mask; 39544f05562SScott Long 39644f05562SScott Long switch (acb->adapter_type) { 39744f05562SScott Long case ACB_ADAPTER_TYPE_A: { 39844f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 399d74001adSXin LI mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE); 40044f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org & mask); 40144f05562SScott Long acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; 40244f05562SScott Long } 40344f05562SScott Long break; 40444f05562SScott Long case ACB_ADAPTER_TYPE_B: { 405d74001adSXin LI /* enable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */ 406d74001adSXin LI mask=(ARCMSR_IOP2DRV_DATA_WRITE_OK|ARCMSR_IOP2DRV_DATA_READ_OK|ARCMSR_IOP2DRV_CDB_DONE|ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); 407d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell_mask, intmask_org | mask); /*1=interrupt enable, 0=interrupt disable*/ 40844f05562SScott Long acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f; 40944f05562SScott Long } 41044f05562SScott Long break; 411d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 412d74001adSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 413d74001adSXin LI mask=~(ARCMSR_HBCMU_UTILITY_A_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK); 414d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org & mask); 415d74001adSXin LI acb->outbound_int_enable= ~(intmask_org & mask) & 0x0000000f; 416d74001adSXin LI } 417d74001adSXin LI break; 41844f05562SScott Long } 41944f05562SScott Long } 42044f05562SScott Long /* 42144f05562SScott Long ********************************************************************** 42244f05562SScott Long ********************************************************************** 42344f05562SScott Long */ 42444f05562SScott Long static u_int8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) 42544f05562SScott Long { 42644f05562SScott Long u_int32_t Index; 42744f05562SScott Long u_int8_t Retries=0x00; 42844f05562SScott Long 42944f05562SScott Long do { 43044f05562SScott Long for(Index=0; Index < 100; Index++) { 431d74001adSXin LI if(CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { 432d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/ 43344f05562SScott Long return TRUE; 43444f05562SScott Long } 43544f05562SScott Long UDELAY(10000); 43644f05562SScott Long }/*max 1 seconds*/ 43744f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 438dac36688SXin LI return (FALSE); 43944f05562SScott Long } 44044f05562SScott Long /* 44144f05562SScott Long ********************************************************************** 44244f05562SScott Long ********************************************************************** 44344f05562SScott Long */ 44444f05562SScott Long static u_int8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) 44544f05562SScott Long { 44644f05562SScott Long u_int32_t Index; 44744f05562SScott Long u_int8_t Retries=0x00; 44844f05562SScott Long 44944f05562SScott Long do { 45044f05562SScott Long for(Index=0; Index < 100; Index++) { 451d74001adSXin LI if(CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { 452d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/ 453d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 454d74001adSXin LI return TRUE; 455d74001adSXin LI } 456d74001adSXin LI UDELAY(10000); 457d74001adSXin LI }/*max 1 seconds*/ 458d74001adSXin LI }while(Retries++ < 20);/*max 20 sec*/ 459dac36688SXin LI return (FALSE); 460d74001adSXin LI } 461d74001adSXin LI /* 462d74001adSXin LI ********************************************************************** 463d74001adSXin LI ********************************************************************** 464d74001adSXin LI */ 465d74001adSXin LI static u_int8_t arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock *acb) 466d74001adSXin LI { 467d74001adSXin LI u_int32_t Index; 468d74001adSXin LI u_int8_t Retries=0x00; 469d74001adSXin LI 470d74001adSXin LI do { 471d74001adSXin LI for(Index=0; Index < 100; Index++) { 472d74001adSXin LI if(CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { 473d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);/*clear interrupt*/ 47444f05562SScott Long return TRUE; 47544f05562SScott Long } 47644f05562SScott Long UDELAY(10000); 47744f05562SScott Long }/*max 1 seconds*/ 47844f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 479dac36688SXin LI return (FALSE); 48044f05562SScott Long } 48144f05562SScott Long /* 48244f05562SScott Long ************************************************************************ 48344f05562SScott Long ************************************************************************ 48444f05562SScott Long */ 48544f05562SScott Long static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) 48644f05562SScott Long { 48744f05562SScott Long int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */ 48844f05562SScott Long 489d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 49044f05562SScott Long do { 49144f05562SScott Long if(arcmsr_hba_wait_msgint_ready(acb)) { 49244f05562SScott Long break; 49344f05562SScott Long } else { 49444f05562SScott Long retry_count--; 49544f05562SScott Long } 49644f05562SScott Long }while(retry_count!=0); 49744f05562SScott Long } 49844f05562SScott Long /* 49944f05562SScott Long ************************************************************************ 50044f05562SScott Long ************************************************************************ 50144f05562SScott Long */ 50244f05562SScott Long static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) 50344f05562SScott Long { 50444f05562SScott Long int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */ 50544f05562SScott Long 50644f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 50744f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_FLUSH_CACHE); 50844f05562SScott Long do { 50944f05562SScott Long if(arcmsr_hbb_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 */ 520d74001adSXin LI static void arcmsr_flush_hbc_cache(struct AdapterControlBlock *acb) 521d74001adSXin LI { 522d74001adSXin LI int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */ 523d74001adSXin LI 524d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 525d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 526d74001adSXin LI do { 527d74001adSXin LI if(arcmsr_hbc_wait_msgint_ready(acb)) { 528d74001adSXin LI break; 529d74001adSXin LI } else { 530d74001adSXin LI retry_count--; 531d74001adSXin LI } 532d74001adSXin LI }while(retry_count!=0); 533d74001adSXin LI } 534d74001adSXin LI /* 535d74001adSXin LI ************************************************************************ 536d74001adSXin LI ************************************************************************ 537d74001adSXin LI */ 53844f05562SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) 53944f05562SScott Long { 54044f05562SScott Long switch (acb->adapter_type) { 54144f05562SScott Long case ACB_ADAPTER_TYPE_A: { 54244f05562SScott Long arcmsr_flush_hba_cache(acb); 54344f05562SScott Long } 54444f05562SScott Long break; 54544f05562SScott Long case ACB_ADAPTER_TYPE_B: { 54644f05562SScott Long arcmsr_flush_hbb_cache(acb); 54744f05562SScott Long } 54844f05562SScott Long break; 549d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 550d74001adSXin LI arcmsr_flush_hbc_cache(acb); 551d74001adSXin LI } 552d74001adSXin LI break; 55344f05562SScott Long } 55444f05562SScott Long } 55544f05562SScott Long /* 556ad6d6297SScott Long ******************************************************************************* 557ad6d6297SScott Long ******************************************************************************* 558f1c579b1SScott Long */ 559ad6d6297SScott Long static int arcmsr_suspend(device_t dev) 560f1c579b1SScott Long { 561ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 562f1c579b1SScott Long 563ad6d6297SScott Long /* flush controller */ 564ad6d6297SScott Long arcmsr_iop_parking(acb); 565d74001adSXin LI /* disable all outbound interrupt */ 566d74001adSXin LI arcmsr_disable_allintr(acb); 567ad6d6297SScott Long return(0); 568ad6d6297SScott Long } 569ad6d6297SScott Long /* 570ad6d6297SScott Long ******************************************************************************* 571ad6d6297SScott Long ******************************************************************************* 572ad6d6297SScott Long */ 573ad6d6297SScott Long static int arcmsr_resume(device_t dev) 574ad6d6297SScott Long { 575ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 576f1c579b1SScott Long 577ad6d6297SScott Long arcmsr_iop_init(acb); 578ad6d6297SScott Long return(0); 579f1c579b1SScott Long } 580f1c579b1SScott Long /* 581f1c579b1SScott Long ********************************************************************************* 582f1c579b1SScott Long ********************************************************************************* 583f1c579b1SScott Long */ 584ad6d6297SScott Long static void arcmsr_async(void *cb_arg, u_int32_t code, struct cam_path *path, void *arg) 585f1c579b1SScott Long { 586ad6d6297SScott Long struct AdapterControlBlock *acb; 587ad6d6297SScott Long u_int8_t target_id, target_lun; 588f1c579b1SScott Long struct cam_sim * sim; 589f1c579b1SScott Long 590f1c579b1SScott Long sim=(struct cam_sim *) cb_arg; 591ad6d6297SScott Long acb =(struct AdapterControlBlock *) cam_sim_softc(sim); 592ad6d6297SScott Long switch (code) { 593f1c579b1SScott Long case AC_LOST_DEVICE: 594f1c579b1SScott Long target_id=xpt_path_target_id(path); 595f1c579b1SScott Long target_lun=xpt_path_lun_id(path); 596d74001adSXin LI if((target_id > ARCMSR_MAX_TARGETID) || (target_lun > ARCMSR_MAX_TARGETLUN)) { 597f1c579b1SScott Long break; 598f1c579b1SScott Long } 599dac36688SXin LI // printf("%s:scsi id=%d lun=%d device lost \n", device_get_name(acb->pci_dev), target_id, target_lun); 600f1c579b1SScott Long break; 601f1c579b1SScott Long default: 602f1c579b1SScott Long break; 603f1c579b1SScott Long } 604f1c579b1SScott Long } 605f1c579b1SScott Long /* 606f1c579b1SScott Long ********************************************************************** 607f1c579b1SScott Long ********************************************************************** 608f1c579b1SScott Long */ 609ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb) 610f1c579b1SScott Long { 611ad6d6297SScott Long union ccb * pccb=srb->pccb; 612f1c579b1SScott Long 613ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 614ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 615dac36688SXin LI if(pccb->csio.sense_len) { 616ad6d6297SScott Long memset(&pccb->csio.sense_data, 0, sizeof(pccb->csio.sense_data)); 617ad6d6297SScott Long memcpy(&pccb->csio.sense_data, srb->arcmsr_cdb.SenseData, 618ad6d6297SScott Long get_min(sizeof(struct SENSE_DATA), sizeof(pccb->csio.sense_data))); 619ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); /* Valid,ErrorCode */ 620f1c579b1SScott Long pccb->ccb_h.status |= CAM_AUTOSNS_VALID; 621f1c579b1SScott Long } 622f1c579b1SScott Long } 623f1c579b1SScott Long /* 624f1c579b1SScott Long ********************************************************************* 62544f05562SScott Long ********************************************************************* 62644f05562SScott Long */ 62744f05562SScott Long static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) 62844f05562SScott Long { 62944f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 63044f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 631d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 63244f05562SScott Long } 63344f05562SScott Long } 63444f05562SScott Long /* 63544f05562SScott Long ********************************************************************* 63644f05562SScott Long ********************************************************************* 63744f05562SScott Long */ 63844f05562SScott Long static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) 63944f05562SScott Long { 64044f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_ABORT_CMD); 64144f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 642d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 643d74001adSXin LI } 644d74001adSXin LI } 645d74001adSXin LI /* 646d74001adSXin LI ********************************************************************* 647d74001adSXin LI ********************************************************************* 648d74001adSXin LI */ 649d74001adSXin LI static void arcmsr_abort_hbc_allcmd(struct AdapterControlBlock *acb) 650d74001adSXin LI { 651d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 652d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 653d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 654d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 65544f05562SScott Long } 65644f05562SScott Long } 65744f05562SScott Long /* 65844f05562SScott Long ********************************************************************* 659f1c579b1SScott Long ********************************************************************* 660f1c579b1SScott Long */ 661ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) 662f1c579b1SScott Long { 66344f05562SScott Long switch (acb->adapter_type) { 66444f05562SScott Long case ACB_ADAPTER_TYPE_A: { 66544f05562SScott Long arcmsr_abort_hba_allcmd(acb); 66644f05562SScott Long } 66744f05562SScott Long break; 66844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 66944f05562SScott Long arcmsr_abort_hbb_allcmd(acb); 67044f05562SScott Long } 67144f05562SScott Long break; 672d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 673d74001adSXin LI arcmsr_abort_hbc_allcmd(acb); 674d74001adSXin LI } 675d74001adSXin LI break; 67644f05562SScott Long } 67744f05562SScott Long } 67844f05562SScott Long /* 679231c8b71SXin LI ********************************************************************** 680231c8b71SXin LI ********************************************************************** 681231c8b71SXin LI */ 682231c8b71SXin LI static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag) 683231c8b71SXin LI { 684231c8b71SXin LI struct AdapterControlBlock *acb=srb->acb; 685231c8b71SXin LI union ccb * pccb=srb->pccb; 686231c8b71SXin LI 68722f2616bSXin LI if(srb->srb_flags & SRB_FLAG_TIMER_START) 68822f2616bSXin LI callout_stop(&srb->ccb_callout); 689231c8b71SXin LI if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 690231c8b71SXin LI bus_dmasync_op_t op; 691231c8b71SXin LI 692231c8b71SXin LI if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 693231c8b71SXin LI op = BUS_DMASYNC_POSTREAD; 694231c8b71SXin LI } else { 695231c8b71SXin LI op = BUS_DMASYNC_POSTWRITE; 696231c8b71SXin LI } 697231c8b71SXin LI bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 698231c8b71SXin LI bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 699231c8b71SXin LI } 700231c8b71SXin LI if(stand_flag==1) { 701231c8b71SXin LI atomic_subtract_int(&acb->srboutstandingcount, 1); 702231c8b71SXin LI if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) && ( 703231c8b71SXin LI acb->srboutstandingcount < ARCMSR_RELEASE_SIMQ_LEVEL)) { 704231c8b71SXin LI acb->acb_flags &= ~ACB_F_CAM_DEV_QFRZN; 705231c8b71SXin LI pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 706231c8b71SXin LI } 707231c8b71SXin LI } 70822f2616bSXin LI if(srb->srb_state != ARCMSR_SRB_TIMEOUT) 70922f2616bSXin LI arcmsr_free_srb(srb); 71022f2616bSXin LI #ifdef ARCMSR_DEBUG1 71122f2616bSXin LI acb->pktReturnCount++; 71222f2616bSXin LI #endif 713231c8b71SXin LI xpt_done(pccb); 714231c8b71SXin LI } 715231c8b71SXin LI /* 71644f05562SScott Long ************************************************************************** 71744f05562SScott Long ************************************************************************** 71844f05562SScott Long */ 719d74001adSXin LI static void arcmsr_report_srb_state(struct AdapterControlBlock *acb, struct CommandControlBlock *srb, u_int16_t error) 72044f05562SScott Long { 72144f05562SScott Long int target, lun; 72244f05562SScott Long 72344f05562SScott Long target=srb->pccb->ccb_h.target_id; 72444f05562SScott Long lun=srb->pccb->ccb_h.target_lun; 725d74001adSXin LI if(error == FALSE) { 72644f05562SScott Long if(acb->devstate[target][lun]==ARECA_RAID_GONE) { 72744f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GOOD; 72844f05562SScott Long } 72944f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_CMP; 73044f05562SScott Long arcmsr_srb_complete(srb, 1); 73144f05562SScott Long } else { 73244f05562SScott Long switch(srb->arcmsr_cdb.DeviceStatus) { 73344f05562SScott Long case ARCMSR_DEV_SELECT_TIMEOUT: { 73444f05562SScott Long if(acb->devstate[target][lun]==ARECA_RAID_GOOD) { 735d74001adSXin LI printf( "arcmsr%d: Target=%x, Lun=%x, selection timeout, raid volume was lost\n", acb->pci_unit, target, lun); 736ad6d6297SScott Long } 73744f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GONE; 738d74001adSXin LI srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 73944f05562SScott Long arcmsr_srb_complete(srb, 1); 74044f05562SScott Long } 74144f05562SScott Long break; 74244f05562SScott Long case ARCMSR_DEV_ABORTED: 74344f05562SScott Long case ARCMSR_DEV_INIT_FAIL: { 74444f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GONE; 74544f05562SScott Long srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 74644f05562SScott Long arcmsr_srb_complete(srb, 1); 74744f05562SScott Long } 74844f05562SScott Long break; 74944f05562SScott Long case SCSISTAT_CHECK_CONDITION: { 75044f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GOOD; 75144f05562SScott Long arcmsr_report_sense_info(srb); 75244f05562SScott Long arcmsr_srb_complete(srb, 1); 75344f05562SScott Long } 75444f05562SScott Long break; 75544f05562SScott Long default: 75610d66948SKevin Lo printf("arcmsr%d: scsi id=%d lun=%d isr got command error done,but got unknown DeviceStatus=0x%x \n" 757d74001adSXin LI , acb->pci_unit, target, lun ,srb->arcmsr_cdb.DeviceStatus); 75844f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GONE; 75944f05562SScott Long srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY; 76010d66948SKevin Lo /*unknown error or crc error just for retry*/ 76144f05562SScott Long arcmsr_srb_complete(srb, 1); 76244f05562SScott Long break; 76344f05562SScott Long } 76444f05562SScott Long } 76544f05562SScott Long } 76644f05562SScott Long /* 76744f05562SScott Long ************************************************************************** 76844f05562SScott Long ************************************************************************** 76944f05562SScott Long */ 770d74001adSXin LI static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t flag_srb, u_int16_t error) 77144f05562SScott Long { 77244f05562SScott Long struct CommandControlBlock *srb; 77344f05562SScott Long 77444f05562SScott Long /* check if command done with no error*/ 775d74001adSXin LI switch (acb->adapter_type) { 776d74001adSXin LI case ACB_ADAPTER_TYPE_C: 77722f2616bSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/ 778d74001adSXin LI break; 779d74001adSXin LI case ACB_ADAPTER_TYPE_A: 780d74001adSXin LI case ACB_ADAPTER_TYPE_B: 781d74001adSXin LI default: 782d74001adSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 783d74001adSXin LI break; 784d74001adSXin LI } 78522f2616bSXin LI if((srb->acb!=acb) || (srb->srb_state!=ARCMSR_SRB_START)) { 78622f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_TIMEOUT) { 78722f2616bSXin LI arcmsr_free_srb(srb); 78822f2616bSXin LI printf("arcmsr%d: srb='%p' return srb has been timeouted\n", acb->pci_unit, srb); 78944f05562SScott Long return; 79044f05562SScott Long } 79122f2616bSXin LI printf("arcmsr%d: return srb has been completed\n" 79222f2616bSXin LI "srb='%p' srb_state=0x%x outstanding srb count=%d \n", 79322f2616bSXin LI acb->pci_unit, srb, srb->srb_state, acb->srboutstandingcount); 79444f05562SScott Long return; 79544f05562SScott Long } 796d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 79744f05562SScott Long } 79844f05562SScott Long /* 79922f2616bSXin LI ************************************************************************** 80022f2616bSXin LI ************************************************************************** 80122f2616bSXin LI */ 80222f2616bSXin LI static void arcmsr_srb_timeout(void* arg) 80322f2616bSXin LI { 80422f2616bSXin LI struct CommandControlBlock *srb = (struct CommandControlBlock *)arg; 80522f2616bSXin LI struct AdapterControlBlock *acb; 80622f2616bSXin LI int target, lun; 80722f2616bSXin LI u_int8_t cmd; 80822f2616bSXin LI 80922f2616bSXin LI target=srb->pccb->ccb_h.target_id; 81022f2616bSXin LI lun=srb->pccb->ccb_h.target_lun; 81122f2616bSXin LI acb = srb->acb; 81222f2616bSXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 81322f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) 81422f2616bSXin LI { 81522f2616bSXin LI cmd = srb->pccb->csio.cdb_io.cdb_bytes[0]; 81622f2616bSXin LI srb->srb_state = ARCMSR_SRB_TIMEOUT; 81722f2616bSXin LI srb->pccb->ccb_h.status |= CAM_CMD_TIMEOUT; 81822f2616bSXin LI arcmsr_srb_complete(srb, 1); 81922f2616bSXin LI printf("arcmsr%d: scsi id %d lun %d cmd=0x%x srb='%p' ccb command time out!\n", 82022f2616bSXin LI acb->pci_unit, target, lun, cmd, srb); 82122f2616bSXin LI } 82222f2616bSXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 82322f2616bSXin LI #ifdef ARCMSR_DEBUG1 82422f2616bSXin LI arcmsr_dump_data(acb); 82522f2616bSXin LI #endif 82622f2616bSXin LI } 82722f2616bSXin LI 82822f2616bSXin LI /* 82944f05562SScott Long ********************************************************************** 83044f05562SScott Long ********************************************************************** 83144f05562SScott Long */ 83244f05562SScott Long static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) 83344f05562SScott Long { 83444f05562SScott Long int i=0; 83544f05562SScott Long u_int32_t flag_srb; 836d74001adSXin LI u_int16_t error; 83744f05562SScott Long 83844f05562SScott Long switch (acb->adapter_type) { 83944f05562SScott Long case ACB_ADAPTER_TYPE_A: { 84044f05562SScott Long u_int32_t outbound_intstatus; 84144f05562SScott Long 84244f05562SScott Long /*clear and abort all outbound posted Q*/ 843d74001adSXin LI outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 844d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/ 845d74001adSXin LI while(((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_queueport)) != 0xFFFFFFFF) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { 846d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 847d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 84844f05562SScott Long } 84944f05562SScott Long } 85044f05562SScott Long break; 85144f05562SScott Long case ACB_ADAPTER_TYPE_B: { 85244f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 85344f05562SScott Long 85444f05562SScott Long /*clear all outbound posted Q*/ 855d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 85644f05562SScott Long for(i=0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) { 85744f05562SScott Long if((flag_srb=phbbmu->done_qbuffer[i])!=0) { 85844f05562SScott Long phbbmu->done_qbuffer[i]=0; 859d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 860d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 86144f05562SScott Long } 86244f05562SScott Long phbbmu->post_qbuffer[i]=0; 86344f05562SScott Long }/*drain reply FIFO*/ 86444f05562SScott Long phbbmu->doneq_index=0; 86544f05562SScott Long phbbmu->postq_index=0; 86644f05562SScott Long } 86744f05562SScott Long break; 868d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 869d74001adSXin LI 870d74001adSXin LI while((CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { 871d74001adSXin LI flag_srb=CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 872d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; 873d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 874d74001adSXin LI } 875d74001adSXin LI } 876d74001adSXin LI break; 87744f05562SScott Long } 878f1c579b1SScott Long } 879f1c579b1SScott Long /* 880f1c579b1SScott Long **************************************************************************** 881f1c579b1SScott Long **************************************************************************** 882f1c579b1SScott Long */ 883ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb) 884f1c579b1SScott Long { 885ad6d6297SScott Long struct CommandControlBlock *srb; 88644f05562SScott Long u_int32_t intmask_org; 887ad6d6297SScott Long u_int32_t i=0; 888f1c579b1SScott Long 88944f05562SScott Long if(acb->srboutstandingcount>0) { 89044f05562SScott Long /* disable all outbound interrupt */ 89144f05562SScott Long intmask_org=arcmsr_disable_allintr(acb); 89244f05562SScott Long /*clear and abort all outbound posted Q*/ 89344f05562SScott Long arcmsr_done4abort_postqueue(acb); 894f1c579b1SScott Long /* talk to iop 331 outstanding command aborted*/ 895ad6d6297SScott Long arcmsr_abort_allcmd(acb); 896ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 897ad6d6297SScott Long srb=acb->psrb_pool[i]; 89822f2616bSXin LI if(srb->srb_state==ARCMSR_SRB_START) { 89922f2616bSXin LI srb->srb_state=ARCMSR_SRB_ABORTED; 900ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 901ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 90222f2616bSXin LI printf("arcmsr%d: scsi id=%d lun=%d srb='%p' aborted\n" 90322f2616bSXin LI , acb->pci_unit, srb->pccb->ccb_h.target_id 90422f2616bSXin LI , srb->pccb->ccb_h.target_lun, srb); 905f1c579b1SScott Long } 906f1c579b1SScott Long } 907f1c579b1SScott Long /* enable all outbound interrupt */ 90844f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 909f1c579b1SScott Long } 91022f2616bSXin LI acb->srboutstandingcount=0; 911ad6d6297SScott Long acb->workingsrb_doneindex=0; 912ad6d6297SScott Long acb->workingsrb_startindex=0; 91322f2616bSXin LI #ifdef ARCMSR_DEBUG1 91422f2616bSXin LI acb->pktRequestCount = 0; 91522f2616bSXin LI acb->pktReturnCount = 0; 91622f2616bSXin LI #endif 917f1c579b1SScott Long } 918f1c579b1SScott Long /* 919f1c579b1SScott Long ********************************************************************** 920f1c579b1SScott Long ********************************************************************** 921f1c579b1SScott Long */ 92244f05562SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, 92344f05562SScott Long bus_dma_segment_t *dm_segs, u_int32_t nseg) 924f1c579b1SScott Long { 925ad6d6297SScott Long struct ARCMSR_CDB * arcmsr_cdb= &srb->arcmsr_cdb; 926ad6d6297SScott Long u_int8_t * psge=(u_int8_t *)&arcmsr_cdb->u; 927ad6d6297SScott Long u_int32_t address_lo, address_hi; 928ad6d6297SScott Long union ccb * pccb=srb->pccb; 929f1c579b1SScott Long struct ccb_scsiio * pcsio= &pccb->csio; 930ad6d6297SScott Long u_int32_t arccdbsize=0x30; 931f1c579b1SScott Long 932ad6d6297SScott Long memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB)); 933ad6d6297SScott Long arcmsr_cdb->Bus=0; 934ad6d6297SScott Long arcmsr_cdb->TargetID=pccb->ccb_h.target_id; 935ad6d6297SScott Long arcmsr_cdb->LUN=pccb->ccb_h.target_lun; 936ad6d6297SScott Long arcmsr_cdb->Function=1; 937ad6d6297SScott Long arcmsr_cdb->CdbLength=(u_int8_t)pcsio->cdb_len; 93844f05562SScott Long arcmsr_cdb->Context=0; 939ad6d6297SScott Long bcopy(pcsio->cdb_io.cdb_bytes, arcmsr_cdb->Cdb, pcsio->cdb_len); 940ad6d6297SScott Long if(nseg != 0) { 941ad6d6297SScott Long struct AdapterControlBlock *acb=srb->acb; 942f1c579b1SScott Long bus_dmasync_op_t op; 943ad6d6297SScott Long u_int32_t length, i, cdb_sgcount=0; 944f1c579b1SScott Long 945ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 946ad6d6297SScott Long op=BUS_DMASYNC_PREREAD; 947ad6d6297SScott Long } else { 948ad6d6297SScott Long op=BUS_DMASYNC_PREWRITE; 949ad6d6297SScott Long arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_WRITE; 950ad6d6297SScott Long srb->srb_flags|=SRB_FLAG_WRITE; 951ad6d6297SScott Long } 952ad6d6297SScott Long bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 953ad6d6297SScott Long for(i=0;i<nseg;i++) { 954f1c579b1SScott Long /* Get the physical address of the current data pointer */ 955ad6d6297SScott Long length=arcmsr_htole32(dm_segs[i].ds_len); 956ad6d6297SScott Long address_lo=arcmsr_htole32(dma_addr_lo32(dm_segs[i].ds_addr)); 957ad6d6297SScott Long address_hi=arcmsr_htole32(dma_addr_hi32(dm_segs[i].ds_addr)); 958ad6d6297SScott Long if(address_hi==0) { 959ad6d6297SScott Long struct SG32ENTRY * pdma_sg=(struct SG32ENTRY *)psge; 960f1c579b1SScott Long pdma_sg->address=address_lo; 961f1c579b1SScott Long pdma_sg->length=length; 962ad6d6297SScott Long psge += sizeof(struct SG32ENTRY); 963ad6d6297SScott Long arccdbsize += sizeof(struct SG32ENTRY); 964ad6d6297SScott Long } else { 965ad6d6297SScott Long u_int32_t sg64s_size=0, tmplength=length; 966f1c579b1SScott Long 967ad6d6297SScott Long while(1) { 968ad6d6297SScott Long u_int64_t span4G, length0; 969ad6d6297SScott Long struct SG64ENTRY * pdma_sg=(struct SG64ENTRY *)psge; 970f1c579b1SScott Long 971ad6d6297SScott Long span4G=(u_int64_t)address_lo + tmplength; 972f1c579b1SScott Long pdma_sg->addresshigh=address_hi; 973f1c579b1SScott Long pdma_sg->address=address_lo; 974ad6d6297SScott Long if(span4G > 0x100000000) { 975f1c579b1SScott Long /*see if cross 4G boundary*/ 976f1c579b1SScott Long length0=0x100000000-address_lo; 977ad6d6297SScott Long pdma_sg->length=(u_int32_t)length0|IS_SG64_ADDR; 978f1c579b1SScott Long address_hi=address_hi+1; 979f1c579b1SScott Long address_lo=0; 980ad6d6297SScott Long tmplength=tmplength-(u_int32_t)length0; 981ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 982ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 983f1c579b1SScott Long cdb_sgcount++; 984ad6d6297SScott Long } else { 985f1c579b1SScott Long pdma_sg->length=tmplength|IS_SG64_ADDR; 986ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 987ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 988f1c579b1SScott Long break; 989f1c579b1SScott Long } 990f1c579b1SScott Long } 991f1c579b1SScott Long arccdbsize += sg64s_size; 992f1c579b1SScott Long } 993f1c579b1SScott Long cdb_sgcount++; 994f1c579b1SScott Long } 995ad6d6297SScott Long arcmsr_cdb->sgcount=(u_int8_t)cdb_sgcount; 996ad6d6297SScott Long arcmsr_cdb->DataLength=pcsio->dxfer_len; 997ad6d6297SScott Long if( arccdbsize > 256) { 998ad6d6297SScott Long arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_SGL_BSIZE; 999f1c579b1SScott Long } 1000d74001adSXin LI } else { 1001d74001adSXin LI arcmsr_cdb->DataLength = 0; 1002f1c579b1SScott Long } 1003d74001adSXin LI srb->arc_cdb_size=arccdbsize; 1004f1c579b1SScott Long } 1005f1c579b1SScott Long /* 1006f1c579b1SScott Long ************************************************************************** 1007f1c579b1SScott Long ************************************************************************** 1008f1c579b1SScott Long */ 1009ad6d6297SScott Long static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandControlBlock *srb) 1010f1c579b1SScott Long { 1011ad6d6297SScott Long u_int32_t cdb_shifted_phyaddr=(u_int32_t) srb->cdb_shifted_phyaddr; 1012ad6d6297SScott Long struct ARCMSR_CDB * arcmsr_cdb=(struct ARCMSR_CDB *)&srb->arcmsr_cdb; 1013f1c579b1SScott Long 1014d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, (srb->srb_flags & SRB_FLAG_WRITE) ? BUS_DMASYNC_POSTWRITE:BUS_DMASYNC_POSTREAD); 1015ad6d6297SScott Long atomic_add_int(&acb->srboutstandingcount, 1); 101622f2616bSXin LI srb->srb_state=ARCMSR_SRB_START; 1017d74001adSXin LI 101844f05562SScott Long switch (acb->adapter_type) { 101944f05562SScott Long case ACB_ADAPTER_TYPE_A: { 1020ad6d6297SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 1021d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE); 1022ad6d6297SScott Long } else { 1023d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_shifted_phyaddr); 102444f05562SScott Long } 102544f05562SScott Long } 102644f05562SScott Long break; 102744f05562SScott Long case ACB_ADAPTER_TYPE_B: { 102844f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 102944f05562SScott Long int ending_index, index; 103044f05562SScott Long 103144f05562SScott Long index=phbbmu->postq_index; 103244f05562SScott Long ending_index=((index+1)%ARCMSR_MAX_HBB_POSTQUEUE); 103344f05562SScott Long phbbmu->post_qbuffer[ending_index]=0; 103444f05562SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 1035d74001adSXin LI phbbmu->post_qbuffer[index]= cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE; 103644f05562SScott Long } else { 1037d74001adSXin LI phbbmu->post_qbuffer[index]= cdb_shifted_phyaddr; 103844f05562SScott Long } 103944f05562SScott Long index++; 104044f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 104144f05562SScott Long phbbmu->postq_index=index; 1042d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED); 1043d74001adSXin LI } 1044d74001adSXin LI break; 1045d74001adSXin LI case ACB_ADAPTER_TYPE_C: 1046d74001adSXin LI { 1047d74001adSXin LI u_int32_t ccb_post_stamp, arc_cdb_size, cdb_phyaddr_hi32; 1048d74001adSXin LI 1049d74001adSXin LI arc_cdb_size=(srb->arc_cdb_size>0x300)?0x300:srb->arc_cdb_size; 1050d74001adSXin LI ccb_post_stamp=(cdb_shifted_phyaddr | ((arc_cdb_size-1) >> 6) | 1); 1051d74001adSXin LI cdb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high; 1052d74001adSXin LI if(cdb_phyaddr_hi32) 1053d74001adSXin LI { 1054d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_high, cdb_phyaddr_hi32); 1055d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp); 1056d74001adSXin LI } 1057d74001adSXin LI else 1058d74001adSXin LI { 1059d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp); 1060d74001adSXin LI } 106144f05562SScott Long } 106244f05562SScott Long break; 1063f1c579b1SScott Long } 1064f1c579b1SScott Long } 1065f1c579b1SScott Long /* 106644f05562SScott Long ************************************************************************ 106744f05562SScott Long ************************************************************************ 106844f05562SScott Long */ 106944f05562SScott Long static struct QBUFFER * arcmsr_get_iop_rqbuffer( struct AdapterControlBlock *acb) 107044f05562SScott Long { 107144f05562SScott Long struct QBUFFER *qbuffer=NULL; 107244f05562SScott Long 107344f05562SScott Long switch (acb->adapter_type) { 107444f05562SScott Long case ACB_ADAPTER_TYPE_A: { 107544f05562SScott Long struct HBA_MessageUnit *phbamu=(struct HBA_MessageUnit *)acb->pmu; 107644f05562SScott Long 107744f05562SScott Long qbuffer=(struct QBUFFER *)&phbamu->message_rbuffer; 107844f05562SScott Long } 107944f05562SScott Long break; 108044f05562SScott Long case ACB_ADAPTER_TYPE_B: { 108144f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 108244f05562SScott Long 108344f05562SScott Long qbuffer=(struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_rbuffer; 108444f05562SScott Long } 108544f05562SScott Long break; 1086d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1087d74001adSXin LI struct HBC_MessageUnit *phbcmu=(struct HBC_MessageUnit *)acb->pmu; 1088d74001adSXin LI 1089d74001adSXin LI qbuffer=(struct QBUFFER *)&phbcmu->message_rbuffer; 1090d74001adSXin LI } 1091d74001adSXin LI break; 109244f05562SScott Long } 109344f05562SScott Long return(qbuffer); 109444f05562SScott Long } 109544f05562SScott Long /* 109644f05562SScott Long ************************************************************************ 109744f05562SScott Long ************************************************************************ 109844f05562SScott Long */ 109944f05562SScott Long static struct QBUFFER * arcmsr_get_iop_wqbuffer( struct AdapterControlBlock *acb) 110044f05562SScott Long { 110144f05562SScott Long struct QBUFFER *qbuffer=NULL; 110244f05562SScott Long 110344f05562SScott Long switch (acb->adapter_type) { 110444f05562SScott Long case ACB_ADAPTER_TYPE_A: { 110544f05562SScott Long struct HBA_MessageUnit *phbamu=(struct HBA_MessageUnit *)acb->pmu; 110644f05562SScott Long 110744f05562SScott Long qbuffer=(struct QBUFFER *)&phbamu->message_wbuffer; 110844f05562SScott Long } 110944f05562SScott Long break; 111044f05562SScott Long case ACB_ADAPTER_TYPE_B: { 111144f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 111244f05562SScott Long 111344f05562SScott Long qbuffer=(struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_wbuffer; 111444f05562SScott Long } 111544f05562SScott Long break; 1116d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1117d74001adSXin LI struct HBC_MessageUnit *phbcmu=(struct HBC_MessageUnit *)acb->pmu; 1118d74001adSXin LI 1119d74001adSXin LI qbuffer=(struct QBUFFER *)&phbcmu->message_wbuffer; 1120d74001adSXin LI } 1121d74001adSXin LI break; 112244f05562SScott Long } 112344f05562SScott Long return(qbuffer); 112444f05562SScott Long } 112544f05562SScott Long /* 112644f05562SScott Long ************************************************************************** 112744f05562SScott Long ************************************************************************** 112844f05562SScott Long */ 112944f05562SScott Long static void arcmsr_iop_message_read(struct AdapterControlBlock *acb) 113044f05562SScott Long { 113144f05562SScott Long switch (acb->adapter_type) { 113244f05562SScott Long case ACB_ADAPTER_TYPE_A: { 113344f05562SScott Long /* let IOP know data has been read */ 1134d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 113544f05562SScott Long } 113644f05562SScott Long break; 113744f05562SScott Long case ACB_ADAPTER_TYPE_B: { 113844f05562SScott Long /* let IOP know data has been read */ 1139d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 114044f05562SScott Long } 114144f05562SScott Long break; 1142d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1143d74001adSXin LI /* let IOP know data has been read */ 1144d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK); 1145d74001adSXin LI } 114644f05562SScott Long } 114744f05562SScott Long } 114844f05562SScott Long /* 114944f05562SScott Long ************************************************************************** 115044f05562SScott Long ************************************************************************** 115144f05562SScott Long */ 115244f05562SScott Long static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) 115344f05562SScott Long { 115444f05562SScott Long switch (acb->adapter_type) { 115544f05562SScott Long case ACB_ADAPTER_TYPE_A: { 115644f05562SScott Long /* 115744f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 115844f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 115944f05562SScott Long */ 1160d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK); 116144f05562SScott Long } 116244f05562SScott Long break; 116344f05562SScott Long case ACB_ADAPTER_TYPE_B: { 116444f05562SScott Long /* 116544f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 116644f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 116744f05562SScott Long */ 1168d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_WRITE_OK); 1169d74001adSXin LI } 1170d74001adSXin LI break; 1171d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1172d74001adSXin LI /* 1173d74001adSXin LI ** push inbound doorbell tell iop, driver data write ok 1174d74001adSXin LI ** and wait reply on next hwinterrupt for next Qbuffer post 1175d74001adSXin LI */ 1176d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK); 117744f05562SScott Long } 117844f05562SScott Long break; 117944f05562SScott Long } 118044f05562SScott Long } 118144f05562SScott Long /* 1182f1c579b1SScott Long ********************************************************************** 1183f1c579b1SScott Long ********************************************************************** 1184f1c579b1SScott Long */ 118544f05562SScott Long static void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb) 1186f1c579b1SScott Long { 1187ad6d6297SScott Long u_int8_t *pQbuffer; 118844f05562SScott Long struct QBUFFER *pwbuffer; 118944f05562SScott Long u_int8_t * iop_data; 119044f05562SScott Long int32_t allxfer_len=0; 1191f1c579b1SScott Long 119244f05562SScott Long pwbuffer=arcmsr_get_iop_wqbuffer(acb); 119344f05562SScott Long iop_data=(u_int8_t *)pwbuffer->data; 119444f05562SScott Long if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) { 119544f05562SScott Long acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 119644f05562SScott Long while((acb->wqbuf_firstindex!=acb->wqbuf_lastindex) 119744f05562SScott Long && (allxfer_len<124)) { 1198ad6d6297SScott Long pQbuffer=&acb->wqbuffer[acb->wqbuf_firstindex]; 1199f1c579b1SScott Long memcpy(iop_data, pQbuffer, 1); 1200ad6d6297SScott Long acb->wqbuf_firstindex++; 120144f05562SScott Long acb->wqbuf_firstindex %=ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */ 1202f1c579b1SScott Long iop_data++; 1203f1c579b1SScott Long allxfer_len++; 1204f1c579b1SScott Long } 1205f1c579b1SScott Long pwbuffer->data_len=allxfer_len; 1206f1c579b1SScott Long /* 1207f1c579b1SScott Long ** push inbound doorbell and wait reply at hwinterrupt routine for next Qbuffer post 1208f1c579b1SScott Long */ 120944f05562SScott Long arcmsr_iop_message_wrote(acb); 1210ad6d6297SScott Long } 1211f1c579b1SScott Long } 1212f1c579b1SScott Long /* 1213f1c579b1SScott Long ************************************************************************ 1214f1c579b1SScott Long ************************************************************************ 1215f1c579b1SScott Long */ 121644f05562SScott Long static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb) 1217f1c579b1SScott Long { 1218ad6d6297SScott Long acb->acb_flags &=~ACB_F_MSG_START_BGRB; 121944f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 122044f05562SScott Long 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 122144f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 1222d74001adSXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n" 1223ad6d6297SScott Long , acb->pci_unit); 1224ad6d6297SScott Long } 1225f1c579b1SScott Long } 1226f1c579b1SScott Long /* 1227f1c579b1SScott Long ************************************************************************ 1228f1c579b1SScott Long ************************************************************************ 1229f1c579b1SScott Long */ 123044f05562SScott Long static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb) 123144f05562SScott Long { 123244f05562SScott Long acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 123344f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 123444f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_STOP_BGRB); 123544f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 1236d74001adSXin LI printf( "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" 123744f05562SScott Long , acb->pci_unit); 123844f05562SScott Long } 123944f05562SScott Long } 124044f05562SScott Long /* 124144f05562SScott Long ************************************************************************ 124244f05562SScott Long ************************************************************************ 124344f05562SScott Long */ 1244d74001adSXin LI static void arcmsr_stop_hbc_bgrb(struct AdapterControlBlock *acb) 1245d74001adSXin LI { 1246d74001adSXin LI acb->acb_flags &=~ACB_F_MSG_START_BGRB; 1247d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 1248d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 1249d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 1250d74001adSXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit); 1251d74001adSXin LI } 1252d74001adSXin LI } 1253d74001adSXin LI /* 1254d74001adSXin LI ************************************************************************ 1255d74001adSXin LI ************************************************************************ 1256d74001adSXin LI */ 125744f05562SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) 125844f05562SScott Long { 125944f05562SScott Long switch (acb->adapter_type) { 126044f05562SScott Long case ACB_ADAPTER_TYPE_A: { 126144f05562SScott Long arcmsr_stop_hba_bgrb(acb); 126244f05562SScott Long } 126344f05562SScott Long break; 126444f05562SScott Long case ACB_ADAPTER_TYPE_B: { 126544f05562SScott Long arcmsr_stop_hbb_bgrb(acb); 126644f05562SScott Long } 126744f05562SScott Long break; 1268d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1269d74001adSXin LI arcmsr_stop_hbc_bgrb(acb); 1270d74001adSXin LI } 1271d74001adSXin LI break; 127244f05562SScott Long } 127344f05562SScott Long } 127444f05562SScott Long /* 127544f05562SScott Long ************************************************************************ 127644f05562SScott Long ************************************************************************ 127744f05562SScott Long */ 1278ad6d6297SScott Long static void arcmsr_poll(struct cam_sim * psim) 1279f1c579b1SScott Long { 1280579ec1a5SScott Long struct AdapterControlBlock *acb; 12814e32649fSXin LI int mutex; 1282579ec1a5SScott Long 1283579ec1a5SScott Long acb = (struct AdapterControlBlock *)cam_sim_softc(psim); 12844e32649fSXin LI mutex = mtx_owned(&acb->qbuffer_lock); 12854e32649fSXin LI if( mutex == 0 ) 1286579ec1a5SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 1287579ec1a5SScott Long arcmsr_interrupt(acb); 12884e32649fSXin LI if( mutex == 0 ) 1289579ec1a5SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1290f1c579b1SScott Long } 1291f1c579b1SScott Long /* 129244f05562SScott Long ************************************************************************** 129344f05562SScott Long ************************************************************************** 12945878cbecSScott Long */ 129544f05562SScott Long static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) 1296f1c579b1SScott Long { 129744f05562SScott Long struct QBUFFER *prbuffer; 1298ad6d6297SScott Long u_int8_t *pQbuffer; 129944f05562SScott Long u_int8_t *iop_data; 130044f05562SScott Long int my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; 1301ad6d6297SScott Long 1302f1c579b1SScott Long /*check this iop data if overflow my rqbuffer*/ 1303ad6d6297SScott Long rqbuf_lastindex=acb->rqbuf_lastindex; 1304ad6d6297SScott Long rqbuf_firstindex=acb->rqbuf_firstindex; 130544f05562SScott Long prbuffer=arcmsr_get_iop_rqbuffer(acb); 130644f05562SScott Long iop_data=(u_int8_t *)prbuffer->data; 1307f1c579b1SScott Long iop_len=prbuffer->data_len; 1308f1c579b1SScott Long my_empty_len=(rqbuf_firstindex-rqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1); 1309ad6d6297SScott Long if(my_empty_len>=iop_len) { 1310ad6d6297SScott Long while(iop_len > 0) { 131144f05562SScott Long pQbuffer=&acb->rqbuffer[rqbuf_lastindex]; 1312f1c579b1SScott Long memcpy(pQbuffer, iop_data, 1); 131344f05562SScott Long rqbuf_lastindex++; 131444f05562SScott Long rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;/*if last index number set it to 0 */ 1315f1c579b1SScott Long iop_data++; 1316f1c579b1SScott Long iop_len--; 1317f1c579b1SScott Long } 131844f05562SScott Long acb->rqbuf_lastindex=rqbuf_lastindex; 131944f05562SScott Long arcmsr_iop_message_read(acb); 132044f05562SScott Long /*signature, let IOP know data has been read */ 1321ad6d6297SScott Long } else { 1322ad6d6297SScott Long acb->acb_flags|=ACB_F_IOPDATA_OVERFLOW; 1323f1c579b1SScott Long } 1324f1c579b1SScott Long } 1325f1c579b1SScott Long /* 132644f05562SScott Long ************************************************************************** 132744f05562SScott Long ************************************************************************** 132844f05562SScott Long */ 132944f05562SScott Long static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) 133044f05562SScott Long { 133144f05562SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READ; 133244f05562SScott Long /* 133344f05562SScott Long ***************************************************************** 133444f05562SScott Long ** check if there are any mail packages from user space program 133544f05562SScott Long ** in my post bag, now is the time to send them into Areca's firmware 133644f05562SScott Long ***************************************************************** 1337f1c579b1SScott Long */ 1338ad6d6297SScott Long if(acb->wqbuf_firstindex!=acb->wqbuf_lastindex) { 1339ad6d6297SScott Long u_int8_t *pQbuffer; 134044f05562SScott Long struct QBUFFER *pwbuffer; 134144f05562SScott Long u_int8_t *iop_data; 134244f05562SScott Long int allxfer_len=0; 1343f1c579b1SScott Long 134444f05562SScott Long acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 134544f05562SScott Long pwbuffer=arcmsr_get_iop_wqbuffer(acb); 134644f05562SScott Long iop_data=(u_int8_t *)pwbuffer->data; 134744f05562SScott Long while((acb->wqbuf_firstindex!=acb->wqbuf_lastindex) 134844f05562SScott Long && (allxfer_len<124)) { 1349ad6d6297SScott Long pQbuffer=&acb->wqbuffer[acb->wqbuf_firstindex]; 1350f1c579b1SScott Long memcpy(iop_data, pQbuffer, 1); 1351ad6d6297SScott Long acb->wqbuf_firstindex++; 135244f05562SScott Long acb->wqbuf_firstindex %=ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */ 1353f1c579b1SScott Long iop_data++; 1354f1c579b1SScott Long allxfer_len++; 1355f1c579b1SScott Long } 1356f1c579b1SScott Long pwbuffer->data_len=allxfer_len; 1357f1c579b1SScott Long /* 1358ad6d6297SScott Long ** push inbound doorbell tell iop driver data write ok 1359ad6d6297SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 1360f1c579b1SScott Long */ 136144f05562SScott Long arcmsr_iop_message_wrote(acb); 1362f1c579b1SScott Long } 1363ad6d6297SScott Long if(acb->wqbuf_firstindex==acb->wqbuf_lastindex) { 1364ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; 1365f1c579b1SScott Long } 1366f1c579b1SScott Long } 1367d74001adSXin LI 1368d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb) 1369d74001adSXin LI { 1370d74001adSXin LI /* 1371d74001adSXin LI if (ccb->ccb_h.status != CAM_REQ_CMP) 1372d74001adSXin LI printf("arcmsr_rescanLun_cb: Rescan Target=%x, lun=%x, failure status=%x\n",ccb->ccb_h.target_id,ccb->ccb_h.target_lun,ccb->ccb_h.status); 1373d74001adSXin LI else 1374d74001adSXin LI printf("arcmsr_rescanLun_cb: Rescan lun successfully!\n"); 1375d74001adSXin LI */ 1376d74001adSXin LI xpt_free_path(ccb->ccb_h.path); 1377d74001adSXin LI xpt_free_ccb(ccb); 1378d74001adSXin LI } 1379d74001adSXin LI 1380d74001adSXin LI static void arcmsr_rescan_lun(struct AdapterControlBlock *acb, int target, int lun) 1381d74001adSXin LI { 1382d74001adSXin LI struct cam_path *path; 1383d74001adSXin LI union ccb *ccb; 1384d74001adSXin LI 1385d74001adSXin LI if ((ccb = (union ccb *)xpt_alloc_ccb_nowait()) == NULL) 1386d74001adSXin LI return; 1387d74001adSXin LI if (xpt_create_path(&path, xpt_periph, cam_sim_path(acb->psim), target, lun) != CAM_REQ_CMP) 1388d74001adSXin LI { 1389d74001adSXin LI xpt_free_ccb(ccb); 1390d74001adSXin LI return; 1391d74001adSXin LI } 1392d74001adSXin LI /* printf("arcmsr_rescan_lun: Rescan Target=%x, Lun=%x\n", target, lun); */ 1393d74001adSXin LI bzero(ccb, sizeof(union ccb)); 1394d74001adSXin LI xpt_setup_ccb(&ccb->ccb_h, path, 5); 1395d74001adSXin LI ccb->ccb_h.func_code = XPT_SCAN_LUN; 1396d74001adSXin LI ccb->ccb_h.cbfcnp = arcmsr_rescanLun_cb; 1397d74001adSXin LI ccb->crcn.flags = CAM_FLAG_NONE; 1398d74001adSXin LI xpt_action(ccb); 1399d74001adSXin LI } 1400d74001adSXin LI 1401d74001adSXin LI 1402d74001adSXin LI static void arcmsr_abort_dr_ccbs(struct AdapterControlBlock *acb, int target, int lun) 1403d74001adSXin LI { 1404d74001adSXin LI struct CommandControlBlock *srb; 1405d74001adSXin LI u_int32_t intmask_org; 1406d74001adSXin LI int i; 1407d74001adSXin LI 1408d74001adSXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 1409d74001adSXin LI /* disable all outbound interrupts */ 1410d74001adSXin LI intmask_org = arcmsr_disable_allintr(acb); 1411d74001adSXin LI for (i = 0; i < ARCMSR_MAX_FREESRB_NUM; i++) 1412d74001adSXin LI { 1413d74001adSXin LI srb = acb->psrb_pool[i]; 141422f2616bSXin LI if (srb->srb_state == ARCMSR_SRB_START) 1415d74001adSXin LI { 1416d74001adSXin LI if((target == srb->pccb->ccb_h.target_id) && (lun == srb->pccb->ccb_h.target_lun)) 1417d74001adSXin LI { 141822f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 1419d74001adSXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 1420d74001adSXin LI arcmsr_srb_complete(srb, 1); 142122f2616bSXin LI printf("arcmsr%d: abort scsi id %d lun %d srb=%p \n", acb->pci_unit, target, lun, srb); 1422d74001adSXin LI } 1423d74001adSXin LI } 1424d74001adSXin LI } 1425d74001adSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 1426d74001adSXin LI arcmsr_enable_allintr(acb, intmask_org); 1427d74001adSXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1428d74001adSXin LI } 1429d74001adSXin LI 1430d74001adSXin LI 1431d74001adSXin LI /* 1432d74001adSXin LI ************************************************************************** 1433d74001adSXin LI ************************************************************************** 1434d74001adSXin LI */ 1435d74001adSXin LI static void arcmsr_dr_handle(struct AdapterControlBlock *acb) { 1436d74001adSXin LI u_int32_t devicemap; 1437d74001adSXin LI u_int32_t target, lun; 1438d74001adSXin LI u_int32_t deviceMapCurrent[4]={0}; 1439d74001adSXin LI u_int8_t *pDevMap; 1440d74001adSXin LI 1441d74001adSXin LI switch (acb->adapter_type) { 1442d74001adSXin LI case ACB_ADAPTER_TYPE_A: 1443d74001adSXin LI devicemap = offsetof(struct HBA_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1444d74001adSXin LI for (target= 0; target < 4; target++) 1445d74001adSXin LI { 1446d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1447d74001adSXin LI devicemap += 4; 1448d74001adSXin LI } 1449d74001adSXin LI break; 1450d74001adSXin LI 1451d74001adSXin LI case ACB_ADAPTER_TYPE_B: 1452d74001adSXin LI devicemap = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1453d74001adSXin LI for (target= 0; target < 4; target++) 1454d74001adSXin LI { 1455d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[1], acb->bhandle[1], devicemap); 1456d74001adSXin LI devicemap += 4; 1457d74001adSXin LI } 1458d74001adSXin LI break; 1459d74001adSXin LI 1460d74001adSXin LI case ACB_ADAPTER_TYPE_C: 1461d74001adSXin LI devicemap = offsetof(struct HBC_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1462d74001adSXin LI for (target= 0; target < 4; target++) 1463d74001adSXin LI { 1464d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1465d74001adSXin LI devicemap += 4; 1466d74001adSXin LI } 1467d74001adSXin LI break; 1468d74001adSXin LI } 1469dac36688SXin LI 1470d74001adSXin LI if(acb->acb_flags & ACB_F_BUS_HANG_ON) 1471d74001adSXin LI { 1472d74001adSXin LI acb->acb_flags &= ~ACB_F_BUS_HANG_ON; 1473d74001adSXin LI } 1474d74001adSXin LI /* 1475d74001adSXin LI ** adapter posted CONFIG message 1476d74001adSXin LI ** copy the new map, note if there are differences with the current map 1477d74001adSXin LI */ 1478d74001adSXin LI pDevMap = (u_int8_t *)&deviceMapCurrent[0]; 1479d74001adSXin LI for (target= 0; target < ARCMSR_MAX_TARGETID - 1; target++) 1480d74001adSXin LI { 1481d74001adSXin LI if (*pDevMap != acb->device_map[target]) 1482d74001adSXin LI { 1483d74001adSXin LI u_int8_t difference, bit_check; 1484d74001adSXin LI 1485d74001adSXin LI difference= *pDevMap ^ acb->device_map[target]; 1486d74001adSXin LI for(lun=0; lun < ARCMSR_MAX_TARGETLUN; lun++) 1487d74001adSXin LI { 1488d74001adSXin LI bit_check=(1 << lun); /*check bit from 0....31*/ 1489d74001adSXin LI if(difference & bit_check) 1490d74001adSXin LI { 1491d74001adSXin LI if(acb->device_map[target] & bit_check) 1492d74001adSXin LI {/* unit departed */ 1493d74001adSXin LI printf("arcmsr_dr_handle: Target=%x, lun=%x, GONE!!!\n",target,lun); 1494d74001adSXin LI arcmsr_abort_dr_ccbs(acb, target, lun); 1495d74001adSXin LI arcmsr_rescan_lun(acb, target, lun); 1496d74001adSXin LI acb->devstate[target][lun] = ARECA_RAID_GONE; 1497d74001adSXin LI } 1498d74001adSXin LI else 1499d74001adSXin LI {/* unit arrived */ 150022f2616bSXin LI printf("arcmsr_dr_handle: Target=%x, lun=%x, Plug-IN!!!\n",target,lun); 1501d74001adSXin LI arcmsr_rescan_lun(acb, target, lun); 1502d74001adSXin LI acb->devstate[target][lun] = ARECA_RAID_GOOD; 1503d74001adSXin LI } 1504d74001adSXin LI } 1505d74001adSXin LI } 1506d74001adSXin LI /* printf("arcmsr_dr_handle: acb->device_map[%x]=0x%x, deviceMapCurrent[%x]=%x\n",target,acb->device_map[target],target,*pDevMap); */ 1507d74001adSXin LI acb->device_map[target]= *pDevMap; 1508d74001adSXin LI } 1509d74001adSXin LI pDevMap++; 1510d74001adSXin LI } 1511d74001adSXin LI } 1512d74001adSXin LI /* 1513d74001adSXin LI ************************************************************************** 1514d74001adSXin LI ************************************************************************** 1515d74001adSXin LI */ 1516d74001adSXin LI static void arcmsr_hba_message_isr(struct AdapterControlBlock *acb) { 1517d74001adSXin LI u_int32_t outbound_message; 1518d74001adSXin LI 1519d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT); 1520d74001adSXin LI outbound_message = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[0]); 1521d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1522d74001adSXin LI arcmsr_dr_handle( acb ); 1523d74001adSXin LI } 1524d74001adSXin LI /* 1525d74001adSXin LI ************************************************************************** 1526d74001adSXin LI ************************************************************************** 1527d74001adSXin LI */ 1528d74001adSXin LI static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) { 1529d74001adSXin LI u_int32_t outbound_message; 1530d74001adSXin LI 1531d74001adSXin LI /* clear interrupts */ 1532d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN); 1533d74001adSXin LI outbound_message = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0]); 1534d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1535d74001adSXin LI arcmsr_dr_handle( acb ); 1536d74001adSXin LI } 1537d74001adSXin LI /* 1538d74001adSXin LI ************************************************************************** 1539d74001adSXin LI ************************************************************************** 1540d74001adSXin LI */ 1541d74001adSXin LI static void arcmsr_hbc_message_isr(struct AdapterControlBlock *acb) { 1542d74001adSXin LI u_int32_t outbound_message; 1543d74001adSXin LI 1544d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR); 1545d74001adSXin LI outbound_message = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[0]); 1546d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1547d74001adSXin LI arcmsr_dr_handle( acb ); 1548d74001adSXin LI } 154944f05562SScott Long /* 155044f05562SScott Long ************************************************************************** 155144f05562SScott Long ************************************************************************** 155244f05562SScott Long */ 155344f05562SScott Long static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) 155444f05562SScott Long { 155544f05562SScott Long u_int32_t outbound_doorbell; 155644f05562SScott Long 155744f05562SScott Long /* 155844f05562SScott Long ******************************************************************* 155944f05562SScott Long ** Maybe here we need to check wrqbuffer_lock is lock or not 156044f05562SScott Long ** DOORBELL: din! don! 156144f05562SScott Long ** check if there are any mail need to pack from firmware 156244f05562SScott Long ******************************************************************* 156344f05562SScott Long */ 156444f05562SScott Long outbound_doorbell=CHIP_REG_READ32(HBA_MessageUnit, 156544f05562SScott Long 0, outbound_doorbell); 156644f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 156744f05562SScott Long 0, outbound_doorbell, outbound_doorbell); /* clear doorbell interrupt */ 156844f05562SScott Long if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { 156944f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 1570ad6d6297SScott Long } 157144f05562SScott Long if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { 157244f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 157344f05562SScott Long } 157444f05562SScott Long } 157544f05562SScott Long /* 157644f05562SScott Long ************************************************************************** 157744f05562SScott Long ************************************************************************** 157844f05562SScott Long */ 1579d74001adSXin LI static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb) 1580d74001adSXin LI { 1581d74001adSXin LI u_int32_t outbound_doorbell; 1582d74001adSXin LI 1583d74001adSXin LI /* 1584d74001adSXin LI ******************************************************************* 1585d74001adSXin LI ** Maybe here we need to check wrqbuffer_lock is lock or not 1586d74001adSXin LI ** DOORBELL: din! don! 1587d74001adSXin LI ** check if there are any mail need to pack from firmware 1588d74001adSXin LI ******************************************************************* 1589d74001adSXin LI */ 1590d74001adSXin LI outbound_doorbell=CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); 1591d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell); /* clear doorbell interrupt */ 1592d74001adSXin LI if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) { 1593d74001adSXin LI arcmsr_iop2drv_data_wrote_handle(acb); 1594d74001adSXin LI } 1595d74001adSXin LI if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) { 1596d74001adSXin LI arcmsr_iop2drv_data_read_handle(acb); 1597d74001adSXin LI } 1598d74001adSXin LI if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { 1599d74001adSXin LI arcmsr_hbc_message_isr(acb); /* messenger of "driver to iop commands" */ 1600d74001adSXin LI } 1601d74001adSXin LI } 1602d74001adSXin LI /* 1603d74001adSXin LI ************************************************************************** 1604d74001adSXin LI ************************************************************************** 1605d74001adSXin LI */ 160644f05562SScott Long static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb) 160744f05562SScott Long { 160844f05562SScott Long u_int32_t flag_srb; 1609d74001adSXin LI u_int16_t error; 161044f05562SScott Long 1611f1c579b1SScott Long /* 1612f1c579b1SScott Long ***************************************************************************** 1613f1c579b1SScott Long ** areca cdb command done 1614f1c579b1SScott Long ***************************************************************************** 1615f1c579b1SScott Long */ 161644f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 161744f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 161844f05562SScott Long while((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 161944f05562SScott Long 0, outbound_queueport)) != 0xFFFFFFFF) { 1620f1c579b1SScott Long /* check if command done with no error*/ 1621d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 1622d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 162344f05562SScott Long } /*drain reply FIFO*/ 1624f1c579b1SScott Long } 162544f05562SScott Long /* 162644f05562SScott Long ************************************************************************** 162744f05562SScott Long ************************************************************************** 162844f05562SScott Long */ 162944f05562SScott Long static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) 163044f05562SScott Long { 163144f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 163244f05562SScott Long u_int32_t flag_srb; 163344f05562SScott Long int index; 1634d74001adSXin LI u_int16_t error; 163544f05562SScott Long 163644f05562SScott Long /* 163744f05562SScott Long ***************************************************************************** 163844f05562SScott Long ** areca cdb command done 163944f05562SScott Long ***************************************************************************** 164044f05562SScott Long */ 164144f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 164244f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 164344f05562SScott Long index=phbbmu->doneq_index; 164444f05562SScott Long while((flag_srb=phbbmu->done_qbuffer[index]) != 0) { 164544f05562SScott Long phbbmu->done_qbuffer[index]=0; 164644f05562SScott Long index++; 164744f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 164844f05562SScott Long phbbmu->doneq_index=index; 164944f05562SScott Long /* check if command done with no error*/ 1650d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 1651d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 1652d74001adSXin LI } /*drain reply FIFO*/ 1653d74001adSXin LI } 1654d74001adSXin LI /* 1655d74001adSXin LI ************************************************************************** 1656d74001adSXin LI ************************************************************************** 1657d74001adSXin LI */ 1658d74001adSXin LI static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb) 1659d74001adSXin LI { 1660d74001adSXin LI u_int32_t flag_srb,throttling=0; 1661d74001adSXin LI u_int16_t error; 1662d74001adSXin LI 1663d74001adSXin LI /* 1664d74001adSXin LI ***************************************************************************** 1665d74001adSXin LI ** areca cdb command done 1666d74001adSXin LI ***************************************************************************** 1667d74001adSXin LI */ 1668d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 1669d74001adSXin LI 1670d74001adSXin LI while(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) { 1671d74001adSXin LI 1672d74001adSXin LI flag_srb=CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 1673d74001adSXin LI /* check if command done with no error*/ 1674d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; 1675d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 1676d74001adSXin LI if(throttling==ARCMSR_HBC_ISR_THROTTLING_LEVEL) { 1677d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING); 1678d74001adSXin LI break; 1679d74001adSXin LI } 1680d74001adSXin LI throttling++; 168144f05562SScott Long } /*drain reply FIFO*/ 1682f1c579b1SScott Long } 168344f05562SScott Long /* 168444f05562SScott Long ********************************************************************** 168544f05562SScott Long ********************************************************************** 168644f05562SScott Long */ 168744f05562SScott Long static void arcmsr_handle_hba_isr( struct AdapterControlBlock *acb) 168844f05562SScott Long { 1689dac36688SXin LI u_int32_t outbound_intStatus; 169044f05562SScott Long /* 169144f05562SScott Long ********************************************* 169244f05562SScott Long ** check outbound intstatus 169344f05562SScott Long ********************************************* 169444f05562SScott Long */ 1695dac36688SXin LI outbound_intStatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 1696dac36688SXin LI if(!outbound_intStatus) { 169744f05562SScott Long /*it must be share irq*/ 169844f05562SScott Long return; 1699f1c579b1SScott Long } 1700dac36688SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intStatus);/*clear interrupt*/ 170144f05562SScott Long /* MU doorbell interrupts*/ 1702dac36688SXin LI if(outbound_intStatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) { 170344f05562SScott Long arcmsr_hba_doorbell_isr(acb); 1704f1c579b1SScott Long } 170544f05562SScott Long /* MU post queue interrupts*/ 1706dac36688SXin LI if(outbound_intStatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { 170744f05562SScott Long arcmsr_hba_postqueue_isr(acb); 170844f05562SScott Long } 1709dac36688SXin LI if(outbound_intStatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { 1710d74001adSXin LI arcmsr_hba_message_isr(acb); 1711d74001adSXin LI } 171244f05562SScott Long } 171344f05562SScott Long /* 171444f05562SScott Long ********************************************************************** 171544f05562SScott Long ********************************************************************** 171644f05562SScott Long */ 171744f05562SScott Long static void arcmsr_handle_hbb_isr( struct AdapterControlBlock *acb) 171844f05562SScott Long { 171944f05562SScott Long u_int32_t outbound_doorbell; 172044f05562SScott Long /* 172144f05562SScott Long ********************************************* 172244f05562SScott Long ** check outbound intstatus 172344f05562SScott Long ********************************************* 172444f05562SScott Long */ 172544f05562SScott Long outbound_doorbell=CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & acb->outbound_int_enable; 172644f05562SScott Long if(!outbound_doorbell) { 172744f05562SScott Long /*it must be share irq*/ 172844f05562SScott Long return; 172944f05562SScott Long } 173044f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ~outbound_doorbell); /* clear doorbell interrupt */ 173144f05562SScott Long CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell); 173244f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 173344f05562SScott Long /* MU ioctl transfer doorbell interrupts*/ 173444f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { 173544f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 173644f05562SScott Long } 173744f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) { 173844f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 173944f05562SScott Long } 174044f05562SScott Long /* MU post queue interrupts*/ 174144f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) { 174244f05562SScott Long arcmsr_hbb_postqueue_isr(acb); 174344f05562SScott Long } 1744d74001adSXin LI if(outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { 1745d74001adSXin LI arcmsr_hbb_message_isr(acb); 1746d74001adSXin LI } 1747d74001adSXin LI } 1748d74001adSXin LI /* 1749d74001adSXin LI ********************************************************************** 1750d74001adSXin LI ********************************************************************** 1751d74001adSXin LI */ 1752d74001adSXin LI static void arcmsr_handle_hbc_isr( struct AdapterControlBlock *acb) 1753d74001adSXin LI { 1754d74001adSXin LI u_int32_t host_interrupt_status; 1755d74001adSXin LI /* 1756d74001adSXin LI ********************************************* 1757d74001adSXin LI ** check outbound intstatus 1758d74001adSXin LI ********************************************* 1759d74001adSXin LI */ 1760d74001adSXin LI host_interrupt_status=CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status); 1761d74001adSXin LI if(!host_interrupt_status) { 1762d74001adSXin LI /*it must be share irq*/ 1763d74001adSXin LI return; 1764d74001adSXin LI } 1765d74001adSXin LI /* MU doorbell interrupts*/ 1766d74001adSXin LI if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) { 1767d74001adSXin LI arcmsr_hbc_doorbell_isr(acb); 1768d74001adSXin LI } 1769d74001adSXin LI /* MU post queue interrupts*/ 1770d74001adSXin LI if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) { 1771d74001adSXin LI arcmsr_hbc_postqueue_isr(acb); 1772d74001adSXin LI } 177344f05562SScott Long } 177444f05562SScott Long /* 177544f05562SScott Long ****************************************************************************** 177644f05562SScott Long ****************************************************************************** 177744f05562SScott Long */ 177844f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb) 177944f05562SScott Long { 178044f05562SScott Long switch (acb->adapter_type) { 178144f05562SScott Long case ACB_ADAPTER_TYPE_A: 178244f05562SScott Long arcmsr_handle_hba_isr(acb); 1783f1c579b1SScott Long break; 178444f05562SScott Long case ACB_ADAPTER_TYPE_B: 178544f05562SScott Long arcmsr_handle_hbb_isr(acb); 1786f1c579b1SScott Long break; 1787d74001adSXin LI case ACB_ADAPTER_TYPE_C: 1788d74001adSXin LI arcmsr_handle_hbc_isr(acb); 1789d74001adSXin LI break; 1790f1c579b1SScott Long default: 179144f05562SScott Long printf("arcmsr%d: interrupt service," 179210d66948SKevin Lo " unknown adapter type =%d\n", acb->pci_unit, acb->adapter_type); 1793f1c579b1SScott Long break; 1794f1c579b1SScott Long } 1795f1c579b1SScott Long } 1796f1c579b1SScott Long /* 1797d74001adSXin LI ********************************************************************** 1798d74001adSXin LI ********************************************************************** 1799d74001adSXin LI */ 1800d74001adSXin LI static void arcmsr_intr_handler(void *arg) 1801d74001adSXin LI { 1802d74001adSXin LI struct AdapterControlBlock *acb=(struct AdapterControlBlock *)arg; 1803d74001adSXin LI 1804d74001adSXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 1805d74001adSXin LI arcmsr_interrupt(acb); 1806d74001adSXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1807d74001adSXin LI } 1808d74001adSXin LI /* 1809d74001adSXin LI ****************************************************************************** 1810d74001adSXin LI ****************************************************************************** 1811d74001adSXin LI */ 1812d74001adSXin LI static void arcmsr_polling_devmap(void* arg) 1813d74001adSXin LI { 1814d74001adSXin LI struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg; 1815d74001adSXin LI switch (acb->adapter_type) { 1816d74001adSXin LI case ACB_ADAPTER_TYPE_A: 1817dac36688SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 1818d74001adSXin LI break; 1819d74001adSXin LI 1820d74001adSXin LI case ACB_ADAPTER_TYPE_B: 1821d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG); 1822d74001adSXin LI break; 1823d74001adSXin LI 1824d74001adSXin LI case ACB_ADAPTER_TYPE_C: 1825d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 1826d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 1827d74001adSXin LI break; 1828d74001adSXin LI } 1829d74001adSXin LI 1830d74001adSXin LI if((acb->acb_flags & ACB_F_SCSISTOPADAPTER) == 0) 1831d74001adSXin LI { 1832d74001adSXin LI callout_reset(&acb->devmap_callout, 5 * hz, arcmsr_polling_devmap, acb); /* polling per 5 seconds */ 1833d74001adSXin LI } 1834d74001adSXin LI } 1835d74001adSXin LI 1836d74001adSXin LI /* 1837ad6d6297SScott Long ******************************************************************************* 1838ad6d6297SScott Long ** 1839ad6d6297SScott Long ******************************************************************************* 1840ad6d6297SScott Long */ 1841ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb) 1842ad6d6297SScott Long { 1843d74001adSXin LI u_int32_t intmask_org; 1844d74001adSXin LI 1845ad6d6297SScott Long if(acb!=NULL) { 1846ad6d6297SScott Long /* stop adapter background rebuild */ 1847ad6d6297SScott Long if(acb->acb_flags & ACB_F_MSG_START_BGRB) { 1848d74001adSXin LI intmask_org = arcmsr_disable_allintr(acb); 1849ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 1850ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 1851d74001adSXin LI arcmsr_enable_allintr(acb, intmask_org); 1852ad6d6297SScott Long } 1853ad6d6297SScott Long } 1854ad6d6297SScott Long } 1855ad6d6297SScott Long /* 1856f1c579b1SScott Long *********************************************************************** 1857f1c579b1SScott Long ** 1858f1c579b1SScott Long ************************************************************************ 1859f1c579b1SScott Long */ 1860ad6d6297SScott Long u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg) 1861f1c579b1SScott Long { 1862ad6d6297SScott Long struct CMD_MESSAGE_FIELD * pcmdmessagefld; 1863ad6d6297SScott Long u_int32_t retvalue=EINVAL; 1864f1c579b1SScott Long 1865ad6d6297SScott Long pcmdmessagefld=(struct CMD_MESSAGE_FIELD *) arg; 1866ad6d6297SScott Long if(memcmp(pcmdmessagefld->cmdmessage.Signature, "ARCMSR", 6)!=0) { 1867ad6d6297SScott Long return retvalue; 1868f1c579b1SScott Long } 1869ad6d6297SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 1870ad6d6297SScott Long switch(ioctl_cmd) { 1871ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 1872ad6d6297SScott Long u_int8_t * pQbuffer; 1873ad6d6297SScott Long u_int8_t * ptmpQbuffer=pcmdmessagefld->messagedatabuffer; 1874ad6d6297SScott Long u_int32_t allxfer_len=0; 1875f1c579b1SScott Long 187644f05562SScott Long while((acb->rqbuf_firstindex!=acb->rqbuf_lastindex) 187744f05562SScott Long && (allxfer_len<1031)) { 1878f1c579b1SScott Long /*copy READ QBUFFER to srb*/ 1879ad6d6297SScott Long pQbuffer= &acb->rqbuffer[acb->rqbuf_firstindex]; 1880f1c579b1SScott Long memcpy(ptmpQbuffer, pQbuffer, 1); 1881ad6d6297SScott Long acb->rqbuf_firstindex++; 1882ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 1883ad6d6297SScott Long /*if last index number set it to 0 */ 1884f1c579b1SScott Long ptmpQbuffer++; 1885f1c579b1SScott Long allxfer_len++; 1886f1c579b1SScott Long } 1887ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 188844f05562SScott Long struct QBUFFER * prbuffer; 188944f05562SScott Long u_int8_t * iop_data; 1890ad6d6297SScott Long u_int32_t iop_len; 1891f1c579b1SScott Long 1892ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 189344f05562SScott Long prbuffer=arcmsr_get_iop_rqbuffer(acb); 189444f05562SScott Long iop_data=(u_int8_t *)prbuffer->data; 1895ad6d6297SScott Long iop_len=(u_int32_t)prbuffer->data_len; 1896f1c579b1SScott Long /*this iop data does no chance to make me overflow again here, so just do it*/ 1897ad6d6297SScott Long while(iop_len>0) { 1898ad6d6297SScott Long pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex]; 1899f1c579b1SScott Long memcpy(pQbuffer, iop_data, 1); 1900ad6d6297SScott Long acb->rqbuf_lastindex++; 1901ad6d6297SScott Long acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 1902ad6d6297SScott Long /*if last index number set it to 0 */ 1903f1c579b1SScott Long iop_data++; 1904f1c579b1SScott Long iop_len--; 1905f1c579b1SScott Long } 190644f05562SScott Long arcmsr_iop_message_read(acb); 190744f05562SScott Long /*signature, let IOP know data has been readed */ 1908f1c579b1SScott Long } 1909ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length=allxfer_len; 1910ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1911ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1912f1c579b1SScott Long } 1913f1c579b1SScott Long break; 1914ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 1915ad6d6297SScott Long u_int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 1916ad6d6297SScott Long u_int8_t * pQbuffer; 1917ad6d6297SScott Long u_int8_t * ptmpuserbuffer=pcmdmessagefld->messagedatabuffer; 1918f1c579b1SScott Long 1919ad6d6297SScott Long user_len=pcmdmessagefld->cmdmessage.Length; 1920f1c579b1SScott Long /*check if data xfer length of this request will overflow my array qbuffer */ 1921ad6d6297SScott Long wqbuf_lastindex=acb->wqbuf_lastindex; 1922ad6d6297SScott Long wqbuf_firstindex=acb->wqbuf_firstindex; 1923ad6d6297SScott Long if(wqbuf_lastindex!=wqbuf_firstindex) { 192444f05562SScott Long arcmsr_post_ioctldata2iop(acb); 1925ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; 1926ad6d6297SScott Long } else { 1927f1c579b1SScott Long my_empty_len=(wqbuf_firstindex-wqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1); 1928ad6d6297SScott Long if(my_empty_len>=user_len) { 1929ad6d6297SScott Long while(user_len>0) { 1930f1c579b1SScott Long /*copy srb data to wqbuffer*/ 1931ad6d6297SScott Long pQbuffer= &acb->wqbuffer[acb->wqbuf_lastindex]; 1932f1c579b1SScott Long memcpy(pQbuffer, ptmpuserbuffer, 1); 1933ad6d6297SScott Long acb->wqbuf_lastindex++; 1934ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 1935ad6d6297SScott Long /*if last index number set it to 0 */ 1936f1c579b1SScott Long ptmpuserbuffer++; 1937f1c579b1SScott Long user_len--; 1938f1c579b1SScott Long } 1939f1c579b1SScott Long /*post fist Qbuffer*/ 1940ad6d6297SScott Long if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 1941ad6d6297SScott Long acb->acb_flags &=~ACB_F_MESSAGE_WQBUFFER_CLEARED; 194244f05562SScott Long arcmsr_post_ioctldata2iop(acb); 1943f1c579b1SScott Long } 1944ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1945ad6d6297SScott Long } else { 1946ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; 1947f1c579b1SScott Long } 1948f1c579b1SScott Long } 1949ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1950f1c579b1SScott Long } 1951f1c579b1SScott Long break; 1952ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 1953ad6d6297SScott Long u_int8_t * pQbuffer=acb->rqbuffer; 1954ad6d6297SScott Long 1955ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1956ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 195744f05562SScott Long arcmsr_iop_message_read(acb); 195844f05562SScott Long /*signature, let IOP know data has been readed */ 1959f1c579b1SScott Long } 1960ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 1961ad6d6297SScott Long acb->rqbuf_firstindex=0; 1962ad6d6297SScott Long acb->rqbuf_lastindex=0; 1963f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 1964ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1965ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1966f1c579b1SScott Long } 1967f1c579b1SScott Long break; 1968ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: 1969f1c579b1SScott Long { 1970ad6d6297SScott Long u_int8_t * pQbuffer=acb->wqbuffer; 1971f1c579b1SScott Long 1972ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1973ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 197444f05562SScott Long arcmsr_iop_message_read(acb); 197544f05562SScott Long /*signature, let IOP know data has been readed */ 1976f1c579b1SScott Long } 197744f05562SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ); 1978ad6d6297SScott Long acb->wqbuf_firstindex=0; 1979ad6d6297SScott Long acb->wqbuf_lastindex=0; 1980f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 1981ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1982ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1983f1c579b1SScott Long } 1984f1c579b1SScott Long break; 1985ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 1986ad6d6297SScott Long u_int8_t * pQbuffer; 1987f1c579b1SScott Long 1988ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1989ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 199044f05562SScott Long arcmsr_iop_message_read(acb); 199144f05562SScott Long /*signature, let IOP know data has been readed */ 1992f1c579b1SScott Long } 1993ad6d6297SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED 1994ad6d6297SScott Long |ACB_F_MESSAGE_RQBUFFER_CLEARED 199544f05562SScott Long |ACB_F_MESSAGE_WQBUFFER_READ); 1996ad6d6297SScott Long acb->rqbuf_firstindex=0; 1997ad6d6297SScott Long acb->rqbuf_lastindex=0; 1998ad6d6297SScott Long acb->wqbuf_firstindex=0; 1999ad6d6297SScott Long acb->wqbuf_lastindex=0; 2000ad6d6297SScott Long pQbuffer=acb->rqbuffer; 2001ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 2002ad6d6297SScott Long pQbuffer=acb->wqbuffer; 2003ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 2004ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 2005ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 2006f1c579b1SScott Long } 2007f1c579b1SScott Long break; 2008ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 2009ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_3F; 2010ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 2011f1c579b1SScott Long } 2012f1c579b1SScott Long break; 2013ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 2014ad6d6297SScott Long u_int8_t * hello_string="Hello! I am ARCMSR"; 2015ad6d6297SScott Long u_int8_t * puserbuffer=(u_int8_t *)pcmdmessagefld->messagedatabuffer; 2016f1c579b1SScott Long 2017ad6d6297SScott Long if(memcpy(puserbuffer, hello_string, (int16_t)strlen(hello_string))) { 2018ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; 2019ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2020f1c579b1SScott Long return ENOIOCTL; 2021f1c579b1SScott Long } 2022ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 2023ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 2024ad6d6297SScott Long } 2025ad6d6297SScott Long break; 2026ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: { 2027ad6d6297SScott Long arcmsr_iop_parking(acb); 2028ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 2029ad6d6297SScott Long } 2030ad6d6297SScott Long break; 2031ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: { 2032ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2033ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 2034f1c579b1SScott Long } 2035f1c579b1SScott Long break; 2036f1c579b1SScott Long } 2037ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2038dac36688SXin LI return (retvalue); 2039f1c579b1SScott Long } 2040f1c579b1SScott Long /* 2041f1c579b1SScott Long ************************************************************************** 2042f1c579b1SScott Long ************************************************************************** 2043f1c579b1SScott Long */ 204422f2616bSXin LI static void arcmsr_free_srb(struct CommandControlBlock *srb) 204522f2616bSXin LI { 204622f2616bSXin LI struct AdapterControlBlock *acb; 204722f2616bSXin LI int mutex; 204822f2616bSXin LI 204922f2616bSXin LI acb = srb->acb; 205022f2616bSXin LI mutex = mtx_owned(&acb->qbuffer_lock); 205122f2616bSXin LI if( mutex == 0 ) 205222f2616bSXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 205322f2616bSXin LI srb->srb_state=ARCMSR_SRB_DONE; 205422f2616bSXin LI srb->srb_flags=0; 205522f2616bSXin LI acb->srbworkingQ[acb->workingsrb_doneindex]=srb; 205622f2616bSXin LI acb->workingsrb_doneindex++; 205722f2616bSXin LI acb->workingsrb_doneindex %= ARCMSR_MAX_FREESRB_NUM; 205822f2616bSXin LI if( mutex == 0 ) 205922f2616bSXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 206022f2616bSXin LI } 206122f2616bSXin LI /* 206222f2616bSXin LI ************************************************************************** 206322f2616bSXin LI ************************************************************************** 206422f2616bSXin LI */ 2065ad6d6297SScott Long struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb) 2066f1c579b1SScott Long { 2067ad6d6297SScott Long struct CommandControlBlock *srb=NULL; 2068ad6d6297SScott Long u_int32_t workingsrb_startindex, workingsrb_doneindex; 20694e32649fSXin LI int mutex; 2070f1c579b1SScott Long 20714e32649fSXin LI mutex = mtx_owned(&acb->qbuffer_lock); 20724e32649fSXin LI if( mutex == 0 ) 2073579ec1a5SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2074ad6d6297SScott Long workingsrb_doneindex=acb->workingsrb_doneindex; 2075ad6d6297SScott Long workingsrb_startindex=acb->workingsrb_startindex; 2076ad6d6297SScott Long srb=acb->srbworkingQ[workingsrb_startindex]; 2077ad6d6297SScott Long workingsrb_startindex++; 2078ad6d6297SScott Long workingsrb_startindex %= ARCMSR_MAX_FREESRB_NUM; 2079ad6d6297SScott Long if(workingsrb_doneindex!=workingsrb_startindex) { 2080ad6d6297SScott Long acb->workingsrb_startindex=workingsrb_startindex; 2081ad6d6297SScott Long } else { 2082ad6d6297SScott Long srb=NULL; 2083ad6d6297SScott Long } 20844e32649fSXin LI if( mutex == 0 ) 2085579ec1a5SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2086ad6d6297SScott Long return(srb); 2087ad6d6297SScott Long } 2088ad6d6297SScott Long /* 2089ad6d6297SScott Long ************************************************************************** 2090ad6d6297SScott Long ************************************************************************** 2091ad6d6297SScott Long */ 2092ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb) 2093ad6d6297SScott Long { 2094ad6d6297SScott Long struct CMD_MESSAGE_FIELD * pcmdmessagefld; 2095ad6d6297SScott Long int retvalue = 0, transfer_len = 0; 2096ad6d6297SScott Long char *buffer; 209744f05562SScott Long u_int32_t controlcode = (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[5] << 24 | 209844f05562SScott Long (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[6] << 16 | 209944f05562SScott Long (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[7] << 8 | 210044f05562SScott Long (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[8]; 2101ad6d6297SScott Long /* 4 bytes: Areca io control code */ 2102ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) { 2103ad6d6297SScott Long buffer = pccb->csio.data_ptr; 2104ad6d6297SScott Long transfer_len = pccb->csio.dxfer_len; 2105ad6d6297SScott Long } else { 2106ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2107ad6d6297SScott Long goto message_out; 2108ad6d6297SScott Long } 2109ad6d6297SScott Long if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) { 2110ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2111ad6d6297SScott Long goto message_out; 2112ad6d6297SScott Long } 2113ad6d6297SScott Long pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer; 2114ad6d6297SScott Long switch(controlcode) { 2115ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 2116ad6d6297SScott Long u_int8_t *pQbuffer; 2117ad6d6297SScott Long u_int8_t *ptmpQbuffer=pcmdmessagefld->messagedatabuffer; 2118ad6d6297SScott Long int32_t allxfer_len = 0; 2119f1c579b1SScott Long 2120ad6d6297SScott Long while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) 2121ad6d6297SScott Long && (allxfer_len < 1031)) { 2122ad6d6297SScott Long pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; 2123ad6d6297SScott Long memcpy(ptmpQbuffer, pQbuffer, 1); 2124ad6d6297SScott Long acb->rqbuf_firstindex++; 2125ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 2126ad6d6297SScott Long ptmpQbuffer++; 2127ad6d6297SScott Long allxfer_len++; 2128f1c579b1SScott Long } 2129ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 213044f05562SScott Long struct QBUFFER *prbuffer; 213144f05562SScott Long u_int8_t *iop_data; 2132ad6d6297SScott Long int32_t iop_len; 2133ad6d6297SScott Long 2134ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 213544f05562SScott Long prbuffer=arcmsr_get_iop_rqbuffer(acb); 213644f05562SScott Long iop_data = (u_int8_t *)prbuffer->data; 2137ad6d6297SScott Long iop_len =(u_int32_t)prbuffer->data_len; 2138ad6d6297SScott Long while (iop_len > 0) { 2139ad6d6297SScott Long pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex]; 2140ad6d6297SScott Long memcpy(pQbuffer, iop_data, 1); 2141ad6d6297SScott Long acb->rqbuf_lastindex++; 2142ad6d6297SScott Long acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 2143ad6d6297SScott Long iop_data++; 2144ad6d6297SScott Long iop_len--; 2145f1c579b1SScott Long } 214644f05562SScott Long arcmsr_iop_message_read(acb); 2147ad6d6297SScott Long } 2148ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length = allxfer_len; 2149ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2150ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 2151ad6d6297SScott Long } 2152ad6d6297SScott Long break; 2153ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 2154ad6d6297SScott Long int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 2155ad6d6297SScott Long u_int8_t *pQbuffer; 2156ad6d6297SScott Long u_int8_t *ptmpuserbuffer=pcmdmessagefld->messagedatabuffer; 2157ad6d6297SScott Long 2158ad6d6297SScott Long user_len = pcmdmessagefld->cmdmessage.Length; 2159ad6d6297SScott Long wqbuf_lastindex = acb->wqbuf_lastindex; 2160ad6d6297SScott Long wqbuf_firstindex = acb->wqbuf_firstindex; 2161ad6d6297SScott Long if (wqbuf_lastindex != wqbuf_firstindex) { 216244f05562SScott Long arcmsr_post_ioctldata2iop(acb); 2163ad6d6297SScott Long /* has error report sensedata */ 2164dac36688SXin LI if(pccb->csio.sense_len) { 2165ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 2166ad6d6297SScott Long /* Valid,ErrorCode */ 2167ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 2168ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 2169ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 2170ad6d6297SScott Long /* AdditionalSenseLength */ 2171ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 2172ad6d6297SScott Long /* AdditionalSenseCode */ 2173ad6d6297SScott Long } 2174ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2175ad6d6297SScott Long } else { 2176ad6d6297SScott Long my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) 2177ad6d6297SScott Long &(ARCMSR_MAX_QBUFFER - 1); 2178ad6d6297SScott Long if (my_empty_len >= user_len) { 2179ad6d6297SScott Long while (user_len > 0) { 2180ad6d6297SScott Long pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; 2181ad6d6297SScott Long memcpy(pQbuffer, ptmpuserbuffer, 1); 2182ad6d6297SScott Long acb->wqbuf_lastindex++; 2183ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 2184ad6d6297SScott Long ptmpuserbuffer++; 2185ad6d6297SScott Long user_len--; 2186ad6d6297SScott Long } 2187ad6d6297SScott Long if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 2188ad6d6297SScott Long acb->acb_flags &= 2189ad6d6297SScott Long ~ACB_F_MESSAGE_WQBUFFER_CLEARED; 219044f05562SScott Long arcmsr_post_ioctldata2iop(acb); 2191ad6d6297SScott Long } 2192ad6d6297SScott Long } else { 2193ad6d6297SScott Long /* has error report sensedata */ 2194dac36688SXin LI if(pccb->csio.sense_len) { 2195ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 2196ad6d6297SScott Long /* Valid,ErrorCode */ 2197ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 2198ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 2199ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 2200ad6d6297SScott Long /* AdditionalSenseLength */ 2201ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 2202ad6d6297SScott Long /* AdditionalSenseCode */ 2203ad6d6297SScott Long } 2204ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2205ad6d6297SScott Long } 2206ad6d6297SScott Long } 2207ad6d6297SScott Long } 2208ad6d6297SScott Long break; 2209ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 2210ad6d6297SScott Long u_int8_t *pQbuffer = acb->rqbuffer; 2211ad6d6297SScott Long 2212ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2213ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 221444f05562SScott Long arcmsr_iop_message_read(acb); 2215ad6d6297SScott Long } 2216ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 2217ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2218ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2219ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2220ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 2221ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 2222ad6d6297SScott Long } 2223ad6d6297SScott Long break; 2224ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { 2225ad6d6297SScott Long u_int8_t *pQbuffer = acb->wqbuffer; 2226ad6d6297SScott Long 2227ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2228ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 222944f05562SScott Long arcmsr_iop_message_read(acb); 2230ad6d6297SScott Long } 2231ad6d6297SScott Long acb->acb_flags |= 2232ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED | 223344f05562SScott Long ACB_F_MESSAGE_WQBUFFER_READ); 2234ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2235ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2236ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2237ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 2238ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 2239ad6d6297SScott Long } 2240ad6d6297SScott Long break; 2241ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 2242ad6d6297SScott Long u_int8_t *pQbuffer; 2243ad6d6297SScott Long 2244ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2245ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 224644f05562SScott Long arcmsr_iop_message_read(acb); 2247ad6d6297SScott Long } 2248ad6d6297SScott Long acb->acb_flags |= 2249ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED 2250ad6d6297SScott Long | ACB_F_MESSAGE_RQBUFFER_CLEARED 225144f05562SScott Long | ACB_F_MESSAGE_WQBUFFER_READ); 2252ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2253ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2254ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2255ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2256ad6d6297SScott Long pQbuffer = acb->rqbuffer; 2257ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 2258ad6d6297SScott Long pQbuffer = acb->wqbuffer; 2259ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 2260ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2261ad6d6297SScott Long } 2262ad6d6297SScott Long break; 2263ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 2264ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; 2265ad6d6297SScott Long } 2266ad6d6297SScott Long break; 2267ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 2268ad6d6297SScott Long int8_t * hello_string = "Hello! I am ARCMSR"; 2269ad6d6297SScott Long 2270ad6d6297SScott Long memcpy(pcmdmessagefld->messagedatabuffer, hello_string 2271ad6d6297SScott Long , (int16_t)strlen(hello_string)); 2272ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2273ad6d6297SScott Long } 2274ad6d6297SScott Long break; 2275ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: 2276ad6d6297SScott Long arcmsr_iop_parking(acb); 2277ad6d6297SScott Long break; 2278ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: 2279ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2280ad6d6297SScott Long break; 2281ad6d6297SScott Long default: 2282ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2283ad6d6297SScott Long } 2284ad6d6297SScott Long message_out: 2285dac36688SXin LI return (retvalue); 2286f1c579b1SScott Long } 2287f1c579b1SScott Long /* 2288f1c579b1SScott Long ********************************************************************* 2289f1c579b1SScott Long ********************************************************************* 2290f1c579b1SScott Long */ 2291231c8b71SXin LI static void arcmsr_execute_srb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 2292f1c579b1SScott Long { 2293ad6d6297SScott Long struct CommandControlBlock *srb=(struct CommandControlBlock *)arg; 2294ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)srb->acb; 2295f1c579b1SScott Long union ccb * pccb; 2296ad6d6297SScott Long int target, lun; 2297f1c579b1SScott Long 2298ad6d6297SScott Long pccb=srb->pccb; 2299ad6d6297SScott Long target=pccb->ccb_h.target_id; 2300ad6d6297SScott Long lun=pccb->ccb_h.target_lun; 230122f2616bSXin LI #ifdef ARCMSR_DEBUG1 230222f2616bSXin LI acb->pktRequestCount++; 230322f2616bSXin LI #endif 2304ad6d6297SScott Long if(error != 0) { 2305ad6d6297SScott Long if(error != EFBIG) { 230644f05562SScott Long printf("arcmsr%d: unexpected error %x" 230744f05562SScott Long " returned from 'bus_dmamap_load' \n" 2308ad6d6297SScott Long , acb->pci_unit, error); 2309f1c579b1SScott Long } 2310ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { 231115735becSScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 2312f1c579b1SScott Long } 2313ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2314f1c579b1SScott Long return; 2315f1c579b1SScott Long } 2316ad6d6297SScott Long if(nseg > ARCMSR_MAX_SG_ENTRIES) { 2317ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 2318ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2319ad6d6297SScott Long return; 2320f1c579b1SScott Long } 2321ad6d6297SScott Long if(acb->acb_flags & ACB_F_BUS_RESET) { 2322ad6d6297SScott Long printf("arcmsr%d: bus reset and return busy \n", acb->pci_unit); 2323ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_BUS_RESET; 2324ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2325ad6d6297SScott Long return; 2326ad6d6297SScott Long } 2327ad6d6297SScott Long if(acb->devstate[target][lun]==ARECA_RAID_GONE) { 232822f2616bSXin LI u_int8_t block_cmd, cmd; 2329ad6d6297SScott Long 233022f2616bSXin LI cmd = pccb->csio.cdb_io.cdb_bytes[0]; 233122f2616bSXin LI block_cmd= cmd & 0x0f; 2332ad6d6297SScott Long if(block_cmd==0x08 || block_cmd==0x0a) { 2333ad6d6297SScott Long printf("arcmsr%d:block 'read/write' command " 233422f2616bSXin LI "with gone raid volume Cmd=0x%2x, TargetId=%d, Lun=%d \n" 233522f2616bSXin LI , acb->pci_unit, cmd, target, lun); 2336ad6d6297SScott Long pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 2337ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2338ad6d6297SScott Long return; 2339ad6d6297SScott Long } 2340ad6d6297SScott Long } 2341ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { 2342ad6d6297SScott Long if(nseg != 0) { 2343ad6d6297SScott Long bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 2344ad6d6297SScott Long } 2345ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2346f1c579b1SScott Long return; 2347f1c579b1SScott Long } 2348dac36688SXin LI if(acb->srboutstandingcount > ARCMSR_MAX_OUTSTANDING_CMD) { 234915735becSScott Long xpt_freeze_simq(acb->psim, 1); 235015735becSScott Long pccb->ccb_h.status = CAM_REQUEUE_REQ; 2351dc3a205bSScott Long acb->acb_flags |= ACB_F_CAM_DEV_QFRZN; 2352ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2353ad6d6297SScott Long return; 2354f1c579b1SScott Long } 235515735becSScott Long pccb->ccb_h.status |= CAM_SIM_QUEUED; 2356ad6d6297SScott Long arcmsr_build_srb(srb, dm_segs, nseg); 2357ad6d6297SScott Long arcmsr_post_srb(acb, srb); 235822f2616bSXin LI if (pccb->ccb_h.timeout != CAM_TIME_INFINITY) 235922f2616bSXin LI { 236022f2616bSXin LI arcmsr_callout_init(&srb->ccb_callout); 2361dac36688SXin LI callout_reset(&srb->ccb_callout, ((pccb->ccb_h.timeout + (ARCMSR_TIMEOUT_DELAY * 1000)) * hz) / 1000, arcmsr_srb_timeout, srb); 236222f2616bSXin LI srb->srb_flags |= SRB_FLAG_TIMER_START; 236322f2616bSXin LI } 2364f1c579b1SScott Long } 2365f1c579b1SScott Long /* 2366f1c579b1SScott Long ***************************************************************************************** 2367f1c579b1SScott Long ***************************************************************************************** 2368f1c579b1SScott Long */ 2369ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb) 2370f1c579b1SScott Long { 2371ad6d6297SScott Long struct CommandControlBlock *srb; 2372ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *) abortccb->ccb_h.arcmsr_ccbacb_ptr; 237344f05562SScott Long u_int32_t intmask_org; 2374ad6d6297SScott Long int i=0; 2375f1c579b1SScott Long 2376ad6d6297SScott Long acb->num_aborts++; 2377f1c579b1SScott Long /* 2378ad6d6297SScott Long *************************************************************************** 2379f1c579b1SScott Long ** It is the upper layer do abort command this lock just prior to calling us. 2380f1c579b1SScott Long ** First determine if we currently own this command. 2381f1c579b1SScott Long ** Start by searching the device queue. If not found 2382f1c579b1SScott Long ** at all, and the system wanted us to just abort the 2383f1c579b1SScott Long ** command return success. 2384ad6d6297SScott Long *************************************************************************** 2385f1c579b1SScott Long */ 2386ad6d6297SScott Long if(acb->srboutstandingcount!=0) { 238722f2616bSXin LI /* disable all outbound interrupt */ 238822f2616bSXin LI intmask_org=arcmsr_disable_allintr(acb); 2389ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 2390ad6d6297SScott Long srb=acb->psrb_pool[i]; 239122f2616bSXin LI if(srb->srb_state==ARCMSR_SRB_START) { 2392ad6d6297SScott Long if(srb->pccb==abortccb) { 239322f2616bSXin LI srb->srb_state=ARCMSR_SRB_ABORTED; 2394ad6d6297SScott Long printf("arcmsr%d:scsi id=%d lun=%d abort srb '%p'" 2395ad6d6297SScott Long "outstanding command \n" 2396ad6d6297SScott Long , acb->pci_unit, abortccb->ccb_h.target_id 2397ad6d6297SScott Long , abortccb->ccb_h.target_lun, srb); 2398ad6d6297SScott Long arcmsr_polling_srbdone(acb, srb); 239944f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 240044f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 2401ad6d6297SScott Long return (TRUE); 2402f1c579b1SScott Long } 240322f2616bSXin LI } 240422f2616bSXin LI } 240522f2616bSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 240622f2616bSXin LI arcmsr_enable_allintr(acb, intmask_org); 240722f2616bSXin LI } 240822f2616bSXin LI return(FALSE); 240922f2616bSXin LI } 2410f1c579b1SScott Long /* 2411f1c579b1SScott Long **************************************************************************** 2412f1c579b1SScott Long **************************************************************************** 2413f1c579b1SScott Long */ 2414ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb) 2415f1c579b1SScott Long { 2416ad6d6297SScott Long int retry=0; 2417f1c579b1SScott Long 2418ad6d6297SScott Long acb->num_resets++; 2419ad6d6297SScott Long acb->acb_flags |=ACB_F_BUS_RESET; 2420ad6d6297SScott Long while(acb->srboutstandingcount!=0 && retry < 400) { 242144f05562SScott Long arcmsr_interrupt(acb); 2422ad6d6297SScott Long UDELAY(25000); 2423ad6d6297SScott Long retry++; 2424ad6d6297SScott Long } 2425ad6d6297SScott Long arcmsr_iop_reset(acb); 2426ad6d6297SScott Long acb->acb_flags &= ~ACB_F_BUS_RESET; 2427f1c579b1SScott Long } 2428f1c579b1SScott Long /* 2429ad6d6297SScott Long ************************************************************************** 2430ad6d6297SScott Long ************************************************************************** 2431ad6d6297SScott Long */ 2432ad6d6297SScott Long static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, 2433ad6d6297SScott Long union ccb * pccb) 2434ad6d6297SScott Long { 2435ad6d6297SScott Long switch (pccb->csio.cdb_io.cdb_bytes[0]) { 2436ad6d6297SScott Long case INQUIRY: { 2437ad6d6297SScott Long unsigned char inqdata[36]; 2438c2ede4b3SMartin Blapp char *buffer=pccb->csio.data_ptr; 2439ad6d6297SScott Long 2440ad6d6297SScott Long if (pccb->ccb_h.target_lun) { 2441*61ba2ac6SJim Harris pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 2442ad6d6297SScott Long xpt_done(pccb); 2443ad6d6297SScott Long return; 2444ad6d6297SScott Long } 2445231c8b71SXin LI inqdata[0] = T_PROCESSOR; /* Periph Qualifier & Periph Dev Type */ 2446231c8b71SXin LI inqdata[1] = 0; /* rem media bit & Dev Type Modifier */ 2447231c8b71SXin LI inqdata[2] = 0; /* ISO, ECMA, & ANSI versions */ 2448231c8b71SXin LI inqdata[3] = 0; 2449231c8b71SXin LI inqdata[4] = 31; /* length of additional data */ 2450231c8b71SXin LI inqdata[5] = 0; 2451231c8b71SXin LI inqdata[6] = 0; 2452231c8b71SXin LI inqdata[7] = 0; 2453231c8b71SXin LI strncpy(&inqdata[8], "Areca ", 8); /* Vendor Identification */ 2454231c8b71SXin LI strncpy(&inqdata[16], "RAID controller ", 16); /* Product Identification */ 2455ad6d6297SScott Long strncpy(&inqdata[32], "R001", 4); /* Product Revision */ 2456ad6d6297SScott Long memcpy(buffer, inqdata, sizeof(inqdata)); 2457*61ba2ac6SJim Harris pccb->ccb_h.status |= CAM_REQ_CMP; 2458ad6d6297SScott Long xpt_done(pccb); 2459ad6d6297SScott Long } 2460ad6d6297SScott Long break; 2461ad6d6297SScott Long case WRITE_BUFFER: 2462ad6d6297SScott Long case READ_BUFFER: { 2463ad6d6297SScott Long if (arcmsr_iop_message_xfer(acb, pccb)) { 2464ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 2465ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 2466ad6d6297SScott Long } 2467*61ba2ac6SJim Harris pccb->ccb_h.status |= CAM_REQ_CMP; 2468ad6d6297SScott Long xpt_done(pccb); 2469ad6d6297SScott Long } 2470ad6d6297SScott Long break; 2471ad6d6297SScott Long default: 2472*61ba2ac6SJim Harris pccb->ccb_h.status |= CAM_REQ_CMP; 2473ad6d6297SScott Long xpt_done(pccb); 2474ad6d6297SScott Long } 2475ad6d6297SScott Long } 2476ad6d6297SScott Long /* 2477f1c579b1SScott Long ********************************************************************* 2478f1c579b1SScott Long ********************************************************************* 2479f1c579b1SScott Long */ 2480ad6d6297SScott Long static void arcmsr_action(struct cam_sim * psim, union ccb * pccb) 2481f1c579b1SScott Long { 2482ad6d6297SScott Long struct AdapterControlBlock * acb; 2483f1c579b1SScott Long 2484ad6d6297SScott Long acb=(struct AdapterControlBlock *) cam_sim_softc(psim); 2485ad6d6297SScott Long if(acb==NULL) { 2486ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2487f1c579b1SScott Long xpt_done(pccb); 2488f1c579b1SScott Long return; 2489f1c579b1SScott Long } 2490ad6d6297SScott Long switch (pccb->ccb_h.func_code) { 2491ad6d6297SScott Long case XPT_SCSI_IO: { 2492ad6d6297SScott Long struct CommandControlBlock *srb; 2493ad6d6297SScott Long int target=pccb->ccb_h.target_id; 2494f1c579b1SScott Long 2495ad6d6297SScott Long if(target == 16) { 2496ad6d6297SScott Long /* virtual device for iop message transfer */ 2497ad6d6297SScott Long arcmsr_handle_virtual_command(acb, pccb); 2498ad6d6297SScott Long return; 2499ad6d6297SScott Long } 2500ad6d6297SScott Long if((srb=arcmsr_get_freesrb(acb)) == NULL) { 2501ad6d6297SScott Long pccb->ccb_h.status |= CAM_RESRC_UNAVAIL; 2502f1c579b1SScott Long xpt_done(pccb); 2503f1c579b1SScott Long return; 2504f1c579b1SScott Long } 2505ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbsrb_ptr=srb; 2506ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbacb_ptr=acb; 2507ad6d6297SScott Long srb->pccb=pccb; 2508ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 2509ad6d6297SScott Long if(!(pccb->ccb_h.flags & CAM_SCATTER_VALID)) { 2510ad6d6297SScott Long /* Single buffer */ 2511ad6d6297SScott Long if(!(pccb->ccb_h.flags & CAM_DATA_PHYS)) { 2512ad6d6297SScott Long /* Buffer is virtual */ 2513ad6d6297SScott Long u_int32_t error, s; 2514f1c579b1SScott Long 2515f1c579b1SScott Long s=splsoftvm(); 2516ad6d6297SScott Long error = bus_dmamap_load(acb->dm_segs_dmat 2517ad6d6297SScott Long , srb->dm_segs_dmamap 2518ad6d6297SScott Long , pccb->csio.data_ptr 2519ad6d6297SScott Long , pccb->csio.dxfer_len 2520231c8b71SXin LI , arcmsr_execute_srb, srb, /*flags*/0); 2521ad6d6297SScott Long if(error == EINPROGRESS) { 2522ad6d6297SScott Long xpt_freeze_simq(acb->psim, 1); 2523f1c579b1SScott Long pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 2524f1c579b1SScott Long } 2525f1c579b1SScott Long splx(s); 2526231c8b71SXin LI } 2527231c8b71SXin LI else { /* Buffer is physical */ 2528add5afdcSXin LI #ifdef PAE 2529add5afdcSXin LI panic("arcmsr: CAM_DATA_PHYS not supported"); 2530add5afdcSXin LI #else 2531231c8b71SXin LI struct bus_dma_segment seg; 2532231c8b71SXin LI 2533231c8b71SXin LI seg.ds_addr = (bus_addr_t)pccb->csio.data_ptr; 2534231c8b71SXin LI seg.ds_len = pccb->csio.dxfer_len; 2535231c8b71SXin LI arcmsr_execute_srb(srb, &seg, 1, 0); 2536add5afdcSXin LI #endif 2537f1c579b1SScott Long } 2538ad6d6297SScott Long } else { 2539ad6d6297SScott Long /* Scatter/gather list */ 2540f1c579b1SScott Long struct bus_dma_segment *segs; 2541f1c579b1SScott Long 2542ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0 2543ad6d6297SScott Long || (pccb->ccb_h.flags & CAM_DATA_PHYS) != 0) { 2544ad6d6297SScott Long pccb->ccb_h.status |= CAM_PROVIDE_FAIL; 2545f1c579b1SScott Long xpt_done(pccb); 2546ad6d6297SScott Long free(srb, M_DEVBUF); 2547f1c579b1SScott Long return; 2548f1c579b1SScott Long } 2549f1c579b1SScott Long segs=(struct bus_dma_segment *)pccb->csio.data_ptr; 2550231c8b71SXin LI arcmsr_execute_srb(srb, segs, pccb->csio.sglist_cnt, 0); 2551f1c579b1SScott Long } 2552ad6d6297SScott Long } else { 2553231c8b71SXin LI arcmsr_execute_srb(srb, NULL, 0, 0); 2554f1c579b1SScott Long } 2555f1c579b1SScott Long break; 2556f1c579b1SScott Long } 2557ad6d6297SScott Long case XPT_TARGET_IO: { 2558ad6d6297SScott Long /* target mode not yet support vendor specific commands. */ 2559ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2560f1c579b1SScott Long xpt_done(pccb); 2561f1c579b1SScott Long break; 2562f1c579b1SScott Long } 2563ad6d6297SScott Long case XPT_PATH_INQ: { 2564f1c579b1SScott Long struct ccb_pathinq *cpi= &pccb->cpi; 2565f1c579b1SScott Long 2566f1c579b1SScott Long cpi->version_num=1; 2567f1c579b1SScott Long cpi->hba_inquiry=PI_SDTR_ABLE | PI_TAG_ABLE; 2568f1c579b1SScott Long cpi->target_sprt=0; 2569f1c579b1SScott Long cpi->hba_misc=0; 2570f1c579b1SScott Long cpi->hba_eng_cnt=0; 2571ad6d6297SScott Long cpi->max_target=ARCMSR_MAX_TARGETID; /* 0-16 */ 2572ad6d6297SScott Long cpi->max_lun=ARCMSR_MAX_TARGETLUN; /* 0-7 */ 2573ad6d6297SScott Long cpi->initiator_id=ARCMSR_SCSI_INITIATOR_ID; /* 255 */ 2574f1c579b1SScott Long cpi->bus_id=cam_sim_bus(psim); 2575f1c579b1SScott Long strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 2576f1c579b1SScott Long strncpy(cpi->hba_vid, "ARCMSR", HBA_IDLEN); 2577f1c579b1SScott Long strncpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN); 2578f1c579b1SScott Long cpi->unit_number=cam_sim_unit(psim); 257944f05562SScott Long #ifdef CAM_NEW_TRAN_CODE 2580dac36688SXin LI if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G) 2581dac36688SXin LI cpi->base_transfer_speed = 600000; 2582dac36688SXin LI else 2583dac36688SXin LI cpi->base_transfer_speed = 300000; 2584dac36688SXin LI if((acb->vendor_device_id == PCIDevVenIDARC1880) || 2585dac36688SXin LI (acb->vendor_device_id == PCIDevVenIDARC1680)) 2586dac36688SXin LI { 2587dac36688SXin LI cpi->transport = XPORT_SAS; 2588dac36688SXin LI cpi->transport_version = 0; 2589dac36688SXin LI cpi->protocol_version = SCSI_REV_SPC2; 2590dac36688SXin LI } 2591dac36688SXin LI else 2592dac36688SXin LI { 2593fa9ed865SMatt Jacob cpi->transport = XPORT_SPI; 2594fa9ed865SMatt Jacob cpi->transport_version = 2; 2595fa9ed865SMatt Jacob cpi->protocol_version = SCSI_REV_2; 2596dac36688SXin LI } 2597dac36688SXin LI cpi->protocol = PROTO_SCSI; 259844f05562SScott Long #endif 2599ad6d6297SScott Long cpi->ccb_h.status |= CAM_REQ_CMP; 2600f1c579b1SScott Long xpt_done(pccb); 2601f1c579b1SScott Long break; 2602f1c579b1SScott Long } 2603ad6d6297SScott Long case XPT_ABORT: { 2604f1c579b1SScott Long union ccb *pabort_ccb; 2605f1c579b1SScott Long 2606f1c579b1SScott Long pabort_ccb=pccb->cab.abort_ccb; 2607ad6d6297SScott Long switch (pabort_ccb->ccb_h.func_code) { 2608f1c579b1SScott Long case XPT_ACCEPT_TARGET_IO: 2609f1c579b1SScott Long case XPT_IMMED_NOTIFY: 2610f1c579b1SScott Long case XPT_CONT_TARGET_IO: 2611ad6d6297SScott Long if(arcmsr_seek_cmd2abort(pabort_ccb)==TRUE) { 2612ad6d6297SScott Long pabort_ccb->ccb_h.status |= CAM_REQ_ABORTED; 2613f1c579b1SScott Long xpt_done(pabort_ccb); 2614ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2615ad6d6297SScott Long } else { 2616f1c579b1SScott Long xpt_print_path(pabort_ccb->ccb_h.path); 2617f1c579b1SScott Long printf("Not found\n"); 2618ad6d6297SScott Long pccb->ccb_h.status |= CAM_PATH_INVALID; 2619f1c579b1SScott Long } 2620f1c579b1SScott Long break; 2621f1c579b1SScott Long case XPT_SCSI_IO: 2622ad6d6297SScott Long pccb->ccb_h.status |= CAM_UA_ABORT; 2623f1c579b1SScott Long break; 2624f1c579b1SScott Long default: 2625ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2626f1c579b1SScott Long break; 2627f1c579b1SScott Long } 2628f1c579b1SScott Long xpt_done(pccb); 2629f1c579b1SScott Long break; 2630f1c579b1SScott Long } 2631f1c579b1SScott Long case XPT_RESET_BUS: 2632ad6d6297SScott Long case XPT_RESET_DEV: { 2633ad6d6297SScott Long u_int32_t i; 2634f1c579b1SScott Long 2635ad6d6297SScott Long arcmsr_bus_reset(acb); 2636ad6d6297SScott Long for (i=0; i < 500; i++) { 2637f1c579b1SScott Long DELAY(1000); 2638f1c579b1SScott Long } 2639ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2640f1c579b1SScott Long xpt_done(pccb); 2641f1c579b1SScott Long break; 2642f1c579b1SScott Long } 2643ad6d6297SScott Long case XPT_TERM_IO: { 2644ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2645f1c579b1SScott Long xpt_done(pccb); 2646f1c579b1SScott Long break; 2647f1c579b1SScott Long } 2648ad6d6297SScott Long case XPT_GET_TRAN_SETTINGS: { 2649ad6d6297SScott Long struct ccb_trans_settings *cts; 2650ad6d6297SScott Long 2651ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 2652ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 2653ad6d6297SScott Long xpt_done(pccb); 2654ad6d6297SScott Long break; 2655ad6d6297SScott Long } 2656ad6d6297SScott Long cts= &pccb->cts; 265744f05562SScott Long #ifdef CAM_NEW_TRAN_CODE 265844f05562SScott Long { 265944f05562SScott Long struct ccb_trans_settings_scsi *scsi; 266044f05562SScott Long struct ccb_trans_settings_spi *spi; 2661dac36688SXin LI struct ccb_trans_settings_sas *sas; 266244f05562SScott Long 2663ad6d6297SScott Long scsi = &cts->proto_specific.scsi; 2664dac36688SXin LI scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 2665dac36688SXin LI scsi->valid = CTS_SCSI_VALID_TQ; 2666fa9ed865SMatt Jacob cts->protocol = PROTO_SCSI; 2667dac36688SXin LI 2668dac36688SXin LI if((acb->vendor_device_id == PCIDevVenIDARC1880) || 2669dac36688SXin LI (acb->vendor_device_id == PCIDevVenIDARC1680)) 2670dac36688SXin LI { 2671dac36688SXin LI cts->protocol_version = SCSI_REV_SPC2; 2672dac36688SXin LI cts->transport_version = 0; 2673dac36688SXin LI cts->transport = XPORT_SAS; 2674dac36688SXin LI sas = &cts->xport_specific.sas; 2675dac36688SXin LI sas->valid = CTS_SAS_VALID_SPEED; 2676dac36688SXin LI if(acb->vendor_device_id == PCIDevVenIDARC1880) 2677dac36688SXin LI sas->bitrate = 600000; 2678dac36688SXin LI else if(acb->vendor_device_id == PCIDevVenIDARC1680) 2679dac36688SXin LI sas->bitrate = 300000; 2680dac36688SXin LI } 2681dac36688SXin LI else 2682dac36688SXin LI { 2683fa9ed865SMatt Jacob cts->protocol_version = SCSI_REV_2; 2684fa9ed865SMatt Jacob cts->transport_version = 2; 2685dac36688SXin LI cts->transport = XPORT_SPI; 2686dac36688SXin LI spi = &cts->xport_specific.spi; 2687fa9ed865SMatt Jacob spi->flags = CTS_SPI_FLAGS_DISC_ENB; 2688dac36688SXin LI spi->sync_period=2; 2689fa9ed865SMatt Jacob spi->sync_offset=32; 2690fa9ed865SMatt Jacob spi->bus_width=MSG_EXT_WDTR_BUS_16_BIT; 26919d98ff4dSScott Long spi->valid = CTS_SPI_VALID_DISC 26929d98ff4dSScott Long | CTS_SPI_VALID_SYNC_RATE 2693fa9ed865SMatt Jacob | CTS_SPI_VALID_SYNC_OFFSET 2694fa9ed865SMatt Jacob | CTS_SPI_VALID_BUS_WIDTH; 2695dac36688SXin LI } 269644f05562SScott Long } 269744f05562SScott Long #else 269844f05562SScott Long { 269944f05562SScott Long cts->flags=(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB); 2700dac36688SXin LI cts->sync_period=2; 270144f05562SScott Long cts->sync_offset=32; 270244f05562SScott Long cts->bus_width=MSG_EXT_WDTR_BUS_16_BIT; 270344f05562SScott Long cts->valid=CCB_TRANS_SYNC_RATE_VALID | 270444f05562SScott Long CCB_TRANS_SYNC_OFFSET_VALID | 270544f05562SScott Long CCB_TRANS_BUS_WIDTH_VALID | 270644f05562SScott Long CCB_TRANS_DISC_VALID | 270744f05562SScott Long CCB_TRANS_TQ_VALID; 270844f05562SScott Long } 270944f05562SScott Long #endif 2710ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2711ad6d6297SScott Long xpt_done(pccb); 2712ad6d6297SScott Long break; 2713ad6d6297SScott Long } 2714ad6d6297SScott Long case XPT_SET_TRAN_SETTINGS: { 2715ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 2716ad6d6297SScott Long xpt_done(pccb); 2717ad6d6297SScott Long break; 2718ad6d6297SScott Long } 2719f3b080e6SMarius Strobl case XPT_CALC_GEOMETRY: 2720ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 2721ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 2722ad6d6297SScott Long xpt_done(pccb); 2723ad6d6297SScott Long break; 2724ad6d6297SScott Long } 2725f3b080e6SMarius Strobl #if __FreeBSD_version >= 500000 2726f3b080e6SMarius Strobl cam_calc_geometry(&pccb->ccg, 1); 2727f3b080e6SMarius Strobl #else 2728f3b080e6SMarius Strobl { 2729f3b080e6SMarius Strobl struct ccb_calc_geometry *ccg; 2730f3b080e6SMarius Strobl u_int32_t size_mb; 2731f3b080e6SMarius Strobl u_int32_t secs_per_cylinder; 2732f3b080e6SMarius Strobl 2733f1c579b1SScott Long ccg= &pccb->ccg; 2734ad6d6297SScott Long if (ccg->block_size == 0) { 2735ad6d6297SScott Long pccb->ccb_h.status = CAM_REQ_INVALID; 2736ad6d6297SScott Long xpt_done(pccb); 2737ad6d6297SScott Long break; 2738ad6d6297SScott Long } 2739ad6d6297SScott Long if(((1024L * 1024L)/ccg->block_size) < 0) { 2740ad6d6297SScott Long pccb->ccb_h.status = CAM_REQ_INVALID; 2741ad6d6297SScott Long xpt_done(pccb); 2742ad6d6297SScott Long break; 2743ad6d6297SScott Long } 2744f1c579b1SScott Long size_mb=ccg->volume_size/((1024L * 1024L)/ccg->block_size); 2745ad6d6297SScott Long if(size_mb > 1024 ) { 2746f1c579b1SScott Long ccg->heads=255; 2747f1c579b1SScott Long ccg->secs_per_track=63; 2748ad6d6297SScott Long } else { 2749f1c579b1SScott Long ccg->heads=64; 2750f1c579b1SScott Long ccg->secs_per_track=32; 2751f1c579b1SScott Long } 2752f1c579b1SScott Long secs_per_cylinder=ccg->heads * ccg->secs_per_track; 2753f1c579b1SScott Long ccg->cylinders=ccg->volume_size / secs_per_cylinder; 2754ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2755f3b080e6SMarius Strobl } 2756f3b080e6SMarius Strobl #endif 2757f1c579b1SScott Long xpt_done(pccb); 2758f1c579b1SScott Long break; 2759f1c579b1SScott Long default: 2760ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2761f1c579b1SScott Long xpt_done(pccb); 2762f1c579b1SScott Long break; 2763f1c579b1SScott Long } 2764f1c579b1SScott Long } 2765f1c579b1SScott Long /* 2766f1c579b1SScott Long ********************************************************************** 2767f1c579b1SScott Long ********************************************************************** 2768f1c579b1SScott Long */ 276944f05562SScott Long static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) 2770f1c579b1SScott Long { 2771ad6d6297SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 277244f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 277344f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 2774ad6d6297SScott Long printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 2775ad6d6297SScott Long } 2776f1c579b1SScott Long } 2777f1c579b1SScott Long /* 2778f1c579b1SScott Long ********************************************************************** 2779f1c579b1SScott Long ********************************************************************** 2780f1c579b1SScott Long */ 278144f05562SScott Long static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb) 278244f05562SScott Long { 278344f05562SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 2784d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_START_BGRB); 278544f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 278644f05562SScott Long printf( "arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 278744f05562SScott Long } 278844f05562SScott Long } 278944f05562SScott Long /* 279044f05562SScott Long ********************************************************************** 279144f05562SScott Long ********************************************************************** 279244f05562SScott Long */ 2793d74001adSXin LI static void arcmsr_start_hbc_bgrb(struct AdapterControlBlock *acb) 2794d74001adSXin LI { 2795d74001adSXin LI acb->acb_flags |= ACB_F_MSG_START_BGRB; 2796d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 2797d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 2798d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 2799d74001adSXin LI printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 2800d74001adSXin LI } 2801d74001adSXin LI } 2802d74001adSXin LI /* 2803d74001adSXin LI ********************************************************************** 2804d74001adSXin LI ********************************************************************** 2805d74001adSXin LI */ 280644f05562SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) 280744f05562SScott Long { 280844f05562SScott Long switch (acb->adapter_type) { 280944f05562SScott Long case ACB_ADAPTER_TYPE_A: 281044f05562SScott Long arcmsr_start_hba_bgrb(acb); 281144f05562SScott Long break; 281244f05562SScott Long case ACB_ADAPTER_TYPE_B: 281344f05562SScott Long arcmsr_start_hbb_bgrb(acb); 281444f05562SScott Long break; 2815d74001adSXin LI case ACB_ADAPTER_TYPE_C: 2816d74001adSXin LI arcmsr_start_hbc_bgrb(acb); 2817d74001adSXin LI break; 281844f05562SScott Long } 281944f05562SScott Long } 282044f05562SScott Long /* 282144f05562SScott Long ********************************************************************** 282244f05562SScott Long ** 282344f05562SScott Long ********************************************************************** 282444f05562SScott Long */ 282544f05562SScott Long static void arcmsr_polling_hba_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 2826f1c579b1SScott Long { 2827ad6d6297SScott Long struct CommandControlBlock *srb; 282844f05562SScott Long u_int32_t flag_srb, outbound_intstatus, poll_srb_done=0, poll_count=0; 2829d74001adSXin LI u_int16_t error; 2830f1c579b1SScott Long 283144f05562SScott Long polling_ccb_retry: 2832ad6d6297SScott Long poll_count++; 2833d74001adSXin LI outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 2834d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus); /*clear interrupt*/ 283544f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 2836ad6d6297SScott Long while(1) { 283744f05562SScott Long if((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 283844f05562SScott Long 0, outbound_queueport))==0xFFFFFFFF) { 2839ad6d6297SScott Long if(poll_srb_done) { 2840ad6d6297SScott Long break;/*chip FIFO no ccb for completion already*/ 2841ad6d6297SScott Long } else { 2842ad6d6297SScott Long UDELAY(25000); 2843d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 2844ad6d6297SScott Long break; 2845f1c579b1SScott Long } 284644f05562SScott Long goto polling_ccb_retry; 2847f1c579b1SScott Long } 2848ad6d6297SScott Long } 2849ad6d6297SScott Long /* check if command done with no error*/ 285044f05562SScott Long srb=(struct CommandControlBlock *) 285144f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 2852d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 285344f05562SScott Long poll_srb_done = (srb==poll_srb) ? 1:0; 285422f2616bSXin LI if((srb->acb!=acb) || (srb->srb_state!=ARCMSR_SRB_START)) { 285522f2616bSXin LI if(srb->srb_state==ARCMSR_SRB_ABORTED) { 2856ad6d6297SScott Long printf("arcmsr%d: scsi id=%d lun=%d srb='%p'" 2857ad6d6297SScott Long "poll command abort successfully \n" 2858ad6d6297SScott Long , acb->pci_unit 2859ad6d6297SScott Long , srb->pccb->ccb_h.target_id 2860ad6d6297SScott Long , srb->pccb->ccb_h.target_lun, srb); 2861ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 2862ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 2863ad6d6297SScott Long continue; 2864ad6d6297SScott Long } 2865ad6d6297SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 2866ad6d6297SScott Long "srboutstandingcount=%d \n" 2867ad6d6297SScott Long , acb->pci_unit 2868ad6d6297SScott Long , srb, acb->srboutstandingcount); 2869ad6d6297SScott Long continue; 2870ad6d6297SScott Long } 2871d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 2872ad6d6297SScott Long } /*drain reply FIFO*/ 2873f1c579b1SScott Long } 2874f1c579b1SScott Long /* 2875f1c579b1SScott Long ********************************************************************** 287644f05562SScott Long ** 2877ad6d6297SScott Long ********************************************************************** 2878ad6d6297SScott Long */ 287944f05562SScott Long static void arcmsr_polling_hbb_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 288044f05562SScott Long { 288144f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 288244f05562SScott Long struct CommandControlBlock *srb; 288344f05562SScott Long u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 288444f05562SScott Long int index; 2885d74001adSXin LI u_int16_t error; 288644f05562SScott Long 288744f05562SScott Long polling_ccb_retry: 288844f05562SScott Long poll_count++; 288944f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 289044f05562SScott Long 0, iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 289144f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 289244f05562SScott Long while(1) { 289344f05562SScott Long index=phbbmu->doneq_index; 289444f05562SScott Long if((flag_srb=phbbmu->done_qbuffer[index]) == 0) { 289544f05562SScott Long if(poll_srb_done) { 289644f05562SScott Long break;/*chip FIFO no ccb for completion already*/ 289744f05562SScott Long } else { 289844f05562SScott Long UDELAY(25000); 2899d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 290044f05562SScott Long break; 290144f05562SScott Long } 290244f05562SScott Long goto polling_ccb_retry; 290344f05562SScott Long } 290444f05562SScott Long } 290544f05562SScott Long phbbmu->done_qbuffer[index]=0; 290644f05562SScott Long index++; 290744f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 290844f05562SScott Long phbbmu->doneq_index=index; 290944f05562SScott Long /* check if command done with no error*/ 291044f05562SScott Long srb=(struct CommandControlBlock *) 291144f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 2912d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 291344f05562SScott Long poll_srb_done = (srb==poll_srb) ? 1:0; 291422f2616bSXin LI if((srb->acb!=acb) || (srb->srb_state!=ARCMSR_SRB_START)) { 291522f2616bSXin LI if(srb->srb_state==ARCMSR_SRB_ABORTED) { 291644f05562SScott Long printf("arcmsr%d: scsi id=%d lun=%d srb='%p'" 291744f05562SScott Long "poll command abort successfully \n" 291844f05562SScott Long , acb->pci_unit 291944f05562SScott Long , srb->pccb->ccb_h.target_id 292044f05562SScott Long , srb->pccb->ccb_h.target_lun, srb); 292144f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 292244f05562SScott Long arcmsr_srb_complete(srb, 1); 292344f05562SScott Long continue; 292444f05562SScott Long } 292544f05562SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 292644f05562SScott Long "srboutstandingcount=%d \n" 292744f05562SScott Long , acb->pci_unit 292844f05562SScott Long , srb, acb->srboutstandingcount); 292944f05562SScott Long continue; 293044f05562SScott Long } 2931d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 2932d74001adSXin LI } /*drain reply FIFO*/ 2933d74001adSXin LI } 2934d74001adSXin LI /* 2935d74001adSXin LI ********************************************************************** 2936d74001adSXin LI ** 2937d74001adSXin LI ********************************************************************** 2938d74001adSXin LI */ 2939d74001adSXin LI static void arcmsr_polling_hbc_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 2940d74001adSXin LI { 2941d74001adSXin LI struct CommandControlBlock *srb; 2942d74001adSXin LI u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 2943d74001adSXin LI u_int16_t error; 2944d74001adSXin LI 2945d74001adSXin LI polling_ccb_retry: 2946d74001adSXin LI poll_count++; 2947d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 2948d74001adSXin LI while(1) { 2949d74001adSXin LI if(!(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR)) { 2950d74001adSXin LI if(poll_srb_done) { 2951d74001adSXin LI break;/*chip FIFO no ccb for completion already*/ 2952d74001adSXin LI } else { 2953d74001adSXin LI UDELAY(25000); 2954d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 2955d74001adSXin LI break; 2956d74001adSXin LI } 2957d74001adSXin LI if (acb->srboutstandingcount == 0) { 2958d74001adSXin LI break; 2959d74001adSXin LI } 2960d74001adSXin LI goto polling_ccb_retry; 2961d74001adSXin LI } 2962d74001adSXin LI } 2963d74001adSXin LI flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 2964d74001adSXin LI /* check if command done with no error*/ 296522f2616bSXin LI srb=(struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/ 2966d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; 2967d74001adSXin LI if (poll_srb != NULL) 2968d74001adSXin LI poll_srb_done = (srb==poll_srb) ? 1:0; 296922f2616bSXin LI if((srb->acb!=acb) || (srb->srb_state!=ARCMSR_SRB_START)) { 297022f2616bSXin LI if(srb->srb_state==ARCMSR_SRB_ABORTED) { 2971d74001adSXin LI printf("arcmsr%d: scsi id=%d lun=%d srb='%p'poll command abort successfully \n" 2972d74001adSXin LI , acb->pci_unit, srb->pccb->ccb_h.target_id, srb->pccb->ccb_h.target_lun, srb); 2973d74001adSXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 2974d74001adSXin LI arcmsr_srb_complete(srb, 1); 2975d74001adSXin LI continue; 2976d74001adSXin LI } 2977d74001adSXin LI printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n" 2978d74001adSXin LI , acb->pci_unit, srb, acb->srboutstandingcount); 2979d74001adSXin LI continue; 2980d74001adSXin LI } 2981d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 298244f05562SScott Long } /*drain reply FIFO*/ 298344f05562SScott Long } 298444f05562SScott Long /* 298544f05562SScott Long ********************************************************************** 298644f05562SScott Long ********************************************************************** 298744f05562SScott Long */ 298844f05562SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 298944f05562SScott Long { 299044f05562SScott Long switch (acb->adapter_type) { 299144f05562SScott Long case ACB_ADAPTER_TYPE_A: { 299244f05562SScott Long arcmsr_polling_hba_srbdone(acb, poll_srb); 299344f05562SScott Long } 299444f05562SScott Long break; 299544f05562SScott Long case ACB_ADAPTER_TYPE_B: { 299644f05562SScott Long arcmsr_polling_hbb_srbdone(acb, poll_srb); 299744f05562SScott Long } 299844f05562SScott Long break; 2999d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3000d74001adSXin LI arcmsr_polling_hbc_srbdone(acb, poll_srb); 3001d74001adSXin LI } 3002d74001adSXin LI break; 300344f05562SScott Long } 300444f05562SScott Long } 300544f05562SScott Long /* 300644f05562SScott Long ********************************************************************** 300744f05562SScott Long ********************************************************************** 300844f05562SScott Long */ 300944f05562SScott Long static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) 3010ad6d6297SScott Long { 3011ad6d6297SScott Long char *acb_firm_model=acb->firm_model; 3012ad6d6297SScott Long char *acb_firm_version=acb->firm_version; 3013d74001adSXin LI char *acb_device_map = acb->device_map; 3014d74001adSXin LI size_t iop_firm_model=offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3015d74001adSXin LI size_t iop_firm_version=offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3016d74001adSXin LI size_t iop_device_map = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 3017ad6d6297SScott Long int i; 3018ad6d6297SScott Long 301944f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 302044f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 3021d74001adSXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 3022ad6d6297SScott Long } 3023ad6d6297SScott Long i=0; 3024ad6d6297SScott Long while(i<8) { 302544f05562SScott Long *acb_firm_model=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 3026ad6d6297SScott Long /* 8 bytes firm_model, 15, 60-67*/ 3027ad6d6297SScott Long acb_firm_model++; 3028ad6d6297SScott Long i++; 3029ad6d6297SScott Long } 3030ad6d6297SScott Long i=0; 3031ad6d6297SScott Long while(i<16) { 303244f05562SScott Long *acb_firm_version=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 3033ad6d6297SScott Long /* 16 bytes firm_version, 17, 68-83*/ 3034ad6d6297SScott Long acb_firm_version++; 3035ad6d6297SScott Long i++; 3036ad6d6297SScott Long } 3037d74001adSXin LI i=0; 3038d74001adSXin LI while(i<16) { 3039d74001adSXin LI *acb_device_map=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 3040d74001adSXin LI acb_device_map++; 3041d74001adSXin LI i++; 3042d74001adSXin LI } 3043ad6d6297SScott Long printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION); 3044ad6d6297SScott Long printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version); 3045d74001adSXin LI acb->firm_request_len=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3046d74001adSXin LI acb->firm_numbers_queue=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3047d74001adSXin LI acb->firm_sdram_size=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3048d74001adSXin LI acb->firm_ide_channels=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3049d74001adSXin LI acb->firm_cfg_version=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3050ad6d6297SScott Long } 3051ad6d6297SScott Long /* 3052ad6d6297SScott Long ********************************************************************** 305344f05562SScott Long ********************************************************************** 305444f05562SScott Long */ 305544f05562SScott Long static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) 305644f05562SScott Long { 305744f05562SScott Long char *acb_firm_model=acb->firm_model; 305844f05562SScott Long char *acb_firm_version=acb->firm_version; 3059d74001adSXin LI char *acb_device_map = acb->device_map; 3060d74001adSXin LI size_t iop_firm_model=offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3061d74001adSXin LI size_t iop_firm_version=offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3062d74001adSXin LI size_t iop_device_map = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 306344f05562SScott Long int i; 306444f05562SScott Long 3065d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG); 306644f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 3067d74001adSXin LI printf( "arcmsr%d: wait" "'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 306844f05562SScott Long } 306944f05562SScott Long i=0; 307044f05562SScott Long while(i<8) { 307144f05562SScott Long *acb_firm_model=bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_model+i); 307244f05562SScott Long /* 8 bytes firm_model, 15, 60-67*/ 307344f05562SScott Long acb_firm_model++; 307444f05562SScott Long i++; 307544f05562SScott Long } 307644f05562SScott Long i=0; 307744f05562SScott Long while(i<16) { 307844f05562SScott Long *acb_firm_version=bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_version+i); 307944f05562SScott Long /* 16 bytes firm_version, 17, 68-83*/ 308044f05562SScott Long acb_firm_version++; 308144f05562SScott Long i++; 308244f05562SScott Long } 3083d74001adSXin LI i=0; 3084d74001adSXin LI while(i<16) { 3085d74001adSXin LI *acb_device_map=bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_device_map+i); 3086d74001adSXin LI acb_device_map++; 3087d74001adSXin LI i++; 3088d74001adSXin LI } 308944f05562SScott Long printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION); 309044f05562SScott Long printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version); 3091d74001adSXin LI acb->firm_request_len=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3092d74001adSXin LI acb->firm_numbers_queue=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3093d74001adSXin LI acb->firm_sdram_size=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3094d74001adSXin LI acb->firm_ide_channels=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3095d74001adSXin LI acb->firm_cfg_version=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3096d74001adSXin LI } 3097d74001adSXin LI /* 3098d74001adSXin LI ********************************************************************** 3099d74001adSXin LI ********************************************************************** 3100d74001adSXin LI */ 3101d74001adSXin LI static void arcmsr_get_hbc_config(struct AdapterControlBlock *acb) 3102d74001adSXin LI { 3103d74001adSXin LI char *acb_firm_model=acb->firm_model; 3104d74001adSXin LI char *acb_firm_version=acb->firm_version; 3105d74001adSXin LI char *acb_device_map = acb->device_map; 3106d74001adSXin LI size_t iop_firm_model=offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3107d74001adSXin LI size_t iop_firm_version=offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3108d74001adSXin LI size_t iop_device_map = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 3109d74001adSXin LI int i; 3110d74001adSXin LI 3111d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 3112d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 3113d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 3114d74001adSXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 3115d74001adSXin LI } 3116d74001adSXin LI i=0; 3117d74001adSXin LI while(i<8) { 3118d74001adSXin LI *acb_firm_model=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 3119d74001adSXin LI /* 8 bytes firm_model, 15, 60-67*/ 3120d74001adSXin LI acb_firm_model++; 3121d74001adSXin LI i++; 3122d74001adSXin LI } 3123d74001adSXin LI i=0; 3124d74001adSXin LI while(i<16) { 3125d74001adSXin LI *acb_firm_version=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 3126d74001adSXin LI /* 16 bytes firm_version, 17, 68-83*/ 3127d74001adSXin LI acb_firm_version++; 3128d74001adSXin LI i++; 3129d74001adSXin LI } 3130d74001adSXin LI i=0; 3131d74001adSXin LI while(i<16) { 3132d74001adSXin LI *acb_device_map=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 3133d74001adSXin LI acb_device_map++; 3134d74001adSXin LI i++; 3135d74001adSXin LI } 3136d74001adSXin LI printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION); 3137d74001adSXin LI printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version); 3138d74001adSXin LI acb->firm_request_len =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3139d74001adSXin LI acb->firm_numbers_queue =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3140d74001adSXin LI acb->firm_sdram_size =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3141d74001adSXin LI acb->firm_ide_channels =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3142d74001adSXin LI acb->firm_cfg_version =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 314344f05562SScott Long } 314444f05562SScott Long /* 314544f05562SScott Long ********************************************************************** 314644f05562SScott Long ********************************************************************** 314744f05562SScott Long */ 314844f05562SScott Long static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) 314944f05562SScott Long { 315044f05562SScott Long switch (acb->adapter_type) { 315144f05562SScott Long case ACB_ADAPTER_TYPE_A: { 315244f05562SScott Long arcmsr_get_hba_config(acb); 315344f05562SScott Long } 315444f05562SScott Long break; 315544f05562SScott Long case ACB_ADAPTER_TYPE_B: { 315644f05562SScott Long arcmsr_get_hbb_config(acb); 315744f05562SScott Long } 315844f05562SScott Long break; 3159d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3160d74001adSXin LI arcmsr_get_hbc_config(acb); 3161d74001adSXin LI } 3162d74001adSXin LI break; 316344f05562SScott Long } 316444f05562SScott Long } 316544f05562SScott Long /* 316644f05562SScott Long ********************************************************************** 316744f05562SScott Long ********************************************************************** 316844f05562SScott Long */ 316944f05562SScott Long static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb) 317044f05562SScott Long { 317144f05562SScott Long int timeout=0; 317244f05562SScott Long 317344f05562SScott Long switch (acb->adapter_type) { 317444f05562SScott Long case ACB_ADAPTER_TYPE_A: { 3175d74001adSXin LI while ((CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) 317644f05562SScott Long { 317744f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 317844f05562SScott Long { 3179d74001adSXin LI printf( "arcmsr%d:timed out waiting for firmware \n", acb->pci_unit); 318044f05562SScott Long return; 318144f05562SScott Long } 318244f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 318344f05562SScott Long } 318444f05562SScott Long } 318544f05562SScott Long break; 318644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 3187d74001adSXin LI while ((CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & ARCMSR_MESSAGE_FIRMWARE_OK) == 0) 318844f05562SScott Long { 318944f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 319044f05562SScott Long { 3191d74001adSXin LI printf( "arcmsr%d: timed out waiting for firmware \n", acb->pci_unit); 319244f05562SScott Long return; 319344f05562SScott Long } 319444f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 319544f05562SScott Long } 3196d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 3197d74001adSXin LI } 3198d74001adSXin LI break; 3199d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3200d74001adSXin LI while ((CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0) 3201d74001adSXin LI { 3202d74001adSXin LI if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 3203d74001adSXin LI { 3204d74001adSXin LI printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit); 3205d74001adSXin LI return; 3206d74001adSXin LI } 3207d74001adSXin LI UDELAY(15000); /* wait 15 milli-seconds */ 3208d74001adSXin LI } 320944f05562SScott Long } 321044f05562SScott Long break; 321144f05562SScott Long } 321244f05562SScott Long } 321344f05562SScott Long /* 321444f05562SScott Long ********************************************************************** 321544f05562SScott Long ********************************************************************** 321644f05562SScott Long */ 321744f05562SScott Long static void arcmsr_clear_doorbell_queue_buffer( struct AdapterControlBlock *acb) 321844f05562SScott Long { 3219d74001adSXin LI u_int32_t outbound_doorbell; 3220d74001adSXin LI 322144f05562SScott Long switch (acb->adapter_type) { 322244f05562SScott Long case ACB_ADAPTER_TYPE_A: { 322344f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 3224d74001adSXin LI outbound_doorbell = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell); 3225d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, outbound_doorbell); /*clear doorbell interrupt */ 3226d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 3227d74001adSXin LI 322844f05562SScott Long } 322944f05562SScott Long break; 323044f05562SScott Long case ACB_ADAPTER_TYPE_B: { 3231d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt and message state*/ 3232d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 323344f05562SScott Long /* let IOP know data has been read */ 323444f05562SScott Long } 323544f05562SScott Long break; 3236d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3237d74001adSXin LI /* empty doorbell Qbuffer if door bell ringed */ 3238d74001adSXin LI outbound_doorbell = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); 3239d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell); /*clear doorbell interrupt */ 3240d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK); 3241d74001adSXin LI 3242d74001adSXin LI } 3243d74001adSXin LI break; 324444f05562SScott Long } 324544f05562SScott Long } 324644f05562SScott Long /* 324744f05562SScott Long ************************************************************************ 324844f05562SScott Long ************************************************************************ 324944f05562SScott Long */ 325044f05562SScott Long static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb) 325144f05562SScott Long { 325244f05562SScott Long unsigned long srb_phyaddr; 325344f05562SScott Long u_int32_t srb_phyaddr_hi32; 325444f05562SScott Long 325544f05562SScott Long /* 325644f05562SScott Long ******************************************************************** 325744f05562SScott Long ** here we need to tell iop 331 our freesrb.HighPart 325844f05562SScott Long ** if freesrb.HighPart is not zero 325944f05562SScott Long ******************************************************************** 326044f05562SScott Long */ 3261d74001adSXin LI srb_phyaddr= (unsigned long) acb->srb_phyaddr.phyaddr; 3262d74001adSXin LI // srb_phyaddr_hi32=(u_int32_t) ((srb_phyaddr>>16)>>16); 3263d74001adSXin LI srb_phyaddr_hi32=acb->srb_phyaddr.B.phyadd_high; 326444f05562SScott Long switch (acb->adapter_type) { 326544f05562SScott Long case ACB_ADAPTER_TYPE_A: { 326644f05562SScott Long if(srb_phyaddr_hi32!=0) { 3267d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 3268d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 3269d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 327044f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 3271d74001adSXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 327244f05562SScott Long return FALSE; 327344f05562SScott Long } 327444f05562SScott Long } 327544f05562SScott Long } 327644f05562SScott Long break; 327744f05562SScott Long /* 327844f05562SScott Long *********************************************************************** 327944f05562SScott Long ** if adapter type B, set window of "post command Q" 328044f05562SScott Long *********************************************************************** 328144f05562SScott Long */ 328244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 328344f05562SScott Long u_int32_t post_queue_phyaddr; 328444f05562SScott Long struct HBB_MessageUnit *phbbmu; 328544f05562SScott Long 328644f05562SScott Long phbbmu=(struct HBB_MessageUnit *)acb->pmu; 328744f05562SScott Long phbbmu->postq_index=0; 328844f05562SScott Long phbbmu->doneq_index=0; 3289d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_SET_POST_WINDOW); 329044f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 3291d74001adSXin LI printf( "arcmsr%d: 'set window of post command Q' timeout\n", acb->pci_unit); 329244f05562SScott Long return FALSE; 329344f05562SScott Long } 329422f2616bSXin LI post_queue_phyaddr = srb_phyaddr + ARCMSR_SRBS_POOL_SIZE 329544f05562SScott Long + offsetof(struct HBB_MessageUnit, post_qbuffer); 3296d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */ 3297d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1], srb_phyaddr_hi32); /* normal should be zero */ 3298d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ size (256+8)*4 */ 3299d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3], post_queue_phyaddr+1056); /* doneQ size (256+8)*4 */ 3300d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4], 1056); /* srb maxQ size must be --> [(256+8)*4] */ 3301d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_SET_CONFIG); 330244f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 330344f05562SScott Long printf( "arcmsr%d: 'set command Q window' timeout \n", acb->pci_unit); 330444f05562SScott Long return FALSE; 330544f05562SScott Long } 3306d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_START_DRIVER_MODE); 330744f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 330844f05562SScott Long printf( "arcmsr%d: 'start diver mode' timeout \n", acb->pci_unit); 330944f05562SScott Long return FALSE; 331044f05562SScott Long } 331144f05562SScott Long } 331244f05562SScott Long break; 3313d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3314d74001adSXin LI if(srb_phyaddr_hi32!=0) { 3315d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 3316d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 3317d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 3318d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 3319d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 3320d74001adSXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 3321d74001adSXin LI return FALSE; 3322d74001adSXin LI } 3323d74001adSXin LI } 3324d74001adSXin LI } 3325d74001adSXin LI break; 332644f05562SScott Long } 3327dac36688SXin LI return (TRUE); 332844f05562SScott Long } 332944f05562SScott Long /* 333044f05562SScott Long ************************************************************************ 333144f05562SScott Long ************************************************************************ 333244f05562SScott Long */ 333344f05562SScott Long static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb) 333444f05562SScott Long { 333544f05562SScott Long switch (acb->adapter_type) 333644f05562SScott Long { 333744f05562SScott Long case ACB_ADAPTER_TYPE_A: 3338d74001adSXin LI case ACB_ADAPTER_TYPE_C: 3339d74001adSXin LI break; 334044f05562SScott Long case ACB_ADAPTER_TYPE_B: { 3341d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell,ARCMSR_MESSAGE_ACTIVE_EOI_MODE); 334244f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 3343d74001adSXin LI printf( "arcmsr%d: 'iop enable eoi mode' timeout \n", acb->pci_unit); 3344d74001adSXin LI 334544f05562SScott Long return; 334644f05562SScott Long } 334744f05562SScott Long } 334844f05562SScott Long break; 334944f05562SScott Long } 335044f05562SScott Long } 335144f05562SScott Long /* 335244f05562SScott Long ********************************************************************** 3353ad6d6297SScott Long ********************************************************************** 3354ad6d6297SScott Long */ 3355ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb) 3356ad6d6297SScott Long { 335744f05562SScott Long u_int32_t intmask_org; 3358ad6d6297SScott Long 335944f05562SScott Long /* disable all outbound interrupt */ 336044f05562SScott Long intmask_org=arcmsr_disable_allintr(acb); 336144f05562SScott Long arcmsr_wait_firmware_ready(acb); 336244f05562SScott Long arcmsr_iop_confirm(acb); 3363ad6d6297SScott Long arcmsr_get_firmware_spec(acb); 336444f05562SScott Long /*start background rebuild*/ 3365ad6d6297SScott Long arcmsr_start_adapter_bgrb(acb); 336644f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 336744f05562SScott Long arcmsr_clear_doorbell_queue_buffer(acb); 336844f05562SScott Long arcmsr_enable_eoi_mode(acb); 336944f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 337044f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 3371ad6d6297SScott Long acb->acb_flags |=ACB_F_IOP_INITED; 3372ad6d6297SScott Long } 3373ad6d6297SScott Long /* 3374ad6d6297SScott Long ********************************************************************** 3375f1c579b1SScott Long ********************************************************************** 3376f1c579b1SScott Long */ 3377231c8b71SXin LI static void arcmsr_map_free_srb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 3378f1c579b1SScott Long { 3379ad6d6297SScott Long struct AdapterControlBlock *acb=arg; 3380ad6d6297SScott Long struct CommandControlBlock *srb_tmp; 3381ad6d6297SScott Long u_int8_t * dma_memptr; 338244f05562SScott Long u_int32_t i; 3383ad6d6297SScott Long unsigned long srb_phyaddr=(unsigned long)segs->ds_addr; 3384f1c579b1SScott Long 3385ad6d6297SScott Long dma_memptr=acb->uncacheptr; 3386d74001adSXin LI acb->srb_phyaddr.phyaddr=srb_phyaddr; 3387ad6d6297SScott Long srb_tmp=(struct CommandControlBlock *)dma_memptr; 3388ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 338944f05562SScott Long if(bus_dmamap_create(acb->dm_segs_dmat, 339044f05562SScott Long /*flags*/0, &srb_tmp->dm_segs_dmamap)!=0) { 3391ad6d6297SScott Long acb->acb_flags |= ACB_F_MAPFREESRB_FAILD; 339244f05562SScott Long printf("arcmsr%d:" 339344f05562SScott Long " srb dmamap bus_dmamap_create error\n", acb->pci_unit); 3394ad6d6297SScott Long return; 3395ad6d6297SScott Long } 3396d74001adSXin LI srb_tmp->cdb_shifted_phyaddr=(acb->adapter_type==ACB_ADAPTER_TYPE_C)?srb_phyaddr:(srb_phyaddr >> 5); 3397ad6d6297SScott Long srb_tmp->acb=acb; 3398ad6d6297SScott Long acb->srbworkingQ[i]=acb->psrb_pool[i]=srb_tmp; 339922f2616bSXin LI srb_phyaddr=srb_phyaddr+SRB_SIZE; 340022f2616bSXin LI srb_tmp = (struct CommandControlBlock *)((unsigned long)srb_tmp+SRB_SIZE); 3401ad6d6297SScott Long } 3402ad6d6297SScott Long acb->vir2phy_offset=(unsigned long)srb_tmp-(unsigned long)srb_phyaddr; 3403f1c579b1SScott Long } 3404f1c579b1SScott Long /* 3405f1c579b1SScott Long ************************************************************************ 3406f1c579b1SScott Long ** 3407f1c579b1SScott Long ** 3408f1c579b1SScott Long ************************************************************************ 3409f1c579b1SScott Long */ 3410ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb) 3411f1c579b1SScott Long { 3412f1c579b1SScott Long /* remove the control device */ 3413ad6d6297SScott Long if(acb->ioctl_dev != NULL) { 3414ad6d6297SScott Long destroy_dev(acb->ioctl_dev); 3415f1c579b1SScott Long } 3416ad6d6297SScott Long bus_dmamap_unload(acb->srb_dmat, acb->srb_dmamap); 3417ad6d6297SScott Long bus_dmamap_destroy(acb->srb_dmat, acb->srb_dmamap); 3418ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 3419ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 3420ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 3421f1c579b1SScott Long } 3422f1c579b1SScott Long /* 3423f1c579b1SScott Long ************************************************************************ 3424f1c579b1SScott Long ************************************************************************ 3425f1c579b1SScott Long */ 3426ad6d6297SScott Long static u_int32_t arcmsr_initialize(device_t dev) 3427f1c579b1SScott Long { 3428ad6d6297SScott Long struct AdapterControlBlock *acb=device_get_softc(dev); 3429ad6d6297SScott Long u_int16_t pci_command; 343044f05562SScott Long int i, j,max_coherent_size; 3431dac36688SXin LI u_int32_t vendor_dev_id; 3432f1c579b1SScott Long 3433dac36688SXin LI vendor_dev_id = pci_get_devid(dev); 3434dac36688SXin LI acb->vendor_device_id = vendor_dev_id; 3435dac36688SXin LI switch (vendor_dev_id) { 3436dac36688SXin LI case PCIDevVenIDARC1880: 3437dac36688SXin LI case PCIDevVenIDARC1882: 3438dac36688SXin LI case PCIDevVenIDARC1213: 3439dac36688SXin LI case PCIDevVenIDARC1223: { 3440d74001adSXin LI acb->adapter_type=ACB_ADAPTER_TYPE_C; 3441dac36688SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_6G; 3442d74001adSXin LI max_coherent_size=ARCMSR_SRBS_POOL_SIZE; 3443d74001adSXin LI } 3444d74001adSXin LI break; 3445231c8b71SXin LI case PCIDevVenIDARC1200: 344644f05562SScott Long case PCIDevVenIDARC1201: { 344744f05562SScott Long acb->adapter_type=ACB_ADAPTER_TYPE_B; 3448dac36688SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_3G; 3449d74001adSXin LI max_coherent_size=ARCMSR_SRBS_POOL_SIZE+(sizeof(struct HBB_MessageUnit)); 345044f05562SScott Long } 345144f05562SScott Long break; 345244f05562SScott Long case PCIDevVenIDARC1110: 345344f05562SScott Long case PCIDevVenIDARC1120: 345444f05562SScott Long case PCIDevVenIDARC1130: 345544f05562SScott Long case PCIDevVenIDARC1160: 345644f05562SScott Long case PCIDevVenIDARC1170: 345744f05562SScott Long case PCIDevVenIDARC1210: 345844f05562SScott Long case PCIDevVenIDARC1220: 345944f05562SScott Long case PCIDevVenIDARC1230: 3460231c8b71SXin LI case PCIDevVenIDARC1231: 346144f05562SScott Long case PCIDevVenIDARC1260: 3462231c8b71SXin LI case PCIDevVenIDARC1261: 346344f05562SScott Long case PCIDevVenIDARC1270: 346444f05562SScott Long case PCIDevVenIDARC1280: 3465d74001adSXin LI case PCIDevVenIDARC1212: 3466d74001adSXin LI case PCIDevVenIDARC1222: 346744f05562SScott Long case PCIDevVenIDARC1380: 346844f05562SScott Long case PCIDevVenIDARC1381: 346944f05562SScott Long case PCIDevVenIDARC1680: 347044f05562SScott Long case PCIDevVenIDARC1681: { 347144f05562SScott Long acb->adapter_type=ACB_ADAPTER_TYPE_A; 3472dac36688SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_3G; 347344f05562SScott Long max_coherent_size=ARCMSR_SRBS_POOL_SIZE; 347444f05562SScott Long } 347544f05562SScott Long break; 347644f05562SScott Long default: { 347744f05562SScott Long printf("arcmsr%d:" 347844f05562SScott Long " unknown RAID adapter type \n", device_get_unit(dev)); 347944f05562SScott Long return ENOMEM; 348044f05562SScott Long } 348144f05562SScott Long } 3482b6f97155SScott Long if(bus_dma_tag_create( /*PCI parent*/ bus_get_dma_tag(dev), 3483f1c579b1SScott Long /*alignemnt*/ 1, 3484f1c579b1SScott Long /*boundary*/ 0, 3485701d9f1fSScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 3486f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 3487f1c579b1SScott Long /*filter*/ NULL, 3488f1c579b1SScott Long /*filterarg*/ NULL, 3489f1c579b1SScott Long /*maxsize*/ BUS_SPACE_MAXSIZE_32BIT, 3490f1c579b1SScott Long /*nsegments*/ BUS_SPACE_UNRESTRICTED, 3491f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 3492f1c579b1SScott Long /*flags*/ 0, 349322f2616bSXin LI #if __FreeBSD_version >= 501102 3494f1c579b1SScott Long /*lockfunc*/ NULL, 3495f1c579b1SScott Long /*lockarg*/ NULL, 3496f1c579b1SScott Long #endif 3497231c8b71SXin LI &acb->parent_dmat) != 0) 3498f1c579b1SScott Long { 349944f05562SScott Long printf("arcmsr%d: parent_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 3500f1c579b1SScott Long return ENOMEM; 3501f1c579b1SScott Long } 3502231c8b71SXin LI 3503f1c579b1SScott Long /* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */ 3504ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 3505f1c579b1SScott Long /*alignment*/ 1, 3506f1c579b1SScott Long /*boundary*/ 0, 350722f2616bSXin LI #ifdef PAE 350822f2616bSXin LI /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 350922f2616bSXin LI #else 3510f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 351122f2616bSXin LI #endif 3512f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 3513f1c579b1SScott Long /*filter*/ NULL, 3514f1c579b1SScott Long /*filterarg*/ NULL, 3515231c8b71SXin LI /*maxsize*/ ARCMSR_MAX_SG_ENTRIES * PAGE_SIZE * ARCMSR_MAX_FREESRB_NUM, 3516f1c579b1SScott Long /*nsegments*/ ARCMSR_MAX_SG_ENTRIES, 3517f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 3518ad6d6297SScott Long /*flags*/ 0, 351922f2616bSXin LI #if __FreeBSD_version >= 501102 3520f1c579b1SScott Long /*lockfunc*/ busdma_lock_mutex, 35215878cbecSScott Long /*lockarg*/ &acb->qbuffer_lock, 3522f1c579b1SScott Long #endif 3523231c8b71SXin LI &acb->dm_segs_dmat) != 0) 3524f1c579b1SScott Long { 3525ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 352644f05562SScott Long printf("arcmsr%d: dm_segs_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 3527f1c579b1SScott Long return ENOMEM; 3528f1c579b1SScott Long } 3529231c8b71SXin LI 3530ad6d6297SScott Long /* DMA tag for our srb structures.... Allocate the freesrb memory */ 3531ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 353244f05562SScott Long /*alignment*/ 0x20, 3533f1c579b1SScott Long /*boundary*/ 0, 3534f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 3535f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 3536f1c579b1SScott Long /*filter*/ NULL, 3537f1c579b1SScott Long /*filterarg*/ NULL, 353844f05562SScott Long /*maxsize*/ max_coherent_size, 3539f1c579b1SScott Long /*nsegments*/ 1, 3540f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 3541701d9f1fSScott Long /*flags*/ 0, 354222f2616bSXin LI #if __FreeBSD_version >= 501102 3543f1c579b1SScott Long /*lockfunc*/ NULL, 3544f1c579b1SScott Long /*lockarg*/ NULL, 3545f1c579b1SScott Long #endif 3546231c8b71SXin LI &acb->srb_dmat) != 0) 3547f1c579b1SScott Long { 3548ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 3549ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 355044f05562SScott Long printf("arcmsr%d: srb_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 3551f1c579b1SScott Long return ENXIO; 3552f1c579b1SScott Long } 3553f1c579b1SScott Long /* Allocation for our srbs */ 3554d74001adSXin LI if(bus_dmamem_alloc(acb->srb_dmat, (void **)&acb->uncacheptr, BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &acb->srb_dmamap) != 0) { 3555ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 3556ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 3557ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 355844f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamem_alloc failure!\n", device_get_unit(dev)); 3559f1c579b1SScott Long return ENXIO; 3560f1c579b1SScott Long } 3561f1c579b1SScott Long /* And permanently map them */ 3562231c8b71SXin LI if(bus_dmamap_load(acb->srb_dmat, acb->srb_dmamap, acb->uncacheptr, max_coherent_size, arcmsr_map_free_srb, acb, /*flags*/0)) { 3563ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 3564ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 3565ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 356644f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamap_load failure!\n", device_get_unit(dev)); 3567f1c579b1SScott Long return ENXIO; 3568f1c579b1SScott Long } 3569f1c579b1SScott Long pci_command=pci_read_config(dev, PCIR_COMMAND, 2); 3570f1c579b1SScott Long pci_command |= PCIM_CMD_BUSMASTEREN; 3571f1c579b1SScott Long pci_command |= PCIM_CMD_PERRESPEN; 3572f1c579b1SScott Long pci_command |= PCIM_CMD_MWRICEN; 3573f1c579b1SScott Long /* Enable Busmaster/Mem */ 3574f1c579b1SScott Long pci_command |= PCIM_CMD_MEMEN; 3575f1c579b1SScott Long pci_write_config(dev, PCIR_COMMAND, pci_command, 2); 357644f05562SScott Long switch(acb->adapter_type) { 357744f05562SScott Long case ACB_ADAPTER_TYPE_A: { 357844f05562SScott Long u_int32_t rid0=PCIR_BAR(0); 357944f05562SScott Long vm_offset_t mem_base0; 358044f05562SScott Long 3581d74001adSXin LI acb->sys_res_arcmsr[0]=bus_alloc_resource(dev,SYS_RES_MEMORY, &rid0, 0ul, ~0ul, 0x1000, RF_ACTIVE); 358244f05562SScott Long if(acb->sys_res_arcmsr[0] == NULL) { 3583ad6d6297SScott Long arcmsr_free_resource(acb); 3584d74001adSXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 3585f1c579b1SScott Long return ENOMEM; 3586f1c579b1SScott Long } 358744f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 3588ad6d6297SScott Long arcmsr_free_resource(acb); 3589d74001adSXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 3590f1c579b1SScott Long return ENXIO; 3591f1c579b1SScott Long } 359244f05562SScott Long mem_base0=(vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 359344f05562SScott Long if(mem_base0==0) { 3594ad6d6297SScott Long arcmsr_free_resource(acb); 3595d74001adSXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 3596f1c579b1SScott Long return ENXIO; 3597f1c579b1SScott Long } 359844f05562SScott Long acb->btag[0]=rman_get_bustag(acb->sys_res_arcmsr[0]); 359944f05562SScott Long acb->bhandle[0]=rman_get_bushandle(acb->sys_res_arcmsr[0]); 360044f05562SScott Long acb->pmu=(struct MessageUnit_UNION *)mem_base0; 360144f05562SScott Long } 360244f05562SScott Long break; 360344f05562SScott Long case ACB_ADAPTER_TYPE_B: { 360444f05562SScott Long struct HBB_MessageUnit *phbbmu; 360544f05562SScott Long struct CommandControlBlock *freesrb; 360644f05562SScott Long u_int32_t rid[]={ PCIR_BAR(0), PCIR_BAR(2) }; 360744f05562SScott Long vm_offset_t mem_base[]={0,0}; 360844f05562SScott Long for(i=0; i<2; i++) { 360944f05562SScott Long if(i==0) { 3610d74001adSXin LI acb->sys_res_arcmsr[i]=bus_alloc_resource(dev,SYS_RES_MEMORY, &rid[i], 3611231c8b71SXin LI 0ul, ~0ul, sizeof(struct HBB_DOORBELL), RF_ACTIVE); 361244f05562SScott Long } else { 3613d74001adSXin LI acb->sys_res_arcmsr[i]=bus_alloc_resource(dev, SYS_RES_MEMORY, &rid[i], 3614231c8b71SXin LI 0ul, ~0ul, sizeof(struct HBB_RWBUFFER), RF_ACTIVE); 361544f05562SScott Long } 361644f05562SScott Long if(acb->sys_res_arcmsr[i] == NULL) { 361744f05562SScott Long arcmsr_free_resource(acb); 3618d74001adSXin LI printf("arcmsr%d: bus_alloc_resource %d failure!\n", device_get_unit(dev), i); 361944f05562SScott Long return ENOMEM; 362044f05562SScott Long } 362144f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[i]) <= 0) { 362244f05562SScott Long arcmsr_free_resource(acb); 3623d74001adSXin LI printf("arcmsr%d: rman_get_start %d failure!\n", device_get_unit(dev), i); 362444f05562SScott Long return ENXIO; 362544f05562SScott Long } 362644f05562SScott Long mem_base[i]=(vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[i]); 362744f05562SScott Long if(mem_base[i]==0) { 362844f05562SScott Long arcmsr_free_resource(acb); 3629d74001adSXin LI printf("arcmsr%d: rman_get_virtual %d failure!\n", device_get_unit(dev), i); 363044f05562SScott Long return ENXIO; 363144f05562SScott Long } 363244f05562SScott Long acb->btag[i]=rman_get_bustag(acb->sys_res_arcmsr[i]); 363344f05562SScott Long acb->bhandle[i]=rman_get_bushandle(acb->sys_res_arcmsr[i]); 363444f05562SScott Long } 363544f05562SScott Long freesrb=(struct CommandControlBlock *)acb->uncacheptr; 363622f2616bSXin LI // acb->pmu=(struct MessageUnit_UNION *)&freesrb[ARCMSR_MAX_FREESRB_NUM]; 363722f2616bSXin LI acb->pmu=(struct MessageUnit_UNION *)((unsigned long)freesrb+ARCMSR_SRBS_POOL_SIZE); 363844f05562SScott Long phbbmu=(struct HBB_MessageUnit *)acb->pmu; 363944f05562SScott Long phbbmu->hbb_doorbell=(struct HBB_DOORBELL *)mem_base[0]; 364044f05562SScott Long phbbmu->hbb_rwbuffer=(struct HBB_RWBUFFER *)mem_base[1]; 364144f05562SScott Long } 364244f05562SScott Long break; 3643d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3644d74001adSXin LI u_int32_t rid0=PCIR_BAR(1); 3645d74001adSXin LI vm_offset_t mem_base0; 3646d74001adSXin LI 3647d74001adSXin LI acb->sys_res_arcmsr[0]=bus_alloc_resource(dev,SYS_RES_MEMORY, &rid0, 0ul, ~0ul, sizeof(struct HBC_MessageUnit), RF_ACTIVE); 3648d74001adSXin LI if(acb->sys_res_arcmsr[0] == NULL) { 3649d74001adSXin LI arcmsr_free_resource(acb); 3650d74001adSXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 3651d74001adSXin LI return ENOMEM; 3652d74001adSXin LI } 3653d74001adSXin LI if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 3654d74001adSXin LI arcmsr_free_resource(acb); 3655d74001adSXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 3656d74001adSXin LI return ENXIO; 3657d74001adSXin LI } 3658d74001adSXin LI mem_base0=(vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 3659d74001adSXin LI if(mem_base0==0) { 3660d74001adSXin LI arcmsr_free_resource(acb); 3661d74001adSXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 3662d74001adSXin LI return ENXIO; 3663d74001adSXin LI } 3664d74001adSXin LI acb->btag[0]=rman_get_bustag(acb->sys_res_arcmsr[0]); 3665d74001adSXin LI acb->bhandle[0]=rman_get_bushandle(acb->sys_res_arcmsr[0]); 3666d74001adSXin LI acb->pmu=(struct MessageUnit_UNION *)mem_base0; 3667d74001adSXin LI } 3668d74001adSXin LI break; 366944f05562SScott Long } 3670ad6d6297SScott Long if(acb->acb_flags & ACB_F_MAPFREESRB_FAILD) { 3671ad6d6297SScott Long arcmsr_free_resource(acb); 367244f05562SScott Long printf("arcmsr%d: map free srb failure!\n", device_get_unit(dev)); 3673f1c579b1SScott Long return ENXIO; 3674f1c579b1SScott Long } 3675d74001adSXin LI acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_RQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ); 3676ad6d6297SScott Long acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; 3677ad6d6297SScott Long /* 3678ad6d6297SScott Long ******************************************************************** 3679ad6d6297SScott Long ** init raid volume state 3680ad6d6297SScott Long ******************************************************************** 3681ad6d6297SScott Long */ 3682ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_TARGETID;i++) { 3683ad6d6297SScott Long for(j=0;j<ARCMSR_MAX_TARGETLUN;j++) { 368444f05562SScott Long acb->devstate[i][j]=ARECA_RAID_GONE; 3685ad6d6297SScott Long } 3686ad6d6297SScott Long } 3687ad6d6297SScott Long arcmsr_iop_init(acb); 3688f1c579b1SScott Long return(0); 3689f1c579b1SScott Long } 3690f1c579b1SScott Long /* 3691f1c579b1SScott Long ************************************************************************ 3692f1c579b1SScott Long ************************************************************************ 3693f1c579b1SScott Long */ 3694f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev) 3695f1c579b1SScott Long { 3696ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 3697ad6d6297SScott Long u_int32_t unit=device_get_unit(dev); 3698f1c579b1SScott Long struct ccb_setasync csa; 3699f1c579b1SScott Long struct cam_devq *devq; /* Device Queue to use for this SIM */ 3700f1c579b1SScott Long struct resource *irqres; 3701f1c579b1SScott Long int rid; 3702f1c579b1SScott Long 3703ad6d6297SScott Long if(acb == NULL) { 3704ad6d6297SScott Long printf("arcmsr%d: cannot allocate softc\n", unit); 3705ad6d6297SScott Long return (ENOMEM); 3706ad6d6297SScott Long } 37075878cbecSScott Long ARCMSR_LOCK_INIT(&acb->qbuffer_lock, "arcmsr Q buffer lock"); 3708ad6d6297SScott Long if(arcmsr_initialize(dev)) { 3709ad6d6297SScott Long printf("arcmsr%d: initialize failure!\n", unit); 37105878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3711f1c579b1SScott Long return ENXIO; 3712f1c579b1SScott Long } 3713f1c579b1SScott Long /* After setting up the adapter, map our interrupt */ 3714f1c579b1SScott Long rid=0; 3715ad6d6297SScott Long irqres=bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE); 3716ad6d6297SScott Long if(irqres == NULL || 371744f05562SScott Long #if __FreeBSD_version >= 700025 3718d74001adSXin LI bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, NULL, arcmsr_intr_handler, acb, &acb->ih)) { 371944f05562SScott Long #else 3720d74001adSXin LI bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, arcmsr_intr_handler, acb, &acb->ih)) { 372144f05562SScott Long #endif 3722ad6d6297SScott Long arcmsr_free_resource(acb); 37235878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3724f1c579b1SScott Long printf("arcmsr%d: unable to register interrupt handler!\n", unit); 3725f1c579b1SScott Long return ENXIO; 3726f1c579b1SScott Long } 3727ad6d6297SScott Long acb->irqres=irqres; 3728ad6d6297SScott Long acb->pci_dev=dev; 3729ad6d6297SScott Long acb->pci_unit=unit; 3730f1c579b1SScott Long /* 3731f1c579b1SScott Long * Now let the CAM generic SCSI layer find the SCSI devices on 3732f1c579b1SScott Long * the bus * start queue to reset to the idle loop. * 3733f1c579b1SScott Long * Create device queue of SIM(s) * (MAX_START_JOB - 1) : 3734f1c579b1SScott Long * max_sim_transactions 3735f1c579b1SScott Long */ 3736f1c579b1SScott Long devq=cam_simq_alloc(ARCMSR_MAX_START_JOB); 3737ad6d6297SScott Long if(devq == NULL) { 3738ad6d6297SScott Long arcmsr_free_resource(acb); 3739ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 37405878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3741ad6d6297SScott Long printf("arcmsr%d: cam_simq_alloc failure!\n", unit); 3742f1c579b1SScott Long return ENXIO; 3743f1c579b1SScott Long } 374444f05562SScott Long #if __FreeBSD_version >= 700025 3745d74001adSXin LI acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, &acb->qbuffer_lock, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq); 374644f05562SScott Long #else 3747d74001adSXin LI acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq); 374844f05562SScott Long #endif 3749ad6d6297SScott Long if(acb->psim == NULL) { 3750ad6d6297SScott Long arcmsr_free_resource(acb); 3751ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 3752f1c579b1SScott Long cam_simq_free(devq); 37535878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3754ad6d6297SScott Long printf("arcmsr%d: cam_sim_alloc failure!\n", unit); 3755f1c579b1SScott Long return ENXIO; 3756f1c579b1SScott Long } 37575878cbecSScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 3758f40b4cabSScott Long #if __FreeBSD_version >= 700044 3759b50569b7SScott Long if(xpt_bus_register(acb->psim, dev, 0) != CAM_SUCCESS) { 376044f05562SScott Long #else 376144f05562SScott Long if(xpt_bus_register(acb->psim, 0) != CAM_SUCCESS) { 376244f05562SScott Long #endif 3763ad6d6297SScott Long arcmsr_free_resource(acb); 3764ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 3765ad6d6297SScott Long cam_sim_free(acb->psim, /*free_devq*/TRUE); 37665878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3767ad6d6297SScott Long printf("arcmsr%d: xpt_bus_register failure!\n", unit); 3768f1c579b1SScott Long return ENXIO; 3769f1c579b1SScott Long } 3770d74001adSXin LI if(xpt_create_path(&acb->ppath, /* periph */ NULL, cam_sim_path(acb->psim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 3771ad6d6297SScott Long arcmsr_free_resource(acb); 3772ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 3773ad6d6297SScott Long xpt_bus_deregister(cam_sim_path(acb->psim)); 3774ad6d6297SScott Long cam_sim_free(acb->psim, /* free_simq */ TRUE); 37755878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3776ad6d6297SScott Long printf("arcmsr%d: xpt_create_path failure!\n", unit); 3777f1c579b1SScott Long return ENXIO; 3778f1c579b1SScott Long } 3779f1c579b1SScott Long /* 3780f1c579b1SScott Long **************************************************** 3781f1c579b1SScott Long */ 3782ad6d6297SScott Long xpt_setup_ccb(&csa.ccb_h, acb->ppath, /*priority*/5); 3783f1c579b1SScott Long csa.ccb_h.func_code=XPT_SASYNC_CB; 3784f1c579b1SScott Long csa.event_enable=AC_FOUND_DEVICE|AC_LOST_DEVICE; 3785f1c579b1SScott Long csa.callback=arcmsr_async; 3786ad6d6297SScott Long csa.callback_arg=acb->psim; 3787f1c579b1SScott Long xpt_action((union ccb *)&csa); 37885878cbecSScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 3789f1c579b1SScott Long /* Create the control device. */ 3790d74001adSXin LI acb->ioctl_dev=make_dev(&arcmsr_cdevsw, unit, UID_ROOT, GID_WHEEL /* GID_OPERATOR */, S_IRUSR | S_IWUSR, "arcmsr%d", unit); 3791d74001adSXin LI 3792f1c579b1SScott Long #if __FreeBSD_version < 503000 3793ad6d6297SScott Long acb->ioctl_dev->si_drv1=acb; 3794f1c579b1SScott Long #endif 3795f1c579b1SScott Long #if __FreeBSD_version > 500005 3796ad6d6297SScott Long (void)make_dev_alias(acb->ioctl_dev, "arc%d", unit); 3797f1c579b1SScott Long #endif 379822f2616bSXin LI arcmsr_callout_init(&acb->devmap_callout); 3799d74001adSXin LI callout_reset(&acb->devmap_callout, 60 * hz, arcmsr_polling_devmap, acb); 3800dac36688SXin LI return (0); 3801f1c579b1SScott Long } 380222f2616bSXin LI 3803f1c579b1SScott Long /* 3804f1c579b1SScott Long ************************************************************************ 3805f1c579b1SScott Long ************************************************************************ 3806f1c579b1SScott Long */ 3807f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev) 3808f1c579b1SScott Long { 3809ad6d6297SScott Long u_int32_t id; 3810ad6d6297SScott Long static char buf[256]; 3811231c8b71SXin LI char x_type[]={"X-TYPE"}; 3812ad6d6297SScott Long char *type; 3813ad6d6297SScott Long int raid6 = 1; 3814ad6d6297SScott Long 3815ad6d6297SScott Long if (pci_get_vendor(dev) != PCI_VENDOR_ID_ARECA) { 3816ad6d6297SScott Long return (ENXIO); 3817ad6d6297SScott Long } 3818ad6d6297SScott Long switch(id=pci_get_devid(dev)) { 3819f1c579b1SScott Long case PCIDevVenIDARC1110: 3820231c8b71SXin LI case PCIDevVenIDARC1200: 382144f05562SScott Long case PCIDevVenIDARC1201: 3822231c8b71SXin LI case PCIDevVenIDARC1210: 3823ad6d6297SScott Long raid6 = 0; 3824ad6d6297SScott Long /*FALLTHRU*/ 3825ad6d6297SScott Long case PCIDevVenIDARC1120: 3826ad6d6297SScott Long case PCIDevVenIDARC1130: 3827ad6d6297SScott Long case PCIDevVenIDARC1160: 3828ad6d6297SScott Long case PCIDevVenIDARC1170: 3829f1c579b1SScott Long case PCIDevVenIDARC1220: 3830f1c579b1SScott Long case PCIDevVenIDARC1230: 3831231c8b71SXin LI case PCIDevVenIDARC1231: 3832f1c579b1SScott Long case PCIDevVenIDARC1260: 3833231c8b71SXin LI case PCIDevVenIDARC1261: 3834ad6d6297SScott Long case PCIDevVenIDARC1270: 3835ad6d6297SScott Long case PCIDevVenIDARC1280: 3836ad6d6297SScott Long type = "SATA"; 3837ad6d6297SScott Long break; 3838d74001adSXin LI case PCIDevVenIDARC1212: 3839d74001adSXin LI case PCIDevVenIDARC1222: 3840ad6d6297SScott Long case PCIDevVenIDARC1380: 3841ad6d6297SScott Long case PCIDevVenIDARC1381: 3842ad6d6297SScott Long case PCIDevVenIDARC1680: 3843ad6d6297SScott Long case PCIDevVenIDARC1681: 3844d74001adSXin LI type = "SAS 3G"; 3845d74001adSXin LI break; 3846d74001adSXin LI case PCIDevVenIDARC1880: 3847dac36688SXin LI case PCIDevVenIDARC1882: 3848dac36688SXin LI case PCIDevVenIDARC1213: 3849dac36688SXin LI case PCIDevVenIDARC1223: 3850d74001adSXin LI type = "SAS 6G"; 3851ad6d6297SScott Long break; 3852ad6d6297SScott Long default: 3853231c8b71SXin LI type = x_type; 3854ad6d6297SScott Long break; 3855f1c579b1SScott Long } 3856231c8b71SXin LI if(type == x_type) 3857231c8b71SXin LI return(ENXIO); 3858ad6d6297SScott Long sprintf(buf, "Areca %s Host Adapter RAID Controller %s\n", type, raid6 ? "(RAID6 capable)" : ""); 3859ad6d6297SScott Long device_set_desc_copy(dev, buf); 386003389298SXin LI return (BUS_PROBE_DEFAULT); 3861f1c579b1SScott Long } 3862f1c579b1SScott Long /* 3863f1c579b1SScott Long ************************************************************************ 3864f1c579b1SScott Long ************************************************************************ 3865f1c579b1SScott Long */ 3866f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev) 3867f1c579b1SScott Long { 386844f05562SScott Long u_int32_t i; 3869ad6d6297SScott Long u_int32_t intmask_org; 3870ad6d6297SScott Long struct CommandControlBlock *srb; 3871ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 3872f1c579b1SScott Long 3873f1c579b1SScott Long /* stop adapter background rebuild */ 38745878cbecSScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 387544f05562SScott Long /* disable all outbound interrupt */ 387644f05562SScott Long intmask_org=arcmsr_disable_allintr(acb); 3877ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 3878ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 3879f1c579b1SScott Long /* abort all outstanding command */ 3880ad6d6297SScott Long acb->acb_flags |= ACB_F_SCSISTOPADAPTER; 3881ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOP_INITED; 3882ad6d6297SScott Long if(acb->srboutstandingcount!=0) { 388344f05562SScott Long /*clear and abort all outbound posted Q*/ 388444f05562SScott Long arcmsr_done4abort_postqueue(acb); 388544f05562SScott Long /* talk to iop 331 outstanding command aborted*/ 3886ad6d6297SScott Long arcmsr_abort_allcmd(acb); 3887ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 3888ad6d6297SScott Long srb=acb->psrb_pool[i]; 388922f2616bSXin LI if(srb->srb_state==ARCMSR_SRB_START) { 389022f2616bSXin LI srb->srb_state=ARCMSR_SRB_ABORTED; 3891ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 3892ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 3893f1c579b1SScott Long } 3894f1c579b1SScott Long } 3895f1c579b1SScott Long } 389622f2616bSXin LI acb->srboutstandingcount=0; 3897ad6d6297SScott Long acb->workingsrb_doneindex=0; 3898ad6d6297SScott Long acb->workingsrb_startindex=0; 389922f2616bSXin LI #ifdef ARCMSR_DEBUG1 390022f2616bSXin LI acb->pktRequestCount = 0; 390122f2616bSXin LI acb->pktReturnCount = 0; 390222f2616bSXin LI #endif 39035878cbecSScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 3904f2aa0e9fSWarner Losh return (0); 3905f1c579b1SScott Long } 3906f1c579b1SScott Long /* 3907f1c579b1SScott Long ************************************************************************ 3908f1c579b1SScott Long ************************************************************************ 3909f1c579b1SScott Long */ 3910f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev) 3911f1c579b1SScott Long { 3912ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 391344f05562SScott Long int i; 3914f1c579b1SScott Long 3915d74001adSXin LI callout_stop(&acb->devmap_callout); 39165878cbecSScott Long bus_teardown_intr(dev, acb->irqres, acb->ih); 3917f1c579b1SScott Long arcmsr_shutdown(dev); 3918ad6d6297SScott Long arcmsr_free_resource(acb); 391944f05562SScott Long for(i=0; (acb->sys_res_arcmsr[i]!=NULL) && (i<2); i++) { 392044f05562SScott Long bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(i), acb->sys_res_arcmsr[i]); 392144f05562SScott Long } 3922ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 39235878cbecSScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 3924ad6d6297SScott Long xpt_async(AC_LOST_DEVICE, acb->ppath, NULL); 3925ad6d6297SScott Long xpt_free_path(acb->ppath); 3926ad6d6297SScott Long xpt_bus_deregister(cam_sim_path(acb->psim)); 3927ad6d6297SScott Long cam_sim_free(acb->psim, TRUE); 39285878cbecSScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 39295878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3930f1c579b1SScott Long return (0); 3931f1c579b1SScott Long } 3932f1c579b1SScott Long 393322f2616bSXin LI #ifdef ARCMSR_DEBUG1 393422f2616bSXin LI static void arcmsr_dump_data(struct AdapterControlBlock *acb) 393522f2616bSXin LI { 393622f2616bSXin LI if((acb->pktRequestCount - acb->pktReturnCount) == 0) 393722f2616bSXin LI return; 393822f2616bSXin LI printf("Command Request Count =0x%x\n",acb->pktRequestCount); 393922f2616bSXin LI printf("Command Return Count =0x%x\n",acb->pktReturnCount); 394022f2616bSXin LI printf("Command (Req-Rtn) Count =0x%x\n",(acb->pktRequestCount - acb->pktReturnCount)); 394122f2616bSXin LI printf("Queued Command Count =0x%x\n",acb->srboutstandingcount); 394222f2616bSXin LI } 394322f2616bSXin LI #endif 3944f1c579b1SScott Long 3945