1f1c579b1SScott Long /* 246a7789eSMatt Jacob ***************************************************************************************** 3f1c579b1SScott Long ** O.S : FreeBSD 4f1c579b1SScott Long ** FILE NAME : arcmsr.c 5f1c579b1SScott Long ** BY : Erich Chen 6f1c579b1SScott Long ** Description: SCSI RAID Device Driver for 7ad6d6297SScott Long ** ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX) 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 ** 13f1c579b1SScott Long ** Copyright (c) 2004-2006 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 41f1c579b1SScott Long ** 1.00.00.00 3/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 43ad6d6297SScott Long ** 1.20.00.03 4/19/2005 Erich Chen add SATA 24 Ports adapter type support 44ad6d6297SScott Long ** clean unused function 45ad6d6297SScott Long ** 1.20.00.12 9/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 50ad6d6297SScott Long ** 1.20.00.13 8/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 57f48f00a1SScott Long 58f1c579b1SScott Long ****************************************************************************************** 59ad6d6297SScott Long * $FreeBSD$ 60f1c579b1SScott Long */ 61f1c579b1SScott Long #include <sys/param.h> 62f1c579b1SScott Long #include <sys/systm.h> 63f1c579b1SScott Long #include <sys/malloc.h> 64f1c579b1SScott Long #include <sys/kernel.h> 65f1c579b1SScott Long #include <sys/bus.h> 66f1c579b1SScott Long #include <sys/queue.h> 67f1c579b1SScott Long #include <sys/stat.h> 68f1c579b1SScott Long #include <sys/devicestat.h> 69f1c579b1SScott Long #include <sys/kthread.h> 70f1c579b1SScott Long #include <sys/module.h> 71f1c579b1SScott Long #include <sys/proc.h> 72f1c579b1SScott Long #include <sys/lock.h> 73f1c579b1SScott Long #include <sys/sysctl.h> 74f1c579b1SScott Long #include <sys/poll.h> 75f1c579b1SScott Long #include <sys/ioccom.h> 76f1c579b1SScott Long #include <vm/vm.h> 77f1c579b1SScott Long #include <vm/vm_param.h> 78f1c579b1SScott Long #include <vm/pmap.h> 79f1c579b1SScott Long 80f1c579b1SScott Long #include <isa/rtc.h> 81f1c579b1SScott Long 82f1c579b1SScott Long #include <machine/bus.h> 83f1c579b1SScott Long #include <machine/resource.h> 84f1c579b1SScott Long #include <machine/atomic.h> 85f1c579b1SScott Long #include <sys/conf.h> 86f1c579b1SScott Long #include <sys/rman.h> 87f1c579b1SScott Long 88f1c579b1SScott Long #include <cam/cam.h> 89f1c579b1SScott Long #include <cam/cam_ccb.h> 90f1c579b1SScott Long #include <cam/cam_sim.h> 91f1c579b1SScott Long #include <cam/cam_xpt_sim.h> 92f1c579b1SScott Long #include <cam/cam_debug.h> 93f1c579b1SScott Long #include <cam/scsi/scsi_all.h> 94f1c579b1SScott Long #include <cam/scsi/scsi_message.h> 95f1c579b1SScott Long /* 96f1c579b1SScott Long ************************************************************************** 97f1c579b1SScott Long ************************************************************************** 98f1c579b1SScott Long */ 99f1c579b1SScott Long #if __FreeBSD_version >= 500005 100f1c579b1SScott Long #include <sys/selinfo.h> 101f1c579b1SScott Long #include <sys/mutex.h> 102ad6d6297SScott Long #include <sys/endian.h> 103f1c579b1SScott Long #include <dev/pci/pcivar.h> 104f1c579b1SScott Long #include <dev/pci/pcireg.h> 105f1c579b1SScott Long #define ARCMSR_LOCK_INIT(l, s) mtx_init(l, s, NULL, MTX_DEF|MTX_RECURSE) 106f1c579b1SScott Long #define ARCMSR_LOCK_ACQUIRE(l) mtx_lock(l) 107f1c579b1SScott Long #define ARCMSR_LOCK_RELEASE(l) mtx_unlock(l) 108ad6d6297SScott Long #define ARCMSR_LOCK_TRY(l) mtx_trylock(l) 109ad6d6297SScott Long #define arcmsr_htole32(x) htole32(x) 110f1c579b1SScott Long typedef struct mtx arcmsr_lock_t; 111f1c579b1SScott Long #else 112f1c579b1SScott Long #include <sys/select.h> 113f1c579b1SScott Long #include <pci/pcivar.h> 114f1c579b1SScott Long #include <pci/pcireg.h> 115f1c579b1SScott Long #define ARCMSR_LOCK_INIT(l, s) simple_lock_init(l) 116f1c579b1SScott Long #define ARCMSR_LOCK_ACQUIRE(l) simple_lock(l) 117f1c579b1SScott Long #define ARCMSR_LOCK_RELEASE(l) simple_unlock(l) 118ad6d6297SScott Long #define ARCMSR_LOCK_TRY(l) simple_lock_try(l) 119ad6d6297SScott Long #define arcmsr_htole32(x) (x) 120f1c579b1SScott Long typedef struct simplelock arcmsr_lock_t; 121f1c579b1SScott Long #endif 122f1c579b1SScott Long #include <dev/arcmsr/arcmsr.h> 123ad6d6297SScott Long #define ARCMSR_SRBS_POOL_SIZE ((sizeof(struct CommandControlBlock) * ARCMSR_MAX_FREESRB_NUM)+0x20) 124f1c579b1SScott Long /* 125f1c579b1SScott Long ************************************************************************** 126f1c579b1SScott Long ************************************************************************** 127f1c579b1SScott Long */ 128ad6d6297SScott Long #define CHIP_REG_READ32(r) bus_space_read_4(acb->btag, acb->bhandle, offsetof(struct MessageUnit,r)) 129ad6d6297SScott Long #define CHIP_REG_WRITE32(r,d) bus_space_write_4(acb->btag, acb->bhandle, offsetof(struct MessageUnit,r), d) 130f1c579b1SScott Long /* 131f1c579b1SScott Long ************************************************************************** 132f1c579b1SScott Long ************************************************************************** 133f1c579b1SScott Long */ 134ad6d6297SScott Long static struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb); 135ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb); 136ad6d6297SScott Long static u_int8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *acb); 137ad6d6297SScott Long static u_int32_t arcmsr_probe(device_t dev); 138ad6d6297SScott Long static u_int32_t arcmsr_attach(device_t dev); 139ad6d6297SScott Long static u_int32_t arcmsr_detach(device_t dev); 140ad6d6297SScott Long static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg); 141ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb); 142ad6d6297SScott Long static void arcmsr_shutdown(device_t dev); 143ad6d6297SScott Long static void arcmsr_interrupt(void *arg); 144ad6d6297SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb); 145ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb); 146ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb); 147ad6d6297SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); 148ad6d6297SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb); 149ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb); 150ad6d6297SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb); 151ad6d6297SScott Long static void arcmsr_post_Qbuffer(struct AdapterControlBlock *acb); 152ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb); 153ad6d6297SScott Long static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag); 154ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb); 155ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb); 156ad6d6297SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t * dm_segs, u_int32_t nseg); 157ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb); 158ad6d6297SScott Long static int arcmsr_resume(device_t dev); 159ad6d6297SScott Long static int arcmsr_suspend(device_t dev); 160f1c579b1SScott Long /* 161f1c579b1SScott Long ************************************************************************** 162ad6d6297SScott Long ************************************************************************** 163ad6d6297SScott Long */ 164ad6d6297SScott Long static void UDELAY(u_int32_t us) { DELAY(us); } 165ad6d6297SScott Long /* 166ad6d6297SScott Long ************************************************************************** 167f1c579b1SScott Long ************************************************************************** 168f1c579b1SScott Long */ 169f1c579b1SScott Long static bus_dmamap_callback_t arcmsr_map_freesrb; 170f1c579b1SScott Long static bus_dmamap_callback_t arcmsr_executesrb; 171f1c579b1SScott Long /* 172f1c579b1SScott Long ************************************************************************** 173f1c579b1SScott Long ************************************************************************** 174f1c579b1SScott Long */ 175f1c579b1SScott Long static d_open_t arcmsr_open; 176f1c579b1SScott Long static d_close_t arcmsr_close; 177f1c579b1SScott Long static d_ioctl_t arcmsr_ioctl; 178f1c579b1SScott Long 179f1c579b1SScott Long static device_method_t arcmsr_methods[]={ 180f1c579b1SScott Long DEVMETHOD(device_probe, arcmsr_probe), 181f1c579b1SScott Long DEVMETHOD(device_attach, arcmsr_attach), 182f1c579b1SScott Long DEVMETHOD(device_detach, arcmsr_detach), 183f1c579b1SScott Long DEVMETHOD(device_shutdown, arcmsr_shutdown), 184ad6d6297SScott Long DEVMETHOD(device_suspend, arcmsr_suspend), 185ad6d6297SScott Long DEVMETHOD(device_resume, arcmsr_resume), 186ad6d6297SScott Long 187ad6d6297SScott Long DEVMETHOD(bus_print_child, bus_generic_print_child), 188ad6d6297SScott Long DEVMETHOD(bus_driver_added, bus_generic_driver_added), 189f1c579b1SScott Long { 0, 0 } 190f1c579b1SScott Long }; 191f1c579b1SScott Long 192f1c579b1SScott Long static driver_t arcmsr_driver={ 193ad6d6297SScott Long "arcmsr", arcmsr_methods, sizeof(struct AdapterControlBlock) 194f1c579b1SScott Long }; 195f1c579b1SScott Long 196f1c579b1SScott Long static devclass_t arcmsr_devclass; 197f1c579b1SScott Long DRIVER_MODULE(arcmsr, pci, arcmsr_driver, arcmsr_devclass, 0, 0); 198d3cf342dSScott Long MODULE_DEPEND(arcmsr, pci, 1, 1, 1); 199d3cf342dSScott Long MODULE_DEPEND(arcmsr, cam, 1, 1, 1); 200ad6d6297SScott Long #ifndef BUS_DMA_COHERENT 201ad6d6297SScott Long #define BUS_DMA_COHERENT 0x04 /* hint: map memory in a coherent way */ 202ad6d6297SScott Long #endif 203ad6d6297SScott Long #if __FreeBSD_version >= 501000 204ad6d6297SScott Long #ifndef D_NEEDGIANT 205ad6d6297SScott Long #define D_NEEDGIANT 0x00400000 /* driver want Giant */ 206ad6d6297SScott Long #endif 207ad6d6297SScott Long #ifndef D_VERSION 208ad6d6297SScott Long #define D_VERSION 0x20011966 209ad6d6297SScott Long #endif 210f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw={ 211ad6d6297SScott Long #if __FreeBSD_version > 502010 212f1c579b1SScott Long .d_version = D_VERSION, 213ad6d6297SScott Long #endif 214f1c579b1SScott Long .d_flags = D_NEEDGIANT, 215f1c579b1SScott Long .d_open = arcmsr_open, /* open */ 216f1c579b1SScott Long .d_close = arcmsr_close, /* close */ 217f1c579b1SScott Long .d_ioctl = arcmsr_ioctl, /* ioctl */ 218f1c579b1SScott Long .d_name = "arcmsr", /* name */ 219f1c579b1SScott Long }; 220f1c579b1SScott Long #else 221f1c579b1SScott Long #define ARCMSR_CDEV_MAJOR 180 222f1c579b1SScott Long 223f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw = { 224f1c579b1SScott Long arcmsr_open, /* open */ 225f1c579b1SScott Long arcmsr_close, /* close */ 226f1c579b1SScott Long noread, /* read */ 227f1c579b1SScott Long nowrite, /* write */ 228f1c579b1SScott Long arcmsr_ioctl, /* ioctl */ 229f1c579b1SScott Long nopoll, /* poll */ 230f1c579b1SScott Long nommap, /* mmap */ 231f1c579b1SScott Long nostrategy, /* strategy */ 232f1c579b1SScott Long "arcmsr", /* name */ 233f1c579b1SScott Long ARCMSR_CDEV_MAJOR, /* major */ 234f1c579b1SScott Long nodump, /* dump */ 235f1c579b1SScott Long nopsize, /* psize */ 236f1c579b1SScott Long 0 /* flags */ 237f1c579b1SScott Long }; 238f1c579b1SScott Long #endif 239f1c579b1SScott Long 240f1c579b1SScott Long #if __FreeBSD_version < 500005 241f1c579b1SScott Long static int arcmsr_open(dev_t dev, int flags, int fmt, struct proc *proc) 242f1c579b1SScott Long #else 243f1c579b1SScott Long #if __FreeBSD_version < 503000 244f1c579b1SScott Long static int arcmsr_open(dev_t dev, int flags, int fmt, struct thread *proc) 245f1c579b1SScott Long #else 246f1c579b1SScott Long static int arcmsr_open(struct cdev *dev, int flags, int fmt, d_thread_t *proc) 247f1c579b1SScott Long #endif 248f1c579b1SScott Long #endif 249f1c579b1SScott Long { 250f1c579b1SScott Long #if __FreeBSD_version < 503000 251ad6d6297SScott Long struct AdapterControlBlock *acb=dev->si_drv1; 252f1c579b1SScott Long #else 253f1c579b1SScott Long int unit = minor(dev); 254ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 255f1c579b1SScott Long #endif 256ad6d6297SScott Long if(acb==NULL) { 257f1c579b1SScott Long return ENXIO; 258f1c579b1SScott Long } 259f1c579b1SScott Long return 0; 260f1c579b1SScott Long } 261f1c579b1SScott Long /* 262f1c579b1SScott Long ************************************************************************** 263f1c579b1SScott Long ************************************************************************** 264f1c579b1SScott Long */ 265f1c579b1SScott Long #if __FreeBSD_version < 500005 266f1c579b1SScott Long static int arcmsr_close(dev_t dev, int flags, int fmt, struct proc *proc) 267f1c579b1SScott Long #else 268f1c579b1SScott Long #if __FreeBSD_version < 503000 269f1c579b1SScott Long static int arcmsr_close(dev_t dev, int flags, int fmt, struct thread *proc) 270f1c579b1SScott Long #else 271f1c579b1SScott Long static int arcmsr_close(struct cdev *dev, int flags, int fmt, d_thread_t *proc) 272f1c579b1SScott Long #endif 273f1c579b1SScott Long #endif 274f1c579b1SScott Long { 275f1c579b1SScott Long #if __FreeBSD_version < 503000 276ad6d6297SScott Long struct AdapterControlBlock *acb=dev->si_drv1; 277f1c579b1SScott Long #else 278f1c579b1SScott Long int unit = minor(dev); 279ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 280f1c579b1SScott Long #endif 281ad6d6297SScott Long if(acb==NULL) { 282f1c579b1SScott Long return ENXIO; 283f1c579b1SScott Long } 284f1c579b1SScott Long return 0; 285f1c579b1SScott Long } 286f1c579b1SScott Long /* 287f1c579b1SScott Long ************************************************************************** 288f1c579b1SScott Long ************************************************************************** 289f1c579b1SScott Long */ 290f1c579b1SScott Long #if __FreeBSD_version < 500005 291f1c579b1SScott Long static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct proc *proc) 292f1c579b1SScott Long #else 293f1c579b1SScott Long #if __FreeBSD_version < 503000 294f1c579b1SScott Long static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc) 295f1c579b1SScott Long #else 296f1c579b1SScott Long static int arcmsr_ioctl(struct cdev *dev, u_long ioctl_cmd, caddr_t arg, int flags, d_thread_t *proc) 297f1c579b1SScott Long #endif 298f1c579b1SScott Long #endif 299f1c579b1SScott Long { 300f1c579b1SScott Long #if __FreeBSD_version < 503000 301ad6d6297SScott Long struct AdapterControlBlock *acb=dev->si_drv1; 302f1c579b1SScott Long #else 303f1c579b1SScott Long int unit = minor(dev); 304ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 305f1c579b1SScott Long #endif 306f1c579b1SScott Long 307ad6d6297SScott Long if(acb==NULL) { 308f1c579b1SScott Long return ENXIO; 309f1c579b1SScott Long } 310ad6d6297SScott Long return(arcmsr_iop_ioctlcmd(acb, ioctl_cmd, arg)); 311f1c579b1SScott Long } 312f1c579b1SScott Long /* 313ad6d6297SScott Long ******************************************************************************* 314ad6d6297SScott Long ******************************************************************************* 315f1c579b1SScott Long */ 316ad6d6297SScott Long static int arcmsr_suspend(device_t dev) 317f1c579b1SScott Long { 318ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 319ad6d6297SScott Long u_int32_t intmask_org; 320f1c579b1SScott Long 321ad6d6297SScott Long /* disable all outbound interrupt */ 322ad6d6297SScott Long intmask_org=CHIP_REG_READ32(outbound_intmask); 323ad6d6297SScott Long CHIP_REG_WRITE32(outbound_intmask, (intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE)); 324ad6d6297SScott Long /* flush controller */ 325ad6d6297SScott Long arcmsr_iop_parking(acb); 326ad6d6297SScott Long return(0); 327ad6d6297SScott Long } 328ad6d6297SScott Long /* 329ad6d6297SScott Long ******************************************************************************* 330ad6d6297SScott Long ******************************************************************************* 331ad6d6297SScott Long */ 332ad6d6297SScott Long static int arcmsr_resume(device_t dev) 333ad6d6297SScott Long { 334ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 335f1c579b1SScott Long 336ad6d6297SScott Long arcmsr_iop_init(acb); 337ad6d6297SScott Long return(0); 338f1c579b1SScott Long } 339f1c579b1SScott Long /* 340f1c579b1SScott Long ********************************************************************************* 341f1c579b1SScott Long ********************************************************************************* 342f1c579b1SScott Long */ 343ad6d6297SScott Long static void arcmsr_async(void *cb_arg, u_int32_t code, struct cam_path *path, void *arg) 344f1c579b1SScott Long { 345ad6d6297SScott Long struct AdapterControlBlock *acb; 346ad6d6297SScott Long u_int8_t target_id, target_lun; 347f1c579b1SScott Long struct cam_sim * sim; 348f1c579b1SScott Long 349f1c579b1SScott Long sim=(struct cam_sim *) cb_arg; 350ad6d6297SScott Long acb =(struct AdapterControlBlock *) cam_sim_softc(sim); 351ad6d6297SScott Long switch (code) { 352f1c579b1SScott Long case AC_LOST_DEVICE: 353f1c579b1SScott Long target_id=xpt_path_target_id(path); 354f1c579b1SScott Long target_lun=xpt_path_lun_id(path); 355ad6d6297SScott Long if((target_id > ARCMSR_MAX_TARGETID) || (target_lun > ARCMSR_MAX_TARGETLUN)) { 356f1c579b1SScott Long break; 357f1c579b1SScott Long } 358ad6d6297SScott Long printf("%s:scsi id%d lun%d device lost \n" 359ad6d6297SScott Long , device_get_name(acb->pci_dev), target_id, target_lun); 360f1c579b1SScott Long break; 361f1c579b1SScott Long default: 362f1c579b1SScott Long break; 363f1c579b1SScott Long } 364f1c579b1SScott Long } 365f1c579b1SScott Long /* 366f1c579b1SScott Long ************************************************************************ 367f1c579b1SScott Long ************************************************************************ 368f1c579b1SScott Long */ 369ad6d6297SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) 370f1c579b1SScott Long { 371ad6d6297SScott Long CHIP_REG_WRITE32(inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 372ad6d6297SScott Long if(arcmsr_wait_msgint_ready(acb)) { 373ad6d6297SScott Long printf("arcmsr%d: wait 'flush adapter cache' timeout \n" 374ad6d6297SScott Long , acb->pci_unit); 375ad6d6297SScott Long } 376f1c579b1SScott Long return; 377f1c579b1SScott Long } 378f1c579b1SScott Long /* 379f1c579b1SScott Long ********************************************************************** 380f1c579b1SScott Long ********************************************************************** 381f1c579b1SScott Long */ 382ad6d6297SScott Long static u_int8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *acb) 383f1c579b1SScott Long { 384ad6d6297SScott Long u_int32_t Index; 385ad6d6297SScott Long u_int8_t Retries=0x00; 386ad6d6297SScott Long 387ad6d6297SScott Long do { 388ad6d6297SScott Long for(Index=0; Index < 100; Index++) { 389ad6d6297SScott Long if(CHIP_REG_READ32(outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { 390ad6d6297SScott Long /*clear interrupt*/ 391ad6d6297SScott Long CHIP_REG_WRITE32(outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT); 392ad6d6297SScott Long return 0x00; 393f1c579b1SScott Long } 394f1c579b1SScott Long /* one us delay */ 395ad6d6297SScott Long UDELAY(10000); 396ad6d6297SScott Long }/*max 1 seconds*/ 397ad6d6297SScott Long }while(Retries++ < 20);/*max 20 sec*/ 398ad6d6297SScott Long return 0xff; 399f1c579b1SScott Long } 400f1c579b1SScott Long /* 401f1c579b1SScott Long ********************************************************************** 402f1c579b1SScott Long ********************************************************************** 403f1c579b1SScott Long */ 404ad6d6297SScott Long static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag) 405f1c579b1SScott Long { 406ad6d6297SScott Long struct AdapterControlBlock *acb=srb->acb; 407ad6d6297SScott Long union ccb * pccb=srb->pccb; 408f1c579b1SScott Long 409ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 410f1c579b1SScott Long bus_dmasync_op_t op; 411f1c579b1SScott Long 412ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 413f1c579b1SScott Long op = BUS_DMASYNC_POSTREAD; 414ad6d6297SScott Long } else { 415f1c579b1SScott Long op = BUS_DMASYNC_POSTWRITE; 416f1c579b1SScott Long } 417ad6d6297SScott Long bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 418ad6d6297SScott Long bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 419f1c579b1SScott Long } 420ad6d6297SScott Long ARCMSR_LOCK_ACQUIRE(&acb->workingQ_done_lock); 421ad6d6297SScott Long if(stand_flag==1) { 422ad6d6297SScott Long atomic_subtract_int(&acb->srboutstandingcount, 1); 423dc3a205bSScott Long if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) && ( 424dc3a205bSScott Long acb->srboutstandingcount < ARCMSR_RELEASE_SIMQ_LEVEL)) { 425dc3a205bSScott Long acb->acb_flags &= ~ACB_F_CAM_DEV_QFRZN; 426dc3a205bSScott Long pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 427dc3a205bSScott Long } 428ad6d6297SScott Long } 429ad6d6297SScott Long srb->startdone=ARCMSR_SRB_DONE; 430ad6d6297SScott Long srb->srb_flags=0; 431ad6d6297SScott Long acb->srbworkingQ[acb->workingsrb_doneindex]=srb; 432ad6d6297SScott Long acb->workingsrb_doneindex++; 433ad6d6297SScott Long acb->workingsrb_doneindex %= ARCMSR_MAX_FREESRB_NUM; 434ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->workingQ_done_lock); 435f1c579b1SScott Long xpt_done(pccb); 436f1c579b1SScott Long return; 437f1c579b1SScott Long } 438f1c579b1SScott Long /* 439f1c579b1SScott Long ********************************************************************** 440f1c579b1SScott Long ********************************************************************** 441f1c579b1SScott Long */ 442ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb) 443f1c579b1SScott Long { 444ad6d6297SScott Long union ccb * pccb=srb->pccb; 445f1c579b1SScott Long 446ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 447ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 448ad6d6297SScott Long if(&pccb->csio.sense_data) { 449ad6d6297SScott Long memset(&pccb->csio.sense_data, 0, sizeof(pccb->csio.sense_data)); 450ad6d6297SScott Long memcpy(&pccb->csio.sense_data, srb->arcmsr_cdb.SenseData, 451ad6d6297SScott Long get_min(sizeof(struct SENSE_DATA), sizeof(pccb->csio.sense_data))); 452ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); /* Valid,ErrorCode */ 453f1c579b1SScott Long pccb->ccb_h.status |= CAM_AUTOSNS_VALID; 454f1c579b1SScott Long } 455f1c579b1SScott Long return; 456f1c579b1SScott Long } 457f1c579b1SScott Long /* 458f1c579b1SScott Long ********************************************************************* 459f1c579b1SScott Long ** 460f1c579b1SScott Long ********************************************************************* 461f1c579b1SScott Long */ 462ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) 463f1c579b1SScott Long { 464ad6d6297SScott Long CHIP_REG_WRITE32(inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 465ad6d6297SScott Long if(arcmsr_wait_msgint_ready(acb)) { 466ad6d6297SScott Long printf("arcmsr%d: wait 'abort all outstanding command' timeout \n" 467ad6d6297SScott Long , acb->pci_unit); 468ad6d6297SScott Long } 469f1c579b1SScott Long return; 470f1c579b1SScott Long } 471f1c579b1SScott Long /* 472f1c579b1SScott Long **************************************************************************** 473f1c579b1SScott Long **************************************************************************** 474f1c579b1SScott Long */ 475ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb) 476f1c579b1SScott Long { 477ad6d6297SScott Long struct CommandControlBlock *srb; 478ad6d6297SScott Long u_int32_t intmask_org, mask; 479ad6d6297SScott Long u_int32_t i=0; 480f1c579b1SScott Long 481ad6d6297SScott Long if(acb->srboutstandingcount!=0) 482f1c579b1SScott Long { 483f1c579b1SScott Long /* talk to iop 331 outstanding command aborted*/ 484ad6d6297SScott Long arcmsr_abort_allcmd(acb); 485ad6d6297SScott Long UDELAY(3000*1000);/*wait for 3 sec for all command aborted*/ 486ad6d6297SScott Long /* disable all outbound interrupt */ 487ad6d6297SScott Long intmask_org=CHIP_REG_READ32(outbound_intmask); 488ad6d6297SScott Long CHIP_REG_WRITE32(outbound_intmask 489ad6d6297SScott Long , intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); 490f1c579b1SScott Long /*clear all outbound posted Q*/ 491ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_OUTSTANDING_CMD;i++) { 492ad6d6297SScott Long CHIP_REG_READ32(outbound_queueport); 493f1c579b1SScott Long } 494ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 495ad6d6297SScott Long srb=acb->psrb_pool[i]; 496ad6d6297SScott Long if(srb->startdone==ARCMSR_SRB_START) { 497ad6d6297SScott Long srb->startdone=ARCMSR_SRB_ABORTED; 498ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 499ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 500f1c579b1SScott Long } 501f1c579b1SScott Long } 502f1c579b1SScott Long /* enable all outbound interrupt */ 503ad6d6297SScott Long mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE 504ad6d6297SScott Long |ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); 505ad6d6297SScott Long CHIP_REG_WRITE32(outbound_intmask, intmask_org & mask); 506f1c579b1SScott Long /* post abort all outstanding command message to RAID controller */ 507f1c579b1SScott Long } 508ad6d6297SScott Long atomic_set_int(&acb->srboutstandingcount, 0); 509ad6d6297SScott Long acb->workingsrb_doneindex=0; 510ad6d6297SScott Long acb->workingsrb_startindex=0; 511f1c579b1SScott Long return; 512f1c579b1SScott Long } 513f1c579b1SScott Long /* 514f1c579b1SScott Long ********************************************************************** 515f1c579b1SScott Long ********************************************************************** 516f1c579b1SScott Long */ 517ad6d6297SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t *dm_segs, u_int32_t nseg) 518f1c579b1SScott Long { 519ad6d6297SScott Long struct ARCMSR_CDB * arcmsr_cdb= &srb->arcmsr_cdb; 520ad6d6297SScott Long u_int8_t * psge=(u_int8_t *)&arcmsr_cdb->u; 521ad6d6297SScott Long u_int32_t address_lo, address_hi; 522ad6d6297SScott Long union ccb * pccb=srb->pccb; 523f1c579b1SScott Long struct ccb_scsiio * pcsio= &pccb->csio; 524ad6d6297SScott Long u_int32_t arccdbsize=0x30; 525f1c579b1SScott Long 526ad6d6297SScott Long memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB)); 527ad6d6297SScott Long arcmsr_cdb->Bus=0; 528ad6d6297SScott Long arcmsr_cdb->TargetID=pccb->ccb_h.target_id; 529ad6d6297SScott Long arcmsr_cdb->LUN=pccb->ccb_h.target_lun; 530ad6d6297SScott Long arcmsr_cdb->Function=1; 531ad6d6297SScott Long arcmsr_cdb->CdbLength=(u_int8_t)pcsio->cdb_len; 532ad6d6297SScott Long arcmsr_cdb->Context=(unsigned long)arcmsr_cdb; 533ad6d6297SScott Long bcopy(pcsio->cdb_io.cdb_bytes, arcmsr_cdb->Cdb, pcsio->cdb_len); 534ad6d6297SScott Long if(nseg != 0) { 535ad6d6297SScott Long struct AdapterControlBlock *acb=srb->acb; 536f1c579b1SScott Long bus_dmasync_op_t op; 537ad6d6297SScott Long u_int32_t length, i, cdb_sgcount=0; 538f1c579b1SScott Long 539ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 540ad6d6297SScott Long op=BUS_DMASYNC_PREREAD; 541ad6d6297SScott Long } else { 542ad6d6297SScott Long op=BUS_DMASYNC_PREWRITE; 543ad6d6297SScott Long arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_WRITE; 544ad6d6297SScott Long srb->srb_flags|=SRB_FLAG_WRITE; 545ad6d6297SScott Long } 546ad6d6297SScott Long bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 547ad6d6297SScott Long for(i=0;i<nseg;i++) { 548f1c579b1SScott Long /* Get the physical address of the current data pointer */ 549ad6d6297SScott Long length=arcmsr_htole32(dm_segs[i].ds_len); 550ad6d6297SScott Long address_lo=arcmsr_htole32(dma_addr_lo32(dm_segs[i].ds_addr)); 551ad6d6297SScott Long address_hi=arcmsr_htole32(dma_addr_hi32(dm_segs[i].ds_addr)); 552ad6d6297SScott Long if(address_hi==0) { 553ad6d6297SScott Long struct SG32ENTRY * pdma_sg=(struct SG32ENTRY *)psge; 554f1c579b1SScott Long pdma_sg->address=address_lo; 555f1c579b1SScott Long pdma_sg->length=length; 556ad6d6297SScott Long psge += sizeof(struct SG32ENTRY); 557ad6d6297SScott Long arccdbsize += sizeof(struct SG32ENTRY); 558ad6d6297SScott Long } else { 559ad6d6297SScott Long u_int32_t sg64s_size=0, tmplength=length; 560f1c579b1SScott Long 561ad6d6297SScott Long while(1) { 562ad6d6297SScott Long u_int64_t span4G, length0; 563ad6d6297SScott Long struct SG64ENTRY * pdma_sg=(struct SG64ENTRY *)psge; 564f1c579b1SScott Long 565ad6d6297SScott Long span4G=(u_int64_t)address_lo + tmplength; 566f1c579b1SScott Long pdma_sg->addresshigh=address_hi; 567f1c579b1SScott Long pdma_sg->address=address_lo; 568ad6d6297SScott Long if(span4G > 0x100000000) { 569f1c579b1SScott Long /*see if cross 4G boundary*/ 570f1c579b1SScott Long length0=0x100000000-address_lo; 571ad6d6297SScott Long pdma_sg->length=(u_int32_t)length0|IS_SG64_ADDR; 572f1c579b1SScott Long address_hi=address_hi+1; 573f1c579b1SScott Long address_lo=0; 574ad6d6297SScott Long tmplength=tmplength-(u_int32_t)length0; 575ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 576ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 577f1c579b1SScott Long cdb_sgcount++; 578ad6d6297SScott Long } else { 579f1c579b1SScott Long pdma_sg->length=tmplength|IS_SG64_ADDR; 580ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 581ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 582f1c579b1SScott Long break; 583f1c579b1SScott Long } 584f1c579b1SScott Long } 585f1c579b1SScott Long arccdbsize += sg64s_size; 586f1c579b1SScott Long } 587f1c579b1SScott Long cdb_sgcount++; 588f1c579b1SScott Long } 589ad6d6297SScott Long arcmsr_cdb->sgcount=(u_int8_t)cdb_sgcount; 590ad6d6297SScott Long arcmsr_cdb->DataLength=pcsio->dxfer_len; 591ad6d6297SScott Long if( arccdbsize > 256) { 592ad6d6297SScott Long arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_SGL_BSIZE; 593f1c579b1SScott Long } 594f1c579b1SScott Long } 595f1c579b1SScott Long return; 596f1c579b1SScott Long } 597f1c579b1SScott Long /* 598f1c579b1SScott Long ************************************************************************** 599f1c579b1SScott Long ************************************************************************** 600f1c579b1SScott Long */ 601ad6d6297SScott Long static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandControlBlock *srb) 602f1c579b1SScott Long { 603ad6d6297SScott Long u_int32_t cdb_shifted_phyaddr=(u_int32_t) srb->cdb_shifted_phyaddr; 604ad6d6297SScott Long struct ARCMSR_CDB * arcmsr_cdb=(struct ARCMSR_CDB *)&srb->arcmsr_cdb; 605f1c579b1SScott Long 606ad6d6297SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 607ad6d6297SScott Long (srb->srb_flags & SRB_FLAG_WRITE) ? BUS_DMASYNC_POSTWRITE:BUS_DMASYNC_POSTREAD); 608ad6d6297SScott Long atomic_add_int(&acb->srboutstandingcount, 1); 609ad6d6297SScott Long srb->startdone=ARCMSR_SRB_START; 610ad6d6297SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 611ad6d6297SScott Long CHIP_REG_WRITE32(inbound_queueport, cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE); 612ad6d6297SScott Long } else { 613ad6d6297SScott Long CHIP_REG_WRITE32(inbound_queueport, cdb_shifted_phyaddr); 614f1c579b1SScott Long } 615f1c579b1SScott Long return; 616f1c579b1SScott Long } 617f1c579b1SScott Long /* 618f1c579b1SScott Long ********************************************************************** 619f1c579b1SScott Long ********************************************************************** 620f1c579b1SScott Long */ 621ad6d6297SScott Long static void arcmsr_post_Qbuffer(struct AdapterControlBlock *acb) 622f1c579b1SScott Long { 623ad6d6297SScott Long u_int8_t * pQbuffer; 624ad6d6297SScott Long struct QBUFFER * pwbuffer=(struct QBUFFER *)&acb->pmu->message_wbuffer; 625ad6d6297SScott Long u_int8_t * iop_data=(u_int8_t *)pwbuffer->data; 626ad6d6297SScott Long u_int32_t allxfer_len=0; 627f1c579b1SScott Long 628ad6d6297SScott Long if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READED) { 629ad6d6297SScott Long acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); 630ad6d6297SScott Long while((acb->wqbuf_firstindex!=acb->wqbuf_lastindex) && (allxfer_len<124)) { 631ad6d6297SScott Long pQbuffer= &acb->wqbuffer[acb->wqbuf_firstindex]; 632f1c579b1SScott Long memcpy(iop_data, pQbuffer, 1); 633ad6d6297SScott Long acb->wqbuf_firstindex++; 634ad6d6297SScott Long acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 635ad6d6297SScott Long /*if last index number set it to 0 */ 636f1c579b1SScott Long iop_data++; 637f1c579b1SScott Long allxfer_len++; 638f1c579b1SScott Long } 639f1c579b1SScott Long pwbuffer->data_len=allxfer_len; 640f1c579b1SScott Long /* 641f1c579b1SScott Long ** push inbound doorbell and wait reply at hwinterrupt routine for next Qbuffer post 642f1c579b1SScott Long */ 643ad6d6297SScott Long CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK); 644ad6d6297SScott Long } 645f1c579b1SScott Long return; 646f1c579b1SScott Long } 647f1c579b1SScott Long /* 648f1c579b1SScott Long ************************************************************************ 649f1c579b1SScott Long ************************************************************************ 650f1c579b1SScott Long */ 651ad6d6297SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) 652f1c579b1SScott Long { 653ad6d6297SScott Long acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 654ad6d6297SScott Long CHIP_REG_WRITE32(inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 655ad6d6297SScott Long if(arcmsr_wait_msgint_ready(acb)) { 656ad6d6297SScott Long printf("arcmsr%d: wait 'stop adapter rebulid' timeout \n" 657ad6d6297SScott Long , acb->pci_unit); 658ad6d6297SScott Long } 659f1c579b1SScott Long return; 660f1c579b1SScott Long } 661f1c579b1SScott Long /* 662f1c579b1SScott Long ************************************************************************ 663f1c579b1SScott Long ************************************************************************ 664f1c579b1SScott Long */ 665ad6d6297SScott Long static void arcmsr_poll(struct cam_sim * psim) 666f1c579b1SScott Long { 667f1c579b1SScott Long arcmsr_interrupt(cam_sim_softc(psim)); 668f1c579b1SScott Long return; 669f1c579b1SScott Long } 670f1c579b1SScott Long /* 671f1c579b1SScott Long ********************************************************************** 672f1c579b1SScott Long ********************************************************************** 673f1c579b1SScott Long */ 674ad6d6297SScott Long static void arcmsr_interrupt(void *arg) 675f1c579b1SScott Long { 676ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)arg; 677ad6d6297SScott Long struct CommandControlBlock *srb; 678ad6d6297SScott Long u_int32_t flag_srb, outbound_intstatus, outbound_doorbell; 679f1c579b1SScott Long 680f1c579b1SScott Long /* 681f1c579b1SScott Long ********************************************* 682ad6d6297SScott Long ** check outbound intstatus 683f1c579b1SScott Long ********************************************* 684f1c579b1SScott Long */ 685ad6d6297SScott Long outbound_intstatus=CHIP_REG_READ32(outbound_intstatus) & acb->outbound_int_enable; 686ad6d6297SScott Long CHIP_REG_WRITE32(outbound_intstatus, outbound_intstatus);/*clear interrupt*/ 687ad6d6297SScott Long if(outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) { 688f1c579b1SScott Long /* 689f1c579b1SScott Long ********************************************* 690ad6d6297SScott Long ** DOORBELL 691f1c579b1SScott Long ********************************************* 692f1c579b1SScott Long */ 693ad6d6297SScott Long outbound_doorbell=CHIP_REG_READ32(outbound_doorbell); 694ad6d6297SScott Long CHIP_REG_WRITE32(outbound_doorbell, outbound_doorbell);/*clear interrupt */ 695ad6d6297SScott Long if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { 696ad6d6297SScott Long struct QBUFFER * prbuffer=(struct QBUFFER *)&acb->pmu->message_rbuffer; 697ad6d6297SScott Long u_int8_t * iop_data=(u_int8_t *)prbuffer->data; 698ad6d6297SScott Long u_int8_t * pQbuffer; 699ad6d6297SScott Long u_int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; 700ad6d6297SScott Long 701f1c579b1SScott Long /*check this iop data if overflow my rqbuffer*/ 702ad6d6297SScott Long rqbuf_lastindex=acb->rqbuf_lastindex; 703ad6d6297SScott Long rqbuf_firstindex=acb->rqbuf_firstindex; 704f1c579b1SScott Long iop_len=prbuffer->data_len; 705f1c579b1SScott Long my_empty_len=(rqbuf_firstindex-rqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1); 706ad6d6297SScott Long if(my_empty_len>=iop_len) { 707ad6d6297SScott Long while(iop_len > 0) { 708ad6d6297SScott Long pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex]; 709f1c579b1SScott Long memcpy(pQbuffer, iop_data, 1); 710ad6d6297SScott Long acb->rqbuf_lastindex++; 711ad6d6297SScott Long acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 712ad6d6297SScott Long /*if last index number set it to 0 */ 713f1c579b1SScott Long iop_data++; 714f1c579b1SScott Long iop_len--; 715f1c579b1SScott Long } 716ad6d6297SScott Long CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 717ad6d6297SScott Long /*signature, let IOP331 know data has been readed */ 718ad6d6297SScott Long } else { 719ad6d6297SScott Long acb->acb_flags|=ACB_F_IOPDATA_OVERFLOW; 720f1c579b1SScott Long } 721f1c579b1SScott Long } 722ad6d6297SScott Long if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { 723ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED; 724f1c579b1SScott Long /* 725f1c579b1SScott Long ********************************************* 726f1c579b1SScott Long ********************************************* 727f1c579b1SScott Long */ 728ad6d6297SScott Long if(acb->wqbuf_firstindex!=acb->wqbuf_lastindex) { 729ad6d6297SScott Long u_int8_t * pQbuffer; 730ad6d6297SScott Long struct QBUFFER * pwbuffer=(struct QBUFFER *)&acb->pmu->message_wbuffer; 731ad6d6297SScott Long u_int8_t * iop_data=(u_int8_t *)pwbuffer->data; 732ad6d6297SScott Long u_int32_t allxfer_len=0; 733f1c579b1SScott Long 734ad6d6297SScott Long acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); 735ad6d6297SScott Long while((acb->wqbuf_firstindex!=acb->wqbuf_lastindex) && (allxfer_len<124)) { 736ad6d6297SScott Long pQbuffer= &acb->wqbuffer[acb->wqbuf_firstindex]; 737f1c579b1SScott Long memcpy(iop_data, pQbuffer, 1); 738ad6d6297SScott Long acb->wqbuf_firstindex++; 739ad6d6297SScott Long acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 740ad6d6297SScott Long /*if last index number set it to 0 */ 741f1c579b1SScott Long iop_data++; 742f1c579b1SScott Long allxfer_len++; 743f1c579b1SScott Long } 744f1c579b1SScott Long pwbuffer->data_len=allxfer_len; 745f1c579b1SScott Long /* 746ad6d6297SScott Long ** push inbound doorbell tell iop driver data write ok 747ad6d6297SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 748f1c579b1SScott Long */ 749ad6d6297SScott Long CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK); 750f1c579b1SScott Long } 751ad6d6297SScott Long if(acb->wqbuf_firstindex==acb->wqbuf_lastindex) { 752ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; 753f1c579b1SScott Long } 754f1c579b1SScott Long } 755ad6d6297SScott Long } 756ad6d6297SScott Long if(outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { 757ad6d6297SScott Long int target, lun; 758f1c579b1SScott Long /* 759f1c579b1SScott Long ***************************************************************************** 760f1c579b1SScott Long ** areca cdb command done 761f1c579b1SScott Long ***************************************************************************** 762f1c579b1SScott Long */ 763ad6d6297SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 764ad6d6297SScott Long while(1) { 765ad6d6297SScott Long if((flag_srb=CHIP_REG_READ32(outbound_queueport)) == 0xFFFFFFFF) { 766f1c579b1SScott Long break;/*chip FIFO no srb for completion already*/ 767f1c579b1SScott Long } 768f1c579b1SScott Long /* check if command done with no error*/ 769ad6d6297SScott Long srb=(struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5)); 770ad6d6297SScott Long /*frame must be 32 bytes aligned*/ 771ad6d6297SScott Long if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) { 772ad6d6297SScott Long if(srb->startdone==ARCMSR_SRB_ABORTED) { 773ad6d6297SScott Long printf("arcmsr%d: srb='%p' isr got aborted command \n" 774ad6d6297SScott Long , acb->pci_unit, srb); 775ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 776ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 777ad6d6297SScott Long continue; 778f1c579b1SScott Long } 779ad6d6297SScott Long printf("arcmsr%d: isr get an illegal srb command done" 780ad6d6297SScott Long "acb='%p' srb='%p' srbacb='%p' startdone=0x%x" 781ad6d6297SScott Long "srboutstandingcount=%d \n", 782ad6d6297SScott Long acb->pci_unit, acb, srb, srb->acb, 783ad6d6297SScott Long srb->startdone, acb->srboutstandingcount); 784ad6d6297SScott Long continue; 785f1c579b1SScott Long } 786ad6d6297SScott Long target=srb->pccb->ccb_h.target_id; 787ad6d6297SScott Long lun=srb->pccb->ccb_h.target_lun; 788ad6d6297SScott Long if((flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR)==0) { 789ad6d6297SScott Long if(acb->devstate[target][lun]==ARECA_RAID_GONE) { 790ad6d6297SScott Long acb->devstate[target][lun]=ARECA_RAID_GOOD; 791f1c579b1SScott Long } 792ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_CMP; 793ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 794ad6d6297SScott Long } else { 795ad6d6297SScott Long switch(srb->arcmsr_cdb.DeviceStatus) { 796ad6d6297SScott Long case ARCMSR_DEV_SELECT_TIMEOUT: { 797ad6d6297SScott Long acb->devstate[target][lun]=ARECA_RAID_GONE; 798ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_SEL_TIMEOUT; 799ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 800f1c579b1SScott Long } 801f1c579b1SScott Long break; 802f1c579b1SScott Long case ARCMSR_DEV_ABORTED: 803ad6d6297SScott Long case ARCMSR_DEV_INIT_FAIL: { 804ad6d6297SScott Long acb->devstate[target][lun]=ARECA_RAID_GONE; 805ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 806ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 807f1c579b1SScott Long } 808f1c579b1SScott Long break; 809ad6d6297SScott Long case SCSISTAT_CHECK_CONDITION: { 810ad6d6297SScott Long acb->devstate[target][lun]=ARECA_RAID_GOOD; 811ad6d6297SScott Long arcmsr_report_sense_info(srb); 812ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 813f1c579b1SScott Long } 814f1c579b1SScott Long break; 815f1c579b1SScott Long default: 816ad6d6297SScott Long printf("arcmsr%d: scsi id=%d lun=%d" 817ad6d6297SScott Long "isr get command error done," 818ad6d6297SScott Long "but got unknow DeviceStatus=0x%x \n" 819ad6d6297SScott Long , acb->pci_unit, target, lun 820ad6d6297SScott Long ,srb->arcmsr_cdb.DeviceStatus); 821ad6d6297SScott Long acb->devstate[target][lun]=ARECA_RAID_GONE; 822ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY; 823ad6d6297SScott Long /*unknow error or crc error just for retry*/ 824ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 825f1c579b1SScott Long break; 826f1c579b1SScott Long } 827f1c579b1SScott Long } 828f1c579b1SScott Long } /*drain reply FIFO*/ 829f1c579b1SScott Long } 830f1c579b1SScott Long return; 831f1c579b1SScott Long } 832f1c579b1SScott Long /* 833ad6d6297SScott Long ******************************************************************************* 834ad6d6297SScott Long ** 835ad6d6297SScott Long ******************************************************************************* 836ad6d6297SScott Long */ 837ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb) 838ad6d6297SScott Long { 839ad6d6297SScott Long if(acb!=NULL) { 840ad6d6297SScott Long /* stop adapter background rebuild */ 841ad6d6297SScott Long if(acb->acb_flags & ACB_F_MSG_START_BGRB) { 842ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 843ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 844ad6d6297SScott Long } 845ad6d6297SScott Long } 846ad6d6297SScott Long } 847ad6d6297SScott Long /* 848f1c579b1SScott Long *********************************************************************** 849f1c579b1SScott Long ** 850f1c579b1SScott Long ************************************************************************ 851f1c579b1SScott Long */ 852ad6d6297SScott Long u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg) 853f1c579b1SScott Long { 854ad6d6297SScott Long struct CMD_MESSAGE_FIELD * pcmdmessagefld; 855ad6d6297SScott Long u_int32_t retvalue=EINVAL; 856f1c579b1SScott Long 857ad6d6297SScott Long pcmdmessagefld=(struct CMD_MESSAGE_FIELD *) arg; 858ad6d6297SScott Long if(memcmp(pcmdmessagefld->cmdmessage.Signature, "ARCMSR", 6)!=0) { 859ad6d6297SScott Long return retvalue; 860f1c579b1SScott Long } 861ad6d6297SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 862ad6d6297SScott Long switch(ioctl_cmd) { 863ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 864ad6d6297SScott Long u_int8_t * pQbuffer; 865ad6d6297SScott Long u_int8_t * ptmpQbuffer=pcmdmessagefld->messagedatabuffer; 866ad6d6297SScott Long u_int32_t allxfer_len=0; 867f1c579b1SScott Long 868ad6d6297SScott Long while((acb->rqbuf_firstindex!=acb->rqbuf_lastindex) && (allxfer_len<1031)) { 869f1c579b1SScott Long /*copy READ QBUFFER to srb*/ 870ad6d6297SScott Long pQbuffer= &acb->rqbuffer[acb->rqbuf_firstindex]; 871f1c579b1SScott Long memcpy(ptmpQbuffer, pQbuffer, 1); 872ad6d6297SScott Long acb->rqbuf_firstindex++; 873ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 874ad6d6297SScott Long /*if last index number set it to 0 */ 875f1c579b1SScott Long ptmpQbuffer++; 876f1c579b1SScott Long allxfer_len++; 877f1c579b1SScott Long } 878ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 879ad6d6297SScott Long struct QBUFFER * prbuffer=(struct QBUFFER *)&acb->pmu->message_rbuffer; 880ad6d6297SScott Long u_int8_t * iop_data=(u_int8_t *)prbuffer->data; 881ad6d6297SScott Long u_int32_t iop_len; 882f1c579b1SScott Long 883ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 884ad6d6297SScott Long iop_len=(u_int32_t)prbuffer->data_len; 885f1c579b1SScott Long /*this iop data does no chance to make me overflow again here, so just do it*/ 886ad6d6297SScott Long while(iop_len>0) { 887ad6d6297SScott Long pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex]; 888f1c579b1SScott Long memcpy(pQbuffer, iop_data, 1); 889ad6d6297SScott Long acb->rqbuf_lastindex++; 890ad6d6297SScott Long acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 891ad6d6297SScott Long /*if last index number set it to 0 */ 892f1c579b1SScott Long iop_data++; 893f1c579b1SScott Long iop_len--; 894f1c579b1SScott Long } 895ad6d6297SScott Long CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 896ad6d6297SScott Long /*signature, let IOP331 know data has been readed */ 897f1c579b1SScott Long } 898ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length=allxfer_len; 899ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 900ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 901f1c579b1SScott Long } 902f1c579b1SScott Long break; 903ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 904ad6d6297SScott Long u_int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 905ad6d6297SScott Long u_int8_t * pQbuffer; 906ad6d6297SScott Long u_int8_t * ptmpuserbuffer=pcmdmessagefld->messagedatabuffer; 907f1c579b1SScott Long 908ad6d6297SScott Long user_len=pcmdmessagefld->cmdmessage.Length; 909f1c579b1SScott Long /*check if data xfer length of this request will overflow my array qbuffer */ 910ad6d6297SScott Long wqbuf_lastindex=acb->wqbuf_lastindex; 911ad6d6297SScott Long wqbuf_firstindex=acb->wqbuf_firstindex; 912ad6d6297SScott Long if(wqbuf_lastindex!=wqbuf_firstindex) { 913ad6d6297SScott Long arcmsr_post_Qbuffer(acb); 914ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; 915ad6d6297SScott Long } else { 916f1c579b1SScott Long my_empty_len=(wqbuf_firstindex-wqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1); 917ad6d6297SScott Long if(my_empty_len>=user_len) { 918ad6d6297SScott Long while(user_len>0) { 919f1c579b1SScott Long /*copy srb data to wqbuffer*/ 920ad6d6297SScott Long pQbuffer= &acb->wqbuffer[acb->wqbuf_lastindex]; 921f1c579b1SScott Long memcpy(pQbuffer, ptmpuserbuffer, 1); 922ad6d6297SScott Long acb->wqbuf_lastindex++; 923ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 924ad6d6297SScott Long /*if last index number set it to 0 */ 925f1c579b1SScott Long ptmpuserbuffer++; 926f1c579b1SScott Long user_len--; 927f1c579b1SScott Long } 928f1c579b1SScott Long /*post fist Qbuffer*/ 929ad6d6297SScott Long if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 930ad6d6297SScott Long acb->acb_flags &=~ACB_F_MESSAGE_WQBUFFER_CLEARED; 931ad6d6297SScott Long arcmsr_post_Qbuffer(acb); 932f1c579b1SScott Long } 933ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 934ad6d6297SScott Long } else { 935ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; 936f1c579b1SScott Long } 937f1c579b1SScott Long } 938ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 939f1c579b1SScott Long } 940f1c579b1SScott Long break; 941ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 942ad6d6297SScott Long u_int8_t * pQbuffer=acb->rqbuffer; 943ad6d6297SScott Long 944ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 945ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 946ad6d6297SScott Long CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 947ad6d6297SScott Long /*signature, let IOP331 know data has been readed */ 948f1c579b1SScott Long } 949ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 950ad6d6297SScott Long acb->rqbuf_firstindex=0; 951ad6d6297SScott Long acb->rqbuf_lastindex=0; 952f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 953ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 954ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 955f1c579b1SScott Long } 956f1c579b1SScott Long break; 957ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: 958f1c579b1SScott Long { 959ad6d6297SScott Long u_int8_t * pQbuffer=acb->wqbuffer; 960f1c579b1SScott Long 961ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 962ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 963ad6d6297SScott Long CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 964ad6d6297SScott Long /*signature, let IOP331 know data has been readed */ 965f1c579b1SScott Long } 966ad6d6297SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READED); 967ad6d6297SScott Long acb->wqbuf_firstindex=0; 968ad6d6297SScott Long acb->wqbuf_lastindex=0; 969f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 970ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 971ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 972f1c579b1SScott Long } 973f1c579b1SScott Long break; 974ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 975ad6d6297SScott Long u_int8_t * pQbuffer; 976f1c579b1SScott Long 977ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 978ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 979ad6d6297SScott Long CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 980ad6d6297SScott Long /*signature, let IOP331 know data has been readed */ 981f1c579b1SScott Long } 982ad6d6297SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED 983ad6d6297SScott Long |ACB_F_MESSAGE_RQBUFFER_CLEARED 984ad6d6297SScott Long |ACB_F_MESSAGE_WQBUFFER_READED); 985ad6d6297SScott Long acb->rqbuf_firstindex=0; 986ad6d6297SScott Long acb->rqbuf_lastindex=0; 987ad6d6297SScott Long acb->wqbuf_firstindex=0; 988ad6d6297SScott Long acb->wqbuf_lastindex=0; 989ad6d6297SScott Long pQbuffer=acb->rqbuffer; 990ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 991ad6d6297SScott Long pQbuffer=acb->wqbuffer; 992ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 993ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 994ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 995f1c579b1SScott Long } 996f1c579b1SScott Long break; 997ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 998ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_3F; 999ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1000f1c579b1SScott Long } 1001f1c579b1SScott Long break; 1002ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 1003ad6d6297SScott Long u_int8_t * hello_string="Hello! I am ARCMSR"; 1004ad6d6297SScott Long u_int8_t * puserbuffer=(u_int8_t *)pcmdmessagefld->messagedatabuffer; 1005f1c579b1SScott Long 1006ad6d6297SScott Long if(memcpy(puserbuffer, hello_string, (int16_t)strlen(hello_string))) { 1007ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; 1008ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1009f1c579b1SScott Long return ENOIOCTL; 1010f1c579b1SScott Long } 1011ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1012ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1013ad6d6297SScott Long } 1014ad6d6297SScott Long break; 1015ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: { 1016ad6d6297SScott Long arcmsr_iop_parking(acb); 1017ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1018ad6d6297SScott Long } 1019ad6d6297SScott Long break; 1020ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: { 1021ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 1022ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1023f1c579b1SScott Long } 1024f1c579b1SScott Long break; 1025f1c579b1SScott Long } 1026ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1027ad6d6297SScott Long return retvalue; 1028f1c579b1SScott Long } 1029f1c579b1SScott Long /* 1030f1c579b1SScott Long ************************************************************************** 1031f1c579b1SScott Long ************************************************************************** 1032f1c579b1SScott Long */ 1033ad6d6297SScott Long struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb) 1034f1c579b1SScott Long { 1035ad6d6297SScott Long struct CommandControlBlock *srb=NULL; 1036ad6d6297SScott Long u_int32_t workingsrb_startindex, workingsrb_doneindex; 1037f1c579b1SScott Long 1038ad6d6297SScott Long ARCMSR_LOCK_ACQUIRE(&acb->workingQ_start_lock); 1039ad6d6297SScott Long workingsrb_doneindex=acb->workingsrb_doneindex; 1040ad6d6297SScott Long workingsrb_startindex=acb->workingsrb_startindex; 1041ad6d6297SScott Long srb=acb->srbworkingQ[workingsrb_startindex]; 1042ad6d6297SScott Long workingsrb_startindex++; 1043ad6d6297SScott Long workingsrb_startindex %= ARCMSR_MAX_FREESRB_NUM; 1044ad6d6297SScott Long if(workingsrb_doneindex!=workingsrb_startindex) { 1045ad6d6297SScott Long acb->workingsrb_startindex=workingsrb_startindex; 1046ad6d6297SScott Long } else { 1047ad6d6297SScott Long srb=NULL; 1048ad6d6297SScott Long } 1049ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->workingQ_start_lock); 1050ad6d6297SScott Long return(srb); 1051ad6d6297SScott Long } 1052ad6d6297SScott Long /* 1053ad6d6297SScott Long ************************************************************************** 1054ad6d6297SScott Long ************************************************************************** 1055ad6d6297SScott Long */ 1056ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb) 1057ad6d6297SScott Long { 1058ad6d6297SScott Long struct CMD_MESSAGE_FIELD * pcmdmessagefld; 1059ad6d6297SScott Long int retvalue = 0, transfer_len = 0; 1060ad6d6297SScott Long char *buffer; 1061ad6d6297SScott Long uint32_t controlcode = (uint32_t ) pccb->csio.cdb_io.cdb_bytes[5] << 24 | 1062ad6d6297SScott Long (uint32_t ) pccb->csio.cdb_io.cdb_bytes[6] << 16 | 1063ad6d6297SScott Long (uint32_t ) pccb->csio.cdb_io.cdb_bytes[7] << 8 | 1064ad6d6297SScott Long (uint32_t ) pccb->csio.cdb_io.cdb_bytes[8]; 1065ad6d6297SScott Long /* 4 bytes: Areca io control code */ 1066ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) { 1067ad6d6297SScott Long buffer = pccb->csio.data_ptr; 1068ad6d6297SScott Long transfer_len = pccb->csio.dxfer_len; 1069ad6d6297SScott Long } else { 1070ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 1071ad6d6297SScott Long goto message_out; 1072ad6d6297SScott Long } 1073ad6d6297SScott Long if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) { 1074ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 1075ad6d6297SScott Long goto message_out; 1076ad6d6297SScott Long } 1077ad6d6297SScott Long pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer; 1078ad6d6297SScott Long switch(controlcode) { 1079ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 1080ad6d6297SScott Long u_int8_t *pQbuffer; 1081ad6d6297SScott Long u_int8_t *ptmpQbuffer=pcmdmessagefld->messagedatabuffer; 1082ad6d6297SScott Long int32_t allxfer_len = 0; 1083f1c579b1SScott Long 1084ad6d6297SScott Long while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) 1085ad6d6297SScott Long && (allxfer_len < 1031)) { 1086ad6d6297SScott Long pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; 1087ad6d6297SScott Long memcpy(ptmpQbuffer, pQbuffer, 1); 1088ad6d6297SScott Long acb->rqbuf_firstindex++; 1089ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 1090ad6d6297SScott Long ptmpQbuffer++; 1091ad6d6297SScott Long allxfer_len++; 1092f1c579b1SScott Long } 1093ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1094ad6d6297SScott Long struct QBUFFER *prbuffer = (struct QBUFFER *) &acb->pmu->message_rbuffer; 1095ad6d6297SScott Long u_int8_t *iop_data = (u_int8_t *)prbuffer->data; 1096ad6d6297SScott Long int32_t iop_len; 1097ad6d6297SScott Long 1098ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 1099ad6d6297SScott Long iop_len =(u_int32_t)prbuffer->data_len; 1100ad6d6297SScott Long while (iop_len > 0) { 1101ad6d6297SScott Long pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex]; 1102ad6d6297SScott Long memcpy(pQbuffer, iop_data, 1); 1103ad6d6297SScott Long acb->rqbuf_lastindex++; 1104ad6d6297SScott Long acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 1105ad6d6297SScott Long iop_data++; 1106ad6d6297SScott Long iop_len--; 1107f1c579b1SScott Long } 1108ad6d6297SScott Long CHIP_REG_WRITE32(inbound_doorbell, 1109ad6d6297SScott Long ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 1110ad6d6297SScott Long } 1111ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length = allxfer_len; 1112ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 1113ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1114ad6d6297SScott Long } 1115ad6d6297SScott Long break; 1116ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 1117ad6d6297SScott Long int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 1118ad6d6297SScott Long u_int8_t *pQbuffer; 1119ad6d6297SScott Long u_int8_t *ptmpuserbuffer=pcmdmessagefld->messagedatabuffer; 1120ad6d6297SScott Long 1121ad6d6297SScott Long user_len = pcmdmessagefld->cmdmessage.Length; 1122ad6d6297SScott Long wqbuf_lastindex = acb->wqbuf_lastindex; 1123ad6d6297SScott Long wqbuf_firstindex = acb->wqbuf_firstindex; 1124ad6d6297SScott Long if (wqbuf_lastindex != wqbuf_firstindex) { 1125ad6d6297SScott Long arcmsr_post_Qbuffer(acb); 1126ad6d6297SScott Long /* has error report sensedata */ 1127ad6d6297SScott Long if(&pccb->csio.sense_data) { 1128ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 1129ad6d6297SScott Long /* Valid,ErrorCode */ 1130ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 1131ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 1132ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 1133ad6d6297SScott Long /* AdditionalSenseLength */ 1134ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 1135ad6d6297SScott Long /* AdditionalSenseCode */ 1136ad6d6297SScott Long } 1137ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 1138ad6d6297SScott Long } else { 1139ad6d6297SScott Long my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) 1140ad6d6297SScott Long &(ARCMSR_MAX_QBUFFER - 1); 1141ad6d6297SScott Long if (my_empty_len >= user_len) { 1142ad6d6297SScott Long while (user_len > 0) { 1143ad6d6297SScott Long pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; 1144ad6d6297SScott Long memcpy(pQbuffer, ptmpuserbuffer, 1); 1145ad6d6297SScott Long acb->wqbuf_lastindex++; 1146ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 1147ad6d6297SScott Long ptmpuserbuffer++; 1148ad6d6297SScott Long user_len--; 1149ad6d6297SScott Long } 1150ad6d6297SScott Long if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 1151ad6d6297SScott Long acb->acb_flags &= 1152ad6d6297SScott Long ~ACB_F_MESSAGE_WQBUFFER_CLEARED; 1153ad6d6297SScott Long arcmsr_post_Qbuffer(acb); 1154ad6d6297SScott Long } 1155ad6d6297SScott Long } else { 1156ad6d6297SScott Long /* has error report sensedata */ 1157ad6d6297SScott Long if(&pccb->csio.sense_data) { 1158ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 1159ad6d6297SScott Long /* Valid,ErrorCode */ 1160ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 1161ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 1162ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 1163ad6d6297SScott Long /* AdditionalSenseLength */ 1164ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 1165ad6d6297SScott Long /* AdditionalSenseCode */ 1166ad6d6297SScott Long } 1167ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 1168ad6d6297SScott Long } 1169ad6d6297SScott Long } 1170ad6d6297SScott Long } 1171ad6d6297SScott Long break; 1172ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 1173ad6d6297SScott Long u_int8_t *pQbuffer = acb->rqbuffer; 1174ad6d6297SScott Long 1175ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1176ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 1177ad6d6297SScott Long CHIP_REG_WRITE32(inbound_doorbell 1178ad6d6297SScott Long , ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 1179ad6d6297SScott Long } 1180ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 1181ad6d6297SScott Long acb->rqbuf_firstindex = 0; 1182ad6d6297SScott Long acb->rqbuf_lastindex = 0; 1183ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 1184ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 1185ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 1186ad6d6297SScott Long } 1187ad6d6297SScott Long break; 1188ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { 1189ad6d6297SScott Long u_int8_t *pQbuffer = acb->wqbuffer; 1190ad6d6297SScott Long 1191ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1192ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 1193ad6d6297SScott Long CHIP_REG_WRITE32(inbound_doorbell 1194ad6d6297SScott Long , ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 1195ad6d6297SScott Long } 1196ad6d6297SScott Long acb->acb_flags |= 1197ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED | 1198ad6d6297SScott Long ACB_F_MESSAGE_WQBUFFER_READED); 1199ad6d6297SScott Long acb->wqbuf_firstindex = 0; 1200ad6d6297SScott Long acb->wqbuf_lastindex = 0; 1201ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 1202ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 1203ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 1204ad6d6297SScott Long } 1205ad6d6297SScott Long break; 1206ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 1207ad6d6297SScott Long u_int8_t *pQbuffer; 1208ad6d6297SScott Long 1209ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1210ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 1211ad6d6297SScott Long CHIP_REG_WRITE32(inbound_doorbell 1212ad6d6297SScott Long , ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 1213ad6d6297SScott Long } 1214ad6d6297SScott Long acb->acb_flags |= 1215ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED 1216ad6d6297SScott Long | ACB_F_MESSAGE_RQBUFFER_CLEARED 1217ad6d6297SScott Long | ACB_F_MESSAGE_WQBUFFER_READED); 1218ad6d6297SScott Long acb->rqbuf_firstindex = 0; 1219ad6d6297SScott Long acb->rqbuf_lastindex = 0; 1220ad6d6297SScott Long acb->wqbuf_firstindex = 0; 1221ad6d6297SScott Long acb->wqbuf_lastindex = 0; 1222ad6d6297SScott Long pQbuffer = acb->rqbuffer; 1223ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 1224ad6d6297SScott Long pQbuffer = acb->wqbuffer; 1225ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 1226ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 1227ad6d6297SScott Long } 1228ad6d6297SScott Long break; 1229ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 1230ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; 1231ad6d6297SScott Long } 1232ad6d6297SScott Long break; 1233ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 1234ad6d6297SScott Long int8_t * hello_string = "Hello! I am ARCMSR"; 1235ad6d6297SScott Long 1236ad6d6297SScott Long memcpy(pcmdmessagefld->messagedatabuffer, hello_string 1237ad6d6297SScott Long , (int16_t)strlen(hello_string)); 1238ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 1239ad6d6297SScott Long } 1240ad6d6297SScott Long break; 1241ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: 1242ad6d6297SScott Long arcmsr_iop_parking(acb); 1243ad6d6297SScott Long break; 1244ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: 1245ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 1246ad6d6297SScott Long break; 1247ad6d6297SScott Long default: 1248ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 1249ad6d6297SScott Long } 1250ad6d6297SScott Long message_out: 1251ad6d6297SScott Long return retvalue; 1252f1c579b1SScott Long } 1253f1c579b1SScott Long /* 1254f1c579b1SScott Long ********************************************************************* 1255f1c579b1SScott Long ********************************************************************* 1256f1c579b1SScott Long */ 1257ad6d6297SScott Long static void arcmsr_executesrb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 1258f1c579b1SScott Long { 1259ad6d6297SScott Long struct CommandControlBlock *srb=(struct CommandControlBlock *)arg; 1260ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)srb->acb; 1261f1c579b1SScott Long union ccb * pccb; 1262ad6d6297SScott Long int target, lun; 1263f1c579b1SScott Long 1264ad6d6297SScott Long pccb=srb->pccb; 1265ad6d6297SScott Long target=pccb->ccb_h.target_id; 1266ad6d6297SScott Long lun=pccb->ccb_h.target_lun; 1267ad6d6297SScott Long if(error != 0) { 1268ad6d6297SScott Long if(error != EFBIG) { 1269ad6d6297SScott Long printf("arcmsr%d: unexpected error %x returned from 'bus_dmamap_load' \n" 1270ad6d6297SScott Long , acb->pci_unit, error); 1271f1c579b1SScott Long } 1272ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { 127315735becSScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 1274f1c579b1SScott Long } 1275ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 1276f1c579b1SScott Long return; 1277f1c579b1SScott Long } 1278ad6d6297SScott Long if(nseg > ARCMSR_MAX_SG_ENTRIES) { 1279ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 1280ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 1281ad6d6297SScott Long return; 1282f1c579b1SScott Long } 1283ad6d6297SScott Long if(acb->acb_flags & ACB_F_BUS_RESET) { 1284ad6d6297SScott Long printf("arcmsr%d: bus reset and return busy \n", acb->pci_unit); 1285ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_BUS_RESET; 1286ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 1287ad6d6297SScott Long return; 1288ad6d6297SScott Long } 1289ad6d6297SScott Long if(acb->devstate[target][lun]==ARECA_RAID_GONE) { 1290ad6d6297SScott Long u_int8_t block_cmd; 1291ad6d6297SScott Long 1292ad6d6297SScott Long block_cmd=pccb->csio.cdb_io.cdb_bytes[0] & 0x0f; 1293ad6d6297SScott Long if(block_cmd==0x08 || block_cmd==0x0a) { 1294ad6d6297SScott Long printf("arcmsr%d:block 'read/write' command" 1295ad6d6297SScott Long "with gone raid volume Cmd=%2x, TargetId=%d, Lun=%d \n" 1296ad6d6297SScott Long , acb->pci_unit, block_cmd, target, lun); 1297ad6d6297SScott Long pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 1298ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 1299ad6d6297SScott Long return; 1300ad6d6297SScott Long } 1301ad6d6297SScott Long } 1302ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { 1303ad6d6297SScott Long if(nseg != 0) { 1304ad6d6297SScott Long bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 1305ad6d6297SScott Long } 1306ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 1307f1c579b1SScott Long return; 1308f1c579b1SScott Long } 1309ad6d6297SScott Long if(acb->srboutstandingcount >= ARCMSR_MAX_OUTSTANDING_CMD) { 131015735becSScott Long xpt_freeze_simq(acb->psim, 1); 131115735becSScott Long pccb->ccb_h.status = CAM_REQUEUE_REQ; 1312dc3a205bSScott Long acb->acb_flags |= ACB_F_CAM_DEV_QFRZN; 1313ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 1314ad6d6297SScott Long return; 1315f1c579b1SScott Long } 131615735becSScott Long pccb->ccb_h.status |= CAM_SIM_QUEUED; 1317ad6d6297SScott Long arcmsr_build_srb(srb, dm_segs, nseg); 1318ad6d6297SScott Long arcmsr_post_srb(acb, srb); 1319f1c579b1SScott Long return; 1320f1c579b1SScott Long } 1321f1c579b1SScott Long /* 1322f1c579b1SScott Long ***************************************************************************************** 1323f1c579b1SScott Long ***************************************************************************************** 1324f1c579b1SScott Long */ 1325ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb) 1326f1c579b1SScott Long { 1327ad6d6297SScott Long struct CommandControlBlock *srb; 1328ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *) abortccb->ccb_h.arcmsr_ccbacb_ptr; 1329ad6d6297SScott Long u_int32_t intmask_org, mask; 1330ad6d6297SScott Long int i=0; 1331f1c579b1SScott Long 1332ad6d6297SScott Long acb->num_aborts++; 1333f1c579b1SScott Long /* 1334ad6d6297SScott Long *************************************************************************** 1335f1c579b1SScott Long ** It is the upper layer do abort command this lock just prior to calling us. 1336f1c579b1SScott Long ** First determine if we currently own this command. 1337f1c579b1SScott Long ** Start by searching the device queue. If not found 1338f1c579b1SScott Long ** at all, and the system wanted us to just abort the 1339f1c579b1SScott Long ** command return success. 1340ad6d6297SScott Long *************************************************************************** 1341f1c579b1SScott Long */ 1342ad6d6297SScott Long if(acb->srboutstandingcount!=0) { 1343ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 1344ad6d6297SScott Long srb=acb->psrb_pool[i]; 1345ad6d6297SScott Long if(srb->startdone==ARCMSR_SRB_START) { 1346ad6d6297SScott Long if(srb->pccb==abortccb) { 1347ad6d6297SScott Long srb->startdone=ARCMSR_SRB_ABORTED; 1348ad6d6297SScott Long printf("arcmsr%d:scsi id=%d lun=%d abort srb '%p'" 1349ad6d6297SScott Long "outstanding command \n" 1350ad6d6297SScott Long , acb->pci_unit, abortccb->ccb_h.target_id 1351ad6d6297SScott Long , abortccb->ccb_h.target_lun, srb); 1352ad6d6297SScott Long goto abort_outstanding_cmd; 1353f1c579b1SScott Long } 1354f1c579b1SScott Long } 1355f1c579b1SScott Long } 1356f1c579b1SScott Long } 1357f1c579b1SScott Long return(FALSE); 1358ad6d6297SScott Long abort_outstanding_cmd: 1359ad6d6297SScott Long /* do not talk to iop 331 abort command */ 1360ad6d6297SScott Long UDELAY(3000*1000);/*wait for 3 sec for all command done*/ 1361ad6d6297SScott Long /* disable all outbound interrupt */ 1362ad6d6297SScott Long intmask_org=CHIP_REG_READ32(outbound_intmask); 1363ad6d6297SScott Long CHIP_REG_WRITE32(outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); 1364ad6d6297SScott Long arcmsr_polling_srbdone(acb, srb); 1365ad6d6297SScott Long /* enable all outbound interrupt */ 1366ad6d6297SScott Long mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); 1367ad6d6297SScott Long CHIP_REG_WRITE32(outbound_intmask, intmask_org & mask); 1368ad6d6297SScott Long return (TRUE); 1369f1c579b1SScott Long } 1370f1c579b1SScott Long /* 1371f1c579b1SScott Long **************************************************************************** 1372f1c579b1SScott Long **************************************************************************** 1373f1c579b1SScott Long */ 1374ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb) 1375f1c579b1SScott Long { 1376ad6d6297SScott Long int retry=0; 1377f1c579b1SScott Long 1378ad6d6297SScott Long acb->num_resets++; 1379ad6d6297SScott Long acb->acb_flags |=ACB_F_BUS_RESET; 1380ad6d6297SScott Long while(acb->srboutstandingcount!=0 && retry < 400) { 1381ad6d6297SScott Long arcmsr_interrupt((void *)acb); 1382ad6d6297SScott Long UDELAY(25000); 1383ad6d6297SScott Long retry++; 1384ad6d6297SScott Long } 1385ad6d6297SScott Long arcmsr_iop_reset(acb); 1386ad6d6297SScott Long acb->acb_flags &= ~ACB_F_BUS_RESET; 1387f1c579b1SScott Long return; 1388f1c579b1SScott Long } 1389f1c579b1SScott Long /* 1390ad6d6297SScott Long ************************************************************************** 1391ad6d6297SScott Long ************************************************************************** 1392ad6d6297SScott Long */ 1393ad6d6297SScott Long static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, 1394ad6d6297SScott Long union ccb * pccb) 1395ad6d6297SScott Long { 1396ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 1397ad6d6297SScott Long switch (pccb->csio.cdb_io.cdb_bytes[0]) { 1398ad6d6297SScott Long case INQUIRY: { 1399ad6d6297SScott Long unsigned char inqdata[36]; 1400ad6d6297SScott Long char *buffer=pccb->csio.data_ptr;; 1401ad6d6297SScott Long 1402ad6d6297SScott Long if (pccb->ccb_h.target_lun) { 1403ad6d6297SScott Long pccb->ccb_h.status |= CAM_SEL_TIMEOUT; 1404ad6d6297SScott Long xpt_done(pccb); 1405ad6d6297SScott Long return; 1406ad6d6297SScott Long } 1407ad6d6297SScott Long inqdata[0] = T_PROCESSOR; 1408ad6d6297SScott Long /* Periph Qualifier & Periph Dev Type */ 1409ad6d6297SScott Long inqdata[1] = 0; 1410ad6d6297SScott Long /* rem media bit & Dev Type Modifier */ 1411ad6d6297SScott Long inqdata[2] = 0; 1412ad6d6297SScott Long /* ISO, ECMA, & ANSI versions */ 1413ad6d6297SScott Long inqdata[4] = 31; 1414ad6d6297SScott Long /* length of additional data */ 1415ad6d6297SScott Long strncpy(&inqdata[8], "Areca ", 8); 1416ad6d6297SScott Long /* Vendor Identification */ 1417ad6d6297SScott Long strncpy(&inqdata[16], "RAID controller ", 16); 1418ad6d6297SScott Long /* Product Identification */ 1419ad6d6297SScott Long strncpy(&inqdata[32], "R001", 4); /* Product Revision */ 1420ad6d6297SScott Long memcpy(buffer, inqdata, sizeof(inqdata)); 1421ad6d6297SScott Long xpt_done(pccb); 1422ad6d6297SScott Long } 1423ad6d6297SScott Long break; 1424ad6d6297SScott Long case WRITE_BUFFER: 1425ad6d6297SScott Long case READ_BUFFER: { 1426ad6d6297SScott Long if (arcmsr_iop_message_xfer(acb, pccb)) { 1427ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 1428ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 1429ad6d6297SScott Long } 1430ad6d6297SScott Long xpt_done(pccb); 1431ad6d6297SScott Long } 1432ad6d6297SScott Long break; 1433ad6d6297SScott Long default: 1434ad6d6297SScott Long xpt_done(pccb); 1435ad6d6297SScott Long } 1436ad6d6297SScott Long } 1437ad6d6297SScott Long /* 1438f1c579b1SScott Long ********************************************************************* 1439f1c579b1SScott Long ********************************************************************* 1440f1c579b1SScott Long */ 1441ad6d6297SScott Long static void arcmsr_action(struct cam_sim * psim, union ccb * pccb) 1442f1c579b1SScott Long { 1443ad6d6297SScott Long struct AdapterControlBlock * acb; 1444f1c579b1SScott Long 1445ad6d6297SScott Long acb=(struct AdapterControlBlock *) cam_sim_softc(psim); 1446ad6d6297SScott Long if(acb==NULL) { 1447ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 1448f1c579b1SScott Long xpt_done(pccb); 1449f1c579b1SScott Long return; 1450f1c579b1SScott Long } 1451ad6d6297SScott Long switch (pccb->ccb_h.func_code) { 1452ad6d6297SScott Long case XPT_SCSI_IO: { 1453ad6d6297SScott Long struct CommandControlBlock *srb; 1454ad6d6297SScott Long int target=pccb->ccb_h.target_id; 1455f1c579b1SScott Long 1456ad6d6297SScott Long if(target == 16) { 1457ad6d6297SScott Long /* virtual device for iop message transfer */ 1458ad6d6297SScott Long arcmsr_handle_virtual_command(acb, pccb); 1459ad6d6297SScott Long return; 1460ad6d6297SScott Long } 1461ad6d6297SScott Long if((srb=arcmsr_get_freesrb(acb)) == NULL) { 1462ad6d6297SScott Long pccb->ccb_h.status |= CAM_RESRC_UNAVAIL; 1463f1c579b1SScott Long xpt_done(pccb); 1464f1c579b1SScott Long return; 1465f1c579b1SScott Long } 1466ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbsrb_ptr=srb; 1467ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbacb_ptr=acb; 1468ad6d6297SScott Long srb->pccb=pccb; 1469ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 1470ad6d6297SScott Long if(!(pccb->ccb_h.flags & CAM_SCATTER_VALID)) { 1471ad6d6297SScott Long /* Single buffer */ 1472ad6d6297SScott Long if(!(pccb->ccb_h.flags & CAM_DATA_PHYS)) { 1473ad6d6297SScott Long /* Buffer is virtual */ 1474ad6d6297SScott Long u_int32_t error, s; 1475f1c579b1SScott Long 1476f1c579b1SScott Long s=splsoftvm(); 1477ad6d6297SScott Long error = bus_dmamap_load(acb->dm_segs_dmat 1478ad6d6297SScott Long , srb->dm_segs_dmamap 1479ad6d6297SScott Long , pccb->csio.data_ptr 1480ad6d6297SScott Long , pccb->csio.dxfer_len 1481ad6d6297SScott Long , arcmsr_executesrb, srb, /*flags*/0); 1482ad6d6297SScott Long if(error == EINPROGRESS) { 1483ad6d6297SScott Long xpt_freeze_simq(acb->psim, 1); 1484f1c579b1SScott Long pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 1485f1c579b1SScott Long } 1486f1c579b1SScott Long splx(s); 1487ad6d6297SScott Long } else { 1488ad6d6297SScott Long /* Buffer is physical */ 14891c7e9358SScott Long panic("arcmsr: CAM_DATA_PHYS not supported"); 1490f1c579b1SScott Long } 1491ad6d6297SScott Long } else { 1492ad6d6297SScott Long /* Scatter/gather list */ 1493f1c579b1SScott Long struct bus_dma_segment *segs; 1494f1c579b1SScott Long 1495ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0 1496ad6d6297SScott Long || (pccb->ccb_h.flags & CAM_DATA_PHYS) != 0) { 1497ad6d6297SScott Long pccb->ccb_h.status |= CAM_PROVIDE_FAIL; 1498f1c579b1SScott Long xpt_done(pccb); 1499ad6d6297SScott Long free(srb, M_DEVBUF); 1500f1c579b1SScott Long return; 1501f1c579b1SScott Long } 1502f1c579b1SScott Long segs=(struct bus_dma_segment *)pccb->csio.data_ptr; 1503ad6d6297SScott Long arcmsr_executesrb(srb, segs, pccb->csio.sglist_cnt, 0); 1504f1c579b1SScott Long } 1505ad6d6297SScott Long } else { 1506ad6d6297SScott Long arcmsr_executesrb(srb, NULL, 0, 0); 1507f1c579b1SScott Long } 1508f1c579b1SScott Long break; 1509f1c579b1SScott Long } 1510ad6d6297SScott Long case XPT_TARGET_IO: { 1511ad6d6297SScott Long /* target mode not yet support vendor specific commands. */ 1512ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 1513f1c579b1SScott Long xpt_done(pccb); 1514f1c579b1SScott Long break; 1515f1c579b1SScott Long } 1516ad6d6297SScott Long case XPT_PATH_INQ: { 1517f1c579b1SScott Long struct ccb_pathinq *cpi= &pccb->cpi; 1518f1c579b1SScott Long 1519f1c579b1SScott Long cpi->version_num=1; 1520f1c579b1SScott Long cpi->hba_inquiry=PI_SDTR_ABLE | PI_TAG_ABLE; 1521f1c579b1SScott Long cpi->target_sprt=0; 1522f1c579b1SScott Long cpi->hba_misc=0; 1523f1c579b1SScott Long cpi->hba_eng_cnt=0; 1524ad6d6297SScott Long cpi->max_target=ARCMSR_MAX_TARGETID; /* 0-16 */ 1525ad6d6297SScott Long cpi->max_lun=ARCMSR_MAX_TARGETLUN; /* 0-7 */ 1526ad6d6297SScott Long cpi->initiator_id=ARCMSR_SCSI_INITIATOR_ID; /* 255 */ 1527f1c579b1SScott Long cpi->bus_id=cam_sim_bus(psim); 1528f1c579b1SScott Long strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 1529f1c579b1SScott Long strncpy(cpi->hba_vid, "ARCMSR", HBA_IDLEN); 1530f1c579b1SScott Long strncpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN); 1531f1c579b1SScott Long cpi->unit_number=cam_sim_unit(psim); 1532fa9ed865SMatt Jacob cpi->transport = XPORT_SPI; 1533fa9ed865SMatt Jacob cpi->transport_version = 2; 1534fa9ed865SMatt Jacob cpi->protocol = PROTO_SCSI; 1535fa9ed865SMatt Jacob cpi->protocol_version = SCSI_REV_2; 1536ad6d6297SScott Long cpi->ccb_h.status |= CAM_REQ_CMP; 1537f1c579b1SScott Long xpt_done(pccb); 1538f1c579b1SScott Long break; 1539f1c579b1SScott Long } 1540ad6d6297SScott Long case XPT_ABORT: { 1541f1c579b1SScott Long union ccb *pabort_ccb; 1542f1c579b1SScott Long 1543f1c579b1SScott Long pabort_ccb=pccb->cab.abort_ccb; 1544ad6d6297SScott Long switch (pabort_ccb->ccb_h.func_code) { 1545f1c579b1SScott Long case XPT_ACCEPT_TARGET_IO: 1546f1c579b1SScott Long case XPT_IMMED_NOTIFY: 1547f1c579b1SScott Long case XPT_CONT_TARGET_IO: 1548ad6d6297SScott Long if(arcmsr_seek_cmd2abort(pabort_ccb)==TRUE) { 1549ad6d6297SScott Long pabort_ccb->ccb_h.status |= CAM_REQ_ABORTED; 1550f1c579b1SScott Long xpt_done(pabort_ccb); 1551ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 1552ad6d6297SScott Long } else { 1553f1c579b1SScott Long xpt_print_path(pabort_ccb->ccb_h.path); 1554f1c579b1SScott Long printf("Not found\n"); 1555ad6d6297SScott Long pccb->ccb_h.status |= CAM_PATH_INVALID; 1556f1c579b1SScott Long } 1557f1c579b1SScott Long break; 1558f1c579b1SScott Long case XPT_SCSI_IO: 1559ad6d6297SScott Long pccb->ccb_h.status |= CAM_UA_ABORT; 1560f1c579b1SScott Long break; 1561f1c579b1SScott Long default: 1562ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 1563f1c579b1SScott Long break; 1564f1c579b1SScott Long } 1565f1c579b1SScott Long xpt_done(pccb); 1566f1c579b1SScott Long break; 1567f1c579b1SScott Long } 1568f1c579b1SScott Long case XPT_RESET_BUS: 1569ad6d6297SScott Long case XPT_RESET_DEV: { 1570ad6d6297SScott Long u_int32_t i; 1571f1c579b1SScott Long 1572ad6d6297SScott Long arcmsr_bus_reset(acb); 1573ad6d6297SScott Long for (i=0; i < 500; i++) { 1574f1c579b1SScott Long DELAY(1000); 1575f1c579b1SScott Long } 1576ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 1577f1c579b1SScott Long xpt_done(pccb); 1578f1c579b1SScott Long break; 1579f1c579b1SScott Long } 1580ad6d6297SScott Long case XPT_TERM_IO: { 1581ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 1582f1c579b1SScott Long xpt_done(pccb); 1583f1c579b1SScott Long break; 1584f1c579b1SScott Long } 1585ad6d6297SScott Long case XPT_GET_TRAN_SETTINGS: { 1586ad6d6297SScott Long struct ccb_trans_settings *cts; 1587ad6d6297SScott Long struct ccb_trans_settings_scsi *scsi; 1588ad6d6297SScott Long struct ccb_trans_settings_spi *spi; 1589ad6d6297SScott Long 1590ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 1591ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 1592ad6d6297SScott Long xpt_done(pccb); 1593ad6d6297SScott Long break; 1594ad6d6297SScott Long } 1595ad6d6297SScott Long 1596ad6d6297SScott Long cts= &pccb->cts; 1597ad6d6297SScott Long scsi = &cts->proto_specific.scsi; 1598ad6d6297SScott Long spi = &cts->xport_specific.spi; 1599fa9ed865SMatt Jacob 1600fa9ed865SMatt Jacob cts->protocol = PROTO_SCSI; 1601fa9ed865SMatt Jacob cts->protocol_version = SCSI_REV_2; 1602fa9ed865SMatt Jacob cts->transport = XPORT_SPI; 1603fa9ed865SMatt Jacob cts->transport_version = 2; 1604fa9ed865SMatt Jacob spi->flags = CTS_SPI_FLAGS_DISC_ENB; 1605fa9ed865SMatt Jacob spi->sync_period=3; 1606fa9ed865SMatt Jacob spi->sync_offset=32; 1607fa9ed865SMatt Jacob spi->bus_width=MSG_EXT_WDTR_BUS_16_BIT; 1608fa9ed865SMatt Jacob scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 1609fa9ed865SMatt Jacob spi->valid = CTS_SPI_VALID_SYNC_RATE 1610fa9ed865SMatt Jacob | CTS_SPI_VALID_SYNC_OFFSET 1611fa9ed865SMatt Jacob | CTS_SPI_VALID_BUS_WIDTH; 1612fa9ed865SMatt Jacob scsi->valid = CTS_SCSI_VALID_TQ; 1613f1c579b1SScott Long 1614ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 1615ad6d6297SScott Long xpt_done(pccb); 1616ad6d6297SScott Long break; 1617ad6d6297SScott Long } 1618ad6d6297SScott Long case XPT_SET_TRAN_SETTINGS: { 1619ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 1620ad6d6297SScott Long xpt_done(pccb); 1621ad6d6297SScott Long break; 1622ad6d6297SScott Long } 1623ad6d6297SScott Long case XPT_CALC_GEOMETRY: { 1624ad6d6297SScott Long struct ccb_calc_geometry *ccg; 1625ad6d6297SScott Long u_int32_t size_mb; 1626ad6d6297SScott Long u_int32_t secs_per_cylinder; 1627ad6d6297SScott Long 1628ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 1629ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 1630ad6d6297SScott Long xpt_done(pccb); 1631ad6d6297SScott Long break; 1632ad6d6297SScott Long } 1633f1c579b1SScott Long ccg= &pccb->ccg; 1634ad6d6297SScott Long if (ccg->block_size == 0) { 1635ad6d6297SScott Long pccb->ccb_h.status = CAM_REQ_INVALID; 1636ad6d6297SScott Long xpt_done(pccb); 1637ad6d6297SScott Long break; 1638ad6d6297SScott Long } 1639ad6d6297SScott Long if(((1024L * 1024L)/ccg->block_size) < 0) { 1640ad6d6297SScott Long pccb->ccb_h.status = CAM_REQ_INVALID; 1641ad6d6297SScott Long xpt_done(pccb); 1642ad6d6297SScott Long break; 1643ad6d6297SScott Long } 1644f1c579b1SScott Long size_mb=ccg->volume_size/((1024L * 1024L)/ccg->block_size); 1645ad6d6297SScott Long if(size_mb > 1024 ) { 1646f1c579b1SScott Long ccg->heads=255; 1647f1c579b1SScott Long ccg->secs_per_track=63; 1648ad6d6297SScott Long } else { 1649f1c579b1SScott Long ccg->heads=64; 1650f1c579b1SScott Long ccg->secs_per_track=32; 1651f1c579b1SScott Long } 1652f1c579b1SScott Long secs_per_cylinder=ccg->heads * ccg->secs_per_track; 1653f1c579b1SScott Long ccg->cylinders=ccg->volume_size / secs_per_cylinder; 1654ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 1655f1c579b1SScott Long xpt_done(pccb); 1656f1c579b1SScott Long break; 1657f1c579b1SScott Long } 1658f1c579b1SScott Long default: 1659ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 1660f1c579b1SScott Long xpt_done(pccb); 1661f1c579b1SScott Long break; 1662f1c579b1SScott Long } 1663f1c579b1SScott Long return; 1664f1c579b1SScott Long } 1665f1c579b1SScott Long /* 1666f1c579b1SScott Long ********************************************************************** 1667f1c579b1SScott Long ********************************************************************** 1668f1c579b1SScott Long */ 1669ad6d6297SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) 1670f1c579b1SScott Long { 1671ad6d6297SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 1672ad6d6297SScott Long CHIP_REG_WRITE32(inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 1673ad6d6297SScott Long if(arcmsr_wait_msgint_ready(acb)) { 1674ad6d6297SScott Long printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 1675ad6d6297SScott Long } 1676f1c579b1SScott Long return; 1677f1c579b1SScott Long } 1678f1c579b1SScott Long /* 1679f1c579b1SScott Long ********************************************************************** 1680f1c579b1SScott Long ********************************************************************** 1681f1c579b1SScott Long */ 1682ad6d6297SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 1683f1c579b1SScott Long { 1684ad6d6297SScott Long struct CommandControlBlock *srb; 1685ad6d6297SScott Long uint32_t flag_srb, outbound_intstatus, poll_srb_done=0, poll_count=0; 1686ad6d6297SScott Long int id, lun; 1687f1c579b1SScott Long 1688ad6d6297SScott Long polling_srb_retry: 1689ad6d6297SScott Long poll_count++; 1690ad6d6297SScott Long outbound_intstatus=CHIP_REG_READ32(outbound_intstatus) & acb->outbound_int_enable; 1691ad6d6297SScott Long CHIP_REG_WRITE32(outbound_intstatus, outbound_intstatus);/*clear interrupt*/ 1692ad6d6297SScott Long while(1) { 1693ad6d6297SScott Long if((flag_srb=CHIP_REG_READ32(outbound_queueport))==0xFFFFFFFF) { 1694ad6d6297SScott Long if(poll_srb_done) { 1695ad6d6297SScott Long break;/*chip FIFO no ccb for completion already*/ 1696ad6d6297SScott Long } else { 1697ad6d6297SScott Long UDELAY(25000); 1698ad6d6297SScott Long if(poll_count > 100) { 1699ad6d6297SScott Long break; 1700f1c579b1SScott Long } 1701ad6d6297SScott Long goto polling_srb_retry; 1702f1c579b1SScott Long } 1703ad6d6297SScott Long } 1704ad6d6297SScott Long /* check ifcommand done with no error*/ 1705ad6d6297SScott Long srb=(struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5)); 1706ad6d6297SScott Long /*frame must be 32 bytes aligned*/ 1707ad6d6297SScott Long if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) { 1708ad6d6297SScott Long if((srb->startdone==ARCMSR_SRB_ABORTED) && (srb==poll_srb)) { 1709ad6d6297SScott Long printf("arcmsr%d: scsi id=%d lun=%d srb='%p'" 1710ad6d6297SScott Long "poll command abort successfully \n" 1711ad6d6297SScott Long , acb->pci_unit 1712ad6d6297SScott Long , srb->pccb->ccb_h.target_id 1713ad6d6297SScott Long , srb->pccb->ccb_h.target_lun, srb); 1714ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 1715ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 1716ad6d6297SScott Long poll_srb_done=1; 1717ad6d6297SScott Long continue; 1718ad6d6297SScott Long } 1719ad6d6297SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 1720ad6d6297SScott Long "srboutstandingcount=%d \n" 1721ad6d6297SScott Long , acb->pci_unit 1722ad6d6297SScott Long , srb, acb->srboutstandingcount); 1723ad6d6297SScott Long continue; 1724ad6d6297SScott Long } 1725ad6d6297SScott Long id=srb->pccb->ccb_h.target_id; 1726ad6d6297SScott Long lun=srb->pccb->ccb_h.target_lun; 1727ad6d6297SScott Long if((flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR)==0) { 1728ad6d6297SScott Long if(acb->devstate[id][lun]==ARECA_RAID_GONE) { 1729ad6d6297SScott Long acb->devstate[id][lun]=ARECA_RAID_GOOD; 1730ad6d6297SScott Long } 1731ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_CMP; 1732ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 1733ad6d6297SScott Long } else { 1734ad6d6297SScott Long switch(srb->arcmsr_cdb.DeviceStatus) { 1735ad6d6297SScott Long case ARCMSR_DEV_SELECT_TIMEOUT: { 1736ad6d6297SScott Long acb->devstate[id][lun]=ARECA_RAID_GONE; 1737ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_SEL_TIMEOUT; 1738ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 1739ad6d6297SScott Long } 1740ad6d6297SScott Long break; 1741ad6d6297SScott Long case ARCMSR_DEV_ABORTED: 1742ad6d6297SScott Long case ARCMSR_DEV_INIT_FAIL: { 1743ad6d6297SScott Long acb->devstate[id][lun]=ARECA_RAID_GONE; 1744ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 1745ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 1746ad6d6297SScott Long } 1747ad6d6297SScott Long break; 1748ad6d6297SScott Long case SCSISTAT_CHECK_CONDITION: { 1749ad6d6297SScott Long acb->devstate[id][lun]=ARECA_RAID_GOOD; 1750ad6d6297SScott Long arcmsr_report_sense_info(srb); 1751ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 1752ad6d6297SScott Long } 1753ad6d6297SScott Long break; 1754ad6d6297SScott Long default: 1755ad6d6297SScott Long printf("arcmsr%d: scsi id=%d lun=%d" 1756ad6d6297SScott Long "polling and getting command error done" 1757ad6d6297SScott Long ", but got unknow DeviceStatus=0x%x \n" 1758ad6d6297SScott Long , acb->pci_unit, id, lun, srb->arcmsr_cdb.DeviceStatus); 1759ad6d6297SScott Long acb->devstate[id][lun]=ARECA_RAID_GONE; 1760ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY; 1761ad6d6297SScott Long /*unknow error or crc error just for retry*/ 1762ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 1763ad6d6297SScott Long break; 1764ad6d6297SScott Long } 1765ad6d6297SScott Long } 1766ad6d6297SScott Long } /*drain reply FIFO*/ 1767f1c579b1SScott Long return; 1768f1c579b1SScott Long } 1769f1c579b1SScott Long /* 1770f1c579b1SScott Long ********************************************************************** 1771ad6d6297SScott Long ** get firmware miscellaneous data 1772ad6d6297SScott Long ********************************************************************** 1773ad6d6297SScott Long */ 1774ad6d6297SScott Long static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) 1775ad6d6297SScott Long { 1776ad6d6297SScott Long char *acb_firm_model=acb->firm_model; 1777ad6d6297SScott Long char *acb_firm_version=acb->firm_version; 1778ad6d6297SScott Long size_t iop_firm_model=offsetof(struct MessageUnit,message_rwbuffer[15]); /*firm_model,15,60-67*/ 1779ad6d6297SScott Long size_t iop_firm_version=offsetof(struct MessageUnit,message_rwbuffer[17]); /*firm_version,17,68-83*/ 1780ad6d6297SScott Long int i; 1781ad6d6297SScott Long 1782ad6d6297SScott Long CHIP_REG_WRITE32(inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 1783ad6d6297SScott Long if(arcmsr_wait_msgint_ready(acb)) { 1784ad6d6297SScott Long printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n" 1785ad6d6297SScott Long , acb->pci_unit); 1786ad6d6297SScott Long } 1787ad6d6297SScott Long i=0; 1788ad6d6297SScott Long while(i<8) { 1789ad6d6297SScott Long *acb_firm_model=bus_space_read_1(acb->btag, acb->bhandle, iop_firm_model+i); 1790ad6d6297SScott Long /* 8 bytes firm_model, 15, 60-67*/ 1791ad6d6297SScott Long acb_firm_model++; 1792ad6d6297SScott Long i++; 1793ad6d6297SScott Long } 1794ad6d6297SScott Long i=0; 1795ad6d6297SScott Long while(i<16) { 1796ad6d6297SScott Long *acb_firm_version=bus_space_read_1(acb->btag, acb->bhandle, iop_firm_version+i); 1797ad6d6297SScott Long /* 16 bytes firm_version, 17, 68-83*/ 1798ad6d6297SScott Long acb_firm_version++; 1799ad6d6297SScott Long i++; 1800ad6d6297SScott Long } 1801ad6d6297SScott Long printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION); 1802ad6d6297SScott Long printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version); 1803ad6d6297SScott Long acb->firm_request_len=CHIP_REG_READ32(message_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 1804ad6d6297SScott Long acb->firm_numbers_queue=CHIP_REG_READ32(message_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 1805ad6d6297SScott Long acb->firm_sdram_size=CHIP_REG_READ32(message_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 1806ad6d6297SScott Long acb->firm_ide_channels=CHIP_REG_READ32(message_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 1807ad6d6297SScott Long return; 1808ad6d6297SScott Long } 1809ad6d6297SScott Long /* 1810ad6d6297SScott Long ********************************************************************** 1811ad6d6297SScott Long ** start background rebulid 1812ad6d6297SScott Long ********************************************************************** 1813ad6d6297SScott Long */ 1814ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb) 1815ad6d6297SScott Long { 1816ad6d6297SScott Long u_int32_t intmask_org, mask, outbound_doorbell, firmware_state=0; 1817ad6d6297SScott Long 1818ad6d6297SScott Long do { 1819ad6d6297SScott Long firmware_state=CHIP_REG_READ32(outbound_msgaddr1); 1820ad6d6297SScott Long } while((firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK)==0); 1821ad6d6297SScott Long intmask_org=CHIP_REG_READ32(outbound_intmask)|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE; 1822ad6d6297SScott Long CHIP_REG_WRITE32(outbound_intmask, intmask_org); 1823ad6d6297SScott Long intmask_org=CHIP_REG_READ32(outbound_intmask)|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE; 1824ad6d6297SScott Long arcmsr_get_firmware_spec(acb); 1825ad6d6297SScott Long arcmsr_start_adapter_bgrb(acb); 1826ad6d6297SScott Long /* clear Qbuffer if door bell ringed */ 1827ad6d6297SScott Long outbound_doorbell=CHIP_REG_READ32(outbound_doorbell); 1828ad6d6297SScott Long CHIP_REG_WRITE32(outbound_doorbell, outbound_doorbell);/*clear interrupt */ 1829ad6d6297SScott Long CHIP_REG_WRITE32(inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 1830ad6d6297SScott Long /* enable outbound Post Queue, outbound message0, outbell doorbell Interrupt */ 1831ad6d6297SScott Long mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); 1832ad6d6297SScott Long CHIP_REG_WRITE32(outbound_intmask, intmask_org & mask); 1833ad6d6297SScott Long acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; 1834ad6d6297SScott Long acb->acb_flags |=ACB_F_IOP_INITED; 1835ad6d6297SScott Long return; 1836ad6d6297SScott Long } 1837ad6d6297SScott Long /* 1838ad6d6297SScott Long ********************************************************************** 1839f1c579b1SScott Long ********************************************************************** 1840f1c579b1SScott Long */ 1841f1c579b1SScott Long static void arcmsr_map_freesrb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1842f1c579b1SScott Long { 1843ad6d6297SScott Long struct AdapterControlBlock *acb=arg; 1844ad6d6297SScott Long struct CommandControlBlock *srb_tmp; 1845ad6d6297SScott Long u_int8_t * dma_memptr; 1846ad6d6297SScott Long u_int32_t i, srb_phyaddr_hi32; 1847ad6d6297SScott Long unsigned long srb_phyaddr=(unsigned long)segs->ds_addr; 1848f1c579b1SScott Long 1849ad6d6297SScott Long dma_memptr=acb->uncacheptr; 1850ad6d6297SScott Long srb_phyaddr=segs->ds_addr; /* We suppose bus_addr_t high part always 0 here*/ 1851ad6d6297SScott Long if(((unsigned long)dma_memptr & 0x1F)!=0) { 1852ad6d6297SScott Long dma_memptr=dma_memptr+(0x20-((unsigned long)dma_memptr & 0x1F)); 1853ad6d6297SScott Long srb_phyaddr=srb_phyaddr+(0x20-((unsigned long)srb_phyaddr & 0x1F)); 1854f1c579b1SScott Long } 1855ad6d6297SScott Long srb_tmp=(struct CommandControlBlock *)dma_memptr; 1856ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 1857ad6d6297SScott Long /*srb address must 32 (0x20) boundary*/ 1858ad6d6297SScott Long if(((unsigned long)srb_tmp & 0x1F)==0) { 1859ad6d6297SScott Long if(bus_dmamap_create(acb->dm_segs_dmat, /*flags*/0, &srb_tmp->dm_segs_dmamap)!=0) { 1860ad6d6297SScott Long acb->acb_flags |= ACB_F_MAPFREESRB_FAILD; 1861ad6d6297SScott Long printf("arcmsr%d: srb dmamap bus_dmamap_create error\n", acb->pci_unit); 1862ad6d6297SScott Long return; 1863ad6d6297SScott Long } 1864ad6d6297SScott Long srb_tmp->cdb_shifted_phyaddr=srb_phyaddr >> 5; 1865ad6d6297SScott Long srb_tmp->acb=acb; 1866ad6d6297SScott Long acb->srbworkingQ[i]=acb->psrb_pool[i]=srb_tmp; 1867ad6d6297SScott Long srb_phyaddr=srb_phyaddr+sizeof(struct CommandControlBlock); 1868ad6d6297SScott Long } else { 1869ad6d6297SScott Long acb->acb_flags |= ACB_F_MAPFREESRB_FAILD; 1870ad6d6297SScott Long printf("arcmsr%d: dma_memptr=%p i=%d" 1871ad6d6297SScott Long "this srb cross 32 bytes boundary ignored srb_tmp=%p \n" 1872ad6d6297SScott Long , acb->pci_unit, dma_memptr, i, srb_tmp); 1873ad6d6297SScott Long return; 1874ad6d6297SScott Long } 1875ad6d6297SScott Long srb_tmp++; 1876ad6d6297SScott Long } 1877ad6d6297SScott Long acb->vir2phy_offset=(unsigned long)srb_tmp-(unsigned long)srb_phyaddr; 1878f1c579b1SScott Long /* 1879f1c579b1SScott Long ******************************************************************** 1880f1c579b1SScott Long ** here we need to tell iop 331 our freesrb.HighPart 1881f1c579b1SScott Long ** if freesrb.HighPart is not zero 1882f1c579b1SScott Long ******************************************************************** 1883f1c579b1SScott Long */ 1884ad6d6297SScott Long srb_phyaddr_hi32=(uint32_t) ((srb_phyaddr>>16)>>16); 1885ad6d6297SScott Long if(srb_phyaddr_hi32!=0) { 1886ad6d6297SScott Long CHIP_REG_WRITE32(message_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 1887ad6d6297SScott Long CHIP_REG_WRITE32(message_rwbuffer[1], srb_phyaddr_hi32); 1888ad6d6297SScott Long CHIP_REG_WRITE32(inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 1889ad6d6297SScott Long if(arcmsr_wait_msgint_ready(acb)) { 1890ad6d6297SScott Long printf("arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 1891f1c579b1SScott Long } 1892f1c579b1SScott Long } 1893f1c579b1SScott Long return; 1894f1c579b1SScott Long } 1895f1c579b1SScott Long /* 1896f1c579b1SScott Long ************************************************************************ 1897f1c579b1SScott Long ** 1898f1c579b1SScott Long ** 1899f1c579b1SScott Long ************************************************************************ 1900f1c579b1SScott Long */ 1901ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb) 1902f1c579b1SScott Long { 1903f1c579b1SScott Long /* remove the control device */ 1904ad6d6297SScott Long if(acb->ioctl_dev != NULL) { 1905ad6d6297SScott Long destroy_dev(acb->ioctl_dev); 1906f1c579b1SScott Long } 1907ad6d6297SScott Long bus_dmamap_unload(acb->srb_dmat, acb->srb_dmamap); 1908ad6d6297SScott Long bus_dmamap_destroy(acb->srb_dmat, acb->srb_dmamap); 1909ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 1910ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 1911ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 1912f1c579b1SScott Long return; 1913f1c579b1SScott Long } 1914f1c579b1SScott Long /* 1915f1c579b1SScott Long ************************************************************************ 1916f1c579b1SScott Long ************************************************************************ 1917f1c579b1SScott Long */ 1918ad6d6297SScott Long static u_int32_t arcmsr_initialize(device_t dev) 1919f1c579b1SScott Long { 1920ad6d6297SScott Long struct AdapterControlBlock *acb=device_get_softc(dev); 1921ad6d6297SScott Long u_int32_t intmask_org, rid=PCIR_BAR(0); 1922f1c579b1SScott Long vm_offset_t mem_base; 1923ad6d6297SScott Long u_int16_t pci_command; 1924ad6d6297SScott Long int i, j; 1925f1c579b1SScott Long 1926f1c579b1SScott Long #if __FreeBSD_version >= 502010 1927f1c579b1SScott Long if(bus_dma_tag_create( /*parent*/ NULL, 1928f1c579b1SScott Long /*alignemnt*/ 1, 1929f1c579b1SScott Long /*boundary*/ 0, 1930701d9f1fSScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 1931f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 1932f1c579b1SScott Long /*filter*/ NULL, 1933f1c579b1SScott Long /*filterarg*/ NULL, 1934f1c579b1SScott Long /*maxsize*/ BUS_SPACE_MAXSIZE_32BIT, 1935f1c579b1SScott Long /*nsegments*/ BUS_SPACE_UNRESTRICTED, 1936f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 1937f1c579b1SScott Long /*flags*/ 0, 1938f1c579b1SScott Long /*lockfunc*/ NULL, 1939f1c579b1SScott Long /*lockarg*/ NULL, 1940ad6d6297SScott Long &acb->parent_dmat) != 0) 1941f1c579b1SScott Long #else 1942f1c579b1SScott Long if(bus_dma_tag_create( /*parent*/ NULL, 1943f1c579b1SScott Long /*alignemnt*/ 1, 1944f1c579b1SScott Long /*boundary*/ 0, 1945701d9f1fSScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 1946f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 1947f1c579b1SScott Long /*filter*/ NULL, 1948f1c579b1SScott Long /*filterarg*/ NULL, 1949f1c579b1SScott Long /*maxsize*/ BUS_SPACE_MAXSIZE_32BIT, 1950f1c579b1SScott Long /*nsegments*/ BUS_SPACE_UNRESTRICTED, 1951f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 1952f1c579b1SScott Long /*flags*/ 0, 1953ad6d6297SScott Long &acb->parent_dmat) != 0) 1954f1c579b1SScott Long #endif 1955f1c579b1SScott Long { 1956ad6d6297SScott Long printf("arcmsr%d: parent_dmat bus_dma_tag_create failure!\n", acb->pci_unit); 1957f1c579b1SScott Long return ENOMEM; 1958f1c579b1SScott Long } 1959f1c579b1SScott Long /* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */ 1960f1c579b1SScott Long #if __FreeBSD_version >= 502010 1961ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 1962f1c579b1SScott Long /*alignment*/ 1, 1963f1c579b1SScott Long /*boundary*/ 0, 1964f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 1965f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 1966f1c579b1SScott Long /*filter*/ NULL, 1967f1c579b1SScott Long /*filterarg*/ NULL, 1968f1c579b1SScott Long /*maxsize*/ MAXBSIZE, 1969f1c579b1SScott Long /*nsegments*/ ARCMSR_MAX_SG_ENTRIES, 1970f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 1971ad6d6297SScott Long /*flags*/ 0, 1972f1c579b1SScott Long /*lockfunc*/ busdma_lock_mutex, 1973f1c579b1SScott Long /*lockarg*/ &Giant, 1974ad6d6297SScott Long &acb->dm_segs_dmat) != 0) 1975f1c579b1SScott Long #else 1976ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 1977f1c579b1SScott Long /*alignment*/ 1, 1978f1c579b1SScott Long /*boundary*/ 0, 1979f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 1980f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 1981f1c579b1SScott Long /*filter*/ NULL, 1982f1c579b1SScott Long /*filterarg*/ NULL, 1983f1c579b1SScott Long /*maxsize*/ MAXBSIZE, 1984f1c579b1SScott Long /*nsegments*/ ARCMSR_MAX_SG_ENTRIES, 1985f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 1986ad6d6297SScott Long /*flags*/ 0, 1987ad6d6297SScott Long &acb->dm_segs_dmat) != 0) 1988f1c579b1SScott Long #endif 1989f1c579b1SScott Long { 1990ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 1991ad6d6297SScott Long printf("arcmsr%d: dm_segs_dmat bus_dma_tag_create failure!\n", acb->pci_unit); 1992f1c579b1SScott Long return ENOMEM; 1993f1c579b1SScott Long } 1994ad6d6297SScott Long /* DMA tag for our srb structures.... Allocate the freesrb memory */ 1995f1c579b1SScott Long #if __FreeBSD_version >= 502010 1996ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 1997f1c579b1SScott Long /*alignment*/ 1, 1998f1c579b1SScott Long /*boundary*/ 0, 1999f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 2000f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 2001f1c579b1SScott Long /*filter*/ NULL, 2002f1c579b1SScott Long /*filterarg*/ NULL, 2003ad6d6297SScott Long /*maxsize*/ ARCMSR_SRBS_POOL_SIZE, 2004f1c579b1SScott Long /*nsegments*/ 1, 2005f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 2006701d9f1fSScott Long /*flags*/ 0, 2007f1c579b1SScott Long /*lockfunc*/ NULL, 2008f1c579b1SScott Long /*lockarg*/ NULL, 2009ad6d6297SScott Long &acb->srb_dmat) != 0) 2010f1c579b1SScott Long #else 2011ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 2012f1c579b1SScott Long /*alignment*/ 1, 2013f1c579b1SScott Long /*boundary*/ 0, 2014f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 2015f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 2016f1c579b1SScott Long /*filter*/ NULL, 2017f1c579b1SScott Long /*filterarg*/ NULL, 2018ad6d6297SScott Long /*maxsize*/ ARCMSR_SRBS_POOL_SIZE, 2019f1c579b1SScott Long /*nsegments*/ 1, 2020f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 2021701d9f1fSScott Long /*flags*/ 0, 2022ad6d6297SScott Long &acb->srb_dmat) != 0) 2023f1c579b1SScott Long #endif 2024f1c579b1SScott Long { 2025ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 2026ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 2027ad6d6297SScott Long printf("arcmsr%d: srb_dmat bus_dma_tag_create failure!\n", acb->pci_unit); 2028f1c579b1SScott Long return ENXIO; 2029f1c579b1SScott Long } 2030f1c579b1SScott Long /* Allocation for our srbs */ 2031ad6d6297SScott Long if(bus_dmamem_alloc(acb->srb_dmat, (void **)&acb->uncacheptr 2032ad6d6297SScott Long , BUS_DMA_WAITOK | BUS_DMA_COHERENT, &acb->srb_dmamap) != 0) { 2033ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 2034ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 2035ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 2036ad6d6297SScott Long printf("arcmsr%d: srb_dmat bus_dmamem_alloc failure!\n", acb->pci_unit); 2037f1c579b1SScott Long return ENXIO; 2038f1c579b1SScott Long } 2039f1c579b1SScott Long /* And permanently map them */ 2040ad6d6297SScott Long if(bus_dmamap_load(acb->srb_dmat, acb->srb_dmamap, acb->uncacheptr 2041ad6d6297SScott Long , ARCMSR_SRBS_POOL_SIZE, arcmsr_map_freesrb, acb, /*flags*/0)) { 2042ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 2043ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 2044ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 2045ad6d6297SScott Long printf("arcmsr%d: srb_dmat bus_dmamap_load failure!\n", acb->pci_unit); 2046f1c579b1SScott Long return ENXIO; 2047f1c579b1SScott Long } 2048f1c579b1SScott Long pci_command=pci_read_config(dev, PCIR_COMMAND, 2); 2049f1c579b1SScott Long pci_command |= PCIM_CMD_BUSMASTEREN; 2050f1c579b1SScott Long pci_command |= PCIM_CMD_PERRESPEN; 2051f1c579b1SScott Long pci_command |= PCIM_CMD_MWRICEN; 2052f1c579b1SScott Long /* Enable Busmaster/Mem */ 2053f1c579b1SScott Long pci_command |= PCIM_CMD_MEMEN; 2054f1c579b1SScott Long pci_write_config(dev, PCIR_COMMAND, pci_command, 2); 2055ad6d6297SScott Long acb->sys_res_arcmsr=bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0ul, ~0ul, 0x1000, RF_ACTIVE); 2056ad6d6297SScott Long if(acb->sys_res_arcmsr == NULL) { 2057ad6d6297SScott Long arcmsr_free_resource(acb); 2058ad6d6297SScott Long printf("arcmsr%d: bus_alloc_resource failure!\n", acb->pci_unit); 2059f1c579b1SScott Long return ENOMEM; 2060f1c579b1SScott Long } 2061ad6d6297SScott Long if(rman_get_start(acb->sys_res_arcmsr) <= 0) { 2062ad6d6297SScott Long arcmsr_free_resource(acb); 2063ad6d6297SScott Long printf("arcmsr%d: rman_get_start failure!\n", acb->pci_unit); 2064f1c579b1SScott Long return ENXIO; 2065f1c579b1SScott Long } 2066ad6d6297SScott Long mem_base=(vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr); 2067ad6d6297SScott Long if(mem_base==0) { 2068ad6d6297SScott Long arcmsr_free_resource(acb); 2069ad6d6297SScott Long printf("arcmsr%d: rman_get_virtual failure!\n", acb->pci_unit); 2070f1c579b1SScott Long return ENXIO; 2071f1c579b1SScott Long } 2072ad6d6297SScott Long if(acb->acb_flags & ACB_F_MAPFREESRB_FAILD) { 2073ad6d6297SScott Long arcmsr_free_resource(acb); 2074ad6d6297SScott Long printf("arcmsr%d: map free srb failure!\n", acb->pci_unit); 2075f1c579b1SScott Long return ENXIO; 2076f1c579b1SScott Long } 2077ad6d6297SScott Long acb->btag=rman_get_bustag(acb->sys_res_arcmsr); 2078ad6d6297SScott Long acb->bhandle=rman_get_bushandle(acb->sys_res_arcmsr); 2079ad6d6297SScott Long acb->pmu=(struct MessageUnit *)mem_base; 2080ad6d6297SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED 2081ad6d6297SScott Long |ACB_F_MESSAGE_RQBUFFER_CLEARED 2082ad6d6297SScott Long |ACB_F_MESSAGE_WQBUFFER_READED); 2083ad6d6297SScott Long acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; 2084ad6d6297SScott Long /* 2085ad6d6297SScott Long ******************************************************************** 2086ad6d6297SScott Long ** init raid volume state 2087ad6d6297SScott Long ******************************************************************** 2088ad6d6297SScott Long */ 2089ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_TARGETID;i++) { 2090ad6d6297SScott Long for(j=0;j<ARCMSR_MAX_TARGETLUN;j++) { 2091ad6d6297SScott Long acb->devstate[i][j]=ARECA_RAID_GOOD; 2092ad6d6297SScott Long } 2093ad6d6297SScott Long } 2094ad6d6297SScott Long /* disable iop all outbound interrupt */ 2095ad6d6297SScott Long intmask_org=CHIP_REG_READ32(outbound_intmask); 2096ad6d6297SScott Long CHIP_REG_WRITE32(outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); 2097ad6d6297SScott Long arcmsr_iop_init(acb); 2098f1c579b1SScott Long return(0); 2099f1c579b1SScott Long } 2100f1c579b1SScott Long /* 2101f1c579b1SScott Long ************************************************************************ 2102f1c579b1SScott Long ************************************************************************ 2103f1c579b1SScott Long */ 2104ad6d6297SScott Long static u_int32_t arcmsr_attach(device_t dev) 2105f1c579b1SScott Long { 2106ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 2107ad6d6297SScott Long u_int32_t unit=device_get_unit(dev); 2108f1c579b1SScott Long struct ccb_setasync csa; 2109f1c579b1SScott Long struct cam_devq *devq; /* Device Queue to use for this SIM */ 2110f1c579b1SScott Long struct resource *irqres; 2111f1c579b1SScott Long int rid; 2112f1c579b1SScott Long 2113ad6d6297SScott Long if(acb == NULL) { 2114ad6d6297SScott Long printf("arcmsr%d: cannot allocate softc\n", unit); 2115ad6d6297SScott Long return (ENOMEM); 2116ad6d6297SScott Long } 2117ad6d6297SScott Long bzero(acb, sizeof(struct AdapterControlBlock)); 2118ad6d6297SScott Long if(arcmsr_initialize(dev)) { 2119ad6d6297SScott Long printf("arcmsr%d: initialize failure!\n", unit); 2120f1c579b1SScott Long return ENXIO; 2121f1c579b1SScott Long } 2122f1c579b1SScott Long /* After setting up the adapter, map our interrupt */ 2123f1c579b1SScott Long rid=0; 2124ad6d6297SScott Long irqres=bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE); 2125ad6d6297SScott Long if(irqres == NULL || 2126ad6d6297SScott Long bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE 2127ef544f63SPaolo Pisati , NULL, arcmsr_interrupt, acb, &acb->ih)) { 2128ad6d6297SScott Long arcmsr_free_resource(acb); 2129f1c579b1SScott Long printf("arcmsr%d: unable to register interrupt handler!\n", unit); 2130f1c579b1SScott Long return ENXIO; 2131f1c579b1SScott Long } 2132ad6d6297SScott Long acb->irqres=irqres; 2133ad6d6297SScott Long acb->pci_dev=dev; 2134ad6d6297SScott Long acb->pci_unit=unit; 2135f1c579b1SScott Long /* 2136f1c579b1SScott Long * Now let the CAM generic SCSI layer find the SCSI devices on 2137f1c579b1SScott Long * the bus * start queue to reset to the idle loop. * 2138f1c579b1SScott Long * Create device queue of SIM(s) * (MAX_START_JOB - 1) : 2139f1c579b1SScott Long * max_sim_transactions 2140f1c579b1SScott Long */ 2141f1c579b1SScott Long devq=cam_simq_alloc(ARCMSR_MAX_START_JOB); 2142ad6d6297SScott Long if(devq == NULL) { 2143ad6d6297SScott Long arcmsr_free_resource(acb); 2144ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 2145ad6d6297SScott Long printf("arcmsr%d: cam_simq_alloc failure!\n", unit); 2146f1c579b1SScott Long return ENXIO; 2147f1c579b1SScott Long } 21482b83592fSScott Long acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll, 21492b83592fSScott Long "arcmsr", acb, unit, &Giant, 1, 21502b83592fSScott Long ARCMSR_MAX_OUTSTANDING_CMD, devq); 2151ad6d6297SScott Long if(acb->psim == NULL) { 2152ad6d6297SScott Long arcmsr_free_resource(acb); 2153ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 2154f1c579b1SScott Long cam_simq_free(devq); 2155ad6d6297SScott Long printf("arcmsr%d: cam_sim_alloc failure!\n", unit); 2156f1c579b1SScott Long return ENXIO; 2157f1c579b1SScott Long } 2158b50569b7SScott Long if(xpt_bus_register(acb->psim, dev, 0) != CAM_SUCCESS) { 2159ad6d6297SScott Long arcmsr_free_resource(acb); 2160ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 2161ad6d6297SScott Long cam_sim_free(acb->psim, /*free_devq*/TRUE); 2162ad6d6297SScott Long printf("arcmsr%d: xpt_bus_register failure!\n", unit); 2163f1c579b1SScott Long return ENXIO; 2164f1c579b1SScott Long } 2165ad6d6297SScott Long if(xpt_create_path(&acb->ppath, /* periph */ NULL 2166ad6d6297SScott Long , cam_sim_path(acb->psim) 2167ad6d6297SScott Long , CAM_TARGET_WILDCARD 2168ad6d6297SScott Long , CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 2169ad6d6297SScott Long arcmsr_free_resource(acb); 2170ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 2171ad6d6297SScott Long xpt_bus_deregister(cam_sim_path(acb->psim)); 2172ad6d6297SScott Long cam_sim_free(acb->psim, /* free_simq */ TRUE); 2173ad6d6297SScott Long printf("arcmsr%d: xpt_create_path failure!\n", unit); 2174f1c579b1SScott Long return ENXIO; 2175f1c579b1SScott Long } 2176ad6d6297SScott Long ARCMSR_LOCK_INIT(&acb->workingQ_done_lock, "arcmsr done working Q lock"); 2177ad6d6297SScott Long ARCMSR_LOCK_INIT(&acb->workingQ_start_lock, "arcmsr start working Q lock"); 2178ad6d6297SScott Long ARCMSR_LOCK_INIT(&acb->qbuffer_lock, "arcmsr Q buffer lock"); 2179f1c579b1SScott Long /* 2180f1c579b1SScott Long **************************************************** 2181f1c579b1SScott Long */ 2182ad6d6297SScott Long xpt_setup_ccb(&csa.ccb_h, acb->ppath, /*priority*/5); 2183f1c579b1SScott Long csa.ccb_h.func_code=XPT_SASYNC_CB; 2184f1c579b1SScott Long csa.event_enable=AC_FOUND_DEVICE|AC_LOST_DEVICE; 2185f1c579b1SScott Long csa.callback=arcmsr_async; 2186ad6d6297SScott Long csa.callback_arg=acb->psim; 2187f1c579b1SScott Long xpt_action((union ccb *)&csa); 2188f1c579b1SScott Long /* Create the control device. */ 2189ad6d6297SScott Long acb->ioctl_dev=make_dev(&arcmsr_cdevsw 2190ad6d6297SScott Long , unit 2191ad6d6297SScott Long , UID_ROOT 2192ad6d6297SScott Long , GID_WHEEL /* GID_OPERATOR */ 2193ad6d6297SScott Long , S_IRUSR | S_IWUSR 2194ad6d6297SScott Long , "arcmsr%d", unit); 2195f1c579b1SScott Long #if __FreeBSD_version < 503000 2196ad6d6297SScott Long acb->ioctl_dev->si_drv1=acb; 2197f1c579b1SScott Long #endif 2198f1c579b1SScott Long #if __FreeBSD_version > 500005 2199ad6d6297SScott Long (void)make_dev_alias(acb->ioctl_dev, "arc%d", unit); 2200f1c579b1SScott Long #endif 2201f1c579b1SScott Long return 0; 2202f1c579b1SScott Long } 2203f1c579b1SScott Long /* 2204f1c579b1SScott Long ************************************************************************ 2205f1c579b1SScott Long ************************************************************************ 2206f1c579b1SScott Long */ 2207ad6d6297SScott Long static u_int32_t arcmsr_probe(device_t dev) 2208f1c579b1SScott Long { 2209ad6d6297SScott Long u_int32_t id; 2210ad6d6297SScott Long static char buf[256]; 2211ad6d6297SScott Long char *type; 2212ad6d6297SScott Long int raid6 = 1; 2213ad6d6297SScott Long 2214ad6d6297SScott Long if (pci_get_vendor(dev) != PCI_VENDOR_ID_ARECA) { 2215ad6d6297SScott Long return (ENXIO); 2216ad6d6297SScott Long } 2217ad6d6297SScott Long switch(id=pci_get_devid(dev)) { 2218f1c579b1SScott Long case PCIDevVenIDARC1110: 2219f1c579b1SScott Long case PCIDevVenIDARC1210: 2220ad6d6297SScott Long raid6 = 0; 2221ad6d6297SScott Long /*FALLTHRU*/ 2222ad6d6297SScott Long case PCIDevVenIDARC1120: 2223ad6d6297SScott Long case PCIDevVenIDARC1130: 2224ad6d6297SScott Long case PCIDevVenIDARC1160: 2225ad6d6297SScott Long case PCIDevVenIDARC1170: 2226f1c579b1SScott Long case PCIDevVenIDARC1220: 2227f1c579b1SScott Long case PCIDevVenIDARC1230: 2228f1c579b1SScott Long case PCIDevVenIDARC1260: 2229ad6d6297SScott Long case PCIDevVenIDARC1270: 2230ad6d6297SScott Long case PCIDevVenIDARC1280: 2231ad6d6297SScott Long type = "SATA"; 2232ad6d6297SScott Long break; 2233ad6d6297SScott Long case PCIDevVenIDARC1380: 2234ad6d6297SScott Long case PCIDevVenIDARC1381: 2235ad6d6297SScott Long case PCIDevVenIDARC1680: 2236ad6d6297SScott Long case PCIDevVenIDARC1681: 2237ad6d6297SScott Long type = "SAS"; 2238ad6d6297SScott Long break; 2239ad6d6297SScott Long default: 2240ad6d6297SScott Long type = "X-TYPE"; 2241ad6d6297SScott Long break; 2242f1c579b1SScott Long } 2243ad6d6297SScott Long sprintf(buf, "Areca %s Host Adapter RAID Controller %s\n", type, raid6 ? "(RAID6 capable)" : ""); 2244ad6d6297SScott Long device_set_desc_copy(dev, buf); 2245ad6d6297SScott Long return 0; 2246f1c579b1SScott Long } 2247f1c579b1SScott Long /* 2248f1c579b1SScott Long ************************************************************************ 2249f1c579b1SScott Long ************************************************************************ 2250f1c579b1SScott Long */ 2251ad6d6297SScott Long static void arcmsr_shutdown(device_t dev) 2252f1c579b1SScott Long { 2253ad6d6297SScott Long u_int32_t i, poll_count=0; 2254ad6d6297SScott Long u_int32_t intmask_org; 2255ad6d6297SScott Long struct CommandControlBlock *srb; 2256ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 2257f1c579b1SScott Long 2258f1c579b1SScott Long /* stop adapter background rebuild */ 2259ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 2260ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2261ad6d6297SScott Long /* disable all outbound interrupt */ 2262ad6d6297SScott Long intmask_org=CHIP_REG_READ32(outbound_intmask); 2263ad6d6297SScott Long CHIP_REG_WRITE32(outbound_intmask, (intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE)); 2264f1c579b1SScott Long /* abort all outstanding command */ 2265ad6d6297SScott Long acb->acb_flags |= ACB_F_SCSISTOPADAPTER; 2266ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOP_INITED; 2267ad6d6297SScott Long if(acb->srboutstandingcount!=0) { 2268ad6d6297SScott Long while((acb->srboutstandingcount!=0) && (poll_count < 256)) { 2269ad6d6297SScott Long arcmsr_interrupt((void *)acb); 2270ad6d6297SScott Long UDELAY(25000); 2271ad6d6297SScott Long poll_count++; 2272f1c579b1SScott Long } 2273ad6d6297SScott Long if(acb->srboutstandingcount!=0) { 2274ad6d6297SScott Long arcmsr_abort_allcmd(acb); 2275ad6d6297SScott Long /*clear all outbound posted Q*/ 2276ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_OUTSTANDING_CMD;i++) { 2277ad6d6297SScott Long CHIP_REG_READ32(outbound_queueport); 2278f1c579b1SScott Long } 2279ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 2280ad6d6297SScott Long srb=acb->psrb_pool[i]; 2281ad6d6297SScott Long if(srb->startdone==ARCMSR_SRB_START) { 2282ad6d6297SScott Long srb->startdone=ARCMSR_SRB_ABORTED; 2283ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 2284ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 2285f1c579b1SScott Long } 2286f1c579b1SScott Long } 2287f1c579b1SScott Long } 2288ad6d6297SScott Long } 2289ad6d6297SScott Long atomic_set_int(&acb->srboutstandingcount, 0); 2290ad6d6297SScott Long acb->workingsrb_doneindex=0; 2291ad6d6297SScott Long acb->workingsrb_startindex=0; 2292f1c579b1SScott Long return; 2293f1c579b1SScott Long } 2294f1c579b1SScott Long /* 2295f1c579b1SScott Long ************************************************************************ 2296f1c579b1SScott Long ************************************************************************ 2297f1c579b1SScott Long */ 2298ad6d6297SScott Long static u_int32_t arcmsr_detach(device_t dev) 2299f1c579b1SScott Long { 2300ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 2301f1c579b1SScott Long 2302f1c579b1SScott Long arcmsr_shutdown(dev); 2303ad6d6297SScott Long arcmsr_free_resource(acb); 2304ad6d6297SScott Long bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0), acb->sys_res_arcmsr); 2305ad6d6297SScott Long bus_teardown_intr(dev, acb->irqres, acb->ih); 2306ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 2307ad6d6297SScott Long xpt_async(AC_LOST_DEVICE, acb->ppath, NULL); 2308ad6d6297SScott Long xpt_free_path(acb->ppath); 2309ad6d6297SScott Long xpt_bus_deregister(cam_sim_path(acb->psim)); 2310ad6d6297SScott Long cam_sim_free(acb->psim, TRUE); 2311f1c579b1SScott Long return (0); 2312f1c579b1SScott Long } 2313f1c579b1SScott Long 2314f1c579b1SScott Long 2315