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 5744f05562SScott Long ** 1.20.00.15 10/10/2007 Erich Chen support new RAID adapter type ARC120x 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) 1065878cbecSScott Long #define ARCMSR_LOCK_DESTROY(l) mtx_destroy(l) 107f1c579b1SScott Long #define ARCMSR_LOCK_ACQUIRE(l) mtx_lock(l) 108f1c579b1SScott Long #define ARCMSR_LOCK_RELEASE(l) mtx_unlock(l) 109ad6d6297SScott Long #define ARCMSR_LOCK_TRY(l) mtx_trylock(l) 110ad6d6297SScott Long #define arcmsr_htole32(x) htole32(x) 111f1c579b1SScott Long typedef struct mtx arcmsr_lock_t; 112f1c579b1SScott Long #else 113f1c579b1SScott Long #include <sys/select.h> 114f1c579b1SScott Long #include <pci/pcivar.h> 115f1c579b1SScott Long #include <pci/pcireg.h> 116f1c579b1SScott Long #define ARCMSR_LOCK_INIT(l, s) simple_lock_init(l) 1175878cbecSScott Long #define ARCMSR_LOCK_DESTROY(l) 118f1c579b1SScott Long #define ARCMSR_LOCK_ACQUIRE(l) simple_lock(l) 119f1c579b1SScott Long #define ARCMSR_LOCK_RELEASE(l) simple_unlock(l) 120ad6d6297SScott Long #define ARCMSR_LOCK_TRY(l) simple_lock_try(l) 121ad6d6297SScott Long #define arcmsr_htole32(x) (x) 122f1c579b1SScott Long typedef struct simplelock arcmsr_lock_t; 123f1c579b1SScott Long #endif 12444f05562SScott Long 12544f05562SScott Long #if !defined(CAM_NEW_TRAN_CODE) && __FreeBSD_version >= 700025 12644f05562SScott Long #define CAM_NEW_TRAN_CODE 1 12744f05562SScott Long #endif 12844f05562SScott Long 129f1c579b1SScott Long #include <dev/arcmsr/arcmsr.h> 13044f05562SScott Long #define ARCMSR_SRBS_POOL_SIZE ((sizeof(struct CommandControlBlock) * ARCMSR_MAX_FREESRB_NUM)) 131f1c579b1SScott Long /* 132f1c579b1SScott Long ************************************************************************** 133f1c579b1SScott Long ************************************************************************** 134f1c579b1SScott Long */ 13544f05562SScott Long #define CHIP_REG_READ32(s, b, r) bus_space_read_4(acb->btag[b], acb->bhandle[b], offsetof(struct s, r)) 13644f05562SScott Long #define CHIP_REG_WRITE32(s, b, r, d) bus_space_write_4(acb->btag[b], acb->bhandle[b], offsetof(struct s, r), d) 137f1c579b1SScott Long /* 138f1c579b1SScott Long ************************************************************************** 139f1c579b1SScott Long ************************************************************************** 140f1c579b1SScott Long */ 141ad6d6297SScott Long static struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb); 142ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb); 143ad6d6297SScott Long static u_int32_t arcmsr_probe(device_t dev); 144ad6d6297SScott Long static u_int32_t arcmsr_attach(device_t dev); 145ad6d6297SScott Long static u_int32_t arcmsr_detach(device_t dev); 146ad6d6297SScott Long static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg); 147ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb); 148ad6d6297SScott Long static void arcmsr_shutdown(device_t dev); 14944f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb); 150ad6d6297SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb); 151ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb); 152ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb); 153ad6d6297SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); 154ad6d6297SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb); 155ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb); 156ad6d6297SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb); 15744f05562SScott Long static void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb); 158ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb); 159ad6d6297SScott Long static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag); 160ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb); 161ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb); 162ad6d6297SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t * dm_segs, u_int32_t nseg); 163ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb); 164ad6d6297SScott Long static int arcmsr_resume(device_t dev); 165ad6d6297SScott Long static int arcmsr_suspend(device_t dev); 166f1c579b1SScott Long /* 167f1c579b1SScott Long ************************************************************************** 168ad6d6297SScott Long ************************************************************************** 169ad6d6297SScott Long */ 170ad6d6297SScott Long static void UDELAY(u_int32_t us) { DELAY(us); } 171ad6d6297SScott Long /* 172ad6d6297SScott Long ************************************************************************** 173f1c579b1SScott Long ************************************************************************** 174f1c579b1SScott Long */ 175f1c579b1SScott Long static bus_dmamap_callback_t arcmsr_map_freesrb; 176f1c579b1SScott Long static bus_dmamap_callback_t arcmsr_executesrb; 177f1c579b1SScott Long /* 178f1c579b1SScott Long ************************************************************************** 179f1c579b1SScott Long ************************************************************************** 180f1c579b1SScott Long */ 181f1c579b1SScott Long static d_open_t arcmsr_open; 182f1c579b1SScott Long static d_close_t arcmsr_close; 183f1c579b1SScott Long static d_ioctl_t arcmsr_ioctl; 184f1c579b1SScott Long 185f1c579b1SScott Long static device_method_t arcmsr_methods[]={ 186f1c579b1SScott Long DEVMETHOD(device_probe, arcmsr_probe), 187f1c579b1SScott Long DEVMETHOD(device_attach, arcmsr_attach), 188f1c579b1SScott Long DEVMETHOD(device_detach, arcmsr_detach), 189f1c579b1SScott Long DEVMETHOD(device_shutdown, arcmsr_shutdown), 190ad6d6297SScott Long DEVMETHOD(device_suspend, arcmsr_suspend), 191ad6d6297SScott Long DEVMETHOD(device_resume, arcmsr_resume), 192ad6d6297SScott Long 193ad6d6297SScott Long DEVMETHOD(bus_print_child, bus_generic_print_child), 194ad6d6297SScott Long DEVMETHOD(bus_driver_added, bus_generic_driver_added), 195f1c579b1SScott Long { 0, 0 } 196f1c579b1SScott Long }; 197f1c579b1SScott Long 198f1c579b1SScott Long static driver_t arcmsr_driver={ 199ad6d6297SScott Long "arcmsr", arcmsr_methods, sizeof(struct AdapterControlBlock) 200f1c579b1SScott Long }; 201f1c579b1SScott Long 202f1c579b1SScott Long static devclass_t arcmsr_devclass; 203f1c579b1SScott Long DRIVER_MODULE(arcmsr, pci, arcmsr_driver, arcmsr_devclass, 0, 0); 204d3cf342dSScott Long MODULE_DEPEND(arcmsr, pci, 1, 1, 1); 205d3cf342dSScott Long MODULE_DEPEND(arcmsr, cam, 1, 1, 1); 206ad6d6297SScott Long #ifndef BUS_DMA_COHERENT 207ad6d6297SScott Long #define BUS_DMA_COHERENT 0x04 /* hint: map memory in a coherent way */ 208ad6d6297SScott Long #endif 209ad6d6297SScott Long #if __FreeBSD_version >= 501000 210ad6d6297SScott Long #ifndef D_NEEDGIANT 211ad6d6297SScott Long #define D_NEEDGIANT 0x00400000 /* driver want Giant */ 212ad6d6297SScott Long #endif 213ad6d6297SScott Long #ifndef D_VERSION 214ad6d6297SScott Long #define D_VERSION 0x20011966 215ad6d6297SScott Long #endif 216f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw={ 217ad6d6297SScott Long #if __FreeBSD_version > 502010 218f1c579b1SScott Long .d_version = D_VERSION, 219ad6d6297SScott Long #endif 220f1c579b1SScott Long .d_flags = D_NEEDGIANT, 221f1c579b1SScott Long .d_open = arcmsr_open, /* open */ 222f1c579b1SScott Long .d_close = arcmsr_close, /* close */ 223f1c579b1SScott Long .d_ioctl = arcmsr_ioctl, /* ioctl */ 224f1c579b1SScott Long .d_name = "arcmsr", /* name */ 225f1c579b1SScott Long }; 226f1c579b1SScott Long #else 227f1c579b1SScott Long #define ARCMSR_CDEV_MAJOR 180 228f1c579b1SScott Long 229f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw = { 230f1c579b1SScott Long arcmsr_open, /* open */ 231f1c579b1SScott Long arcmsr_close, /* close */ 232f1c579b1SScott Long noread, /* read */ 233f1c579b1SScott Long nowrite, /* write */ 234f1c579b1SScott Long arcmsr_ioctl, /* ioctl */ 235f1c579b1SScott Long nopoll, /* poll */ 236f1c579b1SScott Long nommap, /* mmap */ 237f1c579b1SScott Long nostrategy, /* strategy */ 238f1c579b1SScott Long "arcmsr", /* name */ 239f1c579b1SScott Long ARCMSR_CDEV_MAJOR, /* major */ 240f1c579b1SScott Long nodump, /* dump */ 241f1c579b1SScott Long nopsize, /* psize */ 242f1c579b1SScott Long 0 /* flags */ 243f1c579b1SScott Long }; 244f1c579b1SScott Long #endif 245f1c579b1SScott Long 246f1c579b1SScott Long #if __FreeBSD_version < 500005 247f1c579b1SScott Long static int arcmsr_open(dev_t dev, int flags, int fmt, struct proc *proc) 248f1c579b1SScott Long #else 249f1c579b1SScott Long #if __FreeBSD_version < 503000 250f1c579b1SScott Long static int arcmsr_open(dev_t dev, int flags, int fmt, struct thread *proc) 251f1c579b1SScott Long #else 252f1c579b1SScott Long static int arcmsr_open(struct cdev *dev, int flags, int fmt, d_thread_t *proc) 253f1c579b1SScott Long #endif 254f1c579b1SScott Long #endif 255f1c579b1SScott Long { 256f1c579b1SScott Long #if __FreeBSD_version < 503000 257ad6d6297SScott Long struct AdapterControlBlock *acb=dev->si_drv1; 258f1c579b1SScott Long #else 259f1c579b1SScott Long int unit = minor(dev); 260ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 261f1c579b1SScott Long #endif 262ad6d6297SScott Long if(acb==NULL) { 263f1c579b1SScott Long return ENXIO; 264f1c579b1SScott Long } 265f1c579b1SScott Long return 0; 266f1c579b1SScott Long } 267f1c579b1SScott Long /* 268f1c579b1SScott Long ************************************************************************** 269f1c579b1SScott Long ************************************************************************** 270f1c579b1SScott Long */ 271f1c579b1SScott Long #if __FreeBSD_version < 500005 272f1c579b1SScott Long static int arcmsr_close(dev_t dev, int flags, int fmt, struct proc *proc) 273f1c579b1SScott Long #else 274f1c579b1SScott Long #if __FreeBSD_version < 503000 275f1c579b1SScott Long static int arcmsr_close(dev_t dev, int flags, int fmt, struct thread *proc) 276f1c579b1SScott Long #else 277f1c579b1SScott Long static int arcmsr_close(struct cdev *dev, int flags, int fmt, d_thread_t *proc) 278f1c579b1SScott Long #endif 279f1c579b1SScott Long #endif 280f1c579b1SScott Long { 281f1c579b1SScott Long #if __FreeBSD_version < 503000 282ad6d6297SScott Long struct AdapterControlBlock *acb=dev->si_drv1; 283f1c579b1SScott Long #else 284f1c579b1SScott Long int unit = minor(dev); 285ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 286f1c579b1SScott Long #endif 287ad6d6297SScott Long if(acb==NULL) { 288f1c579b1SScott Long return ENXIO; 289f1c579b1SScott Long } 290f1c579b1SScott Long return 0; 291f1c579b1SScott Long } 292f1c579b1SScott Long /* 293f1c579b1SScott Long ************************************************************************** 294f1c579b1SScott Long ************************************************************************** 295f1c579b1SScott Long */ 296f1c579b1SScott Long #if __FreeBSD_version < 500005 297f1c579b1SScott Long static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct proc *proc) 298f1c579b1SScott Long #else 299f1c579b1SScott Long #if __FreeBSD_version < 503000 300f1c579b1SScott Long static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc) 301f1c579b1SScott Long #else 302f1c579b1SScott Long static int arcmsr_ioctl(struct cdev *dev, u_long ioctl_cmd, caddr_t arg, int flags, d_thread_t *proc) 303f1c579b1SScott Long #endif 304f1c579b1SScott Long #endif 305f1c579b1SScott Long { 306f1c579b1SScott Long #if __FreeBSD_version < 503000 307ad6d6297SScott Long struct AdapterControlBlock *acb=dev->si_drv1; 308f1c579b1SScott Long #else 309f1c579b1SScott Long int unit = minor(dev); 310ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 311f1c579b1SScott Long #endif 312f1c579b1SScott Long 313ad6d6297SScott Long if(acb==NULL) { 314f1c579b1SScott Long return ENXIO; 315f1c579b1SScott Long } 316ad6d6297SScott Long return(arcmsr_iop_ioctlcmd(acb, ioctl_cmd, arg)); 317f1c579b1SScott Long } 318f1c579b1SScott Long /* 31944f05562SScott Long ********************************************************************** 32044f05562SScott Long ********************************************************************** 32144f05562SScott Long */ 32244f05562SScott Long static u_int32_t arcmsr_disable_allintr( struct AdapterControlBlock *acb) 32344f05562SScott Long { 32444f05562SScott Long u_int32_t intmask_org=0; 32544f05562SScott Long 32644f05562SScott Long switch (acb->adapter_type) { 32744f05562SScott Long case ACB_ADAPTER_TYPE_A: { 32844f05562SScott Long /* disable all outbound interrupt */ 32944f05562SScott Long intmask_org=CHIP_REG_READ32(HBA_MessageUnit, 33044f05562SScott Long 0, outbound_intmask)|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE; /* disable outbound message0 int */ 33144f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 33244f05562SScott Long 0, outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); 33344f05562SScott Long } 33444f05562SScott Long break; 33544f05562SScott Long case ACB_ADAPTER_TYPE_B: { 33644f05562SScott Long /* disable all outbound interrupt */ 33744f05562SScott Long intmask_org=CHIP_REG_READ32(HBB_DOORBELL, 33844f05562SScott Long 0, iop2drv_doorbell_mask) & (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); /* disable outbound message0 int */ 33944f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 34044f05562SScott Long 0, iop2drv_doorbell_mask, 0); /* disable all interrupt */ 34144f05562SScott Long } 34244f05562SScott Long break; 34344f05562SScott Long } 34444f05562SScott Long return(intmask_org); 34544f05562SScott Long } 34644f05562SScott Long /* 34744f05562SScott Long ********************************************************************** 34844f05562SScott Long ********************************************************************** 34944f05562SScott Long */ 35044f05562SScott Long static void arcmsr_enable_allintr( struct AdapterControlBlock *acb, u_int32_t intmask_org) 35144f05562SScott Long { 35244f05562SScott Long u_int32_t mask; 35344f05562SScott Long 35444f05562SScott Long switch (acb->adapter_type) { 35544f05562SScott Long case ACB_ADAPTER_TYPE_A: { 35644f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 35744f05562SScott Long mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); 35844f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org & mask); 35944f05562SScott Long acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; 36044f05562SScott Long } 36144f05562SScott Long break; 36244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 36344f05562SScott Long /* disable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */ 36444f05562SScott Long mask=(ARCMSR_IOP2DRV_DATA_WRITE_OK|ARCMSR_IOP2DRV_DATA_READ_OK|ARCMSR_IOP2DRV_CDB_DONE); 36544f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 36644f05562SScott Long 0, iop2drv_doorbell_mask, intmask_org | mask); /*1=interrupt enable, 0=interrupt disable*/ 36744f05562SScott Long acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f; 36844f05562SScott Long } 36944f05562SScott Long break; 37044f05562SScott Long } 37144f05562SScott Long return; 37244f05562SScott Long } 37344f05562SScott Long /* 37444f05562SScott Long ********************************************************************** 37544f05562SScott Long ********************************************************************** 37644f05562SScott Long */ 37744f05562SScott Long static u_int8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) 37844f05562SScott Long { 37944f05562SScott Long u_int32_t Index; 38044f05562SScott Long u_int8_t Retries=0x00; 38144f05562SScott Long 38244f05562SScott Long do { 38344f05562SScott Long for(Index=0; Index < 100; Index++) { 38444f05562SScott Long if(CHIP_REG_READ32(HBA_MessageUnit, 38544f05562SScott Long 0, outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { 38644f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 38744f05562SScott Long 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/ 38844f05562SScott Long return TRUE; 38944f05562SScott Long } 39044f05562SScott Long UDELAY(10000); 39144f05562SScott Long }/*max 1 seconds*/ 39244f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 39344f05562SScott Long return FALSE; 39444f05562SScott Long } 39544f05562SScott Long /* 39644f05562SScott Long ********************************************************************** 39744f05562SScott Long ********************************************************************** 39844f05562SScott Long */ 39944f05562SScott Long static u_int8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) 40044f05562SScott Long { 40144f05562SScott Long u_int32_t Index; 40244f05562SScott Long u_int8_t Retries=0x00; 40344f05562SScott Long 40444f05562SScott Long do { 40544f05562SScott Long for(Index=0; Index < 100; Index++) { 40644f05562SScott Long if(CHIP_REG_READ32(HBB_DOORBELL, 40744f05562SScott Long 0, iop2drv_doorbell) & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { 40844f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 40944f05562SScott Long 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/ 41044f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 41144f05562SScott Long 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 41244f05562SScott Long return TRUE; 41344f05562SScott Long } 41444f05562SScott Long UDELAY(10000); 41544f05562SScott Long }/*max 1 seconds*/ 41644f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 41744f05562SScott Long return FALSE; 41844f05562SScott Long } 41944f05562SScott Long /* 42044f05562SScott Long ************************************************************************ 42144f05562SScott Long ************************************************************************ 42244f05562SScott Long */ 42344f05562SScott Long static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) 42444f05562SScott Long { 42544f05562SScott Long int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */ 42644f05562SScott Long 42744f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 42844f05562SScott Long 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 42944f05562SScott Long do { 43044f05562SScott Long if(arcmsr_hba_wait_msgint_ready(acb)) { 43144f05562SScott Long break; 43244f05562SScott Long } else { 43344f05562SScott Long retry_count--; 43444f05562SScott Long } 43544f05562SScott Long }while(retry_count!=0); 43644f05562SScott Long return; 43744f05562SScott Long } 43844f05562SScott Long /* 43944f05562SScott Long ************************************************************************ 44044f05562SScott Long ************************************************************************ 44144f05562SScott Long */ 44244f05562SScott Long static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) 44344f05562SScott Long { 44444f05562SScott Long int retry_count=30;/* enlarge wait flush adapter cache time: 10 minute */ 44544f05562SScott Long 44644f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 44744f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_FLUSH_CACHE); 44844f05562SScott Long do { 44944f05562SScott Long if(arcmsr_hbb_wait_msgint_ready(acb)) { 45044f05562SScott Long break; 45144f05562SScott Long } else { 45244f05562SScott Long retry_count--; 45344f05562SScott Long } 45444f05562SScott Long }while(retry_count!=0); 45544f05562SScott Long return; 45644f05562SScott Long } 45744f05562SScott Long /* 45844f05562SScott Long ************************************************************************ 45944f05562SScott Long ************************************************************************ 46044f05562SScott Long */ 46144f05562SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) 46244f05562SScott Long { 46344f05562SScott Long switch (acb->adapter_type) { 46444f05562SScott Long case ACB_ADAPTER_TYPE_A: { 46544f05562SScott Long arcmsr_flush_hba_cache(acb); 46644f05562SScott Long } 46744f05562SScott Long break; 46844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 46944f05562SScott Long arcmsr_flush_hbb_cache(acb); 47044f05562SScott Long } 47144f05562SScott Long break; 47244f05562SScott Long } 47344f05562SScott Long return; 47444f05562SScott Long } 47544f05562SScott Long /* 476ad6d6297SScott Long ******************************************************************************* 477ad6d6297SScott Long ******************************************************************************* 478f1c579b1SScott Long */ 479ad6d6297SScott Long static int arcmsr_suspend(device_t dev) 480f1c579b1SScott Long { 481ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 482f1c579b1SScott Long 483ad6d6297SScott Long /* disable all outbound interrupt */ 48444f05562SScott Long arcmsr_disable_allintr(acb); 485ad6d6297SScott Long /* flush controller */ 486ad6d6297SScott Long arcmsr_iop_parking(acb); 487ad6d6297SScott Long return(0); 488ad6d6297SScott Long } 489ad6d6297SScott Long /* 490ad6d6297SScott Long ******************************************************************************* 491ad6d6297SScott Long ******************************************************************************* 492ad6d6297SScott Long */ 493ad6d6297SScott Long static int arcmsr_resume(device_t dev) 494ad6d6297SScott Long { 495ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 496f1c579b1SScott Long 497ad6d6297SScott Long arcmsr_iop_init(acb); 498ad6d6297SScott Long return(0); 499f1c579b1SScott Long } 500f1c579b1SScott Long /* 501f1c579b1SScott Long ********************************************************************************* 502f1c579b1SScott Long ********************************************************************************* 503f1c579b1SScott Long */ 504ad6d6297SScott Long static void arcmsr_async(void *cb_arg, u_int32_t code, struct cam_path *path, void *arg) 505f1c579b1SScott Long { 506ad6d6297SScott Long struct AdapterControlBlock *acb; 507ad6d6297SScott Long u_int8_t target_id, target_lun; 508f1c579b1SScott Long struct cam_sim * sim; 509f1c579b1SScott Long 510f1c579b1SScott Long sim=(struct cam_sim *) cb_arg; 511ad6d6297SScott Long acb =(struct AdapterControlBlock *) cam_sim_softc(sim); 512ad6d6297SScott Long switch (code) { 513f1c579b1SScott Long case AC_LOST_DEVICE: 514f1c579b1SScott Long target_id=xpt_path_target_id(path); 515f1c579b1SScott Long target_lun=xpt_path_lun_id(path); 51644f05562SScott Long if((target_id > ARCMSR_MAX_TARGETID) 51744f05562SScott Long || (target_lun > ARCMSR_MAX_TARGETLUN)) { 518f1c579b1SScott Long break; 519f1c579b1SScott Long } 520ad6d6297SScott Long printf("%s:scsi id%d lun%d device lost \n" 521ad6d6297SScott Long , device_get_name(acb->pci_dev), target_id, target_lun); 522f1c579b1SScott Long break; 523f1c579b1SScott Long default: 524f1c579b1SScott Long break; 525f1c579b1SScott Long } 526f1c579b1SScott Long } 527f1c579b1SScott Long /* 528f1c579b1SScott Long ********************************************************************** 529f1c579b1SScott Long ********************************************************************** 530f1c579b1SScott Long */ 531ad6d6297SScott Long static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag) 532f1c579b1SScott Long { 533ad6d6297SScott Long struct AdapterControlBlock *acb=srb->acb; 534ad6d6297SScott Long union ccb * pccb=srb->pccb; 535f1c579b1SScott Long 536ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 537f1c579b1SScott Long bus_dmasync_op_t op; 538f1c579b1SScott Long 539ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 540f1c579b1SScott Long op = BUS_DMASYNC_POSTREAD; 541ad6d6297SScott Long } else { 542f1c579b1SScott Long op = BUS_DMASYNC_POSTWRITE; 543f1c579b1SScott Long } 544ad6d6297SScott Long bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 545ad6d6297SScott Long bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 546f1c579b1SScott Long } 547ad6d6297SScott Long if(stand_flag==1) { 548ad6d6297SScott Long atomic_subtract_int(&acb->srboutstandingcount, 1); 549dc3a205bSScott Long if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) && ( 550dc3a205bSScott Long acb->srboutstandingcount < ARCMSR_RELEASE_SIMQ_LEVEL)) { 551dc3a205bSScott Long acb->acb_flags &= ~ACB_F_CAM_DEV_QFRZN; 552dc3a205bSScott Long pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 553dc3a205bSScott Long } 554ad6d6297SScott Long } 555ad6d6297SScott Long srb->startdone=ARCMSR_SRB_DONE; 556ad6d6297SScott Long srb->srb_flags=0; 557ad6d6297SScott Long acb->srbworkingQ[acb->workingsrb_doneindex]=srb; 558ad6d6297SScott Long acb->workingsrb_doneindex++; 559ad6d6297SScott Long acb->workingsrb_doneindex %= ARCMSR_MAX_FREESRB_NUM; 560f1c579b1SScott Long xpt_done(pccb); 561f1c579b1SScott Long return; 562f1c579b1SScott Long } 563f1c579b1SScott Long /* 564f1c579b1SScott Long ********************************************************************** 565f1c579b1SScott Long ********************************************************************** 566f1c579b1SScott Long */ 567ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb) 568f1c579b1SScott Long { 569ad6d6297SScott Long union ccb * pccb=srb->pccb; 570f1c579b1SScott Long 571ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 572ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 573ad6d6297SScott Long if(&pccb->csio.sense_data) { 574ad6d6297SScott Long memset(&pccb->csio.sense_data, 0, sizeof(pccb->csio.sense_data)); 575ad6d6297SScott Long memcpy(&pccb->csio.sense_data, srb->arcmsr_cdb.SenseData, 576ad6d6297SScott Long get_min(sizeof(struct SENSE_DATA), sizeof(pccb->csio.sense_data))); 577ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); /* Valid,ErrorCode */ 578f1c579b1SScott Long pccb->ccb_h.status |= CAM_AUTOSNS_VALID; 579f1c579b1SScott Long } 580f1c579b1SScott Long return; 581f1c579b1SScott Long } 582f1c579b1SScott Long /* 583f1c579b1SScott Long ********************************************************************* 58444f05562SScott Long ********************************************************************* 58544f05562SScott Long */ 58644f05562SScott Long static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) 58744f05562SScott Long { 58844f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 58944f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 59044f05562SScott Long printf("arcmsr%d: wait 'abort all outstanding command' timeout \n" 59144f05562SScott Long , acb->pci_unit); 59244f05562SScott Long } 59344f05562SScott Long return; 59444f05562SScott Long } 59544f05562SScott Long /* 59644f05562SScott Long ********************************************************************* 59744f05562SScott Long ********************************************************************* 59844f05562SScott Long */ 59944f05562SScott Long static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) 60044f05562SScott Long { 60144f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_MESSAGE_ABORT_CMD); 60244f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 60344f05562SScott Long printf("arcmsr%d: wait 'abort all outstanding command' timeout \n" 60444f05562SScott Long , acb->pci_unit); 60544f05562SScott Long } 60644f05562SScott Long return; 60744f05562SScott Long } 60844f05562SScott Long /* 60944f05562SScott Long ********************************************************************* 610f1c579b1SScott Long ********************************************************************* 611f1c579b1SScott Long */ 612ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) 613f1c579b1SScott Long { 61444f05562SScott Long switch (acb->adapter_type) { 61544f05562SScott Long case ACB_ADAPTER_TYPE_A: { 61644f05562SScott Long arcmsr_abort_hba_allcmd(acb); 61744f05562SScott Long } 61844f05562SScott Long break; 61944f05562SScott Long case ACB_ADAPTER_TYPE_B: { 62044f05562SScott Long arcmsr_abort_hbb_allcmd(acb); 62144f05562SScott Long } 62244f05562SScott Long break; 62344f05562SScott Long } 62444f05562SScott Long return; 62544f05562SScott Long } 62644f05562SScott Long /* 62744f05562SScott Long ************************************************************************** 62844f05562SScott Long ************************************************************************** 62944f05562SScott Long */ 63044f05562SScott Long static void arcmsr_report_srb_state(struct AdapterControlBlock *acb, 63144f05562SScott Long struct CommandControlBlock *srb, u_int32_t flag_srb) 63244f05562SScott Long { 63344f05562SScott Long int target, lun; 63444f05562SScott Long 63544f05562SScott Long target=srb->pccb->ccb_h.target_id; 63644f05562SScott Long lun=srb->pccb->ccb_h.target_lun; 63744f05562SScott Long if((flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR)==0) { 63844f05562SScott Long if(acb->devstate[target][lun]==ARECA_RAID_GONE) { 63944f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GOOD; 64044f05562SScott Long } 64144f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_CMP; 64244f05562SScott Long arcmsr_srb_complete(srb, 1); 64344f05562SScott Long } else { 64444f05562SScott Long switch(srb->arcmsr_cdb.DeviceStatus) { 64544f05562SScott Long case ARCMSR_DEV_SELECT_TIMEOUT: { 64644f05562SScott Long if(acb->devstate[target][lun]==ARECA_RAID_GOOD) { 64744f05562SScott Long printf( "arcmsr%d: select timeout" 64844f05562SScott Long ", raid volume was kicked out \n" 649ad6d6297SScott Long , acb->pci_unit); 650ad6d6297SScott Long } 65144f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GONE; 65244f05562SScott Long srb->pccb->ccb_h.status |= CAM_SEL_TIMEOUT; 65344f05562SScott Long arcmsr_srb_complete(srb, 1); 65444f05562SScott Long } 65544f05562SScott Long break; 65644f05562SScott Long case ARCMSR_DEV_ABORTED: 65744f05562SScott Long case ARCMSR_DEV_INIT_FAIL: { 65844f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GONE; 65944f05562SScott Long srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 66044f05562SScott Long arcmsr_srb_complete(srb, 1); 66144f05562SScott Long } 66244f05562SScott Long break; 66344f05562SScott Long case SCSISTAT_CHECK_CONDITION: { 66444f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GOOD; 66544f05562SScott Long arcmsr_report_sense_info(srb); 66644f05562SScott Long arcmsr_srb_complete(srb, 1); 66744f05562SScott Long } 66844f05562SScott Long break; 66944f05562SScott Long default: 67044f05562SScott Long printf("arcmsr%d: scsi id=%d lun=%d" 67144f05562SScott Long "isr get command error done," 67244f05562SScott Long "but got unknow DeviceStatus=0x%x \n" 67344f05562SScott Long , acb->pci_unit, target, lun 67444f05562SScott Long ,srb->arcmsr_cdb.DeviceStatus); 67544f05562SScott Long acb->devstate[target][lun]=ARECA_RAID_GONE; 67644f05562SScott Long srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY; 67744f05562SScott Long /*unknow error or crc error just for retry*/ 67844f05562SScott Long arcmsr_srb_complete(srb, 1); 67944f05562SScott Long break; 68044f05562SScott Long } 68144f05562SScott Long } 68244f05562SScott Long return; 68344f05562SScott Long } 68444f05562SScott Long /* 68544f05562SScott Long ************************************************************************** 68644f05562SScott Long ************************************************************************** 68744f05562SScott Long */ 68844f05562SScott Long static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t flag_srb) 68944f05562SScott Long { 69044f05562SScott Long struct CommandControlBlock *srb; 69144f05562SScott Long 69244f05562SScott Long /* check if command done with no error*/ 69344f05562SScott Long srb=(struct CommandControlBlock *) 69444f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 69544f05562SScott Long if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) { 69644f05562SScott Long if(srb->startdone==ARCMSR_SRB_ABORTED) { 69744f05562SScott Long printf("arcmsr%d: srb='%p' isr got aborted command \n" 69844f05562SScott Long , acb->pci_unit, srb); 69944f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 70044f05562SScott Long arcmsr_srb_complete(srb, 1); 70144f05562SScott Long return; 70244f05562SScott Long } 70344f05562SScott Long printf("arcmsr%d: isr get an illegal srb command done" 70444f05562SScott Long "acb='%p' srb='%p' srbacb='%p' startdone=0x%x" 70544f05562SScott Long "srboutstandingcount=%d \n", 70644f05562SScott Long acb->pci_unit, acb, srb, srb->acb, 70744f05562SScott Long srb->startdone, acb->srboutstandingcount); 70844f05562SScott Long return; 70944f05562SScott Long } 71044f05562SScott Long arcmsr_report_srb_state(acb, srb, flag_srb); 71144f05562SScott Long return; 71244f05562SScott Long } 71344f05562SScott Long /* 71444f05562SScott Long ********************************************************************** 71544f05562SScott Long ********************************************************************** 71644f05562SScott Long */ 71744f05562SScott Long static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) 71844f05562SScott Long { 71944f05562SScott Long int i=0; 72044f05562SScott Long u_int32_t flag_srb; 72144f05562SScott Long 72244f05562SScott Long switch (acb->adapter_type) { 72344f05562SScott Long case ACB_ADAPTER_TYPE_A: { 72444f05562SScott Long u_int32_t outbound_intstatus; 72544f05562SScott Long 72644f05562SScott Long /*clear and abort all outbound posted Q*/ 72744f05562SScott Long outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 72844f05562SScott Long 0, outbound_intstatus) & acb->outbound_int_enable; 72944f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 73044f05562SScott Long 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/ 73144f05562SScott Long while(((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 73244f05562SScott Long 0, outbound_queueport)) != 0xFFFFFFFF) 73344f05562SScott Long && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { 73444f05562SScott Long arcmsr_drain_donequeue(acb, flag_srb); 73544f05562SScott Long } 73644f05562SScott Long } 73744f05562SScott Long break; 73844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 73944f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 74044f05562SScott Long 74144f05562SScott Long /*clear all outbound posted Q*/ 74244f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 74344f05562SScott Long 0, iop2drv_doorbell, 74444f05562SScott Long ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 74544f05562SScott Long for(i=0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) { 74644f05562SScott Long if((flag_srb=phbbmu->done_qbuffer[i])!=0) { 74744f05562SScott Long phbbmu->done_qbuffer[i]=0; 74844f05562SScott Long arcmsr_drain_donequeue(acb, flag_srb); 74944f05562SScott Long } 75044f05562SScott Long phbbmu->post_qbuffer[i]=0; 75144f05562SScott Long }/*drain reply FIFO*/ 75244f05562SScott Long phbbmu->doneq_index=0; 75344f05562SScott Long phbbmu->postq_index=0; 75444f05562SScott Long } 75544f05562SScott Long break; 75644f05562SScott Long } 757f1c579b1SScott Long return; 758f1c579b1SScott Long } 759f1c579b1SScott Long /* 760f1c579b1SScott Long **************************************************************************** 761f1c579b1SScott Long **************************************************************************** 762f1c579b1SScott Long */ 763ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb) 764f1c579b1SScott Long { 765ad6d6297SScott Long struct CommandControlBlock *srb; 76644f05562SScott Long u_int32_t intmask_org; 767ad6d6297SScott Long u_int32_t i=0; 768f1c579b1SScott Long 76944f05562SScott Long if(acb->srboutstandingcount>0) { 77044f05562SScott Long /* disable all outbound interrupt */ 77144f05562SScott Long intmask_org=arcmsr_disable_allintr(acb); 77244f05562SScott Long /*clear and abort all outbound posted Q*/ 77344f05562SScott Long arcmsr_done4abort_postqueue(acb); 774f1c579b1SScott Long /* talk to iop 331 outstanding command aborted*/ 775ad6d6297SScott Long arcmsr_abort_allcmd(acb); 776ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 777ad6d6297SScott Long srb=acb->psrb_pool[i]; 778ad6d6297SScott Long if(srb->startdone==ARCMSR_SRB_START) { 779ad6d6297SScott Long srb->startdone=ARCMSR_SRB_ABORTED; 780ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 781ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 782f1c579b1SScott Long } 783f1c579b1SScott Long } 784f1c579b1SScott Long /* enable all outbound interrupt */ 78544f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 786f1c579b1SScott Long } 787ad6d6297SScott Long atomic_set_int(&acb->srboutstandingcount, 0); 788ad6d6297SScott Long acb->workingsrb_doneindex=0; 789ad6d6297SScott Long acb->workingsrb_startindex=0; 790f1c579b1SScott Long return; 791f1c579b1SScott Long } 792f1c579b1SScott Long /* 793f1c579b1SScott Long ********************************************************************** 794f1c579b1SScott Long ********************************************************************** 795f1c579b1SScott Long */ 79644f05562SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, 79744f05562SScott Long bus_dma_segment_t *dm_segs, u_int32_t nseg) 798f1c579b1SScott Long { 799ad6d6297SScott Long struct ARCMSR_CDB * arcmsr_cdb= &srb->arcmsr_cdb; 800ad6d6297SScott Long u_int8_t * psge=(u_int8_t *)&arcmsr_cdb->u; 801ad6d6297SScott Long u_int32_t address_lo, address_hi; 802ad6d6297SScott Long union ccb * pccb=srb->pccb; 803f1c579b1SScott Long struct ccb_scsiio * pcsio= &pccb->csio; 804ad6d6297SScott Long u_int32_t arccdbsize=0x30; 805f1c579b1SScott Long 806ad6d6297SScott Long memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB)); 807ad6d6297SScott Long arcmsr_cdb->Bus=0; 808ad6d6297SScott Long arcmsr_cdb->TargetID=pccb->ccb_h.target_id; 809ad6d6297SScott Long arcmsr_cdb->LUN=pccb->ccb_h.target_lun; 810ad6d6297SScott Long arcmsr_cdb->Function=1; 811ad6d6297SScott Long arcmsr_cdb->CdbLength=(u_int8_t)pcsio->cdb_len; 81244f05562SScott Long arcmsr_cdb->Context=0; 813ad6d6297SScott Long bcopy(pcsio->cdb_io.cdb_bytes, arcmsr_cdb->Cdb, pcsio->cdb_len); 814ad6d6297SScott Long if(nseg != 0) { 815ad6d6297SScott Long struct AdapterControlBlock *acb=srb->acb; 816f1c579b1SScott Long bus_dmasync_op_t op; 817ad6d6297SScott Long u_int32_t length, i, cdb_sgcount=0; 818f1c579b1SScott Long 819ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 820ad6d6297SScott Long op=BUS_DMASYNC_PREREAD; 821ad6d6297SScott Long } else { 822ad6d6297SScott Long op=BUS_DMASYNC_PREWRITE; 823ad6d6297SScott Long arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_WRITE; 824ad6d6297SScott Long srb->srb_flags|=SRB_FLAG_WRITE; 825ad6d6297SScott Long } 826ad6d6297SScott Long bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 827ad6d6297SScott Long for(i=0;i<nseg;i++) { 828f1c579b1SScott Long /* Get the physical address of the current data pointer */ 829ad6d6297SScott Long length=arcmsr_htole32(dm_segs[i].ds_len); 830ad6d6297SScott Long address_lo=arcmsr_htole32(dma_addr_lo32(dm_segs[i].ds_addr)); 831ad6d6297SScott Long address_hi=arcmsr_htole32(dma_addr_hi32(dm_segs[i].ds_addr)); 832ad6d6297SScott Long if(address_hi==0) { 833ad6d6297SScott Long struct SG32ENTRY * pdma_sg=(struct SG32ENTRY *)psge; 834f1c579b1SScott Long pdma_sg->address=address_lo; 835f1c579b1SScott Long pdma_sg->length=length; 836ad6d6297SScott Long psge += sizeof(struct SG32ENTRY); 837ad6d6297SScott Long arccdbsize += sizeof(struct SG32ENTRY); 838ad6d6297SScott Long } else { 839ad6d6297SScott Long u_int32_t sg64s_size=0, tmplength=length; 840f1c579b1SScott Long 841ad6d6297SScott Long while(1) { 842ad6d6297SScott Long u_int64_t span4G, length0; 843ad6d6297SScott Long struct SG64ENTRY * pdma_sg=(struct SG64ENTRY *)psge; 844f1c579b1SScott Long 845ad6d6297SScott Long span4G=(u_int64_t)address_lo + tmplength; 846f1c579b1SScott Long pdma_sg->addresshigh=address_hi; 847f1c579b1SScott Long pdma_sg->address=address_lo; 848ad6d6297SScott Long if(span4G > 0x100000000) { 849f1c579b1SScott Long /*see if cross 4G boundary*/ 850f1c579b1SScott Long length0=0x100000000-address_lo; 851ad6d6297SScott Long pdma_sg->length=(u_int32_t)length0|IS_SG64_ADDR; 852f1c579b1SScott Long address_hi=address_hi+1; 853f1c579b1SScott Long address_lo=0; 854ad6d6297SScott Long tmplength=tmplength-(u_int32_t)length0; 855ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 856ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 857f1c579b1SScott Long cdb_sgcount++; 858ad6d6297SScott Long } else { 859f1c579b1SScott Long pdma_sg->length=tmplength|IS_SG64_ADDR; 860ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 861ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 862f1c579b1SScott Long break; 863f1c579b1SScott Long } 864f1c579b1SScott Long } 865f1c579b1SScott Long arccdbsize += sg64s_size; 866f1c579b1SScott Long } 867f1c579b1SScott Long cdb_sgcount++; 868f1c579b1SScott Long } 869ad6d6297SScott Long arcmsr_cdb->sgcount=(u_int8_t)cdb_sgcount; 870ad6d6297SScott Long arcmsr_cdb->DataLength=pcsio->dxfer_len; 871ad6d6297SScott Long if( arccdbsize > 256) { 872ad6d6297SScott Long arcmsr_cdb->Flags|=ARCMSR_CDB_FLAG_SGL_BSIZE; 873f1c579b1SScott Long } 874f1c579b1SScott Long } 875f1c579b1SScott Long return; 876f1c579b1SScott Long } 877f1c579b1SScott Long /* 878f1c579b1SScott Long ************************************************************************** 879f1c579b1SScott Long ************************************************************************** 880f1c579b1SScott Long */ 881ad6d6297SScott Long static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandControlBlock *srb) 882f1c579b1SScott Long { 883ad6d6297SScott Long u_int32_t cdb_shifted_phyaddr=(u_int32_t) srb->cdb_shifted_phyaddr; 884ad6d6297SScott Long struct ARCMSR_CDB * arcmsr_cdb=(struct ARCMSR_CDB *)&srb->arcmsr_cdb; 885f1c579b1SScott Long 886ad6d6297SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 887ad6d6297SScott Long (srb->srb_flags & SRB_FLAG_WRITE) ? BUS_DMASYNC_POSTWRITE:BUS_DMASYNC_POSTREAD); 888ad6d6297SScott Long atomic_add_int(&acb->srboutstandingcount, 1); 889ad6d6297SScott Long srb->startdone=ARCMSR_SRB_START; 89044f05562SScott Long switch (acb->adapter_type) { 89144f05562SScott Long case ACB_ADAPTER_TYPE_A: { 892ad6d6297SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 89344f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 89444f05562SScott Long 0, inbound_queueport, 89544f05562SScott Long cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE); 896ad6d6297SScott Long } else { 89744f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 89844f05562SScott Long 0, inbound_queueport, cdb_shifted_phyaddr); 89944f05562SScott Long } 90044f05562SScott Long } 90144f05562SScott Long break; 90244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 90344f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 90444f05562SScott Long int ending_index, index; 90544f05562SScott Long 90644f05562SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 90744f05562SScott Long index=phbbmu->postq_index; 90844f05562SScott Long ending_index=((index+1)%ARCMSR_MAX_HBB_POSTQUEUE); 90944f05562SScott Long phbbmu->post_qbuffer[ending_index]=0; 91044f05562SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 91144f05562SScott Long phbbmu->post_qbuffer[index]= 91244f05562SScott Long cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE; 91344f05562SScott Long } else { 91444f05562SScott Long phbbmu->post_qbuffer[index]= 91544f05562SScott Long cdb_shifted_phyaddr; 91644f05562SScott Long } 91744f05562SScott Long index++; 91844f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 91944f05562SScott Long phbbmu->postq_index=index; 92044f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 92144f05562SScott Long 0, drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED); 92244f05562SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 92344f05562SScott Long } 92444f05562SScott Long break; 925f1c579b1SScott Long } 926f1c579b1SScott Long return; 927f1c579b1SScott Long } 928f1c579b1SScott Long /* 92944f05562SScott Long ************************************************************************ 93044f05562SScott Long ************************************************************************ 93144f05562SScott Long */ 93244f05562SScott Long static struct QBUFFER * arcmsr_get_iop_rqbuffer( struct AdapterControlBlock *acb) 93344f05562SScott Long { 93444f05562SScott Long struct QBUFFER *qbuffer=NULL; 93544f05562SScott Long 93644f05562SScott Long switch (acb->adapter_type) { 93744f05562SScott Long case ACB_ADAPTER_TYPE_A: { 93844f05562SScott Long struct HBA_MessageUnit *phbamu=(struct HBA_MessageUnit *)acb->pmu; 93944f05562SScott Long 94044f05562SScott Long qbuffer=(struct QBUFFER *)&phbamu->message_rbuffer; 94144f05562SScott Long } 94244f05562SScott Long break; 94344f05562SScott Long case ACB_ADAPTER_TYPE_B: { 94444f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 94544f05562SScott Long 94644f05562SScott Long qbuffer=(struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_rbuffer; 94744f05562SScott Long } 94844f05562SScott Long break; 94944f05562SScott Long } 95044f05562SScott Long return(qbuffer); 95144f05562SScott Long } 95244f05562SScott Long /* 95344f05562SScott Long ************************************************************************ 95444f05562SScott Long ************************************************************************ 95544f05562SScott Long */ 95644f05562SScott Long static struct QBUFFER * arcmsr_get_iop_wqbuffer( struct AdapterControlBlock *acb) 95744f05562SScott Long { 95844f05562SScott Long struct QBUFFER *qbuffer=NULL; 95944f05562SScott Long 96044f05562SScott Long switch (acb->adapter_type) { 96144f05562SScott Long case ACB_ADAPTER_TYPE_A: { 96244f05562SScott Long struct HBA_MessageUnit *phbamu=(struct HBA_MessageUnit *)acb->pmu; 96344f05562SScott Long 96444f05562SScott Long qbuffer=(struct QBUFFER *)&phbamu->message_wbuffer; 96544f05562SScott Long } 96644f05562SScott Long break; 96744f05562SScott Long case ACB_ADAPTER_TYPE_B: { 96844f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 96944f05562SScott Long 97044f05562SScott Long qbuffer=(struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_wbuffer; 97144f05562SScott Long } 97244f05562SScott Long break; 97344f05562SScott Long } 97444f05562SScott Long return(qbuffer); 97544f05562SScott Long } 97644f05562SScott Long /* 97744f05562SScott Long ************************************************************************** 97844f05562SScott Long ************************************************************************** 97944f05562SScott Long */ 98044f05562SScott Long static void arcmsr_iop_message_read(struct AdapterControlBlock *acb) 98144f05562SScott Long { 98244f05562SScott Long switch (acb->adapter_type) { 98344f05562SScott Long case ACB_ADAPTER_TYPE_A: { 98444f05562SScott Long /* let IOP know data has been read */ 98544f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 98644f05562SScott Long 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 98744f05562SScott Long } 98844f05562SScott Long break; 98944f05562SScott Long case ACB_ADAPTER_TYPE_B: { 99044f05562SScott Long /* let IOP know data has been read */ 99144f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 99244f05562SScott Long 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 99344f05562SScott Long } 99444f05562SScott Long break; 99544f05562SScott Long } 99644f05562SScott Long return; 99744f05562SScott Long } 99844f05562SScott Long /* 99944f05562SScott Long ************************************************************************** 100044f05562SScott Long ************************************************************************** 100144f05562SScott Long */ 100244f05562SScott Long static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) 100344f05562SScott Long { 100444f05562SScott Long switch (acb->adapter_type) { 100544f05562SScott Long case ACB_ADAPTER_TYPE_A: { 100644f05562SScott Long /* 100744f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 100844f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 100944f05562SScott Long */ 101044f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 101144f05562SScott Long 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK); 101244f05562SScott Long } 101344f05562SScott Long break; 101444f05562SScott Long case ACB_ADAPTER_TYPE_B: { 101544f05562SScott Long /* 101644f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 101744f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 101844f05562SScott Long */ 101944f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 102044f05562SScott Long 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_WRITE_OK); 102144f05562SScott Long } 102244f05562SScott Long break; 102344f05562SScott Long } 102444f05562SScott Long } 102544f05562SScott Long /* 1026f1c579b1SScott Long ********************************************************************** 1027f1c579b1SScott Long ********************************************************************** 1028f1c579b1SScott Long */ 102944f05562SScott Long static void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb) 1030f1c579b1SScott Long { 1031ad6d6297SScott Long u_int8_t *pQbuffer; 103244f05562SScott Long struct QBUFFER *pwbuffer; 103344f05562SScott Long u_int8_t * iop_data; 103444f05562SScott Long int32_t allxfer_len=0; 1035f1c579b1SScott Long 103644f05562SScott Long pwbuffer=arcmsr_get_iop_wqbuffer(acb); 103744f05562SScott Long iop_data=(u_int8_t *)pwbuffer->data; 103844f05562SScott Long if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) { 103944f05562SScott Long acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 104044f05562SScott Long while((acb->wqbuf_firstindex!=acb->wqbuf_lastindex) 104144f05562SScott Long && (allxfer_len<124)) { 1042ad6d6297SScott Long pQbuffer=&acb->wqbuffer[acb->wqbuf_firstindex]; 1043f1c579b1SScott Long memcpy(iop_data, pQbuffer, 1); 1044ad6d6297SScott Long acb->wqbuf_firstindex++; 104544f05562SScott Long acb->wqbuf_firstindex %=ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */ 1046f1c579b1SScott Long iop_data++; 1047f1c579b1SScott Long allxfer_len++; 1048f1c579b1SScott Long } 1049f1c579b1SScott Long pwbuffer->data_len=allxfer_len; 1050f1c579b1SScott Long /* 1051f1c579b1SScott Long ** push inbound doorbell and wait reply at hwinterrupt routine for next Qbuffer post 1052f1c579b1SScott Long */ 105344f05562SScott Long arcmsr_iop_message_wrote(acb); 1054ad6d6297SScott Long } 1055f1c579b1SScott Long return; 1056f1c579b1SScott Long } 1057f1c579b1SScott Long /* 1058f1c579b1SScott Long ************************************************************************ 1059f1c579b1SScott Long ************************************************************************ 1060f1c579b1SScott Long */ 106144f05562SScott Long static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb) 1062f1c579b1SScott Long { 1063ad6d6297SScott Long acb->acb_flags &=~ACB_F_MSG_START_BGRB; 106444f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 106544f05562SScott Long 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 106644f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 1067ad6d6297SScott Long printf("arcmsr%d: wait 'stop adapter rebulid' timeout \n" 1068ad6d6297SScott Long , acb->pci_unit); 1069ad6d6297SScott Long } 1070f1c579b1SScott Long return; 1071f1c579b1SScott Long } 1072f1c579b1SScott Long /* 1073f1c579b1SScott Long ************************************************************************ 1074f1c579b1SScott Long ************************************************************************ 1075f1c579b1SScott Long */ 107644f05562SScott Long static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb) 107744f05562SScott Long { 107844f05562SScott Long acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 107944f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 108044f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_STOP_BGRB); 108144f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 108244f05562SScott Long printf( "arcmsr%d: wait 'stop adapter rebulid' timeout \n" 108344f05562SScott Long , acb->pci_unit); 108444f05562SScott Long } 108544f05562SScott Long return; 108644f05562SScott Long } 108744f05562SScott Long /* 108844f05562SScott Long ************************************************************************ 108944f05562SScott Long ************************************************************************ 109044f05562SScott Long */ 109144f05562SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) 109244f05562SScott Long { 109344f05562SScott Long switch (acb->adapter_type) { 109444f05562SScott Long case ACB_ADAPTER_TYPE_A: { 109544f05562SScott Long arcmsr_stop_hba_bgrb(acb); 109644f05562SScott Long } 109744f05562SScott Long break; 109844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 109944f05562SScott Long arcmsr_stop_hbb_bgrb(acb); 110044f05562SScott Long } 110144f05562SScott Long break; 110244f05562SScott Long } 110344f05562SScott Long return; 110444f05562SScott Long } 110544f05562SScott Long /* 110644f05562SScott Long ************************************************************************ 110744f05562SScott Long ************************************************************************ 110844f05562SScott Long */ 1109ad6d6297SScott Long static void arcmsr_poll(struct cam_sim * psim) 1110f1c579b1SScott Long { 111144f05562SScott Long arcmsr_interrupt((struct AdapterControlBlock *)cam_sim_softc(psim)); 1112f1c579b1SScott Long return; 1113f1c579b1SScott Long } 1114f1c579b1SScott Long /* 1115f1c579b1SScott Long ********************************************************************** 1116f1c579b1SScott Long ********************************************************************** 1117f1c579b1SScott Long */ 11185878cbecSScott Long static void arcmsr_intr_handler(void *arg) 11195878cbecSScott Long { 11205878cbecSScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)arg; 11215878cbecSScott Long 11225878cbecSScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 11235878cbecSScott Long arcmsr_interrupt(acb); 11245878cbecSScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 11255878cbecSScott Long } 11265878cbecSScott Long /* 112744f05562SScott Long ************************************************************************** 112844f05562SScott Long ************************************************************************** 11295878cbecSScott Long */ 113044f05562SScott Long static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) 1131f1c579b1SScott Long { 113244f05562SScott Long struct QBUFFER *prbuffer; 1133ad6d6297SScott Long u_int8_t *pQbuffer; 113444f05562SScott Long u_int8_t *iop_data; 113544f05562SScott Long int my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; 1136ad6d6297SScott Long 1137f1c579b1SScott Long /*check this iop data if overflow my rqbuffer*/ 1138ad6d6297SScott Long rqbuf_lastindex=acb->rqbuf_lastindex; 1139ad6d6297SScott Long rqbuf_firstindex=acb->rqbuf_firstindex; 114044f05562SScott Long prbuffer=arcmsr_get_iop_rqbuffer(acb); 114144f05562SScott Long iop_data=(u_int8_t *)prbuffer->data; 1142f1c579b1SScott Long iop_len=prbuffer->data_len; 1143f1c579b1SScott Long my_empty_len=(rqbuf_firstindex-rqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1); 1144ad6d6297SScott Long if(my_empty_len>=iop_len) { 1145ad6d6297SScott Long while(iop_len > 0) { 114644f05562SScott Long pQbuffer=&acb->rqbuffer[rqbuf_lastindex]; 1147f1c579b1SScott Long memcpy(pQbuffer, iop_data, 1); 114844f05562SScott Long rqbuf_lastindex++; 114944f05562SScott Long rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;/*if last index number set it to 0 */ 1150f1c579b1SScott Long iop_data++; 1151f1c579b1SScott Long iop_len--; 1152f1c579b1SScott Long } 115344f05562SScott Long acb->rqbuf_lastindex=rqbuf_lastindex; 115444f05562SScott Long arcmsr_iop_message_read(acb); 115544f05562SScott Long /*signature, let IOP know data has been read */ 1156ad6d6297SScott Long } else { 1157ad6d6297SScott Long acb->acb_flags|=ACB_F_IOPDATA_OVERFLOW; 1158f1c579b1SScott Long } 115944f05562SScott Long return; 1160f1c579b1SScott Long } 1161f1c579b1SScott Long /* 116244f05562SScott Long ************************************************************************** 116344f05562SScott Long ************************************************************************** 116444f05562SScott Long */ 116544f05562SScott Long static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) 116644f05562SScott Long { 116744f05562SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READ; 116844f05562SScott Long /* 116944f05562SScott Long ***************************************************************** 117044f05562SScott Long ** check if there are any mail packages from user space program 117144f05562SScott Long ** in my post bag, now is the time to send them into Areca's firmware 117244f05562SScott Long ***************************************************************** 1173f1c579b1SScott Long */ 1174ad6d6297SScott Long if(acb->wqbuf_firstindex!=acb->wqbuf_lastindex) { 1175ad6d6297SScott Long u_int8_t *pQbuffer; 117644f05562SScott Long struct QBUFFER *pwbuffer; 117744f05562SScott Long u_int8_t *iop_data; 117844f05562SScott Long int allxfer_len=0; 1179f1c579b1SScott Long 118044f05562SScott Long acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 118144f05562SScott Long pwbuffer=arcmsr_get_iop_wqbuffer(acb); 118244f05562SScott Long iop_data=(u_int8_t *)pwbuffer->data; 118344f05562SScott Long while((acb->wqbuf_firstindex!=acb->wqbuf_lastindex) 118444f05562SScott Long && (allxfer_len<124)) { 1185ad6d6297SScott Long pQbuffer=&acb->wqbuffer[acb->wqbuf_firstindex]; 1186f1c579b1SScott Long memcpy(iop_data, pQbuffer, 1); 1187ad6d6297SScott Long acb->wqbuf_firstindex++; 118844f05562SScott Long acb->wqbuf_firstindex %=ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */ 1189f1c579b1SScott Long iop_data++; 1190f1c579b1SScott Long allxfer_len++; 1191f1c579b1SScott Long } 1192f1c579b1SScott Long pwbuffer->data_len=allxfer_len; 1193f1c579b1SScott Long /* 1194ad6d6297SScott Long ** push inbound doorbell tell iop driver data write ok 1195ad6d6297SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 1196f1c579b1SScott Long */ 119744f05562SScott Long arcmsr_iop_message_wrote(acb); 1198f1c579b1SScott Long } 1199ad6d6297SScott Long if(acb->wqbuf_firstindex==acb->wqbuf_lastindex) { 1200ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; 1201f1c579b1SScott Long } 120244f05562SScott Long return; 1203f1c579b1SScott Long } 120444f05562SScott Long /* 120544f05562SScott Long ************************************************************************** 120644f05562SScott Long ************************************************************************** 120744f05562SScott Long */ 120844f05562SScott Long static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) 120944f05562SScott Long { 121044f05562SScott Long u_int32_t outbound_doorbell; 121144f05562SScott Long 121244f05562SScott Long /* 121344f05562SScott Long ******************************************************************* 121444f05562SScott Long ** Maybe here we need to check wrqbuffer_lock is lock or not 121544f05562SScott Long ** DOORBELL: din! don! 121644f05562SScott Long ** check if there are any mail need to pack from firmware 121744f05562SScott Long ******************************************************************* 121844f05562SScott Long */ 121944f05562SScott Long outbound_doorbell=CHIP_REG_READ32(HBA_MessageUnit, 122044f05562SScott Long 0, outbound_doorbell); 122144f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 122244f05562SScott Long 0, outbound_doorbell, outbound_doorbell); /* clear doorbell interrupt */ 122344f05562SScott Long if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { 122444f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 1225ad6d6297SScott Long } 122644f05562SScott Long if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { 122744f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 122844f05562SScott Long } 122944f05562SScott Long return; 123044f05562SScott Long } 123144f05562SScott Long /* 123244f05562SScott Long ************************************************************************** 123344f05562SScott Long ************************************************************************** 123444f05562SScott Long */ 123544f05562SScott Long static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb) 123644f05562SScott Long { 123744f05562SScott Long u_int32_t flag_srb; 123844f05562SScott Long 1239f1c579b1SScott Long /* 1240f1c579b1SScott Long ***************************************************************************** 1241f1c579b1SScott Long ** areca cdb command done 1242f1c579b1SScott Long ***************************************************************************** 1243f1c579b1SScott Long */ 124444f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 124544f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 124644f05562SScott Long while((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 124744f05562SScott Long 0, outbound_queueport)) != 0xFFFFFFFF) { 1248f1c579b1SScott Long /* check if command done with no error*/ 124944f05562SScott Long arcmsr_drain_donequeue(acb, flag_srb); 125044f05562SScott Long } /*drain reply FIFO*/ 125144f05562SScott Long return; 1252f1c579b1SScott Long } 125344f05562SScott Long /* 125444f05562SScott Long ************************************************************************** 125544f05562SScott Long ************************************************************************** 125644f05562SScott Long */ 125744f05562SScott Long static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) 125844f05562SScott Long { 125944f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 126044f05562SScott Long u_int32_t flag_srb; 126144f05562SScott Long int index; 126244f05562SScott Long 126344f05562SScott Long /* 126444f05562SScott Long ***************************************************************************** 126544f05562SScott Long ** areca cdb command done 126644f05562SScott Long ***************************************************************************** 126744f05562SScott Long */ 126844f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 126944f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 127044f05562SScott Long index=phbbmu->doneq_index; 127144f05562SScott Long while((flag_srb=phbbmu->done_qbuffer[index]) != 0) { 127244f05562SScott Long phbbmu->done_qbuffer[index]=0; 127344f05562SScott Long index++; 127444f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 127544f05562SScott Long phbbmu->doneq_index=index; 127644f05562SScott Long /* check if command done with no error*/ 127744f05562SScott Long arcmsr_drain_donequeue(acb, flag_srb); 127844f05562SScott Long } /*drain reply FIFO*/ 127944f05562SScott Long return; 1280f1c579b1SScott Long } 128144f05562SScott Long /* 128244f05562SScott Long ********************************************************************** 128344f05562SScott Long ********************************************************************** 128444f05562SScott Long */ 128544f05562SScott Long static void arcmsr_handle_hba_isr( struct AdapterControlBlock *acb) 128644f05562SScott Long { 128744f05562SScott Long u_int32_t outbound_intstatus; 128844f05562SScott Long /* 128944f05562SScott Long ********************************************* 129044f05562SScott Long ** check outbound intstatus 129144f05562SScott Long ********************************************* 129244f05562SScott Long */ 129344f05562SScott Long outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 129444f05562SScott Long 0, outbound_intstatus) & acb->outbound_int_enable; 129544f05562SScott Long if(!outbound_intstatus) { 129644f05562SScott Long /*it must be share irq*/ 129744f05562SScott Long return; 1298f1c579b1SScott Long } 129944f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 130044f05562SScott Long 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/ 130144f05562SScott Long /* MU doorbell interrupts*/ 130244f05562SScott Long if(outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) { 130344f05562SScott Long arcmsr_hba_doorbell_isr(acb); 1304f1c579b1SScott Long } 130544f05562SScott Long /* MU post queue interrupts*/ 130644f05562SScott Long if(outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { 130744f05562SScott Long arcmsr_hba_postqueue_isr(acb); 130844f05562SScott Long } 130944f05562SScott Long return; 131044f05562SScott Long } 131144f05562SScott Long /* 131244f05562SScott Long ********************************************************************** 131344f05562SScott Long ********************************************************************** 131444f05562SScott Long */ 131544f05562SScott Long static void arcmsr_handle_hbb_isr( struct AdapterControlBlock *acb) 131644f05562SScott Long { 131744f05562SScott Long u_int32_t outbound_doorbell; 131844f05562SScott Long /* 131944f05562SScott Long ********************************************* 132044f05562SScott Long ** check outbound intstatus 132144f05562SScott Long ********************************************* 132244f05562SScott Long */ 132344f05562SScott Long outbound_doorbell=CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell) & acb->outbound_int_enable; 132444f05562SScott Long if(!outbound_doorbell) { 132544f05562SScott Long /*it must be share irq*/ 132644f05562SScott Long return; 132744f05562SScott Long } 132844f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 0, iop2drv_doorbell, ~outbound_doorbell); /* clear doorbell interrupt */ 132944f05562SScott Long CHIP_REG_READ32(HBB_DOORBELL, 0, iop2drv_doorbell); 133044f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 133144f05562SScott Long /* MU ioctl transfer doorbell interrupts*/ 133244f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { 133344f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 133444f05562SScott Long } 133544f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) { 133644f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 133744f05562SScott Long } 133844f05562SScott Long /* MU post queue interrupts*/ 133944f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) { 134044f05562SScott Long arcmsr_hbb_postqueue_isr(acb); 134144f05562SScott Long } 134244f05562SScott Long return; 134344f05562SScott Long } 134444f05562SScott Long /* 134544f05562SScott Long ****************************************************************************** 134644f05562SScott Long ****************************************************************************** 134744f05562SScott Long */ 134844f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb) 134944f05562SScott Long { 135044f05562SScott Long switch (acb->adapter_type) { 135144f05562SScott Long case ACB_ADAPTER_TYPE_A: 135244f05562SScott Long arcmsr_handle_hba_isr(acb); 1353f1c579b1SScott Long break; 135444f05562SScott Long case ACB_ADAPTER_TYPE_B: 135544f05562SScott Long arcmsr_handle_hbb_isr(acb); 1356f1c579b1SScott Long break; 1357f1c579b1SScott Long default: 135844f05562SScott Long printf("arcmsr%d: interrupt service," 135944f05562SScott Long " unknow adapter type =%d\n", acb->pci_unit, acb->adapter_type); 1360f1c579b1SScott Long break; 1361f1c579b1SScott Long } 1362f1c579b1SScott Long return; 1363f1c579b1SScott Long } 1364f1c579b1SScott Long /* 1365ad6d6297SScott Long ******************************************************************************* 1366ad6d6297SScott Long ** 1367ad6d6297SScott Long ******************************************************************************* 1368ad6d6297SScott Long */ 1369ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb) 1370ad6d6297SScott Long { 1371ad6d6297SScott Long if(acb!=NULL) { 1372ad6d6297SScott Long /* stop adapter background rebuild */ 1373ad6d6297SScott Long if(acb->acb_flags & ACB_F_MSG_START_BGRB) { 1374ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 1375ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 1376ad6d6297SScott Long } 1377ad6d6297SScott Long } 1378ad6d6297SScott Long } 1379ad6d6297SScott Long /* 1380f1c579b1SScott Long *********************************************************************** 1381f1c579b1SScott Long ** 1382f1c579b1SScott Long ************************************************************************ 1383f1c579b1SScott Long */ 1384ad6d6297SScott Long u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg) 1385f1c579b1SScott Long { 1386ad6d6297SScott Long struct CMD_MESSAGE_FIELD * pcmdmessagefld; 1387ad6d6297SScott Long u_int32_t retvalue=EINVAL; 1388f1c579b1SScott Long 1389ad6d6297SScott Long pcmdmessagefld=(struct CMD_MESSAGE_FIELD *) arg; 1390ad6d6297SScott Long if(memcmp(pcmdmessagefld->cmdmessage.Signature, "ARCMSR", 6)!=0) { 1391ad6d6297SScott Long return retvalue; 1392f1c579b1SScott Long } 1393ad6d6297SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 1394ad6d6297SScott Long switch(ioctl_cmd) { 1395ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 1396ad6d6297SScott Long u_int8_t * pQbuffer; 1397ad6d6297SScott Long u_int8_t * ptmpQbuffer=pcmdmessagefld->messagedatabuffer; 1398ad6d6297SScott Long u_int32_t allxfer_len=0; 1399f1c579b1SScott Long 140044f05562SScott Long while((acb->rqbuf_firstindex!=acb->rqbuf_lastindex) 140144f05562SScott Long && (allxfer_len<1031)) { 1402f1c579b1SScott Long /*copy READ QBUFFER to srb*/ 1403ad6d6297SScott Long pQbuffer= &acb->rqbuffer[acb->rqbuf_firstindex]; 1404f1c579b1SScott Long memcpy(ptmpQbuffer, pQbuffer, 1); 1405ad6d6297SScott Long acb->rqbuf_firstindex++; 1406ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 1407ad6d6297SScott Long /*if last index number set it to 0 */ 1408f1c579b1SScott Long ptmpQbuffer++; 1409f1c579b1SScott Long allxfer_len++; 1410f1c579b1SScott Long } 1411ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 141244f05562SScott Long struct QBUFFER * prbuffer; 141344f05562SScott Long u_int8_t * iop_data; 1414ad6d6297SScott Long u_int32_t iop_len; 1415f1c579b1SScott Long 1416ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 141744f05562SScott Long prbuffer=arcmsr_get_iop_rqbuffer(acb); 141844f05562SScott Long iop_data=(u_int8_t *)prbuffer->data; 1419ad6d6297SScott Long iop_len=(u_int32_t)prbuffer->data_len; 1420f1c579b1SScott Long /*this iop data does no chance to make me overflow again here, so just do it*/ 1421ad6d6297SScott Long while(iop_len>0) { 1422ad6d6297SScott Long pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex]; 1423f1c579b1SScott Long memcpy(pQbuffer, iop_data, 1); 1424ad6d6297SScott Long acb->rqbuf_lastindex++; 1425ad6d6297SScott Long acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 1426ad6d6297SScott Long /*if last index number set it to 0 */ 1427f1c579b1SScott Long iop_data++; 1428f1c579b1SScott Long iop_len--; 1429f1c579b1SScott Long } 143044f05562SScott Long arcmsr_iop_message_read(acb); 143144f05562SScott Long /*signature, let IOP know data has been readed */ 1432f1c579b1SScott Long } 1433ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length=allxfer_len; 1434ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1435ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1436f1c579b1SScott Long } 1437f1c579b1SScott Long break; 1438ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 1439ad6d6297SScott Long u_int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 1440ad6d6297SScott Long u_int8_t * pQbuffer; 1441ad6d6297SScott Long u_int8_t * ptmpuserbuffer=pcmdmessagefld->messagedatabuffer; 1442f1c579b1SScott Long 1443ad6d6297SScott Long user_len=pcmdmessagefld->cmdmessage.Length; 1444f1c579b1SScott Long /*check if data xfer length of this request will overflow my array qbuffer */ 1445ad6d6297SScott Long wqbuf_lastindex=acb->wqbuf_lastindex; 1446ad6d6297SScott Long wqbuf_firstindex=acb->wqbuf_firstindex; 1447ad6d6297SScott Long if(wqbuf_lastindex!=wqbuf_firstindex) { 144844f05562SScott Long arcmsr_post_ioctldata2iop(acb); 1449ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; 1450ad6d6297SScott Long } else { 1451f1c579b1SScott Long my_empty_len=(wqbuf_firstindex-wqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1); 1452ad6d6297SScott Long if(my_empty_len>=user_len) { 1453ad6d6297SScott Long while(user_len>0) { 1454f1c579b1SScott Long /*copy srb data to wqbuffer*/ 1455ad6d6297SScott Long pQbuffer= &acb->wqbuffer[acb->wqbuf_lastindex]; 1456f1c579b1SScott Long memcpy(pQbuffer, ptmpuserbuffer, 1); 1457ad6d6297SScott Long acb->wqbuf_lastindex++; 1458ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 1459ad6d6297SScott Long /*if last index number set it to 0 */ 1460f1c579b1SScott Long ptmpuserbuffer++; 1461f1c579b1SScott Long user_len--; 1462f1c579b1SScott Long } 1463f1c579b1SScott Long /*post fist Qbuffer*/ 1464ad6d6297SScott Long if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 1465ad6d6297SScott Long acb->acb_flags &=~ACB_F_MESSAGE_WQBUFFER_CLEARED; 146644f05562SScott Long arcmsr_post_ioctldata2iop(acb); 1467f1c579b1SScott Long } 1468ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1469ad6d6297SScott Long } else { 1470ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; 1471f1c579b1SScott Long } 1472f1c579b1SScott Long } 1473ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1474f1c579b1SScott Long } 1475f1c579b1SScott Long break; 1476ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 1477ad6d6297SScott Long u_int8_t * pQbuffer=acb->rqbuffer; 1478ad6d6297SScott Long 1479ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1480ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 148144f05562SScott Long arcmsr_iop_message_read(acb); 148244f05562SScott Long /*signature, let IOP know data has been readed */ 1483f1c579b1SScott Long } 1484ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 1485ad6d6297SScott Long acb->rqbuf_firstindex=0; 1486ad6d6297SScott Long acb->rqbuf_lastindex=0; 1487f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 1488ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1489ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1490f1c579b1SScott Long } 1491f1c579b1SScott Long break; 1492ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: 1493f1c579b1SScott Long { 1494ad6d6297SScott Long u_int8_t * pQbuffer=acb->wqbuffer; 1495f1c579b1SScott Long 1496ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1497ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 149844f05562SScott Long arcmsr_iop_message_read(acb); 149944f05562SScott Long /*signature, let IOP know data has been readed */ 1500f1c579b1SScott Long } 150144f05562SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ); 1502ad6d6297SScott Long acb->wqbuf_firstindex=0; 1503ad6d6297SScott Long acb->wqbuf_lastindex=0; 1504f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 1505ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1506ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1507f1c579b1SScott Long } 1508f1c579b1SScott Long break; 1509ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 1510ad6d6297SScott Long u_int8_t * pQbuffer; 1511f1c579b1SScott Long 1512ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1513ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 151444f05562SScott Long arcmsr_iop_message_read(acb); 151544f05562SScott Long /*signature, let IOP know data has been readed */ 1516f1c579b1SScott Long } 1517ad6d6297SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED 1518ad6d6297SScott Long |ACB_F_MESSAGE_RQBUFFER_CLEARED 151944f05562SScott Long |ACB_F_MESSAGE_WQBUFFER_READ); 1520ad6d6297SScott Long acb->rqbuf_firstindex=0; 1521ad6d6297SScott Long acb->rqbuf_lastindex=0; 1522ad6d6297SScott Long acb->wqbuf_firstindex=0; 1523ad6d6297SScott Long acb->wqbuf_lastindex=0; 1524ad6d6297SScott Long pQbuffer=acb->rqbuffer; 1525ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 1526ad6d6297SScott Long pQbuffer=acb->wqbuffer; 1527ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 1528ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1529ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1530f1c579b1SScott Long } 1531f1c579b1SScott Long break; 1532ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 1533ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_3F; 1534ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1535f1c579b1SScott Long } 1536f1c579b1SScott Long break; 1537ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 1538ad6d6297SScott Long u_int8_t * hello_string="Hello! I am ARCMSR"; 1539ad6d6297SScott Long u_int8_t * puserbuffer=(u_int8_t *)pcmdmessagefld->messagedatabuffer; 1540f1c579b1SScott Long 1541ad6d6297SScott Long if(memcpy(puserbuffer, hello_string, (int16_t)strlen(hello_string))) { 1542ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_ERROR; 1543ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1544f1c579b1SScott Long return ENOIOCTL; 1545f1c579b1SScott Long } 1546ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode=ARCMSR_MESSAGE_RETURNCODE_OK; 1547ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1548ad6d6297SScott Long } 1549ad6d6297SScott Long break; 1550ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: { 1551ad6d6297SScott Long arcmsr_iop_parking(acb); 1552ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1553ad6d6297SScott Long } 1554ad6d6297SScott Long break; 1555ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: { 1556ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 1557ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1558f1c579b1SScott Long } 1559f1c579b1SScott Long break; 1560f1c579b1SScott Long } 1561ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1562ad6d6297SScott Long return retvalue; 1563f1c579b1SScott Long } 1564f1c579b1SScott Long /* 1565f1c579b1SScott Long ************************************************************************** 1566f1c579b1SScott Long ************************************************************************** 1567f1c579b1SScott Long */ 1568ad6d6297SScott Long struct CommandControlBlock * arcmsr_get_freesrb(struct AdapterControlBlock *acb) 1569f1c579b1SScott Long { 1570ad6d6297SScott Long struct CommandControlBlock *srb=NULL; 1571ad6d6297SScott Long u_int32_t workingsrb_startindex, workingsrb_doneindex; 1572f1c579b1SScott Long 1573ad6d6297SScott Long workingsrb_doneindex=acb->workingsrb_doneindex; 1574ad6d6297SScott Long workingsrb_startindex=acb->workingsrb_startindex; 1575ad6d6297SScott Long srb=acb->srbworkingQ[workingsrb_startindex]; 1576ad6d6297SScott Long workingsrb_startindex++; 1577ad6d6297SScott Long workingsrb_startindex %= ARCMSR_MAX_FREESRB_NUM; 1578ad6d6297SScott Long if(workingsrb_doneindex!=workingsrb_startindex) { 1579ad6d6297SScott Long acb->workingsrb_startindex=workingsrb_startindex; 1580ad6d6297SScott Long } else { 1581ad6d6297SScott Long srb=NULL; 1582ad6d6297SScott Long } 1583ad6d6297SScott Long return(srb); 1584ad6d6297SScott Long } 1585ad6d6297SScott Long /* 1586ad6d6297SScott Long ************************************************************************** 1587ad6d6297SScott Long ************************************************************************** 1588ad6d6297SScott Long */ 1589ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb * pccb) 1590ad6d6297SScott Long { 1591ad6d6297SScott Long struct CMD_MESSAGE_FIELD * pcmdmessagefld; 1592ad6d6297SScott Long int retvalue = 0, transfer_len = 0; 1593ad6d6297SScott Long char *buffer; 159444f05562SScott Long u_int32_t controlcode = (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[5] << 24 | 159544f05562SScott Long (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[6] << 16 | 159644f05562SScott Long (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[7] << 8 | 159744f05562SScott Long (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[8]; 1598ad6d6297SScott Long /* 4 bytes: Areca io control code */ 1599ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) { 1600ad6d6297SScott Long buffer = pccb->csio.data_ptr; 1601ad6d6297SScott Long transfer_len = pccb->csio.dxfer_len; 1602ad6d6297SScott Long } else { 1603ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 1604ad6d6297SScott Long goto message_out; 1605ad6d6297SScott Long } 1606ad6d6297SScott Long if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) { 1607ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 1608ad6d6297SScott Long goto message_out; 1609ad6d6297SScott Long } 1610ad6d6297SScott Long pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer; 1611ad6d6297SScott Long switch(controlcode) { 1612ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 1613ad6d6297SScott Long u_int8_t *pQbuffer; 1614ad6d6297SScott Long u_int8_t *ptmpQbuffer=pcmdmessagefld->messagedatabuffer; 1615ad6d6297SScott Long int32_t allxfer_len = 0; 1616f1c579b1SScott Long 1617ad6d6297SScott Long while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) 1618ad6d6297SScott Long && (allxfer_len < 1031)) { 1619ad6d6297SScott Long pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; 1620ad6d6297SScott Long memcpy(ptmpQbuffer, pQbuffer, 1); 1621ad6d6297SScott Long acb->rqbuf_firstindex++; 1622ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 1623ad6d6297SScott Long ptmpQbuffer++; 1624ad6d6297SScott Long allxfer_len++; 1625f1c579b1SScott Long } 1626ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 162744f05562SScott Long struct QBUFFER *prbuffer; 162844f05562SScott Long u_int8_t *iop_data; 1629ad6d6297SScott Long int32_t iop_len; 1630ad6d6297SScott Long 1631ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 163244f05562SScott Long prbuffer=arcmsr_get_iop_rqbuffer(acb); 163344f05562SScott Long iop_data = (u_int8_t *)prbuffer->data; 1634ad6d6297SScott Long iop_len =(u_int32_t)prbuffer->data_len; 1635ad6d6297SScott Long while (iop_len > 0) { 1636ad6d6297SScott Long pQbuffer= &acb->rqbuffer[acb->rqbuf_lastindex]; 1637ad6d6297SScott Long memcpy(pQbuffer, iop_data, 1); 1638ad6d6297SScott Long acb->rqbuf_lastindex++; 1639ad6d6297SScott Long acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 1640ad6d6297SScott Long iop_data++; 1641ad6d6297SScott Long iop_len--; 1642f1c579b1SScott Long } 164344f05562SScott Long arcmsr_iop_message_read(acb); 1644ad6d6297SScott Long } 1645ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length = allxfer_len; 1646ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 1647ad6d6297SScott Long retvalue=ARCMSR_MESSAGE_SUCCESS; 1648ad6d6297SScott Long } 1649ad6d6297SScott Long break; 1650ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 1651ad6d6297SScott Long int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 1652ad6d6297SScott Long u_int8_t *pQbuffer; 1653ad6d6297SScott Long u_int8_t *ptmpuserbuffer=pcmdmessagefld->messagedatabuffer; 1654ad6d6297SScott Long 1655ad6d6297SScott Long user_len = pcmdmessagefld->cmdmessage.Length; 1656ad6d6297SScott Long wqbuf_lastindex = acb->wqbuf_lastindex; 1657ad6d6297SScott Long wqbuf_firstindex = acb->wqbuf_firstindex; 1658ad6d6297SScott Long if (wqbuf_lastindex != wqbuf_firstindex) { 165944f05562SScott Long arcmsr_post_ioctldata2iop(acb); 1660ad6d6297SScott Long /* has error report sensedata */ 1661ad6d6297SScott Long if(&pccb->csio.sense_data) { 1662ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 1663ad6d6297SScott Long /* Valid,ErrorCode */ 1664ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 1665ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 1666ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 1667ad6d6297SScott Long /* AdditionalSenseLength */ 1668ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 1669ad6d6297SScott Long /* AdditionalSenseCode */ 1670ad6d6297SScott Long } 1671ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 1672ad6d6297SScott Long } else { 1673ad6d6297SScott Long my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) 1674ad6d6297SScott Long &(ARCMSR_MAX_QBUFFER - 1); 1675ad6d6297SScott Long if (my_empty_len >= user_len) { 1676ad6d6297SScott Long while (user_len > 0) { 1677ad6d6297SScott Long pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; 1678ad6d6297SScott Long memcpy(pQbuffer, ptmpuserbuffer, 1); 1679ad6d6297SScott Long acb->wqbuf_lastindex++; 1680ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 1681ad6d6297SScott Long ptmpuserbuffer++; 1682ad6d6297SScott Long user_len--; 1683ad6d6297SScott Long } 1684ad6d6297SScott Long if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 1685ad6d6297SScott Long acb->acb_flags &= 1686ad6d6297SScott Long ~ACB_F_MESSAGE_WQBUFFER_CLEARED; 168744f05562SScott Long arcmsr_post_ioctldata2iop(acb); 1688ad6d6297SScott Long } 1689ad6d6297SScott Long } else { 1690ad6d6297SScott Long /* has error report sensedata */ 1691ad6d6297SScott Long if(&pccb->csio.sense_data) { 1692ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 1693ad6d6297SScott Long /* Valid,ErrorCode */ 1694ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 1695ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 1696ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 1697ad6d6297SScott Long /* AdditionalSenseLength */ 1698ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 1699ad6d6297SScott Long /* AdditionalSenseCode */ 1700ad6d6297SScott Long } 1701ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 1702ad6d6297SScott Long } 1703ad6d6297SScott Long } 1704ad6d6297SScott Long } 1705ad6d6297SScott Long break; 1706ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 1707ad6d6297SScott Long u_int8_t *pQbuffer = acb->rqbuffer; 1708ad6d6297SScott Long 1709ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1710ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 171144f05562SScott Long arcmsr_iop_message_read(acb); 1712ad6d6297SScott Long } 1713ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 1714ad6d6297SScott Long acb->rqbuf_firstindex = 0; 1715ad6d6297SScott Long acb->rqbuf_lastindex = 0; 1716ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 1717ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 1718ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 1719ad6d6297SScott Long } 1720ad6d6297SScott Long break; 1721ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { 1722ad6d6297SScott Long u_int8_t *pQbuffer = acb->wqbuffer; 1723ad6d6297SScott Long 1724ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1725ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 172644f05562SScott Long arcmsr_iop_message_read(acb); 1727ad6d6297SScott Long } 1728ad6d6297SScott Long acb->acb_flags |= 1729ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED | 173044f05562SScott Long ACB_F_MESSAGE_WQBUFFER_READ); 1731ad6d6297SScott Long acb->wqbuf_firstindex = 0; 1732ad6d6297SScott Long acb->wqbuf_lastindex = 0; 1733ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 1734ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 1735ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 1736ad6d6297SScott Long } 1737ad6d6297SScott Long break; 1738ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 1739ad6d6297SScott Long u_int8_t *pQbuffer; 1740ad6d6297SScott Long 1741ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 1742ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 174344f05562SScott Long arcmsr_iop_message_read(acb); 1744ad6d6297SScott Long } 1745ad6d6297SScott Long acb->acb_flags |= 1746ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED 1747ad6d6297SScott Long | ACB_F_MESSAGE_RQBUFFER_CLEARED 174844f05562SScott Long | ACB_F_MESSAGE_WQBUFFER_READ); 1749ad6d6297SScott Long acb->rqbuf_firstindex = 0; 1750ad6d6297SScott Long acb->rqbuf_lastindex = 0; 1751ad6d6297SScott Long acb->wqbuf_firstindex = 0; 1752ad6d6297SScott Long acb->wqbuf_lastindex = 0; 1753ad6d6297SScott Long pQbuffer = acb->rqbuffer; 1754ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 1755ad6d6297SScott Long pQbuffer = acb->wqbuffer; 1756ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 1757ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 1758ad6d6297SScott Long } 1759ad6d6297SScott Long break; 1760ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 1761ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; 1762ad6d6297SScott Long } 1763ad6d6297SScott Long break; 1764ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 1765ad6d6297SScott Long int8_t * hello_string = "Hello! I am ARCMSR"; 1766ad6d6297SScott Long 1767ad6d6297SScott Long memcpy(pcmdmessagefld->messagedatabuffer, hello_string 1768ad6d6297SScott Long , (int16_t)strlen(hello_string)); 1769ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 1770ad6d6297SScott Long } 1771ad6d6297SScott Long break; 1772ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: 1773ad6d6297SScott Long arcmsr_iop_parking(acb); 1774ad6d6297SScott Long break; 1775ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: 1776ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 1777ad6d6297SScott Long break; 1778ad6d6297SScott Long default: 1779ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 1780ad6d6297SScott Long } 1781ad6d6297SScott Long message_out: 1782ad6d6297SScott Long return retvalue; 1783f1c579b1SScott Long } 1784f1c579b1SScott Long /* 1785f1c579b1SScott Long ********************************************************************* 1786f1c579b1SScott Long ********************************************************************* 1787f1c579b1SScott Long */ 1788ad6d6297SScott Long static void arcmsr_executesrb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 1789f1c579b1SScott Long { 1790ad6d6297SScott Long struct CommandControlBlock *srb=(struct CommandControlBlock *)arg; 1791ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)srb->acb; 1792f1c579b1SScott Long union ccb * pccb; 1793ad6d6297SScott Long int target, lun; 1794f1c579b1SScott Long 1795ad6d6297SScott Long pccb=srb->pccb; 1796ad6d6297SScott Long target=pccb->ccb_h.target_id; 1797ad6d6297SScott Long lun=pccb->ccb_h.target_lun; 1798ad6d6297SScott Long if(error != 0) { 1799ad6d6297SScott Long if(error != EFBIG) { 180044f05562SScott Long printf("arcmsr%d: unexpected error %x" 180144f05562SScott Long " returned from 'bus_dmamap_load' \n" 1802ad6d6297SScott Long , acb->pci_unit, error); 1803f1c579b1SScott Long } 1804ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { 180515735becSScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 1806f1c579b1SScott Long } 1807ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 1808f1c579b1SScott Long return; 1809f1c579b1SScott Long } 1810ad6d6297SScott Long if(nseg > ARCMSR_MAX_SG_ENTRIES) { 1811ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 1812ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 1813ad6d6297SScott Long return; 1814f1c579b1SScott Long } 1815ad6d6297SScott Long if(acb->acb_flags & ACB_F_BUS_RESET) { 1816ad6d6297SScott Long printf("arcmsr%d: bus reset and return busy \n", acb->pci_unit); 1817ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_BUS_RESET; 1818ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 1819ad6d6297SScott Long return; 1820ad6d6297SScott Long } 1821ad6d6297SScott Long if(acb->devstate[target][lun]==ARECA_RAID_GONE) { 1822ad6d6297SScott Long u_int8_t block_cmd; 1823ad6d6297SScott Long 1824ad6d6297SScott Long block_cmd=pccb->csio.cdb_io.cdb_bytes[0] & 0x0f; 1825ad6d6297SScott Long if(block_cmd==0x08 || block_cmd==0x0a) { 1826ad6d6297SScott Long printf("arcmsr%d:block 'read/write' command" 1827ad6d6297SScott Long "with gone raid volume Cmd=%2x, TargetId=%d, Lun=%d \n" 1828ad6d6297SScott Long , acb->pci_unit, block_cmd, target, lun); 1829ad6d6297SScott Long pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 1830ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 1831ad6d6297SScott Long return; 1832ad6d6297SScott Long } 1833ad6d6297SScott Long } 1834ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { 1835ad6d6297SScott Long if(nseg != 0) { 1836ad6d6297SScott Long bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 1837ad6d6297SScott Long } 1838ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 1839f1c579b1SScott Long return; 1840f1c579b1SScott Long } 1841ad6d6297SScott Long if(acb->srboutstandingcount >= ARCMSR_MAX_OUTSTANDING_CMD) { 184215735becSScott Long xpt_freeze_simq(acb->psim, 1); 184315735becSScott Long pccb->ccb_h.status = CAM_REQUEUE_REQ; 1844dc3a205bSScott Long acb->acb_flags |= ACB_F_CAM_DEV_QFRZN; 1845ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 1846ad6d6297SScott Long return; 1847f1c579b1SScott Long } 184815735becSScott Long pccb->ccb_h.status |= CAM_SIM_QUEUED; 1849ad6d6297SScott Long arcmsr_build_srb(srb, dm_segs, nseg); 1850ad6d6297SScott Long arcmsr_post_srb(acb, srb); 1851f1c579b1SScott Long return; 1852f1c579b1SScott Long } 1853f1c579b1SScott Long /* 1854f1c579b1SScott Long ***************************************************************************************** 1855f1c579b1SScott Long ***************************************************************************************** 1856f1c579b1SScott Long */ 1857ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb * abortccb) 1858f1c579b1SScott Long { 1859ad6d6297SScott Long struct CommandControlBlock *srb; 1860ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *) abortccb->ccb_h.arcmsr_ccbacb_ptr; 186144f05562SScott Long u_int32_t intmask_org; 1862ad6d6297SScott Long int i=0; 1863f1c579b1SScott Long 1864ad6d6297SScott Long acb->num_aborts++; 1865f1c579b1SScott Long /* 1866ad6d6297SScott Long *************************************************************************** 1867f1c579b1SScott Long ** It is the upper layer do abort command this lock just prior to calling us. 1868f1c579b1SScott Long ** First determine if we currently own this command. 1869f1c579b1SScott Long ** Start by searching the device queue. If not found 1870f1c579b1SScott Long ** at all, and the system wanted us to just abort the 1871f1c579b1SScott Long ** command return success. 1872ad6d6297SScott Long *************************************************************************** 1873f1c579b1SScott Long */ 1874ad6d6297SScott Long if(acb->srboutstandingcount!=0) { 1875ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 1876ad6d6297SScott Long srb=acb->psrb_pool[i]; 1877ad6d6297SScott Long if(srb->startdone==ARCMSR_SRB_START) { 1878ad6d6297SScott Long if(srb->pccb==abortccb) { 1879ad6d6297SScott Long srb->startdone=ARCMSR_SRB_ABORTED; 1880ad6d6297SScott Long printf("arcmsr%d:scsi id=%d lun=%d abort srb '%p'" 1881ad6d6297SScott Long "outstanding command \n" 1882ad6d6297SScott Long , acb->pci_unit, abortccb->ccb_h.target_id 1883ad6d6297SScott Long , abortccb->ccb_h.target_lun, srb); 1884ad6d6297SScott Long goto abort_outstanding_cmd; 1885f1c579b1SScott Long } 1886f1c579b1SScott Long } 1887f1c579b1SScott Long } 1888f1c579b1SScott Long } 1889f1c579b1SScott Long return(FALSE); 1890ad6d6297SScott Long abort_outstanding_cmd: 1891ad6d6297SScott Long /* disable all outbound interrupt */ 189244f05562SScott Long intmask_org=arcmsr_disable_allintr(acb); 1893ad6d6297SScott Long arcmsr_polling_srbdone(acb, srb); 189444f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 189544f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 1896ad6d6297SScott Long return (TRUE); 1897f1c579b1SScott Long } 1898f1c579b1SScott Long /* 1899f1c579b1SScott Long **************************************************************************** 1900f1c579b1SScott Long **************************************************************************** 1901f1c579b1SScott Long */ 1902ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb) 1903f1c579b1SScott Long { 1904ad6d6297SScott Long int retry=0; 1905f1c579b1SScott Long 1906ad6d6297SScott Long acb->num_resets++; 1907ad6d6297SScott Long acb->acb_flags |=ACB_F_BUS_RESET; 1908ad6d6297SScott Long while(acb->srboutstandingcount!=0 && retry < 400) { 190944f05562SScott Long arcmsr_interrupt(acb); 1910ad6d6297SScott Long UDELAY(25000); 1911ad6d6297SScott Long retry++; 1912ad6d6297SScott Long } 1913ad6d6297SScott Long arcmsr_iop_reset(acb); 1914ad6d6297SScott Long acb->acb_flags &= ~ACB_F_BUS_RESET; 1915f1c579b1SScott Long return; 1916f1c579b1SScott Long } 1917f1c579b1SScott Long /* 1918ad6d6297SScott Long ************************************************************************** 1919ad6d6297SScott Long ************************************************************************** 1920ad6d6297SScott Long */ 1921ad6d6297SScott Long static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, 1922ad6d6297SScott Long union ccb * pccb) 1923ad6d6297SScott Long { 1924ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 1925ad6d6297SScott Long switch (pccb->csio.cdb_io.cdb_bytes[0]) { 1926ad6d6297SScott Long case INQUIRY: { 1927ad6d6297SScott Long unsigned char inqdata[36]; 1928ad6d6297SScott Long char *buffer=pccb->csio.data_ptr;; 1929ad6d6297SScott Long 1930ad6d6297SScott Long if (pccb->ccb_h.target_lun) { 1931ad6d6297SScott Long pccb->ccb_h.status |= CAM_SEL_TIMEOUT; 1932ad6d6297SScott Long xpt_done(pccb); 1933ad6d6297SScott Long return; 1934ad6d6297SScott Long } 1935ad6d6297SScott Long inqdata[0] = T_PROCESSOR; 1936ad6d6297SScott Long /* Periph Qualifier & Periph Dev Type */ 1937ad6d6297SScott Long inqdata[1] = 0; 1938ad6d6297SScott Long /* rem media bit & Dev Type Modifier */ 1939ad6d6297SScott Long inqdata[2] = 0; 1940ad6d6297SScott Long /* ISO, ECMA, & ANSI versions */ 1941ad6d6297SScott Long inqdata[4] = 31; 1942ad6d6297SScott Long /* length of additional data */ 1943ad6d6297SScott Long strncpy(&inqdata[8], "Areca ", 8); 1944ad6d6297SScott Long /* Vendor Identification */ 1945ad6d6297SScott Long strncpy(&inqdata[16], "RAID controller ", 16); 1946ad6d6297SScott Long /* Product Identification */ 1947ad6d6297SScott Long strncpy(&inqdata[32], "R001", 4); /* Product Revision */ 1948ad6d6297SScott Long memcpy(buffer, inqdata, sizeof(inqdata)); 1949ad6d6297SScott Long xpt_done(pccb); 1950ad6d6297SScott Long } 1951ad6d6297SScott Long break; 1952ad6d6297SScott Long case WRITE_BUFFER: 1953ad6d6297SScott Long case READ_BUFFER: { 1954ad6d6297SScott Long if (arcmsr_iop_message_xfer(acb, pccb)) { 1955ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 1956ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 1957ad6d6297SScott Long } 1958ad6d6297SScott Long xpt_done(pccb); 1959ad6d6297SScott Long } 1960ad6d6297SScott Long break; 1961ad6d6297SScott Long default: 1962ad6d6297SScott Long xpt_done(pccb); 1963ad6d6297SScott Long } 1964ad6d6297SScott Long } 1965ad6d6297SScott Long /* 1966f1c579b1SScott Long ********************************************************************* 1967f1c579b1SScott Long ********************************************************************* 1968f1c579b1SScott Long */ 1969ad6d6297SScott Long static void arcmsr_action(struct cam_sim * psim, union ccb * pccb) 1970f1c579b1SScott Long { 1971ad6d6297SScott Long struct AdapterControlBlock * acb; 1972f1c579b1SScott Long 1973ad6d6297SScott Long acb=(struct AdapterControlBlock *) cam_sim_softc(psim); 1974ad6d6297SScott Long if(acb==NULL) { 1975ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 1976f1c579b1SScott Long xpt_done(pccb); 1977f1c579b1SScott Long return; 1978f1c579b1SScott Long } 1979ad6d6297SScott Long switch (pccb->ccb_h.func_code) { 1980ad6d6297SScott Long case XPT_SCSI_IO: { 1981ad6d6297SScott Long struct CommandControlBlock *srb; 1982ad6d6297SScott Long int target=pccb->ccb_h.target_id; 1983f1c579b1SScott Long 1984ad6d6297SScott Long if(target == 16) { 1985ad6d6297SScott Long /* virtual device for iop message transfer */ 1986ad6d6297SScott Long arcmsr_handle_virtual_command(acb, pccb); 1987ad6d6297SScott Long return; 1988ad6d6297SScott Long } 1989ad6d6297SScott Long if((srb=arcmsr_get_freesrb(acb)) == NULL) { 1990ad6d6297SScott Long pccb->ccb_h.status |= CAM_RESRC_UNAVAIL; 1991f1c579b1SScott Long xpt_done(pccb); 1992f1c579b1SScott Long return; 1993f1c579b1SScott Long } 1994ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbsrb_ptr=srb; 1995ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbacb_ptr=acb; 1996ad6d6297SScott Long srb->pccb=pccb; 1997ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 1998ad6d6297SScott Long if(!(pccb->ccb_h.flags & CAM_SCATTER_VALID)) { 1999ad6d6297SScott Long /* Single buffer */ 2000ad6d6297SScott Long if(!(pccb->ccb_h.flags & CAM_DATA_PHYS)) { 2001ad6d6297SScott Long /* Buffer is virtual */ 2002ad6d6297SScott Long u_int32_t error, s; 2003f1c579b1SScott Long 2004f1c579b1SScott Long s=splsoftvm(); 2005ad6d6297SScott Long error = bus_dmamap_load(acb->dm_segs_dmat 2006ad6d6297SScott Long , srb->dm_segs_dmamap 2007ad6d6297SScott Long , pccb->csio.data_ptr 2008ad6d6297SScott Long , pccb->csio.dxfer_len 2009ad6d6297SScott Long , arcmsr_executesrb, srb, /*flags*/0); 2010ad6d6297SScott Long if(error == EINPROGRESS) { 2011ad6d6297SScott Long xpt_freeze_simq(acb->psim, 1); 2012f1c579b1SScott Long pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 2013f1c579b1SScott Long } 2014f1c579b1SScott Long splx(s); 2015ad6d6297SScott Long } else { 2016ad6d6297SScott Long /* Buffer is physical */ 20171c7e9358SScott Long panic("arcmsr: CAM_DATA_PHYS not supported"); 2018f1c579b1SScott Long } 2019ad6d6297SScott Long } else { 2020ad6d6297SScott Long /* Scatter/gather list */ 2021f1c579b1SScott Long struct bus_dma_segment *segs; 2022f1c579b1SScott Long 2023ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0 2024ad6d6297SScott Long || (pccb->ccb_h.flags & CAM_DATA_PHYS) != 0) { 2025ad6d6297SScott Long pccb->ccb_h.status |= CAM_PROVIDE_FAIL; 2026f1c579b1SScott Long xpt_done(pccb); 2027ad6d6297SScott Long free(srb, M_DEVBUF); 2028f1c579b1SScott Long return; 2029f1c579b1SScott Long } 2030f1c579b1SScott Long segs=(struct bus_dma_segment *)pccb->csio.data_ptr; 2031ad6d6297SScott Long arcmsr_executesrb(srb, segs, pccb->csio.sglist_cnt, 0); 2032f1c579b1SScott Long } 2033ad6d6297SScott Long } else { 2034ad6d6297SScott Long arcmsr_executesrb(srb, NULL, 0, 0); 2035f1c579b1SScott Long } 2036f1c579b1SScott Long break; 2037f1c579b1SScott Long } 2038ad6d6297SScott Long case XPT_TARGET_IO: { 2039ad6d6297SScott Long /* target mode not yet support vendor specific commands. */ 2040ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2041f1c579b1SScott Long xpt_done(pccb); 2042f1c579b1SScott Long break; 2043f1c579b1SScott Long } 2044ad6d6297SScott Long case XPT_PATH_INQ: { 2045f1c579b1SScott Long struct ccb_pathinq *cpi= &pccb->cpi; 2046f1c579b1SScott Long 2047f1c579b1SScott Long cpi->version_num=1; 2048f1c579b1SScott Long cpi->hba_inquiry=PI_SDTR_ABLE | PI_TAG_ABLE; 2049f1c579b1SScott Long cpi->target_sprt=0; 2050f1c579b1SScott Long cpi->hba_misc=0; 2051f1c579b1SScott Long cpi->hba_eng_cnt=0; 2052ad6d6297SScott Long cpi->max_target=ARCMSR_MAX_TARGETID; /* 0-16 */ 2053ad6d6297SScott Long cpi->max_lun=ARCMSR_MAX_TARGETLUN; /* 0-7 */ 2054ad6d6297SScott Long cpi->initiator_id=ARCMSR_SCSI_INITIATOR_ID; /* 255 */ 2055f1c579b1SScott Long cpi->bus_id=cam_sim_bus(psim); 2056f1c579b1SScott Long strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 2057f1c579b1SScott Long strncpy(cpi->hba_vid, "ARCMSR", HBA_IDLEN); 2058f1c579b1SScott Long strncpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN); 2059f1c579b1SScott Long cpi->unit_number=cam_sim_unit(psim); 206044f05562SScott Long #ifdef CAM_NEW_TRAN_CODE 2061fa9ed865SMatt Jacob cpi->transport = XPORT_SPI; 2062fa9ed865SMatt Jacob cpi->transport_version = 2; 2063fa9ed865SMatt Jacob cpi->protocol = PROTO_SCSI; 2064fa9ed865SMatt Jacob cpi->protocol_version = SCSI_REV_2; 206544f05562SScott Long #endif 2066ad6d6297SScott Long cpi->ccb_h.status |= CAM_REQ_CMP; 2067f1c579b1SScott Long xpt_done(pccb); 2068f1c579b1SScott Long break; 2069f1c579b1SScott Long } 2070ad6d6297SScott Long case XPT_ABORT: { 2071f1c579b1SScott Long union ccb *pabort_ccb; 2072f1c579b1SScott Long 2073f1c579b1SScott Long pabort_ccb=pccb->cab.abort_ccb; 2074ad6d6297SScott Long switch (pabort_ccb->ccb_h.func_code) { 2075f1c579b1SScott Long case XPT_ACCEPT_TARGET_IO: 2076f1c579b1SScott Long case XPT_IMMED_NOTIFY: 2077f1c579b1SScott Long case XPT_CONT_TARGET_IO: 2078ad6d6297SScott Long if(arcmsr_seek_cmd2abort(pabort_ccb)==TRUE) { 2079ad6d6297SScott Long pabort_ccb->ccb_h.status |= CAM_REQ_ABORTED; 2080f1c579b1SScott Long xpt_done(pabort_ccb); 2081ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2082ad6d6297SScott Long } else { 2083f1c579b1SScott Long xpt_print_path(pabort_ccb->ccb_h.path); 2084f1c579b1SScott Long printf("Not found\n"); 2085ad6d6297SScott Long pccb->ccb_h.status |= CAM_PATH_INVALID; 2086f1c579b1SScott Long } 2087f1c579b1SScott Long break; 2088f1c579b1SScott Long case XPT_SCSI_IO: 2089ad6d6297SScott Long pccb->ccb_h.status |= CAM_UA_ABORT; 2090f1c579b1SScott Long break; 2091f1c579b1SScott Long default: 2092ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2093f1c579b1SScott Long break; 2094f1c579b1SScott Long } 2095f1c579b1SScott Long xpt_done(pccb); 2096f1c579b1SScott Long break; 2097f1c579b1SScott Long } 2098f1c579b1SScott Long case XPT_RESET_BUS: 2099ad6d6297SScott Long case XPT_RESET_DEV: { 2100ad6d6297SScott Long u_int32_t i; 2101f1c579b1SScott Long 2102ad6d6297SScott Long arcmsr_bus_reset(acb); 2103ad6d6297SScott Long for (i=0; i < 500; i++) { 2104f1c579b1SScott Long DELAY(1000); 2105f1c579b1SScott Long } 2106ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2107f1c579b1SScott Long xpt_done(pccb); 2108f1c579b1SScott Long break; 2109f1c579b1SScott Long } 2110ad6d6297SScott Long case XPT_TERM_IO: { 2111ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2112f1c579b1SScott Long xpt_done(pccb); 2113f1c579b1SScott Long break; 2114f1c579b1SScott Long } 2115ad6d6297SScott Long case XPT_GET_TRAN_SETTINGS: { 2116ad6d6297SScott Long struct ccb_trans_settings *cts; 2117ad6d6297SScott Long 2118ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 2119ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 2120ad6d6297SScott Long xpt_done(pccb); 2121ad6d6297SScott Long break; 2122ad6d6297SScott Long } 2123ad6d6297SScott Long cts= &pccb->cts; 212444f05562SScott Long #ifdef CAM_NEW_TRAN_CODE 212544f05562SScott Long { 212644f05562SScott Long struct ccb_trans_settings_scsi *scsi; 212744f05562SScott Long struct ccb_trans_settings_spi *spi; 212844f05562SScott Long 2129ad6d6297SScott Long scsi = &cts->proto_specific.scsi; 2130ad6d6297SScott Long spi = &cts->xport_specific.spi; 2131fa9ed865SMatt Jacob cts->protocol = PROTO_SCSI; 2132fa9ed865SMatt Jacob cts->protocol_version = SCSI_REV_2; 2133fa9ed865SMatt Jacob cts->transport = XPORT_SPI; 2134fa9ed865SMatt Jacob cts->transport_version = 2; 2135fa9ed865SMatt Jacob spi->flags = CTS_SPI_FLAGS_DISC_ENB; 2136fa9ed865SMatt Jacob spi->sync_period=3; 2137fa9ed865SMatt Jacob spi->sync_offset=32; 2138fa9ed865SMatt Jacob spi->bus_width=MSG_EXT_WDTR_BUS_16_BIT; 2139fa9ed865SMatt Jacob scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 2140fa9ed865SMatt Jacob spi->valid = CTS_SPI_VALID_SYNC_RATE 2141fa9ed865SMatt Jacob | CTS_SPI_VALID_SYNC_OFFSET 2142fa9ed865SMatt Jacob | CTS_SPI_VALID_BUS_WIDTH; 2143fa9ed865SMatt Jacob scsi->valid = CTS_SCSI_VALID_TQ; 214444f05562SScott Long } 214544f05562SScott Long #else 214644f05562SScott Long { 214744f05562SScott Long cts->flags=(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB); 214844f05562SScott Long cts->sync_period=3; 214944f05562SScott Long cts->sync_offset=32; 215044f05562SScott Long cts->bus_width=MSG_EXT_WDTR_BUS_16_BIT; 215144f05562SScott Long cts->valid=CCB_TRANS_SYNC_RATE_VALID | 215244f05562SScott Long CCB_TRANS_SYNC_OFFSET_VALID | 215344f05562SScott Long CCB_TRANS_BUS_WIDTH_VALID | 215444f05562SScott Long CCB_TRANS_DISC_VALID | 215544f05562SScott Long CCB_TRANS_TQ_VALID; 215644f05562SScott Long } 215744f05562SScott Long #endif 2158ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2159ad6d6297SScott Long xpt_done(pccb); 2160ad6d6297SScott Long break; 2161ad6d6297SScott Long } 2162ad6d6297SScott Long case XPT_SET_TRAN_SETTINGS: { 2163ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 2164ad6d6297SScott Long xpt_done(pccb); 2165ad6d6297SScott Long break; 2166ad6d6297SScott Long } 2167ad6d6297SScott Long case XPT_CALC_GEOMETRY: { 2168ad6d6297SScott Long struct ccb_calc_geometry *ccg; 2169ad6d6297SScott Long u_int32_t size_mb; 2170ad6d6297SScott Long u_int32_t secs_per_cylinder; 2171ad6d6297SScott Long 2172ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 2173ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 2174ad6d6297SScott Long xpt_done(pccb); 2175ad6d6297SScott Long break; 2176ad6d6297SScott Long } 2177f1c579b1SScott Long ccg= &pccb->ccg; 2178ad6d6297SScott Long if (ccg->block_size == 0) { 2179ad6d6297SScott Long pccb->ccb_h.status = CAM_REQ_INVALID; 2180ad6d6297SScott Long xpt_done(pccb); 2181ad6d6297SScott Long break; 2182ad6d6297SScott Long } 2183ad6d6297SScott Long if(((1024L * 1024L)/ccg->block_size) < 0) { 2184ad6d6297SScott Long pccb->ccb_h.status = CAM_REQ_INVALID; 2185ad6d6297SScott Long xpt_done(pccb); 2186ad6d6297SScott Long break; 2187ad6d6297SScott Long } 2188f1c579b1SScott Long size_mb=ccg->volume_size/((1024L * 1024L)/ccg->block_size); 2189ad6d6297SScott Long if(size_mb > 1024 ) { 2190f1c579b1SScott Long ccg->heads=255; 2191f1c579b1SScott Long ccg->secs_per_track=63; 2192ad6d6297SScott Long } else { 2193f1c579b1SScott Long ccg->heads=64; 2194f1c579b1SScott Long ccg->secs_per_track=32; 2195f1c579b1SScott Long } 2196f1c579b1SScott Long secs_per_cylinder=ccg->heads * ccg->secs_per_track; 2197f1c579b1SScott Long ccg->cylinders=ccg->volume_size / secs_per_cylinder; 2198ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2199f1c579b1SScott Long xpt_done(pccb); 2200f1c579b1SScott Long break; 2201f1c579b1SScott Long } 2202f1c579b1SScott Long default: 2203ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2204f1c579b1SScott Long xpt_done(pccb); 2205f1c579b1SScott Long break; 2206f1c579b1SScott Long } 2207f1c579b1SScott Long return; 2208f1c579b1SScott Long } 2209f1c579b1SScott Long /* 2210f1c579b1SScott Long ********************************************************************** 2211f1c579b1SScott Long ********************************************************************** 2212f1c579b1SScott Long */ 221344f05562SScott Long static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) 2214f1c579b1SScott Long { 2215ad6d6297SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 221644f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 221744f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 2218ad6d6297SScott Long printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 2219ad6d6297SScott Long } 2220f1c579b1SScott Long return; 2221f1c579b1SScott Long } 2222f1c579b1SScott Long /* 2223f1c579b1SScott Long ********************************************************************** 2224f1c579b1SScott Long ********************************************************************** 2225f1c579b1SScott Long */ 222644f05562SScott Long static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb) 222744f05562SScott Long { 222844f05562SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 222944f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 223044f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_START_BGRB); 223144f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 223244f05562SScott Long printf( "arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 223344f05562SScott Long } 223444f05562SScott Long return; 223544f05562SScott Long } 223644f05562SScott Long /* 223744f05562SScott Long ********************************************************************** 223844f05562SScott Long ********************************************************************** 223944f05562SScott Long */ 224044f05562SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) 224144f05562SScott Long { 224244f05562SScott Long switch (acb->adapter_type) { 224344f05562SScott Long case ACB_ADAPTER_TYPE_A: 224444f05562SScott Long arcmsr_start_hba_bgrb(acb); 224544f05562SScott Long break; 224644f05562SScott Long case ACB_ADAPTER_TYPE_B: 224744f05562SScott Long arcmsr_start_hbb_bgrb(acb); 224844f05562SScott Long break; 224944f05562SScott Long } 225044f05562SScott Long return; 225144f05562SScott Long } 225244f05562SScott Long /* 225344f05562SScott Long ********************************************************************** 225444f05562SScott Long ** 225544f05562SScott Long ********************************************************************** 225644f05562SScott Long */ 225744f05562SScott Long static void arcmsr_polling_hba_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 2258f1c579b1SScott Long { 2259ad6d6297SScott Long struct CommandControlBlock *srb; 226044f05562SScott Long u_int32_t flag_srb, outbound_intstatus, poll_srb_done=0, poll_count=0; 2261f1c579b1SScott Long 226244f05562SScott Long polling_ccb_retry: 2263ad6d6297SScott Long poll_count++; 226444f05562SScott Long outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 226544f05562SScott Long 0, outbound_intstatus) & acb->outbound_int_enable; 226644f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 226744f05562SScott Long 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/ 226844f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 2269ad6d6297SScott Long while(1) { 227044f05562SScott Long if((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 227144f05562SScott Long 0, outbound_queueport))==0xFFFFFFFF) { 2272ad6d6297SScott Long if(poll_srb_done) { 2273ad6d6297SScott Long break;/*chip FIFO no ccb for completion already*/ 2274ad6d6297SScott Long } else { 2275ad6d6297SScott Long UDELAY(25000); 2276ad6d6297SScott Long if(poll_count > 100) { 2277ad6d6297SScott Long break; 2278f1c579b1SScott Long } 227944f05562SScott Long goto polling_ccb_retry; 2280f1c579b1SScott Long } 2281ad6d6297SScott Long } 2282ad6d6297SScott Long /* check ifcommand done with no error*/ 228344f05562SScott Long srb=(struct CommandControlBlock *) 228444f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 228544f05562SScott Long poll_srb_done = (srb==poll_srb) ? 1:0; 2286ad6d6297SScott Long if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) { 228744f05562SScott Long if(srb->startdone==ARCMSR_SRB_ABORTED) { 2288ad6d6297SScott Long printf("arcmsr%d: scsi id=%d lun=%d srb='%p'" 2289ad6d6297SScott Long "poll command abort successfully \n" 2290ad6d6297SScott Long , acb->pci_unit 2291ad6d6297SScott Long , srb->pccb->ccb_h.target_id 2292ad6d6297SScott Long , srb->pccb->ccb_h.target_lun, srb); 2293ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 2294ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 2295ad6d6297SScott Long continue; 2296ad6d6297SScott Long } 2297ad6d6297SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 2298ad6d6297SScott Long "srboutstandingcount=%d \n" 2299ad6d6297SScott Long , acb->pci_unit 2300ad6d6297SScott Long , srb, acb->srboutstandingcount); 2301ad6d6297SScott Long continue; 2302ad6d6297SScott Long } 230344f05562SScott Long arcmsr_report_srb_state(acb, srb, flag_srb); 2304ad6d6297SScott Long } /*drain reply FIFO*/ 2305f1c579b1SScott Long return; 2306f1c579b1SScott Long } 2307f1c579b1SScott Long /* 2308f1c579b1SScott Long ********************************************************************** 230944f05562SScott Long ** 2310ad6d6297SScott Long ********************************************************************** 2311ad6d6297SScott Long */ 231244f05562SScott Long static void arcmsr_polling_hbb_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 231344f05562SScott Long { 231444f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 231544f05562SScott Long struct CommandControlBlock *srb; 231644f05562SScott Long u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 231744f05562SScott Long int index; 231844f05562SScott Long 231944f05562SScott Long polling_ccb_retry: 232044f05562SScott Long poll_count++; 232144f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 232244f05562SScott Long 0, iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 232344f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 232444f05562SScott Long while(1) { 232544f05562SScott Long index=phbbmu->doneq_index; 232644f05562SScott Long if((flag_srb=phbbmu->done_qbuffer[index]) == 0) { 232744f05562SScott Long if(poll_srb_done) { 232844f05562SScott Long break;/*chip FIFO no ccb for completion already*/ 232944f05562SScott Long } else { 233044f05562SScott Long UDELAY(25000); 233144f05562SScott Long if(poll_count > 100) { 233244f05562SScott Long break; 233344f05562SScott Long } 233444f05562SScott Long goto polling_ccb_retry; 233544f05562SScott Long } 233644f05562SScott Long } 233744f05562SScott Long phbbmu->done_qbuffer[index]=0; 233844f05562SScott Long index++; 233944f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 234044f05562SScott Long phbbmu->doneq_index=index; 234144f05562SScott Long /* check if command done with no error*/ 234244f05562SScott Long srb=(struct CommandControlBlock *) 234344f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 234444f05562SScott Long poll_srb_done = (srb==poll_srb) ? 1:0; 234544f05562SScott Long if((srb->acb!=acb) || (srb->startdone!=ARCMSR_SRB_START)) { 234644f05562SScott Long if(srb->startdone==ARCMSR_SRB_ABORTED) { 234744f05562SScott Long printf("arcmsr%d: scsi id=%d lun=%d srb='%p'" 234844f05562SScott Long "poll command abort successfully \n" 234944f05562SScott Long , acb->pci_unit 235044f05562SScott Long , srb->pccb->ccb_h.target_id 235144f05562SScott Long , srb->pccb->ccb_h.target_lun, srb); 235244f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 235344f05562SScott Long arcmsr_srb_complete(srb, 1); 235444f05562SScott Long continue; 235544f05562SScott Long } 235644f05562SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 235744f05562SScott Long "srboutstandingcount=%d \n" 235844f05562SScott Long , acb->pci_unit 235944f05562SScott Long , srb, acb->srboutstandingcount); 236044f05562SScott Long continue; 236144f05562SScott Long } 236244f05562SScott Long arcmsr_report_srb_state(acb, srb, flag_srb); 236344f05562SScott Long } /*drain reply FIFO*/ 236444f05562SScott Long return; 236544f05562SScott Long } 236644f05562SScott Long /* 236744f05562SScott Long ********************************************************************** 236844f05562SScott Long ********************************************************************** 236944f05562SScott Long */ 237044f05562SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 237144f05562SScott Long { 237244f05562SScott Long switch (acb->adapter_type) { 237344f05562SScott Long case ACB_ADAPTER_TYPE_A: { 237444f05562SScott Long arcmsr_polling_hba_srbdone(acb, poll_srb); 237544f05562SScott Long } 237644f05562SScott Long break; 237744f05562SScott Long case ACB_ADAPTER_TYPE_B: { 237844f05562SScott Long arcmsr_polling_hbb_srbdone(acb, poll_srb); 237944f05562SScott Long } 238044f05562SScott Long break; 238144f05562SScott Long } 238244f05562SScott Long } 238344f05562SScott Long /* 238444f05562SScott Long ********************************************************************** 238544f05562SScott Long ********************************************************************** 238644f05562SScott Long */ 238744f05562SScott Long static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) 2388ad6d6297SScott Long { 2389ad6d6297SScott Long char *acb_firm_model=acb->firm_model; 2390ad6d6297SScott Long char *acb_firm_version=acb->firm_version; 239144f05562SScott Long size_t iop_firm_model=offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[15]); /*firm_model,15,60-67*/ 239244f05562SScott Long size_t iop_firm_version=offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[17]); /*firm_version,17,68-83*/ 2393ad6d6297SScott Long int i; 2394ad6d6297SScott Long 239544f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 239644f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 2397ad6d6297SScott Long printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n" 2398ad6d6297SScott Long , acb->pci_unit); 2399ad6d6297SScott Long } 2400ad6d6297SScott Long i=0; 2401ad6d6297SScott Long while(i<8) { 240244f05562SScott Long *acb_firm_model=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 2403ad6d6297SScott Long /* 8 bytes firm_model, 15, 60-67*/ 2404ad6d6297SScott Long acb_firm_model++; 2405ad6d6297SScott Long i++; 2406ad6d6297SScott Long } 2407ad6d6297SScott Long i=0; 2408ad6d6297SScott Long while(i<16) { 240944f05562SScott Long *acb_firm_version=bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 2410ad6d6297SScott Long /* 16 bytes firm_version, 17, 68-83*/ 2411ad6d6297SScott Long acb_firm_version++; 2412ad6d6297SScott Long i++; 2413ad6d6297SScott Long } 2414ad6d6297SScott Long printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION); 2415ad6d6297SScott Long printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version); 241644f05562SScott Long acb->firm_request_len=CHIP_REG_READ32(HBA_MessageUnit, 241744f05562SScott Long 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 241844f05562SScott Long acb->firm_numbers_queue=CHIP_REG_READ32(HBA_MessageUnit, 241944f05562SScott Long 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 242044f05562SScott Long acb->firm_sdram_size=CHIP_REG_READ32(HBA_MessageUnit, 242144f05562SScott Long 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 242244f05562SScott Long acb->firm_ide_channels=CHIP_REG_READ32(HBA_MessageUnit, 242344f05562SScott Long 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 2424ad6d6297SScott Long return; 2425ad6d6297SScott Long } 2426ad6d6297SScott Long /* 2427ad6d6297SScott Long ********************************************************************** 242844f05562SScott Long ********************************************************************** 242944f05562SScott Long */ 243044f05562SScott Long static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) 243144f05562SScott Long { 243244f05562SScott Long char *acb_firm_model=acb->firm_model; 243344f05562SScott Long char *acb_firm_version=acb->firm_version; 243444f05562SScott Long size_t iop_firm_model=offsetof(struct HBB_RWBUFFER, 243544f05562SScott Long msgcode_rwbuffer[15]); /*firm_model,15,60-67*/ 243644f05562SScott Long size_t iop_firm_version=offsetof(struct HBB_RWBUFFER, 243744f05562SScott Long msgcode_rwbuffer[17]); /*firm_version,17,68-83*/ 243844f05562SScott Long int i; 243944f05562SScott Long 244044f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 244144f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG); 244244f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 244344f05562SScott Long printf( "arcmsr%d: wait" 244444f05562SScott Long "'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 244544f05562SScott Long } 244644f05562SScott Long i=0; 244744f05562SScott Long while(i<8) { 244844f05562SScott Long *acb_firm_model=bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_model+i); 244944f05562SScott Long /* 8 bytes firm_model, 15, 60-67*/ 245044f05562SScott Long acb_firm_model++; 245144f05562SScott Long i++; 245244f05562SScott Long } 245344f05562SScott Long i=0; 245444f05562SScott Long while(i<16) { 245544f05562SScott Long *acb_firm_version=bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_version+i); 245644f05562SScott Long /* 16 bytes firm_version, 17, 68-83*/ 245744f05562SScott Long acb_firm_version++; 245844f05562SScott Long i++; 245944f05562SScott Long } 246044f05562SScott Long printf("ARECA RAID ADAPTER%d: %s \n", acb->pci_unit, ARCMSR_DRIVER_VERSION); 246144f05562SScott Long printf("ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->pci_unit, acb->firm_version); 246244f05562SScott Long acb->firm_request_len=CHIP_REG_READ32(HBB_RWBUFFER, 246344f05562SScott Long 1, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 246444f05562SScott Long acb->firm_numbers_queue=CHIP_REG_READ32(HBB_RWBUFFER, 246544f05562SScott Long 1, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 246644f05562SScott Long acb->firm_sdram_size=CHIP_REG_READ32(HBB_RWBUFFER, 246744f05562SScott Long 1, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 246844f05562SScott Long acb->firm_ide_channels=CHIP_REG_READ32(HBB_RWBUFFER, 246944f05562SScott Long 1, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 247044f05562SScott Long return; 247144f05562SScott Long } 247244f05562SScott Long /* 247344f05562SScott Long ********************************************************************** 247444f05562SScott Long ********************************************************************** 247544f05562SScott Long */ 247644f05562SScott Long static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) 247744f05562SScott Long { 247844f05562SScott Long switch (acb->adapter_type) { 247944f05562SScott Long case ACB_ADAPTER_TYPE_A: { 248044f05562SScott Long arcmsr_get_hba_config(acb); 248144f05562SScott Long } 248244f05562SScott Long break; 248344f05562SScott Long case ACB_ADAPTER_TYPE_B: { 248444f05562SScott Long arcmsr_get_hbb_config(acb); 248544f05562SScott Long } 248644f05562SScott Long break; 248744f05562SScott Long } 248844f05562SScott Long return; 248944f05562SScott Long } 249044f05562SScott Long /* 249144f05562SScott Long ********************************************************************** 249244f05562SScott Long ********************************************************************** 249344f05562SScott Long */ 249444f05562SScott Long static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb) 249544f05562SScott Long { 249644f05562SScott Long int timeout=0; 249744f05562SScott Long 249844f05562SScott Long switch (acb->adapter_type) { 249944f05562SScott Long case ACB_ADAPTER_TYPE_A: { 250044f05562SScott Long while ((CHIP_REG_READ32(HBA_MessageUnit, 250144f05562SScott Long 0, outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) 250244f05562SScott Long { 250344f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 250444f05562SScott Long { 250544f05562SScott Long printf( "arcmsr%d:" 250644f05562SScott Long "timed out waiting for firmware \n", acb->pci_unit); 250744f05562SScott Long return; 250844f05562SScott Long } 250944f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 251044f05562SScott Long } 251144f05562SScott Long } 251244f05562SScott Long break; 251344f05562SScott Long case ACB_ADAPTER_TYPE_B: { 251444f05562SScott Long while ((CHIP_REG_READ32(HBB_DOORBELL, 251544f05562SScott Long 0, iop2drv_doorbell) & ARCMSR_MESSAGE_FIRMWARE_OK) == 0) 251644f05562SScott Long { 251744f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 251844f05562SScott Long { 251944f05562SScott Long printf( "arcmsr%d:" 252044f05562SScott Long " timed out waiting for firmware \n", acb->pci_unit); 252144f05562SScott Long return; 252244f05562SScott Long } 252344f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 252444f05562SScott Long } 252544f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 252644f05562SScott Long 0, drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 252744f05562SScott Long } 252844f05562SScott Long break; 252944f05562SScott Long } 253044f05562SScott Long return; 253144f05562SScott Long } 253244f05562SScott Long /* 253344f05562SScott Long ********************************************************************** 253444f05562SScott Long ********************************************************************** 253544f05562SScott Long */ 253644f05562SScott Long static void arcmsr_clear_doorbell_queue_buffer( struct AdapterControlBlock *acb) 253744f05562SScott Long { 253844f05562SScott Long switch (acb->adapter_type) { 253944f05562SScott Long case ACB_ADAPTER_TYPE_A: { 254044f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 254144f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 254244f05562SScott Long 0, outbound_doorbell, 254344f05562SScott Long CHIP_REG_READ32(HBA_MessageUnit, 254444f05562SScott Long 0, outbound_doorbell));/*clear doorbell interrupt */ 254544f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 254644f05562SScott Long 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 254744f05562SScott Long } 254844f05562SScott Long break; 254944f05562SScott Long case ACB_ADAPTER_TYPE_B: { 255044f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 255144f05562SScott Long 0, iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt and message state*/ 255244f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 255344f05562SScott Long 0, drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 255444f05562SScott Long /* let IOP know data has been read */ 255544f05562SScott Long } 255644f05562SScott Long break; 255744f05562SScott Long } 255844f05562SScott Long return; 255944f05562SScott Long } 256044f05562SScott Long /* 256144f05562SScott Long ************************************************************************ 256244f05562SScott Long ************************************************************************ 256344f05562SScott Long */ 256444f05562SScott Long static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb) 256544f05562SScott Long { 256644f05562SScott Long unsigned long srb_phyaddr; 256744f05562SScott Long u_int32_t srb_phyaddr_hi32; 256844f05562SScott Long 256944f05562SScott Long /* 257044f05562SScott Long ******************************************************************** 257144f05562SScott Long ** here we need to tell iop 331 our freesrb.HighPart 257244f05562SScott Long ** if freesrb.HighPart is not zero 257344f05562SScott Long ******************************************************************** 257444f05562SScott Long */ 257544f05562SScott Long srb_phyaddr= (unsigned long) acb->srb_phyaddr; 257644f05562SScott Long srb_phyaddr_hi32=(u_int32_t) ((srb_phyaddr>>16)>>16); 257744f05562SScott Long switch (acb->adapter_type) { 257844f05562SScott Long case ACB_ADAPTER_TYPE_A: { 257944f05562SScott Long if(srb_phyaddr_hi32!=0) { 258044f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 258144f05562SScott Long 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 258244f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 258344f05562SScott Long 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 258444f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 258544f05562SScott Long 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 258644f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 258744f05562SScott Long printf( "arcmsr%d:" 258844f05562SScott Long " 'set srb high part physical address' timeout \n", acb->pci_unit); 258944f05562SScott Long return FALSE; 259044f05562SScott Long } 259144f05562SScott Long } 259244f05562SScott Long } 259344f05562SScott Long break; 259444f05562SScott Long /* 259544f05562SScott Long *********************************************************************** 259644f05562SScott Long ** if adapter type B, set window of "post command Q" 259744f05562SScott Long *********************************************************************** 259844f05562SScott Long */ 259944f05562SScott Long case ACB_ADAPTER_TYPE_B: { 260044f05562SScott Long u_int32_t post_queue_phyaddr; 260144f05562SScott Long struct HBB_MessageUnit *phbbmu; 260244f05562SScott Long 260344f05562SScott Long phbbmu=(struct HBB_MessageUnit *)acb->pmu; 260444f05562SScott Long phbbmu->postq_index=0; 260544f05562SScott Long phbbmu->doneq_index=0; 260644f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 260744f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_SET_POST_WINDOW); 260844f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 260944f05562SScott Long printf( "arcmsr%d:" 261044f05562SScott Long " 'set window of post command Q' timeout\n", acb->pci_unit); 261144f05562SScott Long return FALSE; 261244f05562SScott Long } 261344f05562SScott Long post_queue_phyaddr = srb_phyaddr 261444f05562SScott Long + ARCMSR_MAX_FREESRB_NUM*sizeof(struct CommandControlBlock) 261544f05562SScott Long + offsetof(struct HBB_MessageUnit, post_qbuffer); 261644f05562SScott Long CHIP_REG_WRITE32(HBB_RWBUFFER, 261744f05562SScott Long 1, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */ 261844f05562SScott Long CHIP_REG_WRITE32(HBB_RWBUFFER, 261944f05562SScott Long 1, msgcode_rwbuffer[1], srb_phyaddr_hi32); /* normal should be zero */ 262044f05562SScott Long CHIP_REG_WRITE32(HBB_RWBUFFER, 262144f05562SScott Long 1, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ size (256+8)*4 */ 262244f05562SScott Long CHIP_REG_WRITE32(HBB_RWBUFFER, 262344f05562SScott Long 1, msgcode_rwbuffer[3], post_queue_phyaddr+1056); /* doneQ size (256+8)*4 */ 262444f05562SScott Long CHIP_REG_WRITE32(HBB_RWBUFFER, 262544f05562SScott Long 1, msgcode_rwbuffer[4], 1056); /* srb maxQ size must be --> [(256+8)*4] */ 262644f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 262744f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_SET_CONFIG); 262844f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 262944f05562SScott Long printf( "arcmsr%d: 'set command Q window' timeout \n", acb->pci_unit); 263044f05562SScott Long return FALSE; 263144f05562SScott Long } 263244f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 263344f05562SScott Long 0, drv2iop_doorbell, ARCMSR_MESSAGE_START_DRIVER_MODE); 263444f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 263544f05562SScott Long printf( "arcmsr%d: 'start diver mode' timeout \n", acb->pci_unit); 263644f05562SScott Long return FALSE; 263744f05562SScott Long } 263844f05562SScott Long } 263944f05562SScott Long break; 264044f05562SScott Long } 264144f05562SScott Long return TRUE; 264244f05562SScott Long } 264344f05562SScott Long /* 264444f05562SScott Long ************************************************************************ 264544f05562SScott Long ************************************************************************ 264644f05562SScott Long */ 264744f05562SScott Long static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb) 264844f05562SScott Long { 264944f05562SScott Long switch (acb->adapter_type) 265044f05562SScott Long { 265144f05562SScott Long case ACB_ADAPTER_TYPE_A: 265244f05562SScott Long return; 265344f05562SScott Long case ACB_ADAPTER_TYPE_B: { 265444f05562SScott Long CHIP_REG_WRITE32(HBB_DOORBELL, 265544f05562SScott Long 0, drv2iop_doorbell,ARCMSR_MESSAGE_ACTIVE_EOI_MODE); 265644f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 265744f05562SScott Long printf( "arcmsr%d:" 265844f05562SScott Long " 'iop enable eoi mode' timeout \n", acb->pci_unit); 265944f05562SScott Long return; 266044f05562SScott Long } 266144f05562SScott Long } 266244f05562SScott Long break; 266344f05562SScott Long } 266444f05562SScott Long return; 266544f05562SScott Long } 266644f05562SScott Long /* 266744f05562SScott Long ********************************************************************** 2668ad6d6297SScott Long ********************************************************************** 2669ad6d6297SScott Long */ 2670ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb) 2671ad6d6297SScott Long { 267244f05562SScott Long u_int32_t intmask_org; 2673ad6d6297SScott Long 267444f05562SScott Long /* disable all outbound interrupt */ 267544f05562SScott Long intmask_org=arcmsr_disable_allintr(acb); 267644f05562SScott Long arcmsr_wait_firmware_ready(acb); 267744f05562SScott Long arcmsr_iop_confirm(acb); 2678ad6d6297SScott Long arcmsr_get_firmware_spec(acb); 267944f05562SScott Long /*start background rebuild*/ 2680ad6d6297SScott Long arcmsr_start_adapter_bgrb(acb); 268144f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 268244f05562SScott Long arcmsr_clear_doorbell_queue_buffer(acb); 268344f05562SScott Long arcmsr_enable_eoi_mode(acb); 268444f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 268544f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 2686ad6d6297SScott Long acb->acb_flags |=ACB_F_IOP_INITED; 2687ad6d6297SScott Long return; 2688ad6d6297SScott Long } 2689ad6d6297SScott Long /* 2690ad6d6297SScott Long ********************************************************************** 2691f1c579b1SScott Long ********************************************************************** 2692f1c579b1SScott Long */ 2693f1c579b1SScott Long static void arcmsr_map_freesrb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 2694f1c579b1SScott Long { 2695ad6d6297SScott Long struct AdapterControlBlock *acb=arg; 2696ad6d6297SScott Long struct CommandControlBlock *srb_tmp; 2697ad6d6297SScott Long u_int8_t * dma_memptr; 269844f05562SScott Long u_int32_t i; 2699ad6d6297SScott Long unsigned long srb_phyaddr=(unsigned long)segs->ds_addr; 2700f1c579b1SScott Long 2701ad6d6297SScott Long dma_memptr=acb->uncacheptr; 270244f05562SScott Long acb->srb_phyaddr=srb_phyaddr; 2703ad6d6297SScott Long srb_tmp=(struct CommandControlBlock *)dma_memptr; 2704ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 270544f05562SScott Long if(bus_dmamap_create(acb->dm_segs_dmat, 270644f05562SScott Long /*flags*/0, &srb_tmp->dm_segs_dmamap)!=0) { 2707ad6d6297SScott Long acb->acb_flags |= ACB_F_MAPFREESRB_FAILD; 270844f05562SScott Long printf("arcmsr%d:" 270944f05562SScott Long " srb dmamap bus_dmamap_create error\n", acb->pci_unit); 2710ad6d6297SScott Long return; 2711ad6d6297SScott Long } 2712ad6d6297SScott Long srb_tmp->cdb_shifted_phyaddr=srb_phyaddr >> 5; 2713ad6d6297SScott Long srb_tmp->acb=acb; 2714ad6d6297SScott Long acb->srbworkingQ[i]=acb->psrb_pool[i]=srb_tmp; 2715ad6d6297SScott Long srb_phyaddr=srb_phyaddr+sizeof(struct CommandControlBlock); 2716ad6d6297SScott Long srb_tmp++; 2717ad6d6297SScott Long } 2718ad6d6297SScott Long acb->vir2phy_offset=(unsigned long)srb_tmp-(unsigned long)srb_phyaddr; 2719f1c579b1SScott Long return; 2720f1c579b1SScott Long } 2721f1c579b1SScott Long /* 2722f1c579b1SScott Long ************************************************************************ 2723f1c579b1SScott Long ** 2724f1c579b1SScott Long ** 2725f1c579b1SScott Long ************************************************************************ 2726f1c579b1SScott Long */ 2727ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb) 2728f1c579b1SScott Long { 2729f1c579b1SScott Long /* remove the control device */ 2730ad6d6297SScott Long if(acb->ioctl_dev != NULL) { 2731ad6d6297SScott Long destroy_dev(acb->ioctl_dev); 2732f1c579b1SScott Long } 2733ad6d6297SScott Long bus_dmamap_unload(acb->srb_dmat, acb->srb_dmamap); 2734ad6d6297SScott Long bus_dmamap_destroy(acb->srb_dmat, acb->srb_dmamap); 2735ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 2736ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 2737ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 2738f1c579b1SScott Long return; 2739f1c579b1SScott Long } 2740f1c579b1SScott Long /* 2741f1c579b1SScott Long ************************************************************************ 2742f1c579b1SScott Long ************************************************************************ 2743f1c579b1SScott Long */ 2744ad6d6297SScott Long static u_int32_t arcmsr_initialize(device_t dev) 2745f1c579b1SScott Long { 2746ad6d6297SScott Long struct AdapterControlBlock *acb=device_get_softc(dev); 2747ad6d6297SScott Long u_int16_t pci_command; 274844f05562SScott Long int i, j,max_coherent_size; 2749f1c579b1SScott Long 275044f05562SScott Long switch (pci_get_devid(dev)) { 275144f05562SScott Long case PCIDevVenIDARC1201: { 275244f05562SScott Long acb->adapter_type=ACB_ADAPTER_TYPE_B; 275344f05562SScott Long max_coherent_size=ARCMSR_SRBS_POOL_SIZE 275444f05562SScott Long +(sizeof(struct HBB_MessageUnit)); 275544f05562SScott Long } 275644f05562SScott Long break; 275744f05562SScott Long case PCIDevVenIDARC1110: 275844f05562SScott Long case PCIDevVenIDARC1120: 275944f05562SScott Long case PCIDevVenIDARC1130: 276044f05562SScott Long case PCIDevVenIDARC1160: 276144f05562SScott Long case PCIDevVenIDARC1170: 276244f05562SScott Long case PCIDevVenIDARC1210: 276344f05562SScott Long case PCIDevVenIDARC1220: 276444f05562SScott Long case PCIDevVenIDARC1230: 276544f05562SScott Long case PCIDevVenIDARC1260: 276644f05562SScott Long case PCIDevVenIDARC1270: 276744f05562SScott Long case PCIDevVenIDARC1280: 276844f05562SScott Long case PCIDevVenIDARC1380: 276944f05562SScott Long case PCIDevVenIDARC1381: 277044f05562SScott Long case PCIDevVenIDARC1680: 277144f05562SScott Long case PCIDevVenIDARC1681: { 277244f05562SScott Long acb->adapter_type=ACB_ADAPTER_TYPE_A; 277344f05562SScott Long max_coherent_size=ARCMSR_SRBS_POOL_SIZE; 277444f05562SScott Long } 277544f05562SScott Long break; 277644f05562SScott Long default: { 277744f05562SScott Long printf("arcmsr%d:" 277844f05562SScott Long " unknown RAID adapter type \n", device_get_unit(dev)); 277944f05562SScott Long return ENOMEM; 278044f05562SScott Long } 278144f05562SScott Long } 2782f1c579b1SScott Long #if __FreeBSD_version >= 502010 2783f1c579b1SScott Long if(bus_dma_tag_create( /*parent*/ NULL, 2784f1c579b1SScott Long /*alignemnt*/ 1, 2785f1c579b1SScott Long /*boundary*/ 0, 2786701d9f1fSScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 2787f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 2788f1c579b1SScott Long /*filter*/ NULL, 2789f1c579b1SScott Long /*filterarg*/ NULL, 2790f1c579b1SScott Long /*maxsize*/ BUS_SPACE_MAXSIZE_32BIT, 2791f1c579b1SScott Long /*nsegments*/ BUS_SPACE_UNRESTRICTED, 2792f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 2793f1c579b1SScott Long /*flags*/ 0, 2794f1c579b1SScott Long /*lockfunc*/ NULL, 2795f1c579b1SScott Long /*lockarg*/ NULL, 2796ad6d6297SScott Long &acb->parent_dmat) != 0) 2797f1c579b1SScott Long #else 2798f1c579b1SScott Long if(bus_dma_tag_create( /*parent*/ NULL, 2799f1c579b1SScott Long /*alignemnt*/ 1, 2800f1c579b1SScott Long /*boundary*/ 0, 2801701d9f1fSScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 2802f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 2803f1c579b1SScott Long /*filter*/ NULL, 2804f1c579b1SScott Long /*filterarg*/ NULL, 2805f1c579b1SScott Long /*maxsize*/ BUS_SPACE_MAXSIZE_32BIT, 2806f1c579b1SScott Long /*nsegments*/ BUS_SPACE_UNRESTRICTED, 2807f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 2808f1c579b1SScott Long /*flags*/ 0, 2809ad6d6297SScott Long &acb->parent_dmat) != 0) 2810f1c579b1SScott Long #endif 2811f1c579b1SScott Long { 281244f05562SScott Long printf("arcmsr%d: parent_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 2813f1c579b1SScott Long return ENOMEM; 2814f1c579b1SScott Long } 2815f1c579b1SScott Long /* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */ 2816f1c579b1SScott Long #if __FreeBSD_version >= 502010 2817ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 2818f1c579b1SScott Long /*alignment*/ 1, 2819f1c579b1SScott Long /*boundary*/ 0, 2820f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 2821f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 2822f1c579b1SScott Long /*filter*/ NULL, 2823f1c579b1SScott Long /*filterarg*/ NULL, 2824f1c579b1SScott Long /*maxsize*/ MAXBSIZE, 2825f1c579b1SScott Long /*nsegments*/ ARCMSR_MAX_SG_ENTRIES, 2826f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 2827ad6d6297SScott Long /*flags*/ 0, 2828f1c579b1SScott Long /*lockfunc*/ busdma_lock_mutex, 28295878cbecSScott Long /*lockarg*/ &acb->qbuffer_lock, 2830ad6d6297SScott Long &acb->dm_segs_dmat) != 0) 2831f1c579b1SScott Long #else 2832ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 2833f1c579b1SScott Long /*alignment*/ 1, 2834f1c579b1SScott Long /*boundary*/ 0, 2835f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 2836f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 2837f1c579b1SScott Long /*filter*/ NULL, 2838f1c579b1SScott Long /*filterarg*/ NULL, 2839f1c579b1SScott Long /*maxsize*/ MAXBSIZE, 2840f1c579b1SScott Long /*nsegments*/ ARCMSR_MAX_SG_ENTRIES, 2841f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 2842ad6d6297SScott Long /*flags*/ 0, 2843ad6d6297SScott Long &acb->dm_segs_dmat) != 0) 2844f1c579b1SScott Long #endif 2845f1c579b1SScott Long { 2846ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 284744f05562SScott Long printf("arcmsr%d: dm_segs_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 2848f1c579b1SScott Long return ENOMEM; 2849f1c579b1SScott Long } 2850ad6d6297SScott Long /* DMA tag for our srb structures.... Allocate the freesrb memory */ 2851f1c579b1SScott Long #if __FreeBSD_version >= 502010 2852ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 285344f05562SScott Long /*alignment*/ 0x20, 2854f1c579b1SScott Long /*boundary*/ 0, 2855f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 2856f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 2857f1c579b1SScott Long /*filter*/ NULL, 2858f1c579b1SScott Long /*filterarg*/ NULL, 285944f05562SScott Long /*maxsize*/ max_coherent_size, 2860f1c579b1SScott Long /*nsegments*/ 1, 2861f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 2862701d9f1fSScott Long /*flags*/ 0, 2863f1c579b1SScott Long /*lockfunc*/ NULL, 2864f1c579b1SScott Long /*lockarg*/ NULL, 2865ad6d6297SScott Long &acb->srb_dmat) != 0) 2866f1c579b1SScott Long #else 2867ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 286844f05562SScott Long /*alignment*/ 0x20, 2869f1c579b1SScott Long /*boundary*/ 0, 2870f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 2871f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 2872f1c579b1SScott Long /*filter*/ NULL, 2873f1c579b1SScott Long /*filterarg*/ NULL, 287444f05562SScott Long /*maxsize*/ max_coherent_size, 2875f1c579b1SScott Long /*nsegments*/ 1, 2876f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 2877701d9f1fSScott Long /*flags*/ 0, 2878ad6d6297SScott Long &acb->srb_dmat) != 0) 2879f1c579b1SScott Long #endif 2880f1c579b1SScott Long { 2881ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 2882ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 288344f05562SScott Long printf("arcmsr%d: srb_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 2884f1c579b1SScott Long return ENXIO; 2885f1c579b1SScott Long } 2886f1c579b1SScott Long /* Allocation for our srbs */ 2887ad6d6297SScott Long if(bus_dmamem_alloc(acb->srb_dmat, (void **)&acb->uncacheptr 2888ad6d6297SScott Long , BUS_DMA_WAITOK | BUS_DMA_COHERENT, &acb->srb_dmamap) != 0) { 2889ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 2890ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 2891ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 289244f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamem_alloc failure!\n", device_get_unit(dev)); 2893f1c579b1SScott Long return ENXIO; 2894f1c579b1SScott Long } 2895f1c579b1SScott Long /* And permanently map them */ 2896ad6d6297SScott Long if(bus_dmamap_load(acb->srb_dmat, acb->srb_dmamap, acb->uncacheptr 289744f05562SScott Long , max_coherent_size, arcmsr_map_freesrb, acb, /*flags*/0)) { 2898ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 2899ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 2900ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 290144f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamap_load failure!\n", device_get_unit(dev)); 2902f1c579b1SScott Long return ENXIO; 2903f1c579b1SScott Long } 2904f1c579b1SScott Long pci_command=pci_read_config(dev, PCIR_COMMAND, 2); 2905f1c579b1SScott Long pci_command |= PCIM_CMD_BUSMASTEREN; 2906f1c579b1SScott Long pci_command |= PCIM_CMD_PERRESPEN; 2907f1c579b1SScott Long pci_command |= PCIM_CMD_MWRICEN; 2908f1c579b1SScott Long /* Enable Busmaster/Mem */ 2909f1c579b1SScott Long pci_command |= PCIM_CMD_MEMEN; 2910f1c579b1SScott Long pci_write_config(dev, PCIR_COMMAND, pci_command, 2); 291144f05562SScott Long switch(acb->adapter_type) { 291244f05562SScott Long case ACB_ADAPTER_TYPE_A: { 291344f05562SScott Long u_int32_t rid0=PCIR_BAR(0); 291444f05562SScott Long vm_offset_t mem_base0; 291544f05562SScott Long 291644f05562SScott Long acb->sys_res_arcmsr[0]=bus_alloc_resource(dev, 291744f05562SScott Long SYS_RES_MEMORY, &rid0, 0ul, ~0ul, 0x1000, RF_ACTIVE); 291844f05562SScott Long if(acb->sys_res_arcmsr[0] == NULL) { 2919ad6d6297SScott Long arcmsr_free_resource(acb); 292044f05562SScott Long printf("arcmsr%d:" 292144f05562SScott Long " bus_alloc_resource failure!\n", device_get_unit(dev)); 2922f1c579b1SScott Long return ENOMEM; 2923f1c579b1SScott Long } 292444f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 2925ad6d6297SScott Long arcmsr_free_resource(acb); 292644f05562SScott Long printf("arcmsr%d:" 292744f05562SScott Long " rman_get_start failure!\n", device_get_unit(dev)); 2928f1c579b1SScott Long return ENXIO; 2929f1c579b1SScott Long } 293044f05562SScott Long mem_base0=(vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 293144f05562SScott Long if(mem_base0==0) { 2932ad6d6297SScott Long arcmsr_free_resource(acb); 293344f05562SScott Long printf("arcmsr%d:" 293444f05562SScott Long " rman_get_virtual failure!\n", device_get_unit(dev)); 2935f1c579b1SScott Long return ENXIO; 2936f1c579b1SScott Long } 293744f05562SScott Long acb->btag[0]=rman_get_bustag(acb->sys_res_arcmsr[0]); 293844f05562SScott Long acb->bhandle[0]=rman_get_bushandle(acb->sys_res_arcmsr[0]); 293944f05562SScott Long acb->pmu=(struct MessageUnit_UNION *)mem_base0; 294044f05562SScott Long } 294144f05562SScott Long break; 294244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 294344f05562SScott Long struct HBB_MessageUnit *phbbmu; 294444f05562SScott Long struct CommandControlBlock *freesrb; 294544f05562SScott Long u_int32_t rid[]={ PCIR_BAR(0), PCIR_BAR(2) }; 294644f05562SScott Long vm_offset_t mem_base[]={0,0}; 294744f05562SScott Long for(i=0; i<2; i++) { 294844f05562SScott Long if(i==0) { 294944f05562SScott Long acb->sys_res_arcmsr[i]=bus_alloc_resource(dev, 295044f05562SScott Long SYS_RES_MEMORY, &rid[i], 295144f05562SScott Long 0x20400, 0x20400+sizeof(struct HBB_DOORBELL), 295244f05562SScott Long sizeof(struct HBB_DOORBELL), RF_ACTIVE); 295344f05562SScott Long } else { 295444f05562SScott Long acb->sys_res_arcmsr[i]=bus_alloc_resource(dev, 295544f05562SScott Long SYS_RES_MEMORY, &rid[i], 295644f05562SScott Long 0x0fa00, 0x0fa00+sizeof(struct HBB_RWBUFFER), 295744f05562SScott Long sizeof(struct HBB_RWBUFFER), RF_ACTIVE); 295844f05562SScott Long } 295944f05562SScott Long if(acb->sys_res_arcmsr[i] == NULL) { 296044f05562SScott Long arcmsr_free_resource(acb); 296144f05562SScott Long printf("arcmsr%d:" 296244f05562SScott Long " bus_alloc_resource %d failure!\n", device_get_unit(dev), i); 296344f05562SScott Long return ENOMEM; 296444f05562SScott Long } 296544f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[i]) <= 0) { 296644f05562SScott Long arcmsr_free_resource(acb); 296744f05562SScott Long printf("arcmsr%d:" 296844f05562SScott Long " rman_get_start %d failure!\n", device_get_unit(dev), i); 296944f05562SScott Long return ENXIO; 297044f05562SScott Long } 297144f05562SScott Long mem_base[i]=(vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[i]); 297244f05562SScott Long if(mem_base[i]==0) { 297344f05562SScott Long arcmsr_free_resource(acb); 297444f05562SScott Long printf("arcmsr%d:" 297544f05562SScott Long " rman_get_virtual %d failure!\n", device_get_unit(dev), i); 297644f05562SScott Long return ENXIO; 297744f05562SScott Long } 297844f05562SScott Long acb->btag[i]=rman_get_bustag(acb->sys_res_arcmsr[i]); 297944f05562SScott Long acb->bhandle[i]=rman_get_bushandle(acb->sys_res_arcmsr[i]); 298044f05562SScott Long } 298144f05562SScott Long freesrb=(struct CommandControlBlock *)acb->uncacheptr; 298244f05562SScott Long acb->pmu=(struct MessageUnit_UNION *)&freesrb[ARCMSR_MAX_FREESRB_NUM]; 298344f05562SScott Long phbbmu=(struct HBB_MessageUnit *)acb->pmu; 298444f05562SScott Long phbbmu->hbb_doorbell=(struct HBB_DOORBELL *)mem_base[0]; 298544f05562SScott Long phbbmu->hbb_rwbuffer=(struct HBB_RWBUFFER *)mem_base[1]; 298644f05562SScott Long } 298744f05562SScott Long break; 298844f05562SScott Long } 2989ad6d6297SScott Long if(acb->acb_flags & ACB_F_MAPFREESRB_FAILD) { 2990ad6d6297SScott Long arcmsr_free_resource(acb); 299144f05562SScott Long printf("arcmsr%d: map free srb failure!\n", device_get_unit(dev)); 2992f1c579b1SScott Long return ENXIO; 2993f1c579b1SScott Long } 2994ad6d6297SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED 2995ad6d6297SScott Long |ACB_F_MESSAGE_RQBUFFER_CLEARED 299644f05562SScott Long |ACB_F_MESSAGE_WQBUFFER_READ); 2997ad6d6297SScott Long acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; 2998ad6d6297SScott Long /* 2999ad6d6297SScott Long ******************************************************************** 3000ad6d6297SScott Long ** init raid volume state 3001ad6d6297SScott Long ******************************************************************** 3002ad6d6297SScott Long */ 3003ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_TARGETID;i++) { 3004ad6d6297SScott Long for(j=0;j<ARCMSR_MAX_TARGETLUN;j++) { 300544f05562SScott Long acb->devstate[i][j]=ARECA_RAID_GONE; 3006ad6d6297SScott Long } 3007ad6d6297SScott Long } 3008ad6d6297SScott Long arcmsr_iop_init(acb); 3009f1c579b1SScott Long return(0); 3010f1c579b1SScott Long } 3011f1c579b1SScott Long /* 3012f1c579b1SScott Long ************************************************************************ 3013f1c579b1SScott Long ************************************************************************ 3014f1c579b1SScott Long */ 3015ad6d6297SScott Long static u_int32_t arcmsr_attach(device_t dev) 3016f1c579b1SScott Long { 3017ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 3018ad6d6297SScott Long u_int32_t unit=device_get_unit(dev); 3019f1c579b1SScott Long struct ccb_setasync csa; 3020f1c579b1SScott Long struct cam_devq *devq; /* Device Queue to use for this SIM */ 3021f1c579b1SScott Long struct resource *irqres; 3022f1c579b1SScott Long int rid; 3023f1c579b1SScott Long 3024ad6d6297SScott Long if(acb == NULL) { 3025ad6d6297SScott Long printf("arcmsr%d: cannot allocate softc\n", unit); 3026ad6d6297SScott Long return (ENOMEM); 3027ad6d6297SScott Long } 30285878cbecSScott Long ARCMSR_LOCK_INIT(&acb->qbuffer_lock, "arcmsr Q buffer lock"); 3029ad6d6297SScott Long if(arcmsr_initialize(dev)) { 3030ad6d6297SScott Long printf("arcmsr%d: initialize failure!\n", unit); 30315878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3032f1c579b1SScott Long return ENXIO; 3033f1c579b1SScott Long } 3034f1c579b1SScott Long /* After setting up the adapter, map our interrupt */ 3035f1c579b1SScott Long rid=0; 3036ad6d6297SScott Long irqres=bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0ul, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE); 3037ad6d6297SScott Long if(irqres == NULL || 303844f05562SScott Long #if __FreeBSD_version >= 700025 3039ad6d6297SScott Long bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE 30405878cbecSScott Long , NULL, arcmsr_intr_handler, acb, &acb->ih)) { 304144f05562SScott Long #else 304244f05562SScott Long bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE 304344f05562SScott Long , arcmsr_intr_handler, acb, &acb->ih)) { 304444f05562SScott Long #endif 3045ad6d6297SScott Long arcmsr_free_resource(acb); 30465878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3047f1c579b1SScott Long printf("arcmsr%d: unable to register interrupt handler!\n", unit); 3048f1c579b1SScott Long return ENXIO; 3049f1c579b1SScott Long } 3050ad6d6297SScott Long acb->irqres=irqres; 3051ad6d6297SScott Long acb->pci_dev=dev; 3052ad6d6297SScott Long acb->pci_unit=unit; 3053f1c579b1SScott Long /* 3054f1c579b1SScott Long * Now let the CAM generic SCSI layer find the SCSI devices on 3055f1c579b1SScott Long * the bus * start queue to reset to the idle loop. * 3056f1c579b1SScott Long * Create device queue of SIM(s) * (MAX_START_JOB - 1) : 3057f1c579b1SScott Long * max_sim_transactions 3058f1c579b1SScott Long */ 3059f1c579b1SScott Long devq=cam_simq_alloc(ARCMSR_MAX_START_JOB); 3060ad6d6297SScott Long if(devq == NULL) { 3061ad6d6297SScott Long arcmsr_free_resource(acb); 3062ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 30635878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3064ad6d6297SScott Long printf("arcmsr%d: cam_simq_alloc failure!\n", unit); 3065f1c579b1SScott Long return ENXIO; 3066f1c579b1SScott Long } 306744f05562SScott Long #if __FreeBSD_version >= 700025 30682b83592fSScott Long acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll, 30695878cbecSScott Long "arcmsr", acb, unit, &acb->qbuffer_lock, 1, 30702b83592fSScott Long ARCMSR_MAX_OUTSTANDING_CMD, devq); 307144f05562SScott Long #else 307244f05562SScott Long acb->psim=cam_sim_alloc(arcmsr_action, arcmsr_poll, 307344f05562SScott Long "arcmsr", acb, unit, 1, 307444f05562SScott Long ARCMSR_MAX_OUTSTANDING_CMD, devq); 307544f05562SScott Long #endif 3076ad6d6297SScott Long if(acb->psim == NULL) { 3077ad6d6297SScott Long arcmsr_free_resource(acb); 3078ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 3079f1c579b1SScott Long cam_simq_free(devq); 30805878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3081ad6d6297SScott Long printf("arcmsr%d: cam_sim_alloc failure!\n", unit); 3082f1c579b1SScott Long return ENXIO; 3083f1c579b1SScott Long } 30845878cbecSScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 308544f05562SScott Long #if __FreeBSD_version >= 700099 3086b50569b7SScott Long if(xpt_bus_register(acb->psim, dev, 0) != CAM_SUCCESS) { 308744f05562SScott Long #else 308844f05562SScott Long if(xpt_bus_register(acb->psim, 0) != CAM_SUCCESS) { 308944f05562SScott Long #endif 3090ad6d6297SScott Long arcmsr_free_resource(acb); 3091ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 3092ad6d6297SScott Long cam_sim_free(acb->psim, /*free_devq*/TRUE); 30935878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3094ad6d6297SScott Long printf("arcmsr%d: xpt_bus_register failure!\n", unit); 3095f1c579b1SScott Long return ENXIO; 3096f1c579b1SScott Long } 3097ad6d6297SScott Long if(xpt_create_path(&acb->ppath, /* periph */ NULL 3098ad6d6297SScott Long , cam_sim_path(acb->psim) 3099ad6d6297SScott Long , CAM_TARGET_WILDCARD 3100ad6d6297SScott Long , CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 3101ad6d6297SScott Long arcmsr_free_resource(acb); 3102ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 3103ad6d6297SScott Long xpt_bus_deregister(cam_sim_path(acb->psim)); 3104ad6d6297SScott Long cam_sim_free(acb->psim, /* free_simq */ TRUE); 31055878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3106ad6d6297SScott Long printf("arcmsr%d: xpt_create_path failure!\n", unit); 3107f1c579b1SScott Long return ENXIO; 3108f1c579b1SScott Long } 3109f1c579b1SScott Long /* 3110f1c579b1SScott Long **************************************************** 3111f1c579b1SScott Long */ 3112ad6d6297SScott Long xpt_setup_ccb(&csa.ccb_h, acb->ppath, /*priority*/5); 3113f1c579b1SScott Long csa.ccb_h.func_code=XPT_SASYNC_CB; 3114f1c579b1SScott Long csa.event_enable=AC_FOUND_DEVICE|AC_LOST_DEVICE; 3115f1c579b1SScott Long csa.callback=arcmsr_async; 3116ad6d6297SScott Long csa.callback_arg=acb->psim; 3117f1c579b1SScott Long xpt_action((union ccb *)&csa); 31185878cbecSScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 3119f1c579b1SScott Long /* Create the control device. */ 3120ad6d6297SScott Long acb->ioctl_dev=make_dev(&arcmsr_cdevsw 3121ad6d6297SScott Long , unit 3122ad6d6297SScott Long , UID_ROOT 3123ad6d6297SScott Long , GID_WHEEL /* GID_OPERATOR */ 3124ad6d6297SScott Long , S_IRUSR | S_IWUSR 3125ad6d6297SScott Long , "arcmsr%d", unit); 3126f1c579b1SScott Long #if __FreeBSD_version < 503000 3127ad6d6297SScott Long acb->ioctl_dev->si_drv1=acb; 3128f1c579b1SScott Long #endif 3129f1c579b1SScott Long #if __FreeBSD_version > 500005 3130ad6d6297SScott Long (void)make_dev_alias(acb->ioctl_dev, "arc%d", unit); 3131f1c579b1SScott Long #endif 3132f1c579b1SScott Long return 0; 3133f1c579b1SScott Long } 3134f1c579b1SScott Long /* 3135f1c579b1SScott Long ************************************************************************ 3136f1c579b1SScott Long ************************************************************************ 3137f1c579b1SScott Long */ 3138ad6d6297SScott Long static u_int32_t arcmsr_probe(device_t dev) 3139f1c579b1SScott Long { 3140ad6d6297SScott Long u_int32_t id; 3141ad6d6297SScott Long static char buf[256]; 3142ad6d6297SScott Long char *type; 3143ad6d6297SScott Long int raid6 = 1; 3144ad6d6297SScott Long 3145ad6d6297SScott Long if (pci_get_vendor(dev) != PCI_VENDOR_ID_ARECA) { 3146ad6d6297SScott Long return (ENXIO); 3147ad6d6297SScott Long } 3148ad6d6297SScott Long switch(id=pci_get_devid(dev)) { 3149f1c579b1SScott Long case PCIDevVenIDARC1110: 3150f1c579b1SScott Long case PCIDevVenIDARC1210: 315144f05562SScott Long case PCIDevVenIDARC1201: 3152ad6d6297SScott Long raid6 = 0; 3153ad6d6297SScott Long /*FALLTHRU*/ 3154ad6d6297SScott Long case PCIDevVenIDARC1120: 3155ad6d6297SScott Long case PCIDevVenIDARC1130: 3156ad6d6297SScott Long case PCIDevVenIDARC1160: 3157ad6d6297SScott Long case PCIDevVenIDARC1170: 3158f1c579b1SScott Long case PCIDevVenIDARC1220: 3159f1c579b1SScott Long case PCIDevVenIDARC1230: 3160f1c579b1SScott Long case PCIDevVenIDARC1260: 3161ad6d6297SScott Long case PCIDevVenIDARC1270: 3162ad6d6297SScott Long case PCIDevVenIDARC1280: 3163ad6d6297SScott Long type = "SATA"; 3164ad6d6297SScott Long break; 3165ad6d6297SScott Long case PCIDevVenIDARC1380: 3166ad6d6297SScott Long case PCIDevVenIDARC1381: 3167ad6d6297SScott Long case PCIDevVenIDARC1680: 3168ad6d6297SScott Long case PCIDevVenIDARC1681: 3169ad6d6297SScott Long type = "SAS"; 3170ad6d6297SScott Long break; 3171ad6d6297SScott Long default: 3172ad6d6297SScott Long type = "X-TYPE"; 3173ad6d6297SScott Long break; 3174f1c579b1SScott Long } 3175ad6d6297SScott Long sprintf(buf, "Areca %s Host Adapter RAID Controller %s\n", type, raid6 ? "(RAID6 capable)" : ""); 3176ad6d6297SScott Long device_set_desc_copy(dev, buf); 3177ad6d6297SScott Long return 0; 3178f1c579b1SScott Long } 3179f1c579b1SScott Long /* 3180f1c579b1SScott Long ************************************************************************ 3181f1c579b1SScott Long ************************************************************************ 3182f1c579b1SScott Long */ 3183ad6d6297SScott Long static void arcmsr_shutdown(device_t dev) 3184f1c579b1SScott Long { 318544f05562SScott Long u_int32_t i; 3186ad6d6297SScott Long u_int32_t intmask_org; 3187ad6d6297SScott Long struct CommandControlBlock *srb; 3188ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 3189f1c579b1SScott Long 3190f1c579b1SScott Long /* stop adapter background rebuild */ 31915878cbecSScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 319244f05562SScott Long /* disable all outbound interrupt */ 319344f05562SScott Long intmask_org=arcmsr_disable_allintr(acb); 3194ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 3195ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 3196f1c579b1SScott Long /* abort all outstanding command */ 3197ad6d6297SScott Long acb->acb_flags |= ACB_F_SCSISTOPADAPTER; 3198ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOP_INITED; 3199ad6d6297SScott Long if(acb->srboutstandingcount!=0) { 320044f05562SScott Long /*clear and abort all outbound posted Q*/ 320144f05562SScott Long arcmsr_done4abort_postqueue(acb); 320244f05562SScott Long /* talk to iop 331 outstanding command aborted*/ 3203ad6d6297SScott Long arcmsr_abort_allcmd(acb); 3204ad6d6297SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) { 3205ad6d6297SScott Long srb=acb->psrb_pool[i]; 3206ad6d6297SScott Long if(srb->startdone==ARCMSR_SRB_START) { 3207ad6d6297SScott Long srb->startdone=ARCMSR_SRB_ABORTED; 3208ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 3209ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 3210f1c579b1SScott Long } 3211f1c579b1SScott Long } 3212f1c579b1SScott Long } 3213ad6d6297SScott Long atomic_set_int(&acb->srboutstandingcount, 0); 3214ad6d6297SScott Long acb->workingsrb_doneindex=0; 3215ad6d6297SScott Long acb->workingsrb_startindex=0; 32165878cbecSScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 3217f1c579b1SScott Long return; 3218f1c579b1SScott Long } 3219f1c579b1SScott Long /* 3220f1c579b1SScott Long ************************************************************************ 3221f1c579b1SScott Long ************************************************************************ 3222f1c579b1SScott Long */ 3223ad6d6297SScott Long static u_int32_t arcmsr_detach(device_t dev) 3224f1c579b1SScott Long { 3225ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 322644f05562SScott Long int i; 3227f1c579b1SScott Long 32285878cbecSScott Long bus_teardown_intr(dev, acb->irqres, acb->ih); 3229f1c579b1SScott Long arcmsr_shutdown(dev); 3230ad6d6297SScott Long arcmsr_free_resource(acb); 323144f05562SScott Long for(i=0; (acb->sys_res_arcmsr[i]!=NULL) && (i<2); i++) { 323244f05562SScott Long bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(i), acb->sys_res_arcmsr[i]); 323344f05562SScott Long } 3234ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 32355878cbecSScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 3236ad6d6297SScott Long xpt_async(AC_LOST_DEVICE, acb->ppath, NULL); 3237ad6d6297SScott Long xpt_free_path(acb->ppath); 3238ad6d6297SScott Long xpt_bus_deregister(cam_sim_path(acb->psim)); 3239ad6d6297SScott Long cam_sim_free(acb->psim, TRUE); 32405878cbecSScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 32415878cbecSScott Long ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 3242f1c579b1SScott Long return (0); 3243f1c579b1SScott Long } 3244f1c579b1SScott Long 3245f1c579b1SScott Long 3246