1f1c579b1SScott Long /* 2f1c579b1SScott Long ****************************************************************************************** 3f1c579b1SScott Long ** O.S : FreeBSD 4f1c579b1SScott Long ** FILE NAME : arcmsr.c 5f1c579b1SScott Long ** BY : Erich Chen 6f1c579b1SScott Long ** Description: SCSI RAID Device Driver for 7f1c579b1SScott Long ** ARECA (ARC1110/1120/1160/1210/1220/1260) SATA RAID HOST Adapter 8f1c579b1SScott Long ** ARCMSR RAID Host adapter[RAID controller:INTEL 331(PCI-X) 341(PCI-EXPRESS) chip set] 9f1c579b1SScott Long ****************************************************************************************** 10f1c579b1SScott Long ************************************************************************ 11f1c579b1SScott Long ** 12f1c579b1SScott Long ** Copyright (c) 2004-2006 ARECA Co. Ltd. 13f1c579b1SScott Long ** Erich Chen, Taipei Taiwan All rights reserved. 14f1c579b1SScott Long ** 15f1c579b1SScott Long ** Redistribution and use in source and binary forms,with or without 16f1c579b1SScott Long ** modification,are permitted provided that the following conditions 17f1c579b1SScott Long ** are met: 18f1c579b1SScott Long ** 1. Redistributions of source code must retain the above copyright 19f1c579b1SScott Long ** notice,this list of conditions and the following disclaimer. 20f1c579b1SScott Long ** 2. Redistributions in binary form must reproduce the above copyright 21f1c579b1SScott Long ** notice,this list of conditions and the following disclaimer in the 22f1c579b1SScott Long ** documentation and/or other materials provided with the distribution. 23f1c579b1SScott Long ** 3. The name of the author may not be used to endorse or promote products 24f1c579b1SScott Long ** derived from this software without specific prior written permission. 25f1c579b1SScott Long ** 26f1c579b1SScott Long ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 27f1c579b1SScott Long ** IMPLIED WARRANTIES,INCLUDING,BUT NOT LIMITED TO,THE IMPLIED WARRANTIES 28f1c579b1SScott Long ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29f1c579b1SScott Long ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,INDIRECT, 30f1c579b1SScott Long ** INCIDENTAL,SPECIAL,EXEMPLARY,OR CONSEQUENTIAL DAMAGES(INCLUDING,BUT 31f1c579b1SScott Long ** NOT LIMITED TO,PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32f1c579b1SScott Long ** DATA,OR PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY 33f1c579b1SScott Long ** THEORY OF LIABILITY,WHETHER IN CONTRACT,STRICT LIABILITY,OR TORT 34f1c579b1SScott Long **(INCLUDING NEGLIGENCE OR OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF 35f1c579b1SScott Long ** THIS SOFTWARE,EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36f1c579b1SScott Long ************************************************************************** 37f1c579b1SScott Long ** History 38f1c579b1SScott Long ** 39f1c579b1SScott Long ** REV# DATE NAME DESCRIPTION 40f1c579b1SScott Long ** 1.00.00.00 3/31/2004 Erich Chen First release 41f1c579b1SScott Long ** 1.20.00.02 11/29/2004 Erich Chen bug fix with arcmsr_bus_reset when PHY error 42f1c579b1SScott Long ****************************************************************************************** 43f1c579b1SScott Long ** $FreeBSD$ 44f1c579b1SScott Long */ 45f1c579b1SScott Long #define ARCMSR_DEBUG 1 46f1c579b1SScott Long /* 47f1c579b1SScott Long ********************************** 48f1c579b1SScott Long */ 49f1c579b1SScott Long #include <sys/param.h> 50f1c579b1SScott Long #include <sys/systm.h> 51f1c579b1SScott Long #include <sys/malloc.h> 52f1c579b1SScott Long #include <sys/kernel.h> 53f1c579b1SScott Long #include <sys/bus.h> 54f1c579b1SScott Long #include <sys/queue.h> 55f1c579b1SScott Long #include <sys/stat.h> 56f1c579b1SScott Long #include <sys/devicestat.h> 57f1c579b1SScott Long #include <sys/kthread.h> 58f1c579b1SScott Long #include <sys/module.h> 59f1c579b1SScott Long #include <sys/proc.h> 60f1c579b1SScott Long #include <sys/lock.h> 61f1c579b1SScott Long #include <sys/sysctl.h> 62f1c579b1SScott Long #include <sys/poll.h> 63f1c579b1SScott Long #include <sys/ioccom.h> 64f1c579b1SScott Long #include <vm/vm.h> 65f1c579b1SScott Long #include <vm/vm_param.h> 66f1c579b1SScott Long #include <vm/pmap.h> 67f1c579b1SScott Long 68f1c579b1SScott Long #include <isa/rtc.h> 69f1c579b1SScott Long 70f1c579b1SScott Long #include <machine/bus_memio.h> 71f1c579b1SScott Long #include <machine/bus.h> 72f1c579b1SScott Long #include <machine/clock.h> 73f1c579b1SScott Long #include <machine/resource.h> 74f1c579b1SScott Long #include <machine/atomic.h> 75f1c579b1SScott Long #include <sys/conf.h> 76f1c579b1SScott Long #include <sys/rman.h> 77f1c579b1SScott Long 78f1c579b1SScott Long #include <cam/cam.h> 79f1c579b1SScott Long #include <cam/cam_ccb.h> 80f1c579b1SScott Long #include <cam/cam_sim.h> 81f1c579b1SScott Long #include <cam/cam_xpt_sim.h> 82f1c579b1SScott Long #include <cam/cam_debug.h> 83f1c579b1SScott Long #include <cam/scsi/scsi_all.h> 84f1c579b1SScott Long #include <cam/scsi/scsi_message.h> 85f1c579b1SScott Long /* 86f1c579b1SScott Long ************************************************************************** 87f1c579b1SScott Long ** Define the OS version specific locks 88f1c579b1SScott Long ************************************************************************** 89f1c579b1SScott Long */ 90f1c579b1SScott Long #if __FreeBSD_version >= 500005 91f1c579b1SScott Long #include <sys/selinfo.h> 92f1c579b1SScott Long #include <sys/mutex.h> 93f1c579b1SScott Long #include <dev/pci/pcivar.h> 94f1c579b1SScott Long #include <dev/pci/pcireg.h> 95f1c579b1SScott Long #define ARCMSR_LOCK_INIT(l, s) mtx_init(l, s,NULL, MTX_DEF|MTX_RECURSE) 96f1c579b1SScott Long #define ARCMSR_LOCK_ACQUIRE(l) mtx_lock(l) 97f1c579b1SScott Long #define ARCMSR_LOCK_RELEASE(l) mtx_unlock(l) 98f1c579b1SScott Long typedef struct mtx arcmsr_lock_t; 99f1c579b1SScott Long #else 100f1c579b1SScott Long #include <sys/select.h> 101f1c579b1SScott Long #include <pci/pcivar.h> 102f1c579b1SScott Long #include <pci/pcireg.h> 103f1c579b1SScott Long #define ARCMSR_LOCK_INIT(l, s) simple_lock_init(l) 104f1c579b1SScott Long #define ARCMSR_LOCK_ACQUIRE(l) simple_lock(l) 105f1c579b1SScott Long #define ARCMSR_LOCK_RELEASE(l) simple_unlock(l) 106f1c579b1SScott Long typedef struct simplelock arcmsr_lock_t; 107f1c579b1SScott Long #endif 108f1c579b1SScott Long #include <dev/arcmsr/arcmsr.h> 109f1c579b1SScott Long /* 110f1c579b1SScott Long ************************************************************************** 111f1c579b1SScott Long ** __FreeBSD_version 502010 112f1c579b1SScott Long ************************************************************************** 113f1c579b1SScott Long */ 114f1c579b1SScott Long static VOID arcmsr_interrupt(VOID *arg); 115f1c579b1SScott Long static LONG arcmsr_probe(device_t dev); 116f1c579b1SScott Long static LONG arcmsr_attach(device_t dev); 117f1c579b1SScott Long static LONG arcmsr_detach(device_t dev); 118f1c579b1SScott Long static VOID arcmsr_shutdown(device_t dev); 119f1c579b1SScott Long ULONG arcmsr_make_timespec(ULONG year,ULONG mon,ULONG day,ULONG hour,ULONG min,ULONG sec); 120f1c579b1SScott Long ULONG arcmsr_getcmos_time(VOID); 121f1c579b1SScott Long LONG arcmsr_queue_dpc(PACB pACB,DPCFUN dpcfun,VOID *arg); 122f1c579b1SScott Long LONG arcmsr_iop_ioctlcmd(PACB pACB,ULONG ioctl_cmd,caddr_t arg); 123f1c579b1SScott Long BOOLEAN arcmsr_seek_cmd2abort(union ccb * pabortccb); 124f1c579b1SScott Long BOOLEAN arcmsr_wait_msgint_ready(PACB pACB); 125f1c579b1SScott Long PSRB arcmsr_get_freesrb(PACB pACB); 126f1c579b1SScott Long VOID arcmsr_free_resource(PACB pACB); 127f1c579b1SScott Long VOID arcmsr_bus_reset(PACB pACB); 128f1c579b1SScott Long VOID arcmsr_stop_adapter_bgrb(PACB pACB); 129f1c579b1SScott Long VOID arcmsr_start_adapter_bgrb(PACB pACB); 130f1c579b1SScott Long VOID arcmsr_iop_init(PACB pACB); 131f1c579b1SScott Long VOID arcmsr_do_dpcQ(PACB pACB); 132f1c579b1SScott Long VOID arcmsr_flush_adapter_cache(PACB pACB); 133f1c579b1SScott Long VOID arcmsr_do_thread_works(VOID *arg); 134f1c579b1SScott Long VOID arcmsr_queue_wait2go_srb(PACB pACB,PSRB pSRB); 135f1c579b1SScott Long VOID arcmsr_post_wait2go_srb(PACB pACB); 136f1c579b1SScott Long VOID arcmsr_post_Qbuffer(PACB pACB); 137f1c579b1SScott Long VOID arcmsr_abort_allcmd(PACB pACB); 138f1c579b1SScott Long VOID arcmsr_srb_complete(PSRB pSRB); 139f1c579b1SScott Long VOID arcmsr_iop_reset(PACB pACB); 140f1c579b1SScott Long VOID arcmsr_report_SenseInfoBuffer(PSRB pSRB); 141f1c579b1SScott Long VOID arcmsr_build_srb(PSRB pSRB, bus_dma_segment_t *dm_segs, LONG nseg); 142f1c579b1SScott Long /* 143f1c579b1SScott Long ***************************************************************************************** 144f1c579b1SScott Long ** Character device switch table 145f1c579b1SScott Long **struct cdevsw { 146f1c579b1SScott Long ** d_open_t *d_open; 147f1c579b1SScott Long ** d_close_t *d_close; 148f1c579b1SScott Long ** d_read_t *d_read; 149f1c579b1SScott Long ** d_write_t *d_write; 150f1c579b1SScott Long ** d_ioctl_t *d_ioctl; 151f1c579b1SScott Long ** d_poll_t *d_poll; 152f1c579b1SScott Long ** d_mmap_t *d_mmap; 153f1c579b1SScott Long ** d_strategy_t *d_strategy; 154f1c579b1SScott Long ** const char *d_name; "" base device name, e.g. 'vn' 155f1c579b1SScott Long ** int d_maj; 156f1c579b1SScott Long ** d_dump_t *d_dump; 157f1c579b1SScott Long ** d_psize_t *d_psize; 158f1c579b1SScott Long ** u_int d_flags; 159f1c579b1SScott Long ** int d_bmaj; 160f1c579b1SScott Long ** d_kqfilter_t *d_kqfilter; "" additions below are not binary compatible with 4.2 and below 161f1c579b1SScott Long **}; 162f1c579b1SScott Long ****************************************************************************************** 163f1c579b1SScott Long */ 164f1c579b1SScott Long /* 165f1c579b1SScott Long ************************************************************************** 166f1c579b1SScott Long ** Insert a delay in micro-seconds and milli-seconds. 167f1c579b1SScott Long ** static void MDELAY(LONG ms) { while (ms--) UDELAY(1000); } 168f1c579b1SScott Long ************************************************************************** 169f1c579b1SScott Long */ 170f1c579b1SScott Long static VOID UDELAY(LONG us) { DELAY(us); } 171f1c579b1SScott Long /* 172f1c579b1SScott Long ************************************************************************** 173f1c579b1SScott Long ** 174f1c579b1SScott Long ************************************************************************** 175f1c579b1SScott Long */ 176f1c579b1SScott Long static bus_dmamap_callback_t arcmsr_map_freesrb; 177f1c579b1SScott Long static bus_dmamap_callback_t arcmsr_executesrb; 178f1c579b1SScott Long /* 179f1c579b1SScott Long ************************************************************************** 180f1c579b1SScott Long ** 181f1c579b1SScott Long ************************************************************************** 182f1c579b1SScott Long */ 183f1c579b1SScott Long static d_open_t arcmsr_open; 184f1c579b1SScott Long static d_close_t arcmsr_close; 185f1c579b1SScott Long static d_ioctl_t arcmsr_ioctl; 186f1c579b1SScott Long 187f1c579b1SScott Long static device_method_t arcmsr_methods[]={ 188f1c579b1SScott Long DEVMETHOD(device_probe, arcmsr_probe), 189f1c579b1SScott Long DEVMETHOD(device_attach, arcmsr_attach), 190f1c579b1SScott Long DEVMETHOD(device_detach, arcmsr_detach), 191f1c579b1SScott Long DEVMETHOD(device_shutdown, arcmsr_shutdown), 192f1c579b1SScott Long { 0,0 } 193f1c579b1SScott Long }; 194f1c579b1SScott Long 195f1c579b1SScott Long static driver_t arcmsr_driver={ 196f1c579b1SScott Long "arcmsr",arcmsr_methods,sizeof(struct _ACB) 197f1c579b1SScott Long }; 198f1c579b1SScott Long 199f1c579b1SScott Long static devclass_t arcmsr_devclass; 200f1c579b1SScott Long DRIVER_MODULE(arcmsr,pci,arcmsr_driver,arcmsr_devclass,0,0); 201f1c579b1SScott Long 202f1c579b1SScott Long #if __FreeBSD_version >= 502010 203f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw={ 204f1c579b1SScott Long .d_version = D_VERSION, 205f1c579b1SScott Long .d_flags = D_NEEDGIANT, 206f1c579b1SScott Long .d_open = arcmsr_open, /* open */ 207f1c579b1SScott Long .d_close = arcmsr_close, /* close */ 208f1c579b1SScott Long .d_ioctl = arcmsr_ioctl, /* ioctl */ 209f1c579b1SScott Long .d_name = "arcmsr", /* name */ 210f1c579b1SScott Long }; 211f1c579b1SScott Long #else 212f1c579b1SScott Long #define ARCMSR_CDEV_MAJOR 180 213f1c579b1SScott Long 214f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw = { 215f1c579b1SScott Long arcmsr_open, /* open */ 216f1c579b1SScott Long arcmsr_close, /* close */ 217f1c579b1SScott Long noread, /* read */ 218f1c579b1SScott Long nowrite, /* write */ 219f1c579b1SScott Long arcmsr_ioctl, /* ioctl */ 220f1c579b1SScott Long nopoll, /* poll */ 221f1c579b1SScott Long nommap, /* mmap */ 222f1c579b1SScott Long nostrategy, /* strategy */ 223f1c579b1SScott Long "arcmsr", /* name */ 224f1c579b1SScott Long ARCMSR_CDEV_MAJOR, /* major */ 225f1c579b1SScott Long nodump, /* dump */ 226f1c579b1SScott Long nopsize, /* psize */ 227f1c579b1SScott Long 0 /* flags */ 228f1c579b1SScott Long }; 229f1c579b1SScott Long #endif 230f1c579b1SScott Long 231f1c579b1SScott Long #if __FreeBSD_version < 500005 232f1c579b1SScott Long static int arcmsr_open(dev_t dev, int flags, int fmt, struct proc *proc) 233f1c579b1SScott Long #else 234f1c579b1SScott Long #if __FreeBSD_version < 503000 235f1c579b1SScott Long static int arcmsr_open(dev_t dev, int flags, int fmt, struct thread *proc) 236f1c579b1SScott Long #else 237f1c579b1SScott Long static int arcmsr_open(struct cdev *dev, int flags, int fmt, d_thread_t *proc) 238f1c579b1SScott Long #endif 239f1c579b1SScott Long #endif 240f1c579b1SScott Long { 241f1c579b1SScott Long #if __FreeBSD_version < 503000 242f1c579b1SScott Long PACB pACB=dev->si_drv1; 243f1c579b1SScott Long #else 244f1c579b1SScott Long int unit = minor(dev); 245f1c579b1SScott Long PACB pACB = devclass_get_softc(arcmsr_devclass, unit); 246f1c579b1SScott Long #endif 247f1c579b1SScott Long 248f1c579b1SScott Long if(pACB==NULL) 249f1c579b1SScott Long { 250f1c579b1SScott Long return ENXIO; 251f1c579b1SScott Long } 252f1c579b1SScott Long /* Check to make sure the device isn't already open */ 253f1c579b1SScott Long if (pACB->acb_flags & ACB_F_IOCTL_OPEN) 254f1c579b1SScott Long { 255f1c579b1SScott Long return EBUSY; 256f1c579b1SScott Long } 257f1c579b1SScott Long pACB->acb_flags |= ACB_F_IOCTL_OPEN; 258f1c579b1SScott Long return 0; 259f1c579b1SScott Long } 260f1c579b1SScott Long /* 261f1c579b1SScott Long ************************************************************************** 262f1c579b1SScott Long ************************************************************************** 263f1c579b1SScott Long */ 264f1c579b1SScott Long #if __FreeBSD_version < 500005 265f1c579b1SScott Long static int arcmsr_close(dev_t dev, int flags, int fmt, struct proc *proc) 266f1c579b1SScott Long #else 267f1c579b1SScott Long #if __FreeBSD_version < 503000 268f1c579b1SScott Long static int arcmsr_close(dev_t dev, int flags, int fmt, struct thread *proc) 269f1c579b1SScott Long #else 270f1c579b1SScott Long static int arcmsr_close(struct cdev *dev, int flags, int fmt, d_thread_t *proc) 271f1c579b1SScott Long #endif 272f1c579b1SScott Long #endif 273f1c579b1SScott Long { 274f1c579b1SScott Long #if __FreeBSD_version < 503000 275f1c579b1SScott Long PACB pACB=dev->si_drv1; 276f1c579b1SScott Long #else 277f1c579b1SScott Long int unit = minor(dev); 278f1c579b1SScott Long PACB pACB = devclass_get_softc(arcmsr_devclass, unit); 279f1c579b1SScott Long #endif 280f1c579b1SScott Long 281f1c579b1SScott Long if(pACB==NULL) 282f1c579b1SScott Long { 283f1c579b1SScott Long return ENXIO; 284f1c579b1SScott Long } 285f1c579b1SScott Long pACB->acb_flags &= ~ACB_F_IOCTL_OPEN; 286f1c579b1SScott Long return 0; 287f1c579b1SScott Long } 288f1c579b1SScott Long /* 289f1c579b1SScott Long ************************************************************************** 290f1c579b1SScott Long **ENOENT 291f1c579b1SScott Long **ENOIOCTL 292f1c579b1SScott Long **ENOMEM 293f1c579b1SScott Long **EINVAL 294f1c579b1SScott Long ************************************************************************** 295f1c579b1SScott Long */ 296f1c579b1SScott Long #if __FreeBSD_version < 500005 297f1c579b1SScott Long static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct proc *proc) 298f1c579b1SScott Long #else 299f1c579b1SScott Long #if __FreeBSD_version < 503000 300f1c579b1SScott Long static int arcmsr_ioctl(dev_t dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc) 301f1c579b1SScott Long #else 302f1c579b1SScott Long static int arcmsr_ioctl(struct cdev *dev, u_long ioctl_cmd, caddr_t arg,int flags, d_thread_t *proc) 303f1c579b1SScott Long #endif 304f1c579b1SScott Long #endif 305f1c579b1SScott Long { 306f1c579b1SScott Long #if __FreeBSD_version < 503000 307f1c579b1SScott Long PACB pACB=dev->si_drv1; 308f1c579b1SScott Long #else 309f1c579b1SScott Long int unit = minor(dev); 310f1c579b1SScott Long PACB pACB = devclass_get_softc(arcmsr_devclass, unit); 311f1c579b1SScott Long #endif 312f1c579b1SScott Long 313f1c579b1SScott Long if(pACB==NULL) 314f1c579b1SScott Long { 315f1c579b1SScott Long return ENXIO; 316f1c579b1SScott Long } 317f1c579b1SScott Long return(arcmsr_iop_ioctlcmd(pACB,ioctl_cmd,arg)); 318f1c579b1SScott Long } 319f1c579b1SScott Long /* 320f1c579b1SScott Long ************************************************************************** 321f1c579b1SScott Long ************************************************************************** 322f1c579b1SScott Long */ 323f1c579b1SScott Long LONG arcmsr_queue_dpc(PACB pACB,DPCFUN dpcfun,VOID *arg) 324f1c579b1SScott Long { 325f1c579b1SScott Long ULONG s; 326f1c579b1SScott Long UCHAR index_pointer; 327f1c579b1SScott Long 328f1c579b1SScott Long #if ARCMSR_DEBUG0 329f1c579b1SScott Long printf("arcmsr_queue_dpc................. \n"); 330f1c579b1SScott Long #endif 331f1c579b1SScott Long 332f1c579b1SScott Long s=splcam(); 333f1c579b1SScott Long index_pointer=(pACB->dpcQ_tail + 1) % ARCMSR_MAX_DPC; 334f1c579b1SScott Long if(index_pointer==pACB->dpcQ_head) 335f1c579b1SScott Long { 336f1c579b1SScott Long splx(s); 337f1c579b1SScott Long printf("DPC Queue full!\n"); 338f1c579b1SScott Long return -1; 339f1c579b1SScott Long } 340f1c579b1SScott Long pACB->dpcQ[pACB->dpcQ_tail].dpcfun=dpcfun; 341f1c579b1SScott Long pACB->dpcQ[pACB->dpcQ_tail].arg=arg; 342f1c579b1SScott Long pACB->dpcQ_tail=index_pointer; 343f1c579b1SScott Long /* 344f1c579b1SScott Long ********************************************************* 345f1c579b1SScott Long ********************************************************* 346f1c579b1SScott Long */ 347f1c579b1SScott Long wakeup(pACB->kthread_proc); 348f1c579b1SScott Long 349f1c579b1SScott Long splx(s); 350f1c579b1SScott Long return 0; 351f1c579b1SScott Long } 352f1c579b1SScott Long /* 353f1c579b1SScott Long ************************************************************************** 354f1c579b1SScott Long ** arcmsr_do_dpcQ 355f1c579b1SScott Long ** execute dpc routine by kernel thread 356f1c579b1SScott Long *************************************************************************** 357f1c579b1SScott Long */ 358f1c579b1SScott Long VOID arcmsr_do_dpcQ(PACB pACB) 359f1c579b1SScott Long { 360f1c579b1SScott Long #if ARCMSR_DEBUG0 361f1c579b1SScott Long printf("arcmsr_do_dpcQ................. \n"); 362f1c579b1SScott Long #endif 363f1c579b1SScott Long /* 364f1c579b1SScott Long ****************************************** 365f1c579b1SScott Long ****************************************** 366f1c579b1SScott Long */ 367f1c579b1SScott Long while (pACB->dpcQ_head!=pACB->dpcQ_tail) 368f1c579b1SScott Long { 369f1c579b1SScott Long ULONG s; 370f1c579b1SScott Long DPC dpc; 371f1c579b1SScott Long 372f1c579b1SScott Long /* got a "dpc routine" */ 373f1c579b1SScott Long s=splcam(); 374f1c579b1SScott Long dpc=pACB->dpcQ[pACB->dpcQ_head]; 375f1c579b1SScott Long pACB->dpcQ_head++; 376f1c579b1SScott Long pACB->dpcQ_head %=ARCMSR_MAX_DPC; 377f1c579b1SScott Long splx(s); 378f1c579b1SScott Long /* execute this "dpc routine" */ 379f1c579b1SScott Long dpc.dpcfun(dpc.arg); 380f1c579b1SScott Long } 381f1c579b1SScott Long return; 382f1c579b1SScott Long } 383f1c579b1SScott Long /* 384f1c579b1SScott Long ********************************************************************** 385f1c579b1SScott Long ** <second> bit 05,04,03,02,01,00: 0 - 59 386f1c579b1SScott Long ** <minute> bit 11,10,09,08,07,06: 0 - 59 387f1c579b1SScott Long ** <month> bit 15,14,13,12: 1 - 12 388f1c579b1SScott Long ** <hour> bit 21,20,19,18,17,16: 0 - 59 389f1c579b1SScott Long ** <day> bit 26,25,24,23,22: 1 - 31 390f1c579b1SScott Long ** <year> bit 31,30,29,28,27: 0=2000,31=2031 391f1c579b1SScott Long ********************************************************************** 392f1c579b1SScott Long */ 393f1c579b1SScott Long ULONG arcmsr_make_timespec(ULONG year,ULONG mon,ULONG day,ULONG hour,ULONG min,ULONG sec) 394f1c579b1SScott Long { 395f1c579b1SScott Long return((year<<27)|(day<<22)|(hour<<16)|(mon<<12)|(min<<6)|(sec)); 396f1c579b1SScott Long } 397f1c579b1SScott Long /* 398f1c579b1SScott Long ******************************************************************** 399f1c579b1SScott Long ******************************************************************** 400f1c579b1SScott Long */ 401f1c579b1SScott Long ULONG arcmsr_getcmos_time(VOID) 402f1c579b1SScott Long { 403f1c579b1SScott Long ULONG year,mon,day,hour,min,sec; 404f1c579b1SScott Long 405f1c579b1SScott Long #if ARCMSR_DEBUG0 406f1c579b1SScott Long printf("arcmsr_getcmos_time \n"); 407f1c579b1SScott Long #endif 408f1c579b1SScott Long sec=bcd2bin(rtcin(RTC_SEC)); 409f1c579b1SScott Long min=bcd2bin(rtcin(RTC_MIN)); 410f1c579b1SScott Long hour=bcd2bin(rtcin(RTC_HRS)); 411f1c579b1SScott Long day=bcd2bin(rtcin(RTC_DAY)); 412f1c579b1SScott Long mon=bcd2bin(rtcin(RTC_MONTH)); 413f1c579b1SScott Long year=bcd2bin(rtcin(RTC_YEAR)); 414f1c579b1SScott Long if((year +=1900) < 1970) 415f1c579b1SScott Long year +=100; 416f1c579b1SScott Long return arcmsr_make_timespec(year,mon,day,hour,min,sec); 417f1c579b1SScott Long } 418f1c579b1SScott Long /* 419f1c579b1SScott Long ********************************************************************************* 420f1c579b1SScott Long ** Asynchronous notification handler. 421f1c579b1SScott Long ********************************************************************************* 422f1c579b1SScott Long */ 423f1c579b1SScott Long static VOID arcmsr_async(VOID *cb_arg, ULONG code, struct cam_path *path, VOID *arg) 424f1c579b1SScott Long { 425f1c579b1SScott Long PACB pACB; 426f1c579b1SScott Long UCHAR target_id,target_lun; 427f1c579b1SScott Long struct cam_sim *sim; 428f1c579b1SScott Long ULONG s; 429f1c579b1SScott Long #if ARCMSR_DEBUG0 430f1c579b1SScott Long printf("arcmsr_async.......................................... \n"); 431f1c579b1SScott Long #endif 432f1c579b1SScott Long s=splcam(); 433f1c579b1SScott Long 434f1c579b1SScott Long sim=(struct cam_sim *) cb_arg; 435f1c579b1SScott Long pACB =(PACB) cam_sim_softc(sim); 436f1c579b1SScott Long switch (code) 437f1c579b1SScott Long { 438f1c579b1SScott Long case AC_LOST_DEVICE: 439f1c579b1SScott Long target_id=xpt_path_target_id(path); 440f1c579b1SScott Long target_lun=xpt_path_lun_id(path); 441f1c579b1SScott Long if((target_id > ARCMSR_MAX_TARGETID) || (target_lun > ARCMSR_MAX_TARGETLUN)) 442f1c579b1SScott Long { 443f1c579b1SScott Long break; 444f1c579b1SScott Long } 445f1c579b1SScott Long printf("%s:scsi id%d lun%d device lost \n",device_get_name(pACB->pci_dev),target_id,target_lun); 446f1c579b1SScott Long break; 447f1c579b1SScott Long default: 448f1c579b1SScott Long break; 449f1c579b1SScott Long } 450f1c579b1SScott Long splx(s); 451f1c579b1SScott Long } 452f1c579b1SScott Long /* 453f1c579b1SScott Long ************************************************************************** 454f1c579b1SScott Long * arcmsr_do_thread_works 455f1c579b1SScott Long * execute programs schedule by kernel thread 456f1c579b1SScott Long * execute programs schedule by kernel thread 457f1c579b1SScott Long * :do background rebuilding 458f1c579b1SScott Long * 459f1c579b1SScott Long * tsleep(void *ident,int priority,const char *wmesg,int timo) 460f1c579b1SScott Long * tsleep() 461f1c579b1SScott Long * General sleep call. Suspends the current process until a wakeup is 462f1c579b1SScott Long * performed on the specified identifier. The process will then be made 463f1c579b1SScott Long * runnable with the specified priority. Sleeps at most timo/hz seconds 464f1c579b1SScott Long * (0 means no timeout). If pri includes PCATCH flag, signals are checked 465f1c579b1SScott Long * before and after sleeping, else signals are not checked. Returns 0 if 466f1c579b1SScott Long * awakened, EWOULDBLOCK if the timeout expires. If PCATCH is set and a 467f1c579b1SScott Long * signal needs to be delivered, ERESTART is returned if the current system 468f1c579b1SScott Long * call should be restarted if possible, and EINTR is returned if the system 469f1c579b1SScott Long * call should be interrupted by the signal (return EINTR). 470f1c579b1SScott Long * 471f1c579b1SScott Long * await(int priority, int timo) 472f1c579b1SScott Long * await() - wait for async condition to occur. The process blocks until 473f1c579b1SScott Long * wakeup() is called on the most recent asleep() address. If wakeup is called 474f1c579b1SScott Long * priority to await(), await() winds up being a NOP. 475f1c579b1SScott Long * 476f1c579b1SScott Long * If await() is called more then once (without an intervening asleep() call), 477f1c579b1SScott Long * await() is still effectively a NOP but it calls mi_switch() to give other 478f1c579b1SScott Long * processes some cpu before returning. The process is left runnable. 479f1c579b1SScott Long * 480f1c579b1SScott Long * <<<<<<<< EXPERIMENTAL, UNTESTED >>>>>>>>>> 481f1c579b1SScott Long * asleep(void *ident, int priority, const char *wmesg, int timo) 482f1c579b1SScott Long * asleep() - async sleep call. Place process on wait queue and return 483f1c579b1SScott Long * immediately without blocking. The process stays runnable until await() 484f1c579b1SScott Long * is called. If ident is NULL, remove process from wait queue if it is still 485f1c579b1SScott Long * on one. 486f1c579b1SScott Long * 487f1c579b1SScott Long * Only the most recent sleep condition is effective when making successive 488f1c579b1SScott Long * calls to asleep() or when calling tsleep(). 489f1c579b1SScott Long * 490f1c579b1SScott Long * The timeout, if any, is not initiated until await() is called. The sleep 491f1c579b1SScott Long * priority, signal, and timeout is specified in the asleep() call but may be 492f1c579b1SScott Long * overriden in the await() call. 493f1c579b1SScott Long * 494f1c579b1SScott Long * <<<<<<<< EXPERIMENTAL, UNTESTED >>>>>>>>>> 495f1c579b1SScott Long * :do background rebuilding 496f1c579b1SScott Long *************************************************************************** 497f1c579b1SScott Long */ 498f1c579b1SScott Long VOID arcmsr_do_thread_works(VOID *arg) 499f1c579b1SScott Long { 500f1c579b1SScott Long PACB pACB=(PACB) arg; 501f1c579b1SScott Long ARCMSR_LOCK_INIT(&pACB->arcmsr_kthread_lock, "arcmsr kthread lock"); 502f1c579b1SScott Long 503f1c579b1SScott Long #if ARCMSR_DEBUG0 504f1c579b1SScott Long printf("arcmsr_do_thread_works................. \n"); 505f1c579b1SScott Long #endif 506f1c579b1SScott Long 507f1c579b1SScott Long ARCMSR_LOCK_ACQUIRE(&pACB->arcmsr_kthread_lock); 508f1c579b1SScott Long while(1) 509f1c579b1SScott Long { 510f1c579b1SScott Long tsleep((caddr_t)pACB->kthread_proc, PRIBIO | PWAIT, "arcmsr", hz/4);/*.25 sec*/ 511f1c579b1SScott Long /* 512f1c579b1SScott Long ** if do_dpcQ_semaphore is signal 513f1c579b1SScott Long ** do following works 514f1c579b1SScott Long */ 515f1c579b1SScott Long arcmsr_do_dpcQ(pACB); /*see if there were some dpc routine need to execute*/ 516f1c579b1SScott Long if(pACB->acb_flags & ACB_F_STOP_THREAD) 517f1c579b1SScott Long { 518f1c579b1SScott Long ARCMSR_LOCK_RELEASE(&pACB->arcmsr_kthread_lock); 519f1c579b1SScott Long break; 520f1c579b1SScott Long } 521f1c579b1SScott Long } 522f1c579b1SScott Long kthread_exit(0); 523f1c579b1SScott Long return; 524f1c579b1SScott Long } 525f1c579b1SScott Long /* 526f1c579b1SScott Long ************************************************************************ 527f1c579b1SScott Long ** 528f1c579b1SScott Long ** 529f1c579b1SScott Long ************************************************************************ 530f1c579b1SScott Long */ 531f1c579b1SScott Long VOID arcmsr_flush_adapter_cache(PACB pACB) 532f1c579b1SScott Long { 533f1c579b1SScott Long #if ARCMSR_DEBUG0 534f1c579b1SScott Long printf("arcmsr_flush_adapter_cache..............\n"); 535f1c579b1SScott Long #endif 536f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->inbound_msgaddr0,ARCMSR_INBOUND_MESG0_FLUSH_CACHE); 537f1c579b1SScott Long return; 538f1c579b1SScott Long } 539f1c579b1SScott Long /* 540f1c579b1SScott Long ********************************************************************** 541f1c579b1SScott Long ** 542f1c579b1SScott Long ** 543f1c579b1SScott Long ** 544f1c579b1SScott Long ********************************************************************** 545f1c579b1SScott Long */ 546f1c579b1SScott Long BOOLEAN arcmsr_wait_msgint_ready(PACB pACB) 547f1c579b1SScott Long { 548f1c579b1SScott Long ULONG Index; 549f1c579b1SScott Long UCHAR Retries=0x00; 550f1c579b1SScott Long do 551f1c579b1SScott Long { 552f1c579b1SScott Long for(Index=0; Index < 500000; Index++) 553f1c579b1SScott Long { 554f1c579b1SScott Long if(CHIP_REG_READ32(&pACB->pmu->outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) 555f1c579b1SScott Long { 556f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/ 557f1c579b1SScott Long return TRUE; 558f1c579b1SScott Long } 559f1c579b1SScott Long /* one us delay */ 560f1c579b1SScott Long UDELAY(10); 561f1c579b1SScott Long }/*max 5 seconds*/ 562f1c579b1SScott Long }while(Retries++ < 24);/*max 2 minutes*/ 563f1c579b1SScott Long return FALSE; 564f1c579b1SScott Long } 565f1c579b1SScott Long /* 566f1c579b1SScott Long ********************************************************************** 567f1c579b1SScott Long ** 568f1c579b1SScott Long ** Q back this SRB into ACB ArraySRB 569f1c579b1SScott Long ** 570f1c579b1SScott Long ********************************************************************** 571f1c579b1SScott Long */ 572f1c579b1SScott Long VOID arcmsr_srb_complete(PSRB pSRB) 573f1c579b1SScott Long { 574f1c579b1SScott Long ULONG s; 575f1c579b1SScott Long PACB pACB=pSRB->pACB; 576f1c579b1SScott Long union ccb *pccb=pSRB->pccb; 577f1c579b1SScott Long 578f1c579b1SScott Long #if ARCMSR_DEBUG0 579f1c579b1SScott Long printf("arcmsr_srb_complete: pSRB=%p srb_doneindex=%x srb_startindex=%x\n",pSRB,pACB->srb_doneindex,pACB->srb_startindex); 580f1c579b1SScott Long #endif 581f1c579b1SScott Long 582f1c579b1SScott Long if ((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) 583f1c579b1SScott Long { 584f1c579b1SScott Long bus_dmasync_op_t op; 585f1c579b1SScott Long 586f1c579b1SScott Long if ((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 587f1c579b1SScott Long { 588f1c579b1SScott Long op = BUS_DMASYNC_POSTREAD; 589f1c579b1SScott Long } 590f1c579b1SScott Long else 591f1c579b1SScott Long { 592f1c579b1SScott Long op = BUS_DMASYNC_POSTWRITE; 593f1c579b1SScott Long } 594f1c579b1SScott Long bus_dmamap_sync(pACB->buffer_dmat, pSRB->dmamap, op); 595f1c579b1SScott Long bus_dmamap_unload(pACB->buffer_dmat, pSRB->dmamap); 596f1c579b1SScott Long } 597f1c579b1SScott Long s=splcam(); 598f1c579b1SScott Long atomic_subtract_int(&pACB->srboutstandingcount,1); 599f1c579b1SScott Long pSRB->startdone=ARCMSR_SRB_DONE; 600f1c579b1SScott Long pSRB->srb_flags=0; 601f1c579b1SScott Long pACB->psrbringQ[pACB->srb_doneindex]=pSRB; 602f1c579b1SScott Long pACB->srb_doneindex++; 603f1c579b1SScott Long pACB->srb_doneindex %= ARCMSR_MAX_FREESRB_NUM; 604f1c579b1SScott Long splx(s); 605f1c579b1SScott Long xpt_done(pccb); 606f1c579b1SScott Long return; 607f1c579b1SScott Long } 608f1c579b1SScott Long /* 609f1c579b1SScott Long ********************************************************************** 610f1c579b1SScott Long ** if scsi error do auto request sense 611f1c579b1SScott Long ********************************************************************** 612f1c579b1SScott Long */ 613f1c579b1SScott Long VOID arcmsr_report_SenseInfoBuffer(PSRB pSRB) 614f1c579b1SScott Long { 615f1c579b1SScott Long union ccb *pccb=pSRB->pccb; 616f1c579b1SScott Long PSENSE_DATA psenseBuffer=(PSENSE_DATA)&pccb->csio.sense_data; 617f1c579b1SScott Long #if ARCMSR_DEBUG0 618f1c579b1SScott Long printf("arcmsr_report_SenseInfoBuffer...........\n"); 619f1c579b1SScott Long #endif 620f1c579b1SScott Long 621f1c579b1SScott Long pccb->ccb_h.status|=CAM_REQ_CMP; 622f1c579b1SScott Long if(psenseBuffer) 623f1c579b1SScott Long { 624f1c579b1SScott Long memset(psenseBuffer, 0, sizeof(pccb->csio.sense_data)); 625f1c579b1SScott Long memcpy(psenseBuffer,pSRB->arcmsr_cdb.SenseData,get_min(sizeof(struct _SENSE_DATA),sizeof(pccb->csio.sense_data))); 626f1c579b1SScott Long psenseBuffer->ErrorCode=0x70; 627f1c579b1SScott Long psenseBuffer->Valid=1; 628f1c579b1SScott Long pccb->ccb_h.status|=CAM_AUTOSNS_VALID; 629f1c579b1SScott Long } 630f1c579b1SScott Long return; 631f1c579b1SScott Long } 632f1c579b1SScott Long /* 633f1c579b1SScott Long ********************************************************************* 634f1c579b1SScott Long ** to insert pSRB into tail of pACB wait exec srbQ 635f1c579b1SScott Long ********************************************************************* 636f1c579b1SScott Long */ 637f1c579b1SScott Long VOID arcmsr_queue_wait2go_srb(PACB pACB,PSRB pSRB) 638f1c579b1SScott Long { 639f1c579b1SScott Long ULONG s; 640f1c579b1SScott Long LONG i=0; 641f1c579b1SScott Long #if ARCMSR_DEBUG0 642f1c579b1SScott Long printf("arcmsr_qtail_wait2go_srb:......................................... \n"); 643f1c579b1SScott Long #endif 644f1c579b1SScott Long 645f1c579b1SScott Long s=splcam(); 646f1c579b1SScott Long while(1) 647f1c579b1SScott Long { 648f1c579b1SScott Long if(pACB->psrbwait2go[i]==NULL) 649f1c579b1SScott Long { 650f1c579b1SScott Long pACB->psrbwait2go[i]=pSRB; 651f1c579b1SScott Long atomic_add_int(&pACB->srbwait2gocount,1); 652f1c579b1SScott Long splx(s); 653f1c579b1SScott Long return; 654f1c579b1SScott Long } 655f1c579b1SScott Long i++; 656f1c579b1SScott Long i%=ARCMSR_MAX_OUTSTANDING_CMD; 657f1c579b1SScott Long } 658f1c579b1SScott Long return; 659f1c579b1SScott Long } 660f1c579b1SScott Long /* 661f1c579b1SScott Long ********************************************************************* 662f1c579b1SScott Long ** 663f1c579b1SScott Long ********************************************************************* 664f1c579b1SScott Long */ 665f1c579b1SScott Long VOID arcmsr_abort_allcmd(PACB pACB) 666f1c579b1SScott Long { 667f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->inbound_msgaddr0,ARCMSR_INBOUND_MESG0_ABORT_CMD); 668f1c579b1SScott Long return; 669f1c579b1SScott Long } 670f1c579b1SScott Long 671f1c579b1SScott Long /* 672f1c579b1SScott Long **************************************************************************** 673f1c579b1SScott Long ** Routine Description: Reset 80331 iop. 674f1c579b1SScott Long ** Arguments: 675f1c579b1SScott Long ** Return Value: Nothing. 676f1c579b1SScott Long **************************************************************************** 677f1c579b1SScott Long */ 678f1c579b1SScott Long VOID arcmsr_iop_reset(PACB pACB) 679f1c579b1SScott Long { 680f1c579b1SScott Long PSRB pSRB,pfreesrb; 681f1c579b1SScott Long ULONG intmask_org,mask; 682f1c579b1SScott Long LONG i=0; 683f1c579b1SScott Long 684f1c579b1SScott Long #if ARCMSR_DEBUG0 685f1c579b1SScott Long printf("arcmsr_iop_reset: reset iop controller......................................\n"); 686f1c579b1SScott Long #endif 687f1c579b1SScott Long if(pACB->srboutstandingcount!=0) 688f1c579b1SScott Long { 689f1c579b1SScott Long /* Q back all outstanding srb into wait exec psrb Q*/ 690f1c579b1SScott Long #if ARCMSR_DEBUG0 691f1c579b1SScott Long printf("arcmsr_iop_reset: srboutstandingcount=%d ...\n",pACB->srboutstandingcount); 692f1c579b1SScott Long #endif 693f1c579b1SScott Long /* disable all outbound interrupt */ 694f1c579b1SScott Long intmask_org=CHIP_REG_READ32(&pACB->pmu->outbound_intmask); 695f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->outbound_intmask,intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); 696f1c579b1SScott Long /* talk to iop 331 outstanding command aborted*/ 697f1c579b1SScott Long arcmsr_abort_allcmd(pACB); 698f1c579b1SScott Long if(arcmsr_wait_msgint_ready(pACB)!=TRUE) 699f1c579b1SScott Long { 700f1c579b1SScott Long printf("arcmsr_iop_reset: wait 'abort all outstanding command' timeout.................in \n"); 701f1c579b1SScott Long } 702f1c579b1SScott Long /*clear all outbound posted Q*/ 703f1c579b1SScott Long for(i=0;i<ARCMSR_MAX_OUTSTANDING_CMD;i++) 704f1c579b1SScott Long { 705f1c579b1SScott Long CHIP_REG_READ32(&pACB->pmu->outbound_queueport); 706f1c579b1SScott Long } 707f1c579b1SScott Long pfreesrb=pACB->pfreesrb; 708f1c579b1SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) 709f1c579b1SScott Long { 710f1c579b1SScott Long pSRB=&pfreesrb[i]; 711f1c579b1SScott Long if(pSRB->startdone==ARCMSR_SRB_START) 712f1c579b1SScott Long { 713f1c579b1SScott Long pSRB->startdone=ARCMSR_SRB_ABORTED; 714f1c579b1SScott Long pSRB->pccb->ccb_h.status=CAM_REQ_ABORTED; 715f1c579b1SScott Long arcmsr_srb_complete(pSRB); 716f1c579b1SScott Long } 717f1c579b1SScott Long } 718f1c579b1SScott Long /* enable all outbound interrupt */ 719f1c579b1SScott Long mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE); 720f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->outbound_intmask,intmask_org & mask); 721f1c579b1SScott Long atomic_set_int(&pACB->srboutstandingcount,0); 722f1c579b1SScott Long /* post abort all outstanding command message to RAID controller */ 723f1c579b1SScott Long } 724f1c579b1SScott Long i=0; 725f1c579b1SScott Long while(pACB->srbwait2gocount > 0) 726f1c579b1SScott Long { 727f1c579b1SScott Long pSRB=pACB->psrbwait2go[i]; 728f1c579b1SScott Long if(pSRB!=NULL) 729f1c579b1SScott Long { 730f1c579b1SScott Long #if ARCMSR_DEBUG0 731f1c579b1SScott Long printf("arcmsr_iop_reset:abort command... srbwait2gocount=%d ...\n",pACB->srbwait2gocount); 732f1c579b1SScott Long #endif 733f1c579b1SScott Long pACB->psrbwait2go[i]=NULL; 734f1c579b1SScott Long pSRB->startdone=ARCMSR_SRB_ABORTED; 735f1c579b1SScott Long pSRB->pccb->ccb_h.status=CAM_REQ_ABORTED; 736f1c579b1SScott Long arcmsr_srb_complete(pSRB); 737f1c579b1SScott Long atomic_subtract_int(&pACB->srbwait2gocount,1); 738f1c579b1SScott Long } 739f1c579b1SScott Long i++; 740f1c579b1SScott Long i%=ARCMSR_MAX_OUTSTANDING_CMD; 741f1c579b1SScott Long } 742f1c579b1SScott Long return; 743f1c579b1SScott Long } 744f1c579b1SScott Long /* 745f1c579b1SScott Long ********************************************************************** 746f1c579b1SScott Long ** 747f1c579b1SScott Long ** PAGE_SIZE=4096 or 8192,PAGE_SHIFT=12 748f1c579b1SScott Long ********************************************************************** 749f1c579b1SScott Long */ 750f1c579b1SScott Long VOID arcmsr_build_srb(PSRB pSRB, bus_dma_segment_t *dm_segs, LONG nseg) 751f1c579b1SScott Long { 752f1c579b1SScott Long PARCMSR_CDB pARCMSR_CDB=&pSRB->arcmsr_cdb; 753f1c579b1SScott Long PCHAR psge=(PCHAR)&pARCMSR_CDB->u; 754f1c579b1SScott Long ULONG address_lo,address_hi; 755f1c579b1SScott Long union ccb *pccb=pSRB->pccb; 756f1c579b1SScott Long struct ccb_scsiio *pcsio=&pccb->csio; 757f1c579b1SScott Long LONG arccdbsize=0x30; 758f1c579b1SScott Long 759f1c579b1SScott Long #if ARCMSR_DEBUG0 760f1c579b1SScott Long printf("arcmsr_build_srb........................... \n"); 761f1c579b1SScott Long #endif 762f1c579b1SScott Long memset(pARCMSR_CDB,0,sizeof(struct _ARCMSR_CDB)); 763f1c579b1SScott Long pARCMSR_CDB->Bus=0; 764f1c579b1SScott Long pARCMSR_CDB->TargetID=pccb->ccb_h.target_id; 765f1c579b1SScott Long pARCMSR_CDB->LUN=pccb->ccb_h.target_lun; 766f1c579b1SScott Long pARCMSR_CDB->Function=1; 767f1c579b1SScott Long pARCMSR_CDB->CdbLength=(UCHAR)pcsio->cdb_len; 768f1c579b1SScott Long pARCMSR_CDB->Context=(CPT2INT)pARCMSR_CDB; 769f1c579b1SScott Long bcopy(pcsio->cdb_io.cdb_bytes, pARCMSR_CDB->Cdb, pcsio->cdb_len); 770f1c579b1SScott Long if(nseg != 0) 771f1c579b1SScott Long { 772f1c579b1SScott Long PACB pACB=pSRB->pACB; 773f1c579b1SScott Long bus_dmasync_op_t op; 774f1c579b1SScott Long LONG length,i,cdb_sgcount=0; 775f1c579b1SScott Long 776f1c579b1SScott Long /* map stor port SG list to our iop SG List.*/ 777f1c579b1SScott Long for(i=0;i<nseg;i++) 778f1c579b1SScott Long { 779f1c579b1SScott Long /* Get the physical address of the current data pointer */ 780f1c579b1SScott Long length=(ULONG) dm_segs[i].ds_len; 781f1c579b1SScott Long address_lo=dma_addr_lo32(dm_segs[i].ds_addr); 782f1c579b1SScott Long address_hi=dma_addr_hi32(dm_segs[i].ds_addr); 783f1c579b1SScott Long if(address_hi==0) 784f1c579b1SScott Long { 785f1c579b1SScott Long PSG32ENTRY pdma_sg=(PSG32ENTRY)psge; 786f1c579b1SScott Long pdma_sg->address=address_lo; 787f1c579b1SScott Long pdma_sg->length=length; 788f1c579b1SScott Long psge += sizeof(SG32ENTRY); 789f1c579b1SScott Long arccdbsize += sizeof(SG32ENTRY); 790f1c579b1SScott Long } 791f1c579b1SScott Long else 792f1c579b1SScott Long { 793f1c579b1SScott Long LONG sg64s_size=0,tmplength=length; 794f1c579b1SScott Long 795f1c579b1SScott Long #if ARCMSR_DEBUG0 796f1c579b1SScott Long printf("arcmsr_build_srb: !!!!!!!!!!!......address_hi=%x.... \n",address_hi); 797f1c579b1SScott Long #endif 798f1c579b1SScott Long while(1) 799f1c579b1SScott Long { 800f1c579b1SScott Long LONG64 span4G,length0; 801f1c579b1SScott Long PSG64ENTRY pdma_sg=(PSG64ENTRY)psge; 802f1c579b1SScott Long 803f1c579b1SScott Long span4G=(LONG64)address_lo + tmplength; 804f1c579b1SScott Long pdma_sg->addresshigh=address_hi; 805f1c579b1SScott Long pdma_sg->address=address_lo; 806f1c579b1SScott Long if(span4G > 0x100000000) 807f1c579b1SScott Long { 808f1c579b1SScott Long /*see if cross 4G boundary*/ 809f1c579b1SScott Long length0=0x100000000-address_lo; 810f1c579b1SScott Long pdma_sg->length=(ULONG)length0|IS_SG64_ADDR; 811f1c579b1SScott Long address_hi=address_hi+1; 812f1c579b1SScott Long address_lo=0; 813f1c579b1SScott Long tmplength=tmplength-(LONG)length0; 814f1c579b1SScott Long sg64s_size += sizeof(SG64ENTRY); 815f1c579b1SScott Long psge += sizeof(SG64ENTRY); 816f1c579b1SScott Long cdb_sgcount++; 817f1c579b1SScott Long } 818f1c579b1SScott Long else 819f1c579b1SScott Long { 820f1c579b1SScott Long pdma_sg->length=tmplength|IS_SG64_ADDR; 821f1c579b1SScott Long sg64s_size += sizeof(SG64ENTRY); 822f1c579b1SScott Long psge += sizeof(SG64ENTRY); 823f1c579b1SScott Long break; 824f1c579b1SScott Long } 825f1c579b1SScott Long } 826f1c579b1SScott Long arccdbsize += sg64s_size; 827f1c579b1SScott Long } 828f1c579b1SScott Long cdb_sgcount++; 829f1c579b1SScott Long } 830f1c579b1SScott Long pARCMSR_CDB->sgcount=(UCHAR)cdb_sgcount; 831f1c579b1SScott Long pARCMSR_CDB->DataLength=pcsio->dxfer_len; 832f1c579b1SScott Long if( arccdbsize > 256) 833f1c579b1SScott Long { 834f1c579b1SScott Long pARCMSR_CDB->Flags|=ARCMSR_CDB_FLAG_SGL_BSIZE; 835f1c579b1SScott Long } 836f1c579b1SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 837f1c579b1SScott Long { 838f1c579b1SScott Long op=BUS_DMASYNC_PREREAD; 839f1c579b1SScott Long } 840f1c579b1SScott Long else 841f1c579b1SScott Long { 842f1c579b1SScott Long op=BUS_DMASYNC_PREWRITE; 843f1c579b1SScott Long pARCMSR_CDB->Flags|=ARCMSR_CDB_FLAG_WRITE; 844f1c579b1SScott Long pSRB->srb_flags|=SRB_FLAG_WRITE; 845f1c579b1SScott Long } 846f1c579b1SScott Long bus_dmamap_sync(pACB->buffer_dmat, pSRB->dmamap, op); 847f1c579b1SScott Long } 848f1c579b1SScott Long #if ARCMSR_DEBUG0 849f1c579b1SScott Long printf("arcmsr_build_srb: pSRB=%p cmd=%x xferlength=%d arccdbsize=%d sgcount=%d\n",pSRB,pcsio->cdb_io.cdb_bytes[0],pARCMSR_CDB->DataLength,arccdbsize,pARCMSR_CDB->sgcount); 850f1c579b1SScott Long #endif 851f1c579b1SScott Long return; 852f1c579b1SScott Long } 853f1c579b1SScott Long /* 854f1c579b1SScott Long ************************************************************************** 855f1c579b1SScott Long ** 856f1c579b1SScott Long ** arcmsr_post_srb - Send a protocol specific ARC send postcard to a AIOC . 857f1c579b1SScott Long ** handle: Handle of registered ARC protocol driver 858f1c579b1SScott Long ** adapter_id: AIOC unique identifier(integer) 859f1c579b1SScott Long ** pPOSTCARD_SEND: Pointer to ARC send postcard 860f1c579b1SScott Long ** 861f1c579b1SScott Long ** This routine posts a ARC send postcard to the request post FIFO of a 862f1c579b1SScott Long ** specific ARC adapter. 863f1c579b1SScott Long ** 864f1c579b1SScott Long ************************************************************************** 865f1c579b1SScott Long */ 866f1c579b1SScott Long static VOID arcmsr_post_srb(PACB pACB,PSRB pSRB) 867f1c579b1SScott Long { 868f1c579b1SScott Long ULONG cdb_shifted_phyaddr=(ULONG) pSRB->cdb_shifted_phyaddr; 869f1c579b1SScott Long PARCMSR_CDB pARCMSR_CDB=(PARCMSR_CDB)&pSRB->arcmsr_cdb; 870f1c579b1SScott Long 871f1c579b1SScott Long #if ARCMSR_DEBUG0 872f1c579b1SScott Long printf("arcmsr_post_srb: pSRB=%p cdb_shifted_phyaddr=%x\n",pSRB,cdb_shifted_phyaddr); 873f1c579b1SScott Long #endif 874f1c579b1SScott Long atomic_add_int(&pACB->srboutstandingcount,1); 875f1c579b1SScott Long pSRB->startdone=ARCMSR_SRB_START; 876f1c579b1SScott Long if(pARCMSR_CDB->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) 877f1c579b1SScott Long { 878f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->inbound_queueport,cdb_shifted_phyaddr|ARCMSR_SRBPOST_FLAG_SGL_BSIZE); 879f1c579b1SScott Long } 880f1c579b1SScott Long else 881f1c579b1SScott Long { 882f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->inbound_queueport,cdb_shifted_phyaddr); 883f1c579b1SScott Long } 884f1c579b1SScott Long return; 885f1c579b1SScott Long } 886f1c579b1SScott Long /* 887f1c579b1SScott Long ************************************************************************** 888f1c579b1SScott Long ** 889f1c579b1SScott Long ** 890f1c579b1SScott Long ************************************************************************** 891f1c579b1SScott Long */ 892f1c579b1SScott Long VOID arcmsr_post_wait2go_srb(PACB pACB) 893f1c579b1SScott Long { 894f1c579b1SScott Long ULONG s; 895f1c579b1SScott Long PSRB pSRB; 896f1c579b1SScott Long LONG i=0; 897f1c579b1SScott Long #if ARCMSR_DEBUG0 898f1c579b1SScott Long printf("arcmsr_post_wait2go_srb:srbwait2gocount=%d srboutstandingcount=%d\n",pACB->srbwait2gocount,pACB->srboutstandingcount); 899f1c579b1SScott Long #endif 900f1c579b1SScott Long s=splcam(); 901f1c579b1SScott Long while((pACB->srbwait2gocount > 0) && (pACB->srboutstandingcount < ARCMSR_MAX_OUTSTANDING_CMD)) 902f1c579b1SScott Long { 903f1c579b1SScott Long pSRB=pACB->psrbwait2go[i]; 904f1c579b1SScott Long if(pSRB!=NULL) 905f1c579b1SScott Long { 906f1c579b1SScott Long pACB->psrbwait2go[i]=NULL; 907f1c579b1SScott Long arcmsr_post_srb(pACB,pSRB); 908f1c579b1SScott Long atomic_subtract_int(&pACB->srbwait2gocount,1); 909f1c579b1SScott Long } 910f1c579b1SScott Long i++; 911f1c579b1SScott Long i%=ARCMSR_MAX_OUTSTANDING_CMD; 912f1c579b1SScott Long } 913f1c579b1SScott Long splx(s); 914f1c579b1SScott Long return; 915f1c579b1SScott Long } 916f1c579b1SScott Long /* 917f1c579b1SScott Long ********************************************************************** 918f1c579b1SScott Long ** Function: arcmsr_post_Qbuffer 919f1c579b1SScott Long ** Output: 920f1c579b1SScott Long ********************************************************************** 921f1c579b1SScott Long */ 922f1c579b1SScott Long VOID arcmsr_post_Qbuffer(PACB pACB) 923f1c579b1SScott Long { 924f1c579b1SScott Long ULONG s; 925f1c579b1SScott Long PUCHAR pQbuffer; 926f1c579b1SScott Long PQBUFFER pwbuffer=(PQBUFFER)&pACB->pmu->ioctl_wbuffer; 927f1c579b1SScott Long PUCHAR iop_data=(PUCHAR)pwbuffer->data; 928f1c579b1SScott Long LONG allxfer_len=0; 929f1c579b1SScott Long 930f1c579b1SScott Long s=splcam(); 931f1c579b1SScott Long while((pACB->wqbuf_firstindex!=pACB->wqbuf_lastindex) && (allxfer_len<124)) 932f1c579b1SScott Long { 933f1c579b1SScott Long pQbuffer=&pACB->wqbuffer[pACB->wqbuf_firstindex]; 934f1c579b1SScott Long memcpy(iop_data,pQbuffer,1); 935f1c579b1SScott Long pACB->wqbuf_firstindex++; 936f1c579b1SScott Long pACB->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */ 937f1c579b1SScott Long iop_data++; 938f1c579b1SScott Long allxfer_len++; 939f1c579b1SScott Long } 940f1c579b1SScott Long pwbuffer->data_len=allxfer_len; 941f1c579b1SScott Long /* 942f1c579b1SScott Long ** push inbound doorbell and wait reply at hwinterrupt routine for next Qbuffer post 943f1c579b1SScott Long */ 944f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->inbound_doorbell,ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK); 945f1c579b1SScott Long splx(s); 946f1c579b1SScott Long return; 947f1c579b1SScott Long } 948f1c579b1SScott Long /* 949f1c579b1SScott Long ************************************************************************ 950f1c579b1SScott Long ** 951f1c579b1SScott Long ** 952f1c579b1SScott Long ************************************************************************ 953f1c579b1SScott Long */ 954f1c579b1SScott Long VOID arcmsr_stop_adapter_bgrb(PACB pACB) 955f1c579b1SScott Long { 956f1c579b1SScott Long #if ARCMSR_DEBUG0 957f1c579b1SScott Long printf("arcmsr_stop_adapter_bgrb..............\n"); 958f1c579b1SScott Long #endif 959f1c579b1SScott Long pACB->acb_flags |= ACB_F_MSG_STOP_BGRB; 960f1c579b1SScott Long pACB->acb_flags &= ~ACB_F_MSG_START_BGRB; 961f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->inbound_msgaddr0,ARCMSR_INBOUND_MESG0_STOP_BGRB); 962f1c579b1SScott Long return; 963f1c579b1SScott Long } 964f1c579b1SScott Long /* 965f1c579b1SScott Long ************************************************************************ 966f1c579b1SScott Long ** 967f1c579b1SScott Long ** 968f1c579b1SScott Long ************************************************************************ 969f1c579b1SScott Long */ 970f1c579b1SScott Long static VOID arcmsr_poll(struct cam_sim * psim) 971f1c579b1SScott Long { 972f1c579b1SScott Long arcmsr_interrupt(cam_sim_softc(psim)); 973f1c579b1SScott Long return; 974f1c579b1SScott Long } 975f1c579b1SScott Long /* 976f1c579b1SScott Long ********************************************************************** 977f1c579b1SScott Long ** Function: arcmsr_interrupt 978f1c579b1SScott Long ** Output: VOID 979f1c579b1SScott Long ** CAM Status field values 980f1c579b1SScott Long **typedef enum { 981f1c579b1SScott Long ** CAM_REQ_INPROG, CCB request is in progress 982f1c579b1SScott Long ** CAM_REQ_CMP, CCB request completed without error 983f1c579b1SScott Long ** CAM_REQ_ABORTED, CCB request aborted by the host 984f1c579b1SScott Long ** CAM_UA_ABORT, Unable to abort CCB request 985f1c579b1SScott Long ** CAM_REQ_CMP_ERR, CCB request completed with an error 986f1c579b1SScott Long ** CAM_BUSY, CAM subsytem is busy 987f1c579b1SScott Long ** CAM_REQ_INVALID, CCB request was invalid 988f1c579b1SScott Long ** CAM_PATH_INVALID, Supplied Path ID is invalid 989f1c579b1SScott Long ** CAM_DEV_NOT_THERE, SCSI Device Not Installed/there 990f1c579b1SScott Long ** CAM_UA_TERMIO, Unable to terminate I/O CCB request 991f1c579b1SScott Long ** CAM_SEL_TIMEOUT, Target Selection Timeout 992f1c579b1SScott Long ** CAM_CMD_TIMEOUT, Command timeout 993f1c579b1SScott Long ** CAM_SCSI_STATUS_ERROR, SCSI error, look at error code in CCB 994f1c579b1SScott Long ** CAM_MSG_REJECT_REC, Message Reject Received 995f1c579b1SScott Long ** CAM_SCSI_BUS_RESET, SCSI Bus Reset Sent/Received 996f1c579b1SScott Long ** CAM_UNCOR_PARITY, Uncorrectable parity error occurred 997f1c579b1SScott Long ** CAM_AUTOSENSE_FAIL=0x10, Autosense: request sense cmd fail 998f1c579b1SScott Long ** CAM_NO_HBA, No HBA Detected error 999f1c579b1SScott Long ** CAM_DATA_RUN_ERR, Data Overrun error 1000f1c579b1SScott Long ** CAM_UNEXP_BUSFREE, Unexpected Bus Free 1001f1c579b1SScott Long ** CAM_SEQUENCE_FAIL, Target Bus Phase Sequence Failure 1002f1c579b1SScott Long ** CAM_CCB_LEN_ERR, CCB length supplied is inadequate 1003f1c579b1SScott Long ** CAM_PROVIDE_FAIL, Unable to provide requested capability 1004f1c579b1SScott Long ** CAM_BDR_SENT, A SCSI BDR msg was sent to target 1005f1c579b1SScott Long ** CAM_REQ_TERMIO, CCB request terminated by the host 1006f1c579b1SScott Long ** CAM_UNREC_HBA_ERROR, Unrecoverable Host Bus Adapter Error 1007f1c579b1SScott Long ** CAM_REQ_TOO_BIG, The request was too large for this host 1008f1c579b1SScott Long ** CAM_REQUEUE_REQ, 1009f1c579b1SScott Long ** * This request should be requeued to preserve 1010f1c579b1SScott Long ** * transaction ordering. This typically occurs 1011f1c579b1SScott Long ** * when the SIM recognizes an error that should 1012f1c579b1SScott Long ** * freeze the queue and must place additional 1013f1c579b1SScott Long ** * requests for the target at the sim level 1014f1c579b1SScott Long ** * back into the XPT queue. 1015f1c579b1SScott Long ** 1016f1c579b1SScott Long ** CAM_IDE=0x33, Initiator Detected Error 1017f1c579b1SScott Long ** CAM_RESRC_UNAVAIL, Resource Unavailable 1018f1c579b1SScott Long ** CAM_UNACKED_EVENT, Unacknowledged Event by Host 1019f1c579b1SScott Long ** CAM_MESSAGE_RECV, Message Received in Host Target Mode 1020f1c579b1SScott Long ** CAM_INVALID_CDB, Invalid CDB received in Host Target Mode 1021f1c579b1SScott Long ** CAM_LUN_INVALID, Lun supplied is invalid 1022f1c579b1SScott Long ** CAM_TID_INVALID, Target ID supplied is invalid 1023f1c579b1SScott Long ** CAM_FUNC_NOTAVAIL, The requested function is not available 1024f1c579b1SScott Long ** CAM_NO_NEXUS, Nexus is not established 1025f1c579b1SScott Long ** CAM_IID_INVALID, The initiator ID is invalid 1026f1c579b1SScott Long ** CAM_CDB_RECVD, The SCSI CDB has been received 1027f1c579b1SScott Long ** CAM_LUN_ALRDY_ENA, The LUN is already eanbeld for target mode 1028f1c579b1SScott Long ** CAM_SCSI_BUSY, SCSI Bus Busy 1029f1c579b1SScott Long ** 1030f1c579b1SScott Long ** CAM_DEV_QFRZN=0x40, The DEV queue is frozen w/this err 1031f1c579b1SScott Long ** 1032f1c579b1SScott Long ** Autosense data valid for target 1033f1c579b1SScott Long ** CAM_AUTOSNS_VALID=0x80, 1034f1c579b1SScott Long ** CAM_RELEASE_SIMQ=0x100, SIM ready to take more commands 1035f1c579b1SScott Long ** CAM_SIM_QUEUED =0x200, SIM has this command in it's queue 1036f1c579b1SScott Long ** 1037f1c579b1SScott Long ** CAM_STATUS_MASK=0x3F, Mask bits for just the status # 1038f1c579b1SScott Long ** 1039f1c579b1SScott Long ** Target Specific Adjunct Status 1040f1c579b1SScott Long ** CAM_SENT_SENSE=0x40000000 sent sense with status 1041f1c579b1SScott Long **} cam_status; 1042f1c579b1SScott Long ********************************************************************** 1043f1c579b1SScott Long */ 1044f1c579b1SScott Long static VOID arcmsr_interrupt(VOID *arg) 1045f1c579b1SScott Long { 1046f1c579b1SScott Long PACB pACB=(PACB)arg; 1047f1c579b1SScott Long PSRB pSRB; 1048f1c579b1SScott Long ULONG flagpsrb,outbound_intstatus,outbound_doorbell; 1049f1c579b1SScott Long 1050f1c579b1SScott Long #if ARCMSR_DEBUG0 1051f1c579b1SScott Long printf("arcmsr_interrupt..............\n"); 1052f1c579b1SScott Long #endif 1053f1c579b1SScott Long /* 1054f1c579b1SScott Long ********************************************* 1055f1c579b1SScott Long ** check outbound intstatus �˹�L�l�t�����a 1056f1c579b1SScott Long ********************************************* 1057f1c579b1SScott Long */ 1058f1c579b1SScott Long outbound_intstatus=CHIP_REG_READ32(&pACB->pmu->outbound_intstatus) & pACB->outbound_int_enable; 1059f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->outbound_intstatus, outbound_intstatus);/*clear interrupt*/ 1060f1c579b1SScott Long if(outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) 1061f1c579b1SScott Long { 1062f1c579b1SScott Long #if ARCMSR_DEBUG0 1063f1c579b1SScott Long printf("arcmsr_interrupt:..........ARCMSR_MU_OUTBOUND_DOORBELL_INT\n"); 1064f1c579b1SScott Long #endif 1065f1c579b1SScott Long /* 1066f1c579b1SScott Long ********************************************* 1067f1c579b1SScott Long ** DOORBELL �m��! �O�_���l��nñ�� 1068f1c579b1SScott Long ********************************************* 1069f1c579b1SScott Long */ 1070f1c579b1SScott Long outbound_doorbell=CHIP_REG_READ32(&pACB->pmu->outbound_doorbell); 1071f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->outbound_doorbell,outbound_doorbell);/*clear interrupt */ 1072f1c579b1SScott Long if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) 1073f1c579b1SScott Long { 1074f1c579b1SScott Long PQBUFFER prbuffer=(PQBUFFER)&pACB->pmu->ioctl_rbuffer; 1075f1c579b1SScott Long PUCHAR iop_data=(PUCHAR)prbuffer->data; 1076f1c579b1SScott Long PUCHAR pQbuffer; 1077f1c579b1SScott Long LONG my_empty_len,iop_len,rqbuf_firstindex,rqbuf_lastindex; 1078f1c579b1SScott Long ULONG s; 1079f1c579b1SScott Long /*check this iop data if overflow my rqbuffer*/ 1080f1c579b1SScott Long s=splcam(); 1081f1c579b1SScott Long rqbuf_lastindex=pACB->rqbuf_lastindex; 1082f1c579b1SScott Long rqbuf_firstindex=pACB->rqbuf_firstindex; 1083f1c579b1SScott Long iop_len=prbuffer->data_len; 1084f1c579b1SScott Long my_empty_len=(rqbuf_firstindex-rqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1); 1085f1c579b1SScott Long if(my_empty_len>=iop_len) 1086f1c579b1SScott Long { 1087f1c579b1SScott Long while(iop_len > 0) 1088f1c579b1SScott Long { 1089f1c579b1SScott Long pQbuffer=&pACB->rqbuffer[pACB->rqbuf_lastindex]; 1090f1c579b1SScott Long memcpy(pQbuffer,iop_data,1); 1091f1c579b1SScott Long pACB->rqbuf_lastindex++; 1092f1c579b1SScott Long pACB->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;/*if last index number set it to 0 */ 1093f1c579b1SScott Long iop_data++; 1094f1c579b1SScott Long iop_len--; 1095f1c579b1SScott Long } 1096f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);/*signature, let IOP331 know data has been readed */ 1097f1c579b1SScott Long } 1098f1c579b1SScott Long else 1099f1c579b1SScott Long { 1100f1c579b1SScott Long pACB->acb_flags|=ACB_F_IOPDATA_OVERFLOW; 1101f1c579b1SScott Long } 1102f1c579b1SScott Long splx(s); 1103f1c579b1SScott Long } 1104f1c579b1SScott Long if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) 1105f1c579b1SScott Long { 1106f1c579b1SScott Long ULONG s; 1107f1c579b1SScott Long /* 1108f1c579b1SScott Long ********************************************* 1109f1c579b1SScott Long ** �ݬݬO�_�٦��l��n���D�H�X 1110f1c579b1SScott Long ********************************************* 1111f1c579b1SScott Long */ 1112f1c579b1SScott Long s=splcam(); 1113f1c579b1SScott Long if(pACB->wqbuf_firstindex!=pACB->wqbuf_lastindex) 1114f1c579b1SScott Long { 1115f1c579b1SScott Long PUCHAR pQbuffer; 1116f1c579b1SScott Long PQBUFFER pwbuffer=(PQBUFFER)&pACB->pmu->ioctl_wbuffer; 1117f1c579b1SScott Long PUCHAR iop_data=(PUCHAR)pwbuffer->data; 1118f1c579b1SScott Long LONG allxfer_len=0; 1119f1c579b1SScott Long 1120f1c579b1SScott Long while((pACB->wqbuf_firstindex!=pACB->wqbuf_lastindex) && (allxfer_len<124)) 1121f1c579b1SScott Long { 1122f1c579b1SScott Long pQbuffer=&pACB->wqbuffer[pACB->wqbuf_firstindex]; 1123f1c579b1SScott Long memcpy(iop_data,pQbuffer,1); 1124f1c579b1SScott Long pACB->wqbuf_firstindex++; 1125f1c579b1SScott Long pACB->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */ 1126f1c579b1SScott Long iop_data++; 1127f1c579b1SScott Long allxfer_len++; 1128f1c579b1SScott Long } 1129f1c579b1SScott Long pwbuffer->data_len=allxfer_len; 1130f1c579b1SScott Long /* 1131f1c579b1SScott Long ** push inbound doorbell tell iop driver data write ok and wait reply on next hwinterrupt for next Qbuffer post 1132f1c579b1SScott Long */ 1133f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->inbound_doorbell,ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK); 1134f1c579b1SScott Long } 1135f1c579b1SScott Long else 1136f1c579b1SScott Long { 1137f1c579b1SScott Long pACB->acb_flags |= ACB_F_IOCTL_WQBUFFER_CLEARED; 1138f1c579b1SScott Long } 1139f1c579b1SScott Long splx(s); 1140f1c579b1SScott Long } 1141f1c579b1SScott Long } 1142f1c579b1SScott Long if(outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) 1143f1c579b1SScott Long { 1144f1c579b1SScott Long /* 1145f1c579b1SScott Long ***************************************************************************** 1146f1c579b1SScott Long ** areca cdb command done 1147f1c579b1SScott Long ***************************************************************************** 1148f1c579b1SScott Long */ 1149f1c579b1SScott Long while(1) 1150f1c579b1SScott Long { 1151f1c579b1SScott Long if((flagpsrb=CHIP_REG_READ32(&pACB->pmu->outbound_queueport)) == 0xFFFFFFFF) 1152f1c579b1SScott Long { 1153f1c579b1SScott Long break;/*chip FIFO no srb for completion already*/ 1154f1c579b1SScott Long } 1155f1c579b1SScott Long /* check if command done with no error*/ 1156f1c579b1SScott Long pSRB=(PSRB)(CINT2P)(pACB->vir2phy_offset+(flagpsrb << 5));/*frame must be 32 bytes aligned*/ 1157f1c579b1SScott Long if((pSRB->pACB!=pACB) || (pSRB->startdone!=ARCMSR_SRB_START)) 1158f1c579b1SScott Long { 1159f1c579b1SScott Long if(pSRB->startdone==ARCMSR_SRB_ABORTED) 1160f1c579b1SScott Long { 1161f1c579b1SScott Long pSRB->pccb->ccb_h.status=CAM_REQ_ABORTED; 1162f1c579b1SScott Long arcmsr_srb_complete(pSRB); 1163f1c579b1SScott Long break; 1164f1c579b1SScott Long } 1165f1c579b1SScott Long printf("arcmsr_interrupt:got an illegal srb command done ...pACB=%p pSRB=%p srboutstandingcount=%d .....\n",pACB,pSRB,pACB->srboutstandingcount); 1166f1c579b1SScott Long break; 1167f1c579b1SScott Long } 1168f1c579b1SScott Long if((flagpsrb & ARCMSR_SRBREPLY_FLAG_ERROR)==0) 1169f1c579b1SScott Long { 1170f1c579b1SScott Long pSRB->pccb->ccb_h.status=CAM_REQ_CMP; 1171f1c579b1SScott Long arcmsr_srb_complete(pSRB); 1172f1c579b1SScott Long } 1173f1c579b1SScott Long else 1174f1c579b1SScott Long { 1175f1c579b1SScott Long switch(pSRB->arcmsr_cdb.DeviceStatus) 1176f1c579b1SScott Long { 1177f1c579b1SScott Long case ARCMSR_DEV_SELECT_TIMEOUT: 1178f1c579b1SScott Long { 1179f1c579b1SScott Long #if ARCMSR_DEBUG0 1180f1c579b1SScott Long printf("pSRB=%p ......ARCMSR_DEV_SELECT_TIMEOUT\n",pSRB); 1181f1c579b1SScott Long #endif 1182f1c579b1SScott Long pSRB->pccb->ccb_h.status=CAM_SEL_TIMEOUT; 1183f1c579b1SScott Long arcmsr_srb_complete(pSRB); 1184f1c579b1SScott Long } 1185f1c579b1SScott Long break; 1186f1c579b1SScott Long case ARCMSR_DEV_ABORTED: 1187f1c579b1SScott Long { 1188f1c579b1SScott Long #if ARCMSR_DEBUG0 1189f1c579b1SScott Long printf("pSRB=%p ......ARCMSR_DEV_ABORTED\n",pSRB); 1190f1c579b1SScott Long #endif 1191f1c579b1SScott Long pSRB->pccb->ccb_h.status=CAM_DEV_NOT_THERE; 1192f1c579b1SScott Long arcmsr_srb_complete(pSRB); 1193f1c579b1SScott Long } 1194f1c579b1SScott Long break; 1195f1c579b1SScott Long case ARCMSR_DEV_INIT_FAIL: 1196f1c579b1SScott Long { 1197f1c579b1SScott Long #if ARCMSR_DEBUG0 1198f1c579b1SScott Long printf("pSRB=%p .....ARCMSR_DEV_INIT_FAIL\n",pSRB); 1199f1c579b1SScott Long #endif 1200f1c579b1SScott Long pSRB->pccb->ccb_h.status=CAM_DEV_NOT_THERE; 1201f1c579b1SScott Long arcmsr_srb_complete(pSRB); 1202f1c579b1SScott Long } 1203f1c579b1SScott Long break; 1204f1c579b1SScott Long case SCSISTAT_CHECK_CONDITION: 1205f1c579b1SScott Long { 1206f1c579b1SScott Long #if ARCMSR_DEBUG0 1207f1c579b1SScott Long printf("pSRB=%p .....SCSISTAT_CHECK_CONDITION\n",pSRB); 1208f1c579b1SScott Long #endif 1209f1c579b1SScott Long arcmsr_report_SenseInfoBuffer(pSRB); 1210f1c579b1SScott Long arcmsr_srb_complete(pSRB); 1211f1c579b1SScott Long } 1212f1c579b1SScott Long break; 1213f1c579b1SScott Long default: 1214f1c579b1SScott Long /* error occur Q all error srb to errorsrbpending Q*/ 1215f1c579b1SScott Long printf("arcmsr_interrupt:command error done ......but got unknow DeviceStatus=%x....\n",pSRB->arcmsr_cdb.DeviceStatus); 1216f1c579b1SScott Long pSRB->pccb->ccb_h.status=CAM_UNCOR_PARITY;/*unknow error or crc error just for retry*/ 1217f1c579b1SScott Long arcmsr_srb_complete(pSRB); 1218f1c579b1SScott Long break; 1219f1c579b1SScott Long } 1220f1c579b1SScott Long } 1221f1c579b1SScott Long } /*drain reply FIFO*/ 1222f1c579b1SScott Long } 1223f1c579b1SScott Long if(pACB->srbwait2gocount != 0) 1224f1c579b1SScott Long { 1225f1c579b1SScott Long arcmsr_post_wait2go_srb(pACB);/*try to post all pending srb*/ 1226f1c579b1SScott Long } 1227f1c579b1SScott Long return; 1228f1c579b1SScott Long } 1229f1c579b1SScott Long /* 1230f1c579b1SScott Long *********************************************************************** 1231f1c579b1SScott Long ** 1232f1c579b1SScott Long **int copyin __P((const void *udaddr, void *kaddr, size_t len)); 1233f1c579b1SScott Long **int copyout __P((const void *kaddr, void *udaddr, size_t len)); 1234f1c579b1SScott Long ** 1235f1c579b1SScott Long **ENOENT "" No such file or directory "" 1236f1c579b1SScott Long **ENOIOCTL "" ioctl not handled by this layer "" 1237f1c579b1SScott Long **ENOMEM "" Cannot allocate memory "" 1238f1c579b1SScott Long **EINVAL "" Invalid argument "" 1239f1c579b1SScott Long ************************************************************************ 1240f1c579b1SScott Long */ 1241f1c579b1SScott Long LONG arcmsr_iop_ioctlcmd(PACB pACB,ULONG ioctl_cmd,caddr_t arg) 1242f1c579b1SScott Long { 1243f1c579b1SScott Long PCMD_IO_CONTROL pccbioctl=(PCMD_IO_CONTROL) arg; 1244f1c579b1SScott Long 1245f1c579b1SScott Long #if ARCMSR_DEBUG0 1246f1c579b1SScott Long printf("arcmsr_iop_ioctlcmd................. \n"); 1247f1c579b1SScott Long #endif 1248f1c579b1SScott Long 1249f1c579b1SScott Long if(memcmp(pccbioctl->Signature,"ARCMSR",6)!=0) 1250f1c579b1SScott Long { 1251f1c579b1SScott Long return EINVAL; 1252f1c579b1SScott Long } 1253f1c579b1SScott Long switch(ioctl_cmd) 1254f1c579b1SScott Long { 1255f1c579b1SScott Long case ARCMSR_IOCTL_READ_RQBUFFER: 1256f1c579b1SScott Long { 1257f1c579b1SScott Long ULONG s; 1258f1c579b1SScott Long PCMD_IOCTL_FIELD pccbioctlfld=(PCMD_IOCTL_FIELD)arg; 1259f1c579b1SScott Long PUCHAR pQbuffer,ptmpQbuffer=pccbioctlfld->ioctldatabuffer; 1260f1c579b1SScott Long LONG allxfer_len=0; 1261f1c579b1SScott Long 1262f1c579b1SScott Long s=splcam(); 1263f1c579b1SScott Long while((pACB->rqbuf_firstindex!=pACB->rqbuf_lastindex) && (allxfer_len<1031)) 1264f1c579b1SScott Long { 1265f1c579b1SScott Long /*copy READ QBUFFER to srb*/ 1266f1c579b1SScott Long pQbuffer=&pACB->rqbuffer[pACB->rqbuf_firstindex]; 1267f1c579b1SScott Long memcpy(ptmpQbuffer,pQbuffer,1); 1268f1c579b1SScott Long pACB->rqbuf_firstindex++; 1269f1c579b1SScott Long pACB->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; /*if last index number set it to 0 */ 1270f1c579b1SScott Long ptmpQbuffer++; 1271f1c579b1SScott Long allxfer_len++; 1272f1c579b1SScott Long } 1273f1c579b1SScott Long if(pACB->acb_flags & ACB_F_IOPDATA_OVERFLOW) 1274f1c579b1SScott Long { 1275f1c579b1SScott Long PQBUFFER prbuffer=(PQBUFFER)&pACB->pmu->ioctl_rbuffer; 1276f1c579b1SScott Long PUCHAR pQbuffer; 1277f1c579b1SScott Long PUCHAR iop_data=(PUCHAR)prbuffer->data; 1278f1c579b1SScott Long LONG iop_len; 1279f1c579b1SScott Long 1280f1c579b1SScott Long pACB->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 1281f1c579b1SScott Long iop_len=(LONG)prbuffer->data_len; 1282f1c579b1SScott Long /*this iop data does no chance to make me overflow again here, so just do it*/ 1283f1c579b1SScott Long while(iop_len>0) 1284f1c579b1SScott Long { 1285f1c579b1SScott Long pQbuffer=&pACB->rqbuffer[pACB->rqbuf_lastindex]; 1286f1c579b1SScott Long memcpy(pQbuffer,iop_data,1); 1287f1c579b1SScott Long pACB->rqbuf_lastindex++; 1288f1c579b1SScott Long pACB->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;/*if last index number set it to 0 */ 1289f1c579b1SScott Long iop_data++; 1290f1c579b1SScott Long iop_len--; 1291f1c579b1SScott Long } 1292f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);/*signature, let IOP331 know data has been readed */ 1293f1c579b1SScott Long } 1294f1c579b1SScott Long pccbioctl->Length=allxfer_len; 1295f1c579b1SScott Long pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_OK; 1296f1c579b1SScott Long splx(s); 1297f1c579b1SScott Long return ARC_IOCTL_SUCCESS; 1298f1c579b1SScott Long } 1299f1c579b1SScott Long break; 1300f1c579b1SScott Long case ARCMSR_IOCTL_WRITE_WQBUFFER: 1301f1c579b1SScott Long { 1302f1c579b1SScott Long ULONG s; 1303f1c579b1SScott Long PCMD_IOCTL_FIELD pccbioctlfld=(PCMD_IOCTL_FIELD)arg; 1304f1c579b1SScott Long LONG my_empty_len,user_len,wqbuf_firstindex,wqbuf_lastindex; 1305f1c579b1SScott Long PUCHAR pQbuffer,ptmpuserbuffer=pccbioctlfld->ioctldatabuffer; 1306f1c579b1SScott Long 1307f1c579b1SScott Long s=splcam(); 1308f1c579b1SScott Long user_len=pccbioctl->Length; 1309f1c579b1SScott Long 1310f1c579b1SScott Long /*check if data xfer length of this request will overflow my array qbuffer */ 1311f1c579b1SScott Long wqbuf_lastindex=pACB->wqbuf_lastindex; 1312f1c579b1SScott Long wqbuf_firstindex=pACB->wqbuf_firstindex; 1313f1c579b1SScott Long my_empty_len=(wqbuf_firstindex-wqbuf_lastindex-1)&(ARCMSR_MAX_QBUFFER-1); 1314f1c579b1SScott Long if(my_empty_len>=user_len) 1315f1c579b1SScott Long { 1316f1c579b1SScott Long while(user_len>0) 1317f1c579b1SScott Long { 1318f1c579b1SScott Long /*copy srb data to wqbuffer*/ 1319f1c579b1SScott Long pQbuffer=&pACB->wqbuffer[pACB->wqbuf_lastindex]; 1320f1c579b1SScott Long memcpy(pQbuffer,ptmpuserbuffer,1); 1321f1c579b1SScott Long pACB->wqbuf_lastindex++; 1322f1c579b1SScott Long pACB->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER;/*if last index number set it to 0 */ 1323f1c579b1SScott Long ptmpuserbuffer++; 1324f1c579b1SScott Long user_len--; 1325f1c579b1SScott Long } 1326f1c579b1SScott Long /*post fist Qbuffer*/ 1327f1c579b1SScott Long if(pACB->acb_flags & ACB_F_IOCTL_WQBUFFER_CLEARED) 1328f1c579b1SScott Long { 1329f1c579b1SScott Long pACB->acb_flags &=~ACB_F_IOCTL_WQBUFFER_CLEARED; 1330f1c579b1SScott Long arcmsr_post_Qbuffer(pACB); 1331f1c579b1SScott Long } 1332f1c579b1SScott Long pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_OK; 1333f1c579b1SScott Long } 1334f1c579b1SScott Long else 1335f1c579b1SScott Long { 1336f1c579b1SScott Long pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_ERROR; 1337f1c579b1SScott Long } 1338f1c579b1SScott Long splx(s); 1339f1c579b1SScott Long return ARC_IOCTL_SUCCESS; 1340f1c579b1SScott Long } 1341f1c579b1SScott Long break; 1342f1c579b1SScott Long case ARCMSR_IOCTL_CLEAR_RQBUFFER: 1343f1c579b1SScott Long { 1344f1c579b1SScott Long ULONG s; 1345f1c579b1SScott Long PUCHAR pQbuffer=pACB->rqbuffer; 1346f1c579b1SScott Long s=splcam(); 1347f1c579b1SScott Long if(pACB->acb_flags & ACB_F_IOPDATA_OVERFLOW) 1348f1c579b1SScott Long { 1349f1c579b1SScott Long pACB->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 1350f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);/*signature, let IOP331 know data has been readed */ 1351f1c579b1SScott Long } 1352f1c579b1SScott Long pACB->acb_flags |= ACB_F_IOCTL_RQBUFFER_CLEARED; 1353f1c579b1SScott Long pACB->rqbuf_firstindex=0; 1354f1c579b1SScott Long pACB->rqbuf_lastindex=0; 1355f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 1356f1c579b1SScott Long pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_OK; 1357f1c579b1SScott Long splx(s); 1358f1c579b1SScott Long return ARC_IOCTL_SUCCESS; 1359f1c579b1SScott Long } 1360f1c579b1SScott Long break; 1361f1c579b1SScott Long case ARCMSR_IOCTL_CLEAR_WQBUFFER: 1362f1c579b1SScott Long { 1363f1c579b1SScott Long ULONG s; 1364f1c579b1SScott Long PUCHAR pQbuffer=pACB->wqbuffer; 1365f1c579b1SScott Long 1366f1c579b1SScott Long s=splcam(); 1367f1c579b1SScott Long if(pACB->acb_flags & ACB_F_IOPDATA_OVERFLOW) 1368f1c579b1SScott Long { 1369f1c579b1SScott Long pACB->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 1370f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);/*signature, let IOP331 know data has been readed */ 1371f1c579b1SScott Long } 1372f1c579b1SScott Long pACB->acb_flags |= ACB_F_IOCTL_WQBUFFER_CLEARED; 1373f1c579b1SScott Long pACB->wqbuf_firstindex=0; 1374f1c579b1SScott Long pACB->wqbuf_lastindex=0; 1375f1c579b1SScott Long memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); 1376f1c579b1SScott Long pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_OK; 1377f1c579b1SScott Long splx(s); 1378f1c579b1SScott Long return ARC_IOCTL_SUCCESS; 1379f1c579b1SScott Long } 1380f1c579b1SScott Long break; 1381f1c579b1SScott Long case ARCMSR_IOCTL_CLEAR_ALLQBUFFER: 1382f1c579b1SScott Long { 1383f1c579b1SScott Long ULONG s; 1384f1c579b1SScott Long PUCHAR pQbuffer; 1385f1c579b1SScott Long 1386f1c579b1SScott Long s=splcam(); 1387f1c579b1SScott Long if(pACB->acb_flags & ACB_F_IOPDATA_OVERFLOW) 1388f1c579b1SScott Long { 1389f1c579b1SScott Long pACB->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; 1390f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);/*signature, let IOP331 know data has been readed */ 1391f1c579b1SScott Long } 1392f1c579b1SScott Long pACB->acb_flags |= (ACB_F_IOCTL_WQBUFFER_CLEARED|ACB_F_IOCTL_RQBUFFER_CLEARED); 1393f1c579b1SScott Long pACB->rqbuf_firstindex=0; 1394f1c579b1SScott Long pACB->rqbuf_lastindex=0; 1395f1c579b1SScott Long pACB->wqbuf_firstindex=0; 1396f1c579b1SScott Long pACB->wqbuf_lastindex=0; 1397f1c579b1SScott Long pQbuffer=pACB->rqbuffer; 1398f1c579b1SScott Long memset(pQbuffer, 0, sizeof(struct _QBUFFER)); 1399f1c579b1SScott Long pQbuffer=pACB->wqbuffer; 1400f1c579b1SScott Long memset(pQbuffer, 0, sizeof(struct _QBUFFER)); 1401f1c579b1SScott Long pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_OK; 1402f1c579b1SScott Long splx(s); 1403f1c579b1SScott Long return ARC_IOCTL_SUCCESS; 1404f1c579b1SScott Long } 1405f1c579b1SScott Long break; 1406f1c579b1SScott Long case ARCMSR_IOCTL_RETURN_CODE_3F: 1407f1c579b1SScott Long { 1408f1c579b1SScott Long pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_3F; 1409f1c579b1SScott Long return ARC_IOCTL_SUCCESS; 1410f1c579b1SScott Long } 1411f1c579b1SScott Long break; 1412f1c579b1SScott Long case ARCMSR_IOCTL_SAY_HELLO: 1413f1c579b1SScott Long { 1414f1c579b1SScott Long PCMD_IOCTL_FIELD pccbioctlfld=(PCMD_IOCTL_FIELD)arg; 1415f1c579b1SScott Long PCHAR hello_string="Hello! I am ARCMSR"; 1416f1c579b1SScott Long PCHAR puserbuffer=(PUCHAR)pccbioctlfld->ioctldatabuffer; 1417f1c579b1SScott Long 1418f1c579b1SScott Long if(memcpy(puserbuffer,hello_string,(SHORT)strlen(hello_string))) 1419f1c579b1SScott Long { 1420f1c579b1SScott Long pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_ERROR; 1421f1c579b1SScott Long return ENOIOCTL; 1422f1c579b1SScott Long } 1423f1c579b1SScott Long pccbioctl->ReturnCode=ARCMSR_IOCTL_RETURNCODE_OK; 1424f1c579b1SScott Long return ARC_IOCTL_SUCCESS; 1425f1c579b1SScott Long } 1426f1c579b1SScott Long break; 1427f1c579b1SScott Long } 1428f1c579b1SScott Long return EINVAL; 1429f1c579b1SScott Long } 1430f1c579b1SScott Long /* 1431f1c579b1SScott Long ************************************************************************** 1432f1c579b1SScott Long ** 1433f1c579b1SScott Long ************************************************************************** 1434f1c579b1SScott Long */ 1435f1c579b1SScott Long PSRB arcmsr_get_freesrb(PACB pACB) 1436f1c579b1SScott Long { 1437f1c579b1SScott Long PSRB pSRB=NULL; 1438f1c579b1SScott Long ULONG s; 1439f1c579b1SScott Long LONG srb_startindex,srb_doneindex; 1440f1c579b1SScott Long 1441f1c579b1SScott Long #if ARCMSR_DEBUG0 1442f1c579b1SScott Long printf("arcmsr_get_freesrb: srb_startindex=%d srb_doneindex=%d\n",pACB->srb_startindex,pACB->srb_doneindex); 1443f1c579b1SScott Long #endif 1444f1c579b1SScott Long 1445f1c579b1SScott Long s=splcam(); 1446f1c579b1SScott Long srb_doneindex=pACB->srb_doneindex; 1447f1c579b1SScott Long srb_startindex=pACB->srb_startindex; 1448f1c579b1SScott Long pSRB=pACB->psrbringQ[srb_startindex]; 1449f1c579b1SScott Long srb_startindex++; 1450f1c579b1SScott Long srb_startindex %= ARCMSR_MAX_FREESRB_NUM; 1451f1c579b1SScott Long if(srb_doneindex!=srb_startindex) 1452f1c579b1SScott Long { 1453f1c579b1SScott Long pACB->srb_startindex=srb_startindex; 1454f1c579b1SScott Long } 1455f1c579b1SScott Long else 1456f1c579b1SScott Long { 1457f1c579b1SScott Long pSRB=NULL; 1458f1c579b1SScott Long } 1459f1c579b1SScott Long splx(s); 1460f1c579b1SScott Long return(pSRB); 1461f1c579b1SScott Long } 1462f1c579b1SScott Long /* 1463f1c579b1SScott Long ********************************************************************* 1464f1c579b1SScott Long ** 1465f1c579b1SScott Long ** 1466f1c579b1SScott Long ** 1467f1c579b1SScott Long ********************************************************************* 1468f1c579b1SScott Long */ 1469f1c579b1SScott Long static VOID arcmsr_executesrb(VOID *arg,bus_dma_segment_t *dm_segs,LONG nseg,LONG error) 1470f1c579b1SScott Long { 1471f1c579b1SScott Long PSRB pSRB=(PSRB)arg; 1472f1c579b1SScott Long PACB pACB; 1473f1c579b1SScott Long union ccb *pccb; 1474f1c579b1SScott Long 1475f1c579b1SScott Long #if ARCMSR_DEBUG0 1476f1c579b1SScott Long printf("arcmsr_executesrb........................................ \n" ); 1477f1c579b1SScott Long #endif 1478f1c579b1SScott Long 1479f1c579b1SScott Long pccb=pSRB->pccb; 1480f1c579b1SScott Long pACB=(PACB)pSRB->pACB; 1481f1c579b1SScott Long if(error != 0) 1482f1c579b1SScott Long { 1483f1c579b1SScott Long if(error != EFBIG) 1484f1c579b1SScott Long { 1485f1c579b1SScott Long printf("arcmsr_executesrb:%d Unexepected error %x returned from " "bus_dmamap_load\n",pACB->pci_unit,error); 1486f1c579b1SScott Long } 1487f1c579b1SScott Long if(pccb->ccb_h.status == CAM_REQ_INPROG) 1488f1c579b1SScott Long { 1489f1c579b1SScott Long xpt_freeze_devq(pccb->ccb_h.path,/*count*/1); 1490f1c579b1SScott Long pccb->ccb_h.status=CAM_REQ_TOO_BIG|CAM_DEV_QFRZN; 1491f1c579b1SScott Long } 1492f1c579b1SScott Long xpt_done(pccb); 1493f1c579b1SScott Long return; 1494f1c579b1SScott Long } 1495f1c579b1SScott Long arcmsr_build_srb(pSRB,dm_segs,nseg); 1496f1c579b1SScott Long if(pccb->ccb_h.status != CAM_REQ_INPROG) 1497f1c579b1SScott Long { 1498f1c579b1SScott Long if(nseg != 0) 1499f1c579b1SScott Long { 1500f1c579b1SScott Long bus_dmamap_unload(pACB->buffer_dmat,pSRB->dmamap); 1501f1c579b1SScott Long } 1502f1c579b1SScott Long xpt_done(pccb); 1503f1c579b1SScott Long return; 1504f1c579b1SScott Long } 1505f1c579b1SScott Long pccb->ccb_h.status |= CAM_SIM_QUEUED; 1506f1c579b1SScott Long if(pACB->srboutstandingcount < ARCMSR_MAX_OUTSTANDING_CMD) 1507f1c579b1SScott Long { 1508f1c579b1SScott Long /* 1509f1c579b1SScott Long ****************************************************************** 1510f1c579b1SScott Long ** and we can make sure there were no pending srb in this duration 1511f1c579b1SScott Long ****************************************************************** 1512f1c579b1SScott Long */ 1513f1c579b1SScott Long arcmsr_post_srb(pACB,pSRB); 1514f1c579b1SScott Long } 1515f1c579b1SScott Long else 1516f1c579b1SScott Long { 1517f1c579b1SScott Long /* 1518f1c579b1SScott Long ****************************************************************** 1519f1c579b1SScott Long ** Q of srbwaitexec will be post out when any outstanding command complete 1520f1c579b1SScott Long ****************************************************************** 1521f1c579b1SScott Long */ 1522f1c579b1SScott Long arcmsr_queue_wait2go_srb(pACB,pSRB); 1523f1c579b1SScott Long } 1524f1c579b1SScott Long return; 1525f1c579b1SScott Long } 1526f1c579b1SScott Long /* 1527f1c579b1SScott Long ***************************************************************************************** 1528f1c579b1SScott Long ** 1529f1c579b1SScott Long ***************************************************************************************** 1530f1c579b1SScott Long */ 1531f1c579b1SScott Long BOOLEAN arcmsr_seek_cmd2abort(union ccb * pabortccb) 1532f1c579b1SScott Long { 1533f1c579b1SScott Long PSRB pSRB,pfreesrb; 1534f1c579b1SScott Long PACB pACB=(PACB) pabortccb->ccb_h.arcmsr_ccbacb_ptr; 1535f1c579b1SScott Long ULONG s,intmask_org,mask; 1536f1c579b1SScott Long LONG i=0; 1537f1c579b1SScott Long 1538f1c579b1SScott Long #if ARCMSR_DEBUG0 1539f1c579b1SScott Long printf("arcmsr_seek_cmd2abort.................. \n"); 1540f1c579b1SScott Long #endif 1541f1c579b1SScott Long 1542f1c579b1SScott Long s=splcam(); 1543f1c579b1SScott Long /* 1544f1c579b1SScott Long ** It is the upper layer do abort command this lock just prior to calling us. 1545f1c579b1SScott Long ** First determine if we currently own this command. 1546f1c579b1SScott Long ** Start by searching the device queue. If not found 1547f1c579b1SScott Long ** at all,and the system wanted us to just abort the 1548f1c579b1SScott Long ** command return success. 1549f1c579b1SScott Long */ 1550f1c579b1SScott Long if(pACB->srboutstandingcount!=0) 1551f1c579b1SScott Long { 1552f1c579b1SScott Long /* Q back all outstanding srb into wait exec psrb Q*/ 1553f1c579b1SScott Long pfreesrb=pACB->pfreesrb; 1554f1c579b1SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) 1555f1c579b1SScott Long { 1556f1c579b1SScott Long pSRB=&pfreesrb[i]; 1557f1c579b1SScott Long if(pSRB->startdone==ARCMSR_SRB_START) 1558f1c579b1SScott Long { 1559f1c579b1SScott Long if(pSRB->pccb==pabortccb) 1560f1c579b1SScott Long { 1561f1c579b1SScott Long /* disable all outbound interrupt */ 1562f1c579b1SScott Long intmask_org=CHIP_REG_READ32(&pACB->pmu->outbound_intmask); 1563f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->outbound_intmask,intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); 1564f1c579b1SScott Long /* talk to iop 331 outstanding command aborted*/ 1565f1c579b1SScott Long arcmsr_abort_allcmd(pACB); 1566f1c579b1SScott Long if(arcmsr_wait_msgint_ready(pACB)!=TRUE) 1567f1c579b1SScott Long { 1568f1c579b1SScott Long printf("arcmsr_seek_cmd2abort: wait 'abort all outstanding command' timeout.................in \n"); 1569f1c579b1SScott Long } 1570f1c579b1SScott Long /*clear all outbound posted Q*/ 1571f1c579b1SScott Long for(i=0;i<ARCMSR_MAX_OUTSTANDING_CMD;i++) 1572f1c579b1SScott Long { 1573f1c579b1SScott Long CHIP_REG_READ32(&pACB->pmu->outbound_queueport); 1574f1c579b1SScott Long } 1575f1c579b1SScott Long pfreesrb=pACB->pfreesrb; 1576f1c579b1SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) 1577f1c579b1SScott Long { 1578f1c579b1SScott Long pSRB=&pfreesrb[i]; 1579f1c579b1SScott Long if(pSRB->startdone==ARCMSR_SRB_START) 1580f1c579b1SScott Long { 1581f1c579b1SScott Long pSRB->startdone=ARCMSR_SRB_ABORTED; 1582f1c579b1SScott Long pSRB->pccb->ccb_h.status=CAM_REQ_ABORTED; 1583f1c579b1SScott Long arcmsr_srb_complete(pSRB); 1584f1c579b1SScott Long } 1585f1c579b1SScott Long } 1586f1c579b1SScott Long /* enable all outbound interrupt */ 1587f1c579b1SScott Long mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE); 1588f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->outbound_intmask,intmask_org & mask); 1589f1c579b1SScott Long splx(s); 1590f1c579b1SScott Long return(TRUE); 1591f1c579b1SScott Long } 1592f1c579b1SScott Long } 1593f1c579b1SScott Long } 1594f1c579b1SScott Long } 1595f1c579b1SScott Long /* 1596f1c579b1SScott Long ** seek this command at our command list 1597f1c579b1SScott Long ** if command found then remove,abort it and free this SRB 1598f1c579b1SScott Long */ 1599f1c579b1SScott Long if(pACB->srbwait2gocount!=0) 1600f1c579b1SScott Long { 1601f1c579b1SScott Long for(i=0;i<ARCMSR_MAX_OUTSTANDING_CMD;i++) 1602f1c579b1SScott Long { 1603f1c579b1SScott Long pSRB=pACB->psrbwait2go[i]; 1604f1c579b1SScott Long if(pSRB!=NULL) 1605f1c579b1SScott Long { 1606f1c579b1SScott Long if(pSRB->pccb==pabortccb) 1607f1c579b1SScott Long { 1608f1c579b1SScott Long pACB->psrbwait2go[i]=NULL; 1609f1c579b1SScott Long pSRB->startdone=ARCMSR_SRB_ABORTED; 1610f1c579b1SScott Long pSRB->pccb->ccb_h.status=CAM_REQ_ABORTED; 1611f1c579b1SScott Long arcmsr_srb_complete(pSRB); 1612f1c579b1SScott Long atomic_subtract_int(&pACB->srbwait2gocount,1); 1613f1c579b1SScott Long splx(s); 1614f1c579b1SScott Long return(TRUE); 1615f1c579b1SScott Long } 1616f1c579b1SScott Long } 1617f1c579b1SScott Long } 1618f1c579b1SScott Long } 1619f1c579b1SScott Long splx(s); 1620f1c579b1SScott Long return (FALSE); 1621f1c579b1SScott Long } 1622f1c579b1SScott Long /* 1623f1c579b1SScott Long **************************************************************************** 1624f1c579b1SScott Long ** 1625f1c579b1SScott Long **************************************************************************** 1626f1c579b1SScott Long */ 1627f1c579b1SScott Long VOID arcmsr_bus_reset(PACB pACB) 1628f1c579b1SScott Long { 1629f1c579b1SScott Long #if ARCMSR_DEBUG0 1630f1c579b1SScott Long printf("arcmsr_bus_reset.......................... \n"); 1631f1c579b1SScott Long #endif 1632f1c579b1SScott Long 1633f1c579b1SScott Long arcmsr_iop_reset(pACB); 1634f1c579b1SScott Long return; 1635f1c579b1SScott Long } 1636f1c579b1SScott Long /* 1637f1c579b1SScott Long ********************************************************************* 1638f1c579b1SScott Long ** 1639f1c579b1SScott Long ** CAM Status field values 1640f1c579b1SScott Long **typedef enum { 1641f1c579b1SScott Long ** CAM_REQ_INPROG, CCB request is in progress 1642f1c579b1SScott Long ** CAM_REQ_CMP, CCB request completed without error 1643f1c579b1SScott Long ** CAM_REQ_ABORTED, CCB request aborted by the host 1644f1c579b1SScott Long ** CAM_UA_ABORT, Unable to abort CCB request 1645f1c579b1SScott Long ** CAM_REQ_CMP_ERR, CCB request completed with an error 1646f1c579b1SScott Long ** CAM_BUSY, CAM subsytem is busy 1647f1c579b1SScott Long ** CAM_REQ_INVALID, CCB request was invalid 1648f1c579b1SScott Long ** CAM_PATH_INVALID, Supplied Path ID is invalid 1649f1c579b1SScott Long ** CAM_DEV_NOT_THERE, SCSI Device Not Installed/there 1650f1c579b1SScott Long ** CAM_UA_TERMIO, Unable to terminate I/O CCB request 1651f1c579b1SScott Long ** CAM_SEL_TIMEOUT, Target Selection Timeout 1652f1c579b1SScott Long ** CAM_CMD_TIMEOUT, Command timeout 1653f1c579b1SScott Long ** CAM_SCSI_STATUS_ERROR, SCSI error, look at error code in CCB 1654f1c579b1SScott Long ** CAM_MSG_REJECT_REC, Message Reject Received 1655f1c579b1SScott Long ** CAM_SCSI_BUS_RESET, SCSI Bus Reset Sent/Received 1656f1c579b1SScott Long ** CAM_UNCOR_PARITY, Uncorrectable parity error occurred 1657f1c579b1SScott Long ** CAM_AUTOSENSE_FAIL=0x10, Autosense: request sense cmd fail 1658f1c579b1SScott Long ** CAM_NO_HBA, No HBA Detected error 1659f1c579b1SScott Long ** CAM_DATA_RUN_ERR, Data Overrun error 1660f1c579b1SScott Long ** CAM_UNEXP_BUSFREE, Unexpected Bus Free 1661f1c579b1SScott Long ** CAM_SEQUENCE_FAIL, Target Bus Phase Sequence Failure 1662f1c579b1SScott Long ** CAM_CCB_LEN_ERR, CCB length supplied is inadequate 1663f1c579b1SScott Long ** CAM_PROVIDE_FAIL, Unable to provide requested capability 1664f1c579b1SScott Long ** CAM_BDR_SENT, A SCSI BDR msg was sent to target 1665f1c579b1SScott Long ** CAM_REQ_TERMIO, CCB request terminated by the host 1666f1c579b1SScott Long ** CAM_UNREC_HBA_ERROR, Unrecoverable Host Bus Adapter Error 1667f1c579b1SScott Long ** CAM_REQ_TOO_BIG, The request was too large for this host 1668f1c579b1SScott Long ** CAM_REQUEUE_REQ, 1669f1c579b1SScott Long ** * This request should be requeued to preserve 1670f1c579b1SScott Long ** * transaction ordering. This typically occurs 1671f1c579b1SScott Long ** * when the SIM recognizes an error that should 1672f1c579b1SScott Long ** * freeze the queue and must place additional 1673f1c579b1SScott Long ** * requests for the target at the sim level 1674f1c579b1SScott Long ** * back into the XPT queue. 1675f1c579b1SScott Long ** 1676f1c579b1SScott Long ** CAM_IDE=0x33, Initiator Detected Error 1677f1c579b1SScott Long ** CAM_RESRC_UNAVAIL, Resource Unavailable 1678f1c579b1SScott Long ** CAM_UNACKED_EVENT, Unacknowledged Event by Host 1679f1c579b1SScott Long ** CAM_MESSAGE_RECV, Message Received in Host Target Mode 1680f1c579b1SScott Long ** CAM_INVALID_CDB, Invalid CDB received in Host Target Mode 1681f1c579b1SScott Long ** CAM_LUN_INVALID, Lun supplied is invalid 1682f1c579b1SScott Long ** CAM_TID_INVALID, Target ID supplied is invalid 1683f1c579b1SScott Long ** CAM_FUNC_NOTAVAIL, The requested function is not available 1684f1c579b1SScott Long ** CAM_NO_NEXUS, Nexus is not established 1685f1c579b1SScott Long ** CAM_IID_INVALID, The initiator ID is invalid 1686f1c579b1SScott Long ** CAM_CDB_RECVD, The SCSI CDB has been received 1687f1c579b1SScott Long ** CAM_LUN_ALRDY_ENA, The LUN is already eanbeld for target mode 1688f1c579b1SScott Long ** CAM_SCSI_BUSY, SCSI Bus Busy 1689f1c579b1SScott Long ** 1690f1c579b1SScott Long ** CAM_DEV_QFRZN=0x40, The DEV queue is frozen w/this err 1691f1c579b1SScott Long ** 1692f1c579b1SScott Long ** Autosense data valid for target 1693f1c579b1SScott Long ** CAM_AUTOSNS_VALID=0x80, 1694f1c579b1SScott Long ** CAM_RELEASE_SIMQ=0x100, SIM ready to take more commands 1695f1c579b1SScott Long ** CAM_SIM_QUEUED =0x200, SIM has this command in it's queue 1696f1c579b1SScott Long ** 1697f1c579b1SScott Long ** CAM_STATUS_MASK=0x3F, Mask bits for just the status # 1698f1c579b1SScott Long ** 1699f1c579b1SScott Long ** Target Specific Adjunct Status 1700f1c579b1SScott Long ** CAM_SENT_SENSE=0x40000000 sent sense with status 1701f1c579b1SScott Long **} cam_status; 1702f1c579b1SScott Long ** 1703f1c579b1SScott Long **union ccb { 1704f1c579b1SScott Long ** struct ccb_hdr ccb_h; For convenience 1705f1c579b1SScott Long ** struct ccb_scsiio csio; 1706f1c579b1SScott Long ** struct ccb_getdev cgd; 1707f1c579b1SScott Long ** struct ccb_getdevlist cgdl; 1708f1c579b1SScott Long ** struct ccb_pathinq cpi; 1709f1c579b1SScott Long ** struct ccb_relsim crs; 1710f1c579b1SScott Long ** struct ccb_setasync csa; 1711f1c579b1SScott Long ** struct ccb_setdev csd; 1712f1c579b1SScott Long ** struct ccb_pathstats cpis; 1713f1c579b1SScott Long ** struct ccb_getdevstats cgds; 1714f1c579b1SScott Long ** struct ccb_dev_match cdm; 1715f1c579b1SScott Long ** struct ccb_trans_settings cts; 1716f1c579b1SScott Long ** struct ccb_calc_geometry ccg; 1717f1c579b1SScott Long ** struct ccb_abort cab; 1718f1c579b1SScott Long ** struct ccb_resetbus crb; 1719f1c579b1SScott Long ** struct ccb_resetdev crd; 1720f1c579b1SScott Long ** struct ccb_termio tio; 1721f1c579b1SScott Long ** struct ccb_accept_tio atio; 1722f1c579b1SScott Long ** struct ccb_scsiio ctio; 1723f1c579b1SScott Long ** struct ccb_en_lun cel; 1724f1c579b1SScott Long ** struct ccb_immed_notify cin; 1725f1c579b1SScott Long ** struct ccb_notify_ack cna; 1726f1c579b1SScott Long ** struct ccb_eng_inq cei; 1727f1c579b1SScott Long ** struct ccb_eng_exec cee; 1728f1c579b1SScott Long ** struct ccb_rescan crcn; 1729f1c579b1SScott Long ** struct ccb_debug cdbg; 1730f1c579b1SScott Long ** } 1731f1c579b1SScott Long ** 1732f1c579b1SScott Long **struct ccb_hdr { 1733f1c579b1SScott Long ** cam_pinfo pinfo; "" Info for priority scheduling 1734f1c579b1SScott Long ** camq_entry xpt_links; "" For chaining in the XPT layer 1735f1c579b1SScott Long ** camq_entry sim_links; "" For chaining in the SIM layer 1736f1c579b1SScott Long ** camq_entry periph_links; "" For chaining in the type driver 1737f1c579b1SScott Long ** u_int32_t retry_count; 1738f1c579b1SScott Long ** void (*cbfcnp)(struct cam_periph *, union ccb *);"" Callback on completion function 1739f1c579b1SScott Long ** xpt_opcode func_code; "" XPT function code 1740f1c579b1SScott Long ** u_int32_t status; "" Status returned by CAM subsystem 1741f1c579b1SScott Long ** struct cam_path *path; "" Compiled path for this ccb 1742f1c579b1SScott Long ** path_id_t path_id; "" Path ID for the request 1743f1c579b1SScott Long ** target_id_t target_id; "" Target device ID 1744f1c579b1SScott Long ** lun_id_t target_lun; "" Target LUN number 1745f1c579b1SScott Long ** u_int32_t flags; 1746f1c579b1SScott Long ** ccb_ppriv_area periph_priv; 1747f1c579b1SScott Long ** ccb_spriv_area sim_priv; 1748f1c579b1SScott Long ** u_int32_t timeout; "" Timeout value 1749f1c579b1SScott Long ** struct callout_handle timeout_ch; "" Callout handle used for timeouts 1750f1c579b1SScott Long **}; 1751f1c579b1SScott Long ** 1752f1c579b1SScott Long **typedef union { 1753f1c579b1SScott Long ** u_int8_t *cdb_ptr; "" Pointer to the CDB bytes to send 1754f1c579b1SScott Long ** u_int8_t cdb_bytes[IOCDBLEN]; "" Area for the CDB send 1755f1c579b1SScott Long **} cdb_t; 1756f1c579b1SScott Long ** 1757f1c579b1SScott Long ** SCSI I/O Request CCB used for the XPT_SCSI_IO and XPT_CONT_TARGET_IO 1758f1c579b1SScott Long ** function codes. 1759f1c579b1SScott Long ** 1760f1c579b1SScott Long **struct ccb_scsiio { 1761f1c579b1SScott Long ** struct ccb_hdr ccb_h; 1762f1c579b1SScott Long ** union ccb *next_ccb; "" Ptr for next CCB for action 1763f1c579b1SScott Long ** u_int8_t *req_map; "" Ptr to mapping info 1764f1c579b1SScott Long ** u_int8_t *data_ptr; "" Ptr to the data buf/SG list 1765f1c579b1SScott Long ** u_int32_t dxfer_len; "" Data transfer length 1766f1c579b1SScott Long ** struct scsi_sense_data sense_data; "" Autosense storage 1767f1c579b1SScott Long ** u_int8_t sense_len; "" Number of bytes to autosense 1768f1c579b1SScott Long ** u_int8_t cdb_len; "" Number of bytes for the CDB 1769f1c579b1SScott Long ** u_int16_t sglist_cnt; "" Number of SG list entries 1770f1c579b1SScott Long ** u_int8_t scsi_status; "" Returned SCSI status 1771f1c579b1SScott Long ** u_int8_t sense_resid; "" Autosense resid length: 2's comp 1772f1c579b1SScott Long ** u_int32_t resid; "" Transfer residual length: 2's comp 1773f1c579b1SScott Long ** cdb_t cdb_io; "" Union for CDB bytes/pointer 1774f1c579b1SScott Long ** u_int8_t *msg_ptr; "" Pointer to the message buffer 1775f1c579b1SScott Long ** u_int16_t msg_len; "" Number of bytes for the Message 1776f1c579b1SScott Long ** u_int8_t tag_action; "" What to do for tag queueing 1777f1c579b1SScott Long **#define CAM_TAG_ACTION_NONE 0x00 "" The tag action should be either the define below (to send a non-tagged transaction) or one of the defined scsi tag messages from scsi_message.h. 1778f1c579b1SScott Long ** u_int tag_id; "" tag id from initator (target mode) 1779f1c579b1SScott Long ** u_int init_id; "" initiator id of who selected 1780f1c579b1SScott Long **} 1781f1c579b1SScott Long ********************************************************************* 1782f1c579b1SScott Long */ 1783f1c579b1SScott Long static VOID arcmsr_action(struct cam_sim * psim,union ccb * pccb) 1784f1c579b1SScott Long { 1785f1c579b1SScott Long PACB pACB; 1786f1c579b1SScott Long 1787f1c579b1SScott Long #if ARCMSR_DEBUG0 1788f1c579b1SScott Long printf("arcmsr_action ..................................\n" ); 1789f1c579b1SScott Long #endif 1790f1c579b1SScott Long 1791f1c579b1SScott Long pACB=(PACB) cam_sim_softc(psim); 1792f1c579b1SScott Long if(pACB==NULL) 1793f1c579b1SScott Long { 1794f1c579b1SScott Long pccb->ccb_h.status=CAM_REQ_INVALID; 1795f1c579b1SScott Long xpt_done(pccb); 1796f1c579b1SScott Long return; 1797f1c579b1SScott Long } 1798f1c579b1SScott Long switch (pccb->ccb_h.func_code) 1799f1c579b1SScott Long { 1800f1c579b1SScott Long case XPT_SCSI_IO: 1801f1c579b1SScott Long { 1802f1c579b1SScott Long PSRB pSRB; 1803f1c579b1SScott Long #if ARCMSR_DEBUG0 1804f1c579b1SScott Long printf("arcmsr_action: XPT_SCSI_IO......................\n" ); 1805f1c579b1SScott Long #endif 1806f1c579b1SScott Long 1807f1c579b1SScott Long if((pSRB=arcmsr_get_freesrb(pACB)) == NULL) 1808f1c579b1SScott Long { 1809f1c579b1SScott Long pccb->ccb_h.status=CAM_RESRC_UNAVAIL; 1810f1c579b1SScott Long xpt_done(pccb); 1811f1c579b1SScott Long return; 1812f1c579b1SScott Long } 1813f1c579b1SScott Long pccb->ccb_h.arcmsr_ccbsrb_ptr=pSRB; 1814f1c579b1SScott Long pccb->ccb_h.arcmsr_ccbacb_ptr=pACB; 1815f1c579b1SScott Long pSRB->pccb=pccb; 1816f1c579b1SScott Long if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) 1817f1c579b1SScott Long { 1818f1c579b1SScott Long if((pccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) 1819f1c579b1SScott Long { 1820f1c579b1SScott Long if((pccb->ccb_h.flags & CAM_DATA_PHYS) == 0) 1821f1c579b1SScott Long { 1822f1c579b1SScott Long LONG error,s; 1823f1c579b1SScott Long 1824f1c579b1SScott Long s=splsoftvm(); 1825f1c579b1SScott Long error = bus_dmamap_load(pACB->buffer_dmat,pSRB->dmamap,pccb->csio.data_ptr,pccb->csio.dxfer_len,arcmsr_executesrb,pSRB,/*flags*/0); 1826f1c579b1SScott Long if(error == EINPROGRESS) 1827f1c579b1SScott Long { 1828f1c579b1SScott Long xpt_freeze_simq(pACB->psim,1); 1829f1c579b1SScott Long pccb->ccb_h.status |= CAM_RELEASE_SIMQ; 1830f1c579b1SScott Long } 1831f1c579b1SScott Long splx(s); 1832f1c579b1SScott Long } 1833f1c579b1SScott Long else 1834f1c579b1SScott Long { 1835f1c579b1SScott Long struct bus_dma_segment seg; 1836f1c579b1SScott Long 1837f1c579b1SScott Long seg.ds_addr=(bus_addr_t)pccb->csio.data_ptr; 1838f1c579b1SScott Long seg.ds_len=pccb->csio.dxfer_len; 1839f1c579b1SScott Long arcmsr_executesrb(pSRB,&seg,1,0); 1840f1c579b1SScott Long } 1841f1c579b1SScott Long } 1842f1c579b1SScott Long else 1843f1c579b1SScott Long { 1844f1c579b1SScott Long struct bus_dma_segment *segs; 1845f1c579b1SScott Long 1846f1c579b1SScott Long if((pccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0 || (pccb->ccb_h.flags & CAM_DATA_PHYS) != 0) 1847f1c579b1SScott Long { 1848f1c579b1SScott Long pccb->ccb_h.status=CAM_PROVIDE_FAIL; 1849f1c579b1SScott Long xpt_done(pccb); 1850f1c579b1SScott Long free(pSRB,M_DEVBUF); 1851f1c579b1SScott Long return; 1852f1c579b1SScott Long } 1853f1c579b1SScott Long segs=(struct bus_dma_segment *)pccb->csio.data_ptr; 1854f1c579b1SScott Long arcmsr_executesrb(pSRB,segs,pccb->csio.sglist_cnt,0); 1855f1c579b1SScott Long } 1856f1c579b1SScott Long } 1857f1c579b1SScott Long else 1858f1c579b1SScott Long { 1859f1c579b1SScott Long arcmsr_executesrb(pSRB,NULL,0,0); 1860f1c579b1SScott Long } 1861f1c579b1SScott Long break; 1862f1c579b1SScott Long } 1863f1c579b1SScott Long case XPT_TARGET_IO: 1864f1c579b1SScott Long { 1865f1c579b1SScott Long #if ARCMSR_DEBUG0 1866f1c579b1SScott Long printf("arcmsr_action: XPT_TARGET_IO\n" ); 1867f1c579b1SScott Long #endif 1868f1c579b1SScott Long /* 1869f1c579b1SScott Long ** target mode not yet support vendor specific commands. 1870f1c579b1SScott Long */ 1871f1c579b1SScott Long pccb->ccb_h.status=CAM_REQ_CMP; 1872f1c579b1SScott Long xpt_done(pccb); 1873f1c579b1SScott Long break; 1874f1c579b1SScott Long } 1875f1c579b1SScott Long case XPT_PATH_INQ: 1876f1c579b1SScott Long { 1877f1c579b1SScott Long struct ccb_pathinq *cpi=&pccb->cpi; 1878f1c579b1SScott Long 1879f1c579b1SScott Long #if ARCMSR_DEBUG0 1880f1c579b1SScott Long printf("arcmsr_action: XPT_PATH_INQ\n" ); 1881f1c579b1SScott Long #endif 1882f1c579b1SScott Long cpi->version_num=1; 1883f1c579b1SScott Long cpi->hba_inquiry=PI_SDTR_ABLE | PI_TAG_ABLE; 1884f1c579b1SScott Long cpi->target_sprt=0; 1885f1c579b1SScott Long cpi->hba_misc=0; 1886f1c579b1SScott Long cpi->hba_eng_cnt=0; 1887f1c579b1SScott Long cpi->max_target=ARCMSR_MAX_TARGETID; 1888f1c579b1SScott Long cpi->max_lun=ARCMSR_MAX_TARGETLUN; /* 7 or 0 */ 1889f1c579b1SScott Long cpi->initiator_id=ARCMSR_SCSI_INITIATOR_ID; 1890f1c579b1SScott Long cpi->bus_id=cam_sim_bus(psim); 1891f1c579b1SScott Long strncpy(cpi->sim_vid,"FreeBSD",SIM_IDLEN); 1892f1c579b1SScott Long strncpy(cpi->hba_vid,"ARCMSR",HBA_IDLEN); 1893f1c579b1SScott Long strncpy(cpi->dev_name,cam_sim_name(psim),DEV_IDLEN); 1894f1c579b1SScott Long cpi->unit_number=cam_sim_unit(psim); 1895f1c579b1SScott Long cpi->ccb_h.status=CAM_REQ_CMP; 1896f1c579b1SScott Long xpt_done(pccb); 1897f1c579b1SScott Long break; 1898f1c579b1SScott Long } 1899f1c579b1SScott Long case XPT_ABORT: 1900f1c579b1SScott Long { 1901f1c579b1SScott Long union ccb *pabort_ccb; 1902f1c579b1SScott Long 1903f1c579b1SScott Long #if ARCMSR_DEBUG0 1904f1c579b1SScott Long printf("arcmsr_action: XPT_ABORT\n" ); 1905f1c579b1SScott Long #endif 1906f1c579b1SScott Long pabort_ccb=pccb->cab.abort_ccb; 1907f1c579b1SScott Long switch (pabort_ccb->ccb_h.func_code) 1908f1c579b1SScott Long { 1909f1c579b1SScott Long case XPT_ACCEPT_TARGET_IO: 1910f1c579b1SScott Long case XPT_IMMED_NOTIFY: 1911f1c579b1SScott Long case XPT_CONT_TARGET_IO: 1912f1c579b1SScott Long if(arcmsr_seek_cmd2abort(pabort_ccb)==TRUE) 1913f1c579b1SScott Long { 1914f1c579b1SScott Long pabort_ccb->ccb_h.status=CAM_REQ_ABORTED; 1915f1c579b1SScott Long xpt_done(pabort_ccb); 1916f1c579b1SScott Long pccb->ccb_h.status=CAM_REQ_CMP; 1917f1c579b1SScott Long } 1918f1c579b1SScott Long else 1919f1c579b1SScott Long { 1920f1c579b1SScott Long xpt_print_path(pabort_ccb->ccb_h.path); 1921f1c579b1SScott Long printf("Not found\n"); 1922f1c579b1SScott Long pccb->ccb_h.status=CAM_PATH_INVALID; 1923f1c579b1SScott Long } 1924f1c579b1SScott Long break; 1925f1c579b1SScott Long case XPT_SCSI_IO: 1926f1c579b1SScott Long pccb->ccb_h.status=CAM_UA_ABORT; 1927f1c579b1SScott Long break; 1928f1c579b1SScott Long default: 1929f1c579b1SScott Long pccb->ccb_h.status=CAM_REQ_INVALID; 1930f1c579b1SScott Long break; 1931f1c579b1SScott Long } 1932f1c579b1SScott Long xpt_done(pccb); 1933f1c579b1SScott Long break; 1934f1c579b1SScott Long } 1935f1c579b1SScott Long case XPT_RESET_BUS: 1936f1c579b1SScott Long case XPT_RESET_DEV: 1937f1c579b1SScott Long { 1938f1c579b1SScott Long LONG i; 1939f1c579b1SScott Long 1940f1c579b1SScott Long #if ARCMSR_DEBUG0 1941f1c579b1SScott Long printf("arcmsr_action: XPT_RESET_BUS\n" ); 1942f1c579b1SScott Long #endif 1943f1c579b1SScott Long arcmsr_bus_reset(pACB); 1944f1c579b1SScott Long for (i=0; i < 500; i++) 1945f1c579b1SScott Long { 1946f1c579b1SScott Long DELAY(1000); 1947f1c579b1SScott Long } 1948f1c579b1SScott Long pccb->ccb_h.status=CAM_REQ_CMP; 1949f1c579b1SScott Long xpt_done(pccb); 1950f1c579b1SScott Long break; 1951f1c579b1SScott Long } 1952f1c579b1SScott Long case XPT_TERM_IO: 1953f1c579b1SScott Long { 1954f1c579b1SScott Long #if ARCMSR_DEBUG0 1955f1c579b1SScott Long printf("arcmsr_action: XPT_TERM_IO\n" ); 1956f1c579b1SScott Long #endif 1957f1c579b1SScott Long pccb->ccb_h.status=CAM_REQ_INVALID; 1958f1c579b1SScott Long xpt_done(pccb); 1959f1c579b1SScott Long break; 1960f1c579b1SScott Long } 1961f1c579b1SScott Long case XPT_GET_TRAN_SETTINGS: 1962f1c579b1SScott Long { 1963f1c579b1SScott Long struct ccb_trans_settings *cts; 1964f1c579b1SScott Long ULONG s; 1965f1c579b1SScott Long 1966f1c579b1SScott Long #if ARCMSR_DEBUG0 1967f1c579b1SScott Long printf("arcmsr_action: XPT_GET_TRAN_SETTINGS\n" ); 1968f1c579b1SScott Long #endif 1969f1c579b1SScott Long 1970f1c579b1SScott Long cts=&pccb->cts; 1971f1c579b1SScott Long s=splcam(); 1972f1c579b1SScott Long cts->flags=(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB); 1973f1c579b1SScott Long cts->sync_period=3; 1974f1c579b1SScott Long cts->sync_offset=32; 1975f1c579b1SScott Long cts->bus_width=MSG_EXT_WDTR_BUS_16_BIT; 1976f1c579b1SScott Long cts->valid=CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID | CCB_TRANS_BUS_WIDTH_VALID | CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID; 1977f1c579b1SScott Long splx(s); 1978f1c579b1SScott Long pccb->ccb_h.status=CAM_REQ_CMP; 1979f1c579b1SScott Long xpt_done(pccb); 1980f1c579b1SScott Long break; 1981f1c579b1SScott Long } 1982f1c579b1SScott Long case XPT_SET_TRAN_SETTINGS: 1983f1c579b1SScott Long { 1984f1c579b1SScott Long #if ARCMSR_DEBUG0 1985f1c579b1SScott Long printf("arcmsr_action: XPT_SET_TRAN_SETTINGS\n" ); 1986f1c579b1SScott Long #endif 1987f1c579b1SScott Long pccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 1988f1c579b1SScott Long xpt_done(pccb); 1989f1c579b1SScott Long break; 1990f1c579b1SScott Long } 1991f1c579b1SScott Long case XPT_CALC_GEOMETRY: 1992f1c579b1SScott Long { 1993f1c579b1SScott Long struct ccb_calc_geometry *ccg; 1994f1c579b1SScott Long ULONG size_mb; 1995f1c579b1SScott Long ULONG secs_per_cylinder; 1996f1c579b1SScott Long 1997f1c579b1SScott Long #if ARCMSR_DEBUG0 1998f1c579b1SScott Long printf("arcmsr_action: XPT_CALC_GEOMETRY\n" ); 1999f1c579b1SScott Long #endif 2000f1c579b1SScott Long ccg=&pccb->ccg; 2001f1c579b1SScott Long size_mb=ccg->volume_size/((1024L * 1024L)/ccg->block_size); 2002f1c579b1SScott Long if(size_mb > 1024 ) 2003f1c579b1SScott Long { 2004f1c579b1SScott Long ccg->heads=255; 2005f1c579b1SScott Long ccg->secs_per_track=63; 2006f1c579b1SScott Long } 2007f1c579b1SScott Long else 2008f1c579b1SScott Long { 2009f1c579b1SScott Long ccg->heads=64; 2010f1c579b1SScott Long ccg->secs_per_track=32; 2011f1c579b1SScott Long } 2012f1c579b1SScott Long secs_per_cylinder=ccg->heads * ccg->secs_per_track; 2013f1c579b1SScott Long ccg->cylinders=ccg->volume_size / secs_per_cylinder; 2014f1c579b1SScott Long pccb->ccb_h.status=CAM_REQ_CMP; 2015f1c579b1SScott Long xpt_done(pccb); 2016f1c579b1SScott Long break; 2017f1c579b1SScott Long } 2018f1c579b1SScott Long default: 2019f1c579b1SScott Long #if ARCMSR_DEBUG0 2020f1c579b1SScott Long printf("arcmsr_action: invalid XPT function CAM_REQ_INVALID\n" ); 2021f1c579b1SScott Long #endif 2022f1c579b1SScott Long pccb->ccb_h.status=CAM_REQ_INVALID; 2023f1c579b1SScott Long xpt_done(pccb); 2024f1c579b1SScott Long break; 2025f1c579b1SScott Long } 2026f1c579b1SScott Long return; 2027f1c579b1SScott Long } 2028f1c579b1SScott Long /* 2029f1c579b1SScott Long ********************************************************************** 2030f1c579b1SScott Long ** 2031f1c579b1SScott Long ** start background rebulid 2032f1c579b1SScott Long ** 2033f1c579b1SScott Long ********************************************************************** 2034f1c579b1SScott Long */ 2035f1c579b1SScott Long VOID arcmsr_start_adapter_bgrb(PACB pACB) 2036f1c579b1SScott Long { 2037f1c579b1SScott Long #if ARCMSR_DEBUG0 2038f1c579b1SScott Long printf("arcmsr_start_adapter_bgrb.................................. \n"); 2039f1c579b1SScott Long #endif 2040f1c579b1SScott Long pACB->acb_flags |= ACB_F_MSG_START_BGRB; 2041f1c579b1SScott Long pACB->acb_flags &= ~ACB_F_MSG_STOP_BGRB; 2042f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->inbound_msgaddr0,ARCMSR_INBOUND_MESG0_START_BGRB); 2043f1c579b1SScott Long return; 2044f1c579b1SScott Long } 2045f1c579b1SScott Long /* 2046f1c579b1SScott Long ********************************************************************** 2047f1c579b1SScott Long ** 2048f1c579b1SScott Long ** start background rebulid 2049f1c579b1SScott Long ** 2050f1c579b1SScott Long ********************************************************************** 2051f1c579b1SScott Long */ 2052f1c579b1SScott Long VOID arcmsr_iop_init(PACB pACB) 2053f1c579b1SScott Long { 2054f1c579b1SScott Long ULONG intmask_org,mask,outbound_doorbell,firmware_state=0; 2055f1c579b1SScott Long 2056f1c579b1SScott Long #if ARCMSR_DEBUG0 2057f1c579b1SScott Long printf("arcmsr_iop_init.................................. \n"); 2058f1c579b1SScott Long #endif 2059f1c579b1SScott Long do 2060f1c579b1SScott Long { 2061f1c579b1SScott Long firmware_state=CHIP_REG_READ32(&pACB->pmu->outbound_msgaddr1); 2062f1c579b1SScott Long }while((firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK)==0); 2063f1c579b1SScott Long /* disable all outbound interrupt */ 2064f1c579b1SScott Long intmask_org=CHIP_REG_READ32(&pACB->pmu->outbound_intmask); 2065f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->outbound_intmask,intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE); 2066f1c579b1SScott Long /*start background rebuild*/ 2067f1c579b1SScott Long arcmsr_start_adapter_bgrb(pACB); 2068f1c579b1SScott Long if(arcmsr_wait_msgint_ready(pACB)!=TRUE) 2069f1c579b1SScott Long { 2070f1c579b1SScott Long printf("arcmsr_HwInitialize: wait 'start adapter background rebulid' timeout................. \n"); 2071f1c579b1SScott Long } 2072f1c579b1SScott Long /* clear Qbuffer if door bell ringed */ 2073f1c579b1SScott Long outbound_doorbell=CHIP_REG_READ32(&pACB->pmu->outbound_doorbell); 2074f1c579b1SScott Long if(outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) 2075f1c579b1SScott Long { 2076f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->outbound_doorbell,outbound_doorbell);/*clear interrupt */ 2077f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->inbound_doorbell,ARCMSR_INBOUND_DRIVER_DATA_READ_OK); 2078f1c579b1SScott Long } 2079f1c579b1SScott Long /* enable outbound Post Queue,outbound message0,outbell doorbell Interrupt */ 2080f1c579b1SScott Long mask=~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE); 2081f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->outbound_intmask,intmask_org & mask); 2082f1c579b1SScott Long pACB->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; 2083f1c579b1SScott Long pACB->acb_flags |=ACB_F_IOP_INITED; 2084f1c579b1SScott Long return; 2085f1c579b1SScott Long } 2086f1c579b1SScott Long /* 2087f1c579b1SScott Long ********************************************************************** 2088f1c579b1SScott Long ** 2089f1c579b1SScott Long ** map freesrb 2090f1c579b1SScott Long ** 2091f1c579b1SScott Long ********************************************************************** 2092f1c579b1SScott Long */ 2093f1c579b1SScott Long static void arcmsr_map_freesrb(void *arg, bus_dma_segment_t *segs, int nseg, int error) 2094f1c579b1SScott Long { 2095f1c579b1SScott Long PACB pACB=arg; 2096f1c579b1SScott Long PSRB psrb_tmp,pfreesrb; 2097f1c579b1SScott Long ULONG cdb_phyaddr; 2098f1c579b1SScott Long LONG i; 2099f1c579b1SScott Long 2100f1c579b1SScott Long pfreesrb=(PSRB)pACB->uncacheptr; 2101f1c579b1SScott Long cdb_phyaddr=segs->ds_addr; /* We suppose bus_addr_t high part always 0 here*/ 2102f1c579b1SScott Long if(((CPT2INT)pACB->uncacheptr & 0x1F)!=0) 2103f1c579b1SScott Long { 2104f1c579b1SScott Long pfreesrb=pfreesrb+(0x20-((CPT2INT)pfreesrb & 0x1F)); 2105f1c579b1SScott Long cdb_phyaddr=cdb_phyaddr+(0x20-((CPT2INT)cdb_phyaddr & 0x1F)); 2106f1c579b1SScott Long } 2107f1c579b1SScott Long /* 2108f1c579b1SScott Long ******************************************************************** 2109f1c579b1SScott Long ** here we need to tell iop 331 our freesrb.HighPart 2110f1c579b1SScott Long ** if freesrb.HighPart is not zero 2111f1c579b1SScott Long ******************************************************************** 2112f1c579b1SScott Long */ 2113f1c579b1SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) 2114f1c579b1SScott Long { 2115f1c579b1SScott Long psrb_tmp=&pfreesrb[i]; 2116f1c579b1SScott Long if(((CPT2INT)psrb_tmp & 0x1F)==0) /*srb address must 32 (0x20) boundary*/ 2117f1c579b1SScott Long { 2118f1c579b1SScott Long if(bus_dmamap_create(pACB->buffer_dmat, /*flags*/0, &psrb_tmp->dmamap)!=0) 2119f1c579b1SScott Long { 2120f1c579b1SScott Long pACB->acb_flags |= ACB_F_MAPFREESRB_FAILD; 2121f1c579b1SScott Long printf(" arcmsr_map_freesrb: (pSRB->dmamap) bus_dmamap_create ..............error\n"); 2122f1c579b1SScott Long return; 2123f1c579b1SScott Long } 2124f1c579b1SScott Long psrb_tmp->cdb_shifted_phyaddr=cdb_phyaddr >> 5; 2125f1c579b1SScott Long psrb_tmp->pACB=pACB; 2126f1c579b1SScott Long pACB->psrbringQ[i]=psrb_tmp; 2127f1c579b1SScott Long cdb_phyaddr=cdb_phyaddr+sizeof(struct _SRB); 2128f1c579b1SScott Long } 2129f1c579b1SScott Long else 2130f1c579b1SScott Long { 2131f1c579b1SScott Long pACB->acb_flags |= ACB_F_MAPFREESRB_FAILD; 2132f1c579b1SScott Long printf(" arcmsr_map_freesrb:pfreesrb=%p i=%d this srb cross 32 bytes boundary ignored ......psrb_tmp=%p \n",pfreesrb,i,psrb_tmp); 2133f1c579b1SScott Long return; 2134f1c579b1SScott Long } 2135f1c579b1SScott Long } 2136f1c579b1SScott Long pACB->pfreesrb=pfreesrb; 2137f1c579b1SScott Long pACB->vir2phy_offset=(CPT2INT)psrb_tmp-(cdb_phyaddr-sizeof(struct _SRB)); 2138f1c579b1SScott Long return; 2139f1c579b1SScott Long } 2140f1c579b1SScott Long /* 2141f1c579b1SScott Long ************************************************************************ 2142f1c579b1SScott Long ** 2143f1c579b1SScott Long ** 2144f1c579b1SScott Long ************************************************************************ 2145f1c579b1SScott Long */ 2146f1c579b1SScott Long VOID arcmsr_free_resource(PACB pACB) 2147f1c579b1SScott Long { 2148f1c579b1SScott Long /* remove the control device */ 2149f1c579b1SScott Long if (pACB->ioctl_dev != NULL) 2150f1c579b1SScott Long { 2151f1c579b1SScott Long destroy_dev(pACB->ioctl_dev); 2152f1c579b1SScott Long } 2153f1c579b1SScott Long bus_dmamap_unload(pACB->srb_dmat, pACB->srb_dmamap); 2154f1c579b1SScott Long bus_dmamap_destroy(pACB->srb_dmat, pACB->srb_dmamap); 2155f1c579b1SScott Long bus_dma_tag_destroy(pACB->srb_dmat); 2156f1c579b1SScott Long bus_dma_tag_destroy(pACB->buffer_dmat); 2157f1c579b1SScott Long bus_dma_tag_destroy(pACB->parent_dmat); 2158f1c579b1SScott Long return; 2159f1c579b1SScott Long } 2160f1c579b1SScott Long /* 2161f1c579b1SScott Long ************************************************************************ 2162f1c579b1SScott Long ** PCI config header registers for all devices 2163f1c579b1SScott Long ** 2164f1c579b1SScott Long ** #define PCIR_COMMAND 0x04 2165f1c579b1SScott Long ** #define PCIM_CMD_PORTEN 0x0001 2166f1c579b1SScott Long ** #define PCIM_CMD_MEMEN 0x0002 2167f1c579b1SScott Long ** #define PCIM_CMD_BUSMASTEREN 0x0004 2168f1c579b1SScott Long ** #define PCIM_CMD_MWRICEN 0x0010 2169f1c579b1SScott Long ** #define PCIM_CMD_PERRESPEN 0x0040 2170f1c579b1SScott Long ** 2171f1c579b1SScott Long ** Function : arcmsr_initialize 2172f1c579b1SScott Long ** Purpose : initialize the internal structures for a given SCSI host 2173f1c579b1SScott Long ** Inputs : host - pointer to this host adapter's structure 2174f1c579b1SScott Long ** Preconditions : when this function is called,the chip_type 2175f1c579b1SScott Long ** field of the pACB structure MUST have been set. 2176f1c579b1SScott Long ** 2177f1c579b1SScott Long ** 10h Base Address register #0 2178f1c579b1SScott Long ** 14h Base Address register #1 2179f1c579b1SScott Long ** 18h Base Address register #2 2180f1c579b1SScott Long ** 1Ch Base Address register #3 2181f1c579b1SScott Long ** 20h Base Address register #4 2182f1c579b1SScott Long ** 24h Base Address register #5 2183f1c579b1SScott Long ************************************************************************ 2184f1c579b1SScott Long */ 2185f1c579b1SScott Long static LONG arcmsr_initialize(device_t dev) 2186f1c579b1SScott Long { 2187f1c579b1SScott Long PACB pACB=device_get_softc(dev); 2188f1c579b1SScott Long LONG rid=PCI_BASE_ADDR0; 2189f1c579b1SScott Long vm_offset_t mem_base; 2190f1c579b1SScott Long USHORT pci_command; 2191f1c579b1SScott Long 2192f1c579b1SScott Long #if ARCMSR_DEBUG0 2193f1c579b1SScott Long printf("arcmsr_initialize..............................\n"); 2194f1c579b1SScott Long #endif 2195f1c579b1SScott Long #if __FreeBSD_version >= 502010 2196f1c579b1SScott Long if (bus_dma_tag_create( /*parent*/NULL, 2197f1c579b1SScott Long /*alignemnt*/1, 2198f1c579b1SScott Long /*boundary*/0, 2199f1c579b1SScott Long /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 2200f1c579b1SScott Long /*highaddr*/BUS_SPACE_MAXADDR, 2201f1c579b1SScott Long /*filter*/NULL, 2202f1c579b1SScott Long /*filterarg*/NULL, 2203f1c579b1SScott Long /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, 2204f1c579b1SScott Long /*nsegments*/BUS_SPACE_UNRESTRICTED, 2205f1c579b1SScott Long /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 2206f1c579b1SScott Long /*flags*/0, 2207f1c579b1SScott Long /*lockfunc*/NULL, 2208f1c579b1SScott Long /*lockarg*/NULL, 2209f1c579b1SScott Long &pACB->parent_dmat) != 0) 2210f1c579b1SScott Long #else 2211f1c579b1SScott Long if (bus_dma_tag_create( /*parent*/NULL, 2212f1c579b1SScott Long /*alignemnt*/1, 2213f1c579b1SScott Long /*boundary*/0, 2214f1c579b1SScott Long /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 2215f1c579b1SScott Long /*highaddr*/BUS_SPACE_MAXADDR, 2216f1c579b1SScott Long /*filter*/NULL, 2217f1c579b1SScott Long /*filterarg*/NULL, 2218f1c579b1SScott Long /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, 2219f1c579b1SScott Long /*nsegments*/BUS_SPACE_UNRESTRICTED, 2220f1c579b1SScott Long /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 2221f1c579b1SScott Long /*flags*/0, 2222f1c579b1SScott Long &pACB->parent_dmat) != 0) 2223f1c579b1SScott Long #endif 2224f1c579b1SScott Long { 2225f1c579b1SScott Long printf("arcmsr_initialize: bus_dma_tag_create .......................failure!\n"); 2226f1c579b1SScott Long return ENOMEM; 2227f1c579b1SScott Long } 2228f1c579b1SScott Long /* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */ 2229f1c579b1SScott Long #if __FreeBSD_version >= 502010 2230f1c579b1SScott Long if(bus_dma_tag_create( /*parent_dmat*/pACB->parent_dmat, 2231f1c579b1SScott Long /*alignment*/1, 2232f1c579b1SScott Long /*boundary*/0, 2233f1c579b1SScott Long /*lowaddr*/BUS_SPACE_MAXADDR, 2234f1c579b1SScott Long /*highaddr*/BUS_SPACE_MAXADDR, 2235f1c579b1SScott Long /*filter*/NULL, 2236f1c579b1SScott Long /*filterarg*/NULL, 2237f1c579b1SScott Long /*maxsize*/MAXBSIZE, 2238f1c579b1SScott Long /*nsegments*/ARCMSR_MAX_SG_ENTRIES, 2239f1c579b1SScott Long /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 2240f1c579b1SScott Long /*flags*/BUS_DMA_ALLOCNOW, 2241f1c579b1SScott Long /*lockfunc*/busdma_lock_mutex, 2242f1c579b1SScott Long /*lockarg*/&Giant, 2243f1c579b1SScott Long &pACB->buffer_dmat) != 0) 2244f1c579b1SScott Long #else 2245f1c579b1SScott Long if(bus_dma_tag_create( /*parent_dmat*/pACB->parent_dmat, 2246f1c579b1SScott Long /*alignment*/1, 2247f1c579b1SScott Long /*boundary*/0, 2248f1c579b1SScott Long /*lowaddr*/BUS_SPACE_MAXADDR, 2249f1c579b1SScott Long /*highaddr*/BUS_SPACE_MAXADDR, 2250f1c579b1SScott Long /*filter*/NULL, 2251f1c579b1SScott Long /*filterarg*/NULL, 2252f1c579b1SScott Long /*maxsize*/MAXBSIZE, 2253f1c579b1SScott Long /*nsegments*/ARCMSR_MAX_SG_ENTRIES, 2254f1c579b1SScott Long /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 2255f1c579b1SScott Long /*flags*/BUS_DMA_ALLOCNOW, 2256f1c579b1SScott Long &pACB->buffer_dmat) != 0) 2257f1c579b1SScott Long #endif 2258f1c579b1SScott Long { 2259f1c579b1SScott Long bus_dma_tag_destroy(pACB->parent_dmat); 2260f1c579b1SScott Long printf("arcmsr_initialize: bus_dma_tag_create ............................failure!\n"); 2261f1c579b1SScott Long return ENOMEM; 2262f1c579b1SScott Long } 2263f1c579b1SScott Long /* DMA tag for our srb structures.... Allocate the pfreesrb memory */ 2264f1c579b1SScott Long #if __FreeBSD_version >= 502010 2265f1c579b1SScott Long if (bus_dma_tag_create( /*parent_dmat*/pACB->parent_dmat, 2266f1c579b1SScott Long /*alignment*/1, 2267f1c579b1SScott Long /*boundary*/0, 2268f1c579b1SScott Long /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 2269f1c579b1SScott Long /*highaddr*/BUS_SPACE_MAXADDR, 2270f1c579b1SScott Long /*filter*/NULL, 2271f1c579b1SScott Long /*filterarg*/NULL, 2272f1c579b1SScott Long /*maxsize*/((sizeof(struct _SRB) * ARCMSR_MAX_FREESRB_NUM)+0x20), 2273f1c579b1SScott Long /*nsegments*/1, 2274f1c579b1SScott Long /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 2275f1c579b1SScott Long /*flags*/BUS_DMA_ALLOCNOW, 2276f1c579b1SScott Long /*lockfunc*/NULL, 2277f1c579b1SScott Long /*lockarg*/NULL, 2278f1c579b1SScott Long &pACB->srb_dmat) != 0) 2279f1c579b1SScott Long #else 2280f1c579b1SScott Long if (bus_dma_tag_create( /*parent_dmat*/pACB->parent_dmat, 2281f1c579b1SScott Long /*alignment*/1, 2282f1c579b1SScott Long /*boundary*/0, 2283f1c579b1SScott Long /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 2284f1c579b1SScott Long /*highaddr*/BUS_SPACE_MAXADDR, 2285f1c579b1SScott Long /*filter*/NULL, 2286f1c579b1SScott Long /*filterarg*/NULL, 2287f1c579b1SScott Long /*maxsize*/((sizeof(struct _SRB) * ARCMSR_MAX_FREESRB_NUM)+0x20), 2288f1c579b1SScott Long /*nsegments*/1, 2289f1c579b1SScott Long /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 2290f1c579b1SScott Long /*flags*/BUS_DMA_ALLOCNOW, 2291f1c579b1SScott Long &pACB->srb_dmat) != 0) 2292f1c579b1SScott Long #endif 2293f1c579b1SScott Long { 2294f1c579b1SScott Long bus_dma_tag_destroy(pACB->buffer_dmat); 2295f1c579b1SScott Long bus_dma_tag_destroy(pACB->parent_dmat); 2296f1c579b1SScott Long printf("arcmsr_initialize: pACB->srb_dmat bus_dma_tag_create .....................failure!\n"); 2297f1c579b1SScott Long return ENXIO; 2298f1c579b1SScott Long } 2299f1c579b1SScott Long /* Allocation for our srbs */ 2300f1c579b1SScott Long if (bus_dmamem_alloc(pACB->srb_dmat, (void **)&pACB->uncacheptr, BUS_DMA_WAITOK | BUS_DMA_COHERENT, &pACB->srb_dmamap) != 0) 2301f1c579b1SScott Long { 2302f1c579b1SScott Long bus_dma_tag_destroy(pACB->srb_dmat); 2303f1c579b1SScott Long bus_dma_tag_destroy(pACB->buffer_dmat); 2304f1c579b1SScott Long bus_dma_tag_destroy(pACB->parent_dmat); 2305f1c579b1SScott Long printf("arcmsr_initialize: pACB->srb_dmat bus_dma_tag_create ...............failure!\n"); 2306f1c579b1SScott Long return ENXIO; 2307f1c579b1SScott Long } 2308f1c579b1SScott Long /* And permanently map them */ 2309f1c579b1SScott Long if(bus_dmamap_load(pACB->srb_dmat, pACB->srb_dmamap,pACB->uncacheptr,(sizeof(struct _SRB) * ARCMSR_MAX_FREESRB_NUM)+0x20,arcmsr_map_freesrb, pACB, /*flags*/0)) 2310f1c579b1SScott Long { 2311f1c579b1SScott Long bus_dma_tag_destroy(pACB->srb_dmat); 2312f1c579b1SScott Long bus_dma_tag_destroy(pACB->buffer_dmat); 2313f1c579b1SScott Long bus_dma_tag_destroy(pACB->parent_dmat); 2314f1c579b1SScott Long printf("arcmsr_initialize: bus_dmamap_load................... failure!\n"); 2315f1c579b1SScott Long return ENXIO; 2316f1c579b1SScott Long } 2317f1c579b1SScott Long pci_command=pci_read_config(dev,PCIR_COMMAND,2); 2318f1c579b1SScott Long pci_command |= PCIM_CMD_BUSMASTEREN; 2319f1c579b1SScott Long pci_command |= PCIM_CMD_PERRESPEN; 2320f1c579b1SScott Long pci_command |= PCIM_CMD_MWRICEN; 2321f1c579b1SScott Long /* Enable Busmaster/Mem */ 2322f1c579b1SScott Long pci_command |= PCIM_CMD_MEMEN; 2323f1c579b1SScott Long pci_write_config(dev,PCIR_COMMAND,pci_command,2); 2324f1c579b1SScott Long pACB->sys_res_arcmsr=bus_alloc_resource(dev,SYS_RES_MEMORY,&rid,0,~0,0x1000,RF_ACTIVE); 2325f1c579b1SScott Long if(pACB->sys_res_arcmsr == NULL) 2326f1c579b1SScott Long { 2327f1c579b1SScott Long arcmsr_free_resource(pACB); 2328f1c579b1SScott Long printf("arcmsr_initialize: bus_alloc_resource .....................failure!\n"); 2329f1c579b1SScott Long return ENOMEM; 2330f1c579b1SScott Long } 2331f1c579b1SScott Long if(rman_get_start(pACB->sys_res_arcmsr) <= 0) 2332f1c579b1SScott Long { 2333f1c579b1SScott Long arcmsr_free_resource(pACB); 2334f1c579b1SScott Long printf("arcmsr_initialize: rman_get_start ...........................failure!\n"); 2335f1c579b1SScott Long return ENXIO; 2336f1c579b1SScott Long } 2337f1c579b1SScott Long mem_base=(vm_offset_t) rman_get_virtual(pACB->sys_res_arcmsr); 2338f1c579b1SScott Long if(mem_base==0) 2339f1c579b1SScott Long { 2340f1c579b1SScott Long arcmsr_free_resource(pACB); 2341f1c579b1SScott Long printf("arcmsr_initialize: rman_get_virtual ..........................failure!\n"); 2342f1c579b1SScott Long return ENXIO; 2343f1c579b1SScott Long } 2344f1c579b1SScott Long if(pACB->acb_flags & ACB_F_MAPFREESRB_FAILD) 2345f1c579b1SScott Long { 2346f1c579b1SScott Long arcmsr_free_resource(pACB); 2347f1c579b1SScott Long printf("arcmsr_initialize: arman_get_virtual ..........................failure!\n"); 2348f1c579b1SScott Long return ENXIO; 2349f1c579b1SScott Long } 2350f1c579b1SScott Long pACB->btag=rman_get_bustag(pACB->sys_res_arcmsr); 2351f1c579b1SScott Long pACB->bhandle=rman_get_bushandle(pACB->sys_res_arcmsr); 2352f1c579b1SScott Long pACB->pmu=(PMU)mem_base; 2353f1c579b1SScott Long pACB->acb_flags |= (ACB_F_IOCTL_WQBUFFER_CLEARED|ACB_F_IOCTL_RQBUFFER_CLEARED); 2354f1c579b1SScott Long pACB->acb_flags &= ~ACB_F_SCSISTOPADAPTER; 2355f1c579b1SScott Long arcmsr_iop_init(pACB); 2356f1c579b1SScott Long return(0); 2357f1c579b1SScott Long } 2358f1c579b1SScott Long /* 2359f1c579b1SScott Long ************************************************************************ 2360f1c579b1SScott Long ** 2361f1c579b1SScott Long ** attach and init a host adapter 2362f1c579b1SScott Long ** 2363f1c579b1SScott Long ************************************************************************ 2364f1c579b1SScott Long */ 2365f1c579b1SScott Long static LONG arcmsr_attach(device_t dev) 2366f1c579b1SScott Long { 2367f1c579b1SScott Long PACB pACB=device_get_softc(dev); 2368f1c579b1SScott Long LONG unit=device_get_unit(dev); 2369f1c579b1SScott Long struct ccb_setasync csa; 2370f1c579b1SScott Long struct cam_devq *devq; /* Device Queue to use for this SIM */ 2371f1c579b1SScott Long struct resource *irqres; 2372f1c579b1SScott Long int rid; 2373f1c579b1SScott Long 2374f1c579b1SScott Long #if ARCMSR_DEBUG0 2375f1c579b1SScott Long printf("arcmsr_attach .............................\n" ); 2376f1c579b1SScott Long #endif 2377f1c579b1SScott Long 2378f1c579b1SScott Long if(arcmsr_initialize(dev)) 2379f1c579b1SScott Long { 2380f1c579b1SScott Long printf("arcmsr_attach: arcmsr_initialize failure!\n"); 2381f1c579b1SScott Long return ENXIO; 2382f1c579b1SScott Long } 2383f1c579b1SScott Long /* After setting up the adapter,map our interrupt */ 2384f1c579b1SScott Long rid=0; 2385f1c579b1SScott Long irqres=bus_alloc_resource(dev,SYS_RES_IRQ,&rid,0,~0,1,RF_SHAREABLE | RF_ACTIVE); 2386f1c579b1SScott Long if(irqres == NULL || bus_setup_intr(dev,irqres,INTR_TYPE_CAM,arcmsr_interrupt,pACB,&pACB->ih)) 2387f1c579b1SScott Long { 2388f1c579b1SScott Long arcmsr_free_resource(pACB); 2389f1c579b1SScott Long printf("arcmsr%d: unable to register interrupt handler!\n",unit); 2390f1c579b1SScott Long return ENXIO; 2391f1c579b1SScott Long } 2392f1c579b1SScott Long pACB->irqres=irqres; 2393f1c579b1SScott Long pACB->pci_dev=dev; 2394f1c579b1SScott Long pACB->pci_unit=unit; 2395f1c579b1SScott Long /* 2396f1c579b1SScott Long * Now let the CAM generic SCSI layer find the SCSI devices on 2397f1c579b1SScott Long * the bus * start queue to reset to the idle loop. * 2398f1c579b1SScott Long * Create device queue of SIM(s) * (MAX_START_JOB - 1) : 2399f1c579b1SScott Long * max_sim_transactions 2400f1c579b1SScott Long */ 2401f1c579b1SScott Long devq=cam_simq_alloc(ARCMSR_MAX_START_JOB); 2402f1c579b1SScott Long if(devq == NULL) 2403f1c579b1SScott Long { 2404f1c579b1SScott Long arcmsr_free_resource(pACB); 2405f1c579b1SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, pACB->irqres); 2406f1c579b1SScott Long printf("arcmsr_attach: cam_simq_alloc failure!\n"); 2407f1c579b1SScott Long return ENXIO; 2408f1c579b1SScott Long } 2409f1c579b1SScott Long pACB->psim=cam_sim_alloc(arcmsr_action,arcmsr_poll,"arcmsr",pACB,pACB->pci_unit,1,ARCMSR_MAX_OUTSTANDING_CMD,devq); 2410f1c579b1SScott Long if(pACB->psim == NULL) 2411f1c579b1SScott Long { 2412f1c579b1SScott Long arcmsr_free_resource(pACB); 2413f1c579b1SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, pACB->irqres); 2414f1c579b1SScott Long cam_simq_free(devq); 2415f1c579b1SScott Long printf("arcmsr_attach: cam_sim_alloc ..................failure!\n"); 2416f1c579b1SScott Long return ENXIO; 2417f1c579b1SScott Long } 2418f1c579b1SScott Long if(xpt_bus_register(pACB->psim,0) != CAM_SUCCESS) 2419f1c579b1SScott Long { 2420f1c579b1SScott Long arcmsr_free_resource(pACB); 2421f1c579b1SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, pACB->irqres); 2422f1c579b1SScott Long cam_sim_free(pACB->psim,/*free_devq*/TRUE); 2423f1c579b1SScott Long printf("arcmsr_attach: xpt_bus_register .......................failure!\n"); 2424f1c579b1SScott Long return ENXIO; 2425f1c579b1SScott Long } 2426f1c579b1SScott Long if(xpt_create_path(&pACB->ppath,/* periph */ NULL,cam_sim_path(pACB->psim),CAM_TARGET_WILDCARD,CAM_LUN_WILDCARD) != CAM_REQ_CMP) 2427f1c579b1SScott Long { 2428f1c579b1SScott Long arcmsr_free_resource(pACB); 2429f1c579b1SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, pACB->irqres); 2430f1c579b1SScott Long xpt_bus_deregister(cam_sim_path(pACB->psim)); 2431f1c579b1SScott Long cam_sim_free(pACB->psim,/* free_simq */ TRUE); 2432f1c579b1SScott Long printf("arcmsr_attach: xpt_create_path .....................failure!\n"); 2433f1c579b1SScott Long return ENXIO; 2434f1c579b1SScott Long } 2435f1c579b1SScott Long /* 2436f1c579b1SScott Long **************************************************** 2437f1c579b1SScott Long */ 2438f1c579b1SScott Long xpt_setup_ccb(&csa.ccb_h,pACB->ppath,/*priority*/5); 2439f1c579b1SScott Long csa.ccb_h.func_code=XPT_SASYNC_CB; 2440f1c579b1SScott Long csa.event_enable=AC_FOUND_DEVICE|AC_LOST_DEVICE; 2441f1c579b1SScott Long csa.callback=arcmsr_async; 2442f1c579b1SScott Long csa.callback_arg=pACB->psim; 2443f1c579b1SScott Long xpt_action((union ccb *)&csa); 2444f1c579b1SScott Long /* Create the control device. */ 2445f1c579b1SScott Long pACB->ioctl_dev=make_dev(&arcmsr_cdevsw, unit, UID_ROOT, GID_WHEEL /* GID_OPERATOR */, S_IRUSR | S_IWUSR, "arcmsr%d", unit); 2446f1c579b1SScott Long #if __FreeBSD_version < 503000 2447f1c579b1SScott Long pACB->ioctl_dev->si_drv1=pACB; 2448f1c579b1SScott Long #endif 2449f1c579b1SScott Long #if __FreeBSD_version > 500005 2450f1c579b1SScott Long (void)make_dev_alias(pACB->ioctl_dev, "arc%d", unit); 2451f1c579b1SScott Long #endif 2452f1c579b1SScott Long 2453f1c579b1SScott Long #if 0 2454f1c579b1SScott Long #if __FreeBSD_version > 500005 2455f1c579b1SScott Long if(kthread_create(arcmsr_do_thread_works, pACB, &pACB->kthread_proc,0,"arcmsr%d: kthread",pACB->pci_unit)) 2456f1c579b1SScott Long { 2457f1c579b1SScott Long device_printf(pACB->pci_dev,"cannot create kernel thread for this host adapetr\n"); 2458f1c579b1SScott Long xpt_bus_deregister(cam_sim_path(pACB->psim)); 2459f1c579b1SScott Long cam_sim_free(pACB->psim,/* free_simq */ TRUE); 2460f1c579b1SScott Long panic("arcmsr plunge kernel thread fail"); 2461f1c579b1SScott Long } 2462f1c579b1SScott Long #else 2463f1c579b1SScott Long if(kthread_create(arcmsr_do_thread_works, pACB, &pACB->kthread_proc,"arcmsr%d: kthread", pACB->pci_unit)) 2464f1c579b1SScott Long { 2465f1c579b1SScott Long device_printf(pACB->pci_dev,"cannot create kernel thread for this host adapetr\n"); 2466f1c579b1SScott Long xpt_bus_deregister(cam_sim_path(pACB->psim)); 2467f1c579b1SScott Long cam_sim_free(pACB->psim,/* free_simq */ TRUE); 2468f1c579b1SScott Long panic("arcmsr plunge kernel thread fail"); 2469f1c579b1SScott Long } 2470f1c579b1SScott Long #endif 2471f1c579b1SScott Long #endif 2472f1c579b1SScott Long return 0; 2473f1c579b1SScott Long } 2474f1c579b1SScott Long /* 2475f1c579b1SScott Long ************************************************************************ 2476f1c579b1SScott Long ** 2477f1c579b1SScott Long ** 2478f1c579b1SScott Long ** 2479f1c579b1SScott Long ************************************************************************ 2480f1c579b1SScott Long */ 2481f1c579b1SScott Long static LONG arcmsr_probe(device_t dev) 2482f1c579b1SScott Long { 2483f1c579b1SScott Long ULONG id; 2484f1c579b1SScott Long #if ARCMSR_DEBUG0 2485f1c579b1SScott Long printf("arcmsr_probe................. \n"); 2486f1c579b1SScott Long #endif 2487f1c579b1SScott Long switch(id=pci_get_devid(dev)) 2488f1c579b1SScott Long { 2489f1c579b1SScott Long case PCIDevVenIDARC1110: 2490f1c579b1SScott Long device_set_desc(dev,"ARECA ARC1110 PCI-X 4 PORTS SATA RAID CONTROLLER \n" ARCMSR_DRIVER_VERSION ); 2491f1c579b1SScott Long return 0; 2492f1c579b1SScott Long case PCIDevVenIDARC1120: 2493f1c579b1SScott Long device_set_desc(dev,"ARECA ARC1120 PCI-X 8 PORTS SATA RAID CONTROLLER (RAID6-ENGINE Inside) \n" ARCMSR_DRIVER_VERSION); 2494f1c579b1SScott Long return 0; 2495f1c579b1SScott Long case PCIDevVenIDARC1130: 2496f1c579b1SScott Long device_set_desc(dev,"ARECA ARC1130 PCI-X 12 PORTS SATA RAID CONTROLLER (RAID6-ENGINE Inside) \n" ARCMSR_DRIVER_VERSION); 2497f1c579b1SScott Long return 0; 2498f1c579b1SScott Long case PCIDevVenIDARC1160: 2499f1c579b1SScott Long device_set_desc(dev,"ARECA ARC1160 PCI-X 16 PORTS SATA RAID CONTROLLER (RAID6-ENGINE Inside) \n" ARCMSR_DRIVER_VERSION); 2500f1c579b1SScott Long return 0; 2501f1c579b1SScott Long case PCIDevVenIDARC1210: 2502f1c579b1SScott Long device_set_desc(dev,"ARECA ARC1210 PCI-EXPRESS 4 PORTS SATA RAID CONTROLLER \n" ARCMSR_DRIVER_VERSION); 2503f1c579b1SScott Long return 0; 2504f1c579b1SScott Long case PCIDevVenIDARC1220: 2505f1c579b1SScott Long device_set_desc(dev,"ARECA ARC1220 PCI-EXPRESS 8 PORTS SATA RAID CONTROLLER (RAID6-ENGINE Inside) \n" ARCMSR_DRIVER_VERSION); 2506f1c579b1SScott Long return 0; 2507f1c579b1SScott Long case PCIDevVenIDARC1230: 2508f1c579b1SScott Long device_set_desc(dev,"ARECA ARC1230 PCI-EXPRESS 12 PORTS SATA RAID CONTROLLER (RAID6-ENGINE Inside) \n" ARCMSR_DRIVER_VERSION); 2509f1c579b1SScott Long return 0; 2510f1c579b1SScott Long case PCIDevVenIDARC1260: 2511f1c579b1SScott Long device_set_desc(dev,"ARECA ARC1260 PCI-EXPRESS 16 PORTS SATA RAID CONTROLLER (RAID6-ENGINE Inside) \n" ARCMSR_DRIVER_VERSION); 2512f1c579b1SScott Long return 0; 2513f1c579b1SScott Long } 2514f1c579b1SScott Long return ENXIO; 2515f1c579b1SScott Long } 2516f1c579b1SScott Long /* 2517f1c579b1SScott Long ************************************************************************ 2518f1c579b1SScott Long ** 2519f1c579b1SScott Long ** 2520f1c579b1SScott Long ** 2521f1c579b1SScott Long ************************************************************************ 2522f1c579b1SScott Long */ 2523f1c579b1SScott Long static VOID arcmsr_shutdown(device_t dev) 2524f1c579b1SScott Long { 2525f1c579b1SScott Long LONG i,abort_cmd_cnt=0; 2526f1c579b1SScott Long ULONG s,intmask_org; 2527f1c579b1SScott Long PSRB pSRB; 2528f1c579b1SScott Long PACB pACB=device_get_softc(dev); 2529f1c579b1SScott Long 2530f1c579b1SScott Long #if ARCMSR_DEBUG0 2531f1c579b1SScott Long printf("arcmsr_shutdown................. \n"); 2532f1c579b1SScott Long #endif 2533f1c579b1SScott Long s=splcam(); 2534f1c579b1SScott Long /* disable all outbound interrupt */ 2535f1c579b1SScott Long intmask_org=CHIP_REG_READ32(&pACB->pmu->outbound_intmask); 2536f1c579b1SScott Long CHIP_REG_WRITE32(&pACB->pmu->outbound_intmask,(intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE)); 2537f1c579b1SScott Long /* stop adapter background rebuild */ 2538f1c579b1SScott Long arcmsr_stop_adapter_bgrb(pACB); 2539f1c579b1SScott Long if(arcmsr_wait_msgint_ready(pACB)!=TRUE) 2540f1c579b1SScott Long { 2541f1c579b1SScott Long printf("arcmsr_pcidev_disattach: wait 'stop adapter rebulid' timeout.... \n"); 2542f1c579b1SScott Long } 2543f1c579b1SScott Long arcmsr_flush_adapter_cache(pACB); 2544f1c579b1SScott Long if(arcmsr_wait_msgint_ready(pACB)!=TRUE) 2545f1c579b1SScott Long { 2546f1c579b1SScott Long printf("arcmsr_pcidev_disattach: wait 'flush adapter cache' timeout.... \n"); 2547f1c579b1SScott Long } 2548f1c579b1SScott Long /* abort all outstanding command */ 2549f1c579b1SScott Long pACB->acb_flags |= ACB_F_SCSISTOPADAPTER; 2550f1c579b1SScott Long pACB->acb_flags &= ~ACB_F_IOP_INITED; 2551f1c579b1SScott Long if(pACB->srboutstandingcount!=0) 2552f1c579b1SScott Long { 2553f1c579b1SScott Long PSRB pfreesrb; 2554f1c579b1SScott Long #if ARCMSR_DEBUG0 2555f1c579b1SScott Long printf("arcmsr_pcidev_disattach: .....pACB->srboutstandingcount!=0 \n"); 2556f1c579b1SScott Long #endif 2557f1c579b1SScott Long /* Q back all outstanding srb into wait exec psrb Q*/ 2558f1c579b1SScott Long pfreesrb=pACB->pfreesrb; 2559f1c579b1SScott Long for(i=0;i<ARCMSR_MAX_FREESRB_NUM;i++) 2560f1c579b1SScott Long { 2561f1c579b1SScott Long pSRB=&pfreesrb[i]; 2562f1c579b1SScott Long if(pSRB->startdone==ARCMSR_SRB_START) 2563f1c579b1SScott Long { 2564f1c579b1SScott Long pSRB->srb_flags|=SRB_FLAG_MASTER_ABORTED; 2565f1c579b1SScott Long pSRB->pccb->ccb_h.status=CAM_REQ_ABORTED; 2566f1c579b1SScott Long abort_cmd_cnt++; 2567f1c579b1SScott Long } 2568f1c579b1SScott Long } 2569f1c579b1SScott Long if(abort_cmd_cnt!=0) 2570f1c579b1SScott Long { 2571f1c579b1SScott Long #if ARCMSR_DEBUG0 2572f1c579b1SScott Long printf("arcmsr_pcidev_disattach: .....abort_cmd_cnt!=0 \n"); 2573f1c579b1SScott Long #endif 2574f1c579b1SScott Long arcmsr_abort_allcmd(pACB); 2575f1c579b1SScott Long if(arcmsr_wait_msgint_ready(pACB)!=TRUE) 2576f1c579b1SScott Long { 2577f1c579b1SScott Long printf("arcmsr_pcidev_disattach: wait 'abort all outstanding command' timeout.................in \n"); 2578f1c579b1SScott Long } 2579f1c579b1SScott Long } 2580f1c579b1SScott Long atomic_set_int(&pACB->srboutstandingcount,0); 2581f1c579b1SScott Long } 2582f1c579b1SScott Long if(pACB->srbwait2gocount!=0) 2583f1c579b1SScott Long { /*remove first wait2go srb and abort it*/ 2584f1c579b1SScott Long for(i=0;i<ARCMSR_MAX_OUTSTANDING_CMD;i++) 2585f1c579b1SScott Long { 2586f1c579b1SScott Long pSRB=pACB->psrbwait2go[i]; 2587f1c579b1SScott Long if(pSRB!=NULL) 2588f1c579b1SScott Long { 2589f1c579b1SScott Long pACB->psrbwait2go[i]=NULL; 2590f1c579b1SScott Long atomic_subtract_int(&pACB->srbwait2gocount,1); 2591f1c579b1SScott Long pSRB->pccb->ccb_h.status=CAM_REQ_ABORTED; 2592f1c579b1SScott Long arcmsr_srb_complete(pSRB); 2593f1c579b1SScott Long } 2594f1c579b1SScott Long } 2595f1c579b1SScott Long } 2596f1c579b1SScott Long splx(s); 2597f1c579b1SScott Long pACB->acb_flags |= ACB_F_STOP_THREAD; 2598f1c579b1SScott Long wakeup(pACB->kthread_proc);/* signal to kernel thread do_dpcQ: "stop thread" */ 2599f1c579b1SScott Long return; 2600f1c579b1SScott Long } 2601f1c579b1SScott Long /* 2602f1c579b1SScott Long ************************************************************************ 2603f1c579b1SScott Long ** 2604f1c579b1SScott Long ** 2605f1c579b1SScott Long ** 2606f1c579b1SScott Long ************************************************************************ 2607f1c579b1SScott Long */ 2608f1c579b1SScott Long static LONG arcmsr_detach(device_t dev) 2609f1c579b1SScott Long { 2610f1c579b1SScott Long PACB pACB=device_get_softc(dev); 2611f1c579b1SScott Long 2612f1c579b1SScott Long arcmsr_shutdown(dev); 2613f1c579b1SScott Long arcmsr_free_resource(pACB); 2614f1c579b1SScott Long bus_release_resource(dev, SYS_RES_MEMORY, PCIR_MAPS, pACB->sys_res_arcmsr); 2615f1c579b1SScott Long bus_teardown_intr(dev, pACB->irqres, pACB->ih); 2616f1c579b1SScott Long bus_release_resource(dev, SYS_RES_IRQ, 0, pACB->irqres); 2617f1c579b1SScott Long xpt_async(AC_LOST_DEVICE, pACB->ppath, NULL); 2618f1c579b1SScott Long xpt_free_path(pACB->ppath); 2619f1c579b1SScott Long xpt_bus_deregister(cam_sim_path(pACB->psim)); 2620f1c579b1SScott Long cam_sim_free(pACB->psim, TRUE); 2621f1c579b1SScott Long return (0); 2622f1c579b1SScott Long } 2623f1c579b1SScott Long 2624f1c579b1SScott Long 2625f1c579b1SScott Long 2626