xref: /dflybsd-src/sys/dev/raid/arcmsr/arcmsr.c (revision 030b0c8c4cf27c560ccec70410c8e21934ae677d)
11901a965SSascha Wildner /*
2cec1e926SSascha Wildner ********************************************************************************
3cec1e926SSascha Wildner **        OS    : FreeBSD
41901a965SSascha Wildner **   FILE NAME  : arcmsr.c
51901a965SSascha Wildner **        BY    : Erich Chen, Ching Huang
61901a965SSascha Wildner **   Description: SCSI RAID Device Driver for
7cec1e926SSascha Wildner **                ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX/ARC188x)
8cec1e926SSascha Wildner **                SATA/SAS RAID HOST Adapter
9cec1e926SSascha Wildner ********************************************************************************
10cec1e926SSascha Wildner ********************************************************************************
111901a965SSascha Wildner **
12cec1e926SSascha Wildner ** Copyright (C) 2002 - 2012, Areca Technology Corporation All rights reserved.
131901a965SSascha Wildner **
141901a965SSascha Wildner ** Redistribution and use in source and binary forms, with or without
151901a965SSascha Wildner ** modification, are permitted provided that the following conditions
161901a965SSascha Wildner ** are met:
171901a965SSascha Wildner ** 1. Redistributions of source code must retain the above copyright
181901a965SSascha Wildner **    notice, this list of conditions and the following disclaimer.
191901a965SSascha Wildner ** 2. Redistributions in binary form must reproduce the above copyright
201901a965SSascha Wildner **    notice, this list of conditions and the following disclaimer in the
211901a965SSascha Wildner **    documentation and/or other materials provided with the distribution.
221901a965SSascha Wildner ** 3. The name of the author may not be used to endorse or promote products
231901a965SSascha Wildner **    derived from this software without specific prior written permission.
241901a965SSascha Wildner **
251901a965SSascha Wildner ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
261901a965SSascha Wildner ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
271901a965SSascha Wildner ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
281901a965SSascha Wildner ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
291901a965SSascha Wildner ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT
301901a965SSascha Wildner ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
311901a965SSascha Wildner ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY
321901a965SSascha Wildner ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
331901a965SSascha Wildner **(INCLUDING NEGLIGENCE OR OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF
341901a965SSascha Wildner ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35cec1e926SSascha Wildner ********************************************************************************
361901a965SSascha Wildner ** History
371901a965SSascha Wildner **
381901a965SSascha Wildner **    REV#         DATE         NAME        DESCRIPTION
39cc3b439cSSascha Wildner ** 1.00.00.00   03/31/2004  Erich Chen      First release
401901a965SSascha Wildner ** 1.20.00.02   11/29/2004  Erich Chen      bug fix with arcmsr_bus_reset when PHY error
41cc3b439cSSascha Wildner ** 1.20.00.03   04/19/2005  Erich Chen      add SATA 24 Ports adapter type support
421901a965SSascha Wildner **                                          clean unused function
43cc3b439cSSascha Wildner ** 1.20.00.12   09/12/2005  Erich Chen      bug fix with abort command handling,
441901a965SSascha Wildner **                                          firmware version check
451901a965SSascha Wildner **                                          and firmware update notify for hardware bug fix
461901a965SSascha Wildner **                                          handling if none zero high part physical address
471901a965SSascha Wildner **                                          of srb resource
48cc3b439cSSascha Wildner ** 1.20.00.13   08/18/2006  Erich Chen      remove pending srb and report busy
491901a965SSascha Wildner **                                          add iop message xfer
501901a965SSascha Wildner **                                          with scsi pass-through command
511901a965SSascha Wildner **                                          add new device id of sas raid adapters
521901a965SSascha Wildner **                                          code fit for SPARC64 & PPC
531901a965SSascha Wildner ** 1.20.00.14   02/05/2007  Erich Chen      bug fix for incorrect ccb_h.status report
541901a965SSascha Wildner **                                          and cause g_vfs_done() read write error
551901a965SSascha Wildner ** 1.20.00.15   10/10/2007  Erich Chen      support new RAID adapter type ARC120x
561901a965SSascha Wildner ** 1.20.00.16   10/10/2009  Erich Chen      Bug fix for RAID adapter type ARC120x
571901a965SSascha Wildner **                                          bus_dmamem_alloc() with BUS_DMA_ZERO
581901a965SSascha Wildner ** 1.20.00.17   07/15/2010  Ching Huang     Added support ARC1880
591901a965SSascha Wildner **                                          report CAM_DEV_NOT_THERE instead of CAM_SEL_TIMEOUT when device failed,
601901a965SSascha Wildner **                                          prevent cam_periph_error removing all LUN devices of one Target id
611901a965SSascha Wildner **                                          for any one LUN device failed
6295696aa4SSascha Wildner ** 1.20.00.18   10/14/2010  Ching Huang     Fixed "inquiry data fails comparion at DV1 step"
6395696aa4SSascha Wildner **              10/25/2010  Ching Huang     Fixed bad range input in bus_alloc_resource for ADAPTER_TYPE_B
6495696aa4SSascha Wildner ** 1.20.00.19   11/11/2010  Ching Huang     Fixed arcmsr driver prevent arcsas support for Areca SAS HBA ARC13x0
65cc3b439cSSascha Wildner ** 1.20.00.20   12/08/2010  Ching Huang     Avoid calling atomic_set_int function
66cc3b439cSSascha Wildner ** 1.20.00.21   02/08/2011  Ching Huang     Implement I/O request timeout
67cc3b439cSSascha Wildner **              02/14/2011  Ching Huang     Modified pktRequestCount
68cc3b439cSSascha Wildner ** 1.20.00.21   03/03/2011  Ching Huang     if a command timeout, then wait its ccb back before free it
69cc3b439cSSascha Wildner ** 1.20.00.22   07/04/2011  Ching Huang     Fixed multiple MTX panic
70629e42e2SSascha Wildner ** 1.20.00.23   10/28/2011  Ching Huang     Added TIMEOUT_DELAY in case of too many HDDs need to start
71629e42e2SSascha Wildner ** 1.20.00.23   11/08/2011  Ching Huang     Added report device transfer speed
72629e42e2SSascha Wildner ** 1.20.00.23   01/30/2012  Ching Huang     Fixed Request requeued and Retrying command
73629e42e2SSascha Wildner ** 1.20.00.24   06/11/2012  Ching Huang     Fixed return sense data condition
74629e42e2SSascha Wildner ** 1.20.00.25   08/17/2012  Ching Huang     Fixed hotplug device no function on type A adapter
75cec1e926SSascha Wildner ** 1.20.00.26   12/14/2012  Ching Huang     Added support ARC1214,1224,1264,1284
76cec1e926SSascha Wildner ** 1.20.00.27   05/06/2013  Ching Huang     Fixed out standing cmd full on ARC-12x4
77cec1e926SSascha Wildner ** 1.20.00.28   09/13/2013  Ching Huang     Removed recursive mutex in arcmsr_abort_dr_ccbs
78cec1e926SSascha Wildner ** 1.20.00.29   12/18/2013  Ching Huang     Change simq allocation number, support ARC1883
79111d54bfSSascha Wildner ** 1.30.00.00   11/30/2015  Ching Huang     Added support ARC1203
80111d54bfSSascha Wildner ** 1.40.00.00   10/26/2017  Ching Huang     Added support ARC1884
811901a965SSascha Wildner ******************************************************************************************
82cec1e926SSascha Wildner * $FreeBSD: head/sys/dev/arcmsr/arcmsr.c 259565 2013-12-18 19:25:40Z delphij $
831901a965SSascha Wildner */
84cc3b439cSSascha Wildner #if 0
85cc3b439cSSascha Wildner #define ARCMSR_DEBUG1		1
86cc3b439cSSascha Wildner #endif
871901a965SSascha Wildner #include <sys/param.h>
881901a965SSascha Wildner #include <sys/systm.h>
891901a965SSascha Wildner #include <sys/malloc.h>
901901a965SSascha Wildner #include <sys/kernel.h>
911901a965SSascha Wildner #include <sys/bus.h>
921901a965SSascha Wildner #include <sys/queue.h>
931901a965SSascha Wildner #include <sys/stat.h>
941901a965SSascha Wildner #include <sys/kthread.h>
951901a965SSascha Wildner #include <sys/module.h>
961901a965SSascha Wildner #include <sys/proc.h>
971901a965SSascha Wildner #include <sys/lock.h>
981901a965SSascha Wildner #include <sys/sysctl.h>
991901a965SSascha Wildner #include <sys/thread2.h>
1001901a965SSascha Wildner #include <sys/poll.h>
1011901a965SSascha Wildner #include <sys/device.h>
1021901a965SSascha Wildner #include <vm/vm.h>
1031901a965SSascha Wildner #include <vm/vm_param.h>
1041901a965SSascha Wildner #include <vm/pmap.h>
1051901a965SSascha Wildner 
1061901a965SSascha Wildner #include <machine/atomic.h>
1071901a965SSascha Wildner #include <sys/conf.h>
1081901a965SSascha Wildner #include <sys/rman.h>
1091901a965SSascha Wildner 
1101901a965SSascha Wildner #include <bus/cam/cam.h>
1111901a965SSascha Wildner #include <bus/cam/cam_ccb.h>
1121901a965SSascha Wildner #include <bus/cam/cam_sim.h>
1131901a965SSascha Wildner #include <bus/cam/cam_periph.h>
1141901a965SSascha Wildner #include <bus/cam/cam_xpt_periph.h>
1151901a965SSascha Wildner #include <bus/cam/cam_xpt_sim.h>
1161901a965SSascha Wildner #include <bus/cam/cam_debug.h>
1171901a965SSascha Wildner #include <bus/cam/scsi/scsi_all.h>
1181901a965SSascha Wildner #include <bus/cam/scsi/scsi_message.h>
1191901a965SSascha Wildner /*
1201901a965SSascha Wildner **************************************************************************
1211901a965SSascha Wildner **************************************************************************
1221901a965SSascha Wildner */
1231901a965SSascha Wildner #include <sys/endian.h>
1241901a965SSascha Wildner #include <bus/pci/pcivar.h>
1251901a965SSascha Wildner #include <bus/pci/pcireg.h>
1261901a965SSascha Wildner 
127cc3b439cSSascha Wildner #define arcmsr_callout_init(a)	callout_init_mp(a);
128cc3b439cSSascha Wildner 
129111d54bfSSascha Wildner #define ARCMSR_DRIVER_VERSION	"arcmsr version 1.40.00.00 2017-10-26"
1301901a965SSascha Wildner #include <dev/raid/arcmsr/arcmsr.h>
1311901a965SSascha Wildner /*
1321901a965SSascha Wildner **************************************************************************
1331901a965SSascha Wildner **************************************************************************
1341901a965SSascha Wildner */
135cc3b439cSSascha Wildner static void arcmsr_free_srb(struct CommandControlBlock *srb);
1361901a965SSascha Wildner static struct CommandControlBlock *arcmsr_get_freesrb(struct AdapterControlBlock *acb);
1371901a965SSascha Wildner static u_int8_t arcmsr_seek_cmd2abort(union ccb *abortccb);
1381901a965SSascha Wildner static int arcmsr_probe(device_t dev);
1391901a965SSascha Wildner static int arcmsr_attach(device_t dev);
1401901a965SSascha Wildner static int arcmsr_detach(device_t dev);
1411901a965SSascha Wildner static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg);
1421901a965SSascha Wildner static void arcmsr_iop_parking(struct AdapterControlBlock *acb);
1431901a965SSascha Wildner static int arcmsr_shutdown(device_t dev);
1441901a965SSascha Wildner static void arcmsr_interrupt(struct AdapterControlBlock *acb);
1451901a965SSascha Wildner static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb);
1461901a965SSascha Wildner static void arcmsr_free_resource(struct AdapterControlBlock *acb);
1471901a965SSascha Wildner static void arcmsr_bus_reset(struct AdapterControlBlock *acb);
1481901a965SSascha Wildner static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb);
1491901a965SSascha Wildner static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb);
1501901a965SSascha Wildner static void arcmsr_iop_init(struct AdapterControlBlock *acb);
1511901a965SSascha Wildner static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb);
152cec1e926SSascha Wildner static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, struct QBUFFER *prbuffer);
153cec1e926SSascha Wildner static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb);
1541901a965SSascha Wildner static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb);
1551901a965SSascha Wildner static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag);
1561901a965SSascha Wildner static void arcmsr_iop_reset(struct AdapterControlBlock *acb);
1571901a965SSascha Wildner static void arcmsr_report_sense_info(struct CommandControlBlock *srb);
1581901a965SSascha Wildner static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t *dm_segs, u_int32_t nseg);
1591901a965SSascha Wildner static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *pccb);
1601901a965SSascha Wildner static int arcmsr_resume(device_t dev);
1611901a965SSascha Wildner static int arcmsr_suspend(device_t dev);
1621901a965SSascha Wildner static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb);
1631901a965SSascha Wildner static void arcmsr_polling_devmap(void *arg);
164cc3b439cSSascha Wildner static void arcmsr_srb_timeout(void *arg);
165cec1e926SSascha Wildner static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb);
166111d54bfSSascha Wildner static void arcmsr_hbe_postqueue_isr(struct AdapterControlBlock *acb);
167111d54bfSSascha Wildner static void arcmsr_teardown_intr(device_t dev, struct AdapterControlBlock *acb);
168cc3b439cSSascha Wildner #ifdef ARCMSR_DEBUG1
169cc3b439cSSascha Wildner static void arcmsr_dump_data(struct AdapterControlBlock *acb);
170cc3b439cSSascha Wildner #endif
1711901a965SSascha Wildner /*
1721901a965SSascha Wildner **************************************************************************
1731901a965SSascha Wildner **************************************************************************
1741901a965SSascha Wildner */
UDELAY(u_int32_t us)1751901a965SSascha Wildner static void UDELAY(u_int32_t us) { DELAY(us); }
1761901a965SSascha Wildner /*
1771901a965SSascha Wildner **************************************************************************
1781901a965SSascha Wildner **************************************************************************
1791901a965SSascha Wildner */
18095696aa4SSascha Wildner static bus_dmamap_callback_t arcmsr_map_free_srb;
18195696aa4SSascha Wildner static bus_dmamap_callback_t arcmsr_execute_srb;
1821901a965SSascha Wildner /*
1831901a965SSascha Wildner **************************************************************************
1841901a965SSascha Wildner **************************************************************************
1851901a965SSascha Wildner */
1861901a965SSascha Wildner static d_open_t	arcmsr_open;
1871901a965SSascha Wildner static d_close_t arcmsr_close;
1881901a965SSascha Wildner static d_ioctl_t arcmsr_ioctl;
1891901a965SSascha Wildner 
1901901a965SSascha Wildner static device_method_t arcmsr_methods[]={
1911901a965SSascha Wildner 	DEVMETHOD(device_probe,		arcmsr_probe),
1921901a965SSascha Wildner 	DEVMETHOD(device_attach,	arcmsr_attach),
1931901a965SSascha Wildner 	DEVMETHOD(device_detach,	arcmsr_detach),
1941901a965SSascha Wildner 	DEVMETHOD(device_shutdown,	arcmsr_shutdown),
1951901a965SSascha Wildner 	DEVMETHOD(device_suspend,	arcmsr_suspend),
1961901a965SSascha Wildner 	DEVMETHOD(device_resume,	arcmsr_resume),
197111d54bfSSascha Wildner 	DEVMETHOD(bus_print_child,	bus_generic_print_child),
198111d54bfSSascha Wildner 	DEVMETHOD(bus_driver_added,	bus_generic_driver_added),
199d3c9c58eSSascha Wildner 	DEVMETHOD_END
2001901a965SSascha Wildner };
2011901a965SSascha Wildner 
2021901a965SSascha Wildner static driver_t arcmsr_driver={
2031901a965SSascha Wildner 	"arcmsr", arcmsr_methods, sizeof(struct AdapterControlBlock)
2041901a965SSascha Wildner };
2051901a965SSascha Wildner 
2061901a965SSascha Wildner static devclass_t arcmsr_devclass;
207aa2b9d05SSascha Wildner DRIVER_MODULE(arcmsr, pci, arcmsr_driver, arcmsr_devclass, NULL, NULL);
208365ad4c8SSascha Wildner MODULE_VERSION(arcmsr, 1);
2091901a965SSascha Wildner MODULE_DEPEND(arcmsr, pci, 1, 1, 1);
2101901a965SSascha Wildner MODULE_DEPEND(arcmsr, cam, 1, 1, 1);
2111901a965SSascha Wildner #ifndef BUS_DMA_COHERENT
2121901a965SSascha Wildner 	#define	BUS_DMA_COHERENT	0x04	/* hint: map memory in a coherent way */
2131901a965SSascha Wildner #endif
2141901a965SSascha Wildner static struct dev_ops arcmsr_ops = {
215bfc3d149SSascha Wildner 	{ "arcmsr", 0, D_MPSAFE },
2161901a965SSascha Wildner 	.d_open    = arcmsr_open, 	/* open     */
2171901a965SSascha Wildner 	.d_close   = arcmsr_close, 	/* close    */
2181901a965SSascha Wildner 	.d_ioctl   = arcmsr_ioctl, 	/* ioctl    */
2191901a965SSascha Wildner };
2201901a965SSascha Wildner 
221fb8c9539SSascha Wildner static int	arcmsr_msi_enable = 1;
222fb8c9539SSascha Wildner TUNABLE_INT("hw.arcmsr.msi.enable", &arcmsr_msi_enable);
223fb8c9539SSascha Wildner 
2241901a965SSascha Wildner /*
2251901a965SSascha Wildner **************************************************************************
2261901a965SSascha Wildner **************************************************************************
2271901a965SSascha Wildner */
2281901a965SSascha Wildner static int
arcmsr_open(struct dev_open_args * ap)2291901a965SSascha Wildner arcmsr_open(struct dev_open_args *ap)
2301901a965SSascha Wildner {
2311901a965SSascha Wildner 	cdev_t dev = ap->a_head.a_dev;
2321901a965SSascha Wildner 	struct AdapterControlBlock *acb = dev->si_drv1;
2331901a965SSascha Wildner 
2341901a965SSascha Wildner 	if(acb == NULL) {
2351901a965SSascha Wildner 		return ENXIO;
2361901a965SSascha Wildner 	}
237629e42e2SSascha Wildner 	return (0);
2381901a965SSascha Wildner }
2391901a965SSascha Wildner /*
2401901a965SSascha Wildner **************************************************************************
2411901a965SSascha Wildner **************************************************************************
2421901a965SSascha Wildner */
2431901a965SSascha Wildner static int
arcmsr_close(struct dev_close_args * ap)2441901a965SSascha Wildner arcmsr_close(struct dev_close_args *ap)
2451901a965SSascha Wildner {
2461901a965SSascha Wildner 	cdev_t dev = ap->a_head.a_dev;
2471901a965SSascha Wildner 	struct AdapterControlBlock *acb = dev->si_drv1;
2481901a965SSascha Wildner 
2491901a965SSascha Wildner 	if(acb == NULL) {
2501901a965SSascha Wildner 		return ENXIO;
2511901a965SSascha Wildner 	}
2521901a965SSascha Wildner 	return 0;
2531901a965SSascha Wildner }
2541901a965SSascha Wildner /*
2551901a965SSascha Wildner **************************************************************************
2561901a965SSascha Wildner **************************************************************************
2571901a965SSascha Wildner */
2581901a965SSascha Wildner static int
arcmsr_ioctl(struct dev_ioctl_args * ap)2591901a965SSascha Wildner arcmsr_ioctl(struct dev_ioctl_args *ap)
2601901a965SSascha Wildner {
2611901a965SSascha Wildner 	cdev_t dev = ap->a_head.a_dev;
2621901a965SSascha Wildner 	u_long ioctl_cmd = ap->a_cmd;
2631901a965SSascha Wildner 	caddr_t arg = ap->a_data;
2641901a965SSascha Wildner 	struct AdapterControlBlock *acb = dev->si_drv1;
2651901a965SSascha Wildner 
2661901a965SSascha Wildner 	if(acb == NULL) {
2671901a965SSascha Wildner 		return ENXIO;
2681901a965SSascha Wildner 	}
2691901a965SSascha Wildner 	return (arcmsr_iop_ioctlcmd(acb, ioctl_cmd, arg));
2701901a965SSascha Wildner }
2711901a965SSascha Wildner /*
2721901a965SSascha Wildner **********************************************************************
2731901a965SSascha Wildner **********************************************************************
2741901a965SSascha Wildner */
arcmsr_disable_allintr(struct AdapterControlBlock * acb)2751901a965SSascha Wildner static u_int32_t arcmsr_disable_allintr( struct AdapterControlBlock *acb)
2761901a965SSascha Wildner {
2771901a965SSascha Wildner 	u_int32_t intmask_org = 0;
2781901a965SSascha Wildner 
2791901a965SSascha Wildner 	switch (acb->adapter_type) {
2801901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_A: {
2811901a965SSascha Wildner 			/* disable all outbound interrupt */
2821901a965SSascha Wildner 			intmask_org = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intmask); /* disable outbound message0 int */
2831901a965SSascha Wildner 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE);
2841901a965SSascha Wildner 		}
2851901a965SSascha Wildner 		break;
2861901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_B: {
287111d54bfSSascha Wildner 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
2881901a965SSascha Wildner 			/* disable all outbound interrupt */
289111d54bfSSascha Wildner 			intmask_org = READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask)
290111d54bfSSascha Wildner 						& (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); /* disable outbound message0 int */
291111d54bfSSascha Wildner 			WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask, 0); /* disable all interrupt */
2921901a965SSascha Wildner 		}
2931901a965SSascha Wildner 		break;
2941901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_C: {
2951901a965SSascha Wildner 			/* disable all outbound interrupt */
2961901a965SSascha Wildner 			intmask_org = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_mask)	; /* disable outbound message0 int */
2971901a965SSascha Wildner 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org|ARCMSR_HBCMU_ALL_INTMASKENABLE);
2981901a965SSascha Wildner 		}
2991901a965SSascha Wildner 		break;
300cec1e926SSascha Wildner 	case ACB_ADAPTER_TYPE_D: {
301cec1e926SSascha Wildner 			/* disable all outbound interrupt */
302cec1e926SSascha Wildner 			intmask_org = CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable)	; /* disable outbound message0 int */
303cec1e926SSascha Wildner 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, ARCMSR_HBDMU_ALL_INT_DISABLE);
304cec1e926SSascha Wildner 		}
305cec1e926SSascha Wildner 		break;
306111d54bfSSascha Wildner 	case ACB_ADAPTER_TYPE_E: {
307111d54bfSSascha Wildner 			/* disable all outbound interrupt */
308111d54bfSSascha Wildner 			intmask_org = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_mask)	; /* disable outbound message0 int */
309111d54bfSSascha Wildner 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_mask, intmask_org | ARCMSR_HBEMU_ALL_INTMASKENABLE);
310111d54bfSSascha Wildner 		}
311111d54bfSSascha Wildner 		break;
3121901a965SSascha Wildner 	}
3131901a965SSascha Wildner 	return (intmask_org);
3141901a965SSascha Wildner }
3151901a965SSascha Wildner /*
3161901a965SSascha Wildner **********************************************************************
3171901a965SSascha Wildner **********************************************************************
3181901a965SSascha Wildner */
arcmsr_enable_allintr(struct AdapterControlBlock * acb,u_int32_t intmask_org)3191901a965SSascha Wildner static void arcmsr_enable_allintr( struct AdapterControlBlock *acb, u_int32_t intmask_org)
3201901a965SSascha Wildner {
3211901a965SSascha Wildner 	u_int32_t mask;
3221901a965SSascha Wildner 
3231901a965SSascha Wildner 	switch (acb->adapter_type) {
3241901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_A: {
3251901a965SSascha Wildner 			/* enable outbound Post Queue, outbound doorbell Interrupt */
3261901a965SSascha Wildner 			mask = ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE);
3271901a965SSascha Wildner 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org & mask);
3281901a965SSascha Wildner 			acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff;
3291901a965SSascha Wildner 		}
3301901a965SSascha Wildner 		break;
3311901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_B: {
332111d54bfSSascha Wildner 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
3331901a965SSascha Wildner 			/* enable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */
3341901a965SSascha Wildner 			mask = (ARCMSR_IOP2DRV_DATA_WRITE_OK|ARCMSR_IOP2DRV_DATA_READ_OK|ARCMSR_IOP2DRV_CDB_DONE|ARCMSR_IOP2DRV_MESSAGE_CMD_DONE);
335111d54bfSSascha Wildner 			WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask, intmask_org | mask); /*1=interrupt enable, 0=interrupt disable*/
3361901a965SSascha Wildner 			acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f;
3371901a965SSascha Wildner 		}
3381901a965SSascha Wildner 		break;
3391901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_C: {
3401901a965SSascha Wildner 			/* enable outbound Post Queue, outbound doorbell Interrupt */
3411901a965SSascha Wildner 			mask = ~(ARCMSR_HBCMU_UTILITY_A_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK);
3421901a965SSascha Wildner 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org & mask);
3431901a965SSascha Wildner 			acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f;
3441901a965SSascha Wildner 		}
3451901a965SSascha Wildner 		break;
346cec1e926SSascha Wildner 	case ACB_ADAPTER_TYPE_D: {
347cec1e926SSascha Wildner 			/* enable outbound Post Queue, outbound doorbell Interrupt */
348cec1e926SSascha Wildner 			mask = ARCMSR_HBDMU_ALL_INT_ENABLE;
349cec1e926SSascha Wildner 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, intmask_org | mask);
350cec1e926SSascha Wildner 			CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable);
351cec1e926SSascha Wildner 			acb->outbound_int_enable = mask;
352cec1e926SSascha Wildner 		}
353cec1e926SSascha Wildner 		break;
354111d54bfSSascha Wildner 	case ACB_ADAPTER_TYPE_E: {
355111d54bfSSascha Wildner 			/* enable outbound Post Queue, outbound doorbell Interrupt */
356111d54bfSSascha Wildner 			mask = ~(ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR | ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR);
357111d54bfSSascha Wildner 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_mask, intmask_org & mask);
358111d54bfSSascha Wildner 			acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f;
359111d54bfSSascha Wildner 		}
360111d54bfSSascha Wildner 		break;
3611901a965SSascha Wildner 	}
3621901a965SSascha Wildner }
3631901a965SSascha Wildner /*
3641901a965SSascha Wildner **********************************************************************
3651901a965SSascha Wildner **********************************************************************
3661901a965SSascha Wildner */
arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock * acb)3671901a965SSascha Wildner static u_int8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb)
3681901a965SSascha Wildner {
3691901a965SSascha Wildner 	u_int32_t Index;
3701901a965SSascha Wildner 	u_int8_t Retries = 0x00;
3711901a965SSascha Wildner 
3721901a965SSascha Wildner 	do {
3731901a965SSascha Wildner 		for(Index=0; Index < 100; Index++) {
3741901a965SSascha Wildner 			if(CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
3751901a965SSascha Wildner 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/
3761901a965SSascha Wildner 				return TRUE;
3771901a965SSascha Wildner 			}
3781901a965SSascha Wildner 			UDELAY(10000);
3791901a965SSascha Wildner 		}/*max 1 seconds*/
3801901a965SSascha Wildner 	}while(Retries++ < 20);/*max 20 sec*/
381629e42e2SSascha Wildner 	return (FALSE);
3821901a965SSascha Wildner }
3831901a965SSascha Wildner /*
3841901a965SSascha Wildner **********************************************************************
3851901a965SSascha Wildner **********************************************************************
3861901a965SSascha Wildner */
arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock * acb)3871901a965SSascha Wildner static u_int8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb)
3881901a965SSascha Wildner {
3891901a965SSascha Wildner 	u_int32_t Index;
3901901a965SSascha Wildner 	u_int8_t Retries = 0x00;
391111d54bfSSascha Wildner 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
3921901a965SSascha Wildner 
3931901a965SSascha Wildner 	do {
3941901a965SSascha Wildner 		for(Index=0; Index < 100; Index++) {
395111d54bfSSascha Wildner 			if(READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
396111d54bfSSascha Wildner 				WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/
397111d54bfSSascha Wildner 				WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
3981901a965SSascha Wildner 				return TRUE;
3991901a965SSascha Wildner 			}
4001901a965SSascha Wildner 			UDELAY(10000);
4011901a965SSascha Wildner 		}/*max 1 seconds*/
4021901a965SSascha Wildner 	}while(Retries++ < 20);/*max 20 sec*/
403629e42e2SSascha Wildner 	return (FALSE);
4041901a965SSascha Wildner }
4051901a965SSascha Wildner /*
4061901a965SSascha Wildner **********************************************************************
4071901a965SSascha Wildner **********************************************************************
4081901a965SSascha Wildner */
arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock * acb)4091901a965SSascha Wildner static u_int8_t arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock *acb)
4101901a965SSascha Wildner {
4111901a965SSascha Wildner 	u_int32_t Index;
4121901a965SSascha Wildner 	u_int8_t Retries = 0x00;
4131901a965SSascha Wildner 
4141901a965SSascha Wildner 	do {
4151901a965SSascha Wildner 		for(Index=0; Index < 100; Index++) {
4161901a965SSascha Wildner 			if(CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) {
4171901a965SSascha Wildner 				CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);/*clear interrupt*/
4181901a965SSascha Wildner 				return TRUE;
4191901a965SSascha Wildner 			}
4201901a965SSascha Wildner 			UDELAY(10000);
4211901a965SSascha Wildner 		}/*max 1 seconds*/
4221901a965SSascha Wildner 	}while(Retries++ < 20);/*max 20 sec*/
423629e42e2SSascha Wildner 	return (FALSE);
4241901a965SSascha Wildner }
4251901a965SSascha Wildner /*
426cec1e926SSascha Wildner **********************************************************************
427cec1e926SSascha Wildner **********************************************************************
428cec1e926SSascha Wildner */
arcmsr_hbd_wait_msgint_ready(struct AdapterControlBlock * acb)429cec1e926SSascha Wildner static u_int8_t arcmsr_hbd_wait_msgint_ready(struct AdapterControlBlock *acb)
430cec1e926SSascha Wildner {
431cec1e926SSascha Wildner 	u_int32_t Index;
432cec1e926SSascha Wildner 	u_int8_t Retries = 0x00;
433cec1e926SSascha Wildner 
434cec1e926SSascha Wildner 	do {
435cec1e926SSascha Wildner 		for(Index=0; Index < 100; Index++) {
436cec1e926SSascha Wildner 			if(CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) {
437cec1e926SSascha Wildner 				CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR);/*clear interrupt*/
438cec1e926SSascha Wildner 				return TRUE;
439cec1e926SSascha Wildner 			}
440cec1e926SSascha Wildner 			UDELAY(10000);
441cec1e926SSascha Wildner 		}/*max 1 seconds*/
442cec1e926SSascha Wildner 	}while(Retries++ < 20);/*max 20 sec*/
443cec1e926SSascha Wildner 	return (FALSE);
444cec1e926SSascha Wildner }
445cec1e926SSascha Wildner /*
446111d54bfSSascha Wildner **********************************************************************
447111d54bfSSascha Wildner **********************************************************************
448111d54bfSSascha Wildner */
arcmsr_hbe_wait_msgint_ready(struct AdapterControlBlock * acb)449111d54bfSSascha Wildner static u_int8_t arcmsr_hbe_wait_msgint_ready(struct AdapterControlBlock *acb)
450111d54bfSSascha Wildner {
451111d54bfSSascha Wildner 	u_int32_t Index, read_doorbell;
452111d54bfSSascha Wildner 	u_int8_t Retries = 0x00;
453111d54bfSSascha Wildner 
454111d54bfSSascha Wildner 	do {
455111d54bfSSascha Wildner 		for(Index=0; Index < 100; Index++) {
456111d54bfSSascha Wildner 			read_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell);
457111d54bfSSascha Wildner 			if((read_doorbell ^ acb->in_doorbell) & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) {
458111d54bfSSascha Wildner 				CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0);/*clear interrupt*/
459111d54bfSSascha Wildner 				acb->in_doorbell = read_doorbell;
460111d54bfSSascha Wildner 				return TRUE;
461111d54bfSSascha Wildner 			}
462111d54bfSSascha Wildner 			UDELAY(10000);
463111d54bfSSascha Wildner 		}/*max 1 seconds*/
464111d54bfSSascha Wildner 	}while(Retries++ < 20);/*max 20 sec*/
465111d54bfSSascha Wildner 	return (FALSE);
466111d54bfSSascha Wildner }
467111d54bfSSascha Wildner /*
4681901a965SSascha Wildner ************************************************************************
4691901a965SSascha Wildner ************************************************************************
4701901a965SSascha Wildner */
arcmsr_flush_hba_cache(struct AdapterControlBlock * acb)4711901a965SSascha Wildner static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb)
4721901a965SSascha Wildner {
4731901a965SSascha Wildner 	int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */
4741901a965SSascha Wildner 
4751901a965SSascha Wildner 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
4761901a965SSascha Wildner 	do {
4771901a965SSascha Wildner 		if(arcmsr_hba_wait_msgint_ready(acb)) {
4781901a965SSascha Wildner 			break;
4791901a965SSascha Wildner 		} else {
4801901a965SSascha Wildner 			retry_count--;
4811901a965SSascha Wildner 		}
4821901a965SSascha Wildner 	}while(retry_count != 0);
4831901a965SSascha Wildner }
4841901a965SSascha Wildner /*
4851901a965SSascha Wildner ************************************************************************
4861901a965SSascha Wildner ************************************************************************
4871901a965SSascha Wildner */
arcmsr_flush_hbb_cache(struct AdapterControlBlock * acb)4881901a965SSascha Wildner static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb)
4891901a965SSascha Wildner {
4901901a965SSascha Wildner 	int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */
491111d54bfSSascha Wildner 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
4921901a965SSascha Wildner 
493111d54bfSSascha Wildner 	WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_FLUSH_CACHE);
4941901a965SSascha Wildner 	do {
4951901a965SSascha Wildner 		if(arcmsr_hbb_wait_msgint_ready(acb)) {
4961901a965SSascha Wildner 			break;
4971901a965SSascha Wildner 		} else {
4981901a965SSascha Wildner 			retry_count--;
4991901a965SSascha Wildner 		}
5001901a965SSascha Wildner 	}while(retry_count != 0);
5011901a965SSascha Wildner }
5021901a965SSascha Wildner /*
5031901a965SSascha Wildner ************************************************************************
5041901a965SSascha Wildner ************************************************************************
5051901a965SSascha Wildner */
arcmsr_flush_hbc_cache(struct AdapterControlBlock * acb)5061901a965SSascha Wildner static void arcmsr_flush_hbc_cache(struct AdapterControlBlock *acb)
5071901a965SSascha Wildner {
5081901a965SSascha Wildner 	int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */
5091901a965SSascha Wildner 
5101901a965SSascha Wildner 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
5111901a965SSascha Wildner 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
5121901a965SSascha Wildner 	do {
5131901a965SSascha Wildner 		if(arcmsr_hbc_wait_msgint_ready(acb)) {
5141901a965SSascha Wildner 			break;
5151901a965SSascha Wildner 		} else {
5161901a965SSascha Wildner 			retry_count--;
5171901a965SSascha Wildner 		}
5181901a965SSascha Wildner 	}while(retry_count != 0);
5191901a965SSascha Wildner }
5201901a965SSascha Wildner /*
5211901a965SSascha Wildner ************************************************************************
5221901a965SSascha Wildner ************************************************************************
5231901a965SSascha Wildner */
arcmsr_flush_hbd_cache(struct AdapterControlBlock * acb)524cec1e926SSascha Wildner static void arcmsr_flush_hbd_cache(struct AdapterControlBlock *acb)
525cec1e926SSascha Wildner {
526cec1e926SSascha Wildner 	int retry_count = 30; /* enlarge wait flush adapter cache time: 10 minute */
527cec1e926SSascha Wildner 
528cec1e926SSascha Wildner 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
529cec1e926SSascha Wildner 	do {
530cec1e926SSascha Wildner 		if(arcmsr_hbd_wait_msgint_ready(acb)) {
531cec1e926SSascha Wildner 			break;
532cec1e926SSascha Wildner 		} else {
533cec1e926SSascha Wildner 			retry_count--;
534cec1e926SSascha Wildner 		}
535cec1e926SSascha Wildner 	}while(retry_count != 0);
536cec1e926SSascha Wildner }
537cec1e926SSascha Wildner /*
538cec1e926SSascha Wildner ************************************************************************
539cec1e926SSascha Wildner ************************************************************************
540cec1e926SSascha Wildner */
arcmsr_flush_hbe_cache(struct AdapterControlBlock * acb)541111d54bfSSascha Wildner static void arcmsr_flush_hbe_cache(struct AdapterControlBlock *acb)
542111d54bfSSascha Wildner {
543111d54bfSSascha Wildner 	int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */
544111d54bfSSascha Wildner 
545111d54bfSSascha Wildner 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
546111d54bfSSascha Wildner 	acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
547111d54bfSSascha Wildner 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
548111d54bfSSascha Wildner 	do {
549111d54bfSSascha Wildner 		if(arcmsr_hbe_wait_msgint_ready(acb)) {
550111d54bfSSascha Wildner 			break;
551111d54bfSSascha Wildner 		} else {
552111d54bfSSascha Wildner 			retry_count--;
553111d54bfSSascha Wildner 		}
554111d54bfSSascha Wildner 	}while(retry_count != 0);
555111d54bfSSascha Wildner }
556111d54bfSSascha Wildner /*
557111d54bfSSascha Wildner ************************************************************************
558111d54bfSSascha Wildner ************************************************************************
559111d54bfSSascha Wildner */
arcmsr_flush_adapter_cache(struct AdapterControlBlock * acb)5601901a965SSascha Wildner static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
5611901a965SSascha Wildner {
5621901a965SSascha Wildner 	switch (acb->adapter_type) {
5631901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_A: {
5641901a965SSascha Wildner 			arcmsr_flush_hba_cache(acb);
5651901a965SSascha Wildner 		}
5661901a965SSascha Wildner 		break;
5671901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_B: {
5681901a965SSascha Wildner 			arcmsr_flush_hbb_cache(acb);
5691901a965SSascha Wildner 		}
5701901a965SSascha Wildner 		break;
5711901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_C: {
5721901a965SSascha Wildner 			arcmsr_flush_hbc_cache(acb);
5731901a965SSascha Wildner 		}
5741901a965SSascha Wildner 		break;
575cec1e926SSascha Wildner 	case ACB_ADAPTER_TYPE_D: {
576cec1e926SSascha Wildner 			arcmsr_flush_hbd_cache(acb);
577cec1e926SSascha Wildner 		}
578cec1e926SSascha Wildner 		break;
579111d54bfSSascha Wildner 	case ACB_ADAPTER_TYPE_E: {
580111d54bfSSascha Wildner 			arcmsr_flush_hbe_cache(acb);
581111d54bfSSascha Wildner 		}
582111d54bfSSascha Wildner 		break;
5831901a965SSascha Wildner 	}
5841901a965SSascha Wildner }
5851901a965SSascha Wildner /*
5861901a965SSascha Wildner *******************************************************************************
5871901a965SSascha Wildner *******************************************************************************
5881901a965SSascha Wildner */
arcmsr_suspend(device_t dev)5891901a965SSascha Wildner static int arcmsr_suspend(device_t dev)
5901901a965SSascha Wildner {
5911901a965SSascha Wildner 	struct AdapterControlBlock	*acb = device_get_softc(dev);
5921901a965SSascha Wildner 
5931901a965SSascha Wildner 	/* flush controller */
5941901a965SSascha Wildner 	arcmsr_iop_parking(acb);
5951901a965SSascha Wildner 	/* disable all outbound interrupt */
5961901a965SSascha Wildner 	arcmsr_disable_allintr(acb);
5971901a965SSascha Wildner 	return(0);
5981901a965SSascha Wildner }
5991901a965SSascha Wildner /*
6001901a965SSascha Wildner *******************************************************************************
6011901a965SSascha Wildner *******************************************************************************
6021901a965SSascha Wildner */
arcmsr_resume(device_t dev)6031901a965SSascha Wildner static int arcmsr_resume(device_t dev)
6041901a965SSascha Wildner {
6051901a965SSascha Wildner 	struct AdapterControlBlock	*acb = device_get_softc(dev);
6061901a965SSascha Wildner 
6071901a965SSascha Wildner 	arcmsr_iop_init(acb);
6081901a965SSascha Wildner 	return(0);
6091901a965SSascha Wildner }
6101901a965SSascha Wildner /*
6111901a965SSascha Wildner **********************************************************************
6121901a965SSascha Wildner **********************************************************************
6131901a965SSascha Wildner */
arcmsr_report_sense_info(struct CommandControlBlock * srb)6141901a965SSascha Wildner static void arcmsr_report_sense_info(struct CommandControlBlock *srb)
6151901a965SSascha Wildner {
6161901a965SSascha Wildner 	union ccb *pccb = srb->pccb;
6171901a965SSascha Wildner 
6181901a965SSascha Wildner 	pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
6191901a965SSascha Wildner 	pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
6206d4343eeSSascha Wildner 	if(pccb->csio.sense_len) {
6211901a965SSascha Wildner 		memset(&pccb->csio.sense_data, 0, sizeof(pccb->csio.sense_data));
6221901a965SSascha Wildner 		memcpy(&pccb->csio.sense_data, srb->arcmsr_cdb.SenseData,
6231901a965SSascha Wildner 		get_min(sizeof(struct SENSE_DATA), sizeof(pccb->csio.sense_data)));
6241901a965SSascha Wildner 		((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); /* Valid,ErrorCode */
6251901a965SSascha Wildner 		pccb->ccb_h.status |= CAM_AUTOSNS_VALID;
6261901a965SSascha Wildner 	}
6271901a965SSascha Wildner }
6281901a965SSascha Wildner /*
6291901a965SSascha Wildner *********************************************************************
6301901a965SSascha Wildner *********************************************************************
6311901a965SSascha Wildner */
arcmsr_abort_hba_allcmd(struct AdapterControlBlock * acb)6321901a965SSascha Wildner static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb)
6331901a965SSascha Wildner {
6341901a965SSascha Wildner 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD);
6351901a965SSascha Wildner 	if(!arcmsr_hba_wait_msgint_ready(acb)) {
6361901a965SSascha Wildner 		kprintf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
6371901a965SSascha Wildner 	}
6381901a965SSascha Wildner }
6391901a965SSascha Wildner /*
6401901a965SSascha Wildner *********************************************************************
6411901a965SSascha Wildner *********************************************************************
6421901a965SSascha Wildner */
arcmsr_abort_hbb_allcmd(struct AdapterControlBlock * acb)6431901a965SSascha Wildner static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb)
6441901a965SSascha Wildner {
645111d54bfSSascha Wildner 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
646111d54bfSSascha Wildner 	WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_ABORT_CMD);
6471901a965SSascha Wildner 	if(!arcmsr_hbb_wait_msgint_ready(acb)) {
6481901a965SSascha Wildner 		kprintf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
6491901a965SSascha Wildner 	}
6501901a965SSascha Wildner }
6511901a965SSascha Wildner /*
6521901a965SSascha Wildner *********************************************************************
6531901a965SSascha Wildner *********************************************************************
6541901a965SSascha Wildner */
arcmsr_abort_hbc_allcmd(struct AdapterControlBlock * acb)6551901a965SSascha Wildner static void arcmsr_abort_hbc_allcmd(struct AdapterControlBlock *acb)
6561901a965SSascha Wildner {
6571901a965SSascha Wildner 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD);
6581901a965SSascha Wildner 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
6591901a965SSascha Wildner 	if(!arcmsr_hbc_wait_msgint_ready(acb)) {
6601901a965SSascha Wildner 		kprintf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
6611901a965SSascha Wildner 	}
6621901a965SSascha Wildner }
6631901a965SSascha Wildner /*
6641901a965SSascha Wildner *********************************************************************
6651901a965SSascha Wildner *********************************************************************
6661901a965SSascha Wildner */
arcmsr_abort_hbd_allcmd(struct AdapterControlBlock * acb)667cec1e926SSascha Wildner static void arcmsr_abort_hbd_allcmd(struct AdapterControlBlock *acb)
668cec1e926SSascha Wildner {
669cec1e926SSascha Wildner 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD);
670cec1e926SSascha Wildner 	if(!arcmsr_hbd_wait_msgint_ready(acb)) {
671cec1e926SSascha Wildner 		kprintf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
672cec1e926SSascha Wildner 	}
673cec1e926SSascha Wildner }
674cec1e926SSascha Wildner /*
675cec1e926SSascha Wildner *********************************************************************
676cec1e926SSascha Wildner *********************************************************************
677cec1e926SSascha Wildner */
arcmsr_abort_hbe_allcmd(struct AdapterControlBlock * acb)678111d54bfSSascha Wildner static void arcmsr_abort_hbe_allcmd(struct AdapterControlBlock *acb)
679111d54bfSSascha Wildner {
680111d54bfSSascha Wildner 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD);
681111d54bfSSascha Wildner 	acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
682111d54bfSSascha Wildner 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
683111d54bfSSascha Wildner 	if(!arcmsr_hbe_wait_msgint_ready(acb)) {
684111d54bfSSascha Wildner 		kprintf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
685111d54bfSSascha Wildner 	}
686111d54bfSSascha Wildner }
687111d54bfSSascha Wildner /*
688111d54bfSSascha Wildner *********************************************************************
689111d54bfSSascha Wildner *********************************************************************
690111d54bfSSascha Wildner */
arcmsr_abort_allcmd(struct AdapterControlBlock * acb)6911901a965SSascha Wildner static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb)
6921901a965SSascha Wildner {
6931901a965SSascha Wildner 	switch (acb->adapter_type) {
6941901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_A: {
6951901a965SSascha Wildner 			arcmsr_abort_hba_allcmd(acb);
6961901a965SSascha Wildner 		}
6971901a965SSascha Wildner 		break;
6981901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_B: {
6991901a965SSascha Wildner 			arcmsr_abort_hbb_allcmd(acb);
7001901a965SSascha Wildner 		}
7011901a965SSascha Wildner 		break;
7021901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_C: {
7031901a965SSascha Wildner 			arcmsr_abort_hbc_allcmd(acb);
7041901a965SSascha Wildner 		}
7051901a965SSascha Wildner 		break;
706cec1e926SSascha Wildner 	case ACB_ADAPTER_TYPE_D: {
707cec1e926SSascha Wildner 			arcmsr_abort_hbd_allcmd(acb);
7081901a965SSascha Wildner 		}
709cec1e926SSascha Wildner 		break;
710111d54bfSSascha Wildner 	case ACB_ADAPTER_TYPE_E: {
711111d54bfSSascha Wildner 			arcmsr_abort_hbe_allcmd(acb);
712111d54bfSSascha Wildner 		}
713111d54bfSSascha Wildner 		break;
714cec1e926SSascha Wildner 	}
715cec1e926SSascha Wildner }
716cec1e926SSascha Wildner /*
717cec1e926SSascha Wildner **********************************************************************
718cec1e926SSascha Wildner **********************************************************************
719cec1e926SSascha Wildner */
arcmsr_srb_complete(struct CommandControlBlock * srb,int stand_flag)720cec1e926SSascha Wildner static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag)
721cec1e926SSascha Wildner {
722cec1e926SSascha Wildner 	struct AdapterControlBlock *acb = srb->acb;
723cec1e926SSascha Wildner 	union ccb *pccb = srb->pccb;
724cec1e926SSascha Wildner 
725cec1e926SSascha Wildner 	if(srb->srb_flags & SRB_FLAG_TIMER_START)
726cec1e926SSascha Wildner 		callout_stop(&srb->ccb_callout);
727cec1e926SSascha Wildner 	if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
728cec1e926SSascha Wildner 		bus_dmasync_op_t op;
729cec1e926SSascha Wildner 
730cec1e926SSascha Wildner 		if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
731cec1e926SSascha Wildner 			op = BUS_DMASYNC_POSTREAD;
732cec1e926SSascha Wildner 		} else {
733cec1e926SSascha Wildner 			op = BUS_DMASYNC_POSTWRITE;
734cec1e926SSascha Wildner 		}
735cec1e926SSascha Wildner 		bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op);
736111d54bfSSascha Wildner 		ARCMSR_LOCK_ACQUIRE(&acb->io_lock);
737cec1e926SSascha Wildner 		bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap);
738111d54bfSSascha Wildner 		ARCMSR_LOCK_RELEASE(&acb->io_lock);
739cec1e926SSascha Wildner 	}
740cec1e926SSascha Wildner 	if(stand_flag == 1) {
741cec1e926SSascha Wildner 		atomic_subtract_int(&acb->srboutstandingcount, 1);
742cec1e926SSascha Wildner 		if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) && (
743cec1e926SSascha Wildner 		acb->srboutstandingcount < (acb->maxOutstanding -10))) {
744cec1e926SSascha Wildner 			acb->acb_flags &= ~ACB_F_CAM_DEV_QFRZN;
745cec1e926SSascha Wildner 			pccb->ccb_h.status |= CAM_RELEASE_SIMQ;
746cec1e926SSascha Wildner 		}
747cec1e926SSascha Wildner 	}
748cec1e926SSascha Wildner 	if(srb->srb_state != ARCMSR_SRB_TIMEOUT)
749cec1e926SSascha Wildner 		arcmsr_free_srb(srb);
750cec1e926SSascha Wildner 	acb->pktReturnCount++;
751111d54bfSSascha Wildner 	ARCMSR_LOCK_ACQUIRE(&acb->sim_lock);
752cec1e926SSascha Wildner 	xpt_done(pccb);
753111d54bfSSascha Wildner 	ARCMSR_LOCK_RELEASE(&acb->sim_lock);
7541901a965SSascha Wildner }
7551901a965SSascha Wildner /*
7561901a965SSascha Wildner **************************************************************************
7571901a965SSascha Wildner **************************************************************************
7581901a965SSascha Wildner */
arcmsr_report_srb_state(struct AdapterControlBlock * acb,struct CommandControlBlock * srb,u_int16_t error)7591901a965SSascha Wildner static void arcmsr_report_srb_state(struct AdapterControlBlock *acb, struct CommandControlBlock *srb, u_int16_t error)
7601901a965SSascha Wildner {
7611901a965SSascha Wildner 	int target, lun;
7621901a965SSascha Wildner 
7631901a965SSascha Wildner 	target = srb->pccb->ccb_h.target_id;
7641901a965SSascha Wildner 	lun = srb->pccb->ccb_h.target_lun;
7651901a965SSascha Wildner 	if(error == FALSE) {
7661901a965SSascha Wildner 		if(acb->devstate[target][lun] == ARECA_RAID_GONE) {
7671901a965SSascha Wildner 			acb->devstate[target][lun] = ARECA_RAID_GOOD;
7681901a965SSascha Wildner 		}
7691901a965SSascha Wildner 		srb->pccb->ccb_h.status |= CAM_REQ_CMP;
7701901a965SSascha Wildner 		arcmsr_srb_complete(srb, 1);
7711901a965SSascha Wildner 	} else {
7721901a965SSascha Wildner 		switch(srb->arcmsr_cdb.DeviceStatus) {
7731901a965SSascha Wildner 		case ARCMSR_DEV_SELECT_TIMEOUT: {
7741901a965SSascha Wildner 				if(acb->devstate[target][lun] == ARECA_RAID_GOOD) {
7751901a965SSascha Wildner 					kprintf( "arcmsr%d: Target=%x, Lun=%x, selection timeout, raid volume was lost\n", acb->pci_unit, target, lun);
7761901a965SSascha Wildner 				}
7771901a965SSascha Wildner 				acb->devstate[target][lun] = ARECA_RAID_GONE;
7781901a965SSascha Wildner 				srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
7791901a965SSascha Wildner 				arcmsr_srb_complete(srb, 1);
7801901a965SSascha Wildner 			}
7811901a965SSascha Wildner 			break;
7821901a965SSascha Wildner 		case ARCMSR_DEV_ABORTED:
7831901a965SSascha Wildner 		case ARCMSR_DEV_INIT_FAIL: {
7841901a965SSascha Wildner 				acb->devstate[target][lun] = ARECA_RAID_GONE;
7851901a965SSascha Wildner 				srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
7861901a965SSascha Wildner 				arcmsr_srb_complete(srb, 1);
7871901a965SSascha Wildner 			}
7881901a965SSascha Wildner 			break;
7891901a965SSascha Wildner 		case SCSISTAT_CHECK_CONDITION: {
7901901a965SSascha Wildner 				acb->devstate[target][lun] = ARECA_RAID_GOOD;
7911901a965SSascha Wildner 				arcmsr_report_sense_info(srb);
7921901a965SSascha Wildner 				arcmsr_srb_complete(srb, 1);
7931901a965SSascha Wildner 			}
7941901a965SSascha Wildner 			break;
7951901a965SSascha Wildner 		default:
79695cdd875SSascha Wildner 			kprintf("arcmsr%d: scsi id=%d lun=%d isr got command error done,but got unknown DeviceStatus=0x%x \n"
7971901a965SSascha Wildner 					, acb->pci_unit, target, lun ,srb->arcmsr_cdb.DeviceStatus);
7981901a965SSascha Wildner 			acb->devstate[target][lun] = ARECA_RAID_GONE;
7991901a965SSascha Wildner 			srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY;
80095cdd875SSascha Wildner 			/*unknown error or crc error just for retry*/
8011901a965SSascha Wildner 			arcmsr_srb_complete(srb, 1);
8021901a965SSascha Wildner 			break;
8031901a965SSascha Wildner 		}
8041901a965SSascha Wildner 	}
8051901a965SSascha Wildner }
8061901a965SSascha Wildner /*
8071901a965SSascha Wildner **************************************************************************
8081901a965SSascha Wildner **************************************************************************
8091901a965SSascha Wildner */
arcmsr_drain_donequeue(struct AdapterControlBlock * acb,u_int32_t flag_srb,u_int16_t error)8101901a965SSascha Wildner static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t flag_srb, u_int16_t error)
8111901a965SSascha Wildner {
8121901a965SSascha Wildner 	struct CommandControlBlock *srb;
8131901a965SSascha Wildner 
8141901a965SSascha Wildner 	/* check if command done with no error*/
8151901a965SSascha Wildner 	switch (acb->adapter_type) {
8161901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_C:
817cec1e926SSascha Wildner 	case ACB_ADAPTER_TYPE_D:
818cc3b439cSSascha Wildner 		srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0)); /*frame must be 32 bytes aligned*/
8191901a965SSascha Wildner 		break;
820111d54bfSSascha Wildner 	case ACB_ADAPTER_TYPE_E:
821111d54bfSSascha Wildner 		srb = acb->psrb_pool[flag_srb];
822111d54bfSSascha Wildner 		break;
8231901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_A:
8241901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_B:
8251901a965SSascha Wildner 	default:
8261901a965SSascha Wildner 		srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
8271901a965SSascha Wildner 		break;
8281901a965SSascha Wildner 	}
829cc3b439cSSascha Wildner 	if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
830cc3b439cSSascha Wildner 		if(srb->srb_state == ARCMSR_SRB_TIMEOUT) {
831cc3b439cSSascha Wildner 			arcmsr_free_srb(srb);
832cc3b439cSSascha Wildner 			kprintf("arcmsr%d: srb='%p' return srb has been timeouted\n", acb->pci_unit, srb);
8331901a965SSascha Wildner 			return;
8341901a965SSascha Wildner 		}
835cc3b439cSSascha Wildner 		kprintf("arcmsr%d: return srb has been completed\n"
836cc3b439cSSascha Wildner 			"srb='%p' srb_state=0x%x outstanding srb count=%d \n",
837cc3b439cSSascha Wildner 			acb->pci_unit, srb, srb->srb_state, acb->srboutstandingcount);
8381901a965SSascha Wildner 		return;
8391901a965SSascha Wildner 	}
8401901a965SSascha Wildner 	arcmsr_report_srb_state(acb, srb, error);
8411901a965SSascha Wildner }
8421901a965SSascha Wildner /*
843cc3b439cSSascha Wildner **************************************************************************
844cc3b439cSSascha Wildner **************************************************************************
845cc3b439cSSascha Wildner */
arcmsr_srb_timeout(void * arg)846cc3b439cSSascha Wildner static void	arcmsr_srb_timeout(void *arg)
847cc3b439cSSascha Wildner {
848cc3b439cSSascha Wildner 	struct CommandControlBlock *srb = (struct CommandControlBlock *)arg;
849cc3b439cSSascha Wildner 	struct AdapterControlBlock *acb;
850cc3b439cSSascha Wildner 	int target, lun;
851cc3b439cSSascha Wildner 	u_int8_t cmd;
852cc3b439cSSascha Wildner 
853cc3b439cSSascha Wildner 	target = srb->pccb->ccb_h.target_id;
854cc3b439cSSascha Wildner 	lun = srb->pccb->ccb_h.target_lun;
855cc3b439cSSascha Wildner 	acb = srb->acb;
856cc3b439cSSascha Wildner 	if(srb->srb_state == ARCMSR_SRB_START)
857cc3b439cSSascha Wildner 	{
858cc3b439cSSascha Wildner 		cmd = srb->pccb->csio.cdb_io.cdb_bytes[0];
859cc3b439cSSascha Wildner 		srb->srb_state = ARCMSR_SRB_TIMEOUT;
860cc3b439cSSascha Wildner 		srb->pccb->ccb_h.status |= CAM_CMD_TIMEOUT;
861cc3b439cSSascha Wildner 		arcmsr_srb_complete(srb, 1);
862cc3b439cSSascha Wildner 		kprintf("arcmsr%d: scsi id %d lun %d cmd=0x%x srb='%p' ccb command time out!\n",
863cc3b439cSSascha Wildner 				 acb->pci_unit, target, lun, cmd, srb);
864cc3b439cSSascha Wildner 	}
865cc3b439cSSascha Wildner #ifdef ARCMSR_DEBUG1
866cc3b439cSSascha Wildner 	arcmsr_dump_data(acb);
867cc3b439cSSascha Wildner #endif
868cc3b439cSSascha Wildner }
869cc3b439cSSascha Wildner 
870cc3b439cSSascha Wildner /*
8711901a965SSascha Wildner **********************************************************************
8721901a965SSascha Wildner **********************************************************************
8731901a965SSascha Wildner */
arcmsr_done4abort_postqueue(struct AdapterControlBlock * acb)8741901a965SSascha Wildner static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
8751901a965SSascha Wildner {
8761901a965SSascha Wildner 	int i=0;
8771901a965SSascha Wildner 	u_int32_t flag_srb;
8781901a965SSascha Wildner 	u_int16_t error;
8791901a965SSascha Wildner 
8801901a965SSascha Wildner 	switch (acb->adapter_type) {
8811901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_A: {
8821901a965SSascha Wildner 			u_int32_t outbound_intstatus;
8831901a965SSascha Wildner 
8841901a965SSascha Wildner 			/*clear and abort all outbound posted Q*/
8851901a965SSascha Wildner 			outbound_intstatus = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable;
8861901a965SSascha Wildner 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/
8871901a965SSascha Wildner 			while(((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_queueport)) != 0xFFFFFFFF) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) {
8881901a965SSascha Wildner 				error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
8891901a965SSascha Wildner 				arcmsr_drain_donequeue(acb, flag_srb, error);
8901901a965SSascha Wildner 			}
8911901a965SSascha Wildner 		}
8921901a965SSascha Wildner 		break;
8931901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_B: {
8941901a965SSascha Wildner 			struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu;
8951901a965SSascha Wildner 
8961901a965SSascha Wildner 			/*clear all outbound posted Q*/
897111d54bfSSascha Wildner 			WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */
8981901a965SSascha Wildner 			for(i=0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) {
8991901a965SSascha Wildner 				if((flag_srb = phbbmu->done_qbuffer[i]) != 0) {
9001901a965SSascha Wildner 					phbbmu->done_qbuffer[i] = 0;
9011901a965SSascha Wildner 					error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
9021901a965SSascha Wildner 					arcmsr_drain_donequeue(acb, flag_srb, error);
9031901a965SSascha Wildner 				}
9041901a965SSascha Wildner 				phbbmu->post_qbuffer[i] = 0;
9051901a965SSascha Wildner 			}/*drain reply FIFO*/
9061901a965SSascha Wildner 			phbbmu->doneq_index = 0;
9071901a965SSascha Wildner 			phbbmu->postq_index = 0;
9081901a965SSascha Wildner 		}
9091901a965SSascha Wildner 		break;
9101901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_C: {
9111901a965SSascha Wildner 
9121901a965SSascha Wildner 			while((CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) {
9131901a965SSascha Wildner 				flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low);
9141901a965SSascha Wildner 				error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
9151901a965SSascha Wildner 				arcmsr_drain_donequeue(acb, flag_srb, error);
9161901a965SSascha Wildner 			}
9171901a965SSascha Wildner 		}
9181901a965SSascha Wildner 		break;
919cec1e926SSascha Wildner 	case ACB_ADAPTER_TYPE_D: {
920cec1e926SSascha Wildner 			arcmsr_hbd_postqueue_isr(acb);
921cec1e926SSascha Wildner 		}
922cec1e926SSascha Wildner 		break;
923111d54bfSSascha Wildner 	case ACB_ADAPTER_TYPE_E: {
924111d54bfSSascha Wildner 			arcmsr_hbe_postqueue_isr(acb);
925111d54bfSSascha Wildner 		}
926111d54bfSSascha Wildner 		break;
9271901a965SSascha Wildner 	}
9281901a965SSascha Wildner }
9291901a965SSascha Wildner /*
9301901a965SSascha Wildner ****************************************************************************
9311901a965SSascha Wildner ****************************************************************************
9321901a965SSascha Wildner */
arcmsr_iop_reset(struct AdapterControlBlock * acb)9331901a965SSascha Wildner static void arcmsr_iop_reset(struct AdapterControlBlock *acb)
9341901a965SSascha Wildner {
9351901a965SSascha Wildner 	struct CommandControlBlock *srb;
9361901a965SSascha Wildner 	u_int32_t intmask_org;
9371901a965SSascha Wildner 	u_int32_t i=0;
9381901a965SSascha Wildner 
9391901a965SSascha Wildner 	if(acb->srboutstandingcount>0) {
9401901a965SSascha Wildner 		/* disable all outbound interrupt */
9411901a965SSascha Wildner 		intmask_org = arcmsr_disable_allintr(acb);
9421901a965SSascha Wildner 		/*clear and abort all outbound posted Q*/
9431901a965SSascha Wildner 		arcmsr_done4abort_postqueue(acb);
9441901a965SSascha Wildner 		/* talk to iop 331 outstanding command aborted*/
9451901a965SSascha Wildner 		arcmsr_abort_allcmd(acb);
9461901a965SSascha Wildner 		for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) {
9471901a965SSascha Wildner 			srb = acb->psrb_pool[i];
948cc3b439cSSascha Wildner 			if(srb->srb_state == ARCMSR_SRB_START) {
949cc3b439cSSascha Wildner 				srb->srb_state = ARCMSR_SRB_ABORTED;
9501901a965SSascha Wildner 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
9511901a965SSascha Wildner 				arcmsr_srb_complete(srb, 1);
952cec1e926SSascha Wildner 				kprintf("arcmsr%d: scsi id=%d lun=%jx srb='%p' aborted\n"
953cc3b439cSSascha Wildner 						, acb->pci_unit, srb->pccb->ccb_h.target_id
954cec1e926SSascha Wildner 						, (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
9551901a965SSascha Wildner 			}
9561901a965SSascha Wildner 		}
9571901a965SSascha Wildner 		/* enable all outbound interrupt */
9581901a965SSascha Wildner 		arcmsr_enable_allintr(acb, intmask_org);
9591901a965SSascha Wildner 	}
960cc3b439cSSascha Wildner 	acb->srboutstandingcount = 0;
9611901a965SSascha Wildner 	acb->workingsrb_doneindex = 0;
9621901a965SSascha Wildner 	acb->workingsrb_startindex = 0;
963cc3b439cSSascha Wildner 	acb->pktRequestCount = 0;
964cc3b439cSSascha Wildner 	acb->pktReturnCount = 0;
9651901a965SSascha Wildner }
9661901a965SSascha Wildner /*
9671901a965SSascha Wildner **********************************************************************
9681901a965SSascha Wildner **********************************************************************
9691901a965SSascha Wildner */
arcmsr_build_srb(struct CommandControlBlock * srb,bus_dma_segment_t * dm_segs,u_int32_t nseg)9701901a965SSascha Wildner static void arcmsr_build_srb(struct CommandControlBlock *srb,
9711901a965SSascha Wildner 		bus_dma_segment_t *dm_segs, u_int32_t nseg)
9721901a965SSascha Wildner {
9731901a965SSascha Wildner 	struct ARCMSR_CDB *arcmsr_cdb = &srb->arcmsr_cdb;
9741901a965SSascha Wildner 	u_int8_t *psge = (u_int8_t *)&arcmsr_cdb->u;
9751901a965SSascha Wildner 	u_int32_t address_lo, address_hi;
9761901a965SSascha Wildner 	union ccb *pccb = srb->pccb;
9771901a965SSascha Wildner 	struct ccb_scsiio *pcsio = &pccb->csio;
9781901a965SSascha Wildner 	u_int32_t arccdbsize = 0x30;
9791901a965SSascha Wildner 
9801901a965SSascha Wildner 	memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB));
9811901a965SSascha Wildner 	arcmsr_cdb->Bus = 0;
9821901a965SSascha Wildner 	arcmsr_cdb->TargetID = pccb->ccb_h.target_id;
9831901a965SSascha Wildner 	arcmsr_cdb->LUN = pccb->ccb_h.target_lun;
9841901a965SSascha Wildner 	arcmsr_cdb->Function = 1;
9851901a965SSascha Wildner 	arcmsr_cdb->CdbLength = (u_int8_t)pcsio->cdb_len;
9861901a965SSascha Wildner 	bcopy(pcsio->cdb_io.cdb_bytes, arcmsr_cdb->Cdb, pcsio->cdb_len);
9871901a965SSascha Wildner 	if(nseg != 0) {
9881901a965SSascha Wildner 		struct AdapterControlBlock *acb = srb->acb;
9891901a965SSascha Wildner 		bus_dmasync_op_t op;
9901901a965SSascha Wildner 		u_int32_t length, i, cdb_sgcount = 0;
9911901a965SSascha Wildner 
9921901a965SSascha Wildner 		if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
9931901a965SSascha Wildner 			op = BUS_DMASYNC_PREREAD;
9941901a965SSascha Wildner 		} else {
9951901a965SSascha Wildner 			op = BUS_DMASYNC_PREWRITE;
9961901a965SSascha Wildner 			arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE;
9971901a965SSascha Wildner 			srb->srb_flags |= SRB_FLAG_WRITE;
9981901a965SSascha Wildner 		}
9991901a965SSascha Wildner 		bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op);
10001901a965SSascha Wildner 		for(i=0; i < nseg; i++) {
10011901a965SSascha Wildner 			/* Get the physical address of the current data pointer */
10021901a965SSascha Wildner 			length = arcmsr_htole32(dm_segs[i].ds_len);
10031901a965SSascha Wildner 			address_lo = arcmsr_htole32(dma_addr_lo32(dm_segs[i].ds_addr));
10041901a965SSascha Wildner 			address_hi = arcmsr_htole32(dma_addr_hi32(dm_segs[i].ds_addr));
10051901a965SSascha Wildner 			if(address_hi == 0) {
10061901a965SSascha Wildner 				struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge;
10071901a965SSascha Wildner 				pdma_sg->address = address_lo;
10081901a965SSascha Wildner 				pdma_sg->length = length;
10091901a965SSascha Wildner 				psge += sizeof(struct SG32ENTRY);
10101901a965SSascha Wildner 				arccdbsize += sizeof(struct SG32ENTRY);
10111901a965SSascha Wildner 			} else {
10121901a965SSascha Wildner 				u_int32_t sg64s_size = 0, tmplength = length;
10131901a965SSascha Wildner 
10141901a965SSascha Wildner 				while(1) {
10151901a965SSascha Wildner 					u_int64_t span4G, length0;
10161901a965SSascha Wildner 					struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge;
10171901a965SSascha Wildner 
10181901a965SSascha Wildner 					span4G = (u_int64_t)address_lo + tmplength;
10191901a965SSascha Wildner 					pdma_sg->addresshigh = address_hi;
10201901a965SSascha Wildner 					pdma_sg->address = address_lo;
10211901a965SSascha Wildner 					if(span4G > 0x100000000) {
10221901a965SSascha Wildner 						/*see if cross 4G boundary*/
10231901a965SSascha Wildner 						length0 = 0x100000000-address_lo;
10241901a965SSascha Wildner 						pdma_sg->length = (u_int32_t)length0 | IS_SG64_ADDR;
10251901a965SSascha Wildner 						address_hi = address_hi+1;
10261901a965SSascha Wildner 						address_lo = 0;
10271901a965SSascha Wildner 						tmplength = tmplength - (u_int32_t)length0;
10281901a965SSascha Wildner 						sg64s_size += sizeof(struct SG64ENTRY);
10291901a965SSascha Wildner 						psge += sizeof(struct SG64ENTRY);
10301901a965SSascha Wildner 						cdb_sgcount++;
10311901a965SSascha Wildner 					} else {
10321901a965SSascha Wildner 						pdma_sg->length = tmplength | IS_SG64_ADDR;
10331901a965SSascha Wildner 						sg64s_size += sizeof(struct SG64ENTRY);
10341901a965SSascha Wildner 						psge += sizeof(struct SG64ENTRY);
10351901a965SSascha Wildner 						break;
10361901a965SSascha Wildner 					}
10371901a965SSascha Wildner 				}
10381901a965SSascha Wildner 				arccdbsize += sg64s_size;
10391901a965SSascha Wildner 			}
10401901a965SSascha Wildner 			cdb_sgcount++;
10411901a965SSascha Wildner 		}
10421901a965SSascha Wildner 		arcmsr_cdb->sgcount = (u_int8_t)cdb_sgcount;
10431901a965SSascha Wildner 		arcmsr_cdb->DataLength = pcsio->dxfer_len;
10441901a965SSascha Wildner 		if( arccdbsize > 256) {
10451901a965SSascha Wildner 			arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE;
10461901a965SSascha Wildner 		}
10471901a965SSascha Wildner 	} else {
10481901a965SSascha Wildner 		arcmsr_cdb->DataLength = 0;
10491901a965SSascha Wildner 	}
10501901a965SSascha Wildner 	srb->arc_cdb_size = arccdbsize;
1051cec1e926SSascha Wildner 	arcmsr_cdb->msgPages = (arccdbsize/256) + ((arccdbsize % 256) ? 1 : 0);
10521901a965SSascha Wildner }
10531901a965SSascha Wildner /*
10541901a965SSascha Wildner **************************************************************************
10551901a965SSascha Wildner **************************************************************************
10561901a965SSascha Wildner */
arcmsr_post_srb(struct AdapterControlBlock * acb,struct CommandControlBlock * srb)10571901a965SSascha Wildner static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandControlBlock *srb)
10581901a965SSascha Wildner {
1059cec1e926SSascha Wildner 	u_int32_t cdb_phyaddr_low = (u_int32_t) srb->cdb_phyaddr_low;
10601901a965SSascha Wildner 	struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&srb->arcmsr_cdb;
10611901a965SSascha Wildner 
10621901a965SSascha Wildner 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, (srb->srb_flags & SRB_FLAG_WRITE) ? BUS_DMASYNC_POSTWRITE:BUS_DMASYNC_POSTREAD);
10631901a965SSascha Wildner 	atomic_add_int(&acb->srboutstandingcount, 1);
1064cc3b439cSSascha Wildner 	srb->srb_state = ARCMSR_SRB_START;
10651901a965SSascha Wildner 
10661901a965SSascha Wildner 	switch (acb->adapter_type) {
10671901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_A: {
10681901a965SSascha Wildner 			if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) {
1069cec1e926SSascha Wildner 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_phyaddr_low|ARCMSR_SRBPOST_FLAG_SGL_BSIZE);
10701901a965SSascha Wildner 			} else {
1071cec1e926SSascha Wildner 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_phyaddr_low);
10721901a965SSascha Wildner 			}
10731901a965SSascha Wildner 		}
10741901a965SSascha Wildner 		break;
10751901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_B: {
10761901a965SSascha Wildner 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
10771901a965SSascha Wildner 			int ending_index, index;
10781901a965SSascha Wildner 
10791901a965SSascha Wildner 			index = phbbmu->postq_index;
10801901a965SSascha Wildner 			ending_index = ((index+1) % ARCMSR_MAX_HBB_POSTQUEUE);
10811901a965SSascha Wildner 			phbbmu->post_qbuffer[ending_index] = 0;
10821901a965SSascha Wildner 			if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) {
1083cec1e926SSascha Wildner 				phbbmu->post_qbuffer[index] = cdb_phyaddr_low | ARCMSR_SRBPOST_FLAG_SGL_BSIZE;
10841901a965SSascha Wildner 			} else {
1085cec1e926SSascha Wildner 				phbbmu->post_qbuffer[index] = cdb_phyaddr_low;
10861901a965SSascha Wildner 			}
10871901a965SSascha Wildner 			index++;
10881901a965SSascha Wildner 			index %= ARCMSR_MAX_HBB_POSTQUEUE;     /*if last index number set it to 0 */
10891901a965SSascha Wildner 			phbbmu->postq_index = index;
1090111d54bfSSascha Wildner 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED);
10911901a965SSascha Wildner 		}
10921901a965SSascha Wildner 		break;
1093cec1e926SSascha Wildner 	case ACB_ADAPTER_TYPE_C: {
10941901a965SSascha Wildner 			u_int32_t ccb_post_stamp, arc_cdb_size, cdb_phyaddr_hi32;
10951901a965SSascha Wildner 
10961901a965SSascha Wildner 			arc_cdb_size = (srb->arc_cdb_size > 0x300) ? 0x300 : srb->arc_cdb_size;
1097cec1e926SSascha Wildner 			ccb_post_stamp = (cdb_phyaddr_low | ((arc_cdb_size-1) >> 6) | 1);
10981901a965SSascha Wildner 			cdb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high;
10991901a965SSascha Wildner 			if(cdb_phyaddr_hi32)
11001901a965SSascha Wildner 			{
11011901a965SSascha Wildner 				CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_high, cdb_phyaddr_hi32);
11021901a965SSascha Wildner 				CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp);
11031901a965SSascha Wildner 			}
11041901a965SSascha Wildner 			else
11051901a965SSascha Wildner 			{
11061901a965SSascha Wildner 				CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp);
11071901a965SSascha Wildner 			}
11081901a965SSascha Wildner 		}
11091901a965SSascha Wildner 		break;
1110cec1e926SSascha Wildner 	case ACB_ADAPTER_TYPE_D: {
1111cec1e926SSascha Wildner 			struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
1112cec1e926SSascha Wildner 			u_int16_t index_stripped;
1113cec1e926SSascha Wildner 			u_int16_t postq_index;
1114cec1e926SSascha Wildner 			struct InBound_SRB *pinbound_srb;
1115cec1e926SSascha Wildner 
1116cec1e926SSascha Wildner 			ARCMSR_LOCK_ACQUIRE(&acb->postDone_lock);
1117cec1e926SSascha Wildner 			postq_index = phbdmu->postq_index;
1118cec1e926SSascha Wildner 			pinbound_srb = (struct InBound_SRB *)&phbdmu->post_qbuffer[postq_index & 0xFF];
1119cec1e926SSascha Wildner 			pinbound_srb->addressHigh = srb->cdb_phyaddr_high;
1120cec1e926SSascha Wildner 			pinbound_srb->addressLow = srb->cdb_phyaddr_low;
1121cec1e926SSascha Wildner 			pinbound_srb->length = srb->arc_cdb_size >> 2;
1122cec1e926SSascha Wildner 			arcmsr_cdb->Context = srb->cdb_phyaddr_low;
1123cec1e926SSascha Wildner 			if (postq_index & 0x4000) {
1124cec1e926SSascha Wildner 				index_stripped = postq_index & 0xFF;
1125cec1e926SSascha Wildner 				index_stripped += 1;
1126cec1e926SSascha Wildner 				index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
1127cec1e926SSascha Wildner 				phbdmu->postq_index = index_stripped ? (index_stripped | 0x4000) : index_stripped;
1128cec1e926SSascha Wildner 			} else {
1129cec1e926SSascha Wildner 				index_stripped = postq_index;
1130cec1e926SSascha Wildner 				index_stripped += 1;
1131cec1e926SSascha Wildner 				index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
1132cec1e926SSascha Wildner 				phbdmu->postq_index = index_stripped ? index_stripped : (index_stripped | 0x4000);
1133cec1e926SSascha Wildner 			}
1134cec1e926SSascha Wildner 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, inboundlist_write_pointer, postq_index);
1135cec1e926SSascha Wildner 			ARCMSR_LOCK_RELEASE(&acb->postDone_lock);
1136cec1e926SSascha Wildner 		}
1137cec1e926SSascha Wildner 		break;
1138111d54bfSSascha Wildner 	case ACB_ADAPTER_TYPE_E: {
1139111d54bfSSascha Wildner 			u_int32_t ccb_post_stamp, arc_cdb_size;
1140111d54bfSSascha Wildner 
1141111d54bfSSascha Wildner 			arc_cdb_size = (srb->arc_cdb_size > 0x300) ? 0x300 : srb->arc_cdb_size;
1142111d54bfSSascha Wildner 			ccb_post_stamp = (srb->smid | ((arc_cdb_size-1) >> 6));
1143111d54bfSSascha Wildner 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_queueport_high, 0);
1144111d54bfSSascha Wildner 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_queueport_low, ccb_post_stamp);
1145111d54bfSSascha Wildner         	}
1146111d54bfSSascha Wildner 		break;
11471901a965SSascha Wildner 	}
11481901a965SSascha Wildner }
11491901a965SSascha Wildner /*
11501901a965SSascha Wildner ************************************************************************
11511901a965SSascha Wildner ************************************************************************
11521901a965SSascha Wildner */
arcmsr_get_iop_rqbuffer(struct AdapterControlBlock * acb)11531901a965SSascha Wildner static struct QBUFFER *arcmsr_get_iop_rqbuffer( struct AdapterControlBlock *acb)
11541901a965SSascha Wildner {
11551901a965SSascha Wildner 	struct QBUFFER *qbuffer=NULL;
11561901a965SSascha Wildner 
11571901a965SSascha Wildner 	switch (acb->adapter_type) {
11581901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_A: {
11591901a965SSascha Wildner 			struct HBA_MessageUnit *phbamu = (struct HBA_MessageUnit *)acb->pmu;
11601901a965SSascha Wildner 
11611901a965SSascha Wildner 			qbuffer = (struct QBUFFER *)&phbamu->message_rbuffer;
11621901a965SSascha Wildner 		}
11631901a965SSascha Wildner 		break;
11641901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_B: {
11651901a965SSascha Wildner 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
11661901a965SSascha Wildner 
11671901a965SSascha Wildner 			qbuffer = (struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_rbuffer;
11681901a965SSascha Wildner 		}
11691901a965SSascha Wildner 		break;
11701901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_C: {
11711901a965SSascha Wildner 			struct HBC_MessageUnit *phbcmu = (struct HBC_MessageUnit *)acb->pmu;
11721901a965SSascha Wildner 
11731901a965SSascha Wildner 			qbuffer = (struct QBUFFER *)&phbcmu->message_rbuffer;
11741901a965SSascha Wildner 		}
11751901a965SSascha Wildner 		break;
1176cec1e926SSascha Wildner 	case ACB_ADAPTER_TYPE_D: {
1177cec1e926SSascha Wildner 			struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
1178cec1e926SSascha Wildner 
1179cec1e926SSascha Wildner 			qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_rbuffer;
1180cec1e926SSascha Wildner 		}
1181cec1e926SSascha Wildner 		break;
1182111d54bfSSascha Wildner 	case ACB_ADAPTER_TYPE_E: {
1183111d54bfSSascha Wildner 			struct HBE_MessageUnit *phbcmu = (struct HBE_MessageUnit *)acb->pmu;
1184111d54bfSSascha Wildner 
1185111d54bfSSascha Wildner 			qbuffer = (struct QBUFFER *)&phbcmu->message_rbuffer;
1186111d54bfSSascha Wildner 		}
1187111d54bfSSascha Wildner 		break;
11881901a965SSascha Wildner 	}
11891901a965SSascha Wildner 	return(qbuffer);
11901901a965SSascha Wildner }
11911901a965SSascha Wildner /*
11921901a965SSascha Wildner ************************************************************************
11931901a965SSascha Wildner ************************************************************************
11941901a965SSascha Wildner */
arcmsr_get_iop_wqbuffer(struct AdapterControlBlock * acb)11951901a965SSascha Wildner static struct QBUFFER *arcmsr_get_iop_wqbuffer( struct AdapterControlBlock *acb)
11961901a965SSascha Wildner {
11971901a965SSascha Wildner 	struct QBUFFER *qbuffer = NULL;
11981901a965SSascha Wildner 
11991901a965SSascha Wildner 	switch (acb->adapter_type) {
12001901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_A: {
12011901a965SSascha Wildner 			struct HBA_MessageUnit *phbamu = (struct HBA_MessageUnit *)acb->pmu;
12021901a965SSascha Wildner 
12031901a965SSascha Wildner 			qbuffer = (struct QBUFFER *)&phbamu->message_wbuffer;
12041901a965SSascha Wildner 		}
12051901a965SSascha Wildner 		break;
12061901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_B: {
12071901a965SSascha Wildner 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
12081901a965SSascha Wildner 
12091901a965SSascha Wildner 			qbuffer = (struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_wbuffer;
12101901a965SSascha Wildner 		}
12111901a965SSascha Wildner 		break;
12121901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_C: {
12131901a965SSascha Wildner 			struct HBC_MessageUnit *phbcmu = (struct HBC_MessageUnit *)acb->pmu;
12141901a965SSascha Wildner 
12151901a965SSascha Wildner 			qbuffer = (struct QBUFFER *)&phbcmu->message_wbuffer;
12161901a965SSascha Wildner 		}
12171901a965SSascha Wildner 		break;
1218cec1e926SSascha Wildner 	case ACB_ADAPTER_TYPE_D: {
1219cec1e926SSascha Wildner 			struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
1220cec1e926SSascha Wildner 
1221cec1e926SSascha Wildner 			qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_wbuffer;
1222cec1e926SSascha Wildner 		}
1223cec1e926SSascha Wildner 		break;
1224111d54bfSSascha Wildner 	case ACB_ADAPTER_TYPE_E: {
1225111d54bfSSascha Wildner 			struct HBE_MessageUnit *phbcmu = (struct HBE_MessageUnit *)acb->pmu;
1226111d54bfSSascha Wildner 
1227111d54bfSSascha Wildner 			qbuffer = (struct QBUFFER *)&phbcmu->message_wbuffer;
1228111d54bfSSascha Wildner 		}
1229111d54bfSSascha Wildner 		break;
12301901a965SSascha Wildner 	}
12311901a965SSascha Wildner 	return(qbuffer);
12321901a965SSascha Wildner }
12331901a965SSascha Wildner /*
12341901a965SSascha Wildner **************************************************************************
12351901a965SSascha Wildner **************************************************************************
12361901a965SSascha Wildner */
arcmsr_iop_message_read(struct AdapterControlBlock * acb)12371901a965SSascha Wildner static void arcmsr_iop_message_read(struct AdapterControlBlock *acb)
12381901a965SSascha Wildner {
12391901a965SSascha Wildner 	switch (acb->adapter_type) {
12401901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_A: {
12411901a965SSascha Wildner 			/* let IOP know data has been read */
12421901a965SSascha Wildner 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
12431901a965SSascha Wildner 		}
12441901a965SSascha Wildner 		break;
12451901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_B: {
1246111d54bfSSascha Wildner 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
12471901a965SSascha Wildner 			/* let IOP know data has been read */
1248111d54bfSSascha Wildner 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK);
12491901a965SSascha Wildner 		}
12501901a965SSascha Wildner 		break;
12511901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_C: {
12521901a965SSascha Wildner 			/* let IOP know data has been read */
12531901a965SSascha Wildner 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK);
12541901a965SSascha Wildner 		}
1255cec1e926SSascha Wildner 		break;
1256cec1e926SSascha Wildner 	case ACB_ADAPTER_TYPE_D: {
1257cec1e926SSascha Wildner 			/* let IOP know data has been read */
1258cec1e926SSascha Wildner 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ);
1259cec1e926SSascha Wildner 		}
1260cec1e926SSascha Wildner 		break;
1261111d54bfSSascha Wildner 	case ACB_ADAPTER_TYPE_E: {
1262111d54bfSSascha Wildner 			/* let IOP know data has been read */
1263111d54bfSSascha Wildner 			acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK;
1264111d54bfSSascha Wildner 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
1265111d54bfSSascha Wildner 		}
1266111d54bfSSascha Wildner 		break;
12671901a965SSascha Wildner 	}
12681901a965SSascha Wildner }
12691901a965SSascha Wildner /*
12701901a965SSascha Wildner **************************************************************************
12711901a965SSascha Wildner **************************************************************************
12721901a965SSascha Wildner */
arcmsr_iop_message_wrote(struct AdapterControlBlock * acb)12731901a965SSascha Wildner static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb)
12741901a965SSascha Wildner {
12751901a965SSascha Wildner 	switch (acb->adapter_type) {
12761901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_A: {
12771901a965SSascha Wildner 			/*
12781901a965SSascha Wildner 			** push inbound doorbell tell iop, driver data write ok
12791901a965SSascha Wildner 			** and wait reply on next hwinterrupt for next Qbuffer post
12801901a965SSascha Wildner 			*/
12811901a965SSascha Wildner 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK);
12821901a965SSascha Wildner 		}
12831901a965SSascha Wildner 		break;
12841901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_B: {
1285111d54bfSSascha Wildner 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
12861901a965SSascha Wildner 			/*
12871901a965SSascha Wildner 			** push inbound doorbell tell iop, driver data write ok
12881901a965SSascha Wildner 			** and wait reply on next hwinterrupt for next Qbuffer post
12891901a965SSascha Wildner 			*/
1290111d54bfSSascha Wildner 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_WRITE_OK);
12911901a965SSascha Wildner 		}
12921901a965SSascha Wildner 		break;
12931901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_C: {
12941901a965SSascha Wildner 			/*
12951901a965SSascha Wildner 			** push inbound doorbell tell iop, driver data write ok
12961901a965SSascha Wildner 			** and wait reply on next hwinterrupt for next Qbuffer post
12971901a965SSascha Wildner 			*/
12981901a965SSascha Wildner 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK);
12991901a965SSascha Wildner 		}
13001901a965SSascha Wildner 		break;
1301cec1e926SSascha Wildner 	case ACB_ADAPTER_TYPE_D: {
13021901a965SSascha Wildner 			/*
1303cec1e926SSascha Wildner 			** push inbound doorbell tell iop, driver data write ok
1304cec1e926SSascha Wildner 			** and wait reply on next hwinterrupt for next Qbuffer post
13051901a965SSascha Wildner 			*/
1306cec1e926SSascha Wildner 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_IN_READY);
13071901a965SSascha Wildner 		}
1308cec1e926SSascha Wildner 		break;
1309111d54bfSSascha Wildner 	case ACB_ADAPTER_TYPE_E: {
1310111d54bfSSascha Wildner 			/*
1311111d54bfSSascha Wildner 			** push inbound doorbell tell iop, driver data write ok
1312111d54bfSSascha Wildner 			** and wait reply on next hwinterrupt for next Qbuffer post
1313111d54bfSSascha Wildner 			*/
1314111d54bfSSascha Wildner 			acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_WRITE_OK;
1315111d54bfSSascha Wildner 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
1316111d54bfSSascha Wildner 		}
1317111d54bfSSascha Wildner 		break;
13181901a965SSascha Wildner 	}
13191901a965SSascha Wildner }
13201901a965SSascha Wildner /*
13211901a965SSascha Wildner ************************************************************************
13221901a965SSascha Wildner ************************************************************************
13231901a965SSascha Wildner */
arcmsr_stop_hba_bgrb(struct AdapterControlBlock * acb)13241901a965SSascha Wildner static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb)
13251901a965SSascha Wildner {
13261901a965SSascha Wildner 	acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
13271901a965SSascha Wildner 	CHIP_REG_WRITE32(HBA_MessageUnit,
13281901a965SSascha Wildner 		0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
13291901a965SSascha Wildner 	if(!arcmsr_hba_wait_msgint_ready(acb)) {
1330111d54bfSSascha Wildner 		kprintf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n"
13311901a965SSascha Wildner 			, acb->pci_unit);
13321901a965SSascha Wildner 	}
13331901a965SSascha Wildner }
13341901a965SSascha Wildner /*
13351901a965SSascha Wildner ************************************************************************
13361901a965SSascha Wildner ************************************************************************
13371901a965SSascha Wildner */
arcmsr_stop_hbb_bgrb(struct AdapterControlBlock * acb)13381901a965SSascha Wildner static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb)
13391901a965SSascha Wildner {
1340111d54bfSSascha Wildner 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
13411901a965SSascha Wildner 	acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
1342111d54bfSSascha Wildner 	WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_STOP_BGRB);
13431901a965SSascha Wildner 	if(!arcmsr_hbb_wait_msgint_ready(acb)) {
1344111d54bfSSascha Wildner 		kprintf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n"
13451901a965SSascha Wildner 			, acb->pci_unit);
13461901a965SSascha Wildner 	}
13471901a965SSascha Wildner }
13481901a965SSascha Wildner /*
13491901a965SSascha Wildner ************************************************************************
13501901a965SSascha Wildner ************************************************************************
13511901a965SSascha Wildner */
arcmsr_stop_hbc_bgrb(struct AdapterControlBlock * acb)13521901a965SSascha Wildner static void arcmsr_stop_hbc_bgrb(struct AdapterControlBlock *acb)
13531901a965SSascha Wildner {
13541901a965SSascha Wildner 	acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
13551901a965SSascha Wildner 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
13561901a965SSascha Wildner 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
13571901a965SSascha Wildner 	if(!arcmsr_hbc_wait_msgint_ready(acb)) {
1358111d54bfSSascha Wildner 		kprintf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit);
13591901a965SSascha Wildner 	}
13601901a965SSascha Wildner }
13611901a965SSascha Wildner /*
13621901a965SSascha Wildner ************************************************************************
13631901a965SSascha Wildner ************************************************************************
13641901a965SSascha Wildner */
arcmsr_stop_hbd_bgrb(struct AdapterControlBlock * acb)1365cec1e926SSascha Wildner static void arcmsr_stop_hbd_bgrb(struct AdapterControlBlock *acb)
1366cec1e926SSascha Wildner {
1367cec1e926SSascha Wildner 	acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
1368cec1e926SSascha Wildner 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
1369cec1e926SSascha Wildner 	if(!arcmsr_hbd_wait_msgint_ready(acb)) {
1370cec1e926SSascha Wildner 		kprintf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit);
1371cec1e926SSascha Wildner 	}
1372cec1e926SSascha Wildner }
1373cec1e926SSascha Wildner /*
1374cec1e926SSascha Wildner ************************************************************************
1375cec1e926SSascha Wildner ************************************************************************
1376cec1e926SSascha Wildner */
arcmsr_stop_hbe_bgrb(struct AdapterControlBlock * acb)1377111d54bfSSascha Wildner static void arcmsr_stop_hbe_bgrb(struct AdapterControlBlock *acb)
1378111d54bfSSascha Wildner {
1379111d54bfSSascha Wildner 	acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
1380111d54bfSSascha Wildner 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
1381111d54bfSSascha Wildner 	acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
1382111d54bfSSascha Wildner 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
1383111d54bfSSascha Wildner 	if(!arcmsr_hbe_wait_msgint_ready(acb)) {
1384111d54bfSSascha Wildner 		kprintf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit);
1385111d54bfSSascha Wildner 	}
1386111d54bfSSascha Wildner }
1387111d54bfSSascha Wildner /*
1388111d54bfSSascha Wildner ************************************************************************
1389111d54bfSSascha Wildner ************************************************************************
1390111d54bfSSascha Wildner */
arcmsr_stop_adapter_bgrb(struct AdapterControlBlock * acb)13911901a965SSascha Wildner static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
13921901a965SSascha Wildner {
13931901a965SSascha Wildner 	switch (acb->adapter_type) {
13941901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_A: {
13951901a965SSascha Wildner 			arcmsr_stop_hba_bgrb(acb);
13961901a965SSascha Wildner 		}
13971901a965SSascha Wildner 		break;
13981901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_B: {
13991901a965SSascha Wildner 			arcmsr_stop_hbb_bgrb(acb);
14001901a965SSascha Wildner 		}
14011901a965SSascha Wildner 		break;
14021901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_C: {
14031901a965SSascha Wildner 			arcmsr_stop_hbc_bgrb(acb);
14041901a965SSascha Wildner 		}
14051901a965SSascha Wildner 		break;
1406cec1e926SSascha Wildner 	case ACB_ADAPTER_TYPE_D: {
1407cec1e926SSascha Wildner 			arcmsr_stop_hbd_bgrb(acb);
1408cec1e926SSascha Wildner 		}
1409cec1e926SSascha Wildner 		break;
1410111d54bfSSascha Wildner 	case ACB_ADAPTER_TYPE_E: {
1411111d54bfSSascha Wildner 			arcmsr_stop_hbe_bgrb(acb);
1412111d54bfSSascha Wildner 		}
1413111d54bfSSascha Wildner 		break;
14141901a965SSascha Wildner 	}
14151901a965SSascha Wildner }
14161901a965SSascha Wildner /*
14171901a965SSascha Wildner ************************************************************************
14181901a965SSascha Wildner ************************************************************************
14191901a965SSascha Wildner */
arcmsr_poll(struct cam_sim * psim)14201901a965SSascha Wildner static void arcmsr_poll(struct cam_sim *psim)
14211901a965SSascha Wildner {
14221901a965SSascha Wildner 	struct AdapterControlBlock *acb;
1423cc3b439cSSascha Wildner 	int	mutex;
14241901a965SSascha Wildner 
14251901a965SSascha Wildner 	acb = (struct AdapterControlBlock *)cam_sim_softc(psim);
1426cec1e926SSascha Wildner 	mutex = lockstatus(&acb->isr_lock, curthread);
1427cc3b439cSSascha Wildner 	if( mutex == 0 )
1428cec1e926SSascha Wildner 		ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
14291901a965SSascha Wildner 	arcmsr_interrupt(acb);
1430cc3b439cSSascha Wildner 	if( mutex == 0 )
1431cec1e926SSascha Wildner 		ARCMSR_LOCK_RELEASE(&acb->isr_lock);
1432cec1e926SSascha Wildner }
1433cec1e926SSascha Wildner /*
1434cec1e926SSascha Wildner **************************************************************************
1435cec1e926SSascha Wildner **************************************************************************
1436cec1e926SSascha Wildner */
arcmsr_Read_iop_rqbuffer_data_D(struct AdapterControlBlock * acb,struct QBUFFER * prbuffer)1437cec1e926SSascha Wildner static u_int32_t arcmsr_Read_iop_rqbuffer_data_D(struct AdapterControlBlock *acb,
1438cec1e926SSascha Wildner 	struct QBUFFER *prbuffer) {
1439cec1e926SSascha Wildner 
1440cec1e926SSascha Wildner 	u_int8_t *pQbuffer;
1441394b58a3SSascha Wildner 	u_int8_t *buf1 = NULL;
1442394b58a3SSascha Wildner 	u_int32_t *iop_data, *buf2 = NULL;
1443cec1e926SSascha Wildner 	u_int32_t iop_len, data_len;
1444cec1e926SSascha Wildner 
1445cec1e926SSascha Wildner 	iop_data = (u_int32_t *)prbuffer->data;
1446cec1e926SSascha Wildner 	iop_len = (u_int32_t)prbuffer->data_len;
1447cec1e926SSascha Wildner 	if ( iop_len > 0 )
1448cec1e926SSascha Wildner 	{
1449cec1e926SSascha Wildner 		buf1 = kmalloc(128, M_DEVBUF, M_NOWAIT | M_ZERO);
1450cec1e926SSascha Wildner 		buf2 = (u_int32_t *)buf1;
1451cec1e926SSascha Wildner 		if( buf1 == NULL)
1452cec1e926SSascha Wildner 			return (0);
1453cec1e926SSascha Wildner 		data_len = iop_len;
1454cec1e926SSascha Wildner 		while(data_len >= 4)
1455cec1e926SSascha Wildner 		{
1456cec1e926SSascha Wildner 			*buf2++ = *iop_data++;
1457cec1e926SSascha Wildner 			data_len -= 4;
1458cec1e926SSascha Wildner 		}
1459cec1e926SSascha Wildner 		if(data_len)
1460cec1e926SSascha Wildner 			*buf2 = *iop_data;
1461cec1e926SSascha Wildner 		buf2 = (u_int32_t *)buf1;
1462cec1e926SSascha Wildner 	}
1463cec1e926SSascha Wildner 	while (iop_len > 0) {
1464cec1e926SSascha Wildner 		pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex];
1465cec1e926SSascha Wildner 		*pQbuffer = *buf1;
1466cec1e926SSascha Wildner 		acb->rqbuf_lastindex++;
1467cec1e926SSascha Wildner 		/* if last, index number set it to 0 */
1468cec1e926SSascha Wildner 		acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
1469cec1e926SSascha Wildner 		buf1++;
1470cec1e926SSascha Wildner 		iop_len--;
1471cec1e926SSascha Wildner 	}
1472cec1e926SSascha Wildner 	if(buf2)
1473cec1e926SSascha Wildner 		kfree( (u_int8_t *)buf2, M_DEVBUF);
1474cec1e926SSascha Wildner 	/* let IOP know data has been read */
1475cec1e926SSascha Wildner 	arcmsr_iop_message_read(acb);
1476cec1e926SSascha Wildner 	return (1);
1477cec1e926SSascha Wildner }
1478cec1e926SSascha Wildner /*
1479cec1e926SSascha Wildner **************************************************************************
1480cec1e926SSascha Wildner **************************************************************************
1481cec1e926SSascha Wildner */
arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock * acb,struct QBUFFER * prbuffer)1482cec1e926SSascha Wildner static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb,
1483cec1e926SSascha Wildner 	struct QBUFFER *prbuffer) {
1484cec1e926SSascha Wildner 
1485cec1e926SSascha Wildner 	u_int8_t *pQbuffer;
1486cec1e926SSascha Wildner 	u_int8_t *iop_data;
1487cec1e926SSascha Wildner 	u_int32_t iop_len;
1488cec1e926SSascha Wildner 
1489111d54bfSSascha Wildner 	if(acb->adapter_type >= ACB_ADAPTER_TYPE_B) {
1490cec1e926SSascha Wildner 		return(arcmsr_Read_iop_rqbuffer_data_D(acb, prbuffer));
1491cec1e926SSascha Wildner 	}
1492cec1e926SSascha Wildner 	iop_data = (u_int8_t *)prbuffer->data;
1493cec1e926SSascha Wildner 	iop_len = (u_int32_t)prbuffer->data_len;
1494cec1e926SSascha Wildner 	while (iop_len > 0) {
1495cec1e926SSascha Wildner 		pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex];
1496cec1e926SSascha Wildner 		*pQbuffer = *iop_data;
1497cec1e926SSascha Wildner 		acb->rqbuf_lastindex++;
1498cec1e926SSascha Wildner 		/* if last, index number set it to 0 */
1499cec1e926SSascha Wildner 		acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
1500cec1e926SSascha Wildner 		iop_data++;
1501cec1e926SSascha Wildner 		iop_len--;
1502cec1e926SSascha Wildner 	}
1503cec1e926SSascha Wildner 	/* let IOP know data has been read */
1504cec1e926SSascha Wildner 	arcmsr_iop_message_read(acb);
1505cec1e926SSascha Wildner 	return (1);
15061901a965SSascha Wildner }
15071901a965SSascha Wildner /*
15081901a965SSascha Wildner **************************************************************************
15091901a965SSascha Wildner **************************************************************************
15101901a965SSascha Wildner */
arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock * acb)15111901a965SSascha Wildner static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb)
15121901a965SSascha Wildner {
15131901a965SSascha Wildner 	struct QBUFFER *prbuffer;
1514cec1e926SSascha Wildner 	int my_empty_len;
15151901a965SSascha Wildner 
15161901a965SSascha Wildner 	/*check this iop data if overflow my rqbuffer*/
1517cec1e926SSascha Wildner 	ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
15181901a965SSascha Wildner 	prbuffer = arcmsr_get_iop_rqbuffer(acb);
1519cec1e926SSascha Wildner 	my_empty_len = (acb->rqbuf_lastindex - acb->rqbuf_firstindex - 1) &
1520cec1e926SSascha Wildner 		(ARCMSR_MAX_QBUFFER-1);
1521cec1e926SSascha Wildner 	if(my_empty_len >= prbuffer->data_len) {
1522cec1e926SSascha Wildner 		if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
1523cec1e926SSascha Wildner 			acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
15241901a965SSascha Wildner 	} else {
15251901a965SSascha Wildner 		acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
15261901a965SSascha Wildner 	}
1527cec1e926SSascha Wildner 	ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
1528cec1e926SSascha Wildner }
1529cec1e926SSascha Wildner /*
1530cec1e926SSascha Wildner **********************************************************************
1531cec1e926SSascha Wildner **********************************************************************
1532cec1e926SSascha Wildner */
arcmsr_Write_data_2iop_wqbuffer_D(struct AdapterControlBlock * acb)1533cec1e926SSascha Wildner static void arcmsr_Write_data_2iop_wqbuffer_D(struct AdapterControlBlock *acb)
1534cec1e926SSascha Wildner {
1535cec1e926SSascha Wildner 	u_int8_t *pQbuffer;
1536cec1e926SSascha Wildner 	struct QBUFFER *pwbuffer;
1537394b58a3SSascha Wildner 	u_int8_t *buf1 = NULL;
1538394b58a3SSascha Wildner 	u_int32_t *iop_data, *buf2 = NULL;
1539cec1e926SSascha Wildner 	u_int32_t allxfer_len = 0, data_len;
1540cec1e926SSascha Wildner 
1541cec1e926SSascha Wildner 	if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) {
1542cec1e926SSascha Wildner 		buf1 = kmalloc(128, M_DEVBUF, M_NOWAIT | M_ZERO);
1543cec1e926SSascha Wildner 		buf2 = (u_int32_t *)buf1;
1544cec1e926SSascha Wildner 		if( buf1 == NULL)
1545cec1e926SSascha Wildner 			return;
1546cec1e926SSascha Wildner 
1547cec1e926SSascha Wildner 		acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ);
1548cec1e926SSascha Wildner 		pwbuffer = arcmsr_get_iop_wqbuffer(acb);
1549cec1e926SSascha Wildner 		iop_data = (u_int32_t *)pwbuffer->data;
1550cec1e926SSascha Wildner 		while((acb->wqbuf_firstindex != acb->wqbuf_lastindex)
1551cec1e926SSascha Wildner 			&& (allxfer_len < 124)) {
1552cec1e926SSascha Wildner 			pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex];
1553cec1e926SSascha Wildner 			*buf1 = *pQbuffer;
1554cec1e926SSascha Wildner 			acb->wqbuf_firstindex++;
1555cec1e926SSascha Wildner 			acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
1556cec1e926SSascha Wildner 			buf1++;
1557cec1e926SSascha Wildner 			allxfer_len++;
1558cec1e926SSascha Wildner 		}
1559cec1e926SSascha Wildner 		pwbuffer->data_len = allxfer_len;
1560cec1e926SSascha Wildner 		data_len = allxfer_len;
1561cec1e926SSascha Wildner 		buf1 = (u_int8_t *)buf2;
1562cec1e926SSascha Wildner 		while(data_len >= 4)
1563cec1e926SSascha Wildner 		{
1564cec1e926SSascha Wildner 			*iop_data++ = *buf2++;
1565cec1e926SSascha Wildner 			data_len -= 4;
1566cec1e926SSascha Wildner 		}
1567cec1e926SSascha Wildner 		if(data_len)
1568cec1e926SSascha Wildner 			*iop_data = *buf2;
1569cec1e926SSascha Wildner 		kfree( buf1, M_DEVBUF);
1570cec1e926SSascha Wildner 		arcmsr_iop_message_wrote(acb);
1571cec1e926SSascha Wildner 	}
1572cec1e926SSascha Wildner }
1573cec1e926SSascha Wildner /*
1574cec1e926SSascha Wildner **********************************************************************
1575cec1e926SSascha Wildner **********************************************************************
1576cec1e926SSascha Wildner */
arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock * acb)1577cec1e926SSascha Wildner static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb)
1578cec1e926SSascha Wildner {
1579cec1e926SSascha Wildner 	u_int8_t *pQbuffer;
1580cec1e926SSascha Wildner 	struct QBUFFER *pwbuffer;
1581cec1e926SSascha Wildner 	u_int8_t *iop_data;
1582cec1e926SSascha Wildner 	int32_t allxfer_len=0;
1583cec1e926SSascha Wildner 
1584111d54bfSSascha Wildner 	if(acb->adapter_type >= ACB_ADAPTER_TYPE_B) {
1585cec1e926SSascha Wildner 		arcmsr_Write_data_2iop_wqbuffer_D(acb);
1586cec1e926SSascha Wildner 		return;
1587cec1e926SSascha Wildner 	}
1588cec1e926SSascha Wildner 	if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) {
1589cec1e926SSascha Wildner 		acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ);
1590cec1e926SSascha Wildner 		pwbuffer = arcmsr_get_iop_wqbuffer(acb);
1591cec1e926SSascha Wildner 		iop_data = (u_int8_t *)pwbuffer->data;
1592cec1e926SSascha Wildner 		while((acb->wqbuf_firstindex != acb->wqbuf_lastindex)
1593cec1e926SSascha Wildner 			&& (allxfer_len < 124)) {
1594cec1e926SSascha Wildner 			pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex];
1595cec1e926SSascha Wildner 			*iop_data = *pQbuffer;
1596cec1e926SSascha Wildner 			acb->wqbuf_firstindex++;
1597cec1e926SSascha Wildner 			acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
1598cec1e926SSascha Wildner 			iop_data++;
1599cec1e926SSascha Wildner 			allxfer_len++;
1600cec1e926SSascha Wildner 		}
1601cec1e926SSascha Wildner 		pwbuffer->data_len = allxfer_len;
1602cec1e926SSascha Wildner 		arcmsr_iop_message_wrote(acb);
1603cec1e926SSascha Wildner 	}
16041901a965SSascha Wildner }
16051901a965SSascha Wildner /*
16061901a965SSascha Wildner **************************************************************************
16071901a965SSascha Wildner **************************************************************************
16081901a965SSascha Wildner */
arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock * acb)16091901a965SSascha Wildner static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb)
16101901a965SSascha Wildner {
1611cec1e926SSascha Wildner 	ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
16121901a965SSascha Wildner 	acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READ;
16131901a965SSascha Wildner 	/*
16141901a965SSascha Wildner 	*****************************************************************
16151901a965SSascha Wildner 	**   check if there are any mail packages from user space program
16161901a965SSascha Wildner 	**   in my post bag, now is the time to send them into Areca's firmware
16171901a965SSascha Wildner 	*****************************************************************
16181901a965SSascha Wildner 	*/
16191901a965SSascha Wildner 	if(acb->wqbuf_firstindex != acb->wqbuf_lastindex) {
1620cec1e926SSascha Wildner 		arcmsr_Write_data_2iop_wqbuffer(acb);
16211901a965SSascha Wildner 	}
16221901a965SSascha Wildner 	if(acb->wqbuf_firstindex == acb->wqbuf_lastindex) {
16231901a965SSascha Wildner 		acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED;
16241901a965SSascha Wildner 	}
1625cec1e926SSascha Wildner 	ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
16261901a965SSascha Wildner }
1627cec1e926SSascha Wildner /*
1628cec1e926SSascha Wildner **************************************************************************
1629cec1e926SSascha Wildner **************************************************************************
1630cec1e926SSascha Wildner */
arcmsr_rescanLun_cb(struct cam_periph * periph,union ccb * ccb)16311901a965SSascha Wildner static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb)
16321901a965SSascha Wildner {
16331901a965SSascha Wildner /*
16341901a965SSascha Wildner 	if (ccb->ccb_h.status != CAM_REQ_CMP)
1635cec1e926SSascha Wildner 		kprintf("arcmsr_rescanLun_cb: Rescan Target=%x, lun=%x,"
1636cec1e926SSascha Wildner 			"failure status=%x\n", ccb->ccb_h.target_id,
1637cec1e926SSascha Wildner 			ccb->ccb_h.target_lun, ccb->ccb_h.status);
16381901a965SSascha Wildner 	else
16391901a965SSascha Wildner 		kprintf("arcmsr_rescanLun_cb: Rescan lun successfully!\n");
16401901a965SSascha Wildner */
16411901a965SSascha Wildner 	xpt_free_path(ccb->ccb_h.path);
1642*cec957e9SMatthew Dillon 	xpt_free_ccb(&ccb->ccb_h);
16431901a965SSascha Wildner }
16441901a965SSascha Wildner 
arcmsr_rescan_lun(struct AdapterControlBlock * acb,int target,int lun)16451901a965SSascha Wildner static void	arcmsr_rescan_lun(struct AdapterControlBlock *acb, int target, int lun)
16461901a965SSascha Wildner {
16471901a965SSascha Wildner 	struct cam_path     *path;
1648cec1e926SSascha Wildner 	union ccb           *ccb;
16491901a965SSascha Wildner 
1650cec1e926SSascha Wildner 	if ((ccb = (union ccb *)xpt_alloc_ccb()) == NULL)
16511901a965SSascha Wildner 		return;
1652111d54bfSSascha Wildner 	if (xpt_create_path(&path, xpt_periph, cam_sim_path(acb->psim), target, lun) != CAM_REQ_CMP)
1653cec1e926SSascha Wildner 	{
1654*cec957e9SMatthew Dillon 		xpt_free_ccb(&ccb->ccb_h);
1655cec1e926SSascha Wildner 		return;
1656cec1e926SSascha Wildner 	}
1657cec1e926SSascha Wildner 	xpt_setup_ccb(&ccb->ccb_h, path, 5);
1658cec1e926SSascha Wildner 	ccb->ccb_h.func_code = XPT_SCAN_LUN;
1659cec1e926SSascha Wildner 	ccb->ccb_h.cbfcnp = arcmsr_rescanLun_cb;
1660cec1e926SSascha Wildner 	ccb->crcn.flags = CAM_FLAG_NONE;
1661cec1e926SSascha Wildner 	xpt_action(ccb);
16621901a965SSascha Wildner }
16631901a965SSascha Wildner 
16641901a965SSascha Wildner 
arcmsr_abort_dr_ccbs(struct AdapterControlBlock * acb,int target,int lun)16651901a965SSascha Wildner static void arcmsr_abort_dr_ccbs(struct AdapterControlBlock *acb, int target, int lun)
16661901a965SSascha Wildner {
16671901a965SSascha Wildner 	struct CommandControlBlock *srb;
16681901a965SSascha Wildner 	u_int32_t intmask_org;
16691901a965SSascha Wildner 	int i;
16701901a965SSascha Wildner 
16711901a965SSascha Wildner 	/* disable all outbound interrupts */
16721901a965SSascha Wildner 	intmask_org = arcmsr_disable_allintr(acb);
16731901a965SSascha Wildner 	for (i = 0; i < ARCMSR_MAX_FREESRB_NUM; i++)
16741901a965SSascha Wildner 	{
16751901a965SSascha Wildner 		srb = acb->psrb_pool[i];
1676cc3b439cSSascha Wildner 		if (srb->srb_state == ARCMSR_SRB_START)
16771901a965SSascha Wildner 		{
16781901a965SSascha Wildner 			if((target == srb->pccb->ccb_h.target_id) && (lun == srb->pccb->ccb_h.target_lun))
16791901a965SSascha Wildner 			{
1680cc3b439cSSascha Wildner 				srb->srb_state = ARCMSR_SRB_ABORTED;
16811901a965SSascha Wildner 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
16821901a965SSascha Wildner 				arcmsr_srb_complete(srb, 1);
1683cc3b439cSSascha Wildner 				kprintf("arcmsr%d: abort scsi id %d lun %d srb=%p \n", acb->pci_unit, target, lun, srb);
16841901a965SSascha Wildner 			}
16851901a965SSascha Wildner 		}
16861901a965SSascha Wildner 	}
16871901a965SSascha Wildner 	/* enable outbound Post Queue, outbound doorbell Interrupt */
16881901a965SSascha Wildner 	arcmsr_enable_allintr(acb, intmask_org);
16891901a965SSascha Wildner }
16901901a965SSascha Wildner /*
16911901a965SSascha Wildner **************************************************************************
16921901a965SSascha Wildner **************************************************************************
16931901a965SSascha Wildner */
arcmsr_dr_handle(struct AdapterControlBlock * acb)16941901a965SSascha Wildner static void arcmsr_dr_handle(struct AdapterControlBlock *acb) {
16951901a965SSascha Wildner 	u_int32_t	devicemap;
16961901a965SSascha Wildner 	u_int32_t	target, lun;
16971901a965SSascha Wildner 	u_int32_t	deviceMapCurrent[4]={0};
16981901a965SSascha Wildner 	u_int8_t	*pDevMap;
16991901a965SSascha Wildner 
17001901a965SSascha Wildner 	switch (acb->adapter_type) {
17011901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_A:
17021901a965SSascha Wildner 		devicemap = offsetof(struct HBA_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
17031901a965SSascha Wildner 		for (target = 0; target < 4; target++)
17041901a965SSascha Wildner 		{
17051901a965SSascha Wildner 			deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0],  devicemap);
17061901a965SSascha Wildner 			devicemap += 4;
17071901a965SSascha Wildner 		}
17081901a965SSascha Wildner 		break;
17091901a965SSascha Wildner 
17101901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_B:
17111901a965SSascha Wildner 		devicemap = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
17121901a965SSascha Wildner 		for (target = 0; target < 4; target++)
17131901a965SSascha Wildner 		{
17141901a965SSascha Wildner 			deviceMapCurrent[target]=bus_space_read_4(acb->btag[1], acb->bhandle[1],  devicemap);
17151901a965SSascha Wildner 			devicemap += 4;
17161901a965SSascha Wildner 		}
17171901a965SSascha Wildner 		break;
17181901a965SSascha Wildner 
17191901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_C:
17201901a965SSascha Wildner 		devicemap = offsetof(struct HBC_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
17211901a965SSascha Wildner 		for (target = 0; target < 4; target++)
17221901a965SSascha Wildner 		{
17231901a965SSascha Wildner 			deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0],  devicemap);
17241901a965SSascha Wildner 			devicemap += 4;
17251901a965SSascha Wildner 		}
17261901a965SSascha Wildner 		break;
1727cec1e926SSascha Wildner 	case ACB_ADAPTER_TYPE_D:
1728cec1e926SSascha Wildner 		devicemap = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
1729cec1e926SSascha Wildner 		for (target = 0; target < 4; target++)
1730cec1e926SSascha Wildner 		{
1731cec1e926SSascha Wildner 			deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0],  devicemap);
1732cec1e926SSascha Wildner 			devicemap += 4;
1733cec1e926SSascha Wildner 		}
1734cec1e926SSascha Wildner 		break;
1735111d54bfSSascha Wildner 	case ACB_ADAPTER_TYPE_E:
1736111d54bfSSascha Wildner 		devicemap = offsetof(struct HBE_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
1737111d54bfSSascha Wildner 		for (target = 0; target < 4; target++)
1738111d54bfSSascha Wildner 		{
1739111d54bfSSascha Wildner             		deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0],  devicemap);
1740111d54bfSSascha Wildner             		devicemap += 4;
1741111d54bfSSascha Wildner 		}
1742111d54bfSSascha Wildner 		break;
17431901a965SSascha Wildner 	}
1744629e42e2SSascha Wildner 
17451901a965SSascha Wildner 	if(acb->acb_flags & ACB_F_BUS_HANG_ON)
17461901a965SSascha Wildner 	{
17471901a965SSascha Wildner 		acb->acb_flags &= ~ACB_F_BUS_HANG_ON;
17481901a965SSascha Wildner 	}
17491901a965SSascha Wildner 	/*
17501901a965SSascha Wildner 	** adapter posted CONFIG message
17511901a965SSascha Wildner 	** copy the new map, note if there are differences with the current map
17521901a965SSascha Wildner 	*/
17531901a965SSascha Wildner 	pDevMap = (u_int8_t *)&deviceMapCurrent[0];
17541901a965SSascha Wildner 	for (target = 0; target < ARCMSR_MAX_TARGETID - 1; target++)
17551901a965SSascha Wildner 	{
17561901a965SSascha Wildner 		if (*pDevMap != acb->device_map[target])
17571901a965SSascha Wildner 		{
17581901a965SSascha Wildner 			u_int8_t difference, bit_check;
17591901a965SSascha Wildner 
17601901a965SSascha Wildner 			difference = *pDevMap ^ acb->device_map[target];
17611901a965SSascha Wildner 			for(lun=0; lun < ARCMSR_MAX_TARGETLUN; lun++)
17621901a965SSascha Wildner 			{
17631901a965SSascha Wildner 				bit_check = (1 << lun);		/*check bit from 0....31*/
17641901a965SSascha Wildner 				if(difference & bit_check)
17651901a965SSascha Wildner 				{
17661901a965SSascha Wildner 					if(acb->device_map[target] & bit_check)
17671901a965SSascha Wildner 					{/* unit departed */
17681901a965SSascha Wildner 						kprintf("arcmsr_dr_handle: Target=%x, lun=%x, GONE!!!\n",target,lun);
17691901a965SSascha Wildner 						arcmsr_abort_dr_ccbs(acb, target, lun);
17701901a965SSascha Wildner 						arcmsr_rescan_lun(acb, target, lun);
17711901a965SSascha Wildner 						acb->devstate[target][lun] = ARECA_RAID_GONE;
17721901a965SSascha Wildner 					}
17731901a965SSascha Wildner 					else
17741901a965SSascha Wildner 					{/* unit arrived */
1775cc3b439cSSascha Wildner 						kprintf("arcmsr_dr_handle: Target=%x, lun=%x, Plug-IN!!!\n",target,lun);
17761901a965SSascha Wildner 						arcmsr_rescan_lun(acb, target, lun);
17771901a965SSascha Wildner 						acb->devstate[target][lun] = ARECA_RAID_GOOD;
17781901a965SSascha Wildner 					}
17791901a965SSascha Wildner 				}
17801901a965SSascha Wildner 			}
17811901a965SSascha Wildner /*			kprintf("arcmsr_dr_handle: acb->device_map[%x]=0x%x, deviceMapCurrent[%x]=%x\n",target,acb->device_map[target],target,*pDevMap); */
17821901a965SSascha Wildner 			acb->device_map[target] = *pDevMap;
17831901a965SSascha Wildner 		}
17841901a965SSascha Wildner 		pDevMap++;
17851901a965SSascha Wildner 	}
17861901a965SSascha Wildner }
17871901a965SSascha Wildner /*
17881901a965SSascha Wildner **************************************************************************
17891901a965SSascha Wildner **************************************************************************
17901901a965SSascha Wildner */
arcmsr_hba_message_isr(struct AdapterControlBlock * acb)17911901a965SSascha Wildner static void arcmsr_hba_message_isr(struct AdapterControlBlock *acb) {
17921901a965SSascha Wildner 	u_int32_t outbound_message;
17931901a965SSascha Wildner 
17941901a965SSascha Wildner 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);
17951901a965SSascha Wildner 	outbound_message = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[0]);
17961901a965SSascha Wildner 	if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
17971901a965SSascha Wildner 		arcmsr_dr_handle( acb );
17981901a965SSascha Wildner }
17991901a965SSascha Wildner /*
18001901a965SSascha Wildner **************************************************************************
18011901a965SSascha Wildner **************************************************************************
18021901a965SSascha Wildner */
arcmsr_hbb_message_isr(struct AdapterControlBlock * acb)18031901a965SSascha Wildner static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) {
18041901a965SSascha Wildner 	u_int32_t outbound_message;
1805111d54bfSSascha Wildner 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
18061901a965SSascha Wildner 
18071901a965SSascha Wildner 	/* clear interrupts */
1808111d54bfSSascha Wildner 	WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);
18091901a965SSascha Wildner 	outbound_message = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0]);
18101901a965SSascha Wildner 	if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
18111901a965SSascha Wildner 		arcmsr_dr_handle( acb );
18121901a965SSascha Wildner }
18131901a965SSascha Wildner /*
18141901a965SSascha Wildner **************************************************************************
18151901a965SSascha Wildner **************************************************************************
18161901a965SSascha Wildner */
arcmsr_hbc_message_isr(struct AdapterControlBlock * acb)18171901a965SSascha Wildner static void arcmsr_hbc_message_isr(struct AdapterControlBlock *acb) {
18181901a965SSascha Wildner 	u_int32_t outbound_message;
18191901a965SSascha Wildner 
18201901a965SSascha Wildner 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);
18211901a965SSascha Wildner 	outbound_message = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[0]);
18221901a965SSascha Wildner 	if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
18231901a965SSascha Wildner 		arcmsr_dr_handle( acb );
18241901a965SSascha Wildner }
18251901a965SSascha Wildner /*
18261901a965SSascha Wildner **************************************************************************
18271901a965SSascha Wildner **************************************************************************
18281901a965SSascha Wildner */
arcmsr_hbd_message_isr(struct AdapterControlBlock * acb)1829cec1e926SSascha Wildner static void arcmsr_hbd_message_isr(struct AdapterControlBlock *acb) {
1830cec1e926SSascha Wildner 	u_int32_t outbound_message;
1831cec1e926SSascha Wildner 
1832cec1e926SSascha Wildner 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR);
1833cec1e926SSascha Wildner 	outbound_message = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[0]);
1834cec1e926SSascha Wildner 	if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
1835cec1e926SSascha Wildner 		arcmsr_dr_handle( acb );
1836cec1e926SSascha Wildner }
1837cec1e926SSascha Wildner /*
1838cec1e926SSascha Wildner **************************************************************************
1839cec1e926SSascha Wildner **************************************************************************
1840cec1e926SSascha Wildner */
arcmsr_hbe_message_isr(struct AdapterControlBlock * acb)1841111d54bfSSascha Wildner static void arcmsr_hbe_message_isr(struct AdapterControlBlock *acb) {
1842111d54bfSSascha Wildner 	u_int32_t outbound_message;
1843111d54bfSSascha Wildner 
1844111d54bfSSascha Wildner 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0);
1845111d54bfSSascha Wildner 	outbound_message = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[0]);
1846111d54bfSSascha Wildner 	if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
1847111d54bfSSascha Wildner 		arcmsr_dr_handle( acb );
1848111d54bfSSascha Wildner }
1849111d54bfSSascha Wildner /*
1850111d54bfSSascha Wildner **************************************************************************
1851111d54bfSSascha Wildner **************************************************************************
1852111d54bfSSascha Wildner */
arcmsr_hba_doorbell_isr(struct AdapterControlBlock * acb)18531901a965SSascha Wildner static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb)
18541901a965SSascha Wildner {
1855cec1e926SSascha Wildner 	u_int32_t doorbell_status;
18561901a965SSascha Wildner 
18571901a965SSascha Wildner 	/*
18581901a965SSascha Wildner 	*******************************************************************
18591901a965SSascha Wildner 	**  Maybe here we need to check wrqbuffer_lock is lock or not
18601901a965SSascha Wildner 	**  DOORBELL: din! don!
18611901a965SSascha Wildner 	**  check if there are any mail need to pack from firmware
18621901a965SSascha Wildner 	*******************************************************************
18631901a965SSascha Wildner 	*/
1864cec1e926SSascha Wildner 	doorbell_status = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell);
1865cec1e926SSascha Wildner 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */
1866cec1e926SSascha Wildner 	if(doorbell_status & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) {
18671901a965SSascha Wildner 		arcmsr_iop2drv_data_wrote_handle(acb);
18681901a965SSascha Wildner 	}
1869cec1e926SSascha Wildner 	if(doorbell_status & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) {
18701901a965SSascha Wildner 		arcmsr_iop2drv_data_read_handle(acb);
18711901a965SSascha Wildner 	}
18721901a965SSascha Wildner }
18731901a965SSascha Wildner /*
18741901a965SSascha Wildner **************************************************************************
18751901a965SSascha Wildner **************************************************************************
18761901a965SSascha Wildner */
arcmsr_hbc_doorbell_isr(struct AdapterControlBlock * acb)18771901a965SSascha Wildner static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb)
18781901a965SSascha Wildner {
1879cec1e926SSascha Wildner 	u_int32_t doorbell_status;
18801901a965SSascha Wildner 
18811901a965SSascha Wildner 	/*
18821901a965SSascha Wildner 	*******************************************************************
18831901a965SSascha Wildner 	**  Maybe here we need to check wrqbuffer_lock is lock or not
18841901a965SSascha Wildner 	**  DOORBELL: din! don!
18851901a965SSascha Wildner 	**  check if there are any mail need to pack from firmware
18861901a965SSascha Wildner 	*******************************************************************
18871901a965SSascha Wildner 	*/
1888cec1e926SSascha Wildner 	doorbell_status = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell);
1889cec1e926SSascha Wildner 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, doorbell_status); /* clear doorbell interrupt */
1890cec1e926SSascha Wildner 	if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) {
18911901a965SSascha Wildner 		arcmsr_iop2drv_data_wrote_handle(acb);
18921901a965SSascha Wildner 	}
1893cec1e926SSascha Wildner 	if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) {
18941901a965SSascha Wildner 		arcmsr_iop2drv_data_read_handle(acb);
18951901a965SSascha Wildner 	}
1896cec1e926SSascha Wildner 	if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) {
18971901a965SSascha Wildner 		arcmsr_hbc_message_isr(acb);    /* messenger of "driver to iop commands" */
18981901a965SSascha Wildner 	}
18991901a965SSascha Wildner }
19001901a965SSascha Wildner /*
19011901a965SSascha Wildner **************************************************************************
19021901a965SSascha Wildner **************************************************************************
19031901a965SSascha Wildner */
arcmsr_hbd_doorbell_isr(struct AdapterControlBlock * acb)1904cec1e926SSascha Wildner static void arcmsr_hbd_doorbell_isr(struct AdapterControlBlock *acb)
1905cec1e926SSascha Wildner {
1906cec1e926SSascha Wildner 	u_int32_t doorbell_status;
1907cec1e926SSascha Wildner 
1908cec1e926SSascha Wildner 	/*
1909cec1e926SSascha Wildner 	*******************************************************************
1910cec1e926SSascha Wildner 	**  Maybe here we need to check wrqbuffer_lock is lock or not
1911cec1e926SSascha Wildner 	**  DOORBELL: din! don!
1912cec1e926SSascha Wildner 	**  check if there are any mail need to pack from firmware
1913cec1e926SSascha Wildner 	*******************************************************************
1914cec1e926SSascha Wildner 	*/
1915cec1e926SSascha Wildner 	doorbell_status = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE;
1916cec1e926SSascha Wildner 	if(doorbell_status)
1917cec1e926SSascha Wildner 		CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */
1918cec1e926SSascha Wildner 	while( doorbell_status & ARCMSR_HBDMU_F0_DOORBELL_CAUSE ) {
1919cec1e926SSascha Wildner 		if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_DATA_WRITE_OK) {
1920cec1e926SSascha Wildner 			arcmsr_iop2drv_data_wrote_handle(acb);
1921cec1e926SSascha Wildner 		}
1922cec1e926SSascha Wildner 		if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_DATA_READ_OK) {
1923cec1e926SSascha Wildner 			arcmsr_iop2drv_data_read_handle(acb);
1924cec1e926SSascha Wildner 		}
1925cec1e926SSascha Wildner 		if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) {
1926cec1e926SSascha Wildner 			arcmsr_hbd_message_isr(acb);    /* messenger of "driver to iop commands" */
1927cec1e926SSascha Wildner 		}
1928cec1e926SSascha Wildner 		doorbell_status = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE;
1929cec1e926SSascha Wildner 		if(doorbell_status)
1930cec1e926SSascha Wildner 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */
1931cec1e926SSascha Wildner 	}
1932cec1e926SSascha Wildner }
1933cec1e926SSascha Wildner /*
1934cec1e926SSascha Wildner **************************************************************************
1935cec1e926SSascha Wildner **************************************************************************
1936cec1e926SSascha Wildner */
arcmsr_hbe_doorbell_isr(struct AdapterControlBlock * acb)1937111d54bfSSascha Wildner static void arcmsr_hbe_doorbell_isr(struct AdapterControlBlock *acb)
1938111d54bfSSascha Wildner {
1939111d54bfSSascha Wildner 	u_int32_t doorbell_status, in_doorbell;
1940111d54bfSSascha Wildner 
1941111d54bfSSascha Wildner 	/*
1942111d54bfSSascha Wildner 	*******************************************************************
1943111d54bfSSascha Wildner 	**  Maybe here we need to check wrqbuffer_lock is lock or not
1944111d54bfSSascha Wildner 	**  DOORBELL: din! don!
1945111d54bfSSascha Wildner 	**  check if there are any mail need to pack from firmware
1946111d54bfSSascha Wildner 	*******************************************************************
1947111d54bfSSascha Wildner 	*/
1948111d54bfSSascha Wildner 	in_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell);
1949111d54bfSSascha Wildner 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /* clear doorbell interrupt */
1950111d54bfSSascha Wildner 	doorbell_status = in_doorbell ^ acb->in_doorbell;
1951111d54bfSSascha Wildner 	if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_WRITE_OK) {
1952111d54bfSSascha Wildner 		arcmsr_iop2drv_data_wrote_handle(acb);
1953111d54bfSSascha Wildner 	}
1954111d54bfSSascha Wildner 	if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_READ_OK) {
1955111d54bfSSascha Wildner 		arcmsr_iop2drv_data_read_handle(acb);
1956111d54bfSSascha Wildner 	}
1957111d54bfSSascha Wildner 	if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) {
1958111d54bfSSascha Wildner 		arcmsr_hbe_message_isr(acb);    /* messenger of "driver to iop commands" */
1959111d54bfSSascha Wildner 	}
1960111d54bfSSascha Wildner 	acb->in_doorbell = in_doorbell;
1961111d54bfSSascha Wildner }
1962111d54bfSSascha Wildner /*
1963111d54bfSSascha Wildner **************************************************************************
1964111d54bfSSascha Wildner **************************************************************************
1965111d54bfSSascha Wildner */
arcmsr_hba_postqueue_isr(struct AdapterControlBlock * acb)19661901a965SSascha Wildner static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb)
19671901a965SSascha Wildner {
19681901a965SSascha Wildner 	u_int32_t flag_srb;
19691901a965SSascha Wildner 	u_int16_t error;
19701901a965SSascha Wildner 
19711901a965SSascha Wildner 	/*
19721901a965SSascha Wildner 	*****************************************************************************
19731901a965SSascha Wildner 	**               areca cdb command done
19741901a965SSascha Wildner 	*****************************************************************************
19751901a965SSascha Wildner 	*/
19761901a965SSascha Wildner 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap,
19771901a965SSascha Wildner 		BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
19781901a965SSascha Wildner 	while((flag_srb = CHIP_REG_READ32(HBA_MessageUnit,
19791901a965SSascha Wildner 		0, outbound_queueport)) != 0xFFFFFFFF) {
19801901a965SSascha Wildner 		/* check if command done with no error*/
19811901a965SSascha Wildner 	error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0) ? TRUE : FALSE;
19821901a965SSascha Wildner 		arcmsr_drain_donequeue(acb, flag_srb, error);
19831901a965SSascha Wildner 	}	/*drain reply FIFO*/
19841901a965SSascha Wildner }
19851901a965SSascha Wildner /*
19861901a965SSascha Wildner **************************************************************************
19871901a965SSascha Wildner **************************************************************************
19881901a965SSascha Wildner */
arcmsr_hbb_postqueue_isr(struct AdapterControlBlock * acb)19891901a965SSascha Wildner static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb)
19901901a965SSascha Wildner {
19911901a965SSascha Wildner 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
19921901a965SSascha Wildner 	u_int32_t flag_srb;
19931901a965SSascha Wildner 	int index;
19941901a965SSascha Wildner 	u_int16_t error;
19951901a965SSascha Wildner 
19961901a965SSascha Wildner 	/*
19971901a965SSascha Wildner 	*****************************************************************************
19981901a965SSascha Wildner 	**               areca cdb command done
19991901a965SSascha Wildner 	*****************************************************************************
20001901a965SSascha Wildner 	*/
20011901a965SSascha Wildner 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap,
20021901a965SSascha Wildner 		BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
20031901a965SSascha Wildner 	index = phbbmu->doneq_index;
20041901a965SSascha Wildner 	while((flag_srb = phbbmu->done_qbuffer[index]) != 0) {
20051901a965SSascha Wildner 		phbbmu->done_qbuffer[index] = 0;
20061901a965SSascha Wildner 		index++;
20071901a965SSascha Wildner 		index %= ARCMSR_MAX_HBB_POSTQUEUE;     /*if last index number set it to 0 */
20081901a965SSascha Wildner 		phbbmu->doneq_index = index;
20091901a965SSascha Wildner 		/* check if command done with no error*/
20101901a965SSascha Wildner 	error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
20111901a965SSascha Wildner 		arcmsr_drain_donequeue(acb, flag_srb, error);
20121901a965SSascha Wildner 	}	/*drain reply FIFO*/
20131901a965SSascha Wildner }
20141901a965SSascha Wildner /*
20151901a965SSascha Wildner **************************************************************************
20161901a965SSascha Wildner **************************************************************************
20171901a965SSascha Wildner */
arcmsr_hbc_postqueue_isr(struct AdapterControlBlock * acb)20181901a965SSascha Wildner static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb)
20191901a965SSascha Wildner {
20201901a965SSascha Wildner 	u_int32_t flag_srb,throttling = 0;
20211901a965SSascha Wildner 	u_int16_t error;
20221901a965SSascha Wildner 
20231901a965SSascha Wildner 	/*
20241901a965SSascha Wildner 	*****************************************************************************
20251901a965SSascha Wildner 	**               areca cdb command done
20261901a965SSascha Wildner 	*****************************************************************************
20271901a965SSascha Wildner 	*/
20281901a965SSascha Wildner 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
2029cec1e926SSascha Wildner 	do {
20301901a965SSascha Wildner 		flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low);
2031111d54bfSSascha Wildner 		if (flag_srb == 0xFFFFFFFF)
2032111d54bfSSascha Wildner 			break;
20331901a965SSascha Wildner 		/* check if command done with no error*/
20341901a965SSascha Wildner 		error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE;
20351901a965SSascha Wildner 		arcmsr_drain_donequeue(acb, flag_srb, error);
2036cec1e926SSascha Wildner 		throttling++;
20371901a965SSascha Wildner 		if(throttling == ARCMSR_HBC_ISR_THROTTLING_LEVEL) {
20381901a965SSascha Wildner 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING);
2039cec1e926SSascha Wildner 			throttling = 0;
20401901a965SSascha Wildner 		}
2041cec1e926SSascha Wildner 	} while(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR);
2042cec1e926SSascha Wildner }
2043cec1e926SSascha Wildner /*
2044cec1e926SSascha Wildner **********************************************************************
2045cec1e926SSascha Wildner **
2046cec1e926SSascha Wildner **********************************************************************
2047cec1e926SSascha Wildner */
arcmsr_get_doneq_index(struct HBD_MessageUnit0 * phbdmu)2048cec1e926SSascha Wildner static uint16_t arcmsr_get_doneq_index(struct HBD_MessageUnit0 *phbdmu)
2049cec1e926SSascha Wildner {
2050cec1e926SSascha Wildner 	uint16_t doneq_index, index_stripped;
2051cec1e926SSascha Wildner 
2052cec1e926SSascha Wildner 	doneq_index = phbdmu->doneq_index;
2053cec1e926SSascha Wildner 	if (doneq_index & 0x4000) {
2054cec1e926SSascha Wildner 		index_stripped = doneq_index & 0xFF;
2055cec1e926SSascha Wildner 		index_stripped += 1;
2056cec1e926SSascha Wildner 		index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
2057cec1e926SSascha Wildner 		phbdmu->doneq_index = index_stripped ?
2058cec1e926SSascha Wildner 		    (index_stripped | 0x4000) : index_stripped;
2059cec1e926SSascha Wildner 	} else {
2060cec1e926SSascha Wildner 		index_stripped = doneq_index;
2061cec1e926SSascha Wildner 		index_stripped += 1;
2062cec1e926SSascha Wildner 		index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
2063cec1e926SSascha Wildner 		phbdmu->doneq_index = index_stripped ?
2064cec1e926SSascha Wildner 		    index_stripped : (index_stripped | 0x4000);
2065cec1e926SSascha Wildner 	}
2066cec1e926SSascha Wildner 	return (phbdmu->doneq_index);
2067cec1e926SSascha Wildner }
2068cec1e926SSascha Wildner /*
2069cec1e926SSascha Wildner **************************************************************************
2070cec1e926SSascha Wildner **************************************************************************
2071cec1e926SSascha Wildner */
arcmsr_hbd_postqueue_isr(struct AdapterControlBlock * acb)2072cec1e926SSascha Wildner static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb)
2073cec1e926SSascha Wildner {
2074cec1e926SSascha Wildner 	struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
2075cec1e926SSascha Wildner 	u_int32_t outbound_write_pointer;
2076cec1e926SSascha Wildner 	u_int32_t addressLow;
2077cec1e926SSascha Wildner 	uint16_t doneq_index;
2078cec1e926SSascha Wildner 	u_int16_t error;
2079cec1e926SSascha Wildner 	/*
2080cec1e926SSascha Wildner 	*****************************************************************************
2081cec1e926SSascha Wildner 	**               areca cdb command done
2082cec1e926SSascha Wildner 	*****************************************************************************
2083cec1e926SSascha Wildner 	*/
2084cec1e926SSascha Wildner 	if((CHIP_REG_READ32(HBD_MessageUnit, 0, outboundlist_interrupt_cause) &
2085cec1e926SSascha Wildner 		ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT) == 0)
2086cec1e926SSascha Wildner 		return;
2087cec1e926SSascha Wildner 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap,
2088cec1e926SSascha Wildner 		BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
2089cec1e926SSascha Wildner 	outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow;
2090cec1e926SSascha Wildner 	doneq_index = phbdmu->doneq_index;
2091cec1e926SSascha Wildner 	while ((doneq_index & 0xFF) != (outbound_write_pointer & 0xFF)) {
2092cec1e926SSascha Wildner 		doneq_index = arcmsr_get_doneq_index(phbdmu);
2093cec1e926SSascha Wildner 		addressLow = phbdmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow;
2094cec1e926SSascha Wildner 		error = (addressLow & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
2095cec1e926SSascha Wildner 		arcmsr_drain_donequeue(acb, addressLow, error); /*Check if command done with no error */
2096cec1e926SSascha Wildner 		CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_read_pointer, doneq_index);
2097cec1e926SSascha Wildner 		outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow;
2098cec1e926SSascha Wildner 	}
2099cec1e926SSascha Wildner 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_interrupt_cause, ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT_CLEAR);
2100cec1e926SSascha Wildner 	CHIP_REG_READ32(HBD_MessageUnit, 0, outboundlist_interrupt_cause); /*Dummy ioread32 to force pci flush */
21011901a965SSascha Wildner }
21021901a965SSascha Wildner /*
2103111d54bfSSascha Wildner **************************************************************************
2104111d54bfSSascha Wildner **************************************************************************
2105111d54bfSSascha Wildner */
arcmsr_hbe_postqueue_isr(struct AdapterControlBlock * acb)2106111d54bfSSascha Wildner static void arcmsr_hbe_postqueue_isr(struct AdapterControlBlock *acb)
2107111d54bfSSascha Wildner {
2108111d54bfSSascha Wildner 	u_int16_t error;
2109111d54bfSSascha Wildner 	uint32_t doneq_index;
2110111d54bfSSascha Wildner 	uint16_t cmdSMID;
2111111d54bfSSascha Wildner 
2112111d54bfSSascha Wildner 	/*
2113111d54bfSSascha Wildner 	*****************************************************************************
2114111d54bfSSascha Wildner 	**               areca cdb command done
2115111d54bfSSascha Wildner 	*****************************************************************************
2116111d54bfSSascha Wildner 	*/
2117111d54bfSSascha Wildner 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
2118111d54bfSSascha Wildner 	doneq_index = acb->doneq_index;
2119111d54bfSSascha Wildner 	while ((CHIP_REG_READ32(HBE_MessageUnit, 0, reply_post_producer_index) & 0xFFFF) != doneq_index) {
2120111d54bfSSascha Wildner 		cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID;
2121111d54bfSSascha Wildner 		error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
2122111d54bfSSascha Wildner 		arcmsr_drain_donequeue(acb, (u_int32_t)cmdSMID, error);
2123111d54bfSSascha Wildner 		doneq_index++;
2124111d54bfSSascha Wildner 		if (doneq_index >= acb->completionQ_entry)
2125111d54bfSSascha Wildner 			doneq_index = 0;
2126111d54bfSSascha Wildner 	}
2127111d54bfSSascha Wildner 	acb->doneq_index = doneq_index;
2128111d54bfSSascha Wildner 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, reply_post_consumer_index, doneq_index);
2129111d54bfSSascha Wildner }
2130111d54bfSSascha Wildner /*
21311901a965SSascha Wildner **********************************************************************
21321901a965SSascha Wildner **********************************************************************
21331901a965SSascha Wildner */
arcmsr_handle_hba_isr(struct AdapterControlBlock * acb)21341901a965SSascha Wildner static void arcmsr_handle_hba_isr( struct AdapterControlBlock *acb)
21351901a965SSascha Wildner {
2136629e42e2SSascha Wildner 	u_int32_t outbound_intStatus;
21371901a965SSascha Wildner 	/*
21381901a965SSascha Wildner 	*********************************************
21391901a965SSascha Wildner 	**   check outbound intstatus
21401901a965SSascha Wildner 	*********************************************
21411901a965SSascha Wildner 	*/
2142629e42e2SSascha Wildner 	outbound_intStatus = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable;
2143629e42e2SSascha Wildner 	if(!outbound_intStatus) {
21441901a965SSascha Wildner 		/*it must be share irq*/
21451901a965SSascha Wildner 		return;
21461901a965SSascha Wildner 	}
2147629e42e2SSascha Wildner 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intStatus); /*clear interrupt*/
21481901a965SSascha Wildner 	/* MU doorbell interrupts*/
2149629e42e2SSascha Wildner 	if(outbound_intStatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) {
21501901a965SSascha Wildner 		arcmsr_hba_doorbell_isr(acb);
21511901a965SSascha Wildner 	}
21521901a965SSascha Wildner 	/* MU post queue interrupts*/
2153629e42e2SSascha Wildner 	if(outbound_intStatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) {
21541901a965SSascha Wildner 		arcmsr_hba_postqueue_isr(acb);
21551901a965SSascha Wildner 	}
2156629e42e2SSascha Wildner 	if(outbound_intStatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
21571901a965SSascha Wildner 		arcmsr_hba_message_isr(acb);
21581901a965SSascha Wildner 	}
21591901a965SSascha Wildner }
21601901a965SSascha Wildner /*
21611901a965SSascha Wildner **********************************************************************
21621901a965SSascha Wildner **********************************************************************
21631901a965SSascha Wildner */
arcmsr_handle_hbb_isr(struct AdapterControlBlock * acb)21641901a965SSascha Wildner static void arcmsr_handle_hbb_isr( struct AdapterControlBlock *acb)
21651901a965SSascha Wildner {
21661901a965SSascha Wildner 	u_int32_t outbound_doorbell;
2167111d54bfSSascha Wildner 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
21681901a965SSascha Wildner 	/*
21691901a965SSascha Wildner 	*********************************************
21701901a965SSascha Wildner 	**   check outbound intstatus
21711901a965SSascha Wildner 	*********************************************
21721901a965SSascha Wildner 	*/
2173111d54bfSSascha Wildner 	outbound_doorbell = READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & acb->outbound_int_enable;
21741901a965SSascha Wildner 	if(!outbound_doorbell) {
21751901a965SSascha Wildner 		/*it must be share irq*/
21761901a965SSascha Wildner 		return;
21771901a965SSascha Wildner 	}
2178111d54bfSSascha Wildner 	WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ~outbound_doorbell); /* clear doorbell interrupt */
2179111d54bfSSascha Wildner 	READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell);
2180111d54bfSSascha Wildner 	WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
21811901a965SSascha Wildner 	/* MU ioctl transfer doorbell interrupts*/
21821901a965SSascha Wildner 	if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) {
21831901a965SSascha Wildner 		arcmsr_iop2drv_data_wrote_handle(acb);
21841901a965SSascha Wildner 	}
21851901a965SSascha Wildner 	if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) {
21861901a965SSascha Wildner 		arcmsr_iop2drv_data_read_handle(acb);
21871901a965SSascha Wildner 	}
21881901a965SSascha Wildner 	/* MU post queue interrupts*/
21891901a965SSascha Wildner 	if(outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) {
21901901a965SSascha Wildner 		arcmsr_hbb_postqueue_isr(acb);
21911901a965SSascha Wildner 	}
21921901a965SSascha Wildner 	if(outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
21931901a965SSascha Wildner 		arcmsr_hbb_message_isr(acb);
21941901a965SSascha Wildner 	}
21951901a965SSascha Wildner }
21961901a965SSascha Wildner /*
21971901a965SSascha Wildner **********************************************************************
21981901a965SSascha Wildner **********************************************************************
21991901a965SSascha Wildner */
arcmsr_handle_hbc_isr(struct AdapterControlBlock * acb)22001901a965SSascha Wildner static void arcmsr_handle_hbc_isr( struct AdapterControlBlock *acb)
22011901a965SSascha Wildner {
22021901a965SSascha Wildner 	u_int32_t host_interrupt_status;
22031901a965SSascha Wildner 	/*
22041901a965SSascha Wildner 	*********************************************
22051901a965SSascha Wildner 	**   check outbound intstatus
22061901a965SSascha Wildner 	*********************************************
22071901a965SSascha Wildner 	*/
2208cec1e926SSascha Wildner 	host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) &
2209cec1e926SSascha Wildner 		(ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR |
2210cec1e926SSascha Wildner 		ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR);
22111901a965SSascha Wildner 	if(!host_interrupt_status) {
22121901a965SSascha Wildner 		/*it must be share irq*/
22131901a965SSascha Wildner 		return;
22141901a965SSascha Wildner 	}
2215cec1e926SSascha Wildner 	do {
22161901a965SSascha Wildner 		/* MU doorbell interrupts*/
22171901a965SSascha Wildner 		if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) {
22181901a965SSascha Wildner 			arcmsr_hbc_doorbell_isr(acb);
22191901a965SSascha Wildner 		}
22201901a965SSascha Wildner 		/* MU post queue interrupts*/
22211901a965SSascha Wildner 		if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) {
22221901a965SSascha Wildner 			arcmsr_hbc_postqueue_isr(acb);
22231901a965SSascha Wildner 		}
2224cec1e926SSascha Wildner 		host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status);
2225cec1e926SSascha Wildner 	} while (host_interrupt_status & (ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR));
2226cec1e926SSascha Wildner }
2227cec1e926SSascha Wildner /*
2228cec1e926SSascha Wildner **********************************************************************
2229cec1e926SSascha Wildner **********************************************************************
2230cec1e926SSascha Wildner */
arcmsr_handle_hbd_isr(struct AdapterControlBlock * acb)2231cec1e926SSascha Wildner static void arcmsr_handle_hbd_isr( struct AdapterControlBlock *acb)
2232cec1e926SSascha Wildner {
2233cec1e926SSascha Wildner 	u_int32_t host_interrupt_status;
2234cec1e926SSascha Wildner 	u_int32_t intmask_org;
2235cec1e926SSascha Wildner 	/*
2236cec1e926SSascha Wildner 	*********************************************
2237cec1e926SSascha Wildner 	**   check outbound intstatus
2238cec1e926SSascha Wildner 	*********************************************
2239cec1e926SSascha Wildner 	*/
2240cec1e926SSascha Wildner 	host_interrupt_status = CHIP_REG_READ32(HBD_MessageUnit, 0, host_int_status) & acb->outbound_int_enable;
2241cec1e926SSascha Wildner 	if(!(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_INT)) {
2242cec1e926SSascha Wildner 		/*it must be share irq*/
2243cec1e926SSascha Wildner 		return;
2244cec1e926SSascha Wildner 	}
2245cec1e926SSascha Wildner 	/* disable outbound interrupt */
2246cec1e926SSascha Wildner 	intmask_org = CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable)	; /* disable outbound message0 int */
2247cec1e926SSascha Wildner 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, ARCMSR_HBDMU_ALL_INT_DISABLE);
2248cec1e926SSascha Wildner 	/* MU doorbell interrupts*/
2249cec1e926SSascha Wildner 	if(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_DOORBELL_INT) {
2250cec1e926SSascha Wildner 		arcmsr_hbd_doorbell_isr(acb);
2251cec1e926SSascha Wildner 	}
2252cec1e926SSascha Wildner 	/* MU post queue interrupts*/
2253cec1e926SSascha Wildner 	if(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_POSTQUEUE_INT) {
2254cec1e926SSascha Wildner 		arcmsr_hbd_postqueue_isr(acb);
2255cec1e926SSascha Wildner 	}
2256cec1e926SSascha Wildner 	/* enable all outbound interrupt */
2257cec1e926SSascha Wildner 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, intmask_org | ARCMSR_HBDMU_ALL_INT_ENABLE);
2258cec1e926SSascha Wildner //	CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable);
22591901a965SSascha Wildner }
22601901a965SSascha Wildner /*
2261111d54bfSSascha Wildner **********************************************************************
2262111d54bfSSascha Wildner **********************************************************************
2263111d54bfSSascha Wildner */
arcmsr_handle_hbe_isr(struct AdapterControlBlock * acb)2264111d54bfSSascha Wildner static void arcmsr_handle_hbe_isr( struct AdapterControlBlock *acb)
2265111d54bfSSascha Wildner {
2266111d54bfSSascha Wildner 	u_int32_t host_interrupt_status;
2267111d54bfSSascha Wildner 	/*
2268111d54bfSSascha Wildner 	*********************************************
2269111d54bfSSascha Wildner 	**   check outbound intstatus
2270111d54bfSSascha Wildner 	*********************************************
2271111d54bfSSascha Wildner 	*/
2272111d54bfSSascha Wildner 	host_interrupt_status = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_status) &
2273111d54bfSSascha Wildner 		(ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR |
2274111d54bfSSascha Wildner 		ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR);
2275111d54bfSSascha Wildner 	if(!host_interrupt_status) {
2276111d54bfSSascha Wildner 		/*it must be share irq*/
2277111d54bfSSascha Wildner 		return;
2278111d54bfSSascha Wildner 	}
2279111d54bfSSascha Wildner 	do {
2280111d54bfSSascha Wildner 		/* MU doorbell interrupts*/
2281111d54bfSSascha Wildner 		if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR) {
2282111d54bfSSascha Wildner 			arcmsr_hbe_doorbell_isr(acb);
2283111d54bfSSascha Wildner 		}
2284111d54bfSSascha Wildner 		/* MU post queue interrupts*/
2285111d54bfSSascha Wildner 		if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR) {
2286111d54bfSSascha Wildner 			arcmsr_hbe_postqueue_isr(acb);
2287111d54bfSSascha Wildner 		}
2288111d54bfSSascha Wildner 		host_interrupt_status = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_status);
2289111d54bfSSascha Wildner 	} while (host_interrupt_status & (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR));
2290111d54bfSSascha Wildner }
2291111d54bfSSascha Wildner /*
22921901a965SSascha Wildner ******************************************************************************
22931901a965SSascha Wildner ******************************************************************************
22941901a965SSascha Wildner */
arcmsr_interrupt(struct AdapterControlBlock * acb)22951901a965SSascha Wildner static void arcmsr_interrupt(struct AdapterControlBlock *acb)
22961901a965SSascha Wildner {
22971901a965SSascha Wildner 	switch (acb->adapter_type) {
22981901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_A:
22991901a965SSascha Wildner 		arcmsr_handle_hba_isr(acb);
23001901a965SSascha Wildner 		break;
23011901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_B:
23021901a965SSascha Wildner 		arcmsr_handle_hbb_isr(acb);
23031901a965SSascha Wildner 		break;
23041901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_C:
23051901a965SSascha Wildner 		arcmsr_handle_hbc_isr(acb);
23061901a965SSascha Wildner 		break;
2307cec1e926SSascha Wildner 	case ACB_ADAPTER_TYPE_D:
2308cec1e926SSascha Wildner 		arcmsr_handle_hbd_isr(acb);
2309cec1e926SSascha Wildner 		break;
2310111d54bfSSascha Wildner 	case ACB_ADAPTER_TYPE_E:
2311111d54bfSSascha Wildner 		arcmsr_handle_hbe_isr(acb);
2312111d54bfSSascha Wildner 		break;
23131901a965SSascha Wildner 	default:
23141901a965SSascha Wildner 		kprintf("arcmsr%d: interrupt service,"
231595cdd875SSascha Wildner 		" unknown adapter type =%d\n", acb->pci_unit, acb->adapter_type);
23161901a965SSascha Wildner 		break;
23171901a965SSascha Wildner 	}
23181901a965SSascha Wildner }
23191901a965SSascha Wildner /*
23201901a965SSascha Wildner **********************************************************************
23211901a965SSascha Wildner **********************************************************************
23221901a965SSascha Wildner */
arcmsr_intr_handler(void * arg)23231901a965SSascha Wildner static void arcmsr_intr_handler(void *arg)
23241901a965SSascha Wildner {
23251901a965SSascha Wildner 	struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg;
23261901a965SSascha Wildner 
23271901a965SSascha Wildner 	arcmsr_interrupt(acb);
23281901a965SSascha Wildner }
23291901a965SSascha Wildner /*
23301901a965SSascha Wildner ******************************************************************************
23311901a965SSascha Wildner ******************************************************************************
23321901a965SSascha Wildner */
arcmsr_polling_devmap(void * arg)23331901a965SSascha Wildner static void	arcmsr_polling_devmap(void *arg)
23341901a965SSascha Wildner {
23351901a965SSascha Wildner 	struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg;
23361901a965SSascha Wildner 	switch (acb->adapter_type) {
23371901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_A:
2338629e42e2SSascha Wildner 		CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
23391901a965SSascha Wildner 		break;
23401901a965SSascha Wildner 
2341111d54bfSSascha Wildner     	case ACB_ADAPTER_TYPE_B: {
2342111d54bfSSascha Wildner 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
2343111d54bfSSascha Wildner 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG);
2344111d54bfSSascha Wildner 		}
23451901a965SSascha Wildner 		break;
23461901a965SSascha Wildner 
23471901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_C:
23481901a965SSascha Wildner 		CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
23491901a965SSascha Wildner 		CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
23501901a965SSascha Wildner 		break;
2351cec1e926SSascha Wildner 
2352cec1e926SSascha Wildner 	case ACB_ADAPTER_TYPE_D:
2353cec1e926SSascha Wildner 		CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
2354cec1e926SSascha Wildner 		break;
2355111d54bfSSascha Wildner 
2356111d54bfSSascha Wildner     	case ACB_ADAPTER_TYPE_E:
2357111d54bfSSascha Wildner 		CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
2358111d54bfSSascha Wildner 		acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
2359111d54bfSSascha Wildner 		CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
2360111d54bfSSascha Wildner 	    	break;
23611901a965SSascha Wildner 	}
23621901a965SSascha Wildner 
23631901a965SSascha Wildner 	if((acb->acb_flags & ACB_F_SCSISTOPADAPTER) == 0)
23641901a965SSascha Wildner 	{
23651901a965SSascha Wildner 		callout_reset(&acb->devmap_callout, 5 * hz, arcmsr_polling_devmap, acb);	/* polling per 5 seconds */
23661901a965SSascha Wildner 	}
23671901a965SSascha Wildner }
23681901a965SSascha Wildner 
23691901a965SSascha Wildner /*
23701901a965SSascha Wildner *******************************************************************************
23711901a965SSascha Wildner **
23721901a965SSascha Wildner *******************************************************************************
23731901a965SSascha Wildner */
arcmsr_iop_parking(struct AdapterControlBlock * acb)23741901a965SSascha Wildner static void arcmsr_iop_parking(struct AdapterControlBlock *acb)
23751901a965SSascha Wildner {
23761901a965SSascha Wildner 	u_int32_t intmask_org;
23771901a965SSascha Wildner 
23781901a965SSascha Wildner 	if(acb != NULL) {
23791901a965SSascha Wildner 		/* stop adapter background rebuild */
23801901a965SSascha Wildner 		if(acb->acb_flags & ACB_F_MSG_START_BGRB) {
23811901a965SSascha Wildner 			intmask_org = arcmsr_disable_allintr(acb);
23821901a965SSascha Wildner 			arcmsr_stop_adapter_bgrb(acb);
23831901a965SSascha Wildner 			arcmsr_flush_adapter_cache(acb);
23841901a965SSascha Wildner 			arcmsr_enable_allintr(acb, intmask_org);
23851901a965SSascha Wildner 		}
23861901a965SSascha Wildner 	}
23871901a965SSascha Wildner }
23881901a965SSascha Wildner /*
23891901a965SSascha Wildner ***********************************************************************
23901901a965SSascha Wildner **
23911901a965SSascha Wildner ************************************************************************
23921901a965SSascha Wildner */
arcmsr_iop_ioctlcmd(struct AdapterControlBlock * acb,u_int32_t ioctl_cmd,caddr_t arg)23938406cf70SSascha Wildner static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg)
23941901a965SSascha Wildner {
23951901a965SSascha Wildner 	struct CMD_MESSAGE_FIELD *pcmdmessagefld;
23961901a965SSascha Wildner 	u_int32_t retvalue = EINVAL;
23971901a965SSascha Wildner 
23981901a965SSascha Wildner 	pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) arg;
23991901a965SSascha Wildner 	if(memcmp(pcmdmessagefld->cmdmessage.Signature, "ARCMSR", 6)!=0) {
24001901a965SSascha Wildner 		return retvalue;
24011901a965SSascha Wildner 	}
24021901a965SSascha Wildner 	ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
24031901a965SSascha Wildner 	switch(ioctl_cmd) {
24041901a965SSascha Wildner 	case ARCMSR_MESSAGE_READ_RQBUFFER: {
24051901a965SSascha Wildner 			u_int8_t *pQbuffer;
24061901a965SSascha Wildner 			u_int8_t *ptmpQbuffer = pcmdmessagefld->messagedatabuffer;
24071901a965SSascha Wildner 			u_int32_t allxfer_len=0;
24081901a965SSascha Wildner 
24091901a965SSascha Wildner 			while((acb->rqbuf_firstindex != acb->rqbuf_lastindex)
24101901a965SSascha Wildner 				&& (allxfer_len < 1031)) {
24111901a965SSascha Wildner 				/*copy READ QBUFFER to srb*/
24121901a965SSascha Wildner 				pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex];
2413cec1e926SSascha Wildner 				*ptmpQbuffer = *pQbuffer;
24141901a965SSascha Wildner 				acb->rqbuf_firstindex++;
24151901a965SSascha Wildner 				acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
24161901a965SSascha Wildner 				/*if last index number set it to 0 */
24171901a965SSascha Wildner 				ptmpQbuffer++;
24181901a965SSascha Wildner 				allxfer_len++;
24191901a965SSascha Wildner 			}
24201901a965SSascha Wildner 			if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
24211901a965SSascha Wildner 				struct QBUFFER *prbuffer;
24221901a965SSascha Wildner 
24231901a965SSascha Wildner 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
24241901a965SSascha Wildner 				prbuffer = arcmsr_get_iop_rqbuffer(acb);
2425cec1e926SSascha Wildner 				if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
2426cec1e926SSascha Wildner 					acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
24271901a965SSascha Wildner 			}
24281901a965SSascha Wildner 			pcmdmessagefld->cmdmessage.Length = allxfer_len;
24291901a965SSascha Wildner 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
24301901a965SSascha Wildner 			retvalue = ARCMSR_MESSAGE_SUCCESS;
24311901a965SSascha Wildner 		}
24321901a965SSascha Wildner 		break;
24331901a965SSascha Wildner 	case ARCMSR_MESSAGE_WRITE_WQBUFFER: {
24341901a965SSascha Wildner 			u_int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
24351901a965SSascha Wildner 			u_int8_t *pQbuffer;
24361901a965SSascha Wildner 			u_int8_t *ptmpuserbuffer = pcmdmessagefld->messagedatabuffer;
24371901a965SSascha Wildner 
24381901a965SSascha Wildner 			user_len = pcmdmessagefld->cmdmessage.Length;
24391901a965SSascha Wildner 			/*check if data xfer length of this request will overflow my array qbuffer */
24401901a965SSascha Wildner 			wqbuf_lastindex = acb->wqbuf_lastindex;
24411901a965SSascha Wildner 			wqbuf_firstindex = acb->wqbuf_firstindex;
24421901a965SSascha Wildner 			if(wqbuf_lastindex != wqbuf_firstindex) {
2443cec1e926SSascha Wildner 				arcmsr_Write_data_2iop_wqbuffer(acb);
24441901a965SSascha Wildner 				pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR;
24451901a965SSascha Wildner 			} else {
2446cec1e926SSascha Wildner 				my_empty_len = (wqbuf_firstindex - wqbuf_lastindex - 1) &
2447cec1e926SSascha Wildner 					(ARCMSR_MAX_QBUFFER - 1);
24481901a965SSascha Wildner 				if(my_empty_len >= user_len) {
24491901a965SSascha Wildner 					while(user_len > 0) {
24501901a965SSascha Wildner 						/*copy srb data to wqbuffer*/
24511901a965SSascha Wildner 						pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex];
2452cec1e926SSascha Wildner 						*pQbuffer = *ptmpuserbuffer;
24531901a965SSascha Wildner 						acb->wqbuf_lastindex++;
24541901a965SSascha Wildner 						acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
24551901a965SSascha Wildner 						/*if last index number set it to 0 */
24561901a965SSascha Wildner 						ptmpuserbuffer++;
24571901a965SSascha Wildner 						user_len--;
24581901a965SSascha Wildner 					}
24591901a965SSascha Wildner 					/*post fist Qbuffer*/
24601901a965SSascha Wildner 					if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) {
24611901a965SSascha Wildner 						acb->acb_flags &= ~ACB_F_MESSAGE_WQBUFFER_CLEARED;
2462cec1e926SSascha Wildner 						arcmsr_Write_data_2iop_wqbuffer(acb);
24631901a965SSascha Wildner 					}
24641901a965SSascha Wildner 					pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
24651901a965SSascha Wildner 				} else {
24661901a965SSascha Wildner 					pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR;
24671901a965SSascha Wildner 				}
24681901a965SSascha Wildner 			}
24691901a965SSascha Wildner 			retvalue = ARCMSR_MESSAGE_SUCCESS;
24701901a965SSascha Wildner 		}
24711901a965SSascha Wildner 		break;
24721901a965SSascha Wildner 	case ARCMSR_MESSAGE_CLEAR_RQBUFFER: {
24731901a965SSascha Wildner 			u_int8_t *pQbuffer = acb->rqbuffer;
24741901a965SSascha Wildner 
24751901a965SSascha Wildner 			if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
24761901a965SSascha Wildner 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
24771901a965SSascha Wildner 				arcmsr_iop_message_read(acb);
24781901a965SSascha Wildner 				/*signature, let IOP know data has been readed */
24791901a965SSascha Wildner 			}
24801901a965SSascha Wildner 			acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED;
24811901a965SSascha Wildner 			acb->rqbuf_firstindex = 0;
24821901a965SSascha Wildner 			acb->rqbuf_lastindex = 0;
24831901a965SSascha Wildner 			memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
24841901a965SSascha Wildner 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
24851901a965SSascha Wildner 			retvalue = ARCMSR_MESSAGE_SUCCESS;
24861901a965SSascha Wildner 		}
24871901a965SSascha Wildner 		break;
24881901a965SSascha Wildner 	case ARCMSR_MESSAGE_CLEAR_WQBUFFER:
24891901a965SSascha Wildner 		{
24901901a965SSascha Wildner 			u_int8_t *pQbuffer = acb->wqbuffer;
24911901a965SSascha Wildner 
24921901a965SSascha Wildner 			if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
24931901a965SSascha Wildner 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
24941901a965SSascha Wildner 				arcmsr_iop_message_read(acb);
24951901a965SSascha Wildner 				/*signature, let IOP know data has been readed */
24961901a965SSascha Wildner 			}
24971901a965SSascha Wildner 			acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ);
24981901a965SSascha Wildner 			acb->wqbuf_firstindex = 0;
24991901a965SSascha Wildner 			acb->wqbuf_lastindex = 0;
25001901a965SSascha Wildner 			memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
25011901a965SSascha Wildner 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
25021901a965SSascha Wildner 			retvalue = ARCMSR_MESSAGE_SUCCESS;
25031901a965SSascha Wildner 		}
25041901a965SSascha Wildner 		break;
25051901a965SSascha Wildner 	case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: {
25061901a965SSascha Wildner 			u_int8_t *pQbuffer;
25071901a965SSascha Wildner 
25081901a965SSascha Wildner 			if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
25091901a965SSascha Wildner 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
25101901a965SSascha Wildner 				arcmsr_iop_message_read(acb);
25111901a965SSascha Wildner 				/*signature, let IOP know data has been readed */
25121901a965SSascha Wildner 			}
25131901a965SSascha Wildner 			acb->acb_flags  |= (ACB_F_MESSAGE_WQBUFFER_CLEARED
25141901a965SSascha Wildner 					|ACB_F_MESSAGE_RQBUFFER_CLEARED
25151901a965SSascha Wildner 					|ACB_F_MESSAGE_WQBUFFER_READ);
25161901a965SSascha Wildner 			acb->rqbuf_firstindex = 0;
25171901a965SSascha Wildner 			acb->rqbuf_lastindex = 0;
25181901a965SSascha Wildner 			acb->wqbuf_firstindex = 0;
25191901a965SSascha Wildner 			acb->wqbuf_lastindex = 0;
25201901a965SSascha Wildner 			pQbuffer = acb->rqbuffer;
25211901a965SSascha Wildner 			memset(pQbuffer, 0, sizeof(struct QBUFFER));
25221901a965SSascha Wildner 			pQbuffer = acb->wqbuffer;
25231901a965SSascha Wildner 			memset(pQbuffer, 0, sizeof(struct QBUFFER));
25241901a965SSascha Wildner 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
25251901a965SSascha Wildner 			retvalue = ARCMSR_MESSAGE_SUCCESS;
25261901a965SSascha Wildner 		}
25271901a965SSascha Wildner 		break;
25281901a965SSascha Wildner 	case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: {
25291901a965SSascha Wildner 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F;
25301901a965SSascha Wildner 			retvalue = ARCMSR_MESSAGE_SUCCESS;
25311901a965SSascha Wildner 		}
25321901a965SSascha Wildner 		break;
25331901a965SSascha Wildner 	case ARCMSR_MESSAGE_SAY_HELLO: {
25341901a965SSascha Wildner 			u_int8_t *hello_string = "Hello! I am ARCMSR";
25351901a965SSascha Wildner 			u_int8_t *puserbuffer = (u_int8_t *)pcmdmessagefld->messagedatabuffer;
25361901a965SSascha Wildner 
25371901a965SSascha Wildner 			if(memcpy(puserbuffer, hello_string, (int16_t)strlen(hello_string))) {
25381901a965SSascha Wildner 				pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR;
25391901a965SSascha Wildner 				ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
25401901a965SSascha Wildner 				return ENOIOCTL;
25411901a965SSascha Wildner 			}
25421901a965SSascha Wildner 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
25431901a965SSascha Wildner 			retvalue = ARCMSR_MESSAGE_SUCCESS;
25441901a965SSascha Wildner 		}
25451901a965SSascha Wildner 		break;
25461901a965SSascha Wildner 	case ARCMSR_MESSAGE_SAY_GOODBYE: {
25471901a965SSascha Wildner 			arcmsr_iop_parking(acb);
25481901a965SSascha Wildner 			retvalue = ARCMSR_MESSAGE_SUCCESS;
25491901a965SSascha Wildner 		}
25501901a965SSascha Wildner 		break;
25511901a965SSascha Wildner 	case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: {
25521901a965SSascha Wildner 			arcmsr_flush_adapter_cache(acb);
25531901a965SSascha Wildner 			retvalue = ARCMSR_MESSAGE_SUCCESS;
25541901a965SSascha Wildner 		}
25551901a965SSascha Wildner 		break;
25561901a965SSascha Wildner 	}
25571901a965SSascha Wildner 	ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
2558629e42e2SSascha Wildner 	return (retvalue);
25591901a965SSascha Wildner }
25601901a965SSascha Wildner /*
25611901a965SSascha Wildner **************************************************************************
25621901a965SSascha Wildner **************************************************************************
25631901a965SSascha Wildner */
arcmsr_free_srb(struct CommandControlBlock * srb)2564cc3b439cSSascha Wildner static void arcmsr_free_srb(struct CommandControlBlock *srb)
2565cc3b439cSSascha Wildner {
2566cc3b439cSSascha Wildner 	struct AdapterControlBlock	*acb;
2567cc3b439cSSascha Wildner 
2568cc3b439cSSascha Wildner 	acb = srb->acb;
2569cec1e926SSascha Wildner 	ARCMSR_LOCK_ACQUIRE(&acb->srb_lock);
2570cc3b439cSSascha Wildner 	srb->srb_state = ARCMSR_SRB_DONE;
2571cc3b439cSSascha Wildner 	srb->srb_flags = 0;
2572cc3b439cSSascha Wildner 	acb->srbworkingQ[acb->workingsrb_doneindex] = srb;
2573cc3b439cSSascha Wildner 	acb->workingsrb_doneindex++;
2574cc3b439cSSascha Wildner 	acb->workingsrb_doneindex %= ARCMSR_MAX_FREESRB_NUM;
2575cec1e926SSascha Wildner 	ARCMSR_LOCK_RELEASE(&acb->srb_lock);
2576cc3b439cSSascha Wildner }
2577cc3b439cSSascha Wildner /*
2578cc3b439cSSascha Wildner **************************************************************************
2579cc3b439cSSascha Wildner **************************************************************************
2580cc3b439cSSascha Wildner */
arcmsr_get_freesrb(struct AdapterControlBlock * acb)25818406cf70SSascha Wildner static struct CommandControlBlock *arcmsr_get_freesrb(struct AdapterControlBlock *acb)
25821901a965SSascha Wildner {
25831901a965SSascha Wildner 	struct CommandControlBlock *srb = NULL;
25841901a965SSascha Wildner 	u_int32_t workingsrb_startindex, workingsrb_doneindex;
25851901a965SSascha Wildner 
2586cec1e926SSascha Wildner 	ARCMSR_LOCK_ACQUIRE(&acb->srb_lock);
25871901a965SSascha Wildner 	workingsrb_doneindex = acb->workingsrb_doneindex;
25881901a965SSascha Wildner 	workingsrb_startindex = acb->workingsrb_startindex;
25891901a965SSascha Wildner 	srb = acb->srbworkingQ[workingsrb_startindex];
25901901a965SSascha Wildner 	workingsrb_startindex++;
25911901a965SSascha Wildner 	workingsrb_startindex %= ARCMSR_MAX_FREESRB_NUM;
25921901a965SSascha Wildner 	if(workingsrb_doneindex != workingsrb_startindex) {
25931901a965SSascha Wildner 		acb->workingsrb_startindex = workingsrb_startindex;
25941901a965SSascha Wildner 	} else {
25951901a965SSascha Wildner 		srb = NULL;
25961901a965SSascha Wildner 	}
2597cec1e926SSascha Wildner 	ARCMSR_LOCK_RELEASE(&acb->srb_lock);
25981901a965SSascha Wildner 	return(srb);
25991901a965SSascha Wildner }
26001901a965SSascha Wildner /*
26011901a965SSascha Wildner **************************************************************************
26021901a965SSascha Wildner **************************************************************************
26031901a965SSascha Wildner */
arcmsr_iop_message_xfer(struct AdapterControlBlock * acb,union ccb * pccb)26041901a965SSascha Wildner static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *pccb)
26051901a965SSascha Wildner {
26061901a965SSascha Wildner 	struct CMD_MESSAGE_FIELD *pcmdmessagefld;
26071901a965SSascha Wildner 	int retvalue = 0, transfer_len = 0;
26081901a965SSascha Wildner 	char *buffer;
26091901a965SSascha Wildner 	u_int32_t controlcode = (u_int32_t ) pccb->csio.cdb_io.cdb_bytes[5] << 24 |
26101901a965SSascha Wildner 				(u_int32_t ) pccb->csio.cdb_io.cdb_bytes[6] << 16 |
26111901a965SSascha Wildner 				(u_int32_t ) pccb->csio.cdb_io.cdb_bytes[7] << 8  |
26121901a965SSascha Wildner 				(u_int32_t ) pccb->csio.cdb_io.cdb_bytes[8];
26131901a965SSascha Wildner 					/* 4 bytes: Areca io control code */
26141901a965SSascha Wildner 	if((pccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
26151901a965SSascha Wildner 		buffer = pccb->csio.data_ptr;
26161901a965SSascha Wildner 		transfer_len = pccb->csio.dxfer_len;
26171901a965SSascha Wildner 	} else {
26181901a965SSascha Wildner 		retvalue = ARCMSR_MESSAGE_FAIL;
26191901a965SSascha Wildner 		goto message_out;
26201901a965SSascha Wildner 	}
26211901a965SSascha Wildner 	if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) {
26221901a965SSascha Wildner 		retvalue = ARCMSR_MESSAGE_FAIL;
26231901a965SSascha Wildner 		goto message_out;
26241901a965SSascha Wildner 	}
26251901a965SSascha Wildner 	pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer;
26261901a965SSascha Wildner 	switch(controlcode) {
26271901a965SSascha Wildner 	case ARCMSR_MESSAGE_READ_RQBUFFER: {
26281901a965SSascha Wildner 			u_int8_t *pQbuffer;
26291901a965SSascha Wildner 			u_int8_t *ptmpQbuffer = pcmdmessagefld->messagedatabuffer;
26301901a965SSascha Wildner 			int32_t allxfer_len = 0;
26311901a965SSascha Wildner 
2632cec1e926SSascha Wildner 			ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
26331901a965SSascha Wildner 			while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex)
26341901a965SSascha Wildner 				&& (allxfer_len < 1031)) {
26351901a965SSascha Wildner 				pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex];
2636cec1e926SSascha Wildner 				*ptmpQbuffer = *pQbuffer;
26371901a965SSascha Wildner 				acb->rqbuf_firstindex++;
26381901a965SSascha Wildner 				acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
26391901a965SSascha Wildner 				ptmpQbuffer++;
26401901a965SSascha Wildner 				allxfer_len++;
26411901a965SSascha Wildner 			}
26421901a965SSascha Wildner 			if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
26431901a965SSascha Wildner 				struct QBUFFER  *prbuffer;
26441901a965SSascha Wildner 
26451901a965SSascha Wildner 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
26461901a965SSascha Wildner 				prbuffer = arcmsr_get_iop_rqbuffer(acb);
2647cec1e926SSascha Wildner 				if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
2648cec1e926SSascha Wildner 					acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
26491901a965SSascha Wildner 			}
26501901a965SSascha Wildner 			pcmdmessagefld->cmdmessage.Length = allxfer_len;
26511901a965SSascha Wildner 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
26521901a965SSascha Wildner 			retvalue = ARCMSR_MESSAGE_SUCCESS;
2653cec1e926SSascha Wildner 			ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
26541901a965SSascha Wildner 		}
26551901a965SSascha Wildner 		break;
26561901a965SSascha Wildner 	case ARCMSR_MESSAGE_WRITE_WQBUFFER: {
26571901a965SSascha Wildner 			int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
26581901a965SSascha Wildner 			u_int8_t *pQbuffer;
26591901a965SSascha Wildner 			u_int8_t *ptmpuserbuffer = pcmdmessagefld->messagedatabuffer;
26601901a965SSascha Wildner 
26611901a965SSascha Wildner 			user_len = pcmdmessagefld->cmdmessage.Length;
2662cec1e926SSascha Wildner 			ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
26631901a965SSascha Wildner 			wqbuf_lastindex = acb->wqbuf_lastindex;
26641901a965SSascha Wildner 			wqbuf_firstindex = acb->wqbuf_firstindex;
26651901a965SSascha Wildner 			if (wqbuf_lastindex != wqbuf_firstindex) {
2666cec1e926SSascha Wildner 				arcmsr_Write_data_2iop_wqbuffer(acb);
26671901a965SSascha Wildner 				/* has error report sensedata */
26686d4343eeSSascha Wildner 				if(pccb->csio.sense_len) {
26691901a965SSascha Wildner 				((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70);
26701901a965SSascha Wildner 				/* Valid,ErrorCode */
26711901a965SSascha Wildner 				((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05;
26721901a965SSascha Wildner 				/* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */
26731901a965SSascha Wildner 				((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A;
26741901a965SSascha Wildner 				/* AdditionalSenseLength */
26751901a965SSascha Wildner 				((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20;
26761901a965SSascha Wildner 				/* AdditionalSenseCode */
26771901a965SSascha Wildner 				}
26781901a965SSascha Wildner 				retvalue = ARCMSR_MESSAGE_FAIL;
26791901a965SSascha Wildner 			} else {
26801901a965SSascha Wildner 				my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1)
26811901a965SSascha Wildner 						&(ARCMSR_MAX_QBUFFER - 1);
26821901a965SSascha Wildner 				if (my_empty_len >= user_len) {
26831901a965SSascha Wildner 					while (user_len > 0) {
26841901a965SSascha Wildner 						pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex];
2685cec1e926SSascha Wildner 						*pQbuffer = *ptmpuserbuffer;
26861901a965SSascha Wildner 						acb->wqbuf_lastindex++;
26871901a965SSascha Wildner 						acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
26881901a965SSascha Wildner 						ptmpuserbuffer++;
26891901a965SSascha Wildner 						user_len--;
26901901a965SSascha Wildner 					}
26911901a965SSascha Wildner 					if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) {
26921901a965SSascha Wildner 						acb->acb_flags &=
26931901a965SSascha Wildner 						    ~ACB_F_MESSAGE_WQBUFFER_CLEARED;
2694cec1e926SSascha Wildner 						arcmsr_Write_data_2iop_wqbuffer(acb);
26951901a965SSascha Wildner 					}
26961901a965SSascha Wildner 				} else {
26971901a965SSascha Wildner 					/* has error report sensedata */
26986d4343eeSSascha Wildner 					if(pccb->csio.sense_len) {
26991901a965SSascha Wildner 					((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70);
27001901a965SSascha Wildner 					/* Valid,ErrorCode */
27011901a965SSascha Wildner 					((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05;
27021901a965SSascha Wildner 					/* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */
27031901a965SSascha Wildner 					((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A;
27041901a965SSascha Wildner 					/* AdditionalSenseLength */
27051901a965SSascha Wildner 					((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20;
27061901a965SSascha Wildner 					/* AdditionalSenseCode */
27071901a965SSascha Wildner 					}
27081901a965SSascha Wildner 					retvalue = ARCMSR_MESSAGE_FAIL;
27091901a965SSascha Wildner 				}
27101901a965SSascha Wildner 			}
2711cec1e926SSascha Wildner 			ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
27121901a965SSascha Wildner 		}
27131901a965SSascha Wildner 		break;
27141901a965SSascha Wildner 	case ARCMSR_MESSAGE_CLEAR_RQBUFFER: {
27151901a965SSascha Wildner 			u_int8_t *pQbuffer = acb->rqbuffer;
27161901a965SSascha Wildner 
2717cec1e926SSascha Wildner 			ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
27181901a965SSascha Wildner 			if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
27191901a965SSascha Wildner 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
27201901a965SSascha Wildner 				arcmsr_iop_message_read(acb);
27211901a965SSascha Wildner 			}
27221901a965SSascha Wildner 			acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED;
27231901a965SSascha Wildner 			acb->rqbuf_firstindex = 0;
27241901a965SSascha Wildner 			acb->rqbuf_lastindex = 0;
27251901a965SSascha Wildner 			memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
27261901a965SSascha Wildner 			pcmdmessagefld->cmdmessage.ReturnCode =
27271901a965SSascha Wildner 			    ARCMSR_MESSAGE_RETURNCODE_OK;
2728cec1e926SSascha Wildner 			ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
27291901a965SSascha Wildner 		}
27301901a965SSascha Wildner 		break;
27311901a965SSascha Wildner 	case ARCMSR_MESSAGE_CLEAR_WQBUFFER: {
27321901a965SSascha Wildner 			u_int8_t *pQbuffer = acb->wqbuffer;
27331901a965SSascha Wildner 
2734cec1e926SSascha Wildner 			ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
27351901a965SSascha Wildner 			if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
27361901a965SSascha Wildner 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
27371901a965SSascha Wildner 				arcmsr_iop_message_read(acb);
27381901a965SSascha Wildner 			}
27391901a965SSascha Wildner 			acb->acb_flags |=
27401901a965SSascha Wildner 				(ACB_F_MESSAGE_WQBUFFER_CLEARED |
27411901a965SSascha Wildner 					ACB_F_MESSAGE_WQBUFFER_READ);
27421901a965SSascha Wildner 			acb->wqbuf_firstindex = 0;
27431901a965SSascha Wildner 			acb->wqbuf_lastindex = 0;
27441901a965SSascha Wildner 			memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
27451901a965SSascha Wildner 			pcmdmessagefld->cmdmessage.ReturnCode =
27461901a965SSascha Wildner 				ARCMSR_MESSAGE_RETURNCODE_OK;
2747cec1e926SSascha Wildner 			ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
27481901a965SSascha Wildner 		}
27491901a965SSascha Wildner 		break;
27501901a965SSascha Wildner 	case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: {
27511901a965SSascha Wildner 			u_int8_t *pQbuffer;
27521901a965SSascha Wildner 
2753cec1e926SSascha Wildner 			ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
27541901a965SSascha Wildner 			if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
27551901a965SSascha Wildner 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
27561901a965SSascha Wildner 				arcmsr_iop_message_read(acb);
27571901a965SSascha Wildner 			}
27581901a965SSascha Wildner 			acb->acb_flags |=
27591901a965SSascha Wildner 				(ACB_F_MESSAGE_WQBUFFER_CLEARED
27601901a965SSascha Wildner 				| ACB_F_MESSAGE_RQBUFFER_CLEARED
27611901a965SSascha Wildner 				| ACB_F_MESSAGE_WQBUFFER_READ);
27621901a965SSascha Wildner 			acb->rqbuf_firstindex = 0;
27631901a965SSascha Wildner 			acb->rqbuf_lastindex = 0;
27641901a965SSascha Wildner 			acb->wqbuf_firstindex = 0;
27651901a965SSascha Wildner 			acb->wqbuf_lastindex = 0;
27661901a965SSascha Wildner 			pQbuffer = acb->rqbuffer;
27671901a965SSascha Wildner 			memset(pQbuffer, 0, sizeof (struct QBUFFER));
27681901a965SSascha Wildner 			pQbuffer = acb->wqbuffer;
27691901a965SSascha Wildner 			memset(pQbuffer, 0, sizeof (struct QBUFFER));
27701901a965SSascha Wildner 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
2771cec1e926SSascha Wildner 			ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
27721901a965SSascha Wildner 		}
27731901a965SSascha Wildner 		break;
27741901a965SSascha Wildner 	case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: {
27751901a965SSascha Wildner 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F;
27761901a965SSascha Wildner 		}
27771901a965SSascha Wildner 		break;
27781901a965SSascha Wildner 	case ARCMSR_MESSAGE_SAY_HELLO: {
27791901a965SSascha Wildner 			int8_t *hello_string = "Hello! I am ARCMSR";
27801901a965SSascha Wildner 
27811901a965SSascha Wildner 			memcpy(pcmdmessagefld->messagedatabuffer, hello_string
27821901a965SSascha Wildner 				, (int16_t)strlen(hello_string));
27831901a965SSascha Wildner 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
27841901a965SSascha Wildner 		}
27851901a965SSascha Wildner 		break;
27861901a965SSascha Wildner 	case ARCMSR_MESSAGE_SAY_GOODBYE:
27871901a965SSascha Wildner 		arcmsr_iop_parking(acb);
27881901a965SSascha Wildner 		break;
27891901a965SSascha Wildner 	case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE:
27901901a965SSascha Wildner 		arcmsr_flush_adapter_cache(acb);
27911901a965SSascha Wildner 		break;
27921901a965SSascha Wildner 	default:
27931901a965SSascha Wildner 		retvalue = ARCMSR_MESSAGE_FAIL;
27941901a965SSascha Wildner 	}
27951901a965SSascha Wildner message_out:
2796629e42e2SSascha Wildner 	return (retvalue);
27971901a965SSascha Wildner }
27981901a965SSascha Wildner /*
27991901a965SSascha Wildner *********************************************************************
28001901a965SSascha Wildner *********************************************************************
28011901a965SSascha Wildner */
arcmsr_execute_srb(void * arg,bus_dma_segment_t * dm_segs,int nseg,int error)280295696aa4SSascha Wildner static void arcmsr_execute_srb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
28031901a965SSascha Wildner {
28041901a965SSascha Wildner 	struct CommandControlBlock *srb = (struct CommandControlBlock *)arg;
28051901a965SSascha Wildner 	struct AdapterControlBlock *acb = (struct AdapterControlBlock *)srb->acb;
28061901a965SSascha Wildner 	union ccb *pccb;
28071901a965SSascha Wildner 	int target, lun;
28081901a965SSascha Wildner 
28091901a965SSascha Wildner 	pccb = srb->pccb;
28101901a965SSascha Wildner 	target = pccb->ccb_h.target_id;
28111901a965SSascha Wildner 	lun = pccb->ccb_h.target_lun;
2812cc3b439cSSascha Wildner 	acb->pktRequestCount++;
28131901a965SSascha Wildner 	if(error != 0) {
28141901a965SSascha Wildner 		if(error != EFBIG) {
28151901a965SSascha Wildner 			kprintf("arcmsr%d: unexpected error %x"
28161901a965SSascha Wildner 				" returned from 'bus_dmamap_load' \n"
28171901a965SSascha Wildner 				, acb->pci_unit, error);
28181901a965SSascha Wildner 		}
28191901a965SSascha Wildner 		if((pccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) {
28201901a965SSascha Wildner 			pccb->ccb_h.status |= CAM_REQ_TOO_BIG;
28211901a965SSascha Wildner 		}
28221901a965SSascha Wildner 		arcmsr_srb_complete(srb, 0);
28231901a965SSascha Wildner 		return;
28241901a965SSascha Wildner 	}
28251901a965SSascha Wildner 	if(nseg > ARCMSR_MAX_SG_ENTRIES) {
28261901a965SSascha Wildner 		pccb->ccb_h.status |= CAM_REQ_TOO_BIG;
28271901a965SSascha Wildner 		arcmsr_srb_complete(srb, 0);
28281901a965SSascha Wildner 		return;
28291901a965SSascha Wildner 	}
28301901a965SSascha Wildner 	if(acb->acb_flags & ACB_F_BUS_RESET) {
28311901a965SSascha Wildner 		kprintf("arcmsr%d: bus reset and return busy \n", acb->pci_unit);
28321901a965SSascha Wildner 		pccb->ccb_h.status |= CAM_SCSI_BUS_RESET;
28331901a965SSascha Wildner 		arcmsr_srb_complete(srb, 0);
28341901a965SSascha Wildner 		return;
28351901a965SSascha Wildner 	}
28361901a965SSascha Wildner 	if(acb->devstate[target][lun] == ARECA_RAID_GONE) {
2837cc3b439cSSascha Wildner 		u_int8_t block_cmd, cmd;
28381901a965SSascha Wildner 
2839cc3b439cSSascha Wildner 		cmd = pccb->csio.cdb_io.cdb_bytes[0];
2840cc3b439cSSascha Wildner 		block_cmd = cmd & 0x0f;
28411901a965SSascha Wildner 		if(block_cmd == 0x08 || block_cmd == 0x0a) {
28421901a965SSascha Wildner 			kprintf("arcmsr%d:block 'read/write' command "
2843cc3b439cSSascha Wildner 				"with gone raid volume Cmd=0x%2x, TargetId=%d, Lun=%d \n"
2844cc3b439cSSascha Wildner 				, acb->pci_unit, cmd, target, lun);
28451901a965SSascha Wildner 			pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
28461901a965SSascha Wildner 			arcmsr_srb_complete(srb, 0);
28471901a965SSascha Wildner 			return;
28481901a965SSascha Wildner 		}
28491901a965SSascha Wildner 	}
28501901a965SSascha Wildner 	if((pccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
28511901a965SSascha Wildner 		if(nseg != 0) {
2852111d54bfSSascha Wildner 			ARCMSR_LOCK_ACQUIRE(&acb->io_lock);
28531901a965SSascha Wildner 			bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap);
2854111d54bfSSascha Wildner 			ARCMSR_LOCK_RELEASE(&acb->io_lock);
28551901a965SSascha Wildner 		}
28561901a965SSascha Wildner 		arcmsr_srb_complete(srb, 0);
28571901a965SSascha Wildner 		return;
28581901a965SSascha Wildner 	}
2859cec1e926SSascha Wildner 	if(acb->srboutstandingcount >= acb->maxOutstanding) {
2860cec1e926SSascha Wildner 		if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) == 0)
2861cec1e926SSascha Wildner 		{
28621901a965SSascha Wildner 			xpt_freeze_simq(acb->psim, 1);
28631901a965SSascha Wildner 			acb->acb_flags |= ACB_F_CAM_DEV_QFRZN;
2864cec1e926SSascha Wildner 		}
2865cec1e926SSascha Wildner 		pccb->ccb_h.status &= ~CAM_SIM_QUEUED;
2866cec1e926SSascha Wildner 		pccb->ccb_h.status |= CAM_REQUEUE_REQ;
28671901a965SSascha Wildner 		arcmsr_srb_complete(srb, 0);
28681901a965SSascha Wildner 		return;
28691901a965SSascha Wildner 	}
28701901a965SSascha Wildner 	pccb->ccb_h.status |= CAM_SIM_QUEUED;
28711901a965SSascha Wildner 	arcmsr_build_srb(srb, dm_segs, nseg);
28721901a965SSascha Wildner 	arcmsr_post_srb(acb, srb);
2873cc3b439cSSascha Wildner 	if (pccb->ccb_h.timeout != CAM_TIME_INFINITY)
2874cc3b439cSSascha Wildner 	{
28751f872987SFrançois Tigeot 		callout_init_lk(&srb->ccb_callout, &srb->acb->isr_lock);
2876629e42e2SSascha Wildner 		callout_reset(&srb->ccb_callout, ((pccb->ccb_h.timeout + (ARCMSR_TIMEOUT_DELAY * 1000)) * hz) / 1000, arcmsr_srb_timeout, srb);
2877cc3b439cSSascha Wildner 		srb->srb_flags |= SRB_FLAG_TIMER_START;
2878cc3b439cSSascha Wildner 	}
28791901a965SSascha Wildner }
28801901a965SSascha Wildner /*
28811901a965SSascha Wildner *****************************************************************************************
28821901a965SSascha Wildner *****************************************************************************************
28831901a965SSascha Wildner */
arcmsr_seek_cmd2abort(union ccb * abortccb)28841901a965SSascha Wildner static u_int8_t arcmsr_seek_cmd2abort(union ccb *abortccb)
28851901a965SSascha Wildner {
28861901a965SSascha Wildner 	struct CommandControlBlock *srb;
28871901a965SSascha Wildner 	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) abortccb->ccb_h.arcmsr_ccbacb_ptr;
28881901a965SSascha Wildner 	u_int32_t intmask_org;
28891901a965SSascha Wildner 	int i = 0;
28901901a965SSascha Wildner 
28911901a965SSascha Wildner 	acb->num_aborts++;
28921901a965SSascha Wildner 	/*
28931901a965SSascha Wildner 	***************************************************************************
28941901a965SSascha Wildner 	** It is the upper layer do abort command this lock just prior to calling us.
28951901a965SSascha Wildner 	** First determine if we currently own this command.
28961901a965SSascha Wildner 	** Start by searching the device queue. If not found
28971901a965SSascha Wildner 	** at all, and the system wanted us to just abort the
28981901a965SSascha Wildner 	** command return success.
28991901a965SSascha Wildner 	***************************************************************************
29001901a965SSascha Wildner 	*/
29011901a965SSascha Wildner 	if(acb->srboutstandingcount != 0) {
2902cc3b439cSSascha Wildner 		/* disable all outbound interrupt */
2903cc3b439cSSascha Wildner 		intmask_org = arcmsr_disable_allintr(acb);
29041901a965SSascha Wildner 		for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) {
29051901a965SSascha Wildner 			srb = acb->psrb_pool[i];
2906cc3b439cSSascha Wildner 			if(srb->srb_state == ARCMSR_SRB_START) {
29071901a965SSascha Wildner 				if(srb->pccb == abortccb) {
2908cc3b439cSSascha Wildner 					srb->srb_state = ARCMSR_SRB_ABORTED;
2909cec1e926SSascha Wildner 					kprintf("arcmsr%d:scsi id=%d lun=%jx abort srb '%p'"
29101901a965SSascha Wildner 						"outstanding command \n"
29111901a965SSascha Wildner 						, acb->pci_unit, abortccb->ccb_h.target_id
2912cec1e926SSascha Wildner 						, (uintmax_t)abortccb->ccb_h.target_lun, srb);
29131901a965SSascha Wildner 					arcmsr_polling_srbdone(acb, srb);
29141901a965SSascha Wildner 					/* enable outbound Post Queue, outbound doorbell Interrupt */
29151901a965SSascha Wildner 					arcmsr_enable_allintr(acb, intmask_org);
29161901a965SSascha Wildner 					return (TRUE);
29171901a965SSascha Wildner 				}
2918cc3b439cSSascha Wildner 			}
2919cc3b439cSSascha Wildner 		}
2920cc3b439cSSascha Wildner 		/* enable outbound Post Queue, outbound doorbell Interrupt */
2921cc3b439cSSascha Wildner 		arcmsr_enable_allintr(acb, intmask_org);
2922cc3b439cSSascha Wildner 	}
2923cc3b439cSSascha Wildner 	return(FALSE);
2924cc3b439cSSascha Wildner }
29251901a965SSascha Wildner /*
29261901a965SSascha Wildner ****************************************************************************
29271901a965SSascha Wildner ****************************************************************************
29281901a965SSascha Wildner */
arcmsr_bus_reset(struct AdapterControlBlock * acb)29291901a965SSascha Wildner static void arcmsr_bus_reset(struct AdapterControlBlock *acb)
29301901a965SSascha Wildner {
29311901a965SSascha Wildner 	int retry = 0;
29321901a965SSascha Wildner 
29331901a965SSascha Wildner 	acb->num_resets++;
29341901a965SSascha Wildner 	acb->acb_flags |= ACB_F_BUS_RESET;
29351901a965SSascha Wildner 	while(acb->srboutstandingcount != 0 && retry < 400) {
29361901a965SSascha Wildner 		arcmsr_interrupt(acb);
29371901a965SSascha Wildner 		UDELAY(25000);
29381901a965SSascha Wildner 		retry++;
29391901a965SSascha Wildner 	}
29401901a965SSascha Wildner 	arcmsr_iop_reset(acb);
29411901a965SSascha Wildner 	acb->acb_flags &= ~ACB_F_BUS_RESET;
29421901a965SSascha Wildner }
29431901a965SSascha Wildner /*
29441901a965SSascha Wildner **************************************************************************
29451901a965SSascha Wildner **************************************************************************
29461901a965SSascha Wildner */
arcmsr_handle_virtual_command(struct AdapterControlBlock * acb,union ccb * pccb)29471901a965SSascha Wildner static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb,
29481901a965SSascha Wildner 		union ccb *pccb)
29491901a965SSascha Wildner {
2950cec1e926SSascha Wildner 	if (pccb->ccb_h.target_lun) {
2951cec1e926SSascha Wildner 		pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
2952cec1e926SSascha Wildner 		xpt_done(pccb);
2953cec1e926SSascha Wildner 		return;
2954cec1e926SSascha Wildner 	}
29551901a965SSascha Wildner 	pccb->ccb_h.status |= CAM_REQ_CMP;
29561901a965SSascha Wildner 	switch (pccb->csio.cdb_io.cdb_bytes[0]) {
29571901a965SSascha Wildner 	case INQUIRY: {
29581901a965SSascha Wildner 		unsigned char inqdata[36];
29591901a965SSascha Wildner 		char *buffer = pccb->csio.data_ptr;
29601901a965SSascha Wildner 
296195696aa4SSascha Wildner 		inqdata[0] = T_PROCESSOR;	/* Periph Qualifier & Periph Dev Type */
296295696aa4SSascha Wildner 		inqdata[1] = 0;			/* rem media bit & Dev Type Modifier */
296395696aa4SSascha Wildner 		inqdata[2] = 0;			/* ISO, ECMA, & ANSI versions */
296495696aa4SSascha Wildner 		inqdata[3] = 0;
296595696aa4SSascha Wildner 		inqdata[4] = 31;		/* length of additional data */
296695696aa4SSascha Wildner 		inqdata[5] = 0;
296795696aa4SSascha Wildner 		inqdata[6] = 0;
296895696aa4SSascha Wildner 		inqdata[7] = 0;
296995696aa4SSascha Wildner 		strncpy(&inqdata[8], "Areca   ", 8);	/* Vendor Identification */
297095696aa4SSascha Wildner 		strncpy(&inqdata[16], "RAID controller ", 16);	/* Product Identification */
29711901a965SSascha Wildner 		strncpy(&inqdata[32], "R001", 4); /* Product Revision */
29721901a965SSascha Wildner 		memcpy(buffer, inqdata, sizeof(inqdata));
29731901a965SSascha Wildner 		xpt_done(pccb);
29741901a965SSascha Wildner 	}
29751901a965SSascha Wildner 	break;
29761901a965SSascha Wildner 	case WRITE_BUFFER:
29771901a965SSascha Wildner 	case READ_BUFFER: {
29781901a965SSascha Wildner 		if (arcmsr_iop_message_xfer(acb, pccb)) {
29791901a965SSascha Wildner 			pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
29801901a965SSascha Wildner 			pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
29811901a965SSascha Wildner 		}
29821901a965SSascha Wildner 		xpt_done(pccb);
29831901a965SSascha Wildner 	}
29841901a965SSascha Wildner 	break;
29851901a965SSascha Wildner 	default:
29861901a965SSascha Wildner 		xpt_done(pccb);
29871901a965SSascha Wildner 	}
29881901a965SSascha Wildner }
29891901a965SSascha Wildner /*
29901901a965SSascha Wildner *********************************************************************
29911901a965SSascha Wildner *********************************************************************
29921901a965SSascha Wildner */
arcmsr_action(struct cam_sim * psim,union ccb * pccb)29931901a965SSascha Wildner static void arcmsr_action(struct cam_sim *psim, union ccb *pccb)
29941901a965SSascha Wildner {
29951901a965SSascha Wildner 	struct AdapterControlBlock *acb;
29961901a965SSascha Wildner 
29971901a965SSascha Wildner 	acb = (struct AdapterControlBlock *) cam_sim_softc(psim);
29981901a965SSascha Wildner 	if(acb == NULL) {
29991901a965SSascha Wildner 		pccb->ccb_h.status |= CAM_REQ_INVALID;
30001901a965SSascha Wildner 		xpt_done(pccb);
30011901a965SSascha Wildner 		return;
30021901a965SSascha Wildner 	}
30031901a965SSascha Wildner 	switch (pccb->ccb_h.func_code) {
30041901a965SSascha Wildner 	case XPT_SCSI_IO: {
30051901a965SSascha Wildner 			struct CommandControlBlock *srb;
30061901a965SSascha Wildner 			int target = pccb->ccb_h.target_id;
30071901a965SSascha Wildner 
30081901a965SSascha Wildner 			if(target == 16) {
30091901a965SSascha Wildner 				/* virtual device for iop message transfer */
30101901a965SSascha Wildner 				arcmsr_handle_virtual_command(acb, pccb);
30111901a965SSascha Wildner 				return;
30121901a965SSascha Wildner 			}
30131901a965SSascha Wildner 			if((srb = arcmsr_get_freesrb(acb)) == NULL) {
30141901a965SSascha Wildner 				pccb->ccb_h.status |= CAM_RESRC_UNAVAIL;
30151901a965SSascha Wildner 				xpt_done(pccb);
30161901a965SSascha Wildner 				return;
30171901a965SSascha Wildner 			}
30181901a965SSascha Wildner 			pccb->ccb_h.arcmsr_ccbsrb_ptr = srb;
30191901a965SSascha Wildner 			pccb->ccb_h.arcmsr_ccbacb_ptr = acb;
30201901a965SSascha Wildner 			srb->pccb = pccb;
30211901a965SSascha Wildner 			if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
30221901a965SSascha Wildner 				if(!(pccb->ccb_h.flags & CAM_SCATTER_VALID)) {
30231901a965SSascha Wildner 					/* Single buffer */
30241901a965SSascha Wildner 					if(!(pccb->ccb_h.flags & CAM_DATA_PHYS)) {
30251901a965SSascha Wildner 						/* Buffer is virtual */
30261901a965SSascha Wildner 						u_int32_t error;
30271901a965SSascha Wildner 
30281901a965SSascha Wildner 						crit_enter();
3029111d54bfSSascha Wildner 						ARCMSR_LOCK_ACQUIRE(&acb->io_lock);
30301901a965SSascha Wildner 						error =	bus_dmamap_load(acb->dm_segs_dmat
30311901a965SSascha Wildner 							, srb->dm_segs_dmamap
30321901a965SSascha Wildner 							, pccb->csio.data_ptr
30331901a965SSascha Wildner 							, pccb->csio.dxfer_len
303495696aa4SSascha Wildner 							, arcmsr_execute_srb, srb, /*flags*/0);
3035111d54bfSSascha Wildner 						ARCMSR_LOCK_RELEASE(&acb->io_lock);
30361901a965SSascha Wildner 						if(error == EINPROGRESS) {
30371901a965SSascha Wildner 							xpt_freeze_simq(acb->psim, 1);
30381901a965SSascha Wildner 							pccb->ccb_h.status |= CAM_RELEASE_SIMQ;
30391901a965SSascha Wildner 						}
30401901a965SSascha Wildner 						crit_exit();
304195696aa4SSascha Wildner 					}
304295696aa4SSascha Wildner 					else {		/* Buffer is physical */
304395696aa4SSascha Wildner 						struct bus_dma_segment seg;
304495696aa4SSascha Wildner 
304595696aa4SSascha Wildner 						seg.ds_addr = (bus_addr_t)pccb->csio.data_ptr;
304695696aa4SSascha Wildner 						seg.ds_len = pccb->csio.dxfer_len;
304795696aa4SSascha Wildner 						arcmsr_execute_srb(srb, &seg, 1, 0);
30481901a965SSascha Wildner 					}
30491901a965SSascha Wildner 				} else {
30501901a965SSascha Wildner 					/* Scatter/gather list */
30511901a965SSascha Wildner 					struct bus_dma_segment *segs;
30521901a965SSascha Wildner 
30531901a965SSascha Wildner 					if((pccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0
30541901a965SSascha Wildner 					|| (pccb->ccb_h.flags & CAM_DATA_PHYS) != 0) {
30551901a965SSascha Wildner 						pccb->ccb_h.status |= CAM_PROVIDE_FAIL;
30561901a965SSascha Wildner 						xpt_done(pccb);
30571901a965SSascha Wildner 						kfree(srb, M_DEVBUF);
30581901a965SSascha Wildner 						return;
30591901a965SSascha Wildner 					}
30601901a965SSascha Wildner 					segs=(struct bus_dma_segment *)pccb->csio.data_ptr;
306195696aa4SSascha Wildner 					arcmsr_execute_srb(srb, segs, pccb->csio.sglist_cnt, 0);
30621901a965SSascha Wildner 				}
30631901a965SSascha Wildner 			} else {
306495696aa4SSascha Wildner 				arcmsr_execute_srb(srb, NULL, 0, 0);
30651901a965SSascha Wildner 			}
30661901a965SSascha Wildner 			break;
30671901a965SSascha Wildner 		}
30681901a965SSascha Wildner 	case XPT_TARGET_IO: {
30691901a965SSascha Wildner 			/* target mode not yet support vendor specific commands. */
30701901a965SSascha Wildner 			pccb->ccb_h.status |= CAM_REQ_CMP;
30711901a965SSascha Wildner 			xpt_done(pccb);
30721901a965SSascha Wildner 			break;
30731901a965SSascha Wildner 		}
30741901a965SSascha Wildner 	case XPT_PATH_INQ: {
30751901a965SSascha Wildner 			struct ccb_pathinq *cpi = &pccb->cpi;
30761901a965SSascha Wildner 
30771901a965SSascha Wildner 			cpi->version_num = 1;
30781901a965SSascha Wildner 			cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE;
30791901a965SSascha Wildner 			cpi->target_sprt = 0;
30801901a965SSascha Wildner 			cpi->hba_misc = 0;
30811901a965SSascha Wildner 			cpi->hba_eng_cnt = 0;
30821901a965SSascha Wildner 			cpi->max_target = ARCMSR_MAX_TARGETID;        /* 0-16 */
30831901a965SSascha Wildner 			cpi->max_lun = ARCMSR_MAX_TARGETLUN;	    /* 0-7 */
30841901a965SSascha Wildner 			cpi->initiator_id = ARCMSR_SCSI_INITIATOR_ID; /* 255 */
30851901a965SSascha Wildner 			cpi->bus_id = cam_sim_bus(psim);
30861901a965SSascha Wildner 			strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
30871901a965SSascha Wildner 			strncpy(cpi->hba_vid, "ARCMSR", HBA_IDLEN);
30881901a965SSascha Wildner 			strncpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN);
30891901a965SSascha Wildner 			cpi->unit_number = cam_sim_unit(psim);
3090cec1e926SSascha Wildner 			if(acb->adapter_bus_speed == ACB_BUS_SPEED_12G)
3091cec1e926SSascha Wildner 				cpi->base_transfer_speed = 1200000;
3092cec1e926SSascha Wildner 			else if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G)
3093629e42e2SSascha Wildner 				cpi->base_transfer_speed = 600000;
3094629e42e2SSascha Wildner 			else
3095629e42e2SSascha Wildner 				cpi->base_transfer_speed = 300000;
3096629e42e2SSascha Wildner 			if((acb->vendor_device_id == PCIDevVenIDARC1880) ||
3097111d54bfSSascha Wildner 			   (acb->vendor_device_id == PCIDevVenIDARC1884) ||
3098cec1e926SSascha Wildner 			   (acb->vendor_device_id == PCIDevVenIDARC1680) ||
3099cec1e926SSascha Wildner 			   (acb->vendor_device_id == PCIDevVenIDARC1214))
3100629e42e2SSascha Wildner 			{
3101629e42e2SSascha Wildner 				cpi->transport = XPORT_SAS;
3102629e42e2SSascha Wildner 				cpi->transport_version = 0;
3103629e42e2SSascha Wildner 				cpi->protocol_version = SCSI_REV_SPC2;
3104629e42e2SSascha Wildner 			}
3105629e42e2SSascha Wildner 			else
3106629e42e2SSascha Wildner 			{
31071901a965SSascha Wildner 				cpi->transport = XPORT_SPI;
31081901a965SSascha Wildner 				cpi->transport_version = 2;
31091901a965SSascha Wildner 				cpi->protocol_version = SCSI_REV_2;
3110629e42e2SSascha Wildner 			}
3111629e42e2SSascha Wildner 			cpi->protocol = PROTO_SCSI;
31121901a965SSascha Wildner 			cpi->ccb_h.status |= CAM_REQ_CMP;
31131901a965SSascha Wildner 			xpt_done(pccb);
31141901a965SSascha Wildner 			break;
31151901a965SSascha Wildner 		}
31161901a965SSascha Wildner 	case XPT_ABORT: {
31171901a965SSascha Wildner 			union ccb *pabort_ccb;
31181901a965SSascha Wildner 
31191901a965SSascha Wildner 			pabort_ccb = pccb->cab.abort_ccb;
31201901a965SSascha Wildner 			switch (pabort_ccb->ccb_h.func_code) {
31211901a965SSascha Wildner 			case XPT_ACCEPT_TARGET_IO:
31221901a965SSascha Wildner 			case XPT_IMMED_NOTIFY:
31231901a965SSascha Wildner 			case XPT_CONT_TARGET_IO:
31241901a965SSascha Wildner 				if(arcmsr_seek_cmd2abort(pabort_ccb)==TRUE) {
31251901a965SSascha Wildner 					pabort_ccb->ccb_h.status |= CAM_REQ_ABORTED;
31261901a965SSascha Wildner 					xpt_done(pabort_ccb);
31271901a965SSascha Wildner 					pccb->ccb_h.status |= CAM_REQ_CMP;
31281901a965SSascha Wildner 				} else {
31291901a965SSascha Wildner 					xpt_print_path(pabort_ccb->ccb_h.path);
31301901a965SSascha Wildner 					kprintf("Not found\n");
31311901a965SSascha Wildner 					pccb->ccb_h.status |= CAM_PATH_INVALID;
31321901a965SSascha Wildner 				}
31331901a965SSascha Wildner 				break;
31341901a965SSascha Wildner 			case XPT_SCSI_IO:
31351901a965SSascha Wildner 				pccb->ccb_h.status |= CAM_UA_ABORT;
31361901a965SSascha Wildner 				break;
31371901a965SSascha Wildner 			default:
31381901a965SSascha Wildner 				pccb->ccb_h.status |= CAM_REQ_INVALID;
31391901a965SSascha Wildner 				break;
31401901a965SSascha Wildner 			}
31411901a965SSascha Wildner 			xpt_done(pccb);
31421901a965SSascha Wildner 			break;
31431901a965SSascha Wildner 		}
31441901a965SSascha Wildner 	case XPT_RESET_BUS:
31451901a965SSascha Wildner 	case XPT_RESET_DEV: {
31461901a965SSascha Wildner 			u_int32_t	i;
31471901a965SSascha Wildner 
31481901a965SSascha Wildner 			arcmsr_bus_reset(acb);
31491901a965SSascha Wildner 			for (i=0; i < 500; i++) {
31501901a965SSascha Wildner 				DELAY(1000);
31511901a965SSascha Wildner 			}
31521901a965SSascha Wildner 			pccb->ccb_h.status |= CAM_REQ_CMP;
31531901a965SSascha Wildner 			xpt_done(pccb);
31541901a965SSascha Wildner 			break;
31551901a965SSascha Wildner 		}
31561901a965SSascha Wildner 	case XPT_TERM_IO: {
31571901a965SSascha Wildner 			pccb->ccb_h.status |= CAM_REQ_INVALID;
31581901a965SSascha Wildner 			xpt_done(pccb);
31591901a965SSascha Wildner 			break;
31601901a965SSascha Wildner 		}
31611901a965SSascha Wildner 	case XPT_GET_TRAN_SETTINGS: {
31621901a965SSascha Wildner 			struct ccb_trans_settings *cts;
31631901a965SSascha Wildner 
31641901a965SSascha Wildner 			if(pccb->ccb_h.target_id == 16) {
31651901a965SSascha Wildner 				pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL;
31661901a965SSascha Wildner 				xpt_done(pccb);
31671901a965SSascha Wildner 				break;
31681901a965SSascha Wildner 			}
31691901a965SSascha Wildner 			cts = &pccb->cts;
31701901a965SSascha Wildner 			{
31711901a965SSascha Wildner 				struct ccb_trans_settings_scsi *scsi;
31721901a965SSascha Wildner 				struct ccb_trans_settings_spi *spi;
3173629e42e2SSascha Wildner 				struct ccb_trans_settings_sas *sas;
31741901a965SSascha Wildner 
31751901a965SSascha Wildner 				scsi = &cts->proto_specific.scsi;
3176629e42e2SSascha Wildner 				scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
3177629e42e2SSascha Wildner 				scsi->valid = CTS_SCSI_VALID_TQ;
31781901a965SSascha Wildner 				cts->protocol = PROTO_SCSI;
3179629e42e2SSascha Wildner 
3180629e42e2SSascha Wildner 				if((acb->vendor_device_id == PCIDevVenIDARC1880) ||
3181111d54bfSSascha Wildner 				   (acb->vendor_device_id == PCIDevVenIDARC1884) ||
3182cec1e926SSascha Wildner 				   (acb->vendor_device_id == PCIDevVenIDARC1680) ||
3183cec1e926SSascha Wildner 				   (acb->vendor_device_id == PCIDevVenIDARC1214))
3184629e42e2SSascha Wildner 				{
3185629e42e2SSascha Wildner 					cts->protocol_version = SCSI_REV_SPC2;
3186629e42e2SSascha Wildner 					cts->transport_version = 0;
3187629e42e2SSascha Wildner 					cts->transport = XPORT_SAS;
3188629e42e2SSascha Wildner 					sas = &cts->xport_specific.sas;
3189629e42e2SSascha Wildner 					sas->valid = CTS_SAS_VALID_SPEED;
3190111d54bfSSascha Wildner 					if (acb->adapter_bus_speed == ACB_BUS_SPEED_12G)
3191cec1e926SSascha Wildner 						sas->bitrate = 1200000;
3192111d54bfSSascha Wildner 					else if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G)
3193629e42e2SSascha Wildner 						sas->bitrate = 600000;
3194111d54bfSSascha Wildner 					else if(acb->adapter_bus_speed == ACB_BUS_SPEED_3G)
3195629e42e2SSascha Wildner 						sas->bitrate = 300000;
3196629e42e2SSascha Wildner 				}
3197629e42e2SSascha Wildner 				else
3198629e42e2SSascha Wildner 				{
31991901a965SSascha Wildner 					cts->protocol_version = SCSI_REV_2;
32001901a965SSascha Wildner 					cts->transport_version = 2;
3201629e42e2SSascha Wildner 					cts->transport = XPORT_SPI;
3202629e42e2SSascha Wildner 					spi = &cts->xport_specific.spi;
32031901a965SSascha Wildner 					spi->flags = CTS_SPI_FLAGS_DISC_ENB;
3204111d54bfSSascha Wildner 					if (acb->adapter_bus_speed == ACB_BUS_SPEED_6G)
3205111d54bfSSascha Wildner 						spi->sync_period = 1;
3206111d54bfSSascha Wildner 					else
3207629e42e2SSascha Wildner 						spi->sync_period = 2;
32081901a965SSascha Wildner 					spi->sync_offset = 32;
32091901a965SSascha Wildner 					spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
32101901a965SSascha Wildner 					spi->valid = CTS_SPI_VALID_DISC
32111901a965SSascha Wildner 						| CTS_SPI_VALID_SYNC_RATE
32121901a965SSascha Wildner 						| CTS_SPI_VALID_SYNC_OFFSET
32131901a965SSascha Wildner 						| CTS_SPI_VALID_BUS_WIDTH;
3214629e42e2SSascha Wildner 				}
32151901a965SSascha Wildner 			}
32161901a965SSascha Wildner 			pccb->ccb_h.status |= CAM_REQ_CMP;
32171901a965SSascha Wildner 			xpt_done(pccb);
32181901a965SSascha Wildner 			break;
32191901a965SSascha Wildner 		}
32201901a965SSascha Wildner 	case XPT_SET_TRAN_SETTINGS: {
32211901a965SSascha Wildner 			pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL;
32221901a965SSascha Wildner 			xpt_done(pccb);
32231901a965SSascha Wildner 			break;
32241901a965SSascha Wildner 		}
322521a3f12eSSascha Wildner 	case XPT_CALC_GEOMETRY:
32261901a965SSascha Wildner 			if(pccb->ccb_h.target_id == 16) {
32271901a965SSascha Wildner 				pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL;
32281901a965SSascha Wildner 				xpt_done(pccb);
32291901a965SSascha Wildner 				break;
32301901a965SSascha Wildner 			}
323121a3f12eSSascha Wildner 			cam_calc_geometry(&pccb->ccg, 1);
32321901a965SSascha Wildner 			xpt_done(pccb);
32331901a965SSascha Wildner 			break;
32341901a965SSascha Wildner 	default:
32351901a965SSascha Wildner 		pccb->ccb_h.status |= CAM_REQ_INVALID;
32361901a965SSascha Wildner 		xpt_done(pccb);
32371901a965SSascha Wildner 		break;
32381901a965SSascha Wildner 	}
32391901a965SSascha Wildner }
32401901a965SSascha Wildner /*
32411901a965SSascha Wildner **********************************************************************
32421901a965SSascha Wildner **********************************************************************
32431901a965SSascha Wildner */
arcmsr_start_hba_bgrb(struct AdapterControlBlock * acb)32441901a965SSascha Wildner static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb)
32451901a965SSascha Wildner {
32461901a965SSascha Wildner 	acb->acb_flags |= ACB_F_MSG_START_BGRB;
32471901a965SSascha Wildner 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB);
32481901a965SSascha Wildner 	if(!arcmsr_hba_wait_msgint_ready(acb)) {
3249111d54bfSSascha Wildner 		kprintf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit);
32501901a965SSascha Wildner 	}
32511901a965SSascha Wildner }
32521901a965SSascha Wildner /*
32531901a965SSascha Wildner **********************************************************************
32541901a965SSascha Wildner **********************************************************************
32551901a965SSascha Wildner */
arcmsr_start_hbb_bgrb(struct AdapterControlBlock * acb)32561901a965SSascha Wildner static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb)
32571901a965SSascha Wildner {
3258111d54bfSSascha Wildner 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
32591901a965SSascha Wildner 	acb->acb_flags |= ACB_F_MSG_START_BGRB;
3260111d54bfSSascha Wildner 	WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_START_BGRB);
32611901a965SSascha Wildner 	if(!arcmsr_hbb_wait_msgint_ready(acb)) {
3262111d54bfSSascha Wildner 		kprintf( "arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit);
32631901a965SSascha Wildner 	}
32641901a965SSascha Wildner }
32651901a965SSascha Wildner /*
32661901a965SSascha Wildner **********************************************************************
32671901a965SSascha Wildner **********************************************************************
32681901a965SSascha Wildner */
arcmsr_start_hbc_bgrb(struct AdapterControlBlock * acb)32691901a965SSascha Wildner static void arcmsr_start_hbc_bgrb(struct AdapterControlBlock *acb)
32701901a965SSascha Wildner {
32711901a965SSascha Wildner 	acb->acb_flags |= ACB_F_MSG_START_BGRB;
32721901a965SSascha Wildner 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB);
32731901a965SSascha Wildner 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
32741901a965SSascha Wildner 	if(!arcmsr_hbc_wait_msgint_ready(acb)) {
3275111d54bfSSascha Wildner 		kprintf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit);
32761901a965SSascha Wildner 	}
32771901a965SSascha Wildner }
32781901a965SSascha Wildner /*
32791901a965SSascha Wildner **********************************************************************
32801901a965SSascha Wildner **********************************************************************
32811901a965SSascha Wildner */
arcmsr_start_hbd_bgrb(struct AdapterControlBlock * acb)3282cec1e926SSascha Wildner static void arcmsr_start_hbd_bgrb(struct AdapterControlBlock *acb)
3283cec1e926SSascha Wildner {
3284cec1e926SSascha Wildner 	acb->acb_flags |= ACB_F_MSG_START_BGRB;
3285cec1e926SSascha Wildner 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB);
3286cec1e926SSascha Wildner 	if(!arcmsr_hbd_wait_msgint_ready(acb)) {
3287cec1e926SSascha Wildner 		kprintf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit);
3288cec1e926SSascha Wildner 	}
3289cec1e926SSascha Wildner }
3290cec1e926SSascha Wildner /*
3291cec1e926SSascha Wildner **********************************************************************
3292cec1e926SSascha Wildner **********************************************************************
3293cec1e926SSascha Wildner */
arcmsr_start_hbe_bgrb(struct AdapterControlBlock * acb)3294111d54bfSSascha Wildner static void arcmsr_start_hbe_bgrb(struct AdapterControlBlock *acb)
3295111d54bfSSascha Wildner {
3296111d54bfSSascha Wildner 	acb->acb_flags |= ACB_F_MSG_START_BGRB;
3297111d54bfSSascha Wildner 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB);
3298111d54bfSSascha Wildner 	acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
3299111d54bfSSascha Wildner 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
3300111d54bfSSascha Wildner 	if(!arcmsr_hbe_wait_msgint_ready(acb)) {
3301111d54bfSSascha Wildner 		kprintf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit);
3302111d54bfSSascha Wildner 	}
3303111d54bfSSascha Wildner }
3304111d54bfSSascha Wildner /*
3305111d54bfSSascha Wildner **********************************************************************
3306111d54bfSSascha Wildner **********************************************************************
3307111d54bfSSascha Wildner */
arcmsr_start_adapter_bgrb(struct AdapterControlBlock * acb)33081901a965SSascha Wildner static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb)
33091901a965SSascha Wildner {
33101901a965SSascha Wildner 	switch (acb->adapter_type) {
33111901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_A:
33121901a965SSascha Wildner 		arcmsr_start_hba_bgrb(acb);
33131901a965SSascha Wildner 		break;
33141901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_B:
33151901a965SSascha Wildner 		arcmsr_start_hbb_bgrb(acb);
33161901a965SSascha Wildner 		break;
33171901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_C:
33181901a965SSascha Wildner 		arcmsr_start_hbc_bgrb(acb);
33191901a965SSascha Wildner 		break;
3320cec1e926SSascha Wildner 	case ACB_ADAPTER_TYPE_D:
3321cec1e926SSascha Wildner 		arcmsr_start_hbd_bgrb(acb);
3322cec1e926SSascha Wildner 		break;
3323111d54bfSSascha Wildner 	case ACB_ADAPTER_TYPE_E:
3324111d54bfSSascha Wildner 		arcmsr_start_hbe_bgrb(acb);
3325111d54bfSSascha Wildner 		break;
33261901a965SSascha Wildner 	}
33271901a965SSascha Wildner }
33281901a965SSascha Wildner /*
33291901a965SSascha Wildner **********************************************************************
33301901a965SSascha Wildner **
33311901a965SSascha Wildner **********************************************************************
33321901a965SSascha Wildner */
arcmsr_polling_hba_srbdone(struct AdapterControlBlock * acb,struct CommandControlBlock * poll_srb)33331901a965SSascha Wildner static void arcmsr_polling_hba_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
33341901a965SSascha Wildner {
33351901a965SSascha Wildner 	struct CommandControlBlock *srb;
33361901a965SSascha Wildner 	u_int32_t flag_srb, outbound_intstatus, poll_srb_done=0, poll_count=0;
33371901a965SSascha Wildner 	u_int16_t	error;
33381901a965SSascha Wildner 
33391901a965SSascha Wildner polling_ccb_retry:
33401901a965SSascha Wildner 	poll_count++;
33411901a965SSascha Wildner 	outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable;
33421901a965SSascha Wildner 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);	/*clear interrupt*/
33431901a965SSascha Wildner 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
33441901a965SSascha Wildner 	while(1) {
33451901a965SSascha Wildner 		if((flag_srb = CHIP_REG_READ32(HBA_MessageUnit,
33461901a965SSascha Wildner 			0, outbound_queueport)) == 0xFFFFFFFF) {
33471901a965SSascha Wildner 			if(poll_srb_done) {
33481901a965SSascha Wildner 				break;/*chip FIFO no ccb for completion already*/
33491901a965SSascha Wildner 			} else {
33501901a965SSascha Wildner 				UDELAY(25000);
33511901a965SSascha Wildner 				if ((poll_count > 100) && (poll_srb != NULL)) {
33521901a965SSascha Wildner 					break;
33531901a965SSascha Wildner 				}
33541901a965SSascha Wildner 				goto polling_ccb_retry;
33551901a965SSascha Wildner 			}
33561901a965SSascha Wildner 		}
33571901a965SSascha Wildner 		/* check if command done with no error*/
33581901a965SSascha Wildner 		srb = (struct CommandControlBlock *)
33591901a965SSascha Wildner 			(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
33601901a965SSascha Wildner 		error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
33611901a965SSascha Wildner 		poll_srb_done = (srb == poll_srb) ? 1:0;
3362cc3b439cSSascha Wildner 		if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
3363cc3b439cSSascha Wildner 			if(srb->srb_state == ARCMSR_SRB_ABORTED) {
3364cec1e926SSascha Wildner 				kprintf("arcmsr%d: scsi id=%d lun=%jx srb='%p'"
33651901a965SSascha Wildner 					"poll command abort successfully \n"
33661901a965SSascha Wildner 					, acb->pci_unit
33671901a965SSascha Wildner 					, srb->pccb->ccb_h.target_id
3368cec1e926SSascha Wildner 					, (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
33691901a965SSascha Wildner 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
33701901a965SSascha Wildner 				arcmsr_srb_complete(srb, 1);
33711901a965SSascha Wildner 				continue;
33721901a965SSascha Wildner 			}
33731901a965SSascha Wildner 			kprintf("arcmsr%d: polling get an illegal srb command done srb='%p'"
33741901a965SSascha Wildner 				"srboutstandingcount=%d \n"
33751901a965SSascha Wildner 				, acb->pci_unit
33761901a965SSascha Wildner 				, srb, acb->srboutstandingcount);
33771901a965SSascha Wildner 			continue;
33781901a965SSascha Wildner 		}
33791901a965SSascha Wildner 		arcmsr_report_srb_state(acb, srb, error);
33801901a965SSascha Wildner 	}	/*drain reply FIFO*/
33811901a965SSascha Wildner }
33821901a965SSascha Wildner /*
33831901a965SSascha Wildner **********************************************************************
33841901a965SSascha Wildner **
33851901a965SSascha Wildner **********************************************************************
33861901a965SSascha Wildner */
arcmsr_polling_hbb_srbdone(struct AdapterControlBlock * acb,struct CommandControlBlock * poll_srb)33871901a965SSascha Wildner static void arcmsr_polling_hbb_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
33881901a965SSascha Wildner {
33891901a965SSascha Wildner 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
33901901a965SSascha Wildner 	struct CommandControlBlock *srb;
33911901a965SSascha Wildner 	u_int32_t flag_srb, poll_srb_done=0, poll_count=0;
33921901a965SSascha Wildner 	int index;
33931901a965SSascha Wildner 	u_int16_t	error;
33941901a965SSascha Wildner 
33951901a965SSascha Wildner polling_ccb_retry:
33961901a965SSascha Wildner 	poll_count++;
3397111d54bfSSascha Wildner 	WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */
33981901a965SSascha Wildner 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
33991901a965SSascha Wildner 	while(1) {
34001901a965SSascha Wildner 		index = phbbmu->doneq_index;
34011901a965SSascha Wildner 		if((flag_srb = phbbmu->done_qbuffer[index]) == 0) {
34021901a965SSascha Wildner 			if(poll_srb_done) {
34031901a965SSascha Wildner 				break;/*chip FIFO no ccb for completion already*/
34041901a965SSascha Wildner 			} else {
34051901a965SSascha Wildner 				UDELAY(25000);
34061901a965SSascha Wildner 				if ((poll_count > 100) && (poll_srb != NULL)) {
34071901a965SSascha Wildner 					break;
34081901a965SSascha Wildner 				}
34091901a965SSascha Wildner 				goto polling_ccb_retry;
34101901a965SSascha Wildner 			}
34111901a965SSascha Wildner 		}
34121901a965SSascha Wildner 		phbbmu->done_qbuffer[index] = 0;
34131901a965SSascha Wildner 		index++;
34141901a965SSascha Wildner 		index %= ARCMSR_MAX_HBB_POSTQUEUE;     /*if last index number set it to 0 */
34151901a965SSascha Wildner 		phbbmu->doneq_index = index;
34161901a965SSascha Wildner 		/* check if command done with no error*/
34171901a965SSascha Wildner 		srb = (struct CommandControlBlock *)
34181901a965SSascha Wildner 			(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
34191901a965SSascha Wildner 		error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
34201901a965SSascha Wildner 		poll_srb_done = (srb == poll_srb) ? 1:0;
3421cc3b439cSSascha Wildner 		if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
3422cc3b439cSSascha Wildner 			if(srb->srb_state == ARCMSR_SRB_ABORTED) {
3423cec1e926SSascha Wildner 				kprintf("arcmsr%d: scsi id=%d lun=%jx srb='%p'"
34241901a965SSascha Wildner 					"poll command abort successfully \n"
34251901a965SSascha Wildner 					, acb->pci_unit
34261901a965SSascha Wildner 					, srb->pccb->ccb_h.target_id
3427cec1e926SSascha Wildner 					, (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
34281901a965SSascha Wildner 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
34291901a965SSascha Wildner 				arcmsr_srb_complete(srb, 1);
34301901a965SSascha Wildner 				continue;
34311901a965SSascha Wildner 			}
34321901a965SSascha Wildner 			kprintf("arcmsr%d: polling get an illegal srb command done srb='%p'"
34331901a965SSascha Wildner 				"srboutstandingcount=%d \n"
34341901a965SSascha Wildner 				, acb->pci_unit
34351901a965SSascha Wildner 				, srb, acb->srboutstandingcount);
34361901a965SSascha Wildner 			continue;
34371901a965SSascha Wildner 		}
34381901a965SSascha Wildner 		arcmsr_report_srb_state(acb, srb, error);
34391901a965SSascha Wildner 	}	/*drain reply FIFO*/
34401901a965SSascha Wildner }
34411901a965SSascha Wildner /*
34421901a965SSascha Wildner **********************************************************************
34431901a965SSascha Wildner **
34441901a965SSascha Wildner **********************************************************************
34451901a965SSascha Wildner */
arcmsr_polling_hbc_srbdone(struct AdapterControlBlock * acb,struct CommandControlBlock * poll_srb)34461901a965SSascha Wildner static void arcmsr_polling_hbc_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
34471901a965SSascha Wildner {
34481901a965SSascha Wildner 	struct CommandControlBlock *srb;
34491901a965SSascha Wildner 	u_int32_t flag_srb, poll_srb_done=0, poll_count=0;
34501901a965SSascha Wildner 	u_int16_t	error;
34511901a965SSascha Wildner 
34521901a965SSascha Wildner polling_ccb_retry:
34531901a965SSascha Wildner 	poll_count++;
34541901a965SSascha Wildner 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
34551901a965SSascha Wildner 	while(1) {
34561901a965SSascha Wildner 		if(!(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR)) {
34571901a965SSascha Wildner 			if(poll_srb_done) {
34581901a965SSascha Wildner 				break;/*chip FIFO no ccb for completion already*/
34591901a965SSascha Wildner 			} else {
34601901a965SSascha Wildner 				UDELAY(25000);
34611901a965SSascha Wildner 				if ((poll_count > 100) && (poll_srb != NULL)) {
34621901a965SSascha Wildner 					break;
34631901a965SSascha Wildner 				}
34641901a965SSascha Wildner 				if (acb->srboutstandingcount == 0) {
34651901a965SSascha Wildner 				    break;
34661901a965SSascha Wildner 				}
34671901a965SSascha Wildner 				goto polling_ccb_retry;
34681901a965SSascha Wildner 			}
34691901a965SSascha Wildner 		}
34701901a965SSascha Wildner 		flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low);
34711901a965SSascha Wildner 		/* check if command done with no error*/
3472cc3b439cSSascha Wildner 		srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/
34731901a965SSascha Wildner 		error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE;
34741901a965SSascha Wildner 		if (poll_srb != NULL)
34751901a965SSascha Wildner 			poll_srb_done = (srb == poll_srb) ? 1:0;
3476cc3b439cSSascha Wildner 		if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
3477cc3b439cSSascha Wildner 			if(srb->srb_state == ARCMSR_SRB_ABORTED) {
3478cec1e926SSascha Wildner 				kprintf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n"
3479cec1e926SSascha Wildner 						, acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
3480cec1e926SSascha Wildner 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
3481cec1e926SSascha Wildner 				arcmsr_srb_complete(srb, 1);
3482cec1e926SSascha Wildner 				continue;
3483cec1e926SSascha Wildner 			}
3484cec1e926SSascha Wildner 			kprintf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n"
3485cec1e926SSascha Wildner 					, acb->pci_unit, srb, acb->srboutstandingcount);
3486cec1e926SSascha Wildner 			continue;
3487cec1e926SSascha Wildner 		}
3488cec1e926SSascha Wildner 		arcmsr_report_srb_state(acb, srb, error);
3489cec1e926SSascha Wildner 	}	/*drain reply FIFO*/
3490cec1e926SSascha Wildner }
3491cec1e926SSascha Wildner /*
3492cec1e926SSascha Wildner **********************************************************************
3493cec1e926SSascha Wildner **
3494cec1e926SSascha Wildner **********************************************************************
3495cec1e926SSascha Wildner */
arcmsr_polling_hbd_srbdone(struct AdapterControlBlock * acb,struct CommandControlBlock * poll_srb)3496cec1e926SSascha Wildner static void arcmsr_polling_hbd_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
3497cec1e926SSascha Wildner {
3498cec1e926SSascha Wildner 	struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
3499cec1e926SSascha Wildner 	struct CommandControlBlock *srb;
3500cec1e926SSascha Wildner 	u_int32_t flag_srb, poll_srb_done=0, poll_count=0;
3501cec1e926SSascha Wildner 	u_int32_t outbound_write_pointer;
3502cec1e926SSascha Wildner 	u_int16_t	error, doneq_index;
3503cec1e926SSascha Wildner 
3504cec1e926SSascha Wildner polling_ccb_retry:
3505cec1e926SSascha Wildner 	poll_count++;
3506cec1e926SSascha Wildner 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
3507cec1e926SSascha Wildner 	while(1) {
3508cec1e926SSascha Wildner 		outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow;
3509cec1e926SSascha Wildner 		doneq_index = phbdmu->doneq_index;
3510cec1e926SSascha Wildner 		if ((outbound_write_pointer & 0xFF) == (doneq_index & 0xFF)) {
3511cec1e926SSascha Wildner 			if(poll_srb_done) {
3512cec1e926SSascha Wildner 				break;/*chip FIFO no ccb for completion already*/
3513cec1e926SSascha Wildner 			} else {
3514cec1e926SSascha Wildner 				UDELAY(25000);
3515cec1e926SSascha Wildner 				if ((poll_count > 100) && (poll_srb != NULL)) {
3516cec1e926SSascha Wildner 					break;
3517cec1e926SSascha Wildner 				}
3518cec1e926SSascha Wildner 				if (acb->srboutstandingcount == 0) {
3519cec1e926SSascha Wildner 					break;
3520cec1e926SSascha Wildner 				}
3521cec1e926SSascha Wildner 				goto polling_ccb_retry;
3522cec1e926SSascha Wildner 			}
3523cec1e926SSascha Wildner 		}
3524cec1e926SSascha Wildner 		doneq_index = arcmsr_get_doneq_index(phbdmu);
3525cec1e926SSascha Wildner 		flag_srb = phbdmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow;
3526cec1e926SSascha Wildner 		/* check if command done with no error*/
3527cec1e926SSascha Wildner 		srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/
3528cec1e926SSascha Wildner 		error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
3529cec1e926SSascha Wildner 		CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_read_pointer, doneq_index);
3530cec1e926SSascha Wildner 		if (poll_srb != NULL)
3531cec1e926SSascha Wildner 			poll_srb_done = (srb == poll_srb) ? 1:0;
3532cec1e926SSascha Wildner 		if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
3533cec1e926SSascha Wildner 			if(srb->srb_state == ARCMSR_SRB_ABORTED) {
3534cec1e926SSascha Wildner 				kprintf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n"
3535cec1e926SSascha Wildner 						, acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
35361901a965SSascha Wildner 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
35371901a965SSascha Wildner 				arcmsr_srb_complete(srb, 1);
35381901a965SSascha Wildner 				continue;
35391901a965SSascha Wildner 			}
35401901a965SSascha Wildner 			kprintf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n"
35411901a965SSascha Wildner 					, acb->pci_unit, srb, acb->srboutstandingcount);
35421901a965SSascha Wildner 			continue;
35431901a965SSascha Wildner 		}
35441901a965SSascha Wildner 		arcmsr_report_srb_state(acb, srb, error);
35451901a965SSascha Wildner 	}	/*drain reply FIFO*/
35461901a965SSascha Wildner }
35471901a965SSascha Wildner /*
35481901a965SSascha Wildner **********************************************************************
3549111d54bfSSascha Wildner **
3550111d54bfSSascha Wildner **********************************************************************
3551111d54bfSSascha Wildner */
arcmsr_polling_hbe_srbdone(struct AdapterControlBlock * acb,struct CommandControlBlock * poll_srb)3552111d54bfSSascha Wildner static void arcmsr_polling_hbe_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
3553111d54bfSSascha Wildner {
3554111d54bfSSascha Wildner 	struct CommandControlBlock *srb;
3555111d54bfSSascha Wildner 	u_int32_t poll_srb_done=0, poll_count=0, doneq_index;
3556111d54bfSSascha Wildner 	u_int16_t	error, cmdSMID;
3557111d54bfSSascha Wildner 
3558111d54bfSSascha Wildner polling_ccb_retry:
3559111d54bfSSascha Wildner 	poll_count++;
3560111d54bfSSascha Wildner 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
3561111d54bfSSascha Wildner 	while(1) {
3562111d54bfSSascha Wildner 		doneq_index = acb->doneq_index;
3563111d54bfSSascha Wildner 		if((CHIP_REG_READ32(HBE_MessageUnit, 0, reply_post_producer_index) & 0xFFFF) == doneq_index) {
3564111d54bfSSascha Wildner 			if(poll_srb_done) {
3565111d54bfSSascha Wildner 				break;/*chip FIFO no ccb for completion already*/
3566111d54bfSSascha Wildner 			} else {
3567111d54bfSSascha Wildner 				UDELAY(25000);
3568111d54bfSSascha Wildner 			    if ((poll_count > 100) && (poll_srb != NULL)) {
3569111d54bfSSascha Wildner 					break;
3570111d54bfSSascha Wildner 				}
3571111d54bfSSascha Wildner 			    if (acb->srboutstandingcount == 0) {
3572111d54bfSSascha Wildner 				    break;
3573111d54bfSSascha Wildner 			    }
3574111d54bfSSascha Wildner 				goto polling_ccb_retry;
3575111d54bfSSascha Wildner 			}
3576111d54bfSSascha Wildner 		}
3577111d54bfSSascha Wildner 		cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID;
3578111d54bfSSascha Wildner 		doneq_index++;
3579111d54bfSSascha Wildner 		if (doneq_index >= acb->completionQ_entry)
3580111d54bfSSascha Wildner 			doneq_index = 0;
3581111d54bfSSascha Wildner 		acb->doneq_index = doneq_index;
3582111d54bfSSascha Wildner 		srb = acb->psrb_pool[cmdSMID];
3583111d54bfSSascha Wildner 		error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
3584111d54bfSSascha Wildner 		if (poll_srb != NULL)
3585111d54bfSSascha Wildner 			poll_srb_done = (srb == poll_srb) ? 1:0;
3586111d54bfSSascha Wildner 		if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
3587111d54bfSSascha Wildner 			if(srb->srb_state == ARCMSR_SRB_ABORTED) {
3588111d54bfSSascha Wildner 				kprintf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n"
3589111d54bfSSascha Wildner 						, acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
3590111d54bfSSascha Wildner 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
3591111d54bfSSascha Wildner 				arcmsr_srb_complete(srb, 1);
3592111d54bfSSascha Wildner 				continue;
3593111d54bfSSascha Wildner 			}
3594111d54bfSSascha Wildner 			kprintf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n"
3595111d54bfSSascha Wildner 					, acb->pci_unit, srb, acb->srboutstandingcount);
3596111d54bfSSascha Wildner 			continue;
3597111d54bfSSascha Wildner 		}
3598111d54bfSSascha Wildner 		arcmsr_report_srb_state(acb, srb, error);
3599111d54bfSSascha Wildner 	}	/*drain reply FIFO*/
3600111d54bfSSascha Wildner 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, reply_post_producer_index, doneq_index);
3601111d54bfSSascha Wildner }
3602111d54bfSSascha Wildner /*
3603111d54bfSSascha Wildner **********************************************************************
36041901a965SSascha Wildner **********************************************************************
36051901a965SSascha Wildner */
arcmsr_polling_srbdone(struct AdapterControlBlock * acb,struct CommandControlBlock * poll_srb)36061901a965SSascha Wildner static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
36071901a965SSascha Wildner {
36081901a965SSascha Wildner 	switch (acb->adapter_type) {
36091901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_A: {
36101901a965SSascha Wildner 			arcmsr_polling_hba_srbdone(acb, poll_srb);
36111901a965SSascha Wildner 		}
36121901a965SSascha Wildner 		break;
36131901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_B: {
36141901a965SSascha Wildner 			arcmsr_polling_hbb_srbdone(acb, poll_srb);
36151901a965SSascha Wildner 		}
36161901a965SSascha Wildner 		break;
36171901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_C: {
36181901a965SSascha Wildner 			arcmsr_polling_hbc_srbdone(acb, poll_srb);
36191901a965SSascha Wildner 		}
36201901a965SSascha Wildner 		break;
3621cec1e926SSascha Wildner 	case ACB_ADAPTER_TYPE_D: {
3622cec1e926SSascha Wildner 			arcmsr_polling_hbd_srbdone(acb, poll_srb);
3623cec1e926SSascha Wildner 		}
3624cec1e926SSascha Wildner 		break;
3625111d54bfSSascha Wildner 	case ACB_ADAPTER_TYPE_E: {
3626111d54bfSSascha Wildner 			arcmsr_polling_hbe_srbdone(acb, poll_srb);
3627111d54bfSSascha Wildner 		}
3628111d54bfSSascha Wildner 		break;
36291901a965SSascha Wildner 	}
36301901a965SSascha Wildner }
36311901a965SSascha Wildner /*
36321901a965SSascha Wildner **********************************************************************
36331901a965SSascha Wildner **********************************************************************
36341901a965SSascha Wildner */
arcmsr_get_hba_config(struct AdapterControlBlock * acb)36351901a965SSascha Wildner static void arcmsr_get_hba_config(struct AdapterControlBlock *acb)
36361901a965SSascha Wildner {
36371901a965SSascha Wildner 	char *acb_firm_model = acb->firm_model;
36381901a965SSascha Wildner 	char *acb_firm_version = acb->firm_version;
36391901a965SSascha Wildner 	char *acb_device_map = acb->device_map;
36401901a965SSascha Wildner 	size_t iop_firm_model = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);	/*firm_model,15,60-67*/
36411901a965SSascha Wildner 	size_t iop_firm_version = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]);	/*firm_version,17,68-83*/
36421901a965SSascha Wildner 	size_t iop_device_map = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
36431901a965SSascha Wildner 	int i;
36441901a965SSascha Wildner 
36451901a965SSascha Wildner 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
36461901a965SSascha Wildner 	if(!arcmsr_hba_wait_msgint_ready(acb)) {
36471901a965SSascha Wildner 		kprintf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
36481901a965SSascha Wildner 	}
36491901a965SSascha Wildner 	i = 0;
36501901a965SSascha Wildner 	while(i < 8) {
36511901a965SSascha Wildner 		*acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i);
36521901a965SSascha Wildner 		/* 8 bytes firm_model, 15, 60-67*/
36531901a965SSascha Wildner 		acb_firm_model++;
36541901a965SSascha Wildner 		i++;
36551901a965SSascha Wildner 	}
36561901a965SSascha Wildner 	i=0;
36571901a965SSascha Wildner 	while(i < 16) {
36581901a965SSascha Wildner 		*acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i);
36591901a965SSascha Wildner 		/* 16 bytes firm_version, 17, 68-83*/
36601901a965SSascha Wildner 		acb_firm_version++;
36611901a965SSascha Wildner 		i++;
36621901a965SSascha Wildner 	}
36631901a965SSascha Wildner 	i=0;
36641901a965SSascha Wildner 	while(i < 16) {
36651901a965SSascha Wildner 		*acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i);
36661901a965SSascha Wildner 		acb_device_map++;
36671901a965SSascha Wildner 		i++;
36681901a965SSascha Wildner 	}
3669cec1e926SSascha Wildner 	kprintf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version);
36701901a965SSascha Wildner 	acb->firm_request_len = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[1]);   /*firm_request_len, 1, 04-07*/
36711901a965SSascha Wildner 	acb->firm_numbers_queue = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/
36721901a965SSascha Wildner 	acb->firm_sdram_size = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[3]);    /*firm_sdram_size, 3, 12-15*/
36731901a965SSascha Wildner 	acb->firm_ide_channels = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[4]);  /*firm_ide_channels, 4, 16-19*/
36741901a965SSascha Wildner 	acb->firm_cfg_version = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);	/*firm_cfg_version,  25, 	  */
3675cec1e926SSascha Wildner 	if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD)
3676cec1e926SSascha Wildner 		acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1;
3677cec1e926SSascha Wildner 	else
3678cec1e926SSascha Wildner 		acb->maxOutstanding = acb->firm_numbers_queue - 1;
36791901a965SSascha Wildner }
36801901a965SSascha Wildner /*
36811901a965SSascha Wildner **********************************************************************
36821901a965SSascha Wildner **********************************************************************
36831901a965SSascha Wildner */
arcmsr_get_hbb_config(struct AdapterControlBlock * acb)36841901a965SSascha Wildner static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb)
36851901a965SSascha Wildner {
3686111d54bfSSascha Wildner 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
36871901a965SSascha Wildner 	char *acb_firm_model = acb->firm_model;
36881901a965SSascha Wildner 	char *acb_firm_version = acb->firm_version;
36891901a965SSascha Wildner 	char *acb_device_map = acb->device_map;
36901901a965SSascha Wildner 	size_t iop_firm_model = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);	/*firm_model,15,60-67*/
36911901a965SSascha Wildner 	size_t iop_firm_version = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]);	/*firm_version,17,68-83*/
36921901a965SSascha Wildner 	size_t iop_device_map = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
36931901a965SSascha Wildner 	int i;
36941901a965SSascha Wildner 
3695111d54bfSSascha Wildner 	WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG);
36961901a965SSascha Wildner 	if(!arcmsr_hbb_wait_msgint_ready(acb)) {
36971901a965SSascha Wildner 		kprintf( "arcmsr%d: wait" "'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
36981901a965SSascha Wildner 	}
36991901a965SSascha Wildner 	i = 0;
37001901a965SSascha Wildner 	while(i < 8) {
37011901a965SSascha Wildner 		*acb_firm_model = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_model+i);
37021901a965SSascha Wildner 		/* 8 bytes firm_model, 15, 60-67*/
37031901a965SSascha Wildner 		acb_firm_model++;
37041901a965SSascha Wildner 		i++;
37051901a965SSascha Wildner 	}
37061901a965SSascha Wildner 	i = 0;
37071901a965SSascha Wildner 	while(i < 16) {
37081901a965SSascha Wildner 		*acb_firm_version = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_version+i);
37091901a965SSascha Wildner 		/* 16 bytes firm_version, 17, 68-83*/
37101901a965SSascha Wildner 		acb_firm_version++;
37111901a965SSascha Wildner 		i++;
37121901a965SSascha Wildner 	}
37131901a965SSascha Wildner 	i = 0;
37141901a965SSascha Wildner 	while(i < 16) {
37151901a965SSascha Wildner 		*acb_device_map = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_device_map+i);
37161901a965SSascha Wildner 		acb_device_map++;
37171901a965SSascha Wildner 		i++;
37181901a965SSascha Wildner 	}
3719cec1e926SSascha Wildner 	kprintf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version);
37201901a965SSascha Wildner 	acb->firm_request_len = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1]);   /*firm_request_len, 1, 04-07*/
37211901a965SSascha Wildner 	acb->firm_numbers_queue = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/
37221901a965SSascha Wildner 	acb->firm_sdram_size = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3]);    /*firm_sdram_size, 3, 12-15*/
37231901a965SSascha Wildner 	acb->firm_ide_channels = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4]);  /*firm_ide_channels, 4, 16-19*/
37241901a965SSascha Wildner 	acb->firm_cfg_version = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);	/*firm_cfg_version,  25, 	  */
3725cec1e926SSascha Wildner 	if(acb->firm_numbers_queue > ARCMSR_MAX_HBB_POSTQUEUE)
3726cec1e926SSascha Wildner 		acb->maxOutstanding = ARCMSR_MAX_HBB_POSTQUEUE - 1;
3727cec1e926SSascha Wildner 	else
3728cec1e926SSascha Wildner 		acb->maxOutstanding = acb->firm_numbers_queue - 1;
37291901a965SSascha Wildner }
37301901a965SSascha Wildner /*
37311901a965SSascha Wildner **********************************************************************
37321901a965SSascha Wildner **********************************************************************
37331901a965SSascha Wildner */
arcmsr_get_hbc_config(struct AdapterControlBlock * acb)37341901a965SSascha Wildner static void arcmsr_get_hbc_config(struct AdapterControlBlock *acb)
37351901a965SSascha Wildner {
37361901a965SSascha Wildner 	char *acb_firm_model = acb->firm_model;
37371901a965SSascha Wildner 	char *acb_firm_version = acb->firm_version;
37381901a965SSascha Wildner 	char *acb_device_map = acb->device_map;
37391901a965SSascha Wildner 	size_t iop_firm_model = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);   /*firm_model,15,60-67*/
37401901a965SSascha Wildner 	size_t iop_firm_version = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/
37411901a965SSascha Wildner 	size_t iop_device_map = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
37421901a965SSascha Wildner 	int i;
37431901a965SSascha Wildner 
37441901a965SSascha Wildner 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
37451901a965SSascha Wildner 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
37461901a965SSascha Wildner 	if(!arcmsr_hbc_wait_msgint_ready(acb)) {
37471901a965SSascha Wildner 		kprintf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
37481901a965SSascha Wildner 	}
37491901a965SSascha Wildner 	i = 0;
37501901a965SSascha Wildner 	while(i < 8) {
37511901a965SSascha Wildner 		*acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i);
37521901a965SSascha Wildner 		/* 8 bytes firm_model, 15, 60-67*/
37531901a965SSascha Wildner 		acb_firm_model++;
37541901a965SSascha Wildner 		i++;
37551901a965SSascha Wildner 	}
37561901a965SSascha Wildner 	i = 0;
37571901a965SSascha Wildner 	while(i < 16) {
37581901a965SSascha Wildner 		*acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i);
37591901a965SSascha Wildner 		/* 16 bytes firm_version, 17, 68-83*/
37601901a965SSascha Wildner 		acb_firm_version++;
37611901a965SSascha Wildner 		i++;
37621901a965SSascha Wildner 	}
37631901a965SSascha Wildner 	i = 0;
37641901a965SSascha Wildner 	while(i < 16) {
37651901a965SSascha Wildner 		*acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i);
37661901a965SSascha Wildner 		acb_device_map++;
37671901a965SSascha Wildner 		i++;
37681901a965SSascha Wildner 	}
3769cec1e926SSascha Wildner 	kprintf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version);
37701901a965SSascha Wildner 	acb->firm_request_len	= CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[1]);	/*firm_request_len,   1, 04-07*/
37711901a965SSascha Wildner 	acb->firm_numbers_queue	= CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[2]);	/*firm_numbers_queue, 2, 08-11*/
37721901a965SSascha Wildner 	acb->firm_sdram_size	= CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[3]);	/*firm_sdram_size,    3, 12-15*/
37731901a965SSascha Wildner 	acb->firm_ide_channels	= CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[4]);	/*firm_ide_channels,  4, 16-19*/
37741901a965SSascha Wildner 	acb->firm_cfg_version	= CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);	/*firm_cfg_version,  25, 	  */
3775cec1e926SSascha Wildner 	if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD)
3776cec1e926SSascha Wildner 		acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1;
3777cec1e926SSascha Wildner 	else
3778cec1e926SSascha Wildner 		acb->maxOutstanding = acb->firm_numbers_queue - 1;
3779cec1e926SSascha Wildner }
3780cec1e926SSascha Wildner /*
3781cec1e926SSascha Wildner **********************************************************************
3782cec1e926SSascha Wildner **********************************************************************
3783cec1e926SSascha Wildner */
arcmsr_get_hbd_config(struct AdapterControlBlock * acb)3784cec1e926SSascha Wildner static void arcmsr_get_hbd_config(struct AdapterControlBlock *acb)
3785cec1e926SSascha Wildner {
3786cec1e926SSascha Wildner 	char *acb_firm_model = acb->firm_model;
3787cec1e926SSascha Wildner 	char *acb_firm_version = acb->firm_version;
3788cec1e926SSascha Wildner 	char *acb_device_map = acb->device_map;
3789cec1e926SSascha Wildner 	size_t iop_firm_model = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);   /*firm_model,15,60-67*/
3790cec1e926SSascha Wildner 	size_t iop_firm_version = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/
3791cec1e926SSascha Wildner 	size_t iop_device_map = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
3792cec1e926SSascha Wildner 	int i;
3793cec1e926SSascha Wildner 
3794cec1e926SSascha Wildner 	if(CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE)
3795cec1e926SSascha Wildner 		CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR);
3796cec1e926SSascha Wildner 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
3797cec1e926SSascha Wildner 	if(!arcmsr_hbd_wait_msgint_ready(acb)) {
3798cec1e926SSascha Wildner 		kprintf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
3799cec1e926SSascha Wildner 	}
3800cec1e926SSascha Wildner 	i = 0;
3801cec1e926SSascha Wildner 	while(i < 8) {
3802cec1e926SSascha Wildner 		*acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i);
3803cec1e926SSascha Wildner 		/* 8 bytes firm_model, 15, 60-67*/
3804cec1e926SSascha Wildner 		acb_firm_model++;
3805cec1e926SSascha Wildner 		i++;
3806cec1e926SSascha Wildner 	}
3807cec1e926SSascha Wildner 	i = 0;
3808cec1e926SSascha Wildner 	while(i < 16) {
3809cec1e926SSascha Wildner 		*acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i);
3810cec1e926SSascha Wildner 		/* 16 bytes firm_version, 17, 68-83*/
3811cec1e926SSascha Wildner 		acb_firm_version++;
3812cec1e926SSascha Wildner 		i++;
3813cec1e926SSascha Wildner 	}
3814cec1e926SSascha Wildner 	i = 0;
3815cec1e926SSascha Wildner 	while(i < 16) {
3816cec1e926SSascha Wildner 		*acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i);
3817cec1e926SSascha Wildner 		acb_device_map++;
3818cec1e926SSascha Wildner 		i++;
3819cec1e926SSascha Wildner 	}
3820cec1e926SSascha Wildner 	kprintf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version);
3821111d54bfSSascha Wildner 	acb->firm_request_len	= CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[1]);	/*firm_request_len,   1, 04-07*/
3822111d54bfSSascha Wildner 	acb->firm_numbers_queue	= CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[2]);	/*firm_numbers_queue, 2, 08-11*/
3823111d54bfSSascha Wildner 	acb->firm_sdram_size	= CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[3]);	/*firm_sdram_size,    3, 12-15*/
3824111d54bfSSascha Wildner 	acb->firm_ide_channels	= CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[4]);	/*firm_ide_channels,  4, 16-19*/
3825cec1e926SSascha Wildner 	acb->firm_cfg_version	= CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);	/*firm_cfg_version,  25, 	  */
3826cec1e926SSascha Wildner 	if(acb->firm_numbers_queue > ARCMSR_MAX_HBD_POSTQUEUE)
3827cec1e926SSascha Wildner 		acb->maxOutstanding = ARCMSR_MAX_HBD_POSTQUEUE - 1;
3828cec1e926SSascha Wildner 	else
3829cec1e926SSascha Wildner 		acb->maxOutstanding = acb->firm_numbers_queue - 1;
38301901a965SSascha Wildner }
38311901a965SSascha Wildner /*
38321901a965SSascha Wildner **********************************************************************
38331901a965SSascha Wildner **********************************************************************
38341901a965SSascha Wildner */
arcmsr_get_hbe_config(struct AdapterControlBlock * acb)3835111d54bfSSascha Wildner static void arcmsr_get_hbe_config(struct AdapterControlBlock *acb)
3836111d54bfSSascha Wildner {
3837111d54bfSSascha Wildner 	char *acb_firm_model = acb->firm_model;
3838111d54bfSSascha Wildner 	char *acb_firm_version = acb->firm_version;
3839111d54bfSSascha Wildner 	char *acb_device_map = acb->device_map;
3840111d54bfSSascha Wildner 	size_t iop_firm_model = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);   /*firm_model,15,60-67*/
3841111d54bfSSascha Wildner 	size_t iop_firm_version = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/
3842111d54bfSSascha Wildner 	size_t iop_device_map = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
3843111d54bfSSascha Wildner 	int i;
3844111d54bfSSascha Wildner 
3845111d54bfSSascha Wildner 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
3846111d54bfSSascha Wildner 	acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
3847111d54bfSSascha Wildner 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
3848111d54bfSSascha Wildner 	if(!arcmsr_hbe_wait_msgint_ready(acb)) {
3849111d54bfSSascha Wildner 		kprintf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
3850111d54bfSSascha Wildner 	}
3851111d54bfSSascha Wildner 
3852111d54bfSSascha Wildner 	i = 0;
3853111d54bfSSascha Wildner 	while(i < 8) {
3854111d54bfSSascha Wildner 		*acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i);
3855111d54bfSSascha Wildner 		/* 8 bytes firm_model, 15, 60-67*/
3856111d54bfSSascha Wildner 		acb_firm_model++;
3857111d54bfSSascha Wildner 		i++;
3858111d54bfSSascha Wildner 	}
3859111d54bfSSascha Wildner 	i = 0;
3860111d54bfSSascha Wildner 	while(i < 16) {
3861111d54bfSSascha Wildner 		*acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i);
3862111d54bfSSascha Wildner 		/* 16 bytes firm_version, 17, 68-83*/
3863111d54bfSSascha Wildner 		acb_firm_version++;
3864111d54bfSSascha Wildner 		i++;
3865111d54bfSSascha Wildner 	}
3866111d54bfSSascha Wildner 	i = 0;
3867111d54bfSSascha Wildner 	while(i < 16) {
3868111d54bfSSascha Wildner 		*acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i);
3869111d54bfSSascha Wildner 		acb_device_map++;
3870111d54bfSSascha Wildner 		i++;
3871111d54bfSSascha Wildner 	}
3872111d54bfSSascha Wildner 	kprintf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version);
3873111d54bfSSascha Wildner 	acb->firm_request_len	= CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[1]);	/*firm_request_len,   1, 04-07*/
3874111d54bfSSascha Wildner 	acb->firm_numbers_queue	= CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[2]);	/*firm_numbers_queue, 2, 08-11*/
3875111d54bfSSascha Wildner 	acb->firm_sdram_size	= CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[3]);	/*firm_sdram_size,    3, 12-15*/
3876111d54bfSSascha Wildner 	acb->firm_ide_channels	= CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[4]);	/*firm_ide_channels,  4, 16-19*/
3877111d54bfSSascha Wildner 	acb->firm_cfg_version	= CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);	/*firm_cfg_version,  25, 	  */
3878111d54bfSSascha Wildner 	if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD)
3879111d54bfSSascha Wildner 		acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1;
3880111d54bfSSascha Wildner 	else
3881111d54bfSSascha Wildner 		acb->maxOutstanding = acb->firm_numbers_queue - 1;
3882111d54bfSSascha Wildner }
3883111d54bfSSascha Wildner /*
3884111d54bfSSascha Wildner **********************************************************************
3885111d54bfSSascha Wildner **********************************************************************
3886111d54bfSSascha Wildner */
arcmsr_get_firmware_spec(struct AdapterControlBlock * acb)38871901a965SSascha Wildner static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
38881901a965SSascha Wildner {
38891901a965SSascha Wildner 	switch (acb->adapter_type) {
38901901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_A: {
38911901a965SSascha Wildner 			arcmsr_get_hba_config(acb);
38921901a965SSascha Wildner 		}
38931901a965SSascha Wildner 		break;
38941901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_B: {
38951901a965SSascha Wildner 			arcmsr_get_hbb_config(acb);
38961901a965SSascha Wildner 		}
38971901a965SSascha Wildner 		break;
38981901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_C: {
38991901a965SSascha Wildner 			arcmsr_get_hbc_config(acb);
39001901a965SSascha Wildner 		}
39011901a965SSascha Wildner 		break;
3902cec1e926SSascha Wildner 	case ACB_ADAPTER_TYPE_D: {
3903cec1e926SSascha Wildner 			arcmsr_get_hbd_config(acb);
3904cec1e926SSascha Wildner 		}
3905cec1e926SSascha Wildner 		break;
3906111d54bfSSascha Wildner 	case ACB_ADAPTER_TYPE_E: {
3907111d54bfSSascha Wildner 			arcmsr_get_hbe_config(acb);
3908111d54bfSSascha Wildner 		}
3909111d54bfSSascha Wildner 		break;
39101901a965SSascha Wildner 	}
39111901a965SSascha Wildner }
39121901a965SSascha Wildner /*
39131901a965SSascha Wildner **********************************************************************
39141901a965SSascha Wildner **********************************************************************
39151901a965SSascha Wildner */
arcmsr_wait_firmware_ready(struct AdapterControlBlock * acb)39161901a965SSascha Wildner static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb)
39171901a965SSascha Wildner {
39181901a965SSascha Wildner 	int	timeout=0;
39191901a965SSascha Wildner 
39201901a965SSascha Wildner 	switch (acb->adapter_type) {
39211901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_A: {
39221901a965SSascha Wildner 			while ((CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0)
39231901a965SSascha Wildner 			{
39241901a965SSascha Wildner 				if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */
39251901a965SSascha Wildner 				{
39261901a965SSascha Wildner 					kprintf( "arcmsr%d:timed out waiting for firmware \n", acb->pci_unit);
39271901a965SSascha Wildner 					return;
39281901a965SSascha Wildner 				}
39291901a965SSascha Wildner 				UDELAY(15000); /* wait 15 milli-seconds */
39301901a965SSascha Wildner 			}
39311901a965SSascha Wildner 		}
39321901a965SSascha Wildner 		break;
39331901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_B: {
3934111d54bfSSascha Wildner 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
3935111d54bfSSascha Wildner 			while ((READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & ARCMSR_MESSAGE_FIRMWARE_OK) == 0)
39361901a965SSascha Wildner 			{
39371901a965SSascha Wildner 				if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */
39381901a965SSascha Wildner 				{
39391901a965SSascha Wildner 					kprintf( "arcmsr%d: timed out waiting for firmware \n", acb->pci_unit);
39401901a965SSascha Wildner 					return;
39411901a965SSascha Wildner 				}
39421901a965SSascha Wildner 				UDELAY(15000); /* wait 15 milli-seconds */
39431901a965SSascha Wildner 			}
3944111d54bfSSascha Wildner 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
39451901a965SSascha Wildner 		}
39461901a965SSascha Wildner 		break;
39471901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_C: {
39481901a965SSascha Wildner 			while ((CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0)
39491901a965SSascha Wildner 			{
39501901a965SSascha Wildner 				if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */
39511901a965SSascha Wildner 				{
39521901a965SSascha Wildner 					kprintf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit);
39531901a965SSascha Wildner 					return;
39541901a965SSascha Wildner 				}
39551901a965SSascha Wildner 				UDELAY(15000); /* wait 15 milli-seconds */
39561901a965SSascha Wildner 			}
39571901a965SSascha Wildner 		}
39581901a965SSascha Wildner 		break;
3959cec1e926SSascha Wildner 	case ACB_ADAPTER_TYPE_D: {
3960cec1e926SSascha Wildner 			while ((CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBDMU_MESSAGE_FIRMWARE_OK) == 0)
3961cec1e926SSascha Wildner 			{
3962cec1e926SSascha Wildner 				if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */
3963cec1e926SSascha Wildner 				{
3964cec1e926SSascha Wildner 					kprintf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit);
3965cec1e926SSascha Wildner 					return;
3966cec1e926SSascha Wildner 				}
3967cec1e926SSascha Wildner 				UDELAY(15000); /* wait 15 milli-seconds */
3968cec1e926SSascha Wildner 			}
3969cec1e926SSascha Wildner 		}
3970cec1e926SSascha Wildner 		break;
3971111d54bfSSascha Wildner 	case ACB_ADAPTER_TYPE_E: {
3972111d54bfSSascha Wildner 			while ((CHIP_REG_READ32(HBE_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBEMU_MESSAGE_FIRMWARE_OK) == 0)
3973111d54bfSSascha Wildner 			{
3974111d54bfSSascha Wildner 				if (timeout++ > 4000) /* (4000*15)/1000 = 60 sec */
3975111d54bfSSascha Wildner 				{
3976111d54bfSSascha Wildner 					kprintf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit);
3977111d54bfSSascha Wildner 					return;
3978111d54bfSSascha Wildner 				}
3979111d54bfSSascha Wildner 				UDELAY(15000); /* wait 15 milli-seconds */
3980111d54bfSSascha Wildner 			}
3981111d54bfSSascha Wildner 		}
3982111d54bfSSascha Wildner 		break;
39831901a965SSascha Wildner 	}
39841901a965SSascha Wildner }
39851901a965SSascha Wildner /*
39861901a965SSascha Wildner **********************************************************************
39871901a965SSascha Wildner **********************************************************************
39881901a965SSascha Wildner */
arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock * acb)39891901a965SSascha Wildner static void arcmsr_clear_doorbell_queue_buffer( struct AdapterControlBlock *acb)
39901901a965SSascha Wildner {
39911901a965SSascha Wildner 	u_int32_t outbound_doorbell;
39921901a965SSascha Wildner 
39931901a965SSascha Wildner 	switch (acb->adapter_type) {
39941901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_A: {
39951901a965SSascha Wildner 			/* empty doorbell Qbuffer if door bell ringed */
39961901a965SSascha Wildner 			outbound_doorbell = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell);
39971901a965SSascha Wildner 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, outbound_doorbell);	/*clear doorbell interrupt */
39981901a965SSascha Wildner 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
39991901a965SSascha Wildner 		}
40001901a965SSascha Wildner 		break;
40011901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_B: {
4002111d54bfSSascha Wildner 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
4003111d54bfSSascha Wildner 			WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN);/*clear interrupt and message state*/
4004111d54bfSSascha Wildner 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK);
40051901a965SSascha Wildner 			/* let IOP know data has been read */
40061901a965SSascha Wildner 		}
40071901a965SSascha Wildner 		break;
40081901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_C: {
40091901a965SSascha Wildner 			/* empty doorbell Qbuffer if door bell ringed */
40101901a965SSascha Wildner 			outbound_doorbell = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell);
40111901a965SSascha Wildner 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell);	/*clear doorbell interrupt */
40121901a965SSascha Wildner 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK);
4013cec1e926SSascha Wildner 			CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell_clear); /* Dummy read to force pci flush */
4014cec1e926SSascha Wildner 			CHIP_REG_READ32(HBC_MessageUnit, 0, inbound_doorbell); /* Dummy read to force pci flush */
4015cec1e926SSascha Wildner 		}
4016cec1e926SSascha Wildner 		break;
4017cec1e926SSascha Wildner 	case ACB_ADAPTER_TYPE_D: {
4018cec1e926SSascha Wildner 			/* empty doorbell Qbuffer if door bell ringed */
4019cec1e926SSascha Wildner 			outbound_doorbell = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell);
4020cec1e926SSascha Wildner 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, outbound_doorbell);	/*clear doorbell interrupt */
4021cec1e926SSascha Wildner 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ);
4022111d54bfSSascha Wildner 		}
4023111d54bfSSascha Wildner 		break;
4024111d54bfSSascha Wildner 	case ACB_ADAPTER_TYPE_E: {
4025111d54bfSSascha Wildner 			/* empty doorbell Qbuffer if door bell ringed */
4026111d54bfSSascha Wildner 			acb->in_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell);
4027111d54bfSSascha Wildner 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0);	/*clear doorbell interrupt */
4028111d54bfSSascha Wildner 			acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK;
4029111d54bfSSascha Wildner 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
40301901a965SSascha Wildner 		}
40311901a965SSascha Wildner 		break;
40321901a965SSascha Wildner 	}
40331901a965SSascha Wildner }
40341901a965SSascha Wildner /*
40351901a965SSascha Wildner ************************************************************************
40361901a965SSascha Wildner ************************************************************************
40371901a965SSascha Wildner */
arcmsr_iop_confirm(struct AdapterControlBlock * acb)40381901a965SSascha Wildner static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb)
40391901a965SSascha Wildner {
40401901a965SSascha Wildner 	unsigned long srb_phyaddr;
40411901a965SSascha Wildner 	u_int32_t srb_phyaddr_hi32;
4042cec1e926SSascha Wildner 	u_int32_t srb_phyaddr_lo32;
40431901a965SSascha Wildner 
40441901a965SSascha Wildner 	/*
40451901a965SSascha Wildner 	********************************************************************
40461901a965SSascha Wildner 	** here we need to tell iop 331 our freesrb.HighPart
40471901a965SSascha Wildner 	** if freesrb.HighPart is not zero
40481901a965SSascha Wildner 	********************************************************************
40491901a965SSascha Wildner 	*/
40501901a965SSascha Wildner 	srb_phyaddr = (unsigned long) acb->srb_phyaddr.phyaddr;
40511901a965SSascha Wildner 	srb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high;
4052cec1e926SSascha Wildner 	srb_phyaddr_lo32 = acb->srb_phyaddr.B.phyadd_low;
40531901a965SSascha Wildner 	switch (acb->adapter_type) {
40541901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_A: {
40551901a965SSascha Wildner 			if(srb_phyaddr_hi32 != 0) {
40561901a965SSascha Wildner 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG);
40571901a965SSascha Wildner 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32);
40581901a965SSascha Wildner 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
40591901a965SSascha Wildner 				if(!arcmsr_hba_wait_msgint_ready(acb)) {
40601901a965SSascha Wildner 					kprintf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit);
40611901a965SSascha Wildner 					return FALSE;
40621901a965SSascha Wildner 				}
40631901a965SSascha Wildner 			}
40641901a965SSascha Wildner 		}
40651901a965SSascha Wildner 		break;
40661901a965SSascha Wildner 		/*
40671901a965SSascha Wildner 		***********************************************************************
40681901a965SSascha Wildner 		**    if adapter type B, set window of "post command Q"
40691901a965SSascha Wildner 		***********************************************************************
40701901a965SSascha Wildner 		*/
40711901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_B: {
40721901a965SSascha Wildner 			u_int32_t post_queue_phyaddr;
40731901a965SSascha Wildner 			struct HBB_MessageUnit *phbbmu;
40741901a965SSascha Wildner 
40751901a965SSascha Wildner 			phbbmu = (struct HBB_MessageUnit *)acb->pmu;
40761901a965SSascha Wildner 			phbbmu->postq_index = 0;
40771901a965SSascha Wildner 			phbbmu->doneq_index = 0;
4078111d54bfSSascha Wildner 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_SET_POST_WINDOW);
40791901a965SSascha Wildner 			if(!arcmsr_hbb_wait_msgint_ready(acb)) {
40801901a965SSascha Wildner 				kprintf( "arcmsr%d: 'set window of post command Q' timeout\n", acb->pci_unit);
40811901a965SSascha Wildner 				return FALSE;
40821901a965SSascha Wildner 			}
4083cc3b439cSSascha Wildner 			post_queue_phyaddr = srb_phyaddr + ARCMSR_SRBS_POOL_SIZE
40841901a965SSascha Wildner 								+ offsetof(struct HBB_MessageUnit, post_qbuffer);
40851901a965SSascha Wildner 			CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */
40861901a965SSascha Wildner 			CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1], srb_phyaddr_hi32); /* normal should be zero */
40871901a965SSascha Wildner 			CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ size (256+8)*4 */
40881901a965SSascha Wildner 			CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3], post_queue_phyaddr+1056); /* doneQ size (256+8)*4 */
40891901a965SSascha Wildner 			CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4], 1056); /* srb maxQ size must be --> [(256+8)*4] */
4090111d54bfSSascha Wildner 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_SET_CONFIG);
40911901a965SSascha Wildner 			if(!arcmsr_hbb_wait_msgint_ready(acb)) {
40921901a965SSascha Wildner 				kprintf( "arcmsr%d: 'set command Q window' timeout \n", acb->pci_unit);
40931901a965SSascha Wildner 				return FALSE;
40941901a965SSascha Wildner 			}
4095111d54bfSSascha Wildner 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_START_DRIVER_MODE);
40961901a965SSascha Wildner 			if(!arcmsr_hbb_wait_msgint_ready(acb)) {
40971901a965SSascha Wildner 				kprintf( "arcmsr%d: 'start diver mode' timeout \n", acb->pci_unit);
40981901a965SSascha Wildner 				return FALSE;
40991901a965SSascha Wildner 			}
41001901a965SSascha Wildner 		}
41011901a965SSascha Wildner 		break;
41021901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_C: {
41031901a965SSascha Wildner 			if(srb_phyaddr_hi32 != 0) {
41041901a965SSascha Wildner 				CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG);
41051901a965SSascha Wildner 				CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32);
41061901a965SSascha Wildner 				CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
41071901a965SSascha Wildner 				CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
41081901a965SSascha Wildner 				if(!arcmsr_hbc_wait_msgint_ready(acb)) {
41091901a965SSascha Wildner 					kprintf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit);
41101901a965SSascha Wildner 					return FALSE;
41111901a965SSascha Wildner 				}
41121901a965SSascha Wildner 			}
41131901a965SSascha Wildner 		}
41141901a965SSascha Wildner 		break;
4115cec1e926SSascha Wildner 	case ACB_ADAPTER_TYPE_D: {
4116cec1e926SSascha Wildner 			u_int32_t post_queue_phyaddr, done_queue_phyaddr;
4117cec1e926SSascha Wildner 			struct HBD_MessageUnit0 *phbdmu;
4118cec1e926SSascha Wildner 
4119cec1e926SSascha Wildner 			phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
4120cec1e926SSascha Wildner 			phbdmu->postq_index = 0;
4121cec1e926SSascha Wildner 			phbdmu->doneq_index = 0x40FF;
4122cec1e926SSascha Wildner 			post_queue_phyaddr = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE
4123cec1e926SSascha Wildner 								+ offsetof(struct HBD_MessageUnit0, post_qbuffer);
4124cec1e926SSascha Wildner 			done_queue_phyaddr = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE
4125cec1e926SSascha Wildner 								+ offsetof(struct HBD_MessageUnit0, done_qbuffer);
4126cec1e926SSascha Wildner 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */
4127cec1e926SSascha Wildner 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32);
4128cec1e926SSascha Wildner 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ base */
4129cec1e926SSascha Wildner 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[3], done_queue_phyaddr); /* doneQ base */
4130cec1e926SSascha Wildner 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[4], 0x100);
4131cec1e926SSascha Wildner 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
4132cec1e926SSascha Wildner 			if(!arcmsr_hbd_wait_msgint_ready(acb)) {
4133cec1e926SSascha Wildner 				kprintf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit);
4134cec1e926SSascha Wildner 				return FALSE;
4135cec1e926SSascha Wildner 			}
4136cec1e926SSascha Wildner 		}
4137cec1e926SSascha Wildner 		break;
4138111d54bfSSascha Wildner 	case ACB_ADAPTER_TYPE_E: {
4139111d54bfSSascha Wildner 			u_int32_t cdb_phyaddr_lo32;
4140111d54bfSSascha Wildner 			cdb_phyaddr_lo32 = srb_phyaddr_lo32 + offsetof(struct CommandControlBlock, arcmsr_cdb);
4141111d54bfSSascha Wildner 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG);
4142111d54bfSSascha Wildner 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[1], ARCMSR_SIGNATURE_1884);
4143111d54bfSSascha Wildner 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[2], cdb_phyaddr_lo32);
4144111d54bfSSascha Wildner 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[3], srb_phyaddr_hi32);
4145111d54bfSSascha Wildner 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[4], SRB_SIZE);
4146111d54bfSSascha Wildner 			cdb_phyaddr_lo32 = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE;
4147111d54bfSSascha Wildner 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[5], cdb_phyaddr_lo32);
4148111d54bfSSascha Wildner 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[6], srb_phyaddr_hi32);
4149111d54bfSSascha Wildner 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[7], COMPLETION_Q_POOL_SIZE);
4150111d54bfSSascha Wildner 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
4151111d54bfSSascha Wildner 			acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
4152111d54bfSSascha Wildner 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
4153111d54bfSSascha Wildner 			if(!arcmsr_hbe_wait_msgint_ready(acb)) {
4154111d54bfSSascha Wildner 				kprintf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit);
4155111d54bfSSascha Wildner 				return FALSE;
4156111d54bfSSascha Wildner 			}
4157111d54bfSSascha Wildner 		}
4158111d54bfSSascha Wildner 		break;
41591901a965SSascha Wildner 	}
4160629e42e2SSascha Wildner 	return (TRUE);
41611901a965SSascha Wildner }
41621901a965SSascha Wildner /*
41631901a965SSascha Wildner ************************************************************************
41641901a965SSascha Wildner ************************************************************************
41651901a965SSascha Wildner */
arcmsr_enable_eoi_mode(struct AdapterControlBlock * acb)41661901a965SSascha Wildner static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb)
41671901a965SSascha Wildner {
4168111d54bfSSascha Wildner 	if (acb->adapter_type == ACB_ADAPTER_TYPE_B)
41691901a965SSascha Wildner 	{
4170111d54bfSSascha Wildner 		struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
4171111d54bfSSascha Wildner 		WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_ACTIVE_EOI_MODE);
41721901a965SSascha Wildner 		if(!arcmsr_hbb_wait_msgint_ready(acb)) {
41731901a965SSascha Wildner 			kprintf( "arcmsr%d: 'iop enable eoi mode' timeout \n", acb->pci_unit);
41741901a965SSascha Wildner 			return;
41751901a965SSascha Wildner 		}
41761901a965SSascha Wildner 	}
41771901a965SSascha Wildner }
41781901a965SSascha Wildner /*
41791901a965SSascha Wildner **********************************************************************
41801901a965SSascha Wildner **********************************************************************
41811901a965SSascha Wildner */
arcmsr_iop_init(struct AdapterControlBlock * acb)41821901a965SSascha Wildner static void arcmsr_iop_init(struct AdapterControlBlock *acb)
41831901a965SSascha Wildner {
41841901a965SSascha Wildner 	u_int32_t intmask_org;
41851901a965SSascha Wildner 
41861901a965SSascha Wildner 	/* disable all outbound interrupt */
41871901a965SSascha Wildner 	intmask_org = arcmsr_disable_allintr(acb);
41881901a965SSascha Wildner 	arcmsr_wait_firmware_ready(acb);
41891901a965SSascha Wildner 	arcmsr_iop_confirm(acb);
41901901a965SSascha Wildner 	arcmsr_get_firmware_spec(acb);
41911901a965SSascha Wildner 	/*start background rebuild*/
41921901a965SSascha Wildner 	arcmsr_start_adapter_bgrb(acb);
41931901a965SSascha Wildner 	/* empty doorbell Qbuffer if door bell ringed */
41941901a965SSascha Wildner 	arcmsr_clear_doorbell_queue_buffer(acb);
41951901a965SSascha Wildner 	arcmsr_enable_eoi_mode(acb);
41961901a965SSascha Wildner 	/* enable outbound Post Queue, outbound doorbell Interrupt */
41971901a965SSascha Wildner 	arcmsr_enable_allintr(acb, intmask_org);
41981901a965SSascha Wildner 	acb->acb_flags |= ACB_F_IOP_INITED;
41991901a965SSascha Wildner }
42001901a965SSascha Wildner /*
42011901a965SSascha Wildner **********************************************************************
42021901a965SSascha Wildner **********************************************************************
42031901a965SSascha Wildner */
arcmsr_map_free_srb(void * arg,bus_dma_segment_t * segs,int nseg,int error)420495696aa4SSascha Wildner static void arcmsr_map_free_srb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
42051901a965SSascha Wildner {
42061901a965SSascha Wildner 	struct AdapterControlBlock *acb = arg;
42071901a965SSascha Wildner 	struct CommandControlBlock *srb_tmp;
42081901a965SSascha Wildner 	u_int32_t i;
42091901a965SSascha Wildner 	unsigned long srb_phyaddr = (unsigned long)segs->ds_addr;
42101901a965SSascha Wildner 
42111901a965SSascha Wildner 	acb->srb_phyaddr.phyaddr = srb_phyaddr;
4212cec1e926SSascha Wildner 	srb_tmp = (struct CommandControlBlock *)acb->uncacheptr;
42131901a965SSascha Wildner 	for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) {
42141901a965SSascha Wildner 		if(bus_dmamap_create(acb->dm_segs_dmat,
42151901a965SSascha Wildner 			 /*flags*/0, &srb_tmp->dm_segs_dmamap) != 0) {
42161901a965SSascha Wildner 			acb->acb_flags |= ACB_F_MAPFREESRB_FAILD;
42171901a965SSascha Wildner 			kprintf("arcmsr%d:"
42181901a965SSascha Wildner 			" srb dmamap bus_dmamap_create error\n", acb->pci_unit);
42191901a965SSascha Wildner 			return;
42201901a965SSascha Wildner 		}
4221111d54bfSSascha Wildner 		if((acb->adapter_type == ACB_ADAPTER_TYPE_C) || (acb->adapter_type == ACB_ADAPTER_TYPE_D)
4222111d54bfSSascha Wildner 			 || (acb->adapter_type == ACB_ADAPTER_TYPE_E))
4223cec1e926SSascha Wildner 		{
4224cec1e926SSascha Wildner 			srb_tmp->cdb_phyaddr_low = srb_phyaddr;
4225cec1e926SSascha Wildner 			srb_tmp->cdb_phyaddr_high = (u_int32_t)((srb_phyaddr >> 16) >> 16);
4226cec1e926SSascha Wildner 		}
4227cec1e926SSascha Wildner 		else
4228cec1e926SSascha Wildner 			srb_tmp->cdb_phyaddr_low = srb_phyaddr >> 5;
42291901a965SSascha Wildner 		srb_tmp->acb = acb;
4230111d54bfSSascha Wildner 		srb_tmp->smid = i << 16;
42311901a965SSascha Wildner 		acb->srbworkingQ[i] = acb->psrb_pool[i] = srb_tmp;
4232cc3b439cSSascha Wildner 		srb_phyaddr = srb_phyaddr + SRB_SIZE;
4233cc3b439cSSascha Wildner 		srb_tmp = (struct CommandControlBlock *)((unsigned long)srb_tmp + SRB_SIZE);
42341901a965SSascha Wildner 	}
4235111d54bfSSascha Wildner 	acb->pCompletionQ = (pCompletion_Q)srb_tmp;
4236cec1e926SSascha Wildner 	acb->vir2phy_offset = (unsigned long)srb_tmp - (unsigned long)srb_phyaddr;
42371901a965SSascha Wildner }
42381901a965SSascha Wildner /*
42391901a965SSascha Wildner ************************************************************************
42401901a965SSascha Wildner ************************************************************************
42411901a965SSascha Wildner */
arcmsr_free_resource(struct AdapterControlBlock * acb)42421901a965SSascha Wildner static void arcmsr_free_resource(struct AdapterControlBlock *acb)
42431901a965SSascha Wildner {
42441901a965SSascha Wildner 	/* remove the control device */
42451901a965SSascha Wildner 	if(acb->ioctl_dev != NULL) {
42461901a965SSascha Wildner 		destroy_dev(acb->ioctl_dev);
42471901a965SSascha Wildner 	}
42481901a965SSascha Wildner 	bus_dmamap_unload(acb->srb_dmat, acb->srb_dmamap);
42491901a965SSascha Wildner 	bus_dmamap_destroy(acb->srb_dmat, acb->srb_dmamap);
42501901a965SSascha Wildner 	bus_dma_tag_destroy(acb->srb_dmat);
42511901a965SSascha Wildner 	bus_dma_tag_destroy(acb->dm_segs_dmat);
42521901a965SSascha Wildner 	bus_dma_tag_destroy(acb->parent_dmat);
42531901a965SSascha Wildner }
42541901a965SSascha Wildner /*
42551901a965SSascha Wildner ************************************************************************
42561901a965SSascha Wildner ************************************************************************
42571901a965SSascha Wildner */
arcmsr_mutex_init(struct AdapterControlBlock * acb)4258cec1e926SSascha Wildner static void arcmsr_mutex_init(struct AdapterControlBlock *acb)
4259cec1e926SSascha Wildner {
4260cec1e926SSascha Wildner 	ARCMSR_LOCK_INIT(&acb->isr_lock, "arcmsr isr lock");
4261cec1e926SSascha Wildner 	ARCMSR_LOCK_INIT(&acb->srb_lock, "arcmsr srb lock");
4262cec1e926SSascha Wildner 	ARCMSR_LOCK_INIT(&acb->postDone_lock, "arcmsr postQ lock");
4263cec1e926SSascha Wildner 	ARCMSR_LOCK_INIT(&acb->qbuffer_lock, "arcmsr RW buffer lock");
4264111d54bfSSascha Wildner 	ARCMSR_LOCK_INIT(&acb->io_lock, "arcmsr io lock");
4265111d54bfSSascha Wildner 	ARCMSR_LOCK_INIT(&acb->sim_lock, "arcmsr sim lock");
4266cec1e926SSascha Wildner }
4267cec1e926SSascha Wildner /*
4268cec1e926SSascha Wildner ************************************************************************
4269cec1e926SSascha Wildner ************************************************************************
4270cec1e926SSascha Wildner */
arcmsr_mutex_destroy(struct AdapterControlBlock * acb)4271cec1e926SSascha Wildner static void arcmsr_mutex_destroy(struct AdapterControlBlock *acb)
4272cec1e926SSascha Wildner {
4273111d54bfSSascha Wildner 	ARCMSR_LOCK_DESTROY(&acb->sim_lock);
4274111d54bfSSascha Wildner 	ARCMSR_LOCK_DESTROY(&acb->io_lock);
4275cec1e926SSascha Wildner 	ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock);
4276cec1e926SSascha Wildner 	ARCMSR_LOCK_DESTROY(&acb->postDone_lock);
4277cec1e926SSascha Wildner 	ARCMSR_LOCK_DESTROY(&acb->srb_lock);
4278cec1e926SSascha Wildner 	ARCMSR_LOCK_DESTROY(&acb->isr_lock);
4279cec1e926SSascha Wildner }
4280cec1e926SSascha Wildner /*
4281cec1e926SSascha Wildner ************************************************************************
4282cec1e926SSascha Wildner ************************************************************************
4283cec1e926SSascha Wildner */
arcmsr_initialize(device_t dev)42841901a965SSascha Wildner static u_int32_t arcmsr_initialize(device_t dev)
42851901a965SSascha Wildner {
42861901a965SSascha Wildner 	struct AdapterControlBlock *acb = device_get_softc(dev);
42871901a965SSascha Wildner 	u_int16_t pci_command;
42881901a965SSascha Wildner 	int i, j,max_coherent_size;
4289629e42e2SSascha Wildner 	u_int32_t vendor_dev_id;
42901901a965SSascha Wildner 
4291629e42e2SSascha Wildner 	vendor_dev_id = pci_get_devid(dev);
4292629e42e2SSascha Wildner 	acb->vendor_device_id = vendor_dev_id;
4293cec1e926SSascha Wildner 	acb->sub_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2);
4294629e42e2SSascha Wildner 	switch (vendor_dev_id) {
4295629e42e2SSascha Wildner 	case PCIDevVenIDARC1880:
4296629e42e2SSascha Wildner 	case PCIDevVenIDARC1882:
4297629e42e2SSascha Wildner 	case PCIDevVenIDARC1213:
4298629e42e2SSascha Wildner 	case PCIDevVenIDARC1223: {
42991901a965SSascha Wildner 			acb->adapter_type = ACB_ADAPTER_TYPE_C;
4300111d54bfSSascha Wildner 			if ((acb->sub_device_id == ARECA_SUB_DEV_ID_1883) ||
4301111d54bfSSascha Wildner 			    (acb->sub_device_id == ARECA_SUB_DEV_ID_1216) ||
4302111d54bfSSascha Wildner 			    (acb->sub_device_id == ARECA_SUB_DEV_ID_1226))
4303cec1e926SSascha Wildner 				acb->adapter_bus_speed = ACB_BUS_SPEED_12G;
4304cec1e926SSascha Wildner 			else
4305629e42e2SSascha Wildner 				acb->adapter_bus_speed = ACB_BUS_SPEED_6G;
43061901a965SSascha Wildner 			max_coherent_size = ARCMSR_SRBS_POOL_SIZE;
43071901a965SSascha Wildner 		}
43081901a965SSascha Wildner 		break;
4309111d54bfSSascha Wildner 	case PCIDevVenIDARC1884:
4310111d54bfSSascha Wildner 		acb->adapter_type = ACB_ADAPTER_TYPE_E;
4311111d54bfSSascha Wildner 		acb->adapter_bus_speed = ACB_BUS_SPEED_12G;
4312111d54bfSSascha Wildner 		max_coherent_size = ARCMSR_SRBS_POOL_SIZE + COMPLETION_Q_POOL_SIZE;
4313111d54bfSSascha Wildner 		acb->completionQ_entry = COMPLETION_Q_POOL_SIZE / sizeof(struct deliver_completeQ);
4314111d54bfSSascha Wildner 		break;
4315cec1e926SSascha Wildner 	case PCIDevVenIDARC1214: {
4316cec1e926SSascha Wildner 			acb->adapter_type = ACB_ADAPTER_TYPE_D;
4317cec1e926SSascha Wildner 			acb->adapter_bus_speed = ACB_BUS_SPEED_6G;
4318cec1e926SSascha Wildner 			max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBD_MessageUnit0));
4319cec1e926SSascha Wildner 		}
4320cec1e926SSascha Wildner 		break;
432195696aa4SSascha Wildner 	case PCIDevVenIDARC1200:
43221901a965SSascha Wildner 	case PCIDevVenIDARC1201: {
43231901a965SSascha Wildner 			acb->adapter_type = ACB_ADAPTER_TYPE_B;
4324629e42e2SSascha Wildner 			acb->adapter_bus_speed = ACB_BUS_SPEED_3G;
43251901a965SSascha Wildner 			max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBB_MessageUnit));
43261901a965SSascha Wildner 		}
43271901a965SSascha Wildner 		break;
4328111d54bfSSascha Wildner 	case PCIDevVenIDARC1203: {
4329111d54bfSSascha Wildner 			acb->adapter_type = ACB_ADAPTER_TYPE_B;
4330111d54bfSSascha Wildner 			acb->adapter_bus_speed = ACB_BUS_SPEED_6G;
4331111d54bfSSascha Wildner 			max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBB_MessageUnit));
4332111d54bfSSascha Wildner 		}
4333111d54bfSSascha Wildner 		break;
43341901a965SSascha Wildner 	case PCIDevVenIDARC1110:
43351901a965SSascha Wildner 	case PCIDevVenIDARC1120:
43361901a965SSascha Wildner 	case PCIDevVenIDARC1130:
43371901a965SSascha Wildner 	case PCIDevVenIDARC1160:
43381901a965SSascha Wildner 	case PCIDevVenIDARC1170:
43391901a965SSascha Wildner 	case PCIDevVenIDARC1210:
43401901a965SSascha Wildner 	case PCIDevVenIDARC1220:
43411901a965SSascha Wildner 	case PCIDevVenIDARC1230:
434295696aa4SSascha Wildner 	case PCIDevVenIDARC1231:
43431901a965SSascha Wildner 	case PCIDevVenIDARC1260:
434495696aa4SSascha Wildner 	case PCIDevVenIDARC1261:
43451901a965SSascha Wildner 	case PCIDevVenIDARC1270:
43461901a965SSascha Wildner 	case PCIDevVenIDARC1280:
43471901a965SSascha Wildner 	case PCIDevVenIDARC1212:
43481901a965SSascha Wildner 	case PCIDevVenIDARC1222:
43491901a965SSascha Wildner 	case PCIDevVenIDARC1380:
43501901a965SSascha Wildner 	case PCIDevVenIDARC1381:
43511901a965SSascha Wildner 	case PCIDevVenIDARC1680:
43521901a965SSascha Wildner 	case PCIDevVenIDARC1681: {
43531901a965SSascha Wildner 			acb->adapter_type = ACB_ADAPTER_TYPE_A;
4354629e42e2SSascha Wildner 			acb->adapter_bus_speed = ACB_BUS_SPEED_3G;
43551901a965SSascha Wildner 			max_coherent_size = ARCMSR_SRBS_POOL_SIZE;
43561901a965SSascha Wildner 		}
43571901a965SSascha Wildner 		break;
43581901a965SSascha Wildner 	default: {
43591901a965SSascha Wildner 			kprintf("arcmsr%d:"
43601901a965SSascha Wildner 			" unknown RAID adapter type \n", device_get_unit(dev));
43611901a965SSascha Wildner 			return ENOMEM;
43621901a965SSascha Wildner 		}
43631901a965SSascha Wildner 	}
4364cec1e926SSascha Wildner 	if(bus_dma_tag_create(  /*PCI parent*/		bus_get_dma_tag(dev),
43651901a965SSascha Wildner 				/*alignemnt*/		1,
43661901a965SSascha Wildner 				/*boundary*/		0,
43671901a965SSascha Wildner 				/*lowaddr*/		BUS_SPACE_MAXADDR,
43681901a965SSascha Wildner 				/*highaddr*/		BUS_SPACE_MAXADDR,
43691901a965SSascha Wildner 				/*maxsize*/		BUS_SPACE_MAXSIZE_32BIT,
43701901a965SSascha Wildner 				/*nsegments*/		BUS_SPACE_UNRESTRICTED,
43711901a965SSascha Wildner 				/*maxsegsz*/		BUS_SPACE_MAXSIZE_32BIT,
43721901a965SSascha Wildner 				/*flags*/		0,
43731901a965SSascha Wildner 							&acb->parent_dmat) != 0)
43741901a965SSascha Wildner 	{
43751901a965SSascha Wildner 		kprintf("arcmsr%d: parent_dmat bus_dma_tag_create failure!\n", device_get_unit(dev));
43761901a965SSascha Wildner 		return ENOMEM;
43771901a965SSascha Wildner 	}
43781901a965SSascha Wildner 	/* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */
43791901a965SSascha Wildner 	if(bus_dma_tag_create(  /*parent_dmat*/		acb->parent_dmat,
43801901a965SSascha Wildner 				/*alignment*/		1,
43811901a965SSascha Wildner 				/*boundary*/		0,
43821901a965SSascha Wildner 				/*lowaddr*/		BUS_SPACE_MAXADDR,
43831901a965SSascha Wildner 				/*highaddr*/		BUS_SPACE_MAXADDR,
438495696aa4SSascha Wildner 				/*maxsize*/		ARCMSR_MAX_SG_ENTRIES * PAGE_SIZE * ARCMSR_MAX_FREESRB_NUM,
43851901a965SSascha Wildner 				/*nsegments*/		ARCMSR_MAX_SG_ENTRIES,
43861901a965SSascha Wildner 				/*maxsegsz*/		BUS_SPACE_MAXSIZE_32BIT,
43871901a965SSascha Wildner 				/*flags*/		0,
43881901a965SSascha Wildner 							&acb->dm_segs_dmat) != 0)
43891901a965SSascha Wildner 	{
43901901a965SSascha Wildner 		bus_dma_tag_destroy(acb->parent_dmat);
43911901a965SSascha Wildner 		kprintf("arcmsr%d: dm_segs_dmat bus_dma_tag_create failure!\n", device_get_unit(dev));
43921901a965SSascha Wildner 		return ENOMEM;
43931901a965SSascha Wildner 	}
4394cec1e926SSascha Wildner 
43951901a965SSascha Wildner 	/* DMA tag for our srb structures.... Allocate the freesrb memory */
43961901a965SSascha Wildner 	if(bus_dma_tag_create(  /*parent_dmat*/		acb->parent_dmat,
43971901a965SSascha Wildner 				/*alignment*/		0x20,
43981901a965SSascha Wildner 				/*boundary*/		0,
43991901a965SSascha Wildner 				/*lowaddr*/		BUS_SPACE_MAXADDR_32BIT,
44001901a965SSascha Wildner 				/*highaddr*/		BUS_SPACE_MAXADDR,
44011901a965SSascha Wildner 				/*maxsize*/		max_coherent_size,
44021901a965SSascha Wildner 				/*nsegments*/		1,
44031901a965SSascha Wildner 				/*maxsegsz*/		BUS_SPACE_MAXSIZE_32BIT,
44041901a965SSascha Wildner 				/*flags*/		0,
44051901a965SSascha Wildner 							&acb->srb_dmat) != 0)
44061901a965SSascha Wildner 	{
44071901a965SSascha Wildner 		bus_dma_tag_destroy(acb->dm_segs_dmat);
44081901a965SSascha Wildner 		bus_dma_tag_destroy(acb->parent_dmat);
44091901a965SSascha Wildner 		kprintf("arcmsr%d: srb_dmat bus_dma_tag_create failure!\n", device_get_unit(dev));
44101901a965SSascha Wildner 		return ENXIO;
44111901a965SSascha Wildner 	}
44121901a965SSascha Wildner 	/* Allocation for our srbs */
44131901a965SSascha Wildner 	if(bus_dmamem_alloc(acb->srb_dmat, (void **)&acb->uncacheptr, BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &acb->srb_dmamap) != 0) {
44141901a965SSascha Wildner 		bus_dma_tag_destroy(acb->srb_dmat);
44151901a965SSascha Wildner 		bus_dma_tag_destroy(acb->dm_segs_dmat);
44161901a965SSascha Wildner 		bus_dma_tag_destroy(acb->parent_dmat);
44171901a965SSascha Wildner 		kprintf("arcmsr%d: srb_dmat bus_dmamem_alloc failure!\n", device_get_unit(dev));
44181901a965SSascha Wildner 		return ENXIO;
44191901a965SSascha Wildner 	}
44201901a965SSascha Wildner 	/* And permanently map them */
442195696aa4SSascha Wildner 	if(bus_dmamap_load(acb->srb_dmat, acb->srb_dmamap, acb->uncacheptr, max_coherent_size, arcmsr_map_free_srb, acb, /*flags*/0)) {
44221901a965SSascha Wildner 		bus_dma_tag_destroy(acb->srb_dmat);
44231901a965SSascha Wildner 		bus_dma_tag_destroy(acb->dm_segs_dmat);
44241901a965SSascha Wildner 		bus_dma_tag_destroy(acb->parent_dmat);
44251901a965SSascha Wildner 		kprintf("arcmsr%d: srb_dmat bus_dmamap_load failure!\n", device_get_unit(dev));
44261901a965SSascha Wildner 		return ENXIO;
44271901a965SSascha Wildner 	}
44281901a965SSascha Wildner 	pci_command = pci_read_config(dev, PCIR_COMMAND, 2);
44291901a965SSascha Wildner 	pci_command |= PCIM_CMD_BUSMASTEREN;
44301901a965SSascha Wildner 	pci_command |= PCIM_CMD_PERRESPEN;
44311901a965SSascha Wildner 	pci_command |= PCIM_CMD_MWRICEN;
4432cec1e926SSascha Wildner 	/* Enable Busmaster */
44331901a965SSascha Wildner 	pci_write_config(dev, PCIR_COMMAND, pci_command, 2);
44341901a965SSascha Wildner 	switch(acb->adapter_type) {
44351901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_A: {
44361901a965SSascha Wildner 		u_int32_t rid0 = PCIR_BAR(0);
44371901a965SSascha Wildner 		vm_offset_t	mem_base0;
44381901a965SSascha Wildner 
4439111d54bfSSascha Wildner 		acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid0, RF_ACTIVE);
44401901a965SSascha Wildner 		if(acb->sys_res_arcmsr[0] == NULL) {
44411901a965SSascha Wildner 			arcmsr_free_resource(acb);
44421901a965SSascha Wildner 			kprintf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
44431901a965SSascha Wildner 			return ENOMEM;
44441901a965SSascha Wildner 		}
44451901a965SSascha Wildner 		if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
44461901a965SSascha Wildner 			arcmsr_free_resource(acb);
44471901a965SSascha Wildner 			kprintf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
44481901a965SSascha Wildner 			return ENXIO;
44491901a965SSascha Wildner 		}
44501901a965SSascha Wildner 		mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
44511901a965SSascha Wildner 		if(mem_base0 == 0) {
44521901a965SSascha Wildner 			arcmsr_free_resource(acb);
44531901a965SSascha Wildner 			kprintf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
44541901a965SSascha Wildner 			return ENXIO;
44551901a965SSascha Wildner 		}
44561901a965SSascha Wildner 		acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
44571901a965SSascha Wildner 		acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
44581901a965SSascha Wildner 		acb->pmu = (struct MessageUnit_UNION *)mem_base0;
4459111d54bfSSascha Wildner 		acb->rid[0] = rid0;
44601901a965SSascha Wildner 		}
44611901a965SSascha Wildner 		break;
44621901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_B: {
44631901a965SSascha Wildner 		struct HBB_MessageUnit *phbbmu;
44641901a965SSascha Wildner 		struct CommandControlBlock *freesrb;
44651901a965SSascha Wildner 		u_int32_t rid[]={ PCIR_BAR(0), PCIR_BAR(2) };
44661901a965SSascha Wildner 		vm_offset_t	mem_base[]={0,0};
4467111d54bfSSascha Wildner 		u_long	size;
4468111d54bfSSascha Wildner 		if (vendor_dev_id == PCIDevVenIDARC1203)
4469111d54bfSSascha Wildner 			size = sizeof(struct HBB_DOORBELL_1203);
4470111d54bfSSascha Wildner 		else
4471111d54bfSSascha Wildner 			size = sizeof(struct HBB_DOORBELL);
44721901a965SSascha Wildner 		for(i=0; i < 2; i++) {
4473111d54bfSSascha Wildner 			acb->sys_res_arcmsr[i] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid[i], RF_ACTIVE);
44741901a965SSascha Wildner 			if(acb->sys_res_arcmsr[i] == NULL) {
44751901a965SSascha Wildner 				arcmsr_free_resource(acb);
44761901a965SSascha Wildner 				kprintf("arcmsr%d: bus_alloc_resource %d failure!\n", device_get_unit(dev), i);
44771901a965SSascha Wildner 				return ENOMEM;
44781901a965SSascha Wildner 			}
44791901a965SSascha Wildner 			if(rman_get_start(acb->sys_res_arcmsr[i]) <= 0) {
44801901a965SSascha Wildner 				arcmsr_free_resource(acb);
44811901a965SSascha Wildner 				kprintf("arcmsr%d: rman_get_start %d failure!\n", device_get_unit(dev), i);
44821901a965SSascha Wildner 				return ENXIO;
44831901a965SSascha Wildner 			}
44841901a965SSascha Wildner 			mem_base[i] = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[i]);
44851901a965SSascha Wildner 			if(mem_base[i] == 0) {
44861901a965SSascha Wildner 				arcmsr_free_resource(acb);
44871901a965SSascha Wildner 				kprintf("arcmsr%d: rman_get_virtual %d failure!\n", device_get_unit(dev), i);
44881901a965SSascha Wildner 				return ENXIO;
44891901a965SSascha Wildner 			}
44901901a965SSascha Wildner 			acb->btag[i] = rman_get_bustag(acb->sys_res_arcmsr[i]);
44911901a965SSascha Wildner 			acb->bhandle[i] = rman_get_bushandle(acb->sys_res_arcmsr[i]);
44921901a965SSascha Wildner 		}
44931901a965SSascha Wildner 		freesrb = (struct CommandControlBlock *)acb->uncacheptr;
4494cc3b439cSSascha Wildner 		acb->pmu = (struct MessageUnit_UNION *)((unsigned long)freesrb+ARCMSR_SRBS_POOL_SIZE);
44951901a965SSascha Wildner 		phbbmu = (struct HBB_MessageUnit *)acb->pmu;
44961901a965SSascha Wildner 		phbbmu->hbb_doorbell = (struct HBB_DOORBELL *)mem_base[0];
44971901a965SSascha Wildner 		phbbmu->hbb_rwbuffer = (struct HBB_RWBUFFER *)mem_base[1];
4498111d54bfSSascha Wildner 		if (vendor_dev_id == PCIDevVenIDARC1203) {
4499111d54bfSSascha Wildner 			phbbmu->drv2iop_doorbell = offsetof(struct HBB_DOORBELL_1203, drv2iop_doorbell);
4500111d54bfSSascha Wildner 			phbbmu->drv2iop_doorbell_mask = offsetof(struct HBB_DOORBELL_1203, drv2iop_doorbell_mask);
4501111d54bfSSascha Wildner 			phbbmu->iop2drv_doorbell = offsetof(struct HBB_DOORBELL_1203, iop2drv_doorbell);
4502111d54bfSSascha Wildner 			phbbmu->iop2drv_doorbell_mask = offsetof(struct HBB_DOORBELL_1203, iop2drv_doorbell_mask);
4503111d54bfSSascha Wildner 		} else {
4504111d54bfSSascha Wildner 			phbbmu->drv2iop_doorbell = offsetof(struct HBB_DOORBELL, drv2iop_doorbell);
4505111d54bfSSascha Wildner 			phbbmu->drv2iop_doorbell_mask = offsetof(struct HBB_DOORBELL, drv2iop_doorbell_mask);
4506111d54bfSSascha Wildner 			phbbmu->iop2drv_doorbell = offsetof(struct HBB_DOORBELL, iop2drv_doorbell);
4507111d54bfSSascha Wildner 			phbbmu->iop2drv_doorbell_mask = offsetof(struct HBB_DOORBELL, iop2drv_doorbell_mask);
4508111d54bfSSascha Wildner 		}
4509111d54bfSSascha Wildner 		acb->rid[0] = rid[0];
4510111d54bfSSascha Wildner 		acb->rid[1] = rid[1];
45111901a965SSascha Wildner 		}
45121901a965SSascha Wildner 		break;
45131901a965SSascha Wildner 	case ACB_ADAPTER_TYPE_C: {
45141901a965SSascha Wildner 		u_int32_t rid0 = PCIR_BAR(1);
45151901a965SSascha Wildner 		vm_offset_t	mem_base0;
45161901a965SSascha Wildner 
4517111d54bfSSascha Wildner 		acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid0, RF_ACTIVE);
45181901a965SSascha Wildner 		if(acb->sys_res_arcmsr[0] == NULL) {
45191901a965SSascha Wildner 			arcmsr_free_resource(acb);
45201901a965SSascha Wildner 			kprintf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
45211901a965SSascha Wildner 			return ENOMEM;
45221901a965SSascha Wildner 		}
45231901a965SSascha Wildner 		if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
45241901a965SSascha Wildner 			arcmsr_free_resource(acb);
45251901a965SSascha Wildner 			kprintf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
45261901a965SSascha Wildner 			return ENXIO;
45271901a965SSascha Wildner 		}
45281901a965SSascha Wildner 		mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
45291901a965SSascha Wildner 		if(mem_base0 == 0) {
45301901a965SSascha Wildner 			arcmsr_free_resource(acb);
45311901a965SSascha Wildner 			kprintf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
45321901a965SSascha Wildner 			return ENXIO;
45331901a965SSascha Wildner 		}
45341901a965SSascha Wildner 		acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
45351901a965SSascha Wildner 		acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
45361901a965SSascha Wildner 		acb->pmu = (struct MessageUnit_UNION *)mem_base0;
4537111d54bfSSascha Wildner 		acb->rid[0] = rid0;
45381901a965SSascha Wildner 		}
45391901a965SSascha Wildner 		break;
4540cec1e926SSascha Wildner 	case ACB_ADAPTER_TYPE_D: {
4541cec1e926SSascha Wildner 		struct HBD_MessageUnit0 *phbdmu;
4542cec1e926SSascha Wildner 		u_int32_t rid0 = PCIR_BAR(0);
4543cec1e926SSascha Wildner 		vm_offset_t	mem_base0;
4544cec1e926SSascha Wildner 
4545111d54bfSSascha Wildner 		acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid0, RF_ACTIVE);
4546cec1e926SSascha Wildner 		if(acb->sys_res_arcmsr[0] == NULL) {
4547cec1e926SSascha Wildner 			arcmsr_free_resource(acb);
4548cec1e926SSascha Wildner 			kprintf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
4549cec1e926SSascha Wildner 			return ENOMEM;
4550cec1e926SSascha Wildner 		}
4551cec1e926SSascha Wildner 		if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
4552cec1e926SSascha Wildner 			arcmsr_free_resource(acb);
4553cec1e926SSascha Wildner 			kprintf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
4554cec1e926SSascha Wildner 			return ENXIO;
4555cec1e926SSascha Wildner 		}
4556cec1e926SSascha Wildner 		mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
4557cec1e926SSascha Wildner 		if(mem_base0 == 0) {
4558cec1e926SSascha Wildner 			arcmsr_free_resource(acb);
4559cec1e926SSascha Wildner 			kprintf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
4560cec1e926SSascha Wildner 			return ENXIO;
4561cec1e926SSascha Wildner 		}
4562cec1e926SSascha Wildner 		acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
4563cec1e926SSascha Wildner 		acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
4564cec1e926SSascha Wildner 		acb->pmu = (struct MessageUnit_UNION *)((unsigned long)acb->uncacheptr+ARCMSR_SRBS_POOL_SIZE);
4565cec1e926SSascha Wildner 		phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
4566cec1e926SSascha Wildner 		phbdmu->phbdmu = (struct HBD_MessageUnit *)mem_base0;
4567111d54bfSSascha Wildner 		acb->rid[0] = rid0;
4568111d54bfSSascha Wildner 		}
4569111d54bfSSascha Wildner 		break;
4570111d54bfSSascha Wildner 	case ACB_ADAPTER_TYPE_E: {
4571111d54bfSSascha Wildner 		u_int32_t rid0 = PCIR_BAR(1);
4572111d54bfSSascha Wildner 		vm_offset_t	mem_base0;
4573111d54bfSSascha Wildner 
4574111d54bfSSascha Wildner 		acb->sys_res_arcmsr[0] = bus_alloc_resource(dev,SYS_RES_MEMORY, &rid0, 0ul, ~0ul, sizeof(struct HBE_MessageUnit), RF_ACTIVE);
4575111d54bfSSascha Wildner 		if(acb->sys_res_arcmsr[0] == NULL) {
4576111d54bfSSascha Wildner 			arcmsr_free_resource(acb);
4577111d54bfSSascha Wildner 			kprintf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
4578111d54bfSSascha Wildner 			return ENOMEM;
4579111d54bfSSascha Wildner 		}
4580111d54bfSSascha Wildner 		if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
4581111d54bfSSascha Wildner 			arcmsr_free_resource(acb);
4582111d54bfSSascha Wildner 			kprintf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
4583111d54bfSSascha Wildner 			return ENXIO;
4584111d54bfSSascha Wildner 		}
4585111d54bfSSascha Wildner 		mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
4586111d54bfSSascha Wildner 		if(mem_base0 == 0) {
4587111d54bfSSascha Wildner 			arcmsr_free_resource(acb);
4588111d54bfSSascha Wildner 			kprintf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
4589111d54bfSSascha Wildner 			return ENXIO;
4590111d54bfSSascha Wildner 		}
4591111d54bfSSascha Wildner 		acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
4592111d54bfSSascha Wildner 		acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
4593111d54bfSSascha Wildner 		acb->pmu = (struct MessageUnit_UNION *)mem_base0;
4594111d54bfSSascha Wildner 		acb->doneq_index = 0;
4595111d54bfSSascha Wildner 		acb->in_doorbell = 0;
4596111d54bfSSascha Wildner 		acb->out_doorbell = 0;
4597111d54bfSSascha Wildner 		acb->rid[0] = rid0;
4598111d54bfSSascha Wildner 		CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /*clear interrupt*/
4599111d54bfSSascha Wildner 		CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, ARCMSR_HBEMU_DOORBELL_SYNC); /* synchronize doorbell to 0 */
4600cec1e926SSascha Wildner 		}
4601cec1e926SSascha Wildner 		break;
46021901a965SSascha Wildner 	}
46031901a965SSascha Wildner 	if(acb->acb_flags & ACB_F_MAPFREESRB_FAILD) {
46041901a965SSascha Wildner 		arcmsr_free_resource(acb);
46051901a965SSascha Wildner 		kprintf("arcmsr%d: map free srb failure!\n", device_get_unit(dev));
46061901a965SSascha Wildner 		return ENXIO;
46071901a965SSascha Wildner 	}
46081901a965SSascha Wildner 	acb->acb_flags  |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_RQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ);
46091901a965SSascha Wildner 	acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER;
46101901a965SSascha Wildner 	/*
46111901a965SSascha Wildner 	********************************************************************
46121901a965SSascha Wildner 	** init raid volume state
46131901a965SSascha Wildner 	********************************************************************
46141901a965SSascha Wildner 	*/
46151901a965SSascha Wildner 	for(i=0; i < ARCMSR_MAX_TARGETID; i++) {
46161901a965SSascha Wildner 		for(j=0; j < ARCMSR_MAX_TARGETLUN; j++) {
46171901a965SSascha Wildner 			acb->devstate[i][j] = ARECA_RAID_GONE;
46181901a965SSascha Wildner 		}
46191901a965SSascha Wildner 	}
46201901a965SSascha Wildner 	arcmsr_iop_init(acb);
46211901a965SSascha Wildner 	return(0);
46221901a965SSascha Wildner }
4623111d54bfSSascha Wildner 
4624111d54bfSSascha Wildner /*
4625111d54bfSSascha Wildner ************************************************************************
4626111d54bfSSascha Wildner ************************************************************************
4627111d54bfSSascha Wildner */
arcmsr_teardown_intr(device_t dev,struct AdapterControlBlock * acb)4628111d54bfSSascha Wildner static void arcmsr_teardown_intr(device_t dev, struct AdapterControlBlock *acb)
4629111d54bfSSascha Wildner {
4630111d54bfSSascha Wildner 	int i;
4631111d54bfSSascha Wildner 
4632111d54bfSSascha Wildner 	if (acb->acb_flags & ACB_F_MSIX_ENABLED) {
4633111d54bfSSascha Wildner 		for (i = 0; i < acb->msix_vectors; i++) {
4634111d54bfSSascha Wildner 			if (acb->ih[i])
4635111d54bfSSascha Wildner 				bus_teardown_intr(dev, acb->irqres[i], acb->ih[i]);
4636111d54bfSSascha Wildner 		//	if (acb->irqres[i] != NULL)
4637111d54bfSSascha Wildner 		//		bus_release_resource(dev, SYS_RES_IRQ,
4638111d54bfSSascha Wildner 		//		    acb->irq_id[i], acb->irqres[i]);
4639111d54bfSSascha Wildner 
4640111d54bfSSascha Wildner 			acb->ih[i] = NULL;
4641111d54bfSSascha Wildner 		}
4642111d54bfSSascha Wildner 		pci_release_msi(dev);
4643111d54bfSSascha Wildner 	} else {
4644111d54bfSSascha Wildner 		if ((acb->ih[0] != NULL) && (acb->irqres[0] != NULL))
4645111d54bfSSascha Wildner 			bus_teardown_intr(dev, acb->irqres[0], acb->ih[0]);
4646111d54bfSSascha Wildner 		if (acb->irqres[0] != NULL)
4647111d54bfSSascha Wildner 			bus_release_resource(dev, SYS_RES_IRQ,
4648111d54bfSSascha Wildner 			    acb->irq_id[0], acb->irqres[0]);
4649111d54bfSSascha Wildner 		if (acb->irq_type == PCI_INTR_TYPE_MSI)
4650111d54bfSSascha Wildner       			pci_release_msi(dev);
4651111d54bfSSascha Wildner 		acb->ih[0] = NULL;
4652111d54bfSSascha Wildner 		acb->irqres[0] = NULL;
4653111d54bfSSascha Wildner 		acb->irq_type = 0;
4654111d54bfSSascha Wildner 	}
4655111d54bfSSascha Wildner 
4656111d54bfSSascha Wildner }
46571901a965SSascha Wildner /*
46581901a965SSascha Wildner ************************************************************************
46591901a965SSascha Wildner ************************************************************************
46601901a965SSascha Wildner */
arcmsr_attach(device_t dev)46611901a965SSascha Wildner static int arcmsr_attach(device_t dev)
46621901a965SSascha Wildner {
46631901a965SSascha Wildner 	struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev);
46641901a965SSascha Wildner 	u_int32_t unit=device_get_unit(dev);
4665111d54bfSSascha Wildner 	union ccb *ccb;
46661901a965SSascha Wildner 	struct cam_devq	*devq;	/* Device Queue to use for this SIM */
46671901a965SSascha Wildner 	struct resource	*irqres;
4668fb8c9539SSascha Wildner 	u_int irq_flags;
46691901a965SSascha Wildner 
46701901a965SSascha Wildner 	if(acb == NULL) {
46711901a965SSascha Wildner 		kprintf("arcmsr%d: cannot allocate softc\n", unit);
46721901a965SSascha Wildner 		return (ENOMEM);
46731901a965SSascha Wildner 	}
4674cec1e926SSascha Wildner 	arcmsr_mutex_init(acb);
4675cec1e926SSascha Wildner 	acb->pci_dev = dev;
4676cec1e926SSascha Wildner 	acb->pci_unit = unit;
46771901a965SSascha Wildner 	if(arcmsr_initialize(dev)) {
46781901a965SSascha Wildner 		kprintf("arcmsr%d: initialize failure!\n", unit);
4679111d54bfSSascha Wildner 		goto initialize_failed;
46801901a965SSascha Wildner 	}
46811901a965SSascha Wildner 	/* After setting up the adapter, map our interrupt */
4682111d54bfSSascha Wildner 	acb->irq_id[0] = 0;
4683111d54bfSSascha Wildner 	acb->irq_type = pci_alloc_1intr(dev, arcmsr_msi_enable, &acb->irq_id[0], &irq_flags);
4684111d54bfSSascha Wildner 	irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &acb->irq_id[0], irq_flags);
4685111d54bfSSascha Wildner 	if(irqres == NULL ) {
4686111d54bfSSascha Wildner 		kprintf("arcmsr%d: unable to alloc interrupt resource!\n", unit);
4687111d54bfSSascha Wildner 		goto alloc_intr_failed;
46881901a965SSascha Wildner 	}
4689111d54bfSSascha Wildner 	if(bus_setup_intr(dev, irqres, INTR_MPSAFE, arcmsr_intr_handler, acb, &acb->ih[0], NULL)) {
4690111d54bfSSascha Wildner 		kprintf("arcmsr%d: unable to setup interrupt handler!\n", unit);
4691111d54bfSSascha Wildner 		goto setup_intr_failed;
4692111d54bfSSascha Wildner 	}
4693111d54bfSSascha Wildner 	acb->irqres[0] = irqres;
46941901a965SSascha Wildner 	/*
46951901a965SSascha Wildner 	 * Now let the CAM generic SCSI layer find the SCSI devices on
46961901a965SSascha Wildner 	 * the bus *  start queue to reset to the idle loop. *
46971901a965SSascha Wildner 	 * Create device queue of SIM(s) *  (MAX_START_JOB - 1) :
46981901a965SSascha Wildner 	 * max_sim_transactions
46991901a965SSascha Wildner 	*/
4700cec1e926SSascha Wildner 	devq = cam_simq_alloc(acb->maxOutstanding);
47011901a965SSascha Wildner 	if(devq == NULL) {
47021901a965SSascha Wildner 		kprintf("arcmsr%d: cam_simq_alloc failure!\n", unit);
4703111d54bfSSascha Wildner 		goto simq_alloc_failed;
47041901a965SSascha Wildner 	}
4705cec1e926SSascha Wildner 	acb->psim = cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, &acb->isr_lock, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq);
4706284d4d40SSascha Wildner 	cam_simq_release(devq);
47071901a965SSascha Wildner 	if(acb->psim == NULL) {
47081901a965SSascha Wildner 		kprintf("arcmsr%d: cam_sim_alloc failure!\n", unit);
4709111d54bfSSascha Wildner 		goto sim_alloc_failed;
47101901a965SSascha Wildner 	}
4711cec1e926SSascha Wildner 	ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
47121901a965SSascha Wildner 	if(xpt_bus_register(acb->psim, 0) != CAM_SUCCESS) {
47131901a965SSascha Wildner 		kprintf("arcmsr%d: xpt_bus_register failure!\n", unit);
4714111d54bfSSascha Wildner 		goto xpt_bus_failed;
47151901a965SSascha Wildner 	}
4716111d54bfSSascha Wildner 	if ((ccb = xpt_alloc_ccb()) == NULL) {
4717111d54bfSSascha Wildner 		kprintf("arcmsr%d: xpt_alloc_ccb failure!\n", unit);
4718111d54bfSSascha Wildner 		goto xpt_ccb_failed;
4719111d54bfSSascha Wildner 	}
4720111d54bfSSascha Wildner 	if(xpt_create_path(&ccb->ccb_h.path, xpt_periph, cam_sim_path(acb->psim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
47211901a965SSascha Wildner 		kprintf("arcmsr%d: xpt_create_path failure!\n", unit);
4722111d54bfSSascha Wildner 		goto xpt_path_failed;
47231901a965SSascha Wildner 	}
47241901a965SSascha Wildner 	/*
47251901a965SSascha Wildner 	****************************************************
47261901a965SSascha Wildner 	*/
4727111d54bfSSascha Wildner 	xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, /*priority*/5);
4728111d54bfSSascha Wildner 	ccb->ccb_h.func_code = XPT_SCAN_BUS;
4729111d54bfSSascha Wildner 	ccb->ccb_h.cbfcnp = arcmsr_rescanLun_cb;
4730111d54bfSSascha Wildner 	ccb->crcn.flags = CAM_FLAG_NONE;
4731111d54bfSSascha Wildner 	xpt_action(ccb);
4732cec1e926SSascha Wildner 	ARCMSR_LOCK_RELEASE(&acb->isr_lock);
4733111d54bfSSascha Wildner 
47341901a965SSascha Wildner 	/* Create the control device.  */
47351901a965SSascha Wildner 	acb->ioctl_dev = make_dev(&arcmsr_ops, unit, UID_ROOT, GID_WHEEL /* GID_OPERATOR */, S_IRUSR | S_IWUSR, "arcmsr%d", unit);
47361901a965SSascha Wildner 	acb->ioctl_dev->si_drv1 = acb;
47371901a965SSascha Wildner 	(void)make_dev_alias(acb->ioctl_dev, "arc%d", unit);
4738cc3b439cSSascha Wildner 	arcmsr_callout_init(&acb->devmap_callout);
47391901a965SSascha Wildner 	callout_reset(&acb->devmap_callout, 60 * hz, arcmsr_polling_devmap, acb);
4740629e42e2SSascha Wildner 	return (0);
4741111d54bfSSascha Wildner 
4742111d54bfSSascha Wildner xpt_path_failed:
4743*cec957e9SMatthew Dillon         xpt_free_ccb(&ccb->ccb_h);
4744111d54bfSSascha Wildner xpt_ccb_failed:
4745111d54bfSSascha Wildner 	xpt_bus_deregister(cam_sim_path(acb->psim));
4746111d54bfSSascha Wildner xpt_bus_failed:
4747111d54bfSSascha Wildner 	ARCMSR_LOCK_RELEASE(&acb->isr_lock);
4748111d54bfSSascha Wildner 	cam_sim_free(acb->psim);
4749111d54bfSSascha Wildner sim_alloc_failed:
4750111d54bfSSascha Wildner 	cam_simq_release(devq);
4751111d54bfSSascha Wildner simq_alloc_failed:
4752111d54bfSSascha Wildner 	arcmsr_teardown_intr(dev, acb);
4753111d54bfSSascha Wildner setup_intr_failed:
4754111d54bfSSascha Wildner 	arcmsr_free_resource(acb);
4755111d54bfSSascha Wildner 	bus_release_resource(dev, SYS_RES_IRQ, acb->irq_id[0], irqres);
4756111d54bfSSascha Wildner alloc_intr_failed:
4757111d54bfSSascha Wildner 	if (acb->irq_type == PCI_INTR_TYPE_MSI)
4758111d54bfSSascha Wildner       		pci_release_msi(dev);
4759111d54bfSSascha Wildner initialize_failed:
4760111d54bfSSascha Wildner 	arcmsr_mutex_destroy(acb);
4761111d54bfSSascha Wildner 	return ENXIO;
47621901a965SSascha Wildner }
4763cc3b439cSSascha Wildner 
47641901a965SSascha Wildner /*
47651901a965SSascha Wildner ************************************************************************
47661901a965SSascha Wildner ************************************************************************
47671901a965SSascha Wildner */
arcmsr_probe(device_t dev)47681901a965SSascha Wildner static int arcmsr_probe(device_t dev)
47691901a965SSascha Wildner {
47701901a965SSascha Wildner 	u_int32_t id;
4771cec1e926SSascha Wildner 	u_int16_t sub_device_id;
47721901a965SSascha Wildner 	static char buf[256];
4773cec1e926SSascha Wildner 	char x_type[]={"unknown"};
47741901a965SSascha Wildner 	char *type;
47751901a965SSascha Wildner 	int raid6 = 1;
47761901a965SSascha Wildner 
47771901a965SSascha Wildner 	if (pci_get_vendor(dev) != PCI_VENDOR_ID_ARECA) {
47781901a965SSascha Wildner 		return (ENXIO);
47791901a965SSascha Wildner 	}
4780cec1e926SSascha Wildner 	sub_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2);
47811901a965SSascha Wildner 	switch(id = pci_get_devid(dev)) {
47821901a965SSascha Wildner 	case PCIDevVenIDARC1110:
478395696aa4SSascha Wildner 	case PCIDevVenIDARC1200:
47841901a965SSascha Wildner 	case PCIDevVenIDARC1201:
478595696aa4SSascha Wildner 	case PCIDevVenIDARC1210:
47861901a965SSascha Wildner 		raid6 = 0;
47871901a965SSascha Wildner 		/*FALLTHRU*/
47881901a965SSascha Wildner 	case PCIDevVenIDARC1120:
47891901a965SSascha Wildner 	case PCIDevVenIDARC1130:
47901901a965SSascha Wildner 	case PCIDevVenIDARC1160:
47911901a965SSascha Wildner 	case PCIDevVenIDARC1170:
47921901a965SSascha Wildner 	case PCIDevVenIDARC1220:
47931901a965SSascha Wildner 	case PCIDevVenIDARC1230:
479495696aa4SSascha Wildner 	case PCIDevVenIDARC1231:
47951901a965SSascha Wildner 	case PCIDevVenIDARC1260:
479695696aa4SSascha Wildner 	case PCIDevVenIDARC1261:
47971901a965SSascha Wildner 	case PCIDevVenIDARC1270:
47981901a965SSascha Wildner 	case PCIDevVenIDARC1280:
4799cec1e926SSascha Wildner 		type = "SATA 3G";
48001901a965SSascha Wildner 		break;
48011901a965SSascha Wildner 	case PCIDevVenIDARC1212:
48021901a965SSascha Wildner 	case PCIDevVenIDARC1222:
48031901a965SSascha Wildner 	case PCIDevVenIDARC1380:
48041901a965SSascha Wildner 	case PCIDevVenIDARC1381:
48051901a965SSascha Wildner 	case PCIDevVenIDARC1680:
48061901a965SSascha Wildner 	case PCIDevVenIDARC1681:
48071901a965SSascha Wildner 		type = "SAS 3G";
48081901a965SSascha Wildner 		break;
48091901a965SSascha Wildner 	case PCIDevVenIDARC1880:
4810629e42e2SSascha Wildner 	case PCIDevVenIDARC1882:
4811629e42e2SSascha Wildner 	case PCIDevVenIDARC1213:
4812629e42e2SSascha Wildner 	case PCIDevVenIDARC1223:
4813111d54bfSSascha Wildner 		if ((sub_device_id == ARECA_SUB_DEV_ID_1883) ||
4814111d54bfSSascha Wildner 		    (sub_device_id == ARECA_SUB_DEV_ID_1216) ||
4815111d54bfSSascha Wildner 		    (sub_device_id == ARECA_SUB_DEV_ID_1226))
4816cec1e926SSascha Wildner 			type = "SAS 12G";
4817cec1e926SSascha Wildner 		else
48181901a965SSascha Wildner 			type = "SAS 6G";
4819ad8f657dSSascha Wildner 		arcmsr_msi_enable = 0;
48201901a965SSascha Wildner 		break;
4821111d54bfSSascha Wildner 	case PCIDevVenIDARC1884:
4822111d54bfSSascha Wildner 		type = "SAS 12G";
4823111d54bfSSascha Wildner 		arcmsr_msi_enable = 0;
4824111d54bfSSascha Wildner 		break;
4825cec1e926SSascha Wildner 	case PCIDevVenIDARC1214:
4826111d54bfSSascha Wildner 		arcmsr_msi_enable = 0;
4827111d54bfSSascha Wildner 	case PCIDevVenIDARC1203:
4828cec1e926SSascha Wildner 		type = "SATA 6G";
4829cec1e926SSascha Wildner 		break;
48301901a965SSascha Wildner 	default:
483195696aa4SSascha Wildner 		type = x_type;
4832cec1e926SSascha Wildner 		raid6 = 0;
48331901a965SSascha Wildner 		break;
48341901a965SSascha Wildner 	}
483595696aa4SSascha Wildner 	if(type == x_type)
483695696aa4SSascha Wildner 		return(ENXIO);
4837111d54bfSSascha Wildner 	ksprintf(buf, "Areca %s Host Adapter RAID Controller %s\n%s\n",
4838111d54bfSSascha Wildner 		type, raid6 ? "(RAID6 capable)" : "", ARCMSR_DRIVER_VERSION);
48391901a965SSascha Wildner 	device_set_desc_copy(dev, buf);
4840629e42e2SSascha Wildner 	return (BUS_PROBE_DEFAULT);
48411901a965SSascha Wildner }
48421901a965SSascha Wildner /*
48431901a965SSascha Wildner ************************************************************************
48441901a965SSascha Wildner ************************************************************************
48451901a965SSascha Wildner */
arcmsr_shutdown(device_t dev)48461901a965SSascha Wildner static int arcmsr_shutdown(device_t dev)
48471901a965SSascha Wildner {
48481901a965SSascha Wildner 	u_int32_t  i;
48491901a965SSascha Wildner 	struct CommandControlBlock *srb;
48501901a965SSascha Wildner 	struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev);
48511901a965SSascha Wildner 
48521901a965SSascha Wildner 	/* stop adapter background rebuild */
4853cec1e926SSascha Wildner 	ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
48541901a965SSascha Wildner 	/* disable all outbound interrupt */
4855ed8258e4SSascha Wildner 	arcmsr_disable_allintr(acb);
48561901a965SSascha Wildner 	arcmsr_stop_adapter_bgrb(acb);
48571901a965SSascha Wildner 	arcmsr_flush_adapter_cache(acb);
48581901a965SSascha Wildner 	/* abort all outstanding command */
48591901a965SSascha Wildner 	acb->acb_flags |= ACB_F_SCSISTOPADAPTER;
48601901a965SSascha Wildner 	acb->acb_flags &= ~ACB_F_IOP_INITED;
48611901a965SSascha Wildner 	if(acb->srboutstandingcount != 0) {
48621901a965SSascha Wildner 		/*clear and abort all outbound posted Q*/
48631901a965SSascha Wildner 		arcmsr_done4abort_postqueue(acb);
48641901a965SSascha Wildner 		/* talk to iop 331 outstanding command aborted*/
48651901a965SSascha Wildner 		arcmsr_abort_allcmd(acb);
48661901a965SSascha Wildner 		for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) {
48671901a965SSascha Wildner 			srb = acb->psrb_pool[i];
4868cc3b439cSSascha Wildner 			if(srb->srb_state == ARCMSR_SRB_START) {
4869cc3b439cSSascha Wildner 				srb->srb_state = ARCMSR_SRB_ABORTED;
48701901a965SSascha Wildner 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
48711901a965SSascha Wildner 				arcmsr_srb_complete(srb, 1);
48721901a965SSascha Wildner 			}
48731901a965SSascha Wildner 		}
48741901a965SSascha Wildner 	}
4875cc3b439cSSascha Wildner 	acb->srboutstandingcount = 0;
48761901a965SSascha Wildner 	acb->workingsrb_doneindex = 0;
48771901a965SSascha Wildner 	acb->workingsrb_startindex = 0;
4878cc3b439cSSascha Wildner 	acb->pktRequestCount = 0;
4879cc3b439cSSascha Wildner 	acb->pktReturnCount = 0;
4880cec1e926SSascha Wildner 	ARCMSR_LOCK_RELEASE(&acb->isr_lock);
48811901a965SSascha Wildner 	return (0);
48821901a965SSascha Wildner }
48831901a965SSascha Wildner /*
48841901a965SSascha Wildner ************************************************************************
48851901a965SSascha Wildner ************************************************************************
48861901a965SSascha Wildner */
arcmsr_detach(device_t dev)48871901a965SSascha Wildner static int arcmsr_detach(device_t dev)
48881901a965SSascha Wildner {
48891901a965SSascha Wildner 	struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev);
48901901a965SSascha Wildner 	int i;
48911901a965SSascha Wildner 
48921901a965SSascha Wildner 	callout_stop(&acb->devmap_callout);
4893111d54bfSSascha Wildner 	arcmsr_teardown_intr(dev, acb);
48941901a965SSascha Wildner 	arcmsr_shutdown(dev);
48951901a965SSascha Wildner 	arcmsr_free_resource(acb);
4896111d54bfSSascha Wildner 	for(i=0; (i < 2) && (acb->sys_res_arcmsr[i]!=NULL); i++) {
4897111d54bfSSascha Wildner 		bus_release_resource(dev, SYS_RES_MEMORY, acb->rid[i], acb->sys_res_arcmsr[i]);
48981901a965SSascha Wildner 	}
4899cec1e926SSascha Wildner 	ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
49001901a965SSascha Wildner 	xpt_bus_deregister(cam_sim_path(acb->psim));
49011901a965SSascha Wildner 	cam_sim_free(acb->psim);
4902cec1e926SSascha Wildner 	ARCMSR_LOCK_RELEASE(&acb->isr_lock);
4903cec1e926SSascha Wildner 	arcmsr_mutex_destroy(acb);
49041901a965SSascha Wildner 	return (0);
49051901a965SSascha Wildner }
4906cc3b439cSSascha Wildner 
4907cc3b439cSSascha Wildner #ifdef ARCMSR_DEBUG1
arcmsr_dump_data(struct AdapterControlBlock * acb)4908cc3b439cSSascha Wildner static void arcmsr_dump_data(struct AdapterControlBlock *acb)
4909cc3b439cSSascha Wildner {
4910cc3b439cSSascha Wildner 	if((acb->pktRequestCount - acb->pktReturnCount) == 0)
4911cc3b439cSSascha Wildner 		return;
4912cec1e926SSascha Wildner 	kprintf("Command Request Count   =0x%x\n",acb->pktRequestCount);
4913cec1e926SSascha Wildner 	kprintf("Command Return Count    =0x%x\n",acb->pktReturnCount);
4914cec1e926SSascha Wildner 	kprintf("Command (Req-Rtn) Count =0x%x\n",(acb->pktRequestCount - acb->pktReturnCount));
4915cec1e926SSascha Wildner 	kprintf("Queued Command Count    =0x%x\n",acb->srboutstandingcount);
4916cc3b439cSSascha Wildner }
4917cc3b439cSSascha Wildner #endif
4918