1f1c579b1SScott Long /* 235689395SXin LI ******************************************************************************** 335689395SXin LI ** OS : FreeBSD 4f1c579b1SScott Long ** FILE NAME : arcmsr.c 5d74001adSXin LI ** BY : Erich Chen, Ching Huang 6f1c579b1SScott Long ** Description: SCSI RAID Device Driver for 735689395SXin LI ** ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX/ARC188x) 835689395SXin LI ** SATA/SAS RAID HOST Adapter 935689395SXin LI ******************************************************************************** 1035689395SXin LI ******************************************************************************** 11f1c579b1SScott Long ** 1235689395SXin LI ** Copyright (C) 2002 - 2012, Areca Technology Corporation All rights reserved. 13f1c579b1SScott Long ** 14f1c579b1SScott Long ** Redistribution and use in source and binary forms, with or without 15f1c579b1SScott Long ** modification, are permitted provided that the following conditions 16f1c579b1SScott Long ** are met: 17f1c579b1SScott Long ** 1. Redistributions of source code must retain the above copyright 18f1c579b1SScott Long ** notice, this list of conditions and the following disclaimer. 19f1c579b1SScott Long ** 2. Redistributions in binary form must reproduce the above copyright 20f1c579b1SScott Long ** notice, this list of conditions and the following disclaimer in the 21f1c579b1SScott Long ** documentation and/or other materials provided with the distribution. 22f1c579b1SScott Long ** 3. The name of the author may not be used to endorse or promote products 23f1c579b1SScott Long ** derived from this software without specific prior written permission. 24f1c579b1SScott Long ** 25f1c579b1SScott Long ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 26f1c579b1SScott Long ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 27f1c579b1SScott Long ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28f1c579b1SScott Long ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 29f1c579b1SScott Long ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT 30f1c579b1SScott Long ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31f1c579b1SScott Long ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY 32f1c579b1SScott Long ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33f1c579b1SScott Long **(INCLUDING NEGLIGENCE OR OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF 34f1c579b1SScott Long ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3535689395SXin LI ******************************************************************************** 36f1c579b1SScott Long ** History 37f1c579b1SScott Long ** 38f1c579b1SScott Long ** REV# DATE NAME DESCRIPTION 3922f2616bSXin LI ** 1.00.00.00 03/31/2004 Erich Chen First release 40f1c579b1SScott Long ** 1.20.00.02 11/29/2004 Erich Chen bug fix with arcmsr_bus_reset when PHY error 4122f2616bSXin LI ** 1.20.00.03 04/19/2005 Erich Chen add SATA 24 Ports adapter type support 42ad6d6297SScott Long ** clean unused function 4322f2616bSXin LI ** 1.20.00.12 09/12/2005 Erich Chen bug fix with abort command handling, 44ad6d6297SScott Long ** firmware version check 45ad6d6297SScott Long ** and firmware update notify for hardware bug fix 46ad6d6297SScott Long ** handling if none zero high part physical address 47ad6d6297SScott Long ** of srb resource 4822f2616bSXin LI ** 1.20.00.13 08/18/2006 Erich Chen remove pending srb and report busy 49ad6d6297SScott Long ** add iop message xfer 50ad6d6297SScott Long ** with scsi pass-through command 51ad6d6297SScott Long ** add new device id of sas raid adapters 52ad6d6297SScott Long ** code fit for SPARC64 & PPC 53f48f00a1SScott Long ** 1.20.00.14 02/05/2007 Erich Chen bug fix for incorrect ccb_h.status report 54f48f00a1SScott Long ** and cause g_vfs_done() read write error 5544f05562SScott Long ** 1.20.00.15 10/10/2007 Erich Chen support new RAID adapter type ARC120x 56641182baSXin LI ** 1.20.00.16 10/10/2009 Erich Chen Bug fix for RAID adapter type ARC120x 57641182baSXin LI ** bus_dmamem_alloc() with BUS_DMA_ZERO 58d74001adSXin LI ** 1.20.00.17 07/15/2010 Ching Huang Added support ARC1880 59d74001adSXin LI ** report CAM_DEV_NOT_THERE instead of CAM_SEL_TIMEOUT when device failed, 60d74001adSXin LI ** prevent cam_periph_error removing all LUN devices of one Target id 61d74001adSXin LI ** for any one LUN device failed 62231c8b71SXin LI ** 1.20.00.18 10/14/2010 Ching Huang Fixed "inquiry data fails comparion at DV1 step" 63231c8b71SXin LI ** 10/25/2010 Ching Huang Fixed bad range input in bus_alloc_resource for ADAPTER_TYPE_B 64231c8b71SXin LI ** 1.20.00.19 11/11/2010 Ching Huang Fixed arcmsr driver prevent arcsas support for Areca SAS HBA ARC13x0 6522f2616bSXin LI ** 1.20.00.20 12/08/2010 Ching Huang Avoid calling atomic_set_int function 6622f2616bSXin LI ** 1.20.00.21 02/08/2011 Ching Huang Implement I/O request timeout 6722f2616bSXin LI ** 02/14/2011 Ching Huang Modified pktRequestCount 6822f2616bSXin LI ** 1.20.00.21 03/03/2011 Ching Huang if a command timeout, then wait its ccb back before free it 694e32649fSXin LI ** 1.20.00.22 07/04/2011 Ching Huang Fixed multiple MTX panic 70dac36688SXin LI ** 1.20.00.23 10/28/2011 Ching Huang Added TIMEOUT_DELAY in case of too many HDDs need to start 71dac36688SXin LI ** 1.20.00.23 11/08/2011 Ching Huang Added report device transfer speed 72dac36688SXin LI ** 1.20.00.23 01/30/2012 Ching Huang Fixed Request requeued and Retrying command 73dac36688SXin LI ** 1.20.00.24 06/11/2012 Ching Huang Fixed return sense data condition 74dac36688SXin LI ** 1.20.00.25 08/17/2012 Ching Huang Fixed hotplug device no function on type A adapter 75abfdbca9SXin LI ** 1.20.00.26 12/14/2012 Ching Huang Added support ARC1214,1224,1264,1284 76abfdbca9SXin LI ** 1.20.00.27 05/06/2013 Ching Huang Fixed out standing cmd full on ARC-12x4 771e7d660aSXin LI ** 1.20.00.28 09/13/2013 Ching Huang Removed recursive mutex in arcmsr_abort_dr_ccbs 78224a78aeSXin LI ** 1.20.00.29 12/18/2013 Ching Huang Change simq allocation number, support ARC1883 79b23a1998SXin LI ** 1.30.00.00 11/30/2015 Ching Huang Added support ARC1203 80f1c579b1SScott Long ****************************************************************************************** 81f1c579b1SScott Long */ 824b7ec270SMarius Strobl 834b7ec270SMarius Strobl #include <sys/cdefs.h> 844b7ec270SMarius Strobl __FBSDID("$FreeBSD$"); 854b7ec270SMarius Strobl 8622f2616bSXin LI #if 0 8722f2616bSXin LI #define ARCMSR_DEBUG1 1 8822f2616bSXin LI #endif 89f1c579b1SScott Long #include <sys/param.h> 90f1c579b1SScott Long #include <sys/systm.h> 91f1c579b1SScott Long #include <sys/malloc.h> 92f1c579b1SScott Long #include <sys/kernel.h> 93f1c579b1SScott Long #include <sys/bus.h> 94f1c579b1SScott Long #include <sys/queue.h> 95f1c579b1SScott Long #include <sys/stat.h> 96f1c579b1SScott Long #include <sys/devicestat.h> 97f1c579b1SScott Long #include <sys/kthread.h> 98f1c579b1SScott Long #include <sys/module.h> 99f1c579b1SScott Long #include <sys/proc.h> 100f1c579b1SScott Long #include <sys/lock.h> 101f1c579b1SScott Long #include <sys/sysctl.h> 102f1c579b1SScott Long #include <sys/poll.h> 103f1c579b1SScott Long #include <sys/ioccom.h> 104f1c579b1SScott Long #include <vm/vm.h> 105f1c579b1SScott Long #include <vm/vm_param.h> 106f1c579b1SScott Long #include <vm/pmap.h> 107f1c579b1SScott Long 108f1c579b1SScott Long #include <isa/rtc.h> 109f1c579b1SScott Long 110f1c579b1SScott Long #include <machine/bus.h> 111f1c579b1SScott Long #include <machine/resource.h> 112f1c579b1SScott Long #include <machine/atomic.h> 113f1c579b1SScott Long #include <sys/conf.h> 114f1c579b1SScott Long #include <sys/rman.h> 115f1c579b1SScott Long 116f1c579b1SScott Long #include <cam/cam.h> 117f1c579b1SScott Long #include <cam/cam_ccb.h> 118f1c579b1SScott Long #include <cam/cam_sim.h> 119d74001adSXin LI #include <cam/cam_periph.h> 120d74001adSXin LI #include <cam/cam_xpt_periph.h> 121f1c579b1SScott Long #include <cam/cam_xpt_sim.h> 122f1c579b1SScott Long #include <cam/cam_debug.h> 123f1c579b1SScott Long #include <cam/scsi/scsi_all.h> 124f1c579b1SScott Long #include <cam/scsi/scsi_message.h> 125f1c579b1SScott Long /* 126f1c579b1SScott Long ************************************************************************** 127f1c579b1SScott Long ************************************************************************** 128f1c579b1SScott Long */ 129f1c579b1SScott Long #if __FreeBSD_version >= 500005 130f1c579b1SScott Long #include <sys/selinfo.h> 131f1c579b1SScott Long #include <sys/mutex.h> 132ad6d6297SScott Long #include <sys/endian.h> 133f1c579b1SScott Long #include <dev/pci/pcivar.h> 134f1c579b1SScott Long #include <dev/pci/pcireg.h> 135f1c579b1SScott Long #else 136f1c579b1SScott Long #include <sys/select.h> 137f1c579b1SScott Long #include <pci/pcivar.h> 138f1c579b1SScott Long #include <pci/pcireg.h> 139f1c579b1SScott Long #endif 14044f05562SScott Long 14144f05562SScott Long #if !defined(CAM_NEW_TRAN_CODE) && __FreeBSD_version >= 700025 14244f05562SScott Long #define CAM_NEW_TRAN_CODE 1 14344f05562SScott Long #endif 14444f05562SScott Long 14522f2616bSXin LI #if __FreeBSD_version > 500000 14622f2616bSXin LI #define arcmsr_callout_init(a) callout_init(a, /*mpsafe*/1); 14722f2616bSXin LI #else 14822f2616bSXin LI #define arcmsr_callout_init(a) callout_init(a); 14922f2616bSXin LI #endif 15022f2616bSXin LI 151b23a1998SXin LI #define ARCMSR_DRIVER_VERSION "arcmsr version 1.30.00.00 2015-11-30" 152f1c579b1SScott Long #include <dev/arcmsr/arcmsr.h> 153f1c579b1SScott Long /* 154f1c579b1SScott Long ************************************************************************** 155f1c579b1SScott Long ************************************************************************** 156f1c579b1SScott Long */ 15722f2616bSXin LI static void arcmsr_free_srb(struct CommandControlBlock *srb); 158ad6d6297SScott Long static struct CommandControlBlock *arcmsr_get_freesrb(struct AdapterControlBlock *acb); 159ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb *abortccb); 160f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev); 161f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev); 162f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev); 163ad6d6297SScott Long static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg); 164ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb); 165f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev); 16644f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb); 167ad6d6297SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb); 168ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb); 169ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb); 170ad6d6297SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); 171ad6d6297SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb); 172ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb); 173ad6d6297SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb); 17435689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, struct QBUFFER *prbuffer); 1757a7bc959SXin LI static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb); 176ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb); 177ad6d6297SScott Long static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag); 178ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb); 179ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb); 180ad6d6297SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t *dm_segs, u_int32_t nseg); 181ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *pccb); 182ad6d6297SScott Long static int arcmsr_resume(device_t dev); 183ad6d6297SScott Long static int arcmsr_suspend(device_t dev); 184d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb); 185d74001adSXin LI static void arcmsr_polling_devmap(void *arg); 18622f2616bSXin LI static void arcmsr_srb_timeout(void *arg); 1877a7bc959SXin LI static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb); 18822f2616bSXin LI #ifdef ARCMSR_DEBUG1 18922f2616bSXin LI static void arcmsr_dump_data(struct AdapterControlBlock *acb); 19022f2616bSXin LI #endif 191f1c579b1SScott Long /* 192f1c579b1SScott Long ************************************************************************** 193ad6d6297SScott Long ************************************************************************** 194ad6d6297SScott Long */ 195ad6d6297SScott Long static void UDELAY(u_int32_t us) { DELAY(us); } 196ad6d6297SScott Long /* 197ad6d6297SScott Long ************************************************************************** 198f1c579b1SScott Long ************************************************************************** 199f1c579b1SScott Long */ 200231c8b71SXin LI static bus_dmamap_callback_t arcmsr_map_free_srb; 201231c8b71SXin LI static bus_dmamap_callback_t arcmsr_execute_srb; 202f1c579b1SScott Long /* 203f1c579b1SScott Long ************************************************************************** 204f1c579b1SScott Long ************************************************************************** 205f1c579b1SScott Long */ 206f1c579b1SScott Long static d_open_t arcmsr_open; 207f1c579b1SScott Long static d_close_t arcmsr_close; 208f1c579b1SScott Long static d_ioctl_t arcmsr_ioctl; 209f1c579b1SScott Long 210f1c579b1SScott Long static device_method_t arcmsr_methods[]={ 211f1c579b1SScott Long DEVMETHOD(device_probe, arcmsr_probe), 212f1c579b1SScott Long DEVMETHOD(device_attach, arcmsr_attach), 213f1c579b1SScott Long DEVMETHOD(device_detach, arcmsr_detach), 214f1c579b1SScott Long DEVMETHOD(device_shutdown, arcmsr_shutdown), 215ad6d6297SScott Long DEVMETHOD(device_suspend, arcmsr_suspend), 216ad6d6297SScott Long DEVMETHOD(device_resume, arcmsr_resume), 2174b7ec270SMarius Strobl 21835689395SXin LI #if __FreeBSD_version >= 803000 2194b7ec270SMarius Strobl DEVMETHOD_END 22035689395SXin LI #else 22135689395SXin LI { 0, 0 } 22235689395SXin LI #endif 223f1c579b1SScott Long }; 224f1c579b1SScott Long 225f1c579b1SScott Long static driver_t arcmsr_driver={ 226ad6d6297SScott Long "arcmsr", arcmsr_methods, sizeof(struct AdapterControlBlock) 227f1c579b1SScott Long }; 228f1c579b1SScott Long 229f1c579b1SScott Long static devclass_t arcmsr_devclass; 230f1c579b1SScott Long DRIVER_MODULE(arcmsr, pci, arcmsr_driver, arcmsr_devclass, 0, 0); 231d3cf342dSScott Long MODULE_DEPEND(arcmsr, pci, 1, 1, 1); 232d3cf342dSScott Long MODULE_DEPEND(arcmsr, cam, 1, 1, 1); 233ad6d6297SScott Long #ifndef BUS_DMA_COHERENT 234ad6d6297SScott Long #define BUS_DMA_COHERENT 0x04 /* hint: map memory in a coherent way */ 235ad6d6297SScott Long #endif 236ad6d6297SScott Long #if __FreeBSD_version >= 501000 237f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw={ 23822f2616bSXin LI #if __FreeBSD_version >= 503000 239f1c579b1SScott Long .d_version = D_VERSION, 240ad6d6297SScott Long #endif 24122f2616bSXin LI #if (__FreeBSD_version>=503000 && __FreeBSD_version<600034) 242f1c579b1SScott Long .d_flags = D_NEEDGIANT, 24322f2616bSXin LI #endif 244f1c579b1SScott Long .d_open = arcmsr_open, /* open */ 245f1c579b1SScott Long .d_close = arcmsr_close, /* close */ 246f1c579b1SScott Long .d_ioctl = arcmsr_ioctl, /* ioctl */ 247f1c579b1SScott Long .d_name = "arcmsr", /* name */ 248f1c579b1SScott Long }; 249f1c579b1SScott Long #else 250f1c579b1SScott Long #define ARCMSR_CDEV_MAJOR 180 251f1c579b1SScott Long 252f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw = { 253f1c579b1SScott Long arcmsr_open, /* open */ 254f1c579b1SScott Long arcmsr_close, /* close */ 255f1c579b1SScott Long noread, /* read */ 256f1c579b1SScott Long nowrite, /* write */ 257f1c579b1SScott Long arcmsr_ioctl, /* ioctl */ 258f1c579b1SScott Long nopoll, /* poll */ 259f1c579b1SScott Long nommap, /* mmap */ 260f1c579b1SScott Long nostrategy, /* strategy */ 261f1c579b1SScott Long "arcmsr", /* name */ 262f1c579b1SScott Long ARCMSR_CDEV_MAJOR, /* major */ 263f1c579b1SScott Long nodump, /* dump */ 264f1c579b1SScott Long nopsize, /* psize */ 265f1c579b1SScott Long 0 /* flags */ 266f1c579b1SScott Long }; 267f1c579b1SScott Long #endif 268d74001adSXin LI /* 269d74001adSXin LI ************************************************************************** 270d74001adSXin LI ************************************************************************** 271d74001adSXin LI */ 272f1c579b1SScott Long #if __FreeBSD_version < 500005 273f1c579b1SScott Long static int arcmsr_open(dev_t dev, int flags, int fmt, struct proc *proc) 274f1c579b1SScott Long #else 275f1c579b1SScott Long #if __FreeBSD_version < 503000 276f1c579b1SScott Long static int arcmsr_open(dev_t dev, int flags, int fmt, struct thread *proc) 277f1c579b1SScott Long #else 27800b4e54aSWarner Losh static int arcmsr_open(struct cdev *dev, int flags, int fmt, struct thread *proc) 279f1c579b1SScott Long #endif 280f1c579b1SScott Long #endif 281f1c579b1SScott Long { 282f1c579b1SScott Long #if __FreeBSD_version < 503000 283ad6d6297SScott Long struct AdapterControlBlock *acb = dev->si_drv1; 284f1c579b1SScott Long #else 2856bfa9a2dSEd Schouten int unit = dev2unit(dev); 286ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 287f1c579b1SScott Long #endif 288ad6d6297SScott Long if(acb == NULL) { 289f1c579b1SScott Long return ENXIO; 290f1c579b1SScott Long } 291dac36688SXin LI return (0); 292f1c579b1SScott Long } 293f1c579b1SScott Long /* 294f1c579b1SScott Long ************************************************************************** 295f1c579b1SScott Long ************************************************************************** 296f1c579b1SScott Long */ 297f1c579b1SScott Long #if __FreeBSD_version < 500005 298f1c579b1SScott Long static int arcmsr_close(dev_t dev, int flags, int fmt, struct proc *proc) 299f1c579b1SScott Long #else 300f1c579b1SScott Long #if __FreeBSD_version < 503000 301f1c579b1SScott Long static int arcmsr_close(dev_t dev, int flags, int fmt, struct thread *proc) 302f1c579b1SScott Long #else 30300b4e54aSWarner Losh static int arcmsr_close(struct cdev *dev, int flags, int fmt, struct thread *proc) 304f1c579b1SScott Long #endif 305f1c579b1SScott Long #endif 306f1c579b1SScott Long { 307f1c579b1SScott Long #if __FreeBSD_version < 503000 308ad6d6297SScott Long struct AdapterControlBlock *acb = dev->si_drv1; 309f1c579b1SScott Long #else 3106bfa9a2dSEd Schouten int unit = dev2unit(dev); 311ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 312f1c579b1SScott Long #endif 313ad6d6297SScott Long if(acb == NULL) { 314f1c579b1SScott Long return ENXIO; 315f1c579b1SScott Long } 316f1c579b1SScott Long return 0; 317f1c579b1SScott Long } 318f1c579b1SScott Long /* 319f1c579b1SScott Long ************************************************************************** 320f1c579b1SScott Long ************************************************************************** 321f1c579b1SScott Long */ 322f1c579b1SScott Long #if __FreeBSD_version < 500005 323f1c579b1SScott Long static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct proc *proc) 324f1c579b1SScott Long #else 325f1c579b1SScott Long #if __FreeBSD_version < 503000 326f1c579b1SScott Long static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc) 327f1c579b1SScott Long #else 32800b4e54aSWarner Losh static int arcmsr_ioctl(struct cdev *dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc) 329f1c579b1SScott Long #endif 330f1c579b1SScott Long #endif 331f1c579b1SScott Long { 332f1c579b1SScott Long #if __FreeBSD_version < 503000 333ad6d6297SScott Long struct AdapterControlBlock *acb = dev->si_drv1; 334f1c579b1SScott Long #else 3356bfa9a2dSEd Schouten int unit = dev2unit(dev); 336ad6d6297SScott Long struct AdapterControlBlock *acb = devclass_get_softc(arcmsr_devclass, unit); 337f1c579b1SScott Long #endif 338f1c579b1SScott Long 339ad6d6297SScott Long if(acb == NULL) { 340f1c579b1SScott Long return ENXIO; 341f1c579b1SScott Long } 342ad6d6297SScott Long return (arcmsr_iop_ioctlcmd(acb, ioctl_cmd, arg)); 343f1c579b1SScott Long } 344f1c579b1SScott Long /* 34544f05562SScott Long ********************************************************************** 34644f05562SScott Long ********************************************************************** 34744f05562SScott Long */ 34844f05562SScott Long static u_int32_t arcmsr_disable_allintr( struct AdapterControlBlock *acb) 34944f05562SScott Long { 35044f05562SScott Long u_int32_t intmask_org = 0; 35144f05562SScott Long 35244f05562SScott Long switch (acb->adapter_type) { 35344f05562SScott Long case ACB_ADAPTER_TYPE_A: { 35444f05562SScott Long /* disable all outbound interrupt */ 355d74001adSXin LI intmask_org = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intmask); /* disable outbound message0 int */ 356d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); 35744f05562SScott Long } 35844f05562SScott Long break; 35944f05562SScott Long case ACB_ADAPTER_TYPE_B: { 360b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 36144f05562SScott Long /* disable all outbound interrupt */ 362b23a1998SXin LI intmask_org = READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask) 363b23a1998SXin LI & (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); /* disable outbound message0 int */ 364b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask, 0); /* disable all interrupt */ 365d74001adSXin LI } 366d74001adSXin LI break; 367d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 368d74001adSXin LI /* disable all outbound interrupt */ 369d74001adSXin LI intmask_org = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_mask) ; /* disable outbound message0 int */ 370d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org|ARCMSR_HBCMU_ALL_INTMASKENABLE); 37144f05562SScott Long } 37244f05562SScott Long break; 3737a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 3747a7bc959SXin LI /* disable all outbound interrupt */ 3757a7bc959SXin LI intmask_org = CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable) ; /* disable outbound message0 int */ 3767a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, ARCMSR_HBDMU_ALL_INT_DISABLE); 3777a7bc959SXin LI } 3787a7bc959SXin LI break; 37944f05562SScott Long } 38044f05562SScott Long return (intmask_org); 38144f05562SScott Long } 38244f05562SScott Long /* 38344f05562SScott Long ********************************************************************** 38444f05562SScott Long ********************************************************************** 38544f05562SScott Long */ 38644f05562SScott Long static void arcmsr_enable_allintr( struct AdapterControlBlock *acb, u_int32_t intmask_org) 38744f05562SScott Long { 38844f05562SScott Long u_int32_t mask; 38944f05562SScott Long 39044f05562SScott Long switch (acb->adapter_type) { 39144f05562SScott Long case ACB_ADAPTER_TYPE_A: { 39244f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 393d74001adSXin LI mask = ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE); 39444f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org & mask); 39544f05562SScott Long acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; 39644f05562SScott Long } 39744f05562SScott Long break; 39844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 399b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 400d74001adSXin LI /* enable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */ 401d74001adSXin LI mask = (ARCMSR_IOP2DRV_DATA_WRITE_OK|ARCMSR_IOP2DRV_DATA_READ_OK|ARCMSR_IOP2DRV_CDB_DONE|ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); 402b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask, intmask_org | mask); /*1=interrupt enable, 0=interrupt disable*/ 40344f05562SScott Long acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f; 40444f05562SScott Long } 40544f05562SScott Long break; 406d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 407d74001adSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 408d74001adSXin LI mask = ~(ARCMSR_HBCMU_UTILITY_A_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK); 409d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org & mask); 410d74001adSXin LI acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f; 411d74001adSXin LI } 412d74001adSXin LI break; 4137a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 4147a7bc959SXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 4157a7bc959SXin LI mask = ARCMSR_HBDMU_ALL_INT_ENABLE; 4167a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, intmask_org | mask); 4177a7bc959SXin LI CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable); 4187a7bc959SXin LI acb->outbound_int_enable = mask; 4197a7bc959SXin LI } 4207a7bc959SXin LI break; 42144f05562SScott Long } 42244f05562SScott Long } 42344f05562SScott Long /* 42444f05562SScott Long ********************************************************************** 42544f05562SScott Long ********************************************************************** 42644f05562SScott Long */ 42744f05562SScott Long static u_int8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) 42844f05562SScott Long { 42944f05562SScott Long u_int32_t Index; 43044f05562SScott Long u_int8_t Retries = 0x00; 43144f05562SScott Long 43244f05562SScott Long do { 43344f05562SScott Long for(Index=0; Index < 100; Index++) { 434d74001adSXin LI if(CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { 435d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/ 43644f05562SScott Long return TRUE; 43744f05562SScott Long } 43844f05562SScott Long UDELAY(10000); 43944f05562SScott Long }/*max 1 seconds*/ 44044f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 441dac36688SXin LI return (FALSE); 44244f05562SScott Long } 44344f05562SScott Long /* 44444f05562SScott Long ********************************************************************** 44544f05562SScott Long ********************************************************************** 44644f05562SScott Long */ 44744f05562SScott Long static u_int8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) 44844f05562SScott Long { 44944f05562SScott Long u_int32_t Index; 45044f05562SScott Long u_int8_t Retries = 0x00; 451b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 45244f05562SScott Long 45344f05562SScott Long do { 45444f05562SScott Long for(Index=0; Index < 100; Index++) { 455b23a1998SXin LI if(READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { 456b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/ 457b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 458d74001adSXin LI return TRUE; 459d74001adSXin LI } 460d74001adSXin LI UDELAY(10000); 461d74001adSXin LI }/*max 1 seconds*/ 462d74001adSXin LI }while(Retries++ < 20);/*max 20 sec*/ 463dac36688SXin LI return (FALSE); 464d74001adSXin LI } 465d74001adSXin LI /* 466d74001adSXin LI ********************************************************************** 467d74001adSXin LI ********************************************************************** 468d74001adSXin LI */ 469d74001adSXin LI static u_int8_t arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock *acb) 470d74001adSXin LI { 471d74001adSXin LI u_int32_t Index; 472d74001adSXin LI u_int8_t Retries = 0x00; 473d74001adSXin LI 474d74001adSXin LI do { 475d74001adSXin LI for(Index=0; Index < 100; Index++) { 476d74001adSXin LI if(CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { 477d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);/*clear interrupt*/ 47844f05562SScott Long return TRUE; 47944f05562SScott Long } 48044f05562SScott Long UDELAY(10000); 48144f05562SScott Long }/*max 1 seconds*/ 48244f05562SScott Long }while(Retries++ < 20);/*max 20 sec*/ 483dac36688SXin LI return (FALSE); 48444f05562SScott Long } 48544f05562SScott Long /* 4867a7bc959SXin LI ********************************************************************** 4877a7bc959SXin LI ********************************************************************** 4887a7bc959SXin LI */ 4897a7bc959SXin LI static u_int8_t arcmsr_hbd_wait_msgint_ready(struct AdapterControlBlock *acb) 4907a7bc959SXin LI { 4917a7bc959SXin LI u_int32_t Index; 4927a7bc959SXin LI u_int8_t Retries = 0x00; 4937a7bc959SXin LI 4947a7bc959SXin LI do { 4957a7bc959SXin LI for(Index=0; Index < 100; Index++) { 4967a7bc959SXin LI if(CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) { 4977a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR);/*clear interrupt*/ 4987a7bc959SXin LI return TRUE; 4997a7bc959SXin LI } 5007a7bc959SXin LI UDELAY(10000); 5017a7bc959SXin LI }/*max 1 seconds*/ 5027a7bc959SXin LI }while(Retries++ < 20);/*max 20 sec*/ 5037a7bc959SXin LI return (FALSE); 5047a7bc959SXin LI } 5057a7bc959SXin LI /* 50644f05562SScott Long ************************************************************************ 50744f05562SScott Long ************************************************************************ 50844f05562SScott Long */ 50944f05562SScott Long static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) 51044f05562SScott Long { 51144f05562SScott Long int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ 51244f05562SScott Long 513d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 51444f05562SScott Long do { 51544f05562SScott Long if(arcmsr_hba_wait_msgint_ready(acb)) { 51644f05562SScott Long break; 51744f05562SScott Long } else { 51844f05562SScott Long retry_count--; 51944f05562SScott Long } 52044f05562SScott Long }while(retry_count != 0); 52144f05562SScott Long } 52244f05562SScott Long /* 52344f05562SScott Long ************************************************************************ 52444f05562SScott Long ************************************************************************ 52544f05562SScott Long */ 52644f05562SScott Long static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) 52744f05562SScott Long { 52844f05562SScott Long int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ 529b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 53044f05562SScott Long 531b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_FLUSH_CACHE); 53244f05562SScott Long do { 53344f05562SScott Long if(arcmsr_hbb_wait_msgint_ready(acb)) { 53444f05562SScott Long break; 53544f05562SScott Long } else { 53644f05562SScott Long retry_count--; 53744f05562SScott Long } 53844f05562SScott Long }while(retry_count != 0); 53944f05562SScott Long } 54044f05562SScott Long /* 54144f05562SScott Long ************************************************************************ 54244f05562SScott Long ************************************************************************ 54344f05562SScott Long */ 544d74001adSXin LI static void arcmsr_flush_hbc_cache(struct AdapterControlBlock *acb) 545d74001adSXin LI { 546d74001adSXin LI int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */ 547d74001adSXin LI 548d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 549d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 550d74001adSXin LI do { 551d74001adSXin LI if(arcmsr_hbc_wait_msgint_ready(acb)) { 552d74001adSXin LI break; 553d74001adSXin LI } else { 554d74001adSXin LI retry_count--; 555d74001adSXin LI } 556d74001adSXin LI }while(retry_count != 0); 557d74001adSXin LI } 558d74001adSXin LI /* 559d74001adSXin LI ************************************************************************ 560d74001adSXin LI ************************************************************************ 561d74001adSXin LI */ 5627a7bc959SXin LI static void arcmsr_flush_hbd_cache(struct AdapterControlBlock *acb) 5637a7bc959SXin LI { 5647a7bc959SXin LI int retry_count = 30; /* enlarge wait flush adapter cache time: 10 minute */ 5657a7bc959SXin LI 5667a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 5677a7bc959SXin LI do { 5687a7bc959SXin LI if(arcmsr_hbd_wait_msgint_ready(acb)) { 5697a7bc959SXin LI break; 5707a7bc959SXin LI } else { 5717a7bc959SXin LI retry_count--; 5727a7bc959SXin LI } 5737a7bc959SXin LI }while(retry_count != 0); 5747a7bc959SXin LI } 5757a7bc959SXin LI /* 5767a7bc959SXin LI ************************************************************************ 5777a7bc959SXin LI ************************************************************************ 5787a7bc959SXin LI */ 57944f05562SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) 58044f05562SScott Long { 58144f05562SScott Long switch (acb->adapter_type) { 58244f05562SScott Long case ACB_ADAPTER_TYPE_A: { 58344f05562SScott Long arcmsr_flush_hba_cache(acb); 58444f05562SScott Long } 58544f05562SScott Long break; 58644f05562SScott Long case ACB_ADAPTER_TYPE_B: { 58744f05562SScott Long arcmsr_flush_hbb_cache(acb); 58844f05562SScott Long } 58944f05562SScott Long break; 590d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 591d74001adSXin LI arcmsr_flush_hbc_cache(acb); 592d74001adSXin LI } 593d74001adSXin LI break; 5947a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 5957a7bc959SXin LI arcmsr_flush_hbd_cache(acb); 5967a7bc959SXin LI } 5977a7bc959SXin LI break; 59844f05562SScott Long } 59944f05562SScott Long } 60044f05562SScott Long /* 601ad6d6297SScott Long ******************************************************************************* 602ad6d6297SScott Long ******************************************************************************* 603f1c579b1SScott Long */ 604ad6d6297SScott Long static int arcmsr_suspend(device_t dev) 605f1c579b1SScott Long { 606ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 607f1c579b1SScott Long 608ad6d6297SScott Long /* flush controller */ 609ad6d6297SScott Long arcmsr_iop_parking(acb); 610d74001adSXin LI /* disable all outbound interrupt */ 611d74001adSXin LI arcmsr_disable_allintr(acb); 612ad6d6297SScott Long return(0); 613ad6d6297SScott Long } 614ad6d6297SScott Long /* 615ad6d6297SScott Long ******************************************************************************* 616ad6d6297SScott Long ******************************************************************************* 617ad6d6297SScott Long */ 618ad6d6297SScott Long static int arcmsr_resume(device_t dev) 619ad6d6297SScott Long { 620ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 621f1c579b1SScott Long 622ad6d6297SScott Long arcmsr_iop_init(acb); 623ad6d6297SScott Long return(0); 624f1c579b1SScott Long } 625f1c579b1SScott Long /* 626f1c579b1SScott Long ********************************************************************************* 627f1c579b1SScott Long ********************************************************************************* 628f1c579b1SScott Long */ 629ad6d6297SScott Long static void arcmsr_async(void *cb_arg, u_int32_t code, struct cam_path *path, void *arg) 630f1c579b1SScott Long { 631ad6d6297SScott Long struct AdapterControlBlock *acb; 632ad6d6297SScott Long u_int8_t target_id, target_lun; 633f1c579b1SScott Long struct cam_sim *sim; 634f1c579b1SScott Long 635f1c579b1SScott Long sim = (struct cam_sim *) cb_arg; 636ad6d6297SScott Long acb =(struct AdapterControlBlock *) cam_sim_softc(sim); 637ad6d6297SScott Long switch (code) { 638f1c579b1SScott Long case AC_LOST_DEVICE: 639f1c579b1SScott Long target_id = xpt_path_target_id(path); 640f1c579b1SScott Long target_lun = xpt_path_lun_id(path); 641d74001adSXin LI if((target_id > ARCMSR_MAX_TARGETID) || (target_lun > ARCMSR_MAX_TARGETLUN)) { 642f1c579b1SScott Long break; 643f1c579b1SScott Long } 644dac36688SXin LI // printf("%s:scsi id=%d lun=%d device lost \n", device_get_name(acb->pci_dev), target_id, target_lun); 645f1c579b1SScott Long break; 646f1c579b1SScott Long default: 647f1c579b1SScott Long break; 648f1c579b1SScott Long } 649f1c579b1SScott Long } 650f1c579b1SScott Long /* 651f1c579b1SScott Long ********************************************************************** 652f1c579b1SScott Long ********************************************************************** 653f1c579b1SScott Long */ 654ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb) 655f1c579b1SScott Long { 656ad6d6297SScott Long union ccb *pccb = srb->pccb; 657f1c579b1SScott Long 658ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 659ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 660dac36688SXin LI if(pccb->csio.sense_len) { 661ad6d6297SScott Long memset(&pccb->csio.sense_data, 0, sizeof(pccb->csio.sense_data)); 662ad6d6297SScott Long memcpy(&pccb->csio.sense_data, srb->arcmsr_cdb.SenseData, 663ad6d6297SScott Long get_min(sizeof(struct SENSE_DATA), sizeof(pccb->csio.sense_data))); 664ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); /* Valid,ErrorCode */ 665f1c579b1SScott Long pccb->ccb_h.status |= CAM_AUTOSNS_VALID; 666f1c579b1SScott Long } 667f1c579b1SScott Long } 668f1c579b1SScott Long /* 669f1c579b1SScott Long ********************************************************************* 67044f05562SScott Long ********************************************************************* 67144f05562SScott Long */ 67244f05562SScott Long static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) 67344f05562SScott Long { 67444f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 67544f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 676d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 67744f05562SScott Long } 67844f05562SScott Long } 67944f05562SScott Long /* 68044f05562SScott Long ********************************************************************* 68144f05562SScott Long ********************************************************************* 68244f05562SScott Long */ 68344f05562SScott Long static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) 68444f05562SScott Long { 685b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 686b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_ABORT_CMD); 68744f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 688d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 689d74001adSXin LI } 690d74001adSXin LI } 691d74001adSXin LI /* 692d74001adSXin LI ********************************************************************* 693d74001adSXin LI ********************************************************************* 694d74001adSXin LI */ 695d74001adSXin LI static void arcmsr_abort_hbc_allcmd(struct AdapterControlBlock *acb) 696d74001adSXin LI { 697d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 698d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 699d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 700d74001adSXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 70144f05562SScott Long } 70244f05562SScott Long } 70344f05562SScott Long /* 70444f05562SScott Long ********************************************************************* 705f1c579b1SScott Long ********************************************************************* 706f1c579b1SScott Long */ 7077a7bc959SXin LI static void arcmsr_abort_hbd_allcmd(struct AdapterControlBlock *acb) 7087a7bc959SXin LI { 7097a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD); 7107a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 7117a7bc959SXin LI printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit); 7127a7bc959SXin LI } 7137a7bc959SXin LI } 7147a7bc959SXin LI /* 7157a7bc959SXin LI ********************************************************************* 7167a7bc959SXin LI ********************************************************************* 7177a7bc959SXin LI */ 718ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) 719f1c579b1SScott Long { 72044f05562SScott Long switch (acb->adapter_type) { 72144f05562SScott Long case ACB_ADAPTER_TYPE_A: { 72244f05562SScott Long arcmsr_abort_hba_allcmd(acb); 72344f05562SScott Long } 72444f05562SScott Long break; 72544f05562SScott Long case ACB_ADAPTER_TYPE_B: { 72644f05562SScott Long arcmsr_abort_hbb_allcmd(acb); 72744f05562SScott Long } 72844f05562SScott Long break; 729d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 730d74001adSXin LI arcmsr_abort_hbc_allcmd(acb); 731d74001adSXin LI } 732d74001adSXin LI break; 7337a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 7347a7bc959SXin LI arcmsr_abort_hbd_allcmd(acb); 7357a7bc959SXin LI } 7367a7bc959SXin LI break; 73744f05562SScott Long } 73844f05562SScott Long } 73944f05562SScott Long /* 740231c8b71SXin LI ********************************************************************** 741231c8b71SXin LI ********************************************************************** 742231c8b71SXin LI */ 743231c8b71SXin LI static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag) 744231c8b71SXin LI { 745231c8b71SXin LI struct AdapterControlBlock *acb = srb->acb; 746231c8b71SXin LI union ccb *pccb = srb->pccb; 747231c8b71SXin LI 74822f2616bSXin LI if(srb->srb_flags & SRB_FLAG_TIMER_START) 74922f2616bSXin LI callout_stop(&srb->ccb_callout); 750231c8b71SXin LI if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 751231c8b71SXin LI bus_dmasync_op_t op; 752231c8b71SXin LI 753231c8b71SXin LI if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 754231c8b71SXin LI op = BUS_DMASYNC_POSTREAD; 755231c8b71SXin LI } else { 756231c8b71SXin LI op = BUS_DMASYNC_POSTWRITE; 757231c8b71SXin LI } 758231c8b71SXin LI bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 759231c8b71SXin LI bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 760231c8b71SXin LI } 761231c8b71SXin LI if(stand_flag == 1) { 762231c8b71SXin LI atomic_subtract_int(&acb->srboutstandingcount, 1); 763231c8b71SXin LI if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) && ( 764abfdbca9SXin LI acb->srboutstandingcount < (acb->maxOutstanding -10))) { 765231c8b71SXin LI acb->acb_flags &= ~ACB_F_CAM_DEV_QFRZN; 766231c8b71SXin LI pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 767231c8b71SXin LI } 768231c8b71SXin LI } 76922f2616bSXin LI if(srb->srb_state != ARCMSR_SRB_TIMEOUT) 77022f2616bSXin LI arcmsr_free_srb(srb); 77122f2616bSXin LI acb->pktReturnCount++; 772231c8b71SXin LI xpt_done(pccb); 773231c8b71SXin LI } 774231c8b71SXin LI /* 77544f05562SScott Long ************************************************************************** 77644f05562SScott Long ************************************************************************** 77744f05562SScott Long */ 778d74001adSXin LI static void arcmsr_report_srb_state(struct AdapterControlBlock *acb, struct CommandControlBlock *srb, u_int16_t error) 77944f05562SScott Long { 78044f05562SScott Long int target, lun; 78144f05562SScott Long 78244f05562SScott Long target = srb->pccb->ccb_h.target_id; 78344f05562SScott Long lun = srb->pccb->ccb_h.target_lun; 784d74001adSXin LI if(error == FALSE) { 78544f05562SScott Long if(acb->devstate[target][lun] == ARECA_RAID_GONE) { 78644f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GOOD; 78744f05562SScott Long } 78844f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_CMP; 78944f05562SScott Long arcmsr_srb_complete(srb, 1); 79044f05562SScott Long } else { 79144f05562SScott Long switch(srb->arcmsr_cdb.DeviceStatus) { 79244f05562SScott Long case ARCMSR_DEV_SELECT_TIMEOUT: { 79344f05562SScott Long if(acb->devstate[target][lun] == ARECA_RAID_GOOD) { 794d74001adSXin LI printf( "arcmsr%d: Target=%x, Lun=%x, selection timeout, raid volume was lost\n", acb->pci_unit, target, lun); 795ad6d6297SScott Long } 79644f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GONE; 797d74001adSXin LI srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 79844f05562SScott Long arcmsr_srb_complete(srb, 1); 79944f05562SScott Long } 80044f05562SScott Long break; 80144f05562SScott Long case ARCMSR_DEV_ABORTED: 80244f05562SScott Long case ARCMSR_DEV_INIT_FAIL: { 80344f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GONE; 80444f05562SScott Long srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 80544f05562SScott Long arcmsr_srb_complete(srb, 1); 80644f05562SScott Long } 80744f05562SScott Long break; 80844f05562SScott Long case SCSISTAT_CHECK_CONDITION: { 80944f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GOOD; 81044f05562SScott Long arcmsr_report_sense_info(srb); 81144f05562SScott Long arcmsr_srb_complete(srb, 1); 81244f05562SScott Long } 81344f05562SScott Long break; 81444f05562SScott Long default: 81510d66948SKevin Lo printf("arcmsr%d: scsi id=%d lun=%d isr got command error done,but got unknown DeviceStatus=0x%x \n" 816d74001adSXin LI , acb->pci_unit, target, lun ,srb->arcmsr_cdb.DeviceStatus); 81744f05562SScott Long acb->devstate[target][lun] = ARECA_RAID_GONE; 81844f05562SScott Long srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY; 81910d66948SKevin Lo /*unknown error or crc error just for retry*/ 82044f05562SScott Long arcmsr_srb_complete(srb, 1); 82144f05562SScott Long break; 82244f05562SScott Long } 82344f05562SScott Long } 82444f05562SScott Long } 82544f05562SScott Long /* 82644f05562SScott Long ************************************************************************** 82744f05562SScott Long ************************************************************************** 82844f05562SScott Long */ 829d74001adSXin LI static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t flag_srb, u_int16_t error) 83044f05562SScott Long { 83144f05562SScott Long struct CommandControlBlock *srb; 83244f05562SScott Long 83344f05562SScott Long /* check if command done with no error*/ 834d74001adSXin LI switch (acb->adapter_type) { 835d74001adSXin LI case ACB_ADAPTER_TYPE_C: 8367a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 83722f2616bSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0)); /*frame must be 32 bytes aligned*/ 838d74001adSXin LI break; 839d74001adSXin LI case ACB_ADAPTER_TYPE_A: 840d74001adSXin LI case ACB_ADAPTER_TYPE_B: 841d74001adSXin LI default: 842d74001adSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 843d74001adSXin LI break; 844d74001adSXin LI } 84522f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 84622f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_TIMEOUT) { 84722f2616bSXin LI arcmsr_free_srb(srb); 84822f2616bSXin LI printf("arcmsr%d: srb='%p' return srb has been timeouted\n", acb->pci_unit, srb); 84944f05562SScott Long return; 85044f05562SScott Long } 85122f2616bSXin LI printf("arcmsr%d: return srb has been completed\n" 85222f2616bSXin LI "srb='%p' srb_state=0x%x outstanding srb count=%d \n", 85322f2616bSXin LI acb->pci_unit, srb, srb->srb_state, acb->srboutstandingcount); 85444f05562SScott Long return; 85544f05562SScott Long } 856d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 85744f05562SScott Long } 85844f05562SScott Long /* 85922f2616bSXin LI ************************************************************************** 86022f2616bSXin LI ************************************************************************** 86122f2616bSXin LI */ 86222f2616bSXin LI static void arcmsr_srb_timeout(void *arg) 86322f2616bSXin LI { 86422f2616bSXin LI struct CommandControlBlock *srb = (struct CommandControlBlock *)arg; 86522f2616bSXin LI struct AdapterControlBlock *acb; 86622f2616bSXin LI int target, lun; 86722f2616bSXin LI u_int8_t cmd; 86822f2616bSXin LI 86922f2616bSXin LI target = srb->pccb->ccb_h.target_id; 87022f2616bSXin LI lun = srb->pccb->ccb_h.target_lun; 87122f2616bSXin LI acb = srb->acb; 8727a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 87322f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) 87422f2616bSXin LI { 875*4aa947cbSWarner Losh cmd = scsiio_cdb_ptr(&srb->pccb->csio)[0]; 87622f2616bSXin LI srb->srb_state = ARCMSR_SRB_TIMEOUT; 87722f2616bSXin LI srb->pccb->ccb_h.status |= CAM_CMD_TIMEOUT; 87822f2616bSXin LI arcmsr_srb_complete(srb, 1); 87922f2616bSXin LI printf("arcmsr%d: scsi id %d lun %d cmd=0x%x srb='%p' ccb command time out!\n", 88022f2616bSXin LI acb->pci_unit, target, lun, cmd, srb); 88122f2616bSXin LI } 8827a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 88322f2616bSXin LI #ifdef ARCMSR_DEBUG1 88422f2616bSXin LI arcmsr_dump_data(acb); 88522f2616bSXin LI #endif 88622f2616bSXin LI } 88722f2616bSXin LI 88822f2616bSXin LI /* 88944f05562SScott Long ********************************************************************** 89044f05562SScott Long ********************************************************************** 89144f05562SScott Long */ 89244f05562SScott Long static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) 89344f05562SScott Long { 89444f05562SScott Long int i=0; 89544f05562SScott Long u_int32_t flag_srb; 896d74001adSXin LI u_int16_t error; 89744f05562SScott Long 89844f05562SScott Long switch (acb->adapter_type) { 89944f05562SScott Long case ACB_ADAPTER_TYPE_A: { 90044f05562SScott Long u_int32_t outbound_intstatus; 90144f05562SScott Long 90244f05562SScott Long /*clear and abort all outbound posted Q*/ 903d74001adSXin LI outbound_intstatus = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 904d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/ 905d74001adSXin LI while(((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_queueport)) != 0xFFFFFFFF) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { 906d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 907d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 90844f05562SScott Long } 90944f05562SScott Long } 91044f05562SScott Long break; 91144f05562SScott Long case ACB_ADAPTER_TYPE_B: { 91244f05562SScott Long struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu; 91344f05562SScott Long 91444f05562SScott Long /*clear all outbound posted Q*/ 915b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 91644f05562SScott Long for(i=0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) { 91744f05562SScott Long if((flag_srb = phbbmu->done_qbuffer[i]) != 0) { 91844f05562SScott Long phbbmu->done_qbuffer[i] = 0; 919d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 920d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 92144f05562SScott Long } 92244f05562SScott Long phbbmu->post_qbuffer[i] = 0; 92344f05562SScott Long }/*drain reply FIFO*/ 92444f05562SScott Long phbbmu->doneq_index = 0; 92544f05562SScott Long phbbmu->postq_index = 0; 92644f05562SScott Long } 92744f05562SScott Long break; 928d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 929d74001adSXin LI 930d74001adSXin LI while((CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { 931d74001adSXin LI flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 932d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 933d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 934d74001adSXin LI } 935d74001adSXin LI } 936d74001adSXin LI break; 9377a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 9387a7bc959SXin LI arcmsr_hbd_postqueue_isr(acb); 9397a7bc959SXin LI } 9407a7bc959SXin LI break; 94144f05562SScott Long } 942f1c579b1SScott Long } 943f1c579b1SScott Long /* 944f1c579b1SScott Long **************************************************************************** 945f1c579b1SScott Long **************************************************************************** 946f1c579b1SScott Long */ 947ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb) 948f1c579b1SScott Long { 949ad6d6297SScott Long struct CommandControlBlock *srb; 95044f05562SScott Long u_int32_t intmask_org; 951ad6d6297SScott Long u_int32_t i=0; 952f1c579b1SScott Long 95344f05562SScott Long if(acb->srboutstandingcount>0) { 95444f05562SScott Long /* disable all outbound interrupt */ 95544f05562SScott Long intmask_org = arcmsr_disable_allintr(acb); 95644f05562SScott Long /*clear and abort all outbound posted Q*/ 95744f05562SScott Long arcmsr_done4abort_postqueue(acb); 958f1c579b1SScott Long /* talk to iop 331 outstanding command aborted*/ 959ad6d6297SScott Long arcmsr_abort_allcmd(acb); 960ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 961ad6d6297SScott Long srb = acb->psrb_pool[i]; 96222f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) { 96322f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 964ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 965ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 966123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p' aborted\n" 96722f2616bSXin LI , acb->pci_unit, srb->pccb->ccb_h.target_id 968123055f0SNathan Whitehorn , (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 969f1c579b1SScott Long } 970f1c579b1SScott Long } 971f1c579b1SScott Long /* enable all outbound interrupt */ 97244f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 973f1c579b1SScott Long } 97422f2616bSXin LI acb->srboutstandingcount = 0; 975ad6d6297SScott Long acb->workingsrb_doneindex = 0; 976ad6d6297SScott Long acb->workingsrb_startindex = 0; 97722f2616bSXin LI acb->pktRequestCount = 0; 97822f2616bSXin LI acb->pktReturnCount = 0; 979f1c579b1SScott Long } 980f1c579b1SScott Long /* 981f1c579b1SScott Long ********************************************************************** 982f1c579b1SScott Long ********************************************************************** 983f1c579b1SScott Long */ 98444f05562SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, 98544f05562SScott Long bus_dma_segment_t *dm_segs, u_int32_t nseg) 986f1c579b1SScott Long { 987ad6d6297SScott Long struct ARCMSR_CDB *arcmsr_cdb = &srb->arcmsr_cdb; 988ad6d6297SScott Long u_int8_t *psge = (u_int8_t *)&arcmsr_cdb->u; 989ad6d6297SScott Long u_int32_t address_lo, address_hi; 990ad6d6297SScott Long union ccb *pccb = srb->pccb; 991f1c579b1SScott Long struct ccb_scsiio *pcsio = &pccb->csio; 992ad6d6297SScott Long u_int32_t arccdbsize = 0x30; 993f1c579b1SScott Long 994ad6d6297SScott Long memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB)); 995ad6d6297SScott Long arcmsr_cdb->Bus = 0; 996ad6d6297SScott Long arcmsr_cdb->TargetID = pccb->ccb_h.target_id; 997ad6d6297SScott Long arcmsr_cdb->LUN = pccb->ccb_h.target_lun; 998ad6d6297SScott Long arcmsr_cdb->Function = 1; 999ad6d6297SScott Long arcmsr_cdb->CdbLength = (u_int8_t)pcsio->cdb_len; 1000*4aa947cbSWarner Losh bcopy(scsiio_cdb_ptr(pcsio), arcmsr_cdb->Cdb, pcsio->cdb_len); 1001ad6d6297SScott Long if(nseg != 0) { 1002ad6d6297SScott Long struct AdapterControlBlock *acb = srb->acb; 1003f1c579b1SScott Long bus_dmasync_op_t op; 1004ad6d6297SScott Long u_int32_t length, i, cdb_sgcount = 0; 1005f1c579b1SScott Long 1006ad6d6297SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 1007ad6d6297SScott Long op = BUS_DMASYNC_PREREAD; 1008ad6d6297SScott Long } else { 1009ad6d6297SScott Long op = BUS_DMASYNC_PREWRITE; 1010ad6d6297SScott Long arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE; 1011ad6d6297SScott Long srb->srb_flags |= SRB_FLAG_WRITE; 1012ad6d6297SScott Long } 1013ad6d6297SScott Long bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op); 1014ad6d6297SScott Long for(i=0; i < nseg; i++) { 1015f1c579b1SScott Long /* Get the physical address of the current data pointer */ 1016ad6d6297SScott Long length = arcmsr_htole32(dm_segs[i].ds_len); 1017ad6d6297SScott Long address_lo = arcmsr_htole32(dma_addr_lo32(dm_segs[i].ds_addr)); 1018ad6d6297SScott Long address_hi = arcmsr_htole32(dma_addr_hi32(dm_segs[i].ds_addr)); 1019ad6d6297SScott Long if(address_hi == 0) { 1020ad6d6297SScott Long struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge; 1021f1c579b1SScott Long pdma_sg->address = address_lo; 1022f1c579b1SScott Long pdma_sg->length = length; 1023ad6d6297SScott Long psge += sizeof(struct SG32ENTRY); 1024ad6d6297SScott Long arccdbsize += sizeof(struct SG32ENTRY); 1025ad6d6297SScott Long } else { 1026ad6d6297SScott Long u_int32_t sg64s_size = 0, tmplength = length; 1027f1c579b1SScott Long 1028ad6d6297SScott Long while(1) { 1029ad6d6297SScott Long u_int64_t span4G, length0; 1030ad6d6297SScott Long struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge; 1031f1c579b1SScott Long 1032ad6d6297SScott Long span4G = (u_int64_t)address_lo + tmplength; 1033f1c579b1SScott Long pdma_sg->addresshigh = address_hi; 1034f1c579b1SScott Long pdma_sg->address = address_lo; 1035ad6d6297SScott Long if(span4G > 0x100000000) { 1036f1c579b1SScott Long /*see if cross 4G boundary*/ 1037f1c579b1SScott Long length0 = 0x100000000-address_lo; 1038ad6d6297SScott Long pdma_sg->length = (u_int32_t)length0 | IS_SG64_ADDR; 1039f1c579b1SScott Long address_hi = address_hi+1; 1040f1c579b1SScott Long address_lo = 0; 1041ad6d6297SScott Long tmplength = tmplength - (u_int32_t)length0; 1042ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 1043ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 1044f1c579b1SScott Long cdb_sgcount++; 1045ad6d6297SScott Long } else { 1046f1c579b1SScott Long pdma_sg->length = tmplength | IS_SG64_ADDR; 1047ad6d6297SScott Long sg64s_size += sizeof(struct SG64ENTRY); 1048ad6d6297SScott Long psge += sizeof(struct SG64ENTRY); 1049f1c579b1SScott Long break; 1050f1c579b1SScott Long } 1051f1c579b1SScott Long } 1052f1c579b1SScott Long arccdbsize += sg64s_size; 1053f1c579b1SScott Long } 1054f1c579b1SScott Long cdb_sgcount++; 1055f1c579b1SScott Long } 1056ad6d6297SScott Long arcmsr_cdb->sgcount = (u_int8_t)cdb_sgcount; 1057ad6d6297SScott Long arcmsr_cdb->DataLength = pcsio->dxfer_len; 1058ad6d6297SScott Long if( arccdbsize > 256) { 1059ad6d6297SScott Long arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE; 1060f1c579b1SScott Long } 1061d74001adSXin LI } else { 1062d74001adSXin LI arcmsr_cdb->DataLength = 0; 1063f1c579b1SScott Long } 1064d74001adSXin LI srb->arc_cdb_size = arccdbsize; 10657a7bc959SXin LI arcmsr_cdb->msgPages = (arccdbsize/256) + ((arccdbsize % 256) ? 1 : 0); 1066f1c579b1SScott Long } 1067f1c579b1SScott Long /* 1068f1c579b1SScott Long ************************************************************************** 1069f1c579b1SScott Long ************************************************************************** 1070f1c579b1SScott Long */ 1071ad6d6297SScott Long static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandControlBlock *srb) 1072f1c579b1SScott Long { 10737a7bc959SXin LI u_int32_t cdb_phyaddr_low = (u_int32_t) srb->cdb_phyaddr_low; 1074ad6d6297SScott Long struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&srb->arcmsr_cdb; 1075f1c579b1SScott Long 1076d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, (srb->srb_flags & SRB_FLAG_WRITE) ? BUS_DMASYNC_POSTWRITE:BUS_DMASYNC_POSTREAD); 1077ad6d6297SScott Long atomic_add_int(&acb->srboutstandingcount, 1); 107822f2616bSXin LI srb->srb_state = ARCMSR_SRB_START; 1079d74001adSXin LI 108044f05562SScott Long switch (acb->adapter_type) { 108144f05562SScott Long case ACB_ADAPTER_TYPE_A: { 1082ad6d6297SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 10837a7bc959SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_phyaddr_low|ARCMSR_SRBPOST_FLAG_SGL_BSIZE); 1084ad6d6297SScott Long } else { 10857a7bc959SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_phyaddr_low); 108644f05562SScott Long } 108744f05562SScott Long } 108844f05562SScott Long break; 108944f05562SScott Long case ACB_ADAPTER_TYPE_B: { 109044f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 109144f05562SScott Long int ending_index, index; 109244f05562SScott Long 109344f05562SScott Long index = phbbmu->postq_index; 109444f05562SScott Long ending_index = ((index+1) % ARCMSR_MAX_HBB_POSTQUEUE); 109544f05562SScott Long phbbmu->post_qbuffer[ending_index] = 0; 109644f05562SScott Long if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { 10977a7bc959SXin LI phbbmu->post_qbuffer[index] = cdb_phyaddr_low | ARCMSR_SRBPOST_FLAG_SGL_BSIZE; 109844f05562SScott Long } else { 10997a7bc959SXin LI phbbmu->post_qbuffer[index] = cdb_phyaddr_low; 110044f05562SScott Long } 110144f05562SScott Long index++; 110244f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 110344f05562SScott Long phbbmu->postq_index = index; 1104b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED); 1105d74001adSXin LI } 1106d74001adSXin LI break; 11077a7bc959SXin LI case ACB_ADAPTER_TYPE_C: { 1108d74001adSXin LI u_int32_t ccb_post_stamp, arc_cdb_size, cdb_phyaddr_hi32; 1109d74001adSXin LI 1110d74001adSXin LI arc_cdb_size = (srb->arc_cdb_size > 0x300) ? 0x300 : srb->arc_cdb_size; 11117a7bc959SXin LI ccb_post_stamp = (cdb_phyaddr_low | ((arc_cdb_size-1) >> 6) | 1); 1112d74001adSXin LI cdb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high; 1113d74001adSXin LI if(cdb_phyaddr_hi32) 1114d74001adSXin LI { 1115d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_high, cdb_phyaddr_hi32); 1116d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp); 1117d74001adSXin LI } 1118d74001adSXin LI else 1119d74001adSXin LI { 1120d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp); 1121d74001adSXin LI } 112244f05562SScott Long } 112344f05562SScott Long break; 11247a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 11257a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 11267a7bc959SXin LI u_int16_t index_stripped; 11277a7bc959SXin LI u_int16_t postq_index; 11287a7bc959SXin LI struct InBound_SRB *pinbound_srb; 11297a7bc959SXin LI 11307a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->postDone_lock); 11317a7bc959SXin LI postq_index = phbdmu->postq_index; 11327a7bc959SXin LI pinbound_srb = (struct InBound_SRB *)&phbdmu->post_qbuffer[postq_index & 0xFF]; 11337a7bc959SXin LI pinbound_srb->addressHigh = srb->cdb_phyaddr_high; 11347a7bc959SXin LI pinbound_srb->addressLow = srb->cdb_phyaddr_low; 11357a7bc959SXin LI pinbound_srb->length = srb->arc_cdb_size >> 2; 11367a7bc959SXin LI arcmsr_cdb->Context = srb->cdb_phyaddr_low; 11377a7bc959SXin LI if (postq_index & 0x4000) { 11387a7bc959SXin LI index_stripped = postq_index & 0xFF; 11397a7bc959SXin LI index_stripped += 1; 11407a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 11417a7bc959SXin LI phbdmu->postq_index = index_stripped ? (index_stripped | 0x4000) : index_stripped; 11427a7bc959SXin LI } else { 11437a7bc959SXin LI index_stripped = postq_index; 11447a7bc959SXin LI index_stripped += 1; 11457a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 11467a7bc959SXin LI phbdmu->postq_index = index_stripped ? index_stripped : (index_stripped | 0x4000); 11477a7bc959SXin LI } 11487a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inboundlist_write_pointer, postq_index); 11497a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->postDone_lock); 11507a7bc959SXin LI } 11517a7bc959SXin LI break; 1152f1c579b1SScott Long } 1153f1c579b1SScott Long } 1154f1c579b1SScott Long /* 115544f05562SScott Long ************************************************************************ 115644f05562SScott Long ************************************************************************ 115744f05562SScott Long */ 115844f05562SScott Long static struct QBUFFER *arcmsr_get_iop_rqbuffer( struct AdapterControlBlock *acb) 115944f05562SScott Long { 116044f05562SScott Long struct QBUFFER *qbuffer=NULL; 116144f05562SScott Long 116244f05562SScott Long switch (acb->adapter_type) { 116344f05562SScott Long case ACB_ADAPTER_TYPE_A: { 116444f05562SScott Long struct HBA_MessageUnit *phbamu = (struct HBA_MessageUnit *)acb->pmu; 116544f05562SScott Long 116644f05562SScott Long qbuffer = (struct QBUFFER *)&phbamu->message_rbuffer; 116744f05562SScott Long } 116844f05562SScott Long break; 116944f05562SScott Long case ACB_ADAPTER_TYPE_B: { 117044f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 117144f05562SScott Long 117244f05562SScott Long qbuffer = (struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_rbuffer; 117344f05562SScott Long } 117444f05562SScott Long break; 1175d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1176d74001adSXin LI struct HBC_MessageUnit *phbcmu = (struct HBC_MessageUnit *)acb->pmu; 1177d74001adSXin LI 1178d74001adSXin LI qbuffer = (struct QBUFFER *)&phbcmu->message_rbuffer; 1179d74001adSXin LI } 1180d74001adSXin LI break; 11817a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 11827a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 11837a7bc959SXin LI 11847a7bc959SXin LI qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_rbuffer; 11857a7bc959SXin LI } 11867a7bc959SXin LI break; 118744f05562SScott Long } 118844f05562SScott Long return(qbuffer); 118944f05562SScott Long } 119044f05562SScott Long /* 119144f05562SScott Long ************************************************************************ 119244f05562SScott Long ************************************************************************ 119344f05562SScott Long */ 119444f05562SScott Long static struct QBUFFER *arcmsr_get_iop_wqbuffer( struct AdapterControlBlock *acb) 119544f05562SScott Long { 119644f05562SScott Long struct QBUFFER *qbuffer = NULL; 119744f05562SScott Long 119844f05562SScott Long switch (acb->adapter_type) { 119944f05562SScott Long case ACB_ADAPTER_TYPE_A: { 120044f05562SScott Long struct HBA_MessageUnit *phbamu = (struct HBA_MessageUnit *)acb->pmu; 120144f05562SScott Long 120244f05562SScott Long qbuffer = (struct QBUFFER *)&phbamu->message_wbuffer; 120344f05562SScott Long } 120444f05562SScott Long break; 120544f05562SScott Long case ACB_ADAPTER_TYPE_B: { 120644f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 120744f05562SScott Long 120844f05562SScott Long qbuffer = (struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_wbuffer; 120944f05562SScott Long } 121044f05562SScott Long break; 1211d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1212d74001adSXin LI struct HBC_MessageUnit *phbcmu = (struct HBC_MessageUnit *)acb->pmu; 1213d74001adSXin LI 1214d74001adSXin LI qbuffer = (struct QBUFFER *)&phbcmu->message_wbuffer; 1215d74001adSXin LI } 1216d74001adSXin LI break; 12177a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 12187a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 12197a7bc959SXin LI 12207a7bc959SXin LI qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_wbuffer; 12217a7bc959SXin LI } 12227a7bc959SXin LI break; 122344f05562SScott Long } 122444f05562SScott Long return(qbuffer); 122544f05562SScott Long } 122644f05562SScott Long /* 122744f05562SScott Long ************************************************************************** 122844f05562SScott Long ************************************************************************** 122944f05562SScott Long */ 123044f05562SScott Long static void arcmsr_iop_message_read(struct AdapterControlBlock *acb) 123144f05562SScott Long { 123244f05562SScott Long switch (acb->adapter_type) { 123344f05562SScott Long case ACB_ADAPTER_TYPE_A: { 123444f05562SScott Long /* let IOP know data has been read */ 1235d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 123644f05562SScott Long } 123744f05562SScott Long break; 123844f05562SScott Long case ACB_ADAPTER_TYPE_B: { 1239b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 124044f05562SScott Long /* let IOP know data has been read */ 1241b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 124244f05562SScott Long } 124344f05562SScott Long break; 1244d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1245d74001adSXin LI /* let IOP know data has been read */ 1246d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK); 1247d74001adSXin LI } 12487a7bc959SXin LI break; 12497a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 12507a7bc959SXin LI /* let IOP know data has been read */ 12517a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ); 12527a7bc959SXin LI } 12537a7bc959SXin LI break; 125444f05562SScott Long } 125544f05562SScott Long } 125644f05562SScott Long /* 125744f05562SScott Long ************************************************************************** 125844f05562SScott Long ************************************************************************** 125944f05562SScott Long */ 126044f05562SScott Long static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) 126144f05562SScott Long { 126244f05562SScott Long switch (acb->adapter_type) { 126344f05562SScott Long case ACB_ADAPTER_TYPE_A: { 126444f05562SScott Long /* 126544f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 126644f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 126744f05562SScott Long */ 1268d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK); 126944f05562SScott Long } 127044f05562SScott Long break; 127144f05562SScott Long case ACB_ADAPTER_TYPE_B: { 1272b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 127344f05562SScott Long /* 127444f05562SScott Long ** push inbound doorbell tell iop, driver data write ok 127544f05562SScott Long ** and wait reply on next hwinterrupt for next Qbuffer post 127644f05562SScott Long */ 1277b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_WRITE_OK); 1278d74001adSXin LI } 1279d74001adSXin LI break; 1280d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1281d74001adSXin LI /* 1282d74001adSXin LI ** push inbound doorbell tell iop, driver data write ok 1283d74001adSXin LI ** and wait reply on next hwinterrupt for next Qbuffer post 1284d74001adSXin LI */ 1285d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK); 128644f05562SScott Long } 128744f05562SScott Long break; 12887a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 128944f05562SScott Long /* 12907a7bc959SXin LI ** push inbound doorbell tell iop, driver data write ok 12917a7bc959SXin LI ** and wait reply on next hwinterrupt for next Qbuffer post 1292f1c579b1SScott Long */ 12937a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_IN_READY); 1294f1c579b1SScott Long } 12957a7bc959SXin LI break; 1296ad6d6297SScott Long } 1297f1c579b1SScott Long } 1298f1c579b1SScott Long /* 1299f1c579b1SScott Long ************************************************************************ 1300f1c579b1SScott Long ************************************************************************ 1301f1c579b1SScott Long */ 130244f05562SScott Long static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb) 1303f1c579b1SScott Long { 1304ad6d6297SScott Long acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 130544f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 130644f05562SScott Long 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 130744f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 1308d74001adSXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n" 1309ad6d6297SScott Long , acb->pci_unit); 1310ad6d6297SScott Long } 1311f1c579b1SScott Long } 1312f1c579b1SScott Long /* 1313f1c579b1SScott Long ************************************************************************ 1314f1c579b1SScott Long ************************************************************************ 1315f1c579b1SScott Long */ 131644f05562SScott Long static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb) 131744f05562SScott Long { 1318b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 131944f05562SScott Long acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 1320b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_STOP_BGRB); 132144f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 1322d74001adSXin LI printf( "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" 132344f05562SScott Long , acb->pci_unit); 132444f05562SScott Long } 132544f05562SScott Long } 132644f05562SScott Long /* 132744f05562SScott Long ************************************************************************ 132844f05562SScott Long ************************************************************************ 132944f05562SScott Long */ 1330d74001adSXin LI static void arcmsr_stop_hbc_bgrb(struct AdapterControlBlock *acb) 1331d74001adSXin LI { 1332d74001adSXin LI acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 1333d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 1334d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 1335d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 1336d74001adSXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit); 1337d74001adSXin LI } 1338d74001adSXin LI } 1339d74001adSXin LI /* 1340d74001adSXin LI ************************************************************************ 1341d74001adSXin LI ************************************************************************ 1342d74001adSXin LI */ 13437a7bc959SXin LI static void arcmsr_stop_hbd_bgrb(struct AdapterControlBlock *acb) 13447a7bc959SXin LI { 13457a7bc959SXin LI acb->acb_flags &= ~ACB_F_MSG_START_BGRB; 13467a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB); 13477a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 13487a7bc959SXin LI printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit); 13497a7bc959SXin LI } 13507a7bc959SXin LI } 13517a7bc959SXin LI /* 13527a7bc959SXin LI ************************************************************************ 13537a7bc959SXin LI ************************************************************************ 13547a7bc959SXin LI */ 135544f05562SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) 135644f05562SScott Long { 135744f05562SScott Long switch (acb->adapter_type) { 135844f05562SScott Long case ACB_ADAPTER_TYPE_A: { 135944f05562SScott Long arcmsr_stop_hba_bgrb(acb); 136044f05562SScott Long } 136144f05562SScott Long break; 136244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 136344f05562SScott Long arcmsr_stop_hbb_bgrb(acb); 136444f05562SScott Long } 136544f05562SScott Long break; 1366d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 1367d74001adSXin LI arcmsr_stop_hbc_bgrb(acb); 1368d74001adSXin LI } 1369d74001adSXin LI break; 13707a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 13717a7bc959SXin LI arcmsr_stop_hbd_bgrb(acb); 13727a7bc959SXin LI } 13737a7bc959SXin LI break; 137444f05562SScott Long } 137544f05562SScott Long } 137644f05562SScott Long /* 137744f05562SScott Long ************************************************************************ 137844f05562SScott Long ************************************************************************ 137944f05562SScott Long */ 1380ad6d6297SScott Long static void arcmsr_poll(struct cam_sim *psim) 1381f1c579b1SScott Long { 1382579ec1a5SScott Long struct AdapterControlBlock *acb; 13834e32649fSXin LI int mutex; 1384579ec1a5SScott Long 1385579ec1a5SScott Long acb = (struct AdapterControlBlock *)cam_sim_softc(psim); 13867a7bc959SXin LI mutex = mtx_owned(&acb->isr_lock); 13874e32649fSXin LI if( mutex == 0 ) 13887a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 1389579ec1a5SScott Long arcmsr_interrupt(acb); 13904e32649fSXin LI if( mutex == 0 ) 13917a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 13927a7bc959SXin LI } 13937a7bc959SXin LI /* 13947a7bc959SXin LI ************************************************************************** 13957a7bc959SXin LI ************************************************************************** 13967a7bc959SXin LI */ 139735689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data_D(struct AdapterControlBlock *acb, 139835689395SXin LI struct QBUFFER *prbuffer) { 139935689395SXin LI 140035689395SXin LI u_int8_t *pQbuffer; 140135689395SXin LI u_int8_t *buf1 = 0; 140235689395SXin LI u_int32_t *iop_data, *buf2 = 0; 140335689395SXin LI u_int32_t iop_len, data_len; 140435689395SXin LI 140535689395SXin LI iop_data = (u_int32_t *)prbuffer->data; 140635689395SXin LI iop_len = (u_int32_t)prbuffer->data_len; 140735689395SXin LI if ( iop_len > 0 ) 140835689395SXin LI { 140935689395SXin LI buf1 = malloc(128, M_DEVBUF, M_NOWAIT | M_ZERO); 141035689395SXin LI buf2 = (u_int32_t *)buf1; 141135689395SXin LI if( buf1 == NULL) 141235689395SXin LI return (0); 141335689395SXin LI data_len = iop_len; 141435689395SXin LI while(data_len >= 4) 141535689395SXin LI { 141635689395SXin LI *buf2++ = *iop_data++; 141735689395SXin LI data_len -= 4; 141835689395SXin LI } 141935689395SXin LI if(data_len) 142035689395SXin LI *buf2 = *iop_data; 142135689395SXin LI buf2 = (u_int32_t *)buf1; 142235689395SXin LI } 142335689395SXin LI while (iop_len > 0) { 142435689395SXin LI pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex]; 142535689395SXin LI *pQbuffer = *buf1; 142635689395SXin LI acb->rqbuf_lastindex++; 142735689395SXin LI /* if last, index number set it to 0 */ 142835689395SXin LI acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 142935689395SXin LI buf1++; 143035689395SXin LI iop_len--; 143135689395SXin LI } 143235689395SXin LI if(buf2) 143335689395SXin LI free( (u_int8_t *)buf2, M_DEVBUF); 143435689395SXin LI /* let IOP know data has been read */ 143535689395SXin LI arcmsr_iop_message_read(acb); 143635689395SXin LI return (1); 143735689395SXin LI } 143835689395SXin LI /* 143935689395SXin LI ************************************************************************** 144035689395SXin LI ************************************************************************** 144135689395SXin LI */ 144235689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, 14437a7bc959SXin LI struct QBUFFER *prbuffer) { 14447a7bc959SXin LI 14457a7bc959SXin LI u_int8_t *pQbuffer; 14467a7bc959SXin LI u_int8_t *iop_data; 14477a7bc959SXin LI u_int32_t iop_len; 14487a7bc959SXin LI 1449224a78aeSXin LI if(acb->adapter_type & (ACB_ADAPTER_TYPE_C | ACB_ADAPTER_TYPE_D)) { 145035689395SXin LI return(arcmsr_Read_iop_rqbuffer_data_D(acb, prbuffer)); 145135689395SXin LI } 14527a7bc959SXin LI iop_data = (u_int8_t *)prbuffer->data; 14537a7bc959SXin LI iop_len = (u_int32_t)prbuffer->data_len; 14547a7bc959SXin LI while (iop_len > 0) { 14557a7bc959SXin LI pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex]; 14567a7bc959SXin LI *pQbuffer = *iop_data; 14577a7bc959SXin LI acb->rqbuf_lastindex++; 14587a7bc959SXin LI /* if last, index number set it to 0 */ 14597a7bc959SXin LI acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 14607a7bc959SXin LI iop_data++; 14617a7bc959SXin LI iop_len--; 14627a7bc959SXin LI } 14637a7bc959SXin LI /* let IOP know data has been read */ 14647a7bc959SXin LI arcmsr_iop_message_read(acb); 146535689395SXin LI return (1); 1466f1c579b1SScott Long } 1467f1c579b1SScott Long /* 146844f05562SScott Long ************************************************************************** 146944f05562SScott Long ************************************************************************** 14705878cbecSScott Long */ 147144f05562SScott Long static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) 1472f1c579b1SScott Long { 147344f05562SScott Long struct QBUFFER *prbuffer; 14747a7bc959SXin LI int my_empty_len; 1475ad6d6297SScott Long 1476f1c579b1SScott Long /*check this iop data if overflow my rqbuffer*/ 14777a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 147844f05562SScott Long prbuffer = arcmsr_get_iop_rqbuffer(acb); 14797a7bc959SXin LI my_empty_len = (acb->rqbuf_lastindex - acb->rqbuf_firstindex - 1) & 14807a7bc959SXin LI (ARCMSR_MAX_QBUFFER-1); 14817a7bc959SXin LI if(my_empty_len >= prbuffer->data_len) { 148235689395SXin LI if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) 148335689395SXin LI acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 1484ad6d6297SScott Long } else { 1485ad6d6297SScott Long acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 1486f1c579b1SScott Long } 14877a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 14887a7bc959SXin LI } 14897a7bc959SXin LI /* 14907a7bc959SXin LI ********************************************************************** 14917a7bc959SXin LI ********************************************************************** 14927a7bc959SXin LI */ 149335689395SXin LI static void arcmsr_Write_data_2iop_wqbuffer_D(struct AdapterControlBlock *acb) 149435689395SXin LI { 149535689395SXin LI u_int8_t *pQbuffer; 149635689395SXin LI struct QBUFFER *pwbuffer; 149735689395SXin LI u_int8_t *buf1 = 0; 149835689395SXin LI u_int32_t *iop_data, *buf2 = 0; 149935689395SXin LI u_int32_t allxfer_len = 0, data_len; 150035689395SXin LI 150135689395SXin LI if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) { 150235689395SXin LI buf1 = malloc(128, M_DEVBUF, M_NOWAIT | M_ZERO); 150335689395SXin LI buf2 = (u_int32_t *)buf1; 150435689395SXin LI if( buf1 == NULL) 150535689395SXin LI return; 150635689395SXin LI 150735689395SXin LI acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 150835689395SXin LI pwbuffer = arcmsr_get_iop_wqbuffer(acb); 150935689395SXin LI iop_data = (u_int32_t *)pwbuffer->data; 151035689395SXin LI while((acb->wqbuf_firstindex != acb->wqbuf_lastindex) 151135689395SXin LI && (allxfer_len < 124)) { 151235689395SXin LI pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex]; 151335689395SXin LI *buf1 = *pQbuffer; 151435689395SXin LI acb->wqbuf_firstindex++; 151535689395SXin LI acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 151635689395SXin LI buf1++; 151735689395SXin LI allxfer_len++; 151835689395SXin LI } 151935689395SXin LI pwbuffer->data_len = allxfer_len; 152035689395SXin LI data_len = allxfer_len; 152135689395SXin LI buf1 = (u_int8_t *)buf2; 152235689395SXin LI while(data_len >= 4) 152335689395SXin LI { 152435689395SXin LI *iop_data++ = *buf2++; 152535689395SXin LI data_len -= 4; 152635689395SXin LI } 152735689395SXin LI if(data_len) 152835689395SXin LI *iop_data = *buf2; 152935689395SXin LI free( buf1, M_DEVBUF); 153035689395SXin LI arcmsr_iop_message_wrote(acb); 153135689395SXin LI } 153235689395SXin LI } 153335689395SXin LI /* 153435689395SXin LI ********************************************************************** 153535689395SXin LI ********************************************************************** 153635689395SXin LI */ 15377a7bc959SXin LI static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb) 15387a7bc959SXin LI { 15397a7bc959SXin LI u_int8_t *pQbuffer; 15407a7bc959SXin LI struct QBUFFER *pwbuffer; 15417a7bc959SXin LI u_int8_t *iop_data; 15427a7bc959SXin LI int32_t allxfer_len=0; 15437a7bc959SXin LI 1544224a78aeSXin LI if(acb->adapter_type & (ACB_ADAPTER_TYPE_C | ACB_ADAPTER_TYPE_D)) { 154535689395SXin LI arcmsr_Write_data_2iop_wqbuffer_D(acb); 154635689395SXin LI return; 154735689395SXin LI } 15487a7bc959SXin LI if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) { 15497a7bc959SXin LI acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ); 15507a7bc959SXin LI pwbuffer = arcmsr_get_iop_wqbuffer(acb); 15517a7bc959SXin LI iop_data = (u_int8_t *)pwbuffer->data; 15527a7bc959SXin LI while((acb->wqbuf_firstindex != acb->wqbuf_lastindex) 15537a7bc959SXin LI && (allxfer_len < 124)) { 15547a7bc959SXin LI pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex]; 15557a7bc959SXin LI *iop_data = *pQbuffer; 15567a7bc959SXin LI acb->wqbuf_firstindex++; 15577a7bc959SXin LI acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 15587a7bc959SXin LI iop_data++; 15597a7bc959SXin LI allxfer_len++; 15607a7bc959SXin LI } 15617a7bc959SXin LI pwbuffer->data_len = allxfer_len; 15627a7bc959SXin LI arcmsr_iop_message_wrote(acb); 15637a7bc959SXin LI } 1564f1c579b1SScott Long } 1565f1c579b1SScott Long /* 156644f05562SScott Long ************************************************************************** 156744f05562SScott Long ************************************************************************** 156844f05562SScott Long */ 156944f05562SScott Long static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) 157044f05562SScott Long { 15717a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 157244f05562SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READ; 157344f05562SScott Long /* 157444f05562SScott Long ***************************************************************** 157544f05562SScott Long ** check if there are any mail packages from user space program 157644f05562SScott Long ** in my post bag, now is the time to send them into Areca's firmware 157744f05562SScott Long ***************************************************************** 1578f1c579b1SScott Long */ 1579ad6d6297SScott Long if(acb->wqbuf_firstindex != acb->wqbuf_lastindex) { 15807a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 1581f1c579b1SScott Long } 1582ad6d6297SScott Long if(acb->wqbuf_firstindex == acb->wqbuf_lastindex) { 1583ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; 1584f1c579b1SScott Long } 15857a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 1586f1c579b1SScott Long } 15877a7bc959SXin LI /* 15887a7bc959SXin LI ************************************************************************** 15897a7bc959SXin LI ************************************************************************** 15907a7bc959SXin LI */ 1591d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb) 1592d74001adSXin LI { 1593d74001adSXin LI /* 1594d74001adSXin LI if (ccb->ccb_h.status != CAM_REQ_CMP) 15957a7bc959SXin LI printf("arcmsr_rescanLun_cb: Rescan Target=%x, lun=%x," 15967a7bc959SXin LI "failure status=%x\n", ccb->ccb_h.target_id, 15977a7bc959SXin LI ccb->ccb_h.target_lun, ccb->ccb_h.status); 1598d74001adSXin LI else 1599d74001adSXin LI printf("arcmsr_rescanLun_cb: Rescan lun successfully!\n"); 1600d74001adSXin LI */ 1601d74001adSXin LI xpt_free_path(ccb->ccb_h.path); 1602d74001adSXin LI xpt_free_ccb(ccb); 1603d74001adSXin LI } 1604d74001adSXin LI 1605d74001adSXin LI static void arcmsr_rescan_lun(struct AdapterControlBlock *acb, int target, int lun) 1606d74001adSXin LI { 1607d74001adSXin LI struct cam_path *path; 1608d74001adSXin LI union ccb *ccb; 1609d74001adSXin LI 1610d74001adSXin LI if ((ccb = (union ccb *)xpt_alloc_ccb_nowait()) == NULL) 1611d74001adSXin LI return; 1612abfdbca9SXin LI if (xpt_create_path(&path, NULL, cam_sim_path(acb->psim), target, lun) != CAM_REQ_CMP) 1613d74001adSXin LI { 1614d74001adSXin LI xpt_free_ccb(ccb); 1615d74001adSXin LI return; 1616d74001adSXin LI } 1617d74001adSXin LI /* printf("arcmsr_rescan_lun: Rescan Target=%x, Lun=%x\n", target, lun); */ 1618d74001adSXin LI bzero(ccb, sizeof(union ccb)); 1619d74001adSXin LI xpt_setup_ccb(&ccb->ccb_h, path, 5); 1620d74001adSXin LI ccb->ccb_h.func_code = XPT_SCAN_LUN; 1621d74001adSXin LI ccb->ccb_h.cbfcnp = arcmsr_rescanLun_cb; 1622d74001adSXin LI ccb->crcn.flags = CAM_FLAG_NONE; 1623d74001adSXin LI xpt_action(ccb); 1624d74001adSXin LI } 1625d74001adSXin LI 1626d74001adSXin LI 1627d74001adSXin LI static void arcmsr_abort_dr_ccbs(struct AdapterControlBlock *acb, int target, int lun) 1628d74001adSXin LI { 1629d74001adSXin LI struct CommandControlBlock *srb; 1630d74001adSXin LI u_int32_t intmask_org; 1631d74001adSXin LI int i; 1632d74001adSXin LI 1633d74001adSXin LI /* disable all outbound interrupts */ 1634d74001adSXin LI intmask_org = arcmsr_disable_allintr(acb); 1635d74001adSXin LI for (i = 0; i < ARCMSR_MAX_FREESRB_NUM; i++) 1636d74001adSXin LI { 1637d74001adSXin LI srb = acb->psrb_pool[i]; 163822f2616bSXin LI if (srb->srb_state == ARCMSR_SRB_START) 1639d74001adSXin LI { 1640d74001adSXin LI if((target == srb->pccb->ccb_h.target_id) && (lun == srb->pccb->ccb_h.target_lun)) 1641d74001adSXin LI { 164222f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 1643d74001adSXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 1644d74001adSXin LI arcmsr_srb_complete(srb, 1); 164522f2616bSXin LI printf("arcmsr%d: abort scsi id %d lun %d srb=%p \n", acb->pci_unit, target, lun, srb); 1646d74001adSXin LI } 1647d74001adSXin LI } 1648d74001adSXin LI } 1649d74001adSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 1650d74001adSXin LI arcmsr_enable_allintr(acb, intmask_org); 1651d74001adSXin LI } 1652d74001adSXin LI /* 1653d74001adSXin LI ************************************************************************** 1654d74001adSXin LI ************************************************************************** 1655d74001adSXin LI */ 1656d74001adSXin LI static void arcmsr_dr_handle(struct AdapterControlBlock *acb) { 1657d74001adSXin LI u_int32_t devicemap; 1658d74001adSXin LI u_int32_t target, lun; 1659d74001adSXin LI u_int32_t deviceMapCurrent[4]={0}; 1660d74001adSXin LI u_int8_t *pDevMap; 1661d74001adSXin LI 1662d74001adSXin LI switch (acb->adapter_type) { 1663d74001adSXin LI case ACB_ADAPTER_TYPE_A: 1664d74001adSXin LI devicemap = offsetof(struct HBA_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1665d74001adSXin LI for (target = 0; target < 4; target++) 1666d74001adSXin LI { 1667d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1668d74001adSXin LI devicemap += 4; 1669d74001adSXin LI } 1670d74001adSXin LI break; 1671d74001adSXin LI 1672d74001adSXin LI case ACB_ADAPTER_TYPE_B: 1673d74001adSXin LI devicemap = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1674d74001adSXin LI for (target = 0; target < 4; target++) 1675d74001adSXin LI { 1676d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[1], acb->bhandle[1], devicemap); 1677d74001adSXin LI devicemap += 4; 1678d74001adSXin LI } 1679d74001adSXin LI break; 1680d74001adSXin LI 1681d74001adSXin LI case ACB_ADAPTER_TYPE_C: 1682d74001adSXin LI devicemap = offsetof(struct HBC_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 1683d74001adSXin LI for (target = 0; target < 4; target++) 1684d74001adSXin LI { 1685d74001adSXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 1686d74001adSXin LI devicemap += 4; 1687d74001adSXin LI } 1688d74001adSXin LI break; 16897a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 16907a7bc959SXin LI devicemap = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 16917a7bc959SXin LI for (target = 0; target < 4; target++) 16927a7bc959SXin LI { 16937a7bc959SXin LI deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0], devicemap); 16947a7bc959SXin LI devicemap += 4; 16957a7bc959SXin LI } 16967a7bc959SXin LI break; 1697d74001adSXin LI } 1698dac36688SXin LI 1699d74001adSXin LI if(acb->acb_flags & ACB_F_BUS_HANG_ON) 1700d74001adSXin LI { 1701d74001adSXin LI acb->acb_flags &= ~ACB_F_BUS_HANG_ON; 1702d74001adSXin LI } 1703d74001adSXin LI /* 1704d74001adSXin LI ** adapter posted CONFIG message 1705d74001adSXin LI ** copy the new map, note if there are differences with the current map 1706d74001adSXin LI */ 1707d74001adSXin LI pDevMap = (u_int8_t *)&deviceMapCurrent[0]; 1708d74001adSXin LI for (target = 0; target < ARCMSR_MAX_TARGETID - 1; target++) 1709d74001adSXin LI { 1710d74001adSXin LI if (*pDevMap != acb->device_map[target]) 1711d74001adSXin LI { 1712d74001adSXin LI u_int8_t difference, bit_check; 1713d74001adSXin LI 1714d74001adSXin LI difference = *pDevMap ^ acb->device_map[target]; 1715d74001adSXin LI for(lun=0; lun < ARCMSR_MAX_TARGETLUN; lun++) 1716d74001adSXin LI { 1717d74001adSXin LI bit_check = (1 << lun); /*check bit from 0....31*/ 1718d74001adSXin LI if(difference & bit_check) 1719d74001adSXin LI { 1720d74001adSXin LI if(acb->device_map[target] & bit_check) 1721d74001adSXin LI {/* unit departed */ 1722d74001adSXin LI printf("arcmsr_dr_handle: Target=%x, lun=%x, GONE!!!\n",target,lun); 1723d74001adSXin LI arcmsr_abort_dr_ccbs(acb, target, lun); 1724d74001adSXin LI arcmsr_rescan_lun(acb, target, lun); 1725d74001adSXin LI acb->devstate[target][lun] = ARECA_RAID_GONE; 1726d74001adSXin LI } 1727d74001adSXin LI else 1728d74001adSXin LI {/* unit arrived */ 172922f2616bSXin LI printf("arcmsr_dr_handle: Target=%x, lun=%x, Plug-IN!!!\n",target,lun); 1730d74001adSXin LI arcmsr_rescan_lun(acb, target, lun); 1731d74001adSXin LI acb->devstate[target][lun] = ARECA_RAID_GOOD; 1732d74001adSXin LI } 1733d74001adSXin LI } 1734d74001adSXin LI } 1735d74001adSXin LI /* printf("arcmsr_dr_handle: acb->device_map[%x]=0x%x, deviceMapCurrent[%x]=%x\n",target,acb->device_map[target],target,*pDevMap); */ 1736d74001adSXin LI acb->device_map[target] = *pDevMap; 1737d74001adSXin LI } 1738d74001adSXin LI pDevMap++; 1739d74001adSXin LI } 1740d74001adSXin LI } 1741d74001adSXin LI /* 1742d74001adSXin LI ************************************************************************** 1743d74001adSXin LI ************************************************************************** 1744d74001adSXin LI */ 1745d74001adSXin LI static void arcmsr_hba_message_isr(struct AdapterControlBlock *acb) { 1746d74001adSXin LI u_int32_t outbound_message; 1747d74001adSXin LI 1748d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT); 1749d74001adSXin LI outbound_message = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[0]); 1750d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1751d74001adSXin LI arcmsr_dr_handle( acb ); 1752d74001adSXin LI } 1753d74001adSXin LI /* 1754d74001adSXin LI ************************************************************************** 1755d74001adSXin LI ************************************************************************** 1756d74001adSXin LI */ 1757d74001adSXin LI static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) { 1758d74001adSXin LI u_int32_t outbound_message; 1759b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 1760d74001adSXin LI 1761d74001adSXin LI /* clear interrupts */ 1762b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN); 1763d74001adSXin LI outbound_message = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0]); 1764d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1765d74001adSXin LI arcmsr_dr_handle( acb ); 1766d74001adSXin LI } 1767d74001adSXin LI /* 1768d74001adSXin LI ************************************************************************** 1769d74001adSXin LI ************************************************************************** 1770d74001adSXin LI */ 1771d74001adSXin LI static void arcmsr_hbc_message_isr(struct AdapterControlBlock *acb) { 1772d74001adSXin LI u_int32_t outbound_message; 1773d74001adSXin LI 1774d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR); 1775d74001adSXin LI outbound_message = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[0]); 1776d74001adSXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 1777d74001adSXin LI arcmsr_dr_handle( acb ); 1778d74001adSXin LI } 177944f05562SScott Long /* 178044f05562SScott Long ************************************************************************** 178144f05562SScott Long ************************************************************************** 178244f05562SScott Long */ 17837a7bc959SXin LI static void arcmsr_hbd_message_isr(struct AdapterControlBlock *acb) { 17847a7bc959SXin LI u_int32_t outbound_message; 17857a7bc959SXin LI 17867a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR); 17877a7bc959SXin LI outbound_message = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[0]); 17887a7bc959SXin LI if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG) 17897a7bc959SXin LI arcmsr_dr_handle( acb ); 17907a7bc959SXin LI } 17917a7bc959SXin LI /* 17927a7bc959SXin LI ************************************************************************** 17937a7bc959SXin LI ************************************************************************** 17947a7bc959SXin LI */ 179544f05562SScott Long static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) 179644f05562SScott Long { 1797224a78aeSXin LI u_int32_t doorbell_status; 179844f05562SScott Long 179944f05562SScott Long /* 180044f05562SScott Long ******************************************************************* 180144f05562SScott Long ** Maybe here we need to check wrqbuffer_lock is lock or not 180244f05562SScott Long ** DOORBELL: din! don! 180344f05562SScott Long ** check if there are any mail need to pack from firmware 180444f05562SScott Long ******************************************************************* 180544f05562SScott Long */ 1806224a78aeSXin LI doorbell_status = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell); 1807224a78aeSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */ 1808224a78aeSXin LI if(doorbell_status & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { 180944f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 1810ad6d6297SScott Long } 1811224a78aeSXin LI if(doorbell_status & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { 181244f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 181344f05562SScott Long } 181444f05562SScott Long } 181544f05562SScott Long /* 181644f05562SScott Long ************************************************************************** 181744f05562SScott Long ************************************************************************** 181844f05562SScott Long */ 1819d74001adSXin LI static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb) 1820d74001adSXin LI { 1821224a78aeSXin LI u_int32_t doorbell_status; 1822d74001adSXin LI 1823d74001adSXin LI /* 1824d74001adSXin LI ******************************************************************* 1825d74001adSXin LI ** Maybe here we need to check wrqbuffer_lock is lock or not 1826d74001adSXin LI ** DOORBELL: din! don! 1827d74001adSXin LI ** check if there are any mail need to pack from firmware 1828d74001adSXin LI ******************************************************************* 1829d74001adSXin LI */ 1830224a78aeSXin LI doorbell_status = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); 1831224a78aeSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, doorbell_status); /* clear doorbell interrupt */ 1832224a78aeSXin LI if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) { 1833d74001adSXin LI arcmsr_iop2drv_data_wrote_handle(acb); 1834d74001adSXin LI } 1835224a78aeSXin LI if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) { 1836d74001adSXin LI arcmsr_iop2drv_data_read_handle(acb); 1837d74001adSXin LI } 1838224a78aeSXin LI if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) { 1839d74001adSXin LI arcmsr_hbc_message_isr(acb); /* messenger of "driver to iop commands" */ 1840d74001adSXin LI } 1841d74001adSXin LI } 1842d74001adSXin LI /* 1843d74001adSXin LI ************************************************************************** 1844d74001adSXin LI ************************************************************************** 1845d74001adSXin LI */ 18467a7bc959SXin LI static void arcmsr_hbd_doorbell_isr(struct AdapterControlBlock *acb) 18477a7bc959SXin LI { 1848224a78aeSXin LI u_int32_t doorbell_status; 18497a7bc959SXin LI 18507a7bc959SXin LI /* 18517a7bc959SXin LI ******************************************************************* 18527a7bc959SXin LI ** Maybe here we need to check wrqbuffer_lock is lock or not 18537a7bc959SXin LI ** DOORBELL: din! don! 18547a7bc959SXin LI ** check if there are any mail need to pack from firmware 18557a7bc959SXin LI ******************************************************************* 18567a7bc959SXin LI */ 1857224a78aeSXin LI doorbell_status = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE; 1858224a78aeSXin LI if(doorbell_status) 1859224a78aeSXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */ 1860224a78aeSXin LI while( doorbell_status & ARCMSR_HBDMU_F0_DOORBELL_CAUSE ) { 1861224a78aeSXin LI if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_DATA_WRITE_OK) { 18627a7bc959SXin LI arcmsr_iop2drv_data_wrote_handle(acb); 18637a7bc959SXin LI } 1864224a78aeSXin LI if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_DATA_READ_OK) { 18657a7bc959SXin LI arcmsr_iop2drv_data_read_handle(acb); 18667a7bc959SXin LI } 1867224a78aeSXin LI if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) { 18687a7bc959SXin LI arcmsr_hbd_message_isr(acb); /* messenger of "driver to iop commands" */ 18697a7bc959SXin LI } 1870224a78aeSXin LI doorbell_status = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE; 1871224a78aeSXin LI if(doorbell_status) 1872224a78aeSXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */ 18737a7bc959SXin LI } 18747a7bc959SXin LI } 18757a7bc959SXin LI /* 18767a7bc959SXin LI ************************************************************************** 18777a7bc959SXin LI ************************************************************************** 18787a7bc959SXin LI */ 187944f05562SScott Long static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb) 188044f05562SScott Long { 188144f05562SScott Long u_int32_t flag_srb; 1882d74001adSXin LI u_int16_t error; 188344f05562SScott Long 1884f1c579b1SScott Long /* 1885f1c579b1SScott Long ***************************************************************************** 1886f1c579b1SScott Long ** areca cdb command done 1887f1c579b1SScott Long ***************************************************************************** 1888f1c579b1SScott Long */ 188944f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 189044f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 189144f05562SScott Long while((flag_srb = CHIP_REG_READ32(HBA_MessageUnit, 189244f05562SScott Long 0, outbound_queueport)) != 0xFFFFFFFF) { 1893f1c579b1SScott Long /* check if command done with no error*/ 1894d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0) ? TRUE : FALSE; 1895d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 189644f05562SScott Long } /*drain reply FIFO*/ 1897f1c579b1SScott Long } 189844f05562SScott Long /* 189944f05562SScott Long ************************************************************************** 190044f05562SScott Long ************************************************************************** 190144f05562SScott Long */ 190244f05562SScott Long static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) 190344f05562SScott Long { 190444f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 190544f05562SScott Long u_int32_t flag_srb; 190644f05562SScott Long int index; 1907d74001adSXin LI u_int16_t error; 190844f05562SScott Long 190944f05562SScott Long /* 191044f05562SScott Long ***************************************************************************** 191144f05562SScott Long ** areca cdb command done 191244f05562SScott Long ***************************************************************************** 191344f05562SScott Long */ 191444f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 191544f05562SScott Long BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 191644f05562SScott Long index = phbbmu->doneq_index; 191744f05562SScott Long while((flag_srb = phbbmu->done_qbuffer[index]) != 0) { 191844f05562SScott Long phbbmu->done_qbuffer[index] = 0; 191944f05562SScott Long index++; 192044f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 192144f05562SScott Long phbbmu->doneq_index = index; 192244f05562SScott Long /* check if command done with no error*/ 1923d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 1924d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 1925d74001adSXin LI } /*drain reply FIFO*/ 1926d74001adSXin LI } 1927d74001adSXin LI /* 1928d74001adSXin LI ************************************************************************** 1929d74001adSXin LI ************************************************************************** 1930d74001adSXin LI */ 1931d74001adSXin LI static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb) 1932d74001adSXin LI { 1933d74001adSXin LI u_int32_t flag_srb,throttling = 0; 1934d74001adSXin LI u_int16_t error; 1935d74001adSXin LI 1936d74001adSXin LI /* 1937d74001adSXin LI ***************************************************************************** 1938d74001adSXin LI ** areca cdb command done 1939d74001adSXin LI ***************************************************************************** 1940d74001adSXin LI */ 1941d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 1942224a78aeSXin LI do { 1943d74001adSXin LI flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 1944b23a1998SXin LI if (flag_srb == 0xFFFFFFFF) 1945b23a1998SXin LI break; 1946d74001adSXin LI /* check if command done with no error*/ 1947d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; 1948d74001adSXin LI arcmsr_drain_donequeue(acb, flag_srb, error); 1949abfdbca9SXin LI throttling++; 1950d74001adSXin LI if(throttling == ARCMSR_HBC_ISR_THROTTLING_LEVEL) { 1951d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING); 1952abfdbca9SXin LI throttling = 0; 1953d74001adSXin LI } 1954224a78aeSXin LI } while(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR); 1955f1c579b1SScott Long } 195644f05562SScott Long /* 195744f05562SScott Long ********************************************************************** 19587a7bc959SXin LI ** 19597a7bc959SXin LI ********************************************************************** 19607a7bc959SXin LI */ 19617a7bc959SXin LI static uint16_t arcmsr_get_doneq_index(struct HBD_MessageUnit0 *phbdmu) 19627a7bc959SXin LI { 19637a7bc959SXin LI uint16_t doneq_index, index_stripped; 19647a7bc959SXin LI 19657a7bc959SXin LI doneq_index = phbdmu->doneq_index; 19667a7bc959SXin LI if (doneq_index & 0x4000) { 19677a7bc959SXin LI index_stripped = doneq_index & 0xFF; 19687a7bc959SXin LI index_stripped += 1; 19697a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 19707a7bc959SXin LI phbdmu->doneq_index = index_stripped ? 19717a7bc959SXin LI (index_stripped | 0x4000) : index_stripped; 19727a7bc959SXin LI } else { 19737a7bc959SXin LI index_stripped = doneq_index; 19747a7bc959SXin LI index_stripped += 1; 19757a7bc959SXin LI index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE; 19767a7bc959SXin LI phbdmu->doneq_index = index_stripped ? 19777a7bc959SXin LI index_stripped : (index_stripped | 0x4000); 19787a7bc959SXin LI } 19797a7bc959SXin LI return (phbdmu->doneq_index); 19807a7bc959SXin LI } 19817a7bc959SXin LI /* 19827a7bc959SXin LI ************************************************************************** 19837a7bc959SXin LI ************************************************************************** 19847a7bc959SXin LI */ 19857a7bc959SXin LI static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb) 19867a7bc959SXin LI { 19877a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 19887a7bc959SXin LI u_int32_t outbound_write_pointer; 19897a7bc959SXin LI u_int32_t addressLow; 19907a7bc959SXin LI uint16_t doneq_index; 19917a7bc959SXin LI u_int16_t error; 19927a7bc959SXin LI /* 19937a7bc959SXin LI ***************************************************************************** 19947a7bc959SXin LI ** areca cdb command done 19957a7bc959SXin LI ***************************************************************************** 19967a7bc959SXin LI */ 19977a7bc959SXin LI if((CHIP_REG_READ32(HBD_MessageUnit, 0, outboundlist_interrupt_cause) & 19987a7bc959SXin LI ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT) == 0) 19997a7bc959SXin LI return; 20007a7bc959SXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, 20017a7bc959SXin LI BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 20027a7bc959SXin LI outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow; 20037a7bc959SXin LI doneq_index = phbdmu->doneq_index; 20047a7bc959SXin LI while ((doneq_index & 0xFF) != (outbound_write_pointer & 0xFF)) { 20057a7bc959SXin LI doneq_index = arcmsr_get_doneq_index(phbdmu); 20067a7bc959SXin LI addressLow = phbdmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow; 20077a7bc959SXin LI error = (addressLow & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 20087a7bc959SXin LI arcmsr_drain_donequeue(acb, addressLow, error); /*Check if command done with no error */ 20097a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_read_pointer, doneq_index); 20107a7bc959SXin LI outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow; 20117a7bc959SXin LI } 20127a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_interrupt_cause, ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT_CLEAR); 20137a7bc959SXin LI CHIP_REG_READ32(HBD_MessageUnit, 0, outboundlist_interrupt_cause); /*Dummy ioread32 to force pci flush */ 20147a7bc959SXin LI } 20157a7bc959SXin LI /* 20167a7bc959SXin LI ********************************************************************** 201744f05562SScott Long ********************************************************************** 201844f05562SScott Long */ 201944f05562SScott Long static void arcmsr_handle_hba_isr( struct AdapterControlBlock *acb) 202044f05562SScott Long { 2021dac36688SXin LI u_int32_t outbound_intStatus; 202244f05562SScott Long /* 202344f05562SScott Long ********************************************* 202444f05562SScott Long ** check outbound intstatus 202544f05562SScott Long ********************************************* 202644f05562SScott Long */ 2027dac36688SXin LI outbound_intStatus = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 2028dac36688SXin LI if(!outbound_intStatus) { 202944f05562SScott Long /*it must be share irq*/ 203044f05562SScott Long return; 2031f1c579b1SScott Long } 2032dac36688SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intStatus); /*clear interrupt*/ 203344f05562SScott Long /* MU doorbell interrupts*/ 2034dac36688SXin LI if(outbound_intStatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) { 203544f05562SScott Long arcmsr_hba_doorbell_isr(acb); 2036f1c579b1SScott Long } 203744f05562SScott Long /* MU post queue interrupts*/ 2038dac36688SXin LI if(outbound_intStatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { 203944f05562SScott Long arcmsr_hba_postqueue_isr(acb); 204044f05562SScott Long } 2041dac36688SXin LI if(outbound_intStatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { 2042d74001adSXin LI arcmsr_hba_message_isr(acb); 2043d74001adSXin LI } 204444f05562SScott Long } 204544f05562SScott Long /* 204644f05562SScott Long ********************************************************************** 204744f05562SScott Long ********************************************************************** 204844f05562SScott Long */ 204944f05562SScott Long static void arcmsr_handle_hbb_isr( struct AdapterControlBlock *acb) 205044f05562SScott Long { 205144f05562SScott Long u_int32_t outbound_doorbell; 2052b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 205344f05562SScott Long /* 205444f05562SScott Long ********************************************* 205544f05562SScott Long ** check outbound intstatus 205644f05562SScott Long ********************************************* 205744f05562SScott Long */ 2058b23a1998SXin LI outbound_doorbell = READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & acb->outbound_int_enable; 205944f05562SScott Long if(!outbound_doorbell) { 206044f05562SScott Long /*it must be share irq*/ 206144f05562SScott Long return; 206244f05562SScott Long } 2063b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ~outbound_doorbell); /* clear doorbell interrupt */ 2064b23a1998SXin LI READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell); 2065b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 206644f05562SScott Long /* MU ioctl transfer doorbell interrupts*/ 206744f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { 206844f05562SScott Long arcmsr_iop2drv_data_wrote_handle(acb); 206944f05562SScott Long } 207044f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) { 207144f05562SScott Long arcmsr_iop2drv_data_read_handle(acb); 207244f05562SScott Long } 207344f05562SScott Long /* MU post queue interrupts*/ 207444f05562SScott Long if(outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) { 207544f05562SScott Long arcmsr_hbb_postqueue_isr(acb); 207644f05562SScott Long } 2077d74001adSXin LI if(outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { 2078d74001adSXin LI arcmsr_hbb_message_isr(acb); 2079d74001adSXin LI } 2080d74001adSXin LI } 2081d74001adSXin LI /* 2082d74001adSXin LI ********************************************************************** 2083d74001adSXin LI ********************************************************************** 2084d74001adSXin LI */ 2085d74001adSXin LI static void arcmsr_handle_hbc_isr( struct AdapterControlBlock *acb) 2086d74001adSXin LI { 2087d74001adSXin LI u_int32_t host_interrupt_status; 2088d74001adSXin LI /* 2089d74001adSXin LI ********************************************* 2090d74001adSXin LI ** check outbound intstatus 2091d74001adSXin LI ********************************************* 2092d74001adSXin LI */ 2093224a78aeSXin LI host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & 2094224a78aeSXin LI (ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR | 2095224a78aeSXin LI ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR); 2096d74001adSXin LI if(!host_interrupt_status) { 2097d74001adSXin LI /*it must be share irq*/ 2098d74001adSXin LI return; 2099d74001adSXin LI } 2100224a78aeSXin LI do { 2101d74001adSXin LI /* MU doorbell interrupts*/ 2102d74001adSXin LI if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) { 2103d74001adSXin LI arcmsr_hbc_doorbell_isr(acb); 2104d74001adSXin LI } 2105d74001adSXin LI /* MU post queue interrupts*/ 2106d74001adSXin LI if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) { 2107d74001adSXin LI arcmsr_hbc_postqueue_isr(acb); 2108d74001adSXin LI } 2109224a78aeSXin LI host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status); 2110224a78aeSXin LI } while (host_interrupt_status & (ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR)); 211144f05562SScott Long } 211244f05562SScott Long /* 21137a7bc959SXin LI ********************************************************************** 21147a7bc959SXin LI ********************************************************************** 21157a7bc959SXin LI */ 21167a7bc959SXin LI static void arcmsr_handle_hbd_isr( struct AdapterControlBlock *acb) 21177a7bc959SXin LI { 21187a7bc959SXin LI u_int32_t host_interrupt_status; 21197a7bc959SXin LI u_int32_t intmask_org; 21207a7bc959SXin LI /* 21217a7bc959SXin LI ********************************************* 21227a7bc959SXin LI ** check outbound intstatus 21237a7bc959SXin LI ********************************************* 21247a7bc959SXin LI */ 21257a7bc959SXin LI host_interrupt_status = CHIP_REG_READ32(HBD_MessageUnit, 0, host_int_status) & acb->outbound_int_enable; 21267a7bc959SXin LI if(!(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_INT)) { 21277a7bc959SXin LI /*it must be share irq*/ 21287a7bc959SXin LI return; 21297a7bc959SXin LI } 21307a7bc959SXin LI /* disable outbound interrupt */ 21317a7bc959SXin LI intmask_org = CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable) ; /* disable outbound message0 int */ 21327a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, ARCMSR_HBDMU_ALL_INT_DISABLE); 21337a7bc959SXin LI /* MU doorbell interrupts*/ 21347a7bc959SXin LI if(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_DOORBELL_INT) { 21357a7bc959SXin LI arcmsr_hbd_doorbell_isr(acb); 21367a7bc959SXin LI } 21377a7bc959SXin LI /* MU post queue interrupts*/ 21387a7bc959SXin LI if(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_POSTQUEUE_INT) { 21397a7bc959SXin LI arcmsr_hbd_postqueue_isr(acb); 21407a7bc959SXin LI } 21417a7bc959SXin LI /* enable all outbound interrupt */ 21427a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, intmask_org | ARCMSR_HBDMU_ALL_INT_ENABLE); 21437a7bc959SXin LI // CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable); 21447a7bc959SXin LI } 21457a7bc959SXin LI /* 214644f05562SScott Long ****************************************************************************** 214744f05562SScott Long ****************************************************************************** 214844f05562SScott Long */ 214944f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb) 215044f05562SScott Long { 215144f05562SScott Long switch (acb->adapter_type) { 215244f05562SScott Long case ACB_ADAPTER_TYPE_A: 215344f05562SScott Long arcmsr_handle_hba_isr(acb); 2154f1c579b1SScott Long break; 215544f05562SScott Long case ACB_ADAPTER_TYPE_B: 215644f05562SScott Long arcmsr_handle_hbb_isr(acb); 2157f1c579b1SScott Long break; 2158d74001adSXin LI case ACB_ADAPTER_TYPE_C: 2159d74001adSXin LI arcmsr_handle_hbc_isr(acb); 2160d74001adSXin LI break; 21617a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 21627a7bc959SXin LI arcmsr_handle_hbd_isr(acb); 21637a7bc959SXin LI break; 2164f1c579b1SScott Long default: 216544f05562SScott Long printf("arcmsr%d: interrupt service," 216610d66948SKevin Lo " unknown adapter type =%d\n", acb->pci_unit, acb->adapter_type); 2167f1c579b1SScott Long break; 2168f1c579b1SScott Long } 2169f1c579b1SScott Long } 2170f1c579b1SScott Long /* 2171d74001adSXin LI ********************************************************************** 2172d74001adSXin LI ********************************************************************** 2173d74001adSXin LI */ 2174d74001adSXin LI static void arcmsr_intr_handler(void *arg) 2175d74001adSXin LI { 2176d74001adSXin LI struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg; 2177d74001adSXin LI 21787a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 2179d74001adSXin LI arcmsr_interrupt(acb); 21807a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 2181d74001adSXin LI } 2182d74001adSXin LI /* 2183d74001adSXin LI ****************************************************************************** 2184d74001adSXin LI ****************************************************************************** 2185d74001adSXin LI */ 2186d74001adSXin LI static void arcmsr_polling_devmap(void *arg) 2187d74001adSXin LI { 2188d74001adSXin LI struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg; 2189d74001adSXin LI switch (acb->adapter_type) { 2190d74001adSXin LI case ACB_ADAPTER_TYPE_A: 2191dac36688SXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 2192d74001adSXin LI break; 2193d74001adSXin LI 2194b23a1998SXin LI case ACB_ADAPTER_TYPE_B: { 2195b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 2196b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG); 2197b23a1998SXin LI } 2198d74001adSXin LI break; 2199d74001adSXin LI 2200d74001adSXin LI case ACB_ADAPTER_TYPE_C: 2201d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 2202d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 2203d74001adSXin LI break; 22047a7bc959SXin LI 22057a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 22067a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 22077a7bc959SXin LI break; 2208d74001adSXin LI } 2209d74001adSXin LI 2210d74001adSXin LI if((acb->acb_flags & ACB_F_SCSISTOPADAPTER) == 0) 2211d74001adSXin LI { 2212d74001adSXin LI callout_reset(&acb->devmap_callout, 5 * hz, arcmsr_polling_devmap, acb); /* polling per 5 seconds */ 2213d74001adSXin LI } 2214d74001adSXin LI } 2215d74001adSXin LI 2216d74001adSXin LI /* 2217ad6d6297SScott Long ******************************************************************************* 2218ad6d6297SScott Long ** 2219ad6d6297SScott Long ******************************************************************************* 2220ad6d6297SScott Long */ 2221ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb) 2222ad6d6297SScott Long { 2223d74001adSXin LI u_int32_t intmask_org; 2224d74001adSXin LI 2225ad6d6297SScott Long if(acb != NULL) { 2226ad6d6297SScott Long /* stop adapter background rebuild */ 2227ad6d6297SScott Long if(acb->acb_flags & ACB_F_MSG_START_BGRB) { 2228d74001adSXin LI intmask_org = arcmsr_disable_allintr(acb); 2229ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 2230ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2231d74001adSXin LI arcmsr_enable_allintr(acb, intmask_org); 2232ad6d6297SScott Long } 2233ad6d6297SScott Long } 2234ad6d6297SScott Long } 2235ad6d6297SScott Long /* 2236f1c579b1SScott Long *********************************************************************** 2237f1c579b1SScott Long ** 2238f1c579b1SScott Long ************************************************************************ 2239f1c579b1SScott Long */ 2240ad6d6297SScott Long u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg) 2241f1c579b1SScott Long { 2242ad6d6297SScott Long struct CMD_MESSAGE_FIELD *pcmdmessagefld; 2243ad6d6297SScott Long u_int32_t retvalue = EINVAL; 2244f1c579b1SScott Long 2245ad6d6297SScott Long pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) arg; 2246ad6d6297SScott Long if(memcmp(pcmdmessagefld->cmdmessage.Signature, "ARCMSR", 6)!=0) { 2247ad6d6297SScott Long return retvalue; 2248f1c579b1SScott Long } 2249ad6d6297SScott Long ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2250ad6d6297SScott Long switch(ioctl_cmd) { 2251ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 2252ad6d6297SScott Long u_int8_t *pQbuffer; 2253ad6d6297SScott Long u_int8_t *ptmpQbuffer = pcmdmessagefld->messagedatabuffer; 2254ad6d6297SScott Long u_int32_t allxfer_len=0; 2255f1c579b1SScott Long 225644f05562SScott Long while((acb->rqbuf_firstindex != acb->rqbuf_lastindex) 225744f05562SScott Long && (allxfer_len < 1031)) { 2258f1c579b1SScott Long /*copy READ QBUFFER to srb*/ 2259ad6d6297SScott Long pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; 22607a7bc959SXin LI *ptmpQbuffer = *pQbuffer; 2261ad6d6297SScott Long acb->rqbuf_firstindex++; 2262ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 2263ad6d6297SScott Long /*if last index number set it to 0 */ 2264f1c579b1SScott Long ptmpQbuffer++; 2265f1c579b1SScott Long allxfer_len++; 2266f1c579b1SScott Long } 2267ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 226844f05562SScott Long struct QBUFFER *prbuffer; 2269f1c579b1SScott Long 2270ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 227144f05562SScott Long prbuffer = arcmsr_get_iop_rqbuffer(acb); 227235689395SXin LI if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) 227335689395SXin LI acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 2274f1c579b1SScott Long } 2275ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length = allxfer_len; 2276ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2277ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2278f1c579b1SScott Long } 2279f1c579b1SScott Long break; 2280ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 2281ad6d6297SScott Long u_int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 2282ad6d6297SScott Long u_int8_t *pQbuffer; 2283ad6d6297SScott Long u_int8_t *ptmpuserbuffer = pcmdmessagefld->messagedatabuffer; 2284f1c579b1SScott Long 2285ad6d6297SScott Long user_len = pcmdmessagefld->cmdmessage.Length; 2286f1c579b1SScott Long /*check if data xfer length of this request will overflow my array qbuffer */ 2287ad6d6297SScott Long wqbuf_lastindex = acb->wqbuf_lastindex; 2288ad6d6297SScott Long wqbuf_firstindex = acb->wqbuf_firstindex; 2289ad6d6297SScott Long if(wqbuf_lastindex != wqbuf_firstindex) { 22907a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2291ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR; 2292ad6d6297SScott Long } else { 22937a7bc959SXin LI my_empty_len = (wqbuf_firstindex - wqbuf_lastindex - 1) & 22947a7bc959SXin LI (ARCMSR_MAX_QBUFFER - 1); 2295ad6d6297SScott Long if(my_empty_len >= user_len) { 2296ad6d6297SScott Long while(user_len > 0) { 2297f1c579b1SScott Long /*copy srb data to wqbuffer*/ 2298ad6d6297SScott Long pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; 22997a7bc959SXin LI *pQbuffer = *ptmpuserbuffer; 2300ad6d6297SScott Long acb->wqbuf_lastindex++; 2301ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 2302ad6d6297SScott Long /*if last index number set it to 0 */ 2303f1c579b1SScott Long ptmpuserbuffer++; 2304f1c579b1SScott Long user_len--; 2305f1c579b1SScott Long } 2306f1c579b1SScott Long /*post fist Qbuffer*/ 2307ad6d6297SScott Long if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 2308ad6d6297SScott Long acb->acb_flags &= ~ACB_F_MESSAGE_WQBUFFER_CLEARED; 23097a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2310f1c579b1SScott Long } 2311ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2312ad6d6297SScott Long } else { 2313ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR; 2314f1c579b1SScott Long } 2315f1c579b1SScott Long } 2316ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2317f1c579b1SScott Long } 2318f1c579b1SScott Long break; 2319ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 2320ad6d6297SScott Long u_int8_t *pQbuffer = acb->rqbuffer; 2321ad6d6297SScott Long 2322ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2323ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 232444f05562SScott Long arcmsr_iop_message_read(acb); 232544f05562SScott Long /*signature, let IOP know data has been readed */ 2326f1c579b1SScott Long } 2327ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 2328ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2329ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2330f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2331ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2332ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2333f1c579b1SScott Long } 2334f1c579b1SScott Long break; 2335ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: 2336f1c579b1SScott Long { 2337ad6d6297SScott Long u_int8_t *pQbuffer = acb->wqbuffer; 2338f1c579b1SScott Long 2339ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2340ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 234144f05562SScott Long arcmsr_iop_message_read(acb); 234244f05562SScott Long /*signature, let IOP know data has been readed */ 2343f1c579b1SScott Long } 234444f05562SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ); 2345ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2346ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2347f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2348ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2349ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2350f1c579b1SScott Long } 2351f1c579b1SScott Long break; 2352ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 2353ad6d6297SScott Long u_int8_t *pQbuffer; 2354f1c579b1SScott Long 2355ad6d6297SScott Long if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2356ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 235744f05562SScott Long arcmsr_iop_message_read(acb); 235844f05562SScott Long /*signature, let IOP know data has been readed */ 2359f1c579b1SScott Long } 2360ad6d6297SScott Long acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED 2361ad6d6297SScott Long |ACB_F_MESSAGE_RQBUFFER_CLEARED 236244f05562SScott Long |ACB_F_MESSAGE_WQBUFFER_READ); 2363ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2364ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2365ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2366ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2367ad6d6297SScott Long pQbuffer = acb->rqbuffer; 2368ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 2369ad6d6297SScott Long pQbuffer = acb->wqbuffer; 2370ad6d6297SScott Long memset(pQbuffer, 0, sizeof(struct QBUFFER)); 2371ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2372ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2373f1c579b1SScott Long } 2374f1c579b1SScott Long break; 2375ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 2376ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; 2377ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2378f1c579b1SScott Long } 2379f1c579b1SScott Long break; 2380ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 2381ad6d6297SScott Long u_int8_t *hello_string = "Hello! I am ARCMSR"; 2382ad6d6297SScott Long u_int8_t *puserbuffer = (u_int8_t *)pcmdmessagefld->messagedatabuffer; 2383f1c579b1SScott Long 2384ad6d6297SScott Long if(memcpy(puserbuffer, hello_string, (int16_t)strlen(hello_string))) { 2385ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR; 2386ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2387f1c579b1SScott Long return ENOIOCTL; 2388f1c579b1SScott Long } 2389ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2390ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2391ad6d6297SScott Long } 2392ad6d6297SScott Long break; 2393ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: { 2394ad6d6297SScott Long arcmsr_iop_parking(acb); 2395ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2396ad6d6297SScott Long } 2397ad6d6297SScott Long break; 2398ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: { 2399ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2400ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 2401f1c579b1SScott Long } 2402f1c579b1SScott Long break; 2403f1c579b1SScott Long } 2404ad6d6297SScott Long ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2405dac36688SXin LI return (retvalue); 2406f1c579b1SScott Long } 2407f1c579b1SScott Long /* 2408f1c579b1SScott Long ************************************************************************** 2409f1c579b1SScott Long ************************************************************************** 2410f1c579b1SScott Long */ 241122f2616bSXin LI static void arcmsr_free_srb(struct CommandControlBlock *srb) 241222f2616bSXin LI { 241322f2616bSXin LI struct AdapterControlBlock *acb; 241422f2616bSXin LI 241522f2616bSXin LI acb = srb->acb; 24167a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->srb_lock); 241722f2616bSXin LI srb->srb_state = ARCMSR_SRB_DONE; 241822f2616bSXin LI srb->srb_flags = 0; 241922f2616bSXin LI acb->srbworkingQ[acb->workingsrb_doneindex] = srb; 242022f2616bSXin LI acb->workingsrb_doneindex++; 242122f2616bSXin LI acb->workingsrb_doneindex %= ARCMSR_MAX_FREESRB_NUM; 24227a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->srb_lock); 242322f2616bSXin LI } 242422f2616bSXin LI /* 242522f2616bSXin LI ************************************************************************** 242622f2616bSXin LI ************************************************************************** 242722f2616bSXin LI */ 2428ad6d6297SScott Long struct CommandControlBlock *arcmsr_get_freesrb(struct AdapterControlBlock *acb) 2429f1c579b1SScott Long { 2430ad6d6297SScott Long struct CommandControlBlock *srb = NULL; 2431ad6d6297SScott Long u_int32_t workingsrb_startindex, workingsrb_doneindex; 2432f1c579b1SScott Long 24337a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->srb_lock); 2434ad6d6297SScott Long workingsrb_doneindex = acb->workingsrb_doneindex; 2435ad6d6297SScott Long workingsrb_startindex = acb->workingsrb_startindex; 2436ad6d6297SScott Long srb = acb->srbworkingQ[workingsrb_startindex]; 2437ad6d6297SScott Long workingsrb_startindex++; 2438ad6d6297SScott Long workingsrb_startindex %= ARCMSR_MAX_FREESRB_NUM; 2439ad6d6297SScott Long if(workingsrb_doneindex != workingsrb_startindex) { 2440ad6d6297SScott Long acb->workingsrb_startindex = workingsrb_startindex; 2441ad6d6297SScott Long } else { 2442ad6d6297SScott Long srb = NULL; 2443ad6d6297SScott Long } 24447a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->srb_lock); 2445ad6d6297SScott Long return(srb); 2446ad6d6297SScott Long } 2447ad6d6297SScott Long /* 2448ad6d6297SScott Long ************************************************************************** 2449ad6d6297SScott Long ************************************************************************** 2450ad6d6297SScott Long */ 2451ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *pccb) 2452ad6d6297SScott Long { 2453ad6d6297SScott Long struct CMD_MESSAGE_FIELD *pcmdmessagefld; 2454ad6d6297SScott Long int retvalue = 0, transfer_len = 0; 2455ad6d6297SScott Long char *buffer; 2456*4aa947cbSWarner Losh uint8_t *ptr = scsiio_cdb_ptr(&pccb->csio); 2457*4aa947cbSWarner Losh u_int32_t controlcode = (u_int32_t ) ptr[5] << 24 | 2458*4aa947cbSWarner Losh (u_int32_t ) ptr[6] << 16 | 2459*4aa947cbSWarner Losh (u_int32_t ) ptr[7] << 8 | 2460*4aa947cbSWarner Losh (u_int32_t ) ptr[8]; 2461ad6d6297SScott Long /* 4 bytes: Areca io control code */ 2462dd0b4fb6SKonstantin Belousov if ((pccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) { 2463ad6d6297SScott Long buffer = pccb->csio.data_ptr; 2464ad6d6297SScott Long transfer_len = pccb->csio.dxfer_len; 2465ad6d6297SScott Long } else { 2466ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2467ad6d6297SScott Long goto message_out; 2468ad6d6297SScott Long } 2469ad6d6297SScott Long if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) { 2470ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2471ad6d6297SScott Long goto message_out; 2472ad6d6297SScott Long } 2473ad6d6297SScott Long pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer; 2474ad6d6297SScott Long switch(controlcode) { 2475ad6d6297SScott Long case ARCMSR_MESSAGE_READ_RQBUFFER: { 2476ad6d6297SScott Long u_int8_t *pQbuffer; 2477ad6d6297SScott Long u_int8_t *ptmpQbuffer = pcmdmessagefld->messagedatabuffer; 2478ad6d6297SScott Long int32_t allxfer_len = 0; 2479f1c579b1SScott Long 24807a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2481ad6d6297SScott Long while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) 2482ad6d6297SScott Long && (allxfer_len < 1031)) { 2483ad6d6297SScott Long pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; 24847a7bc959SXin LI *ptmpQbuffer = *pQbuffer; 2485ad6d6297SScott Long acb->rqbuf_firstindex++; 2486ad6d6297SScott Long acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; 2487ad6d6297SScott Long ptmpQbuffer++; 2488ad6d6297SScott Long allxfer_len++; 2489f1c579b1SScott Long } 2490ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 249144f05562SScott Long struct QBUFFER *prbuffer; 2492ad6d6297SScott Long 2493ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 249444f05562SScott Long prbuffer = arcmsr_get_iop_rqbuffer(acb); 249535689395SXin LI if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0) 249635689395SXin LI acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; 2497ad6d6297SScott Long } 2498ad6d6297SScott Long pcmdmessagefld->cmdmessage.Length = allxfer_len; 2499ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2500ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_SUCCESS; 25017a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2502ad6d6297SScott Long } 2503ad6d6297SScott Long break; 2504ad6d6297SScott Long case ARCMSR_MESSAGE_WRITE_WQBUFFER: { 2505ad6d6297SScott Long int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; 2506ad6d6297SScott Long u_int8_t *pQbuffer; 2507ad6d6297SScott Long u_int8_t *ptmpuserbuffer = pcmdmessagefld->messagedatabuffer; 2508ad6d6297SScott Long 2509ad6d6297SScott Long user_len = pcmdmessagefld->cmdmessage.Length; 25107a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2511ad6d6297SScott Long wqbuf_lastindex = acb->wqbuf_lastindex; 2512ad6d6297SScott Long wqbuf_firstindex = acb->wqbuf_firstindex; 2513ad6d6297SScott Long if (wqbuf_lastindex != wqbuf_firstindex) { 25147a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2515ad6d6297SScott Long /* has error report sensedata */ 2516dac36688SXin LI if(pccb->csio.sense_len) { 2517ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 2518ad6d6297SScott Long /* Valid,ErrorCode */ 2519ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 2520ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 2521ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 2522ad6d6297SScott Long /* AdditionalSenseLength */ 2523ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 2524ad6d6297SScott Long /* AdditionalSenseCode */ 2525ad6d6297SScott Long } 2526ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2527ad6d6297SScott Long } else { 2528ad6d6297SScott Long my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) 2529ad6d6297SScott Long &(ARCMSR_MAX_QBUFFER - 1); 2530ad6d6297SScott Long if (my_empty_len >= user_len) { 2531ad6d6297SScott Long while (user_len > 0) { 2532ad6d6297SScott Long pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex]; 25337a7bc959SXin LI *pQbuffer = *ptmpuserbuffer; 2534ad6d6297SScott Long acb->wqbuf_lastindex++; 2535ad6d6297SScott Long acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; 2536ad6d6297SScott Long ptmpuserbuffer++; 2537ad6d6297SScott Long user_len--; 2538ad6d6297SScott Long } 2539ad6d6297SScott Long if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { 2540ad6d6297SScott Long acb->acb_flags &= 2541ad6d6297SScott Long ~ACB_F_MESSAGE_WQBUFFER_CLEARED; 25427a7bc959SXin LI arcmsr_Write_data_2iop_wqbuffer(acb); 2543ad6d6297SScott Long } 2544ad6d6297SScott Long } else { 2545ad6d6297SScott Long /* has error report sensedata */ 2546dac36688SXin LI if(pccb->csio.sense_len) { 2547ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); 2548ad6d6297SScott Long /* Valid,ErrorCode */ 2549ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05; 2550ad6d6297SScott Long /* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */ 2551ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A; 2552ad6d6297SScott Long /* AdditionalSenseLength */ 2553ad6d6297SScott Long ((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20; 2554ad6d6297SScott Long /* AdditionalSenseCode */ 2555ad6d6297SScott Long } 2556ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2557ad6d6297SScott Long } 2558ad6d6297SScott Long } 25597a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2560ad6d6297SScott Long } 2561ad6d6297SScott Long break; 2562ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { 2563ad6d6297SScott Long u_int8_t *pQbuffer = acb->rqbuffer; 2564ad6d6297SScott Long 25657a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2566ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2567ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 256844f05562SScott Long arcmsr_iop_message_read(acb); 2569ad6d6297SScott Long } 2570ad6d6297SScott Long acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; 2571ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2572ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2573ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2574ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 2575ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 25767a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2577ad6d6297SScott Long } 2578ad6d6297SScott Long break; 2579ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { 2580ad6d6297SScott Long u_int8_t *pQbuffer = acb->wqbuffer; 2581ad6d6297SScott Long 25827a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2583ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2584ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 258544f05562SScott Long arcmsr_iop_message_read(acb); 2586ad6d6297SScott Long } 2587ad6d6297SScott Long acb->acb_flags |= 2588ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED | 258944f05562SScott Long ACB_F_MESSAGE_WQBUFFER_READ); 2590ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2591ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2592ad6d6297SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 2593ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = 2594ad6d6297SScott Long ARCMSR_MESSAGE_RETURNCODE_OK; 25957a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2596ad6d6297SScott Long } 2597ad6d6297SScott Long break; 2598ad6d6297SScott Long case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { 2599ad6d6297SScott Long u_int8_t *pQbuffer; 2600ad6d6297SScott Long 26017a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock); 2602ad6d6297SScott Long if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { 2603ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 260444f05562SScott Long arcmsr_iop_message_read(acb); 2605ad6d6297SScott Long } 2606ad6d6297SScott Long acb->acb_flags |= 2607ad6d6297SScott Long (ACB_F_MESSAGE_WQBUFFER_CLEARED 2608ad6d6297SScott Long | ACB_F_MESSAGE_RQBUFFER_CLEARED 260944f05562SScott Long | ACB_F_MESSAGE_WQBUFFER_READ); 2610ad6d6297SScott Long acb->rqbuf_firstindex = 0; 2611ad6d6297SScott Long acb->rqbuf_lastindex = 0; 2612ad6d6297SScott Long acb->wqbuf_firstindex = 0; 2613ad6d6297SScott Long acb->wqbuf_lastindex = 0; 2614ad6d6297SScott Long pQbuffer = acb->rqbuffer; 2615ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 2616ad6d6297SScott Long pQbuffer = acb->wqbuffer; 2617ad6d6297SScott Long memset(pQbuffer, 0, sizeof (struct QBUFFER)); 2618ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 26197a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock); 2620ad6d6297SScott Long } 2621ad6d6297SScott Long break; 2622ad6d6297SScott Long case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: { 2623ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; 2624ad6d6297SScott Long } 2625ad6d6297SScott Long break; 2626ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_HELLO: { 2627ad6d6297SScott Long int8_t *hello_string = "Hello! I am ARCMSR"; 2628ad6d6297SScott Long 2629ad6d6297SScott Long memcpy(pcmdmessagefld->messagedatabuffer, hello_string 2630ad6d6297SScott Long , (int16_t)strlen(hello_string)); 2631ad6d6297SScott Long pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; 2632ad6d6297SScott Long } 2633ad6d6297SScott Long break; 2634ad6d6297SScott Long case ARCMSR_MESSAGE_SAY_GOODBYE: 2635ad6d6297SScott Long arcmsr_iop_parking(acb); 2636ad6d6297SScott Long break; 2637ad6d6297SScott Long case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: 2638ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 2639ad6d6297SScott Long break; 2640ad6d6297SScott Long default: 2641ad6d6297SScott Long retvalue = ARCMSR_MESSAGE_FAIL; 2642ad6d6297SScott Long } 2643ad6d6297SScott Long message_out: 2644dac36688SXin LI return (retvalue); 2645f1c579b1SScott Long } 2646f1c579b1SScott Long /* 2647f1c579b1SScott Long ********************************************************************* 2648f1c579b1SScott Long ********************************************************************* 2649f1c579b1SScott Long */ 2650231c8b71SXin LI static void arcmsr_execute_srb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 2651f1c579b1SScott Long { 2652ad6d6297SScott Long struct CommandControlBlock *srb = (struct CommandControlBlock *)arg; 2653ad6d6297SScott Long struct AdapterControlBlock *acb = (struct AdapterControlBlock *)srb->acb; 2654f1c579b1SScott Long union ccb *pccb; 2655ad6d6297SScott Long int target, lun; 2656f1c579b1SScott Long 2657ad6d6297SScott Long pccb = srb->pccb; 2658ad6d6297SScott Long target = pccb->ccb_h.target_id; 2659ad6d6297SScott Long lun = pccb->ccb_h.target_lun; 266022f2616bSXin LI acb->pktRequestCount++; 2661ad6d6297SScott Long if(error != 0) { 2662ad6d6297SScott Long if(error != EFBIG) { 266344f05562SScott Long printf("arcmsr%d: unexpected error %x" 266444f05562SScott Long " returned from 'bus_dmamap_load' \n" 2665ad6d6297SScott Long , acb->pci_unit, error); 2666f1c579b1SScott Long } 2667ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) { 266815735becSScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 2669f1c579b1SScott Long } 2670ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2671f1c579b1SScott Long return; 2672f1c579b1SScott Long } 2673ad6d6297SScott Long if(nseg > ARCMSR_MAX_SG_ENTRIES) { 2674ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_TOO_BIG; 2675ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2676ad6d6297SScott Long return; 2677f1c579b1SScott Long } 2678ad6d6297SScott Long if(acb->acb_flags & ACB_F_BUS_RESET) { 2679ad6d6297SScott Long printf("arcmsr%d: bus reset and return busy \n", acb->pci_unit); 2680ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_BUS_RESET; 2681ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2682ad6d6297SScott Long return; 2683ad6d6297SScott Long } 2684ad6d6297SScott Long if(acb->devstate[target][lun] == ARECA_RAID_GONE) { 268522f2616bSXin LI u_int8_t block_cmd, cmd; 2686ad6d6297SScott Long 2687*4aa947cbSWarner Losh cmd = scsiio_cdb_ptr(&pccb->csio)[0]; 268822f2616bSXin LI block_cmd = cmd & 0x0f; 2689ad6d6297SScott Long if(block_cmd == 0x08 || block_cmd == 0x0a) { 2690ad6d6297SScott Long printf("arcmsr%d:block 'read/write' command " 269122f2616bSXin LI "with gone raid volume Cmd=0x%2x, TargetId=%d, Lun=%d \n" 269222f2616bSXin LI , acb->pci_unit, cmd, target, lun); 2693ad6d6297SScott Long pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 2694ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2695ad6d6297SScott Long return; 2696ad6d6297SScott Long } 2697ad6d6297SScott Long } 2698ad6d6297SScott Long if((pccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { 2699ad6d6297SScott Long if(nseg != 0) { 2700ad6d6297SScott Long bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap); 2701ad6d6297SScott Long } 2702ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2703f1c579b1SScott Long return; 2704f1c579b1SScott Long } 2705abfdbca9SXin LI if(acb->srboutstandingcount >= acb->maxOutstanding) { 27067a7bc959SXin LI if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) == 0) 27077a7bc959SXin LI { 270815735becSScott Long xpt_freeze_simq(acb->psim, 1); 2709dc3a205bSScott Long acb->acb_flags |= ACB_F_CAM_DEV_QFRZN; 27107a7bc959SXin LI } 27117a7bc959SXin LI pccb->ccb_h.status &= ~CAM_SIM_QUEUED; 27127a7bc959SXin LI pccb->ccb_h.status |= CAM_REQUEUE_REQ; 2713ad6d6297SScott Long arcmsr_srb_complete(srb, 0); 2714ad6d6297SScott Long return; 2715f1c579b1SScott Long } 271615735becSScott Long pccb->ccb_h.status |= CAM_SIM_QUEUED; 2717ad6d6297SScott Long arcmsr_build_srb(srb, dm_segs, nseg); 2718ad6d6297SScott Long arcmsr_post_srb(acb, srb); 271922f2616bSXin LI if (pccb->ccb_h.timeout != CAM_TIME_INFINITY) 272022f2616bSXin LI { 272122f2616bSXin LI arcmsr_callout_init(&srb->ccb_callout); 272285c9dd9dSSteven Hartland callout_reset_sbt(&srb->ccb_callout, SBT_1MS * 272385c9dd9dSSteven Hartland (pccb->ccb_h.timeout + (ARCMSR_TIMEOUT_DELAY * 1000)), 0, 272485c9dd9dSSteven Hartland arcmsr_srb_timeout, srb, 0); 272522f2616bSXin LI srb->srb_flags |= SRB_FLAG_TIMER_START; 272622f2616bSXin LI } 2727f1c579b1SScott Long } 2728f1c579b1SScott Long /* 2729f1c579b1SScott Long ***************************************************************************************** 2730f1c579b1SScott Long ***************************************************************************************** 2731f1c579b1SScott Long */ 2732ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb *abortccb) 2733f1c579b1SScott Long { 2734ad6d6297SScott Long struct CommandControlBlock *srb; 2735ad6d6297SScott Long struct AdapterControlBlock *acb = (struct AdapterControlBlock *) abortccb->ccb_h.arcmsr_ccbacb_ptr; 273644f05562SScott Long u_int32_t intmask_org; 2737ad6d6297SScott Long int i = 0; 2738f1c579b1SScott Long 2739ad6d6297SScott Long acb->num_aborts++; 2740f1c579b1SScott Long /* 2741ad6d6297SScott Long *************************************************************************** 2742f1c579b1SScott Long ** It is the upper layer do abort command this lock just prior to calling us. 2743f1c579b1SScott Long ** First determine if we currently own this command. 2744f1c579b1SScott Long ** Start by searching the device queue. If not found 2745f1c579b1SScott Long ** at all, and the system wanted us to just abort the 2746f1c579b1SScott Long ** command return success. 2747ad6d6297SScott Long *************************************************************************** 2748f1c579b1SScott Long */ 2749ad6d6297SScott Long if(acb->srboutstandingcount != 0) { 275022f2616bSXin LI /* disable all outbound interrupt */ 275122f2616bSXin LI intmask_org = arcmsr_disable_allintr(acb); 2752ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 2753ad6d6297SScott Long srb = acb->psrb_pool[i]; 275422f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) { 2755ad6d6297SScott Long if(srb->pccb == abortccb) { 275622f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 2757123055f0SNathan Whitehorn printf("arcmsr%d:scsi id=%d lun=%jx abort srb '%p'" 2758ad6d6297SScott Long "outstanding command \n" 2759ad6d6297SScott Long , acb->pci_unit, abortccb->ccb_h.target_id 2760123055f0SNathan Whitehorn , (uintmax_t)abortccb->ccb_h.target_lun, srb); 2761ad6d6297SScott Long arcmsr_polling_srbdone(acb, srb); 276244f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 276344f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 2764ad6d6297SScott Long return (TRUE); 2765f1c579b1SScott Long } 276622f2616bSXin LI } 276722f2616bSXin LI } 276822f2616bSXin LI /* enable outbound Post Queue, outbound doorbell Interrupt */ 276922f2616bSXin LI arcmsr_enable_allintr(acb, intmask_org); 277022f2616bSXin LI } 277122f2616bSXin LI return(FALSE); 277222f2616bSXin LI } 2773f1c579b1SScott Long /* 2774f1c579b1SScott Long **************************************************************************** 2775f1c579b1SScott Long **************************************************************************** 2776f1c579b1SScott Long */ 2777ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb) 2778f1c579b1SScott Long { 2779ad6d6297SScott Long int retry = 0; 2780f1c579b1SScott Long 2781ad6d6297SScott Long acb->num_resets++; 2782ad6d6297SScott Long acb->acb_flags |= ACB_F_BUS_RESET; 2783ad6d6297SScott Long while(acb->srboutstandingcount != 0 && retry < 400) { 278444f05562SScott Long arcmsr_interrupt(acb); 2785ad6d6297SScott Long UDELAY(25000); 2786ad6d6297SScott Long retry++; 2787ad6d6297SScott Long } 2788ad6d6297SScott Long arcmsr_iop_reset(acb); 2789ad6d6297SScott Long acb->acb_flags &= ~ACB_F_BUS_RESET; 2790f1c579b1SScott Long } 2791f1c579b1SScott Long /* 2792ad6d6297SScott Long ************************************************************************** 2793ad6d6297SScott Long ************************************************************************** 2794ad6d6297SScott Long */ 2795ad6d6297SScott Long static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb, 2796ad6d6297SScott Long union ccb *pccb) 2797ad6d6297SScott Long { 2798ad6d6297SScott Long if (pccb->ccb_h.target_lun) { 279961ba2ac6SJim Harris pccb->ccb_h.status |= CAM_DEV_NOT_THERE; 2800ad6d6297SScott Long xpt_done(pccb); 2801ad6d6297SScott Long return; 2802ad6d6297SScott Long } 28037a7bc959SXin LI pccb->ccb_h.status |= CAM_REQ_CMP; 2804*4aa947cbSWarner Losh switch (scsiio_cdb_ptr(&pccb->csio)[0]) { 28057a7bc959SXin LI case INQUIRY: { 28067a7bc959SXin LI unsigned char inqdata[36]; 28077a7bc959SXin LI char *buffer = pccb->csio.data_ptr; 28087a7bc959SXin LI 2809231c8b71SXin LI inqdata[0] = T_PROCESSOR; /* Periph Qualifier & Periph Dev Type */ 2810231c8b71SXin LI inqdata[1] = 0; /* rem media bit & Dev Type Modifier */ 2811231c8b71SXin LI inqdata[2] = 0; /* ISO, ECMA, & ANSI versions */ 2812231c8b71SXin LI inqdata[3] = 0; 2813231c8b71SXin LI inqdata[4] = 31; /* length of additional data */ 2814231c8b71SXin LI inqdata[5] = 0; 2815231c8b71SXin LI inqdata[6] = 0; 2816231c8b71SXin LI inqdata[7] = 0; 2817231c8b71SXin LI strncpy(&inqdata[8], "Areca ", 8); /* Vendor Identification */ 2818231c8b71SXin LI strncpy(&inqdata[16], "RAID controller ", 16); /* Product Identification */ 2819ad6d6297SScott Long strncpy(&inqdata[32], "R001", 4); /* Product Revision */ 2820ad6d6297SScott Long memcpy(buffer, inqdata, sizeof(inqdata)); 2821ad6d6297SScott Long xpt_done(pccb); 2822ad6d6297SScott Long } 2823ad6d6297SScott Long break; 2824ad6d6297SScott Long case WRITE_BUFFER: 2825ad6d6297SScott Long case READ_BUFFER: { 2826ad6d6297SScott Long if (arcmsr_iop_message_xfer(acb, pccb)) { 2827ad6d6297SScott Long pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 2828ad6d6297SScott Long pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 2829ad6d6297SScott Long } 2830ad6d6297SScott Long xpt_done(pccb); 2831ad6d6297SScott Long } 2832ad6d6297SScott Long break; 2833ad6d6297SScott Long default: 2834ad6d6297SScott Long xpt_done(pccb); 2835ad6d6297SScott Long } 2836ad6d6297SScott Long } 2837ad6d6297SScott Long /* 2838f1c579b1SScott Long ********************************************************************* 2839f1c579b1SScott Long ********************************************************************* 2840f1c579b1SScott Long */ 2841ad6d6297SScott Long static void arcmsr_action(struct cam_sim *psim, union ccb *pccb) 2842f1c579b1SScott Long { 2843ad6d6297SScott Long struct AdapterControlBlock *acb; 2844f1c579b1SScott Long 2845ad6d6297SScott Long acb = (struct AdapterControlBlock *) cam_sim_softc(psim); 2846ad6d6297SScott Long if(acb == NULL) { 2847ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2848f1c579b1SScott Long xpt_done(pccb); 2849f1c579b1SScott Long return; 2850f1c579b1SScott Long } 2851ad6d6297SScott Long switch (pccb->ccb_h.func_code) { 2852ad6d6297SScott Long case XPT_SCSI_IO: { 2853ad6d6297SScott Long struct CommandControlBlock *srb; 2854ad6d6297SScott Long int target = pccb->ccb_h.target_id; 2855dd0b4fb6SKonstantin Belousov int error; 2856f1c579b1SScott Long 2857*4aa947cbSWarner Losh if (pccb->ccb_h.flags & CAM_CDB_PHYS) { 2858*4aa947cbSWarner Losh pccb->ccb_h.status = CAM_REQ_INVALID; 2859*4aa947cbSWarner Losh xpt_done(pccb); 2860*4aa947cbSWarner Losh return; 2861*4aa947cbSWarner Losh } 2862*4aa947cbSWarner Losh 2863ad6d6297SScott Long if(target == 16) { 2864ad6d6297SScott Long /* virtual device for iop message transfer */ 2865ad6d6297SScott Long arcmsr_handle_virtual_command(acb, pccb); 2866ad6d6297SScott Long return; 2867ad6d6297SScott Long } 2868ad6d6297SScott Long if((srb = arcmsr_get_freesrb(acb)) == NULL) { 2869ad6d6297SScott Long pccb->ccb_h.status |= CAM_RESRC_UNAVAIL; 2870f1c579b1SScott Long xpt_done(pccb); 2871f1c579b1SScott Long return; 2872f1c579b1SScott Long } 2873ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbsrb_ptr = srb; 2874ad6d6297SScott Long pccb->ccb_h.arcmsr_ccbacb_ptr = acb; 2875ad6d6297SScott Long srb->pccb = pccb; 2876dd0b4fb6SKonstantin Belousov error = bus_dmamap_load_ccb(acb->dm_segs_dmat 2877ad6d6297SScott Long , srb->dm_segs_dmamap 2878dd0b4fb6SKonstantin Belousov , pccb 2879231c8b71SXin LI , arcmsr_execute_srb, srb, /*flags*/0); 2880ad6d6297SScott Long if(error == EINPROGRESS) { 2881ad6d6297SScott Long xpt_freeze_simq(acb->psim, 1); 2882f1c579b1SScott Long pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 2883f1c579b1SScott Long } 2884f1c579b1SScott Long break; 2885f1c579b1SScott Long } 2886ad6d6297SScott Long case XPT_TARGET_IO: { 2887ad6d6297SScott Long /* target mode not yet support vendor specific commands. */ 2888ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2889f1c579b1SScott Long xpt_done(pccb); 2890f1c579b1SScott Long break; 2891f1c579b1SScott Long } 2892ad6d6297SScott Long case XPT_PATH_INQ: { 2893f1c579b1SScott Long struct ccb_pathinq *cpi = &pccb->cpi; 2894f1c579b1SScott Long 2895f1c579b1SScott Long cpi->version_num = 1; 2896f1c579b1SScott Long cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE; 2897f1c579b1SScott Long cpi->target_sprt = 0; 2898f1c579b1SScott Long cpi->hba_misc = 0; 2899f1c579b1SScott Long cpi->hba_eng_cnt = 0; 2900ad6d6297SScott Long cpi->max_target = ARCMSR_MAX_TARGETID; /* 0-16 */ 2901ad6d6297SScott Long cpi->max_lun = ARCMSR_MAX_TARGETLUN; /* 0-7 */ 2902ad6d6297SScott Long cpi->initiator_id = ARCMSR_SCSI_INITIATOR_ID; /* 255 */ 2903f1c579b1SScott Long cpi->bus_id = cam_sim_bus(psim); 2904f1c579b1SScott Long strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 2905f1c579b1SScott Long strncpy(cpi->hba_vid, "ARCMSR", HBA_IDLEN); 2906f1c579b1SScott Long strncpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN); 2907f1c579b1SScott Long cpi->unit_number = cam_sim_unit(psim); 290844f05562SScott Long #ifdef CAM_NEW_TRAN_CODE 2909224a78aeSXin LI if(acb->adapter_bus_speed == ACB_BUS_SPEED_12G) 2910224a78aeSXin LI cpi->base_transfer_speed = 1200000; 2911224a78aeSXin LI else if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G) 2912dac36688SXin LI cpi->base_transfer_speed = 600000; 2913dac36688SXin LI else 2914dac36688SXin LI cpi->base_transfer_speed = 300000; 2915dac36688SXin LI if((acb->vendor_device_id == PCIDevVenIDARC1880) || 29167a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1680) || 29177a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1214)) 2918dac36688SXin LI { 2919dac36688SXin LI cpi->transport = XPORT_SAS; 2920dac36688SXin LI cpi->transport_version = 0; 2921dac36688SXin LI cpi->protocol_version = SCSI_REV_SPC2; 2922dac36688SXin LI } 2923dac36688SXin LI else 2924dac36688SXin LI { 2925fa9ed865SMatt Jacob cpi->transport = XPORT_SPI; 2926fa9ed865SMatt Jacob cpi->transport_version = 2; 2927fa9ed865SMatt Jacob cpi->protocol_version = SCSI_REV_2; 2928dac36688SXin LI } 2929dac36688SXin LI cpi->protocol = PROTO_SCSI; 293044f05562SScott Long #endif 2931ad6d6297SScott Long cpi->ccb_h.status |= CAM_REQ_CMP; 2932f1c579b1SScott Long xpt_done(pccb); 2933f1c579b1SScott Long break; 2934f1c579b1SScott Long } 2935ad6d6297SScott Long case XPT_ABORT: { 2936f1c579b1SScott Long union ccb *pabort_ccb; 2937f1c579b1SScott Long 2938f1c579b1SScott Long pabort_ccb = pccb->cab.abort_ccb; 2939ad6d6297SScott Long switch (pabort_ccb->ccb_h.func_code) { 2940f1c579b1SScott Long case XPT_ACCEPT_TARGET_IO: 2941f1c579b1SScott Long case XPT_IMMED_NOTIFY: 2942f1c579b1SScott Long case XPT_CONT_TARGET_IO: 2943ad6d6297SScott Long if(arcmsr_seek_cmd2abort(pabort_ccb)==TRUE) { 2944ad6d6297SScott Long pabort_ccb->ccb_h.status |= CAM_REQ_ABORTED; 2945f1c579b1SScott Long xpt_done(pabort_ccb); 2946ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2947ad6d6297SScott Long } else { 2948f1c579b1SScott Long xpt_print_path(pabort_ccb->ccb_h.path); 2949f1c579b1SScott Long printf("Not found\n"); 2950ad6d6297SScott Long pccb->ccb_h.status |= CAM_PATH_INVALID; 2951f1c579b1SScott Long } 2952f1c579b1SScott Long break; 2953f1c579b1SScott Long case XPT_SCSI_IO: 2954ad6d6297SScott Long pccb->ccb_h.status |= CAM_UA_ABORT; 2955f1c579b1SScott Long break; 2956f1c579b1SScott Long default: 2957ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2958f1c579b1SScott Long break; 2959f1c579b1SScott Long } 2960f1c579b1SScott Long xpt_done(pccb); 2961f1c579b1SScott Long break; 2962f1c579b1SScott Long } 2963f1c579b1SScott Long case XPT_RESET_BUS: 2964ad6d6297SScott Long case XPT_RESET_DEV: { 2965ad6d6297SScott Long u_int32_t i; 2966f1c579b1SScott Long 2967ad6d6297SScott Long arcmsr_bus_reset(acb); 2968ad6d6297SScott Long for (i=0; i < 500; i++) { 2969f1c579b1SScott Long DELAY(1000); 2970f1c579b1SScott Long } 2971ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 2972f1c579b1SScott Long xpt_done(pccb); 2973f1c579b1SScott Long break; 2974f1c579b1SScott Long } 2975ad6d6297SScott Long case XPT_TERM_IO: { 2976ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 2977f1c579b1SScott Long xpt_done(pccb); 2978f1c579b1SScott Long break; 2979f1c579b1SScott Long } 2980ad6d6297SScott Long case XPT_GET_TRAN_SETTINGS: { 2981ad6d6297SScott Long struct ccb_trans_settings *cts; 2982ad6d6297SScott Long 2983ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 2984ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 2985ad6d6297SScott Long xpt_done(pccb); 2986ad6d6297SScott Long break; 2987ad6d6297SScott Long } 2988ad6d6297SScott Long cts = &pccb->cts; 298944f05562SScott Long #ifdef CAM_NEW_TRAN_CODE 299044f05562SScott Long { 299144f05562SScott Long struct ccb_trans_settings_scsi *scsi; 299244f05562SScott Long struct ccb_trans_settings_spi *spi; 2993dac36688SXin LI struct ccb_trans_settings_sas *sas; 299444f05562SScott Long 2995ad6d6297SScott Long scsi = &cts->proto_specific.scsi; 2996dac36688SXin LI scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 2997dac36688SXin LI scsi->valid = CTS_SCSI_VALID_TQ; 2998fa9ed865SMatt Jacob cts->protocol = PROTO_SCSI; 2999dac36688SXin LI 3000dac36688SXin LI if((acb->vendor_device_id == PCIDevVenIDARC1880) || 30017a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1680) || 30027a7bc959SXin LI (acb->vendor_device_id == PCIDevVenIDARC1214)) 3003dac36688SXin LI { 3004dac36688SXin LI cts->protocol_version = SCSI_REV_SPC2; 3005dac36688SXin LI cts->transport_version = 0; 3006dac36688SXin LI cts->transport = XPORT_SAS; 3007dac36688SXin LI sas = &cts->xport_specific.sas; 3008dac36688SXin LI sas->valid = CTS_SAS_VALID_SPEED; 3009b23a1998SXin LI if (acb->adapter_bus_speed == ACB_BUS_SPEED_12G) 3010224a78aeSXin LI sas->bitrate = 1200000; 3011b23a1998SXin LI else if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G) 3012dac36688SXin LI sas->bitrate = 600000; 3013b23a1998SXin LI else if(acb->adapter_bus_speed == ACB_BUS_SPEED_3G) 3014dac36688SXin LI sas->bitrate = 300000; 3015dac36688SXin LI } 3016dac36688SXin LI else 3017dac36688SXin LI { 3018fa9ed865SMatt Jacob cts->protocol_version = SCSI_REV_2; 3019fa9ed865SMatt Jacob cts->transport_version = 2; 3020dac36688SXin LI cts->transport = XPORT_SPI; 3021dac36688SXin LI spi = &cts->xport_specific.spi; 3022fa9ed865SMatt Jacob spi->flags = CTS_SPI_FLAGS_DISC_ENB; 3023b23a1998SXin LI if (acb->adapter_bus_speed == ACB_BUS_SPEED_6G) 3024b23a1998SXin LI spi->sync_period = 1; 3025b23a1998SXin LI else 3026dac36688SXin LI spi->sync_period = 2; 3027fa9ed865SMatt Jacob spi->sync_offset = 32; 3028fa9ed865SMatt Jacob spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 30299d98ff4dSScott Long spi->valid = CTS_SPI_VALID_DISC 30309d98ff4dSScott Long | CTS_SPI_VALID_SYNC_RATE 3031fa9ed865SMatt Jacob | CTS_SPI_VALID_SYNC_OFFSET 3032fa9ed865SMatt Jacob | CTS_SPI_VALID_BUS_WIDTH; 3033dac36688SXin LI } 303444f05562SScott Long } 303544f05562SScott Long #else 303644f05562SScott Long { 303744f05562SScott Long cts->flags = (CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB); 3038b23a1998SXin LI if (acb->adapter_bus_speed == ACB_BUS_SPEED_6G) 3039b23a1998SXin LI cts->sync_period = 1; 3040b23a1998SXin LI else 3041dac36688SXin LI cts->sync_period = 2; 304244f05562SScott Long cts->sync_offset = 32; 304344f05562SScott Long cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT; 304444f05562SScott Long cts->valid = CCB_TRANS_SYNC_RATE_VALID | 304544f05562SScott Long CCB_TRANS_SYNC_OFFSET_VALID | 304644f05562SScott Long CCB_TRANS_BUS_WIDTH_VALID | 304744f05562SScott Long CCB_TRANS_DISC_VALID | 304844f05562SScott Long CCB_TRANS_TQ_VALID; 304944f05562SScott Long } 305044f05562SScott Long #endif 3051ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 3052ad6d6297SScott Long xpt_done(pccb); 3053ad6d6297SScott Long break; 3054ad6d6297SScott Long } 3055ad6d6297SScott Long case XPT_SET_TRAN_SETTINGS: { 3056ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 3057ad6d6297SScott Long xpt_done(pccb); 3058ad6d6297SScott Long break; 3059ad6d6297SScott Long } 3060f3b080e6SMarius Strobl case XPT_CALC_GEOMETRY: 3061ad6d6297SScott Long if(pccb->ccb_h.target_id == 16) { 3062ad6d6297SScott Long pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL; 3063ad6d6297SScott Long xpt_done(pccb); 3064ad6d6297SScott Long break; 3065ad6d6297SScott Long } 3066f3b080e6SMarius Strobl #if __FreeBSD_version >= 500000 3067f3b080e6SMarius Strobl cam_calc_geometry(&pccb->ccg, 1); 3068f3b080e6SMarius Strobl #else 3069f3b080e6SMarius Strobl { 3070f3b080e6SMarius Strobl struct ccb_calc_geometry *ccg; 3071f3b080e6SMarius Strobl u_int32_t size_mb; 3072f3b080e6SMarius Strobl u_int32_t secs_per_cylinder; 3073f3b080e6SMarius Strobl 3074f1c579b1SScott Long ccg = &pccb->ccg; 3075ad6d6297SScott Long if (ccg->block_size == 0) { 3076ad6d6297SScott Long pccb->ccb_h.status = CAM_REQ_INVALID; 3077ad6d6297SScott Long xpt_done(pccb); 3078ad6d6297SScott Long break; 3079ad6d6297SScott Long } 3080ad6d6297SScott Long if(((1024L * 1024L)/ccg->block_size) < 0) { 3081ad6d6297SScott Long pccb->ccb_h.status = CAM_REQ_INVALID; 3082ad6d6297SScott Long xpt_done(pccb); 3083ad6d6297SScott Long break; 3084ad6d6297SScott Long } 3085f1c579b1SScott Long size_mb = ccg->volume_size/((1024L * 1024L)/ccg->block_size); 3086ad6d6297SScott Long if(size_mb > 1024 ) { 3087f1c579b1SScott Long ccg->heads = 255; 3088f1c579b1SScott Long ccg->secs_per_track = 63; 3089ad6d6297SScott Long } else { 3090f1c579b1SScott Long ccg->heads = 64; 3091f1c579b1SScott Long ccg->secs_per_track = 32; 3092f1c579b1SScott Long } 3093f1c579b1SScott Long secs_per_cylinder = ccg->heads * ccg->secs_per_track; 3094f1c579b1SScott Long ccg->cylinders = ccg->volume_size / secs_per_cylinder; 3095ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_CMP; 3096f3b080e6SMarius Strobl } 3097f3b080e6SMarius Strobl #endif 3098f1c579b1SScott Long xpt_done(pccb); 3099f1c579b1SScott Long break; 3100f1c579b1SScott Long default: 3101ad6d6297SScott Long pccb->ccb_h.status |= CAM_REQ_INVALID; 3102f1c579b1SScott Long xpt_done(pccb); 3103f1c579b1SScott Long break; 3104f1c579b1SScott Long } 3105f1c579b1SScott Long } 3106f1c579b1SScott Long /* 3107f1c579b1SScott Long ********************************************************************** 3108f1c579b1SScott Long ********************************************************************** 3109f1c579b1SScott Long */ 311044f05562SScott Long static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) 3111f1c579b1SScott Long { 3112ad6d6297SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 311344f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 311444f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 3115ad6d6297SScott Long printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 3116ad6d6297SScott Long } 3117f1c579b1SScott Long } 3118f1c579b1SScott Long /* 3119f1c579b1SScott Long ********************************************************************** 3120f1c579b1SScott Long ********************************************************************** 3121f1c579b1SScott Long */ 312244f05562SScott Long static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb) 312344f05562SScott Long { 3124b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 312544f05562SScott Long acb->acb_flags |= ACB_F_MSG_START_BGRB; 3126b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_START_BGRB); 312744f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 312844f05562SScott Long printf( "arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 312944f05562SScott Long } 313044f05562SScott Long } 313144f05562SScott Long /* 313244f05562SScott Long ********************************************************************** 313344f05562SScott Long ********************************************************************** 313444f05562SScott Long */ 3135d74001adSXin LI static void arcmsr_start_hbc_bgrb(struct AdapterControlBlock *acb) 3136d74001adSXin LI { 3137d74001adSXin LI acb->acb_flags |= ACB_F_MSG_START_BGRB; 3138d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 3139d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 3140d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 3141d74001adSXin LI printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 3142d74001adSXin LI } 3143d74001adSXin LI } 3144d74001adSXin LI /* 3145d74001adSXin LI ********************************************************************** 3146d74001adSXin LI ********************************************************************** 3147d74001adSXin LI */ 31487a7bc959SXin LI static void arcmsr_start_hbd_bgrb(struct AdapterControlBlock *acb) 31497a7bc959SXin LI { 31507a7bc959SXin LI acb->acb_flags |= ACB_F_MSG_START_BGRB; 31517a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB); 31527a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 31537a7bc959SXin LI printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit); 31547a7bc959SXin LI } 31557a7bc959SXin LI } 31567a7bc959SXin LI /* 31577a7bc959SXin LI ********************************************************************** 31587a7bc959SXin LI ********************************************************************** 31597a7bc959SXin LI */ 316044f05562SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) 316144f05562SScott Long { 316244f05562SScott Long switch (acb->adapter_type) { 316344f05562SScott Long case ACB_ADAPTER_TYPE_A: 316444f05562SScott Long arcmsr_start_hba_bgrb(acb); 316544f05562SScott Long break; 316644f05562SScott Long case ACB_ADAPTER_TYPE_B: 316744f05562SScott Long arcmsr_start_hbb_bgrb(acb); 316844f05562SScott Long break; 3169d74001adSXin LI case ACB_ADAPTER_TYPE_C: 3170d74001adSXin LI arcmsr_start_hbc_bgrb(acb); 3171d74001adSXin LI break; 31727a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 31737a7bc959SXin LI arcmsr_start_hbd_bgrb(acb); 31747a7bc959SXin LI break; 317544f05562SScott Long } 317644f05562SScott Long } 317744f05562SScott Long /* 317844f05562SScott Long ********************************************************************** 317944f05562SScott Long ** 318044f05562SScott Long ********************************************************************** 318144f05562SScott Long */ 318244f05562SScott Long static void arcmsr_polling_hba_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 3183f1c579b1SScott Long { 3184ad6d6297SScott Long struct CommandControlBlock *srb; 318544f05562SScott Long u_int32_t flag_srb, outbound_intstatus, poll_srb_done=0, poll_count=0; 3186d74001adSXin LI u_int16_t error; 3187f1c579b1SScott Long 318844f05562SScott Long polling_ccb_retry: 3189ad6d6297SScott Long poll_count++; 3190d74001adSXin LI outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable; 3191d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus); /*clear interrupt*/ 319244f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 3193ad6d6297SScott Long while(1) { 319444f05562SScott Long if((flag_srb = CHIP_REG_READ32(HBA_MessageUnit, 319544f05562SScott Long 0, outbound_queueport)) == 0xFFFFFFFF) { 3196ad6d6297SScott Long if(poll_srb_done) { 3197ad6d6297SScott Long break;/*chip FIFO no ccb for completion already*/ 3198ad6d6297SScott Long } else { 3199ad6d6297SScott Long UDELAY(25000); 3200d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 3201ad6d6297SScott Long break; 3202f1c579b1SScott Long } 320344f05562SScott Long goto polling_ccb_retry; 3204f1c579b1SScott Long } 3205ad6d6297SScott Long } 3206ad6d6297SScott Long /* check if command done with no error*/ 320744f05562SScott Long srb = (struct CommandControlBlock *) 320844f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 3209d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 321044f05562SScott Long poll_srb_done = (srb == poll_srb) ? 1:0; 321122f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 321222f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3213123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'" 3214ad6d6297SScott Long "poll command abort successfully \n" 3215ad6d6297SScott Long , acb->pci_unit 3216ad6d6297SScott Long , srb->pccb->ccb_h.target_id 3217123055f0SNathan Whitehorn , (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 3218ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 3219ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 3220ad6d6297SScott Long continue; 3221ad6d6297SScott Long } 3222ad6d6297SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 3223ad6d6297SScott Long "srboutstandingcount=%d \n" 3224ad6d6297SScott Long , acb->pci_unit 3225ad6d6297SScott Long , srb, acb->srboutstandingcount); 3226ad6d6297SScott Long continue; 3227ad6d6297SScott Long } 3228d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 3229ad6d6297SScott Long } /*drain reply FIFO*/ 3230f1c579b1SScott Long } 3231f1c579b1SScott Long /* 3232f1c579b1SScott Long ********************************************************************** 323344f05562SScott Long ** 3234ad6d6297SScott Long ********************************************************************** 3235ad6d6297SScott Long */ 323644f05562SScott Long static void arcmsr_polling_hbb_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 323744f05562SScott Long { 323844f05562SScott Long struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 323944f05562SScott Long struct CommandControlBlock *srb; 324044f05562SScott Long u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 324144f05562SScott Long int index; 3242d74001adSXin LI u_int16_t error; 324344f05562SScott Long 324444f05562SScott Long polling_ccb_retry: 324544f05562SScott Long poll_count++; 3246b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */ 324744f05562SScott Long bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 324844f05562SScott Long while(1) { 324944f05562SScott Long index = phbbmu->doneq_index; 325044f05562SScott Long if((flag_srb = phbbmu->done_qbuffer[index]) == 0) { 325144f05562SScott Long if(poll_srb_done) { 325244f05562SScott Long break;/*chip FIFO no ccb for completion already*/ 325344f05562SScott Long } else { 325444f05562SScott Long UDELAY(25000); 3255d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 325644f05562SScott Long break; 325744f05562SScott Long } 325844f05562SScott Long goto polling_ccb_retry; 325944f05562SScott Long } 326044f05562SScott Long } 326144f05562SScott Long phbbmu->done_qbuffer[index] = 0; 326244f05562SScott Long index++; 326344f05562SScott Long index %= ARCMSR_MAX_HBB_POSTQUEUE; /*if last index number set it to 0 */ 326444f05562SScott Long phbbmu->doneq_index = index; 326544f05562SScott Long /* check if command done with no error*/ 326644f05562SScott Long srb = (struct CommandControlBlock *) 326744f05562SScott Long (acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/ 3268d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE; 326944f05562SScott Long poll_srb_done = (srb == poll_srb) ? 1:0; 327022f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 327122f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3272123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'" 327344f05562SScott Long "poll command abort successfully \n" 327444f05562SScott Long , acb->pci_unit 327544f05562SScott Long , srb->pccb->ccb_h.target_id 3276123055f0SNathan Whitehorn , (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 327744f05562SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 327844f05562SScott Long arcmsr_srb_complete(srb, 1); 327944f05562SScott Long continue; 328044f05562SScott Long } 328144f05562SScott Long printf("arcmsr%d: polling get an illegal srb command done srb='%p'" 328244f05562SScott Long "srboutstandingcount=%d \n" 328344f05562SScott Long , acb->pci_unit 328444f05562SScott Long , srb, acb->srboutstandingcount); 328544f05562SScott Long continue; 328644f05562SScott Long } 3287d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 3288d74001adSXin LI } /*drain reply FIFO*/ 3289d74001adSXin LI } 3290d74001adSXin LI /* 3291d74001adSXin LI ********************************************************************** 3292d74001adSXin LI ** 3293d74001adSXin LI ********************************************************************** 3294d74001adSXin LI */ 3295d74001adSXin LI static void arcmsr_polling_hbc_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 3296d74001adSXin LI { 3297d74001adSXin LI struct CommandControlBlock *srb; 3298d74001adSXin LI u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 3299d74001adSXin LI u_int16_t error; 3300d74001adSXin LI 3301d74001adSXin LI polling_ccb_retry: 3302d74001adSXin LI poll_count++; 3303d74001adSXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 3304d74001adSXin LI while(1) { 3305d74001adSXin LI if(!(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR)) { 3306d74001adSXin LI if(poll_srb_done) { 3307d74001adSXin LI break;/*chip FIFO no ccb for completion already*/ 3308d74001adSXin LI } else { 3309d74001adSXin LI UDELAY(25000); 3310d74001adSXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 3311d74001adSXin LI break; 3312d74001adSXin LI } 3313d74001adSXin LI if (acb->srboutstandingcount == 0) { 3314d74001adSXin LI break; 3315d74001adSXin LI } 3316d74001adSXin LI goto polling_ccb_retry; 3317d74001adSXin LI } 3318d74001adSXin LI } 3319d74001adSXin LI flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low); 3320d74001adSXin LI /* check if command done with no error*/ 332122f2616bSXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/ 3322d74001adSXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE; 3323d74001adSXin LI if (poll_srb != NULL) 3324d74001adSXin LI poll_srb_done = (srb == poll_srb) ? 1:0; 332522f2616bSXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 332622f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3327123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n" 3328123055f0SNathan Whitehorn , acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 3329d74001adSXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 3330d74001adSXin LI arcmsr_srb_complete(srb, 1); 3331d74001adSXin LI continue; 3332d74001adSXin LI } 3333d74001adSXin LI printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n" 3334d74001adSXin LI , acb->pci_unit, srb, acb->srboutstandingcount); 3335d74001adSXin LI continue; 3336d74001adSXin LI } 3337d74001adSXin LI arcmsr_report_srb_state(acb, srb, error); 333844f05562SScott Long } /*drain reply FIFO*/ 333944f05562SScott Long } 334044f05562SScott Long /* 334144f05562SScott Long ********************************************************************** 33427a7bc959SXin LI ** 33437a7bc959SXin LI ********************************************************************** 33447a7bc959SXin LI */ 33457a7bc959SXin LI static void arcmsr_polling_hbd_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 33467a7bc959SXin LI { 33477a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 33487a7bc959SXin LI struct CommandControlBlock *srb; 33497a7bc959SXin LI u_int32_t flag_srb, poll_srb_done=0, poll_count=0; 33507a7bc959SXin LI u_int32_t outbound_write_pointer; 33517a7bc959SXin LI u_int16_t error, doneq_index; 33527a7bc959SXin LI 33537a7bc959SXin LI polling_ccb_retry: 33547a7bc959SXin LI poll_count++; 33557a7bc959SXin LI bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 33567a7bc959SXin LI while(1) { 33577a7bc959SXin LI outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow; 33587a7bc959SXin LI doneq_index = phbdmu->doneq_index; 33597a7bc959SXin LI if ((outbound_write_pointer & 0xFF) == (doneq_index & 0xFF)) { 33607a7bc959SXin LI if(poll_srb_done) { 33617a7bc959SXin LI break;/*chip FIFO no ccb for completion already*/ 33627a7bc959SXin LI } else { 33637a7bc959SXin LI UDELAY(25000); 33647a7bc959SXin LI if ((poll_count > 100) && (poll_srb != NULL)) { 33657a7bc959SXin LI break; 33667a7bc959SXin LI } 33677a7bc959SXin LI if (acb->srboutstandingcount == 0) { 33687a7bc959SXin LI break; 33697a7bc959SXin LI } 33707a7bc959SXin LI goto polling_ccb_retry; 33717a7bc959SXin LI } 33727a7bc959SXin LI } 33737a7bc959SXin LI doneq_index = arcmsr_get_doneq_index(phbdmu); 33747a7bc959SXin LI flag_srb = phbdmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow; 33757a7bc959SXin LI /* check if command done with no error*/ 33767a7bc959SXin LI srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/ 33777a7bc959SXin LI error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE; 33787a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_read_pointer, doneq_index); 33797a7bc959SXin LI if (poll_srb != NULL) 33807a7bc959SXin LI poll_srb_done = (srb == poll_srb) ? 1:0; 33817a7bc959SXin LI if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) { 33827a7bc959SXin LI if(srb->srb_state == ARCMSR_SRB_ABORTED) { 3383123055f0SNathan Whitehorn printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n" 3384123055f0SNathan Whitehorn , acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb); 33857a7bc959SXin LI srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 33867a7bc959SXin LI arcmsr_srb_complete(srb, 1); 33877a7bc959SXin LI continue; 33887a7bc959SXin LI } 33897a7bc959SXin LI printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n" 33907a7bc959SXin LI , acb->pci_unit, srb, acb->srboutstandingcount); 33917a7bc959SXin LI continue; 33927a7bc959SXin LI } 33937a7bc959SXin LI arcmsr_report_srb_state(acb, srb, error); 33947a7bc959SXin LI } /*drain reply FIFO*/ 33957a7bc959SXin LI } 33967a7bc959SXin LI /* 33977a7bc959SXin LI ********************************************************************** 339844f05562SScott Long ********************************************************************** 339944f05562SScott Long */ 340044f05562SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb) 340144f05562SScott Long { 340244f05562SScott Long switch (acb->adapter_type) { 340344f05562SScott Long case ACB_ADAPTER_TYPE_A: { 340444f05562SScott Long arcmsr_polling_hba_srbdone(acb, poll_srb); 340544f05562SScott Long } 340644f05562SScott Long break; 340744f05562SScott Long case ACB_ADAPTER_TYPE_B: { 340844f05562SScott Long arcmsr_polling_hbb_srbdone(acb, poll_srb); 340944f05562SScott Long } 341044f05562SScott Long break; 3411d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3412d74001adSXin LI arcmsr_polling_hbc_srbdone(acb, poll_srb); 3413d74001adSXin LI } 3414d74001adSXin LI break; 34157a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 34167a7bc959SXin LI arcmsr_polling_hbd_srbdone(acb, poll_srb); 34177a7bc959SXin LI } 34187a7bc959SXin LI break; 341944f05562SScott Long } 342044f05562SScott Long } 342144f05562SScott Long /* 342244f05562SScott Long ********************************************************************** 342344f05562SScott Long ********************************************************************** 342444f05562SScott Long */ 342544f05562SScott Long static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) 3426ad6d6297SScott Long { 3427ad6d6297SScott Long char *acb_firm_model = acb->firm_model; 3428ad6d6297SScott Long char *acb_firm_version = acb->firm_version; 3429d74001adSXin LI char *acb_device_map = acb->device_map; 3430d74001adSXin LI size_t iop_firm_model = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3431d74001adSXin LI size_t iop_firm_version = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3432d74001adSXin LI size_t iop_device_map = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 3433ad6d6297SScott Long int i; 3434ad6d6297SScott Long 343544f05562SScott Long CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 343644f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 3437d74001adSXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 3438ad6d6297SScott Long } 3439ad6d6297SScott Long i = 0; 3440ad6d6297SScott Long while(i < 8) { 344144f05562SScott Long *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 3442ad6d6297SScott Long /* 8 bytes firm_model, 15, 60-67*/ 3443ad6d6297SScott Long acb_firm_model++; 3444ad6d6297SScott Long i++; 3445ad6d6297SScott Long } 3446ad6d6297SScott Long i=0; 3447ad6d6297SScott Long while(i < 16) { 344844f05562SScott Long *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 3449ad6d6297SScott Long /* 16 bytes firm_version, 17, 68-83*/ 3450ad6d6297SScott Long acb_firm_version++; 3451ad6d6297SScott Long i++; 3452ad6d6297SScott Long } 3453d74001adSXin LI i=0; 3454d74001adSXin LI while(i < 16) { 3455d74001adSXin LI *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 3456d74001adSXin LI acb_device_map++; 3457d74001adSXin LI i++; 3458d74001adSXin LI } 34591e7d660aSXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 3460d74001adSXin LI acb->firm_request_len = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3461d74001adSXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3462d74001adSXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3463d74001adSXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3464d74001adSXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3465abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD) 3466abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1; 3467abfdbca9SXin LI else 3468abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 3469ad6d6297SScott Long } 3470ad6d6297SScott Long /* 3471ad6d6297SScott Long ********************************************************************** 347244f05562SScott Long ********************************************************************** 347344f05562SScott Long */ 347444f05562SScott Long static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) 347544f05562SScott Long { 3476b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 347744f05562SScott Long char *acb_firm_model = acb->firm_model; 347844f05562SScott Long char *acb_firm_version = acb->firm_version; 3479d74001adSXin LI char *acb_device_map = acb->device_map; 3480d74001adSXin LI size_t iop_firm_model = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3481d74001adSXin LI size_t iop_firm_version = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3482d74001adSXin LI size_t iop_device_map = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 348344f05562SScott Long int i; 348444f05562SScott Long 3485b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG); 348644f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 3487d74001adSXin LI printf( "arcmsr%d: wait" "'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 348844f05562SScott Long } 348944f05562SScott Long i = 0; 349044f05562SScott Long while(i < 8) { 349144f05562SScott Long *acb_firm_model = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_model+i); 349244f05562SScott Long /* 8 bytes firm_model, 15, 60-67*/ 349344f05562SScott Long acb_firm_model++; 349444f05562SScott Long i++; 349544f05562SScott Long } 349644f05562SScott Long i = 0; 349744f05562SScott Long while(i < 16) { 349844f05562SScott Long *acb_firm_version = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_version+i); 349944f05562SScott Long /* 16 bytes firm_version, 17, 68-83*/ 350044f05562SScott Long acb_firm_version++; 350144f05562SScott Long i++; 350244f05562SScott Long } 3503d74001adSXin LI i = 0; 3504d74001adSXin LI while(i < 16) { 3505d74001adSXin LI *acb_device_map = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_device_map+i); 3506d74001adSXin LI acb_device_map++; 3507d74001adSXin LI i++; 3508d74001adSXin LI } 35091e7d660aSXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 3510d74001adSXin LI acb->firm_request_len = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3511d74001adSXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3512d74001adSXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3513d74001adSXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3514d74001adSXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3515abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_HBB_POSTQUEUE) 3516abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_HBB_POSTQUEUE - 1; 3517abfdbca9SXin LI else 3518abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 3519d74001adSXin LI } 3520d74001adSXin LI /* 3521d74001adSXin LI ********************************************************************** 3522d74001adSXin LI ********************************************************************** 3523d74001adSXin LI */ 3524d74001adSXin LI static void arcmsr_get_hbc_config(struct AdapterControlBlock *acb) 3525d74001adSXin LI { 3526d74001adSXin LI char *acb_firm_model = acb->firm_model; 3527d74001adSXin LI char *acb_firm_version = acb->firm_version; 3528d74001adSXin LI char *acb_device_map = acb->device_map; 3529d74001adSXin LI size_t iop_firm_model = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 3530d74001adSXin LI size_t iop_firm_version = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 3531d74001adSXin LI size_t iop_device_map = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 3532d74001adSXin LI int i; 3533d74001adSXin LI 3534d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 3535d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 3536d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 3537d74001adSXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 3538d74001adSXin LI } 3539d74001adSXin LI i = 0; 3540d74001adSXin LI while(i < 8) { 3541d74001adSXin LI *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 3542d74001adSXin LI /* 8 bytes firm_model, 15, 60-67*/ 3543d74001adSXin LI acb_firm_model++; 3544d74001adSXin LI i++; 3545d74001adSXin LI } 3546d74001adSXin LI i = 0; 3547d74001adSXin LI while(i < 16) { 3548d74001adSXin LI *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 3549d74001adSXin LI /* 16 bytes firm_version, 17, 68-83*/ 3550d74001adSXin LI acb_firm_version++; 3551d74001adSXin LI i++; 3552d74001adSXin LI } 3553d74001adSXin LI i = 0; 3554d74001adSXin LI while(i < 16) { 3555d74001adSXin LI *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 3556d74001adSXin LI acb_device_map++; 3557d74001adSXin LI i++; 3558d74001adSXin LI } 35591e7d660aSXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 3560d74001adSXin LI acb->firm_request_len = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3561d74001adSXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3562d74001adSXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3563d74001adSXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 3564d74001adSXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3565abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD) 3566abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1; 3567abfdbca9SXin LI else 3568abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 356944f05562SScott Long } 357044f05562SScott Long /* 357144f05562SScott Long ********************************************************************** 357244f05562SScott Long ********************************************************************** 357344f05562SScott Long */ 35747a7bc959SXin LI static void arcmsr_get_hbd_config(struct AdapterControlBlock *acb) 35757a7bc959SXin LI { 35767a7bc959SXin LI char *acb_firm_model = acb->firm_model; 35777a7bc959SXin LI char *acb_firm_version = acb->firm_version; 35787a7bc959SXin LI char *acb_device_map = acb->device_map; 35797a7bc959SXin LI size_t iop_firm_model = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]); /*firm_model,15,60-67*/ 35807a7bc959SXin LI size_t iop_firm_version = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/ 35817a7bc959SXin LI size_t iop_device_map = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]); 35827a7bc959SXin LI int i; 35837a7bc959SXin LI 35847a7bc959SXin LI if(CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) 35857a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR); 35867a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG); 35877a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 35887a7bc959SXin LI printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit); 35897a7bc959SXin LI } 35907a7bc959SXin LI i = 0; 35917a7bc959SXin LI while(i < 8) { 35927a7bc959SXin LI *acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i); 35937a7bc959SXin LI /* 8 bytes firm_model, 15, 60-67*/ 35947a7bc959SXin LI acb_firm_model++; 35957a7bc959SXin LI i++; 35967a7bc959SXin LI } 35977a7bc959SXin LI i = 0; 35987a7bc959SXin LI while(i < 16) { 35997a7bc959SXin LI *acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i); 36007a7bc959SXin LI /* 16 bytes firm_version, 17, 68-83*/ 36017a7bc959SXin LI acb_firm_version++; 36027a7bc959SXin LI i++; 36037a7bc959SXin LI } 36047a7bc959SXin LI i = 0; 36057a7bc959SXin LI while(i < 16) { 36067a7bc959SXin LI *acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i); 36077a7bc959SXin LI acb_device_map++; 36087a7bc959SXin LI i++; 36097a7bc959SXin LI } 36101e7d660aSXin LI printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version); 3611b23a1998SXin LI acb->firm_request_len = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[1]); /*firm_request_len, 1, 04-07*/ 3612b23a1998SXin LI acb->firm_numbers_queue = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/ 3613b23a1998SXin LI acb->firm_sdram_size = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[3]); /*firm_sdram_size, 3, 12-15*/ 3614b23a1998SXin LI acb->firm_ide_channels = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[4]); /*firm_ide_channels, 4, 16-19*/ 36157a7bc959SXin LI acb->firm_cfg_version = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]); /*firm_cfg_version, 25, */ 3616abfdbca9SXin LI if(acb->firm_numbers_queue > ARCMSR_MAX_HBD_POSTQUEUE) 3617abfdbca9SXin LI acb->maxOutstanding = ARCMSR_MAX_HBD_POSTQUEUE - 1; 3618abfdbca9SXin LI else 3619abfdbca9SXin LI acb->maxOutstanding = acb->firm_numbers_queue - 1; 36207a7bc959SXin LI } 36217a7bc959SXin LI /* 36227a7bc959SXin LI ********************************************************************** 36237a7bc959SXin LI ********************************************************************** 36247a7bc959SXin LI */ 362544f05562SScott Long static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) 362644f05562SScott Long { 362744f05562SScott Long switch (acb->adapter_type) { 362844f05562SScott Long case ACB_ADAPTER_TYPE_A: { 362944f05562SScott Long arcmsr_get_hba_config(acb); 363044f05562SScott Long } 363144f05562SScott Long break; 363244f05562SScott Long case ACB_ADAPTER_TYPE_B: { 363344f05562SScott Long arcmsr_get_hbb_config(acb); 363444f05562SScott Long } 363544f05562SScott Long break; 3636d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3637d74001adSXin LI arcmsr_get_hbc_config(acb); 3638d74001adSXin LI } 3639d74001adSXin LI break; 36407a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 36417a7bc959SXin LI arcmsr_get_hbd_config(acb); 36427a7bc959SXin LI } 36437a7bc959SXin LI break; 364444f05562SScott Long } 364544f05562SScott Long } 364644f05562SScott Long /* 364744f05562SScott Long ********************************************************************** 364844f05562SScott Long ********************************************************************** 364944f05562SScott Long */ 365044f05562SScott Long static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb) 365144f05562SScott Long { 365244f05562SScott Long int timeout=0; 365344f05562SScott Long 365444f05562SScott Long switch (acb->adapter_type) { 365544f05562SScott Long case ACB_ADAPTER_TYPE_A: { 3656d74001adSXin LI while ((CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) 365744f05562SScott Long { 365844f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 365944f05562SScott Long { 3660d74001adSXin LI printf( "arcmsr%d:timed out waiting for firmware \n", acb->pci_unit); 366144f05562SScott Long return; 366244f05562SScott Long } 366344f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 366444f05562SScott Long } 366544f05562SScott Long } 366644f05562SScott Long break; 366744f05562SScott Long case ACB_ADAPTER_TYPE_B: { 3668b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 3669b23a1998SXin LI while ((READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & ARCMSR_MESSAGE_FIRMWARE_OK) == 0) 367044f05562SScott Long { 367144f05562SScott Long if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 367244f05562SScott Long { 3673d74001adSXin LI printf( "arcmsr%d: timed out waiting for firmware \n", acb->pci_unit); 367444f05562SScott Long return; 367544f05562SScott Long } 367644f05562SScott Long UDELAY(15000); /* wait 15 milli-seconds */ 367744f05562SScott Long } 3678b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT); 3679d74001adSXin LI } 3680d74001adSXin LI break; 3681d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3682d74001adSXin LI while ((CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0) 3683d74001adSXin LI { 3684d74001adSXin LI if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 3685d74001adSXin LI { 3686d74001adSXin LI printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit); 3687d74001adSXin LI return; 3688d74001adSXin LI } 3689d74001adSXin LI UDELAY(15000); /* wait 15 milli-seconds */ 3690d74001adSXin LI } 369144f05562SScott Long } 369244f05562SScott Long break; 36937a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 36947a7bc959SXin LI while ((CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBDMU_MESSAGE_FIRMWARE_OK) == 0) 36957a7bc959SXin LI { 36967a7bc959SXin LI if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */ 36977a7bc959SXin LI { 36987a7bc959SXin LI printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit); 36997a7bc959SXin LI return; 37007a7bc959SXin LI } 37017a7bc959SXin LI UDELAY(15000); /* wait 15 milli-seconds */ 37027a7bc959SXin LI } 37037a7bc959SXin LI } 37047a7bc959SXin LI break; 370544f05562SScott Long } 370644f05562SScott Long } 370744f05562SScott Long /* 370844f05562SScott Long ********************************************************************** 370944f05562SScott Long ********************************************************************** 371044f05562SScott Long */ 371144f05562SScott Long static void arcmsr_clear_doorbell_queue_buffer( struct AdapterControlBlock *acb) 371244f05562SScott Long { 3713d74001adSXin LI u_int32_t outbound_doorbell; 3714d74001adSXin LI 371544f05562SScott Long switch (acb->adapter_type) { 371644f05562SScott Long case ACB_ADAPTER_TYPE_A: { 371744f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 3718d74001adSXin LI outbound_doorbell = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell); 3719d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, outbound_doorbell); /*clear doorbell interrupt */ 3720d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 3721d74001adSXin LI 372244f05562SScott Long } 372344f05562SScott Long break; 372444f05562SScott Long case ACB_ADAPTER_TYPE_B: { 3725b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 3726b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt and message state*/ 3727b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK); 372844f05562SScott Long /* let IOP know data has been read */ 372944f05562SScott Long } 373044f05562SScott Long break; 3731d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3732d74001adSXin LI /* empty doorbell Qbuffer if door bell ringed */ 3733d74001adSXin LI outbound_doorbell = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell); 3734d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell); /*clear doorbell interrupt */ 3735d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK); 37367a7bc959SXin LI CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell_clear); /* Dummy read to force pci flush */ 37377a7bc959SXin LI CHIP_REG_READ32(HBC_MessageUnit, 0, inbound_doorbell); /* Dummy read to force pci flush */ 37387a7bc959SXin LI } 37397a7bc959SXin LI break; 37407a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 37417a7bc959SXin LI /* empty doorbell Qbuffer if door bell ringed */ 37427a7bc959SXin LI outbound_doorbell = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell); 37437a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, outbound_doorbell); /*clear doorbell interrupt */ 37447a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ); 3745d74001adSXin LI 3746d74001adSXin LI } 3747d74001adSXin LI break; 374844f05562SScott Long } 374944f05562SScott Long } 375044f05562SScott Long /* 375144f05562SScott Long ************************************************************************ 375244f05562SScott Long ************************************************************************ 375344f05562SScott Long */ 375444f05562SScott Long static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb) 375544f05562SScott Long { 375644f05562SScott Long unsigned long srb_phyaddr; 375744f05562SScott Long u_int32_t srb_phyaddr_hi32; 37587a7bc959SXin LI u_int32_t srb_phyaddr_lo32; 375944f05562SScott Long 376044f05562SScott Long /* 376144f05562SScott Long ******************************************************************** 376244f05562SScott Long ** here we need to tell iop 331 our freesrb.HighPart 376344f05562SScott Long ** if freesrb.HighPart is not zero 376444f05562SScott Long ******************************************************************** 376544f05562SScott Long */ 3766d74001adSXin LI srb_phyaddr = (unsigned long) acb->srb_phyaddr.phyaddr; 3767d74001adSXin LI srb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high; 37687a7bc959SXin LI srb_phyaddr_lo32 = acb->srb_phyaddr.B.phyadd_low; 376944f05562SScott Long switch (acb->adapter_type) { 377044f05562SScott Long case ACB_ADAPTER_TYPE_A: { 377144f05562SScott Long if(srb_phyaddr_hi32 != 0) { 3772d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 3773d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 3774d74001adSXin LI CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 377544f05562SScott Long if(!arcmsr_hba_wait_msgint_ready(acb)) { 3776d74001adSXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 377744f05562SScott Long return FALSE; 377844f05562SScott Long } 377944f05562SScott Long } 378044f05562SScott Long } 378144f05562SScott Long break; 378244f05562SScott Long /* 378344f05562SScott Long *********************************************************************** 378444f05562SScott Long ** if adapter type B, set window of "post command Q" 378544f05562SScott Long *********************************************************************** 378644f05562SScott Long */ 378744f05562SScott Long case ACB_ADAPTER_TYPE_B: { 378844f05562SScott Long u_int32_t post_queue_phyaddr; 378944f05562SScott Long struct HBB_MessageUnit *phbbmu; 379044f05562SScott Long 379144f05562SScott Long phbbmu = (struct HBB_MessageUnit *)acb->pmu; 379244f05562SScott Long phbbmu->postq_index = 0; 379344f05562SScott Long phbbmu->doneq_index = 0; 3794b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_SET_POST_WINDOW); 379544f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 3796d74001adSXin LI printf( "arcmsr%d: 'set window of post command Q' timeout\n", acb->pci_unit); 379744f05562SScott Long return FALSE; 379844f05562SScott Long } 379922f2616bSXin LI post_queue_phyaddr = srb_phyaddr + ARCMSR_SRBS_POOL_SIZE 380044f05562SScott Long + offsetof(struct HBB_MessageUnit, post_qbuffer); 3801d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */ 3802d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1], srb_phyaddr_hi32); /* normal should be zero */ 3803d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ size (256+8)*4 */ 3804d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3], post_queue_phyaddr+1056); /* doneQ size (256+8)*4 */ 3805d74001adSXin LI CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4], 1056); /* srb maxQ size must be --> [(256+8)*4] */ 3806b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_SET_CONFIG); 380744f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 380844f05562SScott Long printf( "arcmsr%d: 'set command Q window' timeout \n", acb->pci_unit); 380944f05562SScott Long return FALSE; 381044f05562SScott Long } 3811b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_START_DRIVER_MODE); 381244f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 381344f05562SScott Long printf( "arcmsr%d: 'start diver mode' timeout \n", acb->pci_unit); 381444f05562SScott Long return FALSE; 381544f05562SScott Long } 381644f05562SScott Long } 381744f05562SScott Long break; 3818d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 3819d74001adSXin LI if(srb_phyaddr_hi32 != 0) { 3820d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); 3821d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 3822d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 3823d74001adSXin LI CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE); 3824d74001adSXin LI if(!arcmsr_hbc_wait_msgint_ready(acb)) { 3825d74001adSXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 3826d74001adSXin LI return FALSE; 3827d74001adSXin LI } 3828d74001adSXin LI } 3829d74001adSXin LI } 3830d74001adSXin LI break; 38317a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 38327a7bc959SXin LI u_int32_t post_queue_phyaddr, done_queue_phyaddr; 38337a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu; 38347a7bc959SXin LI 38357a7bc959SXin LI phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 38367a7bc959SXin LI phbdmu->postq_index = 0; 38377a7bc959SXin LI phbdmu->doneq_index = 0x40FF; 38387a7bc959SXin LI post_queue_phyaddr = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE 38397a7bc959SXin LI + offsetof(struct HBD_MessageUnit0, post_qbuffer); 38407a7bc959SXin LI done_queue_phyaddr = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE 38417a7bc959SXin LI + offsetof(struct HBD_MessageUnit0, done_qbuffer); 38427a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */ 38437a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32); 38447a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ base */ 38457a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[3], done_queue_phyaddr); /* doneQ base */ 38467a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[4], 0x100); 38477a7bc959SXin LI CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG); 38487a7bc959SXin LI if(!arcmsr_hbd_wait_msgint_ready(acb)) { 38497a7bc959SXin LI printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit); 38507a7bc959SXin LI return FALSE; 38517a7bc959SXin LI } 38527a7bc959SXin LI } 38537a7bc959SXin LI break; 385444f05562SScott Long } 3855dac36688SXin LI return (TRUE); 385644f05562SScott Long } 385744f05562SScott Long /* 385844f05562SScott Long ************************************************************************ 385944f05562SScott Long ************************************************************************ 386044f05562SScott Long */ 386144f05562SScott Long static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb) 386244f05562SScott Long { 386344f05562SScott Long switch (acb->adapter_type) 386444f05562SScott Long { 386544f05562SScott Long case ACB_ADAPTER_TYPE_A: 3866d74001adSXin LI case ACB_ADAPTER_TYPE_C: 38677a7bc959SXin LI case ACB_ADAPTER_TYPE_D: 3868d74001adSXin LI break; 386944f05562SScott Long case ACB_ADAPTER_TYPE_B: { 3870b23a1998SXin LI struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu; 3871b23a1998SXin LI WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_ACTIVE_EOI_MODE); 387244f05562SScott Long if(!arcmsr_hbb_wait_msgint_ready(acb)) { 3873d74001adSXin LI printf( "arcmsr%d: 'iop enable eoi mode' timeout \n", acb->pci_unit); 387444f05562SScott Long return; 387544f05562SScott Long } 387644f05562SScott Long } 387744f05562SScott Long break; 387844f05562SScott Long } 387944f05562SScott Long } 388044f05562SScott Long /* 388144f05562SScott Long ********************************************************************** 3882ad6d6297SScott Long ********************************************************************** 3883ad6d6297SScott Long */ 3884ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb) 3885ad6d6297SScott Long { 388644f05562SScott Long u_int32_t intmask_org; 3887ad6d6297SScott Long 388844f05562SScott Long /* disable all outbound interrupt */ 388944f05562SScott Long intmask_org = arcmsr_disable_allintr(acb); 389044f05562SScott Long arcmsr_wait_firmware_ready(acb); 389144f05562SScott Long arcmsr_iop_confirm(acb); 3892ad6d6297SScott Long arcmsr_get_firmware_spec(acb); 389344f05562SScott Long /*start background rebuild*/ 3894ad6d6297SScott Long arcmsr_start_adapter_bgrb(acb); 389544f05562SScott Long /* empty doorbell Qbuffer if door bell ringed */ 389644f05562SScott Long arcmsr_clear_doorbell_queue_buffer(acb); 389744f05562SScott Long arcmsr_enable_eoi_mode(acb); 389844f05562SScott Long /* enable outbound Post Queue, outbound doorbell Interrupt */ 389944f05562SScott Long arcmsr_enable_allintr(acb, intmask_org); 3900ad6d6297SScott Long acb->acb_flags |= ACB_F_IOP_INITED; 3901ad6d6297SScott Long } 3902ad6d6297SScott Long /* 3903ad6d6297SScott Long ********************************************************************** 3904f1c579b1SScott Long ********************************************************************** 3905f1c579b1SScott Long */ 3906231c8b71SXin LI static void arcmsr_map_free_srb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 3907f1c579b1SScott Long { 3908ad6d6297SScott Long struct AdapterControlBlock *acb = arg; 3909ad6d6297SScott Long struct CommandControlBlock *srb_tmp; 391044f05562SScott Long u_int32_t i; 3911ad6d6297SScott Long unsigned long srb_phyaddr = (unsigned long)segs->ds_addr; 3912f1c579b1SScott Long 3913d74001adSXin LI acb->srb_phyaddr.phyaddr = srb_phyaddr; 39147a7bc959SXin LI srb_tmp = (struct CommandControlBlock *)acb->uncacheptr; 3915ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 391644f05562SScott Long if(bus_dmamap_create(acb->dm_segs_dmat, 391744f05562SScott Long /*flags*/0, &srb_tmp->dm_segs_dmamap) != 0) { 3918ad6d6297SScott Long acb->acb_flags |= ACB_F_MAPFREESRB_FAILD; 391944f05562SScott Long printf("arcmsr%d:" 392044f05562SScott Long " srb dmamap bus_dmamap_create error\n", acb->pci_unit); 3921ad6d6297SScott Long return; 3922ad6d6297SScott Long } 39237a7bc959SXin LI if((acb->adapter_type == ACB_ADAPTER_TYPE_C) || (acb->adapter_type == ACB_ADAPTER_TYPE_D)) 39247a7bc959SXin LI { 39257a7bc959SXin LI srb_tmp->cdb_phyaddr_low = srb_phyaddr; 39267a7bc959SXin LI srb_tmp->cdb_phyaddr_high = (u_int32_t)((srb_phyaddr >> 16) >> 16); 39277a7bc959SXin LI } 39287a7bc959SXin LI else 39297a7bc959SXin LI srb_tmp->cdb_phyaddr_low = srb_phyaddr >> 5; 3930ad6d6297SScott Long srb_tmp->acb = acb; 3931ad6d6297SScott Long acb->srbworkingQ[i] = acb->psrb_pool[i] = srb_tmp; 393222f2616bSXin LI srb_phyaddr = srb_phyaddr + SRB_SIZE; 393322f2616bSXin LI srb_tmp = (struct CommandControlBlock *)((unsigned long)srb_tmp + SRB_SIZE); 3934ad6d6297SScott Long } 3935ad6d6297SScott Long acb->vir2phy_offset = (unsigned long)srb_tmp - (unsigned long)srb_phyaddr; 3936f1c579b1SScott Long } 3937f1c579b1SScott Long /* 3938f1c579b1SScott Long ************************************************************************ 3939f1c579b1SScott Long ************************************************************************ 3940f1c579b1SScott Long */ 3941ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb) 3942f1c579b1SScott Long { 3943f1c579b1SScott Long /* remove the control device */ 3944ad6d6297SScott Long if(acb->ioctl_dev != NULL) { 3945ad6d6297SScott Long destroy_dev(acb->ioctl_dev); 3946f1c579b1SScott Long } 3947ad6d6297SScott Long bus_dmamap_unload(acb->srb_dmat, acb->srb_dmamap); 3948ad6d6297SScott Long bus_dmamap_destroy(acb->srb_dmat, acb->srb_dmamap); 3949ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 3950ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 3951ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 3952f1c579b1SScott Long } 3953f1c579b1SScott Long /* 3954f1c579b1SScott Long ************************************************************************ 3955f1c579b1SScott Long ************************************************************************ 3956f1c579b1SScott Long */ 39577a7bc959SXin LI static void arcmsr_mutex_init(struct AdapterControlBlock *acb) 39587a7bc959SXin LI { 39597a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->isr_lock, "arcmsr isr lock"); 39607a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->srb_lock, "arcmsr srb lock"); 39617a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->postDone_lock, "arcmsr postQ lock"); 39627a7bc959SXin LI ARCMSR_LOCK_INIT(&acb->qbuffer_lock, "arcmsr RW buffer lock"); 39637a7bc959SXin LI } 39647a7bc959SXin LI /* 39657a7bc959SXin LI ************************************************************************ 39667a7bc959SXin LI ************************************************************************ 39677a7bc959SXin LI */ 39687a7bc959SXin LI static void arcmsr_mutex_destroy(struct AdapterControlBlock *acb) 39697a7bc959SXin LI { 39707a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock); 39717a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->postDone_lock); 39727a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->srb_lock); 39737a7bc959SXin LI ARCMSR_LOCK_DESTROY(&acb->isr_lock); 39747a7bc959SXin LI } 39757a7bc959SXin LI /* 39767a7bc959SXin LI ************************************************************************ 39777a7bc959SXin LI ************************************************************************ 39787a7bc959SXin LI */ 3979ad6d6297SScott Long static u_int32_t arcmsr_initialize(device_t dev) 3980f1c579b1SScott Long { 3981ad6d6297SScott Long struct AdapterControlBlock *acb = device_get_softc(dev); 3982ad6d6297SScott Long u_int16_t pci_command; 398344f05562SScott Long int i, j,max_coherent_size; 3984dac36688SXin LI u_int32_t vendor_dev_id; 3985f1c579b1SScott Long 3986dac36688SXin LI vendor_dev_id = pci_get_devid(dev); 3987dac36688SXin LI acb->vendor_device_id = vendor_dev_id; 3988224a78aeSXin LI acb->sub_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2); 3989dac36688SXin LI switch (vendor_dev_id) { 3990dac36688SXin LI case PCIDevVenIDARC1880: 3991dac36688SXin LI case PCIDevVenIDARC1882: 3992dac36688SXin LI case PCIDevVenIDARC1213: 3993dac36688SXin LI case PCIDevVenIDARC1223: { 3994d74001adSXin LI acb->adapter_type = ACB_ADAPTER_TYPE_C; 3995224a78aeSXin LI if (acb->sub_device_id == ARECA_SUB_DEV_ID_1883) 3996224a78aeSXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_12G; 3997224a78aeSXin LI else 3998dac36688SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_6G; 3999d74001adSXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE; 4000d74001adSXin LI } 4001d74001adSXin LI break; 40027a7bc959SXin LI case PCIDevVenIDARC1214: { 40037a7bc959SXin LI acb->adapter_type = ACB_ADAPTER_TYPE_D; 40047a7bc959SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_6G; 40057a7bc959SXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBD_MessageUnit0)); 40067a7bc959SXin LI } 40077a7bc959SXin LI break; 4008231c8b71SXin LI case PCIDevVenIDARC1200: 400944f05562SScott Long case PCIDevVenIDARC1201: { 401044f05562SScott Long acb->adapter_type = ACB_ADAPTER_TYPE_B; 4011dac36688SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_3G; 4012d74001adSXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBB_MessageUnit)); 401344f05562SScott Long } 401444f05562SScott Long break; 4015b23a1998SXin LI case PCIDevVenIDARC1203: { 4016b23a1998SXin LI acb->adapter_type = ACB_ADAPTER_TYPE_B; 4017b23a1998SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_6G; 4018b23a1998SXin LI max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBB_MessageUnit)); 4019b23a1998SXin LI } 4020b23a1998SXin LI break; 402144f05562SScott Long case PCIDevVenIDARC1110: 402244f05562SScott Long case PCIDevVenIDARC1120: 402344f05562SScott Long case PCIDevVenIDARC1130: 402444f05562SScott Long case PCIDevVenIDARC1160: 402544f05562SScott Long case PCIDevVenIDARC1170: 402644f05562SScott Long case PCIDevVenIDARC1210: 402744f05562SScott Long case PCIDevVenIDARC1220: 402844f05562SScott Long case PCIDevVenIDARC1230: 4029231c8b71SXin LI case PCIDevVenIDARC1231: 403044f05562SScott Long case PCIDevVenIDARC1260: 4031231c8b71SXin LI case PCIDevVenIDARC1261: 403244f05562SScott Long case PCIDevVenIDARC1270: 403344f05562SScott Long case PCIDevVenIDARC1280: 4034d74001adSXin LI case PCIDevVenIDARC1212: 4035d74001adSXin LI case PCIDevVenIDARC1222: 403644f05562SScott Long case PCIDevVenIDARC1380: 403744f05562SScott Long case PCIDevVenIDARC1381: 403844f05562SScott Long case PCIDevVenIDARC1680: 403944f05562SScott Long case PCIDevVenIDARC1681: { 404044f05562SScott Long acb->adapter_type = ACB_ADAPTER_TYPE_A; 4041dac36688SXin LI acb->adapter_bus_speed = ACB_BUS_SPEED_3G; 404244f05562SScott Long max_coherent_size = ARCMSR_SRBS_POOL_SIZE; 404344f05562SScott Long } 404444f05562SScott Long break; 404544f05562SScott Long default: { 404644f05562SScott Long printf("arcmsr%d:" 404744f05562SScott Long " unknown RAID adapter type \n", device_get_unit(dev)); 404844f05562SScott Long return ENOMEM; 404944f05562SScott Long } 405044f05562SScott Long } 40517a7bc959SXin LI #if __FreeBSD_version >= 700000 4052b6f97155SScott Long if(bus_dma_tag_create( /*PCI parent*/ bus_get_dma_tag(dev), 40537a7bc959SXin LI #else 40547a7bc959SXin LI if(bus_dma_tag_create( /*PCI parent*/ NULL, 40557a7bc959SXin LI #endif 4056f1c579b1SScott Long /*alignemnt*/ 1, 4057f1c579b1SScott Long /*boundary*/ 0, 4058701d9f1fSScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 4059f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 4060f1c579b1SScott Long /*filter*/ NULL, 4061f1c579b1SScott Long /*filterarg*/ NULL, 4062f1c579b1SScott Long /*maxsize*/ BUS_SPACE_MAXSIZE_32BIT, 4063f1c579b1SScott Long /*nsegments*/ BUS_SPACE_UNRESTRICTED, 4064f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 4065f1c579b1SScott Long /*flags*/ 0, 406622f2616bSXin LI #if __FreeBSD_version >= 501102 4067f1c579b1SScott Long /*lockfunc*/ NULL, 4068f1c579b1SScott Long /*lockarg*/ NULL, 4069f1c579b1SScott Long #endif 4070231c8b71SXin LI &acb->parent_dmat) != 0) 4071f1c579b1SScott Long { 407244f05562SScott Long printf("arcmsr%d: parent_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 4073f1c579b1SScott Long return ENOMEM; 4074f1c579b1SScott Long } 4075231c8b71SXin LI 4076f1c579b1SScott Long /* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */ 4077ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 4078f1c579b1SScott Long /*alignment*/ 1, 4079f1c579b1SScott Long /*boundary*/ 0, 408022f2616bSXin LI #ifdef PAE 408122f2616bSXin LI /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 408222f2616bSXin LI #else 4083f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR, 408422f2616bSXin LI #endif 4085f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 4086f1c579b1SScott Long /*filter*/ NULL, 4087f1c579b1SScott Long /*filterarg*/ NULL, 4088231c8b71SXin LI /*maxsize*/ ARCMSR_MAX_SG_ENTRIES * PAGE_SIZE * ARCMSR_MAX_FREESRB_NUM, 4089f1c579b1SScott Long /*nsegments*/ ARCMSR_MAX_SG_ENTRIES, 4090f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 4091ad6d6297SScott Long /*flags*/ 0, 409222f2616bSXin LI #if __FreeBSD_version >= 501102 4093f1c579b1SScott Long /*lockfunc*/ busdma_lock_mutex, 40947a7bc959SXin LI /*lockarg*/ &acb->isr_lock, 4095f1c579b1SScott Long #endif 4096231c8b71SXin LI &acb->dm_segs_dmat) != 0) 4097f1c579b1SScott Long { 4098ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 409944f05562SScott Long printf("arcmsr%d: dm_segs_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 4100f1c579b1SScott Long return ENOMEM; 4101f1c579b1SScott Long } 4102231c8b71SXin LI 4103ad6d6297SScott Long /* DMA tag for our srb structures.... Allocate the freesrb memory */ 4104ad6d6297SScott Long if(bus_dma_tag_create( /*parent_dmat*/ acb->parent_dmat, 410544f05562SScott Long /*alignment*/ 0x20, 4106f1c579b1SScott Long /*boundary*/ 0, 4107f1c579b1SScott Long /*lowaddr*/ BUS_SPACE_MAXADDR_32BIT, 4108f1c579b1SScott Long /*highaddr*/ BUS_SPACE_MAXADDR, 4109f1c579b1SScott Long /*filter*/ NULL, 4110f1c579b1SScott Long /*filterarg*/ NULL, 411144f05562SScott Long /*maxsize*/ max_coherent_size, 4112f1c579b1SScott Long /*nsegments*/ 1, 4113f1c579b1SScott Long /*maxsegsz*/ BUS_SPACE_MAXSIZE_32BIT, 4114701d9f1fSScott Long /*flags*/ 0, 411522f2616bSXin LI #if __FreeBSD_version >= 501102 4116f1c579b1SScott Long /*lockfunc*/ NULL, 4117f1c579b1SScott Long /*lockarg*/ NULL, 4118f1c579b1SScott Long #endif 4119231c8b71SXin LI &acb->srb_dmat) != 0) 4120f1c579b1SScott Long { 4121ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 4122ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 412344f05562SScott Long printf("arcmsr%d: srb_dmat bus_dma_tag_create failure!\n", device_get_unit(dev)); 4124f1c579b1SScott Long return ENXIO; 4125f1c579b1SScott Long } 4126f1c579b1SScott Long /* Allocation for our srbs */ 4127d74001adSXin LI if(bus_dmamem_alloc(acb->srb_dmat, (void **)&acb->uncacheptr, BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &acb->srb_dmamap) != 0) { 4128ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 4129ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 4130ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 413144f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamem_alloc failure!\n", device_get_unit(dev)); 4132f1c579b1SScott Long return ENXIO; 4133f1c579b1SScott Long } 4134f1c579b1SScott Long /* And permanently map them */ 4135231c8b71SXin LI if(bus_dmamap_load(acb->srb_dmat, acb->srb_dmamap, acb->uncacheptr, max_coherent_size, arcmsr_map_free_srb, acb, /*flags*/0)) { 4136ad6d6297SScott Long bus_dma_tag_destroy(acb->srb_dmat); 4137ad6d6297SScott Long bus_dma_tag_destroy(acb->dm_segs_dmat); 4138ad6d6297SScott Long bus_dma_tag_destroy(acb->parent_dmat); 413944f05562SScott Long printf("arcmsr%d: srb_dmat bus_dmamap_load failure!\n", device_get_unit(dev)); 4140f1c579b1SScott Long return ENXIO; 4141f1c579b1SScott Long } 4142f1c579b1SScott Long pci_command = pci_read_config(dev, PCIR_COMMAND, 2); 4143f1c579b1SScott Long pci_command |= PCIM_CMD_BUSMASTEREN; 4144f1c579b1SScott Long pci_command |= PCIM_CMD_PERRESPEN; 4145f1c579b1SScott Long pci_command |= PCIM_CMD_MWRICEN; 4146c68534f1SScott Long /* Enable Busmaster */ 4147f1c579b1SScott Long pci_write_config(dev, PCIR_COMMAND, pci_command, 2); 414844f05562SScott Long switch(acb->adapter_type) { 414944f05562SScott Long case ACB_ADAPTER_TYPE_A: { 415044f05562SScott Long u_int32_t rid0 = PCIR_BAR(0); 415144f05562SScott Long vm_offset_t mem_base0; 415244f05562SScott Long 4153eff83876SJustin Hibbits acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid0, RF_ACTIVE); 415444f05562SScott Long if(acb->sys_res_arcmsr[0] == NULL) { 4155ad6d6297SScott Long arcmsr_free_resource(acb); 4156d74001adSXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 4157f1c579b1SScott Long return ENOMEM; 4158f1c579b1SScott Long } 415944f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 4160ad6d6297SScott Long arcmsr_free_resource(acb); 4161d74001adSXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 4162f1c579b1SScott Long return ENXIO; 4163f1c579b1SScott Long } 416444f05562SScott Long mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 416544f05562SScott Long if(mem_base0 == 0) { 4166ad6d6297SScott Long arcmsr_free_resource(acb); 4167d74001adSXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 4168f1c579b1SScott Long return ENXIO; 4169f1c579b1SScott Long } 417044f05562SScott Long acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 417144f05562SScott Long acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 417244f05562SScott Long acb->pmu = (struct MessageUnit_UNION *)mem_base0; 417344f05562SScott Long } 417444f05562SScott Long break; 417544f05562SScott Long case ACB_ADAPTER_TYPE_B: { 417644f05562SScott Long struct HBB_MessageUnit *phbbmu; 417744f05562SScott Long struct CommandControlBlock *freesrb; 417844f05562SScott Long u_int32_t rid[]={ PCIR_BAR(0), PCIR_BAR(2) }; 417944f05562SScott Long vm_offset_t mem_base[]={0,0}; 4180b23a1998SXin LI u_long size; 4181b23a1998SXin LI if (vendor_dev_id == PCIDevVenIDARC1203) 4182b23a1998SXin LI size = sizeof(struct HBB_DOORBELL_1203); 4183b23a1998SXin LI else 4184b23a1998SXin LI size = sizeof(struct HBB_DOORBELL); 418544f05562SScott Long for(i=0; i < 2; i++) { 418644f05562SScott Long if(i == 0) { 4187eff83876SJustin Hibbits acb->sys_res_arcmsr[i] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid[i], 4188eff83876SJustin Hibbits RF_ACTIVE); 418944f05562SScott Long } else { 4190eff83876SJustin Hibbits acb->sys_res_arcmsr[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid[i], 4191eff83876SJustin Hibbits RF_ACTIVE); 419244f05562SScott Long } 419344f05562SScott Long if(acb->sys_res_arcmsr[i] == NULL) { 419444f05562SScott Long arcmsr_free_resource(acb); 4195d74001adSXin LI printf("arcmsr%d: bus_alloc_resource %d failure!\n", device_get_unit(dev), i); 419644f05562SScott Long return ENOMEM; 419744f05562SScott Long } 419844f05562SScott Long if(rman_get_start(acb->sys_res_arcmsr[i]) <= 0) { 419944f05562SScott Long arcmsr_free_resource(acb); 4200d74001adSXin LI printf("arcmsr%d: rman_get_start %d failure!\n", device_get_unit(dev), i); 420144f05562SScott Long return ENXIO; 420244f05562SScott Long } 420344f05562SScott Long mem_base[i] = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[i]); 420444f05562SScott Long if(mem_base[i] == 0) { 420544f05562SScott Long arcmsr_free_resource(acb); 4206d74001adSXin LI printf("arcmsr%d: rman_get_virtual %d failure!\n", device_get_unit(dev), i); 420744f05562SScott Long return ENXIO; 420844f05562SScott Long } 420944f05562SScott Long acb->btag[i] = rman_get_bustag(acb->sys_res_arcmsr[i]); 421044f05562SScott Long acb->bhandle[i] = rman_get_bushandle(acb->sys_res_arcmsr[i]); 421144f05562SScott Long } 421244f05562SScott Long freesrb = (struct CommandControlBlock *)acb->uncacheptr; 421322f2616bSXin LI acb->pmu = (struct MessageUnit_UNION *)((unsigned long)freesrb+ARCMSR_SRBS_POOL_SIZE); 421444f05562SScott Long phbbmu = (struct HBB_MessageUnit *)acb->pmu; 421544f05562SScott Long phbbmu->hbb_doorbell = (struct HBB_DOORBELL *)mem_base[0]; 421644f05562SScott Long phbbmu->hbb_rwbuffer = (struct HBB_RWBUFFER *)mem_base[1]; 4217b23a1998SXin LI if (vendor_dev_id == PCIDevVenIDARC1203) { 4218b23a1998SXin LI phbbmu->drv2iop_doorbell = offsetof(struct HBB_DOORBELL_1203, drv2iop_doorbell); 4219b23a1998SXin LI phbbmu->drv2iop_doorbell_mask = offsetof(struct HBB_DOORBELL_1203, drv2iop_doorbell_mask); 4220b23a1998SXin LI phbbmu->iop2drv_doorbell = offsetof(struct HBB_DOORBELL_1203, iop2drv_doorbell); 4221b23a1998SXin LI phbbmu->iop2drv_doorbell_mask = offsetof(struct HBB_DOORBELL_1203, iop2drv_doorbell_mask); 4222b23a1998SXin LI } else { 4223b23a1998SXin LI phbbmu->drv2iop_doorbell = offsetof(struct HBB_DOORBELL, drv2iop_doorbell); 4224b23a1998SXin LI phbbmu->drv2iop_doorbell_mask = offsetof(struct HBB_DOORBELL, drv2iop_doorbell_mask); 4225b23a1998SXin LI phbbmu->iop2drv_doorbell = offsetof(struct HBB_DOORBELL, iop2drv_doorbell); 4226b23a1998SXin LI phbbmu->iop2drv_doorbell_mask = offsetof(struct HBB_DOORBELL, iop2drv_doorbell_mask); 4227b23a1998SXin LI } 422844f05562SScott Long } 422944f05562SScott Long break; 4230d74001adSXin LI case ACB_ADAPTER_TYPE_C: { 4231d74001adSXin LI u_int32_t rid0 = PCIR_BAR(1); 4232d74001adSXin LI vm_offset_t mem_base0; 4233d74001adSXin LI 4234eff83876SJustin Hibbits acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid0, RF_ACTIVE); 4235d74001adSXin LI if(acb->sys_res_arcmsr[0] == NULL) { 4236d74001adSXin LI arcmsr_free_resource(acb); 4237d74001adSXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 4238d74001adSXin LI return ENOMEM; 4239d74001adSXin LI } 4240d74001adSXin LI if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 4241d74001adSXin LI arcmsr_free_resource(acb); 4242d74001adSXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 4243d74001adSXin LI return ENXIO; 4244d74001adSXin LI } 4245d74001adSXin LI mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 4246d74001adSXin LI if(mem_base0 == 0) { 4247d74001adSXin LI arcmsr_free_resource(acb); 4248d74001adSXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 4249d74001adSXin LI return ENXIO; 4250d74001adSXin LI } 4251d74001adSXin LI acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 4252d74001adSXin LI acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 4253d74001adSXin LI acb->pmu = (struct MessageUnit_UNION *)mem_base0; 4254d74001adSXin LI } 4255d74001adSXin LI break; 42567a7bc959SXin LI case ACB_ADAPTER_TYPE_D: { 42577a7bc959SXin LI struct HBD_MessageUnit0 *phbdmu; 42587a7bc959SXin LI u_int32_t rid0 = PCIR_BAR(0); 42597a7bc959SXin LI vm_offset_t mem_base0; 42607a7bc959SXin LI 4261eff83876SJustin Hibbits acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid0, RF_ACTIVE); 42627a7bc959SXin LI if(acb->sys_res_arcmsr[0] == NULL) { 42637a7bc959SXin LI arcmsr_free_resource(acb); 42647a7bc959SXin LI printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev)); 42657a7bc959SXin LI return ENOMEM; 42667a7bc959SXin LI } 42677a7bc959SXin LI if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) { 42687a7bc959SXin LI arcmsr_free_resource(acb); 42697a7bc959SXin LI printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev)); 42707a7bc959SXin LI return ENXIO; 42717a7bc959SXin LI } 42727a7bc959SXin LI mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]); 42737a7bc959SXin LI if(mem_base0 == 0) { 42747a7bc959SXin LI arcmsr_free_resource(acb); 42757a7bc959SXin LI printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev)); 42767a7bc959SXin LI return ENXIO; 42777a7bc959SXin LI } 42787a7bc959SXin LI acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]); 42797a7bc959SXin LI acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]); 42807a7bc959SXin LI acb->pmu = (struct MessageUnit_UNION *)((unsigned long)acb->uncacheptr+ARCMSR_SRBS_POOL_SIZE); 42817a7bc959SXin LI phbdmu = (struct HBD_MessageUnit0 *)acb->pmu; 42827a7bc959SXin LI phbdmu->phbdmu = (struct HBD_MessageUnit *)mem_base0; 42837a7bc959SXin LI } 42847a7bc959SXin LI break; 428544f05562SScott Long } 4286ad6d6297SScott Long if(acb->acb_flags & ACB_F_MAPFREESRB_FAILD) { 4287ad6d6297SScott Long arcmsr_free_resource(acb); 428844f05562SScott Long printf("arcmsr%d: map free srb failure!\n", device_get_unit(dev)); 4289f1c579b1SScott Long return ENXIO; 4290f1c579b1SScott Long } 4291d74001adSXin LI acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_RQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ); 4292ad6d6297SScott Long acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; 4293ad6d6297SScott Long /* 4294ad6d6297SScott Long ******************************************************************** 4295ad6d6297SScott Long ** init raid volume state 4296ad6d6297SScott Long ******************************************************************** 4297ad6d6297SScott Long */ 4298ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_TARGETID; i++) { 4299ad6d6297SScott Long for(j=0; j < ARCMSR_MAX_TARGETLUN; j++) { 430044f05562SScott Long acb->devstate[i][j] = ARECA_RAID_GONE; 4301ad6d6297SScott Long } 4302ad6d6297SScott Long } 4303ad6d6297SScott Long arcmsr_iop_init(acb); 4304f1c579b1SScott Long return(0); 4305f1c579b1SScott Long } 4306f1c579b1SScott Long /* 4307f1c579b1SScott Long ************************************************************************ 4308f1c579b1SScott Long ************************************************************************ 4309f1c579b1SScott Long */ 4310f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev) 4311f1c579b1SScott Long { 4312ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 4313ad6d6297SScott Long u_int32_t unit=device_get_unit(dev); 4314f1c579b1SScott Long struct ccb_setasync csa; 4315f1c579b1SScott Long struct cam_devq *devq; /* Device Queue to use for this SIM */ 4316f1c579b1SScott Long struct resource *irqres; 4317f1c579b1SScott Long int rid; 4318f1c579b1SScott Long 4319ad6d6297SScott Long if(acb == NULL) { 4320ad6d6297SScott Long printf("arcmsr%d: cannot allocate softc\n", unit); 4321ad6d6297SScott Long return (ENOMEM); 4322ad6d6297SScott Long } 43237a7bc959SXin LI arcmsr_mutex_init(acb); 43241e7d660aSXin LI acb->pci_dev = dev; 43251e7d660aSXin LI acb->pci_unit = unit; 4326ad6d6297SScott Long if(arcmsr_initialize(dev)) { 4327ad6d6297SScott Long printf("arcmsr%d: initialize failure!\n", unit); 43287a7bc959SXin LI arcmsr_mutex_destroy(acb); 4329f1c579b1SScott Long return ENXIO; 4330f1c579b1SScott Long } 4331f1c579b1SScott Long /* After setting up the adapter, map our interrupt */ 4332f1c579b1SScott Long rid = 0; 433343cd6160SJustin Hibbits irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); 4334ad6d6297SScott Long if(irqres == NULL || 433544f05562SScott Long #if __FreeBSD_version >= 700025 4336d74001adSXin LI bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, NULL, arcmsr_intr_handler, acb, &acb->ih)) { 433744f05562SScott Long #else 4338d74001adSXin LI bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, arcmsr_intr_handler, acb, &acb->ih)) { 433944f05562SScott Long #endif 4340ad6d6297SScott Long arcmsr_free_resource(acb); 43417a7bc959SXin LI arcmsr_mutex_destroy(acb); 4342f1c579b1SScott Long printf("arcmsr%d: unable to register interrupt handler!\n", unit); 4343f1c579b1SScott Long return ENXIO; 4344f1c579b1SScott Long } 4345ad6d6297SScott Long acb->irqres = irqres; 4346f1c579b1SScott Long /* 4347f1c579b1SScott Long * Now let the CAM generic SCSI layer find the SCSI devices on 4348f1c579b1SScott Long * the bus * start queue to reset to the idle loop. * 4349f1c579b1SScott Long * Create device queue of SIM(s) * (MAX_START_JOB - 1) : 4350f1c579b1SScott Long * max_sim_transactions 4351f1c579b1SScott Long */ 4352224a78aeSXin LI devq = cam_simq_alloc(acb->maxOutstanding); 4353ad6d6297SScott Long if(devq == NULL) { 4354ad6d6297SScott Long arcmsr_free_resource(acb); 4355ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 43567a7bc959SXin LI arcmsr_mutex_destroy(acb); 4357ad6d6297SScott Long printf("arcmsr%d: cam_simq_alloc failure!\n", unit); 4358f1c579b1SScott Long return ENXIO; 4359f1c579b1SScott Long } 436044f05562SScott Long #if __FreeBSD_version >= 700025 43617a7bc959SXin LI acb->psim = cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, &acb->isr_lock, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq); 436244f05562SScott Long #else 4363d74001adSXin LI acb->psim = cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq); 436444f05562SScott Long #endif 4365ad6d6297SScott Long if(acb->psim == NULL) { 4366ad6d6297SScott Long arcmsr_free_resource(acb); 4367ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 4368f1c579b1SScott Long cam_simq_free(devq); 43697a7bc959SXin LI arcmsr_mutex_destroy(acb); 4370ad6d6297SScott Long printf("arcmsr%d: cam_sim_alloc failure!\n", unit); 4371f1c579b1SScott Long return ENXIO; 4372f1c579b1SScott Long } 43737a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 4374f40b4cabSScott Long #if __FreeBSD_version >= 700044 4375b50569b7SScott Long if(xpt_bus_register(acb->psim, dev, 0) != CAM_SUCCESS) { 437644f05562SScott Long #else 437744f05562SScott Long if(xpt_bus_register(acb->psim, 0) != CAM_SUCCESS) { 437844f05562SScott Long #endif 4379ad6d6297SScott Long arcmsr_free_resource(acb); 4380ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 4381ad6d6297SScott Long cam_sim_free(acb->psim, /*free_devq*/TRUE); 43827a7bc959SXin LI arcmsr_mutex_destroy(acb); 4383ad6d6297SScott Long printf("arcmsr%d: xpt_bus_register failure!\n", unit); 4384f1c579b1SScott Long return ENXIO; 4385f1c579b1SScott Long } 4386d74001adSXin LI if(xpt_create_path(&acb->ppath, /* periph */ NULL, cam_sim_path(acb->psim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 4387ad6d6297SScott Long arcmsr_free_resource(acb); 4388ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 4389ad6d6297SScott Long xpt_bus_deregister(cam_sim_path(acb->psim)); 4390ad6d6297SScott Long cam_sim_free(acb->psim, /* free_simq */ TRUE); 43917a7bc959SXin LI arcmsr_mutex_destroy(acb); 4392ad6d6297SScott Long printf("arcmsr%d: xpt_create_path failure!\n", unit); 4393f1c579b1SScott Long return ENXIO; 4394f1c579b1SScott Long } 4395f1c579b1SScott Long /* 4396f1c579b1SScott Long **************************************************** 4397f1c579b1SScott Long */ 4398ad6d6297SScott Long xpt_setup_ccb(&csa.ccb_h, acb->ppath, /*priority*/5); 4399f1c579b1SScott Long csa.ccb_h.func_code = XPT_SASYNC_CB; 4400f1c579b1SScott Long csa.event_enable = AC_FOUND_DEVICE|AC_LOST_DEVICE; 4401f1c579b1SScott Long csa.callback = arcmsr_async; 4402ad6d6297SScott Long csa.callback_arg = acb->psim; 4403f1c579b1SScott Long xpt_action((union ccb *)&csa); 44047a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 4405f1c579b1SScott Long /* Create the control device. */ 4406d74001adSXin LI acb->ioctl_dev = make_dev(&arcmsr_cdevsw, unit, UID_ROOT, GID_WHEEL /* GID_OPERATOR */, S_IRUSR | S_IWUSR, "arcmsr%d", unit); 4407d74001adSXin LI 4408f1c579b1SScott Long #if __FreeBSD_version < 503000 4409ad6d6297SScott Long acb->ioctl_dev->si_drv1 = acb; 4410f1c579b1SScott Long #endif 4411f1c579b1SScott Long #if __FreeBSD_version > 500005 4412ad6d6297SScott Long (void)make_dev_alias(acb->ioctl_dev, "arc%d", unit); 4413f1c579b1SScott Long #endif 441422f2616bSXin LI arcmsr_callout_init(&acb->devmap_callout); 4415d74001adSXin LI callout_reset(&acb->devmap_callout, 60 * hz, arcmsr_polling_devmap, acb); 4416dac36688SXin LI return (0); 4417f1c579b1SScott Long } 441822f2616bSXin LI 4419f1c579b1SScott Long /* 4420f1c579b1SScott Long ************************************************************************ 4421f1c579b1SScott Long ************************************************************************ 4422f1c579b1SScott Long */ 4423f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev) 4424f1c579b1SScott Long { 4425ad6d6297SScott Long u_int32_t id; 4426224a78aeSXin LI u_int16_t sub_device_id; 4427ad6d6297SScott Long static char buf[256]; 44281e7d660aSXin LI char x_type[]={"unknown"}; 4429ad6d6297SScott Long char *type; 4430ad6d6297SScott Long int raid6 = 1; 4431ad6d6297SScott Long 4432ad6d6297SScott Long if (pci_get_vendor(dev) != PCI_VENDOR_ID_ARECA) { 4433ad6d6297SScott Long return (ENXIO); 4434ad6d6297SScott Long } 4435224a78aeSXin LI sub_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2); 4436ad6d6297SScott Long switch(id = pci_get_devid(dev)) { 4437f1c579b1SScott Long case PCIDevVenIDARC1110: 4438231c8b71SXin LI case PCIDevVenIDARC1200: 443944f05562SScott Long case PCIDevVenIDARC1201: 4440231c8b71SXin LI case PCIDevVenIDARC1210: 4441ad6d6297SScott Long raid6 = 0; 4442ad6d6297SScott Long /*FALLTHRU*/ 4443ad6d6297SScott Long case PCIDevVenIDARC1120: 4444ad6d6297SScott Long case PCIDevVenIDARC1130: 4445ad6d6297SScott Long case PCIDevVenIDARC1160: 4446ad6d6297SScott Long case PCIDevVenIDARC1170: 4447f1c579b1SScott Long case PCIDevVenIDARC1220: 4448f1c579b1SScott Long case PCIDevVenIDARC1230: 4449231c8b71SXin LI case PCIDevVenIDARC1231: 4450f1c579b1SScott Long case PCIDevVenIDARC1260: 4451231c8b71SXin LI case PCIDevVenIDARC1261: 4452ad6d6297SScott Long case PCIDevVenIDARC1270: 4453ad6d6297SScott Long case PCIDevVenIDARC1280: 44547a7bc959SXin LI type = "SATA 3G"; 4455ad6d6297SScott Long break; 4456d74001adSXin LI case PCIDevVenIDARC1212: 4457d74001adSXin LI case PCIDevVenIDARC1222: 4458ad6d6297SScott Long case PCIDevVenIDARC1380: 4459ad6d6297SScott Long case PCIDevVenIDARC1381: 4460ad6d6297SScott Long case PCIDevVenIDARC1680: 4461ad6d6297SScott Long case PCIDevVenIDARC1681: 4462d74001adSXin LI type = "SAS 3G"; 4463d74001adSXin LI break; 4464d74001adSXin LI case PCIDevVenIDARC1880: 4465dac36688SXin LI case PCIDevVenIDARC1882: 4466dac36688SXin LI case PCIDevVenIDARC1213: 4467dac36688SXin LI case PCIDevVenIDARC1223: 4468224a78aeSXin LI if (sub_device_id == ARECA_SUB_DEV_ID_1883) 4469224a78aeSXin LI type = "SAS 12G"; 4470224a78aeSXin LI else 4471d74001adSXin LI type = "SAS 6G"; 4472ad6d6297SScott Long break; 44737a7bc959SXin LI case PCIDevVenIDARC1214: 4474b23a1998SXin LI case PCIDevVenIDARC1203: 44757a7bc959SXin LI type = "SATA 6G"; 44767a7bc959SXin LI break; 4477ad6d6297SScott Long default: 4478231c8b71SXin LI type = x_type; 44791e7d660aSXin LI raid6 = 0; 4480ad6d6297SScott Long break; 4481f1c579b1SScott Long } 4482231c8b71SXin LI if(type == x_type) 4483231c8b71SXin LI return(ENXIO); 44841e7d660aSXin LI sprintf(buf, "Areca %s Host Adapter RAID Controller %s\n%s\n", 44851e7d660aSXin LI type, raid6 ? "(RAID6 capable)" : "", ARCMSR_DRIVER_VERSION); 4486ad6d6297SScott Long device_set_desc_copy(dev, buf); 448703389298SXin LI return (BUS_PROBE_DEFAULT); 4488f1c579b1SScott Long } 4489f1c579b1SScott Long /* 4490f1c579b1SScott Long ************************************************************************ 4491f1c579b1SScott Long ************************************************************************ 4492f1c579b1SScott Long */ 4493f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev) 4494f1c579b1SScott Long { 449544f05562SScott Long u_int32_t i; 4496ad6d6297SScott Long u_int32_t intmask_org; 4497ad6d6297SScott Long struct CommandControlBlock *srb; 4498ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 4499f1c579b1SScott Long 4500f1c579b1SScott Long /* stop adapter background rebuild */ 45017a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 450244f05562SScott Long /* disable all outbound interrupt */ 450344f05562SScott Long intmask_org = arcmsr_disable_allintr(acb); 4504ad6d6297SScott Long arcmsr_stop_adapter_bgrb(acb); 4505ad6d6297SScott Long arcmsr_flush_adapter_cache(acb); 4506f1c579b1SScott Long /* abort all outstanding command */ 4507ad6d6297SScott Long acb->acb_flags |= ACB_F_SCSISTOPADAPTER; 4508ad6d6297SScott Long acb->acb_flags &= ~ACB_F_IOP_INITED; 4509ad6d6297SScott Long if(acb->srboutstandingcount != 0) { 451044f05562SScott Long /*clear and abort all outbound posted Q*/ 451144f05562SScott Long arcmsr_done4abort_postqueue(acb); 451244f05562SScott Long /* talk to iop 331 outstanding command aborted*/ 4513ad6d6297SScott Long arcmsr_abort_allcmd(acb); 4514ad6d6297SScott Long for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) { 4515ad6d6297SScott Long srb = acb->psrb_pool[i]; 451622f2616bSXin LI if(srb->srb_state == ARCMSR_SRB_START) { 451722f2616bSXin LI srb->srb_state = ARCMSR_SRB_ABORTED; 4518ad6d6297SScott Long srb->pccb->ccb_h.status |= CAM_REQ_ABORTED; 4519ad6d6297SScott Long arcmsr_srb_complete(srb, 1); 4520f1c579b1SScott Long } 4521f1c579b1SScott Long } 4522f1c579b1SScott Long } 452322f2616bSXin LI acb->srboutstandingcount = 0; 4524ad6d6297SScott Long acb->workingsrb_doneindex = 0; 4525ad6d6297SScott Long acb->workingsrb_startindex = 0; 452622f2616bSXin LI acb->pktRequestCount = 0; 452722f2616bSXin LI acb->pktReturnCount = 0; 45287a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 4529f2aa0e9fSWarner Losh return (0); 4530f1c579b1SScott Long } 4531f1c579b1SScott Long /* 4532f1c579b1SScott Long ************************************************************************ 4533f1c579b1SScott Long ************************************************************************ 4534f1c579b1SScott Long */ 4535f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev) 4536f1c579b1SScott Long { 4537ad6d6297SScott Long struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev); 453844f05562SScott Long int i; 4539f1c579b1SScott Long 4540d74001adSXin LI callout_stop(&acb->devmap_callout); 45415878cbecSScott Long bus_teardown_intr(dev, acb->irqres, acb->ih); 4542f1c579b1SScott Long arcmsr_shutdown(dev); 4543ad6d6297SScott Long arcmsr_free_resource(acb); 454444f05562SScott Long for(i=0; (acb->sys_res_arcmsr[i]!=NULL) && (i<2); i++) { 454544f05562SScott Long bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(i), acb->sys_res_arcmsr[i]); 454644f05562SScott Long } 4547ad6d6297SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, acb->irqres); 45487a7bc959SXin LI ARCMSR_LOCK_ACQUIRE(&acb->isr_lock); 4549ad6d6297SScott Long xpt_async(AC_LOST_DEVICE, acb->ppath, NULL); 4550ad6d6297SScott Long xpt_free_path(acb->ppath); 4551ad6d6297SScott Long xpt_bus_deregister(cam_sim_path(acb->psim)); 4552ad6d6297SScott Long cam_sim_free(acb->psim, TRUE); 45537a7bc959SXin LI ARCMSR_LOCK_RELEASE(&acb->isr_lock); 45547a7bc959SXin LI arcmsr_mutex_destroy(acb); 4555f1c579b1SScott Long return (0); 4556f1c579b1SScott Long } 4557f1c579b1SScott Long 455822f2616bSXin LI #ifdef ARCMSR_DEBUG1 455922f2616bSXin LI static void arcmsr_dump_data(struct AdapterControlBlock *acb) 456022f2616bSXin LI { 456122f2616bSXin LI if((acb->pktRequestCount - acb->pktReturnCount) == 0) 456222f2616bSXin LI return; 456322f2616bSXin LI printf("Command Request Count =0x%x\n",acb->pktRequestCount); 456422f2616bSXin LI printf("Command Return Count =0x%x\n",acb->pktReturnCount); 456522f2616bSXin LI printf("Command (Req-Rtn) Count =0x%x\n",(acb->pktRequestCount - acb->pktReturnCount)); 456622f2616bSXin LI printf("Queued Command Count =0x%x\n",acb->srboutstandingcount); 456722f2616bSXin LI } 456822f2616bSXin LI #endif 4569f1c579b1SScott Long 4570