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 72f1c579b1SScott Long ****************************************************************************************** 73f1c579b1SScott Long */ 74*4b7ec270SMarius Strobl 75*4b7ec270SMarius Strobl #include <sys/cdefs.h> 76*4b7ec270SMarius Strobl __FBSDID("$FreeBSD$"); 77*4b7ec270SMarius Strobl 7822f2616bSXin LI #if 0 7922f2616bSXin LI #define ARCMSR_DEBUG1 1 8022f2616bSXin LI #endif 81f1c579b1SScott Long #include <sys/param.h> 82f1c579b1SScott Long #include <sys/systm.h> 83f1c579b1SScott Long #include <sys/malloc.h> 84f1c579b1SScott Long #include <sys/kernel.h> 85f1c579b1SScott Long #include <sys/bus.h> 86f1c579b1SScott Long #include <sys/queue.h> 87f1c579b1SScott Long #include <sys/stat.h> 88f1c579b1SScott Long #include <sys/devicestat.h> 89f1c579b1SScott Long #include <sys/kthread.h> 90f1c579b1SScott Long #include <sys/module.h> 91f1c579b1SScott Long #include <sys/proc.h> 92f1c579b1SScott Long #include <sys/lock.h> 93f1c579b1SScott Long #include <sys/sysctl.h> 94f1c579b1SScott Long #include <sys/poll.h> 95f1c579b1SScott Long #include <sys/ioccom.h> 96f1c579b1SScott Long #include <vm/vm.h> 97f1c579b1SScott Long #include <vm/vm_param.h> 98f1c579b1SScott Long #include <vm/pmap.h> 99f1c579b1SScott Long 100f1c579b1SScott Long #include <isa/rtc.h> 101f1c579b1SScott Long 102f1c579b1SScott Long #include <machine/bus.h> 103f1c579b1SScott Long #include <machine/resource.h> 104f1c579b1SScott Long #include <machine/atomic.h> 105f1c579b1SScott Long #include <sys/conf.h> 106f1c579b1SScott Long #include <sys/rman.h> 107f1c579b1SScott Long 108f1c579b1SScott Long #include <cam/cam.h> 109f1c579b1SScott Long #include <cam/cam_ccb.h> 110f1c579b1SScott Long #include <cam/cam_sim.h> 111d74001adSXin LI #include <cam/cam_periph.h> 112d74001adSXin LI #include <cam/cam_xpt_periph.h> 113f1c579b1SScott Long #include <cam/cam_xpt_sim.h> 114f1c579b1SScott Long #include <cam/cam_debug.h> 115f1c579b1SScott Long #include <cam/scsi/scsi_all.h> 116f1c579b1SScott Long #include <cam/scsi/scsi_message.h> 117f1c579b1SScott Long /* 118f1c579b1SScott Long ************************************************************************** 119f1c579b1SScott Long ************************************************************************** 120f1c579b1SScott Long */ 121f1c579b1SScott Long #if __FreeBSD_version >= 500005 122f1c579b1SScott Long #include <sys/selinfo.h> 123f1c579b1SScott Long #include <sys/mutex.h> 124ad6d6297SScott Long #include <sys/endian.h> 125f1c579b1SScott Long #include <dev/pci/pcivar.h> 126f1c579b1SScott Long #include <dev/pci/pcireg.h> 127579ec1a5SScott Long #define ARCMSR_LOCK_INIT(l, s) mtx_init(l, s, NULL, MTX_DEF) 1285878cbecSScott Long #define ARCMSR_LOCK_DESTROY(l) mtx_destroy(l) 129f1c579b1SScott Long #define ARCMSR_LOCK_ACQUIRE(l) mtx_lock(l) 130f1c579b1SScott Long #define ARCMSR_LOCK_RELEASE(l) mtx_unlock(l) 131ad6d6297SScott Long #define ARCMSR_LOCK_TRY(l) mtx_trylock(l) 132ad6d6297SScott Long #define arcmsr_htole32(x) htole32(x) 133f1c579b1SScott Long typedef struct mtx arcmsr_lock_t; 134f1c579b1SScott Long #else 135f1c579b1SScott Long #include <sys/select.h> 136f1c579b1SScott Long #include <pci/pcivar.h> 137f1c579b1SScott Long #include <pci/pcireg.h> 138f1c579b1SScott Long #define ARCMSR_LOCK_INIT(l, s) simple_lock_init(l) 1395878cbecSScott Long #define ARCMSR_LOCK_DESTROY(l) 140f1c579b1SScott Long #define ARCMSR_LOCK_ACQUIRE(l) simple_lock(l) 141f1c579b1SScott Long #define ARCMSR_LOCK_RELEASE(l) simple_unlock(l) 142ad6d6297SScott Long #define ARCMSR_LOCK_TRY(l) simple_lock_try(l) 143ad6d6297SScott Long #define arcmsr_htole32(x) (x) 144f1c579b1SScott Long typedef struct simplelock arcmsr_lock_t; 145f1c579b1SScott Long #endif 14644f05562SScott Long 14744f05562SScott Long #if !defined(CAM_NEW_TRAN_CODE) && __FreeBSD_version >= 700025 14844f05562SScott Long #define CAM_NEW_TRAN_CODE 1 14944f05562SScott Long #endif 15044f05562SScott Long 15122f2616bSXin LI #if __FreeBSD_version > 500000 15222f2616bSXin LI #define arcmsr_callout_init(a) callout_init(a, /*mpsafe*/1); 15322f2616bSXin LI #else 15422f2616bSXin LI #define arcmsr_callout_init(a) callout_init(a); 15522f2616bSXin LI #endif 15622f2616bSXin LI 1574e32649fSXin LI #define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.22 2011-07-04" 158f1c579b1SScott Long #include <dev/arcmsr/arcmsr.h> 15922f2616bSXin LI #define SRB_SIZE ((sizeof(struct CommandControlBlock)+0x1f) & 0xffe0) 16022f2616bSXin LI #define ARCMSR_SRBS_POOL_SIZE (SRB_SIZE * ARCMSR_MAX_FREESRB_NUM) 161f1c579b1SScott Long /* 162f1c579b1SScott Long ************************************************************************** 163f1c579b1SScott Long ************************************************************************** 164f1c579b1SScott Long */ 16544f05562SScott Long #define CHIP_REG_READ32(s, b, r) bus_space_read_4(acb->btag[b], acb->bhandle[b], offsetof(struct s, r)) 16644f05562SScott Long #define CHIP_REG_WRITE32(s, b, r, d) bus_space_write_4(acb->btag[b], acb->bhandle[b], offsetof(struct s, r), d) 167f1c579b1SScott Long /* 168f1c579b1SScott Long ************************************************************************** 169f1c579b1SScott Long ************************************************************************** 170f1c579b1SScott Long */ 17122f2616bSXin LI static void arcmsr_free_srb(struct CommandControlBlock *srb); 172ad6d6297SScott Long static struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb); 173ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb); 174f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev); 175f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev); 176f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev); 177ad6d6297SScott Long static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg); 178ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb); 179f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev); 18044f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb); 181ad6d6297SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb); 182ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb); 183ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb); 184ad6d6297SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); 185ad6d6297SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb); 186ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb); 187ad6d6297SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb); 18844f05562SScott Long static void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb); 189ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb); 190ad6d6297SScott Long static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag); 191ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb); 192ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb); 193ad6d6297SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t * dm_segs, u_int32_t nseg); 194ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb); 195ad6d6297SScott Long static int arcmsr_resume(device_t dev); 196ad6d6297SScott Long static int arcmsr_suspend(device_t dev); 197d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb); 198d74001adSXin LI static void arcmsr_polling_devmap(void* arg); 19922f2616bSXin LI static void arcmsr_srb_timeout(void* arg); 20022f2616bSXin LI #ifdef ARCMSR_DEBUG1 20122f2616bSXin LI static void arcmsr_dump_data(struct AdapterControlBlock *acb); 20222f2616bSXin LI #endif 203f1c579b1SScott Long /* 204f1c579b1SScott Long ************************************************************************** 205ad6d6297SScott Long ************************************************************************** 206ad6d6297SScott Long */ 207ad6d6297SScott Long static void UDELAY(u_int32_t us) { DELAY(us); } 208ad6d6297SScott Long /* 209ad6d6297SScott Long ************************************************************************** 210f1c579b1SScott Long ************************************************************************** 211f1c579b1SScott Long */ 212231c8b71SXin LI static bus_dmamap_callback_t arcmsr_map_free_srb; 213231c8b71SXin LI static bus_dmamap_callback_t arcmsr_execute_srb; 214f1c579b1SScott Long /* 215f1c579b1SScott Long ************************************************************************** 216f1c579b1SScott Long ************************************************************************** 217f1c579b1SScott Long */ 218f1c579b1SScott Long static d_open_t arcmsr_open; 219f1c579b1SScott Long static d_close_t arcmsr_close; 220f1c579b1SScott Long static d_ioctl_t arcmsr_ioctl; 221f1c579b1SScott Long 222f1c579b1SScott Long static device_method_t arcmsr_methods[]={ 223f1c579b1SScott Long DEVMETHOD(device_probe, arcmsr_probe), 224f1c579b1SScott Long DEVMETHOD(device_attach, arcmsr_attach), 225f1c579b1SScott Long DEVMETHOD(device_detach, arcmsr_detach), 226f1c579b1SScott Long DEVMETHOD(device_shutdown, arcmsr_shutdown), 227ad6d6297SScott Long DEVMETHOD(device_suspend, arcmsr_suspend), 228ad6d6297SScott Long DEVMETHOD(device_resume, arcmsr_resume), 229*4b7ec270SMarius Strobl 230*4b7ec270SMarius Strobl DEVMETHOD_END 231f1c579b1SScott Long }; 232f1c579b1SScott Long 233f1c579b1SScott Long static driver_t arcmsr_driver={ 234ad6d6297SScott Long "arcmsr", arcmsr_methods, sizeof(struct AdapterControlBlock) 235f1c579b1SScott Long }; 236f1c579b1SScott Long 237f1c579b1SScott Long static devclass_t arcmsr_devclass; 238f1c579b1SScott Long DRIVER_MODULE(arcmsr, pci, arcmsr_driver, arcmsr_devclass, 0, 0); 239d3cf342dSScott Long MODULE_DEPEND(arcmsr, pci, 1, 1, 1); 240d3cf342dSScott Long MODULE_DEPEND(arcmsr, cam, 1, 1, 1); 241ad6d6297SScott Long #ifndef BUS_DMA_COHERENT 242ad6d6297SScott Long #define BUS_DMA_COHERENT 0x04 /* hint: map memory in a coherent way */ 243ad6d6297SScott Long #endif 244ad6d6297SScott Long #if __FreeBSD_version >= 501000 245f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw={ 24622f2616bSXin LI #if __FreeBSD_version >= 503000 247f1c579b1SScott Long .d_version = D_VERSION, 248ad6d6297SScott Long #endif 24922f2616bSXin LI #if (__FreeBSD_version>=503000 && __FreeBSD_version<600034) 250f1c579b1SScott Long .d_flags = D_NEEDGIANT, 25122f2616bSXin LI #endif 252f1c579b1SScott Long .d_open = arcmsr_open, /* open */ 253f1c579b1SScott Long .d_close = arcmsr_close, /* close */ 254f1c579b1SScott Long .d_ioctl = arcmsr_ioctl, /* ioctl */ 255f1c579b1SScott Long .d_name = "arcmsr", /* name */ 256f1c579b1SScott Long }; 257f1c579b1SScott Long #else 258f1c579b1SScott Long #define ARCMSR_CDEV_MAJOR 180 259f1c579b1SScott Long 260f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw = { 261f1c579b1SScott Long arcmsr_open, /* open */ 262f1c579b1SScott Long arcmsr_close, /* close */ 263f1c579b1SScott Long noread, /* read */ 264f1c579b1SScott Long nowrite, /* write */ 265f1c579b1SScott Long arcmsr_ioctl, /* ioctl */ 266f1c579b1SScott Long nopoll, /* poll */ 267f1c579b1SScott Long nommap, /* mmap */ 268f1c579b1SScott Long nostrategy, /* strategy */ 269f1c579b1SScott Long "arcmsr", /* name */ 270f1c579b1SScott Long ARCMSR_CDEV_MAJOR, /* major */ 271f1c579b1SScott Long nodump, /* dump */ 272f1c579b1SScott Long nopsize, /* psize */ 273f1c579b1SScott Long 0 /* flags */ 274f1c579b1SScott Long }; 275f1c579b1SScott Long #endif 276d74001adSXin LI /* 277d74001adSXin LI ************************************************************************** 278d74001adSXin LI ************************************************************************** 279d74001adSXin LI */ 280f1c579b1SScott Long #if __FreeBSD_version < 500005 281f1c579b1SScott Long static int arcmsr_open(dev_t dev, int flags, int fmt, struct proc *proc) 282f1c579b1SScott Long #else 283f1c579b1SScott Long #if __FreeBSD_version < 503000 284f1c579b1SScott Long static int arcmsr_open(dev_t dev, int flags, int fmt, struct thread *proc) 285f1c579b1SScott Long #else 28600b4e54aSWarner Losh static int arcmsr_open(struct cdev *dev, int flags, int fmt, struct thread *proc) 287f1c579b1SScott Long #endif 288f1c579b1SScott Long #endif 289f1c579b1SScott Long { 290f1c579b1SScott Long #if __FreeBSD_version < 503000 291ad6d6297SScott Long struct AdapterControlBlock *acb=dev->si_drv1; 292f1c579b1SScott Long #else 2936bfa9a2dSEd Schouten int unit = dev2unit(dev); 294ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 295f1c579b1SScott Long #endif 296ad6d6297SScott Long if(acb==NULL) { 297f1c579b1SScott Long return ENXIO; 298f1c579b1SScott Long } 299f1c579b1SScott Long return 0; 300f1c579b1SScott Long } 301f1c579b1SScott Long /* 302f1c579b1SScott Long ************************************************************************** 303f1c579b1SScott Long ************************************************************************** 304f1c579b1SScott Long */ 305f1c579b1SScott Long #if __FreeBSD_version < 500005 306f1c579b1SScott Long static int arcmsr_close(dev_t dev, int flags, int fmt, struct proc *proc) 307f1c579b1SScott Long #else 308f1c579b1SScott Long #if __FreeBSD_version < 503000 309f1c579b1SScott Long static int arcmsr_close(dev_t dev, int flags, int fmt, struct thread *proc) 310f1c579b1SScott Long #else 31100b4e54aSWarner Losh static int arcmsr_close(struct cdev *dev, int flags, int fmt, struct thread *proc) 312f1c579b1SScott Long #endif 313f1c579b1SScott Long #endif 314f1c579b1SScott Long { 315f1c579b1SScott Long #if __FreeBSD_version < 503000 316ad6d6297SScott Long struct AdapterControlBlock *acb=dev->si_drv1; 317f1c579b1SScott Long #else 3186bfa9a2dSEd Schouten int unit = dev2unit(dev); 319ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 320f1c579b1SScott Long #endif 321ad6d6297SScott Long if(acb==NULL) { 322f1c579b1SScott Long return ENXIO; 323f1c579b1SScott Long } 324f1c579b1SScott Long return 0; 325f1c579b1SScott Long } 326f1c579b1SScott Long /* 327f1c579b1SScott Long ************************************************************************** 328f1c579b1SScott Long ************************************************************************** 329f1c579b1SScott Long */ 330f1c579b1SScott Long #if __FreeBSD_version < 500005 331f1c579b1SScott Long static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct proc *proc) 332f1c579b1SScott Long #else 333f1c579b1SScott Long #if __FreeBSD_version < 503000 334f1c579b1SScott Long static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc) 335f1c579b1SScott Long #else 33600b4e54aSWarner Losh static int arcmsr_ioctl(struct cdev *dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc) 337f1c579b1SScott Long #endif 338f1c579b1SScott Long #endif 339f1c579b1SScott Long { 340f1c579b1SScott Long #if __FreeBSD_version < 503000 341ad6d6297SScott Long struct AdapterControlBlock *acb=dev->si_drv1; 342f1c579b1SScott Long #else 3436bfa9a2dSEd Schouten int unit = dev2unit(dev); 344ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 345f1c579b1SScott Long #endif 346f1c579b1SScott Long 347ad6d6297SScott Long if(acb==NULL) { 348f1c579b1SScott Long return ENXIO; 349f1c579b1SScott Long } 350ad6d6297SScott Long return(arcmsr_iop_ioctlcmd(acb, ioctl_cmd, arg)); 351f1c579b1SScott Long } 352f1c579b1SScott Long /* 35344f05562SScott Long ********************************************************************** 35444f05562SScott Long ********************************************************************** 35544f05562SScott Long */ 35644f05562SScott Long static u_int32_t arcmsr_disable_allintr( struct AdapterControlBlock *acb) 35744f05562SScott Long { 35844f05562SScott Long u_int32_t intmask_org=0; 35944f05562SScott Long 36044f05562SScott Long switch (acb->adapter_type) { 36144f05562SScott Long case ACB_ADAPTER_TYPE_A: { 36244f05562SScott Long /* disable all outbound interrupt */ 363d74001adSXin LI intmask_org=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intmask); /* disable outbound message0 int */ 364d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); 36544f05562SScott Long } 36644f05562SScott Long break; 36744f05562SScott Long case ACB_ADAPTER_TYPE_B: { 36844f05562SScott Long /* disable all outbound interrupt */ 36944f05562SScott Long intmask_org=CHIP_REG_READ32(HBB_DOORBELL, 37044f05562SScott Long 0, iop2drv_doorbell_mask) & (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); /* disable outbound message0 int */ 371d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell_mask, 0); /* disable all interrupt */ 372d74001adSXin LI } 373d74001adSXin LI break; 374d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 375d74001adSXin LI /* disable all outbound interrupt */ 376d74001adSXin LI intmask_org=CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_mask) ; /* disable outbound message0 int */ 377d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org|ARCMSR_HBCMU_ALL_INTMASKENABLE); 37844f05562SScott Long } 37944f05562SScott Long break; 38044f05562SScott Long } 38144f05562SScott Long return(intmask_org); 38244f05562SScott Long } 38344f05562SScott Long /* 38444f05562SScott Long ********************************************************************** 38544f05562SScott Long ********************************************************************** 38644f05562SScott Long */ 38744f05562SScott Long static void arcmsr_enable_allintr( struct AdapterControlBlock *acb, u_int32_t intmask_org) 38844f05562SScott Long { 38944f05562SScott Long u_int32_t mask; 39044f05562SScott Long 39144f05562SScott Long switch (acb->adapter_type) { 39244f05562SScott Long case ACB_ADAPTER_TYPE_A: { 39344f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 394d74001adSXin LI mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE); 39544f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org & mask); 39644f05562SScott Long acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; 39744f05562SScott Long } 39844f05562SScott Long break; 39944f05562SScott Long case ACB_ADAPTER_TYPE_B: { 400d74001adSXin LI /* enable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */ 401d74001adSXin LI mask=(ARCMSR_IOP2DRV_DATA_WRITE_OK|ARCMSR_IOP2DRV_DATA_READ_OK|ARCMSR_IOP2DRV_CDB_DONE|ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); 402d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell_mask, intmask_org | mask); /*1=interrupt enable, 0=interrupt disable*/ 40344f05562SScott Long acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f; 40444f05562SScott Long } 40544f05562SScott Long break; 406d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 407d74001adSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 408d74001adSXin LI mask=~(ARCMSR_HBCMU_UTILITY_A_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK); 409d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org & mask); 410d74001adSXin LI acb->outbound_int_enable= ~(intmask_org & mask) & 0x0000000f; 411d74001adSXin LI } 412d74001adSXin LI break; 41344f05562SScott Long } 41444f05562SScott Long return; 41544f05562SScott Long } 41644f05562SScott Long /* 41744f05562SScott Long ********************************************************************** 41844f05562SScott Long ********************************************************************** 41944f05562SScott Long */ 42044f05562SScott Long static u_int8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) 42144f05562SScott Long { 42244f05562SScott Long u_int32_t Index; 42344f05562SScott Long u_int8_t Retries=0x00; 42444f05562SScott Long 42544f05562SScott Long do { 42644f05562SScott Long for(Index=0; Index < 100; Index++) { 427d74001adSXin LI if(CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { 428d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/ 42944f05562SScott Long return TRUE; 43044f05562SScott Long } 43144f05562SScott Long UDELAY(10000); 43244f05562SScott Long }/*max 1 seconds*/ 43344f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 43444f05562SScott Long return FALSE; 43544f05562SScott Long } 43644f05562SScott Long /* 43744f05562SScott Long ********************************************************************** 43844f05562SScott Long ********************************************************************** 43944f05562SScott Long */ 44044f05562SScott Long static u_int8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) 44144f05562SScott Long { 44244f05562SScott Long u_int32_t Index; 44344f05562SScott Long u_int8_t Retries=0x00; 44444f05562SScott Long 44544f05562SScott Long do { 44644f05562SScott Long for(Index=0; Index < 100; Index++) { 447d74001adSXin LI if(CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { 448d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/ 449d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 450d74001adSXin LI return TRUE; 451d74001adSXin LI } 452d74001adSXin LI UDELAY(10000); 453d74001adSXin LI }/*max 1 seconds*/ 454d74001adSXin LI }while(Retries++ < 20);/*max 20 sec*/ 455d74001adSXin LI return FALSE; 456d74001adSXin LI } 457d74001adSXin LI /* 458d74001adSXin LI ********************************************************************** 459d74001adSXin LI ********************************************************************** 460d74001adSXin LI */ 461d74001adSXin LI static u_int8_t arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock *acb) 462d74001adSXin LI { 463d74001adSXin LI u_int32_t Index; 464d74001adSXin LI u_int8_t Retries=0x00; 465d74001adSXin LI 466d74001adSXin LI do { 467d74001adSXin LI for(Index=0; Index < 100; Index++) { 468d74001adSXin LI if(CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { 469d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);/*clear interrupt*/ 47044f05562SScott Long return TRUE; 47144f05562SScott Long } 47244f05562SScott Long UDELAY(10000); 47344f05562SScott Long }/*max 1 seconds*/ 47444f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 47544f05562SScott Long return FALSE; 47644f05562SScott Long } 47744f05562SScott Long /* 47844f05562SScott Long ************************************************************************ 47944f05562SScott Long ************************************************************************ 48044f05562SScott Long */ 48144f05562SScott Long static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) 48244f05562SScott Long { 48344f05562SScott Long int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */ 48444f05562SScott Long 485d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 48644f05562SScott Long do { 48744f05562SScott Long if(arcmsr_hba_wait_msgint_ready(acb)) { 48844f05562SScott Long break; 48944f05562SScott Long } else { 49044f05562SScott Long retry_count--; 49144f05562SScott Long } 49244f05562SScott Long }while(retry_count!=0); 49344f05562SScott Long return; 49444f05562SScott Long } 49544f05562SScott Long /* 49644f05562SScott Long ************************************************************************ 49744f05562SScott Long ************************************************************************ 49844f05562SScott Long */ 49944f05562SScott Long static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) 50044f05562SScott Long { 50144f05562SScott Long int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */ 50244f05562SScott Long 50344f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 50444f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_FLUSH_CACHE); 50544f05562SScott Long do { 50644f05562SScott Long if(arcmsr_hbb_wait_msgint_ready(acb)) { 50744f05562SScott Long break; 50844f05562SScott Long } else { 50944f05562SScott Long retry_count--; 51044f05562SScott Long } 51144f05562SScott Long }while(retry_count!=0); 51244f05562SScott Long return; 51344f05562SScott Long } 51444f05562SScott Long /* 51544f05562SScott Long ************************************************************************ 51644f05562SScott Long ************************************************************************ 51744f05562SScott Long */ 518d74001adSXin LI static void arcmsr_flush_hbc_cache(struct AdapterControlBlock *acb) 519d74001adSXin LI { 520d74001adSXin LI int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */ 521d74001adSXin LI 522d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 523d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 524d74001adSXin LI do { 525d74001adSXin LI if(arcmsr_hbc_wait_msgint_ready(acb)) { 526d74001adSXin LI break; 527d74001adSXin LI } else { 528d74001adSXin LI retry_count--; 529d74001adSXin LI } 530d74001adSXin LI }while(retry_count!=0); 531d74001adSXin LI return; 532d74001adSXin LI } 533d74001adSXin LI /* 534d74001adSXin LI ************************************************************************ 535d74001adSXin LI ************************************************************************ 536d74001adSXin LI */ 53744f05562SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) 53844f05562SScott Long { 53944f05562SScott Long switch (acb->adapter_type) { 54044f05562SScott Long case ACB_ADAPTER_TYPE_A: { 54144f05562SScott Long arcmsr_flush_hba_cache(acb); 54244f05562SScott Long } 54344f05562SScott Long break; 54444f05562SScott Long case ACB_ADAPTER_TYPE_B: { 54544f05562SScott Long arcmsr_flush_hbb_cache(acb); 54644f05562SScott Long } 54744f05562SScott Long break; 548d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 549d74001adSXin LI arcmsr_flush_hbc_cache(acb); 550d74001adSXin LI } 551d74001adSXin LI break; 55244f05562SScott Long } 55344f05562SScott Long return; 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 } 599d74001adSXin 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; 615ad6d6297SScott Long if(&pccb->csio.sense_data) { 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 return; 623f1c579b1SScott Long } 624f1c579b1SScott Long /* 625f1c579b1SScott Long ********************************************************************* 62644f05562SScott Long ********************************************************************* 62744f05562SScott Long */ 62844f05562SScott Long static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) 62944f05562SScott Long { 63044f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 63144f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 632d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 63344f05562SScott Long } 63444f05562SScott Long return; 63544f05562SScott Long } 63644f05562SScott Long /* 63744f05562SScott Long ********************************************************************* 63844f05562SScott Long ********************************************************************* 63944f05562SScott Long */ 64044f05562SScott Long static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) 64144f05562SScott Long { 64244f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_ABORT_CMD); 64344f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 644d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 645d74001adSXin LI } 646d74001adSXin LI return; 647d74001adSXin LI } 648d74001adSXin LI /* 649d74001adSXin LI ********************************************************************* 650d74001adSXin LI ********************************************************************* 651d74001adSXin LI */ 652d74001adSXin LI static void arcmsr_abort_hbc_allcmd(struct AdapterControlBlock *acb) 653d74001adSXin LI { 654d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 655d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 656d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 657d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 65844f05562SScott Long } 65944f05562SScott Long return; 66044f05562SScott Long } 66144f05562SScott Long /* 66244f05562SScott Long ********************************************************************* 663f1c579b1SScott Long ********************************************************************* 664f1c579b1SScott Long */ 665ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) 666f1c579b1SScott Long { 66744f05562SScott Long switch (acb->adapter_type) { 66844f05562SScott Long case ACB_ADAPTER_TYPE_A: { 66944f05562SScott Long arcmsr_abort_hba_allcmd(acb); 67044f05562SScott Long } 67144f05562SScott Long break; 67244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 67344f05562SScott Long arcmsr_abort_hbb_allcmd(acb); 67444f05562SScott Long } 67544f05562SScott Long break; 676d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 677d74001adSXin LI arcmsr_abort_hbc_allcmd(acb); 678d74001adSXin LI } 679d74001adSXin LI break; 68044f05562SScott Long } 68144f05562SScott Long return; 68244f05562SScott Long } 68344f05562SScott Long /* 684231c8b71SXin LI ********************************************************************** 685231c8b71SXin LI ********************************************************************** 686231c8b71SXin LI */ 687231c8b71SXin LI static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag) 688231c8b71SXin LI { 689231c8b71SXin LI struct AdapterControlBlock *acb=srb->acb; 690231c8b71SXin LI union ccb * pccb=srb->pccb; 691231c8b71SXin LI 69222f2616bSXin LI if(srb->srb_flags & SRB_FLAG_TIMER_START) 69322f2616bSXin LI callout_stop(&srb->ccb_callout); 694231c8b71SXin LI if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 695231c8b71SXin LI bus_dmasync_op_t op; 696231c8b71SXin LI 697231c8b71SXin LI if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 698231c8b71SXin LI op = BUS_DMASYNC_POSTREAD; 699231c8b71SXin LI } else { 700231c8b71SXin LI op = BUS_DMASYNC_POSTWRITE; 701231c8b71SXin LI } 702231c8b71SXin LI bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 703231c8b71SXin LI bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 704231c8b71SXin LI } 705231c8b71SXin LI if(stand_flag==1) { 706231c8b71SXin LI atomic_subtract_int(&acb->srboutstandingcount, 1); 707231c8b71SXin LI if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) && ( 708231c8b71SXin LI acb->srboutstandingcount < ARCMSR_RELEASE_SIMQ_LEVEL)) { 709231c8b71SXin LI acb->acb_flags &= ~ACB_F_CAM_DEV_QFRZN; 710231c8b71SXin LI pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 711231c8b71SXin LI } 712231c8b71SXin LI } 71322f2616bSXin LI if(srb->srb_state != ARCMSR_SRB_TIMEOUT) 71422f2616bSXin LI arcmsr_free_srb(srb); 71522f2616bSXin LI #ifdef ARCMSR_DEBUG1 71622f2616bSXin LI acb->pktReturnCount++; 71722f2616bSXin LI #endif 718231c8b71SXin LI xpt_done(pccb); 719231c8b71SXin LI return; 720231c8b71SXin LI } 721231c8b71SXin LI /* 72244f05562SScott Long ************************************************************************** 72344f05562SScott Long ************************************************************************** 72444f05562SScott Long */ 725d74001adSXin LI static void arcmsr_report_srb_state(struct AdapterControlBlock *acb, struct CommandControlBlock *srb, u_int16_t error) 72644f05562SScott Long { 72744f05562SScott Long int target, lun; 72844f05562SScott Long 72944f05562SScott Long target=srb->pccb->ccb_h.target_id; 73044f05562SScott Long lun=srb->pccb->ccb_h.target_lun; 731d74001adSXin LI if(error == FALSE) { 73244f05562SScott Long if(acb->devstate[target][lun]==ARECA_RAID_GONE) { 73344f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GOOD; 73444f05562SScott Long } 73544f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_CMP; 73644f05562SScott Long arcmsr_srb_complete(srb, 1); 73744f05562SScott Long } else { 73844f05562SScott Long switch(srb->arcmsr_cdb.DeviceStatus) { 73944f05562SScott Long case ARCMSR_DEV_SELECT_TIMEOUT: { 74044f05562SScott Long if(acb->devstate[target][lun]==ARECA_RAID_GOOD) { 741d74001adSXin LI printf( "arcmsr%d: Target=%x, Lun=%x, selection timeout, raid volume was lost\n", acb->pci_unit, target, lun); 742ad6d6297SScott Long } 74344f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GONE; 744d74001adSXin LI srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 74544f05562SScott Long arcmsr_srb_complete(srb, 1); 74644f05562SScott Long } 74744f05562SScott Long break; 74844f05562SScott Long case ARCMSR_DEV_ABORTED: 74944f05562SScott Long case ARCMSR_DEV_INIT_FAIL: { 75044f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GONE; 75144f05562SScott Long srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 75244f05562SScott Long arcmsr_srb_complete(srb, 1); 75344f05562SScott Long } 75444f05562SScott Long break; 75544f05562SScott Long case SCSISTAT_CHECK_CONDITION: { 75644f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GOOD; 75744f05562SScott Long arcmsr_report_sense_info(srb); 75844f05562SScott Long arcmsr_srb_complete(srb, 1); 75944f05562SScott Long } 76044f05562SScott Long break; 76144f05562SScott Long default: 762d74001adSXin LI printf("arcmsr%d: scsi id=%d lun=%d isr got command error done,but got unknow DeviceStatus=0x%x \n" 763d74001adSXin LI , acb->pci_unit, target, lun ,srb->arcmsr_cdb.DeviceStatus); 76444f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GONE; 76544f05562SScott Long srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY; 76644f05562SScott Long /*unknow error or crc error just for retry*/ 76744f05562SScott Long arcmsr_srb_complete(srb, 1); 76844f05562SScott Long break; 76944f05562SScott Long } 77044f05562SScott Long } 77144f05562SScott Long return; 77244f05562SScott Long } 77344f05562SScott Long /* 77444f05562SScott Long ************************************************************************** 77544f05562SScott Long ************************************************************************** 77644f05562SScott Long */ 777d74001adSXin LI static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t flag_srb, u_int16_t error) 77844f05562SScott Long { 77944f05562SScott Long struct CommandControlBlock *srb; 78044f05562SScott Long 78144f05562SScott Long /* check if command done with no error*/ 782d74001adSXin LI switch (acb->adapter_type) { 783d74001adSXin LI case ACB_ADAPTER_TYPE_C: 78422f2616bSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/ 785d74001adSXin LI break; 786d74001adSXin LI case ACB_ADAPTER_TYPE_A: 787d74001adSXin LI case ACB_ADAPTER_TYPE_B: 788d74001adSXin LI default: 789d74001adSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 790d74001adSXin LI break; 791d74001adSXin LI } 79222f2616bSXin LI if((srb->acb!=acb) || (srb->srb_state!=ARCMSR_SRB_START)) { 79322f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_TIMEOUT) { 79422f2616bSXin LI arcmsr_free_srb(srb); 79522f2616bSXin LI printf("arcmsr%d: srb='%p' return srb has been timeouted\n", acb->pci_unit, srb); 79644f05562SScott Long return; 79744f05562SScott Long } 79822f2616bSXin LI printf("arcmsr%d: return srb has been completed\n" 79922f2616bSXin LI "srb='%p' srb_state=0x%x outstanding srb count=%d \n", 80022f2616bSXin LI acb->pci_unit, srb, srb->srb_state, acb->srboutstandingcount); 80144f05562SScott Long return; 80244f05562SScott Long } 803d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 80444f05562SScott Long return; 80544f05562SScott Long } 80644f05562SScott Long /* 80722f2616bSXin LI ************************************************************************** 80822f2616bSXin LI ************************************************************************** 80922f2616bSXin LI */ 81022f2616bSXin LI static void arcmsr_srb_timeout(void* arg) 81122f2616bSXin LI { 81222f2616bSXin LI struct CommandControlBlock *srb = (struct CommandControlBlock *)arg; 81322f2616bSXin LI struct AdapterControlBlock *acb; 81422f2616bSXin LI int target, lun; 81522f2616bSXin LI u_int8_t cmd; 81622f2616bSXin LI 81722f2616bSXin LI target=srb->pccb->ccb_h.target_id; 81822f2616bSXin LI lun=srb->pccb->ccb_h.target_lun; 81922f2616bSXin LI acb = srb->acb; 82022f2616bSXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 82122f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) 82222f2616bSXin LI { 82322f2616bSXin LI cmd = srb->pccb->csio.cdb_io.cdb_bytes[0]; 82422f2616bSXin LI srb->srb_state = ARCMSR_SRB_TIMEOUT; 82522f2616bSXin LI srb->pccb->ccb_h.status |= CAM_CMD_TIMEOUT; 82622f2616bSXin LI arcmsr_srb_complete(srb, 1); 82722f2616bSXin LI printf("arcmsr%d: scsi id %d lun %d cmd=0x%x srb='%p' ccb command time out!\n", 82822f2616bSXin LI acb->pci_unit, target, lun, cmd, srb); 82922f2616bSXin LI } 83022f2616bSXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 83122f2616bSXin LI #ifdef ARCMSR_DEBUG1 83222f2616bSXin LI arcmsr_dump_data(acb); 83322f2616bSXin LI #endif 83422f2616bSXin LI } 83522f2616bSXin LI 83622f2616bSXin LI /* 83744f05562SScott Long ********************************************************************** 83844f05562SScott Long ********************************************************************** 83944f05562SScott Long */ 84044f05562SScott Long static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) 84144f05562SScott Long { 84244f05562SScott Long int i=0; 84344f05562SScott Long u_int32_t flag_srb; 844d74001adSXin LI u_int16_t error; 84544f05562SScott Long 84644f05562SScott Long switch (acb->adapter_type) { 84744f05562SScott Long case ACB_ADAPTER_TYPE_A: { 84844f05562SScott Long u_int32_t outbound_intstatus; 84944f05562SScott Long 85044f05562SScott Long /*clear and abort all outbound posted Q*/ 851d74001adSXin LI outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 852d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/ 853d74001adSXin LI while(((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_queueport)) != 0xFFFFFFFF) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { 854d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 855d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 85644f05562SScott Long } 85744f05562SScott Long } 85844f05562SScott Long break; 85944f05562SScott Long case ACB_ADAPTER_TYPE_B: { 86044f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 86144f05562SScott Long 86244f05562SScott Long /*clear all outbound posted Q*/ 863d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 86444f05562SScott Long for(i=0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) { 86544f05562SScott Long if((flag_srb=phbbmu->done_qbuffer[i])!=0) { 86644f05562SScott Long phbbmu->done_qbuffer[i]=0; 867d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 868d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 86944f05562SScott Long } 87044f05562SScott Long phbbmu->post_qbuffer[i]=0; 87144f05562SScott Long }/*drain reply FIFO*/ 87244f05562SScott Long phbbmu->doneq_index=0; 87344f05562SScott Long phbbmu->postq_index=0; 87444f05562SScott Long } 87544f05562SScott Long break; 876d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 877d74001adSXin LI 878d74001adSXin LI while((CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { 879d74001adSXin LI flag_srb=CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 880d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; 881d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 882d74001adSXin LI } 883d74001adSXin LI } 884d74001adSXin LI break; 88544f05562SScott Long } 886f1c579b1SScott Long return; 887f1c579b1SScott Long } 888f1c579b1SScott Long /* 889f1c579b1SScott Long **************************************************************************** 890f1c579b1SScott Long **************************************************************************** 891f1c579b1SScott Long */ 892ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb) 893f1c579b1SScott Long { 894ad6d6297SScott Long struct CommandControlBlock *srb; 89544f05562SScott Long u_int32_t intmask_org; 896ad6d6297SScott Long u_int32_t i=0; 897f1c579b1SScott Long 89844f05562SScott Long if(acb->srboutstandingcount>0) { 89944f05562SScott Long /* disable all outbound interrupt */ 90044f05562SScott Long intmask_org=arcmsr_disable_allintr(acb); 90144f05562SScott Long /*clear and abort all outbound posted Q*/ 90244f05562SScott Long arcmsr_done4abort_postqueue(acb); 903f1c579b1SScott Long /* talk to iop 331 outstanding command aborted*/ 904ad6d6297SScott Long arcmsr_abort_allcmd(acb); 905ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 906ad6d6297SScott Long srb=acb->psrb_pool[i]; 90722f2616bSXin LI if(srb->srb_state==ARCMSR_SRB_START) { 90822f2616bSXin LI srb->srb_state=ARCMSR_SRB_ABORTED; 909ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 910ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 91122f2616bSXin LI printf("arcmsr%d: scsi id=%d lun=%d srb='%p' aborted\n" 91222f2616bSXin LI , acb->pci_unit, srb->pccb->ccb_h.target_id 91322f2616bSXin LI , srb->pccb->ccb_h.target_lun, srb); 914f1c579b1SScott Long } 915f1c579b1SScott Long } 916f1c579b1SScott Long /* enable all outbound interrupt */ 91744f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 918f1c579b1SScott Long } 91922f2616bSXin LI acb->srboutstandingcount=0; 920ad6d6297SScott Long acb->workingsrb_doneindex=0; 921ad6d6297SScott Long acb->workingsrb_startindex=0; 92222f2616bSXin LI #ifdef ARCMSR_DEBUG1 92322f2616bSXin LI acb->pktRequestCount = 0; 92422f2616bSXin LI acb->pktReturnCount = 0; 92522f2616bSXin LI #endif 926f1c579b1SScott Long return; 927f1c579b1SScott Long } 928f1c579b1SScott Long /* 929f1c579b1SScott Long ********************************************************************** 930f1c579b1SScott Long ********************************************************************** 931f1c579b1SScott Long */ 93244f05562SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, 93344f05562SScott Long bus_dma_segment_t *dm_segs, u_int32_t nseg) 934f1c579b1SScott Long { 935ad6d6297SScott Long struct ARCMSR_CDB * arcmsr_cdb= &srb->arcmsr_cdb; 936ad6d6297SScott Long u_int8_t * psge=(u_int8_t *)&arcmsr_cdb->u; 937ad6d6297SScott Long u_int32_t address_lo, address_hi; 938ad6d6297SScott Long union ccb * pccb=srb->pccb; 939f1c579b1SScott Long struct ccb_scsiio * pcsio= &pccb->csio; 940ad6d6297SScott Long u_int32_t arccdbsize=0x30; 941f1c579b1SScott Long 942ad6d6297SScott Long memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB)); 943ad6d6297SScott Long arcmsr_cdb->Bus=0; 944ad6d6297SScott Long arcmsr_cdb->TargetID=pccb->ccb_h.target_id; 945ad6d6297SScott Long arcmsr_cdb->LUN=pccb->ccb_h.target_lun; 946ad6d6297SScott Long arcmsr_cdb->Function=1; 947ad6d6297SScott Long arcmsr_cdb->CdbLength=(u_int8_t)pcsio->cdb_len; 94844f05562SScott Long arcmsr_cdb->Context=0; 949ad6d6297SScott Long bcopy(pcsio->cdb_io.cdb_bytes, arcmsr_cdb->Cdb, pcsio->cdb_len); 950ad6d6297SScott Long if(nseg != 0) { 951ad6d6297SScott Long struct AdapterControlBlock *acb=srb->acb; 952f1c579b1SScott Long bus_dmasync_op_t op; 953ad6d6297SScott Long u_int32_t length, i, cdb_sgcount=0; 954f1c579b1SScott Long 955ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 956ad6d6297SScott Long op=BUS_DMASYNC_PREREAD; 957ad6d6297SScott Long } else { 958ad6d6297SScott Long op=BUS_DMASYNC_PREWRITE; 959ad6d6297SScott Long arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_WRITE; 960ad6d6297SScott Long srb->srb_flags|=SRB_FLAG_WRITE; 961ad6d6297SScott Long } 962ad6d6297SScott Long bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 963ad6d6297SScott Long for(i=0;i<nseg;i++) { 964f1c579b1SScott Long /* Get the physical address of the current data pointer */ 965ad6d6297SScott Long length=arcmsr_htole32(dm_segs[i].ds_len); 966ad6d6297SScott Long address_lo=arcmsr_htole32(dma_addr_lo32(dm_segs[i].ds_addr)); 967ad6d6297SScott Long address_hi=arcmsr_htole32(dma_addr_hi32(dm_segs[i].ds_addr)); 968ad6d6297SScott Long if(address_hi==0) { 969ad6d6297SScott Long struct SG32ENTRY * pdma_sg=(struct SG32ENTRY *)psge; 970f1c579b1SScott Long pdma_sg->address=address_lo; 971f1c579b1SScott Long pdma_sg->length=length; 972ad6d6297SScott Long psge += sizeof(struct SG32ENTRY); 973ad6d6297SScott Long arccdbsize += sizeof(struct SG32ENTRY); 974ad6d6297SScott Long } else { 975ad6d6297SScott Long u_int32_t sg64s_size=0, tmplength=length; 976f1c579b1SScott Long 977ad6d6297SScott Long while(1) { 978ad6d6297SScott Long u_int64_t span4G, length0; 979ad6d6297SScott Long struct SG64ENTRY * pdma_sg=(struct SG64ENTRY *)psge; 980f1c579b1SScott Long 981ad6d6297SScott Long span4G=(u_int64_t)address_lo + tmplength; 982f1c579b1SScott Long pdma_sg->addresshigh=address_hi; 983f1c579b1SScott Long pdma_sg->address=address_lo; 984ad6d6297SScott Long if(span4G > 0x100000000) { 985f1c579b1SScott Long /*see if cross 4G boundary*/ 986f1c579b1SScott Long length0=0x100000000-address_lo; 987ad6d6297SScott Long pdma_sg->length=(u_int32_t)length0|IS_SG64_ADDR; 988f1c579b1SScott Long address_hi=address_hi+1; 989f1c579b1SScott Long address_lo=0; 990ad6d6297SScott Long tmplength=tmplength-(u_int32_t)length0; 991ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 992ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 993f1c579b1SScott Long cdb_sgcount++; 994ad6d6297SScott Long } else { 995f1c579b1SScott Long pdma_sg->length=tmplength|IS_SG64_ADDR; 996ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 997ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 998f1c579b1SScott Long break; 999f1c579b1SScott Long } 1000f1c579b1SScott Long } 1001f1c579b1SScott Long arccdbsize += sg64s_size; 1002f1c579b1SScott Long } 1003f1c579b1SScott Long cdb_sgcount++; 1004f1c579b1SScott Long } 1005ad6d6297SScott Long arcmsr_cdb->sgcount=(u_int8_t)cdb_sgcount; 1006ad6d6297SScott Long arcmsr_cdb->DataLength=pcsio->dxfer_len; 1007ad6d6297SScott Long if( arccdbsize > 256) { 1008ad6d6297SScott Long arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_SGL_BSIZE; 1009f1c579b1SScott Long } 1010d74001adSXin LI } else { 1011d74001adSXin LI arcmsr_cdb->DataLength = 0; 1012f1c579b1SScott Long } 1013d74001adSXin LI srb->arc_cdb_size=arccdbsize; 1014f1c579b1SScott Long return; 1015f1c579b1SScott Long } 1016f1c579b1SScott Long /* 1017f1c579b1SScott Long ************************************************************************** 1018f1c579b1SScott Long ************************************************************************** 1019f1c579b1SScott Long */ 1020ad6d6297SScott Long static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandControlBlock *srb) 1021f1c579b1SScott Long { 1022ad6d6297SScott Long u_int32_t cdb_shifted_phyaddr=(u_int32_t) srb->cdb_shifted_phyaddr; 1023ad6d6297SScott Long struct ARCMSR_CDB * arcmsr_cdb=(struct ARCMSR_CDB *)&srb->arcmsr_cdb; 1024f1c579b1SScott Long 1025d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, (srb->srb_flags & SRB_FLAG_WRITE) ? BUS_DMASYNC_POSTWRITE:BUS_DMASYNC_POSTREAD); 1026ad6d6297SScott Long atomic_add_int(&acb->srboutstandingcount, 1); 102722f2616bSXin LI srb->srb_state=ARCMSR_SRB_START; 1028d74001adSXin LI 102944f05562SScott Long switch (acb->adapter_type) { 103044f05562SScott Long case ACB_ADAPTER_TYPE_A: { 1031ad6d6297SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 1032d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE); 1033ad6d6297SScott Long } else { 1034d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_shifted_phyaddr); 103544f05562SScott Long } 103644f05562SScott Long } 103744f05562SScott Long break; 103844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 103944f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 104044f05562SScott Long int ending_index, index; 104144f05562SScott Long 104244f05562SScott Long index=phbbmu->postq_index; 104344f05562SScott Long ending_index=((index+1)%ARCMSR_MAX_HBB_POSTQUEUE); 104444f05562SScott Long phbbmu->post_qbuffer[ending_index]=0; 104544f05562SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 1046d74001adSXin LI phbbmu->post_qbuffer[index]= cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE; 104744f05562SScott Long } else { 1048d74001adSXin LI phbbmu->post_qbuffer[index]= cdb_shifted_phyaddr; 104944f05562SScott Long } 105044f05562SScott Long index++; 105144f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 105244f05562SScott Long phbbmu->postq_index=index; 1053d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED); 1054d74001adSXin LI } 1055d74001adSXin LI break; 1056d74001adSXin LI case ACB_ADAPTER_TYPE_C: 1057d74001adSXin LI { 1058d74001adSXin LI u_int32_t ccb_post_stamp, arc_cdb_size, cdb_phyaddr_hi32; 1059d74001adSXin LI 1060d74001adSXin LI arc_cdb_size=(srb->arc_cdb_size>0x300)?0x300:srb->arc_cdb_size; 1061d74001adSXin LI ccb_post_stamp=(cdb_shifted_phyaddr | ((arc_cdb_size-1) >> 6) | 1); 1062d74001adSXin LI cdb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high; 1063d74001adSXin LI if(cdb_phyaddr_hi32) 1064d74001adSXin LI { 1065d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_high, cdb_phyaddr_hi32); 1066d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp); 1067d74001adSXin LI } 1068d74001adSXin LI else 1069d74001adSXin LI { 1070d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp); 1071d74001adSXin LI } 107244f05562SScott Long } 107344f05562SScott Long break; 1074f1c579b1SScott Long } 1075f1c579b1SScott Long return; 1076f1c579b1SScott Long } 1077f1c579b1SScott Long /* 107844f05562SScott Long ************************************************************************ 107944f05562SScott Long ************************************************************************ 108044f05562SScott Long */ 108144f05562SScott Long static struct QBUFFER * arcmsr_get_iop_rqbuffer( struct AdapterControlBlock *acb) 108244f05562SScott Long { 108344f05562SScott Long struct QBUFFER *qbuffer=NULL; 108444f05562SScott Long 108544f05562SScott Long switch (acb->adapter_type) { 108644f05562SScott Long case ACB_ADAPTER_TYPE_A: { 108744f05562SScott Long struct HBA_MessageUnit *phbamu=(struct HBA_MessageUnit *)acb->pmu; 108844f05562SScott Long 108944f05562SScott Long qbuffer=(struct QBUFFER *)&phbamu->message_rbuffer; 109044f05562SScott Long } 109144f05562SScott Long break; 109244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 109344f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 109444f05562SScott Long 109544f05562SScott Long qbuffer=(struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_rbuffer; 109644f05562SScott Long } 109744f05562SScott Long break; 1098d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1099d74001adSXin LI struct HBC_MessageUnit *phbcmu=(struct HBC_MessageUnit *)acb->pmu; 1100d74001adSXin LI 1101d74001adSXin LI qbuffer=(struct QBUFFER *)&phbcmu->message_rbuffer; 1102d74001adSXin LI } 1103d74001adSXin LI break; 110444f05562SScott Long } 110544f05562SScott Long return(qbuffer); 110644f05562SScott Long } 110744f05562SScott Long /* 110844f05562SScott Long ************************************************************************ 110944f05562SScott Long ************************************************************************ 111044f05562SScott Long */ 111144f05562SScott Long static struct QBUFFER * arcmsr_get_iop_wqbuffer( struct AdapterControlBlock *acb) 111244f05562SScott Long { 111344f05562SScott Long struct QBUFFER *qbuffer=NULL; 111444f05562SScott Long 111544f05562SScott Long switch (acb->adapter_type) { 111644f05562SScott Long case ACB_ADAPTER_TYPE_A: { 111744f05562SScott Long struct HBA_MessageUnit *phbamu=(struct HBA_MessageUnit *)acb->pmu; 111844f05562SScott Long 111944f05562SScott Long qbuffer=(struct QBUFFER *)&phbamu->message_wbuffer; 112044f05562SScott Long } 112144f05562SScott Long break; 112244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 112344f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 112444f05562SScott Long 112544f05562SScott Long qbuffer=(struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_wbuffer; 112644f05562SScott Long } 112744f05562SScott Long break; 1128d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1129d74001adSXin LI struct HBC_MessageUnit *phbcmu=(struct HBC_MessageUnit *)acb->pmu; 1130d74001adSXin LI 1131d74001adSXin LI qbuffer=(struct QBUFFER *)&phbcmu->message_wbuffer; 1132d74001adSXin LI } 1133d74001adSXin LI break; 113444f05562SScott Long } 113544f05562SScott Long return(qbuffer); 113644f05562SScott Long } 113744f05562SScott Long /* 113844f05562SScott Long ************************************************************************** 113944f05562SScott Long ************************************************************************** 114044f05562SScott Long */ 114144f05562SScott Long static void arcmsr_iop_message_read(struct AdapterControlBlock *acb) 114244f05562SScott Long { 114344f05562SScott Long switch (acb->adapter_type) { 114444f05562SScott Long case ACB_ADAPTER_TYPE_A: { 114544f05562SScott Long /* let IOP know data has been read */ 1146d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 114744f05562SScott Long } 114844f05562SScott Long break; 114944f05562SScott Long case ACB_ADAPTER_TYPE_B: { 115044f05562SScott Long /* let IOP know data has been read */ 1151d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 115244f05562SScott Long } 115344f05562SScott Long break; 1154d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1155d74001adSXin LI /* let IOP know data has been read */ 1156d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK); 1157d74001adSXin LI } 115844f05562SScott Long } 115944f05562SScott Long return; 116044f05562SScott Long } 116144f05562SScott Long /* 116244f05562SScott Long ************************************************************************** 116344f05562SScott Long ************************************************************************** 116444f05562SScott Long */ 116544f05562SScott Long static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) 116644f05562SScott Long { 116744f05562SScott Long switch (acb->adapter_type) { 116844f05562SScott Long case ACB_ADAPTER_TYPE_A: { 116944f05562SScott Long /* 117044f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 117144f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 117244f05562SScott Long */ 1173d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK); 117444f05562SScott Long } 117544f05562SScott Long break; 117644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 117744f05562SScott Long /* 117844f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 117944f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 118044f05562SScott Long */ 1181d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_WRITE_OK); 1182d74001adSXin LI } 1183d74001adSXin LI break; 1184d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1185d74001adSXin LI /* 1186d74001adSXin LI ** push inbound doorbell tell iop, driver data write ok 1187d74001adSXin LI ** and wait reply on next hwinterrupt for next Qbuffer post 1188d74001adSXin LI */ 1189d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK); 119044f05562SScott Long } 119144f05562SScott Long break; 119244f05562SScott Long } 119344f05562SScott Long } 119444f05562SScott Long /* 1195f1c579b1SScott Long ********************************************************************** 1196f1c579b1SScott Long ********************************************************************** 1197f1c579b1SScott Long */ 119844f05562SScott Long static void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb) 1199f1c579b1SScott Long { 1200ad6d6297SScott Long u_int8_t *pQbuffer; 120144f05562SScott Long struct QBUFFER *pwbuffer; 120244f05562SScott Long u_int8_t * iop_data; 120344f05562SScott Long int32_t allxfer_len=0; 1204f1c579b1SScott Long 120544f05562SScott Long pwbuffer=arcmsr_get_iop_wqbuffer(acb); 120644f05562SScott Long iop_data=(u_int8_t *)pwbuffer->data; 120744f05562SScott Long if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) { 120844f05562SScott Long acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 120944f05562SScott Long while((acb->wqbuf_firstindex!=acb->wqbuf_lastindex) 121044f05562SScott Long && (allxfer_len<124)) { 1211ad6d6297SScott Long pQbuffer=&acb->wqbuffer[acb->wqbuf_firstindex]; 1212f1c579b1SScott Long memcpy(iop_data, pQbuffer, 1); 1213ad6d6297SScott Long acb->wqbuf_firstindex++; 121444f05562SScott Long acb->wqbuf_firstindex %=ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */ 1215f1c579b1SScott Long iop_data++; 1216f1c579b1SScott Long allxfer_len++; 1217f1c579b1SScott Long } 1218f1c579b1SScott Long pwbuffer->data_len=allxfer_len; 1219f1c579b1SScott Long /* 1220f1c579b1SScott Long ** push inbound doorbell and wait reply at hwinterrupt routine for next Qbuffer post 1221f1c579b1SScott Long */ 122244f05562SScott Long arcmsr_iop_message_wrote(acb); 1223ad6d6297SScott Long } 1224f1c579b1SScott Long return; 1225f1c579b1SScott Long } 1226f1c579b1SScott Long /* 1227f1c579b1SScott Long ************************************************************************ 1228f1c579b1SScott Long ************************************************************************ 1229f1c579b1SScott Long */ 123044f05562SScott Long static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb) 1231f1c579b1SScott Long { 1232ad6d6297SScott Long acb->acb_flags &=~ACB_F_MSG_START_BGRB; 123344f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 123444f05562SScott Long 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 123544f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 1236d74001adSXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n" 1237ad6d6297SScott Long , acb->pci_unit); 1238ad6d6297SScott Long } 1239f1c579b1SScott Long return; 1240f1c579b1SScott Long } 1241f1c579b1SScott Long /* 1242f1c579b1SScott Long ************************************************************************ 1243f1c579b1SScott Long ************************************************************************ 1244f1c579b1SScott Long */ 124544f05562SScott Long static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb) 124644f05562SScott Long { 124744f05562SScott Long acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 124844f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 124944f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_STOP_BGRB); 125044f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 1251d74001adSXin LI printf( "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" 125244f05562SScott Long , acb->pci_unit); 125344f05562SScott Long } 125444f05562SScott Long return; 125544f05562SScott Long } 125644f05562SScott Long /* 125744f05562SScott Long ************************************************************************ 125844f05562SScott Long ************************************************************************ 125944f05562SScott Long */ 1260d74001adSXin LI static void arcmsr_stop_hbc_bgrb(struct AdapterControlBlock *acb) 1261d74001adSXin LI { 1262d74001adSXin LI acb->acb_flags &=~ACB_F_MSG_START_BGRB; 1263d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 1264d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 1265d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 1266d74001adSXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit); 1267d74001adSXin LI } 1268d74001adSXin LI return; 1269d74001adSXin LI } 1270d74001adSXin LI /* 1271d74001adSXin LI ************************************************************************ 1272d74001adSXin LI ************************************************************************ 1273d74001adSXin LI */ 127444f05562SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) 127544f05562SScott Long { 127644f05562SScott Long switch (acb->adapter_type) { 127744f05562SScott Long case ACB_ADAPTER_TYPE_A: { 127844f05562SScott Long arcmsr_stop_hba_bgrb(acb); 127944f05562SScott Long } 128044f05562SScott Long break; 128144f05562SScott Long case ACB_ADAPTER_TYPE_B: { 128244f05562SScott Long arcmsr_stop_hbb_bgrb(acb); 128344f05562SScott Long } 128444f05562SScott Long break; 1285d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1286d74001adSXin LI arcmsr_stop_hbc_bgrb(acb); 1287d74001adSXin LI } 1288d74001adSXin LI break; 128944f05562SScott Long } 129044f05562SScott Long return; 129144f05562SScott Long } 129244f05562SScott Long /* 129344f05562SScott Long ************************************************************************ 129444f05562SScott Long ************************************************************************ 129544f05562SScott Long */ 1296ad6d6297SScott Long static void arcmsr_poll(struct cam_sim * psim) 1297f1c579b1SScott Long { 1298579ec1a5SScott Long struct AdapterControlBlock *acb; 12994e32649fSXin LI int mutex; 1300579ec1a5SScott Long 1301579ec1a5SScott Long acb = (struct AdapterControlBlock *)cam_sim_softc(psim); 13024e32649fSXin LI mutex = mtx_owned(&acb->qbuffer_lock); 13034e32649fSXin LI if( mutex == 0 ) 1304579ec1a5SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 1305579ec1a5SScott Long arcmsr_interrupt(acb); 13064e32649fSXin LI if( mutex == 0 ) 1307579ec1a5SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1308f1c579b1SScott Long return; 1309f1c579b1SScott Long } 1310f1c579b1SScott Long /* 131144f05562SScott Long ************************************************************************** 131244f05562SScott Long ************************************************************************** 13135878cbecSScott Long */ 131444f05562SScott Long static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) 1315f1c579b1SScott Long { 131644f05562SScott Long struct QBUFFER *prbuffer; 1317ad6d6297SScott Long u_int8_t *pQbuffer; 131844f05562SScott Long u_int8_t *iop_data; 131944f05562SScott Long int my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; 1320ad6d6297SScott Long 1321f1c579b1SScott Long /*check this iop data if overflow my rqbuffer*/ 1322ad6d6297SScott Long rqbuf_lastindex=acb->rqbuf_lastindex; 1323ad6d6297SScott Long rqbuf_firstindex=acb->rqbuf_firstindex; 132444f05562SScott Long prbuffer=arcmsr_get_iop_rqbuffer(acb); 132544f05562SScott Long iop_data=(u_int8_t *)prbuffer->data; 1326f1c579b1SScott Long iop_len=prbuffer->data_len; 1327f1c579b1SScott Long my_empty_len=(rqbuf_firstindex-rqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1); 1328ad6d6297SScott Long if(my_empty_len>=iop_len) { 1329ad6d6297SScott Long while(iop_len > 0) { 133044f05562SScott Long pQbuffer=&acb->rqbuffer[rqbuf_lastindex]; 1331f1c579b1SScott Long memcpy(pQbuffer, iop_data, 1); 133244f05562SScott Long rqbuf_lastindex++; 133344f05562SScott Long rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;/*if last index number set it to 0 */ 1334f1c579b1SScott Long iop_data++; 1335f1c579b1SScott Long iop_len--; 1336f1c579b1SScott Long } 133744f05562SScott Long acb->rqbuf_lastindex=rqbuf_lastindex; 133844f05562SScott Long arcmsr_iop_message_read(acb); 133944f05562SScott Long /*signature, let IOP know data has been read */ 1340ad6d6297SScott Long } else { 1341ad6d6297SScott Long acb->acb_flags|=ACB_F_IOPDATA_OVERFLOW; 1342f1c579b1SScott Long } 134344f05562SScott Long return; 1344f1c579b1SScott Long } 1345f1c579b1SScott Long /* 134644f05562SScott Long ************************************************************************** 134744f05562SScott Long ************************************************************************** 134844f05562SScott Long */ 134944f05562SScott Long static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) 135044f05562SScott Long { 135144f05562SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READ; 135244f05562SScott Long /* 135344f05562SScott Long ***************************************************************** 135444f05562SScott Long ** check if there are any mail packages from user space program 135544f05562SScott Long ** in my post bag, now is the time to send them into Areca's firmware 135644f05562SScott Long ***************************************************************** 1357f1c579b1SScott Long */ 1358ad6d6297SScott Long if(acb->wqbuf_firstindex!=acb->wqbuf_lastindex) { 1359ad6d6297SScott Long u_int8_t *pQbuffer; 136044f05562SScott Long struct QBUFFER *pwbuffer; 136144f05562SScott Long u_int8_t *iop_data; 136244f05562SScott Long int allxfer_len=0; 1363f1c579b1SScott Long 136444f05562SScott Long acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 136544f05562SScott Long pwbuffer=arcmsr_get_iop_wqbuffer(acb); 136644f05562SScott Long iop_data=(u_int8_t *)pwbuffer->data; 136744f05562SScott Long while((acb->wqbuf_firstindex!=acb->wqbuf_lastindex) 136844f05562SScott Long && (allxfer_len<124)) { 1369ad6d6297SScott Long pQbuffer=&acb->wqbuffer[acb->wqbuf_firstindex]; 1370f1c579b1SScott Long memcpy(iop_data, pQbuffer, 1); 1371ad6d6297SScott Long acb->wqbuf_firstindex++; 137244f05562SScott Long acb->wqbuf_firstindex %=ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */ 1373f1c579b1SScott Long iop_data++; 1374f1c579b1SScott Long allxfer_len++; 1375f1c579b1SScott Long } 1376f1c579b1SScott Long pwbuffer->data_len=allxfer_len; 1377f1c579b1SScott Long /* 1378ad6d6297SScott Long ** push inbound doorbell tell iop driver data write ok 1379ad6d6297SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 1380f1c579b1SScott Long */ 138144f05562SScott Long arcmsr_iop_message_wrote(acb); 1382f1c579b1SScott Long } 1383ad6d6297SScott Long if(acb->wqbuf_firstindex==acb->wqbuf_lastindex) { 1384ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; 1385f1c579b1SScott Long } 138644f05562SScott Long return; 1387f1c579b1SScott Long } 1388d74001adSXin LI 1389d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb) 1390d74001adSXin LI { 1391d74001adSXin LI /* 1392d74001adSXin LI if (ccb->ccb_h.status != CAM_REQ_CMP) 1393d74001adSXin 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); 1394d74001adSXin LI else 1395d74001adSXin LI printf("arcmsr_rescanLun_cb: Rescan lun successfully!\n"); 1396d74001adSXin LI */ 1397d74001adSXin LI xpt_free_path(ccb->ccb_h.path); 1398d74001adSXin LI xpt_free_ccb(ccb); 1399d74001adSXin LI } 1400d74001adSXin LI 1401d74001adSXin LI static void arcmsr_rescan_lun(struct AdapterControlBlock *acb, int target, int lun) 1402d74001adSXin LI { 1403d74001adSXin LI struct cam_path *path; 1404d74001adSXin LI union ccb *ccb; 1405d74001adSXin LI 1406d74001adSXin LI if ((ccb = (union ccb *)xpt_alloc_ccb_nowait()) == NULL) 1407d74001adSXin LI return; 1408d74001adSXin LI if (xpt_create_path(&path, xpt_periph, cam_sim_path(acb->psim), target, lun) != CAM_REQ_CMP) 1409d74001adSXin LI { 1410d74001adSXin LI xpt_free_ccb(ccb); 1411d74001adSXin LI return; 1412d74001adSXin LI } 1413d74001adSXin LI /* printf("arcmsr_rescan_lun: Rescan Target=%x, Lun=%x\n", target, lun); */ 1414d74001adSXin LI bzero(ccb, sizeof(union ccb)); 1415d74001adSXin LI xpt_setup_ccb(&ccb->ccb_h, path, 5); 1416d74001adSXin LI ccb->ccb_h.func_code = XPT_SCAN_LUN; 1417d74001adSXin LI ccb->ccb_h.cbfcnp = arcmsr_rescanLun_cb; 1418d74001adSXin LI ccb->crcn.flags = CAM_FLAG_NONE; 1419d74001adSXin LI xpt_action(ccb); 1420d74001adSXin LI return; 1421d74001adSXin LI } 1422d74001adSXin LI 1423d74001adSXin LI 1424d74001adSXin LI static void arcmsr_abort_dr_ccbs(struct AdapterControlBlock *acb, int target, int lun) 1425d74001adSXin LI { 1426d74001adSXin LI struct CommandControlBlock *srb; 1427d74001adSXin LI u_int32_t intmask_org; 1428d74001adSXin LI int i; 1429d74001adSXin LI 1430d74001adSXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 1431d74001adSXin LI /* disable all outbound interrupts */ 1432d74001adSXin LI intmask_org = arcmsr_disable_allintr(acb); 1433d74001adSXin LI for (i = 0; i < ARCMSR_MAX_FREESRB_NUM; i++) 1434d74001adSXin LI { 1435d74001adSXin LI srb = acb->psrb_pool[i]; 143622f2616bSXin LI if (srb->srb_state == ARCMSR_SRB_START) 1437d74001adSXin LI { 1438d74001adSXin LI if((target == srb->pccb->ccb_h.target_id) && (lun == srb->pccb->ccb_h.target_lun)) 1439d74001adSXin LI { 144022f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 1441d74001adSXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 1442d74001adSXin LI arcmsr_srb_complete(srb, 1); 144322f2616bSXin LI printf("arcmsr%d: abort scsi id %d lun %d srb=%p \n", acb->pci_unit, target, lun, srb); 1444d74001adSXin LI } 1445d74001adSXin LI } 1446d74001adSXin LI } 1447d74001adSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 1448d74001adSXin LI arcmsr_enable_allintr(acb, intmask_org); 1449d74001adSXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1450d74001adSXin LI } 1451d74001adSXin LI 1452d74001adSXin LI 1453d74001adSXin LI /* 1454d74001adSXin LI ************************************************************************** 1455d74001adSXin LI ************************************************************************** 1456d74001adSXin LI */ 1457d74001adSXin LI static void arcmsr_dr_handle(struct AdapterControlBlock *acb) { 1458d74001adSXin LI u_int32_t devicemap; 1459d74001adSXin LI u_int32_t target, lun; 1460d74001adSXin LI u_int32_t deviceMapCurrent[4]={0}; 1461d74001adSXin LI u_int8_t *pDevMap; 1462d74001adSXin LI 1463d74001adSXin LI switch (acb->adapter_type) { 1464d74001adSXin LI case ACB_ADAPTER_TYPE_A: 1465d74001adSXin LI devicemap = offsetof(struct HBA_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1466d74001adSXin LI for (target= 0; target < 4; target++) 1467d74001adSXin LI { 1468d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1469d74001adSXin LI devicemap += 4; 1470d74001adSXin LI } 1471d74001adSXin LI break; 1472d74001adSXin LI 1473d74001adSXin LI case ACB_ADAPTER_TYPE_B: 1474d74001adSXin LI devicemap = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1475d74001adSXin LI for (target= 0; target < 4; target++) 1476d74001adSXin LI { 1477d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[1], acb->bhandle[1], devicemap); 1478d74001adSXin LI devicemap += 4; 1479d74001adSXin LI } 1480d74001adSXin LI break; 1481d74001adSXin LI 1482d74001adSXin LI case ACB_ADAPTER_TYPE_C: 1483d74001adSXin LI devicemap = offsetof(struct HBC_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1484d74001adSXin LI for (target= 0; target < 4; target++) 1485d74001adSXin LI { 1486d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1487d74001adSXin LI devicemap += 4; 1488d74001adSXin LI } 1489d74001adSXin LI break; 1490d74001adSXin LI } 1491d74001adSXin LI if(acb->acb_flags & ACB_F_BUS_HANG_ON) 1492d74001adSXin LI { 1493d74001adSXin LI acb->acb_flags &= ~ACB_F_BUS_HANG_ON; 1494d74001adSXin LI } 1495d74001adSXin LI /* 1496d74001adSXin LI ** adapter posted CONFIG message 1497d74001adSXin LI ** copy the new map, note if there are differences with the current map 1498d74001adSXin LI */ 1499d74001adSXin LI pDevMap = (u_int8_t *)&deviceMapCurrent[0]; 1500d74001adSXin LI for (target= 0; target < ARCMSR_MAX_TARGETID - 1; target++) 1501d74001adSXin LI { 1502d74001adSXin LI if (*pDevMap != acb->device_map[target]) 1503d74001adSXin LI { 1504d74001adSXin LI u_int8_t difference, bit_check; 1505d74001adSXin LI 1506d74001adSXin LI difference= *pDevMap ^ acb->device_map[target]; 1507d74001adSXin LI for(lun=0; lun < ARCMSR_MAX_TARGETLUN; lun++) 1508d74001adSXin LI { 1509d74001adSXin LI bit_check=(1 << lun); /*check bit from 0....31*/ 1510d74001adSXin LI if(difference & bit_check) 1511d74001adSXin LI { 1512d74001adSXin LI if(acb->device_map[target] & bit_check) 1513d74001adSXin LI {/* unit departed */ 1514d74001adSXin LI printf("arcmsr_dr_handle: Target=%x, lun=%x, GONE!!!\n",target,lun); 1515d74001adSXin LI arcmsr_abort_dr_ccbs(acb, target, lun); 1516d74001adSXin LI arcmsr_rescan_lun(acb, target, lun); 1517d74001adSXin LI acb->devstate[target][lun] = ARECA_RAID_GONE; 1518d74001adSXin LI } 1519d74001adSXin LI else 1520d74001adSXin LI {/* unit arrived */ 152122f2616bSXin LI printf("arcmsr_dr_handle: Target=%x, lun=%x, Plug-IN!!!\n",target,lun); 1522d74001adSXin LI arcmsr_rescan_lun(acb, target, lun); 1523d74001adSXin LI acb->devstate[target][lun] = ARECA_RAID_GOOD; 1524d74001adSXin LI } 1525d74001adSXin LI } 1526d74001adSXin LI } 1527d74001adSXin LI /* printf("arcmsr_dr_handle: acb->device_map[%x]=0x%x, deviceMapCurrent[%x]=%x\n",target,acb->device_map[target],target,*pDevMap); */ 1528d74001adSXin LI acb->device_map[target]= *pDevMap; 1529d74001adSXin LI } 1530d74001adSXin LI pDevMap++; 1531d74001adSXin LI } 1532d74001adSXin LI } 1533d74001adSXin LI /* 1534d74001adSXin LI ************************************************************************** 1535d74001adSXin LI ************************************************************************** 1536d74001adSXin LI */ 1537d74001adSXin LI static void arcmsr_hba_message_isr(struct AdapterControlBlock *acb) { 1538d74001adSXin LI u_int32_t outbound_message; 1539d74001adSXin LI 1540d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT); 1541d74001adSXin LI outbound_message = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[0]); 1542d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1543d74001adSXin LI arcmsr_dr_handle( acb ); 1544d74001adSXin LI } 1545d74001adSXin LI /* 1546d74001adSXin LI ************************************************************************** 1547d74001adSXin LI ************************************************************************** 1548d74001adSXin LI */ 1549d74001adSXin LI static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) { 1550d74001adSXin LI u_int32_t outbound_message; 1551d74001adSXin LI 1552d74001adSXin LI /* clear interrupts */ 1553d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN); 1554d74001adSXin LI outbound_message = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0]); 1555d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1556d74001adSXin LI arcmsr_dr_handle( acb ); 1557d74001adSXin LI } 1558d74001adSXin LI /* 1559d74001adSXin LI ************************************************************************** 1560d74001adSXin LI ************************************************************************** 1561d74001adSXin LI */ 1562d74001adSXin LI static void arcmsr_hbc_message_isr(struct AdapterControlBlock *acb) { 1563d74001adSXin LI u_int32_t outbound_message; 1564d74001adSXin LI 1565d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR); 1566d74001adSXin LI outbound_message = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[0]); 1567d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1568d74001adSXin LI arcmsr_dr_handle( acb ); 1569d74001adSXin LI } 157044f05562SScott Long /* 157144f05562SScott Long ************************************************************************** 157244f05562SScott Long ************************************************************************** 157344f05562SScott Long */ 157444f05562SScott Long static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) 157544f05562SScott Long { 157644f05562SScott Long u_int32_t outbound_doorbell; 157744f05562SScott Long 157844f05562SScott Long /* 157944f05562SScott Long ******************************************************************* 158044f05562SScott Long ** Maybe here we need to check wrqbuffer_lock is lock or not 158144f05562SScott Long ** DOORBELL: din! don! 158244f05562SScott Long ** check if there are any mail need to pack from firmware 158344f05562SScott Long ******************************************************************* 158444f05562SScott Long */ 158544f05562SScott Long outbound_doorbell=CHIP_REG_READ32(HBA_MessageUnit, 158644f05562SScott Long 0, outbound_doorbell); 158744f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 158844f05562SScott Long 0, outbound_doorbell, outbound_doorbell); /* clear doorbell interrupt */ 158944f05562SScott Long if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { 159044f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 1591ad6d6297SScott Long } 159244f05562SScott Long if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { 159344f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 159444f05562SScott Long } 159544f05562SScott Long return; 159644f05562SScott Long } 159744f05562SScott Long /* 159844f05562SScott Long ************************************************************************** 159944f05562SScott Long ************************************************************************** 160044f05562SScott Long */ 1601d74001adSXin LI static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb) 1602d74001adSXin LI { 1603d74001adSXin LI u_int32_t outbound_doorbell; 1604d74001adSXin LI 1605d74001adSXin LI /* 1606d74001adSXin LI ******************************************************************* 1607d74001adSXin LI ** Maybe here we need to check wrqbuffer_lock is lock or not 1608d74001adSXin LI ** DOORBELL: din! don! 1609d74001adSXin LI ** check if there are any mail need to pack from firmware 1610d74001adSXin LI ******************************************************************* 1611d74001adSXin LI */ 1612d74001adSXin LI outbound_doorbell=CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); 1613d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell); /* clear doorbell interrupt */ 1614d74001adSXin LI if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) { 1615d74001adSXin LI arcmsr_iop2drv_data_wrote_handle(acb); 1616d74001adSXin LI } 1617d74001adSXin LI if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) { 1618d74001adSXin LI arcmsr_iop2drv_data_read_handle(acb); 1619d74001adSXin LI } 1620d74001adSXin LI if(outbound_doorbell & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { 1621d74001adSXin LI arcmsr_hbc_message_isr(acb); /* messenger of "driver to iop commands" */ 1622d74001adSXin LI } 1623d74001adSXin LI return; 1624d74001adSXin LI } 1625d74001adSXin LI /* 1626d74001adSXin LI ************************************************************************** 1627d74001adSXin LI ************************************************************************** 1628d74001adSXin LI */ 162944f05562SScott Long static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb) 163044f05562SScott Long { 163144f05562SScott Long u_int32_t flag_srb; 1632d74001adSXin LI u_int16_t error; 163344f05562SScott Long 1634f1c579b1SScott Long /* 1635f1c579b1SScott Long ***************************************************************************** 1636f1c579b1SScott Long ** areca cdb command done 1637f1c579b1SScott Long ***************************************************************************** 1638f1c579b1SScott Long */ 163944f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 164044f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 164144f05562SScott Long while((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 164244f05562SScott Long 0, outbound_queueport)) != 0xFFFFFFFF) { 1643f1c579b1SScott Long /* check if command done with no error*/ 1644d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 1645d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 164644f05562SScott Long } /*drain reply FIFO*/ 164744f05562SScott Long return; 1648f1c579b1SScott Long } 164944f05562SScott Long /* 165044f05562SScott Long ************************************************************************** 165144f05562SScott Long ************************************************************************** 165244f05562SScott Long */ 165344f05562SScott Long static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) 165444f05562SScott Long { 165544f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 165644f05562SScott Long u_int32_t flag_srb; 165744f05562SScott Long int index; 1658d74001adSXin LI u_int16_t error; 165944f05562SScott Long 166044f05562SScott Long /* 166144f05562SScott Long ***************************************************************************** 166244f05562SScott Long ** areca cdb command done 166344f05562SScott Long ***************************************************************************** 166444f05562SScott Long */ 166544f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 166644f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 166744f05562SScott Long index=phbbmu->doneq_index; 166844f05562SScott Long while((flag_srb=phbbmu->done_qbuffer[index]) != 0) { 166944f05562SScott Long phbbmu->done_qbuffer[index]=0; 167044f05562SScott Long index++; 167144f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 167244f05562SScott Long phbbmu->doneq_index=index; 167344f05562SScott Long /* check if command done with no error*/ 1674d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 1675d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 1676d74001adSXin LI } /*drain reply FIFO*/ 1677d74001adSXin LI return; 1678d74001adSXin LI } 1679d74001adSXin LI /* 1680d74001adSXin LI ************************************************************************** 1681d74001adSXin LI ************************************************************************** 1682d74001adSXin LI */ 1683d74001adSXin LI static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb) 1684d74001adSXin LI { 1685d74001adSXin LI u_int32_t flag_srb,throttling=0; 1686d74001adSXin LI u_int16_t error; 1687d74001adSXin LI 1688d74001adSXin LI /* 1689d74001adSXin LI ***************************************************************************** 1690d74001adSXin LI ** areca cdb command done 1691d74001adSXin LI ***************************************************************************** 1692d74001adSXin LI */ 1693d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 1694d74001adSXin LI 1695d74001adSXin LI while(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) { 1696d74001adSXin LI 1697d74001adSXin LI flag_srb=CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 1698d74001adSXin LI /* check if command done with no error*/ 1699d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; 1700d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 1701d74001adSXin LI if(throttling==ARCMSR_HBC_ISR_THROTTLING_LEVEL) { 1702d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING); 1703d74001adSXin LI break; 1704d74001adSXin LI } 1705d74001adSXin LI throttling++; 170644f05562SScott Long } /*drain reply FIFO*/ 170744f05562SScott Long return; 1708f1c579b1SScott Long } 170944f05562SScott Long /* 171044f05562SScott Long ********************************************************************** 171144f05562SScott Long ********************************************************************** 171244f05562SScott Long */ 171344f05562SScott Long static void arcmsr_handle_hba_isr( struct AdapterControlBlock *acb) 171444f05562SScott Long { 171544f05562SScott Long u_int32_t outbound_intstatus; 171644f05562SScott Long /* 171744f05562SScott Long ********************************************* 171844f05562SScott Long ** check outbound intstatus 171944f05562SScott Long ********************************************* 172044f05562SScott Long */ 1721d74001adSXin LI outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 172244f05562SScott Long if(!outbound_intstatus) { 172344f05562SScott Long /*it must be share irq*/ 172444f05562SScott Long return; 1725f1c579b1SScott Long } 1726d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/ 172744f05562SScott Long /* MU doorbell interrupts*/ 172844f05562SScott Long if(outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) { 172944f05562SScott Long arcmsr_hba_doorbell_isr(acb); 1730f1c579b1SScott Long } 173144f05562SScott Long /* MU post queue interrupts*/ 173244f05562SScott Long if(outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { 173344f05562SScott Long arcmsr_hba_postqueue_isr(acb); 173444f05562SScott Long } 1735d74001adSXin LI if(outbound_intstatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { 1736d74001adSXin LI arcmsr_hba_message_isr(acb); 1737d74001adSXin LI } 173844f05562SScott Long return; 173944f05562SScott Long } 174044f05562SScott Long /* 174144f05562SScott Long ********************************************************************** 174244f05562SScott Long ********************************************************************** 174344f05562SScott Long */ 174444f05562SScott Long static void arcmsr_handle_hbb_isr( struct AdapterControlBlock *acb) 174544f05562SScott Long { 174644f05562SScott Long u_int32_t outbound_doorbell; 174744f05562SScott Long /* 174844f05562SScott Long ********************************************* 174944f05562SScott Long ** check outbound intstatus 175044f05562SScott Long ********************************************* 175144f05562SScott Long */ 175244f05562SScott Long outbound_doorbell=CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & acb->outbound_int_enable; 175344f05562SScott Long if(!outbound_doorbell) { 175444f05562SScott Long /*it must be share irq*/ 175544f05562SScott Long return; 175644f05562SScott Long } 175744f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ~outbound_doorbell); /* clear doorbell interrupt */ 175844f05562SScott Long CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell); 175944f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 176044f05562SScott Long /* MU ioctl transfer doorbell interrupts*/ 176144f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { 176244f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 176344f05562SScott Long } 176444f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) { 176544f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 176644f05562SScott Long } 176744f05562SScott Long /* MU post queue interrupts*/ 176844f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) { 176944f05562SScott Long arcmsr_hbb_postqueue_isr(acb); 177044f05562SScott Long } 1771d74001adSXin LI if(outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { 1772d74001adSXin LI arcmsr_hbb_message_isr(acb); 1773d74001adSXin LI } 1774d74001adSXin LI return; 1775d74001adSXin LI } 1776d74001adSXin LI /* 1777d74001adSXin LI ********************************************************************** 1778d74001adSXin LI ********************************************************************** 1779d74001adSXin LI */ 1780d74001adSXin LI static void arcmsr_handle_hbc_isr( struct AdapterControlBlock *acb) 1781d74001adSXin LI { 1782d74001adSXin LI u_int32_t host_interrupt_status; 1783d74001adSXin LI /* 1784d74001adSXin LI ********************************************* 1785d74001adSXin LI ** check outbound intstatus 1786d74001adSXin LI ********************************************* 1787d74001adSXin LI */ 1788d74001adSXin LI host_interrupt_status=CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status); 1789d74001adSXin LI if(!host_interrupt_status) { 1790d74001adSXin LI /*it must be share irq*/ 1791d74001adSXin LI return; 1792d74001adSXin LI } 1793d74001adSXin LI /* MU doorbell interrupts*/ 1794d74001adSXin LI if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) { 1795d74001adSXin LI arcmsr_hbc_doorbell_isr(acb); 1796d74001adSXin LI } 1797d74001adSXin LI /* MU post queue interrupts*/ 1798d74001adSXin LI if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) { 1799d74001adSXin LI arcmsr_hbc_postqueue_isr(acb); 1800d74001adSXin LI } 180144f05562SScott Long return; 180244f05562SScott Long } 180344f05562SScott Long /* 180444f05562SScott Long ****************************************************************************** 180544f05562SScott Long ****************************************************************************** 180644f05562SScott Long */ 180744f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb) 180844f05562SScott Long { 180944f05562SScott Long switch (acb->adapter_type) { 181044f05562SScott Long case ACB_ADAPTER_TYPE_A: 181144f05562SScott Long arcmsr_handle_hba_isr(acb); 1812f1c579b1SScott Long break; 181344f05562SScott Long case ACB_ADAPTER_TYPE_B: 181444f05562SScott Long arcmsr_handle_hbb_isr(acb); 1815f1c579b1SScott Long break; 1816d74001adSXin LI case ACB_ADAPTER_TYPE_C: 1817d74001adSXin LI arcmsr_handle_hbc_isr(acb); 1818d74001adSXin LI break; 1819f1c579b1SScott Long default: 182044f05562SScott Long printf("arcmsr%d: interrupt service," 182144f05562SScott Long " unknow adapter type =%d\n", acb->pci_unit, acb->adapter_type); 1822f1c579b1SScott Long break; 1823f1c579b1SScott Long } 1824f1c579b1SScott Long return; 1825f1c579b1SScott Long } 1826f1c579b1SScott Long /* 1827d74001adSXin LI ********************************************************************** 1828d74001adSXin LI ********************************************************************** 1829d74001adSXin LI */ 1830d74001adSXin LI static void arcmsr_intr_handler(void *arg) 1831d74001adSXin LI { 1832d74001adSXin LI struct AdapterControlBlock *acb=(struct AdapterControlBlock *)arg; 1833d74001adSXin LI 1834d74001adSXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 1835d74001adSXin LI arcmsr_interrupt(acb); 1836d74001adSXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1837d74001adSXin LI } 1838d74001adSXin LI /* 1839d74001adSXin LI ****************************************************************************** 1840d74001adSXin LI ****************************************************************************** 1841d74001adSXin LI */ 1842d74001adSXin LI static void arcmsr_polling_devmap(void* arg) 1843d74001adSXin LI { 1844d74001adSXin LI struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg; 1845d74001adSXin LI switch (acb->adapter_type) { 1846d74001adSXin LI case ACB_ADAPTER_TYPE_A: 1847d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 1848d74001adSXin LI break; 1849d74001adSXin LI 1850d74001adSXin LI case ACB_ADAPTER_TYPE_B: 1851d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG); 1852d74001adSXin LI break; 1853d74001adSXin LI 1854d74001adSXin LI case ACB_ADAPTER_TYPE_C: 1855d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 1856d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 1857d74001adSXin LI break; 1858d74001adSXin LI } 1859d74001adSXin LI 1860d74001adSXin LI if((acb->acb_flags & ACB_F_SCSISTOPADAPTER) == 0) 1861d74001adSXin LI { 1862d74001adSXin LI callout_reset(&acb->devmap_callout, 5 * hz, arcmsr_polling_devmap, acb); /* polling per 5 seconds */ 1863d74001adSXin LI } 1864d74001adSXin LI } 1865d74001adSXin LI 1866d74001adSXin LI /* 1867ad6d6297SScott Long ******************************************************************************* 1868ad6d6297SScott Long ** 1869ad6d6297SScott Long ******************************************************************************* 1870ad6d6297SScott Long */ 1871ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb) 1872ad6d6297SScott Long { 1873d74001adSXin LI u_int32_t intmask_org; 1874d74001adSXin LI 1875ad6d6297SScott Long if(acb!=NULL) { 1876ad6d6297SScott Long /* stop adapter background rebuild */ 1877ad6d6297SScott Long if(acb->acb_flags & ACB_F_MSG_START_BGRB) { 1878d74001adSXin LI intmask_org = arcmsr_disable_allintr(acb); 1879ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 1880ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 1881d74001adSXin LI arcmsr_enable_allintr(acb, intmask_org); 1882ad6d6297SScott Long } 1883ad6d6297SScott Long } 1884ad6d6297SScott Long } 1885ad6d6297SScott Long /* 1886f1c579b1SScott Long *********************************************************************** 1887f1c579b1SScott Long ** 1888f1c579b1SScott Long ************************************************************************ 1889f1c579b1SScott Long */ 1890ad6d6297SScott Long u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg) 1891f1c579b1SScott Long { 1892ad6d6297SScott Long struct CMD_MESSAGE_FIELD * pcmdmessagefld; 1893ad6d6297SScott Long u_int32_t retvalue=EINVAL; 1894f1c579b1SScott Long 1895ad6d6297SScott Long pcmdmessagefld=(struct CMD_MESSAGE_FIELD *) arg; 1896ad6d6297SScott Long if(memcmp(pcmdmessagefld->cmdmessage.Signature, "ARCMSR", 6)!=0) { 1897ad6d6297SScott Long return retvalue; 1898f1c579b1SScott Long } 1899ad6d6297SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 1900ad6d6297SScott Long switch(ioctl_cmd) { 1901ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 1902ad6d6297SScott Long u_int8_t * pQbuffer; 1903ad6d6297SScott Long u_int8_t * ptmpQbuffer=pcmdmessagefld->messagedatabuffer; 1904ad6d6297SScott Long u_int32_t allxfer_len=0; 1905f1c579b1SScott Long 190644f05562SScott Long while((acb->rqbuf_firstindex!=acb->rqbuf_lastindex) 190744f05562SScott Long && (allxfer_len<1031)) { 1908f1c579b1SScott Long /*copy READ QBUFFER to srb*/ 1909ad6d6297SScott Long pQbuffer= &acb->rqbuffer[acb->rqbuf_firstindex]; 1910f1c579b1SScott Long memcpy(ptmpQbuffer, pQbuffer, 1); 1911ad6d6297SScott Long acb->rqbuf_firstindex++; 1912ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 1913ad6d6297SScott Long /*if last index number set it to 0 */ 1914f1c579b1SScott Long ptmpQbuffer++; 1915f1c579b1SScott Long allxfer_len++; 1916f1c579b1SScott Long } 1917ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 191844f05562SScott Long struct QBUFFER * prbuffer; 191944f05562SScott Long u_int8_t * iop_data; 1920ad6d6297SScott Long u_int32_t iop_len; 1921f1c579b1SScott Long 1922ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 192344f05562SScott Long prbuffer=arcmsr_get_iop_rqbuffer(acb); 192444f05562SScott Long iop_data=(u_int8_t *)prbuffer->data; 1925ad6d6297SScott Long iop_len=(u_int32_t)prbuffer->data_len; 1926f1c579b1SScott Long /*this iop data does no chance to make me overflow again here, so just do it*/ 1927ad6d6297SScott Long while(iop_len>0) { 1928ad6d6297SScott Long pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex]; 1929f1c579b1SScott Long memcpy(pQbuffer, iop_data, 1); 1930ad6d6297SScott Long acb->rqbuf_lastindex++; 1931ad6d6297SScott Long acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 1932ad6d6297SScott Long /*if last index number set it to 0 */ 1933f1c579b1SScott Long iop_data++; 1934f1c579b1SScott Long iop_len--; 1935f1c579b1SScott Long } 193644f05562SScott Long arcmsr_iop_message_read(acb); 193744f05562SScott Long /*signature, let IOP know data has been readed */ 1938f1c579b1SScott Long } 1939ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length=allxfer_len; 1940ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1941ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1942f1c579b1SScott Long } 1943f1c579b1SScott Long break; 1944ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 1945ad6d6297SScott Long u_int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 1946ad6d6297SScott Long u_int8_t * pQbuffer; 1947ad6d6297SScott Long u_int8_t * ptmpuserbuffer=pcmdmessagefld->messagedatabuffer; 1948f1c579b1SScott Long 1949ad6d6297SScott Long user_len=pcmdmessagefld->cmdmessage.Length; 1950f1c579b1SScott Long /*check if data xfer length of this request will overflow my array qbuffer */ 1951ad6d6297SScott Long wqbuf_lastindex=acb->wqbuf_lastindex; 1952ad6d6297SScott Long wqbuf_firstindex=acb->wqbuf_firstindex; 1953ad6d6297SScott Long if(wqbuf_lastindex!=wqbuf_firstindex) { 195444f05562SScott Long arcmsr_post_ioctldata2iop(acb); 1955ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; 1956ad6d6297SScott Long } else { 1957f1c579b1SScott Long my_empty_len=(wqbuf_firstindex-wqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1); 1958ad6d6297SScott Long if(my_empty_len>=user_len) { 1959ad6d6297SScott Long while(user_len>0) { 1960f1c579b1SScott Long /*copy srb data to wqbuffer*/ 1961ad6d6297SScott Long pQbuffer= &acb->wqbuffer[acb->wqbuf_lastindex]; 1962f1c579b1SScott Long memcpy(pQbuffer, ptmpuserbuffer, 1); 1963ad6d6297SScott Long acb->wqbuf_lastindex++; 1964ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 1965ad6d6297SScott Long /*if last index number set it to 0 */ 1966f1c579b1SScott Long ptmpuserbuffer++; 1967f1c579b1SScott Long user_len--; 1968f1c579b1SScott Long } 1969f1c579b1SScott Long /*post fist Qbuffer*/ 1970ad6d6297SScott Long if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 1971ad6d6297SScott Long acb->acb_flags &=~ACB_F_MESSAGE_WQBUFFER_CLEARED; 197244f05562SScott Long arcmsr_post_ioctldata2iop(acb); 1973f1c579b1SScott Long } 1974ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1975ad6d6297SScott Long } else { 1976ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; 1977f1c579b1SScott Long } 1978f1c579b1SScott Long } 1979ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1980f1c579b1SScott Long } 1981f1c579b1SScott Long break; 1982ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 1983ad6d6297SScott Long u_int8_t * pQbuffer=acb->rqbuffer; 1984ad6d6297SScott Long 1985ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1986ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 198744f05562SScott Long arcmsr_iop_message_read(acb); 198844f05562SScott Long /*signature, let IOP know data has been readed */ 1989f1c579b1SScott Long } 1990ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 1991ad6d6297SScott Long acb->rqbuf_firstindex=0; 1992ad6d6297SScott Long acb->rqbuf_lastindex=0; 1993f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 1994ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1995ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1996f1c579b1SScott Long } 1997f1c579b1SScott Long break; 1998ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: 1999f1c579b1SScott Long { 2000ad6d6297SScott Long u_int8_t * pQbuffer=acb->wqbuffer; 2001f1c579b1SScott Long 2002ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2003ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 200444f05562SScott Long arcmsr_iop_message_read(acb); 200544f05562SScott Long /*signature, let IOP know data has been readed */ 2006f1c579b1SScott Long } 200744f05562SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ); 2008ad6d6297SScott Long acb->wqbuf_firstindex=0; 2009ad6d6297SScott Long acb->wqbuf_lastindex=0; 2010f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2011ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 2012ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 2013f1c579b1SScott Long } 2014f1c579b1SScott Long break; 2015ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 2016ad6d6297SScott Long u_int8_t * pQbuffer; 2017f1c579b1SScott Long 2018ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2019ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 202044f05562SScott Long arcmsr_iop_message_read(acb); 202144f05562SScott Long /*signature, let IOP know data has been readed */ 2022f1c579b1SScott Long } 2023ad6d6297SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED 2024ad6d6297SScott Long |ACB_F_MESSAGE_RQBUFFER_CLEARED 202544f05562SScott Long |ACB_F_MESSAGE_WQBUFFER_READ); 2026ad6d6297SScott Long acb->rqbuf_firstindex=0; 2027ad6d6297SScott Long acb->rqbuf_lastindex=0; 2028ad6d6297SScott Long acb->wqbuf_firstindex=0; 2029ad6d6297SScott Long acb->wqbuf_lastindex=0; 2030ad6d6297SScott Long pQbuffer=acb->rqbuffer; 2031ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 2032ad6d6297SScott Long pQbuffer=acb->wqbuffer; 2033ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 2034ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 2035ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 2036f1c579b1SScott Long } 2037f1c579b1SScott Long break; 2038ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 2039ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_3F; 2040ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 2041f1c579b1SScott Long } 2042f1c579b1SScott Long break; 2043ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 2044ad6d6297SScott Long u_int8_t * hello_string="Hello! I am ARCMSR"; 2045ad6d6297SScott Long u_int8_t * puserbuffer=(u_int8_t *)pcmdmessagefld->messagedatabuffer; 2046f1c579b1SScott Long 2047ad6d6297SScott Long if(memcpy(puserbuffer, hello_string, (int16_t)strlen(hello_string))) { 2048ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; 2049ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2050f1c579b1SScott Long return ENOIOCTL; 2051f1c579b1SScott Long } 2052ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 2053ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 2054ad6d6297SScott Long } 2055ad6d6297SScott Long break; 2056ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: { 2057ad6d6297SScott Long arcmsr_iop_parking(acb); 2058ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 2059ad6d6297SScott Long } 2060ad6d6297SScott Long break; 2061ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: { 2062ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2063ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 2064f1c579b1SScott Long } 2065f1c579b1SScott Long break; 2066f1c579b1SScott Long } 2067ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2068ad6d6297SScott Long return retvalue; 2069f1c579b1SScott Long } 2070f1c579b1SScott Long /* 2071f1c579b1SScott Long ************************************************************************** 2072f1c579b1SScott Long ************************************************************************** 2073f1c579b1SScott Long */ 207422f2616bSXin LI static void arcmsr_free_srb(struct CommandControlBlock *srb) 207522f2616bSXin LI { 207622f2616bSXin LI struct AdapterControlBlock *acb; 207722f2616bSXin LI int mutex; 207822f2616bSXin LI 207922f2616bSXin LI acb = srb->acb; 208022f2616bSXin LI mutex = mtx_owned(&acb->qbuffer_lock); 208122f2616bSXin LI if( mutex == 0 ) 208222f2616bSXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 208322f2616bSXin LI srb->srb_state=ARCMSR_SRB_DONE; 208422f2616bSXin LI srb->srb_flags=0; 208522f2616bSXin LI acb->srbworkingQ[acb->workingsrb_doneindex]=srb; 208622f2616bSXin LI acb->workingsrb_doneindex++; 208722f2616bSXin LI acb->workingsrb_doneindex %= ARCMSR_MAX_FREESRB_NUM; 208822f2616bSXin LI if( mutex == 0 ) 208922f2616bSXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 209022f2616bSXin LI } 209122f2616bSXin LI /* 209222f2616bSXin LI ************************************************************************** 209322f2616bSXin LI ************************************************************************** 209422f2616bSXin LI */ 2095ad6d6297SScott Long struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb) 2096f1c579b1SScott Long { 2097ad6d6297SScott Long struct CommandControlBlock *srb=NULL; 2098ad6d6297SScott Long u_int32_t workingsrb_startindex, workingsrb_doneindex; 20994e32649fSXin LI int mutex; 2100f1c579b1SScott Long 21014e32649fSXin LI mutex = mtx_owned(&acb->qbuffer_lock); 21024e32649fSXin LI if( mutex == 0 ) 2103579ec1a5SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2104ad6d6297SScott Long workingsrb_doneindex=acb->workingsrb_doneindex; 2105ad6d6297SScott Long workingsrb_startindex=acb->workingsrb_startindex; 2106ad6d6297SScott Long srb=acb->srbworkingQ[workingsrb_startindex]; 2107ad6d6297SScott Long workingsrb_startindex++; 2108ad6d6297SScott Long workingsrb_startindex %= ARCMSR_MAX_FREESRB_NUM; 2109ad6d6297SScott Long if(workingsrb_doneindex!=workingsrb_startindex) { 2110ad6d6297SScott Long acb->workingsrb_startindex=workingsrb_startindex; 2111ad6d6297SScott Long } else { 2112ad6d6297SScott Long srb=NULL; 2113ad6d6297SScott Long } 21144e32649fSXin LI if( mutex == 0 ) 2115579ec1a5SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2116ad6d6297SScott Long return(srb); 2117ad6d6297SScott Long } 2118ad6d6297SScott Long /* 2119ad6d6297SScott Long ************************************************************************** 2120ad6d6297SScott Long ************************************************************************** 2121ad6d6297SScott Long */ 2122ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb) 2123ad6d6297SScott Long { 2124ad6d6297SScott Long struct CMD_MESSAGE_FIELD * pcmdmessagefld; 2125ad6d6297SScott Long int retvalue = 0, transfer_len = 0; 2126ad6d6297SScott Long char *buffer; 212744f05562SScott Long u_int32_t controlcode = (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[5] << 24 | 212844f05562SScott Long (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[6] << 16 | 212944f05562SScott Long (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[7] << 8 | 213044f05562SScott Long (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[8]; 2131ad6d6297SScott Long /* 4 bytes: Areca io control code */ 2132ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) { 2133ad6d6297SScott Long buffer = pccb->csio.data_ptr; 2134ad6d6297SScott Long transfer_len = pccb->csio.dxfer_len; 2135ad6d6297SScott Long } else { 2136ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2137ad6d6297SScott Long goto message_out; 2138ad6d6297SScott Long } 2139ad6d6297SScott Long if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) { 2140ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2141ad6d6297SScott Long goto message_out; 2142ad6d6297SScott Long } 2143ad6d6297SScott Long pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer; 2144ad6d6297SScott Long switch(controlcode) { 2145ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 2146ad6d6297SScott Long u_int8_t *pQbuffer; 2147ad6d6297SScott Long u_int8_t *ptmpQbuffer=pcmdmessagefld->messagedatabuffer; 2148ad6d6297SScott Long int32_t allxfer_len = 0; 2149f1c579b1SScott Long 2150ad6d6297SScott Long while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) 2151ad6d6297SScott Long && (allxfer_len < 1031)) { 2152ad6d6297SScott Long pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; 2153ad6d6297SScott Long memcpy(ptmpQbuffer, pQbuffer, 1); 2154ad6d6297SScott Long acb->rqbuf_firstindex++; 2155ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 2156ad6d6297SScott Long ptmpQbuffer++; 2157ad6d6297SScott Long allxfer_len++; 2158f1c579b1SScott Long } 2159ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 216044f05562SScott Long struct QBUFFER *prbuffer; 216144f05562SScott Long u_int8_t *iop_data; 2162ad6d6297SScott Long int32_t iop_len; 2163ad6d6297SScott Long 2164ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 216544f05562SScott Long prbuffer=arcmsr_get_iop_rqbuffer(acb); 216644f05562SScott Long iop_data = (u_int8_t *)prbuffer->data; 2167ad6d6297SScott Long iop_len =(u_int32_t)prbuffer->data_len; 2168ad6d6297SScott Long while (iop_len > 0) { 2169ad6d6297SScott Long pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex]; 2170ad6d6297SScott Long memcpy(pQbuffer, iop_data, 1); 2171ad6d6297SScott Long acb->rqbuf_lastindex++; 2172ad6d6297SScott Long acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 2173ad6d6297SScott Long iop_data++; 2174ad6d6297SScott Long iop_len--; 2175f1c579b1SScott Long } 217644f05562SScott Long arcmsr_iop_message_read(acb); 2177ad6d6297SScott Long } 2178ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length = allxfer_len; 2179ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2180ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 2181ad6d6297SScott Long } 2182ad6d6297SScott Long break; 2183ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 2184ad6d6297SScott Long int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 2185ad6d6297SScott Long u_int8_t *pQbuffer; 2186ad6d6297SScott Long u_int8_t *ptmpuserbuffer=pcmdmessagefld->messagedatabuffer; 2187ad6d6297SScott Long 2188ad6d6297SScott Long user_len = pcmdmessagefld->cmdmessage.Length; 2189ad6d6297SScott Long wqbuf_lastindex = acb->wqbuf_lastindex; 2190ad6d6297SScott Long wqbuf_firstindex = acb->wqbuf_firstindex; 2191ad6d6297SScott Long if (wqbuf_lastindex != wqbuf_firstindex) { 219244f05562SScott Long arcmsr_post_ioctldata2iop(acb); 2193ad6d6297SScott Long /* has error report sensedata */ 2194ad6d6297SScott Long if(&pccb->csio.sense_data) { 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 } else { 2206ad6d6297SScott Long my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) 2207ad6d6297SScott Long &(ARCMSR_MAX_QBUFFER - 1); 2208ad6d6297SScott Long if (my_empty_len >= user_len) { 2209ad6d6297SScott Long while (user_len > 0) { 2210ad6d6297SScott Long pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; 2211ad6d6297SScott Long memcpy(pQbuffer, ptmpuserbuffer, 1); 2212ad6d6297SScott Long acb->wqbuf_lastindex++; 2213ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 2214ad6d6297SScott Long ptmpuserbuffer++; 2215ad6d6297SScott Long user_len--; 2216ad6d6297SScott Long } 2217ad6d6297SScott Long if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 2218ad6d6297SScott Long acb->acb_flags &= 2219ad6d6297SScott Long ~ACB_F_MESSAGE_WQBUFFER_CLEARED; 222044f05562SScott Long arcmsr_post_ioctldata2iop(acb); 2221ad6d6297SScott Long } 2222ad6d6297SScott Long } else { 2223ad6d6297SScott Long /* has error report sensedata */ 2224ad6d6297SScott Long if(&pccb->csio.sense_data) { 2225ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 2226ad6d6297SScott Long /* Valid,ErrorCode */ 2227ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 2228ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 2229ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 2230ad6d6297SScott Long /* AdditionalSenseLength */ 2231ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 2232ad6d6297SScott Long /* AdditionalSenseCode */ 2233ad6d6297SScott Long } 2234ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2235ad6d6297SScott Long } 2236ad6d6297SScott Long } 2237ad6d6297SScott Long } 2238ad6d6297SScott Long break; 2239ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 2240ad6d6297SScott Long u_int8_t *pQbuffer = acb->rqbuffer; 2241ad6d6297SScott Long 2242ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2243ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 224444f05562SScott Long arcmsr_iop_message_read(acb); 2245ad6d6297SScott Long } 2246ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 2247ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2248ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2249ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2250ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 2251ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 2252ad6d6297SScott Long } 2253ad6d6297SScott Long break; 2254ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { 2255ad6d6297SScott Long u_int8_t *pQbuffer = acb->wqbuffer; 2256ad6d6297SScott Long 2257ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2258ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 225944f05562SScott Long arcmsr_iop_message_read(acb); 2260ad6d6297SScott Long } 2261ad6d6297SScott Long acb->acb_flags |= 2262ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED | 226344f05562SScott Long ACB_F_MESSAGE_WQBUFFER_READ); 2264ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2265ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2266ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2267ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 2268ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 2269ad6d6297SScott Long } 2270ad6d6297SScott Long break; 2271ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 2272ad6d6297SScott Long u_int8_t *pQbuffer; 2273ad6d6297SScott Long 2274ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2275ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 227644f05562SScott Long arcmsr_iop_message_read(acb); 2277ad6d6297SScott Long } 2278ad6d6297SScott Long acb->acb_flags |= 2279ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED 2280ad6d6297SScott Long | ACB_F_MESSAGE_RQBUFFER_CLEARED 228144f05562SScott Long | ACB_F_MESSAGE_WQBUFFER_READ); 2282ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2283ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2284ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2285ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2286ad6d6297SScott Long pQbuffer = acb->rqbuffer; 2287ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 2288ad6d6297SScott Long pQbuffer = acb->wqbuffer; 2289ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 2290ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2291ad6d6297SScott Long } 2292ad6d6297SScott Long break; 2293ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 2294ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; 2295ad6d6297SScott Long } 2296ad6d6297SScott Long break; 2297ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 2298ad6d6297SScott Long int8_t * hello_string = "Hello! I am ARCMSR"; 2299ad6d6297SScott Long 2300ad6d6297SScott Long memcpy(pcmdmessagefld->messagedatabuffer, hello_string 2301ad6d6297SScott Long , (int16_t)strlen(hello_string)); 2302ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2303ad6d6297SScott Long } 2304ad6d6297SScott Long break; 2305ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: 2306ad6d6297SScott Long arcmsr_iop_parking(acb); 2307ad6d6297SScott Long break; 2308ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: 2309ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2310ad6d6297SScott Long break; 2311ad6d6297SScott Long default: 2312ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2313ad6d6297SScott Long } 2314ad6d6297SScott Long message_out: 2315ad6d6297SScott Long return retvalue; 2316f1c579b1SScott Long } 2317f1c579b1SScott Long /* 2318f1c579b1SScott Long ********************************************************************* 2319f1c579b1SScott Long ********************************************************************* 2320f1c579b1SScott Long */ 2321231c8b71SXin LI static void arcmsr_execute_srb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 2322f1c579b1SScott Long { 2323ad6d6297SScott Long struct CommandControlBlock *srb=(struct CommandControlBlock *)arg; 2324ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)srb->acb; 2325f1c579b1SScott Long union ccb * pccb; 2326ad6d6297SScott Long int target, lun; 2327f1c579b1SScott Long 2328ad6d6297SScott Long pccb=srb->pccb; 2329ad6d6297SScott Long target=pccb->ccb_h.target_id; 2330ad6d6297SScott Long lun=pccb->ccb_h.target_lun; 233122f2616bSXin LI #ifdef ARCMSR_DEBUG1 233222f2616bSXin LI acb->pktRequestCount++; 233322f2616bSXin LI #endif 2334ad6d6297SScott Long if(error != 0) { 2335ad6d6297SScott Long if(error != EFBIG) { 233644f05562SScott Long printf("arcmsr%d: unexpected error %x" 233744f05562SScott Long " returned from 'bus_dmamap_load' \n" 2338ad6d6297SScott Long , acb->pci_unit, error); 2339f1c579b1SScott Long } 2340ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { 234115735becSScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 2342f1c579b1SScott Long } 2343ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2344f1c579b1SScott Long return; 2345f1c579b1SScott Long } 2346ad6d6297SScott Long if(nseg > ARCMSR_MAX_SG_ENTRIES) { 2347ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 2348ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2349ad6d6297SScott Long return; 2350f1c579b1SScott Long } 2351ad6d6297SScott Long if(acb->acb_flags & ACB_F_BUS_RESET) { 2352ad6d6297SScott Long printf("arcmsr%d: bus reset and return busy \n", acb->pci_unit); 2353ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_BUS_RESET; 2354ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2355ad6d6297SScott Long return; 2356ad6d6297SScott Long } 2357ad6d6297SScott Long if(acb->devstate[target][lun]==ARECA_RAID_GONE) { 235822f2616bSXin LI u_int8_t block_cmd, cmd; 2359ad6d6297SScott Long 236022f2616bSXin LI cmd = pccb->csio.cdb_io.cdb_bytes[0]; 236122f2616bSXin LI block_cmd= cmd & 0x0f; 2362ad6d6297SScott Long if(block_cmd==0x08 || block_cmd==0x0a) { 2363ad6d6297SScott Long printf("arcmsr%d:block 'read/write' command " 236422f2616bSXin LI "with gone raid volume Cmd=0x%2x, TargetId=%d, Lun=%d \n" 236522f2616bSXin LI , acb->pci_unit, cmd, target, lun); 2366ad6d6297SScott Long pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 2367ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2368ad6d6297SScott Long return; 2369ad6d6297SScott Long } 2370ad6d6297SScott Long } 2371ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { 2372ad6d6297SScott Long if(nseg != 0) { 2373ad6d6297SScott Long bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 2374ad6d6297SScott Long } 2375ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2376f1c579b1SScott Long return; 2377f1c579b1SScott Long } 2378ad6d6297SScott Long if(acb->srboutstandingcount >= ARCMSR_MAX_OUTSTANDING_CMD) { 237915735becSScott Long xpt_freeze_simq(acb->psim, 1); 238015735becSScott Long pccb->ccb_h.status = CAM_REQUEUE_REQ; 2381dc3a205bSScott Long acb->acb_flags |= ACB_F_CAM_DEV_QFRZN; 2382ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2383ad6d6297SScott Long return; 2384f1c579b1SScott Long } 238515735becSScott Long pccb->ccb_h.status |= CAM_SIM_QUEUED; 2386ad6d6297SScott Long arcmsr_build_srb(srb, dm_segs, nseg); 2387ad6d6297SScott Long arcmsr_post_srb(acb, srb); 238822f2616bSXin LI if (pccb->ccb_h.timeout != CAM_TIME_INFINITY) 238922f2616bSXin LI { 239022f2616bSXin LI arcmsr_callout_init(&srb->ccb_callout); 239122f2616bSXin LI callout_reset(&srb->ccb_callout, (pccb->ccb_h.timeout * hz ) / 1000, arcmsr_srb_timeout, srb); 239222f2616bSXin LI srb->srb_flags |= SRB_FLAG_TIMER_START; 239322f2616bSXin LI } 2394f1c579b1SScott Long return; 2395f1c579b1SScott Long } 2396f1c579b1SScott Long /* 2397f1c579b1SScott Long ***************************************************************************************** 2398f1c579b1SScott Long ***************************************************************************************** 2399f1c579b1SScott Long */ 2400ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb) 2401f1c579b1SScott Long { 2402ad6d6297SScott Long struct CommandControlBlock *srb; 2403ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *) abortccb->ccb_h.arcmsr_ccbacb_ptr; 240444f05562SScott Long u_int32_t intmask_org; 2405ad6d6297SScott Long int i=0; 2406f1c579b1SScott Long 2407ad6d6297SScott Long acb->num_aborts++; 2408f1c579b1SScott Long /* 2409ad6d6297SScott Long *************************************************************************** 2410f1c579b1SScott Long ** It is the upper layer do abort command this lock just prior to calling us. 2411f1c579b1SScott Long ** First determine if we currently own this command. 2412f1c579b1SScott Long ** Start by searching the device queue. If not found 2413f1c579b1SScott Long ** at all, and the system wanted us to just abort the 2414f1c579b1SScott Long ** command return success. 2415ad6d6297SScott Long *************************************************************************** 2416f1c579b1SScott Long */ 2417ad6d6297SScott Long if(acb->srboutstandingcount!=0) { 241822f2616bSXin LI /* disable all outbound interrupt */ 241922f2616bSXin LI intmask_org=arcmsr_disable_allintr(acb); 2420ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 2421ad6d6297SScott Long srb=acb->psrb_pool[i]; 242222f2616bSXin LI if(srb->srb_state==ARCMSR_SRB_START) { 2423ad6d6297SScott Long if(srb->pccb==abortccb) { 242422f2616bSXin LI srb->srb_state=ARCMSR_SRB_ABORTED; 2425ad6d6297SScott Long printf("arcmsr%d:scsi id=%d lun=%d abort srb '%p'" 2426ad6d6297SScott Long "outstanding command \n" 2427ad6d6297SScott Long , acb->pci_unit, abortccb->ccb_h.target_id 2428ad6d6297SScott Long , abortccb->ccb_h.target_lun, srb); 2429ad6d6297SScott Long arcmsr_polling_srbdone(acb, srb); 243044f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 243144f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 2432ad6d6297SScott Long return (TRUE); 2433f1c579b1SScott Long } 243422f2616bSXin LI } 243522f2616bSXin LI } 243622f2616bSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 243722f2616bSXin LI arcmsr_enable_allintr(acb, intmask_org); 243822f2616bSXin LI } 243922f2616bSXin LI return(FALSE); 244022f2616bSXin LI } 2441f1c579b1SScott Long /* 2442f1c579b1SScott Long **************************************************************************** 2443f1c579b1SScott Long **************************************************************************** 2444f1c579b1SScott Long */ 2445ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb) 2446f1c579b1SScott Long { 2447ad6d6297SScott Long int retry=0; 2448f1c579b1SScott Long 2449ad6d6297SScott Long acb->num_resets++; 2450ad6d6297SScott Long acb->acb_flags |=ACB_F_BUS_RESET; 2451ad6d6297SScott Long while(acb->srboutstandingcount!=0 && retry < 400) { 245244f05562SScott Long arcmsr_interrupt(acb); 2453ad6d6297SScott Long UDELAY(25000); 2454ad6d6297SScott Long retry++; 2455ad6d6297SScott Long } 2456ad6d6297SScott Long arcmsr_iop_reset(acb); 2457ad6d6297SScott Long acb->acb_flags &= ~ACB_F_BUS_RESET; 2458f1c579b1SScott Long return; 2459f1c579b1SScott Long } 2460f1c579b1SScott Long /* 2461ad6d6297SScott Long ************************************************************************** 2462ad6d6297SScott Long ************************************************************************** 2463ad6d6297SScott Long */ 2464ad6d6297SScott Long static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, 2465ad6d6297SScott Long union ccb * pccb) 2466ad6d6297SScott Long { 2467ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2468ad6d6297SScott Long switch (pccb->csio.cdb_io.cdb_bytes[0]) { 2469ad6d6297SScott Long case INQUIRY: { 2470ad6d6297SScott Long unsigned char inqdata[36]; 2471c2ede4b3SMartin Blapp char *buffer=pccb->csio.data_ptr; 2472ad6d6297SScott Long 2473ad6d6297SScott Long if (pccb->ccb_h.target_lun) { 2474ad6d6297SScott Long pccb->ccb_h.status |= CAM_SEL_TIMEOUT; 2475ad6d6297SScott Long xpt_done(pccb); 2476ad6d6297SScott Long return; 2477ad6d6297SScott Long } 2478231c8b71SXin LI inqdata[0] = T_PROCESSOR; /* Periph Qualifier & Periph Dev Type */ 2479231c8b71SXin LI inqdata[1] = 0; /* rem media bit & Dev Type Modifier */ 2480231c8b71SXin LI inqdata[2] = 0; /* ISO, ECMA, & ANSI versions */ 2481231c8b71SXin LI inqdata[3] = 0; 2482231c8b71SXin LI inqdata[4] = 31; /* length of additional data */ 2483231c8b71SXin LI inqdata[5] = 0; 2484231c8b71SXin LI inqdata[6] = 0; 2485231c8b71SXin LI inqdata[7] = 0; 2486231c8b71SXin LI strncpy(&inqdata[8], "Areca ", 8); /* Vendor Identification */ 2487231c8b71SXin LI strncpy(&inqdata[16], "RAID controller ", 16); /* Product Identification */ 2488ad6d6297SScott Long strncpy(&inqdata[32], "R001", 4); /* Product Revision */ 2489ad6d6297SScott Long memcpy(buffer, inqdata, sizeof(inqdata)); 2490ad6d6297SScott Long xpt_done(pccb); 2491ad6d6297SScott Long } 2492ad6d6297SScott Long break; 2493ad6d6297SScott Long case WRITE_BUFFER: 2494ad6d6297SScott Long case READ_BUFFER: { 2495ad6d6297SScott Long if (arcmsr_iop_message_xfer(acb, pccb)) { 2496ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 2497ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 2498ad6d6297SScott Long } 2499ad6d6297SScott Long xpt_done(pccb); 2500ad6d6297SScott Long } 2501ad6d6297SScott Long break; 2502ad6d6297SScott Long default: 2503ad6d6297SScott Long xpt_done(pccb); 2504ad6d6297SScott Long } 2505ad6d6297SScott Long } 2506ad6d6297SScott Long /* 2507f1c579b1SScott Long ********************************************************************* 2508f1c579b1SScott Long ********************************************************************* 2509f1c579b1SScott Long */ 2510ad6d6297SScott Long static void arcmsr_action(struct cam_sim * psim, union ccb * pccb) 2511f1c579b1SScott Long { 2512ad6d6297SScott Long struct AdapterControlBlock * acb; 2513f1c579b1SScott Long 2514ad6d6297SScott Long acb=(struct AdapterControlBlock *) cam_sim_softc(psim); 2515ad6d6297SScott Long if(acb==NULL) { 2516ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2517f1c579b1SScott Long xpt_done(pccb); 2518f1c579b1SScott Long return; 2519f1c579b1SScott Long } 2520ad6d6297SScott Long switch (pccb->ccb_h.func_code) { 2521ad6d6297SScott Long case XPT_SCSI_IO: { 2522ad6d6297SScott Long struct CommandControlBlock *srb; 2523ad6d6297SScott Long int target=pccb->ccb_h.target_id; 2524f1c579b1SScott Long 2525ad6d6297SScott Long if(target == 16) { 2526ad6d6297SScott Long /* virtual device for iop message transfer */ 2527ad6d6297SScott Long arcmsr_handle_virtual_command(acb, pccb); 2528ad6d6297SScott Long return; 2529ad6d6297SScott Long } 2530ad6d6297SScott Long if((srb=arcmsr_get_freesrb(acb)) == NULL) { 2531ad6d6297SScott Long pccb->ccb_h.status |= CAM_RESRC_UNAVAIL; 2532f1c579b1SScott Long xpt_done(pccb); 2533f1c579b1SScott Long return; 2534f1c579b1SScott Long } 2535ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbsrb_ptr=srb; 2536ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbacb_ptr=acb; 2537ad6d6297SScott Long srb->pccb=pccb; 2538ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 2539ad6d6297SScott Long if(!(pccb->ccb_h.flags & CAM_SCATTER_VALID)) { 2540ad6d6297SScott Long /* Single buffer */ 2541ad6d6297SScott Long if(!(pccb->ccb_h.flags & CAM_DATA_PHYS)) { 2542ad6d6297SScott Long /* Buffer is virtual */ 2543ad6d6297SScott Long u_int32_t error, s; 2544f1c579b1SScott Long 2545f1c579b1SScott Long s=splsoftvm(); 2546ad6d6297SScott Long error = bus_dmamap_load(acb->dm_segs_dmat 2547ad6d6297SScott Long , srb->dm_segs_dmamap 2548ad6d6297SScott Long , pccb->csio.data_ptr 2549ad6d6297SScott Long , pccb->csio.dxfer_len 2550231c8b71SXin LI , arcmsr_execute_srb, srb, /*flags*/0); 2551ad6d6297SScott Long if(error == EINPROGRESS) { 2552ad6d6297SScott Long xpt_freeze_simq(acb->psim, 1); 2553f1c579b1SScott Long pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 2554f1c579b1SScott Long } 2555f1c579b1SScott Long splx(s); 2556231c8b71SXin LI } 2557231c8b71SXin LI else { /* Buffer is physical */ 2558add5afdcSXin LI #ifdef PAE 2559add5afdcSXin LI panic("arcmsr: CAM_DATA_PHYS not supported"); 2560add5afdcSXin LI #else 2561231c8b71SXin LI struct bus_dma_segment seg; 2562231c8b71SXin LI 2563231c8b71SXin LI seg.ds_addr = (bus_addr_t)pccb->csio.data_ptr; 2564231c8b71SXin LI seg.ds_len = pccb->csio.dxfer_len; 2565231c8b71SXin LI arcmsr_execute_srb(srb, &seg, 1, 0); 2566add5afdcSXin LI #endif 2567f1c579b1SScott Long } 2568ad6d6297SScott Long } else { 2569ad6d6297SScott Long /* Scatter/gather list */ 2570f1c579b1SScott Long struct bus_dma_segment *segs; 2571f1c579b1SScott Long 2572ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0 2573ad6d6297SScott Long || (pccb->ccb_h.flags & CAM_DATA_PHYS) != 0) { 2574ad6d6297SScott Long pccb->ccb_h.status |= CAM_PROVIDE_FAIL; 2575f1c579b1SScott Long xpt_done(pccb); 2576ad6d6297SScott Long free(srb, M_DEVBUF); 2577f1c579b1SScott Long return; 2578f1c579b1SScott Long } 2579f1c579b1SScott Long segs=(struct bus_dma_segment *)pccb->csio.data_ptr; 2580231c8b71SXin LI arcmsr_execute_srb(srb, segs, pccb->csio.sglist_cnt, 0); 2581f1c579b1SScott Long } 2582ad6d6297SScott Long } else { 2583231c8b71SXin LI arcmsr_execute_srb(srb, NULL, 0, 0); 2584f1c579b1SScott Long } 2585f1c579b1SScott Long break; 2586f1c579b1SScott Long } 2587ad6d6297SScott Long case XPT_TARGET_IO: { 2588ad6d6297SScott Long /* target mode not yet support vendor specific commands. */ 2589ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2590f1c579b1SScott Long xpt_done(pccb); 2591f1c579b1SScott Long break; 2592f1c579b1SScott Long } 2593ad6d6297SScott Long case XPT_PATH_INQ: { 2594f1c579b1SScott Long struct ccb_pathinq *cpi= &pccb->cpi; 2595f1c579b1SScott Long 2596f1c579b1SScott Long cpi->version_num=1; 2597f1c579b1SScott Long cpi->hba_inquiry=PI_SDTR_ABLE | PI_TAG_ABLE; 2598f1c579b1SScott Long cpi->target_sprt=0; 2599f1c579b1SScott Long cpi->hba_misc=0; 2600f1c579b1SScott Long cpi->hba_eng_cnt=0; 2601ad6d6297SScott Long cpi->max_target=ARCMSR_MAX_TARGETID; /* 0-16 */ 2602ad6d6297SScott Long cpi->max_lun=ARCMSR_MAX_TARGETLUN; /* 0-7 */ 2603ad6d6297SScott Long cpi->initiator_id=ARCMSR_SCSI_INITIATOR_ID; /* 255 */ 2604f1c579b1SScott Long cpi->bus_id=cam_sim_bus(psim); 2605f1c579b1SScott Long strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 2606f1c579b1SScott Long strncpy(cpi->hba_vid, "ARCMSR", HBA_IDLEN); 2607f1c579b1SScott Long strncpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN); 2608f1c579b1SScott Long cpi->unit_number=cam_sim_unit(psim); 260944f05562SScott Long #ifdef CAM_NEW_TRAN_CODE 2610fa9ed865SMatt Jacob cpi->transport = XPORT_SPI; 2611fa9ed865SMatt Jacob cpi->transport_version = 2; 2612fa9ed865SMatt Jacob cpi->protocol = PROTO_SCSI; 2613fa9ed865SMatt Jacob cpi->protocol_version = SCSI_REV_2; 261444f05562SScott Long #endif 2615ad6d6297SScott Long cpi->ccb_h.status |= CAM_REQ_CMP; 2616f1c579b1SScott Long xpt_done(pccb); 2617f1c579b1SScott Long break; 2618f1c579b1SScott Long } 2619ad6d6297SScott Long case XPT_ABORT: { 2620f1c579b1SScott Long union ccb *pabort_ccb; 2621f1c579b1SScott Long 2622f1c579b1SScott Long pabort_ccb=pccb->cab.abort_ccb; 2623ad6d6297SScott Long switch (pabort_ccb->ccb_h.func_code) { 2624f1c579b1SScott Long case XPT_ACCEPT_TARGET_IO: 2625f1c579b1SScott Long case XPT_IMMED_NOTIFY: 2626f1c579b1SScott Long case XPT_CONT_TARGET_IO: 2627ad6d6297SScott Long if(arcmsr_seek_cmd2abort(pabort_ccb)==TRUE) { 2628ad6d6297SScott Long pabort_ccb->ccb_h.status |= CAM_REQ_ABORTED; 2629f1c579b1SScott Long xpt_done(pabort_ccb); 2630ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2631ad6d6297SScott Long } else { 2632f1c579b1SScott Long xpt_print_path(pabort_ccb->ccb_h.path); 2633f1c579b1SScott Long printf("Not found\n"); 2634ad6d6297SScott Long pccb->ccb_h.status |= CAM_PATH_INVALID; 2635f1c579b1SScott Long } 2636f1c579b1SScott Long break; 2637f1c579b1SScott Long case XPT_SCSI_IO: 2638ad6d6297SScott Long pccb->ccb_h.status |= CAM_UA_ABORT; 2639f1c579b1SScott Long break; 2640f1c579b1SScott Long default: 2641ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2642f1c579b1SScott Long break; 2643f1c579b1SScott Long } 2644f1c579b1SScott Long xpt_done(pccb); 2645f1c579b1SScott Long break; 2646f1c579b1SScott Long } 2647f1c579b1SScott Long case XPT_RESET_BUS: 2648ad6d6297SScott Long case XPT_RESET_DEV: { 2649ad6d6297SScott Long u_int32_t i; 2650f1c579b1SScott Long 2651ad6d6297SScott Long arcmsr_bus_reset(acb); 2652ad6d6297SScott Long for (i=0; i < 500; i++) { 2653f1c579b1SScott Long DELAY(1000); 2654f1c579b1SScott Long } 2655ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2656f1c579b1SScott Long xpt_done(pccb); 2657f1c579b1SScott Long break; 2658f1c579b1SScott Long } 2659ad6d6297SScott Long case XPT_TERM_IO: { 2660ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2661f1c579b1SScott Long xpt_done(pccb); 2662f1c579b1SScott Long break; 2663f1c579b1SScott Long } 2664ad6d6297SScott Long case XPT_GET_TRAN_SETTINGS: { 2665ad6d6297SScott Long struct ccb_trans_settings *cts; 2666ad6d6297SScott Long 2667ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 2668ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 2669ad6d6297SScott Long xpt_done(pccb); 2670ad6d6297SScott Long break; 2671ad6d6297SScott Long } 2672ad6d6297SScott Long cts= &pccb->cts; 267344f05562SScott Long #ifdef CAM_NEW_TRAN_CODE 267444f05562SScott Long { 267544f05562SScott Long struct ccb_trans_settings_scsi *scsi; 267644f05562SScott Long struct ccb_trans_settings_spi *spi; 267744f05562SScott Long 2678ad6d6297SScott Long scsi = &cts->proto_specific.scsi; 2679ad6d6297SScott Long spi = &cts->xport_specific.spi; 2680fa9ed865SMatt Jacob cts->protocol = PROTO_SCSI; 2681fa9ed865SMatt Jacob cts->protocol_version = SCSI_REV_2; 2682fa9ed865SMatt Jacob cts->transport = XPORT_SPI; 2683fa9ed865SMatt Jacob cts->transport_version = 2; 2684fa9ed865SMatt Jacob spi->flags = CTS_SPI_FLAGS_DISC_ENB; 2685fa9ed865SMatt Jacob spi->sync_period=3; 2686fa9ed865SMatt Jacob spi->sync_offset=32; 2687fa9ed865SMatt Jacob spi->bus_width=MSG_EXT_WDTR_BUS_16_BIT; 2688fa9ed865SMatt Jacob scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 26899d98ff4dSScott Long spi->valid = CTS_SPI_VALID_DISC 26909d98ff4dSScott Long | CTS_SPI_VALID_SYNC_RATE 2691fa9ed865SMatt Jacob | CTS_SPI_VALID_SYNC_OFFSET 2692fa9ed865SMatt Jacob | CTS_SPI_VALID_BUS_WIDTH; 2693fa9ed865SMatt Jacob scsi->valid = CTS_SCSI_VALID_TQ; 269444f05562SScott Long } 269544f05562SScott Long #else 269644f05562SScott Long { 269744f05562SScott Long cts->flags=(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB); 269844f05562SScott Long cts->sync_period=3; 269944f05562SScott Long cts->sync_offset=32; 270044f05562SScott Long cts->bus_width=MSG_EXT_WDTR_BUS_16_BIT; 270144f05562SScott Long cts->valid=CCB_TRANS_SYNC_RATE_VALID | 270244f05562SScott Long CCB_TRANS_SYNC_OFFSET_VALID | 270344f05562SScott Long CCB_TRANS_BUS_WIDTH_VALID | 270444f05562SScott Long CCB_TRANS_DISC_VALID | 270544f05562SScott Long CCB_TRANS_TQ_VALID; 270644f05562SScott Long } 270744f05562SScott Long #endif 2708ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2709ad6d6297SScott Long xpt_done(pccb); 2710ad6d6297SScott Long break; 2711ad6d6297SScott Long } 2712ad6d6297SScott Long case XPT_SET_TRAN_SETTINGS: { 2713ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 2714ad6d6297SScott Long xpt_done(pccb); 2715ad6d6297SScott Long break; 2716ad6d6297SScott Long } 2717ad6d6297SScott Long case XPT_CALC_GEOMETRY: { 2718ad6d6297SScott Long struct ccb_calc_geometry *ccg; 2719ad6d6297SScott Long u_int32_t size_mb; 2720ad6d6297SScott Long u_int32_t secs_per_cylinder; 2721ad6d6297SScott Long 2722ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 2723ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 2724ad6d6297SScott Long xpt_done(pccb); 2725ad6d6297SScott Long break; 2726ad6d6297SScott Long } 2727f1c579b1SScott Long ccg= &pccb->ccg; 2728ad6d6297SScott Long if (ccg->block_size == 0) { 2729ad6d6297SScott Long pccb->ccb_h.status = CAM_REQ_INVALID; 2730ad6d6297SScott Long xpt_done(pccb); 2731ad6d6297SScott Long break; 2732ad6d6297SScott Long } 2733ad6d6297SScott Long if(((1024L * 1024L)/ccg->block_size) < 0) { 2734ad6d6297SScott Long pccb->ccb_h.status = CAM_REQ_INVALID; 2735ad6d6297SScott Long xpt_done(pccb); 2736ad6d6297SScott Long break; 2737ad6d6297SScott Long } 2738f1c579b1SScott Long size_mb=ccg->volume_size/((1024L * 1024L)/ccg->block_size); 2739ad6d6297SScott Long if(size_mb > 1024 ) { 2740f1c579b1SScott Long ccg->heads=255; 2741f1c579b1SScott Long ccg->secs_per_track=63; 2742ad6d6297SScott Long } else { 2743f1c579b1SScott Long ccg->heads=64; 2744f1c579b1SScott Long ccg->secs_per_track=32; 2745f1c579b1SScott Long } 2746f1c579b1SScott Long secs_per_cylinder=ccg->heads * ccg->secs_per_track; 2747f1c579b1SScott Long ccg->cylinders=ccg->volume_size / secs_per_cylinder; 2748ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2749f1c579b1SScott Long xpt_done(pccb); 2750f1c579b1SScott Long break; 2751f1c579b1SScott Long } 2752f1c579b1SScott Long default: 2753ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2754f1c579b1SScott Long xpt_done(pccb); 2755f1c579b1SScott Long break; 2756f1c579b1SScott Long } 2757f1c579b1SScott Long return; 2758f1c579b1SScott Long } 2759f1c579b1SScott Long /* 2760f1c579b1SScott Long ********************************************************************** 2761f1c579b1SScott Long ********************************************************************** 2762f1c579b1SScott Long */ 276344f05562SScott Long static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) 2764f1c579b1SScott Long { 2765ad6d6297SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 276644f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 276744f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 2768ad6d6297SScott Long printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 2769ad6d6297SScott Long } 2770f1c579b1SScott Long return; 2771f1c579b1SScott Long } 2772f1c579b1SScott Long /* 2773f1c579b1SScott Long ********************************************************************** 2774f1c579b1SScott Long ********************************************************************** 2775f1c579b1SScott Long */ 277644f05562SScott Long static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb) 277744f05562SScott Long { 277844f05562SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 2779d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_START_BGRB); 278044f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 278144f05562SScott Long printf( "arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 278244f05562SScott Long } 278344f05562SScott Long return; 278444f05562SScott Long } 278544f05562SScott Long /* 278644f05562SScott Long ********************************************************************** 278744f05562SScott Long ********************************************************************** 278844f05562SScott Long */ 2789d74001adSXin LI static void arcmsr_start_hbc_bgrb(struct AdapterControlBlock *acb) 2790d74001adSXin LI { 2791d74001adSXin LI acb->acb_flags |= ACB_F_MSG_START_BGRB; 2792d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 2793d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 2794d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 2795d74001adSXin LI printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 2796d74001adSXin LI } 2797d74001adSXin LI return; 2798d74001adSXin LI } 2799d74001adSXin LI /* 2800d74001adSXin LI ********************************************************************** 2801d74001adSXin LI ********************************************************************** 2802d74001adSXin LI */ 280344f05562SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) 280444f05562SScott Long { 280544f05562SScott Long switch (acb->adapter_type) { 280644f05562SScott Long case ACB_ADAPTER_TYPE_A: 280744f05562SScott Long arcmsr_start_hba_bgrb(acb); 280844f05562SScott Long break; 280944f05562SScott Long case ACB_ADAPTER_TYPE_B: 281044f05562SScott Long arcmsr_start_hbb_bgrb(acb); 281144f05562SScott Long break; 2812d74001adSXin LI case ACB_ADAPTER_TYPE_C: 2813d74001adSXin LI arcmsr_start_hbc_bgrb(acb); 2814d74001adSXin LI break; 281544f05562SScott Long } 281644f05562SScott Long return; 281744f05562SScott Long } 281844f05562SScott Long /* 281944f05562SScott Long ********************************************************************** 282044f05562SScott Long ** 282144f05562SScott Long ********************************************************************** 282244f05562SScott Long */ 282344f05562SScott Long static void arcmsr_polling_hba_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 2824f1c579b1SScott Long { 2825ad6d6297SScott Long struct CommandControlBlock *srb; 282644f05562SScott Long u_int32_t flag_srb, outbound_intstatus, poll_srb_done=0, poll_count=0; 2827d74001adSXin LI u_int16_t error; 2828f1c579b1SScott Long 282944f05562SScott Long polling_ccb_retry: 2830ad6d6297SScott Long poll_count++; 2831d74001adSXin LI outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 2832d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus); /*clear interrupt*/ 283344f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 2834ad6d6297SScott Long while(1) { 283544f05562SScott Long if((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 283644f05562SScott Long 0, outbound_queueport))==0xFFFFFFFF) { 2837ad6d6297SScott Long if(poll_srb_done) { 2838ad6d6297SScott Long break;/*chip FIFO no ccb for completion already*/ 2839ad6d6297SScott Long } else { 2840ad6d6297SScott Long UDELAY(25000); 2841d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 2842ad6d6297SScott Long break; 2843f1c579b1SScott Long } 284444f05562SScott Long goto polling_ccb_retry; 2845f1c579b1SScott Long } 2846ad6d6297SScott Long } 2847ad6d6297SScott Long /* check if command done with no error*/ 284844f05562SScott Long srb=(struct CommandControlBlock *) 284944f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 2850d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 285144f05562SScott Long poll_srb_done = (srb==poll_srb) ? 1:0; 285222f2616bSXin LI if((srb->acb!=acb) || (srb->srb_state!=ARCMSR_SRB_START)) { 285322f2616bSXin LI if(srb->srb_state==ARCMSR_SRB_ABORTED) { 2854ad6d6297SScott Long printf("arcmsr%d: scsi id=%d lun=%d srb='%p'" 2855ad6d6297SScott Long "poll command abort successfully \n" 2856ad6d6297SScott Long , acb->pci_unit 2857ad6d6297SScott Long , srb->pccb->ccb_h.target_id 2858ad6d6297SScott Long , srb->pccb->ccb_h.target_lun, srb); 2859ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 2860ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 2861ad6d6297SScott Long continue; 2862ad6d6297SScott Long } 2863ad6d6297SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 2864ad6d6297SScott Long "srboutstandingcount=%d \n" 2865ad6d6297SScott Long , acb->pci_unit 2866ad6d6297SScott Long , srb, acb->srboutstandingcount); 2867ad6d6297SScott Long continue; 2868ad6d6297SScott Long } 2869d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 2870ad6d6297SScott Long } /*drain reply FIFO*/ 2871f1c579b1SScott Long return; 2872f1c579b1SScott Long } 2873f1c579b1SScott Long /* 2874f1c579b1SScott Long ********************************************************************** 287544f05562SScott Long ** 2876ad6d6297SScott Long ********************************************************************** 2877ad6d6297SScott Long */ 287844f05562SScott Long static void arcmsr_polling_hbb_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 287944f05562SScott Long { 288044f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 288144f05562SScott Long struct CommandControlBlock *srb; 288244f05562SScott Long u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 288344f05562SScott Long int index; 2884d74001adSXin LI u_int16_t error; 288544f05562SScott Long 288644f05562SScott Long polling_ccb_retry: 288744f05562SScott Long poll_count++; 288844f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 288944f05562SScott Long 0, iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 289044f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 289144f05562SScott Long while(1) { 289244f05562SScott Long index=phbbmu->doneq_index; 289344f05562SScott Long if((flag_srb=phbbmu->done_qbuffer[index]) == 0) { 289444f05562SScott Long if(poll_srb_done) { 289544f05562SScott Long break;/*chip FIFO no ccb for completion already*/ 289644f05562SScott Long } else { 289744f05562SScott Long UDELAY(25000); 2898d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 289944f05562SScott Long break; 290044f05562SScott Long } 290144f05562SScott Long goto polling_ccb_retry; 290244f05562SScott Long } 290344f05562SScott Long } 290444f05562SScott Long phbbmu->done_qbuffer[index]=0; 290544f05562SScott Long index++; 290644f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 290744f05562SScott Long phbbmu->doneq_index=index; 290844f05562SScott Long /* check if command done with no error*/ 290944f05562SScott Long srb=(struct CommandControlBlock *) 291044f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 2911d74001adSXin LI error=(flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 291244f05562SScott Long poll_srb_done = (srb==poll_srb) ? 1:0; 291322f2616bSXin LI if((srb->acb!=acb) || (srb->srb_state!=ARCMSR_SRB_START)) { 291422f2616bSXin LI if(srb->srb_state==ARCMSR_SRB_ABORTED) { 291544f05562SScott Long printf("arcmsr%d: scsi id=%d lun=%d srb='%p'" 291644f05562SScott Long "poll command abort successfully \n" 291744f05562SScott Long , acb->pci_unit 291844f05562SScott Long , srb->pccb->ccb_h.target_id 291944f05562SScott Long , srb->pccb->ccb_h.target_lun, srb); 292044f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 292144f05562SScott Long arcmsr_srb_complete(srb, 1); 292244f05562SScott Long continue; 292344f05562SScott Long } 292444f05562SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 292544f05562SScott Long "srboutstandingcount=%d \n" 292644f05562SScott Long , acb->pci_unit 292744f05562SScott Long , srb, acb->srboutstandingcount); 292844f05562SScott Long continue; 292944f05562SScott Long } 2930d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 2931d74001adSXin LI } /*drain reply FIFO*/ 2932d74001adSXin LI return; 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 return; 298444f05562SScott Long } 298544f05562SScott Long /* 298644f05562SScott Long ********************************************************************** 298744f05562SScott Long ********************************************************************** 298844f05562SScott Long */ 298944f05562SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 299044f05562SScott Long { 299144f05562SScott Long switch (acb->adapter_type) { 299244f05562SScott Long case ACB_ADAPTER_TYPE_A: { 299344f05562SScott Long arcmsr_polling_hba_srbdone(acb, poll_srb); 299444f05562SScott Long } 299544f05562SScott Long break; 299644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 299744f05562SScott Long arcmsr_polling_hbb_srbdone(acb, poll_srb); 299844f05562SScott Long } 299944f05562SScott Long break; 3000d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3001d74001adSXin LI arcmsr_polling_hbc_srbdone(acb, poll_srb); 3002d74001adSXin LI } 3003d74001adSXin LI break; 300444f05562SScott Long } 300544f05562SScott Long } 300644f05562SScott Long /* 300744f05562SScott Long ********************************************************************** 300844f05562SScott Long ********************************************************************** 300944f05562SScott Long */ 301044f05562SScott Long static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) 3011ad6d6297SScott Long { 3012ad6d6297SScott Long char *acb_firm_model=acb->firm_model; 3013ad6d6297SScott Long char *acb_firm_version=acb->firm_version; 3014d74001adSXin LI char *acb_device_map = acb->device_map; 3015d74001adSXin LI size_t iop_firm_model=offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3016d74001adSXin LI size_t iop_firm_version=offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3017d74001adSXin LI size_t iop_device_map = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 3018ad6d6297SScott Long int i; 3019ad6d6297SScott Long 302044f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 302144f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 3022d74001adSXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 3023ad6d6297SScott Long } 3024ad6d6297SScott Long i=0; 3025ad6d6297SScott Long while(i<8) { 302644f05562SScott Long *acb_firm_model=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 3027ad6d6297SScott Long /* 8 bytes firm_model, 15, 60-67*/ 3028ad6d6297SScott Long acb_firm_model++; 3029ad6d6297SScott Long i++; 3030ad6d6297SScott Long } 3031ad6d6297SScott Long i=0; 3032ad6d6297SScott Long while(i<16) { 303344f05562SScott Long *acb_firm_version=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 3034ad6d6297SScott Long /* 16 bytes firm_version, 17, 68-83*/ 3035ad6d6297SScott Long acb_firm_version++; 3036ad6d6297SScott Long i++; 3037ad6d6297SScott Long } 3038d74001adSXin LI i=0; 3039d74001adSXin LI while(i<16) { 3040d74001adSXin LI *acb_device_map=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 3041d74001adSXin LI acb_device_map++; 3042d74001adSXin LI i++; 3043d74001adSXin LI } 3044ad6d6297SScott Long printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION); 3045ad6d6297SScott Long printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version); 3046d74001adSXin LI acb->firm_request_len=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3047d74001adSXin LI acb->firm_numbers_queue=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3048d74001adSXin LI acb->firm_sdram_size=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3049d74001adSXin LI acb->firm_ide_channels=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3050d74001adSXin LI acb->firm_cfg_version=CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3051ad6d6297SScott Long return; 3052ad6d6297SScott Long } 3053ad6d6297SScott Long /* 3054ad6d6297SScott Long ********************************************************************** 305544f05562SScott Long ********************************************************************** 305644f05562SScott Long */ 305744f05562SScott Long static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) 305844f05562SScott Long { 305944f05562SScott Long char *acb_firm_model=acb->firm_model; 306044f05562SScott Long char *acb_firm_version=acb->firm_version; 3061d74001adSXin LI char *acb_device_map = acb->device_map; 3062d74001adSXin LI size_t iop_firm_model=offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3063d74001adSXin LI size_t iop_firm_version=offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3064d74001adSXin LI size_t iop_device_map = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 306544f05562SScott Long int i; 306644f05562SScott Long 3067d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG); 306844f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 3069d74001adSXin LI printf( "arcmsr%d: wait" "'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 307044f05562SScott Long } 307144f05562SScott Long i=0; 307244f05562SScott Long while(i<8) { 307344f05562SScott Long *acb_firm_model=bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_model+i); 307444f05562SScott Long /* 8 bytes firm_model, 15, 60-67*/ 307544f05562SScott Long acb_firm_model++; 307644f05562SScott Long i++; 307744f05562SScott Long } 307844f05562SScott Long i=0; 307944f05562SScott Long while(i<16) { 308044f05562SScott Long *acb_firm_version=bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_version+i); 308144f05562SScott Long /* 16 bytes firm_version, 17, 68-83*/ 308244f05562SScott Long acb_firm_version++; 308344f05562SScott Long i++; 308444f05562SScott Long } 3085d74001adSXin LI i=0; 3086d74001adSXin LI while(i<16) { 3087d74001adSXin LI *acb_device_map=bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_device_map+i); 3088d74001adSXin LI acb_device_map++; 3089d74001adSXin LI i++; 3090d74001adSXin LI } 309144f05562SScott Long printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION); 309244f05562SScott Long printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version); 3093d74001adSXin LI acb->firm_request_len=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3094d74001adSXin LI acb->firm_numbers_queue=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3095d74001adSXin LI acb->firm_sdram_size=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3096d74001adSXin LI acb->firm_ide_channels=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3097d74001adSXin LI acb->firm_cfg_version=CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3098d74001adSXin LI return; 3099d74001adSXin LI } 3100d74001adSXin LI /* 3101d74001adSXin LI ********************************************************************** 3102d74001adSXin LI ********************************************************************** 3103d74001adSXin LI */ 3104d74001adSXin LI static void arcmsr_get_hbc_config(struct AdapterControlBlock *acb) 3105d74001adSXin LI { 3106d74001adSXin LI char *acb_firm_model=acb->firm_model; 3107d74001adSXin LI char *acb_firm_version=acb->firm_version; 3108d74001adSXin LI char *acb_device_map = acb->device_map; 3109d74001adSXin LI size_t iop_firm_model=offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3110d74001adSXin LI size_t iop_firm_version=offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3111d74001adSXin LI size_t iop_device_map = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 3112d74001adSXin LI int i; 3113d74001adSXin LI 3114d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 3115d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 3116d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 3117d74001adSXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 3118d74001adSXin LI } 3119d74001adSXin LI i=0; 3120d74001adSXin LI while(i<8) { 3121d74001adSXin LI *acb_firm_model=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 3122d74001adSXin LI /* 8 bytes firm_model, 15, 60-67*/ 3123d74001adSXin LI acb_firm_model++; 3124d74001adSXin LI i++; 3125d74001adSXin LI } 3126d74001adSXin LI i=0; 3127d74001adSXin LI while(i<16) { 3128d74001adSXin LI *acb_firm_version=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 3129d74001adSXin LI /* 16 bytes firm_version, 17, 68-83*/ 3130d74001adSXin LI acb_firm_version++; 3131d74001adSXin LI i++; 3132d74001adSXin LI } 3133d74001adSXin LI i=0; 3134d74001adSXin LI while(i<16) { 3135d74001adSXin LI *acb_device_map=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 3136d74001adSXin LI acb_device_map++; 3137d74001adSXin LI i++; 3138d74001adSXin LI } 3139d74001adSXin LI printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION); 3140d74001adSXin LI printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version); 3141d74001adSXin LI acb->firm_request_len =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3142d74001adSXin LI acb->firm_numbers_queue =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3143d74001adSXin LI acb->firm_sdram_size =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3144d74001adSXin LI acb->firm_ide_channels =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3145d74001adSXin LI acb->firm_cfg_version =CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 314644f05562SScott Long return; 314744f05562SScott Long } 314844f05562SScott Long /* 314944f05562SScott Long ********************************************************************** 315044f05562SScott Long ********************************************************************** 315144f05562SScott Long */ 315244f05562SScott Long static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) 315344f05562SScott Long { 315444f05562SScott Long switch (acb->adapter_type) { 315544f05562SScott Long case ACB_ADAPTER_TYPE_A: { 315644f05562SScott Long arcmsr_get_hba_config(acb); 315744f05562SScott Long } 315844f05562SScott Long break; 315944f05562SScott Long case ACB_ADAPTER_TYPE_B: { 316044f05562SScott Long arcmsr_get_hbb_config(acb); 316144f05562SScott Long } 316244f05562SScott Long break; 3163d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3164d74001adSXin LI arcmsr_get_hbc_config(acb); 3165d74001adSXin LI } 3166d74001adSXin LI break; 316744f05562SScott Long } 316844f05562SScott Long return; 316944f05562SScott Long } 317044f05562SScott Long /* 317144f05562SScott Long ********************************************************************** 317244f05562SScott Long ********************************************************************** 317344f05562SScott Long */ 317444f05562SScott Long static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb) 317544f05562SScott Long { 317644f05562SScott Long int timeout=0; 317744f05562SScott Long 317844f05562SScott Long switch (acb->adapter_type) { 317944f05562SScott Long case ACB_ADAPTER_TYPE_A: { 3180d74001adSXin LI while ((CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) 318144f05562SScott Long { 318244f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 318344f05562SScott Long { 3184d74001adSXin LI printf( "arcmsr%d:timed out waiting for firmware \n", acb->pci_unit); 318544f05562SScott Long return; 318644f05562SScott Long } 318744f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 318844f05562SScott Long } 318944f05562SScott Long } 319044f05562SScott Long break; 319144f05562SScott Long case ACB_ADAPTER_TYPE_B: { 3192d74001adSXin LI while ((CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & ARCMSR_MESSAGE_FIRMWARE_OK) == 0) 319344f05562SScott Long { 319444f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 319544f05562SScott Long { 3196d74001adSXin LI printf( "arcmsr%d: timed out waiting for firmware \n", acb->pci_unit); 319744f05562SScott Long return; 319844f05562SScott Long } 319944f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 320044f05562SScott Long } 3201d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 3202d74001adSXin LI } 3203d74001adSXin LI break; 3204d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3205d74001adSXin LI while ((CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0) 3206d74001adSXin LI { 3207d74001adSXin LI if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 3208d74001adSXin LI { 3209d74001adSXin LI printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit); 3210d74001adSXin LI return; 3211d74001adSXin LI } 3212d74001adSXin LI UDELAY(15000); /* wait 15 milli-seconds */ 3213d74001adSXin LI } 321444f05562SScott Long } 321544f05562SScott Long break; 321644f05562SScott Long } 321744f05562SScott Long return; 321844f05562SScott Long } 321944f05562SScott Long /* 322044f05562SScott Long ********************************************************************** 322144f05562SScott Long ********************************************************************** 322244f05562SScott Long */ 322344f05562SScott Long static void arcmsr_clear_doorbell_queue_buffer( struct AdapterControlBlock *acb) 322444f05562SScott Long { 3225d74001adSXin LI u_int32_t outbound_doorbell; 3226d74001adSXin LI 322744f05562SScott Long switch (acb->adapter_type) { 322844f05562SScott Long case ACB_ADAPTER_TYPE_A: { 322944f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 3230d74001adSXin LI outbound_doorbell = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell); 3231d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, outbound_doorbell); /*clear doorbell interrupt */ 3232d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 3233d74001adSXin LI 323444f05562SScott Long } 323544f05562SScott Long break; 323644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 3237d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt and message state*/ 3238d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 323944f05562SScott Long /* let IOP know data has been read */ 324044f05562SScott Long } 324144f05562SScott Long break; 3242d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3243d74001adSXin LI /* empty doorbell Qbuffer if door bell ringed */ 3244d74001adSXin LI outbound_doorbell = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); 3245d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell); /*clear doorbell interrupt */ 3246d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK); 3247d74001adSXin LI 3248d74001adSXin LI } 3249d74001adSXin LI break; 325044f05562SScott Long } 325144f05562SScott Long return; 325244f05562SScott Long } 325344f05562SScott Long /* 325444f05562SScott Long ************************************************************************ 325544f05562SScott Long ************************************************************************ 325644f05562SScott Long */ 325744f05562SScott Long static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb) 325844f05562SScott Long { 325944f05562SScott Long unsigned long srb_phyaddr; 326044f05562SScott Long u_int32_t srb_phyaddr_hi32; 326144f05562SScott Long 326244f05562SScott Long /* 326344f05562SScott Long ******************************************************************** 326444f05562SScott Long ** here we need to tell iop 331 our freesrb.HighPart 326544f05562SScott Long ** if freesrb.HighPart is not zero 326644f05562SScott Long ******************************************************************** 326744f05562SScott Long */ 3268d74001adSXin LI srb_phyaddr= (unsigned long) acb->srb_phyaddr.phyaddr; 3269d74001adSXin LI // srb_phyaddr_hi32=(u_int32_t) ((srb_phyaddr>>16)>>16); 3270d74001adSXin LI srb_phyaddr_hi32=acb->srb_phyaddr.B.phyadd_high; 327144f05562SScott Long switch (acb->adapter_type) { 327244f05562SScott Long case ACB_ADAPTER_TYPE_A: { 327344f05562SScott Long if(srb_phyaddr_hi32!=0) { 3274d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 3275d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 3276d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 327744f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 3278d74001adSXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 327944f05562SScott Long return FALSE; 328044f05562SScott Long } 328144f05562SScott Long } 328244f05562SScott Long } 328344f05562SScott Long break; 328444f05562SScott Long /* 328544f05562SScott Long *********************************************************************** 328644f05562SScott Long ** if adapter type B, set window of "post command Q" 328744f05562SScott Long *********************************************************************** 328844f05562SScott Long */ 328944f05562SScott Long case ACB_ADAPTER_TYPE_B: { 329044f05562SScott Long u_int32_t post_queue_phyaddr; 329144f05562SScott Long struct HBB_MessageUnit *phbbmu; 329244f05562SScott Long 329344f05562SScott Long phbbmu=(struct HBB_MessageUnit *)acb->pmu; 329444f05562SScott Long phbbmu->postq_index=0; 329544f05562SScott Long phbbmu->doneq_index=0; 3296d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_SET_POST_WINDOW); 329744f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 3298d74001adSXin LI printf( "arcmsr%d: 'set window of post command Q' timeout\n", acb->pci_unit); 329944f05562SScott Long return FALSE; 330044f05562SScott Long } 330122f2616bSXin LI post_queue_phyaddr = srb_phyaddr + ARCMSR_SRBS_POOL_SIZE 330244f05562SScott Long + offsetof(struct HBB_MessageUnit, post_qbuffer); 3303d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */ 3304d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1], srb_phyaddr_hi32); /* normal should be zero */ 3305d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ size (256+8)*4 */ 3306d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3], post_queue_phyaddr+1056); /* doneQ size (256+8)*4 */ 3307d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4], 1056); /* srb maxQ size must be --> [(256+8)*4] */ 3308d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_SET_CONFIG); 330944f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 331044f05562SScott Long printf( "arcmsr%d: 'set command Q window' timeout \n", acb->pci_unit); 331144f05562SScott Long return FALSE; 331244f05562SScott Long } 3313d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_START_DRIVER_MODE); 331444f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 331544f05562SScott Long printf( "arcmsr%d: 'start diver mode' timeout \n", acb->pci_unit); 331644f05562SScott Long return FALSE; 331744f05562SScott Long } 331844f05562SScott Long } 331944f05562SScott Long break; 3320d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3321d74001adSXin LI if(srb_phyaddr_hi32!=0) { 3322d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 3323d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 3324d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 3325d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 3326d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 3327d74001adSXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 3328d74001adSXin LI return FALSE; 3329d74001adSXin LI } 3330d74001adSXin LI } 3331d74001adSXin LI } 3332d74001adSXin LI break; 333344f05562SScott Long } 333444f05562SScott Long return TRUE; 333544f05562SScott Long } 333644f05562SScott Long /* 333744f05562SScott Long ************************************************************************ 333844f05562SScott Long ************************************************************************ 333944f05562SScott Long */ 334044f05562SScott Long static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb) 334144f05562SScott Long { 334244f05562SScott Long switch (acb->adapter_type) 334344f05562SScott Long { 334444f05562SScott Long case ACB_ADAPTER_TYPE_A: 3345d74001adSXin LI case ACB_ADAPTER_TYPE_C: 3346d74001adSXin LI break; 334744f05562SScott Long case ACB_ADAPTER_TYPE_B: { 3348d74001adSXin LI CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell,ARCMSR_MESSAGE_ACTIVE_EOI_MODE); 334944f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 3350d74001adSXin LI printf( "arcmsr%d: 'iop enable eoi mode' timeout \n", acb->pci_unit); 3351d74001adSXin LI 335244f05562SScott Long return; 335344f05562SScott Long } 335444f05562SScott Long } 335544f05562SScott Long break; 335644f05562SScott Long } 335744f05562SScott Long return; 335844f05562SScott Long } 335944f05562SScott Long /* 336044f05562SScott Long ********************************************************************** 3361ad6d6297SScott Long ********************************************************************** 3362ad6d6297SScott Long */ 3363ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb) 3364ad6d6297SScott Long { 336544f05562SScott Long u_int32_t intmask_org; 3366ad6d6297SScott Long 336744f05562SScott Long /* disable all outbound interrupt */ 336844f05562SScott Long intmask_org=arcmsr_disable_allintr(acb); 336944f05562SScott Long arcmsr_wait_firmware_ready(acb); 337044f05562SScott Long arcmsr_iop_confirm(acb); 3371ad6d6297SScott Long arcmsr_get_firmware_spec(acb); 337244f05562SScott Long /*start background rebuild*/ 3373ad6d6297SScott Long arcmsr_start_adapter_bgrb(acb); 337444f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 337544f05562SScott Long arcmsr_clear_doorbell_queue_buffer(acb); 337644f05562SScott Long arcmsr_enable_eoi_mode(acb); 337744f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 337844f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 3379ad6d6297SScott Long acb->acb_flags |=ACB_F_IOP_INITED; 3380ad6d6297SScott Long return; 3381ad6d6297SScott Long } 3382ad6d6297SScott Long /* 3383ad6d6297SScott Long ********************************************************************** 3384f1c579b1SScott Long ********************************************************************** 3385f1c579b1SScott Long */ 3386231c8b71SXin LI static void arcmsr_map_free_srb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 3387f1c579b1SScott Long { 3388ad6d6297SScott Long struct AdapterControlBlock *acb=arg; 3389ad6d6297SScott Long struct CommandControlBlock *srb_tmp; 3390ad6d6297SScott Long u_int8_t * dma_memptr; 339144f05562SScott Long u_int32_t i; 3392ad6d6297SScott Long unsigned long srb_phyaddr=(unsigned long)segs->ds_addr; 3393f1c579b1SScott Long 3394ad6d6297SScott Long dma_memptr=acb->uncacheptr; 3395d74001adSXin LI acb->srb_phyaddr.phyaddr=srb_phyaddr; 3396ad6d6297SScott Long srb_tmp=(struct CommandControlBlock *)dma_memptr; 3397ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 339844f05562SScott Long if(bus_dmamap_create(acb->dm_segs_dmat, 339944f05562SScott Long /*flags*/0, &srb_tmp->dm_segs_dmamap)!=0) { 3400ad6d6297SScott Long acb->acb_flags |= ACB_F_MAPFREESRB_FAILD; 340144f05562SScott Long printf("arcmsr%d:" 340244f05562SScott Long " srb dmamap bus_dmamap_create error\n", acb->pci_unit); 3403ad6d6297SScott Long return; 3404ad6d6297SScott Long } 3405d74001adSXin LI srb_tmp->cdb_shifted_phyaddr=(acb->adapter_type==ACB_ADAPTER_TYPE_C)?srb_phyaddr:(srb_phyaddr >> 5); 3406ad6d6297SScott Long srb_tmp->acb=acb; 3407ad6d6297SScott Long acb->srbworkingQ[i]=acb->psrb_pool[i]=srb_tmp; 340822f2616bSXin LI srb_phyaddr=srb_phyaddr+SRB_SIZE; 340922f2616bSXin LI srb_tmp = (struct CommandControlBlock *)((unsigned long)srb_tmp+SRB_SIZE); 3410ad6d6297SScott Long } 3411ad6d6297SScott Long acb->vir2phy_offset=(unsigned long)srb_tmp-(unsigned long)srb_phyaddr; 3412f1c579b1SScott Long return; 3413f1c579b1SScott Long } 3414f1c579b1SScott Long /* 3415f1c579b1SScott Long ************************************************************************ 3416f1c579b1SScott Long ** 3417f1c579b1SScott Long ** 3418f1c579b1SScott Long ************************************************************************ 3419f1c579b1SScott Long */ 3420ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb) 3421f1c579b1SScott Long { 3422f1c579b1SScott Long /* remove the control device */ 3423ad6d6297SScott Long if(acb->ioctl_dev != NULL) { 3424ad6d6297SScott Long destroy_dev(acb->ioctl_dev); 3425f1c579b1SScott Long } 3426ad6d6297SScott Long bus_dmamap_unload(acb->srb_dmat, acb->srb_dmamap); 3427ad6d6297SScott Long bus_dmamap_destroy(acb->srb_dmat, acb->srb_dmamap); 3428ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 3429ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 3430ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 3431f1c579b1SScott Long return; 3432f1c579b1SScott Long } 3433f1c579b1SScott Long /* 3434f1c579b1SScott Long ************************************************************************ 3435f1c579b1SScott Long ************************************************************************ 3436f1c579b1SScott Long */ 3437ad6d6297SScott Long static u_int32_t arcmsr_initialize(device_t dev) 3438f1c579b1SScott Long { 3439ad6d6297SScott Long struct AdapterControlBlock *acb=device_get_softc(dev); 3440ad6d6297SScott Long u_int16_t pci_command; 344144f05562SScott Long int i, j,max_coherent_size; 3442f1c579b1SScott Long 344344f05562SScott Long switch (pci_get_devid(dev)) { 3444d74001adSXin LI case PCIDevVenIDARC1880: { 3445d74001adSXin LI acb->adapter_type=ACB_ADAPTER_TYPE_C; 3446d74001adSXin LI max_coherent_size=ARCMSR_SRBS_POOL_SIZE; 3447d74001adSXin LI } 3448d74001adSXin LI break; 3449231c8b71SXin LI case PCIDevVenIDARC1200: 345044f05562SScott Long case PCIDevVenIDARC1201: { 345144f05562SScott Long acb->adapter_type=ACB_ADAPTER_TYPE_B; 3452d74001adSXin LI max_coherent_size=ARCMSR_SRBS_POOL_SIZE+(sizeof(struct HBB_MessageUnit)); 345344f05562SScott Long } 345444f05562SScott Long break; 345544f05562SScott Long case PCIDevVenIDARC1110: 345644f05562SScott Long case PCIDevVenIDARC1120: 345744f05562SScott Long case PCIDevVenIDARC1130: 345844f05562SScott Long case PCIDevVenIDARC1160: 345944f05562SScott Long case PCIDevVenIDARC1170: 346044f05562SScott Long case PCIDevVenIDARC1210: 346144f05562SScott Long case PCIDevVenIDARC1220: 346244f05562SScott Long case PCIDevVenIDARC1230: 3463231c8b71SXin LI case PCIDevVenIDARC1231: 346444f05562SScott Long case PCIDevVenIDARC1260: 3465231c8b71SXin LI case PCIDevVenIDARC1261: 346644f05562SScott Long case PCIDevVenIDARC1270: 346744f05562SScott Long case PCIDevVenIDARC1280: 3468d74001adSXin LI case PCIDevVenIDARC1212: 3469d74001adSXin LI case PCIDevVenIDARC1222: 347044f05562SScott Long case PCIDevVenIDARC1380: 347144f05562SScott Long case PCIDevVenIDARC1381: 347244f05562SScott Long case PCIDevVenIDARC1680: 347344f05562SScott Long case PCIDevVenIDARC1681: { 347444f05562SScott Long acb->adapter_type=ACB_ADAPTER_TYPE_A; 347544f05562SScott Long max_coherent_size=ARCMSR_SRBS_POOL_SIZE; 347644f05562SScott Long } 347744f05562SScott Long break; 347844f05562SScott Long default: { 347944f05562SScott Long printf("arcmsr%d:" 348044f05562SScott Long " unknown RAID adapter type \n", device_get_unit(dev)); 348144f05562SScott Long return ENOMEM; 348244f05562SScott Long } 348344f05562SScott Long } 3484f1c579b1SScott Long if(bus_dma_tag_create( /*parent*/ NULL, 3485f1c579b1SScott Long /*alignemnt*/ 1, 3486f1c579b1SScott Long /*boundary*/ 0, 3487701d9f1fSScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 3488f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 3489f1c579b1SScott Long /*filter*/ NULL, 3490f1c579b1SScott Long /*filterarg*/ NULL, 3491f1c579b1SScott Long /*maxsize*/ BUS_SPACE_MAXSIZE_32BIT, 3492f1c579b1SScott Long /*nsegments*/ BUS_SPACE_UNRESTRICTED, 3493f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 3494f1c579b1SScott Long /*flags*/ 0, 349522f2616bSXin LI #if __FreeBSD_version >= 501102 3496f1c579b1SScott Long /*lockfunc*/ NULL, 3497f1c579b1SScott Long /*lockarg*/ NULL, 3498f1c579b1SScott Long #endif 3499231c8b71SXin LI &acb->parent_dmat) != 0) 3500f1c579b1SScott Long { 350144f05562SScott Long printf("arcmsr%d: parent_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 3502f1c579b1SScott Long return ENOMEM; 3503f1c579b1SScott Long } 3504231c8b71SXin LI 3505f1c579b1SScott Long /* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */ 3506ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 3507f1c579b1SScott Long /*alignment*/ 1, 3508f1c579b1SScott Long /*boundary*/ 0, 350922f2616bSXin LI #ifdef PAE 351022f2616bSXin LI /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 351122f2616bSXin LI #else 3512f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 351322f2616bSXin LI #endif 3514f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 3515f1c579b1SScott Long /*filter*/ NULL, 3516f1c579b1SScott Long /*filterarg*/ NULL, 3517231c8b71SXin LI /*maxsize*/ ARCMSR_MAX_SG_ENTRIES * PAGE_SIZE * ARCMSR_MAX_FREESRB_NUM, 3518f1c579b1SScott Long /*nsegments*/ ARCMSR_MAX_SG_ENTRIES, 3519f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 3520ad6d6297SScott Long /*flags*/ 0, 352122f2616bSXin LI #if __FreeBSD_version >= 501102 3522f1c579b1SScott Long /*lockfunc*/ busdma_lock_mutex, 35235878cbecSScott Long /*lockarg*/ &acb->qbuffer_lock, 3524f1c579b1SScott Long #endif 3525231c8b71SXin LI &acb->dm_segs_dmat) != 0) 3526f1c579b1SScott Long { 3527ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 352844f05562SScott Long printf("arcmsr%d: dm_segs_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 3529f1c579b1SScott Long return ENOMEM; 3530f1c579b1SScott Long } 3531231c8b71SXin LI 3532ad6d6297SScott Long /* DMA tag for our srb structures.... Allocate the freesrb memory */ 3533ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 353444f05562SScott Long /*alignment*/ 0x20, 3535f1c579b1SScott Long /*boundary*/ 0, 3536f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 3537f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 3538f1c579b1SScott Long /*filter*/ NULL, 3539f1c579b1SScott Long /*filterarg*/ NULL, 354044f05562SScott Long /*maxsize*/ max_coherent_size, 3541f1c579b1SScott Long /*nsegments*/ 1, 3542f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 3543701d9f1fSScott Long /*flags*/ 0, 354422f2616bSXin LI #if __FreeBSD_version >= 501102 3545f1c579b1SScott Long /*lockfunc*/ NULL, 3546f1c579b1SScott Long /*lockarg*/ NULL, 3547f1c579b1SScott Long #endif 3548231c8b71SXin LI &acb->srb_dmat) != 0) 3549f1c579b1SScott Long { 3550ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 3551ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 355244f05562SScott Long printf("arcmsr%d: srb_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 3553f1c579b1SScott Long return ENXIO; 3554f1c579b1SScott Long } 3555f1c579b1SScott Long /* Allocation for our srbs */ 3556d74001adSXin LI if(bus_dmamem_alloc(acb->srb_dmat, (void **)&acb->uncacheptr, BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &acb->srb_dmamap) != 0) { 3557ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 3558ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 3559ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 356044f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamem_alloc failure!\n", device_get_unit(dev)); 3561f1c579b1SScott Long return ENXIO; 3562f1c579b1SScott Long } 3563f1c579b1SScott Long /* And permanently map them */ 3564231c8b71SXin LI if(bus_dmamap_load(acb->srb_dmat, acb->srb_dmamap, acb->uncacheptr, max_coherent_size, arcmsr_map_free_srb, acb, /*flags*/0)) { 3565ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 3566ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 3567ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 356844f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamap_load failure!\n", device_get_unit(dev)); 3569f1c579b1SScott Long return ENXIO; 3570f1c579b1SScott Long } 3571f1c579b1SScott Long pci_command=pci_read_config(dev, PCIR_COMMAND, 2); 3572f1c579b1SScott Long pci_command |= PCIM_CMD_BUSMASTEREN; 3573f1c579b1SScott Long pci_command |= PCIM_CMD_PERRESPEN; 3574f1c579b1SScott Long pci_command |= PCIM_CMD_MWRICEN; 3575f1c579b1SScott Long /* Enable Busmaster/Mem */ 3576f1c579b1SScott Long pci_command |= PCIM_CMD_MEMEN; 3577f1c579b1SScott Long pci_write_config(dev, PCIR_COMMAND, pci_command, 2); 357844f05562SScott Long switch(acb->adapter_type) { 357944f05562SScott Long case ACB_ADAPTER_TYPE_A: { 358044f05562SScott Long u_int32_t rid0=PCIR_BAR(0); 358144f05562SScott Long vm_offset_t mem_base0; 358244f05562SScott Long 3583d74001adSXin LI acb->sys_res_arcmsr[0]=bus_alloc_resource(dev,SYS_RES_MEMORY, &rid0, 0ul, ~0ul, 0x1000, RF_ACTIVE); 358444f05562SScott Long if(acb->sys_res_arcmsr[0] == NULL) { 3585ad6d6297SScott Long arcmsr_free_resource(acb); 3586d74001adSXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 3587f1c579b1SScott Long return ENOMEM; 3588f1c579b1SScott Long } 358944f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 3590ad6d6297SScott Long arcmsr_free_resource(acb); 3591d74001adSXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 3592f1c579b1SScott Long return ENXIO; 3593f1c579b1SScott Long } 359444f05562SScott Long mem_base0=(vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 359544f05562SScott Long if(mem_base0==0) { 3596ad6d6297SScott Long arcmsr_free_resource(acb); 3597d74001adSXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 3598f1c579b1SScott Long return ENXIO; 3599f1c579b1SScott Long } 360044f05562SScott Long acb->btag[0]=rman_get_bustag(acb->sys_res_arcmsr[0]); 360144f05562SScott Long acb->bhandle[0]=rman_get_bushandle(acb->sys_res_arcmsr[0]); 360244f05562SScott Long acb->pmu=(struct MessageUnit_UNION *)mem_base0; 360344f05562SScott Long } 360444f05562SScott Long break; 360544f05562SScott Long case ACB_ADAPTER_TYPE_B: { 360644f05562SScott Long struct HBB_MessageUnit *phbbmu; 360744f05562SScott Long struct CommandControlBlock *freesrb; 360844f05562SScott Long u_int32_t rid[]={ PCIR_BAR(0), PCIR_BAR(2) }; 360944f05562SScott Long vm_offset_t mem_base[]={0,0}; 361044f05562SScott Long for(i=0; i<2; i++) { 361144f05562SScott Long if(i==0) { 3612d74001adSXin LI acb->sys_res_arcmsr[i]=bus_alloc_resource(dev,SYS_RES_MEMORY, &rid[i], 3613231c8b71SXin LI 0ul, ~0ul, sizeof(struct HBB_DOORBELL), RF_ACTIVE); 361444f05562SScott Long } else { 3615d74001adSXin LI acb->sys_res_arcmsr[i]=bus_alloc_resource(dev, SYS_RES_MEMORY, &rid[i], 3616231c8b71SXin LI 0ul, ~0ul, sizeof(struct HBB_RWBUFFER), RF_ACTIVE); 361744f05562SScott Long } 361844f05562SScott Long if(acb->sys_res_arcmsr[i] == NULL) { 361944f05562SScott Long arcmsr_free_resource(acb); 3620d74001adSXin LI printf("arcmsr%d: bus_alloc_resource %d failure!\n", device_get_unit(dev), i); 362144f05562SScott Long return ENOMEM; 362244f05562SScott Long } 362344f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[i]) <= 0) { 362444f05562SScott Long arcmsr_free_resource(acb); 3625d74001adSXin LI printf("arcmsr%d: rman_get_start %d failure!\n", device_get_unit(dev), i); 362644f05562SScott Long return ENXIO; 362744f05562SScott Long } 362844f05562SScott Long mem_base[i]=(vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[i]); 362944f05562SScott Long if(mem_base[i]==0) { 363044f05562SScott Long arcmsr_free_resource(acb); 3631d74001adSXin LI printf("arcmsr%d: rman_get_virtual %d failure!\n", device_get_unit(dev), i); 363244f05562SScott Long return ENXIO; 363344f05562SScott Long } 363444f05562SScott Long acb->btag[i]=rman_get_bustag(acb->sys_res_arcmsr[i]); 363544f05562SScott Long acb->bhandle[i]=rman_get_bushandle(acb->sys_res_arcmsr[i]); 363644f05562SScott Long } 363744f05562SScott Long freesrb=(struct CommandControlBlock *)acb->uncacheptr; 363822f2616bSXin LI // acb->pmu=(struct MessageUnit_UNION *)&freesrb[ARCMSR_MAX_FREESRB_NUM]; 363922f2616bSXin LI acb->pmu=(struct MessageUnit_UNION *)((unsigned long)freesrb+ARCMSR_SRBS_POOL_SIZE); 364044f05562SScott Long phbbmu=(struct HBB_MessageUnit *)acb->pmu; 364144f05562SScott Long phbbmu->hbb_doorbell=(struct HBB_DOORBELL *)mem_base[0]; 364244f05562SScott Long phbbmu->hbb_rwbuffer=(struct HBB_RWBUFFER *)mem_base[1]; 364344f05562SScott Long } 364444f05562SScott Long break; 3645d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3646d74001adSXin LI u_int32_t rid0=PCIR_BAR(1); 3647d74001adSXin LI vm_offset_t mem_base0; 3648d74001adSXin LI 3649d74001adSXin LI acb->sys_res_arcmsr[0]=bus_alloc_resource(dev,SYS_RES_MEMORY, &rid0, 0ul, ~0ul, sizeof(struct HBC_MessageUnit), RF_ACTIVE); 3650d74001adSXin LI if(acb->sys_res_arcmsr[0] == NULL) { 3651d74001adSXin LI arcmsr_free_resource(acb); 3652d74001adSXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 3653d74001adSXin LI return ENOMEM; 3654d74001adSXin LI } 3655d74001adSXin LI if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 3656d74001adSXin LI arcmsr_free_resource(acb); 3657d74001adSXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 3658d74001adSXin LI return ENXIO; 3659d74001adSXin LI } 3660d74001adSXin LI mem_base0=(vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 3661d74001adSXin LI if(mem_base0==0) { 3662d74001adSXin LI arcmsr_free_resource(acb); 3663d74001adSXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 3664d74001adSXin LI return ENXIO; 3665d74001adSXin LI } 3666d74001adSXin LI acb->btag[0]=rman_get_bustag(acb->sys_res_arcmsr[0]); 3667d74001adSXin LI acb->bhandle[0]=rman_get_bushandle(acb->sys_res_arcmsr[0]); 3668d74001adSXin LI acb->pmu=(struct MessageUnit_UNION *)mem_base0; 3669d74001adSXin LI } 3670d74001adSXin LI break; 367144f05562SScott Long } 3672ad6d6297SScott Long if(acb->acb_flags & ACB_F_MAPFREESRB_FAILD) { 3673ad6d6297SScott Long arcmsr_free_resource(acb); 367444f05562SScott Long printf("arcmsr%d: map free srb failure!\n", device_get_unit(dev)); 3675f1c579b1SScott Long return ENXIO; 3676f1c579b1SScott Long } 3677d74001adSXin LI acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_RQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ); 3678ad6d6297SScott Long acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; 3679ad6d6297SScott Long /* 3680ad6d6297SScott Long ******************************************************************** 3681ad6d6297SScott Long ** init raid volume state 3682ad6d6297SScott Long ******************************************************************** 3683ad6d6297SScott Long */ 3684ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_TARGETID;i++) { 3685ad6d6297SScott Long for(j=0;j<ARCMSR_MAX_TARGETLUN;j++) { 368644f05562SScott Long acb->devstate[i][j]=ARECA_RAID_GONE; 3687ad6d6297SScott Long } 3688ad6d6297SScott Long } 3689ad6d6297SScott Long arcmsr_iop_init(acb); 3690f1c579b1SScott Long return(0); 3691f1c579b1SScott Long } 3692f1c579b1SScott Long /* 3693f1c579b1SScott Long ************************************************************************ 3694f1c579b1SScott Long ************************************************************************ 3695f1c579b1SScott Long */ 3696f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev) 3697f1c579b1SScott Long { 3698ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 3699ad6d6297SScott Long u_int32_t unit=device_get_unit(dev); 3700f1c579b1SScott Long struct ccb_setasync csa; 3701f1c579b1SScott Long struct cam_devq *devq; /* Device Queue to use for this SIM */ 3702f1c579b1SScott Long struct resource *irqres; 3703f1c579b1SScott Long int rid; 3704f1c579b1SScott Long 3705ad6d6297SScott Long if(acb == NULL) { 3706ad6d6297SScott Long printf("arcmsr%d: cannot allocate softc\n", unit); 3707ad6d6297SScott Long return (ENOMEM); 3708ad6d6297SScott Long } 37095878cbecSScott Long ARCMSR_LOCK_INIT(&acb->qbuffer_lock, "arcmsr Q buffer lock"); 3710ad6d6297SScott Long if(arcmsr_initialize(dev)) { 3711ad6d6297SScott Long printf("arcmsr%d: initialize failure!\n", unit); 37125878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3713f1c579b1SScott Long return ENXIO; 3714f1c579b1SScott Long } 3715f1c579b1SScott Long /* After setting up the adapter, map our interrupt */ 3716f1c579b1SScott Long rid=0; 3717ad6d6297SScott Long irqres=bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE); 3718ad6d6297SScott Long if(irqres == NULL || 371944f05562SScott Long #if __FreeBSD_version >= 700025 3720d74001adSXin LI bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, NULL, arcmsr_intr_handler, acb, &acb->ih)) { 372144f05562SScott Long #else 3722d74001adSXin LI bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, arcmsr_intr_handler, acb, &acb->ih)) { 372344f05562SScott Long #endif 3724ad6d6297SScott Long arcmsr_free_resource(acb); 37255878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3726f1c579b1SScott Long printf("arcmsr%d: unable to register interrupt handler!\n", unit); 3727f1c579b1SScott Long return ENXIO; 3728f1c579b1SScott Long } 3729ad6d6297SScott Long acb->irqres=irqres; 3730ad6d6297SScott Long acb->pci_dev=dev; 3731ad6d6297SScott Long acb->pci_unit=unit; 3732f1c579b1SScott Long /* 3733f1c579b1SScott Long * Now let the CAM generic SCSI layer find the SCSI devices on 3734f1c579b1SScott Long * the bus * start queue to reset to the idle loop. * 3735f1c579b1SScott Long * Create device queue of SIM(s) * (MAX_START_JOB - 1) : 3736f1c579b1SScott Long * max_sim_transactions 3737f1c579b1SScott Long */ 3738f1c579b1SScott Long devq=cam_simq_alloc(ARCMSR_MAX_START_JOB); 3739ad6d6297SScott Long if(devq == NULL) { 3740ad6d6297SScott Long arcmsr_free_resource(acb); 3741ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 37425878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3743ad6d6297SScott Long printf("arcmsr%d: cam_simq_alloc failure!\n", unit); 3744f1c579b1SScott Long return ENXIO; 3745f1c579b1SScott Long } 374644f05562SScott Long #if __FreeBSD_version >= 700025 3747d74001adSXin LI acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, &acb->qbuffer_lock, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq); 374844f05562SScott Long #else 3749d74001adSXin LI acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq); 375044f05562SScott Long #endif 3751ad6d6297SScott Long if(acb->psim == NULL) { 3752ad6d6297SScott Long arcmsr_free_resource(acb); 3753ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 3754f1c579b1SScott Long cam_simq_free(devq); 37555878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3756ad6d6297SScott Long printf("arcmsr%d: cam_sim_alloc failure!\n", unit); 3757f1c579b1SScott Long return ENXIO; 3758f1c579b1SScott Long } 37595878cbecSScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 3760f40b4cabSScott Long #if __FreeBSD_version >= 700044 3761b50569b7SScott Long if(xpt_bus_register(acb->psim, dev, 0) != CAM_SUCCESS) { 376244f05562SScott Long #else 376344f05562SScott Long if(xpt_bus_register(acb->psim, 0) != CAM_SUCCESS) { 376444f05562SScott Long #endif 3765ad6d6297SScott Long arcmsr_free_resource(acb); 3766ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 3767ad6d6297SScott Long cam_sim_free(acb->psim, /*free_devq*/TRUE); 37685878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3769ad6d6297SScott Long printf("arcmsr%d: xpt_bus_register failure!\n", unit); 3770f1c579b1SScott Long return ENXIO; 3771f1c579b1SScott Long } 3772d74001adSXin LI if(xpt_create_path(&acb->ppath, /* periph */ NULL, cam_sim_path(acb->psim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 3773ad6d6297SScott Long arcmsr_free_resource(acb); 3774ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 3775ad6d6297SScott Long xpt_bus_deregister(cam_sim_path(acb->psim)); 3776ad6d6297SScott Long cam_sim_free(acb->psim, /* free_simq */ TRUE); 37775878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3778ad6d6297SScott Long printf("arcmsr%d: xpt_create_path failure!\n", unit); 3779f1c579b1SScott Long return ENXIO; 3780f1c579b1SScott Long } 3781f1c579b1SScott Long /* 3782f1c579b1SScott Long **************************************************** 3783f1c579b1SScott Long */ 3784ad6d6297SScott Long xpt_setup_ccb(&csa.ccb_h, acb->ppath, /*priority*/5); 3785f1c579b1SScott Long csa.ccb_h.func_code=XPT_SASYNC_CB; 3786f1c579b1SScott Long csa.event_enable=AC_FOUND_DEVICE|AC_LOST_DEVICE; 3787f1c579b1SScott Long csa.callback=arcmsr_async; 3788ad6d6297SScott Long csa.callback_arg=acb->psim; 3789f1c579b1SScott Long xpt_action((union ccb *)&csa); 37905878cbecSScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 3791f1c579b1SScott Long /* Create the control device. */ 3792d74001adSXin LI acb->ioctl_dev=make_dev(&arcmsr_cdevsw, unit, UID_ROOT, GID_WHEEL /* GID_OPERATOR */, S_IRUSR | S_IWUSR, "arcmsr%d", unit); 3793d74001adSXin LI 3794f1c579b1SScott Long #if __FreeBSD_version < 503000 3795ad6d6297SScott Long acb->ioctl_dev->si_drv1=acb; 3796f1c579b1SScott Long #endif 3797f1c579b1SScott Long #if __FreeBSD_version > 500005 3798ad6d6297SScott Long (void)make_dev_alias(acb->ioctl_dev, "arc%d", unit); 3799f1c579b1SScott Long #endif 380022f2616bSXin LI arcmsr_callout_init(&acb->devmap_callout); 3801d74001adSXin LI callout_reset(&acb->devmap_callout, 60 * hz, arcmsr_polling_devmap, acb); 3802f1c579b1SScott Long return 0; 3803f1c579b1SScott Long } 380422f2616bSXin LI 3805f1c579b1SScott Long /* 3806f1c579b1SScott Long ************************************************************************ 3807f1c579b1SScott Long ************************************************************************ 3808f1c579b1SScott Long */ 3809f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev) 3810f1c579b1SScott Long { 3811ad6d6297SScott Long u_int32_t id; 3812ad6d6297SScott Long static char buf[256]; 3813231c8b71SXin LI char x_type[]={"X-TYPE"}; 3814ad6d6297SScott Long char *type; 3815ad6d6297SScott Long int raid6 = 1; 3816ad6d6297SScott Long 3817ad6d6297SScott Long if (pci_get_vendor(dev) != PCI_VENDOR_ID_ARECA) { 3818ad6d6297SScott Long return (ENXIO); 3819ad6d6297SScott Long } 3820ad6d6297SScott Long switch(id=pci_get_devid(dev)) { 3821f1c579b1SScott Long case PCIDevVenIDARC1110: 3822231c8b71SXin LI case PCIDevVenIDARC1200: 382344f05562SScott Long case PCIDevVenIDARC1201: 3824231c8b71SXin LI case PCIDevVenIDARC1210: 3825ad6d6297SScott Long raid6 = 0; 3826ad6d6297SScott Long /*FALLTHRU*/ 3827ad6d6297SScott Long case PCIDevVenIDARC1120: 3828ad6d6297SScott Long case PCIDevVenIDARC1130: 3829ad6d6297SScott Long case PCIDevVenIDARC1160: 3830ad6d6297SScott Long case PCIDevVenIDARC1170: 3831f1c579b1SScott Long case PCIDevVenIDARC1220: 3832f1c579b1SScott Long case PCIDevVenIDARC1230: 3833231c8b71SXin LI case PCIDevVenIDARC1231: 3834f1c579b1SScott Long case PCIDevVenIDARC1260: 3835231c8b71SXin LI case PCIDevVenIDARC1261: 3836ad6d6297SScott Long case PCIDevVenIDARC1270: 3837ad6d6297SScott Long case PCIDevVenIDARC1280: 3838ad6d6297SScott Long type = "SATA"; 3839ad6d6297SScott Long break; 3840d74001adSXin LI case PCIDevVenIDARC1212: 3841d74001adSXin LI case PCIDevVenIDARC1222: 3842ad6d6297SScott Long case PCIDevVenIDARC1380: 3843ad6d6297SScott Long case PCIDevVenIDARC1381: 3844ad6d6297SScott Long case PCIDevVenIDARC1680: 3845ad6d6297SScott Long case PCIDevVenIDARC1681: 3846d74001adSXin LI type = "SAS 3G"; 3847d74001adSXin LI break; 3848d74001adSXin LI case PCIDevVenIDARC1880: 3849d74001adSXin LI type = "SAS 6G"; 3850ad6d6297SScott Long break; 3851ad6d6297SScott Long default: 3852231c8b71SXin LI type = x_type; 3853ad6d6297SScott Long break; 3854f1c579b1SScott Long } 3855231c8b71SXin LI if(type == x_type) 3856231c8b71SXin LI return(ENXIO); 3857ad6d6297SScott Long sprintf(buf, "Areca %s Host Adapter RAID Controller %s\n", type, raid6 ? "(RAID6 capable)" : ""); 3858ad6d6297SScott Long device_set_desc_copy(dev, buf); 3859ad6d6297SScott Long return 0; 3860f1c579b1SScott Long } 3861f1c579b1SScott Long /* 3862f1c579b1SScott Long ************************************************************************ 3863f1c579b1SScott Long ************************************************************************ 3864f1c579b1SScott Long */ 3865f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev) 3866f1c579b1SScott Long { 386744f05562SScott Long u_int32_t i; 3868ad6d6297SScott Long u_int32_t intmask_org; 3869ad6d6297SScott Long struct CommandControlBlock *srb; 3870ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 3871f1c579b1SScott Long 3872f1c579b1SScott Long /* stop adapter background rebuild */ 38735878cbecSScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 387444f05562SScott Long /* disable all outbound interrupt */ 387544f05562SScott Long intmask_org=arcmsr_disable_allintr(acb); 3876ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 3877ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 3878f1c579b1SScott Long /* abort all outstanding command */ 3879ad6d6297SScott Long acb->acb_flags |= ACB_F_SCSISTOPADAPTER; 3880ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOP_INITED; 3881ad6d6297SScott Long if(acb->srboutstandingcount!=0) { 388244f05562SScott Long /*clear and abort all outbound posted Q*/ 388344f05562SScott Long arcmsr_done4abort_postqueue(acb); 388444f05562SScott Long /* talk to iop 331 outstanding command aborted*/ 3885ad6d6297SScott Long arcmsr_abort_allcmd(acb); 3886ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 3887ad6d6297SScott Long srb=acb->psrb_pool[i]; 388822f2616bSXin LI if(srb->srb_state==ARCMSR_SRB_START) { 388922f2616bSXin LI srb->srb_state=ARCMSR_SRB_ABORTED; 3890ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 3891ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 3892f1c579b1SScott Long } 3893f1c579b1SScott Long } 3894f1c579b1SScott Long } 389522f2616bSXin LI acb->srboutstandingcount=0; 3896ad6d6297SScott Long acb->workingsrb_doneindex=0; 3897ad6d6297SScott Long acb->workingsrb_startindex=0; 389822f2616bSXin LI #ifdef ARCMSR_DEBUG1 389922f2616bSXin LI acb->pktRequestCount = 0; 390022f2616bSXin LI acb->pktReturnCount = 0; 390122f2616bSXin LI #endif 39025878cbecSScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 3903f2aa0e9fSWarner Losh return (0); 3904f1c579b1SScott Long } 3905f1c579b1SScott Long /* 3906f1c579b1SScott Long ************************************************************************ 3907f1c579b1SScott Long ************************************************************************ 3908f1c579b1SScott Long */ 3909f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev) 3910f1c579b1SScott Long { 3911ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 391244f05562SScott Long int i; 3913f1c579b1SScott Long 3914d74001adSXin LI callout_stop(&acb->devmap_callout); 39155878cbecSScott Long bus_teardown_intr(dev, acb->irqres, acb->ih); 3916f1c579b1SScott Long arcmsr_shutdown(dev); 3917ad6d6297SScott Long arcmsr_free_resource(acb); 391844f05562SScott Long for(i=0; (acb->sys_res_arcmsr[i]!=NULL) && (i<2); i++) { 391944f05562SScott Long bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(i), acb->sys_res_arcmsr[i]); 392044f05562SScott Long } 3921ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 39225878cbecSScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 3923ad6d6297SScott Long xpt_async(AC_LOST_DEVICE, acb->ppath, NULL); 3924ad6d6297SScott Long xpt_free_path(acb->ppath); 3925ad6d6297SScott Long xpt_bus_deregister(cam_sim_path(acb->psim)); 3926ad6d6297SScott Long cam_sim_free(acb->psim, TRUE); 39275878cbecSScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 39285878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3929f1c579b1SScott Long return (0); 3930f1c579b1SScott Long } 3931f1c579b1SScott Long 393222f2616bSXin LI #ifdef ARCMSR_DEBUG1 393322f2616bSXin LI static void arcmsr_dump_data(struct AdapterControlBlock *acb) 393422f2616bSXin LI { 393522f2616bSXin LI if((acb->pktRequestCount - acb->pktReturnCount) == 0) 393622f2616bSXin LI return; 393722f2616bSXin LI printf("Command Request Count =0x%x\n",acb->pktRequestCount); 393822f2616bSXin LI printf("Command Return Count =0x%x\n",acb->pktReturnCount); 393922f2616bSXin LI printf("Command (Req-Rtn) Count =0x%x\n",(acb->pktRequestCount - acb->pktReturnCount)); 394022f2616bSXin LI printf("Queued Command Count =0x%x\n",acb->srboutstandingcount); 394122f2616bSXin LI } 394222f2616bSXin LI #endif 3943f1c579b1SScott Long 3944