xref: /freebsd/sys/dev/arcmsr/arcmsr.c (revision 0d6d8bac8b70340be935a1a494a4f0cbb5651cec)
1f1c579b1SScott Long /*
235689395SXin LI ********************************************************************************
335689395SXin LI **        OS    : FreeBSD
4f1c579b1SScott Long **   FILE NAME  : arcmsr.c
5d74001adSXin LI **        BY    : Erich Chen, Ching Huang
6f1c579b1SScott Long **   Description: SCSI RAID Device Driver for
735689395SXin LI **                ARECA (ARC11XX/ARC12XX/ARC13XX/ARC16XX/ARC188x)
835689395SXin LI **                SATA/SAS RAID HOST Adapter
935689395SXin LI ********************************************************************************
1035689395SXin LI ********************************************************************************
11f1c579b1SScott Long **
12718cf2ccSPedro F. Giffuni ** SPDX-License-Identifier: BSD-3-Clause
13718cf2ccSPedro F. Giffuni **
1435689395SXin LI ** Copyright (C) 2002 - 2012, Areca Technology Corporation All rights reserved.
15f1c579b1SScott Long **
16f1c579b1SScott Long ** Redistribution and use in source and binary forms, with or without
17f1c579b1SScott Long ** modification, are permitted provided that the following conditions
18f1c579b1SScott Long ** are met:
19f1c579b1SScott Long ** 1. Redistributions of source code must retain the above copyright
20f1c579b1SScott Long **    notice, this list of conditions and the following disclaimer.
21f1c579b1SScott Long ** 2. Redistributions in binary form must reproduce the above copyright
22f1c579b1SScott Long **    notice, this list of conditions and the following disclaimer in the
23f1c579b1SScott Long **    documentation and/or other materials provided with the distribution.
24f1c579b1SScott Long ** 3. The name of the author may not be used to endorse or promote products
25f1c579b1SScott Long **    derived from this software without specific prior written permission.
26f1c579b1SScott Long **
27f1c579b1SScott Long ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
28f1c579b1SScott Long ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
29f1c579b1SScott Long ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30f1c579b1SScott Long ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
31f1c579b1SScott Long ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT
32f1c579b1SScott Long ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33f1c579b1SScott Long ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY
34f1c579b1SScott Long ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35f1c579b1SScott Long **(INCLUDING NEGLIGENCE OR OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF
36f1c579b1SScott Long ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3735689395SXin LI ********************************************************************************
38f1c579b1SScott Long ** History
39f1c579b1SScott Long **
40f1c579b1SScott Long **    REV#         DATE         NAME        DESCRIPTION
4122f2616bSXin LI ** 1.00.00.00   03/31/2004  Erich Chen      First release
42f1c579b1SScott Long ** 1.20.00.02   11/29/2004  Erich Chen      bug fix with arcmsr_bus_reset when PHY error
4322f2616bSXin LI ** 1.20.00.03   04/19/2005  Erich Chen      add SATA 24 Ports adapter type support
44ad6d6297SScott Long **                                          clean unused function
4522f2616bSXin LI ** 1.20.00.12   09/12/2005  Erich Chen      bug fix with abort command handling,
46ad6d6297SScott Long **                                          firmware version check
47ad6d6297SScott Long **                                          and firmware update notify for hardware bug fix
48ad6d6297SScott Long **                                          handling if none zero high part physical address
49ad6d6297SScott Long **                                          of srb resource
5022f2616bSXin LI ** 1.20.00.13   08/18/2006  Erich Chen      remove pending srb and report busy
51ad6d6297SScott Long **                                          add iop message xfer
52ad6d6297SScott Long **                                          with scsi pass-through command
53ad6d6297SScott Long **                                          add new device id of sas raid adapters
54ad6d6297SScott Long **                                          code fit for SPARC64 & PPC
55f48f00a1SScott Long ** 1.20.00.14   02/05/2007  Erich Chen      bug fix for incorrect ccb_h.status report
56f48f00a1SScott Long **                                          and cause g_vfs_done() read write error
5744f05562SScott Long ** 1.20.00.15   10/10/2007  Erich Chen      support new RAID adapter type ARC120x
58641182baSXin LI ** 1.20.00.16   10/10/2009  Erich Chen      Bug fix for RAID adapter type ARC120x
59641182baSXin LI **                                          bus_dmamem_alloc() with BUS_DMA_ZERO
60d74001adSXin LI ** 1.20.00.17   07/15/2010  Ching Huang     Added support ARC1880
61d74001adSXin LI **                                          report CAM_DEV_NOT_THERE instead of CAM_SEL_TIMEOUT when device failed,
62d74001adSXin LI **                                          prevent cam_periph_error removing all LUN devices of one Target id
63d74001adSXin LI **                                          for any one LUN device failed
64231c8b71SXin LI ** 1.20.00.18   10/14/2010  Ching Huang     Fixed "inquiry data fails comparion at DV1 step"
65231c8b71SXin LI **              10/25/2010  Ching Huang     Fixed bad range input in bus_alloc_resource for ADAPTER_TYPE_B
66231c8b71SXin LI ** 1.20.00.19   11/11/2010  Ching Huang     Fixed arcmsr driver prevent arcsas support for Areca SAS HBA ARC13x0
6722f2616bSXin LI ** 1.20.00.20   12/08/2010  Ching Huang     Avoid calling atomic_set_int function
6822f2616bSXin LI ** 1.20.00.21   02/08/2011  Ching Huang     Implement I/O request timeout
6922f2616bSXin LI **              02/14/2011  Ching Huang     Modified pktRequestCount
7022f2616bSXin LI ** 1.20.00.21   03/03/2011  Ching Huang     if a command timeout, then wait its ccb back before free it
714e32649fSXin LI ** 1.20.00.22   07/04/2011  Ching Huang     Fixed multiple MTX panic
72dac36688SXin LI ** 1.20.00.23   10/28/2011  Ching Huang     Added TIMEOUT_DELAY in case of too many HDDs need to start
73dac36688SXin LI ** 1.20.00.23   11/08/2011  Ching Huang     Added report device transfer speed
74dac36688SXin LI ** 1.20.00.23   01/30/2012  Ching Huang     Fixed Request requeued and Retrying command
75dac36688SXin LI ** 1.20.00.24   06/11/2012  Ching Huang     Fixed return sense data condition
76dac36688SXin LI ** 1.20.00.25   08/17/2012  Ching Huang     Fixed hotplug device no function on type A adapter
77abfdbca9SXin LI ** 1.20.00.26   12/14/2012  Ching Huang     Added support ARC1214,1224,1264,1284
78abfdbca9SXin LI ** 1.20.00.27   05/06/2013  Ching Huang     Fixed out standing cmd full on ARC-12x4
791e7d660aSXin LI ** 1.20.00.28   09/13/2013  Ching Huang     Removed recursive mutex in arcmsr_abort_dr_ccbs
80224a78aeSXin LI ** 1.20.00.29   12/18/2013  Ching Huang     Change simq allocation number, support ARC1883
81b23a1998SXin LI ** 1.30.00.00   11/30/2015  Ching Huang     Added support ARC1203
82a1103e04SXin LI ** 1.40.00.00   07/11/2017  Ching Huang     Added support ARC1884
83fc5ef1caSXin LI ** 1.40.00.01   10/30/2017  Ching Huang     Fixed release memory resource
84fa42a0bfSXin LI ** 1.50.00.00   09/30/2020  Ching Huang     Added support ARC-1886, NVMe/SAS/SATA controller
855842073aSXin LI ** 1.50.00.01   02/26/2021  Ching Huang     Fixed no action of hot plugging device on type_F adapter
86438b5532SXin LI ** 1.50.00.02   04/16/2021  Ching Huang     Fixed scsi command timeout on ARC-1886 when
87438b5532SXin LI **                                          scatter-gather count large than some number
886964b77eS黃清隆 ** 1.50.00.03   05/04/2021  Ching Huang     Fixed doorbell status arrived late on ARC-1886
896964b77eS黃清隆 ** 1.50.00.04   12/08/2021  Ching Huang     Fixed boot up hung under ARC-1886 with no volume created
90f1c579b1SScott Long ******************************************************************************************
91f1c579b1SScott Long */
924b7ec270SMarius Strobl 
934b7ec270SMarius Strobl #include <sys/cdefs.h>
944b7ec270SMarius Strobl __FBSDID("$FreeBSD$");
954b7ec270SMarius Strobl 
9622f2616bSXin LI #if 0
9722f2616bSXin LI #define ARCMSR_DEBUG1			1
9822f2616bSXin LI #endif
99f1c579b1SScott Long #include <sys/param.h>
100f1c579b1SScott Long #include <sys/systm.h>
101f1c579b1SScott Long #include <sys/malloc.h>
102f1c579b1SScott Long #include <sys/kernel.h>
103f1c579b1SScott Long #include <sys/bus.h>
104f1c579b1SScott Long #include <sys/queue.h>
105f1c579b1SScott Long #include <sys/stat.h>
106f1c579b1SScott Long #include <sys/devicestat.h>
107f1c579b1SScott Long #include <sys/kthread.h>
108f1c579b1SScott Long #include <sys/module.h>
109f1c579b1SScott Long #include <sys/proc.h>
110f1c579b1SScott Long #include <sys/lock.h>
111f1c579b1SScott Long #include <sys/sysctl.h>
112f1c579b1SScott Long #include <sys/poll.h>
113f1c579b1SScott Long #include <sys/ioccom.h>
114f1c579b1SScott Long #include <vm/vm.h>
115f1c579b1SScott Long #include <vm/vm_param.h>
116f1c579b1SScott Long #include <vm/pmap.h>
117f1c579b1SScott Long 
118f1c579b1SScott Long #include <isa/rtc.h>
119f1c579b1SScott Long 
120f1c579b1SScott Long #include <machine/bus.h>
121f1c579b1SScott Long #include <machine/resource.h>
122f1c579b1SScott Long #include <machine/atomic.h>
123f1c579b1SScott Long #include <sys/conf.h>
124f1c579b1SScott Long #include <sys/rman.h>
125f1c579b1SScott Long 
126f1c579b1SScott Long #include <cam/cam.h>
127f1c579b1SScott Long #include <cam/cam_ccb.h>
128f1c579b1SScott Long #include <cam/cam_sim.h>
129d74001adSXin LI #include <cam/cam_periph.h>
130d74001adSXin LI #include <cam/cam_xpt_periph.h>
131f1c579b1SScott Long #include <cam/cam_xpt_sim.h>
132f1c579b1SScott Long #include <cam/cam_debug.h>
133f1c579b1SScott Long #include <cam/scsi/scsi_all.h>
134f1c579b1SScott Long #include <cam/scsi/scsi_message.h>
135f1c579b1SScott Long /*
136f1c579b1SScott Long **************************************************************************
137f1c579b1SScott Long **************************************************************************
138f1c579b1SScott Long */
139f1c579b1SScott Long #include <sys/selinfo.h>
140f1c579b1SScott Long #include <sys/mutex.h>
141ad6d6297SScott Long #include <sys/endian.h>
142f1c579b1SScott Long #include <dev/pci/pcivar.h>
143f1c579b1SScott Long #include <dev/pci/pcireg.h>
14444f05562SScott Long 
14522f2616bSXin LI #define arcmsr_callout_init(a)	callout_init(a, /*mpsafe*/1);
14622f2616bSXin LI 
1476964b77eS黃清隆 #define ARCMSR_DRIVER_VERSION	"arcmsr version 1.50.00.04 2021-12-08"
148f1c579b1SScott Long #include <dev/arcmsr/arcmsr.h>
149f1c579b1SScott Long /*
150f1c579b1SScott Long **************************************************************************
151f1c579b1SScott Long **************************************************************************
152f1c579b1SScott Long */
15322f2616bSXin LI static void arcmsr_free_srb(struct CommandControlBlock *srb);
154ad6d6297SScott Long static struct CommandControlBlock *arcmsr_get_freesrb(struct AdapterControlBlock *acb);
155ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb *abortccb);
156f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev);
157f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev);
158f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev);
159ad6d6297SScott Long static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg);
160ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb);
161f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev);
16244f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb);
163ad6d6297SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb);
164ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb);
165ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb);
166ad6d6297SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb);
167ad6d6297SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb);
168ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb);
169ad6d6297SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb);
17035689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb, struct QBUFFER *prbuffer);
1717a7bc959SXin LI static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb);
172ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb);
173ad6d6297SScott Long static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag);
174ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb);
175ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb);
176ad6d6297SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb, bus_dma_segment_t *dm_segs, u_int32_t nseg);
177ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *pccb);
178ad6d6297SScott Long static int arcmsr_resume(device_t dev);
179ad6d6297SScott Long static int arcmsr_suspend(device_t dev);
180d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb);
181d74001adSXin LI static void arcmsr_polling_devmap(void *arg);
18222f2616bSXin LI static void arcmsr_srb_timeout(void *arg);
1837a7bc959SXin LI static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb);
184a1103e04SXin LI static void arcmsr_hbe_postqueue_isr(struct AdapterControlBlock *acb);
185fa42a0bfSXin LI static void arcmsr_hbf_postqueue_isr(struct AdapterControlBlock *acb);
186fc5ef1caSXin LI static void arcmsr_teardown_intr(device_t dev, struct AdapterControlBlock *acb);
18722f2616bSXin LI #ifdef ARCMSR_DEBUG1
18822f2616bSXin LI static void arcmsr_dump_data(struct AdapterControlBlock *acb);
18922f2616bSXin LI #endif
190f1c579b1SScott Long /*
191f1c579b1SScott Long **************************************************************************
192ad6d6297SScott Long **************************************************************************
193ad6d6297SScott Long */
194ad6d6297SScott Long static void UDELAY(u_int32_t us) { DELAY(us); }
195ad6d6297SScott Long /*
196ad6d6297SScott Long **************************************************************************
197f1c579b1SScott Long **************************************************************************
198f1c579b1SScott Long */
199231c8b71SXin LI static bus_dmamap_callback_t arcmsr_map_free_srb;
200231c8b71SXin LI static bus_dmamap_callback_t arcmsr_execute_srb;
201f1c579b1SScott Long /*
202f1c579b1SScott Long **************************************************************************
203f1c579b1SScott Long **************************************************************************
204f1c579b1SScott Long */
205f1c579b1SScott Long static d_open_t	arcmsr_open;
206f1c579b1SScott Long static d_close_t arcmsr_close;
207f1c579b1SScott Long static d_ioctl_t arcmsr_ioctl;
208f1c579b1SScott Long 
209f1c579b1SScott Long static device_method_t arcmsr_methods[]={
210f1c579b1SScott Long 	DEVMETHOD(device_probe,		arcmsr_probe),
211f1c579b1SScott Long 	DEVMETHOD(device_attach,	arcmsr_attach),
212f1c579b1SScott Long 	DEVMETHOD(device_detach,	arcmsr_detach),
213f1c579b1SScott Long 	DEVMETHOD(device_shutdown,	arcmsr_shutdown),
214ad6d6297SScott Long 	DEVMETHOD(device_suspend,	arcmsr_suspend),
215ad6d6297SScott Long 	DEVMETHOD(device_resume,	arcmsr_resume),
2164b7ec270SMarius Strobl 	DEVMETHOD_END
217f1c579b1SScott Long };
218f1c579b1SScott Long 
219f1c579b1SScott Long static driver_t arcmsr_driver={
220ad6d6297SScott Long 	"arcmsr", arcmsr_methods, sizeof(struct AdapterControlBlock)
221f1c579b1SScott Long };
222f1c579b1SScott Long 
223*0d6d8bacSJohn Baldwin DRIVER_MODULE(arcmsr, pci, arcmsr_driver, 0, 0);
224d3cf342dSScott Long MODULE_DEPEND(arcmsr, pci, 1, 1, 1);
225d3cf342dSScott Long MODULE_DEPEND(arcmsr, cam, 1, 1, 1);
226ad6d6297SScott Long #ifndef BUS_DMA_COHERENT
227ad6d6297SScott Long 	#define	BUS_DMA_COHERENT	0x04	/* hint: map memory in a coherent way */
228ad6d6297SScott Long #endif
229f1c579b1SScott Long static struct cdevsw arcmsr_cdevsw={
230f1c579b1SScott Long 		.d_version = D_VERSION,
231f1c579b1SScott Long 		.d_open    = arcmsr_open, 	/* open     */
232f1c579b1SScott Long 		.d_close   = arcmsr_close, 	/* close    */
233f1c579b1SScott Long 		.d_ioctl   = arcmsr_ioctl, 	/* ioctl    */
234f1c579b1SScott Long 		.d_name    = "arcmsr", 		/* name     */
235f1c579b1SScott Long 	};
236d74001adSXin LI /*
237d74001adSXin LI **************************************************************************
238d74001adSXin LI **************************************************************************
239d74001adSXin LI */
24000b4e54aSWarner Losh static int arcmsr_open(struct cdev *dev, int flags, int fmt, struct thread *proc)
241f1c579b1SScott Long {
242dac36688SXin LI 	return (0);
243f1c579b1SScott Long }
244f1c579b1SScott Long /*
245f1c579b1SScott Long **************************************************************************
246f1c579b1SScott Long **************************************************************************
247f1c579b1SScott Long */
24800b4e54aSWarner Losh static int arcmsr_close(struct cdev *dev, int flags, int fmt, struct thread *proc)
249f1c579b1SScott Long {
250f1c579b1SScott Long 	return 0;
251f1c579b1SScott Long }
252f1c579b1SScott Long /*
253f1c579b1SScott Long **************************************************************************
254f1c579b1SScott Long **************************************************************************
255f1c579b1SScott Long */
25600b4e54aSWarner Losh static int arcmsr_ioctl(struct cdev *dev, u_long ioctl_cmd, caddr_t arg, int flags, struct thread *proc)
257f1c579b1SScott Long {
258a9e5e04eSJohn Baldwin 	struct AdapterControlBlock *acb = dev->si_drv1;
259f1c579b1SScott Long 
260ad6d6297SScott Long 	return (arcmsr_iop_ioctlcmd(acb, ioctl_cmd, arg));
261f1c579b1SScott Long }
262f1c579b1SScott Long /*
26344f05562SScott Long **********************************************************************
26444f05562SScott Long **********************************************************************
26544f05562SScott Long */
26644f05562SScott Long static u_int32_t arcmsr_disable_allintr( struct AdapterControlBlock *acb)
26744f05562SScott Long {
26844f05562SScott Long 	u_int32_t intmask_org = 0;
26944f05562SScott Long 
27044f05562SScott Long 	switch (acb->adapter_type) {
27144f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
27244f05562SScott Long 			/* disable all outbound interrupt */
273d74001adSXin LI 			intmask_org = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intmask); /* disable outbound message0 int */
274d74001adSXin LI 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE);
27544f05562SScott Long 		}
27644f05562SScott Long 		break;
27744f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
278b23a1998SXin LI 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
27944f05562SScott Long 			/* disable all outbound interrupt */
280b23a1998SXin LI 			intmask_org = READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask)
281b23a1998SXin LI 						& (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); /* disable outbound message0 int */
282b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask, 0); /* disable all interrupt */
283d74001adSXin LI 		}
284d74001adSXin LI 		break;
285d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
286d74001adSXin LI 			/* disable all outbound interrupt */
287d74001adSXin LI 			intmask_org = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_mask); /* disable outbound message0 int */
288d74001adSXin LI 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org|ARCMSR_HBCMU_ALL_INTMASKENABLE);
28944f05562SScott Long 		}
29044f05562SScott Long 		break;
2917a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
2927a7bc959SXin LI 			/* disable all outbound interrupt */
2937a7bc959SXin LI 			intmask_org = CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable); /* disable outbound message0 int */
2947a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, ARCMSR_HBDMU_ALL_INT_DISABLE);
2957a7bc959SXin LI 		}
2967a7bc959SXin LI 		break;
297fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
298fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
299a1103e04SXin LI 			/* disable all outbound interrupt */
300fa42a0bfSXin LI 			intmask_org = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_mask); /* disable outbound message0 int */
301a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_mask, intmask_org | ARCMSR_HBEMU_ALL_INTMASKENABLE);
302a1103e04SXin LI 		}
303a1103e04SXin LI 		break;
30444f05562SScott Long 	}
30544f05562SScott Long 	return (intmask_org);
30644f05562SScott Long }
30744f05562SScott Long /*
30844f05562SScott Long **********************************************************************
30944f05562SScott Long **********************************************************************
31044f05562SScott Long */
31144f05562SScott Long static void arcmsr_enable_allintr( struct AdapterControlBlock *acb, u_int32_t intmask_org)
31244f05562SScott Long {
31344f05562SScott Long 	u_int32_t mask;
31444f05562SScott Long 
31544f05562SScott Long 	switch (acb->adapter_type) {
31644f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
31744f05562SScott Long 			/* enable outbound Post Queue, outbound doorbell Interrupt */
318d74001adSXin LI 			mask = ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE|ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE|ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE);
31944f05562SScott Long 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intmask, intmask_org & mask);
32044f05562SScott Long 			acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff;
32144f05562SScott Long 		}
32244f05562SScott Long 		break;
32344f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
324b23a1998SXin LI 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
325d74001adSXin LI 			/* enable ARCMSR_IOP2DRV_MESSAGE_CMD_DONE */
326d74001adSXin LI 			mask = (ARCMSR_IOP2DRV_DATA_WRITE_OK|ARCMSR_IOP2DRV_DATA_READ_OK|ARCMSR_IOP2DRV_CDB_DONE|ARCMSR_IOP2DRV_MESSAGE_CMD_DONE);
327b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell_mask, intmask_org | mask); /*1=interrupt enable, 0=interrupt disable*/
32844f05562SScott Long 			acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f;
32944f05562SScott Long 		}
33044f05562SScott Long 		break;
331d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
332d74001adSXin LI 			/* enable outbound Post Queue, outbound doorbell Interrupt */
333d74001adSXin LI 			mask = ~(ARCMSR_HBCMU_UTILITY_A_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR_MASK | ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR_MASK);
334d74001adSXin LI 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, host_int_mask, intmask_org & mask);
335d74001adSXin LI 			acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f;
336d74001adSXin LI 		}
337d74001adSXin LI 		break;
3387a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
3397a7bc959SXin LI 			/* enable outbound Post Queue, outbound doorbell Interrupt */
3407a7bc959SXin LI 			mask = ARCMSR_HBDMU_ALL_INT_ENABLE;
3417a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, intmask_org | mask);
3427a7bc959SXin LI 			CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable);
3437a7bc959SXin LI 			acb->outbound_int_enable = mask;
3447a7bc959SXin LI 		}
3457a7bc959SXin LI 		break;
346fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
347fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
348a1103e04SXin LI 			/* enable outbound Post Queue, outbound doorbell Interrupt */
349a1103e04SXin LI 			mask = ~(ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR | ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR);
350a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_mask, intmask_org & mask);
351a1103e04SXin LI 			acb->outbound_int_enable = ~(intmask_org & mask) & 0x0000000f;
352a1103e04SXin LI 		}
353a1103e04SXin LI 		break;
35444f05562SScott Long 	}
35544f05562SScott Long }
35644f05562SScott Long /*
35744f05562SScott Long **********************************************************************
35844f05562SScott Long **********************************************************************
35944f05562SScott Long */
36044f05562SScott Long static u_int8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb)
36144f05562SScott Long {
36244f05562SScott Long 	u_int32_t Index;
36344f05562SScott Long 	u_int8_t Retries = 0x00;
36444f05562SScott Long 
36544f05562SScott Long 	do {
36644f05562SScott Long 		for(Index=0; Index < 100; Index++) {
367d74001adSXin LI 			if(CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
368d74001adSXin LI 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);/*clear interrupt*/
36944f05562SScott Long 				return TRUE;
37044f05562SScott Long 			}
37144f05562SScott Long 			UDELAY(10000);
37244f05562SScott Long 		}/*max 1 seconds*/
37344f05562SScott Long 	}while(Retries++ < 20);/*max 20 sec*/
374dac36688SXin LI 	return (FALSE);
37544f05562SScott Long }
37644f05562SScott Long /*
37744f05562SScott Long **********************************************************************
37844f05562SScott Long **********************************************************************
37944f05562SScott Long */
38044f05562SScott Long static u_int8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb)
38144f05562SScott Long {
38244f05562SScott Long 	u_int32_t Index;
38344f05562SScott Long 	u_int8_t Retries = 0x00;
384b23a1998SXin LI 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
38544f05562SScott Long 
38644f05562SScott Long 	do {
38744f05562SScott Long 		for(Index=0; Index < 100; Index++) {
388b23a1998SXin LI 			if(READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
389b23a1998SXin LI 				WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);/*clear interrupt*/
390b23a1998SXin LI 				WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
391d74001adSXin LI 				return TRUE;
392d74001adSXin LI 			}
393d74001adSXin LI 			UDELAY(10000);
394d74001adSXin LI 		}/*max 1 seconds*/
395d74001adSXin LI 	}while(Retries++ < 20);/*max 20 sec*/
396dac36688SXin LI 	return (FALSE);
397d74001adSXin LI }
398d74001adSXin LI /*
399d74001adSXin LI **********************************************************************
400d74001adSXin LI **********************************************************************
401d74001adSXin LI */
402d74001adSXin LI static u_int8_t arcmsr_hbc_wait_msgint_ready(struct AdapterControlBlock *acb)
403d74001adSXin LI {
404d74001adSXin LI 	u_int32_t Index;
405d74001adSXin LI 	u_int8_t Retries = 0x00;
406d74001adSXin LI 
407d74001adSXin LI 	do {
408d74001adSXin LI 		for(Index=0; Index < 100; Index++) {
409d74001adSXin LI 			if(CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) {
410d74001adSXin LI 				CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);/*clear interrupt*/
41144f05562SScott Long 				return TRUE;
41244f05562SScott Long 			}
41344f05562SScott Long 			UDELAY(10000);
41444f05562SScott Long 		}/*max 1 seconds*/
41544f05562SScott Long 	}while(Retries++ < 20);/*max 20 sec*/
416dac36688SXin LI 	return (FALSE);
41744f05562SScott Long }
41844f05562SScott Long /*
4197a7bc959SXin LI **********************************************************************
4207a7bc959SXin LI **********************************************************************
4217a7bc959SXin LI */
4227a7bc959SXin LI static u_int8_t arcmsr_hbd_wait_msgint_ready(struct AdapterControlBlock *acb)
4237a7bc959SXin LI {
4247a7bc959SXin LI 	u_int32_t Index;
4257a7bc959SXin LI 	u_int8_t Retries = 0x00;
4267a7bc959SXin LI 
4277a7bc959SXin LI 	do {
4287a7bc959SXin LI 		for(Index=0; Index < 100; Index++) {
4297a7bc959SXin LI 			if(CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) {
4307a7bc959SXin LI 				CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR);/*clear interrupt*/
4317a7bc959SXin LI 				return TRUE;
4327a7bc959SXin LI 			}
4337a7bc959SXin LI 			UDELAY(10000);
4347a7bc959SXin LI 		}/*max 1 seconds*/
4357a7bc959SXin LI 	}while(Retries++ < 20);/*max 20 sec*/
4367a7bc959SXin LI 	return (FALSE);
4377a7bc959SXin LI }
4387a7bc959SXin LI /*
439a1103e04SXin LI **********************************************************************
440a1103e04SXin LI **********************************************************************
441a1103e04SXin LI */
442a1103e04SXin LI static u_int8_t arcmsr_hbe_wait_msgint_ready(struct AdapterControlBlock *acb)
443a1103e04SXin LI {
444a1103e04SXin LI 	u_int32_t Index, read_doorbell;
445a1103e04SXin LI 	u_int8_t Retries = 0x00;
446a1103e04SXin LI 
447a1103e04SXin LI 	do {
448a1103e04SXin LI 		for(Index=0; Index < 100; Index++) {
449a1103e04SXin LI 			read_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell);
450a1103e04SXin LI 			if((read_doorbell ^ acb->in_doorbell) & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) {
451a1103e04SXin LI 				CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0);/*clear interrupt*/
452a1103e04SXin LI 				acb->in_doorbell = read_doorbell;
453a1103e04SXin LI 				return TRUE;
454a1103e04SXin LI 			}
455a1103e04SXin LI 			UDELAY(10000);
456a1103e04SXin LI 		}/*max 1 seconds*/
457a1103e04SXin LI 	}while(Retries++ < 20);/*max 20 sec*/
458a1103e04SXin LI 	return (FALSE);
459a1103e04SXin LI }
460a1103e04SXin LI /*
46144f05562SScott Long ************************************************************************
46244f05562SScott Long ************************************************************************
46344f05562SScott Long */
46444f05562SScott Long static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb)
46544f05562SScott Long {
46644f05562SScott Long 	int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */
46744f05562SScott Long 
468d74001adSXin LI 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
46944f05562SScott Long 	do {
47044f05562SScott Long 		if(arcmsr_hba_wait_msgint_ready(acb)) {
47144f05562SScott Long 			break;
47244f05562SScott Long 		} else {
47344f05562SScott Long 			retry_count--;
47444f05562SScott Long 		}
47544f05562SScott Long 	}while(retry_count != 0);
47644f05562SScott Long }
47744f05562SScott Long /*
47844f05562SScott Long ************************************************************************
47944f05562SScott Long ************************************************************************
48044f05562SScott Long */
48144f05562SScott Long static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb)
48244f05562SScott Long {
48344f05562SScott Long 	int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */
484b23a1998SXin LI 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
48544f05562SScott Long 
486b23a1998SXin LI 	WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_FLUSH_CACHE);
48744f05562SScott Long 	do {
48844f05562SScott Long 		if(arcmsr_hbb_wait_msgint_ready(acb)) {
48944f05562SScott Long 			break;
49044f05562SScott Long 		} else {
49144f05562SScott Long 			retry_count--;
49244f05562SScott Long 		}
49344f05562SScott Long 	}while(retry_count != 0);
49444f05562SScott Long }
49544f05562SScott Long /*
49644f05562SScott Long ************************************************************************
49744f05562SScott Long ************************************************************************
49844f05562SScott Long */
499d74001adSXin LI static void arcmsr_flush_hbc_cache(struct AdapterControlBlock *acb)
500d74001adSXin LI {
501d74001adSXin LI 	int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */
502d74001adSXin LI 
503d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
504d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
505d74001adSXin LI 	do {
506d74001adSXin LI 		if(arcmsr_hbc_wait_msgint_ready(acb)) {
507d74001adSXin LI 			break;
508d74001adSXin LI 		} else {
509d74001adSXin LI 			retry_count--;
510d74001adSXin LI 		}
511d74001adSXin LI 	}while(retry_count != 0);
512d74001adSXin LI }
513d74001adSXin LI /*
514d74001adSXin LI ************************************************************************
515d74001adSXin LI ************************************************************************
516d74001adSXin LI */
5177a7bc959SXin LI static void arcmsr_flush_hbd_cache(struct AdapterControlBlock *acb)
5187a7bc959SXin LI {
5197a7bc959SXin LI 	int retry_count = 30; /* enlarge wait flush adapter cache time: 10 minute */
5207a7bc959SXin LI 
5217a7bc959SXin LI 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
5227a7bc959SXin LI 	do {
5237a7bc959SXin LI 		if(arcmsr_hbd_wait_msgint_ready(acb)) {
5247a7bc959SXin LI 			break;
5257a7bc959SXin LI 		} else {
5267a7bc959SXin LI 			retry_count--;
5277a7bc959SXin LI 		}
5287a7bc959SXin LI 	}while(retry_count != 0);
5297a7bc959SXin LI }
5307a7bc959SXin LI /*
5317a7bc959SXin LI ************************************************************************
5327a7bc959SXin LI ************************************************************************
5337a7bc959SXin LI */
534a1103e04SXin LI static void arcmsr_flush_hbe_cache(struct AdapterControlBlock *acb)
535a1103e04SXin LI {
536a1103e04SXin LI 	int retry_count = 30;/* enlarge wait flush adapter cache time: 10 minute */
537a1103e04SXin LI 
538a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_FLUSH_CACHE);
539a1103e04SXin LI 	acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
540a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
541a1103e04SXin LI 	do {
542a1103e04SXin LI 		if(arcmsr_hbe_wait_msgint_ready(acb)) {
543a1103e04SXin LI 			break;
544a1103e04SXin LI 		} else {
545a1103e04SXin LI 			retry_count--;
546a1103e04SXin LI 		}
547a1103e04SXin LI 	}while(retry_count != 0);
548a1103e04SXin LI }
549a1103e04SXin LI /*
550a1103e04SXin LI ************************************************************************
551a1103e04SXin LI ************************************************************************
552a1103e04SXin LI */
55344f05562SScott Long static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb)
55444f05562SScott Long {
55544f05562SScott Long 	switch (acb->adapter_type) {
55644f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
55744f05562SScott Long 			arcmsr_flush_hba_cache(acb);
55844f05562SScott Long 		}
55944f05562SScott Long 		break;
56044f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
56144f05562SScott Long 			arcmsr_flush_hbb_cache(acb);
56244f05562SScott Long 		}
56344f05562SScott Long 		break;
564d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
565d74001adSXin LI 			arcmsr_flush_hbc_cache(acb);
566d74001adSXin LI 		}
567d74001adSXin LI 		break;
5687a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
5697a7bc959SXin LI 			arcmsr_flush_hbd_cache(acb);
5707a7bc959SXin LI 		}
5717a7bc959SXin LI 		break;
572fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
573fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
574a1103e04SXin LI 			arcmsr_flush_hbe_cache(acb);
575a1103e04SXin LI 		}
576a1103e04SXin LI 		break;
57744f05562SScott Long 	}
57844f05562SScott Long }
57944f05562SScott Long /*
580ad6d6297SScott Long *******************************************************************************
581ad6d6297SScott Long *******************************************************************************
582f1c579b1SScott Long */
583ad6d6297SScott Long static int arcmsr_suspend(device_t dev)
584f1c579b1SScott Long {
585ad6d6297SScott Long 	struct AdapterControlBlock	*acb = device_get_softc(dev);
586f1c579b1SScott Long 
587ad6d6297SScott Long 	/* flush controller */
588ad6d6297SScott Long 	arcmsr_iop_parking(acb);
589d74001adSXin LI 	/* disable all outbound interrupt */
590d74001adSXin LI 	arcmsr_disable_allintr(acb);
591ad6d6297SScott Long 	return(0);
592ad6d6297SScott Long }
593ad6d6297SScott Long /*
594ad6d6297SScott Long *******************************************************************************
595ad6d6297SScott Long *******************************************************************************
596ad6d6297SScott Long */
597ad6d6297SScott Long static int arcmsr_resume(device_t dev)
598ad6d6297SScott Long {
599ad6d6297SScott Long 	struct AdapterControlBlock	*acb = device_get_softc(dev);
600f1c579b1SScott Long 
601ad6d6297SScott Long 	arcmsr_iop_init(acb);
602ad6d6297SScott Long 	return(0);
603f1c579b1SScott Long }
604f1c579b1SScott Long /*
605f1c579b1SScott Long *********************************************************************************
606f1c579b1SScott Long *********************************************************************************
607f1c579b1SScott Long */
608ad6d6297SScott Long static void arcmsr_async(void *cb_arg, u_int32_t code, struct cam_path *path, void *arg)
609f1c579b1SScott Long {
610ad6d6297SScott Long 	u_int8_t target_id, target_lun;
611f1c579b1SScott Long 
612ad6d6297SScott Long 	switch (code) {
613f1c579b1SScott Long 	case AC_LOST_DEVICE:
614f1c579b1SScott Long 		target_id = xpt_path_target_id(path);
615f1c579b1SScott Long 		target_lun = xpt_path_lun_id(path);
616d74001adSXin LI 		if((target_id > ARCMSR_MAX_TARGETID) || (target_lun > ARCMSR_MAX_TARGETLUN)) {
617f1c579b1SScott Long 			break;
618f1c579b1SScott Long 		}
619f1c579b1SScott Long 		break;
620f1c579b1SScott Long 	default:
621f1c579b1SScott Long 		break;
622f1c579b1SScott Long 	}
623f1c579b1SScott Long }
624f1c579b1SScott Long /*
625f1c579b1SScott Long **********************************************************************
626f1c579b1SScott Long **********************************************************************
627f1c579b1SScott Long */
628ad6d6297SScott Long static void arcmsr_report_sense_info(struct CommandControlBlock *srb)
629f1c579b1SScott Long {
630ad6d6297SScott Long 	union ccb *pccb = srb->pccb;
631f1c579b1SScott Long 
632ad6d6297SScott Long 	pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
633ad6d6297SScott Long 	pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
634dac36688SXin LI 	if(pccb->csio.sense_len) {
635ad6d6297SScott Long 		memset(&pccb->csio.sense_data, 0, sizeof(pccb->csio.sense_data));
636ad6d6297SScott Long 		memcpy(&pccb->csio.sense_data, srb->arcmsr_cdb.SenseData,
637ad6d6297SScott Long 		get_min(sizeof(struct SENSE_DATA), sizeof(pccb->csio.sense_data)));
638ad6d6297SScott Long 		((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70); /* Valid,ErrorCode */
639f1c579b1SScott Long 		pccb->ccb_h.status |= CAM_AUTOSNS_VALID;
640f1c579b1SScott Long 	}
641f1c579b1SScott Long }
642f1c579b1SScott Long /*
643f1c579b1SScott Long *********************************************************************
64444f05562SScott Long *********************************************************************
64544f05562SScott Long */
64644f05562SScott Long static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb)
64744f05562SScott Long {
64844f05562SScott Long 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD);
64944f05562SScott Long 	if(!arcmsr_hba_wait_msgint_ready(acb)) {
650d74001adSXin LI 		printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
65144f05562SScott Long 	}
65244f05562SScott Long }
65344f05562SScott Long /*
65444f05562SScott Long *********************************************************************
65544f05562SScott Long *********************************************************************
65644f05562SScott Long */
65744f05562SScott Long static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb)
65844f05562SScott Long {
659b23a1998SXin LI 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
660b23a1998SXin LI 	WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_ABORT_CMD);
66144f05562SScott Long 	if(!arcmsr_hbb_wait_msgint_ready(acb)) {
662d74001adSXin LI 		printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
663d74001adSXin LI 	}
664d74001adSXin LI }
665d74001adSXin LI /*
666d74001adSXin LI *********************************************************************
667d74001adSXin LI *********************************************************************
668d74001adSXin LI */
669d74001adSXin LI static void arcmsr_abort_hbc_allcmd(struct AdapterControlBlock *acb)
670d74001adSXin LI {
671d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD);
672d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
673d74001adSXin LI 	if(!arcmsr_hbc_wait_msgint_ready(acb)) {
674d74001adSXin LI 		printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
67544f05562SScott Long 	}
67644f05562SScott Long }
67744f05562SScott Long /*
67844f05562SScott Long *********************************************************************
679f1c579b1SScott Long *********************************************************************
680f1c579b1SScott Long */
6817a7bc959SXin LI static void arcmsr_abort_hbd_allcmd(struct AdapterControlBlock *acb)
6827a7bc959SXin LI {
6837a7bc959SXin LI 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD);
6847a7bc959SXin LI 	if(!arcmsr_hbd_wait_msgint_ready(acb)) {
6857a7bc959SXin LI 		printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
6867a7bc959SXin LI 	}
6877a7bc959SXin LI }
6887a7bc959SXin LI /*
6897a7bc959SXin LI *********************************************************************
6907a7bc959SXin LI *********************************************************************
6917a7bc959SXin LI */
692a1103e04SXin LI static void arcmsr_abort_hbe_allcmd(struct AdapterControlBlock *acb)
693a1103e04SXin LI {
694a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_ABORT_CMD);
695a1103e04SXin LI 	acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
696a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
697a1103e04SXin LI 	if(!arcmsr_hbe_wait_msgint_ready(acb)) {
698a1103e04SXin LI 		printf("arcmsr%d: wait 'abort all outstanding command' timeout \n", acb->pci_unit);
699a1103e04SXin LI 	}
700a1103e04SXin LI }
701a1103e04SXin LI /*
702a1103e04SXin LI *********************************************************************
703a1103e04SXin LI *********************************************************************
704a1103e04SXin LI */
705ad6d6297SScott Long static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb)
706f1c579b1SScott Long {
70744f05562SScott Long 	switch (acb->adapter_type) {
70844f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
70944f05562SScott Long 			arcmsr_abort_hba_allcmd(acb);
71044f05562SScott Long 		}
71144f05562SScott Long 		break;
71244f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
71344f05562SScott Long 			arcmsr_abort_hbb_allcmd(acb);
71444f05562SScott Long 		}
71544f05562SScott Long 		break;
716d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
717d74001adSXin LI 			arcmsr_abort_hbc_allcmd(acb);
718d74001adSXin LI 		}
719d74001adSXin LI 		break;
7207a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
7217a7bc959SXin LI 			arcmsr_abort_hbd_allcmd(acb);
7227a7bc959SXin LI 		}
7237a7bc959SXin LI 		break;
724fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
725fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
726a1103e04SXin LI 			arcmsr_abort_hbe_allcmd(acb);
727a1103e04SXin LI 		}
728a1103e04SXin LI 		break;
72944f05562SScott Long 	}
73044f05562SScott Long }
73144f05562SScott Long /*
732231c8b71SXin LI **********************************************************************
733231c8b71SXin LI **********************************************************************
734231c8b71SXin LI */
735231c8b71SXin LI static void arcmsr_srb_complete(struct CommandControlBlock *srb, int stand_flag)
736231c8b71SXin LI {
737231c8b71SXin LI 	struct AdapterControlBlock *acb = srb->acb;
738231c8b71SXin LI 	union ccb *pccb = srb->pccb;
739231c8b71SXin LI 
74022f2616bSXin LI 	if(srb->srb_flags & SRB_FLAG_TIMER_START)
74122f2616bSXin LI 		callout_stop(&srb->ccb_callout);
742231c8b71SXin LI 	if((pccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
743231c8b71SXin LI 		bus_dmasync_op_t op;
744231c8b71SXin LI 
745231c8b71SXin LI 		if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
746231c8b71SXin LI 			op = BUS_DMASYNC_POSTREAD;
747231c8b71SXin LI 		} else {
748231c8b71SXin LI 			op = BUS_DMASYNC_POSTWRITE;
749231c8b71SXin LI 		}
750231c8b71SXin LI 		bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op);
751231c8b71SXin LI 		bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap);
752231c8b71SXin LI 	}
753231c8b71SXin LI 	if(stand_flag == 1) {
754231c8b71SXin LI 		atomic_subtract_int(&acb->srboutstandingcount, 1);
755231c8b71SXin LI 		if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) && (
756abfdbca9SXin LI 		acb->srboutstandingcount < (acb->maxOutstanding -10))) {
757231c8b71SXin LI 			acb->acb_flags &= ~ACB_F_CAM_DEV_QFRZN;
758231c8b71SXin LI 			pccb->ccb_h.status |= CAM_RELEASE_SIMQ;
759231c8b71SXin LI 		}
760231c8b71SXin LI 	}
76122f2616bSXin LI 	if(srb->srb_state != ARCMSR_SRB_TIMEOUT)
76222f2616bSXin LI 		arcmsr_free_srb(srb);
76322f2616bSXin LI 	acb->pktReturnCount++;
764231c8b71SXin LI 	xpt_done(pccb);
765231c8b71SXin LI }
766231c8b71SXin LI /*
76744f05562SScott Long **************************************************************************
76844f05562SScott Long **************************************************************************
76944f05562SScott Long */
770d74001adSXin LI static void arcmsr_report_srb_state(struct AdapterControlBlock *acb, struct CommandControlBlock *srb, u_int16_t error)
77144f05562SScott Long {
77244f05562SScott Long 	int target, lun;
77344f05562SScott Long 
77444f05562SScott Long 	target = srb->pccb->ccb_h.target_id;
77544f05562SScott Long 	lun = srb->pccb->ccb_h.target_lun;
776d74001adSXin LI 	if(error == FALSE) {
77744f05562SScott Long 		if(acb->devstate[target][lun] == ARECA_RAID_GONE) {
77844f05562SScott Long 			acb->devstate[target][lun] = ARECA_RAID_GOOD;
77944f05562SScott Long 		}
78044f05562SScott Long 		srb->pccb->ccb_h.status |= CAM_REQ_CMP;
78144f05562SScott Long 		arcmsr_srb_complete(srb, 1);
78244f05562SScott Long 	} else {
78344f05562SScott Long 		switch(srb->arcmsr_cdb.DeviceStatus) {
78444f05562SScott Long 		case ARCMSR_DEV_SELECT_TIMEOUT: {
78544f05562SScott Long 				if(acb->devstate[target][lun] == ARECA_RAID_GOOD) {
786d74001adSXin LI 					printf( "arcmsr%d: Target=%x, Lun=%x, selection timeout, raid volume was lost\n", acb->pci_unit, target, lun);
787ad6d6297SScott Long 				}
78844f05562SScott Long 				acb->devstate[target][lun] = ARECA_RAID_GONE;
789d74001adSXin LI 				srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
79044f05562SScott Long 				arcmsr_srb_complete(srb, 1);
79144f05562SScott Long 			}
79244f05562SScott Long 			break;
79344f05562SScott Long 		case ARCMSR_DEV_ABORTED:
79444f05562SScott Long 		case ARCMSR_DEV_INIT_FAIL: {
79544f05562SScott Long 				acb->devstate[target][lun] = ARECA_RAID_GONE;
79644f05562SScott Long 				srb->pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
79744f05562SScott Long 				arcmsr_srb_complete(srb, 1);
79844f05562SScott Long 			}
79944f05562SScott Long 			break;
80044f05562SScott Long 		case SCSISTAT_CHECK_CONDITION: {
80144f05562SScott Long 				acb->devstate[target][lun] = ARECA_RAID_GOOD;
80244f05562SScott Long 				arcmsr_report_sense_info(srb);
80344f05562SScott Long 				arcmsr_srb_complete(srb, 1);
80444f05562SScott Long 			}
80544f05562SScott Long 			break;
80644f05562SScott Long 		default:
80710d66948SKevin Lo 			printf("arcmsr%d: scsi id=%d lun=%d isr got command error done,but got unknown DeviceStatus=0x%x \n"
808d74001adSXin LI 					, acb->pci_unit, target, lun ,srb->arcmsr_cdb.DeviceStatus);
80944f05562SScott Long 			acb->devstate[target][lun] = ARECA_RAID_GONE;
81044f05562SScott Long 			srb->pccb->ccb_h.status |= CAM_UNCOR_PARITY;
81110d66948SKevin Lo 			/*unknown error or crc error just for retry*/
81244f05562SScott Long 			arcmsr_srb_complete(srb, 1);
81344f05562SScott Long 			break;
81444f05562SScott Long 		}
81544f05562SScott Long 	}
81644f05562SScott Long }
81744f05562SScott Long /*
81844f05562SScott Long **************************************************************************
81944f05562SScott Long **************************************************************************
82044f05562SScott Long */
821d74001adSXin LI static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, u_int32_t flag_srb, u_int16_t error)
82244f05562SScott Long {
82344f05562SScott Long 	struct CommandControlBlock *srb;
82444f05562SScott Long 
82544f05562SScott Long 	/* check if command done with no error*/
826d74001adSXin LI 	switch (acb->adapter_type) {
827fc5ef1caSXin LI 	case ACB_ADAPTER_TYPE_A:
828fc5ef1caSXin LI 	case ACB_ADAPTER_TYPE_B:
829fc5ef1caSXin LI 		srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
830fc5ef1caSXin LI 		break;
831d74001adSXin LI 	case ACB_ADAPTER_TYPE_C:
8327a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D:
83322f2616bSXin LI 		srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0)); /*frame must be 32 bytes aligned*/
834d74001adSXin LI 		break;
835a1103e04SXin LI 	case ACB_ADAPTER_TYPE_E:
836fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F:
837a1103e04SXin LI 		srb = acb->psrb_pool[flag_srb];
838a1103e04SXin LI 		break;
839d74001adSXin LI 	default:
840d74001adSXin LI 		srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
841d74001adSXin LI 		break;
842d74001adSXin LI 	}
84322f2616bSXin LI 	if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
84422f2616bSXin LI 		if(srb->srb_state == ARCMSR_SRB_TIMEOUT) {
84522f2616bSXin LI 			arcmsr_free_srb(srb);
84622f2616bSXin LI 			printf("arcmsr%d: srb='%p' return srb has been timeouted\n", acb->pci_unit, srb);
84744f05562SScott Long 			return;
84844f05562SScott Long 		}
84922f2616bSXin LI 		printf("arcmsr%d: return srb has been completed\n"
85022f2616bSXin LI 			"srb='%p' srb_state=0x%x outstanding srb count=%d \n",
85122f2616bSXin LI 			acb->pci_unit, srb, srb->srb_state, acb->srboutstandingcount);
85244f05562SScott Long 		return;
85344f05562SScott Long 	}
854d74001adSXin LI 	arcmsr_report_srb_state(acb, srb, error);
85544f05562SScott Long }
85644f05562SScott Long /*
85722f2616bSXin LI **************************************************************************
85822f2616bSXin LI **************************************************************************
85922f2616bSXin LI */
86022f2616bSXin LI static void	arcmsr_srb_timeout(void *arg)
86122f2616bSXin LI {
86222f2616bSXin LI 	struct CommandControlBlock *srb = (struct CommandControlBlock *)arg;
86322f2616bSXin LI 	struct AdapterControlBlock *acb;
86422f2616bSXin LI 	int target, lun;
86522f2616bSXin LI 	u_int8_t cmd;
86622f2616bSXin LI 
86722f2616bSXin LI 	target = srb->pccb->ccb_h.target_id;
86822f2616bSXin LI 	lun = srb->pccb->ccb_h.target_lun;
86922f2616bSXin LI 	acb = srb->acb;
8707a7bc959SXin LI 	ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
87122f2616bSXin LI 	if(srb->srb_state == ARCMSR_SRB_START)
87222f2616bSXin LI 	{
8734aa947cbSWarner Losh 		cmd = scsiio_cdb_ptr(&srb->pccb->csio)[0];
87422f2616bSXin LI 		srb->srb_state = ARCMSR_SRB_TIMEOUT;
87522f2616bSXin LI 		srb->pccb->ccb_h.status |= CAM_CMD_TIMEOUT;
87622f2616bSXin LI 		arcmsr_srb_complete(srb, 1);
87722f2616bSXin LI 		printf("arcmsr%d: scsi id %d lun %d cmd=0x%x srb='%p' ccb command time out!\n",
87822f2616bSXin LI 				 acb->pci_unit, target, lun, cmd, srb);
87922f2616bSXin LI 	}
8807a7bc959SXin LI 	ARCMSR_LOCK_RELEASE(&acb->isr_lock);
88122f2616bSXin LI #ifdef ARCMSR_DEBUG1
88222f2616bSXin LI 	arcmsr_dump_data(acb);
88322f2616bSXin LI #endif
88422f2616bSXin LI }
88522f2616bSXin LI 
88622f2616bSXin LI /*
88744f05562SScott Long **********************************************************************
88844f05562SScott Long **********************************************************************
88944f05562SScott Long */
89044f05562SScott Long static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb)
89144f05562SScott Long {
89244f05562SScott Long 	int i=0;
89344f05562SScott Long 	u_int32_t flag_srb;
894d74001adSXin LI 	u_int16_t error;
89544f05562SScott Long 
89644f05562SScott Long 	switch (acb->adapter_type) {
89744f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
89844f05562SScott Long 			u_int32_t outbound_intstatus;
89944f05562SScott Long 
90044f05562SScott Long 			/*clear and abort all outbound posted Q*/
901d74001adSXin LI 			outbound_intstatus = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable;
902d74001adSXin LI 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);/*clear interrupt*/
903d74001adSXin LI 			while(((flag_srb=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_queueport)) != 0xFFFFFFFF) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) {
904d74001adSXin LI 				error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
905d74001adSXin LI 				arcmsr_drain_donequeue(acb, flag_srb, error);
90644f05562SScott Long 			}
90744f05562SScott Long 		}
90844f05562SScott Long 		break;
90944f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
91044f05562SScott Long 			struct HBB_MessageUnit *phbbmu=(struct HBB_MessageUnit *)acb->pmu;
91144f05562SScott Long 
91244f05562SScott Long 			/*clear all outbound posted Q*/
913b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */
91444f05562SScott Long 			for(i=0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) {
91544f05562SScott Long 				if((flag_srb = phbbmu->done_qbuffer[i]) != 0) {
91644f05562SScott Long 					phbbmu->done_qbuffer[i] = 0;
917d74001adSXin LI 					error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
918d74001adSXin LI 					arcmsr_drain_donequeue(acb, flag_srb, error);
91944f05562SScott Long 				}
92044f05562SScott Long 				phbbmu->post_qbuffer[i] = 0;
92144f05562SScott Long 			}/*drain reply FIFO*/
92244f05562SScott Long 			phbbmu->doneq_index = 0;
92344f05562SScott Long 			phbbmu->postq_index = 0;
92444f05562SScott Long 		}
92544f05562SScott Long 		break;
926d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
927d74001adSXin LI 			while((CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) {
928d74001adSXin LI 				flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low);
929d74001adSXin LI 				error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
930d74001adSXin LI 				arcmsr_drain_donequeue(acb, flag_srb, error);
931d74001adSXin LI 			}
932d74001adSXin LI 		}
933d74001adSXin LI 		break;
934fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_D:
9357a7bc959SXin LI 		arcmsr_hbd_postqueue_isr(acb);
9367a7bc959SXin LI 		break;
937fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
938a1103e04SXin LI 		arcmsr_hbe_postqueue_isr(acb);
939fa42a0bfSXin LI 		break;
940fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F:
941fa42a0bfSXin LI 		arcmsr_hbf_postqueue_isr(acb);
942a1103e04SXin LI 		break;
94344f05562SScott Long 	}
944f1c579b1SScott Long }
945f1c579b1SScott Long /*
946f1c579b1SScott Long ****************************************************************************
947f1c579b1SScott Long ****************************************************************************
948f1c579b1SScott Long */
949ad6d6297SScott Long static void arcmsr_iop_reset(struct AdapterControlBlock *acb)
950f1c579b1SScott Long {
951ad6d6297SScott Long 	struct CommandControlBlock *srb;
95244f05562SScott Long 	u_int32_t intmask_org;
953ad6d6297SScott Long 	u_int32_t i=0;
954f1c579b1SScott Long 
95544f05562SScott Long 	if(acb->srboutstandingcount>0) {
95644f05562SScott Long 		/* disable all outbound interrupt */
95744f05562SScott Long 		intmask_org = arcmsr_disable_allintr(acb);
95844f05562SScott Long 		/*clear and abort all outbound posted Q*/
95944f05562SScott Long 		arcmsr_done4abort_postqueue(acb);
960f1c579b1SScott Long 		/* talk to iop 331 outstanding command aborted*/
961ad6d6297SScott Long 		arcmsr_abort_allcmd(acb);
962ad6d6297SScott Long 		for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) {
963ad6d6297SScott Long 			srb = acb->psrb_pool[i];
96422f2616bSXin LI 			if(srb->srb_state == ARCMSR_SRB_START) {
96522f2616bSXin LI 				srb->srb_state = ARCMSR_SRB_ABORTED;
966ad6d6297SScott Long 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
967ad6d6297SScott Long 				arcmsr_srb_complete(srb, 1);
968123055f0SNathan Whitehorn 				printf("arcmsr%d: scsi id=%d lun=%jx srb='%p' aborted\n"
96922f2616bSXin LI 						, acb->pci_unit, srb->pccb->ccb_h.target_id
970123055f0SNathan Whitehorn 						, (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
971f1c579b1SScott Long 			}
972f1c579b1SScott Long 		}
973f1c579b1SScott Long 		/* enable all outbound interrupt */
97444f05562SScott Long 		arcmsr_enable_allintr(acb, intmask_org);
975f1c579b1SScott Long 	}
97622f2616bSXin LI 	acb->srboutstandingcount = 0;
977ad6d6297SScott Long 	acb->workingsrb_doneindex = 0;
978ad6d6297SScott Long 	acb->workingsrb_startindex = 0;
97922f2616bSXin LI 	acb->pktRequestCount = 0;
98022f2616bSXin LI 	acb->pktReturnCount = 0;
981f1c579b1SScott Long }
982f1c579b1SScott Long /*
983f1c579b1SScott Long **********************************************************************
984f1c579b1SScott Long **********************************************************************
985f1c579b1SScott Long */
98644f05562SScott Long static void arcmsr_build_srb(struct CommandControlBlock *srb,
98744f05562SScott Long 		bus_dma_segment_t *dm_segs, u_int32_t nseg)
988f1c579b1SScott Long {
989ad6d6297SScott Long 	struct ARCMSR_CDB *arcmsr_cdb = &srb->arcmsr_cdb;
990ad6d6297SScott Long 	u_int8_t *psge = (u_int8_t *)&arcmsr_cdb->u;
991ad6d6297SScott Long 	u_int32_t address_lo, address_hi;
992ad6d6297SScott Long 	union ccb *pccb = srb->pccb;
993f1c579b1SScott Long 	struct ccb_scsiio *pcsio = &pccb->csio;
994ad6d6297SScott Long 	u_int32_t arccdbsize = 0x30;
995f1c579b1SScott Long 
996ad6d6297SScott Long 	memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB));
997ad6d6297SScott Long 	arcmsr_cdb->Bus = 0;
998ad6d6297SScott Long 	arcmsr_cdb->TargetID = pccb->ccb_h.target_id;
999ad6d6297SScott Long 	arcmsr_cdb->LUN = pccb->ccb_h.target_lun;
1000ad6d6297SScott Long 	arcmsr_cdb->Function = 1;
1001ad6d6297SScott Long 	arcmsr_cdb->CdbLength = (u_int8_t)pcsio->cdb_len;
10024aa947cbSWarner Losh 	bcopy(scsiio_cdb_ptr(pcsio), arcmsr_cdb->Cdb, pcsio->cdb_len);
1003ad6d6297SScott Long 	if(nseg != 0) {
1004ad6d6297SScott Long 		struct AdapterControlBlock *acb = srb->acb;
1005f1c579b1SScott Long 		bus_dmasync_op_t op;
1006ad6d6297SScott Long 		u_int32_t length, i, cdb_sgcount = 0;
1007f1c579b1SScott Long 
1008ad6d6297SScott Long 		if((pccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
1009ad6d6297SScott Long 			op = BUS_DMASYNC_PREREAD;
1010ad6d6297SScott Long 		} else {
1011ad6d6297SScott Long 			op = BUS_DMASYNC_PREWRITE;
1012ad6d6297SScott Long 			arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_WRITE;
1013ad6d6297SScott Long 			srb->srb_flags |= SRB_FLAG_WRITE;
1014ad6d6297SScott Long 		}
1015ad6d6297SScott Long 		bus_dmamap_sync(acb->dm_segs_dmat, srb->dm_segs_dmamap, op);
1016ad6d6297SScott Long 		for(i=0; i < nseg; i++) {
1017f1c579b1SScott Long 			/* Get the physical address of the current data pointer */
1018ad6d6297SScott Long 			length = arcmsr_htole32(dm_segs[i].ds_len);
1019ad6d6297SScott Long 			address_lo = arcmsr_htole32(dma_addr_lo32(dm_segs[i].ds_addr));
1020ad6d6297SScott Long 			address_hi = arcmsr_htole32(dma_addr_hi32(dm_segs[i].ds_addr));
1021ad6d6297SScott Long 			if(address_hi == 0) {
1022ad6d6297SScott Long 				struct SG32ENTRY *pdma_sg = (struct SG32ENTRY *)psge;
1023f1c579b1SScott Long 				pdma_sg->address = address_lo;
1024f1c579b1SScott Long 				pdma_sg->length = length;
1025ad6d6297SScott Long 				psge += sizeof(struct SG32ENTRY);
1026ad6d6297SScott Long 				arccdbsize += sizeof(struct SG32ENTRY);
1027ad6d6297SScott Long 			} else {
1028ad6d6297SScott Long 				u_int32_t sg64s_size = 0, tmplength = length;
1029f1c579b1SScott Long 
1030ad6d6297SScott Long 				while(1) {
1031ad6d6297SScott Long 					u_int64_t span4G, length0;
1032ad6d6297SScott Long 					struct SG64ENTRY *pdma_sg = (struct SG64ENTRY *)psge;
1033f1c579b1SScott Long 
1034ad6d6297SScott Long 					span4G = (u_int64_t)address_lo + tmplength;
1035f1c579b1SScott Long 					pdma_sg->addresshigh = address_hi;
1036f1c579b1SScott Long 					pdma_sg->address = address_lo;
1037ad6d6297SScott Long 					if(span4G > 0x100000000) {
1038f1c579b1SScott Long 						/*see if cross 4G boundary*/
1039f1c579b1SScott Long 						length0 = 0x100000000-address_lo;
1040ad6d6297SScott Long 						pdma_sg->length = (u_int32_t)length0 | IS_SG64_ADDR;
1041f1c579b1SScott Long 						address_hi = address_hi+1;
1042f1c579b1SScott Long 						address_lo = 0;
1043ad6d6297SScott Long 						tmplength = tmplength - (u_int32_t)length0;
1044ad6d6297SScott Long 						sg64s_size += sizeof(struct SG64ENTRY);
1045ad6d6297SScott Long 						psge += sizeof(struct SG64ENTRY);
1046f1c579b1SScott Long 						cdb_sgcount++;
1047ad6d6297SScott Long 					} else {
1048f1c579b1SScott Long 						pdma_sg->length = tmplength | IS_SG64_ADDR;
1049ad6d6297SScott Long 						sg64s_size += sizeof(struct SG64ENTRY);
1050ad6d6297SScott Long 						psge += sizeof(struct SG64ENTRY);
1051f1c579b1SScott Long 						break;
1052f1c579b1SScott Long 					}
1053f1c579b1SScott Long 				}
1054f1c579b1SScott Long 				arccdbsize += sg64s_size;
1055f1c579b1SScott Long 			}
1056f1c579b1SScott Long 			cdb_sgcount++;
1057f1c579b1SScott Long 		}
1058ad6d6297SScott Long 		arcmsr_cdb->sgcount = (u_int8_t)cdb_sgcount;
1059ad6d6297SScott Long 		arcmsr_cdb->DataLength = pcsio->dxfer_len;
1060ad6d6297SScott Long 		if( arccdbsize > 256) {
1061ad6d6297SScott Long 			arcmsr_cdb->Flags |= ARCMSR_CDB_FLAG_SGL_BSIZE;
1062f1c579b1SScott Long 		}
1063d74001adSXin LI 	} else {
1064d74001adSXin LI 		arcmsr_cdb->DataLength = 0;
1065f1c579b1SScott Long 	}
1066d74001adSXin LI 	srb->arc_cdb_size = arccdbsize;
10677a7bc959SXin LI 	arcmsr_cdb->msgPages = (arccdbsize/256) + ((arccdbsize % 256) ? 1 : 0);
1068f1c579b1SScott Long }
1069f1c579b1SScott Long /*
1070f1c579b1SScott Long **************************************************************************
1071f1c579b1SScott Long **************************************************************************
1072f1c579b1SScott Long */
1073ad6d6297SScott Long static void arcmsr_post_srb(struct AdapterControlBlock *acb, struct CommandControlBlock *srb)
1074f1c579b1SScott Long {
10757a7bc959SXin LI 	u_int32_t cdb_phyaddr_low = (u_int32_t) srb->cdb_phyaddr_low;
1076ad6d6297SScott Long 	struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&srb->arcmsr_cdb;
1077f1c579b1SScott Long 
1078d74001adSXin LI 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, (srb->srb_flags & SRB_FLAG_WRITE) ? BUS_DMASYNC_POSTWRITE:BUS_DMASYNC_POSTREAD);
1079ad6d6297SScott Long 	atomic_add_int(&acb->srboutstandingcount, 1);
108022f2616bSXin LI 	srb->srb_state = ARCMSR_SRB_START;
1081d74001adSXin LI 
108244f05562SScott Long 	switch (acb->adapter_type) {
108344f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
1084ad6d6297SScott Long 			if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) {
10857a7bc959SXin LI 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_phyaddr_low|ARCMSR_SRBPOST_FLAG_SGL_BSIZE);
1086ad6d6297SScott Long 			} else {
10877a7bc959SXin LI 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_queueport, cdb_phyaddr_low);
108844f05562SScott Long 			}
108944f05562SScott Long 		}
109044f05562SScott Long 		break;
109144f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
109244f05562SScott Long 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
109344f05562SScott Long 			int ending_index, index;
109444f05562SScott Long 
109544f05562SScott Long 			index = phbbmu->postq_index;
109644f05562SScott Long 			ending_index = ((index+1) % ARCMSR_MAX_HBB_POSTQUEUE);
109744f05562SScott Long 			phbbmu->post_qbuffer[ending_index] = 0;
109844f05562SScott Long 			if(arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) {
10997a7bc959SXin LI 				phbbmu->post_qbuffer[index] = cdb_phyaddr_low | ARCMSR_SRBPOST_FLAG_SGL_BSIZE;
110044f05562SScott Long 			} else {
11017a7bc959SXin LI 				phbbmu->post_qbuffer[index] = cdb_phyaddr_low;
110244f05562SScott Long 			}
110344f05562SScott Long 			index++;
110444f05562SScott Long 			index %= ARCMSR_MAX_HBB_POSTQUEUE;     /*if last index number set it to 0 */
110544f05562SScott Long 			phbbmu->postq_index = index;
1106b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_CDB_POSTED);
1107d74001adSXin LI 		}
1108d74001adSXin LI 		break;
11097a7bc959SXin LI 	case ACB_ADAPTER_TYPE_C: {
1110d74001adSXin LI 			u_int32_t ccb_post_stamp, arc_cdb_size, cdb_phyaddr_hi32;
1111d74001adSXin LI 
1112d74001adSXin LI 			arc_cdb_size = (srb->arc_cdb_size > 0x300) ? 0x300 : srb->arc_cdb_size;
11137a7bc959SXin LI 			ccb_post_stamp = (cdb_phyaddr_low | ((arc_cdb_size-1) >> 6) | 1);
1114d74001adSXin LI 			cdb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high;
1115d74001adSXin LI 			if(cdb_phyaddr_hi32)
1116d74001adSXin LI 			{
1117d74001adSXin LI 				CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_high, cdb_phyaddr_hi32);
1118d74001adSXin LI 				CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp);
1119d74001adSXin LI 			}
1120d74001adSXin LI 			else
1121d74001adSXin LI 			{
1122d74001adSXin LI 				CHIP_REG_WRITE32(HBC_MessageUnit,0,inbound_queueport_low, ccb_post_stamp);
1123d74001adSXin LI 			}
112444f05562SScott Long 		}
112544f05562SScott Long 		break;
11267a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
11277a7bc959SXin LI 			struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
11287a7bc959SXin LI 			u_int16_t index_stripped;
11297a7bc959SXin LI 			u_int16_t postq_index;
11307a7bc959SXin LI 			struct InBound_SRB *pinbound_srb;
11317a7bc959SXin LI 
11327a7bc959SXin LI 			ARCMSR_LOCK_ACQUIRE(&acb->postDone_lock);
11337a7bc959SXin LI 			postq_index = phbdmu->postq_index;
11347a7bc959SXin LI 			pinbound_srb = (struct InBound_SRB *)&phbdmu->post_qbuffer[postq_index & 0xFF];
11357a7bc959SXin LI 			pinbound_srb->addressHigh = srb->cdb_phyaddr_high;
11367a7bc959SXin LI 			pinbound_srb->addressLow = srb->cdb_phyaddr_low;
11377a7bc959SXin LI 			pinbound_srb->length = srb->arc_cdb_size >> 2;
11387a7bc959SXin LI 			arcmsr_cdb->Context = srb->cdb_phyaddr_low;
11397a7bc959SXin LI 			if (postq_index & 0x4000) {
11407a7bc959SXin LI 				index_stripped = postq_index & 0xFF;
11417a7bc959SXin LI 				index_stripped += 1;
11427a7bc959SXin LI 				index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
11437a7bc959SXin LI 				phbdmu->postq_index = index_stripped ? (index_stripped | 0x4000) : index_stripped;
11447a7bc959SXin LI 			} else {
11457a7bc959SXin LI 				index_stripped = postq_index;
11467a7bc959SXin LI 				index_stripped += 1;
11477a7bc959SXin LI 				index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
11487a7bc959SXin LI 				phbdmu->postq_index = index_stripped ? index_stripped : (index_stripped | 0x4000);
11497a7bc959SXin LI 			}
11507a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, inboundlist_write_pointer, postq_index);
11517a7bc959SXin LI 			ARCMSR_LOCK_RELEASE(&acb->postDone_lock);
11527a7bc959SXin LI 		}
11537a7bc959SXin LI 		break;
1154a1103e04SXin LI 	case ACB_ADAPTER_TYPE_E: {
1155a1103e04SXin LI 			u_int32_t ccb_post_stamp, arc_cdb_size;
1156a1103e04SXin LI 
1157a1103e04SXin LI 			arc_cdb_size = (srb->arc_cdb_size > 0x300) ? 0x300 : srb->arc_cdb_size;
1158a1103e04SXin LI 			ccb_post_stamp = (srb->smid | ((arc_cdb_size-1) >> 6));
1159a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_queueport_high, 0);
1160a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_queueport_low, ccb_post_stamp);
1161a1103e04SXin LI 		}
1162a1103e04SXin LI 		break;
1163fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
1164fa42a0bfSXin LI 			u_int32_t ccb_post_stamp, arc_cdb_size;
1165fa42a0bfSXin LI 
1166fa42a0bfSXin LI 			if (srb->arc_cdb_size <= 0x300)
1167fa42a0bfSXin LI 				arc_cdb_size = (srb->arc_cdb_size - 1) >> 6 | 1;
1168438b5532SXin LI 			else {
1169438b5532SXin LI 				arc_cdb_size = ((srb->arc_cdb_size + 0xff) >> 8) + 2;
1170438b5532SXin LI 				if (arc_cdb_size > 0xF)
1171438b5532SXin LI 					arc_cdb_size = 0xF;
1172438b5532SXin LI 				arc_cdb_size = (arc_cdb_size << 1) | 1;
1173438b5532SXin LI 			}
1174fa42a0bfSXin LI 			ccb_post_stamp = (srb->smid | arc_cdb_size);
1175fa42a0bfSXin LI 			CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_queueport_high, 0);
1176fa42a0bfSXin LI 			CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_queueport_low, ccb_post_stamp);
1177fa42a0bfSXin LI 		}
1178fa42a0bfSXin LI 		break;
1179f1c579b1SScott Long 	}
1180f1c579b1SScott Long }
1181f1c579b1SScott Long /*
118244f05562SScott Long ************************************************************************
118344f05562SScott Long ************************************************************************
118444f05562SScott Long */
118544f05562SScott Long static struct QBUFFER *arcmsr_get_iop_rqbuffer( struct AdapterControlBlock *acb)
118644f05562SScott Long {
118744f05562SScott Long 	struct QBUFFER *qbuffer=NULL;
118844f05562SScott Long 
118944f05562SScott Long 	switch (acb->adapter_type) {
119044f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
119144f05562SScott Long 			struct HBA_MessageUnit *phbamu = (struct HBA_MessageUnit *)acb->pmu;
119244f05562SScott Long 
119344f05562SScott Long 			qbuffer = (struct QBUFFER *)&phbamu->message_rbuffer;
119444f05562SScott Long 		}
119544f05562SScott Long 		break;
119644f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
119744f05562SScott Long 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
119844f05562SScott Long 
119944f05562SScott Long 			qbuffer = (struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_rbuffer;
120044f05562SScott Long 		}
120144f05562SScott Long 		break;
1202d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
1203d74001adSXin LI 			struct HBC_MessageUnit *phbcmu = (struct HBC_MessageUnit *)acb->pmu;
1204d74001adSXin LI 
1205d74001adSXin LI 			qbuffer = (struct QBUFFER *)&phbcmu->message_rbuffer;
1206d74001adSXin LI 		}
1207d74001adSXin LI 		break;
12087a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
12097a7bc959SXin LI 			struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
12107a7bc959SXin LI 
12117a7bc959SXin LI 			qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_rbuffer;
12127a7bc959SXin LI 		}
12137a7bc959SXin LI 		break;
1214a1103e04SXin LI 	case ACB_ADAPTER_TYPE_E: {
1215a1103e04SXin LI 			struct HBE_MessageUnit *phbcmu = (struct HBE_MessageUnit *)acb->pmu;
1216a1103e04SXin LI 
1217a1103e04SXin LI 			qbuffer = (struct QBUFFER *)&phbcmu->message_rbuffer;
1218a1103e04SXin LI 		}
1219a1103e04SXin LI 		break;
1220fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F:
1221fa42a0bfSXin LI 		qbuffer = (struct QBUFFER *)acb->message_rbuffer;
1222fa42a0bfSXin LI 		break;
122344f05562SScott Long 	}
122444f05562SScott Long 	return(qbuffer);
122544f05562SScott Long }
122644f05562SScott Long /*
122744f05562SScott Long ************************************************************************
122844f05562SScott Long ************************************************************************
122944f05562SScott Long */
123044f05562SScott Long static struct QBUFFER *arcmsr_get_iop_wqbuffer( struct AdapterControlBlock *acb)
123144f05562SScott Long {
123244f05562SScott Long 	struct QBUFFER *qbuffer = NULL;
123344f05562SScott Long 
123444f05562SScott Long 	switch (acb->adapter_type) {
123544f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
123644f05562SScott Long 			struct HBA_MessageUnit *phbamu = (struct HBA_MessageUnit *)acb->pmu;
123744f05562SScott Long 
123844f05562SScott Long 			qbuffer = (struct QBUFFER *)&phbamu->message_wbuffer;
123944f05562SScott Long 		}
124044f05562SScott Long 		break;
124144f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
124244f05562SScott Long 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
124344f05562SScott Long 
124444f05562SScott Long 			qbuffer = (struct QBUFFER *)&phbbmu->hbb_rwbuffer->message_wbuffer;
124544f05562SScott Long 		}
124644f05562SScott Long 		break;
1247d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
1248d74001adSXin LI 			struct HBC_MessageUnit *phbcmu = (struct HBC_MessageUnit *)acb->pmu;
1249d74001adSXin LI 
1250d74001adSXin LI 			qbuffer = (struct QBUFFER *)&phbcmu->message_wbuffer;
1251d74001adSXin LI 		}
1252d74001adSXin LI 		break;
12537a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
12547a7bc959SXin LI 			struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
12557a7bc959SXin LI 
12567a7bc959SXin LI 			qbuffer = (struct QBUFFER *)&phbdmu->phbdmu->message_wbuffer;
12577a7bc959SXin LI 		}
12587a7bc959SXin LI 		break;
1259a1103e04SXin LI 	case ACB_ADAPTER_TYPE_E: {
1260a1103e04SXin LI 			struct HBE_MessageUnit *phbcmu = (struct HBE_MessageUnit *)acb->pmu;
1261a1103e04SXin LI 
1262a1103e04SXin LI 			qbuffer = (struct QBUFFER *)&phbcmu->message_wbuffer;
1263a1103e04SXin LI 		}
1264a1103e04SXin LI 		break;
1265fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F:
1266fa42a0bfSXin LI 		qbuffer = (struct QBUFFER *)acb->message_wbuffer;
1267fa42a0bfSXin LI 		break;
126844f05562SScott Long 	}
126944f05562SScott Long 	return(qbuffer);
127044f05562SScott Long }
127144f05562SScott Long /*
127244f05562SScott Long **************************************************************************
127344f05562SScott Long **************************************************************************
127444f05562SScott Long */
127544f05562SScott Long static void arcmsr_iop_message_read(struct AdapterControlBlock *acb)
127644f05562SScott Long {
127744f05562SScott Long 	switch (acb->adapter_type) {
127844f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
127944f05562SScott Long 			/* let IOP know data has been read */
1280d74001adSXin LI 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
128144f05562SScott Long 		}
128244f05562SScott Long 		break;
128344f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
1284b23a1998SXin LI 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
128544f05562SScott Long 			/* let IOP know data has been read */
1286b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK);
128744f05562SScott Long 		}
128844f05562SScott Long 		break;
1289d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
1290d74001adSXin LI 			/* let IOP know data has been read */
1291d74001adSXin LI 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK);
1292d74001adSXin LI 		}
12937a7bc959SXin LI 		break;
12947a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
12957a7bc959SXin LI 			/* let IOP know data has been read */
12967a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ);
12977a7bc959SXin LI 		}
12987a7bc959SXin LI 		break;
1299fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
1300fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
1301a1103e04SXin LI 			/* let IOP know data has been read */
1302a1103e04SXin LI 			acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK;
1303a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
1304a1103e04SXin LI 		}
1305a1103e04SXin LI 		break;
130644f05562SScott Long 	}
130744f05562SScott Long }
130844f05562SScott Long /*
130944f05562SScott Long **************************************************************************
131044f05562SScott Long **************************************************************************
131144f05562SScott Long */
131244f05562SScott Long static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb)
131344f05562SScott Long {
131444f05562SScott Long 	switch (acb->adapter_type) {
131544f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
131644f05562SScott Long 			/*
131744f05562SScott Long 			** push inbound doorbell tell iop, driver data write ok
131844f05562SScott Long 			** and wait reply on next hwinterrupt for next Qbuffer post
131944f05562SScott Long 			*/
1320d74001adSXin LI 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK);
132144f05562SScott Long 		}
132244f05562SScott Long 		break;
132344f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
1324b23a1998SXin LI 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
132544f05562SScott Long 			/*
132644f05562SScott Long 			** push inbound doorbell tell iop, driver data write ok
132744f05562SScott Long 			** and wait reply on next hwinterrupt for next Qbuffer post
132844f05562SScott Long 			*/
1329b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_WRITE_OK);
1330d74001adSXin LI 		}
1331d74001adSXin LI 		break;
1332d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
1333d74001adSXin LI 			/*
1334d74001adSXin LI 			** push inbound doorbell tell iop, driver data write ok
1335d74001adSXin LI 			** and wait reply on next hwinterrupt for next Qbuffer post
1336d74001adSXin LI 			*/
1337d74001adSXin LI 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_WRITE_OK);
133844f05562SScott Long 		}
133944f05562SScott Long 		break;
13407a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
134144f05562SScott Long 			/*
13427a7bc959SXin LI 			** push inbound doorbell tell iop, driver data write ok
13437a7bc959SXin LI 			** and wait reply on next hwinterrupt for next Qbuffer post
1344f1c579b1SScott Long 			*/
13457a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_IN_READY);
1346f1c579b1SScott Long 		}
13477a7bc959SXin LI 		break;
1348fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
1349fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
1350a1103e04SXin LI 			/*
1351a1103e04SXin LI 			** push inbound doorbell tell iop, driver data write ok
1352a1103e04SXin LI 			** and wait reply on next hwinterrupt for next Qbuffer post
1353a1103e04SXin LI 			*/
1354a1103e04SXin LI 			acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_WRITE_OK;
1355a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
1356a1103e04SXin LI 		}
1357a1103e04SXin LI 		break;
1358ad6d6297SScott Long 	}
1359f1c579b1SScott Long }
1360f1c579b1SScott Long /*
1361f1c579b1SScott Long ************************************************************************
1362f1c579b1SScott Long ************************************************************************
1363f1c579b1SScott Long */
136444f05562SScott Long static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb)
1365f1c579b1SScott Long {
1366ad6d6297SScott Long 	acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
136744f05562SScott Long 	CHIP_REG_WRITE32(HBA_MessageUnit,
136844f05562SScott Long 		0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
136944f05562SScott Long 	if(!arcmsr_hba_wait_msgint_ready(acb)) {
1370d74001adSXin LI 		printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n"
1371ad6d6297SScott Long 			, acb->pci_unit);
1372ad6d6297SScott Long 	}
1373f1c579b1SScott Long }
1374f1c579b1SScott Long /*
1375f1c579b1SScott Long ************************************************************************
1376f1c579b1SScott Long ************************************************************************
1377f1c579b1SScott Long */
137844f05562SScott Long static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb)
137944f05562SScott Long {
1380b23a1998SXin LI 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
138144f05562SScott Long 	acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
1382b23a1998SXin LI 	WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_STOP_BGRB);
138344f05562SScott Long 	if(!arcmsr_hbb_wait_msgint_ready(acb)) {
1384d74001adSXin LI 		printf( "arcmsr%d: wait 'stop adapter background rebulid' timeout \n"
138544f05562SScott Long 			, acb->pci_unit);
138644f05562SScott Long 	}
138744f05562SScott Long }
138844f05562SScott Long /*
138944f05562SScott Long ************************************************************************
139044f05562SScott Long ************************************************************************
139144f05562SScott Long */
1392d74001adSXin LI static void arcmsr_stop_hbc_bgrb(struct AdapterControlBlock *acb)
1393d74001adSXin LI {
1394d74001adSXin LI 	acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
1395d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
1396d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
1397d74001adSXin LI 	if(!arcmsr_hbc_wait_msgint_ready(acb)) {
1398d74001adSXin LI 		printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit);
1399d74001adSXin LI 	}
1400d74001adSXin LI }
1401d74001adSXin LI /*
1402d74001adSXin LI ************************************************************************
1403d74001adSXin LI ************************************************************************
1404d74001adSXin LI */
14057a7bc959SXin LI static void arcmsr_stop_hbd_bgrb(struct AdapterControlBlock *acb)
14067a7bc959SXin LI {
14077a7bc959SXin LI 	acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
14087a7bc959SXin LI 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
14097a7bc959SXin LI 	if(!arcmsr_hbd_wait_msgint_ready(acb)) {
14107a7bc959SXin LI 		printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit);
14117a7bc959SXin LI 	}
14127a7bc959SXin LI }
14137a7bc959SXin LI /*
14147a7bc959SXin LI ************************************************************************
14157a7bc959SXin LI ************************************************************************
14167a7bc959SXin LI */
1417a1103e04SXin LI static void arcmsr_stop_hbe_bgrb(struct AdapterControlBlock *acb)
1418a1103e04SXin LI {
1419a1103e04SXin LI 	acb->acb_flags &= ~ACB_F_MSG_START_BGRB;
1420a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_STOP_BGRB);
1421a1103e04SXin LI 	acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
1422a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
1423a1103e04SXin LI 	if(!arcmsr_hbe_wait_msgint_ready(acb)) {
1424a1103e04SXin LI 		printf("arcmsr%d: wait 'stop adapter background rebulid' timeout \n", acb->pci_unit);
1425a1103e04SXin LI 	}
1426a1103e04SXin LI }
1427a1103e04SXin LI /*
1428a1103e04SXin LI ************************************************************************
1429a1103e04SXin LI ************************************************************************
1430a1103e04SXin LI */
143144f05562SScott Long static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb)
143244f05562SScott Long {
143344f05562SScott Long 	switch (acb->adapter_type) {
143444f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
143544f05562SScott Long 			arcmsr_stop_hba_bgrb(acb);
143644f05562SScott Long 		}
143744f05562SScott Long 		break;
143844f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
143944f05562SScott Long 			arcmsr_stop_hbb_bgrb(acb);
144044f05562SScott Long 		}
144144f05562SScott Long 		break;
1442d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
1443d74001adSXin LI 			arcmsr_stop_hbc_bgrb(acb);
1444d74001adSXin LI 		}
1445d74001adSXin LI 		break;
14467a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
14477a7bc959SXin LI 			arcmsr_stop_hbd_bgrb(acb);
14487a7bc959SXin LI 		}
14497a7bc959SXin LI 		break;
1450fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
1451fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
1452a1103e04SXin LI 			arcmsr_stop_hbe_bgrb(acb);
1453a1103e04SXin LI 		}
1454a1103e04SXin LI 		break;
145544f05562SScott Long 	}
145644f05562SScott Long }
145744f05562SScott Long /*
145844f05562SScott Long ************************************************************************
145944f05562SScott Long ************************************************************************
146044f05562SScott Long */
1461ad6d6297SScott Long static void arcmsr_poll(struct cam_sim *psim)
1462f1c579b1SScott Long {
1463579ec1a5SScott Long 	struct AdapterControlBlock *acb;
14644e32649fSXin LI 	int	mutex;
1465579ec1a5SScott Long 
1466579ec1a5SScott Long 	acb = (struct AdapterControlBlock *)cam_sim_softc(psim);
14677a7bc959SXin LI 	mutex = mtx_owned(&acb->isr_lock);
14684e32649fSXin LI 	if( mutex == 0 )
14697a7bc959SXin LI 		ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
1470579ec1a5SScott Long 	arcmsr_interrupt(acb);
14714e32649fSXin LI 	if( mutex == 0 )
14727a7bc959SXin LI 		ARCMSR_LOCK_RELEASE(&acb->isr_lock);
14737a7bc959SXin LI }
14747a7bc959SXin LI /*
14757a7bc959SXin LI **************************************************************************
14767a7bc959SXin LI **************************************************************************
14777a7bc959SXin LI */
147835689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data_D(struct AdapterControlBlock *acb,
147935689395SXin LI 	struct QBUFFER *prbuffer) {
148035689395SXin LI 	u_int8_t *pQbuffer;
14814d24901aSPedro F. Giffuni 	u_int8_t *buf1 = NULL;
14824d24901aSPedro F. Giffuni 	u_int32_t *iop_data, *buf2 = NULL;
148335689395SXin LI 	u_int32_t iop_len, data_len;
148435689395SXin LI 
148535689395SXin LI 	iop_data = (u_int32_t *)prbuffer->data;
148635689395SXin LI 	iop_len = (u_int32_t)prbuffer->data_len;
148735689395SXin LI 	if ( iop_len > 0 )
148835689395SXin LI 	{
148935689395SXin LI 		buf1 = malloc(128, M_DEVBUF, M_NOWAIT | M_ZERO);
149035689395SXin LI 		buf2 = (u_int32_t *)buf1;
149135689395SXin LI 		if( buf1 == NULL)
149235689395SXin LI 			return (0);
149335689395SXin LI 		data_len = iop_len;
149435689395SXin LI 		while(data_len >= 4)
149535689395SXin LI 		{
149635689395SXin LI 			*buf2++ = *iop_data++;
149735689395SXin LI 			data_len -= 4;
149835689395SXin LI 		}
149935689395SXin LI 		if(data_len)
150035689395SXin LI 			*buf2 = *iop_data;
150135689395SXin LI 		buf2 = (u_int32_t *)buf1;
150235689395SXin LI 	}
150335689395SXin LI 	while (iop_len > 0) {
150435689395SXin LI 		pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex];
150535689395SXin LI 		*pQbuffer = *buf1;
150635689395SXin LI 		acb->rqbuf_lastindex++;
150735689395SXin LI 		/* if last, index number set it to 0 */
150835689395SXin LI 		acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
150935689395SXin LI 		buf1++;
151035689395SXin LI 		iop_len--;
151135689395SXin LI 	}
151235689395SXin LI 	if(buf2)
151335689395SXin LI 		free( (u_int8_t *)buf2, M_DEVBUF);
151435689395SXin LI 	/* let IOP know data has been read */
151535689395SXin LI 	arcmsr_iop_message_read(acb);
151635689395SXin LI 	return (1);
151735689395SXin LI }
151835689395SXin LI /*
151935689395SXin LI **************************************************************************
152035689395SXin LI **************************************************************************
152135689395SXin LI */
152235689395SXin LI static u_int32_t arcmsr_Read_iop_rqbuffer_data(struct AdapterControlBlock *acb,
15237a7bc959SXin LI 	struct QBUFFER *prbuffer) {
15247a7bc959SXin LI 	u_int8_t *pQbuffer;
15257a7bc959SXin LI 	u_int8_t *iop_data;
15267a7bc959SXin LI 	u_int32_t iop_len;
15277a7bc959SXin LI 
1528fc5ef1caSXin LI 	if(acb->adapter_type >= ACB_ADAPTER_TYPE_B) {
152935689395SXin LI 		return(arcmsr_Read_iop_rqbuffer_data_D(acb, prbuffer));
153035689395SXin LI 	}
15317a7bc959SXin LI 	iop_data = (u_int8_t *)prbuffer->data;
15327a7bc959SXin LI 	iop_len = (u_int32_t)prbuffer->data_len;
15337a7bc959SXin LI 	while (iop_len > 0) {
15347a7bc959SXin LI 		pQbuffer = &acb->rqbuffer[acb->rqbuf_lastindex];
15357a7bc959SXin LI 		*pQbuffer = *iop_data;
15367a7bc959SXin LI 		acb->rqbuf_lastindex++;
15377a7bc959SXin LI 		/* if last, index number set it to 0 */
15387a7bc959SXin LI 		acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
15397a7bc959SXin LI 		iop_data++;
15407a7bc959SXin LI 		iop_len--;
15417a7bc959SXin LI 	}
15427a7bc959SXin LI 	/* let IOP know data has been read */
15437a7bc959SXin LI 	arcmsr_iop_message_read(acb);
154435689395SXin LI 	return (1);
1545f1c579b1SScott Long }
1546f1c579b1SScott Long /*
154744f05562SScott Long **************************************************************************
154844f05562SScott Long **************************************************************************
15495878cbecSScott Long */
155044f05562SScott Long static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb)
1551f1c579b1SScott Long {
155244f05562SScott Long 	struct QBUFFER *prbuffer;
15537a7bc959SXin LI 	int my_empty_len;
1554ad6d6297SScott Long 
1555f1c579b1SScott Long 	/*check this iop data if overflow my rqbuffer*/
15567a7bc959SXin LI 	ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
155744f05562SScott Long 	prbuffer = arcmsr_get_iop_rqbuffer(acb);
15587a7bc959SXin LI 	my_empty_len = (acb->rqbuf_lastindex - acb->rqbuf_firstindex - 1) &
15597a7bc959SXin LI 		(ARCMSR_MAX_QBUFFER-1);
15607a7bc959SXin LI 	if(my_empty_len >= prbuffer->data_len) {
156135689395SXin LI 		if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
156235689395SXin LI 			acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
1563ad6d6297SScott Long 	} else {
1564ad6d6297SScott Long 		acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
1565f1c579b1SScott Long 	}
15667a7bc959SXin LI 	ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
15677a7bc959SXin LI }
15687a7bc959SXin LI /*
15697a7bc959SXin LI **********************************************************************
15707a7bc959SXin LI **********************************************************************
15717a7bc959SXin LI */
157235689395SXin LI static void arcmsr_Write_data_2iop_wqbuffer_D(struct AdapterControlBlock *acb)
157335689395SXin LI {
157435689395SXin LI 	u_int8_t *pQbuffer;
157535689395SXin LI 	struct QBUFFER *pwbuffer;
15764d24901aSPedro F. Giffuni 	u_int8_t *buf1 = NULL;
15774d24901aSPedro F. Giffuni 	u_int32_t *iop_data, *buf2 = NULL;
157835689395SXin LI 	u_int32_t allxfer_len = 0, data_len;
157935689395SXin LI 
158035689395SXin LI 	if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) {
158135689395SXin LI 		buf1 = malloc(128, M_DEVBUF, M_NOWAIT | M_ZERO);
158235689395SXin LI 		buf2 = (u_int32_t *)buf1;
158335689395SXin LI 		if( buf1 == NULL)
158435689395SXin LI 			return;
158535689395SXin LI 
158635689395SXin LI 		acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ);
158735689395SXin LI 		pwbuffer = arcmsr_get_iop_wqbuffer(acb);
158835689395SXin LI 		iop_data = (u_int32_t *)pwbuffer->data;
158935689395SXin LI 		while((acb->wqbuf_firstindex != acb->wqbuf_lastindex)
159035689395SXin LI 			&& (allxfer_len < 124)) {
159135689395SXin LI 			pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex];
159235689395SXin LI 			*buf1 = *pQbuffer;
159335689395SXin LI 			acb->wqbuf_firstindex++;
159435689395SXin LI 			acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
159535689395SXin LI 			buf1++;
159635689395SXin LI 			allxfer_len++;
159735689395SXin LI 		}
159835689395SXin LI 		pwbuffer->data_len = allxfer_len;
159935689395SXin LI 		data_len = allxfer_len;
160035689395SXin LI 		buf1 = (u_int8_t *)buf2;
160135689395SXin LI 		while(data_len >= 4)
160235689395SXin LI 		{
160335689395SXin LI 			*iop_data++ = *buf2++;
160435689395SXin LI 			data_len -= 4;
160535689395SXin LI 		}
160635689395SXin LI 		if(data_len)
160735689395SXin LI 			*iop_data = *buf2;
160835689395SXin LI 		free( buf1, M_DEVBUF);
160935689395SXin LI 		arcmsr_iop_message_wrote(acb);
161035689395SXin LI 	}
161135689395SXin LI }
161235689395SXin LI /*
161335689395SXin LI **********************************************************************
161435689395SXin LI **********************************************************************
161535689395SXin LI */
16167a7bc959SXin LI static void arcmsr_Write_data_2iop_wqbuffer(struct AdapterControlBlock *acb)
16177a7bc959SXin LI {
16187a7bc959SXin LI 	u_int8_t *pQbuffer;
16197a7bc959SXin LI 	struct QBUFFER *pwbuffer;
16207a7bc959SXin LI 	u_int8_t *iop_data;
16217a7bc959SXin LI 	int32_t allxfer_len=0;
16227a7bc959SXin LI 
1623fc5ef1caSXin LI 	if(acb->adapter_type >= ACB_ADAPTER_TYPE_B) {
162435689395SXin LI 		arcmsr_Write_data_2iop_wqbuffer_D(acb);
162535689395SXin LI 		return;
162635689395SXin LI 	}
16277a7bc959SXin LI 	if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READ) {
16287a7bc959SXin LI 		acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READ);
16297a7bc959SXin LI 		pwbuffer = arcmsr_get_iop_wqbuffer(acb);
16307a7bc959SXin LI 		iop_data = (u_int8_t *)pwbuffer->data;
16317a7bc959SXin LI 		while((acb->wqbuf_firstindex != acb->wqbuf_lastindex)
16327a7bc959SXin LI 			&& (allxfer_len < 124)) {
16337a7bc959SXin LI 			pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex];
16347a7bc959SXin LI 			*iop_data = *pQbuffer;
16357a7bc959SXin LI 			acb->wqbuf_firstindex++;
16367a7bc959SXin LI 			acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
16377a7bc959SXin LI 			iop_data++;
16387a7bc959SXin LI 			allxfer_len++;
16397a7bc959SXin LI 		}
16407a7bc959SXin LI 		pwbuffer->data_len = allxfer_len;
16417a7bc959SXin LI 		arcmsr_iop_message_wrote(acb);
16427a7bc959SXin LI 	}
1643f1c579b1SScott Long }
1644f1c579b1SScott Long /*
164544f05562SScott Long **************************************************************************
164644f05562SScott Long **************************************************************************
164744f05562SScott Long */
164844f05562SScott Long static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb)
164944f05562SScott Long {
16507a7bc959SXin LI 	ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
165144f05562SScott Long 	acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READ;
165244f05562SScott Long 	/*
165344f05562SScott Long 	*****************************************************************
165444f05562SScott Long 	**   check if there are any mail packages from user space program
165544f05562SScott Long 	**   in my post bag, now is the time to send them into Areca's firmware
165644f05562SScott Long 	*****************************************************************
1657f1c579b1SScott Long 	*/
1658ad6d6297SScott Long 	if(acb->wqbuf_firstindex != acb->wqbuf_lastindex) {
16597a7bc959SXin LI 		arcmsr_Write_data_2iop_wqbuffer(acb);
1660f1c579b1SScott Long 	}
1661ad6d6297SScott Long 	if(acb->wqbuf_firstindex == acb->wqbuf_lastindex) {
1662ad6d6297SScott Long 		acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED;
1663f1c579b1SScott Long 	}
16647a7bc959SXin LI 	ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
1665f1c579b1SScott Long }
16667a7bc959SXin LI /*
16677a7bc959SXin LI **************************************************************************
16687a7bc959SXin LI **************************************************************************
16697a7bc959SXin LI */
1670d74001adSXin LI static void arcmsr_rescanLun_cb(struct cam_periph *periph, union ccb *ccb)
1671d74001adSXin LI {
1672d74001adSXin LI /*
1673d74001adSXin LI 	if (ccb->ccb_h.status != CAM_REQ_CMP)
16747a7bc959SXin LI 		printf("arcmsr_rescanLun_cb: Rescan Target=%x, lun=%x,"
16757a7bc959SXin LI 			"failure status=%x\n", ccb->ccb_h.target_id,
16767a7bc959SXin LI 			ccb->ccb_h.target_lun, ccb->ccb_h.status);
1677d74001adSXin LI 	else
1678d74001adSXin LI 		printf("arcmsr_rescanLun_cb: Rescan lun successfully!\n");
1679d74001adSXin LI */
1680d74001adSXin LI 	xpt_free_path(ccb->ccb_h.path);
1681d74001adSXin LI 	xpt_free_ccb(ccb);
1682d74001adSXin LI }
1683d74001adSXin LI 
1684d74001adSXin LI static void	arcmsr_rescan_lun(struct AdapterControlBlock *acb, int target, int lun)
1685d74001adSXin LI {
1686d74001adSXin LI 	struct cam_path     *path;
1687d74001adSXin LI 	union ccb           *ccb;
1688d74001adSXin LI 
1689d74001adSXin LI 	if ((ccb = (union ccb *)xpt_alloc_ccb_nowait()) == NULL)
1690d74001adSXin LI 		return;
1691abfdbca9SXin LI 	if (xpt_create_path(&path, NULL, cam_sim_path(acb->psim), target, lun) != CAM_REQ_CMP)
1692d74001adSXin LI 	{
1693d74001adSXin LI 		xpt_free_ccb(ccb);
1694d74001adSXin LI 		return;
1695d74001adSXin LI 	}
1696d74001adSXin LI /*	printf("arcmsr_rescan_lun: Rescan Target=%x, Lun=%x\n", target, lun); */
1697d74001adSXin LI 	xpt_setup_ccb(&ccb->ccb_h, path, 5);
1698d74001adSXin LI 	ccb->ccb_h.func_code = XPT_SCAN_LUN;
1699d74001adSXin LI 	ccb->ccb_h.cbfcnp = arcmsr_rescanLun_cb;
1700d74001adSXin LI 	ccb->crcn.flags = CAM_FLAG_NONE;
1701d74001adSXin LI 	xpt_action(ccb);
1702d74001adSXin LI }
1703d74001adSXin LI 
1704d74001adSXin LI static void arcmsr_abort_dr_ccbs(struct AdapterControlBlock *acb, int target, int lun)
1705d74001adSXin LI {
1706d74001adSXin LI 	struct CommandControlBlock *srb;
1707d74001adSXin LI 	u_int32_t intmask_org;
1708d74001adSXin LI 	int i;
1709d74001adSXin LI 
1710d74001adSXin LI 	/* disable all outbound interrupts */
1711d74001adSXin LI 	intmask_org = arcmsr_disable_allintr(acb);
1712d74001adSXin LI 	for (i = 0; i < ARCMSR_MAX_FREESRB_NUM; i++)
1713d74001adSXin LI 	{
1714d74001adSXin LI 		srb = acb->psrb_pool[i];
171522f2616bSXin LI 		if (srb->srb_state == ARCMSR_SRB_START)
1716d74001adSXin LI 		{
1717d74001adSXin LI 			if((target == srb->pccb->ccb_h.target_id) && (lun == srb->pccb->ccb_h.target_lun))
1718d74001adSXin LI 			{
171922f2616bSXin LI 				srb->srb_state = ARCMSR_SRB_ABORTED;
1720d74001adSXin LI 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
1721d74001adSXin LI 				arcmsr_srb_complete(srb, 1);
172222f2616bSXin LI 				printf("arcmsr%d: abort scsi id %d lun %d srb=%p \n", acb->pci_unit, target, lun, srb);
1723d74001adSXin LI 			}
1724d74001adSXin LI 		}
1725d74001adSXin LI 	}
1726d74001adSXin LI 	/* enable outbound Post Queue, outbound doorbell Interrupt */
1727d74001adSXin LI 	arcmsr_enable_allintr(acb, intmask_org);
1728d74001adSXin LI }
1729d74001adSXin LI /*
1730d74001adSXin LI **************************************************************************
1731d74001adSXin LI **************************************************************************
1732d74001adSXin LI */
1733d74001adSXin LI static void arcmsr_dr_handle(struct AdapterControlBlock *acb) {
1734d74001adSXin LI 	u_int32_t	devicemap;
1735d74001adSXin LI 	u_int32_t	target, lun;
1736d74001adSXin LI 	u_int32_t	deviceMapCurrent[4]={0};
1737d74001adSXin LI 	u_int8_t	*pDevMap;
1738d74001adSXin LI 
1739d74001adSXin LI 	switch (acb->adapter_type) {
1740d74001adSXin LI 	case ACB_ADAPTER_TYPE_A:
1741d74001adSXin LI 		devicemap = offsetof(struct HBA_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
1742d74001adSXin LI 		for (target = 0; target < 4; target++)
1743d74001adSXin LI 		{
1744d74001adSXin LI 			deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0],  devicemap);
1745d74001adSXin LI 			devicemap += 4;
1746d74001adSXin LI 		}
1747d74001adSXin LI 		break;
1748d74001adSXin LI 
1749d74001adSXin LI 	case ACB_ADAPTER_TYPE_B:
1750d74001adSXin LI 		devicemap = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
1751d74001adSXin LI 		for (target = 0; target < 4; target++)
1752d74001adSXin LI 		{
1753d74001adSXin LI 			deviceMapCurrent[target]=bus_space_read_4(acb->btag[1], acb->bhandle[1],  devicemap);
1754d74001adSXin LI 			devicemap += 4;
1755d74001adSXin LI 		}
1756d74001adSXin LI 		break;
1757d74001adSXin LI 
1758d74001adSXin LI 	case ACB_ADAPTER_TYPE_C:
1759d74001adSXin LI 		devicemap = offsetof(struct HBC_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
1760d74001adSXin LI 		for (target = 0; target < 4; target++)
1761d74001adSXin LI 		{
1762d74001adSXin LI 			deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0],  devicemap);
1763d74001adSXin LI 			devicemap += 4;
1764d74001adSXin LI 		}
1765d74001adSXin LI 		break;
17667a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D:
17677a7bc959SXin LI 		devicemap = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
17687a7bc959SXin LI 		for (target = 0; target < 4; target++)
17697a7bc959SXin LI 		{
17707a7bc959SXin LI 			deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0],  devicemap);
17717a7bc959SXin LI 			devicemap += 4;
17727a7bc959SXin LI 		}
17737a7bc959SXin LI 		break;
1774a1103e04SXin LI 	case ACB_ADAPTER_TYPE_E:
1775a1103e04SXin LI 		devicemap = offsetof(struct HBE_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
1776a1103e04SXin LI 		for (target = 0; target < 4; target++)
1777a1103e04SXin LI 		{
1778a1103e04SXin LI 			deviceMapCurrent[target]=bus_space_read_4(acb->btag[0], acb->bhandle[0],  devicemap);
1779a1103e04SXin LI 			devicemap += 4;
1780a1103e04SXin LI 		}
1781a1103e04SXin LI 		break;
1782fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F:
1783fa42a0bfSXin LI 		devicemap = ARCMSR_FW_DEVMAP_OFFSET;
1784fa42a0bfSXin LI 		for (target = 0; target < 4; target++)
1785fa42a0bfSXin LI 		{
1786fa42a0bfSXin LI 			deviceMapCurrent[target] = acb->msgcode_rwbuffer[devicemap];
1787fa42a0bfSXin LI 			devicemap += 1;
1788fa42a0bfSXin LI 		}
1789fa42a0bfSXin LI 		break;
1790d74001adSXin LI 	}
1791dac36688SXin LI 
1792d74001adSXin LI 	if(acb->acb_flags & ACB_F_BUS_HANG_ON)
1793d74001adSXin LI 	{
1794d74001adSXin LI 		acb->acb_flags &= ~ACB_F_BUS_HANG_ON;
1795d74001adSXin LI 	}
1796d74001adSXin LI 	/*
1797d74001adSXin LI 	** adapter posted CONFIG message
1798d74001adSXin LI 	** copy the new map, note if there are differences with the current map
1799d74001adSXin LI 	*/
1800d74001adSXin LI 	pDevMap = (u_int8_t *)&deviceMapCurrent[0];
1801d74001adSXin LI 	for (target = 0; target < ARCMSR_MAX_TARGETID - 1; target++)
1802d74001adSXin LI 	{
1803d74001adSXin LI 		if (*pDevMap != acb->device_map[target])
1804d74001adSXin LI 		{
1805d74001adSXin LI 			u_int8_t difference, bit_check;
1806d74001adSXin LI 
1807d74001adSXin LI 			difference = *pDevMap ^ acb->device_map[target];
1808d74001adSXin LI 			for(lun=0; lun < ARCMSR_MAX_TARGETLUN; lun++)
1809d74001adSXin LI 			{
1810d74001adSXin LI 				bit_check = (1 << lun);		/*check bit from 0....31*/
1811d74001adSXin LI 				if(difference & bit_check)
1812d74001adSXin LI 				{
1813d74001adSXin LI 					if(acb->device_map[target] & bit_check)
1814d74001adSXin LI 					{/* unit departed */
1815d74001adSXin LI 						printf("arcmsr_dr_handle: Target=%x, lun=%x, GONE!!!\n",target,lun);
1816d74001adSXin LI 						arcmsr_abort_dr_ccbs(acb, target, lun);
1817d74001adSXin LI 						arcmsr_rescan_lun(acb, target, lun);
1818d74001adSXin LI 						acb->devstate[target][lun] = ARECA_RAID_GONE;
1819d74001adSXin LI 					}
1820d74001adSXin LI 					else
1821d74001adSXin LI 					{/* unit arrived */
182222f2616bSXin LI 						printf("arcmsr_dr_handle: Target=%x, lun=%x, Plug-IN!!!\n",target,lun);
1823d74001adSXin LI 						arcmsr_rescan_lun(acb, target, lun);
1824d74001adSXin LI 						acb->devstate[target][lun] = ARECA_RAID_GOOD;
1825d74001adSXin LI 					}
1826d74001adSXin LI 				}
1827d74001adSXin LI 			}
1828d74001adSXin LI /*			printf("arcmsr_dr_handle: acb->device_map[%x]=0x%x, deviceMapCurrent[%x]=%x\n",target,acb->device_map[target],target,*pDevMap); */
1829d74001adSXin LI 			acb->device_map[target] = *pDevMap;
1830d74001adSXin LI 		}
1831d74001adSXin LI 		pDevMap++;
1832d74001adSXin LI 	}
1833d74001adSXin LI }
1834d74001adSXin LI /*
1835d74001adSXin LI **************************************************************************
1836d74001adSXin LI **************************************************************************
1837d74001adSXin LI */
1838d74001adSXin LI static void arcmsr_hba_message_isr(struct AdapterControlBlock *acb) {
1839d74001adSXin LI 	u_int32_t outbound_message;
1840d74001adSXin LI 
1841d74001adSXin LI 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, ARCMSR_MU_OUTBOUND_MESSAGE0_INT);
1842d74001adSXin LI 	outbound_message = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[0]);
1843d74001adSXin LI 	if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
1844d74001adSXin LI 		arcmsr_dr_handle( acb );
1845d74001adSXin LI }
1846d74001adSXin LI /*
1847d74001adSXin LI **************************************************************************
1848d74001adSXin LI **************************************************************************
1849d74001adSXin LI */
1850d74001adSXin LI static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) {
1851d74001adSXin LI 	u_int32_t outbound_message;
1852b23a1998SXin LI 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
1853d74001adSXin LI 
1854d74001adSXin LI 	/* clear interrupts */
1855b23a1998SXin LI 	WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_MESSAGE_INT_CLEAR_PATTERN);
1856d74001adSXin LI 	outbound_message = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0]);
1857d74001adSXin LI 	if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
1858d74001adSXin LI 		arcmsr_dr_handle( acb );
1859d74001adSXin LI }
1860d74001adSXin LI /*
1861d74001adSXin LI **************************************************************************
1862d74001adSXin LI **************************************************************************
1863d74001adSXin LI */
1864d74001adSXin LI static void arcmsr_hbc_message_isr(struct AdapterControlBlock *acb) {
1865d74001adSXin LI 	u_int32_t outbound_message;
1866d74001adSXin LI 
1867d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE_DOORBELL_CLEAR);
1868d74001adSXin LI 	outbound_message = CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[0]);
1869d74001adSXin LI 	if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
1870d74001adSXin LI 		arcmsr_dr_handle( acb );
1871d74001adSXin LI }
187244f05562SScott Long /*
187344f05562SScott Long **************************************************************************
187444f05562SScott Long **************************************************************************
187544f05562SScott Long */
18767a7bc959SXin LI static void arcmsr_hbd_message_isr(struct AdapterControlBlock *acb) {
18777a7bc959SXin LI 	u_int32_t outbound_message;
18787a7bc959SXin LI 
18797a7bc959SXin LI 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR);
18807a7bc959SXin LI 	outbound_message = CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[0]);
18817a7bc959SXin LI 	if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
18827a7bc959SXin LI 		arcmsr_dr_handle( acb );
18837a7bc959SXin LI }
18847a7bc959SXin LI /*
18857a7bc959SXin LI **************************************************************************
18867a7bc959SXin LI **************************************************************************
18877a7bc959SXin LI */
1888a1103e04SXin LI static void arcmsr_hbe_message_isr(struct AdapterControlBlock *acb) {
1889a1103e04SXin LI 	u_int32_t outbound_message;
1890a1103e04SXin LI 
1891a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0);
18925842073aSXin LI 	if (acb->adapter_type == ACB_ADAPTER_TYPE_E)
1893a1103e04SXin LI 		outbound_message = CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[0]);
18945842073aSXin LI 	else
18955842073aSXin LI 		outbound_message = acb->msgcode_rwbuffer[0];
1896a1103e04SXin LI 	if (outbound_message == ARCMSR_SIGNATURE_GET_CONFIG)
1897a1103e04SXin LI 		arcmsr_dr_handle( acb );
1898a1103e04SXin LI }
1899a1103e04SXin LI /*
1900a1103e04SXin LI **************************************************************************
1901a1103e04SXin LI **************************************************************************
1902a1103e04SXin LI */
190344f05562SScott Long static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb)
190444f05562SScott Long {
1905224a78aeSXin LI 	u_int32_t doorbell_status;
190644f05562SScott Long 
190744f05562SScott Long 	/*
190844f05562SScott Long 	*******************************************************************
190944f05562SScott Long 	**  Maybe here we need to check wrqbuffer_lock is lock or not
191044f05562SScott Long 	**  DOORBELL: din! don!
191144f05562SScott Long 	**  check if there are any mail need to pack from firmware
191244f05562SScott Long 	*******************************************************************
191344f05562SScott Long 	*/
1914224a78aeSXin LI 	doorbell_status = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell);
1915224a78aeSXin LI 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */
1916224a78aeSXin LI 	if(doorbell_status & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) {
191744f05562SScott Long 		arcmsr_iop2drv_data_wrote_handle(acb);
1918ad6d6297SScott Long 	}
1919224a78aeSXin LI 	if(doorbell_status & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) {
192044f05562SScott Long 		arcmsr_iop2drv_data_read_handle(acb);
192144f05562SScott Long 	}
192244f05562SScott Long }
192344f05562SScott Long /*
192444f05562SScott Long **************************************************************************
192544f05562SScott Long **************************************************************************
192644f05562SScott Long */
1927d74001adSXin LI static void arcmsr_hbc_doorbell_isr(struct AdapterControlBlock *acb)
1928d74001adSXin LI {
1929224a78aeSXin LI 	u_int32_t doorbell_status;
1930d74001adSXin LI 
1931d74001adSXin LI 	/*
1932d74001adSXin LI 	*******************************************************************
1933d74001adSXin LI 	**  Maybe here we need to check wrqbuffer_lock is lock or not
1934d74001adSXin LI 	**  DOORBELL: din! don!
1935d74001adSXin LI 	**  check if there are any mail need to pack from firmware
1936d74001adSXin LI 	*******************************************************************
1937d74001adSXin LI 	*/
1938224a78aeSXin LI 	doorbell_status = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell);
1939224a78aeSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, doorbell_status); /* clear doorbell interrupt */
1940224a78aeSXin LI 	if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_DATA_WRITE_OK) {
1941d74001adSXin LI 		arcmsr_iop2drv_data_wrote_handle(acb);
1942d74001adSXin LI 	}
1943224a78aeSXin LI 	if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_DATA_READ_OK) {
1944d74001adSXin LI 		arcmsr_iop2drv_data_read_handle(acb);
1945d74001adSXin LI 	}
1946224a78aeSXin LI 	if(doorbell_status & ARCMSR_HBCMU_IOP2DRV_MESSAGE_CMD_DONE) {
1947d74001adSXin LI 		arcmsr_hbc_message_isr(acb);    /* messenger of "driver to iop commands" */
1948d74001adSXin LI 	}
1949d74001adSXin LI }
1950d74001adSXin LI /*
1951d74001adSXin LI **************************************************************************
1952d74001adSXin LI **************************************************************************
1953d74001adSXin LI */
19547a7bc959SXin LI static void arcmsr_hbd_doorbell_isr(struct AdapterControlBlock *acb)
19557a7bc959SXin LI {
1956224a78aeSXin LI 	u_int32_t doorbell_status;
19577a7bc959SXin LI 
19587a7bc959SXin LI 	/*
19597a7bc959SXin LI 	*******************************************************************
19607a7bc959SXin LI 	**  Maybe here we need to check wrqbuffer_lock is lock or not
19617a7bc959SXin LI 	**  DOORBELL: din! don!
19627a7bc959SXin LI 	**  check if there are any mail need to pack from firmware
19637a7bc959SXin LI 	*******************************************************************
19647a7bc959SXin LI 	*/
1965224a78aeSXin LI 	doorbell_status = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE;
1966224a78aeSXin LI 	if(doorbell_status)
1967224a78aeSXin LI 		CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */
1968224a78aeSXin LI 	while( doorbell_status & ARCMSR_HBDMU_F0_DOORBELL_CAUSE ) {
1969224a78aeSXin LI 		if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_DATA_WRITE_OK) {
19707a7bc959SXin LI 			arcmsr_iop2drv_data_wrote_handle(acb);
19717a7bc959SXin LI 		}
1972224a78aeSXin LI 		if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_DATA_READ_OK) {
19737a7bc959SXin LI 			arcmsr_iop2drv_data_read_handle(acb);
19747a7bc959SXin LI 		}
1975224a78aeSXin LI 		if(doorbell_status & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE) {
19767a7bc959SXin LI 			arcmsr_hbd_message_isr(acb);    /* messenger of "driver to iop commands" */
19777a7bc959SXin LI 		}
1978224a78aeSXin LI 		doorbell_status = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_F0_DOORBELL_CAUSE;
1979224a78aeSXin LI 		if(doorbell_status)
1980224a78aeSXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, doorbell_status); /* clear doorbell interrupt */
19817a7bc959SXin LI 	}
19827a7bc959SXin LI }
19837a7bc959SXin LI /*
19847a7bc959SXin LI **************************************************************************
19857a7bc959SXin LI **************************************************************************
19867a7bc959SXin LI */
1987a1103e04SXin LI static void arcmsr_hbe_doorbell_isr(struct AdapterControlBlock *acb)
1988a1103e04SXin LI {
1989a1103e04SXin LI 	u_int32_t doorbell_status, in_doorbell;
1990a1103e04SXin LI 
1991a1103e04SXin LI 	/*
1992a1103e04SXin LI 	*******************************************************************
1993a1103e04SXin LI 	**  Maybe here we need to check wrqbuffer_lock is lock or not
1994a1103e04SXin LI 	**  DOORBELL: din! don!
1995a1103e04SXin LI 	**  check if there are any mail need to pack from firmware
1996a1103e04SXin LI 	*******************************************************************
1997a1103e04SXin LI 	*/
1998a1103e04SXin LI 	in_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell);
1999a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /* clear doorbell interrupt */
2000a1103e04SXin LI 	doorbell_status = in_doorbell ^ acb->in_doorbell;
2001a1103e04SXin LI 	if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_WRITE_OK) {
2002a1103e04SXin LI 		arcmsr_iop2drv_data_wrote_handle(acb);
2003a1103e04SXin LI 	}
2004a1103e04SXin LI 	if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_READ_OK) {
2005a1103e04SXin LI 		arcmsr_iop2drv_data_read_handle(acb);
2006a1103e04SXin LI 	}
2007a1103e04SXin LI 	if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) {
2008a1103e04SXin LI 		arcmsr_hbe_message_isr(acb);    /* messenger of "driver to iop commands" */
2009a1103e04SXin LI 	}
2010a1103e04SXin LI 	acb->in_doorbell = in_doorbell;
2011a1103e04SXin LI }
2012a1103e04SXin LI /*
2013a1103e04SXin LI **************************************************************************
2014a1103e04SXin LI **************************************************************************
2015a1103e04SXin LI */
20166964b77eS黃清隆 static void arcmsr_hbf_doorbell_isr(struct AdapterControlBlock *acb)
20176964b77eS黃清隆 {
20186964b77eS黃清隆 	u_int32_t doorbell_status, in_doorbell;
20196964b77eS黃清隆 
20206964b77eS黃清隆 	/*
20216964b77eS黃清隆 	*******************************************************************
20226964b77eS黃清隆 	**  Maybe here we need to check wrqbuffer_lock is lock or not
20236964b77eS黃清隆 	**  DOORBELL: din! don!
20246964b77eS黃清隆 	**  check if there are any mail need to pack from firmware
20256964b77eS黃清隆 	*******************************************************************
20266964b77eS黃清隆 	*/
20276964b77eS黃清隆 	while(1) {
20286964b77eS黃清隆 		in_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell);
20296964b77eS黃清隆 		if ((in_doorbell != 0) && (in_doorbell != 0xFFFFFFFF))
20306964b77eS黃清隆 			break;
20316964b77eS黃清隆 	}
20326964b77eS黃清隆 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /* clear doorbell interrupt */
20336964b77eS黃清隆 	doorbell_status = in_doorbell ^ acb->in_doorbell;
20346964b77eS黃清隆 	if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_WRITE_OK) {
20356964b77eS黃清隆 		arcmsr_iop2drv_data_wrote_handle(acb);
20366964b77eS黃清隆 	}
20376964b77eS黃清隆 	if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_DATA_READ_OK) {
20386964b77eS黃清隆 		arcmsr_iop2drv_data_read_handle(acb);
20396964b77eS黃清隆 	}
20406964b77eS黃清隆 	if(doorbell_status & ARCMSR_HBEMU_IOP2DRV_MESSAGE_CMD_DONE) {
20416964b77eS黃清隆 		arcmsr_hbe_message_isr(acb);    /* messenger of "driver to iop commands" */
20426964b77eS黃清隆 	}
20436964b77eS黃清隆 	acb->in_doorbell = in_doorbell;
20446964b77eS黃清隆 }
20456964b77eS黃清隆 /*
20466964b77eS黃清隆 **************************************************************************
20476964b77eS黃清隆 **************************************************************************
20486964b77eS黃清隆 */
204944f05562SScott Long static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb)
205044f05562SScott Long {
205144f05562SScott Long 	u_int32_t flag_srb;
2052d74001adSXin LI 	u_int16_t error;
205344f05562SScott Long 
2054f1c579b1SScott Long 	/*
2055f1c579b1SScott Long 	*****************************************************************************
2056f1c579b1SScott Long 	**               areca cdb command done
2057f1c579b1SScott Long 	*****************************************************************************
2058f1c579b1SScott Long 	*/
205944f05562SScott Long 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap,
206044f05562SScott Long 		BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
206144f05562SScott Long 	while((flag_srb = CHIP_REG_READ32(HBA_MessageUnit,
206244f05562SScott Long 		0, outbound_queueport)) != 0xFFFFFFFF) {
2063f1c579b1SScott Long 		/* check if command done with no error*/
2064d74001adSXin LI 		error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0) ? TRUE : FALSE;
2065d74001adSXin LI 		arcmsr_drain_donequeue(acb, flag_srb, error);
206644f05562SScott Long 	}	/*drain reply FIFO*/
2067f1c579b1SScott Long }
206844f05562SScott Long /*
206944f05562SScott Long **************************************************************************
207044f05562SScott Long **************************************************************************
207144f05562SScott Long */
207244f05562SScott Long static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb)
207344f05562SScott Long {
207444f05562SScott Long 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
207544f05562SScott Long 	u_int32_t flag_srb;
207644f05562SScott Long 	int index;
2077d74001adSXin LI 	u_int16_t error;
207844f05562SScott Long 
207944f05562SScott Long 	/*
208044f05562SScott Long 	*****************************************************************************
208144f05562SScott Long 	**               areca cdb command done
208244f05562SScott Long 	*****************************************************************************
208344f05562SScott Long 	*/
208444f05562SScott Long 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap,
208544f05562SScott Long 		BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
208644f05562SScott Long 	index = phbbmu->doneq_index;
208744f05562SScott Long 	while((flag_srb = phbbmu->done_qbuffer[index]) != 0) {
208844f05562SScott Long 		phbbmu->done_qbuffer[index] = 0;
208944f05562SScott Long 		index++;
209044f05562SScott Long 		index %= ARCMSR_MAX_HBB_POSTQUEUE;     /*if last index number set it to 0 */
209144f05562SScott Long 		phbbmu->doneq_index = index;
209244f05562SScott Long 		/* check if command done with no error*/
2093d74001adSXin LI 		error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
2094d74001adSXin LI 		arcmsr_drain_donequeue(acb, flag_srb, error);
2095d74001adSXin LI 	}	/*drain reply FIFO*/
2096d74001adSXin LI }
2097d74001adSXin LI /*
2098d74001adSXin LI **************************************************************************
2099d74001adSXin LI **************************************************************************
2100d74001adSXin LI */
2101d74001adSXin LI static void arcmsr_hbc_postqueue_isr(struct AdapterControlBlock *acb)
2102d74001adSXin LI {
2103d74001adSXin LI 	u_int32_t flag_srb,throttling = 0;
2104d74001adSXin LI 	u_int16_t error;
2105d74001adSXin LI 
2106d74001adSXin LI 	/*
2107d74001adSXin LI 	*****************************************************************************
2108d74001adSXin LI 	**               areca cdb command done
2109d74001adSXin LI 	*****************************************************************************
2110d74001adSXin LI 	*/
2111d74001adSXin LI 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
2112224a78aeSXin LI 	do {
2113d74001adSXin LI 		flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low);
2114b23a1998SXin LI 		if (flag_srb == 0xFFFFFFFF)
2115b23a1998SXin LI 			break;
2116d74001adSXin LI 		/* check if command done with no error*/
2117d74001adSXin LI 		error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE;
2118d74001adSXin LI 		arcmsr_drain_donequeue(acb, flag_srb, error);
2119abfdbca9SXin LI 		throttling++;
2120d74001adSXin LI 		if(throttling == ARCMSR_HBC_ISR_THROTTLING_LEVEL) {
2121d74001adSXin LI 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_POSTQUEUE_THROTTLING);
2122abfdbca9SXin LI 			throttling = 0;
2123d74001adSXin LI 		}
2124224a78aeSXin LI 	} while(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR);
2125f1c579b1SScott Long }
212644f05562SScott Long /*
212744f05562SScott Long **********************************************************************
21287a7bc959SXin LI **
21297a7bc959SXin LI **********************************************************************
21307a7bc959SXin LI */
21317a7bc959SXin LI static uint16_t arcmsr_get_doneq_index(struct HBD_MessageUnit0 *phbdmu)
21327a7bc959SXin LI {
21337a7bc959SXin LI 	uint16_t doneq_index, index_stripped;
21347a7bc959SXin LI 
21357a7bc959SXin LI 	doneq_index = phbdmu->doneq_index;
21367a7bc959SXin LI 	if (doneq_index & 0x4000) {
21377a7bc959SXin LI 		index_stripped = doneq_index & 0xFF;
21387a7bc959SXin LI 		index_stripped += 1;
21397a7bc959SXin LI 		index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
21407a7bc959SXin LI 		phbdmu->doneq_index = index_stripped ?
21417a7bc959SXin LI 		    (index_stripped | 0x4000) : index_stripped;
21427a7bc959SXin LI 	} else {
21437a7bc959SXin LI 		index_stripped = doneq_index;
21447a7bc959SXin LI 		index_stripped += 1;
21457a7bc959SXin LI 		index_stripped %= ARCMSR_MAX_HBD_POSTQUEUE;
21467a7bc959SXin LI 		phbdmu->doneq_index = index_stripped ?
21477a7bc959SXin LI 		    index_stripped : (index_stripped | 0x4000);
21487a7bc959SXin LI 	}
21497a7bc959SXin LI 	return (phbdmu->doneq_index);
21507a7bc959SXin LI }
21517a7bc959SXin LI /*
21527a7bc959SXin LI **************************************************************************
21537a7bc959SXin LI **************************************************************************
21547a7bc959SXin LI */
21557a7bc959SXin LI static void arcmsr_hbd_postqueue_isr(struct AdapterControlBlock *acb)
21567a7bc959SXin LI {
21577a7bc959SXin LI 	struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
21587a7bc959SXin LI 	u_int32_t outbound_write_pointer;
21597a7bc959SXin LI 	u_int32_t addressLow;
21607a7bc959SXin LI 	uint16_t doneq_index;
21617a7bc959SXin LI 	u_int16_t error;
21627a7bc959SXin LI 	/*
21637a7bc959SXin LI 	*****************************************************************************
21647a7bc959SXin LI 	**               areca cdb command done
21657a7bc959SXin LI 	*****************************************************************************
21667a7bc959SXin LI 	*/
21677a7bc959SXin LI 	if((CHIP_REG_READ32(HBD_MessageUnit, 0, outboundlist_interrupt_cause) &
21687a7bc959SXin LI 		ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT) == 0)
21697a7bc959SXin LI 		return;
21707a7bc959SXin LI 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap,
21717a7bc959SXin LI 		BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
21727a7bc959SXin LI 	outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow;
21737a7bc959SXin LI 	doneq_index = phbdmu->doneq_index;
21747a7bc959SXin LI 	while ((doneq_index & 0xFF) != (outbound_write_pointer & 0xFF)) {
21757a7bc959SXin LI 		doneq_index = arcmsr_get_doneq_index(phbdmu);
21767a7bc959SXin LI 		addressLow = phbdmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow;
21777a7bc959SXin LI 		error = (addressLow & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
21787a7bc959SXin LI 		arcmsr_drain_donequeue(acb, addressLow, error); /*Check if command done with no error */
21797a7bc959SXin LI 		CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_read_pointer, doneq_index);
21807a7bc959SXin LI 		outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow;
21817a7bc959SXin LI 	}
21827a7bc959SXin LI 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_interrupt_cause, ARCMSR_HBDMU_OUTBOUND_LIST_INTERRUPT_CLEAR);
21837a7bc959SXin LI 	CHIP_REG_READ32(HBD_MessageUnit, 0, outboundlist_interrupt_cause); /*Dummy ioread32 to force pci flush */
21847a7bc959SXin LI }
21857a7bc959SXin LI /*
2186a1103e04SXin LI **************************************************************************
2187a1103e04SXin LI **************************************************************************
2188a1103e04SXin LI */
2189a1103e04SXin LI static void arcmsr_hbe_postqueue_isr(struct AdapterControlBlock *acb)
2190a1103e04SXin LI {
2191a1103e04SXin LI 	u_int16_t error;
2192a1103e04SXin LI 	uint32_t doneq_index;
2193a1103e04SXin LI 	uint16_t cmdSMID;
2194a1103e04SXin LI 
2195a1103e04SXin LI 	/*
2196a1103e04SXin LI 	*****************************************************************************
2197a1103e04SXin LI 	**               areca cdb command done
2198a1103e04SXin LI 	*****************************************************************************
2199a1103e04SXin LI 	*/
2200a1103e04SXin LI 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
2201a1103e04SXin LI 	doneq_index = acb->doneq_index;
2202a1103e04SXin LI 	while ((CHIP_REG_READ32(HBE_MessageUnit, 0, reply_post_producer_index) & 0xFFFF) != doneq_index) {
2203a1103e04SXin LI 		cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID;
2204a1103e04SXin LI 		error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
2205a1103e04SXin LI 		arcmsr_drain_donequeue(acb, (u_int32_t)cmdSMID, error);
2206a1103e04SXin LI 		doneq_index++;
2207a1103e04SXin LI 		if (doneq_index >= acb->completionQ_entry)
2208a1103e04SXin LI 			doneq_index = 0;
2209a1103e04SXin LI 	}
2210a1103e04SXin LI 	acb->doneq_index = doneq_index;
2211a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, reply_post_consumer_index, doneq_index);
2212a1103e04SXin LI }
2213fa42a0bfSXin LI 
2214fa42a0bfSXin LI static void arcmsr_hbf_postqueue_isr(struct AdapterControlBlock *acb)
2215fa42a0bfSXin LI {
2216fa42a0bfSXin LI 	uint16_t error;
2217fa42a0bfSXin LI 	uint32_t doneq_index;
2218fa42a0bfSXin LI 	uint16_t cmdSMID;
2219fa42a0bfSXin LI 
2220fa42a0bfSXin LI 	/*
2221fa42a0bfSXin LI 	*****************************************************************************
2222fa42a0bfSXin LI 	**               areca cdb command done
2223fa42a0bfSXin LI 	*****************************************************************************
2224fa42a0bfSXin LI 	*/
2225fa42a0bfSXin LI 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
2226fa42a0bfSXin LI 	doneq_index = acb->doneq_index;
2227fa42a0bfSXin LI 	while (1) {
2228fa42a0bfSXin LI 		cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID;
2229fa42a0bfSXin LI 		if (cmdSMID == 0xffff)
2230fa42a0bfSXin LI 			break;
2231fa42a0bfSXin LI 		error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
2232fa42a0bfSXin LI 		arcmsr_drain_donequeue(acb, (u_int32_t)cmdSMID, error);
2233fa42a0bfSXin LI 		acb->pCompletionQ[doneq_index].cmdSMID = 0xffff;
2234fa42a0bfSXin LI 		doneq_index++;
2235fa42a0bfSXin LI 		if (doneq_index >= acb->completionQ_entry)
2236fa42a0bfSXin LI 			doneq_index = 0;
2237fa42a0bfSXin LI 	}
2238fa42a0bfSXin LI 	acb->doneq_index = doneq_index;
2239fa42a0bfSXin LI 	CHIP_REG_WRITE32(HBF_MessageUnit, 0, reply_post_consumer_index, doneq_index);
2240fa42a0bfSXin LI }
2241fa42a0bfSXin LI 
2242a1103e04SXin LI /*
22437a7bc959SXin LI **********************************************************************
224444f05562SScott Long **********************************************************************
224544f05562SScott Long */
224644f05562SScott Long static void arcmsr_handle_hba_isr( struct AdapterControlBlock *acb)
224744f05562SScott Long {
2248dac36688SXin LI 	u_int32_t outbound_intStatus;
224944f05562SScott Long 	/*
225044f05562SScott Long 	*********************************************
225144f05562SScott Long 	**   check outbound intstatus
225244f05562SScott Long 	*********************************************
225344f05562SScott Long 	*/
2254dac36688SXin LI 	outbound_intStatus = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable;
2255dac36688SXin LI 	if(!outbound_intStatus) {
225644f05562SScott Long 		/*it must be share irq*/
225744f05562SScott Long 		return;
2258f1c579b1SScott Long 	}
2259dac36688SXin LI 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intStatus); /*clear interrupt*/
226044f05562SScott Long 	/* MU doorbell interrupts*/
2261dac36688SXin LI 	if(outbound_intStatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) {
226244f05562SScott Long 		arcmsr_hba_doorbell_isr(acb);
2263f1c579b1SScott Long 	}
226444f05562SScott Long 	/* MU post queue interrupts*/
2265dac36688SXin LI 	if(outbound_intStatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) {
226644f05562SScott Long 		arcmsr_hba_postqueue_isr(acb);
226744f05562SScott Long 	}
2268dac36688SXin LI 	if(outbound_intStatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) {
2269d74001adSXin LI 		arcmsr_hba_message_isr(acb);
2270d74001adSXin LI 	}
227144f05562SScott Long }
227244f05562SScott Long /*
227344f05562SScott Long **********************************************************************
227444f05562SScott Long **********************************************************************
227544f05562SScott Long */
227644f05562SScott Long static void arcmsr_handle_hbb_isr( struct AdapterControlBlock *acb)
227744f05562SScott Long {
227844f05562SScott Long 	u_int32_t outbound_doorbell;
2279b23a1998SXin LI 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
228044f05562SScott Long 	/*
228144f05562SScott Long 	*********************************************
228244f05562SScott Long 	**   check outbound intstatus
228344f05562SScott Long 	*********************************************
228444f05562SScott Long 	*/
2285b23a1998SXin LI 	outbound_doorbell = READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & acb->outbound_int_enable;
228644f05562SScott Long 	if(!outbound_doorbell) {
228744f05562SScott Long 		/*it must be share irq*/
228844f05562SScott Long 		return;
228944f05562SScott Long 	}
2290b23a1998SXin LI 	WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ~outbound_doorbell); /* clear doorbell interrupt */
2291b23a1998SXin LI 	READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell);
2292b23a1998SXin LI 	WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
229344f05562SScott Long 	/* MU ioctl transfer doorbell interrupts*/
229444f05562SScott Long 	if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) {
229544f05562SScott Long 		arcmsr_iop2drv_data_wrote_handle(acb);
229644f05562SScott Long 	}
229744f05562SScott Long 	if(outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) {
229844f05562SScott Long 		arcmsr_iop2drv_data_read_handle(acb);
229944f05562SScott Long 	}
230044f05562SScott Long 	/* MU post queue interrupts*/
230144f05562SScott Long 	if(outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) {
230244f05562SScott Long 		arcmsr_hbb_postqueue_isr(acb);
230344f05562SScott Long 	}
2304d74001adSXin LI 	if(outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) {
2305d74001adSXin LI 		arcmsr_hbb_message_isr(acb);
2306d74001adSXin LI 	}
2307d74001adSXin LI }
2308d74001adSXin LI /*
2309d74001adSXin LI **********************************************************************
2310d74001adSXin LI **********************************************************************
2311d74001adSXin LI */
2312d74001adSXin LI static void arcmsr_handle_hbc_isr( struct AdapterControlBlock *acb)
2313d74001adSXin LI {
2314d74001adSXin LI 	u_int32_t host_interrupt_status;
2315d74001adSXin LI 	/*
2316d74001adSXin LI 	*********************************************
2317d74001adSXin LI 	**   check outbound intstatus
2318d74001adSXin LI 	*********************************************
2319d74001adSXin LI 	*/
2320224a78aeSXin LI 	host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) &
2321224a78aeSXin LI 		(ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR |
2322224a78aeSXin LI 		ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR);
2323d74001adSXin LI 	if(!host_interrupt_status) {
2324d74001adSXin LI 		/*it must be share irq*/
2325d74001adSXin LI 		return;
2326d74001adSXin LI 	}
2327224a78aeSXin LI 	do {
2328d74001adSXin LI 		/* MU doorbell interrupts*/
2329d74001adSXin LI 		if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR) {
2330d74001adSXin LI 			arcmsr_hbc_doorbell_isr(acb);
2331d74001adSXin LI 		}
2332d74001adSXin LI 		/* MU post queue interrupts*/
2333d74001adSXin LI 		if(host_interrupt_status & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR) {
2334d74001adSXin LI 			arcmsr_hbc_postqueue_isr(acb);
2335d74001adSXin LI 		}
2336224a78aeSXin LI 		host_interrupt_status = CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status);
2337224a78aeSXin LI 	} while (host_interrupt_status & (ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBCMU_OUTBOUND_DOORBELL_ISR));
233844f05562SScott Long }
233944f05562SScott Long /*
23407a7bc959SXin LI **********************************************************************
23417a7bc959SXin LI **********************************************************************
23427a7bc959SXin LI */
23437a7bc959SXin LI static void arcmsr_handle_hbd_isr( struct AdapterControlBlock *acb)
23447a7bc959SXin LI {
23457a7bc959SXin LI 	u_int32_t host_interrupt_status;
23467a7bc959SXin LI 	u_int32_t intmask_org;
23477a7bc959SXin LI 	/*
23487a7bc959SXin LI 	*********************************************
23497a7bc959SXin LI 	**   check outbound intstatus
23507a7bc959SXin LI 	*********************************************
23517a7bc959SXin LI 	*/
23527a7bc959SXin LI 	host_interrupt_status = CHIP_REG_READ32(HBD_MessageUnit, 0, host_int_status) & acb->outbound_int_enable;
23537a7bc959SXin LI 	if(!(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_INT)) {
23547a7bc959SXin LI 		/*it must be share irq*/
23557a7bc959SXin LI 		return;
23567a7bc959SXin LI 	}
23577a7bc959SXin LI 	/* disable outbound interrupt */
23587a7bc959SXin LI 	intmask_org = CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable)	; /* disable outbound message0 int */
23597a7bc959SXin LI 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, ARCMSR_HBDMU_ALL_INT_DISABLE);
23607a7bc959SXin LI 	/* MU doorbell interrupts*/
23617a7bc959SXin LI 	if(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_DOORBELL_INT) {
23627a7bc959SXin LI 		arcmsr_hbd_doorbell_isr(acb);
23637a7bc959SXin LI 	}
23647a7bc959SXin LI 	/* MU post queue interrupts*/
23657a7bc959SXin LI 	if(host_interrupt_status & ARCMSR_HBDMU_OUTBOUND_POSTQUEUE_INT) {
23667a7bc959SXin LI 		arcmsr_hbd_postqueue_isr(acb);
23677a7bc959SXin LI 	}
23687a7bc959SXin LI 	/* enable all outbound interrupt */
23697a7bc959SXin LI 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, pcief0_int_enable, intmask_org | ARCMSR_HBDMU_ALL_INT_ENABLE);
23707a7bc959SXin LI //	CHIP_REG_READ32(HBD_MessageUnit, 0, pcief0_int_enable);
23717a7bc959SXin LI }
23727a7bc959SXin LI /*
2373a1103e04SXin LI **********************************************************************
2374a1103e04SXin LI **********************************************************************
2375a1103e04SXin LI */
2376a1103e04SXin LI static void arcmsr_handle_hbe_isr( struct AdapterControlBlock *acb)
2377a1103e04SXin LI {
2378a1103e04SXin LI 	u_int32_t host_interrupt_status;
2379a1103e04SXin LI 	/*
2380a1103e04SXin LI 	*********************************************
2381a1103e04SXin LI 	**   check outbound intstatus
2382a1103e04SXin LI 	*********************************************
2383a1103e04SXin LI 	*/
2384a1103e04SXin LI 	host_interrupt_status = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_status) &
2385a1103e04SXin LI 		(ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR |
2386a1103e04SXin LI 		ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR);
2387a1103e04SXin LI 	if(!host_interrupt_status) {
2388a1103e04SXin LI 		/*it must be share irq*/
2389a1103e04SXin LI 		return;
2390a1103e04SXin LI 	}
2391a1103e04SXin LI 	do {
2392a1103e04SXin LI 		/* MU doorbell interrupts*/
2393a1103e04SXin LI 		if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR) {
2394a1103e04SXin LI 			arcmsr_hbe_doorbell_isr(acb);
2395a1103e04SXin LI 		}
2396a1103e04SXin LI 		/* MU post queue interrupts*/
2397a1103e04SXin LI 		if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR) {
2398a1103e04SXin LI 			arcmsr_hbe_postqueue_isr(acb);
2399a1103e04SXin LI 		}
2400a1103e04SXin LI 		host_interrupt_status = CHIP_REG_READ32(HBE_MessageUnit, 0, host_int_status);
2401a1103e04SXin LI 	} while (host_interrupt_status & (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR));
2402a1103e04SXin LI }
2403fa42a0bfSXin LI 
2404fa42a0bfSXin LI static void arcmsr_handle_hbf_isr( struct AdapterControlBlock *acb)
2405fa42a0bfSXin LI {
2406fa42a0bfSXin LI 	u_int32_t host_interrupt_status;
2407fa42a0bfSXin LI 	/*
2408fa42a0bfSXin LI 	*********************************************
2409fa42a0bfSXin LI 	**   check outbound intstatus
2410fa42a0bfSXin LI 	*********************************************
2411fa42a0bfSXin LI 	*/
2412fa42a0bfSXin LI 	host_interrupt_status = CHIP_REG_READ32(HBF_MessageUnit, 0, host_int_status) &
2413fa42a0bfSXin LI 		(ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR |
2414fa42a0bfSXin LI 		ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR);
2415fa42a0bfSXin LI 	if(!host_interrupt_status) {
2416fa42a0bfSXin LI 		/*it must be share irq*/
2417fa42a0bfSXin LI 		return;
2418fa42a0bfSXin LI 	}
2419fa42a0bfSXin LI 	do {
2420fa42a0bfSXin LI 		/* MU doorbell interrupts*/
2421fa42a0bfSXin LI 		if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR) {
24226964b77eS黃清隆 			arcmsr_hbf_doorbell_isr(acb);
2423fa42a0bfSXin LI 		}
2424fa42a0bfSXin LI 		/* MU post queue interrupts*/
2425fa42a0bfSXin LI 		if(host_interrupt_status & ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR) {
2426fa42a0bfSXin LI 			arcmsr_hbf_postqueue_isr(acb);
2427fa42a0bfSXin LI 		}
2428fa42a0bfSXin LI 		host_interrupt_status = CHIP_REG_READ32(HBF_MessageUnit, 0, host_int_status);
2429fa42a0bfSXin LI 	} while (host_interrupt_status & (ARCMSR_HBEMU_OUTBOUND_POSTQUEUE_ISR | ARCMSR_HBEMU_OUTBOUND_DOORBELL_ISR));
2430fa42a0bfSXin LI }
2431a1103e04SXin LI /*
243244f05562SScott Long ******************************************************************************
243344f05562SScott Long ******************************************************************************
243444f05562SScott Long */
243544f05562SScott Long static void arcmsr_interrupt(struct AdapterControlBlock *acb)
243644f05562SScott Long {
243744f05562SScott Long 	switch (acb->adapter_type) {
243844f05562SScott Long 	case ACB_ADAPTER_TYPE_A:
243944f05562SScott Long 		arcmsr_handle_hba_isr(acb);
2440f1c579b1SScott Long 		break;
244144f05562SScott Long 	case ACB_ADAPTER_TYPE_B:
244244f05562SScott Long 		arcmsr_handle_hbb_isr(acb);
2443f1c579b1SScott Long 		break;
2444d74001adSXin LI 	case ACB_ADAPTER_TYPE_C:
2445d74001adSXin LI 		arcmsr_handle_hbc_isr(acb);
2446d74001adSXin LI 		break;
24477a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D:
24487a7bc959SXin LI 		arcmsr_handle_hbd_isr(acb);
24497a7bc959SXin LI 		break;
2450a1103e04SXin LI 	case ACB_ADAPTER_TYPE_E:
2451a1103e04SXin LI 		arcmsr_handle_hbe_isr(acb);
2452a1103e04SXin LI 		break;
2453fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F:
2454fa42a0bfSXin LI 		arcmsr_handle_hbf_isr(acb);
2455fa42a0bfSXin LI 		break;
2456f1c579b1SScott Long 	default:
245744f05562SScott Long 		printf("arcmsr%d: interrupt service,"
245810d66948SKevin Lo 		" unknown adapter type =%d\n", acb->pci_unit, acb->adapter_type);
2459f1c579b1SScott Long 		break;
2460f1c579b1SScott Long 	}
2461f1c579b1SScott Long }
2462f1c579b1SScott Long /*
2463d74001adSXin LI **********************************************************************
2464d74001adSXin LI **********************************************************************
2465d74001adSXin LI */
2466d74001adSXin LI static void arcmsr_intr_handler(void *arg)
2467d74001adSXin LI {
2468d74001adSXin LI 	struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg;
2469d74001adSXin LI 
24707a7bc959SXin LI 	ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
2471d74001adSXin LI 	arcmsr_interrupt(acb);
24727a7bc959SXin LI 	ARCMSR_LOCK_RELEASE(&acb->isr_lock);
2473d74001adSXin LI }
2474d74001adSXin LI /*
2475d74001adSXin LI ******************************************************************************
2476d74001adSXin LI ******************************************************************************
2477d74001adSXin LI */
2478d74001adSXin LI static void	arcmsr_polling_devmap(void *arg)
2479d74001adSXin LI {
2480d74001adSXin LI 	struct AdapterControlBlock *acb = (struct AdapterControlBlock *)arg;
2481d74001adSXin LI 	switch (acb->adapter_type) {
2482d74001adSXin LI 	case ACB_ADAPTER_TYPE_A:
2483dac36688SXin LI 		CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
2484d74001adSXin LI 		break;
2485d74001adSXin LI 
2486b23a1998SXin LI 	case ACB_ADAPTER_TYPE_B: {
2487b23a1998SXin LI 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
2488b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG);
2489b23a1998SXin LI 		}
2490d74001adSXin LI 		break;
2491d74001adSXin LI 
2492d74001adSXin LI 	case ACB_ADAPTER_TYPE_C:
2493d74001adSXin LI 		CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
2494d74001adSXin LI 		CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
2495d74001adSXin LI 		break;
24967a7bc959SXin LI 
24977a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D:
24987a7bc959SXin LI 		CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
24997a7bc959SXin LI 		break;
2500a1103e04SXin LI 
2501a1103e04SXin LI 	case ACB_ADAPTER_TYPE_E:
2502a1103e04SXin LI 		CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
2503a1103e04SXin LI 		acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
2504a1103e04SXin LI 		CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
2505a1103e04SXin LI 		break;
2506d74001adSXin LI 
2507fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
2508fa42a0bfSXin LI 		u_int32_t outMsg1 = CHIP_REG_READ32(HBF_MessageUnit, 0, outbound_msgaddr1);
2509fa42a0bfSXin LI 		if (!(outMsg1 & ARCMSR_HBFMU_MESSAGE_FIRMWARE_OK) ||
2510fa42a0bfSXin LI 			(outMsg1 & ARCMSR_HBFMU_MESSAGE_NO_VOLUME_CHANGE))
2511fa42a0bfSXin LI 			goto nxt6s;
2512fa42a0bfSXin LI 		CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
2513fa42a0bfSXin LI 		acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
2514fa42a0bfSXin LI 		CHIP_REG_WRITE32(HBF_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
2515fa42a0bfSXin LI 		break;
2516fa42a0bfSXin LI 		}
2517fa42a0bfSXin LI 	}
2518fa42a0bfSXin LI nxt6s:
2519d74001adSXin LI 	if((acb->acb_flags & ACB_F_SCSISTOPADAPTER) == 0)
2520d74001adSXin LI 	{
2521d74001adSXin LI 		callout_reset(&acb->devmap_callout, 5 * hz, arcmsr_polling_devmap, acb);	/* polling per 5 seconds */
2522d74001adSXin LI 	}
2523d74001adSXin LI }
2524d74001adSXin LI 
2525d74001adSXin LI /*
2526ad6d6297SScott Long *******************************************************************************
2527ad6d6297SScott Long **
2528ad6d6297SScott Long *******************************************************************************
2529ad6d6297SScott Long */
2530ad6d6297SScott Long static void arcmsr_iop_parking(struct AdapterControlBlock *acb)
2531ad6d6297SScott Long {
2532d74001adSXin LI 	u_int32_t intmask_org;
2533d74001adSXin LI 
2534ad6d6297SScott Long 	if(acb != NULL) {
2535ad6d6297SScott Long 		/* stop adapter background rebuild */
2536ad6d6297SScott Long 		if(acb->acb_flags & ACB_F_MSG_START_BGRB) {
2537d74001adSXin LI 			intmask_org = arcmsr_disable_allintr(acb);
2538ad6d6297SScott Long 			arcmsr_stop_adapter_bgrb(acb);
2539ad6d6297SScott Long 			arcmsr_flush_adapter_cache(acb);
2540d74001adSXin LI 			arcmsr_enable_allintr(acb, intmask_org);
2541ad6d6297SScott Long 		}
2542ad6d6297SScott Long 	}
2543ad6d6297SScott Long }
2544ad6d6297SScott Long /*
2545f1c579b1SScott Long ***********************************************************************
2546f1c579b1SScott Long **
2547f1c579b1SScott Long ************************************************************************
2548f1c579b1SScott Long */
2549fc5ef1caSXin LI static u_int32_t arcmsr_iop_ioctlcmd(struct AdapterControlBlock *acb, u_int32_t ioctl_cmd, caddr_t arg)
2550f1c579b1SScott Long {
2551ad6d6297SScott Long 	struct CMD_MESSAGE_FIELD *pcmdmessagefld;
2552ad6d6297SScott Long 	u_int32_t retvalue = EINVAL;
2553f1c579b1SScott Long 
2554ad6d6297SScott Long 	pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) arg;
2555ad6d6297SScott Long 	if(memcmp(pcmdmessagefld->cmdmessage.Signature, "ARCMSR", 6)!=0) {
2556ad6d6297SScott Long 		return retvalue;
2557f1c579b1SScott Long 	}
2558ad6d6297SScott Long 	ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
2559ad6d6297SScott Long 	switch(ioctl_cmd) {
2560ad6d6297SScott Long 	case ARCMSR_MESSAGE_READ_RQBUFFER: {
2561ad6d6297SScott Long 			u_int8_t *pQbuffer;
2562ad6d6297SScott Long 			u_int8_t *ptmpQbuffer = pcmdmessagefld->messagedatabuffer;
2563ad6d6297SScott Long 			u_int32_t allxfer_len=0;
2564f1c579b1SScott Long 
256544f05562SScott Long 			while((acb->rqbuf_firstindex != acb->rqbuf_lastindex)
256644f05562SScott Long 				&& (allxfer_len < 1031)) {
2567f1c579b1SScott Long 				/*copy READ QBUFFER to srb*/
2568ad6d6297SScott Long 				pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex];
25697a7bc959SXin LI 				*ptmpQbuffer = *pQbuffer;
2570ad6d6297SScott Long 				acb->rqbuf_firstindex++;
2571ad6d6297SScott Long 				acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
2572ad6d6297SScott Long 				/*if last index number set it to 0 */
2573f1c579b1SScott Long 				ptmpQbuffer++;
2574f1c579b1SScott Long 				allxfer_len++;
2575f1c579b1SScott Long 			}
2576ad6d6297SScott Long 			if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
257744f05562SScott Long 				struct QBUFFER *prbuffer;
2578f1c579b1SScott Long 
2579ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
258044f05562SScott Long 				prbuffer = arcmsr_get_iop_rqbuffer(acb);
258135689395SXin LI 				if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
258235689395SXin LI 					acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
2583f1c579b1SScott Long 			}
2584ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.Length = allxfer_len;
2585ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
2586ad6d6297SScott Long 			retvalue = ARCMSR_MESSAGE_SUCCESS;
2587f1c579b1SScott Long 		}
2588f1c579b1SScott Long 		break;
2589ad6d6297SScott Long 	case ARCMSR_MESSAGE_WRITE_WQBUFFER: {
2590ad6d6297SScott Long 			u_int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
2591ad6d6297SScott Long 			u_int8_t *pQbuffer;
2592ad6d6297SScott Long 			u_int8_t *ptmpuserbuffer = pcmdmessagefld->messagedatabuffer;
2593f1c579b1SScott Long 
2594ad6d6297SScott Long 			user_len = pcmdmessagefld->cmdmessage.Length;
2595f1c579b1SScott Long 			/*check if data xfer length of this request will overflow my array qbuffer */
2596ad6d6297SScott Long 			wqbuf_lastindex = acb->wqbuf_lastindex;
2597ad6d6297SScott Long 			wqbuf_firstindex = acb->wqbuf_firstindex;
2598ad6d6297SScott Long 			if(wqbuf_lastindex != wqbuf_firstindex) {
25997a7bc959SXin LI 				arcmsr_Write_data_2iop_wqbuffer(acb);
2600ad6d6297SScott Long 				pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR;
2601ad6d6297SScott Long 			} else {
26027a7bc959SXin LI 				my_empty_len = (wqbuf_firstindex - wqbuf_lastindex - 1) &
26037a7bc959SXin LI 					(ARCMSR_MAX_QBUFFER - 1);
2604ad6d6297SScott Long 				if(my_empty_len >= user_len) {
2605ad6d6297SScott Long 					while(user_len > 0) {
2606f1c579b1SScott Long 						/*copy srb data to wqbuffer*/
2607ad6d6297SScott Long 						pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex];
26087a7bc959SXin LI 						*pQbuffer = *ptmpuserbuffer;
2609ad6d6297SScott Long 						acb->wqbuf_lastindex++;
2610ad6d6297SScott Long 						acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
2611ad6d6297SScott Long 						/*if last index number set it to 0 */
2612f1c579b1SScott Long 						ptmpuserbuffer++;
2613f1c579b1SScott Long 						user_len--;
2614f1c579b1SScott Long 					}
2615f1c579b1SScott Long 					/*post fist Qbuffer*/
2616ad6d6297SScott Long 					if(acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) {
2617ad6d6297SScott Long 						acb->acb_flags &= ~ACB_F_MESSAGE_WQBUFFER_CLEARED;
26187a7bc959SXin LI 						arcmsr_Write_data_2iop_wqbuffer(acb);
2619f1c579b1SScott Long 					}
2620ad6d6297SScott Long 					pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
2621ad6d6297SScott Long 				} else {
2622ad6d6297SScott Long 					pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR;
2623f1c579b1SScott Long 				}
2624f1c579b1SScott Long 			}
2625ad6d6297SScott Long 			retvalue = ARCMSR_MESSAGE_SUCCESS;
2626f1c579b1SScott Long 		}
2627f1c579b1SScott Long 		break;
2628ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_RQBUFFER: {
2629ad6d6297SScott Long 			u_int8_t *pQbuffer = acb->rqbuffer;
2630ad6d6297SScott Long 
2631ad6d6297SScott Long 			if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
2632ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
263344f05562SScott Long 				arcmsr_iop_message_read(acb);
263444f05562SScott Long 				/*signature, let IOP know data has been readed */
2635f1c579b1SScott Long 			}
2636ad6d6297SScott Long 			acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED;
2637ad6d6297SScott Long 			acb->rqbuf_firstindex = 0;
2638ad6d6297SScott Long 			acb->rqbuf_lastindex = 0;
2639f1c579b1SScott Long 			memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
2640ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
2641ad6d6297SScott Long 			retvalue = ARCMSR_MESSAGE_SUCCESS;
2642f1c579b1SScott Long 		}
2643f1c579b1SScott Long 		break;
2644ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_WQBUFFER:
2645f1c579b1SScott Long 		{
2646ad6d6297SScott Long 			u_int8_t *pQbuffer = acb->wqbuffer;
2647f1c579b1SScott Long 
2648ad6d6297SScott Long 			if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
2649ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
265044f05562SScott Long 				arcmsr_iop_message_read(acb);
265144f05562SScott Long 				/*signature, let IOP know data has been readed */
2652f1c579b1SScott Long 			}
265344f05562SScott Long 			acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ);
2654ad6d6297SScott Long 			acb->wqbuf_firstindex = 0;
2655ad6d6297SScott Long 			acb->wqbuf_lastindex = 0;
2656f1c579b1SScott Long 			memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
2657ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
2658ad6d6297SScott Long 			retvalue = ARCMSR_MESSAGE_SUCCESS;
2659f1c579b1SScott Long 		}
2660f1c579b1SScott Long 		break;
2661ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: {
2662ad6d6297SScott Long 			u_int8_t *pQbuffer;
2663f1c579b1SScott Long 
2664ad6d6297SScott Long 			if(acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
2665ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
266644f05562SScott Long 				arcmsr_iop_message_read(acb);
266744f05562SScott Long 				/*signature, let IOP know data has been readed */
2668f1c579b1SScott Long 			}
2669ad6d6297SScott Long 			acb->acb_flags  |= (ACB_F_MESSAGE_WQBUFFER_CLEARED
2670ad6d6297SScott Long 					|ACB_F_MESSAGE_RQBUFFER_CLEARED
267144f05562SScott Long 					|ACB_F_MESSAGE_WQBUFFER_READ);
2672ad6d6297SScott Long 			acb->rqbuf_firstindex = 0;
2673ad6d6297SScott Long 			acb->rqbuf_lastindex = 0;
2674ad6d6297SScott Long 			acb->wqbuf_firstindex = 0;
2675ad6d6297SScott Long 			acb->wqbuf_lastindex = 0;
2676ad6d6297SScott Long 			pQbuffer = acb->rqbuffer;
2677ad6d6297SScott Long 			memset(pQbuffer, 0, sizeof(struct QBUFFER));
2678ad6d6297SScott Long 			pQbuffer = acb->wqbuffer;
2679ad6d6297SScott Long 			memset(pQbuffer, 0, sizeof(struct QBUFFER));
2680ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
2681ad6d6297SScott Long 			retvalue = ARCMSR_MESSAGE_SUCCESS;
2682f1c579b1SScott Long 		}
2683f1c579b1SScott Long 		break;
2684ad6d6297SScott Long 	case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: {
2685ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F;
2686ad6d6297SScott Long 			retvalue = ARCMSR_MESSAGE_SUCCESS;
2687f1c579b1SScott Long 		}
2688f1c579b1SScott Long 		break;
2689ad6d6297SScott Long 	case ARCMSR_MESSAGE_SAY_HELLO: {
2690ad6d6297SScott Long 			u_int8_t *hello_string = "Hello! I am ARCMSR";
2691ad6d6297SScott Long 			u_int8_t *puserbuffer = (u_int8_t *)pcmdmessagefld->messagedatabuffer;
2692f1c579b1SScott Long 
2693ad6d6297SScott Long 			if(memcpy(puserbuffer, hello_string, (int16_t)strlen(hello_string))) {
2694ad6d6297SScott Long 				pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_ERROR;
2695ad6d6297SScott Long 				ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
2696f1c579b1SScott Long 				return ENOIOCTL;
2697f1c579b1SScott Long 			}
2698ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
2699ad6d6297SScott Long 			retvalue = ARCMSR_MESSAGE_SUCCESS;
2700ad6d6297SScott Long 		}
2701ad6d6297SScott Long 		break;
2702ad6d6297SScott Long 	case ARCMSR_MESSAGE_SAY_GOODBYE: {
2703ad6d6297SScott Long 			arcmsr_iop_parking(acb);
2704ad6d6297SScott Long 			retvalue = ARCMSR_MESSAGE_SUCCESS;
2705ad6d6297SScott Long 		}
2706ad6d6297SScott Long 		break;
2707ad6d6297SScott Long 	case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: {
2708ad6d6297SScott Long 			arcmsr_flush_adapter_cache(acb);
2709ad6d6297SScott Long 			retvalue = ARCMSR_MESSAGE_SUCCESS;
2710f1c579b1SScott Long 		}
2711f1c579b1SScott Long 		break;
2712f1c579b1SScott Long 	}
2713ad6d6297SScott Long 	ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
2714dac36688SXin LI 	return (retvalue);
2715f1c579b1SScott Long }
2716f1c579b1SScott Long /*
2717f1c579b1SScott Long **************************************************************************
2718f1c579b1SScott Long **************************************************************************
2719f1c579b1SScott Long */
272022f2616bSXin LI static void arcmsr_free_srb(struct CommandControlBlock *srb)
272122f2616bSXin LI {
272222f2616bSXin LI 	struct AdapterControlBlock	*acb;
272322f2616bSXin LI 
272422f2616bSXin LI 	acb = srb->acb;
27257a7bc959SXin LI 	ARCMSR_LOCK_ACQUIRE(&acb->srb_lock);
272622f2616bSXin LI 	srb->srb_state = ARCMSR_SRB_DONE;
272722f2616bSXin LI 	srb->srb_flags = 0;
272822f2616bSXin LI 	acb->srbworkingQ[acb->workingsrb_doneindex] = srb;
272922f2616bSXin LI 	acb->workingsrb_doneindex++;
273022f2616bSXin LI 	acb->workingsrb_doneindex %= ARCMSR_MAX_FREESRB_NUM;
27317a7bc959SXin LI 	ARCMSR_LOCK_RELEASE(&acb->srb_lock);
273222f2616bSXin LI }
273322f2616bSXin LI /*
273422f2616bSXin LI **************************************************************************
273522f2616bSXin LI **************************************************************************
273622f2616bSXin LI */
2737fc5ef1caSXin LI static struct CommandControlBlock *arcmsr_get_freesrb(struct AdapterControlBlock *acb)
2738f1c579b1SScott Long {
2739ad6d6297SScott Long 	struct CommandControlBlock *srb = NULL;
2740ad6d6297SScott Long 	u_int32_t workingsrb_startindex, workingsrb_doneindex;
2741f1c579b1SScott Long 
27427a7bc959SXin LI 	ARCMSR_LOCK_ACQUIRE(&acb->srb_lock);
2743ad6d6297SScott Long 	workingsrb_doneindex = acb->workingsrb_doneindex;
2744ad6d6297SScott Long 	workingsrb_startindex = acb->workingsrb_startindex;
2745ad6d6297SScott Long 	srb = acb->srbworkingQ[workingsrb_startindex];
2746ad6d6297SScott Long 	workingsrb_startindex++;
2747ad6d6297SScott Long 	workingsrb_startindex %= ARCMSR_MAX_FREESRB_NUM;
2748ad6d6297SScott Long 	if(workingsrb_doneindex != workingsrb_startindex) {
2749ad6d6297SScott Long 		acb->workingsrb_startindex = workingsrb_startindex;
2750ad6d6297SScott Long 	} else {
2751ad6d6297SScott Long 		srb = NULL;
2752ad6d6297SScott Long 	}
27537a7bc959SXin LI 	ARCMSR_LOCK_RELEASE(&acb->srb_lock);
2754ad6d6297SScott Long 	return(srb);
2755ad6d6297SScott Long }
2756ad6d6297SScott Long /*
2757ad6d6297SScott Long **************************************************************************
2758ad6d6297SScott Long **************************************************************************
2759ad6d6297SScott Long */
2760ad6d6297SScott Long static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, union ccb *pccb)
2761ad6d6297SScott Long {
2762ad6d6297SScott Long 	struct CMD_MESSAGE_FIELD *pcmdmessagefld;
2763ad6d6297SScott Long 	int retvalue = 0, transfer_len = 0;
2764ad6d6297SScott Long 	char *buffer;
27654aa947cbSWarner Losh 	uint8_t *ptr = scsiio_cdb_ptr(&pccb->csio);
27664aa947cbSWarner Losh 	u_int32_t controlcode = (u_int32_t ) ptr[5] << 24 |
27674aa947cbSWarner Losh 				(u_int32_t ) ptr[6] << 16 |
27684aa947cbSWarner Losh 				(u_int32_t ) ptr[7] << 8  |
27694aa947cbSWarner Losh 				(u_int32_t ) ptr[8];
2770ad6d6297SScott Long 					/* 4 bytes: Areca io control code */
2771dd0b4fb6SKonstantin Belousov 	if ((pccb->ccb_h.flags & CAM_DATA_MASK) == CAM_DATA_VADDR) {
2772ad6d6297SScott Long 		buffer = pccb->csio.data_ptr;
2773ad6d6297SScott Long 		transfer_len = pccb->csio.dxfer_len;
2774ad6d6297SScott Long 	} else {
2775ad6d6297SScott Long 		retvalue = ARCMSR_MESSAGE_FAIL;
2776ad6d6297SScott Long 		goto message_out;
2777ad6d6297SScott Long 	}
2778ad6d6297SScott Long 	if (transfer_len > sizeof(struct CMD_MESSAGE_FIELD)) {
2779ad6d6297SScott Long 		retvalue = ARCMSR_MESSAGE_FAIL;
2780ad6d6297SScott Long 		goto message_out;
2781ad6d6297SScott Long 	}
2782ad6d6297SScott Long 	pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer;
2783ad6d6297SScott Long 	switch(controlcode) {
2784ad6d6297SScott Long 	case ARCMSR_MESSAGE_READ_RQBUFFER: {
2785ad6d6297SScott Long 			u_int8_t *pQbuffer;
2786ad6d6297SScott Long 			u_int8_t *ptmpQbuffer = pcmdmessagefld->messagedatabuffer;
2787ad6d6297SScott Long 			int32_t allxfer_len = 0;
2788f1c579b1SScott Long 
27897a7bc959SXin LI 			ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
2790ad6d6297SScott Long 			while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex)
2791ad6d6297SScott Long 				&& (allxfer_len < 1031)) {
2792ad6d6297SScott Long 				pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex];
27937a7bc959SXin LI 				*ptmpQbuffer = *pQbuffer;
2794ad6d6297SScott Long 				acb->rqbuf_firstindex++;
2795ad6d6297SScott Long 				acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER;
2796ad6d6297SScott Long 				ptmpQbuffer++;
2797ad6d6297SScott Long 				allxfer_len++;
2798f1c579b1SScott Long 			}
2799ad6d6297SScott Long 			if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
280044f05562SScott Long 				struct QBUFFER  *prbuffer;
2801ad6d6297SScott Long 
2802ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
280344f05562SScott Long 				prbuffer = arcmsr_get_iop_rqbuffer(acb);
280435689395SXin LI 				if(arcmsr_Read_iop_rqbuffer_data(acb, prbuffer) == 0)
280535689395SXin LI 					acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW;
2806ad6d6297SScott Long 			}
2807ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.Length = allxfer_len;
2808ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
2809ad6d6297SScott Long 			retvalue = ARCMSR_MESSAGE_SUCCESS;
28107a7bc959SXin LI 			ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
2811ad6d6297SScott Long 		}
2812ad6d6297SScott Long 		break;
2813ad6d6297SScott Long 	case ARCMSR_MESSAGE_WRITE_WQBUFFER: {
2814ad6d6297SScott Long 			int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex;
2815ad6d6297SScott Long 			u_int8_t *pQbuffer;
2816ad6d6297SScott Long 			u_int8_t *ptmpuserbuffer = pcmdmessagefld->messagedatabuffer;
2817ad6d6297SScott Long 
2818ad6d6297SScott Long 			user_len = pcmdmessagefld->cmdmessage.Length;
28197a7bc959SXin LI 			ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
2820ad6d6297SScott Long 			wqbuf_lastindex = acb->wqbuf_lastindex;
2821ad6d6297SScott Long 			wqbuf_firstindex = acb->wqbuf_firstindex;
2822ad6d6297SScott Long 			if (wqbuf_lastindex != wqbuf_firstindex) {
28237a7bc959SXin LI 				arcmsr_Write_data_2iop_wqbuffer(acb);
2824ad6d6297SScott Long 				/* has error report sensedata */
2825dac36688SXin LI 				if(pccb->csio.sense_len) {
2826ad6d6297SScott Long 				((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70);
2827ad6d6297SScott Long 				/* Valid,ErrorCode */
2828ad6d6297SScott Long 				((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05;
2829ad6d6297SScott Long 				/* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */
2830ad6d6297SScott Long 				((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A;
2831ad6d6297SScott Long 				/* AdditionalSenseLength */
2832ad6d6297SScott Long 				((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20;
2833ad6d6297SScott Long 				/* AdditionalSenseCode */
2834ad6d6297SScott Long 				}
2835ad6d6297SScott Long 				retvalue = ARCMSR_MESSAGE_FAIL;
2836ad6d6297SScott Long 			} else {
2837ad6d6297SScott Long 				my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1)
2838ad6d6297SScott Long 						&(ARCMSR_MAX_QBUFFER - 1);
2839ad6d6297SScott Long 				if (my_empty_len >= user_len) {
2840ad6d6297SScott Long 					while (user_len > 0) {
2841ad6d6297SScott Long 						pQbuffer = &acb->wqbuffer[acb->wqbuf_lastindex];
28427a7bc959SXin LI 						*pQbuffer = *ptmpuserbuffer;
2843ad6d6297SScott Long 						acb->wqbuf_lastindex++;
2844ad6d6297SScott Long 						acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER;
2845ad6d6297SScott Long 						ptmpuserbuffer++;
2846ad6d6297SScott Long 						user_len--;
2847ad6d6297SScott Long 					}
2848ad6d6297SScott Long 					if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) {
2849ad6d6297SScott Long 						acb->acb_flags &=
2850ad6d6297SScott Long 						    ~ACB_F_MESSAGE_WQBUFFER_CLEARED;
28517a7bc959SXin LI 						arcmsr_Write_data_2iop_wqbuffer(acb);
2852ad6d6297SScott Long 					}
2853ad6d6297SScott Long 				} else {
2854ad6d6297SScott Long 					/* has error report sensedata */
2855dac36688SXin LI 					if(pccb->csio.sense_len) {
2856ad6d6297SScott Long 					((u_int8_t *)&pccb->csio.sense_data)[0] = (0x1 << 7 | 0x70);
2857ad6d6297SScott Long 					/* Valid,ErrorCode */
2858ad6d6297SScott Long 					((u_int8_t *)&pccb->csio.sense_data)[2] = 0x05;
2859ad6d6297SScott Long 					/* FileMark,EndOfMedia,IncorrectLength,Reserved,SenseKey */
2860ad6d6297SScott Long 					((u_int8_t *)&pccb->csio.sense_data)[7] = 0x0A;
2861ad6d6297SScott Long 					/* AdditionalSenseLength */
2862ad6d6297SScott Long 					((u_int8_t *)&pccb->csio.sense_data)[12] = 0x20;
2863ad6d6297SScott Long 					/* AdditionalSenseCode */
2864ad6d6297SScott Long 					}
2865ad6d6297SScott Long 					retvalue = ARCMSR_MESSAGE_FAIL;
2866ad6d6297SScott Long 				}
2867ad6d6297SScott Long 			}
28687a7bc959SXin LI 			ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
2869ad6d6297SScott Long 		}
2870ad6d6297SScott Long 		break;
2871ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_RQBUFFER: {
2872ad6d6297SScott Long 			u_int8_t *pQbuffer = acb->rqbuffer;
2873ad6d6297SScott Long 
28747a7bc959SXin LI 			ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
2875ad6d6297SScott Long 			if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
2876ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
287744f05562SScott Long 				arcmsr_iop_message_read(acb);
2878ad6d6297SScott Long 			}
2879ad6d6297SScott Long 			acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED;
2880ad6d6297SScott Long 			acb->rqbuf_firstindex = 0;
2881ad6d6297SScott Long 			acb->rqbuf_lastindex = 0;
2882ad6d6297SScott Long 			memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
2883ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode =
2884ad6d6297SScott Long 			    ARCMSR_MESSAGE_RETURNCODE_OK;
28857a7bc959SXin LI 			ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
2886ad6d6297SScott Long 		}
2887ad6d6297SScott Long 		break;
2888ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_WQBUFFER: {
2889ad6d6297SScott Long 			u_int8_t *pQbuffer = acb->wqbuffer;
2890ad6d6297SScott Long 
28917a7bc959SXin LI 			ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
2892ad6d6297SScott Long 			if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
2893ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
289444f05562SScott Long 				arcmsr_iop_message_read(acb);
2895ad6d6297SScott Long 			}
2896ad6d6297SScott Long 			acb->acb_flags |=
2897ad6d6297SScott Long 				(ACB_F_MESSAGE_WQBUFFER_CLEARED |
289844f05562SScott Long 					ACB_F_MESSAGE_WQBUFFER_READ);
2899ad6d6297SScott Long 			acb->wqbuf_firstindex = 0;
2900ad6d6297SScott Long 			acb->wqbuf_lastindex = 0;
2901ad6d6297SScott Long 			memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER);
2902ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode =
2903ad6d6297SScott Long 				ARCMSR_MESSAGE_RETURNCODE_OK;
29047a7bc959SXin LI 			ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
2905ad6d6297SScott Long 		}
2906ad6d6297SScott Long 		break;
2907ad6d6297SScott Long 	case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: {
2908ad6d6297SScott Long 			u_int8_t *pQbuffer;
2909ad6d6297SScott Long 
29107a7bc959SXin LI 			ARCMSR_LOCK_ACQUIRE(&acb->qbuffer_lock);
2911ad6d6297SScott Long 			if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) {
2912ad6d6297SScott Long 				acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW;
291344f05562SScott Long 				arcmsr_iop_message_read(acb);
2914ad6d6297SScott Long 			}
2915ad6d6297SScott Long 			acb->acb_flags |=
2916ad6d6297SScott Long 				(ACB_F_MESSAGE_WQBUFFER_CLEARED
2917ad6d6297SScott Long 				| ACB_F_MESSAGE_RQBUFFER_CLEARED
291844f05562SScott Long 				| ACB_F_MESSAGE_WQBUFFER_READ);
2919ad6d6297SScott Long 			acb->rqbuf_firstindex = 0;
2920ad6d6297SScott Long 			acb->rqbuf_lastindex = 0;
2921ad6d6297SScott Long 			acb->wqbuf_firstindex = 0;
2922ad6d6297SScott Long 			acb->wqbuf_lastindex = 0;
2923ad6d6297SScott Long 			pQbuffer = acb->rqbuffer;
2924ad6d6297SScott Long 			memset(pQbuffer, 0, sizeof (struct QBUFFER));
2925ad6d6297SScott Long 			pQbuffer = acb->wqbuffer;
2926ad6d6297SScott Long 			memset(pQbuffer, 0, sizeof (struct QBUFFER));
2927ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
29287a7bc959SXin LI 			ARCMSR_LOCK_RELEASE(&acb->qbuffer_lock);
2929ad6d6297SScott Long 		}
2930ad6d6297SScott Long 		break;
2931ad6d6297SScott Long 	case ARCMSR_MESSAGE_REQUEST_RETURNCODE_3F: {
2932ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F;
2933ad6d6297SScott Long 		}
2934ad6d6297SScott Long 		break;
2935ad6d6297SScott Long 	case ARCMSR_MESSAGE_SAY_HELLO: {
2936ad6d6297SScott Long 			int8_t *hello_string = "Hello! I am ARCMSR";
2937ad6d6297SScott Long 
2938ad6d6297SScott Long 			memcpy(pcmdmessagefld->messagedatabuffer, hello_string
2939ad6d6297SScott Long 				, (int16_t)strlen(hello_string));
2940ad6d6297SScott Long 			pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK;
2941ad6d6297SScott Long 		}
2942ad6d6297SScott Long 		break;
2943ad6d6297SScott Long 	case ARCMSR_MESSAGE_SAY_GOODBYE:
2944ad6d6297SScott Long 		arcmsr_iop_parking(acb);
2945ad6d6297SScott Long 		break;
2946ad6d6297SScott Long 	case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE:
2947ad6d6297SScott Long 		arcmsr_flush_adapter_cache(acb);
2948ad6d6297SScott Long 		break;
2949ad6d6297SScott Long 	default:
2950ad6d6297SScott Long 		retvalue = ARCMSR_MESSAGE_FAIL;
2951ad6d6297SScott Long 	}
2952ad6d6297SScott Long message_out:
2953dac36688SXin LI 	return (retvalue);
2954f1c579b1SScott Long }
2955f1c579b1SScott Long /*
2956f1c579b1SScott Long *********************************************************************
2957f1c579b1SScott Long *********************************************************************
2958f1c579b1SScott Long */
2959231c8b71SXin LI static void arcmsr_execute_srb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error)
2960f1c579b1SScott Long {
2961ad6d6297SScott Long 	struct CommandControlBlock *srb = (struct CommandControlBlock *)arg;
2962ad6d6297SScott Long 	struct AdapterControlBlock *acb = (struct AdapterControlBlock *)srb->acb;
2963f1c579b1SScott Long 	union ccb *pccb;
2964ad6d6297SScott Long 	int target, lun;
2965f1c579b1SScott Long 
2966ad6d6297SScott Long 	pccb = srb->pccb;
2967ad6d6297SScott Long 	target = pccb->ccb_h.target_id;
2968ad6d6297SScott Long 	lun = pccb->ccb_h.target_lun;
296922f2616bSXin LI 	acb->pktRequestCount++;
2970ad6d6297SScott Long 	if(error != 0) {
2971ad6d6297SScott Long 		if(error != EFBIG) {
297244f05562SScott Long 			printf("arcmsr%d: unexpected error %x"
297344f05562SScott Long 				" returned from 'bus_dmamap_load' \n"
2974ad6d6297SScott Long 				, acb->pci_unit, error);
2975f1c579b1SScott Long 		}
2976ad6d6297SScott Long 		if((pccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG) {
297715735becSScott Long 			pccb->ccb_h.status |= CAM_REQ_TOO_BIG;
2978f1c579b1SScott Long 		}
2979ad6d6297SScott Long 		arcmsr_srb_complete(srb, 0);
2980f1c579b1SScott Long 		return;
2981f1c579b1SScott Long 	}
2982ad6d6297SScott Long 	if(nseg > ARCMSR_MAX_SG_ENTRIES) {
2983ad6d6297SScott Long 		pccb->ccb_h.status |= CAM_REQ_TOO_BIG;
2984ad6d6297SScott Long 		arcmsr_srb_complete(srb, 0);
2985ad6d6297SScott Long 		return;
2986f1c579b1SScott Long 	}
2987ad6d6297SScott Long 	if(acb->acb_flags & ACB_F_BUS_RESET) {
2988ad6d6297SScott Long 		printf("arcmsr%d: bus reset and return busy \n", acb->pci_unit);
2989ad6d6297SScott Long 		pccb->ccb_h.status |= CAM_SCSI_BUS_RESET;
2990ad6d6297SScott Long 		arcmsr_srb_complete(srb, 0);
2991ad6d6297SScott Long 		return;
2992ad6d6297SScott Long 	}
2993ad6d6297SScott Long 	if(acb->devstate[target][lun] == ARECA_RAID_GONE) {
299422f2616bSXin LI 		u_int8_t block_cmd, cmd;
2995ad6d6297SScott Long 
29964aa947cbSWarner Losh 		cmd = scsiio_cdb_ptr(&pccb->csio)[0];
299722f2616bSXin LI 		block_cmd = cmd & 0x0f;
2998ad6d6297SScott Long 		if(block_cmd == 0x08 || block_cmd == 0x0a) {
2999ad6d6297SScott Long 			printf("arcmsr%d:block 'read/write' command "
300022f2616bSXin LI 				"with gone raid volume Cmd=0x%2x, TargetId=%d, Lun=%d \n"
300122f2616bSXin LI 				, acb->pci_unit, cmd, target, lun);
3002ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
3003ad6d6297SScott Long 			arcmsr_srb_complete(srb, 0);
3004ad6d6297SScott Long 			return;
3005ad6d6297SScott Long 		}
3006ad6d6297SScott Long 	}
3007ad6d6297SScott Long 	if((pccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
3008ad6d6297SScott Long 		if(nseg != 0) {
3009ad6d6297SScott Long 			bus_dmamap_unload(acb->dm_segs_dmat, srb->dm_segs_dmamap);
3010ad6d6297SScott Long 		}
3011ad6d6297SScott Long 		arcmsr_srb_complete(srb, 0);
3012f1c579b1SScott Long 		return;
3013f1c579b1SScott Long 	}
3014abfdbca9SXin LI 	if(acb->srboutstandingcount >= acb->maxOutstanding) {
30157a7bc959SXin LI 		if((acb->acb_flags & ACB_F_CAM_DEV_QFRZN) == 0)
30167a7bc959SXin LI 		{
301715735becSScott Long 			xpt_freeze_simq(acb->psim, 1);
3018dc3a205bSScott Long 			acb->acb_flags |= ACB_F_CAM_DEV_QFRZN;
30197a7bc959SXin LI 		}
30207a7bc959SXin LI 		pccb->ccb_h.status &= ~CAM_SIM_QUEUED;
30217a7bc959SXin LI 		pccb->ccb_h.status |= CAM_REQUEUE_REQ;
3022ad6d6297SScott Long 		arcmsr_srb_complete(srb, 0);
3023ad6d6297SScott Long 		return;
3024f1c579b1SScott Long 	}
302515735becSScott Long 	pccb->ccb_h.status |= CAM_SIM_QUEUED;
3026ad6d6297SScott Long 	arcmsr_build_srb(srb, dm_segs, nseg);
3027ad6d6297SScott Long 	arcmsr_post_srb(acb, srb);
302822f2616bSXin LI 	if (pccb->ccb_h.timeout != CAM_TIME_INFINITY)
302922f2616bSXin LI 	{
303022f2616bSXin LI 		arcmsr_callout_init(&srb->ccb_callout);
303185c9dd9dSSteven Hartland 		callout_reset_sbt(&srb->ccb_callout, SBT_1MS *
303285c9dd9dSSteven Hartland 		    (pccb->ccb_h.timeout + (ARCMSR_TIMEOUT_DELAY * 1000)), 0,
303385c9dd9dSSteven Hartland 		    arcmsr_srb_timeout, srb, 0);
303422f2616bSXin LI 		srb->srb_flags |= SRB_FLAG_TIMER_START;
303522f2616bSXin LI 	}
3036f1c579b1SScott Long }
3037f1c579b1SScott Long /*
3038f1c579b1SScott Long *****************************************************************************************
3039f1c579b1SScott Long *****************************************************************************************
3040f1c579b1SScott Long */
3041ad6d6297SScott Long static u_int8_t arcmsr_seek_cmd2abort(union ccb *abortccb)
3042f1c579b1SScott Long {
3043ad6d6297SScott Long 	struct CommandControlBlock *srb;
3044ad6d6297SScott Long 	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) abortccb->ccb_h.arcmsr_ccbacb_ptr;
304544f05562SScott Long 	u_int32_t intmask_org;
3046ad6d6297SScott Long 	int i = 0;
3047f1c579b1SScott Long 
3048ad6d6297SScott Long 	acb->num_aborts++;
3049f1c579b1SScott Long 	/*
3050ad6d6297SScott Long 	***************************************************************************
3051f1c579b1SScott Long 	** It is the upper layer do abort command this lock just prior to calling us.
3052f1c579b1SScott Long 	** First determine if we currently own this command.
3053f1c579b1SScott Long 	** Start by searching the device queue. If not found
3054f1c579b1SScott Long 	** at all, and the system wanted us to just abort the
3055f1c579b1SScott Long 	** command return success.
3056ad6d6297SScott Long 	***************************************************************************
3057f1c579b1SScott Long 	*/
3058ad6d6297SScott Long 	if(acb->srboutstandingcount != 0) {
305922f2616bSXin LI 		/* disable all outbound interrupt */
306022f2616bSXin LI 		intmask_org = arcmsr_disable_allintr(acb);
3061ad6d6297SScott Long 		for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) {
3062ad6d6297SScott Long 			srb = acb->psrb_pool[i];
306322f2616bSXin LI 			if(srb->srb_state == ARCMSR_SRB_START) {
3064ad6d6297SScott Long 				if(srb->pccb == abortccb) {
306522f2616bSXin LI 					srb->srb_state = ARCMSR_SRB_ABORTED;
3066123055f0SNathan Whitehorn 					printf("arcmsr%d:scsi id=%d lun=%jx abort srb '%p'"
3067ad6d6297SScott Long 						"outstanding command \n"
3068ad6d6297SScott Long 						, acb->pci_unit, abortccb->ccb_h.target_id
3069123055f0SNathan Whitehorn 						, (uintmax_t)abortccb->ccb_h.target_lun, srb);
3070ad6d6297SScott Long 					arcmsr_polling_srbdone(acb, srb);
307144f05562SScott Long 					/* enable outbound Post Queue, outbound doorbell Interrupt */
307244f05562SScott Long 					arcmsr_enable_allintr(acb, intmask_org);
3073ad6d6297SScott Long 					return (TRUE);
3074f1c579b1SScott Long 				}
307522f2616bSXin LI 			}
307622f2616bSXin LI 		}
307722f2616bSXin LI 		/* enable outbound Post Queue, outbound doorbell Interrupt */
307822f2616bSXin LI 		arcmsr_enable_allintr(acb, intmask_org);
307922f2616bSXin LI 	}
308022f2616bSXin LI 	return(FALSE);
308122f2616bSXin LI }
3082f1c579b1SScott Long /*
3083f1c579b1SScott Long ****************************************************************************
3084f1c579b1SScott Long ****************************************************************************
3085f1c579b1SScott Long */
3086ad6d6297SScott Long static void arcmsr_bus_reset(struct AdapterControlBlock *acb)
3087f1c579b1SScott Long {
3088ad6d6297SScott Long 	int retry = 0;
3089f1c579b1SScott Long 
3090ad6d6297SScott Long 	acb->num_resets++;
3091ad6d6297SScott Long 	acb->acb_flags |= ACB_F_BUS_RESET;
3092ad6d6297SScott Long 	while(acb->srboutstandingcount != 0 && retry < 400) {
309344f05562SScott Long 		arcmsr_interrupt(acb);
3094ad6d6297SScott Long 		UDELAY(25000);
3095ad6d6297SScott Long 		retry++;
3096ad6d6297SScott Long 	}
3097ad6d6297SScott Long 	arcmsr_iop_reset(acb);
3098ad6d6297SScott Long 	acb->acb_flags &= ~ACB_F_BUS_RESET;
3099f1c579b1SScott Long }
3100f1c579b1SScott Long /*
3101ad6d6297SScott Long **************************************************************************
3102ad6d6297SScott Long **************************************************************************
3103ad6d6297SScott Long */
3104ad6d6297SScott Long static void arcmsr_handle_virtual_command(struct AdapterControlBlock *acb,
3105ad6d6297SScott Long 		union ccb *pccb)
3106ad6d6297SScott Long {
3107ad6d6297SScott Long 	if (pccb->ccb_h.target_lun) {
310861ba2ac6SJim Harris 		pccb->ccb_h.status |= CAM_DEV_NOT_THERE;
3109ad6d6297SScott Long 		xpt_done(pccb);
3110ad6d6297SScott Long 		return;
3111ad6d6297SScott Long 	}
31127a7bc959SXin LI 	pccb->ccb_h.status |= CAM_REQ_CMP;
31134aa947cbSWarner Losh 	switch (scsiio_cdb_ptr(&pccb->csio)[0]) {
31147a7bc959SXin LI 	case INQUIRY: {
31157a7bc959SXin LI 		unsigned char inqdata[36];
31167a7bc959SXin LI 		char *buffer = pccb->csio.data_ptr;
31177a7bc959SXin LI 
3118231c8b71SXin LI 		inqdata[0] = T_PROCESSOR;	/* Periph Qualifier & Periph Dev Type */
3119231c8b71SXin LI 		inqdata[1] = 0;			/* rem media bit & Dev Type Modifier */
3120231c8b71SXin LI 		inqdata[2] = 0;			/* ISO, ECMA, & ANSI versions */
3121231c8b71SXin LI 		inqdata[3] = 0;
3122231c8b71SXin LI 		inqdata[4] = 31;		/* length of additional data */
3123231c8b71SXin LI 		inqdata[5] = 0;
3124231c8b71SXin LI 		inqdata[6] = 0;
3125231c8b71SXin LI 		inqdata[7] = 0;
3126231c8b71SXin LI 		strncpy(&inqdata[8], "Areca   ", 8);	/* Vendor Identification */
3127231c8b71SXin LI 		strncpy(&inqdata[16], "RAID controller ", 16);	/* Product Identification */
3128ad6d6297SScott Long 		strncpy(&inqdata[32], "R001", 4); /* Product Revision */
3129ad6d6297SScott Long 		memcpy(buffer, inqdata, sizeof(inqdata));
3130ad6d6297SScott Long 		xpt_done(pccb);
3131ad6d6297SScott Long 	}
3132ad6d6297SScott Long 	break;
3133ad6d6297SScott Long 	case WRITE_BUFFER:
3134ad6d6297SScott Long 	case READ_BUFFER: {
3135ad6d6297SScott Long 		if (arcmsr_iop_message_xfer(acb, pccb)) {
3136ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
3137ad6d6297SScott Long 			pccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
3138ad6d6297SScott Long 		}
3139ad6d6297SScott Long 		xpt_done(pccb);
3140ad6d6297SScott Long 	}
3141ad6d6297SScott Long 	break;
3142ad6d6297SScott Long 	default:
3143ad6d6297SScott Long 		xpt_done(pccb);
3144ad6d6297SScott Long 	}
3145ad6d6297SScott Long }
3146ad6d6297SScott Long /*
3147f1c579b1SScott Long *********************************************************************
3148f1c579b1SScott Long *********************************************************************
3149f1c579b1SScott Long */
3150ad6d6297SScott Long static void arcmsr_action(struct cam_sim *psim, union ccb *pccb)
3151f1c579b1SScott Long {
3152ad6d6297SScott Long 	struct AdapterControlBlock *acb;
3153f1c579b1SScott Long 
3154ad6d6297SScott Long 	acb = (struct AdapterControlBlock *) cam_sim_softc(psim);
3155ad6d6297SScott Long 	if(acb == NULL) {
3156ad6d6297SScott Long 		pccb->ccb_h.status |= CAM_REQ_INVALID;
3157f1c579b1SScott Long 		xpt_done(pccb);
3158f1c579b1SScott Long 		return;
3159f1c579b1SScott Long 	}
3160ad6d6297SScott Long 	switch (pccb->ccb_h.func_code) {
3161ad6d6297SScott Long 	case XPT_SCSI_IO: {
3162ad6d6297SScott Long 			struct CommandControlBlock *srb;
3163ad6d6297SScott Long 			int target = pccb->ccb_h.target_id;
3164dd0b4fb6SKonstantin Belousov 			int error;
3165f1c579b1SScott Long 
31664aa947cbSWarner Losh 			if (pccb->ccb_h.flags & CAM_CDB_PHYS) {
31674aa947cbSWarner Losh 				pccb->ccb_h.status = CAM_REQ_INVALID;
31684aa947cbSWarner Losh 				xpt_done(pccb);
31694aa947cbSWarner Losh 				return;
31704aa947cbSWarner Losh 			}
31714aa947cbSWarner Losh 
3172ad6d6297SScott Long 			if(target == 16) {
3173ad6d6297SScott Long 				/* virtual device for iop message transfer */
3174ad6d6297SScott Long 				arcmsr_handle_virtual_command(acb, pccb);
3175ad6d6297SScott Long 				return;
3176ad6d6297SScott Long 			}
3177ad6d6297SScott Long 			if((srb = arcmsr_get_freesrb(acb)) == NULL) {
3178ad6d6297SScott Long 				pccb->ccb_h.status |= CAM_RESRC_UNAVAIL;
3179f1c579b1SScott Long 				xpt_done(pccb);
3180f1c579b1SScott Long 				return;
3181f1c579b1SScott Long 			}
3182ad6d6297SScott Long 			pccb->ccb_h.arcmsr_ccbsrb_ptr = srb;
3183ad6d6297SScott Long 			pccb->ccb_h.arcmsr_ccbacb_ptr = acb;
3184ad6d6297SScott Long 			srb->pccb = pccb;
3185dd0b4fb6SKonstantin Belousov 			error =	bus_dmamap_load_ccb(acb->dm_segs_dmat
3186ad6d6297SScott Long 				, srb->dm_segs_dmamap
3187dd0b4fb6SKonstantin Belousov 				, pccb
3188231c8b71SXin LI 				, arcmsr_execute_srb, srb, /*flags*/0);
3189ad6d6297SScott Long 			if(error == EINPROGRESS) {
3190ad6d6297SScott Long 				xpt_freeze_simq(acb->psim, 1);
3191f1c579b1SScott Long 				pccb->ccb_h.status |= CAM_RELEASE_SIMQ;
3192f1c579b1SScott Long 			}
3193f1c579b1SScott Long 			break;
3194f1c579b1SScott Long 		}
3195ad6d6297SScott Long 	case XPT_PATH_INQ: {
3196f1c579b1SScott Long 			struct ccb_pathinq *cpi = &pccb->cpi;
3197f1c579b1SScott Long 
3198f1c579b1SScott Long 			cpi->version_num = 1;
3199f1c579b1SScott Long 			cpi->hba_inquiry = PI_SDTR_ABLE | PI_TAG_ABLE;
3200f1c579b1SScott Long 			cpi->target_sprt = 0;
3201f1c579b1SScott Long 			cpi->hba_misc = 0;
3202f1c579b1SScott Long 			cpi->hba_eng_cnt = 0;
3203ad6d6297SScott Long 			cpi->max_target = ARCMSR_MAX_TARGETID;        /* 0-16 */
3204ad6d6297SScott Long 			cpi->max_lun = ARCMSR_MAX_TARGETLUN;	    /* 0-7 */
3205ad6d6297SScott Long 			cpi->initiator_id = ARCMSR_SCSI_INITIATOR_ID; /* 255 */
3206f1c579b1SScott Long 			cpi->bus_id = cam_sim_bus(psim);
32074195c7deSAlan Somers 			strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
32084195c7deSAlan Somers 			strlcpy(cpi->hba_vid, "ARCMSR", HBA_IDLEN);
32094195c7deSAlan Somers 			strlcpy(cpi->dev_name, cam_sim_name(psim), DEV_IDLEN);
3210f1c579b1SScott Long 			cpi->unit_number = cam_sim_unit(psim);
3211224a78aeSXin LI 			if(acb->adapter_bus_speed == ACB_BUS_SPEED_12G)
3212224a78aeSXin LI 				cpi->base_transfer_speed = 1200000;
3213224a78aeSXin LI 			else if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G)
3214dac36688SXin LI 				cpi->base_transfer_speed = 600000;
3215dac36688SXin LI 			else
3216dac36688SXin LI 				cpi->base_transfer_speed = 300000;
3217dac36688SXin LI 			if((acb->vendor_device_id == PCIDevVenIDARC1880) ||
3218a1103e04SXin LI 			   (acb->vendor_device_id == PCIDevVenIDARC1884) ||
32197a7bc959SXin LI 			   (acb->vendor_device_id == PCIDevVenIDARC1680) ||
32207a7bc959SXin LI 			   (acb->vendor_device_id == PCIDevVenIDARC1214))
3221dac36688SXin LI 			{
3222dac36688SXin LI 				cpi->transport = XPORT_SAS;
3223dac36688SXin LI 				cpi->transport_version = 0;
3224dac36688SXin LI 				cpi->protocol_version = SCSI_REV_SPC2;
3225dac36688SXin LI 			}
3226dac36688SXin LI 			else
3227dac36688SXin LI 			{
3228fa9ed865SMatt Jacob 				cpi->transport = XPORT_SPI;
3229fa9ed865SMatt Jacob 				cpi->transport_version = 2;
3230fa9ed865SMatt Jacob 				cpi->protocol_version = SCSI_REV_2;
3231dac36688SXin LI 			}
3232dac36688SXin LI 			cpi->protocol = PROTO_SCSI;
3233ad6d6297SScott Long 			cpi->ccb_h.status |= CAM_REQ_CMP;
3234f1c579b1SScott Long 			xpt_done(pccb);
3235f1c579b1SScott Long 			break;
3236f1c579b1SScott Long 		}
3237ad6d6297SScott Long 	case XPT_ABORT: {
3238f1c579b1SScott Long 			union ccb *pabort_ccb;
3239f1c579b1SScott Long 
3240f1c579b1SScott Long 			pabort_ccb = pccb->cab.abort_ccb;
3241ad6d6297SScott Long 			switch (pabort_ccb->ccb_h.func_code) {
3242f1c579b1SScott Long 			case XPT_ACCEPT_TARGET_IO:
3243f1c579b1SScott Long 			case XPT_CONT_TARGET_IO:
3244ad6d6297SScott Long 				if(arcmsr_seek_cmd2abort(pabort_ccb)==TRUE) {
3245ad6d6297SScott Long 					pabort_ccb->ccb_h.status |= CAM_REQ_ABORTED;
3246f1c579b1SScott Long 					xpt_done(pabort_ccb);
3247ad6d6297SScott Long 					pccb->ccb_h.status |= CAM_REQ_CMP;
3248ad6d6297SScott Long 				} else {
3249f1c579b1SScott Long 					xpt_print_path(pabort_ccb->ccb_h.path);
3250f1c579b1SScott Long 					printf("Not found\n");
3251ad6d6297SScott Long 					pccb->ccb_h.status |= CAM_PATH_INVALID;
3252f1c579b1SScott Long 				}
3253f1c579b1SScott Long 				break;
3254f1c579b1SScott Long 			case XPT_SCSI_IO:
3255ad6d6297SScott Long 				pccb->ccb_h.status |= CAM_UA_ABORT;
3256f1c579b1SScott Long 				break;
3257f1c579b1SScott Long 			default:
3258ad6d6297SScott Long 				pccb->ccb_h.status |= CAM_REQ_INVALID;
3259f1c579b1SScott Long 				break;
3260f1c579b1SScott Long 			}
3261f1c579b1SScott Long 			xpt_done(pccb);
3262f1c579b1SScott Long 			break;
3263f1c579b1SScott Long 		}
3264f1c579b1SScott Long 	case XPT_RESET_BUS:
3265ad6d6297SScott Long 	case XPT_RESET_DEV: {
3266ad6d6297SScott Long 			u_int32_t	i;
3267f1c579b1SScott Long 
3268ad6d6297SScott Long 			arcmsr_bus_reset(acb);
3269ad6d6297SScott Long 			for (i=0; i < 500; i++) {
3270f1c579b1SScott Long 				DELAY(1000);
3271f1c579b1SScott Long 			}
3272ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_REQ_CMP;
3273f1c579b1SScott Long 			xpt_done(pccb);
3274f1c579b1SScott Long 			break;
3275f1c579b1SScott Long 		}
3276ad6d6297SScott Long 	case XPT_TERM_IO: {
3277ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_REQ_INVALID;
3278f1c579b1SScott Long 			xpt_done(pccb);
3279f1c579b1SScott Long 			break;
3280f1c579b1SScott Long 		}
3281ad6d6297SScott Long 	case XPT_GET_TRAN_SETTINGS: {
3282ad6d6297SScott Long 			struct ccb_trans_settings *cts;
3283ad6d6297SScott Long 
3284ad6d6297SScott Long 			if(pccb->ccb_h.target_id == 16) {
3285ad6d6297SScott Long 				pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL;
3286ad6d6297SScott Long 				xpt_done(pccb);
3287ad6d6297SScott Long 				break;
3288ad6d6297SScott Long 			}
3289ad6d6297SScott Long 			cts = &pccb->cts;
329044f05562SScott Long 			{
329144f05562SScott Long 				struct ccb_trans_settings_scsi *scsi;
329244f05562SScott Long 				struct ccb_trans_settings_spi *spi;
3293dac36688SXin LI 				struct ccb_trans_settings_sas *sas;
329444f05562SScott Long 
3295ad6d6297SScott Long 				scsi = &cts->proto_specific.scsi;
3296dac36688SXin LI 				scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
3297dac36688SXin LI 				scsi->valid = CTS_SCSI_VALID_TQ;
3298fa9ed865SMatt Jacob 				cts->protocol = PROTO_SCSI;
3299dac36688SXin LI 
3300dac36688SXin LI 				if((acb->vendor_device_id == PCIDevVenIDARC1880) ||
3301a1103e04SXin LI 				   (acb->vendor_device_id == PCIDevVenIDARC1884) ||
33027a7bc959SXin LI 				   (acb->vendor_device_id == PCIDevVenIDARC1680) ||
33037a7bc959SXin LI 				   (acb->vendor_device_id == PCIDevVenIDARC1214))
3304dac36688SXin LI 				{
3305dac36688SXin LI 					cts->protocol_version = SCSI_REV_SPC2;
3306dac36688SXin LI 					cts->transport_version = 0;
3307dac36688SXin LI 					cts->transport = XPORT_SAS;
3308dac36688SXin LI 					sas = &cts->xport_specific.sas;
3309dac36688SXin LI 					sas->valid = CTS_SAS_VALID_SPEED;
3310b23a1998SXin LI 					if (acb->adapter_bus_speed == ACB_BUS_SPEED_12G)
3311224a78aeSXin LI 						sas->bitrate = 1200000;
3312b23a1998SXin LI 					else if(acb->adapter_bus_speed == ACB_BUS_SPEED_6G)
3313dac36688SXin LI 						sas->bitrate = 600000;
3314b23a1998SXin LI 					else if(acb->adapter_bus_speed == ACB_BUS_SPEED_3G)
3315dac36688SXin LI 						sas->bitrate = 300000;
3316dac36688SXin LI 				}
3317dac36688SXin LI 				else
3318dac36688SXin LI 				{
3319fa9ed865SMatt Jacob 					cts->protocol_version = SCSI_REV_2;
3320fa9ed865SMatt Jacob 					cts->transport_version = 2;
3321dac36688SXin LI 					cts->transport = XPORT_SPI;
3322dac36688SXin LI 					spi = &cts->xport_specific.spi;
3323fa9ed865SMatt Jacob 					spi->flags = CTS_SPI_FLAGS_DISC_ENB;
3324b23a1998SXin LI 					if (acb->adapter_bus_speed == ACB_BUS_SPEED_6G)
3325b23a1998SXin LI 						spi->sync_period = 1;
3326b23a1998SXin LI 					else
3327dac36688SXin LI 						spi->sync_period = 2;
3328fa9ed865SMatt Jacob 					spi->sync_offset = 32;
3329fa9ed865SMatt Jacob 					spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT;
33309d98ff4dSScott Long 					spi->valid = CTS_SPI_VALID_DISC
33319d98ff4dSScott Long 						| CTS_SPI_VALID_SYNC_RATE
3332fa9ed865SMatt Jacob 						| CTS_SPI_VALID_SYNC_OFFSET
3333fa9ed865SMatt Jacob 						| CTS_SPI_VALID_BUS_WIDTH;
3334dac36688SXin LI 				}
333544f05562SScott Long 			}
3336ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_REQ_CMP;
3337ad6d6297SScott Long 			xpt_done(pccb);
3338ad6d6297SScott Long 			break;
3339ad6d6297SScott Long 		}
3340ad6d6297SScott Long 	case XPT_SET_TRAN_SETTINGS: {
3341ad6d6297SScott Long 			pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL;
3342ad6d6297SScott Long 			xpt_done(pccb);
3343ad6d6297SScott Long 			break;
3344ad6d6297SScott Long 		}
3345f3b080e6SMarius Strobl 	case XPT_CALC_GEOMETRY:
3346ad6d6297SScott Long 			if(pccb->ccb_h.target_id == 16) {
3347ad6d6297SScott Long 				pccb->ccb_h.status |= CAM_FUNC_NOTAVAIL;
3348ad6d6297SScott Long 				xpt_done(pccb);
3349ad6d6297SScott Long 				break;
3350ad6d6297SScott Long 			}
3351f3b080e6SMarius Strobl 			cam_calc_geometry(&pccb->ccg, 1);
3352f1c579b1SScott Long 			xpt_done(pccb);
3353f1c579b1SScott Long 			break;
3354f1c579b1SScott Long 	default:
3355ad6d6297SScott Long 		pccb->ccb_h.status |= CAM_REQ_INVALID;
3356f1c579b1SScott Long 		xpt_done(pccb);
3357f1c579b1SScott Long 		break;
3358f1c579b1SScott Long 	}
3359f1c579b1SScott Long }
3360f1c579b1SScott Long /*
3361f1c579b1SScott Long **********************************************************************
3362f1c579b1SScott Long **********************************************************************
3363f1c579b1SScott Long */
336444f05562SScott Long static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb)
3365f1c579b1SScott Long {
3366ad6d6297SScott Long 	acb->acb_flags |= ACB_F_MSG_START_BGRB;
336744f05562SScott Long 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB);
336844f05562SScott Long 	if(!arcmsr_hba_wait_msgint_ready(acb)) {
3369ad6d6297SScott Long 		printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit);
3370ad6d6297SScott Long 	}
3371f1c579b1SScott Long }
3372f1c579b1SScott Long /*
3373f1c579b1SScott Long **********************************************************************
3374f1c579b1SScott Long **********************************************************************
3375f1c579b1SScott Long */
337644f05562SScott Long static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb)
337744f05562SScott Long {
3378b23a1998SXin LI 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
337944f05562SScott Long 	acb->acb_flags |= ACB_F_MSG_START_BGRB;
3380b23a1998SXin LI 	WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_START_BGRB);
338144f05562SScott Long 	if(!arcmsr_hbb_wait_msgint_ready(acb)) {
338244f05562SScott Long 		printf( "arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit);
338344f05562SScott Long 	}
338444f05562SScott Long }
338544f05562SScott Long /*
338644f05562SScott Long **********************************************************************
338744f05562SScott Long **********************************************************************
338844f05562SScott Long */
3389d74001adSXin LI static void arcmsr_start_hbc_bgrb(struct AdapterControlBlock *acb)
3390d74001adSXin LI {
3391d74001adSXin LI 	acb->acb_flags |= ACB_F_MSG_START_BGRB;
3392d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB);
3393d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
3394d74001adSXin LI 	if(!arcmsr_hbc_wait_msgint_ready(acb)) {
3395d74001adSXin LI 		printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit);
3396d74001adSXin LI 	}
3397d74001adSXin LI }
3398d74001adSXin LI /*
3399d74001adSXin LI **********************************************************************
3400d74001adSXin LI **********************************************************************
3401d74001adSXin LI */
34027a7bc959SXin LI static void arcmsr_start_hbd_bgrb(struct AdapterControlBlock *acb)
34037a7bc959SXin LI {
34047a7bc959SXin LI 	acb->acb_flags |= ACB_F_MSG_START_BGRB;
34057a7bc959SXin LI 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB);
34067a7bc959SXin LI 	if(!arcmsr_hbd_wait_msgint_ready(acb)) {
34077a7bc959SXin LI 		printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit);
34087a7bc959SXin LI 	}
34097a7bc959SXin LI }
34107a7bc959SXin LI /*
34117a7bc959SXin LI **********************************************************************
34127a7bc959SXin LI **********************************************************************
34137a7bc959SXin LI */
3414a1103e04SXin LI static void arcmsr_start_hbe_bgrb(struct AdapterControlBlock *acb)
3415a1103e04SXin LI {
3416a1103e04SXin LI 	acb->acb_flags |= ACB_F_MSG_START_BGRB;
3417a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_START_BGRB);
3418a1103e04SXin LI 	acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
3419a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
3420a1103e04SXin LI 	if(!arcmsr_hbe_wait_msgint_ready(acb)) {
3421a1103e04SXin LI 		printf("arcmsr%d: wait 'start adapter background rebulid' timeout \n", acb->pci_unit);
3422a1103e04SXin LI 	}
3423a1103e04SXin LI }
3424a1103e04SXin LI /*
3425a1103e04SXin LI **********************************************************************
3426a1103e04SXin LI **********************************************************************
3427a1103e04SXin LI */
342844f05562SScott Long static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb)
342944f05562SScott Long {
343044f05562SScott Long 	switch (acb->adapter_type) {
343144f05562SScott Long 	case ACB_ADAPTER_TYPE_A:
343244f05562SScott Long 		arcmsr_start_hba_bgrb(acb);
343344f05562SScott Long 		break;
343444f05562SScott Long 	case ACB_ADAPTER_TYPE_B:
343544f05562SScott Long 		arcmsr_start_hbb_bgrb(acb);
343644f05562SScott Long 		break;
3437d74001adSXin LI 	case ACB_ADAPTER_TYPE_C:
3438d74001adSXin LI 		arcmsr_start_hbc_bgrb(acb);
3439d74001adSXin LI 		break;
34407a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D:
34417a7bc959SXin LI 		arcmsr_start_hbd_bgrb(acb);
34427a7bc959SXin LI 		break;
3443a1103e04SXin LI 	case ACB_ADAPTER_TYPE_E:
3444fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F:
3445a1103e04SXin LI 		arcmsr_start_hbe_bgrb(acb);
3446a1103e04SXin LI 		break;
344744f05562SScott Long 	}
344844f05562SScott Long }
344944f05562SScott Long /*
345044f05562SScott Long **********************************************************************
345144f05562SScott Long **
345244f05562SScott Long **********************************************************************
345344f05562SScott Long */
345444f05562SScott Long static void arcmsr_polling_hba_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
3455f1c579b1SScott Long {
3456ad6d6297SScott Long 	struct CommandControlBlock *srb;
345744f05562SScott Long 	u_int32_t flag_srb, outbound_intstatus, poll_srb_done=0, poll_count=0;
3458d74001adSXin LI 	u_int16_t	error;
3459f1c579b1SScott Long 
346044f05562SScott Long polling_ccb_retry:
3461ad6d6297SScott Long 	poll_count++;
3462d74001adSXin LI 	outbound_intstatus=CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_intstatus) & acb->outbound_int_enable;
3463d74001adSXin LI 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_intstatus, outbound_intstatus);	/*clear interrupt*/
346444f05562SScott Long 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
3465ad6d6297SScott Long 	while(1) {
346644f05562SScott Long 		if((flag_srb = CHIP_REG_READ32(HBA_MessageUnit,
346744f05562SScott Long 			0, outbound_queueport)) == 0xFFFFFFFF) {
3468ad6d6297SScott Long 			if(poll_srb_done) {
3469ad6d6297SScott Long 				break;/*chip FIFO no ccb for completion already*/
3470ad6d6297SScott Long 			} else {
3471ad6d6297SScott Long 				UDELAY(25000);
3472d74001adSXin LI 				if ((poll_count > 100) && (poll_srb != NULL)) {
3473ad6d6297SScott Long 					break;
3474f1c579b1SScott Long 				}
347544f05562SScott Long 				goto polling_ccb_retry;
3476f1c579b1SScott Long 			}
3477ad6d6297SScott Long 		}
3478ad6d6297SScott Long 		/* check if command done with no error*/
347944f05562SScott Long 		srb = (struct CommandControlBlock *)
348044f05562SScott Long 			(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
3481d74001adSXin LI 		error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
348244f05562SScott Long 		poll_srb_done = (srb == poll_srb) ? 1:0;
348322f2616bSXin LI 		if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
348422f2616bSXin LI 			if(srb->srb_state == ARCMSR_SRB_ABORTED) {
3485123055f0SNathan Whitehorn 				printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'"
3486ad6d6297SScott Long 					"poll command abort successfully \n"
3487ad6d6297SScott Long 					, acb->pci_unit
3488ad6d6297SScott Long 					, srb->pccb->ccb_h.target_id
3489123055f0SNathan Whitehorn 					, (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
3490ad6d6297SScott Long 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
3491ad6d6297SScott Long 				arcmsr_srb_complete(srb, 1);
3492ad6d6297SScott Long 				continue;
3493ad6d6297SScott Long 			}
3494ad6d6297SScott Long 			printf("arcmsr%d: polling get an illegal srb command done srb='%p'"
3495ad6d6297SScott Long 				"srboutstandingcount=%d \n"
3496ad6d6297SScott Long 				, acb->pci_unit
3497ad6d6297SScott Long 				, srb, acb->srboutstandingcount);
3498ad6d6297SScott Long 			continue;
3499ad6d6297SScott Long 		}
3500d74001adSXin LI 		arcmsr_report_srb_state(acb, srb, error);
3501ad6d6297SScott Long 	}	/*drain reply FIFO*/
3502f1c579b1SScott Long }
3503f1c579b1SScott Long /*
3504f1c579b1SScott Long **********************************************************************
350544f05562SScott Long **
3506ad6d6297SScott Long **********************************************************************
3507ad6d6297SScott Long */
350844f05562SScott Long static void arcmsr_polling_hbb_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
350944f05562SScott Long {
351044f05562SScott Long 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
351144f05562SScott Long 	struct CommandControlBlock *srb;
351244f05562SScott Long 	u_int32_t flag_srb, poll_srb_done=0, poll_count=0;
351344f05562SScott Long 	int index;
3514d74001adSXin LI 	u_int16_t	error;
351544f05562SScott Long 
351644f05562SScott Long polling_ccb_retry:
351744f05562SScott Long 	poll_count++;
3518b23a1998SXin LI 	WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN); /* clear doorbell interrupt */
351944f05562SScott Long 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
352044f05562SScott Long 	while(1) {
352144f05562SScott Long 		index = phbbmu->doneq_index;
352244f05562SScott Long 		if((flag_srb = phbbmu->done_qbuffer[index]) == 0) {
352344f05562SScott Long 			if(poll_srb_done) {
352444f05562SScott Long 				break;/*chip FIFO no ccb for completion already*/
352544f05562SScott Long 			} else {
352644f05562SScott Long 				UDELAY(25000);
3527d74001adSXin LI 				if ((poll_count > 100) && (poll_srb != NULL)) {
352844f05562SScott Long 					break;
352944f05562SScott Long 				}
353044f05562SScott Long 				goto polling_ccb_retry;
353144f05562SScott Long 			}
353244f05562SScott Long 		}
353344f05562SScott Long 		phbbmu->done_qbuffer[index] = 0;
353444f05562SScott Long 		index++;
353544f05562SScott Long 		index %= ARCMSR_MAX_HBB_POSTQUEUE;     /*if last index number set it to 0 */
353644f05562SScott Long 		phbbmu->doneq_index = index;
353744f05562SScott Long 		/* check if command done with no error*/
353844f05562SScott Long 		srb = (struct CommandControlBlock *)
353944f05562SScott Long 			(acb->vir2phy_offset+(flag_srb << 5));/*frame must be 32 bytes aligned*/
3540d74001adSXin LI 		error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE0)?TRUE:FALSE;
354144f05562SScott Long 		poll_srb_done = (srb == poll_srb) ? 1:0;
354222f2616bSXin LI 		if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
354322f2616bSXin LI 			if(srb->srb_state == ARCMSR_SRB_ABORTED) {
3544123055f0SNathan Whitehorn 				printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'"
354544f05562SScott Long 					"poll command abort successfully \n"
354644f05562SScott Long 					, acb->pci_unit
354744f05562SScott Long 					, srb->pccb->ccb_h.target_id
3548123055f0SNathan Whitehorn 					, (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
354944f05562SScott Long 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
355044f05562SScott Long 				arcmsr_srb_complete(srb, 1);
355144f05562SScott Long 				continue;
355244f05562SScott Long 			}
355344f05562SScott Long 			printf("arcmsr%d: polling get an illegal srb command done srb='%p'"
355444f05562SScott Long 				"srboutstandingcount=%d \n"
355544f05562SScott Long 				, acb->pci_unit
355644f05562SScott Long 				, srb, acb->srboutstandingcount);
355744f05562SScott Long 			continue;
355844f05562SScott Long 		}
3559d74001adSXin LI 		arcmsr_report_srb_state(acb, srb, error);
3560d74001adSXin LI 	}	/*drain reply FIFO*/
3561d74001adSXin LI }
3562d74001adSXin LI /*
3563d74001adSXin LI **********************************************************************
3564d74001adSXin LI **
3565d74001adSXin LI **********************************************************************
3566d74001adSXin LI */
3567d74001adSXin LI static void arcmsr_polling_hbc_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
3568d74001adSXin LI {
3569d74001adSXin LI 	struct CommandControlBlock *srb;
3570d74001adSXin LI 	u_int32_t flag_srb, poll_srb_done=0, poll_count=0;
3571d74001adSXin LI 	u_int16_t	error;
3572d74001adSXin LI 
3573d74001adSXin LI polling_ccb_retry:
3574d74001adSXin LI 	poll_count++;
3575d74001adSXin LI 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
3576d74001adSXin LI 	while(1) {
3577d74001adSXin LI 		if(!(CHIP_REG_READ32(HBC_MessageUnit, 0, host_int_status) & ARCMSR_HBCMU_OUTBOUND_POSTQUEUE_ISR)) {
3578d74001adSXin LI 			if(poll_srb_done) {
3579d74001adSXin LI 				break;/*chip FIFO no ccb for completion already*/
3580d74001adSXin LI 			} else {
3581d74001adSXin LI 				UDELAY(25000);
3582d74001adSXin LI 				if ((poll_count > 100) && (poll_srb != NULL)) {
3583d74001adSXin LI 					break;
3584d74001adSXin LI 				}
3585d74001adSXin LI 				if (acb->srboutstandingcount == 0) {
3586d74001adSXin LI 					break;
3587d74001adSXin LI 				}
3588d74001adSXin LI 				goto polling_ccb_retry;
3589d74001adSXin LI 			}
3590d74001adSXin LI 		}
3591d74001adSXin LI 		flag_srb = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_queueport_low);
3592d74001adSXin LI 		/* check if command done with no error*/
359322f2616bSXin LI 		srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/
3594d74001adSXin LI 		error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1)?TRUE:FALSE;
3595d74001adSXin LI 		if (poll_srb != NULL)
3596d74001adSXin LI 			poll_srb_done = (srb == poll_srb) ? 1:0;
359722f2616bSXin LI 		if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
359822f2616bSXin LI 			if(srb->srb_state == ARCMSR_SRB_ABORTED) {
3599123055f0SNathan Whitehorn 				printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n"
3600123055f0SNathan Whitehorn 						, acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
3601d74001adSXin LI 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
3602d74001adSXin LI 				arcmsr_srb_complete(srb, 1);
3603d74001adSXin LI 				continue;
3604d74001adSXin LI 			}
3605d74001adSXin LI 			printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n"
3606d74001adSXin LI 					, acb->pci_unit, srb, acb->srboutstandingcount);
3607d74001adSXin LI 			continue;
3608d74001adSXin LI 		}
3609d74001adSXin LI 		arcmsr_report_srb_state(acb, srb, error);
361044f05562SScott Long 	}	/*drain reply FIFO*/
361144f05562SScott Long }
361244f05562SScott Long /*
361344f05562SScott Long **********************************************************************
36147a7bc959SXin LI **
36157a7bc959SXin LI **********************************************************************
36167a7bc959SXin LI */
36177a7bc959SXin LI static void arcmsr_polling_hbd_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
36187a7bc959SXin LI {
36197a7bc959SXin LI 	struct HBD_MessageUnit0 *phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
36207a7bc959SXin LI 	struct CommandControlBlock *srb;
36217a7bc959SXin LI 	u_int32_t flag_srb, poll_srb_done=0, poll_count=0;
36227a7bc959SXin LI 	u_int32_t outbound_write_pointer;
36237a7bc959SXin LI 	u_int16_t	error, doneq_index;
36247a7bc959SXin LI 
36257a7bc959SXin LI polling_ccb_retry:
36267a7bc959SXin LI 	poll_count++;
36277a7bc959SXin LI 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
36287a7bc959SXin LI 	while(1) {
36297a7bc959SXin LI 		outbound_write_pointer = phbdmu->done_qbuffer[0].addressLow;
36307a7bc959SXin LI 		doneq_index = phbdmu->doneq_index;
36317a7bc959SXin LI 		if ((outbound_write_pointer & 0xFF) == (doneq_index & 0xFF)) {
36327a7bc959SXin LI 			if(poll_srb_done) {
36337a7bc959SXin LI 				break;/*chip FIFO no ccb for completion already*/
36347a7bc959SXin LI 			} else {
36357a7bc959SXin LI 				UDELAY(25000);
36367a7bc959SXin LI 				if ((poll_count > 100) && (poll_srb != NULL)) {
36377a7bc959SXin LI 					break;
36387a7bc959SXin LI 				}
36397a7bc959SXin LI 				if (acb->srboutstandingcount == 0) {
36407a7bc959SXin LI 					break;
36417a7bc959SXin LI 				}
36427a7bc959SXin LI 				goto polling_ccb_retry;
36437a7bc959SXin LI 			}
36447a7bc959SXin LI 		}
36457a7bc959SXin LI 		doneq_index = arcmsr_get_doneq_index(phbdmu);
36467a7bc959SXin LI 		flag_srb = phbdmu->done_qbuffer[(doneq_index & 0xFF)+1].addressLow;
36477a7bc959SXin LI 		/* check if command done with no error*/
36487a7bc959SXin LI 		srb = (struct CommandControlBlock *)(acb->vir2phy_offset+(flag_srb & 0xFFFFFFE0));/*frame must be 32 bytes aligned*/
36497a7bc959SXin LI 		error = (flag_srb & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
36507a7bc959SXin LI 		CHIP_REG_WRITE32(HBD_MessageUnit, 0, outboundlist_read_pointer, doneq_index);
36517a7bc959SXin LI 		if (poll_srb != NULL)
36527a7bc959SXin LI 			poll_srb_done = (srb == poll_srb) ? 1:0;
36537a7bc959SXin LI 		if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
36547a7bc959SXin LI 			if(srb->srb_state == ARCMSR_SRB_ABORTED) {
3655123055f0SNathan Whitehorn 				printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n"
3656123055f0SNathan Whitehorn 						, acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
36577a7bc959SXin LI 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
36587a7bc959SXin LI 				arcmsr_srb_complete(srb, 1);
36597a7bc959SXin LI 				continue;
36607a7bc959SXin LI 			}
36617a7bc959SXin LI 			printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n"
36627a7bc959SXin LI 					, acb->pci_unit, srb, acb->srboutstandingcount);
36637a7bc959SXin LI 			continue;
36647a7bc959SXin LI 		}
36657a7bc959SXin LI 		arcmsr_report_srb_state(acb, srb, error);
36667a7bc959SXin LI 	}	/*drain reply FIFO*/
36677a7bc959SXin LI }
36687a7bc959SXin LI /*
36697a7bc959SXin LI **********************************************************************
3670a1103e04SXin LI **
3671a1103e04SXin LI **********************************************************************
3672a1103e04SXin LI */
3673a1103e04SXin LI static void arcmsr_polling_hbe_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
3674a1103e04SXin LI {
3675a1103e04SXin LI 	struct CommandControlBlock *srb;
3676a1103e04SXin LI 	u_int32_t poll_srb_done=0, poll_count=0, doneq_index;
3677a1103e04SXin LI 	u_int16_t	error, cmdSMID;
3678a1103e04SXin LI 
3679a1103e04SXin LI polling_ccb_retry:
3680a1103e04SXin LI 	poll_count++;
3681a1103e04SXin LI 	bus_dmamap_sync(acb->srb_dmat, acb->srb_dmamap, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
3682a1103e04SXin LI 	while(1) {
3683a1103e04SXin LI 		doneq_index = acb->doneq_index;
3684a1103e04SXin LI 		if((CHIP_REG_READ32(HBE_MessageUnit, 0, reply_post_producer_index) & 0xFFFF) == doneq_index) {
3685a1103e04SXin LI 			if(poll_srb_done) {
3686a1103e04SXin LI 				break;/*chip FIFO no ccb for completion already*/
3687a1103e04SXin LI 			} else {
3688a1103e04SXin LI 				UDELAY(25000);
3689a1103e04SXin LI 				if ((poll_count > 100) && (poll_srb != NULL)) {
3690a1103e04SXin LI 					break;
3691a1103e04SXin LI 				}
3692a1103e04SXin LI 				if (acb->srboutstandingcount == 0) {
3693a1103e04SXin LI 					break;
3694a1103e04SXin LI 				}
3695a1103e04SXin LI 				goto polling_ccb_retry;
3696a1103e04SXin LI 			}
3697a1103e04SXin LI 		}
3698a1103e04SXin LI 		cmdSMID = acb->pCompletionQ[doneq_index].cmdSMID;
3699a1103e04SXin LI 		doneq_index++;
3700a1103e04SXin LI 		if (doneq_index >= acb->completionQ_entry)
3701a1103e04SXin LI 			doneq_index = 0;
3702a1103e04SXin LI 		acb->doneq_index = doneq_index;
3703a1103e04SXin LI 		srb = acb->psrb_pool[cmdSMID];
3704a1103e04SXin LI 		error = (acb->pCompletionQ[doneq_index].cmdFlag & ARCMSR_SRBREPLY_FLAG_ERROR_MODE1) ? TRUE : FALSE;
3705a1103e04SXin LI 		if (poll_srb != NULL)
3706a1103e04SXin LI 			poll_srb_done = (srb == poll_srb) ? 1:0;
3707a1103e04SXin LI 		if((srb->acb != acb) || (srb->srb_state != ARCMSR_SRB_START)) {
3708a1103e04SXin LI 			if(srb->srb_state == ARCMSR_SRB_ABORTED) {
3709a1103e04SXin LI 				printf("arcmsr%d: scsi id=%d lun=%jx srb='%p'poll command abort successfully \n"
3710a1103e04SXin LI 						, acb->pci_unit, srb->pccb->ccb_h.target_id, (uintmax_t)srb->pccb->ccb_h.target_lun, srb);
3711a1103e04SXin LI 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
3712a1103e04SXin LI 				arcmsr_srb_complete(srb, 1);
3713a1103e04SXin LI 				continue;
3714a1103e04SXin LI 			}
3715a1103e04SXin LI 			printf("arcmsr%d: polling get an illegal srb command done srb='%p'srboutstandingcount=%d \n"
3716a1103e04SXin LI 					, acb->pci_unit, srb, acb->srboutstandingcount);
3717a1103e04SXin LI 			continue;
3718a1103e04SXin LI 		}
3719a1103e04SXin LI 		arcmsr_report_srb_state(acb, srb, error);
3720a1103e04SXin LI 	}	/*drain reply FIFO*/
3721a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, reply_post_producer_index, doneq_index);
3722a1103e04SXin LI }
3723a1103e04SXin LI /*
3724a1103e04SXin LI **********************************************************************
372544f05562SScott Long **********************************************************************
372644f05562SScott Long */
372744f05562SScott Long static void arcmsr_polling_srbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_srb)
372844f05562SScott Long {
372944f05562SScott Long 	switch (acb->adapter_type) {
3730fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_A:
373144f05562SScott Long 		arcmsr_polling_hba_srbdone(acb, poll_srb);
373244f05562SScott Long 		break;
3733fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_B:
373444f05562SScott Long 		arcmsr_polling_hbb_srbdone(acb, poll_srb);
373544f05562SScott Long 		break;
3736fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_C:
3737d74001adSXin LI 		arcmsr_polling_hbc_srbdone(acb, poll_srb);
3738d74001adSXin LI 		break;
3739fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_D:
37407a7bc959SXin LI 		arcmsr_polling_hbd_srbdone(acb, poll_srb);
37417a7bc959SXin LI 		break;
3742fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
3743fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F:
3744a1103e04SXin LI 		arcmsr_polling_hbe_srbdone(acb, poll_srb);
3745a1103e04SXin LI 		break;
374644f05562SScott Long 	}
374744f05562SScott Long }
374844f05562SScott Long /*
374944f05562SScott Long **********************************************************************
375044f05562SScott Long **********************************************************************
375144f05562SScott Long */
375244f05562SScott Long static void arcmsr_get_hba_config(struct AdapterControlBlock *acb)
3753ad6d6297SScott Long {
3754ad6d6297SScott Long 	char *acb_firm_model = acb->firm_model;
3755ad6d6297SScott Long 	char *acb_firm_version = acb->firm_version;
3756d74001adSXin LI 	char *acb_device_map = acb->device_map;
3757d74001adSXin LI 	size_t iop_firm_model = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);	/*firm_model,15,60-67*/
3758d74001adSXin LI 	size_t iop_firm_version = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]);	/*firm_version,17,68-83*/
3759d74001adSXin LI 	size_t iop_device_map = offsetof(struct HBA_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
3760ad6d6297SScott Long 	int i;
3761ad6d6297SScott Long 
376244f05562SScott Long 	CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
376344f05562SScott Long 	if(!arcmsr_hba_wait_msgint_ready(acb)) {
3764d74001adSXin LI 		printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
3765ad6d6297SScott Long 	}
3766ad6d6297SScott Long 	i = 0;
3767ad6d6297SScott Long 	while(i < 8) {
376844f05562SScott Long 		*acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i);
3769ad6d6297SScott Long 		/* 8 bytes firm_model, 15, 60-67*/
3770ad6d6297SScott Long 		acb_firm_model++;
3771ad6d6297SScott Long 		i++;
3772ad6d6297SScott Long 	}
3773ad6d6297SScott Long 	i=0;
3774ad6d6297SScott Long 	while(i < 16) {
377544f05562SScott Long 		*acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i);
3776ad6d6297SScott Long 		/* 16 bytes firm_version, 17, 68-83*/
3777ad6d6297SScott Long 		acb_firm_version++;
3778ad6d6297SScott Long 		i++;
3779ad6d6297SScott Long 	}
3780d74001adSXin LI 	i=0;
3781d74001adSXin LI 	while(i < 16) {
3782d74001adSXin LI 		*acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i);
3783d74001adSXin LI 		acb_device_map++;
3784d74001adSXin LI 		i++;
3785d74001adSXin LI 	}
37861e7d660aSXin LI 	printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version);
3787d74001adSXin LI 	acb->firm_request_len = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[1]);   /*firm_request_len, 1, 04-07*/
3788d74001adSXin LI 	acb->firm_numbers_queue = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/
3789d74001adSXin LI 	acb->firm_sdram_size = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[3]);    /*firm_sdram_size, 3, 12-15*/
3790d74001adSXin LI 	acb->firm_ide_channels = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[4]);  /*firm_ide_channels, 4, 16-19*/
3791d74001adSXin LI 	acb->firm_cfg_version = CHIP_REG_READ32(HBA_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);	/*firm_cfg_version,  25, 	  */
3792abfdbca9SXin LI 	if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD)
3793abfdbca9SXin LI 		acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1;
3794abfdbca9SXin LI 	else
3795abfdbca9SXin LI 		acb->maxOutstanding = acb->firm_numbers_queue - 1;
3796ad6d6297SScott Long }
3797ad6d6297SScott Long /*
3798ad6d6297SScott Long **********************************************************************
379944f05562SScott Long **********************************************************************
380044f05562SScott Long */
380144f05562SScott Long static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb)
380244f05562SScott Long {
3803b23a1998SXin LI 	struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
380444f05562SScott Long 	char *acb_firm_model = acb->firm_model;
380544f05562SScott Long 	char *acb_firm_version = acb->firm_version;
3806d74001adSXin LI 	char *acb_device_map = acb->device_map;
3807d74001adSXin LI 	size_t iop_firm_model = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);	/*firm_model,15,60-67*/
3808d74001adSXin LI 	size_t iop_firm_version = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]);	/*firm_version,17,68-83*/
3809d74001adSXin LI 	size_t iop_device_map = offsetof(struct HBB_RWBUFFER, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
381044f05562SScott Long 	int i;
381144f05562SScott Long 
3812b23a1998SXin LI 	WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_GET_CONFIG);
381344f05562SScott Long 	if(!arcmsr_hbb_wait_msgint_ready(acb)) {
3814d74001adSXin LI 		printf( "arcmsr%d: wait" "'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
381544f05562SScott Long 	}
381644f05562SScott Long 	i = 0;
381744f05562SScott Long 	while(i < 8) {
381844f05562SScott Long 		*acb_firm_model = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_model+i);
381944f05562SScott Long 		/* 8 bytes firm_model, 15, 60-67*/
382044f05562SScott Long 		acb_firm_model++;
382144f05562SScott Long 		i++;
382244f05562SScott Long 	}
382344f05562SScott Long 	i = 0;
382444f05562SScott Long 	while(i < 16) {
382544f05562SScott Long 		*acb_firm_version = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_firm_version+i);
382644f05562SScott Long 		/* 16 bytes firm_version, 17, 68-83*/
382744f05562SScott Long 		acb_firm_version++;
382844f05562SScott Long 		i++;
382944f05562SScott Long 	}
3830d74001adSXin LI 	i = 0;
3831d74001adSXin LI 	while(i < 16) {
3832d74001adSXin LI 		*acb_device_map = bus_space_read_1(acb->btag[1], acb->bhandle[1], iop_device_map+i);
3833d74001adSXin LI 		acb_device_map++;
3834d74001adSXin LI 		i++;
3835d74001adSXin LI 	}
38361e7d660aSXin LI 	printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version);
3837d74001adSXin LI 	acb->firm_request_len = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1]);   /*firm_request_len, 1, 04-07*/
3838d74001adSXin LI 	acb->firm_numbers_queue = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2]); /*firm_numbers_queue, 2, 08-11*/
3839d74001adSXin LI 	acb->firm_sdram_size = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3]);    /*firm_sdram_size, 3, 12-15*/
3840d74001adSXin LI 	acb->firm_ide_channels = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4]);  /*firm_ide_channels, 4, 16-19*/
3841d74001adSXin LI 	acb->firm_cfg_version = CHIP_REG_READ32(HBB_RWBUFFER, 1, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);	/*firm_cfg_version,  25, 	  */
3842abfdbca9SXin LI 	if(acb->firm_numbers_queue > ARCMSR_MAX_HBB_POSTQUEUE)
3843abfdbca9SXin LI 		acb->maxOutstanding = ARCMSR_MAX_HBB_POSTQUEUE - 1;
3844abfdbca9SXin LI 	else
3845abfdbca9SXin LI 		acb->maxOutstanding = acb->firm_numbers_queue - 1;
3846d74001adSXin LI }
3847d74001adSXin LI /*
3848d74001adSXin LI **********************************************************************
3849d74001adSXin LI **********************************************************************
3850d74001adSXin LI */
3851d74001adSXin LI static void arcmsr_get_hbc_config(struct AdapterControlBlock *acb)
3852d74001adSXin LI {
3853d74001adSXin LI 	char *acb_firm_model = acb->firm_model;
3854d74001adSXin LI 	char *acb_firm_version = acb->firm_version;
3855d74001adSXin LI 	char *acb_device_map = acb->device_map;
3856d74001adSXin LI 	size_t iop_firm_model = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);   /*firm_model,15,60-67*/
3857d74001adSXin LI 	size_t iop_firm_version = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/
3858d74001adSXin LI 	size_t iop_device_map = offsetof(struct HBC_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
3859d74001adSXin LI 	int i;
3860d74001adSXin LI 
3861d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
3862d74001adSXin LI 	CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
3863d74001adSXin LI 	if(!arcmsr_hbc_wait_msgint_ready(acb)) {
3864d74001adSXin LI 		printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
3865d74001adSXin LI 	}
3866d74001adSXin LI 	i = 0;
3867d74001adSXin LI 	while(i < 8) {
3868d74001adSXin LI 		*acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i);
3869d74001adSXin LI 		/* 8 bytes firm_model, 15, 60-67*/
3870d74001adSXin LI 		acb_firm_model++;
3871d74001adSXin LI 		i++;
3872d74001adSXin LI 	}
3873d74001adSXin LI 	i = 0;
3874d74001adSXin LI 	while(i < 16) {
3875d74001adSXin LI 		*acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i);
3876d74001adSXin LI 		/* 16 bytes firm_version, 17, 68-83*/
3877d74001adSXin LI 		acb_firm_version++;
3878d74001adSXin LI 		i++;
3879d74001adSXin LI 	}
3880d74001adSXin LI 	i = 0;
3881d74001adSXin LI 	while(i < 16) {
3882d74001adSXin LI 		*acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i);
3883d74001adSXin LI 		acb_device_map++;
3884d74001adSXin LI 		i++;
3885d74001adSXin LI 	}
38861e7d660aSXin LI 	printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version);
3887d74001adSXin LI 	acb->firm_request_len	= CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[1]);	/*firm_request_len,   1, 04-07*/
3888d74001adSXin LI 	acb->firm_numbers_queue	= CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[2]);	/*firm_numbers_queue, 2, 08-11*/
3889d74001adSXin LI 	acb->firm_sdram_size	= CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[3]);	/*firm_sdram_size,    3, 12-15*/
3890d74001adSXin LI 	acb->firm_ide_channels	= CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[4]);	/*firm_ide_channels,  4, 16-19*/
3891d74001adSXin LI 	acb->firm_cfg_version	= CHIP_REG_READ32(HBC_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);	/*firm_cfg_version,  25, 	  */
3892abfdbca9SXin LI 	if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD)
3893abfdbca9SXin LI 		acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1;
3894abfdbca9SXin LI 	else
3895abfdbca9SXin LI 		acb->maxOutstanding = acb->firm_numbers_queue - 1;
389644f05562SScott Long }
389744f05562SScott Long /*
389844f05562SScott Long **********************************************************************
389944f05562SScott Long **********************************************************************
390044f05562SScott Long */
39017a7bc959SXin LI static void arcmsr_get_hbd_config(struct AdapterControlBlock *acb)
39027a7bc959SXin LI {
39037a7bc959SXin LI 	char *acb_firm_model = acb->firm_model;
39047a7bc959SXin LI 	char *acb_firm_version = acb->firm_version;
39057a7bc959SXin LI 	char *acb_device_map = acb->device_map;
39067a7bc959SXin LI 	size_t iop_firm_model = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);   /*firm_model,15,60-67*/
39077a7bc959SXin LI 	size_t iop_firm_version = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/
39087a7bc959SXin LI 	size_t iop_device_map = offsetof(struct HBD_MessageUnit, msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
39097a7bc959SXin LI 	int i;
39107a7bc959SXin LI 
39117a7bc959SXin LI 	if(CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell) & ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE)
39127a7bc959SXin LI 		CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, ARCMSR_HBDMU_IOP2DRV_MESSAGE_CMD_DONE_CLEAR);
39137a7bc959SXin LI 	CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
39147a7bc959SXin LI 	if(!arcmsr_hbd_wait_msgint_ready(acb)) {
39157a7bc959SXin LI 		printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
39167a7bc959SXin LI 	}
39177a7bc959SXin LI 	i = 0;
39187a7bc959SXin LI 	while(i < 8) {
39197a7bc959SXin LI 		*acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i);
39207a7bc959SXin LI 		/* 8 bytes firm_model, 15, 60-67*/
39217a7bc959SXin LI 		acb_firm_model++;
39227a7bc959SXin LI 		i++;
39237a7bc959SXin LI 	}
39247a7bc959SXin LI 	i = 0;
39257a7bc959SXin LI 	while(i < 16) {
39267a7bc959SXin LI 		*acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i);
39277a7bc959SXin LI 		/* 16 bytes firm_version, 17, 68-83*/
39287a7bc959SXin LI 		acb_firm_version++;
39297a7bc959SXin LI 		i++;
39307a7bc959SXin LI 	}
39317a7bc959SXin LI 	i = 0;
39327a7bc959SXin LI 	while(i < 16) {
39337a7bc959SXin LI 		*acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i);
39347a7bc959SXin LI 		acb_device_map++;
39357a7bc959SXin LI 		i++;
39367a7bc959SXin LI 	}
39371e7d660aSXin LI 	printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version);
3938b23a1998SXin LI 	acb->firm_request_len	= CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[1]);	/*firm_request_len,   1, 04-07*/
3939b23a1998SXin LI 	acb->firm_numbers_queue	= CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[2]);	/*firm_numbers_queue, 2, 08-11*/
3940b23a1998SXin LI 	acb->firm_sdram_size	= CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[3]);	/*firm_sdram_size,    3, 12-15*/
3941b23a1998SXin LI 	acb->firm_ide_channels	= CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[4]);	/*firm_ide_channels,  4, 16-19*/
39427a7bc959SXin LI 	acb->firm_cfg_version	= CHIP_REG_READ32(HBD_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);	/*firm_cfg_version,  25, 	  */
3943abfdbca9SXin LI 	if(acb->firm_numbers_queue > ARCMSR_MAX_HBD_POSTQUEUE)
3944abfdbca9SXin LI 		acb->maxOutstanding = ARCMSR_MAX_HBD_POSTQUEUE - 1;
3945abfdbca9SXin LI 	else
3946abfdbca9SXin LI 		acb->maxOutstanding = acb->firm_numbers_queue - 1;
39477a7bc959SXin LI }
39487a7bc959SXin LI /*
39497a7bc959SXin LI **********************************************************************
39507a7bc959SXin LI **********************************************************************
39517a7bc959SXin LI */
3952a1103e04SXin LI static void arcmsr_get_hbe_config(struct AdapterControlBlock *acb)
3953a1103e04SXin LI {
3954a1103e04SXin LI 	char *acb_firm_model = acb->firm_model;
3955a1103e04SXin LI 	char *acb_firm_version = acb->firm_version;
3956a1103e04SXin LI 	char *acb_device_map = acb->device_map;
3957a1103e04SXin LI 	size_t iop_firm_model = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_MODEL_OFFSET]);   /*firm_model,15,60-67*/
3958a1103e04SXin LI 	size_t iop_firm_version = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_VERS_OFFSET]); /*firm_version,17,68-83*/
3959a1103e04SXin LI 	size_t iop_device_map = offsetof(struct HBE_MessageUnit,msgcode_rwbuffer[ARCMSR_FW_DEVMAP_OFFSET]);
3960a1103e04SXin LI 	int i;
3961a1103e04SXin LI 
3962a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
3963a1103e04SXin LI 	acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
3964a1103e04SXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
3965a1103e04SXin LI 	if(!arcmsr_hbe_wait_msgint_ready(acb)) {
3966a1103e04SXin LI 		printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
3967a1103e04SXin LI 	}
3968a1103e04SXin LI 
3969a1103e04SXin LI 	i = 0;
3970a1103e04SXin LI 	while(i < 8) {
3971a1103e04SXin LI 		*acb_firm_model = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_model+i);
3972a1103e04SXin LI 		/* 8 bytes firm_model, 15, 60-67*/
3973a1103e04SXin LI 		acb_firm_model++;
3974a1103e04SXin LI 		i++;
3975a1103e04SXin LI 	}
3976a1103e04SXin LI 	i = 0;
3977a1103e04SXin LI 	while(i < 16) {
3978a1103e04SXin LI 		*acb_firm_version = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_firm_version+i);
3979a1103e04SXin LI 		/* 16 bytes firm_version, 17, 68-83*/
3980a1103e04SXin LI 		acb_firm_version++;
3981a1103e04SXin LI 		i++;
3982a1103e04SXin LI 	}
3983a1103e04SXin LI 	i = 0;
3984a1103e04SXin LI 	while(i < 16) {
3985a1103e04SXin LI 		*acb_device_map = bus_space_read_1(acb->btag[0], acb->bhandle[0], iop_device_map+i);
3986a1103e04SXin LI 		acb_device_map++;
3987a1103e04SXin LI 		i++;
3988a1103e04SXin LI 	}
3989a1103e04SXin LI 	printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version);
3990a1103e04SXin LI 	acb->firm_request_len	= CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[1]);	/*firm_request_len,   1, 04-07*/
3991a1103e04SXin LI 	acb->firm_numbers_queue	= CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[2]);	/*firm_numbers_queue, 2, 08-11*/
3992a1103e04SXin LI 	acb->firm_sdram_size	= CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[3]);	/*firm_sdram_size,    3, 12-15*/
3993a1103e04SXin LI 	acb->firm_ide_channels	= CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[4]);	/*firm_ide_channels,  4, 16-19*/
3994a1103e04SXin LI 	acb->firm_cfg_version	= CHIP_REG_READ32(HBE_MessageUnit, 0, msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]);	/*firm_cfg_version,  25, 	  */
3995a1103e04SXin LI 	if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD)
3996a1103e04SXin LI 		acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1;
3997a1103e04SXin LI 	else
3998a1103e04SXin LI 		acb->maxOutstanding = acb->firm_numbers_queue - 1;
3999a1103e04SXin LI }
4000a1103e04SXin LI /*
4001a1103e04SXin LI **********************************************************************
4002a1103e04SXin LI **********************************************************************
4003a1103e04SXin LI */
4004fa42a0bfSXin LI static void arcmsr_get_hbf_config(struct AdapterControlBlock *acb)
4005fa42a0bfSXin LI {
4006fa42a0bfSXin LI 	u_int32_t *acb_firm_model = (u_int32_t *)acb->firm_model;
4007fa42a0bfSXin LI 	u_int32_t *acb_firm_version = (u_int32_t *)acb->firm_version;
4008fa42a0bfSXin LI 	u_int32_t *acb_device_map = (u_int32_t *)acb->device_map;
4009fa42a0bfSXin LI 	size_t iop_firm_model = ARCMSR_FW_MODEL_OFFSET;   /*firm_model,15,60-67*/
4010fa42a0bfSXin LI 	size_t iop_firm_version = ARCMSR_FW_VERS_OFFSET; /*firm_version,17,68-83*/
4011fa42a0bfSXin LI 	size_t iop_device_map = ARCMSR_FW_DEVMAP_OFFSET;
4012fa42a0bfSXin LI 	int i;
4013fa42a0bfSXin LI 
4014fa42a0bfSXin LI 	CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_GET_CONFIG);
4015fa42a0bfSXin LI 	acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
4016fa42a0bfSXin LI 	CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
4017fa42a0bfSXin LI 	if(!arcmsr_hbe_wait_msgint_ready(acb))
4018fa42a0bfSXin LI 		printf("arcmsr%d: wait 'get adapter firmware miscellaneous data' timeout \n", acb->pci_unit);
4019fa42a0bfSXin LI 
4020fa42a0bfSXin LI 	i = 0;
4021fa42a0bfSXin LI 	while(i < 2) {
4022fa42a0bfSXin LI 		*acb_firm_model = acb->msgcode_rwbuffer[iop_firm_model];
4023fa42a0bfSXin LI 		/* 8 bytes firm_model, 15, 60-67*/
4024fa42a0bfSXin LI 		acb_firm_model++;
4025fa42a0bfSXin LI 		iop_firm_model++;
4026fa42a0bfSXin LI 		i++;
4027fa42a0bfSXin LI 	}
4028fa42a0bfSXin LI 	i = 0;
4029fa42a0bfSXin LI 	while(i < 4) {
4030fa42a0bfSXin LI 		*acb_firm_version = acb->msgcode_rwbuffer[iop_firm_version];
4031fa42a0bfSXin LI 		/* 16 bytes firm_version, 17, 68-83*/
4032fa42a0bfSXin LI 		acb_firm_version++;
4033fa42a0bfSXin LI 		iop_firm_version++;
4034fa42a0bfSXin LI 		i++;
4035fa42a0bfSXin LI 	}
4036fa42a0bfSXin LI 	i = 0;
4037fa42a0bfSXin LI 	while(i < 4) {
4038fa42a0bfSXin LI 		*acb_device_map = acb->msgcode_rwbuffer[iop_device_map];
4039fa42a0bfSXin LI 		acb_device_map++;
4040fa42a0bfSXin LI 		iop_device_map++;
4041fa42a0bfSXin LI 		i++;
4042fa42a0bfSXin LI 	}
4043fa42a0bfSXin LI 	printf("Areca RAID adapter%d: %s F/W version %s \n", acb->pci_unit, acb->firm_model, acb->firm_version);
4044fa42a0bfSXin LI 	acb->firm_request_len	= acb->msgcode_rwbuffer[1];	/*firm_request_len,   1, 04-07*/
4045fa42a0bfSXin LI 	acb->firm_numbers_queue	= acb->msgcode_rwbuffer[2];	/*firm_numbers_queue, 2, 08-11*/
4046fa42a0bfSXin LI 	acb->firm_sdram_size	= acb->msgcode_rwbuffer[3];	/*firm_sdram_size,    3, 12-15*/
4047fa42a0bfSXin LI 	acb->firm_ide_channels	= acb->msgcode_rwbuffer[4];	/*firm_ide_channels,  4, 16-19*/
4048fa42a0bfSXin LI 	acb->firm_cfg_version	= acb->msgcode_rwbuffer[ARCMSR_FW_CFGVER_OFFSET]; /*firm_cfg_version,  25*/
4049fa42a0bfSXin LI 	if(acb->firm_numbers_queue > ARCMSR_MAX_OUTSTANDING_CMD)
4050fa42a0bfSXin LI 		acb->maxOutstanding = ARCMSR_MAX_OUTSTANDING_CMD - 1;
4051fa42a0bfSXin LI 	else
4052fa42a0bfSXin LI 		acb->maxOutstanding = acb->firm_numbers_queue - 1;
4053fa42a0bfSXin LI }
4054fa42a0bfSXin LI /*
4055fa42a0bfSXin LI **********************************************************************
4056fa42a0bfSXin LI **********************************************************************
4057fa42a0bfSXin LI */
405844f05562SScott Long static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb)
405944f05562SScott Long {
406044f05562SScott Long 	switch (acb->adapter_type) {
4061fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_A:
406244f05562SScott Long 		arcmsr_get_hba_config(acb);
406344f05562SScott Long 		break;
4064fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_B:
406544f05562SScott Long 		arcmsr_get_hbb_config(acb);
406644f05562SScott Long 		break;
4067fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_C:
4068d74001adSXin LI 		arcmsr_get_hbc_config(acb);
4069d74001adSXin LI 		break;
4070fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_D:
40717a7bc959SXin LI 		arcmsr_get_hbd_config(acb);
40727a7bc959SXin LI 		break;
4073fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
4074a1103e04SXin LI 		arcmsr_get_hbe_config(acb);
4075fa42a0bfSXin LI 		break;
4076fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F:
4077fa42a0bfSXin LI 		arcmsr_get_hbf_config(acb);
4078a1103e04SXin LI 		break;
407944f05562SScott Long 	}
408044f05562SScott Long }
408144f05562SScott Long /*
408244f05562SScott Long **********************************************************************
408344f05562SScott Long **********************************************************************
408444f05562SScott Long */
408544f05562SScott Long static void arcmsr_wait_firmware_ready( struct AdapterControlBlock *acb)
408644f05562SScott Long {
408744f05562SScott Long 	int	timeout=0;
408844f05562SScott Long 
408944f05562SScott Long 	switch (acb->adapter_type) {
409044f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
4091d74001adSXin LI 			while ((CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0)
409244f05562SScott Long 			{
409344f05562SScott Long 				if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */
409444f05562SScott Long 				{
4095d74001adSXin LI 					printf( "arcmsr%d:timed out waiting for firmware \n", acb->pci_unit);
409644f05562SScott Long 					return;
409744f05562SScott Long 				}
409844f05562SScott Long 				UDELAY(15000); /* wait 15 milli-seconds */
409944f05562SScott Long 			}
410044f05562SScott Long 		}
410144f05562SScott Long 		break;
410244f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
4103b23a1998SXin LI 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
4104b23a1998SXin LI 			while ((READ_CHIP_REG32(0, phbbmu->iop2drv_doorbell) & ARCMSR_MESSAGE_FIRMWARE_OK) == 0)
410544f05562SScott Long 			{
410644f05562SScott Long 				if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */
410744f05562SScott Long 				{
4108d74001adSXin LI 					printf( "arcmsr%d: timed out waiting for firmware \n", acb->pci_unit);
410944f05562SScott Long 					return;
411044f05562SScott Long 				}
411144f05562SScott Long 				UDELAY(15000); /* wait 15 milli-seconds */
411244f05562SScott Long 			}
4113b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_END_OF_INTERRUPT);
4114d74001adSXin LI 		}
4115d74001adSXin LI 		break;
4116d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
4117d74001adSXin LI 			while ((CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBCMU_MESSAGE_FIRMWARE_OK) == 0)
4118d74001adSXin LI 			{
4119d74001adSXin LI 				if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */
4120d74001adSXin LI 				{
4121d74001adSXin LI 					printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit);
4122d74001adSXin LI 					return;
4123d74001adSXin LI 				}
4124d74001adSXin LI 				UDELAY(15000); /* wait 15 milli-seconds */
4125d74001adSXin LI 			}
412644f05562SScott Long 		}
412744f05562SScott Long 		break;
41287a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
41297a7bc959SXin LI 			while ((CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBDMU_MESSAGE_FIRMWARE_OK) == 0)
41307a7bc959SXin LI 			{
41317a7bc959SXin LI 				if (timeout++ > 2000) /* (2000*15)/1000 = 30 sec */
41327a7bc959SXin LI 				{
41337a7bc959SXin LI 					printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit);
41347a7bc959SXin LI 					return;
41357a7bc959SXin LI 				}
41367a7bc959SXin LI 				UDELAY(15000); /* wait 15 milli-seconds */
41377a7bc959SXin LI 			}
41387a7bc959SXin LI 		}
41397a7bc959SXin LI 		break;
4140fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
4141fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
4142a1103e04SXin LI 			while ((CHIP_REG_READ32(HBE_MessageUnit, 0, outbound_msgaddr1) & ARCMSR_HBEMU_MESSAGE_FIRMWARE_OK) == 0)
4143a1103e04SXin LI 			{
4144a1103e04SXin LI 				if (timeout++ > 4000) /* (4000*15)/1000 = 60 sec */
4145a1103e04SXin LI 				{
4146a1103e04SXin LI 					printf( "arcmsr%d:timed out waiting for firmware ready\n", acb->pci_unit);
4147a1103e04SXin LI 					return;
4148a1103e04SXin LI 				}
4149a1103e04SXin LI 				UDELAY(15000); /* wait 15 milli-seconds */
4150a1103e04SXin LI 			}
4151a1103e04SXin LI 		}
4152a1103e04SXin LI 		break;
415344f05562SScott Long 	}
415444f05562SScott Long }
415544f05562SScott Long /*
415644f05562SScott Long **********************************************************************
415744f05562SScott Long **********************************************************************
415844f05562SScott Long */
415944f05562SScott Long static void arcmsr_clear_doorbell_queue_buffer( struct AdapterControlBlock *acb)
416044f05562SScott Long {
4161d74001adSXin LI 	u_int32_t outbound_doorbell;
4162d74001adSXin LI 
416344f05562SScott Long 	switch (acb->adapter_type) {
416444f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
416544f05562SScott Long 			/* empty doorbell Qbuffer if door bell ringed */
4166d74001adSXin LI 			outbound_doorbell = CHIP_REG_READ32(HBA_MessageUnit, 0, outbound_doorbell);
4167d74001adSXin LI 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, outbound_doorbell, outbound_doorbell);	/*clear doorbell interrupt */
4168d74001adSXin LI 			CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_doorbell, ARCMSR_INBOUND_DRIVER_DATA_READ_OK);
416944f05562SScott Long 		}
417044f05562SScott Long 		break;
417144f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
4172b23a1998SXin LI 			struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
4173fc5ef1caSXin LI 			WRITE_CHIP_REG32(0, phbbmu->iop2drv_doorbell, ARCMSR_DOORBELL_INT_CLEAR_PATTERN);/*clear interrupt and message state*/
4174b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_DRV2IOP_DATA_READ_OK);
417544f05562SScott Long 			/* let IOP know data has been read */
417644f05562SScott Long 		}
417744f05562SScott Long 		break;
4178d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
4179d74001adSXin LI 			/* empty doorbell Qbuffer if door bell ringed */
4180d74001adSXin LI 			outbound_doorbell = CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell);
4181d74001adSXin LI 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, outbound_doorbell_clear, outbound_doorbell);	/*clear doorbell interrupt */
4182d74001adSXin LI 			CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell, ARCMSR_HBCMU_DRV2IOP_DATA_READ_OK);
41837a7bc959SXin LI 			CHIP_REG_READ32(HBC_MessageUnit, 0, outbound_doorbell_clear); /* Dummy read to force pci flush */
41847a7bc959SXin LI 			CHIP_REG_READ32(HBC_MessageUnit, 0, inbound_doorbell); /* Dummy read to force pci flush */
41857a7bc959SXin LI 		}
41867a7bc959SXin LI 		break;
41877a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
41887a7bc959SXin LI 			/* empty doorbell Qbuffer if door bell ringed */
41897a7bc959SXin LI 			outbound_doorbell = CHIP_REG_READ32(HBD_MessageUnit, 0, outbound_doorbell);
41907a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, outbound_doorbell, outbound_doorbell);	/*clear doorbell interrupt */
41917a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_doorbell, ARCMSR_HBDMU_DRV2IOP_DATA_OUT_READ);
4192d74001adSXin LI 		}
4193d74001adSXin LI 		break;
4194fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_E:
4195fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
4196a1103e04SXin LI 			/* empty doorbell Qbuffer if door bell ringed */
4197a1103e04SXin LI 			acb->in_doorbell = CHIP_REG_READ32(HBE_MessageUnit, 0, iobound_doorbell);
4198a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0);	/*clear doorbell interrupt */
4199a1103e04SXin LI 			acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_DATA_READ_OK;
4200a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
4201a1103e04SXin LI 		}
4202a1103e04SXin LI 		break;
420344f05562SScott Long 	}
420444f05562SScott Long }
420544f05562SScott Long /*
420644f05562SScott Long ************************************************************************
420744f05562SScott Long ************************************************************************
420844f05562SScott Long */
420944f05562SScott Long static u_int32_t arcmsr_iop_confirm(struct AdapterControlBlock *acb)
421044f05562SScott Long {
421144f05562SScott Long 	unsigned long srb_phyaddr;
421244f05562SScott Long 	u_int32_t srb_phyaddr_hi32;
42137a7bc959SXin LI 	u_int32_t srb_phyaddr_lo32;
421444f05562SScott Long 
421544f05562SScott Long 	/*
421644f05562SScott Long 	********************************************************************
421744f05562SScott Long 	** here we need to tell iop 331 our freesrb.HighPart
421844f05562SScott Long 	** if freesrb.HighPart is not zero
421944f05562SScott Long 	********************************************************************
422044f05562SScott Long 	*/
4221d74001adSXin LI 	srb_phyaddr = (unsigned long) acb->srb_phyaddr.phyaddr;
4222d74001adSXin LI 	srb_phyaddr_hi32 = acb->srb_phyaddr.B.phyadd_high;
42237a7bc959SXin LI 	srb_phyaddr_lo32 = acb->srb_phyaddr.B.phyadd_low;
422444f05562SScott Long 	switch (acb->adapter_type) {
422544f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
422644f05562SScott Long 			if(srb_phyaddr_hi32 != 0) {
4227d74001adSXin LI 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG);
4228d74001adSXin LI 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32);
4229d74001adSXin LI 				CHIP_REG_WRITE32(HBA_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
423044f05562SScott Long 				if(!arcmsr_hba_wait_msgint_ready(acb)) {
4231d74001adSXin LI 					printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit);
423244f05562SScott Long 					return FALSE;
423344f05562SScott Long 				}
423444f05562SScott Long 			}
423544f05562SScott Long 		}
423644f05562SScott Long 		break;
423744f05562SScott Long 		/*
423844f05562SScott Long 		***********************************************************************
423944f05562SScott Long 		**    if adapter type B, set window of "post command Q"
424044f05562SScott Long 		***********************************************************************
424144f05562SScott Long 		*/
424244f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
424344f05562SScott Long 			u_int32_t post_queue_phyaddr;
424444f05562SScott Long 			struct HBB_MessageUnit *phbbmu;
424544f05562SScott Long 
424644f05562SScott Long 			phbbmu = (struct HBB_MessageUnit *)acb->pmu;
424744f05562SScott Long 			phbbmu->postq_index = 0;
424844f05562SScott Long 			phbbmu->doneq_index = 0;
4249b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_SET_POST_WINDOW);
425044f05562SScott Long 			if(!arcmsr_hbb_wait_msgint_ready(acb)) {
4251d74001adSXin LI 				printf( "arcmsr%d: 'set window of post command Q' timeout\n", acb->pci_unit);
425244f05562SScott Long 				return FALSE;
425344f05562SScott Long 			}
425422f2616bSXin LI 			post_queue_phyaddr = srb_phyaddr + ARCMSR_SRBS_POOL_SIZE
425544f05562SScott Long 								+ offsetof(struct HBB_MessageUnit, post_qbuffer);
4256d74001adSXin LI 			CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */
4257d74001adSXin LI 			CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[1], srb_phyaddr_hi32); /* normal should be zero */
4258d74001adSXin LI 			CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ size (256+8)*4 */
4259d74001adSXin LI 			CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[3], post_queue_phyaddr+1056); /* doneQ size (256+8)*4 */
4260d74001adSXin LI 			CHIP_REG_WRITE32(HBB_RWBUFFER, 1, msgcode_rwbuffer[4], 1056); /* srb maxQ size must be --> [(256+8)*4] */
4261b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_SET_CONFIG);
426244f05562SScott Long 			if(!arcmsr_hbb_wait_msgint_ready(acb)) {
426344f05562SScott Long 				printf( "arcmsr%d: 'set command Q window' timeout \n", acb->pci_unit);
426444f05562SScott Long 				return FALSE;
426544f05562SScott Long 			}
4266b23a1998SXin LI 			WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_START_DRIVER_MODE);
426744f05562SScott Long 			if(!arcmsr_hbb_wait_msgint_ready(acb)) {
426844f05562SScott Long 				printf( "arcmsr%d: 'start diver mode' timeout \n", acb->pci_unit);
426944f05562SScott Long 				return FALSE;
427044f05562SScott Long 			}
427144f05562SScott Long 		}
427244f05562SScott Long 		break;
4273d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
4274d74001adSXin LI 			if(srb_phyaddr_hi32 != 0) {
4275d74001adSXin LI 				CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG);
4276d74001adSXin LI 				CHIP_REG_WRITE32(HBC_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32);
4277d74001adSXin LI 				CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
4278d74001adSXin LI 				CHIP_REG_WRITE32(HBC_MessageUnit, 0, inbound_doorbell,ARCMSR_HBCMU_DRV2IOP_MESSAGE_CMD_DONE);
4279d74001adSXin LI 				if(!arcmsr_hbc_wait_msgint_ready(acb)) {
4280d74001adSXin LI 					printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit);
4281d74001adSXin LI 					return FALSE;
4282d74001adSXin LI 				}
4283d74001adSXin LI 			}
4284d74001adSXin LI 		}
4285d74001adSXin LI 		break;
42867a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
42877a7bc959SXin LI 			u_int32_t post_queue_phyaddr, done_queue_phyaddr;
42887a7bc959SXin LI 			struct HBD_MessageUnit0 *phbdmu;
42897a7bc959SXin LI 
42907a7bc959SXin LI 			phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
42917a7bc959SXin LI 			phbdmu->postq_index = 0;
42927a7bc959SXin LI 			phbdmu->doneq_index = 0x40FF;
42937a7bc959SXin LI 			post_queue_phyaddr = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE
42947a7bc959SXin LI 								+ offsetof(struct HBD_MessageUnit0, post_qbuffer);
42957a7bc959SXin LI 			done_queue_phyaddr = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE
42967a7bc959SXin LI 								+ offsetof(struct HBD_MessageUnit0, done_qbuffer);
42977a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG); /* driver "set config" signature */
42987a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[1], srb_phyaddr_hi32);
42997a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[2], post_queue_phyaddr); /* postQ base */
43007a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[3], done_queue_phyaddr); /* doneQ base */
43017a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, msgcode_rwbuffer[4], 0x100);
43027a7bc959SXin LI 			CHIP_REG_WRITE32(HBD_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
43037a7bc959SXin LI 			if(!arcmsr_hbd_wait_msgint_ready(acb)) {
43047a7bc959SXin LI 				printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit);
43057a7bc959SXin LI 				return FALSE;
43067a7bc959SXin LI 			}
43077a7bc959SXin LI 		}
43087a7bc959SXin LI 		break;
4309a1103e04SXin LI 	case ACB_ADAPTER_TYPE_E: {
4310a1103e04SXin LI 			u_int32_t cdb_phyaddr_lo32;
4311a1103e04SXin LI 			cdb_phyaddr_lo32 = srb_phyaddr_lo32 + offsetof(struct CommandControlBlock, arcmsr_cdb);
4312a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[0], ARCMSR_SIGNATURE_SET_CONFIG);
4313a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[1], ARCMSR_SIGNATURE_1884);
4314a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[2], cdb_phyaddr_lo32);
4315a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[3], srb_phyaddr_hi32);
4316a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[4], SRB_SIZE);
4317a1103e04SXin LI 			cdb_phyaddr_lo32 = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE;
4318a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[5], cdb_phyaddr_lo32);
4319a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[6], srb_phyaddr_hi32);
4320a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, msgcode_rwbuffer[7], COMPLETION_Q_POOL_SIZE);
4321a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
4322a1103e04SXin LI 			acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
4323a1103e04SXin LI 			CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
4324a1103e04SXin LI 			if(!arcmsr_hbe_wait_msgint_ready(acb)) {
4325a1103e04SXin LI 				printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit);
4326a1103e04SXin LI 				return FALSE;
4327a1103e04SXin LI 			}
4328a1103e04SXin LI 		}
4329a1103e04SXin LI 		break;
4330fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
4331fa42a0bfSXin LI 			u_int32_t cdb_phyaddr_lo32;
4332fa42a0bfSXin LI 			cdb_phyaddr_lo32 = srb_phyaddr_lo32 + offsetof(struct CommandControlBlock, arcmsr_cdb);
4333fa42a0bfSXin LI 			acb->msgcode_rwbuffer[0] = ARCMSR_SIGNATURE_SET_CONFIG;
4334fa42a0bfSXin LI 			acb->msgcode_rwbuffer[1] = ARCMSR_SIGNATURE_1886;
4335fa42a0bfSXin LI 			acb->msgcode_rwbuffer[2] = cdb_phyaddr_lo32;
4336fa42a0bfSXin LI 			acb->msgcode_rwbuffer[3] = srb_phyaddr_hi32;
4337fa42a0bfSXin LI 			acb->msgcode_rwbuffer[4] = SRB_SIZE;
4338fa42a0bfSXin LI 			cdb_phyaddr_lo32 = srb_phyaddr_lo32 + ARCMSR_SRBS_POOL_SIZE;
4339fa42a0bfSXin LI 			acb->msgcode_rwbuffer[5] = cdb_phyaddr_lo32;
4340fa42a0bfSXin LI 			acb->msgcode_rwbuffer[6] = srb_phyaddr_hi32;
4341fa42a0bfSXin LI 			acb->msgcode_rwbuffer[7] = COMPLETION_Q_POOL_SIZE;
4342fa42a0bfSXin LI 			CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_msgaddr0, ARCMSR_INBOUND_MESG0_SET_CONFIG);
4343fa42a0bfSXin LI 			acb->out_doorbell ^= ARCMSR_HBEMU_DRV2IOP_MESSAGE_CMD_DONE;
4344fa42a0bfSXin LI 			CHIP_REG_WRITE32(HBF_MessageUnit, 0, iobound_doorbell, acb->out_doorbell);
4345fa42a0bfSXin LI 			if(!arcmsr_hbe_wait_msgint_ready(acb)) {
4346fa42a0bfSXin LI 				printf( "arcmsr%d: 'set srb high part physical address' timeout \n", acb->pci_unit);
4347fa42a0bfSXin LI 				return FALSE;
4348fa42a0bfSXin LI 			}
4349fa42a0bfSXin LI 		}
4350fa42a0bfSXin LI 		break;
435144f05562SScott Long 	}
4352dac36688SXin LI 	return (TRUE);
435344f05562SScott Long }
435444f05562SScott Long /*
435544f05562SScott Long ************************************************************************
435644f05562SScott Long ************************************************************************
435744f05562SScott Long */
435844f05562SScott Long static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb)
435944f05562SScott Long {
4360a1103e04SXin LI 	if (acb->adapter_type == ACB_ADAPTER_TYPE_B)
436144f05562SScott Long 	{
4362b23a1998SXin LI 		struct HBB_MessageUnit *phbbmu = (struct HBB_MessageUnit *)acb->pmu;
4363b23a1998SXin LI 		WRITE_CHIP_REG32(0, phbbmu->drv2iop_doorbell, ARCMSR_MESSAGE_ACTIVE_EOI_MODE);
436444f05562SScott Long 		if(!arcmsr_hbb_wait_msgint_ready(acb)) {
4365d74001adSXin LI 			printf( "arcmsr%d: 'iop enable eoi mode' timeout \n", acb->pci_unit);
436644f05562SScott Long 			return;
436744f05562SScott Long 		}
436844f05562SScott Long 	}
436944f05562SScott Long }
437044f05562SScott Long /*
437144f05562SScott Long **********************************************************************
4372ad6d6297SScott Long **********************************************************************
4373ad6d6297SScott Long */
4374ad6d6297SScott Long static void arcmsr_iop_init(struct AdapterControlBlock *acb)
4375ad6d6297SScott Long {
437644f05562SScott Long 	u_int32_t intmask_org;
4377ad6d6297SScott Long 
437844f05562SScott Long 	/* disable all outbound interrupt */
437944f05562SScott Long 	intmask_org = arcmsr_disable_allintr(acb);
438044f05562SScott Long 	arcmsr_wait_firmware_ready(acb);
438144f05562SScott Long 	arcmsr_iop_confirm(acb);
4382ad6d6297SScott Long 	arcmsr_get_firmware_spec(acb);
438344f05562SScott Long 	/*start background rebuild*/
4384ad6d6297SScott Long 	arcmsr_start_adapter_bgrb(acb);
438544f05562SScott Long 	/* empty doorbell Qbuffer if door bell ringed */
438644f05562SScott Long 	arcmsr_clear_doorbell_queue_buffer(acb);
438744f05562SScott Long 	arcmsr_enable_eoi_mode(acb);
438844f05562SScott Long 	/* enable outbound Post Queue, outbound doorbell Interrupt */
438944f05562SScott Long 	arcmsr_enable_allintr(acb, intmask_org);
4390ad6d6297SScott Long 	acb->acb_flags |= ACB_F_IOP_INITED;
4391ad6d6297SScott Long }
4392ad6d6297SScott Long /*
4393ad6d6297SScott Long **********************************************************************
4394f1c579b1SScott Long **********************************************************************
4395f1c579b1SScott Long */
4396231c8b71SXin LI static void arcmsr_map_free_srb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
4397f1c579b1SScott Long {
4398ad6d6297SScott Long 	struct AdapterControlBlock *acb = arg;
4399ad6d6297SScott Long 	struct CommandControlBlock *srb_tmp;
440044f05562SScott Long 	u_int32_t i;
4401ad6d6297SScott Long 	unsigned long srb_phyaddr = (unsigned long)segs->ds_addr;
4402f1c579b1SScott Long 
4403d74001adSXin LI 	acb->srb_phyaddr.phyaddr = srb_phyaddr;
44047a7bc959SXin LI 	srb_tmp = (struct CommandControlBlock *)acb->uncacheptr;
4405ad6d6297SScott Long 	for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) {
440644f05562SScott Long 		if(bus_dmamap_create(acb->dm_segs_dmat,
440744f05562SScott Long 			 /*flags*/0, &srb_tmp->dm_segs_dmamap) != 0) {
4408ad6d6297SScott Long 			acb->acb_flags |= ACB_F_MAPFREESRB_FAILD;
440944f05562SScott Long 			printf("arcmsr%d:"
441044f05562SScott Long 			" srb dmamap bus_dmamap_create error\n", acb->pci_unit);
4411ad6d6297SScott Long 			return;
4412ad6d6297SScott Long 		}
4413a1103e04SXin LI 		if((acb->adapter_type == ACB_ADAPTER_TYPE_C) || (acb->adapter_type == ACB_ADAPTER_TYPE_D)
4414fa42a0bfSXin LI 			 || (acb->adapter_type == ACB_ADAPTER_TYPE_E) || (acb->adapter_type == ACB_ADAPTER_TYPE_F))
44157a7bc959SXin LI 		{
44167a7bc959SXin LI 			srb_tmp->cdb_phyaddr_low = srb_phyaddr;
44177a7bc959SXin LI 			srb_tmp->cdb_phyaddr_high = (u_int32_t)((srb_phyaddr >> 16) >> 16);
44187a7bc959SXin LI 		}
44197a7bc959SXin LI 		else
44207a7bc959SXin LI 			srb_tmp->cdb_phyaddr_low = srb_phyaddr >> 5;
4421ad6d6297SScott Long 		srb_tmp->acb = acb;
4422a1103e04SXin LI 		srb_tmp->smid = i << 16;
4423ad6d6297SScott Long 		acb->srbworkingQ[i] = acb->psrb_pool[i] = srb_tmp;
442422f2616bSXin LI 		srb_phyaddr = srb_phyaddr + SRB_SIZE;
442522f2616bSXin LI 		srb_tmp = (struct CommandControlBlock *)((unsigned long)srb_tmp + SRB_SIZE);
4426ad6d6297SScott Long 	}
4427fc5ef1caSXin LI 	if (acb->adapter_type == ACB_ADAPTER_TYPE_E)
4428a1103e04SXin LI 		acb->pCompletionQ = (pCompletion_Q)srb_tmp;
4429fa42a0bfSXin LI 	else if (acb->adapter_type == ACB_ADAPTER_TYPE_F) {
4430fa42a0bfSXin LI 		acb->pCompletionQ = (pCompletion_Q)srb_tmp;
4431fa42a0bfSXin LI 		acb->completeQ_phys = srb_phyaddr;
4432fa42a0bfSXin LI 		memset(acb->pCompletionQ, 0xff, COMPLETION_Q_POOL_SIZE);
4433fa42a0bfSXin LI 		acb->message_wbuffer = (u_int32_t *)((unsigned long)acb->pCompletionQ + COMPLETION_Q_POOL_SIZE);
4434fa42a0bfSXin LI 		acb->message_rbuffer = (u_int32_t *)((unsigned long)acb->message_wbuffer + 0x100);
4435fa42a0bfSXin LI 		acb->msgcode_rwbuffer = (u_int32_t *)((unsigned long)acb->message_wbuffer + 0x200);
4436fa42a0bfSXin LI 		memset((void *)acb->message_wbuffer, 0, MESG_RW_BUFFER_SIZE);
4437fa42a0bfSXin LI 	}
4438ad6d6297SScott Long 	acb->vir2phy_offset = (unsigned long)srb_tmp - (unsigned long)srb_phyaddr;
4439f1c579b1SScott Long }
4440f1c579b1SScott Long /*
4441f1c579b1SScott Long ************************************************************************
4442f1c579b1SScott Long ************************************************************************
4443f1c579b1SScott Long */
4444ad6d6297SScott Long static void arcmsr_free_resource(struct AdapterControlBlock *acb)
4445f1c579b1SScott Long {
4446f1c579b1SScott Long 	/* remove the control device */
4447ad6d6297SScott Long 	if(acb->ioctl_dev != NULL) {
4448ad6d6297SScott Long 		destroy_dev(acb->ioctl_dev);
4449f1c579b1SScott Long 	}
4450ad6d6297SScott Long 	bus_dmamap_unload(acb->srb_dmat, acb->srb_dmamap);
4451ad6d6297SScott Long 	bus_dmamap_destroy(acb->srb_dmat, acb->srb_dmamap);
4452ad6d6297SScott Long 	bus_dma_tag_destroy(acb->srb_dmat);
4453ad6d6297SScott Long 	bus_dma_tag_destroy(acb->dm_segs_dmat);
4454ad6d6297SScott Long 	bus_dma_tag_destroy(acb->parent_dmat);
4455f1c579b1SScott Long }
4456f1c579b1SScott Long /*
4457f1c579b1SScott Long ************************************************************************
4458f1c579b1SScott Long ************************************************************************
4459f1c579b1SScott Long */
44607a7bc959SXin LI static void arcmsr_mutex_init(struct AdapterControlBlock *acb)
44617a7bc959SXin LI {
44627a7bc959SXin LI 	ARCMSR_LOCK_INIT(&acb->isr_lock, "arcmsr isr lock");
44637a7bc959SXin LI 	ARCMSR_LOCK_INIT(&acb->srb_lock, "arcmsr srb lock");
44647a7bc959SXin LI 	ARCMSR_LOCK_INIT(&acb->postDone_lock, "arcmsr postQ lock");
44657a7bc959SXin LI 	ARCMSR_LOCK_INIT(&acb->qbuffer_lock, "arcmsr RW buffer lock");
44667a7bc959SXin LI }
44677a7bc959SXin LI /*
44687a7bc959SXin LI ************************************************************************
44697a7bc959SXin LI ************************************************************************
44707a7bc959SXin LI */
44717a7bc959SXin LI static void arcmsr_mutex_destroy(struct AdapterControlBlock *acb)
44727a7bc959SXin LI {
44737a7bc959SXin LI 	ARCMSR_LOCK_DESTROY(&acb->qbuffer_lock);
44747a7bc959SXin LI 	ARCMSR_LOCK_DESTROY(&acb->postDone_lock);
44757a7bc959SXin LI 	ARCMSR_LOCK_DESTROY(&acb->srb_lock);
44767a7bc959SXin LI 	ARCMSR_LOCK_DESTROY(&acb->isr_lock);
44777a7bc959SXin LI }
44787a7bc959SXin LI /*
44797a7bc959SXin LI ************************************************************************
44807a7bc959SXin LI ************************************************************************
44817a7bc959SXin LI */
4482ad6d6297SScott Long static u_int32_t arcmsr_initialize(device_t dev)
4483f1c579b1SScott Long {
4484ad6d6297SScott Long 	struct AdapterControlBlock *acb = device_get_softc(dev);
4485ad6d6297SScott Long 	u_int16_t pci_command;
448644f05562SScott Long 	int i, j,max_coherent_size;
4487dac36688SXin LI 	u_int32_t vendor_dev_id;
4488f1c579b1SScott Long 
4489dac36688SXin LI 	vendor_dev_id = pci_get_devid(dev);
4490dac36688SXin LI 	acb->vendor_device_id = vendor_dev_id;
4491224a78aeSXin LI 	acb->sub_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2);
4492dac36688SXin LI 	switch (vendor_dev_id) {
4493dac36688SXin LI 	case PCIDevVenIDARC1880:
4494dac36688SXin LI 	case PCIDevVenIDARC1882:
4495dac36688SXin LI 	case PCIDevVenIDARC1213:
4496dac36688SXin LI 	case PCIDevVenIDARC1223: {
4497d74001adSXin LI 			acb->adapter_type = ACB_ADAPTER_TYPE_C;
4498fc5ef1caSXin LI 			if ((acb->sub_device_id == ARECA_SUB_DEV_ID_1883) ||
4499fc5ef1caSXin LI 			    (acb->sub_device_id == ARECA_SUB_DEV_ID_1216) ||
4500fc5ef1caSXin LI 			    (acb->sub_device_id == ARECA_SUB_DEV_ID_1226))
4501224a78aeSXin LI 				acb->adapter_bus_speed = ACB_BUS_SPEED_12G;
4502224a78aeSXin LI 			else
4503dac36688SXin LI 				acb->adapter_bus_speed = ACB_BUS_SPEED_6G;
4504d74001adSXin LI 			max_coherent_size = ARCMSR_SRBS_POOL_SIZE;
4505d74001adSXin LI 		}
4506d74001adSXin LI 		break;
4507a1103e04SXin LI 	case PCIDevVenIDARC1884:
4508a1103e04SXin LI 		acb->adapter_type = ACB_ADAPTER_TYPE_E;
4509a1103e04SXin LI 		acb->adapter_bus_speed = ACB_BUS_SPEED_12G;
4510a1103e04SXin LI 		max_coherent_size = ARCMSR_SRBS_POOL_SIZE + COMPLETION_Q_POOL_SIZE;
4511a1103e04SXin LI 		acb->completionQ_entry = COMPLETION_Q_POOL_SIZE / sizeof(struct deliver_completeQ);
4512a1103e04SXin LI 		break;
4513fa42a0bfSXin LI 	case PCIDevVenIDARC1886_:
4514fa42a0bfSXin LI 	case PCIDevVenIDARC1886:
4515fa42a0bfSXin LI 		acb->adapter_type = ACB_ADAPTER_TYPE_F;
4516fa42a0bfSXin LI 		acb->adapter_bus_speed = ACB_BUS_SPEED_12G;
4517fa42a0bfSXin LI 		max_coherent_size = ARCMSR_SRBS_POOL_SIZE + COMPLETION_Q_POOL_SIZE + MESG_RW_BUFFER_SIZE;
4518fa42a0bfSXin LI 		acb->completionQ_entry = COMPLETION_Q_POOL_SIZE / sizeof(struct deliver_completeQ);
4519fa42a0bfSXin LI 		break;
45207a7bc959SXin LI 	case PCIDevVenIDARC1214: {
45217a7bc959SXin LI 			acb->adapter_type = ACB_ADAPTER_TYPE_D;
45227a7bc959SXin LI 			acb->adapter_bus_speed = ACB_BUS_SPEED_6G;
45237a7bc959SXin LI 			max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBD_MessageUnit0));
45247a7bc959SXin LI 		}
45257a7bc959SXin LI 		break;
4526231c8b71SXin LI 	case PCIDevVenIDARC1200:
452744f05562SScott Long 	case PCIDevVenIDARC1201: {
452844f05562SScott Long 			acb->adapter_type = ACB_ADAPTER_TYPE_B;
4529dac36688SXin LI 			acb->adapter_bus_speed = ACB_BUS_SPEED_3G;
4530d74001adSXin LI 			max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBB_MessageUnit));
453144f05562SScott Long 		}
453244f05562SScott Long 		break;
4533b23a1998SXin LI 	case PCIDevVenIDARC1203: {
4534b23a1998SXin LI 			acb->adapter_type = ACB_ADAPTER_TYPE_B;
4535b23a1998SXin LI 			acb->adapter_bus_speed = ACB_BUS_SPEED_6G;
4536b23a1998SXin LI 			max_coherent_size = ARCMSR_SRBS_POOL_SIZE + (sizeof(struct HBB_MessageUnit));
4537b23a1998SXin LI 		}
4538b23a1998SXin LI 		break;
453944f05562SScott Long 	case PCIDevVenIDARC1110:
454044f05562SScott Long 	case PCIDevVenIDARC1120:
454144f05562SScott Long 	case PCIDevVenIDARC1130:
454244f05562SScott Long 	case PCIDevVenIDARC1160:
454344f05562SScott Long 	case PCIDevVenIDARC1170:
454444f05562SScott Long 	case PCIDevVenIDARC1210:
454544f05562SScott Long 	case PCIDevVenIDARC1220:
454644f05562SScott Long 	case PCIDevVenIDARC1230:
4547231c8b71SXin LI 	case PCIDevVenIDARC1231:
454844f05562SScott Long 	case PCIDevVenIDARC1260:
4549231c8b71SXin LI 	case PCIDevVenIDARC1261:
455044f05562SScott Long 	case PCIDevVenIDARC1270:
455144f05562SScott Long 	case PCIDevVenIDARC1280:
4552d74001adSXin LI 	case PCIDevVenIDARC1212:
4553d74001adSXin LI 	case PCIDevVenIDARC1222:
455444f05562SScott Long 	case PCIDevVenIDARC1380:
455544f05562SScott Long 	case PCIDevVenIDARC1381:
455644f05562SScott Long 	case PCIDevVenIDARC1680:
455744f05562SScott Long 	case PCIDevVenIDARC1681: {
455844f05562SScott Long 			acb->adapter_type = ACB_ADAPTER_TYPE_A;
4559dac36688SXin LI 			acb->adapter_bus_speed = ACB_BUS_SPEED_3G;
456044f05562SScott Long 			max_coherent_size = ARCMSR_SRBS_POOL_SIZE;
456144f05562SScott Long 		}
456244f05562SScott Long 		break;
456344f05562SScott Long 	default: {
456444f05562SScott Long 			printf("arcmsr%d:"
456544f05562SScott Long 			" unknown RAID adapter type \n", device_get_unit(dev));
456644f05562SScott Long 			return ENOMEM;
456744f05562SScott Long 		}
456844f05562SScott Long 	}
4569b6f97155SScott Long 	if(bus_dma_tag_create(  /*PCI parent*/		bus_get_dma_tag(dev),
4570f1c579b1SScott Long 				/*alignemnt*/		1,
4571f1c579b1SScott Long 				/*boundary*/		0,
4572701d9f1fSScott Long 				/*lowaddr*/		BUS_SPACE_MAXADDR,
4573f1c579b1SScott Long 				/*highaddr*/		BUS_SPACE_MAXADDR,
4574f1c579b1SScott Long 				/*filter*/		NULL,
4575f1c579b1SScott Long 				/*filterarg*/		NULL,
4576f1c579b1SScott Long 				/*maxsize*/		BUS_SPACE_MAXSIZE_32BIT,
4577f1c579b1SScott Long 				/*nsegments*/		BUS_SPACE_UNRESTRICTED,
4578f1c579b1SScott Long 				/*maxsegsz*/		BUS_SPACE_MAXSIZE_32BIT,
4579f1c579b1SScott Long 				/*flags*/		0,
4580f1c579b1SScott Long 				/*lockfunc*/		NULL,
4581f1c579b1SScott Long 				/*lockarg*/		NULL,
4582231c8b71SXin LI 							&acb->parent_dmat) != 0)
4583f1c579b1SScott Long 	{
458444f05562SScott Long 		printf("arcmsr%d: parent_dmat bus_dma_tag_create failure!\n", device_get_unit(dev));
4585f1c579b1SScott Long 		return ENOMEM;
4586f1c579b1SScott Long 	}
4587231c8b71SXin LI 
4588f1c579b1SScott Long 	/* Create a single tag describing a region large enough to hold all of the s/g lists we will need. */
4589ad6d6297SScott Long 	if(bus_dma_tag_create(  /*parent_dmat*/		acb->parent_dmat,
4590f1c579b1SScott Long 				/*alignment*/		1,
4591f1c579b1SScott Long 				/*boundary*/		0,
459222f2616bSXin LI #ifdef PAE
459322f2616bSXin LI 				/*lowaddr*/		BUS_SPACE_MAXADDR_32BIT,
459422f2616bSXin LI #else
4595f1c579b1SScott Long 				/*lowaddr*/		BUS_SPACE_MAXADDR,
459622f2616bSXin LI #endif
4597f1c579b1SScott Long 				/*highaddr*/		BUS_SPACE_MAXADDR,
4598f1c579b1SScott Long 				/*filter*/		NULL,
4599f1c579b1SScott Long 				/*filterarg*/		NULL,
4600231c8b71SXin LI 				/*maxsize*/		ARCMSR_MAX_SG_ENTRIES * PAGE_SIZE * ARCMSR_MAX_FREESRB_NUM,
4601f1c579b1SScott Long 				/*nsegments*/		ARCMSR_MAX_SG_ENTRIES,
4602f1c579b1SScott Long 				/*maxsegsz*/		BUS_SPACE_MAXSIZE_32BIT,
4603ad6d6297SScott Long 				/*flags*/		0,
4604f1c579b1SScott Long 				/*lockfunc*/		busdma_lock_mutex,
46057a7bc959SXin LI 				/*lockarg*/		&acb->isr_lock,
4606231c8b71SXin LI 							&acb->dm_segs_dmat) != 0)
4607f1c579b1SScott Long 	{
4608ad6d6297SScott Long 		bus_dma_tag_destroy(acb->parent_dmat);
460944f05562SScott Long 		printf("arcmsr%d: dm_segs_dmat bus_dma_tag_create failure!\n", device_get_unit(dev));
4610f1c579b1SScott Long 		return ENOMEM;
4611f1c579b1SScott Long 	}
4612231c8b71SXin LI 
4613ad6d6297SScott Long 	/* DMA tag for our srb structures.... Allocate the freesrb memory */
4614ad6d6297SScott Long 	if(bus_dma_tag_create(  /*parent_dmat*/		acb->parent_dmat,
461544f05562SScott Long 				/*alignment*/		0x20,
4616f1c579b1SScott Long 				/*boundary*/		0,
4617f1c579b1SScott Long 				/*lowaddr*/		BUS_SPACE_MAXADDR_32BIT,
4618f1c579b1SScott Long 				/*highaddr*/		BUS_SPACE_MAXADDR,
4619f1c579b1SScott Long 				/*filter*/		NULL,
4620f1c579b1SScott Long 				/*filterarg*/		NULL,
462144f05562SScott Long 				/*maxsize*/		max_coherent_size,
4622f1c579b1SScott Long 				/*nsegments*/		1,
4623f1c579b1SScott Long 				/*maxsegsz*/		BUS_SPACE_MAXSIZE_32BIT,
4624701d9f1fSScott Long 				/*flags*/		0,
4625f1c579b1SScott Long 				/*lockfunc*/		NULL,
4626f1c579b1SScott Long 				/*lockarg*/		NULL,
4627231c8b71SXin LI 							&acb->srb_dmat) != 0)
4628f1c579b1SScott Long 	{
4629ad6d6297SScott Long 		bus_dma_tag_destroy(acb->dm_segs_dmat);
4630ad6d6297SScott Long 		bus_dma_tag_destroy(acb->parent_dmat);
463144f05562SScott Long 		printf("arcmsr%d: srb_dmat bus_dma_tag_create failure!\n", device_get_unit(dev));
4632f1c579b1SScott Long 		return ENXIO;
4633f1c579b1SScott Long 	}
4634f1c579b1SScott Long 	/* Allocation for our srbs */
4635d74001adSXin LI 	if(bus_dmamem_alloc(acb->srb_dmat, (void **)&acb->uncacheptr, BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, &acb->srb_dmamap) != 0) {
4636ad6d6297SScott Long 		bus_dma_tag_destroy(acb->srb_dmat);
4637ad6d6297SScott Long 		bus_dma_tag_destroy(acb->dm_segs_dmat);
4638ad6d6297SScott Long 		bus_dma_tag_destroy(acb->parent_dmat);
463944f05562SScott Long 		printf("arcmsr%d: srb_dmat bus_dmamem_alloc failure!\n", device_get_unit(dev));
4640f1c579b1SScott Long 		return ENXIO;
4641f1c579b1SScott Long 	}
4642f1c579b1SScott Long 	/* And permanently map them */
4643231c8b71SXin LI 	if(bus_dmamap_load(acb->srb_dmat, acb->srb_dmamap, acb->uncacheptr, max_coherent_size, arcmsr_map_free_srb, acb, /*flags*/0)) {
4644ad6d6297SScott Long 		bus_dma_tag_destroy(acb->srb_dmat);
4645ad6d6297SScott Long 		bus_dma_tag_destroy(acb->dm_segs_dmat);
4646ad6d6297SScott Long 		bus_dma_tag_destroy(acb->parent_dmat);
464744f05562SScott Long 		printf("arcmsr%d: srb_dmat bus_dmamap_load failure!\n", device_get_unit(dev));
4648f1c579b1SScott Long 		return ENXIO;
4649f1c579b1SScott Long 	}
4650f1c579b1SScott Long 	pci_command = pci_read_config(dev, PCIR_COMMAND, 2);
4651f1c579b1SScott Long 	pci_command |= PCIM_CMD_BUSMASTEREN;
4652f1c579b1SScott Long 	pci_command |= PCIM_CMD_PERRESPEN;
4653f1c579b1SScott Long 	pci_command |= PCIM_CMD_MWRICEN;
4654c68534f1SScott Long 	/* Enable Busmaster */
4655f1c579b1SScott Long 	pci_write_config(dev, PCIR_COMMAND, pci_command, 2);
465644f05562SScott Long 	switch(acb->adapter_type) {
465744f05562SScott Long 	case ACB_ADAPTER_TYPE_A: {
465844f05562SScott Long 		u_int32_t rid0 = PCIR_BAR(0);
465944f05562SScott Long 		vm_offset_t	mem_base0;
466044f05562SScott Long 
4661eff83876SJustin Hibbits 		acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev,SYS_RES_MEMORY, &rid0, RF_ACTIVE);
466244f05562SScott Long 		if(acb->sys_res_arcmsr[0] == NULL) {
4663ad6d6297SScott Long 			arcmsr_free_resource(acb);
4664d74001adSXin LI 			printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
4665f1c579b1SScott Long 			return ENOMEM;
4666f1c579b1SScott Long 		}
466744f05562SScott Long 		if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
4668ad6d6297SScott Long 			arcmsr_free_resource(acb);
4669d74001adSXin LI 			printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
4670f1c579b1SScott Long 			return ENXIO;
4671f1c579b1SScott Long 		}
467244f05562SScott Long 		mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
467344f05562SScott Long 		if(mem_base0 == 0) {
4674ad6d6297SScott Long 			arcmsr_free_resource(acb);
4675d74001adSXin LI 			printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
4676f1c579b1SScott Long 			return ENXIO;
4677f1c579b1SScott Long 		}
467844f05562SScott Long 		acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
467944f05562SScott Long 		acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
468044f05562SScott Long 		acb->pmu = (struct MessageUnit_UNION *)mem_base0;
4681fc5ef1caSXin LI 		acb->rid[0] = rid0;
468244f05562SScott Long 		}
468344f05562SScott Long 		break;
468444f05562SScott Long 	case ACB_ADAPTER_TYPE_B: {
468544f05562SScott Long 		struct HBB_MessageUnit *phbbmu;
468644f05562SScott Long 		struct CommandControlBlock *freesrb;
468744f05562SScott Long 		u_int32_t rid[]={ PCIR_BAR(0), PCIR_BAR(2) };
468844f05562SScott Long 		vm_offset_t	mem_base[]={0,0};
468944f05562SScott Long 		for(i=0; i < 2; i++) {
4690fc5ef1caSXin LI 			acb->sys_res_arcmsr[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid[i], RF_ACTIVE);
469144f05562SScott Long 			if(acb->sys_res_arcmsr[i] == NULL) {
469244f05562SScott Long 				arcmsr_free_resource(acb);
4693d74001adSXin LI 				printf("arcmsr%d: bus_alloc_resource %d failure!\n", device_get_unit(dev), i);
469444f05562SScott Long 				return ENOMEM;
469544f05562SScott Long 			}
469644f05562SScott Long 			if(rman_get_start(acb->sys_res_arcmsr[i]) <= 0) {
469744f05562SScott Long 				arcmsr_free_resource(acb);
4698d74001adSXin LI 				printf("arcmsr%d: rman_get_start %d failure!\n", device_get_unit(dev), i);
469944f05562SScott Long 				return ENXIO;
470044f05562SScott Long 			}
470144f05562SScott Long 			mem_base[i] = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[i]);
470244f05562SScott Long 			if(mem_base[i] == 0) {
470344f05562SScott Long 				arcmsr_free_resource(acb);
4704d74001adSXin LI 				printf("arcmsr%d: rman_get_virtual %d failure!\n", device_get_unit(dev), i);
470544f05562SScott Long 				return ENXIO;
470644f05562SScott Long 			}
470744f05562SScott Long 			acb->btag[i] = rman_get_bustag(acb->sys_res_arcmsr[i]);
470844f05562SScott Long 			acb->bhandle[i] = rman_get_bushandle(acb->sys_res_arcmsr[i]);
470944f05562SScott Long 		}
471044f05562SScott Long 		freesrb = (struct CommandControlBlock *)acb->uncacheptr;
471122f2616bSXin LI 		acb->pmu = (struct MessageUnit_UNION *)((unsigned long)freesrb+ARCMSR_SRBS_POOL_SIZE);
471244f05562SScott Long 		phbbmu = (struct HBB_MessageUnit *)acb->pmu;
471344f05562SScott Long 		phbbmu->hbb_doorbell = (struct HBB_DOORBELL *)mem_base[0];
471444f05562SScott Long 		phbbmu->hbb_rwbuffer = (struct HBB_RWBUFFER *)mem_base[1];
4715b23a1998SXin LI 		if (vendor_dev_id == PCIDevVenIDARC1203) {
4716b23a1998SXin LI 			phbbmu->drv2iop_doorbell = offsetof(struct HBB_DOORBELL_1203, drv2iop_doorbell);
4717b23a1998SXin LI 			phbbmu->drv2iop_doorbell_mask = offsetof(struct HBB_DOORBELL_1203, drv2iop_doorbell_mask);
4718b23a1998SXin LI 			phbbmu->iop2drv_doorbell = offsetof(struct HBB_DOORBELL_1203, iop2drv_doorbell);
4719b23a1998SXin LI 			phbbmu->iop2drv_doorbell_mask = offsetof(struct HBB_DOORBELL_1203, iop2drv_doorbell_mask);
4720b23a1998SXin LI 		} else {
4721b23a1998SXin LI 			phbbmu->drv2iop_doorbell = offsetof(struct HBB_DOORBELL, drv2iop_doorbell);
4722b23a1998SXin LI 			phbbmu->drv2iop_doorbell_mask = offsetof(struct HBB_DOORBELL, drv2iop_doorbell_mask);
4723b23a1998SXin LI 			phbbmu->iop2drv_doorbell = offsetof(struct HBB_DOORBELL, iop2drv_doorbell);
4724b23a1998SXin LI 			phbbmu->iop2drv_doorbell_mask = offsetof(struct HBB_DOORBELL, iop2drv_doorbell_mask);
4725b23a1998SXin LI 		}
4726fc5ef1caSXin LI 		acb->rid[0] = rid[0];
4727fc5ef1caSXin LI 		acb->rid[1] = rid[1];
472844f05562SScott Long 		}
472944f05562SScott Long 		break;
4730d74001adSXin LI 	case ACB_ADAPTER_TYPE_C: {
4731d74001adSXin LI 		u_int32_t rid0 = PCIR_BAR(1);
4732d74001adSXin LI 		vm_offset_t	mem_base0;
4733d74001adSXin LI 
4734eff83876SJustin Hibbits 		acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid0, RF_ACTIVE);
4735d74001adSXin LI 		if(acb->sys_res_arcmsr[0] == NULL) {
4736d74001adSXin LI 			arcmsr_free_resource(acb);
4737d74001adSXin LI 			printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
4738d74001adSXin LI 			return ENOMEM;
4739d74001adSXin LI 		}
4740d74001adSXin LI 		if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
4741d74001adSXin LI 			arcmsr_free_resource(acb);
4742d74001adSXin LI 			printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
4743d74001adSXin LI 			return ENXIO;
4744d74001adSXin LI 		}
4745d74001adSXin LI 		mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
4746d74001adSXin LI 		if(mem_base0 == 0) {
4747d74001adSXin LI 			arcmsr_free_resource(acb);
4748d74001adSXin LI 			printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
4749d74001adSXin LI 			return ENXIO;
4750d74001adSXin LI 		}
4751d74001adSXin LI 		acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
4752d74001adSXin LI 		acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
4753d74001adSXin LI 		acb->pmu = (struct MessageUnit_UNION *)mem_base0;
4754fc5ef1caSXin LI 		acb->rid[0] = rid0;
4755d74001adSXin LI 		}
4756d74001adSXin LI 		break;
47577a7bc959SXin LI 	case ACB_ADAPTER_TYPE_D: {
47587a7bc959SXin LI 		struct HBD_MessageUnit0 *phbdmu;
47597a7bc959SXin LI 		u_int32_t rid0 = PCIR_BAR(0);
47607a7bc959SXin LI 		vm_offset_t	mem_base0;
47617a7bc959SXin LI 
4762eff83876SJustin Hibbits 		acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid0, RF_ACTIVE);
47637a7bc959SXin LI 		if(acb->sys_res_arcmsr[0] == NULL) {
47647a7bc959SXin LI 			arcmsr_free_resource(acb);
47657a7bc959SXin LI 			printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
47667a7bc959SXin LI 			return ENOMEM;
47677a7bc959SXin LI 		}
47687a7bc959SXin LI 		if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
47697a7bc959SXin LI 			arcmsr_free_resource(acb);
47707a7bc959SXin LI 			printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
47717a7bc959SXin LI 			return ENXIO;
47727a7bc959SXin LI 		}
47737a7bc959SXin LI 		mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
47747a7bc959SXin LI 		if(mem_base0 == 0) {
47757a7bc959SXin LI 			arcmsr_free_resource(acb);
47767a7bc959SXin LI 			printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
47777a7bc959SXin LI 			return ENXIO;
47787a7bc959SXin LI 		}
47797a7bc959SXin LI 		acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
47807a7bc959SXin LI 		acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
47817a7bc959SXin LI 		acb->pmu = (struct MessageUnit_UNION *)((unsigned long)acb->uncacheptr+ARCMSR_SRBS_POOL_SIZE);
47827a7bc959SXin LI 		phbdmu = (struct HBD_MessageUnit0 *)acb->pmu;
47837a7bc959SXin LI 		phbdmu->phbdmu = (struct HBD_MessageUnit *)mem_base0;
4784fc5ef1caSXin LI 		acb->rid[0] = rid0;
4785a1103e04SXin LI 		}
4786a1103e04SXin LI 		break;
4787a1103e04SXin LI 	case ACB_ADAPTER_TYPE_E: {
4788a1103e04SXin LI 		u_int32_t rid0 = PCIR_BAR(1);
4789a1103e04SXin LI 		vm_offset_t	mem_base0;
4790a1103e04SXin LI 
4791fc5ef1caSXin LI 		acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid0, RF_ACTIVE);
4792a1103e04SXin LI 		if(acb->sys_res_arcmsr[0] == NULL) {
4793a1103e04SXin LI 			arcmsr_free_resource(acb);
4794a1103e04SXin LI 			printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
4795a1103e04SXin LI 			return ENOMEM;
4796a1103e04SXin LI 		}
4797a1103e04SXin LI 		if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
4798a1103e04SXin LI 			arcmsr_free_resource(acb);
4799a1103e04SXin LI 			printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
4800a1103e04SXin LI 			return ENXIO;
4801a1103e04SXin LI 		}
4802a1103e04SXin LI 		mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
4803a1103e04SXin LI 		if(mem_base0 == 0) {
4804a1103e04SXin LI 			arcmsr_free_resource(acb);
4805a1103e04SXin LI 			printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
4806a1103e04SXin LI 			return ENXIO;
4807a1103e04SXin LI 		}
4808a1103e04SXin LI 		acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
4809a1103e04SXin LI 		acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
4810a1103e04SXin LI 		acb->pmu = (struct MessageUnit_UNION *)mem_base0;
4811a1103e04SXin LI 		acb->doneq_index = 0;
4812a1103e04SXin LI 		acb->in_doorbell = 0;
4813a1103e04SXin LI 		acb->out_doorbell = 0;
4814fc5ef1caSXin LI 		acb->rid[0] = rid0;
4815a1103e04SXin LI 		CHIP_REG_WRITE32(HBE_MessageUnit, 0, host_int_status, 0); /*clear interrupt*/
4816a1103e04SXin LI 		CHIP_REG_WRITE32(HBE_MessageUnit, 0, iobound_doorbell, ARCMSR_HBEMU_DOORBELL_SYNC); /* synchronize doorbell to 0 */
48177a7bc959SXin LI 		}
48187a7bc959SXin LI 		break;
4819fa42a0bfSXin LI 	case ACB_ADAPTER_TYPE_F: {
4820fa42a0bfSXin LI 		u_int32_t rid0 = PCIR_BAR(0);
4821fa42a0bfSXin LI 		vm_offset_t	mem_base0;
4822fa42a0bfSXin LI 		unsigned long	host_buffer_dma;
4823fa42a0bfSXin LI 
4824fa42a0bfSXin LI 		acb->sys_res_arcmsr[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid0, RF_ACTIVE);
4825fa42a0bfSXin LI 		if(acb->sys_res_arcmsr[0] == NULL) {
4826fa42a0bfSXin LI 			arcmsr_free_resource(acb);
4827fa42a0bfSXin LI 			printf("arcmsr%d: bus_alloc_resource failure!\n", device_get_unit(dev));
4828fa42a0bfSXin LI 			return ENOMEM;
4829fa42a0bfSXin LI 		}
4830fa42a0bfSXin LI 		if(rman_get_start(acb->sys_res_arcmsr[0]) <= 0) {
4831fa42a0bfSXin LI 			arcmsr_free_resource(acb);
4832fa42a0bfSXin LI 			printf("arcmsr%d: rman_get_start failure!\n", device_get_unit(dev));
4833fa42a0bfSXin LI 			return ENXIO;
4834fa42a0bfSXin LI 		}
4835fa42a0bfSXin LI 		mem_base0 = (vm_offset_t) rman_get_virtual(acb->sys_res_arcmsr[0]);
4836fa42a0bfSXin LI 		if(mem_base0 == 0) {
4837fa42a0bfSXin LI 			arcmsr_free_resource(acb);
4838fa42a0bfSXin LI 			printf("arcmsr%d: rman_get_virtual failure!\n", device_get_unit(dev));
4839fa42a0bfSXin LI 			return ENXIO;
4840fa42a0bfSXin LI 		}
4841fa42a0bfSXin LI 		acb->btag[0] = rman_get_bustag(acb->sys_res_arcmsr[0]);
4842fa42a0bfSXin LI 		acb->bhandle[0] = rman_get_bushandle(acb->sys_res_arcmsr[0]);
4843fa42a0bfSXin LI 		acb->pmu = (struct MessageUnit_UNION *)mem_base0;
4844fa42a0bfSXin LI 		acb->doneq_index = 0;
4845fa42a0bfSXin LI 		acb->in_doorbell = 0;
4846fa42a0bfSXin LI 		acb->out_doorbell = 0;
4847fa42a0bfSXin LI 		acb->rid[0] = rid0;
4848fa42a0bfSXin LI 		CHIP_REG_WRITE32(HBF_MessageUnit, 0, host_int_status, 0); /*clear interrupt*/
4849fa42a0bfSXin LI 		CHIP_REG_WRITE32(HBF_MessageUnit, 0, iobound_doorbell, ARCMSR_HBEMU_DOORBELL_SYNC); /* synchronize doorbell to 0 */
48506964b77eS黃清隆 		arcmsr_wait_firmware_ready(acb);
4851fa42a0bfSXin LI 		host_buffer_dma = acb->completeQ_phys + COMPLETION_Q_POOL_SIZE;
4852fa42a0bfSXin LI 		CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_msgaddr0, (u_int32_t)(host_buffer_dma | 1));  /* host buffer low addr, bit0:1 all buffer active */
4853fa42a0bfSXin LI 		CHIP_REG_WRITE32(HBF_MessageUnit, 0, inbound_msgaddr1, (u_int32_t)((host_buffer_dma >> 16) >> 16));/* host buffer high addr */
4854fa42a0bfSXin LI 		CHIP_REG_WRITE32(HBF_MessageUnit, 0, iobound_doorbell, ARCMSR_HBFMU_DOORBELL_SYNC1);       /* set host buffer physical address */
4855fa42a0bfSXin LI 		}
4856fa42a0bfSXin LI 		break;
485744f05562SScott Long 	}
4858ad6d6297SScott Long 	if(acb->acb_flags & ACB_F_MAPFREESRB_FAILD) {
4859ad6d6297SScott Long 		arcmsr_free_resource(acb);
486044f05562SScott Long 		printf("arcmsr%d: map free srb failure!\n", device_get_unit(dev));
4861f1c579b1SScott Long 		return ENXIO;
4862f1c579b1SScott Long 	}
4863d74001adSXin LI 	acb->acb_flags  |= (ACB_F_MESSAGE_WQBUFFER_CLEARED|ACB_F_MESSAGE_RQBUFFER_CLEARED|ACB_F_MESSAGE_WQBUFFER_READ);
4864ad6d6297SScott Long 	acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER;
4865ad6d6297SScott Long 	/*
4866ad6d6297SScott Long 	********************************************************************
4867ad6d6297SScott Long 	** init raid volume state
4868ad6d6297SScott Long 	********************************************************************
4869ad6d6297SScott Long 	*/
4870ad6d6297SScott Long 	for(i=0; i < ARCMSR_MAX_TARGETID; i++) {
4871ad6d6297SScott Long 		for(j=0; j < ARCMSR_MAX_TARGETLUN; j++) {
487244f05562SScott Long 			acb->devstate[i][j] = ARECA_RAID_GONE;
4873ad6d6297SScott Long 		}
4874ad6d6297SScott Long 	}
4875ad6d6297SScott Long 	arcmsr_iop_init(acb);
4876f1c579b1SScott Long 	return(0);
4877f1c579b1SScott Long }
4878a1103e04SXin LI 
4879a1103e04SXin LI static int arcmsr_setup_msix(struct AdapterControlBlock *acb)
4880a1103e04SXin LI {
4881a1103e04SXin LI 	int i;
4882a1103e04SXin LI 
4883a1103e04SXin LI 	for (i = 0; i < acb->msix_vectors; i++) {
4884fc5ef1caSXin LI 		acb->irq_id[i] = 1 + i;
4885a1103e04SXin LI 		acb->irqres[i] = bus_alloc_resource_any(acb->pci_dev,
4886a1103e04SXin LI 		    SYS_RES_IRQ, &acb->irq_id[i], RF_ACTIVE);
4887a1103e04SXin LI 		if (acb->irqres[i] == NULL) {
4888a1103e04SXin LI 			printf("arcmsr: Can't allocate MSI-X resource\n");
4889a1103e04SXin LI 			goto irq_alloc_failed;
4890a1103e04SXin LI 		}
4891a1103e04SXin LI 		if (bus_setup_intr(acb->pci_dev, acb->irqres[i],
4892a1103e04SXin LI 		    INTR_MPSAFE | INTR_TYPE_CAM, NULL, arcmsr_intr_handler,
4893a1103e04SXin LI 		    acb, &acb->ih[i])) {
4894a1103e04SXin LI 			printf("arcmsr: Cannot set up MSI-X interrupt handler\n");
4895a1103e04SXin LI 			goto irq_alloc_failed;
4896a1103e04SXin LI 		}
4897a1103e04SXin LI 	}
4898a1103e04SXin LI 	printf("arcmsr: MSI-X INT enabled\n");
4899a1103e04SXin LI 	acb->acb_flags |= ACB_F_MSIX_ENABLED;
4900a1103e04SXin LI 	return TRUE;
4901a1103e04SXin LI 
4902a1103e04SXin LI irq_alloc_failed:
4903a1103e04SXin LI 	arcmsr_teardown_intr(acb->pci_dev, acb);
4904a1103e04SXin LI 	return FALSE;
4905a1103e04SXin LI }
4906a1103e04SXin LI 
4907f1c579b1SScott Long /*
4908f1c579b1SScott Long ************************************************************************
4909f1c579b1SScott Long ************************************************************************
4910f1c579b1SScott Long */
4911f2aa0e9fSWarner Losh static int arcmsr_attach(device_t dev)
4912f1c579b1SScott Long {
4913a9e5e04eSJohn Baldwin 	struct make_dev_args args;
4914ad6d6297SScott Long 	struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev);
4915ad6d6297SScott Long 	u_int32_t unit=device_get_unit(dev);
4916f1c579b1SScott Long 	struct ccb_setasync csa;
4917f1c579b1SScott Long 	struct cam_devq	*devq;	/* Device Queue to use for this SIM */
4918f1c579b1SScott Long 	struct resource	*irqres;
4919f1c579b1SScott Long 
4920ad6d6297SScott Long 	if(acb == NULL) {
4921ad6d6297SScott Long 		printf("arcmsr%d: cannot allocate softc\n", unit);
4922ad6d6297SScott Long 		return (ENOMEM);
4923ad6d6297SScott Long 	}
49247a7bc959SXin LI 	arcmsr_mutex_init(acb);
49251e7d660aSXin LI 	acb->pci_dev = dev;
49261e7d660aSXin LI 	acb->pci_unit = unit;
4927ad6d6297SScott Long 	if(arcmsr_initialize(dev)) {
4928ad6d6297SScott Long 		printf("arcmsr%d: initialize failure!\n", unit);
4929a1103e04SXin LI 		goto initialize_failed;
4930f1c579b1SScott Long 	}
4931f1c579b1SScott Long 	/* After setting up the adapter, map our interrupt */
4932a1103e04SXin LI 	acb->msix_vectors = ARCMSR_NUM_MSIX_VECTORS;
4933a1103e04SXin LI 	if (pci_alloc_msix(dev, &acb->msix_vectors) == 0) {
4934a1103e04SXin LI 		if (arcmsr_setup_msix(acb) == TRUE)
4935a1103e04SXin LI 			goto irqx;
4936a1103e04SXin LI 	}
4937fc5ef1caSXin LI 	acb->irq_id[0] = 0;
4938a1103e04SXin LI 	irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &acb->irq_id[0], RF_SHAREABLE | RF_ACTIVE);
4939ad6d6297SScott Long 	if(irqres == NULL ||
4940a1103e04SXin LI 		bus_setup_intr(dev, irqres, INTR_TYPE_CAM|INTR_ENTROPY|INTR_MPSAFE, NULL, arcmsr_intr_handler, acb, &acb->ih[0])) {
4941f1c579b1SScott Long 		printf("arcmsr%d: unable to register interrupt handler!\n", unit);
4942a1103e04SXin LI 		goto setup_intr_failed;
4943f1c579b1SScott Long 	}
4944a1103e04SXin LI 	acb->irqres[0] = irqres;
4945a1103e04SXin LI irqx:
4946f1c579b1SScott Long 	/*
4947f1c579b1SScott Long 	 * Now let the CAM generic SCSI layer find the SCSI devices on
4948f1c579b1SScott Long 	 * the bus *  start queue to reset to the idle loop. *
4949f1c579b1SScott Long 	 * Create device queue of SIM(s) *  (MAX_START_JOB - 1) :
4950f1c579b1SScott Long 	 * max_sim_transactions
4951f1c579b1SScott Long 	*/
4952224a78aeSXin LI 	devq = cam_simq_alloc(acb->maxOutstanding);
4953ad6d6297SScott Long 	if(devq == NULL) {
4954ad6d6297SScott Long 		printf("arcmsr%d: cam_simq_alloc failure!\n", unit);
4955a1103e04SXin LI 		goto simq_alloc_failed;
4956f1c579b1SScott Long 	}
49577a7bc959SXin LI 	acb->psim = cam_sim_alloc(arcmsr_action, arcmsr_poll, "arcmsr", acb, unit, &acb->isr_lock, 1, ARCMSR_MAX_OUTSTANDING_CMD, devq);
4958ad6d6297SScott Long 	if(acb->psim == NULL) {
4959ad6d6297SScott Long 		printf("arcmsr%d: cam_sim_alloc failure!\n", unit);
4960a1103e04SXin LI 		goto sim_alloc_failed;
4961f1c579b1SScott Long 	}
49627a7bc959SXin LI 	ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
4963b50569b7SScott Long 	if(xpt_bus_register(acb->psim, dev, 0) != CAM_SUCCESS) {
4964ad6d6297SScott Long 		printf("arcmsr%d: xpt_bus_register failure!\n", unit);
4965a1103e04SXin LI 		goto xpt_bus_failed;
4966f1c579b1SScott Long 	}
4967d74001adSXin LI 	if(xpt_create_path(&acb->ppath, /* periph */ NULL, cam_sim_path(acb->psim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
4968ad6d6297SScott Long 		printf("arcmsr%d: xpt_create_path failure!\n", unit);
4969a1103e04SXin LI 		goto xpt_path_failed;
4970f1c579b1SScott Long 	}
4971f1c579b1SScott Long 	/*
4972f1c579b1SScott Long 	****************************************************
4973f1c579b1SScott Long 	*/
497445f57ce1SEdward Tomasz Napierala 	memset(&csa, 0, sizeof(csa));
4975ad6d6297SScott Long 	xpt_setup_ccb(&csa.ccb_h, acb->ppath, /*priority*/5);
4976f1c579b1SScott Long 	csa.ccb_h.func_code = XPT_SASYNC_CB;
4977f1c579b1SScott Long 	csa.event_enable = AC_FOUND_DEVICE|AC_LOST_DEVICE;
4978f1c579b1SScott Long 	csa.callback = arcmsr_async;
4979ad6d6297SScott Long 	csa.callback_arg = acb->psim;
4980f1c579b1SScott Long 	xpt_action((union ccb *)&csa);
49817a7bc959SXin LI 	ARCMSR_LOCK_RELEASE(&acb->isr_lock);
4982f1c579b1SScott Long 	/* Create the control device.  */
4983a9e5e04eSJohn Baldwin 	make_dev_args_init(&args);
4984a9e5e04eSJohn Baldwin 	args.mda_devsw = &arcmsr_cdevsw;
4985a9e5e04eSJohn Baldwin 	args.mda_uid = UID_ROOT;
4986a9e5e04eSJohn Baldwin 	args.mda_gid = GID_WHEEL /* GID_OPERATOR */;
4987a9e5e04eSJohn Baldwin 	args.mda_mode = S_IRUSR | S_IWUSR;
4988a9e5e04eSJohn Baldwin 	args.mda_si_drv1 = acb;
4989a9e5e04eSJohn Baldwin 	(void)make_dev_s(&args, &acb->ioctl_dev, "arcmsr%d", unit);
4990d74001adSXin LI 
4991ad6d6297SScott Long 	(void)make_dev_alias(acb->ioctl_dev, "arc%d", unit);
499222f2616bSXin LI 	arcmsr_callout_init(&acb->devmap_callout);
4993d74001adSXin LI 	callout_reset(&acb->devmap_callout, 60 * hz, arcmsr_polling_devmap, acb);
4994dac36688SXin LI 	return (0);
4995a1103e04SXin LI xpt_path_failed:
4996a1103e04SXin LI 	xpt_bus_deregister(cam_sim_path(acb->psim));
4997a1103e04SXin LI xpt_bus_failed:
4998a1103e04SXin LI 	cam_sim_free(acb->psim, /* free_simq */ TRUE);
4999a1103e04SXin LI sim_alloc_failed:
5000a1103e04SXin LI 	cam_simq_free(devq);
5001a1103e04SXin LI simq_alloc_failed:
5002a1103e04SXin LI 	arcmsr_teardown_intr(dev, acb);
5003a1103e04SXin LI setup_intr_failed:
5004a1103e04SXin LI 	arcmsr_free_resource(acb);
5005a1103e04SXin LI initialize_failed:
5006a1103e04SXin LI 	arcmsr_mutex_destroy(acb);
5007a1103e04SXin LI 	return ENXIO;
5008f1c579b1SScott Long }
500922f2616bSXin LI 
5010f1c579b1SScott Long /*
5011f1c579b1SScott Long ************************************************************************
5012f1c579b1SScott Long ************************************************************************
5013f1c579b1SScott Long */
5014f2aa0e9fSWarner Losh static int arcmsr_probe(device_t dev)
5015f1c579b1SScott Long {
5016ad6d6297SScott Long 	u_int32_t id;
5017224a78aeSXin LI 	u_int16_t sub_device_id;
5018ad6d6297SScott Long 	static char buf[256];
50191e7d660aSXin LI 	char x_type[]={"unknown"};
5020ad6d6297SScott Long 	char *type;
5021ad6d6297SScott Long 	int raid6 = 1;
5022ad6d6297SScott Long 
5023ad6d6297SScott Long 	if (pci_get_vendor(dev) != PCI_VENDOR_ID_ARECA) {
5024ad6d6297SScott Long 		return (ENXIO);
5025ad6d6297SScott Long 	}
5026224a78aeSXin LI 	sub_device_id = pci_read_config(dev, PCIR_SUBDEV_0, 2);
5027ad6d6297SScott Long 	switch(id = pci_get_devid(dev)) {
5028f1c579b1SScott Long 	case PCIDevVenIDARC1110:
5029231c8b71SXin LI 	case PCIDevVenIDARC1200:
503044f05562SScott Long 	case PCIDevVenIDARC1201:
5031231c8b71SXin LI 	case PCIDevVenIDARC1210:
5032ad6d6297SScott Long 		raid6 = 0;
5033ad6d6297SScott Long 		/*FALLTHRU*/
5034ad6d6297SScott Long 	case PCIDevVenIDARC1120:
5035ad6d6297SScott Long 	case PCIDevVenIDARC1130:
5036ad6d6297SScott Long 	case PCIDevVenIDARC1160:
5037ad6d6297SScott Long 	case PCIDevVenIDARC1170:
5038f1c579b1SScott Long 	case PCIDevVenIDARC1220:
5039f1c579b1SScott Long 	case PCIDevVenIDARC1230:
5040231c8b71SXin LI 	case PCIDevVenIDARC1231:
5041f1c579b1SScott Long 	case PCIDevVenIDARC1260:
5042231c8b71SXin LI 	case PCIDevVenIDARC1261:
5043ad6d6297SScott Long 	case PCIDevVenIDARC1270:
5044ad6d6297SScott Long 	case PCIDevVenIDARC1280:
50457a7bc959SXin LI 		type = "SATA 3G";
5046ad6d6297SScott Long 		break;
5047d74001adSXin LI 	case PCIDevVenIDARC1212:
5048d74001adSXin LI 	case PCIDevVenIDARC1222:
5049ad6d6297SScott Long 	case PCIDevVenIDARC1380:
5050ad6d6297SScott Long 	case PCIDevVenIDARC1381:
5051ad6d6297SScott Long 	case PCIDevVenIDARC1680:
5052ad6d6297SScott Long 	case PCIDevVenIDARC1681:
5053d74001adSXin LI 		type = "SAS 3G";
5054d74001adSXin LI 		break;
5055d74001adSXin LI 	case PCIDevVenIDARC1880:
5056dac36688SXin LI 	case PCIDevVenIDARC1882:
5057dac36688SXin LI 	case PCIDevVenIDARC1213:
5058dac36688SXin LI 	case PCIDevVenIDARC1223:
5059fc5ef1caSXin LI 		if ((sub_device_id == ARECA_SUB_DEV_ID_1883) ||
5060fc5ef1caSXin LI 		    (sub_device_id == ARECA_SUB_DEV_ID_1216) ||
5061fc5ef1caSXin LI 		    (sub_device_id == ARECA_SUB_DEV_ID_1226))
5062224a78aeSXin LI 			type = "SAS 12G";
5063224a78aeSXin LI 		else
5064d74001adSXin LI 			type = "SAS 6G";
5065ad6d6297SScott Long 		break;
5066a1103e04SXin LI 	case PCIDevVenIDARC1884:
5067a1103e04SXin LI 		type = "SAS 12G";
5068a1103e04SXin LI 		break;
5069fa42a0bfSXin LI 	case PCIDevVenIDARC1886_:
5070fa42a0bfSXin LI 	case PCIDevVenIDARC1886:
5071fa42a0bfSXin LI 		type = "NVME,SAS-12G,SATA-6G";
5072fa42a0bfSXin LI 		break;
50737a7bc959SXin LI 	case PCIDevVenIDARC1214:
5074b23a1998SXin LI 	case PCIDevVenIDARC1203:
50757a7bc959SXin LI 		type = "SATA 6G";
50767a7bc959SXin LI 		break;
5077ad6d6297SScott Long 	default:
5078231c8b71SXin LI 		type = x_type;
50791e7d660aSXin LI 		raid6 = 0;
5080ad6d6297SScott Long 		break;
5081f1c579b1SScott Long 	}
5082231c8b71SXin LI 	if(type == x_type)
5083231c8b71SXin LI 		return(ENXIO);
50841e7d660aSXin LI 	sprintf(buf, "Areca %s Host Adapter RAID Controller %s\n%s\n",
50851e7d660aSXin LI 		type, raid6 ? "(RAID6 capable)" : "", ARCMSR_DRIVER_VERSION);
5086ad6d6297SScott Long 	device_set_desc_copy(dev, buf);
508703389298SXin LI 	return (BUS_PROBE_DEFAULT);
5088f1c579b1SScott Long }
5089f1c579b1SScott Long /*
5090f1c579b1SScott Long ************************************************************************
5091f1c579b1SScott Long ************************************************************************
5092f1c579b1SScott Long */
5093f2aa0e9fSWarner Losh static int arcmsr_shutdown(device_t dev)
5094f1c579b1SScott Long {
509544f05562SScott Long 	u_int32_t  i;
5096ad6d6297SScott Long 	struct CommandControlBlock *srb;
5097ad6d6297SScott Long 	struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev);
5098f1c579b1SScott Long 
5099f1c579b1SScott Long 	/* stop adapter background rebuild */
51007a7bc959SXin LI 	ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
510144f05562SScott Long 	/* disable all outbound interrupt */
5102bca8e8c0SScott Long 	arcmsr_disable_allintr(acb);
5103ad6d6297SScott Long 	arcmsr_stop_adapter_bgrb(acb);
5104ad6d6297SScott Long 	arcmsr_flush_adapter_cache(acb);
5105f1c579b1SScott Long 	/* abort all outstanding command */
5106ad6d6297SScott Long 	acb->acb_flags |= ACB_F_SCSISTOPADAPTER;
5107ad6d6297SScott Long 	acb->acb_flags &= ~ACB_F_IOP_INITED;
5108ad6d6297SScott Long 	if(acb->srboutstandingcount != 0) {
510944f05562SScott Long 		/*clear and abort all outbound posted Q*/
511044f05562SScott Long 		arcmsr_done4abort_postqueue(acb);
511144f05562SScott Long 		/* talk to iop 331 outstanding command aborted*/
5112ad6d6297SScott Long 		arcmsr_abort_allcmd(acb);
5113ad6d6297SScott Long 		for(i=0; i < ARCMSR_MAX_FREESRB_NUM; i++) {
5114ad6d6297SScott Long 			srb = acb->psrb_pool[i];
511522f2616bSXin LI 			if(srb->srb_state == ARCMSR_SRB_START) {
511622f2616bSXin LI 				srb->srb_state = ARCMSR_SRB_ABORTED;
5117ad6d6297SScott Long 				srb->pccb->ccb_h.status |= CAM_REQ_ABORTED;
5118ad6d6297SScott Long 				arcmsr_srb_complete(srb, 1);
5119f1c579b1SScott Long 			}
5120f1c579b1SScott Long 		}
5121f1c579b1SScott Long 	}
512222f2616bSXin LI 	acb->srboutstandingcount = 0;
5123ad6d6297SScott Long 	acb->workingsrb_doneindex = 0;
5124ad6d6297SScott Long 	acb->workingsrb_startindex = 0;
512522f2616bSXin LI 	acb->pktRequestCount = 0;
512622f2616bSXin LI 	acb->pktReturnCount = 0;
51277a7bc959SXin LI 	ARCMSR_LOCK_RELEASE(&acb->isr_lock);
5128f2aa0e9fSWarner Losh 	return (0);
5129f1c579b1SScott Long }
5130f1c579b1SScott Long /*
5131f1c579b1SScott Long ************************************************************************
5132f1c579b1SScott Long ************************************************************************
5133f1c579b1SScott Long */
5134fc5ef1caSXin LI static void arcmsr_teardown_intr(device_t dev, struct AdapterControlBlock *acb)
5135a1103e04SXin LI {
5136a1103e04SXin LI 	int i;
5137a1103e04SXin LI 
5138a1103e04SXin LI 	if (acb->acb_flags & ACB_F_MSIX_ENABLED) {
5139a1103e04SXin LI 		for (i = 0; i < acb->msix_vectors; i++) {
5140a1103e04SXin LI 			if (acb->ih[i])
5141a1103e04SXin LI 				bus_teardown_intr(dev, acb->irqres[i], acb->ih[i]);
5142a1103e04SXin LI 			if (acb->irqres[i] != NULL)
5143a1103e04SXin LI 				bus_release_resource(dev, SYS_RES_IRQ,
5144a1103e04SXin LI 				    acb->irq_id[i], acb->irqres[i]);
5145a1103e04SXin LI 
5146a1103e04SXin LI 			acb->ih[i] = NULL;
5147a1103e04SXin LI 		}
5148a1103e04SXin LI 		pci_release_msi(dev);
5149a1103e04SXin LI 	} else {
5150a1103e04SXin LI 		if (acb->ih[0])
5151a1103e04SXin LI 			bus_teardown_intr(dev, acb->irqres[0], acb->ih[0]);
5152a1103e04SXin LI 		if (acb->irqres[0] != NULL)
5153a1103e04SXin LI 			bus_release_resource(dev, SYS_RES_IRQ,
5154a1103e04SXin LI 			    acb->irq_id[0], acb->irqres[0]);
5155a1103e04SXin LI 		acb->ih[0] = NULL;
5156a1103e04SXin LI 	}
5157a1103e04SXin LI 
5158a1103e04SXin LI }
5159a1103e04SXin LI /*
5160a1103e04SXin LI ************************************************************************
5161a1103e04SXin LI ************************************************************************
5162a1103e04SXin LI */
5163f2aa0e9fSWarner Losh static int arcmsr_detach(device_t dev)
5164f1c579b1SScott Long {
5165ad6d6297SScott Long 	struct AdapterControlBlock *acb=(struct AdapterControlBlock *)device_get_softc(dev);
516644f05562SScott Long 	int i;
5167f1c579b1SScott Long 
5168d74001adSXin LI 	callout_stop(&acb->devmap_callout);
5169a1103e04SXin LI 	arcmsr_teardown_intr(dev, acb);
5170f1c579b1SScott Long 	arcmsr_shutdown(dev);
5171ad6d6297SScott Long 	arcmsr_free_resource(acb);
517244f05562SScott Long 	for(i=0; (acb->sys_res_arcmsr[i]!=NULL) && (i<2); i++) {
5173fc5ef1caSXin LI 		bus_release_resource(dev, SYS_RES_MEMORY, acb->rid[i], acb->sys_res_arcmsr[i]);
517444f05562SScott Long 	}
51757a7bc959SXin LI 	ARCMSR_LOCK_ACQUIRE(&acb->isr_lock);
5176ad6d6297SScott Long 	xpt_async(AC_LOST_DEVICE, acb->ppath, NULL);
5177ad6d6297SScott Long 	xpt_free_path(acb->ppath);
5178ad6d6297SScott Long 	xpt_bus_deregister(cam_sim_path(acb->psim));
5179ad6d6297SScott Long 	cam_sim_free(acb->psim, TRUE);
51807a7bc959SXin LI 	ARCMSR_LOCK_RELEASE(&acb->isr_lock);
51817a7bc959SXin LI 	arcmsr_mutex_destroy(acb);
5182f1c579b1SScott Long 	return (0);
5183f1c579b1SScott Long }
5184f1c579b1SScott Long 
518522f2616bSXin LI #ifdef ARCMSR_DEBUG1
518622f2616bSXin LI static void arcmsr_dump_data(struct AdapterControlBlock *acb)
518722f2616bSXin LI {
518822f2616bSXin LI 	if((acb->pktRequestCount - acb->pktReturnCount) == 0)
518922f2616bSXin LI 		return;
519022f2616bSXin LI 	printf("Command Request Count   =0x%x\n",acb->pktRequestCount);
519122f2616bSXin LI 	printf("Command Return Count    =0x%x\n",acb->pktReturnCount);
519222f2616bSXin LI 	printf("Command (Req-Rtn) Count =0x%x\n",(acb->pktRequestCount - acb->pktReturnCount));
519322f2616bSXin LI 	printf("Queued Command Count    =0x%x\n",acb->srboutstandingcount);
519422f2616bSXin LI }
519522f2616bSXin LI #endif
5196